1/*
2 * =========================================================================
3 * ARM and PandaBoard specific functions
4 * =========================================================================
5 */
6
7#include <barrelfish/barrelfish.h>
8
9#include <usb/usb.h>
10
11#include <arch/arm/omap44xx/device_registers.h>
12#include <maps/omap44xx_map.h>
13
14#include <dev/omap/ehci_dev.h>
15#include <dev/omap/omap44xx_hsusbhost_dev.h>
16#include <dev/omap/omap44xx_usbtllhs_config_dev.h>
17#include <dev/omap/omap44xx_scrm_dev.h>
18#include <dev/omap/omap44xx_sysctrl_padconf_core_dev.h>
19#include <dev/omap/omap44xx_sysctrl_padconf_wkup_dev.h>
20#include <dev/omap/omap44xx_gpio_dev.h>
21#include <dev/omap/omap44xx_ehci_dev.h>
22#include <dev/omap/omap44xx_l3init_cm2_dev.h>
23#include <dev/omap/omap44xx_l4per_cm2_dev.h>
24#include <dev/omap/omap44xx_ckgen_prm_dev.h>
25
26#include <driverkit/driverkit.h>
27
28/* mackerel bases for USB initialization */
29static omap44xx_hsusbhost_t hsusbhost_base;
30static omap44xx_usbtllhs_config_t usbtllhs_config_base;
31static omap44xx_scrm_t srcm_base;
32static omap44xx_sysctrl_padconf_wkup_t sysctrl_padconf_wkup_base;
33static omap44xx_sysctrl_padconf_core_t sysctrl_padconf_core_base;
34static omap44xx_gpio_t gpio_1_base;
35static omap44xx_gpio_t gpio_2_base;
36static omap44xx_ehci_t ehci_base;
37static omap44xx_ckgen_prm_t ckgen_base;
38static omap44xx_l4per_cm2_t l4per_base;
39static omap44xx_l3init_cm2_t l3init_base;
40
41#include "platform.h"
42// the offset into the supplied capability
43#define USB_CAPABILITY_OFFSET (0x00000C00)
44
45// the EHCI interrupt number on the pandaboard
46#define USB_ARM_EHCI_IRQ 109
47
48
49
50/*
51 * initialize the USB functionality of the pandaboard
52 */
53static void hsusb_init(void)
54{
55
56    printf("  > hsusb_init()...\n");
57
58    /*
59     * Global Initialization of the OMAPP44xx USB Sub System
60     */
61    printf("  >  > USB TTL reset...");
62
63    /*
64     * Reset USBTTL
65     * USBTLL_SYSCONFIG = 0x2
66     */
67    omap44xx_usbtllhs_config_usbtll_sysconfig_softreset_wrf(
68            &usbtllhs_config_base, 0x1);
69
70    /*
71     * wait till reset is done
72     */
73    while (!omap44xx_usbtllhs_config_usbtll_sysstatus_resetdone_rdf(
74            &usbtllhs_config_base))
75        ;
76
77    /*
78     * USBTLL_SYSCONFIG
79     *  - Setting ENAWAKEUP
80     *  - Setting SIDLEMODE
81     *  - Setting CLOCKACTIVITY
82     */
83    omap44xx_usbtllhs_config_usbtll_sysconfig_t sysconf = 0x0;
84    sysconf = omap44xx_usbtllhs_config_usbtll_sysconfig_clockactivity_insert(
85            sysconf, 0x1);
86    sysconf = omap44xx_usbtllhs_config_usbtll_sysconfig_enawakeup_insert(
87            sysconf, 0x1);
88    sysconf = omap44xx_usbtllhs_config_usbtll_sysconfig_sidlemode_insert(
89            sysconf, 0x1);
90    omap44xx_usbtllhs_config_usbtll_sysconfig_wr(&usbtllhs_config_base,
91            sysconf);
92
93    printf("OK\n");
94
95    /*
96     * USBTLL_IRQENABLE:
97     *  - all interrupts
98     */
99    omap44xx_usbtllhs_config_usbtll_irqenable_t irqena = omap44xx_usbtllhs_config_usbtll_irqenable_default;
100    irqena = omap44xx_usbtllhs_config_usbtll_irqenable_fclk_start_en_insert(
101            irqena, 0x1);
102    irqena = omap44xx_usbtllhs_config_usbtll_irqenable_fclk_end_en_insert(
103            irqena, 0x1);
104    irqena = omap44xx_usbtllhs_config_usbtll_irqenable_access_error_en_insert(
105            irqena, 0x1);
106    omap44xx_usbtllhs_config_usbtll_irqenable_wr(&usbtllhs_config_base, irqena);
107
108    printf("  >  > USB host controller reset...");
109
110    /*
111     * per form a reset on the USB host controller module
112     * this resets both EHCI and OCHI controllers
113     *
114     * UHH_SYSCONFIG = 0x1
115     */
116    omap44xx_hsusbhost_uhh_sysconfig_softreset_wrf(&hsusbhost_base, 0x1);
117
118    /*
119     * wait till reset is done
120     * UHH_SYSSTATUS = 0x6
121     */
122    omap44xx_hsusbhost_uhh_sysstatus_t uhh_sysstat;
123    uint8_t ehci_done;
124    uint8_t ohci_done;
125    do {
126        uhh_sysstat = omap44xx_hsusbhost_uhh_sysstatus_rd(&hsusbhost_base);
127        ehci_done = omap44xx_hsusbhost_uhh_sysstatus_ehci_resetdone_extract(
128                uhh_sysstat);
129        ohci_done = omap44xx_hsusbhost_uhh_sysstatus_ohci_resetdone_extract(
130                uhh_sysstat);
131    } while (!(ehci_done & ohci_done));
132
133    /* enable some USB host features
134     * UHH_SYSCONFIG
135     *  - STANDBYMODE
136     *  - IDLEMODE
137     */
138    omap44xx_hsusbhost_uhh_sysconfig_standbymode_wrf(&hsusbhost_base, 0x1);
139    omap44xx_hsusbhost_uhh_sysconfig_idlemode_wrf(&hsusbhost_base, 0x1);
140
141    printf("OK\n");
142
143    printf("  >  > Setting USB host configuration values...");
144
145    /*
146     * setting the host configuration to external PHY and enable
147     * the burst types, app start clk
148     *
149     * UHH_HOSTCONFIG
150     *  - APP_START_CLK
151     *  - ENAINCR_x
152     */
153    // *((volatile uint32_t*) (0x4A064040)) =
154    //       (uint32_t) ((0x7 << 2) | (0x1 << 31));
155    omap44xx_hsusbhost_uhh_hostconfig_t hcfg = omap44xx_hsusbhost_uhh_hostconfig_default;
156    hcfg = omap44xx_hsusbhost_uhh_hostconfig_app_start_clk_insert(hcfg, 0x1);
157    hcfg = omap44xx_hsusbhost_uhh_hostconfig_ena_incr4_insert(hcfg, 0x1);
158    hcfg = omap44xx_hsusbhost_uhh_hostconfig_ena_incr8_insert(hcfg, 0x1);
159    hcfg = omap44xx_hsusbhost_uhh_hostconfig_ena_incr16_insert(hcfg, 0x1);
160    omap44xx_hsusbhost_uhh_hostconfig_wr(&hsusbhost_base, hcfg);
161
162    printf("OK\n");
163
164    printf("  > done.\n");
165}
166
167// GPIO numbers for enabling the USB hub on the pandaboard
168#define HSUSB_HUB_POWER 1
169#define HSUSB_HUB_RESET 30
170
171
172/*
173 * Initialize the high speed usb hub on the pandaboard
174 */
175static void usb_power_on(void)
176{
177    printf("usb_power_on()... \n");
178
179    printf("  > forward the AUXCLK3 to GPIO_WK31\n");
180    /*
181     * the USB hub needs the FREF_CLK3_OUT to be 19.2 MHz and that this
182     * clock goes to the GPIO_WK31 out.
183     * Assume that the sys clock is 38.4 MHz so we use a divider of 2
184     *
185     * Bit  8: is the enable bit
186     * Bit 16: is the divider bit (here for two)
187     */
188
189    omap44xx_scrm_auxclk3_t auxclk3 = omap44xx_scrm_auxclk3_default;
190    auxclk3 = omap44xx_scrm_auxclk3_enable_insert(auxclk3,
191            omap44xx_scrm_ENABLE_EXT_1);
192    auxclk3 = omap44xx_scrm_auxclk3_clkdiv_insert(auxclk3,
193            omap44xx_scrm_MODE_1);
194    omap44xx_scrm_auxclk3_wr(&srcm_base, auxclk3);
195
196    /*
197     * Forward the clock to the GPIO_WK31 pin
198     *  - muxmode = fref_clk3_out (0x0)
199     *  - no pullup/down (0x0)
200     *  - no input buffer (0x0)
201     *  - no wake up (0x0)
202     */
203    omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_t clk3_out;
204    clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_rd(
205            &sysctrl_padconf_wkup_base);
206    clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_muxmode_insert(
207            clk3_out, 0x0);
208    clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_pulludenable_insert(
209            clk3_out, 0x0);
210    clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_pulltypeselect_insert(
211            clk3_out, 0x0);
212    clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_inputenable_insert(
213            clk3_out, 0x0);
214    clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_wakeupenable_insert(
215            clk3_out, 0x0);
216    clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_wakeupevent_insert(
217            clk3_out, 0x0);
218    omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_wr(
219            &sysctrl_padconf_wkup_base, clk3_out);
220
221    printf("  > reset external USB hub and PHY\n");
222
223    /*
224     * Perform a reset on the USB hub i.e. drive the GPIO_1 pin to low
225     * and enable the dataout for the this pin in GPIO
226     */
227
228    uint32_t gpoi_1_oe = omap44xx_gpio_oe_rd(&gpio_1_base)
229            & (~(1UL << HSUSB_HUB_POWER));
230    omap44xx_gpio_oe_wr(&gpio_1_base, gpoi_1_oe);
231
232    omap44xx_gpio_cleardataout_wr(&gpio_1_base, (1UL << HSUSB_HUB_POWER));
233
234    /*
235     * forward the data outline to the USB hub by muxing the
236     * CONTROL_CORE_PAD0_KPD_COL1_PAD1_KPD_COL2 into mode 3 (gpio_1)
237     */
238
239    omap44xx_sysctrl_padconf_core_control_core_pad0_kpd_col1_pad1_kpd_col2_t gpio1_mux;
240    gpio1_mux = omap44xx_sysctrl_padconf_core_control_core_pad0_kpd_col1_pad1_kpd_col2_rd(
241            &sysctrl_padconf_core_base) & 0x0000FFFF;
242    gpio1_mux = omap44xx_sysctrl_padconf_core_control_core_pad0_kpd_col1_pad1_kpd_col2_kpd_col2_muxmode_insert(
243            gpio1_mux, 0x3);
244    omap44xx_sysctrl_padconf_core_control_core_pad0_kpd_col1_pad1_kpd_col2_wr(
245            &sysctrl_padconf_core_base, gpio1_mux);
246
247    /*
248     * Perform a reset on the USB phy i.e. drive GPIO_62 to low
249     *
250     * HSUSB_HUB_RESET: 0 = Hub & Phy held in reset     1 = Normal operation.
251     */
252
253    uint32_t gpoi_2_oe = omap44xx_gpio_oe_rd(&gpio_2_base)
254            & (~(1UL << HSUSB_HUB_RESET));
255    omap44xx_gpio_oe_wr(&gpio_2_base, gpoi_2_oe);
256
257    omap44xx_gpio_cleardataout_wr(&gpio_2_base, (1UL << HSUSB_HUB_RESET));
258
259    /*
260     * forward the data on gpio_62 pin to the output by muxing
261     *  CONTROL_CORE_PAD0_GPMC_WAIT1_PAD1_GPMC_WAIT2 to mode 0x3
262     */
263
264    omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_t gpio62_mux;
265    gpio62_mux = (omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_rd(
266            &sysctrl_padconf_core_base) & 0xFFFF0000);
267    gpio62_mux = omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_gpmc_wait1_muxmode_insert(
268            gpio62_mux, 0x3);
269    omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_wr(
270            &sysctrl_padconf_core_base, gpio62_mux);
271    omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_wr(
272            &sysctrl_padconf_core_base, gpio62_mux);
273
274    /* delay to give the hardware time to reset */
275    barrelfish_usleep(1000000);
276
277    hsusb_init();
278
279    printf("  > enable the external USB hub and PHY\n");
280
281    /* power on the USB subsystem */
282    omap44xx_gpio_setdataout_wr(&gpio_1_base, (1UL << HSUSB_HUB_POWER));
283
284    /* enable the USB HUB */
285    omap44xx_gpio_setdataout_wr(&gpio_2_base, (1UL << HSUSB_HUB_RESET));
286
287    barrelfish_usleep(1000000);
288
289    printf("  > performing softreset on the USB PHY\n");
290
291    omap44xx_ehci_insnreg05_ulpi_t ulpi = omap44xx_ehci_insnreg05_ulpi_default;
292    ulpi = omap44xx_ehci_insnreg05_ulpi_control_insert(ulpi,
293            omap44xx_ehci_CONTROL_1);
294    ulpi = omap44xx_ehci_insnreg05_ulpi_portsel_insert(ulpi,
295            omap44xx_ehci_PORTSEL_1);
296    ulpi = omap44xx_ehci_insnreg05_ulpi_opsel_insert(ulpi,
297            omap44xx_ehci_OPSEL_2);
298    ulpi = omap44xx_ehci_insnreg05_ulpi_regadd_insert(ulpi, 0x5);  //ctrl reg
299    ulpi = omap44xx_ehci_insnreg05_ulpi_rdwrdata_insert(ulpi, (0x1 << 5));
300
301    omap44xx_ehci_insnreg05_ulpi_wr(&ehci_base, ulpi);
302
303    while (omap44xx_ehci_insnreg05_ulpi_control_rdf(&ehci_base)) {
304        barrelfish_usleep(10000);
305    }
306
307    try_again:
308    /* wait till reset is done */
309    ulpi = omap44xx_ehci_insnreg05_ulpi_opsel_insert(ulpi,
310            omap44xx_ehci_OPSEL_3);
311    ulpi = omap44xx_ehci_insnreg05_ulpi_rdwrdata_insert(ulpi, 0x0);
312    omap44xx_ehci_insnreg05_ulpi_wr(&ehci_base, ulpi);
313
314    while (omap44xx_ehci_insnreg05_ulpi_control_rdf(&ehci_base)) {
315        barrelfish_usleep(10000);
316    }
317    if (omap44xx_ehci_insnreg05_ulpi_rdwrdata_rdf(&ehci_base) & (0x1 << 5)) {
318        goto try_again;
319    }
320
321    /* read the debug register */
322    ulpi = omap44xx_ehci_insnreg05_ulpi_regadd_insert(ulpi, 0x15);
323    omap44xx_ehci_insnreg05_ulpi_wr(&ehci_base, ulpi);
324
325    while (omap44xx_ehci_insnreg05_ulpi_control_rdf(&ehci_base)) {
326        barrelfish_usleep(10000);
327    }
328
329    uint8_t line_state = omap44xx_ehci_insnreg05_ulpi_rdwrdata_rdf(&ehci_base) & 0x1;
330    printf("  > ULPI line state = %s\n",
331            line_state ? "Connected" : "Disconnected");
332    assert(line_state);
333
334    printf("done.\n");
335}
336
337static void prcm_init(void)
338{
339    printf("prcm_init()...\n");
340
341    printf("  > CM_SYS_CLKSEL=38.4MHz \n");
342    /*
343     * Set the system clock to 38.4 MHz
344     * CM_SYS_CLKSEL = 0x7
345     */
346
347    omap44xx_ckgen_prm_cm_sys_clksel_wr(&ckgen_base,
348            omap44xx_ckgen_prm_SYS_CLKSEL_7);
349
350    if (!omap44xx_ckgen_prm_cm_sys_clksel_rd(&ckgen_base)) {
351        printf("WARNING: Could not set SYS_CLK\n");
352        return;
353    }
354
355    /* ALTCLKSRC in SRCM*/
356    omap44xx_scrm_altclksrc_t altclk = omap44xx_scrm_altclksrc_default;
357    altclk = omap44xx_scrm_altclksrc_mode_insert(altclk, omap44xx_scrm_MODE_1);
358    altclk = omap44xx_scrm_altclksrc_enable_int_insert(altclk, 0x1);
359    altclk = omap44xx_scrm_altclksrc_enable_ext_insert(altclk, 0x1);
360    omap44xx_scrm_altclksrc_wr(&srcm_base, altclk);
361
362    printf("  > Enabling L4PER interconnect clock\n");
363    /* CM_L4PER_CLKSTCTRL */
364    omap44xx_l4per_cm2_cm_l4per_clkstctrl_clktrctrl_wrf(&l4per_base, 0x2);
365
366    printf("  > Enabling GPIOi clocks\n");
367    /* CM_L4PER_GPIO2_CLKCTRL */
368    omap44xx_l4per_cm2_cm_l4per_gpio2_clkctrl_modulemode_wrf(&l4per_base, 0x1);
369    /* CM_L4PER_GPIO3_CLKCTRL */
370    omap44xx_l4per_cm2_cm_l4per_gpio3_clkctrl_modulemode_wrf(&l4per_base, 0x1);
371    /* CM_L4PER_GPIO4_CLKCTRL */
372    omap44xx_l4per_cm2_cm_l4per_gpio4_clkctrl_modulemode_wrf(&l4per_base, 0x1);
373    /* CM_L4PER_GPIO5_CLKCTRL */
374    omap44xx_l4per_cm2_cm_l4per_gpio5_clkctrl_modulemode_wrf(&l4per_base, 0x1);
375    /* CM_L4PER_GPIO6_CLKCTRL */
376    omap44xx_l4per_cm2_cm_l4per_gpio6_clkctrl_modulemode_wrf(&l4per_base, 0x1);
377    /* CM_L4PER_HDQ1W_CLKCTRL */
378    omap44xx_l4per_cm2_cm_l4per_hdq1w_clkctrl_modulemode_wrf(&l4per_base, 0x2);
379
380    printf("  > Enabling L3INIT USB clocks\n");
381    /* CM_L3INIT_HSI_CLKCTRL */
382    omap44xx_l3init_cm2_cm_l3init_hsi_clkctrl_modulemode_wrf(&l3init_base, 0x1);
383
384    /* CM_L3INIT_HSUSBHOST_CLKCTRL */
385    omap44xx_l3init_cm2_cm_l3init_hsusbhost_clkctrl_t hsusb_cm = 0x0;
386    hsusb_cm = omap44xx_l3init_cm2_cm_l3init_hsusbhost_clkctrl_clksel_utmi_p1_insert(
387            hsusb_cm, 0x3);
388    hsusb_cm = omap44xx_l3init_cm2_cm_l3init_hsusbhost_clkctrl_modulemode_insert(
389            hsusb_cm, 0x2);
390    hsusb_cm |= 0xFF00;  // all clocks
391    omap44xx_l3init_cm2_cm_l3init_hsusbhost_clkctrl_wr(&l3init_base, hsusb_cm);
392
393    /* CM_L3INIT_HSUSBOTG_CLKCTRL */
394    omap44xx_l3init_cm2_cm_l3init_hsusbotg_clkctrl_modulemode_wrf(&l3init_base,
395            0x1);
396
397    /* CM_L3INIT_HSUSBTLL_CLKCTRL */
398    omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_t usbtll_cm = 0x0;
399    usbtll_cm = omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_modulemode_insert(
400            usbtll_cm, 0x1);
401    usbtll_cm = omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_optfclken_usb_ch0_clk_insert(
402            usbtll_cm, 0x1);
403    usbtll_cm = omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_optfclken_usb_ch1_clk_insert(
404            usbtll_cm, 0x1);
405    omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_wr(&l3init_base, usbtll_cm);
406
407    /* CM_L3INIT_FSUSB_CLKCTRL */
408    omap44xx_l3init_cm2_cm_l3init_fsusb_clkctrl_modulemode_wrf(&l3init_base,
409            0x2);
410    /* CM_L3INIT_USBPHY_CLKCTRL */
411    omap44xx_l3init_cm2_cm_l3init_usbphy_clkctrl_wr(&l3init_base, 0x301);
412
413    printf("done.\n");
414}
415
416static void set_muxconf_regs(void)
417{
418    printf("set_muxconf_regs()...");
419
420    /* CONTROL_PADCONF_CORE_SYSCONFIG */
421    omap44xx_sysctrl_padconf_core_control_padconf_core_sysconfig_ip_sysconfig_idlemode_wrf(
422            &sysctrl_padconf_core_base, 0x1);
423
424    /* CONTROL_PADCONF_WKUP_SYSCONFIG */
425    omap44xx_sysctrl_padconf_wkup_control_padconf_wkup_sysconfig_ip_sysconfig_idlemode_wrf(
426            &sysctrl_padconf_wkup_base, 0x1);
427
428    /* USBB1_CLK */
429    omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_t ulpitll;
430    ulpitll = omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_rd(
431            &sysctrl_padconf_core_base) & 0x0000FFFF;
432    ulpitll = omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_usbb1_ulpitll_clk_inputenable_insert(
433            ulpitll, 0x1);
434    ulpitll = omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_usbb1_ulpitll_clk_pulludenable_insert(
435            ulpitll, 0x1);
436    ulpitll = omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_usbb1_ulpitll_clk_muxmode_insert(
437            ulpitll, 0x4);
438    omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_wr(
439            &sysctrl_padconf_core_base, ulpitll);
440
441    /* USBB1_STP / USBB1_DIR */
442    omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_t usb_dir = 0x0;
443    usb_dir = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_usbb1_ulpitll_stp_muxmode_insert(
444            usb_dir, 0x4);
445    usb_dir = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_usbb1_ulpitll_dir_muxmode_insert(
446            usb_dir, 0x4);
447    usb_dir = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_usbb1_ulpitll_dir_inputenable_insert(
448            usb_dir, 0x1);
449    usb_dir = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_usbb1_ulpitll_dir_pulludenable_insert(
450            usb_dir, 0x1);
451    omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_wr(
452            &sysctrl_padconf_core_base, usb_dir);
453
454    /* this values are used for all the 8 data lines */
455    uint32_t usb_dat = 0x0;
456    usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_dat0_muxmode_insert(
457            usb_dat, 0x4);
458    usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_nxt_muxmode_insert(
459            usb_dat, 0x4);
460    usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_dat0_inputenable_insert(
461            usb_dat, 0x1);
462    usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_nxt_inputenable_insert(
463            usb_dat, 0x1);
464    usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_dat0_pulludenable_insert(
465            usb_dat, 0x1);
466    usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_nxt_pulludenable_insert(
467            usb_dat, 0x1);
468
469    /* USBB1_DAT0 / USBB1_NXT */
470    omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_wr(
471            &sysctrl_padconf_core_base, usb_dat);
472
473    /* USBB1_DAT1 / USBB1_DAT2 */
474    omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat1_pad1_usbb1_ulpitll_dat2_wr(
475            &sysctrl_padconf_core_base, usb_dat);
476
477    /* USBB1_DAT3 / USBB1_DAT4 */
478    omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat3_pad1_usbb1_ulpitll_dat4_wr(
479            &sysctrl_padconf_core_base, usb_dat);
480
481    /* USBB1_DAT5 / USBB1_DAT6 */
482    omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat5_pad1_usbb1_ulpitll_dat6_wr(
483            &sysctrl_padconf_core_base, usb_dat);
484
485    /* USBB1_DAT7 */
486    omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_t usb_dat7;
487    usb_dat7 = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_rd(
488            &sysctrl_padconf_core_base) & 0xFFFF0000;
489    usb_dat7 = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_usbb1_ulpitll_dat7_muxmode_insert(
490            usb_dat7, 0x4);
491    usb_dat7 = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_usbb1_ulpitll_dat7_pulludenable_insert(
492            usb_dat7, 0x1);
493    usb_dat7 = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_usbb1_ulpitll_dat7_inputenable_insert(
494            usb_dat7, 0x1);
495    omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_wr(
496            &sysctrl_padconf_core_base, usb_dat7);
497
498    printf("done\n");
499}
500
501/**
502 * Entry point called from boot.S for bootstrap processor.
503 * if is_bsp == true, then pointer points to multiboot_info
504 * else pointer points to a global struct
505 */
506static errval_t usb_init(void)
507{
508    errval_t err;
509    printf("-------------------------\nUSB Host initialization\n");
510    lvaddr_t base;
511    err = map_device_register(OMAP44XX_MAP_L4_CFG_HSUSBHOST, OMAP44XX_MAP_L4_CFG_HSUSBHOST_SIZE, &base);
512    if (err_is_fail(err)) {
513        return err;
514    }
515    omap44xx_hsusbhost_initialize(&hsusbhost_base, (mackerel_addr_t) base);
516    omap44xx_ehci_initialize(&ehci_base, (mackerel_addr_t) base + 0xC00);
517
518    err = map_device_register(OMAP44XX_MAP_L4_CFG_HSUSBTLL, OMAP44XX_MAP_L4_CFG_HSUSBTLL_SIZE, &base);
519    if (err_is_fail(err)) {
520        return err;
521    }
522    omap44xx_usbtllhs_config_initialize(&usbtllhs_config_base, (mackerel_addr_t) base);
523
524
525    err = map_device_register(OMAP44XX_MAP_L4_WKUP_SRCM, OMAP44XX_MAP_L4_WKUP_SRCM_SIZE, &base);
526    if (err_is_fail(err)) {
527        return err;
528    }
529    omap44xx_scrm_initialize(&srcm_base, (mackerel_addr_t) base);
530
531    err = map_device_register(OMAP44XX_MAP_L4_WKUP_SYSCTRL_PADCONF_WKUP, OMAP44XX_MAP_L4_WKUP_SYSCTRL_PADCONF_WKUP_SIZE, &base);
532    if (err_is_fail(err)) {
533        return err;
534    }
535    omap44xx_sysctrl_padconf_wkup_initialize(&sysctrl_padconf_wkup_base, (mackerel_addr_t) base);
536
537    err = map_device_register(OMAP44XX_MAP_L4_CFG_SYSCTRL_PADCONF_CORE, OMAP44XX_MAP_L4_CFG_SYSCTRL_PADCONF_CORE_SIZE, &base);
538    if (err_is_fail(err)) {
539        return err;
540    }
541    omap44xx_sysctrl_padconf_core_initialize(&sysctrl_padconf_core_base, (mackerel_addr_t) base);
542
543    err = map_device_register(OMAP44XX_MAP_L4_WKUP_GPIO1, OMAP44XX_MAP_L4_WKUP_GPIO1_SIZE, &base);
544    if (err_is_fail(err)) {
545        return err;
546    }
547    omap44xx_gpio_initialize(&gpio_1_base, (mackerel_addr_t) base);
548
549    err = map_device_register(OMAP44XX_MAP_L4_PER_GPIO2, OMAP44XX_MAP_L4_PER_GPIO2_SIZE, &base);
550    if (err_is_fail(err)) {
551        return err;
552    }
553    omap44xx_gpio_initialize(&gpio_2_base, (mackerel_addr_t) base);
554
555    err = map_device_register(OMAP44XX_MAP_L4_WKUP_PRM, OMAP44XX_MAP_L4_WKUP_PRM_SIZE, &base);
556    if (err_is_fail(err)) {
557        return err;
558    }
559    omap44xx_ckgen_prm_initialize(&ckgen_base, (mackerel_addr_t) base + 0x100);
560
561    err = map_device_register(OMAP44XX_MAP_L4_CFG_CM2, OMAP44XX_MAP_L4_CFG_CM2_SIZE, &base);
562    if (err_is_fail(err)) {
563        return err;
564    }
565    omap44xx_l4per_cm2_initialize(&l4per_base, (mackerel_addr_t) base + 0x1400);
566    omap44xx_l3init_cm2_initialize(&l3init_base, (mackerel_addr_t) base + 0x1300);
567
568    prcm_init();
569    set_muxconf_regs();
570    usb_power_on();
571    printf("-------------------------\n");
572
573    return SYS_ERR_OK;
574}
575
576/**
577 * \brief this is a quick check function if everything is all right
578 *
579 * NOTE: there is just one specific setting possible on the PandaBoard
580 *       EHCI controller, with the specific capability and the specific offset
581 *       This function checks if these values match to ensure functionality
582 *       If you change something with the startup of the USB manager domain
583 *       you may need to change the values in this function!
584 */
585usb_error_t platform_checkup(uintptr_t base, int argc, char *argv[])
586{
587    USB_DEBUG("performing pandaboard integrity check.\n");
588
589    errval_t err = usb_init();
590    if (err_is_fail(err)) {
591        USER_PANIC_ERR(err, "USB initialization failed\n");
592    }
593
594    /* checking the host controller type */
595    if (strcmp(argv[0], "ehci")) {
596        debug_printf("wrong host controller type: %s\n", argv[0]);
597        return (USB_ERR_INVAL);
598    }
599
600    /* checking the memory offset */
601    if (strtoul(argv[1], NULL, 10) != ((uint32_t) USB_CAPABILITY_OFFSET)) {
602        debug_printf("wrong offset!: %x (%s)\n", strtoul(argv[1], NULL, 10),
603                argv[1]);
604        return (USB_ERR_INVAL);
605    }
606
607    /* checking the IRQ number */
608    if (strtoul(argv[2], NULL, 10) != USB_ARM_EHCI_IRQ) {
609        debug_printf("wrong interrupt number: %s, %x", argv[2],
610                strtoul(argv[2], NULL, 10));
611        return (USB_ERR_INVAL);
612    }
613
614    /*
615     * here we read some values from the ULPI register of the PandaBoards
616     * additional ULPI interface on the EHCI controller.
617     *
618     * The request are forwarded to the external ULPI receiver on the
619     * PandaBoard.
620     *
621     * NOTE: Not every EHCI controller has those register!
622     */
623
624    uintptr_t tmp = USB_CAPABILITY_OFFSET + (uintptr_t) base;
625    volatile uint32_t *ulpi_debug_reg = (volatile uint32_t*) (tmp + 0x00A4);
626    debug_printf("address of ehci base = %p\n", (void *)tmp);
627    debug_printf("address of ulpi debug reg = %p\n", ulpi_debug_reg);
628    /*
629     * This request reads the debug register of the ULPI receiver. The values
630     * returned are the line state. If the returned value is 0x1 this means
631     * there is connection i.e. the USB hub on the PandaBoard is reachable.
632     */
633
634    printf("check whether USB hub is reachable... ");
635    *ulpi_debug_reg = (uint32_t) ((0x15 << 16)
636            | (0x3 << 22) | (0x1 << 24) | (0x1 << 31));
637
638    /* wait till the request is done */
639    while ((*ulpi_debug_reg) & (1UL << 31)) {
640        thread_yield();
641    }
642
643    // XXX: reset register here?
644    ulpi_debug_reg = (volatile uint32_t*) (tmp + 0x00A4);
645    /* compare the result */
646    if (!((*ulpi_debug_reg) & 0x1)) {
647        return (USB_ERR_INVAL);
648    }
649
650    printf("ok\nCheck vendor ID of ULPI receiver... ");
651    /*
652     * This request reads out the low part of the vendor id from the ULPI
653     * receiver on the PandaBoard. This should be 0x24.
654     *
655     * XXX: Assuming that all the Pandaboards have the same ULPI receiver
656     */
657    *ulpi_debug_reg = (uint32_t) ((0x00 << 16)
658            | (0x3 << 22) | (0x1 << 24) | (0x1 << 31));
659
660    /* wait till request is done */
661    while ((*ulpi_debug_reg) & (1 << 31)) {
662    }
663
664    /* compare the values */
665    if (0x24 != ((*ulpi_debug_reg) & 0xFF)) {
666        return (USB_ERR_INVAL);
667    }
668    printf("ok\n");
669
670    return (USB_ERR_OK);
671}
672