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]; 4392fc2b484SDan Carpenter int size; 440338a1281SOctavian Purdila 441338a1281SOctavian Purdila spin_lock(&dln2->disconnect_lock); 442338a1281SOctavian Purdila if (!dln2->disconnect) 443338a1281SOctavian Purdila dln2->active_transfers++; 444338a1281SOctavian Purdila else 445338a1281SOctavian Purdila ret = -ENODEV; 446338a1281SOctavian Purdila spin_unlock(&dln2->disconnect_lock); 447338a1281SOctavian Purdila 448338a1281SOctavian Purdila if (ret) 449338a1281SOctavian Purdila return ret; 450338a1281SOctavian Purdila 451338a1281SOctavian Purdila rx_slot = alloc_rx_slot(dln2, handle); 452338a1281SOctavian Purdila if (rx_slot < 0) { 453338a1281SOctavian Purdila ret = rx_slot; 454338a1281SOctavian Purdila goto out_decr; 455338a1281SOctavian Purdila } 456338a1281SOctavian Purdila 457338a1281SOctavian Purdila ret = dln2_send_wait(dln2, handle, cmd, rx_slot, obuf, obuf_len); 458338a1281SOctavian Purdila if (ret < 0) { 459338a1281SOctavian Purdila dev_err(dev, "USB write failed: %d\n", ret); 460338a1281SOctavian Purdila goto out_free_rx_slot; 461338a1281SOctavian Purdila } 462338a1281SOctavian Purdila 463338a1281SOctavian Purdila rxc = &rxs->slots[rx_slot]; 464338a1281SOctavian Purdila 465338a1281SOctavian Purdila ret = wait_for_completion_interruptible_timeout(&rxc->done, timeout); 466338a1281SOctavian Purdila if (ret <= 0) { 467338a1281SOctavian Purdila if (!ret) 468338a1281SOctavian Purdila ret = -ETIMEDOUT; 469338a1281SOctavian Purdila goto out_free_rx_slot; 4707ca2b1c6SOctavian Purdila } else { 4717ca2b1c6SOctavian Purdila ret = 0; 472338a1281SOctavian Purdila } 473338a1281SOctavian Purdila 474338a1281SOctavian Purdila if (dln2->disconnect) { 475338a1281SOctavian Purdila ret = -ENODEV; 476338a1281SOctavian Purdila goto out_free_rx_slot; 477338a1281SOctavian Purdila } 478338a1281SOctavian Purdila 479338a1281SOctavian Purdila /* if we got here we know that the response header has been checked */ 480338a1281SOctavian Purdila rsp = rxc->urb->transfer_buffer; 4812fc2b484SDan Carpenter size = le16_to_cpu(rsp->hdr.size); 482338a1281SOctavian Purdila 4832fc2b484SDan Carpenter if (size < sizeof(*rsp)) { 484338a1281SOctavian Purdila ret = -EPROTO; 485338a1281SOctavian Purdila goto out_free_rx_slot; 486338a1281SOctavian Purdila } 487338a1281SOctavian Purdila 488338a1281SOctavian Purdila if (le16_to_cpu(rsp->result) > 0x80) { 489338a1281SOctavian Purdila dev_dbg(dev, "%d received response with error %d\n", 490338a1281SOctavian Purdila handle, le16_to_cpu(rsp->result)); 491338a1281SOctavian Purdila ret = -EREMOTEIO; 492338a1281SOctavian Purdila goto out_free_rx_slot; 493338a1281SOctavian Purdila } 494338a1281SOctavian Purdila 4957ca2b1c6SOctavian Purdila if (!ibuf) 496338a1281SOctavian Purdila goto out_free_rx_slot; 497338a1281SOctavian Purdila 4982fc2b484SDan Carpenter if (*ibuf_len > size - sizeof(*rsp)) 4992fc2b484SDan Carpenter *ibuf_len = size - sizeof(*rsp); 500338a1281SOctavian Purdila 501338a1281SOctavian Purdila memcpy(ibuf, rsp + 1, *ibuf_len); 502338a1281SOctavian Purdila 503338a1281SOctavian Purdila out_free_rx_slot: 504338a1281SOctavian Purdila free_rx_slot(dln2, handle, rx_slot); 505338a1281SOctavian Purdila out_decr: 506338a1281SOctavian Purdila spin_lock(&dln2->disconnect_lock); 507338a1281SOctavian Purdila dln2->active_transfers--; 508338a1281SOctavian Purdila spin_unlock(&dln2->disconnect_lock); 509338a1281SOctavian Purdila if (dln2->disconnect) 510338a1281SOctavian Purdila wake_up(&dln2->disconnect_wq); 511338a1281SOctavian Purdila 512338a1281SOctavian Purdila return ret; 513338a1281SOctavian Purdila } 514338a1281SOctavian Purdila 515338a1281SOctavian Purdila int dln2_transfer(struct platform_device *pdev, u16 cmd, 516338a1281SOctavian Purdila const void *obuf, unsigned obuf_len, 517338a1281SOctavian Purdila void *ibuf, unsigned *ibuf_len) 518338a1281SOctavian Purdila { 519338a1281SOctavian Purdila struct dln2_platform_data *dln2_pdata; 520338a1281SOctavian Purdila struct dln2_dev *dln2; 521338a1281SOctavian Purdila u16 handle; 522338a1281SOctavian Purdila 523338a1281SOctavian Purdila dln2 = dev_get_drvdata(pdev->dev.parent); 524338a1281SOctavian Purdila dln2_pdata = dev_get_platdata(&pdev->dev); 525338a1281SOctavian Purdila handle = dln2_pdata->handle; 526338a1281SOctavian Purdila 527338a1281SOctavian Purdila return _dln2_transfer(dln2, handle, cmd, obuf, obuf_len, ibuf, 528338a1281SOctavian Purdila ibuf_len); 529338a1281SOctavian Purdila } 530338a1281SOctavian Purdila EXPORT_SYMBOL(dln2_transfer); 531338a1281SOctavian Purdila 532338a1281SOctavian Purdila static int dln2_check_hw(struct dln2_dev *dln2) 533338a1281SOctavian Purdila { 534338a1281SOctavian Purdila int ret; 535338a1281SOctavian Purdila __le32 hw_type; 536338a1281SOctavian Purdila int len = sizeof(hw_type); 537338a1281SOctavian Purdila 538338a1281SOctavian Purdila ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_VER, 539338a1281SOctavian Purdila NULL, 0, &hw_type, &len); 540338a1281SOctavian Purdila if (ret < 0) 541338a1281SOctavian Purdila return ret; 542338a1281SOctavian Purdila if (len < sizeof(hw_type)) 543338a1281SOctavian Purdila return -EREMOTEIO; 544338a1281SOctavian Purdila 545338a1281SOctavian Purdila if (le32_to_cpu(hw_type) != DLN2_HW_ID) { 546338a1281SOctavian Purdila dev_err(&dln2->interface->dev, "Device ID 0x%x not supported\n", 547338a1281SOctavian Purdila le32_to_cpu(hw_type)); 548338a1281SOctavian Purdila return -ENODEV; 549338a1281SOctavian Purdila } 550338a1281SOctavian Purdila 551338a1281SOctavian Purdila return 0; 552338a1281SOctavian Purdila } 553338a1281SOctavian Purdila 554338a1281SOctavian Purdila static int dln2_print_serialno(struct dln2_dev *dln2) 555338a1281SOctavian Purdila { 556338a1281SOctavian Purdila int ret; 557338a1281SOctavian Purdila __le32 serial_no; 558338a1281SOctavian Purdila int len = sizeof(serial_no); 559338a1281SOctavian Purdila struct device *dev = &dln2->interface->dev; 560338a1281SOctavian Purdila 561338a1281SOctavian Purdila ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_SN, NULL, 0, 562338a1281SOctavian Purdila &serial_no, &len); 563338a1281SOctavian Purdila if (ret < 0) 564338a1281SOctavian Purdila return ret; 565338a1281SOctavian Purdila if (len < sizeof(serial_no)) 566338a1281SOctavian Purdila return -EREMOTEIO; 567338a1281SOctavian Purdila 568338a1281SOctavian Purdila dev_info(dev, "Diolan DLN2 serial %u\n", le32_to_cpu(serial_no)); 569338a1281SOctavian Purdila 570338a1281SOctavian Purdila return 0; 571338a1281SOctavian Purdila } 572338a1281SOctavian Purdila 573338a1281SOctavian Purdila static int dln2_hw_init(struct dln2_dev *dln2) 574338a1281SOctavian Purdila { 575338a1281SOctavian Purdila int ret; 576338a1281SOctavian Purdila 577338a1281SOctavian Purdila ret = dln2_check_hw(dln2); 578338a1281SOctavian Purdila if (ret < 0) 579338a1281SOctavian Purdila return ret; 580338a1281SOctavian Purdila 581338a1281SOctavian Purdila return dln2_print_serialno(dln2); 582338a1281SOctavian Purdila } 583338a1281SOctavian Purdila 584338a1281SOctavian Purdila static void dln2_free_rx_urbs(struct dln2_dev *dln2) 585338a1281SOctavian Purdila { 586338a1281SOctavian Purdila int i; 587338a1281SOctavian Purdila 588338a1281SOctavian Purdila for (i = 0; i < DLN2_MAX_URBS; i++) { 589338a1281SOctavian Purdila usb_kill_urb(dln2->rx_urb[i]); 590338a1281SOctavian Purdila usb_free_urb(dln2->rx_urb[i]); 591338a1281SOctavian Purdila kfree(dln2->rx_buf[i]); 592338a1281SOctavian Purdila } 593338a1281SOctavian Purdila } 594338a1281SOctavian Purdila 595338a1281SOctavian Purdila static void dln2_free(struct dln2_dev *dln2) 596338a1281SOctavian Purdila { 597338a1281SOctavian Purdila dln2_free_rx_urbs(dln2); 598338a1281SOctavian Purdila usb_put_dev(dln2->usb_dev); 599338a1281SOctavian Purdila kfree(dln2); 600338a1281SOctavian Purdila } 601338a1281SOctavian Purdila 602338a1281SOctavian Purdila static int dln2_setup_rx_urbs(struct dln2_dev *dln2, 603338a1281SOctavian Purdila struct usb_host_interface *hostif) 604338a1281SOctavian Purdila { 605338a1281SOctavian Purdila int i; 606338a1281SOctavian Purdila int ret; 607338a1281SOctavian Purdila const int rx_max_size = DLN2_RX_BUF_SIZE; 608338a1281SOctavian Purdila struct device *dev = &dln2->interface->dev; 609338a1281SOctavian Purdila 610338a1281SOctavian Purdila for (i = 0; i < DLN2_MAX_URBS; i++) { 611338a1281SOctavian Purdila dln2->rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL); 612338a1281SOctavian Purdila if (!dln2->rx_buf[i]) 613338a1281SOctavian Purdila return -ENOMEM; 614338a1281SOctavian Purdila 615338a1281SOctavian Purdila dln2->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); 616338a1281SOctavian Purdila if (!dln2->rx_urb[i]) 617338a1281SOctavian Purdila return -ENOMEM; 618338a1281SOctavian Purdila 619338a1281SOctavian Purdila usb_fill_bulk_urb(dln2->rx_urb[i], dln2->usb_dev, 620338a1281SOctavian Purdila usb_rcvbulkpipe(dln2->usb_dev, dln2->ep_in), 621338a1281SOctavian Purdila dln2->rx_buf[i], rx_max_size, dln2_rx, dln2); 622338a1281SOctavian Purdila 623338a1281SOctavian Purdila ret = usb_submit_urb(dln2->rx_urb[i], GFP_KERNEL); 624338a1281SOctavian Purdila if (ret < 0) { 625338a1281SOctavian Purdila dev_err(dev, "failed to submit RX URB: %d\n", ret); 626338a1281SOctavian Purdila return ret; 627338a1281SOctavian Purdila } 628338a1281SOctavian Purdila } 629338a1281SOctavian Purdila 630338a1281SOctavian Purdila return 0; 631338a1281SOctavian Purdila } 632338a1281SOctavian Purdila 633338a1281SOctavian Purdila static struct dln2_platform_data dln2_pdata_gpio = { 634338a1281SOctavian Purdila .handle = DLN2_HANDLE_GPIO, 635338a1281SOctavian Purdila }; 636338a1281SOctavian Purdila 637338a1281SOctavian Purdila /* Only one I2C port seems to be supported on current hardware */ 638338a1281SOctavian Purdila static struct dln2_platform_data dln2_pdata_i2c = { 639338a1281SOctavian Purdila .handle = DLN2_HANDLE_I2C, 640338a1281SOctavian Purdila .port = 0, 641338a1281SOctavian Purdila }; 642338a1281SOctavian Purdila 643338a1281SOctavian Purdila static const struct mfd_cell dln2_devs[] = { 644338a1281SOctavian Purdila { 645338a1281SOctavian Purdila .name = "dln2-gpio", 646338a1281SOctavian Purdila .platform_data = &dln2_pdata_gpio, 647338a1281SOctavian Purdila .pdata_size = sizeof(struct dln2_platform_data), 648338a1281SOctavian Purdila }, 649338a1281SOctavian Purdila { 650338a1281SOctavian Purdila .name = "dln2-i2c", 651338a1281SOctavian Purdila .platform_data = &dln2_pdata_i2c, 652338a1281SOctavian Purdila .pdata_size = sizeof(struct dln2_platform_data), 653338a1281SOctavian Purdila }, 654338a1281SOctavian Purdila }; 655338a1281SOctavian Purdila 656338a1281SOctavian Purdila static void dln2_disconnect(struct usb_interface *interface) 657338a1281SOctavian Purdila { 658338a1281SOctavian Purdila struct dln2_dev *dln2 = usb_get_intfdata(interface); 659338a1281SOctavian Purdila int i, j; 660338a1281SOctavian Purdila 661338a1281SOctavian Purdila /* don't allow starting new transfers */ 662338a1281SOctavian Purdila spin_lock(&dln2->disconnect_lock); 663338a1281SOctavian Purdila dln2->disconnect = true; 664338a1281SOctavian Purdila spin_unlock(&dln2->disconnect_lock); 665338a1281SOctavian Purdila 666338a1281SOctavian Purdila /* cancel in progress transfers */ 667338a1281SOctavian Purdila for (i = 0; i < DLN2_HANDLES; i++) { 668338a1281SOctavian Purdila struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[i]; 669338a1281SOctavian Purdila unsigned long flags; 670338a1281SOctavian Purdila 671338a1281SOctavian Purdila spin_lock_irqsave(&rxs->lock, flags); 672338a1281SOctavian Purdila 673338a1281SOctavian Purdila /* cancel all response waiters */ 674338a1281SOctavian Purdila for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) { 675338a1281SOctavian Purdila struct dln2_rx_context *rxc = &rxs->slots[j]; 676338a1281SOctavian Purdila 677338a1281SOctavian Purdila if (rxc->in_use) 678338a1281SOctavian Purdila complete(&rxc->done); 679338a1281SOctavian Purdila } 680338a1281SOctavian Purdila 681338a1281SOctavian Purdila spin_unlock_irqrestore(&rxs->lock, flags); 682338a1281SOctavian Purdila } 683338a1281SOctavian Purdila 684338a1281SOctavian Purdila /* wait for transfers to end */ 685338a1281SOctavian Purdila wait_event(dln2->disconnect_wq, !dln2->active_transfers); 686338a1281SOctavian Purdila 687338a1281SOctavian Purdila mfd_remove_devices(&interface->dev); 688338a1281SOctavian Purdila 689338a1281SOctavian Purdila dln2_free(dln2); 690338a1281SOctavian Purdila } 691338a1281SOctavian Purdila 692338a1281SOctavian Purdila static int dln2_probe(struct usb_interface *interface, 693338a1281SOctavian Purdila const struct usb_device_id *usb_id) 694338a1281SOctavian Purdila { 695338a1281SOctavian Purdila struct usb_host_interface *hostif = interface->cur_altsetting; 696338a1281SOctavian Purdila struct device *dev = &interface->dev; 697338a1281SOctavian Purdila struct dln2_dev *dln2; 698338a1281SOctavian Purdila int ret; 699338a1281SOctavian Purdila int i, j; 700338a1281SOctavian Purdila 701338a1281SOctavian Purdila if (hostif->desc.bInterfaceNumber != 0 || 702338a1281SOctavian Purdila hostif->desc.bNumEndpoints < 2) 703338a1281SOctavian Purdila return -ENODEV; 704338a1281SOctavian Purdila 705338a1281SOctavian Purdila dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL); 706338a1281SOctavian Purdila if (!dln2) 707338a1281SOctavian Purdila return -ENOMEM; 708338a1281SOctavian Purdila 709338a1281SOctavian Purdila dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress; 710338a1281SOctavian Purdila dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress; 711338a1281SOctavian Purdila dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface)); 712338a1281SOctavian Purdila dln2->interface = interface; 713338a1281SOctavian Purdila usb_set_intfdata(interface, dln2); 714338a1281SOctavian Purdila init_waitqueue_head(&dln2->disconnect_wq); 715338a1281SOctavian Purdila 716338a1281SOctavian Purdila for (i = 0; i < DLN2_HANDLES; i++) { 717338a1281SOctavian Purdila init_waitqueue_head(&dln2->mod_rx_slots[i].wq); 718338a1281SOctavian Purdila spin_lock_init(&dln2->mod_rx_slots[i].lock); 719338a1281SOctavian Purdila for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) 720338a1281SOctavian Purdila init_completion(&dln2->mod_rx_slots[i].slots[j].done); 721338a1281SOctavian Purdila } 722338a1281SOctavian Purdila 723338a1281SOctavian Purdila spin_lock_init(&dln2->event_cb_lock); 724338a1281SOctavian Purdila spin_lock_init(&dln2->disconnect_lock); 725338a1281SOctavian Purdila INIT_LIST_HEAD(&dln2->event_cb_list); 726338a1281SOctavian Purdila 727338a1281SOctavian Purdila ret = dln2_setup_rx_urbs(dln2, hostif); 728338a1281SOctavian Purdila if (ret) 729338a1281SOctavian Purdila goto out_cleanup; 730338a1281SOctavian Purdila 731338a1281SOctavian Purdila ret = dln2_hw_init(dln2); 732338a1281SOctavian Purdila if (ret < 0) { 733338a1281SOctavian Purdila dev_err(dev, "failed to initialize hardware\n"); 734338a1281SOctavian Purdila goto out_cleanup; 735338a1281SOctavian Purdila } 736338a1281SOctavian Purdila 737338a1281SOctavian Purdila ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs)); 738338a1281SOctavian Purdila if (ret != 0) { 739338a1281SOctavian Purdila dev_err(dev, "failed to add mfd devices to core\n"); 740338a1281SOctavian Purdila goto out_cleanup; 741338a1281SOctavian Purdila } 742338a1281SOctavian Purdila 743338a1281SOctavian Purdila return 0; 744338a1281SOctavian Purdila 745338a1281SOctavian Purdila out_cleanup: 746338a1281SOctavian Purdila dln2_free(dln2); 747338a1281SOctavian Purdila 748338a1281SOctavian Purdila return ret; 749338a1281SOctavian Purdila } 750338a1281SOctavian Purdila 751338a1281SOctavian Purdila static const struct usb_device_id dln2_table[] = { 752338a1281SOctavian Purdila { USB_DEVICE(0xa257, 0x2013) }, 753338a1281SOctavian Purdila { } 754338a1281SOctavian Purdila }; 755338a1281SOctavian Purdila 756338a1281SOctavian Purdila MODULE_DEVICE_TABLE(usb, dln2_table); 757338a1281SOctavian Purdila 758338a1281SOctavian Purdila static struct usb_driver dln2_driver = { 759338a1281SOctavian Purdila .name = "dln2", 760338a1281SOctavian Purdila .probe = dln2_probe, 761338a1281SOctavian Purdila .disconnect = dln2_disconnect, 762338a1281SOctavian Purdila .id_table = dln2_table, 763338a1281SOctavian Purdila }; 764338a1281SOctavian Purdila 765338a1281SOctavian Purdila module_usb_driver(dln2_driver); 766338a1281SOctavian Purdila 767338a1281SOctavian Purdila MODULE_AUTHOR("Octavian Purdila <octavian.purdila@intel.com>"); 768338a1281SOctavian Purdila MODULE_DESCRIPTION("Core driver for the Diolan DLN2 interface adapter"); 769338a1281SOctavian Purdila MODULE_LICENSE("GPL v2"); 770