1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
From 7cb1e9a0797dd5d372f943f0ed971a5b432d16aa Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:23 +0100
Subject: [PATCH] s3c2410-usb-switch.patch
---
drivers/usb/host/ohci-s3c2410.c | 43 +++++++++++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 3c7a740..5877fc9 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -24,6 +24,7 @@
#include <asm/hardware.h>
#include <asm/arch/usb-control.h>
+#include <asm/arch/regs-gpio.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
@@ -308,6 +309,40 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)
local_irq_restore(flags);
}
+/* switching of USB pads */
+static ssize_t show_usb_mode(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ if (__raw_readl(S3C24XX_MISCCR) & S3C2410_MISCCR_USBHOST)
+ return sprintf(buf, "host\n");
+
+ return sprintf(buf, "device\n");
+}
+
+static ssize_t set_usb_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (!strncmp(buf, "host", 4)) {
+ printk("s3c2410: changing usb to host\n");
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
+ S3C2410_MISCCR_USBHOST);
+ /* FIXME:
+ * - call machine-specific disable-pullup function i
+ * - enable +Vbus (if hardware supports it)
+ */
+ s3c2410_gpio_setpin(S3C2410_GPB9, 0);
+ } else if (!strncmp(buf, "device", 6)) {
+ printk("s3c2410: changing usb to device\n");
+ s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0);
+ s3c2410_gpio_setpin(S3C2410_GPB9, 1);
+ } else
+ printk("s3c2410: unknown mode\n");
+ return -EINVAL;
+ return count;
+}
+
+static DEVICE_ATTR(usb_mode, S_IRUGO | S_IWUSR, show_usb_mode, set_usb_mode);
+
/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
@@ -325,6 +360,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc)
static void
usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
+ device_remove_file(&dev->dev, &dev_attr_usb_mode);
usb_remove_hcd(hcd);
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
@@ -392,8 +428,15 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
if (retval != 0)
goto err_ioremap;
+ retval = device_create_file(&dev->dev, &dev_attr_usb_mode);
+ if (retval != 0)
+ goto err_hcd;
+
return 0;
+ err_hcd:
+ usb_remove_hcd(hcd);
+
err_ioremap:
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
--
1.5.6.3
|