1 /*
2  * Copyright (c) 2025, YC113
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbh_core.h"
7 #include "usb_hc_ehci.h"
8 
9 #ifdef CONFIG_USB_EHCI_WITH_OHCI
10 #include "usb_hc_ohci.h"
11 #endif
12 
13 #include "interrupt.h"
14 #include "drv_reg_base.h"
15 #include "drv_clock.h"
16 
17 #if CONFIG_USBHOST_MAX_BUS != 2
18 #error "t113 has 2 usb host controller"
19 #endif
20 
21 #if CONFIG_USB_OHCI_HCOR_OFFSET != 0x400
22 #error "t113 CONFIG_USB_OHCI_HCOR_OFFSET must be 0x400"
23 #endif
24 
25 #if defined(CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE)
26 #error "t113 usb ehci register need reserved"
27 #endif
28 
29 #if !defined(CONFIG_USB_EHCI_CONFIGFLAG)
30 #error "t113 usb ehci has configflag register"
31 #endif
32 
33 #if defined(CONFIG_USB_EHCI_ISO)
34 #error "t113 usb ehci no iso register"
35 #endif
36 
usb_select_phyTohci(void)37 void usb_select_phyTohci(void)
38 {
39     *(volatile rt_uint32_t *)(USB0_OTG_BASE_ADDR + 0x420) &= ~(1 << 0);
40 }
41 
usb_gate_open(rt_uint8_t busid)42 void usb_gate_open(rt_uint8_t busid)
43 {
44     rt_uint32_t addr;
45 
46     addr = (rt_uint32_t)&CCU->usb0_clk + busid * 4;
47 
48     if(busid == 0) {
49         /* otg gate open*/
50         CCU->usb_bgr |= 1 << 8;
51 
52         /* otg bus reset */
53         CCU->usb_bgr &= ~(1 << 24);
54         sdelay(10);
55         CCU->usb_bgr |= (1 << 24);
56         sdelay(10);
57     }
58 
59     /* ehci gate open */
60     CCU->usb_bgr |= (1 << 4) << busid;
61 
62     /* ehci bus reset */
63     CCU->usb_bgr &= ~((1 << 20) << busid);
64     sdelay(10);
65     CCU->usb_bgr |= (1 << 20) << busid;
66     sdelay(10);
67 
68     /* ohci gate open */
69     CCU->usb_bgr |= 1 << busid;
70 
71     /* ohci bus reset */
72     CCU->usb_bgr &= ~((1 << 16) << busid);
73     sdelay(10);
74     CCU->usb_bgr |= (1 << 16) << busid;
75     sdelay(10);
76 
77     sdelay(10);
78 
79     /* clock enable */
80     *(volatile rt_uint32_t *)addr &= ~(3 << 24);
81     *(volatile rt_uint32_t *)addr |= (1 << 31) | (1 << 24);
82 
83     /* reset phy */
84     *(volatile rt_uint32_t *)addr &= ~(1 << 30);
85     sdelay(10);
86     *(volatile rt_uint32_t *)addr |= 1 << 30;
87     sdelay(10);
88 
89     /* otg phy select */
90     if(busid == 0) usb_select_phyTohci();
91 
92     USB_LOG_DBG("usb%d gate : %X, clock : %X\n", busid, CCU->usb_bgr, *(volatile rt_uint32_t *)addr);
93 }
94 
usb_clean_siddp(struct usbh_bus * bus)95 void usb_clean_siddp(struct usbh_bus *bus)
96 {
97     *(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x810) &= ~(1 << 3);
98 }
99 
usb_hci_set_passby(struct usbh_bus * bus)100 void usb_hci_set_passby(struct usbh_bus *bus)
101 {
102     /* AHB Master interface INCR16 enable */
103     /* AHB Master interface INCR8 enable */
104     /* AHB Master interface burst type INCR4 enable */
105     /* AHB Master interface INCRX align enable */
106     /* ULPI bypass enable */
107     *(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x800) |= (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 0);
108 }
109 
t113_ehci_isr(int vector,void * arg)110 void t113_ehci_isr(int vector, void *arg)
111 {
112     rt_interrupt_enter();
113 
114     struct usbh_bus *bus = (struct usbh_bus *)arg;
115 
116     USB_LOG_DBG("t113_ehci_isr");
117 
118     extern void USBH_IRQHandler(uint8_t busid);
119     USBH_IRQHandler(bus->hcd.hcd_id);
120 
121     rt_interrupt_leave();
122 }
123 
124 #ifdef CONFIG_USB_EHCI_WITH_OHCI
125 
t113_ohci_isr(int vector,void * arg)126 void t113_ohci_isr(int vector, void *arg)
127 {
128     rt_interrupt_enter();
129 
130     struct usbh_bus *bus = (struct usbh_bus *)arg;
131 
132     USB_LOG_DBG("t113_ohci_isr");
133 
134     extern void OHCI_IRQHandler(uint8_t busid);
135     OHCI_IRQHandler(bus->hcd.hcd_id);
136 
137     rt_interrupt_leave();
138 }
139 
140 #endif
141 
usb_hc_low_level_init(struct usbh_bus * bus)142 void usb_hc_low_level_init(struct usbh_bus *bus)
143 {
144     int vector;
145     RT_ASSERT(bus->busid <= 1);
146 
147     usb_gate_open(bus->busid);
148     usb_clean_siddp(bus);
149     usb_hci_set_passby(bus);
150 
151     /* register EHCI interrupt callback */
152     vector = T113_IRQ_USB0_EHCI + (bus->busid > 0 ? 3 : 0);
153     rt_hw_interrupt_install(vector, t113_ehci_isr, bus, RT_NULL);
154     rt_hw_interrupt_umask(vector);
155 
156     /* register OHCI interrupt callback */
157 #ifdef CONFIG_USB_EHCI_WITH_OHCI
158     rt_hw_interrupt_install(vector + 1, t113_ohci_isr, bus, RT_NULL);
159     rt_hw_interrupt_set_priority(vector, 11 << 4);
160     rt_hw_interrupt_umask(vector + 1);
161 #endif
162 
163     USB_LOG_DBG("usb%d vector : %d, phy : %X\n", bus->busid, vector, *(volatile rt_uint32_t *)(bus->hcd.reg_base + 0x810));
164     USB_LOG_DBG("usb%d hc low level init success\n", bus->busid);
165 }
166 
usbh_get_port_speed(struct usbh_bus * bus,const uint8_t port)167 uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
168 {
169     /* Defined by individual manufacturers */
170     uint32_t regval;
171 
172     regval = EHCI_HCOR->portsc[port - 1];
173     if ((regval & EHCI_PORTSC_LSTATUS_MASK) == EHCI_PORTSC_LSTATUS_KSTATE)
174         return USB_SPEED_LOW;
175 
176     if (regval & EHCI_PORTSC_PE)
177         return USB_SPEED_HIGH;
178     else
179         return USB_SPEED_FULL;
180 }
181 
__usbh_init(void)182 int __usbh_init(void)
183 {
184 #ifdef T113_USING_USB0_HOST
185     /* USB0 MSC test OK */
186     usbh_initialize(0, USB0_BASE_ADDR);
187 #endif
188 
189 #ifdef T113_USING_USB1_HOST
190     /* USB1 MSC test OK */
191     usbh_initialize(1, USB1_BASE_ADDR);
192 #endif
193     return 0;
194 }
195 
196 #ifdef PKG_CHERRYUSB_HOST
197 
198 #include <rtthread.h>
199 #include <rtdevice.h>
200 
201 INIT_ENV_EXPORT(__usbh_init);
202 
203 #endif
204