blob: 609b7cc66768ff81a6fa8dafafb812bd659ae02a [file] [log] [blame]
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -08001/*
2 * USB host driver for the Greybus "generic" USB module.
3 *
4 * Copyright 2014 Google Inc.
Alex Eldera46e9672014-12-12 12:08:42 -06005 * Copyright 2014 Linaro Ltd.
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -08006 *
7 * Released under the GPLv2 only.
8 *
9 */
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/slab.h>
13#include <linux/usb.h>
14#include <linux/usb/hcd.h>
15
16#include "greybus.h"
17
18/* Version of the Greybus USB protocol we support */
19#define GB_USB_VERSION_MAJOR 0x00
20#define GB_USB_VERSION_MINOR 0x01
21
22/* Greybus USB request types */
23#define GB_USB_TYPE_INVALID 0x00
24#define GB_USB_TYPE_PROTOCOL_VERSION 0x01
25#define GB_USB_TYPE_HCD_STOP 0x02
26#define GB_USB_TYPE_HCD_START 0x03
27#define GB_USB_TYPE_URB_ENQUEUE 0x04
28#define GB_USB_TYPE_URB_DEQUEUE 0x05
29#define GB_USB_TYPE_ENDPOINT_DISABLE 0x06
30#define GB_USB_TYPE_HUB_CONTROL 0x07
31#define GB_USB_TYPE_GET_FRAME_NUMBER 0x08
32#define GB_USB_TYPE_HUB_STATUS_DATA 0x09
33
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -080034struct gb_usb_urb_enqueue_request {
35 __le32 pipe;
36 __le32 transfer_flags;
37 __le32 transfer_buffer_length;
38 __le32 maxpacket;
39 __le32 interval;
40 __le64 hcpriv_ep;
41 __le32 number_of_packets;
42 u8 setup_packet[8];
43 u8 payload[0];
44};
45
46struct gb_usb_urb_dequeue_request {
47 __le64 hcpriv_ep;
48};
49
50struct gb_usb_endpoint_disable_request {
51 __le64 hcpriv;
52};
53
54struct gb_usb_hub_control_request {
55 __le16 typeReq;
56 __le16 wValue;
57 __le16 wIndex;
58 __le16 wLength;
59};
60
61struct gb_usb_hub_control_response {
62 u8 buf[0];
63};
64
65struct gb_usb_header {
66 __le16 size;
67 __le16 id;
68 __u8 type;
69};
70
71struct gb_usb_hub_status {
72 __le32 status;
73 __le16 buf_size;
74 u8 buf[0];
75};
76
77static struct gb_usb_hub_status *hub_status; // FIXME!!!
78static DEFINE_SPINLOCK(hub_status_lock);
79static atomic_t frame_number; // FIXME!!!
80
81struct gb_usb_device {
82 struct gb_connection *connection;
83
84 struct usb_hcd *hcd;
85 u8 version_major;
86 u8 version_minor;
87};
88
89#define to_gb_usb_device(d) ((struct gb_usb_device*) d->hcd_priv)
90
Viresh Kumar36e79de2015-01-21 18:12:36 +053091/* Define get_version() routine */
92define_get_version(gb_usb_device, USB);
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -080093
94static void hcd_stop(struct usb_hcd *hcd)
95{
96 struct gb_usb_device *dev = to_gb_usb_device(hcd);
97 int ret;
98
99 ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_STOP,
100 NULL, 0, NULL, 0);
101 if (ret)
102 dev_err(&dev->connection->dev, "HCD stop failed '%d'\n", ret);
103}
104
105static int hcd_start(struct usb_hcd *hcd)
106{
107 struct usb_bus *bus = hcd_to_bus(hcd);
108 struct gb_usb_device *dev = to_gb_usb_device(hcd);
109 int ret;
110
111 ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HCD_START,
112 NULL, 0, NULL, 0);
113 if (ret) {
114 dev_err(&dev->connection->dev, "HCD start failed '%d'\n", ret);
115 return ret;
116 }
117
118 hcd->state = HC_STATE_RUNNING;
119 if (bus->root_hub)
120 usb_hcd_resume_root_hub(hcd);
121 return 0;
122}
123
124static int urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
125{
126 struct gb_usb_device *dev = to_gb_usb_device(hcd);
127 struct gb_usb_urb_enqueue_request *request;
128 struct gb_operation *operation;
129 int ret;
130
131 operation = gb_operation_create(dev->connection,
132 GB_USB_TYPE_URB_ENQUEUE,
133 sizeof(*request) +
134 urb->transfer_buffer_length, 0);
135 if (!operation)
136 return -ENODEV;
137
138 request = operation->request->payload;
139 request->pipe = cpu_to_le32(urb->pipe);
140 request->transfer_flags = cpu_to_le32(urb->transfer_flags);
141 request->transfer_buffer_length = cpu_to_le32(urb->transfer_buffer_length);
142 request->interval = cpu_to_le32(urb->interval);
Johan Hovoldc020d562015-03-19 16:46:13 +0100143 request->hcpriv_ep = cpu_to_le64((unsigned long)urb->ep->hcpriv);
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -0800144 request->number_of_packets = cpu_to_le32(urb->number_of_packets);
145
146 memcpy(request->setup_packet, urb->setup_packet, 8);
147 memcpy(&request->payload, urb->transfer_buffer,
148 urb->transfer_buffer_length);
149
Alex Elderc25572c2014-12-03 08:35:09 -0600150 ret = gb_operation_request_send_sync(operation);
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -0800151 gb_operation_destroy(operation);
152
153 return ret;
154}
155
156static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
157{
158 struct gb_usb_device *dev = to_gb_usb_device(hcd);
159 struct gb_usb_urb_dequeue_request request;
160 int ret;
161
162 urb->ep->hcpriv = NULL;
Johan Hovoldc020d562015-03-19 16:46:13 +0100163 request.hcpriv_ep = cpu_to_le64((unsigned long)urb->hcpriv);
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -0800164 ret = gb_operation_sync(dev->connection, GB_USB_TYPE_URB_DEQUEUE,
165 &request, sizeof(request), NULL, 0);
166 urb->hcpriv = NULL;
167 return ret;
168}
169
170static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
171{
172 struct gb_usb_device *dev = to_gb_usb_device(hcd);
173 struct gb_usb_endpoint_disable_request request;
174 int ret;
175
Johan Hovoldc020d562015-03-19 16:46:13 +0100176 request.hcpriv = cpu_to_le64((unsigned long)ep->hcpriv);
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -0800177 ret = gb_operation_sync(dev->connection, GB_USB_TYPE_ENDPOINT_DISABLE,
178 &request, sizeof(request), NULL, 0);
179 ep->hcpriv = NULL;
180}
181
182static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
183{
184}
185
186static int get_frame_number(struct usb_hcd *hcd)
187{
188 return atomic_read(&frame_number);
189}
190
191static int hub_status_data(struct usb_hcd *hcd, char *buf)
192{
193 int retval;
194 unsigned long flags;
195
196 spin_lock_irqsave(&hub_status_lock, flags);
197 memcpy(buf, hub_status->buf, le16_to_cpu(hub_status->buf_size));
198 retval = le32_to_cpu(hub_status->status);
199 spin_unlock_irqrestore(&hub_status_lock, flags);
200
201 return retval;
202}
203
204static int hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
205 char *buf, u16 wLength)
206{
207 struct gb_usb_hub_control_request request;
208 struct gb_usb_device *dev = to_gb_usb_device(hcd);
209 int ret;
210
211 request.typeReq = cpu_to_le16(typeReq);
212 request.wValue = cpu_to_le16(wValue);
213 request.wIndex = cpu_to_le16(wIndex);
214 request.wLength = cpu_to_le16(wLength);
215
216 // FIXME - buf needs to come back in struct gb_usb_hub_control_response
217 // for some types of requests, depending on typeReq. Do we do this in a
218 // "generic" way, or only ask for a response for the ones we "know" need
219 // a response (a small subset of all valid typeReq, thankfully.)
220 ret = gb_operation_sync(dev->connection, GB_USB_TYPE_HUB_CONTROL,
221 &request, sizeof(request), NULL, 0);
222
223 return ret;
224}
225
226static struct hc_driver usb_gb_hc_driver = {
227 .description = "greybus_usb",
228 .product_desc = "GB-Bridge USB Controller", /* TODO: Get this from GPB ?*/
229 .flags = HCD_MEMORY | HCD_USB2, /* FIXME: Get this from GPB */
230 .hcd_priv_size = sizeof(struct gb_usb_device),
231
232 .start = hcd_start,
233 .stop = hcd_stop,
234 .urb_enqueue = urb_enqueue,
235 .urb_dequeue = urb_dequeue,
236 .endpoint_disable = endpoint_disable,
237 .endpoint_reset = endpoint_reset,
238 .get_frame_number = get_frame_number,
239 .hub_status_data = hub_status_data,
240 .hub_control = hub_control,
241};
242
243#if 0
244static inline void gb_usb_handle_get_frame_number(struct gbuf *gbuf)
245{
246 __le32 frame_num;
247 const size_t packet_size = sizeof(struct gb_usb_header) +
248 sizeof(frame_num);
249 struct gb_usb_header* hdr = gbuf->transfer_buffer;
250
251 if (le16_to_cpu(hdr->size) != packet_size) {
252 pr_err("%s(): dropping packet too small\n", __func__);
253 return;
254 }
255
256 frame_num = (__le32) ((char*) gbuf->transfer_buffer +
257 sizeof(struct gb_usb_header));
258 atomic_set(&frame_number, le32_to_cpu(frame_num));
259}
260
261static inline void gb_usb_handle_hubs_status_data(struct gbuf *gbuf)
262{
263 struct gb_usb_hub_status *new_hubstatus, *hubstatus;
264 struct gb_usb_header* hdr = gbuf->transfer_buffer;
265 const size_t min_packet_size = sizeof(struct gb_usb_header) +
266 sizeof(struct gb_usb_hub_status);
267 unsigned long flags;
268
269 if (le16_to_cpu(hdr->size) < min_packet_size) {
270 pr_err("%s(): dropping packet too small\n", __func__);
271 return;
272 }
273
274 hubstatus = (struct gb_usb_hub_status*) ((char*) gbuf->transfer_buffer
275 + sizeof(struct gb_usb_header));
276
277 if (le16_to_cpu(hdr->size) != min_packet_size + hubstatus->buf_size) {
278 pr_err("%s(): invalid packet size, dropping packet\n",
279 __func__);
280 return;
281 }
282
283 new_hubstatus = kmalloc(hubstatus->buf_size, GFP_KERNEL);
284 memcpy(&new_hubstatus, hubstatus, hubstatus->buf_size);
285
286 spin_lock_irqsave(&hub_status_lock, flags);
287 hubstatus = hub_status;
288 hub_status = new_hubstatus;
289 spin_unlock_irqrestore(&hub_status_lock, flags);
290
291 kfree(hubstatus);
292}
293
294static void gb_usb_in_handler(struct gbuf *gbuf)
295{
296 struct gb_usb_header* hdr = gbuf->transfer_buffer;
297
298 switch (hdr->type) {
299 case GB_USB_TYPE_GET_FRAME_NUMBER:
300 gb_usb_handle_get_frame_number(gbuf);
301 break;
302
303 case GB_USB_TYPE_HUB_STATUS_DATA:
304 gb_usb_handle_hubs_status_data(gbuf);
305 break;
306 }
307}
308#endif
309
310static int gb_usb_connection_init(struct gb_connection *connection)
311{
312 struct device *dev = &connection->dev;
313 struct gb_usb_device *gb_usb_dev;
314
315 int retval;
316
317 gb_usb_dev = kzalloc(sizeof(*gb_usb_dev), GFP_KERNEL);
318 if (!gb_usb_dev)
319 return -ENOMEM;
320
321 gb_usb_dev->connection = connection;
Alex Elder93bbe852014-12-03 12:27:42 -0600322 connection->private = gb_usb_dev;
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -0800323
324 /* Check for compatible protocol version */
325 retval = get_version(gb_usb_dev);
326 if (retval)
327 goto error_create_hcd;
328
329 gb_usb_dev->hcd = usb_create_hcd(&usb_gb_hc_driver, dev, dev_name(dev));
330 if (!gb_usb_dev->hcd) {
331 retval = -ENODEV;
332 goto error_create_hcd;
333 }
334
335 gb_usb_dev->hcd->has_tt = 1;
336 gb_usb_dev->hcd->hcd_priv[0] = (unsigned long) gb_usb_dev;
337
338 retval = usb_add_hcd(gb_usb_dev->hcd, 0, 0);
339 if (retval)
340 goto error_add_hcd;
341
342 return 0;
343error_add_hcd:
344 usb_put_hcd(gb_usb_dev->hcd);
345error_create_hcd:
346 kfree(gb_usb_dev);
347 return retval;
348}
349
350static void gb_usb_connection_exit(struct gb_connection *connection)
351{
352 // FIXME - tear everything down!
353}
354
355static struct gb_protocol usb_protocol = {
Greg Kroah-Hartman7422a1e2014-12-24 13:01:45 -0800356 .name = "usb",
Greg Kroah-Hartman615772a2014-11-25 16:59:21 -0800357 .id = GREYBUS_PROTOCOL_USB,
358 .major = 0,
359 .minor = 1,
360 .connection_init = gb_usb_connection_init,
361 .connection_exit = gb_usb_connection_exit,
362 .request_recv = NULL, /* FIXME we have requests!!! */
363};
364
Viresh Kumarbdac5992015-05-20 17:20:10 +0530365gb_gpbridge_protocol_driver(usb_protocol);