xref: /minix/minix/drivers/usb/usbd/hcd/musb/musb_am335x.c (revision 83133719)
1 /*
2  * Implementation of whatever is hardware specific in AM335x MCU
3  */
4 
5 #include <string.h>					/* memset */
6 
7 #include <usbd/hcd_common.h>
8 #include <usbd/hcd_platforms.h>
9 #include <usbd/hcd_interface.h>
10 #include <usbd/usbd_common.h>
11 
12 #include "musb_core.h"
13 
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
18 
19 
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
30 
31 
32 /*===========================================================================*
33  *    AM335x USB specific register defines                                   *
34  *===========================================================================*/
35 /* SS registers base address */
36 
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
79 
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
115 
116 /* Values to be set */
117 #define AM335X_VAL_USBXCTRL_SOFT_RESET		HCD_BIT(0)
118 #define AM335X_VAL_USBXCTRL_UINT		HCD_BIT(3)
119 
120 #define AM335X_VAL_USBXMODE_IDDIG_MUX		HCD_BIT(7)
121 #define AM335X_VAL_USBXMODE_IDDIG		HCD_BIT(8)
122 
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)
154 
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)
165 
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)
181 
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)
192 
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))
196 
197 
198 /*===========================================================================*
199  *    AM335x clocking register defines                                       *
200  *===========================================================================*/
201 /* Clock module registers offsets */
202 #define AM335X_REG_CM_PER_USB0_CLKCTRL_OFFSET			0x1Cu
203 
204 /* Possible values to be set */
205 #define AM335X_VAL_CM_PER_USB0_CLKCTRL_MODULEMODE_ENABLE	0x2u
206 #define AM335X_CLKCONF_FULL_VAL					0xFFFFFFFFu
207 
208 
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
215 
216 /* Hardware configuration values specific to AM335X USBSS (USB Subsystem) */
217 typedef struct am335x_ss_config {
218 
219 	void * regs; /* Points to beginning of memory mapped register space */
220 }
221 am335x_ss_config;
222 
223 /* Hardware configuration values specific to AM335X USB(0,1) OTG */
224 typedef struct am335x_usbX_config {
225 
226 	void * regs; /* Points to beginning of memory mapped register space */
227 }
228 am335x_usbX_config;
229 
230 /* Private data for AM335X's IRQ thread */
231 typedef struct am335x_irq_private {
232 
233 	int usb_num; /* Number of currently handled controller (0, 1) */
234 }
235 am335x_irq_private;
236 
237 /* Single MUSB peripheral information */
238 typedef struct am335x_controller {
239 
240 	am335x_irq_private	priv;
241 	am335x_usbX_config	usb;
242 	musb_core_config	core;
243 	hcd_driver_state	driver;
244 }
245 am335x_controller;
246 
247 #define AM335X_NUM_USB_CONTROLLERS	2
248 #define AM335X_USB0			0
249 #define AM335X_USB1			1
250 
251 /* Configuration values specific to AM335X... */
252 typedef struct am335x_config {
253 
254 	am335x_ss_config	ss;
255 	am335x_controller	ctrl[AM335X_NUM_USB_CONTROLLERS];
256 }
257 am335x_config;
258 
259 /* ...and their current holder */
260 static am335x_config am335x;
261 
262 
263 /*===========================================================================*
264  *    Local declarations                                                     *
265  *===========================================================================*/
266 /* Basic functionality */
267 static int musb_am335x_internal_init(void);
268 static void musb_am335x_internal_deinit(void);
269 
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);
275 
276 /* Configuration helpers */
277 static void musb_am335x_usb_reset(int);
278 static void musb_am335x_otg_enable(int);
279 
280 
281 /*===========================================================================*
282  *    musb_am335x_init                                                       *
283  *===========================================================================*/
284 int
285 musb_am335x_init(void)
286 {
287 	am335x_controller * ctrl;
288 
289 	DEBUG_DUMP;
290 
291 	/* Initial cleanup */
292 	memset(&am335x, 0, sizeof(am335x));
293 
294 	/* These registers are specific to AM335X so they are mapped here */
295 	/* -------------------------------------------------------------- */
296 	/* USBSS -------------------------------------------------------- */
297 	/* -------------------------------------------------------------- */
298 
299 	/* Map memory for USBSS */
300 	am335x.ss.regs = hcd_os_regs_init(AM335X_USBSS_BASE_ADDR,
301 					AM335X_USBSS_TOTAL_REG_LEN);
302 
303 	if (NULL == am335x.ss.regs)
304 		return EXIT_FAILURE;
305 
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;
312 
313 #ifdef AM335X_USE_USB0
314 	/* -------------------------------------------------------------- */
315 	/* USB0 --------------------------------------------------------- */
316 	/* -------------------------------------------------------------- */
317 	{
318 		ctrl = &(am335x.ctrl[AM335X_USB0]);
319 
320 		/* IRQ thread private data */
321 		ctrl->priv.usb_num = AM335X_USB0;
322 
323 		/* MUSB core addresses for later registering */
324 		ctrl->core.regs = (void*)((hcd_addr)am335x.ss.regs +
325 					AM335X_MUSB_CORE0_BASE_OFFSET);
326 
327 		/* Map AM335X USB0 specific addresses */
328 		ctrl->usb.regs = (void*)((hcd_addr)am335x.ss.regs +
329 					AM335X_USB0_BASE_OFFSET);
330 
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;
337 
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;
352 	}
353 #endif
354 
355 	/* -------------------------------------------------------------- */
356 	/* USB1 --------------------------------------------------------- */
357 	/* -------------------------------------------------------------- */
358 	{
359 		ctrl = &(am335x.ctrl[AM335X_USB1]);
360 
361 		/* IRQ thread private data */
362 		ctrl->priv.usb_num = AM335X_USB1;
363 
364 		/* MUSB core addresses for later registering */
365 		ctrl->core.regs = (void*)((hcd_addr)am335x.ss.regs +
366 					AM335X_MUSB_CORE1_BASE_OFFSET);
367 
368 		/* Map AM335X USB0 specific addresses */
369 		ctrl->usb.regs = (void*)((hcd_addr)am335x.ss.regs +
370 					AM335X_USB1_BASE_OFFSET);
371 
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;
378 
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;
393 	}
394 
395 	return musb_am335x_internal_init();
396 }
397 
398 
399 /*===========================================================================*
400  *    musb_am335x_deinit                                                     *
401  *===========================================================================*/
402 void
403 musb_am335x_deinit(void)
404 {
405 	DEBUG_DUMP;
406 
407 	musb_am335x_internal_deinit();
408 
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);
417 
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");
423 }
424 
425 
426 /*===========================================================================*
427  *    musb_am335x_internal_init                                              *
428  *===========================================================================*/
429 static int
430 musb_am335x_internal_init(void)
431 {
432 	DEBUG_DUMP;
433 
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;
439 
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));
443 
444 	/* Allow OS to handle previously configured USBSS interrupts */
445 	hcd_os_interrupt_enable(AM335X_USBSS_IRQ);
446 
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
457 
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));
466 
467 	return EXIT_SUCCESS;
468 }
469 
470 
471 /*===========================================================================*
472  *    musb_am335x_internal_deinit                                            *
473  *===========================================================================*/
474 static void
475 musb_am335x_internal_deinit(void)
476 {
477 	DEBUG_DUMP;
478 
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);
485 
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));
491 
492 	/* Every clkconf call should have corresponding release */
493 	hcd_os_clkconf_release();
494 }
495 
496 
497 /*===========================================================================*
498  *    musb_am335x_irq_init                                                   *
499  *===========================================================================*/
500 static void
501 musb_am335x_irq_init(void * UNUSED(unused))
502 {
503 	DEBUG_DUMP;
504 
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;
509 }
510 
511 
512 /*===========================================================================*
513  *    musb_am335x_usbss_isr                                                  *
514  *===========================================================================*/
515 static void
516 musb_am335x_usbss_isr(void * UNUSED(data))
517 {
518 	void * r;
519 	hcd_reg4 irqstat;
520 
521 	DEBUG_DUMP;
522 
523 	r = am335x.ss.regs;
524 
525 	irqstat = HCD_RD4(r, AM335X_REG_IRQSTAT);
526 
527 	USB_DBG("AM335X_REG_IRQSTAT = %X", (unsigned int)irqstat);
528 
529 	/* Write to clear interrupt */
530 	HCD_WR4(r, AM335X_REG_IRQSTAT, irqstat);
531 }
532 
533 
534 /*===========================================================================*
535  *    musb_am335x_usbx_isr                                                   *
536  *===========================================================================*/
537 static void
538 musb_am335x_usbx_isr(void * data)
539 {
540 	void * r;
541 	hcd_driver_state * driver;
542 	hcd_reg4 irqstat0;
543 	hcd_reg4 irqstat1;
544 	int usb_num;
545 
546 	DEBUG_DUMP;
547 
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);
552 
553 	/* Read, handle and clean interrupts */
554 	irqstat0 = HCD_RD4(r, AM335X_REG_USBXIRQSTAT0);
555 	irqstat1 = HCD_RD4(r, AM335X_REG_USBXIRQSTAT1);
556 
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;
563 	}
564 
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;
572 	}
573 
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;
581 	}
582 
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;
589 	}
590 
591 	if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND) {
592 		USB_DBG("Unhandled SUSPEND IRQ");
593 		CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SUSPEND);
594 		return;
595 	}
596 
597 	if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_RESUME) {
598 		USB_DBG("Unhandled RESUME IRQ");
599 		CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_RESUME);
600 		return;
601 	}
602 
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;
607 	}
608 
609 	if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SOF) {
610 		USB_DBG("Unhandled SOF IRQ");
611 		CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SOF);
612 		return;
613 	}
614 
615 	if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_SRP) {
616 		USB_DBG("Unhandled SRP IRQ");
617 		CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_SRP);
618 		return;
619 	}
620 
621 	if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_VBUS) {
622 		USB_DBG("Unhandled VBUS IRQ");
623 		CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_VBUS);
624 		return;
625 	}
626 
627 	if (irqstat1 & AM335X_VAL_USBXIRQENABLEXXX1_GENERIC) {
628 		USB_DBG("Unhandled GENERIC IRQ");
629 		CLEAR_IRQ1(AM335X_VAL_USBXIRQENABLEXXX1_GENERIC);
630 		return;
631 	}
632 
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");
637 }
638 
639 
640 /*===========================================================================*
641  *    musb_am335x_irqstat0_to_ep                                             *
642  *===========================================================================*/
643 static hcd_reg1
644 musb_am335x_irqstat0_to_ep(int irqstat0)
645 {
646 	hcd_reg1 ep;
647 
648 	DEBUG_DUMP;
649 
650 	ep = 0;
651 
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)");
658 	}
659 
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)");
666 	}
667 
668 	return ep;
669 }
670 
671 
672 /*===========================================================================*
673  *    musb_am335x_usb_reset                                                  *
674  *===========================================================================*/
675 static void
676 musb_am335x_usb_reset(int usb_num)
677 {
678 	void * r;
679 	hcd_reg4 ctrl;
680 
681 	DEBUG_DUMP;
682 
683 	r = am335x.ctrl[usb_num].usb.regs;
684 
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);
691 }
692 
693 
694 /*===========================================================================*
695  *    musb_am335x_otg_enable                                                 *
696  *===========================================================================*/
697 static void
698 musb_am335x_otg_enable(int usb_num)
699 {
700 	void * r;
701 	hcd_reg4 intreg;
702 	hcd_reg4 mode;
703 
704 	DEBUG_DUMP;
705 
706 	r = am335x.ctrl[usb_num].usb.regs;
707 
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);
713 
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);
726 
727 	HCD_WR4(r, AM335X_REG_USBXIRQENABLESET1, intreg);
728 
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	;
761 
762 	HCD_WR4(r, AM335X_REG_USBXIRQENABLESET0, intreg);
763 }
764