usb.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/usb.h>
  8. #include "mt7601u.h"
  9. #include "usb.h"
  10. #include "trace.h"
  11. static const struct usb_device_id mt7601u_device_table[] = {
  12. { USB_DEVICE(0x0b05, 0x17d3) },
  13. { USB_DEVICE(0x0e8d, 0x760a) },
  14. { USB_DEVICE(0x0e8d, 0x760b) },
  15. { USB_DEVICE(0x13d3, 0x3431) },
  16. { USB_DEVICE(0x13d3, 0x3434) },
  17. { USB_DEVICE(0x148f, 0x7601) },
  18. { USB_DEVICE(0x148f, 0x760a) },
  19. { USB_DEVICE(0x148f, 0x760b) },
  20. { USB_DEVICE(0x148f, 0x760c) },
  21. { USB_DEVICE(0x148f, 0x760d) },
  22. { USB_DEVICE(0x2001, 0x3d04) },
  23. { USB_DEVICE(0x2717, 0x4106) },
  24. { USB_DEVICE(0x2955, 0x0001) },
  25. { USB_DEVICE(0x2955, 0x1001) },
  26. { USB_DEVICE(0x2955, 0x1003) },
  27. { USB_DEVICE(0x2a5f, 0x1000) },
  28. { USB_DEVICE(0x7392, 0x7710) },
  29. { 0, }
  30. };
  31. bool mt7601u_usb_alloc_buf(struct mt7601u_dev *dev, size_t len,
  32. struct mt7601u_dma_buf *buf)
  33. {
  34. struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
  35. buf->len = len;
  36. buf->urb = usb_alloc_urb(0, GFP_KERNEL);
  37. buf->buf = usb_alloc_coherent(usb_dev, buf->len, GFP_KERNEL, &buf->dma);
  38. return !buf->urb || !buf->buf;
  39. }
  40. void mt7601u_usb_free_buf(struct mt7601u_dev *dev, struct mt7601u_dma_buf *buf)
  41. {
  42. struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
  43. usb_free_coherent(usb_dev, buf->len, buf->buf, buf->dma);
  44. usb_free_urb(buf->urb);
  45. }
  46. int mt7601u_usb_submit_buf(struct mt7601u_dev *dev, int dir, int ep_idx,
  47. struct mt7601u_dma_buf *buf, gfp_t gfp,
  48. usb_complete_t complete_fn, void *context)
  49. {
  50. struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
  51. unsigned pipe;
  52. int ret;
  53. if (dir == USB_DIR_IN)
  54. pipe = usb_rcvbulkpipe(usb_dev, dev->in_eps[ep_idx]);
  55. else
  56. pipe = usb_sndbulkpipe(usb_dev, dev->out_eps[ep_idx]);
  57. usb_fill_bulk_urb(buf->urb, usb_dev, pipe, buf->buf, buf->len,
  58. complete_fn, context);
  59. buf->urb->transfer_dma = buf->dma;
  60. buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
  61. trace_mt_submit_urb(dev, buf->urb);
  62. ret = usb_submit_urb(buf->urb, gfp);
  63. if (ret)
  64. dev_err(dev->dev, "Error: submit URB dir:%d ep:%d failed:%d\n",
  65. dir, ep_idx, ret);
  66. return ret;
  67. }
  68. void mt7601u_complete_urb(struct urb *urb)
  69. {
  70. struct completion *cmpl = urb->context;
  71. complete(cmpl);
  72. }
  73. int mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
  74. const u8 direction, const u16 val, const u16 offset,
  75. void *buf, const size_t buflen)
  76. {
  77. int i, ret;
  78. struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
  79. const u8 req_type = direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
  80. const unsigned int pipe = (direction == USB_DIR_IN) ?
  81. usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
  82. for (i = 0; i < MT_VEND_REQ_MAX_RETRY; i++) {
  83. ret = usb_control_msg(usb_dev, pipe, req, req_type,
  84. val, offset, buf, buflen,
  85. MT_VEND_REQ_TOUT_MS);
  86. trace_mt_vend_req(dev, pipe, req, req_type, val, offset,
  87. buf, buflen, ret);
  88. if (ret == -ENODEV)
  89. set_bit(MT7601U_STATE_REMOVED, &dev->state);
  90. if (ret >= 0 || ret == -ENODEV)
  91. return ret;
  92. msleep(5);
  93. }
  94. dev_err(dev->dev, "Vendor request req:%02x off:%04x failed:%d\n",
  95. req, offset, ret);
  96. return ret;
  97. }
  98. void mt7601u_vendor_reset(struct mt7601u_dev *dev)
  99. {
  100. mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT,
  101. MT_VEND_DEV_MODE_RESET, 0, NULL, 0);
  102. }
  103. /* should be called with vendor_req_mutex held */
  104. static u32 __mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
  105. {
  106. int ret;
  107. u32 val = ~0;
  108. WARN_ONCE(offset > USHRT_MAX, "read high off:%08x", offset);
  109. ret = mt7601u_vendor_request(dev, MT_VEND_MULTI_READ, USB_DIR_IN,
  110. 0, offset, dev->vend_buf, MT_VEND_BUF);
  111. if (ret == MT_VEND_BUF)
  112. val = get_unaligned_le32(dev->vend_buf);
  113. else if (ret > 0)
  114. dev_err(dev->dev, "Error: wrong size read:%d off:%08x\n",
  115. ret, offset);
  116. trace_reg_read(dev, offset, val);
  117. return val;
  118. }
  119. u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
  120. {
  121. u32 ret;
  122. mutex_lock(&dev->vendor_req_mutex);
  123. ret = __mt7601u_rr(dev, offset);
  124. mutex_unlock(&dev->vendor_req_mutex);
  125. return ret;
  126. }
  127. /* should be called with vendor_req_mutex held */
  128. static int __mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
  129. const u16 offset, const u32 val)
  130. {
  131. int ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
  132. val & 0xffff, offset, NULL, 0);
  133. if (!ret)
  134. ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
  135. val >> 16, offset + 2, NULL, 0);
  136. trace_reg_write(dev, offset, val);
  137. return ret;
  138. }
  139. int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
  140. const u16 offset, const u32 val)
  141. {
  142. int ret;
  143. mutex_lock(&dev->vendor_req_mutex);
  144. ret = __mt7601u_vendor_single_wr(dev, req, offset, val);
  145. mutex_unlock(&dev->vendor_req_mutex);
  146. return ret;
  147. }
  148. void mt7601u_wr(struct mt7601u_dev *dev, u32 offset, u32 val)
  149. {
  150. WARN_ONCE(offset > USHRT_MAX, "write high off:%08x", offset);
  151. mt7601u_vendor_single_wr(dev, MT_VEND_WRITE, offset, val);
  152. }
  153. u32 mt7601u_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
  154. {
  155. mutex_lock(&dev->vendor_req_mutex);
  156. val |= __mt7601u_rr(dev, offset) & ~mask;
  157. __mt7601u_vendor_single_wr(dev, MT_VEND_WRITE, offset, val);
  158. mutex_unlock(&dev->vendor_req_mutex);
  159. return val;
  160. }
  161. u32 mt7601u_rmc(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
  162. {
  163. u32 reg;
  164. mutex_lock(&dev->vendor_req_mutex);
  165. reg = __mt7601u_rr(dev, offset);
  166. val |= reg & ~mask;
  167. if (reg != val)
  168. __mt7601u_vendor_single_wr(dev, MT_VEND_WRITE,
  169. offset, val);
  170. mutex_unlock(&dev->vendor_req_mutex);
  171. return val;
  172. }
  173. void mt7601u_wr_copy(struct mt7601u_dev *dev, u32 offset,
  174. const void *data, int len)
  175. {
  176. WARN_ONCE(offset & 3, "unaligned write copy off:%08x", offset);
  177. WARN_ONCE(len & 3, "short write copy off:%08x", offset);
  178. mt7601u_burst_write_regs(dev, offset, data, len / 4);
  179. }
  180. void mt7601u_addr_wr(struct mt7601u_dev *dev, const u32 offset, const u8 *addr)
  181. {
  182. mt7601u_wr(dev, offset, get_unaligned_le32(addr));
  183. mt7601u_wr(dev, offset + 4, addr[4] | addr[5] << 8);
  184. }
  185. static int mt7601u_assign_pipes(struct usb_interface *usb_intf,
  186. struct mt7601u_dev *dev)
  187. {
  188. struct usb_endpoint_descriptor *ep_desc;
  189. struct usb_host_interface *intf_desc = usb_intf->cur_altsetting;
  190. unsigned i, ep_i = 0, ep_o = 0;
  191. BUILD_BUG_ON(sizeof(dev->in_eps) < __MT_EP_IN_MAX);
  192. BUILD_BUG_ON(sizeof(dev->out_eps) < __MT_EP_OUT_MAX);
  193. for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
  194. ep_desc = &intf_desc->endpoint[i].desc;
  195. if (usb_endpoint_is_bulk_in(ep_desc) &&
  196. ep_i++ < __MT_EP_IN_MAX) {
  197. dev->in_eps[ep_i - 1] = usb_endpoint_num(ep_desc);
  198. dev->in_max_packet = usb_endpoint_maxp(ep_desc);
  199. /* Note: this is ignored by usb sub-system but vendor
  200. * code does it. We can drop this at some point.
  201. */
  202. dev->in_eps[ep_i - 1] |= USB_DIR_IN;
  203. } else if (usb_endpoint_is_bulk_out(ep_desc) &&
  204. ep_o++ < __MT_EP_OUT_MAX) {
  205. dev->out_eps[ep_o - 1] = usb_endpoint_num(ep_desc);
  206. dev->out_max_packet = usb_endpoint_maxp(ep_desc);
  207. }
  208. }
  209. if (ep_i != __MT_EP_IN_MAX || ep_o != __MT_EP_OUT_MAX) {
  210. dev_err(dev->dev, "Error: wrong pipe number in:%d out:%d\n",
  211. ep_i, ep_o);
  212. return -EINVAL;
  213. }
  214. return 0;
  215. }
  216. static int mt7601u_probe(struct usb_interface *usb_intf,
  217. const struct usb_device_id *id)
  218. {
  219. struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
  220. struct mt7601u_dev *dev;
  221. u32 asic_rev, mac_rev;
  222. int ret;
  223. dev = mt7601u_alloc_device(&usb_intf->dev);
  224. if (!dev)
  225. return -ENOMEM;
  226. usb_dev = usb_get_dev(usb_dev);
  227. usb_reset_device(usb_dev);
  228. usb_set_intfdata(usb_intf, dev);
  229. dev->vend_buf = devm_kmalloc(dev->dev, MT_VEND_BUF, GFP_KERNEL);
  230. if (!dev->vend_buf) {
  231. ret = -ENOMEM;
  232. goto err;
  233. }
  234. ret = mt7601u_assign_pipes(usb_intf, dev);
  235. if (ret)
  236. goto err;
  237. ret = mt7601u_wait_asic_ready(dev);
  238. if (ret)
  239. goto err;
  240. asic_rev = mt7601u_rr(dev, MT_ASIC_VERSION);
  241. mac_rev = mt7601u_rr(dev, MT_MAC_CSR0);
  242. dev_info(dev->dev, "ASIC revision: %08x MAC revision: %08x\n",
  243. asic_rev, mac_rev);
  244. if ((asic_rev >> 16) != 0x7601) {
  245. ret = -ENODEV;
  246. goto err;
  247. }
  248. /* Note: vendor driver skips this check for MT7601U */
  249. if (!(mt7601u_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
  250. dev_warn(dev->dev, "Warning: eFUSE not present\n");
  251. ret = mt7601u_init_hardware(dev);
  252. if (ret)
  253. goto err;
  254. ret = mt7601u_register_device(dev);
  255. if (ret)
  256. goto err_hw;
  257. set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
  258. return 0;
  259. err_hw:
  260. mt7601u_cleanup(dev);
  261. err:
  262. usb_set_intfdata(usb_intf, NULL);
  263. usb_put_dev(interface_to_usbdev(usb_intf));
  264. destroy_workqueue(dev->stat_wq);
  265. ieee80211_free_hw(dev->hw);
  266. return ret;
  267. }
  268. static void mt7601u_disconnect(struct usb_interface *usb_intf)
  269. {
  270. struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
  271. ieee80211_unregister_hw(dev->hw);
  272. mt7601u_cleanup(dev);
  273. usb_set_intfdata(usb_intf, NULL);
  274. usb_put_dev(interface_to_usbdev(usb_intf));
  275. destroy_workqueue(dev->stat_wq);
  276. ieee80211_free_hw(dev->hw);
  277. }
  278. static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state)
  279. {
  280. struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
  281. mt7601u_cleanup(dev);
  282. return 0;
  283. }
  284. static int mt7601u_resume(struct usb_interface *usb_intf)
  285. {
  286. struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
  287. int ret;
  288. ret = mt7601u_init_hardware(dev);
  289. if (ret)
  290. return ret;
  291. set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
  292. return 0;
  293. }
  294. MODULE_DEVICE_TABLE(usb, mt7601u_device_table);
  295. MODULE_FIRMWARE(MT7601U_FIRMWARE);
  296. MODULE_DESCRIPTION("MediaTek MT7601U USB Wireless LAN driver");
  297. MODULE_LICENSE("GPL");
  298. static struct usb_driver mt7601u_driver = {
  299. .name = KBUILD_MODNAME,
  300. .id_table = mt7601u_device_table,
  301. .probe = mt7601u_probe,
  302. .disconnect = mt7601u_disconnect,
  303. .suspend = mt7601u_suspend,
  304. .resume = mt7601u_resume,
  305. .reset_resume = mt7601u_resume,
  306. .soft_unbind = 1,
  307. .disable_hub_initiated_lpm = 1,
  308. };
  309. module_usb_driver(mt7601u_driver);