diff options
author | Tobias Diedrich <ranma+coreboot@tdiedrich.de> | 2010-05-18 07:00:57 +0000 |
---|---|---|
committer | Tobias Diedrich <ranma+coreboot@tdiedrich.de> | 2010-05-18 07:00:57 +0000 |
commit | 922f83e64729910dcc83e66cd5aa54c9a4bd4cd2 (patch) | |
tree | eb698f97f936886487bf11baa63c3848223409ea /firmware/target/arm/as3525 | |
parent | c23a7ccbbc9e8e817503bac5c1401125ef23a136 (diff) | |
download | rockbox-922f83e64729910dcc83e66cd5aa54c9a4bd4cd2.tar.gz rockbox-922f83e64729910dcc83e66cd5aa54c9a4bd4cd2.zip |
Not quite working yet, but almost.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26126 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/as3525')
-rw-r--r-- | firmware/target/arm/as3525/system-as3525.c | 6 | ||||
-rw-r--r-- | firmware/target/arm/as3525/usb-drv-as3525.c | 982 |
2 files changed, 831 insertions, 157 deletions
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index d79caadf1b..ba8aa43715 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c | |||
@@ -114,6 +114,7 @@ struct vec_int_src vec_int_srcs[] = | |||
114 | { INT_SRC_NAND, INT_NAND }, | 114 | { INT_SRC_NAND, INT_NAND }, |
115 | { INT_SRC_I2C_AUDIO, INT_I2C_AUDIO }, | 115 | { INT_SRC_I2C_AUDIO, INT_I2C_AUDIO }, |
116 | { INT_SRC_AUDIO, INT_AUDIO }, | 116 | { INT_SRC_AUDIO, INT_AUDIO }, |
117 | { INT_SRC_USB, INT_USB, }, | ||
117 | #if (defined HAVE_MULTIDRIVE && CONFIG_CPU == AS3525) | 118 | #if (defined HAVE_MULTIDRIVE && CONFIG_CPU == AS3525) |
118 | { INT_SRC_MCI0, INT_MCI0 }, | 119 | { INT_SRC_MCI0, INT_MCI0 }, |
119 | #endif | 120 | #endif |
@@ -324,7 +325,7 @@ void system_init(void) | |||
324 | CGU_PLLASUP = 0; /* enable PLLA */ | 325 | CGU_PLLASUP = 0; /* enable PLLA */ |
325 | while(!(CGU_INTCTRL & (1<<0))); /* wait until PLLA is locked */ | 326 | while(!(CGU_INTCTRL & (1<<0))); /* wait until PLLA is locked */ |
326 | 327 | ||
327 | #if (AS3525_MCLK_SEL == AS3525_CLK_PLLB) | 328 | #if defined(USE_ROCKBOX_USB) || (AS3525_MCLK_SEL == AS3525_CLK_PLLB) |
328 | CGU_COUNTB = 0xff; | 329 | CGU_COUNTB = 0xff; |
329 | CGU_PLLB = AS3525_PLLB_SETTING; | 330 | CGU_PLLB = AS3525_PLLB_SETTING; |
330 | CGU_PLLBSUP = 0; /* enable PLLB */ | 331 | CGU_PLLBSUP = 0; /* enable PLLB */ |
@@ -392,6 +393,9 @@ void system_reboot(void) | |||
392 | 393 | ||
393 | void system_exception_wait(void) | 394 | void system_exception_wait(void) |
394 | { | 395 | { |
396 | /* make sure backlight is on */ | ||
397 | _backlight_on(); | ||
398 | _backlight_pwm(1); | ||
395 | /* wait until button release (if a button is pressed) */ | 399 | /* wait until button release (if a button is pressed) */ |
396 | while(button_read_device()); | 400 | while(button_read_device()); |
397 | /* then wait until next button press */ | 401 | /* then wait until next button press */ |
diff --git a/firmware/target/arm/as3525/usb-drv-as3525.c b/firmware/target/arm/as3525/usb-drv-as3525.c index 488fbff6b1..d6b9c1dfea 100644 --- a/firmware/target/arm/as3525/usb-drv-as3525.c +++ b/firmware/target/arm/as3525/usb-drv-as3525.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "system.h" | ||
22 | #include "usb.h" | 23 | #include "usb.h" |
23 | #include "usb_drv.h" | 24 | #include "usb_drv.h" |
24 | #include "as3525.h" | 25 | #include "as3525.h" |
@@ -28,169 +29,489 @@ | |||
28 | #include <stdbool.h> | 29 | #include <stdbool.h> |
29 | #include "panic.h" | 30 | #include "panic.h" |
30 | /*#define LOGF_ENABLE*/ | 31 | /*#define LOGF_ENABLE*/ |
32 | #define LOGF_ENABLE | ||
31 | #include "logf.h" | 33 | #include "logf.h" |
34 | #include "usb_ch9.h" | ||
35 | #include "usb_core.h" | ||
36 | #include "string.h" | ||
32 | 37 | ||
38 | #define USB_NUM_EPS 4 | ||
39 | |||
40 | typedef struct { | ||
41 | volatile unsigned long offset[4096]; | ||
42 | } __regbase; | ||
43 | |||
44 | /* | ||
45 | * This generates better code. | ||
46 | * Stripped object size with __regbase construct: 5192 | ||
47 | * Stripped object size with *((volatile int)(x)): 5228 | ||
48 | */ | ||
49 | #define USB_REG(x) ((__regbase *)(USB_BASE))->offset[(x)>>2] | ||
33 | 50 | ||
34 | /* 4 input endpoints */ | 51 | /* 4 input endpoints */ |
35 | #define USB_IEP_CTRL(i) *((volatile unsigned long*) (USB_BASE + 0x0000 + (i*0x20))) | 52 | #define USB_IEP_CTRL(i) USB_REG(0x0000 + i*0x20) |
36 | #define USB_IEP_STS(i) *((volatile unsigned long*) (USB_BASE + 0x0004 + (i*0x20))) | 53 | #define USB_IEP_STS(i) USB_REG(0x0004 + i*0x20) |
37 | #define USB_IEP_TXFSIZE(i) *((volatile unsigned long*) (USB_BASE + 0x0008 + (i*0x20))) | 54 | #define USB_IEP_TXFSIZE(i) USB_REG(0x0008 + i*0x20) |
38 | #define USB_IEP_MPS(i) *((volatile unsigned long*) (USB_BASE + 0x000C + (i*0x20))) | 55 | #define USB_IEP_MPS(i) USB_REG(0x000C + i*0x20) |
39 | #define USB_IEP_DESC_PTR(i) *((volatile unsigned long*) (USB_BASE + 0x0014 + (i*0x20))) | 56 | #define USB_IEP_DESC_PTR(i) USB_REG(0x0014 + i*0x20) |
40 | #define USB_IEP_STS_MASK(i) *((volatile unsigned long*) (USB_BASE + 0x0018 + (i*0x20))) | 57 | #define USB_IEP_STS_MASK(i) USB_REG(0x0018 + i*0x20) |
41 | 58 | ||
42 | /* 4 output endpoints */ | 59 | /* 4 output endpoints */ |
43 | #define USB_OEP_CTRL(i) *((volatile unsigned long*) (USB_BASE + 0x0200 + (i*0x20))) | 60 | #define USB_OEP_CTRL(i) USB_REG(0x0200 + i*0x20) |
44 | #define USB_OEP_STS(i) *((volatile unsigned long*) (USB_BASE + 0x0204 + (i*0x20))) | 61 | #define USB_OEP_STS(i) USB_REG(0x0204 + i*0x20) |
45 | #define USB_OEP_RXFR(i) *((volatile unsigned long*) (USB_BASE + 0x0208 + (i*0x20))) | 62 | #define USB_OEP_RXFR(i) USB_REG(0x0208 + i*0x20) |
46 | #define USB_OEP_MPS(i) *((volatile unsigned long*) (USB_BASE + 0x020C + (i*0x20))) | 63 | #define USB_OEP_MPS(i) USB_REG(0x020C + i*0x20) |
47 | #define USB_OEP_SUP_PTR(i) *((volatile unsigned long*) (USB_BASE + 0x0210 + (i*0x20))) | 64 | #define USB_OEP_SUP_PTR(i) USB_REG(0x0210 + i*0x20) |
48 | #define USB_OEP_DESC_PTR(i) *((volatile unsigned long*) (USB_BASE + 0x0214 + (i*0x20))) | 65 | #define USB_OEP_DESC_PTR(i) USB_REG(0x0214 + i*0x20) |
49 | #define USB_OEP_STS_MASK(i) *((volatile unsigned long*) (USB_BASE + 0x0218 + (i*0x20))) | 66 | #define USB_OEP_STS_MASK(i) USB_REG(0x0218 + i*0x20) |
50 | 67 | ||
51 | #define USB_DEV_CFG *((volatile unsigned long*) (USB_BASE + 0x0400)) | 68 | /* more general macro */ |
52 | #define USB_DEV_CTRL *((volatile unsigned long*) (USB_BASE + 0x0404)) | 69 | /* d: true => IN, false => OUT */ |
53 | #define USB_DEV_STS *((volatile unsigned long*) (USB_BASE + 0x0408)) | 70 | #define USB_EP_CTRL(i,d) USB_REG(0x0000 + i*0x20 + (!d)*0x0200) |
54 | #define USB_DEV_INTR *((volatile unsigned long*) (USB_BASE + 0x040C)) | 71 | #define USB_EP_STS(i,d) USB_REG(0x0004 + i*0x20 + (!d)*0x0200) |
55 | #define USB_DEV_INTR_MASK *((volatile unsigned long*) (USB_BASE + 0x0410)) | 72 | #define USB_EP_TXFSIZE(i,d) USB_REG(0x0008 + i*0x20 + (!d)*0x0200) |
56 | #define USB_DEV_EP_INTR *((volatile unsigned long*) (USB_BASE + 0x0414)) | 73 | #define USB_EP_MPS(i,d) USB_REG(0x000C + i*0x20 + (!d)*0x0200) |
57 | #define USB_DEV_EP_INTR_MASK *((volatile unsigned long*) (USB_BASE + 0x0418)) | 74 | #define USB_EP_DESC_PTR(i,d) USB_REG(0x0014 + i*0x20 + (!d)*0x0200) |
58 | 75 | #define USB_EP_STS_MASK(i,d) USB_REG(0x0018 + i*0x20 + (!d)*0x0200) | |
59 | #define USB_PHY_EP0_INFO *((volatile unsigned long*) (USB_BASE + 0x0504)) | 76 | |
60 | #define USB_PHY_EP1_INFO *((volatile unsigned long*) (USB_BASE + 0x0508)) | 77 | #define USB_DEV_CFG USB_REG(0x0400) |
61 | #define USB_PHY_EP2_INFO *((volatile unsigned long*) (USB_BASE + 0x050C)) | 78 | #define USB_DEV_CTRL USB_REG(0x0404) |
62 | #define USB_PHY_EP3_INFO *((volatile unsigned long*) (USB_BASE + 0x0510)) | 79 | #define USB_DEV_STS USB_REG(0x0408) |
63 | #define USB_PHY_EP4_INFO *((volatile unsigned long*) (USB_BASE + 0x0514)) | 80 | #define USB_DEV_INTR USB_REG(0x040C) |
64 | #define USB_PHY_EP5_INFO *((volatile unsigned long*) (USB_BASE + 0x0518)) | 81 | #define USB_DEV_INTR_MASK USB_REG(0x0410) |
82 | #define USB_DEV_EP_INTR USB_REG(0x0414) | ||
83 | #define USB_DEV_EP_INTR_MASK USB_REG(0x0418) | ||
84 | |||
85 | /* NOTE: Not written to in OF, most lied in host mode? */ | ||
86 | #define USB_PHY_EP0_INFO USB_REG(0x0504) | ||
87 | #define USB_PHY_EP1_INFO USB_REG(0x0508) | ||
88 | #define USB_PHY_EP2_INFO USB_REG(0x050C) | ||
89 | #define USB_PHY_EP3_INFO USB_REG(0x0510) | ||
90 | #define USB_PHY_EP4_INFO USB_REG(0x0514) | ||
91 | #define USB_PHY_EP5_INFO USB_REG(0x0518) | ||
65 | 92 | ||
66 | /* 4 channels */ | 93 | /* 4 channels */ |
67 | #define USB_HOST_CH_SPLT(i) *((volatile unsigned long*) (USB_BASE + 0x1000 + (i*0x20))) | 94 | #define USB_HOST_CH_SPLT(i) USB_REG(0x1000 + i*0x20) |
68 | #define USB_HOST_CH_STS(i) *((volatile unsigned long*) (USB_BASE + 0x1004 + (i*0x20))) | 95 | #define USB_HOST_CH_STS(i) USB_REG(0x1004 + i*0x20) |
69 | #define USB_HOST_CH_TXFSIZE(i) *((volatile unsigned long*) (USB_BASE + 0x1008 + (i*0x20))) | 96 | #define USB_HOST_CH_TXFSIZE(i) USB_REG(0x1008 + i*0x20) |
70 | #define USB_HOST_CH_REQ(i) *((volatile unsigned long*) (USB_BASE + 0x100C + (i*0x20))) | 97 | #define USB_HOST_CH_REQ(i) USB_REG(0x100C + i*0x20) |
71 | #define USB_HOST_CH_PER_INFO(i) *((volatile unsigned long*) (USB_BASE + 0x1010 + (i*0x20))) | 98 | #define USB_HOST_CH_PER_INFO(i) USB_REG(0x1010 + i*0x20) |
72 | #define USB_HOST_CH_DESC_PTR(i) *((volatile unsigned long*) (USB_BASE + 0x1014 + (i*0x20))) | 99 | #define USB_HOST_CH_DESC_PTR(i) USB_REG(0x1014 + i*0x20) |
73 | #define USB_HOST_CH_STS_MASK(i) *((volatile unsigned long*) (USB_BASE + 0x1018 + (i*0x20))) | 100 | #define USB_HOST_CH_STS_MASK(i) USB_REG(0x1018 + i*0x20) |
74 | 101 | ||
75 | #define USB_HOST_CFG *((volatile unsigned long*) (USB_BASE + 0x1400)) | 102 | #define USB_HOST_CFG USB_REG(0x1400) |
76 | #define USB_HOST_CTRL *((volatile unsigned long*) (USB_BASE + 0x1404)) | 103 | #define USB_HOST_CTRL USB_REG(0x1404) |
77 | #define USB_HOST_INTR *((volatile unsigned long*) (USB_BASE + 0x140C)) | 104 | #define USB_HOST_INTR USB_REG(0x140C) |
78 | #define USB_HOST_INTR_MASK *((volatile unsigned long*) (USB_BASE + 0x1410)) | 105 | #define USB_HOST_INTR_MASK USB_REG(0x1410) |
79 | #define USB_HOST_CH_INTR *((volatile unsigned long*) (USB_BASE + 0x1414)) | 106 | #define USB_HOST_CH_INTR USB_REG(0x1414) |
80 | #define USB_HOST_CH_INTR_MASK *((volatile unsigned long*) (USB_BASE + 0x1418)) | 107 | #define USB_HOST_CH_INTR_MASK USB_REG(0x1418) |
81 | #define USB_HOST_FRAME_INT *((volatile unsigned long*) (USB_BASE + 0x141C)) | 108 | #define USB_HOST_FRAME_INT USB_REG(0x141C) |
82 | #define USB_HOST_FRAME_REM *((volatile unsigned long*) (USB_BASE + 0x1420)) | 109 | #define USB_HOST_FRAME_REM USB_REG(0x1420) |
83 | #define USB_HOST_FRAME_NUM *((volatile unsigned long*) (USB_BASE + 0x1424)) | 110 | #define USB_HOST_FRAME_NUM USB_REG(0x1424) |
84 | 111 | ||
85 | #define USB_HOST_PORT0_CTRL_STS *((volatile unsigned long*) (USB_BASE + 0x1500)) | 112 | #define USB_HOST_PORT0_CTRL_STS USB_REG(0x1500) |
86 | 113 | ||
87 | #define USB_OTG_CSR *((volatile unsigned long*) (USB_BASE + 0x2000)) | 114 | #define USB_OTG_CSR USB_REG(0x2000) |
88 | #define USB_I2C_CSR *((volatile unsigned long*) (USB_BASE + 0x2004)) | 115 | #define USB_I2C_CSR USB_REG(0x2004) |
89 | #define USB_GPIO_CSR *((volatile unsigned long*) (USB_BASE + 0x2008)) | 116 | #define USB_GPIO_CSR USB_REG(0x2008) |
90 | #define USB_SNPSID_CSR *((volatile unsigned long*) (USB_BASE + 0x200C)) | 117 | #define USB_SNPSID_CSR USB_REG(0x200C) |
91 | #define USB_USERID_CSR *((volatile unsigned long*) (USB_BASE + 0x2010)) | 118 | #define USB_USERID_CSR USB_REG(0x2010) |
92 | #define USB_USER_CONF1 *((volatile unsigned long*) (USB_BASE + 0x2014)) | 119 | #define USB_USER_CONF1 USB_REG(0x2014) |
93 | #define USB_USER_CONF2 *((volatile unsigned long*) (USB_BASE + 0x2018)) | 120 | #define USB_USER_CONF2 USB_REG(0x2018) |
94 | #define USB_USER_CONF3 *((volatile unsigned long*) (USB_BASE + 0x201C)) | 121 | #define USB_USER_CONF3 USB_REG(0x201C) |
95 | #define USB_USER_CONF4 *((volatile unsigned long*) (USB_BASE + 0x2020)) | 122 | #define USB_USER_CONF4 USB_REG(0x2020) |
96 | #define USB_USER_CONF5 *((volatile unsigned long*) (USB_BASE + 0x2024)) | 123 | /* USER_CONF5 seems to the same as USBt least on read */ |
124 | #define USB_USER_CONF5 USB_REG(0x2024) | ||
125 | |||
126 | /* write bits 31..16 */ | ||
127 | #define USB_GPIO_IDDIG_SEL (1<<30) | ||
128 | #define USB_GPIO_FS_DATA_EXT (1<<29) | ||
129 | #define USB_GPIO_FS_SE0_EXT (1<<28) | ||
130 | #define USB_GPIO_FS_XCVR_OWNER (1<<27) | ||
131 | #define USB_GPIO_TX_ENABLE_N (1<<26) | ||
132 | #define USB_GPIO_TX_BIT_STUFF_EN (1<<25) | ||
133 | #define USB_GPIO_BSESSVLD_EXT (1<<24) | ||
134 | #define USB_GPIO_ASESSVLD_EXT (1<<23) | ||
135 | #define USB_GPIO_VBUS_VLD_EXT (1<<22) | ||
136 | #define USB_GPIO_VBUS_VLD_EXT_SEL (1<<21) | ||
137 | #define USB_GPIO_XO_ON (1<<20) | ||
138 | #define USB_GPIO_CLK_SEL11 (3<<18) | ||
139 | #define USB_GPIO_CLK_SEL10 (2<<18) | ||
140 | #define USB_GPIO_CLK_SEL01 (1<<18) | ||
141 | #define USB_GPIO_CLK_SEL00 (0<<18) | ||
142 | #define USB_GPIO_XO_EXT_CLK_ENBN (1<<17) | ||
143 | #define USB_GPIO_XO_REFCLK_ENB (1<<16) | ||
144 | /* readronly bits 15..0 */ | ||
145 | #define USB_GPIO_PHY_VBUSDRV (1<< 1) | ||
146 | #define USB_GPIO_HS_INTR (1<< 0) | ||
147 | |||
148 | /* Device Control Register and bit fields */ | ||
149 | #define USB_DEV_CTRL_REMOTE_WAKEUP 0x00000001 // set remote wake-up signal | ||
150 | #define USB_DEV_CTRL_RDE 0x00000004 // receive dma enable | ||
151 | #define USB_DEV_CTRL_DESC_UPDATE 0x00000010 // descriptor update | ||
152 | #define USB_DEV_CTRL_THRES_ENABLE 0x00000080 // threshold enable | ||
153 | #define USB_DEV_CTRL_BURST_CONTROL 0x00000100 // burst control | ||
154 | #define USB_DEV_CTRL_SOFT_DISCONN 0x00000400 // soft disconnect | ||
155 | #define USB_DEV_CTRL_APCSR_DONE 0x00002000 // app Prog CSR Done | ||
156 | #define USB_DEV_CTRL_MASK_BURST_LEN 0x000f0000 // mask for burst length | ||
157 | #define USB_DEV_CTRL_MASK_THRESHOLD_LEN 0xff000000 // mask for threshold length | ||
158 | |||
159 | /* settings of burst length for maskBurstLen_c field */ | ||
160 | #define USB_DEV_CTRL_BLEN_1DWORD 0x00000000 | ||
161 | #define USB_DEV_CTRL_BLEN_2DWORDS 0x00010000 | ||
162 | #define USB_DEV_CTRL_BLEN_4DWORDS 0x00020000 | ||
163 | #define USB_DEV_CTRL_BLEN_8DWORDS 0x00030000 | ||
164 | #define USB_DEV_CTRL_BLEN_16DWORDS 0x00040000 | ||
165 | #define USB_DEV_CTRL_BLEN_32DWORDS 0x00050000 | ||
166 | #define USB_DEV_CTRL_BLEN_64DWORDS 0x00060000 | ||
167 | #define USB_DEV_CTRL_BLEN_128DWORDS 0x00070000 | ||
168 | #define USB_DEV_CTRL_BLEN_256DWORDS 0x00080000 | ||
169 | #define USB_DEV_CTRL_BLEN_512DWORDS 0x00090000 | ||
170 | |||
171 | /* settings of threshold length for maskThresholdLen_c field */ | ||
172 | #define USB_DEV_CTRL_TLEN_1DWORD 0x00000000 | ||
173 | #define USB_DEV_CTRL_TLEN_HALFMAXSIZE 0x01000000 | ||
174 | #define USB_DEV_CTRL_TLEN_4THMAXSIZE 0x02000000 | ||
175 | #define USB_DEV_CTRL_TLEN_8THMAXSIZE 0x03000000 | ||
176 | |||
177 | #define USB_DEV_CFG_HS 0x00000000 | ||
178 | #define USB_DEV_CFG_FS 0x00000001 /* 30 or 60MHz */ | ||
179 | #define USB_DEV_CFG_LS 0x00000002 | ||
180 | #define USB_DEV_CFG_FS_48 0x00000003 /* 48MHz */ | ||
181 | #define USB_DEV_CFG_REMOTE_WAKEUP 0x00000004 | ||
182 | #define USB_DEV_CFG_SELF_POWERED 0x00000008 | ||
183 | #define USB_DEV_CFG_SYNC_FRAME 0x00000010 | ||
184 | #define USB_DEV_CFG_PI_16BIT 0x00000000 | ||
185 | #define USB_DEV_CFG_PI_8BIT 0x00000020 | ||
186 | #define USB_DEV_CFG_UNI_DIR 0x00000000 | ||
187 | #define USB_DEV_CFG_BI_DIR 0x00000040 | ||
188 | #define USB_DEV_CFG_STAT_ACK 0x00000000 | ||
189 | #define USB_DEV_CFG_STAT_STALL 0x00000080 | ||
190 | |||
191 | /* Device Status Register and bit fields */ | ||
192 | #define USB_DEV_STS_MASK_CFG 0x0000000f | ||
193 | #define USB_DEV_STS_MASK_IF 0x000000f0 | ||
194 | #define USB_DEV_STS_MASK_ALT_SET 0x00000f00 | ||
195 | #define USB_DEV_STS_SUSPEND_STAT 0x00001000 | ||
196 | #define USB_DEV_STS_MASK_SPD 0x00006000 /* Enumerated Speed */ | ||
197 | #define USB_DEV_STS_SPD_HS 0x00000000 | ||
198 | #define USB_DEV_STS_SPD_FS 0x00002000 | ||
199 | #define USB_DEV_STS_SPD_LS 0x00004000 | ||
200 | #define USB_DEV_STS_RXF_EMPTY 0x00008000 | ||
201 | #define USB_DEV_STS_MASK_FRM_NUM 0xfffc0000 /* SOF frame number */ | ||
202 | |||
203 | |||
204 | /* Device Intr Register and bit fields */ | ||
205 | #define USB_DEV_INTR_SET_CONFIG 0x00000001 /* set configuration cmd rcvd */ | ||
206 | #define USB_DEV_INTR_SET_INTERFACE 0x00000002 /* set interface command rcvd */ | ||
207 | #define USB_DEV_INTR_EARLY_SUSPEND 0x00000004 /* idle on usb for 3ms */ | ||
208 | #define USB_DEV_INTR_USB_RESET 0x00000008 /* usb bus reset req */ | ||
209 | #define USB_DEV_INTR_USB_SUSPEND 0x00000010 /* usb bus suspend req */ | ||
210 | #define USB_DEV_INTR_SOF 0x00000020 /* SOF seen on bus */ | ||
211 | #define USB_DEV_INTR_ENUM_DONE 0x00000040 /* usb speed enum done */ | ||
212 | #define USB_DEV_INTR_OTG 0x00000080 /* otg status change? */ | ||
213 | #define USB_DEV_INTR_BUSERR 0x00000080 /* AHB DMA error */ | ||
214 | |||
215 | /* EP Control Register Fields */ | ||
216 | #define USB_EP_CTRL_STALL 0x00000001 | ||
217 | #define USB_EP_CTRL_FLUSH 0x00000002 /* EP In data fifo Flush */ | ||
218 | #define USB_EP_CTRL_SNOOP_MODE 0x00000004 // snoop mode for out endpoint | ||
219 | #define USB_EP_CTRL_PD 0x00000008 /* EP Poll Demand */ | ||
220 | #define USB_EP_CTRL_EPTYPE_MASK 0x00000030 // bit 5-4: endpoint types | ||
221 | #define USB_EP_TYPE_CONTROL 0x00000000 // control endpoint | ||
222 | #define USB_EP_TYPE_ISO 0x00000010 // isochronous endpoint | ||
223 | #define USB_EP_TYPE_BULK 0x00000020 // bulk endpoint | ||
224 | #define USB_EP_TYPE_INTERRUPT 0x00000030 // interrupt endpoint | ||
225 | #define USB_EP_CTRL_NAK 0x00000040 /* EP NAK Status */ | ||
226 | #define USB_EP_CTRL_SNAK 0x00000080 /* EP Set NAK Bit */ | ||
227 | #define USB_EP_CTRL_CNAK 0x00000100 /* EP Clr NAK Bit */ | ||
228 | #define USB_EP_CTRL_ACT 0x00000400 /* EP Clr NAK Bit */ | ||
229 | |||
230 | /* bit fields in EP Status Register */ | ||
231 | #define USB_EP_STAT_OUT_RCVD 0x00000010 /* OUT token received */ | ||
232 | #define USB_EP_STAT_SETUP_RCVD 0x00000020 /* SETUP token received */ | ||
233 | #define USB_EP_STAT_IN 0x00000040 /* IN token received? */ | ||
234 | #define USB_EP_STAT_BNA 0x00000080 /* Buffer Not Available */ | ||
235 | #define USB_EP_STAT_BUFF_ERROR 0x00000100 | ||
236 | #define USB_EP_STAT_HERR 0x00000200 /* Host Error */ | ||
237 | #define USB_EP_STAT_AHB_ERROR 0x00000200 | ||
238 | #define USB_EP_STAT_TDC 0x00000400 /* Transmit DMA Complete */ | ||
239 | |||
240 | /*-------------------------*/ | ||
241 | /* DMA Related Definitions */ | ||
242 | /*-------------------------*/ | ||
243 | |||
244 | /* dma status */ | ||
245 | #define USB_DMA_DESC_BUFF_STS 0x80000000 /* Buffer Status */ | ||
246 | #define USB_DMA_DESC_BS_HST_RDY 0x80000000 /* Host Ready */ | ||
247 | #define USB_DMA_DESC_BS_DMA_DONE 0x00000000 /* DMA Done */ | ||
248 | #define USB_DMA_DESC_ZERO_LEN 0x40000000 /* zero length packet */ | ||
249 | #define USB_DMA_DESC_EARY_INTR 0x20000000 /* early interrupt */ | ||
250 | #define USB_DMA_DESC_RXTX_STS 0x10000000 | ||
251 | #define USB_DMA_DESC_RTS_SUCC 0x00000000 /* Success */ | ||
252 | #define USB_DMA_DESC_RTS_BUFERR 0x10000000 /* Buffer Error */ | ||
253 | #define USB_DMA_DESC_LAST 0x08000000 | ||
254 | #define USB_DMA_DESC_MASK_FRAM_NUM 0x07ff0000 // bits 26-16: frame number for iso | ||
255 | #define USB_DMA_DESC_RXTX_BYTES 0x0000FFFF | ||
256 | |||
257 | /* setup descriptor */ | ||
258 | #define SETUP_MASK_CONFIG_STAT 0x0fff0000 | ||
259 | #define SETUP_MASK_CONFIG_NUM 0x0f000000 | ||
260 | #define SETUP_MASK_IF_NUM 0x00f00000 | ||
261 | #define SETUP_MASK_ALT_SETNUM 0x000f0000 | ||
262 | |||
263 | #define EP_STATE_ALLOCATED 0x00000001 | ||
264 | #define EP_STATE_BUSY 0x00000002 | ||
265 | #define EP_STATE_ASYNC 0x00000004 | ||
266 | |||
267 | struct usb_dev_dma_desc { | ||
268 | int status; | ||
269 | int resv; | ||
270 | void *data_ptr; | ||
271 | void *next_desc; | ||
272 | }; | ||
273 | |||
274 | struct usb_dev_setup_buf { | ||
275 | int status; | ||
276 | int resv; | ||
277 | int data1; /* first 4 bytes of data */ | ||
278 | int data2; /* last 4 bytes of data */ | ||
279 | }; | ||
97 | 280 | ||
98 | struct usb_endpoint | 281 | struct usb_endpoint |
99 | { | 282 | { |
100 | void *buf; | 283 | void *buf; |
101 | unsigned int len; | 284 | unsigned int len; |
102 | union | 285 | volatile unsigned int state; |
103 | { | 286 | int rc; |
104 | unsigned int sent; | 287 | struct wakeup complete; |
105 | unsigned int received; | 288 | struct usb_dev_dma_desc *uc_desc; |
106 | }; | ||
107 | bool wait; | ||
108 | bool busy; | ||
109 | }; | 289 | }; |
110 | 290 | ||
111 | static struct usb_endpoint endpoints[USB_NUM_ENDPOINTS*2]; | 291 | static struct usb_endpoint endpoints[USB_NUM_EPS][2]; |
292 | |||
293 | /* | ||
294 | * dma/setup descriptors and buffers should avoid sharing | ||
295 | * a cacheline with other data. | ||
296 | * dmadescs may share with each other, since we only access them uncached. | ||
297 | */ | ||
298 | static struct usb_dev_dma_desc dmadescs[USB_NUM_EPS][2] __attribute__((aligned(32))); | ||
299 | |||
300 | static struct usb_dev_setup_buf setup_desc; | ||
301 | /* Dummy buffer, to keep rx_buf out of this cacheline */ | ||
302 | static struct usb_dev_setup_buf dummy __attribute__((unused)); | ||
303 | |||
304 | static char rx_buf[1024]; | ||
305 | static char tx_buf[1024]; | ||
112 | 306 | ||
113 | void usb_attach(void) | 307 | void usb_attach(void) |
114 | { | 308 | { |
115 | usb_enable(true); | 309 | usb_enable(true); |
116 | } | 310 | } |
117 | 311 | ||
118 | void usb_drv_init(void) | 312 | static inline void usb_delay(int delay) |
313 | { //TUNEME : delay is in milliseconds | ||
314 | delay <<= 14; | ||
315 | while(delay--) ; | ||
316 | } | ||
317 | |||
318 | static void usb_phy_on(void) | ||
319 | { | ||
320 | /* PHY clock */ | ||
321 | CGU_USB = 1<<5 /* enable */ | ||
322 | | (CLK_DIV(AS3525_PLLB_FREQ, 48000000) / 2) << 2 | ||
323 | | 2; /* source = PLLB */ | ||
324 | |||
325 | /* UVDD on */ | ||
326 | ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) | (1<<4)); | ||
327 | usb_delay(100); | ||
328 | |||
329 | /* reset */ | ||
330 | CCU_SRC = CCU_SRC_USB_AHB_EN|CCU_SRC_USB_PHY_EN; | ||
331 | CCU_SRL = CCU_SRL_MAGIC_NUMBER; | ||
332 | usb_delay(1); | ||
333 | CCU_SRC = CCU_SRC_USB_AHB_EN; | ||
334 | usb_delay(1); | ||
335 | CCU_SRC = CCU_SRL = 0; | ||
336 | |||
337 | USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N | ||
338 | | USB_GPIO_TX_BIT_STUFF_EN | ||
339 | | USB_GPIO_XO_ON | ||
340 | | USB_GPIO_CLK_SEL10; /* 0x06180000; */ | ||
341 | } | ||
342 | |||
343 | static void usb_phy_suspend(void) | ||
344 | { | ||
345 | USB_GPIO_CSR |= USB_GPIO_ASESSVLD_EXT | | ||
346 | USB_GPIO_BSESSVLD_EXT | | ||
347 | USB_GPIO_VBUS_VLD_EXT; | ||
348 | usb_delay(3); | ||
349 | USB_GPIO_CSR |= USB_GPIO_VBUS_VLD_EXT_SEL; | ||
350 | usb_delay(10); | ||
351 | } | ||
352 | |||
353 | static void usb_phy_resume(void) | ||
354 | { | ||
355 | USB_GPIO_CSR &= ~(USB_GPIO_ASESSVLD_EXT | | ||
356 | USB_GPIO_BSESSVLD_EXT | | ||
357 | USB_GPIO_VBUS_VLD_EXT); | ||
358 | usb_delay(3); | ||
359 | USB_GPIO_CSR &= ~USB_GPIO_VBUS_VLD_EXT_SEL; | ||
360 | usb_delay(10); | ||
361 | } | ||
362 | |||
363 | static void setup_desc_init(struct usb_dev_setup_buf *desc) | ||
364 | { | ||
365 | struct usb_dev_setup_buf *uc_desc = UNCACHED_ADDR(desc); | ||
366 | |||
367 | uc_desc->status = USB_DMA_DESC_BS_HST_RDY; | ||
368 | uc_desc->resv = 0xffffffff; | ||
369 | uc_desc->data1 = 0xffffffff; | ||
370 | uc_desc->data2 = 0xffffffff; | ||
371 | } | ||
372 | |||
373 | static void dma_desc_init(int ep, int dir) | ||
374 | { | ||
375 | struct usb_dev_dma_desc *desc = &dmadescs[ep][dir]; | ||
376 | struct usb_dev_dma_desc *uc_desc = UNCACHED_ADDR(desc); | ||
377 | |||
378 | endpoints[ep][dir].uc_desc = uc_desc; | ||
379 | |||
380 | if (dir == 0) { | ||
381 | uc_desc->status = USB_DMA_DESC_BS_DMA_DONE | USB_DMA_DESC_LAST | 0x40; | ||
382 | uc_desc->resv = 0xffffffff; | ||
383 | uc_desc->data_ptr = tx_buf; | ||
384 | uc_desc->next_desc = 0; | ||
385 | } else { | ||
386 | uc_desc->status = USB_DMA_DESC_BS_HST_RDY | /*USB_DMA_DESC_LAST |*/ 0x40; | ||
387 | uc_desc->resv = 0xffffffff; | ||
388 | uc_desc->data_ptr = rx_buf; | ||
389 | uc_desc->next_desc = 0; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | static void reset_endpoints(int init) | ||
119 | { | 394 | { |
120 | int i; | 395 | int i; |
121 | for(i = 0; i < USB_NUM_ENDPOINTS * 2; i++) | ||
122 | endpoints[i].busy = false; | ||
123 | 396 | ||
124 | ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2); | 397 | /* |
125 | ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) & ~(1<<4)); | 398 | * OUT EP 2 is an alias for OUT EP 0 on this HW! |
399 | * | ||
400 | * Resonates with "3 bidirectional- plus 1 in-endpoints in device mode" | ||
401 | * from the datasheet, but why ep2 and not ep3? | ||
402 | * | ||
403 | * Reserve it here so we will skip over it in request_endpoint(). | ||
404 | */ | ||
405 | endpoints[2][1].state |= EP_STATE_ALLOCATED; | ||
406 | |||
407 | for(i = 0; i < USB_NUM_EPS; i++) { | ||
408 | int mps = i == 0 ? 64 : 2048; /* For HS */ | ||
409 | |||
410 | if (init) { | ||
411 | endpoints[i][0].state = 0; | ||
412 | wakeup_init(&endpoints[i][0].complete); | ||
413 | |||
414 | if (i != 2) { /* Skip the OUT EP0 alias */ | ||
415 | endpoints[i][1].state = 0; | ||
416 | wakeup_init(&endpoints[i][1].complete); | ||
417 | USB_OEP_SUP_PTR(i) = 0; | ||
418 | } | ||
419 | } | ||
126 | 420 | ||
127 | /* PHY part */ | 421 | dma_desc_init(i, 0); |
128 | CGU_USB = 1<<5 /* enable */ | 422 | USB_IEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK; |
129 | | (CLK_DIV(AS3525_PLLA_FREQ, 48000000) / 2) << 2 | 423 | USB_IEP_MPS (i) = mps; |
130 | | 1; /* source = PLLA */ | 424 | /* We don't care about the 'IN token received' event */ |
425 | USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */ | ||
426 | USB_IEP_TXFSIZE (i) = 0x20; | ||
427 | USB_IEP_STS (i) = 0xffffffff; /* clear status */ | ||
428 | USB_IEP_DESC_PTR(i) = 0; | ||
429 | |||
430 | if (i != 2) { /* Skip the OUT EP0 alias */ | ||
431 | dma_desc_init(i, 1); | ||
432 | USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK; | ||
433 | USB_OEP_MPS (i) = 0x08000000|mps; | ||
434 | USB_OEP_STS_MASK(i) = 0x0000; /* OF: 0x1800 */ | ||
435 | USB_OEP_RXFR (i) = 0x00; | ||
436 | USB_OEP_STS (i) = 0xffffffff; /* clear status */ | ||
437 | USB_OEP_DESC_PTR(i) = 0; | ||
438 | } | ||
439 | } | ||
131 | 440 | ||
132 | /* AHB part */ | 441 | setup_desc_init(&setup_desc); |
133 | CGU_PERI |= CGU_USB_CLOCK_ENABLE; | 442 | USB_OEP_SUP_PTR(0) = (int)&setup_desc; |
443 | } | ||
134 | 444 | ||
135 | USB_GPIO_CSR = 0x6180000; | 445 | void usb_drv_init(void) |
136 | USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */ | 446 | { |
137 | USB_DEV_CTRL |= 0x400; /* soft disconnect */ | 447 | logf("usb_drv_init() !!!!\n"); |
138 | 448 | ||
139 | /* UVDD */ | 449 | /* length regulator: normal operation */ |
140 | ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) | (1<<4)); | 450 | ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2); |
141 | sleep(10); //msleep(100) | ||
142 | |||
143 | USB_GPIO_CSR = 0x6180000; | ||
144 | |||
145 | USB_GPIO_CSR |= 0x1C00000; | ||
146 | sleep(1); //msleep(3) | ||
147 | USB_GPIO_CSR |= 0x200000; | ||
148 | sleep(1); //msleep(10) | ||
149 | |||
150 | USB_DEV_CTRL |= 0x400; /* soft disconnect */ | ||
151 | |||
152 | USB_GPIO_CSR &= ~0x1C00000; | ||
153 | sleep(1); //msleep(3) | ||
154 | USB_GPIO_CSR &= ~0x200000; | ||
155 | sleep(1); //msleep(10) | ||
156 | USB_DEV_CTRL &= ~0x400; /* clear soft disconnect */ | ||
157 | |||
158 | #if defined(SANSA_CLIP) | ||
159 | GPIOA_DIR |= (1<<6); | ||
160 | GPIOA_PIN(6) = (1<<6); | ||
161 | GPIOA_DIR &= ~(1<<6); /* restore direction for usb_detect() */ | ||
162 | #elif defined(SANSA_FUZE) || defined(SANSA_E200V2) | ||
163 | GPIOA_DIR |= (1<<3); | ||
164 | GPIOA_PIN(3) = (1<<3); | ||
165 | GPIOA_DIR &= ~(1<<3); /* restore direction for usb_detect() */ | ||
166 | #elif defined(SANSA_C200V2) | ||
167 | GPIOA_DIR |= (1<<1); | ||
168 | GPIOA_PIN(1) = (1<<1); | ||
169 | GPIOA_DIR &= ~(1<<1); /* restore direction for usb_detect() */ | ||
170 | #endif | ||
171 | 451 | ||
172 | #if 0 /* linux */ | 452 | /* AHB part */ |
173 | USB_DEV_CFG |= (1<<17) /* csr programming */ | 453 | CGU_PERI |= CGU_USB_CLOCK_ENABLE; |
174 | | (1<<3) /* self powered */ | ||
175 | | (1<<2); /* remote wakeup */ | ||
176 | 454 | ||
177 | USB_DEV_CFG &= ~3; /* high speed */ | 455 | /* reset AHB */ |
178 | #endif | 456 | CCU_SRC = CCU_SRC_USB_AHB_EN; |
457 | CCU_SRL = CCU_SRL_MAGIC_NUMBER; | ||
458 | usb_delay(1); | ||
459 | CCU_SRC = CCU_SRL = 0; | ||
179 | 460 | ||
180 | USB_IEP_CTRL(0) &= (3 << 4); /* control endpoint */ | 461 | USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N |
181 | USB_IEP_DESC_PTR(0) = 0; | 462 | | USB_GPIO_TX_BIT_STUFF_EN |
463 | | USB_GPIO_XO_ON | ||
464 | | USB_GPIO_CLK_SEL10; /* 0x06180000; */ | ||
182 | 465 | ||
183 | USB_OEP_CTRL(0) &= (3 << 4); /* control endpoint */ | 466 | /* bug workaround according to linux patch */ |
184 | USB_OEP_DESC_PTR(0) = 0; | 467 | USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */ |
185 | 468 | ||
186 | USB_DEV_INTR_MASK &= ~0xff; /* unmask all flags */ | 469 | /* enable soft disconnect */ |
470 | USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN; | ||
471 | |||
472 | usb_phy_on(); | ||
473 | usb_phy_suspend(); | ||
474 | USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN; | ||
475 | |||
476 | /* We don't care about OTG or SOF events */ | ||
477 | /* Right now we don't handle suspend or reset, so mask those too */ | ||
478 | USB_DEV_INTR_MASK = USB_DEV_INTR_OTG | | ||
479 | USB_DEV_INTR_SOF | | ||
480 | USB_DEV_INTR_USB_SUSPEND | | ||
481 | USB_DEV_INTR_EARLY_SUSPEND; | ||
482 | |||
483 | USB_DEV_CFG = USB_DEV_CFG_STAT_ACK | | ||
484 | USB_DEV_CFG_UNI_DIR | | ||
485 | USB_DEV_CFG_PI_16BIT | | ||
486 | USB_DEV_CFG_HS | | ||
487 | USB_DEV_CFG_SELF_POWERED | | ||
488 | 0x20200; | ||
489 | |||
490 | USB_DEV_CTRL = USB_DEV_CTRL_BLEN_1DWORD | | ||
491 | USB_DEV_CTRL_DESC_UPDATE | | ||
492 | USB_DEV_CTRL_THRES_ENABLE | | ||
493 | USB_DEV_CTRL_RDE | | ||
494 | 0x04000000; | ||
187 | 495 | ||
188 | USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */ | 496 | USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */ |
189 | 497 | ||
498 | reset_endpoints(1); | ||
499 | |||
500 | /* clear pending interrupts */ | ||
501 | USB_DEV_EP_INTR = 0xffffffff; | ||
502 | USB_DEV_INTR = 0xffffffff; | ||
503 | |||
190 | VIC_INT_ENABLE = INTERRUPT_USB; | 504 | VIC_INT_ENABLE = INTERRUPT_USB; |
191 | 505 | ||
192 | USB_IEP_CTRL(0) |= (1<<7); /* set NAK */ | 506 | usb_phy_resume(); |
193 | USB_OEP_CTRL(0) |= (1<<7); /* set NAK */ | 507 | USB_DEV_CTRL &= ~USB_DEV_CTRL_SOFT_DISCONN; |
508 | |||
509 | USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N | ||
510 | | USB_GPIO_TX_BIT_STUFF_EN | ||
511 | | USB_GPIO_XO_ON | ||
512 | | USB_GPIO_HS_INTR | ||
513 | | USB_GPIO_CLK_SEL10; /* 0x06180000; */ | ||
514 | |||
194 | } | 515 | } |
195 | 516 | ||
196 | void usb_drv_exit(void) | 517 | void usb_drv_exit(void) |
@@ -199,72 +520,421 @@ void usb_drv_exit(void) | |||
199 | VIC_INT_EN_CLEAR = INTERRUPT_USB; | 520 | VIC_INT_EN_CLEAR = INTERRUPT_USB; |
200 | CGU_USB &= ~(1<<5); | 521 | CGU_USB &= ~(1<<5); |
201 | CGU_PERI &= ~CGU_USB_CLOCK_ENABLE; | 522 | CGU_PERI &= ~CGU_USB_CLOCK_ENABLE; |
523 | /* Disable UVDD generating LDO */ | ||
202 | ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) & ~(1<<4)); | 524 | ascodec_write(AS3515_USB_UTIL, ascodec_read(AS3515_USB_UTIL) & ~(1<<4)); |
525 | logf("usb_drv_exit() !!!!\n"); | ||
203 | } | 526 | } |
204 | 527 | ||
205 | int usb_drv_port_speed(void) | 528 | int usb_drv_port_speed(void) |
206 | { | 529 | { |
207 | return (USB_DEV_CFG & 3) ? 0 : 1; | 530 | return (USB_DEV_STS & USB_DEV_STS_MASK_SPD) ? 0 : 1; |
208 | } | 531 | } |
209 | 532 | ||
210 | int usb_drv_request_endpoint(int type, int dir) | 533 | int usb_drv_request_endpoint(int type, int dir) |
211 | { | 534 | { |
212 | (void) type; | 535 | int d = dir == USB_DIR_IN ? 0 : 1; |
213 | int i = dir == USB_DIR_IN ? 0 : 1; | 536 | int i = 1; /* skip the control EP */ |
214 | 537 | ||
215 | for(; i < USB_NUM_ENDPOINTS * 2; i += 2) | 538 | for(; i < USB_NUM_EPS; i++) { |
216 | if(!endpoints[i].busy) | 539 | if (endpoints[i][d].state & EP_STATE_ALLOCATED) |
217 | { | 540 | continue; |
218 | endpoints[i].busy = true; | 541 | |
219 | i >>= 1; | 542 | endpoints[i][d].state |= EP_STATE_ALLOCATED; |
220 | USB_DEV_EP_INTR_MASK &= ~((1<<i) | (1<<(16+i))); | 543 | |
221 | return i | dir; | 544 | if (dir == USB_DIR_IN) { |
545 | USB_IEP_CTRL(i) = USB_EP_CTRL_FLUSH | | ||
546 | USB_EP_CTRL_SNAK | | ||
547 | USB_EP_CTRL_ACT | | ||
548 | (type << 4); | ||
549 | USB_DEV_EP_INTR_MASK &= ~(1<<i); | ||
550 | } else { | ||
551 | USB_OEP_CTRL(i) = USB_EP_CTRL_FLUSH | | ||
552 | USB_EP_CTRL_SNAK | | ||
553 | USB_EP_CTRL_ACT | | ||
554 | (type << 4); | ||
555 | USB_DEV_EP_INTR_MASK &= ~(1<<(16+i)); | ||
222 | } | 556 | } |
557 | logf("usb_drv_request_endpoint(%d, %d): returning %02x\n", type, dir, i | dir); | ||
558 | return i | dir; | ||
559 | } | ||
223 | 560 | ||
561 | logf("usb_drv_request_endpoint(%d, %d): no free endpoint found\n", type, dir); | ||
224 | return -1; | 562 | return -1; |
225 | } | 563 | } |
226 | 564 | ||
227 | void usb_drv_release_endpoint(int ep) | 565 | void usb_drv_release_endpoint(int ep) |
228 | { | 566 | { |
229 | int i = (ep & 0x7f) * 2; | 567 | int i = ep & 0x7f; |
230 | if(ep & USB_DIR_OUT) | 568 | int d = ep & USB_DIR_IN ? 0 : 1; |
231 | i++; | 569 | |
232 | endpoints[i].busy = false; | 570 | if (i >= USB_NUM_EPS) |
233 | USB_DEV_EP_INTR_MASK |= (1<<ep) | (1<<(16+ep)); | 571 | return; |
572 | /* | ||
573 | * Check for control EP and ignore it. | ||
574 | * Unfortunately the usb core calls | ||
575 | * usb_drv_release_endpoint() for ep=0..(USB_NUM_ENDPOINTS-1), | ||
576 | * but doesn't request a new control EP after that... | ||
577 | */ | ||
578 | if (i == 0 || /* Don't mask control EP */ | ||
579 | (i == 2 && d == 1)) /* See reset_endpoints(), EP2_OUT == EP0_OUT */ | ||
580 | return; | ||
581 | |||
582 | if (!(endpoints[i][d].state & EP_STATE_ALLOCATED)) | ||
583 | return; | ||
584 | |||
585 | logf("usb_drv_release_endpoint(%d, %d)\n", i, d); | ||
586 | endpoints[i][d].state = 0; | ||
587 | USB_DEV_EP_INTR_MASK |= (1<<(16*d+i)); | ||
588 | USB_EP_CTRL(i, !d) = USB_EP_CTRL_FLUSH | USB_EP_CTRL_SNAK; | ||
234 | } | 589 | } |
235 | 590 | ||
236 | void usb_drv_cancel_all_transfers(void) | 591 | void usb_drv_cancel_all_transfers(void) |
237 | { | 592 | { |
593 | logf("usb_drv_cancel_all_transfers()\n"); | ||
594 | return; | ||
595 | |||
596 | int flags = disable_irq_save(); | ||
597 | reset_endpoints(0); | ||
598 | restore_irq(flags); | ||
599 | } | ||
600 | |||
601 | static void *virt_to_bus(void *addr) | ||
602 | { | ||
603 | unsigned int x = (long)addr; | ||
604 | |||
605 | x -= (x & 0x40000000) >> 2; /* fix uncached address */ | ||
606 | |||
607 | if (x >= IRAM_ORIG) { /* iram address */ | ||
608 | x -= IRAM_ORIG; | ||
609 | } | ||
610 | |||
611 | return (void*)x; | ||
238 | } | 612 | } |
239 | 613 | ||
240 | int usb_drv_recv(int ep, void *ptr, int len) | 614 | int usb_drv_recv(int ep, void *ptr, int len) |
241 | { | 615 | { |
242 | (void)ep;(void)ptr;(void)len; | 616 | struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc; |
243 | if(ep >= 2) | 617 | |
244 | return -1; | 618 | ep &= 0x7f; |
619 | logf("usb_drv_recv(%d,%x,%d)\n", ep, (int)ptr, len); | ||
620 | |||
621 | if ((int)ptr & 31) { | ||
622 | logf("addr %08x not aligned!\n", (int)ptr); | ||
623 | } | ||
624 | |||
625 | endpoints[ep][1].state |= EP_STATE_BUSY; | ||
626 | endpoints[ep][1].len = len; | ||
627 | endpoints[ep][1].rc = -1; | ||
628 | |||
629 | /* remove data buffer from cache */ | ||
630 | invalidate_dcache(); | ||
631 | /* DMA setup */ | ||
632 | uc_desc->status = USB_DMA_DESC_BS_HST_RDY | | ||
633 | USB_DMA_DESC_LAST | | ||
634 | len; | ||
635 | if (len == 0) { | ||
636 | uc_desc->status |= USB_DMA_DESC_ZERO_LEN; | ||
637 | uc_desc->data_ptr = 0; | ||
638 | } else { | ||
639 | uc_desc->data_ptr = virt_to_bus(ptr); | ||
640 | } | ||
641 | USB_OEP_DESC_PTR(ep) = (int)&dmadescs[ep][1]; | ||
642 | USB_OEP_STS(ep) = USB_EP_STAT_OUT_RCVD; /* clear status */ | ||
643 | USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; | ||
644 | |||
645 | return 0; | ||
646 | } | ||
245 | 647 | ||
246 | return -1; | 648 | #if defined(LOGF_ENABLE) |
649 | static char hexbuf[1025]; | ||
650 | static char hextab[16] = "0123456789abcdef"; | ||
651 | |||
652 | char *make_hex(char *data, int len) | ||
653 | { | ||
654 | int i; | ||
655 | if (!((int)data & 0x40000000)) | ||
656 | data = UNCACHED_ADDR(data); /* don't pollute the cache */ | ||
657 | |||
658 | if (len > 512) | ||
659 | len = 512; | ||
660 | |||
661 | for (i=0; i<len; i++) { | ||
662 | hexbuf[2*i ] = hextab[(unsigned char)data[i] >> 4 ]; | ||
663 | hexbuf[2*i+1] = hextab[(unsigned char)data[i] & 0xf]; | ||
664 | } | ||
665 | hexbuf[2*i] = 0; | ||
666 | |||
667 | return hexbuf; | ||
668 | } | ||
669 | #endif | ||
670 | |||
671 | void ep_send(int ep, void *ptr, int len) | ||
672 | { | ||
673 | struct usb_dev_dma_desc *uc_desc = endpoints[ep][0].uc_desc; | ||
674 | int i; | ||
675 | |||
676 | endpoints[ep][0].state |= EP_STATE_BUSY; | ||
677 | endpoints[ep][0].len = len; | ||
678 | endpoints[ep][0].rc = -1; | ||
679 | |||
680 | USB_IEP_CTRL(ep) |= USB_EP_CTRL_CNAK; | ||
681 | |||
682 | /* TEST: delay a little here */ | ||
683 | for (i=0; i<1000; i++) asm volatile ("nop\n"); | ||
684 | |||
685 | /* Make sure data is committed to memory */ | ||
686 | clean_dcache(); | ||
687 | |||
688 | logf("xx%s\n", make_hex(ptr, len)); | ||
689 | |||
690 | uc_desc->status = USB_DMA_DESC_BS_HST_RDY | | ||
691 | USB_DMA_DESC_LAST | | ||
692 | len; | ||
693 | if (len == 0) | ||
694 | uc_desc->status |= USB_DMA_DESC_ZERO_LEN; | ||
695 | |||
696 | uc_desc->data_ptr = virt_to_bus(ptr); | ||
697 | |||
698 | USB_IEP_CTRL(ep) |= USB_EP_CTRL_FLUSH; | ||
699 | USB_IEP_DESC_PTR(ep) = (int)&dmadescs[ep][0]; | ||
700 | USB_IEP_STS(ep) = 0xffffffff; /* clear status */ | ||
701 | /* start transfer */ | ||
702 | USB_IEP_CTRL(ep) |= USB_EP_CTRL_PD; | ||
247 | } | 703 | } |
248 | 704 | ||
249 | int usb_drv_send(int ep, void *ptr, int len) | 705 | int usb_drv_send(int ep, void *ptr, int len) |
250 | { | 706 | { |
251 | (void)ep;(void)ptr;(void)len; | 707 | logf("usb_drv_send(%d,%x,%d): ", ep, (int)ptr, len); |
252 | if(ep >= 2) | ||
253 | return -1; | ||
254 | 708 | ||
255 | return -1; | 709 | ep &= 0x7f; |
710 | ep_send(ep, ptr, len); | ||
711 | while (endpoints[ep][0].state & EP_STATE_BUSY) | ||
712 | wakeup_wait(&endpoints[ep][0].complete, TIMEOUT_BLOCK); | ||
713 | |||
714 | return endpoints[ep][0].rc; | ||
256 | } | 715 | } |
257 | 716 | ||
258 | int usb_drv_send_nonblocking(int ep, void *ptr, int len) | 717 | int usb_drv_send_nonblocking(int ep, void *ptr, int len) |
259 | { | 718 | { |
260 | /* TODO */ | 719 | logf("usb_drv_send_nonblocking(%d,%x,%d): ", ep, (int)ptr, len); |
261 | return usb_drv_send(ep, ptr, len); | 720 | ep &= 0x7f; |
721 | endpoints[ep][0].state |= EP_STATE_ASYNC; | ||
722 | ep_send(ep, ptr, len); | ||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static void handle_in_ep(int ep) | ||
727 | { | ||
728 | int ep_sts = USB_IEP_STS(ep) & ~USB_IEP_STS_MASK(ep); | ||
729 | |||
730 | if (ep > 3) | ||
731 | panicf("in_ep > 3?!"); | ||
732 | |||
733 | USB_IEP_STS(ep) = ep_sts; /* ack */ | ||
734 | |||
735 | if (ep_sts & USB_EP_STAT_TDC) { | ||
736 | ep_sts &= ~USB_EP_STAT_TDC; | ||
737 | /* OF does SNAK and FLUSH at once here */ | ||
738 | USB_IEP_CTRL(ep) |= USB_EP_CTRL_SNAK | USB_EP_CTRL_FLUSH; | ||
739 | endpoints[ep][0].state &= ~EP_STATE_BUSY; | ||
740 | endpoints[ep][0].rc = 0; | ||
741 | logf("EP%d %stx done len %x stat %08x\n", | ||
742 | ep, endpoints[ep][0].state & EP_STATE_ASYNC ? "async " :"", | ||
743 | endpoints[ep][0].len, | ||
744 | endpoints[ep][0].uc_desc->status); | ||
745 | if (endpoints[ep][0].state & EP_STATE_ASYNC) { | ||
746 | endpoints[ep][0].state &= ~EP_STATE_ASYNC; | ||
747 | usb_core_transfer_complete(ep, USB_DIR_IN, 0, endpoints[ep][0].len); | ||
748 | } else { | ||
749 | wakeup_signal(&endpoints[ep][0].complete); | ||
750 | } | ||
751 | } | ||
752 | |||
753 | if (ep_sts) { | ||
754 | logf("ep%d IN, hwstat %lx, epstat %x\n", ep, USB_IEP_STS(ep), endpoints[ep][0].state); | ||
755 | panicf("ep%d IN 0x%x", ep, ep_sts); | ||
756 | } | ||
757 | |||
758 | /* HW automatically disables RDE, re-enable it */ | ||
759 | /* But this an IN ep, I wonder... */ | ||
760 | USB_DEV_CTRL |= USB_DEV_CTRL_RDE; | ||
761 | } | ||
762 | |||
763 | static void handle_out_ep(int ep) | ||
764 | { | ||
765 | struct usb_ctrlrequest *req = (void*)UNCACHED_ADDR(&setup_desc.data1); | ||
766 | int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep); | ||
767 | struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc; | ||
768 | |||
769 | if (ep > 3) | ||
770 | panicf("out_ep > 3!?"); | ||
771 | |||
772 | USB_OEP_STS(ep) = ep_sts; /* ACK */ | ||
773 | |||
774 | if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */ | ||
775 | logf("ep%d OUT, status %x (BNA)\n", ep, ep_sts); | ||
776 | panicf("ep%d OUT 0x%x (BNA)", ep, ep_sts); | ||
777 | } | ||
778 | |||
779 | if (ep_sts & USB_EP_STAT_OUT_RCVD) { | ||
780 | int dma_sts = uc_desc->status; | ||
781 | int dma_len = dma_sts & 0xffff; | ||
782 | int dma_frm = (dma_sts >> 16) & 0x7ff; | ||
783 | int dma_mst = dma_sts & 0xf8000000; | ||
784 | |||
785 | uc_desc->status = USB_DMA_DESC_BS_HST_RDY | | ||
786 | USB_DMA_DESC_LAST | | ||
787 | 0x40; | ||
788 | uc_desc->data_ptr = rx_buf; | ||
789 | USB_OEP_DESC_PTR(ep) = (int)&dmadescs[ep][1]; | ||
790 | |||
791 | if (!(dma_sts & USB_DMA_DESC_ZERO_LEN)) { | ||
792 | logf("EP%d OUT token, st:%08x len:%d frm:%x data=%s\n", ep, | ||
793 | dma_mst, dma_len, dma_frm, make_hex(uc_desc->data_ptr, dma_len)); | ||
794 | /* | ||
795 | * If parts of the just dmaed range are in cache, dump them now. | ||
796 | */ | ||
797 | dump_dcache_range(uc_desc->data_ptr, dma_len); | ||
798 | } else{ | ||
799 | logf("EP%d OUT token, st:%08x len:%d frm:%x\n", ep, | ||
800 | dma_mst, dma_len, dma_frm); | ||
801 | } | ||
802 | |||
803 | if (endpoints[ep][1].state & EP_STATE_BUSY) { | ||
804 | endpoints[ep][1].state &= ~EP_STATE_BUSY; | ||
805 | endpoints[ep][1].rc = 0; | ||
806 | usb_core_transfer_complete(ep, 0, 0, endpoints[ep][0].len); | ||
807 | } else { | ||
808 | logf("EP%d OUT, but no one was listening?\n", ep); | ||
809 | } | ||
810 | |||
811 | USB_OEP_CTRL(ep) |= USB_EP_CTRL_SNAK; /* make sure NAK is set */ | ||
812 | |||
813 | ep_sts &= ~USB_EP_STAT_OUT_RCVD; | ||
814 | } | ||
815 | |||
816 | if (ep_sts & USB_EP_STAT_SETUP_RCVD) { | ||
817 | static struct usb_ctrlrequest req_copy; | ||
818 | |||
819 | req_copy = *req; | ||
820 | logf("t%ld:got SETUP packet: type=%d req=%d val=%d ind=%d len=%d\n", | ||
821 | current_tick, | ||
822 | req->bRequestType, | ||
823 | req->bRequest, | ||
824 | req->wValue, | ||
825 | req->wIndex, | ||
826 | req->wLength); | ||
827 | |||
828 | usb_core_control_request(&req_copy); | ||
829 | setup_desc_init(&setup_desc); | ||
830 | |||
831 | ep_sts &= ~USB_EP_STAT_SETUP_RCVD; | ||
832 | } | ||
833 | |||
834 | if (ep_sts) { | ||
835 | logf("ep%d OUT, status %x\n", ep, ep_sts); | ||
836 | panicf("ep%d OUT 0x%x", ep, ep_sts); | ||
837 | } | ||
838 | |||
839 | /* HW automatically disables RDE, re-enable it */ | ||
840 | /* THEORY: Because we only set up one DMA buffer... */ | ||
841 | USB_DEV_CTRL |= USB_DEV_CTRL_RDE; | ||
262 | } | 842 | } |
263 | 843 | ||
264 | /* interrupt service routine */ | 844 | /* interrupt service routine */ |
265 | void INT_USB(void) | 845 | void INT_USB(void) |
266 | { | 846 | { |
267 | panicf("USB interrupt !"); | 847 | int ep = USB_DEV_EP_INTR & ~USB_DEV_EP_INTR_MASK; |
848 | int intr = USB_DEV_INTR & ~USB_DEV_INTR_MASK; | ||
849 | |||
850 | /* ACK interrupt sources */ | ||
851 | USB_DEV_EP_INTR = ep; | ||
852 | USB_DEV_INTR = intr; | ||
853 | |||
854 | /* Handle endpoint interrupts */ | ||
855 | while (ep) { | ||
856 | int onebit = 31-__builtin_clz(ep); | ||
857 | |||
858 | if (onebit < 16) handle_in_ep(onebit); | ||
859 | else handle_out_ep(onebit-16); | ||
860 | |||
861 | ep &= ~(1 << onebit); | ||
862 | } | ||
863 | |||
864 | /* Handle general device interrupts */ | ||
865 | if (intr) { | ||
866 | if (intr & USB_DEV_INTR_SET_INTERFACE) {/* SET_INTERFACE received */ | ||
867 | logf("set interface\n"); | ||
868 | panicf("set interface"); | ||
869 | intr &= ~USB_DEV_INTR_SET_INTERFACE; | ||
870 | } | ||
871 | if (intr & USB_DEV_INTR_SET_CONFIG) {/* SET_CONFIGURATION received */ | ||
872 | /* | ||
873 | * This is handled in HW, we have to fake a request here | ||
874 | * for usb_core. | ||
875 | */ | ||
876 | static struct usb_ctrlrequest set_config = { | ||
877 | bRequestType: USB_TYPE_STANDARD | USB_RECIP_DEVICE, | ||
878 | bRequest: USB_REQ_SET_CONFIGURATION, | ||
879 | wValue: 0, | ||
880 | wIndex: 0, | ||
881 | wLength: 0, | ||
882 | }; | ||
883 | |||
884 | logf("set config\n"); | ||
885 | |||
886 | set_config.wValue = USB_DEV_STS & USB_DEV_STS_MASK_CFG; | ||
887 | usb_core_control_request(&set_config); | ||
888 | |||
889 | /* Tell the HW we handled the request */ | ||
890 | USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE; | ||
891 | intr &= ~USB_DEV_INTR_SET_CONFIG; | ||
892 | } | ||
893 | if (intr & USB_DEV_INTR_EARLY_SUSPEND) {/* idle >3ms detected */ | ||
894 | logf("usb idle\n"); | ||
895 | intr &= ~USB_DEV_INTR_EARLY_SUSPEND; | ||
896 | } | ||
897 | if (intr & USB_DEV_INTR_USB_RESET) {/* usb reset from host? */ | ||
898 | logf("usb reset\n"); | ||
899 | reset_endpoints(1); | ||
900 | usb_core_bus_reset(); | ||
901 | intr &= ~USB_DEV_INTR_USB_RESET; | ||
902 | } | ||
903 | if (intr & USB_DEV_INTR_USB_SUSPEND) {/* suspend req from host? */ | ||
904 | logf("usb suspend\n"); | ||
905 | intr &= ~USB_DEV_INTR_USB_SUSPEND; | ||
906 | } | ||
907 | if (intr & USB_DEV_INTR_SOF) {/* sof received */ | ||
908 | logf("sof\n"); | ||
909 | intr &= ~USB_DEV_INTR_SOF; | ||
910 | } | ||
911 | if (intr & USB_DEV_INTR_ENUM_DONE) {/* speed enumeration complete */ | ||
912 | int spd = USB_DEV_STS & USB_DEV_STS_MASK_SPD; /* Enumerated Speed */ | ||
913 | |||
914 | logf("speed enum complete: "); | ||
915 | if (spd == USB_DEV_STS_SPD_HS) logf("hs\n"); | ||
916 | if (spd == USB_DEV_STS_SPD_FS) logf("fs\n"); | ||
917 | if (spd == USB_DEV_STS_SPD_LS) logf("ls\n"); | ||
918 | |||
919 | USB_PHY_EP0_INFO = 0x00200000; | ||
920 | USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE; | ||
921 | USB_IEP_CTRL(0) |= USB_EP_CTRL_ACT; | ||
922 | USB_OEP_CTRL(0) |= USB_EP_CTRL_ACT; | ||
923 | intr &= ~USB_DEV_INTR_ENUM_DONE; | ||
924 | } | ||
925 | if (intr & USB_DEV_INTR_BUSERR) { | ||
926 | panicf("usb dma bus error"); | ||
927 | intr &= ~USB_DEV_INTR_BUSERR; | ||
928 | } | ||
929 | if (intr) | ||
930 | panicf("usb devirq 0x%x", intr); | ||
931 | } | ||
932 | |||
933 | if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){ | ||
934 | logf("re-enabling receive DMA\n"); | ||
935 | USB_DEV_CTRL |= USB_DEV_CTRL_RDE; | ||
936 | } | ||
937 | |||
268 | } | 938 | } |
269 | 939 | ||
270 | /* (not essential? , not implemented in usb-tcc.c) */ | 940 | /* (not essential? , not implemented in usb-tcc.c) */ |
@@ -273,6 +943,7 @@ void usb_drv_set_test_mode(int mode) | |||
273 | (void)mode; | 943 | (void)mode; |
274 | } | 944 | } |
275 | 945 | ||
946 | /* handled internally by controller */ | ||
276 | void usb_drv_set_address(int address) | 947 | void usb_drv_set_address(int address) |
277 | { | 948 | { |
278 | (void)address; | 949 | (void)address; |
@@ -280,12 +951,11 @@ void usb_drv_set_address(int address) | |||
280 | 951 | ||
281 | void usb_drv_stall(int ep, bool stall, bool in) | 952 | void usb_drv_stall(int ep, bool stall, bool in) |
282 | { | 953 | { |
283 | (void)ep;(void)stall;(void)in; | 954 | if (stall) USB_EP_CTRL(ep, in) |= USB_EP_CTRL_STALL; |
955 | else USB_EP_CTRL(ep, in) &= ~USB_EP_CTRL_STALL; | ||
284 | } | 956 | } |
285 | 957 | ||
286 | bool usb_drv_stalled(int ep, bool in) | 958 | bool usb_drv_stalled(int ep, bool in) |
287 | { | 959 | { |
288 | (void)ep;(void)in; | 960 | return USB_EP_CTRL(ep, in) & USB_EP_CTRL_STALL ? true : false; |
289 | return true; | ||
290 | } | 961 | } |
291 | |||