]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/usb/host/ehci-faraday.c
usb: ohci: enable cache support
[karo-tx-uboot.git] / drivers / usb / host / ehci-faraday.c
1 /*
2  * Faraday USB 2.0 EHCI Controller
3  *
4  * (C) Copyright 2010 Faraday Technology
5  * Dante Su <dantesu@faraday-tech.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <asm/io.h>
12 #include <usb.h>
13 #include <usb/fusbh200.h>
14 #include <usb/fotg210.h>
15
16 #include "ehci.h"
17
18 #ifndef CONFIG_USB_EHCI_BASE_LIST
19 #define CONFIG_USB_EHCI_BASE_LIST       { CONFIG_USB_EHCI_BASE }
20 #endif
21
22 union ehci_faraday_regs {
23         struct fusbh200_regs usb;
24         struct fotg210_regs  otg;
25 };
26
27 static inline int ehci_is_fotg2xx(union ehci_faraday_regs *regs)
28 {
29         return !readl(&regs->usb.easstr);
30 }
31
32 void faraday_ehci_set_usbmode(struct ehci_ctrl *ctrl)
33 {
34         /* nothing needs to be done */
35 }
36
37 int faraday_ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)
38 {
39         int spd, ret = PORTSC_PSPD_HS;
40         union ehci_faraday_regs *regs;
41
42         ret = (void __iomem *)((ulong)ctrl->hcor - 0x10);
43         if (ehci_is_fotg2xx(regs))
44                 spd = OTGCSR_SPD(readl(&regs->otg.otgcsr));
45         else
46                 spd = BMCSR_SPD(readl(&regs->usb.bmcsr));
47
48         switch (spd) {
49         case 0:    /* full speed */
50                 ret = PORTSC_PSPD_FS;
51                 break;
52         case 1:    /* low  speed */
53                 ret = PORTSC_PSPD_LS;
54                 break;
55         case 2:    /* high speed */
56                 ret = PORTSC_PSPD_HS;
57                 break;
58         default:
59                 printf("ehci-faraday: invalid device speed\n");
60                 break;
61         }
62
63         return ret;
64 }
65
66 uint32_t *faraday_ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port)
67 {
68         /* Faraday EHCI has one and only one portsc register */
69         if (port) {
70                 /* Printing the message would cause a scan failure! */
71                 debug("The request port(%d) is not configured\n", port);
72                 return NULL;
73         }
74
75         /* Faraday EHCI PORTSC register offset is 0x20 from hcor */
76         return (uint32_t *)((uint8_t *)ctrl->hcor + 0x20);
77 }
78
79 static const struct ehci_ops faraday_ehci_ops = {
80         .set_usb_mode           = faraday_ehci_set_usbmode,
81         .get_port_speed         = faraday_ehci_get_port_speed,
82         .get_portsc_register    = faraday_ehci_get_portsc_register,
83 };
84
85 /*
86  * Create the appropriate control structures to manage
87  * a new EHCI host controller.
88  */
89 int ehci_hcd_init(int index, enum usb_init_type init,
90                 struct ehci_hccr **ret_hccr, struct ehci_hcor **ret_hcor)
91 {
92         struct ehci_hccr *hccr;
93         struct ehci_hcor *hcor;
94         union ehci_faraday_regs *regs;
95         uint32_t base_list[] = CONFIG_USB_EHCI_BASE_LIST;
96
97         if (index < 0 || index >= ARRAY_SIZE(base_list))
98                 return -1;
99         ehci_set_controller_priv(index, NULL, &faraday_ehci_ops);
100         regs = (void __iomem *)base_list[index];
101         hccr = (struct ehci_hccr *)&regs->usb.hccr;
102         hcor = (struct ehci_hcor *)&regs->usb.hcor;
103
104         if (ehci_is_fotg2xx(regs)) {
105                 /* A-device bus reset */
106                 /* ... Power off A-device */
107                 setbits_le32(&regs->otg.otgcsr, OTGCSR_A_BUSDROP);
108                 /* ... Drop vbus and bus traffic */
109                 clrbits_le32(&regs->otg.otgcsr, OTGCSR_A_BUSREQ);
110                 mdelay(1);
111                 /* ... Power on A-device */
112                 clrbits_le32(&regs->otg.otgcsr, OTGCSR_A_BUSDROP);
113                 /* ... Drive vbus and bus traffic */
114                 setbits_le32(&regs->otg.otgcsr, OTGCSR_A_BUSREQ);
115                 mdelay(1);
116                 /* Disable OTG & DEV interrupts, triggered at level-high */
117                 writel(IMR_IRQLH | IMR_OTG | IMR_DEV, &regs->otg.imr);
118                 /* Clear all interrupt status */
119                 writel(ISR_HOST | ISR_OTG | ISR_DEV, &regs->otg.isr);
120         } else {
121                 /* Interrupt=level-high */
122                 setbits_le32(&regs->usb.bmcsr, BMCSR_IRQLH);
123                 /* VBUS on */
124                 clrbits_le32(&regs->usb.bmcsr, BMCSR_VBUS_OFF);
125                 /* Disable all interrupts */
126                 writel(0x00, &regs->usb.bmier);
127                 writel(0x1f, &regs->usb.bmisr);
128         }
129
130         *ret_hccr = hccr;
131         *ret_hcor = hcor;
132
133         return 0;
134 }
135
136 /*
137  * Destroy the appropriate control structures corresponding
138  * the the EHCI host controller.
139  */
140 int ehci_hcd_stop(int index)
141 {
142         return 0;
143 }