diff options
197 files changed, 8328 insertions, 1126 deletions
@@ -1,5 +1,5 @@ VERSION = 2012 -PATCHLEVEL = 11 +PATCHLEVEL = 12 SUBLEVEL = 0 EXTRAVERSION = NAME = Amissive Actinocutious Kiwi @@ -1166,115 +1166,10 @@ htmldocs: Doxyfile.version # Generate tags for editors # --------------------------------------------------------------------------- +quiet_cmd_tags = GEN $@ + cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@ -#We want __srctree to totally vanish out when KBUILD_OUTPUT is not set -#(which is the most common case IMHO) to avoid unneeded clutter in the big tags file. -#Adding $(srctree) adds about 20M on i386 to the size of the output file! - -ifeq ($(src),$(obj)) -__srctree = -else -__srctree = $(srctree)/ -endif - -ifeq ($(ALLSOURCE_ARCHS),) -ifeq ($(ARCH),um) -ALLINCLUDE_ARCHS := $(ARCH) $(SUBARCH) -else -ALLINCLUDE_ARCHS := $(ARCH) -endif -else -#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behavour. -ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS) -endif - -ALLSOURCE_ARCHS := $(ARCH) - -define find-sources - ( find $(__srctree) $(RCS_FIND_IGNORE) \ - \( -name include -o -name arch \) -prune -o \ - -name $1 -print; \ - for ARCH in $(ALLSOURCE_ARCHS) ; do \ - find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \ - -name $1 -print; \ - done ; \ - find $(__srctree)include $(RCS_FIND_IGNORE) \ - \( -name config -o -name 'asm-*' \) -prune \ - -o -name $1 -print; \ - for ARCH in $(ALLINCLUDE_ARCHS) ; do \ - test -e $(__srctree)include/asm-$${arch} && \ - find $(__srctree)include/asm-$${arch} $(RCS_FIND_IGNORE) \ - -name $1 -print; \ - test -e $(__srctree)arch/$${arch}/include/asm && \ - find $(__srctree)arch/$${arch}/include/asm $(RCS_FIND_IGNORE) \ - -name $1 -print; \ - done ; \ - find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \ - -name $1 -print ) -endef - -define all-sources - $(call find-sources,'*.[chS]') -endef -define all-kconfigs - $(call find-sources,'Kconfig*') -endef -define all-defconfigs - $(call find-sources,'defconfig') -endef - -define xtags - if $1 --version 2>&1 | grep -iq exuberant; then \ - $(all-sources) | xargs $1 -a \ - -I __initdata,__exitdata,__acquires,__releases \ - -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ - --extra=+f --c-kinds=+px \ - --regex-asm='/ENTRY\(([^)]*)\).*/\1/'; \ - $(all-kconfigs) | xargs $1 -a \ - --langdef=kconfig \ - --language-force=kconfig \ - --regex-kconfig='/^[[:blank:]]*config[[:blank:]]+([[:alnum:]_]+)/\1/'; \ - $(all-defconfigs) | xargs -r $1 -a \ - --langdef=dotconfig \ - --language-force=dotconfig \ - --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/'; \ - elif $1 --version 2>&1 | grep -iq emacs; then \ - $(all-sources) | xargs $1 -a; \ - $(all-kconfigs) | xargs $1 -a \ - --regex='/^[ \t]*config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \ - $(all-defconfigs) | xargs -r $1 -a \ - --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \ - else \ - $(all-sources) | xargs $1 -a; \ - fi -endef - -quiet_cmd_cscope-file = FILELST cscope.files - cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files - -quiet_cmd_cscope = MAKE cscope.out - cmd_cscope = cscope -b - -cscope: FORCE - $(call cmd,cscope-file) - $(call cmd,cscope) - -quiet_cmd_TAGS = MAKE $@ -define cmd_TAGS - rm -f $@; \ - $(call xtags,etags) -endef - -TAGS: FORCE - $(call cmd,TAGS) - -quiet_cmd_tags = MAKE $@ -define cmd_tags - rm -f $@; \ - $(call xtags,ctags) -endef - -tags: FORCE +tags TAGS cscope: FORCE $(call cmd,tags) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3afd88514f..cdb5081188 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -57,6 +57,7 @@ config ARCH_IMX select COMMON_CLK select CLKDEV_LOOKUP select WATCHDOG_IMX_RESET_SOURCE + select HAS_DEBUG_LL config ARCH_MXS bool "Freescale i.MX23/28 (mxs) based" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 8cef771490..3bd645fbfa 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -75,6 +75,7 @@ board-$(CONFIG_MACH_AT91SAM9261EK) := at91sam9261ek board-$(CONFIG_MACH_AT91SAM9263EK) := at91sam9263ek board-$(CONFIG_MACH_AT91SAM9G10EK) := at91sam9261ek board-$(CONFIG_MACH_AT91SAM9G20EK) := at91sam9260ek +board-$(CONFIG_MACH_AT91SAM9N12EK) := at91sam9n12ek board-$(CONFIG_MACH_AT91SAM9X5EK) := at91sam9x5ek board-$(CONFIG_MACH_AT91SAM9M10G45EK) := at91sam9m10g45ek board-$(CONFIG_MACH_CLEP7212) := clep7212 @@ -148,6 +149,7 @@ board-$(CONFIG_MACH_CCMX51) := ccxmx51 board-$(CONFIG_MACH_TINY210) := friendlyarm-tiny210 board-$(CONFIG_MACH_SABRELITE) := freescale-mx6-sabrelite board-$(CONFIG_MACH_TX53) := karo-tx53 +board-$(CONFIG_MACH_GUF_VINCELL) := guf-vincell machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y)) diff --git a/arch/arm/boards/archosg9/env/config b/arch/arm/boards/archosg9/env/config index 38fc51c9c4..8f3edb0e55 100644 --- a/arch/arm/boards/archosg9/env/config +++ b/arch/arm/boards/archosg9/env/config @@ -1 +1,3 @@ -global.linux.bootargs.base="earlyprintk=serial console=ttyO1,1000000n8 keep_bootcon pm_disable initcall_debug ignore_loglevel no_console_suspend=1 root=/dev/ram0 init=/linuxrc" +global.bootm.image="${TARGET_ROOT}/boot/zImage" +global.bootm.initrd="${TARGET_ROOT}/boot/initrd" +global.linux.bootargs.base="console=ttyO0,115200n8 root=/dev/ram0" diff --git a/arch/arm/boards/archosg9/env/init/usbboot b/arch/arm/boards/archosg9/env/init/usbboot index 25536e28c3..83dd19a193 100644 --- a/arch/arm/boards/archosg9/env/init/usbboot +++ b/arch/arm/boards/archosg9/env/init/usbboot @@ -1,5 +1,6 @@ -mkdir /usb -mount -t omap4_usbbootfs omap4_usbboot /usb +TARGET_ROOT="/mnt/usb" +mkdir ${TARGET_ROOT} +mount -t omap4_usbbootfs omap4_usbboot ${TARGET_ROOT} . /env/config -. /usb/boot/config -bootm -r /usb/boot/initrd /usb/boot/zImage +. ${TARGET_ROOT}/boot/config +bootm diff --git a/arch/arm/boards/at91sam9261ek/init.c b/arch/arm/boards/at91sam9261ek/init.c index 636da12279..8842cfe144 100644 --- a/arch/arm/boards/at91sam9261ek/init.c +++ b/arch/arm/boards/at91sam9261ek/init.c @@ -180,7 +180,7 @@ static void ek_add_device_keyboard_buttons(void) at91_set_deglitch(keys[i].gpio, 1); } - add_gpio_keys_device(-1, &gk_pdata); + add_gpio_keys_device(DEVICE_ID_DYNAMIC, &gk_pdata); } #else static void ek_add_device_keyboard_buttons(void) {} diff --git a/arch/arm/boards/at91sam9m10g45ek/init.c b/arch/arm/boards/at91sam9m10g45ek/init.c index f1c43cc98a..6ad3726acc 100644 --- a/arch/arm/boards/at91sam9m10g45ek/init.c +++ b/arch/arm/boards/at91sam9m10g45ek/init.c @@ -204,7 +204,7 @@ static void ek_device_add_keyboard(void) at91_set_deglitch(keys[i].gpio, 1); } - add_gpio_keys_device(-1, &gk_pdata); + add_gpio_keys_device(DEVICE_ID_DYNAMIC, &gk_pdata); } #else static void ek_device_add_keyboard(void) {} diff --git a/arch/arm/boards/at91sam9n12ek/Makefile b/arch/arm/boards/at91sam9n12ek/Makefile new file mode 100644 index 0000000000..eb072c0161 --- /dev/null +++ b/arch/arm/boards/at91sam9n12ek/Makefile @@ -0,0 +1 @@ +obj-y += init.o diff --git a/arch/arm/boards/at91sam9n12ek/config.h b/arch/arm/boards/at91sam9n12ek/config.h new file mode 100644 index 0000000000..5779a479fd --- /dev/null +++ b/arch/arm/boards/at91sam9n12ek/config.h @@ -0,0 +1,6 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#define AT91_MAIN_CLOCK 16000000 /* 16 MHz crystal */ + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/at91sam9n12ek/env/bin/init_board b/arch/arm/boards/at91sam9n12ek/env/bin/init_board new file mode 100644 index 0000000000..977430debd --- /dev/null +++ b/arch/arm/boards/at91sam9n12ek/env/bin/init_board @@ -0,0 +1,50 @@ +#!/bin/sh + +button_name="dfu_bp" +button_wait=5 + +product_id=0x1234 +vendor_id=0x4321 + +dfu_config="/dev/nand0.barebox.bb(barebox)sr,/dev/nand0.kernel.bb(kernel)r,/dev/nand0.rootfs.bb(rootfs)r" + +if [ $at91_udc0.vbus != 1 ] +then + echo "No USB Device cable plugged, normal boot" + exit +fi + +gpio_get_value ${dfu_button} +if [ $? != 0 ] +then + autoboot_timeout=16 + echo "enable tty over USB Device, increase the boot delay to ${autoboot_timeout}s" + usbserial + exit +fi + +echo "${button_name} pressed detected wait ${button_wait}s" +timeout -s -a ${button_wait} + +if [ $at91_udc0.vbus != 1 ] +then + echo "No USB Device cable plugged, normal boot" + exit +fi + +gpio_get_value ${dfu_button} +if [ $? != 0 ] +then + echo "${button_name} released, normal boot" + autoboot_timeout=16 + echo "enable tty over USB Device, increase the boot delay to ${autoboot_timeout}s" + usbserial + exit +fi + +echo "" +echo "Start DFU Mode" +echo "" + +led ds5 1 +dfu ${dfu_config} -P ${product_id} -V ${vendor_id} diff --git a/arch/arm/boards/at91sam9n12ek/env/config b/arch/arm/boards/at91sam9n12ek/env/config new file mode 100644 index 0000000000..f5cd1cc0f7 --- /dev/null +++ b/arch/arm/boards/at91sam9n12ek/env/config @@ -0,0 +1,41 @@ +#!/bin/sh + +# use 'dhcp' to do dhcp in barebox and in kernel +# use 'none' if you want to skip kernel ip autoconfiguration +ip=dhcp-barebox +global.dhcp.vendor_id=barebox-at91sam9n12ek + +# 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', 'nor' or 'nand' +kernel_loc=nfs +# can be either 'net', 'nor', 'nand' or 'initrd' +rootfs_loc=net +# can be either 'nfs', 'tftp', 'nand' or empty +oftree_loc=nfs + +# can be either 'jffs2' or 'ubifs' +rootfs_type=ubifs +rootfsimage=root.$rootfs_type +ubiroot=rootfs + +# The image type of the kernel. Can be uimage, zimage, raw, or raw_lzo +kernelimage=zImage +#kernelimage=uImage +#kernelimage=Image +#kernelimage=Image.lzo + +nand_device=atmel_nand +nand_parts="256k(at91bootstrap),384k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),128k(oftree),1M(free),6M(kernel),120M(rootfs),-(data)" +rootfs_mtdblock_nand=7 + +autoboot_timeout=3 + +bootargs="console=ttyS0,115200" + +# set a fancy prompt (if support is compiled in) +PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m\n# " diff --git a/arch/arm/boards/at91sam9n12ek/init.c b/arch/arm/boards/at91sam9n12ek/init.c new file mode 100644 index 0000000000..3d4ab5b0cc --- /dev/null +++ b/arch/arm/boards/at91sam9n12ek/init.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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. + * + * + */ + +#include <common.h> +#include <net.h> +#include <init.h> +#include <environment.h> +#include <fec.h> +#include <asm/armlinux.h> +#include <generated/mach-types.h> +#include <partition.h> +#include <fs.h> +#include <fcntl.h> +#include <io.h> +#include <asm/hardware.h> +#include <nand.h> +#include <sizes.h> +#include <linux/mtd/nand.h> +#include <mach/board.h> +#include <mach/at91sam9_smc.h> +#include <mach/sam9_smc.h> +#include <gpio.h> +#include <mach/io.h> +#include <mach/at91_pmc.h> +#include <mach/at91_rstc.h> +#include <mach/at91sam9x5_matrix.h> +#include <input/qt1070.h> +#include <readkey.h> +#include <spi/spi.h> + +static struct atmel_nand_data nand_pdata = { + .ale = 21, + .cle = 22, + .det_pin = 0, + .rdy_pin = AT91_PIN_PD5, + .enable_pin = AT91_PIN_PD4, + .ecc_mode = NAND_ECC_HW, + .pmecc_sector_size = 512, + .pmecc_corr_cap = 2, + .bus_on_d0 = 1, + .on_flash_bbt = 1, +}; + +static struct sam9_smc_config ek_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 2, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 6, + .nrd_pulse = 4, + .ncs_write_pulse = 5, + .nwe_pulse = 3, + + .read_cycle = 7, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, + .tdf_cycles = 1, +}; + +static void ek_add_device_nand(void) +{ + ek_nand_smc_config.mode |= AT91_SMC_DBW_8; + + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &ek_nand_smc_config); + + at91_add_device_nand(&nand_pdata); +} + +/* + * KS8851 ethernet device + */ +#if defined(CONFIG_DRIVER_NET_KS8851_MLL) +/* + * SMC timings for the KS8851. + * Note: These timings were calculated + * for MASTER_CLOCK = 100000000 according to the KS8851 timings. + */ +static struct sam9_smc_config __initdata ks8851_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 2, + + .ncs_read_pulse = 7, + .nrd_pulse = 7, + .ncs_write_pulse = 7, + .nwe_pulse = 7, + + .read_cycle = 9, + .write_cycle = 9, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_SELECT | AT91_SMC_DBW_16, + .tdf_cycles = 1, +}; + +static void __init ek_add_device_ks8851(void) +{ + /* Configure chip-select 2 (KS8851) */ + sam9_smc_configure(2, &ks8851_smc_config); + /* Configure NCS signal */ + at91_set_B_periph(AT91_PIN_PD19, 0); + /* Configure Interrupt pin as input, no pull-up */ + at91_set_gpio_input(AT91_PIN_PD21, 0); + + add_ks8851_device(DEVICE_ID_SINGLE, AT91_CHIPSELECT_2, AT91_CHIPSELECT_2 + 2, + IORESOURCE_MEM_16BIT, NULL); +} +#else +static void __init ek_add_device_ks8851(void) {} +#endif /* CONFIG_DRIVER_NET_KS8851_MLL */ + +/* + * MCI (SD/MMC) + */ +/* mci0 detect_pin is revision dependent */ +static struct atmel_mci_platform_data mci0_data = { + .bus_width = 4, + .detect_pin = AT91_PIN_PA7, + .wp_pin = 0, +}; + +static void ek_add_device_mci(void) +{ + /* MMC0 */ + at91_add_device_mci(0, &mci0_data); +} + +struct qt1070_platform_data qt1070_pdata = { + .irq_pin = AT91_PIN_PA2, +}; + +static struct i2c_board_info i2c_devices[] = { + { + .platform_data = &qt1070_pdata, + I2C_BOARD_INFO("qt1070", 0x1b), + }, +}; + +static void ek_add_device_i2c(void) +{ + at91_set_gpio_input(qt1070_pdata.irq_pin, 0); + at91_set_deglitch(qt1070_pdata.irq_pin, 1); + at91_add_device_i2c(0, i2c_devices, ARRAY_SIZE(i2c_devices)); +} + +static const struct spi_board_info ek_spi_devices[] = { + { + .name = "m25p80", + .chip_select = 0, + .max_speed_hz = 1 * 1000 * 1000, + .bus_num = 0, + }, +}; + +static unsigned spi0_standard_cs[] = { AT91_PIN_PA14 }; +static struct at91_spi_platform_data spi_pdata = { + .chipselect = spi0_standard_cs, + .num_chipselect = ARRAY_SIZE(spi0_standard_cs), +}; + +static void ek_add_device_spi(void) +{ + spi_register_board_info(ek_spi_devices, + ARRAY_SIZE(ek_spi_devices)); + at91_add_device_spi(0, &spi_pdata); +} + +/* + * USB Device port + */ +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PB16, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + +struct gpio_led leds[] = { + { + .gpio = AT91_PIN_PB4, + .led = { + .name = "d8", + }, + }, { + .gpio = AT91_PIN_PB5, + .active_low = 1, + .led = { + .name = "d9", + }, + }, { + .gpio = AT91_PIN_PB6, + .led = { + .name = "10", + }, + }, +}; + +static void __init ek_add_led(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(leds); i++) { + at91_set_gpio_output(leds[i].gpio, leds[i].active_low); + led_gpio_register(&leds[i]); + } + led_set_trigger(LED_TRIGGER_HEARTBEAT, &leds[0].led); +} + +static void __init ek_add_device_buttons(void) +{ + at91_set_gpio_input(AT91_PIN_PB3, 1); + at91_set_deglitch(AT91_PIN_PB3, 1); + export_env_ull("dfu_button", AT91_PIN_PB3); +} + +static int at91sam9n12ek_mem_init(void) +{ + at91_add_device_sdram(128 * 1024 * 1024); + + return 0; +} +mem_initcall(at91sam9n12ek_mem_init); + +static int at91sam9n12ek_devices_init(void) +{ + ek_add_device_spi(); + ek_add_device_nand(); + ek_add_device_mci(); + ek_add_led(); + at91_add_device_udc(&ek_udc_data); + ek_add_device_i2c(); + ek_add_device_ks8851(); + ek_add_device_buttons(); + + armlinux_set_bootparams((void *)(AT91_CHIPSELECT_1 + 0x100)); + armlinux_set_architecture(CONFIG_MACH_AT91SAM9N12EK); + + devfs_add_partition("nand0", 0x00000, SZ_256K, DEVFS_PARTITION_FIXED, "at91bootstrap_raw"); + dev_add_bb_dev("at91bootstrap_raw", "at91bootstrap"); + devfs_add_partition("nand0", SZ_256K, SZ_256K + SZ_128K, DEVFS_PARTITION_FIXED, "self_raw"); + dev_add_bb_dev("self_raw", "self0"); + devfs_add_partition("nand0", SZ_512K + SZ_128K, SZ_128K, DEVFS_PARTITION_FIXED, "env_raw"); + dev_add_bb_dev("env_raw", "env0"); + devfs_add_partition("nand0", SZ_512K + SZ_256K, SZ_128K, DEVFS_PARTITION_FIXED, "env_raw1"); + dev_add_bb_dev("env_raw1", "env1"); + + return 0; +} +device_initcall(at91sam9n12ek_devices_init); + +static int at91sam9n12ek_console_init(void) +{ + at91_register_uart(0, 0); + return 0; +} +console_initcall(at91sam9n12ek_console_init); diff --git a/arch/arm/boards/beagle/board.c b/arch/arm/boards/beagle/board.c index ec26528cdd..de8206bedf 100644 --- a/arch/arm/boards/beagle/board.c +++ b/arch/arm/boards/beagle/board.c @@ -23,8 +23,6 @@ /** * @page ti_beagle Texas Instruments Beagle Board * - * FileName: arch/arm/boards/omap/board-beagle.c - * * Beagle Board from Texas Instruments as described here: * http://www.beagleboard.org * diff --git a/arch/arm/boards/ccxmx51/ccxmx51.c b/arch/arm/boards/ccxmx51/ccxmx51.c index a8d172c0ff..b3173a424f 100644 --- a/arch/arm/boards/ccxmx51/ccxmx51.c +++ b/arch/arm/boards/ccxmx51/ccxmx51.c @@ -197,15 +197,6 @@ static const struct spi_board_info ccxmx51_spi_board_info[] = { }, }; -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 diff --git a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c index 92e8df2b9f..ae2363aa2a 100644 --- a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c +++ b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c @@ -117,14 +117,6 @@ static struct fsl_usb2_platform_data usb_pdata = { .phy_mode = FSL_USB2_PHY_UTMI, }; -static int eukrea_cpuimx25_mem_init(void) -{ - arm_add_mem_device("ram0", MX25_CSD0_BASE_ADDR, 64 * 1024 * 1024); - - return 0; -} -mem_initcall(eukrea_cpuimx25_mem_init); - static iomux_v3_cfg_t eukrea_cpuimx25_pads[] = { MX25_PAD_FEC_MDC__FEC_MDC, MX25_PAD_FEC_MDIO__FEC_MDIO, diff --git a/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c b/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c index c89ce8a192..498e9b4a8e 100644 --- a/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c +++ b/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c @@ -46,12 +46,6 @@ #include <mach/iomux-mx27.h> #include <mach/devices-imx27.h> -#if defined CONFIG_EUKREA_CPUIMX27_SDRAM_256MB -#define SDRAM0 256 -#elif defined CONFIG_EUKREA_CPUIMX27_SDRAM_128MB -#define SDRAM0 128 -#endif - static struct fec_platform_data fec_info = { .xcv_type = MII100, .phy_addr = 1, @@ -86,14 +80,6 @@ static struct i2c_board_info i2c_devices[] = { }, }; -static int eukrea_cpuimx27_mem_init(void) -{ - arm_add_mem_device("ram0", 0xa0000000, SDRAM0 * 1024 * 1024); - - return 0; -} -mem_initcall(eukrea_cpuimx27_mem_init); - #ifdef CONFIG_DRIVER_VIDEO_IMX static struct imx_fb_videomode imxfb_mode = { .mode = { diff --git a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c index fdbc26ab42..2c9600724c 100644 --- a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c +++ b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c @@ -122,14 +122,6 @@ static struct fsl_usb2_platform_data usb_pdata = { }; #endif -static int eukrea_cpuimx35_mem_init(void) -{ - arm_add_mem_device("ram0", MX35_CSD0_BASE_ADDR, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(eukrea_cpuimx35_mem_init); - static int eukrea_cpuimx35_mmu_init(void) { l2x0_init((void __iomem *)0x30000000, 0x00030024, 0x00000000); diff --git a/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c b/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c index ab0ff81d73..fdbd051dc4 100644 --- a/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c +++ b/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c @@ -103,14 +103,6 @@ static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = { #define GPIO_LAN8700_RESET (1 * 32 + 31) #define GPIO_LCD_BL (2 * 32 + 4) -static int eukrea_cpuimx51_mem_init(void) -{ - arm_add_mem_device("ram0", 0x90000000, 256 * 1024 * 1024); - - return 0; -} -mem_initcall(eukrea_cpuimx51_mem_init); - static int eukrea_cpuimx51_devices_init(void) { imx51_add_fec(&fec_info); diff --git a/arch/arm/boards/freescale-mx25-3-stack/3stack.c b/arch/arm/boards/freescale-mx25-3-stack/3stack.c index 5ce2f8e290..1271ad95ca 100644 --- a/arch/arm/boards/freescale-mx25-3-stack/3stack.c +++ b/arch/arm/boards/freescale-mx25-3-stack/3stack.c @@ -186,22 +186,6 @@ static int imx25_3ds_fec_init(void) } late_initcall(imx25_3ds_fec_init); -static int imx25_mem_init(void) -{ -#if defined CONFIG_FREESCALE_MX25_3STACK_SDRAM_64MB_DDR2 -#define SDRAM_SIZE 64 * 1024 * 1024 -#elif defined CONFIG_FREESCALE_MX25_3STACK_SDRAM_128MB_MDDR -#define SDRAM_SIZE 128 * 1024 * 1024 -#else -#error "Unsupported SDRAM type" -#endif - arm_add_mem_device("ram0", MX25_CSD0_BASE_ADDR, SDRAM_SIZE); - add_mem_device("sram0", 0x78000000, 128 * 1024, IORESOURCE_MEM_WRITEABLE); - - return 0; -} -mem_initcall(imx25_mem_init); - static int imx25_devices_init(void) { #ifdef CONFIG_USB @@ -215,6 +199,8 @@ static int imx25_devices_init(void) imx25_iim_register_fec_ethaddr(); imx25_add_fec(&fec_info); + add_mem_device("sram0", 0x78000000, 128 * 1024, IORESOURCE_MEM_WRITEABLE); + if (readl(MX25_CCM_BASE_ADDR + MX25_CCM_RCSR) & (1 << 14)) nand_info.width = 2; diff --git a/arch/arm/boards/freescale-mx35-3-stack/3stack.c b/arch/arm/boards/freescale-mx35-3-stack/3stack.c index 7da031ab6b..3128d4fb1a 100644 --- a/arch/arm/boards/freescale-mx35-3-stack/3stack.c +++ b/arch/arm/boards/freescale-mx35-3-stack/3stack.c @@ -128,15 +128,6 @@ static void set_board_rev(int rev) imx35_3ds_system_rev = (imx35_3ds_system_rev & ~(0xF << 8)) | (rev & 0xF) << 8; } -static int f3s_mem_init(void) -{ - arm_add_mem_device("ram0", MX35_CSD0_BASE_ADDR, 128 * 1024 * 1024); - arm_add_mem_device("ram1", MX35_CSD1_BASE_ADDR, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(f3s_mem_init); - static int f3s_devices_init(void) { uint32_t reg; diff --git a/arch/arm/boards/freescale-mx51-pdk/board.c b/arch/arm/boards/freescale-mx51-pdk/board.c index 9db0ed9bef..831ed0eea7 100644 --- a/arch/arm/boards/freescale-mx51-pdk/board.c +++ b/arch/arm/boards/freescale-mx51-pdk/board.c @@ -97,14 +97,6 @@ static iomux_v3_cfg_t f3s_pads[] = { MX51_PAD_GPIO1_5__GPIO1_5, }; -static int babbage_mem_init(void) -{ - arm_add_mem_device("ram0", 0x90000000, 512 * 1024 * 1024); - - return 0; -} -mem_initcall(babbage_mem_init); - #define BABBAGE_ECSPI1_CS0 (3 * 32 + 24) static int spi_0_cs[] = {BABBAGE_ECSPI1_CS0}; @@ -262,7 +254,7 @@ static int f3s_devices_init(void) armlinux_set_architecture(MACH_TYPE_MX51_BABBAGE); imx51_bbu_internal_mmc_register_handler("mmc", "/dev/disk0", - BBU_HANDLER_FLAG_DEFAULT, dcd_entry, sizeof(dcd_entry)); + BBU_HANDLER_FLAG_DEFAULT, dcd_entry, sizeof(dcd_entry), 0); return 0; } diff --git a/arch/arm/boards/freescale-mx53-loco/board.c b/arch/arm/boards/freescale-mx53-loco/board.c index 216d26a0a8..5846725b55 100644 --- a/arch/arm/boards/freescale-mx53-loco/board.c +++ b/arch/arm/boards/freescale-mx53-loco/board.c @@ -133,15 +133,6 @@ static void set_board_rev(int rev) loco_system_rev = (loco_system_rev & ~(0xF << 8)) | (rev & 0xF) << 8; } -static int loco_mem_init(void) -{ - arm_add_mem_device("ram0", 0x70000000, SZ_512M); - arm_add_mem_device("ram1", 0xb0000000, SZ_512M); - - return 0; -} -mem_initcall(loco_mem_init); - #define LOCO_FEC_PHY_RST IMX_GPIO_NR(7, 6) static void loco_fec_reset(void) @@ -203,7 +194,7 @@ static int loco_devices_init(void) armlinux_set_architecture(MACH_TYPE_MX53_LOCO); imx53_bbu_internal_mmc_register_handler("mmc", "/dev/disk0", - BBU_HANDLER_FLAG_DEFAULT, dcd_entry, sizeof(dcd_entry)); + BBU_HANDLER_FLAG_DEFAULT, dcd_entry, sizeof(dcd_entry), 0); return 0; } diff --git a/arch/arm/boards/freescale-mx53-loco/env/config b/arch/arm/boards/freescale-mx53-loco/env/config deleted file mode 100644 index 2ab126828b..0000000000 --- a/arch/arm/boards/freescale-mx53-loco/env/config +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh - -global.hostname=loco -eth0.serverip= -user= - -# use 'dhcp' to do dhcp in barebox and in kernel -# use 'none' if you want to skip kernel ip autoconfiguration -ip=dhcp -global.dhcp.vendor_id=barebox-mx53-loco - -# 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', 'nor' or 'nand' -kernel_loc=tftp -# can be either 'net', 'nor', 'nand' or 'initrd' -rootfs_loc=net - -# can be either 'jffs2' or 'ubifs' -rootfs_type=ubifs -rootfsimage=root-${global.hostname}.$rootfs_type - -kernelimage=zImage-${global.hostname} -#kernelimage=uImage-${global.hostname} -#kernelimage=Image-${global.hostname} -#kernelimage=Image-${global.hostname}.lzo - -if [ -n $user ]; then - kernelimage="$user"-"$kernelimage" - nfsroot="$eth0.serverip:/home/$user/nfsroot/${global.hostname}" - rootfsimage="$user"-"$rootfsimage" -else - nfsroot="$eth0.serverip:/path/to/nfs/root" -fi - -autoboot_timeout=3 - -bootargs="console=ttymxc0,115200" - -disk_parts="256k(barebox)ro,128k(bareboxenv),4M(kernel),-(root)" - -# 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/freescale-mx53-loco/env/init/config-board b/arch/arm/boards/freescale-mx53-loco/env/init/config-board new file mode 100644 index 0000000000..a6cf69ddbc --- /dev/null +++ b/arch/arm/boards/freescale-mx53-loco/env/init/config-board @@ -0,0 +1,7 @@ +#!/bin/sh + +# board defaults, do not change in running system. Change /env/config +# instead + +global.hostname=loco +global.linux.bootargs.base="console=ttymxc0,115200" diff --git a/arch/arm/boards/freescale-mx53-smd/board.c b/arch/arm/boards/freescale-mx53-smd/board.c index a5ad009106..64ba7f2701 100644 --- a/arch/arm/boards/freescale-mx53-smd/board.c +++ b/arch/arm/boards/freescale-mx53-smd/board.c @@ -98,15 +98,6 @@ static iomux_v3_cfg_t smd_pads[] = { MX53_PAD_PATA_RESET_B__ESDHC3_CMD, }; -static int smd_mem_init(void) -{ - arm_add_mem_device("ram0", 0x70000000, SZ_512M); - arm_add_mem_device("ram1", 0xb0000000, SZ_512M); - - return 0; -} -mem_initcall(smd_mem_init); - #define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6) static void smd_fec_reset(void) diff --git a/arch/arm/boards/guf-cupid/board.c b/arch/arm/boards/guf-cupid/board.c index 5b1732631a..839b415e9f 100644 --- a/arch/arm/boards/guf-cupid/board.c +++ b/arch/arm/boards/guf-cupid/board.c @@ -94,14 +94,6 @@ static struct imx_ipu_fb_platform_data ipu_fb_data = { .enable = cupid_fb_enable, }; -static int cupid_mem_init(void) -{ - arm_add_mem_device("ram0", MX35_CSD0_BASE_ADDR, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(cupid_mem_init); - static int cupid_mmu_init(void) { l2x0_init((void __iomem *)0x30000000, 0x00030024, 0x00000000); diff --git a/arch/arm/boards/guf-neso/board.c b/arch/arm/boards/guf-neso/board.c index 200a2efc53..086d96b229 100644 --- a/arch/arm/boards/guf-neso/board.c +++ b/arch/arm/boards/guf-neso/board.c @@ -133,14 +133,6 @@ static void neso_usbh_init(void) } #endif -static int neso_mem_init(void) -{ - arm_add_mem_device("ram0", 0xa0000000, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(neso_mem_init); - static int neso_devices_init(void) { int i; diff --git a/arch/arm/boards/guf-vincell/Makefile b/arch/arm/boards/guf-vincell/Makefile new file mode 100644 index 0000000000..8f4f9787d2 --- /dev/null +++ b/arch/arm/boards/guf-vincell/Makefile @@ -0,0 +1,3 @@ +obj-y += board.o +obj-y += flash_header.o lowlevel.o +pbl-y += flash_header.o lowlevel.o diff --git a/arch/arm/boards/guf-vincell/board.c b/arch/arm/boards/guf-vincell/board.c new file mode 100644 index 0000000000..1020bcea3b --- /dev/null +++ b/arch/arm/boards/guf-vincell/board.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2007 Sascha Hauer, Pengutronix + * Copyright (C) 2011 Marc Kleine-Budde <mkl@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 <environment.h> +#include <fcntl.h> +#include <fec.h> +#include <fs.h> +#include <init.h> +#include <nand.h> +#include <net.h> +#include <partition.h> +#include <sizes.h> +#include <bbu.h> +#include <gpio.h> +#include <io.h> +#include <i2c/i2c.h> +#include <linux/clk.h> + +#include <generated/mach-types.h> + +#include <mach/imx53-regs.h> +#include <mach/iomux-mx53.h> +#include <mach/devices-imx53.h> +#include <mach/generic.h> +#include <mach/imx-nand.h> +#include <mach/iim.h> +#include <mach/imx-nand.h> +#include <mach/bbu.h> +#include <mach/imx-flash-header.h> +#include <mach/imx5.h> + +#include <asm/armlinux.h> +#include <asm/mmu.h> + +static struct fec_platform_data fec_info = { + .xcv_type = RMII, +}; + +static iomux_v3_cfg_t vincell_pads[] = { + MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD, + MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC, + MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD, + MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS, + MX53_PAD_GPIO_8__CAN1_RXCAN, + MX53_PAD_GPIO_7__CAN1_TXCAN, + MX53_PAD_KEY_ROW4__CAN2_RXCAN, + MX53_PAD_KEY_COL4__CAN2_TXCAN, + MX53_PAD_GPIO_3__CCM_CLKO2, + MX53_PAD_KEY_COL1__ECSPI1_MISO, + MX53_PAD_KEY_ROW0__ECSPI1_MOSI, + MX53_PAD_GPIO_19__ECSPI1_RDY, + MX53_PAD_KEY_COL0__ECSPI1_SCLK, + MX53_PAD_KEY_ROW1__GPIO4_9, /* ECSPI1_SS0 */ + MX53_PAD_KEY_COL2__GPIO4_10, /* ECSPI1_SS1 */ + MX53_PAD_KEY_ROW2__GPIO4_11, /* ECSPI1_SS2 */ + MX53_PAD_KEY_COL3__GPIO4_12, /* ECSPI1_SS3 */ + MX53_PAD_CSI0_DAT10__ECSPI2_MISO, + MX53_PAD_EIM_CS1__ECSPI2_MOSI, + MX53_PAD_EIM_A25__ECSPI2_RDY, + MX53_PAD_DISP0_DAT19__ECSPI2_SCLK, + MX53_PAD_DISP0_DAT18__GPIO5_12, /* ECSPI2_SS0 */ + MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0, + MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1, + MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2, + MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3, + MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4, + MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5, + MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6, + MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7, + MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8, + MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9, + MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10, + MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11, + MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12, + MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13, + MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14, + MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15, + MX53_PAD_NANDF_ALE__EMI_NANDF_ALE, + MX53_PAD_NANDF_CLE__EMI_NANDF_CLE, + MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0, + MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1, + MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2, + MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3, + MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0, + MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B, + MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B, + MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B, + MX53_PAD_EIM_A16__EMI_WEIM_A_16, + MX53_PAD_EIM_A17__EMI_WEIM_A_17, + MX53_PAD_EIM_A18__EMI_WEIM_A_18, + MX53_PAD_EIM_A19__EMI_WEIM_A_19, + MX53_PAD_EIM_A20__EMI_WEIM_A_20, + MX53_PAD_EIM_CS0__EMI_WEIM_CS_0, + MX53_PAD_EIM_D16__EMI_WEIM_D_16, + MX53_PAD_EIM_D17__EMI_WEIM_D_17, + MX53_PAD_EIM_D18__EMI_WEIM_D_18, + MX53_PAD_EIM_D19__EMI_WEIM_D_19, + MX53_PAD_EIM_D20__EMI_WEIM_D_20, + MX53_PAD_EIM_D21__EMI_WEIM_D_21, + MX53_PAD_EIM_D22__EMI_WEIM_D_22, + MX53_PAD_EIM_D23__EMI_WEIM_D_23, + MX53_PAD_EIM_D24__EMI_WEIM_D_24, + MX53_PAD_EIM_D25__EMI_WEIM_D_25, + MX53_PAD_EIM_D26__EMI_WEIM_D_26, + MX53_PAD_EIM_D27__EMI_WEIM_D_27, + MX53_PAD_EIM_D28__EMI_WEIM_D_28, + MX53_PAD_EIM_D29__EMI_WEIM_D_29, + MX53_PAD_EIM_D30__EMI_WEIM_D_30, + MX53_PAD_EIM_D31__EMI_WEIM_D_31, + MX53_PAD_EIM_EB0__EMI_WEIM_EB_0, + MX53_PAD_EIM_EB1__EMI_WEIM_EB_1, + MX53_PAD_EIM_OE__EMI_WEIM_OE, + MX53_PAD_EIM_RW__EMI_WEIM_RW, + MX53_PAD_SD1_CLK__ESDHC1_CLK, + MX53_PAD_SD1_CMD__ESDHC1_CMD, + MX53_PAD_SD1_DATA0__ESDHC1_DAT0, + MX53_PAD_SD1_DATA1__ESDHC1_DAT1, + MX53_PAD_SD1_DATA2__ESDHC1_DAT2, + MX53_PAD_SD1_DATA3__ESDHC1_DAT3, + MX53_PAD_DI0_PIN4__ESDHC1_WP, + MX53_PAD_FEC_MDC__FEC_MDC, + MX53_PAD_FEC_MDIO__FEC_MDIO, + MX53_PAD_FEC_RXD0__FEC_RDATA_0, + MX53_PAD_FEC_RXD1__FEC_RDATA_1, + MX53_PAD_FEC_CRS_DV__FEC_RX_DV, + MX53_PAD_FEC_RX_ER__FEC_RX_ER, + MX53_PAD_FEC_TXD0__FEC_TDATA_0, + MX53_PAD_FEC_TXD1__FEC_TDATA_1, + MX53_PAD_FEC_REF_CLK__FEC_TX_CLK, + MX53_PAD_FEC_TX_EN__FEC_TX_EN, + MX53_PAD_SD2_CLK__GPIO1_10, + MX53_PAD_SD2_DATA3__GPIO1_12, + MX53_PAD_GPIO_2__GPIO1_2, + MX53_PAD_GPIO_4__GPIO1_4, + MX53_PAD_PATA_DATA0__GPIO2_0, + MX53_PAD_PATA_DATA1__GPIO2_1, + MX53_PAD_PATA_DATA10__GPIO2_10, + MX53_PAD_PATA_DATA11__GPIO2_11, + MX53_PAD_PATA_DATA13__GPIO2_13, + MX53_PAD_PATA_DATA14__GPIO2_14, + MX53_PAD_PATA_DATA15__GPIO2_15, + MX53_PAD_PATA_DATA2__GPIO2_2, + MX53_PAD_PATA_DATA3__GPIO2_3, + MX53_PAD_EIM_EB2__GPIO2_30, + MX53_PAD_PATA_DATA4__PATA_DATA_4, + MX53_PAD_PATA_DATA5__GPIO2_5, + MX53_PAD_PATA_DATA6__GPIO2_6, + MX53_PAD_PATA_DATA7__GPIO2_7, + MX53_PAD_PATA_DATA8__GPIO2_8, + MX53_PAD_PATA_DATA9__GPIO2_9, + MX53_PAD_GPIO_10__GPIO4_0, + MX53_PAD_GPIO_11__GPIO4_1, + MX53_PAD_GPIO_12__GPIO4_2, + MX53_PAD_DISP0_DAT8__GPIO4_29, + MX53_PAD_GPIO_13__GPIO4_3, + MX53_PAD_DISP0_DAT16__GPIO5_10, + MX53_PAD_DISP0_DAT17__GPIO5_11, + MX53_PAD_CSI0_PIXCLK__GPIO5_18, + MX53_PAD_CSI0_MCLK__GPIO5_19, + MX53_PAD_CSI0_DATA_EN__GPIO5_20, + MX53_PAD_CSI0_VSYNC__GPIO5_21, + MX53_PAD_CSI0_DAT4__GPIO5_22, + MX53_PAD_CSI0_DAT5__GPIO5_23, + MX53_PAD_CSI0_DAT6__GPIO5_24, + MX53_PAD_DISP0_DAT14__GPIO5_8, + MX53_PAD_DISP0_DAT15__GPIO5_9, + MX53_PAD_PATA_DIOW__GPIO6_17, + MX53_PAD_PATA_DMACK__GPIO6_18, + MX53_PAD_GPIO_17__GPIO7_12, + MX53_PAD_GPIO_18__GPIO7_13, + MX53_PAD_PATA_RESET_B__GPIO7_4, + MX53_PAD_PATA_IORDY__GPIO7_5, + MX53_PAD_PATA_DA_0__GPIO7_6, + MX53_PAD_PATA_DA_2__GPIO7_8, + MX53_PAD_CSI0_DAT9__I2C1_SCL, + MX53_PAD_CSI0_DAT8__I2C1_SDA, + MX53_PAD_KEY_COL3__I2C2_SCL, + MX53_PAD_KEY_ROW3__I2C2_SDA, + MX53_PAD_GPIO_5__I2C3_SCL, + MX53_PAD_GPIO_6__I2C3_SDA, + MX53_PAD_KEY_COL0__KPP_COL_0, + MX53_PAD_KEY_COL1__KPP_COL_1, + MX53_PAD_KEY_COL2__KPP_COL_2, + MX53_PAD_KEY_COL3__KPP_COL_3, + MX53_PAD_GPIO_19__KPP_COL_5, + MX53_PAD_GPIO_9__KPP_COL_6, + MX53_PAD_SD2_DATA1__KPP_COL_7, + MX53_PAD_KEY_ROW0__KPP_ROW_0, + MX53_PAD_KEY_ROW1__KPP_ROW_1, + MX53_PAD_KEY_ROW2__KPP_ROW_2, + MX53_PAD_KEY_ROW3__KPP_ROW_3, + MX53_PAD_SD2_CMD__KPP_ROW_5, + MX53_PAD_SD2_DATA2__KPP_ROW_6, + MX53_PAD_SD2_DATA0__KPP_ROW_7, + MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK, + MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0, + MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1, + MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2, + MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3, + MX53_PAD_DISP0_DAT8__PWM1_PWMO, + MX53_PAD_DISP0_DAT9__PWM2_PWMO, + MX53_PAD_PATA_INTRQ__UART2_CTS, + MX53_PAD_PATA_DIOR__UART2_RTS, + MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX, + MX53_PAD_PATA_DMARQ__UART2_TXD_MUX, + MX53_PAD_PATA_DA_1__UART3_CTS, + MX53_PAD_PATA_CS_1__UART3_RXD_MUX, + MX53_PAD_PATA_CS_0__UART3_TXD_MUX, + MX53_PAD_CSI0_DAT17__UART4_CTS, + MX53_PAD_CSI0_DAT16__UART4_RTS, + MX53_PAD_CSI0_DAT13__UART4_RXD_MUX, + MX53_PAD_CSI0_DAT12__UART4_TXD_MUX, + MX53_PAD_CSI0_DAT19__UART5_CTS, + MX53_PAD_CSI0_DAT18__UART5_RTS, + MX53_PAD_CSI0_DAT15__UART5_RXD_MUX, + MX53_PAD_CSI0_DAT14__UART5_TXD_MUX, + MX53_PAD_GPIO_0__USBOH3_USBH1_PWR, + MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK, + MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0, + MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1, + MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2, + MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3, + MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4, + MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5, + MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6, + MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7, + MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR, + MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT, + MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP, + MX53_PAD_GPIO_1__WDOG2_WDOG_B, +}; + +#define LOCO_FEC_PHY_RST IMX_GPIO_NR(7, 6) + +static void vincell_fec_reset(void) +{ + gpio_direction_output(LOCO_FEC_PHY_RST, 0); + mdelay(1); + gpio_set_value(LOCO_FEC_PHY_RST, 1); +} + +static struct imx_nand_platform_data nand_info = { + .width = 1, + .hw_ecc = 1, + .flash_bbt = 1, +}; + +static struct imx_dcd_v2_entry __dcd_entry_section dcd_entry[] = { +}; + +static struct i2c_board_info i2c_devices[] = { + { + I2C_BOARD_INFO("da9053", 0x48), + }, +}; + +static int vincell_devices_init(void) +{ + writel(0, MX53_M4IF_BASE_ADDR + 0xc); + + console_flush(); + imx53_init_lowlevel(1000); + clk_set_rate(clk_lookup("nfc_podf"), 66666667); + + imx53_add_nand(&nand_info); + imx51_iim_register_fec_ethaddr(); + imx53_add_fec(&fec_info); + imx53_add_mmc0(NULL); + i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices)); + imx53_add_i2c0(NULL); + + vincell_fec_reset(); + + armlinux_set_bootparams((void *)0x70000100); + armlinux_set_architecture(3297); + + devfs_add_partition("nand0", SZ_1M, SZ_512K, DEVFS_PARTITION_FIXED, "self_raw"); + dev_add_bb_dev("self_raw", "self0"); + devfs_add_partition("nand0", SZ_1M + SZ_512K, SZ_512K, DEVFS_PARTITION_FIXED, "env_raw"); + dev_add_bb_dev("env_raw", "env0"); + + imx53_bbu_internal_nand_register_handler("nand", + BBU_HANDLER_FLAG_DEFAULT, dcd_entry, sizeof(dcd_entry), 3 * SZ_128K, 0xf8020000); + + return 0; +} + +device_initcall(vincell_devices_init); + +static int vincell_part_init(void) +{ + devfs_add_partition("disk0", 0x00000, 0x80000, DEVFS_PARTITION_FIXED, "self0"); + devfs_add_partition("disk0", 0x80000, 0x80000, DEVFS_PARTITION_FIXED, "env0"); + + return 0; +} +late_initcall(vincell_part_init); + +static int vincell_console_init(void) +{ + mxc_iomux_v3_setup_multiple_pads(vincell_pads, ARRAY_SIZE(vincell_pads)); + + imx53_add_uart1(); + + return 0; +} + +console_initcall(vincell_console_init); diff --git a/arch/arm/boards/guf-vincell/config.h b/arch/arm/boards/guf-vincell/config.h new file mode 100644 index 0000000000..b7effe5d28 --- /dev/null +++ b/arch/arm/boards/guf-vincell/config.h @@ -0,0 +1,24 @@ +/** + * @file + * @brief Global defintions for the ARM i.MX51 based babbage 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/guf-vincell/env/boot/nand-ubi b/arch/arm/boards/guf-vincell/env/boot/nand-ubi new file mode 100644 index 0000000000..a3f748e746 --- /dev/null +++ b/arch/arm/boards/guf-vincell/env/boot/nand-ubi @@ -0,0 +1,10 @@ +#!/bin/sh + +if [ "$1" = menu ]; then + boot-menu-add-entry "$0" "nand (UBI)" + exit +fi + +global.bootm.image="/dev/nand0.kernel.bb" +#global.bootm.oftree="/env/oftree" +bootargs-root-ubi -r root -m nand0.root diff --git a/arch/arm/boards/guf-vincell/env/init/bootargs-base b/arch/arm/boards/guf-vincell/env/init/bootargs-base new file mode 100644 index 0000000000..d86975406e --- /dev/null +++ b/arch/arm/boards/guf-vincell/env/init/bootargs-base @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "$1" = menu ]; then + init-menu-add-entry "$0" "Base bootargs" + exit +fi + +global.linux.bootargs.base="console=ttymxc0,115200" diff --git a/arch/arm/boards/guf-vincell/env/init/hostname b/arch/arm/boards/guf-vincell/env/init/hostname new file mode 100644 index 0000000000..ca2789ddf4 --- /dev/null +++ b/arch/arm/boards/guf-vincell/env/init/hostname @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "$1" = menu ]; then + init-menu-add-entry "$0" "hostname" + exit +fi + +global.hostname=vincell diff --git a/arch/arm/boards/guf-vincell/env/init/mtdparts-nand b/arch/arm/boards/guf-vincell/env/init/mtdparts-nand new file mode 100644 index 0000000000..4fffefca8b --- /dev/null +++ b/arch/arm/boards/guf-vincell/env/init/mtdparts-nand @@ -0,0 +1,11 @@ +#!/bin/sh + +if [ "$1" = menu ]; then + init-menu-add-entry "$0" "NAND partitions" + exit +fi + +mtdparts="512k(nand0.barebox)ro,512k(nand0.bareboxenv),4M(nand0.kernel),-(nand0.root)" +kernelname="mxc_nand" + +mtdparts-add -b -d nand0 -k ${kernelname} -p ${mtdparts} diff --git a/arch/arm/boards/guf-vincell/flash_header.c b/arch/arm/boards/guf-vincell/flash_header.c new file mode 100644 index 0000000000..df480d254f --- /dev/null +++ b/arch/arm/boards/guf-vincell/flash_header.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011 Marc Kleine-Budde <mkl@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 <sizes.h> +#include <asm/byteorder.h> +#include <asm/barebox-arm-head.h> +#include <mach/imx-flash-header.h> + +void __naked __flash_header_start go(void) +{ + barebox_arm_head(); +} + +#define APP_DEST 0xf8020000 + +struct imx_flash_header_v2 __flash_header_section flash_header = { + .header.tag = IVT_HEADER_TAG, + .header.length = cpu_to_be16(32), + .header.version = IVT_VERSION, + + .entry = APP_DEST + 0x1000, + .dcd_ptr = APP_DEST + 0x400 + offsetof(struct imx_flash_header_v2, dcd), + .boot_data_ptr = APP_DEST + 0x400 + offsetof(struct imx_flash_header_v2, boot_data), + .self = APP_DEST + 0x400, + + .boot_data.start = APP_DEST, + .boot_data.size = DCD_BAREBOX_SIZE, +}; diff --git a/arch/arm/boards/guf-vincell/lowlevel.c b/arch/arm/boards/guf-vincell/lowlevel.c new file mode 100644 index 0000000000..8003c673b4 --- /dev/null +++ b/arch/arm/boards/guf-vincell/lowlevel.c @@ -0,0 +1,149 @@ +#include <common.h> +#include <io.h> +#include <init.h> +#include <mach/imx53-regs.h> +#include <mach/imx5.h> +#include <mach/iomux-v3.h> +#include <mach/esdctl-v4.h> +#include <asm/barebox-arm.h> +#include <asm/barebox-arm-head.h> +#include <io.h> + +#define IOMUX_PADCTL_DDRI_DDR (1 << 9) + +#define IOMUX_PADCTL_DDRDSE(x) ((x) << 19) +#define IOMUX_PADCTL_DDRSEL(x) ((x) << 25) + +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM3 0x554 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3 0x558 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM2 0x560 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 0x564 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2 0x568 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_1 0x570 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS 0x574 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 0x578 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 0x57c +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 0x580 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS 0x588 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 0x590 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 0x594 +#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 0x584 +#define IOMUXC_SW_PAD_CTL_GRP_ADDDS 0x6f0 +#define IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL 0x6f4 +#define IOMUXC_SW_PAD_CTL_GRP_DDRPKE 0x6fc +#define IOMUXC_SW_PAD_CTL_GRP_DDRHYS 0x710 +#define IOMUXC_SW_PAD_CTL_GRP_DDRMODE 0x714 +#define IOMUXC_SW_PAD_CTL_GRP_B0DS 0x718 +#define IOMUXC_SW_PAD_CTL_GRP_B1DS 0x71c +#define IOMUXC_SW_PAD_CTL_GRP_CTLDS 0x720 +#define IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE 0x724 +#define IOMUXC_SW_PAD_CTL_GRP_B2DS 0x728 +#define IOMUXC_SW_PAD_CTL_GRP_B3DS 0x72c + + +static void configure_dram_iomux(void) +{ + void __iomem *iomux = (void *)MX53_IOMUXC_BASE_ADDR; + u32 r1, r2, r4, r5, r6; + + /* define the INPUT mode for DRAM_D[31:0] */ + writel(0, iomux + IOMUXC_SW_PAD_CTL_GRP_DDRMODE); + + /* + * define the INPUT mode for SDQS[3:0] + * (Freescale's documentation suggests DDR-mode for the + * control line, but their source actually uses CMOS) + */ + writel(IOMUX_PADCTL_DDRI_DDR, iomux + IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL); + + r1 = IOMUX_PADCTL_DDRDSE(5); + r2 = IOMUX_PADCTL_DDRDSE(5) | PAD_CTL_PUE; + r4 = IOMUX_PADCTL_DDRSEL(2); + r5 = IOMUX_PADCTL_DDRDSE(5) | PAD_CTL_PKE | PAD_CTL_PUE | IOMUX_PADCTL_DDRI_DDR | PAD_CTL_PUS_47K_UP; + r6 = IOMUX_PADCTL_DDRDSE(4); + + /* + * this will adisable the Pull/Keeper for DRAM_x pins EXCEPT, + * for DRAM_SDQS[3:0] and DRAM_SDODT[1:0] + */ + writel(0, iomux + IOMUXC_SW_PAD_CTL_GRP_DDRPKE); + + /* set global drive strength for all DRAM_x pins */ + writel(r4, iomux + IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE); + + /* set data dqs dqm drive strength */ + writel(r6, iomux + IOMUXC_SW_PAD_CTL_GRP_B0DS); + writel(r6, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0); + writel(r5, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0); + + writel(r1, iomux + IOMUXC_SW_PAD_CTL_GRP_B1DS); + writel(r1, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1); + writel(r5, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1); + + writel(r6, iomux + IOMUXC_SW_PAD_CTL_GRP_B2DS); + writel(r6, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM2); + writel(r5, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2); + + writel(r1, iomux + IOMUXC_SW_PAD_CTL_GRP_B3DS); + writel(r1, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM3); + writel(r5, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3); + + /* SDCLK pad drive strength control options */ + writel(r1, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0); + writel(r1, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_1); + + /* Control and addr bus pad drive strength control options */ + writel(r1, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS); + writel(r1, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS); + writel(r1, iomux + IOMUXC_SW_PAD_CTL_GRP_ADDDS); + writel(r1, iomux + IOMUXC_SW_PAD_CTL_GRP_CTLDS); + writel(r2, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0); + writel(r2, iomux + IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1); + + /* + * enable hysteresis on input pins + * (Freescale's documentation suggests that enable hysteresis + * would be better, but their source-code doesn't) + */ + writel(PAD_CTL_HYS, iomux + IOMUXC_SW_PAD_CTL_GRP_DDRHYS); +} + +void disable_watchdog(void) +{ + /* + * configure WDOG to generate external reset on trigger + * and disable power down counter + */ + writew(0x38, MX53_WDOG1_BASE_ADDR); + writew(0x0, MX53_WDOG1_BASE_ADDR + 8); + writew(0x38, MX53_WDOG2_BASE_ADDR); + writew(0x0, MX53_WDOG2_BASE_ADDR + 8); +} + +void sdram_init(void); + +void __bare_init __naked reset(void) +{ + u32 r; + + common_reset(); + + /* Skip SDRAM initialization if we run from RAM */ + r = get_pc(); + if (r > 0x70000000 && r < 0xf0000000) + board_init_lowlevel_return(); + + /* Setup a preliminary stack */ + r = 0xf8000000 + 0x60000 - 16; + __asm__ __volatile__("mov sp, %0" : : "r"(r)); + + disable_watchdog(); + + configure_dram_iomux(); + + imx5_init_lowlevel(); + + imx_esdctlv4_init(); + + board_init_lowlevel_return(); +} diff --git a/arch/arm/boards/imx27ads/imx27ads.c b/arch/arm/boards/imx27ads/imx27ads.c index f41b155d16..d07d553772 100644 --- a/arch/arm/boards/imx27ads/imx27ads.c +++ b/arch/arm/boards/imx27ads/imx27ads.c @@ -65,14 +65,6 @@ static int imx27ads_timing_init(void) core_initcall(imx27ads_timing_init); -static int mx27ads_mem_init(void) -{ - arm_add_mem_device("ram0", 0xa0000000, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(mx27ads_mem_init); - static int mx27ads_devices_init(void) { int i; diff --git a/arch/arm/boards/karo-tx25/board.c b/arch/arm/boards/karo-tx25/board.c index 1ffd890dd6..98140b33cc 100644 --- a/arch/arm/boards/karo-tx25/board.c +++ b/arch/arm/boards/karo-tx25/board.c @@ -50,17 +50,6 @@ struct imx_nand_platform_data nand_info = { .flash_bbt = 1, }; -static int tx25_mem_init(void) -{ - arm_add_mem_device("ram0", MX25_CSD0_BASE_ADDR, 32 * 1024 * 1024); - arm_add_mem_device("ram0", MX25_CSD1_BASE_ADDR, 32 * 1024 * 1024); - add_mem_device("ram0", 0x78000000, 128 * 1024, - IORESOURCE_MEM_WRITEABLE); - - return 0; -} -mem_initcall(tx25_mem_init); - static iomux_v3_cfg_t karo_tx25_padsd_fec[] = { MX25_PAD_D11__GPIO_4_9, /* FEC PHY power on pin */ MX25_PAD_D13__GPIO_4_7, /* FEC reset */ @@ -119,6 +108,9 @@ static int tx25_devices_init(void) devfs_add_partition("nand0", 0x40000, 0x80000, DEVFS_PARTITION_FIXED, "env_raw"); dev_add_bb_dev("env_raw", "env0"); + add_mem_device("sram0", 0x78000000, 128 * 1024, + IORESOURCE_MEM_WRITEABLE); + armlinux_set_bootparams((void *)0x80000100); armlinux_set_architecture(MACH_TYPE_TX25); armlinux_set_serial(imx_uid()); diff --git a/arch/arm/boards/karo-tx28/tx28.c b/arch/arm/boards/karo-tx28/tx28.c index a62cb8257f..6e8da155a3 100644 --- a/arch/arm/boards/karo-tx28/tx28.c +++ b/arch/arm/boards/karo-tx28/tx28.c @@ -35,11 +35,12 @@ static const uint32_t tx28_pad_setup[] = { GPMI_D6 | VE_3_3V | PULLUP(1), GPMI_D7 | VE_3_3V | PULLUP(1), GPMI_READY0 | VE_3_3V | PULLUP(0), /* external PU */ + GPMI_CE0N | VE_3_3V | PULLUP(1), GPMI_RDN | VE_3_3V | PULLUP(1), GPMI_WRN | VE_3_3V | BITKEEPER(1), GPMI_ALE | VE_3_3V | PULLUP(1), GPMI_CLE | VE_3_3V | PULLUP(1), - GPMI_RESETN_GPIO | VE_3_3V | GPIO_IN, /* act as WP, external PU */ + GPMI_RESETN | VE_3_3V | PULLUP(0), /* external PU */ /* Network interface */ @@ -91,6 +92,9 @@ static int tx28_devices_init(void) base_board_init(); + add_generic_device("mxs_nand", 0, NULL, MXS_GPMI_BASE, 0x2000, + IORESOURCE_MEM, NULL); + return 0; } diff --git a/arch/arm/boards/karo-tx51/tx51.c b/arch/arm/boards/karo-tx51/tx51.c index dd377c140a..6c2b14b35a 100644 --- a/arch/arm/boards/karo-tx51/tx51.c +++ b/arch/arm/boards/karo-tx51/tx51.c @@ -112,14 +112,6 @@ static iomux_v3_cfg_t tx51_pads[] = { MX51_PAD_GPIO1_0__GPIO1_0, }; -static int tx51_mem_init(void) -{ - arm_add_mem_device("ram0", MX51_CSD0_BASE_ADDR, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(tx51_mem_init); - static int spi_0_cs[] = { IMX_GPIO_NR(4, 24), IMX_GPIO_NR(4, 25), diff --git a/arch/arm/boards/karo-tx53/board.c b/arch/arm/boards/karo-tx53/board.c index 8f87c9c9a8..8a69e994b9 100644 --- a/arch/arm/boards/karo-tx53/board.c +++ b/arch/arm/boards/karo-tx53/board.c @@ -99,17 +99,6 @@ static iomux_v3_cfg_t tx53_pads[] = { MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK, }; -static int tx53_mem_init(void) -{ - if (IS_ENABLED(CONFIG_TX53_REV_1011)) - arm_add_mem_device("ram0", 0x70000000, SZ_1G); - else - arm_add_mem_device("ram0", 0x70000000, SZ_512M); - - return 0; -} -mem_initcall(tx53_mem_init); - #define TX53_SD1_CD IMX_GPIO_NR(3, 24) static struct esdhc_platform_data tx53_sd1_data = { @@ -229,11 +218,12 @@ static int tx53_devices_init(void) /* rev xx30 can boot from nand or USB */ imx53_bbu_internal_nand_register_handler("nand-xx30", - BBU_HANDLER_FLAG_DEFAULT, (void *)dcd_entry_xx30, sizeof(dcd_entry_xx30), SZ_512K); + BBU_HANDLER_FLAG_DEFAULT, (void *)dcd_entry_xx30, + sizeof(dcd_entry_xx30), SZ_512K, 0); /* rev 1011 can boot from MMC/SD, other bootsource currently unknown */ imx53_bbu_internal_mmc_register_handler("mmc-1011", "/dev/disk0", - 0, (void *)dcd_entry_1011, sizeof(dcd_entry_1011)); + 0, (void *)dcd_entry_1011, sizeof(dcd_entry_1011), 0); return 0; } diff --git a/arch/arm/boards/omap343xdsp/board.c b/arch/arm/boards/omap343xdsp/board.c index 692cf9ac44..8b8e0b20e0 100644 --- a/arch/arm/boards/omap343xdsp/board.c +++ b/arch/arm/boards/omap343xdsp/board.c @@ -23,8 +23,6 @@ /** * @page ti_SDP3430 Texas Instruments SDP3430 * - * FileName: arch/arm/boards/omap/board-sdp343x.c - * * SDP3430 from Texas Instruments as described here: * http://www.ti.com/omap3430_devplatform * This file provides initialization in two stages: diff --git a/arch/arm/boards/omap3evm/board.c b/arch/arm/boards/omap3evm/board.c index 7d4a87f895..d18cf392da 100644 --- a/arch/arm/boards/omap3evm/board.c +++ b/arch/arm/boards/omap3evm/board.c @@ -2,8 +2,6 @@ * @file * @brief Board Initialization routines for OMAP3EVM. * - * FileName: arch/arm/boards/omap/board-omap3evm.c - * * This board is based on OMAP3530. * More on OMAP3530 (including documentation can be found here): * http://focus.ti.com/docs/prod/folders/print/omap3530.html diff --git a/arch/arm/boards/pcm037/pcm037.c b/arch/arm/boards/pcm037/pcm037.c index ff4089ad25..ff32e3541f 100644 --- a/arch/arm/boards/pcm037/pcm037.c +++ b/arch/arm/boards/pcm037/pcm037.c @@ -145,17 +145,6 @@ static void pcm037_usb_init(void) } #endif -static int pcm037_mem_init(void) -{ - arm_add_mem_device("ram0", MX31_CSD0_BASE_ADDR, SDRAM0 * 1024 * 1024); -#ifndef CONFIG_PCM037_SDRAM_BANK1_NONE - arm_add_mem_device("ram1", MX31_CSD1_BASE_ADDR, SDRAM1 * 1024 * 1024); -#endif - - return 0; -} -mem_initcall(pcm037_mem_init); - static int pcm037_mmu_init(void) { l2x0_init((void __iomem *)0x30000000, 0x00030024, 0x00000000); diff --git a/arch/arm/boards/pcm038/pcm038.c b/arch/arm/boards/pcm038/pcm038.c index 715d604726..ea50a78905 100644 --- a/arch/arm/boards/pcm038/pcm038.c +++ b/arch/arm/boards/pcm038/pcm038.c @@ -180,16 +180,6 @@ static int pcm038_power_init(void) return 0; } -static int pcm038_mem_init(void) -{ - arm_add_mem_device("ram0", 0xa0000000, 128 * 1024 * 1024); - - add_mem_device("ram1", 0xc8000000, 512 * 1024, /* Can be up to 2MiB */ - IORESOURCE_MEM_WRITEABLE); - return 0; -} -mem_initcall(pcm038_mem_init); - static int pcm038_devices_init(void) { int i; @@ -279,6 +269,10 @@ static int pcm038_devices_init(void) /* configure SRAM on cs1 */ imx27_setup_weimcs(1, 0x0000d843, 0x22252521, 0x22220a00); + /* Can be up to 2MiB */ + add_mem_device("ram1", 0xc8000000, 512 * 1024, + IORESOURCE_MEM_WRITEABLE); + /* initizalize gpios */ for (i = 0; i < ARRAY_SIZE(mode); i++) imx_gpio_mode(mode[i]); diff --git a/arch/arm/boards/pcm043/pcm043.c b/arch/arm/boards/pcm043/pcm043.c index abfeaf148a..95da8f0b10 100644 --- a/arch/arm/boards/pcm043/pcm043.c +++ b/arch/arm/boards/pcm043/pcm043.c @@ -98,14 +98,6 @@ static struct imx_ipu_fb_platform_data ipu_fb_data = { .bpp = 16, }; -static int pcm043_mem_init(void) -{ - arm_add_mem_device("ram0", MX35_CSD0_BASE_ADDR, SZ_128M); - - return 0; -} -mem_initcall(pcm043_mem_init); - static int pcm043_mmu_init(void) { l2x0_init((void __iomem *)0x30000000, 0x00030024, 0x00000000); diff --git a/arch/arm/boards/phycard-a-l1/pca-a-l1.c b/arch/arm/boards/phycard-a-l1/pca-a-l1.c index 6652242114..e35db1837f 100644 --- a/arch/arm/boards/phycard-a-l1/pca-a-l1.c +++ b/arch/arm/boards/phycard-a-l1/pca-a-l1.c @@ -2,8 +2,6 @@ * @file * @brief Board Initialization routines for the phyCARD-A-L1 * - * FileName: arch/arm/boards/phycard-a-l1/pca-a-l1.c - * * This board is based on OMAP3530. * More on OMAP3530 (including documentation can be found here): * http://focus.ti.com/docs/prod/folders/print/omap3530.html @@ -22,9 +20,7 @@ * @li serial @ref serial_ns16550.c driver device definition * * Originally from arch/arm/boards/omap/board-beagle.c - */ - -/* + * * Copyright (C) 2011 Phytec Messtechnik GmbH - http://www.phytec.de/ * Juergen Kilb <j.kilb@phytec.de> * @@ -40,7 +36,6 @@ * 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> diff --git a/arch/arm/boards/phycard-a-l1/pca-a-l1.h b/arch/arm/boards/phycard-a-l1/pca-a-l1.h index 0441a00fe6..f6f8996697 100644 --- a/arch/arm/boards/phycard-a-l1/pca-a-l1.h +++ b/arch/arm/boards/phycard-a-l1/pca-a-l1.h @@ -2,11 +2,8 @@ * @file * @brief exported generic APIs which various board files implement * - * FileName: arch/arm/boards/phycard-a-l1/board.h - * * This file will not contain any board specific implementations. - */ -/* + * * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Raghavendra KH <r-khandenahally@ti.com> @@ -20,8 +17,8 @@ * 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 __BOARD_OMAP_H_ #define __BOARD_OMAP_H_ diff --git a/arch/arm/boards/phycard-i.MX27/pca100.c b/arch/arm/boards/phycard-i.MX27/pca100.c index 0b66b04e5f..1a21c8afbd 100644 --- a/arch/arm/boards/phycard-i.MX27/pca100.c +++ b/arch/arm/boards/phycard-i.MX27/pca100.c @@ -143,14 +143,6 @@ static void pca100_usb_register(void) } #endif -static int pca100_mem_init(void) -{ - arm_add_mem_device("ram0", 0xa0000000, 128 * 1024 * 1024); - - return 0; -} -mem_initcall(pca100_mem_init); - static void pca100_usb_init(void) { u32 reg; diff --git a/arch/arm/boards/scb9328/scb9328.c b/arch/arm/boards/scb9328/scb9328.c index c70852c308..d91b21d97e 100644 --- a/arch/arm/boards/scb9328/scb9328.c +++ b/arch/arm/boards/scb9328/scb9328.c @@ -48,14 +48,6 @@ struct gpio_led leds[] = { }, }; -static int scb9328_mem_init(void) -{ - arm_add_mem_device("ram0", 0x08000000, 16 * 1024 * 1024); - - return 0; -} -mem_initcall(scb9328_mem_init); - static int scb9328_devices_init(void) { int i; diff --git a/arch/arm/boards/tqma53/board.c b/arch/arm/boards/tqma53/board.c index 77535b53f2..03cb8eadf0 100644 --- a/arch/arm/boards/tqma53/board.c +++ b/arch/arm/boards/tqma53/board.c @@ -207,17 +207,6 @@ static iomux_v3_cfg_t tqma53_pads[] = { #define GPIO_FEC_NRESET IMX_GPIO_NR(7, 6) -static int tqma53_mem_init(void) -{ - arm_add_mem_device("ram0", 0x70000000, SZ_512M); -#ifdef CONFIG_MACH_TQMA53_1GB_RAM - arm_add_mem_device("ram1", 0xb0000000, SZ_512M); -#endif - - return 0; -} -mem_initcall(tqma53_mem_init); - #define GPIO_SD2_CD IMX_GPIO_NR(1, 4) #define GPIO_SD2_WP IMX_GPIO_NR(1, 2) diff --git a/arch/arm/configs/archosg9_defconfig b/arch/arm/configs/archosg9_defconfig index e598258397..2a20dd77ba 100644 --- a/arch/arm/configs/archosg9_defconfig +++ b/arch/arm/configs/archosg9_defconfig @@ -55,7 +55,7 @@ CONFIG_CMD_I2C=y CONFIG_DRIVER_SERIAL_OMAP4_USBBOOT=y CONFIG_DRIVER_SERIAL_NS16550=y CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y -CONFIG_BAUDRATE=1000000 +CONFIG_BAUDRATE=115200 # CONFIG_SPI is not set CONFIG_I2C=y CONFIG_I2C_OMAP=y diff --git a/arch/arm/configs/at91sam9n12ek_defconfig b/arch/arm/configs/at91sam9n12ek_defconfig new file mode 100644 index 0000000000..d46a9bd258 --- /dev/null +++ b/arch/arm/configs/at91sam9n12ek_defconfig @@ -0,0 +1,87 @@ +CONFIG_ARCH_AT91SAM9N12=y +CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 +CONFIG_AEABI=y +# CONFIG_CMD_ARM_CPUINFO is not set +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_PBL_IMAGE=y +CONFIG_MMU=y +CONFIG_TEXT_BASE=0x26f00000 +CONFIG_BAREBOX_MAX_IMAGE_SIZE=0x40000 +CONFIG_EXPERIMENTAL=y +CONFIG_MALLOC_TLSF=y +CONFIG_PROMPT="9G20-EK:" +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_PROMPT_HUSH_PS2="y" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_CONSOLE_ACTIVATE_ALL=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/at91sam9n12ek/env" +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_BOOTM_INITRD=y +CONFIG_CMD_BOOTM_OFTREE=y +CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y +CONFIG_CMD_UIMAGE=y +# CONFIG_CMD_BOOTU is not set +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_SPI=y +CONFIG_CMD_LED=y +CONFIG_CMD_LED_TRIGGER=y +CONFIG_CMD_MIITOOL=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_NETCONSOLE=y +CONFIG_DRIVER_NET_KS8851_MLL=y +CONFIG_DRIVER_SPI_ATMEL=y +CONFIG_I2C=y +CONFIG_I2C_GPIO=y +CONFIG_MTD=y +# CONFIG_MTD_OOB_DEVICE is not set +CONFIG_MTD_M25P80=y +CONFIG_NAND=y +# CONFIG_NAND_ECC_SOFT is not set +# CONFIG_NAND_ECC_HW_SYNDROME is not set +# CONFIG_NAND_ECC_HW_NONE is not set +CONFIG_NAND_ATMEL=y +CONFIG_NAND_ATMEL_PMECC=y +CONFIG_UBI=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DFU=y +CONFIG_USB_GADGET_SERIAL=y +CONFIG_MCI=y +CONFIG_MCI_STARTUP=y +CONFIG_MCI_ATMEL=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_TRIGGERS=y +CONFIG_EEPROM_AT24=y +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_QT1070=y +CONFIG_FS_TFTP=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y +CONFIG_ZLIB=y diff --git a/arch/arm/configs/freescale_mx53_loco_defconfig b/arch/arm/configs/freescale_mx53_loco_defconfig index b50b0509c3..b61f0cfa46 100644 --- a/arch/arm/configs/freescale_mx53_loco_defconfig +++ b/arch/arm/configs/freescale_mx53_loco_defconfig @@ -2,43 +2,57 @@ CONFIG_ARCH_IMX=y CONFIG_ARCH_IMX53=y CONFIG_IMX_IIM=y CONFIG_IMX_IIM_FUSE_BLOW=y -CONFIG_AEABI=y +CONFIG_THUMB2_BAREBOX=y +CONFIG_CMD_ARM_MMUINFO=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_ARM_UNWIND=y +CONFIG_PBL_IMAGE=y CONFIG_MMU=y CONFIG_TEXT_BASE=0x7ff00000 CONFIG_MALLOC_SIZE=0x2000000 CONFIG_MALLOC_TLSF=y CONFIG_KALLSYMS=y CONFIG_LONGHELP=y -CONFIG_GLOB=y CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y -CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_MENU=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/freescale-mx53-loco/env/" +CONFIG_RESET_SOURCE=y CONFIG_DEBUG_INFO=y CONFIG_CMD_EDIT=y CONFIG_CMD_SLEEP=y +CONFIG_CMD_MSLEEP=y CONFIG_CMD_SAVEENV=y CONFIG_CMD_EXPORT=y CONFIG_CMD_PRINTENV=y CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y CONFIG_CMD_TIME=y +CONFIG_CMD_DIRNAME=y +CONFIG_CMD_LN=y +CONFIG_CMD_READLINK=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_FILETYPE=y CONFIG_CMD_ECHO_E=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_IOMEM=y -CONFIG_CMD_FLASH=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MD5SUM=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y CONFIG_CMD_BOOTM_INITRD=y CONFIG_CMD_BOOTM_OFTREE=y CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y CONFIG_CMD_UIMAGE=y -# CONFIG_CMD_BOOTZ is not set # CONFIG_CMD_BOOTU is not set CONFIG_CMD_RESET=y CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_BAREBOX_UPDATE=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_MAGICVAR=y @@ -46,18 +60,19 @@ CONFIG_CMD_MAGICVAR_HELP=y CONFIG_CMD_GPIO=y CONFIG_CMD_UNCOMPRESS=y CONFIG_CMD_I2C=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_CLK=y +CONFIG_CMD_WD=y CONFIG_NET=y CONFIG_NET_DHCP=y -CONFIG_NET_NFS=y CONFIG_NET_PING=y -CONFIG_CMD_TFTP=y -CONFIG_FS_TFTP=y CONFIG_NET_NETCONSOLE=y CONFIG_SMSC_PHY=y CONFIG_DRIVER_NET_FEC_IMX=y # CONFIG_SPI is not set CONFIG_I2C=y CONFIG_I2C_IMX=y +CONFIG_DISK_ATA=y CONFIG_USB=y CONFIG_USB_EHCI=y CONFIG_USB_STORAGE=y @@ -65,6 +80,10 @@ CONFIG_MCI=y CONFIG_MCI_STARTUP=y CONFIG_MCI_IMX_ESDHC=y CONFIG_I2C_MC34708=y +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_IMX=y +CONFIG_FS_TFTP=y +CONFIG_FS_NFS=y CONFIG_FS_FAT=y CONFIG_FS_FAT_WRITE=y CONFIG_FS_FAT_LFN=y diff --git a/arch/arm/configs/vincell_defconfig b/arch/arm/configs/vincell_defconfig new file mode 100644 index 0000000000..ac1f877b8f --- /dev/null +++ b/arch/arm/configs/vincell_defconfig @@ -0,0 +1,82 @@ +CONFIG_ARCH_IMX=y +CONFIG_ARCH_IMX53=y +CONFIG_MACH_GUF_VINCELL=y +CONFIG_IMX_IIM=y +CONFIG_IMX_IIM_FUSE_BLOW=y +CONFIG_THUMB2_BAREBOX=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_ARM_UNWIND=y +CONFIG_PBL_IMAGE=y +CONFIG_MMU=y +CONFIG_TEXT_BASE=0x7fe00000 +CONFIG_MALLOC_SIZE=0x2000000 +CONFIG_MALLOC_TLSF=y +CONFIG_KALLSYMS=y +CONFIG_LONGHELP=y +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/guf-vincell/env" +CONFIG_DEBUG_INFO=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_DIRNAME=y +CONFIG_CMD_LN=y +CONFIG_CMD_READLINK=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_FILETYPE=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_BOOTM_VERBOSE=y +CONFIG_CMD_BOOTM_INITRD=y +CONFIG_CMD_BOOTM_OFTREE=y +# CONFIG_CMD_BOOTU is not set +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_BAREBOX_UPDATE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_MAGICVAR=y +CONFIG_CMD_MAGICVAR_HELP=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_CLK=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_RESOLV=y +CONFIG_DRIVER_NET_FEC_IMX=y +# CONFIG_SPI is not set +CONFIG_I2C=y +CONFIG_I2C_IMX=y +CONFIG_MTD=y +CONFIG_MTD_RAW_DEVICE=y +CONFIG_NAND=y +# CONFIG_NAND_ECC_SOFT is not set +# CONFIG_NAND_ECC_HW_SYNDROME is not set +# CONFIG_NAND_ECC_HW_NONE is not set +CONFIG_NAND_IMX=y +CONFIG_MCI=y +CONFIG_MCI_STARTUP=y +CONFIG_MCI_IMX_ESDHC=y +CONFIG_FS_TFTP=y +CONFIG_FS_NFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 288c0b24a8..51ac9af605 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -143,7 +143,7 @@ static int do_bootz_linux_fdt(int fd, struct image_data *data) if (ret < sizeof(*header)) return ret; - if (file_detect_type(header) != filetype_oftree) + if (file_detect_type(header, sizeof(*header)) != filetype_oftree) return -ENXIO; end = be32_to_cpu(header->totalsize); diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 3a985f7ae5..6fea9035c8 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -8,12 +8,13 @@ config ARCH_TEXT_BASE config BOARDINFO default "Atmel at91rm9200-ek" if MACH_AT91RM9200EK - default "Atmel 91SAM9260-EK" if MACH_AT91SAM9260EK + default "Atmel at91sam9260-ek" if MACH_AT91SAM9260EK default "Atmel at91sam9261-ek" if MACH_AT91SAM9261EK default "Atmel at91sam9263-ek" if MACH_AT91SAM9263EK default "Atmel at91sam9g10-ek" if MACH_AT91SAM9G10EK default "Atmel at91sam9g20-ek" if MACH_AT91SAM9G20EK default "Atmel at91sam9m10g45-ek" if MACH_AT91SAM9M10G45EK + default "Atmel at91sam9n12-ek" if MACH_AT91SAM9N12EK default "Atmel at91sam9x5-ek" if MACH_AT91SAM9X5EK default "Bucyrus MMC-CPU" if MACH_MMCCPU default "Calao USB-A9260" if MACH_USB_A9260 @@ -92,6 +93,11 @@ config ARCH_AT91SAM9X5 select HAS_MACB select AT91SAM9G45_RESET +config ARCH_AT91SAM9N12 + bool "AT91SAM9N12" + select CPU_ARM926T + select AT91SAM9G45_RESET + endchoice config ARCH_BAREBOX_MAX_BARE_INIT_SIZE @@ -103,6 +109,7 @@ config ARCH_BAREBOX_MAX_BARE_INIT_SIZE default 0x3000 if ARCH_AT91SAM9G10 default 0xF000 if ARCH_AT91SAM9G45 default 0x6000 if ARCH_AT91SAM9X5 + default 0x6000 if ARCH_AT91SAM9N12 default 0xffffffff config SUPPORT_CALAO_DAB_MMX @@ -336,6 +343,22 @@ endif # ---------------------------------------------------------- +if ARCH_AT91SAM9N12 + +choice + prompt "AT91SAM9N12 Board Type" + +config MACH_AT91SAM9N12EK + bool "Atmel AT91SAM9N12 Evaluation Kit" + help + Select this if you are using Atmel's AT91SAM9N12-EK Evaluation Kit. + +endchoice + +endif + +# ---------------------------------------------------------- + comment "AT91 Board Options" config MTD_AT91_DATAFLASH_CARD diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 3ade725778..7a1e50643b 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_d obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9X5) += at91sam9x5.o at91sam926x_time.o at91sam9x5_devices.o sam9_smc.o +obj-$(CONFIG_ARCH_AT91SAM9N12) += at91sam9n12.o at91sam926x_time.o at91sam9n12_devices.o sam9_smc.o diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c new file mode 100644 index 0000000000..b74a72a8ec --- /dev/null +++ b/arch/arm/mach-at91/at91sam9n12.c @@ -0,0 +1,233 @@ +#include <common.h> +#include <gpio.h> +#include <init.h> +#include <asm/hardware.h> +#include <mach/at91_pmc.h> +#include <mach/io.h> +#include <mach/cpu.h> + +#include "generic.h" +#include "clock.h" + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioAB_clk = { + .name = "pioAB_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_PIOAB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioCD_clk = { + .name = "pioCD_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_PIOCD, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_USART0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_USART1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_USART2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart3_clk = { + .name = "usart3_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_USART3, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi0_clk = { + .name = "twi0_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_TWI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi1_clk = { + .name = "twi1_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_TWI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { + .name = "mci_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_MCI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk uart0_clk = { + .name = "uart0_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_UART0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk uart1_clk = { + .name = "uart1_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_UART1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk tcb0_clk = { + .name = "tcb0_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_TCB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pwm_clk = { + .name = "pwm_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_PWM, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk adc_clk = { + .name = "adc_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_ADC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk dma_clk = { + .name = "dma_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_DMA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk uhpfs_clk = { + .name = "uhpfs_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_UHPFS, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_UDPFS, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_LCDC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ssc_clk = { + .name = "ssc_clk", + .pmc_mask = 1 << AT91SAM9N12_ID_SSC, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioAB_clk, + &pioCD_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &usart3_clk, + &twi0_clk, + &twi1_clk, + &mmc_clk, + &spi0_clk, + &spi1_clk, + &uart0_clk, + &uart1_clk, + &tcb0_clk, + &pwm_clk, + &adc_clk, + &dma_clk, + &lcdc_clk, + &uhpfs_clk, + &udc_clk, + &ssc_clk, +}; + +static struct clk_lookup periph_clocks_lookups[] = { + CLKDEV_CON_ID("ohci_clk", &uhpfs_clk), + CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi0", &spi0_clk), + CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi1", &spi1_clk), +}; + +static struct clk_lookup usart_clocks_lookups[] = { + CLKDEV_CON_DEV_ID("usart", "atmel_usart0", &mck), + CLKDEV_CON_DEV_ID("usart", "atmel_usart1", &usart0_clk), + CLKDEV_CON_DEV_ID("usart", "atmel_usart2", &usart1_clk), + CLKDEV_CON_DEV_ID("usart", "atmel_usart3", &usart2_clk), + CLKDEV_CON_DEV_ID("usart", "atmel_usart4", &usart3_clk), +}; + +/* + * The two programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; + +static void __init at91sam9n12_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); + + clkdev_add_table(periph_clocks_lookups, + ARRAY_SIZE(periph_clocks_lookups)); + clkdev_add_table(usart_clocks_lookups, + ARRAY_SIZE(usart_clocks_lookups)); + +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9n12_gpio[] = { + { + .regbase = IOMEM(AT91_BASE_PIOA), + .clock = &pioAB_clk, + }, { + .regbase = IOMEM(AT91_BASE_PIOB), + .clock = &pioAB_clk, + }, { + .regbase = IOMEM(AT91_BASE_PIOC), + .clock = &pioCD_clk, + }, { + .regbase = IOMEM(AT91_BASE_PIOD), + .clock = &pioCD_clk, + } +}; + +/* -------------------------------------------------------------------- + * AT91SAM9N12 processor initialization + * -------------------------------------------------------------------- */ + +static int at91sam9n12_initialize(void) +{ + /* Init clock subsystem */ + at91_clock_init(AT91_MAIN_CLOCK); + + /* Register the processor-specific clocks */ + at91sam9n12_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9n12_gpio, 4); + return 0; +} +core_initcall(at91sam9n12_initialize); diff --git a/arch/arm/mach-at91/at91sam9n12_devices.c b/arch/arm/mach-at91/at91sam9n12_devices.c new file mode 100644 index 0000000000..33baf41743 --- /dev/null +++ b/arch/arm/mach-at91/at91sam9n12_devices.c @@ -0,0 +1,374 @@ +/* + * On-Chip devices setup code for the AT91SAM9x5 family + * + * Copyright (C) 2010 Atmel Corporation. + * + * 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 <init.h> +#include <sizes.h> +#include <asm/armlinux.h> +#include <asm/hardware.h> +#include <mach/board.h> +#include <mach/at91_pmc.h> +#include <mach/at91sam9n12_matrix.h> +#include <mach/gpio.h> +#include <mach/io.h> +#include <mach/cpu.h> +#include <i2c/i2c-gpio.h> + +#include "generic.h" + +void at91_add_device_sdram(u32 size) +{ + arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size); + add_mem_device("sram0", AT91SAM9N12_SRAM_BASE, + AT91SAM9N12_SRAM_SIZE, IORESOURCE_MEM_WRITEABLE); +} + +/* -------------------------------------------------------------------- + * USB Host (OHCI) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI) +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) +{ + int i; + + if (!data) + return; + + /* Enable VBus control for UHP ports */ + for (i = 0; i < data->ports; i++) { + if (data->vbus_pin[i]) + at91_set_gpio_output(data->vbus_pin[i], 0); + } + + add_generic_device("at91_ohci", DEVICE_ID_DYNAMIC, NULL, AT91SAM9N12_OHCI_BASE, + SZ_1M, IORESOURCE_MEM, data); +} +#else +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {} +#endif + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_DRIVER_AT91 +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + if (data->vbus_pin > 0) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + add_generic_device("at91_udc", DEVICE_ID_SINGLE, NULL, AT91SAM9N12_BASE_UDPFS, + SZ_16K, IORESOURCE_MEM, data); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + +#if defined(CONFIG_MCI_ATMEL) +/* Consider only one slot : slot 0 */ +void __init at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data) +{ + if (!data) + return; + + /* Must have at least one usable slot */ + if (!data->bus_width) + return; + + /* input/irq */ + if (data->detect_pin) { + at91_set_gpio_input(data->detect_pin, 1); + at91_set_deglitch(data->detect_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA17, 0); + + /* CMD */ + at91_set_A_periph(AT91_PIN_PA16, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA15, 1); + if (data->bus_width == 4) { + at91_set_A_periph(AT91_PIN_PA18, 1); + at91_set_A_periph(AT91_PIN_PA19, 1); + at91_set_A_periph(AT91_PIN_PA20, 1); + } + + add_generic_device("atmel_mci", DEVICE_ID_SINGLE, NULL, AT91SAM9N12_BASE_MCI, SZ_16K, + IORESOURCE_MEM, data); +} +#else +void __init at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data) {} +#endif + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_NAND_ATMEL) +static struct resource nand_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_3, + .end = AT91_CHIPSELECT_3 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_PMECC, + .end = AT91_BASE_SYS + AT91_PMECC + 0x600 - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = AT91_BASE_SYS + AT91_PMERRLOC, + .end = AT91_BASE_SYS + AT91_PMERRLOC + 0x200 - 1, + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = AT91SAM9N12_ROM_BASE, + .end = AT91SAM9N12_ROM_BASE + AT91SAM9N12_ROM_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +void __init at91_add_device_nand(struct atmel_nand_data *data) +{ + unsigned long csa; + + if (!data) + return; + + data->pmecc_lookup_table_offset = 0x8000; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + + /* Assign CS3 to NAND/SmartMedia Interface */ + csa |= AT91_MATRIX_EBI_CS3A_SMC_NANDFLASH; + /* Configure databus */ + if (!data->bus_on_d0) + csa |= AT91_MATRIX_NFD0_ON_D16; + else + csa &= ~AT91_MATRIX_NFD0_ON_D16; + /* Configure IO drive */ + csa |= AT91_MATRIX_EBI_HIGH_DRIVE; + + at91_sys_write(AT91_MATRIX_EBICSA, csa); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + /* configure NANDOE */ + at91_set_A_periph(AT91_PIN_PD0, 1); + /* configure NANDWE */ + at91_set_A_periph(AT91_PIN_PD1, 1); + /* configure ALE */ + at91_set_A_periph(AT91_PIN_PD2, 1); + /* configure CLE */ + at91_set_A_periph(AT91_PIN_PD3, 1); + + /* configure multiplexed pins for D16~D31 */ + if (!data->bus_on_d0) { + at91_set_A_periph(AT91_PIN_PD6, 1); + at91_set_A_periph(AT91_PIN_PD7, 1); + at91_set_A_periph(AT91_PIN_PD8, 1); + at91_set_A_periph(AT91_PIN_PD9, 1); + at91_set_A_periph(AT91_PIN_PD10, 1); + at91_set_A_periph(AT91_PIN_PD11, 1); + at91_set_A_periph(AT91_PIN_PD12, 1); + at91_set_A_periph(AT91_PIN_PD13, 1); + + if (data->bus_width_16) { + at91_set_A_periph(AT91_PIN_PD14, 1); + at91_set_A_periph(AT91_PIN_PD15, 1); + at91_set_A_periph(AT91_PIN_PD16, 1); + at91_set_A_periph(AT91_PIN_PD17, 1); + at91_set_A_periph(AT91_PIN_PD18, 1); + at91_set_A_periph(AT91_PIN_PD19, 1); + at91_set_A_periph(AT91_PIN_PD20, 1); + at91_set_A_periph(AT91_PIN_PD21, 1); + } + + } + + add_generic_device_res("atmel_nand", DEVICE_ID_SINGLE, nand_resources, + ARRAY_SIZE(nand_resources), data); +} +#else +void __init at91_add_device_nand(struct atmel_nand_data *data) {} +#endif + +#if defined(CONFIG_I2C_GPIO) +static struct i2c_gpio_platform_data pdata_i2c0 = { + .sda_pin = AT91_PIN_PA30, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PA31, + .scl_is_open_drain = 1, + .udelay = 5, /* ~100 kHz */ +}; + +void at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) +{ + struct i2c_gpio_platform_data *pdata = &pdata_i2c0; + + i2c_register_board_info(0, devices, nr_devices); + + at91_set_GPIO_periph(pdata->sda_pin, 1); /* TWD (SDA) */ + at91_set_multi_drive(pdata->sda_pin, 1); + + at91_set_GPIO_periph(pdata->scl_pin, 1); /* TWCK (SCL) */ + at91_set_multi_drive(pdata->scl_pin, 1); + + add_generic_device_res("i2c-gpio", 0, NULL, 0, pdata); +} +#else +void at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) {} +#endif + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_DRIVER_SPI_ATMEL) +static unsigned spi0_standard_cs[4] = { AT91_PIN_PA14, AT91_PIN_PA7, AT91_PIN_PA1, AT91_PIN_PB3 }; + +static unsigned spi1_standard_cs[4] = { AT91_PIN_PA8, AT91_PIN_PA0, AT91_PIN_PA31, AT91_PIN_PA30 }; + +static struct at91_spi_platform_data spi_pdata[] = { + [0] = { + .chipselect = spi0_standard_cs, + .num_chipselect = ARRAY_SIZE(spi0_standard_cs), + }, + [1] = { + .chipselect = spi1_standard_cs, + .num_chipselect = ARRAY_SIZE(spi1_standard_cs), + }, +}; + +void at91_add_device_spi(int spi_id, struct at91_spi_platform_data *pdata) +{ + int i; + int cs_pin; + resource_size_t start = ~0; + + BUG_ON(spi_id > 1); + + if (!pdata) + pdata = &spi_pdata[spi_id]; + + for (i = 0; i < pdata->num_chipselect; i++) { + cs_pin = pdata->chipselect[i]; + + /* enable chip-select pin */ + if (gpio_is_valid(cs_pin)) + at91_set_gpio_output(cs_pin, 1); + } + + /* Configure SPI bus(es) */ + switch (spi_id) { + case 0: + start = AT91SAM9N12_BASE_SPI0; + at91_set_A_periph(AT91_PIN_PA11, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PA12, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* SPI0_SPCK */ + break; + case 1: + start = AT91SAM9N12_BASE_SPI1; + at91_set_B_periph(AT91_PIN_PA21, 0); /* SPI1_MISO */ + at91_set_B_periph(AT91_PIN_PA22, 0); /* SPI1_MOSI */ + at91_set_B_periph(AT91_PIN_PA23, 0); /* SPI1_SPCK */ + break; + } + + add_generic_device("atmel_spi", spi_id, NULL, start, SZ_16K, + IORESOURCE_MEM, pdata); +} +#else +void at91_add_device_spi(int spi_id, struct at91_spi_platform_data *pdata) {} +#endif + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_DRIVER_SERIAL_ATMEL) +resource_size_t __init at91_configure_dbgu(void) +{ + at91_set_A_periph(AT91_PIN_PA9, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PA10, 1); /* DTXD */ + + return AT91_BASE_SYS + AT91_DBGU; +} + +resource_size_t __init at91_configure_usart0(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PA0, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* RXD0 */ + + if (pins & ATMEL_UART_RTS) + at91_set_A_periph(AT91_PIN_PA2, 0); /* RTS0 */ + if (pins & ATMEL_UART_CTS) + at91_set_A_periph(AT91_PIN_PA3, 0); /* CTS0 */ + + return AT91SAM9N12_BASE_USART0; +} + +resource_size_t __init at91_configure_usart1(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PA5, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PA6, 0); /* RXD1 */ + + if (pins & ATMEL_UART_RTS) + at91_set_C_periph(AT91_PIN_PC27, 0); /* RTS1 */ + if (pins & ATMEL_UART_CTS) + at91_set_C_periph(AT91_PIN_PC28, 0); /* CTS1 */ + + return AT91SAM9N12_BASE_USART1; +} + +resource_size_t __init at91_configure_usart2(unsigned pins) +{ + at91_set_A_periph(AT91_PIN_PA7, 1); /* TXD2 */ + at91_set_A_periph(AT91_PIN_PA8, 0); /* RXD2 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PB0, 0); /* RTS2 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PB1, 0); /* CTS2 */ + + return AT91SAM9N12_BASE_USART2; +} + +resource_size_t __init at91_configure_usart3(unsigned pins) +{ + at91_set_B_periph(AT91_PIN_PC22, 1); /* TXD3 */ + at91_set_B_periph(AT91_PIN_PC23, 0); /* RXD3 */ + + if (pins & ATMEL_UART_RTS) + at91_set_B_periph(AT91_PIN_PC24, 0); /* RTS3 */ + if (pins & ATMEL_UART_CTS) + at91_set_B_periph(AT91_PIN_PC25, 0); /* CTS3 */ + + return AT91SAM9N12_BASE_USART3; +} +#endif diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index fd9ba4633f..e911270abc 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -46,7 +46,8 @@ #define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \ || cpu_is_at91sam9g45() \ - || cpu_is_at91sam9x5()) + || cpu_is_at91sam9x5() \ + || cpu_is_at91sam9n12()) #define cpu_has_300M_plla() (cpu_is_at91sam9g10()) @@ -58,7 +59,8 @@ #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ || cpu_is_at91sam9g45() \ - || cpu_is_at91sam9x5())) + || cpu_is_at91sam9x5() \ + || cpu_is_at91sam9n12())) #define cpu_has_upll() (cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5()) @@ -72,12 +74,15 @@ || cpu_is_at91sam9x5())) #define cpu_has_plladiv2() (cpu_is_at91sam9g45() \ - || cpu_is_at91sam9x5()) + || cpu_is_at91sam9x5() \ + || cpu_is_at91sam9n12()) #define cpu_has_mdiv3() (cpu_is_at91sam9g45() \ - || cpu_is_at91sam9x5()) + || cpu_is_at91sam9x5() \ + || cpu_is_at91sam9n12()) -#define cpu_has_alt_prescaler() (cpu_is_at91sam9x5()) +#define cpu_has_alt_prescaler() (cpu_is_at91sam9x5() \ + || cpu_is_at91sam9n12()) static LIST_HEAD(clocks); diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index c303326eaa..c35f00e142 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c @@ -364,7 +364,7 @@ int at91_gpio_init(struct at91_gpio_bank *data, int nr_banks) clk_enable(data->clock); } - cpu_has_pio3 = cpu_is_at91sam9x5(); + cpu_has_pio3 = cpu_is_at91sam9x5() || cpu_is_at91sam9n12(); return 0; } diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h new file mode 100644 index 0000000000..dcbdb1b694 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at91sam9n12.h @@ -0,0 +1,166 @@ +/* + * Chip-specific header file for the AT91SAM9N12 SoC + * + * Copyright (C) 2011 Atmel Corporation + * + * Common definitions. + * Based on AT91SAM9N12 preliminary datasheet + * + * 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. + */ + +#ifndef __MACH_AT91SAM9N12_H_ +#define __MACH_AT91SAM9N12_H_ + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */ +#define AT91_ID_SYS 1 /* System Controller Interrupt */ +#define AT91SAM9N12_ID_PIOAB 2 /* Parallel I/O Controller A and B */ +#define AT91SAM9N12_ID_PIOCD 3 /* Parallel I/O Controller C and D */ +/* Reserved 4 */ +#define AT91SAM9N12_ID_USART0 5 /* USART 0 */ +#define AT91SAM9N12_ID_USART1 6 /* USART 1 */ +#define AT91SAM9N12_ID_USART2 7 /* USART 2 */ +#define AT91SAM9N12_ID_USART3 8 /* USART 3 */ +#define AT91SAM9N12_ID_TWI0 9 /* Two-Wire Interface 0 */ +#define AT91SAM9N12_ID_TWI1 10 /* Two-Wire Interface 1 */ +/* Reserved 11 */ +#define AT91SAM9N12_ID_MCI 12 /* High Speed Multimedia Card Interface 0 */ +#define AT91SAM9N12_ID_SPI0 13 /* Serial Peripheral Interface 0 */ +#define AT91SAM9N12_ID_SPI1 14 /* Serial Peripheral Interface 1 */ +#define AT91SAM9N12_ID_UART0 15 /* UART 0 */ +#define AT91SAM9N12_ID_UART1 16 /* UART 1 */ +#define AT91SAM9N12_ID_TCB 17 /* Timer Counter 0, 1, 2, 3, 4 and 5 */ +#define AT91SAM9N12_ID_PWM 18 /* Pulse Width Modulation Controller */ +#define AT91SAM9N12_ID_ADC 19 /* ADC Controller */ +#define AT91SAM9N12_ID_DMA 20 /* DMA Controller 0 */ +/* Reserved 21 */ +#define AT91SAM9N12_ID_UHPFS 22 /* USB Host Full Speed */ +#define AT91SAM9N12_ID_UDPFS 23 /* USB Device Full Speed */ +/* Reserved 24 */ +#define AT91SAM9N12_ID_LCDC 25 /* LCD Controller */ +/* Reserved 26 */ +/* Reserved 27 */ +#define AT91SAM9N12_ID_SSC 28 /* Synchronous Serial Controller */ +/* Reserved 29 */ +#define AT91SAM9N12_ID_TRNG 30 /* True Random Number Generator */ +#define AT91SAM9N12_ID_IRQ0 31 /* Advanced Interrupt Controller */ + +/* + * User Peripheral physical base addresses. + */ +#define AT91SAM9N12_BASE_SPI0 0xf0000000 +#define AT91SAM9N12_BASE_SPI1 0xf0004000 +#define AT91SAM9N12_BASE_MCI 0xf0008000 +#define AT91SAM9N12_BASE_SSC 0xf0010000 +#define AT91SAM9N12_BASE_TCB0 0xf8008000 +#define AT91SAM9N12_BASE_TC0 0xf8008000 +#define AT91SAM9N12_BASE_TC1 0xf8008040 +#define AT91SAM9N12_BASE_TC2 0xf8008080 +#define AT91SAM9N12_BASE_TCB1 0xf800c000 +#define AT91SAM9N12_BASE_TC3 0xf800c000 +#define AT91SAM9N12_BASE_TC4 0xf800c040 +#define AT91SAM9N12_BASE_TC5 0xf800c080 +#define AT91SAM9N12_BASE_TWI0 0xf8010000 +#define AT91SAM9N12_BASE_TWI1 0xf8014000 +#define AT91SAM9N12_BASE_USART0 0xf801c000 +#define AT91SAM9N12_BASE_USART1 0xf8020000 +#define AT91SAM9N12_BASE_USART2 0xf8024000 +#define AT91SAM9N12_BASE_USART3 0xf8028000 +#define AT91SAM9N12_BASE_PWMC 0xf8034000 +#define AT91SAM9N12_BASE_LCDC 0xf8038000 +#define AT91SAM9N12_BASE_UDPFS 0xf803c000 +#define AT91SAM9N12_BASE_UART0 0xf8040000 +#define AT91SAM9N12_BASE_UART1 0xf8044000 +#define AT91SAM9N12_BASE_TRNG 0xf8048000 +#define AT91SAM9N12_BASE_ADC 0xf804c000 +#define AT91_BASE_SYS 0xffffc000 + +/* + * System Peripherals (offset from AT91_BASE_SYS) + */ +#define AT91_FUSE (0xffffdc00 - AT91_BASE_SYS) +#define AT91_MATRIX (0xffffde00 - AT91_BASE_SYS) +#define AT91_PMECC (0xffffe000 - AT91_BASE_SYS) +#define AT91_PMERRLOC (0xffffe600 - AT91_BASE_SYS) +#define AT91_DDRSDRC0 (0xffffe800 - AT91_BASE_SYS) +#define AT91_SMC (0xffffea00 - AT91_BASE_SYS) +#define AT91_DMA (0xffffec00 - AT91_BASE_SYS) +#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) +#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS) +#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) +#define AT91_RSTC (0xfffffe00 - AT91_BASE_SYS) +#define AT91_SHDWC (0xfffffe10 - AT91_BASE_SYS) +#define AT91_PIT (0xfffffe30 - AT91_BASE_SYS) +#define AT91_WDT (0xfffffe40 - AT91_BASE_SYS) +#define AT91_GPBR (0xfffffe60 - AT91_BASE_SYS) +#define AT91_RTC (0xfffffeb0 - AT91_BASE_SYS) + +#define AT91_BASE_PIOA 0xfffff400 +#define AT91_BASE_PIOB 0xfffff600 +#define AT91_BASE_PIOC 0xfffff800 +#define AT91_BASE_PIOD 0xfffffa00 + +#define AT91_USART0 AT91SAM9X5_BASE_US0 +#define AT91_USART1 AT91SAM9X5_BASE_US1 +#define AT91_USART2 AT91SAM9X5_BASE_US2 +#define AT91_USART3 AT91SAM9X5_BASE_US3 +#define AT91_NB_USART 5 + + +/* + * Internal Memory. + */ +#define AT91SAM9N12_SRAM_BASE 0x00300000 /* Internal SRAM base address */ +#define AT91SAM9N12_SRAM_SIZE SZ_32K /* Internal SRAM size (32Kb) */ + +#define AT91SAM9N12_ROM_BASE 0x00100000 /* Internal ROM base address */ +#define AT91SAM9N12_ROM_SIZE SZ_1M /* Internal ROM size (1Mb) */ + +#define AT91SAM9N12_SMD_BASE 0x00400000 /* SMD Controller */ +#define AT91SAM9N12_OHCI_BASE 0x00500000 /* USB Host controller (OHCI) */ + +#define CONFIG_DRAM_BASE AT91_CHIPSELECT_1 + +#define CONSISTENT_DMA_SIZE (14 * SZ_1M) + +/* + * DMA0 peripheral identifiers + * for hardware handshaking interface + */ +#define AT_DMA_ID_MCI 0 +#define AT_DMA_ID_SPI0_TX 1 +#define AT_DMA_ID_SPI0_RX 2 +#define AT_DMA_ID_SPI1_TX 3 +#define AT_DMA_ID_SPI1_RX 4 +#define AT_DMA_ID_USART0_TX 5 +#define AT_DMA_ID_USART0_RX 6 +#define AT_DMA_ID_USART1_TX 7 +#define AT_DMA_ID_USART1_RX 8 +#define AT_DMA_ID_USART2_TX 9 +#define AT_DMA_ID_USART2_RX 10 +#define AT_DMA_ID_USART3_TX 11 +#define AT_DMA_ID_USART3_RX 12 +#define AT_DMA_ID_TWI0_TX 13 +#define AT_DMA_ID_TWI0_RX 14 +#define AT_DMA_ID_TWI1_TX 15 +#define AT_DMA_ID_TWI1_RX 16 +#define AT_DMA_ID_UART0_TX 17 +#define AT_DMA_ID_UART0_RX 18 +#define AT_DMA_ID_UART1_TX 19 +#define AT_DMA_ID_UART1_RX 20 +#define AT_DMA_ID_SSC_TX 21 +#define AT_DMA_ID_SSC_RX 22 +#define AT_DMA_ID_ADC_RX 23 +#define AT_DMA_ID_DBGU_TX 24 +#define AT_DMA_ID_DBGU_RX 25 +#define AT_DMA_ID_AES_TX 26 +#define AT_DMA_ID_AES_RX 27 +#define AT_DMA_ID_SHA_RX 28 + +#endif diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h new file mode 100644 index 0000000000..0e42918f65 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h @@ -0,0 +1,98 @@ +/* + * Matrix-Centric header file for the AT91SAM9N12 SoC + * + * Copyright (C) 2011 Atmel Corporation + * + * Memory Controllers (MATRIX, EBI) - System peripherals registers. + * Based on AT91SAM9N12 preliminary datasheet. + * + * 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. + */ + +#ifndef _AT91SAM9N12_MATRIX_H_ +#define _AT91SAM9N12_MATRIX_H_ + +#define AT91_MATRIX_MCFG0 (AT91_MATRIX + 0x00) /* Master Configuration Register 0 */ +#define AT91_MATRIX_MCFG1 (AT91_MATRIX + 0x04) /* Master Configuration Register 1 */ +#define AT91_MATRIX_MCFG2 (AT91_MATRIX + 0x08) /* Master Configuration Register 2 */ +#define AT91_MATRIX_MCFG3 (AT91_MATRIX + 0x0C) /* Master Configuration Register 3 */ +#define AT91_MATRIX_MCFG4 (AT91_MATRIX + 0x10) /* Master Configuration Register 4 */ +#define AT91_MATRIX_MCFG5 (AT91_MATRIX + 0x14) /* Master Configuration Register 5 */ +#define AT91_MATRIX_ULBT (7 << 0) /* Undefined Length Burst Type */ +#define AT91_MATRIX_ULBT_INFINITE (0 << 0) +#define AT91_MATRIX_ULBT_SINGLE (1 << 0) +#define AT91_MATRIX_ULBT_FOUR (2 << 0) +#define AT91_MATRIX_ULBT_EIGHT (3 << 0) +#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0) +#define AT91_MATRIX_ULBT_THIRTYTWO (5 << 0) +#define AT91_MATRIX_ULBT_SIXTYFOUR (6 << 0) +#define AT91_MATRIX_ULBT_128 (7 << 0) + +#define AT91_MATRIX_SCFG0 (AT91_MATRIX + 0x40) /* Slave Configuration Register 0 */ +#define AT91_MATRIX_SCFG1 (AT91_MATRIX + 0x44) /* Slave Configuration Register 1 */ +#define AT91_MATRIX_SCFG2 (AT91_MATRIX + 0x48) /* Slave Configuration Register 2 */ +#define AT91_MATRIX_SCFG3 (AT91_MATRIX + 0x4C) /* Slave Configuration Register 3 */ +#define AT91_MATRIX_SCFG4 (AT91_MATRIX + 0x50) /* Slave Configuration Register 4 */ +#define AT91_MATRIX_SLOT_CYCLE (0x1ff << 0) /* Maximum Number of Allowed Cycles for a Burst */ +#define AT91_MATRIX_DEFMSTR_TYPE (3 << 16) /* Default Master Type */ +#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16) +#define AT91_MATRIX_FIXED_DEFMSTR (0xf << 18) /* Fixed Index of Default Master */ + +#define AT91_MATRIX_PRAS0 (AT91_MATRIX + 0x80) /* Priority Register A for Slave 0 */ +#define AT91_MATRIX_PRAS1 (AT91_MATRIX + 0x88) /* Priority Register A for Slave 1 */ +#define AT91_MATRIX_PRAS2 (AT91_MATRIX + 0x90) /* Priority Register A for Slave 2 */ +#define AT91_MATRIX_PRAS3 (AT91_MATRIX + 0x98) /* Priority Register A for Slave 3 */ +#define AT91_MATRIX_PRAS4 (AT91_MATRIX + 0xA0) /* Priority Register A for Slave 4 */ +#define AT91_MATRIX_M0PR (3 << 0) /* Master 0 Priority */ +#define AT91_MATRIX_M1PR (3 << 4) /* Master 1 Priority */ +#define AT91_MATRIX_M2PR (3 << 8) /* Master 2 Priority */ +#define AT91_MATRIX_M3PR (3 << 12) /* Master 3 Priority */ +#define AT91_MATRIX_M4PR (3 << 16) /* Master 4 Priority */ +#define AT91_MATRIX_M5PR (3 << 20) /* Master 5 Priority */ + +#define AT91_MATRIX_MRCR (AT91_MATRIX + 0x100) /* Master Remap Control Register */ +#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */ +#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */ +#define AT91_MATRIX_RCB2 (1 << 2) +#define AT91_MATRIX_RCB3 (1 << 3) +#define AT91_MATRIX_RCB4 (1 << 4) +#define AT91_MATRIX_RCB5 (1 << 5) + +#define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x118) /* EBI Chip Select Assignment Register */ +#define AT91_MATRIX_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */ +#define AT91_MATRIX_EBI_CS1A_SMC (0 << 1) +#define AT91_MATRIX_EBI_CS1A_SDRAMC (1 << 1) +#define AT91_MATRIX_EBI_CS3A (1 << 3) /* Chip Select 3 Assignment */ +#define AT91_MATRIX_EBI_CS3A_SMC (0 << 3) +#define AT91_MATRIX_EBI_CS3A_SMC_NANDFLASH (1 << 3) +#define AT91_MATRIX_EBI_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ +#define AT91_MATRIX_EBI_DBPU_ON (0 << 8) +#define AT91_MATRIX_EBI_DBPU_OFF (1 << 8) +#define AT91_MATRIX_EBI_DBPDC (1 << 9) /* Data Bus Pull-up Configuration */ +#define AT91_MATRIX_EBI_DBPD_ON (0 << 9) +#define AT91_MATRIX_EBI_DBPD_OFF (1 << 9) +#define AT91_MATRIX_EBI_DRIVE (1 << 17) /* EBI I/O Drive Configuration */ +#define AT91_MATRIX_EBI_LOW_DRIVE (0 << 17) +#define AT91_MATRIX_EBI_HIGH_DRIVE (1 << 17) +#define AT91_MATRIX_NFD0_SELECT (1 << 24) /* NAND Flash Data Bus Selection */ +#define AT91_MATRIX_NFD0_ON_D0 (0 << 24) +#define AT91_MATRIX_NFD0_ON_D16 (1 << 24) + +#define AT91_MATRIX_WPMR (AT91_MATRIX + 0x1E4) /* Write Protect Mode Register */ +#define AT91_MATRIX_WPMR_WPEN (1 << 0) /* Write Protect ENable */ +#define AT91_MATRIX_WPMR_WP_WPDIS (0 << 0) +#define AT91_MATRIX_WPMR_WP_WPEN (1 << 0) +#define AT91_MATRIX_WPMR_WPKEY (0xFFFFFF << 8) /* Write Protect KEY */ + +#define AT91_MATRIX_WPSR (AT91_MATRIX + 0x1E8) /* Write Protect Status Register */ +#define AT91_MATRIX_WPSR_WPVS (1 << 0) /* Write Protect Violation Status */ +#define AT91_MATRIX_WPSR_NO_WPV (0 << 0) +#define AT91_MATRIX_WPSR_WPV (1 << 0) +#define AT91_MATRIX_WPSR_WPVSRC (0xFFFF << 8) /* Write Protect Violation Source */ + +#endif diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index dcea9f3954..98c69f9f66 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -54,6 +54,7 @@ struct atmel_nand_data { u8 bus_width_16; /* buswidth is 16 bit */ u8 ecc_mode; /* NAND_ECC_* */ u8 on_flash_bbt; /* Use flash based bbt */ + u8 bus_on_d0; u8 pmecc_corr_cap; u16 pmecc_sector_size; diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index 0700f21253..90b9f8a391 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -28,6 +28,7 @@ #define ARCH_ID_AT91SAM9G45MRL 0x819b05a2 /* aka 9G45-ES2 & non ES lots */ #define ARCH_ID_AT91SAM9G45ES 0x819b05a1 /* 9G45-ES (Engineering Sample) */ #define ARCH_ID_AT91SAM9X5 0x819a05a0 +#define ARCH_ID_AT91SAM9N12 0x819a07a0 #define ARCH_ID_AT91CAP9 0x039A03A0 #define ARCH_ID_AT91SAM9XE128 0x329973a0 @@ -171,6 +172,12 @@ static inline unsigned long at91cap9_rev_identify(void) #define cpu_is_at91sam9x25() (0) #endif +#ifdef CONFIG_ARCH_AT91SAM9N12 +#define cpu_is_at91sam9n12() (at91_cpu_identify() == ARCH_ID_AT91SAM9N12) +#else +#define cpu_is_at91sam9n12() (0) +#endif + #ifdef CONFIG_ARCH_AT91CAP9 #define cpu_is_at91cap9() (at91_cpu_identify() == ARCH_ID_AT91CAP9) #define cpu_is_at91cap9_revB() (at91cap9_rev_identify() == ARCH_REVISION_CAP9_B) diff --git a/arch/arm/mach-at91/include/mach/debug_ll.h b/arch/arm/mach-at91/include/mach/debug_ll.h index ee824cbf2f..a85fdee994 100644 --- a/arch/arm/mach-at91/include/mach/debug_ll.h +++ b/arch/arm/mach-at91/include/mach/debug_ll.h @@ -25,7 +25,7 @@ * * This does not append a newline */ -static void putc(int c) +static inline void PUTC_LL(char c) { while (!(__raw_readl(UART_BASE + ATMEL_US_CSR) & ATMEL_US_TXRDY)) barrier(); diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h index 7af88038a7..f8ac7910e5 100644 --- a/arch/arm/mach-at91/include/mach/hardware.h +++ b/arch/arm/mach-at91/include/mach/hardware.h @@ -26,6 +26,8 @@ #include <mach/at91sam9rl.h> #elif defined(CONFIG_ARCH_AT91SAM9G45) #include <mach/at91sam9g45.h> +#elif defined(CONFIG_ARCH_AT91SAM9N12) +#include <mach/at91sam9n12.h> #elif defined(CONFIG_ARCH_AT91SAM9X5) #include <mach/at91sam9x5.h> #elif defined(CONFIG_ARCH_AT91CAP9) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 3f4b45210c..1bc2e249b9 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -28,6 +28,7 @@ config ARCH_TEXT_BASE default 0x97f00000 if MACH_CCMX51 default 0x4fc00000 if MACH_SABRELITE default 0x8fe00000 if MACH_TX53 + default 0x7fc00000 if MACH_GUF_VINCELL config BOARDINFO default "Eukrea CPUIMX25" if MACH_EUKREA_CPUIMX25 @@ -55,6 +56,7 @@ config BOARDINFO default "ConnectCore i.MX51" if MACH_CCMX51 default "Sabre Lite" if MACH_SABRELITE default "Ka-Ro tx53" if MACH_TX53 + default "Garz+Fricke Vincell" if MACH_GUF_VINCELL choice prompt "Select boot mode" @@ -446,6 +448,7 @@ choice prompt "i.MX53 Board Type" config MACH_FREESCALE_MX53_LOCO + select HAVE_DEFAULT_ENVIRONMENT_NEW bool "Freescale i.MX53 LOCO" config MACH_FREESCALE_MX53_SMD @@ -468,6 +471,11 @@ config MACH_TX53 help Say Y here if you are using the Ka-Ro tx53 board +config MACH_GUF_VINCELL + select HAVE_DEFAULT_ENVIRONMENT_NEW + select MACH_HAS_LOWLEVEL_INIT + bool "Garz-Fricke Vincell" + endchoice if MACH_TX53 @@ -477,7 +485,9 @@ config TX53_REV_1011 bool "1011" config TX53_REV_XX30 bool "8030 / 1030" + endchoice + endif endif diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 259733ece0..104ab21134 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -6,14 +6,15 @@ obj-$(CONFIG_ARCH_IMX27) += imx27.o iomux-v1.o clk-imx27.o obj-$(CONFIG_ARCH_IMX31) += imx31.o iomux-v2.o clk-imx31.o obj-$(CONFIG_ARCH_IMX35) += imx35.o iomux-v3.o clk-imx35.o obj-$(CONFIG_ARCH_IMX51) += imx51.o iomux-v3.o imx5.o clk-imx5.o -obj-$(CONFIG_ARCH_IMX53) += imx53.o iomux-v3.o imx5.o clk-imx5.o -pbl-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o +obj-$(CONFIG_ARCH_IMX53) += imx53.o iomux-v3.o imx5.o clk-imx5.o esdctl-v4.o +pbl-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o obj-$(CONFIG_ARCH_IMX6) += imx6.o iomux-v3.o usb-imx6.o clk-imx6.o obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_NAND_IMX) += nand.o obj-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o pbl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-pfd.o -obj-y += devices.o imx.o +obj-y += devices.o imx.o esdctl.o obj-y += boot.o obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o +pbl-y += esdctl.o diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c index ae7c48b2ea..8c7f8eefa3 100644 --- a/arch/arm/mach-imx/boot.c +++ b/arch/arm/mach-imx/boot.c @@ -218,3 +218,63 @@ int imx53_boot_save_loc(void __iomem *src_base) return 0; } + +#define IMX6_SRC_SBMR1 0x04 +#define IMX6_SRC_SBMR2 0x1c + +int imx6_boot_save_loc(void __iomem *src_base) +{ + enum imx_bootsource src = bootsource_unknown; + uint32_t sbmr2 = readl(src_base + IMX6_SRC_SBMR2) >> 24; + uint32_t cfg1 = readl(src_base + IMX6_SRC_SBMR1) & 0xff; + uint32_t boot_cfg_4_2_0; + int boot_mode; + + boot_mode = (sbmr2 >> 24) & 0x3; + + switch (boot_mode) { + case 0: /* Fuses, fall through */ + case 2: /* internal boot */ + goto internal_boot; + case 1: /* Serial Downloader */ + src = bootsource_serial; + break; + case 3: /* reserved */ + break; + }; + + imx_set_bootsource(src); + + return 0; + +internal_boot: + + switch (cfg1 >> 4) { + case 2: + src = bootsource_hd; + break; + case 3: + boot_cfg_4_2_0 = (cfg1 >> 16) & 0x7; + + if (boot_cfg_4_2_0 > 4) + src = bootsource_i2c; + else + src = bootsource_spi; + break; + case 4: + case 5: + case 6: + case 7: + src = bootsource_mmc; + break; + default: + break; + } + + if (cfg1 & (1 << 7)) + src = bootsource_nand; + + imx_set_bootsource(src); + + return 0; +} diff --git a/arch/arm/mach-imx/clk-imx5.c b/arch/arm/mach-imx/clk-imx5.c index 050842d103..d7548aea01 100644 --- a/arch/arm/mach-imx/clk-imx5.c +++ b/arch/arm/mach-imx/clk-imx5.c @@ -219,6 +219,7 @@ int __init mx51_clocks_init(void __iomem *regs, unsigned long rate_ckil, unsigne clkdev_add_physbase(clks[esdhc_b_podf], MX51_MMC_SDHC2_BASE_ADDR, NULL); clkdev_add_physbase(clks[esdhc_c_s], MX51_MMC_SDHC3_BASE_ADDR, NULL); clkdev_add_physbase(clks[esdhc_d_s], MX51_MMC_SDHC4_BASE_ADDR, NULL); + clkdev_add_physbase(clks[ipg], MX51_ATA_BASE_ADDR, NULL); return 0; } @@ -280,6 +281,7 @@ int __init mx53_clocks_init(void __iomem *regs, unsigned long rate_ckil, unsigne clkdev_add_physbase(clks[esdhc_c_s], MX53_ESDHC2_BASE_ADDR, NULL); clkdev_add_physbase(clks[esdhc_b_podf], MX53_ESDHC3_BASE_ADDR, NULL); clkdev_add_physbase(clks[esdhc_d_s], MX53_ESDHC4_BASE_ADDR, NULL); + clkdev_add_physbase(clks[ahb], MX53_SATA_BASE_ADDR, NULL); return 0; } diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c index a1da47a959..f78d3d2bcd 100644 --- a/arch/arm/mach-imx/clk-imx6.c +++ b/arch/arm/mach-imx/clk-imx6.c @@ -81,8 +81,9 @@ enum mx6q_clks { gpmi_bch_apb, gpmi_bch, gpmi_io, gpmi_apb, sata, sdma, spba, ssi1, ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3, usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg, - pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg, + pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg, ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, + sata_ref, pcie_ref, sata_ref_100m, pcie_ref_125m, enet_ref, clk_max }; @@ -169,6 +170,14 @@ static const char *cko1_sels[] = { "pll4_audio", }; +static struct clk_div_table clk_enet_ref_table[] = { + { .val = 0, .div = 20, }, + { .val = 1, .div = 10, }, + { .val = 2, .div = 5, }, + { .val = 3, .div = 4, }, + { }, +}; + static int imx6_ccm_probe(struct device_d *dev) { void __iomem *base, *anatop_base, *ccm_base; @@ -186,15 +195,22 @@ static int imx6_ccm_probe(struct device_d *dev) clks[ckih] = clk_fixed("ckih", ckih_rate); clks[osc] = clk_fixed("osc", osc_rate); - /* type name parent_name base gate_mask div_mask */ - clks[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x2000, 0x7f); - clks[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x2000, 0x1); - clks[pll3_usb_otg] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x2000, 0x3); - clks[pll4_audio] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x2000, 0x7f); - clks[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x2000, 0x7f); - clks[pll6_mlb] = imx_clk_pllv3(IMX_PLLV3_MLB, "pll6_mlb", "osc", base + 0xd0, 0x2000, 0x0); - clks[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x2000, 0x3); - clks[pll8_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll8_enet", "osc", base + 0xe0, 0x182000, 0x3); + /* type name parent_name base div_mask */ + clks[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); + clks[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1); + clks[pll3_usb_otg] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3); + clks[pll4_audio] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f); + clks[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f); + clks[pll8_mlb] = imx_clk_pllv3(IMX_PLLV3_MLB, "pll8_mlb", "osc", base + 0xd0, 0x0); + clks[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3); + clks[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3); + + clks[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5); + clks[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4); + clks[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20); + clks[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19); + + clks[enet_ref] = clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table); /* name parent_name reg idx */ clks[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0); @@ -281,6 +297,7 @@ static int imx6_ccm_probe(struct device_d *dev) clkdev_add_physbase(clks[ipg_per], MX6_I2C1_BASE_ADDR, NULL); clkdev_add_physbase(clks[ipg_per], MX6_I2C2_BASE_ADDR, NULL); clkdev_add_physbase(clks[ipg_per], MX6_I2C3_BASE_ADDR, NULL); + clkdev_add_physbase(clks[ahb], MX6_SATA_BASE_ADDR, NULL); writel(0xffffffff, ccm_base + CCGR0); writel(0xffffffff, ccm_base + CCGR1); @@ -291,6 +308,9 @@ static int imx6_ccm_probe(struct device_d *dev) writel(0xffffffff, ccm_base + CCGR6); writel(0xffffffff, ccm_base + CCGR7); + clk_enable(clks[pll6_enet]); + clk_enable(clks[sata_ref_100m]); + return 0; } diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index e337e87f13..e38dcdfdaa 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -35,7 +35,6 @@ struct clk_pllv3 { struct clk clk; void __iomem *base; bool powerup_set; - u32 gate_mask; u32 div_mask; const char *parent; }; @@ -46,7 +45,7 @@ static int clk_pllv3_enable(struct clk *clk) { struct clk_pllv3 *pll = to_clk_pllv3(clk); u32 val; - int ret; + int timeout = 10000; val = readl(pll->base); val &= ~BM_PLL_BYPASS; @@ -57,12 +56,16 @@ static int clk_pllv3_enable(struct clk *clk) writel(val, pll->base); /* Wait for PLL to lock */ - ret = wait_on_timeout(10 * MSECOND, !(readl(pll->base) & BM_PLL_LOCK)); - if (ret) - return ret; + while (timeout--) { + if (readl(pll->base) & BM_PLL_LOCK) + break; + } + + if (!timeout) + return -ETIMEDOUT; val = readl(pll->base); - val |= pll->gate_mask; + val |= BM_PLL_ENABLE; writel(val, pll->base); return 0; @@ -74,7 +77,7 @@ static void clk_pllv3_disable(struct clk *clk) u32 val; val = readl(pll->base); - val &= ~pll->gate_mask; + val &= ~BM_PLL_ENABLE; writel(val, pll->base); val |= BM_PLL_BYPASS; @@ -261,74 +264,13 @@ static const struct clk_ops clk_pllv3_av_ops = { static unsigned long clk_pllv3_enet_recalc_rate(struct clk *clk, unsigned long parent_rate) { - struct clk_pllv3 *pll = to_clk_pllv3(clk); - u32 div = readl(pll->base) & pll->div_mask; - - switch (div) { - case 0: - return 25000000; - case 1: - return 50000000; - case 2: - return 100000000; - case 3: - return 125000000; - } - - return 0; -} - -static long clk_pllv3_enet_round_rate(struct clk *clk, unsigned long rate, - unsigned long *prate) -{ - if (rate >= 125000000) - rate = 125000000; - else if (rate >= 100000000) - rate = 100000000; - else if (rate >= 50000000) - rate = 50000000; - else - rate = 25000000; - return rate; -} - -static int clk_pllv3_enet_set_rate(struct clk *clk, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_pllv3 *pll = to_clk_pllv3(clk); - u32 val, div; - - switch (rate) { - case 25000000: - div = 0; - break; - case 50000000: - div = 1; - break; - case 100000000: - div = 2; - break; - case 125000000: - div = 3; - break; - default: - return -EINVAL; - } - - val = readl(pll->base); - val &= ~pll->div_mask; - val |= div; - writel(val, pll->base); - - return 0; + return 500000000; } static const struct clk_ops clk_pllv3_enet_ops = { .enable = clk_pllv3_enable, .disable = clk_pllv3_disable, .recalc_rate = clk_pllv3_enet_recalc_rate, - .round_rate = clk_pllv3_enet_round_rate, - .set_rate = clk_pllv3_enet_set_rate, }; static const struct clk_ops clk_pllv3_mlb_ops = { @@ -338,7 +280,7 @@ static const struct clk_ops clk_pllv3_mlb_ops = { struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, const char *parent, void __iomem *base, - u32 gate_mask, u32 div_mask) + u32 div_mask) { struct clk_pllv3 *pll; const struct clk_ops *ops; @@ -367,7 +309,6 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, ops = &clk_pllv3_ops; } pll->base = base; - pll->gate_mask = gate_mask; pll->div_mask = div_mask; pll->parent = parent; pll->clk.ops = ops; diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 0f30082e1f..4a7298d846 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -42,7 +42,7 @@ enum imx_pllv3_type { struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, const char *parent, void __iomem *base, - u32 gate_mask, u32 div_mask); + u32 div_mask); struct clk *imx_clk_pfd(const char *name, const char *parent, void __iomem *reg, u8 idx); diff --git a/arch/arm/mach-imx/devices.c b/arch/arm/mach-imx/devices.c index 4ee4e6cc8d..d82fbf7e6b 100644 --- a/arch/arm/mach-imx/devices.c +++ b/arch/arm/mach-imx/devices.c @@ -67,3 +67,8 @@ struct device_d *imx_add_kpp(void *base, struct matrix_keymap_data *pdata) { return imx_add_device("imx-kpp", -1, base, 0x1000, pdata); } + +struct device_d *imx_add_pata(void *base) +{ + return imx_add_device("imx-pata", -1, base, 0x1000, NULL); +} diff --git a/arch/arm/mach-imx/esdctl-v4.c b/arch/arm/mach-imx/esdctl-v4.c new file mode 100644 index 0000000000..6441ac9ce0 --- /dev/null +++ b/arch/arm/mach-imx/esdctl-v4.c @@ -0,0 +1,710 @@ +/* + * esdctl-v4.c - i.MX sdram controller functions for i.MX53 + * + * 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. + */ + +#include <common.h> +#include <io.h> +#include <mach/esdctl-v4.h> +#include <mach/imx53-regs.h> +#include <asm/system.h> + +void imx_esdctlv4_do_write_leveling(void) +{ + u32 val; + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + + /* switch RAMs to write-leveling mode */ + + val = ESDCTL_V4_DDR3_MR1_ODIC_RZQ7 | ESDCTL_V4_DDR3_MR1_RTTN_DIS | + ESDCTL_V4_DDR3_MR1_AL_DISABLE | ESDCTL_V4_DDR3_MR1_WL | + ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_LMR | + ESDCTL_V4_ESDSCR_CMD_CS0 | ESDCTL_V4_ESDSCR_WL_EN | + ESDCTL_V4_DDR3_REG_MR1; + writel(val, base + ESDCTL_V4_ESDSCR); + + val = ESDCTL_V4_DDR3_MR1_ODIC_RZQ7 | ESDCTL_V4_DDR3_MR1_RTTN_DIS | + ESDCTL_V4_DDR3_MR1_AL_DISABLE | ESDCTL_V4_DDR3_MR1_WL | + ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_LMR | + ESDCTL_V4_ESDSCR_CMD_CS1 | ESDCTL_V4_ESDSCR_WL_EN | + ESDCTL_V4_DDR3_REG_MR1; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* start write leveling */ + writel(ESDCTL_V4_WLGCR_HW_WL_EN, base + ESDCTL_V4_WLGCR); + + do { + val = readl(base + ESDCTL_V4_WLGCR); + } while (val & ESDCTL_V4_WLGCR_HW_WL_EN); + + val &= ESDCTL_V4_WLGCR_WL_HW_ERR3 | ESDCTL_V4_WLGCR_WL_HW_ERR2 | + ESDCTL_V4_WLGCR_WL_HW_ERR1 | ESDCTL_V4_WLGCR_WL_HW_ERR0; + + if (val) + hang(); + + /* + * manual still talks about HW_WLx_CYC fields that + * must be updated from HW_WLx_RES field by SW, but none + * of these fields seem to exist. Closest equivalents + * are WL_CYC_DELx-fields but no RES-fields can be found. + */ + + /* configure RAMs back to normal operation */ + val = ESDCTL_V4_DDR3_MR1_ODIC_RZQ7 | ESDCTL_V4_DDR3_MR1_RTTN_RZQ2 | + ESDCTL_V4_DDR3_MR1_AL_DISABLE | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_LMR | ESDCTL_V4_ESDSCR_CMD_CS0 | + ESDCTL_V4_DDR3_REG_MR1; + writel(val, base + ESDCTL_V4_ESDSCR); + + val = ESDCTL_V4_DDR3_MR1_ODIC_RZQ7 | ESDCTL_V4_DDR3_MR1_RTTN_RZQ2 | + ESDCTL_V4_DDR3_MR1_AL_DISABLE | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_LMR | ESDCTL_V4_ESDSCR_CMD_CS1 | + ESDCTL_V4_DDR3_REG_MR1; + writel(val, base + ESDCTL_V4_ESDSCR); +} + +void imx_esdctlv4_do_dqs_gating(void) +{ + u32 val; + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + + /* configure ESDCTL comparator to use MPR pattern */ + writel(ESDCTL_V4_PDCMPR2_MPR_FULL_CMP | ESDCTL_V4_PDCMPR2_MPR_CMP, + base + ESDCTL_V4_PDCMPR2); + + /* pre-charge all RAM banks */ + writel(ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_CS0 | + ESDCTL_V4_ESDSCR_CMD_PRE_ALL, base + ESDCTL_V4_ESDSCR); + writel(ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_CS1 | + ESDCTL_V4_ESDSCR_CMD_PRE_ALL, base + ESDCTL_V4_ESDSCR); + + /* configure RAMs to generate MPR pattern */ + writel(ESDCTL_V4_DDR3_MR3_MPR_ENABLE | ESDCTL_V4_DDR3_MR3_MPR_PATTERN | + ESDCTL_V4_ESDSCR_CMD_CS0 | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_LMR | ESDCTL_V4_DDR3_REG_MR3, + base + ESDCTL_V4_ESDSCR); + writel(ESDCTL_V4_DDR3_MR3_MPR_ENABLE | ESDCTL_V4_DDR3_MR3_MPR_PATTERN | + ESDCTL_V4_ESDSCR_CMD_CS1 | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_LMR | ESDCTL_V4_DDR3_REG_MR3, + base + ESDCTL_V4_ESDSCR); + + /* start HW DQS gating */ + writel(ESDCTL_V4_ESDDGCTRL0_HW_DG_EN, base + ESDCTL_V4_DGCTRL0); + + do { + val = readl(base + ESDCTL_V4_DGCTRL0); + } while (val & ESDCTL_V4_ESDDGCTRL0_HW_DG_EN); + + if (val & ESDCTL_V4_ESDDGCTRL0_HW_DG_ERR) + hang(); + + /* configure RAMs back to normal operation */ + val = ESDCTL_V4_DDR3_MR3_MPR_DISABLE | ESDCTL_V4_ESDSCR_CMD_CS0 | + ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_LMR | + ESDCTL_V4_DDR3_REG_MR3; + writel(val, base + ESDCTL_V4_ESDSCR); + + val = ESDCTL_V4_DDR3_MR3_MPR_DISABLE | ESDCTL_V4_ESDSCR_CMD_CS1 | + ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_LMR | + ESDCTL_V4_DDR3_REG_MR3; + writel(val, base + ESDCTL_V4_ESDSCR); +} + +void imx_esdctlv4_do_zq_calibration(void) +{ + u32 val; + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + + /* + * configure ZQ parameters + * Note: TZQ_CS is only required to be 64cy by Jedec and RAM + * manufacturers and i.MX53TO1 provides a 64cy setting, but + * TO2 according to official documentation not... + */ + val = ESDCTL_V4_ESDZQHWC_ZQ_PARA_EN | + (ESDCTL_V4_ESDZQHWC_128CYC << ESDCTL_V4_ESDZQHWC_TZQ_CS_SHIFT) | + (ESDCTL_V4_ESDZQHWC_256CYC << ESDCTL_V4_ESDZQHWC_TZQ_OPER_SHIFT) | + (ESDCTL_V4_ESDZQHWC_512CYC << ESDCTL_V4_ESDZQHWC_TZQ_INIT_SHIFT) | + (0 << ESDCTL_V4_ESDZQHWC_ZQ_HW_PD_RES_SHIFT) | + (0 << ESDCTL_V4_ESDZQHWC_ZQ_HW_PU_RES_SHIFT) | + (0 << ESDCTL_V4_ESDZQHWC_ZQ_HW_PER_SHIFT) | + ESDCTL_V4_ESDZQHWC_ZQ_MODE_BOTH_PER | + ESDCTL_V4_ESDZQHWC_ZQ_HW_FOR; + + /* force ZQ calibration */ + writel(val, base + ESDCTL_V4_ZQHWCTRL); + + while (readl(base + ESDCTL_V4_ZQHWCTRL) & ESDCTL_V4_ESDZQHWC_ZQ_HW_FOR); +} + +/* + * start-up a DDR3 SDRAM chip + */ +void imx_esdctlv4_start_ddr3_sdram(int cs) +{ + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + u32 val; + u32 val_cs1; + + if (cs) + val_cs1 = ESDCTL_V4_ESDSCR_CMD_CS1; + else + val_cs1 = ESDCTL_V4_ESDSCR_CMD_CS0; + + /* initialize MR2 */ + val = ESDCTL_V4_DDR3_MR2_RTTWR_OFF | ESDCTL_V4_DDR3_MR2_SRT_NORMAL | + ESDCTL_V4_DDR3_MR2_CWL_5 | ESDCTL_V4_DDR3_MR2_PASR_1_1 | + ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_LMR | + ESDCTL_V4_DDR3_REG_MR2 | val_cs1; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* initialize MR3 */ + val = ESDCTL_V4_DDR3_MR3_MPR_DISABLE | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_LMR | ESDCTL_V4_DDR3_REG_MR3 | val_cs1; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* initialize MR1 */ + val = ESDCTL_V4_DDR3_MR1_ODIC_RZQ7 | ESDCTL_V4_DDR3_MR1_RTTN_RZQ2 | + ESDCTL_V4_DDR3_MR1_AL_DISABLE | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_LMR | ESDCTL_V4_DDR3_REG_MR1 | val_cs1; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* initialize MR0 */ + val = ESDCTL_V4_DDR3_MR0_PPD_SLOW | ESDCTL_V4_DDR3_MR0_WR_6 | + ESDCTL_V4_DDR3_MR0_CL_6 | ESDCTL_V4_DDR3_MR0_BL_FIXED8 | + ESDCTL_V4_DDR3_MR0_RBT_NIBBLE | ESDCTL_V4_DDR3_DLL_RESET | + ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_LMR | + ESDCTL_V4_DDR3_REG_MR0 | val_cs1; + + if (cs) + val = ESDCTL_V4_ESDSCR_DLL_RST1; + else + val = ESDCTL_V4_ESDSCR_DLL_RST0; + + writel(val, base + ESDCTL_V4_ESDSCR); + + /* perform ZQ calibration */ + val = 0x04000000 | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_ZQCALIB_OLD; + val |= val_cs1; + writel(val, base + ESDCTL_V4_ESDSCR); +} + +void imx_esdctlv4_do_read_delay_line_calibration(void) +{ + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + u32 val; + + /* configure ESDCTL comparator to use MPR pattern */ + val = ESDCTL_V4_PDCMPR2_MPR_FULL_CMP | ESDCTL_V4_PDCMPR2_MPR_CMP; + writel(val, base + ESDCTL_V4_PDCMPR2); + + /* pre-charge all RAM banks */ + val = ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_CS0 | + ESDCTL_V4_ESDSCR_CMD_PRE_ALL; + writel(val, base + ESDCTL_V4_ESDSCR); + + val = ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_CS1 | + ESDCTL_V4_ESDSCR_CMD_PRE_ALL; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* configure RAMs to generate MPR pattern */ + val = ESDCTL_V4_DDR3_MR3_MPR_ENABLE | ESDCTL_V4_DDR3_MR3_MPR_PATTERN | + ESDCTL_V4_ESDSCR_CMD_CS0 | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_LMR | ESDCTL_V4_DDR3_REG_MR3; + writel(val, base + ESDCTL_V4_ESDSCR); + + val = ESDCTL_V4_DDR3_MR3_MPR_ENABLE | ESDCTL_V4_DDR3_MR3_MPR_PATTERN | + ESDCTL_V4_ESDSCR_CMD_CS1 | ESDCTL_V4_ESDSCR_CON_REQ | + ESDCTL_V4_ESDSCR_CMD_LMR | ESDCTL_V4_DDR3_REG_MR3; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* start read delay-line calibration */ + writel(ESDCTL_V4_RDDLHWCTL_HW_RDL_EN, base + ESDCTL_V4_RDDLHWCTL); + + do { + val = readl(base + ESDCTL_V4_RDDLHWCTL); + } while (val & ESDCTL_V4_RDDLHWCTL_HW_RDL_EN); + + val &= ESDCTL_V4_RDDLHWCTL_HW_RDL_ERR3 | + ESDCTL_V4_RDDLHWCTL_HW_RDL_ERR2 | + ESDCTL_V4_RDDLHWCTL_HW_RDL_ERR1 | + ESDCTL_V4_RDDLHWCTL_HW_RDL_ERR0; + + if (val) + hang(); + + /* configure RAMs back to normal operation */ + val = ESDCTL_V4_DDR3_MR3_MPR_DISABLE | ESDCTL_V4_ESDSCR_CMD_CS0 | + ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_LMR | + ESDCTL_V4_DDR3_REG_MR3; + writel(val, base + ESDCTL_V4_ESDSCR); + + val = ESDCTL_V4_DDR3_MR3_MPR_DISABLE | ESDCTL_V4_ESDSCR_CMD_CS1 | + ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_LMR | + ESDCTL_V4_DDR3_REG_MR3; + writel(val, base + ESDCTL_V4_ESDSCR); +} + +void imx_esdctlv4_do_write_delay_line_calibration(void) +{ + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + void __iomem *adr; + u32 val; + + /* + * configure ESCTL to normal operation so we can + * write the compare values + */ + writel(ESDCTL_V4_ESDSCR_CMD_NOP, base + ESDCTL_V4_ESDSCR); + + /* write test-pattern to RAM */ + + /* ESCTL uses this address for calibration */ + adr = (void *)MX53_CSD0_BASE_ADDR + 0x10000000; + writel(0, adr + 0x00); + writel(0, adr + 0x0c); + writel(0, adr + 0x10); + writel(0, adr + 0x1c); + writel(0, adr + 0x20); + writel(0, adr + 0x2c); + writel(0, adr + 0x30); + writel(0, adr + 0x4c); + writel(0xffffffff, adr + 0x04); + writel(0xffffffff, adr + 0x08); + writel(0xffffffff, adr + 0x14); + writel(0xffffffff, adr + 0x18); + writel(0xffffffff, adr + 0x24); + writel(0xffffffff, adr + 0x28); + writel(0xffffffff, adr + 0x34); + writel(0xffffffff, adr + 0x48); + + /* pre-charge all RAM banks */ + val = ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_CS0 | + ESDCTL_V4_ESDSCR_CMD_PRE_ALL; + writel(val, base + ESDCTL_V4_ESDSCR); + + val = ESDCTL_V4_ESDSCR_CON_REQ | ESDCTL_V4_ESDSCR_CMD_CS1 | + ESDCTL_V4_ESDSCR_CMD_PRE_ALL; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* write test-pattern to ESCTL */ + writel(0x00ffff00, base + ESDCTL_V4_PDCMPR1); + writel(0, base + ESDCTL_V4_PDCMPR2); + + /* start write delay-line calibration */ + writel(ESDCTL_V4_WRDLHWCTL_HW_WDL_EN, base + ESDCTL_V4_WRDLHWCTL); + + do { + val = readl(base + ESDCTL_V4_WRDLHWCTL); + } while (val & ESDCTL_V4_WRDLHWCTL_HW_WDL_EN); + + val &= ESDCTL_V4_WRDLHWCTL_HW_WDL_ERR3 | + ESDCTL_V4_WRDLHWCTL_HW_WDL_ERR2 | + ESDCTL_V4_WRDLHWCTL_HW_WDL_ERR1 | + ESDCTL_V4_WRDLHWCTL_HW_WDL_ERR0; + + if (val) + hang(); +} + +#define SDRAM_COMPARE_CONST1 0x12345678 +#define SDRAM_COMPARE_CONST2 0xAAAAAAAA + +/* + * write magic values to RAM for testing purposes + */ +static void imx_esdctlv4_write_magic_values(void *adr) +{ + /* + * Freescale asks for first access to be a write to properly + * initialize DQS pin-state and keepers + */ + writel(SDRAM_COMPARE_CONST1, adr); + + /* + * write two magic constants to RAM, to test for bus-size and + * row-/column-configuraion + */ + writel(SDRAM_COMPARE_CONST1, adr); + writel(SDRAM_COMPARE_CONST2, adr + 4); + dsb(); +} + +/* + * check if given DRAM addresses match expected values for row/col configuration + */ +static u32 check_ram_address_line(void *adr, u32 compare, u32 mask) +{ + u32 val; + + val = readl(adr); /* load data from RAM-address to check */ + val &= mask; /* mask data for our bus-size */ + + if (compare == val) /* compare read data with expected value */ + return 1; /* if data is identical, update ESDCTL configuration */ + else + return 0; +} + +/* + * determine RAM chip-density and configure tRFC and tXS accordingly + */ +void imx_esdctlv4_set_tRFC_timing(void) +{ + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + u32 val, trfc, r2, esdcfg; + + /* determine chip-density */ + val = readl(base + ESDCTL_V4_ESDMISC); + if ((val & ESDCTL_V4_ESDMISC_BANKS_MASK) == ESDCTL_V4_ESDMISC_BANKS_4) + r2 = 2; + else + r2 = 3; + + val = readl(base + ESDCTL_V4_ESDCTL0); + if ((val & ESDCTL_V4_ESDCTLx_DSIZ_MASK) == ESDCTL_V4_ESDCTLx_DSIZ_32B) + r2 += 1; + + switch (val & ESDCTL_V4_ESDCTLx_ROW_MASK) { + case ESDCTL_V4_ESDCTLx_ROW_11: r2 += 1; break; + case ESDCTL_V4_ESDCTLx_ROW_12: r2 += 2; break; + case ESDCTL_V4_ESDCTLx_ROW_13: r2 += 3; break; + case ESDCTL_V4_ESDCTLx_ROW_14: r2 += 4; break; + case ESDCTL_V4_ESDCTLx_ROW_15: r2 += 5; break; + case ESDCTL_V4_ESDCTLx_ROW_16: r2 += 6; break; + } + + switch (val & ESDCTL_V4_ESDCTLx_COL_MASK) { + case ESDCTL_V4_ESDCTLx_COL_8: r2 += 8; break; + case ESDCTL_V4_ESDCTLx_COL_9: r2 += 9; break; + case ESDCTL_V4_ESDCTLx_COL_10: r2 += 10; break; + case ESDCTL_V4_ESDCTLx_COL_11: r2 += 11; break; + case ESDCTL_V4_ESDCTLx_COL_12: r2 += 12; break; + } + + /* save current tRFC timing */ + esdcfg = readl(base + ESDCTL_V4_ESDCFG0); + + trfc = (esdcfg & ESDCTL_V4_ESDCFG0_tRFC_MASK) >> ESDCTL_V4_ESDCFG0_tRFC_SHIFT; + + /* clear tRFC and tXS timings */ + esdcfg &= ~(ESDCTL_V4_ESDCFG0_tRFC_MASK | ESDCTL_V4_ESDCFG0_tXS_MASK); + + /* + * determine tRFC depending on density + * (the timings and density-associations are taken + * from JEDEC JESD79-3E DDR3-RAM specification) + */ + if (r2 >= 16) + trfc = 36 - 1; + if (r2 >= 17) + trfc = 44 - 1; + if (r2 >= 18) + trfc = 64 - 1; + if (r2 >= 19) + trfc = 120 - 1; + if (r2 >= 20) + trfc = 140 - 1; + + /* calculate new tRFC and tXS timings */ + esdcfg |= (trfc << ESDCTL_V4_ESDCFG0_tRFC_SHIFT) | + (trfc + 4) << ESDCTL_V4_ESDCFG0_tXS_SHIFT; + + writel(esdcfg, base + ESDCTL_V4_ESDCFG0); +} + +/* + * disable chip-selects that are not equipped + */ +void imx_esdctlv4_detect_sdrams(void) +{ + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + u32 esdctl0; + + esdctl0 = readl(base + ESDCTL_V4_ESDCTL0); + + writel(MX53_CSD0_BASE_ADDR, MX53_CSD0_BASE_ADDR); + writel(MX53_CSD1_BASE_ADDR, MX53_CSD1_BASE_ADDR); + + if (readl(MX53_CSD0_BASE_ADDR) != MX53_CSD0_BASE_ADDR) + esdctl0 &= ~ESDCTL_V4_ESDCTLx_SDE0; + if (readl(MX53_CSD1_BASE_ADDR) != MX53_CSD1_BASE_ADDR) + esdctl0 &= ~ESDCTL_V4_ESDCTLx_SDE1; + + writel(esdctl0, base + ESDCTL_V4_ESDCTL0); +} + +void imx_esdctlv4_init(void) +{ + void __iomem *base = (void *)MX53_ESDCTL_BASE_ADDR; + u32 val, r1, esdctl0, mask, rows, cols; + + /* + * assume worst-case here: 4Gb chips. this will be optimized + * further down, when we can determine the actual chip density + * in imx_esdctlv4_set_tRFC_timing() + */ + val = (((140 - 1) << ESDCTL_V4_ESDCFG0_tRFC_SHIFT) | + ((144 - 1) << ESDCTL_V4_ESDCFG0_tXS_SHIFT) | + ((3 - 1) << ESDCTL_V4_ESDCFG0_tXP_SHIFT) | + ((10 - 1) << ESDCTL_V4_ESDCFG0_tXPDLL_SHIFT) | + ((20 - 1) << ESDCTL_V4_ESDCFG0_tFAW_SHIFT) | + ((6 - 3) << ESDCTL_V4_ESDCFG0_tCL_SHIFT)); + writel(val, base + ESDCTL_V4_ESDCFG0); + + val = (((6 - 1) << ESDCTL_V4_ESDCFG1_tRCD_SHIFT) | + ((6 - 1) << ESDCTL_V4_ESDCFG1_tRP_SHIFT) | + ((21 - 1) << ESDCTL_V4_ESDCFG1_tRC_SHIFT) | + ((15 - 1) << ESDCTL_V4_ESDCFG1_tRAS_SHIFT) | + (1 << ESDCTL_V4_ESDCFG1_tRPA_SHIFT) | + ((6 - 1) << ESDCTL_V4_ESDCFG1_tWR_SHIFT) | + ((4 - 1) << ESDCTL_V4_ESDCFG1_tMRD_SHIFT) | + ((5 - 2) << ESDCTL_V4_ESDCFG1_tCWL_SHIFT)); + writel(val, base + ESDCTL_V4_ESDCFG1); + + val = (((512 - 1) << ESDCTL_V4_ESDCFG2_tDLLK_SHIFT) | + ((4 - 1) << ESDCTL_V4_ESDCFG2_tRTP_SHIFT) | + ((4 - 1) << ESDCTL_V4_ESDCFG2_tWTR_SHIFT) | + ((4 - 1) << ESDCTL_V4_ESDCFG2_tRRD_SHIFT)); + writel(val, base + ESDCTL_V4_ESDCFG2); + + /* + * we don't touch the ESDRWD register as documentation claims + * the power-on defaults are minimum required values and we don't + * want to interfere with changes of these in new chip or + * BootROM revisions. + */ + + val = (((3 - 1) << ESDCTL_V4_ESDOTC_tAOFPD_SHIFT) | + ((3 - 1) << ESDCTL_V4_ESDOTC_tAONPD_SHIFT) | + ((4 - 1) << ESDCTL_V4_ESDOTC_tANPD_SHIFT) | + ((4 - 1) << ESDCTL_V4_ESDOTC_tAXPD_SHIFT) | + (3 << ESDCTL_V4_ESDOTC_tODTLon_SHIFT) | + (3 << ESDCTL_V4_ESDOTC_tODT_idle_off_SHIFT)); + writel(val, base + ESDCTL_V4_ESDOTC); + + /* currently we only support DDR3 RAM, which always has 8 banks */ + val = ESDCTL_V4_ESDMISC_WALAT_0 | ESDCTL_V4_ESDMISC_RALAT_2 | + ESDCTL_V4_ESDMISC_MIF3_MODE_EFAM | + ESDCTL_V4_ESDMISC_DDR_DDR3 | + ESDCTL_V4_ESDMISC_BANKS_8; + writel(val, base + ESDCTL_V4_ESDMISC); + + val = (((144 - 1) << ESDCTL_V4_ESDOR_tXPR_SHIFT) | + ((13 + 1) << ESDCTL_V4_ESDOR_SDE_to_RST_SHIFT) | + ((32 + 1) << ESDCTL_V4_ESDOR_RST_to_CKE_SHIFT)); + writel(val, base + ESDCTL_V4_ESDOR); + + /* + * we assume maximum address line configuration here (32b, 16rows, 12cols, + * both chips) once the RAM is initialized, we determine actual configuration + */ + val = ESDCTL_V4_ESDCTLx_SDE0 | ESDCTL_V4_ESDCTLx_SDE1 | + ESDCTL_V4_ESDCTLx_ROW_16 | ESDCTL_V4_ESDCTLx_COL_8 | + ESDCTL_V4_ESDCTLx_BL_8_8 | ESDCTL_V4_ESDCTLx_DSIZ_32B; + writel(val, base + ESDCTL_V4_ESDCTL0); + + imx_esdctlv4_start_ddr3_sdram(0); + imx_esdctlv4_start_ddr3_sdram(1); + + val = (ESDCTL_V4_ESDPDC_PRCT_DISABLE << ESDCTL_V4_ESDPDC_PRCT1_SHIFT) | + (ESDCTL_V4_ESDPDC_PRCT_DISABLE << ESDCTL_V4_ESDPDC_PRCT0_SHIFT) | + ((3 - 1) << ESDCTL_V4_ESDPDC_tCKE_SHIFT) | + (ESDCTL_V4_ESDPDC_PWDT_DISABLE << ESDCTL_V4_ESDPDC_PWDT1_SHIFT) | + (ESDCTL_V4_ESDPDC_PWDT_DISABLE << ESDCTL_V4_ESDPDC_PWDT0_SHIFT) | + (5 << ESDCTL_V4_ESDPDC_tCKSRX_SHIFT) | + (5 << ESDCTL_V4_ESDPDC_tCKSRE_SHIFT); + writel(val, base + ESDCTL_V4_ESDPDC); + + /* configure ODT */ + val = (ESDCTL_V4_ESDODTC_RTT_120 << ESDCTL_V4_ESDODTC_ODT3_INT_RES_SHIFT) | + (ESDCTL_V4_ESDODTC_RTT_120 << ESDCTL_V4_ESDODTC_ODT2_INT_RES_SHIFT) | + (ESDCTL_V4_ESDODTC_RTT_120 << ESDCTL_V4_ESDODTC_ODT1_INT_RES_SHIFT) | + (ESDCTL_V4_ESDODTC_RTT_120 << ESDCTL_V4_ESDODTC_ODT0_INT_RES_SHIFT) | + ESDCTL_V4_ESDODTC_ODT_RD_PAS_EN | + ESDCTL_V4_ESDODTC_ODT_WR_ACT_EN | + ESDCTL_V4_ESDODTC_ODT_WR_PAS_EN; + writel(val, base + ESDCTL_V4_ODTCTRL); + + /* + * ensure refresh and ZQ calibration are turned off as + * nothing may interfere with the first few calibrations + */ + writel(ESDCTL_V4_ESDREF_REF_SEL_MASK, base + ESDCTL_V4_ESDREF); + + writel(ESDCTL_V4_ESDZQHWC_ZQ_MODE_NO_CAL, base + ESDCTL_V4_ZQHWCTRL); + + /* + * ensure that read/write delays are configured to + * (working) 1/4 cycle default delay, proper delays + * will be calibrated below. + */ + writel(0x30303030, base + ESDCTL_V4_RDDLCTL); + writel(0x40404040, base + ESDCTL_V4_WRDLCTL); + + /* DQS Gating */ + imx_esdctlv4_do_dqs_gating(); + + /* Write Leveling */ + imx_esdctlv4_do_write_leveling(); + + /* + * ZQ calibration (this will also enable regular + * automatic ZQ calibration again) + */ + imx_esdctlv4_do_zq_calibration(); + + /* configure and enable refresh */ + val = (0 << ESDCTL_V4_ESDREF_REF_CNT_SHIFT) | + ESDCTL_V4_ESDREF_REF_SEL_64K | + ((2 - 1) << ESDCTL_V4_ESDREF_REFR_SHIFT); + writel(val, base + ESDCTL_V4_ESDREF); + + + /* Now do proper Delay Line Calibration */ + imx_esdctlv4_do_read_delay_line_calibration(); + imx_esdctlv4_do_write_delay_line_calibration(); + + /* enable regular operation of ESDCTL */ + writel(ESDCTL_V4_ESDSCR_CMD_NOP, base + ESDCTL_V4_ESDSCR); + + dsb(); + + /* + * detect RAM configuration (Note: both CSDx must be + * equipped with identical RAMs, so we only need to detect + * the configuration of CSD0 and anything on CSD1) + */ + esdctl0 = readl(base + ESDCTL_V4_ESDCTL0); + + imx_esdctlv4_write_magic_values((void *)MX53_CSD0_BASE_ADDR); + + /* check for bus-configuration first */ + esdctl0 &= ~ESDCTL_V4_ESDCTLx_DSIZ_MASK; + + /* assume we're on a 32b bus */ + mask = 0xffffffff; + + /* data correct? */ + if (readl(MX53_CSD0_BASE_ADDR) == SDRAM_COMPARE_CONST1) { + esdctl0 |= ESDCTL_V4_ESDCTLx_DSIZ_32B; /* yep, indeed 32b bus */ + goto sdram_bussize_found; + } + + /* + * ok, last possibility is 16b bus on low data-lines, check that + * (i.MX25 also suports 16b on high data-lines, but i.MX53 doesn't) + */ + if (readl(MX53_CSD0_BASE_ADDR) << 16 == SDRAM_COMPARE_CONST1 << 16) { + esdctl0 |= ESDCTL_V4_ESDCTLx_DSIZ_16B_LOW; + mask >>= 16; + goto sdram_bussize_found; + } + + /* nope, no working SDRAM, leave. */ + hang(); + +sdram_bussize_found: + + /* Now determine actual row/column configuration of the RAMs */ + + /* mask unused bits from our compare constant */ + r1 = SDRAM_COMPARE_CONST1 & mask; + /* + * So far we asssumed that we have 16 rows, check for copies of our + * SDRAM_COMPARE_CONST1 due to missing row lines... + */ + + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 25), r1, mask)) + rows = ESDCTL_V4_ESDCTLx_ROW_15; + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 24), r1, mask)) + rows = ESDCTL_V4_ESDCTLx_ROW_14; + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 23), r1, mask)) + rows = ESDCTL_V4_ESDCTLx_ROW_13; + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 22), r1, mask)) + rows = ESDCTL_V4_ESDCTLx_ROW_12; + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 21), r1, mask)) + rows = ESDCTL_V4_ESDCTLx_ROW_11; + + esdctl0 &= ~ESDCTL_V4_ESDCTLx_ROW_MASK; + esdctl0 |= rows; + + /* + * To detect columns we have to switch from the (max rows, min cols) + * configuration we used so far to a (min rows, max cols) configuration + */ + + /* switch ESDCTL to configuration mode */ + val = ESDCTL_V4_ESDSCR_CMD_NOP | ESDCTL_V4_ESDSCR_CON_REQ; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* reconfigure row-/column-lines */ + val = readl(base + ESDCTL_V4_ESDCTL0); + val &= ~(ESDCTL_V4_ESDCTLx_ROW_MASK | ESDCTL_V4_ESDCTLx_COL_MASK); + val |= ESDCTL_V4_ESDCTLx_ROW_11 | ESDCTL_V4_ESDCTLx_COL_12; + writel(val, base + ESDCTL_V4_ESDCTL0); + + dsb(); + + /* switch ESDCTL back to normal operation */ + writel(ESDCTL_V4_ESDSCR_CMD_NOP, base + ESDCTL_V4_ESDSCR); + + /* + * not quite sure why, but the row-/col-reconfiguration destroys the + * contents of the RAM so we have to write our magic values back + * (maybe because refresh is suspended during that time) + */ + imx_esdctlv4_write_magic_values((void *)MX53_CSD0_BASE_ADDR); + + /* + * So far we asssumed that we have 12 columns, check for copies of our + * SDRAM_COMPARE_CONST1 due to missing column lines... + */ + + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 13), r1, mask)) + cols = ESDCTL_V4_ESDCTLx_COL_11; + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 12), r1, mask)) + cols = ESDCTL_V4_ESDCTLx_COL_10; + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 11), r1, mask)) + cols = ESDCTL_V4_ESDCTLx_COL_9; + if (check_ram_address_line((void *)MX53_CSD0_BASE_ADDR + (1 << 10), r1, mask)) + cols = ESDCTL_V4_ESDCTLx_COL_8; + + esdctl0 &= ~ESDCTL_V4_ESDCTLx_COL_MASK; + esdctl0 |= cols; + + /* setup proper row-/column-configuration */ + + /* switch ESDCTL to configuration mode */ + val = ESDCTL_V4_ESDSCR_CMD_NOP | ESDCTL_V4_ESDSCR_CON_REQ; + writel(val, base + ESDCTL_V4_ESDSCR); + + /* reconfigure row-/column-lines */ + writel(esdctl0, base + ESDCTL_V4_ESDCTL0); + + /* configure densitiy dependent timing parameters */ + imx_esdctlv4_set_tRFC_timing(); + + dsb(); + + /* switch ESDCTL back to normal operation */ + writel(ESDCTL_V4_ESDSCR_CMD_NOP, base + ESDCTL_V4_ESDSCR); + + /* see at which CSx we actually have working RAM */ + imx_esdctlv4_detect_sdrams(); +} diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c new file mode 100644 index 0000000000..a40399a0e7 --- /dev/null +++ b/arch/arm/mach-imx/esdctl.c @@ -0,0 +1,334 @@ +/* + * esdctl.c - i.MX sdram controller functions + * + * 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. + */ + +#include <common.h> +#include <io.h> +#include <sizes.h> +#include <init.h> +#include <asm/barebox-arm.h> +#include <asm/memory.h> +#include <mach/esdctl.h> +#include <mach/esdctl-v4.h> +#include <mach/imx1-regs.h> +#include <mach/imx21-regs.h> +#include <mach/imx25-regs.h> +#include <mach/imx27-regs.h> +#include <mach/imx31-regs.h> +#include <mach/imx35-regs.h> +#include <mach/imx51-regs.h> +#include <mach/imx53-regs.h> + +struct imx_esdctl_data { + unsigned long base0; + unsigned long base1; + void (*add_mem)(void *esdctlbase, struct imx_esdctl_data *); +}; + +/* + * v1 - found on i.MX1 + */ +static inline unsigned long imx_v1_sdram_size(void __iomem *esdctlbase, int num) +{ + void __iomem *esdctl = esdctlbase + (num ? 4 : 0); + u32 ctlval = readl(esdctl); + unsigned long size; + int rows, cols, width = 2, banks = 4; + + if (!(ctlval & ESDCTL0_SDE)) + /* SDRAM controller disabled, so no RAM here */ + return 0; + + rows = ((ctlval >> 24) & 0x3) + 11; + cols = ((ctlval >> 20) & 0x3) + 8; + + if (ctlval & (1 << 17)) + width = 4; + + size = (1 << cols) * (1 << rows) * banks * width; + + if (size > SZ_64M) + size = SZ_64M; + + return size; +} + +/* + * v2 - found on i.MX25, i.MX27, i.MX31 and i.MX35 + */ +static inline unsigned long imx_v2_sdram_size(void __iomem *esdctlbase, int num) +{ + void __iomem *esdctl = esdctlbase + (num ? IMX_ESDCTL1 : IMX_ESDCTL0); + u32 ctlval = readl(esdctl); + unsigned long size; + int rows, cols, width = 2, banks = 4; + + if (!(ctlval & ESDCTL0_SDE)) + /* SDRAM controller disabled, so no RAM here */ + return 0; + + rows = ((ctlval >> 24) & 0x7) + 11; + cols = ((ctlval >> 20) & 0x3) + 8; + + if ((ctlval & ESDCTL0_DSIZ_MASK) == ESDCTL0_DSIZ_31_0) + width = 4; + + size = (1 << cols) * (1 << rows) * banks * width; + + if (size > SZ_256M) + size = SZ_256M; + + return size; +} + +/* + * v3 - found on i.MX51 + */ +static inline unsigned long imx_v3_sdram_size(void __iomem *esdctlbase, int num) +{ + unsigned long size; + + size = imx_v2_sdram_size(esdctlbase, num); + + if (readl(esdctlbase + IMX_ESDMISC) & (1 << 6)) + size *= 2; + + if (size > SZ_256M) + size = SZ_256M; + + return size; +} + +/* + * v4 - found on i.MX53 + */ +static inline unsigned long imx_v4_sdram_size(void __iomem *esdctlbase, int cs) +{ + u32 ctlval = readl(esdctlbase + ESDCTL_V4_ESDCTL0); + u32 esdmisc = readl(esdctlbase + ESDCTL_V4_ESDMISC); + unsigned long size; + int rows, cols, width = 2, banks = 8; + + if (cs == 0 && !(ctlval & ESDCTL_V4_ESDCTLx_SDE0)) + return 0; + if (cs == 1 && !(ctlval & ESDCTL_V4_ESDCTLx_SDE1)) + return 0; + + /* one 2GiB cs, memory is returned for cs0 only */ + if (cs == 1 && (esdmisc & ESDCTL_V4_ESDMISC_ONE_CS)) + return 9; + + rows = ((ctlval >> 24) & 0x7) + 11; + switch ((ctlval >> 20) & 0x7) { + case 0: + cols = 9; + break; + case 1: + cols = 10; + break; + case 2: + cols = 11; + break; + case 3: + cols = 8; + break; + case 4: + cols = 12; + break; + default: + cols = 0; + break; + } + + if (ctlval & ESDCTL_V4_ESDCTLx_DSIZ_32B) + width = 4; + + if (esdmisc & ESDCTL_V4_ESDMISC_BANKS_4) + banks = 4; + + size = (1 << cols) * (1 << rows) * banks * width; + + return size; +} + +static void add_mem(unsigned long base0, unsigned long size0, + unsigned long base1, unsigned long size1) +{ + debug("%s: cs0 base: 0x%08x cs0 size: 0x%08x\n", __func__, base0, size0); + debug("%s: cs1 base: 0x%08x cs1 size: 0x%08x\n", __func__, base1, size1); + + if (base0 + size0 == base1 && size1 > 0) { + /* + * concatenate both chip selects to a single bank + */ + arm_add_mem_device("ram0", base0, size0 + size1); + + return; + } + + if (size0) + arm_add_mem_device("ram0", base0, size0); + + if (size1) + arm_add_mem_device(size0 ? "ram1" : "ram0", base1, size1); +} + +static void imx_esdctl_v1_add_mem(void *esdctlbase, struct imx_esdctl_data *data) +{ + add_mem(data->base0, imx_v1_sdram_size(esdctlbase, 0), + data->base1, imx_v1_sdram_size(esdctlbase, 1)); +} + +static void imx_esdctl_v2_add_mem(void *esdctlbase, struct imx_esdctl_data *data) +{ + add_mem(data->base0, imx_v2_sdram_size(esdctlbase, 0), + data->base1, imx_v2_sdram_size(esdctlbase, 1)); +} + +static void imx_esdctl_v3_add_mem(void *esdctlbase, struct imx_esdctl_data *data) +{ + add_mem(data->base0, imx_v3_sdram_size(esdctlbase, 0), + data->base1, imx_v3_sdram_size(esdctlbase, 1)); +} + +static void imx_esdctl_v4_add_mem(void *esdctlbase, struct imx_esdctl_data *data) +{ + add_mem(data->base0, imx_v4_sdram_size(esdctlbase, 0), + data->base1, imx_v4_sdram_size(esdctlbase, 1)); +} + +static int imx_esdctl_probe(struct device_d *dev) +{ + struct imx_esdctl_data *data; + int ret; + void *base; + + ret = dev_get_drvdata(dev, (unsigned long *)&data); + if (ret) + return ret; + + base = dev_request_mem_region(dev, 0); + if (!base) + return -ENOMEM; + + data->add_mem(base, data); + + return 0; +} + +static __maybe_unused struct imx_esdctl_data imx1_data = { + .base0 = MX1_CSD0_BASE_ADDR, + .base1 = MX1_CSD1_BASE_ADDR, + .add_mem = imx_esdctl_v1_add_mem, +}; + +static __maybe_unused struct imx_esdctl_data imx25_data = { + .base0 = MX25_CSD0_BASE_ADDR, + .base1 = MX25_CSD1_BASE_ADDR, + .add_mem = imx_esdctl_v2_add_mem, +}; + +static __maybe_unused struct imx_esdctl_data imx27_data = { + .base0 = MX27_CSD0_BASE_ADDR, + .base1 = MX27_CSD1_BASE_ADDR, + .add_mem = imx_esdctl_v2_add_mem, +}; + +static __maybe_unused struct imx_esdctl_data imx31_data = { + .base0 = MX31_CSD0_BASE_ADDR, + .base1 = MX31_CSD1_BASE_ADDR, + .add_mem = imx_esdctl_v2_add_mem, +}; + +static __maybe_unused struct imx_esdctl_data imx35_data = { + .base0 = MX35_CSD0_BASE_ADDR, + .base1 = MX35_CSD1_BASE_ADDR, + .add_mem = imx_esdctl_v2_add_mem, +}; + +static __maybe_unused struct imx_esdctl_data imx51_data = { + .base0 = MX51_CSD0_BASE_ADDR, + .base1 = MX51_CSD1_BASE_ADDR, + .add_mem = imx_esdctl_v3_add_mem, +}; + +static __maybe_unused struct imx_esdctl_data imx53_data = { + .base0 = MX53_CSD0_BASE_ADDR, + .base1 = MX53_CSD1_BASE_ADDR, + .add_mem = imx_esdctl_v4_add_mem, +}; + +static struct platform_device_id imx_esdctl_ids[] = { +#ifdef CONFIG_ARCH_IMX1 + { + .name = "imx1-sdramc", + .driver_data = (unsigned long)&imx1_data, + }, +#endif +#ifdef CONFIG_ARCH_IMX25 + { + .name = "imx25-esdctl", + .driver_data = (unsigned long)&imx25_data, + }, +#endif +#ifdef CONFIG_ARCH_IMX27 + { + .name = "imx27-esdctl", + .driver_data = (unsigned long)&imx27_data, + }, +#endif +#ifdef CONFIG_ARCH_IMX31 + { + .name = "imx31-esdctl", + .driver_data = (unsigned long)&imx31_data, + }, +#endif +#ifdef CONFIG_ARCH_IMX35 + { + .name = "imx35-esdctl", + .driver_data = (unsigned long)&imx35_data, + }, +#endif +#ifdef CONFIG_ARCH_IMX51 + { + .name = "imx51-esdctl", + .driver_data = (unsigned long)&imx51_data, + }, +#endif +#ifdef CONFIG_ARCH_IMX53 + { + .name = "imx53-esdctl", + .driver_data = (unsigned long)&imx53_data, + }, +#endif + { + /* sentinel */ + }, +}; + +static struct driver_d imx_serial_driver = { + .name = "imx-esdctl", + .probe = imx_esdctl_probe, + .id_table = imx_esdctl_ids, +}; + +static int imx_esdctl_init(void) +{ + return platform_driver_register(&imx_serial_driver); +} + +mem_initcall(imx_esdctl_init); diff --git a/arch/arm/mach-imx/imx-bbu-internal.c b/arch/arm/mach-imx/imx-bbu-internal.c index a36a4271ed..bbc620a6a8 100644 --- a/arch/arm/mach-imx/imx-bbu-internal.c +++ b/arch/arm/mach-imx/imx-bbu-internal.c @@ -36,6 +36,7 @@ #define IMX_INTERNAL_FLAG_NAND (1 << 0) #define IMX_INTERNAL_FLAG_KEEP_DOSPART (1 << 1) +#define IMX_INTERNAL_FLAG_ERASE (1 << 2) struct imx_internal_bbu_handler { struct bbu_handler handler; @@ -60,6 +61,17 @@ static int imx_bbu_write_device(struct imx_internal_bbu_handler *imx_handler, if (fd < 0) return fd; + if (imx_handler->flags & IMX_INTERNAL_FLAG_ERASE) { + debug("%s: eraseing %s from 0 to 0x%08x\n", __func__, + data->devicefile, image_len); + ret = erase(fd, image_len, 0); + if (ret) { + printf("erasing %s failed with %s\n", data->devicefile, + strerror(-ret)); + goto err_close; + } + } + if (imx_handler->flags & IMX_INTERNAL_FLAG_KEEP_DOSPART) { void *mbr = xzalloc(512); @@ -110,7 +122,7 @@ static int imx_bbu_internal_v1_update(struct bbu_handler *handler, struct bbu_da int ret, image_len; void *buf; - if (file_detect_type(data->image) != filetype_arm_barebox) { + if (file_detect_type(data->image, data->len) != filetype_arm_barebox) { if (!bbu_force(data, "Not an ARM barebox image")) return -EINVAL; } @@ -332,7 +344,7 @@ static int imx_bbu_internal_v2_update(struct bbu_handler *handler, struct bbu_da int ret, image_len; void *buf; - if (file_detect_type(data->image) != filetype_arm_barebox) { + if (file_detect_type(data->image, data->len) != filetype_arm_barebox) { if (!bbu_force(data, "Not an ARM barebox image")) return -EINVAL; } @@ -357,8 +369,9 @@ static int imx_bbu_internal_v2_update(struct bbu_handler *handler, struct bbu_da flash_header->header.version = IVT_VERSION; flash_header->entry = imx_handler->app_dest + imx_pre_image_size; - flash_header->dcd_ptr = imx_handler->app_dest + flash_header_offset + - offsetof(struct imx_flash_header_v2, dcd); + if (imx_handler->dcdsize) + flash_header->dcd_ptr = imx_handler->app_dest + flash_header_offset + + offsetof(struct imx_flash_header_v2, dcd); flash_header->boot_data_ptr = imx_handler->app_dest + flash_header_offset + offsetof(struct imx_flash_header_v2, boot_data); flash_header->self = imx_handler->app_dest + flash_header_offset; @@ -366,10 +379,12 @@ static int imx_bbu_internal_v2_update(struct bbu_handler *handler, struct bbu_da flash_header->boot_data.start = imx_handler->app_dest; flash_header->boot_data.size = ALIGN(imx_pre_image_size + data->len, 4096);; - flash_header->dcd.header.tag = DCD_HEADER_TAG; - flash_header->dcd.header.length = cpu_to_be16(sizeof(struct imx_dcd) + - imx_handler->dcdsize); - flash_header->dcd.header.version = DCD_VERSION; + if (imx_handler->dcdsize) { + flash_header->dcd.header.tag = DCD_HEADER_TAG; + flash_header->dcd.header.length = cpu_to_be16(sizeof(struct imx_dcd) + + imx_handler->dcdsize); + flash_header->dcd.header.version = DCD_VERSION; + } /* Add dcd data */ memcpy((void *)flash_header + sizeof(*flash_header), imx_handler->dcd, imx_handler->dcdsize); @@ -453,7 +468,8 @@ static int __register_handler(struct imx_internal_bbu_handler *imx_handler) * Register a i.MX51 internal boot update handler for MMC/SD */ int imx51_bbu_internal_mmc_register_handler(const char *name, char *devicefile, - unsigned long flags, struct imx_dcd_entry *dcd, int dcdsize) + unsigned long flags, struct imx_dcd_entry *dcd, int dcdsize, + unsigned long app_dest) { struct imx_internal_bbu_handler *imx_handler; @@ -461,7 +477,12 @@ int imx51_bbu_internal_mmc_register_handler(const char *name, char *devicefile, imx_handler->dcd = dcd; imx_handler->dcdsize = dcdsize; imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; - imx_handler->app_dest = 0x90000000; + + if (app_dest) + imx_handler->app_dest = app_dest; + else + imx_handler->app_dest = 0x90000000; + imx_handler->flags = IMX_INTERNAL_FLAG_KEEP_DOSPART; imx_handler->handler.handler = imx_bbu_internal_v1_update; @@ -476,6 +497,13 @@ static int imx53_bbu_internal_init_dcd(struct imx_internal_bbu_handler *imx_hand uint32_t *dcd32 = dcd; /* + * For boards which do not have a dcd (i.e. they do their SDRAM + * setup in C code) + */ + if (!dcd || !dcdsize) + return 0; + + /* * The DCD data we have compiled in does not have a DCD_WR_CMD at * the beginning. Instead it is contained in struct imx_flash_header_v2. * This is necessary to generate the DCD size at compile time. If @@ -507,14 +535,20 @@ static int imx53_bbu_internal_init_dcd(struct imx_internal_bbu_handler *imx_hand * Register a i.MX53 internal boot update handler for MMC/SD */ int imx53_bbu_internal_mmc_register_handler(const char *name, char *devicefile, - unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize) + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest) { struct imx_internal_bbu_handler *imx_handler; imx_handler = __init_handler(name, devicefile, flags); imx53_bbu_internal_init_dcd(imx_handler, dcd, dcdsize); imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; - imx_handler->app_dest = 0x70000000; + + if (app_dest) + imx_handler->app_dest = app_dest; + else + imx_handler->app_dest = 0x70000000; + imx_handler->flags = IMX_INTERNAL_FLAG_KEEP_DOSPART; imx_handler->handler.handler = imx_bbu_internal_v2_update; @@ -522,18 +556,49 @@ int imx53_bbu_internal_mmc_register_handler(const char *name, char *devicefile, } /* + * Register a i.MX53 internal boot update handler for i2c/spi + * EEPROMs / flashes. Nearly the same as MMC/SD, but we do not need to + * keep a partition table. We have to erase the device beforehand though. + */ +int imx53_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest) +{ + struct imx_internal_bbu_handler *imx_handler; + + imx_handler = __init_handler(name, devicefile, flags); + imx53_bbu_internal_init_dcd(imx_handler, dcd, dcdsize); + imx_handler->flash_header_offset = FLASH_HEADER_OFFSET_MMC; + + if (app_dest) + imx_handler->app_dest = app_dest; + else + imx_handler->app_dest = 0x70000000; + + imx_handler->flags = IMX_INTERNAL_FLAG_ERASE; + imx_handler->handler.handler = imx_bbu_internal_v2_update; + + return __register_handler(imx_handler); +} + +/* * Register a i.MX53 internal boot update handler for NAND */ int imx53_bbu_internal_nand_register_handler(const char *name, unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, - int partition_size) + int partition_size, unsigned long app_dest) { struct imx_internal_bbu_handler *imx_handler; imx_handler = __init_handler(name, NULL, flags); imx53_bbu_internal_init_dcd(imx_handler, dcd, dcdsize); imx_handler->flash_header_offset = 0x400; - imx_handler->app_dest = 0x70000000; + + if (app_dest) + imx_handler->app_dest = app_dest; + else + imx_handler->app_dest = 0x70000000; + imx_handler->handler.handler = imx_bbu_internal_v2_update; imx_handler->flags = IMX_INTERNAL_FLAG_NAND; imx_handler->handler.devicefile = "/dev/nand0"; @@ -541,3 +606,33 @@ int imx53_bbu_internal_nand_register_handler(const char *name, return __register_handler(imx_handler); } + +/* + * Register a i.MX6 internal boot update handler for MMC/SD + */ +int imx6_bbu_internal_mmc_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest) +{ + if (!app_dest) + app_dest = 0x10000000; + + return imx53_bbu_internal_mmc_register_handler(name, devicefile, + flags, dcd, dcdsize, app_dest); +} + +/* + * Register a i.MX53 internal boot update handler for i2c/spi + * EEPROMs / flashes. Nearly the same as MMC/SD, but we do not need to + * keep a partition table. We have to erase the device beforehand though. + */ +int imx6_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest) +{ + if (!app_dest) + app_dest = 0x10000000; + + return imx53_bbu_internal_spi_i2c_register_handler(name, devicefile, + flags, dcd, dcdsize, app_dest); +} diff --git a/arch/arm/mach-imx/imx1.c b/arch/arm/mach-imx/imx1.c index 18901ea6d0..588ac02c9c 100644 --- a/arch/arm/mach-imx/imx1.c +++ b/arch/arm/mach-imx/imx1.c @@ -49,6 +49,8 @@ void imx1_setup_eimcs(size_t cs, unsigned upper, unsigned lower) writel(lower, MX1_EIM_BASE_ADDR + 4 + cs * 8); } +#include <mach/esdctl.h> + static int imx1_init(void) { imx_iomuxv1_init((void *)MX1_GPIO1_BASE_ADDR); @@ -61,6 +63,7 @@ static int imx1_init(void) add_generic_device("imx1-gpio", 2, NULL, MX1_GPIO3_BASE_ADDR, 0x100, IORESOURCE_MEM, NULL); add_generic_device("imx1-gpio", 3, NULL, MX1_GPIO4_BASE_ADDR, 0x100, IORESOURCE_MEM, NULL); add_generic_device("imx1-wdt", 0, NULL, MX1_WDT_BASE_ADDR, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx1-sdramc", 0, NULL, MX1_SDRAMC_BASE_ADDR, 0x100, IORESOURCE_MEM, NULL); return 0; } diff --git a/arch/arm/mach-imx/imx25.c b/arch/arm/mach-imx/imx25.c index 3bd95c146a..e2ef374a0d 100644 --- a/arch/arm/mach-imx/imx25.c +++ b/arch/arm/mach-imx/imx25.c @@ -75,6 +75,7 @@ static int imx25_init(void) add_generic_device("imx31-gpio", 2, NULL, MX25_GPIO3_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx31-gpio", 3, NULL, MX25_GPIO4_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx21-wdt", 0, NULL, MX25_WDOG_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx25-esdctl", 0, NULL, MX25_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); return 0; } diff --git a/arch/arm/mach-imx/imx27.c b/arch/arm/mach-imx/imx27.c index a0a510f5ab..31117f4501 100644 --- a/arch/arm/mach-imx/imx27.c +++ b/arch/arm/mach-imx/imx27.c @@ -117,6 +117,7 @@ static int imx27_init(void) add_generic_device("imx1-gpio", 4, NULL, MX27_GPIO5_BASE_ADDR, 0x100, IORESOURCE_MEM, NULL); add_generic_device("imx1-gpio", 5, NULL, MX27_GPIO6_BASE_ADDR, 0x100, IORESOURCE_MEM, NULL); add_generic_device("imx21-wdt", 0, NULL, MX27_WDOG_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx27-esdctl", 0, NULL, MX27_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); return 0; } diff --git a/arch/arm/mach-imx/imx31.c b/arch/arm/mach-imx/imx31.c index b2f0724bd1..52be541a57 100644 --- a/arch/arm/mach-imx/imx31.c +++ b/arch/arm/mach-imx/imx31.c @@ -38,6 +38,7 @@ static int imx31_init(void) add_generic_device("imx-gpio", 1, NULL, MX31_GPIO2_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx-gpio", 2, NULL, MX31_GPIO3_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx21-wdt", 0, NULL, MX31_WDOG_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx31-esdctl", 0, NULL, MX31_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); return 0; } diff --git a/arch/arm/mach-imx/imx35.c b/arch/arm/mach-imx/imx35.c index 737eb3a3a8..21c7e90fcf 100644 --- a/arch/arm/mach-imx/imx35.c +++ b/arch/arm/mach-imx/imx35.c @@ -77,6 +77,7 @@ static int imx35_init(void) add_generic_device("imx-gpio", 1, NULL, MX35_GPIO2_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx-gpio", 2, NULL, MX35_GPIO3_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx21-wdt", 0, NULL, MX35_WDOG_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + add_generic_device("imx35-esdctl", 0, NULL, MX35_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); return 0; } diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c index 4b0786b37b..a62daf8480 100644 --- a/arch/arm/mach-imx/imx51.c +++ b/arch/arm/mach-imx/imx51.c @@ -69,6 +69,7 @@ static int imx51_init(void) add_generic_device("imx31-gpio", 2, NULL, MX51_GPIO3_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx31-gpio", 3, NULL, MX51_GPIO4_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx21-wdt", 0, NULL, MX51_WDOG_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx51-esdctl", 0, NULL, MX51_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); return 0; } @@ -93,13 +94,6 @@ postcore_initcall(imx51_init); * power up. */ -#define setup_pll_800(base) imx5_setup_pll((base), 800, (( 8 << 4) + ((1 - 1) << 0)), ( 3 - 1), 1) -#define setup_pll_665(base) imx5_setup_pll((base), 665, (( 6 << 4) + ((1 - 1) << 0)), (96 - 1), 89) -#define setup_pll_600(base) imx5_setup_pll((base), 600, (( 6 << 4) + ((1 - 1) << 0)), ( 4 - 1), 1) -#define setup_pll_400(base) imx5_setup_pll((base), 400, (( 8 << 4) + ((2 - 1) << 0)), ( 3 - 1), 1) -#define setup_pll_455(base) imx5_setup_pll((base), 455, (( 9 << 4) + ((2 - 1) << 0)), (48 - 1), 23) -#define setup_pll_216(base) imx5_setup_pll((base), 216, (( 6 << 4) + ((3 - 1) << 0)), ( 4 - 1), 3) - void imx51_init_lowlevel(unsigned int cpufreq_mhz) { void __iomem *ccm = (void __iomem *)MX51_CCM_BASE_ADDR; @@ -136,27 +130,27 @@ void imx51_init_lowlevel(unsigned int cpufreq_mhz) switch (cpufreq_mhz) { case 600: - setup_pll_600((void __iomem *)MX51_PLL1_BASE_ADDR); + imx5_setup_pll_600((void __iomem *)MX51_PLL1_BASE_ADDR); break; default: /* Default maximum 800MHz */ - setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR); + imx5_setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR); break; } - setup_pll_665((void __iomem *)MX51_PLL3_BASE_ADDR); + imx5_setup_pll_665((void __iomem *)MX51_PLL3_BASE_ADDR); /* Switch peripheral to PLL 3 */ writel(0x000010C0, ccm + MX5_CCM_CBCMR); writel(0x13239145, ccm + MX5_CCM_CBCDR); - setup_pll_665((void __iomem *)MX51_PLL2_BASE_ADDR); + imx5_setup_pll_665((void __iomem *)MX51_PLL2_BASE_ADDR); /* Switch peripheral to PLL2 */ writel(0x19239145, ccm + MX5_CCM_CBCDR); writel(0x000020C0, ccm + MX5_CCM_CBCMR); - setup_pll_216((void __iomem *)MX51_PLL3_BASE_ADDR); + imx51_setup_pll_216((void __iomem *)MX51_PLL3_BASE_ADDR); /* Set the platform clock dividers */ writel(0x00000124, MX51_ARM_BASE_ADDR + 0x14); diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c index e424e7d903..52fb8f78fd 100644 --- a/arch/arm/mach-imx/imx53.c +++ b/arch/arm/mach-imx/imx53.c @@ -69,17 +69,12 @@ static int imx53_init(void) add_generic_device("imx31-gpio", 5, NULL, MX53_GPIO6_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx31-gpio", 6, NULL, MX53_GPIO7_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx21-wdt", 0, NULL, MX53_WDOG1_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx53-esdctl", 0, NULL, MX53_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); return 0; } postcore_initcall(imx53_init); -#define setup_pll_1000(base) imx5_setup_pll((base), 1000, ((10 << 4) + ((1 - 1) << 0)), (12 - 1), 5) -#define setup_pll_800(base) imx5_setup_pll((base), 800, ((8 << 4) + ((1 - 1) << 0)), (3 - 1), 1) -#define setup_pll_400(base) imx5_setup_pll((base), 400, ((8 << 4) + ((2 - 1) << 0)), (3 - 1), 1) -#define setup_pll_455(base) imx5_setup_pll((base), 455, ((9 << 4) + ((2 - 1) << 0)), (48 - 1), 23) -#define setup_pll_216(base) imx5_setup_pll((base), 216, ((8 << 4) + ((2 - 1) << 0)), (1 - 1), 1) - void imx53_init_lowlevel(unsigned int cpufreq_mhz) { void __iomem *ccm = (void __iomem *)MX53_CCM_BASE_ADDR; @@ -112,11 +107,11 @@ void imx53_init_lowlevel(unsigned int cpufreq_mhz) writel(0x4, ccm + MX5_CCM_CCSR); if (cpufreq_mhz == 1000) - setup_pll_1000((void __iomem *)MX53_PLL1_BASE_ADDR); + imx5_setup_pll_1000((void __iomem *)MX53_PLL1_BASE_ADDR); else - setup_pll_800((void __iomem *)MX53_PLL1_BASE_ADDR); + imx5_setup_pll_800((void __iomem *)MX53_PLL1_BASE_ADDR); - setup_pll_400((void __iomem *)MX53_PLL3_BASE_ADDR); + imx5_setup_pll_400((void __iomem *)MX53_PLL3_BASE_ADDR); /* Switch peripheral to PLL3 */ writel(0x00015154, ccm + MX5_CCM_CBCMR); @@ -125,7 +120,7 @@ void imx53_init_lowlevel(unsigned int cpufreq_mhz) /* make sure change is effective */ while (readl(ccm + MX5_CCM_CDHIPR)); - setup_pll_400((void __iomem *)MX53_PLL2_BASE_ADDR); + imx5_setup_pll_400((void __iomem *)MX53_PLL2_BASE_ADDR); /* Switch peripheral to PLL2 */ r = 0x00808145 | @@ -151,8 +146,8 @@ void imx53_init_lowlevel(unsigned int cpufreq_mhz) /* make sure change is effective */ while (readl(ccm + MX5_CCM_CDHIPR)); - setup_pll_216((void __iomem *)MX53_PLL3_BASE_ADDR); - setup_pll_455((void __iomem *)MX53_PLL4_BASE_ADDR); + imx53_setup_pll_216((void __iomem *)MX53_PLL3_BASE_ADDR); + imx5_setup_pll_455((void __iomem *)MX53_PLL4_BASE_ADDR); /* Set the platform clock dividers */ writel(0x00000124, MX53_ARM_BASE_ADDR + 0x14); diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index c9eec5ab75..37ee5d8487 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -15,6 +15,7 @@ #include <common.h> #include <io.h> #include <sizes.h> +#include <mach/generic.h> #include <mach/imx6-regs.h> void imx6_init_lowlevel(void) @@ -54,6 +55,8 @@ void imx6_init_lowlevel(void) static int imx6_init(void) { + imx6_boot_save_loc((void *)MX6_SRC_BASE_ADDR); + add_generic_device("imx-iomuxv3", 0, NULL, MX6_IOMUXC_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); add_generic_device("imx6-ccm", 0, NULL, MX6_CCM_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); add_generic_device("imx31-gpt", 0, NULL, 0x02098000, 0x1000, IORESOURCE_MEM, NULL); diff --git a/arch/arm/mach-imx/include/mach/bbu.h b/arch/arm/mach-imx/include/mach/bbu.h index f9ec1cc0af..ad7c754bc8 100644 --- a/arch/arm/mach-imx/include/mach/bbu.h +++ b/arch/arm/mach-imx/include/mach/bbu.h @@ -9,32 +9,69 @@ struct imx_dcd_v2_entry; #ifdef CONFIG_BAREBOX_UPDATE int imx51_bbu_internal_mmc_register_handler(const char *name, char *devicefile, - unsigned long flags, struct imx_dcd_entry *, int dcdsize); + unsigned long flags, struct imx_dcd_entry *, int dcdsize, + unsigned long app_dest); int imx53_bbu_internal_mmc_register_handler(const char *name, char *devicefile, - unsigned long flags, struct imx_dcd_v2_entry *, int dcdsize); + unsigned long flags, struct imx_dcd_v2_entry *, int dcdsize, + unsigned long app_dest); + +int imx53_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest); int imx53_bbu_internal_nand_register_handler(const char *name, unsigned long flags, struct imx_dcd_v2_entry *, int dcdsize, - int partition_size); + int partition_size, unsigned long app_dest); + +int imx6_bbu_internal_mmc_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *, int dcdsize, + unsigned long app_dest); + +int imx6_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest); #else static inline int imx51_bbu_internal_mmc_register_handler(const char *name, char *devicefile, - unsigned long flags, struct imx_dcd_entry *dcd, int dcdsize) + unsigned long flags, struct imx_dcd_entry *dcd, int dcdsize, + unsigned long app_dest) { return -ENOSYS; } static inline int imx53_bbu_internal_mmc_register_handler(const char *name, char *devicefile, - unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize) + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest) +{ + return -ENOSYS; +} + +static inline int imx53_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest) { return -ENOSYS; } static inline int imx53_bbu_internal_nand_register_handler(const char *name, unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, - int partition_size) + int partition_size, unsigned long app_dest) +{ + return -ENOSYS; +} + +static inline int imx6_bbu_internal_mmc_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest) +{ + return -ENOSYS; +} + +static inline int imx6_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefile, + unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize, + unsigned long app_dest) { return -ENOSYS; } diff --git a/arch/arm/mach-imx/include/mach/debug_ll.h b/arch/arm/mach-imx/include/mach/debug_ll.h new file mode 100644 index 0000000000..cb6dd039bc --- /dev/null +++ b/arch/arm/mach-imx/include/mach/debug_ll.h @@ -0,0 +1,46 @@ +#ifndef __MACH_DEBUG_LL_H__ +#define __MACH_DEBUG_LL_H__ + +#include <io.h> +#include <config.h> +#include <mach/imx1-regs.h> +#include <mach/imx21-regs.h> +#include <mach/imx25-regs.h> +#include <mach/imx27-regs.h> +#include <mach/imx31-regs.h> +#include <mach/imx35-regs.h> +#include <mach/imx51-regs.h> +#include <mach/imx53-regs.h> +#include <mach/imx6-regs.h> + +/* #define IMX_DEBUG_LL_UART_BASE MXxy_UARTx_BASE_ADDR */ + +#ifndef IMX_DEBUG_LL_UART_BASE +#warning define IMX_DEBUG_LL_UART_BASE properly for debug_ll +#define IMX_DEBUG_LL_UART_BASE 0 +#endif + +#define URTX0 0x40 /* Transmitter Register */ + +#define UCR1 0x80 /* Control Register 1 */ +#define UCR1_UARTEN (1 << 0) /* UART enabled */ + +#define USR2 0x98 /* Status Register 2 */ +#define USR2_TXDC (1 << 3) /* Transmitter complete */ + +static inline void PUTC_LL(int c) +{ + void __iomem *base = (void *)IMX_DEBUG_LL_UART_BASE; + + if (!base) + return; + + if (!(readl(base + UCR1) & UCR1_UARTEN)) + return; + + while (!(readl(base + USR2) & USR2_TXDC)); + + writel(c, base + URTX0); +} + +#endif /* __MACH_DEBUG_LL_H__ */ diff --git a/arch/arm/mach-imx/include/mach/devices-imx51.h b/arch/arm/mach-imx/include/mach/devices-imx51.h index 8ee3c17478..95497fa664 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx51.h +++ b/arch/arm/mach-imx/include/mach/devices-imx51.h @@ -93,3 +93,8 @@ static inline struct device_d *imx51_add_kpp(struct matrix_keymap_data *pdata) { return imx_add_kpp((void *)MX51_KPP_BASE_ADDR, pdata); } + +static inline struct device_d *imx51_add_pata(void) +{ + return imx_add_pata((void *)MX51_ATA_BASE_ADDR); +} diff --git a/arch/arm/mach-imx/include/mach/devices-imx53.h b/arch/arm/mach-imx/include/mach/devices-imx53.h index 5f967eaac2..4c330549cd 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx53.h +++ b/arch/arm/mach-imx/include/mach/devices-imx53.h @@ -82,3 +82,13 @@ static inline struct device_d *imx53_add_nand(struct imx_nand_platform_data *pda return dev; } + +static inline struct device_d *imx53_add_kpp(struct matrix_keymap_data *pdata) +{ + return imx_add_kpp((void *)MX53_KPP_BASE_ADDR, pdata); +} + +static inline struct device_d *imx53_add_sata(void) +{ + return add_generic_device("imx53-sata", 0, NULL, MX53_SATA_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); +} diff --git a/arch/arm/mach-imx/include/mach/devices-imx6.h b/arch/arm/mach-imx/include/mach/devices-imx6.h index f8282e7fca..0f17016530 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx6.h +++ b/arch/arm/mach-imx/include/mach/devices-imx6.h @@ -64,3 +64,8 @@ static inline struct device_d *imx6_add_i2c2(struct i2c_platform_data *pdata) { return imx_add_i2c((void *)MX6_I2C3_BASE_ADDR, 2, pdata); } + +static inline struct device_d *imx6_add_sata(void) +{ + return add_generic_device("imx6-sata", 0, NULL, MX6_SATA_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); +} diff --git a/arch/arm/mach-imx/include/mach/devices.h b/arch/arm/mach-imx/include/mach/devices.h index f7824f5406..016778a138 100644 --- a/arch/arm/mach-imx/include/mach/devices.h +++ b/arch/arm/mach-imx/include/mach/devices.h @@ -20,4 +20,4 @@ struct device_d *imx_add_ipufb(void *base, struct imx_ipu_fb_platform_data *pdat struct device_d *imx_add_mmc(void *base, int id, void *pdata); struct device_d *imx_add_esdhc(void *base, int id, struct esdhc_platform_data *pdata); struct device_d *imx_add_kpp(void *base, struct matrix_keymap_data *pdata); - +struct device_d *imx_add_pata(void *base); diff --git a/arch/arm/mach-imx/include/mach/esdctl-v4.h b/arch/arm/mach-imx/include/mach/esdctl-v4.h new file mode 100644 index 0000000000..2e6741e0d5 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/esdctl-v4.h @@ -0,0 +1,520 @@ +#ifndef __MACH_ESDCTL_V4_H +#define __MACH_ESDCTL_V4_H + +#define ESDCTL_V4_ESDCTL0 0x00 +#define ESDCTL_V4_ESDPDC 0x04 +#define ESDCTL_V4_ESDOTC 0x08 +#define ESDCTL_V4_ESDCFG0 0x0c +#define ESDCTL_V4_ESDCFG1 0x10 +#define ESDCTL_V4_ESDCFG2 0x14 +#define ESDCTL_V4_ESDMISC 0x18 +#define ESDCTL_V4_ESDSCR 0x1c +#define ESDCTL_V4_ESDREF 0x20 +#define ESDCTL_V4_ESDWCC 0x24 +#define ESDCTL_V4_ESDRCC 0x28 +#define ESDCTL_V4_ESDRWD 0x2c +#define ESDCTL_V4_ESDOR 0x30 +#define ESDCTL_V4_ESDMRR 0x34 +#define ESDCTL_V4_ESDCFG3_LP 0x38 +#define ESDCTL_V4_ESDMR4 0x3c +#define ESDCTL_V4_ZQHWCTRL 0x40 +#define ESDCTL_V4_ZQSWCTRL 0x44 +#define ESDCTL_V4_WLGCR 0x48 +#define ESDCTL_V4_WLDECTRL0 0x4c +#define ESDCTL_V4_WLDECTRL1 0x50 +#define ESDCTL_V4_WLDLST 0x54 +#define ESDCTL_V4_ODTCTRL 0x58 +#define ESDCTL_V4_RDDQBY0DL 0x5c +#define ESDCTL_V4_RDDQBY1DL 0x60 +#define ESDCTL_V4_RDDQBY2DL 0x64 +#define ESDCTL_V4_RDDQBY3DL 0x68 +#define ESDCTL_V4_WRDQBY0DL 0x6c +#define ESDCTL_V4_WRDQBY1DL 0x70 +#define ESDCTL_V4_WRDQBY2DL 0x74 +#define ESDCTL_V4_WRDQBY3DL 0x78 +#define ESDCTL_V4_DGCTRL0 0x7c +#define ESDCTL_V4_DGCTRL1 0x80 +#define ESDCTL_V4_DGDLST 0x84 +#define ESDCTL_V4_RDDLCTL 0x88 +#define ESDCTL_V4_RDDLST 0x8c +#define ESDCTL_V4_WRDLCTL 0x90 +#define ESDCTL_V4_WRDLST 0x94 +#define ESDCTL_V4_SDCTRL 0x98 +#define ESDCTL_V4_ZQLP2CTL 0x9c +#define ESDCTL_V4_RDDLHWCTL 0xa0 +#define ESDCTL_V4_WRDLHWCTL 0xa4 +#define ESDCTL_V4_RDDLHWST0 0xa8 +#define ESDCTL_V4_RDDLHWST1 0xac +#define ESDCTL_V4_WRDLHWST0 0xb0 +#define ESDCTL_V4_WRDLHWST1 0xb4 +#define ESDCTL_V4_WLHWERR 0xb8 +#define ESDCTL_V4_DGHWST0 0xbc +#define ESDCTL_V4_DGHWST1 0xc0 +#define ESDCTL_V4_DGHWST2 0xc4 +#define ESDCTL_V4_DGHWST3 0xc8 +#define ESDCTL_V4_PDCMPR1 0xcc +#define ESDCTL_V4_PDCMPR2 0xd0 +#define ESDCTL_V4_SWDADR 0xd4 +#define ESDCTL_V4_SWDRDR0 0xd8 +#define ESDCTL_V4_SWDRDR1 0xdc +#define ESDCTL_V4_SWDRDR2 0xe0 +#define ESDCTL_V4_SWDRDR3 0xe4 +#define ESDCTL_V4_SWDRDR4 0xe8 +#define ESDCTL_V4_SWDRDR5 0xec +#define ESDCTL_V4_SWDRDR6 0xf0 +#define ESDCTL_V4_SWDRDR7 0xf4 +#define ESDCTL_V4_MUR 0xf8 +#define ESDCTL_V4_WRCADL 0xfc + +#define ESDCTL_V4_ESDCTLx_SDE0 0x80000000 +#define ESDCTL_V4_ESDCTLx_SDE1 0x40000000 + +#define ESDCTL_V4_ESDCTLx_ROW_MASK 0x07000000 +#define ESDCTL_V4_ESDCTLx_ROW_11 0x00000000 +#define ESDCTL_V4_ESDCTLx_ROW_12 0x01000000 +#define ESDCTL_V4_ESDCTLx_ROW_13 0x02000000 +#define ESDCTL_V4_ESDCTLx_ROW_14 0x03000000 +#define ESDCTL_V4_ESDCTLx_ROW_15 0x04000000 +#define ESDCTL_V4_ESDCTLx_ROW_16 0x05000000 + +#define ESDCTL_V4_ESDCTLx_COL_MASK 0x00700000 +#define ESDCTL_V4_ESDCTLx_COL_9 0x00000000 +#define ESDCTL_V4_ESDCTLx_COL_10 0x00100000 +#define ESDCTL_V4_ESDCTLx_COL_11 0x00200000 +#define ESDCTL_V4_ESDCTLx_COL_8 0x00300000 +#define ESDCTL_V4_ESDCTLx_COL_12 0x00400000 + +#define ESDCTL_V4_ESDCTLx_BL_MASK 0x00080000 +#define ESDCTL_V4_ESDCTLx_BL_4_RES 0x00000000 +#define ESDCTL_V4_ESDCTLx_BL_8_8 0x00080000 + +#define ESDCTL_V4_ESDCTLx_DSIZ_MASK 0x00010000 +#define ESDCTL_V4_ESDCTLx_DSIZ_16B_LOW 0x00000000 +#define ESDCTL_V4_ESDCTLx_DSIZ_32B 0x00010000 + +#define ESDCTL_V4_ESDMISC_CS0_RDY 0x80000000 +#define ESDCTL_V4_ESDMISC_CS1_RDY 0x40000000 +#define ESDCTL_V4_ESDMISC_ONE_CS 0x00100000 +#define ESDCTL_V4_ESDMISC_ADDR_MIRROR 0x00080000 +#define ESDCTL_V4_ESDMISC_LHD 0x00040000 +#define ESDCTL_V4_ESDMISC_WALAT_SHIFT 16 +#define ESDCTL_V4_ESDMISC_WALAT_MASK (0x3 << ESDCTL_V4_ESDMISC_WALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_WALAT_0 (0x0 << ESDCTL_V4_ESDMISC_WALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_WALAT_1 (0x1 << ESDCTL_V4_ESDMISC_WALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_WALAT_2 (0x2 << ESDCTL_V4_ESDMISC_WALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_WALAT_3 (0x3 << ESDCTL_V4_ESDMISC_WALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_BI_ON 0x00001000 +#define ESDCTL_V4_ESDMISC_MIF3_MODE_MASK 0x00000600 +#define ESDCTL_V4_ESDMISC_MIF3_MODE_DIS 0x00000000 +#define ESDCTL_V4_ESDMISC_MIF3_MODE_EF 0x00000200 +#define ESDCTL_V4_ESDMISC_MIF3_MODE_EFA 0x00000400 +#define ESDCTL_V4_ESDMISC_MIF3_MODE_EFAM 0x00000600 +#define ESDCTL_V4_ESDMISC_RALAT_SHIFT 6 +#define ESDCTL_V4_ESDMISC_RALAT_MASK (0x7 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_RALAT_0 (0x0 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_RALAT_1 (0x1 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_RALAT_2 (0x2 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_RALAT_3 (0x3 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_RALAT_4 (0x4 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_RALAT_5 (0x5 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_RALAT_6 (0x6 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) +#define ESDCTL_V4_ESDMISC_RALAT_7 (0x7 << ESDCTL_V4_ESDMISC_RALAT_SHIFT) + +#define ESDCTL_V4_ESDMISC_DDR_MASK 0x00000818 +#define ESDCTL_V4_ESDMISC_DDR_DDR3 0x00000000 +#define ESDCTL_V4_ESDMISC_DDR_LPDDR2_S4 0x00000008 +#define ESDCTL_V4_ESDMISC_DDR_LPDDR2_S2 0x00000808 +#define ESDCTL_V4_ESDMISC_DDR_DDR2 0x00000010 + +#define ESDCTL_V4_ESDMISC_BANKS_MASK 0x00000020 +#define ESDCTL_V4_ESDMISC_BANKS_4 0x00000020 +#define ESDCTL_V4_ESDMISC_BANKS_8 0x00000000 + +#define ESDCTL_V4_ESDMISC_RST 0x00000002 + + +#define ESDCTL_V4_ESDRDDLCTL_RD_DL_ABS_OFFSET3_SHIFT 24 +#define ESDCTL_V4_ESDRDDLCTL_RD_DL_ABS_OFFSET2_SHIFT 16 +#define ESDCTL_V4_ESDRDDLCTL_RD_DL_ABS_OFFSET1_SHIFT 8 +#define ESDCTL_V4_ESDRDDLCTL_RD_DL_ABS_OFFSET0_SHIFT 0 +#define ESDCTL_V4_ESDRDDLCTL_RD_DL_ABS_OFFSET_MASK 0xff + +#define ESDCTL_V4_ESDRDDLCTL_WR_DL_ABS_OFFSET3_SHIFT 24 +#define ESDCTL_V4_ESDRDDLCTL_WR_DL_ABS_OFFSET2_SHIFT 16 +#define ESDCTL_V4_ESDRDDLCTL_WR_DL_ABS_OFFSET1_SHIFT 8 +#define ESDCTL_V4_ESDRDDLCTL_WR_DL_ABS_OFFSET0_SHIFT 0 +#define ESDCTL_V4_ESDRDDLCTL_WR_DL_ABS_OFFSET_MASK 0xff + + +#define ESDCTL_V4_ESDDGCTRL0_RST_RD_FIFO 0x80000000 +#define ESDCTL_V4_ESDDGCTRL0_DG_CMP_CYC 0x40000000 +#define ESDCTL_V4_ESDDGCTRL0_DG_DIS 0x20000000 +#define ESDCTL_V4_ESDDGCTRL0_HW_DG_EN 0x10000000 +#define ESDCTL_V4_ESDDGCTRL0_DG_HC_DEL1_MASK 0x0f000000 +#define ESDCTL_V4_ESDDGCTRL0_DG_HC_DEL1_SHIFT 24 +#define ESDCTL_V4_ESDDGCTRL0_DG_EXT_UP 0x00800000 +#define ESDCTL_V4_ESDDGCTRL0_DG_DL_ABS_OFFSET1_MASK 0x007f0000 +#define ESDCTL_V4_ESDDGCTRL0_DG_DL_ABS_OFFSET1_SHIFT 16 +#define ESDCTL_V4_ESDDGCTRL0_HW_DG_ERR 0x00001000 +#define ESDCTL_V4_ESDDGCTRL0_DG_HC_DEL0_MASK 0x00000f00 +#define ESDCTL_V4_ESDDGCTRL0_DG_HC_DEL0_SHIFT 8 +#define ESDCTL_V4_ESDDGCTRL0_DG_DL_ABS_OFFSET0_MASK 0x0000007f +#define ESDCTL_V4_ESDDGCTRL0_DG_DL_ABS_OFFSET0_SHIFT 0 + +#define ESDCTL_V4_ESDDGCTRL1_DG_HC_DEL3_MASK 0x0f000000 +#define ESDCTL_V4_ESDDGCTRL1_DG_HC_DEL3_SHIFT 24 +#define ESDCTL_V4_ESDDGCTRL1_DG_DL_ABS_OFFSET3_MASK 0x007f0000 +#define ESDCTL_V4_ESDDGCTRL1_DG_DL_ABS_OFFSET3_SHIFT 16 +#define ESDCTL_V4_ESDDGCTRL1_DG_HC_DEL2_MASK 0x00000f00 +#define ESDCTL_V4_ESDDGCTRL1_DG_HC_DEL2_SHIFT 8 +#define ESDCTL_V4_ESDDGCTRL1_DG_DL_ABS_OFFSET2_MASK 0x0000007f +#define ESDCTL_V4_ESDDGCTRL1_DG_DL_ABS_OFFSET2_SHIFT 0 + + +#define ESDCTL_V4_ESDCFG0_tRFC_SHIFT 24 +#define ESDCTL_V4_ESDCFG0_tRFC_MASK (0xff << ESDCTL_V4_ESDCFG0_tRFC_SHIFT) +#define ESDCTL_V4_ESDCFG0_tXS_SHIFT 16 +#define ESDCTL_V4_ESDCFG0_tXS_MASK (0xff << ESDCTL_V4_ESDCFG0_tXS_SHIFT) +#define ESDCTL_V4_ESDCFG0_tXP_SHIFT 13 +#define ESDCTL_V4_ESDCFG0_tXP_MASK (0x7 << ESDCTL_V4_ESDCFG0_tXP_SHIFT) +#define ESDCTL_V4_ESDCFG0_tXPDLL_SHIFT 9 +#define ESDCTL_V4_ESDCFG0_tXPDLL_MASK (0xf << ESDCTL_V4_ESDCFG0_tXPDLL_SHIFT) +#define ESDCTL_V4_ESDCFG0_tFAW_SHIFT 4 +#define ESDCTL_V4_ESDCFG0_tFAW_MASK (0x1f << ESDCTL_V4_ESDCFG0_tFAW_SHIFT) +#define ESDCTL_V4_ESDCFG0_tCL_SHIFT 0 +#define ESDCTL_V4_ESDCFG0_tCL_MASK (0xf << ESDCTL_V4_ESDCFG0_tCL_SHIFT) + +#define ESDCTL_V4_ESDCFG1_tRCD_SHIFT 29 +#define ESDCTL_V4_ESDCFG1_tRCD_MASK (0x7 << ESDCTL_V4_ESDCFG1_tRCD_SHIFT) +#define ESDCTL_V4_ESDCFG1_tRP_SHIFT 26 +#define ESDCTL_V4_ESDCFG1_tRP_MASK (0x7 << ESDCTL_V4_ESDCFG1_tRP_SHIFT) +#define ESDCTL_V4_ESDCFG1_tRC_SHIFT 21 +#define ESDCTL_V4_ESDCFG1_tRC_MASK (0x1f << ESDCTL_V4_ESDCFG1_tRC_SHIFT) +#define ESDCTL_V4_ESDCFG1_tRAS_SHIFT 16 +#define ESDCTL_V4_ESDCFG1_tRAS_MASK (0x1f << ESDCTL_V4_ESDCFG1_tRAS_SHIFT) +#define ESDCTL_V4_ESDCFG1_tRPA_SHIFT 15 +#define ESDCTL_V4_ESDCFG1_tRPA_MASK (0x1 << ESDCTL_V4_ESDCFG1_tRPA_SHIFT) +#define ESDCTL_V4_ESDCFG1_tWR_SHIFT 9 +#define ESDCTL_V4_ESDCFG1_tWR_MASK (0x7 << ESDCTL_V4_ESDCFG1_tWR_SHIFT) +#define ESDCTL_V4_ESDCFG1_tMRD_SHIFT 5 +#define ESDCTL_V4_ESDCFG1_tMRD_MASK (0xf << ESDCTL_V4_ESDCFG1_tMRD_SHIFT) +#define ESDCTL_V4_ESDCFG1_tCWL_SHIFT 0 +#define ESDCTL_V4_ESDCFG1_tCWL_MASK (0x7 << ESDCTL_V4_ESDCFG1_tCWL_SHIFT) + +#define ESDCTL_V4_ESDCFG2_tDLLK_SHIFT 16 +#define ESDCTL_V4_ESDCFG2_tDLLK_MASK (0x1ff << ESDCTL_V4_ESDCFG2_tDLLK_SHIFT) +#define ESDCTL_V4_ESDCFG2_tRTP_SHIFT 6 +#define ESDCTL_V4_ESDCFG2_tRTP_MASK (0x7 << ESDCTL_V4_ESDCFG2_tRTP_SHIFT) +#define ESDCTL_V4_ESDCFG2_tWTR_SHIFT 3 +#define ESDCTL_V4_ESDCFG2_tWTR_MASK (0x7 << ESDCTL_V4_ESDCFG2_tWTR_SHIFT) +#define ESDCTL_V4_ESDCFG2_tRRD_SHIFT 0 +#define ESDCTL_V4_ESDCFG2_tRRD_MASK (0x7 << ESDCTL_V4_ESDCFG2_tRRD_SHIFT) + +#define ESDCTL_V4_ESDRWD_tDAI_SHIFT 16 +#define ESDCTL_V4_ESDRWD_tDAI_MASK (0x1fff << ESDCTL_V4_ESDRWD_tDAI_SHIFT) +#define ESDCTL_V4_ESDRWD_RTW_SAME_SHIFT 12 +#define ESDCTL_V4_ESDRWD_RTW_SAME_MASK (0x7 << ESDCTL_V4_ESDRWD_RTW_SAME_SHIFT) +#define ESDCTL_V4_ESDRWD_WTR_DIFF_SHIFT 9 +#define ESDCTL_V4_ESDRWD_WTR_DIFF_MASK (0x7 << ESDCTL_V4_ESDRWD_WTR_DIFF_SHIFT) +#define ESDCTL_V4_ESDRWD_WTW_DIFF_SHIFT 6 +#define ESDCTL_V4_ESDRWD_WTW_DIFF_MASK (0x7 << ESDCTL_V4_ESDRWD_WTW_DIFF_SHIFT) +#define ESDCTL_V4_ESDRWD_RTW_DIFF_SHIFT 3 +#define ESDCTL_V4_ESDRWD_RTW_DIFF_MASK (0x7 << ESDCTL_V4_ESDRWD_RTW_DIFF_SHIFT) +#define ESDCTL_V4_ESDRWD_RTR_DIFF_SHIFT 0 +#define ESDCTL_V4_ESDRWD_RTR_DIFF_MASK (0x7 << ESDCTL_V4_ESDRWD_RTR_DIFF_SHIFT) + +#define ESDCTL_V4_ESDOR_tXPR_SHIFT 16 +#define ESDCTL_V4_ESDOR_tXPR_MASK (0xff << ESDCTL_V4_ESDOR_tXPR_SHIFT) +#define ESDCTL_V4_ESDOR_SDE_to_RST_SHIFT 8 +#define ESDCTL_V4_ESDOR_SDE_to_RST_MASK (0x3f << ESDCTL_V4_ESDOR_SDE_to_RST_SHIFT) +#define ESDCTL_V4_ESDOR_RST_to_CKE_SHIFT 0 +#define ESDCTL_V4_ESDOR_RST_to_CKE_MASK (0x3f << ESDCTL_V4_ESDOR_RST_to_CKE_SHIFT) + +#define ESDCTL_V4_ESDOTC_tAOFPD_SHIFT 27 +#define ESDCTL_V4_ESDOTC_tAOFPD_MASK (0x7 << ESDCTL_V4_ESDOTC_tAOFPD_SHIFT) +#define ESDCTL_V4_ESDOTC_tAONPD_SHIFT 24 +#define ESDCTL_V4_ESDOTC_tAONPD_MASK (0x7 << ESDCTL_V4_ESDOTC_tAONPD_SHIFT) +#define ESDCTL_V4_ESDOTC_tANPD_SHIFT 20 +#define ESDCTL_V4_ESDOTC_tANPD_MASK (0xf << ESDCTL_V4_ESDOTC_tANPD_SHIFT) +#define ESDCTL_V4_ESDOTC_tAXPD_SHIFT 16 +#define ESDCTL_V4_ESDOTC_tAXPD_MASK (0xf << ESDCTL_V4_ESDOTC_tAXPD_SHIFT) +#define ESDCTL_V4_ESDOTC_tODTLon_SHIFT 12 +#define ESDCTL_V4_ESDOTC_tODTLon_MASK (0x7 << ESDCTL_V4_ESDOTC_tODTLon_SHIFT) +#define ESDCTL_V4_ESDOTC_tODT_idle_off_SHIFT 4 +#define ESDCTL_V4_ESDOTC_tODT_idle_off_MASK (0x1f << ESDCTL_V4_ESDOTC_tODT_idle_off_SHIFT) + +#define ESDCTL_V4_ESDPDC_PRCT1_SHIFT 28 +#define ESDCTL_V4_ESDPDC_PRCT1_MASK (0x7 << ESDCTL_V4_ESDPDC_PRCT1_SHIFT) +#define ESDCTL_V4_ESDPDC_PRCT0_SHIFT 24 +#define ESDCTL_V4_ESDPDC_PRCT0_MASK (0x7 << ESDCTL_V4_ESDPDC_PRCT0_SHIFT) +#define ESDCTL_V4_ESDPDC_tCKE_SHIFT 16 +#define ESDCTL_V4_ESDPDC_tCKE_MASK (0x7 << ESDCTL_V4_ESDPDC_tCKE_SHIFT) +#define ESDCTL_V4_ESDPDC_PWDT1_SHIFT 12 +#define ESDCTL_V4_ESDPDC_PWDT1_MASK (0xf << ESDCTL_V4_ESDPDC_PWDT1_SHIFT) +#define ESDCTL_V4_ESDPDC_PWDT0_SHIFT 8 +#define ESDCTL_V4_ESDPDC_PWDT0_MASK (0xf << ESDCTL_V4_ESDPDC_PWDT0_SHIFT) +#define ESDCTL_V4_ESDPDC_SLOW_PD 0x00000080 +#define ESDCTL_V4_ESDPDC_BOTH_CS_PD 0x00000040 +#define ESDCTL_V4_ESDPDC_tCKSRX_SHIFT 3 +#define ESDCTL_V4_ESDPDC_tCKSRX_MASK (0x7 << ESDCTL_V4_ESDPDC_tCKSRX_SHIFT) +#define ESDCTL_V4_ESDPDC_tCKSRE_SHIFT 0 +#define ESDCTL_V4_ESDPDC_tCKSRE_MASK (0x7 << ESDCTL_V4_ESDPDC_tCKSRE_SHIFT) + +#define ESDCTL_V4_ESDPDC_PRCT_DISABLE 0x0 +#define ESDCTL_V4_ESDPDC_PRCT_2 0x1 +#define ESDCTL_V4_ESDPDC_PRCT_4 0x2 +#define ESDCTL_V4_ESDPDC_PRCT_8 0x3 +#define ESDCTL_V4_ESDPDC_PRCT_16 0x4 +#define ESDCTL_V4_ESDPDC_PRCT_32 0x5 +#define ESDCTL_V4_ESDPDC_PRCT_64 0x6 +#define ESDCTL_V4_ESDPDC_PRCT_128 0x7 + +#define ESDCTL_V4_ESDPDC_PWDT_DISABLE 0x0 +#define ESDCTL_V4_ESDPDC_PWDT_16 0x1 +#define ESDCTL_V4_ESDPDC_PWDT_32 0x2 +#define ESDCTL_V4_ESDPDC_PWDT_64 0x3 +#define ESDCTL_V4_ESDPDC_PWDT_128 0x4 +#define ESDCTL_V4_ESDPDC_PWDT_256 0x5 +#define ESDCTL_V4_ESDPDC_PWDT_512 0x6 +#define ESDCTL_V4_ESDPDC_PWDT_1024 0x7 +#define ESDCTL_V4_ESDPDC_PWDT_2048 0x8 +#define ESDCTL_V4_ESDPDC_PWDT_4096 0x9 +#define ESDCTL_V4_ESDPDC_PWDT_8192 0xa +#define ESDCTL_V4_ESDPDC_PWDT_16384 0xb +#define ESDCTL_V4_ESDPDC_PWDT_32768 0xc + +#define ESDCTL_V4_ESDREF_REF_CNT_SHIFT 16 +#define ESDCTL_V4_ESDREF_REF_CNT_MASK (0xffff << ESDCTL_V4_ESDREF_REF_CNT_SHIFT) +#define ESDCTL_V4_ESDREF_REF_SEL_MASK 0x0000c000 +#define ESDCTL_V4_ESDREF_REF_SEL_64K 0x00000000 +#define ESDCTL_V4_ESDREF_REF_SEL_32K 0x00001000 +#define ESDCTL_V4_ESDREF_REF_SEL_REFCNT 0x00002000 +#define ESDCTL_V4_ESDREF_REFR_SHIFT 11 +#define ESDCTL_V4_ESDREF_REFR_MASK (0x7 << ESDCTL_V4_ESDREF_REFR_SHIFT) +#define ESDCTL_V4_ESDREF_START_REF 0x00000001 + +#define ESDCTL_V4_ESDZQHWC_ZQ_PARA_EN 0x04000000 +#define ESDCTL_V4_ESDZQHWC_TZQ_CS_SHIFT 23 +#define ESDCTL_V4_ESDZQHWC_TZQ_CS_MASK (0x7 << ESDCTL_V4_ESDZQHWC_TZQ_CS_SHIFT) +#define ESDCTL_V4_ESDZQHWC_TZQ_OPER_SHIFT 20 +#define ESDCTL_V4_ESDZQHWC_TZQ_OPER_MASK (0x7 << ESDCTL_V4_ESDZQHWC_TZQ_OPER_SHIFT) +#define ESDCTL_V4_ESDZQHWC_TZQ_INIT_SHIFT 17 +#define ESDCTL_V4_ESDZQHWC_TZQ_INIT_MASK (0x7 << ESDCTL_V4_ESDZQHWC_TZQ_INIT_SHIFT) +#define ESDCTL_V4_ESDZQHWC_ZQ_HW_FOR 0x00010000 +#define ESDCTL_V4_ESDZQHWC_ZQ_HW_PD_RES_SHIFT 11 +#define ESDCTL_V4_ESDZQHWC_ZQ_HW_PD_RES_MASK (0x1f << ESDCTL_V4_ESDZQHWC_ZQ_HW_PD_RES_SHIFT) +#define ESDCTL_V4_ESDZQHWC_ZQ_HW_PU_RES_SHIFT 6 +#define ESDCTL_V4_ESDZQHWC_ZQ_HW_PU_RES_MASK (0x1f << ESDCTL_V4_ESDZQHWC_ZQ_HW_PU_RES_SHIFT) +#define ESDCTL_V4_ESDZQHWC_ZQ_HW_PER_SHIFT 2 +#define ESDCTL_V4_ESDZQHWC_ZQ_HW_PER_MASK (0xf << ESDCTL_V4_ESDZQHWC_ZQ_HW_PER_SHIFT) +#define ESDCTL_V4_ESDZQHWC_ZQ_MODE_SHIFT 0 +#define ESDCTL_V4_ESDZQHWC_ZQ_MODE_MASK (0x3 << ESDCTL_V4_ESDZQHWC_ZQ_MODE_SHIFT) + +#define ESDCTL_V4_ESDZQHWC_32CYC 0x0 +#define ESDCTL_V4_ESDZQHWC_64CYC 0x1 +#define ESDCTL_V4_ESDZQHWC_128CYC 0x2 +#define ESDCTL_V4_ESDZQHWC_256CYC 0x3 +#define ESDCTL_V4_ESDZQHWC_512CYC 0x4 +#define ESDCTL_V4_ESDZQHWC_1024CYC 0x5 + +#define ESDCTL_V4_ESDZQHWC_ZQ_MODE_NO_CAL (0x0 << ESDCTL_V4_ESDZQHWC_ZQ_MODE_SHIFT) +#define ESDCTL_V4_ESDZQHWC_ZQ_MODE_BOTH_EXIT (0x1 << ESDCTL_V4_ESDZQHWC_ZQ_MODE_SHIFT) +#define ESDCTL_V4_ESDZQHWC_ZQ_MODE_EXTERNAL_PER (0x2 << ESDCTL_V4_ESDZQHWC_ZQ_MODE_SHIFT) +#define ESDCTL_V4_ESDZQHWC_ZQ_MODE_BOTH_PER (0x3 << ESDCTL_V4_ESDZQHWC_ZQ_MODE_SHIFT) + +#define ESDCTL_V4_ESDODTC_ODT3_INT_RES_SHIFT 16 +#define ESDCTL_V4_ESDODTC_ODT3_INT_RES_MASK (0x7 << ESDCTL_V4_ESDODTC_ODT3_INT_RES_SHIFT) +#define ESDCTL_V4_ESDODTC_ODT2_INT_RES_SHIFT 12 +#define ESDCTL_V4_ESDODTC_ODT2_INT_RES_MASK (0x7 << ESDCTL_V4_ESDODTC_ODT2_INT_RES_SHIFT) +#define ESDCTL_V4_ESDODTC_ODT1_INT_RES_SHIFT 8 +#define ESDCTL_V4_ESDODTC_ODT1_INT_RES_MASK (0x7 << ESDCTL_V4_ESDODTC_ODT1_INT_RES_SHIFT) +#define ESDCTL_V4_ESDODTC_ODT0_INT_RES_SHIFT 4 +#define ESDCTL_V4_ESDODTC_ODT0_INT_RES_MASK (0x7 << ESDCTL_V4_ESDODTC_ODT0_INT_RES_SHIFT) +#define ESDCTL_V4_ESDODTC_ODT_RD_ACT_EN 0x00000008 +#define ESDCTL_V4_ESDODTC_ODT_RD_PAS_EN 0x00000004 +#define ESDCTL_V4_ESDODTC_ODT_WR_ACT_EN 0x00000002 +#define ESDCTL_V4_ESDODTC_ODT_WR_PAS_EN 0x00000001 + +#define ESDCTL_V4_ESDODTC_RTT_DISABLE 0x0 +#define ESDCTL_V4_ESDODTC_RTT_60 0x1 +#define ESDCTL_V4_ESDODTC_RTT_120 0x2 +#define ESDCTL_V4_ESDODTC_RTT_40 0x3 +#define ESDCTL_V4_ESDODTC_RTT_20 0x4 +#define ESDCTL_V4_ESDODTC_RTT_30 0x5 + +#define ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT 16 +#define ESDCTL_V4_ESDSCR_CMD_ADDR_MASK (0xffff << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_ESDSCR_CON_REQ 0x00008000 +#define ESDCTL_V4_ESDSCR_CON_ACK 0x00004000 +#define ESDCTL_V4_ESDSCR_MRR_DATA_VALID 0x00000400 +#define ESDCTL_V4_ESDSCR_WL_EN 0x00000200 +#define ESDCTL_V4_ESDSCR_DLL_RST1 0x00000100 +#define ESDCTL_V4_ESDSCR_DLL_RST0 0x00000080 +#define ESDCTL_V4_ESDSCR_CMD_SHIFT 4 +#define ESDCTL_V4_ESDSCR_CMD_MASK (0x7 << ESDCTL_V4_ESDSCR_CMD_SHIFT) +#define ESDCTL_V4_ESDSCR_CMD_NOP (0x0 << ESDCTL_V4_ESDSCR_CMD_SHIFT) +#define ESDCTL_V4_ESDSCR_CMD_PRE_ALL (0x1 << ESDCTL_V4_ESDSCR_CMD_SHIFT) +#define ESDCTL_V4_ESDSCR_CMD_AREFRESH (0x2 << ESDCTL_V4_ESDSCR_CMD_SHIFT) +#define ESDCTL_V4_ESDSCR_CMD_LMR (0x3 << ESDCTL_V4_ESDSCR_CMD_SHIFT) +#define ESDCTL_V4_ESDSCR_CMD_ZQCALIB_OLD (0x4 << ESDCTL_V4_ESDSCR_CMD_SHIFT) +#define ESDCTL_V4_ESDSCR_CMD_PRE_ALL_OPEN (0x5 << ESDCTL_V4_ESDSCR_CMD_SHIFT) +#define ESDCTL_V4_ESDSCR_CMD_MRR (0x6 << ESDCTL_V4_ESDSCR_CMD_SHIFT) +#define ESDCTL_V4_ESDSCR_CMD_CS 0x00000008 +#define ESDCTL_V4_ESDSCR_CMD_CS0 0x00000000 +#define ESDCTL_V4_ESDSCR_CMD_CS1 0x00000008 +#define ESDCTL_V4_ESDSCR_CMD_BA_SHIFT 0 +#define ESDCTL_V4_ESDSCR_CMD_BA_MASK (0x7 << ESDCTL_V4_ESDSCR_CMD_BA_SHIFT) + +#define ESDCTL_V4_PDCMPR2_PHY_CA_DL_SHIFT 24 +#define ESDCTL_V4_PDCMPR2_PHY_CA_DL_MASK (0x7f << ESDCTL_V4_PDCMPR2_PHY_CA_DL_SHIFT) +#define ESDCTL_V4_PDCMPR2_CA_DL_ABS_SHIFT 16 +#define ESDCTL_V4_PDCMPR2_CA_DL_ABS_MASK (0x7f << ESDCTL_V4_PDCMPR2_CA_DL_ABS_SHIFT) +#define ESDCTL_V4_PDCMPR2_RLPAT 0x4 +#define ESDCTL_V4_PDCMPR2_RLPAT_0 0x0 +#define ESDCTL_V4_PDCMPR2_RLPAT_1 0x4 +#define ESDCTL_V4_PDCMPR2_MPR_FULL_CMP 0x2 +#define ESDCTL_V4_PDCMPR2_MPR_CMP 0x1 + +#define ESDCTL_V4_WLGCR_WL_HW_ERR3 (1 << 11) +#define ESDCTL_V4_WLGCR_WL_HW_ERR2 (1 << 10) +#define ESDCTL_V4_WLGCR_WL_HW_ERR1 (1 << 9) +#define ESDCTL_V4_WLGCR_WL_HW_ERR0 (1 << 8) +#define ESDCTL_V4_WLGCR_WL_SW_ERR3 (1 << 7) +#define ESDCTL_V4_WLGCR_WL_SW_ERR2 (1 << 6) +#define ESDCTL_V4_WLGCR_WL_SW_ERR1 (1 << 5) +#define ESDCTL_V4_WLGCR_WL_SW_ERR0 (1 << 4) +#define ESDCTL_V4_WLGCR_SW_WL_CNT_EN (1 << 2) +#define ESDCTL_V4_WLGCR_SW_WL_EN (1 << 1) +#define ESDCTL_V4_WLGCR_HW_WL_EN (1 << 1) + +#define ESDCTL_V4_RDDLHWCTL_HW_RDL_CMP_CYC (1 << 5) +#define ESDCTL_V4_RDDLHWCTL_HW_RDL_EN (1 << 4) +#define ESDCTL_V4_RDDLHWCTL_HW_RDL_ERR3 (1 << 3) +#define ESDCTL_V4_RDDLHWCTL_HW_RDL_ERR2 (1 << 2) +#define ESDCTL_V4_RDDLHWCTL_HW_RDL_ERR1 (1 << 1) +#define ESDCTL_V4_RDDLHWCTL_HW_RDL_ERR0 (1 << 0) + +#define ESDCTL_V4_WRDLHWCTL_HW_WDL_CMP_CYC (1 << 5) +#define ESDCTL_V4_WRDLHWCTL_HW_WDL_EN (1 << 4) +#define ESDCTL_V4_WRDLHWCTL_HW_WDL_ERR3 (1 << 3) +#define ESDCTL_V4_WRDLHWCTL_HW_WDL_ERR2 (1 << 2) +#define ESDCTL_V4_WRDLHWCTL_HW_WDL_ERR1 (1 << 1) +#define ESDCTL_V4_WRDLHWCTL_HW_WDL_ERR0 (1 << 0) + +#define ESDCTL_V4_DDR3_REG_MR0 (0x0 << ESDCTL_V4_ESDSCR_CMD_BA_SHIFT) +#define ESDCTL_V4_DDR3_REG_MR1 (0x1 << ESDCTL_V4_ESDSCR_CMD_BA_SHIFT) +#define ESDCTL_V4_DDR3_REG_MR2 (0x2 << ESDCTL_V4_ESDSCR_CMD_BA_SHIFT) +#define ESDCTL_V4_DDR3_REG_MR3 (0x3 << ESDCTL_V4_ESDSCR_CMD_BA_SHIFT) + +#define ESDCTL_V4_DDR3_MR0_PPD (0x1000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_PPD_SLOW (0x0000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_PPD_FAST (0x1000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_SHIFT (9 + ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_MASK (0x7 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_16 (0x0 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_5 (0x1 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_6 (0x2 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_7 (0x3 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_8 (0x4 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_10 (0x5 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_12 (0x6 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_WR_14 (0x7 << ESDCTL_V4_DDR3_MR0_WR_SHIFT) +#define ESDCTL_V4_DDR3_DLL_RESET (0x0100 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_TM (0x0080 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_TM_NORMAL (0x0000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_TM_TEST (0x0080 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_SHIFT (2 + ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_MASK (0x74 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_5 (0x10 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_6 (0x20 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_7 (0x30 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_8 (0x40 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_9 (0x50 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_10 (0x60 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_11 (0x70 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_12 (0x04 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_13 (0x14 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_14 (0x24 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_15 (0x34 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_CL_16 (0x44 << ESDCTL_V4_DDR3_MR0_CL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_RBT (0x0008 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_RBT_NIBBLE (0x0000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_RBT_INTERL (0x0008 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_BL_SHIFT (0 + ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR0_BL_MASK (0x3 << ESDCTL_V4_DDR3_MR0_BL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_BL_FIXED8 (0x0 << ESDCTL_V4_DDR3_MR0_BL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_BL_DYNAMIC (0x1 << ESDCTL_V4_DDR3_MR0_BL_SHIFT) +#define ESDCTL_V4_DDR3_MR0_BL_FIXED4 (0x2 << ESDCTL_V4_DDR3_MR0_BL_SHIFT) + +#define ESDCTL_V4_DDR3_MR1_QOFF (0x1000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_TDQS (0x0800 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_WL (0x0080 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_AL_SHIFT (3 + ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_AL_MASK (0x3 << ESDCTL_V4_DDR3_MR1_AL_SHIFT) +#define ESDCTL_V4_DDR3_MR1_AL_DISABLE (0x0 << ESDCTL_V4_DDR3_MR1_AL_SHIFT) +#define ESDCTL_V4_DDR3_MR1_AL_CL1 (0x1 << ESDCTL_V4_DDR3_MR1_AL_SHIFT) +#define ESDCTL_V4_DDR3_MR1_AL_CL2 (0x2 << ESDCTL_V4_DDR3_MR1_AL_SHIFT) +#define ESDCTL_V4_DDR3_MR1_DLL_DISABLE (0x0001 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_RTTN_MASK (0x0244 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_RTTN_DIS (0x0000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_RTTN_RZQ4 (0x0004 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_RTTN_RZQ2 (0x0040 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_RTTN_RZQ6 (0x0044 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_RTTN_RZQ12 (0x0200 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_RTTN_RZQ8 (0x0204 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_ODIC_MASK (0x0022 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_ODIC_RZQ6 (0x0000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR1_ODIC_RZQ7 (0x0002 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) + +#define ESDCTL_V4_DDR3_MR2_RTTWR_SHIFT (9 + ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_RTTWR_MASK (0x3 << ESDCTL_V4_DDR3_MR2_RTTWR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_RTTWR_OFF (0x0 << ESDCTL_V4_DDR3_MR2_RTTWR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_RTTWR_RZQ4 (0x1 << ESDCTL_V4_DDR3_MR2_RTTWR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_RTTWR_RZQ2 (0x2 << ESDCTL_V4_DDR3_MR2_RTTWR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_SRT (0x0080 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_SRT_NORMAL (0x0000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_SRT_EXTENDED (0x0080 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_ASR_ENABLE (0x0040 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_SHIFT (3 + ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_MASK (0x7 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_5 (0x0 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_6 (0x1 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_7 (0x2 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_8 (0x3 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_9 (0x4 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_10 (0x5 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_11 (0x6 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_CWL_12 (0x7 << ESDCTL_V4_DDR3_MR2_CWL_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_SHIFT (0 + ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_MASK (0x7 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_1_1 (0x0 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_1_2L (0x1 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_1_4L (0x2 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_1_8L (0x3 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_3_4L (0x4 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_1_2H (0x5 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_1_4H (0x6 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) +#define ESDCTL_V4_DDR3_MR2_PASR_1_8H (0x7 << ESDCTL_V4_DDR3_MR2_PASR_SHIFT) + +#define ESDCTL_V4_DDR3_MR3_MPR_DISABLE (0x0000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR3_MPR_ENABLE (0x0004 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR3_MPR_PATTERN (0x0000 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR3_MPR_RFU1 (0x0001 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR3_MPR_RFU2 (0x0002 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) +#define ESDCTL_V4_DDR3_MR3_MPR_RFU3 (0x0003 << ESDCTL_V4_ESDSCR_CMD_ADDR_SHIFT) + +#ifndef __ASSEMBLY__ + +void imx_esdctlv4_do_write_leveling(void); +void imx_esdctlv4_do_dqs_gating(void); +void imx_esdctlv4_do_zq_calibration(void); +void imx_esdctlv4_start_ddr3_sdram(int cs); +void imx_esdctlv4_do_read_delay_line_calibration(void); +void imx_esdctlv4_do_write_delay_line_calibration(void); +void imx_esdctlv4_set_tRFC_timing(void); +void imx_esdctlv4_detect_sdrams(void); +void imx_esdctlv4_init(void); + +#endif + +#endif /* __MACH_ESDCTL_V4_H */ diff --git a/arch/arm/mach-imx/include/mach/esdctl.h b/arch/arm/mach-imx/include/mach/esdctl.h index b601ff80c7..1a265c8e45 100644 --- a/arch/arm/mach-imx/include/mach/esdctl.h +++ b/arch/arm/mach-imx/include/mach/esdctl.h @@ -28,6 +28,7 @@ #define ESDCTL0_DSIZ_31_16 (0 << 16) #define ESDCTL0_DSIZ_15_0 (1 << 16) #define ESDCTL0_DSIZ_31_0 (2 << 16) +#define ESDCTL0_DSIZ_MASK (3 << 16) #define ESDCTL0_REF1 (1 << 13) #define ESDCTL0_REF2 (2 << 13) #define ESDCTL0_REF4 (3 << 13) diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h index 39bb7e351e..5e600a351c 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -20,6 +20,7 @@ int imx_25_35_boot_save_loc(unsigned int ctrl, unsigned int type); void imx_27_boot_save_loc(void __iomem *sysctrl_base); int imx51_boot_save_loc(void __iomem *src_base); int imx53_boot_save_loc(void __iomem *src_base); +int imx6_boot_save_loc(void __iomem *src_base); /* There's a off-by-one betweem the gpio bank number and the gpiochip */ /* range e.g. GPIO_1_5 is gpio 5 under linux */ diff --git a/arch/arm/mach-imx/include/mach/imx1-regs.h b/arch/arm/mach-imx/include/mach/imx1-regs.h index df6ede5b24..69e57e3cfd 100644 --- a/arch/arm/mach-imx/include/mach/imx1-regs.h +++ b/arch/arm/mach-imx/include/mach/imx1-regs.h @@ -4,6 +4,9 @@ #define MX1_IO_BASE_ADDR 0x00200000 #define MX1_IO_SIZE SZ_1M +#define MX1_CSD0_BASE_ADDR 0x08000000 +#define MX1_CSD1_BASE_ADDR 0x0c000000 + #define MX1_CS0_PHYS 0x10000000 #define MX1_CS0_SIZE 0x02000000 diff --git a/arch/arm/mach-imx/include/mach/imx5.h b/arch/arm/mach-imx/include/mach/imx5.h index 4c19d28001..cd0a34728e 100644 --- a/arch/arm/mach-imx/include/mach/imx5.h +++ b/arch/arm/mach-imx/include/mach/imx5.h @@ -3,7 +3,17 @@ void imx51_init_lowlevel(unsigned int cpufreq_mhz); void imx53_init_lowlevel(unsigned int cpufreq_mhz); -void imx5_setup_pll(void __iomem *base, int freq, u32 op, u32 mfd, u32 mfn); void imx5_init_lowlevel(void); +void imx5_setup_pll(void __iomem *base, int freq, u32 op, u32 mfd, u32 mfn); + +#define imx5_setup_pll_1000(base) imx5_setup_pll((base), 1000, ((10 << 4) + ((1 - 1) << 0)), (12 - 1), 5) +#define imx5_setup_pll_800(base) imx5_setup_pll((base), 800, (( 8 << 4) + ((1 - 1) << 0)), (3 - 1), 1) +#define imx5_setup_pll_665(base) imx5_setup_pll((base), 665, (( 6 << 4) + ((1 - 1) << 0)), (96 - 1), 89) +#define imx5_setup_pll_600(base) imx5_setup_pll((base), 600, (( 6 << 4) + ((1 - 1) << 0)), ( 4 - 1), 1) +#define imx5_setup_pll_455(base) imx5_setup_pll((base), 455, (( 9 << 4) + ((2 - 1) << 0)), (48 - 1), 23) +#define imx5_setup_pll_400(base) imx5_setup_pll((base), 400, (( 8 << 4) + ((2 - 1) << 0)), (3 - 1), 1) +#define imx53_setup_pll_216(base) imx5_setup_pll((base), 216, (( 8 << 4) + ((2 - 1) << 0)), (1 - 1), 1) +#define imx51_setup_pll_216(base) imx5_setup_pll((base), 216, (( 6 << 4) + ((3 - 1) << 0)), (4 - 1), 3) + #endif /* __MACH_MX53_H */ diff --git a/arch/arm/mach-imx/include/mach/imx53-regs.h b/arch/arm/mach-imx/include/mach/imx53-regs.h index 8025e97720..473b9428d0 100644 --- a/arch/arm/mach-imx/include/mach/imx53-regs.h +++ b/arch/arm/mach-imx/include/mach/imx53-regs.h @@ -3,6 +3,8 @@ #define MX53_IROM_BASE_ADDR 0x0 +#define MX53_SATA_BASE_ADDR 0x10000000 + /* * SPBA global module enabled #0 */ diff --git a/arch/arm/mach-imx/include/mach/imx6-regs.h b/arch/arm/mach-imx/include/mach/imx6-regs.h index 716e6b4f25..7c72cba838 100644 --- a/arch/arm/mach-imx/include/mach/imx6-regs.h +++ b/arch/arm/mach-imx/include/mach/imx6-regs.h @@ -105,4 +105,6 @@ #define MX6_IP2APB_USBPHY1_BASE_ADDR (MX6_AIPS2_OFF_BASE_ADDR + 0x78000) #define MX6_IP2APB_USBPHY2_BASE_ADDR (MX6_AIPS2_OFF_BASE_ADDR + 0x7C000) +#define MX6_SATA_BASE_ADDR 0x02200000 + #endif /* __MACH_IMX6_REGS_H */ diff --git a/arch/arm/mach-mxs/speed-imx28.c b/arch/arm/mach-mxs/speed-imx28.c index df55f64c24..2cab42d8f5 100644 --- a/arch/arm/mach-mxs/speed-imx28.c +++ b/arch/arm/mach-mxs/speed-imx28.c @@ -121,8 +121,7 @@ unsigned imx_get_xtalclk(void) unsigned imx_get_fecclk(void) { - /* this PLL always runs at 50 MHz */ - return 50000000; + return imx_get_hclk(); } diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig index 81f6127e0a..b9f3dff063 100644 --- a/arch/arm/mach-omap/Kconfig +++ b/arch/arm/mach-omap/Kconfig @@ -75,7 +75,7 @@ config OMAP_BUILD_SPI bool help Say Y here if you want to build an barebox.spi image as used - on the AM35xx chips when booting form SPI NOR flash. + on the AM35xx chips when booting from SPI NOR flash. config ARCH_TEXT_BASE hex @@ -89,7 +89,7 @@ config OMAP4_USBBOOT help Say Y here if you want to be able to boot an OMAP4 cpu from USB. You need the utility program omap4_usbboot to boot from USB. - Please read oamp4_usb_booting.txt for more information. + Please read omap4_usb_booting.txt for more information. config BOARDINFO default "Archos G9" if MACH_ARCHOSG9 @@ -115,14 +115,14 @@ config MACH_BEAGLE select HAVE_NOSHELL select HAVE_DEFAULT_ENVIRONMENT_NEW depends on ARCH_OMAP3 - help + help Say Y here if you are using Beagle Board config MACH_OMAP3EVM bool "Texas Instrument's OMAP3 EVM" select HAVE_NOSHELL depends on ARCH_OMAP3 - help + help Say Y here if you are using OMAP3EVM config MACH_PANDA @@ -155,7 +155,7 @@ config MACH_PCAAL1 bool "Phytec phyCARD-A-L1" select HAVE_NOSHELL depends on ARCH_OMAP3 - help + help Say Y here if you are using a phyCARD-A-L1 PCA-A-L1 config MACH_PCAAXL2 diff --git a/arch/arm/mach-omap/devices-gpmc-nand.c b/arch/arm/mach-omap/devices-gpmc-nand.c index 129f91a617..42cb1b42bf 100644 --- a/arch/arm/mach-omap/devices-gpmc-nand.c +++ b/arch/arm/mach-omap/devices-gpmc-nand.c @@ -2,10 +2,6 @@ * @file * @brief GPMC specific NAND devices * - * FileName: arch/arm/boards/omap/devices-gpmc-nand.c - * - */ -/* * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -19,8 +15,8 @@ * 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 <console.h> #include <init.h> diff --git a/arch/arm/mach-omap/gpmc.c b/arch/arm/mach-omap/gpmc.c index 73d8c44a3b..4cfb7cf4ee 100644 --- a/arch/arm/mach-omap/gpmc.c +++ b/arch/arm/mach-omap/gpmc.c @@ -2,12 +2,8 @@ * @file * @brief Provide Generic GPMC configuration option * - * FileName: arch/arm/mach-omap/gpmc.c - * * This file contains the generic GPMC implementation * - */ -/* * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -21,8 +17,8 @@ * 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 <clock.h> #include <init.h> diff --git a/arch/arm/mach-omap/include/mach/clocks.h b/arch/arm/mach-omap/include/mach/clocks.h index b2b0c99bec..cbadec776a 100644 --- a/arch/arm/mach-omap/include/mach/clocks.h +++ b/arch/arm/mach-omap/include/mach/clocks.h @@ -2,13 +2,10 @@ * @file * @brief Generic Clock wrapper header. * - * FileName: include/asm-arm/arch-omap/clocks.h - * * This includes each of the architecture Clock definitions under it. * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz - */ -/* + * * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Richard Woodruff <r-woodruff2@ti.com> @@ -22,8 +19,8 @@ * 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 __OMAP_CLOCKS_H_ #define __OMAP_CLOCKS_H_ diff --git a/arch/arm/mach-omap/include/mach/control.h b/arch/arm/mach-omap/include/mach/control.h index 18064ba9c5..e03d8d573c 100644 --- a/arch/arm/mach-omap/include/mach/control.h +++ b/arch/arm/mach-omap/include/mach/control.h @@ -2,13 +2,10 @@ * @file * @brief This file contains the Control register defines * - * FileName: include/asm-arm/arch-omap/control.h - * * Originally from Linux kernel: * http://linux.omap.com/pub/kernel/3430zoom/linux-ldp-v1.0b.tar.gz * include/asm-arm/arch-omap/omap34xx.h - */ -/* + * * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -25,7 +22,6 @@ * 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 __ASM_ARCH_OMAP_CONTROL_H diff --git a/arch/arm/mach-omap/include/mach/debug_ll.h b/arch/arm/mach-omap/include/mach/debug_ll.h index c1fcc9d9b6..b2714c5aee 100644 --- a/arch/arm/mach-omap/include/mach/debug_ll.h +++ b/arch/arm/mach-omap/include/mach/debug_ll.h @@ -39,7 +39,7 @@ #define LSR (5 << 2) #define THR (0 << 2) -static inline void putc(char c) +static inline void PUTC_LL(char c) { /* Wait until there is space in the FIFO */ while ((readb(UART_BASE + LSR) & LSR_THRE) == 0); diff --git a/arch/arm/mach-omap/include/mach/gpmc.h b/arch/arm/mach-omap/include/mach/gpmc.h index 95c02dbaac..957ff55eff 100644 --- a/arch/arm/mach-omap/include/mach/gpmc.h +++ b/arch/arm/mach-omap/include/mach/gpmc.h @@ -2,15 +2,11 @@ * @file * @brief This file contains the GPMC's generic definitions * - * FileName: include/asm-arm/arch-omap/gpmc.h - * * OMAP's General Purpose Memory Controller(GPMC) provides features * allowing us to communicate with memory devices such as NOR, NAND, * OneNAND, SRAM etc.. This file defines certain generic parameters * allowing us to configure the same painlessly. * - */ -/* * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -31,7 +27,6 @@ * 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 __ASM_ARCH_OMAP_GPMC_H diff --git a/arch/arm/mach-omap/include/mach/gpmc_nand.h b/arch/arm/mach-omap/include/mach/gpmc_nand.h index 582fb36e8f..4a9346597c 100644 --- a/arch/arm/mach-omap/include/mach/gpmc_nand.h +++ b/arch/arm/mach-omap/include/mach/gpmc_nand.h @@ -2,14 +2,10 @@ * @file * @brief This file contains exported structure for NAND * - * FileName: include/asm-arm/arch-omap/gpmc_nand.h - * * OMAP's General Purpose Memory Controller (GPMC) has a NAND controller * embedded. this file provides the platform data structure required to * hook on to it. * - */ -/* * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> diff --git a/arch/arm/mach-omap/include/mach/intc.h b/arch/arm/mach-omap/include/mach/intc.h index 950f714d1d..6c53528db2 100644 --- a/arch/arm/mach-omap/include/mach/intc.h +++ b/arch/arm/mach-omap/include/mach/intc.h @@ -2,13 +2,10 @@ * @file * @brief This file contains the Interrupt controller register defines * - * FileName: include/asm-arm/arch-omap/intc.h - * * Originally from Linux kernel: * http://linux.omap.com/pub/kernel/3430zoom/linux-ldp-v1.0b.tar.gz * include/asm-arm/arch-omap/omap34xx.h - */ -/* + * * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -25,7 +22,6 @@ * 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 __ASM_ARCH_OMAP_INTC_H diff --git a/arch/arm/mach-omap/include/mach/omap3-clock.h b/arch/arm/mach-omap/include/mach/omap3-clock.h index 4f5a1d1bea..00ce6a5fda 100644 --- a/arch/arm/mach-omap/include/mach/omap3-clock.h +++ b/arch/arm/mach-omap/include/mach/omap3-clock.h @@ -2,12 +2,8 @@ * @file * @brief Contains the PRM and CM definitions * - * FileName: include/asm-arm/arch-omap/omap3-clock.h - * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz * - */ -/* * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Richard Woodruff <r-woodruff2@ti.com> @@ -21,8 +17,8 @@ * 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 _OMAP343X_CLOCKS_H_ #define _OMAP343X_CLOCKS_H_ diff --git a/arch/arm/mach-omap/include/mach/omap3-mux.h b/arch/arm/mach-omap/include/mach/omap3-mux.h index 133bcf8d34..d6fb9c393c 100644 --- a/arch/arm/mach-omap/include/mach/omap3-mux.h +++ b/arch/arm/mach-omap/include/mach/omap3-mux.h @@ -2,15 +2,12 @@ * @file * @brief Mux Configuration Register defines for OMAP3 * - * FileName: include/asm-arm/arch-omap/omap3-mux.h - * * This file defines the various Pin Mux registers * @see include/asm-arm/arch-omap/control.h * The @ref MUX_VAL macro uses the defines from this file * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz - */ -/* + * * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Syed Mohammed Khasim <x0khasim@ti.com> @@ -24,8 +21,8 @@ * 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 _ASM_ARCH_OMAP3_MUX_H_ #define _ASM_ARCH_OMAP3_MUX_H_ diff --git a/arch/arm/mach-omap/include/mach/omap3-silicon.h b/arch/arm/mach-omap/include/mach/omap3-silicon.h index 33e449b070..a655729f8f 100644 --- a/arch/arm/mach-omap/include/mach/omap3-silicon.h +++ b/arch/arm/mach-omap/include/mach/omap3-silicon.h @@ -4,15 +4,12 @@ * the TI OMAP34XX. For more info on OMAP34XX, * See http://focus.ti.com/pdfs/wtbu/swpu114g.pdf * - * FileName: include/asm-arm/arch-omap/omap3-silicon.h - * * OMAP34XX base address defines go here. * * Originally from Linux kernel: * http://linux.omap.com/pub/kernel/3430zoom/linux-ldp-v1.0b.tar.gz * include/asm-arm/arch-omap/omap3-silicon.h - */ -/* + * * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -29,7 +26,6 @@ * 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 __ASM_ARCH_OMAP3_H diff --git a/arch/arm/mach-omap/include/mach/omap3-smx.h b/arch/arm/mach-omap/include/mach/omap3-smx.h index 436e9afae2..f7fa4d2c66 100644 --- a/arch/arm/mach-omap/include/mach/omap3-smx.h +++ b/arch/arm/mach-omap/include/mach/omap3-smx.h @@ -2,13 +2,10 @@ * @file * @brief This file contains the SMX specific register definitions * - * FileName: include/asm-arm/arch-omap/omap3-smx.h - * * Originally from Linux kernel: * http://linux.omap.com/pub/kernel/3430zoom/linux-ldp-v1.0b.tar.gz * include/asm-arm/arch-omap/omap34xx.h - */ -/* + * * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -25,7 +22,6 @@ * 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 __ASM_ARCH_OMAP_SMX_H diff --git a/arch/arm/mach-omap/include/mach/omap_hsmmc.h b/arch/arm/mach-omap/include/mach/omap_hsmmc.h index a15f8e62a2..2055cccbd5 100644 --- a/arch/arm/mach-omap/include/mach/omap_hsmmc.h +++ b/arch/arm/mach-omap/include/mach/omap_hsmmc.h @@ -2,13 +2,10 @@ * @file * @brief This file contains exported structure for OMAP hsmmc * - * FileName: include/asm-arm/arch-omap/omap_hsmmc.h - * * OMAP3 and OMAP4 has a MMC/SD controller embedded. * This file provides the platform data structure required to * addapt to platform specialities. - */ -/* + * * (C) Copyright 2011 * Phytec Messtechnik GmbH, <www.phytec.de> * Juergen Kilb <j.kilb@phytec.de> diff --git a/arch/arm/mach-omap/include/mach/sdrc.h b/arch/arm/mach-omap/include/mach/sdrc.h index 406dc3210e..73031b9280 100644 --- a/arch/arm/mach-omap/include/mach/sdrc.h +++ b/arch/arm/mach-omap/include/mach/sdrc.h @@ -2,11 +2,8 @@ * @file * @brief This file contains the SDRC specific register definitions * - * FileName: include/asm-arm/arch-omap/sdrc.h - * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz - */ -/* + * * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * @@ -22,8 +19,6 @@ * 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 _ASM_ARCH_SDRC_H diff --git a/arch/arm/mach-omap/include/mach/sys_info.h b/arch/arm/mach-omap/include/mach/sys_info.h index 5d9b870877..e54791d54c 100644 --- a/arch/arm/mach-omap/include/mach/sys_info.h +++ b/arch/arm/mach-omap/include/mach/sys_info.h @@ -3,13 +3,10 @@ * @brief This file defines the macros apis which are useful for most OMAP * platforms. * - * FileName: include/asm-arm/arch-omap/sys_info.h - * * These are implemented by the System specific code in omapX-generic.c * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz - */ -/* + * * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Richard Woodruff <r-woodruff2@ti.com> @@ -23,7 +20,6 @@ * 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 __ASM_ARCH_SYS_INFO_H_ diff --git a/arch/arm/mach-omap/include/mach/syslib.h b/arch/arm/mach-omap/include/mach/syslib.h index ab88dcf829..fe8d71d802 100644 --- a/arch/arm/mach-omap/include/mach/syslib.h +++ b/arch/arm/mach-omap/include/mach/syslib.h @@ -2,13 +2,10 @@ * @file * @brief These Apis are OMAP independent support functions * - * FileName: include/asm-arm/arch-omap/syslib.h - * * Implemented by arch/arm/mach-omap/syslib.c * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz - */ -/* + * * (C) Copyright 2004-2008 * Texas Instruments, <www.ti.com> * Richard Woodruff <r-woodruff2@ti.com> @@ -22,8 +19,8 @@ * 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 __ASM_ARCH_OMAP_SYSLIB_H_ #define __ASM_ARCH_OMAP_SYSLIB_H_ #include <io.h> diff --git a/arch/arm/mach-omap/include/mach/timers.h b/arch/arm/mach-omap/include/mach/timers.h index e8dad9a60a..2df507d588 100644 --- a/arch/arm/mach-omap/include/mach/timers.h +++ b/arch/arm/mach-omap/include/mach/timers.h @@ -7,8 +7,6 @@ * Originally from Linux kernel: * http://linux.omap.com/pub/kernel/3430zoom/linux-ldp-v1.0b.tar.gz * - */ -/* * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -25,8 +23,8 @@ * 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 __ASM_ARCH_GPT_H #define __ASM_ARCH_GPT_H diff --git a/arch/arm/mach-omap/include/mach/wdt.h b/arch/arm/mach-omap/include/mach/wdt.h index e359e8b7d3..10cb1f4b5e 100644 --- a/arch/arm/mach-omap/include/mach/wdt.h +++ b/arch/arm/mach-omap/include/mach/wdt.h @@ -2,10 +2,6 @@ * @file * @brief This file contains the Watchdog timer specific register definitions * - * FileName: include/asm-arm/arch-omap/wdt.h - * - */ -/* * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -19,8 +15,8 @@ * 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 __ASM_ARCH_OMAP_WDT_H #define __ASM_ARCH_OMAP_WDT_H diff --git a/arch/arm/mach-omap/omap3_clock.c b/arch/arm/mach-omap/omap3_clock.c index cfac7bc17f..975bf455a9 100644 --- a/arch/arm/mach-omap/omap3_clock.c +++ b/arch/arm/mach-omap/omap3_clock.c @@ -2,8 +2,6 @@ * @file * @brief OMAP DPLL and various clock configuration * - * FileName: arch/arm/mach-omap/omap3_clock.c - * * @ref prcm_init This is the second level clock init for PRCM as defined in * clocks.h -- called from SRAM, or Flash (using temp SRAM stack). * @@ -16,8 +14,7 @@ * should be used, functions cannot use global variables/switch constructs. * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz - */ -/* + * * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Richard Woodruff <r-woodruff2@ti.com> @@ -31,7 +28,6 @@ * 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> diff --git a/arch/arm/mach-omap/omap3_core.S b/arch/arm/mach-omap/omap3_core.S index c3e4086c1f..ea55efd2b6 100644 --- a/arch/arm/mach-omap/omap3_core.S +++ b/arch/arm/mach-omap/omap3_core.S @@ -2,8 +2,6 @@ * @file * @brief Provide Architecture level Initialization * - * FileName: arch/arm/mach-omap/omap3_core.S - * * This provides OMAP3 Architecture initialization. Among these, * @li OMAP ROM Code is located in SRAM, we can piggy back on * the same addresses @@ -12,8 +10,6 @@ * functions. * @li Call architecture initialization function a_init * - */ -/* * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -27,7 +23,6 @@ * 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 <config.h> diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c index 7b6f1f9c41..7cfb3e4eb1 100644 --- a/arch/arm/mach-omap/omap3_generic.c +++ b/arch/arm/mach-omap/omap3_generic.c @@ -2,8 +2,6 @@ * @file * @brief Provide Generic implementations for OMAP3 architecture * - * FileName: arch/arm/mach-omap/omap3_generic.c - * * This file contains the generic implementations of various OMAP3 * relevant functions * For more info on OMAP34XX, see http://focus.ti.com/pdfs/wtbu/swpu114g.pdf @@ -12,8 +10,7 @@ * The implemented functions are present in sys_info.h * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz - */ -/* + * * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Richard Woodruff <r-woodruff2@ti.com> @@ -28,8 +25,8 @@ * 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 <init.h> #include <io.h> diff --git a/arch/arm/mach-omap/s32k_clksource.c b/arch/arm/mach-omap/s32k_clksource.c index 6ce0c6410b..2cfcfa9ed6 100644 --- a/arch/arm/mach-omap/s32k_clksource.c +++ b/arch/arm/mach-omap/s32k_clksource.c @@ -2,14 +2,10 @@ * @file * @brief Provide @ref clocksource functionality for OMAP * - * FileName: arch/arm/mach-omap/s32k_clksource.c - * * @ref clocksource provides a neat architecture. all we do is * To loop in with Sync 32Khz clock ticking away at 32768hz on OMAP. * Sync 32Khz clock is an always ON clock. * - */ -/* * (C) Copyright 2008 * Texas Instruments, <www.ti.com> * Nishanth Menon <x0nishan@ti.com> @@ -23,7 +19,6 @@ * 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> diff --git a/arch/arm/mach-omap/syslib.c b/arch/arm/mach-omap/syslib.c index 01b5cf2a8a..42da348c5a 100644 --- a/arch/arm/mach-omap/syslib.c +++ b/arch/arm/mach-omap/syslib.c @@ -2,14 +2,11 @@ * @file * @brief Provide OMAP independent utility APIs * - * FileName: arch/arm/mach-omap/syslib.c - * * Provide APIs which can be used from platform/architecture code * to operate on * * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz - */ -/* + * * (C) Copyright 2006-2008 * Texas Instruments, <www.ti.com> * Richard Woodruff <r-woodruff2@ti.com> @@ -23,7 +20,6 @@ * 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 <config.h> diff --git a/arch/arm/mach-tegra/include/mach/debug_ll.h b/arch/arm/mach-tegra/include/mach/debug_ll.h index 18024eb1c6..290ad5806f 100644 --- a/arch/arm/mach-tegra/include/mach/debug_ll.h +++ b/arch/arm/mach-tegra/include/mach/debug_ll.h @@ -31,7 +31,7 @@ #define lsr (5 << DEBUG_LL_UART_RSHFT) #define LSR_THRE 0x20 /* Xmit holding register empty */ -static inline void putc(char ch) +static inline void PUTC_LL(char ch) { while (!(__raw_readb(DEBUG_LL_UART_ADDR + lsr) & LSR_THRE)) ; diff --git a/arch/arm/mach-versatile/include/mach/debug_ll.h b/arch/arm/mach-versatile/include/mach/debug_ll.h index 20fbc7c7ab..f91812b12d 100644 --- a/arch/arm/mach-versatile/include/mach/debug_ll.h +++ b/arch/arm/mach-versatile/include/mach/debug_ll.h @@ -19,7 +19,7 @@ #include <linux/amba/serial.h> #include <io.h> -static inline void putc(char c) +static inline void PUTC_LL(char c) { /* Wait until there is space in the FIFO */ while (readl(0x101F1000 + UART01x_FR) & UART01x_FR_TXFF); diff --git a/arch/mips/include/debug_ll_ns16550.h b/arch/mips/include/debug_ll_ns16550.h index a8b74d29d8..e9c7ecf98e 100644 --- a/arch/mips/include/debug_ll_ns16550.h +++ b/arch/mips/include/debug_ll_ns16550.h @@ -28,7 +28,7 @@ #define LSR_THRE 0x20 /* Xmit holding register empty */ -static __inline__ void putc(char ch) +static __inline__ void PUTC_LL(char ch) { while (!(__raw_readb((u8 *)DEBUG_LL_UART_ADDR + lsr) & LSR_THRE)); __raw_writeb(ch, (u8 *)DEBUG_LL_UART_ADDR + rbr); diff --git a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h index 4bf1817eae..0703bb0f23 100644 --- a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h +++ b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h @@ -28,7 +28,7 @@ #define lsr 5 #define LSR_THRE 0x20 /* Xmit holding register empty */ -static __inline__ void putc(char ch) +static __inline__ void PUTC_LL(char ch) { while (!(__raw_readb(DEBUG_LL_UART_ADDR + lsr) & LSR_THRE)); __raw_writeb(ch, DEBUG_LL_UART_ADDR + rbr); diff --git a/commands/bootm.c b/commands/bootm.c index 98d2e4faf6..483e6a1933 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -184,7 +184,7 @@ static int bootm_open_oftree(struct image_data *data, const char *oftree, int nu } } - ft = file_detect_type(fdt); + ft = file_detect_type(fdt, size); if (ft != filetype_oftree) { printf("%s is not an oftree but %s\n", oftree, file_type_to_string(ft)); diff --git a/commands/loadenv.c b/commands/loadenv.c index 5bf17406b2..48284d7a03 100644 --- a/commands/loadenv.c +++ b/commands/loadenv.c @@ -21,27 +21,68 @@ */ #include <common.h> +#include <getopt.h> #include <command.h> #include <environment.h> +#include <fs.h> static int do_loadenv(int argc, char *argv[]) { char *filename, *dirname; + unsigned flags = 0; + int opt; + int scrub = 0; - if (argc < 3) + while ((opt = getopt(argc, argv, "ns")) > 0) { + switch (opt) { + case 'n': + flags |= ENV_FLAG_NO_OVERWRITE; + break; + case 's': + scrub = 1; + break; + default: + return COMMAND_ERROR_USAGE; + } + } + + if (argc - optind < 2) dirname = "/env"; else - dirname = argv[2]; - if (argc < 2) + dirname = argv[optind + 1]; + + if (argc - optind < 1) filename = default_environment_path; else - filename = argv[1]; + filename = argv[optind]; + + if (scrub) { + int ret; + + ret = unlink_recursive(dirname, NULL); + if (ret) { + eprintf("cannot remove %s: %s\n", dirname, + strerror(-ret)); + return 1; + } + + ret = mkdir(dirname, 0); + if (ret) { + eprintf("cannot create %s: %s\n", dirname, + strerror(-ret)); + return ret; + } + } + printf("loading environment from %s\n", filename); - return envfs_load(filename, dirname); + + return envfs_load(filename, dirname, flags); } BAREBOX_CMD_HELP_START(loadenv) -BAREBOX_CMD_HELP_USAGE("loadenv [ENVFS] [DIRECTORY]\n") +BAREBOX_CMD_HELP_USAGE("loadenv OPTIONS [ENVFS] [DIRECTORY]\n") +BAREBOX_CMD_HELP_OPT("-n", "do not overwrite existing files\n") +BAREBOX_CMD_HELP_OPT("-s", "scrub old environment\n") BAREBOX_CMD_HELP_SHORT("Load environment from ENVFS into DIRECTORY (default: /dev/env0 -> /env).\n") BAREBOX_CMD_HELP_END diff --git a/commands/ls.c b/commands/ls.c index 1fdb24406d..f2d990340f 100644 --- a/commands/ls.c +++ b/commands/ls.c @@ -73,12 +73,13 @@ int ls(const char *path, ulong flags) while ((d = readdir(dir))) { sprintf(tmp, "%s/%s", path, d->d_name); - if (lstat(tmp, &s)) - goto out; - if (flags & LS_COLUMN) + if (flags & LS_COLUMN) { string_list_add_sorted(&sl, d->d_name); - else + } else { + if (lstat(tmp, &s)) + goto out; ls_one(d->d_name, tmp, &s); + } } closedir(dir); diff --git a/commands/mem.c b/commands/mem.c index 6fbc7cc4af..51aa04daa2 100644 --- a/commands/mem.c +++ b/commands/mem.c @@ -51,7 +51,7 @@ static char *DEVMEM = "/dev/mem"; */ #define DISP_LINE_LEN 16 -int memory_display(char *addr, loff_t offs, ulong nbytes, int size) +int memory_display(char *addr, loff_t offs, ulong nbytes, int size, int swab) { ulong linebytes, i; u_char *cp; @@ -73,9 +73,17 @@ int memory_display(char *addr, loff_t offs, ulong nbytes, int size) for (i = 0; i < linebytes; i += size) { if (size == 4) { - count -= printf(" %08x", (*uip++ = *((uint *)addr))); + u32 res; + res = (*uip++ = *((uint *)addr)); + if (swab) + res = __swab32(res); + count -= printf(" %08x", res); } else if (size == 2) { - count -= printf(" %04x", (*usp++ = *((ushort *)addr))); + u16 res; + res = (*usp++ = *((ushort *)addr)); + if (swab) + res = __swab16(res); + count -= printf(" %04x", res); } else { count -= printf(" %02x", (*ucp++ = *((u_char *)addr))); } @@ -128,7 +136,7 @@ static int open_and_lseek(const char *filename, int mode, loff_t pos) } static int mem_parse_options(int argc, char *argv[], char *optstr, int *mode, - char **sourcefile, char **destfile) + char **sourcefile, char **destfile, int *swab) { int opt; @@ -149,6 +157,9 @@ static int mem_parse_options(int argc, char *argv[], char *optstr, int *mode, case 'd': *destfile = optarg; break; + case 'x': + *swab = 1; + break; default: return -1; } @@ -165,11 +176,13 @@ static int do_mem_md(int argc, char *argv[]) int fd; char *filename = DEVMEM; int mode = O_RWSIZE_4; + int swab = 0; if (argc < 2) return COMMAND_ERROR_USAGE; - if (mem_parse_options(argc, argv, "bwls:", &mode, &filename, NULL) < 0) + if (mem_parse_options(argc, argv, "bwls:x", &mode, &filename, NULL, + &swab) < 0) return 1; if (optind < argc) { @@ -195,7 +208,8 @@ static int do_mem_md(int argc, char *argv[]) if (!r) goto out; - if ((ret = memory_display(rw_buf, start, r, mode >> O_RWSIZE_SHIFT))) + if ((ret = memory_display(rw_buf, start, r, + mode >> O_RWSIZE_SHIFT, swab))) goto out; start += r; @@ -216,6 +230,7 @@ static const __maybe_unused char cmd_md_help[] = " -b output in bytes\n" " -w output in halfwords (16bit)\n" " -l output in words (32bit)\n" +" -x swap bytes at output\n" "\n" "Memory regions:\n" "Memory regions can be specified in two different forms: start+size\n" @@ -240,8 +255,10 @@ static int do_mem_mw(int argc, char *argv[]) char *filename = DEVMEM; int mode = O_RWSIZE_4; loff_t adr; + int swab = 0; - if (mem_parse_options(argc, argv, "bwld:", &mode, NULL, &filename) < 0) + if (mem_parse_options(argc, argv, "bwld:x", &mode, NULL, &filename, + &swab) < 0) return 1; if (optind + 1 >= argc) @@ -264,10 +281,14 @@ static int do_mem_mw(int argc, char *argv[]) break; case O_RWSIZE_2: val16 = simple_strtoul(argv[optind], NULL, 0); + if (swab) + val16 = __swab16(val16); ret = write(fd, &val16, 2); break; case O_RWSIZE_4: val32 = simple_strtoul(argv[optind], NULL, 0); + if (swab) + val32 = __swab32(val32); ret = write(fd, &val32, 4); break; } @@ -309,7 +330,8 @@ static int do_mem_cmp(int argc, char *argv[]) int offset = 0; struct stat statbuf; - if (mem_parse_options(argc, argv, "bwls:d:", &mode, &sourcefile, &destfile) < 0) + if (mem_parse_options(argc, argv, "bwls:d:", &mode, &sourcefile, + &destfile, NULL) < 0) return 1; if (optind + 2 > argc) @@ -416,7 +438,8 @@ static int do_mem_cp(int argc, char *argv[]) struct stat statbuf; int ret = 0; - if (mem_parse_options(argc, argv, "bwls:d:", &mode, &sourcefile, &destfile) < 0) + if (mem_parse_options(argc, argv, "bwls:d:", &mode, &sourcefile, + &destfile, NULL) < 0) return 1; if (optind + 2 > argc) @@ -521,7 +544,8 @@ static int do_memset(int argc, char *argv[]) int ret = 1; char *file = DEVMEM; - if (mem_parse_options(argc, argv, "bwld:", &mode, NULL, &file) < 0) + if (mem_parse_options(argc, argv, "bwld:", &mode, NULL, &file, + NULL) < 0) return 1; if (optind + 3 > argc) diff --git a/commands/rm.c b/commands/rm.c index 4e765acf7a..5486005d9b 100644 --- a/commands/rm.c +++ b/commands/rm.c @@ -19,17 +19,36 @@ #include <common.h> #include <command.h> #include <fs.h> +#include <getopt.h> #include <errno.h> static int do_rm(int argc, char *argv[]) { - int i = 1; + int i, opt, recursive = 0; + + while ((opt = getopt(argc, argv, "r")) > 0) { + switch (opt) { + case 'r': + recursive = 1; + break; + default: + return COMMAND_ERROR_USAGE; + } + } if (argc < 2) return COMMAND_ERROR_USAGE; + i = optind; + while (i < argc) { - if (unlink(argv[i])) { + int ret; + + if (recursive) + ret = unlink_recursive(argv[i], NULL); + else + ret = unlink(argv[i]); + if (ret) { printf("could not remove %s: %s\n", argv[i], errno_str()); return 1; } @@ -40,8 +59,9 @@ static int do_rm(int argc, char *argv[]) } static const __maybe_unused char cmd_rm_help[] = -"Usage: rm [FILES]\n" -"Remove files\n"; +"Usage: rm [OPTIONS] [FILES]\n" +"Remove files\n" +"-r remove directories and their contents recursively\n"; BAREBOX_CMD_START(rm) .cmd = do_rm, diff --git a/commands/spi.c b/commands/spi.c index 899bf62608..2f6b430baa 100644 --- a/commands/spi.c +++ b/commands/spi.c @@ -101,12 +101,12 @@ static int do_spi(int argc, char *argv[]) printf("\n"); printf("wrote %i bytes\n", count); - memory_display(tx_buf, 0, count, byte_per_word); + memory_display(tx_buf, 0, count, byte_per_word, 0); printf("read %i bytes\n", read); } - memory_display(rx_buf, 0, read, byte_per_word); + memory_display(rx_buf, 0, read, byte_per_word, 0); out: free(rx_buf); diff --git a/common/Kconfig b/common/Kconfig index d60db80747..57119dcbd4 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -667,6 +667,8 @@ config DEBUG_LL prompt "low level debug messages" help Enable this to get low level debug messages during barebox initialization. + This requires SoC specific support. Most SoCs require the debug UART to be + initialized by a debugger or first stage bootloader. endmenu diff --git a/common/environment.c b/common/environment.c index 69c4c0aa76..e11cd9dd47 100644 --- a/common/environment.c +++ b/common/environment.c @@ -206,7 +206,7 @@ EXPORT_SYMBOL(envfs_save); * Note: This function will also be used on the host! See note in the header * of this file. */ -int envfs_load(char *filename, char *dir) +int envfs_load(char *filename, char *dir, unsigned flags) { struct envfs_super super; void *buf = NULL, *buf_free = NULL; @@ -316,6 +316,14 @@ int envfs_load(char *filename, char *dir) } free(str); } else { + struct stat s; + + if (flags & ENV_FLAG_NO_OVERWRITE && + !stat(str, &s)) { + printf("skip %s\n", str); + goto skip; + } + fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); free(str); if (fd < 0) { @@ -333,7 +341,7 @@ int envfs_load(char *filename, char *dir) } close(fd); } - +skip: buf += PAD4(inode_size); size -= headerlen_full + PAD4(inode_size) + sizeof(struct envfs_inode); diff --git a/common/filetype.c b/common/filetype.c index b8d54f7fe0..748e364e65 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -47,6 +47,7 @@ static const struct filetype_str filetype_str[] = { [filetype_mbr] = { "MBR sector", "mbr" }, [filetype_bmp] = { "BMP image", "bmp" }, [filetype_png] = { "PNG image", "png" }, + [filetype_ext] = { "ext filesystem", "ext" }, }; const char *file_type_to_string(enum filetype f) @@ -105,19 +106,25 @@ enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec) return filetype_mbr; } -enum filetype file_detect_type(void *_buf) +enum filetype file_detect_type(void *_buf, size_t bufsize) { u32 *buf = _buf; u64 *buf64 = _buf; u8 *buf8 = _buf; + u16 *buf16 = _buf; enum filetype type; + if (bufsize < 9) + return filetype_unknown; + if (strncmp(buf8, "#!/bin/sh", 9) == 0) return filetype_sh; - if (is_barebox_arm_head(_buf)) - return filetype_arm_barebox; - if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01) - return filetype_arm_zimage; + + if (bufsize < 32) + return filetype_unknown; + + if (strncmp(buf8, "BM", 2) == 0) + return filetype_bmp; if (buf8[0] == 0x89 && buf8[1] == 0x4c && buf8[2] == 0x5a && buf8[3] == 0x4f) return filetype_lzo_compressed; @@ -136,15 +143,31 @@ enum filetype file_detect_type(void *_buf) return filetype_oftree; if (strncmp(buf8, "ANDROID!", 8) == 0) return filetype_aimage; + if (buf64[0] == le64_to_cpu(0x0a1a0a0d474e5089ull)) + return filetype_png; if (strncmp(buf8 + 0x10, "barebox", 7) == 0) return filetype_mips_barebox; + + if (bufsize < 64) + return filetype_unknown; + + if (is_barebox_arm_head(_buf)) + return filetype_arm_barebox; + if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01) + return filetype_arm_zimage; + + if (bufsize < 512) + return filetype_unknown; + type = is_fat_or_mbr(buf8, NULL); if (type != filetype_unknown) return type; - if (strncmp(buf8, "BM", 2) == 0) - return filetype_bmp; - if (buf64[0] == le64_to_cpu(0x0a1a0a0d474e5089ull)) - return filetype_png; + + if (bufsize < 1536) + return filetype_unknown; + + if (buf16[512 + 28] == le16_to_cpu(0xef53)) + return filetype_ext; return filetype_unknown; } @@ -160,13 +183,13 @@ enum filetype file_name_detect_type(const char *filename) if (fd < 0) return fd; - buf = xzalloc(512); + buf = xzalloc(FILE_TYPE_SAFE_BUFSIZE); - ret = read(fd, buf, 512); + ret = read(fd, buf, FILE_TYPE_SAFE_BUFSIZE); if (ret < 0) goto err_out; - type = file_detect_type(buf); + type = file_detect_type(buf, ret); if (type == filetype_mbr) { /* diff --git a/common/password.c b/common/password.c index a03e1dbff7..d157a11b7b 100644 --- a/common/password.c +++ b/common/password.c @@ -66,11 +66,14 @@ int password(unsigned char *passwd, size_t length, int flags, int timeout) case CTL_CH('h'): case KEY_DEL7: case KEY_DEL: - if (flags & STAR && pos > 0) - puts("\b \b"); - *buf = '\0'; - buf--; - pos--; + if (pos > 0) { + if (flags & STAR) + puts("\b \b"); + + *buf = '\0'; + buf--; + pos--; + } continue; default: if (pos < length - 1) { diff --git a/common/startup.c b/common/startup.c index 7bb3c73c12..14409a217d 100644 --- a/common/startup.c +++ b/common/startup.c @@ -108,12 +108,12 @@ void start_barebox (void) debug("initcalls done\n"); #ifdef CONFIG_ENV_HANDLING - if (envfs_load(default_environment_path, "/env")) { + if (envfs_load(default_environment_path, "/env", 0)) { #ifdef CONFIG_DEFAULT_ENVIRONMENT printf("no valid environment found on %s. " "Using default environment\n", default_environment_path); - envfs_load("/dev/defaultenv", "/env"); + envfs_load("/dev/defaultenv", "/env", 0); #endif } #endif diff --git a/common/uimage.c b/common/uimage.c index 3f5a3d5cd0..3bec6b39f8 100644 --- a/common/uimage.c +++ b/common/uimage.c @@ -516,7 +516,7 @@ void *uimage_load_to_buf(struct uimage_handle *handle, int image_no, if (ret < 0) return NULL; - ft = file_detect_type(ftbuf); + ft = file_detect_type(ftbuf, 128); if ((int)ft < 0) return NULL; diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index fe6f5e6f5d..b10c5c7c7a 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -9,6 +9,9 @@ menuconfig DISK if DISK +config DISK_IDE_SFF + bool + config DISK_WRITE select BLOCK_WRITE bool "support writing to disk drives" @@ -30,13 +33,30 @@ config DISK_ATA help Support for native ATA/IDE drives +config DISK_AHCI + bool "AHCI support" + select DISK_ATA + select DISK_DRIVE + +config DISK_AHCI_IMX + depends on DISK_AHCI + bool "i.MX AHCI support" + comment "interface types" config DISK_INTF_PLATFORM_IDE bool "Platform IDE" select DISK_ATA + select DISK_IDE_SFF help Generic platform driver for simple IDE like interfaces to a connected ATA device. +config DISK_PATA_IMX + bool "i.MX PATA driver" + depends on ARCH_IMX + depends on DISK_INTF_PLATFORM_IDE + help + select this to enable support for the i.MX PATA driver + endif diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 2560076d26..c444c4d196 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -1,8 +1,12 @@ # drive types obj-$(CONFIG_DISK_BIOS) += disk_bios_drive.o +obj-$(CONFIG_DISK_IDE_SFF) += ide-sff.o obj-$(CONFIG_DISK_ATA) += disk_ata_drive.o +obj-$(CONFIG_DISK_AHCI) += ahci.o +obj-$(CONFIG_DISK_AHCI_IMX) += sata-imx.o # interface types obj-$(CONFIG_DISK_INTF_PLATFORM_IDE) += intf_platform_ide.o +obj-$(CONFIG_DISK_PATA_IMX) += pata-imx.o diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c new file mode 100644 index 0000000000..14de3c5061 --- /dev/null +++ b/drivers/ata/ahci.c @@ -0,0 +1,678 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. + * Author: Jason Jin<Jason.jin@freescale.com> + * Zhang Wei<wei.zhang@freescale.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 + * + * with the reference on libata and ahci drvier in kernel + * + */ + +#include <common.h> +#include <init.h> +#include <errno.h> +#include <io.h> +#include <malloc.h> +#include <scsi.h> +#include <linux/ctype.h> +#include <disks.h> +#include <asm/mmu.h> +#include <ata_drive.h> +#include <sizes.h> +#include <clock.h> + +#include "ahci.h" + +#define AHCI_MAX_DATA_BYTE_COUNT SZ_4M + +/* + * Some controllers limit number of blocks they can read/write at once. + * Contemporary SSD devices work much faster if the read/write size is aligned + * to a power of 2. + */ +#define MAX_SATA_BLOCKS_READ_WRITE 0x80 + +/* Maximum timeouts for each event */ +#define WAIT_SPINUP (10 * SECOND) +#define WAIT_DATAIO (5 * SECOND) +#define WAIT_FLUSH (5 * SECOND) +#define WAIT_LINKUP (4 * MSECOND) + +#define ahci_port_debug(port, fmt, arg...) \ + dev_dbg(port->ahci->dev, "port %d: " fmt, port->num, ##arg) + +#define ahci_port_info(port, fmt, arg...) \ + dev_info(port->ahci->dev, "port %d: " fmt, port->num, ##arg) + +#define ahci_debug(ahci, fmt, arg...) \ + dev_dbg(ahci->dev, fmt, ##arg) + +struct ahci_cmd_hdr { + u32 opts; + u32 status; + u32 tbl_addr; + u32 tbl_addr_hi; + u32 reserved[4]; +}; + +struct ahci_sg { + u32 addr; + u32 addr_hi; + u32 reserved; + u32 flags_size; +}; + +static inline void ahci_iowrite(struct ahci_device *ahci, int ofs, u32 val) +{ + writel(val, ahci->mmio_base + ofs); +} + +static inline u32 ahci_ioread(struct ahci_device *ahci, int ofs) +{ + return readl(ahci->mmio_base + ofs); +} + +static inline void ahci_iowrite_f(struct ahci_device *ahci, int ofs, u32 val) +{ + writel(val, ahci->mmio_base + ofs); + readl(ahci->mmio_base); +} + +static inline void ahci_port_write(struct ahci_port *port, int ofs, u32 val) +{ + writel(val, port->port_mmio + ofs); +} + +static inline void ahci_port_write_f(struct ahci_port *port, int ofs, u32 val) +{ + writel(val, port->port_mmio + ofs); + readl(port->port_mmio + ofs); +} + +static inline u32 ahci_port_read(struct ahci_port *port, int ofs) +{ + return readl(port->port_mmio + ofs); +} + +static inline void __iomem *ahci_port_base(void __iomem *base, int port) +{ + return base + 0x100 + (port * 0x80); +} + +static int ahci_link_ok(struct ahci_port *ahci_port, int verbose) +{ + u32 val = ahci_port_read(ahci_port, PORT_SCR_STAT) & 0xf; + + if (val == 0x3) + return true; + + if (verbose) + dev_err(ahci_port->ahci->dev, "port %d: no link\n", ahci_port->num); + + return false; +} + +static void ahci_fill_cmd_slot(struct ahci_port *ahci_port, u32 opts) +{ + ahci_port->cmd_slot->opts = cpu_to_le32(opts); + ahci_port->cmd_slot->status = 0; + ahci_port->cmd_slot->tbl_addr = + cpu_to_le32((unsigned long)ahci_port->cmd_tbl & 0xffffffff); + ahci_port->cmd_slot->tbl_addr_hi = 0; +} + +static int ahci_fill_sg(struct ahci_port *ahci_port, const void *buf, int buf_len) +{ + struct ahci_sg *ahci_sg = ahci_port->cmd_tbl_sg; + u32 sg_count; + + sg_count = ((buf_len - 1) / AHCI_MAX_DATA_BYTE_COUNT) + 1; + if (sg_count > AHCI_MAX_SG) + return -EINVAL; + + while (buf_len) { + unsigned int now = min(AHCI_MAX_DATA_BYTE_COUNT, buf_len); + + ahci_sg->addr = cpu_to_le32((u32)buf); + ahci_sg->addr_hi = 0; + ahci_sg->flags_size = cpu_to_le32(now - 1); + + buf_len -= now; + buf += now; + } + + return sg_count; +} + +static int ahci_io(struct ahci_port *ahci_port, u8 *fis, int fis_len, void *rbuf, + const void *wbuf, int buf_len) +{ + u32 opts; + int sg_count; + int ret; + + if (!ahci_link_ok(ahci_port, 1)) + return -EIO; + + if (wbuf) + dma_flush_range((unsigned long)wbuf, (unsigned long)wbuf + buf_len); + + memcpy((unsigned char *)ahci_port->cmd_tbl, fis, fis_len); + + sg_count = ahci_fill_sg(ahci_port, rbuf ? rbuf : wbuf, buf_len); + opts = (fis_len >> 2) | (sg_count << 16); + if (wbuf) + opts |= 1 << 6; + ahci_fill_cmd_slot(ahci_port, opts); + + ahci_port_write_f(ahci_port, PORT_CMD_ISSUE, 1); + + ret = wait_on_timeout(WAIT_DATAIO, + (readl(ahci_port->port_mmio + PORT_CMD_ISSUE) & 0x1) == 0); + if (ret) + return -ETIMEDOUT; + + if (rbuf) + dma_inv_range((unsigned long)rbuf, (unsigned long)rbuf + buf_len); + + return 0; +} + +/* + * SCSI INQUIRY command operation. + */ +static int ahci_read_id(struct ata_port *ata, void *buf) +{ + struct ahci_port *ahci = container_of(ata, struct ahci_port, ata); + u8 fis[20]; + int ret; + + memset(fis, 0, sizeof(fis)); + + /* Construct the FIS */ + fis[0] = 0x27; /* Host to device FIS. */ + fis[1] = 1 << 7; /* Command FIS. */ + fis[2] = ATA_CMD_ID_ATA; /* Command byte. */ + + ret = ahci_io(ahci, fis, sizeof(fis), buf, NULL, SECTOR_SIZE); + if (ret) + return ret; + + return ret; +} + +static int ahci_rw(struct ata_port *ata, void *rbuf, const void *wbuf, + unsigned int block, int num_blocks) +{ + struct ahci_port *ahci = container_of(ata, struct ahci_port, ata); + u8 fis[20]; + int ret; + + memset(fis, 0, sizeof(fis)); + + /* Construct the FIS */ + fis[0] = 0x27; /* Host to device FIS. */ + fis[1] = 1 << 7; /* Command FIS. */ + fis[2] = wbuf ? ATA_CMD_WRITE_EXT : ATA_CMD_READ_EXT; /* Command byte. */ + + while (num_blocks) { + int now; + + now = min(MAX_SATA_BLOCKS_READ_WRITE, num_blocks); + + fis[4] = (block >> 0) & 0xff; + fis[5] = (block >> 8) & 0xff; + fis[6] = (block >> 16) & 0xff; + fis[7] = 1 << 6; /* device reg: set LBA mode */ + fis[8] = ((block >> 24) & 0xff); + fis[3] = 0xe0; /* features */ + + /* Block (sector) count */ + fis[12] = (now >> 0) & 0xff; + fis[13] = (now >> 8) & 0xff; + + ret = ahci_io(ahci, fis, sizeof(fis), rbuf, wbuf, now * SECTOR_SIZE); + if (ret) + return ret; + + if (rbuf) + rbuf += now * SECTOR_SIZE; + if (wbuf) + wbuf += now * SECTOR_SIZE; + num_blocks -= now; + block += now; + } + + return 0; +} + +static int ahci_read(struct ata_port *ata, void *buf, unsigned int block, + int num_blocks) +{ + return ahci_rw(ata, buf, NULL, block, num_blocks); +} + +static int ahci_write(struct ata_port *ata, const void *buf, unsigned int block, + int num_blocks) +{ + return ahci_rw(ata, NULL, buf, block, num_blocks); +} + +static struct ata_port_operations ahci_ops = { + .read_id = ahci_read_id, + .read = ahci_read, + .write = ahci_write, +}; + +static int ahci_init_port(struct ahci_port *ahci_port) +{ + void __iomem *port_mmio; + u32 val, cmd; + int ret; + + port_mmio = ahci_port->port_mmio; + + /* make sure port is not active */ + val = ahci_port_read(ahci_port, PORT_CMD); + if (val & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON | PORT_CMD_FIS_RX | PORT_CMD_START)) { + ahci_port_debug(ahci_port, "Port is active. Deactivating.\n"); + val &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON | + PORT_CMD_FIS_RX | PORT_CMD_START); + ahci_port_write(ahci_port, PORT_CMD, val); + + /* + * spec says 500 msecs for each bit, so + * this is slightly incorrect. + */ + mdelay(500); + } + + /* + * First item in chunk of DMA memory: 32-slot command table, + * 32 bytes each in size + */ + ahci_port->cmd_slot = dma_alloc_coherent(AHCI_CMD_SLOT_SZ * 32); + if (!ahci_port->cmd_slot) { + ret = -ENOMEM; + goto err_alloc; + } + + ahci_port_debug(ahci_port, "cmd_slot = 0x%x\n", (unsigned)ahci_port->cmd_slot); + + /* + * Second item: Received-FIS area + */ + ahci_port->rx_fis = (unsigned long)dma_alloc_coherent(AHCI_RX_FIS_SZ); + if (!ahci_port->rx_fis) { + ret = -ENOMEM; + goto err_alloc1; + } + + /* + * Third item: data area for storing a single command + * and its scatter-gather table + */ + ahci_port->cmd_tbl = dma_alloc_coherent(AHCI_CMD_TBL_SZ); + if (!ahci_port->cmd_tbl) { + ret = -ENOMEM; + goto err_alloc2; + } + + memset(ahci_port->cmd_slot, 0, AHCI_CMD_SLOT_SZ * 32); + memset((void *)ahci_port->rx_fis, 0, AHCI_RX_FIS_SZ); + memset(ahci_port->cmd_tbl, 0, AHCI_CMD_TBL_SZ); + + ahci_port_debug(ahci_port, "cmd_tbl_dma = 0x%p\n", ahci_port->cmd_tbl); + + ahci_port->cmd_tbl_sg = ahci_port->cmd_tbl + AHCI_CMD_TBL_HDR_SZ; + + ahci_port_write_f(ahci_port, PORT_LST_ADDR, (u32)ahci_port->cmd_slot); + ahci_port_write_f(ahci_port, PORT_FIS_ADDR, ahci_port->rx_fis); + + /* + * Add the spinup command to whatever mode bits may + * already be on in the command register. + */ + cmd = ahci_port_read(ahci_port, PORT_CMD); + cmd |= PORT_CMD_FIS_RX; + cmd |= PORT_CMD_SPIN_UP; + cmd |= PORT_CMD_ICC_ACTIVE; + ahci_port_write_f(ahci_port, PORT_CMD, cmd); + + mdelay(10); + + cmd = ahci_port_read(ahci_port, PORT_CMD); + cmd |= PORT_CMD_START; + ahci_port_write_f(ahci_port, PORT_CMD, cmd); + + /* + * Bring up SATA link. + * SATA link bringup time is usually less than 1 ms; only very + * rarely has it taken between 1-2 ms. Never seen it above 2 ms. + */ + ret = wait_on_timeout(WAIT_LINKUP, + (ahci_port_read(ahci_port, PORT_SCR_STAT) & 0xf) == 0x3); + if (ret) { + ahci_port_info(ahci_port, "SATA link timeout\n");; + ret = -ETIMEDOUT; + goto err_init; + } + + ahci_port_info(ahci_port, "SATA link ok\n"); + + /* Clear error status */ + val = ahci_port_read(ahci_port, PORT_SCR_ERR); + if (val) + ahci_port_write(ahci_port, PORT_SCR_ERR, val); + + ahci_port_info(ahci_port, "Spinning up device...\n"); + + ret = wait_on_timeout(WAIT_SPINUP, + (readl(port_mmio + PORT_TFDATA) & + (ATA_STATUS_BUSY | ATA_STATUS_DRQ)) == 0); + if (ret) { + ahci_port_info(ahci_port, "timeout.\n"); + ret = -ENODEV; + goto err_init; + } + + ahci_port_info(ahci_port, "ok.\n"); + + val = ahci_port_read(ahci_port, PORT_SCR_ERR); + + ahci_port_write(ahci_port, PORT_SCR_ERR, val); + + /* ack any pending irq events for this port */ + val = ahci_port_read(ahci_port, PORT_IRQ_STAT); + if (val) + ahci_port_write(ahci_port, PORT_IRQ_STAT, val); + + ahci_iowrite(ahci_port->ahci, HOST_IRQ_STAT, 1 << ahci_port->num); + + /* set irq mask (enables interrupts) */ + ahci_port_write(ahci_port, PORT_IRQ_MASK, DEF_PORT_IRQ); + + /* register linkup ports */ + val = ahci_port_read(ahci_port, PORT_SCR_STAT); + + ahci_port_debug(ahci_port, "status: 0x%08x\n", val); + + ahci_port->ata.ops = &ahci_ops; + + if ((val & 0xf) == 0x03) + return 0; + + ret = -ENODEV; + +err_init: + dma_free_coherent(ahci_port->cmd_tbl, AHCI_CMD_TBL_SZ); +err_alloc2: + dma_free_coherent((void *)ahci_port->rx_fis, AHCI_RX_FIS_SZ); +err_alloc1: + dma_free_coherent(ahci_port->cmd_slot, AHCI_CMD_SLOT_SZ * 32); +err_alloc: + return ret; +} + +static int ahci_host_init(struct ahci_device *ahci) +{ + u8 *mmio = (u8 *)ahci->mmio_base; + u32 tmp, cap_save; + int i, ret; + + ahci_debug(ahci, "ahci_host_init: start\n"); + + cap_save = readl(mmio + HOST_CAP); + cap_save &= ((1 << 28) | (1 << 17)); + cap_save |= (1 << 27); /* Staggered Spin-up. Not needed. */ + + /* global controller reset */ + tmp = ahci_ioread(ahci, HOST_CTL); + if ((tmp & HOST_RESET) == 0) + ahci_iowrite_f(ahci, HOST_CTL, tmp | HOST_RESET); + + /* + * reset must complete within 1 second, or + * the hardware should be considered fried. + */ + ret = wait_on_timeout(SECOND, (readl(mmio + HOST_CTL) & HOST_RESET) == 0); + if (ret) { + ahci_debug(ahci,"controller reset failed (0x%x)\n", tmp); + return -ENODEV; + } + + ahci_iowrite_f(ahci, HOST_CTL, HOST_AHCI_EN); + ahci_iowrite(ahci, HOST_CAP, cap_save); + ahci_iowrite_f(ahci, HOST_PORTS_IMPL, 0xf); + + ahci->cap = ahci_ioread(ahci, HOST_CAP); + ahci->port_map = ahci_ioread(ahci, HOST_PORTS_IMPL); + ahci->n_ports = (ahci->cap & 0x1f) + 1; + + ahci_debug(ahci, "cap 0x%x port_map 0x%x n_ports %d\n", + ahci->cap, ahci->port_map, ahci->n_ports); + + for (i = 0; i < ahci->n_ports; i++) { + struct ahci_port *ahci_port = &ahci->ports[i]; + + ahci_port->num = i; + ahci_port->ahci = ahci; + ahci_port->ata.dev = ahci->dev; + ahci_port->port_mmio = ahci_port_base(mmio, i); + ret = ahci_init_port(ahci_port); + if (!ret) + ahci->link_port_map |= 1 << i; + } + + tmp = ahci_ioread(ahci, HOST_CTL); + ahci_iowrite(ahci, HOST_CTL, tmp | HOST_IRQ_EN); + tmp = ahci_ioread(ahci, HOST_CTL); + + return 0; +} + +static int ahci_port_start(struct ahci_port *ahci_port, u8 port) +{ + if (!ahci_link_ok(ahci_port, 1)) + return -EIO; + + ahci_port_write_f(ahci_port, PORT_CMD, + PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX | + PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP | + PORT_CMD_START); + + ata_port_register(&ahci_port->ata); + + return 0; +} + +static int __ahci_host_init(struct ahci_device *ahci) +{ + int i, rc = 0; + u32 linkmap; + + ahci->host_flags = ATA_FLAG_SATA + | ATA_FLAG_NO_LEGACY + | ATA_FLAG_MMIO + | ATA_FLAG_PIO_DMA + | ATA_FLAG_NO_ATAPI; + ahci->pio_mask = 0x1f; + ahci->udma_mask = 0x7f; /* FIXME: assume to support UDMA6 */ + + /* initialize adapter */ + rc = ahci_host_init(ahci); + if (rc) + goto err_out; + + linkmap = ahci->link_port_map; + + for (i = 0; i < 32; i++) { + if (((linkmap >> i) & 0x01)) { + if (ahci_port_start(&ahci->ports[i], i)) { + printf("Can not start port %d\n", i); + continue; + } + } + } +err_out: + return rc; +} + +#if 0 +/* + * In the general case of generic rotating media it makes sense to have a + * flush capability. It probably even makes sense in the case of SSDs because + * one cannot always know for sure what kind of internal cache/flush mechanism + * is embodied therein. At first it was planned to invoke this after the last + * write to disk and before rebooting. In practice, knowing, a priori, which + * is the last write is difficult. Because writing to the disk in u-boot is + * very rare, this flush command will be invoked after every block write. + */ +static int ata_io_flush(u8 port) +{ + u8 fis[20]; + struct ahci_ioports *pp = &(probe_ent->port[port]); + volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio; + u32 cmd_fis_len = 5; /* five dwords */ + + /* Preset the FIS */ + memset(fis, 0, 20); + fis[0] = 0x27; /* Host to device FIS. */ + fis[1] = 1 << 7; /* Command FIS. */ + fis[2] = ATA_CMD_FLUSH_EXT; + + memcpy((unsigned char *)pp->cmd_tbl, fis, 20); + ahci_fill_cmd_slot(pp, cmd_fis_len); + mywritel_with_flush(1, port_mmio + PORT_CMD_ISSUE); + + if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE, + WAIT_MS_FLUSH, 0x1)) { + debug("scsi_ahci: flush command timeout on port %d.\n", port); + return -EIO; + } + + return 0; +} +#endif + +void ahci_print_info(struct ahci_device *ahci) +{ + u32 vers, cap, cap2, impl, speed; + const char *speed_s; + const char *scc_s; + + vers = ahci_ioread(ahci, HOST_VERSION); + cap = ahci->cap; + cap2 = ahci_ioread(ahci, HOST_CAP2); + impl = ahci->port_map; + + speed = (cap >> 20) & 0xf; + if (speed == 1) + speed_s = "1.5"; + else if (speed == 2) + speed_s = "3"; + else if (speed == 3) + speed_s = "6"; + else + speed_s = "?"; + + scc_s = "SATA"; + + printf("AHCI %02x%02x.%02x%02x " + "%u slots %u ports %s Gbps 0x%x impl %s mode\n", + (vers >> 24) & 0xff, + (vers >> 16) & 0xff, + (vers >> 8) & 0xff, + vers & 0xff, + ((cap >> 8) & 0x1f) + 1, (cap & 0x1f) + 1, speed_s, impl, scc_s); + + printf("flags: " + "%s%s%s%s%s%s%s" + "%s%s%s%s%s%s%s" + "%s%s%s%s%s%s\n", + cap & (1 << 31) ? "64bit " : "", + cap & (1 << 30) ? "ncq " : "", + cap & (1 << 28) ? "ilck " : "", + cap & (1 << 27) ? "stag " : "", + cap & (1 << 26) ? "pm " : "", + cap & (1 << 25) ? "led " : "", + cap & (1 << 24) ? "clo " : "", + cap & (1 << 19) ? "nz " : "", + cap & (1 << 18) ? "only " : "", + cap & (1 << 17) ? "pmp " : "", + cap & (1 << 16) ? "fbss " : "", + cap & (1 << 15) ? "pio " : "", + cap & (1 << 14) ? "slum " : "", + cap & (1 << 13) ? "part " : "", + cap & (1 << 7) ? "ccc " : "", + cap & (1 << 6) ? "ems " : "", + cap & (1 << 5) ? "sxs " : "", + cap2 & (1 << 2) ? "apst " : "", + cap2 & (1 << 1) ? "nvmp " : "", + cap2 & (1 << 0) ? "boh " : ""); +} + +void ahci_info(struct device_d *dev) +{ + struct ahci_device *ahci = dev->priv; + + ahci_print_info(ahci); +} + +int ahci_add_host(struct ahci_device *ahci) +{ + __ahci_host_init(ahci); + + return 0; +} + +static int ahci_probe(struct device_d *dev) +{ + struct ahci_device *ahci; + void __iomem *regs; + int ret; + + ahci = xzalloc(sizeof(*ahci)); + + regs = dev_request_mem_region(dev, 0); + + ahci->dev = dev; + ahci->mmio_base = regs; + dev->priv = ahci; + + ret = ahci_add_host(ahci); + if (ret) + free(ahci); + + return ret; +} + +static struct driver_d ahci_driver = { + .name = "ahci", + .probe = ahci_probe, + .info = ahci_info, +}; + +static int ahci_init(void) +{ + return platform_driver_register(&ahci_driver); +} + +device_initcall(ahci_init); diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h new file mode 100644 index 0000000000..72e5c1af03 --- /dev/null +++ b/drivers/ata/ahci.h @@ -0,0 +1,182 @@ +/* + * Copyright (C) Freescale Semiconductor, Inc. 2006. + * Author: Jason Jin<Jason.jin@freescale.com> + * Zhang Wei<wei.zhang@freescale.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 _AHCI_H_ +#define _AHCI_H_ + +#define AHCI_PCI_BAR 0x24 +#define AHCI_MAX_SG 56 /* hardware max is 64K */ +#define AHCI_CMD_SLOT_SZ 32 +#define AHCI_MAX_CMD_SLOT 32 +#define AHCI_RX_FIS_SZ 256 +#define AHCI_CMD_TBL_HDR_SZ 0x80 +#define AHCI_CMD_TBL_CDB 0x40 +#define AHCI_CMD_TBL_SZ AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 32) +#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ * AHCI_MAX_CMD_SLOT + \ + AHCI_CMD_TBL_SZ + AHCI_RX_FIS_SZ) +#define AHCI_CMD_ATAPI (1 << 5) +#define AHCI_CMD_WRITE (1 << 6) +#define AHCI_CMD_PREFETCH (1 << 7) +#define AHCI_CMD_RESET (1 << 8) +#define AHCI_CMD_CLR_BUSY (1 << 10) + +#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ + +/* Global controller registers */ +#define HOST_CAP 0x00 /* host capabilities */ +#define HOST_CTL 0x04 /* global host control */ +#define HOST_IRQ_STAT 0x08 /* interrupt status */ +#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ +#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ +#define HOST_CAP2 0x24 /* host capabilities, extended */ + +/* HOST_CTL bits */ +#define HOST_RESET (1 << 0) /* reset controller; self-clear */ +#define HOST_IRQ_EN (1 << 1) /* global IRQ enable */ +#define HOST_AHCI_EN (1 << 31) /* AHCI enabled */ + +/* Registers for each SATA port */ +#define PORT_LST_ADDR 0x00 /* command list DMA addr */ +#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ +#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ +#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ +#define PORT_IRQ_STAT 0x10 /* interrupt status */ +#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ +#define PORT_CMD 0x18 /* port command */ +#define PORT_TFDATA 0x20 /* taskfile data */ +#define PORT_SIG 0x24 /* device TF signature */ +#define PORT_CMD_ISSUE 0x38 /* command issue */ +#define PORT_SCR 0x28 /* SATA phy register block */ +#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ +#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ +#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ +#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ + +/* PORT_IRQ_{STAT,MASK} bits */ +#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */ +#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ +#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ +#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ +#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ +#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ +#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ +#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ + +#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ +#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ +#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ +#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ +#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ +#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ +#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ +#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ +#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ + +#define PORT_IRQ_FATAL PORT_IRQ_TF_ERR | PORT_IRQ_HBUS_ERR \ + | PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_IF_ERR + +#define DEF_PORT_IRQ PORT_IRQ_FATAL | PORT_IRQ_PHYRDY \ + | PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE \ + | PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS \ + | PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS \ + | PORT_IRQ_D2H_REG_FIS + +/* PORT_CMD bits */ +#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ +#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ +#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ +#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ +#define PORT_CMD_CLO (1 << 3) /* Command list override */ +#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ +#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ +#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ + +#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ +#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ +#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ + +#define AHCI_MAX_PORTS 32 + +/* SETFEATURES stuff */ +#define SETFEATURES_XFER 0x03 +#define XFER_UDMA_7 0x47 +#define XFER_UDMA_6 0x46 +#define XFER_UDMA_5 0x45 +#define XFER_UDMA_4 0x44 +#define XFER_UDMA_3 0x43 +#define XFER_UDMA_2 0x42 +#define XFER_UDMA_1 0x41 +#define XFER_UDMA_0 0x40 +#define XFER_MW_DMA_2 0x22 +#define XFER_MW_DMA_1 0x21 +#define XFER_MW_DMA_0 0x20 +#define XFER_SW_DMA_2 0x12 +#define XFER_SW_DMA_1 0x11 +#define XFER_SW_DMA_0 0x10 +#define XFER_PIO_4 0x0C +#define XFER_PIO_3 0x0B +#define XFER_PIO_2 0x0A +#define XFER_PIO_1 0x09 +#define XFER_PIO_0 0x08 +#define XFER_PIO_SLOW 0x00 + +#define ATA_FLAG_SATA (1 << 3) +#define ATA_FLAG_NO_LEGACY (1 << 4) /* no legacy mode check */ +#define ATA_FLAG_MMIO (1 << 6) /* use MMIO, not PIO */ +#define ATA_FLAG_SATA_RESET (1 << 7) /* (obsolete) use COMRESET */ +#define ATA_FLAG_PIO_DMA (1 << 8) /* PIO cmds via DMA */ +#define ATA_FLAG_NO_ATAPI (1 << 11) /* No ATAPI support */ + +struct ahci_device; + +struct ahci_port { + struct ata_port ata; + struct ahci_device *ahci; + int num; + unsigned flags; + void __iomem *port_mmio; + struct ahci_cmd_hdr *cmd_slot; + struct ahci_sg *cmd_tbl_sg; + void *cmd_tbl; + u32 rx_fis; +}; + +struct ahci_device { + struct device_d *dev; + struct ahci_port ports[AHCI_MAX_PORTS]; + u32 n_ports; + void __iomem *mmio_base; + u32 cap; /* cache of HOST_CAP register */ + u32 port_map; /* cache of HOST_PORTS_IMPL reg */ + u32 link_port_map; /* linkup port map */ + u32 pio_mask; + u32 udma_mask; + u32 host_flags; +}; + +int ahci_add_host(struct ahci_device *ahci); +void ahci_print_info(struct ahci_device *ahci); +void ahci_info(struct device_d *dev); + +#endif diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c index 6bb72a9756..923be9a26c 100644 --- a/drivers/ata/disk_ata_drive.c +++ b/drivers/ata/disk_ata_drive.c @@ -24,28 +24,7 @@ #include <block.h> #include <ata_drive.h> #include <disks.h> - -#define ATA_CMD_ID_DEVICE 0xEC -#define ATA_CMD_RD_CONF 0x40 -#define ATA_CMD_RD 0x20 -#define ATA_CMD_WR 0x30 - -#define DISK_MASTER 0 -#define DISK_SLAVE 1 - -/* max timeout for a rotating disk in [ms] */ -#define MAX_TIMEOUT 5000 - -/** - * Collection of data we need to know about this drive - */ -struct ata_drive_access { - struct block_device blk; /**< the main device */ - struct ata_ioports *io; /**< register file */ - uint16_t id[(SECTOR_SIZE / sizeof(uint16_t))]; -}; - -#define to_ata_drive_access(x) container_of((x), struct ata_drive_access, blk) +#include <dma.h> #define ata_id_u32(id,n) \ (((uint32_t) (id)[(n) + 1] << 16) | ((uint32_t) (id)[(n)])) @@ -57,18 +36,6 @@ struct ata_drive_access { #define ata_id_has_lba(id) ((id)[49] & (1 << 9)) -/* drive's status flags */ -#define ATA_STATUS_BUSY (1 << 7) -#define ATA_STATUS_READY (1 << 6) -#define ATA_STATUS_WR_FLT (1 << 5) -#define ATA_STATUS_DRQ (1 << 4) -#define ATA_STATUS_CORR (1 << 3) -#define ATA_STATUS_ERROR (1 << 1) -/* command flags */ -#define LBA_FLAG (1 << 6) -#define ATA_DEVCTL_SOFT_RESET (1 << 2) -#define ATA_DEVCTL_INTR_DISABLE (1 << 1) - enum { ATA_ID_SERNO = 10, #define ATA_ID_SERNO_LEN 20 @@ -240,225 +207,6 @@ static void ata_fix_endianess(uint16_t *buf, unsigned wds) } /** - * Read the status register of the ATA drive - * @param io Register file - * @return Register's content - */ -static uint8_t ata_rd_status(struct ata_ioports *io) -{ - return readb(io->status_addr); -} - -/** - * Wait until the disk is busy or time out - * @param io Register file - * @param timeout Timeout in [ms] - * @return 0 on success, -ETIMEDOUT else - */ -static int ata_wait_busy(struct ata_ioports *io, unsigned timeout) -{ - uint8_t status; - uint64_t start = get_time_ns(); - uint64_t toffs = timeout * 1000 * 1000; - - do { - status = ata_rd_status(io); - if (status & ATA_STATUS_BUSY) - return 0; - } while (!is_timeout(start, toffs)); - - return -ETIMEDOUT; -} - -/** - * Wait until the disk is ready again or time out - * @param io Register file - * @param timeout Timeout in [ms] - * @return 0 on success, -ETIMEDOUT else - * - * This function is useful to check if the disk has accepted a command. - */ -static int ata_wait_ready(struct ata_ioports *io, unsigned timeout) -{ - uint8_t status; - uint64_t start = get_time_ns(); - uint64_t toffs = timeout * 1000 * 1000; - - do { - status = ata_rd_status(io); - if (!(status & ATA_STATUS_BUSY)) { - if (status & ATA_STATUS_READY) - return 0; - } - } while (!is_timeout(start, toffs)); - - return -ETIMEDOUT; -} - -/** - * Setup the sector number in LBA notation (LBA28) - * @param io Register file - * @param drive 0 master drive, 1 slave drive - * @param num Sector number - * - * @todo LBA48 support - */ -static int ata_set_lba_sector(struct ata_ioports *io, unsigned drive, uint64_t num) -{ - if (num > 0x0FFFFFFF || drive > 1) - return -EINVAL; - - writeb(0xA0 | LBA_FLAG | drive << 4 | num >> 24, io->device_addr); - writeb(0x00, io->error_addr); - writeb(0x01, io->nsect_addr); - writeb(num, io->lbal_addr); /* 0 ... 7 */ - writeb(num >> 8, io->lbam_addr); /* 8 ... 15 */ - writeb(num >> 16, io->lbah_addr); /* 16 ... 23 */ - - return 0; -} - -/** - * Write an ATA command into the disk - * @param io Register file - * @param cmd Command to write - * @return 0 on success - */ -static int ata_wr_cmd(struct ata_ioports *io, uint8_t cmd) -{ - int rc; - - rc = ata_wait_ready(io, MAX_TIMEOUT); - if (rc != 0) - return rc; - - writeb(cmd, io->command_addr); - return 0; -} - -/** - * Write a new value into the "device control register" - * @param io Register file - * @param val Value to write - */ -static void ata_wr_dev_ctrl(struct ata_ioports *io, uint8_t val) -{ - writeb(val, io->ctl_addr); -} - -/** - * Read one sector from the drive (always SECTOR_SIZE bytes at once) - * @param io Register file - * @param buf Buffer to read the data into - */ -static void ata_rd_sector(struct ata_ioports *io, void *buf) -{ - unsigned u = SECTOR_SIZE / sizeof(uint16_t); - uint16_t *b = buf; - - if (io->dataif_be) { - for (; u > 0; u--) - *b++ = be16_to_cpu(readw(io->data_addr)); - } else { - for (; u > 0; u--) - *b++ = le16_to_cpu(readw(io->data_addr)); - } -} - -/** - * Write one sector into the drive - * @param io Register file - * @param buf Buffer to read the data from - */ -static void ata_wr_sector(struct ata_ioports *io, const void *buf) -{ - unsigned u = SECTOR_SIZE / sizeof(uint16_t); - const uint16_t *b = buf; - - if (io->dataif_be) { - for (; u > 0; u--) - writew(cpu_to_be16(*b++), io->data_addr); - } else { - for (; u > 0; u--) - writew(cpu_to_le16(*b++), io->data_addr); - } -} - -/** - * Read the ATA disk's description info - * @param d All we need to know about the disk - * @return 0 on success - */ -static int ata_get_id(struct ata_drive_access *d) -{ - int rc; - - writeb(0xA0, d->io->device_addr); /* FIXME drive */ - writeb(0x00, d->io->lbal_addr); - writeb(0x00, d->io->lbam_addr); - writeb(0x00, d->io->lbah_addr); - - rc = ata_wr_cmd(d->io, ATA_CMD_ID_DEVICE); - if (rc != 0) - return rc; - - rc = ata_wait_ready(d->io, MAX_TIMEOUT); - if (rc != 0) - return rc; - - ata_rd_sector(d->io, &d->id); - - ata_fix_endianess(d->id, SECTOR_SIZE / sizeof(uint16_t)); - - return ata_id_is_valid(d->id); -} - -static int ata_reset(struct ata_ioports *io) -{ - int rc; - uint8_t reg; - - /* try a hard reset first (if available) */ - if (io->reset != NULL) { - pr_debug("%s: Resetting drive...\n", __func__); - io->reset(1); - rc = ata_wait_busy(io, 500); - io->reset(0); - if (rc == 0) { - rc = ata_wait_ready(io, MAX_TIMEOUT); - if (rc != 0) - return rc; - } else { - pr_debug("%s: Drive does not respond to RESET line. Ignored\n", - __func__); - } - } - - /* try a soft reset */ - ata_wr_dev_ctrl(io, ATA_DEVCTL_SOFT_RESET | ATA_DEVCTL_INTR_DISABLE); - rc = ata_wait_busy(io, MAX_TIMEOUT); /* does the drive accept the command? */ - if (rc != 0) { - pr_debug("%s: Drive fails on soft reset\n", __func__); - return rc; - } - ata_wr_dev_ctrl(io, ATA_DEVCTL_INTR_DISABLE); - rc = ata_wait_ready(io, MAX_TIMEOUT); - if (rc != 0) { - pr_debug("%s: Drive fails after soft reset\n", __func__); - return rc; - } - - reg = ata_rd_status(io) & 0xf; - - if (reg == 0xf) { - pr_debug("%s: Seems no drive connected!\n", __func__); - return -ENODEV; - } - - return 0; -} - -/** * Read a chunk of sectors from the drive * @param blk All info about the block device we need * @param buffer Buffer to read into @@ -474,27 +222,9 @@ static int ata_reset(struct ata_ioports *io) static int ata_read(struct block_device *blk, void *buffer, int block, int num_blocks) { - int rc; - uint64_t sector = block; - struct ata_drive_access *drv = to_ata_drive_access(blk); - - while (num_blocks) { - rc = ata_set_lba_sector(drv->io, DISK_MASTER, sector); - if (rc != 0) - return rc; - rc = ata_wr_cmd(drv->io, ATA_CMD_RD); - if (rc != 0) - return rc; - rc = ata_wait_ready(drv->io, MAX_TIMEOUT); - if (rc != 0) - return rc; - ata_rd_sector(drv->io, buffer); - num_blocks--; - sector++; - buffer += SECTOR_SIZE; - } + struct ata_port *port = container_of(blk, struct ata_port, blk); - return 0; + return port->ops->read(port, buffer, block, num_blocks); } /** @@ -513,24 +243,9 @@ static int ata_read(struct block_device *blk, void *buffer, int block, static int __maybe_unused ata_write(struct block_device *blk, const void *buffer, int block, int num_blocks) { - int rc; - uint64_t sector = block; - struct ata_drive_access *drv = to_ata_drive_access(blk); - - while (num_blocks) { - rc = ata_set_lba_sector(drv->io, DISK_MASTER, sector); - if (rc != 0) - return rc; - rc = ata_wr_cmd(drv->io, ATA_CMD_WR); - if (rc != 0) - return rc; - ata_wr_sector(drv->io, buffer); - num_blocks--; - sector++; - buffer += SECTOR_SIZE; - } + struct ata_port *port = container_of(blk, struct ata_port, blk); - return 0; + return port->ops->write(port, buffer, block, num_blocks); } static struct block_device_ops ata_ops = { @@ -546,55 +261,67 @@ static struct block_device_ops ata_ops = { * @param io ATA register file description * @return 0 on success */ -int register_ata_drive(struct device_d *dev, struct ata_ioports *io) +int ata_port_register(struct ata_port *port) { int rc; - struct ata_drive_access *drive; + struct ata_port_operations *ops = port->ops; + struct device_d *dev = port->dev; - drive = xzalloc(sizeof(struct ata_drive_access)); + port->id = dma_alloc(SECTOR_SIZE); - drive->io = io; - drive->blk.dev = dev; - drive->blk.ops = &ata_ops; + port->blk.dev = dev; + port->blk.ops = &ata_ops; - rc = ata_reset(io); - if (rc) { - dev_dbg(dev, "Resetting failed\n"); - goto on_error; + if (ops->reset) { + rc = ops->reset(port); + if (rc) { + dev_dbg(dev, "Resetting failed\n"); + goto on_error; + } } - rc = ata_get_id(drive); + rc = ops->read_id(port, port->id); if (rc != 0) { dev_dbg(dev, "Reading ID failed\n"); goto on_error; } + ata_fix_endianess(port->id, SECTOR_SIZE / sizeof(uint16_t)); + + rc = ata_id_is_valid(port->id); + if (rc) { + dev_err(dev, "ata id invalid\n"); + free(port->id); + return rc; + } + #ifdef DEBUG - ata_dump_id(drive->id); + ata_dump_id(port->id); #endif - rc = cdev_find_free_index("disk"); + rc = cdev_find_free_index("ata"); if (rc == -1) pr_err("Cannot find a free index for the disk node\n"); - drive->blk.num_blocks = ata_id_n_sectors(drive->id); - drive->blk.cdev.name = asprintf("disk%d", rc); - drive->blk.blockbits = SECTOR_SHIFT; + port->blk.num_blocks = ata_id_n_sectors(port->id); + port->blk.cdev.name = asprintf("ata%d", rc); + port->blk.blockbits = SECTOR_SHIFT; - rc = blockdevice_register(&drive->blk); + rc = blockdevice_register(&port->blk); if (rc != 0) { dev_err(dev, "Failed to register blockdevice\n"); goto on_error; } + dev_info(dev, "registered /dev/%s\n", port->blk.cdev.name); + /* create partitions on demand */ - rc = parse_partition_table(&drive->blk); + rc = parse_partition_table(&port->blk); if (rc != 0) dev_warn(dev, "No partition table found\n"); return 0; on_error: - free(drive); return rc; } diff --git a/drivers/ata/ide-sff.c b/drivers/ata/ide-sff.c new file mode 100644 index 0000000000..3dd6f63e09 --- /dev/null +++ b/drivers/ata/ide-sff.c @@ -0,0 +1,343 @@ +#include <common.h> +#include <ata_drive.h> +#include <io.h> +#include <clock.h> +#include <disks.h> +#include <malloc.h> + +/* max timeout for a rotating disk in [ms] */ +#define MAX_TIMEOUT 5000 + +/** + * Collection of data we need to know about this drive + */ +struct ide_port { + struct ata_ioports *io; /**< register file */ + struct ata_port port; +}; + +#define to_ata_drive_access(x) container_of((x), struct ide_port, port) + +#define DISK_MASTER 0 +#define DISK_SLAVE 1 + +/** + * Read the status register of the ATA drive + * @param io Register file + * @return Register's content + */ +static uint8_t ata_rd_status(struct ide_port *ide) +{ + return readb(ide->io->status_addr); +} + +/** + * Wait until the disk is busy or time out + * @param io Register file + * @param timeout Timeout in [ms] + * @return 0 on success, -ETIMEDOUT else + */ +static int ata_wait_busy(struct ide_port *ide, unsigned timeout) +{ + uint8_t status; + uint64_t start = get_time_ns(); + uint64_t toffs = timeout * 1000 * 1000; + + do { + status = ata_rd_status(ide); + if (status & ATA_STATUS_BUSY) + return 0; + } while (!is_timeout(start, toffs)); + + return -ETIMEDOUT; +} + +/** + * Wait until the disk is ready again or time out + * @param io Register file + * @param timeout Timeout in [ms] + * @return 0 on success, -ETIMEDOUT else + * + * This function is useful to check if the disk has accepted a command. + */ +static int ata_wait_ready(struct ide_port *ide, unsigned timeout) +{ + uint8_t status; + uint64_t start = get_time_ns(); + uint64_t toffs = timeout * 1000 * 1000; + + do { + status = ata_rd_status(ide); + if (!(status & ATA_STATUS_BUSY)) { + if (status & ATA_STATUS_READY) + return 0; + } + } while (!is_timeout(start, toffs)); + + return -ETIMEDOUT; +} + +/** + * Setup the sector number in LBA notation (LBA28) + * @param io Register file + * @param drive 0 master drive, 1 slave drive + * @param num Sector number + * + * @todo LBA48 support + */ +static int ata_set_lba_sector(struct ide_port *ide, unsigned drive, uint64_t num) +{ + if (num > 0x0FFFFFFF || drive > 1) + return -EINVAL; + + writeb(0xA0 | LBA_FLAG | drive << 4 | num >> 24, ide->io->device_addr); + writeb(0x00, ide->io->error_addr); + writeb(0x01, ide->io->nsect_addr); + writeb(num, ide->io->lbal_addr); /* 0 ... 7 */ + writeb(num >> 8, ide->io->lbam_addr); /* 8 ... 15 */ + writeb(num >> 16, ide->io->lbah_addr); /* 16 ... 23 */ + + return 0; +} + +/** + * Write an ATA command into the disk + * @param io Register file + * @param cmd Command to write + * @return 0 on success + */ +static int ata_wr_cmd(struct ide_port *ide, uint8_t cmd) +{ + int rc; + + rc = ata_wait_ready(ide, MAX_TIMEOUT); + if (rc != 0) + return rc; + + writeb(cmd, ide->io->command_addr); + return 0; +} + +/** + * Write a new value into the "device control register" + * @param io Register file + * @param val Value to write + */ +static void ata_wr_dev_ctrl(struct ide_port *ide, uint8_t val) +{ + writeb(val, ide->io->ctl_addr); +} + +/** + * Read one sector from the drive (always SECTOR_SIZE bytes at once) + * @param io Register file + * @param buf Buffer to read the data into + */ +static void ata_rd_sector(struct ide_port *ide, void *buf) +{ + unsigned u = SECTOR_SIZE / sizeof(uint16_t); + uint16_t *b = buf; + + if (ide->io->dataif_be) { + for (; u > 0; u--) + *b++ = be16_to_cpu(readw(ide->io->data_addr)); + } else { + for (; u > 0; u--) + *b++ = le16_to_cpu(readw(ide->io->data_addr)); + } +} + +/** + * Write one sector into the drive + * @param io Register file + * @param buf Buffer to read the data from + */ +static void ata_wr_sector(struct ide_port *ide, const void *buf) +{ + unsigned u = SECTOR_SIZE / sizeof(uint16_t); + const uint16_t *b = buf; + + if (ide->io->dataif_be) { + for (; u > 0; u--) + writew(cpu_to_be16(*b++), ide->io->data_addr); + } else { + for (; u > 0; u--) + writew(cpu_to_le16(*b++), ide->io->data_addr); + } +} + +/** + * Read the ATA disk's description info + * @param d All we need to know about the disk + * @return 0 on success + */ +static int ide_read_id(struct ata_port *port, void *buf) +{ + struct ide_port *ide = to_ata_drive_access(port); + int rc; + + writeb(0xA0, ide->io->device_addr); /* FIXME drive */ + writeb(0x00, ide->io->lbal_addr); + writeb(0x00, ide->io->lbam_addr); + writeb(0x00, ide->io->lbah_addr); + + rc = ata_wr_cmd(ide, ATA_CMD_ID_ATA); + if (rc != 0) + return rc; + + rc = ata_wait_ready(ide, MAX_TIMEOUT); + if (rc != 0) + return rc; + + ata_rd_sector(ide, buf); + + return 0; +} + +static int ide_reset(struct ata_port *port) +{ + struct ide_port *ide = to_ata_drive_access(port); + int rc; + uint8_t reg; + + /* try a hard reset first (if available) */ + if (ide->io->reset != NULL) { + pr_debug("%s: Resetting drive...\n", __func__); + ide->io->reset(1); + rc = ata_wait_busy(ide, 500); + ide->io->reset(0); + if (rc == 0) { + rc = ata_wait_ready(ide, MAX_TIMEOUT); + if (rc != 0) + return rc; + } else { + pr_debug("%s: Drive does not respond to RESET line. Ignored\n", + __func__); + } + } + + /* try a soft reset */ + ata_wr_dev_ctrl(ide, ATA_DEVCTL_SOFT_RESET | ATA_DEVCTL_INTR_DISABLE); + rc = ata_wait_busy(ide, MAX_TIMEOUT); /* does the drive accept the command? */ + if (rc != 0) { + pr_debug("%s: Drive fails on soft reset\n", __func__); + return rc; + } + ata_wr_dev_ctrl(ide, ATA_DEVCTL_INTR_DISABLE); + rc = ata_wait_ready(ide, MAX_TIMEOUT); + if (rc != 0) { + pr_debug("%s: Drive fails after soft reset\n", __func__); + return rc; + } + + reg = ata_rd_status(ide) & 0xf; + + if (reg == 0xf) { + pr_debug("%s: Seems no drive connected!\n", __func__); + return -ENODEV; + } + + return 0; +} + +/** + * Read a chunk of sectors from the drive + * @param blk All info about the block device we need + * @param buffer Buffer to read into + * @param block Sector's LBA number to start read from + * @param num_blocks Sector count to read + * @return 0 on success, anything else on failure + * + * This routine expects the buffer has the correct size to store all data! + * + * @note Due to 'block' is of type 'int' only small disks can be handled! + * @todo Optimize the read loop + */ +static int ide_read(struct ata_port *port, void *buffer, unsigned int block, + int num_blocks) +{ + int rc; + uint64_t sector = block; + struct ide_port *ide = to_ata_drive_access(port); + + while (num_blocks) { + rc = ata_set_lba_sector(ide, DISK_MASTER, sector); + if (rc != 0) + return rc; + rc = ata_wr_cmd(ide, ATA_CMD_READ); + if (rc != 0) + return rc; + rc = ata_wait_ready(ide, MAX_TIMEOUT); + if (rc != 0) + return rc; + ata_rd_sector(ide, buffer); + num_blocks--; + sector++; + buffer += SECTOR_SIZE; + } + + return 0; +} + +/** + * Write a chunk of sectors into the drive + * @param blk All info about the block device we need + * @param buffer Buffer to write from + * @param block Sector's number to start write to + * @param num_blocks Sector count to write + * @return 0 on success, anything else on failure + * + * This routine expects the buffer has the correct size to read all data! + * + * @note Due to 'block' is of type 'int' only small disks can be handled! + * @todo Optimize the write loop + */ +static int __maybe_unused ide_write(struct ata_port *port, + const void *buffer, unsigned int block, int num_blocks) +{ + int rc; + uint64_t sector = block; + struct ide_port *ide = to_ata_drive_access(port); + + while (num_blocks) { + rc = ata_set_lba_sector(ide, DISK_MASTER, sector); + if (rc != 0) + return rc; + rc = ata_wr_cmd(ide, ATA_CMD_WRITE); + if (rc != 0) + return rc; + ata_wr_sector(ide, buffer); + num_blocks--; + sector++; + buffer += SECTOR_SIZE; + } + + return 0; +} + +static struct ata_port_operations ide_ops = { + .read_id = ide_read_id, + .read = ide_read, +#ifdef CONFIG_BLOCK_WRITE + .write = ide_write, +#endif + .reset = ide_reset, +}; + +int ide_port_register(struct device_d *dev, struct ata_ioports *io) +{ + struct ide_port *ide; + int ret; + + ide = xzalloc(sizeof(*ide)); + + ide->io = io; + ide->port.ops = &ide_ops; + + ret = ata_port_register(&ide->port); + + if (ret) + free(ide); + + return ret; +} diff --git a/drivers/ata/intf_platform_ide.c b/drivers/ata/intf_platform_ide.c index a1840f7bbc..6473b38ba3 100644 --- a/drivers/ata/intf_platform_ide.c +++ b/drivers/ata/intf_platform_ide.c @@ -95,7 +95,7 @@ static int platform_ide_probe(struct device_d *dev) io->reset = pdata->reset; io->dataif_be = pdata->dataif_be; - rc = register_ata_drive(dev, io); + rc = ide_port_register(dev, io); if (rc != 0) { dev_err(dev, "Cannot register IDE interface\n"); free(io); diff --git a/drivers/ata/pata-imx.c b/drivers/ata/pata-imx.c new file mode 100644 index 0000000000..202f537569 --- /dev/null +++ b/drivers/ata/pata-imx.c @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2011 Juergen Beisert, Pengutronix + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * Derived from the Linux kernel: Generic platform device PATA driver + * Copyright (C) 2006 - 2007 Paul Mundt + * Based on pata_pcmcia: + * Copyright 2005-2006 Red Hat Inc, all rights reserved. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * 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 <init.h> +#include <xfuncs.h> +#include <malloc.h> +#include <errno.h> +#include <ata_drive.h> +#include <platform_ide.h> +#include <io.h> +#include <linux/err.h> +#include <linux/clk.h> + +#define PATA_IMX_ATA_TIME_OFF 0x0 +#define PATA_IMX_ATA_TIME_ON 0x1 +#define PATA_IMX_ATA_TIME_1 0x2 +#define PATA_IMX_ATA_TIME_2W 0x3 +#define PATA_IMX_ATA_TIME_2R 0x4 +#define PATA_IMX_ATA_TIME_AX 0x5 +#define PATA_IMX_ATA_TIME_PIO_RDX 0x6 +#define PATA_IMX_ATA_TIME_4 0x7 +#define PATA_IMX_ATA_TIME_9 0x8 +#define PATA_IMX_ATA_TIME_M 0x9 +#define PATA_IMX_ATA_TIME_JN 0xa +#define PATA_IMX_ATA_TIME_D 0xb +#define PATA_IMX_ATA_TIME_K 0xc +#define PATA_IMX_ATA_TIME_ACK 0xd +#define PATA_IMX_ATA_TIME_ENV 0xe +#define PATA_IMX_ATA_TIME_UDMA_RDX 0xf +#define PATA_IMX_ATA_TIME_ZAH 0x10 +#define PATA_IMX_ATA_TIME_MLIX 0x11 +#define PATA_IMX_ATA_TIME_DVH 0x12 +#define PATA_IMX_ATA_TIME_DZFS 0x13 +#define PATA_IMX_ATA_TIME_DVS 0x14 +#define PATA_IMX_ATA_TIME_CVH 0x15 +#define PATA_IMX_ATA_TIME_SS 0x16 +#define PATA_IMX_ATA_TIME_CYC 0x17 +#define PATA_IMX_ATA_CONTROL 0x24 +#define PATA_IMX_ATA_CTRL_FIFO_RST_B (1<<7) +#define PATA_IMX_ATA_CTRL_ATA_RST_B (1<<6) +#define PATA_IMX_ATA_CTRL_IORDY_EN (1<<0) +#define PATA_IMX_ATA_INT_EN 0x2C +#define PATA_IMX_ATA_INTR_ATA_INTRQ2 (1<<3) +#define PATA_IMX_DRIVE_DATA 0xA0 +#define PATA_IMX_DRIVE_CONTROL 0xD8 + +static uint16_t pio_t1[] = { 70, 50, 30, 30, 25 }; +static uint16_t pio_t2_8[] = { 290, 290, 290, 80, 70 }; +static uint16_t pio_t4[] = { 30, 20, 15, 10, 10 }; +static uint16_t pio_t9[] = { 20, 15, 10, 10, 10 }; +static uint16_t pio_tA[] = { 50, 50, 50, 50, 50 }; + +static void pata_imx_set_bus_timing(void __iomem *base, unsigned long clkrate, + unsigned char mode) +{ + uint32_t T = 1000000000 / clkrate; + + struct mxc_ata_config_regs *ata_regs; + ata_regs = (struct mxc_ata_config_regs *)base; + + if (mode >= ARRAY_SIZE(pio_t1)) + return; + + /* Write TIME_OFF/ON/1/2W */ + writeb(3, base + PATA_IMX_ATA_TIME_OFF); + writeb(3, base + PATA_IMX_ATA_TIME_ON); + writeb((pio_t1[mode] + T) / T, base + PATA_IMX_ATA_TIME_1); + writeb((pio_t2_8[mode] + T) / T, base + PATA_IMX_ATA_TIME_2W); + + /* Write TIME_2R/AX/RDX/4 */ + writeb((pio_t2_8[mode] + T) / T, base + PATA_IMX_ATA_TIME_2R); + writeb((pio_tA[mode] + T) / T + 2, base + PATA_IMX_ATA_TIME_AX); + writeb(1, base + PATA_IMX_ATA_TIME_PIO_RDX); + writeb((pio_t4[mode] + T) / T, base + PATA_IMX_ATA_TIME_4); + + /* Write TIME_9 ; the rest of timing registers is irrelevant for PIO */ + writeb((pio_t9[mode] + T) / T, base + PATA_IMX_ATA_TIME_9); +} + +/** + * Setup the register specific addresses for an ATA like divice + * @param reg_base Base address of the standard ATA like registers + * @param alt_base Base address of the alternate ATA like registers + * @param ioaddr Register file structure to setup + * @param shift Shift offset between registers + * + * Some of the registers have different names but use the same offset. This is + * due to the fact read or write access at the same offset reaches different + * registers. + */ +static void imx_pata_setup_port(void *reg_base, void *alt_base, + struct ata_ioports *ioaddr, unsigned shift) +{ + /* standard registers (0 ... 7) */ + ioaddr->cmd_addr = reg_base; + + ioaddr->data_addr = reg_base + (IDE_REG_DATA << shift); + + ioaddr->error_addr = reg_base + (IDE_REG_ERR << shift); + ioaddr->feature_addr = reg_base + (IDE_REG_FEATURE << shift); + + ioaddr->nsect_addr = reg_base + (IDE_REG_NSECT << shift); + + ioaddr->lbal_addr = reg_base + (IDE_REG_LBAL << shift); + + ioaddr->lbam_addr = reg_base + (IDE_REG_LBAM << shift); + + ioaddr->lbah_addr = reg_base + (IDE_REG_LBAH << shift); + + ioaddr->device_addr = reg_base + (IDE_REG_DEVICE << shift); + + ioaddr->status_addr = reg_base + (IDE_REG_STATUS << shift); + ioaddr->command_addr = reg_base + (IDE_REG_CMD << shift); + + if (alt_base) { + ioaddr->altstatus_addr = alt_base + (IDE_REG_ALT_STATUS << shift); + ioaddr->ctl_addr = alt_base + (IDE_REG_DEV_CTL << shift); + + ioaddr->alt_dev_addr = alt_base + (IDE_REG_DRV_ADDR << shift); + } else { + ioaddr->altstatus_addr = ioaddr->status_addr; + ioaddr->ctl_addr = ioaddr->status_addr; + /* ioaddr->alt_dev_addr not used in driver */ + } +} + +static int imx_pata_probe(struct device_d *dev) +{ + struct ata_ioports *io; + struct clk *clk; + void __iomem *base; + int ret; + + io = xzalloc(sizeof(struct ata_ioports)); + base = dev_request_mem_region(dev, 0); + + clk = clk_get(dev, NULL); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + goto out_free; + } + + imx_pata_setup_port(base + PATA_IMX_DRIVE_DATA, + base + PATA_IMX_DRIVE_CONTROL, io, 2); + + /* deassert resets */ + writel(PATA_IMX_ATA_CTRL_FIFO_RST_B | + PATA_IMX_ATA_CTRL_ATA_RST_B, + base + PATA_IMX_ATA_CONTROL); + + pata_imx_set_bus_timing(base, clk_get_rate(clk), 4); + + ret= ide_port_register(dev, io); + if (ret) { + dev_err(dev, "Cannot register IDE interface: %s\n", + strerror(-ret)); + goto out_free_clk; + } + + return 0; + +out_free_clk: + clk_put(clk); + +out_free: + free(io); + + return ret; +} + +static struct driver_d imx_pata_driver = { + .name = "imx-pata", + .probe = imx_pata_probe, +}; + +static int imx_pata_init(void) +{ + return platform_driver_register(&imx_pata_driver); +} + +device_initcall(imx_pata_init); diff --git a/drivers/ata/sata-imx.c b/drivers/ata/sata-imx.c new file mode 100644 index 0000000000..fc57f5f104 --- /dev/null +++ b/drivers/ata/sata-imx.c @@ -0,0 +1,155 @@ +#include <common.h> +#include <ata_drive.h> +#include <io.h> +#include <clock.h> +#include <disks.h> +#include <driver.h> +#include <init.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <malloc.h> +#include <mach/imx53-regs.h> +#include <mach/imx6-regs.h> +#include <mfd/imx6q-iomuxc-gpr.h> +#include "ahci.h" + +#define HOST_TIMER1MS 0xe0 /* Timer 1-ms */ + +struct imx_ahci { + struct ahci_device ahci; + struct clk *clk; +}; + +struct imx_sata_data { + int (*init)(struct imx_ahci *imx_ahci); +}; + +static int imx6_sata_init(struct imx_ahci *imx_ahci) +{ + u32 val; + void __iomem *base = (void *)MX6_IOMUXC_BASE_ADDR; + + val = 0x11 << IMX6Q_GPR13_SATA_PHY_2_OFF | IMX6Q_GPR13_SATA_PHY_4_9_16 | + IMX6Q_GPR13_SATA_SPEED_MASK | 0x3 << IMX6Q_GPR13_SATA_PHY_6_OFF | + IMX6Q_GPR13_SATA_PHY_7_SATA2I | IMX6Q_GPR13_SATA_PHY_8_3_0_DB; + + writel(val, base + IOMUXC_GPR13); + writel(val | 2, base + IOMUXC_GPR13); + + return 0; +} + +static int imx53_sata_init(struct imx_ahci *imx_ahci) +{ + u32 val; + void __iomem *base = (void *)MX53_IIM_BASE_ADDR; + + /* + * The clock for the external interface can be set to use internal clock + * if fuse bank 4, row 3, bit 2 is set. + * This is an undocumented feature and it was confirmed by Freescale's support: + * Fuses (but not pins) may be used to configure SATA clocks. + * Particularly the i.MX53 Fuse_Map contains the next information + * about configuring SATA clocks : SATA_ALT_REF_CLK[1:0] (offset 0x180C) + * '00' - 100MHz (External) + * '01' - 50MHz (External) + * '10' - 120MHz, internal (USB PHY) + * '11' - Reserved + */ + val = readl(base + 0x180c); + val &= (0x3 << 1); + val |= (0x1 << 1); + writel(val, base + 0x180c); + + return 0; +} + +static int imx_sata_init_1ms(struct imx_ahci *imx_ahci) +{ + void __iomem *base = imx_ahci->ahci.mmio_base; + u32 val; + + val = readl(base + HOST_PORTS_IMPL); + writel(val | 1, base + HOST_PORTS_IMPL); + + val = clk_get_rate(imx_ahci->clk) / 1000; + + writel(val, base + HOST_TIMER1MS); + + return 0; +} + +static int imx_sata_probe(struct device_d *dev) +{ + struct imx_ahci *imx_ahci; + struct imx_sata_data *data; + int ret; + + ret = dev_get_drvdata(dev, (unsigned long *)&data); + if (ret) + return ret; + + imx_ahci = xzalloc(sizeof(*imx_ahci)); + + imx_ahci->clk = clk_get(dev, NULL); + if (IS_ERR(imx_ahci->clk)) { + ret = PTR_ERR(imx_ahci->clk); + goto err_free; + } + + imx_ahci->ahci.mmio_base = dev_request_mem_region(dev, 0); + if (!imx_ahci->ahci.mmio_base) + return -ENODEV; + + data->init(imx_ahci); + + imx_sata_init_1ms(imx_ahci); + + imx_ahci->ahci.dev = dev; + dev->priv = &imx_ahci->ahci; + + ret = ahci_add_host(&imx_ahci->ahci); + if (ret) + goto err_free; + + return 0; + +err_free: + free(imx_ahci); + + return ret; +} + +struct imx_sata_data data_imx6 = { + .init = imx6_sata_init, +}; + +struct imx_sata_data data_imx53 = { + .init = imx53_sata_init, +}; + +static struct platform_device_id imx_sata_ids[] = { + { + .name = "imx6-sata", + .driver_data = (unsigned long)&data_imx6, + }, { + .name = "imx53-sata", + .driver_data = (unsigned long)&data_imx53, + }, { + /* sentinel */ + }, +}; + +static struct driver_d imx_sata_driver = { + .name = "imx-sata", + .probe = imx_sata_probe, + .info = ahci_info, + .id_table = imx_sata_ids, +}; + +static int ahci_init(void) +{ + return platform_driver_register(&imx_sata_driver); +} + +device_initcall(ahci_init); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 69782d2e7b..e2204da4a4 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -25,9 +25,19 @@ static struct bus_type *get_bus_by_name(const char *name) int bus_register(struct bus_type *bus) { + int ret; + if (get_bus_by_name(bus->name)) return -EEXIST; + strcpy(bus->dev.name, bus->name); + bus->dev.id = DEVICE_ID_SINGLE; + + ret = register_device(&bus->dev); + if (ret) + return ret; + + INIT_LIST_HEAD(&bus->device_list); INIT_LIST_HEAD(&bus->driver_list); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index dc2df91522..c2e681934f 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -125,6 +125,11 @@ int register_device(struct device_d *new_device) if (!new_device->bus) return 0; + if (!new_device->parent) { + new_device->parent = &new_device->bus->dev; + dev_add_child(new_device->parent, new_device); + } + list_add_tail(&new_device->bus_list, &new_device->bus->device_list); bus_for_each_driver(new_device->bus, drv) { diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 3cc7163829..656b8594b1 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \ - clk-mux.o clk-gate.o + clk-mux.o clk-gate.o clk-divider-table.o obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o diff --git a/drivers/clk/clk-divider-table.c b/drivers/clk/clk-divider-table.c new file mode 100644 index 0000000000..204e24d576 --- /dev/null +++ b/drivers/clk/clk-divider-table.c @@ -0,0 +1,119 @@ +/* + * clk-divider-table.c - generic barebox clock support. Based on Linux clk support + * + * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, 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. + * + */ +#include <common.h> +#include <io.h> +#include <malloc.h> +#include <linux/clk.h> +#include <linux/err.h> + +struct clk_divider_table { + struct clk clk; + u8 shift; + u8 width; + void __iomem *reg; + const char *parent; + const struct clk_div_table *table; + int table_size; + int max_div_index; +}; + +static int clk_divider_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_divider_table *div = + container_of(clk, struct clk_divider_table, clk); + unsigned int val; + int i, div_index = -1; + unsigned long best = 0; + + if (rate > parent_rate) + rate = parent_rate; + if (rate < parent_rate / div->table[div->max_div_index].div) + rate = parent_rate / div->table[div->max_div_index].div; + + for (i = 0; i < div->table_size; i++) { + unsigned long now = parent_rate / div->table[i].div; + + if (now <= rate && now >= best) { + best = now; + div_index = i; + } + } + + val = readl(div->reg); + val &= ~(((1 << div->width) - 1) << div->shift); + val |= div_index << div->shift; + writel(val, div->reg); + + return 0; +} + +static unsigned long clk_divider_recalc_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_divider_table *div = + container_of(clk, struct clk_divider_table, clk); + unsigned int val; + + val = readl(div->reg) >> div->shift; + val &= (1 << div->width) - 1; + + if (val >= div->table_size) + return 0; + + return parent_rate / div->table[val].div; +} + +struct clk_ops clk_divider_table_ops = { + .set_rate = clk_divider_set_rate, + .recalc_rate = clk_divider_recalc_rate, +}; + +struct clk *clk_divider_table(const char *name, + const char *parent, void __iomem *reg, u8 shift, u8 width, + const struct clk_div_table *table) +{ + struct clk_divider_table *div = xzalloc(sizeof(*div)); + const struct clk_div_table *clkt; + int ret, max_div = 0; + + div->shift = shift; + div->reg = reg; + div->width = width; + div->parent = parent; + div->clk.ops = &clk_divider_table_ops; + div->clk.name = name; + div->clk.parent_names = &div->parent; + div->clk.num_parents = 1; + div->table = table; + + for (clkt = div->table; clkt->div; clkt++) { + if (clkt->div > max_div) { + max_div = clkt->div; + div->max_div_index = div->table_size; + } + div->table_size++; + } + + ret = clk_register(&div->clk); + if (ret) { + free(div); + return ERR_PTR(ret); + } + + return &div->clk; +} diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c index fa89cb2840..5e81e72946 100644 --- a/drivers/clk/clk-fixed.c +++ b/drivers/clk/clk-fixed.c @@ -44,6 +44,7 @@ struct clk *clk_fixed(const char *name, int rate) fix->rate = rate; fix->clk.ops = &clk_fixed_ops; fix->clk.name = name; + fix->clk.flags = CLK_ALWAYS_ENABLED; ret = clk_register(&fix->clk); if (ret) { diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index bf61e5db94..cb94755c5a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -43,6 +43,12 @@ int clk_enable(struct clk *clk) { int ret; + if (IS_ERR(clk)) + return PTR_ERR(clk); + + if (clk->flags & CLK_ALWAYS_ENABLED) + return 0; + if (!clk->enable_count) { ret = clk_parent_enable(clk); if (ret) @@ -64,6 +70,12 @@ int clk_enable(struct clk *clk) void clk_disable(struct clk *clk) { + if (IS_ERR(clk)) + return; + + if (clk->flags & CLK_ALWAYS_ENABLED) + return; + if (!clk->enable_count) return; @@ -82,6 +94,9 @@ unsigned long clk_get_rate(struct clk *clk) struct clk *parent; unsigned long parent_rate = 0; + if (IS_ERR(clk)) + return 0; + parent = clk_get_parent(clk); if (!IS_ERR_OR_NULL(parent)) parent_rate = clk_get_rate(parent); @@ -94,6 +109,9 @@ unsigned long clk_get_rate(struct clk *clk) long clk_round_rate(struct clk *clk, unsigned long rate) { + if (IS_ERR(clk)) + return 0; + return clk_get_rate(clk); } @@ -102,6 +120,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) struct clk *parent; unsigned long parent_rate = 0; + if (IS_ERR(clk)) + return PTR_ERR(clk); + parent = clk_get_parent(clk); if (parent) parent_rate = clk_get_rate(parent); @@ -131,6 +152,11 @@ int clk_set_parent(struct clk *clk, struct clk *parent) { int i; + if (IS_ERR(clk)) + return PTR_ERR(clk); + if (IS_ERR(parent)) + return PTR_ERR(parent); + if (!clk->num_parents) return -EINVAL; if (!clk->ops->set_parent) @@ -155,6 +181,9 @@ struct clk *clk_get_parent(struct clk *clk) { int idx; + if (IS_ERR(clk)) + return clk; + if (!clk->num_parents) return ERR_PTR(-ENODEV); @@ -182,15 +211,23 @@ int clk_register(struct clk *clk) list_add_tail(&clk->list, &clks); + if (clk->flags & CLK_ALWAYS_ENABLED) { + clk->enable_count = 1; + } + return 0; } static void dump_one(struct clk *clk, int verbose, int indent) { struct clk *c; + char *always = ""; + + if (clk->flags & CLK_ALWAYS_ENABLED) + always = "always "; - printf("%*s%s (rate %ld, %sabled)\n", indent * 4, "", clk->name, clk_get_rate(clk), - clk->enable_count ? "en" : "dis"); + printf("%*s%s (rate %ld, %s%sabled)\n", indent * 4, "", clk->name, clk_get_rate(clk), + always, clk->enable_count ? "en" : "dis"); if (verbose) { if (clk->num_parents > 1) { diff --git a/drivers/eeprom/at25.c b/drivers/eeprom/at25.c index 5578c783ad..9bd7748c64 100644 --- a/drivers/eeprom/at25.c +++ b/drivers/eeprom/at25.c @@ -232,15 +232,10 @@ static ssize_t at25_ee_write(struct cdev *cdev, return written ? written : status; } -static loff_t at25_ee_lseek(struct cdev *cdev, loff_t off) -{ - return off; -} - static struct file_operations at25_fops = { .read = at25_ee_read, .write = at25_ee_write, - .lseek = at25_ee_lseek, + .lseek = dev_lseek_default, }; static int at25_probe(struct device_d *dev) diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 106093b722..8ca6ab8e44 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -11,6 +11,10 @@ config LED_GPIO_RGB bool "gpio rgb LED support" depends on LED_GPIO +config LED_GPIO_BICOLOR + bool "gpio bicolor LED support" + depends on LED_GPIO + config LED_TRIGGERS select POLLER bool "LED triggers support" diff --git a/drivers/led/led-gpio.c b/drivers/led/led-gpio.c index 711146b012..c78ef9e1cb 100644 --- a/drivers/led/led-gpio.c +++ b/drivers/led/led-gpio.c @@ -52,6 +52,53 @@ void led_gpio_unregister(struct gpio_led *led) led_unregister(&led->led); } +#ifdef CONFIG_LED_GPIO_BICOLOR +static void led_gpio_bicolor_set(struct led *led, unsigned int value) +{ + struct gpio_bicolor_led *bi = container_of(led, struct gpio_bicolor_led, led); + int al = bi->active_low; + + switch (value) { + case 0: + gpio_direction_output(bi->gpio_c0, al); + gpio_direction_output(bi->gpio_c1, al); + break; + case 1: + gpio_direction_output(bi->gpio_c0, !al); + gpio_direction_output(bi->gpio_c1, al); + break; + case 2: + gpio_direction_output(bi->gpio_c0, al); + gpio_direction_output(bi->gpio_c1, !al); + break; + } +} + +/** + * led_gpio_bicolor_register - register three gpios as a bicolor LED + * @param led The gpio bicolor LED + * + * This function registers three gpios as a bicolor LED. led->gpio[rg] + * should be initialized to the gpios to control. + */ +int led_gpio_bicolor_register(struct gpio_bicolor_led *led) +{ + led->led.set = led_gpio_bicolor_set; + led->led.max_value = 2; + + return led_register(&led->led); +} + +/** + * led_gpio_bicolor_unregister - remove a gpio controlled bicolor LED from the framework + * @param led The gpio LED + */ +void led_gpio_bicolor_unregister(struct gpio_bicolor_led *led) +{ + led_unregister(&led->led); +} +#endif + #ifdef CONFIG_LED_GPIO_RGB static void led_gpio_rgb_set(struct led *led, unsigned int value) diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index dccffc6eec..e8075a9d92 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -279,7 +279,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) ret = wait_on_timeout(100 * MSECOND, esdhc_read32(®s->irqstat) & IRQSTAT_CC); if (ret) { - dev_err(host->dev, "timeout 1\n"); + dev_dbg(host->dev, "timeout 1\n"); return -ETIMEDOUT; } diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index bf2b0f897e..88892b646f 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -37,6 +37,20 @@ #define MAX_BUFFER_NUMBER 0xffffffff +#define UNSTUFF_BITS(resp,start,size) \ + ({ \ + const int __size = size; \ + const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \ + const int __off = 3 - ((start) / 32); \ + const int __shft = (start) & 31; \ + u32 __res; \ + \ + __res = resp[__off] >> __shft; \ + if (__size + __shft > 32) \ + __res |= resp[__off-1] << ((32 - __shft) % 32); \ + __res & __mask; \ + }) + /** * @file * @brief Memory Card framework @@ -724,7 +738,7 @@ static void mci_extract_max_tran_speed_from_csd(struct mci *mci) */ static void mci_extract_block_lengths_from_csd(struct mci *mci) { - mci->read_bl_len = 1 << ((mci->csd[1] >> 16) & 0xf); + mci->read_bl_len = 1 << UNSTUFF_BITS(mci->csd, 80, 4); if (IS_SD(mci)) mci->write_bl_len = mci->read_bl_len; /* FIXME why? */ @@ -744,15 +758,22 @@ static void mci_extract_card_capacity_from_csd(struct mci *mci) uint64_t csize, cmult; if (mci->high_capacity) { - csize = (mci->csd[1] & 0x3f) << 16 | (mci->csd[2] & 0xffff0000) >> 16; - cmult = 8; + if (IS_SD(mci)) { + csize = UNSTUFF_BITS(mci->csd, 48, 22); + mci->capacity = (1 + csize) << 10; + } else { + mci->capacity = mci->ext_csd[EXT_CSD_SEC_CNT] << 0 | + mci->ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | + mci->ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | + mci->ext_csd[EXT_CSD_SEC_CNT + 3] << 24; + } } else { - csize = (mci->csd[1] & 0x3ff) << 2 | (mci->csd[2] & 0xc0000000) >> 30; - cmult = (mci->csd[2] & 0x00038000) >> 15; + cmult = UNSTUFF_BITS(mci->csd, 47, 3); + csize = UNSTUFF_BITS(mci->csd, 62, 12); + mci->capacity = (csize + 1) << (cmult + 2); } - mci->capacity = (csize + 1) << (cmult + 2); - mci->capacity *= mci->read_bl_len; + mci->capacity *= 1 << UNSTUFF_BITS(mci->csd, 80, 4);; dev_dbg(mci->mci_dev, "Capacity: %u MiB\n", (unsigned)(mci->capacity >> 20)); } @@ -982,7 +1003,6 @@ static int mci_startup(struct mci *mci) mci_detect_version_from_csd(mci); mci_extract_max_tran_speed_from_csd(mci); mci_extract_block_lengths_from_csd(mci); - mci_extract_card_capacity_from_csd(mci); /* sanitiy? */ if (mci->read_bl_len > SECTOR_SIZE) { @@ -1018,6 +1038,8 @@ static int mci_startup(struct mci *mci) if (err) return err; + mci_extract_card_capacity_from_csd(mci); + /* Restrict card's capabilities by what the host can do */ mci->card_caps &= host->host_caps; @@ -1165,7 +1187,10 @@ static int mci_sd_read(struct block_device *blk, void *buffer, int block, */ static unsigned extract_mid(struct mci *mci) { - return mci->cid[0] >> 24; + if (!IS_SD(mci) && mci->version <= MMC_VERSION_1_4) + return UNSTUFF_BITS(mci->cid, 104, 24); + else + return UNSTUFF_BITS(mci->cid, 120, 8); } /** @@ -1198,7 +1223,15 @@ static unsigned extract_prv(struct mci *mci) */ static unsigned extract_psn(struct mci *mci) { - return (mci->cid[2] << 8) | (mci->cid[3] >> 24); + if (IS_SD(mci)) { + return UNSTUFF_BITS(mci->csd, 24, 32); + } else { + if (mci->version > MMC_VERSION_1_4) + return UNSTUFF_BITS(mci->cid, 16, 32); + else + return UNSTUFF_BITS(mci->cid, 16, 24); + } + } /** @@ -1209,7 +1242,10 @@ static unsigned extract_psn(struct mci *mci) */ static unsigned extract_mtd_month(struct mci *mci) { - return (mci->cid[3] >> 8) & 0xf; + if (IS_SD(mci)) + return UNSTUFF_BITS(mci->cid, 8, 4); + else + return UNSTUFF_BITS(mci->cid, 12, 4); } /** @@ -1221,7 +1257,10 @@ static unsigned extract_mtd_month(struct mci *mci) */ static unsigned extract_mtd_year(struct mci *mci) { - return ((mci->cid[3] >> 12) & 0xff) + 2000U; + if (IS_SD(mci)) + return UNSTUFF_BITS(mci->cid, 12, 8) + 2000; + else + return UNSTUFF_BITS(mci->cid, 8, 4) + 1997; } /** diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 3c2017ebe4..9e4bbcccf1 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -118,7 +118,8 @@ static int stmpe_probe(struct device_d *dev) } stmpe_dev = xzalloc(sizeof(struct stmpe)); - stmpe_dev->cdev.name = DRIVERNAME; + stmpe_dev->cdev.name = asprintf(DRIVERNAME "%d", + cdev_find_free_index(DRIVERNAME)); stmpe_dev->client = to_i2c_client(dev); stmpe_dev->cdev.size = 191; /* 191 known registers */ stmpe_dev->cdev.dev = dev; diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index 8601787286..b5916dab02 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -62,65 +62,15 @@ static ssize_t mtd_read(struct cdev *cdev, void* buf, size_t count, #define MTDPGALG(x) ((x) & ~(mtd->writesize - 1)) #ifdef CONFIG_MTD_WRITE -static int all_ff(const void *buf, int len) -{ - int i; - const uint8_t *p = buf; - - for (i = 0; i < len; i++) - if (p[i] != 0xFF) - return 0; - return 1; -} - static ssize_t mtd_write(struct cdev* cdev, const void *buf, size_t _count, 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); - return -EINVAL; - } - - dev_dbg(cdev->dev, "write: offset: 0x%08lx count: 0x%zx\n", offset, count); - while (count) { - now = count > mtd->writesize ? mtd->writesize : count; - - if (NOTALIGNED(now)) { - dev_dbg(cdev->dev, "not aligned: %d %ld\n", - mtd->writesize, - (offset % mtd->writesize)); - wrbuf = xmalloc(mtd->writesize); - memset(wrbuf, 0xff, mtd->writesize); - memcpy(wrbuf + (offset % mtd->writesize), buf, now); - if (!all_ff(wrbuf, mtd->writesize)) - ret = mtd->write(mtd, MTDPGALG(offset), - mtd->writesize, &retlen, - wrbuf); - free(wrbuf); - } else { - if (!all_ff(buf, mtd->writesize)) - ret = mtd->write(mtd, offset, now, &retlen, - buf); - dev_dbg(cdev->dev, - "offset: 0x%08lx now: 0x%zx retlen: 0x%zx\n", - offset, now, retlen); - } - if (ret) - goto out; + size_t retlen; + int ret; - offset += now; - count -= now; - buf += now; - } + ret = mtd->write(mtd, _offset, _count, &retlen, buf); -out: return ret ? ret : _count; } #endif diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c index c7bf40cef8..e5d803903a 100644 --- a/drivers/mtd/mtdoob.c +++ b/drivers/mtd/mtdoob.c @@ -73,6 +73,9 @@ static int add_mtdoob_device(struct mtd_info *mtd, char *devname, void **priv) { struct mtdoob *mtdoob; + if (mtd->oobsize == 0) + return 0; + mtdoob = xzalloc(sizeof(*mtdoob)); mtdoob->cdev.ops = &mtd_ops_oob; mtdoob->cdev.size = (mtd->size / mtd->writesize) * mtd->oobsize; diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c index 975a44f569..c4509d3dd6 100644 --- a/drivers/mtd/nand/nand_mxs.c +++ b/drivers/mtd/nand/nand_mxs.c @@ -1128,6 +1128,7 @@ int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info) int mxs_nand_hw_init(struct mxs_nand_info *info) { void __iomem *gpmi_regs = (void *)MXS_GPMI_BASE; + void __iomem *bch_regs = (void __iomem *)MXS_BCH_BASE; int i = 0, ret; u32 val; @@ -1153,6 +1154,15 @@ int mxs_nand_hw_init(struct mxs_nand_info *info) if (ret) return ret; + val = readl(gpmi_regs + GPMI_VERSION); + info->version = val >> GPMI_VERSION_MINOR_OFFSET; + + /* Reset BCH. Don't use SFTRST on MX23 due to Errata #2847 */ + ret = mxs_reset_block(bch_regs + BCH_CTRL, + info->version == GPMI_VERSION_TYPE_MX23); + if (ret) + return ret; + /* * Choose NAND mode, set IRQ polarity, disable write protection and * select BCH ECC. @@ -1163,9 +1173,6 @@ int mxs_nand_hw_init(struct mxs_nand_info *info) 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: diff --git a/drivers/mtd/nand/nand_write.c b/drivers/mtd/nand/nand_write.c index 5ed04cee57..999712795c 100644 --- a/drivers/mtd/nand/nand_write.c +++ b/drivers/mtd/nand/nand_write.c @@ -273,13 +273,6 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to, if (!writelen) return 0; - /* reject writes, which are not page aligned */ - if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { - printk(KERN_NOTICE "nand_write: " - "Attempt to write not page aligned data\n"); - return -EINVAL; - } - column = to & (mtd->writesize - 1); subpage = column || (writelen & (mtd->writesize - 1)); diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 35319b430b..762adfe020 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -106,7 +106,7 @@ static int mdio_bus_match(struct device_d *dev, struct driver_d *drv) struct phy_device *phydev = to_phy_device(dev); struct phy_driver *phydrv = to_phy_driver(drv); - return ((phydrv->phy_id & phydrv->phy_id_mask) == + return ((phydrv->phy_id & phydrv->phy_id_mask) != (phydev->phy_id & phydrv->phy_id_mask)); } diff --git a/drivers/watchdog/im28wd.c b/drivers/watchdog/im28wd.c index ca32a729d2..bc19369782 100644 --- a/drivers/watchdog/im28wd.c +++ b/drivers/watchdog/im28wd.c @@ -82,6 +82,17 @@ static void __maybe_unused imx28_detect_reset_source(const struct imx28_wd *p) if (reg & MXS_RTC_PERSISTENT0_EXT_RST) { writel(MXS_RTC_PERSISTENT0_EXT_RST, p->regs + MXS_RTC_PERSISTENT0 + MXS_RTC_CLR_ADDR); + /* + * if the RTC has woken up the SoC, additionally the ALARM_WAKE + * bit is set. This bit should have precedence, because it + * reports the real event, why we are here. + */ + if (reg & MXS_RTC_PERSISTENT0_ALARM_WAKE) { + writel(MXS_RTC_PERSISTENT0_ALARM_WAKE, + p->regs + MXS_RTC_PERSISTENT0 + MXS_RTC_CLR_ADDR); + set_reset_source(RESET_WKE); + return; + } set_reset_source(RESET_POR); return; } diff --git a/fs/Kconfig b/fs/Kconfig index 0ab69d75fc..c31c0cd963 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -14,6 +14,8 @@ config FS_CRAMFS select ZLIB prompt "cramfs support" +source fs/ext4/Kconfig + config FS_RAMFS bool default y diff --git a/fs/Makefile b/fs/Makefile index ad745d904a..cc59da766b 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_FS_CRAMFS) += cramfs/ +obj-$(CONFIG_FS_EXT4) += ext4/ obj-$(CONFIG_FS_RAMFS) += ramfs.o obj-y += devfs-core.o obj-$(CONFIG_FS_DEVFS) += devfs.o diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig new file mode 100644 index 0000000000..f36043d9a7 --- /dev/null +++ b/fs/ext4/Kconfig @@ -0,0 +1,3 @@ +config FS_EXT4 + bool + prompt "ext4 filesystem support" diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile new file mode 100644 index 0000000000..5084e3fb25 --- /dev/null +++ b/fs/ext4/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FS_EXT4) += ext4fs.o ext4_common.o ext_barebox.o diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c new file mode 100644 index 0000000000..f426118c53 --- /dev/null +++ b/fs/ext4/ext4_common.c @@ -0,0 +1,551 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * ext4ls and ext4load : Based on ext2 ls load support in Uboot. + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * based on code from grub2 fs/ext2.c and fs/fshelp.c by + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * + * ext4write : Based on generic ext4 protocol. + * + * 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 <malloc.h> +#include <stddef.h> +#include <linux/stat.h> +#include <linux/time.h> +#include <asm/byteorder.h> +#include <dma.h> + +#include "ext4_common.h" + +static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data, + char *buf, struct ext4_extent_header *ext_block, + uint32_t fileblock, int log2_blksz) +{ + struct ext4_extent_idx *index; + unsigned long long block; + struct ext_filesystem *fs = data->fs; + int i, ret; + + while (1) { + index = (struct ext4_extent_idx *)(ext_block + 1); + + if (le32_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) + return 0; + + if (ext_block->eh_depth == 0) + return ext_block; + i = -1; + do { + i++; + if (i >= le32_to_cpu(ext_block->eh_entries)) + break; + } while (fileblock > le32_to_cpu(index[i].ei_block)); + + if (--i < 0) + return 0; + + block = le32_to_cpu(index[i].ei_leaf_hi); + block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); + + ret = ext4fs_devread(fs, block << log2_blksz, 0, fs->blksz, buf); + if (ret) + return NULL; + else + ext_block = (struct ext4_extent_header *)buf; + } +} + +static int ext4fs_blockgroup(struct ext2_data *data, int group, + struct ext2_block_group *blkgrp) +{ + long int blkno; + unsigned int blkoff, desc_per_blk; + struct ext_filesystem *fs = data->fs; + + desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group); + + blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 + + group / desc_per_blk; + blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group); + + debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n", + group, blkno, blkoff); + + return ext4fs_devread(fs, blkno << LOG2_EXT2_BLOCK_SIZE(data), + blkoff, sizeof(struct ext2_block_group), + (char *)blkgrp); +} + +int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) +{ + struct ext2_block_group blkgrp; + struct ext2_sblock *sblock = &data->sblock; + struct ext_filesystem *fs = data->fs; + int inodes_per_block, ret; + long int blkno; + unsigned int blkoff; + + /* It is easier to calculate if the first inode is 0. */ + ino--; + ret = ext4fs_blockgroup(data, ino / __le32_to_cpu + (sblock->inodes_per_group), &blkgrp); + if (ret) + return ret; + + inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz; + blkno = __le32_to_cpu(blkgrp.inode_table_id) + + (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; + blkoff = (ino % inodes_per_block) * fs->inodesz; + /* Read the inode. */ + ret = ext4fs_devread(fs, blkno << LOG2_EXT2_BLOCK_SIZE(data), blkoff, + sizeof(struct ext2_inode), (char *)inode); + if (ret) + return ret; + + return 0; +} + +int ext4fs_get_indir_block(struct ext2fs_node *node, struct ext4fs_indir_block *indir, int blkno) +{ + struct ext_filesystem *fs = node->data->fs; + int blksz; + int ret; + + blksz = EXT2_BLOCK_SIZE(node->data); + + if (indir->blkno == blkno) + return 0; + + ret = ext4fs_devread(fs, blkno, 0, blksz, (void *)indir->data); + if (ret) { + printf("** SI ext2fs read block (indir 1)" + "failed. **\n"); + return ret; + } + + return 0; +} + +long int read_allocated_block(struct ext2fs_node *node, int fileblock) +{ + long int blknr; + int blksz; + int log2_blksz; + long int rblock; + long int perblock_parent; + long int perblock_child; + unsigned long long start; + struct ext2_inode *inode = &node->inode; + struct ext2_data *data = node->data; + int ret; + + /* get the blocksize of the filesystem */ + blksz = EXT2_BLOCK_SIZE(node->data); + log2_blksz = LOG2_EXT2_BLOCK_SIZE(node->data); + + if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { + char *buf = zalloc(blksz); + struct ext4_extent_header *ext_block; + struct ext4_extent *extent; + int i = -1; + + if (!buf) + return -ENOMEM; + + ext_block = ext4fs_get_extent_block(node->data, buf, + (struct ext4_extent_header *)inode->b.blocks.dir_blocks, + fileblock, log2_blksz); + if (!ext_block) { + printf("invalid extent block\n"); + free(buf); + return -EINVAL; + } + + extent = (struct ext4_extent *)(ext_block + 1); + + do { + i++; + if (i >= le32_to_cpu(ext_block->eh_entries)) + break; + } while (fileblock >= le32_to_cpu(extent[i].ee_block)); + + if (--i >= 0) { + fileblock -= le32_to_cpu(extent[i].ee_block); + if (fileblock >= le32_to_cpu(extent[i].ee_len)) { + free(buf); + return 0; + } + + start = le32_to_cpu(extent[i].ee_start_hi); + start = (start << 32) + + le32_to_cpu(extent[i].ee_start_lo); + free(buf); + return fileblock + start; + } + + free(buf); + return -EIO; + } + + if (fileblock < INDIRECT_BLOCKS) { + /* Direct blocks. */ + blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]); + } else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) { + /* Indirect. */ + ret = ext4fs_get_indir_block(node, &data->indir1, + __le32_to_cpu(inode->b.blocks.indir_block) << log2_blksz); + if (ret) + return ret; + blknr = __le32_to_cpu(data->indir1.data[fileblock - INDIRECT_BLOCKS]); + } else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 * + (blksz / 4 + 1)))) { + /* Double indirect. */ + long int perblock = blksz / 4; + long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4); + + ret = ext4fs_get_indir_block(node, &data->indir1, + __le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz); + if (ret) + return ret; + + ret = ext4fs_get_indir_block(node, &data->indir2, + __le32_to_cpu(data->indir1.data[rblock / perblock]) << log2_blksz); + if (ret) + return ret; + + blknr = __le32_to_cpu(data->indir2.data[rblock % perblock]); + } else { + /* Triple indirect. */ + rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + + (blksz / 4 * blksz / 4)); + perblock_child = blksz / 4; + perblock_parent = ((blksz / 4) * (blksz / 4)); + + ret = ext4fs_get_indir_block(node, &data->indir1, + __le32_to_cpu(inode->b.blocks.triple_indir_block) << log2_blksz); + if (ret) + return ret; + + ret = ext4fs_get_indir_block(node, &data->indir2, + __le32_to_cpu(data->indir1.data[rblock / perblock_parent]) << log2_blksz); + if (ret) + return ret; + + ret = ext4fs_get_indir_block(node, &data->indir3, + __le32_to_cpu(data->indir2.data[rblock / perblock_child]) << log2_blksz); + if (ret) + return ret; + + blknr = __le32_to_cpu(data->indir3.data[rblock % perblock_child]); + } + + return blknr; +} + +int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, + struct ext2fs_node **fnode, int *ftype) +{ + unsigned int fpos = 0; + int status, ret; + struct ext2fs_node *diro = (struct ext2fs_node *) dir; + + + if (name != NULL) + debug("Iterate dir %s\n", name); + + if (!diro->inode_read) { + ret = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); + if (ret) + return ret; + } + /* Search the file. */ + while (fpos < __le32_to_cpu(diro->inode.size)) { + struct ext2_dirent dirent; + + status = ext4fs_read_file(diro, fpos, + sizeof(struct ext2_dirent), + (char *) &dirent); + if (status < 1) + return -EINVAL; + + if (dirent.namelen != 0) { + char filename[dirent.namelen + 1]; + struct ext2fs_node *fdiro; + int type = FILETYPE_UNKNOWN; + + status = ext4fs_read_file(diro, + fpos + + sizeof(struct ext2_dirent), + dirent.namelen, filename); + if (status < 1) + return -EINVAL; + + fdiro = zalloc(sizeof(struct ext2fs_node)); + if (!fdiro) + return -ENOMEM; + + fdiro->data = diro->data; + fdiro->ino = __le32_to_cpu(dirent.inode); + + filename[dirent.namelen] = '\0'; + + if (dirent.filetype != FILETYPE_UNKNOWN) { + fdiro->inode_read = 0; + + if (dirent.filetype == FILETYPE_DIRECTORY) + type = FILETYPE_DIRECTORY; + else if (dirent.filetype == FILETYPE_SYMLINK) + type = FILETYPE_SYMLINK; + else if (dirent.filetype == FILETYPE_REG) + type = FILETYPE_REG; + } else { + ret = ext4fs_read_inode(diro->data, + __le32_to_cpu + (dirent.inode), + &fdiro->inode); + if (ret) { + free(fdiro); + return ret; + } + fdiro->inode_read = 1; + + if ((__le16_to_cpu(fdiro->inode.mode) & + FILETYPE_INO_MASK) == + FILETYPE_INO_DIRECTORY) { + type = FILETYPE_DIRECTORY; + } else if ((__le16_to_cpu(fdiro->inode.mode) + & FILETYPE_INO_MASK) == + FILETYPE_INO_SYMLINK) { + type = FILETYPE_SYMLINK; + } else if ((__le16_to_cpu(fdiro->inode.mode) + & FILETYPE_INO_MASK) == + FILETYPE_INO_REG) { + type = FILETYPE_REG; + } + } + + debug("iterate >%s<\n", filename); + + if (strcmp(filename, name) == 0) { + *ftype = type; + *fnode = fdiro; + return 0; + } + + free(fdiro); + } + fpos += __le16_to_cpu(dirent.direntlen); + } + return -ENOENT; +} + +char *ext4fs_read_symlink(struct ext2fs_node *node) +{ + char *symlink; + struct ext2fs_node *diro = node; + int status, ret; + + if (!diro->inode_read) { + ret = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); + if (ret) + return NULL; + } + symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1); + if (!symlink) + return 0; + + if (__le32_to_cpu(diro->inode.size) <= 60) { + strncpy(symlink, diro->inode.b.symlink, + __le32_to_cpu(diro->inode.size)); + } else { + status = ext4fs_read_file(diro, 0, + __le32_to_cpu(diro->inode.size), + symlink); + if (status == 0) { + free(symlink); + return NULL; + } + } + + symlink[__le32_to_cpu(diro->inode.size)] = '\0'; + + return symlink; +} + +int ext4fs_find_file(const char *currpath, + struct ext2fs_node *currroot, + struct ext2fs_node **currfound, int *foundtype) +{ + char fpath[strlen(currpath) + 1]; + char *name = fpath; + char *next; + int type = FILETYPE_DIRECTORY; + struct ext2fs_node *currnode = currroot; + struct ext2fs_node *oldnode = currroot; + int ret = 0; + + strncpy(fpath, currpath, strlen(currpath) + 1); + + /* Remove all leading slashes. */ + while (*name == '/') + name++; + + if (!*name) { + *currfound = currnode; + goto out; + } + + for (;;) { + /* Extract the actual part from the pathname. */ + next = strchr(name, '/'); + if (next) { + /* Remove all leading slashes. */ + while (*next == '/') + *(next++) = '\0'; + } + + if (type != FILETYPE_DIRECTORY) { + ext4fs_free_node(currnode, currroot); + return -ENOENT; + } + + oldnode = currnode; + + /* Iterate over the directory. */ + ret = ext4fs_iterate_dir(currnode, name, &currnode, &type); + if (ret) + return ret; + + ext4fs_free_node(oldnode, currroot); + + /* Found the node! */ + if (!next || *next == '\0') { + *currfound = currnode; + goto out; + } + name = next; + } + +out: + if (foundtype) + *foundtype = type; + + return ret; +} + +int ext4fs_open(struct ext2_data *data, const char *filename, struct ext2fs_node **inode) +{ + struct ext2fs_node *fdiro = NULL; + int status, ret; + int type; + + status = ext4fs_find_file(filename, &data->diropen, &fdiro, &type); + if (status) + goto fail; + + if (type != FILETYPE_REG) + return -EINVAL; + + if (!fdiro->inode_read) { + ret = ext4fs_read_inode(fdiro->data, fdiro->ino, + &fdiro->inode); + if (ret) + goto fail; + } + + *inode = fdiro; + + return 0; +fail: + ext4fs_free_node(fdiro, &data->diropen); + + return -ENOENT; +} + +int ext4fs_mount(struct ext_filesystem *fs) +{ + struct ext2_data *data; + int ret, blksz; + + data = zalloc(sizeof(struct ext2_data)); + if (!data) + return -ENOMEM; + + /* Read the superblock. */ + ret = ext4fs_devread(fs, 1 * 2, 0, sizeof(struct ext2_sblock), + (char *)&data->sblock); + if (ret) + goto fail; + + /* Make sure this is an ext2 filesystem. */ + if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC) { + ret = -EINVAL; + goto fail; + } + + if (__le32_to_cpu(data->sblock.revision_level == 0)) + fs->inodesz = 128; + else + fs->inodesz = __le16_to_cpu(data->sblock.inode_size); + + dev_info(fs->dev, "EXT2 rev %d, inode_size %d\n", + __le32_to_cpu(data->sblock.revision_level), fs->inodesz); + + data->diropen.data = data; + data->diropen.ino = 2; + data->diropen.inode_read = 1; + data->inode = &data->diropen.inode; + data->fs = fs; + fs->data = data; + + blksz = EXT2_BLOCK_SIZE(data); + + fs->data->indir1.data = malloc(blksz); + fs->data->indir2.data = malloc(blksz); + fs->data->indir3.data = malloc(blksz); + + if (!fs->data->indir1.data || !fs->data->indir2.data || + !fs->data->indir3.data) { + ret = -ENOMEM; + goto fail; + } + + ret = ext4fs_read_inode(data, 2, data->inode); + if (ret) + goto fail; + + return 0; +fail: + free(data); + + return ret; +} + +void ext4fs_umount(struct ext_filesystem *fs) +{ + free(fs->data->indir1.data); + free(fs->data->indir2.data); + free(fs->data->indir3.data); + free(fs->data); +} diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h new file mode 100644 index 0000000000..81fb67ef4c --- /dev/null +++ b/fs/ext4/ext4_common.h @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * ext4ls and ext4load : based on ext2 ls load support in Uboot. + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * based on code from grub2 fs/ext2.c and fs/fshelp.c by + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * + * ext4write : Based on generic ext4 protocol. + * + * 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 __EXT4_COMMON__ +#define __EXT4_COMMON__ +#include <malloc.h> +#include <errno.h> +#include <dma.h> +#include "ext4fs.h" +#include "ext_common.h" + +static inline void *zalloc(size_t size) +{ + void *p = dma_alloc(size); + + if (p) + memset(p, 0, size); + + return p; +} + +int ext4fs_read_inode(struct ext2_data *data, int ino, + struct ext2_inode *inode); +int ext4fs_read_file(struct ext2fs_node *node, int pos, + unsigned int len, char *buf); +int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, + struct ext2fs_node **foundnode, int *foundtype); +int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, + struct ext2fs_node **fnode, int *ftype); + +#endif diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c new file mode 100644 index 0000000000..1b9af80f80 --- /dev/null +++ b/fs/ext4/ext4fs.c @@ -0,0 +1,153 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * ext4ls and ext4load : Based on ext2 ls and load support in Uboot. + * Ext4 read optimization taken from Open-Moko + * Qi bootloader + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * based on code from grub2 fs/ext2.c and fs/fshelp.c by + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003, 2004 Free Software Foundation, 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. + * + * 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 <malloc.h> +#include <linux/stat.h> +#include <linux/time.h> +#include <asm/byteorder.h> +#include "ext4_common.h" + +void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot) +{ + if ((node != &node->data->diropen) && (node != currroot)) + free(node); +} + +/* + * Taken from openmoko-kernel mailing list: By Andy green + * Optimized read file API : collects and defers contiguous sector + * reads into one potentially more efficient larger sequential read action + */ +int ext4fs_read_file(struct ext2fs_node *node, int pos, + unsigned int len, char *buf) +{ + int i; + int blockcnt; + int log2blocksize = LOG2_EXT2_BLOCK_SIZE(node->data); + int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS); + unsigned int filesize = __le32_to_cpu(node->inode.size); + int previous_block_number = -1; + int delayed_start = 0; + int delayed_extent = 0; + int delayed_skipfirst = 0; + int delayed_next = 0; + char *delayed_buf = NULL; + short ret; + struct ext_filesystem *fs = node->data->fs; + + /* Adjust len so it we can't read past the end of the file. */ + if (len > filesize) + len = filesize; + + blockcnt = ((len + pos) + blocksize - 1) / blocksize; + + for (i = pos / blocksize; i < blockcnt; i++) { + int blknr; + int blockoff = pos % blocksize; + int blockend = blocksize; + int skipfirst = 0; + blknr = read_allocated_block(node, i); + if (blknr < 0) + return blknr; + + blknr = blknr << log2blocksize; + + /* Last block. */ + if (i == blockcnt - 1) { + blockend = (len + pos) % blocksize; + + /* The last portion is exactly blocksize. */ + if (!blockend) + blockend = blocksize; + } + + /* First block. */ + if (i == pos / blocksize) { + skipfirst = blockoff; + blockend -= skipfirst; + } + if (blknr) { + if (previous_block_number != -1) { + if (delayed_next == blknr) { + delayed_extent += blockend; + delayed_next += blockend >> SECTOR_BITS; + } else { /* spill */ + ret = ext4fs_devread(fs, delayed_start, + delayed_skipfirst, + delayed_extent, + delayed_buf); + if (ret) + return ret; + previous_block_number = blknr; + delayed_start = blknr; + delayed_extent = blockend; + delayed_skipfirst = skipfirst; + delayed_buf = buf; + delayed_next = blknr + + (blockend >> SECTOR_BITS); + } + } else { + previous_block_number = blknr; + delayed_start = blknr; + delayed_extent = blockend; + delayed_skipfirst = skipfirst; + delayed_buf = buf; + delayed_next = blknr + + (blockend >> SECTOR_BITS); + } + } else { + if (previous_block_number != -1) { + /* spill */ + ret = ext4fs_devread(fs, delayed_start, + delayed_skipfirst, + delayed_extent, + delayed_buf); + if (ret) + return ret; + previous_block_number = -1; + } + memset(buf, 0, blocksize - skipfirst); + } + buf += blocksize - skipfirst; + } + if (previous_block_number != -1) { + /* spill */ + ret = ext4fs_devread(fs, delayed_start, + delayed_skipfirst, delayed_extent, + delayed_buf); + if (ret) + return ret; + previous_block_number = -1; + } + + return len; +} diff --git a/fs/ext4/ext4fs.h b/fs/ext4/ext4fs.h new file mode 100644 index 0000000000..ead212d97a --- /dev/null +++ b/fs/ext4/ext4fs.h @@ -0,0 +1,127 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * Ext4 Extent data structures are taken from original ext4 fs code + * as found in the linux kernel. + * + * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com + * Written by Alex Tomas <alex@clusterfs.com> + * + * 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. + * + */ + +#ifndef __EXT4__ +#define __EXT4__ + +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ +#define EXT4_EXT_MAGIC 0xf30a +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 +#define EXT4_INDIRECT_BLOCKS 12 + +#define EXT4_BG_INODE_UNINIT 0x0001 +#define EXT4_BG_BLOCK_UNINIT 0x0002 +#define EXT4_BG_INODE_ZEROED 0x0004 + +/* + * ext4_inode has i_block array (60 bytes total). + * The first 12 bytes store ext4_extent_header; + * the remainder stores an array of ext4_extent. + */ + +/* + * This is the extent on-disk structure. + * It's used at the bottom of the tree. + */ +struct ext4_extent { + __le32 ee_block; /* first logical block extent covers */ + __le16 ee_len; /* number of blocks covered by extent */ + __le16 ee_start_hi; /* high 16 bits of physical block */ + __le32 ee_start_lo; /* low 32 bits of physical block */ +}; + +/* + * This is index on-disk structure. + * It's used at all the levels except the bottom. + */ +struct ext4_extent_idx { + __le32 ei_block; /* index covers logical blocks from 'block' */ + __le32 ei_leaf_lo; /* pointer to the physical block of the next * + * level. leaf or next index could be there */ + __le16 ei_leaf_hi; /* high 16 bits of physical block */ + __u16 ei_unused; +}; + +/* Each block (leaves and indexes), even inode-stored has header. */ +struct ext4_extent_header { + __le16 eh_magic; /* probably will support different formats */ + __le16 eh_entries; /* number of valid entries */ + __le16 eh_max; /* capacity of store in entries */ + __le16 eh_depth; /* has tree real underlying blocks? */ + __le32 eh_generation; /* generation of the tree */ +}; + +struct ext_filesystem { + /* Total Sector of partition */ + uint64_t total_sect; + /* Block size of partition */ + uint32_t blksz; + /* Inode size of partition */ + uint32_t inodesz; + /* Sectors per Block */ + uint32_t sect_perblk; + /* Group Descriptor Block Number */ + uint32_t gdtable_blkno; + /* Total block groups of partition */ + uint32_t no_blkgrp; + /* No of blocks required for bgdtable */ + uint32_t no_blk_pergdt; + /* Superblock */ + struct ext2_sblock *sb; + /* Block group descritpor table */ + struct ext2_block_group *bgd; + char *gdtable; + + /* Block Bitmap Related */ + unsigned char **blk_bmaps; + long int curr_blkno; + uint16_t first_pass_bbmap; + + /* Inode Bitmap Related */ + unsigned char **inode_bmaps; + int curr_inode_no; + uint16_t first_pass_ibmap; + + /* Journal Related */ + + /* Block Device Descriptor */ + struct cdev *cdev; + + struct ext2_data *data; + + struct device_d *dev; +}; + +struct ext2fs_node; + +int ext4fs_open(struct ext2_data *data, const char *filename, struct ext2fs_node **inode); +int ext4fs_read(char *buf, unsigned len); +int ext4fs_mount(struct ext_filesystem *fs); +void ext4fs_umount(struct ext_filesystem *fs); +char *ext4fs_read_symlink(struct ext2fs_node *node); +void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot); +int ext4fs_devread(struct ext_filesystem *fs, int sector, int byte_offset, int byte_len, char *buf); +long int read_allocated_block(struct ext2fs_node *node, int fileblock); + +#endif diff --git a/fs/ext4/ext_barebox.c b/fs/ext4/ext_barebox.c new file mode 100644 index 0000000000..adc8f758e0 --- /dev/null +++ b/fs/ext4/ext_barebox.c @@ -0,0 +1,293 @@ +/* + * barebox ext4 support + * + * 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. + * + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> +#include <fs.h> +#include <command.h> +#include <errno.h> +#include <linux/stat.h> +#include <linux/ctype.h> +#include <xfuncs.h> +#include <fcntl.h> +#include "ext4_common.h" + +int ext4fs_devread(struct ext_filesystem *fs, int __sector, int byte_offset, + int byte_len, char *buf) +{ + ssize_t size; + uint64_t sector = __sector; + + size = cdev_read(fs->cdev, buf, byte_len, sector * SECTOR_SIZE + byte_offset, 0); + if (size < 0) { + dev_err(fs->dev, "read error at sector %d: %s\n", __sector, + strerror(-size)); + return size; + } + + return 0; +} + +static int ext_open(struct device_d *dev, FILE *file, const char *filename) +{ + struct ext_filesystem *fs = dev->priv; + struct ext2fs_node *inode; + int ret; + + ret = ext4fs_open(fs->data, filename, &inode); + if (ret) + return ret; + + file->size = __le32_to_cpu(inode->inode.size); + file->inode = inode; + + return 0; +} + +static int ext_close(struct device_d *dev, FILE *f) +{ + struct ext_filesystem *fs = dev->priv; + + ext4fs_free_node(f->inode, &fs->data->diropen); + + return 0; +} + +static int ext_read(struct device_d *_dev, FILE *f, void *buf, size_t insize) +{ + return ext4fs_read_file(f->inode, f->pos, insize, buf); +} + +static loff_t ext_lseek(struct device_d *dev, FILE *f, loff_t pos) +{ + f->pos = pos; + + return f->pos; +} + +struct ext4fs_dir { + struct ext2fs_node *dirnode; + int fpos; + DIR dir; +}; + +static DIR *ext_opendir(struct device_d *dev, const char *pathname) +{ + struct ext_filesystem *fs = dev->priv; + struct ext4fs_dir *ext4_dir; + int type, ret; + + ext4_dir = xzalloc(sizeof(*ext4_dir)); + + ret = ext4fs_find_file(pathname, &fs->data->diropen, &ext4_dir->dirnode, + &type); + if (ret) { + free(ext4_dir); + return NULL; + } + + if (type != FILETYPE_DIRECTORY) + return NULL; + + ext4_dir->dir.priv = ext4_dir; + + ret = ext4fs_read_inode(ext4_dir->dirnode->data, ext4_dir->dirnode->ino, + &ext4_dir->dirnode->inode); + if (ret) { + ext4fs_free_node(ext4_dir->dirnode, &fs->data->diropen); + free(ext4_dir); + + return NULL; + } + + return &ext4_dir->dir; +} + +static struct dirent *ext_readdir(struct device_d *dev, DIR *dir) +{ + struct ext4fs_dir *ext4_dir = dir->priv; + struct ext2_dirent dirent; + struct ext2fs_node *diro = ext4_dir->dirnode; + int ret; + char *filename; + + if (ext4_dir->fpos >= __le32_to_cpu(diro->inode.size)) + return NULL; + + ret = ext4fs_read_file(diro, ext4_dir->fpos, sizeof(struct ext2_dirent), + (char *) &dirent); + if (ret < 0) + return NULL; + + if (dirent.namelen == 0) + return NULL; + + filename = xzalloc(dirent.namelen + 1); + + ret = ext4fs_read_file(diro, ext4_dir->fpos + sizeof(struct ext2_dirent), + dirent.namelen, filename); + if (ret < 0) { + free(filename); + return NULL; + } + + filename[dirent.namelen] = '\0'; + + ext4_dir->fpos += __le16_to_cpu(dirent.direntlen); + + strcpy(dir->d.d_name, filename); + + free(filename); + + return &dir->d; +} + +static int ext_closedir(struct device_d *dev, DIR *dir) +{ + struct ext_filesystem *fs = dev->priv; + struct ext4fs_dir *ext4_dir = dir->priv; + + ext4fs_free_node(ext4_dir->dirnode, &fs->data->diropen); + + free(ext4_dir); + + return 0; +} + +static int ext_stat(struct device_d *dev, const char *filename, struct stat *s) +{ + struct ext_filesystem *fs = dev->priv; + struct ext2fs_node *node; + int status, ret; + + status = ext4fs_find_file(filename, &fs->data->diropen, &node, NULL); + if (status) + return -ENOENT; + + ret = ext4fs_read_inode(node->data, node->ino, &node->inode); + if (ret) + return ret; + + s->st_size = __le32_to_cpu(node->inode.size); + s->st_mode = __le16_to_cpu(node->inode.mode); + + ext4fs_free_node(node, &fs->data->diropen); + + return 0; +} + +static int ext_readlink(struct device_d *dev, const char *pathname, + char *buf, size_t bufsiz) +{ + struct ext_filesystem *fs = dev->priv; + struct ext2fs_node *node; + char *symlink; + int ret, len, type; + + ret = ext4fs_find_file(pathname, &fs->data->diropen, &node, &type); + if (ret) + return ret; + + if (type != FILETYPE_SYMLINK) + return -EINVAL; + + symlink = ext4fs_read_symlink(node); + if (!symlink) + return -ENOENT; + + len = min(bufsiz, strlen(symlink)); + + memcpy(buf, symlink, len); + + free(symlink); + + return 0; +} + +static int ext_probe(struct device_d *dev) +{ + struct fs_device_d *fsdev = dev_to_fs_device(dev); + char *backingstore = fsdev->backingstore; + int ret; + struct ext_filesystem *fs; + + fs = xzalloc(sizeof(*fs)); + + dev->priv = fs; + fs->dev = dev; + + if (!strncmp(backingstore , "/dev/", 5)) + backingstore += 5; + + fs->cdev = cdev_open(backingstore, O_RDWR); + if (!fs->cdev) { + ret = -ENOENT; + goto err_open; + } + + ret = ext4fs_mount(fs); + if (ret) + goto err_mount; + + return 0; + +err_mount: + cdev_close(fs->cdev); +err_open: + free(fs); + + return ret; +} + +static void ext_remove(struct device_d *dev) +{ + struct ext_filesystem *fs = dev->priv; + + ext4fs_umount(fs); + cdev_close(fs->cdev); + free(fs); +} + +static struct fs_driver_d ext_driver = { + .open = ext_open, + .close = ext_close, + .read = ext_read, + .lseek = ext_lseek, + .opendir = ext_opendir, + .readdir = ext_readdir, + .closedir = ext_closedir, + .stat = ext_stat, + .readlink = ext_readlink, + .type = filetype_ext, + .flags = 0, + .drv = { + .probe = ext_probe, + .remove = ext_remove, + .name = "ext4", + } +}; + +static int ext_init(void) +{ + return register_fs_driver(&ext_driver); +} + +coredevice_initcall(ext_init); diff --git a/fs/ext4/ext_common.h b/fs/ext4/ext_common.h new file mode 100644 index 0000000000..517a1c1487 --- /dev/null +++ b/fs/ext4/ext_common.h @@ -0,0 +1,195 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * Data structures and headers for ext4 support have been taken from + * ext2 ls load support in Uboot + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * based on code from grub2 fs/ext2.c and fs/fshelp.c by + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003, 2004 Free Software Foundation, 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. + * + * 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 __EXT_COMMON__ +#define __EXT_COMMON__ + +#define SECTOR_SIZE 0x200 +#define SECTOR_BITS 9 + +/* Magic value used to identify an ext2 filesystem. */ +#define EXT2_MAGIC 0xEF53 +/* Amount of indirect blocks in an inode. */ +#define INDIRECT_BLOCKS 12 +/* Maximum lenght of a pathname. */ +#define EXT2_PATH_MAX 4096 +/* Maximum nesting of symlinks, used to prevent a loop. */ +#define EXT2_MAX_SYMLINKCNT 8 + +/* Filetype used in directory entry. */ +#define FILETYPE_UNKNOWN 0 +#define FILETYPE_REG 1 +#define FILETYPE_DIRECTORY 2 +#define FILETYPE_SYMLINK 7 + +/* Filetype information as used in inodes. */ +#define FILETYPE_INO_MASK 0170000 +#define FILETYPE_INO_REG 0100000 +#define FILETYPE_INO_DIRECTORY 0040000 +#define FILETYPE_INO_SYMLINK 0120000 +#define EXT2_ROOT_INO 2 /* Root inode */ + +/* Bits used as offset in sector */ +#define DISK_SECTOR_BITS 9 +/* The size of an ext2 block in bytes. */ +#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data)) + +/* Log2 size of ext2 block in 512 blocks. */ +#define LOG2_EXT2_BLOCK_SIZE(data) (__le32_to_cpu \ + (data->sblock.log2_block_size) + 1) + +/* Log2 size of ext2 block in bytes. */ +#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu \ + (data->sblock.log2_block_size) + 10) +#define INODE_SIZE_FILESYSTEM(data) (__le32_to_cpu \ + (data->sblock.inode_size)) + +#define EXT2_FT_DIR 2 +#define SUCCESS 1 + +/* Macro-instructions used to manage several block sizes */ +#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ +#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ +#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) +#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) + +/* The ext2 superblock. */ +struct ext2_sblock { + uint32_t total_inodes; + uint32_t total_blocks; + uint32_t reserved_blocks; + uint32_t free_blocks; + uint32_t free_inodes; + uint32_t first_data_block; + uint32_t log2_block_size; + uint32_t log2_fragment_size; + uint32_t blocks_per_group; + uint32_t fragments_per_group; + uint32_t inodes_per_group; + uint32_t mtime; + uint32_t utime; + uint16_t mnt_count; + uint16_t max_mnt_count; + uint16_t magic; + uint16_t fs_state; + uint16_t error_handling; + uint16_t minor_revision_level; + uint32_t lastcheck; + uint32_t checkinterval; + uint32_t creator_os; + uint32_t revision_level; + uint16_t uid_reserved; + uint16_t gid_reserved; + uint32_t first_inode; + uint16_t inode_size; + uint16_t block_group_number; + uint32_t feature_compatibility; + uint32_t feature_incompat; + uint32_t feature_ro_compat; + uint32_t unique_id[4]; + char volume_name[16]; + char last_mounted_on[64]; + uint32_t compression_info; +}; + +struct ext2_block_group { + __u32 block_id; /* Blocks bitmap block */ + __u32 inode_id; /* Inodes bitmap block */ + __u32 inode_table_id; /* Inodes table block */ + __u16 free_blocks; /* Free blocks count */ + __u16 free_inodes; /* Free inodes count */ + __u16 used_dir_cnt; /* Directories count */ + __u16 bg_flags; + __u32 bg_reserved[2]; + __u16 bg_itable_unused; /* Unused inodes count */ + __u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/ +}; + +/* The ext2 inode. */ +struct ext2_inode { + uint16_t mode; + uint16_t uid; + uint32_t size; + uint32_t atime; + uint32_t ctime; + uint32_t mtime; + uint32_t dtime; + uint16_t gid; + uint16_t nlinks; + uint32_t blockcnt; /* Blocks of 512 bytes!! */ + uint32_t flags; + uint32_t osd1; + union { + struct datablocks { + uint32_t dir_blocks[INDIRECT_BLOCKS]; + uint32_t indir_block; + uint32_t double_indir_block; + uint32_t triple_indir_block; + } blocks; + char symlink[60]; + } b; + uint32_t version; + uint32_t acl; + uint32_t dir_acl; + uint32_t fragment_addr; + uint32_t osd2[3]; +}; + +/* The header of an ext2 directory entry. */ +struct ext2_dirent { + uint32_t inode; + uint16_t direntlen; + uint8_t namelen; + uint8_t filetype; +}; + +struct ext2fs_node { + struct ext2_data *data; + struct ext2_inode inode; + int ino; + int inode_read; +}; + +struct ext4fs_indir_block { + int size; + int blkno; + uint32_t *data; +}; + +/* Information about a "mounted" ext2 filesystem. */ +struct ext2_data { + struct ext2_sblock sblock; + struct ext2_inode *inode; + struct ext2fs_node diropen; + struct ext_filesystem *fs; + struct ext4fs_indir_block indir1, indir2, indir3; +}; + +extern unsigned long part_offset; +#endif @@ -227,7 +227,7 @@ static void tftp_parse_oack(struct file_priv *priv, unsigned char *pkt, int len) debug("got OACK\n"); #ifdef DEBUG - memory_display(pkt, 0, len, 1); + memory_display(pkt, 0, len, 1, 0); #endif s = pkt; diff --git a/include/ata_drive.h b/include/ata_drive.h index cdd8049f0d..1996321012 100644 --- a/include/ata_drive.h +++ b/include/ata_drive.h @@ -16,6 +16,8 @@ #ifndef ATA_DISK_H # define ATA_DISK +#include <block.h> + /* IDE register file */ #define IDE_REG_DATA 0x00 #define IDE_REG_ERR 0x01 @@ -33,6 +35,26 @@ #define IDE_REG_DEV_CTL 0x00 #define IDE_REG_DRV_ADDR 0x01 +#define ATA_CMD_ID_ATA 0xEC +#define ATA_CMD_READ 0x20 +#define ATA_CMD_READ_EXT 0x25 +#define ATA_CMD_WRITE 0x30 +#define ATA_CMD_WRITE_EXT 0x35 + +/* drive's status flags */ +#define ATA_STATUS_BUSY (1 << 7) +#define ATA_STATUS_READY (1 << 6) +#define ATA_STATUS_WR_FLT (1 << 5) +#define ATA_STATUS_DSC (1 << 4) +#define ATA_STATUS_DRQ (1 << 3) +#define ATA_STATUS_CORR (1 << 2) +#define ATA_STATUS_IDX (1 << 1) +#define ATA_STATUS_ERROR (1 << 0) +/* command flags */ +#define LBA_FLAG (1 << 6) +#define ATA_DEVCTL_SOFT_RESET (1 << 2) +#define ATA_DEVCTL_INTR_DISABLE (1 << 1) + /** addresses of each individual IDE drive register */ struct ata_ioports { void __iomem *cmd_addr; @@ -55,8 +77,27 @@ struct ata_ioports { int dataif_be; /* true if 16 bit data register is big endian */ }; +struct ata_port; + +struct ata_port_operations { + int (*read)(struct ata_port *port, void *buf, unsigned int block, int num_blocks); + int (*write)(struct ata_port *port, const void *buf, unsigned int block, int num_blocks); + int (*read_id)(struct ata_port *port, void *buf); + int (*reset)(struct ata_port *port); +}; + +struct ata_port { + struct ata_port_operations *ops; + struct device_d *dev; + void *drvdata; + struct block_device blk; + uint16_t *id; +}; + +int ide_port_register(struct device_d *, struct ata_ioports *); +int ata_port_register(struct ata_port *port); + struct device_d; -extern int register_ata_drive(struct device_d*, struct ata_ioports*); /** * @file diff --git a/include/common.h b/include/common.h index e30774a43e..6256879f83 100644 --- a/include/common.h +++ b/include/common.h @@ -226,7 +226,7 @@ int run_shell(void); #define PAGE_SIZE 4096 #define PAGE_SHIFT 12 -int memory_display(char *addr, loff_t offs, ulong nbytes, int size); +int memory_display(char *addr, loff_t offs, ulong nbytes, int size, int swab); extern const char version_string[]; #ifdef CONFIG_BANNER diff --git a/include/debug_ll.h b/include/debug_ll.h index c7445731d6..f0034ba06a 100644 --- a/include/debug_ll.h +++ b/include/debug_ll.h @@ -1,4 +1,5 @@ -/* debug_ll.h +/* + * debug_ll.h * * written by Marc Singer * 12 Feb 2005 @@ -20,9 +21,16 @@ #define __INCLUDE_DEBUG_LL_H__ #if defined (CONFIG_DEBUG_LL) + +/* + * mach/debug_ll.h should implement PUTC_LL. This can be a macro or a static + * inline function. Note that several SoCs expect the UART to be initialized + * by a debugger or a first stage bootloader. You won't see anything without + * this initialization. Depending on the PUTC_LL implementation the board might + * also hang in PUTC_LL without proper initialization. + */ # include <mach/debug_ll.h> -#define PUTC_LL(x) putc(x) # define PUTHEX_LL(value) ({ unsigned long v = (unsigned long) (value); \ int i; unsigned char ch; \ for (i = 8; i--; ) {\ @@ -30,6 +38,11 @@ ch += (ch >= 10) ? 'a' - 10 : '0';\ PUTC_LL (ch); }}) +/* + * Be careful with PUTS_LL, it only works if the binary is running at the + * link address which often is not the case during early startup. If in doubt + * don't use it. + */ static __inline__ void PUTS_LL(const char * str) { while (*str) { diff --git a/include/driver.h b/include/driver.h index f8d815c619..c2beeb8eb7 100644 --- a/include/driver.h +++ b/include/driver.h @@ -393,6 +393,8 @@ struct bus_type { int (*probe)(struct device_d *dev); void (*remove)(struct device_d *dev); + struct device_d dev; + struct list_head list; struct list_head device_list; struct list_head driver_list; @@ -408,11 +410,11 @@ extern struct list_head bus_list; /* Iterate over all devices of a bus */ -#define bus_for_each_device(bus, dev) list_for_each_entry(dev, &bus->device_list, bus_list) +#define bus_for_each_device(bus, dev) list_for_each_entry(dev, &(bus)->device_list, bus_list) /* Iterate over all drivers of a bus */ -#define bus_for_each_driver(bus, drv) list_for_each_entry(drv, &bus->driver_list, bus_list) +#define bus_for_each_driver(bus, drv) list_for_each_entry(drv, &(bus)->driver_list, bus_list) extern struct bus_type platform_bus; diff --git a/include/environment.h b/include/environment.h index 4184977009..096c1697c4 100644 --- a/include/environment.h +++ b/include/environment.h @@ -75,9 +75,6 @@ int env_push_context(void); /* defaults to /dev/env0 */ extern char *default_environment_path; -int envfs_load(char *filename, char *dirname); -int envfs_save(char *filename, char *dirname); - int export(const char *); struct stat; @@ -86,6 +83,10 @@ int file_save_action(const char *, struct stat *, void *, int); #endif /* __BAREBOX__ */ +#define ENV_FLAG_NO_OVERWRITE (1 << 0) +int envfs_load(char *filename, char *dirname, unsigned flags); +int envfs_save(char *filename, char *dirname); + /* This part is used for the host and the target */ struct action_data { int fd; diff --git a/include/filetype.h b/include/filetype.h index 0a722a0a54..91139dbfe3 100644 --- a/include/filetype.h +++ b/include/filetype.h @@ -22,12 +22,15 @@ enum filetype { filetype_mbr, filetype_bmp, filetype_png, + filetype_ext, filetype_max, }; +#define FILE_TYPE_SAFE_BUFSIZE 2048 + const char *file_type_to_string(enum filetype f); const char *file_type_to_short_string(enum filetype f); -enum filetype file_detect_type(void *_buf); +enum filetype file_detect_type(void *_buf, size_t bufsize); enum filetype file_name_detect_type(const char *filename); enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec); diff --git a/include/fs.h b/include/fs.h index 3d5714c1fb..8ff7300919 100644 --- a/include/fs.h +++ b/include/fs.h @@ -182,4 +182,6 @@ void automount_remove(const char *_path); int automount_add(const char *path, const char *cmd); void automount_print(void); +int unlink_recursive(const char *path, char **failedpath); + #endif /* __FS_H */ diff --git a/include/led.h b/include/led.h index 9ec1f0d37b..dd551fe161 100644 --- a/include/led.h +++ b/include/led.h @@ -65,6 +65,12 @@ struct gpio_led { struct led led; }; +struct gpio_bicolor_led { + int gpio_c0, gpio_c1; + bool active_low; + struct led led; +}; + struct gpio_rgb_led { int gpio_r, gpio_g, gpio_b; bool active_low; @@ -85,6 +91,20 @@ static inline void led_gpio_unregister(struct gpio_led *led) } #endif +#ifdef CONFIG_LED_GPIO_BICOLOR +int led_gpio_bicolor_register(struct gpio_bicolor_led *led); +void led_gpio_bicolor_unregister(struct gpio_bicolor_led *led); +#else +static inline int led_gpio_bicolor_register(struct gpio_bicolor_led *led) +{ + return -ENOSYS; +} + +static inline void led_gpio_bicolor_unregister(struct gpio_bicolor_led *led) +{ +} +#endif + #ifdef CONFIG_LED_GPIO_RGB int led_gpio_rgb_register(struct gpio_rgb_led *led); void led_gpio_rgb_unregister(struct gpio_led *led); diff --git a/include/linux/clk.h b/include/linux/clk.h index 00588bff05..4389cf8b93 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -179,11 +179,22 @@ struct clk { int num_parents; struct clk **parents; + unsigned long flags; +}; + +#define CLK_ALWAYS_ENABLED (1 << 0) + +struct clk_div_table { + unsigned int val; + unsigned int div; }; struct clk *clk_fixed(const char *name, int rate); struct clk *clk_divider(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width); +struct clk *clk_divider_table(const char *name, + const char *parent, void __iomem *reg, u8 shift, u8 width, + const struct clk_div_table *table); struct clk *clk_fixed_factor(const char *name, const char *parent, unsigned int mult, unsigned int div); struct clk *clk_mux(const char *name, void __iomem *reg, diff --git a/include/mfd/imx6q-iomuxc-gpr.h b/include/mfd/imx6q-iomuxc-gpr.h new file mode 100644 index 0000000000..db43d5905c --- /dev/null +++ b/include/mfd/imx6q-iomuxc-gpr.h @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __LINUX_IMX6Q_IOMUXC_GPR_H +#define __LINUX_IMX6Q_IOMUXC_GPR_H + +#include <linux/bitops.h> + +#define IOMUXC_GPR0 0x00 +#define IOMUXC_GPR1 0x04 +#define IOMUXC_GPR2 0x08 +#define IOMUXC_GPR3 0x0c +#define IOMUXC_GPR4 0x10 +#define IOMUXC_GPR5 0x14 +#define IOMUXC_GPR6 0x18 +#define IOMUXC_GPR7 0x1c +#define IOMUXC_GPR8 0x20 +#define IOMUXC_GPR9 0x24 +#define IOMUXC_GPR10 0x28 +#define IOMUXC_GPR11 0x2c +#define IOMUXC_GPR12 0x30 +#define IOMUXC_GPR13 0x34 + +#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_MASK (0x3 << 30) +#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_AUDMUX_RXCLK_P7_MUXED (0x0 << 30) +#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_AUDMUX_RXCLK_P7 (0x1 << 30) +#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_SSI3_SSI_SRCK (0x2 << 30) +#define IMX6Q_GPR0_CLOCK_8_MUX_SEL_SSI3_RX_BIT_CLK (0x3 << 30) +#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_MASK (0x3 << 28) +#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_IND_SCKR_MUXED (0x0 << 28) +#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_IND_SCKR (0x1 << 28) +#define IMX6Q_GPR0_CLOCK_0_MUX_SEL_ESAI1_IPP_DO_SCKR (0x2 << 28) +#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_MASK (0x3 << 26) +#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_AUDMUX_TXCLK_P7_MUXED (0x0 << 26) +#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_AUDMUX_TXCLK_P7 (0x1 << 26) +#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_SSI3_SSI_STCK (0x2 << 26) +#define IMX6Q_GPR0_CLOCK_B_MUX_SEL_SSI3_TX_BIT_CLK (0x3 << 26) +#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_MASK (0x3 << 24) +#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_AUDMUX_RXCLK_P7_MUXED (0x3 << 24) +#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_AUDMUX_RXCLK_P7 (0x3 << 24) +#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_SSI3_SSI_SRCK (0x3 << 24) +#define IMX6Q_GPR0_CLOCK_3_MUX_SEL_SSI3_RX_BIT_CLK (0x3 << 24) +#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_MASK (0x3 << 22) +#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_AUDMUX_TXCLK_P2_MUXED (0x0 << 22) +#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_AUDMUX_TXCLK_P2 (0x1 << 22) +#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_SSI2_SSI_STCK (0x2 << 22) +#define IMX6Q_GPR0_CLOCK_A_MUX_SEL_SSI2_TX_BIT_CLK (0x3 << 22) +#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_MASK (0x3 << 20) +#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_AUDMUX_RXCLK_P2_MUXED (0x0 << 20) +#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_AUDMUX_RXCLK_P2 (0x1 << 20) +#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_SSI2_SSI_SRCK (0x2 << 20) +#define IMX6Q_GPR0_CLOCK_2_MUX_SEL_SSI2_RX_BIT_CLK (0x3 << 20) +#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_MASK (0x3 << 18) +#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_AUDMUX_TXCLK_P1_MUXED (0x0 << 18) +#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_AUDMUX_TXCLK_P1 (0x1 << 18) +#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_SSI1_SSI_STCK (0x2 << 18) +#define IMX6Q_GPR0_CLOCK_9_MUX_SEL_SSI1_SSI_TX_BIT_CLK (0x3 << 18) +#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_MASK (0x3 << 16) +#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_AUDMUX_RXCLK_P1_MUXED (0x0 << 16) +#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_AUDMUX_RXCLK_P1 (0x1 << 16) +#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_SSI1_SSI_SRCK (0x2 << 16) +#define IMX6Q_GPR0_CLOCK_1_MUX_SEL_SSI1_SSI_RX_BIT_CLK (0x3 << 16) +#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_MASK (0x3 << 14) +#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK1 (0x0 << 14) +#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK2 (0x1 << 14) +#define IMX6Q_GPR0_TX_CLK2_MUX_SEL_ASRCK_CLK3 (0x2 << 14) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_MASK BIT(7) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_SPDIF 0x0 +#define IMX6Q_GPR0_DMAREQ_MUX_SEL7_IOMUX BIT(7) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_MASK BIT(6) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_ESAI 0x0 +#define IMX6Q_GPR0_DMAREQ_MUX_SEL6_I2C3 BIT(6) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_MASK BIT(5) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_ECSPI4 0x0 +#define IMX6Q_GPR0_DMAREQ_MUX_SEL5_EPIT2 BIT(5) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_MASK BIT(4) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_ECSPI4 0x0 +#define IMX6Q_GPR0_DMAREQ_MUX_SEL4_I2C1 BIT(4) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_MASK BIT(3) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_ECSPI2 0x0 +#define IMX6Q_GPR0_DMAREQ_MUX_SEL3_I2C1 BIT(3) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_MASK BIT(2) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_ECSPI1 0x0 +#define IMX6Q_GPR0_DMAREQ_MUX_SEL2_I2C2 BIT(2) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_MASK BIT(1) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_ECSPI1 0x0 +#define IMX6Q_GPR0_DMAREQ_MUX_SEL1_I2C3 BIT(1) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_MASK BIT(0) +#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_IPU1 0x0 +#define IMX6Q_GPR0_DMAREQ_MUX_SEL0_IOMUX BIT(0) + +#define IMX6Q_GPR1_PCIE_REQ_MASK (0x3 << 30) +#define IMX6Q_GPR1_PCIE_EXIT_L1 BIT(28) +#define IMX6Q_GPR1_PCIE_RDY_L23 BIT(27) +#define IMX6Q_GPR1_PCIE_ENTER_L1 BIT(26) +#define IMX6Q_GPR1_MIPI_COLOR_SW BIT(25) +#define IMX6Q_GPR1_DPI_OFF BIT(24) +#define IMX6Q_GPR1_EXC_MON_MASK BIT(22) +#define IMX6Q_GPR1_EXC_MON_OKAY 0x0 +#define IMX6Q_GPR1_EXC_MON_SLVE BIT(22) +#define IMX6Q_GPR1_MIPI_IPU2_SEL_MASK BIT(21) +#define IMX6Q_GPR1_MIPI_IPU2_SEL_GASKET 0x0 +#define IMX6Q_GPR1_MIPI_IPU2_SEL_IOMUX BIT(21) +#define IMX6Q_GPR1_MIPI_IPU1_MUX_MASK BIT(20) +#define IMX6Q_GPR1_MIPI_IPU1_MUX_GASKET 0x0 +#define IMX6Q_GPR1_MIPI_IPU1_MUX_IOMUX BIT(20) +#define IMX6Q_GPR1_MIPI_IPU2_MUX_MASK BIT(19) +#define IMX6Q_GPR1_MIPI_IPU2_MUX_GASKET 0x0 +#define IMX6Q_GPR1_MIPI_IPU2_MUX_IOMUX BIT(19) +#define IMX6Q_GPR1_PCIE_TEST_PD BIT(18) +#define IMX6Q_GPR1_IPU_VPU_MUX_MASK BIT(17) +#define IMX6Q_GPR1_IPU_VPU_MUX_IPU1 0x0 +#define IMX6Q_GPR1_IPU_VPU_MUX_IPU2 BIT(17) +#define IMX6Q_GPR1_PCIE_REF_CLK_EN BIT(16) +#define IMX6Q_GPR1_USB_EXP_MODE BIT(15) +#define IMX6Q_GPR1_PCIE_INT BIT(14) +#define IMX6Q_GPR1_USB_OTG_ID_SEL_MASK BIT(13) +#define IMX6Q_GPR1_USB_OTG_ID_SEL_ENET_RX_ER 0x0 +#define IMX6Q_GPR1_USB_OTG_ID_SEL_GPIO_1 BIT(13) +#define IMX6Q_GPR1_GINT BIT(12) +#define IMX6Q_GPR1_ADDRS3_MASK (0x3 << 10) +#define IMX6Q_GPR1_ADDRS3_32MB (0x0 << 10) +#define IMX6Q_GPR1_ADDRS3_64MB (0x1 << 10) +#define IMX6Q_GPR1_ADDRS3_128MB (0x2 << 10) +#define IMX6Q_GPR1_ACT_CS3 BIT(9) +#define IMX6Q_GPR1_ADDRS2_MASK (0x3 << 7) +#define IMX6Q_GPR1_ACT_CS2 BIT(6) +#define IMX6Q_GPR1_ADDRS1_MASK (0x3 << 4) +#define IMX6Q_GPR1_ACT_CS1 BIT(3) +#define IMX6Q_GPR1_ADDRS0_MASK (0x3 << 1) +#define IMX6Q_GPR1_ACT_CS0 BIT(0) + +#define IMX6Q_GPR2_COUNTER_RESET_VAL_MASK (0x3 << 20) +#define IMX6Q_GPR2_COUNTER_RESET_VAL_5 (0x0 << 20) +#define IMX6Q_GPR2_COUNTER_RESET_VAL_3 (0x1 << 20) +#define IMX6Q_GPR2_COUNTER_RESET_VAL_4 (0x2 << 20) +#define IMX6Q_GPR2_COUNTER_RESET_VAL_6 (0x3 << 20) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_MASK (0x7 << 16) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_0 (0x0 << 16) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_1 (0x1 << 16) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_2 (0x2 << 16) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_3 (0x3 << 16) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_4 (0x4 << 16) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_5 (0x5 << 16) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_6 (0x6 << 16) +#define IMX6Q_GPR2_LVDS_CLK_SHIFT_7 (0x7 << 16) +#define IMX6Q_GPR2_BGREF_RRMODE_MASK BIT(15) +#define IMX6Q_GPR2_BGREF_RRMODE_EXT_RESISTOR 0x0 +#define IMX6Q_GPR2_BGREF_RRMODE_INT_RESISTOR BIT(15) +#define IMX6Q_GPR2_DI1_VS_POLARITY_MASK BIT(10) +#define IMX6Q_GPR2_DI1_VS_POLARITY_ACTIVE_H 0x0 +#define IMX6Q_GPR2_DI1_VS_POLARITY_ACTIVE_L BIT(10) +#define IMX6Q_GPR2_DI0_VS_POLARITY_MASK BIT(9) +#define IMX6Q_GPR2_DI0_VS_POLARITY_ACTIVE_H 0x0 +#define IMX6Q_GPR2_DI0_VS_POLARITY_ACTIVE_L BIT(9) +#define IMX6Q_GPR2_BIT_MAPPING_CH1_MASK BIT(8) +#define IMX6Q_GPR2_BIT_MAPPING_CH1_SPWG 0x0 +#define IMX6Q_GPR2_BIT_MAPPING_CH1_JEIDA BIT(8) +#define IMX6Q_GPR2_DATA_WIDTH_CH1_MASK BIT(7) +#define IMX6Q_GPR2_DATA_WIDTH_CH1_18BIT 0x0 +#define IMX6Q_GPR2_DATA_WIDTH_CH1_24BIT BIT(7) +#define IMX6Q_GPR2_BIT_MAPPING_CH0_MASK BIT(6) +#define IMX6Q_GPR2_BIT_MAPPING_CH0_SPWG 0x0 +#define IMX6Q_GPR2_BIT_MAPPING_CH0_JEIDA BIT(6) +#define IMX6Q_GPR2_DATA_WIDTH_CH0_MASK BIT(5) +#define IMX6Q_GPR2_DATA_WIDTH_CH0_18BIT 0x0 +#define IMX6Q_GPR2_DATA_WIDTH_CH0_24BIT BIT(5) +#define IMX6Q_GPR2_SPLIT_MODE_EN BIT(4) +#define IMX6Q_GPR2_CH1_MODE_MASK (0x3 << 2) +#define IMX6Q_GPR2_CH1_MODE_DISABLE (0x0 << 2) +#define IMX6Q_GPR2_CH1_MODE_EN_ROUTE_DI0 (0x1 << 2) +#define IMX6Q_GPR2_CH1_MODE_EN_ROUTE_DI1 (0x3 << 2) +#define IMX6Q_GPR2_CH0_MODE_MASK (0x3 << 0) +#define IMX6Q_GPR2_CH0_MODE_DISABLE (0x0 << 0) +#define IMX6Q_GPR2_CH0_MODE_EN_ROUTE_DI0 (0x1 << 0) +#define IMX6Q_GPR2_CH0_MODE_EN_ROUTE_DI1 (0x3 << 0) + +#define IMX6Q_GPR3_GPU_DBG_MASK (0x3 << 29) +#define IMX6Q_GPR3_GPU_DBG_GPU3D (0x0 << 29) +#define IMX6Q_GPR3_GPU_DBG_GPU2D (0x1 << 29) +#define IMX6Q_GPR3_GPU_DBG_OPENVG (0x2 << 29) +#define IMX6Q_GPR3_BCH_WR_CACHE_CTL BIT(28) +#define IMX6Q_GPR3_BCH_RD_CACHE_CTL BIT(27) +#define IMX6Q_GPR3_USDHCX_WR_CACHE_CTL BIT(26) +#define IMX6Q_GPR3_USDHCX_RD_CACHE_CTL BIT(25) +#define IMX6Q_GPR3_OCRAM_CTL_MASK (0xf << 21) +#define IMX6Q_GPR3_OCRAM_STATUS_MASK (0xf << 17) +#define IMX6Q_GPR3_CORE3_DBG_ACK_EN BIT(16) +#define IMX6Q_GPR3_CORE2_DBG_ACK_EN BIT(15) +#define IMX6Q_GPR3_CORE1_DBG_ACK_EN BIT(14) +#define IMX6Q_GPR3_CORE0_DBG_ACK_EN BIT(13) +#define IMX6Q_GPR3_TZASC2_BOOT_LOCK BIT(12) +#define IMX6Q_GPR3_TZASC1_BOOT_LOCK BIT(11) +#define IMX6Q_GPR3_IPU_DIAG_MASK BIT(10) +#define IMX6Q_GPR3_LVDS1_MUX_CTL_MASK (0x3 << 8) +#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU1_DI0 (0x0 << 8) +#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU1_DI1 (0x1 << 8) +#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU2_DI0 (0x2 << 8) +#define IMX6Q_GPR3_LVDS1_MUX_CTL_IPU2_DI1 (0x3 << 8) +#define IMX6Q_GPR3_LVDS0_MUX_CTL_MASK (0x3 << 6) +#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI0 (0x0 << 6) +#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI1 (0x1 << 6) +#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI0 (0x2 << 6) +#define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI1 (0x3 << 6) +#define IMX6Q_GPR3_MIPI_MUX_CTL_MASK (0x3 << 4) +#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI0 (0x0 << 4) +#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI1 (0x1 << 4) +#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU2_DI0 (0x2 << 4) +#define IMX6Q_GPR3_MIPI_MUX_CTL_IPU2_DI1 (0x3 << 4) +#define IMX6Q_GPR3_HDMI_MUX_CTL_MASK (0x3 << 2) +#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU1_DI0 (0x0 << 2) +#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU1_DI1 (0x1 << 2) +#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU2_DI0 (0x2 << 2) +#define IMX6Q_GPR3_HDMI_MUX_CTL_IPU2_DI1 (0x3 << 2) + +#define IMX6Q_GPR4_VDOA_WR_CACHE_SEL BIT(31) +#define IMX6Q_GPR4_VDOA_RD_CACHE_SEL BIT(30) +#define IMX6Q_GPR4_VDOA_WR_CACHE_VAL BIT(29) +#define IMX6Q_GPR4_VDOA_RD_CACHE_VAL BIT(28) +#define IMX6Q_GPR4_PCIE_WR_CACHE_SEL BIT(27) +#define IMX6Q_GPR4_PCIE_RD_CACHE_SEL BIT(26) +#define IMX6Q_GPR4_PCIE_WR_CACHE_VAL BIT(25) +#define IMX6Q_GPR4_PCIE_RD_CACHE_VAL BIT(24) +#define IMX6Q_GPR4_SDMA_STOP_ACK BIT(19) +#define IMX6Q_GPR4_CAN2_STOP_ACK BIT(18) +#define IMX6Q_GPR4_CAN1_STOP_ACK BIT(17) +#define IMX6Q_GPR4_ENET_STOP_ACK BIT(16) +#define IMX6Q_GPR4_SOC_VERSION_MASK (0xff << 8) +#define IMX6Q_GPR4_SOC_VERSION_OFF 0x8 +#define IMX6Q_GPR4_VPU_WR_CACHE_SEL BIT(7) +#define IMX6Q_GPR4_VPU_RD_CACHE_SEL BIT(6) +#define IMX6Q_GPR4_VPU_P_WR_CACHE_VAL BIT(3) +#define IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK BIT(2) +#define IMX6Q_GPR4_IPU_WR_CACHE_CTL BIT(1) +#define IMX6Q_GPR4_IPU_RD_CACHE_CTL BIT(0) + +#define IMX6Q_GPR5_L2_CLK_STOP BIT(8) + +#define IMX6Q_GPR9_TZASC2_BYP BIT(1) +#define IMX6Q_GPR9_TZASC1_BYP BIT(0) + +#define IMX6Q_GPR10_LOCK_DBG_EN BIT(29) +#define IMX6Q_GPR10_LOCK_DBG_CLK_EN BIT(28) +#define IMX6Q_GPR10_LOCK_SEC_ERR_RESP BIT(27) +#define IMX6Q_GPR10_LOCK_OCRAM_TZ_ADDR (0x3f << 21) +#define IMX6Q_GPR10_LOCK_OCRAM_TZ_EN BIT(20) +#define IMX6Q_GPR10_LOCK_DCIC2_MUX_MASK (0x3 << 18) +#define IMX6Q_GPR10_LOCK_DCIC1_MUX_MASK (0x3 << 16) +#define IMX6Q_GPR10_DBG_EN BIT(13) +#define IMX6Q_GPR10_DBG_CLK_EN BIT(12) +#define IMX6Q_GPR10_SEC_ERR_RESP_MASK BIT(11) +#define IMX6Q_GPR10_SEC_ERR_RESP_OKEY 0x0 +#define IMX6Q_GPR10_SEC_ERR_RESP_SLVE BIT(11) +#define IMX6Q_GPR10_OCRAM_TZ_ADDR_MASK (0x3f << 5) +#define IMX6Q_GPR10_OCRAM_TZ_EN_MASK BIT(4) +#define IMX6Q_GPR10_DCIC2_MUX_CTL_MASK (0x3 << 2) +#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI0 (0x0 << 2) +#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU1_DI1 (0x1 << 2) +#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU2_DI0 (0x2 << 2) +#define IMX6Q_GPR10_DCIC2_MUX_CTL_IPU2_DI1 (0x3 << 2) +#define IMX6Q_GPR10_DCIC1_MUX_CTL_MASK (0x3 << 0) +#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI0 (0x0 << 0) +#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU1_DI1 (0x1 << 0) +#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU2_DI0 (0x2 << 0) +#define IMX6Q_GPR10_DCIC1_MUX_CTL_IPU2_DI1 (0x3 << 0) + +#define IMX6Q_GPR12_ARMP_IPG_CLK_EN BIT(27) +#define IMX6Q_GPR12_ARMP_AHB_CLK_EN BIT(26) +#define IMX6Q_GPR12_ARMP_ATB_CLK_EN BIT(25) +#define IMX6Q_GPR12_ARMP_APB_CLK_EN BIT(24) +#define IMX6Q_GPR12_PCIE_CTL_2 BIT(10) + +#define IMX6Q_GPR13_SDMA_STOP_REQ BIT(30) +#define IMX6Q_GPR13_CAN2_STOP_REQ BIT(29) +#define IMX6Q_GPR13_CAN1_STOP_REQ BIT(28) +#define IMX6Q_GPR13_ENET_STOP_REQ BIT(27) +#define IMX6Q_GPR13_SATA_PHY_8_MASK (0x7 << 24) +#define IMX6Q_GPR13_SATA_PHY_8_0_5_DB (0x0 << 24) +#define IMX6Q_GPR13_SATA_PHY_8_1_0_DB (0x1 << 24) +#define IMX6Q_GPR13_SATA_PHY_8_1_5_DB (0x2 << 24) +#define IMX6Q_GPR13_SATA_PHY_8_2_0_DB (0x3 << 24) +#define IMX6Q_GPR13_SATA_PHY_8_2_5_DB (0x4 << 24) +#define IMX6Q_GPR13_SATA_PHY_8_3_0_DB (0x5 << 24) +#define IMX6Q_GPR13_SATA_PHY_8_3_5_DB (0x6 << 24) +#define IMX6Q_GPR13_SATA_PHY_8_4_0_DB (0x7 << 24) +#define IMX6Q_GPR13_SATA_PHY_7_MASK (0x1f << 19) +#define IMX6Q_GPR13_SATA_PHY_7_SATA1I (0x10 << 19) +#define IMX6Q_GPR13_SATA_PHY_7_SATA1M (0x10 << 19) +#define IMX6Q_GPR13_SATA_PHY_7_SATA1X (0x1a << 19) +#define IMX6Q_GPR13_SATA_PHY_7_SATA2I (0x12 << 19) +#define IMX6Q_GPR13_SATA_PHY_7_SATA2M (0x12 << 19) +#define IMX6Q_GPR13_SATA_PHY_7_SATA2X (0x1a << 19) +#define IMX6Q_GPR13_SATA_PHY_6_MASK (0x7 << 16) +#define IMX6Q_GPR13_SATA_PHY_6_OFF 16 +#define IMX6Q_GPR13_SATA_SPEED_MASK BIT(15) +#define IMX6Q_GPR13_SATA_SPEED_1P5G 0x0 +#define IMX6Q_GPR13_SATA_SPEED_3P0G BIT(15) +#define IMX6Q_GPR13_SATA_PHY_5 BIT(14) +#define IMX6Q_GPR13_SATA_PHY_4_MASK (0x7 << 11) +#define IMX6Q_GPR13_SATA_PHY_4_16_16 (0x0 << 11) +#define IMX6Q_GPR13_SATA_PHY_4_14_16 (0x1 << 11) +#define IMX6Q_GPR13_SATA_PHY_4_12_16 (0x2 << 11) +#define IMX6Q_GPR13_SATA_PHY_4_10_16 (0x3 << 11) +#define IMX6Q_GPR13_SATA_PHY_4_9_16 (0x4 << 11) +#define IMX6Q_GPR13_SATA_PHY_4_8_16 (0x5 << 11) +#define IMX6Q_GPR13_SATA_PHY_3_MASK (0xf << 7) +#define IMX6Q_GPR13_SATA_PHY_3_OFF 0x7 +#define IMX6Q_GPR13_SATA_PHY_2_MASK (0x1f << 2) +#define IMX6Q_GPR13_SATA_PHY_2_OFF 0x2 +#define IMX6Q_GPR13_SATA_PHY_1_MASK (0x3 << 0) +#define IMX6Q_GPR13_SATA_PHY_1_FAST (0x0 << 0) +#define IMX6Q_GPR13_SATA_PHY_1_MED (0x1 << 0) +#define IMX6Q_GPR13_SATA_PHY_1_SLOW (0x2 << 0) + +#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */ diff --git a/lib/Makefile b/lib/Makefile index eb0af9248e..635d52e653 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -36,3 +36,4 @@ obj-$(CONFIG_BITREV) += bitrev.o obj-$(CONFIG_QSORT) += qsort.o obj-y += gui/ obj-$(CONFIG_XYMODEM) += xymodem.o +obj-y += unlink-recursive.o diff --git a/lib/gui/image_renderer.c b/lib/gui/image_renderer.c index 41dc43b3c7..78e5777cbd 100644 --- a/lib/gui/image_renderer.c +++ b/lib/gui/image_renderer.c @@ -13,10 +13,10 @@ static LIST_HEAD(image_renderers); -static struct image_renderer *get_renderer(void* buf) +static struct image_renderer *get_renderer(void* buf, size_t bufsize) { struct image_renderer *ir; - enum filetype type = file_detect_type(buf); + enum filetype type = file_detect_type(buf, bufsize); list_for_each_entry(ir, &image_renderers, list) { if (ir->type == type) @@ -40,7 +40,7 @@ struct image *image_renderer_open(const char* file) return ERR_PTR(-ENOMEM); } - ir = get_renderer(data); + ir = get_renderer(data, size); if (!ir) { ret = -ENOENT; goto out; diff --git a/lib/recursive_action.c b/lib/recursive_action.c index 5bc2595db9..345d3db0ce 100644 --- a/lib/recursive_action.c +++ b/lib/recursive_action.c @@ -130,7 +130,6 @@ int recursive_action(const char *fileName, return 0; return 1; done_nak_warn: - printf("%s", fileName); return 0; } diff --git a/lib/uncompress.c b/lib/uncompress.c index 8e4d3a1d91..e0a69df9f9 100644 --- a/lib/uncompress.c +++ b/lib/uncompress.c @@ -78,7 +78,7 @@ int uncompress(unsigned char *inbuf, int len, char *err; if (inbuf) { - ft = file_detect_type(inbuf); + ft = file_detect_type(inbuf, len); uncompress_buf = NULL; uncompress_size = 0; } else { @@ -93,7 +93,7 @@ int uncompress(unsigned char *inbuf, int len, if (ret < 0) goto err; - ft = file_detect_type(uncompress_buf); + ft = file_detect_type(uncompress_buf, 32); } switch (ft) { diff --git a/lib/unlink-recursive.c b/lib/unlink-recursive.c new file mode 100644 index 0000000000..a4885538c0 --- /dev/null +++ b/lib/unlink-recursive.c @@ -0,0 +1,56 @@ +#include <common.h> +#include <libbb.h> +#include <fs.h> + +static char unlink_recursive_failedpath[PATH_MAX]; + +struct data { + int error; +}; + +static int file_action(const char *filename, struct stat *statbuf, + void *userdata, int depth) +{ + struct data *data = userdata; + int ret; + + ret = unlink(filename); + if (ret) { + strcpy(unlink_recursive_failedpath, filename); + data->error = ret; + } + + return ret ? 0 : 1; +} + +static int dir_action(const char *dirname, struct stat *statbuf, + void *userdata, int depth) +{ + struct data *data = userdata; + int ret; + + ret = rmdir(dirname); + if (ret) { + strcpy(unlink_recursive_failedpath, dirname); + data->error = ret; + } + + return ret ? 0 : 1; +} + +int unlink_recursive(const char *path, char **failedpath) +{ + struct data data = {}; + int ret; + + if (failedpath) + *failedpath = NULL; + + ret = recursive_action(path, ACTION_RECURSE | ACTION_DEPTHFIRST, + file_action, dir_action, &data, 0); + + if (!ret && failedpath) + *failedpath = unlink_recursive_failedpath; + + return ret ? 0 : errno; +} @@ -511,7 +511,7 @@ static void net_bad_packet(unsigned char *pkt, int len) * We received a bad packet. for now just dump it. * We could add more sophisticated debugging here */ - memory_display(pkt, 0, len, 1); + memory_display(pkt, 0, len, 1, 0); #endif } diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c index 5fdc62e238..707d63dd81 100644 --- a/scripts/bareboxenv.c +++ b/scripts/bareboxenv.c @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) if (load) { if (verbose) printf("loading env from file %s to %s\n", filename, dirname); - envfs_load(filename, dirname); + envfs_load(filename, dirname, 0); } if (save) { if (verbose) diff --git a/scripts/tags.sh b/scripts/tags.sh new file mode 100755 index 0000000000..79fdafb0d2 --- /dev/null +++ b/scripts/tags.sh @@ -0,0 +1,265 @@ +#!/bin/sh +# Generate tags or cscope files +# Usage tags.sh <mode> +# +# mode may be any of: tags, TAGS, cscope +# +# Uses the following environment variables: +# ARCH, SUBARCH, SRCARCH, srctree, src, obj + +if [ "$KBUILD_VERBOSE" = "1" ]; then + set -x +fi + +# This is a duplicate of RCS_FIND_IGNORE without escaped '()' +ignore="( -name SCCS -o -name BitKeeper -o -name .svn -o \ + -name CVS -o -name .pc -o -name .hg -o \ + -name .git ) \ + -prune -o" + +# Do not use full path if we do not use O=.. builds +# Use make O=. {tags|cscope} +# to force full paths for a non-O= build +if [ "${KBUILD_SRC}" = "" ]; then + tree= +else + tree=${srctree}/ +fi + +# Find all available archs +find_all_archs() +{ + ALLSOURCE_ARCHS="" + for arch in `ls ${tree}arch`; do + ALLSOURCE_ARCHS="${ALLSOURCE_ARCHS} "${arch##\/} + done +} + +# Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH +if [ "${ALLSOURCE_ARCHS}" = "" ]; then + ALLSOURCE_ARCHS=${SRCARCH} +elif [ "${ALLSOURCE_ARCHS}" = "all" ]; then + find_all_archs +fi + +# find sources in arch/$ARCH +find_arch_sources() +{ + for i in $archincludedir; do + prune="$prune -wholename $i -prune -o" + done + find ${tree}arch/$1 $ignore $prune -name "$2" -print; +} + +# find sources in arch/$1/include +find_arch_include_sources() +{ + include=$(find ${tree}arch/$1/ -name include -type d); + if [ -n "$include" ]; then + archincludedir="$archincludedir $include" + find $include $ignore -name "$2" -print; + fi +} + +# find sources in include/ +find_include_sources() +{ + find ${tree}include $ignore -name config -prune -o -name "$1" -print; +} + +# find sources in rest of tree +# we could benefit from a list of dirs to search in here +find_other_sources() +{ + find ${tree}* $ignore \ + \( -name include -o -name arch -o -name '.tmp_*' \) -prune -o \ + -name "$1" -print; +} + +find_sources() +{ + find_arch_sources $1 "$2" +} + +all_sources() +{ + find_arch_include_sources ${SRCARCH} '*.[chS]' + if [ ! -z "$archinclude" ]; then + find_arch_include_sources $archinclude '*.[chS]' + fi + find_include_sources '*.[chS]' + for arch in $ALLSOURCE_ARCHS + do + find_sources $arch '*.[chS]' + done + find_other_sources '*.[chS]' +} + +all_kconfigs() +{ + for arch in $ALLSOURCE_ARCHS; do + find_sources $arch 'Kconfig*' + done + find_other_sources 'Kconfig*' +} + +all_defconfigs() +{ + find_sources $ALLSOURCE_ARCHS "defconfig" +} + +docscope() +{ + (echo \-k; echo \-q; all_sources) > cscope.files + cscope -b -f cscope.out +} + +dogtags() +{ + all_sources | gtags -i -f - +} + +exuberant() +{ + all_sources | xargs $1 -a \ + -I __initdata,__exitdata,__acquires,__releases \ + -I __read_mostly,____cacheline_aligned \ + -I ____cacheline_aligned_in_smp \ + -I ____cacheline_internodealigned_in_smp \ + -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ + -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \ + --extra=+f --c-kinds=+px \ + --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ + --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ + --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ + --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ + --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ + --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ + --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ + --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ + --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ + --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ + --regex-c='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \ + --regex-c='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/' + + all_kconfigs | xargs $1 -a \ + --langdef=kconfig --language-force=kconfig \ + --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/' + + all_kconfigs | xargs $1 -a \ + --langdef=kconfig --language-force=kconfig \ + --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/CONFIG_\2/' + + all_defconfigs | xargs -r $1 -a \ + --langdef=dotconfig --language-force=dotconfig \ + --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' +} + +emacs() +{ + all_sources | xargs $1 -a \ + --regex='/^(ENTRY|_GLOBAL)(\([^)]*\)).*/\2/' \ + --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ + --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ + --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ + --regex='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ + --regex='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ + --regex='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ + --regex='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ + --regex='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ + --regex='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ + --regex='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ + --regex='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ + --regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ + --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ + --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ + --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ + --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ + --regex='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \ + --regex='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/' + + all_kconfigs | xargs $1 -a \ + --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' + + all_kconfigs | xargs $1 -a \ + --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/CONFIG_\3/' + + all_defconfigs | xargs -r $1 -a \ + --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/' +} + +xtags() +{ + if $1 --version 2>&1 | grep -iq exuberant; then + exuberant $1 + elif $1 --version 2>&1 | grep -iq emacs; then + emacs $1 + else + all_sources | xargs $1 -a + fi +} + + +# Support um (which uses SUBARCH) +if [ "${ARCH}" = "um" ]; then + if [ "$SUBARCH" = "i386" ]; then + archinclude=x86 + elif [ "$SUBARCH" = "x86_64" ]; then + archinclude=x86 + else + archinclude=${SUBARCH} + fi +fi + +remove_structs= +case "$1" in + "cscope") + docscope + ;; + + "gtags") + dogtags + ;; + + "tags") + rm -f tags + xtags ctags + remove_structs=y + ;; + + "TAGS") + rm -f TAGS + xtags etags + remove_structs=y + ;; +esac + +# Remove structure forward declarations. +if [ -n "$remove_structs" ]; then + LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' $1 +fi |