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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
/*
* Copyright (c) 2022, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <aic_core.h>
#include <aic_hal.h>
#include <hal_syscfg.h>
#include "usbh_core.h"
#include "usb_hc_ehci.h"
#include "usb_hc_ohci.h"
#if !defined(CONFIG_USB_EHCI_CONFIGFLAG)
#error "aic ehci must define CONFIG_USB_EHCI_CONFIGFLAG"
#endif
#if !defined(CONFIG_USB_EHCI_WITH_OHCI)
#error "aic must define CONFIG_USB_EHCI_WITH_OHCI for ls/fs device"
#endif
#if CONFIG_USB_OHCI_HCOR_OFFSET != 0x400
#error "aic CONFIG_USB_OHCI_HCOR_OFFSET must be 0x400"
#endif
extern void USBH_IRQHandler(uint8_t busid);
static void aic_ehci_isr(int vector, void *arg)
{
struct usbh_bus *bus = (struct usbh_bus *)arg;
extern void USBH_IRQHandler(uint8_t busid);
USBH_IRQHandler(bus->hcd.hcd_id);
}
static void aic_ohci_isr(int vector, void *arg)
{
struct usbh_bus *bus = (struct usbh_bus *)arg;
extern void OHCI_IRQHandler(uint8_t busid);
OHCI_IRQHandler(bus->hcd.hcd_id);
}
typedef struct aic_ehci_config {
uint32_t base_addr;
uint32_t clk_id;
uint32_t rst_id;
uint32_t phy_clk_id;
uint32_t phy_rst_id;
uint32_t irq_num;
} aic_ehci_config_t;
aic_ehci_config_t config[] = {
#ifdef AIC_USING_USB0_HOST
{ USB_HOST0_BASE,
CLK_USBH0,
RESET_USBH0,
CLK_USB_PHY0,
RESET_USBPHY0,
USB_HOST0_EHCI_IRQn },
#else
{ 0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF,
0xFFFFFFFF },
#endif
#ifdef AIC_USING_USB1_HOST
{ USB_HOST1_BASE,
CLK_USBH1,
RESET_USBH1,
CLK_USB_PHY1,
RESET_USBPHY1,
USB_HOST1_EHCI_IRQn }
#endif
};
void usb_hc_low_level_init(struct usbh_bus *bus)
{
uint32_t val;
int i = 0;
for (i = 0; i < sizeof(config) / sizeof(aic_ehci_config_t); i++) {
if (bus->hcd.reg_base == config[i].base_addr)
break;
}
if (i == sizeof(config) / sizeof(aic_ehci_config_t))
return;
/* set usb0 phy switch: Host/Device */
if (i == 0)
syscfg_usb_phy0_sw_host(1);
/* enable clock */
hal_clk_enable(config[i].phy_clk_id);
hal_clk_enable(config[i].clk_id);
aicos_udelay(300);
hal_reset_assert(config[i].phy_rst_id);
hal_reset_assert(config[i].rst_id);
aicos_udelay(300);
hal_reset_deassert(config[i].phy_rst_id);
hal_reset_deassert(config[i].rst_id);
aicos_udelay(300);
/* set phy type: UTMI/ULPI */
val = readl((volatile void *)(unsigned long)(config[i].base_addr + 0x800));
#ifdef FPGA_BOARD_ARTINCHIP
/* fpga phy type = ULPI */
writel((val & ~0x1U), (volatile void *)(unsigned long)(config[i].base_addr + 0x800));
#else
/* board phy type = UTMI */
writel((val | 0x1), (volatile void *)(unsigned long)(config[i].base_addr + 0x800));
#endif
/* Set AHB2STBUS_INSREG01
Set EHCI packet buffer IN/OUT threshold (in DWORDs)
Must increase the OUT threshold to avoid underrun. (FIFO size - 4)
*/
writel((32 | (127 << 16)), (volatile void *)(unsigned long)(config[i].base_addr + 0x94));
/* register interrupt callback */
aicos_request_irq(config[i].irq_num, (irq_handler_t)aic_ehci_isr,
0, "usb_host_ehci", bus);
aicos_request_irq(config[i].irq_num + 1, (irq_handler_t)aic_ohci_isr,
0, "usb_host_ohci", bus);
aicos_irq_enable(config[i].irq_num);
aicos_irq_enable(config[i].irq_num + 1);
}
uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
{
return USB_SPEED_HIGH;
}
void usb_ehci_dcache_clean(uintptr_t addr, uint32_t len)
{
aicos_dcache_clean_range((size_t *)addr, len);
}
void usb_ehci_dcache_invalidate(uintptr_t addr, uint32_t len)
{
aicos_dcache_invalid_range((size_t *)addr, len);
}
void usb_ehci_dcache_clean_invalidate(uintptr_t addr, uint32_t len)
{
aicos_dcache_clean_invalid_range((size_t *)addr, len);
}
int __usbh_init(void)
{
#if defined(AIC_USING_USB0_HOST) || defined(AIC_USING_USB1_HOST)
int bus_id = 0;
#endif
#ifdef AIC_USING_USB0_HOST
usbh_initialize(bus_id, USB_HOST0_BASE, NULL);
bus_id++;
#endif
#ifdef AIC_USING_USB1_HOST
usbh_initialize(bus_id, USB_HOST1_BASE, NULL);
bus_id++;
#endif
return 0;
}
#if defined(KERNEL_RTTHREAD)
#include <rtthread.h>
#include <rtdevice.h>
INIT_ENV_EXPORT(__usbh_init);
#endif
|