2 * Copyright (c) 2009-2013, ETH Zurich. All rights reserved.
4 * This file is distributed under the terms in the attached LICENSE file.
5 * If you do not find this file, copies can be found by writing to:
6 * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich,
12 * \brief CPU driver init code for the OMAP44xx series SoCs.
13 * interface found in /kernel/include/serial.h
19 #include <exceptions.h>
22 #include <paging_kernel_arch.h>
23 #include <phys_mmap.h>
28 #include <getopt/getopt.h>
31 #include <barrelfish_kpi/arm_core_data.h>
32 #include <startup_arch.h>
33 #include <kernel_multiboot.h>
35 #include <arch/armv7/start_aps.h> // AP_WAIT_*, AUX_CORE_BOOT_* and friends
36 #include <cortexm3_heteropanda.h>
40 #include <omap44xx_map.h>
41 #include <dev/omap/omap44xx_id_dev.h>
42 #include <dev/omap/omap44xx_emif_dev.h>
43 #include <dev/omap/omap44xx_gpio_dev.h>
44 #include <dev/omap/omap44xx_hsusbhost_dev.h>
45 #include <dev/omap/omap44xx_usbtllhs_config_dev.h>
46 #include <dev/omap/omap44xx_scrm_dev.h>
47 #include <dev/omap/omap44xx_sysctrl_padconf_wkup_dev.h>
48 #include <dev/omap/omap44xx_sysctrl_padconf_core_dev.h>
49 #include <dev/omap/omap44xx_ehci_dev.h>
50 #include <dev/omap/omap44xx_ckgen_prm_dev.h>
51 #include <dev/omap/omap44xx_l4per_cm2_dev.h>
52 #include <dev/omap/omap44xx_l3init_cm2_dev.h>
54 /// Round up n to the next multiple of size
55 #define ROUND_UP(n, size) ((((n) + (size) - 1)) & (~((size) - 1)))
58 * Used to store the address of global struct passed during boot across kernel
61 //static uint32_t addr_global;
63 * \brief Kernel stack.
65 * This is the one and only kernel stack for a kernel instance.
67 uintptr_t kernel_stack[KERNEL_STACK_SIZE / sizeof(uintptr_t)] __attribute__ ((aligned(8)));
69 #define MIN(a,b) ((a) < (b) ? (a) : (b))
70 #define MAX(a,b) ((a) > (b) ? (a) : (b))
71 #define CONSTRAIN(x, a, b) MIN(MAX(x, a), b)
74 // Kernel command line variables and binding options
77 static int timeslice = 5; //interval in ms in which the scheduler gets called
79 static struct cmdarg cmdargs[] = {
84 .uinteger = &serial_console_port
91 .uinteger = &serial_debug_port
98 .integer = &kernel_loglevel
105 .integer = &kernel_log_subsystem_mask
112 .integer = ×lice
124 static inline void __attribute__ ((always_inline))
125 relocate_stack(lvaddr_t offset)
128 "add sp, sp, %[offset]\n\t" ::[offset] "r" (offset)
132 static inline void __attribute__ ((always_inline))
133 relocate_got_base(lvaddr_t offset)
136 "add r10, r10, %[offset]\n\t" ::[offset] "r" (offset)
141 static void enable_cycle_counter_user_access(void)
143 /* enable user-mode access to the performance counter*/
144 __asm volatile ("mcr p15, 0, %0, C9, C14, 0\n\t" :: "r"(1));
146 /* disable counter overflow interrupts (just in case)*/
147 __asm volatile ("mcr p15, 0, %0, C9, C14, 2\n\t" :: "r"(0x8000000f));
151 extern void paging_map_device_section(uintptr_t ttbase, lvaddr_t va,
155 * Create initial (temporary) page tables.
157 * We use 1MB (ARM_L1_SECTION_BYTES) pages (sections) with a single-level table.
158 * This allows 1MB*4k (ARM_L1_MAX_ENTRIES) = 4G per pagetable.
160 * Hardware details can be found in:
161 * ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition
162 * B3: Virtual Memory System Architecture (VMSA)
164 static void paging_init(void)
168 * l1_low for addresses < 2GB (translated by TTBR0)
169 * l1_high for addresses >= 2GB (translated by TTBR1)
171 * XXX: We reserve double the space needed to be able to align the
172 * pagetable to 16K after relocation.
174 static union arm_l1_entry l1_low[2*ARM_L1_MAX_ENTRIES];
175 static union arm_l1_entry l1_high[2*ARM_L1_MAX_ENTRIES];
178 * TTBCR: Translation Table Base Control register.
179 * TTBCR.N is bits[2:0]
180 * In a TLB miss TTBCR.N determines whether TTBR0 or TTBR1 is used as the
181 * base address for the translation table walk in memory:
182 * N == 0 -> always use TTBR0
183 * N > 0 -> if VA[31:32-N] > 0 use TTBR1 else use TTBR0
185 * TTBR0 is typically used for processes-specific addresses
186 * TTBR1 is typically used for OS addresses that do not change on context
189 * set TTBCR.N = 1 to use TTBR1 for VAs >= MEMORY_OFFSET (=2GB)
192 uint32_t ttbcr = cp15_read_ttbcr();
193 ttbcr = (ttbcr & ~7) | TTBCR_N;
194 cp15_write_ttbcr(ttbcr);
195 STATIC_ASSERT(1UL<<(32-TTBCR_N) == MEMORY_OFFSET, "");
199 * in omap44xx, physical memory (PHYS_MEMORY_START) is the same with the the
200 * offset of mapped physical memory within virtual address space
201 * (PHYS_MEMORY_START), so we just create identity mappings.
203 STATIC_ASSERT(MEMORY_OFFSET == PHYS_MEMORY_START, "");
204 uintptr_t l1_low_aligned = ROUND_UP((uintptr_t)l1_low, ARM_L1_ALIGN);
205 uintptr_t l1_high_aligned = ROUND_UP((uintptr_t)l1_high, ARM_L1_ALIGN);
206 lvaddr_t vbase = MEMORY_OFFSET, base = 0;
207 for (size_t i=0; i < ARM_L1_MAX_ENTRIES/2; i++) {
208 paging_map_device_section(l1_low_aligned, base, base);
209 paging_map_device_section(l1_high_aligned, vbase, vbase);
210 base += ARM_L1_SECTION_BYTES;
211 vbase += ARM_L1_SECTION_BYTES;
214 // Activate new page tables
215 cp15_write_ttbr1(l1_high_aligned);
216 cp15_write_ttbr0(l1_low_aligned);
219 void kernel_startup_early(void)
222 assert(glbl_core_data != NULL);
223 cmdline = MBADDR_ASSTRING(glbl_core_data->cmdline);
224 parse_commandline(cmdline, cmdargs);
225 timeslice = CONSTRAIN(timeslice, 1, 20);
228 #define KERNEL_DEBUG_USB 0
230 /* mackerel base addresses for USB initialization */
231 #define OMAP44XX_USBTLLHS_CONFIG 0x4A062000
232 #define OMAP44XX_HSUSBHOST 0x4A064000
233 #define OMAP44XX_SCRM 0x4A30A000
234 #define OMAP44XX_SYSCTRL_PADCONF_WKUP 0x4A31E000
235 #define OMAP44XX_SYSCTRL_PADCONF_CORE 0x4A100000
236 #define OMAP44XX_EHCI 0x4A064C00
237 #define OMAP44XX_CKGEN_PRM 0x4A306100
238 #define OMAP44XX_L4PER_CM2 0x4A009400
239 #define OMAP44XX_L3INIT_CM2 0x4A009300
241 /* mackerel bases for USB initialization */
242 static omap44xx_hsusbhost_t hsusbhost_base;
243 static omap44xx_usbtllhs_config_t usbtllhs_config_base;
244 static omap44xx_scrm_t srcm_base;
245 static omap44xx_sysctrl_padconf_wkup_t sysctrl_padconf_wkup_base;
246 static omap44xx_sysctrl_padconf_core_t sysctrl_padconf_core_base;
247 static omap44xx_gpio_t gpio_1_base;
248 static omap44xx_gpio_t gpio_2_base;
249 static omap44xx_ehci_t ehci_base;
250 static omap44xx_ckgen_prm_t ckgen_base;
251 static omap44xx_l4per_cm2_t l4per_base;
252 static omap44xx_l3init_cm2_t l3init_base;
255 * initialize the USB functionality of the pandaboard
257 static void hsusb_init(void)
260 printf(" > hsusb_init()...\n");
263 * Global Initialization of the OMAPP44xx USB Sub System
265 printf(" > > USB TTL reset...");
269 * USBTLL_SYSCONFIG = 0x2
271 omap44xx_usbtllhs_config_usbtll_sysconfig_softreset_wrf(
272 &usbtllhs_config_base, 0x1);
275 * wait till reset is done
277 while (!omap44xx_usbtllhs_config_usbtll_sysstatus_resetdone_rdf(
278 &usbtllhs_config_base))
283 * - Setting ENAWAKEUP
284 * - Setting SIDLEMODE
285 * - Setting CLOCKACTIVITY
287 omap44xx_usbtllhs_config_usbtll_sysconfig_t sysconf = 0x0;
288 sysconf = omap44xx_usbtllhs_config_usbtll_sysconfig_clockactivity_insert(
290 sysconf = omap44xx_usbtllhs_config_usbtll_sysconfig_enawakeup_insert(
292 sysconf = omap44xx_usbtllhs_config_usbtll_sysconfig_sidlemode_insert(
294 omap44xx_usbtllhs_config_usbtll_sysconfig_wr(&usbtllhs_config_base,
303 omap44xx_usbtllhs_config_usbtll_irqenable_t irqena = omap44xx_usbtllhs_config_usbtll_irqenable_default;
304 irqena = omap44xx_usbtllhs_config_usbtll_irqenable_fclk_start_en_insert(
306 irqena = omap44xx_usbtllhs_config_usbtll_irqenable_fclk_end_en_insert(
308 irqena = omap44xx_usbtllhs_config_usbtll_irqenable_access_error_en_insert(
310 omap44xx_usbtllhs_config_usbtll_irqenable_wr(&usbtllhs_config_base, irqena);
312 printf(" > > USB host controller reset...");
315 * per form a reset on the USB host controller module
316 * this resets both EHCI and OCHI controllers
318 * UHH_SYSCONFIG = 0x1
320 omap44xx_hsusbhost_uhh_sysconfig_softreset_wrf(&hsusbhost_base, 0x1);
323 * wait till reset is done
324 * UHH_SYSSTATUS = 0x6
326 omap44xx_hsusbhost_uhh_sysstatus_t uhh_sysstat;
330 uhh_sysstat = omap44xx_hsusbhost_uhh_sysstatus_rd(&hsusbhost_base);
331 ehci_done = omap44xx_hsusbhost_uhh_sysstatus_ehci_resetdone_extract(
333 ohci_done = omap44xx_hsusbhost_uhh_sysstatus_ohci_resetdone_extract(
335 } while (!(ehci_done & ohci_done));
337 /* enable some USB host features
342 omap44xx_hsusbhost_uhh_sysconfig_standbymode_wrf(&hsusbhost_base, 0x1);
343 omap44xx_hsusbhost_uhh_sysconfig_idlemode_wrf(&hsusbhost_base, 0x1);
347 printf(" > > Setting USB host configuration values...");
350 * setting the host configuration to external PHY and enable
351 * the burst types, app start clk
357 // *((volatile uint32_t*) (0x4A064040)) =
358 // (uint32_t) ((0x7 << 2) | (0x1 << 31));
359 omap44xx_hsusbhost_uhh_hostconfig_t hcfg = omap44xx_hsusbhost_uhh_hostconfig_default;
360 hcfg = omap44xx_hsusbhost_uhh_hostconfig_app_start_clk_insert(hcfg, 0x1);
361 hcfg = omap44xx_hsusbhost_uhh_hostconfig_ena_incr4_insert(hcfg, 0x1);
362 hcfg = omap44xx_hsusbhost_uhh_hostconfig_ena_incr8_insert(hcfg, 0x1);
363 hcfg = omap44xx_hsusbhost_uhh_hostconfig_ena_incr16_insert(hcfg, 0x1);
364 omap44xx_hsusbhost_uhh_hostconfig_wr(&hsusbhost_base, hcfg);
368 printf(" > done.\n");
371 // GPIO numbers for enabling the USB hub on the pandaboard
372 #define HSUSB_HUB_POWER 1
373 #define HSUSB_HUB_RESET 30
377 * Initialize the high speed usb hub on the pandaboard
379 static void usb_power_on(void)
381 printf("usb_power_on()... \n");
383 printf(" > forward the AUXCLK3 to GPIO_WK31\n");
385 * the USB hub needs the FREF_CLK3_OUT to be 19.2 MHz and that this
386 * clock goes to the GPIO_WK31 out.
387 * Assume that the sys clock is 38.4 MHz so we use a divider of 2
389 * Bit 8: is the enable bit
390 * Bit 16: is the divider bit (here for two)
393 omap44xx_scrm_auxclk3_t auxclk3 = omap44xx_scrm_auxclk3_default;
394 auxclk3 = omap44xx_scrm_auxclk3_enable_insert(auxclk3,
395 omap44xx_scrm_ENABLE_EXT_1);
396 auxclk3 = omap44xx_scrm_auxclk3_clkdiv_insert(auxclk3,
397 omap44xx_scrm_MODE_1);
398 omap44xx_scrm_auxclk3_wr(&srcm_base, auxclk3);
401 * Forward the clock to the GPIO_WK31 pin
402 * - muxmode = fref_clk3_out (0x0)
403 * - no pullup/down (0x0)
404 * - no input buffer (0x0)
407 omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_t clk3_out;
408 clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_rd(
409 &sysctrl_padconf_wkup_base);
410 clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_muxmode_insert(
412 clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_pulludenable_insert(
414 clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_pulltypeselect_insert(
416 clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_inputenable_insert(
418 clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_wakeupenable_insert(
420 clk3_out = omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_fref_clk3_out_wakeupevent_insert(
422 omap44xx_sysctrl_padconf_wkup_control_wkup_pad0_fref_clk3_out_pad1_fref_clk4_req_wr(
423 &sysctrl_padconf_wkup_base, clk3_out);
425 printf(" > reset external USB hub and PHY\n");
428 * Perform a reset on the USB hub i.e. drive the GPIO_1 pin to low
429 * and enable the dataout for the this pin in GPIO
432 uint32_t gpoi_1_oe = omap44xx_gpio_oe_rd(&gpio_1_base)
433 & (~(1UL << HSUSB_HUB_POWER));
434 omap44xx_gpio_oe_wr(&gpio_1_base, gpoi_1_oe);
436 omap44xx_gpio_cleardataout_wr(&gpio_1_base, (1UL << HSUSB_HUB_POWER));
439 * forward the data outline to the USB hub by muxing the
440 * CONTROL_CORE_PAD0_KPD_COL1_PAD1_KPD_COL2 into mode 3 (gpio_1)
443 omap44xx_sysctrl_padconf_core_control_core_pad0_kpd_col1_pad1_kpd_col2_t gpio1_mux;
444 gpio1_mux = omap44xx_sysctrl_padconf_core_control_core_pad0_kpd_col1_pad1_kpd_col2_rd(
445 &sysctrl_padconf_core_base) & 0x0000FFFF;
446 gpio1_mux = omap44xx_sysctrl_padconf_core_control_core_pad0_kpd_col1_pad1_kpd_col2_kpd_col2_muxmode_insert(
448 omap44xx_sysctrl_padconf_core_control_core_pad0_kpd_col1_pad1_kpd_col2_wr(
449 &sysctrl_padconf_core_base, gpio1_mux);
452 * Perform a reset on the USB phy i.e. drive GPIO_62 to low
454 * HSUSB_HUB_RESET: 0 = Hub & Phy held in reset 1 = Normal operation.
457 uint32_t gpoi_2_oe = omap44xx_gpio_oe_rd(&gpio_2_base)
458 & (~(1UL << HSUSB_HUB_RESET));
459 omap44xx_gpio_oe_wr(&gpio_2_base, gpoi_2_oe);
461 omap44xx_gpio_cleardataout_wr(&gpio_2_base, (1UL << HSUSB_HUB_RESET));
464 * forward the data on gpio_62 pin to the output by muxing
465 * CONTROL_CORE_PAD0_GPMC_WAIT1_PAD1_GPMC_WAIT2 to mode 0x3
468 omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_t gpio62_mux;
469 gpio62_mux = (omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_rd(
470 &sysctrl_padconf_core_base) & 0xFFFF0000);
471 gpio62_mux = omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_gpmc_wait1_muxmode_insert(
473 omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_wr(
474 &sysctrl_padconf_core_base, gpio62_mux);
475 omap44xx_sysctrl_padconf_core_control_core_pad0_gpmc_wait1_pad1_gpmc_wait2_wr(
476 &sysctrl_padconf_core_base, gpio62_mux);
478 /* delay to give the hardware time to reset TODO: propper delay*/
479 for (int j = 0; j < 2000; j++) {
486 printf(" > enable the external USB hub and PHY\n");
488 /* power on the USB subsystem */
489 omap44xx_gpio_setdataout_wr(&gpio_1_base, (1UL << HSUSB_HUB_POWER));
491 /* enable the USB HUB */
492 omap44xx_gpio_setdataout_wr(&gpio_2_base, (1UL << HSUSB_HUB_RESET));
494 for (int j = 0; j < 2000; j++) {
499 printf(" > performing softreset on the USB PHY\n");
501 omap44xx_ehci_insnreg05_ulpi_t ulpi = omap44xx_ehci_insnreg05_ulpi_default;
502 ulpi = omap44xx_ehci_insnreg05_ulpi_control_insert(ulpi,
503 omap44xx_ehci_CONTROL_1);
504 ulpi = omap44xx_ehci_insnreg05_ulpi_portsel_insert(ulpi,
505 omap44xx_ehci_PORTSEL_1);
506 ulpi = omap44xx_ehci_insnreg05_ulpi_opsel_insert(ulpi,
507 omap44xx_ehci_OPSEL_2);
508 ulpi = omap44xx_ehci_insnreg05_ulpi_regadd_insert(ulpi, 0x5); //ctrl reg
509 ulpi = omap44xx_ehci_insnreg05_ulpi_rdwrdata_insert(ulpi, (0x1 << 5));
511 omap44xx_ehci_insnreg05_ulpi_wr(&ehci_base, ulpi);
513 while (omap44xx_ehci_insnreg05_ulpi_control_rdf(&ehci_base)) {
518 /* wait till reset is done */
519 ulpi = omap44xx_ehci_insnreg05_ulpi_opsel_insert(ulpi,
520 omap44xx_ehci_OPSEL_3);
521 ulpi = omap44xx_ehci_insnreg05_ulpi_rdwrdata_insert(ulpi, 0x0);
522 omap44xx_ehci_insnreg05_ulpi_wr(&ehci_base, ulpi);
524 while (omap44xx_ehci_insnreg05_ulpi_control_rdf(&ehci_base)) {
527 if (omap44xx_ehci_insnreg05_ulpi_rdwrdata_rdf(&ehci_base) & (0x1 << 5)) {
531 /* read the debug register */
532 ulpi = omap44xx_ehci_insnreg05_ulpi_regadd_insert(ulpi, 0x15);
533 omap44xx_ehci_insnreg05_ulpi_wr(&ehci_base, ulpi);
535 while (omap44xx_ehci_insnreg05_ulpi_control_rdf(&ehci_base)) {
539 uint8_t line_state = omap44xx_ehci_insnreg05_ulpi_rdwrdata_rdf(&ehci_base) & 0x1;
540 printf(" > ULPI line state = %s\n",
541 line_state ? "Connected" : "Disconnected");
547 static void prcm_init(void)
549 printf("prcm_init()...\n");
551 printf(" > CM_SYS_CLKSEL=38.4MHz \n");
553 * Set the system clock to 38.4 MHz
554 * CM_SYS_CLKSEL = 0x7
557 omap44xx_ckgen_prm_cm_sys_clksel_wr(&ckgen_base,
558 omap44xx_ckgen_prm_SYS_CLKSEL_7);
560 if (!omap44xx_ckgen_prm_cm_sys_clksel_rd(&ckgen_base)) {
561 printf("WARNING: Could not set SYS_CLK\n");
565 /* ALTCLKSRC in SRCM*/
566 omap44xx_scrm_altclksrc_t altclk = omap44xx_scrm_altclksrc_default;
567 altclk = omap44xx_scrm_altclksrc_mode_insert(altclk, omap44xx_scrm_MODE_1);
568 altclk = omap44xx_scrm_altclksrc_enable_int_insert(altclk, 0x1);
569 altclk = omap44xx_scrm_altclksrc_enable_ext_insert(altclk, 0x1);
570 omap44xx_scrm_altclksrc_wr(&srcm_base, altclk);
572 printf(" > Enabling L4PER interconnect clock\n");
573 /* CM_L4PER_CLKSTCTRL */
574 omap44xx_l4per_cm2_cm_l4per_clkstctrl_clktrctrl_wrf(&l4per_base, 0x2);
576 printf(" > Enabling GPIOi clocks\n");
577 /* CM_L4PER_GPIO2_CLKCTRL */
578 omap44xx_l4per_cm2_cm_l4per_gpio2_clkctrl_modulemode_wrf(&l4per_base, 0x1);
579 /* CM_L4PER_GPIO3_CLKCTRL */
580 omap44xx_l4per_cm2_cm_l4per_gpio3_clkctrl_modulemode_wrf(&l4per_base, 0x1);
581 /* CM_L4PER_GPIO4_CLKCTRL */
582 omap44xx_l4per_cm2_cm_l4per_gpio4_clkctrl_modulemode_wrf(&l4per_base, 0x1);
583 /* CM_L4PER_GPIO5_CLKCTRL */
584 omap44xx_l4per_cm2_cm_l4per_gpio5_clkctrl_modulemode_wrf(&l4per_base, 0x1);
585 /* CM_L4PER_GPIO6_CLKCTRL */
586 omap44xx_l4per_cm2_cm_l4per_gpio6_clkctrl_modulemode_wrf(&l4per_base, 0x1);
587 /* CM_L4PER_HDQ1W_CLKCTRL */
588 omap44xx_l4per_cm2_cm_l4per_hdq1w_clkctrl_modulemode_wrf(&l4per_base, 0x2);
590 printf(" > Enabling L3INIT USB clocks\n");
591 /* CM_L3INIT_HSI_CLKCTRL */
592 omap44xx_l3init_cm2_cm_l3init_hsi_clkctrl_modulemode_wrf(&l3init_base, 0x1);
594 /* CM_L3INIT_HSUSBHOST_CLKCTRL */
595 omap44xx_l3init_cm2_cm_l3init_hsusbhost_clkctrl_t hsusb_cm = 0x0;
596 hsusb_cm = omap44xx_l3init_cm2_cm_l3init_hsusbhost_clkctrl_clksel_utmi_p1_insert(
598 hsusb_cm = omap44xx_l3init_cm2_cm_l3init_hsusbhost_clkctrl_modulemode_insert(
600 hsusb_cm |= 0xFF00; // all clocks
601 omap44xx_l3init_cm2_cm_l3init_hsusbhost_clkctrl_wr(&l3init_base, hsusb_cm);
603 /* CM_L3INIT_HSUSBOTG_CLKCTRL */
604 omap44xx_l3init_cm2_cm_l3init_hsusbotg_clkctrl_modulemode_wrf(&l3init_base,
607 /* CM_L3INIT_HSUSBTLL_CLKCTRL */
608 omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_t usbtll_cm = 0x0;
609 usbtll_cm = omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_modulemode_insert(
611 usbtll_cm = omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_optfclken_usb_ch0_clk_insert(
613 usbtll_cm = omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_optfclken_usb_ch1_clk_insert(
615 omap44xx_l3init_cm2_cm_l3init_hsusbtll_clkctrl_wr(&l3init_base, usbtll_cm);
617 /* CM_L3INIT_FSUSB_CLKCTRL */
618 omap44xx_l3init_cm2_cm_l3init_fsusb_clkctrl_modulemode_wrf(&l3init_base,
620 /* CM_L3INIT_USBPHY_CLKCTRL */
621 omap44xx_l3init_cm2_cm_l3init_usbphy_clkctrl_wr(&l3init_base, 0x301);
626 static void set_muxconf_regs(void)
628 printf("set_muxconf_regs()...");
630 /* CONTROL_PADCONF_CORE_SYSCONFIG */
631 omap44xx_sysctrl_padconf_core_control_padconf_core_sysconfig_ip_sysconfig_idlemode_wrf(
632 &sysctrl_padconf_core_base, 0x1);
634 /* CONTROL_PADCONF_WKUP_SYSCONFIG */
635 omap44xx_sysctrl_padconf_wkup_control_padconf_wkup_sysconfig_ip_sysconfig_idlemode_wrf(
636 &sysctrl_padconf_wkup_base, 0x1);
639 omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_t ulpitll;
640 ulpitll = omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_rd(
641 &sysctrl_padconf_core_base) & 0x0000FFFF;
642 ulpitll = omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_usbb1_ulpitll_clk_inputenable_insert(
644 ulpitll = omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_usbb1_ulpitll_clk_pulludenable_insert(
646 ulpitll = omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_usbb1_ulpitll_clk_muxmode_insert(
648 omap44xx_sysctrl_padconf_core_control_core_pad0_cam_globalreset_pad1_usbb1_ulpitll_clk_wr(
649 &sysctrl_padconf_core_base, ulpitll);
651 /* USBB1_STP / USBB1_DIR */
652 omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_t usb_dir = 0x0;
653 usb_dir = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_usbb1_ulpitll_stp_muxmode_insert(
655 usb_dir = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_usbb1_ulpitll_dir_muxmode_insert(
657 usb_dir = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_usbb1_ulpitll_dir_inputenable_insert(
659 usb_dir = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_usbb1_ulpitll_dir_pulludenable_insert(
661 omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_stp_pad1_usbb1_ulpitll_dir_wr(
662 &sysctrl_padconf_core_base, usb_dir);
664 /* this values are used for all the 8 data lines */
665 uint32_t usb_dat = 0x0;
666 usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_dat0_muxmode_insert(
668 usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_nxt_muxmode_insert(
670 usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_dat0_inputenable_insert(
672 usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_nxt_inputenable_insert(
674 usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_dat0_pulludenable_insert(
676 usb_dat = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_usbb1_ulpitll_nxt_pulludenable_insert(
679 /* USBB1_DAT0 / USBB1_NXT */
680 omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_nxt_pad1_usbb1_ulpitll_dat0_wr(
681 &sysctrl_padconf_core_base, usb_dat);
683 /* USBB1_DAT1 / USBB1_DAT2 */
684 omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat1_pad1_usbb1_ulpitll_dat2_wr(
685 &sysctrl_padconf_core_base, usb_dat);
687 /* USBB1_DAT3 / USBB1_DAT4 */
688 omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat3_pad1_usbb1_ulpitll_dat4_wr(
689 &sysctrl_padconf_core_base, usb_dat);
691 /* USBB1_DAT5 / USBB1_DAT6 */
692 omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat5_pad1_usbb1_ulpitll_dat6_wr(
693 &sysctrl_padconf_core_base, usb_dat);
696 omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_t usb_dat7;
697 usb_dat7 = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_rd(
698 &sysctrl_padconf_core_base) & 0xFFFF0000;
699 usb_dat7 = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_usbb1_ulpitll_dat7_muxmode_insert(
701 usb_dat7 = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_usbb1_ulpitll_dat7_pulludenable_insert(
703 usb_dat7 = omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_usbb1_ulpitll_dat7_inputenable_insert(
705 omap44xx_sysctrl_padconf_core_control_core_pad0_usbb1_ulpitll_dat7_pad1_usbb1_hsic_data_wr(
706 &sysctrl_padconf_core_base, usb_dat7);
712 * \brief Continue kernel initialization in kernel address space.
714 * This function resets paging to map out low memory and map in physical
715 * address space, relocating all remaining data structures. It sets up exception handling,
716 * initializes devices and enables interrupts. After that it
717 * calls arm_kernel_startup(), which should not return (if it does, this function
720 static void __attribute__ ((noinline,noreturn)) text_init(void)
724 if ((glbl_core_data->multiboot_flags & MULTIBOOT_INFO_FLAG_HAS_MMAP)) {
725 // BSP core: set final page tables
726 struct arm_coredata_mmap *mmap = (struct arm_coredata_mmap *)
727 local_phys_to_mem(glbl_core_data->mmap_addr);
728 paging_arm_reset(mmap->base_addr, mmap->length);
729 //printf("paging_arm_reset: base: 0x%"PRIx64", length: 0x%"PRIx64".\n", mmap->base_addr, mmap->length);
732 // FIXME: Not sure what to do, so map the whole memory for now
733 paging_arm_reset(PHYS_MEMORY_START, 0x40000000);
738 //printf("invalidate cache\n");
739 cp15_invalidate_i_and_d_caches_fast();
740 //printf("invalidate TLB\n");
741 cp15_invalidate_tlb();
743 kcb_current = (struct kcb *)
744 local_phys_to_mem((lpaddr_t) kcb_current);
746 //printf("startup_early\n");
747 kernel_startup_early();
748 //printf("kernel_startup_early done!\n");
751 serial_init(serial_console_port, true);
754 printf("Barrelfish CPU driver starting on ARMv7 OMAP44xx"
755 " Board id 0x%08"PRIx32"\n", hal_get_board_id());
756 printf("The address of paging_map_kernel_section is %p\n",
757 paging_map_kernel_section);
759 errval = serial_debug_init();
760 if (err_is_fail(errval)) {
761 printf("Failed to initialize debug port: %d", serial_debug_port);
764 if (my_core_id != hal_get_cpu_id()) {
765 printf("** setting my_core_id (="PRIuCOREID") to match hal_get_cpu_id() (=%u)\n");
766 my_core_id = hal_get_cpu_id();
769 // Test MMU by remapping the device identifier and reading it using a
771 lpaddr_t id_code_section = OMAP44XX_MAP_L4_CFG_SYSCTRL_GENERAL_CORE
772 & ~ARM_L1_SECTION_MASK;
773 lvaddr_t id_code_remapped = paging_map_device(id_code_section,
774 ARM_L1_SECTION_BYTES);
776 omap44xx_id_initialize(&id,
777 (mackerel_addr_t) (id_code_remapped
778 + (OMAP44XX_MAP_L4_CFG_SYSCTRL_GENERAL_CORE
779 & ARM_L1_SECTION_MASK)));
782 omap44xx_id_code_pr(buf, 200, &id);
783 printf("Using MMU, %s", buf);
786 printf("gic_init done\n");
788 if (hal_cpu_is_bsp()) {
791 uint32_t omap_num_cores = scu_get_core_count();
792 printf("Number of cores in system: %"PRIu32"\n", omap_num_cores);
794 // ARM Cortex A9 TRM section 2.1
795 if (omap_num_cores > 4)
796 panic("ARM SCU doesn't support more than 4 cores!");
798 // init SCU if more than one core present
799 if (omap_num_cores > 1) {
806 printf("tsc_init done --\n");
808 enable_cycle_counter_user_access();
809 reset_cycle_counter();
812 coreboot_set_spawn_handler(CPU_ARM7, start_aps_arm_start);
814 arm_kernel_startup();
818 * Use Mackerel to print the identification from the system
819 * configuration block.
821 static void print_system_identification(void)
825 omap44xx_id_initialize(&id,
826 (mackerel_addr_t) OMAP44XX_MAP_L4_CFG_SYSCTRL_GENERAL_CORE);
827 omap44xx_id_pr(buf, 799, &id);
829 omap44xx_id_codevals_prtval(buf, 799, omap44xx_id_code_rawrd(&id));
830 printf("Device is a %s\n", buf);
833 static size_t bank_size(int bank, lpaddr_t base)
838 omap44xx_emif_t emif;
839 omap44xx_emif_initialize(&emif, (mackerel_addr_t)base);
841 if (!omap44xx_emif_status_phy_dll_ready_rdf(&emif)) {
842 printf("EMIF%d doesn't seem to have any DDRAM attached.\n", bank);
846 rowbits = omap44xx_emif_sdram_config_rowsize_rdf(&emif) + 9;
847 colbits = omap44xx_emif_sdram_config_pagesize_rdf(&emif) + 9;
848 rowsize = omap44xx_emif_sdram_config2_rdbsize_rdf(&emif) + 5;
850 printf("EMIF%d: ready, %d-bit rows, %d-bit cols, %d-byte row buffer\n",
851 bank, rowbits, colbits, 1<<rowsize);
853 return (1 << (rowbits + colbits + rowsize));
856 static void size_ram(void)
859 sz = bank_size(1, OMAP44XX_MAP_EMIF1) + bank_size(2, OMAP44XX_MAP_EMIF2);
860 printf("We seem to have 0x%08lx bytes of DDRAM: that's %s.\n",
861 sz, sz == 0x40000000 ? "about right" : "unexpected" );
865 * Does work for both LEDs now.
867 static void set_leds(void)
873 printf("Flashing LEDs\n");
875 omap44xx_gpio_initialize(&g, (mackerel_addr_t) OMAP44XX_MAP_L4_WKUP_GPIO1);
877 r = omap44xx_gpio_oe_rd(&g) & (~(1 << 8));
878 omap44xx_gpio_oe_wr(&g, r);
880 r = omap44xx_gpio_dataout_rd(&g) & (~(1 << 8));
882 for (int i = 0; i < 5; i++) {
883 omap44xx_gpio_dataout_wr(&g, r);
884 for (int j = 0; j < 2000; j++) {
887 omap44xx_gpio_dataout_wr(&g, nr);
888 for (int j = 0; j < 2000; j++) {
893 omap44xx_gpio_initialize(&g, (mackerel_addr_t) OMAP44XX_MAP_L4_PER_GPIO4);
896 * TODO: write as mackerel
898 volatile uint32_t *pad_mux = (uint32_t *) 0x4A1000F4;
899 *pad_mux = ((*pad_mux) & ~(0x7 << 16)) | (0x3 << 16);
902 r = omap44xx_gpio_oe_rd(&g) & (~(1 << 14));
903 omap44xx_gpio_oe_wr(&g, r);
905 r = omap44xx_gpio_dataout_rd(&g);
907 for (int i = 0; i < 5; i++) {
908 omap44xx_gpio_dataout_wr(&g, r);
909 for (int j = 0; j < 2000; j++) {
912 omap44xx_gpio_dataout_wr(&g, nr);
913 for (int j = 0; j < 2000; j++) {
920 * Entry point called from boot.S for bootstrap processor.
921 * if is_bsp == true, then pointer points to multiboot_info
922 * else pointer points to a global struct
924 void arch_init(void *pointer)
927 serial_early_init(serial_console_port);
928 spinlock_early_init();//from here on we can safely use printf
930 if (hal_cpu_is_bsp()) {
931 struct multiboot_info *mb = pointer;
933 memset(glbl_core_data, 0, sizeof(struct arm_core_data));
935 size_t max_addr = max(multiboot_end_addr(mb), (uintptr_t)&kernel_final_byte);
936 glbl_core_data->start_free_ram = ROUND_UP(max_addr, BASE_PAGE_SIZE);
937 glbl_core_data->mods_addr = mb->mods_addr;
938 glbl_core_data->mods_count = mb->mods_count;
939 glbl_core_data->cmdline = mb->cmdline;
940 glbl_core_data->mmap_length = mb->mmap_length;
941 glbl_core_data->mmap_addr = mb->mmap_addr;
942 glbl_core_data->multiboot_flags = mb->flags;
944 memset(&global->locks, 0, sizeof(global->locks));
946 extern struct kcb bspkcb;
947 memset(&bspkcb, 0, sizeof(bspkcb));
948 kcb_current = &bspkcb;
950 //boot up a cortex-m3 core
952 cortex_m3_early_init();
953 //set up and run heteropanda_slave image on cortex-m3
954 //XXX: HACK: to find out where the heteropanda_slave image starts, molly will
955 //just write the address into multiboot_info->mem_lower (which is otherwise unused)
956 void* start_slave = (void*) (mb->mem_lower);
957 prepare_and_start_m3(start_slave);
958 //printf("entering endless loop so the M3 can work unhindered.\n");
963 global = (struct global *)GLOBAL_VBASE;
964 // zeroing locks for the app core seems bogus to me --AKK
965 //memset(&global->locks, 0, sizeof(global->locks));
967 // our core data (struct arm_core_data) is placed one page before the
968 // first byte of the kernel image
969 glbl_core_data = (struct arm_core_data *)
970 ((lpaddr_t)&kernel_first_byte - BASE_PAGE_SIZE);
971 glbl_core_data->cmdline = (lpaddr_t)&glbl_core_data->kernel_cmdline;
972 kcb_current = (struct kcb*) (lpaddr_t)glbl_core_data->kcb;
973 my_core_id = glbl_core_data->dst_core_id;
975 // tell BSP that we are started up
976 // See Section 27.4.4 in the OMAP44xx manual for how this should work.
977 // we do this early, to avoid having to map the registers
978 lpaddr_t aux_core_boot_0 = AUX_CORE_BOOT_0;
979 lpaddr_t ap_wait = AP_WAIT_PHYS;
981 *((volatile lvaddr_t *)aux_core_boot_0) = 2<<2;
982 //__sync_synchronize();
983 *((volatile lvaddr_t *)ap_wait) = AP_STARTED;
986 if (kcb_current == NULL) {
987 panic("Did not receive a valid KCB.");
990 // XXX: print kernel address for debugging with gdb
991 printf("Barrelfish OMAP44xx CPU driver starting at addr 0x%"PRIxLVADDR" on core %"PRIuCOREID"\n",
992 local_phys_to_mem((lpaddr_t)&kernel_first_byte), my_core_id);
994 if (hal_cpu_is_bsp()) {
995 print_system_identification();
1001 * pandaboard related USB setup
1003 if (hal_cpu_is_bsp()) {
1004 printf("-------------------------\nUSB Host initialization\n");
1005 omap44xx_hsusbhost_initialize(&hsusbhost_base,
1006 (mackerel_addr_t) OMAP44XX_HSUSBHOST);
1007 omap44xx_usbtllhs_config_initialize(&usbtllhs_config_base,
1008 (mackerel_addr_t) OMAP44XX_USBTLLHS_CONFIG);
1009 omap44xx_scrm_initialize(&srcm_base, (mackerel_addr_t) OMAP44XX_SCRM);
1010 omap44xx_sysctrl_padconf_wkup_initialize(&sysctrl_padconf_wkup_base,
1011 (mackerel_addr_t) OMAP44XX_SYSCTRL_PADCONF_WKUP);
1012 omap44xx_sysctrl_padconf_core_initialize(&sysctrl_padconf_core_base,
1013 (mackerel_addr_t) OMAP44XX_SYSCTRL_PADCONF_CORE);
1014 omap44xx_gpio_initialize(&gpio_1_base,
1015 (mackerel_addr_t) OMAP44XX_MAP_L4_WKUP_GPIO1);
1016 omap44xx_gpio_initialize(&gpio_2_base,
1017 (mackerel_addr_t) OMAP44XX_MAP_L4_PER_GPIO2);
1018 omap44xx_ehci_initialize(&ehci_base, (mackerel_addr_t) OMAP44XX_EHCI);
1020 omap44xx_ckgen_prm_initialize(&ckgen_base,
1021 (mackerel_addr_t) OMAP44XX_CKGEN_PRM);
1022 omap44xx_l4per_cm2_initialize(&l4per_base,
1023 (mackerel_addr_t) OMAP44XX_L4PER_CM2);
1024 omap44xx_l3init_cm2_initialize(&l3init_base,
1025 (mackerel_addr_t) OMAP44XX_L3INIT_CM2);
1029 printf("-------------------------\n");
1038 cp15_enable_alignment();
1039 printf("MMU enabled\n");