diff options
252 files changed, 5382 insertions, 937 deletions
diff --git a/Documentation/boards.dox b/Documentation/boards.dox index 5241f5b442..41de8366ea 100644 --- a/Documentation/boards.dox +++ b/Documentation/boards.dox @@ -38,6 +38,11 @@ ARM type: @li @subpage board_cupid @li @subpage phycard-a-l1 @li @subpage toshiba-ac100 +@li @subpage qil-a9260 +@li @subpage tny-a9g20-lpw +@li @subpage tny-a9263 +@li @subpage usb-a9g20-lpw +@li @subpage usb-a9263 Blackfin type: @@ -264,3 +264,4 @@ then else do_build_target ${ARCH} $1 fi +exit $nb_errors @@ -1,5 +1,5 @@ VERSION = 2012 -PATCHLEVEL = 08 +PATCHLEVEL = 09 SUBLEVEL = 0 EXTRAVERSION = NAME = Amissive Actinocutious Kiwi @@ -254,6 +254,7 @@ MAKEFLAGS += --include-dir=$(srctree) # We need some generic definitions. include $(srctree)/scripts/Kbuild.include +include $(srctree)/scripts/Makefile.lib # Make variables (CC, etc...) @@ -436,12 +437,6 @@ else include/config/auto.conf: ; endif # $(dot-config) -# The all: target is the default when no target is given on the -# command line. -# This allow a user to issue only 'make' to build a kernel -# Defaults barebox but it is usually overridden in the arch makefile -all: barebox.bin - include $(srctree)/arch/$(ARCH)/Makefile ifdef CONFIG_DEBUG_INFO @@ -472,7 +467,14 @@ CFLAGS += $(call cc-option,-Wno-pointer-sign,) # set in the environment # Also any assignments in arch/$(ARCH)/Makefile take precedence over # this default value -export KBUILD_IMAGE ?= barebox +export KBUILD_IMAGE ?= barebox.bin + +barebox-flash-image: $(KBUILD_IMAGE) + $(call if_changed,ln) + +all: barebox-flash-image + +common-$(CONFIG_PBL_IMAGE) += pbl/ barebox-dirs := $(patsubst %/,%,$(filter %/, $(common-y))) @@ -481,6 +483,7 @@ barebox-alldirs := $(sort $(barebox-dirs) $(patsubst %/,%,$(filter %/, \ $(core-n) $(core-) $(drivers-n) $(drivers-) \ $(net-n) $(net-) $(libs-n) $(libs-)))) +pbl-common-y := $(patsubst %/, %/built-in-pbl.o, $(common-y)) common-y := $(patsubst %/, %/built-in.o, $(common-y)) # Build barebox @@ -510,6 +513,8 @@ common-y := $(patsubst %/, %/built-in.o, $(common-y)) # System.map is generated to document addresses of all kernel symbols barebox-common := $(common-y) +barebox-pbl-common := $(pbl-common-y) +export barebox-pbl-common barebox-all := $(barebox-common) barebox-lds := $(lds-y) @@ -517,7 +522,7 @@ barebox-lds := $(lds-y) # May be overridden by arch/$(ARCH)/Makefile quiet_cmd_barebox__ ?= LD $@ cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \ - -T $(barebox-lds) $(barebox-head) \ + -T $(barebox-lds) \ --start-group $(barebox-common) --end-group \ $(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^) @@ -671,7 +676,9 @@ OBJCOPYFLAGS_barebox.bin = -O binary barebox.bin: barebox FORCE $(call if_changed,objcopy) +ifndef CONFIG_PBL_IMAGE $(call cmd,check_file_size,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE)) +endif ifdef CONFIG_X86 barebox.S: barebox @@ -696,9 +703,6 @@ endif @echo " * Init Calls content" >> barebox.S $(Q)$(OBJDUMP) -j .barebox_initcalls -d barebox >> barebox.S else -quiet_cmd_disasm = DISASM $@ - cmd_disasm = $(OBJDUMP) -d $< > $@ - barebox.S: barebox FORCE $(call if_changed,disasm) endif @@ -714,7 +718,7 @@ barebox.srec: barebox # The actual objects are generated when descending, # make sure no implicit rule kicks in -$(sort $(barebox-head) $(barebox-common) ) $(barebox-lds): $(barebox-dirs) ; +$(sort $(barebox-head) $(barebox-common) ) $(barebox-lds) $(barebox-pbl-common): $(barebox-dirs) ; # Handle descending into subdirectories listed in $(barebox-dirs) # Preset locale variables to speed up the build process. Limit locale @@ -1004,7 +1008,7 @@ CLEAN_DIRS += $(MODVERDIR) CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \ .tmp_version .tmp_barebox* barebox.bin barebox.map barebox.S \ .tmp_kallsyms* barebox_default_env* barebox.ldr \ - scripts/bareboxenv-target \ + scripts/bareboxenv-target barebox-flash-image \ Doxyfile.version barebox.srec barebox.s5p # Directories & files removed with 'make mrproper' diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 08c742bfb3..a54ad03445 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -4,6 +4,8 @@ config ARM select HAS_MODULES select HAVE_CONFIGURABLE_MEMORY_LAYOUT select HAVE_CONFIGURABLE_TEXT_BASE + select HAVE_PBL_IMAGE + select HAVE_IMAGE_COMPRESSION default y config ARM_AMBA @@ -14,6 +16,9 @@ config ARM_LINUX default y depends on CMD_BOOTZ || CMD_BOOTU || CMD_BOOTM +config HAVE_MACH_ARM_HEAD + bool + menu "System Type " choice @@ -23,6 +28,8 @@ config ARCH_AT91 bool "Atmel AT91" select GENERIC_GPIO select CLKDEV_LOOKUP + select HAS_DEBUG_LL + select HAVE_MACH_ARM_HEAD config ARCH_EP93XX bool "Cirrus Logic EP93xx" @@ -32,6 +39,7 @@ config ARCH_EP93XX config ARCH_IMX bool "Freescale iMX-based" select GENERIC_GPIO + select GPIOLIB config ARCH_MXS bool "Freescale i.MX23/28 (mxs) based" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1b60261bc8..8e660bea2b 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -160,8 +160,17 @@ CPPFLAGS += -fdata-sections -ffunction-sections LDFLAGS_barebox += -static --gc-sections endif -barebox.netx: barebox.bin - $(Q)scripts/gen_netx_image -i barebox.bin -o barebox.netx \ +ifdef CONFIG_IMAGE_COMPRESSION +KBUILD_BINARY := arch/arm/pbl/zbarebox.bin +KBUILD_TARGET := zbarebox.bin +$(KBUILD_BINARY): $(KBUILD_TARGET) +else +KBUILD_BINARY := barebox.bin +KBUILD_TARGET := barebox.bin +endif + +barebox.netx: $(KBUILD_BINARY) + $(Q)scripts/gen_netx_image -i $< -o barebox.netx \ --sdramctrl=$(CONFIG_NETX_SDRAM_CTRL) \ --sdramtimctrl=$(CONFIG_NETX_SDRAM_TIMING_CTRL) \ --memctrl=$(CONFIG_NETX_MEM_CTRL) \ @@ -169,35 +178,48 @@ barebox.netx: barebox.bin --cookie=$(CONFIG_NETX_COOKIE); ifeq ($(machine-y),netx) -KBUILD_IMAGE := barebox.netx +KBUILD_TARGET := barebox.netx +KBUILD_BINARY := $(KBUILD_TARGET) endif -barebox.s5p: barebox.bin - $(Q)scripts/s5p_cksum barebox.bin barebox.s5p +barebox.s5p: $(KBUILD_BINARY) + $(Q)scripts/s5p_cksum $< barebox.s5p ifeq ($(CONFIG_ARCH_S5PCxx),y) -KBUILD_IMAGE := barebox.s5p +KBUILD_TARGET := barebox.s5p +KBUILD_BINARY := $(KBUILD_TARGET) endif -MLO: barebox.bin - @echo " IFT " $@ - $(Q)scripts/omap_signGP barebox.bin $(TEXT_BASE) 1 - $(Q)test -e barebox.bin.ift && mv barebox.bin.ift MLO +quiet_cmd_mlo ?= IFT $@ + cmd_mlo ?= scripts/omap_signGP $< $(TEXT_BASE) 1; \ + test -e $<.ift && mv $<.ift MLO + +MLO: $(KBUILD_BINARY) + $(call if_changed,mlo) ifeq ($(CONFIG_OMAP_BUILD_IFT),y) -KBUILD_IMAGE := MLO +KBUILD_TARGET := MLO +KBUILD_BINARY := $(KBUILD_TARGET) endif -barebox.ubl: barebox.bin +barebox.ubl: $(KBUILD_BINARY) @echo " UBL " $@ - $(Q)scripts/mkublheader barebox.bin > barebox.ubl - $(Q)cat barebox.bin >> barebox.ubl + $(Q)scripts/mkublheader $< > barebox.ubl + $(Q)cat $< >> barebox.ubl ifeq ($(CONFIG_ARCH_DAVINCI),y) -KBUILD_IMAGE := barebox.ubl +KBUILD_TARGET := barebox.ubl +KBUILD_BINARY := $(KBUILD_TARGET) endif -all: $(KBUILD_IMAGE) +pbl := arch/arm/pbl +zbarebox.S zbarebox.bin zbarebox: barebox.bin + $(Q)$(MAKE) $(build)=$(pbl) $(pbl)/$@ + +archclean: + $(MAKE) $(clean)=$(pbl) + +KBUILD_IMAGE := $(KBUILD_BINARY) archprepare: maketools maketools: @@ -222,4 +244,4 @@ common-y += arch/arm/lib/ arch/arm/cpu/ lds-y := arch/arm/lib/barebox.lds -CLEAN_FILES += include/generated/mach-types.h arch/arm/lib/barebox.lds +CLEAN_FILES += include/generated/mach-types.h arch/arm/lib/barebox.lds barebox-flash-image diff --git a/arch/arm/boards/a9m2410/Makefile b/arch/arm/boards/a9m2410/Makefile index 63026f08b2..6842c844b2 100644 --- a/arch/arm/boards/a9m2410/Makefile +++ b/arch/arm/boards/a9m2410/Makefile @@ -1,3 +1,4 @@ obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += a9m2410.o diff --git a/arch/arm/boards/a9m2410/a9m2410.c b/arch/arm/boards/a9m2410/a9m2410.c index fb3f1baf10..8d97282756 100644 --- a/arch/arm/boards/a9m2410/a9m2410.c +++ b/arch/arm/boards/a9m2410/a9m2410.c @@ -137,13 +137,6 @@ static int a9m2410_devices_init(void) device_initcall(a9m2410_devices_init); -#ifdef CONFIG_S3C_NAND_BOOT -void __bare_init nand_boot(void) -{ - s3c24x0_nand_load_image(_text, 256 * 1024, 0); -} -#endif - static int a9m2410_console_init(void) { s3c24xx_add_uart1(); diff --git a/arch/arm/boards/a9m2440/Makefile b/arch/arm/boards/a9m2440/Makefile index 779e83dc03..8a8f36df02 100644 --- a/arch/arm/boards/a9m2440/Makefile +++ b/arch/arm/boards/a9m2440/Makefile @@ -1,4 +1,5 @@ obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += a9m2440.o obj-$(CONFIG_MACH_A9M2410DEV) += a9m2410dev.o diff --git a/arch/arm/boards/a9m2440/a9m2440.c b/arch/arm/boards/a9m2440/a9m2440.c index 6beb72eb71..ac1c7a491a 100644 --- a/arch/arm/boards/a9m2440/a9m2440.c +++ b/arch/arm/boards/a9m2440/a9m2440.c @@ -156,13 +156,6 @@ static int a9m2440_devices_init(void) device_initcall(a9m2440_devices_init); -#ifdef CONFIG_S3C_NAND_BOOT -void __bare_init nand_boot(void) -{ - s3c24x0_nand_load_image(_text, 256 * 1024, 0); -} -#endif - static int a9m2440_console_init(void) { s3c24xx_add_uart1(); diff --git a/arch/arm/boards/at91sam9260ek/init.c b/arch/arm/boards/at91sam9260ek/init.c index daadf9489f..826f00e353 100644 --- a/arch/arm/boards/at91sam9260ek/init.c +++ b/arch/arm/boards/at91sam9260ek/init.c @@ -234,7 +234,7 @@ static void __init ek_add_led(void) static int at91sam9260ek_mem_init(void) { - at91_add_device_sdram(64 * 1024 * 1024); + at91_add_device_sdram(0); return 0; } diff --git a/arch/arm/boards/at91sam9261ek/init.c b/arch/arm/boards/at91sam9261ek/init.c index b0cab5b0e6..5abe87c966 100644 --- a/arch/arm/boards/at91sam9261ek/init.c +++ b/arch/arm/boards/at91sam9261ek/init.c @@ -236,7 +236,7 @@ static void ek_device_add_leds(void) {} static int at91sam9261ek_mem_init(void) { - at91_add_device_sdram(64 * 1024 * 1024); + at91_add_device_sdram(0); return 0; } diff --git a/arch/arm/boards/at91sam9263ek/init.c b/arch/arm/boards/at91sam9263ek/init.c index 68f4bfc3f1..573fac4562 100644 --- a/arch/arm/boards/at91sam9263ek/init.c +++ b/arch/arm/boards/at91sam9263ek/init.c @@ -166,7 +166,7 @@ static void __init ek_add_device_buttons(void) static int at91sam9263ek_mem_init(void) { - at91_add_device_sdram(64 * 1024 * 1024); + at91_add_device_sdram(0); return 0; } diff --git a/arch/arm/boards/beagle/board.c b/arch/arm/boards/beagle/board.c index 9ddf3172f2..76c9be4fac 100644 --- a/arch/arm/boards/beagle/board.c +++ b/arch/arm/boards/beagle/board.c @@ -253,7 +253,7 @@ static struct NS16550_plat serial_plat = { static int beagle_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, OMAP_UART3_BASE, 1024, IORESOURCE_MEM_8BIT, + add_ns16550_device(DEVICE_ID_DYNAMIC, OMAP_UART3_BASE, 1024, IORESOURCE_MEM_8BIT, &serial_plat); return 0; @@ -283,6 +283,12 @@ static struct i2c_board_info i2c_devices[] = { }, }; +static struct gpmc_nand_platform_data nand_plat = { + .device_width = 16, + .ecc_mode = OMAP_ECC_HAMMING_CODE_HW_ROMCODE, + .nand_cfg = &omap3_nand_cfg, +}; + static int beagle_mem_init(void) { arm_add_mem_device("ram0", 0x80000000, 128 * 1024 * 1024); @@ -306,8 +312,7 @@ static int beagle_devices_init(void) /* WP is made high and WAIT1 active Low */ gpmc_generic_init(0x10); #endif - gpmc_generic_nand_devices_init(0, 16, - OMAP_ECC_HAMMING_CODE_HW_ROMCODE, &omap3_nand_cfg); + omap_add_gpmc_nand_device(&nand_plat); add_generic_device("omap-hsmmc", DEVICE_ID_DYNAMIC, NULL, OMAP_MMC1_BASE, SZ_4K, IORESOURCE_MEM, NULL); diff --git a/arch/arm/boards/ccxmx51/Makefile b/arch/arm/boards/ccxmx51/Makefile index 249927ef2e..f9eb2db14e 100644 --- a/arch/arm/boards/ccxmx51/Makefile +++ b/arch/arm/boards/ccxmx51/Makefile @@ -1,2 +1,3 @@ obj-y += flash_header.o ccxmx51.o +pbl-y += flash_header.o obj-$(CONFIG_MACH_CCMX51_BASEBOARD) += ccxmx51js.o diff --git a/arch/arm/boards/ccxmx51/ccxmx51.c b/arch/arm/boards/ccxmx51/ccxmx51.c index f309e0c693..0b450d64e7 100644 --- a/arch/arm/boards/ccxmx51/ccxmx51.c +++ b/arch/arm/boards/ccxmx51/ccxmx51.c @@ -307,7 +307,7 @@ static int ccxmx51_power_init(void) mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_2, val); } - if (mc13xxx_dev->revision <= MC13892_REVISION_2_0) { + if (mc13xxx_revision(mc13xxx_dev) <= MC13892_REVISION_2_0) { /* Set switchers in PWM mode for Atlas 2.0 and lower */ /* Setup the switcher mode for SW1 & SW2*/ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_4, &val); diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c index b40713d33b..60d1f6283c 100644 --- a/arch/arm/boards/chumby_falconwing/falconwing.c +++ b/arch/arm/boards/chumby_falconwing/falconwing.c @@ -318,7 +318,7 @@ static void falconwing_init_usb(void) imx23_usb_phy_enable(); - add_generic_usb_ehci_device(-1, IMX_USB_BASE, NULL); + add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, IMX_USB_BASE, NULL); } static int falconwing_devices_init(void) diff --git a/arch/arm/boards/crystalfontz-cfa10036/env/init/automount b/arch/arm/boards/crystalfontz-cfa10036/env/init/automount index fe67e55c5a..668775d89b 100644 --- a/arch/arm/boards/crystalfontz-cfa10036/env/init/automount +++ b/arch/arm/boards/crystalfontz-cfa10036/env/init/automount @@ -6,4 +6,4 @@ if [ "$1" = menu ]; then fi mkdir -p /mnt/disk0.1 -automount -d /mnt/disk0.1 '[ -e /dev/disk0.1 ] && mount /dev/disk0.1 fat /mnt/disk0.1' +automount -d /mnt/disk0.1 '[ -e /dev/disk0.1 ] && mount /dev/disk0.1 /mnt/disk0.1' diff --git a/arch/arm/boards/edb93xx/Makefile b/arch/arm/boards/edb93xx/Makefile index e19cd7b4c2..945c963ffd 100644 --- a/arch/arm/boards/edb93xx/Makefile +++ b/arch/arm/boards/edb93xx/Makefile @@ -1,2 +1,3 @@ obj-y += edb93xx.o flash_cfg.o pll_cfg.o sdram_cfg.o +pbl-y += edb93xx.o flash_cfg.o pll_cfg.o sdram_cfg.o diff --git a/arch/arm/boards/edb93xx/edb93xx.c b/arch/arm/boards/edb93xx/edb93xx.c index d32daf4923..3de4d4965e 100644 --- a/arch/arm/boards/edb93xx/edb93xx.c +++ b/arch/arm/boards/edb93xx/edb93xx.c @@ -57,7 +57,7 @@ mem_initcall(ep93xx_mem_init); static int ep93xx_devices_init(void) { - add_cfi_flash_device(-1, 0x60000000, EDB93XX_CFI_FLASH_SIZE, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0x60000000, EDB93XX_CFI_FLASH_SIZE, 0); /* * Create partitions that should be diff --git a/arch/arm/boards/eukrea_cpuimx25/Makefile b/arch/arm/boards/eukrea_cpuimx25/Makefile index 406c6f32f7..cc01cf985b 100644 --- a/arch/arm/boards/eukrea_cpuimx25/Makefile +++ b/arch/arm/boards/eukrea_cpuimx25/Makefile @@ -21,4 +21,7 @@ # obj-y += lowlevel.o +pbl-y += lowlevel.o obj-y += eukrea_cpuimx25.o +obj-$(CONFIG_ARCH_IMX_INTERNAL_BOOT) += flash_header.o +pbl-$(CONFIG_ARCH_IMX_INTERNAL_BOOT) += flash_header.o diff --git a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c index 0aac13c988..a84288cca3 100644 --- a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c +++ b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c @@ -50,40 +50,6 @@ #include <mach/devices-imx25.h> #include <asm/barebox-arm-head.h> -void __naked __flash_header_start go(void) -{ - barebox_arm_head(); -} - -struct imx_dcd_entry __dcd_entry_section dcd_entry[] = { - { .ptr_type = 4, .addr = 0xb8001010, .val = 0x00000004, }, - { .ptr_type = 4, .addr = 0xb8001000, .val = 0x92100000, }, - { .ptr_type = 1, .addr = 0x80000400, .val = 0x12344321, }, - { .ptr_type = 4, .addr = 0xb8001000, .val = 0xa2100000, }, - { .ptr_type = 4, .addr = 0x80000000, .val = 0x12344321, }, - { .ptr_type = 4, .addr = 0x80000000, .val = 0x12344321, }, - { .ptr_type = 4, .addr = 0xb8001000, .val = 0xb2100000, }, - { .ptr_type = 1, .addr = 0x80000033, .val = 0xda, }, - { .ptr_type = 1, .addr = 0x81000000, .val = 0xff, }, - { .ptr_type = 4, .addr = 0xb8001000, .val = 0x82216080, }, - { .ptr_type = 4, .addr = 0xb8001004, .val = 0x00295729, }, - { .ptr_type = 4, .addr = 0x53f80008, .val = 0x20034000, }, -}; - -struct imx_flash_header __flash_header_section flash_header = { - .app_code_jump_vector = DEST_BASE + 0x1000, - .app_code_barker = APP_CODE_BARKER, - .app_code_csf = 0, - .dcd_ptr_ptr = FLASH_HEADER_BASE + offsetof(struct imx_flash_header, dcd), - .super_root_key = 0, - .dcd = FLASH_HEADER_BASE + offsetof(struct imx_flash_header, dcd_barker), - .app_dest = DEST_BASE, - .dcd_barker = DCD_BARKER, - .dcd_block_len = sizeof(dcd_entry), -}; - -unsigned long __image_len_section barebox_len = DCD_BAREBOX_SIZE; - static struct fec_platform_data fec_info = { .xcv_type = RMII, .phy_addr = 0, diff --git a/arch/arm/boards/eukrea_cpuimx25/flash_header.c b/arch/arm/boards/eukrea_cpuimx25/flash_header.c new file mode 100644 index 0000000000..344c7ffc13 --- /dev/null +++ b/arch/arm/boards/eukrea_cpuimx25/flash_header.c @@ -0,0 +1,61 @@ +/* + * (C) 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> + * (c) 2010 Eukrea Electromatique, Eric Bénard <eric@eukrea.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 + * + */ +#include <common.h> +#include <mach/imx-flash-header.h> +#include <mach/imx-regs.h> +#include <asm/barebox-arm-head.h> + +void __naked __flash_header_start go(void) +{ + barebox_arm_head(); +} + +struct imx_dcd_entry __dcd_entry_section dcd_entry[] = { + { .ptr_type = 4, .addr = 0xb8001010, .val = 0x00000004, }, + { .ptr_type = 4, .addr = 0xb8001000, .val = 0x92100000, }, + { .ptr_type = 1, .addr = 0x80000400, .val = 0x12344321, }, + { .ptr_type = 4, .addr = 0xb8001000, .val = 0xa2100000, }, + { .ptr_type = 4, .addr = 0x80000000, .val = 0x12344321, }, + { .ptr_type = 4, .addr = 0x80000000, .val = 0x12344321, }, + { .ptr_type = 4, .addr = 0xb8001000, .val = 0xb2100000, }, + { .ptr_type = 1, .addr = 0x80000033, .val = 0xda, }, + { .ptr_type = 1, .addr = 0x81000000, .val = 0xff, }, + { .ptr_type = 4, .addr = 0xb8001000, .val = 0x82216080, }, + { .ptr_type = 4, .addr = 0xb8001004, .val = 0x00295729, }, + { .ptr_type = 4, .addr = 0x53f80008, .val = 0x20034000, }, +}; + +struct imx_flash_header __flash_header_section flash_header = { + .app_code_jump_vector = DEST_BASE + 0x1000, + .app_code_barker = APP_CODE_BARKER, + .app_code_csf = 0, + .dcd_ptr_ptr = FLASH_HEADER_BASE + offsetof(struct imx_flash_header, dcd), + .super_root_key = 0, + .dcd = FLASH_HEADER_BASE + offsetof(struct imx_flash_header, dcd_barker), + .app_dest = DEST_BASE, + .dcd_barker = DCD_BARKER, + .dcd_block_len = sizeof(dcd_entry), +}; + +unsigned long __image_len_section barebox_len = DCD_BAREBOX_SIZE; diff --git a/arch/arm/boards/eukrea_cpuimx27/Makefile b/arch/arm/boards/eukrea_cpuimx27/Makefile index 5d958fa9aa..fe6d376159 100644 --- a/arch/arm/boards/eukrea_cpuimx27/Makefile +++ b/arch/arm/boards/eukrea_cpuimx27/Makefile @@ -1,3 +1,4 @@ obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += eukrea_cpuimx27.o diff --git a/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c b/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c index 193c277561..10466ba117 100644 --- a/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c +++ b/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c @@ -191,9 +191,9 @@ static int eukrea_cpuimx27_devices_init(void) for (i = 0; i < ARRAY_SIZE(mode); i++) imx_gpio_mode(mode[i]); - add_cfi_flash_device(-1, 0xC0000000, 32 * 1024 * 1024, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0xC0000000, 32 * 1024 * 1024, 0); #ifdef CONFIG_EUKREA_CPUIMX27_NOR_64MB - add_cfi_flash_device(-1, 0xC2000000, 32 * 1024 * 1024, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0xC2000000, 32 * 1024 * 1024, 0); #endif imx27_add_nand(&nand_info); @@ -227,13 +227,13 @@ device_initcall(eukrea_cpuimx27_devices_init); static int eukrea_cpuimx27_console_init(void) { #ifdef CONFIG_DRIVER_SERIAL_IMX - imx_add_uart((void *)IMX_UART1_BASE, -1); + imx_add_uart((void *)IMX_UART1_BASE, DEVICE_ID_DYNAMIC); #endif /* configure 8 bit UART on cs3 */ FMCR &= ~0x2; imx27_setup_weimcs(3, 0x0000D603, 0x0D1D0D01, 0x00D20000); #ifdef CONFIG_DRIVER_SERIAL_NS16550 - add_ns16550_device(-1, IMX_CS3_BASE + QUART_OFFSET, 0xf, + add_ns16550_device(DEVICE_ID_DYNAMIC, IMX_CS3_BASE + QUART_OFFSET, 0xf, IORESOURCE_MEM_16BIT, &quad_uart_serial_plat); #endif return 0; diff --git a/arch/arm/boards/eukrea_cpuimx35/Makefile b/arch/arm/boards/eukrea_cpuimx35/Makefile index 32ffe42cb1..234c1bab12 100644 --- a/arch/arm/boards/eukrea_cpuimx35/Makefile +++ b/arch/arm/boards/eukrea_cpuimx35/Makefile @@ -21,5 +21,7 @@ # obj-y += lowlevel.o +pbl-y += lowlevel.o obj-y += eukrea_cpuimx35.o obj-$(CONFIG_ARCH_IMX_INTERNAL_BOOT) += flash_header.o +pbl-$(CONFIG_ARCH_IMX_INTERNAL_BOOT) += flash_header.o diff --git a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c index 49dbabc491..e657e77e51 100644 --- a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c +++ b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c @@ -220,13 +220,13 @@ static int eukrea_cpuimx35_devices_init(void) #ifdef CONFIG_USB imx35_usb_init(); - add_generic_usb_ehci_device(-1, IMX_OTG_BASE + 0x400, NULL); + add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, IMX_OTG_BASE + 0x400, NULL); #endif #ifdef CONFIG_USB_GADGET /* Workaround ENGcm09152 */ tmp = readl(IMX_OTG_BASE + 0x608); writel(tmp | (1 << 23), IMX_OTG_BASE + 0x608); - add_generic_device("fsl-udc", -1, NULL, IMX_OTG_BASE, 0x200, + add_generic_device("fsl-udc", DEVICE_ID_DYNAMIC, NULL, IMX_OTG_BASE, 0x200, IORESOURCE_MEM, &usb_pdata); #endif armlinux_set_bootparams((void *)0x80000100); diff --git a/arch/arm/boards/eukrea_cpuimx51/Makefile b/arch/arm/boards/eukrea_cpuimx51/Makefile index 0f781c0f34..ce81ffa207 100644 --- a/arch/arm/boards/eukrea_cpuimx51/Makefile +++ b/arch/arm/boards/eukrea_cpuimx51/Makefile @@ -1,2 +1,3 @@ obj-y += eukrea_cpuimx51.o obj-y += flash_header.o +pbl-y += flash_header.o diff --git a/arch/arm/boards/freescale-mx25-3-stack/3stack.c b/arch/arm/boards/freescale-mx25-3-stack/3stack.c index 97c1fd9427..f6162fd279 100644 --- a/arch/arm/boards/freescale-mx25-3-stack/3stack.c +++ b/arch/arm/boards/freescale-mx25-3-stack/3stack.c @@ -213,7 +213,7 @@ static int imx25_devices_init(void) * the CPLD has to be initialized. */ imx25_usb_init(); - add_generic_usb_ehci_device(-1, IMX_OTG_BASE + 0x400, NULL); + add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, IMX_OTG_BASE + 0x400, NULL); #endif imx25_iim_register_fec_ethaddr(); diff --git a/arch/arm/boards/freescale-mx25-3-stack/Makefile b/arch/arm/boards/freescale-mx25-3-stack/Makefile index ab853e0d6b..ff70e1b66c 100644 --- a/arch/arm/boards/freescale-mx25-3-stack/Makefile +++ b/arch/arm/boards/freescale-mx25-3-stack/Makefile @@ -21,4 +21,5 @@ # obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += 3stack.o diff --git a/arch/arm/boards/freescale-mx35-3-stack/3stack.c b/arch/arm/boards/freescale-mx35-3-stack/3stack.c index 9b255a55fa..cfd2c16f0d 100644 --- a/arch/arm/boards/freescale-mx35-3-stack/3stack.c +++ b/arch/arm/boards/freescale-mx35-3-stack/3stack.c @@ -159,7 +159,7 @@ static int f3s_devices_init(void) * This platform supports NOR and NAND */ imx35_add_nand(&nand_info); - add_cfi_flash_device(-1, IMX_CS0_BASE, 64 * 1024 * 1024, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, IMX_CS0_BASE, 64 * 1024 * 1024, 0); switch ((reg >> 25) & 0x3) { case 0x01: /* NAND is the source */ @@ -362,7 +362,6 @@ static int f3s_get_rev(struct mc13xxx *mc13xxx) if (err) return err; - dev_info(&mc13xxx->client->dev, "revision: 0x%x\n", rev); if (rev == 0x00ffffff) return -ENODEV; @@ -379,8 +378,7 @@ static int f3s_pmic_init_v2(struct mc13xxx *mc13xxx) err |= mc13xxx_set_bits(mc13xxx, MC13892_REG_SETTING_0, 0x03, 0x03); err |= mc13xxx_set_bits(mc13xxx, MC13892_REG_MODE_0, 0x01, 0x01); if (err) - dev_err(&mc13xxx->client->dev, - "Init sequence failed, the system might not be working!\n"); + printf("mc13892 Init sequence failed, the system might not be working!\n"); return err; } diff --git a/arch/arm/boards/freescale-mx35-3-stack/Makefile b/arch/arm/boards/freescale-mx35-3-stack/Makefile index a8ea4a3d66..3f224f6ad2 100644 --- a/arch/arm/boards/freescale-mx35-3-stack/Makefile +++ b/arch/arm/boards/freescale-mx35-3-stack/Makefile @@ -1,4 +1,6 @@ obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += 3stack.o obj-$(CONFIG_ARCH_IMX_INTERNAL_BOOT) += flash_header.o +pbl-$(CONFIG_ARCH_IMX_INTERNAL_BOOT) += flash_header.o diff --git a/arch/arm/boards/freescale-mx51-pdk/Makefile b/arch/arm/boards/freescale-mx51-pdk/Makefile index b56ce7f50d..d08bb68a5c 100644 --- a/arch/arm/boards/freescale-mx51-pdk/Makefile +++ b/arch/arm/boards/freescale-mx51-pdk/Makefile @@ -1,2 +1,3 @@ obj-y += board.o obj-y += flash_header.o +pbl-y += flash_header.o diff --git a/arch/arm/boards/freescale-mx51-pdk/board.c b/arch/arm/boards/freescale-mx51-pdk/board.c index 7c2c8fe71e..b67a509680 100644 --- a/arch/arm/boards/freescale-mx51-pdk/board.c +++ b/arch/arm/boards/freescale-mx51-pdk/board.c @@ -178,7 +178,7 @@ static void babbage_power_init(void) mc13xxx_reg_write(mc13xxx, MC13892_REG_SW_2, val); } - if (mc13xxx->revision < MC13892_REVISION_2_0) { + if (mc13xxx_revision(mc13xxx) < MC13892_REVISION_2_0) { /* Set switchers in PWM mode for Atlas 2.0 and lower */ /* Setup the switcher mode for SW1 & SW2*/ mc13xxx_reg_read(mc13xxx, MC13892_REG_SW_4, &val); diff --git a/arch/arm/boards/freescale-mx53-loco/Makefile b/arch/arm/boards/freescale-mx53-loco/Makefile index b56ce7f50d..d08bb68a5c 100644 --- a/arch/arm/boards/freescale-mx53-loco/Makefile +++ b/arch/arm/boards/freescale-mx53-loco/Makefile @@ -1,2 +1,3 @@ obj-y += board.o obj-y += flash_header.o +pbl-y += flash_header.o diff --git a/arch/arm/boards/freescale-mx53-smd/Makefile b/arch/arm/boards/freescale-mx53-smd/Makefile index b56ce7f50d..d08bb68a5c 100644 --- a/arch/arm/boards/freescale-mx53-smd/Makefile +++ b/arch/arm/boards/freescale-mx53-smd/Makefile @@ -1,2 +1,3 @@ obj-y += board.o obj-y += flash_header.o +pbl-y += flash_header.o diff --git a/arch/arm/boards/freescale-mx6-arm2/Makefile b/arch/arm/boards/freescale-mx6-arm2/Makefile index ad2e1beb99..11199d252c 100644 --- a/arch/arm/boards/freescale-mx6-arm2/Makefile +++ b/arch/arm/boards/freescale-mx6-arm2/Makefile @@ -1 +1,2 @@ obj-y += board.o flash_header.o +pbl-y += flash_header.o diff --git a/arch/arm/boards/freescale-mx6-sabrelite/Makefile b/arch/arm/boards/freescale-mx6-sabrelite/Makefile index ad2e1beb99..11199d252c 100644 --- a/arch/arm/boards/freescale-mx6-sabrelite/Makefile +++ b/arch/arm/boards/freescale-mx6-sabrelite/Makefile @@ -1 +1,2 @@ obj-y += board.o flash_header.o +pbl-y += flash_header.o diff --git a/arch/arm/boards/freescale-mx6-sabrelite/board.c b/arch/arm/boards/freescale-mx6-sabrelite/board.c index 13279bc95c..1ac401ebb1 100644 --- a/arch/arm/boards/freescale-mx6-sabrelite/board.c +++ b/arch/arm/boards/freescale-mx6-sabrelite/board.c @@ -77,6 +77,23 @@ static iomux_v3_cfg_t sabrelite_pads[] = { MX6Q_PAD_EIM_D17__ECSPI1_MISO, MX6Q_PAD_EIM_D18__ECSPI1_MOSI, MX6Q_PAD_EIM_D19__GPIO_3_19, /* CS1 */ + + /* I2C0 */ + MX6Q_PAD_EIM_D21__I2C1_SCL, + MX6Q_PAD_EIM_D28__I2C1_SDA, + + /* I2C1 */ + MX6Q_PAD_KEY_COL3__I2C2_SCL, + MX6Q_PAD_KEY_ROW3__I2C2_SDA, + + /* I2C2 */ + MX6Q_PAD_GPIO_5__I2C3_SCL, + MX6Q_PAD_GPIO_16__I2C3_SDA, + + /* USB */ + MX6Q_PAD_GPIO_17__GPIO_7_12, + MX6Q_PAD_EIM_D22__GPIO_3_22, + MX6Q_PAD_EIM_D30__USBOH3_USBH1_OC, }; static iomux_v3_cfg_t sabrelite_enet_pads[] = { @@ -227,6 +244,19 @@ static struct esdhc_platform_data sabrelite_sd4_data = { .wp_type = ESDHC_WP_NONE, }; +static void sabrelite_ehci_init(void) +{ + imx6_usb_phy1_disable_oc(); + imx6_usb_phy1_enable(); + + /* hub reset */ + gpio_direction_output(204, 0); + udelay(2000); + gpio_set_value(204, 1); + + add_generic_usb_ehci_device(1, MX6_USBOH3_USB_BASE_ADDR + 0x200, NULL); +} + static int sabrelite_devices_init(void) { imx6_add_mmc2(&sabrelite_sd3_data); @@ -237,6 +267,8 @@ static int sabrelite_devices_init(void) imx6_add_fec(&fec_info); mx6_rgmii_rework(); + sabrelite_ehci_init(); + spi_register_board_info(sabrelite_spi_board_info, ARRAY_SIZE(sabrelite_spi_board_info)); imx6_add_spi0(&sabrelite_spi_0_data); diff --git a/arch/arm/boards/friendlyarm-mini2440/Makefile b/arch/arm/boards/friendlyarm-mini2440/Makefile index 856fed092e..f56e80382a 100644 --- a/arch/arm/boards/friendlyarm-mini2440/Makefile +++ b/arch/arm/boards/friendlyarm-mini2440/Makefile @@ -1,2 +1,3 @@ obj-y += mini2440.o lowlevel_init.o +pbl-y += lowlevel_init.o diff --git a/arch/arm/boards/friendlyarm-mini2440/mini2440.c b/arch/arm/boards/friendlyarm-mini2440/mini2440.c index a032fbc053..251287ee20 100644 --- a/arch/arm/boards/friendlyarm-mini2440/mini2440.c +++ b/arch/arm/boards/friendlyarm-mini2440/mini2440.c @@ -324,13 +324,6 @@ static int mini2440_devices_init(void) device_initcall(mini2440_devices_init); -#ifdef CONFIG_S3C_NAND_BOOT -void __bare_init nand_boot(void) -{ - s3c24x0_nand_load_image(_text, 256 * 1024, 0); -} -#endif - static int mini2440_console_init(void) { /* diff --git a/arch/arm/boards/friendlyarm-tiny210/tiny210.c b/arch/arm/boards/friendlyarm-tiny210/tiny210.c index 1277649373..18494b0517 100644 --- a/arch/arm/boards/friendlyarm-tiny210/tiny210.c +++ b/arch/arm/boards/friendlyarm-tiny210/tiny210.c @@ -86,7 +86,7 @@ static int tiny210_console_init(void) s3c_gpio_mode(GPA02_NCTS0 | ENABLE_PU); s3c_gpio_mode(GPA03_NRTS0); - add_generic_device("s3c_serial", -1, NULL, + add_generic_device("s3c_serial", DEVICE_ID_DYNAMIC, NULL, S3C_UART1_BASE, S3C_UART1_SIZE, IORESOURCE_MEM, NULL); return 0; diff --git a/arch/arm/boards/guf-cupid/Makefile b/arch/arm/boards/guf-cupid/Makefile index 3a06cf406b..69208aa498 100644 --- a/arch/arm/boards/guf-cupid/Makefile +++ b/arch/arm/boards/guf-cupid/Makefile @@ -21,4 +21,5 @@ # obj-y += lowlevel.o +pbl-y += lowlevel.o obj-y += board.o diff --git a/arch/arm/boards/guf-neso/Makefile b/arch/arm/boards/guf-neso/Makefile index 2b6eb02595..89f0aba1af 100644 --- a/arch/arm/boards/guf-neso/Makefile +++ b/arch/arm/boards/guf-neso/Makefile @@ -1,5 +1,4 @@ - obj-y += lowlevel.o +pbl-y += lowlevel.o obj-y += board.o obj-y += pll_init.o - diff --git a/arch/arm/boards/guf-neso/board.c b/arch/arm/boards/guf-neso/board.c index fbb20c10e0..623dc0ad4e 100644 --- a/arch/arm/boards/guf-neso/board.c +++ b/arch/arm/boards/guf-neso/board.c @@ -280,7 +280,7 @@ static int neso_devices_init(void) #ifdef CONFIG_USB neso_usbh_init(); - add_generic_usb_ehci_device(-1, IMX_OTG_BASE + 0x400, NULL); + add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, IMX_OTG_BASE + 0x400, NULL); #endif imx27_add_fec(&fec_info); diff --git a/arch/arm/boards/imx21ads/Makefile b/arch/arm/boards/imx21ads/Makefile index 7993fdef8a..e18f7d9c3c 100644 --- a/arch/arm/boards/imx21ads/Makefile +++ b/arch/arm/boards/imx21ads/Makefile @@ -1,2 +1,3 @@ obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += imx21ads.o diff --git a/arch/arm/boards/imx21ads/imx21ads.c b/arch/arm/boards/imx21ads/imx21ads.c index 2bbd5ede25..58086bca11 100644 --- a/arch/arm/boards/imx21ads/imx21ads.c +++ b/arch/arm/boards/imx21ads/imx21ads.c @@ -167,7 +167,7 @@ static int mx21ads_devices_init(void) for (i = 0; i < ARRAY_SIZE(mode); i++) imx_gpio_mode(mode[i]); - add_cfi_flash_device(-1, 0xC8000000, 32 * 1024 * 1024, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0xC8000000, 32 * 1024 * 1024, 0); imx21_add_nand(&nand_info); add_generic_device("cs8900", DEVICE_ID_DYNAMIC, NULL, IMX_CS1_BASE, 0x1000, IORESOURCE_MEM, NULL); diff --git a/arch/arm/boards/imx27ads/Makefile b/arch/arm/boards/imx27ads/Makefile index bdc905f0ef..88d1baf619 100644 --- a/arch/arm/boards/imx27ads/Makefile +++ b/arch/arm/boards/imx27ads/Makefile @@ -1,3 +1,4 @@ obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += imx27ads.o diff --git a/arch/arm/boards/imx27ads/imx27ads.c b/arch/arm/boards/imx27ads/imx27ads.c index ff002249de..6b0fc724d8 100644 --- a/arch/arm/boards/imx27ads/imx27ads.c +++ b/arch/arm/boards/imx27ads/imx27ads.c @@ -108,7 +108,7 @@ static int mx27ads_devices_init(void) for (i = 0; i < ARRAY_SIZE(mode); i++) imx_gpio_mode(mode[i]); - add_cfi_flash_device(-1, 0xC0000000, 32 * 1024 * 1024, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0xC0000000, 32 * 1024 * 1024, 0); imx27_add_fec(&fec_info); devfs_add_partition("nor0", 0x00000, 0x20000, DEVFS_PARTITION_FIXED, "self0"); diff --git a/arch/arm/boards/karo-tx25/Makefile b/arch/arm/boards/karo-tx25/Makefile index e909a2c172..90f244b872 100644 --- a/arch/arm/boards/karo-tx25/Makefile +++ b/arch/arm/boards/karo-tx25/Makefile @@ -21,4 +21,5 @@ # obj-y += lowlevel.o +pbl-y += lowlevel.o obj-y += board.o diff --git a/arch/arm/boards/karo-tx51/Makefile b/arch/arm/boards/karo-tx51/Makefile index e8f710e1ac..6f51586e53 100644 --- a/arch/arm/boards/karo-tx51/Makefile +++ b/arch/arm/boards/karo-tx51/Makefile @@ -1,2 +1,3 @@ obj-y += tx51.o -obj-y += flash_header.o +obj-$(CONFIG_ARCH_IMX_INTERNAL_BOOT) += flash_header.o +pbl-$(CONFIG_ARCH_IMX_INTERNAL_BOOT) += flash_header.o diff --git a/arch/arm/boards/mioa701/board.c b/arch/arm/boards/mioa701/board.c index ab5a493e76..b5c05a6eea 100644 --- a/arch/arm/boards/mioa701/board.c +++ b/arch/arm/boards/mioa701/board.c @@ -121,7 +121,7 @@ static int mioa701_devices_init(void) pxa_add_pwm((void *)0x40b00000, 0); pxa_add_fb((void *)0x44000000, &mioa701_pxafb_info); - pxa_add_mmc((void *)0x41100000, -1, &mioa701_mmc_info); + pxa_add_mmc((void *)0x41100000, DEVICE_ID_DYNAMIC, &mioa701_mmc_info); docg3_iospace = map_io_sections(0x0, (void *)0xe0000000, 0x2000); add_generic_device("docg3", DEVICE_ID_DYNAMIC, NULL, (ulong) docg3_iospace, 0x2000, IORESOURCE_MEM, NULL); diff --git a/arch/arm/boards/mioa701/env/bin/sdcard_override b/arch/arm/boards/mioa701/env/bin/sdcard_override index 4b2ad51343..ab83534135 100644 --- a/arch/arm/boards/mioa701/env/bin/sdcard_override +++ b/arch/arm/boards/mioa701/env/bin/sdcard_override @@ -8,7 +8,7 @@ mci0.probe=1 if [ $mci0.probe = 1 ]; then mkdir /sdcard - mount /dev/disk0.0 fat /sdcard + mount /dev/disk0.0 /sdcard if [ -f /sdcard/barebox.env ]; then loadenv /sdcard/barebox.env /env.sd /env.sd/bin/init diff --git a/arch/arm/boards/netx/Makefile b/arch/arm/boards/netx/Makefile index 8b33fec316..ad694cd272 100644 --- a/arch/arm/boards/netx/Makefile +++ b/arch/arm/boards/netx/Makefile @@ -1,2 +1,2 @@ obj-y += netx.o platform.o - +pbl-y += platform.o diff --git a/arch/arm/boards/netx/netx.c b/arch/arm/boards/netx/netx.c index c4a8733aad..fde1b9416a 100644 --- a/arch/arm/boards/netx/netx.c +++ b/arch/arm/boards/netx/netx.c @@ -47,7 +47,7 @@ static int netx_mem_init(void) mem_initcall(netx_mem_init); static int netx_devices_init(void) { - add_cfi_flash_device(-1, 0xC0000000, 32 * 1024 * 1024, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0xC0000000, 32 * 1024 * 1024, 0); add_generic_device("netx-eth", DEVICE_ID_DYNAMIC, NULL, 0, 0, IORESOURCE_MEM, ð0_data); diff --git a/arch/arm/boards/nhk8815/setup.c b/arch/arm/boards/nhk8815/setup.c index ccc0510555..5820114307 100644 --- a/arch/arm/boards/nhk8815/setup.c +++ b/arch/arm/boards/nhk8815/setup.c @@ -63,7 +63,7 @@ static struct resource nhk8815_nand_resources[] = { .flags = IORESOURCE_MEM, }, { .start = NAND_IO_DATA, - .end = NAND_IO_CMD + 0xfff, + .end = NAND_IO_DATA + 0xfff, .flags = IORESOURCE_MEM, } }; diff --git a/arch/arm/boards/omap343xdsp/board.c b/arch/arm/boards/omap343xdsp/board.c index b5174f3a6e..8d4119331b 100644 --- a/arch/arm/boards/omap343xdsp/board.c +++ b/arch/arm/boards/omap343xdsp/board.c @@ -621,7 +621,7 @@ static struct NS16550_plat serial_plat = { static int sdp3430_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, OMAP_UART3_BASE, 1024, IORESOURCE_MEM_8BIT, + add_ns16550_device(DEVICE_ID_DYNAMIC, OMAP_UART3_BASE, 1024, IORESOURCE_MEM_8BIT, &serial_plat); return 0; diff --git a/arch/arm/boards/panda/Makefile b/arch/arm/boards/panda/Makefile index c55e26e066..53b9d5b88b 100644 --- a/arch/arm/boards/panda/Makefile +++ b/arch/arm/boards/panda/Makefile @@ -1 +1,3 @@ -obj-y += board.o lowlevel.o mux.o +obj-y += board.o +obj-y += lowlevel.o mux.o +pbl-y += lowlevel.o mux.o diff --git a/arch/arm/boards/panda/board.c b/arch/arm/boards/panda/board.c index 84b4ecd77e..98c05b2f41 100644 --- a/arch/arm/boards/panda/board.c +++ b/arch/arm/boards/panda/board.c @@ -92,7 +92,7 @@ static void panda_ehci_init(void) /* enable power to hub */ gpio_set_value(GPIO_HUB_POWER, 1); - add_usb_ehci_device(-1, 0x4a064c00, + add_usb_ehci_device(DEVICE_ID_DYNAMIC, 0x4a064c00, 0x4a064c00 + 0x10, &ehci_pdata); } #else diff --git a/arch/arm/boards/panda/lowlevel.c b/arch/arm/boards/panda/lowlevel.c index 8591fff053..0b4b199d34 100644 --- a/arch/arm/boards/panda/lowlevel.c +++ b/arch/arm/boards/panda/lowlevel.c @@ -28,6 +28,8 @@ #include <mach/syslib.h> #include <asm/barebox-arm.h> +#define TPS62361_VSEL0_GPIO 7 + void set_muxconf_regs(void); static const struct ddr_regs ddr_regs_400_mhz_2cs = { @@ -70,7 +72,7 @@ static void noinline panda_init_lowlevel(void) omap4_ddr_init(&ddr_regs_400_mhz_2cs, &core); /* Set VCORE1 = 1.3 V, VCORE2 = VCORE3 = 1.21V */ - omap4_scale_vcores(); + omap4_scale_vcores(TPS62361_VSEL0_GPIO); board_init_lowlevel_return(); } diff --git a/arch/arm/boards/panda/mux.c b/arch/arm/boards/panda/mux.c index 310e43372f..3783006ad6 100644 --- a/arch/arm/boards/panda/mux.c +++ b/arch/arm/boards/panda/mux.c @@ -3,6 +3,7 @@ #include <io.h> #include <mach/omap4-silicon.h> #include <mach/omap4-mux.h> +#include <mach/omap4-clock.h> static const struct pad_conf_entry core_padconf_array[] = { { GPMC_AD0, PTU | IEN | OFF_EN | OFF_PD | OFF_IN | M1 /* sdmmc2_dat0 */ }, @@ -245,4 +246,11 @@ void set_muxconf_regs(void) omap4_do_set_mux(OMAP44XX_CONTROL_PADCONF_WKUP, wkup_padconf_array, ARRAY_SIZE(wkup_padconf_array)); + + /* gpio_wk7 is used for controlling TPS on 4460 */ + if (omap4_revision() >= OMAP4460_ES1_0) { + writew(M3, OMAP44XX_CONTROL_PADCONF_WKUP + PAD1_FREF_CLK4_REQ); + /* Enable GPIO-1 clocks before TPS initialization */ + omap4_enable_gpio1_wup_clocks(); + } } diff --git a/arch/arm/boards/pcm027/Makefile b/arch/arm/boards/pcm027/Makefile index e3830e4f19..1602c0a572 100644 --- a/arch/arm/boards/pcm027/Makefile +++ b/arch/arm/boards/pcm027/Makefile @@ -1,2 +1,3 @@ obj-y += board.o obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o diff --git a/arch/arm/boards/pcm037/Makefile b/arch/arm/boards/pcm037/Makefile index 7d36b77df0..dfe180c8d1 100644 --- a/arch/arm/boards/pcm037/Makefile +++ b/arch/arm/boards/pcm037/Makefile @@ -21,4 +21,5 @@ # obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += pcm037.o diff --git a/arch/arm/boards/pcm038/Makefile b/arch/arm/boards/pcm038/Makefile index 6cd3a5b6c6..2c1b74d306 100644 --- a/arch/arm/boards/pcm038/Makefile +++ b/arch/arm/boards/pcm038/Makefile @@ -1,2 +1,3 @@ obj-y += lowlevel.o pcm038.o +pbl-y += lowlevel.o obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970.o diff --git a/arch/arm/boards/pcm038/pcm038.c b/arch/arm/boards/pcm038/pcm038.c index 8f1271fa5e..912d6ea603 100644 --- a/arch/arm/boards/pcm038/pcm038.c +++ b/arch/arm/boards/pcm038/pcm038.c @@ -292,7 +292,7 @@ static int pcm038_devices_init(void) pcm038_power_init(); - add_cfi_flash_device(-1, 0xC0000000, 32 * 1024 * 1024, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0xC0000000, 32 * 1024 * 1024, 0); imx27_add_nand(&nand_info); imx27_add_fb(&pcm038_fb_data); diff --git a/arch/arm/boards/pcm038/pcm970.c b/arch/arm/boards/pcm038/pcm970.c index b95648270b..31af383c20 100644 --- a/arch/arm/boards/pcm038/pcm970.c +++ b/arch/arm/boards/pcm038/pcm970.c @@ -48,7 +48,7 @@ static void pcm970_usbh2_init(void) mdelay(10); if (!ulpi_setup((void *)(IMX_OTG_BASE + 0x570), 1)) - add_generic_usb_ehci_device(-1, IMX_OTG_BASE + 0x400, NULL); + add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, IMX_OTG_BASE + 0x400, NULL); } #endif @@ -73,7 +73,7 @@ static struct ide_port_info pcm970_ide_pdata = { }; static struct device_d pcm970_ide_device = { - .id = -1, + .id = DEVICE_ID_DYNAMIC, .name = "ide_intf", .num_resources = ARRAY_SIZE(pcm970_ide_resources), .resource = pcm970_ide_resources, diff --git a/arch/arm/boards/pcm043/Makefile b/arch/arm/boards/pcm043/Makefile index 6753bbe81a..961ffcc3a4 100644 --- a/arch/arm/boards/pcm043/Makefile +++ b/arch/arm/boards/pcm043/Makefile @@ -21,4 +21,5 @@ # obj-y += lowlevel.o +pbl-y += lowlevel.o obj-y += pcm043.o diff --git a/arch/arm/boards/pcm043/pcm043.c b/arch/arm/boards/pcm043/pcm043.c index 152b47ce65..95e12fdcb5 100644 --- a/arch/arm/boards/pcm043/pcm043.c +++ b/arch/arm/boards/pcm043/pcm043.c @@ -148,7 +148,7 @@ static int imx35_devices_init(void) * Up to 32MiB NOR type flash, connected to * CS line 0, data width is 16 bit */ - add_cfi_flash_device(-1, IMX_CS0_BASE, 32 * 1024 * 1024, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, IMX_CS0_BASE, 32 * 1024 * 1024, 0); if ((reg & 0xc00) == 0x800) { /* reset mode: external boot */ switch ( (reg >> 25) & 0x3) { diff --git a/arch/arm/boards/pcm049/Makefile b/arch/arm/boards/pcm049/Makefile index 1bb7212a32..df3764ca6a 100644 --- a/arch/arm/boards/pcm049/Makefile +++ b/arch/arm/boards/pcm049/Makefile @@ -1 +1,2 @@ obj-y += board.o mux.o lowlevel.o +pbl-y += lowlevel.o mux.o diff --git a/arch/arm/boards/pcm049/board.c b/arch/arm/boards/pcm049/board.c index 5b7854a5e3..3ef38a7831 100644 --- a/arch/arm/boards/pcm049/board.c +++ b/arch/arm/boards/pcm049/board.c @@ -94,6 +94,12 @@ static struct i2c_board_info i2c_devices[] = { }, }; +static struct gpmc_nand_platform_data nand_plat = { + .wait_mon_pin = 1, + .ecc_mode = OMAP_ECC_BCH8_CODE_HW, + .nand_cfg = &omap4_nand_cfg, +}; + static int pcm049_devices_init(void) { i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices)); @@ -107,8 +113,7 @@ static int pcm049_devices_init(void) pcm049_network_init(); - gpmc_generic_nand_devices_init(0, 8, - OMAP_ECC_BCH8_CODE_HW, &omap4_nand_cfg); + omap_add_gpmc_nand_device(&nand_plat); #ifdef CONFIG_PARTITION devfs_add_partition("nand0", 0x00000, SZ_128K, DEVFS_PARTITION_FIXED, "xload_raw"); diff --git a/arch/arm/boards/pcm049/env/bin/nand_bootstrap b/arch/arm/boards/pcm049/env/bin/nand_bootstrap index acd00dc904..f8873fabe2 100644 --- a/arch/arm/boards/pcm049/env/bin/nand_bootstrap +++ b/arch/arm/boards/pcm049/env/bin/nand_bootstrap @@ -4,7 +4,7 @@ echo "copying barebox to nand..." mci0.probe=1 mkdir mnt -mount /dev/disk0.0 fat /mnt +mount /dev/disk0.0 /mnt if [ $? != 0 ]; then echo "failed to mount mmc card" exit 1 diff --git a/arch/arm/boards/pcm049/lowlevel.c b/arch/arm/boards/pcm049/lowlevel.c index 5b9109833b..65a29ec8ae 100644 --- a/arch/arm/boards/pcm049/lowlevel.c +++ b/arch/arm/boards/pcm049/lowlevel.c @@ -28,6 +28,8 @@ #include <mach/syslib.h> #include <asm/barebox-arm.h> +#define TPS62361_VSEL0_GPIO 182 + void set_muxconf_regs(void); static const struct ddr_regs ddr_regs_mt42L64M64_25_400_mhz = { @@ -46,7 +48,8 @@ static const struct ddr_regs ddr_regs_mt42L64M64_25_400_mhz = { static void noinline pcm049_init_lowlevel(void) { struct dpll_param core = OMAP4_CORE_DPLL_PARAM_19M2_DDR400; - struct dpll_param mpu = OMAP4_MPU_DPLL_PARAM_19M2_MPU1000; + struct dpll_param mpu44xx = OMAP4_MPU_DPLL_PARAM_19M2_MPU1000; + struct dpll_param mpu4460 = OMAP4_MPU_DPLL_PARAM_19M2_MPU920; struct dpll_param iva = OMAP4_IVA_DPLL_PARAM_19M2; struct dpll_param per = OMAP4_PER_DPLL_PARAM_19M2; struct dpll_param abe = OMAP4_ABE_DPLL_PARAM_19M2; @@ -57,12 +60,16 @@ static void noinline pcm049_init_lowlevel(void) omap4_ddr_init(&ddr_regs_mt42L64M64_25_400_mhz, &core); /* Set VCORE1 = 1.3 V, VCORE2 = VCORE3 = 1.21V */ - omap4_scale_vcores(); + omap4_scale_vcores(TPS62361_VSEL0_GPIO); writel(CM_SYS_CLKSEL_19M2, CM_SYS_CLKSEL); /* Configure all DPLL's at 100% OPP */ - omap4_configure_mpu_dpll(&mpu); + if (omap4_revision() < OMAP4460_ES1_0) + omap4_configure_mpu_dpll(&mpu44xx); + else + omap4_configure_mpu_dpll(&mpu4460); + omap4_configure_iva_dpll(&iva); omap4_configure_per_dpll(&per); omap4_configure_abe_dpll(&abe); @@ -88,7 +95,7 @@ void board_init_lowlevel(void) return; r = 0x4030d000; - __asm__ __volatile__("mov sp, %0" : : "r"(r)); + __asm__ __volatile__("mov sp, %0" : : "r"(r)); pcm049_init_lowlevel(); } diff --git a/arch/arm/boards/pcm049/mux.c b/arch/arm/boards/pcm049/mux.c index a7a77b5adc..04e1d67214 100644 --- a/arch/arm/boards/pcm049/mux.c +++ b/arch/arm/boards/pcm049/mux.c @@ -3,6 +3,7 @@ #include <io.h> #include <mach/omap4-silicon.h> #include <mach/omap4-mux.h> +#include <mach/omap4-clock.h> static const struct pad_conf_entry core_padconf_array[] = { {GPMC_AD0, (IEN | PTD | DIS | M0)}, /* gpmc_ad0 */ @@ -242,4 +243,11 @@ void set_muxconf_regs(void) omap4_do_set_mux(OMAP44XX_CONTROL_PADCONF_WKUP, wkup_padconf_array, ARRAY_SIZE(wkup_padconf_array)); + + /* gpio_182 is used for controlling TPS on 4460 */ + if (omap4_revision() >= OMAP4460_ES1_0) { + writew(M3, OMAP44XX_CONTROL_PADCONF_CORE + FREF_CLK2_OUT); + /* Enable GPIO-1 clocks before TPS initialization */ + omap4_enable_gpio_clocks(); + } } 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 1dc7678771..907198d783 100644 --- a/arch/arm/boards/phycard-a-l1/pca-a-l1.c +++ b/arch/arm/boards/phycard-a-l1/pca-a-l1.c @@ -327,7 +327,7 @@ static struct NS16550_plat serial_plat = { */ static int pcaal1_init_console(void) { - add_ns16550_device(-1, OMAP_UART3_BASE, 1024, IORESOURCE_MEM_8BIT, + add_ns16550_device(DEVICE_ID_DYNAMIC, OMAP_UART3_BASE, 1024, IORESOURCE_MEM_8BIT, &serial_plat); return 0; @@ -391,9 +391,16 @@ struct omap_hsmmc_platform_data pcaal1_hsmmc_plat = { }; #endif +static struct gpmc_nand_platform_data nand_plat = { + .device_width = 16, + .ecc_mode = OMAP_ECC_BCH8_CODE_HW, + .nand_cfg = &omap3_nand_cfg, +}; + static int pcaal1_init_devices(void) { - gpmc_generic_nand_devices_init(0, 16, OMAP_ECC_BCH8_CODE_HW, &omap3_nand_cfg); + omap_add_gpmc_nand_device(&nand_plat); + #ifdef CONFIG_MCI_OMAP_HSMMC add_generic_device("omap-hsmmc", DEVICE_ID_DYNAMIC, NULL, OMAP_MMC1_BASE, SZ_4K, IORESOURCE_MEM, &pcaal1_hsmmc_plat); diff --git a/arch/arm/boards/phycard-a-xl2/Makefile b/arch/arm/boards/phycard-a-xl2/Makefile index 1d23d72ddc..23958c2f8f 100644 --- a/arch/arm/boards/phycard-a-xl2/Makefile +++ b/arch/arm/boards/phycard-a-xl2/Makefile @@ -18,3 +18,4 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA obj-y += pca-a-xl2.o mux.o lowlevel.o +pbl-y += mux.o lowlevel.o diff --git a/arch/arm/boards/phycard-a-xl2/env/bin/nand_bootstrap b/arch/arm/boards/phycard-a-xl2/env/bin/nand_bootstrap index acd00dc904..f8873fabe2 100644 --- a/arch/arm/boards/phycard-a-xl2/env/bin/nand_bootstrap +++ b/arch/arm/boards/phycard-a-xl2/env/bin/nand_bootstrap @@ -4,7 +4,7 @@ echo "copying barebox to nand..." mci0.probe=1 mkdir mnt -mount /dev/disk0.0 fat /mnt +mount /dev/disk0.0 /mnt if [ $? != 0 ]; then echo "failed to mount mmc card" exit 1 diff --git a/arch/arm/boards/phycard-a-xl2/lowlevel.c b/arch/arm/boards/phycard-a-xl2/lowlevel.c index b8de2aad0a..38f80c9733 100644 --- a/arch/arm/boards/phycard-a-xl2/lowlevel.c +++ b/arch/arm/boards/phycard-a-xl2/lowlevel.c @@ -28,6 +28,8 @@ #include <mach/syslib.h> #include <asm/barebox-arm.h> +#define TPS62361_VSEL0_GPIO 7 + void set_muxconf_regs(void); static const struct ddr_regs ddr_regs_mt42L64M64_25_400_mhz = { @@ -46,7 +48,8 @@ static const struct ddr_regs ddr_regs_mt42L64M64_25_400_mhz = { static noinline void pcaaxl2_init_lowlevel(void) { struct dpll_param core = OMAP4_CORE_DPLL_PARAM_19M2_DDR400; - struct dpll_param mpu = OMAP4_MPU_DPLL_PARAM_19M2_MPU1000; + struct dpll_param mpu44xx = OMAP4_MPU_DPLL_PARAM_19M2_MPU1000; + struct dpll_param mpu4460 = OMAP4_MPU_DPLL_PARAM_19M2_MPU920; struct dpll_param iva = OMAP4_IVA_DPLL_PARAM_19M2; struct dpll_param per = OMAP4_PER_DPLL_PARAM_19M2; struct dpll_param abe = OMAP4_ABE_DPLL_PARAM_19M2; @@ -57,12 +60,16 @@ static noinline void pcaaxl2_init_lowlevel(void) omap4_ddr_init(&ddr_regs_mt42L64M64_25_400_mhz, &core); /* Set VCORE1 = 1.3 V, VCORE2 = VCORE3 = 1.21V */ - omap4_scale_vcores(); + omap4_scale_vcores(TPS62361_VSEL0_GPIO); writel(CM_SYS_CLKSEL_19M2, CM_SYS_CLKSEL); /* Configure all DPLL's at 100% OPP */ - omap4_configure_mpu_dpll(&mpu); + if (omap4_revision() < OMAP4460_ES1_0) + omap4_configure_mpu_dpll(&mpu44xx); + else + omap4_configure_mpu_dpll(&mpu4460); + omap4_configure_iva_dpll(&iva); omap4_configure_per_dpll(&per); omap4_configure_abe_dpll(&abe); diff --git a/arch/arm/boards/phycard-a-xl2/mux.c b/arch/arm/boards/phycard-a-xl2/mux.c index 179e6b67ab..dc605e38b4 100644 --- a/arch/arm/boards/phycard-a-xl2/mux.c +++ b/arch/arm/boards/phycard-a-xl2/mux.c @@ -3,6 +3,7 @@ #include <io.h> #include <mach/omap4-silicon.h> #include <mach/omap4-mux.h> +#include <mach/omap4-clock.h> static const struct pad_conf_entry core_padconf_array[] = { {GPMC_AD0, (IEN | PTD | DIS | M0)}, /* gpmc_ad0 */ @@ -242,4 +243,11 @@ void set_muxconf_regs(void) omap4_do_set_mux(OMAP44XX_CONTROL_PADCONF_WKUP, wkup_padconf_array, ARRAY_SIZE(wkup_padconf_array)); + + /* gpio_wk7 is used for controlling TPS on 4460 */ + if (omap4_revision() >= OMAP4460_ES1_0) { + writew(M3, OMAP44XX_CONTROL_PADCONF_WKUP + PAD1_FREF_CLK4_REQ); + /* Enable GPIO-1 clocks before TPS initialization */ + omap4_enable_gpio1_wup_clocks(); + } } diff --git a/arch/arm/boards/phycard-a-xl2/pca-a-xl2.c b/arch/arm/boards/phycard-a-xl2/pca-a-xl2.c index 128cb8fd28..4fec0f0e41 100644 --- a/arch/arm/boards/phycard-a-xl2/pca-a-xl2.c +++ b/arch/arm/boards/phycard-a-xl2/pca-a-xl2.c @@ -51,7 +51,7 @@ static struct NS16550_plat serial_plat = { static int pcaaxl2_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, OMAP44XX_UART3_BASE, 1024, + add_ns16550_device(DEVICE_ID_DYNAMIC, OMAP44XX_UART3_BASE, 1024, IORESOURCE_MEM_8BIT, &serial_plat); return 0; @@ -85,7 +85,7 @@ static void pcaaxl2_network_init(void) { gpmc_cs_config(5, &net_cfg); - add_ks8851_device(-1, net_cfg.base, net_cfg.base + 2, + add_ks8851_device(DEVICE_ID_DYNAMIC, net_cfg.base, net_cfg.base + 2, IORESOURCE_MEM_16BIT, NULL); } @@ -104,6 +104,12 @@ static struct omap_hsmmc_platform_data mmc_device = { #define OMAP4_MMC1_PBIASLITE_PWRDNZ (1<<22) #define OMAP4_MMC1_PWRDNZ (1<<26) +static struct gpmc_nand_platform_data nand_plat = { + .device_width = 16, + .ecc_mode = OMAP_ECC_BCH8_CODE_HW, + .nand_cfg = &omap4_nand_cfg, +}; + static int pcaaxl2_devices_init(void) { u32 value; @@ -124,8 +130,7 @@ static int pcaaxl2_devices_init(void) pcaaxl2_network_init(); - gpmc_generic_nand_devices_init(0, 16, - OMAP_ECC_BCH8_CODE_HW, &omap4_nand_cfg); + omap_add_gpmc_nand_device(&nand_plat); #ifdef CONFIG_PARTITION devfs_add_partition("nand0", 0x00000, SZ_128K, diff --git a/arch/arm/boards/phycard-i.MX27/Makefile b/arch/arm/boards/phycard-i.MX27/Makefile index fd52350fbb..60253e55b9 100644 --- a/arch/arm/boards/phycard-i.MX27/Makefile +++ b/arch/arm/boards/phycard-i.MX27/Makefile @@ -1,3 +1,4 @@ obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += pca100.o diff --git a/arch/arm/boards/phycard-i.MX27/pca100.c b/arch/arm/boards/phycard-i.MX27/pca100.c index 126f9efbac..614bfc65eb 100644 --- a/arch/arm/boards/phycard-i.MX27/pca100.c +++ b/arch/arm/boards/phycard-i.MX27/pca100.c @@ -141,9 +141,9 @@ static void pca100_usb_register(void) mdelay(10); ulpi_setup((void *)(IMX_OTG_BASE + 0x170), 1); - add_generic_usb_ehci_device(-1, IMX_OTG_BASE, NULL); + add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, IMX_OTG_BASE, NULL); ulpi_setup((void *)(IMX_OTG_BASE + 0x570), 1); - add_generic_usb_ehci_device(-1, IMX_OTG_BASE + 0x400, NULL); + add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, IMX_OTG_BASE + 0x400, NULL); } #endif diff --git a/arch/arm/boards/qil-a9260/init.c b/arch/arm/boards/qil-a9260/init.c index 305d733a74..6b1ed85609 100644 --- a/arch/arm/boards/qil-a9260/init.c +++ b/arch/arm/boards/qil-a9260/init.c @@ -150,11 +150,7 @@ static void __init ek_add_led(void) static int qil_a9260_mem_init(void) { -#ifdef CONFIG_AT91_HAVE_SRAM_128M - at91_add_device_sdram(128 * 1024 * 1024); -#else - at91_add_device_sdram(64 * 1024 * 1024); -#endif + at91_add_device_sdram(0); return 0; } @@ -196,11 +192,17 @@ device_initcall(qil_a9260_devices_init); static int qil_a9260_console_init(void) { at91_register_uart(0, 0); + at91_set_A_periph(AT91_PIN_PB14, 1); /* Enable pull-up on DRXD */ + at91_register_uart(1, ATMEL_UART_CTS | ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD | ATMEL_UART_RI); + at91_register_uart(2, ATMEL_UART_CTS | ATMEL_UART_RTS); + at91_set_A_periph(AT91_PIN_PB7, 1); /* Enable pull-up on RXD1 */ + at91_register_uart(3, ATMEL_UART_CTS | ATMEL_UART_RTS); + at91_set_A_periph(AT91_PIN_PB9, 1); /* Enable pull-up on RXD2 */ return 0; } diff --git a/arch/arm/boards/qil-a9260/qil-a9260.dox b/arch/arm/boards/qil-a9260/qil-a9260.dox new file mode 100644 index 0000000000..da5c197b34 --- /dev/null +++ b/arch/arm/boards/qil-a9260/qil-a9260.dox @@ -0,0 +1,22 @@ +/** +@page qil-a9260 Calao-systems QIL-A9260 + +@section qil-a9260 The CPU module + +http://www.calao-systems.com + +This CPU module is based on an Atmel AT91SAM9260 CPU. The card is shipped with: + +- 64MiB or 128MiB SDRAM (3.3V) +- 256MiB NAND type Flash Memory (3.3V) +- 64Kib SPI EEPROM +- RMII 10/100 ethernet PHY +- Real Time Clock +- micro SD socket + +@section mob-qil-a9xxx Supported development board + +Supported development board is: +- MOB-QIL-A9xxx + +*/ diff --git a/arch/arm/boards/scb9328/Makefile b/arch/arm/boards/scb9328/Makefile index db6fd7ec37..69d3970223 100644 --- a/arch/arm/boards/scb9328/Makefile +++ b/arch/arm/boards/scb9328/Makefile @@ -1,3 +1,4 @@ obj-y += lowlevel_init.o +pbl-y += lowlevel_init.o obj-y += scb9328.o diff --git a/arch/arm/boards/scb9328/scb9328.c b/arch/arm/boards/scb9328/scb9328.c index 9a342a8170..671adbf274 100644 --- a/arch/arm/boards/scb9328/scb9328.c +++ b/arch/arm/boards/scb9328/scb9328.c @@ -88,8 +88,8 @@ static int scb9328_devices_init(void) CS5U = 0x00008400; CS5L = 0x00000D03; - add_cfi_flash_device(-1, 0x10000000, 16 * 1024 * 1024, 0); - add_dm9000_device(-1, 0x16000000, 0x16000004, + add_cfi_flash_device(DEVICE_ID_DYNAMIC, 0x10000000, 16 * 1024 * 1024, 0); + add_dm9000_device(DEVICE_ID_DYNAMIC, 0x16000000, 0x16000004, IORESOURCE_MEM_16BIT, &dm9000_data); devfs_add_partition("nor0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self0"); diff --git a/arch/arm/boards/tny-a926x/init.c b/arch/arm/boards/tny-a926x/init.c index 2cb7da7cff..5538a44a67 100644 --- a/arch/arm/boards/tny-a926x/init.c +++ b/arch/arm/boards/tny-a926x/init.c @@ -89,7 +89,7 @@ static struct sam9_smc_config tny_a9g20_nand_smc_config = { .ncs_read_pulse = 4, .nrd_pulse = 4, .ncs_write_pulse = 4, - .nwe_pulse = 2, + .nwe_pulse = 4, .read_cycle = 7, .write_cycle = 7, @@ -171,7 +171,7 @@ static void __init ek_add_device_udc(void) static int tny_a9260_mem_init(void) { - at91_add_device_sdram(64 * 1024 * 1024); + at91_add_device_sdram(0); return 0; } diff --git a/arch/arm/boards/tny-a926x/tny-a9263.dox b/arch/arm/boards/tny-a926x/tny-a9263.dox new file mode 100644 index 0000000000..68fcdd109c --- /dev/null +++ b/arch/arm/boards/tny-a926x/tny-a9263.dox @@ -0,0 +1,33 @@ +/** +@page tny-a9263 Calao-systems TNY-A9263 + +@section tny-a9263 The CPU module + +http://www.calao-systems.com + +This CPU module is based on an Atmel AT91SAM9263 CPU. The module is shipped with: + +- 64MiB SDRAM (3.3V) +- 256MiB NAND type Flash Memory (3.3V) +- USB device port +- Top expansion connector for daughter boards (GPS, WIFI/BT, GPRS, 3G, ZigBee, MBUS, ...) +- Bottom expansion connector for development boards + +@section mob-tny-a9xxx-md2 Supported development board + +Supported development board is: +- MOB-TNY-A9xxx-MD2 + +@section tny-db-boards Supported daughter boards + +Supported daughter boards are: +- DAB-GPI2-CXX +- DAB-GPS +- DAB-GPRS +- DAB-HSDPA +- DAB-WLAN-BT +- DAB-ZIGBEE +- DAB-MBUS +- DAB-KNX-RF + +*/ diff --git a/arch/arm/boards/tny-a926x/tny-a9g20-lpw.dox b/arch/arm/boards/tny-a926x/tny-a9g20-lpw.dox new file mode 100644 index 0000000000..e0021070b3 --- /dev/null +++ b/arch/arm/boards/tny-a926x/tny-a9g20-lpw.dox @@ -0,0 +1,37 @@ +/** +@page tny-a9g20-lpw Calao-systems TNY-A9G20-LPW + +@section tny-a9g20-lpw The CPU module + +http://www.calao-systems.com + +This CPU module is based on an Atmel AT91SAM9G20 CPU. The module is shipped with: + +- 64MiB Low Power SDRAM (1.8V) +- 256MiB NAND type Flash Memory (1.8V) +- Real Time Clock (I2C) +- Micro SD socket +- USB device port +- JTAG connector +- Top expansion connector for daughter boards (GPS, WIFI/BT, GPRS, 3G, ZigBee, MBUS, ...) +- Bottom expansion connector for development boards + +@section mob-tny-a9xxx-md2 Supported development board + +Supported development board is: +- MOB-TNY-A9xxx-MD2 + +@section tny-db-boards Supported daughter boards + +Supported daughter boards are: +- DAB-GPI2-CXX +- DAB-GPS +- DAB-GPRS +- DAB-HSDPA +- DAB-WLAN-BT +- DAB-ZIGBEE +- DAB-MBUS +- DAB-KNX-RF + + +*/ diff --git a/arch/arm/boards/toshiba-ac100/serial.c b/arch/arm/boards/toshiba-ac100/serial.c index 2ed0e3901c..39d2658a82 100644 --- a/arch/arm/boards/toshiba-ac100/serial.c +++ b/arch/arm/boards/toshiba-ac100/serial.c @@ -35,7 +35,7 @@ static struct NS16550_plat serial_plat = { static int ac100_serial_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, TEGRA_UARTA_BASE, 8 << serial_plat.shift, + add_ns16550_device(DEVICE_ID_DYNAMIC, TEGRA_UARTA_BASE, 8 << serial_plat.shift, IORESOURCE_MEM_8BIT, &serial_plat); return 0; diff --git a/arch/arm/boards/tqma53/Makefile b/arch/arm/boards/tqma53/Makefile index b56ce7f50d..d08bb68a5c 100644 --- a/arch/arm/boards/tqma53/Makefile +++ b/arch/arm/boards/tqma53/Makefile @@ -1,2 +1,3 @@ obj-y += board.o obj-y += flash_header.o +pbl-y += flash_header.o diff --git a/arch/arm/boards/usb-a926x/init.c b/arch/arm/boards/usb-a926x/init.c index 824a38a94d..00a215d140 100644 --- a/arch/arm/boards/usb-a926x/init.c +++ b/arch/arm/boards/usb-a926x/init.c @@ -90,7 +90,7 @@ static struct sam9_smc_config usb_a9g20_nand_smc_config = { .ncs_read_pulse = 4, .nrd_pulse = 4, .ncs_write_pulse = 4, - .nwe_pulse = 2, + .nwe_pulse = 4, .read_cycle = 7, .write_cycle = 7, @@ -203,11 +203,7 @@ static void __init ek_add_led(void) static int usb_a9260_mem_init(void) { -#ifdef CONFIG_AT91_HAVE_SRAM_128M - at91_add_device_sdram(128 * 1024 * 1024); -#else - at91_add_device_sdram(64 * 1024 * 1024); -#endif + at91_add_device_sdram(0); return 0; } @@ -294,7 +290,7 @@ static void usb_a9260_keyboard_device_dab_mmx(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 usb_a9260_keyboard_device_dab_mmx(void) {} diff --git a/arch/arm/boards/usb-a926x/usb-a9263.dox b/arch/arm/boards/usb-a926x/usb-a9263.dox new file mode 100644 index 0000000000..380a8e2d3d --- /dev/null +++ b/arch/arm/boards/usb-a926x/usb-a9263.dox @@ -0,0 +1,30 @@ +/** +@page usb-a9263 Calao-systems USB-A9263 + +@section usb-a9263 The CPU card + +http://www.calao-systems.com + +This CPU card is based on an Atmel AT91SAM9263 CPU. The card is shipped with: + +- 64MiB or 128MiB SDRAM (3.3V) +- 256MiB NAND type Flash Memory (3.3V) +- Ethernet 10/100M +- USB Host port 2.0 (FS) +- USB device port (FS) +- Top expansion connector for expansion boards (GPS, WIFI/BT, GPRS, 3G, ZigBee, MBUS, ...) +- Bottom expansion connector for development boards + +@section usb-db-boards Supported daughter boards + +Supported daughter boards are: +- DAB-GPI2-CXX +- DAB-GPS +- DAB-GPRS +- DAB-HSDPA +- DAB-WLAN-BT +- DAB-ZIGBEE +- DAB-MBUS +- DAB-KNX-RF + +*/ diff --git a/arch/arm/boards/usb-a926x/usb-a9g20-lpw.dox b/arch/arm/boards/usb-a926x/usb-a9g20-lpw.dox new file mode 100644 index 0000000000..024a3cedda --- /dev/null +++ b/arch/arm/boards/usb-a926x/usb-a9g20-lpw.dox @@ -0,0 +1,33 @@ +/** +@page usb-a9g20-lpw Calao-systems USB-A9G20-LPW + +@section usb-a9g20-lpw The CPU card + +http://www.calao-systems.com + +This CPU card is based on an Atmel AT91SAM9G20 CPU. The card is shipped with: + +- 64MiB or 128MiB SDRAM (1.8V) +- 256MiB NAND type Flash Memory (1.8V) +- Ethernet 10/100M +- USB Host port 2.0 (FS) +- USB device port (FS) +- Micro SD socket +- JTAG connector +- RTC with battery backup +- Top expansion connector for daughter boards (GPS, WIFI/BT, GPRS, 3G, ZigBee, MBUS, ...) +- Bottom expansion connector for development boards + +@section usb-db-boards Supported daughter boards + +Supported daughter boards are: +- DAB-GPI2-CXX +- DAB-GPS +- DAB-GPRS +- DAB-HSDPA +- DAB-WLAN-BT +- DAB-ZIGBEE +- DAB-MBUS +- DAB-KNX-RF + +*/ diff --git a/arch/arm/boards/versatile/versatilepb.c b/arch/arm/boards/versatile/versatilepb.c index b95e605ab2..b834bbbda2 100644 --- a/arch/arm/boards/versatile/versatilepb.c +++ b/arch/arm/boards/versatile/versatilepb.c @@ -50,7 +50,7 @@ mem_initcall(vpb_mem_init); static int vpb_devices_init(void) { - add_cfi_flash_device(-1, VERSATILE_FLASH_BASE, VERSATILE_FLASH_SIZE, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, VERSATILE_FLASH_BASE, VERSATILE_FLASH_SIZE, 0); devfs_add_partition("nor0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self"); devfs_add_partition("nor0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env0"); diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 93a34a9ff1..0ecc72eea7 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -1,7 +1,7 @@ obj-y += cpu.o obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o obj-$(CONFIG_ARM_EXCEPTIONS) += interrupts.o -obj-y += start.o +obj-y += start.o start-reset.o # # Any variants can be called as start-armxyz.S @@ -10,8 +10,13 @@ obj-$(CONFIG_CMD_ARM_CPUINFO) += cpuinfo.o obj-$(CONFIG_CMD_ARM_MMUINFO) += mmuinfo.o obj-$(CONFIG_MMU) += mmu.o obj-$(CONFIG_CPU_32v4T) += cache-armv4.o +pbl-$(CONFIG_CPU_32v4T) += cache-armv4.o obj-$(CONFIG_CPU_32v5) += cache-armv5.o +pbl-$(CONFIG_CPU_32v5) += cache-armv5.o obj-$(CONFIG_CPU_32v6) += cache-armv6.o +pbl-$(CONFIG_CPU_32v6) += cache-armv6.o obj-$(CONFIG_CPU_32v7) += cache-armv7.o +pbl-$(CONFIG_CPU_32v7) += cache-armv7.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o +pbl-y += start-pbl.o start-reset.o diff --git a/arch/arm/cpu/cache-armv4.S b/arch/arm/cpu/cache-armv4.S index 2231eee06b..22fab1455c 100644 --- a/arch/arm/cpu/cache-armv4.S +++ b/arch/arm/cpu/cache-armv4.S @@ -46,6 +46,7 @@ ENDPROC(__mmu_cache_off) .section .text.__mmu_cache_flush ENTRY(__mmu_cache_flush) + stmfd sp!, {r6, r11, lr} mrc p15, 0, r6, c0, c0 @ get processor ID mov r2, #64*1024 @ default: 32K dcache size (*2) mov r11, #32 @ default: 32 byte line size @@ -74,7 +75,7 @@ no_cache_id: mcr p15, 0, r1, c7, c5, 0 @ flush I cache mcr p15, 0, r1, c7, c6, 0 @ flush D cache mcr p15, 0, r1, c7, c10, 4 @ drain WB - mov pc, lr + ldmfd sp!, {r6, r11, pc} ENDPROC(__mmu_cache_flush) /* diff --git a/arch/arm/cpu/cache-armv7.S b/arch/arm/cpu/cache-armv7.S index 9bd74254f3..2eba959672 100644 --- a/arch/arm/cpu/cache-armv7.S +++ b/arch/arm/cpu/cache-armv7.S @@ -3,6 +3,7 @@ .section .text.__mmu_cache_on ENTRY(__mmu_cache_on) + stmfd sp!, {r11, lr} mov r12, lr #ifdef CONFIG_MMU mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0 @@ -28,7 +29,7 @@ ENTRY(__mmu_cache_on) mrc p15, 0, r0, c1, c0, 0 @ and read it back mov r0, #0 mcr p15, 0, r0, c7, c5, 4 @ ISB - mov pc, r12 + ldmfd sp!, {r11, pc} ENDPROC(__mmu_cache_on) .section .text.__mmu_cache_off @@ -54,6 +55,7 @@ ENDPROC(__mmu_cache_off) .section .text.__mmu_cache_flush ENTRY(__mmu_cache_flush) + stmfd sp!, {r10, lr} mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1 tst r10, #0xf << 16 @ hierarchical cache (ARMv7) mov r10, #0 @@ -111,7 +113,7 @@ iflush: mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB mcr p15, 0, r10, c7, c10, 4 @ DSB mcr p15, 0, r10, c7, c5, 4 @ ISB - mov pc, lr + ldmfd sp!, {r10, pc} ENDPROC(__mmu_cache_flush) /* diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index 607f3572db..dad8092e9f 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -8,6 +8,8 @@ #include <asm/system.h> #include <memory.h> +#include "mmu.h" + static unsigned long *ttb; static void create_sections(unsigned long virt, unsigned long phys, int size_m, @@ -21,12 +23,7 @@ static void create_sections(unsigned long virt, unsigned long phys, int size_m, for (i = size_m; i > 0; i--, virt++, phys++) ttb[virt] = (phys << 20) | flags; - asm volatile ( - "bl __mmu_cache_flush;" - : - : - : "r0", "r1", "r2", "r3", "r6", "r10", "r12", "lr", "cc", "memory" - ); + __mmu_cache_flush(); } /* @@ -255,12 +252,7 @@ static int mmu_init(void) create_sections(bank->start, bank->start, bank->size >> 20, PMD_SECT_DEF_CACHED); - asm volatile ( - "bl __mmu_cache_on;" - : - : - : "r0", "r1", "r2", "r3", "r6", "r10", "r12", "lr", "cc", "memory" - ); + __mmu_cache_on(); /* * Now that we have the MMU and caches on remap sdram again using @@ -284,13 +276,8 @@ void mmu_disable(void) if (outer_cache.disable) outer_cache.disable(); - asm volatile ( - "bl __mmu_cache_flush;" - "bl __mmu_cache_off;" - : - : - : "r0", "r1", "r2", "r3", "r6", "r10", "r12", "lr", "cc", "memory" - ); + __mmu_cache_flush(); + __mmu_cache_off(); } #define PAGE_ALIGN(s) ((s) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); diff --git a/arch/arm/cpu/mmu.h b/arch/arm/cpu/mmu.h new file mode 100644 index 0000000000..618968bc82 --- /dev/null +++ b/arch/arm/cpu/mmu.h @@ -0,0 +1,8 @@ +#ifndef __ARM_MMU_H +#define __ARM_MMU_H + +void __mmu_cache_on(void); +void __mmu_cache_off(void); +void __mmu_cache_flush(void); + +#endif /* __ARM_MMU_H */ diff --git a/arch/arm/cpu/start-pbl.c b/arch/arm/cpu/start-pbl.c new file mode 100644 index 0000000000..932a3da9e2 --- /dev/null +++ b/arch/arm/cpu/start-pbl.c @@ -0,0 +1,213 @@ +/* + * start-pbl.c + * + * Copyright (c) 2010-2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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 version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <init.h> +#include <sizes.h> +#include <asm/barebox-arm.h> +#include <asm/barebox-arm-head.h> +#include <asm-generic/memory_layout.h> +#include <asm/sections.h> +#include <asm/pgtable.h> +#include <asm/cache.h> + +#include "mmu.h" + +unsigned long free_mem_ptr; +unsigned long free_mem_end_ptr; + +void __naked __section(.text_head_entry) pbl_start(void) +{ + barebox_arm_head(); +} + +extern void *input_data; +extern void *input_data_end; + +#define STATIC static + +#ifdef CONFIG_IMAGE_COMPRESSION_LZO +#include "../../../lib/decompress_unlzo.c" +#endif + +#ifdef CONFIG_IMAGE_COMPRESSION_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif + +static unsigned long *ttb; + +static void create_sections(unsigned long addr, int size, unsigned int flags) +{ + int i; + + addr >>= 20; + size >>= 20; + + for (i = size; i > 0; i--, addr++) + ttb[addr] = (addr << 20) | flags; +} + +static void map_cachable(unsigned long start, unsigned long size) +{ + start &= ~(SZ_1M - 1); + size = (size + (SZ_1M - 1)) & ~(SZ_1M - 1); + + create_sections(start, size, PMD_SECT_AP_WRITE | + PMD_SECT_AP_READ | PMD_TYPE_SECT | PMD_SECT_WB); +} + +static void mmu_enable(unsigned long compressed_start, unsigned int len) +{ + int i; + + /* Set the ttb register */ + asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb) /*:*/); + + /* Set the Domain Access Control Register */ + i = 0x3; + asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/); + + create_sections(0, 4096, PMD_SECT_AP_WRITE | + PMD_SECT_AP_READ | PMD_TYPE_SECT); + /* + * Setup all regions we need cacheable, namely: + * - the stack + * - the decompressor code + * - the compressed image + * - the uncompressed image + * - the early malloc space + */ + map_cachable(STACK_BASE, STACK_SIZE); + map_cachable((unsigned long)&_text, + (unsigned long)&_end - (unsigned long)&_text); + map_cachable((unsigned long)compressed_start, len); + map_cachable(TEXT_BASE, len * 4); + map_cachable(free_mem_ptr, free_mem_end_ptr - free_mem_ptr); + + __mmu_cache_on(); +} + +static void mmu_disable(void) +{ + __mmu_cache_flush(); + __mmu_cache_off(); +} + +static void barebox_uncompress(void *compressed_start, unsigned int len) +{ + void (*barebox)(void); + int use_mmu = IS_ENABLED(CONFIG_MMU); + + /* set 128 KiB at the end of the MALLOC_BASE for early malloc */ + free_mem_ptr = MALLOC_BASE + MALLOC_SIZE - SZ_128K; + free_mem_end_ptr = free_mem_ptr + SZ_128K; + + ttb = (void *)((free_mem_ptr - 0x4000) & ~0x3fff); + + if (use_mmu) + mmu_enable((unsigned long)compressed_start, len); + + if (IS_ENABLED(CONFIG_THUMB2_BAREBOX)) + barebox = (void *)(TEXT_BASE + 1); + else + barebox = (void *)TEXT_BASE; + + decompress((void *)compressed_start, + len, + NULL, NULL, + (void *)TEXT_BASE, NULL, NULL); + + if (use_mmu) + mmu_disable(); + + flush_icache(); + + barebox(); +} + +/* + * Board code can jump here by either returning from board_init_lowlevel + * or by calling this function directly. + */ +void __naked __section(.text_ll_return) board_init_lowlevel_return(void) +{ + uint32_t r, addr, offset; + uint32_t pg_start, pg_end, pg_len; + + /* + * Get runtime address of this function. Do not + * put any code above this. + */ + __asm__ __volatile__("1: adr %0, 1b":"=r"(addr)); + + /* Setup the stack */ + r = STACK_BASE + STACK_SIZE - 16; + __asm__ __volatile__("mov sp, %0" : : "r"(r)); + + /* Get offset between linked address and runtime address */ + offset = (uint32_t)__ll_return - addr; + + pg_start = (uint32_t)&input_data - offset; + pg_end = (uint32_t)&input_data_end - offset; + pg_len = pg_end - pg_start; + + if (IS_ENABLED(CONFIG_PBL_FORCE_PIGGYDATA_COPY)) + goto copy_piggy_link; + + /* + * Check if the piggydata binary will be overwritten + * by the uncompressed binary or by the pbl relocation + */ + if (!offset || + !((pg_start >= TEXT_BASE && pg_start < TEXT_BASE + pg_len * 4) || + ((uint32_t)_text >= pg_start && (uint32_t)_text <= pg_end))) + goto copy_link; + +copy_piggy_link: + /* + * copy piggydata binary to its link address + */ + memcpy(&input_data, (void *)pg_start, pg_len); + pg_start = (uint32_t)&input_data; + +copy_link: + /* relocate to link address if necessary */ + if (offset) + memcpy((void *)_text, (void *)(_text - offset), + __bss_start - _text); + + /* clear bss */ + memset(__bss_start, 0, __bss_stop - __bss_start); + + flush_icache(); + + r = (unsigned int)&barebox_uncompress; + /* call barebox_uncompress with its absolute address */ + __asm__ __volatile__( + "mov r0, %1\n" + "mov r1, %2\n" + "mov pc, %0\n" + : + : "r"(r), "r"(pg_start), "r"(pg_len) + : "r0", "r1"); +} diff --git a/arch/arm/cpu/start-reset.c b/arch/arm/cpu/start-reset.c new file mode 100644 index 0000000000..e0df676274 --- /dev/null +++ b/arch/arm/cpu/start-reset.c @@ -0,0 +1,67 @@ +/* + * start-reset.c + * + * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <init.h> +#include <asm/system.h> +#include <asm/barebox-arm.h> +#include <asm/sections.h> + +/* + * The actual reset vector. This code is position independent and usually + * does not run at the address it's linked at. + */ +void __naked __bare_init reset(void) +{ + uint32_t r; + + /* set the cpu to SVC32 mode */ + __asm__ __volatile__("mrs %0, cpsr":"=r"(r)); + r &= ~0x1f; + r |= 0xd3; + __asm__ __volatile__("msr cpsr, %0" : : "r"(r)); + +#ifdef CONFIG_ARCH_HAS_LOWLEVEL_INIT + arch_init_lowlevel(); +#endif + + /* disable MMU stuff and caches */ + r = get_cr(); + r &= ~(CR_M | CR_C | CR_B | CR_S | CR_R | CR_V); + r |= CR_I; + +#if __LINUX_ARM_ARCH__ >= 6 + r |= CR_U; +#else + r |= CR_A; +#endif + +#ifdef __ARMEB__ + r |= CR_B; +#endif + set_cr(r); + +#ifdef CONFIG_MACH_DO_LOWLEVEL_INIT + board_init_lowlevel(); +#endif + board_init_lowlevel_return(); +} diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index 112403e33e..07e7dfe822 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -24,53 +24,32 @@ #include <init.h> #include <asm/barebox-arm.h> #include <asm/barebox-arm-head.h> -#include <asm/system.h> #include <asm-generic/memory_layout.h> #include <asm/sections.h> +#include <asm/cache.h> -void __naked __section(.text_entry) start(void) -{ - barebox_arm_head(); -} - +#ifdef CONFIG_PBL_IMAGE /* - * The actual reset vector. This code is position independent and usually - * does not run at the address it's linked at. + * First function in the pbl image. We get here from + * the pbl. */ -void __naked __bare_init reset(void) +void __naked __section(.text_entry) start(void) { - uint32_t r; + u32 r; - /* set the cpu to SVC32 mode */ - __asm__ __volatile__("mrs %0, cpsr":"=r"(r)); - r &= ~0x1f; - r |= 0xd3; - __asm__ __volatile__("msr cpsr, %0" : : "r"(r)); - -#ifdef CONFIG_ARCH_HAS_LOWLEVEL_INIT - arch_init_lowlevel(); -#endif - - /* disable MMU stuff and caches */ - r = get_cr(); - r &= ~(CR_M | CR_C | CR_B | CR_S | CR_R | CR_V); - r |= CR_I; + /* Setup the stack */ + r = STACK_BASE + STACK_SIZE - 16; + __asm__ __volatile__("mov sp, %0" : : "r"(r)); + /* clear bss */ + memset(__bss_start, 0, __bss_stop - __bss_start); -#if __LINUX_ARM_ARCH__ >= 6 - r |= CR_U; + start_barebox(); +} #else - r |= CR_A; -#endif - -#ifdef __ARMEB__ - r |= CR_B; -#endif - set_cr(r); -#ifdef CONFIG_MACH_DO_LOWLEVEL_INIT - board_init_lowlevel(); -#endif - board_init_lowlevel_return(); +void __naked __section(.text_entry) start(void) +{ + barebox_arm_head(); } /* @@ -102,11 +81,10 @@ void __naked __section(.text_ll_return) board_init_lowlevel_return(void) /* clear bss */ memset(__bss_start, 0, __bss_stop - __bss_start); - /* flush I-cache before jumping to the copied binary */ - __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); + flush_icache(); /* call start_barebox with its absolute address */ r = (unsigned int)&start_barebox; __asm__ __volatile__("mov pc, %0" : : "r"(r)); } - +#endif diff --git a/arch/arm/include/asm/barebox-arm-head.h b/arch/arm/include/asm/barebox-arm-head.h index 2c250e948e..0b1d78644d 100644 --- a/arch/arm/include/asm/barebox-arm-head.h +++ b/arch/arm/include/asm/barebox-arm-head.h @@ -1,6 +1,9 @@ #ifndef __ASM_ARM_HEAD_H #define __ASM_ARM_HEAD_H +#ifdef CONFIG_HAVE_MACH_ARM_HEAD +#include <mach/barebox-arm-head.h> +#else static inline void barebox_arm_head(void) { __asm__ __volatile__ ( @@ -31,5 +34,6 @@ static inline void barebox_arm_head(void) ".word _barebox_image_size\n" /* image size to copy */ ); } +#endif #endif /* __ASM_ARM_HEAD_H */ diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h new file mode 100644 index 0000000000..ff797493f7 --- /dev/null +++ b/arch/arm/include/asm/cache.h @@ -0,0 +1,9 @@ +#ifndef __ASM_CACHE_H +#define __ASM_CACHE_H + +static inline void flush_icache(void) +{ + asm volatile("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); +} + +#endif diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 1eaf474911..9d0ff7a856 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -21,3 +21,7 @@ obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS) += memset.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_MODULES) += module.o extra-y += barebox.lds + +pbl-y += lib1funcs.o +pbl-y += ashldi3.o +pbl-y += div0.o diff --git a/arch/arm/lib/barebox.lds.S b/arch/arm/lib/barebox.lds.S index e0bae70f4f..a69013f7f5 100644 --- a/arch/arm/lib/barebox.lds.S +++ b/arch/arm/lib/barebox.lds.S @@ -31,8 +31,9 @@ SECTIONS { . = TEXT_BASE; +#ifndef CONFIG_PBL_IMAGE PRE_IMAGE - +#endif . = ALIGN(4); .text : { diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 491c45446c..3ade725778 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -4,6 +4,8 @@ lowlevel_init-y = at91sam926x_lowlevel_init.o lowlevel_init-$(CONFIG_ARCH_AT91RM9200) = at91rm9200_lowlevel_init.o obj-$(CONFIG_MACH_DO_LOWLEVEL_INIT) += $(lowlevel_init-y) +pbl-$(CONFIG_MACH_DO_LOWLEVEL_INIT) += $(lowlevel_init-y) + obj-$(CONFIG_AT91SAM9_RESET) += at91sam9_reset.o obj-$(CONFIG_AT91SAM9G45_RESET) += at91sam9g45_reset.o diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index b56ca14d1d..9c9534eccf 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -16,6 +16,7 @@ #include <mach/board.h> #include <mach/at91_pmc.h> #include <mach/at91sam9260_matrix.h> +#include <mach/at91sam9_sdramc.h> #include <mach/gpio.h> #include <mach/io.h> #include <mach/cpu.h> @@ -24,6 +25,9 @@ void at91_add_device_sdram(u32 size) { + if (!size) + size = at91_get_sdram_size(); + arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size); if (cpu_is_at91sam9g20()) { add_mem_device("sram0", AT91SAM9G20_SRAM_BASE, diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index a109804139..0091e2dbe9 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -15,6 +15,7 @@ #include <asm/hardware.h> #include <mach/at91_pmc.h> #include <mach/at91sam9261_matrix.h> +#include <mach/at91sam9_sdramc.h> #include <mach/board.h> #include <mach/gpio.h> #include <mach/io.h> @@ -24,6 +25,9 @@ void at91_add_device_sdram(u32 size) { + if (!size) + size = at91_get_sdram_size(); + arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size); if (cpu_is_at91sam9g10()) add_mem_device("sram0", AT91SAM9G10_SRAM_BASE, diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 7f916d21a4..e6864802b7 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -15,6 +15,7 @@ #include <asm/hardware.h> #include <mach/at91_pmc.h> #include <mach/at91sam9263_matrix.h> +#include <mach/at91sam9_sdramc.h> #include <mach/board.h> #include <mach/gpio.h> #include <mach/io.h> @@ -23,6 +24,9 @@ void at91_add_device_sdram(u32 size) { + if (!size) + size = at91_get_sdram_size(); + arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size); add_mem_device("sram0", AT91SAM9263_SRAM0_BASE, AT91SAM9263_SRAM0_SIZE, IORESOURCE_MEM_WRITEABLE); diff --git a/arch/arm/mach-at91/include/mach/at91sam9_sdramc.h b/arch/arm/mach-at91/include/mach/at91sam9_sdramc.h index 5af2b54b12..1ab61e918b 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9_sdramc.h +++ b/arch/arm/mach-at91/include/mach/at91sam9_sdramc.h @@ -83,5 +83,33 @@ #define AT91_SDRAMC_MD_SDRAM 0 #define AT91_SDRAMC_MD_LOW_POWER_SDRAM 1 +#ifndef __ASSEMBLY__ +#include <mach/io.h> +static inline u32 at91_get_sdram_size(void) +{ + u32 val; + u32 size; + + val = at91_sys_read(AT91_SDRAMC_CR); + + /* Formula: + * size = bank << (col + row + 1); + * if (bandwidth == 32 bits) + * size <<= 1; + */ + size = 1; + /* COL */ + size += (val & AT91_SDRAMC_NC) + 8; + /* ROW */ + size += ((val & AT91_SDRAMC_NR) >> 2) + 11; + /* BANK */ + size = ((val & AT91_SDRAMC_NB) ? 4 : 2) << size; + /* bandwidth */ + if (!(val & AT91_SDRAMC_DBW)) + size <<= 1; + + return size; +} +#endif #endif diff --git a/arch/arm/mach-at91/include/mach/barebox-arm-head.h b/arch/arm/mach-at91/include/mach/barebox-arm-head.h new file mode 100644 index 0000000000..a9c8dd44a7 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/barebox-arm-head.h @@ -0,0 +1,33 @@ +#ifndef __MACH_ARM_HEAD_H +#define __MACH_ARM_HEAD_H + +#ifdef CONFIG_SHELL_NONE +#define AT91_EXV6 ".word _barebox_image_size\n" +#else +#define AT91_EXV6 ".word _barebox_bare_init_size\n" +#endif + +static inline void barebox_arm_head(void) +{ + __asm__ __volatile__ ( +#ifdef CONFIG_THUMB2_BAREBOX +#error Thumb2 is not supported +#else + "b reset\n" + "1: b 1b\n" + "1: b 1b\n" + "1: b 1b\n" + "1: b 1b\n" + AT91_EXV6 /* image size to load by the bootrom */ + "1: b 1b\n" + "1: b 1b\n" +#endif + ".asciz \"barebox\"\n" + ".word _text\n" /* text base. If copied there, + * barebox can skip relocation + */ + ".word _barebox_image_size\n" /* image size to copy */ + ); +} + +#endif /* __ASM_ARM_HEAD_H */ diff --git a/arch/arm/mach-at91/include/mach/debug_ll.h b/arch/arm/mach-at91/include/mach/debug_ll.h new file mode 100644 index 0000000000..ee824cbf2f --- /dev/null +++ b/arch/arm/mach-at91/include/mach/debug_ll.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 + * Jean-Christophe PLAGNIOL-VILLARD <planioj@jcrosoft.com> + * + * Under GPLv2 + */ + +#ifndef __MACH_DEBUG_LL_H__ +#define __MACH_DEBUG_LL_H__ + +#include <asm/io.h> +#include <mach/hardware.h> + +#define UART_BASE (AT91_BASE_SYS + AT91_DBGU) + +#define ATMEL_US_CSR 0x0014 +#define ATMEL_US_THR 0x001c +#define ATMEL_US_TXRDY (1 << 1) +#define ATMEL_US_TXEMPTY (1 << 9) + +/* + * The following code assumes the serial port has already been + * initialized by the bootloader. If you didn't setup a port in + * your bootloader then nothing will appear (which might be desired). + * + * This does not append a newline + */ +static void putc(int c) +{ + while (!(__raw_readl(UART_BASE + ATMEL_US_CSR) & ATMEL_US_TXRDY)) + barrier(); + __raw_writel(c, UART_BASE + ATMEL_US_THR); + + while (!(__raw_readl(UART_BASE + ATMEL_US_CSR) & ATMEL_US_TXEMPTY)) + barrier(); +} +#endif diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index d401164e4a..5615394791 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -1,3 +1,4 @@ obj-y += clocksource.o gpio.o led.o header.o obj-$(CONFIG_MACH_DO_LOWLEVEL_INIT) += lowlevel_init.o +pbl-$(CONFIG_MACH_DO_LOWLEVEL_INIT) += lowlevel_init.o led.o diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 2ff537ab89..2b595bce43 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -8,11 +8,12 @@ obj-$(CONFIG_ARCH_IMX31) += speed-imx31.o imx31.o iomux-v2.o obj-$(CONFIG_ARCH_IMX35) += speed-imx35.o imx35.o iomux-v3.o obj-$(CONFIG_ARCH_IMX51) += speed-imx51.o imx51.o iomux-v3.o imx5.o obj-$(CONFIG_ARCH_IMX53) += speed-imx53.o imx53.o iomux-v3.o imx5.o -obj-$(CONFIG_ARCH_IMX6) += speed-imx6.o imx6.o iomux-v3.o +obj-$(CONFIG_ARCH_IMX6) += speed-imx6.o imx6.o iomux-v3.o usb-imx6.o obj-$(CONFIG_IMX_CLKO) += clko.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-y += speed.o obj-y += devices.o obj-y += boot.o diff --git a/arch/arm/mach-imx/devices.c b/arch/arm/mach-imx/devices.c index 8120f56828..9fde84f1a1 100644 --- a/arch/arm/mach-imx/devices.c +++ b/arch/arm/mach-imx/devices.c @@ -20,7 +20,7 @@ struct device_d *imx_add_spi(void *base, int id, struct spi_imx_master *pdata) struct device_d *imx_add_i2c(void *base, int id, struct i2c_platform_data *pdata) { - return imx_add_device("i2c-imx", id, base, 0x1000, pdata); + return imx_add_device("i2c-fsl", id, base, 0x1000, pdata); } struct device_d *imx_add_uart(void *base, int id) diff --git a/arch/arm/mach-imx/gpio.c b/arch/arm/mach-imx/gpio.c index fdee20b865..8d5d4ce2b0 100644 --- a/arch/arm/mach-imx/gpio.c +++ b/arch/arm/mach-imx/gpio.c @@ -27,7 +27,8 @@ #include <errno.h> #include <io.h> #include <mach/imx-regs.h> -#include <mach/gpio.h> +#include <gpio.h> +#include <init.h> #if defined CONFIG_ARCH_IMX1 || defined CONFIG_ARCH_IMX21 || defined CONFIG_ARCH_IMX27 #define GPIO_DR 0x1c @@ -48,21 +49,15 @@ #define GPIO_ISR 0x18 #endif -extern void __iomem *imx_gpio_base[]; -extern int imx_gpio_count; +struct imx_gpio_chip { + void __iomem *base; + struct gpio_chip chip; +}; -static void __iomem *gpio_get_base(unsigned gpio) +static void imx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) { - if (gpio >= imx_gpio_count) - return NULL; - - return imx_gpio_base[gpio / 32]; -} - -void gpio_set_value(unsigned gpio, int value) -{ - void __iomem *base = gpio_get_base(gpio); - int shift = gpio % 32; + struct imx_gpio_chip *imxgpio = container_of(chip, struct imx_gpio_chip, chip); + void __iomem *base = imxgpio->base; u32 val; if (!base) @@ -71,59 +66,88 @@ void gpio_set_value(unsigned gpio, int value) val = readl(base + GPIO_DR); if (value) - val |= 1 << shift; + val |= 1 << gpio; else - val &= ~(1 << shift); + val &= ~(1 << gpio); writel(val, base + GPIO_DR); } -int gpio_direction_input(unsigned gpio) +static int imx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { - void __iomem *base = gpio_get_base(gpio); - int shift = gpio % 32; + struct imx_gpio_chip *imxgpio = container_of(chip, struct imx_gpio_chip, chip); + void __iomem *base = imxgpio->base; u32 val; if (!base) return -EINVAL; val = readl(base + GPIO_GDIR); - val &= ~(1 << shift); + val &= ~(1 << gpio); writel(val, base + GPIO_GDIR); return 0; } -int gpio_direction_output(unsigned gpio, int value) +static int imx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { - void __iomem *base = gpio_get_base(gpio); - int shift = gpio % 32; + struct imx_gpio_chip *imxgpio = container_of(chip, struct imx_gpio_chip, chip); + void __iomem *base = imxgpio->base; u32 val; - if (!base) - return -EINVAL; - - gpio_set_value(gpio, value); + gpio_set_value(gpio + chip->base, value); val = readl(base + GPIO_GDIR); - val |= 1 << shift; + val |= 1 << gpio; writel(val, base + GPIO_GDIR); return 0; } -int gpio_get_value(unsigned gpio) +static int imx_gpio_get_value(struct gpio_chip *chip, unsigned gpio) { - void __iomem *base = gpio_get_base(gpio); - int shift = gpio % 32; + struct imx_gpio_chip *imxgpio = container_of(chip, struct imx_gpio_chip, chip); + void __iomem *base = imxgpio->base; u32 val; - if (!base) - return -EINVAL; - val = readl(base + GPIO_PSR); - return val & (1 << shift) ? 1 : 0; + return val & (1 << gpio) ? 1 : 0; +} + +static struct gpio_ops imx_gpio_ops = { + .direction_input = imx_gpio_direction_input, + .direction_output = imx_gpio_direction_output, + .get = imx_gpio_get_value, + .set = imx_gpio_set_value, +}; + +static int imx_gpio_probe(struct device_d *dev) +{ + struct imx_gpio_chip *imxgpio; + + imxgpio = xzalloc(sizeof(*imxgpio)); + imxgpio->base = dev_request_mem_region(dev, 0); + imxgpio->chip.ops = &imx_gpio_ops; + imxgpio->chip.base = -1; + imxgpio->chip.ngpio = 32; + imxgpio->chip.dev = dev; + gpiochip_add(&imxgpio->chip); + + dev_info(dev, "probed gpiochip%d with base %d\n", dev->id, imxgpio->chip.base); + + return 0; } +static struct driver_d imx_gpio_driver = { + .name = "imx-gpio", + .probe = imx_gpio_probe, +}; + +static int imx_gpio_add(void) +{ + register_driver(&imx_gpio_driver); + return 0; +} +coredevice_initcall(imx_gpio_add); diff --git a/arch/arm/mach-imx/gpio.h b/arch/arm/mach-imx/gpio.h deleted file mode 100644 index 545cebef3b..0000000000 --- a/arch/arm/mach-imx/gpio.h +++ /dev/null @@ -1,4 +0,0 @@ - -extern void *imx_gpio_base[]; -extern int imx_gpio_count; - diff --git a/arch/arm/mach-imx/imx1.c b/arch/arm/mach-imx/imx1.c index 742a260f0a..5a000bc96a 100644 --- a/arch/arm/mach-imx/imx1.c +++ b/arch/arm/mach-imx/imx1.c @@ -16,16 +16,15 @@ */ #include <common.h> +#include <init.h> -#include "gpio.h" - -void *imx_gpio_base[] = { - (void *)0x0021c000, - (void *)0x0021c100, - (void *)0x0021c200, - (void *)0x0021c300, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; - +static int imx1_init(void) +{ + add_generic_device("imx-gpio", 0, NULL, 0x0021c000, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, 0x0021c100, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, 0x0021c200, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 3, NULL, 0x0021c300, 0x100, IORESOURCE_MEM, NULL); + return 0; +} +coredevice_initcall(imx1_init); diff --git a/arch/arm/mach-imx/imx21.c b/arch/arm/mach-imx/imx21.c index bbef33d2d4..85590ee8f4 100644 --- a/arch/arm/mach-imx/imx21.c +++ b/arch/arm/mach-imx/imx21.c @@ -18,8 +18,6 @@ #include <common.h> #include <mach/imx-regs.h> -#include "gpio.h" - int imx_silicon_revision(void) { // Known values: @@ -28,14 +26,15 @@ int imx_silicon_revision(void) return CID; } -void *imx_gpio_base[] = { - (void *)0x10015000, - (void *)0x10015100, - (void *)0x10015200, - (void *)0x10015300, - (void *)0x10015400, - (void *)0x10015500, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; +static int imx21_init(void) +{ + add_generic_device("imx-gpio", 0, NULL, 0x10015000, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, 0x10015100, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, 0x10015200, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 3, NULL, 0x10015300, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 4, NULL, 0x10015400, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 5, NULL, 0x10015500, 0x100, IORESOURCE_MEM, NULL); + return 0; +} +coredevice_initcall(imx21_init); diff --git a/arch/arm/mach-imx/imx25.c b/arch/arm/mach-imx/imx25.c index 19a2909e18..d605022516 100644 --- a/arch/arm/mach-imx/imx25.c +++ b/arch/arm/mach-imx/imx25.c @@ -22,17 +22,6 @@ #include <io.h> #include <sizes.h> -#include "gpio.h" - -void *imx_gpio_base[] = { - (void *)0x53fcc000, - (void *)0x53fd0000, - (void *)0x53fa4000, - (void *)0x53f9c000, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; - u64 imx_uid(void) { u64 uid = 0; @@ -59,6 +48,10 @@ static int imx25_init(void) add_generic_device("imx_iim", 0, NULL, IMX_IIM_BASE, SZ_4K, IORESOURCE_MEM, &imx25_iim_pdata); + add_generic_device("imx-gpio", 0, NULL, 0x53fcc000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, 0x53fd0000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, 0x53fa4000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 3, NULL, 0x53f9c000, 0x1000, IORESOURCE_MEM, NULL); return 0; } coredevice_initcall(imx25_init); diff --git a/arch/arm/mach-imx/imx27.c b/arch/arm/mach-imx/imx27.c index 1af291d33a..c6e6942c58 100644 --- a/arch/arm/mach-imx/imx27.c +++ b/arch/arm/mach-imx/imx27.c @@ -21,24 +21,11 @@ #include <init.h> #include <io.h> -#include "gpio.h" - int imx_silicon_revision(void) { return CID >> 28; } -void *imx_gpio_base[] = { - (void *)0x10015000, - (void *)0x10015100, - (void *)0x10015200, - (void *)0x10015300, - (void *)0x10015400, - (void *)0x10015500, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; - /* * Initialize MAX on i.MX27. necessary to give the DMA engine * higher priority to the memory than the CPU. Needed for proper @@ -86,6 +73,12 @@ static int imx27_init(void) imx27_init_max(); + add_generic_device("imx-gpio", 0, NULL, 0x10015000, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, 0x10015100, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, 0x10015200, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 3, NULL, 0x10015300, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 4, NULL, 0x10015400, 0x100, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 5, NULL, 0x10015500, 0x100, IORESOURCE_MEM, NULL); return 0; } coredevice_initcall(imx27_init); diff --git a/arch/arm/mach-imx/imx31.c b/arch/arm/mach-imx/imx31.c index bb713ca876..90dc4e3180 100644 --- a/arch/arm/mach-imx/imx31.c +++ b/arch/arm/mach-imx/imx31.c @@ -20,21 +20,15 @@ #include <sizes.h> #include <mach/imx-regs.h> -#include "gpio.h" - -void *imx_gpio_base[] = { - (void *)0x53fcc000, - (void *)0x53fd0000, - (void *)0x53fa4000, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; - static int imx31_init(void) { add_generic_device("imx_iim", 0, NULL, IMX_IIM_BASE, SZ_4K, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 0, NULL, 0x53fcc000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, 0x53fd0000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, 0x53fa4000, 0x1000, IORESOURCE_MEM, NULL); + return 0; } coredevice_initcall(imx31_init); diff --git a/arch/arm/mach-imx/imx35.c b/arch/arm/mach-imx/imx35.c index fe0c99ea72..efbee985d3 100644 --- a/arch/arm/mach-imx/imx35.c +++ b/arch/arm/mach-imx/imx35.c @@ -23,16 +23,6 @@ #include <mach/iim.h> #include <mach/generic.h> -#include "gpio.h" - -void *imx_gpio_base[] = { - (void *)0x53fcc000, - (void *)0x53fd0000, - (void *)0x53fa4000, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; - int imx_silicon_revision() { uint32_t reg; @@ -66,6 +56,10 @@ static int imx35_init(void) add_generic_device("imx_iim", 0, NULL, IMX_IIM_BASE, SZ_4K, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 0, NULL, 0x53fcc000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, 0x53fd0000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, 0x53fa4000, 0x1000, IORESOURCE_MEM, NULL); + return 0; } coredevice_initcall(imx35_init); diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c index 53205a9215..e43cc65ecd 100644 --- a/arch/arm/mach-imx/imx51.c +++ b/arch/arm/mach-imx/imx51.c @@ -24,17 +24,6 @@ #include <mach/imx-regs.h> #include <mach/clock-imx51_53.h> -#include "gpio.h" - -void *imx_gpio_base[] = { - (void *)MX51_GPIO1_BASE_ADDR, - (void *)MX51_GPIO2_BASE_ADDR, - (void *)MX51_GPIO3_BASE_ADDR, - (void *)MX51_GPIO4_BASE_ADDR, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; - #define SI_REV 0x48 static u32 mx51_silicon_revision; @@ -89,6 +78,11 @@ static int imx51_init(void) add_generic_device("imx_iim", 0, NULL, MX51_IIM_BASE_ADDR, SZ_4K, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 0, NULL, 0x73f84000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, 0x73f88000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, 0x73f8c000, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 3, NULL, 0x73f90000, 0x1000, IORESOURCE_MEM, NULL); + return 0; } coredevice_initcall(imx51_init); diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c index 7c679bbe79..cb945753b0 100644 --- a/arch/arm/mach-imx/imx53.c +++ b/arch/arm/mach-imx/imx53.c @@ -24,20 +24,6 @@ #include <mach/imx-regs.h> #include <mach/clock-imx51_53.h> -#include "gpio.h" - -void *imx_gpio_base[] = { - (void *)MX53_GPIO1_BASE_ADDR, - (void *)MX53_GPIO2_BASE_ADDR, - (void *)MX53_GPIO3_BASE_ADDR, - (void *)MX53_GPIO4_BASE_ADDR, - (void *)MX53_GPIO5_BASE_ADDR, - (void *)MX53_GPIO6_BASE_ADDR, - (void *)MX53_GPIO7_BASE_ADDR, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; - #define SI_REV 0x48 static u32 mx53_silicon_revision; @@ -88,6 +74,13 @@ static int imx53_init(void) add_generic_device("imx_iim", 0, NULL, MX53_IIM_BASE_ADDR, SZ_4K, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 0, NULL, MX53_GPIO1_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, MX53_GPIO2_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, MX53_GPIO3_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 3, NULL, MX53_GPIO4_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 4, NULL, MX53_GPIO5_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 5, NULL, MX53_GPIO6_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 6, NULL, MX53_GPIO7_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); return 0; } coredevice_initcall(imx53_init); diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index a443343853..c693724a51 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -21,20 +21,6 @@ #include <sizes.h> #include <mach/imx6-regs.h> -#include "gpio.h" - -void *imx_gpio_base[] = { - (void *)MX6_GPIO1_BASE_ADDR, - (void *)MX6_GPIO2_BASE_ADDR, - (void *)MX6_GPIO3_BASE_ADDR, - (void *)MX6_GPIO4_BASE_ADDR, - (void *)MX6_GPIO5_BASE_ADDR, - (void *)MX6_GPIO6_BASE_ADDR, - (void *)MX6_GPIO7_BASE_ADDR, -}; - -int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32; - void imx6_init_lowlevel(void) { void __iomem *aips1 = (void *)MX6_AIPS1_ON_BASE_ADDR; @@ -69,3 +55,17 @@ void imx6_init_lowlevel(void) writel(0xffffffff, 0x020c407c); writel(0xffffffff, 0x020c4080); } + +static int imx6_init(void) +{ + add_generic_device("imx-gpio", 0, NULL, MX6_GPIO1_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 1, NULL, MX6_GPIO2_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 2, NULL, MX6_GPIO3_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 3, NULL, MX6_GPIO4_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 4, NULL, MX6_GPIO5_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 5, NULL, MX6_GPIO6_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + add_generic_device("imx-gpio", 6, NULL, MX6_GPIO7_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + + return 0; +} +coredevice_initcall(imx6_init); diff --git a/arch/arm/mach-imx/include/mach/clock.h b/arch/arm/mach-imx/include/mach/clock.h index 050b7f8921..f613395768 100644 --- a/arch/arm/mach-imx/include/mach/clock.h +++ b/arch/arm/mach-imx/include/mach/clock.h @@ -27,7 +27,7 @@ ulong imx_get_fecclk(void); ulong imx_get_gptclk(void); ulong imx_get_uartclk(void); ulong imx_get_lcdclk(void); -ulong imx_get_i2cclk(void); +ulong fsl_get_i2cclk(void); ulong imx_get_mmcclk(void); ulong imx_get_cspiclk(void); ulong imx_get_ipgclk(void); diff --git a/arch/arm/mach-imx/include/mach/devices-imx35.h b/arch/arm/mach-imx/include/mach/devices-imx35.h index 6c0d750050..9ecaa35ffe 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx35.h +++ b/arch/arm/mach-imx/include/mach/devices-imx35.h @@ -16,6 +16,11 @@ static inline struct device_d *imx35_add_i2c2(struct i2c_platform_data *pdata) return imx_add_i2c((void *)IMX_I2C3_BASE, 2, pdata); } +static inline struct device_d *imx35_add_spi0(struct spi_imx_master *pdata) +{ + return imx_add_spi((void *)IMX_CSPI1_BASE, 0, pdata); +} + static inline struct device_d *imx35_add_uart0(void) { return imx_add_uart((void *)IMX_UART1_BASE, 0); diff --git a/arch/arm/mach-imx/include/mach/devices-imx6.h b/arch/arm/mach-imx/include/mach/devices-imx6.h index ca063c5459..c73e4888ed 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx6.h +++ b/arch/arm/mach-imx/include/mach/devices-imx6.h @@ -49,3 +49,18 @@ static inline struct device_d *imx6_add_spi0(struct spi_imx_master *pdata) { return imx_add_spi((void *)MX6_ECSPI1_BASE_ADDR, 0, pdata); } + +static inline struct device_d *imx6_add_i2c0(struct i2c_platform_data *pdata) +{ + return imx_add_i2c((void *)MX6_I2C1_BASE_ADDR, 0, pdata); +} + +static inline struct device_d *imx6_add_i2c1(struct i2c_platform_data *pdata) +{ + return imx_add_i2c((void *)MX6_I2C2_BASE_ADDR, 1, pdata); +} + +static inline struct device_d *imx6_add_i2c2(struct i2c_platform_data *pdata) +{ + return imx_add_i2c((void *)MX6_I2C3_BASE_ADDR, 2, pdata); +} diff --git a/arch/arm/mach-imx/include/mach/imx35-regs.h b/arch/arm/mach-imx/include/mach/imx35-regs.h index fafcd61e33..91d4b9bf52 100644 --- a/arch/arm/mach-imx/include/mach/imx35-regs.h +++ b/arch/arm/mach-imx/include/mach/imx35-regs.h @@ -49,6 +49,7 @@ #define IMX_I2C1_BASE 0x43F80000 #define IMX_I2C2_BASE 0x43F98000 #define IMX_I2C3_BASE 0x43F84000 +#define IMX_CSPI1_BASE 0x43FA4000 #define IMX_SDHC1_BASE 0x53FB4000 #define IMX_SDHC2_BASE 0x53FB8000 #define IMX_SDHC3_BASE 0x53FBC000 @@ -75,6 +76,7 @@ #define CCM_CGR2 0x34 #define CCM_CGR3 0x38 +#define CCM_CGR0_CSPI1_SHIFT 10 #define CCM_CGR1_FEC_SHIFT 0 #define CCM_CGR1_I2C1_SHIFT 10 #define CCM_CGR1_SDHC1_SHIFT 26 diff --git a/arch/arm/mach-imx/include/mach/imx6-regs.h b/arch/arm/mach-imx/include/mach/imx6-regs.h index e62cc79a07..c7b7481d0f 100644 --- a/arch/arm/mach-imx/include/mach/imx6-regs.h +++ b/arch/arm/mach-imx/include/mach/imx6-regs.h @@ -74,6 +74,7 @@ #define MX6_WDOG2_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x40000) #define MX6_CCM_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x44000) #define MX6_ANATOP_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x48000) +#define MX6_USBPHY1_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x4a000) #define MX6_SNVS_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x4C000) #define MX6_EPIT1_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x50000) #define MX6_EPIT2_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x54000) diff --git a/arch/arm/mach-imx/speed-imx25.c b/arch/arm/mach-imx/speed-imx25.c index ed14113f76..39e68c85a4 100644 --- a/arch/arm/mach-imx/speed-imx25.c +++ b/arch/arm/mach-imx/speed-imx25.c @@ -78,7 +78,7 @@ unsigned long imx_get_lcdclk(void) return imx_get_perclk(7); } -unsigned long imx_get_i2cclk(void) +unsigned long fsl_get_i2cclk(void) { return imx_get_perclk(6); } diff --git a/arch/arm/mach-imx/speed-imx27.c b/arch/arm/mach-imx/speed-imx27.c index 644fd0462a..7224382299 100644 --- a/arch/arm/mach-imx/speed-imx27.c +++ b/arch/arm/mach-imx/speed-imx27.c @@ -155,7 +155,7 @@ ulong imx_get_lcdclk(void) return imx_get_perclk3(); } -ulong imx_get_i2cclk(void) +ulong fsl_get_i2cclk(void) { return imx_get_ipgclk(); } diff --git a/arch/arm/mach-imx/speed-imx35.c b/arch/arm/mach-imx/speed-imx35.c index 6d4236a020..e0ff1793c5 100644 --- a/arch/arm/mach-imx/speed-imx35.c +++ b/arch/arm/mach-imx/speed-imx35.c @@ -187,11 +187,16 @@ ulong imx_get_fecclk(void) return imx_get_ipgclk(); } -ulong imx_get_i2cclk(void) +ulong fsl_get_i2cclk(void) { return imx_get_ipg_perclk(); } +unsigned long imx_get_cspiclk(void) +{ + return imx_get_ipgclk(); +} + void imx_dump_clocks(void) { printf("mpll: %10ld Hz\n", imx_get_mpllclk()); diff --git a/arch/arm/mach-imx/speed-imx51.c b/arch/arm/mach-imx/speed-imx51.c index 288fe1a640..3903afc821 100644 --- a/arch/arm/mach-imx/speed-imx51.c +++ b/arch/arm/mach-imx/speed-imx51.c @@ -179,7 +179,7 @@ unsigned long imx_get_fecclk(void) return imx_get_ipgclk(); } -unsigned long imx_get_i2cclk(void) +unsigned long fsl_get_i2cclk(void) { return imx_get_ipgclk(); } diff --git a/arch/arm/mach-imx/speed-imx53.c b/arch/arm/mach-imx/speed-imx53.c index ede5ffd75b..b1ba5fd1d2 100644 --- a/arch/arm/mach-imx/speed-imx53.c +++ b/arch/arm/mach-imx/speed-imx53.c @@ -190,7 +190,7 @@ static unsigned long imx_get_ipg_perclk(void) return 0; } -unsigned long imx_get_i2cclk(void) +unsigned long fsl_get_i2cclk(void) { return imx_get_ipg_perclk(); } @@ -232,5 +232,5 @@ void imx_dump_clocks(void) printf("ipg: %ld\n", imx_get_ipgclk()); printf("fec: %ld\n", imx_get_fecclk()); printf("gpt: %ld\n", imx_get_gptclk()); - printf("i2c: %ld\n", imx_get_i2cclk()); + printf("i2c: %ld\n", fsl_get_i2cclk()); } diff --git a/arch/arm/mach-imx/speed-imx6.c b/arch/arm/mach-imx/speed-imx6.c index df2454532d..645b2c9735 100644 --- a/arch/arm/mach-imx/speed-imx6.c +++ b/arch/arm/mach-imx/speed-imx6.c @@ -332,6 +332,11 @@ u32 imx_get_fecclk(void) return __get_ipg_clk(); } +u32 imx_get_i2cclk(void) +{ + return __get_ipg_per_clk(); +} + u32 imx_get_cspiclk(void) { return __get_cspi_clk(); @@ -351,6 +356,7 @@ void imx_dump_clocks(void) printf("mx6q pll8: %d\n", freq); printf("mcu main: %d\n", __get_mcu_main_clk()); printf("periph: %d\n", __get_periph_clk()); + printf("i2c: %d\n", __get_ipg_per_clk()); printf("ipg: %d\n", __get_ipg_clk()); printf("ipg per: %d\n", __get_ipg_per_clk()); printf("cspi: %d\n", __get_cspi_clk()); diff --git a/arch/arm/mach-imx/usb-imx6.c b/arch/arm/mach-imx/usb-imx6.c new file mode 100644 index 0000000000..cd234d2084 --- /dev/null +++ b/arch/arm/mach-imx/usb-imx6.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012 Steffen Trumtrar, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation. + * + */ + +#include <common.h> +#include <io.h> +#include <mach/imx6-regs.h> + +#define SET 0x4 +#define CLR 0x8 + +#define USBPHY_CTRL 0x30 +#define USB_OTG_CTRL 0x800 +#define USB_UH1_CTRL 0x804 +#define USB_UH2_CTRL 0x808 +#define USB_UH3_CTRL 0x80c + +#define USB_UH1_USBCMD 0x340 + +#define USB_CMD_RUNSTOP (1 << 0) +#define USB_CMD_RESET (1 << 1) + +#define USB_OVER_CUR_DIS (1 << 7) +#define USBPHY_CTRL_SFTRST (1 << 31) +#define USBPHY_CTRL_CLKGATE (1 << 30) +#define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15) +#define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14) + +#define USBPHY1_PLL_480_CTRL_EN (1 << 13) +#define USBPHY1_PLL_480_CTRL_POWER (1 << 12) +#define USBPHY1_PLL_480_CTRL_EN_USB_CLK (1 << 6) +#define USBPHY1_PLL_480_CTRL_BYPASS (1 << 16) + +int imx6_usb_phy1_disable_oc(void) +{ + int val; + + /* disable over current detection */ + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_CTRL); + val |= USB_OVER_CUR_DIS; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_CTRL); + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH2_CTRL); + val |= USB_OVER_CUR_DIS; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH2_CTRL); + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH3_CTRL); + val |= USB_OVER_CUR_DIS; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH3_CTRL); + + return 0; +} + +int imx6_usb_phy1_enable(void) +{ + int val; + + /* disable external charger detector or DP will be poor */ + writel(0x00180000, MX6_ANATOP_BASE_ADDR + 0x1b0); + writel(0x00180000, MX6_ANATOP_BASE_ADDR + 0x210); + + /* enable usb pll */ + writel(USBPHY1_PLL_480_CTRL_EN | + USBPHY1_PLL_480_CTRL_POWER | + USBPHY1_PLL_480_CTRL_EN_USB_CLK, MX6_ANATOP_BASE_ADDR + 0x24); + + /* turn OFF clk bypass */ + /* at least on imx6 v1.0 this essential for usb to work */ + /* FIXME: test on v1.1. Datasheet declares bit as reserved */ + writel(USBPHY1_PLL_480_CTRL_BYPASS, MX6_ANATOP_BASE_ADDR + 0x28); + + /* stop then reset */ + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD); + val &= ~USB_CMD_RUNSTOP; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD); + while (readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD) & USB_CMD_RUNSTOP); + + val = readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD); + val |= USB_CMD_RESET; + writel(val, MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD); + while (readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD) & USB_CMD_RESET); + + /* reset usbphy */ + writel(USBPHY_CTRL_SFTRST, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + SET); + udelay(10); + /* clr reset and clkgate */ + writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + CLR); + + /* clr all pwd bits => power up phy */ + writel(0xffffffff, MX6_USBPHY1_BASE_ADDR + CLR); + + /* set utmilvl2/3 */ + val = readl(MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL); + val |= USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2; + writel(val, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + SET); + + return 0; +} diff --git a/arch/arm/mach-mxs/bcb.c b/arch/arm/mach-mxs/bcb.c index d0a3ddc8d3..af51d24b03 100644 --- a/arch/arm/mach-mxs/bcb.c +++ b/arch/arm/mach-mxs/bcb.c @@ -236,7 +236,7 @@ static struct mx28_fcb *create_fcb(struct mtd_info *mtd, void *buf, unsigned fw1 fcb->fw1_start_page = fw1_start_block / mtd->writesize; fcb->fw1_sectors = DIV_ROUND_UP(fw_size, mtd->writesize); - if (fw2_start_block != 0 && fw2_start_block < mtd->size / mtd->erasesize) { + if (fw2_start_block) { fcb->fw2_start_page = fw2_start_block / mtd->writesize; fcb->fw2_sectors = fcb->fw1_sectors; } diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile index 87078ae6d5..f087f4b765 100644 --- a/arch/arm/mach-omap/Makefile +++ b/arch/arm/mach-omap/Makefile @@ -20,9 +20,12 @@ # MA 02111-1307 USA # obj-$(CONFIG_ARCH_OMAP) += syslib.o +pbl-$(CONFIG_ARCH_OMAP) += syslib.o obj-$(CONFIG_OMAP_CLOCK_SOURCE_S32K) += s32k_clksource.o obj-$(CONFIG_ARCH_OMAP3) += omap3_core.o omap3_generic.o auxcr.o +pbl-$(CONFIG_ARCH_OMAP3) += omap3_core.o omap3_generic.o auxcr.o obj-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o +pbl-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o obj-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o obj-$(CONFIG_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o obj-$(CONFIG_SHELL_NONE) += xload.o diff --git a/arch/arm/mach-omap/devices-gpmc-nand.c b/arch/arm/mach-omap/devices-gpmc-nand.c index cf87b57d7f..64ca66619f 100644 --- a/arch/arm/mach-omap/devices-gpmc-nand.c +++ b/arch/arm/mach-omap/devices-gpmc-nand.c @@ -39,37 +39,23 @@ #define GPMC_CONF1_VALx8 0x00000800 #define GPMC_CONF1_VALx16 0x00001800 -/** NAND platform specific settings settings */ -static struct gpmc_nand_platform_data nand_plat = { - .cs = 0, - .max_timeout = MSECOND, - .wait_mon_pin = 0, -}; - /** * @brief gpmc_generic_nand_devices_init - init generic nand device * * @return success/fail based on device function */ -int gpmc_generic_nand_devices_init(int cs, int width, - enum gpmc_ecc_mode eccmode, struct gpmc_config *nand_cfg) +int omap_add_gpmc_nand_device(struct gpmc_nand_platform_data *pdata) { - nand_plat.cs = cs; - - if (width == 16) - nand_cfg->cfg[0] = GPMC_CONF1_VALx16; + if (pdata->device_width == 16) + pdata->nand_cfg->cfg[0] = GPMC_CONF1_VALx16; else - nand_cfg->cfg[0] = GPMC_CONF1_VALx8; - - nand_plat.device_width = width; - nand_plat.ecc_mode = eccmode; - nand_plat.priv = nand_cfg; + pdata->nand_cfg->cfg[0] = GPMC_CONF1_VALx8; /* Configure GPMC CS before register */ - gpmc_cs_config(nand_plat.cs, nand_cfg); + gpmc_cs_config(pdata->cs, pdata->nand_cfg); add_generic_device("gpmc_nand", DEVICE_ID_DYNAMIC, NULL, OMAP_GPMC_BASE, - 1024 * 4, IORESOURCE_MEM, &nand_plat); + 1024 * 4, IORESOURCE_MEM, pdata); return 0; } diff --git a/arch/arm/mach-omap/gpmc.c b/arch/arm/mach-omap/gpmc.c index 92a8ae043d..5b4daaf031 100644 --- a/arch/arm/mach-omap/gpmc.c +++ b/arch/arm/mach-omap/gpmc.c @@ -31,6 +31,7 @@ #include <clock.h> #include <init.h> #include <io.h> +#include <errno.h> #include <mach/silicon.h> #include <mach/gpmc.h> #include <mach/sys_info.h> @@ -125,3 +126,63 @@ void gpmc_cs_config(char cs, struct gpmc_config *config) mdelay(1); /* Settling time */ } EXPORT_SYMBOL(gpmc_cs_config); + +#define CS_NUM_SHIFT 24 +#define ENABLE_PREFETCH (0x1 << 7) +#define DMA_MPU_MODE 2 + +/** + * gpmc_prefetch_enable - configures and starts prefetch transfer + * @cs: cs (chip select) number + * @fifo_th: fifo threshold to be used for read/ write + * @dma_mode: dma mode enable (1) or disable (0) + * @u32_count: number of bytes to be transferred + * @is_write: prefetch read(0) or write post(1) mode + */ +int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode, + unsigned int u32_count, int is_write) +{ + if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) { + pr_err("gpmc: fifo threshold is not supported\n"); + return -EINVAL; + } + + /* Set the amount of bytes to be prefetched */ + writel(u32_count, GPMC_REG(PREFETCH_CONFIG2)); + + /* Set dma/mpu mode, the prefetch read / post write and + * enable the engine. Set which cs is has requested for. + */ + writel(((cs << CS_NUM_SHIFT) | PREFETCH_FIFOTHRESHOLD(fifo_th) | + ENABLE_PREFETCH | (dma_mode << DMA_MPU_MODE) | + (0x1 & is_write)), + GPMC_REG(PREFETCH_CONFIG1)); + + /* Start the prefetch engine */ + writel(0x1, GPMC_REG(PREFETCH_CONTROL)); + + return 0; +} +EXPORT_SYMBOL(gpmc_prefetch_enable); + +/** + * gpmc_prefetch_reset - disables and stops the prefetch engine + */ +int gpmc_prefetch_reset(int cs) +{ + u32 config1; + + /* check if the same module/cs is trying to reset */ + config1 = readl(GPMC_REG(PREFETCH_CONFIG1)); + if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs) + return -EINVAL; + + /* Stop the PFPW engine */ + writel(0x0, GPMC_REG(PREFETCH_CONTROL)); + + /* Reset/disable the PFPW engine */ + writel(0x0, GPMC_REG(PREFETCH_CONFIG1)); + + return 0; +} +EXPORT_SYMBOL(gpmc_prefetch_reset); diff --git a/arch/arm/mach-omap/include/mach/gpmc.h b/arch/arm/mach-omap/include/mach/gpmc.h index 3ddc5f5b87..ed4e82df7c 100644 --- a/arch/arm/mach-omap/include/mach/gpmc.h +++ b/arch/arm/mach-omap/include/mach/gpmc.h @@ -51,9 +51,10 @@ #define GPMC_TIMEOUT_CONTROL (0x40) #define GPMC_CFG (0x50) #define GPMC_STATUS (0x54) -#define GPMC_PREFETCH_CONFIG_1 (0x1E0) -#define GPMC_PREFETCH_CONFIG_2 (0x1E4) -#define GPMC_PREFETCH_CTRL (0x1EC) +#define GPMC_PREFETCH_CONFIG1 (0x1E0) +#define GPMC_PREFETCH_CONFIG2 (0x1E4) +#define GPMC_PREFETCH_CONTROL (0x1EC) +#define GPMC_PREFETCH_STATUS (0x1f0) #define GPMC_ECC_CONFIG (0x1F4) #define GPMC_ECC_CONTROL (0x1F8) #define GPMC_ECC_SIZE_CONFIG (0x1FC) @@ -138,6 +139,15 @@ #define GPMC_SIZE_32M 0x0E #define GPMC_SIZE_16M 0x0F +#define PREFETCH_FIFOTHRESHOLD_MAX 0x40 +#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8) +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F) +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) + +int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode, + unsigned int u32_count, int is_write); +int gpmc_prefetch_reset(int cs); + #define NAND_WP_BIT 0x00000010 #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-omap/include/mach/gpmc_nand.h b/arch/arm/mach-omap/include/mach/gpmc_nand.h index b9c659d1a9..582fb36e8f 100644 --- a/arch/arm/mach-omap/include/mach/gpmc_nand.h +++ b/arch/arm/mach-omap/include/mach/gpmc_nand.h @@ -50,10 +50,6 @@ struct gpmc_nand_platform_data { /** If there are any special setups you'd want to do */ int (*nand_setup) (struct gpmc_nand_platform_data *); - /** set up if we want H/w ECC here and other - * platform specific configs here - */ - unsigned short plat_options; /** ecc mode to use */ enum gpmc_ecc_mode ecc_mode; /** setup any special options */ @@ -62,24 +58,14 @@ struct gpmc_nand_platform_data { char device_width; /** Set this to WAITx+1, so GPMC WAIT0 will be 1 and so on. */ char wait_mon_pin; - /** Set this to the max timeout for the device */ - uint64_t max_timeout; /* if you like a custom oob use this. */ struct nand_ecclayout *oob; - /** platform specific private data */ - void *priv; + /** gpmc config for nand */ + struct gpmc_config *nand_cfg; }; -/** Platform specific options definitions */ -/** plat_options: Wait montioring pin low */ -#define NAND_WAITPOL_LOW (0 << 0) -/** plat_options: Wait montioring pin high */ -#define NAND_WAITPOL_HIGH (1 << 0) -#define NAND_WAITPOL_MASK (1 << 0) - -int gpmc_generic_nand_devices_init(int cs, int width, - enum gpmc_ecc_mode, struct gpmc_config *nand_cfg); +int omap_add_gpmc_nand_device(struct gpmc_nand_platform_data *pdata); extern struct gpmc_config omap3_nand_cfg; extern struct gpmc_config omap4_nand_cfg; diff --git a/arch/arm/mach-omap/include/mach/omap4-clock.h b/arch/arm/mach-omap/include/mach/omap4-clock.h index 0a31d09e06..e5302d6c74 100644 --- a/arch/arm/mach-omap/include/mach/omap4-clock.h +++ b/arch/arm/mach-omap/include/mach/omap4-clock.h @@ -271,6 +271,20 @@ #define PLL_FAST_RELOCK_BYPASS 6 /* CORE */ #define PLL_LOCK 7 /* MPU, IVA, CORE & PER */ +/* TPS */ +#define TPS62361_I2C_SLAVE_ADDR 0x60 +#define TPS62361_REG_ADDR_SET0 0x0 +#define TPS62361_REG_ADDR_SET1 0x1 +#define TPS62361_REG_ADDR_SET2 0x2 +#define TPS62361_REG_ADDR_SET3 0x3 +#define TPS62361_REG_ADDR_CTRL 0x4 +#define TPS62361_REG_ADDR_TEMP 0x5 +#define TPS62361_REG_ADDR_RMP_CTRL 0x6 +#define TPS62361_REG_ADDR_CHIP_ID 0x8 +#define TPS62361_REG_ADDR_CHIP_ID_2 0x9 + +#define TPS62361_BASE_VOLT_MV 500 + /* Used to index into DPLL parameter tables */ struct dpll_param { unsigned int m; @@ -289,6 +303,8 @@ struct dpll_param { #define OMAP4_MPU_DPLL_PARAM_38M4 {0x1a, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00} #define OMAP4_MPU_DPLL_PARAM_38M4_MPU600 {0x7d, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00} #define OMAP4_MPU_DPLL_PARAM_38M4_MPU1000 {0x69, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00} +/* dpll locked at 1840 MHz MPU clk at 920 MHz(OPP Turbo 4460) - DCC OFF */ +#define OMAP4_MPU_DPLL_PARAM_19M2_MPU920 {0x23F, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00} #define OMAP4_IVA_DPLL_PARAM_19M2 {0x61, 0x01, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00} #define OMAP4_IVA_DPLL_PARAM_38M4 {0x61, 0x03, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00} @@ -316,5 +332,8 @@ void omap4_configure_usb_dpll(const struct dpll_param *dpll_param); void omap4_configure_core_dpll_no_lock(const struct dpll_param *param); void omap4_lock_core_dpll(void); void omap4_lock_core_dpll_shadow(const struct dpll_param *param); +void omap4_enable_gpio1_wup_clocks(void); +void omap4_enable_gpio_clocks(void); void omap4_enable_all_clocks(void); +void omap4_do_scale_tps62361(u32 reg, u32 volt_mv); diff --git a/arch/arm/mach-omap/include/mach/omap4-silicon.h b/arch/arm/mach-omap/include/mach/omap4-silicon.h index c7854751ad..4082bac34a 100644 --- a/arch/arm/mach-omap/include/mach/omap4-silicon.h +++ b/arch/arm/mach-omap/include/mach/omap4-silicon.h @@ -60,6 +60,13 @@ #define OMAP44XX_PRM_VC_VAL_BYPASS (OMAP44XX_WAKEUP_L4_IO_BASE + 0x7ba0) #define OMAP44XX_PRM_VC_CFG_I2C_MODE (OMAP44XX_WAKEUP_L4_IO_BASE + 0x7ba8) #define OMAP44XX_PRM_VC_CFG_I2C_CLK (OMAP44XX_WAKEUP_L4_IO_BASE + 0x7bac) +#define OMAP44XX_PRM_VC_VAL_BYPASS_VALID_BIT 0x1000000 +#define OMAP44XX_PRM_VC_VAL_BYPASS_SLAVEADDR_SHIFT 0 +#define OMAP44XX_PRM_VC_VAL_BYPASS_SLAVEADDR_MASK 0x7F +#define OMAP44XX_PRM_VC_VAL_BYPASS_REGADDR_SHIFT 8 +#define OMAP44XX_PRM_VC_VAL_BYPASS_REGADDR_MASK 0xFF +#define OMAP44XX_PRM_VC_VAL_BYPASS_DATA_SHIFT 16 +#define OMAP44XX_PRM_VC_VAL_BYPASS_DATA_MASK 0xFF /* IRQ */ #define OMAP44XX_PRM_IRQSTATUS_MPU_A9 (OMAP44XX_WAKEUP_L4_IO_BASE + 0x6010) @@ -94,6 +101,10 @@ #define DMM_LISA_MAP_SYS_SIZE_MASK (7 << 20) #define DMM_LISA_MAP_SYS_SIZE_SHIFT 20 #define DMM_LISA_MAP_SYS_ADDR_MASK (0xFF << 24) + +/* Memory Adapter (4460 onwards) */ +#define OMAP44XX_MA_BASE 0x482AF000 + /* * Hardware Register Details */ @@ -178,6 +189,6 @@ struct dpll_param; void omap4_ddr_init(const struct ddr_regs *, const struct dpll_param *); void omap4_power_i2c_send(u32); unsigned int omap4_revision(void); -noinline int omap4_scale_vcores(void); +noinline int omap4_scale_vcores(unsigned vsel0_pin); #endif diff --git a/arch/arm/mach-omap/omap4_clock.c b/arch/arm/mach-omap/omap4_clock.c index 3ab01f0d3a..1481f16ffd 100644 --- a/arch/arm/mach-omap/omap4_clock.c +++ b/arch/arm/mach-omap/omap4_clock.c @@ -1,6 +1,7 @@ #include <common.h> #include <io.h> #include <mach/syslib.h> +#include <mach/silicon.h> #include <mach/clocks.h> #define LDELAY 12000000 @@ -13,6 +14,10 @@ void omap4_configure_mpu_dpll(const struct dpll_param *dpll_param) sr32(CM_AUTOIDLE_DPLL_MPU, 0, 3, 0x0); /* Disable DPLL autoidle */ + /* Errata ID: i700, clear CM_CLKSEL_DPLL_MPU[22] : DCC_EN */ + if (omap4_revision() >= OMAP4460_ES1_0) + sr32(CM_CLKSEL_DPLL_MPU, 0, 22, 0); + /* Set M,N,M2 values */ sr32(CM_CLKSEL_DPLL_MPU, 8, 11, dpll_param->m); sr32(CM_CLKSEL_DPLL_MPU, 0, 6, dpll_param->n); @@ -197,6 +202,27 @@ void omap4_lock_core_dpll_shadow(const struct dpll_param *param) wait_on_value((1 << 0), 1, CM_IDLEST_DPLL_CORE, LDELAY); } +void omap4_enable_gpio_clocks(void) +{ + sr32(CM_L4PER_GPIO2_CLKCTRL, 0, 32, 0x1); + wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO2_CLKCTRL, LDELAY); + sr32(CM_L4PER_GPIO3_CLKCTRL, 0, 32, 0x1); + wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO3_CLKCTRL, LDELAY); + sr32(CM_L4PER_GPIO4_CLKCTRL, 0, 32, 0x1); + wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO4_CLKCTRL, LDELAY); + sr32(CM_L4PER_GPIO5_CLKCTRL, 0, 32, 0x1); + wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO5_CLKCTRL, LDELAY); + sr32(CM_L4PER_GPIO6_CLKCTRL, 0, 32, 0x1); + wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO6_CLKCTRL, LDELAY); +} + +void omap4_enable_gpio1_wup_clocks(void) +{ + /* WKUP clocks */ + sr32(CM_WKUP_GPIO1_CLKCTRL, 0, 32, 0x1); + wait_on_value((1 << 17)|(1 << 16), 0, CM_WKUP_GPIO1_CLKCTRL, LDELAY); +} + void omap4_enable_all_clocks(void) { /* Enable Ducati clocks */ @@ -254,16 +280,7 @@ void omap4_enable_all_clocks(void) wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_DMTIMER9_CLKCTRL, LDELAY); /* GPIO clocks */ - sr32(CM_L4PER_GPIO2_CLKCTRL, 0, 32, 0x1); - wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO2_CLKCTRL, LDELAY); - sr32(CM_L4PER_GPIO3_CLKCTRL, 0, 32, 0x1); - wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO3_CLKCTRL, LDELAY); - sr32(CM_L4PER_GPIO4_CLKCTRL, 0, 32, 0x1); - wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO4_CLKCTRL, LDELAY); - sr32(CM_L4PER_GPIO5_CLKCTRL, 0, 32, 0x1); - wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO5_CLKCTRL, LDELAY); - sr32(CM_L4PER_GPIO6_CLKCTRL, 0, 32, 0x1); - wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_GPIO6_CLKCTRL, LDELAY); + omap4_enable_gpio_clocks(); sr32(CM_L4PER_HDQ1W_CLKCTRL, 0, 32, 0x2); @@ -313,8 +330,7 @@ void omap4_enable_all_clocks(void) wait_on_value((1 << 17)|(1 << 16), 0, CM_L4PER_UART4_CLKCTRL, LDELAY); /* WKUP clocks */ - sr32(CM_WKUP_GPIO1_CLKCTRL, 0, 32, 0x1); - wait_on_value((1 << 17)|(1 << 16), 0, CM_WKUP_GPIO1_CLKCTRL, LDELAY); + omap4_enable_gpio1_wup_clocks(); sr32(CM_WKUP_TIMER1_CLKCTRL, 0, 32, 0x01000002); wait_on_value((1 << 17)|(1 << 16), 0, CM_WKUP_TIMER1_CLKCTRL, LDELAY); @@ -378,3 +394,21 @@ void omap4_enable_all_clocks(void) sr32(CM_L3INIT_USBPHY_CLKCTRL, 0, 32, 0x301); } +void omap4_do_scale_tps62361(u32 reg, u32 volt_mv) +{ + u32 temp, step; + + step = volt_mv - TPS62361_BASE_VOLT_MV; + step /= 10; + + temp = TPS62361_I2C_SLAVE_ADDR | + (reg << OMAP44XX_PRM_VC_VAL_BYPASS_REGADDR_SHIFT) | + (step << OMAP44XX_PRM_VC_VAL_BYPASS_DATA_SHIFT) | + OMAP44XX_PRM_VC_VAL_BYPASS_VALID_BIT; + debug("do_scale_tps62361: volt - %d step - 0x%x\n", volt_mv, step); + + writel(temp, OMAP44XX_PRM_VC_VAL_BYPASS); + if (!wait_on_value(OMAP44XX_PRM_VC_VAL_BYPASS_VALID_BIT, 0, + OMAP44XX_PRM_VC_VAL_BYPASS, LDELAY)) + puts("Scaling voltage failed for vdd_mpu from TPS\n"); +} diff --git a/arch/arm/mach-omap/omap4_generic.c b/arch/arm/mach-omap/omap4_generic.c index de6993475d..617d786984 100644 --- a/arch/arm/mach-omap/omap4_generic.c +++ b/arch/arm/mach-omap/omap4_generic.c @@ -7,6 +7,7 @@ #include <mach/syslib.h> #include <mach/xload.h> #include <mach/gpmc.h> +#include <mach/gpio.h> /* * The following several lines are taken from U-Boot to support @@ -28,6 +29,10 @@ #define OMAP4460_CONTROL_ID_CODE_ES1_0 0x0B94E02F #define OMAP4460_CONTROL_ID_CODE_ES1_1 0x2B94E02F +/* EMIF_L3_CONFIG register value */ +#define EMIF_L3_CONFIG_VAL_SYS_10_LL_0 0x0A0000FF +#define EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0 0x0A300000 + void __noreturn reset_cpu(unsigned long addr) { writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL); @@ -263,14 +268,15 @@ int omap4_emif_config(unsigned int base, const struct ddr_regs *ddr_regs) static void reset_phy(unsigned int base) { - *(volatile int*)(base + IODFT_TLGC) |= (1 << 10); + unsigned int val = readl(base + IODFT_TLGC); + val |= (1 << 10); + writel(val, base + IODFT_TLGC); } void omap4_ddr_init(const struct ddr_regs *ddr_regs, const struct dpll_param *core) { - unsigned int rev; - rev = omap4_revision(); + unsigned int rev = omap4_revision(); if (rev == OMAP4430_ES2_0) { writel(0x9e9e9e9e, 0x4A100638); @@ -290,8 +296,15 @@ void omap4_ddr_init(const struct ddr_regs *ddr_regs, /* Both EMIFs 128 byte interleaved */ writel(0x80640300, OMAP44XX_DMM_BASE + DMM_LISA_MAP_0); - *(volatile int*)(OMAP44XX_DMM_BASE + DMM_LISA_MAP_2) = 0x00000000; - *(volatile int*)(OMAP44XX_DMM_BASE + DMM_LISA_MAP_3) = 0xFF020100; + writel(0x00000000, OMAP44XX_DMM_BASE + DMM_LISA_MAP_2); + writel(0xFF020100, OMAP44XX_DMM_BASE + DMM_LISA_MAP_3); + + if (rev >= OMAP4460_ES1_0) { + writel(0x80640300, OMAP44XX_MA_BASE + DMM_LISA_MAP_0); + + writel(0x00000000, OMAP44XX_MA_BASE + DMM_LISA_MAP_2); + writel(0xFF020100, OMAP44XX_MA_BASE + DMM_LISA_MAP_3); + } /* DDR needs to be initialised @ 19.2 MHz * So put core DPLL in bypass mode @@ -301,10 +314,10 @@ void omap4_ddr_init(const struct ddr_regs *ddr_regs, /* No IDLE: BUG in SDC */ sr32(CM_MEMIF_CLKSTCTRL, 0, 32, 0x2); - while(((*(volatile int*)CM_MEMIF_CLKSTCTRL) & 0x700) != 0x700); + while ((readl(CM_MEMIF_CLKSTCTRL) & 0x700) != 0x700); - *(volatile int*)(OMAP44XX_EMIF1_BASE + EMIF_PWR_MGMT_CTRL) = 0x0; - *(volatile int*)(OMAP44XX_EMIF2_BASE + EMIF_PWR_MGMT_CTRL) = 0x0; + writel(0x0, OMAP44XX_EMIF1_BASE + EMIF_PWR_MGMT_CTRL); + writel(0x0, OMAP44XX_EMIF2_BASE + EMIF_PWR_MGMT_CTRL); omap4_emif_config(OMAP44XX_EMIF1_BASE, ddr_regs); omap4_emif_config(OMAP44XX_EMIF2_BASE, ddr_regs); @@ -313,13 +326,13 @@ void omap4_ddr_init(const struct ddr_regs *ddr_regs, omap4_lock_core_dpll_shadow(core); /* Set DLL_OVERRIDE = 0 */ - *(volatile int*)CM_DLL_CTRL = 0x0; + writel(0x0, CM_DLL_CTRL); delay(200); /* Check for DDR PHY ready for EMIF1 & EMIF2 */ - while((((*(volatile int*)(OMAP44XX_EMIF1_BASE + EMIF_STATUS))&(0x04)) != 0x04) \ - || (((*(volatile int*)(OMAP44XX_EMIF2_BASE + EMIF_STATUS))&(0x04)) != 0x04)); + while (((readl(OMAP44XX_EMIF1_BASE + EMIF_STATUS) & 0x04) != 0x04) \ + || ((readl(OMAP44XX_EMIF2_BASE + EMIF_STATUS) & 0x04) != 0x04)); /* Reprogram the DDR PYHY Control register */ /* PHY control values */ @@ -331,9 +344,16 @@ void omap4_ddr_init(const struct ddr_regs *ddr_regs, /* No IDLE: BUG in SDC */ //sr32(CM_MEMIF_CLKSTCTRL, 0, 32, 0x2); - //while(((*(volatile int*)CM_MEMIF_CLKSTCTRL) & 0x700) != 0x700); - *(volatile int*)(OMAP44XX_EMIF1_BASE + EMIF_PWR_MGMT_CTRL) = 0x80000000; - *(volatile int*)(OMAP44XX_EMIF2_BASE + EMIF_PWR_MGMT_CTRL) = 0x80000000; + //while ((readl(CM_MEMIF_CLKSTCTRL) & 0x700) != 0x700); + writel(0x80000000, OMAP44XX_EMIF1_BASE + EMIF_PWR_MGMT_CTRL); + writel(0x80000000, OMAP44XX_EMIF2_BASE + EMIF_PWR_MGMT_CTRL); + + if (rev >= OMAP4460_ES1_0) { + writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0, + OMAP44XX_EMIF1_BASE + EMIF_L3_CONFIG); + writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0, + OMAP44XX_EMIF2_BASE + EMIF_L3_CONFIG); + } /* * DMM : DMM_LISA_MAP_0(Section_0) @@ -347,8 +367,8 @@ void omap4_ddr_init(const struct ddr_regs *ddr_regs, reset_phy(OMAP44XX_EMIF1_BASE); reset_phy(OMAP44XX_EMIF2_BASE); - *((volatile int *)0x80000000) = 0; - *((volatile int *)0x80000080) = 0; + writel(0, 0x80000000); + writel(0, 0x80000080); } void omap4_power_i2c_send(u32 r) @@ -466,7 +486,7 @@ enum omap_boot_src omap4_bootsrc(void) #define I2C_SLAVE 0x12 -noinline int omap4_scale_vcores(void) +noinline int omap4_scale_vcores(unsigned vsel0_pin) { unsigned int rev = omap4_revision(); @@ -476,8 +496,41 @@ noinline int omap4_scale_vcores(void) writel(0, OMAP44XX_PRM_VC_CFG_I2C_MODE); writel(0x6026, OMAP44XX_PRM_VC_CFG_I2C_CLK); + /* TPS - supplies vdd_mpu on 4460 */ + if (rev >= OMAP4460_ES1_0) { + /* + * Setup SET1 and SET0 with right values so that kernel + * can use either of them based on its needs. + */ + omap4_do_scale_tps62361(TPS62361_REG_ADDR_SET0, 1430); + omap4_do_scale_tps62361(TPS62361_REG_ADDR_SET1, 1430); + + /* + * Select SET1 in TPS62361: + * VSEL1 is grounded on board. So the following selects + * VSEL1 = 0 and VSEL0 = 1 + */ + gpio_direction_output(vsel0_pin, 0); + gpio_set_value(vsel0_pin, 1); + } + /* set VCORE1 force VSEL */ - omap4_power_i2c_send((0x3A55 << 8) | I2C_SLAVE); + /* + * 4430 : supplies vdd_mpu + * Setting a high voltage for Nitro mode as smart reflex is not enabled. + * We use the maximum possible value in the AVS range because the next + * higher voltage in the discrete range (code >= 0b111010) is way too + * high + * + * 4460 : supplies vdd_core + * + */ + if (rev < OMAP4460_ES1_0) + /* 0x55: i2c addr, 3A: ~ 1430 mvolts*/ + omap4_power_i2c_send((0x3A55 << 8) | I2C_SLAVE); + else + /* 0x55: i2c addr, 28: ~ 1200 mvolts*/ + omap4_power_i2c_send((0x2855 << 8) | I2C_SLAVE); /* FIXME: set VCORE2 force VSEL, Check the reset value */ omap4_power_i2c_send((0x295B << 8) | I2C_SLAVE); @@ -490,6 +543,7 @@ noinline int omap4_scale_vcores(void) case OMAP4430_ES2_1: omap4_power_i2c_send((0x2A61 << 8) | I2C_SLAVE); break; + /* > OMAP4460_ES1_0 : VCORE3 not connected */ } return 0; diff --git a/arch/arm/mach-samsung/Makefile b/arch/arm/mach-samsung/Makefile index 39aa26957b..0ffe3705ef 100644 --- a/arch/arm/mach-samsung/Makefile +++ b/arch/arm/mach-samsung/Makefile @@ -2,6 +2,8 @@ obj-y += s3c-timer.o generic.o obj-$(CONFIG_RESET_SOURCE) += reset_source.o obj-lowlevel-$(CONFIG_ARCH_S3C24xx) += lowlevel-s3c24x0.o obj-lowlevel-$(CONFIG_ARCH_S5PCxx) += lowlevel-s5pcxx.o +pbl-$(CONFIG_ARCH_S3C24xx) += lowlevel-s3c24x0.o +pbl-$(CONFIG_ARCH_S5PCxx) += lowlevel-s5pcxx.o obj-$(CONFIG_ARCH_S3C24xx) += gpio-s3c24x0.o clocks-s3c24xx.o mem-s3c24x0.o obj-$(CONFIG_ARCH_S3C64xx) += gpio-s3c64xx.o clocks-s3c64xx.o mem-s3c64xx.o obj-$(CONFIG_ARCH_S5PCxx) += gpio-s5pcxx.o clocks-s5pcxx.o mem-s5pcxx.o diff --git a/arch/arm/pbl/.gitignore b/arch/arm/pbl/.gitignore new file mode 100644 index 0000000000..3384d8b3c1 --- /dev/null +++ b/arch/arm/pbl/.gitignore @@ -0,0 +1,5 @@ +piggy.gzip +piggy.lzo +zbarebox +zbarebox.bin +zbarebox.lds diff --git a/arch/arm/pbl/Makefile b/arch/arm/pbl/Makefile new file mode 100644 index 0000000000..fe68e72eed --- /dev/null +++ b/arch/arm/pbl/Makefile @@ -0,0 +1,40 @@ + +suffix_$(CONFIG_IMAGE_COMPRESSION_GZIP) = gzip +suffix_$(CONFIG_IMAGE_COMPRESSION_LZO) = lzo + +OBJCOPYFLAGS_zbarebox.bin = -O binary +piggy_o := piggy.$(suffix_y).o + +targets := zbarebox.lds zbarebox zbarebox.bin zbarebox.S \ + $(piggy_o) piggy.$(suffix_y) + +# Make sure files are removed during clean +extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern + +$(obj)/zbarebox.bin: $(obj)/zbarebox FORCE + $(call if_changed,objcopy) + $(call cmd,check_file_size,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE)) + @echo ' Barebox: $@ is ready' + +$(obj)/zbarebox.S: $(obj)/zbarebox FORCE + $(call if_changed,disasm) + +PBL_CPPFLAGS += -fdata-sections -ffunction-sections +LDFLAGS_zbarebox := -Map $(obj)/zbarebox.map +LDFLAGS_zbarebox += -static --gc-sections +zbarebox-common := $(barebox-pbl-common) $(obj)/$(piggy_o) +zbarebox-lds := $(obj)/zbarebox.lds + +quiet_cmd_zbarebox__ ?= LD $@ + cmd_zbarebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_zbarebox) -o $@ \ + -T $(zbarebox-lds) \ + --start-group $(zbarebox-common) --end-group \ + $(filter-out $(zbarebox-lds) $(zbarebox-common) FORCE ,$^) + +$(obj)/zbarebox: $(zbarebox-lds) $(zbarebox-common) FORCE + $(call if_changed,zbarebox__) + +$(obj)/piggy.$(suffix_y): $(obj)/../../../barebox.bin FORCE + $(call if_changed,$(suffix_y)) + +$(obj)/$(piggy_o): $(obj)/piggy.$(suffix_y) FORCE diff --git a/arch/arm/pbl/piggy.gzip.S b/arch/arm/pbl/piggy.gzip.S new file mode 100644 index 0000000000..4a623c0c57 --- /dev/null +++ b/arch/arm/pbl/piggy.gzip.S @@ -0,0 +1,6 @@ + .section .piggydata,#alloc + .globl input_data +input_data: + .incbin "arch/arm/pbl/piggy.gzip" + .globl input_data_end +input_data_end: diff --git a/arch/arm/pbl/piggy.lzo.S b/arch/arm/pbl/piggy.lzo.S new file mode 100644 index 0000000000..e0484c7d5c --- /dev/null +++ b/arch/arm/pbl/piggy.lzo.S @@ -0,0 +1,6 @@ + .section .piggydata,#alloc + .globl input_data +input_data: + .incbin "arch/arm/pbl/piggy.lzo" + .globl input_data_end +input_data_end: diff --git a/arch/arm/pbl/zbarebox.lds.S b/arch/arm/pbl/zbarebox.lds.S new file mode 100644 index 0000000000..2dca278318 --- /dev/null +++ b/arch/arm/pbl/zbarebox.lds.S @@ -0,0 +1,78 @@ +/* + * (C) Copyright 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 as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <asm-generic/barebox.lds.h> +#include <asm-generic/memory_layout.h> + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(pbl_start) +SECTIONS +{ + . = HEAD_TEXT_BASE; + + PRE_IMAGE + + . = ALIGN(4); + .text : + { + _stext = .; + _text = .; + *(.text_head_entry*) + __ll_return = .; + *(.text_ll_return*) + __bare_init_start = .; + *(.text_bare_init*) + __bare_init_end = .; + *(.text*) + } + + /* Discard unwind if enable in barebox */ + /DISCARD/ : { *(.ARM.ex*) } + + BAREBOX_BARE_INIT_SIZE + + . = ALIGN(4); + .rodata : { *(.rodata*) } + + _etext = .; /* End of text and rodata section */ + + . = ALIGN(4); + .data : { *(.data*) } + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss*) } + __bss_stop = .; + _end = .; + + . = ALIGN(4); + __piggydata_start = .; + .piggydata : { + *(.piggydata) + } + __piggydata_end = .; + + _barebox_image_size = __piggydata_end - HEAD_TEXT_BASE; + _barebox_pbl_size = __bss_start - HEAD_TEXT_BASE; +} diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index a0b87f77d7..381c6a9f39 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -13,7 +13,7 @@ CFLAGS += -D__blackfin__ KALLSYMS += --symbol-prefix=_ ifndef CONFIG_BFIN_BOOT_BYPASS -all: barebox.ldr +KBUILD_IMAGE := barebox.ldr endif archprepare: maketools diff --git a/arch/blackfin/include/asm/unaligned.h b/arch/blackfin/include/asm/unaligned.h new file mode 100644 index 0000000000..0f6c0987f2 --- /dev/null +++ b/arch/blackfin/include/asm/unaligned.h @@ -0,0 +1,11 @@ +#ifndef _ASM_BLACKFIN_UNALIGNED_H +#define _ASM_BLACKFIN_UNALIGNED_H + +#include <linux/unaligned/le_struct.h> +#include <linux/unaligned/be_byteshift.h> +#include <linux/unaligned/generic.h> + +#define get_unaligned __get_unaligned_le +#define put_unaligned __put_unaligned_le + +#endif /* _ASM_BLACKFIN_UNALIGNED_H */ diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 6b7dae9faf..5e40de760f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -82,8 +82,6 @@ incdir-y := $(machine-y) endif INCDIR := arch-$(incdir-y) -all: $(KBUILD_IMAGE) - ifneq ($(board-y),) BOARD := arch/mips/boards/$(board-y)/ else diff --git a/arch/mips/boards/dlink-dir-320/serial.c b/arch/mips/boards/dlink-dir-320/serial.c index 3eaab2a129..1185248d5d 100644 --- a/arch/mips/boards/dlink-dir-320/serial.c +++ b/arch/mips/boards/dlink-dir-320/serial.c @@ -35,7 +35,7 @@ static struct NS16550_plat serial_plat = { static int dir320_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, DEBUG_LL_UART_ADDR, 8, + add_ns16550_device(DEVICE_ID_DYNAMIC, DEBUG_LL_UART_ADDR, 8, IORESOURCE_MEM_8BIT, &serial_plat); return 0; diff --git a/arch/mips/boards/qemu-malta/init.c b/arch/mips/boards/qemu-malta/init.c index 0efc92a141..45f66f243d 100644 --- a/arch/mips/boards/qemu-malta/init.c +++ b/arch/mips/boards/qemu-malta/init.c @@ -58,7 +58,7 @@ static struct NS16550_plat serial_plat = { static int malta_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, DEBUG_LL_UART_ADDR, 8, + add_ns16550_device(DEVICE_ID_DYNAMIC, DEBUG_LL_UART_ADDR, 8, IORESOURCE_MEM_8BIT, &serial_plat); return 0; diff --git a/arch/mips/boards/rzx50/serial.c b/arch/mips/boards/rzx50/serial.c index 308cd18eaf..3f593c9a92 100644 --- a/arch/mips/boards/rzx50/serial.c +++ b/arch/mips/boards/rzx50/serial.c @@ -58,7 +58,7 @@ static struct NS16550_plat serial_plat = { static int rzx50_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, UART1_BASE, 8 << JZ4750D_UART_SHIFT, + add_ns16550_device(DEVICE_ID_DYNAMIC, UART1_BASE, 8 << JZ4750D_UART_SHIFT, IORESOURCE_MEM_8BIT, &serial_plat); return 0; diff --git a/arch/nios2/boards/generic/generic.c b/arch/nios2/boards/generic/generic.c index 2c998fe3ac..cdaaa02062 100644 --- a/arch/nios2/boards/generic/generic.c +++ b/arch/nios2/boards/generic/generic.c @@ -34,7 +34,7 @@ static struct device_d mac_dev = { static int generic_devices_init(void) { - add_cfi_flash_device(-1, NIOS_SOPC_FLASH_BASE, NIOS_SOPC_FLASH_SIZE, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, NIOS_SOPC_FLASH_BASE, NIOS_SOPC_FLASH_SIZE, 0); add_mem_device("ram0", NIOS_SOPC_MEMORY_BASE, NIOS_SOPC_MEMORY_SIZE, IORESOURCE_MEM_WRITEABLE); register_device(&mac_dev); diff --git a/arch/openrisc/boards/generic/generic.c b/arch/openrisc/boards/generic/generic.c index 6a9ce5b864..54c73a5aa3 100644 --- a/arch/openrisc/boards/generic/generic.c +++ b/arch/openrisc/boards/generic/generic.c @@ -12,7 +12,7 @@ static struct NS16550_plat serial_plat = { static int openrisc_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, OPENRISC_SOPC_UART_BASE, 1024, IORESOURCE_MEM_8BIT, &serial_plat); + add_ns16550_device(DEVICE_ID_DYNAMIC, OPENRISC_SOPC_UART_BASE, 1024, IORESOURCE_MEM_8BIT, &serial_plat); return 0; } diff --git a/arch/openrisc/include/asm/unaligned.h b/arch/openrisc/include/asm/unaligned.h new file mode 100644 index 0000000000..1141cbd6fd --- /dev/null +++ b/arch/openrisc/include/asm/unaligned.h @@ -0,0 +1,51 @@ +/* + * OpenRISC Linux + * + * Linux architectural port borrowing liberally from similar works of + * others. All original copyrights apply as per the original source + * declaration. + * + * OpenRISC implementation: + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> + * et al. + * + * 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 __ASM_OPENRISC_UNALIGNED_H +#define __ASM_OPENRISC_UNALIGNED_H + +/* + * This is copied from the generic implementation and the C-struct + * variant replaced with the memmove variant. The GCC compiler + * for the OR32 arch optimizes too aggressively for the C-struct + * variant to work, so use the memmove variant instead. + * + * It may be worth considering implementing the unaligned access + * exception handler and allowing unaligned accesses (access_ok.h)... + * not sure if it would be much of a performance win without further + * investigation. + */ +#include <asm/byteorder.h> + +#if defined(__LITTLE_ENDIAN) +# include <linux/unaligned/le_memmove.h> +# include <linux/unaligned/be_byteshift.h> +# include <linux/unaligned/generic.h> +# define get_unaligned __get_unaligned_le +# define put_unaligned __put_unaligned_le +#elif defined(__BIG_ENDIAN) +# include <linux/unaligned/be_memmove.h> +# include <linux/unaligned/le_byteshift.h> +# include <linux/unaligned/generic.h> +# define get_unaligned __get_unaligned_be +# define put_unaligned __put_unaligned_be +#else +# error need to define endianess +#endif + +#endif /* __ASM_OPENRISC_UNALIGNED_H */ diff --git a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c index 20897cbaee..2431cb5d37 100644 --- a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c +++ b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c @@ -26,6 +26,7 @@ #include <driver.h> #include <ns16550.h> #include <types.h> +#include <i2c/i2c.h> #include <partition.h> #include <memory.h> #include <asm/cache.h> @@ -34,7 +35,8 @@ #include <mach/mpc85xx.h> #include <mach/mmu.h> #include <mach/immap_85xx.h> -#include <mach/clocks.h> +#include <mach/gianfar.h> +#include <mach/clock.h> #include <mach/early_udelay.h> #define VSC7385_RST_SET 0x00080000 @@ -61,9 +63,31 @@ #define SYSCLK_50 50000000 #define SYSCLK_100 100000000 +/* Ethernet. Use eTSEC3 */ +static struct gfar_info_struct gfar_info[] = { + { + .phyaddr = 1, + .tbiana = 0, + .tbicr = 0, + }, +}; + +/* I2C busses. */ +struct i2c_platform_data i2cplat = { + .bitrate = 400000, +}; + static int devices_init(void) { - add_cfi_flash_device(-1, CFG_FLASH_BASE, 16 << 20, 0); + add_cfi_flash_device(DEVICE_ID_DYNAMIC, CFG_FLASH_BASE, 16 << 20, 0); + + add_generic_device("i2c-fsl", 0, NULL, I2C1_BASE_ADDR, + 0x100, IORESOURCE_MEM, &i2cplat); + add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR, + 0x100, IORESOURCE_MEM, &i2cplat); + + /* eTSEC3 */ + fsl_eth_init(3, &gfar_info[0]); devfs_add_partition("nor0", 0xf80000, 0x80000, DEVFS_PARTITION_FIXED, "self0"); @@ -81,7 +105,7 @@ static int p2020_console_init(void) { serial_plat.clock = fsl_get_bus_freq(0); - add_ns16550_device(-1, 0xffe04500, 16, IORESOURCE_MEM_8BIT, + add_ns16550_device(DEVICE_ID_DYNAMIC, 0xffe04500, 16, IORESOURCE_MEM_8BIT, &serial_plat); return 0; } diff --git a/arch/ppc/configs/p2020rdb_defconfig b/arch/ppc/configs/p2020rdb_defconfig index f8a0687251..7690327424 100644 --- a/arch/ppc/configs/p2020rdb_defconfig +++ b/arch/ppc/configs/p2020rdb_defconfig @@ -21,3 +21,12 @@ CONFIG_MALLOC_SIZE=0x200000 CONFIG_BAUDRATE=115200 CONFIG_DRIVER_SERIAL_NS16550=y CONFIG_RELOCATABLE=y +CONFIG_DRIVER_NET_GIANFAR=y +CONFIG_NET=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_PING=y +CONFIG_TFTP=y +CONFIG_I2C=y +CONFIG_I2C_IMX=y +CONFIG_CMD_I2C=y diff --git a/arch/ppc/include/asm/fsl_i2c.h b/arch/ppc/include/asm/fsl_i2c.h deleted file mode 100644 index 4f71341327..0000000000 --- a/arch/ppc/include/asm/fsl_i2c.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Freescale I2C Controller - * - * Copyright 2006 Freescale Semiconductor, Inc. - * - * Based on earlier versions by Gleb Natapov <gnatapov@mrv.com>, - * Xianghua Xiao <x.xiao@motorola.com>, Eran Liberty (liberty@freescale.com), - * and Jeff Brown. - * Some bits are taken from linux driver writen by adrian@humboldt.co.uk. - * - * This software may be used and distributed according to the - * terms of the GNU Public License, Version 2, incorporated - * herein by reference. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _ASM_FSL_I2C_H_ -#define _ASM_FSL_I2C_H_ - -#include <asm/types.h> - -typedef struct fsl_i2c { - - u8 adr; /* I2C slave address */ - u8 res0[3]; -#define I2C_ADR 0xFE -#define I2C_ADR_SHIFT 1 -#define I2C_ADR_RES ~(I2C_ADR) - - u8 fdr; /* I2C frequency divider register */ - u8 res1[3]; -#define IC2_FDR 0x3F -#define IC2_FDR_SHIFT 0 -#define IC2_FDR_RES ~(IC2_FDR) - - u8 cr; /* I2C control redister */ - u8 res2[3]; -#define I2C_CR_MEN 0x80 -#define I2C_CR_MIEN 0x40 -#define I2C_CR_MSTA 0x20 -#define I2C_CR_MTX 0x10 -#define I2C_CR_TXAK 0x08 -#define I2C_CR_RSTA 0x04 -#define I2C_CR_BCST 0x01 - - u8 sr; /* I2C status register */ - u8 res3[3]; -#define I2C_SR_MCF 0x80 -#define I2C_SR_MAAS 0x40 -#define I2C_SR_MBB 0x20 -#define I2C_SR_MAL 0x10 -#define I2C_SR_BCSTM 0x08 -#define I2C_SR_SRW 0x04 -#define I2C_SR_MIF 0x02 -#define I2C_SR_RXAK 0x01 - - u8 dr; /* I2C data register */ - u8 res4[3]; -#define I2C_DR 0xFF -#define I2C_DR_SHIFT 0 -#define I2C_DR_RES ~(I2C_DR) - - u8 dfsrr; /* I2C digital filter sampling rate register */ - u8 res5[3]; -#define I2C_DFSRR 0x3F -#define I2C_DFSRR_SHIFT 0 -#define I2C_DFSRR_RES ~(I2C_DR) - - /* Fill out the reserved block */ - u8 res6[0xE8]; -} fsl_i2c_t; - -#endif /* _ASM_I2C_H_ */ diff --git a/arch/ppc/include/asm/unaligned.h b/arch/ppc/include/asm/unaligned.h new file mode 100644 index 0000000000..a41fa8cb4a --- /dev/null +++ b/arch/ppc/include/asm/unaligned.h @@ -0,0 +1,16 @@ +#ifndef _ASM_PPC_UNALIGNED_H +#define _ASM_PPC_UNALIGNED_H + +#ifdef __KERNEL__ + +/* + * The PowerPC can do unaligned accesses itself in big endian mode. + */ +#include <linux/unaligned/access_ok.h> +#include <linux/unaligned/generic.h> + +#define get_unaligned __get_unaligned_be +#define put_unaligned __put_unaligned_be + +#endif /* __KERNEL__ */ +#endif /* _ASM_PPC_UNALIGNED_H */ diff --git a/arch/ppc/mach-mpc85xx/Makefile b/arch/ppc/mach-mpc85xx/Makefile index 03addaf47b..af9be29271 100644 --- a/arch/ppc/mach-mpc85xx/Makefile +++ b/arch/ppc/mach-mpc85xx/Makefile @@ -6,3 +6,4 @@ obj-y += fsl_law.o obj-y += speed.o obj-y +=time.o obj-$(CONFIG_MP) += mp.o +obj-$(CONFIG_DRIVER_NET_GIANFAR) += eth-devices.o diff --git a/arch/ppc/mach-mpc85xx/eth-devices.c b/arch/ppc/mach-mpc85xx/eth-devices.c new file mode 100644 index 0000000000..02a3722136 --- /dev/null +++ b/arch/ppc/mach-mpc85xx/eth-devices.c @@ -0,0 +1,49 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <driver.h> +#include <mach/immap_85xx.h> +#include <mach/gianfar.h> + +int fsl_eth_init(int num, struct gfar_info_struct *gf) +{ + struct resource *res; + + res = xzalloc(3 * sizeof(struct resource)); + /* TSEC interface registers */ + res[0].start = GFAR_BASE_ADDR + ((num - 1) * 0x1000); + res[0].end = res[0].start + 0x1000; + res[0].flags = IORESOURCE_MEM; + /* External PHY access always through eTSEC1 */ + res[1].start = MDIO_BASE_ADDR; + res[1].end = res[1].start + 0x1000; + res[1].flags = IORESOURCE_MEM; + /* Access to TBI/RTBI interface. */ + res[2].start = MDIO_BASE_ADDR + ((num - 1) * 0x1000); + res[2].end = res[2].start + 0x1000; + res[2].flags = IORESOURCE_MEM; + + add_generic_device_res("gfar", DEVICE_ID_DYNAMIC, res, 3, gf); + + return 0; +} diff --git a/arch/ppc/mach-mpc85xx/include/mach/clocks.h b/arch/ppc/mach-mpc85xx/include/mach/clock.h index 2ab367b2ec..e20d68518e 100644 --- a/arch/ppc/mach-mpc85xx/include/mach/clocks.h +++ b/arch/ppc/mach-mpc85xx/include/mach/clock.h @@ -12,5 +12,6 @@ struct sys_info { unsigned long fsl_get_bus_freq(ulong dummy); unsigned long fsl_get_timebase_clock(void); +unsigned long fsl_get_i2c_freq(void); void fsl_get_sys_info(struct sys_info *sysInfo); #endif /* __ASM_ARCH_CLOCKS_H */ diff --git a/arch/ppc/mach-mpc85xx/include/mach/gianfar.h b/arch/ppc/mach-mpc85xx/include/mach/gianfar.h new file mode 100644 index 0000000000..ae3163865c --- /dev/null +++ b/arch/ppc/mach-mpc85xx/include/mach/gianfar.h @@ -0,0 +1,31 @@ +/* + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2004, 2007, 2009 Freescale Semiconductor, Inc. + * (C) Copyright 2003, Motorola, Inc. + * based on tsec.h by Xianghua Xiao and Andy Fleming 2003-2009 + * + * 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 + * + * Platform data for the Motorola Triple Speed Ethernet Controller + */ + +struct gfar_info_struct { + unsigned int phyaddr; + unsigned int tbiana; + unsigned int tbicr; +}; + +int fsl_eth_init(int num, struct gfar_info_struct *gf); diff --git a/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h b/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h index b80224952d..cd43023259 100644 --- a/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h +++ b/arch/ppc/mach-mpc85xx/include/mach/immap_85xx.h @@ -39,6 +39,11 @@ #define MPC85xx_GPIO_OFFSET 0xf000 #define MPC85xx_L2_OFFSET 0x20000 +#ifdef CONFIG_TSECV2 +#define TSEC1_OFFSET 0xB0000 +#else +#define TSEC1_OFFSET 0x24000 +#endif #define MPC85xx_PIC_OFFSET 0x40000 #define MPC85xx_GUTS_OFFSET 0xe0000 @@ -129,4 +134,10 @@ #define MPC85xx_DEVDISR_TB1 0x00001000 #define MPC85xx_GUTS_RSTCR_OFFSET 0xb0 +#define GFAR_BASE_ADDR (CFG_IMMR + TSEC1_OFFSET) +#define MDIO_BASE_ADDR (CFG_IMMR + 0x24000) + +#define I2C1_BASE_ADDR (CFG_IMMR + 0x3000) +#define I2C2_BASE_ADDR (CFG_IMMR + 0x3100) + #endif /*__IMMAP_85xx__*/ diff --git a/arch/ppc/mach-mpc85xx/speed.c b/arch/ppc/mach-mpc85xx/speed.c index 40d3664188..6778d57c29 100644 --- a/arch/ppc/mach-mpc85xx/speed.c +++ b/arch/ppc/mach-mpc85xx/speed.c @@ -30,7 +30,7 @@ #include <common.h> #include <asm/processor.h> -#include <mach/clocks.h> +#include <mach/clock.h> #include <mach/immap_85xx.h> #include <mach/mpc85xx.h> @@ -102,3 +102,12 @@ unsigned long fsl_get_timebase_clock(void) return (sysinfo.freqSystemBus + 4UL)/8UL; } + +unsigned long fsl_get_i2c_freq(void) +{ + struct sys_info sysinfo; + + fsl_get_sys_info(&sysinfo); + + return sysinfo.freqSystemBus / 2; +} diff --git a/arch/ppc/mach-mpc85xx/time.c b/arch/ppc/mach-mpc85xx/time.c index 408a28a2eb..c50591c961 100644 --- a/arch/ppc/mach-mpc85xx/time.c +++ b/arch/ppc/mach-mpc85xx/time.c @@ -25,7 +25,7 @@ #include <common.h> #include <clock.h> #include <init.h> -#include <mach/clocks.h> +#include <mach/clock.h> uint64_t ppc_clocksource_read(void) { diff --git a/arch/sandbox/board/board.c b/arch/sandbox/board/board.c index d2f0667c98..6bccd2cb6d 100644 --- a/arch/sandbox/board/board.c +++ b/arch/sandbox/board/board.c @@ -29,7 +29,7 @@ static struct device_d tap_device = { .id = DEVICE_ID_DYNAMIC, - .name = "tap", + .name = "tap", }; static int devices_init(void) diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index da84fa5f6b..8ca164f214 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -1 +1,6 @@ -/* nothing */ +#ifndef __ASM_SANDBOX_IO_H +#define __ASM_SANDBOX_IO_H + +#include <asm-generic/io.h> + +#endif /* __ASM_SANDBOX_IO_H */ diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c index 92b7dbb2c7..e296574c93 100644 --- a/arch/sandbox/os/common.c +++ b/arch/sandbox/os/common.c @@ -271,33 +271,29 @@ err_out: static void print_usage(const char*); +static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"malloc", 1, 0, 'm'}, + {"image", 1, 0, 'i'}, + {"env", 1, 0, 'e'}, + {"stdout", 1, 0, 'O'}, + {"stdin", 1, 0, 'I'}, + {0, 0, 0, 0}, +}; + +static const char optstring[] = "hm:i:e:O:I:"; + int main(int argc, char *argv[]) { void *ram; int opt, ret, fd; int malloc_size = 8 * 1024 * 1024; char str[6]; - int fdno = 0, envno = 0; - - ram = malloc(malloc_size); - if (!ram) { - printf("unable to get malloc space\n"); - exit(1); - } - mem_malloc_init(ram, ram + malloc_size - 1); + int fdno = 0, envno = 0, option_index = 0; while (1) { - int option_index = 0; - static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"image", 1, 0, 'i'}, - {"env", 1, 0, 'e'}, - {"stdout", 1, 0, 'O'}, - {"stdin", 1, 0, 'I'}, - {0, 0, 0, 0}, - }; - - opt = getopt_long(argc, argv, "hi:e:O:I:", + option_index = 0; + opt = getopt_long(argc, argv, optstring, long_options, &option_index); if (opt == -1) @@ -307,18 +303,7 @@ int main(int argc, char *argv[]) case 'h': print_usage(basename(argv[0])); exit(0); - case 'i': - sprintf(str, "fd%d", fdno); - ret = add_image(optarg, str); - if (ret) - exit(1); - fdno++; - break; case 'm': - /* This option is broken. add_image needs malloc, so - * mem_alloc_init() has to be called before option - * parsing - */ malloc_size = strtoul(optarg, NULL, 0); break; case 'e': @@ -351,6 +336,47 @@ int main(int argc, char *argv[]) } } + ram = malloc(malloc_size); + if (!ram) { + printf("unable to get malloc space\n"); + exit(1); + } + mem_malloc_init(ram, ram + malloc_size - 1); + + /* reset getopt */ + optind = 1; + + while (1) { + option_index = 0; + opt = getopt_long(argc, argv, optstring, + long_options, &option_index); + + if (opt == -1) + break; + + switch (opt) { + case 'h': + break; + case 'm': + break; + case 'i': + sprintf(str, "fd%d", fdno); + ret = add_image(optarg, str); + if (ret) + exit(1); + fdno++; + break; + case 'e': + break; + case 'O': + break; + case 'I': + break; + default: + exit(1); + } + } + barebox_register_console("console", fileno(stdin), fileno(stdout)); rawmode(); @@ -371,6 +397,7 @@ static void print_usage(const char *prgname) "Usage: %s [OPTIONS]\n" "Start barebox.\n\n" "Options:\n\n" +" -m, " " -i, --image=<file> Map an image file to barebox. This option can be given\n" " multiple times. The files will show up as\n" " /dev/fd0 ... /dev/fdx under barebox.\n" diff --git a/arch/x86/Makefile b/arch/x86/Makefile index db4180b32b..518b37fe2f 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -14,11 +14,6 @@ CPPFLAGS += -fdata-sections -ffunction-sections LDFLAGS_uboot += -static --gc-sections endif -all: $(KBUILD_IMAGE) - - - - machdirs := $(patsubst %,arch/x86/mach-%/,$(machine-y)) ifeq ($(KBUILD_SRC),) diff --git a/arch/x86/boards/x86_generic/generic_pc.c b/arch/x86/boards/x86_generic/generic_pc.c index 4be1237607..046f76db72 100644 --- a/arch/x86/boards/x86_generic/generic_pc.c +++ b/arch/x86/boards/x86_generic/generic_pc.c @@ -78,7 +78,7 @@ static struct NS16550_plat serial_plat = { static int pc_console_init(void) { /* Register the serial port */ - add_ns16550_device(-1, 0x3f8, 8, 0, &serial_plat); + add_ns16550_device(DEVICE_ID_DYNAMIC, 0x3f8, 8, 0, &serial_plat); return 0; } diff --git a/commands/Kconfig b/commands/Kconfig index 92a8152905..f2756cc400 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -57,6 +57,10 @@ config CMD_READLINE tristate prompt "readline" +config CMD_LN + tristate + prompt "ln" + config CMD_TRUE tristate default y @@ -220,6 +224,12 @@ config CMD_DIRNAME Strip last component of file name and store the result in a environment variable +config CMD_READLINK + tristate + prompt "readlink" + help + read value of a symbolic link + endmenu menu "console " @@ -406,7 +416,6 @@ config CMD_UIMAGE config CMD_BOOTZ tristate - default y depends on ARM prompt "bootz" help diff --git a/commands/Makefile b/commands/Makefile index e9157bfcc7..ccebd7f559 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -72,3 +72,5 @@ obj-$(CONFIG_CMD_AUTOMOUNT) += automount.o obj-$(CONFIG_CMD_GLOBAL) += global.o obj-$(CONFIG_CMD_BASENAME) += basename.o obj-$(CONFIG_CMD_DIRNAME) += dirname.o +obj-$(CONFIG_CMD_READLINK) += readlink.o +obj-$(CONFIG_CMD_LN) += ln.o diff --git a/commands/dirname.c b/commands/dirname.c index cf1d0a022d..f34d88d0fc 100644 --- a/commands/dirname.c +++ b/commands/dirname.c @@ -24,20 +24,38 @@ #include <command.h> #include <libgen.h> #include <environment.h> +#include <fs.h> +#include <getopt.h> static int do_dirname(int argc, char *argv[]) { - if (argc != 3) + int opt; + int path_fs = 0; + int len = 0; + + while ((opt = getopt(argc, argv, "V")) > 0) { + switch (opt) { + case 'V': + path_fs = 1; + break; + } + } + + if (argc < optind + 2) return COMMAND_ERROR_USAGE; - setenv(argv[2], dirname(argv[1])); + if (path_fs) + len = strlen(get_mounted_path(argv[optind])); + + setenv(argv[optind + 1], dirname(argv[optind]) + len); return 0; } BAREBOX_CMD_HELP_START(dirname) -BAREBOX_CMD_HELP_USAGE("dirname NAME DIRNAME\n") +BAREBOX_CMD_HELP_USAGE("dirname [-V] NAME DIRNAME\n") BAREBOX_CMD_HELP_SHORT("strip last componext of NAME and store into $DIRNAME\n") +BAREBOX_CMD_HELP_SHORT("-V return the path relative to the mountpoint.\n") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(dirname) diff --git a/commands/ln.c b/commands/ln.c new file mode 100644 index 0000000000..0237447ae4 --- /dev/null +++ b/commands/ln.c @@ -0,0 +1,51 @@ +/* + * ln.c - make links between files + * + * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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 version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <libgen.h> +#include <environment.h> +#include <fs.h> +#include <errno.h> + +static int do_ln(int argc, char *argv[]) +{ + if (argc != 3) + return COMMAND_ERROR_USAGE; + + if (symlink(argv[1], argv[2]) < 0) { + perror("ln"); + return 1; + } + return 0; +} + +BAREBOX_CMD_HELP_START(ln) +BAREBOX_CMD_HELP_USAGE("ln SRC DEST\n") +BAREBOX_CMD_HELP_SHORT("symlink - make a new name for a file\n") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(ln) + .cmd = do_ln, + .usage = "symlink - make a new name for a file", + BAREBOX_CMD_HELP(cmd_ln_help) +BAREBOX_CMD_END diff --git a/commands/ls.c b/commands/ls.c index fbcbadcd08..d36ef578c9 100644 --- a/commands/ls.c +++ b/commands/ls.c @@ -29,13 +29,24 @@ #include <getopt.h> #include <stringlist.h> -static void ls_one(const char *path, struct stat *s) +static void ls_one(const char *path, const char* fullname, struct stat *s) { char modestr[11]; unsigned int namelen = strlen(path); mkmodestr(s->st_mode, modestr); - printf("%s %10llu %*.*s\n", modestr, s->st_size, namelen, namelen, path); + printf("%s %10llu %*.*s", modestr, s->st_size, namelen, namelen, path); + + if (S_ISLNK(s->st_mode)) { + char realname[PATH_MAX]; + + memset(realname, 0, PATH_MAX); + + if (readlink(fullname, realname, PATH_MAX - 1) >= 0) + printf(" -> %s", realname); + } + + puts("\n"); } int ls(const char *path, ulong flags) @@ -48,14 +59,14 @@ int ls(const char *path, ulong flags) string_list_init(&sl); - if (stat(path, &s)) + if (lstat(path, &s)) return -errno; if (flags & LS_SHOWARG && s.st_mode & S_IFDIR) printf("%s:\n", path); if (!(s.st_mode & S_IFDIR)) { - ls_one(path, &s); + ls_one(path, path, &s); return 0; } @@ -65,12 +76,12 @@ int ls(const char *path, ulong flags) while ((d = readdir(dir))) { sprintf(tmp, "%s/%s", path, d->d_name); - if (stat(tmp, &s)) + if (lstat(tmp, &s)) goto out; if (flags & LS_COLUMN) string_list_add_sorted(&sl, d->d_name); else - ls_one(d->d_name, &s); + ls_one(d->d_name, tmp, &s); } closedir(dir); @@ -97,7 +108,7 @@ int ls(const char *path, ulong flags) continue; sprintf(tmp, "%s/%s", path, d->d_name); - if (stat(tmp, &s)) + if (lstat(tmp, &s)) goto out; if (s.st_mode & S_IFDIR) { char *norm = normalise_path(tmp); @@ -146,7 +157,7 @@ static int do_ls(int argc, char *argv[]) /* first pass: all files */ while (o < argc) { - ret = stat(argv[o], &s); + ret = lstat(argv[o], &s); if (ret) { printf("%s: %s: %s\n", argv[0], argv[o], errno_str()); @@ -158,7 +169,7 @@ static int do_ls(int argc, char *argv[]) if (flags & LS_COLUMN) string_list_add_sorted(&sl, argv[o]); else - ls_one(argv[o], &s); + ls_one(argv[o], argv[o], &s); } o++; @@ -173,7 +184,7 @@ static int do_ls(int argc, char *argv[]) /* second pass: directories */ while (o < argc) { - ret = stat(argv[o], &s); + ret = lstat(argv[o], &s); if (ret) { o++; continue; diff --git a/commands/mount.c b/commands/mount.c index b32faef709..5b12ad4d96 100644 --- a/commands/mount.c +++ b/commands/mount.c @@ -29,11 +29,14 @@ #include <command.h> #include <fs.h> #include <errno.h> +#include <getopt.h> static int do_mount(int argc, char *argv[]) { + int opt; int ret = 0; struct fs_device_d *fsdev; + char *type = NULL; if (argc == 1) { for_each_fs_device(fsdev) { @@ -45,10 +48,18 @@ static int do_mount(int argc, char *argv[]) return 0; } - if (argc != 4) + while ((opt = getopt(argc, argv, "t:")) > 0) { + switch (opt) { + case 't': + type = optarg; + break; + } + } + + if (argc < optind + 2) return COMMAND_ERROR_USAGE; - if ((ret = mount(argv[1], argv[2], argv[3]))) { + if ((ret = mount(argv[optind], type, argv[optind + 1]))) { perror("mount"); return 1; } @@ -56,8 +67,9 @@ static int do_mount(int argc, char *argv[]) } BAREBOX_CMD_HELP_START(mount) -BAREBOX_CMD_HELP_USAGE("mount [<device> <fstype> <mountpoint>]\n") +BAREBOX_CMD_HELP_USAGE("mount [[-t <fstype] <device> <mountpoint>]\n") BAREBOX_CMD_HELP_SHORT("Mount a filesystem of a given type to a mountpoint.\n") +BAREBOX_CMD_HELP_SHORT("If no fstpye is specified detected it.\n") BAREBOX_CMD_HELP_SHORT("If no argument is given, list mounted filesystems.\n") BAREBOX_CMD_HELP_END diff --git a/commands/readlink.c b/commands/readlink.c new file mode 100644 index 0000000000..d2671e0f2e --- /dev/null +++ b/commands/readlink.c @@ -0,0 +1,80 @@ +/* + * readlink.c - read value of a symbolic link + * + * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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 version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <libgen.h> +#include <environment.h> +#include <fs.h> +#include <malloc.h> +#include <getopt.h> + +static int do_readlink(int argc, char *argv[]) +{ + char realname[PATH_MAX]; + int canonicalize = 0; + int opt; + + memset(realname, 0, PATH_MAX); + + while ((opt = getopt(argc, argv, "f")) > 0) { + switch (opt) { + case 'f': + canonicalize = 1; + break; + } + } + + if (argc < optind + 2) + return COMMAND_ERROR_USAGE; + + if (readlink(argv[optind], realname, PATH_MAX - 1) < 0) + goto err; + + if (canonicalize) { + char *buf = normalise_link(argv[optind], realname); + + if (!buf) + goto err; + setenv(argv[optind + 1], buf); + free(buf); + } else { + setenv(argv[optind + 1], realname); + } + + return 0; +err: + setenv(argv[optind + 1], ""); + return 1; +} + +BAREBOX_CMD_HELP_START(readlink) +BAREBOX_CMD_HELP_USAGE("readlink [-f] FILE REALNAME\n") +BAREBOX_CMD_HELP_SHORT("read value of a symbolic link and store into $REALNAME\n") +BAREBOX_CMD_HELP_SHORT("-f canonicalize by following first symlink"); +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(readlink) + .cmd = do_readlink, + .usage = "read value of a symbolic link", + BAREBOX_CMD_HELP(cmd_readlink_help) +BAREBOX_CMD_END diff --git a/commands/test.c b/commands/test.c index 9ffa892524..18eeaab8c1 100644 --- a/commands/test.c +++ b/commands/test.c @@ -43,6 +43,7 @@ typedef enum { OPT_DIRECTORY, OPT_FILE, OPT_EXISTS, + OPT_SYMBOLIC_LINK, OPT_MAX, } test_opts; @@ -62,6 +63,7 @@ static char *test_options[] = { [OPT_FILE] = "-f", [OPT_DIRECTORY] = "-d", [OPT_EXISTS] = "-e", + [OPT_SYMBOLIC_LINK] = "-L", }; static int parse_opt(const char *opt) @@ -140,9 +142,10 @@ static int do_test(int argc, char *argv[]) case OPT_FILE: case OPT_DIRECTORY: case OPT_EXISTS: + case OPT_SYMBOLIC_LINK: adv = 2; if (ap[1] && *ap[1] != ']' && strlen(ap[1])) { - expr = stat(ap[1], &statbuf); + expr = (opt == OPT_SYMBOLIC_LINK ? lstat : stat)(ap[1], &statbuf); if (expr < 0) { expr = 0; break; @@ -160,6 +163,10 @@ static int do_test(int argc, char *argv[]) expr = 1; break; } + if (opt == OPT_SYMBOLIC_LINK && S_ISLNK(statbuf.st_mode)) { + expr = 1; + break; + } } break; @@ -224,7 +231,7 @@ static const char *test_aliases[] = { "[", NULL}; static const __maybe_unused char cmd_test_help[] = "Usage: test [OPTIONS]\n" -"options: !, =, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, -n, -d, -e, -f\n" +"options: !, =, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, -n, -d, -e, -f, -L\n" "see 'man test' on your PC for more information.\n"; static const __maybe_unused char cmd_test_usage[] = "minimal test like /bin/sh"; diff --git a/common/Kconfig b/common/Kconfig index 7eb5b49a8f..b97392cfdb 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -101,6 +101,48 @@ config ENVIRONMENT_VARIABLES menu "memory layout " +config HAVE_PBL_IMAGE + bool + +config HAVE_IMAGE_COMPRESSION + bool + +config PBL_IMAGE + bool "Pre-Bootloader image" + depends on HAVE_PBL_IMAGE + +config PBL_FORCE_PIGGYDATA_COPY + bool + help + In some case we need to copy the PIGGYDATA as the link address + as example we run from SRAM and shutdown the SDRAM/DDR for + reconfiguration but most of the time we just need to copy the + executable code. + +if PBL_IMAGE + +config IMAGE_COMPRESSION + bool + depends on HAVE_IMAGE_COMPRESSION + default y + +if IMAGE_COMPRESSION + +choice + prompt "Compression" + +config IMAGE_COMPRESSION_LZO + bool "lzo" + +config IMAGE_COMPRESSION_GZIP + bool "gzip" + +endchoice + +endif + +endif + config MMU bool "Enable MMU" help @@ -481,6 +523,8 @@ config DEFAULT_ENVIRONMENT config DEFAULT_ENVIRONMENT_COMPRESSED bool depends on DEFAULT_ENVIRONMENT + depends on !IMAGE_COMPRESSION_LZO + depends on !IMAGE_COMPRESSION_GZIP default y if ZLIB default y if BZLIB default y if LZO_DECOMPRESS diff --git a/common/Makefile b/common/Makefile index d74dffb916..df9f301234 100644 --- a/common/Makefile +++ b/common/Makefile @@ -58,7 +58,7 @@ ifneq ($(CONFIG_DEFAULT_ENVIRONMENT_PATH),"") DEFAULT_ENVIRONMENT_PATH += $(CONFIG_DEFAULT_ENVIRONMENT_PATH) endif -ENV_FILES := $(shell cd $(srctree); for i in $(DEFAULT_ENVIRONMENT_PATH); do find $${i} -type f -exec readlink -f '{}' \;; done) +ENV_FILES := $(shell cd $(srctree); for i in $(DEFAULT_ENVIRONMENT_PATH); do find $${i} -type f ; done) endif # ifdef CONFIG_DEFAULT_ENVIRONMENT diff --git a/common/command.c b/common/command.c index c18998c129..2bfc5117e8 100644 --- a/common/command.c +++ b/common/command.c @@ -38,26 +38,6 @@ LIST_HEAD(command_list); EXPORT_SYMBOL(command_list); -#ifdef CONFIG_SHELL_HUSH - -static int do_exit(int argc, char *argv[]) -{ - int r; - - r = 0; - if (argc > 1) - r = simple_strtoul(argv[1], NULL, 0); - - return -r - 2; -} - -BAREBOX_CMD_START(exit) - .cmd = do_exit, - .usage = "exit script", -BAREBOX_CMD_END - -#endif - void barebox_cmd_usage(struct command *cmdtp) { #ifdef CONFIG_LONGHELP diff --git a/common/environment.c b/common/environment.c index 52ce0de1da..ce46f4a0e6 100644 --- a/common/environment.c +++ b/common/environment.c @@ -53,7 +53,21 @@ int file_size_action(const char *filename, struct stat *statbuf, data->writep += sizeof(struct envfs_inode); data->writep += PAD4(strlen(filename) + 1 - strlen(data->base)); - data->writep += PAD4(statbuf->st_size); + data->writep += sizeof(struct envfs_inode_end); + if (S_ISLNK(statbuf->st_mode)) { + char path[PATH_MAX]; + + memset(path, 0, PATH_MAX); + + if (readlink(filename, path, PATH_MAX - 1) < 0) { + perror("read"); + return 0; + } + data->writep += PAD4(strlen(path) + 1); + } else { + data->writep += PAD4(statbuf->st_size); + } + return 1; } @@ -62,34 +76,60 @@ int file_save_action(const char *filename, struct stat *statbuf, { struct action_data *data = userdata; struct envfs_inode *inode; + struct envfs_inode_end *inode_end; int fd; int namelen = strlen(filename) + 1 - strlen(data->base); - debug("handling file %s size %ld namelen %d\n", filename + strlen(data->base), - statbuf->st_size, namelen); - inode = (struct envfs_inode*)data->writep; inode->magic = ENVFS_32(ENVFS_INODE_MAGIC); - inode->namelen = ENVFS_32(namelen); - inode->size = ENVFS_32(statbuf->st_size); + inode->headerlen = ENVFS_32(PAD4(namelen + sizeof(struct envfs_inode_end))); data->writep += sizeof(struct envfs_inode); strcpy(data->writep, filename + strlen(data->base)); data->writep += PAD4(namelen); + inode_end = (struct envfs_inode_end*)data->writep; + data->writep += sizeof(struct envfs_inode_end); + inode_end->magic = ENVFS_32(ENVFS_INODE_END_MAGIC); + inode_end->mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO); - fd = open(filename, O_RDONLY); - if (fd < 0) { - printf("Open %s %s\n", filename, errno_str()); - goto out; - } + if (S_ISLNK(statbuf->st_mode)) { + char path[PATH_MAX]; + int len; - if (read(fd, data->writep, statbuf->st_size) < statbuf->st_size) { - perror("read"); - goto out; - } - close(fd); + memset(path, 0, PATH_MAX); + + if (readlink(filename, path, PATH_MAX - 1) < 0) { + perror("read"); + goto out; + } + len = strlen(path) + 1; + + inode_end->mode |= ENVFS_32(S_IFLNK); + + memcpy(data->writep, path, len); + inode->size = ENVFS_32(len); + data->writep += PAD4(len); + debug("handling symlink %s size %ld namelen %d headerlen %d\n", filename + strlen(data->base), + len, namelen, ENVFS_32(inode->headerlen)); + } else { + debug("handling file %s size %ld namelen %d headerlen %d\n", filename + strlen(data->base), + statbuf->st_size, namelen, ENVFS_32(inode->headerlen)); - data->writep += PAD4(statbuf->st_size); + inode->size = ENVFS_32(statbuf->st_size); + fd = open(filename, O_RDONLY); + if (fd < 0) { + printf("Open %s %s\n", filename, errno_str()); + goto out; + } + + if (read(fd, data->writep, statbuf->st_size) < statbuf->st_size) { + perror("read"); + goto out; + } + close(fd); + + data->writep += PAD4(statbuf->st_size); + } out: return 1; @@ -125,6 +165,8 @@ int envfs_save(char *filename, char *dirname) super = (struct envfs_super *)buf; super->magic = ENVFS_32(ENVFS_MAGIC); + super->major = ENVFS_MAJOR; + super->minor = ENVFS_MINOR; super->size = ENVFS_32(size); /* second pass: copy files to buffer */ @@ -174,8 +216,13 @@ int envfs_load(char *filename, char *dir) int envfd; int fd, ret = 0; char *str, *tmp; - int namelen_full; + int headerlen_full; unsigned long size; + /* for envfs < 1.0 */ + struct envfs_inode_end inode_end_dummy; + + inode_end_dummy.mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO); + inode_end_dummy.magic = ENVFS_32(ENVFS_INODE_END_MAGIC); envfd = open(filename, O_RDONLY); if (envfd < 0) { @@ -221,11 +268,18 @@ int envfs_load(char *filename, char *dir) goto out; } + if (super.major < ENVFS_MAJOR) + printf("envfs version %d.%d loaded into %d.%d\n", + super.major, super.minor, + ENVFS_MAJOR, ENVFS_MINOR); + while (size) { struct envfs_inode *inode; - uint32_t inode_size, inode_namelen; + struct envfs_inode_end *inode_end; + uint32_t inode_size, inode_headerlen, namelen; inode = (struct envfs_inode *)buf; + buf += sizeof(struct envfs_inode); if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) { printf("envfs: wrong magic on %s\n", filename); @@ -233,38 +287,58 @@ int envfs_load(char *filename, char *dir) goto out; } inode_size = ENVFS_32(inode->size); - inode_namelen = ENVFS_32(inode->namelen); + inode_headerlen = ENVFS_32(inode->headerlen); + namelen = strlen(inode->data) + 1; + if (super.major < 1) + inode_end = &inode_end_dummy; + else + inode_end = (struct envfs_inode_end *)(buf + PAD4(namelen)); - debug("loading %s size %d namelen %d\n", inode->data, - inode_size, inode_namelen); + debug("loading %s size %d namelen %d headerlen %d\n", inode->data, + inode_size, namelen, inode_headerlen); str = concat_path_file(dir, inode->data); tmp = strdup(str); make_directory(dirname(tmp)); free(tmp); - fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); - free(str); - if (fd < 0) { - printf("Open %s\n", errno_str()); - ret = fd; + headerlen_full = PAD4(inode_headerlen); + buf += headerlen_full; + + if (ENVFS_32(inode_end->magic) != ENVFS_INODE_END_MAGIC) { + printf("envfs: wrong inode_end_magic on %s\n", filename); + ret = -EIO; goto out; } - namelen_full = PAD4(inode_namelen); - ret = write(fd, buf + namelen_full + sizeof(struct envfs_inode), - inode_size); - if (ret < inode_size) { - perror("write"); - ret = -errno; + if (S_ISLNK(ENVFS_32(inode_end->mode))) { + debug("symlink: %s -> %s\n", str, (char*)buf); + if (symlink((char*)buf, str) < 0) { + printf("symlink: %s -> %s :", str, (char*)buf); + perror(""); + } + free(str); + } else { + fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); + free(str); + if (fd < 0) { + printf("Open %s\n", errno_str()); + ret = fd; + goto out; + } + + ret = write(fd, buf, inode_size); + if (ret < inode_size) { + perror("write"); + ret = -errno; + close(fd); + goto out; + } close(fd); - goto out; } - close(fd); - buf += PAD4(inode_namelen) + PAD4(inode_size) + - sizeof(struct envfs_inode); - size -= PAD4(inode_namelen) + PAD4(inode_size) + + 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 1a5b82da47..e736d43efe 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -22,6 +22,7 @@ #include <common.h> #include <filetype.h> #include <asm/byteorder.h> +#include <asm/unaligned.h> #include <fcntl.h> #include <fs.h> #include <malloc.h> @@ -40,6 +41,7 @@ static const char *filetype_str[] = { [filetype_aimage] = "Android boot image", [filetype_sh] = "Bourne Shell", [filetype_mips_barebox] = "MIPS barebox image", + [filetype_fat] = "FAT filesytem", }; const char *file_type_to_string(enum filetype f) @@ -50,6 +52,22 @@ const char *file_type_to_string(enum filetype f) return NULL; } +static int is_fat(u8 *buf) +{ + if (get_unaligned_le16(&buf[510]) != 0xAA55) + return 0; + + /* FAT */ + if ((get_unaligned_le32(&buf[54]) & 0xFFFFFF) == 0x544146) + return 1; + + /* FAT32 */ + if ((get_unaligned_le32(&buf[82]) & 0xFFFFFF) == 0x544146) + return 1; + + return 0; +} + enum filetype file_detect_type(void *_buf) { u32 *buf = _buf; @@ -81,6 +99,8 @@ enum filetype file_detect_type(void *_buf) return filetype_aimage; if (strncmp(buf8 + 0x10, "barebox", 7) == 0) return filetype_mips_barebox; + if (is_fat(buf8)) + return filetype_fat; return filetype_unknown; } diff --git a/common/hush.c b/common/hush.c index 8200931387..61aac13d1b 100644 --- a/common/hush.c +++ b/common/hush.c @@ -557,6 +557,18 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child, } #endif +static int builtin_exit(struct p_context *ctx, struct child_prog *child, + int argc, char *argv[]) +{ + int r; + + r = last_return_code; + if (argc > 1) + r = simple_strtoul(argv[1], NULL, 0); + + return -r - 2; +} + static void remove_quotes_in_str(char *src) { char *trg = src; @@ -773,10 +785,17 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi) remove_quotes(globbuf.gl_pathc, globbuf.gl_pathv); - if (!strcmp(globbuf.gl_pathv[0], "getopt")) + if (!strcmp(globbuf.gl_pathv[0], "getopt")) { ret = builtin_getopt(ctx, child, globbuf.gl_pathc, globbuf.gl_pathv); - else + } else if (!strcmp(globbuf.gl_pathv[0], "exit")) { + ret = builtin_exit(ctx, child, globbuf.gl_pathc, globbuf.gl_pathv); + } else { ret = execute_binfmt(globbuf.gl_pathc, globbuf.gl_pathv); + if (ret < 0) { + printf("%s: %s\n", globbuf.gl_pathv[0], strerror(-ret)); + ret = 127; + } + } globfree(&globbuf); @@ -1885,16 +1904,28 @@ BAREBOX_CMD_START(source) BAREBOX_CMD_HELP(cmd_source_help) BAREBOX_CMD_END -#ifdef CONFIG_HUSH_GETOPT -static int do_getopt(int argc, char *argv[]) +static int do_dummy_command(int argc, char *argv[]) { /* - * This function is never reached. The 'getopt' command is - * only here to provide a help text for the getopt builtin. + * This function is never reached. These commands are only here to + * provide help texts for the builtins. */ return 0; } +static const __maybe_unused char cmd_exit_help[] = +"Usage: exit [n]\n" +"\n" +"exit script with a status of n. If n is omitted, the exit status is that\n" +"of the last command executed\n"; + +BAREBOX_CMD_START(exit) + .cmd = do_dummy_command, + .usage = "exit script", + BAREBOX_CMD_HELP(cmd_exit_help) +BAREBOX_CMD_END + +#ifdef CONFIG_HUSH_GETOPT static const __maybe_unused char cmd_getopt_help[] = "Usage: getopt <optstring> <var>\n" "\n" @@ -1905,7 +1936,7 @@ static const __maybe_unused char cmd_getopt_help[] = "can be accessed starting from $1\n"; BAREBOX_CMD_START(getopt) - .cmd = do_getopt, + .cmd = do_dummy_command, .usage = "getopt <optstring> <var>", BAREBOX_CMD_HELP(cmd_getopt_help) BAREBOX_CMD_END diff --git a/common/menu.c b/common/menu.c index 9f536d6aee..97c6b184bd 100644 --- a/common/menu.c +++ b/common/menu.c @@ -314,6 +314,23 @@ int menu_show(struct menu *m) m->auto_select = -1; switch (ch) { + case '0' ... '9': { + struct menu_entry *me; + int num = ch - '0'; + int next_num = m->selected->num + 10; + if (!num) + num = 10; + + if (ch_previous == ch && next_num <= m->nb_entries) + num = next_num; + + me = menu_entry_get_by_num(m, num); + if (me) { + m->selected = me; + repaint = 1; + } + break; + } case KEY_UP: m->selected = list_entry(m->selected->list.prev, struct menu_entry, list); diff --git a/defaultenv-2/base/init/automount b/defaultenv-2/base/init/automount index 7b533094ff..fe56d920e7 100644 --- a/defaultenv-2/base/init/automount +++ b/defaultenv-2/base/init/automount @@ -8,15 +8,15 @@ fi # automount tftp server based on $eth0.serverip mkdir -p /mnt/tftp -automount /mnt/tftp 'ifup eth0 && mount $eth0.serverip tftp /mnt/tftp' +automount /mnt/tftp 'ifup eth0 && mount -t tftp $eth0.serverip /mnt/tftp' # automount nfs server example #nfshost=somehost #mkdir -p /mnt/${nfshost} -#automount /mnt/$nfshost "ifup eth0 && mount ${nfshost}:/tftpboot nfs /mnt/${nfshost}" +#automount /mnt/$nfshost "ifup eth0 && mount -t nfs ${nfshost}:/tftpboot /mnt/${nfshost}" # FAT on usb disk example #mkdir -p /mnt/fat -#automount -d /mnt/fat 'usb && [ -e /dev/disk0.0 ] && mount /dev/disk0.0 fat /mnt/fat' +#automount -d /mnt/fat 'usb && [ -e /dev/disk0.0 ] && mount /dev/disk0.0 /mnt/fat' diff --git a/drivers/Kconfig b/drivers/Kconfig index 883b0e7bc9..70797c182c 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -12,11 +12,13 @@ source "drivers/video/Kconfig" source "drivers/mci/Kconfig" source "drivers/clk/Kconfig" source "drivers/mfd/Kconfig" +source "drivers/misc/Kconfig" source "drivers/led/Kconfig" source "drivers/eeprom/Kconfig" source "drivers/input/Kconfig" source "drivers/watchdog/Kconfig" source "drivers/pwm/Kconfig" source "drivers/dma/Kconfig" +source "drivers/gpio/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index ea3263f615..28a5cb8f35 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -15,5 +15,7 @@ obj-$(CONFIG_LED) += led/ obj-y += eeprom/ obj-$(CONFIG_PWM) += pwm/ obj-y += input/ +obj-y += misc/ obj-y += dma/ obj-y += watchdog/ +obj-y += gpio/ diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig new file mode 100644 index 0000000000..022a30988e --- /dev/null +++ b/drivers/gpio/Kconfig @@ -0,0 +1,13 @@ +config GPIOLIB + bool + +if GPIOLIB + +menu "GPIO " + +config GPIO_STMPE + depends on I2C_STMPE + bool "STMPE GPIO Expander" +endmenu + +endif diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile new file mode 100644 index 0000000000..945122b083 --- /dev/null +++ b/drivers/gpio/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_GPIOLIB) += gpio.o +obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c new file mode 100644 index 0000000000..fa3b041534 --- /dev/null +++ b/drivers/gpio/gpio-stmpe.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2012 Pengutronix + * Steffen Trumtrar <s.trumtrar@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 <errno.h> +#include <io.h> +#include <gpio.h> +#include <init.h> +#include <mfd/stmpe-i2c.h> + +#define GPIO_BASE 0x80 +#define GPIO_SET (GPIO_BASE + 0x02) +#define GPIO_CLR (GPIO_BASE + 0x04) +#define GPIO_MP (GPIO_BASE + 0x06) +#define GPIO_SET_DIR (GPIO_BASE + 0x08) +#define GPIO_ED (GPIO_BASE + 0x0a) +#define GPIO_RE (GPIO_BASE + 0x0c) +#define GPIO_FE (GPIO_BASE + 0x0e) +#define GPIO_PULL_UP (GPIO_BASE + 0x10) +#define GPIO_AF (GPIO_BASE + 0x12) +#define GPIO_LT (GPIO_BASE + 0x16) + +#define OFFSET(gpio) (0xff & (1 << (gpio)) ? 1 : 0) + +struct stmpe_gpio_chip { + struct gpio_chip chip; + struct stmpe_client_info *ci; +}; + +static void stmpe_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) +{ + struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip); + struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci; + int ret; + u8 val; + + ci->read_reg(ci->stmpe, GPIO_MP + OFFSET(gpio), &val); + + val |= 1 << (gpio % 8); + + if (value) + ret = ci->write_reg(ci->stmpe, GPIO_SET + OFFSET(gpio), val); + else + ret = ci->write_reg(ci->stmpe, GPIO_CLR + OFFSET(gpio), val); + + if (ret) + dev_err(chip->dev, "write failed!\n"); +} + +static int stmpe_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ + struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip); + struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci; + int ret; + u8 val; + + ci->read_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), &val); + val &= ~(1 << (gpio % 8)); + ret = ci->write_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), val); + + if (ret) + dev_err(chip->dev, "couldn't change direction. Write failed!\n"); + + return ret; +} + +static int stmpe_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) +{ + struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip); + struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci; + int ret; + u8 val; + + ci->read_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), &val); + val |= 1 << (gpio % 8); + ret = ci->write_reg(ci->stmpe, GPIO_SET_DIR + OFFSET(gpio), val); + + stmpe_gpio_set_value(chip, gpio, value); + + if (ret) + dev_err(chip->dev, "couldn't change direction. Write failed!\n"); + + return ret; +} + +static int stmpe_gpio_get_value(struct gpio_chip *chip, unsigned gpio) +{ + struct stmpe_gpio_chip *stmpegpio = container_of(chip, struct stmpe_gpio_chip, chip); + struct stmpe_client_info *ci = (struct stmpe_client_info *)stmpegpio->ci; + u8 val; + int ret; + + ret = ci->read_reg(ci->stmpe, GPIO_MP + OFFSET(gpio), &val); + + if (ret) + dev_err(chip->dev, "read failed\n"); + + return val & (1 << (gpio % 8)) ? 1 : 0; +} + +static struct gpio_ops stmpe_gpio_ops = { + .direction_input = stmpe_gpio_direction_input, + .direction_output = stmpe_gpio_direction_output, + .get = stmpe_gpio_get_value, + .set = stmpe_gpio_set_value, +}; + +static int stmpe_gpio_probe(struct device_d *dev) +{ + struct stmpe_gpio_chip *stmpegpio; + struct stmpe_client_info *ci; + int ret; + + stmpegpio = xzalloc(sizeof(*stmpegpio)); + + stmpegpio->chip.ops = &stmpe_gpio_ops; + stmpegpio->ci = dev->platform_data; + + ci = (struct stmpe_client_info *)stmpegpio->ci; + + if (ci->stmpe->pdata->gpio_base) + stmpegpio->chip.base = ci->stmpe->pdata->gpio_base; + else + stmpegpio->chip.base = -1; + stmpegpio->chip.ngpio = 16; + stmpegpio->chip.dev = dev; + + ret = gpiochip_add(&stmpegpio->chip); + + if (ret) { + dev_err(dev, "couldn't add gpiochip\n"); + return ret; + } + + dev_info(dev, "probed stmpe gpiochip%d with base %d\n", dev->id, stmpegpio->chip.base); + return 0; +} + +static struct driver_d stmpe_gpio_driver = { + .name = "stmpe-gpio", + .probe = stmpe_gpio_probe, +}; + +static int stmpe_gpio_add(void) +{ + return register_driver(&stmpe_gpio_driver); +} +coredevice_initcall(stmpe_gpio_add); diff --git a/drivers/gpio/gpio.c b/drivers/gpio/gpio.c new file mode 100644 index 0000000000..6ad8d274e7 --- /dev/null +++ b/drivers/gpio/gpio.c @@ -0,0 +1,134 @@ +#include <common.h> +#include <gpio.h> +#include <errno.h> + +static LIST_HEAD(chip_list); + +#define ARCH_NR_GPIOS 256 + +static struct gpio_chip *gpio_desc[ARCH_NR_GPIOS]; + +static int gpio_is_valid(unsigned gpio) +{ + if (gpio < ARCH_NR_GPIOS) + return 1; + return 0; +} + +void gpio_set_value(unsigned gpio, int value) +{ + struct gpio_chip *chip = gpio_desc[gpio]; + + if (!gpio_is_valid(gpio)) + return; + if (!chip) + return; + if (!chip->ops->set) + return; + chip->ops->set(chip, gpio - chip->base, value); +} +EXPORT_SYMBOL(gpio_set_value); + +int gpio_get_value(unsigned gpio) +{ + struct gpio_chip *chip = gpio_desc[gpio]; + + if (!gpio_is_valid(gpio)) + return -EINVAL; + if (!chip) + return -ENODEV; + if (!chip->ops->get) + return -ENOSYS; + return chip->ops->get(chip, gpio - chip->base); +} +EXPORT_SYMBOL(gpio_get_value); + +int gpio_direction_output(unsigned gpio, int value) +{ + struct gpio_chip *chip = gpio_desc[gpio]; + + if (!gpio_is_valid(gpio)) + return -EINVAL; + if (!chip) + return -ENODEV; + if (!chip->ops->direction_output) + return -ENOSYS; + return chip->ops->direction_output(chip, gpio - chip->base, value); +} +EXPORT_SYMBOL(gpio_direction_output); + +int gpio_direction_input(unsigned gpio) +{ + struct gpio_chip *chip = gpio_desc[gpio]; + + if (!gpio_is_valid(gpio)) + return -EINVAL; + if (!chip) + return -ENODEV; + if (!chip->ops->direction_input) + return -ENOSYS; + return chip->ops->direction_input(chip, gpio - chip->base); +} +EXPORT_SYMBOL(gpio_direction_input); + +static int gpiochip_find_base(int start, int ngpio) +{ + int i; + int spare = 0; + int base = -ENOSPC; + + if (start < 0) + start = 0; + + for (i = start; i < ARCH_NR_GPIOS; i++) { + struct gpio_chip *chip = gpio_desc[i]; + + if (!chip) { + spare++; + if (spare == ngpio) { + base = i + 1 - ngpio; + break; + } + } else { + spare = 0; + i += chip->ngpio - 1; + } + } + + if (gpio_is_valid(base)) + debug("%s: found new base at %d\n", __func__, base); + return base; +} + +int gpiochip_add(struct gpio_chip *chip) +{ + int base, i; + + base = gpiochip_find_base(chip->base, chip->ngpio); + if (base < 0) + return base; + + if (chip->base >= 0 && chip->base != base) + return -EBUSY; + + chip->base = base; + + list_add_tail(&chip->list, &chip_list); + + for (i = chip->base; i < chip->base + chip->ngpio; i++) + gpio_desc[i] = chip; + + return 0; +} + +int gpio_get_num(struct device_d *dev, int gpio) +{ + struct gpio_chip *chip; + + list_for_each_entry(chip, &chip_list, list) { + if (chip->dev == dev) + return chip->base + gpio; + } + + return -ENODEV; +} diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 1ce5c00276..3f998eafa5 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -5,8 +5,8 @@ menu "I2C Hardware Bus support" config I2C_IMX - bool "i.MX I2C Master driver" - depends on ARCH_IMX && !ARCH_IMX1 + bool "MPC85xx/i.MX I2C Master driver" + depends on (ARCH_IMX && !ARCH_IMX1) || ARCH_MPC85XX config I2C_OMAP bool "OMAP I2C Master driver" diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index da6218f43c..60182042db 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1,4 +1,5 @@ /* + * Copyright 2012 GE Intelligent Platforms, Inc * Copyright (C) 2002 Motorola GSG-China * 2009 Marc Kleine-Budde, Pengutronix * @@ -22,7 +23,8 @@ * * Desc.: * Implementation of I2C Adapter/Algorithm Driver - * for I2C Bus integrated in Freescale i.MX/MXC processors + * for I2C Bus integrated in Freescale i.MX/MXC processors and + * 85xx processors. * * Derived from Motorola GSG China I2C example driver * @@ -36,7 +38,6 @@ #include <clock.h> #include <common.h> #include <driver.h> -#include <gpio.h> #include <init.h> #include <malloc.h> #include <types.h> @@ -46,23 +47,23 @@ #include <io.h> #include <i2c/i2c.h> -#include <mach/generic.h> #include <mach/clock.h> /* This will be the driver name */ -#define DRIVER_NAME "i2c-imx" +#define DRIVER_NAME "i2c-fsl" /* Default value */ -#define IMX_I2C_BIT_RATE 100000 /* 100kHz */ +#define FSL_I2C_BIT_RATE 100000 /* 100kHz */ -/* IMX I2C registers */ -#define IMX_I2C_IADR 0x00 /* i2c slave address */ -#define IMX_I2C_IFDR 0x04 /* i2c frequency divider */ -#define IMX_I2C_I2CR 0x08 /* i2c control */ -#define IMX_I2C_I2SR 0x0C /* i2c status */ -#define IMX_I2C_I2DR 0x10 /* i2c transfer data */ +/* FSL I2C registers */ +#define FSL_I2C_IADR 0x00 /* i2c slave address */ +#define FSL_I2C_IFDR 0x04 /* i2c frequency divider */ +#define FSL_I2C_I2CR 0x08 /* i2c control */ +#define FSL_I2C_I2SR 0x0C /* i2c status */ +#define FSL_I2C_I2DR 0x10 /* i2c transfer data */ +#define FSL_I2C_DFSRR 0x14 /* i2c digital filter sampling rate */ -/* Bits of IMX I2C registers */ +/* Bits of FSL I2C registers */ #define I2SR_RXAK 0x01 #define I2SR_IIF 0x02 #define I2SR_SRW 0x04 @@ -85,6 +86,7 @@ * * Duplicated divider values removed from list */ +#ifndef CONFIG_PPC static u16 i2c_clk_div[50][2] = { { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, @@ -100,24 +102,26 @@ static u16 i2c_clk_div[50][2] = { { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, { 3072, 0x1E }, { 3840, 0x1F } }; +#endif -struct imx_i2c_struct { +struct fsl_i2c_struct { void __iomem *base; struct i2c_adapter adapter; unsigned int disable_delay; int stopped; - unsigned int ifdr; /* IMX_I2C_IFDR */ + unsigned int ifdr; /* FSL_I2C_IFDR */ + unsigned int dfsrr; /* FSL_I2C_DFSRR */ }; -#define to_imx_i2c_struct(a) container_of(a, struct imx_i2c_struct, adapter) +#define to_fsl_i2c_struct(a) container_of(a, struct fsl_i2c_struct, adapter) #ifdef CONFIG_I2C_DEBUG -static void i2c_imx_dump_reg(struct i2c_adapter *adapter) +static void i2c_fsl_dump_reg(struct i2c_adapter *adapter) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); u32 reg_cr, reg_sr; - reg_cr = readb(i2c_imx->base + IMX_I2C_I2CR); - reg_sr = readb(i2c_imx->base + IMX_I2C_I2SR); + reg_cr = readb(i2c_fsl->base + FSL_I2C_I2CR); + reg_sr = readb(i2c_fsl->base + FSL_I2C_I2SR); dev_dbg(adapter->dev, "CONTROL:\t" "IEN =%d, IIEN=%d, MSTA=%d, MTX =%d, TXAK=%d, RSTA=%d\n", @@ -133,22 +137,22 @@ static void i2c_imx_dump_reg(struct i2c_adapter *adapter) (reg_sr & I2SR_RXAK ? 1 : 0)); } #else -static inline void i2c_imx_dump_reg(struct i2c_adapter *adapter) +static inline void i2c_fsl_dump_reg(struct i2c_adapter *adapter) { return; } #endif -static int i2c_imx_bus_busy(struct i2c_adapter *adapter, int for_busy) +static int i2c_fsl_bus_busy(struct i2c_adapter *adapter, int for_busy) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); - void __iomem *base = i2c_imx->base; + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); + void __iomem *base = i2c_fsl->base; uint64_t start; unsigned int temp; start = get_time_ns(); while (1) { - temp = readb(base + IMX_I2C_I2SR); + temp = readb(base + FSL_I2C_I2SR); if (for_busy && (temp & I2SR_IBB)) break; if (!for_busy && !(temp & I2SR_IBB)) @@ -164,15 +168,15 @@ static int i2c_imx_bus_busy(struct i2c_adapter *adapter, int for_busy) return 0; } -static int i2c_imx_trx_complete(struct i2c_adapter *adapter) +static int i2c_fsl_trx_complete(struct i2c_adapter *adapter) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); - void __iomem *base = i2c_imx->base; + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); + void __iomem *base = i2c_fsl->base; uint64_t start; start = get_time_ns(); while (1) { - unsigned int reg = readb(base + IMX_I2C_I2SR); + unsigned int reg = readb(base + FSL_I2C_I2SR); if (reg & I2SR_IIF) break; @@ -181,20 +185,20 @@ static int i2c_imx_trx_complete(struct i2c_adapter *adapter) return -EIO; } } - writeb(0, base + IMX_I2C_I2SR); + writeb(0, base + FSL_I2C_I2SR); return 0; } -static int i2c_imx_acked(struct i2c_adapter *adapter) +static int i2c_fsl_acked(struct i2c_adapter *adapter) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); - void __iomem *base = i2c_imx->base; + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); + void __iomem *base = i2c_fsl->base; uint64_t start; start = get_time_ns(); while (1) { - unsigned int reg = readb(base + IMX_I2C_I2SR); + unsigned int reg = readb(base + FSL_I2C_I2SR); if (!(reg & I2SR_RXAK)) break; @@ -207,71 +211,137 @@ static int i2c_imx_acked(struct i2c_adapter *adapter) return 0; } -static int i2c_imx_start(struct i2c_adapter *adapter) +static int i2c_fsl_start(struct i2c_adapter *adapter) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); - void __iomem *base = i2c_imx->base; + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); + void __iomem *base = i2c_fsl->base; unsigned int temp = 0; int result; - writeb(i2c_imx->ifdr, base + IMX_I2C_IFDR); + writeb(i2c_fsl->ifdr, base + FSL_I2C_IFDR); + if (i2c_fsl->dfsrr != -1) + writeb(i2c_fsl->dfsrr, base + FSL_I2C_DFSRR); + /* Enable I2C controller */ - writeb(0, base + IMX_I2C_I2SR); - writeb(I2CR_IEN, base + IMX_I2C_I2CR); + writeb(0, base + FSL_I2C_I2SR); + writeb(I2CR_IEN, base + FSL_I2C_I2CR); /* Wait controller to be stable */ udelay(100); /* Start I2C transaction */ - temp = readb(base + IMX_I2C_I2CR); + temp = readb(base + FSL_I2C_I2CR); temp |= I2CR_MSTA; - writeb(temp, base + IMX_I2C_I2CR); + writeb(temp, base + FSL_I2C_I2CR); - result = i2c_imx_bus_busy(adapter, 1); + result = i2c_fsl_bus_busy(adapter, 1); if (result) return result; - i2c_imx->stopped = 0; + i2c_fsl->stopped = 0; temp |= I2CR_MTX | I2CR_TXAK; - writeb(temp, base + IMX_I2C_I2CR); + writeb(temp, base + FSL_I2C_I2CR); return result; } -static void i2c_imx_stop(struct i2c_adapter *adapter) +static void i2c_fsl_stop(struct i2c_adapter *adapter) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); - void __iomem *base = i2c_imx->base; + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); + void __iomem *base = i2c_fsl->base; unsigned int temp = 0; - if (!i2c_imx->stopped) { + if (!i2c_fsl->stopped) { /* Stop I2C transaction */ - temp = readb(base + IMX_I2C_I2CR); + temp = readb(base + FSL_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); - writeb(temp, base + IMX_I2C_I2CR); + writeb(temp, base + FSL_I2C_I2CR); /* wait for the stop condition to be send, otherwise the i2c * controller is disabled before the STOP is sent completely */ - i2c_imx->stopped = i2c_imx_bus_busy(adapter, 0) ? 0 : 1; - } - if (cpu_is_mx1()) { - /* - * This delay caused by an i.MXL hardware bug. - * If no (or too short) delay, no "STOP" bit will be generated. - */ - udelay(i2c_imx->disable_delay); + i2c_fsl->stopped = i2c_fsl_bus_busy(adapter, 0) ? 0 : 1; } - if (!i2c_imx->stopped) { - i2c_imx_bus_busy(adapter, 0); - i2c_imx->stopped = 1; + if (!i2c_fsl->stopped) { + i2c_fsl_bus_busy(adapter, 0); + i2c_fsl->stopped = 1; } /* Disable I2C controller, and force our state to stopped */ - writeb(0, base + IMX_I2C_I2CR); + writeb(0, base + FSL_I2C_I2CR); } -static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, +#ifdef CONFIG_PPC +static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl, + unsigned int rate) +{ + void __iomem *base; + unsigned int i2c_clk; + unsigned short divider; + /* + * We want to choose an FDR/DFSR that generates an I2C bus speed that + * is equal to or lower than the requested speed. That means that we + * want the first divider that is equal to or greater than the + * calculated divider. + */ + u8 dfsr, fdr; + /* a, b and dfsr matches identifiers A,B and C respectively in AN2919 */ + unsigned short a, b, ga, gb; + unsigned long c_div, est_div; + + fdr = 0x31; /* Default if no FDR found */ + base = i2c_fsl->base; + i2c_clk = fsl_get_i2c_freq(); + divider = min((unsigned short)(i2c_clk / rate), (unsigned short) -1); + + /* + * Condition 1: dfsr <= 50ns/T (T=period of I2C source clock in ns). + * or (dfsr * T) <= 50ns. + * Translate to dfsr = 5 * Frequency / 100,000,000 + */ + dfsr = (5 * (i2c_clk / 1000)) / 100000; + dev_dbg(i2c_fsl->adapter.dev, + "<%s> requested speed:%d, i2c_clk:%d\n", __func__, + rate, i2c_clk); + if (!dfsr) + dfsr = 1; + + est_div = ~0; + for (ga = 0x4, a = 10; a <= 30; ga++, a += 2) { + for (gb = 0; gb < 8; gb++) { + b = 16 << gb; + c_div = b * (a + ((3*dfsr)/b)*2); + if ((c_div > divider) && (c_div < est_div)) { + unsigned short bin_gb, bin_ga; + + est_div = c_div; + bin_gb = gb << 2; + bin_ga = (ga & 0x3) | ((ga & 0x4) << 3); + fdr = bin_gb | bin_ga; + rate = i2c_clk / est_div; + dev_dbg(i2c_fsl->adapter.dev, + "FDR:0x%.2x, div:%ld, ga:0x%x, gb:0x%x," + " a:%d, b:%d, speed:%d\n", fdr, est_div, + ga, gb, a, b, rate); + /* Condition 2 not accounted for */ + dev_dbg(i2c_fsl->adapter.dev, + "Tr <= %d ns\n", (b - 3 * dfsr) * + 1000000 / (i2c_clk / 1000)); + } + } + if (a == 20) + a += 2; + if (a == 24) + a += 4; + } + dev_dbg(i2c_fsl->adapter.dev, + "divider:%d, est_div:%ld, DFSR:%d\n", divider, est_div, dfsr); + dev_dbg(i2c_fsl->adapter.dev, "FDR:0x%.2x, speed:%d\n", fdr, rate); + i2c_fsl->ifdr = fdr; + i2c_fsl->dfsrr = dfsr; +} +#else +static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl, unsigned int rate) { unsigned int i2c_clk_rate; @@ -279,7 +349,7 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, int i; /* Divider value calculation */ - i2c_clk_rate = imx_get_i2cclk(); + i2c_clk_rate = fsl_get_i2cclk(); div = (i2c_clk_rate + rate - 1) / rate; if (div < i2c_clk_div[0][0]) i = 0; @@ -290,7 +360,7 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, ; /* Store divider value */ - i2c_imx->ifdr = i2c_clk_div[i][1]; + i2c_fsl->ifdr = i2c_clk_div[i][1]; /* * There dummy delay is calculated. @@ -298,20 +368,21 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, * This delay is used in I2C bus disable function * to fix chip hardware bug. */ - i2c_imx->disable_delay = + i2c_fsl->disable_delay = (500000U * i2c_clk_div[i][0] + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); - dev_dbg(i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", + dev_dbg(i2c_fsl->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", __func__, i2c_clk_rate, div); - dev_dbg(i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", + dev_dbg(i2c_fsl->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", __func__, i2c_clk_div[i][1], i2c_clk_div[i][0]); } +#endif -static int i2c_imx_write(struct i2c_adapter *adapter, struct i2c_msg *msgs) +static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); - void __iomem *base = i2c_imx->base; + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); + void __iomem *base = i2c_fsl->base; int i, result; if ( !(msgs->flags & I2C_M_DATA_ONLY) ) { @@ -320,12 +391,12 @@ static int i2c_imx_write(struct i2c_adapter *adapter, struct i2c_msg *msgs) __func__, msgs->addr << 1); /* write slave address */ - writeb(msgs->addr << 1, base + IMX_I2C_I2DR); + writeb(msgs->addr << 1, base + FSL_I2C_I2DR); - result = i2c_imx_trx_complete(adapter); + result = i2c_fsl_trx_complete(adapter); if (result) return result; - result = i2c_imx_acked(adapter); + result = i2c_fsl_acked(adapter); if (result) return result; } @@ -335,27 +406,27 @@ static int i2c_imx_write(struct i2c_adapter *adapter, struct i2c_msg *msgs) dev_dbg(adapter->dev, "<%s> write byte: B%d=0x%02X\n", __func__, i, msgs->buf[i]); - writeb(msgs->buf[i], base + IMX_I2C_I2DR); + writeb(msgs->buf[i], base + FSL_I2C_I2DR); - result = i2c_imx_trx_complete(adapter); + result = i2c_fsl_trx_complete(adapter); if (result) return result; - result = i2c_imx_acked(adapter); + result = i2c_fsl_acked(adapter); if (result) return result; } return 0; } -static int i2c_imx_read(struct i2c_adapter *adapter, struct i2c_msg *msgs) +static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); - void __iomem *base = i2c_imx->base; + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); + void __iomem *base = i2c_fsl->base; int i, result; unsigned int temp; /* clear IIF */ - writeb(0x0, base + IMX_I2C_I2SR); + writeb(0x0, base + FSL_I2C_I2SR); if ( !(msgs->flags & I2C_M_DATA_ONLY) ) { dev_dbg(adapter->dev, @@ -363,28 +434,28 @@ static int i2c_imx_read(struct i2c_adapter *adapter, struct i2c_msg *msgs) __func__, (msgs->addr << 1) | 0x01); /* write slave address */ - writeb((msgs->addr << 1) | 0x01, base + IMX_I2C_I2DR); + writeb((msgs->addr << 1) | 0x01, base + FSL_I2C_I2DR); - result = i2c_imx_trx_complete(adapter); + result = i2c_fsl_trx_complete(adapter); if (result) return result; - result = i2c_imx_acked(adapter); + result = i2c_fsl_acked(adapter); if (result) return result; } /* setup bus to read data */ - temp = readb(base + IMX_I2C_I2CR); + temp = readb(base + FSL_I2C_I2CR); temp &= ~I2CR_MTX; if (msgs->len - 1) temp &= ~I2CR_TXAK; - writeb(temp, base + IMX_I2C_I2CR); + writeb(temp, base + FSL_I2C_I2CR); - readb(base + IMX_I2C_I2DR); /* dummy read */ + readb(base + FSL_I2C_I2DR); /* dummy read */ /* read data */ for (i = 0; i < msgs->len; i++) { - result = i2c_imx_trx_complete(adapter); + result = i2c_fsl_trx_complete(adapter); if (result) return result; @@ -393,23 +464,23 @@ static int i2c_imx_read(struct i2c_adapter *adapter, struct i2c_msg *msgs) * It must generate STOP before read I2DR to prevent * controller from generating another clock cycle */ - temp = readb(base + IMX_I2C_I2CR); + temp = readb(base + FSL_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); - writeb(temp, base + IMX_I2C_I2CR); + writeb(temp, base + FSL_I2C_I2CR); /* * adding this delay helps on low bitrates */ - udelay(i2c_imx->disable_delay); + udelay(i2c_fsl->disable_delay); - i2c_imx_bus_busy(adapter, 0); - i2c_imx->stopped = 1; + i2c_fsl_bus_busy(adapter, 0); + i2c_fsl->stopped = 1; } else if (i == (msgs->len - 2)) { - temp = readb(base + IMX_I2C_I2CR); + temp = readb(base + FSL_I2C_I2CR); temp |= I2CR_TXAK; - writeb(temp, base + IMX_I2C_I2CR); + writeb(temp, base + FSL_I2C_I2CR); } - msgs->buf[i] = readb(base + IMX_I2C_I2DR); + msgs->buf[i] = readb(base + FSL_I2C_I2DR); dev_dbg(adapter->dev, "<%s> read byte: B%d=0x%02X\n", __func__, i, msgs->buf[i]); @@ -417,76 +488,77 @@ static int i2c_imx_read(struct i2c_adapter *adapter, struct i2c_msg *msgs) return 0; } -static int i2c_imx_xfer(struct i2c_adapter *adapter, +static int i2c_fsl_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { - struct imx_i2c_struct *i2c_imx = to_imx_i2c_struct(adapter); - void __iomem *base = i2c_imx->base; + struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter); + void __iomem *base = i2c_fsl->base; unsigned int i, temp; int result; /* Start I2C transfer */ - result = i2c_imx_start(adapter); + result = i2c_fsl_start(adapter); if (result) goto fail0; /* read/write data */ for (i = 0; i < num; i++) { if (i && !(msgs[i].flags & I2C_M_DATA_ONLY)) { - temp = readb(base + IMX_I2C_I2CR); + temp = readb(base + FSL_I2C_I2CR); temp |= I2CR_RSTA; - writeb(temp, base + IMX_I2C_I2CR); + writeb(temp, base + FSL_I2C_I2CR); - result = i2c_imx_bus_busy(adapter, 1); + result = i2c_fsl_bus_busy(adapter, 1); if (result) goto fail0; } - i2c_imx_dump_reg(adapter); + i2c_fsl_dump_reg(adapter); /* write/read data */ if (msgs[i].flags & I2C_M_RD) - result = i2c_imx_read(adapter, &msgs[i]); + result = i2c_fsl_read(adapter, &msgs[i]); else - result = i2c_imx_write(adapter, &msgs[i]); + result = i2c_fsl_write(adapter, &msgs[i]); if (result) goto fail0; } fail0: /* Stop I2C transfer */ - i2c_imx_stop(adapter); + i2c_fsl_stop(adapter); return (result < 0) ? result : num; } -static int __init i2c_imx_probe(struct device_d *pdev) +static int __init i2c_fsl_probe(struct device_d *pdev) { - struct imx_i2c_struct *i2c_imx; + struct fsl_i2c_struct *i2c_fsl; struct i2c_platform_data *pdata; int ret; pdata = pdev->platform_data; - i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL); + i2c_fsl = kzalloc(sizeof(struct fsl_i2c_struct), GFP_KERNEL); - /* Setup i2c_imx driver structure */ - i2c_imx->adapter.master_xfer = i2c_imx_xfer; - i2c_imx->adapter.nr = pdev->id; - i2c_imx->adapter.dev = pdev; - i2c_imx->base = dev_request_mem_region(pdev, 0); + /* Setup i2c_fsl driver structure */ + i2c_fsl->adapter.master_xfer = i2c_fsl_xfer; + i2c_fsl->adapter.nr = pdev->id; + i2c_fsl->adapter.dev = pdev; + i2c_fsl->base = dev_request_mem_region(pdev, 0); + i2c_fsl->dfsrr = -1; /* Set up clock divider */ if (pdata && pdata->bitrate) - i2c_imx_set_clk(i2c_imx, pdata->bitrate); + i2c_fsl_set_clk(i2c_fsl, pdata->bitrate); else - i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE); + i2c_fsl_set_clk(i2c_fsl, FSL_I2C_BIT_RATE); /* Set up chip registers to defaults */ - writeb(0, i2c_imx->base + IMX_I2C_I2CR); - writeb(0, i2c_imx->base + IMX_I2C_I2SR); + writeb(0, i2c_fsl->base + FSL_I2C_I2CR); + writeb(0, i2c_fsl->base + FSL_I2C_I2SR); /* Add I2C adapter */ - ret = i2c_add_numbered_adapter(&i2c_imx->adapter); + ret = i2c_add_numbered_adapter(&i2c_fsl->adapter); if (ret < 0) { dev_err(pdev, "registration failed\n"); goto fail; @@ -495,17 +567,17 @@ static int __init i2c_imx_probe(struct device_d *pdev) return 0; fail: - kfree(i2c_imx); + kfree(i2c_fsl); return ret; } -static struct driver_d i2c_imx_driver = { - .probe = i2c_imx_probe, +static struct driver_d i2c_fsl_driver = { + .probe = i2c_fsl_probe, .name = DRIVER_NAME, }; -static int __init i2c_adap_imx_init(void) +static int __init i2c_adap_fsl_init(void) { - return register_driver(&i2c_imx_driver); + return register_driver(&i2c_fsl_driver); } -device_initcall(i2c_adap_imx_init); +device_initcall(i2c_adap_fsl_init); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index af67935092..20eef86e39 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -33,4 +33,8 @@ config I2C_TWL6030 select I2C_TWLCORE bool "TWL6030 driver" +config I2C_STMPE + depends on I2C + bool "STMPE-i2c driver" + endmenu diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index e11223b1f9..792ae2da8f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_I2C_LP3972) += lp3972.o obj-$(CONFIG_I2C_TWLCORE) += twl-core.o obj-$(CONFIG_I2C_TWL4030) += twl4030.o obj-$(CONFIG_I2C_TWL6030) += twl6030.o +obj-$(CONFIG_I2C_STMPE) += stmpe-i2c.o diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c index 8bb0d00f8f..704446d019 100644 --- a/drivers/mfd/mc13xxx.c +++ b/drivers/mfd/mc13xxx.c @@ -32,6 +32,21 @@ #define DRIVERNAME "mc13xxx" +enum mc13xxx_mode { + MC13XXX_MODE_I2C, + MC13XXX_MODE_SPI, +}; + +struct mc13xxx { + struct cdev cdev; + union { + struct i2c_client *client; + struct spi_device *spi; + }; + enum mc13xxx_mode mode; + int revision; +}; + #define to_mc13xxx(a) container_of(a, struct mc13xxx, cdev) static struct mc13xxx *mc_dev; @@ -42,6 +57,12 @@ struct mc13xxx *mc13xxx_get(void) } EXPORT_SYMBOL(mc13xxx_get); +int mc13xxx_revision(struct mc13xxx *mc13xxx) +{ + return mc13xxx->revision; +} +EXPORT_SYMBOL(mc13xxx_revision); + #ifdef CONFIG_SPI static int spi_rw(struct spi_device *spi, void * buf, size_t len) { @@ -231,7 +252,7 @@ static struct mc13892_rev mc13892_revisions[] = { static int mc13xxx_query_revision(struct mc13xxx *mc13xxx) { unsigned int rev_id; - char *chipname, *revstr; + char *chipname, revstr[5]; int rev, i; mc13xxx_reg_read(mc13xxx, MC13XXX_REG_IDENTIFICATION, &rev_id); @@ -244,9 +265,9 @@ static int mc13xxx_query_revision(struct mc13xxx *mc13xxx) /* Ver 0.2 is actually 3.2a. Report as 3.2 */ if (rev == 0x02) { rev = 0x32; - revstr = "3.2a"; + strcpy(revstr, "3.2a"); } else - revstr = asprintf("%d.%d", rev / 0x10, rev % 10); + sprintf(revstr, "%d.%d", rev / 0x10, rev % 10); break; case 7: chipname = "MC13892"; @@ -258,12 +279,12 @@ static int mc13xxx_query_revision(struct mc13xxx *mc13xxx) return -EINVAL; rev = mc13892_revisions[i].rev; - revstr = mc13892_revisions[i].revstr; + strcpy(revstr, mc13892_revisions[i].revstr); if (rev == MC13892_REVISION_2_0) { if ((rev_id >> 9) & 0x3) { rev = MC13892_REVISION_2_0a; - revstr = "2.0a"; + strcpy(revstr, "2.0a"); } } break; diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c new file mode 100644 index 0000000000..4af8b7b88c --- /dev/null +++ b/drivers/mfd/stmpe-i2c.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2012 Pengutronix + * Steffen Trumtrar <s.trumtrar@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 <init.h> +#include <driver.h> +#include <xfuncs.h> +#include <errno.h> + +#include <i2c/i2c.h> +#include <mfd/stmpe-i2c.h> + +#define DRIVERNAME "stmpe-i2c" + +#define to_stmpe(a) container_of(a, struct stmpe, cdev) + +int stmpe_reg_read(struct stmpe *stmpe, u32 reg, u8 *val) +{ + int ret; + + ret = i2c_read_reg(stmpe->client, reg, val, 1); + + return ret == 1 ? 0 : ret; +} +EXPORT_SYMBOL(stmpe_reg_read) + +int stmpe_reg_write(struct stmpe *stmpe, u32 reg, u8 val) +{ + int ret; + + ret = i2c_write_reg(stmpe->client, reg, &val, 1); + + return ret == 1 ? 0 : ret; +} +EXPORT_SYMBOL(stmpe_reg_write) + +int stmpe_set_bits(struct stmpe *stmpe, u32 reg, u8 mask, u8 val) +{ + u8 tmp; + int err; + + err = stmpe_reg_read(stmpe, reg, &tmp); + tmp = (tmp & ~mask) | val; + + if (!err) + err = stmpe_reg_write(stmpe, reg, tmp); + + return err; +} +EXPORT_SYMBOL(stmpe_set_bits); + +static ssize_t stmpe_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) +{ + struct stmpe *stmpe = to_stmpe(cdev); + u8 *buf = _buf; + size_t i = count; + int err; + + while (i) { + err = stmpe_reg_read(stmpe, offset, buf); + if (err) + return (ssize_t)err; + buf++; + i--; + offset++; + } + + return count; +} + +static ssize_t stmpe_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags) +{ + struct stmpe *stmpe = to_stmpe(cdev); + const u8 *buf = _buf; + size_t i = count; + int err; + + while (i) { + err = stmpe_reg_write(stmpe, offset, *buf); + if (err) + return (ssize_t)err; + buf++; + i--; + offset++; + } + + return count; +} + +static struct file_operations stmpe_fops = { + .lseek = dev_lseek_default, + .read = stmpe_read, + .write = stmpe_write, +}; + +static int stmpe_probe(struct device_d *dev) +{ + struct stmpe_platform_data *pdata = dev->platform_data; + struct stmpe *stmpe_dev; + struct stmpe_client_info *i2c_ci; + + if (!pdata) { + dev_dbg(dev, "no platform data\n"); + return -ENODEV; + } + + stmpe_dev = xzalloc(sizeof(struct stmpe)); + stmpe_dev->cdev.name = DRIVERNAME; + stmpe_dev->client = to_i2c_client(dev); + stmpe_dev->cdev.size = 191; /* 191 known registers */ + stmpe_dev->cdev.dev = dev; + stmpe_dev->cdev.ops = &stmpe_fops; + stmpe_dev->pdata = pdata; + dev->priv = stmpe_dev; + + i2c_ci = xzalloc(sizeof(struct stmpe_client_info)); + i2c_ci->stmpe = stmpe_dev; + i2c_ci->read_reg = stmpe_reg_read; + i2c_ci->write_reg = stmpe_reg_write; + + if (pdata->blocks &= STMPE_BLOCK_GPIO) + add_generic_device("stmpe-gpio", DEVICE_ID_DYNAMIC, NULL, 0, 0, IORESOURCE_MEM, i2c_ci); + + devfs_create(&stmpe_dev->cdev); + + return 0; +} + +static struct driver_d stmpe_driver = { + .name = DRIVERNAME, + .probe = stmpe_probe, +}; + +static int stmpe_init(void) +{ + register_driver(&stmpe_driver); + return 0; +} + +device_initcall(stmpe_init); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig new file mode 100644 index 0000000000..c3d31ec9a2 --- /dev/null +++ b/drivers/misc/Kconfig @@ -0,0 +1,17 @@ +# +# Misc strange devices +# + +menuconfig MISC_DEVICES + bool "Misc devices " + help + Add support for misc strange devices + +if MISC_DEVICES + +config JTAG + tristate "JTAG Bitbang driver" + help + Controls JTAG chains connected to I/O pins + +endif # MISC_DEVICES diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile new file mode 100644 index 0000000000..b0855777a9 --- /dev/null +++ b/drivers/misc/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for misc devices that really don't fit anywhere else. +# + +obj-$(CONFIG_JTAG) += jtag.o diff --git a/drivers/misc/jtag.c b/drivers/misc/jtag.c new file mode 100644 index 0000000000..99fd081b31 --- /dev/null +++ b/drivers/misc/jtag.c @@ -0,0 +1,392 @@ +/* + * drivers/misc/jtag.c - More infos in include/jtag.h + * + * Written Aug 2009 by Davide Rizzo <elpa.rizzo@gmail.com> + * + * Ported to barebox Jul 2012 by + * Wjatscheslaw Stoljarski <wjatscheslaw.stoljarski@kiwigrid.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <fs.h> +#include <errno.h> +//#include <linux/list.h> +#include <jtag.h> +#include <gpio.h> +#include <driver.h> +#include <malloc.h> +#include <common.h> +#include <init.h> +#include <ioctl.h> + +#define VERSION_MAJ 1 +#define VERSION_MIN 0 + +/* Max devices in the jtag chain */ +#define MAX_DEVICES 16 + +struct jtag_info { + struct jtag_platdata *pdata; + struct cdev cdev; + unsigned int devices; /* Number of devices found in the jtag chain */ + /* Instruction register length of every device in the chain */ + unsigned int ir_len[MAX_DEVICES]; /* [devices] */ +}; + +static const unsigned long bypass = 0xFFFFFFFF; + +static void pulse_tms0(const struct jtag_platdata *pdata) +{ + gpio_set_value(pdata->gpio_tms, 0); + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); +} + +static void pulse_tms1(const struct jtag_platdata *pdata) +{ + gpio_set_value(pdata->gpio_tms, 1); + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); +} + +static void jtag_reset(const struct jtag_platdata *pdata) +{ + gpio_set_value(pdata->gpio_tms, 1); + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); +} + +static void jtag_output(const struct jtag_platdata *pdata, + const unsigned long *data, unsigned int bitlen, int notlast) +{ + unsigned int a; + unsigned long mask; + gpio_set_value(pdata->gpio_tms, 0); + while (bitlen > 0) { + for (a = *data++, mask = 0x00000001; mask != 0 && bitlen > 0; + mask <<= 1, bitlen--) { + gpio_set_value(pdata->gpio_tdo, (a & mask) ? 1 : 0); + if ((bitlen == 1) && !notlast) + gpio_set_value(pdata->gpio_tms, 1); + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); + } + } +} + +static int jtag_ioctl(struct cdev *inode, int cmd, void *arg) +{ + int ret = 0; + struct jtag_info *info = (struct jtag_info *)inode->priv; + int devices = info->devices; + struct jtag_cmd *jcmd = (struct jtag_cmd *)arg; + struct jtag_platdata *pdata = info->pdata; + + if (_IOC_TYPE(cmd) != JTAG_IOC_MAGIC) return -ENOTTY; + if (_IOC_NR(cmd) > JTAG_IOC_MAXNR) return -ENOTTY; + + switch (cmd) { + + case JTAG_GET_DEVICES: + /* Returns how many devices found in the chain */ + ret = info->devices; + break; + + case JTAG_GET_ID: + /* Returns ID register of selected device */ + if ((((struct jtag_rd_id *)arg)->device < 0) || + (((struct jtag_rd_id *)arg)->device >= devices)) { + ret = -EINVAL; + break; + } + jtag_reset(pdata); + pulse_tms0(pdata); + pulse_tms1(pdata); + pulse_tms0(pdata); + pulse_tms0(pdata); + while (devices-- > 0) { + unsigned long id = 0; + pulse_tms0(pdata); + if (gpio_get_value(pdata->gpio_tdi)) { + unsigned long mask; + for (id = 1, mask = 0x00000002; (mask != 0); + mask <<= 1) { + pulse_tms0(pdata); + if (gpio_get_value(pdata->gpio_tdi)) + id |= mask; + } + } + if (devices == ((struct jtag_rd_id *)arg)->device) { + ((struct jtag_rd_id *)arg)->id = id; + ret = 0; + break; + } + } + jtag_reset(pdata); + break; + + case JTAG_SET_IR_LENGTH: + /* Sets up IR length of one device */ + if ((jcmd->device >= 0) && (jcmd->device < devices)) + info->ir_len[jcmd->device] = jcmd->bitlen; + else + ret = -EINVAL; + break; + + case JTAG_RESET: + /* Resets all JTAG states */ + jtag_reset(pdata); + break; + + case JTAG_IR_WR: + /* + * Writes Instruction Register + * If device == -1 writes same Instruction Register in + * all devices. + * If device >= 0 writes Instruction Register in selected + * device and loads BYPASS instruction in all others. + */ + if ((jcmd->device < -1) || (jcmd->device >= devices)) { + ret = -EINVAL; + break; + } + pulse_tms0(pdata); + pulse_tms1(pdata); + pulse_tms1(pdata); + pulse_tms0(pdata); + pulse_tms0(pdata); + while (devices-- > 0) { + if ((jcmd->device == -1) || (jcmd->device == devices)) + /* Loads desired instruction */ + jtag_output(pdata, jcmd->data, + info->ir_len[devices], devices); + else + /* Loads BYPASS instruction */ + jtag_output(pdata, &bypass, + info->ir_len[devices], devices); + } + pulse_tms1(pdata); + pulse_tms0(pdata); + break; + + case JTAG_DR_WR: + /* + * Writes Data Register of all devices + * If device == -1 writes same Data Register in all devices. + * If device >= 0 writes Data Register in selected device + * and loads BYPASS instruction in all others. + */ + if ((jcmd->device < -1) || (jcmd->device >= devices)) { + ret = -EINVAL; + break; + } + pulse_tms0(pdata); + pulse_tms1(pdata); + pulse_tms0(pdata); + pulse_tms0(pdata); + while (devices-- > 0) { + if ((jcmd->device == -1) || (devices == jcmd->device)) + /* Loads desired data */ + jtag_output(pdata, jcmd->data, jcmd->bitlen, + devices); + else + /* Loads 1 dummy bit in BYPASS data register */ + jtag_output(pdata, &bypass, 1, devices); + } + pulse_tms1(pdata); + pulse_tms0(pdata); + break; + + case JTAG_DR_RD: + /* Reads data register of selected device */ + if ((jcmd->device < 0) || (jcmd->device >= devices)) + ret = -EINVAL; + else { + unsigned long mask; + int bitlen = jcmd->bitlen; + unsigned long *data = jcmd->data; + pulse_tms0(pdata); + pulse_tms1(pdata); + pulse_tms0(pdata); + pulse_tms0(pdata); + devices -= (jcmd->device + 1); + while (devices-- > 0) + pulse_tms0(pdata); + while (bitlen > 0) { + for (*data = 0, mask = 0x00000001; + (mask != 0) && (bitlen > 0); + mask <<= 1, bitlen--) { + if (bitlen == 1) + pulse_tms1(pdata); + else + pulse_tms0(pdata); + if (gpio_get_value(pdata->gpio_tdi)) + *data |= mask; + } + data++; + } + pulse_tms1(pdata); + pulse_tms0(pdata); + } + break; + + case JTAG_CLK: + /* Generates arg clock pulses */ + gpio_set_value(pdata->gpio_tms, 0); + while ((*(unsigned int *) arg)--) { + gpio_set_value(pdata->gpio_tclk, 0); + gpio_set_value(pdata->gpio_tclk, 1); + } + break; + + default: + ret = -EFAULT; + } + + return ret; +} + +static struct file_operations jtag_operations = { + .ioctl = jtag_ioctl, +}; + +static int jtag_probe(struct device_d *pdev) +{ + int i, ret; + struct jtag_info *info; + struct jtag_platdata *pdata = pdev->platform_data; + + /* Setup gpio pins */ + gpio_direction_output(pdata->gpio_tms, 0); + gpio_direction_output(pdata->gpio_tclk, 1); + gpio_direction_output(pdata->gpio_tdo, 0); + gpio_direction_input(pdata->gpio_tdi); + if (pdata->use_gpio_trst) { + /* + * Keep fixed at 1 because some devices in the chain could + * not use it, to reset chain use jtag_reset() + */ + gpio_direction_output(pdata->gpio_trst, 1); + } + + /* Find how many devices in chain */ + jtag_reset(pdata); + pulse_tms0(pdata); + pulse_tms1(pdata); + pulse_tms1(pdata); + pulse_tms0(pdata); + pulse_tms0(pdata); + gpio_set_value(pdata->gpio_tdo, 1); + /* Fills all IR with bypass instruction */ + for (i = 0; i < 32 * MAX_DEVICES; i++) + pulse_tms0(pdata); + pulse_tms1(pdata); + pulse_tms1(pdata); + pulse_tms1(pdata); + pulse_tms0(pdata); + pulse_tms0(pdata); + gpio_set_value(pdata->gpio_tdo, 0); + /* Fills all 1-bit bypass register with 0 */ + for (i = 0; i < MAX_DEVICES + 2; i++) + pulse_tms0(pdata); + gpio_set_value(pdata->gpio_tdo, 1); + /* Counts chain's bit length */ + for (i = 0; i < MAX_DEVICES + 1; i++) { + pulse_tms0(pdata); + if (gpio_get_value(pdata->gpio_tdi)) + break; + } + dev_notice(pdev, "%d devices found in chain\n", i); + + /* Allocate structure with chain specific infos */ + info = xzalloc(sizeof(struct jtag_info) + sizeof(info->ir_len[0]) * i); + + info->devices = i; + info->pdata = pdata; + pdev->priv = info; + + info->cdev.name = JTAG_NAME; + info->cdev.dev = pdev; + info->cdev.ops = &jtag_operations; + info->cdev.priv = info; + ret = devfs_create(&info->cdev); + + if (ret) + goto fail_devfs_create; + + return 0; + +fail_devfs_create: + pdev->priv = NULL; + free(info); + return ret; +} + +static void jtag_info(struct device_d *pdev) +{ + int dn, ret; + struct jtag_rd_id jid; + struct jtag_info *info = pdev->priv; + + printf(" JTAG:\n"); + printf(" Devices found: %d\n", info->devices); + for (dn = 0; dn < info->devices; dn++) { + jid.device = dn; + ret = jtag_ioctl(&info->cdev, JTAG_GET_ID, &jid); + printf(" Device number: %d\n", dn); + if (ret == -1) + printf(" JTAG_GET_ID failed: %s\n", strerror(errno)); + else + printf(" ID: 0x%lX\n", jid.id); + } +} + +static void jtag_remove(struct device_d *pdev) +{ + struct jtag_info *info = (struct jtag_info *) pdev->priv; + + devfs_remove(&info->cdev); + pdev->priv = NULL; + free(info); + dev_notice(pdev, "Device removed\n"); +} + +static struct driver_d jtag_driver = { + .name = JTAG_NAME, + .probe = jtag_probe, + .remove = jtag_remove, + .info = jtag_info, +}; + +static int jtag_module_init(void) +{ + return register_driver(&jtag_driver); +} + +device_initcall(jtag_module_init); + +MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>"); +MODULE_AUTHOR("Wjatscheslaw Stoljarski <wjatscheslaw.stoljarski@kiwigrid.com>"); +MODULE_DESCRIPTION("JTAG bitbang driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index 5510439a87..a6132e8ac5 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -79,7 +79,7 @@ static ssize_t mtd_write(struct cdev* cdev, const void *buf, size_t _count, return -EINVAL; } - dev_dbg(cdev->dev, "write: 0x%08lx 0x%08x\n", offset, count); + dev_dbg(cdev->dev, "write: 0x%08lx 0x%08lx\n", offset, count); while (count) { now = count > mtd->writesize ? mtd->writesize : count; @@ -100,7 +100,7 @@ static ssize_t mtd_write(struct cdev* cdev, const void *buf, size_t _count, ret = mtd->write(mtd, offset, now, &retlen, buf); dev_dbg(cdev->dev, - "offset: 0x%08lx now: 0x%08x retlen: 0x%08x\n", + "offset: 0x%08lx now: 0x%08lx retlen: 0x%08lx\n", offset, now, retlen); } if (ret) @@ -174,7 +174,7 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf) } #ifdef CONFIG_MTD_WRITE -static ssize_t mtd_erase(struct cdev *cdev, size_t count, loff_t offset) +static int mtd_erase(struct cdev *cdev, size_t count, loff_t offset) { struct mtd_info *mtd = cdev->priv; struct erase_info erase; @@ -248,7 +248,7 @@ int add_mtd_device(struct mtd_info *mtd, char *devname) list_for_each_entry(hook, &mtd_register_hooks, hook) if (hook->add_mtd_device) - hook->add_mtd_device(mtd, devname); + hook->add_mtd_device(mtd, devname, &hook->priv); return 0; } @@ -259,7 +259,9 @@ int del_mtd_device (struct mtd_info *mtd) list_for_each_entry(hook, &mtd_register_hooks, hook) if (hook->del_mtd_device) - hook->del_mtd_device(mtd); + hook->del_mtd_device(mtd, &hook->priv); + + devfs_remove(&mtd->cdev); unregister_device(&mtd->class_dev); free(mtd->param_size.value); free(mtd->cdev.name); diff --git a/drivers/mtd/mtd.h b/drivers/mtd/mtd.h index c8af6e3c9d..414bd6cdb5 100644 --- a/drivers/mtd/mtd.h +++ b/drivers/mtd/mtd.h @@ -25,8 +25,9 @@ */ struct mtddev_hook { struct list_head hook; - int (*add_mtd_device)(struct mtd_info *mtd, char *devname); - int (*del_mtd_device)(struct mtd_info *mtd); + int (*add_mtd_device)(struct mtd_info *mtd, char *devname, void **priv); + int (*del_mtd_device)(struct mtd_info *mtd, void **priv); + void *priv; }; struct cdev; diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c index e4dd1a00c8..c7bf40cef8 100644 --- a/drivers/mtd/mtdoob.c +++ b/drivers/mtd/mtdoob.c @@ -69,7 +69,7 @@ static struct file_operations mtd_ops_oob = { .lseek = dev_lseek_default, }; -static int add_mtdoob_device(struct mtd_info *mtd, char *devname) +static int add_mtdoob_device(struct mtd_info *mtd, char *devname, void **priv) { struct mtdoob *mtdoob; @@ -80,13 +80,26 @@ static int add_mtdoob_device(struct mtd_info *mtd, char *devname) mtdoob->cdev.priv = mtdoob; mtdoob->cdev.dev = &mtd->class_dev; mtdoob->mtd = mtd; + *priv = mtdoob; devfs_create(&mtdoob->cdev); return 0; } +static int del_mtdoob_device(struct mtd_info *mtd, void **priv) +{ + struct mtdoob *mtdoob; + + mtdoob = *priv; + devfs_remove(&mtdoob->cdev); + free(mtdoob); + + return 0; +} + static struct mtddev_hook mtdoob_hook = { .add_mtd_device = add_mtdoob_device, + .del_mtd_device = del_mtdoob_device, }; static int __init register_mtdoob(void) diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c index 24f7358098..16157e9f48 100644 --- a/drivers/mtd/mtdraw.c +++ b/drivers/mtd/mtdraw.c @@ -137,7 +137,7 @@ static ssize_t mtdraw_read(struct cdev *cdev, void *buf, size_t count, retlen += ret; } if (ret < 0) - printf("err %d\n", ret); + printf("err %lu\n", ret); else ret = retlen; return ret; @@ -222,7 +222,7 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, } } -static ssize_t mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset) +static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset) { struct mtd_info *mtd = to_mtd(cdev); struct erase_info erase; @@ -275,7 +275,7 @@ static const struct file_operations mtd_raw_fops = { .lseek = dev_lseek_default, }; -static int add_mtdraw_device(struct mtd_info *mtd, char *devname) +static int add_mtdraw_device(struct mtd_info *mtd, char *devname, void **priv) { struct mtdraw *mtdraw; @@ -290,13 +290,26 @@ static int add_mtdraw_device(struct mtd_info *mtd, char *devname) mtdraw->cdev.priv = mtdraw; mtdraw->cdev.dev = &mtd->class_dev; mtdraw->cdev.mtd = mtd; + *priv = mtdraw; devfs_create(&mtdraw->cdev); return 0; } +static int del_mtdraw_device(struct mtd_info *mtd, void **priv) +{ + struct mtdraw *mtdraw; + + mtdraw = *priv; + devfs_remove(&mtdraw->cdev); + free(mtdraw); + + return 0; +} + static struct mtddev_hook mtdraw_hook = { .add_mtd_device = add_mtdraw_device, + .del_mtd_device = del_mtdraw_device, }; static int __init register_mtdraw(void) diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 8c08c9f82c..d52c272c5c 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -14,4 +14,5 @@ obj-$(CONFIG_NAND_IMX) += nand_imx.o obj-$(CONFIG_NAND_OMAP_GPMC) += nand_omap_gpmc.o nand_omap_bch_decoder.o obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o obj-$(CONFIG_NAND_S3C24XX) += nand_s3c24xx.o +pbl-$(CONFIG_NAND_S3C24XX) += nand_s3c24xx.o obj-$(CONFIG_NAND_MXS) += nand_mxs.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a5bf757e47..37e57b32ce 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1000,7 +1000,7 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) if (!chip->select_chip) chip->select_chip = nand_select_chip; - if (!chip->read_byte) + if (!chip->read_byte || chip->read_byte == nand_read_byte) chip->read_byte = busw ? nand_read_byte16 : nand_read_byte; if (!chip->read_word) chip->read_word = nand_read_word; @@ -1009,12 +1009,12 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) #ifdef CONFIG_MTD_WRITE if (!chip->block_markbad) chip->block_markbad = nand_default_block_markbad; - if (!chip->write_buf) + if (!chip->write_buf || chip->write_buf == nand_write_buf) chip->write_buf = busw ? nand_write_buf16 : nand_write_buf; #endif - if (!chip->read_buf) + if (!chip->read_buf || chip->read_buf == nand_read_buf) chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; - if (!chip->verify_buf) + if (!chip->verify_buf || chip->verify_buf == nand_verify_buf) chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; #ifdef CONFIG_NAND_BBT if (!chip->scan_bbt) @@ -1258,6 +1258,13 @@ ident_done: break; } + if (chip->options & NAND_BUSWIDTH_AUTO) { + chip->options |= busw; + nand_set_defaults(chip, busw); + if (chip->set_buswidth) + chip->set_buswidth(mtd, chip, busw); + } + /* * Check, if buswidth is correct. Hardware drivers should set * chip correct ! @@ -1326,6 +1333,11 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips) struct nand_chip *chip = mtd->priv; struct nand_flash_dev *type; + if (chip->options & NAND_BUSWIDTH_AUTO && !chip->set_buswidth) { + printk(KERN_ERR "buswidth detection but no buswidth callback\n"); + return -EINVAL; + } + /* Get buswidth to select the correct functions */ busw = chip->options & NAND_BUSWIDTH_16; /* Set the default functions */ diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c index 86d45748ed..fa6074f856 100644 --- a/drivers/mtd/nand/nand_omap_gpmc.c +++ b/drivers/mtd/nand/nand_omap_gpmc.c @@ -22,11 +22,7 @@ * static struct gpmc_nand_platform_data nand_plat = { * .cs = give the chip select of the device * .device_width = what is the width of the device 8 or 16? - * .max_timeout = delay desired for operation * .wait_mon_pin = do you use wait monitoring? if so wait pin - * .plat_options = platform options. - * NAND_HWECC_ENABLE/DISABLE - hw ecc enable/disable - * NAND_WAITPOL_LOW/HIGH - wait pin polarity * .oob = if you would like to replace oob with a custom OOB. * .nand_setup = if you would like a special setup function to be called * .priv = any params you'd like to save(e.g. like nand_setup to use) @@ -112,12 +108,11 @@ struct gpmc_nand_info { void *gpmc_address; void *gpmc_data; void __iomem *gpmc_base; - unsigned char wait_mon_mask; - uint64_t timeout; + u32 wait_mon_mask; unsigned inuse:1; - unsigned wait_pol:1; unsigned char ecc_parity_pairs; enum gpmc_ecc_mode ecc_mode; + void *cs_base; }; /* Typical BOOTROM oob layouts-requires hwecc **/ @@ -191,25 +186,11 @@ static int omap_dev_ready(struct mtd_info *mtd) { struct nand_chip *nand = (struct nand_chip *)(mtd->priv); struct gpmc_nand_info *oinfo = (struct gpmc_nand_info *)(nand->priv); - uint64_t start = get_time_ns(); - unsigned long comp; - /* What do we mean by assert and de-assert? */ - comp = (oinfo->wait_pol == NAND_WAITPOL_HIGH) ? - oinfo->wait_mon_mask : 0x0; - while (1) { - /* Breakout condition */ - if (is_timeout(start, oinfo->timeout)) { - debug("%s timedout\n", __func__); - return -ETIMEDOUT; - } - /* if the wait is released, we are good to go */ - if (comp == - (readl(oinfo->gpmc_base + GPMC_STATUS) && - oinfo->wait_mon_mask)) - break; - } - return 0; + if (readl(oinfo->gpmc_base + GPMC_STATUS) & oinfo->wait_mon_mask) + return 1; + else + return 0; } /** @@ -603,6 +584,101 @@ static int omap_gpmc_read_buf_manual(struct mtd_info *mtd, struct nand_chip *chi return bytes; } +/** + * omap_read_buf_pref - read data from NAND controller into buffer + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read + */ +static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) +{ + struct gpmc_nand_info *info = container_of(mtd, + struct gpmc_nand_info, minfo); + u32 r_count = 0; + u32 *p = (u32 *)buf; + + /* take care of subpage reads */ + if (len % 4) { + if (info->nand.options & NAND_BUSWIDTH_16) + readsw(info->cs_base, buf, (len % 4) / 2); + else + readsb(info->cs_base, buf, len % 4); + p = (u32 *) (buf + len % 4); + len -= len % 4; + } + + /* configure and start prefetch transfer */ + gpmc_prefetch_enable(info->gpmc_cs, + PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0); + + do { + r_count = readl(info->gpmc_base + GPMC_PREFETCH_STATUS); + r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count); + r_count = r_count >> 2; + readsl(info->cs_base, p, r_count); + p += r_count; + len -= r_count << 2; + } while (len); + + /* disable and stop the PFPW engine */ + gpmc_prefetch_reset(info->gpmc_cs); +} + +/** + * omap_write_buf_pref - write buffer to NAND controller + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + */ +static void omap_write_buf_pref(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct gpmc_nand_info *info = container_of(mtd, + struct gpmc_nand_info, minfo); + u32 w_count = 0; + u_char *buf1 = (u_char *)buf; + u32 *p32 = (u32 *)buf; + uint64_t start; + + /* take care of subpage writes */ + while (len % 4 != 0) { + writeb(*buf, info->nand.IO_ADDR_W); + buf1++; + p32 = (u32 *)buf1; + len--; + } + + /* configure and start prefetch transfer */ + gpmc_prefetch_enable(info->gpmc_cs, + PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1); + + while (len >= 0) { + w_count = readl(info->gpmc_base + GPMC_PREFETCH_STATUS); + w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count); + w_count = w_count >> 2; + writesl(info->cs_base, p32, w_count); + p32 += w_count; + len -= w_count << 2; + } + + /* wait for data to flushed-out before reset the prefetch */ + start = get_time_ns(); + while (1) { + u32 regval, status; + regval = readl(info->gpmc_base + GPMC_PREFETCH_STATUS); + status = GPMC_PREFETCH_STATUS_COUNT(regval); + if (!status) + break; + if (is_timeout(start, 100 * MSECOND)) { + dev_err(mtd->dev, "prefetch flush timed out\n"); + break; + } + } + + /* disable and stop the PFPW engine */ + gpmc_prefetch_reset(info->gpmc_cs); +} + /* * read a page with the ecc layout used by the OMAP4 romcode. The * romcode expects an unusual ecc layout (f = free, e = ecc): @@ -803,6 +879,20 @@ static int omap_gpmc_eccmode_set(struct device_d *dev, struct param_d *param, co return omap_gpmc_eccmode(oinfo, i); } +static int gpmc_set_buswidth(struct mtd_info *mtd, struct nand_chip *chip, int buswidth) +{ + struct gpmc_nand_info *oinfo = chip->priv; + + if (buswidth == NAND_BUSWIDTH_16) + oinfo->pdata->nand_cfg->cfg[0] |= 0x00001000; + else + oinfo->pdata->nand_cfg->cfg[0] &= ~0x00001000; + + gpmc_cs_config(oinfo->pdata->cs, oinfo->pdata->nand_cfg); + + return 0; +} + /** * @brief nand device probe. * @@ -853,15 +943,23 @@ static int gpmc_nand_probe(struct device_d *pdev) oinfo->gpmc_command = (void *)(cs_base + GPMC_CS_NAND_COMMAND); oinfo->gpmc_address = (void *)(cs_base + GPMC_CS_NAND_ADDRESS); oinfo->gpmc_data = (void *)(cs_base + GPMC_CS_NAND_DATA); - oinfo->timeout = pdata->max_timeout; + oinfo->cs_base = (void *)pdata->nand_cfg->base; dev_dbg(pdev, "GPMC base=0x%p cmd=0x%p address=0x%p data=0x%p cs_base=0x%p\n", oinfo->gpmc_base, oinfo->gpmc_command, oinfo->gpmc_address, oinfo->gpmc_data, cs_base); - /* If we are 16 bit dev, our gpmc config tells us that */ - if ((readl(cs_base) & 0x3000) == 0x1000) { - dev_dbg(pdev, "16 bit dev\n"); + switch (pdata->device_width) { + case 0: + printk("probe buswidth\n"); + nand->options |= NAND_BUSWIDTH_AUTO; + break; + case 8: + break; + case 16: nand->options |= NAND_BUSWIDTH_16; + break; + default: + return -EINVAL; } /* Same data register for in and out */ @@ -879,11 +977,11 @@ static int gpmc_nand_probe(struct device_d *pdev) err = -EINVAL; goto out_release_mem; } + if (pdata->wait_mon_pin) { /* Set up the wait monitoring mask * This is GPMC_STATUS reg relevant */ oinfo->wait_mon_mask = (0x1 << (pdata->wait_mon_pin - 1)) << 8; - oinfo->wait_pol = (pdata->plat_options & NAND_WAITPOL_MASK); nand->dev_ready = omap_dev_ready; nand->chip_delay = 0; } else { @@ -901,6 +999,8 @@ static int gpmc_nand_probe(struct device_d *pdev) nand->options |= NAND_OWN_BUFFERS; nand->buffers = xzalloc(sizeof(*nand->buffers)); + nand->set_buswidth = gpmc_set_buswidth; + /* State my controller */ nand->controller = &oinfo->controller; @@ -928,18 +1028,12 @@ static int gpmc_nand_probe(struct device_d *pdev) goto out_release_mem; } - switch (pdata->device_width) { - case 8: - lsp = &ecc_sp_x8; - llp = &ecc_lp_x8; - break; - case 16: + if (nand->options & NAND_BUSWIDTH_16) { lsp = &ecc_sp_x16; llp = &ecc_lp_x16; - break; - default: - err = -EINVAL; - goto out_release_mem; + } else { + lsp = &ecc_sp_x8; + llp = &ecc_lp_x8; } switch (minfo->writesize) { @@ -954,6 +1048,9 @@ static int gpmc_nand_probe(struct device_d *pdev) goto out_release_mem; } + nand->read_buf = omap_read_buf_pref; + nand->write_buf = omap_write_buf_pref; + nand->options |= NAND_SKIP_BBTSCAN; dev_add_param(pdev, "eccmode", omap_gpmc_eccmode_set, NULL, 0); diff --git a/drivers/mtd/nand/nand_s3c24xx.c b/drivers/mtd/nand/nand_s3c24xx.c index c6297011a3..3d5732e02a 100644 --- a/drivers/mtd/nand/nand_s3c24xx.c +++ b/drivers/mtd/nand/nand_s3c24xx.c @@ -603,6 +603,16 @@ void __nand_boot_init s3c24x0_nand_load_image(void *dest, int size, int page) disable_nand_controller(host); } +#include <asm-generic/sections.h> + +void __nand_boot_init nand_boot(void) +{ + void *dest = _text; + int size = barebox_image_size; + int page = 0; + + s3c24x0_nand_load_image(dest, size, page); +} #ifdef CONFIG_NAND_S3C_BOOT_DEBUG #include <command.h> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 340839d5d9..3c5f729db3 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -118,6 +118,11 @@ config DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR depends on DRIVER_NET_DESIGNWARE default n +config DRIVER_NET_GIANFAR + bool "Gianfar Ethernet" + depends on ARCH_MPC85XX + select MIIDEV + source "drivers/net/usb/Kconfig" endmenu diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 29727b7d5b..4d960e856f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_NET_USB) += usb/ obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o obj-$(CONFIG_DRIVER_NET_KS8851_MLL) += ks8851_mll.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE) += designware.o +obj-$(CONFIG_DRIVER_NET_GIANFAR) += gianfar.o diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c new file mode 100644 index 0000000000..19544de261 --- /dev/null +++ b/drivers/net/gianfar.c @@ -0,0 +1,548 @@ +/* + * Freescale Three Speed Ethernet Controller driver + * + * This software may be used and distributed according to the + * terms of the GNU Public License, Version 2, incorporated + * herein by reference. + * + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2004-2010 Freescale Semiconductor, Inc. + * (C) Copyright 2003, Motorola, Inc. + * based on work by Andy Fleming + */ + +#include <config.h> +#include <common.h> +#include <malloc.h> +#include <net.h> +#include <init.h> +#include <driver.h> +#include <miidev.h> +#include <command.h> +#include <errno.h> +#include <asm/io.h> +#include "gianfar.h" + +/* 2 seems to be the minimum number of TX descriptors to make it work. */ +#define TX_BUF_CNT 2 +#define RX_BUF_CNT PKTBUFSRX +#define BUF_ALIGN 8 + +/* + * Initialize required registers to appropriate values, zeroing + * those we don't care about (unless zero is bad, in which case, + * choose a more appropriate value) + */ +static void gfar_init_registers(void __iomem *regs) +{ + out_be32(regs + GFAR_IEVENT_OFFSET, GFAR_IEVENT_INIT_CLEAR); + + out_be32(regs + GFAR_IMASK_OFFSET, GFAR_IMASK_INIT_CLEAR); + + out_be32(regs + GFAR_IADDR(0), 0); + out_be32(regs + GFAR_IADDR(1), 0); + out_be32(regs + GFAR_IADDR(2), 0); + out_be32(regs + GFAR_IADDR(3), 0); + out_be32(regs + GFAR_IADDR(4), 0); + out_be32(regs + GFAR_IADDR(5), 0); + out_be32(regs + GFAR_IADDR(6), 0); + out_be32(regs + GFAR_IADDR(7), 0); + + out_be32(regs + GFAR_GADDR(0), 0); + out_be32(regs + GFAR_GADDR(1), 0); + out_be32(regs + GFAR_GADDR(2), 0); + out_be32(regs + GFAR_GADDR(3), 0); + out_be32(regs + GFAR_GADDR(4), 0); + out_be32(regs + GFAR_GADDR(5), 0); + out_be32(regs + GFAR_GADDR(6), 0); + out_be32(regs + GFAR_GADDR(7), 0); + + out_be32(regs + GFAR_RCTRL_OFFSET, 0x00000000); + + memset((void *)(regs + GFAR_TR64_OFFSET), 0, + GFAR_CAM2_OFFSET - GFAR_TR64_OFFSET); + + out_be32(regs + GFAR_CAM1_OFFSET, 0xffffffff); + out_be32(regs + GFAR_CAM2_OFFSET, 0xffffffff); + + out_be32(regs + GFAR_MRBLR_OFFSET, MRBLR_INIT_SETTINGS); + + out_be32(regs + GFAR_MINFLR_OFFSET, MINFLR_INIT_SETTINGS); + + out_be32(regs + GFAR_ATTR_OFFSET, ATTR_INIT_SETTINGS); + out_be32(regs + GFAR_ATTRELI_OFFSET, ATTRELI_INIT_SETTINGS); +} + +/* + * Configure maccfg2 based on negotiated speed and duplex + * reported by PHY handling code + */ +static void gfar_adjust_link(struct eth_device *edev) +{ + struct gfar_private *priv = edev->priv; + struct device_d *mdev = priv->miidev.parent; + void __iomem *regs = priv->regs; + u32 ecntrl, maccfg2; + uint32_t status; + + status = miidev_get_status(&priv->miidev); + + priv->link = status & MIIDEV_STATUS_IS_UP; + if (status & MIIDEV_STATUS_IS_FULL_DUPLEX) + priv->duplexity = 1; + else + priv->duplexity = 0; + + if (status & MIIDEV_STATUS_IS_1000MBIT) + priv->speed = 1000; + else if (status & MIIDEV_STATUS_IS_100MBIT) + priv->speed = 100; + else + priv->speed = 10; + + if (priv->link) { + /* clear all bits relative with interface mode */ + ecntrl = in_be32(regs + GFAR_ECNTRL_OFFSET); + ecntrl &= ~GFAR_ECNTRL_R100; + + maccfg2 = in_be32(regs + GFAR_MACCFG2_OFFSET); + maccfg2 &= ~(GFAR_MACCFG2_IF | GFAR_MACCFG2_FULL_DUPLEX); + + if (priv->duplexity != 0) + maccfg2 |= GFAR_MACCFG2_FULL_DUPLEX; + else + maccfg2 &= ~(GFAR_MACCFG2_FULL_DUPLEX); + + switch (priv->speed) { + case 1000: + maccfg2 |= GFAR_MACCFG2_GMII; + break; + case 100: + case 10: + maccfg2 |= GFAR_MACCFG2_MII; + /* + * Set R100 bit in all modes although + * it is only used in RGMII mode + */ + if (priv->speed == 100) + ecntrl |= GFAR_ECNTRL_R100; + break; + default: + dev_info(mdev, "Speed is unknown\n"); + break; + } + + out_be32(regs + GFAR_ECNTRL_OFFSET, ecntrl); + out_be32(regs + GFAR_MACCFG2_OFFSET, maccfg2); + + dev_info(mdev, "Speed: %d, %s duplex\n", priv->speed, + (priv->duplexity) ? "full" : "half"); + + } else { + dev_info(mdev, "No link.\n"); + } +} + +/* Stop the interface */ +static void gfar_halt(struct eth_device *edev) +{ + struct gfar_private *priv = edev->priv; + void __iomem *regs = priv->regs; + int value; + + clrbits_be32(regs + GFAR_DMACTRL_OFFSET, GFAR_DMACTRL_GRS | + GFAR_DMACTRL_GTS); + setbits_be32(regs + GFAR_DMACTRL_OFFSET, GFAR_DMACTRL_GRS | + GFAR_DMACTRL_GTS); + + value = in_be32(regs + GFAR_IEVENT_OFFSET); + value &= (GFAR_IEVENT_GRSC | GFAR_IEVENT_GTSC); + + while (value != (GFAR_IEVENT_GRSC | GFAR_IEVENT_GTSC)) { + value = in_be32(regs + GFAR_IEVENT_OFFSET); + value &= (GFAR_IEVENT_GRSC | GFAR_IEVENT_GTSC); + } + + clrbits_be32(regs + GFAR_MACCFG1_OFFSET, + GFAR_MACCFG1_TX_EN | GFAR_MACCFG1_RX_EN); +} + +/* Initializes registers for the controller. */ +static int gfar_init(struct eth_device *edev) +{ + struct gfar_private *priv = edev->priv; + void __iomem *regs = priv->regs; + + gfar_halt(edev); + + /* Init MACCFG2. Default to GMII */ + out_be32(regs + GFAR_MACCFG2_OFFSET, MACCFG2_INIT_SETTINGS); + out_be32(regs + GFAR_ECNTRL_OFFSET, ECNTRL_INIT_SETTINGS); + + priv->rxidx = 0; + priv->txidx = 0; + + gfar_init_registers(regs); + + miidev_restart_aneg(&priv->miidev); + + return 0; +} + +static int gfar_open(struct eth_device *edev) +{ + int ix; + struct gfar_private *priv = edev->priv; + void __iomem *regs = priv->regs; + + /* Point to the buffer descriptors */ + out_be32(regs + GFAR_TBASE0_OFFSET, (unsigned int)priv->txbd); + out_be32(regs + GFAR_RBASE0_OFFSET, (unsigned int)priv->rxbd); + + /* Initialize the Rx Buffer descriptors */ + for (ix = 0; ix < RX_BUF_CNT; ix++) { + priv->rxbd[ix].status = RXBD_EMPTY; + priv->rxbd[ix].length = 0; + priv->rxbd[ix].bufPtr = (uint) NetRxPackets[ix]; + } + priv->rxbd[RX_BUF_CNT - 1].status |= RXBD_WRAP; + + /* Initialize the TX Buffer Descriptors */ + for (ix = 0; ix < TX_BUF_CNT; ix++) { + priv->txbd[ix].status = 0; + priv->txbd[ix].length = 0; + priv->txbd[ix].bufPtr = 0; + } + priv->txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; + + miidev_wait_aneg(&priv->miidev); + gfar_adjust_link(edev); + + /* Enable Transmit and Receive */ + setbits_be32(regs + GFAR_MACCFG1_OFFSET, GFAR_MACCFG1_RX_EN | + GFAR_MACCFG1_TX_EN); + + /* Tell the DMA it is clear to go */ + setbits_be32(regs + GFAR_DMACTRL_OFFSET, DMACTRL_INIT_SETTINGS); + out_be32(regs + GFAR_TSTAT_OFFSET, GFAR_TSTAT_CLEAR_THALT); + out_be32(regs + GFAR_RSTAT_OFFSET, GFAR_RSTAT_CLEAR_RHALT); + clrbits_be32(regs + GFAR_DMACTRL_OFFSET, GFAR_DMACTRL_GRS | + GFAR_DMACTRL_GTS); + + return 0; +} + +static int gfar_get_ethaddr(struct eth_device *edev, unsigned char *mac) +{ + return -ENODEV; +} + +static int gfar_set_ethaddr(struct eth_device *edev, unsigned char *mac) +{ + struct gfar_private *priv = edev->priv; + void __iomem *regs = priv->regs; + char tmpbuf[MAC_ADDR_LEN]; + uint tempval; + int ix; + + for (ix = 0; ix < MAC_ADDR_LEN; ix++) + tmpbuf[MAC_ADDR_LEN - 1 - ix] = mac[ix]; + + tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) | + tmpbuf[3]; + + out_be32(regs + GFAR_MACSTRADDR1_OFFSET, tempval); + + tempval = *((uint *)(tmpbuf + 4)); + + out_be32(regs + GFAR_MACSTRADDR2_OFFSET, tempval); + + return 0; +} + +/* Writes the given phy's reg with value, using the specified MDIO regs */ +static int gfar_local_mdio_write(void __iomem *phyregs, uint addr, uint reg, + uint value) +{ + uint64_t start; + + out_be32(phyregs + GFAR_MIIMADD_OFFSET, (addr << 8) | (reg & 0x1f)); + out_be32(phyregs + GFAR_MIIMCON_OFFSET, value); + + start = get_time_ns(); + while (!is_timeout(start, 10 * MSECOND)) { + if (!(in_be32(phyregs + GFAR_MIIMMIND_OFFSET) & + GFAR_MIIMIND_BUSY)) + return 0; + } + + return -EIO; +} + +/* + * Reads register regnum on the device's PHY through the + * specified registers. It lowers and raises the read + * command, and waits for the data to become valid (miimind + * notvalid bit cleared), and the bus to cease activity (miimind + * busy bit cleared), and then returns the value + */ +static uint gfar_local_mdio_read(void __iomem *phyregs, uint phyid, uint regnum) +{ + uint64_t start; + + /* Put the address of the phy, and the register number into MIIMADD */ + out_be32(phyregs + GFAR_MIIMADD_OFFSET, (phyid << 8) | (regnum & 0x1f)); + + /* Clear the command register, and wait */ + out_be32(phyregs + GFAR_MIIMCOM_OFFSET, 0); + + /* Initiate a read command, and wait */ + out_be32(phyregs + GFAR_MIIMCOM_OFFSET, GFAR_MIIM_READ_COMMAND); + + start = get_time_ns(); + while (!is_timeout(start, 10 * MSECOND)) { + if (!(in_be32(phyregs + GFAR_MIIMMIND_OFFSET) & + (GFAR_MIIMIND_NOTVALID | GFAR_MIIMIND_BUSY))) + return in_be32(phyregs + GFAR_MIIMSTAT_OFFSET); + } + + return -EIO; +} + +static void gfar_configure_serdes(struct gfar_private *priv) +{ + gfar_local_mdio_write(priv->phyregs_sgmii, + in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_ANA, + priv->tbiana); + gfar_local_mdio_write(priv->phyregs_sgmii, + in_be32(priv->regs + GFAR_TBIPA_OFFSET), + GFAR_TBI_TBICON, GFAR_TBICON_CLK_SELECT); + gfar_local_mdio_write(priv->phyregs_sgmii, + in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_CR, + priv->tbicr); +} + +/* Reset the internal and external PHYs. */ +static void gfar_init_phy(struct eth_device *dev) +{ + struct gfar_private *priv = dev->priv; + void __iomem *regs = priv->regs; + uint64_t start; + + /* Assign a Physical address to the TBI */ + out_be32(regs + GFAR_TBIPA_OFFSET, GFAR_TBIPA_VALUE); + + /* Reset MII (due to new addresses) */ + out_be32(priv->phyregs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_RESET); + out_be32(priv->phyregs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_INIT_VALUE); + + start = get_time_ns(); + while (!is_timeout(start, 10 * MSECOND)) { + if (!(in_be32(priv->phyregs + GFAR_MIIMMIND_OFFSET) & + GFAR_MIIMIND_BUSY)) + break; + } + + gfar_local_mdio_write(priv->phyregs, priv->phyaddr, GFAR_MIIM_CR, + GFAR_MIIM_CR_RST); + + start = get_time_ns(); + while (!is_timeout(start, 10 * MSECOND)) { + if (!(gfar_local_mdio_read(priv->phyregs, priv->phyaddr, + GFAR_MIIM_CR) & GFAR_MIIM_CR_RST)) + break; + } + + if (in_be32(regs + GFAR_ECNTRL_OFFSET) & GFAR_ECNTRL_SGMII_MODE) + gfar_configure_serdes(priv); +} + +static int gfar_send(struct eth_device *edev, void *packet, int length) +{ + struct gfar_private *priv = edev->priv; + void __iomem *regs = priv->regs; + struct device_d *dev = edev->parent; + uint64_t start; + uint tidx; + + tidx = priv->txidx; + priv->txbd[tidx].bufPtr = (uint) packet; + priv->txbd[tidx].length = length; + priv->txbd[tidx].status |= (TXBD_READY | TXBD_LAST | + TXBD_CRC | TXBD_INTERRUPT); + + /* Tell the DMA to go */ + out_be32(regs + GFAR_TSTAT_OFFSET, GFAR_TSTAT_CLEAR_THALT); + + /* Wait for buffer to be transmitted */ + start = get_time_ns(); + while (priv->txbd[tidx].status & TXBD_READY) { + if (is_timeout(start, 5 * MSECOND)) { + break; + } + } + + if (priv->txbd[tidx].status & TXBD_READY) { + dev_err(dev, "tx timeout: 0x%x\n", priv->txbd[tidx].status); + return -EBUSY; + } + else if (priv->txbd[tidx].status & TXBD_STATS) { + dev_err(dev, "TX error: 0x%x\n", priv->txbd[tidx].status); + return -EIO; + } + + priv->txidx = (priv->txidx + 1) % TX_BUF_CNT; + + return 0; +} + +static int gfar_recv(struct eth_device *edev) +{ + struct gfar_private *priv = edev->priv; + struct device_d *dev = edev->parent; + void __iomem *regs = priv->regs; + int length; + + if (priv->rxbd[priv->rxidx].status & RXBD_EMPTY) { + return 0; /* no data */ + } + + length = priv->rxbd[priv->rxidx].length; + + /* Send the packet up if there were no errors */ + if (!(priv->rxbd[priv->rxidx].status & RXBD_STATS)) { + net_receive(NetRxPackets[priv->rxidx], length - 4); + } else { + dev_err(dev, "Got error %x\n", + (priv->rxbd[priv->rxidx].status & RXBD_STATS)); + } + + priv->rxbd[priv->rxidx].length = 0; + + /* Set the wrap bit if this is the last element in the list */ + if ((priv->rxidx + 1) == RX_BUF_CNT) + priv->rxbd[priv->rxidx].status = RXBD_WRAP; + else + priv->rxbd[priv->rxidx].status = 0; + + priv->rxbd[priv->rxidx].status |= RXBD_EMPTY; + priv->rxidx = (priv->rxidx + 1) % RX_BUF_CNT; + + if (in_be32(regs + GFAR_IEVENT_OFFSET) & GFAR_IEVENT_BSY) { + out_be32(regs + GFAR_IEVENT_OFFSET, GFAR_IEVENT_BSY); + out_be32(regs + GFAR_RSTAT_OFFSET, GFAR_RSTAT_CLEAR_RHALT); + } + + return 0; +} + +/* Read a MII PHY register. */ +static int gfar_miiphy_read(struct mii_device *mdev, int addr, int reg) +{ + struct eth_device *edev = mdev->edev; + struct device_d *dev = edev->parent; + struct gfar_private *priv = edev->priv; + int ret; + + ret = gfar_local_mdio_read(priv->phyregs, addr, reg); + if (ret == -EIO) + dev_err(dev, "Can't read PHY at address %d\n", addr); + + return ret; +} + +/* Write a MII PHY register. */ +static int gfar_miiphy_write(struct mii_device *mdev, int addr, int reg, + int value) +{ + struct eth_device *edev = mdev->edev; + struct device_d *dev = edev->parent; + struct gfar_private *priv = edev->priv; + unsigned short val = value; + int ret; + + ret = gfar_local_mdio_write(priv->phyregs, addr, reg, val); + + if (ret) + dev_err(dev, "Can't write PHY at address %d\n", addr); + + return 0; +} + +/* + * Initialize device structure. Returns success if + * initialization succeeded. + */ +static int gfar_probe(struct device_d *dev) +{ + struct gfar_info_struct *gfar_info = dev->platform_data; + struct eth_device *edev; + struct gfar_private *priv; + size_t size; + char *p; + + priv = xzalloc(sizeof(struct gfar_private)); + + if (NULL == priv) + return -ENODEV; + + edev = &priv->edev; + + priv->regs = dev_request_mem_region(dev, 0); + priv->phyregs = dev_request_mem_region(dev, 1); + priv->phyregs_sgmii = dev_request_mem_region(dev, 2); + + priv->phyaddr = gfar_info->phyaddr; + priv->tbicr = gfar_info->tbicr; + priv->tbiana = gfar_info->tbiana; + + /* + * Allocate descriptors 64-bit aligned. Descriptors + * are 8 bytes in size. + */ + size = ((TX_BUF_CNT * sizeof(struct txbd8)) + + (RX_BUF_CNT * sizeof(struct rxbd8))) + BUF_ALIGN; + p = (char *)xmemalign(BUF_ALIGN, size); + priv->txbd = (struct txbd8 *)p; + priv->rxbd = (struct rxbd8 *)(p + (TX_BUF_CNT * sizeof(struct txbd8))); + + edev->priv = priv; + edev->init = gfar_init; + edev->open = gfar_open; + edev->halt = gfar_halt; + edev->send = gfar_send; + edev->recv = gfar_recv; + edev->get_ethaddr = gfar_get_ethaddr; + edev->set_ethaddr = gfar_set_ethaddr; + edev->parent = dev; + + setbits_be32(priv->regs + GFAR_MACCFG1_OFFSET, GFAR_MACCFG1_SOFT_RESET); + udelay(2); + clrbits_be32(priv->regs + GFAR_MACCFG1_OFFSET, GFAR_MACCFG1_SOFT_RESET); + + priv->miidev.read = gfar_miiphy_read; + priv->miidev.write = gfar_miiphy_write; + priv->miidev.address = priv->phyaddr; + priv->miidev.flags = 0; + priv->miidev.edev = edev; + priv->miidev.parent = dev; + + gfar_init_phy(edev); + + mii_register(&priv->miidev); + + return eth_register(edev); +} + +static struct driver_d gfar_eth_driver = { + .name = "gfar", + .probe = gfar_probe, +}; + +static int gfar_eth_init(void) +{ + register_driver(&gfar_eth_driver); + return 0; +} + +device_initcall(gfar_eth_init); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h new file mode 100644 index 0000000000..a4ad99e3b7 --- /dev/null +++ b/drivers/net/gianfar.h @@ -0,0 +1,284 @@ +/* + * gianfar.h + * + * Driver for the Motorola Triple Speed Ethernet Controller + * + * This software may be used and distributed according to the + * terms of the GNU Public License, Version 2, incorporated + * herein by reference. + * + * Copyright 2012 GE Intelligent Platforms, Inc. + * Copyright 2004, 2007, 2009 Freescale Semiconductor, Inc. + * (C) Copyright 2003, Motorola, Inc. + * based on tsec.h by Xianghua Xiao and Andy Fleming 2003-2009 + */ + +#ifndef __GIANFAR_H +#define __GIANFAR_H + +#include <net.h> +#include <config.h> +#include <mach/gianfar.h> + +#define MAC_ADDR_LEN 6 + +/* TBI register addresses */ +#define GFAR_TBI_CR 0x00 +#define GFAR_TBI_SR 0x01 +#define GFAR_TBI_ANA 0x04 +#define GFAR_TBI_ANLPBPA 0x05 +#define GFAR_TBI_ANEX 0x06 +#define GFAR_TBI_TBICON 0x11 + +/* TBI MDIO register bit fields*/ +#define GFAR_TBICON_CLK_SELECT 0x0020 +#define GFAR_TBIANA_ASYMMETRIC_PAUSE 0x0100 +#define GFAR_TBIANA_SYMMETRIC_PAUSE 0x0080 +#define GFAR_TBIANA_HALF_DUPLEX 0x0040 +#define GFAR_TBIANA_FULL_DUPLEX 0x0020 +/* The two reserved bits below are used in AN3869 to enable SGMII. */ +#define GFAR_TBIANA_RESERVED1 0x4000 +#define GFAR_TBIANA_RESERVED15 0x0001 +#define GFAR_TBICR_PHY_RESET 0x8000 +#define GFAR_TBICR_ANEG_ENABLE 0x1000 +#define GFAR_TBICR_RESTART_ANEG 0x0200 +#define GFAR_TBICR_FULL_DUPLEX 0x0100 +#define GFAR_TBICR_SPEED1_SET 0x0040 + +/* MAC register bits */ +#define GFAR_MACCFG1_SOFT_RESET 0x80000000 +#define GFAR_MACCFG1_RESET_RX_MC 0x00080000 +#define GFAR_MACCFG1_RESET_TX_MC 0x00040000 +#define GFAR_MACCFG1_RESET_RX_FUN 0x00020000 +#define TESC_MACCFG1_RESET_TX_FUN 0x00010000 +#define GFAR_MACCFG1_LOOPBACK 0x00000100 +#define GFAR_MACCFG1_RX_FLOW 0x00000020 +#define GFAR_MACCFG1_TX_FLOW 0x00000010 +#define GFAR_MACCFG1_SYNCD_RX_EN 0x00000008 +#define GFAR_MACCFG1_RX_EN 0x00000004 +#define GFAR_MACCFG1_SYNCD_TX_EN 0x00000002 +#define GFAR_MACCFG1_TX_EN 0x00000001 + +#define MACCFG2_INIT_SETTINGS 0x00007205 +#define GFAR_MACCFG2_FULL_DUPLEX 0x00000001 +#define GFAR_MACCFG2_IF 0x00000300 +#define GFAR_MACCFG2_GMII 0x00000200 +#define GFAR_MACCFG2_MII 0x00000100 + +#define ECNTRL_INIT_SETTINGS 0x00001000 +#define GFAR_ECNTRL_TBI_MODE 0x00000020 +#define GFAR_ECNTRL_R100 0x00000008 +#define GFAR_ECNTRL_SGMII_MODE 0x00000002 + +#ifndef GFAR_TBIPA_VALUE + #define GFAR_TBIPA_VALUE 0x1f +#endif +#define GFAR_MIIMCFG_INIT_VALUE 0x00000003 +#define GFAR_MIIMCFG_RESET 0x80000000 + +#define GFAR_MIIMIND_BUSY 0x00000001 +#define GFAR_MIIMIND_NOTVALID 0x00000004 + +#define GFAR_MIIM_CONTROL 0x00000000 +#define GFAR_MIIM_CONTROL_RESET 0x00009140 +#define GFAR_MIIM_CONTROL_INIT 0x00001140 +#define GFAR_MIIM_CONTROL_RESTART 0x00001340 +#define GFAR_MIIM_ANEN 0x00001000 + +#define GFAR_MIIM_CR 0x00000000 +#define GFAR_MIIM_CR_RST 0x00008000 +#define GFAR_MIIM_CR_INIT 0x00001000 + +#define GFAR_MIIM_STATUS 0x1 +#define GFAR_MIIM_STATUS_AN_DONE 0x00000020 +#define GFAR_MIIM_STATUS_LINK 0x0004 + +#define GFAR_MIIM_PHYIR1 0x2 +#define GFAR_MIIM_PHYIR2 0x3 + +#define GFAR_MIIM_ANAR 0x4 +#define GFAR_MIIM_ANAR_INIT 0x1e1 + +#define GFAR_MIIM_TBI_ANLPBPA 0x5 +#define GFAR_MIIM_TBI_ANLPBPA_HALF 0x00000040 +#define GFAR_MIIM_TBI_ANLPBPA_FULL 0x00000020 + +#define GFAR_MIIM_TBI_ANEX 0x6 +#define GFAR_MIIM_TBI_ANEX_NP 0x00000004 +#define GFAR_MIIM_TBI_ANEX_PRX 0x00000002 + +#define GFAR_MIIM_GBIT_CONTROL 0x9 +#define GFAR_MIIM_GBIT_CONTROL_INIT 0xe00 + +#define GFAR_MIIM_EXT_PAGE_ACCESS 0x1f + +#define GFAR_MIIM_GBIT_CON 0x09 +#define GFAR_MIIM_GBIT_CON_ADVERT 0x0e00 + +#define GFAR_MIIM_READ_COMMAND 0x00000001 + +#define MRBLR_INIT_SETTINGS 1536 + +#define MINFLR_INIT_SETTINGS 0x00000040 + +#define DMACTRL_INIT_SETTINGS 0x000000c3 +#define GFAR_DMACTRL_GRS 0x00000010 +#define GFAR_DMACTRL_GTS 0x00000008 + +#define GFAR_TSTAT_CLEAR_THALT 0x80000000 +#define GFAR_RSTAT_CLEAR_RHALT 0x00800000 + +#define GFAR_IEVENT_INIT_CLEAR 0xffffffff +#define GFAR_IEVENT_BABR 0x80000000 +#define GFAR_IEVENT_RXC 0x40000000 +#define GFAR_IEVENT_BSY 0x20000000 +#define GFAR_IEVENT_EBERR 0x10000000 +#define GFAR_IEVENT_MSRO 0x04000000 +#define GFAR_IEVENT_GTSC 0x02000000 +#define GFAR_IEVENT_BABT 0x01000000 +#define GFAR_IEVENT_TXC 0x00800000 +#define GFAR_IEVENT_TXE 0x00400000 +#define GFAR_IEVENT_TXB 0x00200000 +#define GFAR_IEVENT_TXF 0x00100000 +#define GFAR_IEVENT_IE 0x00080000 +#define GFAR_IEVENT_LC 0x00040000 +#define GFAR_IEVENT_CRL 0x00020000 +#define GFAR_IEVENT_XFUN 0x00010000 +#define GFAR_IEVENT_RXB0 0x00008000 +#define GFAR_IEVENT_GRSC 0x00000100 +#define GFAR_IEVENT_RXF0 0x00000080 + +#define GFAR_IMASK_INIT_CLEAR 0x00000000 + +/* Default Attribute fields */ +#define ATTR_INIT_SETTINGS 0x000000c0 +#define ATTRELI_INIT_SETTINGS 0x00000000 + +/* TxBD status field bits */ +#define TXBD_READY 0x8000 +#define TXBD_PADCRC 0x4000 +#define TXBD_WRAP 0x2000 +#define TXBD_INTERRUPT 0x1000 +#define TXBD_LAST 0x0800 +#define TXBD_CRC 0x0400 +#define TXBD_DEF 0x0200 +#define TXBD_HUGEFRAME 0x0080 +#define TXBD_LATECOLLISION 0x0080 +#define TXBD_RETRYLIMIT 0x0040 +#define TXBD_RETRYCOUNTMASK 0x003c +#define TXBD_UNDERRUN 0x0002 +#define TXBD_STATS 0x03ff + +/* RxBD status field bits */ +#define RXBD_EMPTY 0x8000 +#define RXBD_RO1 0x4000 +#define RXBD_WRAP 0x2000 +#define RXBD_INTERRUPT 0x1000 +#define RXBD_LAST 0x0800 +#define RXBD_FIRST 0x0400 +#define RXBD_MISS 0x0100 +#define RXBD_BROADCAST 0x0080 +#define RXBD_MULTICAST 0x0040 +#define RXBD_LARGE 0x0020 +#define RXBD_NONOCTET 0x0010 +#define RXBD_SHORT 0x0008 +#define RXBD_CRCERR 0x0004 +#define RXBD_OVERRUN 0x0002 +#define RXBD_TRUNCATED 0x0001 +#define RXBD_STATS 0x003f + +struct txbd8 { + ushort status; /* Status Fields */ + ushort length; /* Buffer length */ + uint bufPtr; /* Buffer Pointer */ +}; + +struct rxbd8 { + ushort status; /* Status Fields */ + ushort length; /* Buffer Length */ + uint bufPtr; /* Buffer Pointer */ +}; + +/* eTSEC general control and status registers */ +#define GFAR_IEVENT_OFFSET 0x010 /* Interrupt Event */ +#define GFAR_IMASK_OFFSET 0x014 /* Interrupt Mask */ +#define GFAR_ECNTRL_OFFSET 0x020 /* Ethernet Control */ +#define GFAR_MINFLR_OFFSET 0x024 /* Minimum Frame Length */ +#define GFAR_DMACTRL_OFFSET 0x02c /* DMA Control */ +#define GFAR_TBIPA_OFFSET 0x030 /* TBI PHY address */ + +/* eTSEC transmit control and status register */ +#define GFAR_TSTAT_OFFSET 0x104 /* transmit status register */ +#define GFAR_TBASE0_OFFSET 0x204 /* TxBD Base Address */ + +/* eTSEC receive control and status register */ +#define GFAR_RCTRL_OFFSET 0x300 /* Receive Control */ +#define GFAR_RSTAT_OFFSET 0x304 /* transmit status register */ +#define GFAR_MRBLR_OFFSET 0x340 /* Maximum Receive Buffer Length */ +#define GFAR_RBASE0_OFFSET 0x404 /* RxBD Base Address */ + +/* eTSEC MAC registers */ +#define GFAR_MACCFG1_OFFSET 0x500 /* MAC Configuration #1 */ +#define GFAR_MACCFG2_OFFSET 0x504 /* MAC Configuration #2 */ +#define GFAR_MIIMCFG_OFFSET 0x520 /* MII management configuration */ +#define GFAR_MIIMCOM_OFFSET 0x524 /* MII management command */ +#define GFAR_MIIMADD_OFFSET 0x528 /* MII management address */ +#define GFAR_MIIMCON_OFFSET 0x52c /* MII management control */ +#define GFAR_MIIMSTAT_OFFSET 0x530 /* MII management status */ +#define GFAR_MIIMMIND_OFFSET 0x534 /* MII management indicator */ +#define GFAR_MACSTRADDR1_OFFSET 0x540 /* MAC station address #1 */ +#define GFAR_MACSTRADDR2_OFFSET 0x544 /* MAC station address #2 */ + +/* eTSEC transmit and receive counters registers. */ +#define GFAR_TR64_OFFSET 0x680 +/* eTSEC counter control and TOE statistics registers */ +#define GFAR_CAM1_OFFSET 0x738 +#define GFAR_CAM2_OFFSET 0x73c + +/* Individual/group address registers */ +#define GFAR_IADDR0_OFFSET 0x800 +#define GFAR_IADDR1_OFFSET 0x804 +#define GFAR_IADDR2_OFFSET 0x808 +#define GFAR_IADDR3_OFFSET 0x80c +#define GFAR_IADDR4_OFFSET 0x810 +#define GFAR_IADDR5_OFFSET 0x814 +#define GFAR_IADDR6_OFFSET 0x818 +#define GFAR_IADDR7_OFFSET 0x81c + +#define GFAR_IADDR(REGNUM) (GFAR_IADDR##REGNUM##_OFFSET) + +/* Group address registers */ +#define GFAR_GADDR0_OFFSET 0x880 +#define GFAR_GADDR1_OFFSET 0x884 +#define GFAR_GADDR2_OFFSET 0x888 +#define GFAR_GADDR3_OFFSET 0x88c +#define GFAR_GADDR4_OFFSET 0x890 +#define GFAR_GADDR5_OFFSET 0x894 +#define GFAR_GADDR6_OFFSET 0x898 +#define GFAR_GADDR7_OFFSET 0x89c + +#define GFAR_GADDR(REGNUM) (GFAR_GADDR##REGNUM##_OFFSET) + +/* eTSEC DMA attributes registers */ +#define GFAR_ATTR_OFFSET 0xbf8 /* Default Attribute Register */ +#define GFAR_ATTRELI_OFFSET 0xbfc /* Default Attribute Extract Len/Idx */ + +struct gfar_private { + struct eth_device edev; + void __iomem *regs; + void __iomem *phyregs; + void __iomem *phyregs_sgmii; + struct phy_info *phyinfo; + struct mii_device miidev; + volatile struct txbd8 *txbd; + volatile struct rxbd8 *rxbd; + uint txidx; + uint rxidx; + uint phyaddr; + uint tbicr; + uint tbiana; + uint link; + uint duplexity; + uint speed; +}; +#endif /* __GIANFAR_H */ diff --git a/drivers/net/miidev.c b/drivers/net/miidev.c index b49944bbfe..75b53e3c5c 100644 --- a/drivers/net/miidev.c +++ b/drivers/net/miidev.c @@ -116,7 +116,7 @@ int miidev_wait_aneg(struct mii_device *mdev) return -ETIMEDOUT; } - } while (!(status & BMSR_LSTATUS)); + } while (!(status & BMSR_ANEGCOMPLETE)); return 0; } diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a249b81f51..b5c55a4afc 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -16,7 +16,7 @@ config DRIVER_SPI_IMX_0_0 config DRIVER_SPI_IMX_0_7 bool - depends on ARCH_IMX25 + depends on ARCH_IMX25 || ARCH_IMX35 default y config DRIVER_SPI_IMX_2_3 diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c index 2e59b3c8dd..80a14504f0 100644 --- a/drivers/spi/imx_spi.c +++ b/drivers/spi/imx_spi.c @@ -517,7 +517,7 @@ static int imx_spi_probe(struct device_d *dev) version = SPI_IMX_VER_0_0; #endif #ifdef CONFIG_DRIVER_SPI_IMX_0_7 - if (cpu_is_mx25()) + if (cpu_is_mx25() || cpu_is_mx35()) version = SPI_IMX_VER_0_7; #endif #ifdef CONFIG_DRIVER_SPI_IMX_2_3 diff --git a/fs/Kconfig b/fs/Kconfig index b75820f4a0..4c66543290 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1,6 +1,11 @@ menu "Filesystem support " +config FS + bool + default y + select FILETYPE + config FS_AUTOMOUNT bool diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 5e6c81c358..01724a234f 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -430,6 +430,7 @@ static struct fs_driver_d fat_driver = { .write = fat_write, .truncate = fat_truncate, #endif + .type = filetype_fat, .flags = 0, .drv = { .probe = fat_probe, @@ -26,6 +26,7 @@ #include <errno.h> #include <malloc.h> #include <linux/stat.h> +#include <linux/err.h> #include <fcntl.h> #include <xfuncs.h> #include <init.h> @@ -111,6 +112,61 @@ static int init_cwd(void) postcore_initcall(init_cwd); +char *normalise_link(const char *pathname, const char *symlink) +{ + const char *buf = symlink; + char *path_free, *path; + char *absolute_path; + int point = 0; + int dir = 1; + int len; + + if (symlink[0] == '/') + return strdup(symlink); + + while (*buf == '.' || *buf == '/') { + if (*buf == '.') { + point++; + } else if (*buf == '/') { + point = 0; + dir++; + } + if (point > 2) { + buf -= 2; + break; + } + buf++; + } + + path = path_free = strdup(pathname); + if (!path) + return NULL; + + while(dir) { + path = dirname(path); + dir--; + } + + len = strlen(buf) + strlen(path) + 1; + if (buf[0] != '/') + len++; + + absolute_path = calloc(sizeof(char), len); + + if (!absolute_path) + goto out; + + strcat(absolute_path, path); + if (buf[0] != '/') + strcat(absolute_path, "/"); + strcat(absolute_path, buf); + +out: + free(path_free); + + return absolute_path; +} + char *normalise_path(const char *pathname) { char *path = xzalloc(strlen(pathname) + strlen(cwd) + 2); @@ -187,6 +243,15 @@ static struct fs_device_d *get_fsdevice_by_path(const char *path) return fs_dev_root; } +char *get_mounted_path(const char *path) +{ + struct fs_device_d *fdev; + + fdev = get_fsdevice_by_path(path); + + return fdev->path; +} + static FILE files[MAX_FILES]; static FILE *get_file(void) @@ -392,7 +457,7 @@ static int path_check_prereq(const char *path, unsigned int flags) unsigned int m; int ret = 0; - if (stat(path, &s)) { + if (lstat(path, &s)) { if (flags & S_UB_DOES_NOT_EXIST) goto out; ret = -ENOENT; @@ -434,7 +499,7 @@ static int parent_check_directory(const char *path) int ret; char *dir = dirname(xstrdup(path)); - ret = stat(dir, &s); + ret = lstat(dir, &s); free(dir); @@ -512,18 +577,61 @@ out: } EXPORT_SYMBOL(unlink); +static char *realfile(const char *pathname, struct stat *s) +{ + char *path = normalise_path(pathname); + int ret; + + ret = lstat(path, s); + if (ret) + goto out; + + if (S_ISLNK(s->st_mode)) { + char tmp[PATH_MAX]; + char *new_path; + + memset(tmp, 0, PATH_MAX); + + ret = readlink(path, tmp, PATH_MAX - 1); + if (ret < 0) + goto out; + + new_path = normalise_link(path, tmp); + free(path); + if (!new_path) + return ERR_PTR(-ENOMEM); + path = new_path; + + ret = lstat(path, s); + } + + if (!ret) + return path; + +out: + free(path); + return ERR_PTR(ret); +} + int open(const char *pathname, int flags, ...) { struct fs_device_d *fsdev; struct fs_driver_d *fsdrv; FILE *f; - int exist_err; + int exist_err = 0; struct stat s; - char *path = normalise_path(pathname); - char *freep = path; + char *path; + char *freep; int ret; - exist_err = stat(path, &s); + path = realfile(pathname, &s); + + if (IS_ERR(path)) { + exist_err = PTR_ERR(path); + path = normalise_path(pathname); + } + + freep = path; if (!exist_err && S_ISDIR(s.st_mode)) { ret = -EISDIR; @@ -890,6 +998,94 @@ int close(int fd) } EXPORT_SYMBOL(close); +int readlink(const char *pathname, char *buf, size_t bufsiz) +{ + struct fs_driver_d *fsdrv; + struct fs_device_d *fsdev; + char *p = normalise_path(pathname); + char *freep = p; + int ret; + + ret = path_check_prereq(pathname, S_IFLNK); + if (ret) + goto out; + + fsdev = get_fs_device_and_root_path(&p); + if (!fsdev) { + ret = -ENODEV; + goto out; + } + fsdrv = fsdev->driver; + + if (fsdrv->readlink) + ret = fsdrv->readlink(&fsdev->dev, p, buf, bufsiz); + else + ret = -ENOSYS; + + if (ret) + goto out; + +out: + free(freep); + + if (ret) + errno = -ret; + + return ret; +} +EXPORT_SYMBOL(readlink); + +int symlink(const char *pathname, const char *newpath) +{ + struct fs_driver_d *fsdrv; + struct fs_device_d *fsdev; + char *p; + char *freep = normalise_path(pathname); + int ret; + struct stat s; + + if (!freep) + return -ENOMEM; + + if (!stat(freep, &s) && S_ISDIR(s.st_mode)) { + ret = -ENOSYS; + goto out; + } + + free(freep); + freep = p = normalise_path(newpath); + + if (!p) + return -ENOMEM; + + ret = lstat(p, &s); + if (!ret) { + ret = -EEXIST; + goto out; + } + + fsdev = get_fs_device_and_root_path(&p); + if (!fsdev) { + ret = -ENODEV; + goto out; + } + fsdrv = fsdev->driver; + + if (fsdrv->symlink) { + ret = fsdrv->symlink(&fsdev->dev, pathname, p); + } else { + ret = -EPERM; + } + +out: + free(freep); + if (ret) + errno = -ret; + + return ret; +} +EXPORT_SYMBOL(symlink); + static int fs_match(struct device_d *dev, struct driver_d *drv) { return strcmp(dev->name, drv->name) ? -1 : 0; @@ -954,6 +1150,28 @@ int register_fs_driver(struct fs_driver_d *fsdrv) } EXPORT_SYMBOL(register_fs_driver); +static const char *detect_fs(const char *filename) +{ + enum filetype type = file_name_detect_type(filename); + struct driver_d *drv; + struct fs_driver_d *fdrv; + + if (type == filetype_unknown) + return NULL; + + for_each_driver(drv) { + if (drv->bus != &fs_bus) + continue; + + fdrv = drv_to_fs_driver(drv); + + if (type == fdrv->type) + return drv->name; + } + + return NULL; +} + /* * Mount a device to a directory. * We do this by registering a new device on which the filesystem @@ -985,6 +1203,12 @@ int mount(const char *device, const char *fsname, const char *_path) } } + if (!fsname) + fsname = detect_fs(device); + + if (!fsname) + return -ENOENT; + fsdev = xzalloc(sizeof(struct fs_device_d)); fsdev->backingstore = xstrdup(device); safe_strncpy(fsdev->dev.name, fsname, MAX_DRIVER_NAME); @@ -1132,6 +1356,19 @@ EXPORT_SYMBOL(closedir); int stat(const char *filename, struct stat *s) { + char *f; + + f = realfile(filename, s); + if (IS_ERR(f)) + return PTR_ERR(f); + + free(f); + return 0; +} +EXPORT_SYMBOL(stat); + +int lstat(const char *filename, struct stat *s) +{ struct device_d *dev; struct fs_driver_d *fsdrv; struct fs_device_d *fsdev; @@ -1169,7 +1406,7 @@ out: return ret; } -EXPORT_SYMBOL(stat); +EXPORT_SYMBOL(lstat); int mkdir (const char *pathname, mode_t mode) { @@ -1216,13 +1453,19 @@ int rmdir (const char *pathname) char *freep = p; int ret; + ret = path_check_prereq(pathname, S_IFLNK); + if (!ret) { + ret = -ENOTDIR; + goto out; + } + ret = path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY); if (ret) goto out; fsdev = get_fs_device_and_root_path(&p); if (!fsdev) { - ret = -ENOENT; + ret = -ENODEV; goto out; } fsdrv = fsdev->driver; @@ -605,34 +605,6 @@ static int nfs_read_req(struct file_priv *priv, int offset, int readlen) return 0; } -#if 0 -static int nfs_readlink_reply(unsigned char *pkt, unsigned len) -{ - uint32_t *data; - char *path; - int rlen; -// int ret; - - data = (uint32_t *)(pkt + sizeof(struct rpc_reply)); - - data++; - - rlen = ntohl(net_read_uint32(data)); /* new path length */ - - data++; - path = (char *)data; - - if (*path != '/') { - strcat(nfs_path, "/"); - strncat(nfs_path, path, rlen); - } else { - memcpy(nfs_path, path, rlen); - nfs_path[rlen] = 0; - } - return 0; -} -#endif - static void nfs_handler(void *ctx, char *packet, unsigned len) { char *pkt = net_eth_to_udp_payload(packet); @@ -742,6 +714,63 @@ static struct file_priv *nfs_do_stat(struct device_d *dev, const char *filename, return priv; } +static int nfs_readlink_req(struct file_priv *priv, char* buf, size_t size) +{ + uint32_t data[1024]; + uint32_t *p; + int len; + int ret; + char *path; + uint32_t *filedata; + + p = &(data[0]); + p = rpc_add_credentials(p); + + memcpy(p, priv->filefh, NFS_FHSIZE); + p += (NFS_FHSIZE / 4); + + len = p - &(data[0]); + + ret = rpc_req(priv->npriv, PROG_NFS, NFS_READLINK, data, len); + if (ret) + return ret; + + filedata = nfs_packet + sizeof(struct rpc_reply); + filedata++; + + len = ntohl(net_read_uint32(filedata)); /* new path length */ + filedata++; + + path = (char *)filedata; + + if (len > size) + len = size; + + memcpy(buf, path, len); + + return 0; +} + +static int nfs_readlink(struct device_d *dev, const char *filename, + char *realname, size_t size) +{ + struct file_priv *priv; + int ret; + struct stat s; + + priv = nfs_do_stat(dev, filename, &s); + if (IS_ERR(priv)) + return PTR_ERR(priv); + + ret = nfs_readlink_req(priv, realname, size); + if (ret) { + nfs_do_close(priv); + return ret; + } + + return 0; +} + static int nfs_open(struct device_d *dev, FILE *file, const char *filename) { struct file_priv *priv; @@ -1039,6 +1068,7 @@ static struct fs_driver_d nfs_driver = { .rmdir = nfs_rmdir, .write = nfs_write, .truncate = nfs_truncate, + .readlink = nfs_readlink, .flags = 0, .drv = { .probe = nfs_probe, diff --git a/fs/ramfs.c b/fs/ramfs.c index 91d06b8d3a..8f3b936685 100644 --- a/fs/ramfs.c +++ b/fs/ramfs.c @@ -42,6 +42,7 @@ struct ramfs_inode { struct ramfs_inode *parent; struct ramfs_inode *next; struct ramfs_inode *child; + char *symlink; ulong mode; struct handle_d *handle; @@ -176,6 +177,7 @@ static void ramfs_put_inode(struct ramfs_inode *node) data = tmp; } + free(node->symlink); free(node->name); free(node); } @@ -212,18 +214,38 @@ static struct ramfs_inode* node_insert(struct ramfs_inode *parent_node, const ch /* ---------------------------------------------------------------*/ -static int ramfs_create(struct device_d *dev, const char *pathname, mode_t mode) +static int __ramfs_create(struct device_d *dev, const char *pathname, + mode_t mode, const char *symlink) { struct ramfs_priv *priv = dev->priv; struct ramfs_inode *node; char *file; + char *__symlink = NULL; node = rlookup_parent(priv, pathname, &file); - if (node) { - node_insert(node, file, mode); - return 0; + if (!node) + return -ENOENT; + + if (symlink) { + __symlink = strdup(symlink); + if (!__symlink) + return -ENOMEM; } - return -ENOENT; + + node = node_insert(node, file, mode); + if (!node) { + free(__symlink); + return -ENOMEM; + } + + node->symlink = __symlink; + + return 0; +} + +static int ramfs_create(struct device_d *dev, const char *pathname, mode_t mode) +{ + return __ramfs_create(dev, pathname, mode, NULL); } static int ramfs_unlink(struct device_d *dev, const char *pathname) @@ -532,12 +554,37 @@ static int ramfs_stat(struct device_d *dev, const char *filename, struct stat *s if (!node) return -ENOENT; - s->st_size = node->size; + s->st_size = node->symlink ? strlen(node->symlink) : node->size; s->st_mode = node->mode; return 0; } +static int ramfs_symlink(struct device_d *dev, const char *pathname, + const char *newpath) +{ + mode_t mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; + + return __ramfs_create(dev, newpath, mode, pathname); +} + +static int ramfs_readlink(struct device_d *dev, const char *pathname, + char *buf, size_t bufsiz) +{ + struct ramfs_priv *priv = dev->priv; + struct ramfs_inode *node = rlookup(priv, pathname); + int len; + + if (!node || !node->symlink) + return -ENOENT; + + len = min(bufsiz, strlen(node->symlink)); + + memcpy(buf, node->symlink, len); + + return 0; +} + static int ramfs_probe(struct device_d *dev) { struct ramfs_inode *n; @@ -584,6 +631,8 @@ static struct fs_driver_d ramfs_driver = { .readdir = ramfs_readdir, .closedir = ramfs_closedir, .stat = ramfs_stat, + .symlink = ramfs_symlink, + .readlink = ramfs_readlink, .flags = FS_DRIVER_NO_DEV, .drv = { .probe = ramfs_probe, diff --git a/include/asm-generic/memory_layout.h b/include/asm-generic/memory_layout.h index 941cd42955..eb1607f36d 100644 --- a/include/asm-generic/memory_layout.h +++ b/include/asm-generic/memory_layout.h @@ -13,6 +13,7 @@ #endif +#define HEAD_TEXT_BASE MALLOC_BASE #define MALLOC_SIZE CONFIG_MALLOC_SIZE #define STACK_SIZE CONFIG_STACK_SIZE diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 5484b6f004..17d5fd1ae4 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -7,8 +7,10 @@ extern char __bare_init_start[], __bare_init_end[]; extern char _end[]; extern void *_barebox_image_size; extern void *_barebox_bare_init_size; +extern void *_barebox_pbl_size; #define barebox_image_size (unsigned int)&_barebox_image_size #define barebox_bare_init_size (unsigned int)&_barebox_bare_init_size +#define barebox_pbl_size (unsigned int)&_barebox_pbl_size #endif /* _ASM_GENERIC_SECTIONS_H_ */ diff --git a/include/driver.h b/include/driver.h index 0a8dc8edd3..0fecc7a670 100644 --- a/include/driver.h +++ b/include/driver.h @@ -127,9 +127,9 @@ struct driver_d { #define RW_SIZE_MASK 0x7 /* dynamically assign the next free id */ -#define DEVICE_ID_DYNAMIC -1 +#define DEVICE_ID_DYNAMIC -2 /* do not use an id (only one device available */ -#define DEVICE_ID_SINGLE -2 +#define DEVICE_ID_SINGLE -1 /* Register devices and drivers. */ diff --git a/include/envfs.h b/include/envfs.h index ba976d6d13..3d14fcb9ee 100644 --- a/include/envfs.h +++ b/include/envfs.h @@ -5,15 +5,19 @@ #include <asm/byteorder.h> #endif +#define ENVFS_MAJOR 1 +#define ENVFS_MINOR 0 + #define ENVFS_MAGIC 0x798fba79 /* some random number */ #define ENVFS_INODE_MAGIC 0x67a8c78d +#define ENVFS_INODE_END_MAGIC 0x68a8c78d #define ENVFS_END_MAGIC 0x6a87d6cd #define ENVFS_SIGNATURE "barebox envfs" struct envfs_inode { uint32_t magic; /* ENVFS_INODE_MAGIC */ uint32_t size; /* data size in bytes */ - uint32_t namelen; /* The length of the filename _including_ a trailing 0 */ + uint32_t headerlen; /* The length of the filename _including_ a trailing 0 */ char data[0]; /* The filename (zero terminated) + padding to 4 byte boundary * followed by the data for this inode. * The next inode follows after the data + padding to 4 byte @@ -21,6 +25,11 @@ struct envfs_inode { */ }; +struct envfs_inode_end { + uint32_t magic; /* ENVFS_INODE_END_MAGIC */ + uint32_t mode; /* file mode */ +}; + /* * Superblock information at the beginning of the FS. */ @@ -29,8 +38,10 @@ struct envfs_super { uint32_t priority; uint32_t crc; /* crc for the data */ uint32_t size; /* size of data */ + uint8_t major; /* major */ + uint8_t minor; /* minor */ + uint16_t future; /* reserved for future use */ uint32_t flags; /* feature flags */ - uint32_t future; /* reserved for future use */ uint32_t sb_crc; /* crc for the superblock */ }; diff --git a/include/filetype.h b/include/filetype.h index f5de8ed2b5..179ec0f5eb 100644 --- a/include/filetype.h +++ b/include/filetype.h @@ -18,6 +18,7 @@ enum filetype { filetype_aimage, filetype_sh, filetype_mips_barebox, + filetype_fat, }; const char *file_type_to_string(enum filetype f); diff --git a/include/fs.h b/include/fs.h index c0b9f71fbd..3d5714c1fb 100644 --- a/include/fs.h +++ b/include/fs.h @@ -2,6 +2,7 @@ #define __FS_H #include <driver.h> +#include <filetype.h> #define PATH_MAX 1024 /* include/linux/limits.h */ @@ -50,6 +51,11 @@ struct fs_driver_d { /* Truncate a file to given size */ int (*truncate)(struct device_d *dev, FILE *f, ulong size); + int (*symlink)(struct device_d *dev, const char *pathname, + const char *newpath); + int (*readlink)(struct device_d *dev, const char *pathname, char *name, + size_t size); + int (*open)(struct device_d *dev, FILE *f, const char *pathname); int (*close)(struct device_d *dev, FILE *f); int (*read)(struct device_d *dev, FILE *f, void *buf, size_t size); @@ -72,6 +78,8 @@ struct fs_driver_d { struct driver_d drv; + enum filetype type; + unsigned long flags; }; @@ -93,6 +101,8 @@ struct fs_device_d { struct list_head list; }; +#define drv_to_fs_driver(d) container_of(d, struct fs_driver_d, drv) + /* * standard posix file functions */ @@ -101,6 +111,7 @@ int creat(const char *pathname, mode_t mode); int unlink(const char *pathname); int close(int fd); int flush(int fd); +int lstat(const char *filename, struct stat *s); int stat(const char *filename, struct stat *s); int read(int fd, void *buf, size_t count); int ioctl(int fd, int request, void *buf); @@ -124,6 +135,9 @@ DIR *opendir(const char *pathname); struct dirent *readdir(DIR *dir); int closedir(DIR *dir); +int symlink(const char *pathname, const char *newpath); +int readlink(const char *path, char *buf, size_t bufsiz); + int mount (const char *device, const char *fsname, const char *path); int umount(const char *pathname); @@ -157,6 +171,9 @@ void *read_file(const char *filename, size_t *size); * of "..", "." and double slashes. The returned string must be freed wit free(). */ char *normalise_path(const char *path); +char *normalise_link(const char *pathname, const char* symlink); + +char *get_mounted_path(const char *path); /* Register a new filesystem driver */ int register_fs_driver(struct fs_driver_d *fsdrv); diff --git a/include/gpio.h b/include/gpio.h index b7d840211a..9fb11c3268 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -5,10 +5,35 @@ static inline int gpio_request(unsigned gpio, const char *label) { - return 0; + return 0; } static inline void gpio_free(unsigned gpio) { } + +struct gpio_chip; + +struct gpio_ops { + int (*direction_input)(struct gpio_chip *chip, unsigned offset); + int (*direction_output)(struct gpio_chip *chip, unsigned offset, int value); + int (*get)(struct gpio_chip *chip, unsigned offset); + void (*set)(struct gpio_chip *chip, unsigned offset, int value); +}; + +struct gpio_chip { + struct device_d *dev; + + int base; + int ngpio; + + struct gpio_ops *ops; + + struct list_head list; +}; + +int gpiochip_add(struct gpio_chip *chip); + +int gpio_get_num(struct device_d *dev, int gpio); + #endif /* __GPIO_H */ diff --git a/include/jtag.h b/include/jtag.h new file mode 100644 index 0000000000..26c95fb307 --- /dev/null +++ b/include/jtag.h @@ -0,0 +1,109 @@ +/* + * include/linux/jtag.h + * + * Written Aug 2009 by Davide Rizzo <elpa.rizzo@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * This driver manages one or more jtag chains controlled by host pins. + * Jtag chains must be defined during setup using jtag_platdata structs. + * All operations must be done from user programs using ioctls to /dev/jtag + * Typical operation sequence is: + * - open() the device (normally /dev/jtag) + * - ioctl JTAG_GET_DEVICES reads how many devices in the chain + * (repeat for each chip in the chain) + * - ioctl JTAG_GET_ID identifies the chip + * - ioctl JTAG_SET_IR_LENGTH sets the instruction register length + * Before accessing the data registers, instruction registers' lenghtes + * MUST be programmed for all chips. + * After this initialization, you can execute JTAG_IR_WR, JTAG_DR_RD, JTAG_DR_WR + * commands in any sequence. + */ + +#ifndef __JTAG_H__ +#define __JTAG_H__ + +/* Controller's gpio_tdi must be connected to last device's gpio_tdo */ +/* Controller's gpio_tdo must be connected to first device's gpio_tdi */ +struct jtag_platdata { + unsigned int gpio_tclk; + unsigned int gpio_tms; + unsigned int gpio_tdi; + unsigned int gpio_tdo; + unsigned int gpio_trst; + int use_gpio_trst; +}; + +#define JTAG_NAME "jtag" + +/* structures used for passing arguments to ioctl */ + +struct jtag_rd_id { + int device; /* Device in the chain */ + unsigned long id; +}; + +struct jtag_cmd { + int device; /* Device in the chain (-1 = all devices) */ + unsigned int bitlen; /* Bit length of the register to be transfered */ + unsigned long *data; /* Data to be transfered */ +}; + +/* Use 'j' as magic number */ +#define JTAG_IOC_MAGIC 'j' + +/* ioctl commands */ + +/* Resets jtag chain status, arg is ignored */ +#define JTAG_RESET _IO(JTAG_IOC_MAGIC, 0) + +/* Returns the number of devices in the jtag chain, arg is ignored. */ +#define JTAG_GET_DEVICES _IO(JTAG_IOC_MAGIC, 1) + +/* arg must point to a jtag_rd_id structure. + Fills up the id field with ID of selected device */ +#define JTAG_GET_ID _IOR(JTAG_IOC_MAGIC, 2, struct jtag_rd_id) + +/* arg must point to a struct jtag_cmd. + Programs the Instruction Register length of specified device at bitlen value. + *data is ignored. */ +#define JTAG_SET_IR_LENGTH _IOW(JTAG_IOC_MAGIC, 3, struct jtag_rd_id) + +/* arg must point to a struct jtag_cmd. + Writes *data in the Instruction Register of selected device, and BYPASS + instruction into Instruction Registers of all other devices in the chain. + If device == -1, the Instruction Registers of all devices are programmed + to the same value. + bitlen is always ignored, before using this command you have to program all + Instruction Register's lengthes with JTAG_SET_IR_LENGTH command. */ +#define JTAG_IR_WR _IOW(JTAG_IOC_MAGIC, 4, struct jtag_cmd) + +/* arg must point to a struct jtag_cmd. + Reads data register of selected device, with length bitlen */ +#define JTAG_DR_RD _IOR(JTAG_IOC_MAGIC, 5, struct jtag_cmd) + +/* arg must point to a struct jtag_cmd. + Writes data register of selected device, with length bitlen. + If device == -1, writes same data on all devices. */ +#define JTAG_DR_WR _IOW(JTAG_IOC_MAGIC, 6, struct jtag_cmd) + +/* Generates arg pulses on TCLK pin */ +#define JTAG_CLK _IOW(JTAG_IOC_MAGIC, 7, unsigned int *) + +#define JTAG_IOC_MAXNR 9 + +#endif /* __JTAG_H__ */ diff --git a/include/libbb.h b/include/libbb.h index 110e8ec39d..47b2e08296 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -14,7 +14,7 @@ char* last_char_is(const char *s, int c); enum { ACTION_RECURSE = (1 << 0), - /* ACTION_FOLLOWLINKS = (1 << 1), - unused */ + ACTION_FOLLOWLINKS = (1 << 1), ACTION_DEPTHFIRST = (1 << 2), /*ACTION_REVERSE = (1 << 3), - unused */ }; diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h new file mode 100644 index 0000000000..0c354110c0 --- /dev/null +++ b/include/linux/decompress/mm.h @@ -0,0 +1,68 @@ +/* + * linux/compr_mm.h + * + * Memory management for pre-boot and ramdisk uncompressors + * + * Authors: Alain Knaff <alain@knaff.lu> + * + */ + +#ifndef DECOMPR_MM_H +#define DECOMPR_MM_H + +#ifdef STATIC + +/* Code active when included from pre-boot environment: */ + +/* + * Some architectures want to ensure there is no local data in their + * pre-boot environment, so that data can arbitrarily relocated (via + * GOT references). This is achieved by defining STATIC_RW_DATA to + * be null. + */ +#ifndef STATIC_RW_DATA +#define STATIC_RW_DATA static +#endif + +/* A trivial malloc implementation, adapted from + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + */ +STATIC_RW_DATA unsigned long malloc_ptr; +STATIC_RW_DATA int malloc_count; + +static void *malloc(int size) +{ + void *p; + + if (size < 0) + return NULL; + if (!malloc_ptr) + malloc_ptr = free_mem_ptr; + + malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */ + + p = (void *)malloc_ptr; + malloc_ptr += size; + + if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) + return NULL; + + malloc_count++; + return p; +} + +static void free(void *where) +{ + malloc_count--; + if (!malloc_count) + malloc_ptr = free_mem_ptr; +} + +#define large_malloc(a) malloc(a) +#define large_free(a) free(a) + +#define INIT + +#endif /* STATIC */ + +#endif /* DECOMPR_MM_H */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 4a492b5bcb..d2f864897c 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -169,6 +169,8 @@ typedef enum { #define NAND_NO_READRDY 0x00000100 /* Chip does not allow subpage writes */ #define NAND_NO_SUBPAGE_WRITE 0x00000200 +/* Buswitdh shal be autodetected */ +#define NAND_BUSWIDTH_AUTO 0x00080000 /* Options valid for Samsung large page devices */ @@ -451,6 +453,7 @@ struct nand_chip { int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int page, int cached, int raw); + int (*set_buswidth)(struct mtd_info *mtd, struct nand_chip *this, int buswidth); int chip_delay; unsigned int options; diff --git a/include/mfd/mc13xxx.h b/include/mfd/mc13xxx.h index 632c9fbe4b..59042ebee6 100644 --- a/include/mfd/mc13xxx.h +++ b/include/mfd/mc13xxx.h @@ -150,21 +150,11 @@ #define MC13783_SW1B_SOFTSTART (1 << 17) #define MC13783_SW_PLL_FACTOR(x) (((x) - 28) << 19) -enum mc13xxx_mode { - MC13XXX_MODE_I2C, - MC13XXX_MODE_SPI, -}; - -struct mc13xxx { - struct cdev cdev; - struct i2c_client *client; - struct spi_device *spi; - enum mc13xxx_mode mode; - int revision; -}; +struct mc13xxx; #ifdef CONFIG_MFD_MC13XXX extern struct mc13xxx *mc13xxx_get(void); +extern int mc13xxx_revision(struct mc13xxx *mc13xxx); extern int mc13xxx_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val); extern int mc13xxx_reg_write(struct mc13xxx *mc13xxx, u8 reg, u32 val); extern int mc13xxx_set_bits(struct mc13xxx *mc13xxx, u8 reg, u32 mask, u32 val); @@ -174,6 +164,11 @@ static inline struct mc13xxx *mc13xxx_get(void) return NULL; } +static inline int mc13xxx_revision(struct mc13xxx *mc13xxx) +{ + return -ENODEV; +} + static inline int mc13xxx_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val) { return -ENODEV; diff --git a/include/mfd/stmpe-i2c.h b/include/mfd/stmpe-i2c.h new file mode 100644 index 0000000000..5f073d22d2 --- /dev/null +++ b/include/mfd/stmpe-i2c.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 Pengutronix + * Steffen Trumtrar <s.trumtrar@pengutronix.de> + * + * This file is released under the GPLv2 + * + */ + +#ifndef __ASM_ARCH_STMPE_H +#define __ASM_ARCH_STMPE_H + +enum stmpe_revision { + STMPE610, + STMPE801, + STMPE811, + STMPE1601, + STMPE2401, + STMPE2403, + STMPE_NBR_PARTS +}; + +enum stmpe_blocks { + STMPE_BLOCK_GPIO = 1 << 0, + STMPE_BLOCK_KEYPAD = 1 << 1, + STMPE_BLOCK_TOUCHSCREEN = 1 << 2, + STMPE_BLOCK_ADC = 1 << 3, + STMPE_BLOCK_PWM = 1 << 4, + STMPE_BLOCK_ROTATOR = 1 << 5, +}; + +struct stmpe_platform_data { + enum stmpe_revision revision; + enum stmpe_blocks blocks; + int gpio_base; +}; + +struct stmpe { + struct cdev cdev; + struct i2c_client *client; + struct stmpe_platform_data *pdata; +}; + +struct stmpe_client_info { + struct stmpe *stmpe; + int (*read_reg)(struct stmpe *stmpe, u32 reg, u8 *val); + int (*write_reg)(struct stmpe *stmpe, u32 reg, u8 val); +}; + +int stmpe_reg_read(struct stmpe *priv, u32 reg, u8 *val); +int stmpe_reg_write(struct stmpe *priv, u32 reg, u8 val); +int stmpe_set_bits(struct stmpe *priv, u32 reg, u8 mask, u8 val); + +#endif /* __ASM_ARCH_STMPE_H */ diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c index 526d6a173f..5c1ebb6850 100644 --- a/lib/decompress_inflate.c +++ b/lib/decompress_inflate.c @@ -4,6 +4,7 @@ /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots * errors about console_printk etc... on ARM */ #define _LINUX_KERNEL_H +#include <linux/decompress/mm.h> #include "zlib_inflate/inftrees.c" #include "zlib_inflate/inffast.c" diff --git a/lib/recursive_action.c b/lib/recursive_action.c index 1ef758df61..5bc2595db9 100644 --- a/lib/recursive_action.c +++ b/lib/recursive_action.c @@ -54,14 +54,19 @@ int recursive_action(const char *fileName, const unsigned depth) { struct stat statbuf; + unsigned follow; int status; DIR *dir; struct dirent *next; if (!fileAction) fileAction = true_action; if (!dirAction) dirAction = true_action; - status = stat(fileName, &statbuf); + follow = ACTION_FOLLOWLINKS; + if (depth == 0) + follow = ACTION_FOLLOWLINKS; + follow &= flags; + status = (follow ? stat : lstat)(fileName, &statbuf); if (status < 0) { #ifdef DEBUG_RECURS_ACTION bb_error_msg("status=%d followLinks=%d TRUE=%d", diff --git a/pbl/Makefile b/pbl/Makefile new file mode 100644 index 0000000000..7169c6c72a --- /dev/null +++ b/pbl/Makefile @@ -0,0 +1,5 @@ +# +# only unsed by the pbl +# +pbl-y += misc.o +pbl-y += string.o diff --git a/pbl/misc.c b/pbl/misc.c new file mode 100644 index 0000000000..47e9ceabe3 --- /dev/null +++ b/pbl/misc.c @@ -0,0 +1,14 @@ +#include <common.h> +#include <init.h> +#include <linux/types.h> +#include <linux/string.h> +#include <linux/ctype.h> + +void __noreturn panic(const char *fmt, ...) +{ + while(1); +} + +void start_barebox(void) +{ +} diff --git a/pbl/string.c b/pbl/string.c new file mode 100644 index 0000000000..6787e82c9b --- /dev/null +++ b/pbl/string.c @@ -0,0 +1,127 @@ +/* + * arch/arm/boot/compressed/string.c + * + * Small subset of simple string routines + */ + +#include <linux/types.h> + +void *memcpy(void *__dest, __const void *__src, size_t __n) +{ + int i = 0; + unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; + + for (i = __n >> 3; i > 0; i--) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 2) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 1) { + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1) + *d++ = *s++; + + return __dest; +} + +void *memmove(void *__dest, __const void *__src, size_t count) +{ + unsigned char *d = __dest; + const unsigned char *s = __src; + + if (__dest == __src) + return __dest; + + if (__dest < __src) + return memcpy(__dest, __src, count); + + while (count--) + d[count] = s[count]; + return __dest; +} + +size_t strlen(const char *s) +{ + const char *sc = s; + + while (*sc != '\0') + sc++; + return sc - s; +} + +int memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count; + int res = 0; + + while (su1 < end) { + res = *su1++ - *su2++; + if (res) + break; + } + return res; +} + +int strcmp(const char *cs, const char *ct) +{ + unsigned char c1, c2; + int res = 0; + + do { + c1 = *cs++; + c2 = *ct++; + res = c1 - c2; + if (res) + break; + } while (c1); + return res; +} + +void *memchr(const void *s, int c, size_t count) +{ + const unsigned char *p = s; + + while (count--) + if ((unsigned char)c == *p++) + return (void *)(p - 1); + return NULL; +} + +char *strchr(const char *s, int c) +{ + while (*s != (char)c) + if (*s++ == '\0') + return NULL; + return (char *)s; +} + +#undef memset + +void *memset(void *s, int c, size_t count) +{ + char *xs = s; + while (count--) + *xs++ = c; + return s; +} + +void __memzero(void *s, size_t count) +{ + memset(s, 0, count); +} diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 1a82c44bd4..383d73f66b 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -14,6 +14,7 @@ obj-y := obj-m := lib-y := lib-m := +pbl-y := always := targets := subdir-y := @@ -97,13 +98,19 @@ ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),) lib-target := $(obj)/lib.a endif -ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),) +ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target) $(pbl-y)),) builtin-target := $(obj)/built-in.o endif +ifeq ($(CONFIG_PBL_IMAGE), y) +ifneq ($(strip $(pbl-y) $(builtin-target)),) +pbl-target := $(obj)/built-in-pbl.o +endif +endif + # We keep a list of all modules in $(MODVERDIR) -__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ +__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(pbl-target) $(extra-y)) \ $(if $(KBUILD_MODULES),$(obj-m)) \ $(subdir-ym) $(always) @: @@ -177,9 +184,11 @@ cmd_cc_symtypes_c = \ # (See cmd_cc_o_c + relevant part of rule_cc_o_c) quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ +quiet_cmd_pbl_cc_o_c = PBLCC $@ ifndef CONFIG_MODVERSIONS cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< +cmd_pbl_cc_o_c = $(CC) -D__PBL__ $(c_flags) $(PBL_CPPFLAGS) -c -o $@ $< else # When module versioning is enabled the following steps are executed: @@ -220,8 +229,22 @@ define rule_cc_o_c mv -f $(dot-target).tmp $(dot-target).cmd endef +define rule_pbl_cc_o_c + $(call echo-cmd,checksrc) $(cmd_checksrc) \ + $(call echo-cmd,pbl_cc_o_c) $(cmd_pbl_cc_o_c); \ + $(cmd_modversions) \ + scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,pbl_cc__o_c)' > \ + $(dot-target).tmp; \ + rm -f $(depfile); \ + mv -f $(dot-target).tmp $(dot-target).cmd +endef + # Built-in and composite module parts +pbl-%.o: %.c + $(call cmd,force_checksrc) + $(call if_changed_rule,pbl_cc_o_c) + %.o: %.c FORCE $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) @@ -258,10 +281,16 @@ cmd_as_s_S = $(CPP) $(a_flags) -o $@ $< quiet_cmd_as_o_S = AS $(quiet_modtag) $@ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< +quiet_cmd_pbl_as_o_S = PBLAS $@ +cmd_pbl_as_o_S = $(CC) -D__PBL__ $(a_flags) $(PBL_CPPFLAGS) -c -o $@ $< + +pbl-%.o: %.S + $(call if_changed_dep,pbl_as_o_S) + %.o: %.S FORCE $(call if_changed_dep,as_o_S) -targets += $(real-objs-y) $(real-objs-m) $(lib-y) +targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(pbl-y) targets += $(extra-y) $(MAKECMDGOALS) $(always) # Linker scripts preprocessor (.lds.S -> .lds) @@ -294,6 +323,19 @@ $(builtin-target): $(obj-y) FORCE targets += $(builtin-target) endif # builtin-target +ifdef pbl-target +quiet_cmd_pbl_link_o_target = PBLLD $@ +# If the list of objects to link is empty, just create an empty built-in-pbl.o +cmd_pbl_link_o_target = $(if $(strip $(pbl-y)),\ + $(LD) $(ld_flags) -r -o $@ $(filter $(pbl-y), $^),\ + rm -f $@; $(AR) rcs $@) + +$(pbl-target): $(pbl-y) FORCE + $(call if_changed,pbl_link_o_target) + +targets += $(pbl-target) +endif # pbl-target + # # Rule to compile a set of .o files into one .a file # diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index 702f491613..cff33498fa 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -14,7 +14,7 @@ clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj # The filename Kbuild has precedence over Makefile kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) -#include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) +include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) # Figure out what we need to build from the various variables # ========================================================================== diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index b842c48801..cb46db225e 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -21,6 +21,17 @@ lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) # o if we encounter foo/ in $(obj-m), remove it from $(obj-m) # and add the directory to the list of dirs to descend into: $(subdir-m) +# for non dirs add pbl- prefix to the target +# so we recompile the source with custom flags and custom quiet +__pbl-y := $(notdir $(pbl-y)) +pbl-y := $(patsubst %.o,pbl-%.o,$(__pbl-y)) +# add subdir from $(obj-y) too so we do not need to have the dir define in +# both $(obj-y) and $(pbl-y) +__pbl-y := $(filter-out $(pbl-y), $(filter %/, $(obj-y))) +pbl-y += $(__pbl-y) + +pbl-y := $(sort $(patsubst %/, %/built-in-pbl.o, $(pbl-y))) + __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) subdir-y += $(__subdir-y) __subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) @@ -46,7 +57,9 @@ multi-objs := $(multi-objs-y) $(multi-objs-m) # $(subdir-obj-y) is the list of objects in $(obj-y) which do not live # in the local directory +__subdir-obj-y := $(foreach o,$(pbl-y),$(if $(filter-out $(o),$(notdir $(o))),$(o))) subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o))) +subdir-obj-y += $(__subdir-obj-y) # $(obj-dirs) is a list of directories that contain object files obj-dirs := $(dir $(multi-objs) $(subdir-obj-y)) @@ -63,6 +76,7 @@ targets := $(addprefix $(obj)/,$(targets)) obj-y := $(addprefix $(obj)/,$(obj-y)) obj-m := $(addprefix $(obj)/,$(obj-m)) lib-y := $(addprefix $(obj)/,$(lib-y)) +pbl-y := $(addprefix $(obj)/,$(pbl-y)) subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y)) real-objs-y := $(addprefix $(obj)/,$(real-objs-y)) real-objs-m := $(addprefix $(obj)/,$(real-objs-m)) @@ -228,3 +242,9 @@ quiet_cmd_xzmisc = XZMISC $@ cmd_xzmisc = (cat $(filter-out FORCE,$^) | \ xz --check=crc32 --lzma2=dict=1MiB) > $@ || \ (rm -f $@ ; false) + +quiet_cmd_disasm = DISASM $@ +cmd_disasm = $(OBJDUMP) -d $< > $@ + +quiet_cmd_ln = LN $@ +cmd_ln = ln -sf $< $@ diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c index 866e345b9b..f7f5351ca6 100644 --- a/scripts/bareboxenv.c +++ b/scripts/bareboxenv.c @@ -73,7 +73,7 @@ char* last_char_is(const char *s, int c) enum { ACTION_RECURSE = (1 << 0), - /* ACTION_FOLLOWLINKS = (1 << 1), - unused */ + ACTION_FOLLOWLINKS = (1 << 1), ACTION_DEPTHFIRST = (1 << 2), /*ACTION_REVERSE = (1 << 3), - unused */ }; |