tools/llvm: Do not build with symbols
[minix3.git] / minix / drivers / usb / usbd / hcd / musb / musb_am335x.c
blobb8d25313a63f95fd8b59b6ceab552cefb2a5f607
1 /*
2 * Implementation of whatever is hardware specific in AM335x MCU
3 */
5 #include <string.h> /* memset */
7 #include <usbd/hcd_common.h>
8 #include <usbd/hcd_platforms.h>
9 #include <usbd/hcd_interface.h>
10 #include <usbd/usbd_common.h>
12 #include "musb_core.h"
14 /* TODO: BeagleBone white uses USB0 for PC connection as peripheral,
15 * so this is disabled by default */
16 /* Should USB0 ever be used on BBB/BBW, one can change it to '#define': */
17 #undef AM335X_USE_USB0
20 /*===========================================================================*
21 * AM335x base register defines *
22 *===========================================================================*/
23 /* Memory placement defines */
24 #define AM335X_USBSS_BASE_ADDR 0x47400000u
25 #define AM335X_USB0_BASE_OFFSET 0x1000u
26 #define AM335X_MUSB_CORE0_BASE_OFFSET 0x1400u
27 #define AM335X_USB1_BASE_OFFSET 0x1800u
28 #define AM335X_MUSB_CORE1_BASE_OFFSET 0x1C00u
29 #define AM335X_USBSS_TOTAL_REG_LEN 0x5000u
32 /*===========================================================================*
33 * AM335x USB specific register defines *
34 *===========================================================================*/
35 /* SS registers base address */
37 #define AM335X_REG_REVREG 0x000u
38 #define AM335X_REG_SYSCONFIG 0x010u
39 #define AM335X_REG_IRQSTATRAW 0x024u
40 #define AM335X_REG_IRQSTAT 0x028u
41 #define AM335X_REG_IRQENABLER 0x02Cu
42 #define AM335X_REG_IRQCLEARR 0x030u
43 #define AM335X_REG_IRQDMATHOLDTX00 0x100u
44 #define AM335X_REG_IRQDMATHOLDTX01 0x104u
45 #define AM335X_REG_IRQDMATHOLDTX02 0x108u
46 #define AM335X_REG_IRQDMATHOLDTX03 0x10Cu
47 #define AM335X_REG_IRQDMATHOLDRX00 0x110u
48 #define AM335X_REG_IRQDMATHOLDRX01 0x114u
49 #define AM335X_REG_IRQDMATHOLDRX02 0x118u
50 #define AM335X_REG_IRQDMATHOLDRX03 0x11Cu
51 #define AM335X_REG_IRQDMATHOLDTX10 0x120u
52 #define AM335X_REG_IRQDMATHOLDTX11 0x124u
53 #define AM335X_REG_IRQDMATHOLDTX12 0x128u
54 #define AM335X_REG_IRQDMATHOLDTX13 0x12Cu
55 #define AM335X_REG_IRQDMATHOLDRX10 0x130u
56 #define AM335X_REG_IRQDMATHOLDRX11 0x134u
57 #define AM335X_REG_IRQDMATHOLDRX12 0x138u
58 #define AM335X_REG_IRQDMATHOLDRX13 0x13Cu
59 #define AM335X_REG_IRQDMAENABLE0 0x140u
60 #define AM335X_REG_IRQDMAENABLE1 0x144u
61 #define AM335X_REG_IRQFRAMETHOLDTX00 0x200u
62 #define AM335X_REG_IRQFRAMETHOLDTX01 0x204u
63 #define AM335X_REG_IRQFRAMETHOLDTX02 0x208u
64 #define AM335X_REG_IRQFRAMETHOLDTX03 0x20Cu
65 #define AM335X_REG_IRQFRAMETHOLDRX00 0x210u
66 #define AM335X_REG_IRQFRAMETHOLDRX01 0x214u
67 #define AM335X_REG_IRQFRAMETHOLDRX02 0x218u
68 #define AM335X_REG_IRQFRAMETHOLDRX03 0x21Cu
69 #define AM335X_REG_IRQFRAMETHOLDTX10 0x220u
70 #define AM335X_REG_IRQFRAMETHOLDTX11 0x224u
71 #define AM335X_REG_IRQFRAMETHOLDTX12 0x228u
72 #define AM335X_REG_IRQFRAMETHOLDTX13 0x22Cu
73 #define AM335X_REG_IRQFRAMETHOLDRX10 0x230u
74 #define AM335X_REG_IRQFRAMETHOLDRX11 0x234u
75 #define AM335X_REG_IRQFRAMETHOLDRX12 0x238u
76 #define AM335X_REG_IRQFRAMETHOLDRX13 0x23Cu
77 #define AM335X_REG_IRQFRAMEENABLE0 0x240u
78 #define AM335X_REG_IRQFRAMEENABLE1 0x244u
80 #define AM335X_REG_USBXREV 0x00u
81 #define AM335X_REG_USBXCTRL 0x14u
82 #define AM335X_REG_USBXSTAT 0x18u
83 #define AM335X_REG_USBXIRQMSTAT 0x20u
84 #define AM335X_REG_USBXIRQSTATRAW0 0x28u
85 #define AM335X_REG_USBXIRQSTATRAW1 0x2Cu
86 #define AM335X_REG_USBXIRQSTAT0 0x30u
87 #define AM335X_REG_USBXIRQSTAT1 0x34u
88 #define AM335X_REG_USBXIRQENABLESET0 0x38u
89 #define AM335X_REG_USBXIRQENABLESET1 0x3Cu
90 #define AM335X_REG_USBXIRQENABLECLR0 0x40u
91 #define AM335X_REG_USBXIRQENABLECLR1 0x44u
92 #define AM335X_REG_USBXTXMODE 0x70u
93 #define AM335X_REG_USBXRXMODE 0x74u
94 #define AM335X_REG_USBXGENRNDISEP1 0x80u
95 #define AM335X_REG_USBXGENRNDISEP2 0x84u
96 #define AM335X_REG_USBXGENRNDISEP3 0x88u
97 #define AM335X_REG_USBXGENRNDISEP4 0x8Cu
98 #define AM335X_REG_USBXGENRNDISEP5 0x90u
99 #define AM335X_REG_USBXGENRNDISEP6 0x94u
100 #define AM335X_REG_USBXGENRNDISEP7 0x98u
101 #define AM335X_REG_USBXGENRNDISEP8 0x9Cu
102 #define AM335X_REG_USBXGENRNDISEP9 0xA0u
103 #define AM335X_REG_USBXGENRNDISEP10 0xA4u
104 #define AM335X_REG_USBXGENRNDISEP11 0xA8u
105 #define AM335X_REG_USBXGENRNDISEP12 0xACu
106 #define AM335X_REG_USBXGENRNDISEP13 0xB0u
107 #define AM335X_REG_USBXGENRNDISEP14 0xB4u
108 #define AM335X_REG_USBXGENRNDISEP15 0xB8u
109 #define AM335X_REG_USBXAUTOREQ 0xD0u
110 #define AM335X_REG_USBXSRPFIXTIME 0xD4u
111 #define AM335X_REG_USBX_TDOWN 0xD8u
112 #define AM335X_REG_USBXUTMI 0xE0u
113 #define AM335X_REG_USBXMGCUTMILB 0xE4u
114 #define AM335X_REG_USBXMODE 0xE8u
116 /* Values to be set */
117 #define AM335X_VAL_USBXCTRL_SOFT_RESET HCD_BIT(0)
118 #define AM335X_VAL_USBXCTRL_UINT HCD_BIT(3)
120 #define AM335X_VAL_USBXMODE_IDDIG_MUX HCD_BIT(7)
121 #define AM335X_VAL_USBXMODE_IDDIG HCD_BIT(8)
123 #define AM335X_VAL_USBXIRQENABLEXXX0_EP0 HCD_BIT(0)
124 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP1 HCD_BIT(1)
125 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP2 HCD_BIT(2)
126 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP3 HCD_BIT(3)
127 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP4 HCD_BIT(4)
128 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP5 HCD_BIT(5)
129 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP6 HCD_BIT(6)
130 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP7 HCD_BIT(7)
131 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP8 HCD_BIT(8)
132 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP9 HCD_BIT(9)
133 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP10 HCD_BIT(10)
134 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP11 HCD_BIT(11)
135 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP12 HCD_BIT(12)
136 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP13 HCD_BIT(13)
137 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP14 HCD_BIT(14)
138 #define AM335X_VAL_USBXIRQENABLEXXX0_TX_EP15 HCD_BIT(15)
139 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP1 HCD_BIT(17)
140 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP2 HCD_BIT(18)
141 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP3 HCD_BIT(19)
142 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP4 HCD_BIT(20)
143 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP5 HCD_BIT(21)
144 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP6 HCD_BIT(22)
145 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP7 HCD_BIT(23)
146 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP8 HCD_BIT(24)
147 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP9 HCD_BIT(25)
148 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP10 HCD_BIT(26)
149 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP11 HCD_BIT(27)
150 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP12 HCD_BIT(28)
151 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP13 HCD_BIT(29)
152 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP14 HCD_BIT(30)
153 #define AM335X_VAL_USBXIRQENABLEXXX0_RX_EP15 HCD_BIT(31)
155 #define AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND HCD_BIT(0)
156 #define AM335X_VAL_USBXIRQENABLEXXX1_RESUME HCD_BIT(1)
157 #define AM335X_VAL_USBXIRQENABLEXXX1_RESET_BABBLE HCD_BIT(2)
158 #define AM335X_VAL_USBXIRQENABLEXXX1_SOF HCD_BIT(3)
159 #define AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED HCD_BIT(4)
160 #define AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED HCD_BIT(5)
161 #define AM335X_VAL_USBXIRQENABLEXXX1_SRP HCD_BIT(6)
162 #define AM335X_VAL_USBXIRQENABLEXXX1_VBUS HCD_BIT(7)
163 #define AM335X_VAL_USBXIRQENABLEXXX1_DRVVBUS HCD_BIT(8)
164 #define AM335X_VAL_USBXIRQENABLEXXX1_GENERIC HCD_BIT(9)
166 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_1 HCD_BIT(17)
167 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_2 HCD_BIT(18)
168 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_3 HCD_BIT(19)
169 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_4 HCD_BIT(20)
170 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_5 HCD_BIT(21)
171 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_6 HCD_BIT(22)
172 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_7 HCD_BIT(23)
173 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_8 HCD_BIT(24)
174 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_9 HCD_BIT(25)
175 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_10 HCD_BIT(26)
176 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_11 HCD_BIT(27)
177 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_12 HCD_BIT(28)
178 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_13 HCD_BIT(29)
179 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_14 HCD_BIT(30)
180 #define AM335X_VAL_USBXIRQENABLEXXX1_TX_FIFO_15 HCD_BIT(31)
182 #define AM335X_VAL_USBXIRQSTAT1_SUSPEND HCD_BIT(0)
183 #define AM335X_VAL_USBXIRQSTAT1_RESUME HCD_BIT(1)
184 #define AM335X_VAL_USBXIRQSTAT1_RESET_BABBLE HCD_BIT(2)
185 #define AM335X_VAL_USBXIRQSTAT1_SOF HCD_BIT(3)
186 #define AM335X_VAL_USBXIRQSTAT1_CONNECTED HCD_BIT(4)
187 #define AM335X_VAL_USBXIRQSTAT1_DISCONNECTED HCD_BIT(5)
188 #define AM335X_VAL_USBXIRQSTAT1_SRP HCD_BIT(6)
189 #define AM335X_VAL_USBXIRQSTAT1_VBUS HCD_BIT(7)
190 #define AM335X_VAL_USBXIRQSTAT1_DRVVBUS HCD_BIT(8)
191 #define AM335X_VAL_USBXIRQSTAT1_GENERIC HCD_BIT(9)
193 /* Helpers for interrupt clearing */
194 #define CLEAR_IRQ0(irq0_bit) HCD_WR4(r, AM335X_REG_USBXIRQSTAT0, (irq0_bit))
195 #define CLEAR_IRQ1(irq1_bit) HCD_WR4(r, AM335X_REG_USBXIRQSTAT1, (irq1_bit))
198 /*===========================================================================*
199 * AM335x clocking register defines *
200 *===========================================================================*/
201 /* Clock module registers offsets */
202 #define AM335X_REG_CM_PER_USB0_CLKCTRL_OFFSET 0x1Cu
204 /* Possible values to be set */
205 #define AM335X_VAL_CM_PER_USB0_CLKCTRL_MODULEMODE_ENABLE 0x2u
206 #define AM335X_CLKCONF_FULL_VAL 0xFFFFFFFFu
209 /*===========================================================================*
210 * AM335x USB configuration structures *
211 *===========================================================================*/
212 #define AM335X_USBSS_IRQ 17
213 #define AM335X_USB0_IRQ 18
214 #define AM335X_USB1_IRQ 19
216 /* Hardware configuration values specific to AM335X USBSS (USB Subsystem) */
217 typedef struct am335x_ss_config {
219 void * regs; /* Points to beginning of memory mapped register space */
221 am335x_ss_config;
223 /* Hardware configuration values specific to AM335X USB(0,1) OTG */
224 typedef struct am335x_usbX_config {
226 void * regs; /* Points to beginning of memory mapped register space */
228 am335x_usbX_config;
230 /* Private data for AM335X's IRQ thread */
231 typedef struct am335x_irq_private {
233 int usb_num; /* Number of currently handled controller (0, 1) */
235 am335x_irq_private;
237 /* Single MUSB peripheral information */
238 typedef struct am335x_controller {
240 am335x_irq_private priv;
241 am335x_usbX_config usb;
242 musb_core_config core;
243 hcd_driver_state driver;
245 am335x_controller;
247 #define AM335X_NUM_USB_CONTROLLERS 2
248 #define AM335X_USB0 0
249 #define AM335X_USB1 1
251 /* Configuration values specific to AM335X... */
252 typedef struct am335x_config {
254 am335x_ss_config ss;
255 am335x_controller ctrl[AM335X_NUM_USB_CONTROLLERS];
257 am335x_config;
259 /* ...and their current holder */
260 static am335x_config am335x;
263 /*===========================================================================*
264 * Local declarations *
265 *===========================================================================*/
266 /* Basic functionality */
267 static int musb_am335x_internal_init(void);
268 static void musb_am335x_internal_deinit(void);
270 /* Interrupt related */
271 static void musb_am335x_irq_init(void *);
272 static void musb_am335x_usbss_isr(void *);
273 static void musb_am335x_usbx_isr(void *);
274 static hcd_reg1 musb_am335x_irqstat0_to_ep(int);
276 /* Configuration helpers */
277 static void musb_am335x_usb_reset(int);
278 static void musb_am335x_otg_enable(int);
281 /*===========================================================================*
282 * musb_am335x_init *
283 *===========================================================================*/
285 musb_am335x_init(void)
287 am335x_controller * ctrl;
289 DEBUG_DUMP;
291 /* Initial cleanup */
292 memset(&am335x, 0, sizeof(am335x));
294 /* These registers are specific to AM335X so they are mapped here */
295 /* -------------------------------------------------------------- */
296 /* USBSS -------------------------------------------------------- */
297 /* -------------------------------------------------------------- */
299 /* Map memory for USBSS */
300 am335x.ss.regs = hcd_os_regs_init(AM335X_USBSS_BASE_ADDR,
301 AM335X_USBSS_TOTAL_REG_LEN);
303 if (NULL == am335x.ss.regs)
304 return EXIT_FAILURE;
306 /* Attach IRQ to number */
307 if (EXIT_SUCCESS != hcd_os_interrupt_attach(AM335X_USBSS_IRQ,
308 musb_am335x_irq_init,
309 musb_am335x_usbss_isr,
310 NULL))
311 return EXIT_FAILURE;
313 #ifdef AM335X_USE_USB0
314 /* -------------------------------------------------------------- */
315 /* USB0 --------------------------------------------------------- */
316 /* -------------------------------------------------------------- */
318 ctrl = &(am335x.ctrl[AM335X_USB0]);
320 /* IRQ thread private data */
321 ctrl->priv.usb_num = AM335X_USB0;
323 /* MUSB core addresses for later registering */
324 ctrl->core.regs = (void*)((hcd_addr)am335x.ss.regs +
325 AM335X_MUSB_CORE0_BASE_OFFSET);
327 /* Map AM335X USB0 specific addresses */
328 ctrl->usb.regs = (void*)((hcd_addr)am335x.ss.regs +
329 AM335X_USB0_BASE_OFFSET);
331 /* Attach IRQ to number */
332 if (EXIT_SUCCESS != hcd_os_interrupt_attach(AM335X_USB0_IRQ,
333 musb_am335x_irq_init,
334 musb_am335x_usbx_isr,
335 &(ctrl->priv)))
336 return EXIT_FAILURE;
338 /* Initialize HCD driver */
339 ctrl->driver.private_data = &(ctrl->core);
340 ctrl->driver.setup_device = musb_setup_device;
341 ctrl->driver.reset_device = musb_reset_device;
342 ctrl->driver.setup_stage = musb_setup_stage;
343 ctrl->driver.rx_stage = musb_rx_stage;
344 ctrl->driver.tx_stage = musb_tx_stage;
345 ctrl->driver.in_data_stage = musb_in_data_stage;
346 ctrl->driver.out_data_stage = musb_out_data_stage;
347 ctrl->driver.in_status_stage = musb_in_status_stage;
348 ctrl->driver.out_status_stage = musb_out_status_stage;
349 ctrl->driver.read_data = musb_read_data;
350 ctrl->driver.check_error = musb_check_error;
351 ctrl->driver.port_device = NULL;
353 #endif
355 /* -------------------------------------------------------------- */
356 /* USB1 --------------------------------------------------------- */
357 /* -------------------------------------------------------------- */
359 ctrl = &(am335x.ctrl[AM335X_USB1]);
361 /* IRQ thread private data */
362 ctrl->priv.usb_num = AM335X_USB1;
364 /* MUSB core addresses for later registering */
365 ctrl->core.regs = (void*)((hcd_addr)am335x.ss.regs +
366 AM335X_MUSB_CORE1_BASE_OFFSET);
368 /* Map AM335X USB0 specific addresses */
369 ctrl->usb.regs = (void*)((hcd_addr)am335x.ss.regs +
370 AM335X_USB1_BASE_OFFSET);
372 /* Attach IRQ to number */
373 if (EXIT_SUCCESS != hcd_os_interrupt_attach(AM335X_USB1_IRQ,
374 musb_am335x_irq_init,
375 musb_am335x_usbx_isr,
376 &(ctrl->priv)))
377 return EXIT_FAILURE;
379 /* Initialize HCD driver */
380 ctrl->driver.private_data = &(ctrl->core);
381 ctrl->driver.setup_device = musb_setup_device;
382 ctrl->driver.reset_device = musb_reset_device;
383 ctrl->driver.setup_stage = musb_setup_stage;
384 ctrl->driver.rx_stage = musb_rx_stage;
385 ctrl->driver.tx_stage = musb_tx_stage;
386 ctrl->driver.in_data_stage = musb_in_data_stage;
387 ctrl->driver.out_data_stage = musb_out_data_stage;
388 ctrl->driver.in_status_stage = musb_in_status_stage;
389 ctrl->driver.out_status_stage = musb_out_status_stage;
390 ctrl->driver.read_data = musb_read_data;
391 ctrl->driver.check_error = musb_check_error;
392 ctrl->driver.port_device = NULL;
395 return musb_am335x_internal_init();
399 /*===========================================================================*
400 * musb_am335x_deinit *
401 *===========================================================================*/
402 void
403 musb_am335x_deinit(void)
405 DEBUG_DUMP;
407 musb_am335x_internal_deinit();
409 /* Release IRQ resources */
410 /* TODO: DDEKit has no checks on NULL IRQ and may crash on detach
411 * if interrupts were not attached properly */
412 hcd_os_interrupt_detach(AM335X_USB1_IRQ);
413 #ifdef AM335X_USE_USB0
414 hcd_os_interrupt_detach(AM335X_USB0_IRQ);
415 #endif
416 hcd_os_interrupt_detach(AM335X_USBSS_IRQ);
418 /* Release maps if anything was assigned */
419 if (NULL != am335x.ss.regs)
420 if (EXIT_SUCCESS != hcd_os_regs_deinit((hcd_addr)am335x.ss.regs,
421 AM335X_USBSS_TOTAL_REG_LEN))
422 USB_MSG("Failed to release USBSS mapping");
426 /*===========================================================================*
427 * musb_am335x_internal_init *
428 *===========================================================================*/
429 static int
430 musb_am335x_internal_init(void)
432 DEBUG_DUMP;
434 /* Configure clocking */
435 if (hcd_os_clkconf(AM335X_REG_CM_PER_USB0_CLKCTRL_OFFSET,
436 AM335X_VAL_CM_PER_USB0_CLKCTRL_MODULEMODE_ENABLE,
437 AM335X_CLKCONF_FULL_VAL))
438 return EXIT_FAILURE;
440 /* Read and dump revision register */
441 USB_MSG("MUSB revision (REVREG): 0x%08X",
442 (unsigned int)HCD_RD4(am335x.ss.regs, AM335X_REG_REVREG));
444 /* Allow OS to handle previously configured USBSS interrupts */
445 hcd_os_interrupt_enable(AM335X_USBSS_IRQ);
447 #ifdef AM335X_USE_USB0
448 /* Reset controllers so we get default register values */
449 musb_am335x_usb_reset(AM335X_USB0);
450 /* Allow OS to handle previously configured USB0 interrupts */
451 hcd_os_interrupt_enable(AM335X_USB0_IRQ);
452 /* Enable whatever necessary for OTG part of controller */
453 musb_am335x_otg_enable(AM335X_USB0);
454 /* Start actual MUSB core */
455 musb_core_start(&(am335x.ctrl[AM335X_USB0].core));
456 #endif
458 /* Reset controllers so we get default register values */
459 musb_am335x_usb_reset(AM335X_USB1);
460 /* Allow OS to handle previously configured USB1 interrupts */
461 hcd_os_interrupt_enable(AM335X_USB1_IRQ);
462 /* Enable whatever necessary for OTG part of controller */
463 musb_am335x_otg_enable(AM335X_USB1);
464 /* Start actual MUSB core */
465 musb_core_start(&(am335x.ctrl[AM335X_USB1].core));
467 return EXIT_SUCCESS;
471 /*===========================================================================*
472 * musb_am335x_internal_deinit *
473 *===========================================================================*/
474 static void
475 musb_am335x_internal_deinit(void)
477 DEBUG_DUMP;
479 /* Disable all interrupts */
480 hcd_os_interrupt_disable(AM335X_USBSS_IRQ);
481 #ifdef AM335X_USE_USB0
482 hcd_os_interrupt_disable(AM335X_USB0_IRQ);
483 #endif
484 hcd_os_interrupt_disable(AM335X_USB1_IRQ);
486 /* Stop core */
487 #ifdef AM335X_USE_USB0
488 musb_core_stop(&(am335x.ctrl[AM335X_USB0].core));
489 #endif
490 musb_core_stop(&(am335x.ctrl[AM335X_USB1].core));
492 /* Every clkconf call should have corresponding release */
493 hcd_os_clkconf_release();
497 /*===========================================================================*
498 * musb_am335x_irq_init *
499 *===========================================================================*/
500 static void
501 musb_am335x_irq_init(void * UNUSED(unused))
503 DEBUG_DUMP;
505 /* TODO: This function does nothing and is not needed by MUSB but
506 * is still required by DDEKit for initialization, as NULL pointer
507 * cannot be passed to ddekit_interrupt_attach */
508 return;
512 /*===========================================================================*
513 * musb_am335x_usbss_isr *
514 *===========================================================================*/
515 static void
516 musb_am335x_usbss_isr(void * UNUSED(data))
518 void * r;
519 hcd_reg4 irqstat;
521 DEBUG_DUMP;
523 r = am335x.ss.regs;
525 irqstat = HCD_RD4(r, AM335X_REG_IRQSTAT);
527 USB_DBG("AM335X_REG_IRQSTAT = %X", (unsigned int)irqstat);
529 /* Write to clear interrupt */
530 HCD_WR4(r, AM335X_REG_IRQSTAT, irqstat);
534 /*===========================================================================*
535 * musb_am335x_usbx_isr *
536 *===========================================================================*/
537 static void
538 musb_am335x_usbx_isr(void * data)
540 void * r;
541 hcd_driver_state * driver;
542 hcd_reg4 irqstat0;
543 hcd_reg4 irqstat1;
544 int usb_num;
546 DEBUG_DUMP;
548 /* Prepare locals based on USB controller number for this interrupt */
549 usb_num = ((am335x_irq_private*)data)->usb_num;
550 r = am335x.ctrl[usb_num].usb.regs;
551 driver = &(am335x.ctrl[usb_num].driver);
553 /* Read, handle and clean interrupts */
554 irqstat0 = HCD_RD4(r, AM335X_REG_USBXIRQSTAT0);
555 irqstat1 = HCD_RD4(r, AM335X_REG_USBXIRQSTAT1);
557 /* Interrupts, seem to appear one at a time
558 * Check which bit is set to resolve event */
559 if (irqstat1 & AM335X_VAL_USBXIRQSTAT1_DRVVBUS) {
560 USB_DBG("DRVVBUS level changed");
561 CLEAR_IRQ1(AM335X_VAL_USBXIRQSTAT1_DRVVBUS);
562 return;
565 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED) {
566 USB_DBG("Device connected");
567 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED);
568 hcd_update_port(driver, HCD_EVENT_CONNECTED);
569 hcd_handle_event(driver->port_device, HCD_EVENT_CONNECTED,
570 HCD_UNUSED_VAL);
571 return;
574 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED) {
575 USB_DBG("Device disconnected");
576 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED);
577 hcd_handle_event(driver->port_device, HCD_EVENT_DISCONNECTED,
578 HCD_UNUSED_VAL);
579 hcd_update_port(driver, HCD_EVENT_DISCONNECTED);
580 return;
583 if (0 != irqstat0) {
584 USB_DBG("EP interrupt");
585 CLEAR_IRQ0(irqstat0);
586 hcd_handle_event(driver->port_device, HCD_EVENT_ENDPOINT,
587 musb_am335x_irqstat0_to_ep(irqstat0));
588 return;
591 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND) {
592 USB_DBG("Unhandled SUSPEND IRQ");
593 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND);
594 return;
597 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_RESUME) {
598 USB_DBG("Unhandled RESUME IRQ");
599 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_RESUME);
600 return;
603 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_RESET_BABBLE) {
604 USB_DBG("Unhandled RESET/BABBLE IRQ");
605 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_RESET_BABBLE);
606 return;
609 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SOF) {
610 USB_DBG("Unhandled SOF IRQ");
611 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SOF);
612 return;
615 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SRP) {
616 USB_DBG("Unhandled SRP IRQ");
617 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SRP);
618 return;
621 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_VBUS) {
622 USB_DBG("Unhandled VBUS IRQ");
623 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_VBUS);
624 return;
627 if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_GENERIC) {
628 USB_DBG("Unhandled GENERIC IRQ");
629 CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_GENERIC);
630 return;
633 /* When controller is correctly configured this should never happen: */
634 USB_MSG("Illegal value of IRQxSTAT: 0=%X 1=%X",
635 (unsigned int)irqstat0, (unsigned int)irqstat1);
636 USB_ASSERT(0, "IRQxSTAT error");
640 /*===========================================================================*
641 * musb_am335x_irqstat0_to_ep *
642 *===========================================================================*/
643 static hcd_reg1
644 musb_am335x_irqstat0_to_ep(int irqstat0)
646 hcd_reg1 ep;
648 DEBUG_DUMP;
650 ep = 0;
652 while (0 == (irqstat0 & 0x01)) {
653 irqstat0 >>= 1;
654 ep++;
655 /* Must be within two consecutive EP sets */
656 USB_ASSERT(ep < (2 * HCD_TOTAL_EP),
657 "Invalid IRQSTAT0 supplied (1)");
660 /* Convert RX interrupt to EP number */
661 if (ep >= HCD_TOTAL_EP) {
662 ep -= HCD_TOTAL_EP;
663 /* Must not be control EP */
664 USB_ASSERT(ep != HCD_DEFAULT_EP,
665 "Invalid IRQSTAT0 supplied (2)");
668 return ep;
672 /*===========================================================================*
673 * musb_am335x_usb_reset *
674 *===========================================================================*/
675 static void
676 musb_am335x_usb_reset(int usb_num)
678 void * r;
679 hcd_reg4 ctrl;
681 DEBUG_DUMP;
683 r = am335x.ctrl[usb_num].usb.regs;
685 /* Set SOFT_RESET bit and wait until it is off */
686 ctrl = HCD_RD4(r, AM335X_REG_USBXCTRL);
687 HCD_SET(ctrl, AM335X_VAL_USBXCTRL_SOFT_RESET);
688 HCD_WR4(r, AM335X_REG_USBXCTRL, ctrl);
689 while (HCD_RD4(r, AM335X_REG_USBXCTRL) &
690 AM335X_VAL_USBXCTRL_SOFT_RESET);
694 /*===========================================================================*
695 * musb_am335x_otg_enable *
696 *===========================================================================*/
697 static void
698 musb_am335x_otg_enable(int usb_num)
700 void * r;
701 hcd_reg4 intreg;
702 hcd_reg4 mode;
704 DEBUG_DUMP;
706 r = am335x.ctrl[usb_num].usb.regs;
708 /* Force host operation */
709 mode = HCD_RD4(r, AM335X_REG_USBXMODE);
710 HCD_SET(mode, AM335X_VAL_USBXMODE_IDDIG_MUX);
711 HCD_CLR(mode, AM335X_VAL_USBXMODE_IDDIG);
712 HCD_WR4(r, AM335X_REG_USBXMODE, mode);
714 /* Set all important interrupts to be handled */
715 intreg = HCD_RD4(r, AM335X_REG_USBXIRQENABLESET1);
716 HCD_SET(intreg, AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND |
717 AM335X_VAL_USBXIRQENABLEXXX1_RESUME |
718 AM335X_VAL_USBXIRQENABLEXXX1_RESET_BABBLE |
719 /* AM335X_VAL_USBXIRQENABLEXXX1_SOF | */
720 AM335X_VAL_USBXIRQENABLEXXX1_CONNECTED |
721 AM335X_VAL_USBXIRQENABLEXXX1_DISCONNECTED |
722 AM335X_VAL_USBXIRQENABLEXXX1_SRP |
723 AM335X_VAL_USBXIRQENABLEXXX1_VBUS |
724 AM335X_VAL_USBXIRQENABLEXXX1_DRVVBUS |
725 AM335X_VAL_USBXIRQENABLEXXX1_GENERIC);
727 HCD_WR4(r, AM335X_REG_USBXIRQENABLESET1, intreg);
729 /* Set all EP interrupts as enabled */
730 intreg = AM335X_VAL_USBXIRQENABLEXXX0_EP0 |
731 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP1 |
732 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP2 |
733 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP3 |
734 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP4 |
735 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP5 |
736 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP6 |
737 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP7 |
738 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP8 |
739 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP9 |
740 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP10 |
741 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP11 |
742 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP12 |
743 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP13 |
744 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP14 |
745 AM335X_VAL_USBXIRQENABLEXXX0_TX_EP15 |
746 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP1 |
747 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP2 |
748 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP3 |
749 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP4 |
750 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP5 |
751 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP6 |
752 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP7 |
753 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP8 |
754 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP9 |
755 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP10 |
756 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP11 |
757 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP12 |
758 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP13 |
759 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP14 |
760 AM335X_VAL_USBXIRQENABLEXXX0_RX_EP15 ;
762 HCD_WR4(r, AM335X_REG_USBXIRQENABLESET0, intreg);