Module Name: src Committed By: kiyohara Date: Sat Oct 15 15:27:18 UTC 2016
Modified Files: src/sys/arch/evbarm/gumstix: gumstix_machdep.c gumstix_start.S gxio.c Log Message: Support Duovero and Pepper. To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.52 src/sys/arch/evbarm/gumstix/gumstix_machdep.c cvs rdiff -u -r1.13 -r1.14 src/sys/arch/evbarm/gumstix/gumstix_start.S cvs rdiff -u -r1.20 -r1.21 src/sys/arch/evbarm/gumstix/gxio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/evbarm/gumstix/gumstix_machdep.c diff -u src/sys/arch/evbarm/gumstix/gumstix_machdep.c:1.51 src/sys/arch/evbarm/gumstix/gumstix_machdep.c:1.52 --- src/sys/arch/evbarm/gumstix/gumstix_machdep.c:1.51 Thu Mar 31 14:33:17 2016 +++ src/sys/arch/evbarm/gumstix/gumstix_machdep.c Sat Oct 15 15:27:18 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: gumstix_machdep.c,v 1.51 2016/03/31 14:33:17 kiyohara Exp $ */ +/* $NetBSD: gumstix_machdep.c,v 1.52 2016/10/15 15:27:18 kiyohara Exp $ */ /* * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation. * All rights reserved. @@ -137,16 +137,21 @@ * boards using RedBoot firmware. */ -#include "opt_evbarm_boardtype.h" +#include "opt_com.h" #include "opt_cputypes.h" +#include "opt_evbarm_boardtype.h" #include "opt_gumstix.h" -#ifdef OVERO +#include "opt_kgdb.h" +#include "opt_multiprocessor.h" +#include "opt_pmap_debug.h" +#if defined(OVERO) || defined(DUOVERO) || defined(PEPPER) #include "opt_omap.h" + +#if defined(DUOVERO) +#include "arml2cc.h" +#endif #include "prcm.h" #endif -#include "opt_kgdb.h" -#include "opt_pmap_debug.h" -#include "opt_com.h" #include <sys/param.h> #include <sys/conf.h> @@ -159,22 +164,35 @@ #include <sys/termios.h> #include <sys/bus.h> #include <sys/cpu.h> +#include <sys/gpio.h> + +#include <prop/proplib.h> #include <uvm/uvm_extern.h> -#include <machine/autoconf.h> +#include <arm/mainbus/mainbus.h> /* don't reorder */ + +#include <machine/autoconf.h> /* don't reorder */ #include <machine/bootconfig.h> #include <arm/locore.h> #include <arm/arm32/machdep.h> -#ifdef OVERO -#include <arm/omap/omap2_gpmcreg.h> +#if NARML2CC > 0 +#include <arm/cortex/pl310_var.h> +#endif +#include <arm/cortex/scu_reg.h> #include <arm/omap/omap2_obiovar.h> +#include <arm/omap/am335x_prcm.h> +#include <arm/omap/omap2_gpio.h> +#include <arm/omap/omap2_gpmcreg.h> #include <arm/omap/omap2_prcm.h> -#include <arm/omap/omap2_reg.h> +#if defined(OVERO) || defined(DUOVERO) || defined(PEPPER) +#include <arm/omap/omap2_reg.h> /* Must required "opt_omap.h" */ +#endif +#include <arm/omap/omap3_sdmmcreg.h> #include <arm/omap/omap_var.h> #include <arm/omap/omap_com.h> -#endif +#include <arm/omap/tifbvar.h> #include <arm/xscale/pxa2x0reg.h> #include <arm/xscale/pxa2x0var.h> #include <arm/xscale/pxa2x0_gpio.h> @@ -207,8 +225,9 @@ uint32_t system_serial_low; /* Prototypes */ #if defined(GUMSTIX) static void read_system_serial(void); -#elif defined(OVERO) -static void overo_reset(void); +#endif +#if defined(OMAP2) +static void omap_reset(void); static void find_cpu_clock(void); #endif static void process_kernel_args(int, char *[]); @@ -226,7 +245,7 @@ bs_protos(bs_notimpl); #include <dev/ic/comvar.h> #endif -#if defined(CPU_XSCALE_PXA250) || defined(CPU_XSCALE_PXA270) +#if defined(CPU_XSCALE) #include "lcd.h" #endif @@ -244,7 +263,11 @@ int comcnmode = CONMODE; static char console[16]; #endif -extern void gxio_config_pin(void); +const struct tifb_panel_info *tifb_panel_info = NULL; +/* Use TPS65217 White LED Driver */ +bool use_tps65217_wled = false; + +extern void gxio_config(void); extern void gxio_config_expansion(char *); @@ -335,20 +358,27 @@ static const struct pmap_devmap gumstix_ PTE_NOCACHE, }, #elif defined(OVERO) - { + { /* SCM, PRCM */ OVERO_L4_CORE_VBASE, _A(OMAP3530_L4_CORE_BASE), _S(L1_S_SIZE), /* No need 16MB. Use only first 1MB */ VM_PROT_READ | VM_PROT_WRITE, PTE_NOCACHE }, - { + { /* Console, GPIO[2-6] */ OVERO_L4_PERIPHERAL_VBASE, _A(OMAP3530_L4_PERIPHERAL_BASE), _S(OMAP3530_L4_PERIPHERAL_SIZE), VM_PROT_READ | VM_PROT_WRITE, PTE_NOCACHE }, + { /* GPIO1 */ + OVERO_L4_WAKEUP_VBASE, + _A(OMAP3530_L4_WAKEUP_BASE), + _S(OMAP3530_L4_WAKEUP_SIZE), + VM_PROT_READ | VM_PROT_WRITE, + PTE_NOCACHE + }, { OVERO_GPMC_VBASE, _A(GPMC_BASE), @@ -356,6 +386,52 @@ static const struct pmap_devmap gumstix_ VM_PROT_READ | VM_PROT_WRITE, PTE_NOCACHE }, +#elif defined(DUOVERO) + { + DUOVERO_L4_CM_VBASE, + _A(OMAP4430_L4_CORE_BASE + 0x100000), + _S(L1_S_SIZE), + VM_PROT_READ | VM_PROT_WRITE, + PTE_NOCACHE + }, + { /* Console, SCU, L2CC, GPIO[2-6] */ + DUOVERO_L4_PERIPHERAL_VBASE, + _A(OMAP4430_L4_PERIPHERAL_BASE), + _S(L1_S_SIZE * 3), + VM_PROT_READ | VM_PROT_WRITE, + PTE_NOCACHE + }, + { /* PRCM, GPIO1 */ + DUOVERO_L4_WAKEUP_VBASE, + _A(OMAP4430_L4_WAKEUP_BASE), + _S(OMAP4430_L4_WAKEUP_SIZE), + VM_PROT_READ | VM_PROT_WRITE, + PTE_NOCACHE + }, + { + DUOVERO_GPMC_VBASE, + _A(GPMC_BASE), + _S(GPMC_SIZE), + VM_PROT_READ | VM_PROT_WRITE, + PTE_NOCACHE + }, +#elif defined(PEPPER) + { + /* CM, Control Module, GPIO0, Console */ + PEPPER_PRCM_VBASE, + _A(OMAP2_CM_BASE), + _S(L1_S_SIZE), + VM_PROT_READ | VM_PROT_WRITE, + PTE_NOCACHE + }, + { + /* GPIO[1-3] */ + PEPPER_L4_PERIPHERAL_VBASE, + _A(TI_AM335X_L4_PERIPHERAL_BASE), + _S(L1_S_SIZE), + VM_PROT_READ | VM_PROT_WRITE, + PTE_NOCACHE + }, #endif { 0, 0, 0, 0, 0 } }; @@ -400,16 +476,22 @@ initarm(void *arg) * Overo: * Physical Address Range Description * ----------------------- ---------------------------------- - * 0x80000000 - 0x8fffffff SDRAM Bank 0 (256MB or 512MB) + * 0x80000000 - 0x9fffffff SDRAM Bank 0 + * 0x80000000 - 0x83ffffff KERNEL_BASE + * + * DuoVero, Pepper: + * Physical Address Range Description + * ----------------------- ---------------------------------- + * 0x80000000 - 0xbfffffff SDRAM Bank 0 * 0x80000000 - 0x83ffffff KERNEL_BASE */ -#if defined(GUMSTIX) +#if defined(CPU_XSCALE) cpu_reset_address = NULL; -#elif defined(OVERO) - cpu_reset_address = overo_reset; +#elif defined(OMAP2) + cpu_reset_address = omap_reset; - find_cpu_clock(); // find our CPU speed. + find_cpu_clock(); #endif /* @@ -421,7 +503,7 @@ initarm(void *arg) /* map some peripheral registers at static I/O area */ pmap_devmap_bootstrap((vaddr_t)read_ttb(), gumstix_devmap); -#if defined(CPU_XSCALE_PXA250) || defined(CPU_XSCALE_PXA270) +#if defined(CPU_XSCALE) /* start 32.768kHz OSC */ ioreg_write(GUMSTIX_CLKMAN_VBASE + CLKMAN_OSCC, OSCC_OON); @@ -432,15 +514,12 @@ initarm(void *arg) pxa2x0_gpio_bootstrap(GUMSTIX_GPIO_VBASE); pxa2x0_clkman_bootstrap(GUMSTIX_CLKMAN_VBASE); -#elif defined(CPU_CORTEX) - cortex_pmc_ccnt_init(); #endif cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); - /* configure GPIOs. */ - gxio_config_pin(); - + /* configure MUX, GPIO and CLK. */ + gxio_config(); #ifndef GUMSTIX_NETBSD_ARGS_CONSOLE consinit(); @@ -455,10 +534,11 @@ initarm(void *arg) */ #if defined(GUMSTIX) #define SDRAM_START 0xa0000000UL -#elif defined(OVERO) +#elif defined(OVERO) || defined(DUOVERO) || defined(PEPPER) #define SDRAM_START 0x80000000UL #endif - if (((uint32_t)u_boot_args[r0] & 0xf0000000) != SDRAM_START) + if ((uint32_t)u_boot_args[r0] < SDRAM_START || + (uint32_t)u_boot_args[r0] >= SDRAM_START + ram_size) /* Maybe r0 is 'argc'. We are booted by command 'go'. */ process_kernel_args((int)u_boot_args[r0], (char **)u_boot_args[r1]); @@ -486,6 +566,28 @@ initarm(void *arg) printf("initarm: Configuring system ...\n"); #endif +#if defined(OMAP_4430) + const bus_space_tag_t iot = &omap_bs_tag; + bus_space_handle_t ioh; + +#if NARML2CC > 0 + /* + * Initialize L2-Cache parameters + */ + + if (bus_space_map(iot, OMAP4_L2CC_BASE, OMAP4_L2CC_SIZE, 0, &ioh) != 0) + panic("OMAP4_L2CC_BASE map failed\n"); + arml2cc_init(iot, ioh, 0); +#endif + +#ifdef MULTIPROCESSOR + if (bus_space_map(iot, OMAP4_SCU_BASE, SCU_SIZE, 0, &ioh) != 0) + panic("OMAP4_SCU_BASE map failed\n"); + arm_cpu_max = + 1 + (bus_space_read_4(iot, ioh, SCU_CFG) & SCU_CFG_CPUMAX); +#endif +#endif + /* Fake bootconfig structure for the benefit of pmap.c */ /* XXX must make the memory description h/w independent */ bootconfig.dramblocks = 1; @@ -497,9 +599,9 @@ initarm(void *arg) arm32_bootmem_init(bootconfig.dram[0].address, ram_size, (uintptr_t) KERNEL_BASE_phys); arm32_kernel_vm_init(KERNEL_VM_BASE, -#if defined(CPU_XSCALE_PXA250) || defined(CPU_XSCALE_PXA270) +#if defined(CPU_XSCALE) ARM_VECTORS_LOW, -#elif defined(CPU_CORTEXA8) +#elif defined(CPU_CORTEX) ARM_VECTORS_HIGH, #endif 0, gumstix_devmap, true); @@ -553,13 +655,22 @@ read_system_serial(void) printf("%02x", system_serial[i]); printf("\n"); } +#endif -#elif defined(OVERO) - +#if defined(OMAP2) static void -overo_reset(void) +omap_reset(void) { +#if defined(TI_AM335X) + vaddr_t prm_base = (PEPPER_PRCM_VBASE + AM335X_PRCM_PRM_DEVICE); + + *(volatile uint32_t *)(prm_base + PRM_RSTCTRL) = RST_GLOBAL_WARM_SW; +#elif defined(OMAP_4430) + *(volatile uint32_t *)(DUOVERO_L4_WAKEUP_VBASE + OMAP4_PRM_RSTCTRL) = + OMAP4_PRM_RSTCTRL_WARM; +#endif + #if NPRCM > 0 prcm_cold_reset(); #endif @@ -568,8 +679,11 @@ overo_reset(void) static void find_cpu_clock(void) { - const vaddr_t prm_base = OMAP2_PRM_BASE; + const vaddr_t prm_base __unused = OMAP2_PRM_BASE; const vaddr_t cm_base = OMAP2_CM_BASE; + +#if defined(OMAP_3530) + const uint32_t prm_clksel = *(volatile uint32_t *)(prm_base + PLL_MOD + OMAP3_PRM_CLKSEL); static const uint32_t prm_clksel_freqs[] = OMAP3_PRM_CLKSEL_FREQS; @@ -591,6 +705,38 @@ find_cpu_clock(void) curcpu()->ci_data.cpu_cc_freq = ((sys_clk * m) / ((n + 1) * m2 * 2)) * OMAP3_PRM_CLKSEL_MULT; omap_sys_clk = sys_clk * OMAP3_PRM_CLKSEL_MULT; + +#elif defined(OMAP_4430) + + const uint32_t prm_clksel = + *(volatile uint32_t *)(prm_base + OMAP4_CM_SYS_CLKSEL); + static const uint32_t cm_clksel_freqs[] = OMAP4_CM_CLKSEL_FREQS; + const uint32_t sys_clk = + cm_clksel_freqs[__SHIFTOUT(prm_clksel, OMAP4_CM_SYS_CLKSEL_CLKIN)]; + const uint32_t dpll1 = + *(volatile uint32_t *)(cm_base + OMAP4_CM_CLKSEL_DPLL_MPU); + const uint32_t dpll2 = + *(volatile uint32_t *)(cm_base + OMAP4_CM_DIV_M2_DPLL_MPU); + const uint32_t m = + __SHIFTOUT(dpll1, OMAP4_CM_CLKSEL_DPLL_MPU_DPLL_MULT); + const uint32_t n = __SHIFTOUT(dpll1, OMAP4_CM_CLKSEL_DPLL_MPU_DPLL_DIV); + const uint32_t m2 = + __SHIFTOUT(dpll2, OMAP4_CM_DIV_M2_DPLL_MPU_DPLL_CLKOUT_DIV); + + /* + * MPU_CLK supplies ARM_FCLK which is twice the CPU frequency. + */ + curcpu()->ci_data.cpu_cc_freq = + ((sys_clk * 2 * m) / ((n + 1) * m2)) * OMAP4_CM_CLKSEL_MULT / 2; + omap_sys_clk = sys_clk * OMAP4_CM_CLKSEL_MULT; + +#elif defined(TI_AM335X) + + prcm_bootstrap(cm_base); + am335x_sys_clk(TI_AM335X_CTLMOD_BASE); + am335x_cpu_clk(); + +#endif } #endif @@ -841,9 +987,9 @@ consinit(void) } #endif /* HWUARTCONSOLE */ -#elif defined(OVERO) +#elif defined(OVERO) || defined(DUOVERO) || defined(PEPPER) - if (comcnattach(&omap_a4x_bs_tag, 0x49020000, comcnspeed, + if (comcnattach(&omap_a4x_bs_tag, CONSADDR, comcnspeed, OMAP_COM_FREQ, COM_TYPE_NORMAL, comcnmode) == 0) return; @@ -899,7 +1045,37 @@ gumstix_device_register(device_t dev, vo { prop_dictionary_t dict = device_properties(dev); + if (device_is_a(dev, "a9tmr") || + device_is_a(dev, "a9wdt")) { + /* + * We need to tell the A9 Global/Watchdog Timer + * what frequency it runs at. + */ + + /* + * This clock always runs at (arm_clk div 2) and only goes + * to timers that are part of the A9 MP core subsystem. + */ + prop_dictionary_set_uint32(dict, "frequency", + curcpu()->ci_data.cpu_cc_freq / 2); + } + if (device_is_a(dev, "armperiph")) { + if (device_is_a(device_parent(dev), "mainbus")) { +#if defined(OMAP2) + /* + * XXX KLUDGE ALERT XXX + * The iot mainbus supplies is completely wrong since + * it scales addresses by 2. The simpliest remedy is + * to replace with our bus space used for the armcore + * regisers (which armperiph uses). + */ + struct mainbus_attach_args * const mb = aux; + mb->mb_iot = &omap_bs_tag; +#endif + } + } if (device_is_a(dev, "ehci")) { +#if defined(OVERO) prop_dictionary_set_uint16(dict, "nports", 2); prop_dictionary_set_bool(dict, "phy-reset", true); prop_dictionary_set_cstring(dict, "port0-mode", "none"); @@ -907,6 +1083,14 @@ gumstix_device_register(device_t dev, vo prop_dictionary_set_cstring(dict, "port1-mode", "phy"); prop_dictionary_set_int16(dict, "port1-gpio", 183); prop_dictionary_set_bool(dict, "port1-gpioval", true); +#elif defined(DUOVERO) + prop_dictionary_set_uint16(dict, "nports", 1); + prop_dictionary_set_bool(dict, "phy-reset", true); + prop_dictionary_set_cstring(dict, "port0-mode", "phy"); + prop_dictionary_set_int16(dict, "port0-gpio", 62); + prop_dictionary_set_bool(dict, "port0-gpioval", false); + prop_dictionary_set_bool(dict, "port0-extclk", true); +#endif prop_dictionary_set_uint16(dict, "dpll5-m", 443); prop_dictionary_set_uint16(dict, "dpll5-n", 11); prop_dictionary_set_uint16(dict, "dpll5-m2", 4); @@ -929,9 +1113,7 @@ gumstix_device_register(device_t dev, vo } } if (device_is_a(dev, "omapmputmr")) { -#ifdef OVERO struct obio_attach_args *obio = aux; - int en; switch (obio->obio_addr) { case 0x49032000: /* GPTIMER2 */ @@ -942,14 +1124,73 @@ gumstix_device_register(device_t dev, vo case 0x4903c000: /* GPTIMER7 */ case 0x4903e000: /* GPTIMER8 */ case 0x49040000: /* GPTIMER9 */ +#if defined(OVERO) + { /* Ensure enable PRCM.CM_[FI]CLKEN_PER[3:10]. */ - en = 1 << (((obio->obio_addr >> 13) & 0x3f) - 0x16); + const int en = + 1 << (((obio->obio_addr >> 13) & 0x3f) - 0x16); + ioreg_write(OVERO_L4_CORE_VBASE + 0x5000, ioreg_read(OVERO_L4_CORE_VBASE + 0x5000) | en); ioreg_write(OVERO_L4_CORE_VBASE + 0x5010, ioreg_read(OVERO_L4_CORE_VBASE + 0x5010) | en); + } +#endif break; } + } + if (device_is_a(dev, "sdhc")) { + bool dualvolt = false; + +#if defined(OVERO) || defined(DUOVERO) + if (device_is_a(device_parent(dev), "obio")) { + struct obio_attach_args *obio = aux; + +#if defined(OVERO) + if (obio->obio_addr == SDMMC2_BASE_3530) + dualvolt = true; +#elif defined(DUOVERO) + if (obio->obio_addr == SDMMC5_BASE_4430) + dualvolt = true; +#endif + } +#endif +#if defined(PEPPER) + if (device_is_a(device_parent(dev), "mainbus")) { + struct mainbus_attach_args * const mb = aux; + + if (mb->mb_iobase == SDMMC3_BASE_TIAM335X) + dualvolt = true; + } #endif + prop_dictionary_set_bool(dict, "dual-volt", dualvolt); + } + if (device_is_a(dev, "tifb")) { + prop_data_t panel_info; + + panel_info = prop_data_create_data_nocopy(tifb_panel_info, + sizeof(struct tifb_panel_info)); + KASSERT(panel_info != NULL); + prop_dictionary_set(dict, "panel-info", panel_info); + prop_object_release(panel_info); + + /* enable LCD */ + omap2_gpio_ctl(59, GPIO_PIN_OUTPUT); + omap2_gpio_write(59, 0); /* reset */ + delay(100); + omap2_gpio_write(59, 1); + } + if (device_is_a(dev, "tps65217pmic")) { +#if defined(TI_AM335X) + extern const char *mpu_supply; + + mpu_supply = "DCDC3"; +#endif + + if (use_tps65217_wled) { + prop_dictionary_set_int32(dict, "isel", 1); + prop_dictionary_set_int32(dict, "fdim", 200); + prop_dictionary_set_int32(dict, "brightness", 80); + } } } Index: src/sys/arch/evbarm/gumstix/gumstix_start.S diff -u src/sys/arch/evbarm/gumstix/gumstix_start.S:1.13 src/sys/arch/evbarm/gumstix/gumstix_start.S:1.14 --- src/sys/arch/evbarm/gumstix/gumstix_start.S:1.13 Fri May 23 13:56:18 2014 +++ src/sys/arch/evbarm/gumstix/gumstix_start.S Sat Oct 15 15:27:18 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: gumstix_start.S,v 1.13 2014/05/23 13:56:18 kiyohara Exp $ */ +/* $NetBSD: gumstix_start.S,v 1.14 2016/10/15 15:27:18 kiyohara Exp $ */ /* * Copyright (C) 2005, 2006 WIDE Project and SOUM Corporation. * All rights reserved. @@ -61,12 +61,17 @@ #include "opt_cputypes.h" #include "opt_gumstix.h" +#include "opt_multiprocessor.h" #include <machine/asm.h> #include <arm/armreg.h> #include "assym.h" -RCSID("$NetBSD: gumstix_start.S,v 1.13 2014/05/23 13:56:18 kiyohara Exp $") +#if defined(OVERO) || defined(DUOVERO) || defined(PEPPER) +#include <arm/omap/omap2_obioreg.h> +#endif + +RCSID("$NetBSD: gumstix_start.S,v 1.14 2016/10/15 15:27:18 kiyohara Exp $") /* * CPWAIT -- Canonical method to wait for CP15 update. @@ -74,7 +79,7 @@ RCSID("$NetBSD: gumstix_start.S,v 1.13 2 * copied from arm/arm/cpufunc_asm_xscale.S * XXX: better be in a common header file. */ -#if defined(CPU_XSCALE_PXA250) || defined(CPU_XSCALE_PXA270) +#if defined(CPU_XSCALE) #define CPWAIT_BRANCH \ sub pc, pc, #4 #else @@ -100,9 +105,9 @@ _C_LABEL(gumstix_start): */ /* Our page table might be cached. Disable D-cache beforehand. */ - mrc p15, 0, r4, c1, c0, 0 - bic r4, r4, #CPU_CONTROL_DC_ENABLE - mcr p15, 0, r4, c1, c0, 0 + mrc p15, 0, ip, c1, c0, 0 + bic ip, ip, #CPU_CONTROL_DC_ENABLE + mcr p15, 0, ip, c1, c0, 0 /* * Kernel is loaded in SDRAM (0xa0200000..), and is expected to run @@ -111,38 +116,40 @@ _C_LABEL(gumstix_start): */ /* save u-boot's args */ - adr r4, u_boot_args + adr ip, u_boot_args nop nop nop - stmia r4!, {r0, r1, r2, r3} + stmia ip!, {r0, r1, r2, r3} nop nop nop - /* Calculate RAM size */ - adr r4, ram_size -#if defined(GUMSTIX) - ldr r0, [r4] + /* Calculate RAM size, like vendor's u-boot. */ + adr ip, ram_size +#if defined(GUMSTIX) || defined(PEPPER) + ldr r0, [ip] +#if defined(GUMSTIX) mrc p15, 0, r1, c0, c0, 0 and r1, r1, #CPU_ID_XSCALE_COREGEN_MASK cmp r1, #0x4000 bne 3f /* goto 3f, if basix or connex */ +#endif 0: /* check memory size, if verdex or verdex-pro */ - add r3, r4, r0 + add r3, ip, r0 ldr r1, [r3] cmp r0, r1 beq 2f 1: add r0, r0, r0 /* r0 <<= 1 */ - str r0, [r4] + str r0, [ip] b 0b 2: mvn r1, r1 /* r1 ^= 0xffffffff */ str r1, [r3] - ldr r2, [r4] + ldr r2, [ip] cmp r1, r2 beq 3f str r0, [r3] /* restore */ @@ -159,12 +166,33 @@ _C_LABEL(gumstix_start): ldr r2, [r3] and r2, r1, r2, lsl #13 add r0, r0, r2 +#elif defined(DUOVERO) + mov r0, #0 + mov r3, #0x4e000000 /* OMAP44xx DMM */ + add r3, r3, #0x0050 +0: + ldr r2, [r3, #-4]! /* DMM_LISA_MAP_[3210] */ + and r1, r2, #0xff000000 /* get SYS_ADDR */ + tst r1, #0x80000000 /* is physical mem? */ + beq 1f + and r1, r2, #0x00030000 /* get SDRC_ADDRSPC */ + cmp r1, #0x00020000 /* is Reserved? */ + beq 1f + + lsr r2, r2, #20 + and r1, r2, #0x7 /* get SYS_SIZE */ + mov r2, #0x01000000 + mov r2, r2, lsl r1 + add r0, r0, r2 +1: + tst r3, #0x0000000f + bne 0b #endif - str r0, [r4] + str r0, [ip] /* Build page table from scratch */ ldr r0, Lstartup_pagetable /* pagetable */ - adr r4, mmu_init_table + adr ip, mmu_init_table b 5f 4: @@ -174,20 +202,28 @@ _C_LABEL(gumstix_start): adds r1, r1, #-1 bhi 4b 5: - ldmia r4!, {r1, r2, r3} /* # of sections, PA|attr, VA */ + ldmia ip!, {r1, r2, r3} /* # of sections, PA|attr, VA */ lsr r2, r2, #L1_S_SHIFT cmp r1, #0 bne 4b - mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ - mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ +#if defined(CPU_CORTEX) + mrc p15, 0, r1, c0, c0, 5 /* Read MPIDR */ + cmp r1, #0 /* Check MPIDR_MP (bit 31) */ + orrlt r1, r0, #TTBR_MPATTR + orrge r1, r0, #TTBR_UPATTR +#endif + mcr p15, 0, r1, c2, c0, 0 /* Set TTB */ + mcr p15, 0, r1, c8, c7, 0 /* Flush TLB */ +#if defined(CPU_CORTEX) + mcr p15, 0, r1, c2, c0, 1 /* Set TTB1 */ + mov r1, #TTBCR_S_N_1 + mcr p15, 0, r1, c2, c0, 2 /* Set TTBCR */ + mov r1, #0 + mcr p15, 0, r1, c8, c7, 0 /* Flush TLB */ -#if defined(CPU_CORTEXA8) - mcr p15, 0, r0, c2, c0, 1 /* Set TTB1 */ - mov r0, #TTBCR_S_N_1 - mcr p15, 0, r0, c2, c0, 2 /* Set TTBCR */ - mov r0, #0 - mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ + mov r1, #0 + mcr p15, 0, r1, c13, c0, 1 /* Write KERNEL_PID(#0) to CONTEXTIDR */ #endif /* @@ -195,29 +231,35 @@ _C_LABEL(gumstix_start): * startup_pagetable puts to domain 0 now. */ #define KERNEL_DOMAIN(x) ((x) << (PMAP_DOMAIN_KERNEL << 1)) - mov r0, #(KERNEL_DOMAIN(DOMAIN_CLIENT) | DOMAIN_CLIENT) - mcr p15, 0, r0, c3, c0, 0 + mov r1, #(KERNEL_DOMAIN(DOMAIN_CLIENT) | DOMAIN_CLIENT) + mcr p15, 0, r1, c3, c0, 0 /* Enable MMU and etc. */ - mrc p15, 0, r0, c1, c0, 0 + mrc p15, 0, r1, c1, c0, 0 #if defined(CPU_XSCALE_PXA250) || defined(CPU_XSCALE_PXA270) - orr r0, r0, #CPU_CONTROL_SYST_ENABLE + orr r1, r1, #CPU_CONTROL_SYST_ENABLE #endif +#if defined(CPU_CORTEX) #if defined(CPU_CORTEXA8) /* Disable L2 cache beforehand. */ - mrc p15, 0, r1, c1, c0, 1 - bic r1, r1, #0x2 /* clear L2EN */ - mcr p15, 0, r1, c1, c0, 1 + mrc p15, 0, r2, c1, c0, 1 + bic r2, r2, #0x2 /* clear L2EN */ + mcr p15, 0, r2, c1, c0, 1 +#endif - orr r0, r0, #CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_DC_ENABLE - orr r0, r0, #CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_IC_ENABLE + orr r1, r1, #(CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_DC_ENABLE) + orr r1, r1, #(CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_IC_ENABLE) #endif - orr r0, r0, #CPU_CONTROL_MMU_ENABLE - mcr p15, 0, r0, c1, c0, 0 + orr r1, r1, #CPU_CONTROL_MMU_ENABLE + mcr p15, 0, r1, c1, c0, 0 /* * Ensure that the coprocessor has finished turning on the MMU. */ - CPWAIT(r0) + CPWAIT(r3) + +#if defined(MULTIPROCESSOR) + bl omap_a9_mpinit /* omap_a9_mpinit(r0) */ +#endif /* Jump to kernel code in TRUE VA */ ldr r0, Lstart @@ -226,15 +268,6 @@ _C_LABEL(gumstix_start): Lstart: .word start -#ifndef STARTUP_PAGETABLE_ADDR -#if defined(GUMSTIX) -#define STARTUP_PAGETABLE_ADDR 0xa0000000 /* aligned 16kByte */ -#elif defined(OVERO) -#define STARTUP_PAGETABLE_ADDR 0x80000000 /* aligned 16kByte */ -#endif -#endif -Lstartup_pagetable: - .word STARTUP_PAGETABLE_ADDR .globl _C_LABEL(u_boot_args) u_boot_args: @@ -245,6 +278,17 @@ ram_size: .word 0x04000000 /* 64Mbyte */ +#ifndef STARTUP_PAGETABLE_ADDR +#if defined(GUMSTIX) +#define STARTUP_PAGETABLE_ADDR 0xa0000000 /* aligned 16kByte */ +#elif defined(OVERO) || defined(DUOVERO) || defined(PEPPER) +#define STARTUP_PAGETABLE_ADDR 0x80000000 /* aligned 16kByte */ +#endif +#endif +Lstartup_pagetable: + .word STARTUP_PAGETABLE_ADDR + + #define MMU_INIT(va, pa, n_sec, attr) \ .word n_sec ; \ .word (va) ; \ @@ -252,6 +296,7 @@ ram_size: mmu_init_table: #if defined(GUMSTIX) + /* fill all table VA==PA */ MMU_INIT(0x00000000, 0x00000000, 1 << (32 - L1_S_SHIFT), L1_S_PROTO | L1_S_AP_KRW) @@ -266,16 +311,101 @@ mmu_init_table: MMU_INIT(0xc0000000, SDRAM_START, 64, L1_S_PROTO | L1_S_C | L1_S_AP_KRW) -#elif defined(OVERO) +#elif defined(OVERO) || defined(DUOVERO) || defined(PEPPER) + /* fill all table VA==PA */ MMU_INIT(0x00000000, 0x00000000, - 1 << (32 - L1_S_SHIFT), L1_S_PROTO | L1_S_APv7_KRW) + 1 << (32 - L1_S_SHIFT), L1_S_PROTO | L1_S_APv7_KRW | L1_S_V6_XN) #define SDRAM_START 0x80000000 /* Map VA to PA, write-back cacheable (first 64M only) */ MMU_INIT(KERNEL_BASE & 0xffffffff, SDRAM_START, - 64, L1_S_PROTO | L1_S_B | L1_S_C | L1_S_APv7_KRW) + 64, +#if defined(MULTIPROCESSOR) + L1_S_PROTO | L1_S_V6_S | L1_S_B | L1_S_C | L1_S_APv7_KRW +#else + L1_S_PROTO | L1_S_B | L1_S_C | L1_S_APv7_KRW +#endif + ) + #endif MMU_INIT(0, 0, 0, 0) /* end of table */ + +#undef MMU_INIT + +#if defined(MULTIPROCESSOR) +#define XPUTC(n) + +#define MD_CPU_HATCH _C_LABEL(a9tmr_init_cpu_clock) + +#include <arm/cortex/pl310_reg.h> +#include <arm/cortex/a9_mpsubr.S> + +omap_a9_mpinit: + mrc p15, 0, r1, c0, c0, 5 /* Read MPIDR */ + and r1, r1, #(MPIDR_MP | MPIDR_U) + cmp r1, #MPIDR_MP + bxne lr /* not MP */ + + /* Invalidate CPU0 ways */ + mrc p15, 4, r3, c15, c0, 0; + mov r1, #0xf; + str r1, [r3, #SCU_INV_ALL_REG] + dsb + isb + + ldr r1, [r3, #SCU_CTL] + orr r1, r1, #SCU_CTL_SCU_ENA + str r1, [r3, #SCU_CTL] + dsb + isb + + movw r1, #:lower16:cortex_mmuinfo + movt r1, #:upper16:cortex_mmuinfo + str r0, [r1] + /* Make sure the info makes into memory */ + mcr p15, 0, r1, c7, c10, 1 /* writeback the L1 cache line */ + dsb + add r3, r3, #0x2000 /* PL310 L2 Cache controller */ + str r1, [r3, #L2C_CLEAN_PA] /* L2 cache also writeback */ + mov r0, #0 + str r0, [r3, #L2C_CACHE_SYNC] +0: + ldr r0, [r3, #L2C_CACHE_SYNC] + tst r0, #0x1 + bne 0b + + movw r3, #:lower16:OMAP4_WUGEN_BASE + movt r3, #:upper16:OMAP4_WUGEN_BASE + + /* First we setup the address for the secondaries to jump to. */ + adr r0, cortex_mpstart + str r0, [r3, #OMAP4_AUX_CORE_BOOT1] + dsb + + /* tell the secondary boot rom(s) to exit their loop */ + ldr r1, [r3, #OMAP4_AUX_CORE_BOOT0] + orr r1, r1, #0xf0 /* add mask for cpu #1 */ + str r1, [r3, #OMAP4_AUX_CORE_BOOT0] + dsb + + /* Now we kick it and return. */ + sev + movw r3, #:lower16:arm_cpu_hatched + movt r3, #:upper16:arm_cpu_hatched + + /* Let's wait for the secondary to hatch. */ + mov r1, #0x1000000 +1: dmb + ldr r0, [r3] + cmp r0, #0 + bxne lr + subs r1, r1, #1 + bne 1b + + bx lr + +END(omap_a9_mpinit) +#endif /* MULTIPROCESSOR */ Index: src/sys/arch/evbarm/gumstix/gxio.c diff -u src/sys/arch/evbarm/gumstix/gxio.c:1.20 src/sys/arch/evbarm/gumstix/gxio.c:1.21 --- src/sys/arch/evbarm/gumstix/gxio.c:1.20 Mon Dec 24 06:50:35 2012 +++ src/sys/arch/evbarm/gumstix/gxio.c Sat Oct 15 15:27:18 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: gxio.c,v 1.20 2012/12/24 06:50:35 kiyohara Exp $ */ +/* $NetBSD: gxio.c,v 1.21 2016/10/15 15:27:18 kiyohara Exp $ */ /* * Copyright (C) 2005, 2006, 2007 WIDE Project and SOUM Corporation. * All rights reserved. @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gxio.c,v 1.20 2012/12/24 06:50:35 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gxio.c,v 1.21 2016/10/15 15:27:18 kiyohara Exp $"); #include "opt_cputypes.h" #include "opt_gumstix.h" @@ -49,15 +49,17 @@ __KERNEL_RCSID(0, "$NetBSD: gxio.c,v 1.2 #include <machine/bootconfig.h> -#if defined(OVERO) #include <arm/omap/omap2_gpmcreg.h> +#if defined(OMAP2) #include <arm/omap/omap2_reg.h> #if defined(OMAP3530) #include <arm/omap/omap2_intr.h> #endif -#include <arm/omap/omap_var.h> #endif -#if defined(CPU_XSCALE_PXA270) || defined(CPU_XSCALE_PXA250) +#include <arm/omap/omap_var.h> +#include <arm/omap/tifbvar.h> +#include <arm/omap/ti_iicreg.h> +#if defined(CPU_XSCALE) #include <arm/xscale/pxa2x0cpu.h> #endif #include <arm/xscale/pxa2x0reg.h> @@ -85,9 +87,8 @@ CFATTACH_DECL_NEW(gxio, sizeof(struct gx gxiomatch, gxioattach, NULL, NULL); #endif -void gxio_config_pin(void); +void gxio_config(void); void gxio_config_expansion(char *); -static void gxio_config_gpio(const struct gxioconf *, char *); #if defined(GUMSTIX) static void basix_config(void); static void cfstix_config(void); @@ -104,12 +105,41 @@ static void wifistix_cf_config(void); #elif defined(OVERO) static void eth0_config(void); static void eth1_config(void); +static void dvi_config(void); +static void lcd_config(char); +static void header_40pin_config(int); + static void chestnut_config(void); +static void gallop_config(void); +static void summit_config(void); static void tobi_config(void); static void tobiduo_config(void); +#elif defined(DUOVERO) +static void ehci_config(void); + +static void parlor_config(void); +#elif defined(PEPPER) +static void lcd_config(void); +static void pepper43_config(void); + +static void pepper_config(void); +static void c_config(void); +static void dvi_config(void); +static void r_config(void); +#endif +#if defined(OVERO) || defined(DUOVERO) +struct omap_mux_conf; +static void smsh_config(struct omap_mux_conf *, int, int); +#endif +#if defined(OVERO) || defined(DUOVERO) || defined(PEPPER) +static void __udelay(unsigned int); +#endif +#if defined(PEPPER) +static int read_i2c_device(const vaddr_t, uint16_t, uint8_t, int, uint8_t *); #endif #if defined(CPU_XSCALE_PXA250) + static struct pxa2x0_gpioconf pxa255dep_gpioconf[] = { /* Bluetooth module configuration */ { 7, GPIO_OUT | GPIO_SET }, /* power on */ @@ -169,9 +199,112 @@ static struct pxa2x0_gpioconf verdexdep_ { -1 } }; + +#elif defined(OMAP2) + +struct omap_mux_conf { + int offset; + uint32_t value; +/* OMAP3/4 register values */ +#define WAKEUPEVENT (1 << 15) +#define WAKEUPENABLE (1 << 14) +#define OFFMODEPULLTYPESELECT (1 << 13) +#define OFFMODEPULLUDENABLE (1 << 12) +#define OFFMODEOUTVALUE (1 << 11) +#define OFFMODEOUTENABLE (1 << 10) +#define OFFMODEENABLE (1 << 9) +#define INPUTENABLE (1 << 8) +#define PULLTYPESELECT (1 << 4) +#define PULLUDENABLE (1 << 3) +#define MUXMODE(n) ((n) & 0x7) + +/* Sitara AM3xxx register values */ +#define SLEWCTRL (1 << 6) +#define RXACTIVE (1 << 5) +#define PUTYPESEL (1 << 4) +#define PUDEN (1 << 3) +#define MMODE(n) ((n) & 0x7) +}; +struct omap_gpio_conf { + int pin; + enum { + conf_input = -1, + conf_output_0, + conf_output_1, + } conf; +}; + +static void gxio_omap_mux_config(const struct omap_mux_conf []); +static int gxio_omap_mux_config_address(const char *, unsigned long, + const struct omap_mux_conf[], + const struct omap_mux_conf[]); +static void gxio_omap_gpio_config(const struct omap_gpio_conf[]); +void gxio_omap_gpio_write(int, int); + +static const struct omap_mux_conf overo_mux_i2c3_conf[] = { + { 0x1c2, MUXMODE(0) | INPUTENABLE }, /* i2c3_scl */ + { 0x1c4, MUXMODE(0) | INPUTENABLE }, /* i2c3_sda */ + { -1 } +}; +static const struct omap_mux_conf overo_mux_mmchs2_conf[] = { + { 0x158, /* mmc2_clk */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x15a, /* mmc2_cmd */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x15c, /* mmc2_dat0 */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x15e, /* mmc2_dat1 */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x160, /* mmc2_dat2 */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x162, /* mmc2_dat3 */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } +}; +static const struct omap_mux_conf overo_mux_wireless_conf[] = { + { 0x0b4, MUXMODE(4) }, /* gpio_54:BT_nPOWERON*/ + { 0x0bc, MUXMODE(4) | INPUTENABLE }, /* gpio_58: WIFI_IRQ */ + { 0x19c, MUXMODE(4) }, /* gpio_164:BT_nRESET */ + { 0x5e0, MUXMODE(4) }, /* gpio_16: W2W_nRESET*/ + { -1 } +}; + +static const struct omap_mux_conf duovero_mux_led_conf[] = { + { 0x116, MUXMODE(3) }, /* GPIO 122 */ + { -1 } +}; +static const struct omap_mux_conf duovero_mux_button_conf[] = { + { 0x114, /* GPIO 121 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } +}; + +static const struct omap_mux_conf pepper_mux_led_conf[] = { + { 0x850, MMODE(7) | PUDEN }, /* GPIO 52: Blue */ + { 0x854, MMODE(7) | PUDEN }, /* GPIO 53: Red */ + { -1 } +}; +static const struct omap_mux_conf pepper_mux_button_conf[] = { + { 0x858, MMODE(7) | PUTYPESEL | RXACTIVE }, /* GPIO 54 */ + { -1 } +}; +static const struct omap_mux_conf pepper_mux_mmchs3_conf[] = { + { 0x844, MMODE(3) | PUTYPESEL | RXACTIVE }, /* MMC2_DAT0 */ + { 0x848, MMODE(3) | PUTYPESEL | RXACTIVE }, /* MMC2_DAT1 */ + { 0x84c, MMODE(3) | PUTYPESEL | RXACTIVE }, /* MMC2_DAT2 */ + { 0x878, MMODE(3) | PUTYPESEL | RXACTIVE }, /* MMC2_DAT3 */ + { 0x888, MMODE(3) | PUTYPESEL | RXACTIVE }, /* MMC2_CMD */ + { 0x88c, MMODE(3) | PUTYPESEL | RXACTIVE }, /* MMC2_CLK */ + { -1 } +}; +static const struct omap_mux_conf pepper_mux_audio_codec_conf[] = { + { 0x840, MMODE(7) | PUDEN }, /* GPIO 48: #Reset */ + { -1 } +}; + #endif -static const struct gxioconf busheader_conf[] = { +static const struct gxioconf gxioconflist[] = { #if defined(GUMSTIX) { "basix", basix_config }, { "cfstix", cfstix_config }, @@ -189,8 +322,16 @@ static const struct gxioconf busheader_c { "wifistix", wifistix_config }, #elif defined(OVERO) { "chestnut43", chestnut_config }, + { "gallop43", gallop_config }, + { "summit", summit_config }, { "tobi", tobi_config }, { "tobi-duo", tobiduo_config }, +#elif defined(DUOVERO) + { "parlor", parlor_config }, +#elif defined(PEPPER) + { "43c", c_config }, + { "43r", r_config }, + { "dvi", dvi_config }, #endif { NULL } }; @@ -277,11 +418,12 @@ gxioprint(void *aux, const char *name) #endif +#if defined(GUMSTIX) /* * configure for GPIO pin and expansion boards. */ void -gxio_config_pin(void) +gxio_config(void) { #if defined(CPU_XSCALE_PXA250) struct pxa2x0_gpioconf *gumstix_gpioconf[] = { @@ -330,39 +472,264 @@ gxio_config_pin(void) #endif #endif } +#elif defined(OVERO) || defined(DUOVERO) || defined(PEPPER) +static void +gxio_omap_mux_config(const struct omap_mux_conf mux_conf[]) +{ +#if defined(OVERO) + const vaddr_t ctrlmod_base = OVERO_L4_CORE_VBASE + 0x2000; +#elif defined(DUOVERO) + const vaddr_t ctrlmod_base = DUOVERO_L4_CM_VBASE; +#elif defined(PEPPER) + const vaddr_t ctrlmod_base = PEPPER_PRCM_VBASE + 0x10000; +#endif + int i; + + for (i = 0; mux_conf[i].offset != -1; i++) +#if !defined(TI_AM335X) + ioreg16_write(ctrlmod_base + mux_conf[i].offset, + mux_conf[i].value); +#else + ioreg_write(ctrlmod_base + mux_conf[i].offset, + mux_conf[i].value); +#endif +} + +static int +gxio_omap_mux_config_address(const char *name, unsigned long address, + const struct omap_mux_conf mux_conf[], + const struct omap_mux_conf not_mux_conf[]) +{ + extern struct cfdata cfdata[]; + cfdata_t cf = &cfdata[0]; + + while (cf->cf_name != NULL) { + if (strcmp(name, cf->cf_name) == 0 && + address == cf->cf_loc[OBIOCF_ADDR]) { + gxio_omap_mux_config(mux_conf); + return 0; + } + cf++; + } + + if (not_mux_conf == NULL) + return -1; + + gxio_omap_mux_config(not_mux_conf); + return 0; +} + +#if defined(OVERO) +#define gpio_reg_read ioreg_read +#define gpio_reg_write ioreg_write +#elif defined(DUOVERO) || defined(PEPPER) +#define gpio_reg_read(a) ioreg_read((a) + GPIO_SIZE2) +#define gpio_reg_write(a, v) ioreg_write((a) + GPIO_SIZE2, (v)) +#endif + +static const vaddr_t gpio_bases[] = { +#if defined(OVERO) +#define OVERO_GPIO_VBASE(n) ((n) == 1 ? BASE(WAKEUP, n) : BASE(PERIPHERAL, n)) +#define GPIO(n) GPIO ## n ## _BASE_3530 +#define BASE(a, n) \ + (OVERO_L4_ ## a ## _VBASE + (GPIO(n) - OMAP3530_L4_ ## a ## _BASE)) + + GPIO1_BASE_3530, + GPIO2_BASE_3530, + GPIO3_BASE_3530, + GPIO4_BASE_3530, + GPIO5_BASE_3530, + GPIO6_BASE_3530, + +#elif defined(DUOVERO) +#define DUOVERO_GPIO_VBASE(n) ((n) == 1 ? BASE(WAKEUP, n) : BASE(PERIPHERAL, n)) +#define GPIO(n) GPIO ## n ## _BASE_4430 +#define BASE(a, n) \ + (DUOVERO_L4_ ## a ## _VBASE + (GPIO(n) - OMAP4430_L4_ ## a ## _BASE)) + + DUOVERO_GPIO_VBASE(1), + DUOVERO_GPIO_VBASE(2), + DUOVERO_GPIO_VBASE(3), + DUOVERO_GPIO_VBASE(4), + DUOVERO_GPIO_VBASE(5), + +#elif defined(PEPPER) +#define PEPPER_GPIO_VBASE(n) ((n) == 0 ? WAKEUP(n) : PERIPHERAL(n)) +#define GPIO(n) GPIO ## n ## _BASE_TI_AM335X +#define WAKEUP(n) (PEPPER_PRCM_VBASE + (GPIO(n) - OMAP2_CM_BASE)) +#define PERIPHERAL(n) \ + (PEPPER_L4_PERIPHERAL_VBASE + (GPIO(n) - TI_AM335X_L4_PERIPHERAL_BASE)) + + PEPPER_GPIO_VBASE(0), + PEPPER_GPIO_VBASE(1), + PEPPER_GPIO_VBASE(2), + PEPPER_GPIO_VBASE(3), +#endif +}; + +static void +gxio_omap_gpio_config(const struct omap_gpio_conf gpio_conf[]) +{ + vaddr_t gpio_base; + int mask, i; + + for (i = 0; gpio_conf[i].pin != -1; i++) { + gpio_base = gpio_bases[gpio_conf[i].pin / 32]; + mask = 1 << (gpio_conf[i].pin % 32); + switch (gpio_conf[i].conf) { + case conf_input: + ioreg_write(gpio_base + GPIO_OE, + ioreg_read(gpio_base + GPIO_OE) | mask); + break; + case conf_output_0: + ioreg_write(gpio_base + GPIO_OE, + ioreg_read(gpio_base + GPIO_OE) | ~mask); +#if 0 + ioreg_write(gpio_base + GPIO_CLEARDATAOUT, mask); +#else + ioreg_write(gpio_base + GPIO_DATAOUT, + ioreg_read(gpio_base + GPIO_DATAOUT) & ~mask); +#endif + break; + case conf_output_1: + ioreg_write(gpio_base + GPIO_OE, + ioreg_read(gpio_base + GPIO_OE) | ~mask); +#if 0 + ioreg_write(gpio_base + GPIO_SETDATAOUT, mask); +#else + ioreg_write(gpio_base + GPIO_DATAOUT, + ioreg_read(gpio_base + GPIO_DATAOUT) | mask); +#endif + break; + } + } +} + +void +gxio_omap_gpio_write(int pin, int val) +{ + vaddr_t gpio_base; + int mask; + + KASSERT(pin / 32 < __arraycount(gpio_bases)); + + gpio_base = gpio_bases[pin / 32]; + mask = 1 << (pin % 32); + if (val == 0) + ioreg_write(gpio_base + GPIO_CLEARDATAOUT, mask); + else + ioreg_write(gpio_base + GPIO_SETDATAOUT, mask); +} + +/* + * configure for MUX, GPIO. + */ +void +gxio_config(void) +{ + const struct omap_mux_conf *mux_conf[] = { +#if defined(OVERO) + overo_mux_i2c3_conf, + overo_mux_mmchs2_conf, + overo_mux_wireless_conf, +#elif defined(DUOVERO) + duovero_mux_led_conf, + duovero_mux_button_conf, +#elif defined(PEPPER) + pepper_mux_led_conf, + pepper_mux_button_conf, + pepper_mux_mmchs3_conf, + pepper_mux_audio_codec_conf, +#endif + }; + const struct omap_gpio_conf gpio_conf[] = { +#if defined(OVERO) + { 16, conf_output_0 }, /* Wireless: #Reset */ +#elif defined(PEPPER) + { 48, conf_output_0 }, /* Audio Codec: #Reset */ +#endif + { -1 } + }; + int i; + + for (i = 0; i < __arraycount(mux_conf); i++) + gxio_omap_mux_config(mux_conf[i]); + gxio_omap_gpio_config(gpio_conf); +} +#endif void gxio_config_expansion(char *expansion) { + int i, d, s; if (expansion == NULL) { printf("not specified 'expansion=' in the boot args.\n"); + s = -1; + } else { + for (i = 0; gxioconflist[i].name != NULL; i++) + if (strncasecmp(gxioconflist[i].name, expansion, + strlen(gxioconflist[i].name) + 1) == 0) + break; + if (gxioconflist[i].name == NULL) + printf("unknown expansion specified: %s\n", expansion); + s = i; + } +#ifdef GXIO_DEFAULT_EXPANSION + for (i = 0; gxioconflist[i].name != NULL; i++) + if (strncasecmp(gxioconflist[i].name, GXIO_DEFAULT_EXPANSION, + strlen(gxioconflist[i].name) + 1) == 0) + break; + d = i; +#else + d = -1; +#endif + printf("supported expansions:\n"); + for (i = 0; gxioconflist[i].name != NULL; i++) + printf(" %s%s\n", + gxioconflist[i].name, + i == d ? " (DEFAULT)" : ""); + + if (s < 0 || gxioconflist[i].name == NULL) { #ifdef GXIO_DEFAULT_EXPANSION - printf("configure default expansion (%s)\n", - GXIO_DEFAULT_EXPANSION); expansion = __UNCONST(GXIO_DEFAULT_EXPANSION); #else return; #endif } - gxio_config_gpio(busheader_conf, expansion); -} -static void -gxio_config_gpio(const struct gxioconf *gxioconflist, char *expansion) -{ - int i, rv; - - for (i = 0; i < strlen(expansion); i++) - expansion[i] = tolower(expansion[i]); - for (i = 0; gxioconflist[i].name != NULL; i++) { - rv = strncmp(expansion, gxioconflist[i].name, - strlen(gxioconflist[i].name) + 1); - if (rv == 0) { - gxioconflist[i].config(); - break; - } +#if defined(PEPPER) + if (s < 0) { + struct pepper_board_id { + unsigned int device_vendor; +#define GUMSTIX_PEPPER 0x30000200 /* 1st gen */ +#define GUMSTIX_PEPPER_DVI 0x31000200 /* DVI and newer */ + unsigned char revision; + unsigned char content; + char fab_revision[8]; + char env_var[16]; + char env_setting[64]; + } id; + const vaddr_t i2c_base = PEPPER_PRCM_VBASE + 0xb000; + const uint8_t eeprom = 0x50; + const uint8_t len = sizeof(id); + int rv; + + rv = read_i2c_device(i2c_base, eeprom, 0x00, len, (void *)&id); + if (rv == 0) + if (id.device_vendor == GUMSTIX_PEPPER) { + printf("configure auto detected expansion" + " (pepper)\n"); + pepper_config(); + return; + } } +#endif + + printf("configure %s expansion (%s)\n", + (s < 0 || gxioconflist[i].name == NULL) ? "default" : "specified", + expansion); + gxioconflist[(s < 0 || gxioconflist[i].name == NULL) ? d : s].config(); } @@ -592,72 +959,236 @@ wifistix_cf_config(void) static void eth0_config(void) { - extern struct cfdata cfdata[]; - cfdata_t cf = &cfdata[0]; - /* * ETH0 connects via CS5. It use GPIO 176 for IRQ. * Also GPIO 64 is NRESET. - * - * Basically use current settings by U-Boot. - * However remap physical address to configured address. */ - while (cf->cf_name != NULL) { - if (strcmp(cf->cf_name, "smsh") == 0 && - cf->cf_loc[GPMCCF_INTR] == PIC_MAXSOURCES + 176) - break; - cf++; - } - if (cf->cf_name == NULL || - cf->cf_loc[GPMCCF_ADDR] == GPMCCF_ADDR_DEFAULT) - return; - - ioreg_write(OVERO_GPMC_VBASE + GPMC_CONFIG7_5, - GPMC_CONFIG7_CSVALID | - GPMC_CONFIG7(GPMC_CONFIG7_MASK_16M, cf->cf_loc[GPMCCF_ADDR])); - - /* - * Maybe need NRESET and delay(9). - * However delay(9) needs to attach mputmr. - */ + smsh_config(NULL, 176, 64); } static void eth1_config(void) { - extern struct cfdata cfdata[]; - cfdata_t cf = &cfdata[0]; + struct omap_mux_conf eth1_mux_conf[] = { + { 0x0d2, MUXMODE(4) | INPUTENABLE }, + { -1 } + }; /* * ETH1 connects via CS4. It use GPIO 65 for IRQ. - * - * Basically use current settings by U-Boot. - * However remap physical address to configured address. */ - while (cf->cf_name != NULL) { - if (strcmp(cf->cf_name, "smsh") == 0 && - cf->cf_loc[GPMCCF_INTR] == PIC_MAXSOURCES + 65) - break; - cf++; + smsh_config(eth1_mux_conf, 65, 64); +} + +static void +dvi_config(void) +{ + static const struct omap_mux_conf overo_mux_dvi_conf[] = { + { 0x0d4, MUXMODE(0) }, /* dss_pclk */ + { 0x0d6, MUXMODE(0) }, /* dss_pclk */ + { 0x0d8, MUXMODE(0) }, /* dss_pclk */ + { 0x0da, MUXMODE(0) }, /* dss_pclk */ + { 0x0dc, MUXMODE(0) }, /* dss_pclk */ + { 0x0de, MUXMODE(0) }, /* dss_pclk */ + { 0x0e0, MUXMODE(0) }, /* dss_pclk */ + { 0x0e2, MUXMODE(0) }, /* dss_pclk */ + { 0x0e4, MUXMODE(0) }, /* dss_pclk */ + { 0x0e6, MUXMODE(0) }, /* dss_pclk */ + { 0x0e8, MUXMODE(0) }, /* dss_pclk */ + { 0x0ea, MUXMODE(0) }, /* dss_pclk */ + { 0x0ec, MUXMODE(0) }, /* dss_pclk */ + { 0x0ee, MUXMODE(0) }, /* dss_pclk */ + { 0x0f0, MUXMODE(0) }, /* dss_pclk */ + { 0x0f2, MUXMODE(0) }, /* dss_pclk */ + { 0x0f4, MUXMODE(0) }, /* dss_pclk */ + { 0x0f6, MUXMODE(0) }, /* dss_pclk */ + { 0x0f8, MUXMODE(0) }, /* dss_pclk */ + { 0x0fa, MUXMODE(0) }, /* dss_pclk */ + { 0x0fc, MUXMODE(0) }, /* dss_pclk */ + { 0x0fe, MUXMODE(0) }, /* dss_pclk */ + { 0x100, MUXMODE(0) }, /* dss_pclk */ + { 0x102, MUXMODE(0) }, /* dss_pclk */ + { 0x104, MUXMODE(0) }, /* dss_pclk */ + { 0x106, MUXMODE(0) }, /* dss_pclk */ + { 0x108, MUXMODE(0) }, /* dss_pclk */ + { 0x10a, MUXMODE(0) }, /* dss_pclk */ + { -1 } + }; + + gxio_omap_mux_config(overo_mux_dvi_conf); +} + +static void +lcd_config(char type) +{ + static const struct omap_mux_conf overo_mux_mcspi1_conf[] = { + { 0x1c8, MUXMODE(0) | INPUTENABLE }, /* mcspi1_clk */ + { 0x1ca, MUXMODE(0) | INPUTENABLE }, /* mcspi1_simo*/ + { 0x1cc, MUXMODE(0) | INPUTENABLE }, /* mcspi1_somi*/ + { 0x1ce, MUXMODE(0) | INPUTENABLE }, /* mcspi1_cs0 */ + { 0x1d0, MUXMODE(0) | INPUTENABLE }, /* mcspi1_cs1 */ + { -1 } + }; + static const struct omap_mux_conf overo_mux_ads7846_conf[] = { + { 0x138, /* gpio_114: NPENIRQ */ + MUXMODE(4) | PULLUDENABLE | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf overo_mux_lcd_conf[] = { + { 0x174, MUXMODE(4) }, /* gpio_144: DISPLAY_EN */ + { 0x176, MUXMODE(4) }, /* gpio_145: Brightness */ + { -1 } + }; + + static const struct omap_gpio_conf overo_gpio_lcd_conf[] = { + { 144, conf_output_0 }, /* DISPLAY_EN */ + { 145, conf_output_0 }, /* Brightness */ + { -1 } + }; + + dvi_config(); + if (type != 'C') { + gxio_omap_mux_config(overo_mux_mcspi1_conf); + gxio_omap_mux_config(overo_mux_ads7846_conf); } - if (cf->cf_name == NULL || - cf->cf_loc[GPMCCF_ADDR] == GPMCCF_ADDR_DEFAULT) - return; + gxio_omap_mux_config(overo_mux_lcd_conf); - ioreg_write(OVERO_GPMC_VBASE + GPMC_CONFIG7_4, - GPMC_CONFIG7_CSVALID | - GPMC_CONFIG7(GPMC_CONFIG7_MASK_16M, cf->cf_loc[GPMCCF_ADDR])); + gxio_omap_gpio_config(overo_gpio_lcd_conf); +} - /* ETH1 is sure to be reset with ETH0. */ +enum { + uart1_if_exists = 0, + force_uart1 +}; +static void +header_40pin_config(int uart1) +{ + static const struct omap_mux_conf overo_mux_40pin_header_conf[] = { + /* + * 1: GND + * 2: VCC_3.3 + * 3: GPIO171_SPI1_CLK + * 4: GPIO114_SPI1_NIRQ + * 5: GPIO172_SPI1_MOSI + * 6: GPIO174_SPI1_CS0 + * 7: GPIO173_SPI1_MISO + * 8: GPIO175_SPI1_CS1 + * 9: GPIO151_RXD1 + * 10: GPIO148_TXD1 + * 11: SYS_EN + * 12: VBACKUP + * 13: GPIO0_WAKEUP + * 14: POWERON + * 15: GND + * 16: VCC_1.8 + * 17: GPIO128_GPS_PPS + * 18: GPIO127_TS_IRQ + * 19: GPIO170_HDQ_1WIRE + * 20: GPIO163_IR_CTS3 + * 21: GPIO165_IR_RXD3 (console) + * 22: GPIO166_IR_TXD3 (console) + * 23: GPIO184_SCL3 (system eeprom) + * 24: GPIO185_SDA3 (system eeprom) + * 25: GND + * 26: VCC_1.8 + * 27: GPIO146_PWM11 + * 28: GPIO145_PWM10 + * 29: GPIO147_PWM8 + * 30: GPIO144_PWM9 + * 31: PWM0 (TPS65950) + * 32: PWM1 (TPS65950) + * 33: ADCIN7 (TPS65950) + * 34: ADCIN2 (TPS65950) + * 35: ADCIN6 (TPS65950) + * 36: ADCIN5 (TPS65950) + * 37: AGND (TPS65950) + * 38: ADCIN3 (TPS65950) + * 39: ADCIN4 (TPS65950) + * 40: VIN (TPS65950) + */ + + { 0x152, MUXMODE(4) | INPUTENABLE }, /* gpio_127 */ + { 0x154, MUXMODE(4) | INPUTENABLE }, /* gpio_128 */ + { 0x174, MUXMODE(4) | INPUTENABLE }, /* gpio_144 */ + { 0x176, MUXMODE(4) | INPUTENABLE }, /* gpio_145 */ + { 0x178, MUXMODE(4) | INPUTENABLE }, /* gpio_146 */ + { 0x17a, MUXMODE(4) | INPUTENABLE }, /* gpio_147 */ + { 0x19a, MUXMODE(4) | INPUTENABLE }, /* gpio_163 */ + { -1 } + }; + static const struct omap_mux_conf overo_mux_uart1_conf[] = { + { 0x17c, MUXMODE(0) }, /* uart1_tx */ + { 0x182, MUXMODE(0) | INPUTENABLE }, /* uart1_rx */ + { -1 } + }; + static const struct omap_mux_conf overo_mux_no_uart1_conf[] = { + { 0x17c, MUXMODE(4) | INPUTENABLE }, /* gpio_148 */ + { 0x182, MUXMODE(4) | INPUTENABLE }, /* gpio_151 */ + { -1 } + }; + static const struct omap_mux_conf overo_mux_hdq_conf[] = { +#if 0 + { 0x1c4, MUXMODE(0) | ??? | INPUTENABLE }, /* hdq_sio */ +#endif + { -1 } + }; + static const struct omap_mux_conf overo_mux_no_hdq_conf[] = { + { 0x1c4, MUXMODE(4) | INPUTENABLE }, /* gpio_170 */ + { -1 } + }; + + gxio_omap_mux_config(overo_mux_40pin_header_conf); + if (uart1 == force_uart1) + gxio_omap_mux_config(overo_mux_uart1_conf); + else + gxio_omap_mux_config_address("com", 0x4806a000, + overo_mux_uart1_conf, overo_mux_no_uart1_conf); + gxio_omap_mux_config_address("hdq", 0x480b2000, + overo_mux_hdq_conf, overo_mux_no_hdq_conf); } static void chestnut_config(void) { + static const struct omap_mux_conf chestnut_mux_conf[] = { + { 0x5ec, MUXMODE(4) }, /* gpio_22: LED (Blue)*/ + { 0x5ee, MUXMODE(4) | INPUTENABLE }, /* gpio_23: Button */ + { 0x5dc, MUXMODE(4) | INPUTENABLE }, /* gpio_14: Button */ + { -1 } + }; eth0_config(); + lcd_config('R'); + + header_40pin_config(uart1_if_exists); + gxio_omap_mux_config(chestnut_mux_conf); +} + +static void +gallop_config(void) +{ + static const struct omap_mux_conf gallop43_mux_conf[] = { + { 0x5ec, MUXMODE(4) }, /* gpio_22: LED (Blue)*/ + { 0x5ee, MUXMODE(4) | INPUTENABLE }, /* gpio_23: Button */ + { 0x5dc, MUXMODE(4) | INPUTENABLE }, /* gpio_14: Button */ + { -1 } + }; + + lcd_config('R'); + + header_40pin_config(force_uart1); + gxio_omap_mux_config(gallop43_mux_conf); +} + +static void +summit_config(void) +{ + + dvi_config(); + + header_40pin_config(uart1_if_exists); } static void @@ -665,6 +1196,9 @@ tobi_config(void) { eth0_config(); + dvi_config(); + + header_40pin_config(uart1_if_exists); } static void @@ -674,4 +1208,703 @@ tobiduo_config(void) eth0_config(); eth1_config(); } + +#elif defined(DUOVERO) + +static void +ehci_config(void) +{ + uint32_t val; + +#define SCRM_ALTCLKSRC 0xa110 +#define ALTCLKSRC_ENABLE_EXT (1 << 3) +#define ALTCLKSRC_ENABLE_INT (1 << 2) +#define ALTCLKSRC_MODE_MASK (3 << 0) +#define ALTCLKSRC_MODE_POWERDOWN (0 << 0) +#define ALTCLKSRC_MODE_ACTIVE (1 << 0) +#define ALTCLKSRC_MODE_BYPASS (2 << 0) +#define SCRM_AUXCLK3 0xa31c +#define AUXCLK3_CLKDIV(n) (((n) - 1) << 16) +#define AUXCLK3_CLKDIV_MASK (0xf << 16) +#define AUXCLK3_ENABLE (1 << 8) +#define AUXCLK3_SRCSELECT_MASK (3 << 1) +#define AUXCLK3_SRCSELECT_SYSCLK (0 << 1) +#define AUXCLK3_SRCSELECT_CORE (1 << 1) +#define AUXCLK3_SRCSELECT_PERDPLL (2 << 1) +#define AUXCLK3_SRCSELECT_ALTCLK (3 << 1) +#define AUXCLK3_POLARITY_LOW (0 << 0) +#define AUXCLK3_POLARITY_HIGH (1 << 0) + + /* Use the 1/2 auxiliary clock #3 of system clock. */ + val = ioreg_read(DUOVERO_L4_WAKEUP_VBASE + SCRM_AUXCLK3); + val &= ~(AUXCLK3_CLKDIV_MASK | AUXCLK3_SRCSELECT_MASK); + val |= (AUXCLK3_CLKDIV(2) | AUXCLK3_ENABLE | AUXCLK3_SRCSELECT_SYSCLK); + ioreg_write(DUOVERO_L4_WAKEUP_VBASE + SCRM_AUXCLK3, val); + + val = ioreg_read(DUOVERO_L4_WAKEUP_VBASE + SCRM_ALTCLKSRC); + val &= ~ALTCLKSRC_MODE_MASK; + val |= ALTCLKSRC_MODE_ACTIVE; + val |= (ALTCLKSRC_ENABLE_EXT | ALTCLKSRC_ENABLE_INT); + ioreg_write(DUOVERO_L4_WAKEUP_VBASE + SCRM_ALTCLKSRC, val); +} + +static void +parlor_config(void) +{ +#if 0 + static const struct omap_mux_conf parlor_mux_40pin_header_conf[] = { + /* + * 1: GND + * 2: GND + * 3: MCSPI1_CLK or GPIO 134 + * 4: MCSPI1_CS0 or GPIO 137 + * 5: MCSPI1_SIMO or GPIO 136 + * 6: MCSPI1_CS1 or GPIO 138 + * 7: MCSPI1_SOMI or GPIO 135 + * 8: MCSPI1_CS2 or GPIO 139 + * 9: HDQ_SIO or GPIO 127 + * 10: MCSPI1_CS3 or GPIO 140 + * 11: SDMMC3_CMD or GPIO ??? + * 12: I2C2_SCL or GPIO 128 + * 13: SDMMC3_CLK or GPIO ??? + * 14: I2C2_SDA or GPIO 129 + * 15: UART2_TX or SDMMC3_DAT1 or GPIO 126 + * 16: PMIC_PWM2 (TWL6030) + * 17: UART2_RX or SDMMC3_DAT0 or GPIO 125 + * 18: PMIC_PWM1 (TWL6030) + * 19: BSP2_CLKX or GPIO 110 + * 20: BSP2_FSX or GPIO 113 + * 21: BSP2_DX or GPIO 112 + * 22: BSP2_DR or GPIO 111 + * 23: BSP2_CLKS or GPIO 118 + * 24: FREF1 + * 25: MCSPI4_SOMI or GPIO 153 + * 26: PMIC_NRESWARN + * 27: MCSPI4_SIMO or GPIO 152 + * 28: SYSEN + * 29: MCSPI4_CLK or GPIO 151 + * 30: PWRON + * 31: MCSPI4_CS0 or GPIO 154 + * 32: REGEN1 + * 33: ADCIN3 (TWL6030) + * 34: VCC_1.0 + * 35: ADCIN4_VREF (TWL6030) + * 36: VDD_VAUX2 + * 37: ADCIN4 (TWL6030) + * 38: VCC_3.3 + * 39: ADCIN5 (TWL6030) + * 40: V_BATT_5 + */ + { -1 } + }; +#endif + static const struct omap_mux_conf parlor_mux_mcspi1_conf[] = { +#if 0 + { 0x132, /* 3: MCSPI1_CLK */ + MUXMODE(0) | ??? }, + { 0x138, /* 4: MCSPI1_CS0 */ + MUXMODE(0) | ??? }, + { 0x136, /* 5: MCSPI1_SIMO */ + MUXMODE(0) | ??? }, + { 0x13a, /* 6: MCSPI1_CS1 */ + MUXMODE(0) | ??? }, + { 0x134, /* 7: MCSPI1_SOMI */ + MUXMODE(0) | ??? | INPUTENABLE }, + { 0x13c, /* 8: MCSPI1_CS2 */ + MUXMODE(0) | ??? }, + { 0x13e, /* 10: MCSPI1_CS3 */ + MUXMODE(0) | ??? }, +#endif + { -1 } + }; + static const struct omap_mux_conf parlor_mux_no_mcspi1_conf[] = { + { 0x132, /* 3: GPIO 134 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x138, /* 4: GPIO 137 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x136, /* 5: GPIO 136 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x13a, /* 6: GPIO 138 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x134, /* 7: GPIO 135 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x13c, /* 8: GPIO 139 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x13e, /* 10: GPIO 140 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf parlor_mux_hdq_conf[] = { +#if 0 + { 0x120, /* 9: HDQ_SIO */ + MUXMODE(0) | ??? | INPUTENABLE }, +#endif + { -1 } + }; + static const struct omap_mux_conf parlor_mux_no_hdq_conf[] = { + { 0x120, /* 9: GPIO_127 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf parlor_mux_i2c2_conf[] = { + { 0x126, /* 12: I2C2_SCL */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x128, /* 14: I2C2_SDA */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf parlor_mux_no_i2c2_conf[] = { + { 0x126, /* 12: GPIO 128 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x128, /* 14: GPIO 129 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf parlor_mux_sdmmc3_conf[] = { +#if 0 +11 SDMMC3_CMD DuoVero J2 A15 <- omap pin AG10 + MUXMODE(1) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, +13 SDMMC3_CLK DuoVero J2 A16 <- omap pin AE9 + MUXMODE(1) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, +#endif + { 0x11c, /* 17: SDMMC3_DAT0 */ + MUXMODE(1) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x11e, /* 15: SDMMC3_DAT1 */ + MUXMODE(1) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf parlor_mux_uart2_conf[] = { + { 0x11c, /* 17: UART2_RX */ + MUXMODE(0) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x11e, + MUXMODE(0) | PULLUDENABLE }, /* 15: UART2_TX */ + { -1 } + }; + static const struct omap_mux_conf parlor_mux_no_uart2_conf[] = { + { 0x11c, /* 17: GPIO 125 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x11e, /* 15: GPIO 126 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf parlor_mux_bsp2_conf[] = { + { 0x0f6, /* 19: BSP2_CLKX */ + MUXMODE(0) | INPUTENABLE }, + { 0x0fc, /* 20: BSP2_FSX */ + MUXMODE(0) | INPUTENABLE }, + { 0x0fa, /* 21: BSP2_DX */ + MUXMODE(0) | PULLUDENABLE }, + { 0x0f8, /* 22: BSP2_DR */ + MUXMODE(0) | PULLUDENABLE | INPUTENABLE }, + { 0x10e, /* 23: BSP2_CLKS */ + MUXMODE(0) | PULLUDENABLE | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf parlor_mux_no_bsp2_conf[] = { + { 0x0f6, /* 19: GPIO 110 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x0fc, /* 20: GPIO 113 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x0fa, /* 21: GPIO 112 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x0f8, /* 22: GPIO 111 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x10e, /* 23: GPIO 118 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } + }; + static const struct omap_mux_conf parlor_mux_mcspi4_conf[] = { +#if 0 + { 0x158, /* 25: MCSPI4_SOMI */ + MUXMODE(0) | ??? | INPUTENABLE }, + { 0x156, /* 27: MCSPI4_SIMO */ + MUXMODE(0) | ??? }, + { 0x154, /* 29: MCSPI4_CLK */ + MUXMODE(0) | ??? }, + { 0x15a, /* 31: MCSPI4_CS0 */ + MUXMODE(0) | ??? }, +#endif + { -1 } + }; + static const struct omap_mux_conf parlor_mux_no_mcspi4_conf[] = { + { 0x158, /* 25: GPIO 153 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x156, /* 27: GPIO 152 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x154, /* 29: GPIO 151 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { 0x15a, /* 31: GPIO 154 */ + MUXMODE(3) | PULLUDENABLE | PULLTYPESELECT | INPUTENABLE }, + { -1 } + }; + + /* + * ETH0 connects via CS5. It use GPIO 44 for IRQ. + * Also GPIO 45 is NRESET. + */ + smsh_config(NULL, 44, 45); + + ehci_config(); + + gxio_omap_mux_config_address("mcspi", 0x48098000, + parlor_mux_mcspi1_conf, parlor_mux_no_mcspi1_conf); + gxio_omap_mux_config_address("hdq", 0x480b2000, + parlor_mux_hdq_conf, parlor_mux_no_hdq_conf); + gxio_omap_mux_config_address("tiiic", 0x48072000, + parlor_mux_i2c2_conf, parlor_mux_no_i2c2_conf); + if (gxio_omap_mux_config_address("sdhc", 0x480ad000, + parlor_mux_sdmmc3_conf, NULL) != 0) + gxio_omap_mux_config_address("com", 0x4806c000, + parlor_mux_uart2_conf, parlor_mux_no_uart2_conf); + gxio_omap_mux_config_address("mcbsp", 0x49024000, + parlor_mux_bsp2_conf, parlor_mux_no_bsp2_conf); + gxio_omap_mux_config_address("mcspi", 0x480ba000, + parlor_mux_mcspi4_conf, parlor_mux_no_mcspi4_conf); +} + +#elif defined(PEPPER) + +static void +lcd_config(void) +{ + static const struct tifb_panel_info panel_lcd = { + .panel_tft = 1, + .panel_mono = false, + .panel_bpp = 24, + + .panel_pxl_clk = 18400000, + .panel_width = 480, + .panel_height = 272, + .panel_hfp = 8, + .panel_hbp = 4, + .panel_hsw = 41, + .panel_vfp = 4, + .panel_vbp = 2, + .panel_vsw = 10, + .panel_invert_hsync = 0, + .panel_invert_vsync = 0, + + .panel_ac_bias = 255, + .panel_ac_bias_intrpt = 0, + .panel_dma_burst_sz = 16, + .panel_fdd = 0x80, + .panel_sync_edge = 0, + .panel_sync_ctrl = 1, + .panel_tft_alt_mode = 0, + .panel_invert_pxl_clk = 0, + }; + static const struct omap_mux_conf pepper_mux_lcd_conf[] = { + /* + * LCD_DATA[0-23] configures in tifb.c + */ + + { 0x8e0, MMODE(0) | PUDEN }, /* LCD_VSYNC */ + { 0x8e4, MMODE(0) | PUDEN }, /* LCD_HSYNC */ + { 0x8e8, MMODE(0) | PUDEN }, /* LCD_PCLK */ + { 0x8ec, MMODE(0) | PUDEN }, /* LCD_AC_BIAS_EN */ + + { 0x86c, MMODE(7) | PUTYPESEL }, /* GPIO 59: Enable */ + { -1 } + }; + + if (gxio_omap_mux_config_address("tifb", 0x4830e000, + pepper_mux_lcd_conf, NULL) == 0) { + extern const struct tifb_panel_info *tifb_panel_info; + extern bool use_tps65217_wled; + + tifb_panel_info = &panel_lcd; + use_tps65217_wled = true; + } +} + +static void +pepper43_config(void) +{ + static const struct omap_mux_conf pepper43_mux_wilink8_conf[] = { + /* TI WiLink 8 */ + { 0x800, MMODE(7) | PUTYPESEL }, /* GPIO 32: Bluetooth */ + { 0x804, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 33: irq */ + { 0x860, MMODE(7) | PUTYPESEL }, /* GPIO 56: WiFi */ + { -1 } + }; + static const struct omap_mux_conf pepper43_mux_i2c1_conf[] = { + { 0x968, MMODE(3) | PUTYPESEL | RXACTIVE }, /* I2C1_SDA */ + { 0x96c, MMODE(3) | PUTYPESEL | RXACTIVE }, /* I2C1_SCL */ + { -1 } + }; + static const struct omap_mux_conf pepper43_mpu9150_conf[] = { + /* MPU9150 at I2C1 */ + { 0x808, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 34: IRQ */ + { 0x898, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 68 */ + { 0x870, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 30 */ + { -1 } + }; + static const struct omap_mux_conf pepper43_mux_20pin_header_conf[] = { + { 0x85c, MMODE(7) | PUDEN | RXACTIVE }, /* 1: GPIO 55 */ + { 0x80c, MMODE(7) | PUDEN | RXACTIVE }, /* 2: GPIO 35 */ + { 0x810, MMODE(7) | PUDEN | RXACTIVE }, /* 3: GPIO 36 */ + { 0x814, MMODE(7) | PUDEN | RXACTIVE }, /* 4: GPIO 37 */ + { 0x818, MMODE(7) | PUDEN | RXACTIVE }, /* 5: GPIO 38 */ + { 0x81c, MMODE(7) | PUDEN | RXACTIVE }, /* 6: GPIO 39 */ + { 0x87c, MMODE(7) | PUDEN | RXACTIVE }, /* 7: GPIO 61 */ + { 0x880, MMODE(7) | PUDEN | RXACTIVE }, /* 8: GPIO 62 */ + { 0x884, MMODE(7) | PUDEN | RXACTIVE }, /* 9: GPIO 63 */ + { 0x9e4, MMODE(7) | PUDEN | RXACTIVE }, /* 10: GPIO 103 */ + { 0x9e8, MMODE(7) | PUDEN | RXACTIVE }, /* 11: GPIO 104 */ + { 0x9b0, MMODE(7) | PUDEN | RXACTIVE }, /* 12: GPIO 19 */ +#if 0 /* UART3 or GPIO */ + { 0x964, MMODE(7) | PUDEN | RXACTIVE }, /* 13: GPIO 7 */ + { 0x960, MMODE(7) | PUDEN | RXACTIVE }, /* 14: GPIO 6 */ +#endif +#if 0 /* UART2 or GPIO */ + { 0x910, MMODE(7) | PUDEN | RXACTIVE }, /* 15: GPIO 98 */ + { 0x90c, MMODE(7) | PUDEN | RXACTIVE }, /* 16: GPIO 97 */ +#endif + /* 17: VCC 5v */ + /* 18: VCC 3.3v */ + /* 19: GND */ + /* 20: GND */ + { -1 } + }; + static const struct omap_mux_conf pepper43_mux_uart2_conf[] = { + { 0x90c, MMODE(6) | PUTYPESEL | RXACTIVE }, /* UART2_RXD */ + { 0x910, MMODE(6) | PUDEN }, /* UART2_TXD */ + { -1 } + }; + static const struct omap_mux_conf pepper43_mux_no_uart2_conf[] = { + { 0x90c, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 97 */ + { 0x910, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 98 */ + { -1 } + }; + static const struct omap_mux_conf pepper43_mux_uart3_conf[] = { + { 0x960, MMODE(1) | PUTYPESEL | RXACTIVE }, /* UART3_RXD */ + { 0x964, MMODE(1) | PUDEN }, /* UART3_TXD */ + { -1 } + }; + static const struct omap_mux_conf pepper43_mux_no_uart3_conf[] = { + { 0x960, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 6 */ + { 0x964, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 7 */ + { -1 } + }; + + static const struct omap_mux_conf *pepper43_mux_conf[] = { + pepper43_mux_wilink8_conf, + pepper43_mux_i2c1_conf, + pepper43_mpu9150_conf, + pepper43_mux_20pin_header_conf, + }; + + static const struct omap_gpio_conf pepper43_gpio_wl18xx_conf[] = { + { 32, conf_output_0 }, /* #Reset: Bluetooth */ + { 56, conf_output_0 }, /* #Reset: WiFi */ + { -1 } + }; + int i; + + lcd_config(); + + for (i = 0; i < __arraycount(pepper43_mux_conf); i++) + gxio_omap_mux_config(pepper43_mux_conf[i]); + gxio_omap_gpio_config(pepper43_gpio_wl18xx_conf); + +#if 0 + ioreg_write(gpio1_base + GPIO_SIZE2 + GPIO_OE, /* GPIO 52 (Blue) */ + ioreg_read(gpio1_base + GPIO_SIZE2 + GPIO_OE) & ~(1 << 20)); + ioreg_write(gpio1_base + GPIO_SIZE2 + GPIO_DATAOUT, + ioreg_read(gpio1_base + GPIO_SIZE2 + GPIO_DATAOUT) | (1 << 20)); + ioreg_write(gpio1_base + GPIO_SIZE2 + GPIO_OE, /* GPIO 53 (Red) */ + ioreg_read(gpio1_base + GPIO_SIZE2 + GPIO_OE) & ~(1 << 21)); + ioreg_write(gpio1_base + GPIO_SIZE2 + GPIO_DATAOUT, + ioreg_read(gpio1_base + GPIO_SIZE2 + GPIO_DATAOUT) | (1 << 21)); +#endif + + gxio_omap_mux_config_address("com", 0x48024000, + pepper43_mux_uart2_conf, pepper43_mux_no_uart2_conf); + gxio_omap_mux_config_address("com", 0x481a6000, + pepper43_mux_uart3_conf, pepper43_mux_no_uart3_conf); +} + +static void +pepper_config(void) +{ + static const struct omap_mux_conf pepper_mux_button2_conf[] = { + { 0x85c, MMODE(7) | PUTYPESEL | RXACTIVE }, /* GPIO 55 */ + { -1 } + }; + static const struct omap_mux_conf pepper_mux_i2c1_conf[] = { + { 0x90c, MMODE(3) | PUTYPESEL | RXACTIVE }, /* I2C1_SDA */ + { 0x910, MMODE(3) | PUTYPESEL | RXACTIVE }, /* I2C1_SCL */ + { -1 } + }; + static const struct omap_mux_conf pepper_mux_wi2wi_conf[] = { + { 0x9b4, MMODE(3) | PUDEN }, /* CLKOUT2 */ + /* Wi2Wi */ + { 0x860, MMODE(7) | PUTYPESEL }, /* GPIO 56: nReset */ + { 0x870, MMODE(7) | PUTYPESEL }, /* GPIO 30: nPower */ + { -1 } + }; + static const struct omap_mux_conf pepper_mux_uart1_conf[] = { + { 0x978, MMODE(0) | PUTYPESEL | RXACTIVE }, /* UART1_CTSn */ + { 0x97c, MMODE(0) }, /* UART1_RTSn */ + { 0x980, MMODE(0) | PUTYPESEL | RXACTIVE }, /* UART1_RXD */ + { 0x984, MMODE(0) }, /* UART1_TXD */ + { -1 } + }; + static const struct omap_mux_conf pepper_mux_no_uart1_conf[] = { + { 0x978, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 12 */ + { 0x97c, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 13 */ + { 0x980, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 14 */ + { 0x984, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 15 */ + { -1 } + }; + static const struct omap_mux_conf *pepper_mux_conf[] = { + pepper_mux_button2_conf, + pepper_mux_i2c1_conf, + pepper_mux_wi2wi_conf, + }; + + int i; + + lcd_config(); + + for (i = 0; i < __arraycount(pepper_mux_conf); i++) + gxio_omap_mux_config(pepper_mux_conf[i]); + gxio_omap_mux_config_address("com", 0x48022000, + pepper_mux_uart1_conf, pepper_mux_no_uart1_conf); +} + +static void +c_config(void) +{ + static const struct omap_mux_conf pepper43c_mux_ft5306_conf[] = { + /* FT5306 at I2C2 */ + { 0x9b4, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 20 */ + { 0x95c, MMODE(7) | PUDEN }, /* GPIO 5 */ + { -1 } + }; + static const struct omap_mux_conf pepper43c_mux_i2c2_conf[] = { + { 0x950, MMODE(2) | PUTYPESEL | RXACTIVE }, /* I2C2_SDA */ + { 0x954, MMODE(2) | PUTYPESEL | RXACTIVE }, /* I2C2_SCL */ + { -1 } + }; + static const struct omap_mux_conf *pepper43c_mux_conf[] = { + pepper43c_mux_ft5306_conf, + pepper43c_mux_i2c2_conf, + }; + + static const struct omap_gpio_conf pepper43c_gpio_ft5306_conf[] = { + { 5, conf_output_0 }, /* #Reset */ + { -1 } + }; + int i; + + pepper43_config(); + + for (i = 0; i < __arraycount(pepper43c_mux_conf); i++) + gxio_omap_mux_config(pepper43c_mux_conf[i]); + gxio_omap_gpio_config(pepper43c_gpio_ft5306_conf); +} + +static void +dvi_config(void) +{ + /* XXXX: hmm... mismatch found in Linux's dts and pubs.gumstix.org... */ + + extern struct cfdata cfdata[]; + extern const struct tifb_panel_info *tifb_panel_info; + + static const struct tifb_panel_info panel_dvi = { + .panel_tft = 1, + .panel_mono = false, + .panel_bpp = 16, + + .panel_pxl_clk = 63500000, + .panel_width = 1024, + .panel_height = 768, + .panel_hfp = 8, + .panel_hbp = 4, + .panel_hsw = 41, + .panel_vfp = 4, + .panel_vbp = 2, + .panel_vsw = 10, + .panel_invert_hsync = 0, + .panel_invert_vsync = 0, + + .panel_ac_bias = 255, + .panel_ac_bias_intrpt = 0, + .panel_dma_burst_sz = 16, + .panel_fdd = 0x80, + .panel_sync_edge = 0, + .panel_sync_ctrl = 1, + .panel_invert_pxl_clk = 0, + }; + cfdata_t cf = &cfdata[0]; + + /* Disable wireless module. */ + while (cf->cf_name != NULL) { + if (strcmp(cf->cf_name, "sdhc") == 0 && + strcmp(cf->cf_atname, "mainbus") == 0 && + cf->cf_loc[MAINBUSCF_BASE] == 0x47810000) { + if (cf->cf_fstate == FSTATE_NOTFOUND) + cf->cf_fstate = FSTATE_DNOTFOUND; + else if (cf->cf_fstate == FSTATE_STAR) + cf->cf_fstate = FSTATE_DSTAR; + } + cf++; + } + + tifb_panel_info = &panel_dvi; +} + +static void +r_config(void) +{ + static const struct omap_mux_conf pepper43r_mux_ads7846_conf[] = { + /* ADS7846 at McSPI0 */ + { 0x9b4, MMODE(7) | PUDEN | RXACTIVE }, /* GPIO 20: IRQ */ + { -1 } + }; + static const struct omap_mux_conf pepper43r_mux_spi0_conf[] = { + { 0x950, MMODE(0) | PUTYPESEL | RXACTIVE }, /* SPI0_SCLK */ + { 0x954, MMODE(0) | PUTYPESEL | RXACTIVE }, /* SPI0_D0 */ + { 0x958, MMODE(0) | PUTYPESEL | RXACTIVE }, /* SPI0_D1 */ + { 0x95c, MMODE(0) | PUTYPESEL | RXACTIVE }, /* SPI0_CS0 */ + { -1 } + }; + static const struct omap_mux_conf *pepper43r_mux_conf[] = { + pepper43r_mux_ads7846_conf, + pepper43r_mux_spi0_conf, + }; + int i; + + pepper43_config(); + + for (i = 0; i < __arraycount(pepper43r_mux_conf); i++) + gxio_omap_mux_config(pepper43r_mux_conf[i]); +} + +#endif + +#if defined(OVERO) || defined(DUOVERO) +static void +smsh_config(struct omap_mux_conf *smsh_mux_conf, int intr, int nreset) +{ + struct omap_gpio_conf smsh_gpio_conf[] = { + { intr, conf_input }, + { nreset, conf_output_0 }, + { -1 } + }; + + /* + * Basically use current settings by U-Boot. + * However remap physical address to configured address. + */ + + if (smsh_mux_conf != NULL) + gxio_omap_mux_config(smsh_mux_conf); + gxio_omap_gpio_config(smsh_gpio_conf); + __udelay(100000); + gxio_omap_gpio_write(nreset, 1); +} +#endif + +#if defined(OVERO) || defined(DUOVERO) || defined(PEPPER) +/* + * The delay for configuration time. + * This function use initialized timer by U-Boot. + */ +static void +__udelay(unsigned int usec) +{ +#if defined(OVERO) || defined(DUOVERO) +#define V_SCLK (26000000 >> 1) +#define TCRR 0x28 +#elif defined(PEPPER) +#define V_SCLK 24000000 +#define TCRR 0x3c +#endif +#define SYS_PTV 2 +#define TIMER_CLOCK (V_SCLK / (2 << SYS_PTV)) + + const vaddr_t timer_base = +#if defined(OVERO) + OVERO_L4_PERIPHERAL_VBASE + 0x32000; +#elif defined(DUOVERO) + DUOVERO_L4_PERIPHERAL_VBASE + 0x32000; +#elif defined(PEPPER) + PEPPER_L4_PERIPHERAL_VBASE + 0x40000; +#endif + long timo = usec * (TIMER_CLOCK / 1000) / 1000; + uint32_t now, last; + + last = ioreg_read(timer_base + TCRR); + while (timo > 0) { + now = ioreg_read(timer_base + TCRR); + if (last > now) + timo -= __BITS(0, 31) - last + now + 1; + else + timo -= now - last; + last = now; + } +} +#endif + +#if defined(PEPPER) +static int +read_i2c_device(const vaddr_t i2c_base, uint16_t sa, uint8_t addr, int len, + uint8_t *buf) +{ + uint16_t v; + int aok = 0, cnt = 0; + + ioreg16_write(i2c_base + OMAP2_I2C_IRQSTATUS, 0xffff); + v = ioreg16_read(i2c_base + OMAP2_I2C_IRQSTATUS_RAW); + while (v & I2C_IRQSTATUS_BB) { + ioreg16_write(i2c_base + OMAP2_I2C_IRQSTATUS, v); + __udelay(20); + v = ioreg16_read(i2c_base + OMAP2_I2C_IRQSTATUS_RAW); + } + ioreg16_write(i2c_base + OMAP2_I2C_IRQSTATUS, 0xffff); + + ioreg16_write(i2c_base + OMAP2_I2C_SA, sa); + ioreg16_write(i2c_base + OMAP2_I2C_CNT, sizeof(addr)); + ioreg16_write(i2c_base + OMAP2_I2C_CON, + I2C_CON_EN | I2C_CON_MST | I2C_CON_TRX | I2C_CON_STP | I2C_CON_STT); + while (1 /*CONSTCOND*/) { + __udelay(20); + v = ioreg16_read(i2c_base + OMAP2_I2C_IRQSTATUS_RAW); + if ((v & I2C_IRQSTATUS_XRDY) && aok == 0) { + aok = 1; + ioreg16_write(i2c_base + OMAP2_I2C_DATA, addr); + ioreg16_write(i2c_base + OMAP2_I2C_IRQSTATUS, + I2C_IRQSTATUS_XRDY); + } + if (v & I2C_IRQSTATUS_ARDY) { + ioreg16_write(i2c_base + OMAP2_I2C_IRQSTATUS, + I2C_IRQSTATUS_ARDY); + break; + } + } + + ioreg16_write(i2c_base + OMAP2_I2C_SA, sa); + ioreg16_write(i2c_base + OMAP2_I2C_CNT, len); + ioreg16_write(i2c_base + OMAP2_I2C_CON, + I2C_CON_EN | I2C_CON_MST | I2C_CON_STP | I2C_CON_STT); + while (1 /*CONSTCOND*/) { + v = ioreg16_read(i2c_base + OMAP2_I2C_IRQSTATUS_RAW); + if (v & I2C_IRQSTATUS_RRDY && + cnt < len) { + buf[cnt++] = ioreg16_read(i2c_base + OMAP2_I2C_DATA); + ioreg16_write(i2c_base + OMAP2_I2C_IRQSTATUS, + I2C_IRQSTATUS_RRDY); + } + if (v & I2C_IRQSTATUS_ARDY) { + ioreg16_write(i2c_base + OMAP2_I2C_IRQSTATUS, + I2C_IRQSTATUS_ARDY); + break; + } + } + ioreg16_write(i2c_base + OMAP2_I2C_IRQSTATUS, 0xffff); + return 0; +} #endif