xref: /openbmc/linux/drivers/mfd/dln2.c (revision 00ee7a37)
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