omap2430.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2005-2007 by Texas Instruments
  4. * Some code has been taken from tusb6010.c
  5. * Copyrights for that are attributable to:
  6. * Copyright (C) 2006 Nokia Corporation
  7. * Tony Lindgren <tony@atomide.com>
  8. *
  9. * This file is part of the Inventra Controller Driver for Linux.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/sched.h>
  14. #include <linux/init.h>
  15. #include <linux/list.h>
  16. #include <linux/io.h>
  17. #include <linux/of.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/dma-mapping.h>
  20. #include <linux/pm_runtime.h>
  21. #include <linux/err.h>
  22. #include <linux/delay.h>
  23. #include <linux/usb/musb.h>
  24. #include <linux/phy/omap_control_phy.h>
  25. #include <linux/of_platform.h>
  26. #include "musb_core.h"
  27. #include "omap2430.h"
  28. struct omap2430_glue {
  29. struct device *dev;
  30. struct platform_device *musb;
  31. enum musb_vbus_id_status status;
  32. struct work_struct omap_musb_mailbox_work;
  33. struct device *control_otghs;
  34. };
  35. #define glue_to_musb(g) platform_get_drvdata(g->musb)
  36. static struct omap2430_glue *_glue;
  37. static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
  38. {
  39. struct usb_otg *otg = musb->xceiv->otg;
  40. u8 devctl;
  41. unsigned long timeout = jiffies + msecs_to_jiffies(1000);
  42. /* HDRC controls CPEN, but beware current surges during device
  43. * connect. They can trigger transient overcurrent conditions
  44. * that must be ignored.
  45. */
  46. devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
  47. if (is_on) {
  48. if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
  49. int loops = 100;
  50. /* start the session */
  51. devctl |= MUSB_DEVCTL_SESSION;
  52. musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
  53. /*
  54. * Wait for the musb to set as A device to enable the
  55. * VBUS
  56. */
  57. while (musb_readb(musb->mregs, MUSB_DEVCTL) &
  58. MUSB_DEVCTL_BDEVICE) {
  59. mdelay(5);
  60. cpu_relax();
  61. if (time_after(jiffies, timeout)
  62. || loops-- <= 0) {
  63. dev_err(musb->controller,
  64. "configured as A device timeout");
  65. break;
  66. }
  67. }
  68. otg_set_vbus(otg, 1);
  69. } else {
  70. musb->is_active = 1;
  71. musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
  72. devctl |= MUSB_DEVCTL_SESSION;
  73. MUSB_HST_MODE(musb);
  74. }
  75. } else {
  76. musb->is_active = 0;
  77. /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and
  78. * jumping right to B_IDLE...
  79. */
  80. musb->xceiv->otg->state = OTG_STATE_B_IDLE;
  81. devctl &= ~MUSB_DEVCTL_SESSION;
  82. MUSB_DEV_MODE(musb);
  83. }
  84. musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
  85. dev_dbg(musb->controller, "VBUS %s, devctl %02x "
  86. /* otg %3x conf %08x prcm %08x */ "\n",
  87. usb_otg_state_string(musb->xceiv->otg->state),
  88. musb_readb(musb->mregs, MUSB_DEVCTL));
  89. }
  90. static inline void omap2430_low_level_exit(struct musb *musb)
  91. {
  92. u32 l;
  93. /* in any role */
  94. l = musb_readl(musb->mregs, OTG_FORCESTDBY);
  95. l |= ENABLEFORCE; /* enable MSTANDBY */
  96. musb_writel(musb->mregs, OTG_FORCESTDBY, l);
  97. }
  98. static inline void omap2430_low_level_init(struct musb *musb)
  99. {
  100. u32 l;
  101. l = musb_readl(musb->mregs, OTG_FORCESTDBY);
  102. l &= ~ENABLEFORCE; /* disable MSTANDBY */
  103. musb_writel(musb->mregs, OTG_FORCESTDBY, l);
  104. }
  105. static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
  106. {
  107. struct omap2430_glue *glue = _glue;
  108. if (!glue) {
  109. pr_err("%s: musb core is not yet initialized\n", __func__);
  110. return -EPROBE_DEFER;
  111. }
  112. glue->status = status;
  113. if (!glue_to_musb(glue)) {
  114. pr_err("%s: musb core is not yet ready\n", __func__);
  115. return -EPROBE_DEFER;
  116. }
  117. schedule_work(&glue->omap_musb_mailbox_work);
  118. return 0;
  119. }
  120. static void omap_musb_set_mailbox(struct omap2430_glue *glue)
  121. {
  122. struct musb *musb = glue_to_musb(glue);
  123. struct musb_hdrc_platform_data *pdata =
  124. dev_get_platdata(musb->controller);
  125. struct omap_musb_board_data *data = pdata->board_data;
  126. pm_runtime_get_sync(musb->controller);
  127. switch (glue->status) {
  128. case MUSB_ID_GROUND:
  129. dev_dbg(musb->controller, "ID GND\n");
  130. musb->xceiv->otg->state = OTG_STATE_A_IDLE;
  131. musb->xceiv->last_event = USB_EVENT_ID;
  132. if (musb->gadget_driver) {
  133. omap_control_usb_set_mode(glue->control_otghs,
  134. USB_MODE_HOST);
  135. omap2430_musb_set_vbus(musb, 1);
  136. }
  137. break;
  138. case MUSB_VBUS_VALID:
  139. dev_dbg(musb->controller, "VBUS Connect\n");
  140. musb->xceiv->otg->state = OTG_STATE_B_IDLE;
  141. musb->xceiv->last_event = USB_EVENT_VBUS;
  142. omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
  143. break;
  144. case MUSB_ID_FLOAT:
  145. case MUSB_VBUS_OFF:
  146. dev_dbg(musb->controller, "VBUS Disconnect\n");
  147. musb->xceiv->last_event = USB_EVENT_NONE;
  148. if (musb->gadget_driver)
  149. omap2430_musb_set_vbus(musb, 0);
  150. if (data->interface_type == MUSB_INTERFACE_UTMI)
  151. otg_set_vbus(musb->xceiv->otg, 0);
  152. omap_control_usb_set_mode(glue->control_otghs,
  153. USB_MODE_DISCONNECT);
  154. break;
  155. default:
  156. dev_dbg(musb->controller, "ID float\n");
  157. }
  158. pm_runtime_mark_last_busy(musb->controller);
  159. pm_runtime_put_autosuspend(musb->controller);
  160. atomic_notifier_call_chain(&musb->xceiv->notifier,
  161. musb->xceiv->last_event, NULL);
  162. }
  163. static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
  164. {
  165. struct omap2430_glue *glue = container_of(mailbox_work,
  166. struct omap2430_glue, omap_musb_mailbox_work);
  167. omap_musb_set_mailbox(glue);
  168. }
  169. static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
  170. {
  171. unsigned long flags;
  172. irqreturn_t retval = IRQ_NONE;
  173. struct musb *musb = __hci;
  174. spin_lock_irqsave(&musb->lock, flags);
  175. musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
  176. musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
  177. musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
  178. if (musb->int_usb || musb->int_tx || musb->int_rx)
  179. retval = musb_interrupt(musb);
  180. spin_unlock_irqrestore(&musb->lock, flags);
  181. return retval;
  182. }
  183. static int omap2430_musb_init(struct musb *musb)
  184. {
  185. u32 l;
  186. int status = 0;
  187. struct device *dev = musb->controller;
  188. struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
  189. struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
  190. struct omap_musb_board_data *data = plat->board_data;
  191. /* We require some kind of external transceiver, hooked
  192. * up through ULPI. TWL4030-family PMICs include one,
  193. * which needs a driver, drivers aren't always needed.
  194. */
  195. musb->phy = devm_phy_get(dev->parent, "usb2-phy");
  196. /* We can't totally remove musb->xceiv as of now because
  197. * musb core uses xceiv.state and xceiv.otg. Once we have
  198. * a separate state machine to handle otg, these can be moved
  199. * out of xceiv and then we can start using the generic PHY
  200. * framework
  201. */
  202. musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0);
  203. if (IS_ERR(musb->xceiv)) {
  204. status = PTR_ERR(musb->xceiv);
  205. if (status == -ENXIO)
  206. return status;
  207. dev_dbg(dev, "HS USB OTG: no transceiver configured\n");
  208. return -EPROBE_DEFER;
  209. }
  210. if (IS_ERR(musb->phy)) {
  211. dev_err(dev, "HS USB OTG: no PHY configured\n");
  212. return PTR_ERR(musb->phy);
  213. }
  214. musb->isr = omap2430_musb_interrupt;
  215. phy_init(musb->phy);
  216. phy_power_on(musb->phy);
  217. l = musb_readl(musb->mregs, OTG_INTERFSEL);
  218. if (data->interface_type == MUSB_INTERFACE_UTMI) {
  219. /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
  220. l &= ~ULPI_12PIN; /* Disable ULPI */
  221. l |= UTMI_8BIT; /* Enable UTMI */
  222. } else {
  223. l |= ULPI_12PIN;
  224. }
  225. musb_writel(musb->mregs, OTG_INTERFSEL, l);
  226. dev_dbg(dev, "HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
  227. "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n",
  228. musb_readl(musb->mregs, OTG_REVISION),
  229. musb_readl(musb->mregs, OTG_SYSCONFIG),
  230. musb_readl(musb->mregs, OTG_SYSSTATUS),
  231. musb_readl(musb->mregs, OTG_INTERFSEL),
  232. musb_readl(musb->mregs, OTG_SIMENABLE));
  233. if (glue->status != MUSB_UNKNOWN)
  234. omap_musb_set_mailbox(glue);
  235. return 0;
  236. }
  237. static void omap2430_musb_enable(struct musb *musb)
  238. {
  239. u8 devctl;
  240. unsigned long timeout = jiffies + msecs_to_jiffies(1000);
  241. struct device *dev = musb->controller;
  242. struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
  243. struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
  244. struct omap_musb_board_data *data = pdata->board_data;
  245. switch (glue->status) {
  246. case MUSB_ID_GROUND:
  247. omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST);
  248. if (data->interface_type != MUSB_INTERFACE_UTMI)
  249. break;
  250. devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
  251. /* start the session */
  252. devctl |= MUSB_DEVCTL_SESSION;
  253. musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
  254. while (musb_readb(musb->mregs, MUSB_DEVCTL) &
  255. MUSB_DEVCTL_BDEVICE) {
  256. cpu_relax();
  257. if (time_after(jiffies, timeout)) {
  258. dev_err(dev, "configured as A device timeout");
  259. break;
  260. }
  261. }
  262. break;
  263. case MUSB_VBUS_VALID:
  264. omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
  265. break;
  266. default:
  267. break;
  268. }
  269. }
  270. static void omap2430_musb_disable(struct musb *musb)
  271. {
  272. struct device *dev = musb->controller;
  273. struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
  274. if (glue->status != MUSB_UNKNOWN)
  275. omap_control_usb_set_mode(glue->control_otghs,
  276. USB_MODE_DISCONNECT);
  277. }
  278. static int omap2430_musb_exit(struct musb *musb)
  279. {
  280. struct device *dev = musb->controller;
  281. struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
  282. omap2430_low_level_exit(musb);
  283. phy_power_off(musb->phy);
  284. phy_exit(musb->phy);
  285. musb->phy = NULL;
  286. cancel_work_sync(&glue->omap_musb_mailbox_work);
  287. return 0;
  288. }
  289. static const struct musb_platform_ops omap2430_ops = {
  290. .quirks = MUSB_DMA_INVENTRA,
  291. #ifdef CONFIG_USB_INVENTRA_DMA
  292. .dma_init = musbhs_dma_controller_create,
  293. .dma_exit = musbhs_dma_controller_destroy,
  294. #endif
  295. .init = omap2430_musb_init,
  296. .exit = omap2430_musb_exit,
  297. .enable = omap2430_musb_enable,
  298. .disable = omap2430_musb_disable,
  299. .phy_callback = omap2430_musb_mailbox,
  300. };
  301. static u64 omap2430_dmamask = DMA_BIT_MASK(32);
  302. static int omap2430_probe(struct platform_device *pdev)
  303. {
  304. struct resource musb_resources[3];
  305. struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
  306. struct omap_musb_board_data *data;
  307. struct platform_device *musb;
  308. struct omap2430_glue *glue;
  309. struct device_node *np = pdev->dev.of_node;
  310. struct musb_hdrc_config *config;
  311. struct device_node *control_node;
  312. struct platform_device *control_pdev;
  313. int ret = -ENOMEM, val;
  314. if (!np)
  315. return -ENODEV;
  316. glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
  317. if (!glue)
  318. goto err0;
  319. musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
  320. if (!musb) {
  321. dev_err(&pdev->dev, "failed to allocate musb device\n");
  322. goto err0;
  323. }
  324. musb->dev.parent = &pdev->dev;
  325. musb->dev.dma_mask = &omap2430_dmamask;
  326. musb->dev.coherent_dma_mask = omap2430_dmamask;
  327. glue->dev = &pdev->dev;
  328. glue->musb = musb;
  329. glue->status = MUSB_UNKNOWN;
  330. glue->control_otghs = ERR_PTR(-ENODEV);
  331. pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
  332. if (!pdata)
  333. goto err2;
  334. data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
  335. if (!data)
  336. goto err2;
  337. config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
  338. if (!config)
  339. goto err2;
  340. of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
  341. of_property_read_u32(np, "interface-type",
  342. (u32 *)&data->interface_type);
  343. of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
  344. of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
  345. of_property_read_u32(np, "power", (u32 *)&pdata->power);
  346. ret = of_property_read_u32(np, "multipoint", &val);
  347. if (!ret && val)
  348. config->multipoint = true;
  349. pdata->board_data = data;
  350. pdata->config = config;
  351. control_node = of_parse_phandle(np, "ctrl-module", 0);
  352. if (control_node) {
  353. control_pdev = of_find_device_by_node(control_node);
  354. if (!control_pdev) {
  355. dev_err(&pdev->dev, "Failed to get control device\n");
  356. ret = -EINVAL;
  357. goto err2;
  358. }
  359. glue->control_otghs = &control_pdev->dev;
  360. }
  361. pdata->platform_ops = &omap2430_ops;
  362. platform_set_drvdata(pdev, glue);
  363. /*
  364. * REVISIT if we ever have two instances of the wrapper, we will be
  365. * in big trouble
  366. */
  367. _glue = glue;
  368. INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
  369. memset(musb_resources, 0x00, sizeof(*musb_resources) *
  370. ARRAY_SIZE(musb_resources));
  371. musb_resources[0].name = pdev->resource[0].name;
  372. musb_resources[0].start = pdev->resource[0].start;
  373. musb_resources[0].end = pdev->resource[0].end;
  374. musb_resources[0].flags = pdev->resource[0].flags;
  375. musb_resources[1].name = pdev->resource[1].name;
  376. musb_resources[1].start = pdev->resource[1].start;
  377. musb_resources[1].end = pdev->resource[1].end;
  378. musb_resources[1].flags = pdev->resource[1].flags;
  379. musb_resources[2].name = pdev->resource[2].name;
  380. musb_resources[2].start = pdev->resource[2].start;
  381. musb_resources[2].end = pdev->resource[2].end;
  382. musb_resources[2].flags = pdev->resource[2].flags;
  383. ret = platform_device_add_resources(musb, musb_resources,
  384. ARRAY_SIZE(musb_resources));
  385. if (ret) {
  386. dev_err(&pdev->dev, "failed to add resources\n");
  387. goto err2;
  388. }
  389. ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
  390. if (ret) {
  391. dev_err(&pdev->dev, "failed to add platform_data\n");
  392. goto err2;
  393. }
  394. pm_runtime_enable(glue->dev);
  395. ret = platform_device_add(musb);
  396. if (ret) {
  397. dev_err(&pdev->dev, "failed to register musb device\n");
  398. goto err3;
  399. }
  400. return 0;
  401. err3:
  402. pm_runtime_disable(glue->dev);
  403. err2:
  404. platform_device_put(musb);
  405. err0:
  406. return ret;
  407. }
  408. static int omap2430_remove(struct platform_device *pdev)
  409. {
  410. struct omap2430_glue *glue = platform_get_drvdata(pdev);
  411. platform_device_unregister(glue->musb);
  412. pm_runtime_disable(glue->dev);
  413. return 0;
  414. }
  415. #ifdef CONFIG_PM
  416. static int omap2430_runtime_suspend(struct device *dev)
  417. {
  418. struct omap2430_glue *glue = dev_get_drvdata(dev);
  419. struct musb *musb = glue_to_musb(glue);
  420. if (!musb)
  421. return 0;
  422. musb->context.otg_interfsel = musb_readl(musb->mregs,
  423. OTG_INTERFSEL);
  424. omap2430_low_level_exit(musb);
  425. phy_power_off(musb->phy);
  426. phy_exit(musb->phy);
  427. return 0;
  428. }
  429. static int omap2430_runtime_resume(struct device *dev)
  430. {
  431. struct omap2430_glue *glue = dev_get_drvdata(dev);
  432. struct musb *musb = glue_to_musb(glue);
  433. if (!musb)
  434. return 0;
  435. phy_init(musb->phy);
  436. phy_power_on(musb->phy);
  437. omap2430_low_level_init(musb);
  438. musb_writel(musb->mregs, OTG_INTERFSEL,
  439. musb->context.otg_interfsel);
  440. return 0;
  441. }
  442. static const struct dev_pm_ops omap2430_pm_ops = {
  443. .runtime_suspend = omap2430_runtime_suspend,
  444. .runtime_resume = omap2430_runtime_resume,
  445. };
  446. #define DEV_PM_OPS (&omap2430_pm_ops)
  447. #else
  448. #define DEV_PM_OPS NULL
  449. #endif
  450. #ifdef CONFIG_OF
  451. static const struct of_device_id omap2430_id_table[] = {
  452. {
  453. .compatible = "ti,omap4-musb"
  454. },
  455. {
  456. .compatible = "ti,omap3-musb"
  457. },
  458. {},
  459. };
  460. MODULE_DEVICE_TABLE(of, omap2430_id_table);
  461. #endif
  462. static struct platform_driver omap2430_driver = {
  463. .probe = omap2430_probe,
  464. .remove = omap2430_remove,
  465. .driver = {
  466. .name = "musb-omap2430",
  467. .pm = DEV_PM_OPS,
  468. .of_match_table = of_match_ptr(omap2430_id_table),
  469. },
  470. };
  471. module_platform_driver(omap2430_driver);
  472. MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
  473. MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
  474. MODULE_LICENSE("GPL v2");