diff options
Diffstat (limited to 'patches/barebox-2012.07.0/0000-barebox-v2012.07.0-to-master.patch')
-rw-r--r-- | patches/barebox-2012.07.0/0000-barebox-v2012.07.0-to-master.patch | 12305 |
1 files changed, 12305 insertions, 0 deletions
diff --git a/patches/barebox-2012.07.0/0000-barebox-v2012.07.0-to-master.patch b/patches/barebox-2012.07.0/0000-barebox-v2012.07.0-to-master.patch new file mode 100644 index 0000000..4519124 --- /dev/null +++ b/patches/barebox-2012.07.0/0000-barebox-v2012.07.0-to-master.patch @@ -0,0 +1,12305 @@ +diff --git a/.gitignore b/.gitignore +index df0ed2c..fd429fa 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -65,3 +65,4 @@ cscope.* + *.patch + scripts/gen_netx_image + scripts/s5p_cksum ++scripts/bareboxenv-target +diff --git a/Makefile b/Makefile +index 63da477..ebcf9bf 100644 +--- a/Makefile ++++ b/Makefile +@@ -540,7 +540,7 @@ quiet_cmd_check_file_size = CHKSIZE $@ + max_size=`printf "%d" $2`; \ + if [ $$size -gt $$max_size ] ; \ + then \ +- echo "$@ size $$size > of the maximum size $$max_size"; \ ++ echo "$@ size $$size > of the maximum size $$max_size" >&2; \ + exit 1 ; \ + fi; + +@@ -1003,6 +1003,7 @@ CLEAN_DIRS += $(MODVERDIR) + CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \ + .tmp_version .tmp_barebox* barebox.bin barebox.map barebox.S \ + .tmp_kallsyms* barebox_default_env* barebox.ldr \ ++ scripts/bareboxenv-target \ + Doxyfile.version barebox.srec barebox.s5p + + # Directories & files removed with 'make mrproper' +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 3eada5b..af4cb59 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -135,7 +135,15 @@ config CMD_ARM_CPUINFO + default y + help + Say yes here to get a cpuinfo command to show some +- information about the cp15 registers ++ CPU information using the cp15 registers ++ ++config CMD_ARM_MMUINFO ++ bool "mmuinfo command" ++ depends on CPU_V7 ++ default n ++ help ++ Say yes here to get a mmuinfo command to show some ++ MMU and cache information using the cp15 registers + + config CPU_V7_DCACHE_SKIP + bool "Skip DCache Invalidate" +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index bd684dc..1225df7 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -136,6 +136,7 @@ board-$(CONFIG_MACH_TQMA53) := tqma53 + board-$(CONFIG_MACH_TX51) := karo-tx51 + board-$(CONFIG_MACH_MX6Q_ARM2) := freescale-mx6-arm2 + board-$(CONFIG_MACH_TOSHIBA_AC100) := toshiba-ac100 ++board-$(CONFIG_MACH_CCMX51) := ccxmx51 + + machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y)) + +diff --git a/arch/arm/boards/a9m2410/a9m2410.c b/arch/arm/boards/a9m2410/a9m2410.c +index eaafdbd..e2044a9 100644 +--- a/arch/arm/boards/a9m2410/a9m2410.c ++++ b/arch/arm/boards/a9m2410/a9m2410.c +@@ -32,6 +32,7 @@ + #include <partition.h> + #include <nand.h> + #include <io.h> ++#include <mach/devices-s3c24xx.h> + #include <mach/s3c-iomap.h> + #include <mach/s3c24xx-nand.h> + #include <mach/s3c-generic.h> +@@ -109,8 +110,7 @@ static int a9m2410_devices_init(void) + writel(reg, S3C_MISCCR); + + /* ----------- the devices the boot loader should work with -------- */ +- add_generic_device("s3c24x0_nand", DEVICE_ID_DYNAMIC, NULL, S3C24X0_NAND_BASE, +- 0, IORESOURCE_MEM, &nand_info); ++ s3c24xx_add_nand(&nand_info); + /* + * SMSC 91C111 network controller on the baseboard + * connected to CS line 1 and interrupt line +@@ -145,8 +145,7 @@ void __bare_init nand_boot(void) + + static int a9m2410_console_init(void) + { +- add_generic_device("s3c_serial", DEVICE_ID_DYNAMIC, NULL, S3C_UART1_BASE, +- S3C_UART1_SIZE, IORESOURCE_MEM, NULL); ++ s3c24xx_add_uart1(); + return 0; + } + +diff --git a/arch/arm/boards/a9m2440/a9m2440.c b/arch/arm/boards/a9m2440/a9m2440.c +index 1d20248..8975c15 100644 +--- a/arch/arm/boards/a9m2440/a9m2440.c ++++ b/arch/arm/boards/a9m2440/a9m2440.c +@@ -32,6 +32,7 @@ + #include <partition.h> + #include <nand.h> + #include <io.h> ++#include <mach/devices-s3c24xx.h> + #include <mach/s3c-iomap.h> + #include <mach/s3c24xx-nand.h> + #include <mach/s3c-generic.h> +@@ -129,8 +130,7 @@ static int a9m2440_devices_init(void) + writel(reg, S3C_MISCCR); + + /* ----------- the devices the boot loader should work with -------- */ +- add_generic_device("s3c24x0_nand", DEVICE_ID_DYNAMIC, NULL, S3C24X0_NAND_BASE, 0, +- IORESOURCE_MEM, &nand_info); ++ s3c24xx_add_nand(&nand_info); + /* + * cs8900 network controller onboard + * Connected to CS line 5 + A24 and interrupt line EINT9, +@@ -164,8 +164,7 @@ void __bare_init nand_boot(void) + + static int a9m2440_console_init(void) + { +- add_generic_device("s3c_serial", DEVICE_ID_DYNAMIC, NULL, S3C_UART1_BASE, +- S3C_UART1_SIZE, IORESOURCE_MEM, NULL); ++ s3c24xx_add_uart1(); + return 0; + } + +diff --git a/arch/arm/boards/ccxmx51/Makefile b/arch/arm/boards/ccxmx51/Makefile +new file mode 100644 +index 0000000..249927e +--- /dev/null ++++ b/arch/arm/boards/ccxmx51/Makefile +@@ -0,0 +1,2 @@ ++obj-y += flash_header.o ccxmx51.o ++obj-$(CONFIG_MACH_CCMX51_BASEBOARD) += ccxmx51js.o +diff --git a/arch/arm/boards/ccxmx51/ccxmx51.c b/arch/arm/boards/ccxmx51/ccxmx51.c +new file mode 100644 +index 0000000..f494174 +--- /dev/null ++++ b/arch/arm/boards/ccxmx51/ccxmx51.c +@@ -0,0 +1,489 @@ ++/* ++ * (C) Copyright 2009-2010 Digi International, Inc. ++ * Copyright (C) 2007 Sascha Hauer, Pengutronix ++ * (c) 2011 Eukrea Electromatique, Eric BĂ©nard <eric@eukrea.com> ++ * ++ * 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 <common.h> ++#include <net.h> ++#include <init.h> ++#include <environment.h> ++#include <mach/imx-regs.h> ++#include <fec.h> ++#include <mach/gpio.h> ++#include <asm/armlinux.h> ++#include <generated/mach-types.h> ++#include <partition.h> ++#include <fs.h> ++#include <fcntl.h> ++#include <sizes.h> ++#include <nand.h> ++#include <notifier.h> ++#include <spi/spi.h> ++#include <mfd/mc13xxx.h> ++#include <asm/io.h> ++#include <mach/imx-nand.h> ++#include <mach/spi.h> ++#include <mach/generic.h> ++#include <mach/iomux-mx51.h> ++#include <mach/devices-imx51.h> ++#include <mach/iim.h> ++#include <mach/clock-imx51_53.h> ++#include <mach/imx5.h> ++ ++#include "ccxmx51.h" ++ ++static struct ccxmx51_ident ccxmx51_ids[] = { ++/* 0x00 */ { "Unknown", 0, 0, 0, 0, 0 }, ++/* 0x01 */ { "Not supported", 0, 0, 0, 0, 0 }, ++/* 0x02 */ { "i.MX515@800MHz, Wireless, PHY, Ext. Eth, Accel", SZ_512M, 0, 1, 1, 1 }, ++/* 0x03 */ { "i.MX515@800MHz, PHY, Ext. Eth, Accel", SZ_512M, 0, 1, 1, 0 }, ++/* 0x04 */ { "i.MX515@600MHz, Wireless, PHY, Ext. Eth, Accel", SZ_512M, 1, 1, 1, 1 }, ++/* 0x05 */ { "i.MX515@600MHz, PHY, Ext. Eth, Accel", SZ_512M, 1, 1, 1, 0 }, ++/* 0x06 */ { "i.MX515@800MHz, Wireless, PHY, Accel", SZ_512M, 0, 1, 0, 1 }, ++/* 0x07 */ { "i.MX515@800MHz, PHY, Accel", SZ_512M, 0, 1, 0, 0 }, ++/* 0x08 */ { "i.MX515@800MHz, Wireless, PHY, Accel", SZ_256M, 0, 1, 0, 1 }, ++/* 0x09 */ { "i.MX515@800MHz, PHY, Accel", SZ_256M, 0, 1, 0, 0 }, ++/* 0x0a */ { "i.MX515@600MHz, Wireless, PHY, Accel", SZ_256M, 1, 1, 0, 1 }, ++/* 0x0b */ { "i.MX515@600MHz, PHY, Accel", SZ_256M, 1, 1, 0, 0 }, ++/* 0x0c */ { "i.MX515@800MHz, Wireless, PHY, Accel", SZ_128M, 0, 1, 0, 1 }, ++/* 0x0d */ { "i.MX512@800MHz", SZ_128M, 0, 0, 0, 0 }, ++/* 0x0e */ { "i.MX515@800MHz, Wireless, PHY, Accel", SZ_512M, 0, 1, 0, 1 }, ++/* 0x0f */ { "i.MX515@600MHz, PHY, Accel", SZ_128M, 1, 1, 0, 0 }, ++/* 0x10 */ { "i.MX515@600MHz, Wireless, PHY, Accel", SZ_128M, 1, 1, 0, 1 }, ++/* 0x11 */ { "i.MX515@800MHz, PHY, Accel", SZ_128M, 0, 1, 0, 0 }, ++/* 0x12 */ { "i.MX515@600MHz, Wireless, PHY, Accel", SZ_512M, 1, 1, 0, 1 }, ++/* 0x13 */ { "i.MX515@800MHz, PHY, Accel", SZ_512M, 0, 1, 0, 0 }, ++}; ++ ++struct ccxmx51_ident *ccxmx51_id; ++ ++struct imx_nand_platform_data nand_info = { ++ .width = 1, ++ .hw_ecc = 1, ++ .flash_bbt = 1, ++}; ++ ++#ifdef CONFIG_DRIVER_NET_FEC_IMX ++static struct fec_platform_data fec_info = { ++ .xcv_type = MII100, ++ .phy_addr = 7, ++}; ++#endif ++ ++static iomux_v3_cfg_t ccxmx51_pads[] = { ++ /* UART1 */ ++ MX51_PAD_UART1_RXD__UART1_RXD, ++ MX51_PAD_UART1_TXD__UART1_TXD, ++ /* UART2 */ ++ MX51_PAD_UART2_RXD__UART2_RXD, ++ MX51_PAD_UART2_TXD__UART2_TXD, ++ /* UART3 */ ++ MX51_PAD_UART3_RXD__UART3_RXD, ++ MX51_PAD_UART3_TXD__UART3_TXD, ++ /* I2C2 */ ++ MX51_PAD_GPIO1_2__I2C2_SCL, ++ MX51_PAD_GPIO1_3__I2C2_SDA, ++ /* eCSPI1 */ ++ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, ++ MX51_PAD_CSPI1_MISO__ECSPI1_MISO, ++ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, ++ MX51_PAD_CSPI1_RDY__ECSPI1_RDY, ++ MX51_PAD_CSPI1_SS0__ECSPI1_SS0, ++ MX51_PAD_CSPI1_SS1__ECSPI1_SS1, ++ /* FEC */ ++ MX51_PAD_DISP2_DAT14__FEC_RDATA0, ++ MX51_PAD_DI2_DISP_CLK__FEC_RDATA1, ++ MX51_PAD_DI_GP4__FEC_RDATA2, ++ MX51_PAD_DISP2_DAT0__FEC_RDATA3, ++ MX51_PAD_DISP2_DAT15__FEC_TDATA0, ++ MX51_PAD_DISP2_DAT6__FEC_TDATA1, ++ MX51_PAD_DISP2_DAT7__FEC_TDATA2, ++ MX51_PAD_DISP2_DAT8__FEC_TDATA3, ++ MX51_PAD_DISP2_DAT9__FEC_TX_EN, ++ MX51_PAD_DISP2_DAT10__FEC_COL, ++ MX51_PAD_DISP2_DAT11__FEC_RX_CLK, ++ MX51_PAD_DISP2_DAT12__FEC_RX_DV, ++ MX51_PAD_DISP2_DAT13__FEC_TX_CLK, ++ MX51_PAD_DI2_PIN2__FEC_MDC, ++ MX51_PAD_DI2_PIN4__FEC_CRS, ++ MX51_PAD_DI2_PIN3__FEC_MDIO, ++ MX51_PAD_DI_GP3__FEC_TX_ER, ++ MX51_PAD_DISP2_DAT1__FEC_RX_ER, ++ /* WEIM */ ++ MX51_PAD_EIM_DA0__EIM_DA0, ++ MX51_PAD_EIM_DA1__EIM_DA1, ++ MX51_PAD_EIM_DA2__EIM_DA2, ++ MX51_PAD_EIM_DA3__EIM_DA3, ++ MX51_PAD_EIM_DA4__EIM_DA4, ++ MX51_PAD_EIM_DA5__EIM_DA5, ++ MX51_PAD_EIM_DA6__EIM_DA6, ++ MX51_PAD_EIM_DA7__EIM_DA7, ++ MX51_PAD_EIM_D16__EIM_D16, ++ MX51_PAD_EIM_D17__EIM_D17, ++ MX51_PAD_EIM_D18__EIM_D18, ++ MX51_PAD_EIM_D19__EIM_D19, ++ MX51_PAD_EIM_D20__EIM_D20, ++ MX51_PAD_EIM_D21__EIM_D21, ++ MX51_PAD_EIM_D22__EIM_D22, ++ MX51_PAD_EIM_D23__EIM_D23, ++ MX51_PAD_EIM_D24__EIM_D24, ++ MX51_PAD_EIM_D25__EIM_D25, ++ MX51_PAD_EIM_D26__EIM_D26, ++ MX51_PAD_EIM_D27__EIM_D27, ++ MX51_PAD_EIM_D28__EIM_D28, ++ MX51_PAD_EIM_D29__EIM_D29, ++ MX51_PAD_EIM_D30__EIM_D30, ++ MX51_PAD_EIM_D31__EIM_D31, ++ MX51_PAD_EIM_OE__EIM_OE, ++ MX51_PAD_EIM_CS5__EIM_CS5, ++ /* NAND */ ++ MX51_PAD_NANDF_D0__NANDF_D0, ++ MX51_PAD_NANDF_D1__NANDF_D1, ++ MX51_PAD_NANDF_D2__NANDF_D2, ++ MX51_PAD_NANDF_D3__NANDF_D3, ++ MX51_PAD_NANDF_D4__NANDF_D4, ++ MX51_PAD_NANDF_D5__NANDF_D5, ++ MX51_PAD_NANDF_D6__NANDF_D6, ++ MX51_PAD_NANDF_D7__NANDF_D7, ++ MX51_PAD_NANDF_ALE__NANDF_ALE, ++ MX51_PAD_NANDF_CLE__NANDF_CLE, ++ MX51_PAD_NANDF_RE_B__NANDF_RE_B, ++ MX51_PAD_NANDF_WE_B__NANDF_WE_B, ++ MX51_PAD_NANDF_WP_B__NANDF_WP_B, ++ MX51_PAD_NANDF_CS0__NANDF_CS0, ++ MX51_PAD_NANDF_RB0__NANDF_RB0, ++ /* LAN9221 IRQ (GPIO1.9) */ ++ MX51_PAD_GPIO1_9__GPIO1_9, ++ /* MC13892 IRQ (GPIO1.5) */ ++ MX51_PAD_GPIO1_5__GPIO1_5, ++ /* MMA7455LR IRQ1 (GPIO1.7) */ ++ MX51_PAD_GPIO1_7__GPIO1_7, ++ /* MMA7455LR IRQ2 (GPIO1.6) */ ++ MX51_PAD_GPIO1_6__GPIO1_6, ++}; ++ ++#define CCXMX51_ECSPI1_CS0 IMX_GPIO_NR(4, 24) ++#define CCXMX51_ECSPI1_CS1 IMX_GPIO_NR(4, 25) ++ ++static int ecspi_0_cs[] = { CCXMX51_ECSPI1_CS0, CCXMX51_ECSPI1_CS1, }; ++ ++static struct spi_imx_master ecspi_0_data = { ++ .chipselect = ecspi_0_cs, ++ .num_chipselect = ARRAY_SIZE(ecspi_0_cs), ++}; ++ ++static const struct spi_board_info ccxmx51_spi_board_info[] = { ++ { ++ .name = "mc13xxx-spi", ++ .max_speed_hz = 6000000, ++ .bus_num = 0, ++ .chip_select = 0, ++ }, ++}; ++ ++static int ccxmx51_mem_init(void) ++{ ++ /* Add minimal SDRAM first */ ++ arm_add_mem_device("ram0", MX51_CSD0_BASE_ADDR, SZ_128M); ++ ++ return 0; ++} ++mem_initcall(ccxmx51_mem_init); ++ ++static void ccxmx51_otghost_init(void) ++{ ++#define MX51_USBOTHER_REGS_OFFSET 0x800 ++#define MX51_USBCTRL_OFFSET 0x0 ++#define MX51_USB_PHY_CTR_FUNC_OFFSET 0x8 ++#define MX51_USB_PHY_CTR_FUNC2_OFFSET 0xc ++#define MX51_USB_UTMI_PHYCTRL1_PLLDIV_MASK 0x3 ++#define MX51_USB_PLL_DIV_19_2_MHZ 0x00 ++#define MX51_USB_PLL_DIV_24_MHZ 0x01 ++#define MX51_USB_PLL_DIV_26_MHZ 0x02 ++#define MX51_USB_PLL_DIV_27_MHZ 0x03 ++#define MX51_OTG_PHYCTRL_OC_DIS_BIT (1 << 8) ++#define MX51_OTG_UCTRL_OWIE_BIT (1 << 27) ++#define MX51_OTG_UCTRL_OPM_BIT (1 << 24) ++ ++#define USBOTHER_BASE (MX51_OTG_BASE_ADDR + MX51_USBOTHER_REGS_OFFSET) ++ ++ u32 reg; ++ ++ /* Set sysclock to 24 MHz */ ++ reg = readl(USBOTHER_BASE + MX51_USB_PHY_CTR_FUNC2_OFFSET); ++ reg &= ~MX51_USB_UTMI_PHYCTRL1_PLLDIV_MASK; ++ reg |= MX51_USB_PLL_DIV_24_MHZ; ++ writel(reg, USBOTHER_BASE + MX51_USB_PHY_CTR_FUNC2_OFFSET); ++ ++ /* OC is not used */ ++ reg = readl(USBOTHER_BASE + MX51_USB_PHY_CTR_FUNC_OFFSET); ++ reg |= MX51_OTG_PHYCTRL_OC_DIS_BIT; ++ writel(reg, USBOTHER_BASE + MX51_USB_PHY_CTR_FUNC_OFFSET); ++ ++ /* Power pins enable */ ++ reg = readl(USBOTHER_BASE + MX51_USBCTRL_OFFSET); ++ reg |= MX51_OTG_UCTRL_OWIE_BIT | MX51_OTG_UCTRL_OPM_BIT; ++ writel(reg, USBOTHER_BASE + MX51_USBCTRL_OFFSET); ++ ++ /* Setup PORTSC */ ++ reg = readl(MX51_OTG_BASE_ADDR + 0x184); ++ reg &= ~(3 << 30); ++ reg |= 1 << 28; ++ writel(reg, MX51_OTG_BASE_ADDR + 0x184); ++ ++ mdelay(10); ++ ++ add_generic_usb_ehci_device(0, MX51_OTG_BASE_ADDR, NULL); ++} ++ ++static int ccxmx51_power_init(void) ++{ ++ struct mc13xxx *mc13xxx_dev; ++ u32 val; ++ ++ mc13xxx_dev = mc13xxx_get(); ++ if (!mc13xxx_dev) ++ return -ENODEV; ++ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_POWER_MISC, &val); ++ /* Reset devices by clearing GP01-GPO4 */ ++ val &= ~((1 << 21) | (3 << 12) | (3 << 10) | (3 << 8) | (3 << 6)); ++ /* Switching off the PWGT1SPIEN */ ++ val |= (1 << 15); ++ /* Switching on the PWGT2SPIEN */ ++ val &= ~(1 << 16); ++ /* Enable short circuit protection */ ++ val |= (1 << 0); ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_POWER_MISC, val); ++ ++ /* Allow charger to charge (4.2V and 560mA) */ ++ val = 0x238033; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_CHARGE, val); ++ ++ /* Set core voltage (SW1) to 1.1V */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_0, &val); ++ val &= ~0x00001f; ++ val |= 0x000014; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_0, val); ++ ++ if (imx_silicon_revision() < IMX_CHIP_REV_3_0) { ++ /* Setup VCC (SW2) to 1.25 */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_1, &val); ++ val &= ~0x00001f; ++ val |= 0x00001a; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_1, val); ++ ++ /* Setup 1V2_DIG1 (SW3) to 1.25 */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_2, &val); ++ val &= ~0x00001f; ++ val |= 0x00001a; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_2, val); ++ } else { ++ /* Setup VCC (SW2) to 1.225 */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_1, &val); ++ val &= ~0x00001f; ++ val |= 0x000019; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_1, val); ++ ++ /* Setup 1V2_DIG1 (SW3) to 1.2 */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_2, &val); ++ val &= ~0x00001f; ++ val |= 0x000018; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_2, val); ++ } ++ ++ if (mc13xxx_dev->revision <= MC13892_REVISION_2_0) { ++ /* Set switchers in PWM mode for Atlas 2.0 and lower */ ++ /* Setup the switcher mode for SW1 & SW2*/ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_4, &val); ++ val &= ~0x003c0f; ++ val |= 0x001405; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_4, val); ++ ++ /* Setup the switcher mode for SW3 & SW4 */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_5, &val); ++ val &= ~0x000f0f; ++ val |= 0x000505; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_5, val); ++ } else { ++ /* Set switchers in Auto in NORMAL mode & STANDBY mode for Atlas 2.0a */ ++ /* Setup the switcher mode for SW1 & SW2*/ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_4, &val); ++ val &= ~0x003c0f; ++ val |= 0x002008; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_4, val); ++ ++ /* Setup the switcher mode for SW3 & SW4 */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_5, &val); ++ val &= ~0x000f0f; ++ val |= 0x000808; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_5, val); ++ } ++ ++ /* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SETTING_1, &val); ++ val &= ~0x0001fc; ++ val |= 0x0001f4; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SETTING_1, val); ++ ++ /* Configure VGEN3 and VCAM regulators to use external PNP */ ++ val = 0x000208; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_MODE_1, val); ++ udelay(200); ++ ++ /* Set VGEN3 to 1.8V */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SETTING_0, &val); ++ val &= ~(1 << 14); ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SETTING_0, val); ++ ++ /* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */ ++ val = 0x049249; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_MODE_1, val); ++ ++ /* Enable USB1 charger */ ++ val = 0x000409; ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_USB1, val); ++ ++ /* Set VCOIN to 3.0V and Enable It */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_POWER_CTL0, &val); ++ val &= ~(7 << 20); ++ val |= (4 << 20) | (1 << 23); ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_POWER_CTL0, val); ++ /* Keeps VSRTC and CLK32KMCU */ ++ val |= (1 << 4); ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_POWER_CTL0, val); ++ ++ /* De-assert reset of external devices on GP01, GPO2, GPO3 and GPO4 */ ++ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_POWER_MISC, &val); ++ /* GPO1 - External */ ++ /* GP02 - LAN9221 */ ++ /* GP03 - FEC */ ++ /* GP04 - Wireless */ ++ if (IS_ENABLED(CONFIG_DRIVER_NET_SMC911X) && ccxmx51_id->eth0) ++ val |= (1 << 8); ++ if (IS_ENABLED(CONFIG_DRIVER_NET_FEC_IMX) && ccxmx51_id->eth1) ++ val |= (1 << 10); ++ if (ccxmx51_id->wless) ++ val |= (1 << 12); ++ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_POWER_MISC, val); ++ ++ udelay(100); ++ ++ return 0; ++} ++ ++static int ccxmx51_devices_init(void) ++{ ++ u8 hwid[6]; ++ int pwr; ++ char manloc; ++ ++ if ((imx_iim_read(1, 9, hwid, sizeof(hwid)) != sizeof(hwid)) || (hwid[0] < 0x02) || (hwid[0] >= ARRAY_SIZE(ccxmx51_ids))) ++ memset(hwid, 0x00, sizeof(hwid)); ++ ++ ccxmx51_id = &ccxmx51_ids[hwid[0]]; ++ printf("Module Variant: %s (0x%02x)\n", ccxmx51_id->id_string, hwid[0]); ++ ++ if (hwid[0]) { ++ printf("Module HW Rev : %02x\n", hwid[1]); ++ switch (hwid[2] & 0xc0) { ++ case 0x00: ++ manloc = 'B'; ++ break; ++ case 0x40: ++ manloc = 'W'; ++ break; ++ case 0x80: ++ manloc = 'S'; ++ break; ++ default: ++ manloc = 'N'; ++ break; ++ } ++ printf("Module Serial : %c%d\n", manloc, ((hwid[2] & 0x3f) << 24) | (hwid[3] << 16) | (hwid[4] << 8) | hwid[5]); ++ if ((ccxmx51_id->mem_sz - SZ_128M) > 0) ++ arm_add_mem_device("ram1", MX51_CSD0_BASE_ADDR + SZ_128M, ccxmx51_id->mem_sz - SZ_128M); ++ } ++ ++ imx51_add_uart1(); ++ imx51_add_uart2(); ++ ++ spi_register_board_info(ccxmx51_spi_board_info, ARRAY_SIZE(ccxmx51_spi_board_info)); ++ imx51_add_spi0(&ecspi_0_data); ++ ++ pwr = ccxmx51_power_init(); ++ console_flush(); ++ imx51_init_lowlevel((ccxmx51_id->industrial || pwr) ? 600 : 800); ++ clock_notifier_call_chain(); ++ if (pwr) ++ printf("Could not setup PMIC. Clocks not adjusted.\n"); ++ ++ imx51_add_i2c1(NULL); ++ ++ imx51_add_nand(&nand_info); ++ devfs_add_partition("nand0", 0x00000, 0x80000, DEVFS_PARTITION_FIXED, "self_raw"); ++ dev_add_bb_dev("self_raw", "self0"); ++ devfs_add_partition("nand0", 0x80000, 0x40000, DEVFS_PARTITION_FIXED, "env_raw"); ++ dev_add_bb_dev("env_raw", "env0"); ++ ++#ifdef CONFIG_DRIVER_NET_FEC_IMX ++ if (ccxmx51_id->eth0 && !pwr) { ++ imx51_add_fec(&fec_info); ++ eth_register_ethaddr(0, hwid); ++ } ++#endif ++ ++#ifdef CONFIG_DRIVER_NET_SMC911X ++ if (ccxmx51_id->eth1 && !pwr) { ++ /* Configure the WEIM CS5 timming, bus width, etc */ ++ /* 16 bit on DATA[31..16], not multiplexed, async */ ++ writel(0x00420081, MX51_WEIM_BASE_ADDR + WEIM_CSxGCR1(5)); ++ /* ADH has not effect on non muxed bus */ ++ writel(0, MX51_WEIM_BASE_ADDR + WEIM_CSxGCR2(5)); ++ /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */ ++ writel(0x32260000, MX51_WEIM_BASE_ADDR + WEIM_CSxRCR1(5)); ++ /* APR=0 */ ++ writel(0, MX51_WEIM_BASE_ADDR + WEIM_CSxRCR2(5)); ++ /* WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, WEN=0, WCSA=0 */ ++ writel(0x72080f00, MX51_WEIM_BASE_ADDR + WEIM_CSxWCR1(5)); ++ ++ /* LAN9221 network controller */ ++ add_generic_device("smc911x", 1, NULL, MX51_CS5_BASE_ADDR, SZ_4K, IORESOURCE_MEM, NULL); ++ } ++#endif ++ ++ ccxmx51_otghost_init(); ++ ++ armlinux_set_bootparams((void *)(MX51_CSD0_BASE_ADDR + 0x100)); ++ ++ armlinux_set_architecture(ccxmx51_id->wless ? MACH_TYPE_CCWMX51 : MACH_TYPE_CCMX51); ++ ++ return 0; ++} ++device_initcall(ccxmx51_devices_init); ++ ++static int ccxmx51_console_init(void) ++{ ++ mxc_iomux_v3_setup_multiple_pads(ccxmx51_pads, ARRAY_SIZE(ccxmx51_pads)); ++ ++ imx51_add_uart0(); ++ ++ return 0; ++} ++console_initcall(ccxmx51_console_init); +diff --git a/arch/arm/boards/ccxmx51/ccxmx51.dox b/arch/arm/boards/ccxmx51/ccxmx51.dox +new file mode 100644 +index 0000000..cc28e8d +--- /dev/null ++++ b/arch/arm/boards/ccxmx51/ccxmx51.dox +@@ -0,0 +1,7 @@ ++/** @page ccxmx51 Digi ConnectCore board ++ ++This boards is based on a Freescale i.MX51 CPU. The board is shipped with: ++- Up to 8 GB NAND Flash. ++- Up to 512 MB DDR2 RAM. ++ ++*/ +diff --git a/arch/arm/boards/ccxmx51/ccxmx51.h b/arch/arm/boards/ccxmx51/ccxmx51.h +new file mode 100644 +index 0000000..3feacac +--- /dev/null ++++ b/arch/arm/boards/ccxmx51/ccxmx51.h +@@ -0,0 +1,35 @@ ++/* ++ * Copyright 2010 Digi International Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#ifndef _CCXMX51_H_ ++#define _CCXMX51_H_ ++ ++struct ccxmx51_hwid { ++ u8 variant; ++ u8 version; ++ u32 sn; ++ char mloc; ++}; ++ ++struct ccxmx51_ident { ++ const char *id_string; ++ const int mem_sz; ++ const char industrial; ++ const char eth0; ++ const char eth1; ++ const char wless; ++}; ++ ++extern struct ccxmx51_ident *ccxmx51_id; ++ ++#endif /* _CCXMX51_H_ */ +diff --git a/arch/arm/boards/ccxmx51/ccxmx51js.c b/arch/arm/boards/ccxmx51/ccxmx51js.c +new file mode 100644 +index 0000000..f04615d +--- /dev/null ++++ b/arch/arm/boards/ccxmx51/ccxmx51js.c +@@ -0,0 +1,90 @@ ++/* ++ * 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 <common.h> ++#include <io.h> ++#include <init.h> ++#include <mci.h> ++#include <asm/armlinux.h> ++#include <mach/imx-regs.h> ++#include <mach/iomux-mx51.h> ++#include <mach/devices-imx51.h> ++#include <generated/mach-types.h> ++ ++#include "ccxmx51.h" ++ ++static iomux_v3_cfg_t ccxmx51js_pads[] = { ++ /* SD1 */ ++ MX51_PAD_SD1_CLK__SD1_CLK, ++ MX51_PAD_SD1_CMD__SD1_CMD, ++ MX51_PAD_SD1_DATA0__SD1_DATA0, ++ MX51_PAD_SD1_DATA1__SD1_DATA1, ++ MX51_PAD_SD1_DATA2__SD1_DATA2, ++ MX51_PAD_SD1_DATA3__SD1_DATA3, ++ /* SD3 */ ++ MX51_PAD_NANDF_CS7__SD3_CLK, ++ MX51_PAD_NANDF_RDY_INT__SD3_CMD, ++ MX51_PAD_NANDF_D8__SD3_DATA0, ++ MX51_PAD_NANDF_D9__SD3_DATA1, ++ MX51_PAD_NANDF_D10__SD3_DATA2, ++ MX51_PAD_NANDF_D11__SD3_DATA3, ++ MX51_PAD_NANDF_D12__SD3_DAT4, ++ MX51_PAD_NANDF_D13__SD3_DAT5, ++ MX51_PAD_NANDF_D14__SD3_DAT6, ++ MX51_PAD_NANDF_D15__SD3_DAT7, ++ /* USB HOST1 */ ++ MX51_PAD_USBH1_CLK__USBH1_CLK, ++ MX51_PAD_USBH1_DIR__USBH1_DIR, ++ MX51_PAD_USBH1_NXT__USBH1_NXT, ++ MX51_PAD_USBH1_STP__USBH1_STP, ++ MX51_PAD_USBH1_DATA0__USBH1_DATA0, ++ MX51_PAD_USBH1_DATA1__USBH1_DATA1, ++ MX51_PAD_USBH1_DATA2__USBH1_DATA2, ++ MX51_PAD_USBH1_DATA3__USBH1_DATA3, ++ MX51_PAD_USBH1_DATA4__USBH1_DATA4, ++ MX51_PAD_USBH1_DATA5__USBH1_DATA5, ++ MX51_PAD_USBH1_DATA6__USBH1_DATA6, ++ MX51_PAD_USBH1_DATA7__USBH1_DATA7, ++}; ++ ++static struct esdhc_platform_data sdhc1_pdata = { ++ .cd_type = ESDHC_CD_NONE, ++ .wp_type = ESDHC_WP_NONE, ++ .caps = MMC_MODE_4BIT, ++}; ++ ++static struct esdhc_platform_data sdhc3_pdata = { ++ .cd_type = ESDHC_CD_NONE, ++ .wp_type = ESDHC_WP_NONE, ++ .caps = MMC_MODE_4BIT | MMC_MODE_8BIT, ++}; ++ ++static int ccxmx51js_init(void) ++{ ++ mxc_iomux_v3_setup_multiple_pads(ccxmx51js_pads, ARRAY_SIZE(ccxmx51js_pads)); ++ ++ if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC)) { ++ imx51_add_mmc0(&sdhc1_pdata); ++ imx51_add_mmc2(&sdhc3_pdata); ++ } ++ ++ armlinux_set_architecture(ccxmx51_id->wless ? MACH_TYPE_CCWMX51JS : MACH_TYPE_CCMX51JS); ++ ++ return 0; ++} ++ ++late_initcall(ccxmx51js_init); +diff --git a/arch/arm/boards/ccxmx51/config.h b/arch/arm/boards/ccxmx51/config.h +new file mode 100644 +index 0000000..fdf2f81 +--- /dev/null ++++ b/arch/arm/boards/ccxmx51/config.h +@@ -0,0 +1,24 @@ ++/** ++ * @file ++ * @brief Global defintions for the ARM i.MX51 based ccmx51 board ++ * ++ * 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 ++ ++#endif /* __CONFIG_H */ +diff --git a/arch/arm/boards/ccxmx51/env/config b/arch/arm/boards/ccxmx51/env/config +new file mode 100644 +index 0000000..bbd43e7 +--- /dev/null ++++ b/arch/arm/boards/ccxmx51/env/config +@@ -0,0 +1,37 @@ ++#!/bin/sh ++ ++machine=ccmx51 ++ ++# use 'dhcp' to do dhcp in barebox and in kernel ++# use 'none' if you want to skip kernel ip autoconfiguration ++ip=none ++ ++# or set your networking parameters here ++#eth0.ipaddr=a.b.c.d ++#eth0.netmask=a.b.c.d ++#eth0.gateway=a.b.c.d ++#eth0.serverip=a.b.c.d ++ ++# can be either 'nfs', 'tftp' or 'nand' ++kernel_loc=nand ++# can be either 'net', 'nand' or 'initrd' ++rootfs_loc=nand ++ ++# rootfs ++rootfs_type=cramfs ++ ++# kernel ++kernelimage_type=zimage ++kernel_img=/dev/nand0.kernel ++ ++autoboot_timeout=3 ++ ++bootargs="console=ttymxc0,115200" ++ ++device_type="nand" ++nand_device="mxc_nand" ++nand_parts="512k(barebox)ro,256k(bareboxenv),3328k(kernel),-(root)" ++rootfs_mtdblock_nand=3 ++ ++# set a fancy prompt (if support is compiled in) ++PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m " +diff --git a/arch/arm/boards/ccxmx51/flash_header.c b/arch/arm/boards/ccxmx51/flash_header.c +new file mode 100644 +index 0000000..c148eea +--- /dev/null ++++ b/arch/arm/boards/ccxmx51/flash_header.c +@@ -0,0 +1,84 @@ ++#include <common.h> ++#include <mach/imx-flash-header.h> ++#include <asm/barebox-arm-head.h> ++ ++void __naked __flash_header_start go(void) ++{ ++ barebox_arm_head(); ++} ++ ++struct imx_dcd_entry __dcd_entry_section dcd_entry[] = { ++ { .ptr_type = 4, .addr = 0x73fa88a0, .val = 0x00000200, }, ++ { .ptr_type = 4, .addr = 0x73fa850c, .val = 0x000020c5, }, ++ { .ptr_type = 4, .addr = 0x73fa8510, .val = 0x000020c5, }, ++ { .ptr_type = 4, .addr = 0x73fa883c, .val = 0x00000002, }, ++ { .ptr_type = 4, .addr = 0x73fa8848, .val = 0x00000002, }, ++ { .ptr_type = 4, .addr = 0x73fa84b8, .val = 0x000000e7, }, ++ { .ptr_type = 4, .addr = 0x73fa84bc, .val = 0x00000045, }, ++ { .ptr_type = 4, .addr = 0x73fa84c0, .val = 0x00000045, }, ++ { .ptr_type = 4, .addr = 0x73fa84c4, .val = 0x00000045, }, ++ { .ptr_type = 4, .addr = 0x73fa84c8, .val = 0x00000045, }, ++ { .ptr_type = 4, .addr = 0x73fa8820, .val = 0x00000000, }, ++ { .ptr_type = 4, .addr = 0x73fa84a4, .val = 0x00000003, }, ++ { .ptr_type = 4, .addr = 0x73fa84a8, .val = 0x00000003, }, ++ { .ptr_type = 4, .addr = 0x73fa84ac, .val = 0x000000e3, }, ++ { .ptr_type = 4, .addr = 0x73fa84b0, .val = 0x000000e3, }, ++ { .ptr_type = 4, .addr = 0x73fa84b4, .val = 0x000000e3, }, ++ { .ptr_type = 4, .addr = 0x73fa84cc, .val = 0x000000e3, }, ++ { .ptr_type = 4, .addr = 0x73fa84d0, .val = 0x000000e2, }, ++ { .ptr_type = 4, .addr = 0x73fa882c, .val = 0x00000004, }, ++ { .ptr_type = 4, .addr = 0x73fa88a4, .val = 0x00000004, }, ++ { .ptr_type = 4, .addr = 0x73fa88ac, .val = 0x00000004, }, ++ { .ptr_type = 4, .addr = 0x73fa88b8, .val = 0x00000004, }, ++ { .ptr_type = 4, .addr = 0x83fd9000, .val = 0x82a20000, }, ++ { .ptr_type = 4, .addr = 0x83fd9008, .val = 0x82a20000, }, ++ { .ptr_type = 4, .addr = 0x83fd9010, .val = 0x000ad0d0, }, ++ { .ptr_type = 4, .addr = 0x83fd9004, .val = 0x3f3584ab, }, ++ { .ptr_type = 4, .addr = 0x83fd900c, .val = 0x3f3584ab, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x04008008, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801a, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801b, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00448019, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x07328018, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x04008008, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008010, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008010, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x06328018, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x03808019, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00408019, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008000, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0400800c, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801e, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801f, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0000801d, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0732801c, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0400800c, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008014, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008014, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0632801c, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0380801d, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x0040801d, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00008004, }, ++ { .ptr_type = 4, .addr = 0x83fd9000, .val = 0xb2a20000, }, ++ { .ptr_type = 4, .addr = 0x83fd9008, .val = 0xb2a20000, }, ++ { .ptr_type = 4, .addr = 0x83fd9010, .val = 0x000ad6d0, }, ++ { .ptr_type = 4, .addr = 0x83fd9034, .val = 0x90000000, }, ++ { .ptr_type = 4, .addr = 0x83fd9014, .val = 0x00000000, }, ++}; ++ ++#define APP_DEST 0x90000000 ++ ++struct imx_flash_header __flash_header_section flash_header = { ++ .app_code_jump_vector = APP_DEST + 0x1000, ++ .app_code_barker = APP_CODE_BARKER, ++ .app_code_csf = 0, ++ .dcd_ptr_ptr = APP_DEST + 0x400 + offsetof(struct imx_flash_header, dcd), ++ .super_root_key = 0, ++ .dcd = APP_DEST + 0x400 + offsetof(struct imx_flash_header, dcd_barker), ++ .app_dest = APP_DEST, ++ .dcd_barker = DCD_BARKER, ++ .dcd_block_len = sizeof (dcd_entry), ++}; ++ ++unsigned long __image_len_section barebox_len = DCD_BAREBOX_SIZE; ++ +diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c +index 38f28be..b40713d 100644 +--- a/arch/arm/boards/chumby_falconwing/falconwing.c ++++ b/arch/arm/boards/chumby_falconwing/falconwing.c +@@ -316,7 +316,7 @@ static void falconwing_init_usb(void) + /* bring USB hub out of reset */ + gpio_direction_output(GPIO_USB_HUB_RESET, 1); + +- imx_usb_phy_enable(); ++ imx23_usb_phy_enable(); + + add_generic_usb_ehci_device(-1, IMX_USB_BASE, NULL); + } +diff --git a/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c b/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c +index 3cc7a72..35c114d 100644 +--- a/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c ++++ b/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c +@@ -53,6 +53,11 @@ struct imx_nand_platform_data nand_info = { + }; + + static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = { ++ /* UART1 */ ++ MX51_PAD_UART1_RXD__UART1_RXD, ++ MX51_PAD_UART1_TXD__UART1_TXD, ++ MX51_PAD_UART1_RTS__UART1_RTS, ++ MX51_PAD_UART1_CTS__UART1_CTS, + /* FEC */ + MX51_PAD_DISP2_DAT1__FEC_RX_ER, + MX51_PAD_DISP2_DAT15__FEC_TDATA0, +@@ -141,12 +146,8 @@ static int eukrea_cpuimx51_console_init(void) + + imx51_init_lowlevel(800); + +- writel(0, 0x73fa8228); +- writel(0, 0x73fa822c); +- writel(0, 0x73fa8230); +- writel(0, 0x73fa8234); +- + imx51_add_uart0(); ++ + return 0; + } + +diff --git a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c +index 9168ed8..1283e17 100644 +--- a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c ++++ b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c +@@ -22,17 +22,18 @@ + #include <init.h> + #include <mci.h> + #include <io.h> ++#include <net.h> + + #include <mach/clock.h> + #include <mach/imx-regs.h> + #include <mach/iomux-imx28.h> + #include <mach/mci.h> ++#include <mach/fb.h> ++#include <mach/ocotp.h> + + #include <asm/armlinux.h> + #include <asm/mmu.h> + +-#include <mach/fb.h> +- + #include <generated/mach-types.h> + + #define MX28EVK_FEC_PHY_RESET_GPIO 141 +@@ -118,6 +119,27 @@ static struct mxs_mci_platform_data mci_pdata = { + }; + + /* fec */ ++static void mx28_evk_get_ethaddr(void) ++{ ++ u8 mac_ocotp[3], mac[6]; ++ int ret; ++ ++ ret = mxs_ocotp_read(mac_ocotp, 3, 0); ++ if (ret != 3) { ++ pr_err("Reading MAC from OCOTP failed!\n"); ++ return; ++ } ++ ++ mac[0] = 0x00; ++ mac[1] = 0x04; ++ mac[2] = 0x9f; ++ mac[3] = mac_ocotp[2]; ++ mac[4] = mac_ocotp[1]; ++ mac[5] = mac_ocotp[0]; ++ ++ eth_register_ethaddr(0, mac); ++} ++ + static void __init mx28_evk_fec_reset(void) + { + mdelay(1); +@@ -208,6 +230,10 @@ static int mx28_evk_devices_init(void) + add_generic_device("stmfb", 0, NULL, IMX_FB_BASE, 4096, + IORESOURCE_MEM, &mx28_evk_fb_pdata); + ++ add_generic_device("ocotp", 0, NULL, IMX_OCOTP_BASE, 0, ++ IORESOURCE_MEM, NULL); ++ mx28_evk_get_ethaddr(); /* must be after registering ocotp */ ++ + imx_enable_enetclk(); + mx28_evk_fec_reset(); + add_generic_device("fec_imx", 0, NULL, IMX_FEC0_BASE, 0, +diff --git a/arch/arm/boards/freescale-mx51-pdk/board.c b/arch/arm/boards/freescale-mx51-pdk/board.c +index 0bb2ffe..3a568d0 100644 +--- a/arch/arm/boards/freescale-mx51-pdk/board.c ++++ b/arch/arm/boards/freescale-mx51-pdk/board.c +@@ -48,6 +48,12 @@ static struct fec_platform_data fec_info = { + }; + + static iomux_v3_cfg_t f3s_pads[] = { ++ /* UART1 */ ++ MX51_PAD_UART1_RXD__UART1_RXD, ++ MX51_PAD_UART1_TXD__UART1_TXD, ++ MX51_PAD_UART1_RTS__UART1_RTS, ++ MX51_PAD_UART1_CTS__UART1_CTS, ++ /* FEC */ + MX51_PAD_EIM_EB2__FEC_MDIO, + MX51_PAD_EIM_EB3__FEC_RDATA1, + MX51_PAD_EIM_CS2__FEC_RDATA2, +@@ -246,6 +252,7 @@ static int f3s_devices_init(void) + imx51_iim_register_fec_ethaddr(); + imx51_add_fec(&fec_info); + imx51_add_mmc0(NULL); ++ imx51_add_mmc1(NULL); + + armlinux_set_bootparams((void *)0x90000100); + armlinux_set_architecture(MACH_TYPE_MX51_BABBAGE); +@@ -268,12 +275,8 @@ static int f3s_console_init(void) + { + mxc_iomux_v3_setup_multiple_pads(f3s_pads, ARRAY_SIZE(f3s_pads)); + +- writel(0, 0x73fa8228); +- writel(0, 0x73fa822c); +- writel(0, 0x73fa8230); +- writel(0, 0x73fa8234); +- + imx51_add_uart0(); ++ + return 0; + } + +diff --git a/arch/arm/boards/mini2440/mini2440.c b/arch/arm/boards/mini2440/mini2440.c +index 3d3b820..3523949 100644 +--- a/arch/arm/boards/mini2440/mini2440.c ++++ b/arch/arm/boards/mini2440/mini2440.c +@@ -39,6 +39,7 @@ + #include <io.h> + #include <mach/gpio.h> + #include <mach/s3c-iomap.h> ++#include <mach/devices-s3c24xx.h> + #include <mach/s3c24xx-nand.h> + #include <mach/s3c-generic.h> + #include <mach/s3c-mci.h> +@@ -297,8 +298,7 @@ static int mini2440_devices_init(void) + reg |= 0x10000; + writel(reg, S3C_MISCCR); + +- add_generic_device("s3c24x0_nand", DEVICE_ID_DYNAMIC, NULL, S3C24X0_NAND_BASE, +- 0, IORESOURCE_MEM, &nand_info); ++ s3c24xx_add_nand(&nand_info); + + add_dm9000_device(0, S3C_CS4_BASE + 0x300, S3C_CS4_BASE + 0x304, + IORESOURCE_MEM_16BIT, &dm9000_data); +@@ -312,12 +312,9 @@ static int mini2440_devices_init(void) + devfs_add_partition("nand0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env_raw"); + dev_add_bb_dev("env_raw", "env0"); + #endif +- add_generic_device("s3c_mci", 0, NULL, S3C2410_SDI_BASE, 0, +- IORESOURCE_MEM, &mci_data); +- add_generic_device("s3c_fb", 0, NULL, S3C2410_LCD_BASE, 0, +- IORESOURCE_MEM, &s3c24x0_fb_data); +- add_generic_device("ohci", 0, NULL, S3C2410_USB_HOST_BASE, 0x100, +- IORESOURCE_MEM, NULL); ++ s3c24xx_add_mci(&mci_data); ++ s3c24xx_add_fb(&s3c24x0_fb_data); ++ s3c24xx_add_ohci(); + armlinux_set_bootparams((void*)S3C_SDRAM_BASE + 0x100); + armlinux_set_architecture(MACH_TYPE_MINI2440); + +@@ -344,8 +341,7 @@ static int mini2440_console_init(void) + s3c_gpio_mode(GPH2_TXD0); + s3c_gpio_mode(GPH3_RXD0); + +- add_generic_device("s3c_serial", DEVICE_ID_DYNAMIC, NULL, S3C_UART1_BASE, +- S3C_UART1_SIZE, IORESOURCE_MEM, NULL); ++ s3c24xx_add_uart1(); + return 0; + } + +diff --git a/arch/arm/boards/nhk8815/setup.c b/arch/arm/boards/nhk8815/setup.c +index 173892a..ccc0510 100644 +--- a/arch/arm/boards/nhk8815/setup.c ++++ b/arch/arm/boards/nhk8815/setup.c +@@ -55,15 +55,15 @@ static struct nomadik_nand_platform_data nhk8815_nand_data = { + static struct resource nhk8815_nand_resources[] = { + { + .start = NAND_IO_ADDR, +- .size = 0xfff, ++ .end = NAND_IO_ADDR + 0xfff, + .flags = IORESOURCE_MEM, + }, { + .start = NAND_IO_CMD, +- .size = 0xfff, ++ .end = NAND_IO_CMD + 0xfff, + .flags = IORESOURCE_MEM, + }, { + .start = NAND_IO_DATA, +- .size = 0xfff, ++ .end = NAND_IO_CMD + 0xfff, + .flags = IORESOURCE_MEM, + } + }; +diff --git a/arch/arm/boards/pcm038/pcm970.c b/arch/arm/boards/pcm038/pcm970.c +index ca10afb..df9b852 100644 +--- a/arch/arm/boards/pcm038/pcm970.c ++++ b/arch/arm/boards/pcm038/pcm970.c +@@ -55,7 +55,7 @@ static void pcm970_usbh2_init(void) + static struct resource pcm970_ide_resources[] = { + { + .start = IMX_PCMCIA_MEM_BASE, +- .size = SZ_1K, ++ .end = IMX_PCMCIA_MEM_BASE + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + }; +diff --git a/arch/arm/configs/at91sam9m10g45ek_defconfig b/arch/arm/configs/at91sam9m10g45ek_defconfig +index b72e964..e22f80a 100644 +--- a/arch/arm/configs/at91sam9m10g45ek_defconfig ++++ b/arch/arm/configs/at91sam9m10g45ek_defconfig +@@ -1,5 +1,4 @@ + CONFIG_ARCH_AT91SAM9G45=y +-CONFIG_MACH_AT91SAM9M10G45EK=y + CONFIG_AEABI=y + # CONFIG_CMD_ARM_CPUINFO is not set + CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +@@ -75,3 +74,4 @@ CONFIG_LED_TRIGGERS=y + CONFIG_FS_FAT=y + CONFIG_FS_FAT_WRITE=y + CONFIG_FS_FAT_LFN=y ++CONFIG_LZO_DECOMPRESS=y +diff --git a/arch/arm/configs/ccmx51_defconfig b/arch/arm/configs/ccmx51_defconfig +new file mode 100644 +index 0000000..d14de55 +--- /dev/null ++++ b/arch/arm/configs/ccmx51_defconfig +@@ -0,0 +1,55 @@ ++CONFIG_ARCH_IMX=y ++CONFIG_ARCH_IMX51=y ++CONFIG_MACH_CCMX51=y ++CONFIG_AEABI=y ++CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y ++CONFIG_MALLOC_SIZE=0x2000000 ++CONFIG_LONGHELP=y ++CONFIG_GLOB=y ++CONFIG_HUSH_FANCY_PROMPT=y ++CONFIG_CMDLINE_EDITING=y ++CONFIG_AUTO_COMPLETE=y ++CONFIG_PARTITION=y ++CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y ++CONFIG_DEFAULT_ENVIRONMENT_PATH="defaultenv arch/arm/boards/ccxmx51/env" ++CONFIG_CMD_EDIT=y ++CONFIG_CMD_SLEEP=y ++CONFIG_CMD_SAVEENV=y ++CONFIG_CMD_LOADENV=y ++CONFIG_CMD_EXPORT=y ++CONFIG_CMD_PRINTENV=y ++CONFIG_CMD_READLINE=y ++CONFIG_CMD_ECHO_E=y ++CONFIG_CMD_MEMINFO=y ++CONFIG_CMD_MTEST=y ++CONFIG_CMD_FLASH=y ++CONFIG_CMD_BOOTM_ZLIB=y ++CONFIG_CMD_BOOTM_BZLIB=y ++CONFIG_CMD_BOOTM_SHOW_TYPE=y ++CONFIG_CMD_RESET=y ++CONFIG_CMD_GO=y ++CONFIG_CMD_TIMEOUT=y ++CONFIG_CMD_PARTITION=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_UNLZO=y ++CONFIG_CMD_I2C=y ++CONFIG_NET=y ++CONFIG_NET_DHCP=y ++CONFIG_NET_PING=y ++CONFIG_NET_TFTP=y ++CONFIG_DRIVER_NET_SMC911X=y ++CONFIG_DRIVER_NET_FEC_IMX=y ++CONFIG_DRIVER_SPI_IMX=y ++CONFIG_I2C=y ++CONFIG_I2C_IMX=y ++CONFIG_MTD=y ++CONFIG_NAND=y ++CONFIG_NAND_IMX=y ++CONFIG_USB=y ++CONFIG_USB_EHCI=y ++CONFIG_MCI=y ++# CONFIG_MCI_WRITE is not set ++CONFIG_MCI_IMX_ESDHC=y ++CONFIG_FS_CRAMFS=y ++CONFIG_FS_FAT=y ++CONFIG_FS_FAT_LFN=y +diff --git a/arch/arm/configs/eukrea_cpuimx25_defconfig b/arch/arm/configs/eukrea_cpuimx25_defconfig +index 94ae670..f7207e8 100644 +--- a/arch/arm/configs/eukrea_cpuimx25_defconfig ++++ b/arch/arm/configs/eukrea_cpuimx25_defconfig +@@ -8,6 +8,7 @@ CONFIG_MMU=y + CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 + CONFIG_MALLOC_SIZE=0x800000 + CONFIG_EXPERIMENTAL=y ++CONFIG_MALLOC_TLSF=y + CONFIG_LONGHELP=y + CONFIG_GLOB=y + CONFIG_HUSH_FANCY_PROMPT=y +diff --git a/arch/arm/configs/eukrea_cpuimx35_defconfig b/arch/arm/configs/eukrea_cpuimx35_defconfig +index a888765..880beb6 100644 +--- a/arch/arm/configs/eukrea_cpuimx35_defconfig ++++ b/arch/arm/configs/eukrea_cpuimx35_defconfig +@@ -9,6 +9,7 @@ CONFIG_MMU=y + CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 + CONFIG_MALLOC_SIZE=0x800000 + CONFIG_EXPERIMENTAL=y ++CONFIG_MALLOC_TLSF=y + CONFIG_LONGHELP=y + CONFIG_GLOB=y + CONFIG_HUSH_FANCY_PROMPT=y +diff --git a/arch/arm/configs/eukrea_cpuimx51_defconfig b/arch/arm/configs/eukrea_cpuimx51_defconfig +index f6fd7bc..7261796 100644 +--- a/arch/arm/configs/eukrea_cpuimx51_defconfig ++++ b/arch/arm/configs/eukrea_cpuimx51_defconfig +@@ -7,6 +7,7 @@ CONFIG_MMU=y + CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 + CONFIG_MALLOC_SIZE=0x2000000 + CONFIG_EXPERIMENTAL=y ++CONFIG_MALLOC_TLSF=y + CONFIG_LONGHELP=y + CONFIG_GLOB=y + CONFIG_HUSH_FANCY_PROMPT=y +diff --git a/arch/arm/configs/usb_a9260_defconfig b/arch/arm/configs/usb_a9260_defconfig +index 85e7878..a9574c4 100644 +--- a/arch/arm/configs/usb_a9260_defconfig ++++ b/arch/arm/configs/usb_a9260_defconfig +@@ -6,6 +6,7 @@ CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y + CONFIG_MMU=y + CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 + CONFIG_EXPERIMENTAL=y ++CONFIG_MALLOC_TLSF=y + CONFIG_PROMPT="USB-9G20:" + CONFIG_LONGHELP=y + CONFIG_GLOB=y +diff --git a/arch/arm/configs/usb_a9263_128mib_defconfig b/arch/arm/configs/usb_a9263_128mib_defconfig +index 23bc3d7..d31057f 100644 +--- a/arch/arm/configs/usb_a9263_128mib_defconfig ++++ b/arch/arm/configs/usb_a9263_128mib_defconfig +@@ -1,12 +1,13 @@ + CONFIG_ARCH_AT91SAM9263=y + CONFIG_MACH_USB_A9263=y ++CONFIG_AT91_HAVE_SRAM_128M=y + CONFIG_AEABI=y + # CONFIG_CMD_ARM_CPUINFO is not set +-CONFIG_AT91_HAVE_SRAM_128M=y + CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y + CONFIG_MMU=y + CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 + CONFIG_EXPERIMENTAL=y ++CONFIG_MALLOC_TLSF=y + CONFIG_PROMPT="USB-9263:" + CONFIG_LONGHELP=y + CONFIG_GLOB=y +diff --git a/arch/arm/configs/usb_a9263_defconfig b/arch/arm/configs/usb_a9263_defconfig +index 96ea3e1..b57c300 100644 +--- a/arch/arm/configs/usb_a9263_defconfig ++++ b/arch/arm/configs/usb_a9263_defconfig +@@ -6,6 +6,7 @@ CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y + CONFIG_MMU=y + CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 + CONFIG_EXPERIMENTAL=y ++CONFIG_MALLOC_TLSF=y + CONFIG_PROMPT="USB-9263:" + CONFIG_LONGHELP=y + CONFIG_GLOB=y +@@ -22,7 +23,6 @@ CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env" + CONFIG_CMD_EDIT=y + CONFIG_CMD_SLEEP=y + CONFIG_CMD_SAVEENV=y +-CONFIG_CMD_LOADENV=y + CONFIG_CMD_EXPORT=y + CONFIG_CMD_PRINTENV=y + CONFIG_CMD_READLINE=y +diff --git a/arch/arm/configs/usb_a9g20_128mib_defconfig b/arch/arm/configs/usb_a9g20_128mib_defconfig +index c25d7de..6b02342 100644 +--- a/arch/arm/configs/usb_a9g20_128mib_defconfig ++++ b/arch/arm/configs/usb_a9g20_128mib_defconfig +@@ -1,12 +1,13 @@ + CONFIG_ARCH_AT91SAM9G20=y + CONFIG_MACH_USB_A9G20=y ++CONFIG_AT91_HAVE_SRAM_128M=y + CONFIG_AEABI=y + # CONFIG_CMD_ARM_CPUINFO is not set +-CONFIG_AT91_HAVE_SRAM_128M=y + CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y + CONFIG_MMU=y + CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 + CONFIG_EXPERIMENTAL=y ++CONFIG_MALLOC_TLSF=y + CONFIG_PROMPT="USB-9G20:" + CONFIG_LONGHELP=y + CONFIG_GLOB=y +diff --git a/arch/arm/configs/usb_a9g20_defconfig b/arch/arm/configs/usb_a9g20_defconfig +index d645adb..30bf380 100644 +--- a/arch/arm/configs/usb_a9g20_defconfig ++++ b/arch/arm/configs/usb_a9g20_defconfig +@@ -6,6 +6,7 @@ CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y + CONFIG_MMU=y + CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 + CONFIG_EXPERIMENTAL=y ++CONFIG_MALLOC_TLSF=y + CONFIG_PROMPT="USB-9G20:" + CONFIG_LONGHELP=y + CONFIG_GLOB=y +diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile +index e30ae1c..93a34a9 100644 +--- a/arch/arm/cpu/Makefile ++++ b/arch/arm/cpu/Makefile +@@ -7,6 +7,7 @@ obj-y += start.o + # Any variants can be called as start-armxyz.S + # + obj-$(CONFIG_CMD_ARM_CPUINFO) += cpuinfo.o ++obj-$(CONFIG_CMD_ARM_MMUINFO) += mmuinfo.o + obj-$(CONFIG_MMU) += mmu.o + obj-$(CONFIG_CPU_32v4T) += cache-armv4.o + obj-$(CONFIG_CPU_32v5) += cache-armv5.o +diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c +index c19f931..607f357 100644 +--- a/arch/arm/cpu/mmu.c ++++ b/arch/arm/cpu/mmu.c +@@ -147,7 +147,7 @@ static int arm_mmu_remap_sdram(struct memory_bank *bank) + if ((phys & (SZ_1M - 1)) || (bank->size & (SZ_1M - 1))) + return -EINVAL; + +- ptes = memalign(0x400, num_ptes * sizeof(u32)); ++ ptes = memalign(PAGE_SIZE, num_ptes * sizeof(u32)); + + debug("ptes: 0x%p ttb_start: 0x%08lx ttb_end: 0x%08lx\n", + ptes, ttb_start, ttb_end); +@@ -165,6 +165,9 @@ static int arm_mmu_remap_sdram(struct memory_bank *bank) + pte += 256; + } + ++ dma_flush_range((unsigned long)ttb, (unsigned long)ttb + 0x4000); ++ dma_flush_range((unsigned long)ptes, num_ptes * sizeof(u32)); ++ + tlb_invalidate(); + + return 0; +@@ -299,11 +302,9 @@ void *dma_alloc_coherent(size_t size) + size = PAGE_ALIGN(size); + ret = xmemalign(4096, size); + +-#ifdef CONFIG_MMU + dma_inv_range((unsigned long)ret, (unsigned long)ret + size); + + remap_range(ret, size, PTE_FLAGS_UNCACHED); +-#endif + + return ret; + } +@@ -320,9 +321,7 @@ void *phys_to_virt(unsigned long phys) + + void dma_free_coherent(void *mem, size_t size) + { +-#ifdef CONFIG_MMU + remap_range(mem, size, PTE_FLAGS_CACHED); +-#endif + + free(mem); + } +diff --git a/arch/arm/cpu/mmuinfo.c b/arch/arm/cpu/mmuinfo.c +new file mode 100644 +index 0000000..6bea34e +--- /dev/null ++++ b/arch/arm/cpu/mmuinfo.c +@@ -0,0 +1,111 @@ ++/* ++ * mmuinfo.c - Show MMU/cache information from cp15 registers ++ * ++ * Copyright (c) Jan Luebbe <j.luebbe@pengutronix.de>, Pengutronix ++ * ++ * 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 version 2 ++ * as published by the Free Software Foundation. ++ * ++ * 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 <common.h> ++#include <command.h> ++ ++static char *inner_attr[] = { ++ "0b000 Non-cacheable", ++ "0b001 Strongly-ordered", ++ "0b010 (reserved)", ++ "0b011 Device", ++ "0b100 (reserved)", ++ "0b101 Write-Back, Write-Allocate", ++ "0b110 Write-Through", ++ "0b111 Write-Back, no Write-Allocate", ++}; ++ ++static char *outer_attr[] = { ++ "0b00 Non-cacheable", ++ "0b01 Write-Back, Write-Allocate", ++ "0b10 Write-Through, no Write-Allocate", ++ "0b11 Write-Back, no Write-Allocate", ++}; ++ ++static void decode_par(unsigned long par) ++{ ++ printf(" Physical Address [31:12]: 0x%08lx\n", par & 0xFFFFF000); ++ printf(" Reserved [11]: 0x%lx\n", (par >> 11) & 0x1); ++ printf(" Not Outer Shareable [10]: 0x%lx\n", (par >> 10) & 0x1); ++ printf(" Non-Secure [9]: 0x%lx\n", (par >> 9) & 0x1); ++ printf(" Impl. def. [8]: 0x%lx\n", (par >> 8) & 0x1); ++ printf(" Shareable [7]: 0x%lx\n", (par >> 7) & 0x1); ++ printf(" Inner mem. attr. [6:4]: 0x%lx (%s)\n", (par >> 4) & 0x7, ++ inner_attr[(par >> 4) & 0x7]); ++ printf(" Outer mem. attr. [3:2]: 0x%lx (%s)\n", (par >> 2) & 0x3, ++ outer_attr[(par >> 2) & 0x3]); ++ printf(" SuperSection [1]: 0x%lx\n", (par >> 1) & 0x1); ++ printf(" Failure [0]: 0x%lx\n", (par >> 0) & 0x1); ++} ++ ++static int do_mmuinfo(int argc, char *argv[]) ++{ ++ unsigned long addr = 0, priv_read, priv_write; ++ ++ if (argc < 2) ++ return COMMAND_ERROR_USAGE; ++ ++ addr = strtoul_suffix(argv[1], NULL, 0); ++ ++ __asm__ __volatile__( ++ "mcr p15, 0, %0, c7, c8, 0 @ write VA to PA translation (priv read)\n" ++ : ++ : "r" (addr) ++ : "memory"); ++ ++ __asm__ __volatile__( ++ "mrc p15, 0, %0, c7, c4, 0 @ read PAR\n" ++ : "=r" (priv_read) ++ : ++ : "memory"); ++ ++ __asm__ __volatile__( ++ "mcr p15, 0, %0, c7, c8, 1 @ write VA to PA translation (priv write)\n" ++ : ++ : "r" (addr) ++ : "memory"); ++ ++ __asm__ __volatile__( ++ "mrc p15, 0, %0, c7, c4, 0 @ read PAR\n" ++ : "=r" (priv_write) ++ : ++ : "memory"); ++ ++ printf("PAR result for 0x%08lx: \n", addr); ++ printf(" privileged read: 0x%08lx\n", priv_read); ++ decode_par(priv_read); ++ printf(" privileged write: 0x%08lx\n", priv_write); ++ decode_par(priv_write); ++ ++ return 0; ++} ++ ++BAREBOX_CMD_HELP_START(mmuinfo) ++BAREBOX_CMD_HELP_USAGE("mmuinfo <address>\n") ++BAREBOX_CMD_HELP_SHORT("Show MMU/cache information for an address.\n") ++BAREBOX_CMD_HELP_END ++ ++BAREBOX_CMD_START(mmuinfo) ++ .cmd = do_mmuinfo, ++ .usage = "mmuinfo <address>", ++ BAREBOX_CMD_HELP(cmd_mmuinfo_help) ++BAREBOX_CMD_END +diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c +index 3c282ee..523179d 100644 +--- a/arch/arm/cpu/start.c ++++ b/arch/arm/cpu/start.c +@@ -81,13 +81,11 @@ void __naked __bare_init reset(void) + r &= ~(CR_M | CR_C | CR_B | CR_S | CR_R | CR_V); + r |= CR_I; + +- if (!(r & CR_U)) +- /* catch unaligned access on architectures which do not +- * support unaligned access */ +- r |= CR_A; +- else +- r &= ~CR_A; +- ++#if __LINUX_ARM_ARCH__ >= 6 ++ r |= CR_U; ++#else ++ r |= CR_A; ++#endif + + #ifdef __ARMEB__ + r |= CR_B; +diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h +new file mode 100644 +index 0000000..cb9cd1b +--- /dev/null ++++ b/arch/arm/include/asm/dma.h +@@ -0,0 +1,8 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#include <asm/mmu.h> +diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h +index f5ae7a8..a66da8c 100644 +--- a/arch/arm/include/asm/mmu.h ++++ b/arch/arm/include/asm/mmu.h +@@ -1,9 +1,12 @@ + #ifndef __ASM_MMU_H + #define __ASM_MMU_H + +-#include <asm/pgtable.h> +-#include <malloc.h> ++#include <common.h> + #include <errno.h> ++#include <malloc.h> ++#include <xfuncs.h> ++ ++#include <asm/pgtable.h> + + #define PMD_SECT_DEF_UNCACHED (PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT) + #define PMD_SECT_DEF_CACHED (PMD_SECT_WB | PMD_SECT_DEF_UNCACHED) +@@ -23,6 +26,12 @@ static inline void setup_dma_coherent(unsigned long offset) + { + } + ++#define dma_alloc dma_alloc ++static inline void *dma_alloc(size_t size) ++{ ++ return xmemalign(64, ALIGN(size, 64)); ++} ++ + #ifdef CONFIG_MMU + void *dma_alloc_coherent(size_t size); + void dma_free_coherent(void *mem, size_t size); +diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c +index 033e2eb..3a00437 100644 +--- a/arch/arm/lib/bootm.c ++++ b/arch/arm/lib/bootm.c +@@ -80,7 +80,7 @@ static int __do_bootm_linux(struct image_data *data, int swap) + + if (data->initrd_res) { + initrd_start = data->initrd_res->start; +- initrd_size = data->initrd_res->size; ++ initrd_size = resource_size(data->initrd_res); + } + + if (bootm_verbose(data)) { +@@ -154,7 +154,7 @@ static int do_bootz_linux_fdt(int fd, struct image_data *data) + } + } else { + +- of_res = request_sdram_region("oftree", r->start + r->size, end); ++ of_res = request_sdram_region("oftree", r->start + resource_size(r), end); + if (!of_res) { + perror("zImage: oftree request_sdram_region"); + return -ENOMEM; +@@ -310,9 +310,9 @@ static int aimage_load_resource(int fd, struct resource *r, void* buf, int ps) + { + int ret; + void *image = (void *)r->start; +- unsigned to_read = ps - r->size % ps; ++ unsigned to_read = ps - resource_size(r) % ps; + +- ret = read_full(fd, image, r->size); ++ ret = read_full(fd, image, resource_size(r)); + if (ret < 0) + return ret; + +diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c +index 3297a89..b56ca14 100644 +--- a/arch/arm/mach-at91/at91sam9260_devices.c ++++ b/arch/arm/mach-at91/at91sam9260_devices.c +@@ -111,12 +111,12 @@ void at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} + static struct resource nand_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_3, +- .size = SZ_256M, ++ .end = AT91_CHIPSELECT_3 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_ECC, +- .size = 512, ++ .end = AT91_BASE_SYS + AT91_ECC + 512 - 1, + .flags = IORESOURCE_MEM, + } + }; +diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c +index 2ebc4da..7f916d2 100644 +--- a/arch/arm/mach-at91/at91sam9263_devices.c ++++ b/arch/arm/mach-at91/at91sam9263_devices.c +@@ -113,12 +113,12 @@ void at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} + static struct resource nand_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_3, +- .size = SZ_256M, ++ .end = AT91_CHIPSELECT_3 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_ECC0, +- .size = 512, ++ .end = AT91_BASE_SYS + AT91_ECC0 + 512 - 1, + .flags = IORESOURCE_MEM, + } + }; +diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c +index d406bcc..22b455e 100644 +--- a/arch/arm/mach-at91/at91sam9g45_devices.c ++++ b/arch/arm/mach-at91/at91sam9g45_devices.c +@@ -93,12 +93,12 @@ void at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} + static struct resource nand_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_3, +- .size = SZ_256M, ++ .end = AT91_CHIPSELECT_3 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_ECC, +- .size = 512, ++ .end = AT91_BASE_SYS + AT91_ECC + 512 - 1, + .flags = IORESOURCE_MEM, + } + }; +diff --git a/arch/arm/mach-at91/at91sam9x5_devices.c b/arch/arm/mach-at91/at91sam9x5_devices.c +index 50bad7f..26a380d 100644 +--- a/arch/arm/mach-at91/at91sam9x5_devices.c ++++ b/arch/arm/mach-at91/at91sam9x5_devices.c +@@ -130,12 +130,12 @@ void at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} + static struct resource nand_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_3, +- .size = SZ_256M, ++ .end = AT91_CHIPSELECT_3 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_PMECC, +- .size = 512, ++ .end = AT91_BASE_SYS + AT91_PMECC + 512 - 1, + .flags = IORESOURCE_MEM, + } + }; +diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig +index 564e2fe..5b77245 100644 +--- a/arch/arm/mach-imx/Kconfig ++++ b/arch/arm/mach-imx/Kconfig +@@ -26,6 +26,7 @@ config ARCH_TEXT_BASE + default 0x7ff00000 if MACH_TQMA53 + default 0x97f00000 if MACH_TX51 + default 0x4fc00000 if MACH_MX6Q_ARM2 ++ default 0x97f00000 if MACH_CCMX51 + + config BOARDINFO + default "Eukrea CPUIMX25" if MACH_EUKREA_CPUIMX25 +@@ -50,6 +51,7 @@ config BOARDINFO + default "TQ tqma53" if MACH_TQMA53 + default "Ka-Ro tx51" if MACH_TX51 + default "Freescale i.MX6q armadillo2" if MACH_MX6Q_ARM2 ++ default "ConnectCore i.MX51" if MACH_CCMX51 + + choice + prompt "Select boot mode" +@@ -391,7 +393,7 @@ choice + prompt "i.MX51 Board Type" + + config MACH_FREESCALE_MX51_PDK +- select DEFAULT_ENVIRONMENT_GENERIC_NEW ++ select HAVE_DEFAULT_ENVIRONMENT_NEW + bool "Freescale i.MX51 PDK" + + config MACH_EUKREA_CPUIMX51SD +@@ -405,6 +407,23 @@ config MACH_TX51 + help + Say Y here if you are using the Ka-Ro tx51 board + ++config MACH_CCMX51 ++ bool "ConnectCore i.MX51" ++ select IMX_IIM ++ select SPI ++ select DRIVER_SPI_IMX ++ select MFD_MC13XXX ++ help ++ Say Y here if you are using Digi ConnectCore (W)i-i.MX51 ++ equipped with a Freescale i.MX51 Processor ++ ++config MACH_CCMX51_BASEBOARD ++ bool "Digi development board for CCMX51 module" ++ depends on MACH_CCMX51 ++ default y ++ help ++ This adds board specific devices that can be found on Digi ++ evaluation board for CCMX51 module. + + endchoice + +@@ -517,7 +536,7 @@ menu "i.MX specific settings " + + config IMX_CLKO + bool "clko command" +- depends on ARCH_IMX21 || ARCH_IMX27 || ARCH_IMX35 || ARCH_IMX25 ++ depends on ARCH_IMX21 || ARCH_IMX27 || ARCH_IMX35 || ARCH_IMX25 || ARCH_IMX51 + help + The i.MX SoCs have a Pin which can output different reference frequencies. + Say y here if you want to have the clko command which lets you select the +diff --git a/arch/arm/mach-imx/clko.c b/arch/arm/mach-imx/clko.c +index 0e4fbcc..aeafaa9 100644 +--- a/arch/arm/mach-imx/clko.c ++++ b/arch/arm/mach-imx/clko.c +@@ -6,15 +6,18 @@ + + static int do_clko(int argc, char *argv[]) + { +- int opt, div = 0, src = -2, ret; ++ int opt, div = 0, src = -2, num = 1, ret; + +- while((opt = getopt(argc, argv, "d:s:")) > 0) { ++ while((opt = getopt(argc, argv, "n:d:s:")) > 0) { + switch(opt) { ++ case 'n': ++ num = simple_strtoul(optarg, NULL, 0); ++ break; + case 'd': + div = simple_strtoul(optarg, NULL, 0); + break; + case 's': +- src = simple_strtoul(optarg, NULL, 0); ++ src = simple_strtol(optarg, NULL, 0); + break; + } + } +@@ -23,17 +26,19 @@ static int do_clko(int argc, char *argv[]) + return COMMAND_ERROR_USAGE; + + if (src == -1) { +- imx_clko_set_src(-1); ++ imx_clko_set_src(num, -1); + return 0; + } + + if (src != -2) +- imx_clko_set_src(src); ++ imx_clko_set_src(num, src); + + if (div != 0) { +- ret = imx_clko_set_div(div); +- if (ret != div) +- printf("limited divider to %d\n", ret); ++ ret = imx_clko_set_div(num, div); ++ if (ret < 0) ++ printf("CLKO-line %i not supported.\n", num); ++ else if (ret != div) ++ printf("Divider limited to %d.\n", ret); + } + + return 0; +@@ -42,7 +47,8 @@ static int do_clko(int argc, char *argv[]) + static __maybe_unused char cmd_clko_help[] = + "Usage: clko [OPTION]...\n" + "Route different signals to the i.MX clko pin\n" +-" -d <div> Divider\n" ++" -n <num> Number of CLKO-line (Default 1)\n" ++" -d <div> Divider\n" + " -s <source> Clock select. See Ref. Manual for valid sources. Use -1\n" + " for disabling clock output\n"; + +diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c +index 4f5895c..4e77ece 100644 +--- a/arch/arm/mach-imx/clocksource.c ++++ b/arch/arm/mach-imx/clocksource.c +@@ -38,7 +38,7 @@ + #include <io.h> + + #define GPT(x) __REG(IMX_TIM1_BASE + (x)) +-#define timer_base (IMX_TIM1_BASE) ++#define timer_base IOMEM(IMX_TIM1_BASE) + + static uint64_t imx_clocksource_read(void) + { +@@ -120,15 +120,17 @@ core_initcall(clocksource_init); + */ + void __noreturn reset_cpu (unsigned long addr) + { ++ void __iomem *wdt = IOMEM(IMX_WDT_BASE); ++ + /* Disable watchdog and set Time-Out field to 0 */ +- writew(0x0, IMX_WDT_BASE + WDOG_WCR); ++ writew(0x0, wdt + WDOG_WCR); + + /* Write Service Sequence */ +- writew(0x5555, IMX_WDT_BASE + WDOG_WSR); +- writew(0xaaaa, IMX_WDT_BASE + WDOG_WSR); ++ writew(0x5555, wdt + WDOG_WSR); ++ writew(0xaaaa, wdt + WDOG_WSR); + + /* Enable watchdog */ +- writew(WDOG_WCR_WDE, IMX_WDT_BASE + WDOG_WCR); ++ writew(WDOG_WCR_WDE, wdt + WDOG_WCR); + + while (1); + /*NOTREACHED*/ +diff --git a/arch/arm/mach-imx/iim.c b/arch/arm/mach-imx/iim.c +index f2ace8a..0da8ea0 100644 +--- a/arch/arm/mach-imx/iim.c ++++ b/arch/arm/mach-imx/iim.c +@@ -84,7 +84,7 @@ static int do_fuse_sense(void __iomem *reg_base, unsigned int bank, + } + + static ssize_t imx_iim_cdev_read(struct cdev *cdev, void *buf, size_t count, +- ulong offset, ulong flags) ++ loff_t offset, ulong flags) + { + ulong size, i; + struct iim_priv *priv = cdev->priv; +@@ -94,7 +94,7 @@ static ssize_t imx_iim_cdev_read(struct cdev *cdev, void *buf, size_t count, + if ((sense_param = dev_get_param(cdev->dev, "explicit_sense_enable"))) + explicit_sense = simple_strtoul(sense_param, NULL, 0); + +- size = min((ulong)count, priv->banksize - offset); ++ size = min((loff_t)count, priv->banksize - offset); + if (explicit_sense) { + for (i = 0; i < size; i++) { + int row_val; +@@ -176,7 +176,7 @@ out: + #endif /* CONFIG_IMX_IIM_FUSE_BLOW */ + + static ssize_t imx_iim_cdev_write(struct cdev *cdev, const void *buf, size_t count, +- ulong offset, ulong flags) ++ loff_t offset, ulong flags) + { + ulong size, i; + struct iim_priv *priv = cdev->priv; +@@ -186,7 +186,7 @@ static ssize_t imx_iim_cdev_write(struct cdev *cdev, const void *buf, size_t cou + if ((write_param = dev_get_param(cdev->dev, "permanent_write_enable"))) + blow_enable = simple_strtoul(write_param, NULL, 0); + +- size = min((ulong)count, priv->banksize - offset); ++ size = min((loff_t)count, priv->banksize - offset); + #ifdef CONFIG_IMX_IIM_FUSE_BLOW + if (blow_enable) { + for (i = 0; i < size; i++) { +diff --git a/arch/arm/mach-imx/include/mach/clock.h b/arch/arm/mach-imx/include/mach/clock.h +index 1082178..050b7f8 100644 +--- a/arch/arm/mach-imx/include/mach/clock.h ++++ b/arch/arm/mach-imx/include/mach/clock.h +@@ -30,9 +30,11 @@ ulong imx_get_lcdclk(void); + ulong imx_get_i2cclk(void); + ulong imx_get_mmcclk(void); + ulong imx_get_cspiclk(void); ++ulong imx_get_ipgclk(void); ++ulong imx_get_usbclk(void); + +-int imx_clko_set_div(int div); +-void imx_clko_set_src(int src); ++int imx_clko_set_div(int num, int div); ++void imx_clko_set_src(int num, int src); + + void imx_dump_clocks(void); + +diff --git a/arch/arm/mach-imx/include/mach/devices-imx51.h b/arch/arm/mach-imx/include/mach/devices-imx51.h +index 5de0fa7..dbf5862 100644 +--- a/arch/arm/mach-imx/include/mach/devices-imx51.h ++++ b/arch/arm/mach-imx/include/mach/devices-imx51.h +@@ -67,11 +67,11 @@ static inline struct device_d *imx51_add_nand(struct imx_nand_platform_data *pda + struct resource res[] = { + { + .start = MX51_NFC_BASE_ADDR, +- .size = SZ_4K, ++ .end = MX51_NFC_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MX51_NFC_AXI_BASE_ADDR, +- .size = SZ_4K, ++ .end = MX51_NFC_AXI_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + }; +diff --git a/arch/arm/mach-imx/include/mach/devices-imx53.h b/arch/arm/mach-imx/include/mach/devices-imx53.h +index a9fe454..0fc4b5c 100644 +--- a/arch/arm/mach-imx/include/mach/devices-imx53.h ++++ b/arch/arm/mach-imx/include/mach/devices-imx53.h +@@ -61,11 +61,11 @@ static inline struct device_d *imx53_add_nand(struct imx_nand_platform_data *pda + struct resource res[] = { + { + .start = MX53_NFC_BASE_ADDR, +- .size = SZ_4K, ++ .end = MX53_NFC_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MX53_NFC_AXI_BASE_ADDR, +- .size = SZ_4K, ++ .end = MX53_NFC_AXI_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + }; +diff --git a/arch/arm/mach-imx/include/mach/iomux-mx51.h b/arch/arm/mach-imx/include/mach/iomux-mx51.h +index c7f5169..36c8989 100644 +--- a/arch/arm/mach-imx/include/mach/iomux-mx51.h ++++ b/arch/arm/mach-imx/include/mach/iomux-mx51.h +@@ -256,13 +256,13 @@ + #define MX51_PAD_NANDF_RB1__GPIO3_9 IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_NANDF_RB1__NANDF_RB1 IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_RB1__PATA_IORDY IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL) +-#define MX51_PAD_NANDF_RB1__SD4_CMD IOMUX_PAD(0x4fc, 0x120, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL) ++#define MX51_PAD_NANDF_RB1__SD4_CMD IOMUX_PAD(0x4fc, 0x120, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL) + #define MX51_PAD_NANDF_RB2__DISP2_WAIT IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_RB2__ECSPI2_SCLK IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL) + #define MX51_PAD_NANDF_RB2__FEC_COL IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2) + #define MX51_PAD_NANDF_RB2__GPIO3_10 IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_NANDF_RB2__NANDF_RB2 IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL) +-#define MX51_PAD_NANDF_RB2__USBH3_H3_DP IOMUX_PAD(0x500, 0x124, 7, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_NANDF_RB2__USBH3_H3_DP IOMUX_PAD(0x500, 0x124, 0x17, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_RB2__USBH3_NXT IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_RB3__DISP1_WAIT IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_RB3__ECSPI2_MISO IOMUX_PAD(0x504, 0x128, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL) +@@ -270,7 +270,7 @@ + #define MX51_PAD_NANDF_RB3__GPIO3_11 IOMUX_PAD(0x504, 0x128, 3, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_NANDF_RB3__NANDF_RB3 IOMUX_PAD(0x504, 0x128, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_RB3__USBH3_CLK IOMUX_PAD(0x504, 0x128, 6, 0x9f8, 0, NO_PAD_CTRL) +-#define MX51_PAD_NANDF_RB3__USBH3_H3_DM IOMUX_PAD(0x504, 0x128, 7, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_NANDF_RB3__USBH3_H3_DM IOMUX_PAD(0x504, 0x128, 0x17, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO_NAND__GPIO_NAND IOMUX_PAD(0x514, 0x12c, 0, 0x998, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO_NAND__PATA_INTRQ IOMUX_PAD(0x514, 0x12c, 1, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_CS0__GPIO3_16 IOMUX_PAD(0x518, 0x130, 3, __NA_, 0, MX51_GPIO_PAD_CTRL) +@@ -283,13 +283,13 @@ + #define MX51_PAD_NANDF_CS2__NANDF_CS2 IOMUX_PAD(0x520, 0x138, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_CS2__PATA_CS_0 IOMUX_PAD(0x520, 0x138, 1, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_CS2__SD4_CLK IOMUX_PAD(0x520, 0x138, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS) +-#define MX51_PAD_NANDF_CS2__USBH3_H1_DP IOMUX_PAD(0x520, 0x138, 7, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_NANDF_CS2__USBH3_H1_DP IOMUX_PAD(0x520, 0x138, 0x17, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_CS3__FEC_MDC IOMUX_PAD(0x524, 0x13c, 2, __NA_, 0, MX51_PAD_CTRL_5) + #define MX51_PAD_NANDF_CS3__GPIO3_19 IOMUX_PAD(0x524, 0x13c, 3, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_NANDF_CS3__NANDF_CS3 IOMUX_PAD(0x524, 0x13c, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_CS3__PATA_CS_1 IOMUX_PAD(0x524, 0x13c, 1, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_CS3__SD4_DAT0 IOMUX_PAD(0x524, 0x13c, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL) +-#define MX51_PAD_NANDF_CS3__USBH3_H1_DM IOMUX_PAD(0x524, 0x13c, 7, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_NANDF_CS3__USBH3_H1_DM IOMUX_PAD(0x524, 0x13c, 0x17, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_NANDF_CS4__FEC_TDATA1 IOMUX_PAD(0x528, 0x140, 2, __NA_, 0, MX51_PAD_CTRL_5) + #define MX51_PAD_NANDF_CS4__GPIO3_20 IOMUX_PAD(0x528, 0x140, 3, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_NANDF_CS4__NANDF_CS4 IOMUX_PAD(0x528, 0x140, 0, __NA_, 0, NO_PAD_CTRL) +@@ -316,7 +316,7 @@ + #define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK IOMUX_PAD(0x538, 0x150, 1, 0x974, 0, MX51_PAD_CTRL_4) + #define MX51_PAD_NANDF_RDY_INT__GPIO3_24 IOMUX_PAD(0x538, 0x150, 3, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT IOMUX_PAD(0x538, 0x150, 0, 0x938, 0, NO_PAD_CTRL) +-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD IOMUX_PAD(0x538, 0x150, 5, __NA_, 0, MX51_SDHCI_PAD_CTRL) ++#define MX51_PAD_NANDF_RDY_INT__SD3_CMD IOMUX_PAD(0x538, 0x150, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL) + #define MX51_PAD_NANDF_D15__ECSPI2_MOSI IOMUX_PAD(0x53c, 0x154, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL) + #define MX51_PAD_NANDF_D15__GPIO3_25 IOMUX_PAD(0x53c, 0x154, 3, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_NANDF_D15__NANDF_D15 IOMUX_PAD(0x53c, 0x154, 0, __NA_, 0, NO_PAD_CTRL) +@@ -672,23 +672,23 @@ + #define MX51_PAD_DISP2_DAT5__DISP2_DAT5 IOMUX_PAD(0x770, 0x368, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT6__DISP2_DAT6 IOMUX_PAD(0x774, 0x36c, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT6__FEC_TDATA1 IOMUX_PAD(0x774, 0x36c, 2, __NA_, 0, MX51_PAD_CTRL_5) +-#define MX51_PAD_DISP2_DAT6__GPIO1_19 IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_DISP2_DAT6__GPIO1_19 IOMUX_PAD(0x774, 0x36c, 5, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT6__KEY_ROW4 IOMUX_PAD(0x774, 0x36c, 4, 0x9d0, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT6__USBH3_STP IOMUX_PAD(0x774, 0x36c, 3, 0xa24, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT7__DISP2_DAT7 IOMUX_PAD(0x778, 0x370, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT7__FEC_TDATA2 IOMUX_PAD(0x778, 0x370, 2, __NA_, 0, MX51_PAD_CTRL_5) +-#define MX51_PAD_DISP2_DAT7__GPIO1_29 IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_DISP2_DAT7__GPIO1_29 IOMUX_PAD(0x778, 0x370, 5, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT7__KEY_ROW5 IOMUX_PAD(0x778, 0x370, 4, 0x9d4, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT7__USBH3_NXT IOMUX_PAD(0x778, 0x370, 3, 0xa20, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT8__DISP2_DAT8 IOMUX_PAD(0x77c, 0x374, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT8__FEC_TDATA3 IOMUX_PAD(0x77c, 0x374, 2, __NA_, 0, MX51_PAD_CTRL_5) +-#define MX51_PAD_DISP2_DAT8__GPIO1_30 IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_DISP2_DAT8__GPIO1_30 IOMUX_PAD(0x77c, 0x374, 5, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT8__KEY_ROW6 IOMUX_PAD(0x77c, 0x374, 4, 0x9d8, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT8__USBH3_DATA0 IOMUX_PAD(0x77c, 0x374, 3, 0x9fc, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT9__AUD6_RXC IOMUX_PAD(0x780, 0x378, 4, 0x8f4, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT9__DISP2_DAT9 IOMUX_PAD(0x780, 0x378, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT9__FEC_TX_EN IOMUX_PAD(0x780, 0x378, 2, __NA_, 0, MX51_PAD_CTRL_5) +-#define MX51_PAD_DISP2_DAT9__GPIO1_31 IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_DISP2_DAT9__GPIO1_31 IOMUX_PAD(0x780, 0x378, 5, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT9__USBH3_DATA1 IOMUX_PAD(0x780, 0x378, 3, 0xa00, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT10__DISP2_DAT10 IOMUX_PAD(0x784, 0x37c, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT10__DISP2_SER_CS IOMUX_PAD(0x784, 0x37c, 5, __NA_, 0, NO_PAD_CTRL) +@@ -698,7 +698,7 @@ + #define MX51_PAD_DISP2_DAT11__AUD6_TXD IOMUX_PAD(0x788, 0x380, 4, 0x8f0, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT11__DISP2_DAT11 IOMUX_PAD(0x788, 0x380, 0, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT11__FEC_RX_CLK IOMUX_PAD(0x788, 0x380, 2, 0x968, 1, NO_PAD_CTRL) +-#define MX51_PAD_DISP2_DAT11__GPIO1_10 IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_DISP2_DAT11__GPIO1_10 IOMUX_PAD(0x788, 0x380, 7, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT11__USBH3_DATA3 IOMUX_PAD(0x788, 0x380, 3, 0xa08, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT12__AUD6_RXD IOMUX_PAD(0x78c, 0x384, 4, 0x8ec, 1, NO_PAD_CTRL) + #define MX51_PAD_DISP2_DAT12__DISP2_DAT12 IOMUX_PAD(0x78c, 0x384, 0, __NA_, 0, NO_PAD_CTRL) +@@ -746,16 +746,16 @@ + #define MX51_PAD_SD1_DATA3__CSPI_SS1 IOMUX_PAD(0x7b0, 0x3a8, 2, 0x920, 1, MX51_ECSPI_PAD_CTRL) + #define MX51_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x7b0, 0x3a8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL) + #define MX51_PAD_GPIO1_0__CSPI_SS2 IOMUX_PAD(0x7b4, 0x3ac, 2, 0x924, 0, MX51_ECSPI_PAD_CTRL) +-#define MX51_PAD_GPIO1_0__GPIO1_0 IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_0__GPIO1_0 IOMUX_PAD(0x7b4, 0x3ac, 1, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_0__SD1_CD IOMUX_PAD(0x7b4, 0x3ac, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL) + #define MX51_PAD_GPIO1_1__CSPI_MISO IOMUX_PAD(0x7b8, 0x3b0, 2, 0x918, 2, MX51_ECSPI_PAD_CTRL) +-#define MX51_PAD_GPIO1_1__GPIO1_1 IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_1__GPIO1_1 IOMUX_PAD(0x7b8, 0x3b0, 1, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_1__SD1_WP IOMUX_PAD(0x7b8, 0x3b0, 0, __NA_, 0, MX51_ESDHC_PAD_CTRL) + #define MX51_PAD_EIM_DA12__EIM_DA12 IOMUX_PAD(__NA_, 0x04c, 0, 0x000, 0, NO_PAD_CTRL) + #define MX51_PAD_EIM_DA13__EIM_DA13 IOMUX_PAD(__NA_, 0x050, 0, 0x000, 0, NO_PAD_CTRL) + #define MX51_PAD_EIM_DA14__EIM_DA14 IOMUX_PAD(__NA_, 0x054, 0, 0x000, 0, NO_PAD_CTRL) + #define MX51_PAD_EIM_DA15__EIM_DA15 IOMUX_PAD(__NA_, 0x058, 0, 0x000, 0, NO_PAD_CTRL) +-#define MX51_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(__NA_, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL) ++#define MX51_PAD_SD2_CMD__CSPI_MOSI IOMUX_PAD(0x7bc, 0x3b4, 2, 0x91c, 3, MX51_ECSPI_PAD_CTRL) + #define MX51_PAD_SD2_CMD__I2C1_SCL IOMUX_PAD(0x7bc, 0x3b4, 0x11, 0x9b0, 2, MX51_I2C_PAD_CTRL) + #define MX51_PAD_SD2_CMD__SD2_CMD IOMUX_PAD(0x7bc, 0x3b4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL) + #define MX51_PAD_SD2_CLK__CSPI_SCLK IOMUX_PAD(0x7c0, 0x3b8, 2, 0x914, 3, MX51_ECSPI_PAD_CTRL) +@@ -766,19 +766,19 @@ + #define MX51_PAD_SD2_DATA0__SD2_DATA0 IOMUX_PAD(0x7c4, 0x3bc, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL) + #define MX51_PAD_SD2_DATA1__SD1_DAT5 IOMUX_PAD(0x7c8, 0x3c0, 1, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_SD2_DATA1__SD2_DATA1 IOMUX_PAD(0x7c8, 0x3c0, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL) +-#define MX51_PAD_SD2_DATA1__USBH3_H2_DP IOMUX_PAD(0x7c8, 0x3c0, 2, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_SD2_DATA1__USBH3_H2_DP IOMUX_PAD(0x7c8, 0x3c0, 0x12, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_SD2_DATA2__SD1_DAT6 IOMUX_PAD(0x7cc, 0x3c4, 1, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_SD2_DATA2__SD2_DATA2 IOMUX_PAD(0x7cc, 0x3c4, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL) +-#define MX51_PAD_SD2_DATA2__USBH3_H2_DM IOMUX_PAD(0x7cc, 0x3c4, 2, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_SD2_DATA2__USBH3_H2_DM IOMUX_PAD(0x7cc, 0x3c4, 0x12, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_SD2_DATA3__CSPI_SS2 IOMUX_PAD(0x7d0, 0x3c8, 2, 0x924, 1, MX51_ECSPI_PAD_CTRL) + #define MX51_PAD_SD2_DATA3__SD1_DAT7 IOMUX_PAD(0x7d0, 0x3c8, 1, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_SD2_DATA3__SD2_DATA3 IOMUX_PAD(0x7d0, 0x3c8, 0x10, __NA_, 0, MX51_SDHCI_PAD_CTRL) + #define MX51_PAD_GPIO1_2__CCM_OUT_2 IOMUX_PAD(0x7d4, 0x3cc, 5, __NA_, 0, NO_PAD_CTRL) +-#define MX51_PAD_GPIO1_2__GPIO1_2 IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_2__GPIO1_2 IOMUX_PAD(0x7d4, 0x3cc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_2__I2C2_SCL IOMUX_PAD(0x7d4, 0x3cc, 0x12, 0x9b8, 3, MX51_I2C_PAD_CTRL) + #define MX51_PAD_GPIO1_2__PLL1_BYP IOMUX_PAD(0x7d4, 0x3cc, 7, 0x90c, 1, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_2__PWM1_PWMO IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL) +-#define MX51_PAD_GPIO1_3__GPIO1_3 IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_3__GPIO1_3 IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_3__I2C2_SDA IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL) + #define MX51_PAD_GPIO1_3__PLL2_BYP IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_3__PWM2_PWMO IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL) +@@ -786,27 +786,27 @@ + #define MX51_PAD_PMIC_INT_REQ__PMIC_PMU_IRQ_B IOMUX_PAD(0x7fc, 0x3d4, 1, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_4__DISP2_EXT_CLK IOMUX_PAD(0x804, 0x3d8, 4, 0x908, 1, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_4__EIM_RDY IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL) +-#define MX51_PAD_GPIO1_4__GPIO1_4 IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_4__GPIO1_4 IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_4__WDOG1_WDOG_B IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_5__CSI2_MCLK IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_5__DISP2_PIN16 IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL) +-#define MX51_PAD_GPIO1_5__GPIO1_5 IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_5__GPIO1_5 IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_5__WDOG2_WDOG_B IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_6__DISP2_PIN17 IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL) +-#define MX51_PAD_GPIO1_6__GPIO1_6 IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_6__GPIO1_6 IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_6__REF_EN_B IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_7__CCM_OUT_0 IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL) +-#define MX51_PAD_GPIO1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_7__GPIO1_7 IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_7__SD2_WP IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL) + #define MX51_PAD_GPIO1_7__SPDIF_OUT1 IOMUX_PAD(0x810, 0x3e4, 2, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_8__CSI2_DATA_EN IOMUX_PAD(0x814, 0x3e8, 2, 0x99c, 2, NO_PAD_CTRL) +-#define MX51_PAD_GPIO1_8__GPIO1_8 IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_8__GPIO1_8 IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_8__SD2_CD IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL) + #define MX51_PAD_GPIO1_8__USBH3_PWR IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_9__CCM_OUT_1 IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_9__DISP2_D1_CS IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_9__DISP2_SER_CS IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL) +-#define MX51_PAD_GPIO1_9__GPIO1_9 IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, NO_PAD_CTRL) ++#define MX51_PAD_GPIO1_9__GPIO1_9 IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, MX51_GPIO_PAD_CTRL) + #define MX51_PAD_GPIO1_9__SD2_LCTL IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL) + #define MX51_PAD_GPIO1_9__USBH3_OC IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL) + +diff --git a/arch/arm/mach-imx/speed-imx21.c b/arch/arm/mach-imx/speed-imx21.c +index 6ab1dca..4729583 100644 +--- a/arch/arm/mach-imx/speed-imx21.c ++++ b/arch/arm/mach-imx/speed-imx21.c +@@ -16,6 +16,7 @@ + */ + + #include <common.h> ++#include <asm-generic/errno.h> + #include <mach/imx-regs.h> + #include <mach/generic.h> + #include <mach/clock.h> +@@ -162,9 +163,13 @@ void imx_dump_clocks(void) + * Returns the new divider (which may be smaller + * than the desired one) + */ +-int imx_clko_set_div(int div) ++int imx_clko_set_div(int num, int div) + { + ulong pcdr; ++ ++ if (num != 1) ++ return -ENODEV; ++ + div--; + div &= 0x7; + +@@ -178,11 +183,11 @@ int imx_clko_set_div(int div) + /* + * Set the clock source for the CLKO pin + */ +-void imx_clko_set_src(int src) ++void imx_clko_set_src(int num, int src) + { + unsigned long ccsr; + +- if (src < 0) { ++ if (src < 0 || num != 1) { + return; + } + +diff --git a/arch/arm/mach-imx/speed-imx25.c b/arch/arm/mach-imx/speed-imx25.c +index f6dcacb..ed14113 100644 +--- a/arch/arm/mach-imx/speed-imx25.c ++++ b/arch/arm/mach-imx/speed-imx25.c +@@ -1,4 +1,5 @@ + #include <common.h> ++#include <asm-generic/errno.h> + #include <mach/imx-regs.h> + #include <io.h> + #include <mach/clock.h> +@@ -111,10 +112,13 @@ void imx_dump_clocks(void) + * the new divider (which may be smaller + * than the desired one) + */ +-int imx_clko_set_div(int div) ++int imx_clko_set_div(int num, int div) + { + unsigned long mcr = readl(IMX_CCM_BASE + 0x64); + ++ if (num != 1) ++ return -ENODEV; ++ + div -= 1; + div &= 0x3f; + +@@ -129,10 +133,13 @@ int imx_clko_set_div(int div) + /* + * Set the clock source for the CLKO pin + */ +-void imx_clko_set_src(int src) ++void imx_clko_set_src(int num, int src) + { + unsigned long mcr = readl(IMX_CCM_BASE + 0x64); + ++ if (num != 1) ++ return; ++ + if (src < 0) { + mcr &= ~(1 << 30); + writel(mcr, IMX_CCM_BASE + 0x64); +diff --git a/arch/arm/mach-imx/speed-imx27.c b/arch/arm/mach-imx/speed-imx27.c +index aba5097..644fd04 100644 +--- a/arch/arm/mach-imx/speed-imx27.c ++++ b/arch/arm/mach-imx/speed-imx27.c +@@ -16,6 +16,7 @@ + */ + + #include <common.h> ++#include <asm-generic/errno.h> + #include <mach/imx-regs.h> + #include <mach/generic.h> + #include <mach/clock.h> +@@ -189,9 +190,13 @@ void imx_dump_clocks(void) + * the new divider (which may be smaller + * than the desired one) + */ +-int imx_clko_set_div(int div) ++int imx_clko_set_div(int num, int div) + { + ulong pcdr; ++ ++ if (num != 1) ++ return -ENODEV; ++ + div--; + div &= 0x7; + +@@ -205,10 +210,13 @@ int imx_clko_set_div(int div) + /* + * Set the clock source for the CLKO pin + */ +-void imx_clko_set_src(int src) ++void imx_clko_set_src(int num, int src) + { + unsigned long ccsr; + ++ if (num != 1) ++ return; ++ + if (src < 0) { + PCDR0 &= ~(1 << 25); + return; +diff --git a/arch/arm/mach-imx/speed-imx35.c b/arch/arm/mach-imx/speed-imx35.c +index 1e1c39f..684dc14 100644 +--- a/arch/arm/mach-imx/speed-imx35.c ++++ b/arch/arm/mach-imx/speed-imx35.c +@@ -16,6 +16,7 @@ + */ + + #include <common.h> ++#include <asm-generic/errno.h> + #include <mach/imx-regs.h> + #include <io.h> + #include <mach/clock.h> +@@ -84,7 +85,7 @@ unsigned long imx_get_ahbclk(void) + return fref / aad->ahb; + } + +-static unsigned long imx_get_ipgclk(void) ++unsigned long imx_get_ipgclk(void) + { + ulong clk = imx_get_ahbclk(); + +@@ -203,10 +204,13 @@ void imx_dump_clocks(void) + * the new divider (which may be smaller + * than the desired one) + */ +-int imx_clko_set_div(int div) ++int imx_clko_set_div(int num, int div) + { + unsigned long cosr = readl(IMX_CCM_BASE + CCM_COSR); + ++ if (num != 1) ++ return -ENODEV; ++ + div -= 1; + div &= 0x3f; + +@@ -221,10 +225,13 @@ int imx_clko_set_div(int div) + /* + * Set the clock source for the CLKO pin + */ +-void imx_clko_set_src(int src) ++void imx_clko_set_src(int num, int src) + { + unsigned long cosr = readl(IMX_CCM_BASE + CCM_COSR); + ++ if (num != 1) ++ return; ++ + if (src < 0) { + cosr &= ~(1 << 5); + writel(cosr, IMX_CCM_BASE + CCM_COSR); +diff --git a/arch/arm/mach-imx/speed-imx51.c b/arch/arm/mach-imx/speed-imx51.c +index 8d1ecf3..87fbc75 100644 +--- a/arch/arm/mach-imx/speed-imx51.c ++++ b/arch/arm/mach-imx/speed-imx51.c +@@ -1,12 +1,19 @@ + #include <common.h> + #include <io.h> + #include <asm-generic/div64.h> ++#include <asm-generic/errno.h> + #include <mach/imx51-regs.h> ++#include <mach/clock.h> + #include <mach/clock-imx51_53.h> + + static u32 ccm_readl(u32 ofs) + { +- return readl(MX51_CCM_BASE_ADDR + ofs); ++ return readl(IOMEM(MX51_CCM_BASE_ADDR) + ofs); ++} ++ ++static void ccm_writel(u32 val, u32 ofs) ++{ ++ writel(val, MX51_CCM_BASE_ADDR + ofs); + } + + static unsigned long ckil_get_rate(void) +@@ -142,7 +149,7 @@ unsigned long imx_get_uartclk(void) + return parent_rate / (prediv * podf); + } + +-static unsigned long imx_get_ahbclk(void) ++unsigned long imx_get_ahbclk(void) + { + u32 reg, div; + +@@ -221,6 +228,70 @@ unsigned long imx_get_usbclk(void) + return rate / (prediv * podf); + } + ++/* ++ * Set the divider of the CLKO pin. Returns ++ * the new divider (which may be smaller ++ * than the desired one) ++ */ ++int imx_clko_set_div(int num, int div) ++{ ++ u32 ccosr = ccm_readl(MX5_CCM_CCOSR); ++ ++ div--; ++ ++ switch (num) { ++ case 1: ++ div &= 0x7; ++ ccosr &= ~(0x7 << 4); ++ ccosr |= div << 4; ++ ccm_writel(ccosr, MX5_CCM_CCOSR); ++ break; ++ case 2: ++ div &= 0x7; ++ ccosr &= ~(0x7 << 21); ++ ccosr |= div << 21; ++ ccm_writel(ccosr, MX5_CCM_CCOSR); ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ return div + 1; ++} ++ ++/* ++ * Set the clock source for the CLKO pin ++ */ ++void imx_clko_set_src(int num, int src) ++{ ++ u32 ccosr = ccm_readl(MX5_CCM_CCOSR); ++ ++ switch (num) { ++ case 1: ++ if (src < 0) { ++ ccosr &= ~(1 << 7); ++ break; ++ } ++ ccosr &= ~0xf; ++ ccosr |= src & 0xf; ++ ccosr |= 1 << 7; ++ break; ++ case 2: ++ if (src < 0) { ++ ccosr &= ~(1 << 24); ++ break; ++ } ++ ccosr &= ~(0x1f << 16); ++ ccosr |= (src & 0x1f) << 16; ++ ccosr |= 1 << 24; ++ break; ++ default: ++ return; ++ } ++ ++ ccm_writel(ccosr, MX5_CCM_CCOSR); ++} ++ + void imx_dump_clocks(void) + { + printf("pll1: %ld\n", pll1_main_get_rate()); +diff --git a/arch/arm/mach-imx/speed-imx53.c b/arch/arm/mach-imx/speed-imx53.c +index 634341e..653dae3 100644 +--- a/arch/arm/mach-imx/speed-imx53.c ++++ b/arch/arm/mach-imx/speed-imx53.c +@@ -2,6 +2,7 @@ + #include <io.h> + #include <asm-generic/div64.h> + #include <mach/imx-regs.h> ++#include <mach/clock.h> + #include "mach/clock-imx51_53.h" + + static u32 ccm_readl(u32 ofs) +@@ -139,7 +140,7 @@ unsigned long imx_get_uartclk(void) + return parent_rate / (prediv * podf); + } + +-static unsigned long imx_get_ahbclk(void) ++unsigned long imx_get_ahbclk(void) + { + u32 reg, div; + +diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig +index 3348a3c..746c986 100644 +--- a/arch/arm/mach-mxs/Kconfig ++++ b/arch/arm/mach-mxs/Kconfig +@@ -61,6 +61,7 @@ config MACH_TX28 + + config MACH_MX28EVK + bool "mx28-evk" ++ select MXS_OCOTP + help + Say Y here if you are using the Freescale i.MX28-EVK board + +@@ -80,6 +81,25 @@ config MXS_OCOTP + internal view). Don't use register offsets here, the SET, CLR and + TGL registers are not mapped! + ++config MXS_OCOTP_WRITABLE ++ bool "OCOTP write support" ++ depends on MXS_OCOTP ++ help ++ Enable this option to add writing to OCOTP. ++ Warning: blown bits can not be unblown. Use with care. ++ ++ Before being actually able to blow the bits, you need to explicitely ++ enable writing: ++ ocotp0.permanent_write_enable=1 ++ ++config MXS_CMD_BCB ++ depends on NAND_MXS ++ tristate "Nand bcb command" ++ help ++ To be able to boot from NAND the i.MX23/28 need a Boot Control Block ++ in flash. This option enabled the 'bcb' command which can be used to ++ generate this block during runtime. ++ + endmenu + + menu "Board specific settings " +diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile +index 172d928..fe93096 100644 +--- a/arch/arm/mach-mxs/Makefile ++++ b/arch/arm/mach-mxs/Makefile +@@ -1,5 +1,6 @@ +-obj-y += imx.o iomux-imx.o reset-imx.o ++obj-y += imx.o iomux-imx.o power.o common.o + obj-$(CONFIG_DRIVER_VIDEO_STM) += imx_lcd_clk.o +-obj-$(CONFIG_ARCH_IMX23) += speed-imx23.o clocksource-imx23.o usb.o +-obj-$(CONFIG_ARCH_IMX28) += speed-imx28.o clocksource-imx28.o ++obj-$(CONFIG_ARCH_IMX23) += speed-imx23.o clocksource-imx23.o usb-imx23.o soc-imx23.o ++obj-$(CONFIG_ARCH_IMX28) += speed-imx28.o clocksource-imx28.o usb-imx28.o soc-imx28.o + obj-$(CONFIG_MXS_OCOTP) += ocotp.o ++obj-$(CONFIG_MXS_CMD_BCB) += bcb.o +diff --git a/arch/arm/mach-mxs/bcb.c b/arch/arm/mach-mxs/bcb.c +new file mode 100644 +index 0000000..d0a3ddc +--- /dev/null ++++ b/arch/arm/mach-mxs/bcb.c +@@ -0,0 +1,399 @@ ++/* ++ * (C) Copyright 2011 Wolfram Sang, Pengutronix e.K. ++ * ++ * 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. ++ * ++ * Based on a similar function in Karo Electronics TX28-U-Boot (flash.c). ++ * Probably written by Lothar WaĂźmann (like tx28.c). ++ */ ++ ++#include <common.h> ++#include <command.h> ++#include <environment.h> ++#include <malloc.h> ++#include <nand.h> ++#include <sizes.h> ++#include <errno.h> ++#include <io.h> ++ ++#include <mach/imx-regs.h> ++ ++#include <linux/err.h> ++#include <linux/mtd/nand.h> ++ ++#define FCB_START_BLOCK 0 ++#define NUM_FCB_BLOCKS 1 ++#define MAX_FCB_BLOCKS 32768 ++ ++#define GPMI_TIMING0 0x00000070 ++#define GPMI_TIMING0_ADDRESS_SETUP_MASK (0xff << 16) ++#define GPMI_TIMING0_ADDRESS_SETUP_OFFSET 16 ++#define GPMI_TIMING0_DATA_HOLD_MASK (0xff << 8) ++#define GPMI_TIMING0_DATA_HOLD_OFFSET 8 ++#define GPMI_TIMING0_DATA_SETUP_MASK 0xff ++#define GPMI_TIMING0_DATA_SETUP_OFFSET 0 ++ ++#define GPMI_TIMING1 0x00000080 ++ ++#define BCH_MODE 0x00000020 ++ ++#define BCH_FLASH0LAYOUT0 0x00000080 ++#define BCH_FLASHLAYOUT0_NBLOCKS_MASK (0xff << 24) ++#define BCH_FLASHLAYOUT0_NBLOCKS_OFFSET 24 ++#define BCH_FLASHLAYOUT0_META_SIZE_MASK (0xff << 16) ++#define BCH_FLASHLAYOUT0_META_SIZE_OFFSET 16 ++#define BCH_FLASHLAYOUT0_ECC0_MASK (0xf << 12) ++#define BCH_FLASHLAYOUT0_ECC0_OFFSET 12 ++#define BCH_FLASHLAYOUT0_DATA0_SIZE_MASK 0xfff ++#define BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET 0 ++ ++#define BCH_FLASH0LAYOUT1 0x00000090 ++#define BCH_FLASHLAYOUT1_PAGE_SIZE_MASK (0xffff << 16) ++#define BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET 16 ++#define BCH_FLASHLAYOUT1_ECCN_MASK (0xf << 12) ++#define BCH_FLASHLAYOUT1_ECCN_OFFSET 12 ++#define BCH_FLASHLAYOUT1_DATAN_SIZE_MASK 0xfff ++#define BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET 0 ++ ++struct mx28_nand_timing { ++ u8 data_setup; ++ u8 data_hold; ++ u8 address_setup; ++ u8 dsample_time; ++ u8 nand_timing_state; ++ u8 tREA; ++ u8 tRLOH; ++ u8 tRHOH; ++}; ++ ++struct mx28_fcb { ++ u32 checksum; ++ u32 fingerprint; ++ u32 version; ++ struct mx28_nand_timing timing; ++ u32 page_data_size; ++ u32 total_page_size; ++ u32 sectors_per_block; ++ u32 number_of_nands; /* not used by ROM code */ ++ u32 total_internal_die; /* not used by ROM code */ ++ u32 cell_type; /* not used by ROM code */ ++ u32 ecc_blockn_type; ++ u32 ecc_block0_size; ++ u32 ecc_blockn_size; ++ u32 ecc_block0_type; ++ u32 metadata_size; ++ u32 ecc_blocks_per_page; ++ u32 rsrvd[6]; /* not used by ROM code */ ++ u32 bch_mode; ++ u32 boot_patch; ++ u32 patch_sectors; ++ u32 fw1_start_page; ++ u32 fw2_start_page; ++ u32 fw1_sectors; ++ u32 fw2_sectors; ++ u32 dbbt_search_area; ++ u32 bb_mark_byte; ++ u32 bb_mark_startbit; ++ u32 bb_mark_phys_offset; ++}; ++ ++struct mx28_dbbt_header { ++ u32 checksum; ++ u32 fingerprint; ++ u32 version; ++ u32 number_bb; ++ u32 number_pages; ++ u8 spare[492]; ++}; ++ ++struct mx28_dbbt { ++ u32 nand_number; ++ u32 number_bb; ++ u32 bb_num[2040 / 4]; ++}; ++ ++#define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET) ++#define GETBIT(v,n) (((v) >> (n)) & 0x1) ++ ++static u8 calculate_parity_13_8(u8 d) ++{ ++ u8 p = 0; ++ ++ p |= (GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 3) ^ GETBIT(d, 2)) << 0; ++ p |= (GETBIT(d, 7) ^ GETBIT(d, 5) ^ GETBIT(d, 4) ^ GETBIT(d, 2) ^ GETBIT(d, 1)) << 1; ++ p |= (GETBIT(d, 7) ^ GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 1) ^ GETBIT(d, 0)) << 2; ++ p |= (GETBIT(d, 7) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 0)) << 3; ++ p |= (GETBIT(d, 6) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 2) ^ GETBIT(d, 1) ^ GETBIT(d, 0)) << 4; ++ return p; ++} ++ ++static void encode_hamming_13_8(void *_src, void *_ecc, size_t size) ++{ ++ int i; ++ u8 *src = _src; ++ u8 *ecc = _ecc; ++ ++ for (i = 0; i < size; i++) ++ ecc[i] = calculate_parity_13_8(src[i]); ++} ++ ++static u32 calc_chksum(void *buf, size_t size) ++{ ++ u32 chksum = 0; ++ u8 *bp = buf; ++ size_t i; ++ ++ for (i = 0; i < size; i++) ++ chksum += bp[i]; ++ ++ return ~chksum; ++} ++ ++/* ++ Physical organisation of data in NAND flash: ++ metadata ++ payload chunk 0 (may be empty) ++ ecc for metadata + payload chunk 0 ++ payload chunk 1 ++ ecc for payload chunk 1 ++... ++ payload chunk n ++ ecc for payload chunk n ++ */ ++ ++static int calc_bb_offset(struct mtd_info *mtd, struct mx28_fcb *fcb) ++{ ++ int bb_mark_offset; ++ int chunk_data_size = fcb->ecc_blockn_size * 8; ++ int chunk_ecc_size = (fcb->ecc_blockn_type << 1) * 13; ++ int chunk_total_size = chunk_data_size + chunk_ecc_size; ++ int bb_mark_chunk, bb_mark_chunk_offs; ++ ++ bb_mark_offset = (mtd->writesize - fcb->metadata_size) * 8; ++ if (fcb->ecc_block0_size == 0) ++ bb_mark_offset -= (fcb->ecc_block0_type << 1) * 13; ++ ++ bb_mark_chunk = bb_mark_offset / chunk_total_size; ++ bb_mark_chunk_offs = bb_mark_offset - (bb_mark_chunk * chunk_total_size); ++ if (bb_mark_chunk_offs > chunk_data_size) { ++ printf("Unsupported ECC layout; BB mark resides in ECC data: %u\n", ++ bb_mark_chunk_offs); ++ return -EINVAL; ++ } ++ bb_mark_offset -= bb_mark_chunk * chunk_ecc_size; ++ return bb_mark_offset; ++} ++ ++static struct mx28_fcb *create_fcb(struct mtd_info *mtd, void *buf, unsigned fw1_start_block, ++ size_t fw_size, unsigned fw2_start_block) ++{ ++ u32 fl0, fl1, t0; ++ int metadata_size; ++ int bb_mark_bit_offs; ++ struct mx28_fcb *fcb; ++ int fcb_offs; ++ void __iomem *bch_regs = (void *)MXS_BCH_BASE; ++ void __iomem *gpmi_regs = (void *)MXS_GPMI_BASE; ++ ++ fl0 = readl(bch_regs + BCH_FLASH0LAYOUT0); ++ fl1 = readl(bch_regs + BCH_FLASH0LAYOUT1); ++ t0 = readl(gpmi_regs + GPMI_TIMING0); ++ metadata_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE); ++ ++ fcb = buf + ALIGN(metadata_size, 4); ++ fcb_offs = (void *)fcb - buf; ++ ++ memset(buf, 0x00, fcb_offs); ++ memset(fcb, 0x00, sizeof(*fcb)); ++ memset(fcb + 1, 0xff, mtd->erasesize - fcb_offs - sizeof(*fcb)); ++ ++ strncpy((char *)&fcb->fingerprint, "FCB ", 4); ++ fcb->version = cpu_to_be32(1); ++ ++ fcb->timing.data_setup = BF_VAL(t0, GPMI_TIMING0_DATA_SETUP); ++ fcb->timing.data_hold = BF_VAL(t0, GPMI_TIMING0_DATA_HOLD); ++ fcb->timing.address_setup = BF_VAL(t0, GPMI_TIMING0_ADDRESS_SETUP); ++ ++ fcb->page_data_size = mtd->writesize; ++ fcb->total_page_size = mtd->writesize + mtd->oobsize; ++ fcb->sectors_per_block = mtd->erasesize / mtd->writesize; ++ ++ fcb->ecc_block0_type = BF_VAL(fl0, BCH_FLASHLAYOUT0_ECC0); ++ fcb->ecc_block0_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_DATA0_SIZE); ++ fcb->ecc_blockn_type = BF_VAL(fl1, BCH_FLASHLAYOUT1_ECCN); ++ fcb->ecc_blockn_size = BF_VAL(fl1, BCH_FLASHLAYOUT1_DATAN_SIZE); ++ ++ fcb->metadata_size = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE); ++ fcb->ecc_blocks_per_page = BF_VAL(fl0, BCH_FLASHLAYOUT0_NBLOCKS); ++ fcb->bch_mode = readl(bch_regs + BCH_MODE); ++/* ++ fcb->boot_patch = 0; ++ fcb->patch_sectors = 0; ++*/ ++ fcb->fw1_start_page = fw1_start_block / mtd->writesize; ++ fcb->fw1_sectors = DIV_ROUND_UP(fw_size, mtd->writesize); ++ ++ if (fw2_start_block != 0 && fw2_start_block < mtd->size / mtd->erasesize) { ++ fcb->fw2_start_page = fw2_start_block / mtd->writesize; ++ fcb->fw2_sectors = fcb->fw1_sectors; ++ } ++ ++ fcb->dbbt_search_area = 1; ++ ++ bb_mark_bit_offs = calc_bb_offset(mtd, fcb); ++ if (bb_mark_bit_offs < 0) ++ return ERR_PTR(bb_mark_bit_offs); ++ fcb->bb_mark_byte = bb_mark_bit_offs / 8; ++ fcb->bb_mark_startbit = bb_mark_bit_offs % 8; ++ fcb->bb_mark_phys_offset = mtd->writesize; ++ ++ fcb->checksum = calc_chksum(&fcb->fingerprint, 512 - 4); ++ return fcb; ++} ++ ++static int find_fcb(struct mtd_info *mtd, void *ref, int page) ++{ ++ int ret = 0; ++ struct nand_chip *chip = mtd->priv; ++ void *buf = malloc(mtd->erasesize); ++ ++ if (buf == NULL) ++ return -ENOMEM; ++ ++ chip->select_chip(mtd, 0); ++ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); ++ ret = chip->ecc.read_page_raw(mtd, chip, buf); ++ if (ret) { ++ printf("Failed to read FCB from page %u: %d\n", page, ret); ++ return ret; ++ } ++ chip->select_chip(mtd, -1); ++ if (memcmp(buf, ref, mtd->writesize) == 0) { ++ printf("%s: Found FCB in page %u (%08x)\n", __func__, ++ page, page * mtd->writesize); ++ ret = 1; ++ } ++ free(buf); ++ return ret; ++} ++ ++static int write_fcb(struct mtd_info *mtd, void *buf, int block) ++{ ++ int ret; ++ struct nand_chip *chip = mtd->priv; ++ int page = block / mtd->writesize; ++ struct erase_info erase_opts = { ++ .mtd = mtd, ++ .addr = block, ++ .len = mtd->erasesize, ++ .callback = NULL, ++ }; ++ ++ ret = find_fcb(mtd, buf, page); ++ if (ret > 0) { ++ printf("FCB at block %08x is up to date\n", block); ++ return 0; ++ } ++ ++ ret = mtd->erase(mtd, &erase_opts); ++ if (ret) { ++ printf("Failed to erase FCB block %08x\n", block); ++ return ret; ++ } ++ ++ printf("Writing FCB to block %08x\n", block); ++ chip->select_chip(mtd, 0); ++ ret = chip->write_page(mtd, chip, buf, page, 0, 1); ++ if (ret) { ++ printf("Failed to write FCB to block %08x: %d\n", block, ret); ++ } ++ chip->select_chip(mtd, -1); ++ return ret; ++} ++ ++int update_bcb(int argc, char *argv[]) ++{ ++ int ret; ++ int block; ++ void *buf; ++ struct mx28_fcb *fcb; ++ struct cdev *tmp_cdev, *bcb_cdev, *firmware_cdev; ++ unsigned long fw2_offset = 0; ++ struct mtd_info *mtd; ++ unsigned fcb_written = 0; ++ ++ if (argc == 1) ++ return COMMAND_ERROR_USAGE; ++ ++ tmp_cdev = cdev_by_name("nand0"); ++ if (!tmp_cdev || !tmp_cdev->mtd) { ++ pr_err("%s: No NAND device!\n", __func__); ++ return -ENODEV; ++ } ++ ++ mtd = tmp_cdev->mtd; ++ ++ bcb_cdev = cdev_by_name("nand0.bcb"); ++ if (!bcb_cdev) { ++ pr_err("%s: No FCB device!\n", __func__); ++ return -ENODEV; ++ } ++ ++ firmware_cdev = cdev_by_name(argv[1]); ++ if (!firmware_cdev) { ++ pr_err("%s: Bootstream-Image not found!\n", __func__); ++ return -ENODEV; ++ } ++ ++ if (argc > 2) { ++ tmp_cdev = cdev_by_name(argv[2]); ++ if (!tmp_cdev) { ++ pr_err("%s: Redundant Bootstream-Image not found!\n", __func__); ++ return -ENODEV; ++ } ++ fw2_offset = tmp_cdev->offset; ++ } ++ ++ buf = malloc(mtd->erasesize); ++ if (!buf) ++ return -ENOMEM; ++ ++ fcb = create_fcb(mtd, buf, firmware_cdev->offset, firmware_cdev->size, fw2_offset); ++ if (IS_ERR(fcb)) { ++ printf("Failed to initialize FCB: %ld\n", PTR_ERR(fcb)); ++ return PTR_ERR(fcb); ++ } ++ encode_hamming_13_8(fcb, (void *)fcb + 512, 512); ++ ++ for (block = bcb_cdev->offset; block < bcb_cdev->offset + bcb_cdev->size / 2; ++ block += mtd->erasesize) { ++ ++ if (nand_isbad_bbt(mtd, block, false)) ++ continue; ++ ++ ret = write_fcb(mtd, buf, block); ++ if (ret) { ++ printf("Failed to write FCB to block %u\n", block); ++ return ret; ++ } ++ ++ fcb_written++; ++ } ++ ++ return fcb_written ? 0 : -ENOSPC; ++} ++ ++BAREBOX_CMD_HELP_START(bcb) ++BAREBOX_CMD_HELP_USAGE("bcb <first_bootstream> [second_bootstream]\n") ++BAREBOX_CMD_HELP_SHORT("Write a BCB to NAND flash which an MX23/28 needs to boot.\n") ++BAREBOX_CMD_HELP_TEXT ("Example: bcb nand0.bootstream\n") ++BAREBOX_CMD_HELP_END ++ ++BAREBOX_CMD_START(bcb) ++ .cmd = update_bcb, ++ .usage = "Writes a MX23/28 BCB data structure to flash", ++ BAREBOX_CMD_HELP(cmd_bcb_help) ++BAREBOX_CMD_END +diff --git a/arch/arm/mach-mxs/common.c b/arch/arm/mach-mxs/common.c +new file mode 100644 +index 0000000..3730633 +--- /dev/null ++++ b/arch/arm/mach-mxs/common.c +@@ -0,0 +1,33 @@ ++#include <common.h> ++#include <io.h> ++#include <mach/mxs.h> ++#include <mach/imx-regs.h> ++ ++#define MXS_BLOCK_SFTRST (1 << 31) ++#define MXS_BLOCK_CLKGATE (1 << 30) ++ ++int mxs_reset_block(void __iomem *reg, int just_enable) ++{ ++ /* Clear SFTRST */ ++ writel(MXS_BLOCK_SFTRST, reg + BIT_CLR); ++ mdelay(1); ++ ++ /* Clear CLKGATE */ ++ writel(MXS_BLOCK_CLKGATE, reg + BIT_CLR); ++ ++ if (!just_enable) { ++ /* Set SFTRST */ ++ writel(MXS_BLOCK_SFTRST, reg + BIT_SET); ++ mdelay(1); ++ } ++ ++ /* Clear SFTRST */ ++ writel(MXS_BLOCK_SFTRST, reg + BIT_CLR); ++ mdelay(1); ++ ++ /* Clear CLKGATE */ ++ writel(MXS_BLOCK_CLKGATE, reg + BIT_CLR); ++ mdelay(1); ++ ++ return 0; ++} +diff --git a/arch/arm/mach-mxs/include/mach/clock-imx23.h b/arch/arm/mach-mxs/include/mach/clock-imx23.h +index 723f343..6507792 100644 +--- a/arch/arm/mach-mxs/include/mach/clock-imx23.h ++++ b/arch/arm/mach-mxs/include/mach/clock-imx23.h +@@ -18,11 +18,13 @@ unsigned imx_get_emiclk(void); + unsigned imx_get_ioclk(void); + unsigned imx_get_armclk(void); + unsigned imx_get_hclk(void); ++unsigned imx_set_hclk(unsigned); + unsigned imx_get_xclk(void); + unsigned imx_get_sspclk(unsigned); + unsigned imx_set_sspclk(unsigned, unsigned, int); + unsigned imx_set_ioclk(unsigned); + unsigned imx_set_lcdifclk(unsigned); + unsigned imx_get_lcdifclk(void); ++void imx_enable_nandclk(void); + + #endif /* MACH_CLOCK_IMX23_H */ +diff --git a/arch/arm/mach-mxs/include/mach/clock-imx28.h b/arch/arm/mach-mxs/include/mach/clock-imx28.h +index 45fb043..0604f0a 100644 +--- a/arch/arm/mach-mxs/include/mach/clock-imx28.h ++++ b/arch/arm/mach-mxs/include/mach/clock-imx28.h +@@ -18,6 +18,7 @@ unsigned imx_get_emiclk(void); + unsigned imx_get_ioclk(unsigned); + unsigned imx_get_armclk(void); + unsigned imx_get_hclk(void); ++unsigned imx_set_hclk(unsigned); + unsigned imx_get_xclk(void); + unsigned imx_get_sspclk(unsigned); + unsigned imx_set_sspclk(unsigned, unsigned, int); +@@ -26,6 +27,7 @@ unsigned imx_set_lcdifclk(unsigned); + unsigned imx_get_lcdifclk(void); + unsigned imx_get_fecclk(void); + void imx_enable_enetclk(void); ++void imx_enable_nandclk(void); + + #endif /* MACH_CLOCK_IMX28_H */ + +diff --git a/arch/arm/mach-mxs/include/mach/dma.h b/arch/arm/mach-mxs/include/mach/dma.h +new file mode 100644 +index 0000000..52747e2 +--- /dev/null ++++ b/arch/arm/mach-mxs/include/mach/dma.h +@@ -0,0 +1,145 @@ ++/* ++ * Freescale i.MX28 APBH DMA ++ * ++ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> ++ * on behalf of DENX Software Engineering GmbH ++ * ++ * Based on code from LTIB: ++ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. ++ * ++ * 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 __DMA_H__ ++#define __DMA_H__ ++ ++#include <linux/list.h> ++ ++#ifndef CONFIG_ARCH_DMA_PIO_WORDS ++#define DMA_PIO_WORDS 15 ++#else ++#define DMA_PIO_WORDS CONFIG_ARCH_DMA_PIO_WORDS ++#endif ++ ++#define MXS_DMA_ALIGNMENT 32 ++ ++/* ++ * MXS DMA channels ++ */ ++enum { ++ MXS_DMA_CHANNEL_AHB_APBH_SSP0 = 0, ++ MXS_DMA_CHANNEL_AHB_APBH_SSP1, ++ MXS_DMA_CHANNEL_AHB_APBH_SSP2, ++ MXS_DMA_CHANNEL_AHB_APBH_SSP3, ++ MXS_DMA_CHANNEL_AHB_APBH_GPMI0, ++ MXS_DMA_CHANNEL_AHB_APBH_GPMI1, ++ MXS_DMA_CHANNEL_AHB_APBH_GPMI2, ++ MXS_DMA_CHANNEL_AHB_APBH_GPMI3, ++ MXS_DMA_CHANNEL_AHB_APBH_GPMI4, ++ MXS_DMA_CHANNEL_AHB_APBH_GPMI5, ++ MXS_DMA_CHANNEL_AHB_APBH_GPMI6, ++ MXS_DMA_CHANNEL_AHB_APBH_GPMI7, ++ MXS_DMA_CHANNEL_AHB_APBH_SSP, ++ MXS_MAX_DMA_CHANNELS, ++}; ++ ++/* ++ * MXS DMA hardware command. ++ * ++ * This structure describes the in-memory layout of an entire DMA command, ++ * including space for the maximum number of PIO accesses. See the appropriate ++ * reference manual for a detailed description of what these fields mean to the ++ * DMA hardware. ++ */ ++#define MXS_DMA_DESC_COMMAND_MASK 0x3 ++#define MXS_DMA_DESC_COMMAND_OFFSET 0 ++#define MXS_DMA_DESC_COMMAND_NO_DMAXFER 0x0 ++#define MXS_DMA_DESC_COMMAND_DMA_WRITE 0x1 ++#define MXS_DMA_DESC_COMMAND_DMA_READ 0x2 ++#define MXS_DMA_DESC_COMMAND_DMA_SENSE 0x3 ++#define MXS_DMA_DESC_CHAIN (1 << 2) ++#define MXS_DMA_DESC_IRQ (1 << 3) ++#define MXS_DMA_DESC_NAND_LOCK (1 << 4) ++#define MXS_DMA_DESC_NAND_WAIT_4_READY (1 << 5) ++#define MXS_DMA_DESC_DEC_SEM (1 << 6) ++#define MXS_DMA_DESC_WAIT4END (1 << 7) ++#define MXS_DMA_DESC_HALT_ON_TERMINATE (1 << 8) ++#define MXS_DMA_DESC_TERMINATE_FLUSH (1 << 9) ++#define MXS_DMA_DESC_PIO_WORDS_MASK (0xf << 12) ++#define MXS_DMA_DESC_PIO_WORDS_OFFSET 12 ++#define MXS_DMA_DESC_BYTES_MASK (0xffff << 16) ++#define MXS_DMA_DESC_BYTES_OFFSET 16 ++ ++struct mxs_dma_cmd { ++ unsigned long next; ++ unsigned long data; ++ union { ++ dma_addr_t address; ++ unsigned long alternate; ++ }; ++ unsigned long pio_words[DMA_PIO_WORDS]; ++}; ++ ++/* ++ * MXS DMA command descriptor. ++ * ++ * This structure incorporates an MXS DMA hardware command structure, along ++ * with metadata. ++ */ ++#define MXS_DMA_DESC_FIRST (1 << 0) ++#define MXS_DMA_DESC_LAST (1 << 1) ++#define MXS_DMA_DESC_READY (1 << 31) ++ ++struct mxs_dma_desc { ++ struct mxs_dma_cmd cmd; ++ unsigned int flags; ++ dma_addr_t address; ++ void *buffer; ++ struct list_head node; ++}; ++ ++/** ++ * MXS DMA channel ++ * ++ * This structure represents a single DMA channel. The MXS platform code ++ * maintains an array of these structures to represent every DMA channel in the ++ * system (see mxs_dma_channels). ++ */ ++#define MXS_DMA_FLAGS_IDLE 0 ++#define MXS_DMA_FLAGS_BUSY (1 << 0) ++#define MXS_DMA_FLAGS_FREE 0 ++#define MXS_DMA_FLAGS_ALLOCATED (1 << 16) ++#define MXS_DMA_FLAGS_VALID (1 << 31) ++ ++struct mxs_dma_chan { ++ const char *name; ++ unsigned long dev; ++ struct mxs_dma_device *dma; ++ unsigned int flags; ++ unsigned int active_num; ++ unsigned int pending_num; ++ struct list_head active; ++ struct list_head done; ++}; ++ ++struct mxs_dma_desc *mxs_dma_desc_alloc(void); ++void mxs_dma_desc_free(struct mxs_dma_desc *); ++int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc); ++ ++int mxs_dma_go(int chan); ++int mxs_dma_init(void); ++ ++#endif /* __DMA_H__ */ +diff --git a/arch/arm/mach-mxs/include/mach/imx23-regs.h b/arch/arm/mach-mxs/include/mach/imx23-regs.h +index 60f5bf9..7ea3057 100644 +--- a/arch/arm/mach-mxs/include/mach/imx23-regs.h ++++ b/arch/arm/mach-mxs/include/mach/imx23-regs.h +@@ -27,6 +27,9 @@ + #endif + + #define IMX_MEMORY_BASE 0x40000000 ++#define MXS_APBH_BASE 0x80004000 ++#define MXS_BCH_BASE 0x8000a000 ++#define MXS_GPMI_BASE 0x8000c000 + #define IMX_UART1_BASE 0x8006c000 + #define IMX_UART2_BASE 0x8006e000 + #define IMX_DBGUART_BASE 0x80070000 +diff --git a/arch/arm/mach-mxs/include/mach/imx28-regs.h b/arch/arm/mach-mxs/include/mach/imx28-regs.h +index 9a2052c..16bf5f7 100644 +--- a/arch/arm/mach-mxs/include/mach/imx28-regs.h ++++ b/arch/arm/mach-mxs/include/mach/imx28-regs.h +@@ -23,15 +23,19 @@ + #define IMX_SRAM_BASE 0x00000000 + #define IMX_MEMORY_BASE 0x40000000 + +-#define IMX_NFC_BASE 0x8000C000 ++#define MXS_APBH_BASE 0x80004000 ++#define MXS_BCH_BASE 0x8000a000 ++#define MXS_GPMI_BASE 0x8000c000 + #define IMX_SSP0_BASE 0x80010000 + #define IMX_SSP1_BASE 0x80012000 + #define IMX_SSP2_BASE 0x80014000 + #define IMX_SSP3_BASE 0x80016000 + #define IMX_IOMUXC_BASE 0x80018000 ++#define IMX_DIGCTL_BASE 0x8001c000 + #define IMX_OCOTP_BASE 0x8002c000 + #define IMX_FB_BASE 0x80030000 + #define IMX_CCM_BASE 0x80040000 ++#define IMX_POWER_BASE 0x80044000 + #define IMX_WDT_BASE 0x80056000 + #define IMX_I2C0_BASE 0x80058000 + #define IMX_I2C1_BASE 0x8005a000 +@@ -42,6 +46,9 @@ + #define IMX_UART3_BASE 0x80070000 + #define IMX_UART4_BASE 0x80072000 + #define IMX_DBGUART_BASE 0x80074000 ++#define IMX_USBPHY0_BASE 0x8007c000 ++#define IMX_USBPHY1_BASE 0x8007e000 ++#define IMX_USB_BASE 0x80080000 + #define IMX_FEC0_BASE 0x800F0000 + #define IMX_FEC1_BASE 0x800F4000 + +diff --git a/arch/arm/mach-mxs/include/mach/mxs.h b/arch/arm/mach-mxs/include/mach/mxs.h +new file mode 100644 +index 0000000..182ed8a +--- /dev/null ++++ b/arch/arm/mach-mxs/include/mach/mxs.h +@@ -0,0 +1,6 @@ ++#ifndef __MACH_MXS_H ++#define __MACH_MXS_H ++ ++int mxs_reset_block(void __iomem *reg, int just_enable); ++ ++#endif /* __MACH_MXS_H */ +diff --git a/arch/arm/mach-mxs/include/mach/power.h b/arch/arm/mach-mxs/include/mach/power.h +new file mode 100644 +index 0000000..f429b3c +--- /dev/null ++++ b/arch/arm/mach-mxs/include/mach/power.h +@@ -0,0 +1,8 @@ ++#ifndef __MACH_POWER_H ++#define __MACH_POWER_H ++ ++void imx_power_prepare_usbphy(void); ++int imx_get_vddio(void); ++int imx_set_vddio(int); ++ ++#endif /* __MACH_POWER_H */ +diff --git a/arch/arm/mach-mxs/include/mach/usb.h b/arch/arm/mach-mxs/include/mach/usb.h +index af7d885..2d31b0d 100644 +--- a/arch/arm/mach-mxs/include/mach/usb.h ++++ b/arch/arm/mach-mxs/include/mach/usb.h +@@ -1,6 +1,9 @@ + #ifndef __MACH_USB_H + #define __MACH_USB_H + +-int imx_usb_phy_enable(void); ++int imx23_usb_phy_enable(void); ++ ++int imx28_usb_phy0_enable(void); ++int imx28_usb_phy1_enable(void); + + #endif /* __MACH_USB_H */ +diff --git a/arch/arm/mach-mxs/iomux-imx.c b/arch/arm/mach-mxs/iomux-imx.c +index 6bcde03..a3ecb94 100644 +--- a/arch/arm/mach-mxs/iomux-imx.c ++++ b/arch/arm/mach-mxs/iomux-imx.c +@@ -131,7 +131,7 @@ void imx_gpio_mode(uint32_t m) + if (BK_PRESENT(m)) { + reg_offset = calc_pullup_reg(gpio_pin); + writel(0x1 << (gpio_pin % 32), IMX_IOMUXC_BASE + reg_offset + +- (GET_BITKEEPER(m) == 1 ? BIT_SET : BIT_CLR)); ++ (GET_BITKEEPER(m) == 1 ? BIT_CLR : BIT_SET)); + } + + if (GET_FUNC(m) == IS_GPIO) { +diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c +index 38f9ffd..7824402 100644 +--- a/arch/arm/mach-mxs/ocotp.c ++++ b/arch/arm/mach-mxs/ocotp.c +@@ -25,27 +25,45 @@ + #include <mach/generic.h> + #include <mach/ocotp.h> + #include <mach/imx-regs.h> ++#include <mach/clock-imx28.h> ++#include <mach/power.h> + + #define DRIVERNAME "ocotp" + +-#define OCOTP_WORD_OFFSET 0x20 ++#define OCOTP_CTRL 0x0 ++# define OCOTP_CTRL_ADDR_MASK 0x3f ++# define OCOTP_CTRL_BUSY (1 << 8) ++# define OCOTP_CTRL_ERROR (1 << 9) ++# define OCOTP_CTRL_RD_BANK_OPEN (1 << 12) ++# define OCOTP_CTRL_WR_UNLOCK 0x3e770000 ++ ++#define OCOTP_DATA 0x10 + +-#define BM_OCOTP_CTRL_BUSY (1 << 8) +-#define BM_OCOTP_CTRL_ERROR (1 << 9) +-#define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12) ++#define OCOTP_WORD_OFFSET 0x20 + + struct ocotp_priv { + struct cdev cdev; + void __iomem *base; + }; + ++static int mxs_ocotp_wait_busy(struct ocotp_priv *priv) ++{ ++ uint64_t start = get_time_ns(); ++ ++ /* check both BUSY and ERROR cleared */ ++ while (readl(priv->base + OCOTP_CTRL) & (OCOTP_CTRL_BUSY | OCOTP_CTRL_ERROR)) ++ if (is_timeout(start, MSECOND)) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ + static ssize_t mxs_ocotp_cdev_read(struct cdev *cdev, void *buf, size_t count, +- ulong offset, ulong flags) ++ loff_t offset, ulong flags) + { + struct ocotp_priv *priv = cdev->priv; + void __iomem *base = priv->base; +- size_t size = min((ulong)count, cdev->size - offset); +- uint64_t start; ++ size_t size = min((loff_t)count, cdev->size - offset); + int i; + + /* +@@ -54,25 +72,20 @@ static ssize_t mxs_ocotp_cdev_read(struct cdev *cdev, void *buf, size_t count, + */ + + /* try to clear ERROR bit */ +- writel(BM_OCOTP_CTRL_ERROR, base + BIT_CLR); ++ writel(OCOTP_CTRL_ERROR, base + OCOTP_CTRL + BIT_CLR); + +- /* check both BUSY and ERROR cleared */ +- start = get_time_ns(); +- while (readl(base) & (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) +- if (is_timeout(start, MSECOND)) +- return -ETIMEDOUT; ++ if (mxs_ocotp_wait_busy(priv)) ++ return -ETIMEDOUT; + + /* open OCOTP banks for read */ +- writel(BM_OCOTP_CTRL_RD_BANK_OPEN, base + BIT_SET); ++ writel(OCOTP_CTRL_RD_BANK_OPEN, base + OCOTP_CTRL + BIT_SET); + + /* approximately wait 32 hclk cycles */ + udelay(1); + + /* poll BUSY bit becoming cleared */ +- start = get_time_ns(); +- while (readl(base) & BM_OCOTP_CTRL_BUSY) +- if (is_timeout(start, MSECOND)) +- return -ETIMEDOUT; ++ if (mxs_ocotp_wait_busy(priv)) ++ return -ETIMEDOUT; + + for (i = 0; i < size; i++) + /* When reading bytewise, we need to hop over the SET/CLR/TGL regs */ +@@ -80,16 +93,107 @@ static ssize_t mxs_ocotp_cdev_read(struct cdev *cdev, void *buf, size_t count, + (((i + offset) & 0xfc) << 2) + ((i + offset) & 3)); + + /* close banks for power saving */ +- writel(BM_OCOTP_CTRL_RD_BANK_OPEN, base + BIT_CLR); ++ writel(OCOTP_CTRL_RD_BANK_OPEN, base + OCOTP_CTRL + BIT_CLR); + + return size; + } + ++static ssize_t mxs_ocotp_cdev_write(struct cdev *cdev, const void *buf, size_t count, ++ loff_t offset, ulong flags) ++{ ++ struct ocotp_priv *priv = cdev->priv; ++ void __iomem *base = priv->base; ++ const char *write_param; ++ unsigned int write_enabled = 0; ++ unsigned long old_hclk, aligned_offset; ++ int old_vddio, num_words, num_bytes, i, ret = 0; ++ u8 *work_buf; ++ u32 reg; ++ ++ write_param = dev_get_param(cdev->dev, "permanent_write_enable"); ++ if (write_param) ++ write_enabled = simple_strtoul(write_param, NULL, 0); ++ ++ if (!write_param || !write_enabled) ++ return -EPERM; ++ ++ /* we can only work on u32, so calc some helpers */ ++ aligned_offset = offset & ~3UL; ++ num_words = DIV_ROUND_UP(offset - aligned_offset + count, 4); ++ num_bytes = num_words << 2; ++ ++ /* read in all words which will be modified */ ++ work_buf = xmalloc(num_bytes); ++ ++ i = mxs_ocotp_cdev_read(cdev, work_buf, num_bytes, aligned_offset, 0); ++ if (i != num_bytes) { ++ ret = -ENXIO; ++ goto free_mem; ++ } ++ ++ /* modify read words with to be written data */ ++ for (i = 0; i < count; i++) ++ work_buf[offset - aligned_offset + i] |= ((u8 *)buf)[i]; ++ ++ /* prepare system for OTP write */ ++ old_hclk = imx_get_hclk(); ++ old_vddio = imx_get_vddio(); ++ ++ imx_set_hclk(24000000); ++ imx_set_vddio(2800000); ++ ++ writel(OCOTP_CTRL_RD_BANK_OPEN, base + OCOTP_CTRL + BIT_CLR); ++ ++ if (mxs_ocotp_wait_busy(priv)) { ++ ret = -ETIMEDOUT; ++ goto restore_system; ++ } ++ ++ /* write word for word via data register */ ++ for (i = 0; i < num_words; i++) { ++ reg = readl(base + OCOTP_CTRL) & ~OCOTP_CTRL_ADDR_MASK; ++ reg |= OCOTP_CTRL_WR_UNLOCK | ((aligned_offset >> 2) + i); ++ writel(reg, base + OCOTP_CTRL); ++ ++ writel(((u32 *)work_buf)[i], base + OCOTP_DATA); ++ ++ if (mxs_ocotp_wait_busy(priv)) { ++ ret = -ETIMEDOUT; ++ goto restore_system; ++ } ++ ++ mdelay(2); ++ } ++ ++restore_system: ++ imx_set_vddio(old_vddio); ++ imx_set_hclk(old_hclk); ++free_mem: ++ free(work_buf); ++ ++ return ret; ++} ++ + static struct file_operations mxs_ocotp_ops = { + .read = mxs_ocotp_cdev_read, + .lseek = dev_lseek_default, + }; + ++static int mxs_ocotp_write_enable_set(struct device_d *dev, struct param_d *param, ++ const char *val) ++{ ++ unsigned long write_enable; ++ ++ if (!val) ++ return -EINVAL; ++ ++ write_enable = simple_strtoul(val, NULL, 0); ++ if (write_enable > 1) ++ return -EINVAL; ++ ++ return dev_param_set_generic(dev, param, write_enable ? "1" : "0"); ++} ++ + static int mxs_ocotp_probe(struct device_d *dev) + { + int err; +@@ -106,6 +210,18 @@ static int mxs_ocotp_probe(struct device_d *dev) + if (err < 0) + return err; + ++ if (IS_ENABLED(CONFIG_MXS_OCOTP_WRITABLE)) { ++ mxs_ocotp_ops.write = mxs_ocotp_cdev_write; ++ ++ err = dev_add_param(dev, "permanent_write_enable", ++ mxs_ocotp_write_enable_set, NULL, 0); ++ if (err < 0) ++ return err; ++ err = dev_set_param(dev, "permanent_write_enable", "0"); ++ if (err < 0) ++ return err; ++ } ++ + return 0; + } + +diff --git a/arch/arm/mach-mxs/power.c b/arch/arm/mach-mxs/power.c +new file mode 100644 +index 0000000..f4d0b9e +--- /dev/null ++++ b/arch/arm/mach-mxs/power.c +@@ -0,0 +1,84 @@ ++/* ++ * i.MX28 power related functions ++ * ++ * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> ++ * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang@pengutronix.de> ++ * ++ * 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. ++ */ ++#include <common.h> ++#include <io.h> ++#include <errno.h> ++#include <mach/imx-regs.h> ++ ++#define POWER_CTRL (IMX_POWER_BASE + 0x0) ++#define POWER_CTRL_CLKGATE 0x40000000 ++ ++#define POWER_VDDIOCTRL (IMX_POWER_BASE + 0x60) ++ ++#define POWER_STS (IMX_POWER_BASE + 0xc0) ++#define POWER_STS_VBUSVALID 0x00000002 ++#define POWER_STS_BVALID 0x00000004 ++#define POWER_STS_AVALID 0x00000008 ++ ++#define POWER_DEBUG (IMX_POWER_BASE + 0x110) ++#define POWER_DEBUG_BVALIDPIOLOCK 0x00000002 ++#define POWER_DEBUG_AVALIDPIOLOCK 0x00000004 ++#define POWER_DEBUG_VBUSVALIDPIOLOCK 0x00000008 ++ ++#define TRG_MASK 0x1f ++ ++int imx_get_vddio(void) ++{ ++ u32 val; ++ ++ val = readl(POWER_VDDIOCTRL) & TRG_MASK; ++ if (val > 0x10) ++ val = 0x10; ++ ++ return 2800000 + val * 50000; ++} ++ ++int imx_set_vddio(int new_voltage_uV) ++{ ++ u32 reg, val; ++ ++ if (new_voltage_uV < 2800000 || new_voltage_uV > 3600000) ++ return -EINVAL; ++ ++ val = (new_voltage_uV - 2800000) / 50000; ++ reg = readl(POWER_VDDIOCTRL) & ~TRG_MASK; ++ writel(reg | val, POWER_VDDIOCTRL); ++ ++ /* ++ * Wait for power to become stable. We just wait, because DC_OK can ++ * only detect rising voltages for DCDC. For all other cases, bootlets ++ * also do simple waiting, although horribly nested. We just take the ++ * maximum value of all cases from the bootlets and then add some. ++ */ ++ mdelay(30); ++ ++ return 2800000 + val * 50000; ++} ++ ++void imx_power_prepare_usbphy(void) ++{ ++ u32 reg; ++ ++ /* ++ * Set these bits so that we can force the OTG bits high ++ * so the ARC core operates properly ++ */ ++ writel(POWER_CTRL_CLKGATE, POWER_CTRL + BIT_CLR); ++ ++ writel(POWER_DEBUG_VBUSVALIDPIOLOCK | ++ POWER_DEBUG_AVALIDPIOLOCK | ++ POWER_DEBUG_BVALIDPIOLOCK, POWER_DEBUG + BIT_SET); ++ ++ reg = readl(POWER_STS); ++ reg |= POWER_STS_BVALID | POWER_STS_AVALID | POWER_STS_VBUSVALID; ++ writel(reg, POWER_STS); ++} +diff --git a/arch/arm/mach-mxs/reset-imx.c b/arch/arm/mach-mxs/reset-imx.c +deleted file mode 100644 +index cfb3548..0000000 +--- a/arch/arm/mach-mxs/reset-imx.c ++++ /dev/null +@@ -1,61 +0,0 @@ +-/* +- * (C) Copyright 2010 Juergen Beisert - Pengutronix +- * +- * 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 <common.h> +-#include <init.h> +-#include <notifier.h> +-#include <mach/imx-regs.h> +-#include <io.h> +- +-#define HW_RTC_CTRL 0x000 +-# define BM_RTC_CTRL_WATCHDOGEN (1 << 4) +-#define HW_RTC_CTRL_SET 0x004 +-#define HW_RTC_CTRL_CLR 0x008 +-#define HW_RTC_CTRL_TOG 0x00C +- +-#define HW_RTC_WATCHDOG 0x050 +-#define HW_RTC_WATCHDOG_SET 0x054 +-#define HW_RTC_WATCHDOG_CLR 0x058 +-#define HW_RTC_WATCHDOG_TOG 0x05C +- +-#define WDOG_COUNTER_RATE 1000 /* 1 kHz clock */ +- +-#define HW_RTC_PERSISTENT1 0x070 +-# define BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER 0x80000000 +-#define HW_RTC_PERSISTENT1_SET 0x074 +-#define HW_RTC_PERSISTENT1_CLR 0x078 +-#define HW_RTC_PERSISTENT1_TOG 0x07C +- +-/* +- * Reset the cpu by setting up the watchdog timer and let it time out +- * +- * TODO There is a much easier way to reset the CPU: Refer bit 2 in +- * the HW_CLKCTRL_RESET register, data sheet page 106/4-30 +- */ +-void __noreturn reset_cpu (unsigned long addr) +-{ +- writel(WDOG_COUNTER_RATE, IMX_WDT_BASE + HW_RTC_WATCHDOG); +- writel(BM_RTC_CTRL_WATCHDOGEN, IMX_WDT_BASE + HW_RTC_CTRL_SET); +- writel(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, IMX_WDT_BASE + HW_RTC_PERSISTENT1); +- +- while (1) +- ; +- /*NOTREACHED*/ +-} +-EXPORT_SYMBOL(reset_cpu); +diff --git a/arch/arm/mach-mxs/soc-imx23.c b/arch/arm/mach-mxs/soc-imx23.c +new file mode 100644 +index 0000000..6819b3c +--- /dev/null ++++ b/arch/arm/mach-mxs/soc-imx23.c +@@ -0,0 +1,37 @@ ++/* ++ * (c) 2012 Juergen Beisert <kernel@pengutronix.de> ++ * ++ * 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. ++ * ++ * Collection of some SoC specific functions ++ */ ++ ++#include <common.h> ++#include <init.h> ++#include <mach/imx-regs.h> ++#include <io.h> ++ ++#define HW_CLKCTRL_RESET 0x120 ++# define HW_CLKCTRL_RESET_CHIP (1 << 1) ++ ++/* Reset the full i.MX23 SoC via a chipset feature */ ++void __noreturn reset_cpu(unsigned long addr) ++{ ++ u32 reg; ++ ++ reg = readl(IMX_CCM_BASE + HW_CLKCTRL_RESET); ++ writel(reg | HW_CLKCTRL_RESET_CHIP, IMX_CCM_BASE + HW_CLKCTRL_RESET); ++ ++ while (1) ++ ; ++ /*NOTREACHED*/ ++} ++EXPORT_SYMBOL(reset_cpu); +diff --git a/arch/arm/mach-mxs/soc-imx28.c b/arch/arm/mach-mxs/soc-imx28.c +new file mode 100644 +index 0000000..a181b75 +--- /dev/null ++++ b/arch/arm/mach-mxs/soc-imx28.c +@@ -0,0 +1,37 @@ ++/* ++ * (c) 2012 Juergen Beisert <kernel@pengutronix.de> ++ * ++ * 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. ++ * ++ * Collection of some SoC specific functions ++ */ ++ ++#include <common.h> ++#include <init.h> ++#include <mach/imx-regs.h> ++#include <io.h> ++ ++#define HW_CLKCTRL_RESET 0x1e0 ++# define HW_CLKCTRL_RESET_CHIP (1 << 1) ++ ++/* Reset the full i.MX28 SoC via a chipset feature */ ++void __noreturn reset_cpu(unsigned long addr) ++{ ++ u32 reg; ++ ++ reg = readl(IMX_CCM_BASE + HW_CLKCTRL_RESET); ++ writel(reg | HW_CLKCTRL_RESET_CHIP, IMX_CCM_BASE + HW_CLKCTRL_RESET); ++ ++ while (1) ++ ; ++ /*NOTREACHED*/ ++} ++EXPORT_SYMBOL(reset_cpu); +diff --git a/arch/arm/mach-mxs/speed-imx23.c b/arch/arm/mach-mxs/speed-imx23.c +index b10c786..5d0c90d 100644 +--- a/arch/arm/mach-mxs/speed-imx23.c ++++ b/arch/arm/mach-mxs/speed-imx23.c +@@ -47,6 +47,8 @@ + # define GET_SSP_DIV(x) ((x) & CLKCTRL_SSP_DIV_MASK) + # define SET_SSP_DIV(x) ((x) & CLKCTRL_SSP_DIV_MASK) + #define HW_CLKCTRL_GPMI 0x080 ++# define CLKCTRL_GPMI_CLKGATE (1 << 31) ++# define CLKCTRL_GPMI_DIV_MASK 0x3ff + /* note: no set/clear register! */ + #define HW_CLKCTRL_SPDIF 0x090 + /* note: no set/clear register! */ +@@ -184,12 +186,34 @@ unsigned imx_get_hclk(void) + + if (readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & 0x20) { + rate *= readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & 0x1f; +- rate >>= 5U; /* / 32 */ ++ rate = DIV_ROUND_UP(rate, 32); + } else +- rate /= readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & 0x1f; ++ rate = DIV_ROUND_UP(rate, ++ readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & 0x1f); + return rate * 1000; + } + ++unsigned imx_set_hclk(unsigned nc) ++{ ++ unsigned root_rate = imx_get_armclk(); ++ unsigned reg, div; ++ ++ div = DIV_ROUND_UP(root_rate, nc); ++ if ((div == 0) || (div >= 32)) ++ return 0; ++ ++ if ((root_rate < nc) && (root_rate == 64000000)) ++ div = 3; ++ ++ reg = readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & ~0x3f; ++ writel(reg | div, IMX_CCM_BASE + HW_CLKCTRL_HBUS); ++ ++ while (readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & (1 << 31)) ++ ; ++ ++ return imx_get_hclk(); ++} ++ + /* + * Source of UART, debug UART, audio, PWM, dri, timer, digctl + */ +@@ -266,6 +290,23 @@ unsigned imx_set_sspclk(unsigned index, unsigned nc, int high) + return imx_get_sspclk(index); + } + ++void imx_enable_nandclk(void) ++{ ++ uint32_t reg; ++ ++ /* Clear bypass bit; refman says clear, but fsl-code does set. Hooray! */ ++ writel(CLKCTRL_CLKSEQ_BYPASS_GPMI, ++ IMX_CCM_BASE + HW_CLKCTRL_CLKSEQ + BIT_SET); ++ ++ reg = readl(IMX_CCM_BASE + HW_CLKCTRL_GPMI) & ~CLKCTRL_GPMI_CLKGATE; ++ writel(reg, IMX_CCM_BASE + HW_CLKCTRL_GPMI); ++ udelay(1000); ++ /* Initialize DIV to 1 */ ++ reg &= ~CLKCTRL_GPMI_DIV_MASK; ++ reg |= 1; ++ writel(reg, IMX_CCM_BASE + HW_CLKCTRL_GPMI); ++} ++ + void imx_dump_clocks(void) + { + printf("mpll: %10u kHz\n", imx_get_mpllclk() / 1000); +diff --git a/arch/arm/mach-mxs/speed-imx28.c b/arch/arm/mach-mxs/speed-imx28.c +index 67cdbdf..df55f64 100644 +--- a/arch/arm/mach-mxs/speed-imx28.c ++++ b/arch/arm/mach-mxs/speed-imx28.c +@@ -48,6 +48,8 @@ + # define GET_SSP_DIV(x) ((x) & CLKCTRL_SSP_DIV_MASK) + # define SET_SSP_DIV(x) ((x) & CLKCTRL_SSP_DIV_MASK) + #define HW_CLKCTRL_GPMI 0x0d0 ++# define CLKCTRL_GPMI_CLKGATE (1 << 31) ++# define CLKCTRL_GPMI_DIV_MASK 0x3ff + /* note: no set/clear register! */ + #define HW_CLKCTRL_SPDIF 0x0e0 + /* note: no set/clear register! */ +@@ -251,12 +253,34 @@ unsigned imx_get_hclk(void) + + if (readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & 0x20) { + rate *= readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & 0x1f; +- rate /= 32; ++ rate = DIV_ROUND_UP(rate, 32); + } else +- rate /= readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & 0x1f; ++ rate = DIV_ROUND_UP(rate, ++ readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & 0x1f); + return rate * 1000; + } + ++unsigned imx_set_hclk(unsigned nc) ++{ ++ unsigned root_rate = imx_get_armclk(); ++ unsigned reg, div; ++ ++ div = DIV_ROUND_UP(root_rate, nc); ++ if ((div == 0) || (div >= 32)) ++ return 0; ++ ++ if ((root_rate < nc) && (root_rate == 64000000)) ++ div = 3; ++ ++ reg = readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & ~0x3f; ++ writel(reg | div, IMX_CCM_BASE + HW_CLKCTRL_HBUS); ++ ++ while (readl(IMX_CCM_BASE + HW_CLKCTRL_HBUS) & (1 << 31)) ++ ; ++ ++ return imx_get_hclk(); ++} ++ + /* + * Source of UART, debug UART, audio, PWM, dri, timer, digctl + */ +@@ -376,6 +400,23 @@ void imx_enable_enetclk(void) + IMX_CCM_BASE + HW_CLKCTRL_ENET); + } + ++void imx_enable_nandclk(void) ++{ ++ uint32_t reg; ++ ++ /* Clear bypass bit; refman says clear, but fsl-code does set. Hooray! */ ++ writel(CLKCTRL_CLKSEQ_BYPASS_GPMI, ++ IMX_CCM_BASE + HW_CLKCTRL_CLKSEQ + BIT_SET); ++ ++ reg = readl(IMX_CCM_BASE + HW_CLKCTRL_GPMI) & ~CLKCTRL_GPMI_CLKGATE; ++ writel(reg, IMX_CCM_BASE + HW_CLKCTRL_GPMI); ++ udelay(1000); ++ /* Initialize DIV to 1 */ ++ reg &= ~CLKCTRL_GPMI_DIV_MASK; ++ reg |= 1; ++ writel(reg, IMX_CCM_BASE + HW_CLKCTRL_GPMI); ++} ++ + void imx_dump_clocks(void) + { + printf("mpll: %10u kHz\n", imx_get_mpllclk() / 1000); +diff --git a/arch/arm/mach-mxs/usb-imx23.c b/arch/arm/mach-mxs/usb-imx23.c +new file mode 100644 +index 0000000..9aaf4bc +--- /dev/null ++++ b/arch/arm/mach-mxs/usb-imx23.c +@@ -0,0 +1,65 @@ ++/* ++ * i.MX23 USBPHY setup ++ * ++ * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> ++ * ++ * 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 <common.h> ++#include <io.h> ++#include <mach/imx-regs.h> ++#include <mach/power.h> ++ ++#define USBPHY_PWD (IMX_USBPHY_BASE + 0x0) ++ ++#define USBPHY_CTRL (IMX_USBPHY_BASE + 0x30) ++#define USBPHY_CTRL_SFTRST 0x80000000 ++#define USBPHY_CTRL_CLKGATE 0x40000000 ++ ++#define CLK_PLLCTRL0 (IMX_CCM_BASE + 0x0) ++#define PLLCTRL0_EN_USB_CLKS 0x00040000 ++ ++#define DIGCTRL_CTRL (IMX_DIGCTL_BASE + 0x0) ++#define DIGCTL_CTRL_USB_CLKGATE 0x00000004 ++ ++#define SET 0x4 ++#define CLR 0x8 ++ ++int imx23_usb_phy_enable(void) ++{ ++ imx_power_prepare_usbphy(); ++ ++ /* Reset USBPHY module */ ++ writel(USBPHY_CTRL_SFTRST, USBPHY_CTRL + SET); ++ udelay(10); ++ ++ /* Remove CLKGATE and SFTRST */ ++ writel(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST, USBPHY_CTRL + CLR); ++ ++ /* Turn on the USB clocks */ ++ writel(PLLCTRL0_EN_USB_CLKS, CLK_PLLCTRL0 + SET); ++ writel(DIGCTL_CTRL_USB_CLKGATE, DIGCTRL_CTRL + CLR); ++ ++ /* Power up the PHY */ ++ writel(0, USBPHY_PWD); ++ ++ /* ++ * Set precharge bit to cure overshoot problems at the ++ * start of packets ++ */ ++ writel(1, USBPHY_CTRL + SET); ++ ++ return 0; ++} +diff --git a/arch/arm/mach-mxs/usb-imx28.c b/arch/arm/mach-mxs/usb-imx28.c +new file mode 100644 +index 0000000..61d59c3 +--- /dev/null ++++ b/arch/arm/mach-mxs/usb-imx28.c +@@ -0,0 +1,101 @@ ++/* ++ * i.MX28 USBPHY setup ++ * ++ * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> ++ * ++ * 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 <common.h> ++#include <io.h> ++#include <errno.h> ++#include <mach/imx-regs.h> ++ ++#define POWER_CTRL (IMX_POWER_BASE + 0x0) ++#define POWER_CTRL_CLKGATE 0x40000000 ++ ++#define POWER_STS (IMX_POWER_BASE + 0xc0) ++#define POWER_STS_VBUSVALID 0x00000002 ++#define POWER_STS_BVALID 0x00000004 ++#define POWER_STS_AVALID 0x00000008 ++ ++#define POWER_DEBUG (IMX_POWER_BASE + 0x110) ++#define POWER_DEBUG_BVALIDPIOLOCK 0x00000002 ++#define POWER_DEBUG_AVALIDPIOLOCK 0x00000004 ++#define POWER_DEBUG_VBUSVALIDPIOLOCK 0x00000008 ++ ++#define USBPHY_PWD 0x0 ++ ++#define USBPHY_CTRL 0x30 ++#define USBPHY_CTRL_SFTRST (1 << 31) ++#define USBPHY_CTRL_CLKGATE (1 << 30) ++#define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15) ++#define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14) ++ ++#define CLK_PLL0CTRL0 (IMX_CCM_BASE + 0x0) ++#define CLK_PLL1CTRL0 (IMX_CCM_BASE + 0x20) ++#define PLLCTRL0_EN_USB_CLKS (1 << 18) ++ ++#define DIGCTRL_CTRL (IMX_DIGCTL_BASE + 0x0) ++#define DIGCTL_CTRL_USB0_CLKGATE (1 << 2) ++#define DIGCTL_CTRL_USB1_CLKGATE (1 << 16) ++ ++#define SET 0x4 ++#define CLR 0x8 ++ ++static void imx28_usb_phy_reset(void __iomem *phybase) ++{ ++ /* Reset USBPHY module */ ++ writel(USBPHY_CTRL_SFTRST, phybase + USBPHY_CTRL + SET); ++ udelay(10); ++ writel(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST, ++ phybase + USBPHY_CTRL + CLR); ++} ++ ++static void imx28_usb_phy_enable(void __iomem *phybase) ++{ ++ /* Power up the PHY */ ++ writel(0, phybase + USBPHY_PWD); ++ ++ writel(USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2 | 1, ++ phybase + USBPHY_CTRL + SET); ++} ++ ++int imx28_usb_phy0_enable(void) ++{ ++ imx28_usb_phy_reset((void *)IMX_USBPHY0_BASE); ++ ++ /* Turn on the USB clocks */ ++ writel(PLLCTRL0_EN_USB_CLKS, CLK_PLL0CTRL0 + SET); ++ ++ writel(DIGCTL_CTRL_USB0_CLKGATE, DIGCTRL_CTRL + CLR); ++ ++ imx28_usb_phy_enable((void *)IMX_USBPHY0_BASE); ++ ++ return 0; ++} ++ ++int imx28_usb_phy1_enable(void) ++{ ++ imx28_usb_phy_reset((void *)IMX_USBPHY1_BASE); ++ ++ /* Turn on the USB clocks */ ++ writel(PLLCTRL0_EN_USB_CLKS, CLK_PLL1CTRL0 + SET); ++ ++ writel(DIGCTL_CTRL_USB1_CLKGATE, DIGCTRL_CTRL + CLR); ++ ++ imx28_usb_phy_enable((void *)IMX_USBPHY1_BASE); ++ ++ return 0; ++} +diff --git a/arch/arm/mach-mxs/usb.c b/arch/arm/mach-mxs/usb.c +deleted file mode 100644 +index b7a9376..0000000 +--- a/arch/arm/mach-mxs/usb.c ++++ /dev/null +@@ -1,92 +0,0 @@ +-/* +- * i.MX23/28 USBPHY setup +- * +- * Copyright 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> +- * +- * 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 <common.h> +-#include <io.h> +-#include <mach/imx-regs.h> +- +-#define POWER_CTRL (IMX_POWER_BASE + 0x0) +-#define POWER_CTRL_CLKGATE 0x40000000 +- +-#define POWER_STS (IMX_POWER_BASE + 0xc0) +-#define POWER_STS_VBUSVALID 0x00000002 +-#define POWER_STS_BVALID 0x00000004 +-#define POWER_STS_AVALID 0x00000008 +- +-#define POWER_DEBUG (IMX_POWER_BASE + 0x110) +-#define POWER_DEBUG_BVALIDPIOLOCK 0x00000002 +-#define POWER_DEBUG_AVALIDPIOLOCK 0x00000004 +-#define POWER_DEBUG_VBUSVALIDPIOLOCK 0x00000008 +- +-#define USBPHY_PWD (IMX_USBPHY_BASE + 0x0) +- +-#define USBPHY_CTRL (IMX_USBPHY_BASE + 0x30) +-#define USBPHY_CTRL_SFTRST 0x80000000 +-#define USBPHY_CTRL_CLKGATE 0x40000000 +- +-#define CLK_PLLCTRL0 (IMX_CCM_BASE + 0x0) +-#define PLLCTRL0_EN_USB_CLKS 0x00040000 +- +-#define DIGCTRL_CTRL (IMX_DIGCTL_BASE + 0x0) +-#define DIGCTL_CTRL_USB_CLKGATE 0x00000004 +- +-#define SET 0x4 +-#define CLR 0x8 +- +-int imx_usb_phy_enable(void) +-{ +- u32 reg; +- +- /* +- * Set these bits so that we can force the OTG bits high +- * so the ARC core operates properly +- */ +- writel(POWER_CTRL_CLKGATE, POWER_CTRL + CLR); +- +- writel(POWER_DEBUG_VBUSVALIDPIOLOCK | +- POWER_DEBUG_AVALIDPIOLOCK | +- POWER_DEBUG_BVALIDPIOLOCK, POWER_DEBUG + SET); +- +- reg = readl(POWER_STS); +- reg |= POWER_STS_BVALID | POWER_STS_AVALID | POWER_STS_VBUSVALID; +- writel(reg, POWER_STS); +- +- /* Reset USBPHY module */ +- writel(USBPHY_CTRL_SFTRST, USBPHY_CTRL + SET); +- udelay(10); +- +- /* Remove CLKGATE and SFTRST */ +- writel(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST, USBPHY_CTRL + CLR); +- +- /* Turn on the USB clocks */ +- writel(PLLCTRL0_EN_USB_CLKS, CLK_PLLCTRL0 + SET); +- writel(DIGCTL_CTRL_USB_CLKGATE, DIGCTRL_CTRL + CLR); +- +- /* Power up the PHY */ +- writel(0, USBPHY_PWD); +- +- /* +- * Set precharge bit to cure overshoot problems at the +- * start of packets +- */ +- writel(1, USBPHY_CTRL + SET); +- +- return 0; +-} +- +diff --git a/arch/arm/mach-samsung/include/mach/devices-s3c24xx.h b/arch/arm/mach-samsung/include/mach/devices-s3c24xx.h +new file mode 100644 +index 0000000..51fd9a1 +--- /dev/null ++++ b/arch/arm/mach-samsung/include/mach/devices-s3c24xx.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2012 Juergen Beisert ++ * ++ * 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. ++ * ++ */ ++ ++#ifndef INCLUDE_MACH_DEVICES_S3C24XX_H ++# define INCLUDE_MACH_DEVICES_S3C24XX_H ++ ++#include <driver.h> ++#include <mach/s3c24xx-iomap.h> ++#include <mach/s3c24xx-nand.h> ++#include <mach/s3c-mci.h> ++#include <mach/s3c24xx-fb.h> ++ ++static inline void s3c24xx_add_nand(struct s3c24x0_nand_platform_data *d) ++{ ++ add_generic_device("s3c24x0_nand", DEVICE_ID_DYNAMIC, NULL, ++ S3C24X0_NAND_BASE, 0x80, IORESOURCE_MEM, d); ++} ++ ++static inline void s3c24xx_add_mci(struct s3c_mci_platform_data *d) ++{ ++ add_generic_device("s3c_mci", DEVICE_ID_DYNAMIC, NULL, ++ S3C2410_SDI_BASE, 0x80, IORESOURCE_MEM, d); ++} ++ ++static inline void s3c24xx_add_fb(struct s3c_fb_platform_data *d) ++{ ++ add_generic_device("s3c_fb", DEVICE_ID_DYNAMIC, NULL, ++ S3C2410_LCD_BASE, 0x80, IORESOURCE_MEM, d); ++} ++ ++static inline void s3c24xx_add_ohci(void) ++{ ++ add_generic_device("ohci", DEVICE_ID_DYNAMIC, NULL, ++ S3C2410_USB_HOST_BASE, 0x100, IORESOURCE_MEM, NULL); ++} ++ ++static inline void s3c24xx_add_uart1(void) ++{ ++ add_generic_device("s3c_serial", DEVICE_ID_DYNAMIC, NULL, S3C_UART1_BASE, ++ S3C_UART1_SIZE, IORESOURCE_MEM, NULL); ++} ++ ++#endif /* INCLUDE_MACH_DEVICES_S3C24XX_H */ +diff --git a/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h b/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h +index acd78b8..fa88da1 100644 +--- a/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h ++++ b/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h +@@ -18,6 +18,9 @@ + * + */ + ++#ifndef MACH_S3C24XX_NAND_H ++# define MACH_S3C24XX_NAND_H ++ + #ifdef CONFIG_S3C_NAND_BOOT + extern void s3c24x0_nand_load_image(void*, int, int); + #endif +@@ -52,3 +55,5 @@ struct s3c24x0_nand_platform_data { + * @file + * @brief Basic declaration to use the s3c24x0 NAND driver + */ ++ ++#endif /* MACH_S3C24XX_NAND_H */ +diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h +index cdcb2f8..623ddfb 100644 +--- a/arch/blackfin/include/asm/bitops.h ++++ b/arch/blackfin/include/asm/bitops.h +@@ -268,7 +268,10 @@ static __inline__ int find_next_zero_bit(void *addr, int size, int offset) + return result + ffz(tmp); + } + ++#include <asm-generic/bitops/__ffs.h> ++#include <asm-generic/bitops/__fls.h> + #include <asm-generic/bitops/ffs.h> ++#include <asm-generic/bitops/fls.h> + #include <asm-generic/bitops/hweight.h> + + static __inline__ int ext2_set_bit(int nr, volatile void *addr) +diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h +new file mode 100644 +index 0000000..27d269f +--- /dev/null ++++ b/arch/blackfin/include/asm/dma.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#ifndef __ASM_DMA_H ++#define __ASM_DMA_H ++ ++/* empty */ ++ ++#endif /* __ASM_DMA_H */ +diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile +index 2f77318..cefb4dc 100644 +--- a/arch/blackfin/lib/Makefile ++++ b/arch/blackfin/lib/Makefile +@@ -8,6 +8,7 @@ obj-y += smulsi3_highpart.o + obj-y += umodsi3.o + obj-y += lshrdi3.o + obj-y += ashldi3.o ++obj-y += ashrdi3.o + obj-y += divsi3.o + obj-y += modsi3.o + obj-y += cpu.o +diff --git a/arch/blackfin/lib/ashrdi3.c b/arch/blackfin/lib/ashrdi3.c +new file mode 100644 +index 0000000..b5b351e +--- /dev/null ++++ b/arch/blackfin/lib/ashrdi3.c +@@ -0,0 +1,36 @@ ++/* ++ * Copyright 2004-2009 Analog Devices Inc. ++ * ++ * Licensed under the GPL-2 or later. ++ */ ++ ++#include "gcclib.h" ++ ++#ifdef CONFIG_ARITHMETIC_OPS_L1 ++DItype __ashrdi3(DItype u, word_type b)__attribute__((l1_text)); ++#endif ++ ++DItype __ashrdi3(DItype u, word_type b) ++{ ++ DIunion w; ++ word_type bm; ++ DIunion uu; ++ ++ if (b == 0) ++ return u; ++ ++ uu.ll = u; ++ ++ bm = (sizeof(SItype) * BITS_PER_UNIT) - b; ++ if (bm <= 0) { ++ /* w.s.high = 1..1 or 0..0 */ ++ w.s.high = uu.s.high >> (sizeof(SItype) * BITS_PER_UNIT - 1); ++ w.s.low = uu.s.high >> -bm; ++ } else { ++ USItype carries = (USItype) uu.s.high << bm; ++ w.s.high = uu.s.high >> b; ++ w.s.low = ((USItype) uu.s.low >> b) | carries; ++ } ++ ++ return w.ll; ++} +diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h +index 001ebf2..bf1ac6e 100644 +--- a/arch/mips/include/asm/bitops.h ++++ b/arch/mips/include/asm/bitops.h +@@ -28,5 +28,8 @@ + #define _ASM_MIPS_BITOPS_H_ + + #include <asm-generic/bitops/__ffs.h> ++#include <asm-generic/bitops/__fls.h> ++#include <asm-generic/bitops/ffs.h> ++#include <asm-generic/bitops/fls.h> + + #endif /* _ASM_MIPS_BITOPS_H_ */ +diff --git a/arch/mips/include/asm/dma.h b/arch/mips/include/asm/dma.h +new file mode 100644 +index 0000000..27d269f +--- /dev/null ++++ b/arch/mips/include/asm/dma.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#ifndef __ASM_DMA_H ++#define __ASM_DMA_H ++ ++/* empty */ ++ ++#endif /* __ASM_DMA_H */ +diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig +index 60e411c..c72b741 100644 +--- a/arch/mips/mach-xburst/Kconfig ++++ b/arch/mips/mach-xburst/Kconfig +@@ -12,6 +12,7 @@ choice + + config BOARD_RZX50 + bool "Ritmix RZX-50" ++ select HAS_POWEROFF + select CPU_JZ4755 + + endchoice +diff --git a/arch/mips/mach-xburst/csrc-jz4750.c b/arch/mips/mach-xburst/csrc-jz4750.c +index f625b70..36e401e 100644 +--- a/arch/mips/mach-xburst/csrc-jz4750.c ++++ b/arch/mips/mach-xburst/csrc-jz4750.c +@@ -28,7 +28,7 @@ + #include <io.h> + #include <mach/jz4750d_regs.h> + +-#define JZ_TIMER_CLOCK 40000 ++#define JZ_TIMER_CLOCK 24000000 + + static uint64_t jz4750_cs_read(void) + { +@@ -38,12 +38,13 @@ static uint64_t jz4750_cs_read(void) + static struct clocksource jz4750_cs = { + .read = jz4750_cs_read, + .mask = CLOCKSOURCE_MASK(32), +- .shift = 10, + }; + + static int clocksource_init(void) + { +- jz4750_cs.mult = clocksource_hz2mult(JZ_TIMER_CLOCK, jz4750_cs.shift); ++ clocks_calc_mult_shift(&jz4750_cs.mult, &jz4750_cs.shift, ++ JZ_TIMER_CLOCK, NSEC_PER_SEC, 10); ++ + init_clock(&jz4750_cs); + + __raw_writel(TCU_OSTCSR_PRESCALE1 | TCU_OSTCSR_EXT_EN, +diff --git a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h +index 717493b..eafdd2f 100644 +--- a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h ++++ b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h +@@ -15,6 +15,7 @@ + + #define TCU_BASE 0xb0002000 + #define WDT_BASE 0xb0002000 ++#define RTC_BASE 0xb0003000 + #define UART1_BASE 0xb0031000 + + /************************************************************************* +@@ -77,4 +78,34 @@ + + #define WDT_TCER_TCEN (1 << 0) + ++/************************************************************************* ++ * RTC ++ *************************************************************************/ ++#define RTC_RCR (RTC_BASE + 0x00) /* RTC Control Register */ ++#define RTC_RSR (RTC_BASE + 0x04) /* RTC Second Register */ ++#define RTC_RSAR (RTC_BASE + 0x08) /* RTC Second Alarm Register */ ++#define RTC_RGR (RTC_BASE + 0x0c) /* RTC Regulator Register */ ++ ++#define RTC_HCR (RTC_BASE + 0x20) /* Hibernate Control Register */ ++#define RTC_HWFCR (RTC_BASE + 0x24) /* Hibernate Wakeup Filter Counter Reg */ ++#define RTC_HRCR (RTC_BASE + 0x28) /* Hibernate Reset Counter Register */ ++#define RTC_HWCR (RTC_BASE + 0x2c) /* Hibernate Wakeup Control Register */ ++#define RTC_HWRSR (RTC_BASE + 0x30) /* Hibernate Wakeup Status Register */ ++#define RTC_HSPR (RTC_BASE + 0x34) /* Hibernate Scratch Pattern Register */ ++ ++/* RTC Control Register */ ++#define RTC_RCR_WRDY_BIT 7 ++#define RTC_RCR_WRDY (1 << 7) /* Write Ready Flag */ ++#define RTC_RCR_1HZ_BIT 6 ++#define RTC_RCR_1HZ (1 << RTC_RCR_1HZ_BIT) /* 1Hz Flag */ ++#define RTC_RCR_1HZIE (1 << 5) /* 1Hz Interrupt Enable */ ++#define RTC_RCR_AF_BIT 4 ++#define RTC_RCR_AF (1 << RTC_RCR_AF_BIT) /* Alarm Flag */ ++#define RTC_RCR_AIE (1 << 3) /* Alarm Interrupt Enable */ ++#define RTC_RCR_AE (1 << 2) /* Alarm Enable */ ++#define RTC_RCR_RTCE (1 << 0) /* RTC Enable */ ++ ++/* Hibernate Control Register */ ++#define RTC_HCR_PD (1 << 0) /* Power Down */ ++ + #endif /* __JZ4750D_REGS_H__ */ +diff --git a/arch/mips/mach-xburst/reset-jz4750.c b/arch/mips/mach-xburst/reset-jz4750.c +index 3540ca9..765c033 100644 +--- a/arch/mips/mach-xburst/reset-jz4750.c ++++ b/arch/mips/mach-xburst/reset-jz4750.c +@@ -29,6 +29,19 @@ + + #define JZ_EXTAL 24000000 + ++static void __noreturn jz4750d_halt(void) ++{ ++ while (1) { ++ __asm__(".set push;\n" ++ ".set mips3;\n" ++ "wait;\n" ++ ".set pop;\n" ++ ); ++ } ++ ++ unreachable(); ++} ++ + void __noreturn reset_cpu(ulong addr) + { + __raw_writew(WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN, (u16 *)WDT_TCSR); +@@ -44,3 +57,18 @@ void __noreturn reset_cpu(ulong addr) + unreachable(); + } + EXPORT_SYMBOL(reset_cpu); ++ ++void __noreturn poweroff() ++{ ++ u32 ctrl; ++ ++ shutdown_barebox(); ++ ++ do { ++ ctrl = readl((u32 *)RTC_RCR); ++ } while (!(ctrl & RTC_RCR_WRDY)); ++ ++ writel(RTC_HCR_PD, (u32 *)RTC_HCR); ++ jz4750d_halt(); ++} ++EXPORT_SYMBOL(poweroff); +diff --git a/arch/nios2/boards/generic/generic.c b/arch/nios2/boards/generic/generic.c +index b51b94a..2c998fe 100644 +--- a/arch/nios2/boards/generic/generic.c ++++ b/arch/nios2/boards/generic/generic.c +@@ -9,17 +9,17 @@ static int phy_address = 1; + static struct resource mac_resources[] = { + [0] = { + .start = NIOS_SOPC_TSE_BASE, +- .size = 0x400, ++ .end = NIOS_SOPC_TSE_BASE + 0x400 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = NIOS_SOPC_SGDMA_RX_BASE, +- .size = 0x40, ++ .end = 0x40 + NIOS_SOPC_SGDMA_RX_BASE - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = NIOS_SOPC_SGDMA_TX_BASE, +- .size = 0x40, ++ .end = 0x40 + NIOS_SOPC_SGDMA_TX_BASE - 1, + .flags = IORESOURCE_MEM, + }, + }; +diff --git a/arch/nios2/include/asm/bitops.h b/arch/nios2/include/asm/bitops.h +index ab0e3d5..0712845 100644 +--- a/arch/nios2/include/asm/bitops.h ++++ b/arch/nios2/include/asm/bitops.h +@@ -1,4 +1,9 @@ + #ifndef _ASM_BITOPS_H + #define _ASM_BITOPS_H + ++#include <asm-generic/bitops/__ffs.h> ++#include <asm-generic/bitops/__fls.h> ++#include <asm-generic/bitops/ffs.h> ++#include <asm-generic/bitops/fls.h> ++ + #endif /* _ASM_BITOPS_H */ +diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h +index 5b70f4c..9819a97 100644 +--- a/arch/nios2/include/asm/dma-mapping.h ++++ b/arch/nios2/include/asm/dma-mapping.h +@@ -1,8 +1,12 @@ + #ifndef __ASM_NIOS2_DMA_MAPPING_H + #define __ASM_NIOS2_DMA_MAPPING_H + ++#include <common.h> ++#include <xfuncs.h> ++ + #include <asm/cache.h> + ++ + /* dma_alloc_coherent() return cache-line aligned allocation which is mapped + * to uncached io region. + * +@@ -22,4 +26,10 @@ static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) + return (void *)(*handle | IO_REGION_BASE); + } + ++#define dma_alloc dma_alloc ++static inline void *dma_alloc(size_t size) ++{ ++ return xmemalign(DCACHE_LINE_SIZE, ALIGN(size, DCACHE_LINE_SIZE)); ++} ++ + #endif /* __ASM_NIOS2_DMA_MAPPING_H */ +diff --git a/arch/nios2/include/asm/dma.h b/arch/nios2/include/asm/dma.h +new file mode 100644 +index 0000000..8f709d2 +--- /dev/null ++++ b/arch/nios2/include/asm/dma.h +@@ -0,0 +1,8 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#include <asm/dma-mapping.h> +diff --git a/arch/openrisc/Makefile b/arch/openrisc/Makefile +index fd8bbbf..1f4b175 100644 +--- a/arch/openrisc/Makefile ++++ b/arch/openrisc/Makefile +@@ -1,5 +1,7 @@ + CPPFLAGS += -D__OR1K__ -ffixed-r10 -mhard-mul -mhard-div + ++LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) ++ + board-$(CONFIG_GENERIC) := generic + + KALLSYMS += --symbol-prefix=_ +@@ -18,4 +20,6 @@ common-y += $(BOARD) + common-y += arch/openrisc/lib/ + common-y += arch/openrisc/cpu/ + ++common-y += $(LIBGCC) ++ + lds-y += arch/openrisc/cpu/barebox.lds +diff --git a/arch/openrisc/include/asm/dma.h b/arch/openrisc/include/asm/dma.h +new file mode 100644 +index 0000000..27d269f +--- /dev/null ++++ b/arch/openrisc/include/asm/dma.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#ifndef __ASM_DMA_H ++#define __ASM_DMA_H ++ ++/* empty */ ++ ++#endif /* __ASM_DMA_H */ +diff --git a/arch/ppc/include/asm/dma.h b/arch/ppc/include/asm/dma.h +new file mode 100644 +index 0000000..27d269f +--- /dev/null ++++ b/arch/ppc/include/asm/dma.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#ifndef __ASM_DMA_H ++#define __ASM_DMA_H ++ ++/* empty */ ++ ++#endif /* __ASM_DMA_H */ +diff --git a/arch/ppc/mach-mpc85xx/include/mach/clocks.h b/arch/ppc/mach-mpc85xx/include/mach/clocks.h +index 9477168..2ab367b 100644 +--- a/arch/ppc/mach-mpc85xx/include/mach/clocks.h ++++ b/arch/ppc/mach-mpc85xx/include/mach/clocks.h +@@ -10,8 +10,6 @@ struct sys_info { + unsigned long freqLocalBus; + }; + +-#define NSEC_PER_SEC 1000000000L +- + unsigned long fsl_get_bus_freq(ulong dummy); + unsigned long fsl_get_timebase_clock(void); + void fsl_get_sys_info(struct sys_info *sysInfo); +diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c +index 90a9741..96fa100 100644 +--- a/arch/sandbox/board/hostfile.c ++++ b/arch/sandbox/board/hostfile.c +@@ -34,7 +34,7 @@ struct hf_priv { + struct hf_platform_data *pdata; + }; + +-static ssize_t hf_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags) ++static ssize_t hf_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags) + { + struct hf_platform_data *hf = cdev->priv; + int fd = hf->fd; +@@ -45,7 +45,7 @@ static ssize_t hf_read(struct cdev *cdev, void *buf, size_t count, ulong offset, + return linux_read(fd, buf, count); + } + +-static ssize_t hf_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) ++static ssize_t hf_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) + { + struct hf_platform_data *hf = cdev->priv; + int fd = hf->fd; +diff --git a/arch/sandbox/include/asm/dma.h b/arch/sandbox/include/asm/dma.h +new file mode 100644 +index 0000000..4595367 +--- /dev/null ++++ b/arch/sandbox/include/asm/dma.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#ifndef __ASM_DMA_H ++#define __ASM_DMA_H ++ ++/* empty*/ ++ ++#endif /* __ASM_DMA_H */ +diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h +index b43afa3..830b1a5 100644 +--- a/arch/x86/include/asm/bitops.h ++++ b/arch/x86/include/asm/bitops.h +@@ -27,6 +27,11 @@ + #ifndef _ASM_X86_BITOPS_H_ + #define _ASM_X86_BITOPS_H_ + +-/* nothing special yet */ ++#define BITS_PER_LONG 32 ++ ++#include <asm-generic/bitops/__fls.h> ++#include <asm-generic/bitops/__ffs.h> ++#include <asm-generic/bitops/fls.h> ++#include <asm-generic/bitops/ffs.h> + + #endif /* _ASM_X86_BITOPS_H_ */ +diff --git a/arch/x86/include/asm/dma.h b/arch/x86/include/asm/dma.h +new file mode 100644 +index 0000000..27d269f +--- /dev/null ++++ b/arch/x86/include/asm/dma.h +@@ -0,0 +1,13 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#ifndef __ASM_DMA_H ++#define __ASM_DMA_H ++ ++/* empty */ ++ ++#endif /* __ASM_DMA_H */ +diff --git a/commands/Kconfig b/commands/Kconfig +index 52e1f17..2478e3f 100644 +--- a/commands/Kconfig ++++ b/commands/Kconfig +@@ -6,6 +6,10 @@ config COMMAND_SUPPORT + depends on !SHELL_NONE + default y + ++config HAS_POWEROFF ++ bool ++ default n ++ + if COMMAND_SUPPORT + + menu "commands " +@@ -25,6 +29,10 @@ config CMD_SLEEP + tristate + prompt "sleep" + ++config CMD_MSLEEP ++ tristate ++ prompt "msleep" ++ + config CMD_SAVEENV + tristate + select ENV_HANDLING +@@ -198,6 +206,20 @@ config CMD_AUTOMOUNT + this directory available (discover USB devices, bring network interface + up and finally mount the filesystem). + ++config CMD_BASENAME ++ tristate ++ prompt "basename" ++ help ++ Strip directory and suffix from filenames and store the result in a ++ environment variable ++ ++config CMD_DIRNAME ++ tristate ++ prompt "dirname" ++ help ++ Strip last component of file name and store the result in a ++ environment variable ++ + endmenu + + menu "console " +@@ -422,6 +444,11 @@ config CMD_RESET + tristate + prompt "reset" + ++config CMD_POWEROFF ++ tristate ++ depends on HAS_POWEROFF ++ prompt "poweroff" ++ + config CMD_GO + tristate + prompt "go" +@@ -552,6 +579,25 @@ config CMD_USB + help + The usb command allows to rescan for USB devices. + ++menuconfig CMD_WD ++ bool ++ depends on WATCHDOG ++ prompt "wd command " ++ help ++ The 'wd' command which allows to start, stop and trigger the onboard ++ watchdog. ++ ++if CMD_WD ++ ++config CMD_WD_DEFAULT_TIMOUT ++ int ++ prompt "default timeout" ++ help ++ Define the default timeout value in [seconds] if the first call of ++ 'wd' is done without a timeout value (which means the watchdog gets ++ enabled and re-triggered with the default timeout value). ++endif ++ + endmenu + + endif +diff --git a/commands/Makefile b/commands/Makefile +index 4c8a0a9..54191b4 100644 +--- a/commands/Makefile ++++ b/commands/Makefile +@@ -1,3 +1,4 @@ ++obj-y += stddev.o + obj-$(CONFIG_CMD_BOOTM) += bootm.o + obj-$(CONFIG_CMD_UIMAGE) += uimage.o + obj-$(CONFIG_CMD_LINUX16) += linux16.o +@@ -10,7 +11,9 @@ obj-$(CONFIG_CMD_MTEST) += memtest.o + obj-$(CONFIG_CMD_EDIT) += edit.o + obj-$(CONFIG_CMD_EXEC) += exec.o + obj-$(CONFIG_CMD_SLEEP) += sleep.o ++obj-$(CONFIG_CMD_MSLEEP) += msleep.o + obj-$(CONFIG_CMD_RESET) += reset.o ++obj-$(CONFIG_CMD_POWEROFF) += poweroff.o + obj-$(CONFIG_CMD_GO) += go.o + obj-$(CONFIG_NET) += net.o + obj-$(CONFIG_CMD_PARTITION) += partition.o +@@ -57,6 +60,7 @@ obj-$(CONFIG_CMD_MENU) += menu.o + obj-$(CONFIG_CMD_PASSWD) += passwd.o + obj-$(CONFIG_CMD_LOGIN) += login.o + obj-$(CONFIG_CMD_LED) += led.o ++obj-$(CONFIG_CMD_WD) += wd.o + obj-$(CONFIG_CMD_LED_TRIGGER) += trigger.o + obj-$(CONFIG_CMD_USB) += usb.o + obj-$(CONFIG_CMD_TIME) += time.o +@@ -66,3 +70,5 @@ obj-$(CONFIG_CMD_IOMEM) += iomem.o + obj-$(CONFIG_CMD_LINUX_EXEC) += linux_exec.o + obj-$(CONFIG_CMD_AUTOMOUNT) += automount.o + obj-$(CONFIG_CMD_GLOBAL) += global.o ++obj-$(CONFIG_CMD_BASENAME) += basename.o ++obj-$(CONFIG_CMD_DIRNAME) += dirname.o +diff --git a/commands/basename.c b/commands/basename.c +new file mode 100644 +index 0000000..b47ff8c +--- /dev/null ++++ b/commands/basename.c +@@ -0,0 +1,47 @@ ++/* ++ * basename.c - strip directory and suffix from filenames ++ * ++ * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix ++ * ++ * 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 version 2 ++ * as published by the Free Software Foundation. ++ * ++ * 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 <common.h> ++#include <command.h> ++#include <libgen.h> ++#include <environment.h> ++ ++static int do_basename(int argc, char *argv[]) ++{ ++ if (argc != 3) ++ return COMMAND_ERROR_USAGE; ++ ++ setenv(argv[2], basename(argv[1])); ++ ++ return 0; ++} ++ ++BAREBOX_CMD_HELP_START(basename) ++BAREBOX_CMD_HELP_USAGE("basename NAME BASENAME\n") ++BAREBOX_CMD_HELP_SHORT("strip NAME and store into $BASENAME\n") ++BAREBOX_CMD_HELP_END ++ ++BAREBOX_CMD_START(basename) ++ .cmd = do_basename, ++ .usage = "strip directory and suffix from filenames", ++ BAREBOX_CMD_HELP(cmd_basename_help) ++BAREBOX_CMD_END +diff --git a/commands/bootm.c b/commands/bootm.c +index 2989d39..3c47ab5 100644 +--- a/commands/bootm.c ++++ b/commands/bootm.c +@@ -383,8 +383,7 @@ static int do_bootm(int argc, char *argv[]) + if (data.os_res) + printf("OS image is at 0x%08x-0x%08x\n", + data.os_res->start, +- data.os_res->start + +- data.os_res->size - 1); ++ data.os_res->end); + else + printf("OS image not yet relocated\n"); + +@@ -399,8 +398,7 @@ static int do_bootm(int argc, char *argv[]) + if (data.initrd_res) + printf("initrd is at 0x%08x-0x%08x\n", + data.initrd_res->start, +- data.initrd_res->start + +- data.initrd_res->size - 1); ++ data.initrd_res->end); + else + printf("initrd image not yet relocated\n"); + } +diff --git a/commands/crc.c b/commands/crc.c +index df22941..8f80e42 100644 +--- a/commands/crc.c ++++ b/commands/crc.c +@@ -47,9 +47,12 @@ static int file_crc(char* filename, ulong start, ulong size, ulong *crc, + } + + if (start > 0) { +- ret = lseek(fd, start, SEEK_SET); +- if (ret == -1) { ++ off_t lseek_ret; ++ errno = 0; ++ lseek_ret = lseek(fd, start, SEEK_SET); ++ if (lseek_ret == (off_t)-1 && errno) { + perror("lseek"); ++ ret = -1; + goto out; + } + } +@@ -84,8 +87,8 @@ out: + + static int do_crc(int argc, char *argv[]) + { +- ulong start = 0, size = ~0, total = 0; +- ulong crc = 0, vcrc = 0; ++ loff_t start = 0, size = ~0; ++ ulong crc = 0, vcrc = 0, total = 0; + char *filename = "/dev/mem"; + #ifdef CONFIG_CMD_CRC_CMP + char *vfilename = NULL; +diff --git a/commands/digest.c b/commands/digest.c +index 8432914..07cbec9 100644 +--- a/commands/digest.c ++++ b/commands/digest.c +@@ -51,7 +51,7 @@ static int do_digest(char *algorithm, int argc, char *argv[]) + argv++; + while (*argv) { + char *filename = "/dev/mem"; +- ulong start = 0, size = ~0; ++ loff_t start = 0, size = ~0; + + /* arguments are either file, file+area or area */ + if (parse_area_spec(*argv, &start, &size)) { +@@ -66,7 +66,7 @@ static int do_digest(char *algorithm, int argc, char *argv[]) + for (i = 0; i < d->length; i++) + printf("%02x", hash[i]); + +- printf(" %s\t0x%08lx ... 0x%08lx\n", filename, start, start + size); ++ printf(" %s\t0x%08llx ... 0x%08llx\n", filename, start, start + size); + + argv++; + } +diff --git a/commands/dirname.c b/commands/dirname.c +new file mode 100644 +index 0000000..cf1d0a0 +--- /dev/null ++++ b/commands/dirname.c +@@ -0,0 +1,47 @@ ++/* ++ * dirname.c - strip directory and suffix from filenames ++ * ++ * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix ++ * ++ * 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 version 2 ++ * as published by the Free Software Foundation. ++ * ++ * 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 <common.h> ++#include <command.h> ++#include <libgen.h> ++#include <environment.h> ++ ++static int do_dirname(int argc, char *argv[]) ++{ ++ if (argc != 3) ++ return COMMAND_ERROR_USAGE; ++ ++ setenv(argv[2], dirname(argv[1])); ++ ++ return 0; ++} ++ ++BAREBOX_CMD_HELP_START(dirname) ++BAREBOX_CMD_HELP_USAGE("dirname NAME DIRNAME\n") ++BAREBOX_CMD_HELP_SHORT("strip last componext of NAME and store into $DIRNAME\n") ++BAREBOX_CMD_HELP_END ++ ++BAREBOX_CMD_START(dirname) ++ .cmd = do_dirname, ++ .usage = "strip last component from file name", ++ BAREBOX_CMD_HELP(cmd_dirname_help) ++BAREBOX_CMD_END +diff --git a/commands/flash.c b/commands/flash.c +index 1fcb1cf..d71349a 100644 +--- a/commands/flash.c ++++ b/commands/flash.c +@@ -41,7 +41,7 @@ static int do_flerase(int argc, char *argv[]) + int fd; + char *filename = NULL; + struct stat s; +- unsigned long start = 0, size = ~0; ++ loff_t start = 0, size = ~0; + int ret = 0; + + if (argc == 1) +@@ -109,7 +109,7 @@ static int do_protect(int argc, char *argv[]) + char *filename = NULL; + struct stat s; + int prot = 1; +- unsigned long start = 0, size = ~0; ++ loff_t start = 0, size = ~0; + int ret = 0, err; + + if (argc == 1) +diff --git a/commands/go.c b/commands/go.c +index e9e9d40..14569a5 100644 +--- a/commands/go.c ++++ b/commands/go.c +@@ -92,5 +92,5 @@ BAREBOX_CMD_START(go) + .cmd = do_go, + .usage = "start application at address or file", + BAREBOX_CMD_HELP(cmd_go_help) +- BAREBOX_CMD_COMPLETE(cammand_var_complete) ++ BAREBOX_CMD_COMPLETE(command_var_complete) + BAREBOX_CMD_END +diff --git a/commands/iomem.c b/commands/iomem.c +index 70355fd..c22878c 100644 +--- a/commands/iomem.c ++++ b/commands/iomem.c +@@ -32,8 +32,7 @@ static void __print_resources(struct resource *res, int indent) + + printf(PRINTF_CONVERSION_RESOURCE " - " PRINTF_CONVERSION_RESOURCE + " (size " PRINTF_CONVERSION_RESOURCE ") %s\n", res->start, +- res->start + res->size - 1, +- res->size, res->name); ++ res->end, resource_size(res), res->name); + + list_for_each_entry(r, &res->children, sibling) + __print_resources(r, indent + 1); +diff --git a/commands/ls.c b/commands/ls.c +index ad609f3..fbcbadc 100644 +--- a/commands/ls.c ++++ b/commands/ls.c +@@ -35,7 +35,7 @@ static void ls_one(const char *path, struct stat *s) + unsigned int namelen = strlen(path); + + mkmodestr(s->st_mode, modestr); +- printf("%s %10lu %*.*s\n", modestr, s->st_size, namelen, namelen, path); ++ printf("%s %10llu %*.*s\n", modestr, s->st_size, namelen, namelen, path); + } + + int ls(const char *path, ulong flags) +diff --git a/commands/mem.c b/commands/mem.c +index 080bfde..5322def 100644 +--- a/commands/mem.c ++++ b/commands/mem.c +@@ -43,7 +43,7 @@ + #define PRINTF(fmt,args...) + #endif + +-#define RW_BUF_SIZE (ulong)4096 ++#define RW_BUF_SIZE 4096 + static char *rw_buf; + + static char *DEVMEM = "/dev/mem"; +@@ -55,7 +55,7 @@ static char *DEVMEM = "/dev/mem"; + */ + #define DISP_LINE_LEN 16 + +-int memory_display(char *addr, ulong offs, ulong nbytes, int size) ++int memory_display(char *addr, loff_t offs, ulong nbytes, int size) + { + ulong linebytes, i; + u_char *cp; +@@ -72,7 +72,7 @@ int memory_display(char *addr, ulong offs, ulong nbytes, int size) + u_char *ucp = (u_char *)linebuf; + uint count = 52; + +- printf("%08lx:", offs); ++ printf("%08llx:", offs); + linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes; + + for (i = 0; i < linebytes; i += size) { +@@ -108,7 +108,7 @@ int memory_display(char *addr, ulong offs, ulong nbytes, int size) + return 0; + } + +-static int open_and_lseek(const char *filename, int mode, off_t pos) ++static int open_and_lseek(const char *filename, int mode, loff_t pos) + { + int fd, ret; + +@@ -163,7 +163,7 @@ static int mem_parse_options(int argc, char *argv[], char *optstr, int *mode, + + static int do_mem_md(int argc, char *argv[]) + { +- ulong start = 0, size = 0x100; ++ loff_t start = 0, size = 0x100; + int r, now; + int ret = 0; + int fd; +@@ -180,6 +180,8 @@ static int do_mem_md(int argc, char *argv[]) + } + if (size == ~0) + size = 0x100; ++ } else { ++ return COMMAND_ERROR_USAGE; + } + + fd = open_and_lseek(filename, mode | O_RDONLY, start); +@@ -187,7 +189,7 @@ static int do_mem_md(int argc, char *argv[]) + return 1; + + do { +- now = min(size, RW_BUF_SIZE); ++ now = min(size, (loff_t)RW_BUF_SIZE); + r = read(fd, rw_buf, now); + if (r < 0) { + perror("read"); +@@ -240,7 +242,7 @@ static int do_mem_mw(int argc, char *argv[]) + int fd; + char *filename = DEVMEM; + int mode = O_RWSIZE_4; +- ulong adr; ++ loff_t adr; + + if (mem_parse_options(argc, argv, "bwld:", &mode, NULL, &filename) < 0) + return 1; +@@ -248,7 +250,7 @@ static int do_mem_mw(int argc, char *argv[]) + if (optind + 1 >= argc) + return COMMAND_ERROR_USAGE; + +- adr = strtoul_suffix(argv[optind++], NULL, 0); ++ adr = strtoull_suffix(argv[optind++], NULL, 0); + + fd = open_and_lseek(filename, mode | O_WRONLY, adr); + if (fd < 0) +@@ -300,7 +302,7 @@ BAREBOX_CMD_END + + static int do_mem_cmp(int argc, char *argv[]) + { +- ulong addr1, addr2, count = ~0; ++ loff_t addr1, addr2, count = ~0; + int mode = O_RWSIZE_1; + char *sourcefile = DEVMEM; + char *destfile = DEVMEM; +@@ -316,8 +318,8 @@ static int do_mem_cmp(int argc, char *argv[]) + if (optind + 2 > argc) + return COMMAND_ERROR_USAGE; + +- addr1 = strtoul_suffix(argv[optind], NULL, 0); +- addr2 = strtoul_suffix(argv[optind + 1], NULL, 0); ++ addr1 = strtoull_suffix(argv[optind], NULL, 0); ++ addr2 = strtoull_suffix(argv[optind + 1], NULL, 0); + + if (optind + 2 == argc) { + if (sourcefile == DEVMEM) { +@@ -330,7 +332,7 @@ static int do_mem_cmp(int argc, char *argv[]) + } + count = statbuf.st_size - addr1; + } else { +- count = strtoul_suffix(argv[optind + 2], NULL, 0); ++ count = strtoull_suffix(argv[optind + 2], NULL, 0); + } + + sourcefd = open_and_lseek(sourcefile, mode | O_RDONLY, addr1); +@@ -348,7 +350,7 @@ static int do_mem_cmp(int argc, char *argv[]) + while (count > 0) { + int now, r1, r2, i; + +- now = min(RW_BUF_SIZE, count); ++ now = min((loff_t)RW_BUF_SIZE, count); + + r1 = read(sourcefd, rw_buf, now); + if (r1 < 0) { +@@ -409,8 +411,7 @@ BAREBOX_CMD_END + + static int do_mem_cp(int argc, char *argv[]) + { +- ulong count; +- ulong dest, src; ++ loff_t count, dest, src; + char *sourcefile = DEVMEM; + char *destfile = DEVMEM; + int sourcefd, destfd; +@@ -424,8 +425,8 @@ static int do_mem_cp(int argc, char *argv[]) + if (optind + 2 > argc) + return COMMAND_ERROR_USAGE; + +- src = strtoul_suffix(argv[optind], NULL, 0); +- dest = strtoul_suffix(argv[optind + 1], NULL, 0); ++ src = strtoull_suffix(argv[optind], NULL, 0); ++ dest = strtoull_suffix(argv[optind + 1], NULL, 0); + + if (optind + 2 == argc) { + if (sourcefile == DEVMEM) { +@@ -438,7 +439,7 @@ static int do_mem_cp(int argc, char *argv[]) + } + count = statbuf.st_size - src; + } else { +- count = strtoul_suffix(argv[optind + 2], NULL, 0); ++ count = strtoull_suffix(argv[optind + 2], NULL, 0); + } + + sourcefd = open_and_lseek(sourcefile, mode | O_RDONLY, src); +@@ -454,7 +455,7 @@ static int do_mem_cp(int argc, char *argv[]) + while (count > 0) { + int now, r, w, tmp; + +- now = min(RW_BUF_SIZE, count); ++ now = min((loff_t)RW_BUF_SIZE, count); + + r = read(sourcefd, rw_buf, now); + if (r < 0) { +@@ -516,7 +517,7 @@ BAREBOX_CMD_END + + static int do_memset(int argc, char *argv[]) + { +- ulong s, c, n; ++ loff_t s, c, n; + int fd; + char *buf; + int mode = O_RWSIZE_1; +@@ -529,9 +530,9 @@ static int do_memset(int argc, char *argv[]) + if (optind + 3 > argc) + return COMMAND_ERROR_USAGE; + +- s = strtoul_suffix(argv[optind], NULL, 0); +- c = strtoul_suffix(argv[optind + 1], NULL, 0); +- n = strtoul_suffix(argv[optind + 2], NULL, 0); ++ s = strtoull_suffix(argv[optind], NULL, 0); ++ c = strtoull_suffix(argv[optind + 1], NULL, 0); ++ n = strtoull_suffix(argv[optind + 2], NULL, 0); + + fd = open_and_lseek(file, mode | O_WRONLY, s); + if (fd < 0) +@@ -543,7 +544,7 @@ static int do_memset(int argc, char *argv[]) + while (n > 0) { + int now; + +- now = min(RW_BUF_SIZE, n); ++ now = min((loff_t)RW_BUF_SIZE, n); + + ret = write(fd, buf, now); + if (ret < 0) { +@@ -594,7 +595,7 @@ static int mem_probe(struct device_d *dev) + dev->priv = cdev; + + cdev->name = (char*)dev->resource[0].name; +- cdev->size = (unsigned long)dev->resource[0].size; ++ cdev->size = (unsigned long)resource_size(&dev->resource[0]); + cdev->ops = &memops; + cdev->dev = dev; + +@@ -623,32 +624,3 @@ static int mem_init(void) + } + + device_initcall(mem_init); +- +-static ssize_t zero_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags) +-{ +- memset(buf, 0, count); +- return count; +-} +- +-static struct file_operations zeroops = { +- .read = zero_read, +- .lseek = dev_lseek_default, +-}; +- +-static int zero_init(void) +-{ +- struct cdev *cdev; +- +- cdev = xzalloc(sizeof (*cdev)); +- +- cdev->name = "zero"; +- cdev->size = ~0; +- cdev->ops = &zeroops; +- +- devfs_create(cdev); +- +- return 0; +-} +- +-device_initcall(zero_init); +- +diff --git a/commands/msleep.c b/commands/msleep.c +new file mode 100644 +index 0000000..c9fa23c +--- /dev/null ++++ b/commands/msleep.c +@@ -0,0 +1,40 @@ ++/* ++ * msleep.c - delay execution for n milliseconds ++ * ++ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix ++ * ++ * derived from commands/sleep.c ++ * ++ * 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 published by the Free Software Foundation. ++ * ++ * 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. ++ * ++ */ ++ ++#include <common.h> ++#include <command.h> ++#include <clock.h> ++ ++static int do_msleep(int argc, char *argv[]) ++{ ++ ulong delay; ++ ++ if (argc != 2) ++ return COMMAND_ERROR_USAGE; ++ ++ delay = simple_strtoul(argv[1], NULL, 10); ++ ++ mdelay(delay); ++ ++ return 0; ++} ++ ++BAREBOX_CMD_START(msleep) ++ .cmd = do_msleep, ++ .usage = "delay execution for n milliseconds", ++BAREBOX_CMD_END +diff --git a/commands/nand.c b/commands/nand.c +index 34aa07b..6124dae 100644 +--- a/commands/nand.c ++++ b/commands/nand.c +@@ -79,6 +79,7 @@ static int do_nand(int argc, char *argv[]) + if (command & NAND_MARKBAD) { + if (optind < argc) { + int ret = 0, fd; ++ loff_t __badblock = badblock; + + printf("marking block at 0x%08x on %s as bad\n", badblock, argv[optind]); + +@@ -88,7 +89,7 @@ static int do_nand(int argc, char *argv[]) + return 1; + } + +- ret = ioctl(fd, MEMSETBADBLOCK, (void *)badblock); ++ ret = ioctl(fd, MEMSETBADBLOCK, &__badblock); + if (ret) + perror("ioctl"); + +diff --git a/commands/nandtest.c b/commands/nandtest.c +index d923e42..06b7f94 100644 +--- a/commands/nandtest.c ++++ b/commands/nandtest.c +@@ -307,11 +307,11 @@ static int do_nandtest(int argc, char *argv[]) + for (test_ofs = flash_offset; + test_ofs < flash_offset+length; + test_ofs += meminfo.erasesize) { +- ++ loff_t __test_ofs = test_ofs; + srand(seed); + seed = rand(); + +- if (ioctl(fd, MEMGETBADBLOCK, (void *)test_ofs)) { ++ if (ioctl(fd, MEMGETBADBLOCK, &__test_ofs)) { + printf("\rBad block at 0x%08x\n", + (unsigned)(test_ofs + + memregion.offset)); +diff --git a/commands/net.c b/commands/net.c +index a453f4e..e77f12f 100644 +--- a/commands/net.c ++++ b/commands/net.c +@@ -36,35 +36,6 @@ + #include <errno.h> + #include <libbb.h> + +-#ifdef CONFIG_NET_RARP +-extern void RarpRequest(void); +- +-static int do_rarpb(int argc, char *argv[]) +-{ +- int size; +- +- if (NetLoopInit(RARP) < 0) +- return 1; +- +- NetOurIP = 0; +- RarpRequest(); /* Basically same as BOOTP */ +- +- if ((size = NetLoop()) < 0) +- return 1; +- +- /* NetLoop ok, update environment */ +- netboot_update_env(); +- +- return 0; +-} +- +-BAREBOX_CMD_START(rarpboot) +- .cmd = do_rarpb, +- .usage = "boot image via network using rarp/tftp protocol", +- BAREBOX_CMD_HELP("[loadAddress] [bootfilename]\n") +-BAREBOX_CMD_END +-#endif /* CONFIG_NET_RARP */ +- + static int do_ethact(int argc, char *argv[]) + { + struct eth_device *edev; +diff --git a/commands/poweroff.c b/commands/poweroff.c +new file mode 100644 +index 0000000..ebb146c +--- /dev/null ++++ b/commands/poweroff.c +@@ -0,0 +1,37 @@ ++/* ++ * poweroff.c - turn board's power off ++ * ++ * Copyright (C) 2011 Antony Pavlov <antonynpavlov@gmail.com> ++ * ++ * This file is part of barebox. ++ * 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 version 2 ++ * as published by the Free Software Foundation. ++ * ++ * 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 <common.h> ++#include <command.h> ++ ++static int cmd_poweroff(int argc, char *argv[]) ++{ ++ poweroff(); ++ ++ /* Not reached */ ++ return 1; ++} ++ ++BAREBOX_CMD_START(poweroff) ++ .cmd = cmd_poweroff, ++ .usage = "Perform POWER OFF of the board", ++BAREBOX_CMD_END +diff --git a/commands/sleep.c b/commands/sleep.c +index c5f7867..950ec08 100644 +--- a/commands/sleep.c ++++ b/commands/sleep.c +@@ -47,5 +47,5 @@ static int do_sleep(int argc, char *argv[]) + BAREBOX_CMD_START(sleep) + .cmd = do_sleep, + .usage = "delay execution for n seconds", +- BAREBOX_CMD_COMPLETE(cammand_var_complete) ++ BAREBOX_CMD_COMPLETE(command_var_complete) + BAREBOX_CMD_END +diff --git a/commands/stddev.c b/commands/stddev.c +new file mode 100644 +index 0000000..098aea8 +--- /dev/null ++++ b/commands/stddev.c +@@ -0,0 +1,106 @@ ++/* ++ * Copyright (c) 2011 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix ++ * ++ * 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 version 2 ++ * as published by the Free Software Foundation. ++ * ++ * 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 ++ * MA 02111-1307 USA ++ */ ++ ++#include <common.h> ++#include <init.h> ++ ++static ssize_t zero_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags) ++{ ++ memset(buf, 0, count); ++ return count; ++} ++ ++static struct file_operations zeroops = { ++ .read = zero_read, ++ .lseek = dev_lseek_default, ++}; ++ ++static int zero_init(void) ++{ ++ struct cdev *cdev; ++ ++ cdev = xzalloc(sizeof (*cdev)); ++ ++ cdev->name = "zero"; ++ cdev->flags = DEVFS_IS_CHARACTER_DEV; ++ cdev->ops = &zeroops; ++ ++ devfs_create(cdev); ++ ++ return 0; ++} ++ ++device_initcall(zero_init); ++ ++static ssize_t full_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags) ++{ ++ memset(buf, 0xff, count); ++ return count; ++} ++ ++static struct file_operations fullops = { ++ .read = full_read, ++ .lseek = dev_lseek_default, ++}; ++ ++static int full_init(void) ++{ ++ struct cdev *cdev; ++ ++ cdev = xzalloc(sizeof (*cdev)); ++ ++ cdev->name = "full"; ++ cdev->flags = DEVFS_IS_CHARACTER_DEV; ++ cdev->ops = &fullops; ++ ++ devfs_create(cdev); ++ ++ return 0; ++} ++ ++device_initcall(full_init); ++ ++static ssize_t null_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) ++{ ++ return count; ++} ++ ++static struct file_operations nullops = { ++ .write = null_write, ++ .lseek = dev_lseek_default, ++}; ++ ++static int null_init(void) ++{ ++ struct cdev *cdev; ++ ++ cdev = xzalloc(sizeof (*cdev)); ++ ++ cdev->name = "null"; ++ cdev->flags = DEVFS_IS_CHARACTER_DEV; ++ cdev->ops = &nullops; ++ ++ devfs_create(cdev); ++ ++ return 0; ++} ++ ++device_initcall(null_init); +diff --git a/commands/wd.c b/commands/wd.c +new file mode 100644 +index 0000000..080bab9 +--- /dev/null ++++ b/commands/wd.c +@@ -0,0 +1,68 @@ ++/* ++ * (c) 2012 Juergen Beisert <kernel@pengutronix.de> ++ * ++ * 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. ++ */ ++ ++#include <common.h> ++#include <command.h> ++#include <errno.h> ++#include <linux/ctype.h> ++#include <watchdog.h> ++ ++/* default timeout in [sec] */ ++static unsigned timeout = CONFIG_CMD_WD_DEFAULT_TIMOUT; ++ ++static int do_wd(int argc, char *argv[]) ++{ ++ int rc; ++ ++ if (argc > 1) { ++ if (isdigit(*argv[1])) { ++ timeout = simple_strtoul(argv[1], NULL, 0); ++ } else { ++ printf("numerical parameter expected\n"); ++ return 1; ++ } ++ } ++ ++ rc = watchdog_set_timeout(timeout); ++ if (rc < 0) { ++ switch (rc) { ++ case -EINVAL: ++ printf("Timeout value out of range\n"); ++ break; ++ case -ENOSYS: ++ printf("Watchdog cannot be disabled\n"); ++ break; ++ default: ++ printf("Watchdog fails: '%s'\n", strerror(-rc)); ++ break; ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++BAREBOX_CMD_HELP_START(wd) ++BAREBOX_CMD_HELP_USAGE("wd [<time>]\n") ++BAREBOX_CMD_HELP_SHORT("enable the watchdog to bark in <time> seconds. " ++ "When <time> is 0, the watchdog gets disabled,\n" ++ "without a parameter the watchdog will be re-triggered\n") ++BAREBOX_CMD_HELP_END ++ ++BAREBOX_CMD_START(wd) ++ .cmd = do_wd, ++ .usage = "enable/disable/trigger the watchdog", ++ BAREBOX_CMD_HELP(cmd_wd_help) ++BAREBOX_CMD_END +diff --git a/common/block.c b/common/block.c +index 71ecfd5..7ad5ecc 100644 +--- a/common/block.c ++++ b/common/block.c +@@ -24,6 +24,7 @@ + #include <malloc.h> + #include <linux/err.h> + #include <linux/list.h> ++#include <dma.h> + + #define BLOCKSIZE(blk) (1 << blk->blockbits) + +@@ -179,7 +180,7 @@ static void *block_get(struct block_device *blk, int block) + } + + static ssize_t block_read(struct cdev *cdev, void *buf, size_t count, +- unsigned long offset, unsigned long flags) ++ loff_t offset, unsigned long flags) + { + struct block_device *blk = cdev->priv; + unsigned long mask = BLOCKSIZE(blk) - 1; +@@ -256,7 +257,7 @@ static int block_put(struct block_device *blk, const void *buf, int block) + } + + static ssize_t block_write(struct cdev *cdev, const void *buf, size_t count, +- unsigned long offset, ulong flags) ++ loff_t offset, ulong flags) + { + struct block_device *blk = cdev->priv; + unsigned long mask = BLOCKSIZE(blk) - 1; +@@ -338,7 +339,7 @@ static struct file_operations block_ops = { + + int blockdevice_register(struct block_device *blk) + { +- size_t size = blk->num_blocks * BLOCKSIZE(blk); ++ loff_t size = (loff_t)blk->num_blocks * BLOCKSIZE(blk); + int ret; + int i; + +@@ -357,7 +358,7 @@ int blockdevice_register(struct block_device *blk) + + for (i = 0; i < 8; i++) { + struct chunk *chunk = xzalloc(sizeof(*chunk)); +- chunk->data = xmalloc(BUFSIZE); ++ chunk->data = dma_alloc(BUFSIZE); + chunk->num = i; + list_add_tail(&chunk->list, &blk->idle_blocks); + } +@@ -376,12 +377,12 @@ int blockdevice_unregister(struct block_device *blk) + writebuffer_flush(blk); + + list_for_each_entry_safe(chunk, tmp, &blk->buffered_blocks, list) { +- free(chunk->data); ++ dma_free(chunk->data); + free(chunk); + } + + list_for_each_entry_safe(chunk, tmp, &blk->idle_blocks, list) { +- free(chunk->data); ++ dma_free(chunk->data); + free(chunk); + } + +diff --git a/common/complete.c b/common/complete.c +index 0780888..a8bde8d 100644 +--- a/common/complete.c ++++ b/common/complete.c +@@ -198,7 +198,7 @@ int empty_complete(struct string_list *sl, char *instr) + return COMPLETE_END; + } + +-int cammand_var_complete(struct string_list *sl, char *instr) ++int command_var_complete(struct string_list *sl, char *instr) + { + return COMPLETE_CONTINUE; + } +@@ -221,7 +221,7 @@ static int env_param_complete(struct string_list *sl, char *instr, int eval) + end = ' '; + } + +- instr_param = strrchr(instr, '.'); ++ instr_param = strchr(instr, '.'); + len = strlen(instr); + + current_c = get_current_context(); +diff --git a/common/filetype.c b/common/filetype.c +index 39c2098..1a5b82d 100644 +--- a/common/filetype.c ++++ b/common/filetype.c +@@ -39,6 +39,7 @@ static const char *filetype_str[] = { + [filetype_oftree] = "open firmware flat device tree", + [filetype_aimage] = "Android boot image", + [filetype_sh] = "Bourne Shell", ++ [filetype_mips_barebox] = "MIPS barebox image", + }; + + const char *file_type_to_string(enum filetype f) +diff --git a/common/memory.c b/common/memory.c +index 3b4a5ef..f04cfac 100644 +--- a/common/memory.c ++++ b/common/memory.c +@@ -122,7 +122,7 @@ void barebox_add_memory_bank(const char *name, resource_size_t start, + struct memory_bank *bank = xzalloc(sizeof(*bank)); + struct device_d *dev; + +- bank->res = request_iomem_region(name, start, size); ++ bank->res = request_iomem_region(name, start, start + size - 1); + + BUG_ON(!bank->res); + +@@ -146,7 +146,7 @@ struct resource *request_sdram_region(const char *name, resource_size_t start, + for_each_memory_bank(bank) { + struct resource *res; + +- res = request_region(bank->res, name, start, size); ++ res = request_region(bank->res, name, start, start + size - 1); + if (res) + return res; + } +diff --git a/common/menu.c b/common/menu.c +index 6c530b6..9f536d6 100644 +--- a/common/menu.c ++++ b/common/menu.c +@@ -53,7 +53,6 @@ void menu_free(struct menu *m) + free(m->name); + free(m->display); + free(m->auto_display); +- free(m->display_buffer); + + list_for_each_entry_safe(me, tmp, &m->entries, list) + menu_entry_free(me); +@@ -87,15 +86,9 @@ EXPORT_SYMBOL(menu_remove); + + int menu_add_entry(struct menu *m, struct menu_entry *me) + { +- int len; +- + if (!m || !me || !me->display) + return -EINVAL; + +- len = strlen(me->display); +- +- m->width = max(len, m->width); +- + m->nb_entries++; + me->num = m->nb_entries; + list_add_tail(&me->list, &m->entries); +@@ -160,6 +153,18 @@ void menu_entry_free(struct menu_entry *me) + } + EXPORT_SYMBOL(menu_entry_free); + ++static void __print_entry(const char *str) ++{ ++ static char outstr[256]; ++ ++ if (IS_ENABLED(CONFIG_SHELL_HUSH)) { ++ process_escape_sequence(str, outstr, 256); ++ puts(outstr); ++ } else { ++ puts(str); ++ } ++} ++ + static void print_menu_entry(struct menu *m, struct menu_entry *me, + int selected) + { +@@ -174,17 +179,11 @@ static void print_menu_entry(struct menu *m, struct menu_entry *me, + puts(" "); + } + +- if (IS_ENABLED(CONFIG_SHELL_HUSH)) +- process_escape_sequence(me->display, m->display_buffer, +- m->display_buffer_size); +- + printf(" %d: ", me->num); + if (selected) + puts("\e[7m"); +- if (IS_ENABLED(CONFIG_SHELL_HUSH)) +- puts(m->display_buffer); +- else +- puts(me->display); ++ ++ __print_entry(me->display); + + if (selected) + puts("\e[m"); +@@ -241,13 +240,7 @@ static void print_menu(struct menu *m) + clear(); + gotoXY(1, 2); + if(m->display) { +- if (IS_ENABLED(CONFIG_SHELL_HUSH)) { +- process_escape_sequence(m->display, m->display_buffer, +- m->display_buffer_size); +- puts(m->display_buffer); +- } else { +- puts(m->display); +- } ++ __print_entry(m->display); + } else { + puts("Menu : "); + puts(m->name); +@@ -266,50 +259,16 @@ static void print_menu(struct menu *m) + print_menu_entry(m, m->selected, 1); + } + +-static int menu_alloc_display_buffer(struct menu *m) +-{ +- int min_size; +- +- if (m->display) +- min_size = max((int)strlen(m->display), m->width); +- else +- min_size = m->width; +- +- +- if (m->display_buffer) { +- if (m->display_buffer_size >= min_size) +- return 0; +- m->display_buffer = realloc(m->display_buffer, min_size * sizeof(char)); +- } else { +- m->display_buffer = calloc(min_size, sizeof(char)); +- } +- +- if (!m->display_buffer) { +- perror("display_buffer"); +- return -ENOMEM; +- } +- +- m->display_buffer_size = min_size; +- +- return 0; +-} +- + int menu_show(struct menu *m) + { + int ch, ch_previous = 0; +- int escape = 0; + int countdown; + int auto_display_len = 16; + uint64_t start, second; +- int ret; + + if(!m || list_empty(&m->entries)) + return -EINVAL; + +- ret = menu_alloc_display_buffer(m); +- if (ret) +- return ret; +- + print_menu(m); + + countdown = m->auto_select; +@@ -344,41 +303,34 @@ int menu_show(struct menu *m) + gotoXY(m->selected->num + 1, 3); + + do { ++ struct menu_entry *old_selected = m->selected; ++ int repaint = 0; ++ + if (m->auto_select >= 0) + ch = KEY_RETURN; + else +- ch = getc(); ++ ch = read_key(); + + m->auto_select = -1; + +- switch(ch) { +- case 0x1b: +- escape = 1; +- break; +- case '[': +- if (escape) +- break; +- case 'A': /* up */ +- escape = 0; +- print_menu_entry(m, m->selected, 0); ++ switch (ch) { ++ case KEY_UP: + m->selected = list_entry(m->selected->list.prev, struct menu_entry, + list); + if (&(m->selected->list) == &(m->entries)) { + m->selected = list_entry(m->selected->list.prev, struct menu_entry, + list); + } +- print_menu_entry(m, m->selected, 1); ++ repaint = 1; + break; +- case 'B': /* down */ +- escape = 0; +- print_menu_entry(m, m->selected, 0); ++ case KEY_DOWN: + m->selected = list_entry(m->selected->list.next, struct menu_entry, + list); + if (&(m->selected->list) == &(m->entries)) { + m->selected = list_entry(m->selected->list.next, struct menu_entry, + list); + } +- print_menu_entry(m, m->selected, 1); ++ repaint = 1; + break; + case ' ': + if (m->selected->type != MENU_ENTRY_BOX) +@@ -386,7 +338,7 @@ int menu_show(struct menu *m) + m->selected->box_state = !m->selected->box_state; + if (m->selected->action) + m->selected->action(m, m->selected); +- print_menu_entry(m, m->selected, 1); ++ repaint = 1; + break; + case KEY_ENTER: + if (ch_previous == KEY_RETURN) +@@ -401,9 +353,24 @@ int menu_show(struct menu *m) + return m->selected->num; + else + print_menu(m); ++ break; ++ case KEY_HOME: ++ m->selected = list_first_entry(&m->entries, struct menu_entry, list); ++ repaint = 1; ++ break; ++ case KEY_END: ++ m->selected = list_last_entry(&m->entries, struct menu_entry, list); ++ repaint = 1; ++ break; + default: + break; + } ++ ++ if (repaint) { ++ print_menu_entry(m, old_selected, 0); ++ print_menu_entry(m, m->selected, 1); ++ } ++ + ch_previous = ch; + } while(1); + +diff --git a/common/oftree.c b/common/oftree.c +index 49758a9..677e934 100644 +--- a/common/oftree.c ++++ b/common/oftree.c +@@ -207,7 +207,7 @@ int fdt_find_and_setprop(struct fdt_header *fdt, const char *node, + if (nodeoff < 0) + return nodeoff; + +- if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL)) ++ if ((!create) && (fdt_get_property(fdt, nodeoff, prop, NULL) == NULL)) + return 0; /* create flag not set; so exit quietly */ + + return fdt_setprop(fdt, nodeoff, prop, val, len); +diff --git a/common/partitions.c b/common/partitions.c +index 74b4f12..78b09fc 100644 +--- a/common/partitions.c ++++ b/common/partitions.c +@@ -31,6 +31,7 @@ + #include <block.h> + #include <asm/unaligned.h> + #include <disks.h> ++#include <dma.h> + + struct partition { + uint64_t first_sec; +@@ -43,23 +44,6 @@ struct partition_desc { + }; + + /** +- * Reject values which cannot be used in Barebox +- * @param val Value to be check +- * @return 0 if value can be used in Barebox, -EINVAL if not +- * +- * @note this routine can be removed when Barebox uses file offsets larger +- * than 32 bit +- */ +-static int check_offset_value(uint64_t val) +-{ +-#if 1 /* until Barebox can handle 64 bit offsets */ +- if (val > (__INT_MAX__ / SECTOR_SIZE)) +- return -EINVAL; +-#endif +- return 0; +-} +- +-/** + * Guess the size of the disk, based on the partition table entries + * @param dev device to create partitions for + * @param table partition table +@@ -76,12 +60,6 @@ static int disk_guess_size(struct device_d *dev, struct partition_entry *table) + size += get_unaligned(&table[i].partition_size); + } + } +- /* limit disk sector counts we can't handle due to 32 bit limits */ +- if (check_offset_value(size) != 0) { +- dev_warn(dev, "Warning: Sector count limited due to 31 bit" +- "contraints\n"); +- size = __INT_MAX__ / SECTOR_SIZE; +- } + + return (int)size; + } +@@ -102,7 +80,7 @@ static void __maybe_unused try_dos_partition(struct block_device *blk, + struct partition pentry; + int i, rc; + +- buffer = xmalloc(SECTOR_SIZE); ++ buffer = dma_alloc(SECTOR_SIZE); + + /* read in the MBR to get the partition table */ + rc = blk->ops->read(blk, buffer, 0, 1); +@@ -119,19 +97,13 @@ static void __maybe_unused try_dos_partition(struct block_device *blk, + table = (struct partition_entry *)&buffer[446]; + + /* valid for x86 BIOS based disks only */ +- if (blk->num_blocks == 0) ++ if (IS_ENABLED(CONFIG_DISK_BIOS) && blk->num_blocks == 0) + blk->num_blocks = disk_guess_size(blk->dev, table); + + for (i = 0; i < 4; i++) { + pentry.first_sec = get_unaligned(&table[i].partition_start); + pentry.size = get_unaligned(&table[i].partition_size); + +- /* do we have to ignore this partition due to limitations? */ +- if (check_offset_value(pentry.first_sec) != 0) +- continue; +- if (check_offset_value(pentry.size) != 0) +- continue; +- + if (pentry.first_sec != 0) { + pd->parts[pd->used_entries].first_sec = pentry.first_sec; + pd->parts[pd->used_entries].size = pentry.size; +@@ -142,7 +114,7 @@ static void __maybe_unused try_dos_partition(struct block_device *blk, + } + + on_error: +- free(buffer); ++ dma_free(buffer); + } + + /** +diff --git a/common/resource.c b/common/resource.c +index 63e9c49..ce5aa27 100644 +--- a/common/resource.c ++++ b/common/resource.c +@@ -42,16 +42,20 @@ static int init_resource(struct resource *res, const char *name) + */ + struct resource *request_region(struct resource *parent, + const char *name, resource_size_t start, +- resource_size_t size) ++ resource_size_t end) + { + struct resource *r, *new; + ++ if (end < start) { ++ debug("%s: request region 0x%08x:0x%08x: end < start\n", ++ __func__, start, end); ++ return NULL; ++ } ++ + /* outside parent resource? */ +- if (start < parent->start || +- start + size > parent->start + parent->size) { ++ if (start < parent->start || end > parent->end) { + debug("%s: 0x%08x:0x%08x outside parent resource 0x%08x:0x%08x\n", +- __func__, start, size, parent->start, +- parent->size); ++ __func__, start, end, parent->start, parent->end); + return NULL; + } + +@@ -60,22 +64,22 @@ struct resource *request_region(struct resource *parent, + * us searching for conflicts here. + */ + list_for_each_entry(r, &parent->children, sibling) { +- if (start + size <= r->start) ++ if (end < r->start) + goto ok; +- if (start >= r->start + r->size) ++ if (start > r->end) + continue; + debug("%s: 0x%08x:0x%08x conflicts with 0x%08x:0x%08x\n", +- __func__, start, size, r->start, r->size); ++ __func__, start, end, r->start, r->end); + return NULL; + } + + ok: +- debug("%s ok: 0x%08x 0x%08x\n", __func__, start, size); ++ debug("%s ok: 0x%08x:0x%08x\n", __func__, start, end); + + new = xzalloc(sizeof(*new)); + init_resource(new, name); + new->start = start; +- new->size = size; ++ new->end = end; + new->parent = parent; + list_add_tail(&new->sibling, &r->sibling); + +@@ -100,16 +104,16 @@ int release_region(struct resource *res) + /* The root resource for the whole io space */ + struct resource iomem_resource = { + .start = 0, +- .size = ~0, ++ .end = 0xffffffff, + }; + + /* + * request a region inside the io space + */ + struct resource *request_iomem_region(const char *name, +- resource_size_t start, resource_size_t size) ++ resource_size_t start, resource_size_t end) + { +- return request_region(&iomem_resource, name, start, size); ++ return request_region(&iomem_resource, name, start, end); + } + + static int iomem_init(void) +diff --git a/common/tlsf.c b/common/tlsf.c +index c810e8d..9515ac7 100644 +--- a/common/tlsf.c ++++ b/common/tlsf.c +@@ -367,7 +367,7 @@ static block_header_t* search_suitable_block(pool_t* pool, int* fli, int* sli) + if (!fl_map) + { + /* No free blocks available, memory has been exhausted. */ +- return 0; ++ return NULL; + } + + fl = tlsf_ffs(fl_map); +@@ -563,7 +563,7 @@ static block_header_t* block_trim_free_leading(pool_t* pool, block_header_t* blo + static block_header_t* block_locate_free(pool_t* pool, size_t size) + { + int fl = 0, sl = 0; +- block_header_t* block = 0; ++ block_header_t* block = NULL; + + if (size) + { +@@ -582,7 +582,7 @@ static block_header_t* block_locate_free(pool_t* pool, size_t size) + + static void* block_prepare_used(pool_t* pool, block_header_t* block, size_t size) + { +- void* p = 0; ++ void* p = NULL; + if (block) + { + block_trim_free(pool, block, size); +@@ -737,7 +737,7 @@ size_t tlsf_block_size(void* ptr) + ** tlsf_create, equal to the size of a pool_t plus overhead of the initial + ** free block and the sentinel block. + */ +-size_t tlsf_overhead() ++size_t tlsf_overhead(void) + { + const size_t pool_overhead = sizeof(pool_t) + 2 * block_header_overhead; + return pool_overhead; +@@ -790,7 +790,7 @@ tlsf_pool tlsf_create(void* mem, size_t bytes) + (unsigned int)(pool_overhead + block_size_min), + (unsigned int)(pool_overhead + block_size_max)); + #endif +- return 0; ++ return NULL; + } + + /* Construct a valid pool object. */ +@@ -915,7 +915,7 @@ void tlsf_free(tlsf_pool tlsf, void* ptr) + void* tlsf_realloc(tlsf_pool tlsf, void* ptr, size_t size) + { + pool_t* pool = tlsf_cast(pool_t*, tlsf); +- void* p = 0; ++ void* p = NULL; + + /* Zero-size requests are treated as free. */ + if (ptr && size == 0) +diff --git a/common/uimage.c b/common/uimage.c +index 945f3d6..43878b5 100644 +--- a/common/uimage.c ++++ b/common/uimage.c +@@ -354,9 +354,9 @@ static struct resource *uimage_resource; + + static int uimage_sdram_flush(void *buf, unsigned int len) + { +- if (uimage_size + len > uimage_resource->size) { +- resource_size_t start = uimage_resource->start; +- resource_size_t size = uimage_resource->size + len; ++ if (uimage_size + len > resource_size(uimage_resource)) { ++ resource_size_t start = resource_size(uimage_resource); ++ resource_size_t size = resource_size(uimage_resource) + len; + release_sdram_region(uimage_resource); + + uimage_resource = request_sdram_region("uimage", +diff --git a/defaultenv-2/base/bin/ifup b/defaultenv-2/base/bin/ifup +index 9f6fd6b..37b986c 100644 +--- a/defaultenv-2/base/bin/ifup ++++ b/defaultenv-2/base/bin/ifup +@@ -51,9 +51,17 @@ if [ "$ip" = static ]; then + ${interface}.netmask=$netmask + ${interface}.serverip=$serverip + ${interface}.gateway=$gateway ++ ret=0 + elif [ "$ip" = dhcp ]; then + dhcp +- exit $? ++ ret=$? ++ if [ $ret = 0 -a -n "$serverip" ]; then ++ ${interface}.serverip=$serverip ++ fi ++fi ++ ++if [ $ret = 0 ]; then ++ echo -o /tmp/network/$interface up + fi + +-echo -o /tmp/network/$interface up ++exit $ret +diff --git a/defaultenv-2/base/bin/init b/defaultenv-2/base/bin/init +index e293c62..9d7eb2e 100644 +--- a/defaultenv-2/base/bin/init ++++ b/defaultenv-2/base/bin/init +@@ -4,8 +4,6 @@ export PATH=/env/bin + + global hostname=generic + global user=none +-global tftp.server +-global tftp.path=/mnt/tftp-dhcp + global autoboot_timeout=3 + global boot.default=net + global allow_color=true +diff --git a/defaultenv-2/base/boot/initrd b/defaultenv-2/base/boot/initrd +index 1a1e629..79a353a 100644 +--- a/defaultenv-2/base/boot/initrd ++++ b/defaultenv-2/base/boot/initrd +@@ -5,8 +5,9 @@ if [ "$1" = menu ]; then + exit + fi + +-global.bootm.image="${global.tftp.path}/${global.user}-linux-${global.hostname}" +-global.bootm.initrd="${global.tftp.path}/initramfs" ++path="/mnt/tftp" ++global.bootm.image="${path}/${global.user}-linux-${global.hostname}" ++global.bootm.initrd="${path}/initramfs" + bootargs-root-initrd + #global.bootm.oftree=<path to oftree> + +diff --git a/defaultenv-2/base/boot/net b/defaultenv-2/base/boot/net +index 2684c20..922bef1 100644 +--- a/defaultenv-2/base/boot/net ++++ b/defaultenv-2/base/boot/net +@@ -5,8 +5,10 @@ if [ "$1" = menu ]; then + exit + fi + +-global.bootm.image="${global.tftp.path}/${global.user}-linux-${global.hostname}" +-#global.bootm.oftree="${global.tftp.path}/${global.user}-oftree-${global.hostname}" ++path="/mnt/tftp" ++ ++global.bootm.image="${path}/${global.user}-linux-${global.hostname}" ++#global.bootm.oftree="${path}/${global.user}-oftree-${global.hostname}" + nfsroot="/home/${global.user}/nfsroot/${global.hostname}" + bootargs-ip + bootargs-root-nfs -n "$nfsroot" +diff --git a/defaultenv-2/base/init/automount b/defaultenv-2/base/init/automount +index 63099f9..7b53309 100644 +--- a/defaultenv-2/base/init/automount ++++ b/defaultenv-2/base/init/automount +@@ -5,10 +5,10 @@ if [ "$1" = menu ]; then + exit + fi + +-# automount server returned from dhcp server ++# automount tftp server based on $eth0.serverip + +-mkdir -p /mnt/tftp-dhcp +-automount /mnt/tftp-dhcp 'ifup eth0 && mount $eth0.serverip tftp /mnt/tftp-dhcp' ++mkdir -p /mnt/tftp ++automount /mnt/tftp 'ifup eth0 && mount $eth0.serverip tftp /mnt/tftp' + + # automount nfs server example + +@@ -16,11 +16,6 @@ automount /mnt/tftp-dhcp 'ifup eth0 && mount $eth0.serverip tftp /mnt/tftp-dhcp' + #mkdir -p /mnt/${nfshost} + #automount /mnt/$nfshost "ifup eth0 && mount ${nfshost}:/tftpboot nfs /mnt/${nfshost}" + +-# static tftp server example +- +-#mkdir -p /mnt/tftp +-#automount -d /mnt/tftp 'ifup eth0 && mount $serverip tftp /mnt/tftp' +- + # FAT on usb disk example + + #mkdir -p /mnt/fat +diff --git a/defaultenv-2/base/init/general b/defaultenv-2/base/init/general +index ad6c860..98a92d1 100644 +--- a/defaultenv-2/base/init/general ++++ b/defaultenv-2/base/init/general +@@ -13,6 +13,3 @@ global.autoboot_timeout=3 + + # default boot entry (one of /env/boot/*) + global.boot.default=net +- +-# default tftp path +-global.tftp.path=/mnt/tftp-dhcp +diff --git a/defaultenv/bin/init b/defaultenv/bin/init +index 6e85a82..f535e37 100644 +--- a/defaultenv/bin/init ++++ b/defaultenv/bin/init +@@ -23,7 +23,7 @@ fi + + if [ -f /env/bin/boot_board ]; then + . /env/bin/boot_board +-else ++elif [ -n $autoboot_timeout ]; then + echo + echo -n "Hit any key to stop autoboot: " + timeout -a $autoboot_timeout +diff --git a/drivers/Kconfig b/drivers/Kconfig +index c52c56a..883b0e7 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -15,7 +15,8 @@ source "drivers/mfd/Kconfig" + source "drivers/led/Kconfig" + source "drivers/eeprom/Kconfig" + source "drivers/input/Kconfig" +- ++source "drivers/watchdog/Kconfig" + source "drivers/pwm/Kconfig" ++source "drivers/dma/Kconfig" + + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 3aefc12..ea3263f 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -15,3 +15,5 @@ obj-$(CONFIG_LED) += led/ + obj-y += eeprom/ + obj-$(CONFIG_PWM) += pwm/ + obj-y += input/ ++obj-y += dma/ ++obj-y += watchdog/ +diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c +index 4602af3..d5c5837 100644 +--- a/drivers/ata/disk_ata_drive.c ++++ b/drivers/ata/disk_ata_drive.c +@@ -231,7 +231,7 @@ static void __maybe_unused ata_dump_id(uint16_t *id) + */ + static void ata_fix_endianess(uint16_t *buf, unsigned wds) + { +-#if __BYTE_ORDER == __BIG_ENDIAN ++#ifdef __BIG_ENDIAN + unsigned u; + + for (u = 0; u < wds; u++) +diff --git a/drivers/base/driver.c b/drivers/base/driver.c +index 81cedca..6cd4286 100644 +--- a/drivers/base/driver.c ++++ b/drivers/base/driver.c +@@ -241,15 +241,15 @@ static struct resource *dev_get_resource(struct device_d *dev, int num) + return NULL; + } + +-void __iomem *dev_get_mem_region(struct device_d *dev, int num) ++void *dev_get_mem_region(struct device_d *dev, int num) + { + struct resource *res; + + res = dev_get_resource(dev, num); + if (!res) +- return res; ++ return NULL; + +- return (void __force __iomem *)res->start; ++ return (void __force *)res->start; + } + EXPORT_SYMBOL(dev_get_mem_region); + +@@ -261,7 +261,7 @@ void __iomem *dev_request_mem_region(struct device_d *dev, int num) + if (!res) + return NULL; + +- res = request_iomem_region(dev_name(dev), res->start, res->size); ++ res = request_iomem_region(dev_name(dev), res->start, res->end); + if (!res) + return NULL; + +@@ -339,7 +339,7 @@ static int do_devinfo_subtree(struct device_d *dev, int depth) + list_for_each_entry(cdev, &dev->cdevs, devices_list) { + for (i = 0; i < depth + 1; i++) + printf(" "); +- printf("`---- 0x%08lx-0x%08lx: /dev/%s\n", ++ printf("`---- 0x%08llx-0x%08llx: /dev/%s\n", + cdev->offset, + cdev->offset + cdev->size - 1, + cdev->name); +@@ -392,7 +392,7 @@ static int do_devinfo(int argc, char *argv[]) + printf("name : %s\n", res->name); + printf("start : " PRINTF_CONVERSION_RESOURCE "\nsize : " + PRINTF_CONVERSION_RESOURCE "\n", +- res->start, res->size); ++ res->start, resource_size(res)); + } + + printf("driver: %s\n\n", dev->driver ? +diff --git a/drivers/base/resource.c b/drivers/base/resource.c +index 9844d1a..988d27e 100644 +--- a/drivers/base/resource.c ++++ b/drivers/base/resource.c +@@ -47,7 +47,7 @@ struct device_d *add_generic_device(const char* devname, int id, const char *res + if (resname) + res[0].name = xstrdup(resname); + res[0].start = start; +- res[0].size = size; ++ res[0].end = start + size - 1; + res[0].flags = flags; + + return add_generic_device_res(devname, id, res, 1, pdata); +@@ -94,10 +94,10 @@ struct device_d *add_dm9000_device(int id, resource_size_t base, + } + + res[0].start = base; +- res[0].size = size; ++ res[0].end = base + size - 1; + res[0].flags = IORESOURCE_MEM | flags; + res[1].start = data; +- res[1].size = size; ++ res[1].end = data + size - 1; + res[1].flags = IORESOURCE_MEM | flags; + + return add_generic_device_res("dm9000", id, res, 2, pdata); +@@ -113,10 +113,10 @@ struct device_d *add_usb_ehci_device(int id, resource_size_t hccr, + + res = xzalloc(sizeof(struct resource) * 2); + res[0].start = hccr; +- res[0].size = 0x10; ++ res[0].end = hccr + 0x10 - 1; + res[0].flags = IORESOURCE_MEM; + res[1].start = hcor; +- res[1].size = 0xc0; ++ res[1].end = hcor + 0xc0 - 1; + res[1].flags = IORESOURCE_MEM; + + return add_generic_device_res("ehci", id, res, 2, pdata); +@@ -146,10 +146,10 @@ struct device_d *add_ks8851_device(int id, resource_size_t addr, + res = xzalloc(sizeof(struct resource) * 2); + + res[0].start = addr; +- res[0].size = size; ++ res[0].end = addr + size - 1; + res[0].flags = IORESOURCE_MEM | flags; + res[1].start = addr_cmd; +- res[1].size = size; ++ res[1].end = addr_cmd + size - 1; + res[1].flags = IORESOURCE_MEM | flags; + + return add_generic_device_res("ks8851_mll", id, res, 2, pdata); +diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig +new file mode 100644 +index 0000000..ec6c894 +--- /dev/null ++++ b/drivers/dma/Kconfig +@@ -0,0 +1,8 @@ ++menu "DMA support" ++ ++config MXS_APBH_DMA ++ tristate "MXS APBH DMA ENGINE" ++ depends on ARCH_IMX23 || ARCH_IMX28 ++ help ++ Experimental! ++endmenu +diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile +new file mode 100644 +index 0000000..7a3a3b2 +--- /dev/null ++++ b/drivers/dma/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_MXS_APBH_DMA) += apbh_dma.o +diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c +new file mode 100644 +index 0000000..363878f +--- /dev/null ++++ b/drivers/dma/apbh_dma.c +@@ -0,0 +1,598 @@ ++/* ++ * Freescale i.MX28 APBH DMA driver ++ * ++ * Copyright (C) 2011 Wolfram Sang <w.sang@pengutronix.de> ++ * ++ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> ++ * on behalf of DENX Software Engineering GmbH ++ * ++ * Based on code from LTIB: ++ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. ++ * ++ * 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. ++ */ ++ ++#include <linux/list.h> ++ ++#include <common.h> ++#include <malloc.h> ++#include <errno.h> ++#include <asm/mmu.h> ++#include <asm/io.h> ++#include <mach/clock.h> ++#include <mach/imx-regs.h> ++#include <mach/dma.h> ++#include <mach/mxs.h> ++ ++#define HW_APBHX_CTRL0 0x000 ++#define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29) ++#define BM_APBH_CTRL0_APB_BURST_EN (1 << 28) ++#define BP_APBH_CTRL0_CLKGATE_CHANNEL 8 ++#define BP_APBH_CTRL0_RESET_CHANNEL 16 ++#define HW_APBHX_CTRL1 0x010 ++#define BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN 16 ++#define HW_APBHX_CTRL2 0x020 ++#define HW_APBHX_CHANNEL_CTRL 0x030 ++#define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16 ++#define HW_APBH_VERSION (cpu_is_mx23() ? 0x3f0 : 0x800) ++#define HW_APBX_VERSION 0x800 ++#define BP_APBHX_VERSION_MAJOR 24 ++#define HW_APBHX_CHn_NXTCMDAR(n) \ ++ ((apbh_is_old ? 0x050 : 0x110) + (n) * 0x70) ++#define HW_APBHX_CHn_SEMA(n) \ ++ ((apbh_is_old ? 0x080 : 0x140) + (n) * 0x70) ++#define BM_APBHX_CHn_SEMA_PHORE (0xff << 16) ++#define BP_APBHX_CHn_SEMA_PHORE 16 ++ ++static struct mxs_dma_chan mxs_dma_channels[MXS_MAX_DMA_CHANNELS]; ++static bool apbh_is_old; ++ ++/* ++ * Test is the DMA channel is valid channel ++ */ ++int mxs_dma_validate_chan(int channel) ++{ ++ struct mxs_dma_chan *pchan; ++ ++ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS)) ++ return -EINVAL; ++ ++ pchan = mxs_dma_channels + channel; ++ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/* ++ * Return the address of the command within a descriptor. ++ */ ++static unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc) ++{ ++ return desc->address + offsetof(struct mxs_dma_desc, cmd); ++} ++ ++/* ++ * Read a DMA channel's hardware semaphore. ++ * ++ * As used by the MXS platform's DMA software, the DMA channel's hardware ++ * semaphore reflects the number of DMA commands the hardware will process, but ++ * has not yet finished. This is a volatile value read directly from hardware, ++ * so it must be be viewed as immediately stale. ++ * ++ * If the channel is not marked busy, or has finished processing all its ++ * commands, this value should be zero. ++ * ++ * See mxs_dma_append() for details on how DMA command blocks must be configured ++ * to maintain the expected behavior of the semaphore's value. ++ */ ++static int mxs_dma_read_semaphore(int channel) ++{ ++ void __iomem *apbh_regs = (void *)MXS_APBH_BASE; ++ uint32_t tmp; ++ int ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ tmp = readl(apbh_regs + HW_APBHX_CHn_SEMA(channel)); ++ ++ tmp &= BM_APBHX_CHn_SEMA_PHORE; ++ tmp >>= BP_APBHX_CHn_SEMA_PHORE; ++ ++ return tmp; ++} ++ ++/* ++ * Enable a DMA channel. ++ * ++ * If the given channel has any DMA descriptors on its active list, this ++ * function causes the DMA hardware to begin processing them. ++ * ++ * This function marks the DMA channel as "busy," whether or not there are any ++ * descriptors to process. ++ */ ++static int mxs_dma_enable(int channel) ++{ ++ void __iomem *apbh_regs = (void *)MXS_APBH_BASE; ++ unsigned int sem; ++ struct mxs_dma_chan *pchan; ++ struct mxs_dma_desc *pdesc; ++ int channel_bit, ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ pchan = mxs_dma_channels + channel; ++ ++ if (pchan->pending_num == 0) { ++ pchan->flags |= MXS_DMA_FLAGS_BUSY; ++ return 0; ++ } ++ ++ pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node); ++ if (pdesc == NULL) ++ return -EFAULT; ++ ++ if (pchan->flags & MXS_DMA_FLAGS_BUSY) { ++ if (!(pdesc->cmd.data & MXS_DMA_DESC_CHAIN)) ++ return 0; ++ ++ sem = mxs_dma_read_semaphore(channel); ++ if (sem == 0) ++ return 0; ++ ++ if (sem == 1) { ++ pdesc = list_entry(pdesc->node.next, ++ struct mxs_dma_desc, node); ++ writel(mxs_dma_cmd_address(pdesc), ++ apbh_regs + HW_APBHX_CHn_NXTCMDAR(channel)); ++ } ++ writel(pchan->pending_num, ++ apbh_regs + HW_APBHX_CHn_SEMA(channel)); ++ pchan->active_num += pchan->pending_num; ++ pchan->pending_num = 0; ++ } else { ++ pchan->active_num += pchan->pending_num; ++ pchan->pending_num = 0; ++ writel(mxs_dma_cmd_address(pdesc), ++ apbh_regs + HW_APBHX_CHn_NXTCMDAR(channel)); ++ writel(pchan->active_num, ++ apbh_regs + HW_APBHX_CHn_SEMA(channel)); ++ channel_bit = channel + (apbh_is_old ? BP_APBH_CTRL0_CLKGATE_CHANNEL : 0); ++ writel(1 << channel_bit, apbh_regs + HW_APBHX_CTRL0 + BIT_CLR); ++ } ++ ++ pchan->flags |= MXS_DMA_FLAGS_BUSY; ++ return 0; ++} ++ ++/* ++ * Disable a DMA channel. ++ * ++ * This function shuts down a DMA channel and marks it as "not busy." Any ++ * descriptors on the active list are immediately moved to the head of the ++ * "done" list, whether or not they have actually been processed by the ++ * hardware. The "ready" flags of these descriptors are NOT cleared, so they ++ * still appear to be active. ++ * ++ * This function immediately shuts down a DMA channel's hardware, aborting any ++ * I/O that may be in progress, potentially leaving I/O hardware in an undefined ++ * state. It is unwise to call this function if there is ANY chance the hardware ++ * is still processing a command. ++ */ ++static int mxs_dma_disable(int channel) ++{ ++ struct mxs_dma_chan *pchan; ++ void __iomem *apbh_regs = (void *)MXS_APBH_BASE; ++ int channel_bit, ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ pchan = mxs_dma_channels + channel; ++ ++ if (!(pchan->flags & MXS_DMA_FLAGS_BUSY)) ++ return -EINVAL; ++ ++ channel_bit = channel + (apbh_is_old ? BP_APBH_CTRL0_CLKGATE_CHANNEL : 0); ++ writel(1 << channel_bit, apbh_regs + HW_APBHX_CTRL0 + BIT_SET); ++ ++ pchan->flags &= ~MXS_DMA_FLAGS_BUSY; ++ pchan->active_num = 0; ++ pchan->pending_num = 0; ++ list_splice_init(&pchan->active, &pchan->done); ++ ++ return 0; ++} ++ ++/* ++ * Resets the DMA channel hardware. ++ */ ++static int mxs_dma_reset(int channel) ++{ ++ void __iomem *apbh_regs = (void *)MXS_APBH_BASE; ++ int ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ if (apbh_is_old) ++ writel(1 << (channel + BP_APBH_CTRL0_RESET_CHANNEL), ++ apbh_regs + HW_APBHX_CTRL0 + BIT_SET); ++ else ++ writel(1 << (channel + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL), ++ apbh_regs + HW_APBHX_CHANNEL_CTRL + BIT_SET); ++ ++ return 0; ++} ++ ++/* ++ * Enable or disable DMA interrupt. ++ * ++ * This function enables the given DMA channel to interrupt the CPU. ++ */ ++static int mxs_dma_enable_irq(int channel, int enable) ++{ ++ void __iomem *apbh_regs = (void *)MXS_APBH_BASE; ++ int ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ if (enable) ++ writel(1 << (channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN), ++ apbh_regs + HW_APBHX_CTRL1 + BIT_SET); ++ else ++ writel(1 << (channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN), ++ apbh_regs + HW_APBHX_CTRL1 + BIT_CLR); ++ ++ return 0; ++} ++ ++/* ++ * Clear DMA interrupt. ++ * ++ * The software that is using the DMA channel must register to receive its ++ * interrupts and, when they arrive, must call this function to clear them. ++ */ ++static int mxs_dma_ack_irq(int channel) ++{ ++ void __iomem *apbh_regs = (void *)MXS_APBH_BASE; ++ int ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ writel(1 << channel, apbh_regs + HW_APBHX_CTRL1 + BIT_CLR); ++ writel(1 << channel, apbh_regs + HW_APBHX_CTRL2 + BIT_CLR); ++ ++ return 0; ++} ++ ++/* ++ * Request to reserve a DMA channel ++ */ ++static int mxs_dma_request(int channel) ++{ ++ struct mxs_dma_chan *pchan; ++ ++ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS)) ++ return -EINVAL; ++ ++ pchan = mxs_dma_channels + channel; ++ if ((pchan->flags & MXS_DMA_FLAGS_VALID) != MXS_DMA_FLAGS_VALID) ++ return -ENODEV; ++ ++ if (pchan->flags & MXS_DMA_FLAGS_ALLOCATED) ++ return -EBUSY; ++ ++ pchan->flags |= MXS_DMA_FLAGS_ALLOCATED; ++ pchan->active_num = 0; ++ pchan->pending_num = 0; ++ ++ INIT_LIST_HEAD(&pchan->active); ++ INIT_LIST_HEAD(&pchan->done); ++ ++ return 0; ++} ++ ++/* ++ * Release a DMA channel. ++ * ++ * This function releases a DMA channel from its current owner. ++ * ++ * The channel will NOT be released if it's marked "busy" (see ++ * mxs_dma_enable()). ++ */ ++static int mxs_dma_release(int channel) ++{ ++ struct mxs_dma_chan *pchan; ++ int ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ pchan = mxs_dma_channels + channel; ++ ++ if (pchan->flags & MXS_DMA_FLAGS_BUSY) ++ return -EBUSY; ++ ++ pchan->dev = 0; ++ pchan->active_num = 0; ++ pchan->pending_num = 0; ++ pchan->flags &= ~MXS_DMA_FLAGS_ALLOCATED; ++ ++ return 0; ++} ++ ++/* ++ * Allocate DMA descriptor ++ */ ++struct mxs_dma_desc *mxs_dma_desc_alloc(void) ++{ ++ struct mxs_dma_desc *pdesc; ++ ++ pdesc = dma_alloc_coherent(sizeof(struct mxs_dma_desc)); ++ ++ if (pdesc == NULL) ++ return NULL; ++ ++ memset(pdesc, 0, sizeof(*pdesc)); ++ pdesc->address = (dma_addr_t)pdesc; ++ ++ return pdesc; ++}; ++ ++/* ++ * Free DMA descriptor ++ */ ++void mxs_dma_desc_free(struct mxs_dma_desc *pdesc) ++{ ++ if (pdesc == NULL) ++ return; ++ ++ free(pdesc); ++} ++ ++/* ++ * Add a DMA descriptor to a channel. ++ * ++ * If the descriptor list for this channel is not empty, this function sets the ++ * CHAIN bit and the NEXTCMD_ADDR fields in the last descriptor's DMA command so ++ * it will chain to the new descriptor's command. ++ * ++ * Then, this function marks the new descriptor as "ready," adds it to the end ++ * of the active descriptor list, and increments the count of pending ++ * descriptors. ++ * ++ * The MXS platform DMA software imposes some rules on DMA commands to maintain ++ * important invariants. These rules are NOT checked, but they must be carefully ++ * applied by software that uses MXS DMA channels. ++ * ++ * Invariant: ++ * The DMA channel's hardware semaphore must reflect the number of DMA ++ * commands the hardware will process, but has not yet finished. ++ * ++ * Explanation: ++ * A DMA channel begins processing commands when its hardware semaphore is ++ * written with a value greater than zero, and it stops processing commands ++ * when the semaphore returns to zero. ++ * ++ * When a channel finishes a DMA command, it will decrement its semaphore if ++ * the DECREMENT_SEMAPHORE bit is set in that command's flags bits. ++ * ++ * In principle, it's not necessary for the DECREMENT_SEMAPHORE to be set, ++ * unless it suits the purposes of the software. For example, one could ++ * construct a series of five DMA commands, with the DECREMENT_SEMAPHORE ++ * bit set only in the last one. Then, setting the DMA channel's hardware ++ * semaphore to one would cause the entire series of five commands to be ++ * processed. However, this example would violate the invariant given above. ++ * ++ * Rule: ++ * ALL DMA commands MUST have the DECREMENT_SEMAPHORE bit set so that the DMA ++ * channel's hardware semaphore will be decremented EVERY time a command is ++ * processed. ++ */ ++int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc) ++{ ++ struct mxs_dma_chan *pchan; ++ struct mxs_dma_desc *last; ++ int ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ pchan = mxs_dma_channels + channel; ++ ++ pdesc->cmd.next = mxs_dma_cmd_address(pdesc); ++ pdesc->flags |= MXS_DMA_DESC_FIRST | MXS_DMA_DESC_LAST; ++ ++ if (!list_empty(&pchan->active)) { ++ last = list_entry(pchan->active.prev, struct mxs_dma_desc, ++ node); ++ ++ pdesc->flags &= ~MXS_DMA_DESC_FIRST; ++ last->flags &= ~MXS_DMA_DESC_LAST; ++ ++ last->cmd.next = mxs_dma_cmd_address(pdesc); ++ last->cmd.data |= MXS_DMA_DESC_CHAIN; ++ } ++ pdesc->flags |= MXS_DMA_DESC_READY; ++ if (pdesc->flags & MXS_DMA_DESC_FIRST) ++ pchan->pending_num++; ++ list_add_tail(&pdesc->node, &pchan->active); ++ ++ return ret; ++} ++ ++/* ++ * Clean up processed DMA descriptors. ++ * ++ * This function removes processed DMA descriptors from the "active" list. Pass ++ * in a non-NULL list head to get the descriptors moved to your list. Pass NULL ++ * to get the descriptors moved to the channel's "done" list. Descriptors on ++ * the "done" list can be retrieved with mxs_dma_get_finished(). ++ * ++ * This function marks the DMA channel as "not busy" if no unprocessed ++ * descriptors remain on the "active" list. ++ */ ++static int mxs_dma_finish(int channel, struct list_head *head) ++{ ++ int sem; ++ struct mxs_dma_chan *pchan; ++ struct list_head *p, *q; ++ struct mxs_dma_desc *pdesc; ++ int ret; ++ ++ ret = mxs_dma_validate_chan(channel); ++ if (ret) ++ return ret; ++ ++ pchan = mxs_dma_channels + channel; ++ ++ sem = mxs_dma_read_semaphore(channel); ++ if (sem < 0) ++ return sem; ++ ++ if (sem == pchan->active_num) ++ return 0; ++ ++ list_for_each_safe(p, q, &pchan->active) { ++ if ((pchan->active_num) <= sem) ++ break; ++ ++ pdesc = list_entry(p, struct mxs_dma_desc, node); ++ pdesc->flags &= ~MXS_DMA_DESC_READY; ++ ++ if (head) ++ list_move_tail(p, head); ++ else ++ list_move_tail(p, &pchan->done); ++ ++ if (pdesc->flags & MXS_DMA_DESC_LAST) ++ pchan->active_num--; ++ } ++ ++ if (sem == 0) ++ pchan->flags &= ~MXS_DMA_FLAGS_BUSY; ++ ++ return 0; ++} ++ ++/* ++ * Wait for DMA channel to complete ++ */ ++static int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan) ++{ ++ void __iomem *apbh_regs = (void *)MXS_APBH_BASE; ++ int ret; ++ ++ ret = mxs_dma_validate_chan(chan); ++ if (ret) ++ return ret; ++ ++ while (--timeout) { ++ if (readl(apbh_regs + HW_APBHX_CTRL1) & (1 << chan)) ++ break; ++ udelay(1); ++ } ++ ++ if (timeout == 0) { ++ ret = -ETIMEDOUT; ++ mxs_dma_reset(chan); ++ } ++ ++ return ret; ++} ++ ++/* ++ * Execute the DMA channel ++ */ ++int mxs_dma_go(int chan) ++{ ++ uint32_t timeout = 10000; ++ int ret; ++ ++ LIST_HEAD(tmp_desc_list); ++ ++ mxs_dma_enable_irq(chan, 1); ++ mxs_dma_enable(chan); ++ ++ /* Wait for DMA to finish. */ ++ ret = mxs_dma_wait_complete(timeout, chan); ++ ++ /* Clear out the descriptors we just ran. */ ++ mxs_dma_finish(chan, &tmp_desc_list); ++ ++ /* Shut the DMA channel down. */ ++ mxs_dma_ack_irq(chan); ++ mxs_dma_reset(chan); ++ mxs_dma_enable_irq(chan, 0); ++ mxs_dma_disable(chan); ++ ++ return ret; ++} ++ ++/* ++ * Initialize the DMA hardware ++ */ ++int mxs_dma_init(void) ++{ ++ void __iomem *apbh_regs = (void *)MXS_APBH_BASE; ++ struct mxs_dma_chan *pchan; ++ int ret, channel; ++ u32 val, reg; ++ ++ mxs_reset_block(apbh_regs, 0); ++ ++ /* HACK: Get CPUID and determine APBH version */ ++ val = readl(0x8001c310) >> 16; ++ if (val == 0x2800) ++ reg = MXS_APBH_BASE + 0x0800; ++ else ++ reg = MXS_APBH_BASE + 0x03f0; ++ ++ apbh_is_old = (readl((void *)reg) >> 24) < 3; ++ ++ writel(BM_APBH_CTRL0_APB_BURST8_EN, ++ apbh_regs + HW_APBHX_CTRL0 + BIT_SET); ++ ++ writel(BM_APBH_CTRL0_APB_BURST_EN, ++ apbh_regs + HW_APBHX_CTRL0 + BIT_SET); ++ ++ for (channel = 0; channel < MXS_MAX_DMA_CHANNELS; channel++) { ++ pchan = mxs_dma_channels + channel; ++ pchan->flags = MXS_DMA_FLAGS_VALID; ++ ++ ret = mxs_dma_request(channel); ++ ++ if (ret) { ++ printf("MXS DMA: Can't acquire DMA channel %i\n", ++ channel); ++ ++ goto err; ++ } ++ ++ mxs_dma_reset(channel); ++ mxs_dma_ack_irq(channel); ++ } ++ ++ return 0; ++ ++err: ++ while (--channel >= 0) ++ mxs_dma_release(channel); ++ return ret; ++} +diff --git a/drivers/eeprom/at25.c b/drivers/eeprom/at25.c +index 8a979d5..03d191e 100644 +--- a/drivers/eeprom/at25.c ++++ b/drivers/eeprom/at25.c +@@ -67,7 +67,7 @@ struct at25_data { + static ssize_t at25_ee_read(struct cdev *cdev, + void *buf, + size_t count, +- ulong offset, ++ loff_t offset, + ulong flags) + { + u8 command[EE_MAXADDRLEN + 1]; +@@ -117,7 +117,7 @@ static ssize_t at25_ee_read(struct cdev *cdev, + */ + status = spi_sync(at25->spi, &m); + dev_dbg(at25->cdev.dev, +- "read %d bytes at %lu --> %d\n", ++ "read %d bytes at %llu --> %d\n", + count, offset, (int) status); + + return status ? status : count; +@@ -126,7 +126,7 @@ static ssize_t at25_ee_read(struct cdev *cdev, + static ssize_t at25_ee_write(struct cdev *cdev, + const void *buf, + size_t count, +- ulong off, ++ loff_t off, + ulong flags) + { + ssize_t status = 0; +@@ -232,7 +232,7 @@ static ssize_t at25_ee_write(struct cdev *cdev, + return written ? written : status; + } + +-static off_t at25_ee_lseek(struct cdev *cdev, off_t off) ++static loff_t at25_ee_lseek(struct cdev *cdev, loff_t off) + { + return off; + } +diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c +index ae3c805..585cab9 100644 +--- a/drivers/mci/imx-esdhc.c ++++ b/drivers/mci/imx-esdhc.c +@@ -70,7 +70,7 @@ struct fsl_esdhc { + + struct fsl_esdhc_host { + struct mci_host mci; +- struct fsl_esdhc *regs; ++ struct fsl_esdhc __iomem *regs; + u32 no_snoop; + unsigned long cur_clock; + struct device_d *dev; +@@ -81,7 +81,7 @@ struct fsl_esdhc_host { + #define SDHCI_CMD_ABORTCMD (0xC0 << 16) + + /* Return the XFERTYP flags for a given command and data packet */ +-u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data) ++static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data) + { + u32 xfertyp = 0; + +@@ -185,7 +185,7 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) + static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data) + { + struct fsl_esdhc_host *host = to_fsl_esdhc(mci); +- struct fsl_esdhc *regs = host->regs; ++ struct fsl_esdhc __iomem *regs = host->regs; + #ifndef CONFIG_MCI_IMX_ESDHC_PIO + u32 wml_value; + +@@ -237,7 +237,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) + u32 xfertyp, mixctrl; + u32 irqstat; + struct fsl_esdhc_host *host = to_fsl_esdhc(mci); +- struct fsl_esdhc *regs = host->regs; ++ struct fsl_esdhc __iomem *regs = host->regs; + int ret; + + esdhc_write32(®s->irqstat, -1); +@@ -353,11 +353,11 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) + return 0; + } + +-void set_sysctl(struct mci_host *mci, u32 clock) ++static void set_sysctl(struct mci_host *mci, u32 clock) + { + int div, pre_div; + struct fsl_esdhc_host *host = to_fsl_esdhc(mci); +- struct fsl_esdhc *regs = host->regs; ++ struct fsl_esdhc __iomem *regs = host->regs; + int sdhc_clk = imx_get_mmcclk(); + u32 clk; + +@@ -400,7 +400,7 @@ void set_sysctl(struct mci_host *mci, u32 clock) + static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios) + { + struct fsl_esdhc_host *host = to_fsl_esdhc(mci); +- struct fsl_esdhc *regs = host->regs; ++ struct fsl_esdhc __iomem *regs = host->regs; + + /* Set the clock speed */ + set_sysctl(mci, ios->clock); +@@ -425,7 +425,7 @@ static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios) + + static int esdhc_card_detect(struct fsl_esdhc_host *host) + { +- struct fsl_esdhc *regs = host->regs; ++ struct fsl_esdhc __iomem *regs = host->regs; + struct esdhc_platform_data *pdata = host->dev->platform_data; + int ret; + +@@ -451,7 +451,7 @@ static int esdhc_card_detect(struct fsl_esdhc_host *host) + static int esdhc_init(struct mci_host *mci, struct device_d *dev) + { + struct fsl_esdhc_host *host = to_fsl_esdhc(mci); +- struct fsl_esdhc *regs = host->regs; ++ struct fsl_esdhc __iomem *regs = host->regs; + int timeout = 1000; + int ret = 0; + +@@ -493,7 +493,7 @@ static int esdhc_init(struct mci_host *mci, struct device_d *dev) + return ret; + } + +-static int esdhc_reset(struct fsl_esdhc *regs) ++static int esdhc_reset(struct fsl_esdhc __iomem *regs) + { + uint64_t start; + +diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h +index 19fed5a..7d5ed85 100644 +--- a/drivers/mci/imx-esdhc.h ++++ b/drivers/mci/imx-esdhc.h +@@ -39,7 +39,6 @@ + #define SYSCTL_PEREN 0x00000004 + #define SYSCTL_HCKEN 0x00000002 + #define SYSCTL_IPGEN 0x00000001 +-#define SYSCTL_RSTA 0x01000000 + + #define IRQSTAT 0x0002e030 + #define IRQSTAT_DMAE (0x10000000) +diff --git a/drivers/mfd/lp3972.c b/drivers/mfd/lp3972.c +index 9826699..0f3093b 100644 +--- a/drivers/mfd/lp3972.c ++++ b/drivers/mfd/lp3972.c +@@ -58,7 +58,7 @@ static u32 lp_read_reg(struct lp_priv *lp, int reg) + return buf; + } + +-static ssize_t lp_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t lp_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) + { + struct lp_priv *priv = to_lp_priv(cdev); + int i = count; +diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c +index f9477a3..2934e9d 100644 +--- a/drivers/mfd/mc13xxx.c ++++ b/drivers/mfd/mc13xxx.c +@@ -160,7 +160,7 @@ int mc13xxx_set_bits(struct mc13xxx *mc13xxx, u8 reg, u32 mask, u32 val) + } + EXPORT_SYMBOL(mc13xxx_set_bits); + +-static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) + { + struct mc13xxx *priv = to_mc13xxx(cdev); + u32 *buf = _buf; +@@ -181,7 +181,7 @@ static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset + return count; + } + +-static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags) + { + struct mc13xxx *mc13xxx = to_mc13xxx(cdev); + const u32 *buf = _buf; +diff --git a/drivers/mfd/mc34704.c b/drivers/mfd/mc34704.c +index a2171b3..20c01e2 100644 +--- a/drivers/mfd/mc34704.c ++++ b/drivers/mfd/mc34704.c +@@ -65,7 +65,7 @@ int mc34704_reg_write(struct mc34704 *mc34704, u8 reg, u8 val) + EXPORT_SYMBOL(mc34704_reg_write) + + static ssize_t mc34704_read(struct cdev *cdev, void *_buf, size_t count, +- ulong offset, ulong flags) ++ loff_t offset, ulong flags) + { + struct mc34704 *priv = to_mc34704(cdev); + u8 *buf = _buf; +@@ -85,7 +85,7 @@ static ssize_t mc34704_read(struct cdev *cdev, void *_buf, size_t count, + } + + static ssize_t mc34704_write(struct cdev *cdev, const void *_buf, size_t count, +- ulong offset, ulong flags) ++ loff_t offset, ulong flags) + { + struct mc34704 *mc34704 = to_mc34704(cdev); + const u8 *buf = _buf; +diff --git a/drivers/mfd/mc34708.c b/drivers/mfd/mc34708.c +index e7f40c0..02c58a9 100644 +--- a/drivers/mfd/mc34708.c ++++ b/drivers/mfd/mc34708.c +@@ -163,7 +163,8 @@ int mc34708_set_bits(struct mc34708 *mc34708, enum mc34708_reg reg, u32 mask, u3 + } + EXPORT_SYMBOL(mc34708_set_bits); + +-static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ++ loff_t offset, ulong flags) + { + struct mc34708 *priv = to_mc34708(cdev); + u32 *buf = _buf; +@@ -184,7 +185,8 @@ static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset + return count; + } + +-static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ++ loff_t offset, ulong flags) + { + struct mc34708 *mc34708 = to_mc34708(cdev); + const u32 *buf = _buf; +diff --git a/drivers/mfd/mc9sdz60.c b/drivers/mfd/mc9sdz60.c +index db208ec..0cd5007 100644 +--- a/drivers/mfd/mc9sdz60.c ++++ b/drivers/mfd/mc9sdz60.c +@@ -78,7 +78,7 @@ int mc9sdz60_set_bits(struct mc9sdz60 *mc9sdz60, enum mc9sdz60_reg reg, u8 mask, + } + EXPORT_SYMBOL(mc9sdz60_set_bits); + +-static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) + { + struct mc9sdz60 *mc9sdz60 = to_mc9sdz60(cdev); + u8 *buf = _buf; +@@ -97,7 +97,7 @@ static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset + return count; + } + +-static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags) + { + struct mc9sdz60 *mc9sdz60 = to_mc9sdz60(cdev); + const u8 *buf = _buf; +diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c +index cb2c03d..20bde2c 100644 +--- a/drivers/mfd/twl-core.c ++++ b/drivers/mfd/twl-core.c +@@ -112,7 +112,7 @@ int twlcore_set_bits(struct twlcore *twlcore, u16 reg, u8 mask, u8 val) + EXPORT_SYMBOL(twlcore_set_bits); + + static ssize_t twl_read(struct cdev *cdev, void *_buf, size_t count, +- ulong offset, ulong flags) ++ loff_t offset, ulong flags) + { + struct twlcore *priv = to_twlcore(cdev); + u8 *buf = _buf; +@@ -131,7 +131,7 @@ static ssize_t twl_read(struct cdev *cdev, void *_buf, size_t count, + } + + static ssize_t twl_write(struct cdev *cdev, const void *_buf, size_t count, +- ulong offset, ulong flags) ++ loff_t offset, ulong flags) + { + struct twlcore *twlcore = to_twlcore(cdev); + const u8 *buf = _buf; +diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c +index 87dcba6..5510439 100644 +--- a/drivers/mtd/core.c ++++ b/drivers/mtd/core.c +@@ -31,11 +31,12 @@ + static LIST_HEAD(mtd_register_hooks); + + static ssize_t mtd_read(struct cdev *cdev, void* buf, size_t count, +- ulong offset, ulong flags) ++ loff_t _offset, ulong flags) + { + struct mtd_info *mtd = cdev->priv; + size_t retlen; + int ret; ++ unsigned long offset = _offset; + + debug("mtd_read: 0x%08lx 0x%08x\n", offset, count); + +@@ -64,13 +65,14 @@ static int all_ff(const void *buf, int len) + } + + static ssize_t mtd_write(struct cdev* cdev, const void *buf, size_t _count, +- ulong offset, ulong flags) ++ loff_t _offset, ulong flags) + { + struct mtd_info *mtd = cdev->priv; + size_t retlen, now; + int ret = 0; + void *wrbuf = NULL; + size_t count = _count; ++ unsigned long offset = _offset; + + if (NOTALIGNED(offset)) { + printf("offset 0x%0lx not page aligned\n", offset); +@@ -123,16 +125,17 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf) + struct mtd_ecc_stats *ecc = buf; + #endif + struct region_info_user *reg = buf; ++ loff_t *offset = buf; + + switch (request) { + case MEMGETBADBLOCK: +- dev_dbg(cdev->dev, "MEMGETBADBLOCK: 0x%08lx\n", (off_t)buf); +- ret = mtd->block_isbad(mtd, (off_t)buf); ++ dev_dbg(cdev->dev, "MEMGETBADBLOCK: 0x%08llx\n", *offset); ++ ret = mtd->block_isbad(mtd, *offset); + break; + #ifdef CONFIG_MTD_WRITE + case MEMSETBADBLOCK: +- dev_dbg(cdev->dev, "MEMSETBADBLOCK: 0x%08lx\n", (off_t)buf); +- ret = mtd->block_markbad(mtd, (off_t)buf); ++ dev_dbg(cdev->dev, "MEMSETBADBLOCK: 0x%08llx\n", *offset); ++ ret = mtd->block_markbad(mtd, *offset); + break; + #endif + case MEMGETINFO: +@@ -156,9 +159,10 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf) + #endif + case MEMGETREGIONINFO: + if (cdev->mtd) { ++ unsigned long size = cdev->size; + reg->offset = cdev->offset; + reg->erasesize = cdev->mtd->erasesize; +- reg->numblocks = cdev->size/reg->erasesize; ++ reg->numblocks = size / reg->erasesize; + reg->regionindex = cdev->mtd->index; + } + break; +@@ -170,7 +174,7 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf) + } + + #ifdef CONFIG_MTD_WRITE +-static ssize_t mtd_erase(struct cdev *cdev, size_t count, unsigned long offset) ++static ssize_t mtd_erase(struct cdev *cdev, size_t count, loff_t offset) + { + struct mtd_info *mtd = cdev->priv; + struct erase_info erase; +diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c +index be656a4..e4dd1a0 100644 +--- a/drivers/mtd/mtdoob.c ++++ b/drivers/mtd/mtdoob.c +@@ -38,11 +38,12 @@ static struct mtd_info *to_mtd(struct cdev *cdev) + } + + static ssize_t mtd_read_oob(struct cdev *cdev, void *buf, size_t count, +- ulong offset, ulong flags) ++ loff_t _offset, ulong flags) + { + struct mtd_info *mtd = to_mtd(cdev); + struct mtd_oob_ops ops; + int ret; ++ unsigned long offset = _offset; + + if (count < mtd->oobsize) + return -EINVAL; +diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c +index 7abe235..24f7358 100644 +--- a/drivers/mtd/mtdraw.c ++++ b/drivers/mtd/mtdraw.c +@@ -116,12 +116,13 @@ err: + } + + static ssize_t mtdraw_read(struct cdev *cdev, void *buf, size_t count, +- ulong offset, ulong flags) ++ loff_t _offset, ulong flags) + { + struct mtd_info *mtd = to_mtd(cdev); + ssize_t retlen = 0, ret = 1, toread; + ulong numpage; + int skip; ++ unsigned long offset = _offset; + + numpage = offset / (mtd->writesize + mtd->oobsize); + skip = offset % (mtd->writesize + mtd->oobsize); +@@ -167,13 +168,14 @@ static void mtdraw_fillbuf(struct mtdraw *mtdraw, const void *src, int nbbytes) + } + + static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, +- ulong offset, ulong flags) ++ loff_t _offset, ulong flags) + { + struct mtdraw *mtdraw = to_mtdraw(cdev); + struct mtd_info *mtd = to_mtd(cdev); + int bsz = mtd->writesize + mtd->oobsize; + ulong numpage; + size_t retlen = 0, tofill; ++ unsigned long offset = _offset; + int ret = 0; + + if (mtdraw->write_fill && +@@ -220,10 +222,11 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, + } + } + +-static ssize_t mtdraw_erase(struct cdev *cdev, size_t count, ulong offset) ++static ssize_t mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset) + { + struct mtd_info *mtd = to_mtd(cdev); + struct erase_info erase; ++ unsigned long offset = _offset; + int ret; + + offset = offset / (mtd->writesize + mtd->oobsize) * mtd->writesize; +diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig +index 926a64b..3f90643 100644 +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -53,6 +53,11 @@ config NAND_IMX + prompt "i.MX NAND driver" + depends on ARCH_IMX + ++config NAND_MXS ++ bool ++ prompt "i.MX23/28 NAND driver" ++ depends on MXS_APBH_DMA ++ + config NAND_OMAP_GPMC + tristate "NAND Flash Support for GPMC based OMAP platforms" + depends on OMAP_GPMC +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index 5c6d8b3..1dcfb76 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -15,3 +15,4 @@ obj-$(CONFIG_NAND_IMX) += nand_imx.o + obj-$(CONFIG_NAND_OMAP_GPMC) += nand_omap_gpmc.o nand_omap_bch_decoder.o + obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o + obj-$(CONFIG_NAND_S3C24XX) += nand_s3c24xx.o ++obj-$(CONFIG_NAND_MXS) += nand_mxs.o +diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c +index bd30438..519337e 100644 +--- a/drivers/mtd/nand/nand-bb.c ++++ b/drivers/mtd/nand/nand-bb.c +@@ -42,9 +42,9 @@ struct nand_bb { + + struct mtd_info_user info; + +- size_t raw_size; +- size_t size; +- off_t offset; ++ loff_t raw_size; ++ loff_t size; ++ loff_t offset; + unsigned long flags; + void *writebuf; + +@@ -54,27 +54,27 @@ struct nand_bb { + }; + + static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count, +- unsigned long offset, ulong flags) ++ loff_t offset, ulong flags) + { + struct nand_bb *bb = cdev->priv; + struct cdev *parent = bb->cdev_parent; + int ret, bytes = 0, now; + +- debug("%s %d %d\n", __func__, offset, count); ++ debug("%s 0x%08llx %d\n", __func__, offset, count); + + while(count) { +- ret = cdev_ioctl(parent, MEMGETBADBLOCK, (void *)bb->offset); ++ ret = cdev_ioctl(parent, MEMGETBADBLOCK, &bb->offset); + if (ret < 0) + return ret; + + if (ret) { +- printf("skipping bad block at 0x%08lx\n", bb->offset); ++ printf("skipping bad block at 0x%08llx\n", bb->offset); + bb->offset += bb->info.erasesize; + continue; + } + + now = min(count, (size_t)(bb->info.erasesize - +- (bb->offset % bb->info.erasesize))); ++ ((size_t)bb->offset % bb->info.erasesize))); + ret = cdev_read(parent, buf, now, bb->offset, 0); + if (ret < 0) + return ret; +@@ -96,15 +96,15 @@ static int nand_bb_write_buf(struct nand_bb *bb, size_t count) + int ret, now; + struct cdev *parent = bb->cdev_parent; + void *buf = bb->writebuf; +- int cur_ofs = bb->offset & ~(BB_WRITEBUF_SIZE - 1); ++ loff_t cur_ofs = bb->offset & ~(BB_WRITEBUF_SIZE - 1); + + while (count) { +- ret = cdev_ioctl(parent, MEMGETBADBLOCK, (void *)cur_ofs); ++ ret = cdev_ioctl(parent, MEMGETBADBLOCK, &cur_ofs); + if (ret < 0) + return ret; + + if (ret) { +- debug("skipping bad block at 0x%08x\n", cur_ofs); ++ debug("skipping bad block at 0x%08llx\n", cur_ofs); + bb->offset += bb->info.erasesize; + cur_ofs += bb->info.erasesize; + continue; +@@ -123,12 +123,12 @@ static int nand_bb_write_buf(struct nand_bb *bb, size_t count) + } + + static ssize_t nand_bb_write(struct cdev *cdev, const void *buf, size_t count, +- unsigned long offset, ulong flags) ++ loff_t offset, ulong flags) + { + struct nand_bb *bb = cdev->priv; + int bytes = count, now, wroffs, ret; + +- debug("%s offset: 0x%08x count: 0x%08x\n", __func__, offset, count); ++ debug("%s offset: 0x%08llx count: 0x%08x\n", __func__, offset, count); + + while (count) { + wroffs = bb->offset % BB_WRITEBUF_SIZE; +@@ -152,7 +152,7 @@ static ssize_t nand_bb_write(struct cdev *cdev, const void *buf, size_t count, + return bytes; + } + +-static int nand_bb_erase(struct cdev *cdev, size_t count, unsigned long offset) ++static int nand_bb_erase(struct cdev *cdev, size_t count, loff_t offset) + { + struct nand_bb *bb = cdev->priv; + +@@ -197,11 +197,11 @@ static int nand_bb_close(struct cdev *cdev) + + static int nand_bb_calc_size(struct nand_bb *bb) + { +- ulong pos = 0; ++ loff_t pos = 0; + int ret; + + while (pos < bb->raw_size) { +- ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, (void *)pos); ++ ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, &pos); + if (ret < 0) + return ret; + if (!ret) +@@ -213,10 +213,10 @@ static int nand_bb_calc_size(struct nand_bb *bb) + return 0; + } + +-static off_t nand_bb_lseek(struct cdev *cdev, off_t __offset) ++static loff_t nand_bb_lseek(struct cdev *cdev, loff_t __offset) + { + struct nand_bb *bb = cdev->priv; +- unsigned long raw_pos = 0; ++ loff_t raw_pos = 0; + uint32_t offset = __offset; + int ret; + +@@ -226,7 +226,7 @@ static off_t nand_bb_lseek(struct cdev *cdev, off_t __offset) + while (raw_pos < bb->raw_size) { + off_t now = min(offset, bb->info.erasesize); + +- ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, (void *)raw_pos); ++ ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, &raw_pos); + if (ret < 0) + return ret; + if (!ret) { +diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c +new file mode 100644 +index 0000000..ba49287 +--- /dev/null ++++ b/drivers/mtd/nand/nand_mxs.c +@@ -0,0 +1,1258 @@ ++/* ++ * Freescale i.MX28 NAND flash driver ++ * ++ * Copyright (C) 2011 Wolfram Sang <w.sang@pengutronix.de> ++ * ++ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> ++ * on behalf of DENX Software Engineering GmbH ++ * ++ * Based on code from LTIB: ++ * Freescale GPMI NFC NAND Flash Driver ++ * ++ * Copyright (C) 2010 Freescale Semiconductor, Inc. ++ * Copyright (C) 2008 Embedded Alley Solutions, Inc. ++ * ++ * 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. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/nand.h> ++#include <linux/types.h> ++#include <common.h> ++#include <malloc.h> ++#include <errno.h> ++#include <driver.h> ++#include <init.h> ++#include <asm/mmu.h> ++#include <asm/io.h> ++#include <mach/clock.h> ++#include <mach/imx-regs.h> ++#include <mach/dma.h> ++#include <mach/mxs.h> ++ ++#define MX28_BLOCK_SFTRST (1 << 31) ++#define MX28_BLOCK_CLKGATE (1 << 30) ++ ++#define GPMI_CTRL0 0x00000000 ++#define GPMI_CTRL0_RUN (1 << 29) ++#define GPMI_CTRL0_DEV_IRQ_EN (1 << 28) ++/* Disable for now since we don't need it and it is different on MX23. ++#define GPMI_CTRL0_LOCK_CS (1 << 27) ++*/ ++#define GPMI_CTRL0_UDMA (1 << 26) ++#define GPMI_CTRL0_COMMAND_MODE_MASK (0x3 << 24) ++#define GPMI_CTRL0_COMMAND_MODE_OFFSET 24 ++#define GPMI_CTRL0_COMMAND_MODE_WRITE (0x0 << 24) ++#define GPMI_CTRL0_COMMAND_MODE_READ (0x1 << 24) ++#define GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE (0x2 << 24) ++#define GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY (0x3 << 24) ++#define GPMI_CTRL0_WORD_LENGTH (1 << 23) ++/* Careful: Is 0x3 on MX23 ++#define GPMI_CTRL0_CS_MASK (0x7 << 20) ++*/ ++#define GPMI_CTRL0_CS_OFFSET 20 ++#define GPMI_CTRL0_ADDRESS_MASK (0x7 << 17) ++#define GPMI_CTRL0_ADDRESS_OFFSET 17 ++#define GPMI_CTRL0_ADDRESS_NAND_DATA (0x0 << 17) ++#define GPMI_CTRL0_ADDRESS_NAND_CLE (0x1 << 17) ++#define GPMI_CTRL0_ADDRESS_NAND_ALE (0x2 << 17) ++#define GPMI_CTRL0_ADDRESS_INCREMENT (1 << 16) ++#define GPMI_CTRL0_XFER_COUNT_MASK 0xffff ++#define GPMI_CTRL0_XFER_COUNT_OFFSET 0 ++ ++#define GPMI_CTRL1 0x00000060 ++#define GPMI_CTRL1_DECOUPLE_CS (1 << 24) ++#define GPMI_CTRL1_WRN_DLY_SEL_MASK (0x3 << 22) ++#define GPMI_CTRL1_WRN_DLY_SEL_OFFSET 22 ++#define GPMI_CTRL1_TIMEOUT_IRQ_EN (1 << 20) ++#define GPMI_CTRL1_GANGED_RDYBUSY (1 << 19) ++#define GPMI_CTRL1_BCH_MODE (1 << 18) ++#define GPMI_CTRL1_DLL_ENABLE (1 << 17) ++#define GPMI_CTRL1_HALF_PERIOD (1 << 16) ++#define GPMI_CTRL1_RDN_DELAY_MASK (0xf << 12) ++#define GPMI_CTRL1_RDN_DELAY_OFFSET 12 ++#define GPMI_CTRL1_DMA2ECC_MODE (1 << 11) ++#define GPMI_CTRL1_DEV_IRQ (1 << 10) ++#define GPMI_CTRL1_TIMEOUT_IRQ (1 << 9) ++#define GPMI_CTRL1_BURST_EN (1 << 8) ++#define GPMI_CTRL1_ABORT_WAIT_REQUEST (1 << 7) ++#define GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK (0x7 << 4) ++#define GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET 4 ++#define GPMI_CTRL1_DEV_RESET (1 << 3) ++#define GPMI_CTRL1_ATA_IRQRDY_POLARITY (1 << 2) ++#define GPMI_CTRL1_CAMERA_MODE (1 << 1) ++#define GPMI_CTRL1_GPMI_MODE (1 << 0) ++ ++#define GPMI_ECCCTRL_HANDLE_MASK (0xffff << 16) ++#define GPMI_ECCCTRL_HANDLE_OFFSET 16 ++#define GPMI_ECCCTRL_ECC_CMD_MASK (0x3 << 13) ++#define GPMI_ECCCTRL_ECC_CMD_OFFSET 13 ++#define GPMI_ECCCTRL_ECC_CMD_DECODE (0x0 << 13) ++#define GPMI_ECCCTRL_ECC_CMD_ENCODE (0x1 << 13) ++#define GPMI_ECCCTRL_ENABLE_ECC (1 << 12) ++#define GPMI_ECCCTRL_BUFFER_MASK_MASK 0x1ff ++#define GPMI_ECCCTRL_BUFFER_MASK_OFFSET 0 ++#define GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY 0x100 ++#define GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE 0x1ff ++ ++#define GPMI_STAT 0x000000b0 ++#define GPMI_STAT_READY_BUSY_OFFSET 24 ++ ++#define GPMI_DEBUG 0x000000c0 ++#define GPMI_DEBUG_READY0_OFFSET 28 ++ ++#define GPMI_VERSION 0x000000d0 ++#define GPMI_VERSION_MINOR_OFFSET 16 ++#define GPMI_VERSION_TYPE_MX23 0x0300 ++ ++#define BCH_CTRL 0x00000000 ++#define BCH_CTRL_COMPLETE_IRQ (1 << 0) ++#define BCH_CTRL_COMPLETE_IRQ_EN (1 << 8) ++ ++#define BCH_LAYOUTSELECT 0x00000070 ++ ++#define BCH_FLASH0LAYOUT0 0x00000080 ++#define BCH_FLASHLAYOUT0_NBLOCKS_MASK (0xff << 24) ++#define BCH_FLASHLAYOUT0_NBLOCKS_OFFSET 24 ++#define BCH_FLASHLAYOUT0_META_SIZE_MASK (0xff << 16) ++#define BCH_FLASHLAYOUT0_META_SIZE_OFFSET 16 ++#define BCH_FLASHLAYOUT0_ECC0_MASK (0xf << 12) ++#define BCH_FLASHLAYOUT0_ECC0_OFFSET 12 ++ ++#define BCH_FLASH0LAYOUT1 0x00000090 ++#define BCH_FLASHLAYOUT1_PAGE_SIZE_MASK (0xffff << 16) ++#define BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET 16 ++#define BCH_FLASHLAYOUT1_ECCN_MASK (0xf << 12) ++#define BCH_FLASHLAYOUT1_ECCN_OFFSET 12 ++ ++#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4 ++ ++#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512 ++#define MXS_NAND_METADATA_SIZE 10 ++ ++#define MXS_NAND_COMMAND_BUFFER_SIZE 32 ++ ++#define MXS_NAND_BCH_TIMEOUT 10000 ++ ++struct mxs_nand_info { ++ struct nand_chip nand_chip; ++ void __iomem *io_base; ++ struct mtd_info mtd; ++ u32 version; ++ ++ int cur_chip; ++ ++ uint32_t cmd_queue_len; ++ ++ uint8_t *cmd_buf; ++ uint8_t *data_buf; ++ uint8_t *oob_buf; ++ ++ uint8_t marking_block_bad; ++ uint8_t raw_oob_mode; ++ ++ /* Functions with altered behaviour */ ++ int (*hooked_read_oob)(struct mtd_info *mtd, ++ loff_t from, struct mtd_oob_ops *ops); ++ int (*hooked_write_oob)(struct mtd_info *mtd, ++ loff_t to, struct mtd_oob_ops *ops); ++ int (*hooked_block_markbad)(struct mtd_info *mtd, ++ loff_t ofs); ++ ++ /* DMA descriptors */ ++ struct mxs_dma_desc **desc; ++ uint32_t desc_index; ++}; ++ ++struct nand_ecclayout fake_ecc_layout; ++ ++static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info) ++{ ++ struct mxs_dma_desc *desc; ++ ++ if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) { ++ printf("MXS NAND: Too many DMA descriptors requested\n"); ++ return NULL; ++ } ++ ++ desc = info->desc[info->desc_index]; ++ info->desc_index++; ++ ++ return desc; ++} ++ ++static void mxs_nand_return_dma_descs(struct mxs_nand_info *info) ++{ ++ int i; ++ struct mxs_dma_desc *desc; ++ ++ for (i = 0; i < info->desc_index; i++) { ++ desc = info->desc[i]; ++ memset(desc, 0, sizeof(struct mxs_dma_desc)); ++ desc->address = (dma_addr_t)desc; ++ } ++ ++ info->desc_index = 0; ++} ++ ++static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size) ++{ ++ return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; ++} ++ ++static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength) ++{ ++ return ecc_strength * 13; ++} ++ ++static uint32_t mxs_nand_aux_status_offset(void) ++{ ++ return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3; ++} ++ ++static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size, ++ uint32_t page_oob_size) ++{ ++ if (page_data_size == 2048) ++ return 8; ++ ++ if (page_data_size == 4096) { ++ if (page_oob_size == 128) ++ return 8; ++ ++ if (page_oob_size == 218) ++ return 16; ++ } ++ ++ return 0; ++} ++ ++static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size, ++ uint32_t ecc_strength) ++{ ++ uint32_t chunk_data_size_in_bits; ++ uint32_t chunk_ecc_size_in_bits; ++ uint32_t chunk_total_size_in_bits; ++ uint32_t block_mark_chunk_number; ++ uint32_t block_mark_chunk_bit_offset; ++ uint32_t block_mark_bit_offset; ++ ++ chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8; ++ chunk_ecc_size_in_bits = mxs_nand_ecc_size_in_bits(ecc_strength); ++ ++ chunk_total_size_in_bits = ++ chunk_data_size_in_bits + chunk_ecc_size_in_bits; ++ ++ /* Compute the bit offset of the block mark within the physical page. */ ++ block_mark_bit_offset = page_data_size * 8; ++ ++ /* Subtract the metadata bits. */ ++ block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8; ++ ++ /* ++ * Compute the chunk number (starting at zero) in which the block mark ++ * appears. ++ */ ++ block_mark_chunk_number = ++ block_mark_bit_offset / chunk_total_size_in_bits; ++ ++ /* ++ * Compute the bit offset of the block mark within its chunk, and ++ * validate it. ++ */ ++ block_mark_chunk_bit_offset = block_mark_bit_offset - ++ (block_mark_chunk_number * chunk_total_size_in_bits); ++ ++ if (block_mark_chunk_bit_offset > chunk_data_size_in_bits) ++ return 1; ++ ++ /* ++ * Now that we know the chunk number in which the block mark appears, ++ * we can subtract all the ECC bits that appear before it. ++ */ ++ block_mark_bit_offset -= ++ block_mark_chunk_number * chunk_ecc_size_in_bits; ++ ++ return block_mark_bit_offset; ++} ++ ++static uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd) ++{ ++ uint32_t ecc_strength; ++ ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize); ++ return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3; ++} ++ ++static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd) ++{ ++ uint32_t ecc_strength; ++ ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize); ++ return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7; ++} ++ ++/* ++ * Wait for BCH complete IRQ and clear the IRQ ++ */ ++static int mxs_nand_wait_for_bch_complete(void) ++{ ++ void __iomem *bch_regs = (void __iomem *)MXS_BCH_BASE; ++ int timeout = MXS_NAND_BCH_TIMEOUT; ++ int ret; ++ ++ while (--timeout) { ++ if (readl(bch_regs + BCH_CTRL) & BCH_CTRL_COMPLETE_IRQ) ++ break; ++ udelay(1); ++ } ++ ++ ret = (timeout == 0) ? -ETIMEDOUT : 0; ++ ++ writel(BCH_CTRL_COMPLETE_IRQ, bch_regs + BCH_CTRL + BIT_CLR); ++ ++ return ret; ++} ++ ++/* ++ * This is the function that we install in the cmd_ctrl function pointer of the ++ * owning struct nand_chip. The only functions in the reference implementation ++ * that use these functions pointers are cmdfunc and select_chip. ++ * ++ * In this driver, we implement our own select_chip, so this function will only ++ * be called by the reference implementation's cmdfunc. For this reason, we can ++ * ignore the chip enable bit and concentrate only on sending bytes to the NAND ++ * Flash. ++ */ ++static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct mxs_nand_info *nand_info = nand->priv; ++ struct mxs_dma_desc *d; ++ uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; ++ int ret; ++ ++ /* ++ * If this condition is true, something is _VERY_ wrong in MTD ++ * subsystem! ++ */ ++ if (nand_info->cmd_queue_len == MXS_NAND_COMMAND_BUFFER_SIZE) { ++ printf("MXS NAND: Command queue too long\n"); ++ return; ++ } ++ ++ /* ++ * Every operation begins with a command byte and a series of zero or ++ * more address bytes. These are distinguished by either the Address ++ * Latch Enable (ALE) or Command Latch Enable (CLE) signals being ++ * asserted. When MTD is ready to execute the command, it will ++ * deasert both latch enables. ++ * ++ * Rather than run a separate DMA operation for every single byte, we ++ * queue them up and run a single DMA operation for the entire series ++ * of command and data bytes. ++ */ ++ if (ctrl & (NAND_ALE | NAND_CLE)) { ++ if (data != NAND_CMD_NONE) ++ nand_info->cmd_buf[nand_info->cmd_queue_len++] = data; ++ return; ++ } ++ ++ /* ++ * If control arrives here, MTD has deasserted both the ALE and CLE, ++ * which means it's ready to run an operation. Check if we have any ++ * bytes to send. ++ */ ++ if (nand_info->cmd_queue_len == 0) ++ return; ++ ++ /* Compile the DMA descriptor -- a descriptor that sends command. */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ | ++ MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM | ++ MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) | ++ (nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET); ++ ++ d->cmd.address = (dma_addr_t)nand_info->cmd_buf; ++ ++ d->cmd.pio_words[0] = ++ GPMI_CTRL0_COMMAND_MODE_WRITE | ++ GPMI_CTRL0_WORD_LENGTH | ++ (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | ++ GPMI_CTRL0_ADDRESS_NAND_CLE | ++ GPMI_CTRL0_ADDRESS_INCREMENT | ++ nand_info->cmd_queue_len; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* Execute the DMA chain. */ ++ ret = mxs_dma_go(channel); ++ if (ret) ++ printf("MXS NAND: Error sending command\n"); ++ ++ mxs_nand_return_dma_descs(nand_info); ++ ++ /* Reset the command queue. */ ++ nand_info->cmd_queue_len = 0; ++} ++ ++/* ++ * Test if the NAND flash is ready. ++ */ ++static int mxs_nand_device_ready(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct mxs_nand_info *nand_info = chip->priv; ++ void __iomem *gpmi_regs = (void *)MXS_GPMI_BASE; ++ uint32_t tmp; ++ ++ if (nand_info->version > GPMI_VERSION_TYPE_MX23) { ++ tmp = readl(gpmi_regs + GPMI_STAT); ++ tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip); ++ } else { ++ tmp = readl(gpmi_regs + GPMI_DEBUG); ++ tmp >>= (GPMI_DEBUG_READY0_OFFSET + nand_info->cur_chip); ++ } ++ return tmp & 1; ++} ++ ++/* ++ * Select the NAND chip. ++ */ ++static void mxs_nand_select_chip(struct mtd_info *mtd, int chip) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct mxs_nand_info *nand_info = nand->priv; ++ ++ nand_info->cur_chip = chip; ++} ++ ++/* ++ * Handle block mark swapping. ++ * ++ * Note that, when this function is called, it doesn't know whether it's ++ * swapping the block mark, or swapping it *back* -- but it doesn't matter ++ * because the the operation is the same. ++ */ ++static void mxs_nand_swap_block_mark(struct mtd_info *mtd, ++ uint8_t *data_buf, uint8_t *oob_buf) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct mxs_nand_info *nand_info = chip->priv; ++ ++ uint32_t bit_offset; ++ uint32_t buf_offset; ++ ++ uint32_t src; ++ uint32_t dst; ++ ++ /* Don't do swapping on MX23 */ ++ if (nand_info->version == GPMI_VERSION_TYPE_MX23) ++ return; ++ ++ bit_offset = mxs_nand_mark_bit_offset(mtd); ++ buf_offset = mxs_nand_mark_byte_offset(mtd); ++ ++ /* ++ * Get the byte from the data area that overlays the block mark. Since ++ * the ECC engine applies its own view to the bits in the page, the ++ * physical block mark won't (in general) appear on a byte boundary in ++ * the data. ++ */ ++ src = data_buf[buf_offset] >> bit_offset; ++ src |= data_buf[buf_offset + 1] << (8 - bit_offset); ++ ++ dst = oob_buf[0]; ++ ++ oob_buf[0] = src; ++ ++ data_buf[buf_offset] &= ~(0xff << bit_offset); ++ data_buf[buf_offset + 1] &= 0xff << bit_offset; ++ ++ data_buf[buf_offset] |= dst << bit_offset; ++ data_buf[buf_offset + 1] |= dst >> (8 - bit_offset); ++} ++ ++/* ++ * Read data from NAND. ++ */ ++static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct mxs_nand_info *nand_info = nand->priv; ++ struct mxs_dma_desc *d; ++ uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; ++ int ret; ++ ++ if (length > NAND_MAX_PAGESIZE) { ++ printf("MXS NAND: DMA buffer too big\n"); ++ return; ++ } ++ ++ if (!buf) { ++ printf("MXS NAND: DMA buffer is NULL\n"); ++ return; ++ } ++ ++ /* Compile the DMA descriptor - a descriptor that reads data. */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ | ++ MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END | ++ (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) | ++ (length << MXS_DMA_DESC_BYTES_OFFSET); ++ ++ d->cmd.address = (dma_addr_t)nand_info->data_buf; ++ ++ d->cmd.pio_words[0] = ++ GPMI_CTRL0_COMMAND_MODE_READ | ++ GPMI_CTRL0_WORD_LENGTH | ++ (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | ++ GPMI_CTRL0_ADDRESS_NAND_DATA | ++ length; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* ++ * A DMA descriptor that waits for the command to end and the chip to ++ * become ready. ++ * ++ * I think we actually should *not* be waiting for the chip to become ++ * ready because, after all, we don't care. I think the original code ++ * did that and no one has re-thought it yet. ++ */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ | ++ MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM | ++ MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET); ++ ++ d->cmd.address = 0; ++ ++ d->cmd.pio_words[0] = ++ GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY | ++ GPMI_CTRL0_WORD_LENGTH | ++ (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | ++ GPMI_CTRL0_ADDRESS_NAND_DATA; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* Execute the DMA chain. */ ++ ret = mxs_dma_go(channel); ++ if (ret) { ++ printf("MXS NAND: DMA read error\n"); ++ goto rtn; ++ } ++ ++ memcpy(buf, nand_info->data_buf, length); ++ ++rtn: ++ mxs_nand_return_dma_descs(nand_info); ++} ++ ++/* ++ * Write data to NAND. ++ */ ++static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, ++ int length) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct mxs_nand_info *nand_info = nand->priv; ++ struct mxs_dma_desc *d; ++ uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; ++ int ret; ++ ++ if (length > NAND_MAX_PAGESIZE) { ++ printf("MXS NAND: DMA buffer too big\n"); ++ return; ++ } ++ ++ if (!buf) { ++ printf("MXS NAND: DMA buffer is NULL\n"); ++ return; ++ } ++ ++ memcpy(nand_info->data_buf, buf, length); ++ ++ /* Compile the DMA descriptor - a descriptor that writes data. */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ | ++ MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END | ++ (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) | ++ (length << MXS_DMA_DESC_BYTES_OFFSET); ++ ++ d->cmd.address = (dma_addr_t)nand_info->data_buf; ++ ++ d->cmd.pio_words[0] = ++ GPMI_CTRL0_COMMAND_MODE_WRITE | ++ GPMI_CTRL0_WORD_LENGTH | ++ (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | ++ GPMI_CTRL0_ADDRESS_NAND_DATA | ++ length; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* Execute the DMA chain. */ ++ ret = mxs_dma_go(channel); ++ if (ret) ++ printf("MXS NAND: DMA write error\n"); ++ ++ mxs_nand_return_dma_descs(nand_info); ++} ++ ++/* ++ * Read a single byte from NAND. ++ */ ++static uint8_t mxs_nand_read_byte(struct mtd_info *mtd) ++{ ++ uint8_t buf; ++ mxs_nand_read_buf(mtd, &buf, 1); ++ return buf; ++} ++ ++/* ++ * Read a page from NAND. ++ */ ++static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, ++ uint8_t *buf) ++{ ++ struct mxs_nand_info *nand_info = nand->priv; ++ struct mxs_dma_desc *d; ++ uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; ++ uint32_t corrected = 0, failed = 0; ++ uint8_t *status; ++ int i, ret; ++ ++ /* Compile the DMA descriptor - wait for ready. */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN | ++ MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END | ++ (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET); ++ ++ d->cmd.address = 0; ++ ++ d->cmd.pio_words[0] = ++ GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY | ++ GPMI_CTRL0_WORD_LENGTH | ++ (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | ++ GPMI_CTRL0_ADDRESS_NAND_DATA; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* Compile the DMA descriptor - enable the BCH block and read. */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN | ++ MXS_DMA_DESC_WAIT4END | (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET); ++ ++ d->cmd.address = 0; ++ ++ d->cmd.pio_words[0] = ++ GPMI_CTRL0_COMMAND_MODE_READ | ++ GPMI_CTRL0_WORD_LENGTH | ++ (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | ++ GPMI_CTRL0_ADDRESS_NAND_DATA | ++ (mtd->writesize + mtd->oobsize); ++ d->cmd.pio_words[1] = 0; ++ d->cmd.pio_words[2] = ++ GPMI_ECCCTRL_ENABLE_ECC | ++ GPMI_ECCCTRL_ECC_CMD_DECODE | ++ GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE; ++ d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize; ++ d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf; ++ d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* Compile the DMA descriptor - disable the BCH block. */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN | ++ MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END | ++ (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET); ++ ++ d->cmd.address = 0; ++ ++ d->cmd.pio_words[0] = ++ GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY | ++ GPMI_CTRL0_WORD_LENGTH | ++ (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | ++ GPMI_CTRL0_ADDRESS_NAND_DATA | ++ (mtd->writesize + mtd->oobsize); ++ d->cmd.pio_words[1] = 0; ++ d->cmd.pio_words[2] = 0; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* Compile the DMA descriptor - deassert the NAND lock and interrupt. */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ | ++ MXS_DMA_DESC_DEC_SEM; ++ ++ d->cmd.address = 0; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* Execute the DMA chain. */ ++ ret = mxs_dma_go(channel); ++ if (ret) { ++ printf("MXS NAND: DMA read error\n"); ++ goto rtn; ++ } ++ ++ ret = mxs_nand_wait_for_bch_complete(); ++ if (ret) { ++ printf("MXS NAND: BCH read timeout\n"); ++ goto rtn; ++ } ++ ++ /* Read DMA completed, now do the mark swapping. */ ++ mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); ++ ++ /* Loop over status bytes, accumulating ECC status. */ ++ status = nand_info->oob_buf + mxs_nand_aux_status_offset(); ++ for (i = 0; i < mxs_nand_ecc_chunk_cnt(mtd->writesize); i++) { ++ if (status[i] == 0x00) ++ continue; ++ ++ if (status[i] == 0xff) ++ continue; ++ ++ if (status[i] == 0xfe) { ++ failed++; ++ continue; ++ } ++ ++ corrected += status[i]; ++ } ++ ++ /* Propagate ECC status to the owning MTD. */ ++ mtd->ecc_stats.failed += failed; ++ mtd->ecc_stats.corrected += corrected; ++ ++ /* ++ * It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for ++ * details about our policy for delivering the OOB. ++ * ++ * We fill the caller's buffer with set bits, and then copy the block ++ * mark to the caller's buffer. Note that, if block mark swapping was ++ * necessary, it has already been done, so we can rely on the first ++ * byte of the auxiliary buffer to contain the block mark. ++ */ ++ memset(nand->oob_poi, 0xff, mtd->oobsize); ++ ++ nand->oob_poi[0] = nand_info->oob_buf[0]; ++ ++ memcpy(buf, nand_info->data_buf, mtd->writesize); ++ ++rtn: ++ mxs_nand_return_dma_descs(nand_info); ++ ++ return ret; ++} ++ ++/* ++ * Write a page to NAND. ++ */ ++static void mxs_nand_ecc_write_page(struct mtd_info *mtd, ++ struct nand_chip *nand, const uint8_t *buf) ++{ ++ struct mxs_nand_info *nand_info = nand->priv; ++ struct mxs_dma_desc *d; ++ uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; ++ int ret; ++ ++ memcpy(nand_info->data_buf, buf, mtd->writesize); ++ memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize); ++ ++ /* Handle block mark swapping. */ ++ mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); ++ ++ /* Compile the DMA descriptor - write data. */ ++ d = mxs_nand_get_dma_desc(nand_info); ++ d->cmd.data = ++ MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ | ++ MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END | ++ (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET); ++ ++ d->cmd.address = 0; ++ ++ d->cmd.pio_words[0] = ++ GPMI_CTRL0_COMMAND_MODE_WRITE | ++ GPMI_CTRL0_WORD_LENGTH | ++ (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | ++ GPMI_CTRL0_ADDRESS_NAND_DATA; ++ d->cmd.pio_words[1] = 0; ++ d->cmd.pio_words[2] = ++ GPMI_ECCCTRL_ENABLE_ECC | ++ GPMI_ECCCTRL_ECC_CMD_ENCODE | ++ GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE; ++ d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize); ++ d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf; ++ d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf; ++ ++ mxs_dma_desc_append(channel, d); ++ ++ /* Execute the DMA chain. */ ++ ret = mxs_dma_go(channel); ++ if (ret) { ++ printf("MXS NAND: DMA write error\n"); ++ goto rtn; ++ } ++ ++ ret = mxs_nand_wait_for_bch_complete(); ++ if (ret) { ++ printf("MXS NAND: BCH write timeout\n"); ++ goto rtn; ++ } ++ ++rtn: ++ mxs_nand_return_dma_descs(nand_info); ++} ++ ++/* ++ * Read OOB from NAND. ++ * ++ * This function is a veneer that replaces the function originally installed by ++ * the NAND Flash MTD code. ++ */ ++static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from, ++ struct mtd_oob_ops *ops) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct mxs_nand_info *nand_info = chip->priv; ++ int ret; ++ ++ if (ops->mode == MTD_OOB_RAW) ++ nand_info->raw_oob_mode = 1; ++ else ++ nand_info->raw_oob_mode = 0; ++ ++ ret = nand_info->hooked_read_oob(mtd, from, ops); ++ ++ nand_info->raw_oob_mode = 0; ++ ++ return ret; ++} ++ ++/* ++ * Write OOB to NAND. ++ * ++ * This function is a veneer that replaces the function originally installed by ++ * the NAND Flash MTD code. ++ */ ++static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to, ++ struct mtd_oob_ops *ops) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct mxs_nand_info *nand_info = chip->priv; ++ int ret; ++ ++ if (ops->mode == MTD_OOB_RAW) ++ nand_info->raw_oob_mode = 1; ++ else ++ nand_info->raw_oob_mode = 0; ++ ++ ret = nand_info->hooked_write_oob(mtd, to, ops); ++ ++ nand_info->raw_oob_mode = 0; ++ ++ return ret; ++} ++ ++/* ++ * Mark a block bad in NAND. ++ * ++ * This function is a veneer that replaces the function originally installed by ++ * the NAND Flash MTD code. ++ */ ++static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct mxs_nand_info *nand_info = chip->priv; ++ int ret; ++ ++ nand_info->marking_block_bad = 1; ++ ++ ret = nand_info->hooked_block_markbad(mtd, ofs); ++ ++ nand_info->marking_block_bad = 0; ++ ++ return ret; ++} ++ ++/* ++ * There are several places in this driver where we have to handle the OOB and ++ * block marks. This is the function where things are the most complicated, so ++ * this is where we try to explain it all. All the other places refer back to ++ * here. ++ * ++ * These are the rules, in order of decreasing importance: ++ * ++ * 1) Nothing the caller does can be allowed to imperil the block mark, so all ++ * write operations take measures to protect it. ++ * ++ * 2) In read operations, the first byte of the OOB we return must reflect the ++ * true state of the block mark, no matter where that block mark appears in ++ * the physical page. ++ * ++ * 3) ECC-based read operations return an OOB full of set bits (since we never ++ * allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads ++ * return). ++ * ++ * 4) "Raw" read operations return a direct view of the physical bytes in the ++ * page, using the conventional definition of which bytes are data and which ++ * are OOB. This gives the caller a way to see the actual, physical bytes ++ * in the page, without the distortions applied by our ECC engine. ++ * ++ * What we do for this specific read operation depends on whether we're doing ++ * "raw" read, or an ECC-based read. ++ * ++ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not ++ * easy. When reading a page, for example, the NAND Flash MTD code calls our ++ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an ++ * ECC-based or raw view of the page is implicit in which function it calls ++ * (there is a similar pair of ECC-based/raw functions for writing). ++ * ++ * Since MTD assumes the OOB is not covered by ECC, there is no pair of ++ * ECC-based/raw functions for reading or or writing the OOB. The fact that the ++ * caller wants an ECC-based or raw view of the page is not propagated down to ++ * this driver. ++ * ++ * Since our OOB *is* covered by ECC, we need this information. So, we hook the ++ * ecc.read_oob and ecc.write_oob function pointers in the owning ++ * struct mtd_info with our own functions. These hook functions set the ++ * raw_oob_mode field so that, when control finally arrives here, we'll know ++ * what to do. ++ */ ++static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand, ++ int page, int cmd) ++{ ++ struct mxs_nand_info *nand_info = nand->priv; ++ int column; ++ ++ /* ++ * First, fill in the OOB buffer. If we're doing a raw read, we need to ++ * get the bytes from the physical page. If we're not doing a raw read, ++ * we need to fill the buffer with set bits. ++ */ ++ if (nand_info->raw_oob_mode && nand_info->version > GPMI_VERSION_TYPE_MX23) { ++ /* ++ * If control arrives here, we're doing a "raw" read. Send the ++ * command to read the conventional OOB and read it. ++ */ ++ nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); ++ nand->read_buf(mtd, nand->oob_poi, mtd->oobsize); ++ } else { ++ /* ++ * If control arrives here, we're not doing a "raw" read. Fill ++ * the OOB buffer with set bits and correct the block mark. ++ */ ++ memset(nand->oob_poi, 0xff, mtd->oobsize); ++ ++ column = nand_info->version == GPMI_VERSION_TYPE_MX23 ? 0 : mtd->writesize; ++ nand->cmdfunc(mtd, NAND_CMD_READ0, column, page); ++ mxs_nand_read_buf(mtd, nand->oob_poi, 1); ++ } ++ ++ return 0; ++ ++} ++ ++/* ++ * Write OOB data to NAND. ++ */ ++static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand, ++ int page) ++{ ++ struct mxs_nand_info *nand_info = nand->priv; ++ int column; ++ uint8_t block_mark = 0; ++ ++ /* ++ * There are fundamental incompatibilities between the i.MX GPMI NFC and ++ * the NAND Flash MTD model that make it essentially impossible to write ++ * the out-of-band bytes. ++ * ++ * We permit *ONE* exception. If the *intent* of writing the OOB is to ++ * mark a block bad, we can do that. ++ */ ++ ++ if (!nand_info->marking_block_bad) { ++ printf("NXS NAND: Writing OOB isn't supported\n"); ++ return -EIO; ++ } ++ ++ column = nand_info->version == GPMI_VERSION_TYPE_MX23 ? 0 : mtd->writesize; ++ /* Write the block mark. */ ++ nand->cmdfunc(mtd, NAND_CMD_SEQIN, column, page); ++ nand->write_buf(mtd, &block_mark, 1); ++ nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); ++ ++ /* Check if it worked. */ ++ if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL) ++ return -EIO; ++ ++ return 0; ++} ++ ++/* ++ * Claims all blocks are good. ++ * ++ * In principle, this function is *only* called when the NAND Flash MTD system ++ * isn't allowed to keep an in-memory bad block table, so it is forced to ask ++ * the driver for bad block information. ++ * ++ * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so ++ * this function is *only* called when we take it away. ++ * ++ * Thus, this function is only called when we want *all* blocks to look good, ++ * so it *always* return success. ++ */ ++static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) ++{ ++ return 0; ++} ++ ++/* ++ * Nominally, the purpose of this function is to look for or create the bad ++ * block table. In fact, since the we call this function at the very end of ++ * the initialization process started by nand_scan(), and we doesn't have a ++ * more formal mechanism, we "hook" this function to continue init process. ++ * ++ * At this point, the physical NAND Flash chips have been identified and ++ * counted, so we know the physical geometry. This enables us to make some ++ * important configuration decisions. ++ * ++ * The return value of this function propogates directly back to this driver's ++ * call to nand_scan(). Anything other than zero will cause this driver to ++ * tear everything down and declare failure. ++ */ ++static int mxs_nand_scan_bbt(struct mtd_info *mtd) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct mxs_nand_info *nand_info = nand->priv; ++ void __iomem *bch_regs = (void __iomem *)MXS_BCH_BASE; ++ uint32_t tmp; ++ ++ /* Reset BCH. Don't use SFTRST on MX23 due to Errata #2847 */ ++ mxs_reset_block(bch_regs + BCH_CTRL, nand_info->version == GPMI_VERSION_TYPE_MX23); ++ ++ /* Configure layout 0 */ ++ tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1) ++ << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET; ++ tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET; ++ tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1) ++ << BCH_FLASHLAYOUT0_ECC0_OFFSET; ++ tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE; ++ writel(tmp, bch_regs + BCH_FLASH0LAYOUT0); ++ ++ tmp = (mtd->writesize + mtd->oobsize) ++ << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET; ++ tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1) ++ << BCH_FLASHLAYOUT1_ECCN_OFFSET; ++ tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE; ++ writel(tmp, bch_regs + BCH_FLASH0LAYOUT1); ++ ++ /* Set *all* chip selects to use layout 0 */ ++ writel(0, bch_regs + BCH_LAYOUTSELECT); ++ ++ /* Enable BCH complete interrupt */ ++ writel(BCH_CTRL_COMPLETE_IRQ_EN, bch_regs + BCH_CTRL + BIT_SET); ++ ++ /* Hook some operations at the MTD level. */ ++ if (mtd->read_oob != mxs_nand_hook_read_oob) { ++ nand_info->hooked_read_oob = mtd->read_oob; ++ mtd->read_oob = mxs_nand_hook_read_oob; ++ } ++ ++ if (mtd->write_oob != mxs_nand_hook_write_oob) { ++ nand_info->hooked_write_oob = mtd->write_oob; ++ mtd->write_oob = mxs_nand_hook_write_oob; ++ } ++ ++ if (mtd->block_markbad != mxs_nand_hook_block_markbad) { ++ nand_info->hooked_block_markbad = mtd->block_markbad; ++ mtd->block_markbad = mxs_nand_hook_block_markbad; ++ } ++ ++ /* We use the reference implementation for bad block management. */ ++ return nand_default_bbt(mtd); ++} ++ ++/* ++ * Allocate DMA buffers ++ */ ++int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info) ++{ ++ uint8_t *buf; ++ const int size = NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE; ++ ++ /* DMA buffers */ ++ buf = dma_alloc_coherent(size); ++ if (!buf) { ++ printf("MXS NAND: Error allocating DMA buffers\n"); ++ return -ENOMEM; ++ } ++ ++ memset(buf, 0, size); ++ ++ nand_info->data_buf = buf; ++ nand_info->oob_buf = buf + NAND_MAX_PAGESIZE; ++ ++ /* Command buffers */ ++ nand_info->cmd_buf = dma_alloc_coherent(MXS_NAND_COMMAND_BUFFER_SIZE); ++ if (!nand_info->cmd_buf) { ++ free(buf); ++ printf("MXS NAND: Error allocating command buffers\n"); ++ return -ENOMEM; ++ } ++ memset(nand_info->cmd_buf, 0, MXS_NAND_COMMAND_BUFFER_SIZE); ++ nand_info->cmd_queue_len = 0; ++ ++ return 0; ++} ++ ++/* ++ * Initializes the NFC hardware. ++ */ ++int mxs_nand_hw_init(struct mxs_nand_info *info) ++{ ++ void __iomem *gpmi_regs = (void *)MXS_GPMI_BASE; ++ int i = 0; ++ u32 val; ++ ++ info->desc = malloc(sizeof(struct mxs_dma_desc *) * ++ MXS_NAND_DMA_DESCRIPTOR_COUNT); ++ if (!info->desc) ++ goto err1; ++ ++ /* Allocate the DMA descriptors. */ ++ for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) { ++ info->desc[i] = mxs_dma_desc_alloc(); ++ if (!info->desc[i]) ++ goto err2; ++ } ++ ++ /* Init the DMA controller. */ ++ mxs_dma_init(); ++ ++ imx_enable_nandclk(); ++ ++ /* Reset the GPMI block. */ ++ mxs_reset_block(gpmi_regs + GPMI_CTRL0, 0); ++ ++ /* ++ * Choose NAND mode, set IRQ polarity, disable write protection and ++ * select BCH ECC. ++ */ ++ val = readl(gpmi_regs + GPMI_CTRL1); ++ val &= ~GPMI_CTRL1_GPMI_MODE; ++ val |= GPMI_CTRL1_ATA_IRQRDY_POLARITY | GPMI_CTRL1_DEV_RESET | ++ GPMI_CTRL1_BCH_MODE; ++ writel(val, gpmi_regs + GPMI_CTRL1); ++ ++ val = readl(gpmi_regs + GPMI_VERSION); ++ info->version = val >> GPMI_VERSION_MINOR_OFFSET; ++ ++ return 0; ++ ++err2: ++ free(info->desc); ++err1: ++ for (--i; i >= 0; i--) ++ mxs_dma_desc_free(info->desc[i]); ++ printf("MXS NAND: Unable to allocate DMA descriptors\n"); ++ return -ENOMEM; ++} ++ ++static int mxs_nand_probe(struct device_d *dev) ++{ ++ struct mxs_nand_info *nand_info; ++ struct nand_chip *nand; ++ struct mtd_info *mtd; ++ int err; ++ ++ nand_info = kzalloc(sizeof(struct mxs_nand_info), GFP_KERNEL); ++ if (!nand_info) { ++ printf("MXS NAND: Failed to allocate private data\n"); ++ return -ENOMEM; ++ } ++ ++ /* XXX: Remove u-boot specific access pointers and use io_base instead? */ ++ nand_info->io_base = dev_request_mem_region(dev, 0); ++ ++ err = mxs_nand_alloc_buffers(nand_info); ++ if (err) ++ goto err1; ++ ++ err = mxs_nand_hw_init(nand_info); ++ if (err) ++ goto err2; ++ ++ memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout)); ++ ++ /* structures must be linked */ ++ nand = &nand_info->nand_chip; ++ mtd = &nand_info->mtd; ++ mtd->priv = nand; ++ ++ nand->priv = nand_info; ++ nand->options |= NAND_NO_SUBPAGE_WRITE; ++ ++ nand->cmd_ctrl = mxs_nand_cmd_ctrl; ++ ++ nand->dev_ready = mxs_nand_device_ready; ++ nand->select_chip = mxs_nand_select_chip; ++ nand->block_bad = mxs_nand_block_bad; ++ nand->scan_bbt = mxs_nand_scan_bbt; ++ ++ nand->read_byte = mxs_nand_read_byte; ++ ++ nand->read_buf = mxs_nand_read_buf; ++ nand->write_buf = mxs_nand_write_buf; ++ ++ nand->ecc.read_page = mxs_nand_ecc_read_page; ++ nand->ecc.write_page = mxs_nand_ecc_write_page; ++ nand->ecc.read_oob = mxs_nand_ecc_read_oob; ++ nand->ecc.write_oob = mxs_nand_ecc_write_oob; ++ ++ nand->ecc.layout = &fake_ecc_layout; ++ nand->ecc.mode = NAND_ECC_HW; ++ nand->ecc.bytes = 9; ++ nand->ecc.size = 512; ++ ++ /* Scan to find existence of the device */ ++ err = nand_scan(mtd, 1); ++ if (err) ++ goto err2; ++ ++ return add_mtd_device(mtd, "nand"); ++err2: ++ free(nand_info->data_buf); ++ free(nand_info->cmd_buf); ++err1: ++ free(nand_info); ++ return err; ++} ++ ++static struct driver_d mxs_nand_driver = { ++ .name = "mxs_nand", ++ .probe = mxs_nand_probe, ++}; ++ ++static int __init mxs_nand_init(void) ++{ ++ return register_driver(&mxs_nand_driver); ++} ++ ++device_initcall(mxs_nand_init); ++ ++MODULE_AUTHOR("Denx Software Engeneering and Wolfram Sang"); ++MODULE_DESCRIPTION("MXS NAND MTD driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c +index 95bef1f..c99b64d 100644 +--- a/drivers/mtd/ubi/cdev.c ++++ b/drivers/mtd/ubi/cdev.c +@@ -12,7 +12,7 @@ struct ubi_volume_cdev_priv { + }; + + static ssize_t ubi_volume_cdev_read(struct cdev *cdev, void *buf, size_t size, +- unsigned long offset, unsigned long flags) ++ loff_t offset, unsigned long flags) + { + struct ubi_volume_cdev_priv *priv = cdev->priv; + struct ubi_volume *vol = priv->vol; +@@ -23,7 +23,7 @@ static ssize_t ubi_volume_cdev_read(struct cdev *cdev, void *buf, size_t size, + loff_t offp = offset; + int usable_leb_size = vol->usable_leb_size; + +- printf("%s: %d @ 0x%08lx\n", __func__, size, offset); ++ printf("%s: %d @ 0x%08llx\n", __func__, size, offset); + + len = size > usable_leb_size ? usable_leb_size : size; + +@@ -56,7 +56,7 @@ static ssize_t ubi_volume_cdev_read(struct cdev *cdev, void *buf, size_t size, + } + + static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf, +- size_t size, unsigned long offset, unsigned long flags) ++ size_t size, loff_t offset, unsigned long flags) + { + struct ubi_volume_cdev_priv *priv = cdev->priv; + struct ubi_volume *vol = priv->vol; +@@ -121,7 +121,7 @@ static int ubi_volume_cdev_close(struct cdev *cdev) + return 0; + } + +-static off_t ubi_volume_cdev_lseek(struct cdev *cdev, off_t ofs) ++static loff_t ubi_volume_cdev_lseek(struct cdev *cdev, loff_t ofs) + { + struct ubi_volume_cdev_priv *priv = cdev->priv; + +diff --git a/drivers/mtd/ubi/ubi-barebox.h b/drivers/mtd/ubi/ubi-barebox.h +index d23228f..72f29a6 100644 +--- a/drivers/mtd/ubi/ubi-barebox.h ++++ b/drivers/mtd/ubi/ubi-barebox.h +@@ -135,7 +135,6 @@ struct kmem_cache { int i; }; + #define GFP_KERNEL 0 + #define GFP_NOFS 1 + +-#define __user + #define __init + #define __exit + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 172cc39..749ea6a 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -13,6 +13,9 @@ config HAS_AT91_ETHER + config HAS_NETX_ETHER + bool + ++config HAS_DESIGNWARE_ETH ++ bool ++ + config ARCH_HAS_FEC_IMX + bool + +@@ -108,6 +111,19 @@ config DRIVER_NET_KS8851_MLL + This option enables support for the Micrel KS8851 MLL + ethernet chip. + ++config DRIVER_NET_DESIGNWARE ++ bool "Designware Universal MAC ethernet driver" ++ select MIIDEV ++ depends on HAS_DESIGNWARE_ETH ++ help ++ This option enables support for the Synopsys ++ Designware Core Univesal MAC 10M/100M/1G ethernet IP. ++ ++config DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR ++ bool ++ depends on DRIVER_NET_DESIGNWARE ++ default n ++ + source "drivers/net/usb/Kconfig" + + endmenu +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index 34dbee9..29727b7 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -13,3 +13,4 @@ obj-$(CONFIG_MIIDEV) += miidev.o + obj-$(CONFIG_NET_USB) += usb/ + obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o + obj-$(CONFIG_DRIVER_NET_KS8851_MLL) += ks8851_mll.o ++obj-$(CONFIG_DRIVER_NET_DESIGNWARE) += designware.o +diff --git a/drivers/net/designware.c b/drivers/net/designware.c +new file mode 100644 +index 0000000..379b4e3 +--- /dev/null ++++ b/drivers/net/designware.c +@@ -0,0 +1,436 @@ ++/* ++ * (C) Copyright 2010 ++ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. ++ * ++ * 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 ++ */ ++ ++/* ++ * Designware ethernet IP driver for u-boot ++ */ ++ ++#include <common.h> ++#include <init.h> ++#include <io.h> ++#include <net.h> ++#include <miidev.h> ++#include <asm/mmu.h> ++#include <net/designware.h> ++#include "designware.h" ++ ++ ++struct dw_eth_dev { ++ struct eth_device netdev; ++ struct mii_device miidev; ++ ++ void (*fix_mac_speed)(int speed); ++ u8 macaddr[6]; ++ u32 tx_currdescnum; ++ u32 rx_currdescnum; ++ ++ struct dmamacdescr *tx_mac_descrtable; ++ struct dmamacdescr *rx_mac_descrtable; ++ ++ u8 *txbuffs; ++ u8 *rxbuffs; ++ ++ struct eth_mac_regs *mac_regs_p; ++ struct eth_dma_regs *dma_regs_p; ++}; ++ ++/* Speed specific definitions */ ++#define SPEED_10M 1 ++#define SPEED_100M 2 ++#define SPEED_1000M 3 ++ ++/* Duplex mode specific definitions */ ++#define HALF_DUPLEX 1 ++#define FULL_DUPLEX 2 ++ ++ ++static int dwc_ether_mii_read(struct mii_device *dev, int addr, int reg) ++{ ++ struct dw_eth_dev *priv = dev->edev->priv; ++ struct eth_mac_regs *mac_p = priv->mac_regs_p; ++ u64 start; ++ u32 miiaddr; ++ ++ miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \ ++ ((reg << MIIREGSHIFT) & MII_REGMSK); ++ ++ writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); ++ ++ start = get_time_ns(); ++ while (readl(&mac_p->miiaddr) & MII_BUSY) { ++ if (is_timeout(start, 10 * MSECOND)) { ++ dev_err(&priv->netdev.dev, "MDIO timeout\n"); ++ return -EIO; ++ } ++ } ++ return readl(&mac_p->miidata) & 0xffff; ++} ++ ++static int dwc_ether_mii_write(struct mii_device *dev, int addr, int reg, int val) ++{ ++ struct dw_eth_dev *priv = dev->edev->priv; ++ struct eth_mac_regs *mac_p = priv->mac_regs_p; ++ u64 start; ++ u32 miiaddr; ++ ++ writel(val, &mac_p->miidata); ++ miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \ ++ ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE; ++ ++ writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); ++ ++ start = get_time_ns(); ++ while (readl(&mac_p->miiaddr) & MII_BUSY) { ++ if (is_timeout(start, 10 * MSECOND)) { ++ dev_err(&priv->netdev.dev, "MDIO timeout\n"); ++ return -EIO; ++ } ++ } ++ ++ /* Needed as a fix for ST-Phy */ ++ dwc_ether_mii_read(dev, addr, reg); ++ return 0; ++} ++ ++ ++static int mac_reset(struct eth_device *dev) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ struct eth_mac_regs *mac_p = priv->mac_regs_p; ++ struct eth_dma_regs *dma_p = priv->dma_regs_p; ++ u64 start; ++ ++ writel(DMAMAC_SRST, &dma_p->busmode); ++ writel(MII_PORTSELECT, &mac_p->conf); ++ ++ start = get_time_ns(); ++ while (readl(&dma_p->busmode) & DMAMAC_SRST) { ++ if (is_timeout(start, 10 * MSECOND)) { ++ dev_err(&priv->netdev.dev, "MAC reset timeout\n"); ++ return -EIO; ++ } ++ } ++ return 0; ++} ++ ++static void tx_descs_init(struct eth_device *dev) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ struct eth_dma_regs *dma_p = priv->dma_regs_p; ++ struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0]; ++ char *txbuffs = &priv->txbuffs[0]; ++ struct dmamacdescr *desc_p; ++ u32 idx; ++ ++ for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) { ++ desc_p = &desc_table_p[idx]; ++ desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE]; ++ desc_p->dmamac_next = &desc_table_p[idx + 1]; ++ ++#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) ++ desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST | ++ DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \ ++ DESC_TXSTS_TXCHECKINSCTRL | \ ++ DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS); ++ ++ desc_p->txrx_status |= DESC_TXSTS_TXCHAIN; ++ desc_p->dmamac_cntl = 0; ++ desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA); ++#else ++ desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN; ++ desc_p->txrx_status = 0; ++#endif ++ } ++ ++ /* Correcting the last pointer of the chain */ ++ desc_p->dmamac_next = &desc_table_p[0]; ++ ++ writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr); ++} ++ ++static void rx_descs_init(struct eth_device *dev) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ struct eth_dma_regs *dma_p = priv->dma_regs_p; ++ struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0]; ++ char *rxbuffs = &priv->rxbuffs[0]; ++ struct dmamacdescr *desc_p; ++ u32 idx; ++ ++ for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) { ++ desc_p = &desc_table_p[idx]; ++ desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE]; ++ desc_p->dmamac_next = &desc_table_p[idx + 1]; ++ ++ desc_p->dmamac_cntl = ++ (MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \ ++ DESC_RXCTRL_RXCHAIN; ++ ++ dma_inv_range((unsigned long)desc_p->dmamac_addr, ++ (unsigned long)desc_p->dmamac_addr + CONFIG_ETH_BUFSIZE); ++ desc_p->txrx_status = DESC_RXSTS_OWNBYDMA; ++ } ++ ++ /* Correcting the last pointer of the chain */ ++ desc_p->dmamac_next = &desc_table_p[0]; ++ ++ writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr); ++} ++ ++static void descs_init(struct eth_device *dev) ++{ ++ tx_descs_init(dev); ++ rx_descs_init(dev); ++} ++ ++static int dwc_ether_init(struct eth_device *dev) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ struct eth_mac_regs *mac_p = priv->mac_regs_p; ++ struct eth_dma_regs *dma_p = priv->dma_regs_p; ++ ++ if (mac_reset(dev) < 0) ++ return -1; ++ ++ /* HW MAC address is lost during MAC reset */ ++ dev->set_ethaddr(dev, priv->macaddr); ++ ++ writel(FIXEDBURST | PRIORXTX_41 | BURST_16, &dma_p->busmode); ++ writel(FLUSHTXFIFO | readl(&dma_p->opmode), &dma_p->opmode); ++ writel(STOREFORWARD | TXSECONDFRAME, &dma_p->opmode); ++ writel(FRAMEBURSTENABLE | DISABLERXOWN, &mac_p->conf); ++ return 0; ++} ++ ++static int dwc_ether_open(struct eth_device *dev) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ struct eth_mac_regs *mac_p = priv->mac_regs_p; ++ struct eth_dma_regs *dma_p = priv->dma_regs_p; ++ u32 conf; ++ int link, speed; ++ ++ miidev_wait_aneg(&priv->miidev); ++ miidev_print_status(&priv->miidev); ++ link = miidev_get_status(&priv->miidev); ++ ++ if (priv->fix_mac_speed) { ++ speed = link & MIIDEV_STATUS_IS_1000MBIT ? 1000 : ++ (link & MIIDEV_STATUS_IS_100MBIT ? 100 : 10); ++ priv->fix_mac_speed(speed); ++ } ++ ++ conf = readl(&mac_p->conf); ++ if (link & MIIDEV_STATUS_IS_FULL_DUPLEX) ++ conf |= FULLDPLXMODE; ++ else ++ conf &= ~FULLDPLXMODE; ++ if (link & MIIDEV_STATUS_IS_1000MBIT) ++ conf &= ~MII_PORTSELECT; ++ else ++ conf |= MII_PORTSELECT; ++ writel(conf, &mac_p->conf); ++ ++ descs_init(dev); ++ ++ /* ++ * Start/Enable xfer at dma as well as mac level ++ */ ++ writel(readl(&dma_p->opmode) | RXSTART, &dma_p->opmode); ++ writel(readl(&dma_p->opmode) | TXSTART, &dma_p->opmode); ++ writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf); ++ return 0; ++} ++ ++static int dwc_ether_send(struct eth_device *dev, void *packet, int length) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ struct eth_dma_regs *dma_p = priv->dma_regs_p; ++ u32 desc_num = priv->tx_currdescnum; ++ struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num]; ++ ++ /* Check if the descriptor is owned by CPU */ ++ if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) { ++ dev_err(&dev->dev, "CPU not owner of tx frame\n"); ++ return -1; ++ } ++ ++ memcpy((void *)desc_p->dmamac_addr, packet, length); ++ dma_flush_range((unsigned long)desc_p->dmamac_addr, ++ (unsigned long)desc_p->dmamac_addr + length); ++ ++#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) ++ desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST; ++ desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \ ++ DESC_TXCTRL_SIZE1MASK; ++ ++ desc_p->txrx_status &= ~(DESC_TXSTS_MSK); ++ desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA; ++#else ++ desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \ ++ DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \ ++ DESC_TXCTRL_TXFIRST; ++ ++ desc_p->txrx_status = DESC_TXSTS_OWNBYDMA; ++#endif ++ ++ /* Test the wrap-around condition. */ ++ if (++desc_num >= CONFIG_TX_DESCR_NUM) ++ desc_num = 0; ++ ++ priv->tx_currdescnum = desc_num; ++ ++ /* Start the transmission */ ++ writel(POLL_DATA, &dma_p->txpolldemand); ++ return 0; ++} ++ ++static int dwc_ether_rx(struct eth_device *dev) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ u32 desc_num = priv->rx_currdescnum; ++ struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num]; ++ ++ u32 status = desc_p->txrx_status; ++ int length = 0; ++ ++ /* Check if the owner is the CPU */ ++ if (status & DESC_RXSTS_OWNBYDMA) ++ return 0; ++ ++ length = (status & DESC_RXSTS_FRMLENMSK) >> \ ++ DESC_RXSTS_FRMLENSHFT; ++ ++ net_receive(desc_p->dmamac_addr, length); ++ ++ /* ++ * Make the current descriptor valid again and go to ++ * the next one ++ */ ++ dma_inv_range((unsigned long)desc_p->dmamac_addr, ++ (unsigned long)desc_p->dmamac_addr + length); ++ desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA; ++ ++ /* Test the wrap-around condition. */ ++ if (++desc_num >= CONFIG_RX_DESCR_NUM) ++ desc_num = 0; ++ ++ priv->rx_currdescnum = desc_num; ++ ++ return length; ++} ++ ++static void dwc_ether_halt (struct eth_device *dev) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ ++ mac_reset(dev); ++ priv->tx_currdescnum = priv->rx_currdescnum = 0; ++} ++ ++static int dwc_ether_get_ethaddr(struct eth_device *dev, u8 adr[6]) ++{ ++ /* we have no EEPROM */ ++ return -1; ++} ++ ++static int dwc_ether_set_ethaddr(struct eth_device *dev, u8 adr[6]) ++{ ++ struct dw_eth_dev *priv = dev->priv; ++ struct eth_mac_regs *mac_p = priv->mac_regs_p; ++ u32 macid_lo, macid_hi; ++ ++ macid_lo = adr[0] + (adr[1] << 8) + \ ++ (adr[2] << 16) + (adr[3] << 24); ++ macid_hi = adr[4] + (adr[5] << 8); ++ writel(macid_hi, &mac_p->macaddr0hi); ++ writel(macid_lo, &mac_p->macaddr0lo); ++ memcpy(priv->macaddr, adr, 6); ++ return 0; ++} ++ ++static int dwc_ether_probe(struct device_d *dev) ++{ ++ struct dw_eth_dev *priv; ++ struct eth_device *edev; ++ struct mii_device *miidev; ++ void __iomem *base; ++ struct dwc_ether_platform_data *pdata = dev->platform_data; ++ ++ if (!pdata) { ++ printf("dwc_ether: no platform_data\n"); ++ return -ENODEV; ++ } ++ ++ priv = xzalloc(sizeof(struct dw_eth_dev)); ++ ++ base = dev_request_mem_region(dev, 0); ++ priv->mac_regs_p = base; ++ dev_info(dev, "MAC version %08x\n", readl(&priv->mac_regs_p->version)); ++ priv->dma_regs_p = base + DW_DMA_BASE_OFFSET; ++ priv->tx_mac_descrtable = dma_alloc_coherent( ++ CONFIG_TX_DESCR_NUM * sizeof(struct dmamacdescr)); ++ priv->rx_mac_descrtable = dma_alloc_coherent( ++ CONFIG_RX_DESCR_NUM * sizeof(struct dmamacdescr)); ++ priv->txbuffs = malloc(TX_TOTAL_BUFSIZE); ++ priv->rxbuffs = malloc(RX_TOTAL_BUFSIZE); ++ priv->fix_mac_speed = pdata->fix_mac_speed; ++ ++ edev = &priv->netdev; ++ miidev = &priv->miidev; ++ edev->priv = priv; ++ ++ edev->init = dwc_ether_init; ++ edev->open = dwc_ether_open; ++ edev->send = dwc_ether_send; ++ edev->recv = dwc_ether_rx; ++ edev->halt = dwc_ether_halt; ++ edev->get_ethaddr = dwc_ether_get_ethaddr; ++ edev->set_ethaddr = dwc_ether_set_ethaddr; ++ ++ miidev->address = pdata->phy_addr; ++ miidev->read = dwc_ether_mii_read; ++ miidev->write = dwc_ether_mii_write; ++ miidev->edev = edev; ++ ++ mii_register(miidev); ++ eth_register(edev); ++ return 0; ++} ++ ++static void dwc_ether_remove(struct device_d *dev) ++{ ++} ++ ++static struct driver_d dwc_ether_driver = { ++ .name = "designware_eth", ++ .probe = dwc_ether_probe, ++ .remove = dwc_ether_remove, ++}; ++ ++static int dwc_ether_driver_init(void) ++{ ++ register_driver(&dwc_ether_driver); ++ return 0; ++} ++device_initcall(dwc_ether_driver_init); +diff --git a/drivers/net/designware.h b/drivers/net/designware.h +new file mode 100644 +index 0000000..db2ead4 +--- /dev/null ++++ b/drivers/net/designware.h +@@ -0,0 +1,230 @@ ++/* ++ * (C) Copyright 2010 ++ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. ++ * ++ * 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 __DESIGNWARE_ETH_H ++#define __DESIGNWARE_ETH_H ++ ++#define CONFIG_TX_DESCR_NUM 16 ++#define CONFIG_RX_DESCR_NUM 16 ++#define CONFIG_ETH_BUFSIZE 2048 ++#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM) ++#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM) ++ ++struct eth_mac_regs { ++ u32 conf; /* 0x00 */ ++ u32 framefilt; /* 0x04 */ ++ u32 hashtablehigh; /* 0x08 */ ++ u32 hashtablelow; /* 0x0c */ ++ u32 miiaddr; /* 0x10 */ ++ u32 miidata; /* 0x14 */ ++ u32 flowcontrol; /* 0x18 */ ++ u32 vlantag; /* 0x1c */ ++ u32 version; /* 0x20 */ ++ u8 reserved_1[20]; ++ u32 intreg; /* 0x38 */ ++ u32 intmask; /* 0x3c */ ++ u32 macaddr0hi; /* 0x40 */ ++ u32 macaddr0lo; /* 0x44 */ ++}; ++ ++/* MAC configuration register definitions */ ++#define FRAMEBURSTENABLE (1 << 21) ++#define MII_PORTSELECT (1 << 15) ++#define FES_100 (1 << 14) ++#define DISABLERXOWN (1 << 13) ++#define FULLDPLXMODE (1 << 11) ++#define RXENABLE (1 << 2) ++#define TXENABLE (1 << 3) ++ ++/* MII address register definitions */ ++#define MII_BUSY (1 << 0) ++#define MII_WRITE (1 << 1) ++#define MII_CLKRANGE_60_100M (0) ++#define MII_CLKRANGE_100_150M (0x4) ++#define MII_CLKRANGE_20_35M (0x8) ++#define MII_CLKRANGE_35_60M (0xC) ++#define MII_CLKRANGE_150_250M (0x10) ++#define MII_CLKRANGE_250_300M (0x14) ++ ++#define MIIADDRSHIFT (11) ++#define MIIREGSHIFT (6) ++#define MII_REGMSK (0x1F << 6) ++#define MII_ADDRMSK (0x1F << 11) ++ ++ ++struct eth_dma_regs { ++ u32 busmode; /* 0x00 */ ++ u32 txpolldemand; /* 0x04 */ ++ u32 rxpolldemand; /* 0x08 */ ++ u32 rxdesclistaddr; /* 0x0c */ ++ u32 txdesclistaddr; /* 0x10 */ ++ u32 status; /* 0x14 */ ++ u32 opmode; /* 0x18 */ ++ u32 intenable; /* 0x1c */ ++ u8 reserved[40]; ++ u32 currhosttxdesc; /* 0x48 */ ++ u32 currhostrxdesc; /* 0x4c */ ++ u32 currhosttxbuffaddr; /* 0x50 */ ++ u32 currhostrxbuffaddr; /* 0x54 */ ++}; ++ ++#define DW_DMA_BASE_OFFSET (0x1000) ++ ++/* Bus mode register definitions */ ++#define FIXEDBURST (1 << 16) ++#define PRIORXTX_41 (3 << 14) ++#define PRIORXTX_31 (2 << 14) ++#define PRIORXTX_21 (1 << 14) ++#define PRIORXTX_11 (0 << 14) ++#define BURST_1 (1 << 8) ++#define BURST_2 (2 << 8) ++#define BURST_4 (4 << 8) ++#define BURST_8 (8 << 8) ++#define BURST_16 (16 << 8) ++#define BURST_32 (32 << 8) ++#define RXHIGHPRIO (1 << 1) ++#define DMAMAC_SRST (1 << 0) ++ ++/* Poll demand definitions */ ++#define POLL_DATA (0xFFFFFFFF) ++ ++/* Operation mode definitions */ ++#define STOREFORWARD (1 << 21) ++#define FLUSHTXFIFO (1 << 20) ++#define TXSTART (1 << 13) ++#define TXSECONDFRAME (1 << 2) ++#define RXSTART (1 << 1) ++ ++/* Descriptior related definitions */ ++#define MAC_MAX_FRAME_SZ (1600) ++ ++struct dmamacdescr { ++ u32 txrx_status; ++ u32 dmamac_cntl; ++ void *dmamac_addr; ++ struct dmamacdescr *dmamac_next; ++}; ++ ++/* ++ * txrx_status definitions ++ */ ++ ++/* tx status bits definitions */ ++#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) ++ ++#define DESC_TXSTS_OWNBYDMA (1 << 31) ++#define DESC_TXSTS_TXINT (1 << 30) ++#define DESC_TXSTS_TXLAST (1 << 29) ++#define DESC_TXSTS_TXFIRST (1 << 28) ++#define DESC_TXSTS_TXCRCDIS (1 << 27) ++ ++#define DESC_TXSTS_TXPADDIS (1 << 26) ++#define DESC_TXSTS_TXCHECKINSCTRL (3 << 22) ++#define DESC_TXSTS_TXRINGEND (1 << 21) ++#define DESC_TXSTS_TXCHAIN (1 << 20) ++#define DESC_TXSTS_MSK (0x1FFFF << 0) ++ ++#else ++ ++#define DESC_TXSTS_OWNBYDMA (1 << 31) ++#define DESC_TXSTS_MSK (0x1FFFF << 0) ++ ++#endif ++ ++/* rx status bits definitions */ ++#define DESC_RXSTS_OWNBYDMA (1 << 31) ++#define DESC_RXSTS_DAFILTERFAIL (1 << 30) ++#define DESC_RXSTS_FRMLENMSK (0x3FFF << 16) ++#define DESC_RXSTS_FRMLENSHFT (16) ++ ++#define DESC_RXSTS_ERROR (1 << 15) ++#define DESC_RXSTS_RXTRUNCATED (1 << 14) ++#define DESC_RXSTS_SAFILTERFAIL (1 << 13) ++#define DESC_RXSTS_RXIPC_GIANTFRAME (1 << 12) ++#define DESC_RXSTS_RXDAMAGED (1 << 11) ++#define DESC_RXSTS_RXVLANTAG (1 << 10) ++#define DESC_RXSTS_RXFIRST (1 << 9) ++#define DESC_RXSTS_RXLAST (1 << 8) ++#define DESC_RXSTS_RXIPC_GIANT (1 << 7) ++#define DESC_RXSTS_RXCOLLISION (1 << 6) ++#define DESC_RXSTS_RXFRAMEETHER (1 << 5) ++#define DESC_RXSTS_RXWATCHDOG (1 << 4) ++#define DESC_RXSTS_RXMIIERROR (1 << 3) ++#define DESC_RXSTS_RXDRIBBLING (1 << 2) ++#define DESC_RXSTS_RXCRC (1 << 1) ++ ++/* ++ * dmamac_cntl definitions ++ */ ++ ++/* tx control bits definitions */ ++#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) ++ ++#define DESC_TXCTRL_SIZE1MASK (0x1FFF << 0) ++#define DESC_TXCTRL_SIZE1SHFT (0) ++#define DESC_TXCTRL_SIZE2MASK (0x1FFF << 16) ++#define DESC_TXCTRL_SIZE2SHFT (16) ++ ++#else ++ ++#define DESC_TXCTRL_TXINT (1 << 31) ++#define DESC_TXCTRL_TXLAST (1 << 30) ++#define DESC_TXCTRL_TXFIRST (1 << 29) ++#define DESC_TXCTRL_TXCHECKINSCTRL (3 << 27) ++#define DESC_TXCTRL_TXCRCDIS (1 << 26) ++#define DESC_TXCTRL_TXRINGEND (1 << 25) ++#define DESC_TXCTRL_TXCHAIN (1 << 24) ++ ++#define DESC_TXCTRL_SIZE1MASK (0x7FF << 0) ++#define DESC_TXCTRL_SIZE1SHFT (0) ++#define DESC_TXCTRL_SIZE2MASK (0x7FF << 11) ++#define DESC_TXCTRL_SIZE2SHFT (11) ++ ++#endif ++ ++/* rx control bits definitions */ ++#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) ++ ++#define DESC_RXCTRL_RXINTDIS (1 << 31) ++#define DESC_RXCTRL_RXRINGEND (1 << 15) ++#define DESC_RXCTRL_RXCHAIN (1 << 14) ++ ++#define DESC_RXCTRL_SIZE1MASK (0x1FFF << 0) ++#define DESC_RXCTRL_SIZE1SHFT (0) ++#define DESC_RXCTRL_SIZE2MASK (0x1FFF << 16) ++#define DESC_RXCTRL_SIZE2SHFT (16) ++ ++#else ++ ++#define DESC_RXCTRL_RXINTDIS (1 << 31) ++#define DESC_RXCTRL_RXRINGEND (1 << 25) ++#define DESC_RXCTRL_RXCHAIN (1 << 24) ++ ++#define DESC_RXCTRL_SIZE1MASK (0x7FF << 0) ++#define DESC_RXCTRL_SIZE1SHFT (0) ++#define DESC_RXCTRL_SIZE2MASK (0x7FF << 11) ++#define DESC_RXCTRL_SIZE2SHFT (11) ++ ++#endif ++ ++#endif +diff --git a/drivers/net/miidev.c b/drivers/net/miidev.c +index f47fc9e..b49944b 100644 +--- a/drivers/net/miidev.c ++++ b/drivers/net/miidev.c +@@ -123,7 +123,7 @@ int miidev_wait_aneg(struct mii_device *mdev) + + int miidev_get_status(struct mii_device *mdev) + { +- int ret, status; ++ int ret, status, adv, lpa; + + ret = mii_read(mdev, mdev->address, MII_BMSR); + if (ret < 0) +@@ -136,13 +136,31 @@ int miidev_get_status(struct mii_device *mdev) + goto err_out; + + if (ret & BMCR_ANENABLE) { +- ret = mii_read(mdev, mdev->address, MII_LPA); +- if (ret < 0) ++ if (mdev->capabilities & MIIDEV_CAPABLE_1000M) { ++ lpa = mii_read(mdev, mdev->address, MII_STAT1000); ++ if (lpa < 0) ++ goto err_out; ++ adv = mii_read(mdev, mdev->address, MII_CTRL1000); ++ if (adv < 0) ++ goto err_out; ++ lpa &= adv << 2; ++ if (lpa & (LPA_1000FULL | LPA_1000HALF)) { ++ if (lpa & LPA_1000FULL) ++ status |= MIIDEV_STATUS_IS_FULL_DUPLEX; ++ status |= MIIDEV_STATUS_IS_1000MBIT; ++ return status; ++ } ++ } ++ lpa = mii_read(mdev, mdev->address, MII_LPA); ++ if (lpa < 0) + goto err_out; +- +- status |= ret & LPA_DUPLEX ? MIIDEV_STATUS_IS_FULL_DUPLEX : 0; +- status |= ret & LPA_100 ? MIIDEV_STATUS_IS_100MBIT : +- MIIDEV_STATUS_IS_10MBIT; ++ adv = mii_read(mdev, mdev->address, MII_ADVERTISE); ++ if (adv < 0) ++ goto err_out; ++ lpa &= adv; ++ status |= lpa & LPA_DUPLEX ? MIIDEV_STATUS_IS_FULL_DUPLEX : 0; ++ status |= lpa & LPA_100 ? MIIDEV_STATUS_IS_100MBIT : ++ MIIDEV_STATUS_IS_10MBIT; + } else { + status |= ret & BMCR_FULLDPLX ? MIIDEV_STATUS_IS_FULL_DUPLEX : 0; + status |= ret & BMCR_SPEED100 ? MIIDEV_STATUS_IS_100MBIT : +@@ -170,8 +188,8 @@ int miidev_print_status(struct mii_device *mdev) + return status; + + duplex = status & MIIDEV_STATUS_IS_FULL_DUPLEX ? "Full" : "Half"; +- speed = status & MIIDEV_STATUS_IS_100MBIT ? 100 : 10; +- ++ speed = status & MIIDEV_STATUS_IS_1000MBIT ? 1000 : ++ (status & MIIDEV_STATUS_IS_100MBIT ? 100 : 10); + + printf("%s: Link is %s", mdev->cdev.name, + status & MIIDEV_STATUS_IS_UP ? "up" : "down"); +@@ -180,33 +198,33 @@ int miidev_print_status(struct mii_device *mdev) + return 0; + } + +-static ssize_t miidev_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t miidev_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) + { + int i = count; + uint16_t *buf = _buf; + struct mii_device *mdev = cdev->priv; + +- while (i > 1) { +- *buf = mii_read(mdev, mdev->address, offset); ++ while (i > 0) { ++ *buf = mii_read(mdev, mdev->address, offset / 2); + buf++; + i -= 2; +- offset++; ++ offset += 2; + } + + return count; + } + +-static ssize_t miidev_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags) ++static ssize_t miidev_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags) + { + int i = count; + const uint16_t *buf = _buf; + struct mii_device *mdev = cdev->priv; + +- while (i > 1) { +- mii_write(mdev, mdev->address, offset, *buf); ++ while (i > 0) { ++ mii_write(mdev, mdev->address, offset / 2, *buf); + buf++; + i -= 2; +- offset++; ++ offset += 2; + } + + return count; +@@ -221,7 +239,27 @@ static struct file_operations miidev_ops = { + static int miidev_probe(struct device_d *dev) + { + struct mii_device *mdev = dev->priv; ++ int val; ++ int caps = 0; + ++ val = mii_read(mdev, mdev->address, MII_PHYSID1); ++ if (val < 0 || val == 0xffff) ++ goto err_out; ++ val = mii_read(mdev, mdev->address, MII_PHYSID2); ++ if (val < 0 || val == 0xffff) ++ goto err_out; ++ val = mii_read(mdev, mdev->address, MII_BMSR); ++ if (val < 0) ++ goto err_out; ++ if (val & BMSR_ESTATEN) { ++ val = mii_read(mdev, mdev->address, MII_ESTATUS); ++ if (val < 0) ++ goto err_out; ++ if (val & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) ++ caps = MIIDEV_CAPABLE_1000M; ++ } ++ ++ mdev->capabilities = caps; + mdev->cdev.name = asprintf("phy%d", dev->id); + mdev->cdev.size = 64; + mdev->cdev.ops = &miidev_ops; +@@ -230,6 +268,10 @@ static int miidev_probe(struct device_d *dev) + devfs_create(&mdev->cdev); + list_add_tail(&mdev->list, &miidev_list); + return 0; ++ ++err_out: ++ dev_err(dev, "cannot read PHY registers (addr %d)\n", mdev->address); ++ return -ENODEV; + } + + static void miidev_remove(struct device_d *dev) +diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c +index 800c188..7dddbbc 100644 +--- a/drivers/net/smc911x.c ++++ b/drivers/net/smc911x.c +@@ -691,7 +691,7 @@ static int smc911x_probe(struct device_d *dev) + struct smc911x_priv *priv; + uint32_t val; + int i; +- void *base; ++ void __iomem *base; + + base = dev_request_mem_region(dev, 0); + +diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c +index 654e647..16885c0 100644 +--- a/drivers/nor/cfi_flash.c ++++ b/drivers/nor/cfi_flash.c +@@ -82,9 +82,9 @@ static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c) + return; + } + +-#if __BYTE_ORDER == __BIG_ENDIAN ++#ifdef __BIG_ENDIAN + *cword = (*cword << 8) | c; +-#else ++#elif defined __LITTLE_ENDIAN + + if (bankwidth_is_2(info)) + *cword = (*cword >> 8) | (u16)c << 8; +@@ -92,6 +92,8 @@ static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c) + *cword = (*cword >> 8) | (u32)c << 24; + else if (bankwidth_is_8(info)) + *cword = (*cword >> 8) | (u64)c << 56; ++#else ++#error "could not determine byte order" + #endif + } + +@@ -167,7 +169,7 @@ static void flash_printqry (struct cfi_qry *qry) + uchar flash_read_uchar (struct flash_info *info, uint offset) + { + uchar *cp = flash_make_addr(info, 0, offset); +-#if __BYTE_ORDER == __LITTLE_ENDIAN ++#if defined __LITTLE_ENDIAN + return flash_read8(cp); + #else + return flash_read8(cp + info->portwidth - 1); +@@ -195,7 +197,7 @@ static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint o + debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x)); + } + #endif +-#if __BYTE_ORDER == __LITTLE_ENDIAN ++#if defined __LITTLE_ENDIAN + retval = ((flash_read8(addr) << 16) | + (flash_read8(addr + info->portwidth) << 24) | + (flash_read8(addr + 2 * info->portwidth)) | +@@ -456,7 +458,7 @@ flash_sect_t find_sector (struct flash_info *info, ulong addr) + return sector; + } + +-static int __cfi_erase(struct cdev *cdev, size_t count, unsigned long offset, ++static int __cfi_erase(struct cdev *cdev, size_t count, loff_t offset, + int verbose) + { + struct flash_info *finfo = (struct flash_info *)cdev->priv; +@@ -491,7 +493,7 @@ out: + return ret; + } + +-static int cfi_erase(struct cdev *cdev, size_t count, unsigned long offset) ++static int cfi_erase(struct cdev *cdev, size_t count, loff_t offset) + { + return __cfi_erase(cdev, count, offset, 1); + } +@@ -628,7 +630,7 @@ static int flash_real_protect (struct flash_info *info, long sector, int prot) + return retcode; + } + +-static int cfi_protect(struct cdev *cdev, size_t count, unsigned long offset, int prot) ++static int cfi_protect(struct cdev *cdev, size_t count, loff_t offset, int prot) + { + struct flash_info *finfo = (struct flash_info *)cdev->priv; + unsigned long start, end; +@@ -651,7 +653,7 @@ out: + return ret; + } + +-static ssize_t cfi_write(struct cdev *cdev, const void *buf, size_t count, unsigned long offset, ulong flags) ++static ssize_t cfi_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) + { + struct flash_info *finfo = (struct flash_info *)cdev->priv; + int ret; +diff --git a/drivers/nor/m25p80.c b/drivers/nor/m25p80.c +index 77669c2..1440227 100644 +--- a/drivers/nor/m25p80.c ++++ b/drivers/nor/m25p80.c +@@ -194,13 +194,14 @@ static int erase_sector(struct m25p *flash, u32 offset) + * Erase an address range on the flash chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. + */ +-static ssize_t m25p80_erase(struct cdev *cdev, size_t count, unsigned long offset) ++static ssize_t m25p80_erase(struct cdev *cdev, size_t count, loff_t offset) + { + struct m25p *flash = cdev->priv; + u32 addr, len; + u32 start_sector; + u32 end_sector; + u32 progress = 0; ++ int eraseshift = ffs(flash->erasesize) - 1; + + dev_dbg(&flash->spi->dev, "%s %s 0x%llx, len %lld\n", + __func__, "at", (long long)offset, (long long)count); +@@ -212,8 +213,8 @@ static ssize_t m25p80_erase(struct cdev *cdev, size_t count, unsigned long offse + addr = offset; + len = count; + +- start_sector = offset / flash->erasesize; +- end_sector = (offset + count - 1) / flash->erasesize; ++ start_sector = offset >> eraseshift; ++ end_sector = (offset + count - 1) >> eraseshift; + init_progression_bar(end_sector - start_sector + 1); + + /* whole-chip erase? */ +@@ -250,7 +251,8 @@ static ssize_t m25p80_erase(struct cdev *cdev, size_t count, unsigned long offse + return 0; + } + +-ssize_t m25p80_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags) ++ssize_t m25p80_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ++ ulong flags) + { + struct m25p *flash = cdev->priv; + struct spi_transfer t[2]; +@@ -302,7 +304,8 @@ ssize_t m25p80_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ul + return retlen; + } + +-ssize_t m25p80_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) ++ssize_t m25p80_write(struct cdev *cdev, const void *buf, size_t count, ++ loff_t offset, ulong flags) + { + struct m25p *flash = cdev->priv; + struct spi_transfer t[2]; +@@ -381,7 +384,8 @@ ssize_t m25p80_write(struct cdev *cdev, const void *buf, size_t count, ulong off + return retlen; + } + #ifdef CONFIG_MTD_SST25L +-ssize_t sst_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) ++ssize_t sst_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ++ ulong flags) + { + struct m25p *flash = cdev->priv; + struct spi_transfer t[2]; +diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c +index bd2938d..a5075d5 100644 +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -52,6 +52,7 @@ + #include <asm/byteorder.h> + #include <xfuncs.h> + #include <init.h> ++#include <dma.h> + + #include <usb/usb.h> + +@@ -67,7 +68,6 @@ + + static int dev_index; + static int asynch_allowed; +-static struct devrequest setup_packet; + + static int usb_hub_probe(struct usb_device *dev, int ifnum); + static int hub_port_reset(struct usb_device *dev, int port, +@@ -80,8 +80,8 @@ static void print_usb_device(struct usb_device *dev) + { + printf("Bus %03d Device %03d: ID %04x:%04x %s\n", + dev->host->busnum, dev->devnum, +- dev->descriptor.idVendor, +- dev->descriptor.idProduct, ++ dev->descriptor->idVendor, ++ dev->descriptor->idProduct, + dev->prod); + } + +@@ -299,12 +299,14 @@ static int usb_new_device(struct usb_device *dev) + { + int addr, err; + int tmp; +- unsigned char tmpbuf[USB_BUFSIZ]; ++ void *buf; + struct usb_device_descriptor *desc; + int port = -1; + struct usb_device *parent = dev->parent; + unsigned short portstatus; + ++ buf = dma_alloc(USB_BUFSIZ); ++ + /* We still haven't set the Address yet */ + addr = dev->devnum; + dev->devnum = 0; +@@ -322,8 +324,8 @@ static int usb_new_device(struct usb_device *dev) + * the maxpacket size is 8 or 16 the device may be waiting to transmit + * some more, or keeps on retransmitting the 8 byte header. */ + +- desc = (struct usb_device_descriptor *)tmpbuf; +- dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */ ++ desc = buf; ++ dev->descriptor->bMaxPacketSize0 = 64; /* Start off at 64 bytes */ + /* Default to 64 byte max packet size */ + dev->maxpacketsize = PACKET_SIZE_64; + dev->epmaxpacketin[0] = 64; +@@ -332,10 +334,10 @@ static int usb_new_device(struct usb_device *dev) + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); + if (err < 0) { + USB_PRINTF("%s: usb_get_descriptor() failed with %d\n", __func__, err); +- return 1; ++ goto err_out; + } + +- dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; ++ dev->descriptor->bMaxPacketSize0 = desc->bMaxPacketSize0; + + /* find the port number we're at */ + if (parent) { +@@ -349,20 +351,21 @@ static int usb_new_device(struct usb_device *dev) + } + if (port < 0) { + printf("%s: cannot locate device's port.\n", __func__); +- return 1; ++ err = -ENODEV; ++ goto err_out; + } + + /* reset the port for the second time */ + err = hub_port_reset(dev->parent, port, &portstatus); + if (err < 0) { + printf("\n Couldn't reset port %i\n", port); +- return 1; ++ goto err_out; + } + } + +- dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; +- dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; +- switch (dev->descriptor.bMaxPacketSize0) { ++ dev->epmaxpacketin[0] = dev->descriptor->bMaxPacketSize0; ++ dev->epmaxpacketout[0] = dev->descriptor->bMaxPacketSize0; ++ switch (dev->descriptor->bMaxPacketSize0) { + case 8: + dev->maxpacketsize = PACKET_SIZE_8; + break; +@@ -383,15 +386,15 @@ static int usb_new_device(struct usb_device *dev) + if (err < 0) { + printf("\n USB device not accepting new address " \ + "(error=%lX)\n", dev->status); +- return 1; ++ goto err_out; + } + + wait_ms(10); /* Let the SET_ADDRESS settle */ + +- tmp = sizeof(dev->descriptor); ++ tmp = sizeof(*dev->descriptor); + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, +- &dev->descriptor, sizeof(dev->descriptor)); ++ dev->descriptor, sizeof(*dev->descriptor)); + if (err < tmp) { + if (err < 0) + printf("unable to get device descriptor (error=%d)\n", +@@ -399,37 +402,37 @@ static int usb_new_device(struct usb_device *dev) + else + printf("USB device descriptor short read " \ + "(expected %i, got %i)\n", tmp, err); +- return 1; ++ goto err_out; + } + /* correct le values */ +- le16_to_cpus(&dev->descriptor.bcdUSB); +- le16_to_cpus(&dev->descriptor.idVendor); +- le16_to_cpus(&dev->descriptor.idProduct); +- le16_to_cpus(&dev->descriptor.bcdDevice); ++ le16_to_cpus(&dev->descriptor->bcdUSB); ++ le16_to_cpus(&dev->descriptor->idVendor); ++ le16_to_cpus(&dev->descriptor->idProduct); ++ le16_to_cpus(&dev->descriptor->bcdDevice); + /* only support for one config for now */ +- usb_get_configuration_no(dev, &tmpbuf[0], 0); +- usb_parse_config(dev, &tmpbuf[0], 0); ++ usb_get_configuration_no(dev, buf, 0); ++ usb_parse_config(dev, buf, 0); + usb_set_maxpacket(dev); + /* we set the default configuration here */ + if (usb_set_configuration(dev, dev->config.bConfigurationValue)) { + printf("failed to set default configuration " \ + "len %d, status %lX\n", dev->act_len, dev->status); +- return -1; ++ goto err_out; + } + USB_PRINTF("new device: Mfr=%d, Product=%d, SerialNumber=%d\n", +- dev->descriptor.iManufacturer, dev->descriptor.iProduct, +- dev->descriptor.iSerialNumber); ++ dev->descriptor->iManufacturer, dev->descriptor->iProduct, ++ dev->descriptor->iSerialNumber); + memset(dev->mf, 0, sizeof(dev->mf)); + memset(dev->prod, 0, sizeof(dev->prod)); + memset(dev->serial, 0, sizeof(dev->serial)); +- if (dev->descriptor.iManufacturer) +- usb_string(dev, dev->descriptor.iManufacturer, ++ if (dev->descriptor->iManufacturer) ++ usb_string(dev, dev->descriptor->iManufacturer, + dev->mf, sizeof(dev->mf)); +- if (dev->descriptor.iProduct) +- usb_string(dev, dev->descriptor.iProduct, ++ if (dev->descriptor->iProduct) ++ usb_string(dev, dev->descriptor->iProduct, + dev->prod, sizeof(dev->prod)); +- if (dev->descriptor.iSerialNumber) +- usb_string(dev, dev->descriptor.iSerialNumber, ++ if (dev->descriptor->iSerialNumber) ++ usb_string(dev, dev->descriptor->iSerialNumber, + dev->serial, sizeof(dev->serial)); + /* now prode if the device is a hub */ + usb_hub_probe(dev, 0); +@@ -441,7 +444,11 @@ static int usb_new_device(struct usb_device *dev) + register_device(&dev->dev); + list_add_tail(&dev->list, &usb_device_list); + +- return 0; ++ err = 0; ++ ++err_out: ++ dma_free(buf); ++ return err; + } + + static struct usb_device *usb_alloc_new_device(void) +@@ -454,6 +461,8 @@ static struct usb_device *usb_alloc_new_device(void) + usbdev->devnum = dev_index + 1; + usbdev->maxchild = 0; + usbdev->dev.bus = &usb_bus_type; ++ usbdev->setup_packet = dma_alloc(sizeof(*usbdev->setup_packet)); ++ usbdev->descriptor = dma_alloc(sizeof(*usbdev->descriptor)); + + dev_index++; + +@@ -471,6 +480,8 @@ void usb_rescan(void) + unregister_device(&dev->dev); + if (dev->hub) + free(dev->hub); ++ dma_free(dev->setup_packet); ++ dma_free(dev->descriptor); + free(dev); + } + +@@ -532,6 +543,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, + { + struct usb_host *host = dev->host; + int ret; ++ struct devrequest *setup_packet = dev->setup_packet; + + if ((timeout == 0) && (!asynch_allowed)) { + /* request for a asynch control pipe is not allowed */ +@@ -539,17 +551,18 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, + } + + /* set setup command */ +- setup_packet.requesttype = requesttype; +- setup_packet.request = request; +- setup_packet.value = cpu_to_le16(value); +- setup_packet.index = cpu_to_le16(index); +- setup_packet.length = cpu_to_le16(size); ++ setup_packet->requesttype = requesttype; ++ setup_packet->request = request; ++ setup_packet->value = cpu_to_le16(value); ++ setup_packet->index = cpu_to_le16(index); ++ setup_packet->length = cpu_to_le16(size); + USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X, " \ + "value 0x%X index 0x%X length 0x%X\n", + request, requesttype, value, index, size); + dev->status = USB_ST_NOT_PROC; /*not yet processed */ + +- ret = host->submit_control_msg(dev, pipe, data, size, &setup_packet, timeout); ++ ret = host->submit_control_msg(dev, pipe, data, size, setup_packet, ++ timeout); + if (ret) + return ret; + +@@ -1284,11 +1297,11 @@ int usb_driver_register(struct usb_driver *drv) + static int usb_match_device(struct usb_device *dev, const struct usb_device_id *id) + { + if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && +- id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) ++ id->idVendor != le16_to_cpu(dev->descriptor->idVendor)) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && +- id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) ++ id->idProduct != le16_to_cpu(dev->descriptor->idProduct)) + return 0; + + return 1; +@@ -1311,7 +1324,7 @@ static int usb_match_one_id(struct usb_device *usbdev, + /* The interface class, subclass, and protocol should never be + * checked for a match if the device class is Vendor Specific, + * unless the match record specifies the Vendor ID. */ +- if (usbdev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC && ++ if (usbdev->descriptor->bDeviceClass == USB_CLASS_VENDOR_SPEC && + !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && + (id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO)) + return 0; +@@ -1371,7 +1384,8 @@ static int usb_match(struct device_d *dev, struct driver_d *drv) + struct usb_driver *usbdrv = container_of(dev->driver, struct usb_driver, driver); + const struct usb_device_id *id; + +- debug("matching: 0x%04x 0x%04x\n", usbdev->descriptor.idVendor, usbdev->descriptor.idProduct); ++ debug("matching: 0x%04x 0x%04x\n", usbdev->descriptor->idVendor, ++ usbdev->descriptor->idProduct); + + id = usb_match_id(usbdev, usbdrv->id_table); + if (id) { +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index fd70e62..44e58d7 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -22,6 +22,7 @@ + + #include <common.h> + #include <errno.h> ++#include <dma.h> + #include <usb/composite.h> + #include <asm/byteorder.h> + +@@ -867,7 +868,7 @@ composite_unbind(struct usb_gadget *gadget) + composite->unbind(cdev); + + if (cdev->req) { +- kfree(cdev->req->buf); ++ dma_free(cdev->req->buf); + usb_ep_free_request(gadget->ep0, cdev->req); + } + kfree(cdev); +@@ -911,7 +912,7 @@ static int __init composite_bind(struct usb_gadget *gadget) + cdev->req = usb_ep_alloc_request(gadget->ep0); + if (!cdev->req) + goto fail; +- cdev->req->buf = malloc(USB_BUFSIZ); ++ cdev->req->buf = dma_alloc(USB_BUFSIZ); + if (!cdev->req->buf) + goto fail; + cdev->req->complete = composite_setup_complete; +diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c +index f26c1e4..e205c65 100644 +--- a/drivers/usb/gadget/dfu.c ++++ b/drivers/usb/gadget/dfu.c +@@ -40,6 +40,7 @@ + * - make 'dnstate' attached to 'struct usb_device_instance' + */ + ++#include <dma.h> + #include <asm/byteorder.h> + #include <usb/composite.h> + #include <linux/types.h> +@@ -183,7 +184,7 @@ dfu_unbind(struct usb_configuration *c, struct usb_function *f) + if (gadget_is_dualspeed(c->cdev->gadget)) + free(f->hs_descriptors); + +- free(dfu->dnreq->buf); ++ dma_free(dfu->dnreq->buf); + usb_ep_free_request(c->cdev->gadget->ep0, dfu->dnreq); + free(dfu); + } +@@ -602,7 +603,7 @@ static int dfu_bind_config(struct usb_configuration *c) + dfu->dnreq = usb_ep_alloc_request(c->cdev->gadget->ep0); + if (!dfu->dnreq) + printf("usb_ep_alloc_request failed\n"); +- dfu->dnreq->buf = xmalloc(CONFIG_USBD_DFU_XFER_SIZE); ++ dfu->dnreq->buf = dma_alloc(CONFIG_USBD_DFU_XFER_SIZE); + dfu->dnreq->complete = dn_complete; + dfu->dnreq->zero = 0; + +diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c +index 5b64ec2..5537a0e 100644 +--- a/drivers/usb/gadget/fsl_udc.c ++++ b/drivers/usb/gadget/fsl_udc.c +@@ -1,5 +1,6 @@ + #include <common.h> + #include <errno.h> ++#include <dma.h> + #include <init.h> + #include <clock.h> + #include <usb/ch9.h> +@@ -8,7 +9,6 @@ + #include <io.h> + #include <poller.h> + #include <asm/byteorder.h> +-#include <asm/mmu.h> + + /* ### define USB registers here + */ +@@ -519,7 +519,7 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) + * 2 + ((windex & USB_DIR_IN) ? 1 : 0)) + #define get_pipe_by_ep(EP) (ep_index(EP) * 2 + ep_is_in(EP)) + +-static struct usb_dr_device *dr_regs; ++static struct usb_dr_device __iomem *dr_regs; + static struct fsl_udc *udc_controller = NULL; + + static const struct usb_endpoint_descriptor +@@ -2109,7 +2109,8 @@ static int struct_udc_setup(struct fsl_udc *udc, + udc->status_req = container_of(fsl_alloc_request(NULL), + struct fsl_req, req); + /* allocate a small amount of memory to get valid address */ +- udc->status_req->req.buf = xmalloc(8); ++ udc->status_req->req.buf = dma_alloc(8); ++ udc->status_req->req.length = 8; + udc->resume_state = USB_STATE_NOTATTACHED; + udc->usb_state = USB_STATE_POWERED; + udc->ep0_dir = 0; +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index a2473a9..c2f48ce 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -120,63 +120,6 @@ static struct descriptor { + + #define ehci_is_TDI() (ehci->flags & EHCI_HAS_TT) + +-#ifdef CONFIG_MMU +-/* +- * Routines to handle (flush/invalidate) the dcache for the QH and qTD +- * structures and data buffers. This is needed on platforms using this +- * EHCI support with dcache enabled. +- */ +-static void flush_invalidate(void *addr, int size, int flush) +-{ +- if (flush) { +- dma_flush_range((unsigned long)addr, (unsigned long)(addr + size)); +- } else { +- dma_inv_range((unsigned long)addr, (unsigned long)(addr + size)); +- } +-} +- +-static void cache_qtd(struct qTD *qtd, int flush) +-{ +- u32 *ptr = (u32 *)qtd->qt_buffer[0]; +- int len = (qtd->qt_token & 0x7fff0000) >> 16; +- +- if (ptr && len) +- flush_invalidate(ptr, len, flush); +-} +- +-static void cache_qh(struct ehci_priv *ehci, int flush) +-{ +- int i; +- +- flush_invalidate(ehci->qh_list, sizeof(struct QH) * NUM_QH, flush); +- flush_invalidate(ehci->td, sizeof(struct qTD) * NUM_TD, flush); +- +- for (i = 0; i < NUM_TD; i ++) +- cache_qtd(&ehci->td[i], flush); +-} +- +-static inline void ehci_flush_dcache(struct ehci_priv *ehci) +-{ +- cache_qh(ehci, 1); +-} +- +-static inline void ehci_invalidate_dcache(struct ehci_priv *ehci) +-{ +- cache_qh(ehci, 0); +-} +-#else /* CONFIG_MMU */ +-/* +- * +- */ +-static inline void ehci_flush_dcache(struct ehci_priv *ehci) +-{ +-} +- +-static inline void ehci_invalidate_dcache(struct ehci_priv *ehci) +-{ +-} +-#endif /* CONFIG_MMU */ +- + static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) + { + uint32_t result; +@@ -231,6 +174,9 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) + int idx; + + addr = (uint32_t) buf; ++ td->qtd_dma = addr; ++ td->length = sz; ++ + idx = 0; + while (idx < 5) { + td->qt_buffer[idx] = cpu_to_hc32(addr); +@@ -264,7 +210,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, + uint32_t endpt, token, usbsts; + uint32_t c, toggle; + uint32_t cmd; +- int ret = 0; ++ int ret = 0, i; + uint64_t start, timeout_val; + + debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, +@@ -296,11 +242,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, + (dev->portnr << 23) | + (dev->parent->devnum << 16) | (0 << 8) | (0 << 0); + qh->qh_endpt2 = cpu_to_hc32(endpt); +- qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); +- qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); ++ qh->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); ++ qh->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + + td = NULL; +- tdp = &qh->qh_overlay.qt_next; ++ tdp = &qh->qt_next; + + toggle = + usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); +@@ -363,7 +309,14 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, + ehci->qh_list->qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH); + + /* Flush dcache */ +- ehci_flush_dcache(ehci); ++ if (IS_ENABLED(CONFIG_MMU)) { ++ for (i = 0; i < NUM_TD; i ++) { ++ struct qTD *qtd = &ehci->td[i]; ++ if (!qtd->qtd_dma) ++ continue; ++ dma_flush_range(qtd->qtd_dma, qtd->qtd_dma + qtd->length); ++ } ++ } + + usbsts = ehci_readl(&ehci->hcor->or_usbsts); + ehci_writel(&ehci->hcor->or_usbsts, (usbsts & 0x3f)); +@@ -384,8 +337,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, + start = get_time_ns(); + vtd = td; + do { +- /* Invalidate dcache */ +- ehci_invalidate_dcache(ehci); + token = hc32_to_cpu(vtd->qt_token); + if (is_timeout(start, timeout_val)) { + /* Disable async schedule. */ +@@ -394,11 +345,20 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, + ehci_writel(&ehci->hcor->or_usbcmd, cmd); + + ret = handshake(&ehci->hcor->or_usbsts, STD_ASS, 0, 100 * 1000); +- ehci_writel(&qh->qh_overlay.qt_token, 0); ++ ehci_writel(&qh->qt_token, 0); + return -ETIMEDOUT; + } + } while (token & 0x80); + ++ if (IS_ENABLED(CONFIG_MMU)) { ++ for (i = 0; i < NUM_TD; i ++) { ++ struct qTD *qtd = &ehci->td[i]; ++ if (!qtd->qtd_dma) ++ continue; ++ dma_inv_range(qtd->qtd_dma, qtd->qtd_dma + qtd->length); ++ } ++ } ++ + /* Disable async schedule. */ + cmd = ehci_readl(&ehci->hcor->or_usbcmd); + cmd &= ~CMD_ASE; +@@ -413,7 +373,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, + + ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH); + +- token = hc32_to_cpu(qh->qh_overlay.qt_token); ++ token = hc32_to_cpu(qh->qt_token); + if (!(token & 0x80)) { + debug("TOKEN=0x%08x\n", token); + switch (token & 0xfc) { +@@ -451,10 +411,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, + + fail: + printf("fail1\n"); +- td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); ++ td = (void *)hc32_to_cpu(qh->qt_next); + while (td != (void *)QT_NEXT_TERMINATE) { +- qh->qh_overlay.qt_next = td->qt_next; +- td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); ++ qh->qt_next = td->qt_next; ++ td = (void *)hc32_to_cpu(qh->qt_next); + } + return -1; + } +@@ -770,9 +730,9 @@ static int ehci_init(struct usb_host *host) + ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH); + ehci->qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12)); + ehci->qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE); +- ehci->qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); +- ehci->qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); +- ehci->qh_list->qh_overlay.qt_token = cpu_to_hc32(0x40); ++ ehci->qh_list->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); ++ ehci->qh_list->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); ++ ehci->qh_list->qt_token = cpu_to_hc32(0x40); + + /* Set async. queue head pointer. */ + ehci_writel(&ehci->hcor->or_asynclistaddr, (uint32_t)ehci->qh_list); +@@ -878,8 +838,8 @@ static int ehci_probe(struct device_d *dev) + ehci->hccr = dev_request_mem_region(dev, 0); + ehci->hcor = dev_request_mem_region(dev, 1); + +- ehci->qh_list = xmemalign(32, sizeof(struct QH) * NUM_QH); +- ehci->td = xmemalign(32, sizeof(struct qTD) * NUM_TD); ++ ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_TD); ++ ehci->td = dma_alloc_coherent(sizeof(struct qTD) * NUM_TD); + + host->init = ehci_init; + host->submit_int_msg = submit_int_msg; +diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h +index eac93db..b127b95 100644 +--- a/drivers/usb/host/ehci.h ++++ b/drivers/usb/host/ehci.h +@@ -166,7 +166,9 @@ struct qTD { + uint32_t qt_altnext; + uint32_t qt_token; + uint32_t qt_buffer[5]; +-}; ++ unsigned long qtd_dma; ++ size_t length; ++} __attribute__ ((aligned (32))); + + /* Queue Head (QH). */ + struct QH { +@@ -179,7 +181,11 @@ struct QH { + uint32_t qh_endpt1; + uint32_t qh_endpt2; + uint32_t qh_curtd; +- struct qTD qh_overlay; ++ /* qtd overlay (hardware parts of a struct qTD) */ ++ uint32_t qt_next; ++ uint32_t qt_altnext; ++ uint32_t qt_token; ++ uint32_t qt_buffer[5]; + /* + * Add dummy fill value to make the size of this struct + * aligned to 32 bytes +diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c +index 2ce7c6e..b3e9909 100644 +--- a/drivers/usb/host/ohci-at91.c ++++ b/drivers/usb/host/ohci-at91.c +@@ -64,7 +64,7 @@ static int at91_ohci_probe(struct device_d *dev) + writel(0, ®s->control); + + add_generic_device("ohci", DEVICE_ID_DYNAMIC, NULL, dev->resource[0].start, +- dev->resource[0].size, IORESOURCE_MEM, NULL); ++ resource_size(&dev->resource[0]), IORESOURCE_MEM, NULL); + + return 0; + } +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index 05e4094..f10d827 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -415,7 +415,7 @@ static void ohci_dump(struct ohci *controller, int verbose) + + /* get a transfer request */ + +-int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) ++static int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) + { + struct ed *ed; + int i, size = 0; +@@ -498,7 +498,7 @@ int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) + static inline int sohci_return_job(struct ohci *hc, struct urb_priv *urb) + { + #ifdef ENBALE_PIPE_INTERRUPT +- struct ohci_regs *regs = hc->regs; ++ struct ohci_regs __iomem *regs = hc->regs; + #endif + + switch (usb_pipetype(urb->pipe)) { +@@ -848,7 +848,7 @@ static void td_fill(struct ohci *ohci, unsigned int info, + } + #endif + if (!len) +- data = 0; ++ data = NULL; + + td->hwINFO = m32_swap(info); + td->hwCBP = virt_to_phys((void *)m32_swap((unsigned long)data)); +@@ -894,7 +894,7 @@ static void td_submit_job(struct usb_device *dev, unsigned long pipe, + if (data_len) + data = buffer; + else +- data = 0; ++ data = NULL; + + switch (usb_pipetype(pipe)) { + case PIPE_BULK: +@@ -1214,32 +1214,6 @@ static inline void wr_rh_portstat(struct ohci *ohci, int wIndex, __u32 value) + writel(value, &ohci->regs->roothub.portstatus[wIndex-1]); + } + +-/* request to virtual root hub */ +- +-int rh_check_port_status(struct ohci *controller) +-{ +- __u32 temp, ndp, i; +- int res; +- +- res = -1; +- temp = roothub_a(controller); +- ndp = (temp & RH_A_NDP); +-#ifdef CONFIG_AT91C_PQFP_UHPBUG +- ndp = (ndp == 2) ? 1 : 0; +-#endif +- for (i = 0; i < ndp; i++) { +- temp = roothub_portstatus(controller, i); +- /* check for a device disconnect */ +- if (((temp & (RH_PS_PESC | RH_PS_CSC)) == +- (RH_PS_PESC | RH_PS_CSC)) && +- ((temp & RH_PS_CCS) == 0)) { +- res = i; +- break; +- } +- } +- return res; +-} +- + static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, struct devrequest *cmd) + { +@@ -1502,7 +1476,7 @@ static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + + /* common code for handling submit messages - used for all but root hub */ + /* accesses. */ +-int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, ++static int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval, + int timeout) + { +@@ -1721,7 +1695,7 @@ static int hc_start(struct ohci *ohci) + + static int hc_interrupt(struct ohci *ohci) + { +- struct ohci_regs *regs = ohci->regs; ++ struct ohci_regs __iomem *regs = ohci->regs; + int ints; + int stat = 0; + +@@ -1840,7 +1814,7 @@ static int ohci_probe(struct device_d *dev) + + usb_register_host(host); + +- ohci->regs = (void *)dev->resource[0].start; ++ ohci->regs = dev_request_mem_region(dev, 0); + + return 0; + } +diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h +index 9132963..9c9b837 100644 +--- a/drivers/usb/host/ohci.h ++++ b/drivers/usb/host/ohci.h +@@ -408,7 +408,7 @@ struct ohci { + int disabled; /* e.g. got a UE, we're hung */ + unsigned long flags; /* for HC bugs */ + +- struct ohci_regs *regs; /* OHCI controller's memory */ ++ struct ohci_regs __iomem *regs; /* OHCI controller's memory */ + + int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ + struct ed *ed_rm_list[2]; /* lists of all endpoints to be removed */ +diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c +index e7a5972..68170b6 100644 +--- a/drivers/usb/storage/transport.c ++++ b/drivers/usb/storage/transport.c +@@ -26,6 +26,7 @@ + #include <clock.h> + #include <scsi.h> + #include <errno.h> ++#include <dma.h> + + #undef USB_STOR_DEBUG + +@@ -65,8 +66,8 @@ int usb_stor_Bulk_clear_endpt_stall(struct us_data *us, unsigned int pipe) + /* Determine what the maximum LUN supported is */ + int usb_stor_Bulk_max_lun(struct us_data *us) + { +- int len; +- unsigned char iobuf[1]; ++ int len, ret = 0; ++ unsigned char *iobuf = dma_alloc(1); + + /* issue the command */ + iobuf[0] = 0; +@@ -81,7 +82,9 @@ int usb_stor_Bulk_max_lun(struct us_data *us) + + /* if we have a successful request, return the result */ + if (len > 0) +- return (int)iobuf[0]; ++ ret = iobuf[0]; ++ ++ dma_free(iobuf); + + /* + * Some devices don't like GetMaxLUN. They may STALL the control +@@ -90,7 +93,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us) + * ways. In these cases the best approach is to use the default + * value: only one LUN. + */ +- return 0; ++ return ret; + } + + int usb_stor_Bulk_transport(ccb *srb, struct us_data *us) +diff --git a/drivers/video/fb.c b/drivers/video/fb.c +index 0be465f..d885570 100644 +--- a/drivers/video/fb.c ++++ b/drivers/video/fb.c +@@ -86,7 +86,7 @@ static int fb_setup_mode(struct device_d *dev, struct param_d *param, + if (!ret) { + dev->resource[0].start = (resource_size_t)info->screen_base; + info->cdev.size = info->xres * info->yres * (info->bits_per_pixel >> 3); +- dev->resource[0].size = info->cdev.size; ++ dev->resource[0].end = info->cdev.size - 1; + dev_param_set_generic(dev, param, val); + } else + info->cdev.size = 0; +@@ -116,7 +116,7 @@ int register_framebuffer(struct fb_info *info) + info->cdev.priv = info; + dev->resource = xzalloc(sizeof(struct resource)); + dev->resource[0].start = (resource_size_t)info->screen_base; +- dev->resource[0].size = info->cdev.size; ++ dev->resource[0].end = info->cdev.size - 1; + dev->resource[0].flags = IORESOURCE_MEM; + dev->num_resources = 1; + +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +new file mode 100644 +index 0000000..8fdc7a5 +--- /dev/null ++++ b/drivers/watchdog/Kconfig +@@ -0,0 +1,15 @@ ++menuconfig WATCHDOG ++ bool "Watchdog support " ++ help ++ Many platforms support a watchdog to keep track of a working machine. ++ This framework provides routines to handle these watchdogs. ++ ++if WATCHDOG ++ ++config WATCHDOG_MXS28 ++ bool "i.MX28" ++ depends on ARCH_IMX28 ++ help ++ Add support for watchdog management for the i.MX28 SoC. ++ ++endif +diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile +new file mode 100644 +index 0000000..b29103b +--- /dev/null ++++ b/drivers/watchdog/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_WATCHDOG) += wd_core.o ++obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o +diff --git a/drivers/watchdog/im28wd.c b/drivers/watchdog/im28wd.c +new file mode 100644 +index 0000000..b016910 +--- /dev/null ++++ b/drivers/watchdog/im28wd.c +@@ -0,0 +1,124 @@ ++/* ++ * (c) 2012 Juergen Beisert <kernel@pengutronix.de> ++ * ++ * 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. ++ * ++ * Note: this driver works for the i.MX28 SoC. It might work for the ++ * i.MX23 Soc as well, but is not tested yet. ++ */ ++ ++#include <common.h> ++#include <init.h> ++#include <io.h> ++#include <errno.h> ++#include <malloc.h> ++#include <watchdog.h> ++ ++#define MXS_RTC_CTRL 0x0 ++#define MXS_RTC_SET_ADDR 0x4 ++#define MXS_RTC_CLR_ADDR 0x8 ++# define MXS_RTC_CTRL_WATCHDOGEN (1 << 4) ++ ++#define MXS_RTC_STAT 0x10 ++# define MXS_RTC_STAT_WD_PRESENT (1 << 29) ++ ++#define MXS_RTC_WATCHDOG 0x50 ++ ++#define MXS_RTC_PERSISTENT0 0x60 ++/* dubious meaning from inside the SoC's firmware ROM */ ++# define MXS_RTC_PERSISTENT0_EXT_RST (1 << 21) ++/* dubious meaning from inside the SoC's firmware ROM */ ++# define MXS_RTC_PERSISTENT0_THM_RST (1 << 20) ++ ++#define MXS_RTC_PERSISTENT1 0x70 ++/* dubious meaning from inside the SoC's firmware ROM */ ++# define MXS_RTC_PERSISTENT1_FORCE_UPDATER (1 << 31) ++ ++#define MXS_RTC_DEBUG 0xc0 ++ ++#define WDOG_TICK_RATE 1000 /* the watchdog uses a 1 kHz clock rate */ ++ ++struct imx28_wd { ++ struct watchdog wd; ++ void __iomem *regs; ++}; ++ ++#define to_imx28_wd(h) container_of(h, struct imx28_wd, wd) ++ ++static int imx28_watchdog_set_timeout(struct watchdog *wd, unsigned timeout) ++{ ++ struct imx28_wd *pwd = (struct imx28_wd *)to_imx28_wd(wd); ++ void __iomem *base; ++ ++ if (timeout > (ULONG_MAX / WDOG_TICK_RATE)) ++ return -EINVAL; ++ ++ if (timeout) { ++ writel(timeout * WDOG_TICK_RATE, pwd->regs + MXS_RTC_WATCHDOG); ++ base = pwd->regs + MXS_RTC_SET_ADDR; ++ } else { ++ base = pwd->regs + MXS_RTC_CLR_ADDR; ++ } ++ writel(MXS_RTC_CTRL_WATCHDOGEN, base + MXS_RTC_CTRL); ++ writel(MXS_RTC_PERSISTENT1_FORCE_UPDATER, base + MXS_RTC_PERSISTENT1); ++ ++ return 0; ++} ++ ++static int imx28_wd_probe(struct device_d *dev) ++{ ++ struct imx28_wd *priv; ++ int rc; ++ ++ priv = xzalloc(sizeof(struct imx28_wd)); ++ priv->regs = dev_request_mem_region(dev, 0); ++ priv->wd.set_timeout = imx28_watchdog_set_timeout; ++ ++ if (!(readl(priv->regs + MXS_RTC_STAT) & MXS_RTC_STAT_WD_PRESENT)) { ++ rc = -ENODEV; ++ goto on_error; ++ } ++ ++ /* disable the debug feature to ensure a working WD */ ++ writel(0x00000000, priv->regs + MXS_RTC_DEBUG); ++ ++ rc = watchdog_register(&priv->wd); ++ if (rc != 0) ++ goto on_error; ++ ++ dev->priv = priv; ++ return 0; ++ ++on_error: ++ free(priv); ++ return rc; ++} ++ ++static void imx28_wd_remove(struct device_d *dev) ++{ ++ struct imx28_wd *priv= dev->priv; ++ watchdog_deregister(&priv->wd); ++ free(priv); ++} ++ ++static struct driver_d imx28_wd_driver = { ++ .name = "im28wd", ++ .probe = imx28_wd_probe, ++ .remove = imx28_wd_remove, ++}; ++ ++static int imx28_wd_init(void) ++{ ++ register_driver(&imx28_wd_driver); ++ return 0; ++} ++ ++device_initcall(imx28_wd_init); +diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c +new file mode 100644 +index 0000000..3d0cfc6 +--- /dev/null ++++ b/drivers/watchdog/wd_core.c +@@ -0,0 +1,57 @@ ++/* ++ * (c) 2012 Juergen Beisert <kernel@pengutronix.de> ++ * ++ * 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. ++ */ ++ ++#include <common.h> ++#include <command.h> ++#include <errno.h> ++#include <linux/ctype.h> ++#include <watchdog.h> ++ ++/* ++ * Note: this simple framework supports one watchdog only. ++ */ ++static struct watchdog *watchdog; ++ ++int watchdog_register(struct watchdog *wd) ++{ ++ if (watchdog != NULL) ++ return -EBUSY; ++ ++ watchdog = wd; ++ return 0; ++} ++EXPORT_SYMBOL(watchdog_register); ++ ++int watchdog_deregister(struct watchdog *wd) ++{ ++ if (watchdog == NULL || wd != watchdog) ++ return -ENODEV; ++ ++ watchdog = NULL; ++ return 0; ++} ++EXPORT_SYMBOL(watchdog_deregister); ++ ++/* ++ * start, stop or retrigger the watchdog ++ * timeout in [seconds]. timeout of '0' will disable the watchdog (if possible) ++ */ ++int watchdog_set_timeout(unsigned timeout) ++{ ++ if (watchdog == NULL) ++ return -ENODEV; ++ ++ return watchdog->set_timeout(watchdog, timeout); ++} ++EXPORT_SYMBOL(watchdog_set_timeout); +diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c +index c7c798b..99f6d49 100644 +--- a/fs/cramfs/cramfs.c ++++ b/fs/cramfs/cramfs.c +@@ -358,7 +358,7 @@ static int cramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size) + return outsize; + } + +-static off_t cramfs_lseek(struct device_d *dev, FILE *f, off_t pos) ++static loff_t cramfs_lseek(struct device_d *dev, FILE *f, loff_t pos) + { + f->pos = pos; + return f->pos; +diff --git a/fs/devfs-core.c b/fs/devfs-core.c +index ff6a976..cdb8f79 100644 +--- a/fs/devfs-core.c ++++ b/fs/devfs-core.c +@@ -96,7 +96,7 @@ void cdev_close(struct cdev *cdev) + cdev->ops->close(cdev); + } + +-ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags) ++ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags) + { + if (!cdev->ops->read) + return -ENOSYS; +@@ -104,7 +104,7 @@ ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulon + return cdev->ops->read(cdev, buf, count, cdev->offset +offset, flags); + } + +-ssize_t cdev_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) ++ssize_t cdev_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) + { + if (!cdev->ops->write) + return -ENOSYS; +@@ -123,15 +123,15 @@ int cdev_flush(struct cdev *cdev) + static int partition_ioctl(struct cdev *cdev, int request, void *buf) + { + int ret = 0; +- size_t offset; ++ loff_t offset, *_buf = buf; + struct mtd_info_user *user = buf; + + switch (request) { + case MEMSETBADBLOCK: + case MEMGETBADBLOCK: +- offset = (off_t)buf; ++ offset = *_buf; + offset += cdev->offset; +- ret = cdev->ops->ioctl(cdev, request, (void *)offset); ++ ret = cdev->ops->ioctl(cdev, request, &offset); + break; + case MEMGETINFO: + if (cdev->mtd) { +@@ -165,10 +165,11 @@ static int partition_ioctl(struct cdev *cdev, int request, void *buf) + case MEMGETREGIONINFO: + if (cdev->mtd) { + struct region_info_user *reg = buf; ++ int erasesize_shift = ffs(cdev->mtd->erasesize) - 1; + + reg->offset = cdev->offset; + reg->erasesize = cdev->mtd->erasesize; +- reg->numblocks = cdev->size/reg->erasesize; ++ reg->numblocks = cdev->size >> erasesize_shift; + reg->regionindex = cdev->mtd->index; + } + break; +@@ -191,7 +192,7 @@ int cdev_ioctl(struct cdev *cdev, int request, void *buf) + return cdev->ops->ioctl(cdev, request, buf); + } + +-int cdev_erase(struct cdev *cdev, size_t count, unsigned long offset) ++int cdev_erase(struct cdev *cdev, size_t count, loff_t offset) + { + if (!cdev->ops->erase) + return -ENOSYS; +@@ -226,7 +227,7 @@ int devfs_remove(struct cdev *cdev) + return 0; + } + +-int devfs_add_partition(const char *devname, unsigned long offset, size_t size, ++int devfs_add_partition(const char *devname, loff_t offset, loff_t size, + int flags, const char *name) + { + struct cdev *cdev, *new; +diff --git a/fs/devfs.c b/fs/devfs.c +index ae48451..fccf25a 100644 +--- a/fs/devfs.c ++++ b/fs/devfs.c +@@ -49,13 +49,16 @@ static int devfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t s + { + struct cdev *cdev = f->inode; + ++ if (cdev->flags & DEVFS_PARTITION_READONLY) ++ return -EPERM; ++ + return cdev_write(cdev, buf, size, f->pos, f->flags); + } + +-static off_t devfs_lseek(struct device_d *_dev, FILE *f, off_t pos) ++static loff_t devfs_lseek(struct device_d *_dev, FILE *f, loff_t pos) + { + struct cdev *cdev = f->inode; +- off_t ret = -1; ++ loff_t ret = -1; + + if (cdev->ops->lseek) + ret = cdev->ops->lseek(cdev, pos + cdev->offset); +@@ -66,10 +69,13 @@ static off_t devfs_lseek(struct device_d *_dev, FILE *f, off_t pos) + return ret - cdev->offset; + } + +-static int devfs_erase(struct device_d *_dev, FILE *f, size_t count, unsigned long offset) ++static int devfs_erase(struct device_d *_dev, FILE *f, size_t count, loff_t offset) + { + struct cdev *cdev = f->inode; + ++ if (cdev->flags & DEVFS_PARTITION_READONLY) ++ return -EPERM; ++ + if (!cdev->ops->erase) + return -ENOSYS; + +@@ -79,7 +85,7 @@ static int devfs_erase(struct device_d *_dev, FILE *f, size_t count, unsigned lo + return cdev->ops->erase(cdev, count, offset + cdev->offset); + } + +-static int devfs_protect(struct device_d *_dev, FILE *f, size_t count, unsigned long offset, int prot) ++static int devfs_protect(struct device_d *_dev, FILE *f, size_t count, loff_t offset, int prot) + { + struct cdev *cdev = f->inode; + +@@ -100,7 +106,7 @@ static int devfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags) + ret = cdev->ops->memmap(cdev, map, flags); + + if (!ret) +- *map = (void *)((unsigned long)*map + cdev->offset); ++ *map = (void *)((unsigned long)*map + (unsigned long)cdev->offset); + + return ret; + } +@@ -115,7 +121,8 @@ static int devfs_open(struct device_d *_dev, FILE *f, const char *filename) + if (!cdev) + return -ENOENT; + +- f->size = cdev->size; ++ f->size = cdev->flags & DEVFS_IS_CHARACTER_DEV ? ++ FILE_SIZE_STREAM : cdev->size; + f->inode = cdev; + + if (cdev->ops->open) { +@@ -166,7 +173,7 @@ static int devfs_truncate(struct device_d *dev, FILE *f, ulong size) + { + if (f->dev->num_resources < 1) + return -ENOSPC; +- if (size > f->dev->resource[0].size) ++ if (size > resource_size(&f->dev->resource[0])) + return -ENOSPC; + return 0; + } +diff --git a/fs/fat/fat.c b/fs/fat/fat.c +index 21464bd..5e6c81c 100644 +--- a/fs/fat/fat.c ++++ b/fs/fat/fat.c +@@ -49,7 +49,7 @@ DRESULT disk_read(FATFS *fat, BYTE *buf, DWORD sector, BYTE count) + + debug("%s: sector: %ld count: %d\n", __func__, sector, count); + +- ret = cdev_read(priv->cdev, buf, count << 9, sector * 512, 0); ++ ret = cdev_read(priv->cdev, buf, count << 9, (loff_t)sector * 512, 0); + if (ret != count << 9) + return ret; + +@@ -64,7 +64,7 @@ DRESULT disk_write(FATFS *fat, const BYTE *buf, DWORD sector, BYTE count) + debug("%s: buf: %p sector: %ld count: %d\n", + __func__, buf, sector, count); + +- ret = cdev_write(priv->cdev, buf, count << 9, sector * 512, 0); ++ ret = cdev_write(priv->cdev, buf, count << 9, (loff_t)sector * 512, 0); + if (ret != count << 9) + return ret; + +@@ -271,7 +271,7 @@ static int fat_read(struct device_d *_dev, FILE *f, void *buf, size_t insize) + return outsize; + } + +-static off_t fat_lseek(struct device_d *dev, FILE *f, off_t pos) ++static loff_t fat_lseek(struct device_d *dev, FILE *f, loff_t pos) + { + FIL *f_file = f->inode; + int ret; +diff --git a/fs/fat/ff.c b/fs/fat/ff.c +index 2d476ee..66db1d6 100644 +--- a/fs/fat/ff.c ++++ b/fs/fat/ff.c +@@ -1043,7 +1043,7 @@ int dir_register ( /* 0:Successful, FR_DENIED:No free entry or too many SFN coll + + if (sn[NS] & NS_LOSS) { + /* When LFN is out of 8.3 format, generate a numbered name */ +- fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ ++ fn[NS] = 0; dj->lfn = NULL; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ + res = dir_find(dj); /* Check if the name collides with existing SFN */ +@@ -1496,7 +1496,7 @@ int follow_path ( /* 0(0): successful, !=0: error code */ + if ((UINT)*path < ' ') { + /* Nul path means the start directory itself */ + res = dir_sdi(dj, 0); +- dj->dir = 0; ++ dj->dir = NULL; + return res; + } + +@@ -1718,7 +1718,7 @@ int f_open ( + DEF_NAMEBUF; + + +- fp->fs = 0; /* Clear file object */ ++ fp->fs = NULL; /* Clear file object */ + + #ifdef CONFIG_FS_FAT_WRITE + mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; +@@ -2059,7 +2059,7 @@ int f_close ( + /* Flush cached data */ + res = f_sync(fp); + if (res == 0) +- fp->fs = 0; /* Discard file object */ ++ fp->fs = NULL; /* Discard file object */ + return res; + #endif + } +@@ -2308,7 +2308,7 @@ int f_getfree ( + } else { + clst = fatfs->n_fatent; + sect = fatfs->fatbase; +- i = 0; p = 0; ++ i = 0; p = NULL; + do { + if (!i) { + res = move_window(fatfs, sect++); +diff --git a/fs/fs.c b/fs/fs.c +index af73c8c..0b376a5 100644 +--- a/fs/fs.c ++++ b/fs/fs.c +@@ -33,6 +33,7 @@ + #include <libbb.h> + #include <magicvar.h> + #include <environment.h> ++#include <libgen.h> + + void *read_file(const char *filename, size_t *size) + { +@@ -427,6 +428,25 @@ out: + return ret; + } + ++static int parent_check_directory(const char *path) ++{ ++ struct stat s; ++ int ret; ++ char *dir = dirname(xstrdup(path)); ++ ++ ret = stat(dir, &s); ++ ++ free(dir); ++ ++ if (ret) ++ return -ENOENT; ++ ++ if (!S_ISDIR(s.st_mode)) ++ return -ENOTDIR; ++ ++ return 0; ++} ++ + const char *getcwd(void) + { + return cwd; +@@ -515,6 +535,12 @@ int open(const char *pathname, int flags, ...) + goto out1; + } + ++ if (exist_err) { ++ ret = parent_check_directory(path); ++ if (ret) ++ goto out1; ++ } ++ + f = get_file(); + if (!f) { + ret = -EMFILE; +@@ -617,7 +643,7 @@ int read(int fd, void *buf, size_t count) + + fsdrv = dev_to_fs_driver(dev); + +- if (f->pos + count > f->size) ++ if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size) + count = f->size - f->pos; + + if (!count) +@@ -646,7 +672,7 @@ ssize_t write(int fd, const void *buf, size_t count) + dev = f->dev; + + fsdrv = dev_to_fs_driver(dev); +- if (f->pos + count > f->size) { ++ if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size) { + ret = fsdrv->truncate(dev, f, f->pos + count); + if (ret) { + if (ret != -ENOSPC) +@@ -692,12 +718,12 @@ int flush(int fd) + return ret; + } + +-off_t lseek(int fildes, off_t offset, int whence) ++loff_t lseek(int fildes, loff_t offset, int whence) + { + struct device_d *dev; + struct fs_driver_d *fsdrv; + FILE *f = &files[fildes]; +- off_t pos; ++ loff_t pos; + int ret; + + if (check_fd(fildes)) +@@ -714,12 +740,12 @@ off_t lseek(int fildes, off_t offset, int whence) + + switch (whence) { + case SEEK_SET: +- if (offset > f->size) ++ if (f->size != FILE_SIZE_STREAM && offset > f->size) + goto out; + pos = offset; + break; + case SEEK_CUR: +- if (offset + f->pos > f->size) ++ if (f->size != FILE_SIZE_STREAM && offset + f->pos > f->size) + goto out; + pos = f->pos + offset; + break; +@@ -1153,6 +1179,10 @@ int mkdir (const char *pathname, mode_t mode) + char *freep = p; + int ret; + ++ ret = parent_check_directory(p); ++ if (ret) ++ goto out; ++ + ret = path_check_prereq(pathname, S_UB_DOES_NOT_EXIST); + if (ret) + goto out; +@@ -1243,7 +1273,7 @@ static void memcpy_sz(void *_dst, const void *_src, ulong count, ulong rwsize) + } + } + +-ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags) ++ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags) + { + ulong size; + struct device_d *dev; +@@ -1252,13 +1282,13 @@ ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong + return -1; + dev = cdev->dev; + +- size = min((ulong)count, dev->resource[0].size - offset); ++ size = min((loff_t)count, resource_size(&dev->resource[0]) - offset); + memcpy_sz(buf, dev_get_mem_region(dev, 0) + offset, size, flags & O_RWSIZE_MASK); + return size; + } + EXPORT_SYMBOL(mem_read); + +-ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) ++ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) + { + ulong size; + struct device_d *dev; +@@ -1267,7 +1297,7 @@ ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, ulong offset + return -1; + dev = cdev->dev; + +- size = min((ulong)count, dev->resource[0].size - offset); ++ size = min((loff_t)count, resource_size(&dev->resource[0]) - offset); + memcpy_sz(dev_get_mem_region(dev, 0) + offset, buf, size, flags & O_RWSIZE_MASK); + return size; + } +diff --git a/fs/nfs.c b/fs/nfs.c +index 75a8f25..79e667f 100644 +--- a/fs/nfs.c ++++ b/fs/nfs.c +@@ -805,7 +805,7 @@ static int nfs_read(struct device_d *dev, FILE *file, void *buf, size_t insize) + return outsize; + } + +-static off_t nfs_lseek(struct device_d *dev, FILE *file, off_t pos) ++static loff_t nfs_lseek(struct device_d *dev, FILE *file, loff_t pos) + { + struct file_priv *priv = file->inode; + +diff --git a/fs/ramfs.c b/fs/ramfs.c +index cec5e76..91d06b8 100644 +--- a/fs/ramfs.c ++++ b/fs/ramfs.c +@@ -428,7 +428,7 @@ static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t i + return insize; + } + +-static off_t ramfs_lseek(struct device_d *dev, FILE *f, off_t pos) ++static loff_t ramfs_lseek(struct device_d *dev, FILE *f, loff_t pos) + { + f->pos = pos; + return f->pos; +diff --git a/fs/tftp.c b/fs/tftp.c +index 6586270..b58d6fc 100644 +--- a/fs/tftp.c ++++ b/fs/tftp.c +@@ -569,7 +569,7 @@ static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize) + return outsize; + } + +-static off_t tftp_lseek(struct device_d *dev, FILE *f, off_t pos) ++static loff_t tftp_lseek(struct device_d *dev, FILE *f, loff_t pos) + { + /* not implemented in tftp protocol */ + return -ENOSYS; +diff --git a/include/clock.h b/include/clock.h +index 123f874..c01a8d0 100644 +--- a/include/clock.h ++++ b/include/clock.h +@@ -3,6 +3,8 @@ + #ifndef CLOCK_H + #define CLOCK_H + ++#include <linux/time.h> ++ + #define CLOCKSOURCE_MASK(bits) (uint64_t)((bits) < 64 ? ((1ULL<<(bits))-1) : -1) + + struct clocksource { +diff --git a/include/common.h b/include/common.h +index d2347f8..df12083 100644 +--- a/include/common.h ++++ b/include/common.h +@@ -34,6 +34,24 @@ + #include <linux/stddef.h> + #include <asm/common.h> + ++/* ++ * sanity check. The Linux Kernel defines only one of __LITTLE_ENDIAN and ++ * __BIG_ENDIAN. Endianess can then be tested with #ifdef __xx_ENDIAN. Userspace ++ * always defined both __LITTLE_ENDIAN and __BIG_ENDIAN and byteorder can then ++ * be tested with #if __BYTE_ORDER == __xx_ENDIAN. ++ * ++ * As we tend to use a lot of Kernel code in barebox we use the kernel way of ++ * determing the byte order. Make sure here that architecture code properly ++ * defines it. ++ */ ++#include <asm/byteorder.h> ++#if defined __LITTLE_ENDIAN && defined __BIG_ENDIAN ++#error "both __LITTLE_ENDIAN and __BIG_ENDIAN are defined" ++#endif ++#if !defined __LITTLE_ENDIAN && !defined __BIG_ENDIAN ++#error "None of __LITTLE_ENDIAN and __BIG_ENDIAN are defined" ++#endif ++ + #define pr_info(fmt, arg...) printf(fmt, ##arg) + #define pr_notice(fmt, arg...) printf(fmt, ##arg) + #define pr_err(fmt, arg...) printf(fmt, ##arg) +@@ -102,6 +120,7 @@ long get_ram_size (volatile long *, long); + + /* $(CPU)/cpu.c */ + void __noreturn reset_cpu(unsigned long addr); ++void __noreturn poweroff(void); + + /* lib_$(ARCH)/time.c */ + void udelay (unsigned long); +@@ -138,10 +157,11 @@ struct memarea_info { + unsigned long flags; + }; + +-int parse_area_spec(const char *str, ulong *start, ulong *size); ++int parse_area_spec(const char *str, loff_t *start, loff_t *size); + + /* Just like simple_strtoul(), but this one honors a K/M/G suffix */ + unsigned long strtoul_suffix(const char *str, char **endp, int base); ++unsigned long long strtoull_suffix(const char *str, char **endp, int base); + + void start_barebox(void); + void shutdown_barebox(void); +@@ -210,7 +230,7 @@ int run_shell(void); + #define PAGE_SIZE 4096 + #define PAGE_SHIFT 12 + +-int memory_display(char *addr, ulong offs, ulong nbytes, int size); ++int memory_display(char *addr, loff_t offs, ulong nbytes, int size); + + extern const char version_string[]; + #ifdef CONFIG_BANNER +diff --git a/include/complete.h b/include/complete.h +index 8248c64..33b848c 100644 +--- a/include/complete.h ++++ b/include/complete.h +@@ -15,7 +15,7 @@ int command_complete(struct string_list *sl, char *instr); + int device_complete(struct string_list *sl, char *instr); + int empty_complete(struct string_list *sl, char *instr); + int eth_complete(struct string_list *sl, char *instr); +-int cammand_var_complete(struct string_list *sl, char *instr); ++int command_var_complete(struct string_list *sl, char *instr); + int devfs_partition_complete(struct string_list *sl, char *instr); + + #endif /* __COMPLETE_ */ +diff --git a/include/cramfs/cramfs_fs.h b/include/cramfs/cramfs_fs.h +index af2940b..8c53fc7 100644 +--- a/include/cramfs/cramfs_fs.h ++++ b/include/cramfs/cramfs_fs.h +@@ -84,11 +84,7 @@ struct cramfs_super { + | CRAMFS_FLAG_WRONG_SIGNATURE \ + | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) + +-#ifndef __BYTE_ORDER +-#error "No byte order defined in __BYTE_ORDER" +-#endif +- +-#if __BYTE_ORDER == __LITTLE_ENDIAN ++#ifdef __LITTLE_ENDIAN + #define CRAMFS_16(x) (x) + #define CRAMFS_24(x) (x) + #define CRAMFS_32(x) (x) +@@ -96,7 +92,7 @@ struct cramfs_super { + #define CRAMFS_GET_OFFSET(x) ((x)->offset) + #define CRAMFS_SET_OFFSET(x,y) ((x)->offset = (y)) + #define CRAMFS_SET_NAMELEN(x,y) ((x)->namelen = (y)) +-#elif __BYTE_ORDER ==__BIG_ENDIAN ++#elif defined __BIG_ENDIAN + #ifdef __KERNEL__ + #define CRAMFS_16(x) swab16(x) + #define CRAMFS_24(x) ((swab32(x)) >> 8) +diff --git a/include/dma.h b/include/dma.h +new file mode 100644 +index 0000000..899f831 +--- /dev/null ++++ b/include/dma.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> ++ * ++ * This file is released under the GPLv2 ++ * ++ */ ++ ++#ifndef __DMA_H ++#define __DMA_H ++ ++#include <malloc.h> ++#include <xfuncs.h> ++ ++#include <asm/dma.h> ++ ++#ifndef dma_alloc ++static inline void *dma_alloc(size_t size) ++{ ++ return xmalloc(size); ++} ++#endif ++ ++#ifndef dma_free ++static inline void dma_free(void *mem) ++{ ++ free(mem); ++} ++#endif ++ ++#endif /* __DMA_H */ +diff --git a/include/driver.h b/include/driver.h +index 09dd1e4..7d597b4 100644 +--- a/include/driver.h ++++ b/include/driver.h +@@ -183,7 +183,7 @@ static inline const char *dev_name(const struct device_d *dev) + /* + * get register base 'num' for a device + */ +-void __iomem *dev_get_mem_region(struct device_d *dev, int num); ++void *dev_get_mem_region(struct device_d *dev, int num); + + /* + * exlusively request register base 'num' for a device +@@ -301,8 +301,8 @@ struct cdev; + int dev_protect(struct device_d *dev, size_t count, unsigned long offset, int prot); + + /* These are used by drivers which work with direct memory accesses */ +-ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags); +-ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags); ++ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags); ++ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags); + int mem_memmap(struct cdev *cdev, void **map, int flags); + + /* Use this if you have nothing to do in your drivers probe function */ +@@ -316,7 +316,7 @@ void devices_shutdown(void); + int generic_memmap_ro(struct cdev *dev, void **map, int flags); + int generic_memmap_rw(struct cdev *dev, void **map, int flags); + +-static inline off_t dev_lseek_default(struct cdev *cdev, off_t ofs) ++static inline loff_t dev_lseek_default(struct cdev *cdev, loff_t ofs) + { + return ofs; + } +@@ -373,18 +373,18 @@ extern struct bus_type platform_bus; + + struct file_operations { + /*! Called in response of reading from this device. Required */ +- ssize_t (*read)(struct cdev*, void* buf, size_t count, ulong offset, ulong flags); ++ ssize_t (*read)(struct cdev*, void* buf, size_t count, loff_t offset, ulong flags); + + /*! Called in response of write to this device. Required */ +- ssize_t (*write)(struct cdev*, const void* buf, size_t count, ulong offset, ulong flags); ++ ssize_t (*write)(struct cdev*, const void* buf, size_t count, loff_t offset, ulong flags); + + int (*ioctl)(struct cdev*, int, void *); +- off_t (*lseek)(struct cdev*, off_t); ++ loff_t (*lseek)(struct cdev*, loff_t); + int (*open)(struct cdev*, unsigned long flags); + int (*close)(struct cdev*); + int (*flush)(struct cdev*); +- int (*erase)(struct cdev*, size_t count, unsigned long offset); +- int (*protect)(struct cdev*, size_t count, unsigned long offset, int prot); ++ int (*erase)(struct cdev*, size_t count, loff_t offset); ++ int (*protect)(struct cdev*, size_t count, loff_t offset, int prot); + int (*memmap)(struct cdev*, void **map, int flags); + }; + +@@ -395,8 +395,8 @@ struct cdev { + struct list_head list; + struct list_head devices_list; + char *name; +- unsigned long offset; +- size_t size; ++ loff_t offset; ++ loff_t size; + unsigned int flags; + int open; + struct mtd_info *mtd; +@@ -409,16 +409,17 @@ struct cdev *cdev_by_name(const char *filename); + struct cdev *cdev_open(const char *name, unsigned long flags); + void cdev_close(struct cdev *cdev); + int cdev_flush(struct cdev *cdev); +-ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags); +-ssize_t cdev_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags); ++ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags); ++ssize_t cdev_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags); + int cdev_ioctl(struct cdev *cdev, int cmd, void *buf); +-int cdev_erase(struct cdev *cdev, size_t count, unsigned long offset); ++int cdev_erase(struct cdev *cdev, size_t count, loff_t offset); + + #define DEVFS_PARTITION_FIXED (1 << 0) + #define DEVFS_PARTITION_READONLY (1 << 1) + #define DEVFS_IS_PARTITION (1 << 2) ++#define DEVFS_IS_CHARACTER_DEV (1 << 3) + +-int devfs_add_partition(const char *devname, unsigned long offset, size_t size, ++int devfs_add_partition(const char *devname, loff_t offset, loff_t size, + int flags, const char *name); + int devfs_del_partition(const char *name); + +diff --git a/include/envfs.h b/include/envfs.h +index 67b8902..ba976d6 100644 +--- a/include/envfs.h ++++ b/include/envfs.h +@@ -34,11 +34,25 @@ struct envfs_super { + uint32_t sb_crc; /* crc for the superblock */ + }; + +-#ifndef __BYTE_ORDER +-#error "No byte order defined in __BYTE_ORDER" ++#ifdef __BAREBOX__ ++# ifdef __LITTLE_ENDIAN ++# define ENVFS_ORDER_LITTLE ++# elif defined __BIG_ENDIAN ++# define ENVFS_ORDER_BIG ++# else ++# error "could not determine byte order" ++# endif ++#else ++# if __BYTE_ORDER == __LITTLE_ENDIAN ++# define ENVFS_ORDER_LITTLE ++# elif __BYTE_ORDER == __BIG_ENDIAN ++# define ENVFS_ORDER_BIG ++# else ++# error "could not determine byte order" ++# endif + #endif + +-#if __BYTE_ORDER == __LITTLE_ENDIAN ++#ifdef ENVFS_ORDER_LITTLE + #define ENVFS_16(x) (x) + #define ENVFS_24(x) (x) + #define ENVFS_32(x) (x) +@@ -46,7 +60,7 @@ struct envfs_super { + #define ENVFS_GET_OFFSET(x) ((x)->offset) + #define ENVFS_SET_OFFSET(x,y) ((x)->offset = (y)) + #define ENVFS_SET_NAMELEN(x,y) ((x)->namelen = (y)) +-#elif __BYTE_ORDER == __BIG_ENDIAN ++#elif defined ENVFS_ORDER_BIG + #ifdef __KERNEL__ + #define ENVFS_16(x) swab16(x) + #define ENVFS_24(x) ((swab32(x)) >> 8) +diff --git a/include/fs.h b/include/fs.h +index d82f026..c0b9f71 100644 +--- a/include/fs.h ++++ b/include/fs.h +@@ -23,8 +23,9 @@ typedef struct dir { + + typedef struct filep { + struct device_d *dev; /* The device this FILE belongs to */ +- ulong pos; /* current position in stream */ +- ulong size; /* The size of this inode */ ++ loff_t pos; /* current position in stream */ ++#define FILE_SIZE_STREAM ((loff_t) -1) ++ loff_t size; /* The size of this inode */ + ulong flags; /* the O_* flags from open */ + + void *inode; /* private to the filesystem driver */ +@@ -54,7 +55,7 @@ struct fs_driver_d { + int (*read)(struct device_d *dev, FILE *f, void *buf, size_t size); + int (*write)(struct device_d *dev, FILE *f, const void *buf, size_t size); + int (*flush)(struct device_d *dev, FILE *f); +- off_t (*lseek)(struct device_d *dev, FILE *f, off_t pos); ++ loff_t (*lseek)(struct device_d *dev, FILE *f, loff_t pos); + + struct dir* (*opendir)(struct device_d *dev, const char *pathname); + struct dirent* (*readdir)(struct device_d *dev, struct dir *dir); +@@ -63,9 +64,9 @@ struct fs_driver_d { + + int (*ioctl)(struct device_d *dev, FILE *f, int request, void *buf); + int (*erase)(struct device_d *dev, FILE *f, size_t count, +- unsigned long offset); ++ loff_t offset); + int (*protect)(struct device_d *dev, FILE *f, size_t count, +- unsigned long offset, int prot); ++ loff_t offset, int prot); + + int (*memmap)(struct device_d *dev, FILE *f, void **map, int flags); + +@@ -109,7 +110,7 @@ ssize_t write(int fd, const void *buf, size_t count); + #define SEEK_CUR 2 + #define SEEK_END 3 + +-off_t lseek(int fildes, off_t offset, int whence); ++loff_t lseek(int fildes, loff_t offset, int whence); + int mkdir (const char *pathname, mode_t mode); + + /* Create a directory and its parents */ +diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h +index aab8f4b..2d68d99 100644 +--- a/include/linux/byteorder/generic.h ++++ b/include/linux/byteorder/generic.h +@@ -78,13 +78,6 @@ + * + */ + +-#ifndef __LITTLE_ENDIAN +-#define __LITTLE_ENDIAN 1234 +-#endif +-#ifndef __BIG_ENDIAN +-#define __BIG_ENDIAN 4321 +-#endif +- + #if defined(__KERNEL__) + /* + * inside the kernel, we can use nicknames; +diff --git a/include/linux/compiler.h b/include/linux/compiler.h +index 5be3dab..cc8c4de 100644 +--- a/include/linux/compiler.h ++++ b/include/linux/compiler.h +@@ -4,7 +4,7 @@ + #ifndef __ASSEMBLY__ + + #ifdef __CHECKER__ +-# define __user __attribute__((noderef, address_space(1))) ++# define __user /* no user address space in barebox */ + # define __kernel /* default address space */ + # define __safe __attribute__((safe)) + # define __force __attribute__((force)) +diff --git a/include/linux/ioport.h b/include/linux/ioport.h +index 3f95ddd..6d6cd68 100644 +--- a/include/linux/ioport.h ++++ b/include/linux/ioport.h +@@ -17,7 +17,7 @@ + */ + struct resource { + resource_size_t start; +- resource_size_t size; ++ resource_size_t end; + const char *name; + unsigned long flags; + struct resource *parent; +@@ -113,7 +113,7 @@ struct resource { + + static inline resource_size_t resource_size(const struct resource *res) + { +- return res->size; ++ return res->end - res->start + 1; + } + static inline unsigned long resource_type(const struct resource *res) + { +@@ -121,10 +121,10 @@ static inline unsigned long resource_type(const struct resource *res) + } + + struct resource *request_iomem_region(const char *name, +- resource_size_t start, resource_size_t size); ++ resource_size_t start, resource_size_t end); + + struct resource *request_region(struct resource *parent, +- const char *name, resource_size_t start, ++ const char *name, resource_size_t end, + resource_size_t size); + + int release_region(struct resource *res); +diff --git a/include/linux/stat.h b/include/linux/stat.h +index bc7dce4..af022c5 100644 +--- a/include/linux/stat.h ++++ b/include/linux/stat.h +@@ -52,7 +52,7 @@ struct stat { + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; +- unsigned long st_size; ++ loff_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; +diff --git a/include/linux/time.h b/include/linux/time.h +index bf12b99..3942e82 100644 +--- a/include/linux/time.h ++++ b/include/linux/time.h +@@ -3,156 +3,6 @@ + + #include <linux/types.h> + +-#define _DEFUN(a,b,c) a(c) +-#define _CONST const +-#define _AND , +- +-#define _REENT_ONLY +- +-#define SECSPERMIN 60L +-#define MINSPERHOUR 60L +-#define HOURSPERDAY 24L +-#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +-#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY) +-#define DAYSPERWEEK 7 +-#define MONSPERYEAR 12 +- +-#define YEAR_BASE 1900 +-#define EPOCH_YEAR 1970 +-#define EPOCH_WDAY 4 +- +-#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) +- +- +-/* Used by other time functions. */ +-struct tm { +- int tm_sec; /* Seconds. [0-60] (1 leap second) */ +- int tm_min; /* Minutes. [0-59] */ +- int tm_hour; /* Hours. [0-23] */ +- int tm_mday; /* Day. [1-31] */ +- int tm_mon; /* Month. [0-11] */ +- int tm_year; /* Year - 1900. */ +- int tm_wday; /* Day of week. [0-6] */ +- int tm_yday; /* Days in year.[0-365] */ +- int tm_isdst; /* DST. [-1/0/1]*/ +- +-# ifdef __USE_BSD +- long int tm_gmtoff; /* Seconds east of UTC. */ +- __const char *tm_zone; /* Timezone abbreviation. */ +-# else +- long int __tm_gmtoff; /* Seconds east of UTC. */ +- __const char *__tm_zone; /* Timezone abbreviation. */ +-# endif +-}; +- +-static inline char * +-_DEFUN (asctime_r, (tim_p, result), +- _CONST struct tm *tim_p _AND +- char *result) +-{ +- static _CONST char day_name[7][3] = { +- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +- }; +- static _CONST char mon_name[12][3] = { +- "Jan", "Feb", "Mar", "Apr", "May", "Jun", +- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +- }; +- +- sprintf (result, "%.3s %.3s %.2d %.2d:%.2d:%.2d %d\n", +- day_name[tim_p->tm_wday], +- mon_name[tim_p->tm_mon], +- tim_p->tm_mday, tim_p->tm_hour, tim_p->tm_min, +- tim_p->tm_sec, 1900 + tim_p->tm_year); +- return result; +-} +- +-static inline struct tm * +-_DEFUN (localtime_r, (tim_p, res), +- _CONST time_t * tim_p _AND +- struct tm *res) +-{ +- static _CONST int mon_lengths[2][MONSPERYEAR] = { +- {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, +- {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +- } ; +- +- static _CONST int year_lengths[2] = { +- 365, +- 366 +- } ; +- +- long days, rem; +- int y; +- int yleap; +- _CONST int *ip; +- +- days = ((long) *tim_p) / SECSPERDAY; +- rem = ((long) *tim_p) % SECSPERDAY; +- while (rem < 0) +- { +- rem += SECSPERDAY; +- --days; +- } +- while (rem >= SECSPERDAY) +- { +- rem -= SECSPERDAY; +- ++days; +- } +- +- /* compute hour, min, and sec */ +- res->tm_hour = (int) (rem / SECSPERHOUR); +- rem %= SECSPERHOUR; +- res->tm_min = (int) (rem / SECSPERMIN); +- res->tm_sec = (int) (rem % SECSPERMIN); +- +- /* compute day of week */ +- if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0) +- res->tm_wday += DAYSPERWEEK; +- +- /* compute year & day of year */ +- y = EPOCH_YEAR; +- if (days >= 0) +- { +- for (;;) +- { +- yleap = isleap(y); +- if (days < year_lengths[yleap]) +- break; +- y++; +- days -= year_lengths[yleap]; +- } +- } +- else +- { +- do +- { +- --y; +- yleap = isleap(y); +- days += year_lengths[yleap]; +- } while (days < 0); +- } +- +- res->tm_year = y - YEAR_BASE; +- res->tm_yday = days; +- ip = mon_lengths[yleap]; +- for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon) +- days -= ip[res->tm_mon]; +- res->tm_mday = days + 1; +- +- /* set daylight saving time flag */ +- res->tm_isdst = -1; +- +- return (res); +-} +- +-static inline char * +-_DEFUN (ctime_r, (tim_p, result), +- _CONST time_t * tim_p _AND +- char * result) +- +-{ +- struct tm tm; +- return asctime_r (localtime_r (tim_p, &tm), result); +-} ++#define NSEC_PER_SEC 1000000000L + + #endif +diff --git a/include/menu.h b/include/menu.h +index 74abcfb..40f8eab 100644 +--- a/include/menu.h ++++ b/include/menu.h +@@ -60,9 +60,6 @@ struct menu { + struct list_head entries; + + int nb_entries; +- int width; +- char *display_buffer; +- int display_buffer_size; + + struct menu_entry *selected; + void *priv; +diff --git a/include/miidev.h b/include/miidev.h +index 622784f..4bbf94c 100644 +--- a/include/miidev.h ++++ b/include/miidev.h +@@ -31,6 +31,8 @@ + #define MIIDEV_FORCE_10 (1 << 0) + #define MIIDEV_FORCE_LINK (1 << 1) + ++#define MIIDEV_CAPABLE_1000M (1 << 0) ++ + struct mii_device { + struct device_d dev; + struct device_d *parent; +@@ -40,6 +42,7 @@ struct mii_device { + int (*write) (struct mii_device *dev, int addr, int reg, int value); + + int flags; ++ int capabilities; + + struct eth_device *edev; + struct cdev cdev; +@@ -55,6 +58,7 @@ int miidev_get_status(struct mii_device *mdev); + #define MIIDEV_STATUS_IS_FULL_DUPLEX (1 << 1) + #define MIIDEV_STATUS_IS_10MBIT (1 << 2) + #define MIIDEV_STATUS_IS_100MBIT (1 << 3) ++#define MIIDEV_STATUS_IS_1000MBIT (1 << 4) + int miidev_print_status(struct mii_device *mdev); + + static int inline mii_write(struct mii_device *dev, int addr, int reg, int value) +diff --git a/include/net.h b/include/net.h +index 08f897e..9152943 100644 +--- a/include/net.h ++++ b/include/net.h +@@ -38,8 +38,8 @@ struct eth_device { + int (*send) (struct eth_device*, void *packet, int length); + int (*recv) (struct eth_device*); + void (*halt) (struct eth_device*); +- int (*get_ethaddr) (struct eth_device*, unsigned char *adr); +- int (*set_ethaddr) (struct eth_device*, unsigned char *adr); ++ int (*get_ethaddr) (struct eth_device*, u8 adr[6]); ++ int (*set_ethaddr) (struct eth_device*, u8 adr[6]); + + struct eth_device *next; + void *priv; +@@ -287,8 +287,8 @@ int string_to_ip(const char *s, IPaddr_t *ip); + IPaddr_t getenv_ip(const char *name); + int setenv_ip(const char *name, IPaddr_t ip); + +-int string_to_ethaddr(const char *str, char *enetaddr); +-void ethaddr_to_string(const unsigned char *enetaddr, char *str); ++int string_to_ethaddr(const char *str, u8 enetaddr[6]); ++void ethaddr_to_string(const u8 enetaddr[6], char *str); + + #ifdef CONFIG_NET_RESOLV + IPaddr_t resolv(char *host); +diff --git a/include/net/designware.h b/include/net/designware.h +new file mode 100644 +index 0000000..3f9f5b9 +--- /dev/null ++++ b/include/net/designware.h +@@ -0,0 +1,9 @@ ++#ifndef __DWC_UNIMAC_H ++#define __DWC_UNIMAC_H ++ ++struct dwc_ether_platform_data { ++ u8 phy_addr; ++ void (*fix_mac_speed)(int speed); ++}; ++ ++#endif +diff --git a/include/partition.h b/include/partition.h +index 0827bb4..8ad7490 100644 +--- a/include/partition.h ++++ b/include/partition.h +@@ -8,7 +8,7 @@ struct partition { + + int flags; + +- unsigned long offset; ++ loff_t offset; + + struct device_d *physdev; + struct device_d device; +diff --git a/include/qsort.h b/include/qsort.h +index bbb2359..d279dc2 100644 +--- a/include/qsort.h ++++ b/include/qsort.h +@@ -4,4 +4,6 @@ + void qsort(void *base, size_t nel, size_t width, + int (*comp)(const void *, const void *)); + ++int strcmp_compar(const void *p1, const void *p2); ++ + #endif /* __QSORT_H */ +diff --git a/include/usb/usb.h b/include/usb/usb.h +index 296e4e8..19b092e 100644 +--- a/include/usb/usb.h ++++ b/include/usb/usb.h +@@ -159,8 +159,9 @@ struct usb_device { + int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ + + int configno; /* selected config number */ +- struct usb_device_descriptor descriptor; /* Device Descriptor */ ++ struct usb_device_descriptor *descriptor; /* Device Descriptor */ + struct usb_config_descriptor config; /* config descriptor */ ++ struct devrequest *setup_packet; + + int have_langid; /* whether string_langid is valid yet */ + int string_langid; /* language ID for strings */ +@@ -270,12 +271,14 @@ void usb_rescan(void); + ((x_ & 0xFF000000UL) >> 24)); \ + }) + +-#if __BYTE_ORDER == __LITTLE_ENDIAN ++#ifdef __LITTLE_ENDIAN + # define swap_16(x) (x) + # define swap_32(x) (x) +-#else ++#elif defined BIG_ENDIAN + # define swap_16(x) __swap_16(x) + # define swap_32(x) __swap_32(x) ++#else ++#error "could not determine byte order" + #endif + + /* +diff --git a/include/watchdog.h b/include/watchdog.h +new file mode 100644 +index 0000000..3e2d08e +--- /dev/null ++++ b/include/watchdog.h +@@ -0,0 +1,24 @@ ++/* ++ * 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. ++ */ ++ ++#ifndef INCLUDE_WATCHDOG_H ++# define INCLUDE_WATCHDOG_H ++ ++struct watchdog { ++ int (*set_timeout)(struct watchdog *, unsigned); ++}; ++ ++int watchdog_register(struct watchdog *); ++int watchdog_deregister(struct watchdog *); ++int watchdog_set_timeout(unsigned); ++ ++#endif /* INCLUDE_WATCHDOG_H */ +diff --git a/lib/misc.c b/lib/misc.c +index 549b960..8a95396 100644 +--- a/lib/misc.c ++++ b/lib/misc.c +@@ -27,15 +27,15 @@ + #include <linux/ctype.h> + + /* +- * Like simple_strtoul() but handles an optional G, M, K or k ++ * Like simple_strtoull() but handles an optional G, M, K or k + * suffix for Gigabyte, Megabyte or Kilobyte + */ +-unsigned long strtoul_suffix(const char *str, char **endp, int base) ++unsigned long long strtoull_suffix(const char *str, char **endp, int base) + { +- unsigned long val; ++ unsigned long long val; + char *end; + +- val = simple_strtoul(str, &end, base); ++ val = simple_strtoull(str, &end, base); + + switch (*end) { + case 'G': +@@ -55,6 +55,12 @@ unsigned long strtoul_suffix(const char *str, char **endp, int base) + + return val; + } ++EXPORT_SYMBOL(strtoull_suffix); ++ ++unsigned long strtoul_suffix(const char *str, char **endp, int base) ++{ ++ return strtoull_suffix(str, endp, base); ++} + EXPORT_SYMBOL(strtoul_suffix); + + /* +@@ -69,15 +75,15 @@ EXPORT_SYMBOL(strtoul_suffix); + * 0x1000 -> start = 0x1000, size = ~0 + * 1M+1k -> start = 0x100000, size = 0x400 + */ +-int parse_area_spec(const char *str, ulong *start, ulong *size) ++int parse_area_spec(const char *str, loff_t *start, loff_t *size) + { + char *endp; +- ulong end; ++ loff_t end; + + if (!isdigit(*str)) + return -1; + +- *start = strtoul_suffix(str, &endp, 0); ++ *start = strtoull_suffix(str, &endp, 0); + + str = endp; + +@@ -89,7 +95,7 @@ int parse_area_spec(const char *str, ulong *start, ulong *size) + + if (*str == '-') { + /* beginning and end given */ +- end = strtoul_suffix(str + 1, NULL, 0); ++ end = strtoull_suffix(str + 1, NULL, 0); + if (end < *start) { + printf("end < start\n"); + return -1; +@@ -100,7 +106,7 @@ int parse_area_spec(const char *str, ulong *start, ulong *size) + + if (*str == '+') { + /* beginning and size given */ +- *size = strtoul_suffix(str + 1, NULL, 0); ++ *size = strtoull_suffix(str + 1, NULL, 0); + return 0; + } + +diff --git a/lib/vsprintf.c b/lib/vsprintf.c +index 9763515..17c1973 100644 +--- a/lib/vsprintf.c ++++ b/lib/vsprintf.c +@@ -83,6 +83,7 @@ unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int ba + *endp = (char *) cp; + return result; + } ++EXPORT_SYMBOL(simple_strtoll); + + /* we use this so that we can do without the ctype library */ + #define is_digit(c) ((c) >= '0' && (c) <= '9') +diff --git a/net/eth.c b/net/eth.c +index 2b492ad..c034eaa 100644 +--- a/net/eth.c ++++ b/net/eth.c +@@ -100,11 +100,9 @@ struct eth_device * eth_get_current(void) + struct eth_device *eth_get_byname(char *ethname) + { + struct eth_device *edev; +- char name[MAX_DRIVER_NAME]; + + list_for_each_entry(edev, &netdev_list, list) { +- sprintf(name, "%s%d", edev->dev.name, edev->dev.id); +- if (!strcmp(ethname, name)) ++ if (!strcmp(ethname, dev_name(&edev->dev))) + return edev; + } + return NULL; +@@ -169,7 +167,7 @@ int eth_rx(void) + static int eth_set_ethaddr(struct device_d *dev, struct param_d *param, const char *val) + { + struct eth_device *edev = dev_to_edev(dev); +- char ethaddr[sizeof("xx:xx:xx:xx:xx:xx")]; ++ u8 ethaddr[6]; + + if (!val) + return dev_param_set_generic(dev, param, NULL); +diff --git a/net/net.c b/net/net.c +index c803c48..54d8c25 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -159,7 +159,7 @@ void print_IPaddr (IPaddr_t x) + puts(ip_to_string(x)); + } + +-int string_to_ethaddr(const char *str, char *enetaddr) ++int string_to_ethaddr(const char *str, u8 enetaddr[6]) + { + int reg; + char *e; +@@ -181,7 +181,7 @@ int string_to_ethaddr(const char *str, char *enetaddr) + return 0; + } + +-void ethaddr_to_string(const unsigned char *enetaddr, char *str) ++void ethaddr_to_string(const u8 enetaddr[6], char *str) + { + sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", + enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3], |