/drivers/mfd/omap-usb-host.c

http://github.com/mirrors/linux · C · 875 lines · 665 code · 146 blank · 64 comment · 99 complexity · 669005359c2a8819f4e9c9118546a79e MD5 · raw file

  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /**
  3. * omap-usb-host.c - The USBHS core driver for OMAP EHCI & OHCI
  4. *
  5. * Copyright (C) 2011-2013 Texas Instruments Incorporated - http://www.ti.com
  6. * Author: Keshava Munegowda <keshava_mgowda@ti.com>
  7. * Author: Roger Quadros <rogerq@ti.com>
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/types.h>
  12. #include <linux/slab.h>
  13. #include <linux/delay.h>
  14. #include <linux/clk.h>
  15. #include <linux/dma-mapping.h>
  16. #include <linux/gpio.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/platform_data/usb-omap.h>
  19. #include <linux/pm_runtime.h>
  20. #include <linux/of.h>
  21. #include <linux/of_platform.h>
  22. #include <linux/err.h>
  23. #include "omap-usb.h"
  24. #define USBHS_DRIVER_NAME "usbhs_omap"
  25. #define OMAP_EHCI_DEVICE "ehci-omap"
  26. #define OMAP_OHCI_DEVICE "ohci-omap3"
  27. /* OMAP USBHOST Register addresses */
  28. /* UHH Register Set */
  29. #define OMAP_UHH_REVISION (0x00)
  30. #define OMAP_UHH_SYSCONFIG (0x10)
  31. #define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12)
  32. #define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8)
  33. #define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3)
  34. #define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2)
  35. #define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1)
  36. #define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0)
  37. #define OMAP_UHH_SYSSTATUS (0x14)
  38. #define OMAP_UHH_HOSTCONFIG (0x40)
  39. #define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0)
  40. #define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0)
  41. #define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11)
  42. #define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12)
  43. #define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2)
  44. #define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3)
  45. #define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4)
  46. #define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5)
  47. #define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8)
  48. #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9)
  49. #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10)
  50. #define OMAP4_UHH_HOSTCONFIG_APP_START_CLK (1 << 31)
  51. /* OMAP4-specific defines */
  52. #define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR (3 << 2)
  53. #define OMAP4_UHH_SYSCONFIG_NOIDLE (1 << 2)
  54. #define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR (3 << 4)
  55. #define OMAP4_UHH_SYSCONFIG_NOSTDBY (1 << 4)
  56. #define OMAP4_UHH_SYSCONFIG_SOFTRESET (1 << 0)
  57. #define OMAP4_P1_MODE_CLEAR (3 << 16)
  58. #define OMAP4_P1_MODE_TLL (1 << 16)
  59. #define OMAP4_P1_MODE_HSIC (3 << 16)
  60. #define OMAP4_P2_MODE_CLEAR (3 << 18)
  61. #define OMAP4_P2_MODE_TLL (1 << 18)
  62. #define OMAP4_P2_MODE_HSIC (3 << 18)
  63. #define OMAP_UHH_DEBUG_CSR (0x44)
  64. /* Values of UHH_REVISION - Note: these are not given in the TRM */
  65. #define OMAP_USBHS_REV1 0x00000010 /* OMAP3 */
  66. #define OMAP_USBHS_REV2 0x50700100 /* OMAP4 */
  67. #define is_omap_usbhs_rev1(x) (x->usbhs_rev == OMAP_USBHS_REV1)
  68. #define is_omap_usbhs_rev2(x) (x->usbhs_rev == OMAP_USBHS_REV2)
  69. #define is_ehci_phy_mode(x) (x == OMAP_EHCI_PORT_MODE_PHY)
  70. #define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL)
  71. #define is_ehci_hsic_mode(x) (x == OMAP_EHCI_PORT_MODE_HSIC)
  72. struct usbhs_hcd_omap {
  73. int nports;
  74. struct clk **utmi_clk;
  75. struct clk **hsic60m_clk;
  76. struct clk **hsic480m_clk;
  77. struct clk *xclk60mhsp1_ck;
  78. struct clk *xclk60mhsp2_ck;
  79. struct clk *utmi_p1_gfclk;
  80. struct clk *utmi_p2_gfclk;
  81. struct clk *init_60m_fclk;
  82. struct clk *ehci_logic_fck;
  83. void __iomem *uhh_base;
  84. struct usbhs_omap_platform_data *pdata;
  85. u32 usbhs_rev;
  86. };
  87. /*-------------------------------------------------------------------------*/
  88. static const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
  89. static u64 usbhs_dmamask = DMA_BIT_MASK(32);
  90. /*-------------------------------------------------------------------------*/
  91. static inline void usbhs_write(void __iomem *base, u32 reg, u32 val)
  92. {
  93. writel_relaxed(val, base + reg);
  94. }
  95. static inline u32 usbhs_read(void __iomem *base, u32 reg)
  96. {
  97. return readl_relaxed(base + reg);
  98. }
  99. /*-------------------------------------------------------------------------*/
  100. /**
  101. * Map 'enum usbhs_omap_port_mode' found in <linux/platform_data/usb-omap.h>
  102. * to the device tree binding portN-mode found in
  103. * 'Documentation/devicetree/bindings/mfd/omap-usb-host.txt'
  104. */
  105. static const char * const port_modes[] = {
  106. [OMAP_USBHS_PORT_MODE_UNUSED] = "",
  107. [OMAP_EHCI_PORT_MODE_PHY] = "ehci-phy",
  108. [OMAP_EHCI_PORT_MODE_TLL] = "ehci-tll",
  109. [OMAP_EHCI_PORT_MODE_HSIC] = "ehci-hsic",
  110. [OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0] = "ohci-phy-6pin-datse0",
  111. [OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM] = "ohci-phy-6pin-dpdm",
  112. [OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0] = "ohci-phy-3pin-datse0",
  113. [OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM] = "ohci-phy-4pin-dpdm",
  114. [OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0] = "ohci-tll-6pin-datse0",
  115. [OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM] = "ohci-tll-6pin-dpdm",
  116. [OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0] = "ohci-tll-3pin-datse0",
  117. [OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM] = "ohci-tll-4pin-dpdm",
  118. [OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0] = "ohci-tll-2pin-datse0",
  119. [OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM] = "ohci-tll-2pin-dpdm",
  120. };
  121. static struct platform_device *omap_usbhs_alloc_child(const char *name,
  122. struct resource *res, int num_resources, void *pdata,
  123. size_t pdata_size, struct device *dev)
  124. {
  125. struct platform_device *child;
  126. int ret;
  127. child = platform_device_alloc(name, 0);
  128. if (!child) {
  129. dev_err(dev, "platform_device_alloc %s failed\n", name);
  130. goto err_end;
  131. }
  132. ret = platform_device_add_resources(child, res, num_resources);
  133. if (ret) {
  134. dev_err(dev, "platform_device_add_resources failed\n");
  135. goto err_alloc;
  136. }
  137. ret = platform_device_add_data(child, pdata, pdata_size);
  138. if (ret) {
  139. dev_err(dev, "platform_device_add_data failed\n");
  140. goto err_alloc;
  141. }
  142. child->dev.dma_mask = &usbhs_dmamask;
  143. dma_set_coherent_mask(&child->dev, DMA_BIT_MASK(32));
  144. child->dev.parent = dev;
  145. ret = platform_device_add(child);
  146. if (ret) {
  147. dev_err(dev, "platform_device_add failed\n");
  148. goto err_alloc;
  149. }
  150. return child;
  151. err_alloc:
  152. platform_device_put(child);
  153. err_end:
  154. return NULL;
  155. }
  156. static int omap_usbhs_alloc_children(struct platform_device *pdev)
  157. {
  158. struct device *dev = &pdev->dev;
  159. struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
  160. struct platform_device *ehci;
  161. struct platform_device *ohci;
  162. struct resource *res;
  163. struct resource resources[2];
  164. int ret;
  165. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
  166. if (!res) {
  167. dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n");
  168. ret = -ENODEV;
  169. goto err_end;
  170. }
  171. resources[0] = *res;
  172. res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ehci-irq");
  173. if (!res) {
  174. dev_err(dev, " EHCI get resource IORESOURCE_IRQ failed\n");
  175. ret = -ENODEV;
  176. goto err_end;
  177. }
  178. resources[1] = *res;
  179. ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, pdata,
  180. sizeof(*pdata), dev);
  181. if (!ehci) {
  182. dev_err(dev, "omap_usbhs_alloc_child failed\n");
  183. ret = -ENOMEM;
  184. goto err_end;
  185. }
  186. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci");
  187. if (!res) {
  188. dev_err(dev, "OHCI get resource IORESOURCE_MEM failed\n");
  189. ret = -ENODEV;
  190. goto err_ehci;
  191. }
  192. resources[0] = *res;
  193. res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ohci-irq");
  194. if (!res) {
  195. dev_err(dev, "OHCI get resource IORESOURCE_IRQ failed\n");
  196. ret = -ENODEV;
  197. goto err_ehci;
  198. }
  199. resources[1] = *res;
  200. ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, pdata,
  201. sizeof(*pdata), dev);
  202. if (!ohci) {
  203. dev_err(dev, "omap_usbhs_alloc_child failed\n");
  204. ret = -ENOMEM;
  205. goto err_ehci;
  206. }
  207. return 0;
  208. err_ehci:
  209. platform_device_unregister(ehci);
  210. err_end:
  211. return ret;
  212. }
  213. static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
  214. {
  215. switch (pmode) {
  216. case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
  217. case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
  218. case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
  219. case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
  220. case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
  221. case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
  222. case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
  223. case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
  224. case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
  225. case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
  226. return true;
  227. default:
  228. return false;
  229. }
  230. }
  231. static int usbhs_runtime_resume(struct device *dev)
  232. {
  233. struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
  234. struct usbhs_omap_platform_data *pdata = omap->pdata;
  235. int i, r;
  236. dev_dbg(dev, "usbhs_runtime_resume\n");
  237. omap_tll_enable(pdata);
  238. if (!IS_ERR(omap->ehci_logic_fck))
  239. clk_prepare_enable(omap->ehci_logic_fck);
  240. for (i = 0; i < omap->nports; i++) {
  241. switch (pdata->port_mode[i]) {
  242. case OMAP_EHCI_PORT_MODE_HSIC:
  243. if (!IS_ERR(omap->hsic60m_clk[i])) {
  244. r = clk_prepare_enable(omap->hsic60m_clk[i]);
  245. if (r) {
  246. dev_err(dev,
  247. "Can't enable port %d hsic60m clk:%d\n",
  248. i, r);
  249. }
  250. }
  251. if (!IS_ERR(omap->hsic480m_clk[i])) {
  252. r = clk_prepare_enable(omap->hsic480m_clk[i]);
  253. if (r) {
  254. dev_err(dev,
  255. "Can't enable port %d hsic480m clk:%d\n",
  256. i, r);
  257. }
  258. }
  259. /* Fall through - as HSIC mode needs utmi_clk */
  260. case OMAP_EHCI_PORT_MODE_TLL:
  261. if (!IS_ERR(omap->utmi_clk[i])) {
  262. r = clk_prepare_enable(omap->utmi_clk[i]);
  263. if (r) {
  264. dev_err(dev,
  265. "Can't enable port %d clk : %d\n",
  266. i, r);
  267. }
  268. }
  269. break;
  270. default:
  271. break;
  272. }
  273. }
  274. return 0;
  275. }
  276. static int usbhs_runtime_suspend(struct device *dev)
  277. {
  278. struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
  279. struct usbhs_omap_platform_data *pdata = omap->pdata;
  280. int i;
  281. dev_dbg(dev, "usbhs_runtime_suspend\n");
  282. for (i = 0; i < omap->nports; i++) {
  283. switch (pdata->port_mode[i]) {
  284. case OMAP_EHCI_PORT_MODE_HSIC:
  285. if (!IS_ERR(omap->hsic60m_clk[i]))
  286. clk_disable_unprepare(omap->hsic60m_clk[i]);
  287. if (!IS_ERR(omap->hsic480m_clk[i]))
  288. clk_disable_unprepare(omap->hsic480m_clk[i]);
  289. /* Fall through - as utmi_clks were used in HSIC mode */
  290. case OMAP_EHCI_PORT_MODE_TLL:
  291. if (!IS_ERR(omap->utmi_clk[i]))
  292. clk_disable_unprepare(omap->utmi_clk[i]);
  293. break;
  294. default:
  295. break;
  296. }
  297. }
  298. if (!IS_ERR(omap->ehci_logic_fck))
  299. clk_disable_unprepare(omap->ehci_logic_fck);
  300. omap_tll_disable(pdata);
  301. return 0;
  302. }
  303. static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap,
  304. unsigned reg)
  305. {
  306. struct usbhs_omap_platform_data *pdata = omap->pdata;
  307. int i;
  308. for (i = 0; i < omap->nports; i++) {
  309. switch (pdata->port_mode[i]) {
  310. case OMAP_USBHS_PORT_MODE_UNUSED:
  311. reg &= ~(OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS << i);
  312. break;
  313. case OMAP_EHCI_PORT_MODE_PHY:
  314. if (pdata->single_ulpi_bypass)
  315. break;
  316. if (i == 0)
  317. reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
  318. else
  319. reg &= ~(OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
  320. << (i-1));
  321. break;
  322. default:
  323. if (pdata->single_ulpi_bypass)
  324. break;
  325. if (i == 0)
  326. reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
  327. else
  328. reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
  329. << (i-1);
  330. break;
  331. }
  332. }
  333. if (pdata->single_ulpi_bypass) {
  334. /* bypass ULPI only if none of the ports use PHY mode */
  335. reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
  336. for (i = 0; i < omap->nports; i++) {
  337. if (is_ehci_phy_mode(pdata->port_mode[i])) {
  338. reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
  339. break;
  340. }
  341. }
  342. }
  343. return reg;
  344. }
  345. static unsigned omap_usbhs_rev2_hostconfig(struct usbhs_hcd_omap *omap,
  346. unsigned reg)
  347. {
  348. struct usbhs_omap_platform_data *pdata = omap->pdata;
  349. int i;
  350. for (i = 0; i < omap->nports; i++) {
  351. /* Clear port mode fields for PHY mode */
  352. reg &= ~(OMAP4_P1_MODE_CLEAR << 2 * i);
  353. if (is_ehci_tll_mode(pdata->port_mode[i]) ||
  354. (is_ohci_port(pdata->port_mode[i])))
  355. reg |= OMAP4_P1_MODE_TLL << 2 * i;
  356. else if (is_ehci_hsic_mode(pdata->port_mode[i]))
  357. reg |= OMAP4_P1_MODE_HSIC << 2 * i;
  358. }
  359. return reg;
  360. }
  361. static void omap_usbhs_init(struct device *dev)
  362. {
  363. struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
  364. unsigned reg;
  365. dev_dbg(dev, "starting TI HSUSB Controller\n");
  366. pm_runtime_get_sync(dev);
  367. reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
  368. /* setup ULPI bypass and burst configurations */
  369. reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
  370. | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
  371. | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
  372. reg |= OMAP4_UHH_HOSTCONFIG_APP_START_CLK;
  373. reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
  374. switch (omap->usbhs_rev) {
  375. case OMAP_USBHS_REV1:
  376. reg = omap_usbhs_rev1_hostconfig(omap, reg);
  377. break;
  378. case OMAP_USBHS_REV2:
  379. reg = omap_usbhs_rev2_hostconfig(omap, reg);
  380. break;
  381. default: /* newer revisions */
  382. reg = omap_usbhs_rev2_hostconfig(omap, reg);
  383. break;
  384. }
  385. usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
  386. dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
  387. pm_runtime_put_sync(dev);
  388. }
  389. static int usbhs_omap_get_dt_pdata(struct device *dev,
  390. struct usbhs_omap_platform_data *pdata)
  391. {
  392. int ret, i;
  393. struct device_node *node = dev->of_node;
  394. ret = of_property_read_u32(node, "num-ports", &pdata->nports);
  395. if (ret)
  396. pdata->nports = 0;
  397. if (pdata->nports > OMAP3_HS_USB_PORTS) {
  398. dev_warn(dev, "Too many num_ports <%d> in device tree. Max %d\n",
  399. pdata->nports, OMAP3_HS_USB_PORTS);
  400. return -ENODEV;
  401. }
  402. /* get port modes */
  403. for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
  404. char prop[11];
  405. const char *mode;
  406. pdata->port_mode[i] = OMAP_USBHS_PORT_MODE_UNUSED;
  407. snprintf(prop, sizeof(prop), "port%d-mode", i + 1);
  408. ret = of_property_read_string(node, prop, &mode);
  409. if (ret < 0)
  410. continue;
  411. /* get 'enum usbhs_omap_port_mode' from port mode string */
  412. ret = match_string(port_modes, ARRAY_SIZE(port_modes), mode);
  413. if (ret < 0) {
  414. dev_warn(dev, "Invalid port%d-mode \"%s\" in device tree\n",
  415. i, mode);
  416. return -ENODEV;
  417. }
  418. dev_dbg(dev, "port%d-mode: %s -> %d\n", i, mode, ret);
  419. pdata->port_mode[i] = ret;
  420. }
  421. /* get flags */
  422. pdata->single_ulpi_bypass = of_property_read_bool(node,
  423. "single-ulpi-bypass");
  424. return 0;
  425. }
  426. static const struct of_device_id usbhs_child_match_table[] = {
  427. { .compatible = "ti,ehci-omap", },
  428. { .compatible = "ti,ohci-omap3", },
  429. { }
  430. };
  431. /**
  432. * usbhs_omap_probe - initialize TI-based HCDs
  433. *
  434. * Allocates basic resources for this USB host controller.
  435. */
  436. static int usbhs_omap_probe(struct platform_device *pdev)
  437. {
  438. struct device *dev = &pdev->dev;
  439. struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
  440. struct usbhs_hcd_omap *omap;
  441. struct resource *res;
  442. int ret = 0;
  443. int i;
  444. bool need_logic_fck;
  445. if (dev->of_node) {
  446. /* For DT boot we populate platform data from OF node */
  447. pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  448. if (!pdata)
  449. return -ENOMEM;
  450. ret = usbhs_omap_get_dt_pdata(dev, pdata);
  451. if (ret)
  452. return ret;
  453. dev->platform_data = pdata;
  454. }
  455. if (!pdata) {
  456. dev_err(dev, "Missing platform data\n");
  457. return -ENODEV;
  458. }
  459. if (pdata->nports > OMAP3_HS_USB_PORTS) {
  460. dev_info(dev, "Too many num_ports <%d> in platform_data. Max %d\n",
  461. pdata->nports, OMAP3_HS_USB_PORTS);
  462. return -ENODEV;
  463. }
  464. omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
  465. if (!omap) {
  466. dev_err(dev, "Memory allocation failed\n");
  467. return -ENOMEM;
  468. }
  469. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  470. omap->uhh_base = devm_ioremap_resource(dev, res);
  471. if (IS_ERR(omap->uhh_base))
  472. return PTR_ERR(omap->uhh_base);
  473. omap->pdata = pdata;
  474. /* Initialize the TLL subsystem */
  475. omap_tll_init(pdata);
  476. pm_runtime_enable(dev);
  477. platform_set_drvdata(pdev, omap);
  478. pm_runtime_get_sync(dev);
  479. omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
  480. /* we need to call runtime suspend before we update omap->nports
  481. * to prevent unbalanced clk_disable()
  482. */
  483. pm_runtime_put_sync(dev);
  484. /*
  485. * If platform data contains nports then use that
  486. * else make out number of ports from USBHS revision
  487. */
  488. if (pdata->nports) {
  489. omap->nports = pdata->nports;
  490. } else {
  491. switch (omap->usbhs_rev) {
  492. case OMAP_USBHS_REV1:
  493. omap->nports = 3;
  494. break;
  495. case OMAP_USBHS_REV2:
  496. omap->nports = 2;
  497. break;
  498. default:
  499. omap->nports = OMAP3_HS_USB_PORTS;
  500. dev_dbg(dev,
  501. "USB HOST Rev:0x%x not recognized, assuming %d ports\n",
  502. omap->usbhs_rev, omap->nports);
  503. break;
  504. }
  505. pdata->nports = omap->nports;
  506. }
  507. i = sizeof(struct clk *) * omap->nports;
  508. omap->utmi_clk = devm_kzalloc(dev, i, GFP_KERNEL);
  509. omap->hsic480m_clk = devm_kzalloc(dev, i, GFP_KERNEL);
  510. omap->hsic60m_clk = devm_kzalloc(dev, i, GFP_KERNEL);
  511. if (!omap->utmi_clk || !omap->hsic480m_clk || !omap->hsic60m_clk) {
  512. dev_err(dev, "Memory allocation failed\n");
  513. ret = -ENOMEM;
  514. goto err_mem;
  515. }
  516. /* Set all clocks as invalid to begin with */
  517. omap->ehci_logic_fck = ERR_PTR(-ENODEV);
  518. omap->init_60m_fclk = ERR_PTR(-ENODEV);
  519. omap->utmi_p1_gfclk = ERR_PTR(-ENODEV);
  520. omap->utmi_p2_gfclk = ERR_PTR(-ENODEV);
  521. omap->xclk60mhsp1_ck = ERR_PTR(-ENODEV);
  522. omap->xclk60mhsp2_ck = ERR_PTR(-ENODEV);
  523. for (i = 0; i < omap->nports; i++) {
  524. omap->utmi_clk[i] = ERR_PTR(-ENODEV);
  525. omap->hsic480m_clk[i] = ERR_PTR(-ENODEV);
  526. omap->hsic60m_clk[i] = ERR_PTR(-ENODEV);
  527. }
  528. /* for OMAP3 i.e. USBHS REV1 */
  529. if (omap->usbhs_rev == OMAP_USBHS_REV1) {
  530. need_logic_fck = false;
  531. for (i = 0; i < omap->nports; i++) {
  532. if (is_ehci_phy_mode(pdata->port_mode[i]) ||
  533. is_ehci_tll_mode(pdata->port_mode[i]) ||
  534. is_ehci_hsic_mode(pdata->port_mode[i]))
  535. need_logic_fck |= true;
  536. }
  537. if (need_logic_fck) {
  538. omap->ehci_logic_fck = devm_clk_get(dev,
  539. "usbhost_120m_fck");
  540. if (IS_ERR(omap->ehci_logic_fck)) {
  541. ret = PTR_ERR(omap->ehci_logic_fck);
  542. dev_err(dev, "usbhost_120m_fck failed:%d\n",
  543. ret);
  544. goto err_mem;
  545. }
  546. }
  547. goto initialize;
  548. }
  549. /* for OMAP4+ i.e. USBHS REV2+ */
  550. omap->utmi_p1_gfclk = devm_clk_get(dev, "utmi_p1_gfclk");
  551. if (IS_ERR(omap->utmi_p1_gfclk)) {
  552. ret = PTR_ERR(omap->utmi_p1_gfclk);
  553. dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
  554. goto err_mem;
  555. }
  556. omap->utmi_p2_gfclk = devm_clk_get(dev, "utmi_p2_gfclk");
  557. if (IS_ERR(omap->utmi_p2_gfclk)) {
  558. ret = PTR_ERR(omap->utmi_p2_gfclk);
  559. dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
  560. goto err_mem;
  561. }
  562. omap->xclk60mhsp1_ck = devm_clk_get(dev, "refclk_60m_ext_p1");
  563. if (IS_ERR(omap->xclk60mhsp1_ck)) {
  564. ret = PTR_ERR(omap->xclk60mhsp1_ck);
  565. dev_err(dev, "refclk_60m_ext_p1 failed error:%d\n", ret);
  566. goto err_mem;
  567. }
  568. omap->xclk60mhsp2_ck = devm_clk_get(dev, "refclk_60m_ext_p2");
  569. if (IS_ERR(omap->xclk60mhsp2_ck)) {
  570. ret = PTR_ERR(omap->xclk60mhsp2_ck);
  571. dev_err(dev, "refclk_60m_ext_p2 failed error:%d\n", ret);
  572. goto err_mem;
  573. }
  574. omap->init_60m_fclk = devm_clk_get(dev, "refclk_60m_int");
  575. if (IS_ERR(omap->init_60m_fclk)) {
  576. ret = PTR_ERR(omap->init_60m_fclk);
  577. dev_err(dev, "refclk_60m_int failed error:%d\n", ret);
  578. goto err_mem;
  579. }
  580. for (i = 0; i < omap->nports; i++) {
  581. char clkname[30];
  582. /* clock names are indexed from 1*/
  583. snprintf(clkname, sizeof(clkname),
  584. "usb_host_hs_utmi_p%d_clk", i + 1);
  585. /* If a clock is not found we won't bail out as not all
  586. * platforms have all clocks and we can function without
  587. * them
  588. */
  589. omap->utmi_clk[i] = devm_clk_get(dev, clkname);
  590. if (IS_ERR(omap->utmi_clk[i])) {
  591. ret = PTR_ERR(omap->utmi_clk[i]);
  592. dev_err(dev, "Failed to get clock : %s : %d\n",
  593. clkname, ret);
  594. goto err_mem;
  595. }
  596. snprintf(clkname, sizeof(clkname),
  597. "usb_host_hs_hsic480m_p%d_clk", i + 1);
  598. omap->hsic480m_clk[i] = devm_clk_get(dev, clkname);
  599. if (IS_ERR(omap->hsic480m_clk[i])) {
  600. ret = PTR_ERR(omap->hsic480m_clk[i]);
  601. dev_err(dev, "Failed to get clock : %s : %d\n",
  602. clkname, ret);
  603. goto err_mem;
  604. }
  605. snprintf(clkname, sizeof(clkname),
  606. "usb_host_hs_hsic60m_p%d_clk", i + 1);
  607. omap->hsic60m_clk[i] = devm_clk_get(dev, clkname);
  608. if (IS_ERR(omap->hsic60m_clk[i])) {
  609. ret = PTR_ERR(omap->hsic60m_clk[i]);
  610. dev_err(dev, "Failed to get clock : %s : %d\n",
  611. clkname, ret);
  612. goto err_mem;
  613. }
  614. }
  615. if (is_ehci_phy_mode(pdata->port_mode[0])) {
  616. ret = clk_set_parent(omap->utmi_p1_gfclk,
  617. omap->xclk60mhsp1_ck);
  618. if (ret != 0) {
  619. dev_err(dev, "xclk60mhsp1_ck set parent failed: %d\n",
  620. ret);
  621. goto err_mem;
  622. }
  623. } else if (is_ehci_tll_mode(pdata->port_mode[0])) {
  624. ret = clk_set_parent(omap->utmi_p1_gfclk,
  625. omap->init_60m_fclk);
  626. if (ret != 0) {
  627. dev_err(dev, "P0 init_60m_fclk set parent failed: %d\n",
  628. ret);
  629. goto err_mem;
  630. }
  631. }
  632. if (is_ehci_phy_mode(pdata->port_mode[1])) {
  633. ret = clk_set_parent(omap->utmi_p2_gfclk,
  634. omap->xclk60mhsp2_ck);
  635. if (ret != 0) {
  636. dev_err(dev, "xclk60mhsp2_ck set parent failed: %d\n",
  637. ret);
  638. goto err_mem;
  639. }
  640. } else if (is_ehci_tll_mode(pdata->port_mode[1])) {
  641. ret = clk_set_parent(omap->utmi_p2_gfclk,
  642. omap->init_60m_fclk);
  643. if (ret != 0) {
  644. dev_err(dev, "P1 init_60m_fclk set parent failed: %d\n",
  645. ret);
  646. goto err_mem;
  647. }
  648. }
  649. initialize:
  650. omap_usbhs_init(dev);
  651. if (dev->of_node) {
  652. ret = of_platform_populate(dev->of_node,
  653. usbhs_child_match_table, NULL, dev);
  654. if (ret) {
  655. dev_err(dev, "Failed to create DT children: %d\n", ret);
  656. goto err_mem;
  657. }
  658. } else {
  659. ret = omap_usbhs_alloc_children(pdev);
  660. if (ret) {
  661. dev_err(dev, "omap_usbhs_alloc_children failed: %d\n",
  662. ret);
  663. goto err_mem;
  664. }
  665. }
  666. return 0;
  667. err_mem:
  668. pm_runtime_disable(dev);
  669. return ret;
  670. }
  671. static int usbhs_omap_remove_child(struct device *dev, void *data)
  672. {
  673. dev_info(dev, "unregistering\n");
  674. platform_device_unregister(to_platform_device(dev));
  675. return 0;
  676. }
  677. /**
  678. * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs
  679. * @pdev: USB Host Controller being removed
  680. *
  681. * Reverses the effect of usbhs_omap_probe().
  682. */
  683. static int usbhs_omap_remove(struct platform_device *pdev)
  684. {
  685. pm_runtime_disable(&pdev->dev);
  686. /* remove children */
  687. device_for_each_child(&pdev->dev, NULL, usbhs_omap_remove_child);
  688. return 0;
  689. }
  690. static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
  691. .runtime_suspend = usbhs_runtime_suspend,
  692. .runtime_resume = usbhs_runtime_resume,
  693. };
  694. static const struct of_device_id usbhs_omap_dt_ids[] = {
  695. { .compatible = "ti,usbhs-host" },
  696. { }
  697. };
  698. MODULE_DEVICE_TABLE(of, usbhs_omap_dt_ids);
  699. static struct platform_driver usbhs_omap_driver = {
  700. .driver = {
  701. .name = usbhs_driver_name,
  702. .pm = &usbhsomap_dev_pm_ops,
  703. .of_match_table = usbhs_omap_dt_ids,
  704. },
  705. .probe = usbhs_omap_probe,
  706. .remove = usbhs_omap_remove,
  707. };
  708. MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
  709. MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
  710. MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
  711. MODULE_LICENSE("GPL v2");
  712. MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
  713. static int omap_usbhs_drvinit(void)
  714. {
  715. return platform_driver_register(&usbhs_omap_driver);
  716. }
  717. /*
  718. * init before ehci and ohci drivers;
  719. * The usbhs core driver should be initialized much before
  720. * the omap ehci and ohci probe functions are called.
  721. * This usbhs core driver should be initialized after
  722. * usb tll driver
  723. */
  724. fs_initcall_sync(omap_usbhs_drvinit);
  725. static void omap_usbhs_drvexit(void)
  726. {
  727. platform_driver_unregister(&usbhs_omap_driver);
  728. }
  729. module_exit(omap_usbhs_drvexit);