1338a1281SOctavian Purdila /* 2338a1281SOctavian Purdila * Driver for the Diolan DLN-2 USB adapter 3338a1281SOctavian Purdila * 4338a1281SOctavian Purdila * Copyright (c) 2014 Intel Corporation 5338a1281SOctavian Purdila * 6338a1281SOctavian Purdila * Derived from: 7338a1281SOctavian Purdila * i2c-diolan-u2c.c 8338a1281SOctavian Purdila * Copyright (c) 2010-2011 Ericsson AB 9338a1281SOctavian Purdila * 10338a1281SOctavian Purdila * This program is free software; you can redistribute it and/or 11338a1281SOctavian Purdila * modify it under the terms of the GNU General Public License as 12338a1281SOctavian Purdila * published by the Free Software Foundation, version 2. 13338a1281SOctavian Purdila */ 14338a1281SOctavian Purdila 15338a1281SOctavian Purdila #include <linux/kernel.h> 16338a1281SOctavian Purdila #include <linux/module.h> 17338a1281SOctavian Purdila #include <linux/types.h> 18338a1281SOctavian Purdila #include <linux/slab.h> 19338a1281SOctavian Purdila #include <linux/usb.h> 20338a1281SOctavian Purdila #include <linux/i2c.h> 21338a1281SOctavian Purdila #include <linux/mutex.h> 22338a1281SOctavian Purdila #include <linux/platform_device.h> 23338a1281SOctavian Purdila #include <linux/mfd/core.h> 24338a1281SOctavian Purdila #include <linux/mfd/dln2.h> 25338a1281SOctavian Purdila #include <linux/rculist.h> 26338a1281SOctavian Purdila 27338a1281SOctavian Purdila struct dln2_header { 28338a1281SOctavian Purdila __le16 size; 29338a1281SOctavian Purdila __le16 id; 30338a1281SOctavian Purdila __le16 echo; 31338a1281SOctavian Purdila __le16 handle; 32338a1281SOctavian Purdila }; 33338a1281SOctavian Purdila 34338a1281SOctavian Purdila struct dln2_response { 35338a1281SOctavian Purdila struct dln2_header hdr; 36338a1281SOctavian Purdila __le16 result; 37338a1281SOctavian Purdila }; 38338a1281SOctavian Purdila 39338a1281SOctavian Purdila #define DLN2_GENERIC_MODULE_ID 0x00 40338a1281SOctavian Purdila #define DLN2_GENERIC_CMD(cmd) DLN2_CMD(cmd, DLN2_GENERIC_MODULE_ID) 41338a1281SOctavian Purdila #define CMD_GET_DEVICE_VER DLN2_GENERIC_CMD(0x30) 42338a1281SOctavian Purdila #define CMD_GET_DEVICE_SN DLN2_GENERIC_CMD(0x31) 43338a1281SOctavian Purdila 44338a1281SOctavian Purdila #define DLN2_HW_ID 0x200 45338a1281SOctavian Purdila #define DLN2_USB_TIMEOUT 200 /* in ms */ 46338a1281SOctavian Purdila #define DLN2_MAX_RX_SLOTS 16 47338a1281SOctavian Purdila #define DLN2_MAX_URBS 16 48338a1281SOctavian Purdila #define DLN2_RX_BUF_SIZE 512 49338a1281SOctavian Purdila 50338a1281SOctavian Purdila enum dln2_handle { 51338a1281SOctavian Purdila DLN2_HANDLE_EVENT = 0, /* don't change, hardware defined */ 52338a1281SOctavian Purdila DLN2_HANDLE_CTRL, 53338a1281SOctavian Purdila DLN2_HANDLE_GPIO, 54338a1281SOctavian Purdila DLN2_HANDLE_I2C, 55338a1281SOctavian Purdila DLN2_HANDLES 56338a1281SOctavian Purdila }; 57338a1281SOctavian Purdila 58338a1281SOctavian Purdila /* 59338a1281SOctavian Purdila * Receive context used between the receive demultiplexer and the transfer 60338a1281SOctavian Purdila * routine. While sending a request the transfer routine will look for a free 61338a1281SOctavian Purdila * receive context and use it to wait for a response and to receive the URB and 62338a1281SOctavian Purdila * thus the response data. 63338a1281SOctavian Purdila */ 64338a1281SOctavian Purdila struct dln2_rx_context { 65338a1281SOctavian Purdila /* completion used to wait for a response */ 66338a1281SOctavian Purdila struct completion done; 67338a1281SOctavian Purdila 68338a1281SOctavian Purdila /* if non-NULL the URB contains the response */ 69338a1281SOctavian Purdila struct urb *urb; 70338a1281SOctavian Purdila 71338a1281SOctavian Purdila /* if true then this context is used to wait for a response */ 72338a1281SOctavian Purdila bool in_use; 73338a1281SOctavian Purdila }; 74338a1281SOctavian Purdila 75338a1281SOctavian Purdila /* 76338a1281SOctavian Purdila * Receive contexts for a particular DLN2 module (i2c, gpio, etc.). We use the 77338a1281SOctavian Purdila * handle header field to identify the module in dln2_dev.mod_rx_slots and then 78338a1281SOctavian Purdila * the echo header field to index the slots field and find the receive context 79338a1281SOctavian Purdila * for a particular request. 80338a1281SOctavian Purdila */ 81338a1281SOctavian Purdila struct dln2_mod_rx_slots { 82338a1281SOctavian Purdila /* RX slots bitmap */ 83338a1281SOctavian Purdila DECLARE_BITMAP(bmap, DLN2_MAX_RX_SLOTS); 84338a1281SOctavian Purdila 85338a1281SOctavian Purdila /* used to wait for a free RX slot */ 86338a1281SOctavian Purdila wait_queue_head_t wq; 87338a1281SOctavian Purdila 88338a1281SOctavian Purdila /* used to wait for an RX operation to complete */ 89338a1281SOctavian Purdila struct dln2_rx_context slots[DLN2_MAX_RX_SLOTS]; 90338a1281SOctavian Purdila 91338a1281SOctavian Purdila /* avoid races between alloc/free_rx_slot and dln2_rx_transfer */ 92338a1281SOctavian Purdila spinlock_t lock; 93338a1281SOctavian Purdila }; 94338a1281SOctavian Purdila 95338a1281SOctavian Purdila struct dln2_dev { 96338a1281SOctavian Purdila struct usb_device *usb_dev; 97338a1281SOctavian Purdila struct usb_interface *interface; 98338a1281SOctavian Purdila u8 ep_in; 99338a1281SOctavian Purdila u8 ep_out; 100338a1281SOctavian Purdila 101338a1281SOctavian Purdila struct urb *rx_urb[DLN2_MAX_URBS]; 102338a1281SOctavian Purdila void *rx_buf[DLN2_MAX_URBS]; 103338a1281SOctavian Purdila 104338a1281SOctavian Purdila struct dln2_mod_rx_slots mod_rx_slots[DLN2_HANDLES]; 105338a1281SOctavian Purdila 106338a1281SOctavian Purdila struct list_head event_cb_list; 107338a1281SOctavian Purdila spinlock_t event_cb_lock; 108338a1281SOctavian Purdila 109338a1281SOctavian Purdila bool disconnect; 110338a1281SOctavian Purdila int active_transfers; 111338a1281SOctavian Purdila wait_queue_head_t disconnect_wq; 112338a1281SOctavian Purdila spinlock_t disconnect_lock; 113338a1281SOctavian Purdila }; 114338a1281SOctavian Purdila 115338a1281SOctavian Purdila struct dln2_event_cb_entry { 116338a1281SOctavian Purdila struct list_head list; 117338a1281SOctavian Purdila u16 id; 118338a1281SOctavian Purdila struct platform_device *pdev; 119338a1281SOctavian Purdila dln2_event_cb_t callback; 120338a1281SOctavian Purdila }; 121338a1281SOctavian Purdila 122338a1281SOctavian Purdila int dln2_register_event_cb(struct platform_device *pdev, u16 id, 123338a1281SOctavian Purdila dln2_event_cb_t event_cb) 124338a1281SOctavian Purdila { 125338a1281SOctavian Purdila struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent); 126338a1281SOctavian Purdila struct dln2_event_cb_entry *i, *entry; 127338a1281SOctavian Purdila unsigned long flags; 128338a1281SOctavian Purdila int ret = 0; 129338a1281SOctavian Purdila 130338a1281SOctavian Purdila entry = kzalloc(sizeof(*entry), GFP_KERNEL); 131338a1281SOctavian Purdila if (!entry) 132338a1281SOctavian Purdila return -ENOMEM; 133338a1281SOctavian Purdila 134338a1281SOctavian Purdila entry->id = id; 135338a1281SOctavian Purdila entry->callback = event_cb; 136338a1281SOctavian Purdila entry->pdev = pdev; 137338a1281SOctavian Purdila 138338a1281SOctavian Purdila spin_lock_irqsave(&dln2->event_cb_lock, flags); 139338a1281SOctavian Purdila 140338a1281SOctavian Purdila list_for_each_entry(i, &dln2->event_cb_list, list) { 141338a1281SOctavian Purdila if (i->id == id) { 142338a1281SOctavian Purdila ret = -EBUSY; 143338a1281SOctavian Purdila break; 144338a1281SOctavian Purdila } 145338a1281SOctavian Purdila } 146338a1281SOctavian Purdila 147338a1281SOctavian Purdila if (!ret) 148338a1281SOctavian Purdila list_add_rcu(&entry->list, &dln2->event_cb_list); 149338a1281SOctavian Purdila 150338a1281SOctavian Purdila spin_unlock_irqrestore(&dln2->event_cb_lock, flags); 151338a1281SOctavian Purdila 152338a1281SOctavian Purdila if (ret) 153338a1281SOctavian Purdila kfree(entry); 154338a1281SOctavian Purdila 155338a1281SOctavian Purdila return ret; 156338a1281SOctavian Purdila } 157338a1281SOctavian Purdila EXPORT_SYMBOL(dln2_register_event_cb); 158338a1281SOctavian Purdila 159338a1281SOctavian Purdila void dln2_unregister_event_cb(struct platform_device *pdev, u16 id) 160338a1281SOctavian Purdila { 161338a1281SOctavian Purdila struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent); 162338a1281SOctavian Purdila struct dln2_event_cb_entry *i; 163338a1281SOctavian Purdila unsigned long flags; 164338a1281SOctavian Purdila bool found = false; 165338a1281SOctavian Purdila 166338a1281SOctavian Purdila spin_lock_irqsave(&dln2->event_cb_lock, flags); 167338a1281SOctavian Purdila 168338a1281SOctavian Purdila list_for_each_entry(i, &dln2->event_cb_list, list) { 169338a1281SOctavian Purdila if (i->id == id) { 170338a1281SOctavian Purdila list_del_rcu(&i->list); 171338a1281SOctavian Purdila found = true; 172338a1281SOctavian Purdila break; 173338a1281SOctavian Purdila } 174338a1281SOctavian Purdila } 175338a1281SOctavian Purdila 176338a1281SOctavian Purdila spin_unlock_irqrestore(&dln2->event_cb_lock, flags); 177338a1281SOctavian Purdila 178338a1281SOctavian Purdila if (found) { 179338a1281SOctavian Purdila synchronize_rcu(); 180338a1281SOctavian Purdila kfree(i); 181338a1281SOctavian Purdila } 182338a1281SOctavian Purdila } 183338a1281SOctavian Purdila EXPORT_SYMBOL(dln2_unregister_event_cb); 184338a1281SOctavian Purdila 185338a1281SOctavian Purdila /* 186338a1281SOctavian Purdila * Returns true if a valid transfer slot is found. In this case the URB must not 187338a1281SOctavian Purdila * be resubmitted immediately in dln2_rx as we need the data when dln2_transfer 188338a1281SOctavian Purdila * is woke up. It will be resubmitted there. 189338a1281SOctavian Purdila */ 190338a1281SOctavian Purdila static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb, 191338a1281SOctavian Purdila u16 handle, u16 rx_slot) 192338a1281SOctavian Purdila { 193338a1281SOctavian Purdila struct device *dev = &dln2->interface->dev; 194338a1281SOctavian Purdila struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle]; 195338a1281SOctavian Purdila struct dln2_rx_context *rxc; 196338a1281SOctavian Purdila bool valid_slot = false; 197338a1281SOctavian Purdila 19800ee7a37SOctavian Purdila if (rx_slot >= DLN2_MAX_RX_SLOTS) 19900ee7a37SOctavian Purdila goto out; 20000ee7a37SOctavian Purdila 201338a1281SOctavian Purdila rxc = &rxs->slots[rx_slot]; 202338a1281SOctavian Purdila 203338a1281SOctavian Purdila /* 204338a1281SOctavian Purdila * No need to disable interrupts as this lock is not taken in interrupt 205338a1281SOctavian Purdila * context elsewhere in this driver. This function (or its callers) are 206338a1281SOctavian Purdila * also not exported to other modules. 207338a1281SOctavian Purdila */ 208338a1281SOctavian Purdila spin_lock(&rxs->lock); 209338a1281SOctavian Purdila if (rxc->in_use && !rxc->urb) { 210338a1281SOctavian Purdila rxc->urb = urb; 211338a1281SOctavian Purdila complete(&rxc->done); 212338a1281SOctavian Purdila valid_slot = true; 213338a1281SOctavian Purdila } 214338a1281SOctavian Purdila spin_unlock(&rxs->lock); 215338a1281SOctavian Purdila 21600ee7a37SOctavian Purdila out: 217338a1281SOctavian Purdila if (!valid_slot) 218338a1281SOctavian Purdila dev_warn(dev, "bad/late response %d/%d\n", handle, rx_slot); 219338a1281SOctavian Purdila 220338a1281SOctavian Purdila return valid_slot; 221338a1281SOctavian Purdila } 222338a1281SOctavian Purdila 223338a1281SOctavian Purdila static void dln2_run_event_callbacks(struct dln2_dev *dln2, u16 id, u16 echo, 224338a1281SOctavian Purdila void *data, int len) 225338a1281SOctavian Purdila { 226338a1281SOctavian Purdila struct dln2_event_cb_entry *i; 227338a1281SOctavian Purdila 228338a1281SOctavian Purdila rcu_read_lock(); 229338a1281SOctavian Purdila 230338a1281SOctavian Purdila list_for_each_entry_rcu(i, &dln2->event_cb_list, list) { 231338a1281SOctavian Purdila if (i->id == id) { 232338a1281SOctavian Purdila i->callback(i->pdev, echo, data, len); 233338a1281SOctavian Purdila break; 234338a1281SOctavian Purdila } 235338a1281SOctavian Purdila } 236338a1281SOctavian Purdila 237338a1281SOctavian Purdila rcu_read_unlock(); 238338a1281SOctavian Purdila } 239338a1281SOctavian Purdila 240338a1281SOctavian Purdila static void dln2_rx(struct urb *urb) 241338a1281SOctavian Purdila { 242338a1281SOctavian Purdila struct dln2_dev *dln2 = urb->context; 243338a1281SOctavian Purdila struct dln2_header *hdr = urb->transfer_buffer; 244338a1281SOctavian Purdila struct device *dev = &dln2->interface->dev; 245338a1281SOctavian Purdila u16 id, echo, handle, size; 246338a1281SOctavian Purdila u8 *data; 247338a1281SOctavian Purdila int len; 248338a1281SOctavian Purdila int err; 249338a1281SOctavian Purdila 250338a1281SOctavian Purdila switch (urb->status) { 251338a1281SOctavian Purdila case 0: 252338a1281SOctavian Purdila /* success */ 253338a1281SOctavian Purdila break; 254338a1281SOctavian Purdila case -ECONNRESET: 255338a1281SOctavian Purdila case -ENOENT: 256338a1281SOctavian Purdila case -ESHUTDOWN: 257338a1281SOctavian Purdila case -EPIPE: 258338a1281SOctavian Purdila /* this urb is terminated, clean up */ 259338a1281SOctavian Purdila dev_dbg(dev, "urb shutting down with status %d\n", urb->status); 260338a1281SOctavian Purdila return; 261338a1281SOctavian Purdila default: 262338a1281SOctavian Purdila dev_dbg(dev, "nonzero urb status received %d\n", urb->status); 263338a1281SOctavian Purdila goto out; 264338a1281SOctavian Purdila } 265338a1281SOctavian Purdila 266338a1281SOctavian Purdila if (urb->actual_length < sizeof(struct dln2_header)) { 267338a1281SOctavian Purdila dev_err(dev, "short response: %d\n", urb->actual_length); 268338a1281SOctavian Purdila goto out; 269338a1281SOctavian Purdila } 270338a1281SOctavian Purdila 271338a1281SOctavian Purdila handle = le16_to_cpu(hdr->handle); 272338a1281SOctavian Purdila id = le16_to_cpu(hdr->id); 273338a1281SOctavian Purdila echo = le16_to_cpu(hdr->echo); 274338a1281SOctavian Purdila size = le16_to_cpu(hdr->size); 275338a1281SOctavian Purdila 276338a1281SOctavian Purdila if (size != urb->actual_length) { 277338a1281SOctavian Purdila dev_err(dev, "size mismatch: handle %x cmd %x echo %x size %d actual %d\n", 278338a1281SOctavian Purdila handle, id, echo, size, urb->actual_length); 279338a1281SOctavian Purdila goto out; 280338a1281SOctavian Purdila } 281338a1281SOctavian Purdila 282338a1281SOctavian Purdila if (handle >= DLN2_HANDLES) { 283338a1281SOctavian Purdila dev_warn(dev, "invalid handle %d\n", handle); 284338a1281SOctavian Purdila goto out; 285338a1281SOctavian Purdila } 286338a1281SOctavian Purdila 287338a1281SOctavian Purdila data = urb->transfer_buffer + sizeof(struct dln2_header); 288338a1281SOctavian Purdila len = urb->actual_length - sizeof(struct dln2_header); 289338a1281SOctavian Purdila 290338a1281SOctavian Purdila if (handle == DLN2_HANDLE_EVENT) { 291338a1281SOctavian Purdila dln2_run_event_callbacks(dln2, id, echo, data, len); 292338a1281SOctavian Purdila } else { 293338a1281SOctavian Purdila /* URB will be re-submitted in _dln2_transfer (free_rx_slot) */ 294338a1281SOctavian Purdila if (dln2_transfer_complete(dln2, urb, handle, echo)) 295338a1281SOctavian Purdila return; 296338a1281SOctavian Purdila } 297338a1281SOctavian Purdila 298338a1281SOctavian Purdila out: 299338a1281SOctavian Purdila err = usb_submit_urb(urb, GFP_ATOMIC); 300338a1281SOctavian Purdila if (err < 0) 301338a1281SOctavian Purdila dev_err(dev, "failed to resubmit RX URB: %d\n", err); 302338a1281SOctavian Purdila } 303338a1281SOctavian Purdila 304338a1281SOctavian Purdila static void *dln2_prep_buf(u16 handle, u16 cmd, u16 echo, const void *obuf, 305338a1281SOctavian Purdila int *obuf_len, gfp_t gfp) 306338a1281SOctavian Purdila { 307338a1281SOctavian Purdila int len; 308338a1281SOctavian Purdila void *buf; 309338a1281SOctavian Purdila struct dln2_header *hdr; 310338a1281SOctavian Purdila 311338a1281SOctavian Purdila len = *obuf_len + sizeof(*hdr); 312338a1281SOctavian Purdila buf = kmalloc(len, gfp); 313338a1281SOctavian Purdila if (!buf) 314338a1281SOctavian Purdila return NULL; 315338a1281SOctavian Purdila 316338a1281SOctavian Purdila hdr = (struct dln2_header *)buf; 317338a1281SOctavian Purdila hdr->id = cpu_to_le16(cmd); 318338a1281SOctavian Purdila hdr->size = cpu_to_le16(len); 319338a1281SOctavian Purdila hdr->echo = cpu_to_le16(echo); 320338a1281SOctavian Purdila hdr->handle = cpu_to_le16(handle); 321338a1281SOctavian Purdila 322338a1281SOctavian Purdila memcpy(buf + sizeof(*hdr), obuf, *obuf_len); 323338a1281SOctavian Purdila 324338a1281SOctavian Purdila *obuf_len = len; 325338a1281SOctavian Purdila 326338a1281SOctavian Purdila return buf; 327338a1281SOctavian Purdila } 328338a1281SOctavian Purdila 329338a1281SOctavian Purdila static int dln2_send_wait(struct dln2_dev *dln2, u16 handle, u16 cmd, u16 echo, 330338a1281SOctavian Purdila const void *obuf, int obuf_len) 331338a1281SOctavian Purdila { 332338a1281SOctavian Purdila int ret = 0; 333338a1281SOctavian Purdila int len = obuf_len; 334338a1281SOctavian Purdila void *buf; 335338a1281SOctavian Purdila int actual; 336338a1281SOctavian Purdila 337338a1281SOctavian Purdila buf = dln2_prep_buf(handle, cmd, echo, obuf, &len, GFP_KERNEL); 338338a1281SOctavian Purdila if (!buf) 339338a1281SOctavian Purdila return -ENOMEM; 340338a1281SOctavian Purdila 341338a1281SOctavian Purdila ret = usb_bulk_msg(dln2->usb_dev, 342338a1281SOctavian Purdila usb_sndbulkpipe(dln2->usb_dev, dln2->ep_out), 343338a1281SOctavian Purdila buf, len, &actual, DLN2_USB_TIMEOUT); 344338a1281SOctavian Purdila 345338a1281SOctavian Purdila kfree(buf); 346338a1281SOctavian Purdila 347338a1281SOctavian Purdila return ret; 348338a1281SOctavian Purdila } 349338a1281SOctavian Purdila 350338a1281SOctavian Purdila static bool find_free_slot(struct dln2_dev *dln2, u16 handle, int *slot) 351338a1281SOctavian Purdila { 352338a1281SOctavian Purdila struct dln2_mod_rx_slots *rxs; 353338a1281SOctavian Purdila unsigned long flags; 354338a1281SOctavian Purdila 355338a1281SOctavian Purdila if (dln2->disconnect) { 356338a1281SOctavian Purdila *slot = -ENODEV; 357338a1281SOctavian Purdila return true; 358338a1281SOctavian Purdila } 359338a1281SOctavian Purdila 360338a1281SOctavian Purdila rxs = &dln2->mod_rx_slots[handle]; 361338a1281SOctavian Purdila 362338a1281SOctavian Purdila spin_lock_irqsave(&rxs->lock, flags); 363338a1281SOctavian Purdila 364338a1281SOctavian Purdila *slot = find_first_zero_bit(rxs->bmap, DLN2_MAX_RX_SLOTS); 365338a1281SOctavian Purdila 366338a1281SOctavian Purdila if (*slot < DLN2_MAX_RX_SLOTS) { 367338a1281SOctavian Purdila struct dln2_rx_context *rxc = &rxs->slots[*slot]; 368338a1281SOctavian Purdila 369338a1281SOctavian Purdila set_bit(*slot, rxs->bmap); 370338a1281SOctavian Purdila rxc->in_use = true; 371338a1281SOctavian Purdila } 372338a1281SOctavian Purdila 373338a1281SOctavian Purdila spin_unlock_irqrestore(&rxs->lock, flags); 374338a1281SOctavian Purdila 375338a1281SOctavian Purdila return *slot < DLN2_MAX_RX_SLOTS; 376338a1281SOctavian Purdila } 377338a1281SOctavian Purdila 378338a1281SOctavian Purdila static int alloc_rx_slot(struct dln2_dev *dln2, u16 handle) 379338a1281SOctavian Purdila { 380338a1281SOctavian Purdila int ret; 381338a1281SOctavian Purdila int slot; 382338a1281SOctavian Purdila 383338a1281SOctavian Purdila /* 384338a1281SOctavian Purdila * No need to timeout here, the wait is bounded by the timeout in 385338a1281SOctavian Purdila * _dln2_transfer. 386338a1281SOctavian Purdila */ 387338a1281SOctavian Purdila ret = wait_event_interruptible(dln2->mod_rx_slots[handle].wq, 388338a1281SOctavian Purdila find_free_slot(dln2, handle, &slot)); 389338a1281SOctavian Purdila if (ret < 0) 390338a1281SOctavian Purdila return ret; 391338a1281SOctavian Purdila 392338a1281SOctavian Purdila return slot; 393338a1281SOctavian Purdila } 394338a1281SOctavian Purdila 395338a1281SOctavian Purdila static void free_rx_slot(struct dln2_dev *dln2, u16 handle, int slot) 396338a1281SOctavian Purdila { 397338a1281SOctavian Purdila struct dln2_mod_rx_slots *rxs; 398338a1281SOctavian Purdila struct urb *urb = NULL; 399338a1281SOctavian Purdila unsigned long flags; 400338a1281SOctavian Purdila struct dln2_rx_context *rxc; 401338a1281SOctavian Purdila 402338a1281SOctavian Purdila rxs = &dln2->mod_rx_slots[handle]; 403338a1281SOctavian Purdila 404338a1281SOctavian Purdila spin_lock_irqsave(&rxs->lock, flags); 405338a1281SOctavian Purdila 406338a1281SOctavian Purdila clear_bit(slot, rxs->bmap); 407338a1281SOctavian Purdila 408338a1281SOctavian Purdila rxc = &rxs->slots[slot]; 409338a1281SOctavian Purdila rxc->in_use = false; 410338a1281SOctavian Purdila urb = rxc->urb; 411338a1281SOctavian Purdila rxc->urb = NULL; 412338a1281SOctavian Purdila reinit_completion(&rxc->done); 413338a1281SOctavian Purdila 414338a1281SOctavian Purdila spin_unlock_irqrestore(&rxs->lock, flags); 415338a1281SOctavian Purdila 416338a1281SOctavian Purdila if (urb) { 417338a1281SOctavian Purdila int err; 418338a1281SOctavian Purdila struct device *dev = &dln2->interface->dev; 419338a1281SOctavian Purdila 420338a1281SOctavian Purdila err = usb_submit_urb(urb, GFP_KERNEL); 421338a1281SOctavian Purdila if (err < 0) 422338a1281SOctavian Purdila dev_err(dev, "failed to resubmit RX URB: %d\n", err); 423338a1281SOctavian Purdila } 424338a1281SOctavian Purdila 425338a1281SOctavian Purdila wake_up_interruptible(&rxs->wq); 426338a1281SOctavian Purdila } 427338a1281SOctavian Purdila 428338a1281SOctavian Purdila static int _dln2_transfer(struct dln2_dev *dln2, u16 handle, u16 cmd, 429338a1281SOctavian Purdila const void *obuf, unsigned obuf_len, 430338a1281SOctavian Purdila void *ibuf, unsigned *ibuf_len) 431338a1281SOctavian Purdila { 432338a1281SOctavian Purdila int ret = 0; 433338a1281SOctavian Purdila int rx_slot; 434338a1281SOctavian Purdila struct dln2_response *rsp; 435338a1281SOctavian Purdila struct dln2_rx_context *rxc; 436338a1281SOctavian Purdila struct device *dev = &dln2->interface->dev; 437338a1281SOctavian Purdila const unsigned long timeout = DLN2_USB_TIMEOUT * HZ / 1000; 438338a1281SOctavian Purdila struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle]; 439338a1281SOctavian Purdila 440338a1281SOctavian Purdila spin_lock(&dln2->disconnect_lock); 441338a1281SOctavian Purdila if (!dln2->disconnect) 442338a1281SOctavian Purdila dln2->active_transfers++; 443338a1281SOctavian Purdila else 444338a1281SOctavian Purdila ret = -ENODEV; 445338a1281SOctavian Purdila spin_unlock(&dln2->disconnect_lock); 446338a1281SOctavian Purdila 447338a1281SOctavian Purdila if (ret) 448338a1281SOctavian Purdila return ret; 449338a1281SOctavian Purdila 450338a1281SOctavian Purdila rx_slot = alloc_rx_slot(dln2, handle); 451338a1281SOctavian Purdila if (rx_slot < 0) { 452338a1281SOctavian Purdila ret = rx_slot; 453338a1281SOctavian Purdila goto out_decr; 454338a1281SOctavian Purdila } 455338a1281SOctavian Purdila 456338a1281SOctavian Purdila ret = dln2_send_wait(dln2, handle, cmd, rx_slot, obuf, obuf_len); 457338a1281SOctavian Purdila if (ret < 0) { 458338a1281SOctavian Purdila dev_err(dev, "USB write failed: %d\n", ret); 459338a1281SOctavian Purdila goto out_free_rx_slot; 460338a1281SOctavian Purdila } 461338a1281SOctavian Purdila 462338a1281SOctavian Purdila rxc = &rxs->slots[rx_slot]; 463338a1281SOctavian Purdila 464338a1281SOctavian Purdila ret = wait_for_completion_interruptible_timeout(&rxc->done, timeout); 465338a1281SOctavian Purdila if (ret <= 0) { 466338a1281SOctavian Purdila if (!ret) 467338a1281SOctavian Purdila ret = -ETIMEDOUT; 468338a1281SOctavian Purdila goto out_free_rx_slot; 4697ca2b1c6SOctavian Purdila } else { 4707ca2b1c6SOctavian Purdila ret = 0; 471338a1281SOctavian Purdila } 472338a1281SOctavian Purdila 473338a1281SOctavian Purdila if (dln2->disconnect) { 474338a1281SOctavian Purdila ret = -ENODEV; 475338a1281SOctavian Purdila goto out_free_rx_slot; 476338a1281SOctavian Purdila } 477338a1281SOctavian Purdila 478338a1281SOctavian Purdila /* if we got here we know that the response header has been checked */ 479338a1281SOctavian Purdila rsp = rxc->urb->transfer_buffer; 480338a1281SOctavian Purdila 481338a1281SOctavian Purdila if (rsp->hdr.size < sizeof(*rsp)) { 482338a1281SOctavian Purdila ret = -EPROTO; 483338a1281SOctavian Purdila goto out_free_rx_slot; 484338a1281SOctavian Purdila } 485338a1281SOctavian Purdila 486338a1281SOctavian Purdila if (le16_to_cpu(rsp->result) > 0x80) { 487338a1281SOctavian Purdila dev_dbg(dev, "%d received response with error %d\n", 488338a1281SOctavian Purdila handle, le16_to_cpu(rsp->result)); 489338a1281SOctavian Purdila ret = -EREMOTEIO; 490338a1281SOctavian Purdila goto out_free_rx_slot; 491338a1281SOctavian Purdila } 492338a1281SOctavian Purdila 4937ca2b1c6SOctavian Purdila if (!ibuf) 494338a1281SOctavian Purdila goto out_free_rx_slot; 495338a1281SOctavian Purdila 496338a1281SOctavian Purdila if (*ibuf_len > rsp->hdr.size - sizeof(*rsp)) 497338a1281SOctavian Purdila *ibuf_len = rsp->hdr.size - sizeof(*rsp); 498338a1281SOctavian Purdila 499338a1281SOctavian Purdila memcpy(ibuf, rsp + 1, *ibuf_len); 500338a1281SOctavian Purdila 501338a1281SOctavian Purdila out_free_rx_slot: 502338a1281SOctavian Purdila free_rx_slot(dln2, handle, rx_slot); 503338a1281SOctavian Purdila out_decr: 504338a1281SOctavian Purdila spin_lock(&dln2->disconnect_lock); 505338a1281SOctavian Purdila dln2->active_transfers--; 506338a1281SOctavian Purdila spin_unlock(&dln2->disconnect_lock); 507338a1281SOctavian Purdila if (dln2->disconnect) 508338a1281SOctavian Purdila wake_up(&dln2->disconnect_wq); 509338a1281SOctavian Purdila 510338a1281SOctavian Purdila return ret; 511338a1281SOctavian Purdila } 512338a1281SOctavian Purdila 513338a1281SOctavian Purdila int dln2_transfer(struct platform_device *pdev, u16 cmd, 514338a1281SOctavian Purdila const void *obuf, unsigned obuf_len, 515338a1281SOctavian Purdila void *ibuf, unsigned *ibuf_len) 516338a1281SOctavian Purdila { 517338a1281SOctavian Purdila struct dln2_platform_data *dln2_pdata; 518338a1281SOctavian Purdila struct dln2_dev *dln2; 519338a1281SOctavian Purdila u16 handle; 520338a1281SOctavian Purdila 521338a1281SOctavian Purdila dln2 = dev_get_drvdata(pdev->dev.parent); 522338a1281SOctavian Purdila dln2_pdata = dev_get_platdata(&pdev->dev); 523338a1281SOctavian Purdila handle = dln2_pdata->handle; 524338a1281SOctavian Purdila 525338a1281SOctavian Purdila return _dln2_transfer(dln2, handle, cmd, obuf, obuf_len, ibuf, 526338a1281SOctavian Purdila ibuf_len); 527338a1281SOctavian Purdila } 528338a1281SOctavian Purdila EXPORT_SYMBOL(dln2_transfer); 529338a1281SOctavian Purdila 530338a1281SOctavian Purdila static int dln2_check_hw(struct dln2_dev *dln2) 531338a1281SOctavian Purdila { 532338a1281SOctavian Purdila int ret; 533338a1281SOctavian Purdila __le32 hw_type; 534338a1281SOctavian Purdila int len = sizeof(hw_type); 535338a1281SOctavian Purdila 536338a1281SOctavian Purdila ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_VER, 537338a1281SOctavian Purdila NULL, 0, &hw_type, &len); 538338a1281SOctavian Purdila if (ret < 0) 539338a1281SOctavian Purdila return ret; 540338a1281SOctavian Purdila if (len < sizeof(hw_type)) 541338a1281SOctavian Purdila return -EREMOTEIO; 542338a1281SOctavian Purdila 543338a1281SOctavian Purdila if (le32_to_cpu(hw_type) != DLN2_HW_ID) { 544338a1281SOctavian Purdila dev_err(&dln2->interface->dev, "Device ID 0x%x not supported\n", 545338a1281SOctavian Purdila le32_to_cpu(hw_type)); 546338a1281SOctavian Purdila return -ENODEV; 547338a1281SOctavian Purdila } 548338a1281SOctavian Purdila 549338a1281SOctavian Purdila return 0; 550338a1281SOctavian Purdila } 551338a1281SOctavian Purdila 552338a1281SOctavian Purdila static int dln2_print_serialno(struct dln2_dev *dln2) 553338a1281SOctavian Purdila { 554338a1281SOctavian Purdila int ret; 555338a1281SOctavian Purdila __le32 serial_no; 556338a1281SOctavian Purdila int len = sizeof(serial_no); 557338a1281SOctavian Purdila struct device *dev = &dln2->interface->dev; 558338a1281SOctavian Purdila 559338a1281SOctavian Purdila ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_SN, NULL, 0, 560338a1281SOctavian Purdila &serial_no, &len); 561338a1281SOctavian Purdila if (ret < 0) 562338a1281SOctavian Purdila return ret; 563338a1281SOctavian Purdila if (len < sizeof(serial_no)) 564338a1281SOctavian Purdila return -EREMOTEIO; 565338a1281SOctavian Purdila 566338a1281SOctavian Purdila dev_info(dev, "Diolan DLN2 serial %u\n", le32_to_cpu(serial_no)); 567338a1281SOctavian Purdila 568338a1281SOctavian Purdila return 0; 569338a1281SOctavian Purdila } 570338a1281SOctavian Purdila 571338a1281SOctavian Purdila static int dln2_hw_init(struct dln2_dev *dln2) 572338a1281SOctavian Purdila { 573338a1281SOctavian Purdila int ret; 574338a1281SOctavian Purdila 575338a1281SOctavian Purdila ret = dln2_check_hw(dln2); 576338a1281SOctavian Purdila if (ret < 0) 577338a1281SOctavian Purdila return ret; 578338a1281SOctavian Purdila 579338a1281SOctavian Purdila return dln2_print_serialno(dln2); 580338a1281SOctavian Purdila } 581338a1281SOctavian Purdila 582338a1281SOctavian Purdila static void dln2_free_rx_urbs(struct dln2_dev *dln2) 583338a1281SOctavian Purdila { 584338a1281SOctavian Purdila int i; 585338a1281SOctavian Purdila 586338a1281SOctavian Purdila for (i = 0; i < DLN2_MAX_URBS; i++) { 587338a1281SOctavian Purdila usb_kill_urb(dln2->rx_urb[i]); 588338a1281SOctavian Purdila usb_free_urb(dln2->rx_urb[i]); 589338a1281SOctavian Purdila kfree(dln2->rx_buf[i]); 590338a1281SOctavian Purdila } 591338a1281SOctavian Purdila } 592338a1281SOctavian Purdila 593338a1281SOctavian Purdila static void dln2_free(struct dln2_dev *dln2) 594338a1281SOctavian Purdila { 595338a1281SOctavian Purdila dln2_free_rx_urbs(dln2); 596338a1281SOctavian Purdila usb_put_dev(dln2->usb_dev); 597338a1281SOctavian Purdila kfree(dln2); 598338a1281SOctavian Purdila } 599338a1281SOctavian Purdila 600338a1281SOctavian Purdila static int dln2_setup_rx_urbs(struct dln2_dev *dln2, 601338a1281SOctavian Purdila struct usb_host_interface *hostif) 602338a1281SOctavian Purdila { 603338a1281SOctavian Purdila int i; 604338a1281SOctavian Purdila int ret; 605338a1281SOctavian Purdila const int rx_max_size = DLN2_RX_BUF_SIZE; 606338a1281SOctavian Purdila struct device *dev = &dln2->interface->dev; 607338a1281SOctavian Purdila 608338a1281SOctavian Purdila for (i = 0; i < DLN2_MAX_URBS; i++) { 609338a1281SOctavian Purdila dln2->rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL); 610338a1281SOctavian Purdila if (!dln2->rx_buf[i]) 611338a1281SOctavian Purdila return -ENOMEM; 612338a1281SOctavian Purdila 613338a1281SOctavian Purdila dln2->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); 614338a1281SOctavian Purdila if (!dln2->rx_urb[i]) 615338a1281SOctavian Purdila return -ENOMEM; 616338a1281SOctavian Purdila 617338a1281SOctavian Purdila usb_fill_bulk_urb(dln2->rx_urb[i], dln2->usb_dev, 618338a1281SOctavian Purdila usb_rcvbulkpipe(dln2->usb_dev, dln2->ep_in), 619338a1281SOctavian Purdila dln2->rx_buf[i], rx_max_size, dln2_rx, dln2); 620338a1281SOctavian Purdila 621338a1281SOctavian Purdila ret = usb_submit_urb(dln2->rx_urb[i], GFP_KERNEL); 622338a1281SOctavian Purdila if (ret < 0) { 623338a1281SOctavian Purdila dev_err(dev, "failed to submit RX URB: %d\n", ret); 624338a1281SOctavian Purdila return ret; 625338a1281SOctavian Purdila } 626338a1281SOctavian Purdila } 627338a1281SOctavian Purdila 628338a1281SOctavian Purdila return 0; 629338a1281SOctavian Purdila } 630338a1281SOctavian Purdila 631338a1281SOctavian Purdila static struct dln2_platform_data dln2_pdata_gpio = { 632338a1281SOctavian Purdila .handle = DLN2_HANDLE_GPIO, 633338a1281SOctavian Purdila }; 634338a1281SOctavian Purdila 635338a1281SOctavian Purdila /* Only one I2C port seems to be supported on current hardware */ 636338a1281SOctavian Purdila static struct dln2_platform_data dln2_pdata_i2c = { 637338a1281SOctavian Purdila .handle = DLN2_HANDLE_I2C, 638338a1281SOctavian Purdila .port = 0, 639338a1281SOctavian Purdila }; 640338a1281SOctavian Purdila 641338a1281SOctavian Purdila static const struct mfd_cell dln2_devs[] = { 642338a1281SOctavian Purdila { 643338a1281SOctavian Purdila .name = "dln2-gpio", 644338a1281SOctavian Purdila .platform_data = &dln2_pdata_gpio, 645338a1281SOctavian Purdila .pdata_size = sizeof(struct dln2_platform_data), 646338a1281SOctavian Purdila }, 647338a1281SOctavian Purdila { 648338a1281SOctavian Purdila .name = "dln2-i2c", 649338a1281SOctavian Purdila .platform_data = &dln2_pdata_i2c, 650338a1281SOctavian Purdila .pdata_size = sizeof(struct dln2_platform_data), 651338a1281SOctavian Purdila }, 652338a1281SOctavian Purdila }; 653338a1281SOctavian Purdila 654338a1281SOctavian Purdila static void dln2_disconnect(struct usb_interface *interface) 655338a1281SOctavian Purdila { 656338a1281SOctavian Purdila struct dln2_dev *dln2 = usb_get_intfdata(interface); 657338a1281SOctavian Purdila int i, j; 658338a1281SOctavian Purdila 659338a1281SOctavian Purdila /* don't allow starting new transfers */ 660338a1281SOctavian Purdila spin_lock(&dln2->disconnect_lock); 661338a1281SOctavian Purdila dln2->disconnect = true; 662338a1281SOctavian Purdila spin_unlock(&dln2->disconnect_lock); 663338a1281SOctavian Purdila 664338a1281SOctavian Purdila /* cancel in progress transfers */ 665338a1281SOctavian Purdila for (i = 0; i < DLN2_HANDLES; i++) { 666338a1281SOctavian Purdila struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[i]; 667338a1281SOctavian Purdila unsigned long flags; 668338a1281SOctavian Purdila 669338a1281SOctavian Purdila spin_lock_irqsave(&rxs->lock, flags); 670338a1281SOctavian Purdila 671338a1281SOctavian Purdila /* cancel all response waiters */ 672338a1281SOctavian Purdila for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) { 673338a1281SOctavian Purdila struct dln2_rx_context *rxc = &rxs->slots[j]; 674338a1281SOctavian Purdila 675338a1281SOctavian Purdila if (rxc->in_use) 676338a1281SOctavian Purdila complete(&rxc->done); 677338a1281SOctavian Purdila } 678338a1281SOctavian Purdila 679338a1281SOctavian Purdila spin_unlock_irqrestore(&rxs->lock, flags); 680338a1281SOctavian Purdila } 681338a1281SOctavian Purdila 682338a1281SOctavian Purdila /* wait for transfers to end */ 683338a1281SOctavian Purdila wait_event(dln2->disconnect_wq, !dln2->active_transfers); 684338a1281SOctavian Purdila 685338a1281SOctavian Purdila mfd_remove_devices(&interface->dev); 686338a1281SOctavian Purdila 687338a1281SOctavian Purdila dln2_free(dln2); 688338a1281SOctavian Purdila } 689338a1281SOctavian Purdila 690338a1281SOctavian Purdila static int dln2_probe(struct usb_interface *interface, 691338a1281SOctavian Purdila const struct usb_device_id *usb_id) 692338a1281SOctavian Purdila { 693338a1281SOctavian Purdila struct usb_host_interface *hostif = interface->cur_altsetting; 694338a1281SOctavian Purdila struct device *dev = &interface->dev; 695338a1281SOctavian Purdila struct dln2_dev *dln2; 696338a1281SOctavian Purdila int ret; 697338a1281SOctavian Purdila int i, j; 698338a1281SOctavian Purdila 699338a1281SOctavian Purdila if (hostif->desc.bInterfaceNumber != 0 || 700338a1281SOctavian Purdila hostif->desc.bNumEndpoints < 2) 701338a1281SOctavian Purdila return -ENODEV; 702338a1281SOctavian Purdila 703338a1281SOctavian Purdila dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL); 704338a1281SOctavian Purdila if (!dln2) 705338a1281SOctavian Purdila return -ENOMEM; 706338a1281SOctavian Purdila 707338a1281SOctavian Purdila dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress; 708338a1281SOctavian Purdila dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress; 709338a1281SOctavian Purdila dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface)); 710338a1281SOctavian Purdila dln2->interface = interface; 711338a1281SOctavian Purdila usb_set_intfdata(interface, dln2); 712338a1281SOctavian Purdila init_waitqueue_head(&dln2->disconnect_wq); 713338a1281SOctavian Purdila 714338a1281SOctavian Purdila for (i = 0; i < DLN2_HANDLES; i++) { 715338a1281SOctavian Purdila init_waitqueue_head(&dln2->mod_rx_slots[i].wq); 716338a1281SOctavian Purdila spin_lock_init(&dln2->mod_rx_slots[i].lock); 717338a1281SOctavian Purdila for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) 718338a1281SOctavian Purdila init_completion(&dln2->mod_rx_slots[i].slots[j].done); 719338a1281SOctavian Purdila } 720338a1281SOctavian Purdila 721338a1281SOctavian Purdila spin_lock_init(&dln2->event_cb_lock); 722338a1281SOctavian Purdila spin_lock_init(&dln2->disconnect_lock); 723338a1281SOctavian Purdila INIT_LIST_HEAD(&dln2->event_cb_list); 724338a1281SOctavian Purdila 725338a1281SOctavian Purdila ret = dln2_setup_rx_urbs(dln2, hostif); 726338a1281SOctavian Purdila if (ret) 727338a1281SOctavian Purdila goto out_cleanup; 728338a1281SOctavian Purdila 729338a1281SOctavian Purdila ret = dln2_hw_init(dln2); 730338a1281SOctavian Purdila if (ret < 0) { 731338a1281SOctavian Purdila dev_err(dev, "failed to initialize hardware\n"); 732338a1281SOctavian Purdila goto out_cleanup; 733338a1281SOctavian Purdila } 734338a1281SOctavian Purdila 735338a1281SOctavian Purdila ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs)); 736338a1281SOctavian Purdila if (ret != 0) { 737338a1281SOctavian Purdila dev_err(dev, "failed to add mfd devices to core\n"); 738338a1281SOctavian Purdila goto out_cleanup; 739338a1281SOctavian Purdila } 740338a1281SOctavian Purdila 741338a1281SOctavian Purdila return 0; 742338a1281SOctavian Purdila 743338a1281SOctavian Purdila out_cleanup: 744338a1281SOctavian Purdila dln2_free(dln2); 745338a1281SOctavian Purdila 746338a1281SOctavian Purdila return ret; 747338a1281SOctavian Purdila } 748338a1281SOctavian Purdila 749338a1281SOctavian Purdila static const struct usb_device_id dln2_table[] = { 750338a1281SOctavian Purdila { USB_DEVICE(0xa257, 0x2013) }, 751338a1281SOctavian Purdila { } 752338a1281SOctavian Purdila }; 753338a1281SOctavian Purdila 754338a1281SOctavian Purdila MODULE_DEVICE_TABLE(usb, dln2_table); 755338a1281SOctavian Purdila 756338a1281SOctavian Purdila static struct usb_driver dln2_driver = { 757338a1281SOctavian Purdila .name = "dln2", 758338a1281SOctavian Purdila .probe = dln2_probe, 759338a1281SOctavian Purdila .disconnect = dln2_disconnect, 760338a1281SOctavian Purdila .id_table = dln2_table, 761338a1281SOctavian Purdila }; 762338a1281SOctavian Purdila 763338a1281SOctavian Purdila module_usb_driver(dln2_driver); 764338a1281SOctavian Purdila 765338a1281SOctavian Purdila MODULE_AUTHOR("Octavian Purdila <octavian.purdila@intel.com>"); 766338a1281SOctavian Purdila MODULE_DESCRIPTION("Core driver for the Diolan DLN2 interface adapter"); 767338a1281SOctavian Purdila MODULE_LICENSE("GPL v2"); 768