root/drivers/net/wireless/mediatek/mt7601u/usb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mt7601u_usb_alloc_buf
  2. mt7601u_usb_free_buf
  3. mt7601u_usb_submit_buf
  4. mt7601u_complete_urb
  5. mt7601u_vendor_request
  6. mt7601u_vendor_reset
  7. __mt7601u_rr
  8. mt7601u_rr
  9. __mt7601u_vendor_single_wr
  10. mt7601u_vendor_single_wr
  11. mt7601u_wr
  12. mt7601u_rmw
  13. mt7601u_rmc
  14. mt7601u_wr_copy
  15. mt7601u_addr_wr
  16. mt7601u_assign_pipes
  17. mt7601u_probe
  18. mt7601u_disconnect
  19. mt7601u_suspend
  20. mt7601u_resume

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

/* [<][>][^][v][top][bottom][index][help] */