diff options
Diffstat (limited to 'drivers/usb/host/ehci-ppc-of.c')
| -rw-r--r-- | drivers/usb/host/ehci-ppc-of.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index b018deed2e8f..ef732b704f53 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c | |||
| @@ -107,11 +107,13 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | |||
| 107 | { | 107 | { |
| 108 | struct device_node *dn = op->node; | 108 | struct device_node *dn = op->node; |
| 109 | struct usb_hcd *hcd; | 109 | struct usb_hcd *hcd; |
| 110 | struct ehci_hcd *ehci; | 110 | struct ehci_hcd *ehci = NULL; |
| 111 | struct resource res; | 111 | struct resource res; |
| 112 | int irq; | 112 | int irq; |
| 113 | int rv; | 113 | int rv; |
| 114 | 114 | ||
| 115 | struct device_node *np; | ||
| 116 | |||
| 115 | if (usb_disabled()) | 117 | if (usb_disabled()) |
| 116 | return -ENODEV; | 118 | return -ENODEV; |
| 117 | 119 | ||
| @@ -149,6 +151,20 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | |||
| 149 | } | 151 | } |
| 150 | 152 | ||
| 151 | ehci = hcd_to_ehci(hcd); | 153 | ehci = hcd_to_ehci(hcd); |
| 154 | np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx"); | ||
| 155 | if (np != NULL) { | ||
| 156 | /* claim we really affected by usb23 erratum */ | ||
| 157 | if (!of_address_to_resource(np, 0, &res)) | ||
| 158 | ehci->ohci_hcctrl_reg = ioremap(res.start + | ||
| 159 | OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN); | ||
| 160 | else | ||
| 161 | pr_debug(__FILE__ ": no ohci offset in fdt\n"); | ||
| 162 | if (!ehci->ohci_hcctrl_reg) { | ||
| 163 | pr_debug(__FILE__ ": ioremap for ohci hcctrl failed\n"); | ||
| 164 | } else { | ||
| 165 | ehci->has_amcc_usb23 = 1; | ||
| 166 | } | ||
| 167 | } | ||
| 152 | 168 | ||
| 153 | if (of_get_property(dn, "big-endian", NULL)) { | 169 | if (of_get_property(dn, "big-endian", NULL)) { |
| 154 | ehci->big_endian_mmio = 1; | 170 | ehci->big_endian_mmio = 1; |
| @@ -181,6 +197,9 @@ err_ioremap: | |||
| 181 | irq_dispose_mapping(irq); | 197 | irq_dispose_mapping(irq); |
| 182 | err_irq: | 198 | err_irq: |
| 183 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 199 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| 200 | |||
| 201 | if (ehci->has_amcc_usb23) | ||
| 202 | iounmap(ehci->ohci_hcctrl_reg); | ||
| 184 | err_rmr: | 203 | err_rmr: |
| 185 | usb_put_hcd(hcd); | 204 | usb_put_hcd(hcd); |
| 186 | 205 | ||
| @@ -191,6 +210,11 @@ err_rmr: | |||
| 191 | static int ehci_hcd_ppc_of_remove(struct of_device *op) | 210 | static int ehci_hcd_ppc_of_remove(struct of_device *op) |
| 192 | { | 211 | { |
| 193 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 212 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
| 213 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
| 214 | |||
| 215 | struct device_node *np; | ||
| 216 | struct resource res; | ||
| 217 | |||
| 194 | dev_set_drvdata(&op->dev, NULL); | 218 | dev_set_drvdata(&op->dev, NULL); |
| 195 | 219 | ||
| 196 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); | 220 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); |
| @@ -201,6 +225,25 @@ static int ehci_hcd_ppc_of_remove(struct of_device *op) | |||
| 201 | irq_dispose_mapping(hcd->irq); | 225 | irq_dispose_mapping(hcd->irq); |
| 202 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 226 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| 203 | 227 | ||
| 228 | /* use request_mem_region to test if the ohci driver is loaded. if so | ||
| 229 | * ensure the ohci core is operational. | ||
| 230 | */ | ||
| 231 | if (ehci->has_amcc_usb23) { | ||
| 232 | np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx"); | ||
| 233 | if (np != NULL) { | ||
| 234 | if (!of_address_to_resource(np, 0, &res)) | ||
| 235 | if (!request_mem_region(res.start, | ||
| 236 | 0x4, hcd_name)) | ||
| 237 | set_ohci_hcfs(ehci, 1); | ||
| 238 | else | ||
| 239 | release_mem_region(res.start, 0x4); | ||
| 240 | else | ||
| 241 | pr_debug(__FILE__ ": no ohci offset in fdt\n"); | ||
| 242 | of_node_put(np); | ||
| 243 | } | ||
| 244 | |||
| 245 | iounmap(ehci->ohci_hcctrl_reg); | ||
| 246 | } | ||
| 204 | usb_put_hcd(hcd); | 247 | usb_put_hcd(hcd); |
| 205 | 248 | ||
| 206 | return 0; | 249 | return 0; |
