blob: a0cdde26aae9dbaeaff7c7afb246482b0930680c [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * u_sdio.c - utilities for USB gadget serial over sdio
3 *
4 * This code also borrows from drivers/usb/gadget/u_serial.c, which is
5 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
6 * Copyright (C) 2008 David Brownell
7 * Copyright (C) 2008 by Nokia Corporation
Duy Truong790f06d2013-02-13 16:38:12 -08008 * Copyright (c) 2011, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07009 *
Duy Truong5beda042013-02-13 07:41:45 -070010 * This program from The Linux Foundation is free software; you can
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070011 * redistribute it and/or modify it under the GNU General Public License
12 * version 2 and only version 2 as published by the Free Software Foundation.
13 * The original work available from [kernel.org] is subject to the notice below.
14 *
15 * This software is distributed under the terms of the GNU General
16 * Public License ("GPL") as published by the Free Software Foundation,
17 * either version 2 of that License or (at your option) any later version.
18 *
19 */
20
21#include <linux/kernel.h>
22#include <linux/interrupt.h>
23#include <linux/device.h>
24#include <linux/delay.h>
25#include <linux/slab.h>
26#include <linux/termios.h>
27#include <linux/debugfs.h>
28
29#include <mach/sdio_al.h>
30#include <mach/sdio_cmux.h>
31#include "u_serial.h"
32
33#define SDIO_RX_QUEUE_SIZE 8
34#define SDIO_RX_BUF_SIZE 2048
35
36#define SDIO_TX_QUEUE_SIZE 8
37#define SDIO_TX_BUF_SIZE 2048
38
39/* 1 - DUN, 2-NMEA/GPS */
40#define SDIO_N_PORTS 2
41static struct sdio_portmaster {
42 struct mutex lock;
43 struct gsdio_port *port;
44 struct platform_driver gsdio_ch;
45} sdio_ports[SDIO_N_PORTS];
46static unsigned n_sdio_ports;
47
48struct sdio_port_info {
49 /* data channel info */
50 char *data_ch_name;
51 struct sdio_channel *ch;
52
53 /* control channel info */
54 int ctrl_ch_id;
55};
56
57struct sdio_port_info sport_info[SDIO_N_PORTS] = {
58 {
59 .data_ch_name = "SDIO_DUN",
60 .ctrl_ch_id = 9,
61 },
62 {
63 .data_ch_name = "SDIO_NMEA",
64 .ctrl_ch_id = 10,
65 },
66};
67
68static struct workqueue_struct *gsdio_wq;
69
70struct gsdio_port {
71 unsigned port_num;
72 spinlock_t port_lock;
73
74 unsigned n_read;
75 struct list_head read_pool;
76 struct list_head read_queue;
77 struct work_struct push;
78 unsigned long rp_len;
79 unsigned long rq_len;
80
81 struct list_head write_pool;
82 struct work_struct pull;
83 unsigned long wp_len;
84
85 struct work_struct notify_modem;
86
87 struct gserial *port_usb;
88 struct usb_cdc_line_coding line_coding;
89
90 int sdio_open;
Vamsi Krishnaec632262011-07-14 15:49:05 -070091 int sdio_probe;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092 int ctrl_ch_err;
93 struct sdio_port_info *sport_info;
94 struct delayed_work sdio_open_work;
95
96#define SDIO_ACM_CTRL_RI (1 << 3)
97#define SDIO_ACM_CTRL_DSR (1 << 1)
98#define SDIO_ACM_CTRL_DCD (1 << 0)
99 int cbits_to_laptop;
100
101#define SDIO_ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
102#define SDIO_ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
103 int cbits_to_modem;
104
105 /* pkt logging */
106 unsigned long nbytes_tolaptop;
107 unsigned long nbytes_tomodem;
108};
109
110void gsdio_free_req(struct usb_ep *ep, struct usb_request *req)
111{
112 kfree(req->buf);
113 usb_ep_free_request(ep, req);
114}
115
116struct usb_request *
117gsdio_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags)
118{
119 struct usb_request *req;
120
121 req = usb_ep_alloc_request(ep, flags);
122 if (!req) {
123 pr_err("%s: usb alloc request failed\n", __func__);
124 return NULL;
125 }
126
127 req->length = len;
128 req->buf = kmalloc(len, flags);
129 if (!req->buf) {
130 pr_err("%s: request buf allocation failed\n", __func__);
131 usb_ep_free_request(ep, req);
132 return NULL;
133 }
134
135 return req;
136}
137
138void gsdio_free_requests(struct usb_ep *ep, struct list_head *head)
139{
140 struct usb_request *req;
141
142 while (!list_empty(head)) {
143 req = list_entry(head->next, struct usb_request, list);
144 list_del(&req->list);
145 gsdio_free_req(ep, req);
146 }
147}
148
149int gsdio_alloc_requests(struct usb_ep *ep, struct list_head *head,
150 int num, int size,
151 void (*cb)(struct usb_ep *ep, struct usb_request *))
152{
153 int i;
154 struct usb_request *req;
155
156 pr_debug("%s: ep:%p head:%p num:%d size:%d cb:%p", __func__,
157 ep, head, num, size, cb);
158
159 for (i = 0; i < num; i++) {
160 req = gsdio_alloc_req(ep, size, GFP_ATOMIC);
161 if (!req) {
162 pr_debug("%s: req allocated:%d\n", __func__, i);
163 return list_empty(head) ? -ENOMEM : 0;
164 }
165 req->complete = cb;
166 list_add(&req->list, head);
167 }
168
169 return 0;
170}
171
172void gsdio_start_rx(struct gsdio_port *port)
173{
174 struct list_head *pool;
175 struct usb_ep *out;
176 int ret;
177
178 if (!port) {
179 pr_err("%s: port is null\n", __func__);
180 return;
181 }
182
183 pr_debug("%s: port:%p port#%d\n", __func__, port, port->port_num);
184
185 spin_lock_irq(&port->port_lock);
186
187 if (!port->port_usb) {
188 pr_debug("%s: usb is disconnected\n", __func__);
189 goto start_rx_end;
190 }
191
Vamsi Krishnaec632262011-07-14 15:49:05 -0700192 if (!port->sdio_open) {
193 pr_debug("%s: sdio is not open\n", __func__);
194 goto start_rx_end;
195 }
196
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700197 pool = &port->read_pool;
198 out = port->port_usb->out;
199
200 while (!list_empty(pool)) {
201 struct usb_request *req;
202
203 req = list_entry(pool->next, struct usb_request, list);
204 list_del(&req->list);
205 req->length = SDIO_RX_BUF_SIZE;
206 port->rp_len--;
207
208 spin_unlock_irq(&port->port_lock);
209 ret = usb_ep_queue(out, req, GFP_ATOMIC);
210 spin_lock_irq(&port->port_lock);
211 if (ret) {
212 pr_err("%s: usb ep out queue failed"
213 "port:%p, port#%d\n",
214 __func__, port, port->port_num);
215 list_add_tail(&req->list, pool);
216 port->rp_len++;
217 break;
218 }
219
220 /* usb could have disconnected while we released spin lock */
221 if (!port->port_usb) {
222 pr_debug("%s: usb is disconnected\n", __func__);
223 goto start_rx_end;
224 }
225 }
226
227start_rx_end:
228 spin_unlock_irq(&port->port_lock);
229}
230
231int gsdio_write(struct gsdio_port *port, struct usb_request *req)
232{
233 unsigned avail;
Vamsi Krishnab015f0c2012-03-16 14:14:41 -0700234 char *packet;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700235 unsigned size = req->actual;
236 unsigned n;
237 int ret = 0;
238
239
240 if (!port) {
241 pr_err("%s: port is null\n", __func__);
242 return -ENODEV;
243 }
244
245 if (!req) {
246 pr_err("%s: usb request is null port#%d\n",
247 __func__, port->port_num);
248 return -ENODEV;
249 }
250
251 pr_debug("%s: port:%p port#%d req:%p actual:%d n_read:%d\n",
252 __func__, port, port->port_num, req,
253 req->actual, port->n_read);
254
255 if (!port->sdio_open) {
256 pr_debug("%s: SDIO IO is not supported\n", __func__);
257 return -ENODEV;
258 }
259
260 avail = sdio_write_avail(port->sport_info->ch);
261
262 pr_debug("%s: sdio_write_avail:%d", __func__, avail);
263
264 if (!avail)
265 return -EBUSY;
266
267 if (!req->actual) {
268 pr_debug("%s: req->actual is already zero,update bytes read\n",
269 __func__);
270 port->n_read = 0;
271 return -ENODEV;
272 }
273
274 packet = req->buf;
275 n = port->n_read;
276 if (n) {
277 packet += n;
278 size -= n;
279 }
280
281 if (size > avail)
282 size = avail;
283
284 spin_unlock_irq(&port->port_lock);
285 ret = sdio_write(port->sport_info->ch, packet, size);
286 spin_lock_irq(&port->port_lock);
287 if (ret) {
288 pr_err("%s: port#%d sdio write failed err:%d",
289 __func__, port->port_num, ret);
290 /* try again later */
291 return ret;
292 }
293
294 port->nbytes_tomodem += size;
295
296 if (size + n == req->actual)
297 port->n_read = 0;
298 else
299 port->n_read += size;
300
301 return ret;
302}
303
304void gsdio_rx_push(struct work_struct *w)
305{
306 struct gsdio_port *port = container_of(w, struct gsdio_port, push);
307 struct list_head *q = &port->read_queue;
308 struct usb_ep *out;
309 int ret;
310
311 pr_debug("%s: port:%p port#%d read_queue:%p", __func__,
312 port, port->port_num, q);
313
314 spin_lock_irq(&port->port_lock);
315
316 if (!port->port_usb) {
317 pr_debug("%s: usb cable is disconencted\n", __func__);
318 spin_unlock_irq(&port->port_lock);
319 return;
320 }
321
322 out = port->port_usb->out;
323
324 while (!list_empty(q)) {
325 struct usb_request *req;
326
327 req = list_first_entry(q, struct usb_request, list);
328
329 switch (req->status) {
330 case -ESHUTDOWN:
331 pr_debug("%s: req status shutdown portno#%d port:%p",
332 __func__, port->port_num, port);
333 goto rx_push_end;
334 default:
335 pr_warning("%s: port:%p port#%d"
336 " Unexpected Rx Status:%d\n", __func__,
337 port, port->port_num, req->status);
338 /* FALL THROUGH */
339 case 0:
340 /* normal completion */
341 break;
342 }
343
344 if (!port->sdio_open) {
345 pr_err("%s: sio channel is not open\n", __func__);
346 list_move(&req->list, &port->read_pool);
347 port->rp_len++;
348 port->rq_len--;
349 goto rx_push_end;
350 }
351
352
353 list_del(&req->list);
354 port->rq_len--;
355
356 ret = gsdio_write(port, req);
357 /* as gsdio_write drops spin_lock while writing data
358 * to sdio usb cable may have been disconnected
359 */
360 if (!port->port_usb) {
361 port->n_read = 0;
362 gsdio_free_req(out, req);
363 spin_unlock_irq(&port->port_lock);
364 return;
365 }
366
367 if (ret || port->n_read) {
368 list_add(&req->list, &port->read_queue);
369 port->rq_len++;
370 goto rx_push_end;
371 }
372
373 list_add(&req->list, &port->read_pool);
374 port->rp_len++;
375 }
376
377 if (port->sdio_open && !list_empty(q)) {
378 if (sdio_write_avail(port->sport_info->ch))
379 queue_work(gsdio_wq, &port->push);
380 }
381rx_push_end:
382 spin_unlock_irq(&port->port_lock);
383
384 /* start queuing out requests again to host */
385 gsdio_start_rx(port);
386}
387
388void gsdio_read_complete(struct usb_ep *ep, struct usb_request *req)
389{
390 struct gsdio_port *port = ep->driver_data;
391 unsigned long flags;
392
393 pr_debug("%s: ep:%p port:%p\n", __func__, ep, port);
394
395 if (!port) {
396 pr_err("%s: port is null\n", __func__);
397 return;
398 }
399
400 spin_lock_irqsave(&port->port_lock, flags);
401 list_add_tail(&req->list, &port->read_queue);
402 port->rq_len++;
403 queue_work(gsdio_wq, &port->push);
404 spin_unlock_irqrestore(&port->port_lock, flags);
405
406 return;
407}
408
409void gsdio_write_complete(struct usb_ep *ep, struct usb_request *req)
410{
411 struct gsdio_port *port = ep->driver_data;
412 unsigned long flags;
413
414 pr_debug("%s: ep:%p port:%p\n", __func__, ep, port);
415
416 if (!port) {
417 pr_err("%s: port is null\n", __func__);
418 return;
419 }
420
421 spin_lock_irqsave(&port->port_lock, flags);
422 list_add(&req->list, &port->write_pool);
423 port->wp_len++;
424
425 switch (req->status) {
426 default:
427 pr_warning("%s: port:%p port#%d unexpected %s status %d\n",
428 __func__, port, port->port_num,
429 ep->name, req->status);
430 /* FALL THROUGH */
431 case 0:
432 queue_work(gsdio_wq, &port->pull);
433 break;
434
435 case -ESHUTDOWN:
436 /* disconnect */
437 pr_debug("%s: %s shutdown\n", __func__, ep->name);
438 break;
439 }
440
441 spin_unlock_irqrestore(&port->port_lock, flags);
442
443 return;
444}
445
446void gsdio_read_pending(struct gsdio_port *port)
447{
448 struct sdio_channel *ch;
449 char buf[1024];
450 int avail;
451
452 if (!port) {
453 pr_err("%s: port is null\n", __func__);
454 return;
455 }
456
457 ch = port->sport_info->ch;
458
459 if (!ch)
460 return;
461
462 while ((avail = sdio_read_avail(ch))) {
463 if (avail > 1024)
464 avail = 1024;
465 sdio_read(ch, buf, avail);
466
467 pr_debug("%s: flushed out %d bytes\n", __func__, avail);
468 }
469}
470
471void gsdio_tx_pull(struct work_struct *w)
472{
473 struct gsdio_port *port = container_of(w, struct gsdio_port, pull);
474 struct list_head *pool = &port->write_pool;
475
476 pr_debug("%s: port:%p port#%d pool:%p\n", __func__,
477 port, port->port_num, pool);
478
479 if (!port->port_usb) {
480 pr_err("%s: usb disconnected\n", __func__);
481
482 /* take out all the pending data from sdio */
483 gsdio_read_pending(port);
484
485 return;
486 }
487
488 spin_lock_irq(&port->port_lock);
489
490 while (!list_empty(pool)) {
491 int avail;
492 struct usb_ep *in = port->port_usb->in;
493 struct sdio_channel *ch = port->sport_info->ch;
494 struct usb_request *req;
495 unsigned len = SDIO_TX_BUF_SIZE;
496 int ret;
497
498
499 req = list_entry(pool->next, struct usb_request, list);
500
501 if (!port->sdio_open) {
502 pr_debug("%s: SDIO channel is not open\n", __func__);
503 goto tx_pull_end;
504 }
505
506 avail = sdio_read_avail(ch);
507 if (!avail) {
508 /* REVISIT: for ZLP */
509 pr_debug("%s: read_avail:%d port:%p port#%d\n",
510 __func__, avail, port, port->port_num);
511 goto tx_pull_end;
512 }
513
514 if (avail > len)
515 avail = len;
516
517 list_del(&req->list);
518 port->wp_len--;
519
520 spin_unlock_irq(&port->port_lock);
521 ret = sdio_read(ch, req->buf, avail);
522 spin_lock_irq(&port->port_lock);
523 if (ret) {
524 pr_err("%s: port:%p port#%d sdio read failed err:%d",
525 __func__, port, port->port_num, ret);
526
527 /* check if usb is still active */
528 if (!port->port_usb) {
529 gsdio_free_req(in, req);
530 } else {
531 list_add(&req->list, pool);
532 port->wp_len++;
533 }
534 goto tx_pull_end;
535 }
536
537 req->length = avail;
538
539 spin_unlock_irq(&port->port_lock);
540 ret = usb_ep_queue(in, req, GFP_KERNEL);
541 spin_lock_irq(&port->port_lock);
542 if (ret) {
543 pr_err("%s: usb ep out queue failed"
544 "port:%p, port#%d err:%d\n",
545 __func__, port, port->port_num, ret);
546
547 /* could be usb disconnected */
548 if (!port->port_usb) {
549 gsdio_free_req(in, req);
550 } else {
551 list_add(&req->list, pool);
552 port->wp_len++;
553 }
554 goto tx_pull_end;
555 }
556
557 port->nbytes_tolaptop += avail;
558 }
559tx_pull_end:
560 spin_unlock_irq(&port->port_lock);
561}
562
563int gsdio_start_io(struct gsdio_port *port)
564{
565 int ret;
566 unsigned long flags;
567
568 pr_debug("%s:\n", __func__);
569
570 spin_lock_irqsave(&port->port_lock, flags);
571
572 if (!port->port_usb) {
573 spin_unlock_irqrestore(&port->port_lock, flags);
574 return -ENODEV;
575 }
576
577 /* start usb out queue */
578 ret = gsdio_alloc_requests(port->port_usb->out,
579 &port->read_pool,
580 SDIO_RX_QUEUE_SIZE, SDIO_RX_BUF_SIZE,
581 gsdio_read_complete);
582 if (ret) {
583 spin_unlock_irqrestore(&port->port_lock, flags);
584 pr_err("%s: unable to allocate out reqs\n", __func__);
585 return ret;
586 }
587 port->rp_len = SDIO_RX_QUEUE_SIZE;
588
589 ret = gsdio_alloc_requests(port->port_usb->in,
590 &port->write_pool,
591 SDIO_TX_QUEUE_SIZE, SDIO_TX_BUF_SIZE,
592 gsdio_write_complete);
593 if (ret) {
594 gsdio_free_requests(port->port_usb->out, &port->read_pool);
595 port->rp_len = 0;
596 spin_unlock_irqrestore(&port->port_lock, flags);
597 pr_err("%s: unable to allocate in reqs\n", __func__);
598 return ret;
599 }
600 port->wp_len = SDIO_TX_QUEUE_SIZE;
601 spin_unlock_irqrestore(&port->port_lock, flags);
602
603 gsdio_start_rx(port);
604 queue_work(gsdio_wq, &port->pull);
605
606 return 0;
607}
608
609void gsdio_port_free(unsigned portno)
610{
611 struct gsdio_port *port = sdio_ports[portno].port;
612 struct platform_driver *pdriver = &sdio_ports[portno].gsdio_ch;
613
614 if (!port) {
615 pr_err("%s: invalid portno#%d\n", __func__, portno);
616 return;
617 }
618
619 platform_driver_unregister(pdriver);
620
621 kfree(port);
622}
623
624void gsdio_ctrl_wq(struct work_struct *w)
625{
626 struct gsdio_port *port;
627
628 port = container_of(w, struct gsdio_port, notify_modem);
629
630 if (!port) {
631 pr_err("%s: port is null\n", __func__);
632 return;
633 }
634
635 if (!port->sdio_open || port->ctrl_ch_err)
636 return;
637
638 sdio_cmux_tiocmset(port->sport_info->ctrl_ch_id,
639 port->cbits_to_modem, ~(port->cbits_to_modem));
640}
641
Hemant Kumarf60c0252011-11-03 12:37:07 -0700642void gsdio_ctrl_notify_modem(void *gptr, u8 portno, int ctrl_bits)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700643{
644 struct gsdio_port *port;
645 int temp;
Hemant Kumarf60c0252011-11-03 12:37:07 -0700646 struct gserial *gser = gptr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700647
648 if (portno >= n_sdio_ports) {
649 pr_err("%s: invalid portno#%d\n", __func__, portno);
650 return;
651 }
652
653 if (!gser) {
654 pr_err("%s: gser is null\n", __func__);
655 return;
656 }
657
658 port = sdio_ports[portno].port;
659
660 temp = ctrl_bits & SDIO_ACM_CTRL_DTR ? TIOCM_DTR : 0;
661
662 if (port->cbits_to_modem == temp)
663 return;
664
665 port->cbits_to_modem = temp;
666
667 /* TIOCM_DTR - 0x002 - bit(1) */
668 pr_debug("%s: port:%p port#%d ctrl_bits:%08x\n", __func__,
669 port, port->port_num, ctrl_bits);
670
671 if (!port->sdio_open) {
672 pr_err("%s: port:%p port#%d sdio not connected\n",
673 __func__, port, port->port_num);
674 return;
675 }
676
677 /* whenever DTR is high let laptop know that modem status */
678 if (port->cbits_to_modem && gser->send_modem_ctrl_bits)
679 gser->send_modem_ctrl_bits(gser, port->cbits_to_laptop);
680
681 queue_work(gsdio_wq, &port->notify_modem);
682}
683
684void gsdio_ctrl_modem_status(int ctrl_bits, void *_dev)
685{
686 struct gsdio_port *port = _dev;
687
688 /* TIOCM_CD - 0x040 - bit(6)
689 * TIOCM_RI - 0x080 - bit(7)
690 * TIOCM_DSR- 0x100 - bit(8)
691 */
692 pr_debug("%s: port:%p port#%d event:%08x\n", __func__,
693 port, port->port_num, ctrl_bits);
694
695 port->cbits_to_laptop = 0;
696 ctrl_bits &= TIOCM_RI | TIOCM_CD | TIOCM_DSR;
697 if (ctrl_bits & TIOCM_RI)
698 port->cbits_to_laptop |= SDIO_ACM_CTRL_RI;
699 if (ctrl_bits & TIOCM_CD)
700 port->cbits_to_laptop |= SDIO_ACM_CTRL_DCD;
701 if (ctrl_bits & TIOCM_DSR)
702 port->cbits_to_laptop |= SDIO_ACM_CTRL_DSR;
703
704 if (port->port_usb && port->port_usb->send_modem_ctrl_bits)
705 port->port_usb->send_modem_ctrl_bits(port->port_usb,
706 port->cbits_to_laptop);
707}
708
709void gsdio_ch_notify(void *_dev, unsigned event)
710{
711 struct gsdio_port *port = _dev;
712
713 pr_debug("%s: port:%p port#%d event:%s\n", __func__,
714 port, port->port_num,
715 event == 1 ? "READ AVAIL" : "WRITE_AVAIL");
716
717 if (event == SDIO_EVENT_DATA_WRITE_AVAIL)
718 queue_work(gsdio_wq, &port->push);
719 if (event == SDIO_EVENT_DATA_READ_AVAIL)
720 queue_work(gsdio_wq, &port->pull);
721}
722
723static void gsdio_open_work(struct work_struct *w)
724{
725 struct gsdio_port *port =
726 container_of(w, struct gsdio_port, sdio_open_work.work);
727 struct sdio_port_info *pi = port->sport_info;
728 struct gserial *gser;
729 int ret;
730 int ctrl_bits;
731 int startio;
732
733 ret = sdio_open(pi->data_ch_name, &pi->ch, port, gsdio_ch_notify);
734 if (ret) {
735 pr_err("%s: port:%p port#%d unable to open sdio ch:%s\n",
736 __func__, port, port->port_num,
737 pi->data_ch_name);
738 return;
739 }
740
Vamsi Krishnaec632262011-07-14 15:49:05 -0700741 port->ctrl_ch_err = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742 ret = sdio_cmux_open(pi->ctrl_ch_id, 0, 0,
743 gsdio_ctrl_modem_status, port);
744 if (ret) {
745 pr_err("%s: port:%p port#%d unable to open ctrl ch:%d\n",
746 __func__, port, port->port_num, pi->ctrl_ch_id);
747 port->ctrl_ch_err = 1;
748 }
749
750 /* check for latest status update from modem */
751 if (!port->ctrl_ch_err) {
752 ctrl_bits = sdio_cmux_tiocmget(pi->ctrl_ch_id);
753 gsdio_ctrl_modem_status(ctrl_bits, port);
754 }
755
756 pr_debug("%s: SDIO data:%s ctrl:%d are open\n", __func__,
757 pi->data_ch_name,
758 pi->ctrl_ch_id);
759
760 port->sdio_open = 1;
761
762 /* start tx if usb is open already */
763 spin_lock_irq(&port->port_lock);
764 startio = port->port_usb ? 1 : 0;
765 gser = port->port_usb;
766 spin_unlock_irq(&port->port_lock);
767
768 if (startio) {
769 pr_debug("%s: USB is already open, start io\n", __func__);
770 gsdio_start_io(port);
771 if (gser->send_modem_ctrl_bits)
772 gser->send_modem_ctrl_bits(gser, port->cbits_to_laptop);
773 }
774}
775
776#define SDIO_CH_NAME_MAX_LEN 9
777#define SDIO_OPEN_DELAY msecs_to_jiffies(10000)
Vamsi Krishnaec632262011-07-14 15:49:05 -0700778static int gsdio_ch_remove(struct platform_device *dev)
779{
780 struct gsdio_port *port;
781 struct sdio_port_info *pi;
782 int i;
783 unsigned long flags;
784
785 pr_debug("%s: name:%s\n", __func__, dev->name);
786
787 for (i = 0; i < n_sdio_ports; i++) {
788 port = sdio_ports[i].port;
789 pi = port->sport_info;
790
791 if (!strncmp(pi->data_ch_name, dev->name,
792 SDIO_CH_NAME_MAX_LEN)) {
793 struct gserial *gser = port->port_usb;
794
795 port->sdio_open = 0;
796 port->sdio_probe = 0;
797 port->ctrl_ch_err = 1;
798
799 /* check if usb cable is connected */
800 if (!gser)
801 continue;
802
803 /* indicated call status to usb host */
804 gsdio_ctrl_modem_status(0, port);
805
806 usb_ep_fifo_flush(gser->in);
807 usb_ep_fifo_flush(gser->out);
808
809 cancel_work_sync(&port->push);
810 cancel_work_sync(&port->pull);
811
812 spin_lock_irqsave(&port->port_lock, flags);
813 gsdio_free_requests(gser->out, &port->read_pool);
814 gsdio_free_requests(gser->out, &port->read_queue);
815 gsdio_free_requests(gser->in, &port->write_pool);
816
817 port->rp_len = 0;
818 port->rq_len = 0;
819 port->wp_len = 0;
820 port->n_read = 0;
821 spin_unlock_irqrestore(&port->port_lock, flags);
822
823 }
824 }
825
826 return 0;
827}
828
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700829static int gsdio_ch_probe(struct platform_device *dev)
830{
831 struct gsdio_port *port;
832 struct sdio_port_info *pi;
833 int i;
834
835 pr_debug("%s: name:%s\n", __func__, dev->name);
836
837 for (i = 0; i < n_sdio_ports; i++) {
838 port = sdio_ports[i].port;
839 pi = port->sport_info;
840
841 pr_debug("%s: sdio_ch_name:%s dev_name:%s\n", __func__,
842 pi->data_ch_name, dev->name);
843
844 /* unfortunately cmux channle might not be ready even if
845 * sdio channel is ready. as we dont have good notification
846 * mechanism schedule a delayed work
847 */
848 if (!strncmp(pi->data_ch_name, dev->name,
849 SDIO_CH_NAME_MAX_LEN)) {
Vamsi Krishnaec632262011-07-14 15:49:05 -0700850 port->sdio_probe = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700851 queue_delayed_work(gsdio_wq,
852 &port->sdio_open_work, SDIO_OPEN_DELAY);
853 return 0;
854 }
855 }
856
857 pr_info("%s: name:%s is not found\n", __func__, dev->name);
858
859 return -ENODEV;
860}
861
862int gsdio_port_alloc(unsigned portno,
863 struct usb_cdc_line_coding *coding,
864 struct sdio_port_info *pi)
865{
866 struct gsdio_port *port;
867 struct platform_driver *pdriver;
868
869 port = kzalloc(sizeof(struct gsdio_port), GFP_KERNEL);
870 if (!port) {
871 pr_err("%s: port allocation failed\n", __func__);
872 return -ENOMEM;
873 }
874
875 port->port_num = portno;
876 spin_lock_init(&port->port_lock);
877 port->line_coding = *coding;
878
879 /* READ: read from usb and write into sdio */
880 INIT_LIST_HEAD(&port->read_pool);
881 INIT_LIST_HEAD(&port->read_queue);
882 INIT_WORK(&port->push, gsdio_rx_push);
883
884 INIT_LIST_HEAD(&port->write_pool);
885 INIT_WORK(&port->pull, gsdio_tx_pull);
886
887 INIT_WORK(&port->notify_modem, gsdio_ctrl_wq);
888
889 INIT_DELAYED_WORK(&port->sdio_open_work, gsdio_open_work);
890
891 sdio_ports[portno].port = port;
892
893 port->sport_info = pi;
894 pdriver = &sdio_ports[portno].gsdio_ch;
895
896 pdriver->probe = gsdio_ch_probe;
Vamsi Krishnaec632262011-07-14 15:49:05 -0700897 pdriver->remove = gsdio_ch_remove;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700898 pdriver->driver.name = pi->data_ch_name;
899 pdriver->driver.owner = THIS_MODULE;
900
901 pr_debug("%s: port:%p port#%d sdio_name: %s\n", __func__,
902 port, port->port_num, pi->data_ch_name);
903
904 platform_driver_register(pdriver);
905
906 pr_debug("%s: port:%p port#%d\n", __func__, port, port->port_num);
907
908 return 0;
909}
910
911int gsdio_connect(struct gserial *gser, u8 portno)
912{
913 struct gsdio_port *port;
914 int ret = 0;
915 unsigned long flags;
916
917 if (portno >= n_sdio_ports) {
918 pr_err("%s: invalid portno#%d\n", __func__, portno);
919 return -EINVAL;
920 }
921
922 if (!gser) {
923 pr_err("%s: gser is null\n", __func__);
924 return -EINVAL;
925 }
926
927 port = sdio_ports[portno].port;
928
929 spin_lock_irqsave(&port->port_lock, flags);
930 port->port_usb = gser;
931 gser->notify_modem = gsdio_ctrl_notify_modem;
932 spin_unlock_irqrestore(&port->port_lock, flags);
933
Tatyana Brokhmancf709c12011-06-28 16:33:48 +0300934 ret = usb_ep_enable(gser->in);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700935 if (ret) {
936 pr_err("%s: failed to enable in ep w/ err:%d\n",
937 __func__, ret);
938 port->port_usb = 0;
939 return ret;
940 }
941 gser->in->driver_data = port;
942
Tatyana Brokhmancf709c12011-06-28 16:33:48 +0300943 ret = usb_ep_enable(gser->out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700944 if (ret) {
945 pr_err("%s: failed to enable in ep w/ err:%d\n",
946 __func__, ret);
947 usb_ep_disable(gser->in);
948 port->port_usb = 0;
949 gser->in->driver_data = 0;
950 return ret;
951 }
952 gser->out->driver_data = port;
953
954 if (port->sdio_open) {
955 pr_debug("%s: sdio is already open, start io\n", __func__);
956 gsdio_start_io(port);
957 if (gser->send_modem_ctrl_bits)
958 gser->send_modem_ctrl_bits(gser, port->cbits_to_laptop);
959 }
960
961 return 0;
962}
963
964void gsdio_disconnect(struct gserial *gser, u8 portno)
965{
966 unsigned long flags;
967 struct gsdio_port *port;
968
969 if (portno >= n_sdio_ports) {
970 pr_err("%s: invalid portno#%d\n", __func__, portno);
971 return;
972 }
973
974 if (!gser) {
975 pr_err("%s: gser is null\n", __func__);
976 return;
977 }
978
979 port = sdio_ports[portno].port;
980
981 /* send dtr zero to modem to notify disconnect */
982 port->cbits_to_modem = 0;
983 queue_work(gsdio_wq, &port->notify_modem);
984
985 spin_lock_irqsave(&port->port_lock, flags);
986 port->port_usb = 0;
987 port->nbytes_tomodem = 0;
988 port->nbytes_tolaptop = 0;
989 spin_unlock_irqrestore(&port->port_lock, flags);
990
991 /* disable endpoints, aborting down any active I/O */
992 usb_ep_disable(gser->out);
Chiranjeevi Velempati4fd1c162012-08-01 09:41:22 +0530993 gser->out->driver_data = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700994
995 usb_ep_disable(gser->in);
Chiranjeevi Velempati4fd1c162012-08-01 09:41:22 +0530996 gser->in->driver_data = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997
998 spin_lock_irqsave(&port->port_lock, flags);
999 gsdio_free_requests(gser->out, &port->read_pool);
1000 gsdio_free_requests(gser->out, &port->read_queue);
1001 gsdio_free_requests(gser->in, &port->write_pool);
1002
1003 port->rp_len = 0;
1004 port->rq_len = 0;
1005 port->wp_len = 0;
1006 port->n_read = 0;
1007 spin_unlock_irqrestore(&port->port_lock, flags);
1008}
1009
1010#if defined(CONFIG_DEBUG_FS)
1011static char debug_buffer[PAGE_SIZE];
1012
1013static ssize_t debug_sdio_read_stats(struct file *file, char __user *ubuf,
1014 size_t count, loff_t *ppos)
1015{
1016 struct gsdio_port *port;
Vamsi Krishnaec632262011-07-14 15:49:05 -07001017 char *buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001018 unsigned long flags;
1019 int i = 0;
1020 int temp = 0;
Vamsi Krishnaec632262011-07-14 15:49:05 -07001021 int ret;
1022
1023 buf = kzalloc(sizeof(char) * 1024, GFP_KERNEL);
1024 if (!buf)
1025 return -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001026
1027 while (i < n_sdio_ports) {
1028 port = sdio_ports[i].port;
1029 spin_lock_irqsave(&port->port_lock, flags);
1030 temp += scnprintf(buf + temp, PAGE_SIZE - temp,
1031 "###PORT:%d port:%p###\n"
1032 "nbytes_tolaptop: %lu\n"
1033 "nbytes_tomodem: %lu\n"
1034 "cbits_to_modem: %u\n"
1035 "cbits_to_laptop: %u\n"
1036 "read_pool_len: %lu\n"
1037 "read_queue_len: %lu\n"
1038 "write_pool_len: %lu\n"
Vamsi Krishnaec632262011-07-14 15:49:05 -07001039 "n_read: %u\n"
1040 "sdio_open: %d\n"
1041 "sdio_probe: %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001042 i, port,
1043 port->nbytes_tolaptop, port->nbytes_tomodem,
1044 port->cbits_to_modem, port->cbits_to_laptop,
1045 port->rp_len, port->rq_len, port->wp_len,
Vamsi Krishnaec632262011-07-14 15:49:05 -07001046 port->n_read,
1047 port->sdio_open, port->sdio_probe);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001048 spin_unlock_irqrestore(&port->port_lock, flags);
1049 i++;
1050 }
1051
Vamsi Krishnaec632262011-07-14 15:49:05 -07001052 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
1053
1054 kfree(buf);
1055
1056 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001057}
1058
1059static ssize_t debug_sdio_reset_stats(struct file *file, const char __user *buf,
1060 size_t count, loff_t *ppos)
1061{
1062 struct gsdio_port *port;
1063 unsigned long flags;
1064 int i = 0;
1065
1066 while (i < n_sdio_ports) {
1067 port = sdio_ports[i].port;
1068
1069 spin_lock_irqsave(&port->port_lock, flags);
1070 port->nbytes_tolaptop = 0;
1071 port->nbytes_tomodem = 0;
1072 spin_unlock_irqrestore(&port->port_lock, flags);
1073 i++;
1074 }
1075
1076 return count;
1077}
1078
1079static int debug_sdio_open(struct inode *inode, struct file *file)
1080{
1081 return 0;
1082}
1083
1084static const struct file_operations debug_gsdio_ops = {
1085 .open = debug_sdio_open,
1086 .read = debug_sdio_read_stats,
1087 .write = debug_sdio_reset_stats,
1088};
1089
1090static void gsdio_debugfs_init(void)
1091{
1092 struct dentry *dent;
1093
1094 dent = debugfs_create_dir("usb_gsdio", 0);
1095 if (IS_ERR(dent))
1096 return;
1097
1098 debugfs_create_file("status", 0444, dent, 0, &debug_gsdio_ops);
1099}
1100#else
1101static void gsdio_debugfs_init(void)
1102{
1103 return;
1104}
1105#endif
1106
1107/* connect, disconnect, alloc_requests, free_requests */
1108int gsdio_setup(struct usb_gadget *g, unsigned count)
1109{
1110 struct usb_cdc_line_coding coding;
1111 int i;
1112 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001113
1114 pr_debug("%s: gadget:(%p) count:%d\n", __func__, g, count);
1115
1116 if (count == 0 || count > SDIO_N_PORTS) {
1117 pr_err("%s: invalid number of ports count:%d max_ports:%d\n",
1118 __func__, count, SDIO_N_PORTS);
1119 return -EINVAL;
1120 }
1121
1122 coding.dwDTERate = cpu_to_le32(9600);
1123 coding.bCharFormat = 8;
1124 coding.bParityType = USB_CDC_NO_PARITY;
1125 coding.bDataBits = USB_CDC_1_STOP_BITS;
1126
1127 gsdio_wq = create_singlethread_workqueue("k_gserial");
1128 if (!gsdio_wq) {
1129 pr_err("%s: unable to create workqueue gsdio_wq\n",
1130 __func__);
1131 return -ENOMEM;
1132 }
1133
1134 for (i = 0; i < count; i++) {
1135 mutex_init(&sdio_ports[i].lock);
1136 ret = gsdio_port_alloc(i, &coding, sport_info + i);
Manu Gautamc40be022011-09-26 13:58:31 +05301137 n_sdio_ports++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001138 if (ret) {
Manu Gautamc40be022011-09-26 13:58:31 +05301139 n_sdio_ports--;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001140 pr_err("%s: sdio logical port allocation failed\n",
1141 __func__);
1142 goto free_sdio_ports;
1143 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001144
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001145 }
1146
1147 gsdio_debugfs_init();
1148
1149 return 0;
1150
1151free_sdio_ports:
1152 for (i = 0; i < n_sdio_ports; i++)
1153 gsdio_port_free(i);
1154 destroy_workqueue(gsdio_wq);
1155
1156 return ret;
1157}
1158
1159/* TODO: Add gserial_cleanup */