phy-tahvo.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. * Tahvo USB transceiver driver
  3. *
  4. * Copyright (C) 2005-2006 Nokia Corporation
  5. *
  6. * Parts copied from isp1301_omap.c.
  7. * Copyright (C) 2004 Texas Instruments
  8. * Copyright (C) 2004 David Brownell
  9. *
  10. * Original driver written by Juha Yrjölä, Tony Lindgren and Timo Teräs.
  11. * Modified for Retu/Tahvo MFD by Aaro Koskinen.
  12. *
  13. * This file is subject to the terms and conditions of the GNU General
  14. * Public License. See the file "COPYING" in the main directory of this
  15. * archive for more details.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. */
  22. #include <linux/io.h>
  23. #include <linux/clk.h>
  24. #include <linux/usb.h>
  25. #include <linux/extcon.h>
  26. #include <linux/kernel.h>
  27. #include <linux/module.h>
  28. #include <linux/usb/otg.h>
  29. #include <linux/mfd/retu.h>
  30. #include <linux/usb/gadget.h>
  31. #include <linux/platform_device.h>
  32. #define DRIVER_NAME "tahvo-usb"
  33. #define TAHVO_REG_IDSR 0x02
  34. #define TAHVO_REG_USBR 0x06
  35. #define USBR_SLAVE_CONTROL (1 << 8)
  36. #define USBR_VPPVIO_SW (1 << 7)
  37. #define USBR_SPEED (1 << 6)
  38. #define USBR_REGOUT (1 << 5)
  39. #define USBR_MASTER_SW2 (1 << 4)
  40. #define USBR_MASTER_SW1 (1 << 3)
  41. #define USBR_SLAVE_SW (1 << 2)
  42. #define USBR_NSUSPEND (1 << 1)
  43. #define USBR_SEMODE (1 << 0)
  44. #define TAHVO_MODE_HOST 0
  45. #define TAHVO_MODE_PERIPHERAL 1
  46. struct tahvo_usb {
  47. struct platform_device *pt_dev;
  48. struct usb_phy phy;
  49. int vbus_state;
  50. struct mutex serialize;
  51. struct clk *ick;
  52. int irq;
  53. int tahvo_mode;
  54. struct extcon_dev *extcon;
  55. };
  56. static const unsigned int tahvo_cable[] = {
  57. EXTCON_USB,
  58. EXTCON_USB_HOST,
  59. EXTCON_NONE,
  60. };
  61. static ssize_t vbus_state_show(struct device *device,
  62. struct device_attribute *attr, char *buf)
  63. {
  64. struct tahvo_usb *tu = dev_get_drvdata(device);
  65. return sprintf(buf, "%s\n", tu->vbus_state ? "on" : "off");
  66. }
  67. static DEVICE_ATTR(vbus, 0444, vbus_state_show, NULL);
  68. static void check_vbus_state(struct tahvo_usb *tu)
  69. {
  70. struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
  71. int reg, prev_state;
  72. reg = retu_read(rdev, TAHVO_REG_IDSR);
  73. if (reg & TAHVO_STAT_VBUS) {
  74. switch (tu->phy.otg->state) {
  75. case OTG_STATE_B_IDLE:
  76. /* Enable the gadget driver */
  77. if (tu->phy.otg->gadget)
  78. usb_gadget_vbus_connect(tu->phy.otg->gadget);
  79. tu->phy.otg->state = OTG_STATE_B_PERIPHERAL;
  80. usb_phy_set_event(&tu->phy, USB_EVENT_ENUMERATED);
  81. break;
  82. case OTG_STATE_A_IDLE:
  83. /*
  84. * Session is now valid assuming the USB hub is driving
  85. * Vbus.
  86. */
  87. tu->phy.otg->state = OTG_STATE_A_HOST;
  88. break;
  89. default:
  90. break;
  91. }
  92. dev_info(&tu->pt_dev->dev, "USB cable connected\n");
  93. } else {
  94. switch (tu->phy.otg->state) {
  95. case OTG_STATE_B_PERIPHERAL:
  96. if (tu->phy.otg->gadget)
  97. usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
  98. tu->phy.otg->state = OTG_STATE_B_IDLE;
  99. usb_phy_set_event(&tu->phy, USB_EVENT_NONE);
  100. break;
  101. case OTG_STATE_A_HOST:
  102. tu->phy.otg->state = OTG_STATE_A_IDLE;
  103. break;
  104. default:
  105. break;
  106. }
  107. dev_info(&tu->pt_dev->dev, "USB cable disconnected\n");
  108. }
  109. prev_state = tu->vbus_state;
  110. tu->vbus_state = reg & TAHVO_STAT_VBUS;
  111. if (prev_state != tu->vbus_state) {
  112. extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state);
  113. sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state");
  114. }
  115. }
  116. static void tahvo_usb_become_host(struct tahvo_usb *tu)
  117. {
  118. struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
  119. extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, true);
  120. /* Power up the transceiver in USB host mode */
  121. retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND |
  122. USBR_MASTER_SW2 | USBR_MASTER_SW1);
  123. tu->phy.otg->state = OTG_STATE_A_IDLE;
  124. check_vbus_state(tu);
  125. }
  126. static void tahvo_usb_stop_host(struct tahvo_usb *tu)
  127. {
  128. tu->phy.otg->state = OTG_STATE_A_IDLE;
  129. }
  130. static void tahvo_usb_become_peripheral(struct tahvo_usb *tu)
  131. {
  132. struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
  133. extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, false);
  134. /* Power up transceiver and set it in USB peripheral mode */
  135. retu_write(rdev, TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT |
  136. USBR_NSUSPEND | USBR_SLAVE_SW);
  137. tu->phy.otg->state = OTG_STATE_B_IDLE;
  138. check_vbus_state(tu);
  139. }
  140. static void tahvo_usb_stop_peripheral(struct tahvo_usb *tu)
  141. {
  142. if (tu->phy.otg->gadget)
  143. usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
  144. tu->phy.otg->state = OTG_STATE_B_IDLE;
  145. }
  146. static void tahvo_usb_power_off(struct tahvo_usb *tu)
  147. {
  148. struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
  149. /* Disable gadget controller if any */
  150. if (tu->phy.otg->gadget)
  151. usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
  152. /* Power off transceiver */
  153. retu_write(rdev, TAHVO_REG_USBR, 0);
  154. tu->phy.otg->state = OTG_STATE_UNDEFINED;
  155. }
  156. static int tahvo_usb_set_suspend(struct usb_phy *dev, int suspend)
  157. {
  158. struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, phy);
  159. struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
  160. u16 w;
  161. dev_dbg(&tu->pt_dev->dev, "%s\n", __func__);
  162. w = retu_read(rdev, TAHVO_REG_USBR);
  163. if (suspend)
  164. w &= ~USBR_NSUSPEND;
  165. else
  166. w |= USBR_NSUSPEND;
  167. retu_write(rdev, TAHVO_REG_USBR, w);
  168. return 0;
  169. }
  170. static int tahvo_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
  171. {
  172. struct tahvo_usb *tu = container_of(otg->usb_phy, struct tahvo_usb,
  173. phy);
  174. dev_dbg(&tu->pt_dev->dev, "%s %p\n", __func__, host);
  175. mutex_lock(&tu->serialize);
  176. if (host == NULL) {
  177. if (tu->tahvo_mode == TAHVO_MODE_HOST)
  178. tahvo_usb_power_off(tu);
  179. otg->host = NULL;
  180. mutex_unlock(&tu->serialize);
  181. return 0;
  182. }
  183. if (tu->tahvo_mode == TAHVO_MODE_HOST) {
  184. otg->host = NULL;
  185. tahvo_usb_become_host(tu);
  186. }
  187. otg->host = host;
  188. mutex_unlock(&tu->serialize);
  189. return 0;
  190. }
  191. static int tahvo_usb_set_peripheral(struct usb_otg *otg,
  192. struct usb_gadget *gadget)
  193. {
  194. struct tahvo_usb *tu = container_of(otg->usb_phy, struct tahvo_usb,
  195. phy);
  196. dev_dbg(&tu->pt_dev->dev, "%s %p\n", __func__, gadget);
  197. mutex_lock(&tu->serialize);
  198. if (!gadget) {
  199. if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL)
  200. tahvo_usb_power_off(tu);
  201. tu->phy.otg->gadget = NULL;
  202. mutex_unlock(&tu->serialize);
  203. return 0;
  204. }
  205. tu->phy.otg->gadget = gadget;
  206. if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL)
  207. tahvo_usb_become_peripheral(tu);
  208. mutex_unlock(&tu->serialize);
  209. return 0;
  210. }
  211. static irqreturn_t tahvo_usb_vbus_interrupt(int irq, void *_tu)
  212. {
  213. struct tahvo_usb *tu = _tu;
  214. mutex_lock(&tu->serialize);
  215. check_vbus_state(tu);
  216. mutex_unlock(&tu->serialize);
  217. return IRQ_HANDLED;
  218. }
  219. static ssize_t otg_mode_show(struct device *device,
  220. struct device_attribute *attr, char *buf)
  221. {
  222. struct tahvo_usb *tu = dev_get_drvdata(device);
  223. switch (tu->tahvo_mode) {
  224. case TAHVO_MODE_HOST:
  225. return sprintf(buf, "host\n");
  226. case TAHVO_MODE_PERIPHERAL:
  227. return sprintf(buf, "peripheral\n");
  228. }
  229. return -EINVAL;
  230. }
  231. static ssize_t otg_mode_store(struct device *device,
  232. struct device_attribute *attr,
  233. const char *buf, size_t count)
  234. {
  235. struct tahvo_usb *tu = dev_get_drvdata(device);
  236. int r;
  237. mutex_lock(&tu->serialize);
  238. if (count >= 4 && strncmp(buf, "host", 4) == 0) {
  239. if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL)
  240. tahvo_usb_stop_peripheral(tu);
  241. tu->tahvo_mode = TAHVO_MODE_HOST;
  242. if (tu->phy.otg->host) {
  243. dev_info(device, "HOST mode: host controller present\n");
  244. tahvo_usb_become_host(tu);
  245. } else {
  246. dev_info(device, "HOST mode: no host controller, powering off\n");
  247. tahvo_usb_power_off(tu);
  248. }
  249. r = strlen(buf);
  250. } else if (count >= 10 && strncmp(buf, "peripheral", 10) == 0) {
  251. if (tu->tahvo_mode == TAHVO_MODE_HOST)
  252. tahvo_usb_stop_host(tu);
  253. tu->tahvo_mode = TAHVO_MODE_PERIPHERAL;
  254. if (tu->phy.otg->gadget) {
  255. dev_info(device, "PERIPHERAL mode: gadget driver present\n");
  256. tahvo_usb_become_peripheral(tu);
  257. } else {
  258. dev_info(device, "PERIPHERAL mode: no gadget driver, powering off\n");
  259. tahvo_usb_power_off(tu);
  260. }
  261. r = strlen(buf);
  262. } else {
  263. r = -EINVAL;
  264. }
  265. mutex_unlock(&tu->serialize);
  266. return r;
  267. }
  268. static DEVICE_ATTR(otg_mode, 0644, otg_mode_show, otg_mode_store);
  269. static struct attribute *tahvo_attributes[] = {
  270. &dev_attr_vbus.attr,
  271. &dev_attr_otg_mode.attr,
  272. NULL
  273. };
  274. static struct attribute_group tahvo_attr_group = {
  275. .attrs = tahvo_attributes,
  276. };
  277. static int tahvo_usb_probe(struct platform_device *pdev)
  278. {
  279. struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent);
  280. struct tahvo_usb *tu;
  281. int ret;
  282. tu = devm_kzalloc(&pdev->dev, sizeof(*tu), GFP_KERNEL);
  283. if (!tu)
  284. return -ENOMEM;
  285. tu->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*tu->phy.otg),
  286. GFP_KERNEL);
  287. if (!tu->phy.otg)
  288. return -ENOMEM;
  289. tu->pt_dev = pdev;
  290. /* Default mode */
  291. #ifdef CONFIG_TAHVO_USB_HOST_BY_DEFAULT
  292. tu->tahvo_mode = TAHVO_MODE_HOST;
  293. #else
  294. tu->tahvo_mode = TAHVO_MODE_PERIPHERAL;
  295. #endif
  296. mutex_init(&tu->serialize);
  297. tu->ick = devm_clk_get(&pdev->dev, "usb_l4_ick");
  298. if (!IS_ERR(tu->ick))
  299. clk_enable(tu->ick);
  300. /*
  301. * Set initial state, so that we generate kevents only on state changes.
  302. */
  303. tu->vbus_state = retu_read(rdev, TAHVO_REG_IDSR) & TAHVO_STAT_VBUS;
  304. tu->extcon = devm_extcon_dev_allocate(&pdev->dev, tahvo_cable);
  305. if (IS_ERR(tu->extcon)) {
  306. dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
  307. ret = PTR_ERR(tu->extcon);
  308. goto err_disable_clk;
  309. }
  310. ret = devm_extcon_dev_register(&pdev->dev, tu->extcon);
  311. if (ret) {
  312. dev_err(&pdev->dev, "could not register extcon device: %d\n",
  313. ret);
  314. goto err_disable_clk;
  315. }
  316. /* Set the initial cable state. */
  317. extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST,
  318. tu->tahvo_mode == TAHVO_MODE_HOST);
  319. extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state);
  320. /* Create OTG interface */
  321. tahvo_usb_power_off(tu);
  322. tu->phy.dev = &pdev->dev;
  323. tu->phy.otg->state = OTG_STATE_UNDEFINED;
  324. tu->phy.label = DRIVER_NAME;
  325. tu->phy.set_suspend = tahvo_usb_set_suspend;
  326. tu->phy.otg->usb_phy = &tu->phy;
  327. tu->phy.otg->set_host = tahvo_usb_set_host;
  328. tu->phy.otg->set_peripheral = tahvo_usb_set_peripheral;
  329. ret = usb_add_phy(&tu->phy, USB_PHY_TYPE_USB2);
  330. if (ret < 0) {
  331. dev_err(&pdev->dev, "cannot register USB transceiver: %d\n",
  332. ret);
  333. goto err_disable_clk;
  334. }
  335. dev_set_drvdata(&pdev->dev, tu);
  336. tu->irq = platform_get_irq(pdev, 0);
  337. ret = request_threaded_irq(tu->irq, NULL, tahvo_usb_vbus_interrupt,
  338. IRQF_ONESHOT,
  339. "tahvo-vbus", tu);
  340. if (ret) {
  341. dev_err(&pdev->dev, "could not register tahvo-vbus irq: %d\n",
  342. ret);
  343. goto err_remove_phy;
  344. }
  345. /* Attributes */
  346. ret = sysfs_create_group(&pdev->dev.kobj, &tahvo_attr_group);
  347. if (ret) {
  348. dev_err(&pdev->dev, "cannot create sysfs group: %d\n", ret);
  349. goto err_free_irq;
  350. }
  351. return 0;
  352. err_free_irq:
  353. free_irq(tu->irq, tu);
  354. err_remove_phy:
  355. usb_remove_phy(&tu->phy);
  356. err_disable_clk:
  357. if (!IS_ERR(tu->ick))
  358. clk_disable(tu->ick);
  359. return ret;
  360. }
  361. static int tahvo_usb_remove(struct platform_device *pdev)
  362. {
  363. struct tahvo_usb *tu = platform_get_drvdata(pdev);
  364. sysfs_remove_group(&pdev->dev.kobj, &tahvo_attr_group);
  365. free_irq(tu->irq, tu);
  366. usb_remove_phy(&tu->phy);
  367. if (!IS_ERR(tu->ick))
  368. clk_disable(tu->ick);
  369. return 0;
  370. }
  371. static struct platform_driver tahvo_usb_driver = {
  372. .probe = tahvo_usb_probe,
  373. .remove = tahvo_usb_remove,
  374. .driver = {
  375. .name = "tahvo-usb",
  376. },
  377. };
  378. module_platform_driver(tahvo_usb_driver);
  379. MODULE_DESCRIPTION("Tahvo USB transceiver driver");
  380. MODULE_LICENSE("GPL");
  381. MODULE_AUTHOR("Juha Yrjölä, Tony Lindgren, and Timo Teräs");
  382. MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");