aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorMian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>2010-12-07 09:00:09 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-12-10 17:27:33 -0500
commit969152341e852ae7a5e1b11c33ef6244f3cb3579 (patch)
tree8018fcadcdf682ec5caa49a1319eb68d81093197 /drivers/usb
parent2d0cdcc5a0e4e5e467fc4be4d00cc6c531c80b64 (diff)
usb: add ab8500 usb transceiver driver
Basic driver for ab8500 usb otg transceiver TODO: -Regulators support -Host and OTG testing -Interface with PRCMU -Charging support Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> Acked-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/otg/Kconfig9
-rw-r--r--drivers/usb/otg/Makefile1
-rw-r--r--drivers/usb/otg/ab8500-usb.c585
3 files changed, 595 insertions, 0 deletions
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 2810c2af71b0..6491717a636a 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -92,4 +92,13 @@ config USB_MSM_OTG_72K
92 This driver is required even for peripheral only or host only 92 This driver is required even for peripheral only or host only
93 mode configurations. 93 mode configurations.
94 94
95config AB8500_USB
96 tristate "AB8500 USB Transceiver Driver"
97 depends on AB8500_CORE
98 select USB_OTG_UTILS
99 help
100 Enable this to support the USB OTG transceiver in AB8500 chip.
101 This transceiver supports high and full speed devices plus,
102 in host mode, low speed.
103
95endif # USB || OTG 104endif # USB || OTG
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 3b1b0960fb68..30a23f3b7a1f 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o
16obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o 16obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
17obj-$(CONFIG_USB_ULPI) += ulpi.o 17obj-$(CONFIG_USB_ULPI) += ulpi.o
18obj-$(CONFIG_USB_MSM_OTG_72K) += msm72k_otg.o 18obj-$(CONFIG_USB_MSM_OTG_72K) += msm72k_otg.o
19obj-$(CONFIG_AB8500_USB) += ab8500-usb.o
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
new file mode 100644
index 000000000000..d14736b3107b
--- /dev/null
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -0,0 +1,585 @@
1/*
2 * drivers/usb/otg/ab8500_usb.c
3 *
4 * USB transceiver driver for AB8500 chip
5 *
6 * Copyright (C) 2010 ST-Ericsson AB
7 * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/usb/otg.h>
28#include <linux/slab.h>
29#include <linux/notifier.h>
30#include <linux/interrupt.h>
31#include <linux/delay.h>
32#include <linux/mfd/abx500.h>
33#include <linux/mfd/ab8500.h>
34
35#define AB8500_MAIN_WD_CTRL_REG 0x01
36#define AB8500_USB_LINE_STAT_REG 0x80
37#define AB8500_USB_PHY_CTRL_REG 0x8A
38
39#define AB8500_BIT_OTG_STAT_ID (1 << 0)
40#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
41#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
42#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
43#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
44
45#define AB8500_V1x_LINK_STAT_WAIT (HZ/10)
46#define AB8500_WD_KICK_DELAY_US 100 /* usec */
47#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
48#define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */
49
50/* Usb line status register */
51enum ab8500_usb_link_status {
52 USB_LINK_NOT_CONFIGURED = 0,
53 USB_LINK_STD_HOST_NC,
54 USB_LINK_STD_HOST_C_NS,
55 USB_LINK_STD_HOST_C_S,
56 USB_LINK_HOST_CHG_NM,
57 USB_LINK_HOST_CHG_HS,
58 USB_LINK_HOST_CHG_HS_CHIRP,
59 USB_LINK_DEDICATED_CHG,
60 USB_LINK_ACA_RID_A,
61 USB_LINK_ACA_RID_B,
62 USB_LINK_ACA_RID_C_NM,
63 USB_LINK_ACA_RID_C_HS,
64 USB_LINK_ACA_RID_C_HS_CHIRP,
65 USB_LINK_HM_IDGND,
66 USB_LINK_RESERVED,
67 USB_LINK_NOT_VALID_LINK
68};
69
70struct ab8500_usb {
71 struct otg_transceiver otg;
72 struct device *dev;
73 int irq_num_id_rise;
74 int irq_num_id_fall;
75 int irq_num_vbus_rise;
76 int irq_num_vbus_fall;
77 int irq_num_link_status;
78 unsigned vbus_draw;
79 struct delayed_work dwork;
80 struct work_struct phy_dis_work;
81 unsigned long link_status_wait;
82 int rev;
83};
84
85static inline struct ab8500_usb *xceiv_to_ab(struct otg_transceiver *x)
86{
87 return container_of(x, struct ab8500_usb, otg);
88}
89
90static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
91{
92 abx500_set_register_interruptible(ab->dev,
93 AB8500_SYS_CTRL2_BLOCK,
94 AB8500_MAIN_WD_CTRL_REG,
95 AB8500_BIT_WD_CTRL_ENABLE);
96
97 udelay(AB8500_WD_KICK_DELAY_US);
98
99 abx500_set_register_interruptible(ab->dev,
100 AB8500_SYS_CTRL2_BLOCK,
101 AB8500_MAIN_WD_CTRL_REG,
102 (AB8500_BIT_WD_CTRL_ENABLE
103 | AB8500_BIT_WD_CTRL_KICK));
104
105 if (ab->rev > 0x10) /* v1.1 v2.0 */
106 udelay(AB8500_WD_V11_DISABLE_DELAY_US);
107 else /* v1.0 */
108 msleep(AB8500_WD_V10_DISABLE_DELAY_MS);
109
110 abx500_set_register_interruptible(ab->dev,
111 AB8500_SYS_CTRL2_BLOCK,
112 AB8500_MAIN_WD_CTRL_REG,
113 0);
114}
115
116static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host,
117 bool enable)
118{
119 u8 ctrl_reg;
120 abx500_get_register_interruptible(ab->dev,
121 AB8500_USB,
122 AB8500_USB_PHY_CTRL_REG,
123 &ctrl_reg);
124 if (sel_host) {
125 if (enable)
126 ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN;
127 else
128 ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN;
129 } else {
130 if (enable)
131 ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN;
132 else
133 ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN;
134 }
135
136 abx500_set_register_interruptible(ab->dev,
137 AB8500_USB,
138 AB8500_USB_PHY_CTRL_REG,
139 ctrl_reg);
140
141 /* Needed to enable the phy.*/
142 if (enable)
143 ab8500_usb_wd_workaround(ab);
144}
145
146#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_ctrl(ab, true, true)
147#define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_ctrl(ab, true, false)
148#define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_ctrl(ab, false, true)
149#define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_ctrl(ab, false, false)
150
151static int ab8500_usb_link_status_update(struct ab8500_usb *ab)
152{
153 u8 reg;
154 enum ab8500_usb_link_status lsts;
155 void *v = NULL;
156 enum usb_xceiv_events event;
157
158 abx500_get_register_interruptible(ab->dev,
159 AB8500_USB,
160 AB8500_USB_LINE_STAT_REG,
161 &reg);
162
163 lsts = (reg >> 3) & 0x0F;
164
165 switch (lsts) {
166 case USB_LINK_NOT_CONFIGURED:
167 case USB_LINK_RESERVED:
168 case USB_LINK_NOT_VALID_LINK:
169 /* TODO: Disable regulators. */
170 ab8500_usb_host_phy_dis(ab);
171 ab8500_usb_peri_phy_dis(ab);
172 ab->otg.state = OTG_STATE_B_IDLE;
173 ab->otg.default_a = false;
174 ab->vbus_draw = 0;
175 event = USB_EVENT_NONE;
176 break;
177
178 case USB_LINK_STD_HOST_NC:
179 case USB_LINK_STD_HOST_C_NS:
180 case USB_LINK_STD_HOST_C_S:
181 case USB_LINK_HOST_CHG_NM:
182 case USB_LINK_HOST_CHG_HS:
183 case USB_LINK_HOST_CHG_HS_CHIRP:
184 if (ab->otg.gadget) {
185 /* TODO: Enable regulators. */
186 ab8500_usb_peri_phy_en(ab);
187 v = ab->otg.gadget;
188 }
189 event = USB_EVENT_VBUS;
190 break;
191
192 case USB_LINK_HM_IDGND:
193 if (ab->otg.host) {
194 /* TODO: Enable regulators. */
195 ab8500_usb_host_phy_en(ab);
196 v = ab->otg.host;
197 }
198 ab->otg.state = OTG_STATE_A_IDLE;
199 ab->otg.default_a = true;
200 event = USB_EVENT_ID;
201 break;
202
203 case USB_LINK_ACA_RID_A:
204 case USB_LINK_ACA_RID_B:
205 /* TODO */
206 case USB_LINK_ACA_RID_C_NM:
207 case USB_LINK_ACA_RID_C_HS:
208 case USB_LINK_ACA_RID_C_HS_CHIRP:
209 case USB_LINK_DEDICATED_CHG:
210 /* TODO: vbus_draw */
211 event = USB_EVENT_CHARGER;
212 break;
213 }
214
215 blocking_notifier_call_chain(&ab->otg.notifier, event, v);
216
217 return 0;
218}
219
220static void ab8500_usb_delayed_work(struct work_struct *work)
221{
222 struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
223 dwork.work);
224
225 ab8500_usb_link_status_update(ab);
226}
227
228static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data)
229{
230 struct ab8500_usb *ab = (struct ab8500_usb *) data;
231
232 /* Wait for link status to become stable. */
233 schedule_delayed_work(&ab->dwork, ab->link_status_wait);
234
235 return IRQ_HANDLED;
236}
237
238static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data)
239{
240 struct ab8500_usb *ab = (struct ab8500_usb *) data;
241
242 /* Link status will not be updated till phy is disabled. */
243 ab8500_usb_peri_phy_dis(ab);
244
245 /* Wait for link status to become stable. */
246 schedule_delayed_work(&ab->dwork, ab->link_status_wait);
247
248 return IRQ_HANDLED;
249}
250
251static irqreturn_t ab8500_usb_v20_irq(int irq, void *data)
252{
253 struct ab8500_usb *ab = (struct ab8500_usb *) data;
254
255 ab8500_usb_link_status_update(ab);
256
257 return IRQ_HANDLED;
258}
259
260static void ab8500_usb_phy_disable_work(struct work_struct *work)
261{
262 struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
263 phy_dis_work);
264
265 if (!ab->otg.host)
266 ab8500_usb_host_phy_dis(ab);
267
268 if (!ab->otg.gadget)
269 ab8500_usb_peri_phy_dis(ab);
270}
271
272static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA)
273{
274 struct ab8500_usb *ab;
275
276 if (!otg)
277 return -ENODEV;
278
279 ab = xceiv_to_ab(otg);
280
281 ab->vbus_draw = mA;
282
283 if (mA)
284 blocking_notifier_call_chain(&ab->otg.notifier,
285 USB_EVENT_ENUMERATED, ab->otg.gadget);
286 return 0;
287}
288
289/* TODO: Implement some way for charging or other drivers to read
290 * ab->vbus_draw.
291 */
292
293static int ab8500_usb_set_suspend(struct otg_transceiver *x, int suspend)
294{
295 /* TODO */
296 return 0;
297}
298
299static int ab8500_usb_set_peripheral(struct otg_transceiver *otg,
300 struct usb_gadget *gadget)
301{
302 struct ab8500_usb *ab;
303
304 if (!otg)
305 return -ENODEV;
306
307 ab = xceiv_to_ab(otg);
308
309 /* Some drivers call this function in atomic context.
310 * Do not update ab8500 registers directly till this
311 * is fixed.
312 */
313
314 if (!gadget) {
315 /* TODO: Disable regulators. */
316 ab->otg.gadget = NULL;
317 schedule_work(&ab->phy_dis_work);
318 } else {
319 ab->otg.gadget = gadget;
320 ab->otg.state = OTG_STATE_B_IDLE;
321
322 /* Phy will not be enabled if cable is already
323 * plugged-in. Schedule to enable phy.
324 * Use same delay to avoid any race condition.
325 */
326 schedule_delayed_work(&ab->dwork, ab->link_status_wait);
327 }
328
329 return 0;
330}
331
332static int ab8500_usb_set_host(struct otg_transceiver *otg,
333 struct usb_bus *host)
334{
335 struct ab8500_usb *ab;
336
337 if (!otg)
338 return -ENODEV;
339
340 ab = xceiv_to_ab(otg);
341
342 /* Some drivers call this function in atomic context.
343 * Do not update ab8500 registers directly till this
344 * is fixed.
345 */
346
347 if (!host) {
348 /* TODO: Disable regulators. */
349 ab->otg.host = NULL;
350 schedule_work(&ab->phy_dis_work);
351 } else {
352 ab->otg.host = host;
353 /* Phy will not be enabled if cable is already
354 * plugged-in. Schedule to enable phy.
355 * Use same delay to avoid any race condition.
356 */
357 schedule_delayed_work(&ab->dwork, ab->link_status_wait);
358 }
359
360 return 0;
361}
362
363static void ab8500_usb_irq_free(struct ab8500_usb *ab)
364{
365 if (ab->rev < 0x20) {
366 free_irq(ab->irq_num_id_rise, ab);
367 free_irq(ab->irq_num_id_fall, ab);
368 free_irq(ab->irq_num_vbus_rise, ab);
369 free_irq(ab->irq_num_vbus_fall, ab);
370 } else {
371 free_irq(ab->irq_num_link_status, ab);
372 }
373}
374
375static int ab8500_usb_v1x_res_setup(struct platform_device *pdev,
376 struct ab8500_usb *ab)
377{
378 int err;
379
380 ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R");
381 if (ab->irq_num_id_rise < 0) {
382 dev_err(&pdev->dev, "ID rise irq not found\n");
383 return ab->irq_num_id_rise;
384 }
385 err = request_threaded_irq(ab->irq_num_id_rise, NULL,
386 ab8500_usb_v1x_common_irq,
387 IRQF_NO_SUSPEND | IRQF_SHARED,
388 "usb-id-rise", ab);
389 if (err < 0) {
390 dev_err(ab->dev, "request_irq failed for ID rise irq\n");
391 goto fail0;
392 }
393
394 ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
395 if (ab->irq_num_id_fall < 0) {
396 dev_err(&pdev->dev, "ID fall irq not found\n");
397 return ab->irq_num_id_fall;
398 }
399 err = request_threaded_irq(ab->irq_num_id_fall, NULL,
400 ab8500_usb_v1x_common_irq,
401 IRQF_NO_SUSPEND | IRQF_SHARED,
402 "usb-id-fall", ab);
403 if (err < 0) {
404 dev_err(ab->dev, "request_irq failed for ID fall irq\n");
405 goto fail1;
406 }
407
408 ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R");
409 if (ab->irq_num_vbus_rise < 0) {
410 dev_err(&pdev->dev, "VBUS rise irq not found\n");
411 return ab->irq_num_vbus_rise;
412 }
413 err = request_threaded_irq(ab->irq_num_vbus_rise, NULL,
414 ab8500_usb_v1x_common_irq,
415 IRQF_NO_SUSPEND | IRQF_SHARED,
416 "usb-vbus-rise", ab);
417 if (err < 0) {
418 dev_err(ab->dev, "request_irq failed for Vbus rise irq\n");
419 goto fail2;
420 }
421
422 ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F");
423 if (ab->irq_num_vbus_fall < 0) {
424 dev_err(&pdev->dev, "VBUS fall irq not found\n");
425 return ab->irq_num_vbus_fall;
426 }
427 err = request_threaded_irq(ab->irq_num_vbus_fall, NULL,
428 ab8500_usb_v1x_vbus_fall_irq,
429 IRQF_NO_SUSPEND | IRQF_SHARED,
430 "usb-vbus-fall", ab);
431 if (err < 0) {
432 dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
433 goto fail3;
434 }
435
436 return 0;
437fail3:
438 free_irq(ab->irq_num_vbus_rise, ab);
439fail2:
440 free_irq(ab->irq_num_id_fall, ab);
441fail1:
442 free_irq(ab->irq_num_id_rise, ab);
443fail0:
444 return err;
445}
446
447static int ab8500_usb_v2_res_setup(struct platform_device *pdev,
448 struct ab8500_usb *ab)
449{
450 int err;
451
452 ab->irq_num_link_status = platform_get_irq_byname(pdev,
453 "USB_LINK_STATUS");
454 if (ab->irq_num_link_status < 0) {
455 dev_err(&pdev->dev, "Link status irq not found\n");
456 return ab->irq_num_link_status;
457 }
458
459 err = request_threaded_irq(ab->irq_num_link_status, NULL,
460 ab8500_usb_v20_irq,
461 IRQF_NO_SUSPEND | IRQF_SHARED,
462 "usb-link-status", ab);
463 if (err < 0) {
464 dev_err(ab->dev,
465 "request_irq failed for link status irq\n");
466 return err;
467 }
468
469 return 0;
470}
471
472static int __devinit ab8500_usb_probe(struct platform_device *pdev)
473{
474 struct ab8500_usb *ab;
475 int err;
476 int rev;
477
478 rev = abx500_get_chip_id(&pdev->dev);
479 if (rev < 0) {
480 dev_err(&pdev->dev, "Chip id read failed\n");
481 return rev;
482 } else if (rev < 0x10) {
483 dev_err(&pdev->dev, "Unsupported AB8500 chip\n");
484 return -ENODEV;
485 }
486
487 ab = kzalloc(sizeof *ab, GFP_KERNEL);
488 if (!ab)
489 return -ENOMEM;
490
491 ab->dev = &pdev->dev;
492 ab->rev = rev;
493 ab->otg.dev = ab->dev;
494 ab->otg.label = "ab8500";
495 ab->otg.state = OTG_STATE_UNDEFINED;
496 ab->otg.set_host = ab8500_usb_set_host;
497 ab->otg.set_peripheral = ab8500_usb_set_peripheral;
498 ab->otg.set_suspend = ab8500_usb_set_suspend;
499 ab->otg.set_power = ab8500_usb_set_power;
500
501 platform_set_drvdata(pdev, ab);
502
503 BLOCKING_INIT_NOTIFIER_HEAD(&ab->otg.notifier);
504
505 /* v1: Wait for link status to become stable.
506 * all: Updates form set_host and set_peripheral as they are atomic.
507 */
508 INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work);
509
510 /* all: Disable phy when called from set_host and set_peripheral */
511 INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
512
513 if (ab->rev < 0x20) {
514 err = ab8500_usb_v1x_res_setup(pdev, ab);
515 ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT;
516 } else {
517 err = ab8500_usb_v2_res_setup(pdev, ab);
518 }
519
520 if (err < 0)
521 goto fail0;
522
523 err = otg_set_transceiver(&ab->otg);
524 if (err) {
525 dev_err(&pdev->dev, "Can't register transceiver\n");
526 goto fail1;
527 }
528
529 dev_info(&pdev->dev, "AB8500 usb driver initialized\n");
530
531 return 0;
532fail1:
533 ab8500_usb_irq_free(ab);
534fail0:
535 kfree(ab);
536 return err;
537}
538
539static int __devexit ab8500_usb_remove(struct platform_device *pdev)
540{
541 struct ab8500_usb *ab = platform_get_drvdata(pdev);
542
543 ab8500_usb_irq_free(ab);
544
545 cancel_delayed_work_sync(&ab->dwork);
546
547 cancel_work_sync(&ab->phy_dis_work);
548
549 otg_set_transceiver(NULL);
550
551 ab8500_usb_host_phy_dis(ab);
552 ab8500_usb_peri_phy_dis(ab);
553
554 platform_set_drvdata(pdev, NULL);
555
556 kfree(ab);
557
558 return 0;
559}
560
561static struct platform_driver ab8500_usb_driver = {
562 .probe = ab8500_usb_probe,
563 .remove = __devexit_p(ab8500_usb_remove),
564 .driver = {
565 .name = "ab8500-usb",
566 .owner = THIS_MODULE,
567 },
568};
569
570static int __init ab8500_usb_init(void)
571{
572 return platform_driver_register(&ab8500_usb_driver);
573}
574subsys_initcall(ab8500_usb_init);
575
576static void __exit ab8500_usb_exit(void)
577{
578 platform_driver_unregister(&ab8500_usb_driver);
579}
580module_exit(ab8500_usb_exit);
581
582MODULE_ALIAS("platform:ab8500_usb");
583MODULE_AUTHOR("ST-Ericsson AB");
584MODULE_DESCRIPTION("AB8500 usb transceiver driver");
585MODULE_LICENSE("GPL");