diff options
Diffstat (limited to 'drivers/usb/host/ohci-au1xxx.c')
-rw-r--r-- | drivers/usb/host/ohci-au1xxx.c | 102 |
1 files changed, 87 insertions, 15 deletions
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index db280ca7b7a0..a1c8b3b2fcc7 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c | |||
@@ -23,6 +23,8 @@ | |||
23 | 23 | ||
24 | #include <asm/mach-au1x00/au1000.h> | 24 | #include <asm/mach-au1x00/au1000.h> |
25 | 25 | ||
26 | #ifndef CONFIG_SOC_AU1200 | ||
27 | |||
26 | #define USBH_ENABLE_BE (1<<0) | 28 | #define USBH_ENABLE_BE (1<<0) |
27 | #define USBH_ENABLE_C (1<<1) | 29 | #define USBH_ENABLE_C (1<<1) |
28 | #define USBH_ENABLE_E (1<<2) | 30 | #define USBH_ENABLE_E (1<<2) |
@@ -37,21 +39,68 @@ | |||
37 | #error not byte order defined | 39 | #error not byte order defined |
38 | #endif | 40 | #endif |
39 | 41 | ||
42 | #else /* Au1200 */ | ||
43 | |||
44 | #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) | ||
45 | #define USB_MCFG_PFEN (1<<31) | ||
46 | #define USB_MCFG_RDCOMB (1<<30) | ||
47 | #define USB_MCFG_SSDEN (1<<23) | ||
48 | #define USB_MCFG_OHCCLKEN (1<<16) | ||
49 | #define USB_MCFG_UCAM (1<<7) | ||
50 | #define USB_MCFG_OBMEN (1<<1) | ||
51 | #define USB_MCFG_OMEMEN (1<<0) | ||
52 | |||
53 | #define USBH_ENABLE_CE USB_MCFG_OHCCLKEN | ||
54 | #ifdef CONFIG_DMA_COHERENT | ||
55 | #define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \ | ||
56 | | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ | ||
57 | | USB_MCFG_SSDEN | USB_MCFG_UCAM \ | ||
58 | | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) | ||
59 | #else | ||
60 | #define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \ | ||
61 | | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ | ||
62 | | USB_MCFG_SSDEN \ | ||
63 | | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) | ||
64 | #endif | ||
65 | #define USBH_DISABLE (USB_MCFG_OBMEN | USB_MCFG_OMEMEN) | ||
66 | |||
67 | #endif /* Au1200 */ | ||
68 | |||
40 | extern int usb_disabled(void); | 69 | extern int usb_disabled(void); |
41 | 70 | ||
42 | /*-------------------------------------------------------------------------*/ | 71 | /*-------------------------------------------------------------------------*/ |
43 | 72 | ||
44 | static void au1xxx_start_hc(struct platform_device *dev) | 73 | static void au1xxx_start_ohc(struct platform_device *dev) |
45 | { | 74 | { |
46 | printk(KERN_DEBUG __FILE__ | 75 | printk(KERN_DEBUG __FILE__ |
47 | ": starting Au1xxx OHCI USB Controller\n"); | 76 | ": starting Au1xxx OHCI USB Controller\n"); |
48 | 77 | ||
49 | /* enable host controller */ | 78 | /* enable host controller */ |
79 | |||
80 | #ifndef CONFIG_SOC_AU1200 | ||
81 | |||
50 | au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG); | 82 | au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG); |
51 | udelay(1000); | 83 | udelay(1000); |
52 | au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG); | 84 | au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG); |
53 | udelay(1000); | 85 | udelay(1000); |
54 | 86 | ||
87 | #else /* Au1200 */ | ||
88 | |||
89 | /* write HW defaults again in case Yamon cleared them */ | ||
90 | if (au_readl(USB_HOST_CONFIG) == 0) { | ||
91 | au_writel(0x00d02000, USB_HOST_CONFIG); | ||
92 | au_readl(USB_HOST_CONFIG); | ||
93 | udelay(1000); | ||
94 | } | ||
95 | au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); | ||
96 | au_readl(USB_HOST_CONFIG); | ||
97 | udelay(1000); | ||
98 | au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); | ||
99 | au_readl(USB_HOST_CONFIG); | ||
100 | udelay(1000); | ||
101 | |||
102 | #endif /* Au1200 */ | ||
103 | |||
55 | /* wait for reset complete (read register twice; see au1500 errata) */ | 104 | /* wait for reset complete (read register twice; see au1500 errata) */ |
56 | while (au_readl(USB_HOST_CONFIG), | 105 | while (au_readl(USB_HOST_CONFIG), |
57 | !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) | 106 | !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) |
@@ -61,13 +110,25 @@ static void au1xxx_start_hc(struct platform_device *dev) | |||
61 | ": Clock to USB host has been enabled \n"); | 110 | ": Clock to USB host has been enabled \n"); |
62 | } | 111 | } |
63 | 112 | ||
64 | static void au1xxx_stop_hc(struct platform_device *dev) | 113 | static void au1xxx_stop_ohc(struct platform_device *dev) |
65 | { | 114 | { |
66 | printk(KERN_DEBUG __FILE__ | 115 | printk(KERN_DEBUG __FILE__ |
67 | ": stopping Au1xxx OHCI USB Controller\n"); | 116 | ": stopping Au1xxx OHCI USB Controller\n"); |
68 | 117 | ||
118 | #ifndef CONFIG_SOC_AU1200 | ||
119 | |||
69 | /* Disable clock */ | 120 | /* Disable clock */ |
70 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); | 121 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); |
122 | |||
123 | #else /* Au1200 */ | ||
124 | |||
125 | /* Disable mem */ | ||
126 | au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); | ||
127 | udelay(1000); | ||
128 | /* Disable clock */ | ||
129 | au_writel(~USBH_ENABLE_CE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); | ||
130 | au_readl(USB_HOST_CONFIG); | ||
131 | #endif /* Au1200 */ | ||
71 | } | 132 | } |
72 | 133 | ||
73 | 134 | ||
@@ -78,7 +139,7 @@ static void au1xxx_stop_hc(struct platform_device *dev) | |||
78 | 139 | ||
79 | 140 | ||
80 | /** | 141 | /** |
81 | * usb_hcd_au1xxx_probe - initialize Au1xxx-based HCDs | 142 | * usb_ohci_au1xxx_probe - initialize Au1xxx-based HCDs |
82 | * Context: !in_interrupt() | 143 | * Context: !in_interrupt() |
83 | * | 144 | * |
84 | * Allocates basic resources for this USB host controller, and | 145 | * Allocates basic resources for this USB host controller, and |
@@ -86,14 +147,25 @@ static void au1xxx_stop_hc(struct platform_device *dev) | |||
86 | * through the hotplug entry's driver_data. | 147 | * through the hotplug entry's driver_data. |
87 | * | 148 | * |
88 | */ | 149 | */ |
89 | int usb_hcd_au1xxx_probe (const struct hc_driver *driver, | 150 | static int usb_ohci_au1xxx_probe(const struct hc_driver *driver, |
90 | struct platform_device *dev) | 151 | struct platform_device *dev) |
91 | { | 152 | { |
92 | int retval; | 153 | int retval; |
93 | struct usb_hcd *hcd; | 154 | struct usb_hcd *hcd; |
94 | 155 | ||
95 | if(dev->resource[1].flags != IORESOURCE_IRQ) { | 156 | #if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) |
96 | pr_debug ("resource[1] is not IORESOURCE_IRQ"); | 157 | /* Au1200 AB USB does not support coherent memory */ |
158 | if (!(read_c0_prid() & 0xff)) { | ||
159 | pr_info("%s: this is chip revision AB !!\n", | ||
160 | dev->dev.name); | ||
161 | pr_info("%s: update your board or re-configure the kernel\n", | ||
162 | dev->dev.name); | ||
163 | return -ENODEV; | ||
164 | } | ||
165 | #endif | ||
166 | |||
167 | if (dev->resource[1].flags != IORESOURCE_IRQ) { | ||
168 | pr_debug("resource[1] is not IORESOURCE_IRQ\n"); | ||
97 | return -ENOMEM; | 169 | return -ENOMEM; |
98 | } | 170 | } |
99 | 171 | ||
@@ -104,26 +176,26 @@ int usb_hcd_au1xxx_probe (const struct hc_driver *driver, | |||
104 | hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; | 176 | hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; |
105 | 177 | ||
106 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | 178 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { |
107 | pr_debug("request_mem_region failed"); | 179 | pr_debug("request_mem_region failed\n"); |
108 | retval = -EBUSY; | 180 | retval = -EBUSY; |
109 | goto err1; | 181 | goto err1; |
110 | } | 182 | } |
111 | 183 | ||
112 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | 184 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); |
113 | if (!hcd->regs) { | 185 | if (!hcd->regs) { |
114 | pr_debug("ioremap failed"); | 186 | pr_debug("ioremap failed\n"); |
115 | retval = -ENOMEM; | 187 | retval = -ENOMEM; |
116 | goto err2; | 188 | goto err2; |
117 | } | 189 | } |
118 | 190 | ||
119 | au1xxx_start_hc(dev); | 191 | au1xxx_start_ohc(dev); |
120 | ohci_hcd_init(hcd_to_ohci(hcd)); | 192 | ohci_hcd_init(hcd_to_ohci(hcd)); |
121 | 193 | ||
122 | retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); | 194 | retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT | SA_SHIRQ); |
123 | if (retval == 0) | 195 | if (retval == 0) |
124 | return retval; | 196 | return retval; |
125 | 197 | ||
126 | au1xxx_stop_hc(dev); | 198 | au1xxx_stop_ohc(dev); |
127 | iounmap(hcd->regs); | 199 | iounmap(hcd->regs); |
128 | err2: | 200 | err2: |
129 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 201 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
@@ -146,10 +218,10 @@ int usb_hcd_au1xxx_probe (const struct hc_driver *driver, | |||
146 | * context, normally "rmmod", "apmd", or something similar. | 218 | * context, normally "rmmod", "apmd", or something similar. |
147 | * | 219 | * |
148 | */ | 220 | */ |
149 | void usb_hcd_au1xxx_remove (struct usb_hcd *hcd, struct platform_device *dev) | 221 | static void usb_ohci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev) |
150 | { | 222 | { |
151 | usb_remove_hcd(hcd); | 223 | usb_remove_hcd(hcd); |
152 | au1xxx_stop_hc(dev); | 224 | au1xxx_stop_ohc(dev); |
153 | iounmap(hcd->regs); | 225 | iounmap(hcd->regs); |
154 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 226 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
155 | usb_put_hcd(hcd); | 227 | usb_put_hcd(hcd); |
@@ -235,7 +307,7 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | |||
235 | if (usb_disabled()) | 307 | if (usb_disabled()) |
236 | return -ENODEV; | 308 | return -ENODEV; |
237 | 309 | ||
238 | ret = usb_hcd_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev); | 310 | ret = usb_ohci_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev); |
239 | return ret; | 311 | return ret; |
240 | } | 312 | } |
241 | 313 | ||
@@ -243,7 +315,7 @@ static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) | |||
243 | { | 315 | { |
244 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 316 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
245 | 317 | ||
246 | usb_hcd_au1xxx_remove(hcd, pdev); | 318 | usb_ohci_au1xxx_remove(hcd, pdev); |
247 | return 0; | 319 | return 0; |
248 | } | 320 | } |
249 | /*TBD*/ | 321 | /*TBD*/ |