static int omap_tll_attach(device_t dev) { struct omap_tll_softc *sc; sc = device_get_softc(dev); /* save the device */ sc->sc_dev = dev; /* Allocate resource for the TLL register set */ sc->tll_mem_rid = 0; sc->tll_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->tll_mem_rid, RF_ACTIVE); if (!sc->tll_mem_res) { device_printf(dev, "Error: Could not map TLL memory\n"); goto error; } omap_tll_init(sc); omap_tll_sc = sc; return (0); error: omap_tll_detach(dev); return (ENXIO); }
/** * 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; }