/** * usbhs_omap_probe - initialize TI-based HCDs * * Allocates basic resources for this USB host controller. */ static int usbhs_omap_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev); struct usbhs_hcd_omap *omap; struct resource *res; int ret = 0; int i; bool need_logic_fck; if (dev->of_node) { /* For DT boot we populate platform data from OF node */ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; ret = usbhs_omap_get_dt_pdata(dev, pdata); if (ret) return ret; dev->platform_data = pdata; } if (!pdata) { dev_err(dev, "Missing platform data\n"); return -ENODEV; } if (pdata->nports > OMAP3_HS_USB_PORTS) { dev_info(dev, "Too many num_ports <%d> in platform_data. Max %d\n", pdata->nports, OMAP3_HS_USB_PORTS); return -ENODEV; } omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL); if (!omap) { dev_err(dev, "Memory allocation failed\n"); return -ENOMEM; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); omap->uhh_base = devm_ioremap_resource(dev, res); if (IS_ERR(omap->uhh_base)) return PTR_ERR(omap->uhh_base); omap->pdata = pdata; /* Initialize the TLL subsystem */ omap_tll_init(pdata); pm_runtime_enable(dev); platform_set_drvdata(pdev, omap); pm_runtime_get_sync(dev); omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); /* we need to call runtime suspend before we update omap->nports * to prevent unbalanced clk_disable() */ pm_runtime_put_sync(dev); /* * If platform data contains nports then use that * else make out number of ports from USBHS revision */ if (pdata->nports) { omap->nports = pdata->nports; } else { switch (omap->usbhs_rev) { case OMAP_USBHS_REV1: omap->nports = 3; break; case OMAP_USBHS_REV2: omap->nports = 2; break; default: omap->nports = OMAP3_HS_USB_PORTS; dev_dbg(dev, "USB HOST Rev:0x%x not recognized, assuming %d ports\n", omap->usbhs_rev, omap->nports); break; } pdata->nports = omap->nports; } i = sizeof(struct clk *) * omap->nports; omap->utmi_clk = devm_kzalloc(dev, i, GFP_KERNEL); omap->hsic480m_clk = devm_kzalloc(dev, i, GFP_KERNEL); omap->hsic60m_clk = devm_kzalloc(dev, i, GFP_KERNEL); if (!omap->utmi_clk || !omap->hsic480m_clk || !omap->hsic60m_clk) { dev_err(dev, "Memory allocation failed\n"); ret = -ENOMEM; goto err_mem; } /* Set all clocks as invalid to begin with */ omap->ehci_logic_fck = ERR_PTR(-ENODEV); omap->init_60m_fclk = ERR_PTR(-ENODEV); omap->utmi_p1_gfclk = ERR_PTR(-ENODEV); omap->utmi_p2_gfclk = ERR_PTR(-ENODEV); omap->xclk60mhsp1_ck = ERR_PTR(-ENODEV); omap->xclk60mhsp2_ck = ERR_PTR(-ENODEV); for (i = 0; i < omap->nports; i++) { omap->utmi_clk[i] = ERR_PTR(-ENODEV); omap->hsic480m_clk[i] = ERR_PTR(-ENODEV); omap->hsic60m_clk[i] = ERR_PTR(-ENODEV); } /* for OMAP3 i.e. USBHS REV1 */ if (omap->usbhs_rev == OMAP_USBHS_REV1) { need_logic_fck = false; for (i = 0; i < omap->nports; i++) { if (is_ehci_phy_mode(pdata->port_mode[i]) || is_ehci_tll_mode(pdata->port_mode[i]) || is_ehci_hsic_mode(pdata->port_mode[i])) need_logic_fck |= true; } if (need_logic_fck) { omap->ehci_logic_fck = devm_clk_get(dev, "usbhost_120m_fck"); if (IS_ERR(omap->ehci_logic_fck)) { ret = PTR_ERR(omap->ehci_logic_fck); dev_err(dev, "usbhost_120m_fck failed:%d\n", ret); goto err_mem; } } goto initialize; } /* for OMAP4+ i.e. USBHS REV2+ */ omap->utmi_p1_gfclk = devm_clk_get(dev, "utmi_p1_gfclk"); if (IS_ERR(omap->utmi_p1_gfclk)) { ret = PTR_ERR(omap->utmi_p1_gfclk); dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); goto err_mem; } omap->utmi_p2_gfclk = devm_clk_get(dev, "utmi_p2_gfclk"); if (IS_ERR(omap->utmi_p2_gfclk)) { ret = PTR_ERR(omap->utmi_p2_gfclk); dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); goto err_mem; } omap->xclk60mhsp1_ck = devm_clk_get(dev, "refclk_60m_ext_p1"); if (IS_ERR(omap->xclk60mhsp1_ck)) { ret = PTR_ERR(omap->xclk60mhsp1_ck); dev_err(dev, "refclk_60m_ext_p1 failed error:%d\n", ret); goto err_mem; } omap->xclk60mhsp2_ck = devm_clk_get(dev, "refclk_60m_ext_p2"); if (IS_ERR(omap->xclk60mhsp2_ck)) { ret = PTR_ERR(omap->xclk60mhsp2_ck); dev_err(dev, "refclk_60m_ext_p2 failed error:%d\n", ret); goto err_mem; } omap->init_60m_fclk = devm_clk_get(dev, "refclk_60m_int"); if (IS_ERR(omap->init_60m_fclk)) { ret = PTR_ERR(omap->init_60m_fclk); dev_err(dev, "refclk_60m_int failed error:%d\n", ret); goto err_mem; } for (i = 0; i < omap->nports; i++) { char clkname[30]; /* clock names are indexed from 1*/ snprintf(clkname, sizeof(clkname), "usb_host_hs_utmi_p%d_clk", i + 1); /* If a clock is not found we won't bail out as not all * platforms have all clocks and we can function without * them */ omap->utmi_clk[i] = devm_clk_get(dev, clkname); if (IS_ERR(omap->utmi_clk[i])) { ret = PTR_ERR(omap->utmi_clk[i]); dev_err(dev, "Failed to get clock : %s : %d\n", clkname, ret); goto err_mem; } snprintf(clkname, sizeof(clkname), "usb_host_hs_hsic480m_p%d_clk", i + 1); omap->hsic480m_clk[i] = devm_clk_get(dev, clkname); if (IS_ERR(omap->hsic480m_clk[i])) { ret = PTR_ERR(omap->hsic480m_clk[i]); dev_err(dev, "Failed to get clock : %s : %d\n", clkname, ret); goto err_mem; } snprintf(clkname, sizeof(clkname), "usb_host_hs_hsic60m_p%d_clk", i + 1); omap->hsic60m_clk[i] = devm_clk_get(dev, clkname); if (IS_ERR(omap->hsic60m_clk[i])) { ret = PTR_ERR(omap->hsic60m_clk[i]); dev_err(dev, "Failed to get clock : %s : %d\n", clkname, ret); goto err_mem; } } if (is_ehci_phy_mode(pdata->port_mode[0])) { ret = clk_set_parent(omap->utmi_p1_gfclk, omap->xclk60mhsp1_ck); if (ret != 0) { dev_err(dev, "xclk60mhsp1_ck set parent failed: %d\n", ret); goto err_mem; } } else if (is_ehci_tll_mode(pdata->port_mode[0])) { ret = clk_set_parent(omap->utmi_p1_gfclk, omap->init_60m_fclk); if (ret != 0) { dev_err(dev, "P0 init_60m_fclk set parent failed: %d\n", ret); goto err_mem; } } if (is_ehci_phy_mode(pdata->port_mode[1])) { ret = clk_set_parent(omap->utmi_p2_gfclk, omap->xclk60mhsp2_ck); if (ret != 0) { dev_err(dev, "xclk60mhsp2_ck set parent failed: %d\n", ret); goto err_mem; } } else if (is_ehci_tll_mode(pdata->port_mode[1])) { ret = clk_set_parent(omap->utmi_p2_gfclk, omap->init_60m_fclk); if (ret != 0) { dev_err(dev, "P1 init_60m_fclk set parent failed: %d\n", ret); goto err_mem; } } initialize: omap_usbhs_init(dev); if (dev->of_node) { ret = of_platform_populate(dev->of_node, usbhs_child_match_table, NULL, dev); if (ret) { dev_err(dev, "Failed to create DT children: %d\n", ret); goto err_mem; } } else { ret = omap_usbhs_alloc_children(pdev); if (ret) { dev_err(dev, "omap_usbhs_alloc_children failed: %d\n", ret); goto err_mem; } } return 0; err_mem: pm_runtime_disable(dev); return ret; }
/** * usbhs_omap_probe - initialize TI-based HCDs * * Allocates basic resources for this USB host controller. */ static int __devinit usbhs_omap_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct usbhs_omap_platform_data *pdata = dev->platform_data; struct usbhs_hcd_omap *omap; struct resource *res; int ret = 0; int i; if (!pdata) { dev_err(dev, "Missing platform data\n"); ret = -ENOMEM; goto end_probe; } omap = kzalloc(sizeof(*omap), GFP_KERNEL); if (!omap) { dev_err(dev, "Memory allocation failed\n"); ret = -ENOMEM; goto end_probe; } spin_lock_init(&omap->lock); for (i = 0; i < OMAP3_HS_USB_PORTS; i++) omap->platdata.port_mode[i] = pdata->port_mode[i]; omap->platdata.ehci_data = pdata->ehci_data; omap->platdata.ohci_data = pdata->ohci_data; pm_runtime_enable(dev); for (i = 0; i < OMAP3_HS_USB_PORTS; i++) if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) || is_ehci_hsic_mode(i)) { omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck"); if (IS_ERR(omap->ehci_logic_fck)) { ret = PTR_ERR(omap->ehci_logic_fck); dev_warn(dev, "ehci_logic_fck failed:%d\n", ret); } break; } omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); if (IS_ERR(omap->utmi_p1_fck)) { ret = PTR_ERR(omap->utmi_p1_fck); dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); goto err_end; } omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1"); if (IS_ERR(omap->xclk60mhsp1_ck)) { ret = PTR_ERR(omap->xclk60mhsp1_ck); dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); goto err_utmi_p1_fck; } omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); if (IS_ERR(omap->utmi_p2_fck)) { ret = PTR_ERR(omap->utmi_p2_fck); dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); goto err_xclk60mhsp1_ck; } omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2"); if (IS_ERR(omap->xclk60mhsp2_ck)) { ret = PTR_ERR(omap->xclk60mhsp2_ck); dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); goto err_utmi_p2_fck; } omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); if (IS_ERR(omap->usbhost_p1_fck)) { ret = PTR_ERR(omap->usbhost_p1_fck); dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); goto err_xclk60mhsp2_ck; } omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); if (IS_ERR(omap->usbhost_p2_fck)) { ret = PTR_ERR(omap->usbhost_p2_fck); dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); goto err_usbhost_p1_fck; } if (cpu_is_omap54xx()) { omap->usbhost_p3_fck = clk_get(dev, "usb_host_hs_utmi_p3_clk"); if (IS_ERR(omap->usbhost_p3_fck)) { ret = PTR_ERR(omap->usbhost_p3_fck); dev_err(dev, "usbhost_p3_fck failed error:%d\n", ret); goto err_usbhost_p2_fck; } } if (cpu_is_omap54xx()) omap->init_60m_fclk = clk_get(dev, "l3init_60m_fclk"); else omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); if (IS_ERR(omap->init_60m_fclk)) { ret = PTR_ERR(omap->init_60m_fclk); dev_err(dev, "init_60m_fclk failed error:%d\n", ret); goto err_usbhost_p2_fck; } omap->usb_host_hs_hsic60m_p1_clk = clk_get(dev, "usb_host_hs_hsic60m_p1_clk"); if (IS_ERR(omap->usb_host_hs_hsic60m_p1_clk)) { ret = PTR_ERR(omap->usb_host_hs_hsic60m_p1_clk); dev_err(dev, "Unable to get usb_host_hs_hsic60m_p1_clk\n"); goto err_init_60m_fclk; } omap->usb_host_hs_hsic480m_p1_clk = clk_get(dev, "usb_host_hs_hsic480m_p1_clk"); if (IS_ERR(omap->usb_host_hs_hsic480m_p1_clk)) { ret = PTR_ERR(omap->usb_host_hs_hsic480m_p1_clk); dev_err(dev, "Unable to get usb_host_hs_hsic480m_p1_clk\n"); goto err_usb_host_hs_hsic60m_p1_clk; } omap->usb_host_hs_hsic60m_p2_clk = clk_get(dev, "usb_host_hs_hsic60m_p2_clk"); if (IS_ERR(omap->usb_host_hs_hsic60m_p2_clk)) { ret = PTR_ERR(omap->usb_host_hs_hsic60m_p2_clk); dev_err(dev, "Unable to get usb_host_hs_hsic60m_p2_clk\n"); goto err_usb_host_hs_hsic480m_p1_clk; } omap->usb_host_hs_hsic480m_p2_clk = clk_get(dev, "usb_host_hs_hsic480m_p2_clk"); if (IS_ERR(omap->usb_host_hs_hsic480m_p2_clk)) { ret = PTR_ERR(omap->usb_host_hs_hsic480m_p2_clk); dev_err(dev, "Unable to get usb_host_hs_hsic480m_p2_clk\n"); goto err_usb_host_hs_hsic60m_p2_clk; } if (cpu_is_omap54xx()) { omap->usb_host_hs_hsic60m_p3_clk = clk_get(dev, "usb_host_hs_hsic60m_p3_clk"); if (IS_ERR(omap->usb_host_hs_hsic60m_p3_clk)) { ret = PTR_ERR(omap->usb_host_hs_hsic60m_p3_clk); dev_err(dev, "Unable to get usb_host_hs_hsic60m_p3_clk\n"); goto err_usb_host_hs_hsic480m_p2_clk; } omap->usb_host_hs_hsic480m_p3_clk = clk_get(dev, "usb_host_hs_hsic480m_p3_clk"); if (IS_ERR(omap->usb_host_hs_hsic480m_p3_clk)) { ret = PTR_ERR(omap->usb_host_hs_hsic480m_p3_clk); dev_err(dev, "Unable to get usb_host_hs_hsic480m_p3_clk\n"); goto err_usb_host_hs_hsic60m_p3_clk; } } if (is_ehci_phy_mode(pdata->port_mode[0])) { /* for OMAP3 , the clk set paretn fails */ ret = clk_set_parent(omap->utmi_p1_fck, omap->xclk60mhsp1_ck); if (ret != 0) dev_err(dev, "xclk60mhsp1_ck set parent" "failed error:%d\n", ret); } else if (is_ehci_tll_mode(pdata->port_mode[0])) { ret = clk_set_parent(omap->utmi_p1_fck, omap->init_60m_fclk); if (ret != 0) dev_err(dev, "init_60m_fclk set parent" "failed error:%d\n", ret); } if (is_ehci_phy_mode(pdata->port_mode[1])) { ret = clk_set_parent(omap->utmi_p2_fck, omap->xclk60mhsp2_ck); if (ret != 0) dev_err(dev, "xclk60mhsp2_ck set parent" "failed error:%d\n", ret); } else if (is_ehci_tll_mode(pdata->port_mode[1])) { ret = clk_set_parent(omap->utmi_p2_fck, omap->init_60m_fclk); if (ret != 0) dev_err(dev, "init_60m_fclk set parent" "failed error:%d\n", ret); } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); if (!res) { dev_err(dev, "UHH EHCI get resource failed\n"); ret = -ENODEV; goto err_usb_host_hs_hsic480m_p3_clk; } omap->uhh_base = ioremap(res->start, resource_size(res)); if (!omap->uhh_base) { dev_err(dev, "UHH ioremap failed\n"); ret = -ENOMEM; goto err_usb_host_hs_hsic480m_p3_clk; } platform_set_drvdata(pdev, omap); omap_usbhs_init(dev); ret = omap_usbhs_alloc_children(pdev); if (ret) { dev_err(dev, "omap_usbhs_alloc_children failed\n"); goto err_alloc; } goto end_probe; err_alloc: omap_usbhs_deinit(&pdev->dev); iounmap(omap->uhh_base); err_usb_host_hs_hsic480m_p3_clk: clk_put(omap->usb_host_hs_hsic480m_p3_clk); err_usb_host_hs_hsic60m_p3_clk: clk_put(omap->usb_host_hs_hsic60m_p3_clk); err_usb_host_hs_hsic480m_p2_clk: clk_put(omap->usb_host_hs_hsic480m_p2_clk); err_usb_host_hs_hsic60m_p2_clk: clk_put(omap->usb_host_hs_hsic60m_p2_clk); err_usb_host_hs_hsic480m_p1_clk: clk_put(omap->usb_host_hs_hsic480m_p1_clk); err_usb_host_hs_hsic60m_p1_clk: clk_put(omap->usb_host_hs_hsic60m_p1_clk); err_init_60m_fclk: clk_put(omap->init_60m_fclk); err_usbhost_p2_fck: clk_put(omap->usbhost_p2_fck); err_usbhost_p1_fck: clk_put(omap->usbhost_p1_fck); err_xclk60mhsp2_ck: clk_put(omap->xclk60mhsp2_ck); err_utmi_p2_fck: clk_put(omap->utmi_p2_fck); err_xclk60mhsp1_ck: clk_put(omap->xclk60mhsp1_ck); err_utmi_p1_fck: clk_put(omap->utmi_p1_fck); err_end: clk_put(omap->ehci_logic_fck); pm_runtime_disable(dev); kfree(omap); end_probe: return ret; }