From 2a1325206da5381292c2b268e248702c523cc927 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Wed, 22 Aug 2012 16:16:26 +0200 Subject: Initial Toradex Colibri T20 L4T R15 support. --- .cproject | 253 +++++ .project | 77 ++ .settings/org.eclipse.cdt.core.prefs | 8 + Makefile | 4 +- arch/arm/cpu/armv7/tegra-common/ap20.c | 22 +- arch/arm/cpu/armv7/tegra-common/board.c | 12 + arch/arm/cpu/armv7/tegra-common/clock.c | 7 +- arch/arm/cpu/armv7/tegra-common/display.c | 2 +- arch/arm/cpu/armv7/tegra-common/pwfm.c | 11 +- arch/arm/cpu/armv7/tegra3/warmboot_avp.c | 2 +- arch/arm/include/asm/arch-tegra/clk_rst.h | 2 +- arch/arm/include/asm/arch-tegra/tegra.h | 3 + arch/arm/include/asm/arch-tegra2/pmu.h | 2 + arch/arm/include/asm/arch-tegra2/tegra.h | 2 + arch/arm/include/asm/arch-tegra3/pmu.h | 2 + arch/arm/include/asm/arch-tegra3/pmu_core.h | 36 + arch/arm/include/asm/arch-tegra3/tegra.h | 2 + arch/arm/include/asm/global_data.h | 8 + arch/arm/lib/bootm.c | 3 +- board/nvidia/cardhu/tegra30.dtsi | 11 +- board/nvidia/common/board.c | 36 + board/nvidia/common/pmu.c | 1 - board/nvidia/harmony/tegra2-harmony.dts | 2 +- board/nvidia/seaboard/tegra250.dtsi | 11 +- board/toradex/colibri_t20/Makefile | 52 + board/toradex/colibri_t20/colibri_t20.c | 24 + board/toradex/colibri_t20/colibri_t20.dts | 239 +++++ board/toradex/colibri_t30/Makefile | 52 + board/toradex/colibri_t30/colibri_t30.c | 24 + board/toradex/colibri_t30/colibri_t30.dts | 130 +++ board/toradex/colibri_t30/pinmux-config-common.h | 404 ++++++++ board/toradex/common/Makefile | 60 ++ board/toradex/common/board.c | 911 ++++++++++++++++++ board/toradex/common/board.h | 52 + board/toradex/common/tegra2_nand.c | 1095 ++++++++++++++++++++++ board/toradex/common/tegra2_nand.h | 280 ++++++ board/toradex/common/ulpi_linux.c | 194 ++++ board/toradex/common/usb.c | 561 +++++++++++ boards.cfg | 3 + common/cmd_mtdparts.c | 5 +- common/cmd_nand.c | 2 +- common/cmd_ubi.c | 3 +- common/cmd_usb.c | 35 +- common/cmd_ximg.c | 28 +- common/fdt_decode.c | 19 +- disk/part.c | 6 +- disk/part_efi.c | 30 +- disk/part_efi.h | 4 + drivers/mtd/nand/nand_base.c | 7 + drivers/mtd/nand/nand_ids.c | 2 + drivers/mtd/ubi/vmt.c | 4 +- drivers/serial/ns16550.c | 3 + drivers/usb/eth/asix.c | 129 ++- drivers/usb/host/ehci-hcd.c | 4 +- drivers/video/tegra.c | 6 +- fs/jffs2/jffs2_1pass.c | 13 +- include/configs/cardhu.h | 17 +- include/configs/colibri_t20.h | 246 +++++ include/configs/colibri_t20_sdboot.h | 93 ++ include/configs/colibri_t30.h | 178 ++++ include/configs/harmony.h | 8 + include/configs/tegra-common.h | 1 + include/configs/tegra2-common.h | 7 +- include/configs/tegra3-common.h | 2 +- include/fdt_decode.h | 18 + include/u-boot/md5.h | 5 +- lib/lzo/lzo1x_decompress.c | 3 +- lib/md5.c | 4 +- 68 files changed, 5360 insertions(+), 122 deletions(-) create mode 100644 .cproject create mode 100644 .project create mode 100644 .settings/org.eclipse.cdt.core.prefs create mode 100644 arch/arm/include/asm/arch-tegra3/pmu_core.h create mode 100644 board/toradex/colibri_t20/Makefile create mode 100644 board/toradex/colibri_t20/colibri_t20.c create mode 100644 board/toradex/colibri_t20/colibri_t20.dts create mode 100644 board/toradex/colibri_t30/Makefile create mode 100644 board/toradex/colibri_t30/colibri_t30.c create mode 100644 board/toradex/colibri_t30/colibri_t30.dts create mode 100644 board/toradex/colibri_t30/pinmux-config-common.h create mode 100644 board/toradex/common/Makefile create mode 100644 board/toradex/common/board.c create mode 100644 board/toradex/common/board.h create mode 100644 board/toradex/common/tegra2_nand.c create mode 100644 board/toradex/common/tegra2_nand.h create mode 100644 board/toradex/common/ulpi_linux.c create mode 100644 board/toradex/common/usb.c create mode 100644 include/configs/colibri_t20.h create mode 100644 include/configs/colibri_t20_sdboot.h create mode 100644 include/configs/colibri_t30.h diff --git a/.cproject b/.cproject new file mode 100644 index 0000000000..fc69a41f55 --- /dev/null +++ b/.cproject @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + make + distclean + true + true + true + + + make + colibri_t20_config + true + true + true + + + make + colibri_t20_sdboot_config + true + true + true + + + make + -j3 + true + false + true + + + make + + colibri_t30_config + true + true + true + + + + diff --git a/.project b/.project new file mode 100644 index 0000000000..bbf23632df --- /dev/null +++ b/.project @@ -0,0 +1,77 @@ + + + u-boot-chromium + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 0000000000..1e4f0dd5d9 --- /dev/null +++ b/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,8 @@ +#Thu Jul 05 18:06:20 CEST 2012 +eclipse.preferences.version=1 +environment/project/0.273149272= +environment/project/0.273149272/PATH/delimiter=\: +environment/project/0.273149272/PATH/operation=append +environment/project/0.273149272/PATH/value=$HOME/dtc-v1.3.0 +environment/project/0.273149272/append=true +environment/project/0.273149272/appendContributed=true diff --git a/Makefile b/Makefile index d2835cdd78..db198ff526 100644 --- a/Makefile +++ b/Makefile @@ -220,8 +220,8 @@ LIBS += lib/chromeos/libchromeos.a LIBS += lib/vbexport/libvbexport.a endif -LIBS += board/$(VENDOR)/chromeos/libchromeos_board.a -LIBS += board/$(VENDOR)/vbexport/libvbexport_board.a +LIBS += board/nvidia/chromeos/libchromeos_board.a +LIBS += board/nvidia/vbexport/libvbexport_board.a LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \ "board/$(VENDOR)/common/lib$(VENDOR).o"; fi) LIBS += $(CPUDIR)/lib$(CPU).o diff --git a/arch/arm/cpu/armv7/tegra-common/ap20.c b/arch/arm/cpu/armv7/tegra-common/ap20.c index 517fba30b1..4f54dd6121 100644 --- a/arch/arm/cpu/armv7/tegra-common/ap20.c +++ b/arch/arm/cpu/armv7/tegra-common/ap20.c @@ -146,6 +146,7 @@ int ap20_get_num_cpus(void) return ap20_get_family() == TEGRA_FAMILY_T3x ? 4 : 2; } +/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */ int ap20_cpu_is_cortexa9(void) { u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0); @@ -180,7 +181,7 @@ static int pllx_set_rate(struct clk_pll *pll , u32 divn, u32 divm, u32 divp, bf_update(PLL_DIVM, reg, divm); bf_update(PLL_DIVN, reg, divn); bf_update(PLL_DIVP, reg, divp); - bf_update(PLL_BYPASS, reg, 0); + bf_update(PLL_BYPASS, reg, 0); /* Disable BYPASS */ writel(reg, &pll->pll_base); /* Set cpcon to PLLX_MISC */ @@ -197,6 +198,9 @@ static int pllx_set_rate(struct clk_pll *pll , u32 divn, u32 divm, u32 divp, return 0; } +/* U-Boot treats all errors as warnings, &clkrst->crc_pll[CLOCK_ID_XCPU] uses + a subscript out of range. The pragma disables the warning */ +#pragma GCC diagnostic warning "-Warray-bounds" void ap20_init_pllx(int slow) { struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; @@ -332,10 +336,10 @@ static void enable_cpu_power_rail(enum tegra_family_t family) if (family == TEGRA_FAMILY_T3x) { /* - * TODO(sjg): - * Fow now we do this here. We need to find out what this is + * TODO(sjg): + * For now we do this here. We need to find out what this is * doing, tidy up the code and find a better place for it. - */ + */ tegra_i2c_ll_write_addr(0x005a, 0x0002); tegra_i2c_ll_write_data(0x2328, 0x0a02); udelay(1000); @@ -384,11 +388,11 @@ void t30_init_clocks(void) { #if defined(CONFIG_TEGRA3) /* - * Sadly our clock functions don't support the V and W clocks of T30 - * yet, as well as a few other functions, so use low-level register - * access for now. This eventual removable of low-level code from - * ap20.c is the same process we went through for T20. - */ + * Sadly our clock functions don't support the V and W clocks of T30 + * yet, as well as a few other functions, so use low-level register + * access for now. This eventual removable of low-level code from + * ap20.c is the same process we went through for T20. + */ struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; diff --git a/arch/arm/cpu/armv7/tegra-common/board.c b/arch/arm/cpu/armv7/tegra-common/board.c index 5a57298db7..5f772b55b6 100644 --- a/arch/arm/cpu/armv7/tegra-common/board.c +++ b/arch/arm/cpu/armv7/tegra-common/board.c @@ -1,6 +1,8 @@ /* * (C) Copyright 2010,2011 * NVIDIA Corporation + * (C) Copyright 2012 + * Toradex, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -37,6 +39,7 @@ DECLARE_GLOBAL_DATA_PTR; unsigned int board_query_sdram_size(void) { +#ifndef CONFIG_COLIBRI_T20 struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; u32 reg; @@ -60,6 +63,15 @@ unsigned int board_query_sdram_size(void) default: return 0x40000000; /* 1GB */ } +#else /* CONFIG_COLIBRI_T20 */ + /* Colibri T20 does not use OdmData */ + u32 *pa_emc_adr_cfg = (void *)NV_PA_EMC_ADR_CFG_BASE; + + u32 reg = readl(pa_emc_adr_cfg); + + /* 4 MB shifted by EMEM_DEVSIZE */ + return (4 << 20) << ((reg & EMEM_DEVSIZE_MASK) >> EMEM_DEVSIZE_SHIFT); +#endif /* CONFIG_COLIBRI_T20 */ } #if defined(CONFIG_DISPLAY_BOARDINFO) || defined(CONFIG_DISPLAY_BOARDINFO_LATE) diff --git a/arch/arm/cpu/armv7/tegra-common/clock.c b/arch/arm/cpu/armv7/tegra-common/clock.c index 01caab6b9f..0d1f209165 100644 --- a/arch/arm/cpu/armv7/tegra-common/clock.c +++ b/arch/arm/cpu/armv7/tegra-common/clock.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (c) 2012 Toradex, Inc. * See file CREDITS for list of people who contributed to this * project. * @@ -493,6 +494,7 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { * SPDIF - which is both 0x08 and 0x0c * */ +//I believe above comment concerning SPDIF is bogus #define NONE(name) (-1) #define OFFSET(name, value) PERIPHC_ ## name static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { @@ -1361,11 +1363,14 @@ int clock_early_init(ulong pllp_base) osc_freq_mhz = 12; break; + case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ + osc_freq_mhz = 13; + break; + case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ osc_freq_mhz = 26; break; - case CLOCK_OSC_FREQ_13_0: case CLOCK_OSC_FREQ_19_2: default: /* diff --git a/arch/arm/cpu/armv7/tegra-common/display.c b/arch/arm/cpu/armv7/tegra-common/display.c index 2f12084447..55ea13e128 100644 --- a/arch/arm/cpu/armv7/tegra-common/display.c +++ b/arch/arm/cpu/armv7/tegra-common/display.c @@ -117,7 +117,7 @@ static int update_display_mode(struct dc_disp_reg *disp, /* * The pixel clock divider is in 7.1 format (where the bottom bit * represents 0.5). Here we calculate the divider needed to get from - * the display clock (typically 600MHz for tegra2 and 216MHZ + * the display clock (typically 600MHz for tegra2 and 216MHz * for tegra3) to the pixel clock. We round up or down as requried. */ #if defined(CONFIG_TEGRA2) diff --git a/arch/arm/cpu/armv7/tegra-common/pwfm.c b/arch/arm/cpu/armv7/tegra-common/pwfm.c index 5ef4363082..bdc1620724 100644 --- a/arch/arm/cpu/armv7/tegra-common/pwfm.c +++ b/arch/arm/cpu/armv7/tegra-common/pwfm.c @@ -30,8 +30,11 @@ void pwfm_setup(struct pwfm_ctlr *pwfm, int enable, int pulse_width, { u32 reg; - reg = bf_pack(PWFM_ENABLE, enable) | - bf_pack(PWFM_WIDTH, pulse_width) | - bf_pack(PWFM_DIVIDER, freq_divider); - writel(reg, &pwfm->control); + if(pwfm != NULL) + { + reg = bf_pack(PWFM_ENABLE, enable) | + bf_pack(PWFM_WIDTH, pulse_width) | + bf_pack(PWFM_DIVIDER, freq_divider); + writel(reg, &pwfm->control); + } } diff --git a/arch/arm/cpu/armv7/tegra3/warmboot_avp.c b/arch/arm/cpu/armv7/tegra3/warmboot_avp.c index 02772d42c1..02d320aed7 100644 --- a/arch/arm/cpu/armv7/tegra3/warmboot_avp.c +++ b/arch/arm/cpu/armv7/tegra3/warmboot_avp.c @@ -81,7 +81,7 @@ void wb_start(void) reg = SCLK_SWAKE_FIQ_SRC_CLKM | SCLK_SWAKE_IRQ_SRC_CLKM | SCLK_SWAKE_RUN_SRC_CLKM | SCLK_SWAKE_IDLE_SRC_CLKM | - SCLK_SYS_STATE_RUN; + SCLK_SYS_CPU_STATE_RUN; writel(reg, &clkrst->crc_sclk_brst_pol); /* Update PLLP output dividers for 408 MHz operation */ diff --git a/arch/arm/include/asm/arch-tegra/clk_rst.h b/arch/arm/include/asm/arch-tegra/clk_rst.h index 6bf9cb6131..3233d3b9d0 100644 --- a/arch/arm/include/asm/arch-tegra/clk_rst.h +++ b/arch/arm/include/asm/arch-tegra/clk_rst.h @@ -275,7 +275,7 @@ enum { #define SUPER_CDIV_ENB (1 << 31) /* CRC_SCLK_BURST_POLICY_0 28h */ -#define SCLK_SYS_STATE_RUN (2 << 28) +#define SCLK_SYS_CPU_STATE_RUN (2 << 28) #define SCLK_SWAKE_FIQ_SRC_CLKM (0 << 12) #define SCLK_SWAKE_IRQ_SRC_CLKM (0 << 8) #define SCLK_SWAKE_RUN_SRC_CLKM (0 << 4) diff --git a/arch/arm/include/asm/arch-tegra/tegra.h b/arch/arm/include/asm/arch-tegra/tegra.h index 471420136f..c51a8014e0 100644 --- a/arch/arm/include/asm/arch-tegra/tegra.h +++ b/arch/arm/include/asm/arch-tegra/tegra.h @@ -56,6 +56,9 @@ #define TEGRA_KBC_BASE 0x7000E200 #define NV_PA_PMC_BASE 0x7000E400 #define NV_PA_EMC_BASE 0x7000F400 +#define NV_PA_EMC_ADR_CFG_BASE (NV_PA_EMC_BASE + 0x10) +#define EMEM_DEVSIZE_MASK (0xf << EMEM_DEVSIZE_SHIFT) +#define EMEM_DEVSIZE_SHIFT (16) #define NV_PA_FUSE_BASE 0x7000F800 #define NV_PA_CSITE_BASE 0x70040000 diff --git a/arch/arm/include/asm/arch-tegra2/pmu.h b/arch/arm/include/asm/arch-tegra2/pmu.h index 5baab7604a..0faf07c3db 100644 --- a/arch/arm/include/asm/arch-tegra2/pmu.h +++ b/arch/arm/include/asm/arch-tegra2/pmu.h @@ -54,4 +54,6 @@ #define SM1_PWM_BIT 1 #define SM2_PWM_BIT 2 +#define MAX_I2C_RETRY 3 + #endif /* _ARCH_PMU_H_ */ diff --git a/arch/arm/include/asm/arch-tegra2/tegra.h b/arch/arm/include/asm/arch-tegra2/tegra.h index 6284e22c3b..125e31ed88 100644 --- a/arch/arm/include/asm/arch-tegra2/tegra.h +++ b/arch/arm/include/asm/arch-tegra2/tegra.h @@ -36,6 +36,8 @@ #define NV_PA_USB1_BASE 0xC5000000 #define NV_PA_USB3_BASE 0xC5008000 +#define NV_APB_MISC_BASE 0x70000000 + #include #endif diff --git a/arch/arm/include/asm/arch-tegra3/pmu.h b/arch/arm/include/asm/arch-tegra3/pmu.h index e2ed1d0325..f014a0f15e 100644 --- a/arch/arm/include/asm/arch-tegra3/pmu.h +++ b/arch/arm/include/asm/arch-tegra3/pmu.h @@ -35,4 +35,6 @@ #define PMU_LDO5_SEL(decivolts) ((decivolts - 10) * PMU_LDO5_SEL_0_1V_DELTA + \ PMU_LDO5_SEL_1_0V) +#define MAX_I2C_RETRY 3 + #endif /* _ARCH_PMU_H_ */ diff --git a/arch/arm/include/asm/arch-tegra3/pmu_core.h b/arch/arm/include/asm/arch-tegra3/pmu_core.h new file mode 100644 index 0000000000..48c61e0437 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra3/pmu_core.h @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2012 + * Toradex AG + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* definitions for TPS62360 / TPS62362 */ +#ifndef _PMU_CORE_H_ +#define _PMU_CORE_H_ + +#define DVC_I2C_BUS_NUMBER 0 +#define PMU_CORE_I2C_ADDRESS 0x60 + +#define PMU_CORE_VOLTAGE_START_REG 0x02 +#define PMU_CORE_VOLTAGE_DVFS_REG 0x00 + +#define VDD_CORE_NOMINAL_T30 43 /* 1.2V = 0.77V + x * 10mV */ + +#endif /* PMU_CORE_H */ diff --git a/arch/arm/include/asm/arch-tegra3/tegra.h b/arch/arm/include/asm/arch-tegra3/tegra.h index 62998fdbf1..046e58cddf 100644 --- a/arch/arm/include/asm/arch-tegra3/tegra.h +++ b/arch/arm/include/asm/arch-tegra3/tegra.h @@ -38,6 +38,8 @@ #define NV_PA_USB2_BASE 0x7D004000 #define NV_PA_USB3_BASE 0x7D008000 +#define NV_APB_MISC_BASE 0x70000000 + #include #endif diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index c72f6400d1..800f5fe6a5 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -79,6 +79,14 @@ typedef struct global_data { const void *blob; /* Our device tree, NULL if none */ void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_COLIBRI_T20) || defined(CONFIG_COLIBRI_T30) + unsigned env_offset; /* offset to the u-boot environment in mass storage */ + unsigned conf_blk_offset; /* offset to the Toradex config block in mass storage */ + unsigned conf_blk_offset2; /* offset to the Toradex config block (WinCE) in mass storage */ + unsigned kernel_offset; /* offset to the kernel in mass storage */ + unsigned rootfs_size; /* size of the rootfs in mass storage */ + unsigned rootfs_offset; /* offset to the rootfs in mass storage */ +#endif } gd_t; /* diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 339cb08ae5..b46bec1ae9 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -210,7 +210,8 @@ static int bootm_linux_fdt(int machid, bootm_headers_t *images) if (ret) return ret; -#ifdef CONFIG_OF_UPDATE_FDT_BEFORE_BOOT +#if defined(CONFIG_CHROMEOS) && defined(CONFIG_OF_UPDATE_FDT_BEFORE_BOOT) +//ToDo: this might be helpfull for NAND stuff /* this must be earlier than boot_relocate_fdt */ ret = fit_update_fdt_before_boot(*of_flat_tree, &of_size); if (ret) diff --git a/board/nvidia/cardhu/tegra30.dtsi b/board/nvidia/cardhu/tegra30.dtsi index 846c52ce0d..eb1d3f2954 100644 --- a/board/nvidia/cardhu/tegra30.dtsi +++ b/board/nvidia/cardhu/tegra30.dtsi @@ -248,14 +248,21 @@ usb@0x7d008000 { compatible = "nvidia,tegra250-usb"; - reg = <0x7d008000 0x8000>; + reg = <0x7d008000 0x4000>; periph-id = <59>; // PERIPH_ID_USB3 status = "disabled"; }; + usb@0x7d004000 { + compatible = "nvidia,tegra250-usb"; + reg = <0x7d004000 0x4000>; + periph-id = <58>; // PERIPH_ID_USB2 + status = "disabled"; + }; + usb@0x7d000000 { compatible = "nvidia,tegra250-usb"; - reg = <0x7d000000 0x8000>; + reg = <0x7d000000 0x4000>; periph-id = <22>; // PERIPH_ID_USBD status = "disabled"; }; diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index 5cb219b4f9..1ad40a7b0d 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -152,6 +152,37 @@ static void pin_mux_uart(int uart_ids) #endif /* CONFIG_TEGRA2 */ } +#if defined(CONFIG_TEGRA3) +static void enable_clock(enum periph_id pid, int src) +{ + /* Assert reset and enable clock */ + reset_set_enable(pid, 1); + clock_enable(pid); + + /* Use 'src' if provided, else use default */ + if (src != -1) + clock_ll_set_source(pid, src); + + /* wait for 2us */ + udelay(2); + + /* De-assert reset */ + reset_set_enable(pid, 0); +} + +/* Init misc clocks for kernel booting */ +static void clock_init_misc(void) +{ + /* 0 = PLLA_OUT0, -1 = CLK_M (default) */ + enable_clock(PERIPH_ID_I2S0, -1); + enable_clock(PERIPH_ID_I2S1, 0); + enable_clock(PERIPH_ID_I2S2, 0); + enable_clock(PERIPH_ID_I2S3, 0); + enable_clock(PERIPH_ID_I2S4, -1); + enable_clock(PERIPH_ID_SPDIF, -1); +} +#endif + /* * Routine: pin_mux_switches * Description: Disable internal pullups for the write protect, SDIO3 write @@ -380,6 +411,11 @@ int board_early_init_f(void) init_uarts(gd->blob); #endif +#if defined(CONFIG_TEGRA3) + /* Initialize misc clocks for kernel booting */ + clock_init_misc(); +#endif + #ifdef CONFIG_VIDEO_TEGRA /* Get LCD panel size */ lcd_early_init(gd->blob); diff --git a/board/nvidia/common/pmu.c b/board/nvidia/common/pmu.c index 0ff3167a8c..d18c8d71e8 100644 --- a/board/nvidia/common/pmu.c +++ b/board/nvidia/common/pmu.c @@ -47,7 +47,6 @@ #define stp(x, y) ((x < y) ? VDD_TRANSITION_STEP : -VDD_TRANSITION_STEP) -#define MAX_I2C_RETRY 3 int pmu_read(int reg) { int i; diff --git a/board/nvidia/harmony/tegra2-harmony.dts b/board/nvidia/harmony/tegra2-harmony.dts index b4965ed014..0528ebab3e 100644 --- a/board/nvidia/harmony/tegra2-harmony.dts +++ b/board/nvidia/harmony/tegra2-harmony.dts @@ -1,7 +1,7 @@ /dts-v1/; /memreserve/ 0x1c000000 0x04000000; -/include/ "../../../arch/arm/cpu/armv7/tegra2/tegra250.dtsi" +/include/ "../seaboard/tegra250.dtsi" / { model = "NVIDIA Harmony"; diff --git a/board/nvidia/seaboard/tegra250.dtsi b/board/nvidia/seaboard/tegra250.dtsi index 4a35d53ddd..01f11ad56d 100644 --- a/board/nvidia/seaboard/tegra250.dtsi +++ b/board/nvidia/seaboard/tegra250.dtsi @@ -216,14 +216,21 @@ usb@0xc5008000 { compatible = "nvidia,tegra250-usb"; - reg = <0xc5008000 0x8000>; + reg = <0xc5008000 0x4000>; periph-id = <59>; // PERIPH_ID_USB3 status = "disabled"; }; + usb@0xc5004000 { + compatible = "nvidia,tegra250-usb"; + reg = <0xc5004000 0x4000>; + periph-id = <58>; // PERIPH_ID_USB2 + status = "disabled"; + }; + usb@0xc5000000 { compatible = "nvidia,tegra250-usb"; - reg = <0xc5000000 0x8000>; + reg = <0xc5000000 0x4000>; periph-id = <22>; // PERIPH_ID_USBD status = "disabled"; }; diff --git a/board/toradex/colibri_t20/Makefile b/board/toradex/colibri_t20/Makefile new file mode 100644 index 0000000000..fadc87d213 --- /dev/null +++ b/board/toradex/colibri_t20/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2012 +# Toradex, Inc. +# +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +$(shell mkdir -p $(obj)../common) + +LIB = $(obj)lib$(BOARD).o + +COBJS := $(BOARD).o + +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/toradex/colibri_t20/colibri_t20.c b/board/toradex/colibri_t20/colibri_t20.c new file mode 100644 index 0000000000..eacde4554a --- /dev/null +++ b/board/toradex/colibri_t20/colibri_t20.c @@ -0,0 +1,24 @@ +/* + * (C) Copyright 2012 + * Toradex, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include diff --git a/board/toradex/colibri_t20/colibri_t20.dts b/board/toradex/colibri_t20/colibri_t20.dts new file mode 100644 index 0000000000..76cc495156 --- /dev/null +++ b/board/toradex/colibri_t20/colibri_t20.dts @@ -0,0 +1,239 @@ +/dts-v1/; + +/memreserve/ 0x0c000000 0x04000000; +/include/ "../../nvidia/seaboard/tegra250.dtsi" + +/ { + model = "Toradex Colibri T20"; + compatible = "toradex,t20", "nvidia,tegra250"; + + config { + machine-arch-id = <3323>; + }; + + aliases { + console = "/serial@70006000"; + usb0 = "/usb@0xc5004000"; + usb1 = "/usb@0xc5008000"; + usb2 = "/usb@0xc5000000"; + + sdmmc0 = "/sdhci@c8000600"; + + i2c0 = "/i2c@0x7000d000"; + i2c1 = "/i2c@0x7000c000"; + i2c2 = "/i2c@0x7000c400"; + i2c3 = "/i2c@0x7000c500"; + }; + +//will be auto detected and fixedup + memory { + device_type = "memory"; + reg = <0x00000000 0x10000000>; + }; + + uarta: serial@70006000 { + status = "ok"; + clock-frequency = <216000000>; + }; + + uartb: serial@70006040 { + status = "ok"; + clock-frequency = <216000000>; + }; + + uartd: serial@70006300 { + status = "ok"; + clock-frequency = <216000000>; + }; + + sdhci@c8000600 { + status = "ok"; + width = <4>; /* width of SDIO port */ + removable = <1>; + /* Parameter 3 bit 0:1=output, 0=input; bit 1:1=high, 0=low */ + cd-gpio = <&gpio 23 0>; /* card detect, gpio PC7 */ + }; + + lcd { + compatible = "nvidia,tegra2-lcd"; + width = <640>; + height = <480>; + bits_per_pixel = <16>; + pwfm = <&pwfm2>; + display = <&display1>; + /* frame-buffer location = top of memory - carveout - fb */ + frame-buffer_512 = <0x17400000>; /* 512M - 128M - 12M */ + frame-buffer_256 = <0x09400000>; /* 256M - 96M - 12M */ + + pixel_clock = <25175000>; + + /* Timing: ref_to_sync, sync_width. back_porch, front_porch */ + horiz_timing = <0 96 48 16>; + vert_timing = <1 2 31 11>; + + /* Parameter 3 bit 0:1=output, 0=input; bit 1:1=high, 0=low */ + backlight-enable = <&gpio 255 1>; /* use <&gpio 156 1> for PT4 - SODIMM 71: BL_ON */ + lvds-shutdown = <&gpio 255 1>; + backlight-vdd = <&gpio 255 1>; + panel-vdd = <&gpio 255 1>; + + /* + * Panel required timings + * Timing 1: delay between panel_vdd-rise and data-rise + * Timing 2: delay between data-rise and backlight_vdd-rise + * Timing 3: delay between backlight_vdd and pwm-rise + * Timing 4: delay between pwm-rise and backlight_en-rise + */ + panel-timings = <0 0 0 0>; + }; + + /* EHCI instance 0: USB1_DP/N -> USBOTG_P/N */ + usb@0xc5000000 { + status = "ok"; + host-mode = <1>; + }; + + /* EHCI instance 1: ULPI PHY -> ASIX ETH */ + usb@0xc5004000 { + status = "ok"; + host-mode = <0>; + }; + + usbphy: usbphy@0 { + compatible = "smsc,usb3340"; + status = "ok"; + }; + + /* EHCI instance 2: USB3_DP/N -> USBH1_P/N */ + usb@0xc5008000 { + status = "ok"; + utmi = <&usbphy>; + host-mode = <0>; + }; + + /* Colibri T20 256MB V1.2a intermediate */ + flash1@0x70008000 { + /* + * Auto detection uses two hex digits each of vendor ID, + * device ID and fourth byte of read ID separated by commas + */ + compatible = "micron,MT29F4G08ABBDAH4", "2C,AC,15"; + controller = <&nand>; + + /* How many bytes for data area */ + page-data-bytes = <2048>; + + /* How many ECC bytes to be generated for tag bytes */ + tag-ecc-bytes = <9>; + + /* How many tag bytes in spare area */ + tag-bytes = <48>; + + /* How many ECC bytes for data area */ + data-ecc-bytes = <72>; + + skipped-spare-bytes = <4>; + + /* + * How many bytes in spare area + * spare area = skipped bytes + ECC bytes of data area + * + tag bytes + ECC bytes of tag bytes + */ + page-spare-bytes = <64>; + + /* + * MAX_TRP_TREA: + * non-EDO mode: value (in ns) = Max(tRP, tREA) + 6ns + * EDO mode: value (in ns) = tRP timing + * TRH: tREH timing + * + * Timing values: MAX_TRP_TREA, TWB, Max(tCS, tCH, tALS, tALH), + * TWHR, Max(tCS, tCH, tALS, tALH), TWH, TWP, TRH, TADL + */ + timing = <12 100 20 80 20 10 12 10 70>; + + /* + * The offset of the start of + * u-boot-environment config-block config-block (WinCE) kernel rootfs-size rootfs-start + * rootfs: the numbers are concatenated to mtdparts=tegra_nand:K@K(userspace) + * take them from a download with NVFLASH + */ + /* unknown nv-partitions = <0xE00000 0x1000000 0x1000000 0x1200000 1018368 28160>; */ + }; + + /* Colibri T20 256MB V1.2a new */ + flash2@0x70008000 { + compatible = "micron,MT29F4G08ABBEAH4", "2C,AC,26"; + controller = <&nand>; + page-data-bytes = <4096>; + tag-ecc-bytes = <9>; + tag-bytes = <48>; + data-ecc-bytes = <72>; + skipped-spare-bytes = <4>; + page-spare-bytes = <128>; + timing = <15 100 25 80 25 10 15 10 100>; + nv-partitions = <0x980000 0x11c0000 0x7380000 0xc80000 503552 19712>; + }; + + /* Colibri T20 before V1.1x aka old */ + flash3@0x70008000 { + compatible = "micron,MT29F8G08ABCBB", "2C,38,26"; + controller = <&nand>; + page-data-bytes = <4096>; + tag-ecc-bytes = <9>; + tag-bytes = <48>; + data-ecc-bytes = <72>; + skipped-spare-bytes = <4>; + page-spare-bytes = <128>; + timing = <12 100 20 60 15 10 12 10 70>; + nv-partitions = <0xE00000 0x1880000 0x7900000 0x1200000 1018368 28160>; + }; + + /* Colibri T20 512MB V1.2a intermediate */ + flash4@0x70008000 { + compatible = "micron,MT29F8G08ADBDAH4", "2C,A3,15"; + controller = <&nand>; + page-data-bytes = <2048>; + tag-ecc-bytes = <9>; + tag-bytes = <48>; + data-ecc-bytes = <72>; + skipped-spare-bytes = <4>; + page-spare-bytes = <64>; + timing = <12 100 20 80 20 10 12 10 70>; + /* unknown nv-partitions = <0xE00000 0x1880000 0x1880000 0x1200000 1018368 28160>; */ + }; + + /* Colibri T20 512MB V1.2a new */ + flash5@0x70008000 { + compatible = "micron,MT29F8G08ABBCA", "2C,A3,26"; + controller = <&nand>; + page-data-bytes = <4096>; + tag-ecc-bytes = <9>; + tag-bytes = <48>; + data-ecc-bytes = <72>; + skipped-spare-bytes = <4>; + page-spare-bytes = <128>; + timing = <15 100 25 80 25 10 15 10 100>; + nv-partitions = <0x980000 0x11c0000 0x7380000 0xc80000 1027840 19712>; + }; + + /* Colibri T20 512MB 3.3V TSOP test */ + flash6@0x70008000 { + compatible = "samsung,K9K8G08U0B", "EC,D3,95"; + controller = <&nand>; + page-data-bytes = <2048>; + tag-ecc-bytes = <9>; + tag-bytes = <48>; + data-ecc-bytes = <72>; + skipped-spare-bytes = <4>; + page-spare-bytes = <64>; + timing = <20 100 20 60 20 10 12 10 70>; + nv-partitions = <0x740000 0xE60000 0x1880000 0x9C0000 1032576 15488>; + }; + + nand-controller@0x70008000 { + status = "ok"; + wp-gpio = <&gpio 144 3>; /* Port S = 18 bit = 0: 18 * 8 + 0 */ + width = <8>; + }; +}; diff --git a/board/toradex/colibri_t30/Makefile b/board/toradex/colibri_t30/Makefile new file mode 100644 index 0000000000..fadc87d213 --- /dev/null +++ b/board/toradex/colibri_t30/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2012 +# Toradex, Inc. +# +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +$(shell mkdir -p $(obj)../common) + +LIB = $(obj)lib$(BOARD).o + +COBJS := $(BOARD).o + +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/toradex/colibri_t30/colibri_t30.c b/board/toradex/colibri_t30/colibri_t30.c new file mode 100644 index 0000000000..eacde4554a --- /dev/null +++ b/board/toradex/colibri_t30/colibri_t30.c @@ -0,0 +1,24 @@ +/* + * (C) Copyright 2012 + * Toradex, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include diff --git a/board/toradex/colibri_t30/colibri_t30.dts b/board/toradex/colibri_t30/colibri_t30.dts new file mode 100644 index 0000000000..4a3b9b44c4 --- /dev/null +++ b/board/toradex/colibri_t30/colibri_t30.dts @@ -0,0 +1,130 @@ +/dts-v1/; + +/memreserve/ 0x1c000000 0x04000000; +/include/ "../../nvidia/cardhu/tegra30.dtsi" + +/ { + model = "Toradex Colibri T30"; + compatible = "toradex,t30", "nvidia,tegra30"; + + config { + silent_console = <0>; + odmdata = <0x300d8011>; + hwid = "ARM CARDHU TEST 6666"; + machine-arch-id = <3436>; + }; + + aliases { + console = "/serial@70006000"; + usb0 = "/usb@0x7d004000"; + usb1 = "/usb@0x7d008000"; + usb2 = "/usb@0x7d000000"; + + sdmmc0 = "/sdhci@78000600"; + sdmmc1 = "/sdhci@78000200"; + + i2c0 = "/i2c@0x7000d000"; + i2c1 = "/i2c@0x7000c000"; + i2c2 = "/i2c@0x7000c400"; + i2c3 = "/i2c@0x7000c500"; + i2c4 = "/i2c@0x7000c700"; + }; + + chosen { + bootargs = ""; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0xc0000000>; + }; + + serial@70006000 { + status = "ok"; + /* + * TBD - use CONFIG_SYS_PLLP_BASE_IS_408MHZ somehow here. + * Currently I put this back to 216MHz in fdt_decode.c + */ + clock-frequency = <408000000>; + }; + + sdhci@78000200 { + status = "ok"; + width = <4>; /* width of SDIO port */ + removable = <1>; + /* Parameter 3 bit 0:1=output, 0=input; bit 1:1=high, 0=low */ + cd-gpio = <&gpio 166 0>; /* card detect, gpio PU6 */ + }; + + /* Internal eMMC - SDMMC4 */ + emmc: sdhci@78000600 { + status = "ok"; + width = <4>; /* width of SDIO port */ + removable = <0>; + }; + + lcd { + compatible = "nvidia,tegra2-lcd"; + width = <640>; + height = <480>; + bits_per_pixel = <16>; + pwfm = <&pwfm0>; + display = <&display1>; + /* frame-buffer location = top of memory - carveout - fb */ + frame-buffer = <0xbfb00000>; + + pixel_clock = <25175000>; + + /* Timing: ref_to_sync, sync_width. back_porch, front_porch */ + horiz_timing = <0 96 48 16>; + vert_timing = <1 2 31 11>; + + /* Parameter 3 bit 0:1=output, 0=input; bit 1:1=high, 0=low */ + backlight-vdd = <&gpio 255 3>; /* PH0, LCD1_BL_PWM */ + backlight-enable = <&gpio 255 3>; /* PH2, LCD1_BL_EN */ + lvds-shutdown = <&gpio 255 3>; /* PL2, LVDS1_SHTDN */ + panel-vdd = <&gpio 255 3>; /* PL4, EN_VDD_PNL1 */ + + /* + * Panel required timings + * Timing 1: delay between panel_vdd-rise and data-rise + * Timing 2: delay between data-rise and backlight_vdd-rise + * Timing 3: delay between backlight_vdd and pwm-rise + * Timing 4: delay between pwm-rise and backlight_en-rise + */ + panel-timings = <0 0 0 0>; + }; + + /* EHCI instance 0: USB1_DP/N -> USBC_P/N */ + usb@0x7d000000 { + status = "ok"; + host-mode = <1>; + }; + + usbphya: usbphy@0 { + compatible = "smsc,usb3315"; + status = "ok"; + }; + + /* EHCI instance 1: USB2_DP/N -> ASIX ETH */ + usb@0x7d004000 { + status = "ok"; + utmi = <&usbphya>; + host-mode = <0>; + vbus-gpio = <&gpio 234 3>; /* PDD2, LAN_V_BUS */ + vbus_pullup-gpio = <&gpio 232 3>; /* PDD0, LAN_RESET_N */ + }; + + usbphyb: usbphy@0 { + compatible = "smsc,usb3315"; + status = "ok"; + }; + + /* EHCI instance 2: USB3_DP/N -> USBH_P/N */ + usb@0x7d008000 { + status = "ok"; + utmi = <&usbphyb>; + host-mode = <0>; + vbus-gpio = <&gpio 178 1>; /* PW2, USBH_PEN */ + }; +}; diff --git a/board/toradex/colibri_t30/pinmux-config-common.h b/board/toradex/colibri_t30/pinmux-config-common.h new file mode 100644 index 0000000000..cc62fa4161 --- /dev/null +++ b/board/toradex/colibri_t30/pinmux-config-common.h @@ -0,0 +1,404 @@ +/* + * (C) Copyright 2010,2011 + * NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef PINMUX_CONFIG_COMMON_H +#define PINMUX_CONFIG_COMMON_H + +#define DEFAULT_PINMUX(_pingroup, _mux, _pull, _tri, _io) \ + { \ + .pingroup = PINGRP_##_pingroup, \ + .func = PMUX_FUNC_##_mux, \ + .pull = PMUX_PULL_##_pull, \ + .tristate = PMUX_TRI_##_tri, \ + .io = PMUX_PIN_##_io, \ + .lock = PMUX_PIN_LOCK_DEFAULT, \ + .od = PMUX_PIN_OD_DEFAULT, \ + .ioreset = PMUX_PIN_IO_RESET_DEFAULT, \ + } + +#define I2C_PINMUX(_pingroup, _mux, _pull, _tri, _io, _lock, _od) \ + { \ + .pingroup = PINGRP_##_pingroup, \ + .func = PMUX_FUNC_##_mux, \ + .pull = PMUX_PULL_##_pull, \ + .tristate = PMUX_TRI_##_tri, \ + .io = PMUX_PIN_##_io, \ + .lock = PMUX_PIN_LOCK_##_lock, \ + .od = PMUX_PIN_OD_##_od, \ + .ioreset = PMUX_PIN_IO_RESET_DEFAULT, \ + } + +#define LV_PINMUX(_pingroup, _mux, _pull, _tri, _io, _lock, _ioreset) \ + { \ + .pingroup = PINGRP_##_pingroup, \ + .func = PMUX_FUNC_##_mux, \ + .pull = PMUX_PULL_##_pull, \ + .tristate = PMUX_TRI_##_tri, \ + .io = PMUX_PIN_##_io, \ + .lock = PMUX_PIN_LOCK_##_lock, \ + .od = PMUX_PIN_OD_DEFAULT, \ + .ioreset = PMUX_PIN_IO_RESET_##_ioreset \ + } + +static struct pingroup_config tegra3_pinmux_common[] = { + /* SDMMC1 pinmux */ + DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_CMD, SDMMC1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT3, SDMMC1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT2, SDMMC1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT1, SDMMC1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT0, SDMMC1, UP, NORMAL, INPUT), + + /* SDMMC3 pinmux */ + DEFAULT_PINMUX(SDMMC3_CLK, SDMMC3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_CMD, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT0, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT1, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT2, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT3, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT6, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT7, RSVD1, NORMAL, NORMAL, INPUT), + + /* SDMMC4 pinmux */ + LV_PINMUX(SDMMC4_CLK, SDMMC4, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_CMD, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_DAT0, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_DAT1, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_DAT2, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_DAT3, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_DAT4, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_DAT5, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_DAT6, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_DAT7, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(SDMMC4_RST_N, RSVD1, DOWN, NORMAL, INPUT, DISABLE, DISABLE), + + /* I2C1 pinmux */ + I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* I2C2 pinmux */ + I2C_PINMUX(GEN2_I2C_SCL, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(GEN2_I2C_SDA, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* I2C3 pinmux */ +//multiplexed KB_ROW_13 + I2C_PINMUX(CAM_I2C_SCL, I2C3, NORMAL, TRISTATE,INPUT, DISABLE, ENABLE), +//multiplexed KB_ROW_14 + I2C_PINMUX(CAM_I2C_SDA, I2C3, NORMAL, TRISTATE,INPUT, DISABLE, ENABLE), + + /* I2C4 pinmux */ + I2C_PINMUX(DDC_SCL, I2C4, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(DDC_SDA, I2C4, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* Power I2C pinmux */ + I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + DEFAULT_PINMUX(ULPI_DATA0, UARTA, NORMAL, NORMAL, OUTPUT), +//FF_RXD + DEFAULT_PINMUX(ULPI_DATA1, UARTA, UP, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA2, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA3, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA4, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA5, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA6, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA7, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_CLK, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_DIR, UARTD, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_NXT, UARTD, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_STP, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV2, OWR, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CLK2_OUT, EXTPERIPH2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK2_REQ, DAP, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_PWR2, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_SDIN, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_SDOUT, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_WR_N, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS0_N, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DC0, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_SCK, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_PWR0, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_PCLK, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DE, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_HSYNC, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_VSYNC, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D0, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D1, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D2, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D3, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D4, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D5, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D6, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D7, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D8, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D9, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D10, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D11, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D12, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D13, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D14, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D15, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D16, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D17, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D18, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D19, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D20, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D21, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D22, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D23, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS1_N, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_M1, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DC1, DISPA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CRT_HSYNC, CRT, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CRT_VSYNC, CRT, NORMAL, NORMAL, OUTPUT), + LV_PINMUX(VI_D0, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D1, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D2, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D3, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D4, VI, NORMAL, NORMAL, OUTPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D5, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D7, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D10, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_MCLK, RSVD3, UP, NORMAL, INPUT, DISABLE, DISABLE), + DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU0, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU1, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU2, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU3, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU4, PWM1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU6, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK3_OUT, EXTPERIPH3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CLK3_REQ, DEV3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_WP_N, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD0, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD1, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD2, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD3, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD4, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD5, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD6, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD7, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_ADV_N, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CLK, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CS2_N, NAND, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CS3_N, NAND, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD8, PWM0, NORMAL, NORMAL, OUTPUT), /* LCD1_BL_PWM */ + DEFAULT_PINMUX(GMI_AD10, NAND, NORMAL, NORMAL, OUTPUT), /* LCD1_BL_EN */ + DEFAULT_PINMUX(GMI_A16, SPI4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A17, SPI4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A18, SPI4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A19, SPI4, NORMAL, NORMAL, INPUT), +//multiplexed KB_ROW_10 + DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, UP, TRISTATE, INPUT), +//multiplexed KB_ROW_11 + DEFAULT_PINMUX(GPIO_PCC1, RSVD1, NORMAL, TRISTATE, INPUT), +//multiplexed KB_ROW_12 + DEFAULT_PINMUX(GPIO_PBB0, RSVD1, NORMAL, TRISTATE, INPUT), +//multiplexed KB_ROW_15 + DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GPIO_PBB5, VGP5, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB6, VGP6, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(JTAG_RTCK, RTCK, NORMAL, NORMAL, OUTPUT), + + /* KBC keys */ + DEFAULT_PINMUX(KB_ROW0, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW1, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW2, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW3, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW4, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW5, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW6, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW7, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW8, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW9, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW10, SDMMC2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW11, SDMMC2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW12, SDMMC2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW13, SDMMC2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW14, SDMMC2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW15, SDMMC2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL0, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL1, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL2, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL3, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL4, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL5, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL6, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL7, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD, UP, NORMAL, INPUT), + + DEFAULT_PINMUX(CLK_32K_OUT, BLINK, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK1_REQ, DAP, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, INPUT), +#ifdef CONFIG_SND_HDA_CODEC_REALTEK + DEFAULT_PINMUX(SPDIF_IN, DAP2, DOWN, NORMAL, INPUT), +#else + DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT), +#endif + DEFAULT_PINMUX(SPDIF_OUT, SPDIF, NORMAL, NORMAL, OUTPUT), +#ifdef CONFIG_SND_HDA_CODEC_REALTEK + DEFAULT_PINMUX(DAP2_FS, HDA, DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DIN, HDA, DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, HDA, DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_SCLK, HDA, DOWN, NORMAL, INPUT), +#else + DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), +#endif + DEFAULT_PINMUX(SPI2_CS1_N, SPI2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MOSI, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_SCK, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_CS0_N, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MISO, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L0_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L0_RST_N, PCIE, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(PEX_L0_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_WAKE_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L1_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L1_RST_N, PCIE, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(PEX_L1_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L2_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L2_RST_N, PCIE, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(PEX_L2_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(HDMI_CEC, CEC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(HDMI_INT, RSVD0, NORMAL, TRISTATE, INPUT), + + /* Gpios */ + /* SDMMC1 CD gpio */ + DEFAULT_PINMUX(GMI_IORDY, RSVD1, UP, NORMAL, INPUT), + /* SDMMC1 WP gpio */ + LV_PINMUX(VI_D11, RSVD1, UP, NORMAL, INPUT, DISABLE, DISABLE), + + /* Touch panel GPIO */ + /* Touch IRQ */ + DEFAULT_PINMUX(GMI_AD12, NAND, UP, NORMAL, INPUT), + + /* Touch RESET */ + DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, NORMAL, OUTPUT), + + /* Power rails GPIO */ + DEFAULT_PINMUX(SPI2_SCK, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB4, VGP4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW8, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT5, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT4, SDMMC3, UP, NORMAL, INPUT), + + LV_PINMUX(VI_D6, VI, NORMAL, NORMAL, OUTPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D8, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_D9, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_PCLK, RSVD1, UP, TRISTATE, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_HSYNC, RSVD1, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + LV_PINMUX(VI_VSYNC, RSVD1, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), +}; + +#if 0 // jz +static struct pingroup_config cardhu_pinmux_e118x[] = { + /* Power rails GPIO */ + DEFAULT_PINMUX(SPI2_SCK, SPI2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CS2_N, NAND, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_RST_N, RSVD3, UP, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_AD15, NAND, UP, TRISTATE, INPUT), +}; + +static struct pingroup_config cardhu_pinmux_cardhu[] = { + /* Power rails GPIO */ + DEFAULT_PINMUX(GMI_CS2_N, NAND, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_RST_N, RSVD3, UP, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_AD15, NAND, UP, TRISTATE, INPUT), + + DEFAULT_PINMUX(GMI_CS0_N, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CS1_N, GMI, UP, TRISTATE, INPUT), + /*TP_IRQ*/ + DEFAULT_PINMUX(GMI_CS4_N, GMI, UP, NORMAL, INPUT), +}; + +static struct pingroup_config cardhu_pinmux_cardhu_a03[] = { + /* Power rails GPIO */ + DEFAULT_PINMUX(PEX_L0_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L0_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L1_CLKREQ_N, RSVD3, UP, TRISTATE, INPUT), + DEFAULT_PINMUX(PEX_L1_PRSNT_N, NAND, UP, TRISTATE, INPUT), +}; + +static __initdata struct tegra_pingroup_config cardhu_pinmux_e1198[] = { + /* SPI2 */ + DEFAULT_PINMUX(SPI2_SCK, SPI2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SPI2_MOSI, SPI2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SPI2_MISO, SPI2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SPI2_CS0_N, SPI2, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SPI2_CS2_N, SPI2, UP, NORMAL, INPUT), +}; +#endif // jz + +static struct pingroup_config unused_pins_lowpower[] = { + DEFAULT_PINMUX(GMI_WAIT, NAND, UP, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_ADV_N, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_CLK, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_CS3_N, NAND, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_CS7_N, NAND, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD0, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD1, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD2, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD3, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD4, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD5, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD6, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD7, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD9, PWM1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_AD11, NAND, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_AD13, NAND, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_WR_N, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_OE_N, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_DQS, NAND, NORMAL, TRISTATE, OUTPUT), +}; + +#endif /* PINMUX_CONFIG_COMMON_H */ + diff --git a/board/toradex/common/Makefile b/board/toradex/common/Makefile new file mode 100644 index 0000000000..e3a6dbf938 --- /dev/null +++ b/board/toradex/common/Makefile @@ -0,0 +1,60 @@ +# Copyright (c) 2012 Toradex, Inc. +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA + +include $(TOPDIR)/config.mk + +ifneq ($(OBJTREE),$(SRCTREE)) +$(shell mkdir -p $(obj)crypto) +endif + +LIB = $(obj)lib$(VENDOR).o + +COBJS-y += board.o +COBJS-$(CONFIG_TEGRA2_NAND) += tegra2_nand.o +COBJS-$(CONFIG_USB_EHCI_TEGRA) += ulpi_linux.o +COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o + +COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += ../../nvidia/common/emc.o +COBJS-$(CONFIG_TEGRA_PMU) += ../../nvidia/common/pmu.o +COBJS-$(CONFIG_TEGRA_LP0) += ../../nvidia/common/crypto/aes_ref.o +COBJS-$(CONFIG_TEGRA_LP0) += ../../nvidia/common/crypto/crypto.o + +COBJS := $(COBJS-y) +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### +# This is for $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/toradex/common/board.c b/board/toradex/common/board.c new file mode 100644 index 0000000000..b4461699b7 --- /dev/null +++ b/board/toradex/common/board.c @@ -0,0 +1,911 @@ +/* + * (C) Copyright 2012 + * Toradex, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include /* do not change order of include file */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_TEGRA2 +#include +#include +#endif +#include +#ifdef CONFIG_TEGRA3 +#include +#include +#endif +#include +#ifdef CONFIG_USB_EHCI_TEGRA +#include +#endif +#include + +#ifdef CONFIG_TEGRA_I2C +#include +#endif + +#include "board.h" +#include "../../nvidia/common/pmu.h" + +#ifdef CONFIG_TEGRA_MMC +#include +#include +#endif + +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + + +#define NV_ADDRESS_MAP_FUSE_BASE 0x7000f800 +// Register FUSE_BOOT_DEVICE_INFO_0 +#define FUSE_BOOT_DEVICE_INFO_0 0x1bc +// Register FUSE_RESERVED_SW_0 +#define FUSE_RESERVED_SW_0 0x1c0 + +#define CLK_RST_BASE 0x60006000 +// Register CLK_RST_CONTROLLER_MISC_CLK_ENB_0 +#define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 0x48 + +// Register APB_MISC_PP_STRAPPING_OPT_A_0 +#define APB_MISC_PP_STRAPPING_OPT_A_0 0x8 + +typedef enum +{ + NvBootFuseBootDevice_Sdmmc, + NvBootFuseBootDevice_SnorFlash, + NvBootFuseBootDevice_SpiFlash, + NvBootFuseBootDevice_NandFlash, + NvBootFuseBootDevice_NandFlash_x8 = NvBootFuseBootDevice_NandFlash, + NvBootFuseBootDevice_NandFlash_x16 = NvBootFuseBootDevice_NandFlash, + NvBootFuseBootDevice_MobileLbaNand, + NvBootFuseBootDevice_MuxOneNand, + NvBootFuseBootDevice_Sata, + NvBootFuseBootDevice_BootRom_Reserved_Sdmmc3, /* !!! this enum is strictly used by BootRom code only !!! */ + NvBootFuseBootDevice_Max, /* Must appear after the last legal item */ + NvBootFuseBootDevice_Force32 = 0x7fffffff +} NvBootFuseBootDevice; +typedef enum +{ + NvStrapDevSel_Emmc_Primary_x4 = 0, /* eMMC primary (x4) */ + NvStrapDevSel_Emmc_Primary_x8, /* eMMC primary (x8) */ + NvStrapDevSel_Emmc_Secondary_x4, /* eMMC secondary (x4) */ + NvStrapDevSel_Nand, /* NAND (x8 or x16) */ + NvStrapDevSel_Nand_42nm_x8, /* NAND_42nm (x8) */ + NvStrapDevSel_MobileLbaNand, /* mobileLBA NAND */ + NvStrapDevSel_MuxOneNand, /* MuxOneNAND */ + NvStrapDevSel_Esd_x4, /* eSD (x4) */ + NvStrapDevSel_SpiFlash, /* SPI Flash */ + NvStrapDevSel_Snor_Muxed_x16, /* Sync NOR (Muxed, x16) */ + NvStrapDevSel_Snor_Muxed_x32, /* Sync NOR (Muxed, x32) */ + NvStrapDevSel_Snor_NonMuxed_x16, /* Sync NOR (NonMuxed, x16) */ + NvStrapDevSel_FlexMuxOneNand, /* FlexMuxOneNAND */ + NvStrapDevSel_Sata, /* Sata */ + NvStrapDevSel_Emmc_Secondary_x8, /* eMMC secondary (x8) */ + NvStrapDevSel_UseFuses, /* Use fuses instead */ + + /* The following definitions must be last. */ + NvStrapDevSel_Num, /* Must appear after the last legal item */ + NvStrapDevSel_Force32 = 0x7fffffff +} NvStrapDevSel; +typedef enum +{ + Trdx_BootDevice_NandFlash, + Trdx_BootDevice_eMMC, + Trdx_BootDevice_extSD, + Trdx_BootDevice_Unknown, + Trdx_BootDevice_Max, /* Must appear after the last legal item */ + Trdx_BootDevice_Force32 = 0x7fffffff +} TrdxBootDevice; +const char* sTrdxBootDeviceStr[] = +{ + "Trdx_BootDevice_NandFlash", + "Trdx_BootDevice_eMMC", + "Trdx_BootDevice_extSD", + "Trdx_BootDevice_Unknown" +}; + + + +#if defined(CONFIG_TEGRA_CLOCK_SCALING) && !defined(CONFIG_TEGRA_I2C) +#error "tegra: We need CONFIG_TEGRA_I2C to support CONFIG_TEGRA_CLOCK_SCALING" +#endif + +#if defined(CONFIG_TEGRA_CLOCK_SCALING) && !defined(CONFIG_TEGRA_PMU) +#error "tegra: We need CONFIG_TEGRA_PMU to support CONFIG_TEGRA_CLOCK_SCALING" +#endif + +#define GENERATE_FUSE_DEV_INFO 0 +static TrdxBootDevice board_get_current_bootdev(void) +{ + unsigned reg; +#if GENERATE_FUSE_DEV_INFO + unsigned reg1 = 0; + unsigned reg2; +#endif + unsigned strap_select; + unsigned skip_strap; + unsigned fuse_select; +#if GENERATE_FUSE_DEV_INFO + unsigned fuse_device_info; + unsigned sdmmc_instance; +#endif + TrdxBootDevice boot_device; + + //get the latched strap pins, bit [26:29] + reg = readl( ((unsigned *)NV_APB_MISC_BASE) + APB_MISC_PP_STRAPPING_OPT_A_0); +/* + printf("Strappings Reg 0x%x, BootSelect 0x%x, Recovery %x, NorBoot %x, JTAG %x, MIO_WIDTH %x, RAM_Code %x, NOR_Width %x\n", + reg, (reg>>26)&0xf, (reg>>25)&0x1, (reg>>24)&0x1, (reg>>22)&0x3, (reg>>8)&0x1, (reg>>4)&0xf, (reg)&0x1); +*/ + strap_select = (reg>>26)&0xf; + +#if 0 //Max: this does not work, there is more to read fuses than that + //check if we can access BIT /tegra/core/include/nvbit.h et.al. + + + clock_enable(PERIPH_ID_FUSE); + //make fuses visible + reg = readl( ((unsigned *)CLK_RST_BASE) + CLK_RST_CONTROLLER_MISC_CLK_ENB_0); + reg = reg | (1<<28); + writel(reg, ((unsigned *)CLK_RST_BASE) + CLK_RST_CONTROLLER_MISC_CLK_ENB_0 ); + + printf("1"); + reg = readl( ((unsigned *)NV_ADDRESS_MAP_FUSE_BASE) + FUSE_RESERVED_SW_0); + printf("2"); + reg1 = readl( ((unsigned *)NV_ADDRESS_MAP_FUSE_BASE) + FUSE_BOOT_DEVICE_INFO_0); + printf("3"); + + //make fuses invisible + reg2 = readl( ((unsigned *)CLK_RST_BASE) + CLK_RST_CONTROLLER_MISC_CLK_ENB_0); + reg2 = reg2 & ~(1<<28); + writel(reg2, ((unsigned *)CLK_RST_BASE) + CLK_RST_CONTROLLER_MISC_CLK_ENB_0 ); + + clock_disable(PERIPH_ID_FUSE); +#else +#ifdef CONFIG_TEGRA3 + //simulate a T30 fuse setting + reg = NvBootFuseBootDevice_Sdmmc; +#else + //simulate a T20 fuse setting + reg = NvBootFuseBootDevice_NandFlash; +#endif +#endif + //get the fuse 'SKIP_DEV_SEL_STRAPS', bit 3 + skip_strap = (reg & 8)>>3; + //get the fuse 'BOOT_DEV_SEL', bit [0:2] + fuse_select = reg & 7; + + if(skip_strap || strap_select == NvStrapDevSel_UseFuses) + { + printf("Using fuses, %u\n", fuse_select); + //getting fuse device info and sdmmc instance, bit 7 of fuse_device info +#if GENERATE_FUSE_DEV_INFO + fuse_device_info = reg1 & 0x3fff; + sdmmc_instance = ((reg1 & 0x80)==0x80) ? 2 : 3; +#endif + switch(fuse_select) + { + case NvBootFuseBootDevice_Sdmmc: + boot_device = Trdx_BootDevice_eMMC; + break; + case NvBootFuseBootDevice_NandFlash: + boot_device = Trdx_BootDevice_NandFlash; + break; + default: + boot_device = Trdx_BootDevice_Unknown; + break; + } + } + else + { + /* printf("Using straps, %u\n", strap_select);*/ +#if GENERATE_FUSE_DEV_INFO + sdmmc_instance = 3; +#endif + switch(strap_select) + { + case NvStrapDevSel_Emmc_Primary_x4: + case NvStrapDevSel_Emmc_Secondary_x4: + case NvStrapDevSel_Emmc_Secondary_x8: + case NvStrapDevSel_Esd_x4: + boot_device = Trdx_BootDevice_extSD; + break; + case NvStrapDevSel_Nand: + case NvStrapDevSel_Nand_42nm_x8: + boot_device = Trdx_BootDevice_NandFlash; + break; + default: + boot_device = Trdx_BootDevice_Unknown; + break; + } + } + /* + if(boot_device < sizeof(sTrdxBootDeviceStr)/sizeof(sTrdxBootDeviceStr[0])) + { + printf("%s is used\n",sTrdxBootDeviceStr[boot_device]); + } + */ + return boot_device; +} + +static void board_voltage_init(void); + +enum { + /* UARTs which we can enable */ + UARTA = 1 << 0, + UARTB = 1 << 1, + UARTD = 1 << 3, + UART_ALL = 0xf +}; + +#if defined(BOARD_LATE_INIT) && (defined(CONFIG_TRDX_CFG_BLOCK_OFFSET) || \ + defined(CONFIG_REVISION_TAG) || defined(CONFIG_SERIAL_TAG)) +static unsigned char *config_block = NULL; +#endif + +#ifdef CONFIG_HW_WATCHDOG +static int i2c_is_initialized = 0; +#endif + +/* + * Routine: timer_init + * Description: init the timestamp and lastinc value + */ +int timer_init(void) +{ + reset_timer(); + return 0; +} + +static void enable_uart(enum periph_id pid) +{ + /* Assert UART reset and enable clock */ + reset_set_enable(pid, 1); + clock_enable(pid); + clock_ll_set_source(pid, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */ + + /* wait for 2us */ + udelay(2); + + /* De-assert reset to UART */ + reset_set_enable(pid, 0); +} + +/* + * Routine: clock_init_uart + * Description: init clock for the UART(s) + */ +static void clock_init_uart(int uart_ids) +{ + if (uart_ids & UARTA) + enable_uart(PERIPH_ID_UART1); + if (uart_ids & UARTB) + enable_uart(PERIPH_ID_UART2); + if (uart_ids & UARTD) + enable_uart(PERIPH_ID_UART4); +} + +/* + * Routine: pin_mux_uart + * Description: setup the pin muxes/tristate values for the UART(s) + */ +static void pin_mux_uart(int uart_ids) +{ +#if defined(CONFIG_TEGRA2) + if (uart_ids & UARTA) { + /* Disable UART1 where primary function */ + pinmux_tristate_enable(PINGRP_IRRX); + pinmux_tristate_enable(PINGRP_IRTX); + pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_GMI); + pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_GMI); + pinmux_tristate_enable(PINGRP_SDB); + pinmux_tristate_enable(PINGRP_SDD); + pinmux_set_func(PINGRP_SDB, PMUX_FUNC_PWM); + pinmux_set_func(PINGRP_SDD, PMUX_FUNC_PWM); + + pinmux_set_func(PINGRP_SDMMC1, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PINGRP_SDMMC1); + } + if (uart_ids & UARTB) { + pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA); + pinmux_tristate_disable(PINGRP_UAD); + } + if (uart_ids & UARTD) { + pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD); + pinmux_tristate_disable(PINGRP_GMC); + } +#endif /* CONFIG_TEGRA2 */ +} + +#ifdef CONFIG_TEGRA_MMC +/* + * Routine: pin_mux_mmc + * Description: setup the pin muxes/tristate values for the SDMMC(s) + */ +static void pin_mux_mmc(void) +{ +#ifdef CONFIG_TEGRA2 + /* SDMMC4: config 3, x4 on 2nd set of pins */ + pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4); + pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4); + + pinmux_tristate_disable(PINGRP_ATB); + pinmux_tristate_disable(PINGRP_GMA); +#endif +} +#endif + +#ifdef CONFIG_TEGRA3 +#include "../colibri_t30/pinmux-config-common.h" +#endif + +/* + * Routine: pinmux_init + * Description: Do individual peripheral pinmux configs + */ +#if defined(CONFIG_TEGRA3) +static void pinmux_init(void) +{ + pinmux_config_table(tegra3_pinmux_common, + ARRAY_SIZE(tegra3_pinmux_common)); + + pinmux_config_table(unused_pins_lowpower, + ARRAY_SIZE(unused_pins_lowpower)); +} +#endif + +static void init_uarts(const void *blob) +{ + int uart_ids = 0; /* bit mask of which UART ids to enable */ + struct fdt_uart uart; + + if (!fdt_decode_uart_console(blob, &uart, gd->baudrate)) + uart_ids = 1 << uart.id; + + /* Initialize UART clocks */ + clock_init_uart(uart_ids); + + /* Initialize periph pinmuxes */ +#if defined(CONFIG_TEGRA2) + pin_mux_uart(uart_ids); +#endif +} + +/* + * Routine: power_det_init + * Description: turn off power detects + */ +static void power_det_init(void) +{ +#if defined(CONFIG_TEGRA2) + struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + /* turn off power detects */ + writel(0, &pmc->pmc_pwr_det_latch); + writel(0, &pmc->pmc_pwr_det); +#endif +} + +#if defined(CONFIG_TEGRA3) +static void enable_clock(enum periph_id pid, int src) +{ + /* Assert reset and enable clock */ + reset_set_enable(pid, 1); + clock_enable(pid); + + /* Use 'src' if provided, else use default */ + if (src != -1) + clock_ll_set_source(pid, src); + + /* wait for 2us */ + udelay(2); + + /* De-assert reset */ + reset_set_enable(pid, 0); +} + +/* Init misc clocks for kernel booting */ +static void clock_init_misc(void) +{ + /* 0 = PLLA_OUT0, -1 = CLK_M (default) */ + enable_clock(PERIPH_ID_I2S0, -1); + enable_clock(PERIPH_ID_I2S1, 0); + enable_clock(PERIPH_ID_I2S2, 0); + enable_clock(PERIPH_ID_I2S3, 0); + enable_clock(PERIPH_ID_I2S4, -1); + enable_clock(PERIPH_ID_SPDIF, -1); +} +#endif + +/* + * Routine: board_init + * Description: Early hardware init. + */ +int board_init(void) +{ +#ifdef CONFIG_VIDEO_TEGRA + tegra_lcd_check_next_stage(gd->blob, 0); +#endif + +#ifdef CONFIG_DELAY_CONSOLE + init_uarts(gd->blob); +#endif + + /* Do clocks and UART first so that printf() works */ + clock_init(); + +#ifdef CONFIG_USB_EHCI_TEGRA + board_usb_init(gd->blob); +#endif + + clock_verify(); + + power_det_init(); + + (void)board_get_current_bootdev(); + +#ifdef CONFIG_TEGRA_I2C + /* Ramp up the core voltage, then change to full CPU speed */ + i2c_init_board(); +#endif + +#ifdef CONFIG_TEGRA_CLOCK_SCALING + pmu_set_nominal(); + arch_full_speed(); +#endif + + /* board id for Linux */ + gd->bd->bi_arch_number = fdt_decode_get_machine_arch_id(gd->blob); + if (gd->bd->bi_arch_number == -1U) + printf("Warning: No /config/machine-arch-id defined in fdt\n"); + +#ifdef CONFIG_TEGRA_CLOCK_SCALING + board_emc_init(); +#endif + + board_voltage_init(); + +#ifdef CONFIG_HW_WATCHDOG + i2c_is_initialized = 1; +#endif + +#ifdef CONFIG_TEGRA_LP0 + /* prepare the WB code to LP0 location */ +//ToDo: determine LP0 address dynamically + warmboot_prepare_code(TEGRA_LP0_ADDR, TEGRA_LP0_SIZE); +#endif + + /* boot param addr */ + gd->bd->bi_boot_params = (NV_PA_SDRAM_BASE + 0x100); + + return 0; +} + +#ifdef CONFIG_BOARD_EARLY_INIT_F +int board_early_init_f(void) +{ + ulong pllp_rate = 216000000; /* default PLLP clock rate */ + + /* Initialize essential common plls */ + pllp_rate = fdt_decode_clock_rate(gd->blob, "pllp", pllp_rate); + clock_early_init(pllp_rate); + +#ifdef CONFIG_TEGRA3 + pinmux_init(); +#endif + +#ifndef CONFIG_DELAY_CONSOLE + init_uarts(gd->blob); +#endif + +#if defined(CONFIG_TEGRA3) + /* Initialize misc clocks for kernel booting */ + clock_init_misc(); +#endif + +#ifdef CONFIG_VIDEO_TEGRA + /* Get LCD panel size */ + lcd_early_init(gd->blob); +#endif + + return 0; +} +#endif /* EARLY_INIT */ + +#ifdef BOARD_LATE_INIT +int board_late_init(void) +{ + char env_str[256 ]; + +#ifdef CONFIG_TRDX_CFG_BLOCK_OFFSET + char *addr_str, *end; + unsigned char bi_enetaddr[6] = {0, 0, 0, 0, 0, 0}; /* Ethernet address */ + int i; + unsigned char *mac_addr; + unsigned char mac_addr00[6] = {0, 0, 0, 0, 0, 0}; + + size_t size = 4096; + unsigned char toradex_oui[3] = { 0x00, 0x14, 0x2d }; + int valid = 0; + + unsigned int offset; + int ret; +#endif /* CONFIG_TRDX_CFG_BLOCK_OFFSET */ + +#ifdef CONFIG_VIDEO_TEGRA + /* Make sure we finish initing the LCD */ + tegra_lcd_check_next_stage(gd->blob, 1); +#endif + +#ifdef CONFIG_TRDX_CFG_BLOCK_OFFSET + /* Allocate RAM area for config block */ + config_block = malloc(size); + if (!config_block) { + printf("Not enough malloc space available!\n"); + return -1; + } + + for (i = 0; i < 2; i++) { + if (i == 0) + offset = CONFIG_TRDX_CFG_BLOCK_OFFSET; + else + offset = CONFIG_TRDX_CFG_BLOCK_OFFSET2; + + /* Clear it */ + memset((void *)config_block, 0, size); + + /* Read production parameter config block */ +#ifdef CONFIG_CMD_NAND + ret = nand_read_skip_bad(&nand_info[0], offset, &size, (unsigned char *) config_block); +#endif + /* Check validity */ + if ( (ret==0) && (size>0) ) { + mac_addr = config_block + 8; + if (!(memcmp(mac_addr, toradex_oui, 3))) { + valid = 1; + break; + } + } + else { + /* probably there is no flash, + * give up reading the config block, the nand flash layer crashes on the second attempt */ + break; + } + } + + /* Check validity */ + if (!valid) { + printf("Missing Colibri config block\n"); + memset((void *)config_block, 0, size); + } else { + /* Get MAC address from environment */ + if ((addr_str = getenv("ethaddr")) != NULL) { + for (i = 0; i < 6; i++) { + bi_enetaddr[i] = addr_str ? simple_strtoul(addr_str, &end, 16) : 0; + if (addr_str) { + addr_str = (*end) ? end + 1 : end; + } + } + } + + /* Set Ethernet MAC address from config block if not already set */ + if (memcmp(mac_addr00, bi_enetaddr, 6) == 0) { + sprintf(env_str, "%02x:%02x:%02x:%02x:%02x:%02x", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + setenv("ethaddr", env_str); +#ifndef CONFIG_ENV_IS_NOWHERE + saveenv(); +#endif + } + } + + /* Default memory arguments */ + if (!getenv("memargs")) { + if (gd->ram_size == 0x10000000) { + /* 256 MB */ + setenv("memargs", "mem=148M@0M fbmem=12M@148M nvmem=96M@160M"); + } else { + /* 512 MB */ + setenv("memargs", "mem=372M@0M fbmem=12M@372M nvmem=128M@384M"); + } + } + +#endif /* CONFIG_TRDX_CFG_BLOCK_OFFSET */ + + /* set the nand kernel offset */ + if (!getenv("lnxoffset")) { + sprintf(env_str, "0x%x", (unsigned)(gd->kernel_offset)); + setenv("lnxoffset", env_str); + } + + /* set the mtdparts string */ + if (!getenv("mtdparts")) { + sprintf(env_str, "mtdparts=tegra_nand:%uK@%uK(userspace)", + (unsigned)(gd->rootfs_size), (unsigned)(gd->rootfs_offset) ); + setenv("mtdparts", env_str); + } + + return 0; +} +#endif /* BOARD_LATE_INIT */ + +#ifdef CONFIG_TEGRA_MMC +/* this is a weak define that we are overriding */ +int board_mmc_init(bd_t *bd) +{ + debug("board_mmc_init called\n"); + + /* Enable muxes, etc. for SDMMC controllers */ + pin_mux_mmc(); + + tegra_mmc_init(gd->blob); + + return 0; +} +#endif + +/* + * MK: Do I2C/PMU writes to set nominal voltages for Colibri_T30 + * + */ +static void board_voltage_init(void) +{ +#if defined(CONFIG_TEGRA3) + uchar reg, data_buffer[1]; + int i; + + i2c_set_bus_num(0); /* PMU is on bus 0 */ + + //switch v-ddr ram to 1.35V + data_buffer[0] = 0x3f; + reg = 0x25; + + for (i = 0; i < MAX_I2C_RETRY; ++i) { + if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) + udelay(100); + } + + //switch v-core to 1.2V + data_buffer[0] = VDD_CORE_NOMINAL_T30; + reg = PMU_CORE_VOLTAGE_START_REG; + + for (i = 0; i < MAX_I2C_RETRY; ++i) { + if (i2c_write(PMU_CORE_I2C_ADDRESS, reg, 1, data_buffer, 1)) + udelay(100); + } + data_buffer[0] = VDD_CORE_NOMINAL_T30; + reg = PMU_CORE_VOLTAGE_DVFS_REG; + for (i = 0; i < MAX_I2C_RETRY; ++i) { + if (i2c_write(PMU_CORE_I2C_ADDRESS, reg, 1, data_buffer, 1)) + udelay(100); + } + +#ifndef CONFIG_HW_WATCHDOG + //disable watchdog + data_buffer[0] = 0x10; /* kick the dog once before disabling it or disabling will fail */ + reg = 0x54; + for (i = 0; i < MAX_I2C_RETRY; ++i) { + if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) + udelay(100); + } + + data_buffer[0] = 0xf0; /* at least one of the reserved bits must be '1' or disabling will fail */ + reg = 0x69; + for (i = 0; i < MAX_I2C_RETRY; ++i) { + if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) + udelay(100); + } +#endif +#endif +} + +#ifdef CONFIG_REVISION_TAG +u32 get_board_rev(void) +{ +#ifdef BOARD_LATE_INIT + int i; + unsigned short major = 0, minor = 0, release = 0; + size_t size = 4096; + + if(config_block == NULL) { + return 0; + } + + /* Parse revision information in config block */ + for (i = 0; i < (size - 8); i++) { + if (config_block[i] == 0x02 && config_block[i+1] == 0x40 && + config_block[i+2] == 0x08) { + break; + } + } + + major = (config_block[i+3] << 8) | config_block[i+4]; + minor = (config_block[i+5] << 8) | config_block[i+6]; + release = (config_block[i+7] << 8) | config_block[i+8]; + + /* Check validity */ + if (major) + return ((major & 0xff) << 8) | ((minor & 0xf) << 4) | ((release & 0xf) + 0xa); + else + return 0; +#else + return 0; +#endif /* BOARD_LATE_INIT */ +} +#endif /* CONFIG_REVISION_TAG */ + +#ifdef CONFIG_SERIAL_TAG +void get_board_serial(struct tag_serialnr *serialnr) +{ +#ifdef BOARD_LATE_INIT + int array[8]; + int i; + unsigned int serial = 0; + unsigned int serial_offset = 11; + + if(config_block == NULL) { + serialnr->low = 0; + serialnr->high = 0; + return; + } + + /* Get MAC address from config block */ + memcpy(&serial, config_block + serial_offset, 3); + serial = ntohl(serial); + serial >>= 8; + + /* Check validity */ + if (serial) { + /* Convert to Linux serial number format (hexadecimal coded decimal) */ + i = 7; + while (serial) { + array[i--] = serial % 10; + serial /= 10; + } + serial = 0; + for (i = 0; i < 8; i++) { + serial += array[i]; + serial *= 16; + } + serial /= 16; + } + + serialnr->low = serial; +#else + serialnr->low = 0; +#endif /* BOARD_LATE_INIT */ + serialnr->high = 0; +} +#endif /* CONFIG_SERIAL_TAG */ + +/* + * Possible UART locations: we ignore UARTC at 0x70006200 and UARTE at + * 0x70006400, since we don't have code to init them + */ +static u32 uart_reg_addr[] = { + NV_PA_APB_UARTA_BASE, + NV_PA_APB_UARTB_BASE, + NV_PA_APB_UARTD_BASE, + 0 +}; + +#ifdef CONFIG_HW_WATCHDOG +/* + * kick watchdog in PMU + * + */ +extern void hw_watchdog_reset(void) +{ +#if defined(CONFIG_TEGRA3) + uchar reg, data_buffer[1]; + static unsigned long last_kick = 0; + unsigned long now; + // only kick the watchdog every 10 seconds, the watchdog timeout is 100s + now = get_ticks(); + //first kick after 10 seconds + if( !i2c_is_initialized || (last_kick == 0) ) { + last_kick = now; + } + else if( (signed)(now - last_kick) > (10 * 1000) ) { + last_kick = now; + data_buffer[0] = 0x10; + reg = 0x54; + i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1); + } +#endif +} +#endif + +/** + * Send out serial output wherever we can. + * + * This function produces a low-level panic message, after setting PLLP + * to the given value. + * + * @param pllp_rate Required PLLP rate (408000000 or 216000000) + * @param str String to output + */ +static void send_output_with_pllp(ulong pllp_rate, const char *str) +{ + int uart_ids = UART_ALL; /* turn it all on! */ + u32 *uart_addr; + int clock_freq, multiplier, baudrate, divisor; + + clock_early_init(pllp_rate); + + /* Try to enable all possible UARTs */ + clock_init_uart(uart_ids); + pin_mux_uart(uart_ids); + +#ifdef CONFIG_TEGRA3 + /* Until we sort out pinmux, we must do the global Tegra3 init */ + pinmux_init(); +#endif + + /* + * Now send the string out all the Tegra UARTs. We don't try all + * possible configurations, but this could be added if required. + */ + clock_freq = pllp_rate; + multiplier = CONFIG_DEFAULT_NS16550_MULT; + baudrate = CONFIG_BAUDRATE; + divisor = (clock_freq + (baudrate * (multiplier / 2))) / + (multiplier * baudrate); + + for (uart_addr = uart_reg_addr; *uart_addr; uart_addr++) { + const char *s; + + NS16550_init((NS16550_t)*uart_addr, divisor); + for (s = str; *s; s++) { + NS16550_putc((NS16550_t)*uart_addr, *s); + if (*s == '\n') + NS16550_putc((NS16550_t)*uart_addr, '\r'); + } + } +} + +/* + * This is called when we have no console. About the only reason that this + * happen is if we don't have a valid fdt. So we don't know what kind of + * Tegra board we are. We blindly try to print a message every which way we + * know. + */ +void board_panic_no_console(const char *str) +{ + /* We don't know what PLLP to use, so try both */ + send_output_with_pllp(216000000, str); + send_output_with_pllp(408000000, str); +} diff --git a/board/toradex/common/board.h b/board/toradex/common/board.h new file mode 100644 index 0000000000..8e0689d509 --- /dev/null +++ b/board/toradex/common/board.h @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2012 + * Toradex, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +void gpio_config_uart(const void *blob); +void gpio_early_init_uart(const void *blob); +void gpio_config_mmc(void); +int tegra_mmc_init(const void *blob); +void lcd_early_init(const void *blob); + +/** + * Perform the next stage of the LCD init if it is time to do so. + * + * LCD init can be time-consuming because of the number of delays we need + * while waiting for the backlight power supply, etc. This function can + * be called at various times during U-Boot operation to advance the + * initialization of the LCD to the next stage if sufficient time has + * passed since the last stage. It keeps track of what stage it is up to + * and the time that it is permitted to move to the next stage. + * + * The final call should have wait=1 to complete the init. + * + * @param blob fdt blob containing LCD information + * @param wait 1 to wait until all init is complete, and then return + * 0 to return immediately, potentially doing nothing if it is + * not yet time for the next init. + */ +int tegra_lcd_check_next_stage(const void *blob, int wait); + +#endif /* BOARD_H */ diff --git a/board/toradex/common/tegra2_nand.c b/board/toradex/common/tegra2_nand.c new file mode 100644 index 0000000000..c1eaa8f429 --- /dev/null +++ b/board/toradex/common/tegra2_nand.c @@ -0,0 +1,1095 @@ +/* + * (C) Copyright 2006 Detlev Zundel, dzu@denx.de + * (C) Copyright 2006 DENX Software Engineering + * (C) Copyright 2011 NVIDIA Corporation + * (C) Copyright 2012 Toradex, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tegra2_nand.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define NAND_CMD_TIMEOUT_MS 10 +#define SCAN_TIMING_VAL 0x3f0bd214 +#define SCAN_TIMING2_VAL 0xb + +static struct nand_ecclayout eccoob = { + .eccpos = { + 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, + 60, 61, 62, 63, + }, +}; + +enum { + ECC_OK, + ECC_TAG_ERROR = 1 << 0, + ECC_DATA_ERROR = 1 << 1 +}; + +struct nand_info { + struct nand_ctlr *reg; +/* + * When running in PIO mode to get READ ID bytes from register + * RESP_0, we need this variable as an index to know which byte in + * register RESP_0 should be read. + * Because common code in nand_base.c invokes read_byte function two times + * for NAND_CMD_READID. + * And our controller returns 4 bytes at once in register RESP_0. + */ + int pio_byte_index; + struct fdt_nand config; +}; + +struct nand_info nand_ctrl; + +/** + * nand_waitfor_cmd_completion - wait for command completion + * @param reg: nand_ctlr structure + * @return: + * 1 - Command completed + * 0 - Timeout + */ +static int nand_waitfor_cmd_completion(struct nand_ctlr *reg) +{ + int i; + u32 reg_val; + + for (i = 0; i < NAND_CMD_TIMEOUT_MS * 1000; i++) { + if ((readl(®->command) & CMD_GO) || + !(readl(®->status) & + STATUS_RBSY0) || + !(readl(®->isr) & + ISR_IS_CMD_DONE)) { + udelay(1); + continue; + } + reg_val = readl(®->dma_mst_ctrl); + /* + * If DMA_MST_CTRL_EN_A_ENABLE or + * DMA_MST_CTRL_EN_B_ENABLE is set, + * that means DMA engine is running, then we + * have to wait until + * DMA_MST_CTRL_IS_DMA_DONE + * is cleared for DMA transfer completion. + */ + if (reg_val & (DMA_MST_CTRL_EN_A_ENABLE | + DMA_MST_CTRL_EN_B_ENABLE)) { + if (reg_val & DMA_MST_CTRL_IS_DMA_DONE) + return 1; + } else + return 1; + udelay(1); + } + return 0; +} + +/** + * nand_read_byte - [DEFAULT] read one byte from the chip + * @param mtd: MTD device structure + * @return: data byte + * + * Default read function for 8bit bus-width + */ +static uint8_t nand_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd->priv; + int dword_read; + struct nand_info *info; + + info = (struct nand_info *) chip->priv; + + dword_read = readl(&info->reg->resp); + dword_read = dword_read >> (8 * info->pio_byte_index); + info->pio_byte_index++; + return (uint8_t) dword_read; +} + +/** + * nand_write_buf - [DEFAULT] write buffer to chip + * @param mtd: MTD device structure + * @param buf: data buffer + * @param len: number of bytes to write + * + * Default write function for 8bit bus-width + */ +static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, + int len) +{ + int i, j, l; + struct nand_chip *chip = mtd->priv; + struct nand_info *info; + + info = (struct nand_info *) chip->priv; + + for (i = 0; i < len / 4; i++) { + l = ((int *)buf)[i]; + writel(l, &info->reg->resp); + writel(CMD_GO | CMD_PIO | CMD_TX | + (CMD_TRANS_SIZE_BYTES4 << + CMD_TRANS_SIZE_SHIFT) + | CMD_A_VALID | CMD_CE0, + &info->reg->command); + + if (!nand_waitfor_cmd_completion(info->reg)) + printf("Command timeout during write_buf\n"); + } + if (len & 3) { + l = 0; + for (j = 0; j < (len & 3); j++) + l |= (((int) buf[i * 4 + j]) << (8 * j)); + + writel(l, &info->reg->resp); + writel(CMD_GO | CMD_PIO | CMD_TX | + (((len & 3) - 1) << CMD_TRANS_SIZE_SHIFT) | + CMD_A_VALID | CMD_CE0, + &info->reg->command); + if (!nand_waitfor_cmd_completion(info->reg)) + printf("Command timeout during write_buf\n"); + } +} + +/** + * nand_read_buf - [DEFAULT] read chip data into buffer + * @param mtd: MTD device structure + * @param buf: buffer to store date + * @param len: number of bytes to read + * + * Default read function for 8bit bus-width + */ +static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +{ + int i, j, l; + struct nand_chip *chip = mtd->priv; + int *buf_dword; + struct nand_info *info; + + info = (struct nand_info *) chip->priv; + + buf_dword = (int *) buf; + for (i = 0; i < len / 4; i++) { + writel(CMD_GO | CMD_PIO | CMD_RX | + (CMD_TRANS_SIZE_BYTES4 << + CMD_TRANS_SIZE_SHIFT) + | CMD_A_VALID | CMD_CE0, + &info->reg->command); + if (!nand_waitfor_cmd_completion(info->reg)) + printf("Command timeout during read_buf\n"); + l = readl(&info->reg->resp); + buf_dword[i] = l; + } + if (len & 3) { + writel(CMD_GO | CMD_PIO | CMD_RX | + (((len & 3) - 1) << CMD_TRANS_SIZE_SHIFT) | + CMD_A_VALID | CMD_CE0, + &info->reg->command); + if (!nand_waitfor_cmd_completion(info->reg)) + printf("Command timeout during read_buf\n"); + l = readl(&info->reg->resp); + for (j = 0; j < (len & 3); j++) + buf[i * 4 + j] = (char) (l >> (8 * j)); + } +} + +/** + * nand_dev_ready - check NAND status is ready or not + * @param mtd: MTD device structure + * @return: + * 1 - ready + * 0 - not ready + */ +static int nand_dev_ready(struct mtd_info *mtd) +{ + register struct nand_chip *chip = mtd->priv; + int reg_val; + struct nand_info *info; + + info = (struct nand_info *) chip->priv; + + reg_val = readl(&info->reg->status); + if (reg_val & STATUS_RBSY0) + return 1; + else + return 0; +} + +/* Hardware specific access to control-lines */ +static void nand_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ +} + +/** + * nand_clear_interrupt_status - clear all interrupt status bits + * @param reg: nand_ctlr structure + */ +static void nand_clear_interrupt_status(struct nand_ctlr *reg) +{ + u32 reg_val; + + /* Clear interrupt status */ + reg_val = readl(®->isr); + writel(reg_val, ®->isr); +} + +/** + * nand_command - [DEFAULT] Send command to NAND device + * @param mtd: MTD device structure + * @param command: the command to be sent + * @param column: the column address for this command, -1 if none + * @param page_addr: the page address for this command, -1 if none + */ +static void nand_command(struct mtd_info *mtd, unsigned int command, + int column, int page_addr) +{ + register struct nand_chip *chip = mtd->priv; + struct nand_info *info; + + info = (struct nand_info *) chip->priv; + + /* + * Write out the command to the device. + */ + if (mtd->writesize < 2048) { + /* + * Only command NAND_CMD_RESET or NAND_CMD_READID will come + * here before mtd->writesize is initialized, we don't have + * any action here because page size of NAND HY27UF084G2B + * is 2048 bytes and mtd->writesize will be 2048 after + * initialized. + */ + } else { + /* Emulate NAND_CMD_READOOB */ + if (command == NAND_CMD_READOOB) { + column += mtd->writesize; + command = NAND_CMD_READ0; + } + + /* Adjust columns for 16 bit bus-width */ + if (column != -1 && (chip->options & NAND_BUSWIDTH_16)) + column >>= 1; + } + + nand_clear_interrupt_status(info->reg); + + /* Stop DMA engine, clear DMA completion status */ + writel(DMA_MST_CTRL_EN_A_DISABLE + | DMA_MST_CTRL_EN_B_DISABLE + | DMA_MST_CTRL_IS_DMA_DONE, + &info->reg->dma_mst_ctrl); + + /* + * Program and erase have their own busy handlers + * status and sequential in needs no delay + */ + switch (command) { + case NAND_CMD_READID: + writel(NAND_CMD_READID, &info->reg->cmd_reg1); + writel(CMD_GO | CMD_CLE | CMD_ALE | CMD_PIO + | CMD_RX | + (CMD_TRANS_SIZE_BYTES4 << CMD_TRANS_SIZE_SHIFT) + | CMD_CE0, + &info->reg->command); + info->pio_byte_index = 0; + break; + case NAND_CMD_READ0: + writel(NAND_CMD_READ0, &info->reg->cmd_reg1); + writel(NAND_CMD_READSTART, &info->reg->cmd_reg2); + writel((page_addr << 16) | (column & 0xFFFF), + &info->reg->addr_reg1); + writel(page_addr >> 16, &info->reg->addr_reg2); + return; + case NAND_CMD_SEQIN: + writel(NAND_CMD_SEQIN, &info->reg->cmd_reg1); + writel(NAND_CMD_PAGEPROG, &info->reg->cmd_reg2); + writel((page_addr << 16) | (column & 0xFFFF), + &info->reg->addr_reg1); + writel(page_addr >> 16, + &info->reg->addr_reg2); + return; + case NAND_CMD_PAGEPROG: + return; + case NAND_CMD_ERASE1: + writel(NAND_CMD_ERASE1, &info->reg->cmd_reg1); + writel(NAND_CMD_ERASE2, &info->reg->cmd_reg2); + writel(page_addr, &info->reg->addr_reg1); + writel(CMD_GO | CMD_CLE | CMD_ALE | + CMD_SEC_CMD | CMD_CE0 | CMD_ALE_BYTES3, + &info->reg->command); + break; + case NAND_CMD_RNDOUT: + return; + case NAND_CMD_ERASE2: + return; + case NAND_CMD_STATUS: + writel(NAND_CMD_STATUS, &info->reg->cmd_reg1); + writel(CMD_GO | CMD_CLE | CMD_PIO | CMD_RX + | (CMD_TRANS_SIZE_BYTES1 << + CMD_TRANS_SIZE_SHIFT) + | CMD_CE0, + &info->reg->command); + info->pio_byte_index = 0; + break; + case NAND_CMD_RESET: + writel(NAND_CMD_RESET, &info->reg->cmd_reg1); + writel(CMD_GO | CMD_CLE | CMD_CE0, + &info->reg->command); + break; + default: + return; + } + if (!nand_waitfor_cmd_completion(info->reg)) + printf("Command 0x%02X timeout\n", command); +} + +/* + * blank_check - check whether the pointed buffer are all FF (blank). + * @param: buf - data buffer for blank check + * @param: len - length of the buffer in byte + * @return: + * 1 - blank + * 0 - non-blank + */ +static int blank_check(u8 *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) + if (buf[i] != 0xFF) + return 0; + return 1; +} + +/* + * check_ecc_error - After a DMA transfer for read, we call this function to + * see whether there is any uncorrectable error on the pointed data buffer + * or oob buffer. + * + * @param reg: nand_ctlr structure + * @param databuf: data buffer + * @param a_len: data buffer length + * @param oobbuf: oob buffer + * @param b_len: oob buffer length + * @return: + * ECC_OK - no ECC error or correctable ECC error + * ECC_TAG_ERROR - uncorrectable tag ECC error + * ECC_DATA_ERROR - uncorrectable data ECC error + * ECC_DATA_ERROR + ECC_TAG_ERROR - uncorrectable data+tag ECC error + */ +static int check_ecc_error(struct nand_ctlr *reg, u8 *databuf, + int a_len, u8 *oobbuf, int b_len) +{ + int return_val = ECC_OK; + u32 reg_val; + + if (!(readl(®->isr) & ISR_IS_ECC_ERR)) + return ECC_OK; + + reg_val = readl(®->dec_status); + if ((reg_val & DEC_STATUS_A_ECC_FAIL) && databuf) { + reg_val = readl(®->bch_dec_status_buf); + /* + * If uncorrectable error occurs on data area, then see whether + * they are all FF. If all are FF, it's a blank page. + * Not error. + */ + if ((reg_val & BCH_DEC_STATUS_FAIL_SEC_FLAG_MASK) && + !blank_check(databuf, a_len)) + return_val |= ECC_DATA_ERROR; + } + + if ((reg_val & DEC_STATUS_B_ECC_FAIL) && oobbuf) { + reg_val = readl(®->bch_dec_status_buf); + /* + * If uncorrectable error occurs on tag area, then see whether + * they are all FF. If all are FF, it's a blank page. + * Not error. + */ + if ((reg_val & BCH_DEC_STATUS_FAIL_TAG_MASK) && + !blank_check(oobbuf, b_len)) + return_val |= ECC_TAG_ERROR; + } + + return return_val; +} + +/** + * start_command - set GO bit to send command to device + * @param reg: nand_ctlr structure + */ +static void start_command(struct nand_ctlr *reg) +{ + u32 reg_val; + + reg_val = readl(®->command); + reg_val |= CMD_GO; + writel(reg_val, ®->command); +} + +/** + * stop_command - clear command GO bit, DMA GO bit, and DMA completion status + * @param reg: nand_ctlr structure + */ +static void stop_command(struct nand_ctlr *reg) +{ + /* Stop command */ + writel(0, ®->command); + + /* Stop DMA engine and clear DMA completion status */ + writel(DMA_MST_CTRL_GO_DISABLE + | DMA_MST_CTRL_IS_DMA_DONE, + ®->dma_mst_ctrl); +} + +/* + * set_bus_width_page_size - set up NAND bus width and page size + * @param info: nand_info structure + * @param *reg_val: address of reg_val + * @return: value is set in reg_val + */ +static void set_bus_width_page_size(struct fdt_nand *config, + u32 *reg_val) +{ + if (config->width == 8) + *reg_val = CFG_BUS_WIDTH_8BIT; + else + *reg_val = CFG_BUS_WIDTH_16BIT; + + if (config->page_data_bytes == 256) + *reg_val |= CFG_PAGE_SIZE_256; + else if (config->page_data_bytes == 512) + *reg_val |= CFG_PAGE_SIZE_512; + else if (config->page_data_bytes == 1024) + *reg_val |= CFG_PAGE_SIZE_1024; + else if (config->page_data_bytes == 2048) + *reg_val |= CFG_PAGE_SIZE_2048; + else if (config->page_data_bytes == 4096) + *reg_val |= CFG_PAGE_SIZE_4096; +} + +/** + * nand_rw_page - page read/write function + * @param mtd: mtd info structure + * @param chip: nand chip info structure + * @param buf: data buffer + * @param page: page number + * @param with_ecc: 1 to enable ECC, 0 to disable ECC + * @param is_writing: 0 for read, 1 for write + * @return: 0 when successfully completed + * -EIO when command timeout + */ +static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int page, int with_ecc, int is_writing) +{ + u32 reg_val; + int tag_size; + struct nand_oobfree *free = chip->ecc.layout->oobfree; + /* 128 is larger than the value that our HW can support. */ + u32 tag_buf[128]; + char *tag_ptr; + struct nand_info *info; + struct fdt_nand *config; + + if (((int) buf) & 0x03) { + printf("buf 0x%X has to be 4-byte aligned\n", (u32) buf); + return -EINVAL; + } + + info = (struct nand_info *) chip->priv; + config = &info->config; + + /* Need to be 4-byte aligned */ + tag_ptr = (char *) &tag_buf; + + stop_command(info->reg); + + writel((1 << chip->page_shift) - 1, &info->reg->dma_cfg_a); + writel((u32) buf, &info->reg->data_block_ptr); + + if (with_ecc) { + writel((u32) tag_ptr, &info->reg->tag_ptr); + if (is_writing) + memcpy(tag_ptr, chip->oob_poi + free->offset, + config->tag_bytes + + config->tag_ecc_bytes); + } else + writel((u32) chip->oob_poi, &info->reg->tag_ptr); + + set_bus_width_page_size(&info->config, ®_val); + + /* Set ECC selection, configure ECC settings */ + if (with_ecc) { + tag_size = config->tag_bytes + config->tag_ecc_bytes; + reg_val |= (CFG_SKIP_SPARE_SEL_4 + | CFG_SKIP_SPARE_ENABLE + | CFG_HW_ECC_CORRECTION_ENABLE + | CFG_ECC_EN_TAG_DISABLE + | CFG_HW_ECC_SEL_RS + | CFG_HW_ECC_ENABLE + | CFG_TVAL4 + | (tag_size - 1)); + + if (!is_writing) { + tag_size += config->skipped_spare_bytes; + invalidate_dcache_range((unsigned long) tag_ptr, + ((unsigned long) tag_ptr) + tag_size); + } else + flush_dcache_range((unsigned long) tag_ptr, + ((unsigned long) tag_ptr) + tag_size); + } else { + tag_size = mtd->oobsize; + reg_val |= (CFG_SKIP_SPARE_DISABLE + | CFG_HW_ECC_CORRECTION_DISABLE + | CFG_ECC_EN_TAG_DISABLE + | CFG_HW_ECC_DISABLE + | (tag_size - 1)); + if (!is_writing) { + invalidate_dcache_range((unsigned long) chip->oob_poi, + ((unsigned long) chip->oob_poi) + tag_size); + } else { + flush_dcache_range((unsigned long) chip->oob_poi, + ((unsigned long) chip->oob_poi) + tag_size); + } + } + writel(reg_val, &info->reg->config); + + if (!is_writing) { + invalidate_dcache_range((unsigned long) buf, + ((unsigned long) buf) + + (1 << chip->page_shift)); + } else { + flush_dcache_range((unsigned long) buf, + ((unsigned long) buf) + + (1 << chip->page_shift)); + } + + writel(BCH_CONFIG_BCH_ECC_DISABLE, &info->reg->bch_config); + + writel(tag_size - 1, &info->reg->dma_cfg_b); + + nand_clear_interrupt_status(info->reg); + + reg_val = CMD_CLE | CMD_ALE + | CMD_SEC_CMD + | (CMD_ALE_BYTES5 << CMD_ALE_BYTE_SIZE_SHIFT) + | CMD_A_VALID + | CMD_B_VALID + | (CMD_TRANS_SIZE_BYTES_PAGE_SIZE_SEL << + CMD_TRANS_SIZE_SHIFT) + | CMD_CE0; + if (!is_writing) + reg_val |= (CMD_AFT_DAT_DISABLE | CMD_RX); + else + reg_val |= (CMD_AFT_DAT_ENABLE | CMD_TX); + writel(reg_val, &info->reg->command); + + /* Setup DMA engine */ + reg_val = DMA_MST_CTRL_GO_ENABLE + | DMA_MST_CTRL_BURST_8WORDS + | DMA_MST_CTRL_EN_A_ENABLE + | DMA_MST_CTRL_EN_B_ENABLE; + + if (!is_writing) + reg_val |= DMA_MST_CTRL_DIR_READ; + else + reg_val |= DMA_MST_CTRL_DIR_WRITE; + + writel(reg_val, &info->reg->dma_mst_ctrl); + + start_command(info->reg); + + if (!nand_waitfor_cmd_completion(info->reg)) { + if (!is_writing) + printf("Read Page 0x%X timeout ", page); + else + printf("Write Page 0x%X timeout ", page); + if (with_ecc) + printf("with ECC"); + else + printf("without ECC"); + printf("\n"); + return -EIO; + } + + if (with_ecc && !is_writing) { + memcpy(chip->oob_poi, tag_ptr, + config->skipped_spare_bytes); + memcpy(chip->oob_poi + free->offset, + tag_ptr + config->skipped_spare_bytes, + config->tag_bytes); + reg_val = (u32) check_ecc_error(info->reg, (u8 *) buf, + 1 << chip->page_shift, + (u8 *) (tag_ptr + config->skipped_spare_bytes), + config->tag_bytes); + if (reg_val & ECC_TAG_ERROR) + printf("Read Page 0x%X tag ECC error\n", page); + if (reg_val & ECC_DATA_ERROR) + printf("Read Page 0x%X data ECC error\n", + page); + if (reg_val & (ECC_DATA_ERROR | ECC_TAG_ERROR)) + return -EIO; + } + return 0; +} + +/** + * nand_read_page_hwecc - hardware ecc based page read function + * @param mtd: mtd info structure + * @param chip: nand chip info structure + * @param buf: buffer to store read data + * @param page: page number to read + * @return: 0 when successfully completed + * -EIO when command timeout + */ +static int nand_read_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) +{ + return nand_rw_page(mtd, chip, buf, page, 1, 0); +} + +/** + * nand_write_page_hwecc - hardware ecc based page write function + * @param mtd: mtd info structure + * @param chip: nand chip info structure + * @param buf: data buffer + */ +static void nand_write_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) +{ + int page; + struct nand_info *info; + + info = (struct nand_info *) chip->priv; + + page = (readl(&info->reg->addr_reg1) >> 16) | + (readl(&info->reg->addr_reg2) << 16); + + nand_rw_page(mtd, chip, (uint8_t *) buf, page, 1, 1); +} + + +/** + * nand_read_page_raw - read raw page data without ecc + * @param mtd: mtd info structure + * @param chip: nand chip info structure + * @param buf: buffer to store read data + * @param page: page number to read + * @return: 0 when successfully completed + * -EINVAL when chip->oob_poi is not double-word aligned + * -EIO when command timeout + */ +static int nand_read_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) +{ + return nand_rw_page(mtd, chip, buf, page, 0, 0); +} + +/** + * nand_write_page_raw - raw page write function + * @param mtd: mtd info structure + * @param chip: nand chip info structure + * @param buf: data buffer + */ +static void nand_write_page_raw(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) +{ + int page; + struct nand_info *info; + + info = (struct nand_info *) chip->priv; + page = (readl(&info->reg->addr_reg1) >> 16) | + (readl(&info->reg->addr_reg2) << 16); + + nand_rw_page(mtd, chip, (uint8_t *) buf, page, 0, 1); +} + +/** + * nand_rw_oob - OOB data read/write function + * @param mtd: mtd info structure + * @param chip: nand chip info structure + * @param page: page number to read + * @param with_ecc: 1 to enable ECC, 0 to disable ECC + * @param is_writing: 0 for read, 1 for write + * @return: 0 when successfully completed + * -EINVAL when chip->oob_poi is not double-word aligned + * -EIO when command timeout + */ +static int nand_rw_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page, int with_ecc, int is_writing) +{ + u32 reg_val; + int tag_size; + struct nand_oobfree *free = chip->ecc.layout->oobfree; + struct nand_info *info; + + if (((int) chip->oob_poi) & 0x03) + return -EINVAL; + + info = (struct nand_info *) chip->priv; + stop_command(info->reg); + + writel((u32) chip->oob_poi, &info->reg->tag_ptr); + + set_bus_width_page_size(&info->config, ®_val); + + /* Set ECC selection */ + tag_size = mtd->oobsize; + if (with_ecc) + reg_val |= CFG_ECC_EN_TAG_ENABLE; + else + reg_val |= (CFG_ECC_EN_TAG_DISABLE); + + reg_val |= ((tag_size - 1) | + CFG_SKIP_SPARE_DISABLE | + CFG_HW_ECC_CORRECTION_DISABLE | + CFG_HW_ECC_DISABLE); + writel(reg_val, &info->reg->config); + + if (!is_writing) + invalidate_dcache_range((unsigned long) chip->oob_poi, + ((unsigned long) chip->oob_poi) + tag_size); + else + flush_dcache_range((unsigned long) chip->oob_poi, + ((unsigned long) chip->oob_poi) + tag_size); + + writel(BCH_CONFIG_BCH_ECC_DISABLE, &info->reg->bch_config); + + if (is_writing && with_ecc) + tag_size -= info->config.tag_ecc_bytes; + + writel(tag_size - 1, &info->reg->dma_cfg_b); + + nand_clear_interrupt_status(info->reg); + + reg_val = CMD_CLE | CMD_ALE + | CMD_SEC_CMD + | (CMD_ALE_BYTES5 << CMD_ALE_BYTE_SIZE_SHIFT) + | CMD_B_VALID + | CMD_CE0; + if (!is_writing) + reg_val |= (CMD_AFT_DAT_DISABLE | CMD_RX); + else + reg_val |= (CMD_AFT_DAT_ENABLE | CMD_TX); + writel(reg_val, &info->reg->command); + + /* Setup DMA engine */ + reg_val = DMA_MST_CTRL_GO_ENABLE + | DMA_MST_CTRL_BURST_8WORDS + | DMA_MST_CTRL_EN_B_ENABLE; + if (!is_writing) + reg_val |= DMA_MST_CTRL_DIR_READ; + else + reg_val |= DMA_MST_CTRL_DIR_WRITE; + + writel(reg_val, &info->reg->dma_mst_ctrl); + + start_command(info->reg); + + if (!nand_waitfor_cmd_completion(info->reg)) { + if (!is_writing) + printf("Read OOB of Page 0x%X timeout\n", page); + else + printf("Write OOB of Page 0x%X timeout\n", page); + return -EIO; + } + + if (with_ecc && !is_writing) { + reg_val = (u32) check_ecc_error(info->reg, 0, 0, + (u8 *) (chip->oob_poi + free->offset), + info->config.tag_bytes); + if (reg_val & ECC_TAG_ERROR) + printf("Read OOB of Page 0x%X tag ECC error\n", page); + } + return 0; +} + +/** + * nand_read_oob - OOB data read function + * @param mtd: mtd info structure + * @param chip: nand chip info structure + * @param page: page number to read + * @param sndcmd: flag whether to issue read command or not + * @return: 1 - issue read command next time + * 0 - not to issue + */ +static int nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page, int sndcmd) +{ + if (sndcmd) { + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + sndcmd = 0; + } + nand_rw_oob(mtd, chip, page, 0, 0); + return sndcmd; +} + +/** + * nand_write_oob - OOB data write function + * @param mtd: mtd info structure + * @param chip: nand chip info structure + * @param page: page number to write + * @return: 0 when successfully completed + * -EINVAL when chip->oob_poi is not double-word aligned + * -EIO when command timeout + */ +static int nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); + + return nand_rw_oob(mtd, chip, page, 0, 1); +} + +static void setup_timing(int timing[FDT_NAND_TIMING_COUNT], + struct nand_ctlr *reg) +{ + u32 reg_val, clk_rate, clk_period, time_val; + + clk_rate = (u32) clock_get_periph_rate(PERIPH_ID_NDFLASH, + CLOCK_ID_PERIPH) / 1000000; + clk_period = 1000 / clk_rate; + reg_val = ((timing[FDT_NAND_MAX_TRP_TREA] / clk_period) << + TIMING_TRP_RESP_CNT_SHIFT) & TIMING_TRP_RESP_CNT_MASK; + reg_val |= ((timing[FDT_NAND_TWB] / clk_period) << + TIMING_TWB_CNT_SHIFT) & TIMING_TWB_CNT_MASK; + time_val = timing[FDT_NAND_MAX_TCR_TAR_TRR] / clk_period; + if (time_val > 2) + reg_val |= ((time_val - 2) << TIMING_TCR_TAR_TRR_CNT_SHIFT) & + TIMING_TCR_TAR_TRR_CNT_MASK; + reg_val |= ((timing[FDT_NAND_TWHR] / clk_period) << + TIMING_TWHR_CNT_SHIFT) & TIMING_TWHR_CNT_MASK; + time_val = timing[FDT_NAND_MAX_TCS_TCH_TALS_TALH] / clk_period; + if (time_val > 1) + reg_val |= ((time_val - 1) << TIMING_TCS_CNT_SHIFT) & + TIMING_TCS_CNT_MASK; + reg_val |= ((timing[FDT_NAND_TWH] / clk_period) << + TIMING_TWH_CNT_SHIFT) & TIMING_TWH_CNT_MASK; + reg_val |= ((timing[FDT_NAND_TWP] / clk_period) << + TIMING_TWP_CNT_SHIFT) & TIMING_TWP_CNT_MASK; + reg_val |= ((timing[FDT_NAND_TRH] / clk_period) << + TIMING_TRH_CNT_SHIFT) & TIMING_TRH_CNT_MASK; + reg_val |= ((timing[FDT_NAND_MAX_TRP_TREA] / clk_period) << + TIMING_TRP_CNT_SHIFT) & TIMING_TRP_CNT_MASK; + writel(reg_val, ®->timing); + + reg_val = 0; + time_val = timing[FDT_NAND_TADL] / clk_period; + if (time_val > 2) + reg_val = (time_val - 2) & TIMING2_TADL_CNT_MASK; + writel(reg_val, ®->timing2); +} + +/* + * Board-specific NAND initialization. + * @param nand: nand chip info structure + * @return: 0, after initialized. + */ +int board_nand_init(struct nand_chip *nand) +{ + struct nand_info *info = &nand_ctrl; + struct fdt_nand *config = &info->config; + struct mtd_info tmp_mtd; + int tmp_manf, tmp_id, tmp_4th; + char compat[8]; + int node; + +#ifndef CONFIG_COLIBRI_T30 + /* Adjust controller clock rate */ + clock_start_periph_pll(PERIPH_ID_NDFLASH, CLOCK_ID_PERIPH, CLK_52M); + + /* Pinmux KBCx_SEL uses NAND */ +//move to board configuration + pinmux_set_func(PINGRP_KBCA, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_KBCB, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_KBCC, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_KBCD, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_KBCE, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_KBCF, PMUX_FUNC_NAND); +#else + /* Adjust controller clock rate */ + clock_start_periph_pll(PERIPH_ID_NDFLASH, CLOCK_ID_PERIPH, CLK_52M); + + /* Pinmux NAND on GMI*/ + //TODO move to board configuration + pinmux_set_func(PINGRP_GMI_AD0, PMUX_FUNC_NAND); /* nand D[0:7] */ + pinmux_set_func(PINGRP_GMI_AD1, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_GMI_AD2, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_GMI_AD3, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_GMI_AD4, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_GMI_AD5, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_GMI_AD6, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_GMI_AD7, PMUX_FUNC_NAND); + pinmux_set_func(PINGRP_GMI_ADV_N, PMUX_FUNC_NAND); /* nand ALE */ + pinmux_set_func(PINGRP_GMI_CLK, PMUX_FUNC_NAND); /* nand CLE */ + pinmux_set_func(PINGRP_GMI_CS2_N, PMUX_FUNC_NAND); /* nand CE0_N */ + pinmux_set_func(PINGRP_GMI_CS3_N, PMUX_FUNC_NAND); /* nand CE1_N */ +#if 0 /* on T30 only CE0 is used, the following are reserved */ + pinmux_set_func(PINGRP_GMI_CS4_N, PMUX_FUNC_NAND); /* nand CE2_N */ + pinmux_set_func(PINGRP_GMI_IORDY, PMUX_FUNC_NAND); /* nand CE3_N */ +#endif + pinmux_set_func(PINGRP_GMI_DQS, PMUX_FUNC_NAND); /* nand DQS, used only for sync nands */ + pinmux_set_func(PINGRP_GMI_OE_N, PMUX_FUNC_NAND); /* nand RE */ + pinmux_set_func(PINGRP_GMI_WAIT, PMUX_FUNC_NAND); /* nand BSY */ + pinmux_set_func(PINGRP_GMI_WP_N, PMUX_FUNC_GMI); /* nand WP, note that this special function is shared with GMI_WP, probably, at least that is what I read in DG-05576-001_v08_InterfaceDesignGuide*/ + pinmux_set_func(PINGRP_GMI_WR_N, PMUX_FUNC_NAND); /* nand WE */ +#endif + nand->priv = &nand_ctrl; + + /* Setup fake MTD structure */ + tmp_mtd.priv = nand; + tmp_mtd.writesize = 0; + info->reg = (void *)0x70008000; + +#ifdef CONFIG_COLIBRI_T30 + /* MAX Set compatibility to Tegra 2 */ + printf("InitTiming "); + printf("NAND Config2 was %X ", readl((unsigned *)0x70008000 + 0xd8) ); + + writel(0, (unsigned *)0x70008000 + 0xd8); + printf("changed to %X \n", readl((unsigned *)0x70008000 + 0xd8) ); +#endif + +#if 0 + printf(" CLK_RST_CONTROLLER_RST_DEVICES_L_0 0x%8x \n", readl( (unsigned*)0x60006004 ) & (1<<13)); + printf(" CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0 0x%8x \n", readl( (unsigned*)0x60006010 ) & (1<<13)); + printf(" CLK_RST_CONTROLLER_CLK_SOURCE_NDFLASH_0 0x%8x \n", readl( (unsigned*)0x60006160 )); + printf("status 0x%8x \n", readl(&(info->reg->status)) ); + printf("isr 0x%8x \n", readl(&(info->reg->isr)) ); + printf("ier 0x%8x \n", readl(&(info->reg->ier)) ); + printf("config 0x%8x \n", readl(&(info->reg->config)) ); + printf("timing 0x%8x \n", readl(&(info->reg->timing)) ); + printf("resp 0x%8x \n", readl(&(info->reg->resp)) ); + printf("timing2 0x%8x \n", readl(&(info->reg->timing2)) ); + printf("command 0x%8x \n", readl(&(info->reg->command)) ); + printf("status 0x%8x \n", readl(&(info->reg->status)) ); + printf("isr 0x%8x \n", readl(&(info->reg->isr)) ); + printf("ier 0x%8x \n", readl(&(info->reg->ier)) ); + printf("config 0x%8x \n", readl(&(info->reg->config)) ); + printf("timing 0x%8x \n", readl(&(info->reg->timing)) ); + printf("resp 0x%8x \n", readl(&(info->reg->resp)) ); + printf("timing2 0x%8x \n", readl(&(info->reg->timing2)) ); + printf("cmd_reg1 0x%8x \n", readl(&(info->reg->cmd_reg1)) ); + printf("cmd_reg2 0x%8x \n", readl(&(info->reg->cmd_reg2)) ); + printf("addr_reg1 0x%8x \n", readl(&(info->reg->addr_reg1)) ); + printf("addr_reg2 0x%8x \n", readl(&(info->reg->addr_reg2)) ); + printf("dma_mst_ctrl 0x%8x \n", readl(&(info->reg->dma_mst_ctrl)) ); + printf("dma_cfg_a 0x%8x \n", readl(&(info->reg->dma_cfg_a)) ); + printf("dma_cfg_b 0x%8x \n", readl(&(info->reg->dma_cfg_b)) ); + printf("fifo_ctrl 0x%8x \n", readl(&(info->reg->fifo_ctrl)) ); + printf("data_block_ptr 0x%8x \n", readl(&(info->reg->data_block_ptr)) ); + printf("tag_ptr 0x%8x \n", readl(&(info->reg->tag_ptr)) ); + printf("dec_status 0x%8x \n", readl(&(info->reg->dec_status)) ); + printf("hwstatus_cmd 0x%8x \n", readl(&(info->reg->hwstatus_cmd)) ); + printf("hwstatus_mask 0x%8x \n", readl(&(info->reg->hwstatus_mask)) ); + printf("bch_config 0x%8x \n", readl(&(info->reg->bch_config)) ); + printf("bch_dec_result 0x%8x \n", readl(&(info->reg->bch_dec_result)) ); + printf("bch_dec_status_buf 0x%8x \n", readl(&(info->reg->bch_dec_status_buf)) ); +#endif + /* Set initial scan timing */ + writel(SCAN_TIMING_VAL, &(info->reg->timing)); + writel(SCAN_TIMING2_VAL, &(info->reg->timing2)); + /* reset the nand, as the bootrom does this only when nand is the bootdevice */ + nand_command(&tmp_mtd, NAND_CMD_RESET, -1, -1); + +#ifdef CONFIG_COLIBRI_T30 + printf("ReadID "); +#endif + /* Send command for reading device ID */ + nand_command(&tmp_mtd, NAND_CMD_READID, 0x00, -1); + + /* Read manufacturer and device IDs */ + tmp_manf = nand_read_byte(&tmp_mtd); + tmp_id = nand_read_byte(&tmp_mtd); + tmp_4th = nand_read_byte(&tmp_mtd); /* the 3rd byte is not needed, skip over it */ + tmp_4th = nand_read_byte(&tmp_mtd); + +#ifdef CONFIG_COLIBRI_T30 + printf("NAND ReadID Man %02X, ID %02X, 3th %02X, 4th %02X", tmp_manf, tmp_id, tmp_3rd, tmp_4th); +#endif + + sprintf(compat, "%02X,%02X,%02X", tmp_manf, tmp_id, tmp_4th); + node = fdt_node_offset_by_compatible(gd->blob, 0, compat); + if (node < 0) { +//fall back to former nand-flash node + printf("Could not find NAND flash device node\n"); + return -1; + } + if (fdt_decode_nand(gd->blob, node, config)) { + printf("Could not decode NAND flash device node\n"); + return -1; + } + + //copy partition information to global data + gd->env_offset = (unsigned)(config->nv_partitions[FDT_NAND_ENV_OFFSET]); + gd->conf_blk_offset = (unsigned)(config->nv_partitions[FDT_NAND_CONFIG_OFFSET]); + gd->conf_blk_offset2 = (unsigned)(config->nv_partitions[FDT_NAND_CONFIG_OFFSET2]); + gd->kernel_offset = (unsigned)(config->nv_partitions[FDT_NAND_KERNEL_OFFSET]); + gd->rootfs_size = (unsigned)(config->nv_partitions[FDT_NAND_ROOTFS_LENGTH]); + gd->rootfs_offset = (unsigned)(config->nv_partitions[FDT_NAND_ROOTFS_SIZE]); + + if (!config->enabled) + return -1; + info->reg = config->reg; + + eccoob.eccbytes = config->data_ecc_bytes + config->tag_ecc_bytes; + eccoob.oobavail = config->tag_bytes; + eccoob.oobfree[0].offset = config->skipped_spare_bytes + + config->data_ecc_bytes; + eccoob.oobfree[0].length = config->tag_bytes; + + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.layout = &eccoob; + nand->ecc.size = config->page_data_bytes; + nand->ecc.bytes = config->page_spare_bytes; + + nand->options = LP_OPTIONS; + nand->cmdfunc = nand_command; + nand->read_byte = nand_read_byte; + nand->read_buf = nand_read_buf; + nand->write_buf = nand_write_buf; + nand->ecc.read_page = nand_read_page_hwecc; + nand->ecc.write_page = nand_write_page_hwecc; + nand->ecc.read_page_raw = nand_read_page_raw; + nand->ecc.write_page_raw = nand_write_page_raw; + nand->ecc.read_oob = nand_read_oob; + nand->ecc.write_oob = nand_write_oob; + nand->cmd_ctrl = nand_hwcontrol; + nand->dev_ready = nand_dev_ready; + + /* Adjust timing for NAND device */ + setup_timing(config->timing, info->reg); + + fdt_setup_gpio(&config->wp_gpio); + + return 0; +} diff --git a/board/toradex/common/tegra2_nand.h b/board/toradex/common/tegra2_nand.h new file mode 100644 index 0000000000..9ecb80c50f --- /dev/null +++ b/board/toradex/common/tegra2_nand.h @@ -0,0 +1,280 @@ +enum { + Bit0 = 1 << 0, + Bit1 = 1 << 1, + Bit2 = 1 << 2, + Bit3 = 1 << 3, + Bit4 = 1 << 4, + Bit5 = 1 << 5, + Bit6 = 1 << 6, + Bit7 = 1 << 7, + Bit8 = 1 << 8, + Bit9 = 1 << 9, + Bit10 = 1 << 10, + Bit11 = 1 << 11, + Bit12 = 1 << 12, + Bit13 = 1 << 13, + Bit14 = 1 << 14, + Bit15 = 1 << 15, + Bit16 = 1 << 16, + Bit17 = 1 << 17, + Bit18 = 1 << 18, + Bit19 = 1 << 19, + Bit20 = 1 << 20, + Bit21 = 1 << 21, + Bit22 = 1 << 22, + Bit23 = 1 << 23, + Bit24 = 1 << 24, + Bit25 = 1 << 25, + Bit26 = 1 << 26, + Bit27 = 1 << 27, + Bit28 = 1 << 28, + Bit29 = 1 << 29, + Bit30 = 1 << 30, + Bit31 = 1 << 31 +}; + +/* register offset */ +#define COMMAND_0 0x00 +#define CMD_GO Bit31 +#define CMD_CLE Bit30 +#define CMD_ALE Bit29 +#define CMD_PIO Bit28 +#define CMD_TX Bit27 +#define CMD_RX Bit26 +#define CMD_SEC_CMD Bit25 +#define CMD_AFT_DAT_MASK Bit24 +#define CMD_AFT_DAT_DISABLE 0 +#define CMD_AFT_DAT_ENABLE Bit24 +#define CMD_TRANS_SIZE_SHIFT 20 +enum { + CMD_TRANS_SIZE_BYTES1 = 0, + CMD_TRANS_SIZE_BYTES2, + CMD_TRANS_SIZE_BYTES3, + CMD_TRANS_SIZE_BYTES4, + CMD_TRANS_SIZE_BYTES5, + CMD_TRANS_SIZE_BYTES6, + CMD_TRANS_SIZE_BYTES7, + CMD_TRANS_SIZE_BYTES8, + CMD_TRANS_SIZE_BYTES_PAGE_SIZE_SEL +}; + +#define CMD_TRANS_SIZE_BYTES_PAGE_SIZE_SEL 8 +#define CMD_A_VALID Bit19 +#define CMD_B_VALID Bit18 +#define CMD_RD_STATUS_CHK Bit17 +#define CMD_R_BSY_CHK Bit16 +#define CMD_CE7 Bit15 +#define CMD_CE6 Bit14 +#define CMD_CE5 Bit13 +#define CMD_CE4 Bit12 +#define CMD_CE3 Bit11 +#define CMD_CE2 Bit10 +#define CMD_CE1 Bit9 +#define CMD_CE0 Bit8 +#define CMD_CLE_BYTE_SIZE_SHIFT 4 +enum { + CMD_CLE_BYTES1 = 0, + CMD_CLE_BYTES2, + CMD_CLE_BYTES3, + CMD_CLE_BYTES4, +}; +#define CMD_ALE_BYTE_SIZE_SHIFT 0 +enum { + CMD_ALE_BYTES1 = 0, + CMD_ALE_BYTES2, + CMD_ALE_BYTES3, + CMD_ALE_BYTES4, + CMD_ALE_BYTES5, + CMD_ALE_BYTES6, + CMD_ALE_BYTES7, + CMD_ALE_BYTES8 +}; + +#define STATUS_0 0x04 +#define STATUS_RBSY0 Bit8 + +#define ISR_0 0x08 +#define ISR_IS_CMD_DONE Bit5 +#define ISR_IS_ECC_ERR Bit4 + +#define IER_0 0x0C + +#define CFG_0 0x10 +#define CFG_HW_ECC_MASK Bit31 +#define CFG_HW_ECC_DISABLE 0 +#define CFG_HW_ECC_ENABLE Bit31 +#define CFG_HW_ECC_SEL_MASK Bit30 +#define CFG_HW_ECC_SEL_HAMMING 0 +#define CFG_HW_ECC_SEL_RS Bit30 +#define CFG_HW_ECC_CORRECTION_MASK Bit29 +#define CFG_HW_ECC_CORRECTION_DISABLE 0 +#define CFG_HW_ECC_CORRECTION_ENABLE Bit29 +#define CFG_PIPELINE_EN_MASK Bit28 +#define CFG_PIPELINE_EN_DISABLE 0 +#define CFG_PIPELINE_EN_ENABLE Bit28 +#define CFG_ECC_EN_TAG_MASK Bit27 +#define CFG_ECC_EN_TAG_DISABLE 0 +#define CFG_ECC_EN_TAG_ENABLE Bit27 +#define CFG_TVALUE_MASK (Bit25 | Bit24) +enum { + CFG_TVAL4 = 0 << 24, + CFG_TVAL6 = 1 << 24, + CFG_TVAL8 = 2 << 24 +}; +#define CFG_SKIP_SPARE_MASK Bit23 +#define CFG_SKIP_SPARE_DISABLE 0 +#define CFG_SKIP_SPARE_ENABLE Bit23 +#define CFG_COM_BSY_MASK Bit22 +#define CFG_COM_BSY_DISABLE 0 +#define CFG_COM_BSY_ENABLE Bit22 +#define CFG_BUS_WIDTH_MASK Bit21 +#define CFG_BUS_WIDTH_8BIT 0 +#define CFG_BUS_WIDTH_16BIT Bit21 +#define CFG_LPDDR1_MODE_MASK Bit20 +#define CFG_LPDDR1_MODE_DISABLE 0 +#define CFG_LPDDR1_MODE_ENABLE Bit20 +#define CFG_EDO_MODE_MASK Bit19 +#define CFG_EDO_MODE_DISABLE 0 +#define CFG_EDO_MODE_ENABLE Bit19 +#define CFG_PAGE_SIZE_SEL_MASK (Bit18 | Bit17 | Bit16) +enum { + CFG_PAGE_SIZE_256 = 0 << 16, + CFG_PAGE_SIZE_512 = 1 << 16, + CFG_PAGE_SIZE_1024 = 2 << 16, + CFG_PAGE_SIZE_2048 = 3 << 16, + CFG_PAGE_SIZE_4096 = 4 << 16 +}; +#define CFG_SKIP_SPARE_SEL_MASK (Bit15 | Bit14) +enum { + CFG_SKIP_SPARE_SEL_4 = 0 << 14, + CFG_SKIP_SPARE_SEL_8 = 1 << 14, + CFG_SKIP_SPARE_SEL_12 = 2 << 14, + CFG_SKIP_SPARE_SEL_16 = 3 << 14 +}; +#define CFG_TAG_BYTE_SIZE_MASK 0x1FF + +#define TIMING_0 0x14 +#define TIMING_TRP_RESP_CNT_SHIFT 28 +#define TIMING_TRP_RESP_CNT_MASK (Bit31 | Bit30 | Bit29 | Bit28) +#define TIMING_TWB_CNT_SHIFT 24 +#define TIMING_TWB_CNT_MASK (Bit27 | Bit26 | Bit25 | Bit24) +#define TIMING_TCR_TAR_TRR_CNT_SHIFT 20 +#define TIMING_TCR_TAR_TRR_CNT_MASK (Bit23 | Bit22 | Bit21 | Bit20) +#define TIMING_TWHR_CNT_SHIFT 16 +#define TIMING_TWHR_CNT_MASK (Bit19 | Bit18 | Bit17 | Bit16) +#define TIMING_TCS_CNT_SHIFT 14 +#define TIMING_TCS_CNT_MASK (Bit15 | Bit14) +#define TIMING_TWH_CNT_SHIFT 12 +#define TIMING_TWH_CNT_MASK (Bit13 | Bit12) +#define TIMING_TWP_CNT_SHIFT 8 +#define TIMING_TWP_CNT_MASK (Bit11 | Bit10 | Bit9 | Bit8) +#define TIMING_TRH_CNT_SHIFT 4 +#define TIMING_TRH_CNT_MASK (Bit5 | Bit4) +#define TIMING_TRP_CNT_SHIFT 0 +#define TIMING_TRP_CNT_MASK (Bit3 | Bit2 | Bit1 | Bit0) + +#define RESP_0 0x18 + +#define TIMING2_0 0x1C +#define TIMING2_TADL_CNT_SHIFT 0 +#define TIMING2_TADL_CNT_MASK (Bit3 | Bit2 | Bit1 | Bit0) + +#define CMD_REG1_0 0x20 +#define CMD_REG2_0 0x24 +#define ADDR_REG1_0 0x28 +#define ADDR_REG2_0 0x2C + +#define DMA_MST_CTRL_0 0x30 +#define DMA_MST_CTRL_GO_MASK Bit31 +#define DMA_MST_CTRL_GO_DISABLE 0 +#define DMA_MST_CTRL_GO_ENABLE Bit31 +#define DMA_MST_CTRL_DIR_MASK Bit30 +#define DMA_MST_CTRL_DIR_READ 0 +#define DMA_MST_CTRL_DIR_WRITE Bit30 +#define DMA_MST_CTRL_PERF_EN_MASK Bit29 +#define DMA_MST_CTRL_PERF_EN_DISABLE 0 +#define DMA_MST_CTRL_PERF_EN_ENABLE Bit29 +#define DMA_MST_CTRL_REUSE_BUFFER_MASK Bit27 +#define DMA_MST_CTRL_REUSE_BUFFER_DISABLE 0 +#define DMA_MST_CTRL_REUSE_BUFFER_ENABLE Bit27 +#define DMA_MST_CTRL_BURST_SIZE_MASK (Bit26 | Bit25 | Bit24) +enum { + DMA_MST_CTRL_BURST_1WORDS = 2 << 24, + DMA_MST_CTRL_BURST_4WORDS = 3 << 24, + DMA_MST_CTRL_BURST_8WORDS = 4 << 24, + DMA_MST_CTRL_BURST_16WORDS = 5 << 24 +}; +#define DMA_MST_CTRL_IS_DMA_DONE Bit20 +#define DMA_MST_CTRL_EN_A_MASK Bit2 +#define DMA_MST_CTRL_EN_A_DISABLE 0 +#define DMA_MST_CTRL_EN_A_ENABLE Bit2 +#define DMA_MST_CTRL_EN_B_MASK Bit1 +#define DMA_MST_CTRL_EN_B_DISABLE 0 +#define DMA_MST_CTRL_EN_B_ENABLE Bit1 + +#define DMA_CFG_A_0 0x34 +#define DMA_CFG_B_0 0x38 +#define FIFO_CTRL_0 0x3C +#define DATA_BLOCK_PTR_0 0x40 +#define TAG_PTR_0 0x44 +#define ECC_PTR_0 0x48 + +#define DEC_STATUS_0 0x4C +#define DEC_STATUS_A_ECC_FAIL Bit1 +#define DEC_STATUS_B_ECC_FAIL Bit0 + +#define BCH_CONFIG_0 0xCC +#define BCH_CONFIG_BCH_TVALUE_MASK (Bit5 | Bit4) +enum { + BCH_CONFIG_BCH_TVAL4 = 0 << 4, + BCH_CONFIG_BCH_TVAL8 = 1 << 4, + BCH_CONFIG_BCH_TVAL14 = 2 << 4, + BCH_CONFIG_BCH_TVAL16 = 3 << 4 +}; +#define BCH_CONFIG_BCH_ECC_MASK Bit0 +#define BCH_CONFIG_BCH_ECC_DISABLE 0 +#define BCH_CONFIG_BCH_ECC_ENABLE Bit0 + +#define BCH_DEC_RESULT_0 0xD0 +#define BCH_DEC_RESULT_CORRFAIL_ERR_MASK Bit8 +#define BCH_DEC_RESULT_PAGE_COUNT_MASK 0xFF + +#define BCH_DEC_STATUS_BUF_0 0xD4 +#define BCH_DEC_STATUS_FAIL_SEC_FLAG_MASK 0xFF000000 +#define BCH_DEC_STATUS_CORR_SEC_FLAG_MASK 0x00FF0000 +#define BCH_DEC_STATUS_FAIL_TAG_MASK Bit14 +#define BCH_DEC_STATUS_CORR_TAG_MASK Bit13 +#define BCH_DEC_STATUS_MAX_CORR_CNT_MASK (Bit12 | Bit11 | Bit10 | Bit9 | Bit8) +#define BCH_DEC_STATUS_PAGE_NUMBER_MASK 0xFF + +#define LP_OPTIONS (NAND_NO_READRDY | NAND_NO_AUTOINCR) + +struct nand_ctlr { + u32 command; /* offset 00h */ + u32 status; /* offset 04h */ + u32 isr; /* offset 08h */ + u32 ier; /* offset 0Ch */ + u32 config; /* offset 10h */ + u32 timing; /* offset 14h */ + u32 resp; /* offset 18h */ + u32 timing2; /* offset 1Ch */ + u32 cmd_reg1; /* offset 20h */ + u32 cmd_reg2; /* offset 24h */ + u32 addr_reg1; /* offset 28h */ + u32 addr_reg2; /* offset 2Ch */ + u32 dma_mst_ctrl; /* offset 30h */ + u32 dma_cfg_a; /* offset 34h */ + u32 dma_cfg_b; /* offset 38h */ + u32 fifo_ctrl; /* offset 3Ch */ + u32 data_block_ptr; /* offset 40h */ + u32 tag_ptr; /* offset 44h */ + u32 resv1; /* offset 48h */ + u32 dec_status; /* offset 4Ch */ + u32 hwstatus_cmd; /* offset 50h */ + u32 hwstatus_mask; /* offset 54h */ + u32 resv2[29]; + u32 bch_config; /* offset CCh */ + u32 bch_dec_result; /* offset D0h */ + u32 bch_dec_status_buf; + /* offset D4h */ +}; diff --git a/board/toradex/common/ulpi_linux.c b/board/toradex/common/ulpi_linux.c new file mode 100644 index 0000000000..b3f617152a --- /dev/null +++ b/board/toradex/common/ulpi_linux.c @@ -0,0 +1,194 @@ +/* + * ulpi_linux.c + * + * this file is ulpi_phy_power_on() function taken from + * arch/arm/mach-tegra/usb_phy.c linux kernel code, slightly + * modified for U-Boot by Ant Micro + * + * Original arch/arm/mach-tegra/usb_phy.c Copyrights: + * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2010 - 2011 NVIDIA Corporation + * Erik Gilling + * Benoit Goby + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +#define ULPI_VIEWPORT 0x170 +#define ULPI_WAKEUP (1 << 31) +#define ULPI_RUN (1 << 30) +#define ULPI_RD_RW_WRITE (1 << 29) +#define ULPI_RD_RW_READ (0 << 29) +#define ULPI_PORT(x) (((x) & 0x7) << 24) +#define ULPI_ADDR(x) (((x) & 0xff) << 16) +#define ULPI_DATA_RD(x) (((x) & 0xff) << 8) +#define ULPI_DATA_WR(x) (((x) & 0xff) << 0) + +#define USB_PORTSC1 0x184 +#define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) +#define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26) +#define USB_PORTSC1_PHCD (1 << 23) +#define USB_PORTSC1_WKOC (1 << 22) +#define USB_PORTSC1_WKDS (1 << 21) +#define USB_PORTSC1_WKCN (1 << 20) +#define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16) +#define USB_PORTSC1_PP (1 << 12) +#define USB_PORTSC1_SUSP (1 << 7) +#define USB_PORTSC1_PE (1 << 2) +#define USB_PORTSC1_CCS (1 << 0) + +#define USB_SUSP_CTRL 0x400 +#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) +#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) +#define USB_SUSP_CLR (1 << 5) +#define USB_PHY_CLK_VALID (1 << 7) +#define UTMIP_RESET (1 << 11) +#define UHSIC_RESET (1 << 11) +#define UTMIP_PHY_ENABLE (1 << 12) +#define ULPI_PHY_ENABLE (1 << 13) +#define USB_SUSP_SET (1 << 14) +#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16) + +#define ULPI_TIMING_CTRL_0 0x424 +#define ULPI_OUTPUT_PINMUX_BYP (1 << 10) +#define ULPI_CLKOUT_PINMUX_BYP (1 << 11) + +#define ULPI_TIMING_CTRL_1 0x428 +#define ULPI_DATA_TRIMMER_LOAD (1 << 0) +#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) +#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) +#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) +#define ULPI_DIR_TRIMMER_LOAD (1 << 24) +#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) + +#define uint32_t unsigned int +#define USBADDR2 0xc5004000 + +#define CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0 0x10 +#define CLK_RST_CONTROLLER_RST_DEVICES_L_0 0x4 + +static int wait_for_register(uint32_t addr, uint32_t mask, uint32_t result, int timeout_) +{ + int timeout = timeout_; + while (timeout-- > 0) { + if ((readl(addr) & mask) == result) return 0; + udelay(2); + } + return -1; +} + +/* ulpi phy power on */ +void ulpi_phy_power_on(void) +{ + uint32_t val; + uint32_t base = USBADDR2; + uint32_t RegVal = 0; + + udelay(1000); + + /* begin USB reset */ + + /* enable USB clock */ + RegVal = readl(NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0 + 4); + RegVal |= (1 << 26); +// writel(NV_PA_CLK_RST_BASE+CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0+4, RegVal); +//above not working! +*((uint *) (NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0 + 4)) = RegVal; + + /* reset USB */ + RegVal = readl(NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_RST_DEVICES_L_0 + 4); + if (RegVal & (1 << 26)) { +// writel(NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_RST_DEVICES_L_0 + 4, RegVal); +*((uint *) (NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_RST_DEVICES_L_0 + 4)) = RegVal; + udelay(2); + RegVal = readl(NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_RST_DEVICES_L_0 + 4); + RegVal &= ~(1 << 26); +// writel(NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_RST_DEVICES_L_0 + 4, RegVal); +*((uint *) (NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_RST_DEVICES_L_0 + 4)) = RegVal; + udelay(2); + } + + /* set UTMIP_RESET/UHSIC_RESET */ + RegVal = readl(base + USB_SUSP_CTRL); + RegVal |= (1 << 11); + writel(base + USB_SUSP_CTRL, RegVal); + + /* end USB reset */ + + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); + + val = readl(base + USB_SUSP_CTRL); + val |= ULPI_PHY_ENABLE; + writel(val, base + USB_SUSP_CTRL); + + val = 0; + writel(val, base + ULPI_TIMING_CTRL_1); + + val |= ULPI_DATA_TRIMMER_SEL(4); + val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); + val |= ULPI_DIR_TRIMMER_SEL(4); + writel(val, base + ULPI_TIMING_CTRL_1); + + udelay(10); + + val |= ULPI_DATA_TRIMMER_LOAD; + val |= ULPI_STPDIRNXT_TRIMMER_LOAD; + val |= ULPI_DIR_TRIMMER_LOAD; + writel(val, base + ULPI_TIMING_CTRL_1); + + val = ULPI_WAKEUP | ULPI_RD_RW_WRITE | ULPI_PORT(0); + writel(val, base + ULPI_VIEWPORT); + + if (wait_for_register(base + ULPI_VIEWPORT, ULPI_WAKEUP, 0, 1000)) { + printf("%s: timeout waiting for ulpi phy wakeup\n", __func__); + return; + } + + /* Fix VbusInvalid due to floating VBUS */ + val = ULPI_RUN | ULPI_RD_RW_WRITE | ULPI_PORT(0) | ULPI_ADDR(0x08) | ULPI_DATA_WR(0x40); + writel(val, base + ULPI_VIEWPORT); + if (wait_for_register(base + ULPI_VIEWPORT, ULPI_RUN, 0, 1000)) { + printf("%s: timeout accessing ulpi phy\n", __func__); + return; + } + val = ULPI_RUN | ULPI_RD_RW_WRITE | ULPI_PORT(0) | ULPI_ADDR(0x0B) | ULPI_DATA_WR(0x80); + writel(val, base + ULPI_VIEWPORT); + if (wait_for_register(base + ULPI_VIEWPORT, ULPI_RUN, 0, 1000)) { + printf("%s: timeout accessing ulpi phy\n", __func__); + return; + } + + val = readl(base + USB_PORTSC1); + val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN; + writel(val, base + USB_PORTSC1); + + val = readl(base + USB_SUSP_CTRL); + val |= USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); + udelay(100); + + val = readl(base + USB_SUSP_CTRL); + val &= ~USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); +} diff --git a/board/toradex/common/usb.c b/board/toradex/common/usb.c new file mode 100644 index 0000000000..63accf8394 --- /dev/null +++ b/board/toradex/common/usb.c @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010,2011 NVIDIA Corporation + * (C) Copyright 2012 Toradex, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define CLK_RST_CONTROLLER_CLK_OUT_ENB_U_0 0x18 +#define CLK_RST_CONTROLLER_PLLP_OUTB_0 0xA8 + +enum { + USB_PORTS_MAX = 4, /* Maximum ports we allow */ +}; + +struct usb_port { + struct usb_ctlr *reg; +}; + +static struct usb_port port[USB_PORTS_MAX]; /* List of valid USB ports */ +static unsigned port_count; /* Number of available ports */ + +/* Record which controller can switch from host to device mode */ +static struct usb_ctlr *host_dev_ctlr; + +/* + * This table has USB timing parameters for each Oscillator frequency we + * support. There are four sets of values: + * + * 1. PLLU configuration information (reference clock is osc/clk_m and + * PLLU-FOs are fixed at 12MHz/60MHz/480MHz). + * (T2x) + * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz + * ---------------------------------------------------------------------- + * DIVN 960 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) + * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) + * Filter frequency (MHz) 1 4.8 6 2 + * CPCON 1100b 0011b 1100b 1100b + * LFCON0 0 0 0 0 + * + * (T3x) + * Reference frequency MHZ 12.0 13.0 16.8 19.2 26.0 38.4 48.0 + * ---------------------------------------------------------------------- + * DIVN 960 960 400 200 960 200 960 + * DIVM 12 13 7 4 26 4 12 + * + * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: + * (T2x) + * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz + * --------------------------------------------------------------------------- + * Index 0 1 2 3 + * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) + * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) + * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) + * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) + * + * (T3x) + * Reference frequency MHZ 12.0 13.0 16.8 19.2 26.0 38.4 48.0 + * --------------------------------------------------------------------------- + * Index 8 0 1 4 12 5 9 + * PLLU_ENABLE_DLY_COUNT 02 2 3 3 4 5 6 + * PLLU_STABLE_COUNT 47 51 66 75 102 150 188 + * PLL_ACTIVE_DLY_COUNT 08 9 11 12 17 24 31 + * XTAL_FREQ_COUNT 118 127 165 188 254 375 469 + * + * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and + * SessEnd. Each of these signals have their own debouncer and for each of + * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or + * BIAS_DEBOUNCE_B). + * + * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows: + * 0xffff -> No debouncing at all + * ms = *1000 / (1/19.2MHz) / 4 + * + * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have: + * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0 + * + * We need to use only DebounceA for BOOTROM. We don’t need the DebounceB + * values, so we can keep those to default. + * + * 4. The 20 microsecond delay after bias cell operation. + */ +#if !defined(CONFIG_TEGRA3) +static const int usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { + /* DivN, DivM, DivP, CPCON, LFCON,EN_DLY,STB,ACT, XTAL,Debounce,Bias */ + { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, + { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, + { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, + { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } +}; +#endif +/* UTMIP Idle Wait Delay */ +static const u8 utmip_idle_wait_delay = 17; + +/* UTMIP Elastic limit */ +static const u8 utmip_elastic_limit = 16; + +/* UTMIP High Speed Sync Start Delay */ +static const u8 utmip_hs_sync_start_delay = 9; + +extern void ulpi_phy_power_on(void); + +/* Put the port into host mode (this only works for USB1) */ +static void set_host_mode(struct usb_ctlr *usbctlr) +{ +//check USB3 + /* Check whether remote host from USB1 is driving VBus */ + if (bf_readl(VBUS_VLD_STS, &usbctlr->phy_vbus_sensors)) + return; + +#if !defined(CONFIG_TEGRA3) +//only required for USB3 at least on Iris + /* + * If not driving, we set GPIO USB1_VBus_En. Colibri T20 uses + * PAD SPIG (GPIO W.02) as USB1_VBus_En Config as GPIO + */ + gpio_direction_output(GPIO_PW2, 0); + + /* Z_SPIG = 0, normal, not tristate */ + pinmux_tristate_disable(PINGRP_SPIG); +#else + /* T30 pinmuxes are set globally; GPIOs from fdt */ +#endif +} + +/* Put our ports into host mode */ +void usb_set_host_mode(void) +{ + if (host_dev_ctlr) + set_host_mode(host_dev_ctlr); +} + +void usbf_reset_controller(enum periph_id id, struct usb_ctlr *usbctlr) +{ +#if !defined(CONFIG_TEGRA3) + uint reg; + + /* Configure ULPI pin mux */ +//ToDo: find better place to do this + pinmux_set_func(PINGRP_UAA, PMUX_FUNC_ULPI); + pinmux_set_func(PINGRP_UAB, PMUX_FUNC_ULPI); + pinmux_set_func(PINGRP_UDA, PMUX_FUNC_ULPI); + pinmux_tristate_disable(PINGRP_UAA); + pinmux_tristate_disable(PINGRP_UAB); + pinmux_tristate_disable(PINGRP_UDA); +#endif + + /* Reset the USB controller with 2us delay */ + reset_periph(id, 2); + +#if !defined(CONFIG_TEGRA3) + if (id == PERIPH_ID_USB2) { + + /* Reset ULPI PHY */ + gpio_direction_output(GPIO_PV1, 0); + pinmux_tristate_disable(PINGRP_UAC); + udelay(5000); + gpio_set_value(GPIO_PV1, 1); + + /* Configure CDEV2 as PLLP_OUT4 */ + pinmux_set_func(PINGRP_CDEV2, PMUX_FUNC_PLLP_OUT4); + pinmux_tristate_disable(PINGRP_CDEV2); + + /* Configure 24 MHz clock for ULPI PHY */ +//enable + reg = readl(NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_CLK_OUT_ENB_U_0); + reg |= (1 << 29); +// writel(NV_PA_CLK_RST_BASE+CLK_RST_CONTROLLER_CLK_OUT_ENB_U_0, reg); +//above not working! +*((uint *) (NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_CLK_OUT_ENB_U_0)) = reg; +//rate + reg = readl(NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_PLLP_OUTB_0); + reg |= (8 << 25) | (0 << 24) | (1 << 18); +// writel(NV_PA_CLK_RST_BASE+CLK_RST_CONTROLLER_PLLP_OUTB_0, reg); +*((uint *) (NV_PA_CLK_RST_BASE + CLK_RST_CONTROLLER_PLLP_OUTB_0)) = reg; + + ulpi_phy_power_on(); + + /* Fix Ethernet detection faults */ + udelay(100 * 1000); + + /* Enable ASIX AX88772B V_BUS */ + gpio_direction_output(GPIO_PBB1, 1); + pinmux_tristate_disable(PINGRP_DTE); + } + + /* + * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under + * base address + */ +//what about tegra 3? + if (id == PERIPH_ID_USBD) + bf_writel(USB1_NO_LEGACY_MODE, NO_LEGACY_MODE, + &usbctlr->usb1_legacy_ctrl); + + /* Put UTMIP1/3 in reset */ + if ((id == PERIPH_ID_USBD) || (id == PERIPH_ID_USB3)) + bf_writel(UTMIP_RESET, 1, &usbctlr->susp_ctrl); + + /* Set USB3 to use UTMIP PHY */ + if (id == PERIPH_ID_USB3) + bf_writel(UTMIP_PHY_ENB, 1, &usbctlr->susp_ctrl); +#else /* !CONFIG_TEGRA3 */ + /* Put UTMIP1/2/3 in reset */ + bf_writel(UTMIP_RESET, 1, &usbctlr->susp_ctrl); + + /* Set USB1/2/3 to use UTMIP PHY */ + bf_writel(UTMIP_PHY_ENB, 1, &usbctlr->susp_ctrl); +#endif + + /* + * TODO: where do we take the USB1 out of reset? The old code would + * take USB3 out of reset, but not USB1. This code doesn't do either. + */ +} + +/* set up the USB controller with the parameters provided */ +static void init_usb_controller(enum periph_id id, struct usb_ctlr *usbctlr, + const int *params) +{ + u32 val; + int loop_count; +#if defined(CONFIG_TEGRA3) + struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; +#endif + clock_enable(id); + + /* Reset the usb controller */ + usbf_reset_controller(id, usbctlr); + + /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */ + bf_clearl(UTMIP_PHY_XTAL_CLOCKEN, &usbctlr->utmip_misc_cfg1); + + /* Follow the crystal clock disable by >100ns delay */ + udelay(1); +#if !defined(CONFIG_TEGRA3) + /* + * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP + * mux must be switched to actually use a_sess_vld threshold. + */ + if (id == PERIPH_ID_USBD) + bf_enum_writel(VBUS_SENSE_CTL, A_SESS_VLD, + &usbctlr->usb1_legacy_ctrl); + + /* + * PLL Delay CONFIGURATION settings. The following parameters control + * the bring up of the plls. + */ + val = readl(&usbctlr->utmip_misc_cfg1); + bf_update(UTMIP_PLLU_STABLE_COUNT, val, params[PARAM_STABLE_COUNT]); + bf_update(UTMIP_PLL_ACTIVE_DLY_COUNT, val, + params[PARAM_ACTIVE_DELAY_COUNT]); + writel(val, &usbctlr->utmip_misc_cfg1); + + /* Set PLL enable delay count and crystal frequency count */ + val = readl(&usbctlr->utmip_pll_cfg1); + bf_update(UTMIP_PLLU_ENABLE_DLY_COUNT, val, + params[PARAM_ENABLE_DELAY_COUNT]); + bf_update(UTMIP_XTAL_FREQ_COUNT, val, params[PARAM_XTAL_FREQ_COUNT]); + writel(val, &usbctlr->utmip_pll_cfg1); +#else /* !CONFIG_TEGRA3 */ + /* + * PLL Delay CONFIGURATION settings. The following parameters control + * the bring up of the plls. + */ + val = readl(&clkrst->crc_pll_cfg2); + bf_update(UTMIP_PLLU_STABLE_COUNT, val, params[PARAM_STABLE_COUNT]); + bf_update(UTMIP_PLL_ACTIVE_DLY_COUNT, val, + params[PARAM_ACTIVE_DELAY_COUNT]); + writel(val, &clkrst->crc_pll_cfg2); + + /* Set PLL enable delay count and crystal frequency count */ + val = readl(&clkrst->crc_pll_cfg1); + bf_update(UTMIP_PLLU_ENABLE_DLY_COUNT, val, + params[PARAM_ENABLE_DELAY_COUNT]); + bf_update(UTMIP_XTAL_FREQ_COUNT, val, params[PARAM_XTAL_FREQ_COUNT]); + writel(val, &clkrst->crc_pll_cfg1); + + /* Disable Power Down state for PLL */ + bf_writel(UTMIP_FORCE_PLLU_POWERDOWN, 0, &clkrst->crc_pll_cfg1); + bf_writel(UTMIP_FORCE_PLL_ENABLE_POWERDOWN, 0, &clkrst->crc_pll_cfg1); + bf_writel(UTMIP_FORCE_PLL_ACTIVE_POWERDOWN, 0, &clkrst->crc_pll_cfg1); + + /* Recommended PHY settings for EYE diagram */ + bf_writel(UTMIP_XCVR_SETUP, 0x4, &usbctlr->utmip_xcvr_cfg0); + bf_writel(UTMIP_XCVR_SETUP_MSB, 0x3, &usbctlr->utmip_xcvr_cfg0); + bf_writel(UTMIP_XCVR_HSSLEW_MSB, 0x8, &usbctlr->utmip_xcvr_cfg0); + bf_writel(UTMIP_XCVR_TERM_RANGE_ADJ, 0x7, &usbctlr->utmip_xcvr_cfg1); + bf_writel(UTMIP_HSDISCON_LEVEL_MSB, 0x1, &usbctlr->utmip_bias_cfg0); + bf_writel(UTMIP_HSDISCON_LEVEL, 0x1, &usbctlr->utmip_bias_cfg0); + bf_writel(UTMIP_HSSQUELCH_LEVEL, 0x2, &usbctlr->utmip_bias_cfg0); + + /* Miscellaneous setting mentioned in Programming Guide */ + bf_writel(UTMIP_SUSPEND_EXIT_ON_EDGE, 0, &usbctlr->utmip_misc_cfg0); +#endif /* !CONFIG_TEGRA3 */ + /* Setting the tracking length time */ + bf_writel(UTMIP_BIAS_PDTRK_COUNT, params[PARAM_BIAS_TIME], + &usbctlr->utmip_bias_cfg1); + + /* Program debounce time for VBUS to become valid */ + bf_writel(UTMIP_DEBOUNCE_CFG0, params[PARAM_DEBOUNCE_A_TIME], + &usbctlr->utmip_debounce_cfg0); + + /* Set UTMIP_FS_PREAMBLE_J to 1 */ + bf_writel(UTMIP_FS_PREAMBLE_J, 1, &usbctlr->utmip_tx_cfg0); + + /* Disable battery charge enabling bit */ + bf_writel(UTMIP_PD_CHRG, 1, &usbctlr->utmip_bat_chrg_cfg0); + + /* Set UTMIP_XCVR_LSBIAS_SEL to 0 */ + bf_writel(UTMIP_XCVR_LSBIAS_SE, 0, &usbctlr->utmip_xcvr_cfg0); + + /* Set bit 3 of UTMIP_SPARE_CFG0 to 1 */ + bf_writel(FUSE_SETUP_SEL, 1, &usbctlr->utmip_spare_cfg0); + + /* + * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT + * Setting these fields, together with default values of the + * other fields, results in programming the registers below as + * follows: + * UTMIP_HSRX_CFG0 = 0x9168c000 + * UTMIP_HSRX_CFG1 = 0x13 + */ + + /* Set PLL enable delay count and Crystal frequency count */ + val = readl(&usbctlr->utmip_hsrx_cfg0); + bf_update(UTMIP_IDLE_WAIT, val, utmip_idle_wait_delay); + bf_update(UTMIP_ELASTIC_LIMIT, val, utmip_elastic_limit); + writel(val, &usbctlr->utmip_hsrx_cfg0); + + /* Configure the UTMIP_HS_SYNC_START_DLY */ + bf_writel(UTMIP_HS_SYNC_START_DLY, utmip_hs_sync_start_delay, + &usbctlr->utmip_hsrx_cfg1); + + /* Precede the crystal clock enable by >100ns delay. */ + udelay(1); + + /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ + bf_writel(UTMIP_PHY_XTAL_CLOCKEN, 1, &usbctlr->utmip_misc_cfg1); +#if defined(CONFIG_TEGRA3) + if (id == PERIPH_ID_USBD) + bf_writel(UTMIP_FORCE_PD_SAMP_A_POWERDOWN, 0, + &clkrst->crc_pll_cfg2); + if (id == PERIPH_ID_USB2) + bf_writel(UTMIP_FORCE_PD_SAMP_B_POWERDOWN, 0, + &clkrst->crc_pll_cfg2); + if (id == PERIPH_ID_USB3) + bf_writel(UTMIP_FORCE_PD_SAMP_C_POWERDOWN, 0, + &clkrst->crc_pll_cfg2); +#endif + /* Finished the per-controller init. */ + + /* De-assert UTMIP_RESET to bring out of reset. */ + bf_clearl(UTMIP_RESET, &usbctlr->susp_ctrl); + + /* Wait for the phy clock to become valid in 100 ms */ + for (loop_count = 100000; loop_count != 0; loop_count--) { + if (bf_readl(USB_PHY_CLK_VALID, &usbctlr->susp_ctrl)) + break; + udelay(1); + } +} + +static void power_up_port(struct usb_ctlr *usbctlr) +{ + u32 val; + + /* Deassert power down state */ + val = readl(&usbctlr->utmip_xcvr_cfg0); + bf_update(UTMIP_FORCE_PD_POWERDOWN, val, 0); + bf_update(UTMIP_FORCE_PD2_POWERDOWN, val, 0); + bf_update(UTMIP_FORCE_PDZI_POWERDOWN, val, 0); + writel(val, &usbctlr->utmip_xcvr_cfg0); + + val = readl(&usbctlr->utmip_xcvr_cfg1); + bf_update(UTMIP_FORCE_PDDISC_POWERDOWN, val, 0); + bf_update(UTMIP_FORCE_PDCHRP_POWERDOWN, val, 0); + bf_update(UTMIP_FORCE_PDDR_POWERDOWN, val, 0); + writel(val, &usbctlr->utmip_xcvr_cfg1); +} + +static void config_clock(const int params[]) +{ + clock_start_pll(CLOCK_ID_USB, + params[PARAM_DIVM], params[PARAM_DIVN], + params[PARAM_DIVP], params[PARAM_CPCON], + params[PARAM_LFCON]); +} + +/** + * Add a new USB port to the list of available ports + * + * @param id peripheral id of port (PERIPH_ID_USB3, for example) + * @param usbctlr register address of controller + * @param params timing parameters + * @param utmi 1 if using internal UTMI transceiver + * @return 0 if ok, -1 if error (too many ports) + */ +static int add_port(enum periph_id id, struct usb_ctlr *usbctlr, + const int params[], int utmi) +{ + volatile u32 *ahb_prefetch_reg; + + if (port_count == USB_PORTS_MAX) { + debug("tegrausb: Cannot register more than %d ports\n", + USB_PORTS_MAX); + return -1; + } + init_usb_controller(id, usbctlr, params); +#if defined(CONFIG_TEGRA3) + /* + * BIAS Pad Power Down is common among all 3 USB + * controllers and can be controlled from USB1 only. + */ + if (id == PERIPH_ID_USBD) + bf_writel(UTMIP_BIASPD, 0, &usbctlr->utmip_bias_cfg0); +#endif + if (utmi) { + /* Disable ICUSB FS/LS transceiver */ +//should actually default to disabled on Tegra 3 according to TRM + bf_writel(IC_ENB1, 0, &usbctlr->icusb_ctrl); + +#if !defined(CONFIG_TEGRA3) + /* Select UTMI parallel interface */ + bf_writel(PTS, PTS_UTMI, &usbctlr->port_sc1); + bf_writel(STS, 0, &usbctlr->port_sc1); +#endif +//probably just following required + power_up_port(usbctlr); + } + port[port_count++].reg = usbctlr; + + /* Setting AHB-Prefetch register to avoid TX FIFO underrun + Colibri T20 has Ethernet on USB2 */ + if (id == PERIPH_ID_USB2) { +// printf("setting AHB-prefetch registers for USB2\n"); + ahb_prefetch_reg = (u32 *)0x6000c0f4; + /* AHB_AHB_MEM_PREFETCH_CFG2_0 + 0b1: ENABLE + 0b10010: 18 = USB2 + 0b01100: ADDR_BNDRY 2^(12+4) = 65536 + 0x800: INACTIVITY_TIMEOUT */ + *ahb_prefetch_reg = 0xc9800800; + } + + return 0; +} + +int tegrausb_start_port(unsigned portnum, struct ehci_hccr **hccr, + struct ehci_hcor **hcor) +{ + struct usb_ctlr *usbctlr; + + if (portnum >= port_count) + return -1; + tegrausb_stop_port(portnum); + + usbctlr = port[portnum].reg; +#if defined(CONFIG_TEGRA3) + /* Set Controller Mode as Host mode after Controller Reset was done */ + bf_writel(CM, CM_HOST_MODE, &usbctlr->usb_mode); + + /* Select UTMI parallel interface after setting host mode */ + bf_writel(PTS, PTS_UTMI, &usbctlr->hostpc1_devlc); + bf_writel(STS, STS_PARALLEL_IF, &usbctlr->hostpc1_devlc); +#endif + + *hccr = (struct ehci_hccr *)&usbctlr->cap_length; + *hcor = (struct ehci_hcor *)&usbctlr->usb_cmd; + return 0; +} + +int tegrausb_stop_port(unsigned portnum) +{ + struct usb_ctlr *usbctlr; + + if (portnum >= port_count) + return -1; + + usbctlr = port[portnum].reg; + + /* Stop controller */ + writel(0, &usbctlr->usb_cmd); + udelay(1000); + + /* Initiate controller reset */ + writel(2, &usbctlr->usb_cmd); + udelay(1000); + return 0; +} + +int board_usb_init(const void *blob) +{ + struct fdt_usb config; + int clk_done = 0; + int node, upto = 0; + unsigned osc_freq = clock_get_rate(CLOCK_ID_OSC); + + do { + node = fdt_decode_next_alias(blob, "usb", + COMPAT_NVIDIA_TEGRA250_USB, &upto); + if (node < 0) + break; + if (fdt_decode_usb(blob, node, osc_freq, &config)) + return -1; + if (!config.enabled) + continue; + + /* The first port we find gets to set the clocks */ + if (!clk_done) { + config_clock(config.params); + clk_done = 1; + } + if (config.host_mode) { + /* Only one host-dev port is supported */ + if (host_dev_ctlr) + return -1; + host_dev_ctlr = config.reg; + } + if (add_port(config.periph_id, config.reg, config.params, + config.utmi)) + return -1; + + fdt_setup_gpio(&config.vbus_gpio); + fdt_setup_gpio(&config.vbus_pullup_gpio); + } while (node); + + usb_set_host_mode(); + + return 0; +} diff --git a/boards.cfg b/boards.cfg index 382a4021a3..8e98a547e9 100644 --- a/boards.cfg +++ b/boards.cfg @@ -161,6 +161,9 @@ s5p_goni arm armv7 goni samsung smdkc100 arm armv7 smdkc100 samsung s5pc1xx s5pc210_universal arm armv7 universal_c210 samsung s5pc2xx smdkv310 arm armv7 smdkv310 samsung s5pc2xx +colibri_t20 arm armv7 colibri_t20 toradex tegra2 +colibri_t20_sdboot arm armv7 colibri_t20 toradex tegra2 +colibri_t30 arm armv7 colibri_t30 toradex tegra3 harmony arm armv7 harmony nvidia tegra2 seaboard arm armv7 seaboard nvidia tegra2 cardhu arm armv7 cardhu nvidia tegra3 diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c index 5481c885d3..66a4c302a1 100644 --- a/common/cmd_mtdparts.c +++ b/common/cmd_mtdparts.c @@ -838,7 +838,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_ struct mtdids *id; const char *mtd_id; unsigned int mtd_id_len; - const char *p, *pend; + const char *p; LIST_HEAD(tmp_list); struct list_head *entry, *n; u16 num_parts; @@ -871,8 +871,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_ debug("dev type = %d (%s), dev num = %d, mtd-id = %s\n", id->type, MTD_DEV_TYPE(id->type), id->num, id->mtd_id); - pend = strchr(p, ';'); - debug("parsing partitions %.*s\n", (pend ? pend - p : strlen(p)), p); + debug("parsing partitions %.*s\n", (strchr(p, ';') ? strchr(p, ';') - p : strlen(p)), p); /* parse partitions */ diff --git a/common/cmd_nand.c b/common/cmd_nand.c index ef1253f50b..d42054e0d2 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -190,7 +190,7 @@ static int arg_off_size(int argc, char *const argv[], int *idx, loff_t *off, loff_t *size) { int ret; - loff_t maxsize; + loff_t maxsize=0; if (argc == 0) { *off = 0; diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c index 629758fdf5..8c1bc23a5a 100644 --- a/common/cmd_ubi.c +++ b/common/cmd_ubi.c @@ -316,7 +316,6 @@ static int ubi_volume_write(char *volume, void *buf, size_t size) static int ubi_volume_read(char *volume, char *buf, size_t size) { int err, lnum, off, len, tbuf_size; - size_t count_save = size; void *tbuf; unsigned long long tmp; struct ubi_volume *vol; @@ -347,7 +346,7 @@ static int ubi_volume_read(char *volume, char *buf, size_t size) if (vol->corrupted) printf("read from corrupted volume %d", vol->vol_id); if (offp + size > vol->used_bytes) - count_save = size = vol->used_bytes - offp; + size = vol->used_bytes - offp; tbuf_size = vol->usable_leb_size; if (size < tbuf_size) diff --git a/common/cmd_usb.c b/common/cmd_usb.c index e04f1c5479..0cfde07e2c 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -1,6 +1,8 @@ /* * (C) Copyright 2001 * Denis Peter, MPL AG Switzerland + * (C) Copyright 2012 + * Toradex, Inc. * * Most of this source has been derived from the Linux USB * project. @@ -277,11 +279,12 @@ static inline char *portspeed(int speed) return "12 Mb/s"; } -/* shows the device tree recursively */ -void usb_show_tree_graph(struct usb_device *dev, char *pre) +/* shows the device tree recursively + returns device number of leaf node or zero otherwise (e.g. root hub only) */ +int usb_show_tree_graph(struct usb_device *dev, char *pre) { int i, index; - int has_child, last_child; + int has_child, last_child, leaf = 0; index = strlen(pre); printf(" %s", pre); @@ -311,8 +314,10 @@ void usb_show_tree_graph(struct usb_device *dev, char *pre) } /* for all children of the parent */ printf("\b+-"); /* correct last child */ - if (last_child) + if (last_child) { + leaf = dev->devnum; pre[index-1] = ' '; + } } /* if not root hub */ else printf(" "); @@ -330,20 +335,21 @@ void usb_show_tree_graph(struct usb_device *dev, char *pre) if (dev->maxchild > 0) { for (i = 0; i < dev->maxchild; i++) { if (dev->children[i] != NULL) { - usb_show_tree_graph(dev->children[i], pre); + leaf = usb_show_tree_graph(dev->children[i], pre); pre[index] = 0; } } } + return leaf; } /* main routine for the tree command */ -void usb_show_tree(struct usb_device *dev) +int usb_show_tree(struct usb_device *dev) { char preamble[32]; memset(preamble, 0, 32); - usb_show_tree_graph(dev, &preamble[0]); + return usb_show_tree_graph(dev, &preamble[0]); } @@ -563,8 +569,21 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; } if (strncmp(argv[1], "tree", 4) == 0) { + int dev_index = 0, previous_dev_index = 0; + struct usb_device *usb; + printf("\nDevice Tree:\n"); - usb_show_tree(usb_get_dev_index(0)); + do { + usb = usb_get_dev_index(dev_index); + if (usb) { + dev_index = usb_show_tree(usb); + if (!dev_index) + dev_index = previous_dev_index + 1; + } + else + dev_index = 0; + previous_dev_index = dev_index; + } while (dev_index); return 0; } if (strncmp(argv[1], "inf", 3) == 0) { diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index dceb975498..929ee23841 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -42,6 +42,10 @@ #define CONFIG_SYS_XIMG_LEN 0x800000 #endif +/* Chromium U-Boot treats all errors as warnings, 'hdr' may be used + uninitialized in below function. The pragma disables this warning. */ +#pragma GCC diagnostic warning "-Wuninitialized" + int do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { @@ -51,7 +55,7 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) int verify; int part = 0; char pbuf[10]; - image_header_t *hdr; + image_header_t *hdr = NULL; #if defined(CONFIG_FIT) const char *uname = NULL; const void* fit_hdr; @@ -234,16 +238,22 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) * space, use slower decompression algorithm * which requires at most 2300 KB of memory. */ - i = BZ2_bzBuffToBuffDecompress( - (char*)ntohl(hdr->ih_load), - &unc_len, (char *)data, len, - CONFIG_SYS_MALLOC_LEN < (4096 * 1024), - 0); - if (i != BZ_OK) { - printf ("BUNZIP2 ERROR %d - " - "image not loaded\n", i); + if(hdr == NULL) { + printf ("hdr not set\n"); return 1; } + else { + i = BZ2_bzBuffToBuffDecompress( + (char*)ntohl(hdr->ih_load), + &unc_len, (char *)data, len, + CONFIG_SYS_MALLOC_LEN < (4096 * 1024), + 0); + if (i != BZ_OK) { + printf ("BUNZIP2 ERROR %d - " + "image not loaded\n", i); + return 1; + } + } } break; #endif /* CONFIG_BZIP2 */ diff --git a/common/fdt_decode.c b/common/fdt_decode.c index 4f1eb59b2c..afa070f2d6 100644 --- a/common/fdt_decode.c +++ b/common/fdt_decode.c @@ -28,6 +28,10 @@ /* we need a generic GPIO interface here */ #include +#include +#include +DECLARE_GLOBAL_DATA_PTR; + /* * Here are the type we know about. One day we might allow drivers to * register. For now we just put them here. The COMPAT macro allows us to @@ -533,8 +537,14 @@ int fdt_decode_lcd(const void *blob, struct fdt_lcd *config) config->width == -1 || config->height == -1 || !config->pwfm || !config->disp) return -FDT_ERR_MISSING; - config->frame_buffer = get_addr(blob, node, "frame-buffer"); - + if(gd->ram_size == SZ_256M) + { + config->frame_buffer = get_addr(blob, node, "frame-buffer_256"); + } + else + { + config->frame_buffer = get_addr(blob, node, "frame-buffer_512"); + } err |= fdt_decode_gpio(blob, node, "backlight-enable", &config->backlight_en); err |= fdt_decode_gpio(blob, node, "lvds-shutdown", @@ -708,6 +718,11 @@ int fdt_decode_nand(const void *blob, int node, struct fdt_nand *config) if (err < 0) return err; + err = get_int_array(blob, node, "nv-partitions", config->nv_partitions, + FDT_NAND_PARTOFFSET_COUNT); + if (err < 0) + return err; + /* Now look up the controller and decode that */ node = lookup_phandle(blob, node, "controller"); if (node < 0) diff --git a/disk/part.c b/disk/part.c index c79585f3dd..af6e0a60d2 100644 --- a/disk/part.c +++ b/disk/part.c @@ -386,8 +386,9 @@ static void print_part_header (const char *type, block_dev_desc_t * dev_desc) void print_part (block_dev_desc_t * dev_desc) { - - switch (dev_desc->part_type) { + /* Force EFI */ + dev_desc->part_type = PART_TYPE_EFI; + switch (dev_desc->part_type) { #ifdef CONFIG_MAC_PARTITION case PART_TYPE_MAC: PRINTF ("## Testing for valid MAC partition ##\n"); @@ -418,7 +419,6 @@ void print_part (block_dev_desc_t * dev_desc) print_part_amiga (dev_desc); return; #endif - #ifdef CONFIG_EFI_PARTITION case PART_TYPE_EFI: PRINTF ("## Testing for valid EFI partition ##\n"); diff --git a/disk/part_efi.c b/disk/part_efi.c index 2fef7e7b41..2d7a7b85d7 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -125,8 +125,17 @@ void print_part_efi(block_dev_desc_t * dev_desc) /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, gpt_head, &gpt_pte) != 1) { - printf("%s: *** ERROR: Invalid GPT ***\n", __func__); - goto failure; + printf("%s: *** ERROR: Invalid Primary GPT ***\n", __func__); + /* Testing secondary GPT */ + if(is_gpt_valid(dev_desc, dev_desc->lba - 1, + gpt_head, &gpt_pte) != 1) { + printf("%s: *** ERROR: Invalid Secondary GPT ***\n", __func__); + goto failure; + } + else + { + /* Fix primary GPT here */ + } } debug("%s: gpt-entry at %p\n", __func__, gpt_pte); @@ -175,9 +184,18 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, /* This function validates AND fills in the GPT header and PTE */ if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA, gpt_head, &gpt_pte) != 1) { - printf("%s: *** ERROR: Invalid GPT ***\n", __func__); - err = -1; - goto failure; + printf("%s: *** ERROR: Invalid Primary GPT ***\n", __func__); + /* Testing secondary GPT */ + if(is_gpt_valid(dev_desc, dev_desc->lba-1, + gpt_head, &gpt_pte) != 1) { + printf("%s: *** ERROR: Invalid Secondary GPT ***\n", __func__); + err = -1; + goto failure; + } + else + { + /* Fix primary GPT here */ + } } /* The ulong casting limits the maximum disk size to 2 TB */ @@ -398,6 +416,8 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, le32_to_int(pgpt_head->num_partition_entries), le32_to_int(pgpt_head->sizeof_partition_entry), count); + /* Set count to be a multiple of 512 */ + count = ((count+GPT_BLOCK_SIZE-1) / GPT_BLOCK_SIZE) * GPT_BLOCK_SIZE; /* Allocate memory for PTE, remember to FREE */ if (count != 0) { pte = memalign(CACHE_LINE_SIZE, count); diff --git a/disk/part_efi.h b/disk/part_efi.h index 6bbb06bde9..adf4e55f3b 100644 --- a/disk/part_efi.h +++ b/disk/part_efi.h @@ -39,7 +39,11 @@ #define GPT_BLOCK_SIZE 512 #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL #define GPT_HEADER_REVISION_V1 0x00010000 +#ifndef GPT_PRIMARY_PARTITION_TABLE_LBA +/* might be defined in colibri_t20.h when the device uses the nvidia partitioning + * and the GPT doesn't start at its default sector */ #define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL +#endif #define GPT_ENTRY_NAME "gpt" #define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 52f8575aac..fd94206ea9 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -11,6 +11,7 @@ * * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) * 2002-2006 Thomas Gleixner (tglx@linutronix.de) + * 2012 Toradex, Inc. * * Credits: * David Woodhouse for adding multichip support @@ -2612,6 +2613,12 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, if (!ret) nand_flash_detect_non_onfi(mtd, chip, type, &busw); + /* Work around wrong block size identified for our device + Note: ONFI would really be the way to go but does not seem to be + supported in U-Boot as of yet. */ + if ((*maf_id == 0x2C) && (*dev_id == 0x38)) + mtd->erasesize <<= 1; + /* Get chip options, preserve non chip based options */ chip->options &= ~NAND_CHIPOPTIONS_MSK; chip->options |= type->options & NAND_CHIPOPTIONS_MSK; diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 8d7ea767dd..ad53211f88 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -2,6 +2,7 @@ * drivers/mtd/nandids.c * * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) + * Copyright (C) 2012 Toradex, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -100,6 +101,7 @@ const struct nand_flash_dev nand_flash_ids[] = { {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, LP_OPTIONS16}, /* 8 Gigabit */ + {"NAND 1GiB 3,3V 8-bit", 0x38, 0, 1024, 0, LP_OPTIONS}, {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, LP_OPTIONS}, {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, LP_OPTIONS}, {"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, LP_OPTIONS16}, diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 061da649e1..1153015422 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -678,12 +678,10 @@ out_cdev: */ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) { - int err; - dbg_msg("free volume %d", vol->vol_id); ubi->volumes[vol->vol_id] = NULL; - err = ubi_destroy_gluebi(vol); + (void)ubi_destroy_gluebi(vol); cdev_del(&vol->cdev); volume_sysfs_close(vol); } diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 8b45106a53..d1c5559843 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -124,6 +124,7 @@ static char NS16550_raw_getc(NS16550_t regs) { uart_enable(regs); while ((serial_in(®s->lsr) & UART_LSR_DR) == 0) { + WATCHDOG_RESET(); #ifdef CONFIG_USB_TTY extern void usbtty_poll(void); usbtty_poll(); @@ -200,6 +201,8 @@ char NS16550_getc(NS16550_t regs, unsigned int port) int NS16550_tstc(NS16550_t regs, unsigned int port) { + WATCHDOG_RESET(); + if (port >= NUM_PORTS || !(gd->flags & GD_FLG_RELOC)) return NS16550_raw_tstc(regs); diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c index 3cc9012e15..790390a2fc 100644 --- a/drivers/usb/eth/asix.c +++ b/drivers/usb/eth/asix.c @@ -1,5 +1,9 @@ /* * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (c) 2012 Toradex, Inc. + * + * Patched for AX88772B by Ant Micro + * * See file CREDITS for list of people who contributed to this * project. * @@ -79,9 +83,16 @@ #define AX_RX_CTL_SO 0x0080 #define AX_RX_CTL_AB 0x0008 +/* AX88772B RX_CTL values */ +#define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */ +#define AX_RX_CTL_AB 0x0008 /* Accetp Brocadcast frames*/ +#define AX_RX_CTL_RH1M 0x0100 /* Enable RX-Header mode 0 */ +#define AX_RX_CTL_RH2M 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */ +#define AX_RX_HEADER_DEFAULT (AX_RX_CTL_RH1M | AX_RX_CTL_RH2M) + + #define AX_DEFAULT_RX_CTL \ (AX_RX_CTL_SO | AX_RX_CTL_AB) -#define AX_DISABLE_RX_CTL AX_RX_CTL_AB /* GPIO 2 toggles */ #define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ @@ -241,7 +252,6 @@ static int asix_write_medium_mode(struct ueth_data *dev, u16 mode) return ret; } -#ifdef DEBUG static u16 asix_read_rx_ctl(struct ueth_data *dev) { __le16 v; @@ -253,7 +263,6 @@ static u16 asix_read_rx_ctl(struct ueth_data *dev) ret = le16_to_cpu(v); return ret; } -#endif static int asix_write_rx_ctl(struct ueth_data *dev, u16 mode) { @@ -310,11 +319,22 @@ static int mii_nway_restart(struct ueth_data *dev) return r; } -static int full_init(struct eth_device *eth) +/* + * Asix callbacks + */ +static int asix_init(struct eth_device *eth, bd_t *bd) { - struct ueth_data *dev = (struct ueth_data *)eth->priv; int embd_phy; unsigned char buf[ETH_ALEN]; + struct ueth_data *dev = (struct ueth_data *)eth->priv; + int timeout = 0; + char *addr_str, *end; + int i; + unsigned char env_enetaddr[6] = {0, 0, 0, 0, 0, 0}; /* Ethernet address */ +#define TIMEOUT_RESOLUTION 50 /* ms */ + int link_detected; + + debug("** %s()\n", __func__); if (asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5) < 0) @@ -342,11 +362,55 @@ static int full_init(struct eth_device *eth) goto out_err; } - debug("RX_CTL is 0x%04x after software reset\n", asix_read_rx_ctl(dev)); + (void) asix_read_rx_ctl(dev); if (asix_write_rx_ctl(dev, 0x0000) < 0) goto out_err; - debug("RX_CTL is 0x%04x setting to 0x0000\n", asix_read_rx_ctl(dev)); + (void) asix_read_rx_ctl(dev); + + if ((dev->pusb_dev->descriptor.idVendor == 0x0b95) && (dev->pusb_dev->descriptor.idProduct == 0x772b)) { + #define AX_CMD_READ_EEPROM 0x0B + #define AX_CMD_WRITE_NODE_ID 0x14 + // read MAC from EEPROM + memset(buf, 0, ETH_ALEN); + int i,ret; + for (i = 0; i < (ETH_ALEN >> 1); i++) { + if ((ret = asix_read_cmd (dev, AX_CMD_READ_EEPROM, + 0x04 + i, 0, 2, (buf + i * 2))) < 0) { + debug("read SROM address 04h failed: %d", ret); + goto out_err; + } + } + memcpy(eth->enetaddr, buf, ETH_ALEN); + debug("Read MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + eth->enetaddr[0], eth->enetaddr[1], + eth->enetaddr[2], eth->enetaddr[3], + eth->enetaddr[4], eth->enetaddr[5]); + + if ((ret = asix_write_cmd (dev, AX_CMD_WRITE_NODE_ID, + 0, 0, ETH_ALEN, buf)) < 0) { + debug("set MAC address failed: %d", ret); + goto out_err; + } + } + + + /* Get MAC address from environment */ + if ((addr_str = getenv("ethaddr")) != NULL) { + for (i = 0; i < 6; i++) { + env_enetaddr[i] = addr_str ? simple_strtoul(addr_str, &end, 16) : 0; + if (addr_str) { + addr_str = (*end) ? end + 1 : end; + } + } + } + memcpy(eth->enetaddr, env_enetaddr, ETH_ALEN); + int ret; + if ((ret = asix_write_cmd (dev, AX_CMD_WRITE_NODE_ID, + 0, 0, ETH_ALEN, env_enetaddr)) < 0) { + debug("set MAC address failed: %d", ret); + goto out_err; + } /* Get the MAC address */ if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID, @@ -384,28 +448,14 @@ static int full_init(struct eth_device *eth) debug("Write IPG,IPG1,IPG2 failed\n"); goto out_err; } - return 0; -out_err: - return -1; -} -/* - * Asix callbacks - */ -static int asix_init(struct eth_device *eth, bd_t *bd) -{ - struct ueth_data *dev = (struct ueth_data *)eth->priv; - int timeout = 0; -#define TIMEOUT_RESOLUTION 50 /* ms */ - int link_detected; - debug("** %s()\n", __func__); + if ((dev->pusb_dev->descriptor.idVendor == 0x0b95) && (dev->pusb_dev->descriptor.idProduct == 0x772b)) { + if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL | AX_RX_HEADER_DEFAULT) < 0) goto out_err; + } else if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0) + goto out_err; - if (!dev->has_been_running && full_init(eth)) - return -1; - if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0) - return -1; do { link_detected = asix_mdio_read(dev, dev->phy_id, MII_BMSR) & BMSR_LSTATUS; @@ -421,11 +471,16 @@ static int asix_init(struct eth_device *eth, bd_t *bd) printf("done.\n"); } else { printf("unable to connect.\n"); - return -1; + goto out_err; } - dev->has_been_running = 1; + /* Wait some more to avoid timeout on first transfer + (e.g. EHCI timed out on TD - token=0x8008d80) */ + udelay(25000); + return 0; +out_err: + return -1; } static int asix_send(struct eth_device *eth, volatile void *packet, int length) @@ -510,6 +565,8 @@ static int asix_recv(struct eth_device *eth) return -1; } + if ((dev->pusb_dev->descriptor.idVendor == 0x0b95) && (dev->pusb_dev->descriptor.idProduct == 0x772b)) buf_ptr += 2; + /* Notify net stack */ NetReceive(buf_ptr + sizeof(packet_len), packet_len); @@ -525,11 +582,7 @@ static int asix_recv(struct eth_device *eth) static void asix_halt(struct eth_device *eth) { - struct ueth_data *dev = (struct ueth_data *)eth->priv; - - /* Disable packet reception */ debug("** %s()\n", __func__); - (void)asix_write_rx_ctl(dev, AX_DISABLE_RX_CTL); } /* @@ -555,6 +608,7 @@ static struct asix_dongle asix_dongles[] = { { 0x13b1, 0x0018 }, /* Linksys 200M v2.1 */ { 0x1557, 0x7720 }, /* 0Q0 cable ethernet */ { 0x2001, 0x3c05 }, /* DLink DUB-E100 H/W Ver B1 Alternate */ + { 0x0b95, 0x772b }, /* ASIX 88772B */ { 0x0000, 0x0000 } /* END - Do not remove */ }; @@ -596,17 +650,22 @@ int asix_eth_probe(struct usb_device *dev, unsigned int ifnum, * We are expecting a minimum of 3 endpoints - in, out (bulk), and * int. We will ignore any others. */ + int ep_in_found = 0; + int ep_out_found = 0; for (i = 0; i < iface_desc->bNumEndpoints; i++) { /* is it an BULK endpoint? */ if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { - if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN) - ss->ep_in = iface->ep_desc[i].bEndpointAddress & + if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN) { + if (ep_in_found == 0) ss->ep_in = iface->ep_desc[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - else - ss->ep_out = + ep_in_found = 1; + } else { + if (ep_out_found == 0) ss->ep_out = iface->ep_desc[i].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + ep_out_found = 1; + } } /* is it an interrupt endpoint? */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e5c21d7bf6..eedc824461 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -935,7 +935,7 @@ void *usb_lowlevel_init(int index) reg = ehci_readl(&hccr->cr_hcsparams); descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); - printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); +// printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); /* Port Indicators */ if (HCS_INDICATOR(reg)) descriptor.hub.wHubCharacteristics |= 0x80; @@ -961,7 +961,7 @@ void *usb_lowlevel_init(int index) cmd = ehci_readl(&hcor->or_usbcmd); wait_ms(5); reg = HC_VERSION(ehci_readl(&hccr->cr_capbase)); - printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); +// printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); ehcic[index].rootdev = 0; diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c index 78f6360416..9eea1ca62f 100644 --- a/drivers/video/tegra.c +++ b/drivers/video/tegra.c @@ -47,9 +47,9 @@ static struct fdt_lcd config; /* Our LCD config, set up in handle_stage() */ enum { /* Maximum LCD size we support */ - LCD_MAX_WIDTH = 1366, - LCD_MAX_HEIGHT = 800, - LCD_MAX_LOG2_BPP = 4, /* 16 bpp */ + LCD_MAX_WIDTH = 1920, + LCD_MAX_HEIGHT = 1200, + LCD_MAX_LOG2_BPP = 5, /* 32 bpp */ }; int lcd_line_length; diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 5ddc2b9371..1240eabd7e 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -696,7 +696,6 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest) u32 latestVersion = 0; uchar *lDest; uchar *src; - long ret; int i; u32 counter = 0; #ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS @@ -768,28 +767,25 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest) #endif switch (jNode->compr) { case JFFS2_COMPR_NONE: - ret = (unsigned long) ldr_memcpy(lDest, src, jNode->dsize); + (void) ldr_memcpy(lDest, src, jNode->dsize); break; case JFFS2_COMPR_ZERO: - ret = 0; for (i = 0; i < jNode->dsize; i++) *(lDest++) = 0; break; case JFFS2_COMPR_RTIME: - ret = 0; rtime_decompress(src, lDest, jNode->csize, jNode->dsize); break; case JFFS2_COMPR_DYNRUBIN: /* this is slow but it works */ - ret = 0; dynrubin_decompress(src, lDest, jNode->csize, jNode->dsize); break; case JFFS2_COMPR_ZLIB: - ret = zlib_decompress(src, lDest, jNode->csize, jNode->dsize); + (void)zlib_decompress(src, lDest, jNode->csize, jNode->dsize); break; #if defined(CONFIG_JFFS2_LZO) case JFFS2_COMPR_LZO: - ret = lzo_decompress(src, lDest, jNode->csize, jNode->dsize); + (void)lzo_decompress(src, lDest, jNode->csize, jNode->dsize); break; #endif default: @@ -1575,9 +1571,8 @@ jffs2_1pass_build_lists(struct part_info * part) if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) { uint32_t inbuf_ofs; - uint32_t empty_start, scan_end; + uint32_t scan_end; - empty_start = ofs; ofs += 4; scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE( part->sector_size)/8, diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h index 79cb79c6fe..69d15088b1 100644 --- a/include/configs/cardhu.h +++ b/include/configs/cardhu.h @@ -32,12 +32,13 @@ #define V_PROMPT "Tegra3 # " #define CONFIG_TEGRA3_CARDHU -#define CONFIG_SYS_SKIP_ARM_RELOCATION +/* This currently fails environment memory allocation */ +#undef CONFIG_SYS_SKIP_ARM_RELOCATION #define CONFIG_EXTRA_BOOTARGS \ "panel=lvds " \ "tegraid=30.1.2.0.0 " \ - "debug_uartport=lsport\0" \ + "debug_uartport=lsport\0" #define CONFIG_TEGRA_LP0 #define CONFIG_TEGRA3_WARMBOOT @@ -99,4 +100,16 @@ #define CONFIG_ENV_IS_NOWHERE +/* support USB ethernet adapters */ +#define CONFIG_USB_HOST_ETHER +#define CONFIG_USB_ETHER_ASIX + +/* + * Ethernet support + */ +#define CONFIG_CMD_NET +#define CONFIG_NET_MULTI +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP + #endif /* __CONFIG_H */ diff --git a/include/configs/colibri_t20.h b/include/configs/colibri_t20.h new file mode 100644 index 0000000000..52a8414148 --- /dev/null +++ b/include/configs/colibri_t20.h @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2012 Toradex, Inc. + * Portions Copyright (c) 2010, 2011 NVIDIA Corporation + * Portions Copyright (c) 2011 The Chromium OS Authors + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include + +#define CONFIG_COLIBRI_T20 /* Toradex Colibri T20 module */ + +//#define CONFIG_TEGRA2_LP0 + +/* High-level configuration options */ +#define TEGRA2_SYSMEM "mem=256M@0M" +#define V_PROMPT "Tegra2 # " + +#define CONFIG_OF_UPDATE_FDT_BEFORE_BOOT 1 + +#include "tegra2-common.h" + +//careful this might fail kernel booting +#undef CONFIG_BOOTSTAGE /* Record boot time */ +#undef CONFIG_BOOTSTAGE_REPORT /* Print a boot time report */ + +#define CONFIG_SYS_NAND_BASE_LIST {} + +//#define USB_KBD_DEBUG +#define CONFIG_USB_KEYBOARD + +#define CONFIG_CONSOLE_MUX +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial,usbkbd\0" \ + "stdout=serial,lcd\0" \ + "stderr=serial,lcd\0" + +#define CONFIG_SYS_BOARD_ODMDATA 0x300d8011 /* lp1, 1GB */ + +#define CONFIG_REVISION_TAG 1 +#define CONFIG_SERIAL_TAG 1 + +#define CONFIG_TRDX_CFG_BLOCK_OFFSET (gd->conf_blk_offset) +#define CONFIG_TRDX_CFG_BLOCK_OFFSET2 (gd->conf_blk_offset2) + +#define CONFIG_CMD_ASKENV +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_ELF +#undef CONFIG_CMD_FLASH +#define CONFIG_CMD_SAVEENV +#define CONFIG_CMD_UBI +#define CONFIG_CMD_UBIFS +#define CONFIG_LZO + +#undef CONFIG_BOOTDELAY +#define CONFIG_BOOTDELAY 5 +#define CONFIG_NETMASK 255.255.255.0 +#undef CONFIG_IPADDR +#define CONFIG_IPADDR 192.168.10.2 +#undef CONFIG_SERVERIP +#define CONFIG_SERVERIP 192.168.10.1 +#undef CONFIG_BOOTFILE /* passed by BOOTP/DHCP */ + +#define CONFIG_BZIP2 +#define CONFIG_CRC32_VERIFY +#define CONFIG_TIMESTAMP + +#define CONFIG_AUTO_COMPLETE + +#define CONFIG_SYS_USE_UBI +#define CONFIG_MTD_DEVICE +#define CONFIG_CMD_JFFS2 +#define CONFIG_JFFS2_NAND +#define CONFIG_JFFS2_CMDLINE +#define CONFIG_RBTREE + +#undef CONFIG_LINUXCONSOLE /* dynamically adjusted */ + +#define DEFAULT_BOOTCOMMAND \ + "run flashboot; run nfsboot" + +#define FLASH_BOOTCMD \ + "run setup; " \ + "setenv bootargs ${defargs} ${flashargs} ${mtdparts} ${setupargs}; " \ + "echo Booting from NAND...; " \ + "nboot ${loadaddr} 0 ${lnxoffset} && bootm" + +#define MMC_BOOTCMD \ + "echo Loading RAM disk and kernel from MMC/SD card...; "\ + "mmc init && " \ + "fatload mmc 0:1 0xC08000 rootfs-ext2.img.gz && " \ + "fatload mmc 0:1 ${loadaddr} uImage;" \ + "run ramboot" + +#define NFS_BOOTCMD \ + "run setup; " \ + "setenv bootargs ${defargs} ${nfsargs} ${mtdparts} ${setupargs}; " \ + "echo Booting from NFS...; " \ + "usb start; " \ + "dhcp; " \ + "bootm" + +#define RAM_BOOTCMD \ + "run setup; " \ + "setenv bootargs ${defargs} ${ramargs} ${mtdparts} ${setupargs}; " \ + "echo Booting from RAM...; " \ + "bootm" + +#define UBI_BOOTCMD \ + "run setup; " \ + "setenv bootargs ${defargs} ${ubiargs} ${mtdparts} ${setupargs}; " \ + "echo Booting from NAND...; " \ + "ubi part kernel-ubi && ubi read ${loadaddr} kernel; " \ + "bootm" + +#define USB_BOOTCMD \ + "echo Loading RAM disk and kernel from USB stick...; " \ + "usb start && " \ + "fatload usb 0:1 0xC08000 rootfs-ext2.img.gz && " \ + "fatload usb 0:1 ${loadaddr} uImage;" \ + "run ramboot" + +#define SD_BOOTCMD \ + "run setup; " \ + "setenv bootargs ${defargs} ${sdargs} ${mtdparts} ${setupargs}; " \ + "echo Booting from MMC/SD card...; " \ + "mmc read 0 ${loadaddr} 0x2a00 0x2000; " \ + "bootm" + +#undef CONFIG_BOOTARGS +#undef CONFIG_BOOTCOMMAND +#undef CONFIG_DIRECT_BOOTARGS +#define CONFIG_BOOTCOMMAND DEFAULT_BOOTCOMMAND +#define CONFIG_NFSBOOTCOMMAND NFS_BOOTCMD +#define CONFIG_RAMBOOTCOMMAND RAM_BOOTCMD +//moved from disk/part_efi.h to here, give the block where the GP1 partition starts +//compare with sdargs below +#ifdef __CONFIG_SDBOOT_H +#define GPT_PRIMARY_PARTITION_TABLE_LBA 18945ULL +#else +#define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL +#endif + +#define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_STD_DEVICES_SETTINGS \ + "defargs=video=tegrafb vmalloc=128M usb_high_speed=1\0" \ + "flashargs=ip=off root=/dev/mtdblock0 rw rootfstype=yaffs2\0" \ + "flashboot=" FLASH_BOOTCMD "\0" \ + "mmcboot=" MMC_BOOTCMD "\0" \ + "nfsargs=ip=:::::eth0:on root=/dev/nfs rw netdevwait\0" \ + "ramargs=initrd=0xA1800000,32M ramdisk_size=32768 root=/dev/ram0 rw\0" \ + "sdargs=root=/dev/mmcblk3p1 ip=:::::eth0:off rw,noatime rootfstype=ext3 rootwait gpt gpt_sector=18945\0" \ + "sdboot=" SD_BOOTCMD "\0" \ + "setup=setenv setupargs asix_mac=${ethaddr} no_console_suspend=1 console=ttyS0,${baudrate}n8 console=tty1 debug_uartport=lsport,0 ${memargs}\0" \ + "ubiargs=ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs\0" \ + "ubiboot=" UBI_BOOTCMD "\0" \ + "usbboot=" USB_BOOTCMD "\0" \ + "" + +/* Dynamic MTD partition support */ +#define CONFIG_CMD_MTDPARTS /* Enable 'mtdparts' command line support */ +#define CONFIG_MTD_PARTITIONS /* ??? */ +#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */ +#define MTDIDS_DEFAULT "nand0=tegra_nand" + +/* GPIO */ +#define CONFIG_TEGRA_GPIO +#define CONFIG_CMD_TEGRA_GPIO_INFO + +/* I2C */ +#define CONFIG_TEGRA_I2C +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_SYS_MAX_I2C_BUS 4 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_CMD_I2C + +/* PMU and EMC support, requires i2c */ +#define CONFIG_TEGRA_PMU +#define CONFIG_TEGRA_CLOCK_SCALING + +/* SD/MMC */ +#define CONFIG_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_TEGRA_MMC +#define CONFIG_CMD_MMC + +#define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_FAT + +/* Environment not stored */ +//#define CONFIG_ENV_IS_NOWHERE +#ifndef CONFIG_ENV_IS_NOWHERE +/* Environment stored in NAND flash */ +#define CONFIG_ENV_IS_IN_NAND 1 /* use NAND for environment vars */ +#if defined(CONFIG_ENV_IS_IN_NAND) +/* once the nand is detected the corresponding setting is taken */ +#define CONFIG_ENV_OFFSET (gd->env_offset) +#define CONFIG_ENV_RANGE 0x80000 +#endif + +#endif + +/* + * LCDC configuration + */ +#define CONFIG_LCD +#define CONFIG_VIDEO_TEGRA + +/* TODO: This needs to be configurable at run-time */ +#define LCD_BPP LCD_COLOR16 +#define CONFIG_SYS_WHITE_ON_BLACK /* Console colors */ + +#define CONFIG_DEFAULT_DEVICE_TREE "colibri_t20" + +/* NAND support */ +#define CONFIG_CMD_NAND +#define CONFIG_TEGRA2_NAND + +/* Max number of NAND devices */ +#define CONFIG_SYS_MAX_NAND_DEVICE 1 + +#define CONFIG_CMD_IMI + +#endif /* __CONFIG_H */ diff --git a/include/configs/colibri_t20_sdboot.h b/include/configs/colibri_t20_sdboot.h new file mode 100644 index 0000000000..a23d1a6823 --- /dev/null +++ b/include/configs/colibri_t20_sdboot.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 Toradex, Inc. + * Portions Copyright (c) 2010, 2011 NVIDIA Corporation + * Portions Copyright (c) 2011 The Chromium OS Authors + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Use this configuration for an u-boot which stores its environment in SD/MMC + * Useful if SD/MMC is selected as the boot device, so also the environment is taken from there + * + * Use colibri_t20.h for everything which is not specific to using SD/MMC as the boot device!! + */ + +/* +SD-BOOT +The sd sector numbers are used as follows: +u-boot needs to find ENV and LNX to get to the environment and the kernel, the kernel needs to find the APP partition for the rootfs. +ENV: colibri_t20_sdboot.h +Set CONFIG_ENV_MMC_OFFSET to the byte start address of ENV, take the sector address of Partid 6 (which is in 2024 byte sectors) + +LNX: colibri_t20.h +Set the u-boot environment SDBOOTCMD below, mmc read RAMloadaddr, 512byte sector start, 512byte copy length +take the sector address of Partid 7 (which is in 2024 byte sectors) + +APP: colibri_t20.h +Set the u-boot environment sdargs and the variable GPT_PRIMARY_PARTITION_TABLE_LBA below. +The kernel finds the partition with the help of the GP1/GPT partitions. The kernel commandline must include "gpt gpt_sector=xxx" +to force it to use GUID Partition Table (GPT) and to give the 512byte sector start address of the primary GUID. +Set this in +Take the start address of Partid 8 (which is in 2048 byte sectors). add 1 to the resulting 512byte block. (at pos. 0 is the MBR) + +E.g. Output during nvflash procedure on serial console: +SD Alloc Partid=2, start sector=0,num=1536 +SD Alloc Partid=3, start sector=1536,num=64 +SD Alloc Partid=4, start sector=1600,num=960 +SD Alloc Partid=5, start sector=2560,num=64 +SD Alloc Partid=6, start sector=2624,num=64 +SD Alloc Partid=7, start sector=2688,num=2048 +SD Alloc Partid=8, start sector=4736,num=512 +SD Alloc Partid=9, start sector=5248,num=500032 +SD Alloc Partid=10, start sector=505280,num=460352 + +sector start address 4736 * 2048 -> 18944 * 512 -> GPT start sector is 18945. +*/ + + +#ifndef __CONFIG_SDBOOT_H +#define __CONFIG_SDBOOT_H + +#include "colibri_t20.h" + +#undef DEFAULT_BOOTCOMMAND +#undef CONFIG_BOOTCOMMAND + +#define DEFAULT_BOOTCOMMAND \ + "run sdboot; run nfsboot" +#define CONFIG_BOOTCOMMAND DEFAULT_BOOTCOMMAND + + +#ifdef CONFIG_ENV_IS_NOWHERE +#undef CONFIG_ENV_IS_NOWHERE +#endif +#ifdef CONFIG_ENV_IS_IN_NAND +#undef CONFIG_ENV_IS_IN_NAND +#endif + +/* Environment stored in SD/MMC */ +#define CONFIG_ENV_IS_IN_MMC 1 + +#if defined(CONFIG_ENV_IS_IN_MMC) +#define CONFIG_SYS_MMC_ENV_DEV 0 /* use MMC0, slot on eval board and Iris */ +#define CONFIG_ENV_MMC_OFFSET (10496 * 512) /* Byteaddress of the beginning of the ENV partition */ +#endif + +#endif /* __CONFIG_H */ diff --git a/include/configs/colibri_t30.h b/include/configs/colibri_t30.h new file mode 100644 index 0000000000..02fcbe9139 --- /dev/null +++ b/include/configs/colibri_t30.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2012 Toradex, Inc. + * Portions Copyright (c) 2010, 2011 NVIDIA Corporation + * Portions Copyright (c) 2011 The Chromium OS Authors + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include + +#define CONFIG_COLIBRI_T30 /* Toradex Colibri T30 module */ + +/* High-level configuration options */ +#define TEGRA3_SYSMEM "mem=1023M@2048M vmalloc=128M" +#define V_PROMPT "Tegra3 # " + +#define CONFIG_TEGRA3_CARDHU +/* This currently fails environment memory allocation */ +#undef CONFIG_SYS_SKIP_ARM_RELOCATION + +#include "tegra3-common.h" +/* undef the enviroment settings in tegra3-common.h / tegra-common.h */ +#undef CONFIG_ENV_SIZE +#undef CONFIG_LOADADDR +#undef CONFIG_BOOTDELAY +#undef CONFIG_BOOTARGS +#undef CONFIG_BOOTCOMMAND +#undef CONFIG_DIRECT_BOOTARGS + + +#define CONFIG_DEFAULT_DEVICE_TREE "colibri_t30" + +//#define USB_KBD_DEBUG +#define CONFIG_USB_KEYBOARD + +#define CONFIG_CONSOLE_MUX +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_STD_DEVICES_SETTINGS "stdin=serial,usbkbd\0" \ + "stdout=serial,lcd\0" \ + "stderr=serial,lcd\0" + +#define CONFIG_SYS_BOARD_ODMDATA 0x40080105 /* 1GB, UARTA, etc */ + +/* PMU */ +/* disabled for now #define CONFIG_HW_WATCHDOG */ + +#define CONFIG_BOOTDELAY 3 + +/* ENV */ +#define CONFIG_ENV_SIZE SZ_4K /* env size is a maximum of 4k */ +#define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE + +#define CONFIG_NFSBOOTCOMMAND \ + "setenv bootargs ${defargs} ${nfsargs}; " \ + "echo Booting from NFS...; " \ + "usb start; " \ + "dhcp; " \ + "bootm ${loadaddr} " + +#define USB_BOOTCMD \ + "setenv bootargs ${defargs} root=/dev/sda3 rw rootwait; " \ + "echo Booting from USB Stick...; " \ + "usb start; " \ + "fatload usb 0:1 ${loadaddr} uimage; " \ + "bootm ${loadaddr} " + +#define EMMC_BOOTCMD \ + "setenv bootargs ${defargs} ${mmcargs} ;" \ + "echo Booting from internal eMMC card...; " \ + "mmc read 0 ${loadaddr} ${mmc_kernel_sec}; " \ + "bootm ${loadaddr} " + +#define CONFIG_BOOTCOMMAND "run emmcboot; run usbboot; run nfsboot;" +#define CONFIG_LOADADDR 0x80408000 +#define CONFIG_ETHADDR 00:0e:c6:87:72:01 +#define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_STD_DEVICES_SETTINGS \ + "board=colibri_t30\0" \ + "defargs=console=ttyS0,115200n8 debug_uartport=lsport lp0_vec=0x00002000@0x9C406000 video=tegrafb mem=1023M@2048M vmalloc=128M noinitrd usbcore.old_scheme_first=1 core_edp_mv=1300 panel=lvds tegraid=30.1.2.0.0 tegra_fbmem=3072K@0xBFE00000 \0" \ + "mmcargs=root=/dev/mmcblk0p1 ip=:::::eth0:off rw rootwait rootfstype=ext2 gpt gpt_sector=32768 \0" \ + "mmc_kernel_sec=0x5000 0x2000 \0" \ + "nfsargs=ip=:::::eth0:on root=/dev/nfs rw netdevwait\0" \ + "emmcboot=" EMMC_BOOTCMD "\0" \ + "usbboot=" USB_BOOTCMD "\0" + + +/* GPIO */ +#define CONFIG_TEGRA_GPIO +#define CONFIG_CMD_TEGRA_GPIO_INFO + +/* I2C */ +#define CONFIG_TEGRA_I2C +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_SYS_MAX_I2C_BUS 4 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_CMD_I2C + +/* PMU */ +#define CONFIG_TEGRA_PMU + +/* SD/MMC */ +#define CONFIG_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_TEGRA_MMC +#define CONFIG_CMD_MMC + +#define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_FAT + +/* NAND support */ +/*#define CONFIG_CMD_NAND +#define CONFIG_TEGRA2_NAND */ + +/* Max number of NAND devices */ +/*#define CONFIG_SYS_MAX_NAND_DEVICE 1 */ + +/* Environment storage location, define only one of the alternatives */ +/*#define CONFIG_ENV_IS_NOWHERE*/ /* Environment not stored */ +/*#define CONFIG_ENV_IS_IN_NAND*/ /* use NAND for environment vars */ +#define CONFIG_ENV_IS_IN_MMC /* use NAND for environment vars */ + +/* Environment stored in NAND flash */ +#if defined(CONFIG_ENV_IS_IN_NAND) +/* temporarily use space at end of LNX kernel partition for now */ +/*#define CONFIG_ENV_OFFSET 0x1680000 +#define CONFIG_ENV_RANGE 0x200000*/ +#endif + +#if defined(CONFIG_ENV_IS_IN_MMC) +#define CONFIG_SYS_MMC_ENV_DEV 0 /* use MMC0 */ +#define CONFIG_ENV_OFFSET (16384 * 512) /* Byteaddress of the beginning of the ENV partition */ +#endif + +/* support USB ethernet adapters */ +#define CONFIG_USB_HOST_ETHER +#define CONFIG_USB_ETHER_ASIX + +/* + * Ethernet support + */ +#define CONFIG_CMD_NET +#define CONFIG_NET_MULTI +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP + +/* + * LCDC configuration + */ +#define CONFIG_LCD +#define CONFIG_VIDEO_TEGRA + +/* TODO: This needs to be configurable at run-time */ +#define LCD_BPP LCD_COLOR16 +#define CONFIG_SYS_WHITE_ON_BLACK /*Console colors*/ + +#endif /* __CONFIG_H */ diff --git a/include/configs/harmony.h b/include/configs/harmony.h index 6fb1021fcb..c9e0583e1f 100644 --- a/include/configs/harmony.h +++ b/include/configs/harmony.h @@ -126,6 +126,14 @@ /* physical address to access nand at CS0 */ #define CONFIG_SYS_NAND_BASE TEGRA_NAND_BASE +/* I2C */ +#define CONFIG_TEGRA_I2C +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_SYS_MAX_I2C_BUS 4 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_CMD_I2C + /* Max number of NAND devices */ #define CONFIG_SYS_MAX_NAND_DEVICE 1 #endif /* __CONFIG_H */ diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h index 21ddcdf7a9..8c4448beca 100644 --- a/include/configs/tegra-common.h +++ b/include/configs/tegra-common.h @@ -111,6 +111,7 @@ /* allow to overwrite serial and ethaddr */ #define CONFIG_ENV_OVERWRITE +/* environment baudrate unfortunately does not seem to work properly */ #define CONFIG_BAUDRATE 115200 #define CONFIG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\ 115200} diff --git a/include/configs/tegra2-common.h b/include/configs/tegra2-common.h index 8396dc4d3b..d8f1eda7b3 100644 --- a/include/configs/tegra2-common.h +++ b/include/configs/tegra2-common.h @@ -107,7 +107,8 @@ #define CONFIG_SYS_NO_FLASH #ifdef CONFIG_TEGRA2_WARMBOOT -#define TEGRA_LP0_ADDR 0x1C406000 +//ToDo: determine LP0 address dynamically +#define TEGRA_LP0_ADDR 0x0C406000 #define TEGRA_LP0_SIZE 0x2000 #define TEGRA_LP0_VEC \ "lp0_vec=" QUOTE(TEGRA_LP0_SIZE) "@" QUOTE(TEGRA_LP0_ADDR) " " @@ -154,9 +155,9 @@ */ #define CONFIG_NR_DRAM_BANKS 1 #define PHYS_SDRAM_1 TEGRA_SDRC_CS0 -#define PHYS_SDRAM_1_SIZE 0x20000000 /* 512M */ +/* Size queried at runtime by board_query_sdram_size() */ -#define CONFIG_SYS_TEXT_BASE 0x00E08000 +#define CONFIG_SYS_TEXT_BASE 0x00108000 #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 #define BCT_SDRAM_PARAMS_OFFSET (BCT_OFFSET + 0x88) diff --git a/include/configs/tegra3-common.h b/include/configs/tegra3-common.h index ea391c1900..4a42c63e46 100644 --- a/include/configs/tegra3-common.h +++ b/include/configs/tegra3-common.h @@ -131,7 +131,7 @@ #define PHYS_SDRAM_1 TEGRA_SDRC_CS0 #define PHYS_SDRAM_1_SIZE 0x40000000 /* 1GB */ -#define CONFIG_SYS_TEXT_BASE 0x80E08000 +#define CONFIG_SYS_TEXT_BASE 0x80108000 #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 #define CONFIG_INITRD_TAG /* enable initrd ATAG */ diff --git a/include/fdt_decode.h b/include/fdt_decode.h index 7b9e94919c..0969e29dec 100644 --- a/include/fdt_decode.h +++ b/include/fdt_decode.h @@ -244,6 +244,17 @@ enum { FDT_NAND_TIMING_COUNT }; +enum { + FDT_NAND_ENV_OFFSET, + FDT_NAND_CONFIG_OFFSET, + FDT_NAND_CONFIG_OFFSET2, + FDT_NAND_KERNEL_OFFSET, + FDT_NAND_ROOTFS_LENGTH, + FDT_NAND_ROOTFS_SIZE, + + FDT_NAND_PARTOFFSET_COUNT +}; + /* Information about an attached NAND chip */ struct fdt_nand { struct nand_ctlr *reg; @@ -262,6 +273,13 @@ struct fdt_nand { int page_spare_bytes; int page_data_bytes; /* Bytes in data area */ int timing[FDT_NAND_TIMING_COUNT]; + /* + * The offset of the start of + * u-boot-environment config-block kernel rootfs-size rootfs-start + * rootfs: the numbers are concatenated to mtdparts=tegra_nand:K@K(userspace) + * take them from a download with NVFLASH + */ + int nv_partitions[FDT_NAND_PARTOFFSET_COUNT]; }; /** diff --git a/include/u-boot/md5.h b/include/u-boot/md5.h index 08924cce3c..e09c16a6e3 100644 --- a/include/u-boot/md5.h +++ b/include/u-boot/md5.h @@ -11,7 +11,10 @@ struct MD5Context { __u32 buf[4]; __u32 bits[2]; - unsigned char in[64]; + union { + unsigned char in[64]; + __u32 in32[16]; + }; }; /* diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c index 09bdc8f6ca..8f00a63228 100644 --- a/lib/lzo/lzo1x_decompress.c +++ b/lib/lzo/lzo1x_decompress.c @@ -32,7 +32,6 @@ static const unsigned char lzop_magic[] = { static inline const unsigned char *parse_header(const unsigned char *src) { - u8 level = 0; u16 version; int i; @@ -47,7 +46,7 @@ static inline const unsigned char *parse_header(const unsigned char *src) version = get_unaligned_be16(src); src += 7; if (version >= 0x0940) - level = *src++; + src++; /* skip mtime_high */ if (get_unaligned_be32(src) & HEADER_HAS_FILTER) src += 4; /* filter info */ diff --git a/lib/md5.c b/lib/md5.c index 81a09e3f90..2ae4a06319 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -153,8 +153,8 @@ MD5Final(unsigned char digest[16], struct MD5Context *ctx) byteReverse(ctx->in, 14); /* Append length in bits and transform */ - ((__u32 *) ctx->in)[14] = ctx->bits[0]; - ((__u32 *) ctx->in)[15] = ctx->bits[1]; + ctx->in32[14] = ctx->bits[0]; + ctx->in32[15] = ctx->bits[1]; MD5Transform(ctx->buf, (__u32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); -- cgit v1.2.3