hub.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget
  4. *
  5. * hub.c - virtual hub handling
  6. *
  7. * Copyright 2017 IBM Corporation
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/delay.h>
  18. #include <linux/ioport.h>
  19. #include <linux/slab.h>
  20. #include <linux/errno.h>
  21. #include <linux/list.h>
  22. #include <linux/interrupt.h>
  23. #include <linux/proc_fs.h>
  24. #include <linux/prefetch.h>
  25. #include <linux/clk.h>
  26. #include <linux/usb/gadget.h>
  27. #include <linux/of.h>
  28. #include <linux/of_gpio.h>
  29. #include <linux/regmap.h>
  30. #include <linux/dma-mapping.h>
  31. #include <linux/bcd.h>
  32. #include <linux/version.h>
  33. #include <linux/usb.h>
  34. #include <linux/usb/hcd.h>
  35. #include "vhub.h"
  36. /* usb 2.0 hub device descriptor
  37. *
  38. * A few things we may want to improve here:
  39. *
  40. * - We may need to indicate TT support
  41. * - We may need a device qualifier descriptor
  42. * as devices can pretend to be usb1 or 2
  43. * - Make vid/did overridable
  44. * - make it look like usb1 if usb1 mode forced
  45. */
  46. #define KERNEL_REL bin2bcd(((LINUX_VERSION_CODE >> 16) & 0x0ff))
  47. #define KERNEL_VER bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff))
  48. enum {
  49. AST_VHUB_STR_MANUF = 3,
  50. AST_VHUB_STR_PRODUCT = 2,
  51. AST_VHUB_STR_SERIAL = 1,
  52. };
  53. static const struct usb_device_descriptor ast_vhub_dev_desc = {
  54. .bLength = USB_DT_DEVICE_SIZE,
  55. .bDescriptorType = USB_DT_DEVICE,
  56. .bcdUSB = cpu_to_le16(0x0200),
  57. .bDeviceClass = USB_CLASS_HUB,
  58. .bDeviceSubClass = 0,
  59. .bDeviceProtocol = 1,
  60. .bMaxPacketSize0 = 64,
  61. .idVendor = cpu_to_le16(0x1d6b),
  62. .idProduct = cpu_to_le16(0x0107),
  63. .bcdDevice = cpu_to_le16(0x0100),
  64. .iManufacturer = AST_VHUB_STR_MANUF,
  65. .iProduct = AST_VHUB_STR_PRODUCT,
  66. .iSerialNumber = AST_VHUB_STR_SERIAL,
  67. .bNumConfigurations = 1,
  68. };
  69. /* Patches to the above when forcing USB1 mode */
  70. static void ast_vhub_patch_dev_desc_usb1(struct usb_device_descriptor *desc)
  71. {
  72. desc->bcdUSB = cpu_to_le16(0x0100);
  73. desc->bDeviceProtocol = 0;
  74. }
  75. /*
  76. * Configuration descriptor: same comments as above
  77. * regarding handling USB1 mode.
  78. */
  79. /*
  80. * We don't use sizeof() as Linux definition of
  81. * struct usb_endpoint_descriptor contains 2
  82. * extra bytes
  83. */
  84. #define AST_VHUB_CONF_DESC_SIZE (USB_DT_CONFIG_SIZE + \
  85. USB_DT_INTERFACE_SIZE + \
  86. USB_DT_ENDPOINT_SIZE)
  87. static const struct ast_vhub_full_cdesc {
  88. struct usb_config_descriptor cfg;
  89. struct usb_interface_descriptor intf;
  90. struct usb_endpoint_descriptor ep;
  91. } __attribute__ ((packed)) ast_vhub_conf_desc = {
  92. .cfg = {
  93. .bLength = USB_DT_CONFIG_SIZE,
  94. .bDescriptorType = USB_DT_CONFIG,
  95. .wTotalLength = cpu_to_le16(AST_VHUB_CONF_DESC_SIZE),
  96. .bNumInterfaces = 1,
  97. .bConfigurationValue = 1,
  98. .iConfiguration = 0,
  99. .bmAttributes = USB_CONFIG_ATT_ONE |
  100. USB_CONFIG_ATT_SELFPOWER |
  101. USB_CONFIG_ATT_WAKEUP,
  102. .bMaxPower = 0,
  103. },
  104. .intf = {
  105. .bLength = USB_DT_INTERFACE_SIZE,
  106. .bDescriptorType = USB_DT_INTERFACE,
  107. .bInterfaceNumber = 0,
  108. .bAlternateSetting = 0,
  109. .bNumEndpoints = 1,
  110. .bInterfaceClass = USB_CLASS_HUB,
  111. .bInterfaceSubClass = 0,
  112. .bInterfaceProtocol = 0,
  113. .iInterface = 0,
  114. },
  115. .ep = {
  116. .bLength = USB_DT_ENDPOINT_SIZE,
  117. .bDescriptorType = USB_DT_ENDPOINT,
  118. .bEndpointAddress = 0x81,
  119. .bmAttributes = USB_ENDPOINT_XFER_INT,
  120. .wMaxPacketSize = cpu_to_le16(1),
  121. .bInterval = 0x0c,
  122. },
  123. };
  124. #define AST_VHUB_HUB_DESC_SIZE (USB_DT_HUB_NONVAR_SIZE + 2)
  125. static const struct usb_hub_descriptor ast_vhub_hub_desc = {
  126. .bDescLength = AST_VHUB_HUB_DESC_SIZE,
  127. .bDescriptorType = USB_DT_HUB,
  128. .bNbrPorts = AST_VHUB_NUM_PORTS,
  129. .wHubCharacteristics = cpu_to_le16(HUB_CHAR_NO_LPSM),
  130. .bPwrOn2PwrGood = 10,
  131. .bHubContrCurrent = 0,
  132. .u.hs.DeviceRemovable[0] = 0,
  133. .u.hs.DeviceRemovable[1] = 0xff,
  134. };
  135. /*
  136. * These strings converted to UTF-16 must be smaller than
  137. * our EP0 buffer.
  138. */
  139. static const struct usb_string ast_vhub_str_array[] = {
  140. {
  141. .id = AST_VHUB_STR_SERIAL,
  142. .s = "00000000"
  143. },
  144. {
  145. .id = AST_VHUB_STR_PRODUCT,
  146. .s = "USB Virtual Hub"
  147. },
  148. {
  149. .id = AST_VHUB_STR_MANUF,
  150. .s = "Aspeed"
  151. },
  152. { }
  153. };
  154. static const struct usb_gadget_strings ast_vhub_strings = {
  155. .language = 0x0409,
  156. .strings = (struct usb_string *)ast_vhub_str_array
  157. };
  158. static int ast_vhub_hub_dev_status(struct ast_vhub_ep *ep,
  159. u16 wIndex, u16 wValue)
  160. {
  161. u8 st0;
  162. EPDBG(ep, "GET_STATUS(dev)\n");
  163. /*
  164. * Mark it as self-powered, I doubt the BMC is powered off
  165. * the USB bus ...
  166. */
  167. st0 = 1 << USB_DEVICE_SELF_POWERED;
  168. /*
  169. * Need to double check how remote wakeup actually works
  170. * on that chip and what triggers it.
  171. */
  172. if (ep->vhub->wakeup_en)
  173. st0 |= 1 << USB_DEVICE_REMOTE_WAKEUP;
  174. return ast_vhub_simple_reply(ep, st0, 0);
  175. }
  176. static int ast_vhub_hub_ep_status(struct ast_vhub_ep *ep,
  177. u16 wIndex, u16 wValue)
  178. {
  179. int ep_num;
  180. u8 st0 = 0;
  181. ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
  182. EPDBG(ep, "GET_STATUS(ep%d)\n", ep_num);
  183. /* On the hub we have only EP 0 and 1 */
  184. if (ep_num == 1) {
  185. if (ep->vhub->ep1_stalled)
  186. st0 |= 1 << USB_ENDPOINT_HALT;
  187. } else if (ep_num != 0)
  188. return std_req_stall;
  189. return ast_vhub_simple_reply(ep, st0, 0);
  190. }
  191. static int ast_vhub_hub_dev_feature(struct ast_vhub_ep *ep,
  192. u16 wIndex, u16 wValue,
  193. bool is_set)
  194. {
  195. EPDBG(ep, "%s_FEATURE(dev val=%02x)\n",
  196. is_set ? "SET" : "CLEAR", wValue);
  197. if (wValue != USB_DEVICE_REMOTE_WAKEUP)
  198. return std_req_stall;
  199. ep->vhub->wakeup_en = is_set;
  200. EPDBG(ep, "Hub remote wakeup %s\n",
  201. is_set ? "enabled" : "disabled");
  202. return std_req_complete;
  203. }
  204. static int ast_vhub_hub_ep_feature(struct ast_vhub_ep *ep,
  205. u16 wIndex, u16 wValue,
  206. bool is_set)
  207. {
  208. int ep_num;
  209. u32 reg;
  210. ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
  211. EPDBG(ep, "%s_FEATURE(ep%d val=%02x)\n",
  212. is_set ? "SET" : "CLEAR", ep_num, wValue);
  213. if (ep_num > 1)
  214. return std_req_stall;
  215. if (wValue != USB_ENDPOINT_HALT)
  216. return std_req_stall;
  217. if (ep_num == 0)
  218. return std_req_complete;
  219. EPDBG(ep, "%s stall on EP 1\n",
  220. is_set ? "setting" : "clearing");
  221. ep->vhub->ep1_stalled = is_set;
  222. reg = readl(ep->vhub->regs + AST_VHUB_EP1_CTRL);
  223. if (is_set) {
  224. reg |= VHUB_EP1_CTRL_STALL;
  225. } else {
  226. reg &= ~VHUB_EP1_CTRL_STALL;
  227. reg |= VHUB_EP1_CTRL_RESET_TOGGLE;
  228. }
  229. writel(reg, ep->vhub->regs + AST_VHUB_EP1_CTRL);
  230. return std_req_complete;
  231. }
  232. static int ast_vhub_rep_desc(struct ast_vhub_ep *ep,
  233. u8 desc_type, u16 len)
  234. {
  235. size_t dsize;
  236. EPDBG(ep, "GET_DESCRIPTOR(type:%d)\n", desc_type);
  237. /*
  238. * Copy first to EP buffer and send from there, so
  239. * we can do some in-place patching if needed. We know
  240. * the EP buffer is big enough but ensure that doesn't
  241. * change. We do that now rather than later after we
  242. * have checked sizes etc... to avoid a gcc bug where
  243. * it thinks len is constant and barfs about read
  244. * overflows in memcpy.
  245. */
  246. switch(desc_type) {
  247. case USB_DT_DEVICE:
  248. dsize = USB_DT_DEVICE_SIZE;
  249. memcpy(ep->buf, &ast_vhub_dev_desc, dsize);
  250. BUILD_BUG_ON(dsize > sizeof(ast_vhub_dev_desc));
  251. BUILD_BUG_ON(USB_DT_DEVICE_SIZE >= AST_VHUB_EP0_MAX_PACKET);
  252. break;
  253. case USB_DT_CONFIG:
  254. dsize = AST_VHUB_CONF_DESC_SIZE;
  255. memcpy(ep->buf, &ast_vhub_conf_desc, dsize);
  256. BUILD_BUG_ON(dsize > sizeof(ast_vhub_conf_desc));
  257. BUILD_BUG_ON(AST_VHUB_CONF_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
  258. break;
  259. case USB_DT_HUB:
  260. dsize = AST_VHUB_HUB_DESC_SIZE;
  261. memcpy(ep->buf, &ast_vhub_hub_desc, dsize);
  262. BUILD_BUG_ON(dsize > sizeof(ast_vhub_hub_desc));
  263. BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
  264. break;
  265. default:
  266. return std_req_stall;
  267. }
  268. /* Crop requested length */
  269. if (len > dsize)
  270. len = dsize;
  271. /* Patch it if forcing USB1 */
  272. if (desc_type == USB_DT_DEVICE && ep->vhub->force_usb1)
  273. ast_vhub_patch_dev_desc_usb1(ep->buf);
  274. /* Shoot it from the EP buffer */
  275. return ast_vhub_reply(ep, NULL, len);
  276. }
  277. static int ast_vhub_rep_string(struct ast_vhub_ep *ep,
  278. u8 string_id, u16 lang_id,
  279. u16 len)
  280. {
  281. int rc = usb_gadget_get_string (&ast_vhub_strings, string_id, ep->buf);
  282. /*
  283. * This should never happen unless we put too big strings in
  284. * the array above
  285. */
  286. BUG_ON(rc >= AST_VHUB_EP0_MAX_PACKET);
  287. if (rc < 0)
  288. return std_req_stall;
  289. /* Shoot it from the EP buffer */
  290. return ast_vhub_reply(ep, NULL, min_t(u16, rc, len));
  291. }
  292. enum std_req_rc ast_vhub_std_hub_request(struct ast_vhub_ep *ep,
  293. struct usb_ctrlrequest *crq)
  294. {
  295. struct ast_vhub *vhub = ep->vhub;
  296. u16 wValue, wIndex, wLength;
  297. wValue = le16_to_cpu(crq->wValue);
  298. wIndex = le16_to_cpu(crq->wIndex);
  299. wLength = le16_to_cpu(crq->wLength);
  300. /* First packet, grab speed */
  301. if (vhub->speed == USB_SPEED_UNKNOWN) {
  302. u32 ustat = readl(vhub->regs + AST_VHUB_USBSTS);
  303. if (ustat & VHUB_USBSTS_HISPEED)
  304. vhub->speed = USB_SPEED_HIGH;
  305. else
  306. vhub->speed = USB_SPEED_FULL;
  307. UDCDBG(vhub, "USB status=%08x speed=%s\n", ustat,
  308. vhub->speed == USB_SPEED_HIGH ? "high" : "full");
  309. }
  310. switch ((crq->bRequestType << 8) | crq->bRequest) {
  311. /* SET_ADDRESS */
  312. case DeviceOutRequest | USB_REQ_SET_ADDRESS:
  313. EPDBG(ep, "SET_ADDRESS: Got address %x\n", wValue);
  314. writel(wValue, vhub->regs + AST_VHUB_CONF);
  315. return std_req_complete;
  316. /* GET_STATUS */
  317. case DeviceRequest | USB_REQ_GET_STATUS:
  318. return ast_vhub_hub_dev_status(ep, wIndex, wValue);
  319. case InterfaceRequest | USB_REQ_GET_STATUS:
  320. return ast_vhub_simple_reply(ep, 0, 0);
  321. case EndpointRequest | USB_REQ_GET_STATUS:
  322. return ast_vhub_hub_ep_status(ep, wIndex, wValue);
  323. /* SET/CLEAR_FEATURE */
  324. case DeviceOutRequest | USB_REQ_SET_FEATURE:
  325. return ast_vhub_hub_dev_feature(ep, wIndex, wValue, true);
  326. case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
  327. return ast_vhub_hub_dev_feature(ep, wIndex, wValue, false);
  328. case EndpointOutRequest | USB_REQ_SET_FEATURE:
  329. return ast_vhub_hub_ep_feature(ep, wIndex, wValue, true);
  330. case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
  331. return ast_vhub_hub_ep_feature(ep, wIndex, wValue, false);
  332. /* GET/SET_CONFIGURATION */
  333. case DeviceRequest | USB_REQ_GET_CONFIGURATION:
  334. return ast_vhub_simple_reply(ep, 1);
  335. case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
  336. if (wValue != 1)
  337. return std_req_stall;
  338. return std_req_complete;
  339. /* GET_DESCRIPTOR */
  340. case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
  341. switch (wValue >> 8) {
  342. case USB_DT_DEVICE:
  343. case USB_DT_CONFIG:
  344. return ast_vhub_rep_desc(ep, wValue >> 8,
  345. wLength);
  346. case USB_DT_STRING:
  347. return ast_vhub_rep_string(ep, wValue & 0xff,
  348. wIndex, wLength);
  349. }
  350. return std_req_stall;
  351. /* GET/SET_INTERFACE */
  352. case DeviceRequest | USB_REQ_GET_INTERFACE:
  353. return ast_vhub_simple_reply(ep, 0);
  354. case DeviceOutRequest | USB_REQ_SET_INTERFACE:
  355. if (wValue != 0 || wIndex != 0)
  356. return std_req_stall;
  357. return std_req_complete;
  358. }
  359. return std_req_stall;
  360. }
  361. static void ast_vhub_update_hub_ep1(struct ast_vhub *vhub,
  362. unsigned int port)
  363. {
  364. /* Update HW EP1 response */
  365. u32 reg = readl(vhub->regs + AST_VHUB_EP1_STS_CHG);
  366. u32 pmask = (1 << (port + 1));
  367. if (vhub->ports[port].change)
  368. reg |= pmask;
  369. else
  370. reg &= ~pmask;
  371. writel(reg, vhub->regs + AST_VHUB_EP1_STS_CHG);
  372. }
  373. static void ast_vhub_change_port_stat(struct ast_vhub *vhub,
  374. unsigned int port,
  375. u16 clr_flags,
  376. u16 set_flags,
  377. bool set_c)
  378. {
  379. struct ast_vhub_port *p = &vhub->ports[port];
  380. u16 prev;
  381. /* Update port status */
  382. prev = p->status;
  383. p->status = (prev & ~clr_flags) | set_flags;
  384. DDBG(&p->dev, "port %d status %04x -> %04x (C=%d)\n",
  385. port + 1, prev, p->status, set_c);
  386. /* Update change bits if needed */
  387. if (set_c) {
  388. u16 chg = p->status ^ prev;
  389. /* Only these are relevant for change */
  390. chg &= USB_PORT_STAT_C_CONNECTION |
  391. USB_PORT_STAT_C_ENABLE |
  392. USB_PORT_STAT_C_SUSPEND |
  393. USB_PORT_STAT_C_OVERCURRENT |
  394. USB_PORT_STAT_C_RESET |
  395. USB_PORT_STAT_C_L1;
  396. p->change |= chg;
  397. ast_vhub_update_hub_ep1(vhub, port);
  398. }
  399. }
  400. static void ast_vhub_send_host_wakeup(struct ast_vhub *vhub)
  401. {
  402. u32 reg = readl(vhub->regs + AST_VHUB_CTRL);
  403. UDCDBG(vhub, "Waking up host !\n");
  404. reg |= VHUB_CTRL_MANUAL_REMOTE_WAKEUP;
  405. writel(reg, vhub->regs + AST_VHUB_CTRL);
  406. }
  407. void ast_vhub_device_connect(struct ast_vhub *vhub,
  408. unsigned int port, bool on)
  409. {
  410. if (on)
  411. ast_vhub_change_port_stat(vhub, port, 0,
  412. USB_PORT_STAT_CONNECTION, true);
  413. else
  414. ast_vhub_change_port_stat(vhub, port,
  415. USB_PORT_STAT_CONNECTION |
  416. USB_PORT_STAT_ENABLE,
  417. 0, true);
  418. /*
  419. * If the hub is set to wakup the host on connection events
  420. * then send a wakeup.
  421. */
  422. if (vhub->wakeup_en)
  423. ast_vhub_send_host_wakeup(vhub);
  424. }
  425. static void ast_vhub_wake_work(struct work_struct *work)
  426. {
  427. struct ast_vhub *vhub = container_of(work,
  428. struct ast_vhub,
  429. wake_work);
  430. unsigned long flags;
  431. unsigned int i;
  432. /*
  433. * Wake all sleeping ports. If a port is suspended by
  434. * the host suspend (without explicit state suspend),
  435. * we let the normal host wake path deal with it later.
  436. */
  437. spin_lock_irqsave(&vhub->lock, flags);
  438. for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
  439. struct ast_vhub_port *p = &vhub->ports[i];
  440. if (!(p->status & USB_PORT_STAT_SUSPEND))
  441. continue;
  442. ast_vhub_change_port_stat(vhub, i,
  443. USB_PORT_STAT_SUSPEND,
  444. 0, true);
  445. ast_vhub_dev_resume(&p->dev);
  446. }
  447. ast_vhub_send_host_wakeup(vhub);
  448. spin_unlock_irqrestore(&vhub->lock, flags);
  449. }
  450. void ast_vhub_hub_wake_all(struct ast_vhub *vhub)
  451. {
  452. /*
  453. * A device is trying to wake the world, because this
  454. * can recurse into the device, we break the call chain
  455. * using a work queue
  456. */
  457. schedule_work(&vhub->wake_work);
  458. }
  459. static void ast_vhub_port_reset(struct ast_vhub *vhub, u8 port)
  460. {
  461. struct ast_vhub_port *p = &vhub->ports[port];
  462. u16 set, clr, speed;
  463. /* First mark disabled */
  464. ast_vhub_change_port_stat(vhub, port,
  465. USB_PORT_STAT_ENABLE |
  466. USB_PORT_STAT_SUSPEND,
  467. USB_PORT_STAT_RESET,
  468. false);
  469. if (!p->dev.driver)
  470. return;
  471. /*
  472. * This will either "start" the port or reset the
  473. * device if already started...
  474. */
  475. ast_vhub_dev_reset(&p->dev);
  476. /* Grab the right speed */
  477. speed = p->dev.driver->max_speed;
  478. if (speed == USB_SPEED_UNKNOWN || speed > vhub->speed)
  479. speed = vhub->speed;
  480. switch (speed) {
  481. case USB_SPEED_LOW:
  482. set = USB_PORT_STAT_LOW_SPEED;
  483. clr = USB_PORT_STAT_HIGH_SPEED;
  484. break;
  485. case USB_SPEED_FULL:
  486. set = 0;
  487. clr = USB_PORT_STAT_LOW_SPEED |
  488. USB_PORT_STAT_HIGH_SPEED;
  489. break;
  490. case USB_SPEED_HIGH:
  491. set = USB_PORT_STAT_HIGH_SPEED;
  492. clr = USB_PORT_STAT_LOW_SPEED;
  493. break;
  494. default:
  495. UDCDBG(vhub, "Unsupported speed %d when"
  496. " connecting device\n",
  497. speed);
  498. return;
  499. }
  500. clr |= USB_PORT_STAT_RESET;
  501. set |= USB_PORT_STAT_ENABLE;
  502. /* This should ideally be delayed ... */
  503. ast_vhub_change_port_stat(vhub, port, clr, set, true);
  504. }
  505. static enum std_req_rc ast_vhub_set_port_feature(struct ast_vhub_ep *ep,
  506. u8 port, u16 feat)
  507. {
  508. struct ast_vhub *vhub = ep->vhub;
  509. struct ast_vhub_port *p;
  510. if (port == 0 || port > AST_VHUB_NUM_PORTS)
  511. return std_req_stall;
  512. port--;
  513. p = &vhub->ports[port];
  514. switch(feat) {
  515. case USB_PORT_FEAT_SUSPEND:
  516. if (!(p->status & USB_PORT_STAT_ENABLE))
  517. return std_req_complete;
  518. ast_vhub_change_port_stat(vhub, port,
  519. 0, USB_PORT_STAT_SUSPEND,
  520. false);
  521. ast_vhub_dev_suspend(&p->dev);
  522. return std_req_complete;
  523. case USB_PORT_FEAT_RESET:
  524. EPDBG(ep, "Port reset !\n");
  525. ast_vhub_port_reset(vhub, port);
  526. return std_req_complete;
  527. case USB_PORT_FEAT_POWER:
  528. /*
  529. * On Power-on, we mark the connected flag changed,
  530. * if there's a connected device, some hosts will
  531. * otherwise fail to detect it.
  532. */
  533. if (p->status & USB_PORT_STAT_CONNECTION) {
  534. p->change |= USB_PORT_STAT_C_CONNECTION;
  535. ast_vhub_update_hub_ep1(vhub, port);
  536. }
  537. return std_req_complete;
  538. case USB_PORT_FEAT_TEST:
  539. case USB_PORT_FEAT_INDICATOR:
  540. /* We don't do anything with these */
  541. return std_req_complete;
  542. }
  543. return std_req_stall;
  544. }
  545. static enum std_req_rc ast_vhub_clr_port_feature(struct ast_vhub_ep *ep,
  546. u8 port, u16 feat)
  547. {
  548. struct ast_vhub *vhub = ep->vhub;
  549. struct ast_vhub_port *p;
  550. if (port == 0 || port > AST_VHUB_NUM_PORTS)
  551. return std_req_stall;
  552. port--;
  553. p = &vhub->ports[port];
  554. switch(feat) {
  555. case USB_PORT_FEAT_ENABLE:
  556. ast_vhub_change_port_stat(vhub, port,
  557. USB_PORT_STAT_ENABLE |
  558. USB_PORT_STAT_SUSPEND, 0,
  559. false);
  560. ast_vhub_dev_suspend(&p->dev);
  561. return std_req_complete;
  562. case USB_PORT_FEAT_SUSPEND:
  563. if (!(p->status & USB_PORT_STAT_SUSPEND))
  564. return std_req_complete;
  565. ast_vhub_change_port_stat(vhub, port,
  566. USB_PORT_STAT_SUSPEND, 0,
  567. false);
  568. ast_vhub_dev_resume(&p->dev);
  569. return std_req_complete;
  570. case USB_PORT_FEAT_POWER:
  571. /* We don't do power control */
  572. return std_req_complete;
  573. case USB_PORT_FEAT_INDICATOR:
  574. /* We don't have indicators */
  575. return std_req_complete;
  576. case USB_PORT_FEAT_C_CONNECTION:
  577. case USB_PORT_FEAT_C_ENABLE:
  578. case USB_PORT_FEAT_C_SUSPEND:
  579. case USB_PORT_FEAT_C_OVER_CURRENT:
  580. case USB_PORT_FEAT_C_RESET:
  581. /* Clear state-change feature */
  582. p->change &= ~(1u << (feat - 16));
  583. ast_vhub_update_hub_ep1(vhub, port);
  584. return std_req_complete;
  585. }
  586. return std_req_stall;
  587. }
  588. static enum std_req_rc ast_vhub_get_port_stat(struct ast_vhub_ep *ep,
  589. u8 port)
  590. {
  591. struct ast_vhub *vhub = ep->vhub;
  592. u16 stat, chg;
  593. if (port == 0 || port > AST_VHUB_NUM_PORTS)
  594. return std_req_stall;
  595. port--;
  596. stat = vhub->ports[port].status;
  597. chg = vhub->ports[port].change;
  598. /* We always have power */
  599. stat |= USB_PORT_STAT_POWER;
  600. EPDBG(ep, " port status=%04x change=%04x\n", stat, chg);
  601. return ast_vhub_simple_reply(ep,
  602. stat & 0xff,
  603. stat >> 8,
  604. chg & 0xff,
  605. chg >> 8);
  606. }
  607. enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep,
  608. struct usb_ctrlrequest *crq)
  609. {
  610. u16 wValue, wIndex, wLength;
  611. wValue = le16_to_cpu(crq->wValue);
  612. wIndex = le16_to_cpu(crq->wIndex);
  613. wLength = le16_to_cpu(crq->wLength);
  614. switch ((crq->bRequestType << 8) | crq->bRequest) {
  615. case GetHubStatus:
  616. EPDBG(ep, "GetHubStatus\n");
  617. return ast_vhub_simple_reply(ep, 0, 0, 0, 0);
  618. case GetPortStatus:
  619. EPDBG(ep, "GetPortStatus(%d)\n", wIndex & 0xff);
  620. return ast_vhub_get_port_stat(ep, wIndex & 0xf);
  621. case GetHubDescriptor:
  622. if (wValue != (USB_DT_HUB << 8))
  623. return std_req_stall;
  624. EPDBG(ep, "GetHubDescriptor(%d)\n", wIndex & 0xff);
  625. return ast_vhub_rep_desc(ep, USB_DT_HUB, wLength);
  626. case SetHubFeature:
  627. case ClearHubFeature:
  628. EPDBG(ep, "Get/SetHubFeature(%d)\n", wValue);
  629. /* No feature, just complete the requests */
  630. if (wValue == C_HUB_LOCAL_POWER ||
  631. wValue == C_HUB_OVER_CURRENT)
  632. return std_req_complete;
  633. return std_req_stall;
  634. case SetPortFeature:
  635. EPDBG(ep, "SetPortFeature(%d,%d)\n", wIndex & 0xf, wValue);
  636. return ast_vhub_set_port_feature(ep, wIndex & 0xf, wValue);
  637. case ClearPortFeature:
  638. EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue);
  639. return ast_vhub_clr_port_feature(ep, wIndex & 0xf, wValue);
  640. default:
  641. EPDBG(ep, "Unknown class request\n");
  642. }
  643. return std_req_stall;
  644. }
  645. void ast_vhub_hub_suspend(struct ast_vhub *vhub)
  646. {
  647. unsigned int i;
  648. UDCDBG(vhub, "USB bus suspend\n");
  649. if (vhub->suspended)
  650. return;
  651. vhub->suspended = true;
  652. /*
  653. * Forward to unsuspended ports without changing
  654. * their connection status.
  655. */
  656. for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
  657. struct ast_vhub_port *p = &vhub->ports[i];
  658. if (!(p->status & USB_PORT_STAT_SUSPEND))
  659. ast_vhub_dev_suspend(&p->dev);
  660. }
  661. }
  662. void ast_vhub_hub_resume(struct ast_vhub *vhub)
  663. {
  664. unsigned int i;
  665. UDCDBG(vhub, "USB bus resume\n");
  666. if (!vhub->suspended)
  667. return;
  668. vhub->suspended = false;
  669. /*
  670. * Forward to unsuspended ports without changing
  671. * their connection status.
  672. */
  673. for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
  674. struct ast_vhub_port *p = &vhub->ports[i];
  675. if (!(p->status & USB_PORT_STAT_SUSPEND))
  676. ast_vhub_dev_resume(&p->dev);
  677. }
  678. }
  679. void ast_vhub_hub_reset(struct ast_vhub *vhub)
  680. {
  681. unsigned int i;
  682. UDCDBG(vhub, "USB bus reset\n");
  683. /*
  684. * Is the speed known ? If not we don't care, we aren't
  685. * initialized yet and ports haven't been enabled.
  686. */
  687. if (vhub->speed == USB_SPEED_UNKNOWN)
  688. return;
  689. /* We aren't suspended anymore obviously */
  690. vhub->suspended = false;
  691. /* No speed set */
  692. vhub->speed = USB_SPEED_UNKNOWN;
  693. /* Wakeup not enabled anymore */
  694. vhub->wakeup_en = false;
  695. /*
  696. * Clear all port status, disable gadgets and "suspend"
  697. * them. They will be woken up by a port reset.
  698. */
  699. for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
  700. struct ast_vhub_port *p = &vhub->ports[i];
  701. /* Only keep the connected flag */
  702. p->status &= USB_PORT_STAT_CONNECTION;
  703. p->change = 0;
  704. /* Suspend the gadget if any */
  705. ast_vhub_dev_suspend(&p->dev);
  706. }
  707. /* Cleanup HW */
  708. writel(0, vhub->regs + AST_VHUB_CONF);
  709. writel(0, vhub->regs + AST_VHUB_EP0_CTRL);
  710. writel(VHUB_EP1_CTRL_RESET_TOGGLE |
  711. VHUB_EP1_CTRL_ENABLE,
  712. vhub->regs + AST_VHUB_EP1_CTRL);
  713. writel(0, vhub->regs + AST_VHUB_EP1_STS_CHG);
  714. }
  715. void ast_vhub_init_hub(struct ast_vhub *vhub)
  716. {
  717. vhub->speed = USB_SPEED_UNKNOWN;
  718. INIT_WORK(&vhub->wake_work, ast_vhub_wake_work);
  719. }