Hi, (please sure you also Cc linux-usb@xxxxxxxxxxxxxxx for MUSB patches) Rolf Peukert <rolf.peukert@xxxxxxx> writes: > Hi, > > we're running a 4.x kernel on a board with an AM3505 CPU and would like > to use device trees. The AM35xx glue code for the M-USB controller > didn't support configuration from a DT yet. I now got it working > somehow, but I'm not sure if I'm doing it the correct way. So this post > is not meant as a patch submission, but more as a request for comments > or help. > > In the older kernel we were using before (3.2.x), some data structures > were set up in the respective board file and then passed to the function > am35x_probe(). For the use with DT, I added the function > am35x_get_config, which sets up these data structures with default > values and then tries to read settings from the DT. > The device .compatible declaration is now "ti,am35x-musb", so it's > separate from "ti,omap3-musb" (as used in omap2430.c). > > Now the two things I'm not so sure about: > > a) We needed to set pointers to machine-specific functions like > am35x_musb_clear_irq etc. These functions are implemented in > arch/arm/mach-omap2/omap_phy_internal.c, and declared in > arch/arm/mach-omap2/usb.h. > As this header file can't be included easily from am35x.c, I moved the > declarations to include/linux/platform_data/usb-omap.h. I hope that's > OK, but would be happy about suggestions. Yeah, those functions should not be defined under arch/arm/mach-omap2, they need to be moved to drivers/usb/musb/am35x.c. That PHY power stuff also needs to move to some system controller driver of some sort. > b) The M-USB port on our board is wired as host only. If a device is > unplugged, the driver normally goes into some idle state and waits for > an ID signal change. But on our board that never happens. did you route ID pin anywhere ? I hope you tied it to ground. > So I added two checks for MUSB_OTG mode to support our hardware. Then if your HW is host-only, why are you messing around with OTG ? > I noticed similar code was removed from this file three years ago > (commit 032ec49f5351e9cb242b1a1c367d14415043ab95), and I don't know if > these lines might break something on other hardware. > > Best regards, > Rolf > > --- > Index: linux4/drivers/usb/musb/am35x.c > =================================================================== > --- linux4.orig/drivers/usb/musb/am35x.c > +++ linux4/drivers/usb/musb/am35x.c > @@ -188,6 +188,10 @@ static void am35x_musb_try_idle(struct m > { > static unsigned long last_timer; > > + /* do not try if not in OTG mode */ > + if (musb->port_mode != MUSB_OTG) > + return; peripheral-only and host-only configurations are valid, you should not bail out unless OTG. > @@ -323,8 +327,9 @@ eoi: > musb_writel(reg_base, USB_END_OF_INTR_REG, 0); > } > > - /* Poll for ID change */ > - if (musb->xceiv->otg->state == OTG_STATE_B_IDLE) > + /* Poll for ID change (in OTG mode only) */ > + if (musb->port_mode == MUSB_OTG && > + musb->xceiv->otg->state == OTG_STATE_B_IDLE) no, this is wrong too. > @@ -458,6 +463,70 @@ static const struct platform_device_info > .dma_mask = DMA_BIT_MASK(32), > }; > > +static struct musb_hdrc_platform_data * > +am35x_get_config(struct platform_device *pdev) > +{ > + struct musb_hdrc_platform_data *pdata; > + struct omap_musb_board_data *bdata; > + struct musb_hdrc_config *config; > + struct device_node *np; > + int val, ret; > + > + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); > + if (!pdata) > + goto err_out; > + > + bdata = devm_kzalloc(&pdev->dev, sizeof(*bdata), GFP_KERNEL); > + if (!bdata) > + goto err_pdata; > + > + config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); > + if (!config) > + goto err_bdata; > + > + /* Set defaults */ > + config->num_eps = 16; > + config->ram_bits = 12; > + config->multipoint = true; all of these are board-specific. > + > + bdata->interface_type = MUSB_INTERFACE_UTMI; > + bdata->mode = MUSB_OTG; > + bdata->power = 500; > + bdata->extvbus = 1; so are these. > + bdata->set_phy_power = am35x_musb_phy_power; > + bdata->clear_irq = am35x_musb_clear_irq; > + bdata->set_mode = am35x_set_mode; > + bdata->reset = am35x_musb_reset; > + > + pdata->mode = MUSB_OTG; > + pdata->power = 250; also mode and power. > + pdata->board_data = bdata; > + pdata->config = config; > + > + /* Read settings from device tree */ > + np = pdev->dev.of_node; > + if (np) { > + of_property_read_u32(np, "mode", (u32 *)&pdata->mode); > + of_property_read_u32(np, "interface-type", > + (u32 *)&bdata->interface_type); > + of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); > + of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); > + of_property_read_u32(np, "power", (u32 *)&pdata->power); > + > + ret = of_property_read_u32(np, "multipoint", &val); > + if (!ret && val) > + config->multipoint = true; > + } > + return pdata; > + > +err_bdata: > + kfree(bdata); > +err_pdata: > + kfree(pdata); > +err_out: > + return NULL; > +} > + > static int am35x_probe(struct platform_device *pdev) > { > struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); > @@ -475,14 +544,20 @@ static int am35x_probe(struct platform_d > goto err0; > } > > - phy_clk = clk_get(&pdev->dev, "fck"); > + if (!pdata) { > + pdata = am35x_get_config(pdev); > + if (!pdata) > + goto err1; > + } > + > + phy_clk = clk_get(&pdev->dev, "hsotgusb_fck"); why did you change the clock name ? That shouldn't be necessary. > if (IS_ERR(phy_clk)) { > dev_err(&pdev->dev, "failed to get PHY clock\n"); > ret = PTR_ERR(phy_clk); > goto err3; > } > > - clk = clk_get(&pdev->dev, "ick"); > + clk = clk_get(&pdev->dev, "hsotgusb_ick"); nor here. -- balbi
Attachment:
signature.asc
Description: PGP signature