]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-usb
authorTom Rini <trini@ti.com>
Sun, 26 Oct 2014 18:12:18 +0000 (14:12 -0400)
committerTom Rini <trini@ti.com>
Sun, 26 Oct 2014 18:12:18 +0000 (14:12 -0400)
398 files changed:
Makefile
README
arch/Kconfig
arch/arm/Kconfig
arch/arm/cpu/arm926ejs/at91/led.c
arch/arm/cpu/arm926ejs/kirkwood/Makefile
arch/arm/cpu/arm926ejs/kirkwood/cpu.c
arch/arm/cpu/arm926ejs/kirkwood/mpp.c
arch/arm/cpu/armv7/am33xx/board.c
arch/arm/cpu/armv7/armada-xp/Makefile [new file with mode: 0644]
arch/arm/cpu/armv7/armada-xp/cpu.c [new file with mode: 0644]
arch/arm/cpu/armv7/exynos/pinmux.c
arch/arm/cpu/armv7/mx6/soc.c
arch/arm/cpu/armv7/omap3/board.c
arch/arm/cpu/armv7/omap3/emif4.c
arch/arm/cpu/armv7/omap3/sys_info.c
arch/arm/cpu/armv7/tegra-common/Kconfig
arch/arm/cpu/armv7/tegra20/display.c
arch/arm/cpu/armv7/tegra30/Kconfig
arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c [new file with mode: 0644]
arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c [new file with mode: 0644]
arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c [new file with mode: 0644]
arch/arm/cpu/tegra-common/board.c
arch/arm/cpu/tegra-common/sys_info.c
arch/arm/dts/Makefile
arch/arm/dts/am335x-bone-common.dtsi
arch/arm/dts/dt-bindings/gpio/gpio.h [deleted file]
arch/arm/dts/exynos4.dtsi
arch/arm/dts/exynos4210-origen.dts
arch/arm/dts/exynos4210-pinctrl-uboot.dtsi [new file with mode: 0644]
arch/arm/dts/exynos4210-pinctrl.dtsi [new file with mode: 0644]
arch/arm/dts/exynos4210-smdkv310.dts
arch/arm/dts/exynos4210-trats.dts
arch/arm/dts/exynos4210-universal_c210.dts
arch/arm/dts/exynos4210.dtsi [new file with mode: 0644]
arch/arm/dts/exynos4412-odroid.dts
arch/arm/dts/exynos4412-trats2.dts
arch/arm/dts/exynos4412.dtsi [new file with mode: 0644]
arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi [new file with mode: 0644]
arch/arm/dts/exynos4x12-pinctrl.dtsi [new file with mode: 0644]
arch/arm/dts/exynos4x12.dtsi [new file with mode: 0644]
arch/arm/dts/exynos5.dtsi
arch/arm/dts/exynos5250-pinctrl-uboot.dtsi [new file with mode: 0644]
arch/arm/dts/exynos5250-pinctrl.dtsi [new file with mode: 0644]
arch/arm/dts/exynos5250-smdk5250.dts
arch/arm/dts/exynos5250-snow.dts
arch/arm/dts/exynos5250.dtsi
arch/arm/dts/exynos5420-peach-pit.dts
arch/arm/dts/exynos5420-smdk5420.dts
arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi [new file with mode: 0644]
arch/arm/dts/exynos54xx-pinctrl.dtsi [new file with mode: 0644]
arch/arm/dts/exynos54xx.dtsi
arch/arm/dts/s5pc100-pinctrl.dtsi [new file with mode: 0644]
arch/arm/dts/s5pc110-pinctrl.dtsi [new file with mode: 0644]
arch/arm/dts/s5pc1xx-goni.dts
arch/arm/dts/s5pc1xx-smdkc100.dts
arch/arm/dts/tegra20-trimslice.dts
arch/arm/dts/tegra30-apalis.dts [new file with mode: 0644]
arch/arm/dts/tegra30-beaver.dts
arch/arm/dts/tegra30-cardhu.dts
arch/arm/dts/tegra30-colibri.dts
arch/arm/imx-common/cpu.c
arch/arm/imx-common/i2c-mxv7.c
arch/arm/imx-common/misc.c
arch/arm/include/asm/arch-armada-xp/config.h [new file with mode: 0644]
arch/arm/include/asm/arch-armada-xp/cpu.h [new file with mode: 0644]
arch/arm/include/asm/arch-armada-xp/soc.h [new file with mode: 0644]
arch/arm/include/asm/arch-bcm2835/gpio.h
arch/arm/include/asm/arch-exynos/gpio.h
arch/arm/include/asm/arch-kirkwood/config.h
arch/arm/include/asm/arch-kirkwood/cpu.h
arch/arm/include/asm/arch-kirkwood/gpio.h
arch/arm/include/asm/arch-kirkwood/soc.h [moved from arch/arm/include/asm/arch-kirkwood/kirkwood.h with 90% similarity]
arch/arm/include/asm/arch-mvebu/spi.h [moved from arch/arm/include/asm/arch-kirkwood/spi.h with 100% similarity]
arch/arm/include/asm/arch-mxs/sys_proto.h
arch/arm/include/asm/arch-omap3/sys_proto.h
arch/arm/include/asm/arch-s5pc1xx/gpio.h
arch/arm/include/asm/arch-tegra/board.h
arch/arm/include/asm/arch-tegra114/mc.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/tegra.h
arch/arm/include/asm/arch-tegra114/tegra114_spi.h [deleted file]
arch/arm/include/asm/arch-tegra20/mc.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra20/tegra.h
arch/arm/include/asm/arch-tegra20/tegra20_sflash.h [deleted file]
arch/arm/include/asm/arch-tegra20/tegra20_slink.h [deleted file]
arch/arm/include/asm/arch-tegra30/mc.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/tegra.h
arch/arm/include/asm/arch-uniphier/platdevice.h [new file with mode: 0644]
arch/arm/include/asm/imx-common/mxc_i2c.h
arch/arm/include/asm/mach-types.h
arch/arm/include/asm/omap_gpio.h
arch/arm/include/asm/u-boot-arm.h
arch/arm/lib/board.c
arch/arm/lib/bootm.c
arch/arm/lib/interrupts.c
arch/arm/mvebu-common/Makefile [new file with mode: 0644]
arch/arm/mvebu-common/dram.c [moved from arch/arm/cpu/arm926ejs/kirkwood/dram.c with 57% similarity]
arch/arm/mvebu-common/gpio.c [new file with mode: 0644]
arch/arm/mvebu-common/mbus.c [new file with mode: 0644]
arch/arm/mvebu-common/timer.c [moved from arch/arm/cpu/arm926ejs/kirkwood/timer.c with 63% similarity]
arch/mips/Kconfig
arch/sandbox/dts/sandbox.dts
arch/sandbox/include/asm/spi.h
arch/sandbox/include/asm/state.h
arch/x86/Kconfig
arch/x86/config.mk
arch/x86/cpu/Makefile
arch/x86/cpu/start.S
arch/x86/cpu/start16.S
arch/x86/dts/coreboot.dtsi
arch/x86/dts/link.dts
arch/x86/include/asm/arch-coreboot/gpio.h [new file with mode: 0644]
arch/x86/include/asm/bootm.h [new file with mode: 0644]
arch/x86/include/asm/config.h
arch/x86/include/asm/gpio.h
arch/x86/include/asm/ibmpc.h
arch/x86/lib/Makefile
arch/x86/lib/bootm.c
arch/x86/lib/zimage.c
board/LaCie/net2big_v2/net2big_v2.c
board/LaCie/netspace_v2/netspace_v2.c
board/LaCie/wireless_space/wireless_space.c
board/Marvell/db-mv784mp-gp/Kconfig [new file with mode: 0644]
board/Marvell/db-mv784mp-gp/MAINTAINERS [new file with mode: 0644]
board/Marvell/db-mv784mp-gp/Makefile [new file with mode: 0644]
board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c [new file with mode: 0644]
board/Marvell/db-mv784mp-gp/kwbimage.cfg [new file with mode: 0644]
board/Marvell/dreamplug/dreamplug.c
board/Marvell/guruplug/guruplug.c
board/Marvell/mv88f6281gtw_ge/mv88f6281gtw_ge.c
board/Marvell/openrd/openrd.c
board/Marvell/rd6281a/rd6281a.c
board/Marvell/sheevaplug/sheevaplug.c
board/Seagate/dockstar/dockstar.c
board/Seagate/goflexhome/goflexhome.c
board/atmel/at91rm9200ek/led.c
board/atmel/at91sam9260ek/led.c
board/buffalo/lsxl/lsxl.c
board/chromebook-x86/coreboot/Makefile
board/chromebook-x86/coreboot/coreboot.c [new file with mode: 0644]
board/cloudengines/pogo_e02/pogo_e02.c
board/compulab/cm_fx6/cm_fx6.c
board/d-link/dns325/dns325.c
board/iomega/iconnect/iconnect.c
board/isee/igep00x0/igep00x0.c
board/karo/tk71/tk71.c
board/keymile/km_arm/km_arm.c
board/logicpd/zoom1/zoom1.c
board/maxbcm/Kconfig [new file with mode: 0644]
board/maxbcm/MAINTAINERS [new file with mode: 0644]
board/maxbcm/Makefile [new file with mode: 0644]
board/maxbcm/kwbimage.cfg [new file with mode: 0644]
board/maxbcm/maxbcm.c [new file with mode: 0644]
board/nvidia/common/board.c
board/nvidia/common/emc.c
board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h
board/nvidia/seaboard/seaboard.c
board/overo/overo.c
board/raidsonic/ib62x0/ib62x0.c
board/raspberrypi/rpi_b/rpi_b.c
board/renesas/sh7752evb/sh7752evb.c
board/renesas/sh7753evb/sh7753evb.c
board/renesas/sh7757lcr/sh7757lcr.c
board/samsung/arndale/arndale.c
board/samsung/common/board.c
board/samsung/common/misc.c
board/samsung/goni/goni.c
board/samsung/origen/origen.c
board/samsung/smdk5250/exynos5-dt.c
board/samsung/smdk5420/smdk5420.c
board/samsung/smdkc100/smdkc100.c
board/samsung/smdkv310/smdkv310.c
board/samsung/trats/trats.c
board/samsung/trats2/trats2.c
board/samsung/universal_c210/universal.c
board/technexion/twister/twister.c
board/ti/beagle/beagle.c
board/ti/beagle/led.c
board/toradex/apalis_t30/Kconfig [new file with mode: 0644]
board/toradex/apalis_t30/MAINTAINERS [new file with mode: 0644]
board/toradex/apalis_t30/Makefile [new file with mode: 0644]
board/toradex/apalis_t30/apalis_t30.c [new file with mode: 0644]
board/toradex/apalis_t30/pinmux-config-apalis_t30.h [new file with mode: 0644]
board/toradex/colibri_t30/colibri_t30.c
board/w7o/fsboot.c
common/board_f.c
common/board_r.c
common/bootm.c
common/cmd_bootm.c
common/cmd_elf.c
common/cmd_gpio.c
common/cmd_sf.c
common/cmd_spi.c
common/console.c
common/cros_ec.c
common/env_nand.c
common/env_sf.c
common/exports.c
common/image-fit.c
common/image.c
common/menu.c
common/modem.c
common/stdio.c
config.mk
configs/am335x_boneblack_defconfig
configs/am335x_boneblack_vboot_defconfig
configs/apalis_t30_defconfig [new file with mode: 0644]
configs/db-mv784mp-gp_defconfig [new file with mode: 0644]
configs/maxbcm_defconfig [new file with mode: 0644]
configs/ph1_ld4_defconfig
configs/ph1_pro4_defconfig
configs/ph1_sld8_defconfig
disk/part.c
doc/device-tree-bindings/mtd/spi/spi-flash.txt [new file with mode: 0644]
doc/device-tree-bindings/spi/soft-spi.txt [new file with mode: 0644]
doc/driver-model/README.txt
doc/driver-model/spi-howto.txt [new file with mode: 0644]
doc/uImage.FIT/kernel.its
doc/uImage.FIT/source_file_format.txt
doc/uImage.FIT/x86-fit-boot.txt [new file with mode: 0644]
drivers/block/mvsata_ide.c
drivers/core/Kconfig
drivers/core/Makefile
drivers/core/device.c
drivers/core/lists.c
drivers/core/simple-bus.c [new file with mode: 0644]
drivers/core/uclass.c
drivers/dfu/dfu_sf.c
drivers/gpio/Kconfig
drivers/gpio/bcm2835_gpio.c
drivers/gpio/gpio-uclass.c
drivers/gpio/intel_ich6_gpio.c
drivers/gpio/kw_gpio.c
drivers/gpio/mxc_gpio.c
drivers/gpio/omap_gpio.c
drivers/gpio/s5p_gpio.c
drivers/gpio/sandbox.c
drivers/gpio/tegra_gpio.c
drivers/i2c/designware_i2c.c
drivers/i2c/mvtwsi.c
drivers/i2c/tegra_i2c.c
drivers/input/tegra-kbc.c
drivers/misc/cros_ec.c
drivers/misc/cros_ec_lpc.c
drivers/misc/cros_ec_sandbox.c
drivers/misc/cros_ec_spi.c
drivers/mmc/bcm2835_sdhci.c
drivers/mmc/mvebu_mmc.c
drivers/mmc/omap_hsmmc.c
drivers/mmc/s5p_sdhci.c
drivers/mmc/sdhci.c
drivers/mmc/tegra_mmc.c
drivers/mtd/cfi_flash.c
drivers/mtd/nand/kirkwood_nand.c
drivers/mtd/nand/omap_gpmc.c
drivers/mtd/spi/Makefile
drivers/mtd/spi/ramtron.c
drivers/mtd/spi/sandbox.c
drivers/mtd/spi/sf-uclass.c [new file with mode: 0644]
drivers/mtd/spi/sf_internal.h
drivers/mtd/spi/sf_params.c
drivers/mtd/spi/sf_probe.c
drivers/mtd/spi/spi_spl_load.c
drivers/net/Makefile
drivers/net/davinci_emac.c
drivers/net/fec_mxc.c
drivers/net/mvgbe.c
drivers/net/mvneta.c [new file with mode: 0644]
drivers/net/phy/phy.c
drivers/pci/pci.c
drivers/rtc/mvrtc.h
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/ns16550.c
drivers/serial/serial-uclass.c
drivers/serial/serial.c
drivers/serial/serial_coreboot.c [new file with mode: 0644]
drivers/serial/serial_mxc.c
drivers/serial/serial_ns16550.c
drivers/serial/serial_omap.c [new file with mode: 0644]
drivers/serial/serial_pl01x.c
drivers/serial/serial_pl01x_internal.h [moved from drivers/serial/serial_pl01x.h with 100% similarity]
drivers/serial/serial_s3c24x0.c
drivers/serial/serial_s5p.c
drivers/serial/serial_sh.c
drivers/serial/serial_uniphier.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/exynos_spi.c
drivers/spi/fdt_spi.c [deleted file]
drivers/spi/kirkwood_spi.c
drivers/spi/sandbox_spi.c
drivers/spi/soft_spi.c
drivers/spi/soft_spi_legacy.c [new file with mode: 0644]
drivers/spi/spi-emul-uclass.c [new file with mode: 0644]
drivers/spi/spi-uclass.c [new file with mode: 0644]
drivers/spi/tegra114_spi.c
drivers/spi/tegra20_sflash.c
drivers/spi/tegra20_slink.c
drivers/spi/tegra_spi.h [new file with mode: 0644]
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-marvell.c
drivers/video/cfb_console.c
drivers/video/exynos_fb.c
drivers/video/ipu_common.c
drivers/video/ipu_disp.c
drivers/video/mxc_ipuv3_fb.c
include/asm-generic/gpio.h
include/bootm.h
include/bootstage.h
include/common.h
include/config_fallbacks.h
include/configs/apalis_t30.h [new file with mode: 0644]
include/configs/cm_fx6.h
include/configs/colibri_t30.h
include/configs/coreboot.h
include/configs/db-mv784mp-gp.h [new file with mode: 0644]
include/configs/edb93xx.h
include/configs/exynos-common.h
include/configs/ks2_evm.h
include/configs/ls1021aqds.h
include/configs/ls1021atwr.h
include/configs/ls2085a_common.h
include/configs/maxbcm.h [new file with mode: 0644]
include/configs/peach-pit.h
include/configs/ph1_ld4.h
include/configs/ph1_pro4.h
include/configs/ph1_sld8.h
include/configs/rpi_b.h
include/configs/s5p_goni.h
include/configs/s5pc210_universal.h
include/configs/sacsng.h
include/configs/sandbox.h
include/configs/smdkc100.h
include/configs/sunxi-common.h
include/configs/tegra-common-post.h
include/configs/tegra-common.h
include/configs/ti_am335x_common.h
include/configs/ti_omap3_common.h
include/configs/tqma6.h
include/configs/uniphier-common.h
include/configs/zipitz2.h
include/cros_ec.h
include/dm/device-internal.h
include/dm/device.h
include/dm/lists.h
include/dm/platdata.h
include/dm/platform_data/serial-uniphier.h [new file with mode: 0644]
include/dm/platform_data/serial_mxc.h [new file with mode: 0644]
include/dm/platform_data/serial_pl01x.h [new file with mode: 0644]
include/dm/test.h
include/dm/uclass-id.h
include/dm/uclass.h
include/dm/util.h
include/dt-bindings/pinctrl/am33xx.h [moved from arch/arm/dts/dt-bindings/pinctrl/am33xx.h with 100% similarity]
include/dt-bindings/pinctrl/omap.h [moved from arch/arm/dts/dt-bindings/pinctrl/omap.h with 100% similarity]
include/elf.h
include/fdt_support.h
include/fdtdec.h
include/ide.h
include/image.h
include/libfdt.h
include/linker_lists.h
include/linux/mbus.h [new file with mode: 0644]
include/linux/string.h
include/mmc.h
include/netdev.h
include/ns16550.h
include/phy.h
include/spi.h
include/spi_flash.h
include/spl.h
lib/Kconfig
lib/fdtdec.c
lib/initcall.c
lib/libfdt/fdt_ro.c
lib/lmb.c
lib/time.c
net/eth.c
net/tftp.c
post/post.c
scripts/Makefile.spl
scripts/multiconfig.sh
test/dm/Makefile
test/dm/bus.c
test/dm/core.c
test/dm/gpio.c
test/dm/sf.c [new file with mode: 0644]
test/dm/spi.c [new file with mode: 0644]
test/dm/test-dm.sh
test/dm/test-main.c
test/dm/test.dts
tools/Makefile
tools/kwbimage.c
tools/kwboot.c

index 99097e1e57288ebab699a4678f3635f36f67837c..26dacee98e07d0c203e0156bae557ea95a006d29 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -652,6 +652,10 @@ ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx31 mx35 mxs vf610))
 libs-y += arch/$(ARCH)/imx-common/
 endif
 
+ifneq (,$(filter $(SOC), armada-xp kirkwood))
+libs-y += arch/$(ARCH)/mvebu-common/
+endif
+
 libs-$(CONFIG_ARM) += arch/arm/cpu/
 libs-$(CONFIG_PPC) += arch/powerpc/cpu/
 
@@ -670,13 +674,9 @@ u-boot-main := $(libs-y)
 
 
 # Add GCC lib
-ifdef CONFIG_USE_PRIVATE_LIBGCC
 ifeq ($(CONFIG_USE_PRIVATE_LIBGCC),y)
 PLATFORM_LIBGCC = arch/$(ARCH)/lib/lib.a
 else
-PLATFORM_LIBGCC = -L $(CONFIG_USE_PRIVATE_LIBGCC) -lgcc
-endif
-else
 PLATFORM_LIBGCC := -L $(shell dirname `$(CC) $(c_flags) -print-libgcc-file-name`) -lgcc
 endif
 PLATFORM_LIBS += $(PLATFORM_LIBGCC)
@@ -754,6 +754,11 @@ endif
 endif
 endif
 
+# Add optional build target if defined in board/cpu/soc headers
+ifneq ($(CONFIG_BUILD_TARGET),)
+ALL-y += $(CONFIG_BUILD_TARGET:"%"=%)
+endif
+
 LDFLAGS_u-boot += $(LDFLAGS_FINAL)
 ifneq ($(CONFIG_SYS_TEXT_BASE),)
 LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)
diff --git a/README b/README
index d9a64ea62e22287a70a09fa0c6a00d08b5220c2f..2808dd1eb9a27cdacadb86f1a2dd9eb26121ec29 100644 (file)
--- a/README
+++ b/README
@@ -623,13 +623,6 @@ The following options need to be configured:
                exists, unlike the similar options in the Linux kernel. Do not
                set these options unless they apply!
 
-- CPU timer options:
-               CONFIG_SYS_HZ
-
-               The frequency of the timer returned by get_timer().
-               get_timer() must operate in milliseconds and this CONFIG
-               option must be set to 1000.
-
 - Linux Kernel Interface:
                CONFIG_CLOCKS_IN_MHZ
 
@@ -2725,6 +2718,14 @@ CBFS (Coreboot Filesystem) support
                200 ms.
 
 - Configuration Management:
+               CONFIG_BUILD_TARGET
+
+               Some SoCs need special image types (e.g. U-Boot binary
+               with a special header) as build targets. By defining
+               CONFIG_BUILD_TARGET in the SoC / board header, this
+               special image will be automatically built upon calling
+               make / MAKEALL.
+
                CONFIG_IDENT_STRING
 
                If defined, this string will be added to the U-Boot
@@ -2833,10 +2834,6 @@ CBFS (Coreboot Filesystem) support
 
                Enable auto completion of commands using TAB.
 
-               Note that this feature has NOT been implemented yet
-               for the "hush" shell.
-
-
                CONFIG_SYS_HUSH_PARSER
 
                Define this variable to enable the "hush" shell (from
index bf2676469c7131dd924139cf42dd392b0902bbc3..f63cc5a7e9440416c351e612eb5c8615693aa037 100644 (file)
@@ -7,6 +7,7 @@ config ARC
 
 config ARM
        bool "ARM architecture"
+       select HAVE_PRIVATE_LIBGCC
        select SUPPORT_OF_CONTROL
 
 config AVR32
@@ -24,6 +25,7 @@ config MICROBLAZE
 
 config MIPS
        bool "MIPS architecture"
+       select HAVE_PRIVATE_LIBGCC
 
 config NDS32
        bool "NDS32 architecture"
@@ -36,6 +38,7 @@ config OPENRISC
 
 config PPC
        bool "PowerPC architecture"
+       select HAVE_PRIVATE_LIBGCC
 
 config SANDBOX
        bool "Sandbox"
@@ -43,12 +46,14 @@ config SANDBOX
 
 config SH
        bool "SuperH architecture"
+       select HAVE_PRIVATE_LIBGCC
 
 config SPARC
        bool "SPARC architecture"
 
 config X86
        bool "x86 architecture"
+       select HAVE_PRIVATE_LIBGCC
        select SUPPORT_OF_CONTROL
 
 endchoice
index 72558b85620a638c2945a58ccb3ebbc1faea06b6..109d49f57db7b4a409064fbb49fa5bc263c17f3c 100644 (file)
@@ -141,6 +141,12 @@ config ARCH_DAVINCI
 config KIRKWOOD
        bool "Marvell Kirkwood"
 
+config TARGET_DB_MV784MP_GP
+       bool "Support db-mv784mp-gp"
+
+config TARGET_MAXBCM
+       bool "Support maxbcm"
+
 config TARGET_DEVKIT3250
        bool "Support devkit3250"
 
@@ -567,6 +573,7 @@ source "board/BuS/eb_cpux9k2/Kconfig"
 source "board/BuS/vl_ma2sc/Kconfig"
 source "board/CarMediaLab/flea3/Kconfig"
 source "board/Marvell/aspenite/Kconfig"
+source "board/Marvell/db-mv784mp-gp/Kconfig"
 source "board/Marvell/dkb/Kconfig"
 source "board/Marvell/gplugd/Kconfig"
 source "board/afeb9260/Kconfig"
@@ -648,6 +655,7 @@ source "board/jornada/Kconfig"
 source "board/karo/tx25/Kconfig"
 source "board/logicpd/imx27lite/Kconfig"
 source "board/logicpd/imx31_litekit/Kconfig"
+source "board/maxbcm/Kconfig"
 source "board/mpl/vcma9/Kconfig"
 source "board/olimex/mx23_olinuxino/Kconfig"
 source "board/palmld/Kconfig"
index 46ed055023978aee455ccfdb74155c31705ebb41..b8d5c785df4d36557168e3f178738fdc9f717006 100644 (file)
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <asm/gpio.h>
 #include <asm/arch/gpio.h>
+#include <status_led.h>
 
 #ifdef CONFIG_RED_LED
 void red_led_on(void)
index c230ce8994e7f5ec3e0b069758f5982d89190cd1..df4756e4bdb1fd072e5356a65e9d4ec7e51b54fa 100644 (file)
@@ -7,7 +7,5 @@
 #
 
 obj-y  = cpu.o
-obj-y  += dram.o
-obj-y  += mpp.o
-obj-y  += timer.o
 obj-y  += cache.o
+obj-y  += mpp.o
index 881e2de81b328ca71d106a0bdd8630202537268d..9e412bbb04d585c949f321ddd04032a652a92e00 100644 (file)
@@ -9,14 +9,11 @@
 #include <common.h>
 #include <netdev.h>
 #include <asm/cache.h>
-#include <u-boot/md5.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <mvebu_mmc.h>
 
-#define BUFLEN 16
-
 void reset_cpu(unsigned long ignored)
 {
        struct kwcpu_registers *cpureg =
@@ -29,31 +26,6 @@ void reset_cpu(unsigned long ignored)
        while (1) ;
 }
 
-/*
- * Generates Ramdom hex number reading some time varient system registers
- * and using md5 algorithm
- */
-unsigned char get_random_hex(void)
-{
-       int i;
-       u32 inbuf[BUFLEN];
-       u8 outbuf[BUFLEN];
-
-       /*
-        * in case of 88F6281/88F6282/88F6192 A0,
-        * Bit7 need to reset to generate random values in KW_REG_UNDOC_0x1470
-        * Soc reg offsets KW_REG_UNDOC_0x1470 and KW_REG_UNDOC_0x1478 are
-        * reserved regs and does not have names at this moment
-        * (no errata available)
-        */
-       writel(readl(KW_REG_UNDOC_0x1478) & ~(1 << 7), KW_REG_UNDOC_0x1478);
-       for (i = 0; i < BUFLEN; i++) {
-               inbuf[i] = readl(KW_REG_UNDOC_0x1470);
-       }
-       md5((u8 *) inbuf, (BUFLEN * sizeof(u32)), outbuf);
-       return outbuf[outbuf[7] % 0x0f];
-}
-
 /*
  * Window Size
  * Used with the Base register to set the address window size and location.
@@ -139,50 +111,6 @@ int kw_config_adr_windows(void)
        return 0;
 }
 
-/*
- * kw_config_gpio - GPIO configuration
- */
-void kw_config_gpio(u32 gpp0_oe_val, u32 gpp1_oe_val, u32 gpp0_oe, u32 gpp1_oe)
-{
-       struct kwgpio_registers *gpio0reg =
-               (struct kwgpio_registers *)KW_GPIO0_BASE;
-       struct kwgpio_registers *gpio1reg =
-               (struct kwgpio_registers *)KW_GPIO1_BASE;
-
-       /* Init GPIOS to default values as per board requirement */
-       writel(gpp0_oe_val, &gpio0reg->dout);
-       writel(gpp1_oe_val, &gpio1reg->dout);
-       writel(gpp0_oe, &gpio0reg->oe);
-       writel(gpp1_oe, &gpio1reg->oe);
-}
-
-/*
- * kw_config_mpp - Multi-Purpose Pins Functionality configuration
- *
- * Each MPP can be configured to different functionality through
- * MPP control register, ref (sec 6.1 of kirkwood h/w specification)
- *
- * There are maximum 64 Multi-Pourpose Pins on Kirkwood
- * Each MPP functionality can be configuration by a 4bit value
- * of MPP control reg, the value and associated functionality depends
- * upon used SoC varient
- */
-int kw_config_mpp(u32 mpp0_7, u32 mpp8_15, u32 mpp16_23, u32 mpp24_31,
-               u32 mpp32_39, u32 mpp40_47, u32 mpp48_55)
-{
-       u32 *mppreg = (u32 *) KW_MPP_BASE;
-
-       /* program mpp registers */
-       writel(mpp0_7, &mppreg[0]);
-       writel(mpp8_15, &mppreg[1]);
-       writel(mpp16_23, &mppreg[2]);
-       writel(mpp24_31, &mppreg[3]);
-       writel(mpp32_39, &mppreg[4]);
-       writel(mpp40_47, &mppreg[5]);
-       writel(mpp48_55, &mppreg[6]);
-       return 0;
-}
-
 /*
  * SYSRSTn Duration Counter Support
  *
index 0ba6f098cb6b2c6486dc1a79375a6482634327f9..7222504ed3a43033d93959af3c9857f310642865 100644 (file)
@@ -12,7 +12,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 
 static u32 kirkwood_variant(void)
index 828d10bb5a4e59bf9aaa1a0ddf0775af22749dc3..29b1d734382a3c8a83a41cad409a8b5b6e217d7e 100644 (file)
@@ -9,7 +9,9 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
+#include <ns16550.h>
 #include <spl.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/hardware.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifdef CONFIG_DM_GPIO
+static const struct omap_gpio_platdata am33xx_gpio[] = {
+       { 0, AM33XX_GPIO0_BASE, METHOD_GPIO_24XX },
+       { 1, AM33XX_GPIO1_BASE, METHOD_GPIO_24XX },
+       { 2, AM33XX_GPIO2_BASE, METHOD_GPIO_24XX },
+       { 3, AM33XX_GPIO3_BASE, METHOD_GPIO_24XX },
+#ifdef CONFIG_AM43XX
+       { 4, AM33XX_GPIO4_BASE, METHOD_GPIO_24XX },
+       { 5, AM33XX_GPIO5_BASE, METHOD_GPIO_24XX },
+#endif
+};
+
+U_BOOT_DEVICES(am33xx_gpios) = {
+       { "gpio_omap", &am33xx_gpio[0] },
+       { "gpio_omap", &am33xx_gpio[1] },
+       { "gpio_omap", &am33xx_gpio[2] },
+       { "gpio_omap", &am33xx_gpio[3] },
+#ifdef CONFIG_AM43XX
+       { "gpio_omap", &am33xx_gpio[4] },
+       { "gpio_omap", &am33xx_gpio[5] },
+#endif
+};
+
+# ifndef CONFIG_OF_CONTROL
+/*
+ * TODO(sjg@chromium.org): When we can move SPL serial to DM, we can remove
+ * the CONFIGs. At the same time, we should move this to the board files.
+ */
+static const struct ns16550_platdata am33xx_serial[] = {
+       { CONFIG_SYS_NS16550_COM1, 2, CONFIG_SYS_NS16550_CLK },
+#  ifdef CONFIG_SYS_NS16550_COM2
+       { CONFIG_SYS_NS16550_COM2, 2, CONFIG_SYS_NS16550_CLK },
+#   ifdef CONFIG_SYS_NS16550_COM3
+       { CONFIG_SYS_NS16550_COM3, 2, CONFIG_SYS_NS16550_CLK },
+       { CONFIG_SYS_NS16550_COM4, 2, CONFIG_SYS_NS16550_CLK },
+       { CONFIG_SYS_NS16550_COM5, 2, CONFIG_SYS_NS16550_CLK },
+       { CONFIG_SYS_NS16550_COM6, 2, CONFIG_SYS_NS16550_CLK },
+#   endif
+#  endif
+};
+
+U_BOOT_DEVICES(am33xx_uarts) = {
+       { "serial_omap", &am33xx_serial[0] },
+#  ifdef CONFIG_SYS_NS16550_COM2
+       { "serial_omap", &am33xx_serial[1] },
+#   ifdef CONFIG_SYS_NS16550_COM3
+       { "serial_omap", &am33xx_serial[2] },
+       { "serial_omap", &am33xx_serial[3] },
+       { "serial_omap", &am33xx_serial[4] },
+       { "serial_omap", &am33xx_serial[5] },
+#   endif
+#  endif
+};
+# endif
+
+#else
+
 static const struct gpio_bank gpio_bank_am33xx[] = {
        { (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX },
        { (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX },
@@ -49,6 +108,8 @@ static const struct gpio_bank gpio_bank_am33xx[] = {
 
 const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx;
 
+#endif
+
 #if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD)
 int cpu_mmc_init(bd_t *bis)
 {
diff --git a/arch/arm/cpu/armv7/armada-xp/Makefile b/arch/arm/cpu/armv7/armada-xp/Makefile
new file mode 100644 (file)
index 0000000..885dcee
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  = cpu.o
diff --git a/arch/arm/cpu/armv7/armada-xp/cpu.c b/arch/arm/cpu/armv7/armada-xp/cpu.c
new file mode 100644 (file)
index 0000000..1cf70a9
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#define DDR_BASE_CS_OFF(n)     (0x0000 + ((n) << 3))
+#define DDR_SIZE_CS_OFF(n)     (0x0004 + ((n) << 3))
+
+static struct mbus_win windows[] = {
+       /* PCIE MEM address space */
+       { DEFADR_PCI_MEM, 256 << 20, CPU_TARGET_PCIE13, CPU_ATTR_PCIE_MEM },
+
+       /* PCIE IO address space */
+       { DEFADR_PCI_IO, 64 << 10, CPU_TARGET_PCIE13, CPU_ATTR_PCIE_IO },
+
+       /* SPI */
+       { DEFADR_SPIF, 8 << 20, CPU_TARGET_DEVICEBUS_BOOTROM_SPI,
+         CPU_ATTR_SPIFLASH },
+
+       /* NOR */
+       { DEFADR_BOOTROM, 8 << 20, CPU_TARGET_DEVICEBUS_BOOTROM_SPI,
+         CPU_ATTR_BOOTROM },
+};
+
+void reset_cpu(unsigned long ignored)
+{
+       struct mvebu_system_registers *reg =
+               (struct mvebu_system_registers *)MVEBU_SYSTEM_REG_BASE;
+
+       writel(readl(&reg->rstoutn_mask) | 1, &reg->rstoutn_mask);
+       writel(readl(&reg->sys_soft_rst) | 1, &reg->sys_soft_rst);
+       while (1)
+               ;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+       u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff;
+       u8 revid = readl(MVEBU_REG_PCIE_REVID) & 0xff;
+
+       puts("SoC:   ");
+
+       switch (devid) {
+       case SOC_MV78460_ID:
+               puts("MV78460-");
+               break;
+       default:
+               puts("Unknown-");
+               break;
+       }
+
+       switch (revid) {
+       case 1:
+               puts("A0\n");
+               break;
+       case 2:
+               puts("B0\n");
+               break;
+       default:
+               puts("??\n");
+               break;
+       }
+
+       return 0;
+}
+#endif /* CONFIG_DISPLAY_CPUINFO */
+
+/*
+ * This function initialize Controller DRAM Fastpath windows.
+ * It takes the CS size information from the 0x1500 scratch registers
+ * and sets the correct windows sizes and base addresses accordingly.
+ *
+ * These values are set in the scratch registers by the Marvell
+ * DDR3 training code, which is executed by the BootROM before the
+ * main payload (U-Boot) is executed. This training code is currently
+ * only available in the Marvell U-Boot version. It needs to be
+ * ported to mainline U-Boot SPL at some point.
+ */
+static void update_sdram_window_sizes(void)
+{
+       u64 base = 0;
+       u32 size, temp;
+       int i;
+
+       for (i = 0; i < SDRAM_MAX_CS; i++) {
+               size = readl((MVEBU_SDRAM_SCRATCH + (i * 8))) & SDRAM_ADDR_MASK;
+               if (size != 0) {
+                       size |= ~(SDRAM_ADDR_MASK);
+
+                       /* Set Base Address */
+                       temp = (base & 0xFF000000ll) | ((base >> 32) & 0xF);
+                       writel(temp, MVEBU_SDRAM_BASE + DDR_BASE_CS_OFF(i));
+
+                       /*
+                        * Check if out of max window size and resize
+                        * the window
+                        */
+                       temp = (readl(MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i)) &
+                               ~(SDRAM_ADDR_MASK)) | 1;
+                       temp |= (size & SDRAM_ADDR_MASK);
+                       writel(temp, MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i));
+
+                       base += ((u64)size + 1);
+               } else {
+                       /*
+                        * Disable window if not used, otherwise this
+                        * leads to overlapping enabled windows with
+                        * pretty strange results
+                        */
+                       clrbits_le32(MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i), 1);
+               }
+       }
+}
+
+#ifdef CONFIG_ARCH_CPU_INIT
+int arch_cpu_init(void)
+{
+       /* Linux expects the internal registers to be at 0xf1000000 */
+       writel(SOC_REGS_PHY_BASE, INTREG_BASE_ADDR_REG);
+
+       /*
+        * We need to call mvebu_mbus_probe() before calling
+        * update_sdram_window_sizes() as it disables all previously
+        * configured mbus windows and then configures them as
+        * required for U-Boot. Calling update_sdram_window_sizes()
+        * without this configuration will not work, as the internal
+        * registers can't be accessed reliably because of potenial
+        * double mapping.
+        * After updating the SDRAM access windows we need to call
+        * mvebu_mbus_probe() again, as this now correctly configures
+        * the SDRAM areas that are later used by the MVEBU drivers
+        * (e.g. USB, NETA).
+        */
+
+       /*
+        * First disable all windows
+        */
+       mvebu_mbus_probe(NULL, 0);
+
+       /*
+        * Now the SDRAM access windows can be reconfigured using
+        * the information in the SDRAM scratch pad registers
+        */
+       update_sdram_window_sizes();
+
+       /*
+        * Finally the mbus windows can be configured with the
+        * updated SDRAM sizes
+        */
+       mvebu_mbus_probe(windows, ARRAY_SIZE(windows));
+
+       return 0;
+}
+#endif /* CONFIG_ARCH_CPU_INIT */
+
+/*
+ * SOC specific misc init
+ */
+#if defined(CONFIG_ARCH_MISC_INIT)
+int arch_misc_init(void)
+{
+       /* Nothing yet, perhaps we need something here later */
+       return 0;
+}
+#endif /* CONFIG_ARCH_MISC_INIT */
+
+#ifdef CONFIG_MVNETA
+int cpu_eth_init(bd_t *bis)
+{
+       mvneta_initialize(bis, MVEBU_EGIGA0_BASE, 0, CONFIG_PHY_BASE_ADDR + 0);
+       mvneta_initialize(bis, MVEBU_EGIGA1_BASE, 1, CONFIG_PHY_BASE_ADDR + 1);
+       mvneta_initialize(bis, MVEBU_EGIGA2_BASE, 2, CONFIG_PHY_BASE_ADDR + 2);
+       mvneta_initialize(bis, MVEBU_EGIGA3_BASE, 3, CONFIG_PHY_BASE_ADDR + 3);
+
+       return 0;
+}
+#endif
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+       /* Enable D-cache. I-cache is already enabled in start.S */
+       dcache_enable();
+}
+#endif
index b929486da9c2c99766084bf5440d19a81016a3a1..3d95dc3339e6ee87859748d529510a7036b6cece 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <fdtdec.h>
-#include <asm/arch/gpio.h>
+#include <asm/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/sromc.h>
 
@@ -172,6 +172,9 @@ static int exynos5420_mmc_config(int peripheral, int flags)
                 * this same assumption.
                 */
                if ((peripheral == PERIPH_ID_SDMMC0) && (i == (start + 2))) {
+#ifndef CONFIG_SPL_BUILD
+                       gpio_request(i, "sdmmc0_vdden");
+#endif
                        gpio_set_value(i, 1);
                        gpio_cfg_pin(i, S5P_GPIO_OUTPUT);
                } else {
index 63524222539134df5c69c6b2179a334850199ec4..a202b0318e0659e02551027c6de9e6fa9e56b095 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <common.h>
 #include <asm/armv7.h>
+#include <asm/bootm.h>
 #include <asm/pl310.h>
 #include <asm/errno.h>
 #include <asm/io.h>
index 667e77ff05ba22429fdf101e0884856e5eb54e62..c942fe67eeb2148c0dcce6abbaea21d3193653c2 100644 (file)
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
+#include <mmc.h>
 #include <spl.h>
 #include <asm/io.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/mem.h>
 #include <asm/cache.h>
 #include <asm/armv7.h>
-#include <asm/arch/gpio.h>
+#include <asm/gpio.h>
 #include <asm/omap_common.h>
 #include <asm/arch/mmc_host_def.h>
 #include <i2c.h>
@@ -38,6 +40,27 @@ static void omap3_setup_aux_cr(void);
 static void omap3_invalidate_l2_cache_secure(void);
 #endif
 
+#ifdef CONFIG_DM_GPIO
+static const struct omap_gpio_platdata omap34xx_gpio[] = {
+       { 0, OMAP34XX_GPIO1_BASE, METHOD_GPIO_24XX },
+       { 1, OMAP34XX_GPIO2_BASE, METHOD_GPIO_24XX },
+       { 2, OMAP34XX_GPIO3_BASE, METHOD_GPIO_24XX },
+       { 3, OMAP34XX_GPIO4_BASE, METHOD_GPIO_24XX },
+       { 4, OMAP34XX_GPIO5_BASE, METHOD_GPIO_24XX },
+       { 5, OMAP34XX_GPIO6_BASE, METHOD_GPIO_24XX },
+};
+
+U_BOOT_DEVICES(am33xx_gpios) = {
+       { "gpio_omap", &omap34xx_gpio[0] },
+       { "gpio_omap", &omap34xx_gpio[1] },
+       { "gpio_omap", &omap34xx_gpio[2] },
+       { "gpio_omap", &omap34xx_gpio[3] },
+       { "gpio_omap", &omap34xx_gpio[4] },
+       { "gpio_omap", &omap34xx_gpio[5] },
+};
+
+#else
+
 static const struct gpio_bank gpio_bank_34xx[6] = {
        { (void *)OMAP34XX_GPIO1_BASE, METHOD_GPIO_24XX },
        { (void *)OMAP34XX_GPIO2_BASE, METHOD_GPIO_24XX },
@@ -49,6 +72,8 @@ static const struct gpio_bank gpio_bank_34xx[6] = {
 
 const struct gpio_bank *const omap_gpio_bank = gpio_bank_34xx;
 
+#endif
+
 #ifdef CONFIG_SPL_BUILD
 /*
 * We use static variables because global data is not ready yet.
@@ -266,7 +291,7 @@ int __weak misc_init_r(void)
  * Routine: wait_for_command_complete
  * Description: Wait for posting to finish on watchdog
  *****************************************************************************/
-void wait_for_command_complete(struct watchdog *wd_base)
+static void wait_for_command_complete(struct watchdog *wd_base)
 {
        int pending = 1;
        do {
index 6c7330a0cabdec269698bad41aa2cf0e3a733fdb..a2aadc9816975e7ec00da1a8874ce4ebf414a188 100644 (file)
@@ -61,7 +61,7 @@ u32 get_sdr_cs_offset(u32 cs)
  *  - Init the emif4 module for DDR access
  *  - Early init routines, called from flash or SRAM.
  */
-void do_emif4_init(void)
+static void do_emif4_init(void)
 {
        unsigned int regval;
        /* Set the DDR PHY parameters in PHY ctrl registers */
index bef5f05eaa71e36e0323f12e82c2377435c2421e..bbb65bbe7263674c2b47b97ee05a9f588ed1c58f 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm/io.h>
 #include <asm/arch/mem.h>      /* get mem tables */
 #include <asm/arch/sys_proto.h>
+#include <asm/bootm.h>
+
 #include <i2c.h>
 #include <linux/compiler.h>
 
@@ -202,7 +204,7 @@ u32 __weak get_board_rev(void)
 /********************************************************
  *  get_base(); get upper addr of current execution
  *******************************************************/
-u32 get_base(void)
+static u32 get_base(void)
 {
        u32 val;
 
index bcae2d60334c9f6999073ce96dc1c74b35a1cb6a..3ea6d7651cb7fd87af753248aa91465a8e95863a 100644 (file)
@@ -17,6 +17,9 @@ config TEGRA124
 
 endchoice
 
+config USE_PRIVATE_LIBGCC
+       default y if SPL_BUILD
+
 config SYS_CPU
        default "arm720t" if SPL_BUILD
        default "armv7" if !SPL_BUILD
index fd77f3f0eff368e5a0a83762390826b79f3eada3..d98cec90180f5d133432d57c68bf6759649c0c0c 100644 (file)
@@ -194,7 +194,8 @@ static void rgb_enable(struct dc_com_reg *com)
                writel(rgb_sel_tab[i], &com->pin_output_sel[i]);
 }
 
-int setup_window(struct disp_ctl_win *win, struct fdt_disp_config *config)
+static int setup_window(struct disp_ctl_win *win,
+                       struct fdt_disp_config *config)
 {
        win->x = 0;
        win->y = 0;
index 54aec4ed509ecae278a83c69d397272b21ce03e7..3abdc7ba17392a702a5c30a3fc6ade7beaba3e52 100644 (file)
@@ -3,6 +3,9 @@ if TEGRA30
 choice
        prompt "Tegra30 board select"
 
+config TARGET_APALIS_T30
+       bool "Toradex Apalis T30 board"
+
 config TARGET_BEAVER
        bool "NVIDIA Tegra30 Beaver evaluation board"
 
@@ -20,6 +23,7 @@ endchoice
 config SYS_SOC
        default "tegra30"
 
+source "board/toradex/apalis_t30/Kconfig"
 source "board/nvidia/beaver/Kconfig"
 source "board/nvidia/cardhu/Kconfig"
 source "board/toradex/colibri_t30/Kconfig"
index b385e195447a71b3de2a762228458248999ce5b2..781b511a97b499090b4485f78a57d60070b10673 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
+obj-y += platdevice.o
 obj-y += boot-mode.o
 obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o bcu_init.o \
                sbc_init.o sg_init.o pll_init.o clkrst_init.o pinctrl.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c b/arch/arm/cpu/armv7/uniphier/ph1-ld4/platdevice.c
new file mode 100644 (file)
index 0000000..0047223
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/arch/platdevice.h>
+
+#define UART_MASTER_CLK                36864000
+
+SERIAL_DEVICE(0, 0x54006800, UART_MASTER_CLK)
+SERIAL_DEVICE(1, 0x54006900, UART_MASTER_CLK)
+SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
+SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)
index 712afd1beebe74f0163041ee0adf517c68acd12c..e11f4f6d8b3f36c44d340f5bafdf9d8fd4858b12 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
+obj-y += platdevice.o
 obj-y += boot-mode.o
 obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o sbc_init.o \
                                sg_init.o pll_init.o clkrst_init.o pinctrl.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/platdevice.c
new file mode 100644 (file)
index 0000000..6da921e
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/arch/platdevice.h>
+
+#define UART_MASTER_CLK                73728000
+
+SERIAL_DEVICE(0, 0x54006800, UART_MASTER_CLK)
+SERIAL_DEVICE(1, 0x54006900, UART_MASTER_CLK)
+SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
+SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)
index b385e195447a71b3de2a762228458248999ce5b2..781b511a97b499090b4485f78a57d60070b10673 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
+obj-y += platdevice.o
 obj-y += boot-mode.o
 obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o bcu_init.o \
                sbc_init.o sg_init.o pll_init.o clkrst_init.o pinctrl.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/platdevice.c
new file mode 100644 (file)
index 0000000..59d054a
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/arch/platdevice.h>
+
+#define UART_MASTER_CLK                80000000
+
+SERIAL_DEVICE(0, 0x54006800, UART_MASTER_CLK)
+SERIAL_DEVICE(1, 0x54006900, UART_MASTER_CLK)
+SERIAL_DEVICE(2, 0x54006a00, UART_MASTER_CLK)
+SERIAL_DEVICE(3, 0x54006b00, UART_MASTER_CLK)
index 433da09d10c2ad59efa3fb2db9c8bf971951039c..b6a84a577478a11374ad3e46ed75bc2c437f59ea 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/funcmux.h>
+#include <asm/arch/mc.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/board.h>
 #include <asm/arch-tegra/pmc.h>
@@ -27,55 +28,6 @@ enum {
        UART_COUNT = 5,
 };
 
-#if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30) || \
-       defined(CONFIG_TEGRA114)
-/*
- * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0,
- * so we are using this value to identify memory size.
- */
-unsigned int query_sdram_size(void)
-{
-       struct pmc_ctlr *const pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-       u32 reg;
-
-       reg = readl(&pmc->pmc_scratch20);
-       debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg);
-
-#if defined(CONFIG_TEGRA20)
-       /* bits 30:28 in OdmData are used for RAM size on T20  */
-       reg &= 0x70000000;
-
-       switch ((reg) >> 28) {
-       case 1:
-               return 0x10000000;      /* 256 MB */
-       case 0:
-       case 2:
-       default:
-               return 0x20000000;      /* 512 MB */
-       case 3:
-               return 0x40000000;      /* 1GB */
-       }
-#else  /* Tegra30/Tegra114 */
-       /* bits 31:28 in OdmData are used for RAM size on T30  */
-       switch ((reg) >> 28) {
-       case 0:
-       case 1:
-       default:
-               return 0x10000000;      /* 256 MB */
-       case 2:
-               return 0x20000000;      /* 512 MB */
-       case 3:
-               return 0x30000000;      /* 768 MB */
-       case 4:
-               return 0x40000000;      /* 1GB */
-       case 8:
-               return 0x7ff00000;      /* 2GB - 1MB */
-       }
-#endif
-}
-#else
-#include <asm/arch/mc.h>
-
 /* Read the RAM size directly from the memory controller */
 unsigned int query_sdram_size(void)
 {
@@ -83,12 +35,22 @@ unsigned int query_sdram_size(void)
        u32 size_mb;
 
        size_mb = readl(&mc->mc_emem_cfg);
+#if defined(CONFIG_TEGRA20)
+       debug("mc->mc_emem_cfg (MEM_SIZE_KB) = 0x%08x\n", size_mb);
+       size_mb = get_ram_size((void *)PHYS_SDRAM_1, size_mb * 1024);
+#else
        debug("mc->mc_emem_cfg (MEM_SIZE_MB) = 0x%08x\n", size_mb);
+       size_mb = get_ram_size((void *)PHYS_SDRAM_1, size_mb * 1024 * 1024);
+#endif
 
-       return size_mb * 1024 * 1024;
-}
+#if defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114)
+       /* External memory limited to 2047 MB due to IROM/HI-VEC */
+       if (size_mb == SZ_2G) size_mb -= SZ_1M;
 #endif
 
+       return size_mb;
+}
+
 int dram_init(void)
 {
        /* We do not initialise DRAM here. We just query the size */
index de20325ecf3239666e5da6e5d23cbcba5811108c..5933c35ddd43e9b4242f33fc3d9952404d82088a 100644 (file)
@@ -8,7 +8,7 @@
 #include <common.h>
 #include <linux/ctype.h>
 
-void upstring(char *s)
+static void upstring(char *s)
 {
        while (*s) {
                *s = toupper(*s);
index c37580ed842e6fddb459efb631b2e4796afbff04..c34606334dbea34363aba579097eed3bc8a20200 100644 (file)
@@ -22,6 +22,7 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
        tegra20-ventana.dtb \
        tegra20-whistler.dtb \
        tegra20-colibri_t20_iris.dtb \
+       tegra30-apalis.dtb \
        tegra30-beaver.dtb \
        tegra30-cardhu.dtb \
        tegra30-colibri.dtb \
index 2f66deda9f5c171b4394046e14dba7b4814588df..e70b4d1f1facc8fa8d8fa520dc8996c4a6348eb7 100644 (file)
        model = "TI AM335x BeagleBone";
        compatible = "ti,am335x-bone", "ti,am33xx";
 
+       chosen {
+               stdout-path = &uart0;
+       };
+
        cpus {
                cpu@0 {
                        cpu0-supply = <&dcdc2_reg>;
diff --git a/arch/arm/dts/dt-bindings/gpio/gpio.h b/arch/arm/dts/dt-bindings/gpio/gpio.h
deleted file mode 100644 (file)
index e6b1e0a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * This header provides constants for most GPIO bindings.
- *
- * Most GPIO bindings include a flags cell as part of the GPIO specifier.
- * In most cases, the format of the flags cell uses the standard values
- * defined in this header.
- */
-
-#ifndef _DT_BINDINGS_GPIO_GPIO_H
-#define _DT_BINDINGS_GPIO_GPIO_H
-
-#define GPIO_ACTIVE_HIGH 0
-#define GPIO_ACTIVE_LOW 1
-
-#endif
index 110eb43a2f8b4aa9af5323e2c22937badd2a79f3..77fad48fb4bd72614d575660af1ae81d2188f9c1 100644 (file)
@@ -7,9 +7,16 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
 
 / {
+       combiner: interrupt-controller@10440000 {
+               compatible = "samsung,exynos4210-combiner";
+               #interrupt-cells = <2>;
+               interrupt-controller;
+               reg = <0x10440000 0x1000>;
+       };
+
        serial@13800000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x13800000 0x3c>;
index 15059d22022738954eea77af7f8e30b07bd8696e..dd2476c1a39e35f74beb2f21d2cde8a44dcdbd04 100644 (file)
@@ -8,8 +8,8 @@
  */
 
 /dts-v1/;
-/include/ "skeleton.dtsi"
-/include/ "exynos4.dtsi"
+#include "skeleton.dtsi"
+#include "exynos4210.dtsi"
 
 / {
        model = "Insignal Origen evaluation board based on Exynos4210";
diff --git a/arch/arm/dts/exynos4210-pinctrl-uboot.dtsi b/arch/arm/dts/exynos4210-pinctrl-uboot.dtsi
new file mode 100644 (file)
index 0000000..ee071c1
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * U-Boot additions to enable a generic Exynos GPIO driver
+ *
+ * Copyright (c) 2014 Google, Inc
+ */
+
+/{
+       pinctrl_0: pinctrl@11400000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "samsung,exynos4210-pinctrl";
+       };
+
+       pinctrl_1: pinctrl@11000000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpy0: gpy0 {
+                       reg = <0xc00>;
+               };
+       };
+
+       pinctrl_2: pinctrl@03860000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+};
diff --git a/arch/arm/dts/exynos4210-pinctrl.dtsi b/arch/arm/dts/exynos4210-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..bda17f7
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Samsung's Exynos4210 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ * Copyright (c) 2011-2012 Linaro Ltd.
+ *             www.linaro.org
+ *
+ * Samsung's Exynos4210 SoC pin-mux and pin-config optiosn are listed as device
+ * tree nodes are listed in this file.
+ *
+ * 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.
+*/
+
+/ {
+       pinctrl@11400000 {
+               gpa0: gpa0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpa1: gpa1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb: gpb {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc0: gpc0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc1: gpc1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd0: gpd0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd1: gpd1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe0: gpe0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe1: gpe1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe2: gpe2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe3: gpe3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe4: gpe4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf0: gpf0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf1: gpf1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf2: gpf2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf3: gpf3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+
+       pinctrl@11000000 {
+               gpj0: gpj0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpj1: gpj1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk0: gpk0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk1: gpk1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk2: gpk2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk3: gpk3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl0: gpl0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl1: gpl1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl2: gpl2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpy0: gpy0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy1: gpy1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy2: gpy2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy3: gpy3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy4: gpy4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy5: gpy5 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy6: gpy6 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpx0: gpx0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+                                    <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx1: gpx1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+                                    <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx2: gpx2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx3: gpx3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+
+       pinctrl@03860000 {
+               gpz: gpz {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+       };
+};
index c390c8f0c8afae80b3f807c95fec89330ad22907..00cad0447d8fbb3b29e6ce393a2f0cdb6269bf66 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 /dts-v1/;
-/include/ "exynos4.dtsi"
+#include "exynos4.dtsi"
 
 / {
        model = "Samsung SMDKV310 on Exynos4210";
index 0ff69393b758621eb5d9d953cce61269ca2d5fba..81188bca13b429a8c761db4020c2d507fbeb1078 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "exynos4.dtsi"
+#include "exynos4210.dtsi"
 
 / {
        model = "Samsung Trats based on Exynos4210";
index 6941906aaa353b3a2ebcd5bb405a824937fc5a72..9139810b1a924e7fab07b306f5c121103ff90c4a 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "exynos4.dtsi"
+#include "exynos4210.dtsi"
 
 / {
        model = "Samsung Universal C210 based on Exynos4210 rev0";
                status = "disabled";
        };
 
+       soft-spi {
+               compatible = "u-boot,soft-spi";
+               cs-gpio = <&gpio 235 0>;        /* Y43 */
+               sclk-gpio = <&gpio 225 0>;      /* Y31 */
+               mosi-gpio = <&gpio 227 0>;      /* Y33 */
+               miso-gpio = <&gpio 224 0>;      /* Y30 */
+               spi-delay-us = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cs@0 {
+               };
+       };
+
        fimd@11c00000 {
                compatible = "samsung,exynos-fimd";
                reg = <0x11c00000 0xa4>;
diff --git a/arch/arm/dts/exynos4210.dtsi b/arch/arm/dts/exynos4210.dtsi
new file mode 100644 (file)
index 0000000..634a5c1
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Samsung's Exynos4210 SoC device tree source
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ * Copyright (c) 2010-2011 Linaro Ltd.
+ *             www.linaro.org
+ *
+ * Samsung's Exynos4210 SoC device nodes are listed in this file. Exynos4210
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4210 SoC. As device tree coverage for Exynos4210 increases, additional
+ * nodes can be added to this file.
+ *
+ * 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.
+*/
+
+#include "exynos4.dtsi"
+#include "exynos4210-pinctrl.dtsi"
+#include "exynos4210-pinctrl-uboot.dtsi"
+
+/ {
+       compatible = "samsung,exynos4210";
+
+       aliases {
+               pinctrl0 = &pinctrl_0;
+               pinctrl1 = &pinctrl_1;
+               pinctrl2 = &pinctrl_2;
+       };
+
+       pd_lcd1: lcd1-power-domain@10023CA0 {
+               compatible = "samsung,exynos4210-pd";
+               reg = <0x10023CA0 0x20>;
+       };
+
+       gic: interrupt-controller@10490000 {
+               cpu-offset = <0x8000>;
+       };
+
+       combiner: interrupt-controller@10440000 {
+               samsung,combiner-nr = <16>;
+               interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+                            <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+                            <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+                            <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
+       };
+
+       mct@10050000 {
+               compatible = "samsung,exynos4210-mct";
+               reg = <0x10050000 0x800>;
+               interrupt-parent = <&mct_map>;
+               interrupts = <0>, <1>, <2>, <3>, <4>, <5>;
+               clocks = <&clock 3>, <&clock 344>;
+               clock-names = "fin_pll", "mct";
+
+               mct_map: mct-map {
+                       #interrupt-cells = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <0 &gic 0 57 0>,
+                                       <1 &gic 0 69 0>,
+                                       <2 &combiner 12 6>,
+                                       <3 &combiner 12 7>,
+                                       <4 &gic 0 42 0>,
+                                       <5 &gic 0 48 0>;
+               };
+       };
+
+       clock: clock-controller@10030000 {
+               compatible = "samsung,exynos4210-clock";
+               reg = <0x10030000 0x20000>;
+               #clock-cells = <1>;
+       };
+
+       pmu {
+               compatible = "arm,cortex-a9-pmu";
+               interrupt-parent = <&combiner>;
+               interrupts = <2 2>, <3 2>;
+       };
+
+       pinctrl_0: pinctrl@11400000 {
+               compatible = "samsung,exynos4210-pinctrl";
+               reg = <0x11400000 0x1000>;
+               interrupts = <0 47 0>;
+       };
+
+       pinctrl_1: pinctrl@11000000 {
+               compatible = "samsung,exynos4210-pinctrl";
+               reg = <0x11000000 0x1000>;
+               interrupts = <0 46 0>;
+
+               wakup_eint: wakeup-interrupt-controller {
+                       compatible = "samsung,exynos4210-wakeup-eint";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 32 0>;
+               };
+       };
+
+       pinctrl_2: pinctrl@03860000 {
+               compatible = "samsung,exynos4210-pinctrl";
+               reg = <0x03860000 0x1000>;
+       };
+
+       tmu@100C0000 {
+               compatible = "samsung,exynos4210-tmu";
+               interrupt-parent = <&combiner>;
+               reg = <0x100C0000 0x100>;
+               interrupts = <2 4>;
+               clocks = <&clock 383>;
+               clock-names = "tmu_apbif";
+               status = "disabled";
+       };
+
+       g2d@12800000 {
+               compatible = "samsung,s5pv210-g2d";
+               reg = <0x12800000 0x1000>;
+               interrupts = <0 89 0>;
+               clocks = <&clock 177>, <&clock 277>;
+               clock-names = "sclk_fimg2d", "fimg2d";
+               status = "disabled";
+       };
+
+       camera {
+               clocks = <&clock 132>, <&clock 133>, <&clock 351>, <&clock 352>;
+               clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0", "pxl_async1";
+
+               fimc_0: fimc@11800000 {
+                       samsung,pix-limits = <4224 8192 1920 4224>;
+                       samsung,mainscaler-ext;
+                       samsung,cam-if;
+               };
+
+               fimc_1: fimc@11810000 {
+                       samsung,pix-limits = <4224 8192 1920 4224>;
+                       samsung,mainscaler-ext;
+                       samsung,cam-if;
+               };
+
+               fimc_2: fimc@11820000 {
+                       samsung,pix-limits = <4224 8192 1920 4224>;
+                       samsung,mainscaler-ext;
+                       samsung,lcd-wb;
+               };
+
+               fimc_3: fimc@11830000 {
+                       samsung,pix-limits = <1920 8192 1366 1920>;
+                       samsung,rotators = <0>;
+                       samsung,mainscaler-ext;
+                       samsung,lcd-wb;
+               };
+       };
+};
index 24d0bf18e3e7654c3dac33566edb4cfc14f4174b..4c5e2b39be5cb51181287e6390872b0016df7f5f 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "exynos4.dtsi"
+#include "exynos4.dtsi"
 
 / {
        model = "Odroid based on Exynos4412";
index cc58c878b82ba713f5ca8325642440dafcfd6d1f..3b1e4588b54b3cfb9bd0b5c6bcf3424239eb76c8 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "exynos4.dtsi"
+#include "exynos4412.dtsi"
 
 / {
        model = "Samsung Trats2 based on Exynos4412";
diff --git a/arch/arm/dts/exynos4412.dtsi b/arch/arm/dts/exynos4412.dtsi
new file mode 100644 (file)
index 0000000..87b339c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Samsung's Exynos4412 SoC device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung's Exynos4412 SoC device nodes are listed in this file. Exynos4412
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4412 SoC. As device tree coverage for Exynos4412 increases, additional
+ * nodes can be added to this file.
+ *
+ * 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.
+*/
+
+#include "exynos4x12.dtsi"
+
+/ {
+       compatible = "samsung,exynos4412";
+
+       gic: interrupt-controller@10490000 {
+               cpu-offset = <0x4000>;
+       };
+
+       interrupt-controller@10440000 {
+               samsung,combiner-nr = <20>;
+               interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+                            <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+                            <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+                            <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
+                            <0 107 0>, <0 108 0>, <0 48 0>, <0 42 0>;
+       };
+
+};
diff --git a/arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi b/arch/arm/dts/exynos4x12-pinctrl-uboot.dtsi
new file mode 100644 (file)
index 0000000..c02796d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * U-Boot additions to enable a generic Exynos GPIO driver
+ *
+ * Copyright (c) 2014 Google, Inc
+ */
+
+/{
+       pinctrl_0: pinctrl@11400000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpf0: gpf0 {
+                       reg = <0xc180>;
+               };
+               gpj0: gpj0 {
+                       reg = <0x240>;
+               };
+       };
+
+       pinctrl_1: pinctrl@11000000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpk0: gpk0 {
+                       reg = <0x40>;
+               };
+               gpm0: gpm0 {
+                       reg = <0x260>;
+               };
+               gpy0: gpy0 {
+                       reg = <0x120>;
+               };
+               gpx0: gpx0 {
+                       reg = <0xc00>;
+               };
+       };
+
+       pinctrl_2: pinctrl@03860000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       pinctrl_3: pinctrl@106E0000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+};
diff --git a/arch/arm/dts/exynos4x12-pinctrl.dtsi b/arch/arm/dts/exynos4x12-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..93f3998
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * Samsung's Exynos4x12 SoCs pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung's Exynos4x12 SoCs pin-mux and pin-config optiosn are listed as device
+ * tree nodes are listed in this file.
+ *
+ * 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.
+*/
+
+/ {
+       pinctrl@11400000 {
+               gpa0: gpa0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpa1: gpa1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb: gpb {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc0: gpc0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc1: gpc1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd0: gpd0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd1: gpd1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf0: gpf0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf1: gpf1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf2: gpf2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf3: gpf3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpj0: gpj0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpj1: gpj1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+       };
+
+       pinctrl@11000000 {
+               gpk0: gpk0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk1: gpk1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk2: gpk2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpk3: gpk3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl0: gpl0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl1: gpl1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpl2: gpl2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpm0: gpm0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpm1: gpm1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpm2: gpm2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpm3: gpm3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpm4: gpm4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpy0: gpy0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy1: gpy1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy2: gpy2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy3: gpy3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy4: gpy4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy5: gpy5 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy6: gpy6 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpx0: gpx0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+                                    <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx1: gpx1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+                                    <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx2: gpx2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx3: gpx3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+       };
+
+       pinctrl@03860000 {
+               gpz: gpz {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+       };
+
+       pinctrl@106E0000 {
+               gpv0: gpv0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpv1: gpv1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpv2: gpv2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpv3: gpv3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpv4: gpv4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+       };
+};
diff --git a/arch/arm/dts/exynos4x12.dtsi b/arch/arm/dts/exynos4x12.dtsi
new file mode 100644 (file)
index 0000000..5d58c6e
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Samsung's Exynos4x12 SoCs device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung's Exynos4x12 SoCs device nodes are listed in this file. Exynos4x12
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4x12 SoC. As device tree coverage for Exynos4x12 increases, additional
+ * nodes can be added to this file.
+ *
+ * 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.
+*/
+
+#include "exynos4.dtsi"
+#include "exynos4x12-pinctrl.dtsi"
+#include "exynos4x12-pinctrl-uboot.dtsi"
+
+/ {
+       aliases {
+               pinctrl0 = &pinctrl_0;
+               pinctrl1 = &pinctrl_1;
+               pinctrl2 = &pinctrl_2;
+               pinctrl3 = &pinctrl_3;
+               mshc0 = &mshc_0;
+       };
+
+       pd_isp: isp-power-domain@10023CA0 {
+               compatible = "samsung,exynos4210-pd";
+               reg = <0x10023CA0 0x20>;
+       };
+
+       clock: clock-controller@10030000 {
+               compatible = "samsung,exynos4412-clock";
+               reg = <0x10030000 0x20000>;
+               #clock-cells = <1>;
+       };
+
+       mct@10050000 {
+               compatible = "samsung,exynos4412-mct";
+               reg = <0x10050000 0x800>;
+               interrupt-parent = <&mct_map>;
+               interrupts = <0>, <1>, <2>, <3>, <4>;
+               clocks = <&clock 3>, <&clock 344>;
+               clock-names = "fin_pll", "mct";
+
+               mct_map: mct-map {
+                       #interrupt-cells = <1>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <0 &gic 0 57 0>,
+                                       <1 &combiner 12 5>,
+                                       <2 &combiner 12 6>,
+                                       <3 &combiner 12 7>,
+                                       <4 &gic 1 12 0>;
+               };
+       };
+
+       pinctrl_0: pinctrl@11400000 {
+               compatible = "samsung,exynos4x12-pinctrl";
+               reg = <0x11400000 0x1000>;
+               interrupts = <0 47 0>;
+       };
+
+       pinctrl_1: pinctrl@11000000 {
+               compatible = "samsung,exynos4x12-pinctrl";
+               reg = <0x11000000 0x1000>;
+               interrupts = <0 46 0>;
+
+               wakup_eint: wakeup-interrupt-controller {
+                       compatible = "samsung,exynos4210-wakeup-eint";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 32 0>;
+               };
+       };
+
+       pinctrl_2: pinctrl@03860000 {
+               compatible = "samsung,exynos4x12-pinctrl";
+               reg = <0x03860000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <10 0>;
+       };
+
+       pinctrl_3: pinctrl@106E0000 {
+               compatible = "samsung,exynos4x12-pinctrl";
+               reg = <0x106E0000 0x1000>;
+               interrupts = <0 72 0>;
+       };
+
+       g2d@10800000 {
+               compatible = "samsung,exynos4212-g2d";
+               reg = <0x10800000 0x1000>;
+               interrupts = <0 89 0>;
+               clocks = <&clock 177>, <&clock 277>;
+               clock-names = "sclk_fimg2d", "fimg2d";
+               status = "disabled";
+       };
+
+       mshc_0: mmc@12550000 {
+               compatible = "samsung,exynos4412-dw-mshc";
+               reg = <0x12550000 0x1000>;
+               interrupts = <0 77 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               fifo-depth = <0x80>;
+               clocks = <&clock 301>, <&clock 149>;
+               clock-names = "biu", "ciu";
+               status = "disabled";
+       };
+};
index a2b533a1368ccb503701cb8c77eeaf7f092c37c7..e53906892c82de8b0ba922927fff25c64c859045 100644 (file)
@@ -5,11 +5,38 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
 
 / {
        compatible = "samsung,exynos5";
 
+       combiner: interrupt-controller@10440000 {
+               compatible = "samsung,exynos4210-combiner";
+               #interrupt-cells = <2>;
+               interrupt-controller;
+               samsung,combiner-nr = <32>;
+               reg = <0x10440000 0x1000>;
+               interrupts =    <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+                               <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+                               <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+                               <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
+                               <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+                               <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+                               <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+                               <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+       };
+
+       gic: interrupt-controller@10481000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg =   <0x10481000 0x1000>,
+                       <0x10482000 0x1000>,
+                       <0x10484000 0x2000>,
+                       <0x10486000 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
        sromc@12250000 {
                compatible = "samsung,exynos-sromc";
                reg = <0x12250000 0x20>;
                #size-cells = <0>;
        };
 
+       combiner: interrupt-controller@10440000 {
+               compatible = "samsung,exynos4210-combiner";
+               #interrupt-cells = <2>;
+               interrupt-controller;
+               samsung,combiner-nr = <32>;
+               reg = <0x10440000 0x1000>;
+               interrupts =    <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+                               <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+                               <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+                               <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
+                               <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+                               <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+                               <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+                               <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+       };
+
+       gic: interrupt-controller@10481000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg =   <0x10481000 0x1000>,
+                       <0x10482000 0x1000>,
+                       <0x10484000 0x2000>,
+                       <0x10486000 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
        i2c@12c60000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C30000 0x100>;
                interrupts = <0 54 0>;
+               u-boot,dm-pre-reloc;
                id = <3>;
        };
 
diff --git a/arch/arm/dts/exynos5250-pinctrl-uboot.dtsi b/arch/arm/dts/exynos5250-pinctrl-uboot.dtsi
new file mode 100644 (file)
index 0000000..7edb0ca
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * U-Boot additions to enable a generic Exynos GPIO driver
+ *
+ * Copyright (c) 2014 Google, Inc
+ */
+
+/{
+       pinctrl_0: pinctrl@11400000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpc4: gpc4 {
+                       reg = <0x2e0>;
+               };
+               gpx0: gpx0 {
+                       reg = <0xc00>;
+               };
+       };
+
+       pinctrl_1: pinctrl@13400000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       pinctrl_2: pinctrl@10d10000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpv2: gpv2 {
+                       reg = <0x060>;
+               };
+               gpv4: gpv4 {
+                       reg = <0xc0>;
+               };
+       };
+
+       pinctrl_3: pinctrl@03860000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+};
diff --git a/arch/arm/dts/exynos5250-pinctrl.dtsi b/arch/arm/dts/exynos5250-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..67755a1
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Samsung's Exynos5250 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung's Exynos5250 SoC pin-mux and pin-config optiosn are listed as device
+ * tree nodes are listed in this file.
+ *
+ * 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.
+*/
+
+/ {
+       pinctrl@11400000 {
+               gpa0: gpa0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpa1: gpa1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpa2: gpa2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb0: gpb0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb1: gpb1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb2: gpb2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb3: gpb3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc0: gpc0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc1: gpc1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc2: gpc2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc3: gpc3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd0: gpd0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd1: gpd1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpy0: gpy0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy1: gpy1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy2: gpy2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy3: gpy3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy4: gpy4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy5: gpy5 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy6: gpy6 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpc4: gpc4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx0: gpx0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&combiner>;
+                       #interrupt-cells = <2>;
+                       interrupts = <23 0>, <24 0>, <25 0>, <25 1>,
+                                    <26 0>, <26 1>, <27 0>, <27 1>;
+               };
+
+               gpx1: gpx1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&combiner>;
+                       #interrupt-cells = <2>;
+                       interrupts = <28 0>, <28 1>, <29 0>, <29 1>,
+                                    <30 0>, <30 1>, <31 0>, <31 1>;
+               };
+
+               gpx2: gpx2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx3: gpx3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+       };
+
+       pinctrl@13400000 {
+               gpe0: gpe0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe1: gpe1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf0: gpf0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf1: gpf1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpg0: gpg0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpg1: gpg1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpg2: gpg2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gph0: gph0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gph1: gph1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+
+       pinctrl@10d10000 {
+               gpv0: gpv0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpv1: gpv1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpv2: gpv2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpv3: gpv3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpv4: gpv4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+
+       pinctrl@03860000 {
+               gpz: gpz {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+};
index 9020382d97cf4df92f7ba13513248c58a8f5f5f1..885040920c077cad8aa26f8360daed79bc4d0d81 100644 (file)
@@ -10,7 +10,7 @@
 */
 
 /dts-v1/;
-/include/ "exynos5250.dtsi"
+#include "exynos5250.dtsi"
 
 / {
        model = "SAMSUNG SMDK5250 board based on EXYNOS5250";
index ab4f2f858151c7710b2c114bcca9f11820c2cc57..6fd9275c4ef789134344bd4a774de154e18c4c5a 100644 (file)
@@ -10,7 +10,7 @@
 */
 
 /dts-v1/;
-/include/ "exynos5250.dtsi"
+#include "exynos5250.dtsi"
 
 / {
        model = "Google Snow";
                };
        };
 
+       spi@12d30000 {
+               spi-max-frequency = <50000000>;
+               firmware_storage_spi: flash@0 {
+                       compatible = "spi-flash";
+                       reg = <0>;
+               };
+       };
+
        spi@131b0000 {
                spi-max-frequency = <1000000>;
                spi-deactivate-delay = <100>;
index 0c644e7cac8ce563af433f726ece26abaf8922bc..ccbafe9b07d7500569c4be9a82f3cb57bdf5d322 100644 (file)
@@ -5,9 +5,48 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
-/include/ "exynos5.dtsi"
+#include "exynos5.dtsi"
+#include "exynos5250-pinctrl.dtsi"
+#include "exynos5250-pinctrl-uboot.dtsi"
 
 / {
+       aliases {
+               pinctrl0 = &pinctrl_0;
+               pinctrl1 = &pinctrl_1;
+               pinctrl2 = &pinctrl_2;
+               pinctrl3 = &pinctrl_3;
+       };
+
+       pinctrl_0: pinctrl@11400000 {
+               compatible = "samsung,exynos5250-pinctrl";
+               reg = <0x11400000 0x1000>;
+               interrupts = <0 46 0>;
+
+               wakup_eint: wakeup-interrupt-controller {
+                       compatible = "samsung,exynos4210-wakeup-eint";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 32 0>;
+               };
+       };
+
+       pinctrl_1: pinctrl@13400000 {
+               compatible = "samsung,exynos5250-pinctrl";
+               reg = <0x13400000 0x1000>;
+               interrupts = <0 45 0>;
+       };
+
+       pinctrl_2: pinctrl@10d10000 {
+               compatible = "samsung,exynos5250-pinctrl";
+               reg = <0x10d10000 0x1000>;
+               interrupts = <0 50 0>;
+       };
+
+       pinctrl_3: pinctrl@03860000 {
+               compatible = "samsung,exynos5250-pinctrl";
+               reg = <0x03860000 0x1000>;
+               interrupts = <0 47 0>;
+       };
+
        i2c@12ca0000 {
                #address-cells = <1>;
                #size-cells = <0>;
index 995e62b33721fe345dce5c705a0427382c1c2643..fde863de3cf6b00b9b5fbcc3aa7585f3026044fc 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "exynos54xx.dtsi"
+#include "exynos54xx.dtsi"
 
 / {
        model = "Samsung/Google Peach Pit board based on Exynos5420";
        spi@12d30000 { /* spi1 */
                spi-max-frequency = <50000000>;
                firmware_storage_spi: flash@0 {
+                       compatible = "spi-flash";
                        reg = <0>;
 
                        /*
index 1bc62562835f045b686a9cf3099055d8186fcc97..6855027389d8d84cf7ad59decc7a377d62034e39 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "exynos54xx.dtsi"
+#include "exynos54xx.dtsi"
 
 / {
        model = "SAMSUNG SMDK5420 board based on EXYNOS5420";
diff --git a/arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi b/arch/arm/dts/exynos54xx-pinctrl-uboot.dtsi
new file mode 100644 (file)
index 0000000..5a86211
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * U-Boot additions to enable a generic Exynos GPIO driver
+ *
+ * Copyright (c) 2014 Google, Inc
+ */
+
+/{
+       /*
+        * Replicate the ordering of arch/arm/include/asm/arch-exynos/gpio.h
+        * TODO(sjg@chromium.org): This ordering ceases to matter once GPIO
+        * numbers are not needed in U-Boot for exynos.
+        */
+       pinctrl@14010000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+       pinctrl@13400000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpy7 {
+               };
+
+               gpx0 {
+                       reg = <0xc00>;
+               };
+       };
+       pinctrl@13410000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+       pinctrl@14000000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+       pinctrl@03860000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+};
diff --git a/arch/arm/dts/exynos54xx-pinctrl.dtsi b/arch/arm/dts/exynos54xx-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..775d956
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Samsung's Exynos5420 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung's Exynos5420 SoC pin-mux and pin-config options are listed as device
+ * tree nodes are listed in this file.
+ *
+ * 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.
+*/
+
+#include "exynos54xx-pinctrl-uboot.dtsi"
+
+/ {
+       pinctrl@13400000 {
+               gpy7: gpy7 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx0: gpx0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&combiner>;
+                       #interrupt-cells = <2>;
+                       interrupts = <23 0>, <24 0>, <25 0>, <25 1>,
+                                    <26 0>, <26 1>, <27 0>, <27 1>;
+               };
+
+               gpx1: gpx1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       interrupt-parent = <&combiner>;
+                       #interrupt-cells = <2>;
+                       interrupts = <28 0>, <28 1>, <29 0>, <29 1>,
+                                    <30 0>, <30 1>, <31 0>, <31 1>;
+               };
+
+               gpx2: gpx2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpx3: gpx3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+
+       pinctrl@13410000 {
+               gpc0: gpc0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc1: gpc1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc2: gpc2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc3: gpc3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpc4: gpc4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpd1: gpd1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpy0: gpy0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy1: gpy1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy2: gpy2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy3: gpy3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy4: gpy4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy5: gpy5 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpy6: gpy6 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+       };
+
+       pinctrl@14000000 {
+               gpe0: gpe0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpe1: gpe1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf0: gpf0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpf1: gpf1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpg0: gpg0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpg1: gpg1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpg2: gpg2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpj4: gpj4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+
+       pinctrl@14010000 {
+               gpa0: gpa0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpa1: gpa1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpa2: gpa2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb0: gpb0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb1: gpb1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb2: gpb2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb3: gpb3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpb4: gpb4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gph0: gph0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+
+       pinctrl@03860000 {
+               gpz: gpz {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+       };
+};
index c21d798a23d0b54a295d6f0a90a8f5c578f925dc..916cf3a5b6681dd72d061eb7e48ab88d2ab8c270 100644 (file)
@@ -5,7 +5,8 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
-/include/ "exynos5.dtsi"
+#include "exynos5.dtsi"
+#include "exynos54xx-pinctrl.dtsi"
 
 / {
        config {
                i2c8 = "/i2c@12e00000";
                i2c9 = "/i2c@12e10000";
                i2c10 = "/i2c@12e20000";
+               pinctrl0 = &pinctrl_0;
+               pinctrl1 = &pinctrl_1;
+               pinctrl2 = &pinctrl_2;
+               pinctrl3 = &pinctrl_3;
+               pinctrl4 = &pinctrl_4;
                spi0 = "/spi@12d20000";
                spi1 = "/spi@12d30000";
                spi2 = "/spi@12d40000";
                reg = <0x14680000 0x100>;
        };
 
+       pinctrl_0: pinctrl@13400000 {
+               compatible = "samsung,exynos5420-pinctrl";
+               reg = <0x13400000 0x1000>;
+               interrupts = <0 45 0>;
+
+               wakeup-interrupt-controller {
+                       compatible = "samsung,exynos4210-wakeup-eint";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 32 0>;
+               };
+       };
+
+       pinctrl_1: pinctrl@13410000 {
+               compatible = "samsung,exynos5420-pinctrl";
+               reg = <0x13410000 0x1000>;
+               interrupts = <0 78 0>;
+       };
+
+       pinctrl_2: pinctrl@14000000 {
+               compatible = "samsung,exynos5420-pinctrl";
+               reg = <0x14000000 0x1000>;
+               interrupts = <0 46 0>;
+       };
+
+       pinctrl_3: pinctrl@14010000 {
+               compatible = "samsung,exynos5420-pinctrl";
+               reg = <0x14010000 0x1000>;
+               interrupts = <0 50 0>;
+       };
+
+       pinctrl_4: pinctrl@03860000 {
+               compatible = "samsung,exynos5420-pinctrl";
+               reg = <0x03860000 0x1000>;
+               interrupts = <0 47 0>;
+       };
+
        fimd@14400000 {
                /* sysmmu is not used in U-Boot */
                samsung,disable-sysmmu;
diff --git a/arch/arm/dts/s5pc100-pinctrl.dtsi b/arch/arm/dts/s5pc100-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..bd9f97c
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * U-Boot additions to enable a generic Exynos GPIO driver
+ *
+ * Copyright (c) 2014 Google, Inc
+ */
+
+/ {
+       pinctrl@e0300000 {
+               gpa0: gpa0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpa1: gpa1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpb: gpb {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpc: gpc {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpd: gpd {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpe0: gpe0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpe1: gpe1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpf0: gpf0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpf1: gpf1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpf2: gpf2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpf3: gpf3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpg0: gpg0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpg1: gpg1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpg2: gpg2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpg3: gpg3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpi: gpi {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj0: gpj0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj1: gpj1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj2: gpj2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj3: gpj3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj4: gpj4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpk0: gpk0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpk1: gpk1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpk2: gpk2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpk3: gpk3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpl0: gpl0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpl1: gpl1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpl2: gpl2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpl3: gpl3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpl4: gpl4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gph0: gph0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gph1: gph1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gph2: gph2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gph3: gph3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+       };
+};
diff --git a/arch/arm/dts/s5pc110-pinctrl.dtsi b/arch/arm/dts/s5pc110-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..d21b6ab
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * U-Boot additions to enable a generic Exynos GPIO driver
+ *
+ * Copyright (c) 2014 Google, Inc
+ */
+
+/ {
+       pinctrl@e0200000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpa0: gpa0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpa1: gpa1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpb: gpb {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpc0: gpc0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpc1: gpc1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpd0: gpd0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpd1: gpd1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpe0: gpe0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpe1: gpe1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpf0: gpf0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpf1: gpf1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpf2: gpf2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpf3: gpf3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpg0: gpg0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpg1: gpg1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpg2: gpg2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpg3: gpg3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpi: gpi {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj0: gpj0 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj1: gpj1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj2: gpj2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj3: gpj3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpj4: gpj4 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp01: gpmp01 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp02: gpmp02 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp03: gpmp03 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp04: gpmp04 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp05: gpmp05 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp06: gpmp06 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp07: gpmp07 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp10: gpmp10 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp11: gpmp11 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp12: gpmp12 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp13: gpmp13 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp14: gpmp14 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp15: gpmp15 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp16: gpmp16 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp17: gpmp17 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp18: gpmp18 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp20: gpmp20 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp21: gpmp21 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp22: gpmp22 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp23: gpmp23 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp24: gpmp24 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp25: gpmp25 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp26: gpmp26 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp27: gpmp27 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpmp28: gpmp28 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gph0: gph0 {
+                       reg = <0xc00>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gph1: gph1 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gph2: gph2 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gph3: gph3 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+       };
+};
index 2e671bbf7e9a99f54ad5c4b0d0e26c43ff49c5f5..7bbfe591cd88e1ae45bc25e7cbaf5d8a2fe5c67c 100644 (file)
@@ -9,6 +9,7 @@
 /dts-v1/;
 
 #include "skeleton.dtsi"
+#include "s5pc110-pinctrl.dtsi"
 
 / {
        model = "Samsung Goni based on S5PC110";
        aliases {
                serial2 = "/serial@e2900800";
                console = "/serial@e2900800";
+               pinctrl0 = &pinctrl0;
+       };
+
+       pinctrl0: pinctrl@e0200000 {
+               compatible = "samsung,s5pc110-pinctrl";
+               reg = <0xe0200000 0x1000>;
        };
 
        serial@e2900800 {
index 42754ce811c7c5eab93a298e23309181b728d765..95f15ed48d39ccd57e029f7abe3124ddcc1e9319 100644 (file)
@@ -9,6 +9,7 @@
 /dts-v1/;
 
 #include "skeleton.dtsi"
+#include "s5pc100-pinctrl.dtsi"
 
 / {
        model = "Samsung SMDKC100 based on S5PC100";
        aliases {
                serial0 = "/serial@ec000000";
                console = "/serial@ec000000";
+               pinctrl0 = &pinctrl0;
+       };
+
+       pinctrl0: pinctrl@e0300000 {
+               compatible = "samsung,s5pc100-pinctrl";
+               reg = <0xe0200000 0x1000>;
        };
 
        serial@ec000000 {
index cee5cfe0d2dbb8c6024fffba353e22eec57fc2ef..74e8a16280bd85afa150c77ef52861e734272d46 100644 (file)
@@ -15,6 +15,7 @@
                usb1 = "/usb@c5000000";
                sdhci0 = "/sdhci@c8000600";
                sdhci1 = "/sdhci@c8000000";
+               spi0 = "/spi@7000c380";
        };
 
        memory {
diff --git a/arch/arm/dts/tegra30-apalis.dts b/arch/arm/dts/tegra30-apalis.dts
new file mode 100644 (file)
index 0000000..5bad3e7
--- /dev/null
@@ -0,0 +1,304 @@
+/dts-v1/;
+
+#include "tegra30.dtsi"
+
+/ {
+       model = "Toradex Apalis T30";
+       compatible = "toradex,apalis_t30", "nvidia,tegra30";
+
+       chosen {
+               stdout-path = &uarta;
+       };
+
+       aliases {
+               i2c0 = "/i2c@7000d000";
+               i2c1 = "/i2c@7000c000";
+               i2c2 = "/i2c@7000c500";
+               i2c3 = "/i2c@7000c700";
+               sdhci0 = "/sdhci@78000600";
+               sdhci1 = "/sdhci@78000400";
+               sdhci2 = "/sdhci@78000000";
+               usb0 = "/usb@7d000000";
+               usb1 = "/usb@7d004000";
+               usb2 = "/usb@7d008000";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x40000000>;
+       };
+
+       pcie-controller@00003000 {
+               status = "okay";
+               avdd-pexa-supply = <&vdd2_reg>;
+               vdd-pexa-supply = <&vdd2_reg>;
+               avdd-pexb-supply = <&vdd2_reg>;
+               vdd-pexb-supply = <&vdd2_reg>;
+               avdd-pex-pll-supply = <&vdd2_reg>;
+               avdd-plle-supply = <&ldo6_reg>;
+               vddio-pex-ctl-supply = <&sys_3v3_reg>;
+               hvdd-pex-supply = <&sys_3v3_reg>;
+
+               pci@1,0 {
+                       nvidia,num-lanes = <4>;
+               };
+
+               pci@2,0 {
+                       nvidia,num-lanes = <1>;
+               };
+
+               pci@3,0 {
+                       status = "okay";
+                       nvidia,num-lanes = <1>;
+               };
+       };
+
+       /*
+        * GEN1_I2C: I2C1_SDA/SCL on MXM3 pin 209/211 (e.g. RTC on carrier
+        * board)
+        */
+       i2c@7000c000 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       /* GEN2_I2C: unused */
+
+       /*
+        * CAM_I2C: I2C3_SDA/SCL on MXM3 pin 201/203 (e.g. camera sensor on
+        * carrier board)
+        */
+       i2c@7000c500 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       /* DDC: I2C2_SDA/SCL on MXM3 pin 205/207 (e.g. display EDID) */
+       i2c@7000c700 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       /*
+        * PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
+        * touch screen controller
+        */
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <100000>;
+
+               pmic: tps65911@2d {
+                       compatible = "ti,tps65911";
+                       reg = <0x2d>;
+
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+
+                       ti,system-power-controller;
+
+                       #gpio-cells = <2>;
+                       gpio-controller;
+
+                       vcc1-supply = <&sys_3v3_reg>;
+                       vcc2-supply = <&sys_3v3_reg>;
+                       vcc3-supply = <&vio_reg>;
+                       vcc4-supply = <&sys_3v3_reg>;
+                       vcc5-supply = <&sys_3v3_reg>;
+                       vcc6-supply = <&vio_reg>;
+                       vcc7-supply = <&charge_pump_5v0_reg>;
+                       vccio-supply = <&sys_3v3_reg>;
+
+                       regulators {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               /* SW1: +V1.35_VDDIO_DDR */
+                               vdd1_reg: vdd1 {
+                                       regulator-name = "vddio_ddr_1v35";
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-always-on;
+                               };
+
+                               /* SW2: +V1.05 */
+                               vdd2_reg: vdd2 {
+                                       regulator-name =
+                                               "vdd_pexa,vdd_pexb,vdd_sata";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               /* SW CTRL: +V1.0_VDD_CPU */
+                               vddctrl_reg: vddctrl {
+                                       regulator-name = "vdd_cpu,vdd_sys";
+                                       regulator-min-microvolt = <1150000>;
+                                       regulator-max-microvolt = <1150000>;
+                                       regulator-always-on;
+                               };
+
+                               /* SWIO: +V1.8 */
+                               vio_reg: vio {
+                                       regulator-name = "vdd_1v8_gen";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               /* LDO1: unused */
+
+                               /*
+                                * EN_+V3.3 switching via FET:
+                                * +V3.3_AUDIO_AVDD_S, +V3.3 and +V1.8_VDD_LAN
+                                * see also v3_3 fixed supply
+                                */
+                               ldo2_reg: ldo2 {
+                                       regulator-name = "en_3v3";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
+                               };
+
+                               /* +V1.2_CSI */
+                               ldo3_reg: ldo3 {
+                                       regulator-name =
+                                               "avdd_dsi_csi,pwrdet_mipi";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                               };
+
+                               /* +V1.2_VDD_RTC */
+                               ldo4_reg: ldo4 {
+                                       regulator-name = "vdd_rtc";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+
+                               /*
+                                * +V2.8_AVDD_VDAC:
+                                * only required for analog RGB
+                                */
+                               ldo5_reg: ldo5 {
+                                       regulator-name = "avdd_vdac";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                                       regulator-always-on;
+                               };
+
+                               /*
+                                * +V1.05_AVDD_PLLE: avdd_plle should be 1.05V
+                                * but LDO6 can't set voltage in 50mV
+                                * granularity
+                                */
+                               ldo6_reg: ldo6 {
+                                       regulator-name = "avdd_plle";
+                                       regulator-min-microvolt = <1100000>;
+                                       regulator-max-microvolt = <1100000>;
+                               };
+
+                               /* +V1.2_AVDD_PLL */
+                               ldo7_reg: ldo7 {
+                                       regulator-name = "avdd_pll";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                               };
+
+                               /* +V1.0_VDD_DDR_HS */
+                               ldo8_reg: ldo8 {
+                                       regulator-name = "vdd_ddr_hs";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+                       };
+               };
+       };
+
+       /* SPI1: Apalis SPI1 */
+       spi@7000d400 {
+               status = "okay";
+               spi-max-frequency = <25000000>;
+       };
+
+       /* SPI4: CAN2 */
+       spi@7000da00 {
+               status = "okay";
+               spi-max-frequency = <25000000>;
+       };
+
+       /* SPI5: Apalis SPI2 */
+       spi@7000dc00 {
+               status = "okay";
+               spi-max-frequency = <25000000>;
+       };
+
+       /* SPI6: CAN1 */
+       spi@7000de00 {
+               status = "okay";
+               spi-max-frequency = <25000000>;
+       };
+
+       sdhci@78000000 {
+               status = "okay";
+               bus-width = <4>;
+               cd-gpios = <&gpio 229 1>; /* PCC5, SD1_CD# */
+       };
+
+       sdhci@78000400 {
+               status = "okay";
+               bus-width = <8>;
+               cd-gpios = <&gpio 171 1>; /* PV3, MMC1_CD# */
+       };
+
+       sdhci@78000600 {
+               status = "okay";
+               bus-width = <8>;
+               non-removable;
+       };
+
+       /* EHCI instance 0: USB1_DP/N -> USBO1_DP/N */
+       usb@7d000000 {
+               status = "okay";
+               dr_mode = "peripheral";
+               nvidia,vbus-gpio = <&gpio 157 0>;       /* PT5, USBO1_EN */
+       };
+
+       /* EHCI instance 1: USB2_DP/N -> USBH2_DP/N */
+       usb@7d004000 {
+               status = "okay";
+               nvidia,vbus-gpio = <&gpio 233 0>;       /* PDD1, USBH_EN */
+               phy_type = "utmi";
+       };
+
+       /* EHCI instance 2: USB3_DP/N -> USBH3_DP/N */
+       usb@7d008000 {
+               status = "okay";
+               nvidia,vbus-gpio = <&gpio 233 0>;       /* PDD1, USBH_EN */
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               sys_3v3_reg: regulator@100 {
+                       compatible = "regulator-fixed";
+                       reg = <100>;
+                       regulator-name = "3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               charge_pump_5v0_reg: regulator@101 {
+                       compatible = "regulator-fixed";
+                       reg = <101>;
+                       regulator-name = "5v0";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+       };
+};
index ad140def95f4d630e11519554f16d71fbfb10f25..9acd84d80296fa367f6e1196051cf9f9b200497c 100644 (file)
@@ -18,6 +18,7 @@
                i2c4 = "/i2c@7000c700";
                sdhci0 = "/sdhci@78000600";
                sdhci1 = "/sdhci@78000000";
+               spi0 = "/spi@7000da00";
                usb0 = "/usb@7d000000";
                usb1 = "/usb@7d008000";
        };
index b4fbe71aa534c01d60b541b790bd25b921fc7211..1b8ed737e049707f0cec91f491bdb2e84e3099f0 100644 (file)
@@ -18,6 +18,7 @@
                i2c4 = "/i2c@7000c700";
                sdhci0 = "/sdhci@78000600";
                sdhci1 = "/sdhci@78000000";
+               spi0 = "/spi@7000da00";
                usb0 = "/usb@7d008000";
        };
 
index 43d03ca4fa53a256bfe79cd3abdfe8fa937d2507..572520a00ec5e330d5bbacd4b187967d45db8ec8 100644 (file)
@@ -6,12 +6,17 @@
        model = "Toradex Colibri T30";
        compatible = "toradex,colibri_t30", "nvidia,tegra30";
 
+       chosen {
+               stdout-path = &uarta;
+       };
+
        aliases {
                i2c0 = "/i2c@7000d000";
                i2c1 = "/i2c@7000c000";
                i2c2 = "/i2c@7000c700";
                sdhci0 = "/sdhci@78000600";
                sdhci1 = "/sdhci@78000200";
+               spi0 = "/spi@7000d400";
                usb0 = "/usb@7d000000";
                usb1 = "/usb@7d004000"; /* on module only, for ASIX */
                usb2 = "/usb@7d008000";
index ed826a0e19c99b8cd76337aa46440a831e2b477a..09fc22760d0c6e973359f121f92c63feed26793d 100644 (file)
@@ -7,7 +7,9 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
+#include <bootm.h>
 #include <common.h>
+#include <netdev.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
index a58087399cedc8786983d5a41268e97976ee07e9..34f53872e89b3d0674f9cff2227a8d10ea510c45 100644 (file)
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <malloc.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/errno.h>
@@ -69,15 +70,53 @@ static void * const i2c_bases[] = {
 };
 
 /* i2c_index can be from 0 - 2 */
-void setup_i2c(unsigned i2c_index, int speed, int slave_addr,
-               struct i2c_pads_info *p)
+int setup_i2c(unsigned i2c_index, int speed, int slave_addr,
+             struct i2c_pads_info *p)
 {
+       char *name1, *name2;
+       int ret;
+
        if (i2c_index >= ARRAY_SIZE(i2c_bases))
-               return;
+               return -EINVAL;
+
+       name1 = malloc(9);
+       name2 = malloc(9);
+       if (!name1 || !name2)
+               return -ENOMEM;
+
+       sprintf(name1, "i2c_sda%d", i2c_index);
+       sprintf(name2, "i2c_scl%d", i2c_index);
+       ret = gpio_request(p->sda.gp, name1);
+       if (ret)
+               goto err_req1;
+
+       ret = gpio_request(p->scl.gp, name2);
+       if (ret)
+               goto err_req2;
+
        /* Enable i2c clock */
-       enable_i2c_clk(1, i2c_index);
+       ret = enable_i2c_clk(1, i2c_index);
+       if (ret)
+               goto err_clk;
+
        /* Make sure bus is idle */
-       force_idle_bus(p);
+       ret = force_idle_bus(p);
+       if (ret)
+               goto err_idle;
+
        bus_i2c_init(i2c_bases[i2c_index], speed, slave_addr,
                        force_idle_bus, p);
+
+       return 0;
+
+err_idle:
+err_clk:
+       gpio_free(p->scl.gp);
+err_req2:
+       gpio_free(p->sda.gp);
+err_req1:
+       free(name1);
+       free(name2);
+
+       return ret;
 }
index dbecf4e4348e776d4f62ee77b4dc581d7629b656..12256a38eb97a5803071ff526f4fd2ad3b81fb9b 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <asm/arch/sys_proto.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/imx-common/regs-common.h>
diff --git a/arch/arm/include/asm/arch-armada-xp/config.h b/arch/arm/include/asm/arch-armada-xp/config.h
new file mode 100644 (file)
index 0000000..00ee775
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * (C) Copyright 2011
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Lei Wen <leiwen@marvell.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/*
+ * This file should be included in board config header file.
+ *
+ * It supports common definitions for Armada XP platforms
+ */
+
+#ifndef _ARMADA_XP_CONFIG_H
+#define _ARMADA_XP_CONFIG_H
+
+#include <asm/arch/soc.h>
+
+#define MV88F78X60 /* for the DDR training bin_hdr code */
+
+#define CONFIG_SYS_CACHELINE_SIZE      32
+
+/*
+ * By default kwbimage.cfg from board specific folder is used
+ * If for some board, different configuration file need to be used,
+ * CONFIG_SYS_KWD_CONFIG should be defined in board specific header file
+ */
+#ifndef CONFIG_SYS_KWD_CONFIG
+#define        CONFIG_SYS_KWD_CONFIG   $(CONFIG_BOARDDIR)/kwbimage.cfg
+#endif /* CONFIG_SYS_KWD_CONFIG */
+
+/* Add target to build it automatically upon "make" */
+#define CONFIG_BUILD_TARGET    "u-boot.kwb"
+
+/* end of 16M scrubbed by training in bootrom */
+#define CONFIG_SYS_INIT_SP_ADDR                0x00FF0000
+#define CONFIG_NR_DRAM_BANKS_MAX       2
+
+#define MV_UART_CONSOLE_BASE           MVEBU_UART0_BASE
+
+/*
+ * SPI Flash configuration
+ */
+#ifdef CONFIG_CMD_SF
+#define CONFIG_HARD_SPI                        1
+#define CONFIG_KIRKWOOD_SPI            1
+#ifndef CONFIG_ENV_SPI_BUS
+# define CONFIG_ENV_SPI_BUS            0
+#endif
+#ifndef CONFIG_ENV_SPI_CS
+# define CONFIG_ENV_SPI_CS             0
+#endif
+#ifndef CONFIG_ENV_SPI_MAX_HZ
+# define CONFIG_ENV_SPI_MAX_HZ         50000000
+#endif
+#endif
+
+/*
+ * Ethernet Driver configuration
+ */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_CMD_MII
+#define CONFIG_MII             /* expose smi ove miiphy interface */
+#define CONFIG_MVNETA          /* Enable Marvell Gbe Controller Driver */
+#define CONFIG_PHYLIB
+#define CONFIG_ENV_OVERWRITE   /* ethaddr can be reprogrammed */
+#define CONFIG_PHY_GIGE                /* GbE speed/duplex detect */
+#endif /* CONFIG_CMD_NET */
+
+/*
+ * I2C related stuff
+ */
+#ifdef CONFIG_CMD_I2C
+#ifndef CONFIG_SYS_I2C_SOFT
+#define CONFIG_I2C_MVTWSI
+#endif
+#define CONFIG_SYS_I2C_SLAVE           0x0
+#define CONFIG_SYS_I2C_SPEED           100000
+#endif
+
+#endif /* _ARMADA_XP_CONFIG_H */
diff --git a/arch/arm/include/asm/arch-armada-xp/cpu.h b/arch/arm/include/asm/arch-armada-xp/cpu.h
new file mode 100644 (file)
index 0000000..6b60c21
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _ARMADA_XP_CPU_H
+#define _ARMADA_XP_CPU_H
+
+#include <asm/system.h>
+
+#ifndef __ASSEMBLY__
+
+#define MVEBU_REG_PCIE_DEVID           (MVEBU_REG_PCIE_BASE + 0x00)
+#define MVEBU_REG_PCIE_REVID           (MVEBU_REG_PCIE_BASE + 0x08)
+
+enum memory_bank {
+       BANK0,
+       BANK1,
+       BANK2,
+       BANK3
+};
+
+enum cpu_winen {
+       CPU_WIN_DISABLE,
+       CPU_WIN_ENABLE
+};
+
+enum cpu_target {
+       CPU_TARGET_DRAM = 0x0,
+       CPU_TARGET_DEVICEBUS_BOOTROM_SPI = 0x1,
+       CPU_TARGET_ETH23 = 0x3,
+       CPU_TARGET_PCIE02 = 0x4,
+       CPU_TARGET_ETH01 = 0x7,
+       CPU_TARGET_PCIE13 = 0x8,
+       CPU_TARGET_SASRAM = 0x9,
+       CPU_TARGET_NAND = 0xd,
+};
+
+enum cpu_attrib {
+       CPU_ATTR_SASRAM = 0x01,
+       CPU_ATTR_DRAM_CS0 = 0x0e,
+       CPU_ATTR_DRAM_CS1 = 0x0d,
+       CPU_ATTR_DRAM_CS2 = 0x0b,
+       CPU_ATTR_DRAM_CS3 = 0x07,
+       CPU_ATTR_NANDFLASH = 0x2f,
+       CPU_ATTR_SPIFLASH = 0x1e,
+       CPU_ATTR_BOOTROM = 0x1d,
+       CPU_ATTR_PCIE_IO = 0xe0,
+       CPU_ATTR_PCIE_MEM = 0xe8,
+       CPU_ATTR_DEV_CS0 = 0x3e,
+       CPU_ATTR_DEV_CS1 = 0x3d,
+       CPU_ATTR_DEV_CS2 = 0x3b,
+       CPU_ATTR_DEV_CS3 = 0x37,
+};
+
+/*
+ * Default Device Address MAP BAR values
+ */
+#define DEFADR_PCI_MEM         0x90000000
+#define DEFADR_PCI_IO          0xC0000000
+#define DEFADR_SPIF            0xF4000000
+#define DEFADR_BOOTROM         0xF8000000
+
+struct mbus_win {
+       u32 base;
+       u32 size;
+       u8 target;
+       u8 attr;
+};
+
+/*
+ * System registers
+ * Ref: Datasheet sec:A.28
+ */
+struct mvebu_system_registers {
+       u8 pad1[0x60];
+       u32 rstoutn_mask; /* 0x60 */
+       u32 sys_soft_rst; /* 0x64 */
+};
+
+/*
+ * GPIO Registers
+ * Ref: Datasheet sec:A.19
+ */
+struct kwgpio_registers {
+       u32 dout;
+       u32 oe;
+       u32 blink_en;
+       u32 din_pol;
+       u32 din;
+       u32 irq_cause;
+       u32 irq_mask;
+       u32 irq_level;
+};
+
+/*
+ * functions
+ */
+unsigned int mvebu_sdram_bar(enum memory_bank bank);
+unsigned int mvebu_sdram_bs(enum memory_bank bank);
+void mvebu_sdram_size_adjust(enum memory_bank bank);
+int mvebu_mbus_probe(struct mbus_win windows[], int count);
+#endif /* __ASSEMBLY__ */
+#endif /* _ARMADA_XP_CPU_H */
diff --git a/arch/arm/include/asm/arch-armada-xp/soc.h b/arch/arm/include/asm/arch-armada-xp/soc.h
new file mode 100644 (file)
index 0000000..963e7ac
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * Header file for the Marvell's Feroceon CPU core.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_ARMADA_XP_H
+#define _ASM_ARCH_ARMADA_XP_H
+
+#define SOC_MV78460_ID         0x7846
+
+/* TCLK Core Clock definition */
+#ifndef CONFIG_SYS_TCLK
+#define CONFIG_SYS_TCLK                250000000       /* 250MHz */
+#endif
+
+/* SOC specific definations */
+#define INTREG_BASE            0xd0000000
+#define INTREG_BASE_ADDR_REG   (INTREG_BASE + 0x20080)
+#define SOC_REGS_PHY_BASE      0xf1000000
+#define MVEBU_REGISTER(x)      (SOC_REGS_PHY_BASE + x)
+
+#define MVEBU_SDRAM_SCRATCH    (MVEBU_REGISTER(0x01504))
+#define MVEBU_SPI_BASE         (MVEBU_REGISTER(0x10600))
+#define MVEBU_TWSI_BASE                (MVEBU_REGISTER(0x11000))
+#define MVEBU_UART0_BASE       (MVEBU_REGISTER(0x12000))
+#define MVEBU_UART1_BASE       (MVEBU_REGISTER(0x12100))
+#define MVEBU_MPP_BASE         (MVEBU_REGISTER(0x18000))
+#define MVEBU_GPIO0_BASE       (MVEBU_REGISTER(0x18100))
+#define MVEBU_GPIO1_BASE       (MVEBU_REGISTER(0x18140))
+#define MVEBU_GPIO2_BASE       (MVEBU_REGISTER(0x18180))
+#define MVEBU_SYSTEM_REG_BASE  (MVEBU_REGISTER(0x18200))
+#define MVEBU_CPU_WIN_BASE     (MVEBU_REGISTER(0x20000))
+#define MVEBU_SDRAM_BASE       (MVEBU_REGISTER(0x20180))
+#define MVEBU_TIMER_BASE       (MVEBU_REGISTER(0x20300))
+#define MVEBU_EGIGA2_BASE      (MVEBU_REGISTER(0x30000))
+#define MVEBU_EGIGA3_BASE      (MVEBU_REGISTER(0x34000))
+#define MVEBU_REG_PCIE_BASE    (MVEBU_REGISTER(0x40000))
+#define MVEBU_EGIGA0_BASE      (MVEBU_REGISTER(0x70000))
+#define MVEBU_EGIGA1_BASE      (MVEBU_REGISTER(0x74000))
+
+#define SDRAM_MAX_CS           4
+#define SDRAM_ADDR_MASK                0xFF000000
+
+/* Armada XP GbE controller has 4 ports */
+#define MAX_MVNETA_DEVS                4
+
+/* Kirkwood CPU memory windows */
+#define MVCPU_WIN_CTRL_DATA    CPU_WIN_CTRL_DATA
+#define MVCPU_WIN_ENABLE       CPU_WIN_ENABLE
+#define MVCPU_WIN_DISABLE      CPU_WIN_DISABLE
+
+#endif /* _ASM_ARCH_ARMADA_XP_H */
index 9a49b6e05efa5af346953a183f88d415d98fe46d..db42896201b321fb623af79c78a22addddf9de34 100644 (file)
@@ -52,4 +52,13 @@ struct bcm2835_gpio_regs {
        u32 gppudclk[2];
 };
 
+/**
+ * struct bcm2835_gpio_platdata - GPIO platform description
+ *
+ * @base: Base address of GPIO controller
+ */
+struct bcm2835_gpio_platdata {
+       unsigned long base;
+};
+
 #endif /* _BCM2835_GPIO_H_ */
index 8fb5c2321ecdd5c95c43230e7198260cf10ed8a5..ad2ece64f49b3568e7903541360f89bb1d2e5c63 100644 (file)
@@ -284,7 +284,7 @@ enum exynos4_gpio_pin {
        EXYNOS4_GPIO_Y65,
        EXYNOS4_GPIO_Y66,
        EXYNOS4_GPIO_Y67,
-       EXYNOS4_GPIO_X00 = 896,         /* 896 0x380 */
+       EXYNOS4_GPIO_X00,               /* 256 0x100 */
        EXYNOS4_GPIO_X01,
        EXYNOS4_GPIO_X02,
        EXYNOS4_GPIO_X03,
@@ -292,7 +292,7 @@ enum exynos4_gpio_pin {
        EXYNOS4_GPIO_X05,
        EXYNOS4_GPIO_X06,
        EXYNOS4_GPIO_X07,
-       EXYNOS4_GPIO_X10,               /* 904 0x388 */
+       EXYNOS4_GPIO_X10,               /* 264 0x108 */
        EXYNOS4_GPIO_X11,
        EXYNOS4_GPIO_X12,
        EXYNOS4_GPIO_X13,
@@ -300,7 +300,7 @@ enum exynos4_gpio_pin {
        EXYNOS4_GPIO_X15,
        EXYNOS4_GPIO_X16,
        EXYNOS4_GPIO_X17,
-       EXYNOS4_GPIO_X20,               /* 912 0x390 */
+       EXYNOS4_GPIO_X20,               /* 272 0x110 */
        EXYNOS4_GPIO_X21,
        EXYNOS4_GPIO_X22,
        EXYNOS4_GPIO_X23,
@@ -308,7 +308,7 @@ enum exynos4_gpio_pin {
        EXYNOS4_GPIO_X25,
        EXYNOS4_GPIO_X26,
        EXYNOS4_GPIO_X27,
-       EXYNOS4_GPIO_X30,               /* 920 0x398 */
+       EXYNOS4_GPIO_X30,               /* 280 0x118 */
        EXYNOS4_GPIO_X31,
        EXYNOS4_GPIO_X32,
        EXYNOS4_GPIO_X33,
@@ -318,7 +318,7 @@ enum exynos4_gpio_pin {
        EXYNOS4_GPIO_X37,
 
        /* GPIO_PART3_STARTS */
-       EXYNOS4_GPIO_MAX_PORT_PART_2,   /* 928 0x3A0 */
+       EXYNOS4_GPIO_MAX_PORT_PART_2,   /* 288 0x120 */
        EXYNOS4_GPIO_Z0 = EXYNOS4_GPIO_MAX_PORT_PART_2,
        EXYNOS4_GPIO_Z1,
        EXYNOS4_GPIO_Z2,
@@ -389,7 +389,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_D15,
        EXYNOS4X12_GPIO_D16,
        EXYNOS4X12_GPIO_D17,
-       EXYNOS4X12_GPIO_F00 = 96,       /* 96 0x60 */
+       EXYNOS4X12_GPIO_F00,            /* 56 0x38 */
        EXYNOS4X12_GPIO_F01,
        EXYNOS4X12_GPIO_F02,
        EXYNOS4X12_GPIO_F03,
@@ -397,7 +397,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_F05,
        EXYNOS4X12_GPIO_F06,
        EXYNOS4X12_GPIO_F07,
-       EXYNOS4X12_GPIO_F10,            /* 104 0x68 */
+       EXYNOS4X12_GPIO_F10,            /* 64 0x40 */
        EXYNOS4X12_GPIO_F11,
        EXYNOS4X12_GPIO_F12,
        EXYNOS4X12_GPIO_F13,
@@ -405,7 +405,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_F15,
        EXYNOS4X12_GPIO_F16,
        EXYNOS4X12_GPIO_F17,
-       EXYNOS4X12_GPIO_F20,            /* 112 0x70 */
+       EXYNOS4X12_GPIO_F20,            /* 72 0x48 */
        EXYNOS4X12_GPIO_F21,
        EXYNOS4X12_GPIO_F22,
        EXYNOS4X12_GPIO_F23,
@@ -413,7 +413,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_F25,
        EXYNOS4X12_GPIO_F26,
        EXYNOS4X12_GPIO_F27,
-       EXYNOS4X12_GPIO_F30,            /* 120 0x78 */
+       EXYNOS4X12_GPIO_F30,            /* 80 0x50 */
        EXYNOS4X12_GPIO_F31,
        EXYNOS4X12_GPIO_F32,
        EXYNOS4X12_GPIO_F33,
@@ -421,7 +421,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_F35,
        EXYNOS4X12_GPIO_F36,
        EXYNOS4X12_GPIO_F37,
-       EXYNOS4X12_GPIO_J00 = 144,      /* 144 0x90 */
+       EXYNOS4X12_GPIO_J00,            /* 88 0x58 */
        EXYNOS4X12_GPIO_J01,
        EXYNOS4X12_GPIO_J02,
        EXYNOS4X12_GPIO_J03,
@@ -429,7 +429,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_J05,
        EXYNOS4X12_GPIO_J06,
        EXYNOS4X12_GPIO_J07,
-       EXYNOS4X12_GPIO_J10,            /* 152 0x98 */
+       EXYNOS4X12_GPIO_J10,            /* 96 0x60 */
        EXYNOS4X12_GPIO_J11,
        EXYNOS4X12_GPIO_J12,
        EXYNOS4X12_GPIO_J13,
@@ -439,8 +439,8 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_J17,
 
        /* GPIO_PART2_STARTS */
-       EXYNOS4X12_GPIO_MAX_PORT_PART_1,/* 160 0xA0 */
-       EXYNOS4X12_GPIO_K00 = 176,      /* 176 0xB0 */
+       EXYNOS4X12_GPIO_MAX_PORT_PART_1,/* 104 0x66 */
+       EXYNOS4X12_GPIO_K00 = EXYNOS4X12_GPIO_MAX_PORT_PART_1,
        EXYNOS4X12_GPIO_K01,
        EXYNOS4X12_GPIO_K02,
        EXYNOS4X12_GPIO_K03,
@@ -448,7 +448,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_K05,
        EXYNOS4X12_GPIO_K06,
        EXYNOS4X12_GPIO_K07,
-       EXYNOS4X12_GPIO_K10,            /* 184 0xB8 */
+       EXYNOS4X12_GPIO_K10,            /* 112 0x70 */
        EXYNOS4X12_GPIO_K11,
        EXYNOS4X12_GPIO_K12,
        EXYNOS4X12_GPIO_K13,
@@ -456,7 +456,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_K15,
        EXYNOS4X12_GPIO_K16,
        EXYNOS4X12_GPIO_K17,
-       EXYNOS4X12_GPIO_K20,            /* 192 0xC0 */
+       EXYNOS4X12_GPIO_K20,            /* 120 0x78 */
        EXYNOS4X12_GPIO_K21,
        EXYNOS4X12_GPIO_K22,
        EXYNOS4X12_GPIO_K23,
@@ -464,7 +464,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_K25,
        EXYNOS4X12_GPIO_K26,
        EXYNOS4X12_GPIO_K27,
-       EXYNOS4X12_GPIO_K30,            /* 200 0xC8 */
+       EXYNOS4X12_GPIO_K30,            /* 128 0x80 */
        EXYNOS4X12_GPIO_K31,
        EXYNOS4X12_GPIO_K32,
        EXYNOS4X12_GPIO_K33,
@@ -472,7 +472,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_K35,
        EXYNOS4X12_GPIO_K36,
        EXYNOS4X12_GPIO_K37,
-       EXYNOS4X12_GPIO_L00,            /* 208 0xD0 */
+       EXYNOS4X12_GPIO_L00,            /* 136 0x88 */
        EXYNOS4X12_GPIO_L01,
        EXYNOS4X12_GPIO_L02,
        EXYNOS4X12_GPIO_L03,
@@ -480,7 +480,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_L05,
        EXYNOS4X12_GPIO_L06,
        EXYNOS4X12_GPIO_L07,
-       EXYNOS4X12_GPIO_L10,            /* 216 0xD8 */
+       EXYNOS4X12_GPIO_L10,            /* 144 0x90 */
        EXYNOS4X12_GPIO_L11,
        EXYNOS4X12_GPIO_L12,
        EXYNOS4X12_GPIO_L13,
@@ -488,7 +488,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_L15,
        EXYNOS4X12_GPIO_L16,
        EXYNOS4X12_GPIO_L17,
-       EXYNOS4X12_GPIO_L20,            /* 224 0xE0 */
+       EXYNOS4X12_GPIO_L20,            /* 152 0x98 */
        EXYNOS4X12_GPIO_L21,
        EXYNOS4X12_GPIO_L22,
        EXYNOS4X12_GPIO_L23,
@@ -496,7 +496,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_L25,
        EXYNOS4X12_GPIO_L26,
        EXYNOS4X12_GPIO_L27,
-       EXYNOS4X12_GPIO_Y00,            /* 232 0xE8 */
+       EXYNOS4X12_GPIO_Y00,            /* 160 0xa0 */
        EXYNOS4X12_GPIO_Y01,
        EXYNOS4X12_GPIO_Y02,
        EXYNOS4X12_GPIO_Y03,
@@ -504,7 +504,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_Y05,
        EXYNOS4X12_GPIO_Y06,
        EXYNOS4X12_GPIO_Y07,
-       EXYNOS4X12_GPIO_Y10,            /* 240 0xF0 */
+       EXYNOS4X12_GPIO_Y10,            /* 168 0xa8 */
        EXYNOS4X12_GPIO_Y11,
        EXYNOS4X12_GPIO_Y12,
        EXYNOS4X12_GPIO_Y13,
@@ -512,7 +512,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_Y15,
        EXYNOS4X12_GPIO_Y16,
        EXYNOS4X12_GPIO_Y17,
-       EXYNOS4X12_GPIO_Y20,            /* 248 0xF8 */
+       EXYNOS4X12_GPIO_Y20,            /* 176 0xb0 */
        EXYNOS4X12_GPIO_Y21,
        EXYNOS4X12_GPIO_Y22,
        EXYNOS4X12_GPIO_Y23,
@@ -520,7 +520,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_Y25,
        EXYNOS4X12_GPIO_Y26,
        EXYNOS4X12_GPIO_Y27,
-       EXYNOS4X12_GPIO_Y30,            /* 256 0x100 */
+       EXYNOS4X12_GPIO_Y30,            /* 184 0xb8 */
        EXYNOS4X12_GPIO_Y31,
        EXYNOS4X12_GPIO_Y32,
        EXYNOS4X12_GPIO_Y33,
@@ -528,7 +528,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_Y35,
        EXYNOS4X12_GPIO_Y36,
        EXYNOS4X12_GPIO_Y37,
-       EXYNOS4X12_GPIO_Y40,            /* 264 0x108 */
+       EXYNOS4X12_GPIO_Y40,            /* 192 0xc0 */
        EXYNOS4X12_GPIO_Y41,
        EXYNOS4X12_GPIO_Y42,
        EXYNOS4X12_GPIO_Y43,
@@ -536,7 +536,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_Y45,
        EXYNOS4X12_GPIO_Y46,
        EXYNOS4X12_GPIO_Y47,
-       EXYNOS4X12_GPIO_Y50,            /* 272 0x110 */
+       EXYNOS4X12_GPIO_Y50,            /* 200 0xc8 */
        EXYNOS4X12_GPIO_Y51,
        EXYNOS4X12_GPIO_Y52,
        EXYNOS4X12_GPIO_Y53,
@@ -544,7 +544,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_Y55,
        EXYNOS4X12_GPIO_Y56,
        EXYNOS4X12_GPIO_Y57,
-       EXYNOS4X12_GPIO_Y60,            /* 280 0x118 */
+       EXYNOS4X12_GPIO_Y60,            /* 208 0xd0 */
        EXYNOS4X12_GPIO_Y61,
        EXYNOS4X12_GPIO_Y62,
        EXYNOS4X12_GPIO_Y63,
@@ -552,7 +552,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_Y65,
        EXYNOS4X12_GPIO_Y66,
        EXYNOS4X12_GPIO_Y67,
-       EXYNOS4X12_GPIO_M00 = 312,      /* 312 0xF0 */
+       EXYNOS4X12_GPIO_M00,            /* 216 0xd8 */
        EXYNOS4X12_GPIO_M01,
        EXYNOS4X12_GPIO_M02,
        EXYNOS4X12_GPIO_M03,
@@ -560,7 +560,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_M05,
        EXYNOS4X12_GPIO_M06,
        EXYNOS4X12_GPIO_M07,
-       EXYNOS4X12_GPIO_M10,            /* 320 0xF8 */
+       EXYNOS4X12_GPIO_M10,            /* 224 0xe0 */
        EXYNOS4X12_GPIO_M11,
        EXYNOS4X12_GPIO_M12,
        EXYNOS4X12_GPIO_M13,
@@ -568,7 +568,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_M15,
        EXYNOS4X12_GPIO_M16,
        EXYNOS4X12_GPIO_M17,
-       EXYNOS4X12_GPIO_M20,            /* 328 0x100 */
+       EXYNOS4X12_GPIO_M20,            /* 232 0xe8 */
        EXYNOS4X12_GPIO_M21,
        EXYNOS4X12_GPIO_M22,
        EXYNOS4X12_GPIO_M23,
@@ -576,7 +576,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_M25,
        EXYNOS4X12_GPIO_M26,
        EXYNOS4X12_GPIO_M27,
-       EXYNOS4X12_GPIO_M30,            /* 336 0x108 */
+       EXYNOS4X12_GPIO_M30,            /* 240 0xf0 */
        EXYNOS4X12_GPIO_M31,
        EXYNOS4X12_GPIO_M32,
        EXYNOS4X12_GPIO_M33,
@@ -584,7 +584,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_M35,
        EXYNOS4X12_GPIO_M36,
        EXYNOS4X12_GPIO_M37,
-       EXYNOS4X12_GPIO_M40,            /* 344 0x110 */
+       EXYNOS4X12_GPIO_M40,            /* 248 0xf8 */
        EXYNOS4X12_GPIO_M41,
        EXYNOS4X12_GPIO_M42,
        EXYNOS4X12_GPIO_M43,
@@ -592,7 +592,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_M45,
        EXYNOS4X12_GPIO_M46,
        EXYNOS4X12_GPIO_M47,
-       EXYNOS4X12_GPIO_X00 = 928,      /* 928 0x3A0 */
+       EXYNOS4X12_GPIO_X00,            /* 256 0x100 */
        EXYNOS4X12_GPIO_X01,
        EXYNOS4X12_GPIO_X02,
        EXYNOS4X12_GPIO_X03,
@@ -600,7 +600,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_X05,
        EXYNOS4X12_GPIO_X06,
        EXYNOS4X12_GPIO_X07,
-       EXYNOS4X12_GPIO_X10,            /* 936 0x3A8 */
+       EXYNOS4X12_GPIO_X10,            /* 264 0x108 */
        EXYNOS4X12_GPIO_X11,
        EXYNOS4X12_GPIO_X12,
        EXYNOS4X12_GPIO_X13,
@@ -608,7 +608,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_X15,
        EXYNOS4X12_GPIO_X16,
        EXYNOS4X12_GPIO_X17,
-       EXYNOS4X12_GPIO_X20,            /* 944 0x3B0 */
+       EXYNOS4X12_GPIO_X20,            /* 272 0x110 */
        EXYNOS4X12_GPIO_X21,
        EXYNOS4X12_GPIO_X22,
        EXYNOS4X12_GPIO_X23,
@@ -616,7 +616,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_X25,
        EXYNOS4X12_GPIO_X26,
        EXYNOS4X12_GPIO_X27,
-       EXYNOS4X12_GPIO_X30,            /* 952 0x3B8 */
+       EXYNOS4X12_GPIO_X30,            /* 280 0x118 */
        EXYNOS4X12_GPIO_X31,
        EXYNOS4X12_GPIO_X32,
        EXYNOS4X12_GPIO_X33,
@@ -626,7 +626,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_X37,
 
        /* GPIO_PART3_STARTS */
-       EXYNOS4X12_GPIO_MAX_PORT_PART_2,/* 960 0x3C0 */
+       EXYNOS4X12_GPIO_MAX_PORT_PART_2,/* 288 0x120 */
        EXYNOS4X12_GPIO_Z0 = EXYNOS4X12_GPIO_MAX_PORT_PART_2,
        EXYNOS4X12_GPIO_Z1,
        EXYNOS4X12_GPIO_Z2,
@@ -637,7 +637,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_Z7,
 
        /* GPIO_PART4_STARTS */
-       EXYNOS4X12_GPIO_MAX_PORT_PART_3,/* 968 0x3C8 */
+       EXYNOS4X12_GPIO_MAX_PORT_PART_3,/* 296 0x128 */
        EXYNOS4X12_GPIO_V00 = EXYNOS4X12_GPIO_MAX_PORT_PART_3,
        EXYNOS4X12_GPIO_V01,
        EXYNOS4X12_GPIO_V02,
@@ -646,7 +646,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_V05,
        EXYNOS4X12_GPIO_V06,
        EXYNOS4X12_GPIO_V07,
-       EXYNOS4X12_GPIO_V10,            /* 976 0x3D0 */
+       EXYNOS4X12_GPIO_V10,            /* 304 0x130 */
        EXYNOS4X12_GPIO_V11,
        EXYNOS4X12_GPIO_V12,
        EXYNOS4X12_GPIO_V13,
@@ -654,7 +654,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_V15,
        EXYNOS4X12_GPIO_V16,
        EXYNOS4X12_GPIO_V17,
-       EXYNOS4X12_GPIO_V20 = 992,      /* 992 0x3E0 */
+       EXYNOS4X12_GPIO_V20,            /* 312 0x138 */
        EXYNOS4X12_GPIO_V21,
        EXYNOS4X12_GPIO_V22,
        EXYNOS4X12_GPIO_V23,
@@ -662,7 +662,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_V25,
        EXYNOS4X12_GPIO_V26,
        EXYNOS4X12_GPIO_V27,
-       EXYNOS4X12_GPIO_V30 = 1000,     /* 1000 0x3E8 */
+       EXYNOS4X12_GPIO_V30,            /* 320 0x140 */
        EXYNOS4X12_GPIO_V31,
        EXYNOS4X12_GPIO_V32,
        EXYNOS4X12_GPIO_V33,
@@ -670,7 +670,7 @@ enum exynos4X12_gpio_pin {
        EXYNOS4X12_GPIO_V35,
        EXYNOS4X12_GPIO_V36,
        EXYNOS4X12_GPIO_V37,
-       EXYNOS4X12_GPIO_V40 = 1016,     /* 1016 0x3F8 */
+       EXYNOS4X12_GPIO_V40,            /* 328 0x148 */
        EXYNOS4X12_GPIO_V41,
        EXYNOS4X12_GPIO_V42,
        EXYNOS4X12_GPIO_V43,
@@ -1504,12 +1504,7 @@ static const struct gpio_name_num_table exynos5420_gpio_table[] = {
 void gpio_cfg_pin(int gpio, int cfg);
 void gpio_set_pull(int gpio, int mode);
 void gpio_set_drv(int gpio, int mode);
-int gpio_direction_input(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_set_value(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
 void gpio_set_rate(int gpio, int mode);
-struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio);
 int s5p_gpio_get_pin(unsigned gpio);
 #endif
 
index f7bfa0e74d7f68864a8ee090f77d5e2f4d025574..ccc8e4e7d64b57bc9d1e94587b5e8d0e42d3d690 100644 (file)
@@ -23,7 +23,7 @@
 #error "SOC Name not defined"
 #endif /* CONFIG_KW88F6281 */
 
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #define CONFIG_ARM926EJS       1       /* Basic Architecture */
 #define CONFIG_SYS_CACHELINE_SIZE      32
                                /* default Dcache Line length for kirkwood */
index 97daa403ce7f294400f90dde720de8a5720f24e0..926d347110f8265680171cd12f6bdc1302404b52 100644 (file)
@@ -140,11 +140,11 @@ struct kwgpio_registers {
  * functions
  */
 unsigned char get_random_hex(void);
-unsigned int kw_sdram_bar(enum memory_bank bank);
-unsigned int kw_sdram_bs(enum memory_bank bank);
-void kw_sdram_size_adjust(enum memory_bank bank);
+unsigned int mvebu_sdram_bar(enum memory_bank bank);
+unsigned int mvebu_sdram_bs(enum memory_bank bank);
+void mvebu_sdram_size_adjust(enum memory_bank bank);
 int kw_config_adr_windows(void);
-void kw_config_gpio(unsigned int gpp0_oe_val, unsigned int gpp1_oe_val,
+void mvebu_config_gpio(unsigned int gpp0_oe_val, unsigned int gpp1_oe_val,
                unsigned int gpp0_oe, unsigned int gpp1_oe);
 int kw_config_mpp(unsigned int mpp0_7, unsigned int mpp8_15,
                unsigned int mpp16_23, unsigned int mpp24_31,
index 5f4d78608559dd60f7babb5f70090429e3a56d43..aa8c5da36d35c4b3102083b1f8f9c916f0e0f622 100644 (file)
 
 #define GPIO_MAX               50
 #define GPIO_OFF(pin)          (((pin) >> 5) ? 0x0040 : 0x0000)
-#define GPIO_OUT(pin)          (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x00)
-#define GPIO_IO_CONF(pin)      (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x04)
-#define GPIO_BLINK_EN(pin)     (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x08)
-#define GPIO_IN_POL(pin)       (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x0c)
-#define GPIO_DATA_IN(pin)      (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x10)
-#define GPIO_EDGE_CAUSE(pin)   (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x14)
-#define GPIO_EDGE_MASK(pin)    (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x18)
-#define GPIO_LEVEL_MASK(pin)   (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x1c)
+#define GPIO_OUT(pin)          (MVEBU_GPIO0_BASE + GPIO_OFF(pin) + 0x00)
+#define GPIO_IO_CONF(pin)      (MVEBU_GPIO0_BASE + GPIO_OFF(pin) + 0x04)
+#define GPIO_BLINK_EN(pin)     (MVEBU_GPIO0_BASE + GPIO_OFF(pin) + 0x08)
+#define GPIO_IN_POL(pin)       (MVEBU_GPIO0_BASE + GPIO_OFF(pin) + 0x0c)
+#define GPIO_DATA_IN(pin)      (MVEBU_GPIO0_BASE + GPIO_OFF(pin) + 0x10)
+#define GPIO_EDGE_CAUSE(pin)   (MVEBU_GPIO0_BASE + GPIO_OFF(pin) + 0x14)
+#define GPIO_EDGE_MASK(pin)    (MVEBU_GPIO0_BASE + GPIO_OFF(pin) + 0x18)
+#define GPIO_LEVEL_MASK(pin)   (MVEBU_GPIO0_BASE + GPIO_OFF(pin) + 0x1c)
 
 /*
  * Kirkwood-specific GPIO API
similarity index 90%
rename from arch/arm/include/asm/arch-kirkwood/kirkwood.h
rename to arch/arm/include/asm/arch-kirkwood/soc.h
index 3ea51d7848c5f21bd93baef774b22e692f4eb2c0..58ed71b186413c4c014ca672a3af8ab29246928c 100644 (file)
 #define KW_REG_UNDOC_0x1470            (KW_REGISTER(0x1470))
 #define KW_REG_UNDOC_0x1478            (KW_REGISTER(0x1478))
 
+#define MVEBU_SDRAM_BASE               (KW_REGISTER(0x1500))
 #define KW_TWSI_BASE                   (KW_REGISTER(0x11000))
 #define KW_UART0_BASE                  (KW_REGISTER(0x12000))
 #define KW_UART1_BASE                  (KW_REGISTER(0x12100))
 #define KW_MPP_BASE                    (KW_REGISTER(0x10000))
-#define KW_GPIO0_BASE                  (KW_REGISTER(0x10100))
-#define KW_GPIO1_BASE                  (KW_REGISTER(0x10140))
+#define MVEBU_GPIO0_BASE                       (KW_REGISTER(0x10100))
+#define MVEBU_GPIO1_BASE                       (KW_REGISTER(0x10140))
 #define KW_RTC_BASE                    (KW_REGISTER(0x10300))
 #define KW_NANDF_BASE                  (KW_REGISTER(0x10418))
-#define KW_SPI_BASE                    (KW_REGISTER(0x10600))
+#define MVEBU_SPI_BASE                 (KW_REGISTER(0x10600))
 #define KW_CPU_WIN_BASE                        (KW_REGISTER(0x20000))
 #define KW_CPU_REG_BASE                        (KW_REGISTER(0x20100))
-#define KW_TIMER_BASE                  (KW_REGISTER(0x20300))
+#define MVEBU_TIMER_BASE                       (KW_REGISTER(0x20300))
 #define KW_REG_PCIE_BASE               (KW_REGISTER(0x40000))
 #define KW_USB20_BASE                  (KW_REGISTER(0x50000))
 #define KW_EGIGA0_BASE                 (KW_REGISTER(0x72000))
index 09dfc90a9b0391c7c092285886b1c3fe164daab6..062f3de1d05bfd4de1011762b55fbb6311c84fc9 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef __SYS_PROTO_H__
 #define __SYS_PROTO_H__
 
+#include <asm/imx-common/regs-common.h>
+
 int mxs_reset_block(struct mxs_register_32 *reg);
 int mxs_wait_mask_set(struct mxs_register_32 *reg,
                       uint32_t mask,
index 5866bf23e8d2a003515cf0e1637c1c27e2e66a40..34bd8c509aac924b6886b4a34fe0fe36cba38427 100644 (file)
@@ -64,6 +64,7 @@ void try_unlock_memory(void);
 u32 get_boot_type(void);
 void invalidate_dcache(u32);
 u32 wait_on_value(u32, u32, void *, u32);
+void cancel_out(u32 *num, u32 *den, u32 den_limit);
 void sdelay(unsigned long);
 void make_cs1_contiguous(void);
 void omap_nand_switch_ecc(uint32_t, uint32_t);
index d5dbc22c18d0b1717ecba69fddd1df892fcb0aaf..2de205e74b635ba320b02a2fed8994e814b01d42 100644 (file)
@@ -682,8 +682,7 @@ enum s5pc110_gpio_pin {
        S5PC110_GPIO_MP285,
        S5PC110_GPIO_MP286,
        S5PC110_GPIO_MP287,
-       S5PC110_GPIO_RES,
-       S5PC110_GPIO_H00 = (S5PC110_GPIO_RES + (48 * 8)),
+       S5PC110_GPIO_H00,
        S5PC110_GPIO_H01,
        S5PC110_GPIO_H02,
        S5PC110_GPIO_H03,
@@ -815,11 +814,7 @@ static const struct gpio_name_num_table s5pc110_gpio_table[] = {
 void gpio_cfg_pin(int gpio, int cfg);
 void gpio_set_pull(int gpio, int mode);
 void gpio_set_drv(int gpio, int mode);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_set_value(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
 void gpio_set_rate(int gpio, int mode);
-struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio);
 int s5p_gpio_get_pin(unsigned gpio);
 
 /* GPIO pins per bank  */
index ff773646cbec669607d5e03a624d1207b4c65b8b..783bb3c0fa12265901fdd3b99c9f2cc008486a83 100644 (file)
@@ -24,10 +24,11 @@ void gpio_early_init(void);  /* overrideable GPIO config        */
  * an empty stub function will be called.
  */
 
-void pinmux_init(void);      /* overrideable general pinmux setup */
-void pin_mux_usb(void);      /* overrideable USB pinmux setup     */
-void pin_mux_spi(void);      /* overrideable SPI pinmux setup     */
-void pin_mux_nand(void);     /* overrideable NAND pinmux setup    */
-void pin_mux_display(void);  /* overrideable DISPLAY pinmux setup */
+void pinmux_init(void);      /* overridable general pinmux setup */
+void pin_mux_usb(void);      /* overridable USB pinmux setup     */
+void pin_mux_spi(void);      /* overridable SPI pinmux setup     */
+void pin_mux_nand(void);     /* overridable NAND pinmux setup    */
+void pin_mux_mmc(void);      /* overridable mmc pinmux setup     */
+void pin_mux_display(void);  /* overridable DISPLAY pinmux setup */
 
 #endif
diff --git a/arch/arm/include/asm/arch-tegra114/mc.h b/arch/arm/include/asm/arch-tegra114/mc.h
new file mode 100644 (file)
index 0000000..044b1e0
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  (C) Copyright 2014
+ *  NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _TEGRA114_MC_H_
+#define _TEGRA114_MC_H_
+
+/**
+ * Defines the memory controller registers we need/care about
+ */
+struct mc_ctlr {
+       u32 reserved0[4];                       /* offset 0x00 - 0x0C */
+       u32 mc_smmu_config;                     /* offset 0x10 */
+       u32 mc_smmu_tlb_config;                 /* offset 0x14 */
+       u32 mc_smmu_ptc_config;                 /* offset 0x18 */
+       u32 mc_smmu_ptb_asid;                   /* offset 0x1C */
+       u32 mc_smmu_ptb_data;                   /* offset 0x20 */
+       u32 reserved1[3];                       /* offset 0x24 - 0x2C */
+       u32 mc_smmu_tlb_flush;                  /* offset 0x30 */
+       u32 mc_smmu_ptc_flush;                  /* offset 0x34 */
+       u32 reserved2[6];                       /* offset 0x38 - 0x4C */
+       u32 mc_emem_cfg;                        /* offset 0x50 */
+       u32 mc_emem_adr_cfg;                    /* offset 0x54 */
+       u32 mc_emem_adr_cfg_dev0;               /* offset 0x58 */
+       u32 mc_emem_adr_cfg_dev1;               /* offset 0x5C */
+       u32 reserved3[12];                      /* offset 0x60 - 0x8C */
+       u32 mc_emem_arb_reserved[28];           /* offset 0x90 - 0xFC */
+       u32 reserved4[338];                     /* offset 0x100 - 0x644 */
+       u32 mc_video_protect_bom;               /* offset 0x648 */
+       u32 mc_video_protect_size_mb;           /* offset 0x64c */
+       u32 mc_video_protect_reg_ctrl;          /* offset 0x650 */
+};
+
+#endif /* _TEGRA114_MC_H_ */
index 5d426b524a1e10776e73940e16c0be70596a6e2a..c3d061ec5867e389cd6b374d9e151428a8f3f5a8 100644 (file)
@@ -19,6 +19,7 @@
 
 #define NV_PA_SDRAM_BASE       0x80000000      /* 0x80000000 for real T114 */
 #define NV_PA_TSC_BASE         0x700F0000      /* System Counter TSC regs */
+#define NV_PA_MC_BASE          0x70019000
 
 #include <asm/arch-tegra/tegra.h>
 
diff --git a/arch/arm/include/asm/arch-tegra114/tegra114_spi.h b/arch/arm/include/asm/arch-tegra114/tegra114_spi.h
deleted file mode 100644 (file)
index 48197bc..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * NVIDIA Tegra SPI controller
- *
- * Copyright 2010-2013 NVIDIA Corporation
- *
- * 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 _TEGRA114_SPI_H_
-#define _TEGRA114_SPI_H_
-
-#include <asm/types.h>
-
-int tegra114_spi_init(int *node_list, int count);
-int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs);
-struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs,
-                                 unsigned int max_hz, unsigned int mode);
-void tegra114_spi_free_slave(struct spi_slave *slave);
-int tegra114_spi_claim_bus(struct spi_slave *slave);
-void tegra114_spi_cs_activate(struct spi_slave *slave);
-void tegra114_spi_cs_deactivate(struct spi_slave *slave);
-int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-                    const void *data_out, void *data_in, unsigned long flags);
-
-#endif /* _TEGRA114_SPI_H_ */
diff --git a/arch/arm/include/asm/arch-tegra20/mc.h b/arch/arm/include/asm/arch-tegra20/mc.h
new file mode 100644 (file)
index 0000000..9c6e3ff
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  (C) Copyright 2014
+ *  NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _TEGRA20_MC_H_
+#define _TEGRA20_MC_H_
+
+/**
+ * Defines the memory controller registers we need/care about
+ */
+struct mc_ctlr {
+       u32 reserved0[3];                       /* offset 0x00 - 0x08 */
+       u32 mc_emem_cfg;                        /* offset 0x0C */
+       u32 mc_emem_adr_cfg;                    /* offset 0x10 */
+       u32 mc_emem_arb_cfg0;                   /* offset 0x14 */
+       u32 mc_emem_arb_cfg1;                   /* offset 0x18 */
+       u32 mc_emem_arb_cfg2;                   /* offset 0x1C */
+       u32 reserved1;                          /* offset 0x20 */
+       u32 mc_gart_cfg;                        /* offset 0x24 */
+       u32 mc_gart_entry_addr;                 /* offset 0x28 */
+       u32 mc_gart_entry_data;                 /* offset 0x2C */
+       u32 mc_gart_error_req;                  /* offset 0x30 */
+       u32 mc_gart_error_addr;                 /* offset 0x34 */
+       u32 reserved2;                          /* offset 0x38 */
+       u32 mc_timeout_ctrl;                    /* offset 0x3C */
+       u32 reserved3[6];                       /* offset 0x40 - 0x54 */
+       u32 mc_decerr_emem_others_status;       /* offset 0x58 */
+       u32 mc_decerr_emem_others_adr;          /* offset 0x5C */
+       u32 reserved4[40];                      /* offset 0x60 - 0xFC */
+       u32 reserved5[93];                      /* offset 0x100 - 0x270 */
+};
+
+#endif /* _TEGRA20_MC_H_ */
index 18856ac3727d085977a9b5b1b70f9963f33548f4..22774abb936df1f3c0687041f7482e0cfca96a18 100644 (file)
@@ -9,6 +9,7 @@
 #define _TEGRA20_H_
 
 #define NV_PA_SDRAM_BASE       0x00000000
+#define NV_PA_MC_BASE          0x7000F000
 
 #include <asm/arch-tegra/tegra.h>
 
diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h b/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h
deleted file mode 100644 (file)
index e8cc68c..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * NVIDIA Tegra20 SPI-FLASH controller
- *
- * Copyright 2010-2012 NVIDIA Corporation
- *
- * 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 _TEGRA20_SPI_H_
-#define _TEGRA20_SPI_H_
-
-#include <asm/types.h>
-
-int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs);
-struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs,
-                                 unsigned int max_hz, unsigned int mode);
-void tegra20_spi_free_slave(struct spi_slave *slave);
-int tegra20_spi_init(int *node_list, int count);
-int tegra20_spi_claim_bus(struct spi_slave *slave);
-void tegra20_spi_cs_activate(struct spi_slave *slave);
-void tegra20_spi_cs_deactivate(struct spi_slave *slave);
-int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-            const void *data_out, void *data_in, unsigned long flags);
-
-#endif /* _TEGRA20_SPI_H_ */
diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_slink.h b/arch/arm/include/asm/arch-tegra20/tegra20_slink.h
deleted file mode 100644 (file)
index 5aa74dd..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * NVIDIA Tegra SPI-SLINK controller
- *
- * Copyright 2010-2013 NVIDIA Corporation
- *
- * 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 _TEGRA30_SPI_H_
-#define _TEGRA30_SPI_H_
-
-#include <asm/types.h>
-
-int tegra30_spi_init(int *node_list, int count);
-int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs);
-struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs,
-                                 unsigned int max_hz, unsigned int mode);
-void tegra30_spi_free_slave(struct spi_slave *slave);
-int tegra30_spi_claim_bus(struct spi_slave *slave);
-void tegra30_spi_cs_activate(struct spi_slave *slave);
-void tegra30_spi_cs_deactivate(struct spi_slave *slave);
-int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-                    const void *data_out, void *data_in, unsigned long flags);
-
-#endif /* _TEGRA30_SPI_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/mc.h b/arch/arm/include/asm/arch-tegra30/mc.h
new file mode 100644 (file)
index 0000000..242a1fc
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  (C) Copyright 2014
+ *  NVIDIA Corporation <www.nvidia.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _TEGRA30_MC_H_
+#define _TEGRA30_MC_H_
+
+/**
+ * Defines the memory controller registers we need/care about
+ */
+struct mc_ctlr {
+       u32 reserved0[4];                       /* offset 0x00 - 0x0C */
+       u32 mc_smmu_config;                     /* offset 0x10 */
+       u32 mc_smmu_tlb_config;                 /* offset 0x14 */
+       u32 mc_smmu_ptc_config;                 /* offset 0x18 */
+       u32 mc_smmu_ptb_asid;                   /* offset 0x1C */
+       u32 mc_smmu_ptb_data;                   /* offset 0x20 */
+       u32 reserved1[3];                       /* offset 0x24 - 0x2C */
+       u32 mc_smmu_tlb_flush;                  /* offset 0x30 */
+       u32 mc_smmu_ptc_flush;                  /* offset 0x34 */
+       u32 mc_smmu_asid_security;              /* offset 0x38 */
+       u32 reserved2[5];                       /* offset 0x3C - 0x4C */
+       u32 mc_emem_cfg;                        /* offset 0x50 */
+       u32 mc_emem_adr_cfg;                    /* offset 0x54 */
+       u32 mc_emem_adr_cfg_dev0;               /* offset 0x58 */
+       u32 mc_emem_adr_cfg_dev1;               /* offset 0x5C */
+       u32 reserved3[12];                      /* offset 0x60 - 0x8C */
+       u32 mc_emem_arb_reserved[28];           /* offset 0x90 - 0xFC */
+       u32 reserved4[338];                     /* offset 0x100 - 0x644 */
+       u32 mc_video_protect_bom;               /* offset 0x648 */
+       u32 mc_video_protect_size_mb;           /* offset 0x64c */
+       u32 mc_video_protect_reg_ctrl;          /* offset 0x650 */
+};
+
+#endif /* _TEGRA30_MC_H_ */
index c02c5d850037ffb7460b7df3b17f41cbf5c932ca..93671793a9f61d416824115d844ef3d939da17db 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _TEGRA30_H_
 #define _TEGRA30_H_
 
+#define NV_PA_MC_BASE          0x7000F000
 #define NV_PA_SDRAM_BASE       0x80000000      /* 0x80000000 for real T30 */
 
 #include <asm/arch-tegra/tegra.h>
diff --git a/arch/arm/include/asm/arch-uniphier/platdevice.h b/arch/arm/include/asm/arch-uniphier/platdevice.h
new file mode 100644 (file)
index 0000000..cdf7d13
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef ARCH_PLATDEVICE_H
+#define ARCH_PLATDEVICE_H
+
+#include <dm/platdata.h>
+#include <dm/platform_data/serial-uniphier.h>
+
+#define SERIAL_DEVICE(n, ba, clk)                                      \
+static struct uniphier_serial_platform_data serial_device##n = {       \
+       .base = ba,                                                     \
+       .uartclk = clk                                                  \
+};                                                                     \
+U_BOOT_DEVICE(serial##n) = {                                           \
+       .name = DRIVER_NAME,                                            \
+       .platdata = &serial_device##n                                   \
+};
+
+#endif /* ARCH_PLATDEVICE_H */
index 182c2f397f1748d0f574a4ffaa9a31335475fba5..af861635350d00209405435084ef767bec5b77e6 100644 (file)
@@ -52,8 +52,8 @@ struct i2c_pads_info {
                                        &mx6q_##name : &mx6s_##name
 #endif
 
-void setup_i2c(unsigned i2c_index, int speed, int slave_addr,
-               struct i2c_pads_info *p);
+int setup_i2c(unsigned i2c_index, int speed, int slave_addr,
+             struct i2c_pads_info *p);
 void bus_i2c_init(void *base, int speed, int slave_addr,
                int (*idle_bus_fn)(void *p), void *p);
 int bus_i2c_read(void *base, uchar chip, uint addr, int alen, uchar *buf,
index 560924e83ffdc56ee498a25e9b415c108fe1b3a3..d4a447b2b8a96568307bb907fd012b5da9f99187 100644 (file)
@@ -1107,6 +1107,7 @@ extern unsigned int __machine_arch_type;
 #define MACH_TYPE_ARMADILLO_800EVA     3863
 #define MACH_TYPE_KZM9G                4140
 #define MACH_TYPE_COLIBRI_T30          4493
+#define MACH_TYPE_APALIS_T30           4513
 
 #ifdef CONFIG_ARCH_EBSA110
 # ifdef machine_arch_type
@@ -14248,6 +14249,18 @@ extern unsigned int __machine_arch_type;
 # define machine_is_colibri_t30()      (0)
 #endif
 
+#ifdef CONFIG_MACH_APALIS_T30
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_APALIS_T30
+# endif
+# define machine_is_apalis_t30()       (machine_arch_type == MACH_TYPE_APALIS_T30)
+#else
+# define machine_is_apalis_t30()       (0)
+#endif
+
 /*
  * These have not yet been registered
  */
index 5d25d04c3bf68f45560aa120faf4182cefca8930..839af54d482e9fbc9e03c5a777eb9317566681ea 100644 (file)
 
 #include <asm/arch/cpu.h>
 
+enum gpio_method {
+       METHOD_GPIO_24XX        = 4,
+};
+
+#ifdef CONFIG_DM_GPIO
+
+/* Information about a GPIO bank */
+struct omap_gpio_platdata {
+       int bank_index;
+       ulong base;     /* address of registers in physical memory */
+       enum gpio_method method;
+};
+
+#else
+
 struct gpio_bank {
        void *base;
        int method;
@@ -30,8 +45,6 @@ struct gpio_bank {
 
 extern const struct gpio_bank *const omap_gpio_bank;
 
-#define METHOD_GPIO_24XX       4
-
 /**
  * Check if gpio is valid.
  *
@@ -39,4 +52,6 @@ extern const struct gpio_bank *const omap_gpio_bank;
  * @return 1 if ok, 0 on error
  */
 int gpio_is_valid(int gpio);
+#endif
+
 #endif /* _GPIO_H_ */
index b16694c72f8d6b6f06b2a6efd47cc612c4430ba6..f97f3dd1496aa54f7ca0667d0ebea299c95d50e7 100644 (file)
@@ -45,4 +45,19 @@ void reset_timer_masked      (void);
 ulong  get_timer_masked        (void);
 void   udelay_masked           (unsigned long usec);
 
+/* calls to c from vectors.S */
+void bad_mode(void);
+void do_undefined_instruction(struct pt_regs *pt_regs);
+void do_software_interrupt(struct pt_regs *pt_regs);
+void do_prefetch_abort(struct pt_regs *pt_regs);
+void do_data_abort(struct pt_regs *pt_regs);
+void do_not_used(struct pt_regs *pt_regs);
+#ifdef CONFIG_ARM64
+void do_fiq(struct pt_regs *pt_regs, unsigned int esr);
+void do_irq(struct pt_regs *pt_regs, unsigned int esr);
+#else
+void do_fiq(struct pt_regs *pt_regs);
+void do_irq(struct pt_regs *pt_regswq);
+#endif
+
 #endif /* _U_BOOT_ARM_H_ */
index 76adaf3aa4abf69916155cadd9f1e9e1a5effdb7..f6062557e6677fe0636520f9d7f76a9eedfc8d50 100644 (file)
@@ -34,6 +34,7 @@
 #include <onenand_uboot.h>
 #include <mmc.h>
 #include <scsi.h>
+#include <status_led.h>
 #include <libfdt.h>
 #include <fdtdec.h>
 #include <post.h>
@@ -63,25 +64,15 @@ extern void dataflash_print_info(void);
  ************************************************************************
  * May be supplied by boards if desired
  */
-inline void __coloured_LED_init(void) {}
-void coloured_LED_init(void)
-       __attribute__((weak, alias("__coloured_LED_init")));
-inline void __red_led_on(void) {}
-void red_led_on(void) __attribute__((weak, alias("__red_led_on")));
-inline void __red_led_off(void) {}
-void red_led_off(void) __attribute__((weak, alias("__red_led_off")));
-inline void __green_led_on(void) {}
-void green_led_on(void) __attribute__((weak, alias("__green_led_on")));
-inline void __green_led_off(void) {}
-void green_led_off(void) __attribute__((weak, alias("__green_led_off")));
-inline void __yellow_led_on(void) {}
-void yellow_led_on(void) __attribute__((weak, alias("__yellow_led_on")));
-inline void __yellow_led_off(void) {}
-void yellow_led_off(void) __attribute__((weak, alias("__yellow_led_off")));
-inline void __blue_led_on(void) {}
-void blue_led_on(void) __attribute__((weak, alias("__blue_led_on")));
-inline void __blue_led_off(void) {}
-void blue_led_off(void) __attribute__((weak, alias("__blue_led_off")));
+__weak void coloured_LED_init(void) {}
+__weak void red_led_on(void) {}
+__weak void red_led_off(void) {}
+__weak void green_led_on(void) {}
+__weak void green_led_off(void) {}
+__weak void yellow_led_on(void) {}
+__weak void yellow_led_off(void) {}
+__weak void blue_led_on(void) {}
+__weak void blue_led_off(void) {}
 
 /*
  ************************************************************************
@@ -198,27 +189,21 @@ static int arm_pci_init(void)
  */
 typedef int (init_fnc_t) (void);
 
-void __dram_init_banksize(void)
+__weak void dram_init_banksize(void)
 {
        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
        gd->bd->bi_dram[0].size =  gd->ram_size;
 }
-void dram_init_banksize(void)
-       __attribute__((weak, alias("__dram_init_banksize")));
 
-int __arch_cpu_init(void)
+__weak int arch_cpu_init(void)
 {
        return 0;
 }
-int arch_cpu_init(void)
-       __attribute__((weak, alias("__arch_cpu_init")));
 
-int __power_init_board(void)
+__weak int power_init_board(void)
 {
        return 0;
 }
-int power_init_board(void)
-       __attribute__((weak, alias("__power_init_board")));
 
        /* Record the board_init_f() bootstage (after arch_cpu_init()) */
 static int mark_bootstage(void)
index 39fe7a17fcff439f672331a90138454498755a45..0d19c8ae2366caee800920d36dce8d79f984b6c2 100644 (file)
@@ -15,6 +15,7 @@
 #include <common.h>
 #include <command.h>
 #include <image.h>
+#include <vxworks.h>
 #include <u-boot/zlib.h>
 #include <asm/byteorder.h>
 #include <libfdt.h>
index f6b7c03578b80e24a9a275bc7fe65f64ebe47666..9019736d2c74bec4da3fa4f97752954666a91ec1 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <common.h>
 #include <asm/proc-armv/ptrace.h>
+#include <asm/u-boot-arm.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/arch/arm/mvebu-common/Makefile b/arch/arm/mvebu-common/Makefile
new file mode 100644 (file)
index 0000000..9dcab69
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# (C) Copyright 2009
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  = dram.o
+obj-y  += gpio.o
+obj-$(CONFIG_ARMADA_XP) += mbus.o
+obj-y  += timer.o
similarity index 57%
rename from arch/arm/cpu/arm926ejs/kirkwood/dram.c
rename to arch/arm/mvebu-common/dram.c
index d73ae47c34162a4ed3ea46b9e1f95e6c84082cfc..db18791a8627e77f9baba41199a9ba5fba3af37c 100644 (file)
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-struct kw_sdram_bank {
+struct sdram_bank {
        u32     win_bar;
        u32     win_sz;
 };
 
-struct kw_sdram_addr_dec {
-       struct kw_sdram_bank    sdram_bank[4];
+struct sdram_addr_dec {
+       struct sdram_bank sdram_bank[4];
 };
 
-#define KW_REG_CPUCS_WIN_ENABLE                (1 << 0)
-#define KW_REG_CPUCS_WIN_WR_PROTECT    (1 << 1)
-#define KW_REG_CPUCS_WIN_WIN0_CS(x)    (((x) & 0x3) << 2)
-#define KW_REG_CPUCS_WIN_SIZE(x)       (((x) & 0xff) << 24)
+#define REG_CPUCS_WIN_ENABLE           (1 << 0)
+#define REG_CPUCS_WIN_WR_PROTECT       (1 << 1)
+#define REG_CPUCS_WIN_WIN0_CS(x)       (((x) & 0x3) << 2)
+#define REG_CPUCS_WIN_SIZE(x)          (((x) & 0xff) << 24)
 
 /*
- * kw_sdram_bar - reads SDRAM Base Address Register
+ * mvebu_sdram_bar - reads SDRAM Base Address Register
  */
-u32 kw_sdram_bar(enum memory_bank bank)
+u32 mvebu_sdram_bar(enum memory_bank bank)
 {
-       struct kw_sdram_addr_dec *base =
-               (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500);
+       struct sdram_addr_dec *base =
+               (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
        u32 result = 0;
        u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
 
@@ -46,31 +46,31 @@ u32 kw_sdram_bar(enum memory_bank bank)
 }
 
 /*
- * kw_sdram_bs_set - writes SDRAM Bank size
+ * mvebu_sdram_bs_set - writes SDRAM Bank size
  */
-static void kw_sdram_bs_set(enum memory_bank bank, u32 size)
+static void mvebu_sdram_bs_set(enum memory_bank bank, u32 size)
 {
-       struct kw_sdram_addr_dec *base =
-               (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500);
+       struct sdram_addr_dec *base =
+               (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
        /* Read current register value */
        u32 reg = readl(&base->sdram_bank[bank].win_sz);
 
        /* Clear window size */
-       reg &= ~KW_REG_CPUCS_WIN_SIZE(0xFF);
+       reg &= ~REG_CPUCS_WIN_SIZE(0xFF);
 
        /* Set new window size */
-       reg |= KW_REG_CPUCS_WIN_SIZE((size - 1) >> 24);
+       reg |= REG_CPUCS_WIN_SIZE((size - 1) >> 24);
 
        writel(reg, &base->sdram_bank[bank].win_sz);
 }
 
 /*
- * kw_sdram_bs - reads SDRAM Bank size
+ * mvebu_sdram_bs - reads SDRAM Bank size
  */
-u32 kw_sdram_bs(enum memory_bank bank)
+u32 mvebu_sdram_bs(enum memory_bank bank)
 {
-       struct kw_sdram_addr_dec *base =
-               (struct kw_sdram_addr_dec *)KW_REGISTER(0x1500);
+       struct sdram_addr_dec *base =
+               (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
        u32 result = 0;
        u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
 
@@ -81,15 +81,16 @@ u32 kw_sdram_bs(enum memory_bank bank)
        return result;
 }
 
-void kw_sdram_size_adjust(enum memory_bank bank)
+void mvebu_sdram_size_adjust(enum memory_bank bank)
 {
        u32 size;
 
        /* probe currently equipped RAM size */
-       size = get_ram_size((void *)kw_sdram_bar(bank), kw_sdram_bs(bank));
+       size = get_ram_size((void *)mvebu_sdram_bar(bank),
+                           mvebu_sdram_bs(bank));
 
        /* adjust SDRAM window size accordingly */
-       kw_sdram_bs_set(bank, size);
+       mvebu_sdram_bs_set(bank, size);
 }
 
 #ifndef CONFIG_SYS_BOARD_DRAM_INIT
@@ -99,8 +100,8 @@ int dram_init(void)
 
        gd->ram_size = 0;
        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-               gd->bd->bi_dram[i].start = kw_sdram_bar(i);
-               gd->bd->bi_dram[i].size = kw_sdram_bs(i);
+               gd->bd->bi_dram[i].start = mvebu_sdram_bar(i);
+               gd->bd->bi_dram[i].size = mvebu_sdram_bs(i);
                /*
                 * It is assumed that all memory banks are consecutive
                 * and without gaps.
@@ -110,7 +111,13 @@ int dram_init(void)
                if (gd->bd->bi_dram[i].start != gd->ram_size)
                        break;
 
-               gd->ram_size += gd->bd->bi_dram[i].size;
+               /*
+                * Don't report more than 3GiB of SDRAM, otherwise there is no
+                * address space left for the internal registers etc.
+                */
+               if ((gd->ram_size + gd->bd->bi_dram[i].size != 0) &&
+                   (gd->ram_size + gd->bd->bi_dram[i].size <= (3 << 30)))
+                       gd->ram_size += gd->bd->bi_dram[i].size;
 
        }
 
diff --git a/arch/arm/mvebu-common/gpio.c b/arch/arm/mvebu-common/gpio.c
new file mode 100644 (file)
index 0000000..56e54e0
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+/*
+ * mvebu_config_gpio - GPIO configuration
+ */
+void mvebu_config_gpio(u32 gpp0_oe_val, u32 gpp1_oe_val,
+                      u32 gpp0_oe, u32 gpp1_oe)
+{
+       struct kwgpio_registers *gpio0reg =
+               (struct kwgpio_registers *)MVEBU_GPIO0_BASE;
+       struct kwgpio_registers *gpio1reg =
+               (struct kwgpio_registers *)MVEBU_GPIO1_BASE;
+
+       /* Init GPIOS to default values as per board requirement */
+       writel(gpp0_oe_val, &gpio0reg->dout);
+       writel(gpp1_oe_val, &gpio1reg->dout);
+       writel(gpp0_oe, &gpio0reg->oe);
+       writel(gpp1_oe, &gpio1reg->oe);
+}
diff --git a/arch/arm/mvebu-common/mbus.c b/arch/arm/mvebu-common/mbus.c
new file mode 100644 (file)
index 0000000..05c9ef2
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * Address map functions for Marvell EBU SoCs (Kirkwood, Armada
+ * 370/XP, Dove, Orion5x and MV78xx0)
+ *
+ * Ported from the Barebox version to U-Boot by:
+ * Stefan Roese <sr@denx.de>
+ *
+ * The Barebox version is:
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * based on mbus driver from Linux
+ *   (C) Copyright 2008 Marvell Semiconductor
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ *
+ * The Marvell EBU SoCs have a configurable physical address space:
+ * the physical address at which certain devices (PCIe, NOR, NAND,
+ * etc.) sit can be configured. The configuration takes place through
+ * two sets of registers:
+ *
+ * - One to configure the access of the CPU to the devices. Depending
+ *   on the families, there are between 8 and 20 configurable windows,
+ *   each can be use to create a physical memory window that maps to a
+ *   specific device. Devices are identified by a tuple (target,
+ *   attribute).
+ *
+ * - One to configure the access to the CPU to the SDRAM. There are
+ *   either 2 (for Dove) or 4 (for other families) windows to map the
+ *   SDRAM into the physical address space.
+ *
+ * This driver:
+ *
+ * - Reads out the SDRAM address decoding windows at initialization
+ *   time, and fills the mbus_dram_info structure with these
+ *   informations. The exported function mv_mbus_dram_info() allow
+ *   device drivers to get those informations related to the SDRAM
+ *   address decoding windows. This is because devices also have their
+ *   own windows (configured through registers that are part of each
+ *   device register space), and therefore the drivers for Marvell
+ *   devices have to configure those device -> SDRAM windows to ensure
+ *   that DMA works properly.
+ *
+ * - Provides an API for platform code or device drivers to
+ *   dynamically add or remove address decoding windows for the CPU ->
+ *   device accesses. This API is mvebu_mbus_add_window_by_id(),
+ *   mvebu_mbus_add_window_remap_by_id() and
+ *   mvebu_mbus_del_window().
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <linux/mbus.h>
+
+#define BIT(nr)                        (1UL << (nr))
+
+/* DDR target is the same on all platforms */
+#define TARGET_DDR             0
+
+/* CPU Address Decode Windows registers */
+#define WIN_CTRL_OFF           0x0000
+#define   WIN_CTRL_ENABLE       BIT(0)
+#define   WIN_CTRL_TGT_MASK     0xf0
+#define   WIN_CTRL_TGT_SHIFT    4
+#define   WIN_CTRL_ATTR_MASK    0xff00
+#define   WIN_CTRL_ATTR_SHIFT   8
+#define   WIN_CTRL_SIZE_MASK    0xffff0000
+#define   WIN_CTRL_SIZE_SHIFT   16
+#define WIN_BASE_OFF           0x0004
+#define   WIN_BASE_LOW          0xffff0000
+#define   WIN_BASE_HIGH         0xf
+#define WIN_REMAP_LO_OFF       0x0008
+#define   WIN_REMAP_LOW         0xffff0000
+#define WIN_REMAP_HI_OFF       0x000c
+
+#define ATTR_HW_COHERENCY      (0x1 << 4)
+
+#define DDR_BASE_CS_OFF(n)     (0x0000 + ((n) << 3))
+#define  DDR_BASE_CS_HIGH_MASK  0xf
+#define  DDR_BASE_CS_LOW_MASK   0xff000000
+#define DDR_SIZE_CS_OFF(n)     (0x0004 + ((n) << 3))
+#define  DDR_SIZE_ENABLED       BIT(0)
+#define  DDR_SIZE_CS_MASK       0x1c
+#define  DDR_SIZE_CS_SHIFT      2
+#define  DDR_SIZE_MASK          0xff000000
+
+#define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4)
+
+struct mvebu_mbus_state;
+
+struct mvebu_mbus_soc_data {
+       unsigned int num_wins;
+       unsigned int num_remappable_wins;
+       unsigned int (*win_cfg_offset)(const int win);
+       void (*setup_cpu_target)(struct mvebu_mbus_state *s);
+};
+
+struct mvebu_mbus_state mbus_state
+       __attribute__ ((section(".data")));
+static struct mbus_dram_target_info mbus_dram_info
+       __attribute__ ((section(".data")));
+
+/*
+ * Functions to manipulate the address decoding windows
+ */
+
+static void mvebu_mbus_read_window(struct mvebu_mbus_state *mbus,
+                                  int win, int *enabled, u64 *base,
+                                  u32 *size, u8 *target, u8 *attr,
+                                  u64 *remap)
+{
+       void __iomem *addr = mbus->mbuswins_base +
+               mbus->soc->win_cfg_offset(win);
+       u32 basereg = readl(addr + WIN_BASE_OFF);
+       u32 ctrlreg = readl(addr + WIN_CTRL_OFF);
+
+       if (!(ctrlreg & WIN_CTRL_ENABLE)) {
+               *enabled = 0;
+               return;
+       }
+
+       *enabled = 1;
+       *base = ((u64)basereg & WIN_BASE_HIGH) << 32;
+       *base |= (basereg & WIN_BASE_LOW);
+       *size = (ctrlreg | ~WIN_CTRL_SIZE_MASK) + 1;
+
+       if (target)
+               *target = (ctrlreg & WIN_CTRL_TGT_MASK) >> WIN_CTRL_TGT_SHIFT;
+
+       if (attr)
+               *attr = (ctrlreg & WIN_CTRL_ATTR_MASK) >> WIN_CTRL_ATTR_SHIFT;
+
+       if (remap) {
+               if (win < mbus->soc->num_remappable_wins) {
+                       u32 remap_low = readl(addr + WIN_REMAP_LO_OFF);
+                       u32 remap_hi  = readl(addr + WIN_REMAP_HI_OFF);
+                       *remap = ((u64)remap_hi << 32) | remap_low;
+               } else {
+                       *remap = 0;
+               }
+       }
+}
+
+static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus,
+                                     int win)
+{
+       void __iomem *addr;
+
+       addr = mbus->mbuswins_base + mbus->soc->win_cfg_offset(win);
+
+       writel(0, addr + WIN_BASE_OFF);
+       writel(0, addr + WIN_CTRL_OFF);
+       if (win < mbus->soc->num_remappable_wins) {
+               writel(0, addr + WIN_REMAP_LO_OFF);
+               writel(0, addr + WIN_REMAP_HI_OFF);
+       }
+}
+
+/* Checks whether the given window number is available */
+static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus,
+                                    const int win)
+{
+       void __iomem *addr = mbus->mbuswins_base +
+               mbus->soc->win_cfg_offset(win);
+       u32 ctrl = readl(addr + WIN_CTRL_OFF);
+       return !(ctrl & WIN_CTRL_ENABLE);
+}
+
+/*
+ * Checks whether the given (base, base+size) area doesn't overlap an
+ * existing region
+ */
+static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
+                                      phys_addr_t base, size_t size,
+                                      u8 target, u8 attr)
+{
+       u64 end = (u64)base + size;
+       int win;
+
+       for (win = 0; win < mbus->soc->num_wins; win++) {
+               u64 wbase, wend;
+               u32 wsize;
+               u8 wtarget, wattr;
+               int enabled;
+
+               mvebu_mbus_read_window(mbus, win,
+                                      &enabled, &wbase, &wsize,
+                                      &wtarget, &wattr, NULL);
+
+               if (!enabled)
+                       continue;
+
+               wend = wbase + wsize;
+
+               /*
+                * Check if the current window overlaps with the
+                * proposed physical range
+                */
+               if ((u64)base < wend && end > wbase)
+                       return 0;
+
+               /*
+                * Check if target/attribute conflicts
+                */
+               if (target == wtarget && attr == wattr)
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int mvebu_mbus_find_window(struct mvebu_mbus_state *mbus,
+                                 phys_addr_t base, size_t size)
+{
+       int win;
+
+       for (win = 0; win < mbus->soc->num_wins; win++) {
+               u64 wbase;
+               u32 wsize;
+               int enabled;
+
+               mvebu_mbus_read_window(mbus, win,
+                                      &enabled, &wbase, &wsize,
+                                      NULL, NULL, NULL);
+
+               if (!enabled)
+                       continue;
+
+               if (base == wbase && size == wsize)
+                       return win;
+       }
+
+       return -ENODEV;
+}
+
+static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
+                                  int win, phys_addr_t base, size_t size,
+                                  phys_addr_t remap, u8 target,
+                                  u8 attr)
+{
+       void __iomem *addr = mbus->mbuswins_base +
+               mbus->soc->win_cfg_offset(win);
+       u32 ctrl, remap_addr;
+
+       ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
+               (attr << WIN_CTRL_ATTR_SHIFT)    |
+               (target << WIN_CTRL_TGT_SHIFT)   |
+               WIN_CTRL_ENABLE;
+
+       writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF);
+       writel(ctrl, addr + WIN_CTRL_OFF);
+       if (win < mbus->soc->num_remappable_wins) {
+               if (remap == MVEBU_MBUS_NO_REMAP)
+                       remap_addr = base;
+               else
+                       remap_addr = remap;
+               writel(remap_addr & WIN_REMAP_LOW, addr + WIN_REMAP_LO_OFF);
+               writel(0, addr + WIN_REMAP_HI_OFF);
+       }
+
+       return 0;
+}
+
+static int mvebu_mbus_alloc_window(struct mvebu_mbus_state *mbus,
+                                  phys_addr_t base, size_t size,
+                                  phys_addr_t remap, u8 target,
+                                  u8 attr)
+{
+       int win;
+
+       if (remap == MVEBU_MBUS_NO_REMAP) {
+               for (win = mbus->soc->num_remappable_wins;
+                    win < mbus->soc->num_wins; win++)
+                       if (mvebu_mbus_window_is_free(mbus, win))
+                               return mvebu_mbus_setup_window(mbus, win, base,
+                                                              size, remap,
+                                                              target, attr);
+       }
+
+
+       for (win = 0; win < mbus->soc->num_wins; win++)
+               if (mvebu_mbus_window_is_free(mbus, win))
+                       return mvebu_mbus_setup_window(mbus, win, base, size,
+                                                      remap, target, attr);
+
+       return -ENOMEM;
+}
+
+/*
+ * SoC-specific functions and definitions
+ */
+
+static unsigned int armada_370_xp_mbus_win_offset(int win)
+{
+       /* The register layout is a bit annoying and the below code
+        * tries to cope with it.
+        * - At offset 0x0, there are the registers for the first 8
+        *   windows, with 4 registers of 32 bits per window (ctrl,
+        *   base, remap low, remap high)
+        * - Then at offset 0x80, there is a hole of 0x10 bytes for
+        *   the internal registers base address and internal units
+        *   sync barrier register.
+        * - Then at offset 0x90, there the registers for 12
+        *   windows, with only 2 registers of 32 bits per window
+        *   (ctrl, base).
+        */
+       if (win < 8)
+               return win << 4;
+       else
+               return 0x90 + ((win - 8) << 3);
+}
+
+static unsigned int orion5x_mbus_win_offset(int win)
+{
+       return win << 4;
+}
+
+static void mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
+{
+       int i;
+       int cs;
+
+       mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
+
+       for (i = 0, cs = 0; i < 4; i++) {
+               u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
+               u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
+
+               /*
+                * We only take care of entries for which the chip
+                * select is enabled, and that don't have high base
+                * address bits set (devices can only access the first
+                * 32 bits of the memory).
+                */
+               if ((size & DDR_SIZE_ENABLED) &&
+                   !(base & DDR_BASE_CS_HIGH_MASK)) {
+                       struct mbus_dram_window *w;
+
+                       w = &mbus_dram_info.cs[cs++];
+                       w->cs_index = i;
+                       w->mbus_attr = 0xf & ~(1 << i);
+#if defined(CONFIG_ARMADA_XP)
+                       w->mbus_attr |= ATTR_HW_COHERENCY;
+#endif
+                       w->base = base & DDR_BASE_CS_LOW_MASK;
+                       w->size = (size | ~DDR_SIZE_MASK) + 1;
+               }
+       }
+       mbus_dram_info.num_cs = cs;
+}
+
+static const struct mvebu_mbus_soc_data
+armada_370_xp_mbus_data __maybe_unused = {
+       .num_wins            = 20,
+       .num_remappable_wins = 8,
+       .win_cfg_offset      = armada_370_xp_mbus_win_offset,
+       .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
+};
+
+static const struct mvebu_mbus_soc_data
+kirkwood_mbus_data __maybe_unused = {
+       .num_wins            = 8,
+       .num_remappable_wins = 4,
+       .win_cfg_offset      = orion5x_mbus_win_offset,
+       .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
+};
+
+/*
+ * Public API of the driver
+ */
+const struct mbus_dram_target_info *mvebu_mbus_dram_info(void)
+{
+       return &mbus_dram_info;
+}
+
+int mvebu_mbus_add_window_remap_by_id(unsigned int target,
+                                     unsigned int attribute,
+                                     phys_addr_t base, size_t size,
+                                     phys_addr_t remap)
+{
+       struct mvebu_mbus_state *s = &mbus_state;
+
+       if (!mvebu_mbus_window_conflicts(s, base, size, target, attribute)) {
+               printf("Cannot add window '%x:%x', conflicts with another window\n",
+                      target, attribute);
+               return -EINVAL;
+       }
+
+       return mvebu_mbus_alloc_window(s, base, size, remap, target, attribute);
+}
+
+int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
+                               phys_addr_t base, size_t size)
+{
+       return mvebu_mbus_add_window_remap_by_id(target, attribute, base,
+                                                size, MVEBU_MBUS_NO_REMAP);
+}
+
+int mvebu_mbus_del_window(phys_addr_t base, size_t size)
+{
+       int win;
+
+       win = mvebu_mbus_find_window(&mbus_state, base, size);
+       if (win < 0)
+               return win;
+
+       mvebu_mbus_disable_window(&mbus_state, win);
+       return 0;
+}
+
+int mbus_dt_setup_win(struct mvebu_mbus_state *mbus,
+                     u32 base, u32 size, u8 target, u8 attr)
+{
+       if (!mvebu_mbus_window_conflicts(mbus, base, size, target, attr)) {
+               printf("Cannot add window '%04x:%04x', conflicts with another window\n",
+                      target, attr);
+               return -EBUSY;
+       }
+
+       /*
+        * In U-Boot we first try to add the mbus window to the remap windows.
+        * If this fails, lets try to add the windows to the non-remap windows.
+        */
+       if (mvebu_mbus_alloc_window(mbus, base, size, base, target, attr)) {
+               if (mvebu_mbus_alloc_window(mbus, base, size,
+                                           MVEBU_MBUS_NO_REMAP, target, attr))
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+int mvebu_mbus_probe(struct mbus_win windows[], int count)
+{
+       int win;
+       int ret;
+       int i;
+
+#if defined(CONFIG_KIRKWOOD)
+       mbus_state.soc = &kirkwood_mbus_data;
+#endif
+#if defined(CONFIG_ARMADA_XP)
+       mbus_state.soc = &armada_370_xp_mbus_data;
+#endif
+
+       mbus_state.mbuswins_base = (void __iomem *)MVEBU_CPU_WIN_BASE;
+       mbus_state.sdramwins_base = (void __iomem *)MVEBU_SDRAM_BASE;
+
+       for (win = 0; win < mbus_state.soc->num_wins; win++)
+               mvebu_mbus_disable_window(&mbus_state, win);
+
+       mbus_state.soc->setup_cpu_target(&mbus_state);
+
+       /* Setup statically declared windows in the DT */
+       for (i = 0; i < count; i++) {
+               u32 base, size;
+               u8 target, attr;
+
+               target = windows[i].target;
+               attr = windows[i].attr;
+               base = windows[i].base;
+               size = windows[i].size;
+               ret = mbus_dt_setup_win(&mbus_state, base, size, target, attr);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
similarity index 63%
rename from arch/arm/cpu/arm926ejs/kirkwood/timer.c
rename to arch/arm/mvebu-common/timer.c
index a08f4a1456cf714341dbc3752eb7f407456150bd..40c4bc2da1b233732f69821dec23ccd90495bba9 100644 (file)
@@ -7,75 +7,68 @@
 
 #include <common.h>
 #include <asm/io.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 
-#define UBOOT_CNTR     0       /* counter to use for uboot timer */
-
-/* Timer reload and current value registers */
-struct kwtmr_val {
-       u32 reload;     /* Timer reload reg */
-       u32 val;        /* Timer value reg */
-};
-
-/* Timer registers */
-struct kwtmr_registers {
-       u32 ctrl;       /* Timer control reg */
-       u32 pad[3];
-       struct kwtmr_val tmr[2];
-       u32 wdt_reload;
-       u32 wdt_val;
-};
-
-struct kwtmr_registers *kwtmr_regs = (struct kwtmr_registers *)KW_TIMER_BASE;
+#define UBOOT_CNTR     0       /* counter to use for U-Boot timer */
 
 /*
  * ARM Timers Registers Map
  */
-#define CNTMR_CTRL_REG                 &kwtmr_regs->ctrl
-#define CNTMR_RELOAD_REG(tmrnum)       &kwtmr_regs->tmr[tmrnum].reload
-#define CNTMR_VAL_REG(tmrnum)          &kwtmr_regs->tmr[tmrnum].val
+#define CNTMR_CTRL_REG                 &tmr_regs->ctrl
+#define CNTMR_RELOAD_REG(tmrnum)       &tmr_regs->tmr[tmrnum].reload
+#define CNTMR_VAL_REG(tmrnum)          &tmr_regs->tmr[tmrnum].val
 
 /*
  * ARM Timers Control Register
  * CPU_TIMERS_CTRL_REG (CTCR)
  */
 #define CTCR_ARM_TIMER_EN_OFFS(cntr)   (cntr * 2)
-#define CTCR_ARM_TIMER_EN_MASK(cntr)   (1 << CTCR_ARM_TIMER_EN_OFFS)
 #define CTCR_ARM_TIMER_EN(cntr)                (1 << CTCR_ARM_TIMER_EN_OFFS(cntr))
-#define CTCR_ARM_TIMER_DIS(cntr)       (0 << CTCR_ARM_TIMER_EN_OFFS(cntr))
 
 #define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1)
-#define CTCR_ARM_TIMER_AUTO_MASK(cntr) (1 << 1)
 #define CTCR_ARM_TIMER_AUTO_EN(cntr)   (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
-#define CTCR_ARM_TIMER_AUTO_DIS(cntr)  (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
 
-/*
- * ARM Timer\Watchdog Reload Register
- * CNTMR_RELOAD_REG (TRR)
- */
-#define TRG_ARM_TIMER_REL_OFFS         0
-#define TRG_ARM_TIMER_REL_MASK         0xffffffff
+/* Only Armada XP have the 25MHz enable bit (Kirkwood doesn't) */
+#if defined(CONFIG_ARMADA_XP)
+#define CTCR_ARM_TIMER_25MHZ_OFFS(cntr)        (cntr + 11)
+#define CTCR_ARM_TIMER_25MHZ(cntr)     (1 << CTCR_ARM_TIMER_25MHZ_OFFS(cntr))
+#else
+#define CTCR_ARM_TIMER_25MHZ(cntr)     0
+#endif
 
-/*
- * ARM Timer\Watchdog Register
- * CNTMR_VAL_REG (TVRG)
- */
-#define TVR_ARM_TIMER_OFFS             0
-#define TVR_ARM_TIMER_MASK             0xffffffff
-#define TVR_ARM_TIMER_MAX              0xffffffff
 #define TIMER_LOAD_VAL                         0xffffffff
 
-#define READ_TIMER                     (readl(CNTMR_VAL_REG(UBOOT_CNTR)) /     \
-                                        (CONFIG_SYS_TCLK / 1000))
+#define timestamp                      gd->arch.tbl
+#define lastdec                                gd->arch.lastinc
+
+/* Timer reload and current value registers */
+struct kwtmr_val {
+       u32 reload;     /* Timer reload reg */
+       u32 val;        /* Timer value reg */
+};
+
+/* Timer registers */
+struct kwtmr_registers {
+       u32 ctrl;       /* Timer control reg */
+       u32 pad[3];
+       struct kwtmr_val tmr[4];
+       u32 wdt_reload;
+       u32 wdt_val;
+};
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define timestamp gd->arch.tbl
-#define lastdec gd->arch.lastinc
+static struct kwtmr_registers *tmr_regs =
+       (struct kwtmr_registers *)MVEBU_TIMER_BASE;
+
+static inline ulong read_timer(void)
+{
+       return readl(CNTMR_VAL_REG(UBOOT_CNTR)) / (CONFIG_SYS_TCLK / 1000);
+}
 
 ulong get_timer_masked(void)
 {
-       ulong now = READ_TIMER;
+       ulong now = read_timer();
 
        if (lastdec >= now) {
                /* normal mode */
@@ -119,20 +112,17 @@ void __udelay(unsigned long usec)
  */
 int timer_init(void)
 {
-       unsigned int cntmrctrl;
-
        /* load value into timer */
        writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR));
        writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR));
 
        /* enable timer in auto reload mode */
-       cntmrctrl = readl(CNTMR_CTRL_REG);
-       cntmrctrl |= CTCR_ARM_TIMER_EN(UBOOT_CNTR);
-       cntmrctrl |= CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR);
-       writel(cntmrctrl, CNTMR_CTRL_REG);
+       clrsetbits_le32(CNTMR_CTRL_REG, CTCR_ARM_TIMER_25MHZ(UBOOT_CNTR),
+                       CTCR_ARM_TIMER_EN(UBOOT_CNTR) |
+                       CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR));
 
        /* init the timestamp and lastdec value */
-       lastdec = READ_TIMER;
+       lastdec = read_timer();
        timestamp = 0;
 
        return 0;
index 7686b779bf7b20dd8bb2df58365314105d5f2b47..9b72bab56b64884543e1527a2186b388f7d460ca 100644 (file)
@@ -4,6 +4,9 @@ menu "MIPS architecture"
 config SYS_ARCH
        default "mips"
 
+config USE_PRIVATE_LIBGCC
+       default y
+
 choice
        prompt "Target select"
 
index 797478a2c7f661294bb462d56d71048459652cd7..76147154c22366b7f70e5a95e83c8ea8ee3dfbe1 100644 (file)
@@ -1,6 +1,9 @@
 /dts-v1/;
 
 / {
+       #address-cells = <1>;
+       #size-cells = <0>;
+
        chosen {
                stdout-path = "/serial";
        };
                num-gpios = <20>;
        };
 
+       spi@0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0>;
+               compatible = "sandbox,spi";
+               cs-gpios = <0>, <&gpio_a 0>;
+               flash@0 {
+                       reg = <0>;
+                       compatible = "spansion,m25p16", "sandbox,spi-flash";
+                       spi-max-frequency = <40000000>;
+                       sandbox,filename = "spi.bin";
+               };
+       };
+
+       cros-ec@0 {
+               compatible = "google,cros-ec";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               firmware_storage_spi: flash@0 {
+                       reg = <0 0x400000>;
+               };
+       };
+
 };
index 49b4a0f103a166ad02a0e5a316704aefb96ce8ca..9985e3c494922985d5f4f9538c9212dcb62e8bbf 100644 (file)
@@ -32,19 +32,6 @@ struct sandbox_spi_emu_ops {
        int (*xfer)(void *priv, const u8 *rx, u8 *tx, uint bytes);
 };
 
-/*
- * There are times when the data lines are allowed to tristate.  What
- * is actually sensed on the line depends on the hardware.  It could
- * always be 0xFF/0x00 (if there are pull ups/downs), or things could
- * float and so we'd get garbage back.  This func encapsulates that
- * scenario so we can worry about the details here.
- */
-static inline void sandbox_spi_tristate(u8 *buf, uint len)
-{
-       /* XXX: make this into a user config option ? */
-       memset(buf, 0xff, len);
-}
-
 /*
  * Extract the bus/cs from the spi spec and return the start of the spi
  * client spec.  If the bus/cs are invalid for the current config, then
index d17a82e90fcaab037057531ffef881e41b85525b..32d55ccc4c241deacdcf394daac81859d234657d 100644 (file)
@@ -42,7 +42,7 @@ enum state_terminal_raw {
 
 struct sandbox_spi_info {
        const char *spec;
-       const struct sandbox_spi_emu_ops *ops;
+       struct udevice *emul;
 };
 
 /* The complete state of the test system */
index ff9935acc4fcbe9522ce3b7bd282baf13880fa88..0dba8acbb2b320671541c939c739b98402f100b9 100644 (file)
@@ -4,6 +4,9 @@ menu "x86 architecture"
 config SYS_ARCH
        default "x86"
 
+config USE_PRIVATE_LIBGCC
+       default y
+
 choice
        prompt "Target select"
 
index 3106079c852c0ca54a4c3609805e3413909be2d4..3e7fedb913bed80965c0ca4e2765a35aaec98017 100644 (file)
@@ -28,6 +28,3 @@ PLATFORM_LDFLAGS += --emit-relocs -Bsymbolic -Bsymbolic-functions -m elf_i386
 LDFLAGS_FINAL += --gc-sections -pie
 LDFLAGS_FINAL += --wrap=__divdi3 --wrap=__udivdi3
 LDFLAGS_FINAL += --wrap=__moddi3 --wrap=__umoddi3
-
-export NORMAL_LIBGCC = $(shell $(CC) $(PLATFORM_CPPFLAGS) -print-libgcc-file-name)
-CONFIG_USE_PRIVATE_LIBGCC := arch/x86/lib
index 415bc2498935222afea91cbaee0e51011d69346f..e7bb3e33d5bdd999f246e56e02a2a06775553035 100644 (file)
@@ -9,5 +9,5 @@
 #
 
 extra-y        = start.o
-extra-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
-obj-y  = interrupts.o cpu.o
+obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
+obj-y  += interrupts.o cpu.o
index 329bb3ab35bdce43bc83692c16b60fac04529a8a..338bab19e471fdd3f4ab088aa999afeb2e10145e 100644 (file)
@@ -85,12 +85,25 @@ car_init_ret:
        /* Align global data to 16-byte boundary */
        andl    $0xfffffff0, %esp
 
+       /* Zero the global data since it won't happen later */
+       xorl    %eax, %eax
+       movl    $GENERATED_GBL_DATA_SIZE, %ecx
+       movl    %esp, %edi
+       rep     stosb
+
        /* Setup first parameter to setup_gdt */
        movl    %esp, %eax
 
        /* Reserve space for global descriptor table */
        subl    $X86_GDT_SIZE, %esp
 
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
+       subl    $CONFIG_SYS_MALLOC_F_LEN, %esp
+       movl    %eax, %edx
+       addl    $GD_MALLOC_BASE, %edx
+       movl    %esp, (%edx)
+#endif
+
        /* Align temporary global descriptor table to 16-byte boundary */
        andl    $0xfffffff0, %esp
 
index 8b9b327cd48734fbd50b71dbe3d6a238151d7074..6968fda6494998d1d595c9862e64a10a8082a3e1 100644 (file)
@@ -70,7 +70,7 @@ idt_ptr:
  * GDT is setup in a safe location in RAM
  */
 gdt_ptr:
-       .word   0x20            /* limit (32 bytes = 4 GDT entries) */
+       .word   0x1f            /* limit (31 bytes = 4 GDT entries - 1) */
        .long   BOOT_SEG + gdt  /* base */
 
 /* Some CPUs are picky about GDT alignment... */
index 4862a59704e0deec573debe84c2c64363c357e95..c8dc4cec3c99aac8edf1cbd9186ca900223bc241 100644 (file)
@@ -1,13 +1,14 @@
 /include/ "skeleton.dtsi"
 
 / {
-       aliases {
-               console = "/serial";
+       chosen {
+               stdout-path = "/serial";
        };
 
        serial {
-               compatible = "ns16550";
-               reg-shift = <1>;
+               compatible = "coreboot-uart";
+               reg = <0x3f8 0x10>;
+               reg-shift = <0>;
                io-mapped = <1>;
                multiplier = <1>;
                baudrate = <115200>;
index 4a37dac4ea9adc470005da949b281f0e18923ef6..f2fcb3927cbbb323f30c69468c8aaf687b390f06 100644 (file)
               silent_console = <0>;
        };
 
-       gpio: gpio {};
+       gpioa {
+               compatible = "intel,ich6-gpio";
+               reg = <0 0x10>;
+               bank-name = "A";
+       };
+
+       gpiob {
+               compatible = "intel,ich6-gpio";
+               reg = <0x30 0x10>;
+               bank-name = "B";
+       };
+
+       gpioc {
+               compatible = "intel,ich6-gpio";
+               reg = <0x40 0x10>;
+               bank-name = "C";
+       };
 
        serial {
                reg = <0x3f8 8>;
                        memory-map = <0xff800000 0x00800000>;
                };
        };
+
+       lpc {
+               compatible = "intel,lpc";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               cros-ec@200 {
+                       compatible = "google,cros-ec";
+                       reg = <0x204 1 0x200 1 0x880 0x80>;
+
+                       /* This describes the flash memory within the EC */
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       flash@8000000 {
+                               reg = <0x08000000 0x20000>;
+                               erase-value = <0xff>;
+                       };
+               };
+       };
 };
diff --git a/arch/x86/include/asm/arch-coreboot/gpio.h b/arch/x86/include/asm/arch-coreboot/gpio.h
new file mode 100644 (file)
index 0000000..3ec1816
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2014, Google Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _X86_ARCH_GPIO_H_
+#define _X86_ARCH_GPIO_H_
+
+struct ich6_bank_platdata {
+       uint32_t base_addr;
+       const char *bank_name;
+};
+
+#endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/bootm.h b/arch/x86/include/asm/bootm.h
new file mode 100644 (file)
index 0000000..033ab79
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef ARM_BOOTM_H
+#define ARM_BOOTM_H
+
+void bootm_announce_and_cleanup(void);
+
+#endif
index f06a15cdfca06c76f87e2d2209077856286cea7d..ff15828a713de5d1258aada2dc5aa599734ca900 100644 (file)
@@ -8,4 +8,7 @@
 #define _ASM_CONFIG_H_
 
 #define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_LMB
+#define CONFIG_SYS_BOOT_RAMDISK_HIGH
+
 #endif
index fe09f31515455e12dc8ddcef786db2b76630ee81..8bda414dbd73bdef24c93a816b39a1eb8a6129e6 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _X86_GPIO_H_
 #define _X86_GPIO_H_
 
+#include <asm/arch/gpio.h>
 #include <asm-generic/gpio.h>
 
 #endif /* _X86_GPIO_H_ */
index 0f9665f5495160353e40f8a9d27af726f17ceb16..e6d183b4796bc8ac951d68d3a9f4a9fdfcccfec5 100644 (file)
 #define SYSCTLA         0x92
 #define SLAVE_PIC       0xa0
 
-#if 1
-#define UART0_BASE     0x3f8
-#define UART1_BASE     0x2f8
-#else
-/* FixMe: uarts swapped */
-#define UART0_BASE     0x2f8
-#define UART1_BASE     0x3f8
-#endif
-
-
 #endif
index f7303abccbd3380384b1fa5624cf305683ddfab8..25b672a0c13d831f0ddf1df0f4c17717dab8c863 100644 (file)
@@ -20,9 +20,9 @@ obj-$(CONFIG_SYS_X86_TSC_TIMER)       += tsc_timer.o
 obj-$(CONFIG_VIDEO_VGA)        += video.o
 obj-$(CONFIG_CMD_ZBOOT)        += zimage.o
 
-LIBGCC := $(notdir $(NORMAL_LIBGCC))
-extra-y := $(LIBGCC)
+extra-$(CONFIG_USE_PRIVATE_LIBGCC) := lib.a
 
+NORMAL_LIBGCC = $(shell $(CC) $(PLATFORM_CPPFLAGS) -print-libgcc-file-name)
 OBJCOPYFLAGS := --prefix-symbols=__normal_
-$(obj)/$(LIBGCC): $(NORMAL_LIBGCC) FORCE
+$(obj)/lib.a: $(NORMAL_LIBGCC) FORCE
        $(call if_changed,objcopy)
index ff158dd6a9d940c823bfc59059ce6151bc60d675..4c5c7f5aa796bc679cf2bb91f6f16f64de128098 100644 (file)
 
 #include <common.h>
 #include <command.h>
+#include <fdt_support.h>
 #include <image.h>
 #include <u-boot/zlib.h>
 #include <asm/bootparam.h>
 #include <asm/byteorder.h>
 #include <asm/zimage.h>
+#ifdef CONFIG_SYS_COREBOOT
+#include <asm/arch/timestamp.h>
+#endif
 
 #define COMMAND_LINE_OFFSET 0x9000
 
-/*cmd_boot.c*/
-int do_bootm_linux(int flag, int argc, char * const argv[],
-               bootm_headers_t *images)
+/*
+ * Implement a weak default function for boards that optionally
+ * need to clean up the system before jumping to the kernel.
+ */
+__weak void board_final_cleanup(void)
 {
-       struct boot_params *base_ptr = NULL;
-       ulong os_data, os_len;
-       image_header_t *hdr;
-       void *load_address;
+}
 
-#if defined(CONFIG_FIT)
-       const void      *data;
-       size_t          len;
+void bootm_announce_and_cleanup(void)
+{
+       printf("\nStarting kernel ...\n\n");
+
+#ifdef CONFIG_SYS_COREBOOT
+       timestamp_add_now(TS_U_BOOT_START_KERNEL);
+#endif
+       bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+#ifdef CONFIG_BOOTSTAGE_REPORT
+       bootstage_report();
 #endif
+       board_final_cleanup();
+}
 
-       if (flag & BOOTM_STATE_OS_PREP)
-               return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
+#if defined(CONFIG_OF_LIBFDT) && !defined(CONFIG_OF_NO_KERNEL)
+int arch_fixup_memory_node(void *blob)
+{
+       bd_t    *bd = gd->bd;
+       int bank;
+       u64 start[CONFIG_NR_DRAM_BANKS];
+       u64 size[CONFIG_NR_DRAM_BANKS];
+
+       for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+               start[bank] = bd->bi_dram[bank].start;
+               size[bank] = bd->bi_dram[bank].size;
+       }
+
+       return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
+}
+#endif
 
+/* Subcommand: PREP */
+static int boot_prep_linux(bootm_headers_t *images)
+{
+       char *cmd_line_dest = NULL;
+       image_header_t *hdr;
+       int is_zimage = 0;
+       void *data = NULL;
+       size_t len;
+       int ret;
+
+#ifdef CONFIG_OF_LIBFDT
+       if (images->ft_len) {
+               debug("using: FDT\n");
+               if (image_setup_linux(images)) {
+                       puts("FDT creation failed! hanging...");
+                       hang();
+               }
+       }
+#endif
        if (images->legacy_hdr_valid) {
                hdr = images->legacy_hdr_os;
                if (image_check_type(hdr, IH_TYPE_MULTI)) {
+                       ulong os_data, os_len;
+
                        /* if multi-part image, we need to get first subimage */
                        image_multi_getimg(hdr, 0, &os_data, &os_len);
+                       data = (void *)os_data;
+                       len = os_len;
                } else {
                        /* otherwise get image data */
-                       os_data = image_get_data(hdr);
-                       os_len = image_get_data_size(hdr);
+                       data = (void *)image_get_data(hdr);
+                       len = image_get_data_size(hdr);
                }
+               is_zimage = 1;
 #if defined(CONFIG_FIT)
-       } else if (images->fit_uname_os) {
-               int ret;
-
+       } else if (images->fit_uname_os && is_zimage) {
                ret = fit_image_get_data(images->fit_hdr_os,
-                                       images->fit_noffset_os, &data, &len);
+                               images->fit_noffset_os,
+                               (const void **)&data, &len);
                if (ret) {
                        puts("Can't get image data/size!\n");
                        goto error;
                }
-               os_data = (ulong)data;
-               os_len = (ulong)len;
+               is_zimage = 1;
 #endif
-       } else {
-               puts("Could not find kernel image!\n");
-               goto error;
        }
 
-#ifdef CONFIG_CMD_ZBOOT
-       base_ptr = load_zimage((void *)os_data, os_len, &load_address);
-#endif
+       if (is_zimage) {
+               void *load_address;
+               char *base_ptr;
 
-       if (NULL == base_ptr) {
-               printf("## Kernel loading failed ...\n");
+               base_ptr = (char *)load_zimage(data, len, &load_address);
+               images->os.load = (ulong)load_address;
+               cmd_line_dest = base_ptr + COMMAND_LINE_OFFSET;
+               images->ep = (ulong)base_ptr;
+       } else if (images->ep) {
+               cmd_line_dest = (void *)images->ep + COMMAND_LINE_OFFSET;
+       } else {
+               printf("## Kernel loading failed (no setup) ...\n");
                goto error;
        }
 
-       if (setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
+       printf("Setup at %#08lx\n", images->ep);
+       ret = setup_zimage((void *)images->ep, cmd_line_dest,
                        0, images->rd_start,
-                       images->rd_end - images->rd_start)) {
+                       images->rd_end - images->rd_start);
+
+       if (ret) {
                printf("## Setting up boot parameters failed ...\n");
-               goto error;
+               return 1;
        }
 
-       boot_zimage(base_ptr, load_address);
-       /* does not return */
+       return 0;
 
 error:
        return 1;
 }
+
+/* Subcommand: GO */
+static int boot_jump_linux(bootm_headers_t *images)
+{
+       debug("## Transferring control to Linux (at address %08lx, kernel %08lx) ...\n",
+             images->ep, images->os.load);
+
+       boot_zimage((struct boot_params *)images->ep, (void *)images->os.load);
+       /* does not return */
+
+       return 1;
+}
+
+int do_bootm_linux(int flag, int argc, char * const argv[],
+               bootm_headers_t *images)
+{
+       /* No need for those on x86 */
+       if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
+               return -1;
+
+       if (flag & BOOTM_STATE_OS_PREP)
+               return boot_prep_linux(images);
+
+       if (flag & BOOTM_STATE_OS_GO) {
+               boot_jump_linux(images);
+               return 0;
+       }
+
+       return boot_jump_linux(images);
+}
index 1dab3cc78878dcea322d1685f0df0ed388f7a70c..b1902834e8a9514e5bdcce56b2bccbb03fdc7f7c 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/ptrace.h>
 #include <asm/zimage.h>
 #include <asm/byteorder.h>
+#include <asm/bootm.h>
 #include <asm/bootparam.h>
 #ifdef CONFIG_SYS_COREBOOT
 #include <asm/arch/timestamp.h>
@@ -242,41 +243,27 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
                hdr->loadflags |= HEAP_FLAG;
        }
 
-       if (bootproto >= 0x0202) {
-               hdr->cmd_line_ptr = (uintptr_t)cmd_line;
-       } else if (bootproto >= 0x0200) {
-               setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC;
-               setup_base->screen_info.cl_offset =
-                       (uintptr_t)cmd_line - (uintptr_t)setup_base;
+       if (cmd_line) {
+               if (bootproto >= 0x0202) {
+                       hdr->cmd_line_ptr = (uintptr_t)cmd_line;
+               } else if (bootproto >= 0x0200) {
+                       setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC;
+                       setup_base->screen_info.cl_offset =
+                               (uintptr_t)cmd_line - (uintptr_t)setup_base;
+
+                       hdr->setup_move_size = 0x9100;
+               }
 
-               hdr->setup_move_size = 0x9100;
+               /* build command line at COMMAND_LINE_OFFSET */
+               build_command_line(cmd_line, auto_boot);
        }
 
-       /* build command line at COMMAND_LINE_OFFSET */
-       build_command_line(cmd_line, auto_boot);
        return 0;
 }
 
-/*
- * Implement a weak default function for boards that optionally
- * need to clean up the system before jumping to the kernel.
- */
-__weak void board_final_cleanup(void)
-{
-}
-
 void boot_zimage(void *setup_base, void *load_address)
 {
-       debug("## Transferring control to Linux (at address %08x) ...\n",
-             (u32)setup_base);
-
-       bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
-#ifdef CONFIG_BOOTSTAGE_REPORT
-       bootstage_report();
-#endif
-       board_final_cleanup();
-
-       printf("\nStarting kernel ...\n\n");
+       bootm_announce_and_cleanup();
 
 #ifdef CONFIG_SYS_COREBOOT
        timestamp_add_now(TS_U_BOOT_START_KERNEL);
@@ -295,7 +282,6 @@ void boot_zimage(void *setup_base, void *load_address)
        :: [kernel_entry]"a"(load_address),
           [boot_params] "S"(setup_base),
           "b"(0), "D"(0)
-       :  "%ebp"
        );
 }
 
index 4c3a9ba785a3219a55c6800072691c2630fd8f23..263bb5426c0d1a7086b9ed28ea7085e7ee0a96ed 100644 (file)
@@ -13,7 +13,7 @@
 #include <command.h>
 #include <i2c.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include <asm/arch/gpio.h>
 
@@ -26,8 +26,8 @@ DECLARE_GLOBAL_DATA_PTR;
 int board_early_init_f(void)
 {
        /* GPIO configuration */
-       kw_config_gpio(NET2BIG_V2_OE_VAL_LOW, NET2BIG_V2_OE_VAL_HIGH,
-                       NET2BIG_V2_OE_LOW, NET2BIG_V2_OE_HIGH);
+       mvebu_config_gpio(NET2BIG_V2_OE_VAL_LOW, NET2BIG_V2_OE_VAL_HIGH,
+                         NET2BIG_V2_OE_LOW, NET2BIG_V2_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -77,7 +77,7 @@ int board_init(void)
        gd->bd->bi_arch_number = MACH_TYPE_NET2BIG_V2;
 
        /* Boot parameters address */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index 3773587cc6d1ea9ffb553009b8ff2de0354568ec..17e629622ff733487303611f58730835e1317246 100644 (file)
@@ -12,7 +12,7 @@
 #include <common.h>
 #include <command.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include <asm/arch/gpio.h>
 
@@ -24,8 +24,8 @@ DECLARE_GLOBAL_DATA_PTR;
 int board_early_init_f(void)
 {
        /* Gpio configuration */
-       kw_config_gpio(NETSPACE_V2_OE_VAL_LOW, NETSPACE_V2_OE_VAL_HIGH,
-                       NETSPACE_V2_OE_LOW, NETSPACE_V2_OE_HIGH);
+       mvebu_config_gpio(NETSPACE_V2_OE_VAL_LOW, NETSPACE_V2_OE_VAL_HIGH,
+                         NETSPACE_V2_OE_LOW, NETSPACE_V2_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -73,7 +73,7 @@ int board_init(void)
        gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
 
        /* Boot parameters address */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index 2dc50185604248475eed34d766bf40396973bd9d..8620e4b5d135fa1022043a4cf53f40b2491dde20 100644 (file)
@@ -12,7 +12,7 @@
 #include <common.h>
 #include <command.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include <asm/arch/gpio.h>
 
@@ -97,8 +97,8 @@ struct mv88e61xx_config swcfg = {
 int board_early_init_f(void)
 {
        /* Gpio configuration */
-       kw_config_gpio(WIRELESS_SPACE_OE_VAL_LOW, WIRELESS_SPACE_OE_VAL_HIGH,
-                       WIRELESS_SPACE_OE_LOW, WIRELESS_SPACE_OE_HIGH);
+       mvebu_config_gpio(WIRELESS_SPACE_OE_VAL_LOW, WIRELESS_SPACE_OE_VAL_HIGH,
+                         WIRELESS_SPACE_OE_LOW, WIRELESS_SPACE_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        kirkwood_mpp_conf(kwmpp_config, NULL);
@@ -112,7 +112,7 @@ int board_init(void)
        gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
 
        /* Boot parameters address */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
diff --git a/board/Marvell/db-mv784mp-gp/Kconfig b/board/Marvell/db-mv784mp-gp/Kconfig
new file mode 100644 (file)
index 0000000..f94a444
--- /dev/null
@@ -0,0 +1,23 @@
+if TARGET_DB_MV784MP_GP
+
+config SYS_CPU
+       string
+       default "armv7"
+
+config SYS_BOARD
+       string
+       default "db-mv784mp-gp"
+
+config SYS_VENDOR
+       string
+       default "Marvell"
+
+config SYS_SOC
+       string
+       default "armada-xp"
+
+config SYS_CONFIG_NAME
+       string
+       default "db-mv784mp-gp"
+
+endif
diff --git a/board/Marvell/db-mv784mp-gp/MAINTAINERS b/board/Marvell/db-mv784mp-gp/MAINTAINERS
new file mode 100644 (file)
index 0000000..a095f89
--- /dev/null
@@ -0,0 +1,6 @@
+DB_MV784MP_GP BOARD
+M:     Stefan Roese <sr@denx.de>
+S:     Maintained
+F:     board/Marvell/db-mv784mp-gp/
+F:     include/configs/db-mv784mp-gp.h
+F:     configs/db-mv784mp-gp_defconfig
diff --git a/board/Marvell/db-mv784mp-gp/Makefile b/board/Marvell/db-mv784mp-gp/Makefile
new file mode 100644 (file)
index 0000000..8f5a7fb
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  := db-mv784mp-gp.o
diff --git a/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c b/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c
new file mode 100644 (file)
index 0000000..b3dae89
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <miiphy.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BIT(nr)                                (1UL << (nr))
+
+#define ETH_PHY_CTRL_REG               0
+#define ETH_PHY_CTRL_POWER_DOWN_BIT    11
+#define ETH_PHY_CTRL_POWER_DOWN_MASK   (1 << ETH_PHY_CTRL_POWER_DOWN_BIT)
+
+/*
+ * Those values and defines are taken from the Marvell U-Boot version
+ * "u-boot-2011.12-2014_T1.0" for the board rd78460gp aka
+ * "RD-AXP-GP rev 1.0".
+ *
+ * GPPs
+ * MPP#                NAME                    IN/OUT
+ * ----------------------------------------------
+ * 21          SW_Reset_               OUT
+ * 25          Phy_Int#                IN
+ * 28          SDI_WP                  IN
+ * 29          SDI_Status              IN
+ * 54-61       On GPP Connector        ?
+ * 62          Switch Interrupt        IN
+ * 63-65       Reserved from SW Board  ?
+ * 66          SW_BRD connected        IN
+ */
+#define RD_78460_GP_GPP_OUT_ENA_LOW    (~(BIT(21) | BIT(20)))
+#define RD_78460_GP_GPP_OUT_ENA_MID    (~(BIT(26) | BIT(27)))
+#define RD_78460_GP_GPP_OUT_ENA_HIGH   (~(0x0))
+
+#define RD_78460_GP_GPP_OUT_VAL_LOW    (BIT(21) | BIT(20))
+#define RD_78460_GP_GPP_OUT_VAL_MID    (BIT(26) | BIT(27))
+#define RD_78460_GP_GPP_OUT_VAL_HIGH   0x0
+
+int board_early_init_f(void)
+{
+       /* Configure MPP */
+       writel(0x00000000, MVEBU_MPP_BASE + 0x00);
+       writel(0x00000000, MVEBU_MPP_BASE + 0x04);
+       writel(0x33000000, MVEBU_MPP_BASE + 0x08);
+       writel(0x11000000, MVEBU_MPP_BASE + 0x0c);
+       writel(0x11111111, MVEBU_MPP_BASE + 0x10);
+       writel(0x00221100, MVEBU_MPP_BASE + 0x14);
+       writel(0x00000003, MVEBU_MPP_BASE + 0x18);
+       writel(0x00000000, MVEBU_MPP_BASE + 0x1c);
+       writel(0x00000000, MVEBU_MPP_BASE + 0x20);
+
+       /* Configure GPIO */
+       writel(RD_78460_GP_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+       writel(RD_78460_GP_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+       writel(RD_78460_GP_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
+       writel(RD_78460_GP_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
+       writel(RD_78460_GP_GPP_OUT_VAL_HIGH, MVEBU_GPIO2_BASE + 0x00);
+       writel(RD_78460_GP_GPP_OUT_ENA_HIGH, MVEBU_GPIO2_BASE + 0x04);
+
+       return 0;
+}
+
+int board_init(void)
+{
+       /* adress of boot parameters */
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+       return 0;
+}
+
+int checkboard(void)
+{
+       puts("Board: Marvell DB-MV784MP-GP\n");
+
+       return 0;
+}
+
+#ifdef CONFIG_RESET_PHY_R
+/* Configure and enable MV88E1545 PHY */
+void reset_phy(void)
+{
+       u16 devadr = CONFIG_PHY_BASE_ADDR;
+       char *name = "neta0";
+       u16 reg;
+
+       if (miiphy_set_current_dev(name))
+               return;
+
+       /* Enable QSGMII AN */
+       /* Set page to 4 */
+       miiphy_write(name, devadr, 0x16, 4);
+       /* Enable AN */
+       miiphy_write(name, devadr, 0x0, 0x1140);
+       /* Set page to 0 */
+       miiphy_write(name, devadr, 0x16, 0);
+
+       /* Phy C_ANEG */
+       miiphy_read(name, devadr, 0x4, &reg);
+       reg |= 0x1E0;
+       miiphy_write(name, devadr, 0x4, reg);
+
+       /* Soft-Reset */
+       miiphy_write(name, devadr, 22, 0x0000);
+       miiphy_write(name, devadr, 0, 0x9140);
+
+       /* Power up the phy */
+       miiphy_read(name, devadr, ETH_PHY_CTRL_REG, &reg);
+       reg &= ~(ETH_PHY_CTRL_POWER_DOWN_MASK);
+       miiphy_write(name, devadr, ETH_PHY_CTRL_REG, reg);
+
+       printf("88E1545 Initialized on %s\n", name);
+}
+#endif /* CONFIG_RESET_PHY_R */
diff --git a/board/Marvell/db-mv784mp-gp/kwbimage.cfg b/board/Marvell/db-mv784mp-gp/kwbimage.cfg
new file mode 100644 (file)
index 0000000..d7ef407
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+
+# Armada XP uses version 1 image format
+VERSION                1
+
+# Boot Media configurations
+BOOT_FROM      spi
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY board/Marvell/db-mv784mp-gp/binary.0 0000005b 00000068
index b53c81080d10985faeb02992fa62f9f35864d64f..0887d92c2995469cb115c0ef719846b7e2eb7e24 100644 (file)
@@ -12,7 +12,7 @@
 #include <common.h>
 #include <miiphy.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "dreamplug.h"
 
@@ -25,9 +25,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(DREAMPLUG_OE_VAL_LOW,
-                       DREAMPLUG_OE_VAL_HIGH,
-                       DREAMPLUG_OE_LOW, DREAMPLUG_OE_HIGH);
+       mvebu_config_gpio(DREAMPLUG_OE_VAL_LOW,
+                         DREAMPLUG_OE_VAL_HIGH,
+                         DREAMPLUG_OE_LOW, DREAMPLUG_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -90,7 +90,7 @@ int board_early_init_f(void)
 int board_init(void)
 {
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index 72bccc821ce2cc2b7d9fe21e83382f0546a9663e..b0d5f1e10f4ddf46a4f21371a3f5edaaa22af10f 100644 (file)
@@ -9,7 +9,7 @@
 #include <common.h>
 #include <miiphy.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "guruplug.h"
 
@@ -22,9 +22,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(GURUPLUG_OE_VAL_LOW,
-                       GURUPLUG_OE_VAL_HIGH,
-                       GURUPLUG_OE_LOW, GURUPLUG_OE_HIGH);
+       mvebu_config_gpio(GURUPLUG_OE_VAL_LOW,
+                         GURUPLUG_OE_VAL_HIGH,
+                         GURUPLUG_OE_LOW, GURUPLUG_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -92,7 +92,7 @@ int board_init(void)
        gd->bd->bi_arch_number = MACH_TYPE_GURUPLUG;
 
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index e1652c08317405ac922f087ec1e2f29b153d6da9..ef08ad8928d04dad71afbebfabd9f80f7943052d 100644 (file)
@@ -11,7 +11,7 @@
 #include <common.h>
 #include <netdev.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "mv88f6281gtw_ge.h"
 
@@ -24,9 +24,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(MV88F6281GTW_GE_OE_VAL_LOW,
-                       MV88F6281GTW_GE_OE_VAL_HIGH,
-                       MV88F6281GTW_GE_OE_LOW, MV88F6281GTW_GE_OE_HIGH);
+       mvebu_config_gpio(MV88F6281GTW_GE_OE_VAL_LOW,
+                         MV88F6281GTW_GE_OE_VAL_HIGH,
+                         MV88F6281GTW_GE_OE_LOW, MV88F6281GTW_GE_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -94,7 +94,7 @@ int board_init(void)
        gd->bd->bi_arch_number = MACH_TYPE_MV88F6281GTW_GE;
 
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index a005a2f79dd07618e89267bc32906f9a946e6e11..55cf525cf8aa18e7aed9542c2761ddc30d41a959 100644 (file)
@@ -14,7 +14,7 @@
 #include <common.h>
 #include <miiphy.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "openrd.h"
 
@@ -27,9 +27,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(OPENRD_OE_VAL_LOW,
-                       OPENRD_OE_VAL_HIGH,
-                       OPENRD_OE_LOW, OPENRD_OE_HIGH);
+       mvebu_config_gpio(OPENRD_OE_VAL_LOW,
+                         OPENRD_OE_VAL_HIGH,
+                         OPENRD_OE_LOW, OPENRD_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -104,7 +104,7 @@ int board_init(void)
 #endif
 
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
        return 0;
 }
 
index 33ef0c78e5bba9d18ecb15b57f1a1db567506c42..b0020c95a5bb067ebe2291eb4714981751603edf 100644 (file)
@@ -10,7 +10,7 @@
 #include <miiphy.h>
 #include <netdev.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "rd6281a.h"
 
@@ -23,9 +23,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(RD6281A_OE_VAL_LOW,
-                       RD6281A_OE_VAL_HIGH,
-                       RD6281A_OE_LOW, RD6281A_OE_HIGH);
+       mvebu_config_gpio(RD6281A_OE_VAL_LOW,
+                         RD6281A_OE_VAL_HIGH,
+                         RD6281A_OE_LOW, RD6281A_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -93,7 +93,7 @@ int board_init(void)
        gd->bd->bi_arch_number = MACH_TYPE_RD88F6281;
 
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index 87e49f417bb7138199fd77d3252c46a200206236..8907fb58ff80f90f48c14545e7bbb04c93ae705f 100644 (file)
@@ -9,7 +9,7 @@
 #include <common.h>
 #include <miiphy.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "sheevaplug.h"
 
@@ -22,9 +22,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(SHEEVAPLUG_OE_VAL_LOW,
-                       SHEEVAPLUG_OE_VAL_HIGH,
-                       SHEEVAPLUG_OE_LOW, SHEEVAPLUG_OE_HIGH);
+       mvebu_config_gpio(SHEEVAPLUG_OE_VAL_LOW,
+                         SHEEVAPLUG_OE_VAL_HIGH,
+                         SHEEVAPLUG_OE_LOW, SHEEVAPLUG_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -92,7 +92,7 @@ int board_init(void)
        gd->bd->bi_arch_number = MACH_TYPE_SHEEVAPLUG;
 
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index ff6a6a09ed7794f3d398f101cdb369a010da75d3..83ab1bc32d307dc16b3e5017dcb169d31b32b8d2 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <common.h>
 #include <miiphy.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include <asm/arch/cpu.h>
 #include <asm/io.h>
@@ -26,9 +26,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(DOCKSTAR_OE_VAL_LOW,
-                       DOCKSTAR_OE_VAL_HIGH,
-                       DOCKSTAR_OE_LOW, DOCKSTAR_OE_HIGH);
+       mvebu_config_gpio(DOCKSTAR_OE_VAL_LOW,
+                         DOCKSTAR_OE_VAL_HIGH,
+                         DOCKSTAR_OE_LOW, DOCKSTAR_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -96,7 +96,7 @@ int board_init(void)
        gd->bd->bi_arch_number = MACH_TYPE_DOCKSTAR;
 
        /* address of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
@@ -143,7 +143,7 @@ void reset_phy(void)
 
 static void set_leds(u32 leds, u32 blinking)
 {
-       struct kwgpio_registers *r = (struct kwgpio_registers *)KW_GPIO1_BASE;
+       struct kwgpio_registers *r = (struct kwgpio_registers *)MVEBU_GPIO1_BASE;
        u32 oe = readl(&r->oe) | BOTH_LEDS;
        writel(oe & ~leds, &r->oe);     /* active low */
        u32 bl = readl(&r->blink_en) & ~BOTH_LEDS;
index a6598e9c81e607d29a2a568d7738ec07574f1f1d..1f4fb924942a4c65a9833fd660eb6847853b90a7 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <common.h>
 #include <miiphy.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include <asm/arch/cpu.h>
 #include <asm/io.h>
@@ -83,9 +83,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(GOFLEXHOME_OE_VAL_LOW,
-                      GOFLEXHOME_OE_VAL_HIGH,
-                      GOFLEXHOME_OE_LOW, GOFLEXHOME_OE_HIGH);
+       mvebu_config_gpio(GOFLEXHOME_OE_VAL_LOW,
+                         GOFLEXHOME_OE_VAL_HIGH,
+                         GOFLEXHOME_OE_LOW, GOFLEXHOME_OE_HIGH);
        kirkwood_mpp_conf(kwmpp_config, NULL);
        return 0;
 }
@@ -98,7 +98,7 @@ int board_init(void)
        gd->bd->bi_arch_number = MACH_TYPE_GOFLEXHOME;
 
        /* address of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
@@ -149,7 +149,7 @@ static void set_leds(u32 leds, u32 blinking)
        u32 oe;
        u32 bl;
 
-       r = (struct kwgpio_registers *)KW_GPIO1_BASE;
+       r = (struct kwgpio_registers *)MVEBU_GPIO1_BASE;
        oe = readl(&r->oe) | BOTH_LEDS;
        writel(oe & ~leds, &r->oe);     /* active low */
        bl = readl(&r->blink_en) & ~BOTH_LEDS;
index 2298e3619c4ee0d4e2ff9b9aebc4ed7f785ecac5..6761b141fb82fd42a51f5e47896d1b9bfaed1b7d 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/arch/hardware.h>
 #include <asm/arch/at91_pmc.h>
 #include <asm/arch/at91_pio.h>
+#include <status_led.h>
 
 /* bit mask in PIO port B */
 #define        GREEN_LED       (1<<0)
index 56d811ca42566e8e3409c461c6dffd7ed3a568bb..fbe15afd281b34d59317d3c40d40f35299253df7 100644 (file)
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/gpio.h>
+#include <status_led.h>
 
 void coloured_LED_init(void)
 {
index 659a124b22750fda1fb4b02df5d74defaf4012e6..b0d49c4ee6b8ac266588d63c81b8ef3094097346 100644 (file)
 #include <malloc.h>
 #include <netdev.h>
 #include <miiphy.h>
-#include <asm/arch/kirkwood.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/mpp.h>
 #include <asm/arch/gpio.h>
-#include <spi_flash.h>
 
 #include "lsxl.h"
 
@@ -51,9 +52,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the below configuration configures mainly initial LED status
         */
-       kw_config_gpio(LSXL_OE_VAL_LOW,
-                       LSXL_OE_VAL_HIGH,
-                       LSXL_OE_LOW, LSXL_OE_HIGH);
+       mvebu_config_gpio(LSXL_OE_VAL_LOW,
+                         LSXL_OE_VAL_HIGH,
+                         LSXL_OE_LOW, LSXL_OE_HIGH);
 
        /*
         * Multi-Purpose Pins Functionality configuration
@@ -167,7 +168,7 @@ static void set_led(int state)
 int board_init(void)
 {
        /* address of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        set_led(LED_POWER_BLINKING);
 
index 4f2ac898ebcf3c52ebcb78aef0345612a5d94e0d..27ebe78eb139184cf3687832d13d467ece6ddb20 100644 (file)
@@ -12,4 +12,4 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-y  += coreboot_start.o
+obj-y  += coreboot_start.o coreboot.o
diff --git a/board/chromebook-x86/coreboot/coreboot.c b/board/chromebook-x86/coreboot/coreboot.c
new file mode 100644 (file)
index 0000000..0240c34
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <cros_ec.h>
+
+int arch_early_init_r(void)
+{
+       if (cros_ec_board_init())
+               return -1;
+
+       return 0;
+}
index 0e632582d3dcae7c5a0d36e13fc7cfa15fe5079b..8309d06882e39db567488107608745fd8d694ff7 100644 (file)
@@ -13,7 +13,7 @@
 #include <common.h>
 #include <miiphy.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "pogo_e02.h"
 
@@ -26,9 +26,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(POGO_E02_OE_VAL_LOW,
-                       POGO_E02_OE_VAL_HIGH,
-                       POGO_E02_OE_LOW, POGO_E02_OE_HIGH);
+       mvebu_config_gpio(POGO_E02_OE_VAL_LOW,
+                         POGO_E02_OE_VAL_HIGH,
+                         POGO_E02_OE_LOW, POGO_E02_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -64,7 +64,7 @@ int board_early_init_f(void)
 int board_init(void)
 {
        /* Boot parameters address */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index fdb8ebf9e75567c41965d4018b306f2266ffc5e8..82681b10eb8cef4d92f80a751ad99a2360271a37 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fsl_esdhc.h>
 #include <miiphy.h>
 #include <netdev.h>
@@ -21,6 +22,7 @@
 #include <asm/imx-common/sata.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
+#include <dm/platform_data/serial_mxc.h>
 #include "common.h"
 #include "../common/eeprom.h"
 
@@ -69,16 +71,23 @@ static iomux_v3_cfg_t const sata_pads[] = {
        IOMUX_PADS(PAD_EIM_BCLK__GPIO6_IO31   | MUX_PAD_CTRL(NO_PAD_CTRL)),
 };
 
-static void cm_fx6_setup_issd(void)
+static int cm_fx6_setup_issd(void)
 {
+       int ret, i;
+
        SETUP_IOMUX_PADS(sata_pads);
-       /* Make sure this gpio has logical 0 value */
-       gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0);
-       udelay(100);
 
-       cm_fx6_sata_power(0);
-       mdelay(250);
-       cm_fx6_sata_power(1);
+       for (i = 0; i < ARRAY_SIZE(cm_fx6_issd_gpios); i++) {
+               ret = gpio_request(cm_fx6_issd_gpios[i], "sata");
+               if (ret)
+                       return ret;
+       }
+
+       ret = gpio_request(CM_FX6_SATA_PWLOSS_INT, "sata_pwloss_int");
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
 #define CM_FX6_SATA_INIT_RETRIES       10
@@ -86,7 +95,14 @@ int sata_initialize(void)
 {
        int err, i;
 
-       cm_fx6_setup_issd();
+       /* Make sure this gpio has logical 0 value */
+       gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0);
+       udelay(100);
+
+       cm_fx6_sata_power(0);
+       mdelay(250);
+       cm_fx6_sata_power(1);
+
        for (i = 0; i < CM_FX6_SATA_INIT_RETRIES; i++) {
                err = setup_sata();
                if (err) {
@@ -109,6 +125,8 @@ int sata_initialize(void)
 
        return err;
 }
+#else
+static int cm_fx6_setup_issd(void) { return 0; }
 #endif
 
 #ifdef CONFIG_SYS_I2C_MXC
@@ -141,49 +159,68 @@ I2C_PADS(i2c2_pads,
         IMX_GPIO_NR(1, 6));
 
 
-static void cm_fx6_setup_i2c(void)
+static int cm_fx6_setup_one_i2c(int busnum, struct i2c_pads_info *pads)
+{
+       int ret;
+
+       ret = setup_i2c(busnum, CONFIG_SYS_I2C_SPEED, 0x7f, pads);
+       if (ret)
+               printf("Warning: I2C%d setup failed: %d\n", busnum, ret);
+
+       return ret;
+}
+
+static int cm_fx6_setup_i2c(void)
 {
-       setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c0_pads));
-       setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c1_pads));
-       setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, I2C_PADS_INFO(i2c2_pads));
+       int ret = 0, err;
+
+       /* i2c<x>_pads are wierd macro variables; we can't use an array */
+       err = cm_fx6_setup_one_i2c(0, I2C_PADS_INFO(i2c0_pads));
+       if (err)
+               ret = err;
+       err = cm_fx6_setup_one_i2c(1, I2C_PADS_INFO(i2c1_pads));
+       if (err)
+               ret = err;
+       err = cm_fx6_setup_one_i2c(2, I2C_PADS_INFO(i2c2_pads));
+       if (err)
+               ret = err;
+
+       return ret;
 }
 #else
-static void cm_fx6_setup_i2c(void) { }
+static int cm_fx6_setup_i2c(void) { return 0; }
 #endif
 
 #ifdef CONFIG_USB_EHCI_MX6
 #define WEAK_PULLDOWN  (PAD_CTL_PUS_100K_DOWN |                \
                        PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
                        PAD_CTL_HYS | PAD_CTL_SRE_SLOW)
+#define MX6_USBNC_BASEADDR     0x2184800
+#define USBNC_USB_H1_PWR_POL   (1 << 9)
 
-static int cm_fx6_usb_hub_reset(void)
+static int cm_fx6_setup_usb_host(void)
 {
        int err;
 
        err = gpio_request(CM_FX6_USB_HUB_RST, "usb hub rst");
-       if (err) {
-               printf("USB hub rst gpio request failed: %d\n", err);
-               return -1;
-       }
+       if (err)
+               return err;
 
+       SETUP_IOMUX_PAD(PAD_GPIO_0__USB_H1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL));
        SETUP_IOMUX_PAD(PAD_SD3_RST__GPIO7_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL));
-       gpio_direction_output(CM_FX6_USB_HUB_RST, 0);
-       udelay(10);
-       gpio_direction_output(CM_FX6_USB_HUB_RST, 1);
-       mdelay(1);
 
        return 0;
 }
 
-static int cm_fx6_init_usb_otg(void)
+static int cm_fx6_setup_usb_otg(void)
 {
-       int ret;
+       int err;
        struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
 
-       ret = gpio_request(SB_FX6_USB_OTG_PWR, "usb-pwr");
-       if (ret) {
-               printf("USB OTG pwr gpio request failed: %d\n", ret);
-               return ret;
+       err = gpio_request(SB_FX6_USB_OTG_PWR, "usb-pwr");
+       if (err) {
+               printf("USB OTG pwr gpio request failed: %d\n", err);
+               return err;
        }
 
        SETUP_IOMUX_PAD(PAD_EIM_D22__GPIO3_IO22 | MUX_PAD_CTRL(NO_PAD_CTRL));
@@ -194,25 +231,27 @@ static int cm_fx6_init_usb_otg(void)
        return gpio_direction_output(SB_FX6_USB_OTG_PWR, 0);
 }
 
-#define MX6_USBNC_BASEADDR     0x2184800
-#define USBNC_USB_H1_PWR_POL   (1 << 9)
 int board_ehci_hcd_init(int port)
 {
+       int ret;
        u32 *usbnc_usb_uh1_ctrl = (u32 *)(MX6_USBNC_BASEADDR + 4);
 
-       switch (port) {
-       case 0:
-               return cm_fx6_init_usb_otg();
-       case 1:
-               SETUP_IOMUX_PAD(PAD_GPIO_0__USB_H1_PWR |
-                               MUX_PAD_CTRL(NO_PAD_CTRL));
+       /* Only 1 host controller in use. port 0 is OTG & needs no attention */
+       if (port != 1)
+               return 0;
 
-               /* Set PWR polarity to match power switch's enable polarity */
-               setbits_le32(usbnc_usb_uh1_ctrl, USBNC_USB_H1_PWR_POL);
-               return cm_fx6_usb_hub_reset();
-       default:
-               break;
-       }
+       /* Set PWR polarity to match power switch's enable polarity */
+       setbits_le32(usbnc_usb_uh1_ctrl, USBNC_USB_H1_PWR_POL);
+       ret = gpio_direction_output(CM_FX6_USB_HUB_RST, 0);
+       if (ret)
+               return ret;
+
+       udelay(10);
+       ret = gpio_direction_output(CM_FX6_USB_HUB_RST, 1);
+       if (ret)
+               return ret;
+
+       mdelay(1);
 
        return 0;
 }
@@ -224,6 +263,9 @@ int board_ehci_power(int port, int on)
 
        return 0;
 }
+#else
+static int cm_fx6_setup_usb_otg(void) { return 0; }
+static int cm_fx6_setup_usb_host(void) { return 0; }
 #endif
 
 #ifdef CONFIG_FEC_MXC
@@ -318,12 +360,17 @@ static int handle_mac_address(void)
 
 int board_eth_init(bd_t *bis)
 {
-       int res = handle_mac_address();
-       if (res)
+       int err;
+
+       err = handle_mac_address();
+       if (err)
                puts("No MAC address found\n");
 
        SETUP_IOMUX_PADS(enet_pads);
        /* phy reset */
+       err = gpio_request(CM_FX6_ENET_NRST, "enet_nrst");
+       if (err)
+               printf("Etnernet NRST gpio request failed: %d\n", err);
        gpio_direction_output(CM_FX6_ENET_NRST, 0);
        udelay(500);
        gpio_set_value(CM_FX6_ENET_NRST, 1);
@@ -394,6 +441,16 @@ int board_mmc_init(bd_t *bis)
 }
 #endif
 
+#ifdef CONFIG_MXC_SPI
+int cm_fx6_setup_ecspi(void)
+{
+       cm_fx6_set_ecspi_iomux();
+       return gpio_request(CM_FX6_ECSPI_BUS0_CS0, "ecspi_bus0_cs0");
+}
+#else
+int cm_fx6_setup_ecspi(void) { return 0; }
+#endif
+
 #ifdef CONFIG_OF_BOARD_SETUP
 void ft_board_setup(void *blob, bd_t *bd)
 {
@@ -409,9 +466,37 @@ void ft_board_setup(void *blob, bd_t *bd)
 
 int board_init(void)
 {
+       int ret;
+
        gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
        cm_fx6_setup_gpmi_nand();
-       cm_fx6_setup_i2c();
+
+       ret = cm_fx6_setup_ecspi();
+       if (ret)
+               printf("Warning: ECSPI setup failed: %d\n", ret);
+
+       ret = cm_fx6_setup_usb_otg();
+       if (ret)
+               printf("Warning: USB OTG setup failed: %d\n", ret);
+
+       ret = cm_fx6_setup_usb_host();
+       if (ret)
+               printf("Warning: USB host setup failed: %d\n", ret);
+
+       /*
+        * cm-fx6 may have iSSD not assembled and in this case it has
+        * bypasses for a (m)SATA socket on the baseboard. The socketed
+        * device is not controlled by those GPIOs. So just print a warning
+        * if the setup fails.
+        */
+       ret = cm_fx6_setup_issd();
+       if (ret)
+               printf("Warning: iSSD setup failed: %d\n", ret);
+
+       /* Warn on failure but do not abort boot */
+       ret = cm_fx6_setup_i2c();
+       if (ret)
+               printf("Warning: I2C setup failed: %d\n", ret);
 
        return 0;
 }
@@ -481,3 +566,11 @@ u32 get_board_rev(void)
        return cl_eeprom_get_board_rev();
 }
 
+static struct mxc_serial_platdata cm_fx6_mxc_serial_plat = {
+       .reg = (struct mxc_uart *)UART4_BASE,
+};
+
+U_BOOT_DEVICE(cm_fx6_serial) = {
+       .name   = "serial_mxc",
+       .platdata = &cm_fx6_mxc_serial_plat,
+};
index ff70e9415f0900b466c34ec7d76239334f91b3d8..a022daf71e419bc87b707aeaf35ea7813d6e13fe 100644 (file)
@@ -14,7 +14,7 @@
 #include <miiphy.h>
 #include <netdev.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include <asm/arch/gpio.h>
 #include "dns325.h"
@@ -24,8 +24,8 @@ DECLARE_GLOBAL_DATA_PTR;
 int board_early_init_f(void)
 {
        /* Gpio configuration */
-       kw_config_gpio(DNS325_OE_VAL_LOW, DNS325_OE_VAL_HIGH,
-                       DNS325_OE_LOW, DNS325_OE_HIGH);
+       mvebu_config_gpio(DNS325_OE_VAL_LOW, DNS325_OE_VAL_HIGH,
+                         DNS325_OE_LOW, DNS325_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -92,7 +92,7 @@ int board_early_init_f(void)
 int board_init(void)
 {
        /* Boot parameters address */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index c3443bdc88334f027907010ee63b59da2c97ab48..086a473e8875c98865d9d3dc64d970e93467444b 100644 (file)
@@ -9,7 +9,7 @@
 #include <common.h>
 #include <miiphy.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "iconnect.h"
 
@@ -22,9 +22,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the below configuration configures mainly initial LED status
         */
-       kw_config_gpio(ICONNECT_OE_VAL_LOW,
-                       ICONNECT_OE_VAL_HIGH,
-                       ICONNECT_OE_LOW, ICONNECT_OE_HIGH);
+       mvebu_config_gpio(ICONNECT_OE_VAL_LOW,
+                         ICONNECT_OE_VAL_HIGH,
+                         ICONNECT_OE_LOW, ICONNECT_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -87,7 +87,7 @@ int board_early_init_f(void)
 int board_init(void)
 {
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index 3b2b1f15b8e9647fe0fc72efee1e8f78fa11b588..7b87cc27c41b4e517753342202f240e7ff5668b4 100644 (file)
@@ -5,6 +5,8 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
+#include <ns16550.h>
 #include <twl4030.h>
 #include <netdev.h>
 #include <asm/gpio.h>
@@ -30,6 +32,17 @@ static const u32 gpmc_lan_config[] = {
 };
 #endif
 
+static const struct ns16550_platdata igep_serial = {
+       OMAP34XX_UART3,
+       2,
+       V_NS16550_CLK
+};
+
+U_BOOT_DEVICE(igep_uart) = {
+       "serial_omap",
+       &igep_serial
+};
+
 /*
  * Routine: board_init
  * Description: Early hardware init.
index ed0575cb05a26a6c4a77c6635bdc88ba04f91f9d..35546d24e87560454d3a4a047b76899cd1318413 100644 (file)
@@ -8,7 +8,7 @@
 #include <common.h>
 #include <miiphy.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include <asm/io.h>
 
@@ -26,9 +26,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the  below configuration configures mainly initial LED status
         */
-       kw_config_gpio(TK71_OE_VAL_LOW,
-                       TK71_OE_VAL_HIGH,
-                       TK71_OE_LOW, TK71_OE_HIGH);
+       mvebu_config_gpio(TK71_OE_VAL_LOW,
+                         TK71_OE_VAL_HIGH,
+                         TK71_OE_LOW, TK71_OE_HIGH);
 
        /* Multi-Purpose Pins Functionality configuration */
        static const u32 kwmpp_config[] = {
@@ -97,7 +97,7 @@ int board_init(void)
        gd->bd->bi_arch_number = CONFIG_MACH_TYPE;
 
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index 35402c800bd31df15c7162e03a7c327c50878bb7..1c7c108cb5acd7536e0081a7d2a7f40a7eb23a74 100644 (file)
@@ -20,7 +20,7 @@
 #include <spi.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 
 #include "../common/common.h"
@@ -222,11 +222,11 @@ int board_early_init_f(void)
        u32 tmp;
 
        /* set the 2 bitbang i2c pins as output gpios */
-       tmp = readl(KW_GPIO0_BASE + 4);
-       writel(tmp & (~KM_KIRKWOOD_SOFT_I2C_GPIOS) , KW_GPIO0_BASE + 4);
+       tmp = readl(MVEBU_GPIO0_BASE + 4);
+       writel(tmp & (~KM_KIRKWOOD_SOFT_I2C_GPIOS) , MVEBU_GPIO0_BASE + 4);
 #endif
        /* adjust SDRAM size for bank 0 */
-       kw_sdram_size_adjust(0);
+       mvebu_sdram_size_adjust(0);
        kirkwood_mpp_conf(kwmpp_config, NULL);
        return 0;
 }
@@ -234,7 +234,7 @@ int board_early_init_f(void)
 int board_init(void)
 {
        /* address of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        /*
         * The KM_FLASH_GPIO_PIN switches between using a
index 461a852724eb6d7a76dd79d785599a26300a8fcb..9ef002637a665f7e405e5873bddee8f640da49af 100644 (file)
@@ -15,6 +15,8 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
+#include <ns16550.h>
 #include <netdev.h>
 #include <twl4030.h>
 #include <asm/io.h>
@@ -41,6 +43,17 @@ static const u32 gpmc_lab_enet[] = {
        /*CONF7- computed as params */
 };
 
+static const struct ns16550_platdata zoom1_serial = {
+       OMAP34XX_UART3,
+       2,
+       V_NS16550_CLK
+};
+
+U_BOOT_DEVICE(zoom1_uart) = {
+       "serial_omap",
+       &zoom1_serial
+};
+
 /*
  * Routine: board_init
  * Description: Early hardware init.
diff --git a/board/maxbcm/Kconfig b/board/maxbcm/Kconfig
new file mode 100644 (file)
index 0000000..d34e2ab
--- /dev/null
@@ -0,0 +1,19 @@
+if TARGET_MAXBCM
+
+config SYS_CPU
+       string
+       default "armv7"
+
+config SYS_BOARD
+       string
+       default "maxbcm"
+
+config SYS_SOC
+       string
+       default "armada-xp"
+
+config SYS_CONFIG_NAME
+       string
+       default "maxbcm"
+
+endif
diff --git a/board/maxbcm/MAINTAINERS b/board/maxbcm/MAINTAINERS
new file mode 100644 (file)
index 0000000..3c8af21
--- /dev/null
@@ -0,0 +1,6 @@
+MAXBCM BOARD
+M:     Stefan Roese <sr@denx.de>
+S:     Maintained
+F:     board/maxbcm/
+F:     include/configs/maxbcm.h
+F:     configs/maxbcm_defconfig
diff --git a/board/maxbcm/Makefile b/board/maxbcm/Makefile
new file mode 100644 (file)
index 0000000..37c17d6
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  := maxbcm.o
diff --git a/board/maxbcm/kwbimage.cfg b/board/maxbcm/kwbimage.cfg
new file mode 100644 (file)
index 0000000..5a3bc67
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+
+# Armada XP uses version 1 image format
+VERSION                1
+
+# Boot Media configurations
+BOOT_FROM      spi
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY board/maxbcm/binary.0 0000005b 00000068
diff --git a/board/maxbcm/maxbcm.c b/board/maxbcm/maxbcm.c
new file mode 100644 (file)
index 0000000..7fc83ee
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <miiphy.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <linux/mbus.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Base addresses for the external device chip selects */
+#define DEV_CS0_BASE           0xe0000000
+#define DEV_CS1_BASE           0xe1000000
+#define DEV_CS2_BASE           0xe2000000
+#define DEV_CS3_BASE           0xe3000000
+
+/* Needed for dynamic (board-specific) mbus configuration */
+extern struct mvebu_mbus_state mbus_state;
+
+int board_early_init_f(void)
+{
+       /*
+        * Don't configure MPP (pin multiplexing) and GPIO here,
+        * its already done in bin_hdr
+        */
+
+       /*
+        * Setup some board specific mbus address windows
+        */
+       mbus_dt_setup_win(&mbus_state, DEV_CS0_BASE, 16 << 20,
+                         CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS0);
+       mbus_dt_setup_win(&mbus_state, DEV_CS1_BASE, 16 << 20,
+                         CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS1);
+       mbus_dt_setup_win(&mbus_state, DEV_CS2_BASE, 16 << 20,
+                         CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS2);
+       mbus_dt_setup_win(&mbus_state, DEV_CS3_BASE, 16 << 20,
+                         CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS3);
+
+       return 0;
+}
+
+int board_init(void)
+{
+       /* adress of boot parameters */
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+       return 0;
+}
+
+int checkboard(void)
+{
+       puts("Board: maxBCM\n");
+
+       return 0;
+}
+
+#ifdef CONFIG_RESET_PHY_R
+/* Configure and enable MV88E6185 switch */
+void reset_phy(void)
+{
+       u16 devadr = CONFIG_PHY_BASE_ADDR;
+       char *name = "neta0";
+       u16 reg;
+
+       if (miiphy_set_current_dev(name))
+               return;
+
+       /* todo: fill this with the real setup / config code */
+
+       printf("88E6185 Initialized on %s\n", name);
+}
+#endif /* CONFIG_RESET_PHY_R */
index d01abcee13c14121dfd8db0eeea8f21440b36363..51125df34f018b79a511b44dc49e73a817944a43 100644 (file)
@@ -47,46 +47,19 @@ const struct tegra_sysinfo sysinfo = {
        CONFIG_TEGRA_BOARD_STRING
 };
 
-void __pinmux_init(void)
-{
-}
-
-void pinmux_init(void) __attribute__((weak, alias("__pinmux_init")));
-
-void __pin_mux_usb(void)
-{
-}
-
-void pin_mux_usb(void) __attribute__((weak, alias("__pin_mux_usb")));
-
-void __pin_mux_spi(void)
-{
-}
-
-void pin_mux_spi(void) __attribute__((weak, alias("__pin_mux_spi")));
-
-void __gpio_early_init_uart(void)
-{
-}
-
-void gpio_early_init_uart(void)
-__attribute__((weak, alias("__gpio_early_init_uart")));
+__weak void pinmux_init(void) {}
+__weak void pin_mux_usb(void) {}
+__weak void pin_mux_spi(void) {}
+__weak void gpio_early_init_uart(void) {}
+__weak void pin_mux_display(void) {}
 
 #if defined(CONFIG_TEGRA_NAND)
-void __pin_mux_nand(void)
+__weak void pin_mux_nand(void)
 {
        funcmux_select(PERIPH_ID_NDFLASH, FUNCMUX_DEFAULT);
 }
-
-void pin_mux_nand(void) __attribute__((weak, alias("__pin_mux_nand")));
 #endif
 
-void __pin_mux_display(void)
-{
-}
-
-void pin_mux_display(void) __attribute__((weak, alias("__pin_mux_display")));
-
 /*
  * Routine: power_det_init
  * Description: turn off power detects
@@ -114,9 +87,8 @@ int board_init(void)
        clock_init();
        clock_verify();
 
-#ifdef CONFIG_FDT_SPI
+#ifdef CONFIG_TEGRA_SPI
        pin_mux_spi();
-       spi_init();
 #endif
 
 #ifdef CONFIG_PWM_TEGRA
@@ -205,12 +177,10 @@ int board_late_init(void)
 }
 
 #if defined(CONFIG_TEGRA_MMC)
-void __pin_mux_mmc(void)
+__weak void pin_mux_mmc(void)
 {
 }
 
-void pin_mux_mmc(void) __attribute__((weak, alias("__pin_mux_mmc")));
-
 /* this is a weak define that we are overriding */
 int board_mmc_init(bd_t *bd)
 {
index 8124f8aafde0671e48d0abe770cedcd6bf868c25..8c62f36a7b04a00b8d05f68405567f9d3e1fd687 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include "emc.h"
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/emc.h>
index d338818a64eb898697db9ac014fb392fea858674..de4eb355982cb2b1821849407f635caf65d3759b 100644 (file)
@@ -283,6 +283,11 @@ static const struct pmux_pingrp_config jetson_tk1_pingrps[] = {
        PINCFG(PCC2,                   DEFAULT,      DOWN,   NORMAL,   INPUT,   DEFAULT, DEFAULT),
        PINCFG(SDMMC4_CLK_PCC4,        SDMMC4,       NORMAL, NORMAL,   INPUT,   DEFAULT, DEFAULT),
        PINCFG(CLK2_REQ_PCC5,          DEFAULT,      NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PEX_L0_RST_N_PDD1,      PE0,          NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PEX_L0_CLKREQ_N_PDD2,   PE0,          UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PEX_WAKE_N_PDD3,        PE,           UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
+       PINCFG(PEX_L1_RST_N_PDD5,      PE1,          NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
+       PINCFG(PEX_L1_CLKREQ_N_PDD6,   PE1,          UP,     NORMAL,   INPUT,   DEFAULT, DEFAULT),
        PINCFG(CLK3_OUT_PEE0,          EXTPERIPH3,   NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
        PINCFG(CLK3_REQ_PEE1,          DEFAULT,      NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
        PINCFG(DAP_MCLK1_REQ_PEE2,     SATA,         NORMAL, NORMAL,   OUTPUT,  DEFAULT, DEFAULT),
index 6a243f0aea98cb42b5fd969b16ecd9a361f2aa54..11472ebaf20d1eb385457cf8745322460e7b94bc 100644 (file)
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/tegra.h>
+#include <asm/arch-tegra/board.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/funcmux.h>
 #include <asm/arch/gpio.h>
index 13220c56dd0634dc8a1cee9538fda0dafae2302c..7506820e349f4174679a9d58ee293831c4cc6da2 100644 (file)
@@ -13,6 +13,8 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
+#include <ns16550.h>
 #include <netdev.h>
 #include <twl4030.h>
 #include <linux/mtd/nand.h>
@@ -73,6 +75,17 @@ static const u32 gpmc_lan_config[] = {
     /*CONFIG7- computed as params */
 };
 
+static const struct ns16550_platdata overo_serial = {
+       OMAP34XX_UART3,
+       2,
+       V_NS16550_CLK
+};
+
+U_BOOT_DEVICE(overo_uart) = {
+       "serial_omap",
+       &overo_serial
+};
+
 /*
  * Routine: board_init
  * Description: Early hardware init.
index 976ba4ce94226c8f464944ca6c456a29d6c52269..f01fb1c6e7624bbe66d9714fc3fbfe0d98db0619 100644 (file)
@@ -11,7 +11,7 @@
 #include <miiphy.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/mpp.h>
 #include "ib62x0.h"
 
@@ -24,9 +24,9 @@ int board_early_init_f(void)
         * There are maximum 64 gpios controlled through 2 sets of registers
         * the below configuration configures mainly initial LED status
         */
-       kw_config_gpio(IB62x0_OE_VAL_LOW,
-                       IB62x0_OE_VAL_HIGH,
-                       IB62x0_OE_LOW, IB62x0_OE_HIGH);
+       mvebu_config_gpio(IB62x0_OE_VAL_LOW,
+                         IB62x0_OE_VAL_HIGH,
+                         IB62x0_OE_LOW, IB62x0_OE_HIGH);
 
        /* Set SATA activity LEDs to default off */
        writel(MVSATAHC_LED_POLARITY_CTRL, MVSATAHC_LED_CONF_REG);
@@ -62,7 +62,7 @@ int board_early_init_f(void)
 int board_init(void)
 {
        /* adress of boot parameters */
-       gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;
+       gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
        return 0;
 }
index a92c1ec10f5b50201f3f80176378ae9da1b12dd0..7445f5318ad2ed44525ea8bf8a11cc5ae95cbc42 100644 (file)
 
 #include <common.h>
 #include <config.h>
+#include <dm.h>
 #include <fdt_support.h>
 #include <lcd.h>
 #include <mmc.h>
+#include <asm/gpio.h>
 #include <asm/arch/mbox.h>
 #include <asm/arch/sdhci.h>
 #include <asm/global_data.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static const struct bcm2835_gpio_platdata gpio_platdata = {
+       .base = BCM2835_GPIO_BASE,
+};
+
+U_BOOT_DEVICE(bcm2835_gpios) = {
+       .name = "gpio_bcm2835",
+       .platdata = &gpio_platdata,
+};
+
 struct msg_get_arm_mem {
        struct bcm2835_mbox_hdr hdr;
        struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
index 5eedbf8ce66c5deadd36f268d181f998123fa45e..3aad532367b361cfe0c5bba0ed72f2f0e5c69c90 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/mmc.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 int checkboard(void)
index 42b920fb33395013fdda8ec2af0af823a9efa464..9f6494561c6a43378f899fda6d4702344b6cf63a 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/mmc.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 int checkboard(void)
index 1464f48b43ae00f2ad290c292433f07fcbe7386d..ddcf275f6e7854ca6d23cc7ab1d24162cf3c626f 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/mmc.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 int checkboard(void)
index 83fd3bd754bdf1549a7a9fe65a8929649feb2f2a..881d080522563912da43a96e90a7a66a6fa4866a 100644 (file)
@@ -6,9 +6,9 @@
 
 #include <common.h>
 #include <usb.h>
+#include <asm/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/dwmmc.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/power.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -19,6 +19,8 @@ int board_usb_init(int index, enum usb_init_type init)
        /* Configure gpios for usb 3503 hub:
         * disconnect, toggle reset and connect
         */
+       gpio_request(EXYNOS5_GPIO_D17, "usb_connect");
+       gpio_request(EXYNOS5_GPIO_X35, "usb_reset");
        gpio_direction_output(EXYNOS5_GPIO_D17, 0);
        gpio_direction_output(EXYNOS5_GPIO_X35, 0);
 
index 5c3c5bb9254b0bc427ab493033844f5fb1083086..8b4c8e9a9db90f882a1349e1b5c6e1258fc77ce3 100644 (file)
 #include <tmu.h>
 #include <netdev.h>
 #include <asm/io.h>
+#include <asm/gpio.h>
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/dwmmc.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/power.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int __exynos_early_init_f(void)
+__weak int exynos_early_init_f(void)
 {
        return 0;
 }
-int exynos_early_init_f(void)
-       __attribute__((weak, alias("__exynos_early_init_f")));
 
-int __exynos_power_init(void)
+__weak int exynos_power_init(void)
 {
        return 0;
 }
-int exynos_power_init(void)
-       __attribute__((weak, alias("__exynos_power_init")));
 
 #if defined CONFIG_EXYNOS_TMU
 /* Boot Time Thermal Analysis for SoC temperature threshold breach */
@@ -87,9 +83,6 @@ int board_init(void)
        boot_temp_check();
 #endif
 
-#ifdef CONFIG_EXYNOS_SPI
-       spi_init();
-#endif
        return exynos_init();
 }
 
index 8766f0ca0684948877b28bcec64177c6b51530b0..4538ac7f2a2fc2d2a91f840944d13ec542e35e11 100644 (file)
@@ -14,7 +14,6 @@
 #include <malloc.h>
 #include <linux/sizes.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/gpio.h>
 #include <linux/input.h>
 #include <power/pmic.h>
@@ -412,6 +411,8 @@ void check_boot_mode(void)
 void keys_init(void)
 {
        /* Set direction to input */
+       gpio_request(KEY_VOL_UP_GPIO, "volume-up");
+       gpio_request(KEY_VOL_DOWN_GPIO, "volume-down");
        gpio_direction_input(KEY_VOL_UP_GPIO);
        gpio_direction_input(KEY_VOL_DOWN_GPIO);
 }
index eb0f9bffae0e4a3b925b570af2ab4f1337aa2f60..58cf96eaa84f49bcd9ce47a3f2476504deb783be 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <common.h>
-#include <asm/arch/gpio.h>
+#include <asm/gpio.h>
 #include <asm/arch/mmc.h>
 #include <power/pmic.h>
 #include <usb/s3c_udc.h>
@@ -33,6 +33,16 @@ int board_init(void)
        return 0;
 }
 
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+void i2c_init_board(void)
+{
+       gpio_request(S5PC110_GPIO_J43, "i2c_clk");
+       gpio_request(S5PC110_GPIO_J40, "i2c_data");
+       gpio_direction_output(S5PC110_GPIO_J43, 1);
+       gpio_direction_output(S5PC110_GPIO_J40, 1);
+}
+#endif
+
 int power_init_board(void)
 {
        int ret;
@@ -80,6 +90,7 @@ int board_mmc_init(bd_t *bis)
        int i, ret, ret_sd = 0;
 
        /* MASSMEMORY_EN: XMSMDATA7: GPJ2[7] output high */
+       gpio_request(S5PC110_GPIO_J27, "massmemory_en");
        gpio_direction_output(S5PC110_GPIO_J27, 1);
 
        /*
@@ -108,6 +119,7 @@ int board_mmc_init(bd_t *bis)
         * SD card (T_FLASH) detect and init
         * T_FLASH_DETECT: EINT28: GPH3[4] input mode
         */
+       gpio_request(S5PC110_GPIO_H34, "t_flash_detect");
        gpio_cfg_pin(S5PC110_GPIO_H34, S5P_GPIO_INPUT);
        gpio_set_pull(S5PC110_GPIO_H34, S5P_GPIO_PULL_UP);
 
index a539267a1ca43339ddfe246ecc37aa85b0f73b9f..99a2facd1ee71f00945c01d5774d7d00e955c832 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <common.h>
 #include <asm/io.h>
+#include <asm/gpio.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/periph.h>
 #include <asm/arch/pinmux.h>
index d6ce1337b94ba6f06172ea6459c7162396dbc5ea..53ff7061d730c293260acd1f77367ec1d5bb4f16 100644 (file)
@@ -29,6 +29,7 @@ DECLARE_GLOBAL_DATA_PTR;
 static void board_enable_audio_codec(void)
 {
        /* Enable MAX98095 Codec */
+       gpio_request(EXYNOS5_GPIO_X17, "max98095_enable");
        gpio_direction_output(EXYNOS5_GPIO_X17, 1);
        gpio_set_pull(EXYNOS5_GPIO_X17, S5P_GPIO_PULL_NONE);
 }
@@ -199,16 +200,19 @@ static int board_dp_bridge_setup(void)
        /* Setup the GPIOs */
 
        /* PD is ACTIVE_LOW, and initially de-asserted */
+       gpio_request(EXYNOS5_GPIO_Y25, "dp_bridge_pd");
        gpio_set_pull(EXYNOS5_GPIO_Y25, S5P_GPIO_PULL_NONE);
        gpio_direction_output(EXYNOS5_GPIO_Y25, 1);
 
        /* Reset is ACTIVE_LOW */
+       gpio_request(EXYNOS5_GPIO_X15, "dp_bridge_reset");
        gpio_set_pull(EXYNOS5_GPIO_X15, S5P_GPIO_PULL_NONE);
        gpio_direction_output(EXYNOS5_GPIO_X15, 0);
 
        udelay(10);
        gpio_set_value(EXYNOS5_GPIO_X15, 1);
 
+       gpio_request(EXYNOS5_GPIO_X07, "dp_bridge_hpd");
        gpio_direction_input(EXYNOS5_GPIO_X07);
 
        /*
@@ -236,10 +240,12 @@ static int board_dp_bridge_setup(void)
 void exynos_cfg_lcd_gpio(void)
 {
        /* For Backlight */
+       gpio_request(EXYNOS5_GPIO_B20, "lcd_backlight");
        gpio_cfg_pin(EXYNOS5_GPIO_B20, S5P_GPIO_OUTPUT);
        gpio_set_value(EXYNOS5_GPIO_B20, 1);
 
        /* LCD power on */
+       gpio_request(EXYNOS5_GPIO_X15, "lcd_power");
        gpio_cfg_pin(EXYNOS5_GPIO_X15, S5P_GPIO_OUTPUT);
        gpio_set_value(EXYNOS5_GPIO_X15, 1);
 
@@ -276,6 +282,7 @@ void exynos_backlight_on(unsigned int on)
        mdelay(10);
 
        /* board_dp_backlight_en */
+       gpio_request(EXYNOS5_GPIO_X30, "board_dp_backlight_en");
        gpio_direction_output(EXYNOS5_GPIO_X30, 1);
 #endif
 }
index 270ee834e65695210c88668f2beab5e06ac4a304..a691222b8b143dd61e784ae8e3122dc95b8e3953 100644 (file)
@@ -11,9 +11,9 @@
 #include <lcd.h>
 #include <spi.h>
 #include <errno.h>
+#include <asm/gpio.h>
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/system.h>
 #include <asm/arch/dp_info.h>
@@ -74,9 +74,12 @@ void exynos_lcd_power_on(void)
        mdelay(5);
 
        /* TODO(ajaykumar.rs@samsung.com): Use device tree */
+       gpio_request(EXYNOS5420_GPIO_X35, "edp_slp#");
        gpio_direction_output(EXYNOS5420_GPIO_X35, 1);  /* EDP_SLP# */
        mdelay(10);
+       gpio_request(EXYNOS5420_GPIO_Y77, "edp_rst#");
        gpio_direction_output(EXYNOS5420_GPIO_Y77, 1);  /* EDP_RST# */
+       gpio_request(EXYNOS5420_GPIO_X26, "edp_hpd");
        gpio_direction_input(EXYNOS5420_GPIO_X26);      /* EDP_HPD */
        gpio_set_pull(EXYNOS5420_GPIO_X26, S5P_GPIO_PULL_NONE);
 
@@ -88,6 +91,7 @@ void exynos_lcd_power_on(void)
 void exynos_backlight_on(unsigned int onoff)
 {
        /* For PWM */
+       gpio_request(EXYNOS5420_GPIO_B20, "backlight_on");
        gpio_cfg_pin(EXYNOS5420_GPIO_B20, S5P_GPIO_FUNC(0x1));
        gpio_set_value(EXYNOS5420_GPIO_B20, 1);
 
index e009564a5988ce8a79a9bd7e83634ee9e8ca7ac4..66b6a9801f734ec1894b213a822b37ca86139419 100644 (file)
@@ -7,9 +7,9 @@
  */
 
 #include <common.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/sromc.h>
-#include <asm/arch/gpio.h>
 #include <netdev.h>
 
 DECLARE_GLOBAL_DATA_PTR;
index 8eca358981f10351a639c7775a58e19504072106..cb7f9b0ac88babc95253a5cf43e9e8d2ca580da6 100644 (file)
@@ -5,10 +5,10 @@
  */
 
 #include <common.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <netdev.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/periph.h>
 #include <asm/arch/pinmux.h>
index 3dd340b7d8da7e3b6a80d770e8442d0ba1a477b8..e163e45a587df150324e60ee57114a5735269a76 100644 (file)
@@ -10,8 +10,8 @@
 #include <common.h>
 #include <lcd.h>
 #include <asm/io.h>
+#include <asm/gpio.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/mipi_dsim.h>
@@ -63,6 +63,8 @@ void i2c_init_board(void)
        }
 
        /* I2C_8 -> FG */
+       gpio_request(EXYNOS4_GPIO_Y40, "i2c_clk");
+       gpio_request(EXYNOS4_GPIO_Y41, "i2c_data");
        gpio_direction_output(EXYNOS4_GPIO_Y40, 1);
        gpio_direction_output(EXYNOS4_GPIO_Y41, 1);
 }
@@ -346,12 +348,17 @@ int exynos_power_init(void)
 static unsigned int get_hw_revision(void)
 {
        int hwrev = 0;
+       char str[10];
        int i;
 
        /* hw_rev[3:0] == GPE1[3:0] */
-       for (i = EXYNOS4_GPIO_E10; i < EXYNOS4_GPIO_E14; i++) {
-               gpio_cfg_pin(i, S5P_GPIO_INPUT);
-               gpio_set_pull(i, S5P_GPIO_PULL_NONE);
+       for (i = 0; i < 4; i++) {
+               int pin = i + EXYNOS4_GPIO_E10;
+
+               sprintf(str, "hw_rev%d", i);
+               gpio_request(pin, str);
+               gpio_cfg_pin(pin, S5P_GPIO_INPUT);
+               gpio_set_pull(pin, S5P_GPIO_PULL_NONE);
        }
 
        udelay(1);
@@ -517,6 +524,7 @@ static void board_power_init(void)
 static void exynos_uart_init(void)
 {
        /* UART_SEL GPY4[7] (part2) at EXYNOS4 */
+       gpio_request(EXYNOS4_GPIO_Y47, "uart_sel");
        gpio_set_pull(EXYNOS4_GPIO_Y47, S5P_GPIO_PULL_UP);
        gpio_direction_output(EXYNOS4_GPIO_Y47, 1);
 }
@@ -534,6 +542,7 @@ int exynos_early_init_f(void)
 
 void exynos_reset_lcd(void)
 {
+       gpio_request(EXYNOS4_GPIO_Y45, "lcd_reset");
        gpio_direction_output(EXYNOS4_GPIO_Y45, 1);
        udelay(10000);
        gpio_direction_output(EXYNOS4_GPIO_Y45, 0);
index fa26e61244fc97e2a16b903dc89b971dadf26010..a7377497e5d2d4002f7b847ae051abfe5e8bb2b9 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <lcd.h>
+#include <asm/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/power.h>
 #include <asm/arch/mipi_dsim.h>
@@ -32,6 +33,7 @@ static inline u32 get_model_rev(void);
 static void check_hw_revision(void)
 {
        int modelrev = 0;
+       char str[12];
        int i;
 
        /*
@@ -40,13 +42,22 @@ static void check_hw_revision(void)
         * TRM say that it may cause unexcepted state and leakage current.
         * and pull-none is only for output function.
         */
-       for (i = EXYNOS4X12_GPIO_M10; i < EXYNOS4X12_GPIO_M12; i++)
-               gpio_cfg_pin(i, S5P_GPIO_INPUT);
+       for (i = 0; i < 2; i++) {
+               int pin = i + EXYNOS4X12_GPIO_M10;
+
+               sprintf(str, "model_rev%d", i);
+               gpio_request(pin, str);
+               gpio_cfg_pin(pin, S5P_GPIO_INPUT);
+       }
 
        /* GPM1[5:2]: HW_REV[3:0] */
-       for (i = EXYNOS4X12_GPIO_M12; i < EXYNOS4X12_GPIO_M16; i++) {
-               gpio_cfg_pin(i, S5P_GPIO_INPUT);
-               gpio_set_pull(i, S5P_GPIO_PULL_NONE);
+       for (i = 0; i < 4; i++) {
+               int pin = i + EXYNOS4X12_GPIO_M12;
+
+               sprintf(str, "hw_rev%d", i);
+               gpio_request(pin, str);
+               gpio_cfg_pin(pin, S5P_GPIO_INPUT);
+               gpio_set_pull(pin, S5P_GPIO_PULL_NONE);
        }
 
        /* GPM1[1:0]: MODEL_REV[1:0] */
@@ -102,10 +113,14 @@ static void board_init_i2c(void)
        }
 
        /* I2C_8 */
+       gpio_request(EXYNOS4X12_GPIO_F14, "i2c8_clk");
+       gpio_request(EXYNOS4X12_GPIO_F15, "i2c8_data");
        gpio_direction_output(EXYNOS4X12_GPIO_F14, 1);
        gpio_direction_output(EXYNOS4X12_GPIO_F15, 1);
 
        /* I2C_9 */
+       gpio_request(EXYNOS4X12_GPIO_M21, "i2c9_clk");
+       gpio_request(EXYNOS4X12_GPIO_M20, "i2c9_data");
        gpio_direction_output(EXYNOS4X12_GPIO_M21, 1);
        gpio_direction_output(EXYNOS4X12_GPIO_M20, 1);
 }
@@ -387,6 +402,7 @@ void exynos_lcd_power_on(void)
        struct pmic *p = pmic_get("MAX77686_PMIC");
 
        /* LCD_2.2V_EN: GPC0[1] */
+       gpio_request(EXYNOS4X12_GPIO_C01, "lcd_2v2_en");
        gpio_set_pull(EXYNOS4X12_GPIO_C01, S5P_GPIO_PULL_UP);
        gpio_direction_output(EXYNOS4X12_GPIO_C01, 1);
 
@@ -399,6 +415,7 @@ void exynos_lcd_power_on(void)
 void exynos_reset_lcd(void)
 {
        /* reset lcd */
+       gpio_request(EXYNOS4X12_GPIO_F21, "lcd_reset");
        gpio_direction_output(EXYNOS4X12_GPIO_F21, 0);
        udelay(10);
        gpio_set_value(EXYNOS4X12_GPIO_F21, 1);
index 47e7f538d65b7cd35943328d91ecb44385096961..22b08497cb57c1091b1eb82aeed7b58b73c18857 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/adc.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/watchdog.h>
 #include <ld9040.h>
@@ -202,53 +201,6 @@ int exynos_early_init_f(void)
        return 0;
 }
 
-#ifdef CONFIG_SOFT_SPI
-static void soft_spi_init(void)
-{
-       gpio_direction_output(CONFIG_SOFT_SPI_GPIO_SCLK,
-               CONFIG_SOFT_SPI_MODE & SPI_CPOL);
-       gpio_direction_output(CONFIG_SOFT_SPI_GPIO_MOSI, 1);
-       gpio_direction_input(CONFIG_SOFT_SPI_GPIO_MISO);
-       gpio_direction_output(CONFIG_SOFT_SPI_GPIO_CS,
-               !(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
-       gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
-               !(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
-       SPI_SCL(1);
-       gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
-               CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-       gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
-               !(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
-}
-
-int  spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-       return bus == 0 && cs == 0;
-}
-
-void universal_spi_scl(int bit)
-{
-       gpio_set_value(CONFIG_SOFT_SPI_GPIO_SCLK, bit);
-}
-
-void universal_spi_sda(int bit)
-{
-       gpio_set_value(CONFIG_SOFT_SPI_GPIO_MOSI, bit);
-}
-
-int universal_spi_read(void)
-{
-       return gpio_get_value(CONFIG_SOFT_SPI_GPIO_MISO);
-}
-#endif
-
 static void init_pmic_lcd(void)
 {
        unsigned char val;
@@ -331,9 +283,8 @@ void exynos_cfg_lcd_gpio(void)
        }
 
        /* gpio pad configuration for LCD reset. */
+       gpio_request(EXYNOS4_GPIO_Y45, "lcd_reset");
        gpio_cfg_pin(EXYNOS4_GPIO_Y45, S5P_GPIO_OUTPUT);
-
-       spi_init();
 }
 
 int mipi_power(void)
@@ -387,6 +338,7 @@ int exynos_init(void)
                 * you should set it HIGH since it removes the inverter
                 */
                /* MASSMEMORY_EN: XMDMDATA_6: GPE3[6] */
+               gpio_request(EXYNOS4_GPIO_E36, "ldo_en");
                gpio_direction_output(EXYNOS4_GPIO_E36, 0);
                break;
        default:
@@ -395,13 +347,11 @@ int exynos_init(void)
                 * But set it as HIGH to ensure
                 */
                /* MASSMEMORY_EN: XMDMADDR_3: GPE1[3] */
+               gpio_request(EXYNOS4_GPIO_E13, "massmemory_en");
                gpio_direction_output(EXYNOS4_GPIO_E13, 1);
                break;
        }
 
-#ifdef CONFIG_SOFT_SPI
-       soft_spi_init();
-#endif
        check_hw_revision();
        printf("HW Revision:\t0x%x\n", board_rev);
 
index 054e7ccdedf9bf4f222b22ecaab0fa2805b4d68f..a4aed3ba8baf2d3ce742f7c6967f273e61cc5afb 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm/omap_gpio.h>
 #include <asm/arch/mmc_host_def.h>
 #include <i2c.h>
+#include <spl.h>
+#include <mmc.h>
 #include <asm/gpio.h>
 #ifdef CONFIG_USB_EHCI
 #include <usb.h>
index 94b99bf53762660406c1dd1d87d1b9694d5a5625..4c5e38136fd55c542c52379285d0e42237e2cda2 100644 (file)
@@ -14,6 +14,8 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
+#include <ns16550.h>
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
 #endif
@@ -70,6 +72,17 @@ static struct {
        char env_setting[64];
 } expansion_config;
 
+static const struct ns16550_platdata beagle_serial = {
+       OMAP34XX_UART3,
+       2,
+       V_NS16550_CLK
+};
+
+U_BOOT_DEVICE(beagle_uart) = {
+       "serial_omap",
+       &beagle_serial
+};
+
 /*
  * Routine: board_init
  * Description: Early hardware init.
@@ -103,22 +116,22 @@ int board_init(void)
  */
 static int get_board_revision(void)
 {
-       int revision;
-
-       if (!gpio_request(171, "") &&
-           !gpio_request(172, "") &&
-           !gpio_request(173, "")) {
-
-               gpio_direction_input(171);
-               gpio_direction_input(172);
-               gpio_direction_input(173);
-
-               revision = gpio_get_value(173) << 2 |
-                          gpio_get_value(172) << 1 |
-                          gpio_get_value(171);
-       } else {
-               printf("Error: unable to acquire board revision GPIOs\n");
-               revision = -1;
+       static int revision = -1;
+
+       if (revision == -1) {
+               if (!gpio_request(171, "rev0") &&
+                   !gpio_request(172, "rev1") &&
+                   !gpio_request(173, "rev2")) {
+                       gpio_direction_input(171);
+                       gpio_direction_input(172);
+                       gpio_direction_input(173);
+
+                       revision = gpio_get_value(173) << 2 |
+                               gpio_get_value(172) << 1 |
+                               gpio_get_value(171);
+               } else {
+                       printf("Error: unable to acquire board revision GPIOs\n");
+               }
        }
 
        return revision;
@@ -258,7 +271,7 @@ static void beagle_dvi_pup(void)
        case REVISION_AXBX:
        case REVISION_CX:
        case REVISION_C4:
-               gpio_request(170, "");
+               gpio_request(170, "dvi");
                gpio_direction_output(170, 0);
                gpio_set_value(170, 1);
                break;
index 89b8dd3c3c1ee015be657b27372bc5c2176cc634..a913a4c84aa624453138ce0ad6fa8180db61fc1b 100644 (file)
@@ -27,47 +27,46 @@ void green_led_on(void)
 }
 #endif
 
+static int get_led_gpio(led_id_t mask)
+{
+#ifdef STATUS_LED_BIT
+       if (STATUS_LED_BIT & mask)
+               return BEAGLE_LED_USR0;
+#endif
+#ifdef STATUS_LED_BIT1
+       if (STATUS_LED_BIT1 & mask)
+               return BEAGLE_LED_USR1;
+#endif
+
+       return 0;
+}
+
 void __led_init (led_id_t mask, int state)
 {
-       __led_set (mask, state);
+       int toggle_gpio;
+
+       toggle_gpio = get_led_gpio(mask);
+
+       if (toggle_gpio && !gpio_request(toggle_gpio, "led"))
+               __led_set(mask, state);
 }
 
 void __led_toggle (led_id_t mask)
 {
-       int state, toggle_gpio = 0;
-#ifdef STATUS_LED_BIT
-       if (!toggle_gpio && STATUS_LED_BIT & mask)
-               toggle_gpio = BEAGLE_LED_USR0;
-#endif
-#ifdef STATUS_LED_BIT1
-       if (!toggle_gpio && STATUS_LED_BIT1 & mask)
-               toggle_gpio = BEAGLE_LED_USR1;
-#endif
+       int state, toggle_gpio;
+
+       toggle_gpio = get_led_gpio(mask);
        if (toggle_gpio) {
-               if (!gpio_request(toggle_gpio, "")) {
-                       gpio_direction_output(toggle_gpio, 0);
-                       state = gpio_get_value(toggle_gpio);
-                       gpio_set_value(toggle_gpio, !state);
-               }
+               state = gpio_get_value(toggle_gpio);
+               gpio_direction_output(toggle_gpio, !state);
        }
 }
 
 void __led_set (led_id_t mask, int state)
 {
-#ifdef STATUS_LED_BIT
-       if (STATUS_LED_BIT & mask) {
-               if (!gpio_request(BEAGLE_LED_USR0, "")) {
-                       gpio_direction_output(BEAGLE_LED_USR0, 0);
-                       gpio_set_value(BEAGLE_LED_USR0, state);
-               }
-       }
-#endif
-#ifdef STATUS_LED_BIT1
-       if (STATUS_LED_BIT1 & mask) {
-               if (!gpio_request(BEAGLE_LED_USR1, "")) {
-                       gpio_direction_output(BEAGLE_LED_USR1, 0);
-                       gpio_set_value(BEAGLE_LED_USR1, state);
-               }
-       }
-#endif
+       int toggle_gpio;
+
+       toggle_gpio = get_led_gpio(mask);
+       if (toggle_gpio)
+               gpio_direction_output(toggle_gpio, state);
 }
diff --git a/board/toradex/apalis_t30/Kconfig b/board/toradex/apalis_t30/Kconfig
new file mode 100644 (file)
index 0000000..f1dcda5
--- /dev/null
@@ -0,0 +1,12 @@
+if TARGET_APALIS_T30
+
+config SYS_BOARD
+       default "apalis_t30"
+
+config SYS_VENDOR
+       default "toradex"
+
+config SYS_CONFIG_NAME
+       default "apalis_t30"
+
+endif
diff --git a/board/toradex/apalis_t30/MAINTAINERS b/board/toradex/apalis_t30/MAINTAINERS
new file mode 100644 (file)
index 0000000..01bc73e
--- /dev/null
@@ -0,0 +1,7 @@
+Apalis T30
+M:     Marcel Ziswiler <marcel.ziswiler@toradex.com>
+S:     Maintained
+F:     board/toradex/apalis_t30/
+F:     include/configs/apalis_t30.h
+F:     configs/apalis_t30_defconfig
+F:     arch/arm/dts/tegra30-apalis.dtb
diff --git a/board/toradex/apalis_t30/Makefile b/board/toradex/apalis_t30/Makefile
new file mode 100644 (file)
index 0000000..a968e6b
--- /dev/null
@@ -0,0 +1,6 @@
+# Copyright (c) 2014 Marcel Ziswiler
+# SPDX-License-Identifier:      GPL-2.0+
+
+include $(srctree)/board/nvidia/common/common.mk
+
+obj-y  += apalis_t30.o
diff --git a/board/toradex/apalis_t30/apalis_t30.c b/board/toradex/apalis_t30/apalis_t30.c
new file mode 100644 (file)
index 0000000..b9d694a
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  (C) Copyright 2014
+ *  Marcel Ziswiler <marcel@ziswiler.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+
+#include <asm/arch/gp_padctrl.h>
+#include <asm/arch/pinmux.h>
+#include <asm/gpio.h>
+#include <i2c.h>
+#include <netdev.h>
+
+#include "pinmux-config-apalis_t30.h"
+
+#define PMU_I2C_ADDRESS                0x2D
+#define MAX_I2C_RETRY          3
+
+/*
+ * Routine: pinmux_init
+ * Description: Do individual peripheral pinmux configs
+ */
+void pinmux_init(void)
+{
+       pinmux_config_pingrp_table(tegra3_pinmux_common,
+                                  ARRAY_SIZE(tegra3_pinmux_common));
+
+       pinmux_config_pingrp_table(unused_pins_lowpower,
+                                  ARRAY_SIZE(unused_pins_lowpower));
+
+       /* Initialize any non-default pad configs (APB_MISC_GP regs) */
+       pinmux_config_drvgrp_table(apalis_t30_padctrl,
+                                  ARRAY_SIZE(apalis_t30_padctrl));
+}
+
+#ifdef CONFIG_PCI_TEGRA
+int tegra_pcie_board_init(void)
+{
+       unsigned int old_bus;
+       u8 addr, data[1];
+       int err;
+
+       old_bus = i2c_get_bus_num();
+
+       err = i2c_set_bus_num(0);
+       if (err) {
+               debug("failed to set I2C bus\n");
+               return err;
+       }
+
+       /* TPS659110: VDD2_OP_REG = 1.05V */
+       data[0] = 0x27;
+       addr = 0x25;
+
+       err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1);
+       if (err) {
+               debug("failed to set VDD supply\n");
+               return err;
+       }
+
+       /* TPS659110: VDD2_REG 7.5 mV/us, ACTIVE */
+       data[0] = 0x0D;
+       addr = 0x24;
+
+       err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1);
+       if (err) {
+               debug("failed to enable VDD supply\n");
+               return err;
+       }
+
+       /* TPS659110: LDO6_REG = 1.1V, ACTIVE */
+       data[0] = 0x0D;
+       addr = 0x35;
+
+       err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1);
+       if (err) {
+               debug("failed to set AVDD supply\n");
+               return err;
+       }
+
+       i2c_set_bus_num(old_bus);
+
+       return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+       return pci_eth_init(bis);
+}
+#endif /* CONFIG_PCI_TEGRA */
diff --git a/board/toradex/apalis_t30/pinmux-config-apalis_t30.h b/board/toradex/apalis_t30/pinmux-config-apalis_t30.h
new file mode 100644 (file)
index 0000000..c988d39
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2014, Marcel Ziswiler
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _PINMUX_CONFIG_APALIS_T30_H_
+#define _PINMUX_CONFIG_APALIS_T30_H_
+
+#define DEFAULT_PINMUX(_pingrp, _mux, _pull, _tri, _io)                \
+       {                                                       \
+               .pingrp         = PMUX_PINGRP_##_pingrp,        \
+               .func           = PMUX_FUNC_##_mux,             \
+               .pull           = PMUX_PULL_##_pull,            \
+               .tristate       = PMUX_TRI_##_tri,              \
+               .io             = PMUX_PIN_##_io,               \
+               .lock           = PMUX_PIN_LOCK_DEFAULT,        \
+               .od             = PMUX_PIN_OD_DEFAULT,          \
+               .ioreset        = PMUX_PIN_IO_RESET_DEFAULT,    \
+       }
+
+#define I2C_PINMUX(_pingrp, _mux, _pull, _tri, _io, _lock, _od)        \
+       {                                                       \
+               .pingrp         = PMUX_PINGRP_##_pingrp,        \
+               .func           = PMUX_FUNC_##_mux,             \
+               .pull           = PMUX_PULL_##_pull,            \
+               .tristate       = PMUX_TRI_##_tri,              \
+               .io             = PMUX_PIN_##_io,               \
+               .lock           = PMUX_PIN_LOCK_##_lock,        \
+               .od             = PMUX_PIN_OD_##_od,            \
+               .ioreset        = PMUX_PIN_IO_RESET_DEFAULT,    \
+       }
+
+#define LV_PINMUX(_pingrp, _mux, _pull, _tri, _io, _lock, _ioreset) \
+       {                                                       \
+               .pingrp         = PMUX_PINGRP_##_pingrp,        \
+               .func           = PMUX_FUNC_##_mux,             \
+               .pull           = PMUX_PULL_##_pull,            \
+               .tristate       = PMUX_TRI_##_tri,              \
+               .io             = PMUX_PIN_##_io,               \
+               .lock           = PMUX_PIN_LOCK_##_lock,        \
+               .od             = PMUX_PIN_OD_DEFAULT,          \
+               .ioreset        = PMUX_PIN_IO_RESET_##_ioreset  \
+       }
+
+#define DEFAULT_PADCFG(_drvgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) \
+       {                                                       \
+               .drvgrp         = PMUX_DRVGRP_##_drvgrp,        \
+               .slwf           = _slwf,                        \
+               .slwr           = _slwr,                        \
+               .drvup          = _drvup,                       \
+               .drvdn          = _drvdn,                       \
+               .lpmd           = PMUX_LPMD_##_lpmd,            \
+               .schmt          = PMUX_SCHMT_##_schmt,          \
+               .hsm            = PMUX_HSM_##_hsm,              \
+       }
+
+static struct pmux_pingrp_config tegra3_pinmux_common[] = {
+       /* SDMMC1 pinmux */
+       DEFAULT_PINMUX(SDMMC1_CLK_PZ0, SDMMC1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC1_CMD_PZ1, SDMMC1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC1_DAT3_PY4, SDMMC1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC1_DAT2_PY5, SDMMC1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC1_DAT1_PY6, SDMMC1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC1_DAT0_PY7, SDMMC1, NORMAL, NORMAL, INPUT),
+
+       /* SDMMC3 pinmux */
+       DEFAULT_PINMUX(SDMMC3_CLK_PA6, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_CMD_PA7, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_DAT0_PB7, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_DAT1_PB6, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_DAT2_PB5, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_DAT3_PB4, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_DAT4_PD1, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_DAT5_PD0, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_DAT6_PD3, SDMMC3, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SDMMC3_DAT7_PD4, SDMMC3, NORMAL, NORMAL, INPUT),
+
+       /* SDMMC4 pinmux (eMMC) */
+       LV_PINMUX(SDMMC4_CLK_PCC4, SDMMC4, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_CMD_PT7, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_DAT0_PAA0, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_DAT1_PAA1, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_DAT2_PAA2, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_DAT3_PAA3, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_DAT4_PAA4, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_DAT5_PAA5, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_DAT6_PAA6, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_DAT7_PAA7, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(SDMMC4_RST_N_PCC3, RSVD1, DOWN, NORMAL, INPUT, DISABLE, DISABLE),
+
+       /* I2C1 pinmux */
+       I2C_PINMUX(GEN1_I2C_SCL_PC4, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+       I2C_PINMUX(GEN1_I2C_SDA_PC5, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+
+       /* I2C2 pinmux */
+       I2C_PINMUX(GEN2_I2C_SCL_PT5, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+       I2C_PINMUX(GEN2_I2C_SDA_PT6, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+
+       /* I2C3 pinmux */
+       I2C_PINMUX(CAM_I2C_SCL_PBB1, I2C3, NORMAL, TRISTATE, INPUT, DISABLE, ENABLE),
+       I2C_PINMUX(CAM_I2C_SDA_PBB2, I2C3, NORMAL, TRISTATE, INPUT, DISABLE, ENABLE),
+
+       /* I2C4 pinmux */
+       I2C_PINMUX(DDC_SCL_PV4, I2C4, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+       I2C_PINMUX(DDC_SDA_PV5, I2C4, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+
+       /* Power I2C pinmux */
+       I2C_PINMUX(PWR_I2C_SCL_PZ6, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+       I2C_PINMUX(PWR_I2C_SDA_PZ7, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+
+       DEFAULT_PINMUX(ULPI_DATA0_PO1, UARTA, NORMAL, NORMAL, OUTPUT),
+       /* UARTA RX, make sure we don't get input form a floating Pin */
+       DEFAULT_PINMUX(ULPI_DATA1_PO2, UARTA, UP, NORMAL, INPUT),
+       DEFAULT_PINMUX(ULPI_DATA2_PO3, UARTA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(ULPI_DATA3_PO4, RSVD1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(ULPI_DATA4_PO5, UARTA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(ULPI_DATA5_PO6, UARTA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(ULPI_DATA6_PO7, UARTA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(ULPI_DATA7_PO0, UARTA, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(ULPI_CLK_PY0, UARTD, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(ULPI_DIR_PY1, UARTD, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(ULPI_NXT_PY2, UARTD, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(ULPI_STP_PY3, UARTD, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(DAP3_FS_PP0, I2S2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(DAP3_DIN_PP1, I2S2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(DAP3_DOUT_PP2, I2S2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(DAP3_SCLK_PP3, I2S2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(PV2, OWR, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(PV3, RSVD1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(CLK2_OUT_PW5, EXTPERIPH2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(CLK2_REQ_PCC5, DAP, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_PWR1_PC1, DISPLAYA, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(LCD_PWR2_PC6, DISPLAYA, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(LCD_SDIN_PZ2, SPI5, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_SDOUT_PN5, SPI5, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_WR_N_PZ3, DISPLAYA, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(LCD_CS0_N_PN4, SPI5, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_DC0_PN6, DISPLAYA, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(LCD_SCK_PZ4, SPI5, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_PWR0_PB2, DISPLAYA, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(LCD_PCLK_PB3, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_DE_PJ1, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_HSYNC_PJ3, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_VSYNC_PJ4, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D0_PE0, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D1_PE1, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D2_PE2, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D3_PE3, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D4_PE4, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D5_PE5, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D6_PE6, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D7_PE7, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D8_PF0, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D9_PF1, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D10_PF2, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D11_PF3, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D12_PF4, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D13_PF5, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D14_PF6, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D15_PF7, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D16_PM0, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D17_PM1, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D18_PM2, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D19_PM3, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D20_PM4, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D21_PM5, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D22_PM6, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_D23_PM7, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(LCD_CS1_N_PW0, DISPLAYA, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(LCD_M1_PW1, DISPLAYA, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(LCD_DC1_PD2, DISPLAYA, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(CRT_HSYNC_PV6, CRT, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(CRT_VSYNC_PV7, CRT, NORMAL, NORMAL, OUTPUT),
+       LV_PINMUX(VI_D0_PT4, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D1_PD5, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D2_PL0, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D3_PL1, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D4_PL2, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D5_PL3, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D6_PL4, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D7_PL5, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D8_PL6, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D9_PL7, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D10_PT2, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_D11_PT3, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_HSYNC_PD7, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_MCLK_PT1, VI, NORMAL, NORMAL, OUTPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_PCLK_PT0, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       LV_PINMUX(VI_VSYNC_PD6, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+       DEFAULT_PINMUX(UART2_RXD_PC3, UARTB, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(UART2_TXD_PC2, UARTB, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(UART2_RTS_N_PJ6, UARTB, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(UART2_CTS_N_PJ5, UARTB, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(UART3_TXD_PW6, UARTC, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(UART3_RXD_PW7, UARTC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(UART3_CTS_N_PA1, UARTC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(UART3_RTS_N_PC0, PWM0, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PU0, RSVD1, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(PU1, RSVD1, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(PU2, RSVD1, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(PU3, PWM0, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PU4, PWM1, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PU5, PWM2, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PU6, PWM3, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(DAP4_FS_PP4, I2S3, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(DAP4_DIN_PP5, I2S3, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(DAP4_DOUT_PP6, I2S3, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(DAP4_SCLK_PP7, I2S3, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(CLK3_OUT_PEE0, EXTPERIPH3, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(CLK3_REQ_PEE1, DEV3, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_WP_N_PC7, GMI, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_CS2_N_PK3, RSVD1, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_AD8_PH0, PWM0, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_AD10_PH2, NAND, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_A16_PJ7, UARTD, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_A17_PB0, UARTD, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_A18_PB1, UARTD, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_A19_PK7, UARTD, DOWN, TRISTATE, OUTPUT), /* NC */
+
+       DEFAULT_PINMUX(CAM_MCLK_PCC0, VI_ALT2, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PBB0, RSVD1, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PBB3, VGP3, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PBB4, VGP4, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PBB5, VGP5, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PBB6, VGP6, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PBB7, I2S4, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PCC1, RSVD1, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PCC2, I2S4, NORMAL, NORMAL, OUTPUT),
+
+       DEFAULT_PINMUX(JTAG_RTCK_PU7, RTCK, NORMAL, NORMAL, OUTPUT),
+
+       /* multiplexed VI_D2, VI_D3, VI_D4, VI_D5, VI_D6, VI_D7, VI_D8 and VI_D9
+        */
+       DEFAULT_PINMUX(KB_ROW0_PR0, RSVD2, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW1_PR1, RSVD2, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW2_PR2, RSVD2, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW3_PR3, RSVD2, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW4_PR4, RSVD3, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW5_PR5, KBC, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW6_PR6, KBC, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW7_PR7, KBC, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW8_PS0, KBC, NORMAL, TRISTATE, INPUT),
+       DEFAULT_PINMUX(KB_ROW9_PS1, KBC, NORMAL, TRISTATE, INPUT),
+
+       /* GPIOs */
+       DEFAULT_PINMUX(KB_ROW10_PS2, SDMMC2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_ROW11_PS3, SDMMC2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_ROW12_PS4, SDMMC2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_ROW13_PS5, SDMMC2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_ROW14_PS6, SDMMC2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_ROW15_PS7, SDMMC2, NORMAL, NORMAL, INPUT),
+
+       DEFAULT_PINMUX(KB_COL0_PQ0, KBC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_COL1_PQ1, KBC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_COL2_PQ2, KBC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_COL3_PQ3, KBC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_COL4_PQ4, KBC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_COL5_PQ5, KBC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_COL6_PQ6, KBC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_COL7_PQ7, KBC, NORMAL, NORMAL, INPUT),
+
+       DEFAULT_PINMUX(PV0, RSVD1, NORMAL, NORMAL, INPUT),
+
+       DEFAULT_PINMUX(CLK_32K_OUT_PA0, BLINK, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(SYS_CLK_REQ_PZ5, SYSCLK, NORMAL, NORMAL, INPUT),
+       /* multiplexed KB_COL0 */
+       DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(DAP1_FS_PN0, I2S0, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(DAP1_DIN_PN1, I2S0, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(DAP1_DOUT_PN2, I2S0, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(DAP1_SCLK_PN3, I2S0, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(CLK1_REQ_PEE2, DAP, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(CLK1_OUT_PW4, EXTPERIPH1, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(SPDIF_IN_PK6, SPDIF, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SPDIF_OUT_PK5, SPDIF, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(DAP2_FS_PA2, I2S1, NORMAL, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(DAP2_DIN_PA4, I2S1, NORMAL, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(DAP2_DOUT_PA5, I2S1, NORMAL, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(DAP2_SCLK_PA3, I2S1, NORMAL, TRISTATE, OUTPUT),
+
+       DEFAULT_PINMUX(SPI2_CS1_N_PW2, SPI2, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SPI1_MOSI_PX4, SPI1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SPI1_SCK_PX5, SPI1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SPI1_CS0_N_PX6, SPI1, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(SPI1_MISO_PX7, SPI1, NORMAL, NORMAL, INPUT),
+
+       DEFAULT_PINMUX(PEX_L0_PRSNT_N_PDD0, PCIE, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(PEX_L0_RST_N_PDD1, PCIE, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PEX_L0_CLKREQ_N_PDD2, PCIE, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(PEX_WAKE_N_PDD3, PCIE, NORMAL, NORMAL, INPUT),
+
+       DEFAULT_PINMUX(PEX_L1_PRSNT_N_PDD4, PCIE, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(PEX_L1_RST_N_PDD5, PCIE, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(PEX_L1_CLKREQ_N_PDD6, PCIE, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(PEX_L2_PRSNT_N_PDD7, PCIE, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(PEX_L2_RST_N_PCC6, PCIE, NORMAL, NORMAL, OUTPUT),
+       DEFAULT_PINMUX(PEX_L2_CLKREQ_N_PCC7, PCIE, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(HDMI_CEC_PEE3, CEC, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(HDMI_INT_PN7, RSVD1, NORMAL, NORMAL, INPUT),
+
+       DEFAULT_PINMUX(GMI_IORDY_PI5, RSVD1, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_AD12_PH4, NAND, DOWN, TRISTATE, OUTPUT), /* NC */
+       DEFAULT_PINMUX(GMI_AD14_PH6, NAND, DOWN, TRISTATE, OUTPUT), /* NC */
+
+       DEFAULT_PINMUX(SPI2_SCK_PX2, GMI, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(KB_ROW8_PS0, KBC, NORMAL, NORMAL, INPUT),
+};
+
+static struct pmux_pingrp_config unused_pins_lowpower[] = {
+       DEFAULT_PINMUX(GMI_WAIT_PI7, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_ADV_N_PK0, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_CLK_PK1, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_CS3_N_PK4, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_CS7_N_PI6, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD0_PG0, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD1_PG1, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD2_PG2, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD3_PG3, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD4_PG4, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD5_PG5, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD6_PG6, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD7_PG7, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD9_PH1, PWM1, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD11_PH3, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_AD13_PH5, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_WR_N_PI0, NAND, DOWN, TRISTATE, OUTPUT),
+       DEFAULT_PINMUX(GMI_OE_N_PI1, NAND, NORMAL, NORMAL, INPUT),
+       DEFAULT_PINMUX(GMI_DQS_PI2, NAND, DOWN, TRISTATE, OUTPUT),
+};
+
+static struct pmux_drvgrp_config apalis_t30_padctrl[] = {
+       /* (_drvgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) */
+       DEFAULT_PADCFG(SDIO1, SDIOCFG_DRVUP_SLWF, SDIOCFG_DRVDN_SLWR, \
+               SDIOCFG_DRVUP, SDIOCFG_DRVDN, NONE, DISABLE, DISABLE),
+};
+#endif /* _PINMUX_CONFIG_APALIS_T30_H_ */
index ed043f49b37d70e2739b1c60ac061862cb70ccbf..f4bc7d8728eeda63a0df9b133c3f9fa5757180ee 100644 (file)
@@ -35,7 +35,7 @@ void pinmux_init(void)
 void pin_mux_usb(void)
 {
        /* Reset ASIX using LAN_RESET */
-       gpio_request(GPIO_PDD0, NULL);
+       gpio_request(GPIO_PDD0, "LAN_RESET");
        gpio_direction_output(GPIO_PDD0, 0);
        udelay(5);
        gpio_set_value(GPIO_PDD0, 1);
index 25fbb55c8e6c126c0ebc0f433f584ccf934aa40b..8f4fe310d7d2b23bef6dd5da1bd2e50c50615d6f 100644 (file)
@@ -8,12 +8,11 @@
 #include <common.h>
 #include <config.h>
 #include <command.h>
+#include <elf.h>
 
 /*
  * FIXME: Add code to test image and it's header.
  */
-extern int valid_elf_image (unsigned long addr);
-
 static int
 image_check(ulong addr)
 {
index e6aa298d5a4e8bc5255f7bcacf2022bc7dbf0f8f..b5bebc9dc862727b7aa2386f64691ace23475cc0 100644 (file)
@@ -128,14 +128,11 @@ int init_func_watchdog_reset(void)
 }
 #endif /* CONFIG_WATCHDOG */
 
-void __board_add_ram_info(int use_default)
+__weak void board_add_ram_info(int use_default)
 {
        /* please define platform specific board_add_ram_info() */
 }
 
-void board_add_ram_info(int)
-       __attribute__ ((weak, alias("__board_add_ram_info")));
-
 static int init_baud_rate(void)
 {
        gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
@@ -221,7 +218,7 @@ static int show_dram_config(void)
        return 0;
 }
 
-void __dram_init_banksize(void)
+__weak void dram_init_banksize(void)
 {
 #if defined(CONFIG_NR_DRAM_BANKS) && defined(CONFIG_SYS_SDRAM_BASE)
        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
@@ -229,9 +226,6 @@ void __dram_init_banksize(void)
 #endif
 }
 
-void dram_init_banksize(void)
-       __attribute__((weak, alias("__dram_init_banksize")));
-
 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
 static int init_func_i2c(void)
 {
index 7e1a76d97f73be5d2eb3d347dffbb82d301b7522..7c339008ed2a46b91677d4c4c9e5e97fd58f4a1f 100644 (file)
@@ -60,7 +60,7 @@ DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
 
-int __board_flash_wp_on(void)
+__weak int board_flash_wp_on(void)
 {
        /*
         * Most flashes can't be detected when write protection is enabled,
@@ -70,16 +70,10 @@ int __board_flash_wp_on(void)
        return 0;
 }
 
-int board_flash_wp_on(void)
-       __attribute__ ((weak, alias("__board_flash_wp_on")));
-
-void __cpu_secondary_init_r(void)
+__weak void cpu_secondary_init_r(void)
 {
 }
 
-void cpu_secondary_init_r(void)
-       __attribute__ ((weak, alias("__cpu_secondary_init_r")));
-
 static int initr_secondary_cpu(void)
 {
        /*
@@ -354,7 +348,7 @@ static int initr_flash(void)
 }
 #endif
 
-#ifdef CONFIG_PPC
+#if defined(CONFIG_PPC) && !defined(CONFIG_DM_SPI)
 static int initr_spi(void)
 {
        /* PPC does this here */
@@ -370,7 +364,7 @@ static int initr_spi(void)
 
 #ifdef CONFIG_CMD_NAND
 /* go init the NAND */
-int initr_nand(void)
+static int initr_nand(void)
 {
        puts("NAND:  ");
        nand_init();
@@ -380,7 +374,7 @@ int initr_nand(void)
 
 #if defined(CONFIG_CMD_ONENAND)
 /* go init the NAND */
-int initr_onenand(void)
+static int initr_onenand(void)
 {
        puts("NAND:  ");
        onenand_init();
@@ -389,7 +383,7 @@ int initr_onenand(void)
 #endif
 
 #ifdef CONFIG_GENERIC_MMC
-int initr_mmc(void)
+static int initr_mmc(void)
 {
        puts("MMC:   ");
        mmc_initialize(gd->bd);
@@ -398,7 +392,7 @@ int initr_mmc(void)
 #endif
 
 #ifdef CONFIG_HAS_DATAFLASH
-int initr_dataflash(void)
+static int initr_dataflash(void)
 {
        AT91F_DataflashInit();
        dataflash_print_info();
index ff81a271a559232c07e3f7c1cbebc4bf327731c3..17ed3897f99391cbc0eb8f962d46ae138a4d1d17 100644 (file)
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <bootstage.h>
 #include <bzlib.h>
+#include <errno.h>
 #include <fdt_support.h>
 #include <lmb.h>
 #include <malloc.h>
@@ -83,6 +84,7 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
 {
        const void *os_hdr;
        bool ep_found = false;
+       int ret;
 
        /* get kernel image header, start address and length */
        os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
@@ -102,6 +104,7 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
 
                images.os.end = image_get_image_end(os_hdr);
                images.os.load = image_get_load(os_hdr);
+               images.os.arch = image_get_arch(os_hdr);
                break;
 #endif
 #if defined(CONFIG_FIT)
@@ -129,6 +132,13 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
                        return 1;
                }
 
+               if (fit_image_get_arch(images.fit_hdr_os,
+                                      images.fit_noffset_os,
+                                      &images.os.arch)) {
+                       puts("Can't get image ARCH!\n");
+                       return 1;
+               }
+
                images.os.end = fit_get_end(images.fit_hdr_os);
 
                if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os,
@@ -156,8 +166,17 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
                return 1;
        }
 
-       /* find kernel entry point */
-       if (images.legacy_hdr_valid) {
+       /* If we have a valid setup.bin, we will use that for entry (x86) */
+       if (images.os.arch == IH_ARCH_I386) {
+               ulong len;
+
+               ret = boot_get_setup(&images, IH_ARCH_I386, &images.ep, &len);
+               if (ret < 0 && ret != -ENOENT) {
+                       puts("Could not find a valid setup.bin for x86\n");
+                       return 1;
+               }
+               /* Kernel entry point is the setup.bin */
+       } else if (images.legacy_hdr_valid) {
                images.ep = image_get_ep(&images.legacy_hdr_os_copy);
 #if defined(CONFIG_FIT)
        } else if (images.fit_uname_os) {
index 843ec6e0c2696380d176740bbb5864b05e46624b..67233600b157244409c2710afa606337d2ebaf80 100644 (file)
@@ -12,6 +12,7 @@
 #include <bootm.h>
 #include <command.h>
 #include <environment.h>
+#include <errno.h>
 #include <image.h>
 #include <lmb.h>
 #include <malloc.h>
index ab9c7e332d97b200109e09e464b0fb786ac967c6..42a52965c2722282c36e6ebeaa0049c8c21b4c9f 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <common.h>
+#include <bootm.h>
 #include <command.h>
 #include <linux/ctype.h>
 #include <net.h>
@@ -28,8 +29,7 @@ static unsigned long load_elf_image_phdr(unsigned long addr);
 static unsigned long load_elf_image_shdr(unsigned long addr);
 
 /* Allow ports to override the default behavior */
-__attribute__((weak))
-unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
+static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
                               int argc, char * const argv[])
 {
        unsigned long ret;
index 11f4e4031daddca8570892c53c47e16a198cee8a..65d6df451c6d4f4c5dc9c26a94a02a536b42386e 100644 (file)
@@ -12,7 +12,7 @@
 #include <dm.h>
 #include <asm/gpio.h>
 
-int __weak name_to_gpio(const char *name)
+__weak int name_to_gpio(const char *name)
 {
        return simple_strtoul(name, NULL, 10);
 }
@@ -25,13 +25,6 @@ enum gpio_cmd {
 };
 
 #if defined(CONFIG_DM_GPIO) && !defined(gpio_status)
-static const char * const gpio_function[GPIOF_COUNT] = {
-       "input",
-       "output",
-       "unused",
-       "unknown",
-       "func",
-};
 
 /* A few flags used by show_gpio() */
 enum {
@@ -40,22 +33,16 @@ enum {
        FLAG_SHOW_NEWLINE       = 1 << 2,
 };
 
-static void show_gpio(struct udevice *dev, const char *bank_name, int offset,
-                     int *flagsp)
+static void gpio_get_description(struct udevice *dev, const char *bank_name,
+                                int offset, int *flagsp)
 {
-       struct dm_gpio_ops *ops = gpio_get_ops(dev);
-       int func = GPIOF_UNKNOWN;
        char buf[80];
        int ret;
 
-       BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
-
-       if (ops->get_function) {
-               ret = ops->get_function(dev, offset);
-               if (ret >= 0 && ret < ARRAY_SIZE(gpio_function))
-                       func = ret;
-       }
-       if (!(*flagsp & FLAG_SHOW_ALL) && func == GPIOF_UNUSED)
+       ret = gpio_get_function(dev, offset, NULL);
+       if (ret < 0)
+               goto err;
+       if (!(*flagsp & FLAG_SHOW_ALL) && ret == GPIOF_UNUSED)
                return;
        if ((*flagsp & FLAG_SHOW_BANK) && bank_name) {
                if (*flagsp & FLAG_SHOW_NEWLINE) {
@@ -65,20 +52,15 @@ static void show_gpio(struct udevice *dev, const char *bank_name, int offset,
                printf("Bank %s:\n", bank_name);
                *flagsp &= ~FLAG_SHOW_BANK;
        }
-       *buf = '\0';
-       if (ops->get_state) {
-               ret = ops->get_state(dev, offset, buf, sizeof(buf));
-               if (ret) {
-                       puts("<unknown>");
-                       return;
-               }
-       } else {
-               sprintf(buf, "%s%u: %8s %d", bank_name, offset,
-                       gpio_function[func], ops->get_value(dev, offset));
-       }
 
-       puts(buf);
-       puts("\n");
+       ret = gpio_get_status(dev, offset, buf, sizeof(buf));
+       if (ret)
+               goto err;
+
+       printf("%s\n", buf);
+       return;
+err:
+       printf("Error %d\n", ret);
 }
 
 static int do_gpio_status(bool all, const char *gpio_name)
@@ -101,8 +83,10 @@ static int do_gpio_status(bool all, const char *gpio_name)
                if (all)
                        flags |= FLAG_SHOW_ALL;
                bank_name = gpio_get_bank_info(dev, &num_bits);
-               if (!num_bits)
+               if (!num_bits) {
+                       debug("GPIO device %s has no bits\n", dev->name);
                        continue;
+               }
                banklen = bank_name ? strlen(bank_name) : 0;
 
                if (!gpio_name || !bank_name ||
@@ -113,11 +97,12 @@ static int do_gpio_status(bool all, const char *gpio_name)
                        p = gpio_name + banklen;
                        if (gpio_name && *p) {
                                offset = simple_strtoul(p, NULL, 10);
-                               show_gpio(dev, bank_name, offset, &flags);
+                               gpio_get_description(dev, bank_name, offset,
+                                                    &flags);
                        } else {
                                for (offset = 0; offset < num_bits; offset++) {
-                                       show_gpio(dev, bank_name, offset,
-                                                 &flags);
+                                       gpio_get_description(dev, bank_name,
+                                                            offset, &flags);
                                }
                        }
                }
index c60e8d10df6e1ad244a154a795bff79a4d51c8df..95a6f89a845da57b5e5430b339dbda12f4d5d354 100644 (file)
@@ -8,10 +8,13 @@
 
 #include <common.h>
 #include <div64.h>
+#include <dm.h>
 #include <malloc.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 #include <asm/io.h>
+#include <dm/device-internal.h>
 
 static struct spi_flash *flash;
 
@@ -80,7 +83,12 @@ static int do_spi_flash_probe(int argc, char * const argv[])
        unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
        unsigned int mode = CONFIG_SF_DEFAULT_MODE;
        char *endp;
+#ifdef CONFIG_DM_SPI_FLASH
+       struct udevice *new, *bus_dev;
+       int ret;
+#else
        struct spi_flash *new;
+#endif
 
        if (argc >= 2) {
                cs = simple_strtoul(argv[1], &endp, 0);
@@ -108,6 +116,23 @@ static int do_spi_flash_probe(int argc, char * const argv[])
                        return -1;
        }
 
+#ifdef CONFIG_DM_SPI_FLASH
+       /* Remove the old device, otherwise probe will just be a nop */
+       ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new);
+       if (!ret) {
+               device_remove(new);
+               device_unbind(new);
+       }
+       flash = NULL;
+       ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new);
+       if (ret) {
+               printf("Failed to initialize SPI flash at %u:%u (error %d)\n",
+                      bus, cs, ret);
+               return 1;
+       }
+
+       flash = new->uclass_priv;
+#else
        new = spi_flash_probe(bus, cs, speed, mode);
        if (!new) {
                printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
@@ -117,6 +142,7 @@ static int do_spi_flash_probe(int argc, char * const argv[])
        if (flash)
                spi_flash_free(flash);
        flash = new;
+#endif
 
        return 0;
 }
index be5709c6173d09562a3f274fd6c1a0e4756c67af..64c3ffcf423b35fc1b0a65daccb99d490a053c5f 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <errno.h>
 #include <spi.h>
 
@@ -42,19 +43,38 @@ static uchar                din[MAX_SPI_BYTES];
 static int do_spi_xfer(int bus, int cs)
 {
        struct spi_slave *slave;
-       int rcode = 0;
-
+       int ret = 0;
+
+#ifdef CONFIG_DM_SPI
+       char name[30], *str;
+       struct udevice *dev;
+
+       snprintf(name, sizeof(name), "generic_%d:%d", bus, cs);
+       str = strdup(name);
+       ret = spi_get_bus_and_cs(bus, cs, 1000000, mode, "spi_generic_drv",
+                                str, &dev, &slave);
+       if (ret)
+               return ret;
+#else
        slave = spi_setup_slave(bus, cs, 1000000, mode);
        if (!slave) {
                printf("Invalid device %d:%d\n", bus, cs);
                return -EINVAL;
        }
+#endif
 
-       spi_claim_bus(slave);
-       if (spi_xfer(slave, bitlen, dout, din,
-                    SPI_XFER_BEGIN | SPI_XFER_END) != 0) {
-               printf("Error during SPI transaction\n");
-               rcode = -EIO;
+       ret = spi_claim_bus(slave);
+       if (ret)
+               goto done;
+       ret = spi_xfer(slave, bitlen, dout, din,
+                      SPI_XFER_BEGIN | SPI_XFER_END);
+#ifndef CONFIG_DM_SPI
+       /* We don't get an error code in this case */
+       if (ret)
+               ret = -EIO;
+#endif
+       if (ret) {
+               printf("Error %d during SPI transaction\n", ret);
        } else {
                int j;
 
@@ -62,10 +82,13 @@ static int do_spi_xfer(int bus, int cs)
                        printf("%02X", din[j]);
                printf("\n");
        }
+done:
        spi_release_bus(slave);
+#ifndef CONFIG_DM_SPI
        spi_free_slave(slave);
+#endif
 
-       return rcode;
+       return ret;
 }
 
 /*
index 5a2f411600280acd5ba435762083f8394da61377..4695386a332ab867c12df32e938d4976ce7f0115 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <stdarg.h>
+#include <iomux.h>
 #include <malloc.h>
 #include <os.h>
 #include <serial.h>
@@ -621,7 +622,7 @@ inline void dbg(const char *fmt, ...)
 
 }
 #else
-inline void dbg(const char *fmt, ...)
+static inline void dbg(const char *fmt, ...)
 {
 }
 #endif
index b8ce1b581aab463f65330e4dcc769f3fc00b1f19..bb299bccfff7073791ad9b1cedf5c1d3c171d190 100644 (file)
 
 #include <common.h>
 #include <cros_ec.h>
+#include <dm.h>
+#include <errno.h>
+
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifndef CONFIG_DM_CROS_EC
 struct local_info {
        struct cros_ec_dev *cros_ec_dev;        /* Pointer to cros_ec device */
        int cros_ec_err;                        /* Error for cros_ec, 0 if ok */
 };
 
 static struct local_info local;
+#endif
 
 struct cros_ec_dev *board_get_cros_ec_dev(void)
 {
+#ifdef CONFIG_DM_CROS_EC
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
+       if (ret) {
+               debug("%s: Error %d\n", __func__, ret);
+               return NULL;
+       }
+       return dev->uclass_priv;
+#else
        return local.cros_ec_dev;
+#endif
 }
 
 static int board_init_cros_ec_devices(const void *blob)
 {
+#ifndef CONFIG_DM_CROS_EC
        local.cros_ec_err = cros_ec_init(blob, &local.cros_ec_dev);
        if (local.cros_ec_err)
                return -1;  /* Will report in board_late_init() */
+#endif
 
        return 0;
 }
@@ -40,5 +59,16 @@ int cros_ec_board_init(void)
 
 int cros_ec_get_error(void)
 {
+#ifdef CONFIG_DM_CROS_EC
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
+       if (ret && ret != -ENODEV)
+               return ret;
+
+       return 0;
+#else
        return local.cros_ec_err;
+#endif
 }
index 5a734a9321a9400a73ee8024f29bcdb17d546ee6..749605fe3fa89ab798a0ebde92f1f90e4a40fb2b 100644 (file)
@@ -124,7 +124,7 @@ int env_init(void)
  * The legacy NAND code saved the environment in the first NAND device i.e.,
  * nand_dev_desc + 0. This is also the behaviour using the new NAND code.
  */
-int writeenv(size_t offset, u_char *buf)
+static int writeenv(size_t offset, u_char *buf)
 {
        size_t end = offset + CONFIG_ENV_RANGE;
        size_t amount_saved = 0;
@@ -233,7 +233,7 @@ int saveenv(void)
 }
 #endif /* CMD_SAVEENV */
 
-int readenv(size_t offset, u_char *buf)
+static int readenv(size_t offset, u_char *buf)
 {
        size_t end = offset + CONFIG_ENV_RANGE;
        size_t amount_loaded = 0;
index 37ab13ae17842309339fa9a70a42e49b8669207e..5e3729c2c2d62dfb201e2329081318f1657fa422 100644 (file)
@@ -12,6 +12,7 @@
 #include <common.h>
 #include <environment.h>
 #include <malloc.h>
+#include <spi.h>
 #include <spi_flash.h>
 #include <search.h>
 #include <errno.h>
index b97ca48307dcba1493d9426bde8e6f706d8fa1ed..88fcfc8cb6fc652e8fb5242869ebdb4c0813f5dd 100644 (file)
@@ -27,10 +27,12 @@ unsigned long get_version(void)
 # define i2c_write         dummy
 # define i2c_read          dummy
 #endif
-#ifndef CONFIG_CMD_SPI
+#if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI)
 # define spi_init          dummy
 # define spi_setup_slave   dummy
 # define spi_free_slave    dummy
+#endif
+#ifndef CONFIG_CMD_SPI
 # define spi_claim_bus     dummy
 # define spi_release_bus   dummy
 # define spi_xfer          dummy
index 255c4cac9cafa328d33cd382e524207c1728c7cc..a272ea2e83456d9a50018ffb1752b0e2016ddcf7 100644 (file)
@@ -1434,7 +1434,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
                printf("%s  FDT:          %s\n", p, uname);
 }
 
-int fit_image_select(const void *fit, int rd_noffset, int verify)
+static int fit_image_select(const void *fit, int rd_noffset, int verify)
 {
        fit_image_print(fit, rd_noffset, "   ");
 
@@ -1497,6 +1497,8 @@ static const char *fit_get_image_type_property(int type)
                return FIT_KERNEL_PROP;
        case IH_TYPE_RAMDISK:
                return FIT_RAMDISK_PROP;
+       case IH_TYPE_X86_SETUP:
+               return FIT_SETUP_PROP;
        }
 
        return "unknown";
@@ -1591,7 +1593,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
        }
 
        bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
-#ifndef USE_HOSTCC
+#if !defined(USE_HOSTCC) && !defined(CONFIG_SANDBOX)
        if (!fit_image_check_target_arch(fit, noffset)) {
                puts("Unsupported Architecture\n");
                bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
@@ -1693,3 +1695,23 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
 
        return noffset;
 }
+
+int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
+                       ulong *setup_start, ulong *setup_len)
+{
+       int noffset;
+       ulong addr;
+       ulong len;
+       int ret;
+
+       addr = map_to_sysmem(images->fit_hdr_os);
+       noffset = fit_get_node_from_config(images, FIT_SETUP_PROP, addr);
+       if (noffset < 0)
+               return noffset;
+
+       ret = fit_image_load(images, addr, NULL, NULL, arch,
+                            IH_TYPE_X86_SETUP, BOOTSTAGE_ID_FIT_SETUP_START,
+                            FIT_LOAD_REQUIRED, setup_start, &len);
+
+       return ret;
+}
index 085771c7639b6a4aaed005dcef5f305dc3fe7e4e..640e83b7bdf8013d02416615faf796c483a12d0f 100644 (file)
@@ -143,6 +143,7 @@ static const table_entry_t uimage_type[] = {
        {       IH_TYPE_UBLIMAGE,   "ublimage",   "Davinci UBL image",},
        {       IH_TYPE_MXSIMAGE,   "mxsimage",   "Freescale MXS Boot Image",},
        {       IH_TYPE_ATMELIMAGE, "atmelimage", "ATMEL ROM-Boot Image",},
+       {       IH_TYPE_X86_SETUP,  "x86_setup",  "x86 setup.bin",    },
        {       -1,                 "",           "",                   },
 };
 
@@ -1136,6 +1137,16 @@ error:
 }
 #endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */
 
+int boot_get_setup(bootm_headers_t *images, uint8_t arch,
+                  ulong *setup_start, ulong *setup_len)
+{
+#if defined(CONFIG_FIT)
+       return boot_get_setup_fit(images, arch, setup_start, setup_len);
+#else
+       return -ENOENT;
+#endif
+}
+
 #ifdef CONFIG_SYS_BOOT_GET_CMDLINE
 /**
  * boot_get_cmdline - allocate and initialize kernel cmdline
index 94afeb290098dc4b1356496ade659d1985fcd143..e81c074f36c60a92e8223eed055e5b022c697ad8 100644 (file)
@@ -105,12 +105,9 @@ static inline void *menu_item_destroy(struct menu *m,
        return NULL;
 }
 
-void __menu_display_statusline(struct menu *m)
+__weak void menu_display_statusline(struct menu *m)
 {
-       return;
 }
-void menu_display_statusline(struct menu *m)
-       __attribute__ ((weak, alias("__menu_display_statusline")));
 
 /*
  * Display a menu so the user can make a choice of an item. First display its
index be54b1011018192327fdc0bcfd368d7285e0fd44..96b10648d869620ddb3e15a819528de0d29ab2e0 100644 (file)
@@ -19,7 +19,7 @@ static inline void mdm_readline(char *buf, int bufsiz)
        for(;;) {
                c = serial_getc();
 
-               /*              dbg("(%c)", c); */
+               debug("(%c)", c);
 
                switch(c) {
                case '\r':
@@ -40,7 +40,6 @@ static inline void mdm_readline(char *buf, int bufsiz)
        }
 }
 
-extern void  dbg(const char *fmt, ...);
 int mdm_init (void)
 {
        char env_str[16];
@@ -66,15 +65,15 @@ int mdm_init (void)
                        serial_puts("\n");
                        for(;;) {
                                mdm_readline(console_buffer, CONFIG_SYS_CBSIZE);
-                               dbg("ini%d: [%s]", i, console_buffer);
+                               debug("ini%d: [%s]", i, console_buffer);
 
                                if ((strcmp(console_buffer, "OK") == 0) ||
                                        (strcmp(console_buffer, "ERROR") == 0)) {
-                                       dbg("ini%d: cmd done", i);
+                                       debug("ini%d: cmd done", i);
                                        break;
                                } else /* in case we are originating call ... */
                                        if (strncmp(console_buffer, "CONNECT", 7) == 0) {
-                                               dbg("ini%d: connect", i);
+                                               debug("ini%d: connect", i);
                                                return 0;
                                        }
                        }
@@ -90,9 +89,9 @@ int mdm_init (void)
        for(;i > 1;) { /* if 'i' > 1 - wait for connection
                                  message from modem */
                mdm_readline(console_buffer, CONFIG_SYS_CBSIZE);
-               dbg("ini_f: [%s]", console_buffer);
+               debug("ini_f: [%s]", console_buffer);
                if (strncmp(console_buffer, "CONNECT", 7) == 0) {
-                       dbg("ini_f: connected");
+                       debug("ini_f: connected");
                        return 0;
                }
        }
index 82328150cba17ceb382c1ee111595c41b8fbde00..68c595d2d79c292e3ac9b93ae55b0b22bf0e27f0 100644 (file)
@@ -39,39 +39,39 @@ char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" };
 #endif
 
 #ifdef CONFIG_SYS_DEVICE_NULLDEV
-void nulldev_putc(struct stdio_dev *dev, const char c)
+static void nulldev_putc(struct stdio_dev *dev, const char c)
 {
        /* nulldev is empty! */
 }
 
-void nulldev_puts(struct stdio_dev *dev, const char *s)
+static void nulldev_puts(struct stdio_dev *dev, const char *s)
 {
        /* nulldev is empty! */
 }
 
-int nulldev_input(struct stdio_dev *dev)
+static int nulldev_input(struct stdio_dev *dev)
 {
        /* nulldev is empty! */
        return 0;
 }
 #endif
 
-void stdio_serial_putc(struct stdio_dev *dev, const char c)
+static void stdio_serial_putc(struct stdio_dev *dev, const char c)
 {
        serial_putc(c);
 }
 
-void stdio_serial_puts(struct stdio_dev *dev, const char *s)
+static void stdio_serial_puts(struct stdio_dev *dev, const char *s)
 {
        serial_puts(s);
 }
 
-int stdio_serial_getc(struct stdio_dev *dev)
+static int stdio_serial_getc(struct stdio_dev *dev)
 {
        return serial_getc();
 }
 
-int stdio_serial_tstc(struct stdio_dev *dev)
+static int stdio_serial_tstc(struct stdio_dev *dev)
 {
        return serial_tstc();
 }
index 2157537c823056729fef0aae65cffabfe1588b15..00805bdc5b3d9689b069c86c3bf5e67916e6d35a 100644 (file)
--- a/config.mk
+++ b/config.mk
@@ -18,6 +18,8 @@ PLATFORM_LDFLAGS :=
 LDFLAGS :=
 LDFLAGS_FINAL :=
 OBJCOPYFLAGS :=
+# clear VENDOR for tcsh
+VENDOR :=
 #########################################################################
 
 ARCH := $(CONFIG_SYS_ARCH:"%"=%)
index 38450c0d615c6bb36cf95d1c31d16a29d61e80f4..b631c410dc73414eb83f99349236a2cd5ac6d89b 100644 (file)
@@ -1,4 +1,4 @@
 CONFIG_SPL=y
-CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1,EMMC_BOOT"
+CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_AM335X_EVM=y
index e25714366be5a5b2a7186a97ef640a05e047c0f8..5837a0a4da75bfb9750fcf416194a58977a5ee90 100644 (file)
@@ -1,5 +1,5 @@
 CONFIG_SPL=y
-CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1,EMMC_BOOT,ENABLE_VBOOT"
+CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT,ENABLE_VBOOT"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_AM335X_EVM=y
 CONFIG_OF_CONTROL=y
diff --git a/configs/apalis_t30_defconfig b/configs/apalis_t30_defconfig
new file mode 100644 (file)
index 0000000..fc5e1e4
--- /dev/null
@@ -0,0 +1,5 @@
++S:CONFIG_ARM=y
++S:CONFIG_TEGRA=y
++S:CONFIG_TEGRA30=y
++S:CONFIG_TARGET_APALIS_T30=y
+CONFIG_DEFAULT_DEVICE_TREE="tegra30-apalis"
diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig
new file mode 100644 (file)
index 0000000..7aa216c
--- /dev/null
@@ -0,0 +1,2 @@
+CONFIG_ARM=y
+CONFIG_TARGET_DB_MV784MP_GP=y
diff --git a/configs/maxbcm_defconfig b/configs/maxbcm_defconfig
new file mode 100644 (file)
index 0000000..4bcffd8
--- /dev/null
@@ -0,0 +1,2 @@
+CONFIG_ARM=y
+CONFIG_TARGET_MAXBCM=y
index 53f3126e71e43e453d00815e4222de3204e38016..e6aba422f811940b81784c591201b5e743240d4f 100644 (file)
@@ -2,7 +2,10 @@ CONFIG_SPL=y
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_UNIPHIER=y
 +S:CONFIG_MACH_PH1_LD4=y
+CONFIG_DM=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
+CONFIG_DM_SERIAL=y
+CONFIG_UNIPHIER_SERIAL=y
 S:CONFIG_SPL_NAND_DENALI=y
index 209466ebcb334c900e54692ac75993e7e5dbb00d..334ec4bbdff8ff9af4724770dc19d9a66524a711 100644 (file)
@@ -2,7 +2,10 @@ CONFIG_SPL=y
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_UNIPHIER=y
 +S:CONFIG_MACH_PH1_PRO4=y
+CONFIG_DM=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
+CONFIG_DM_SERIAL=y
+CONFIG_UNIPHIER_SERIAL=y
 S:CONFIG_SPL_NAND_DENALI=y
index 658977bcf6293f8b58e358c1c2bc8d75d0050342..4e8f354c9b596a30fe5eba2429477e1ef0d9b17a 100644 (file)
@@ -2,7 +2,10 @@ CONFIG_SPL=y
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_UNIPHIER=y
 +S:CONFIG_MACH_PH1_SLD8=y
+CONFIG_DM=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
+CONFIG_DM_SERIAL=y
+CONFIG_UNIPHIER_SERIAL=y
 S:CONFIG_SPL_NAND_DENALI=y
index cfd77b0ff567cbacd4f5a3e6223e2edeb28fbd69..43485c9148b0f404e91cb0f45f9a3c76b2267578 100644 (file)
@@ -57,7 +57,7 @@ static const struct block_drvr block_drvr[] = {
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef HAVE_BLOCK_DEVICE
-block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
+static block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
 {
        const struct block_drvr *drvr = block_drvr;
        block_dev_desc_t* (*reloc_get_dev)(int dev);
diff --git a/doc/device-tree-bindings/mtd/spi/spi-flash.txt b/doc/device-tree-bindings/mtd/spi/spi-flash.txt
new file mode 100644 (file)
index 0000000..85522d8
--- /dev/null
@@ -0,0 +1,25 @@
+* MTD SPI driver for serial flash chips
+
+Required properties:
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+  representing partitions.
+- compatible : Should be the manufacturer and the name of the chip. Bear in
+               mind that the DT binding is not U-Boot-only, but in case of
+               U-Boot, see spi_flash_params_table table in
+               drivers/mtd/spi/sf_params.c for the list of supported chips.
+- reg : Chip-Select number
+- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
+
+Optional properties:
+ - memory-map : Address and size of the flash, if memory mapped. This may
+                apply to Intel chipsets, which tend to memory-map flash.
+
+Example:
+
+       flash: m25p80@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spansion,m25p80";
+               reg = <0>;
+               spi-max-frequency = <40000000>;
+       };
diff --git a/doc/device-tree-bindings/spi/soft-spi.txt b/doc/device-tree-bindings/spi/soft-spi.txt
new file mode 100644 (file)
index 0000000..d09c1a5
--- /dev/null
@@ -0,0 +1,34 @@
+Soft SPI
+
+The soft SPI bus implementation allows the use of GPIO pins to simulate a
+SPI bus. No SPI host is required for this to work. The down-side is that the
+performance will typically be much lower than a real SPI bus.
+
+The soft SPI node requires the following properties:
+
+compatible: "u-boot,soft-spi"
+soft_spi_cs: GPIO number to use for SPI chip select (output)
+soft_spi_sclk: GPIO number to use for SPI clock (output)
+soft_spi_mosi: GPIO number to use for SPI MOSI line (output)
+soft_spi_miso GPIO number to use for SPI MISO line (input)
+spi-delay-us: Number of microseconds of delay between each CS transition
+
+The GPIOs should be specified as required by the GPIO controller referenced.
+The first cell holds the phandle of the controller and the second cell
+typically holds the GPIO number.
+
+
+Example:
+
+       soft-spi {
+               compatible = "u-boot,soft-spi";
+               cs-gpio = <&gpio 235 0>;        /* Y43 */
+               sclk-gpio = <&gpio 225 0>;      /* Y31 */
+               mosi-gpio = <&gpio 227 0>;      /* Y33 */
+               miso-gpio = <&gpio 224 0>;      /* Y30 */
+               spi-delay-us = <1>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cs@0 {
+               };
+       };
index f9b68beb6f6d663bba7d0da97fdea32024b337fa..0278dda4d77045a7dbcc8400b1d5593252b4f514 100644 (file)
@@ -95,7 +95,7 @@ are provided in test/dm. To run them, try:
 You should see something like this:
 
     <...U-Boot banner...>
-    Running 21 driver model tests
+    Running 29 driver model tests
     Test: dm_test_autobind
     Test: dm_test_autoprobe
     Test: dm_test_bus_children
@@ -103,6 +103,7 @@ You should see something like this:
     Device 'c-test@0': seq 0 is in use by 'a-test'
     Device 'c-test@1': seq 1 is in use by 'd-test'
     Test: dm_test_bus_children_funcs
+    Test: dm_test_bus_children_iterators
     Test: dm_test_bus_parent_data
     Test: dm_test_bus_parent_ops
     Test: dm_test_children
@@ -114,7 +115,12 @@ You should see something like this:
     Device 'd-test': seq 3 is in use by 'b-test'
     Device 'a-test': seq 0 is in use by 'd-test'
     Test: dm_test_gpio
-    sandbox_gpio: sb_gpio_get_value: error: offset 4 not reserved
+    extra-gpios: get_value: error: gpio b5 not reserved
+    Test: dm_test_gpio_anon
+    Test: dm_test_gpio_copy
+    Test: dm_test_gpio_leak
+    extra-gpios: get_value: error: gpio b5 not reserved
+    Test: dm_test_gpio_requestf
     Test: dm_test_leak
     Test: dm_test_lifecycle
     Test: dm_test_operations
@@ -122,6 +128,26 @@ You should see something like this:
     Test: dm_test_platdata
     Test: dm_test_pre_reloc
     Test: dm_test_remove
+    Test: dm_test_spi_find
+    Invalid chip select 0:0 (err=-19)
+    SF: Failed to get idcodes
+    Device 'name-emul': seq 0 is in use by 'name-emul'
+    SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
+    Test: dm_test_spi_flash
+    2097152 bytes written in 0 ms
+    SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
+    SPI flash test:
+    0 erase: 0 ticks, 65536000 KiB/s 524288.000 Mbps
+    1 check: 0 ticks, 65536000 KiB/s 524288.000 Mbps
+    2 write: 0 ticks, 65536000 KiB/s 524288.000 Mbps
+    3 read: 0 ticks, 65536000 KiB/s 524288.000 Mbps
+    Test passed
+    0 erase: 0 ticks, 65536000 KiB/s 524288.000 Mbps
+    1 check: 0 ticks, 65536000 KiB/s 524288.000 Mbps
+    2 write: 0 ticks, 65536000 KiB/s 524288.000 Mbps
+    3 read: 0 ticks, 65536000 KiB/s 524288.000 Mbps
+    Test: dm_test_spi_xfer
+    SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
     Test: dm_test_uclass
     Test: dm_test_uclass_before_ready
     Failures: 0
@@ -358,7 +384,9 @@ Device Sequence Numbers
 U-Boot numbers devices from 0 in many situations, such as in the command
 line for I2C and SPI buses, and the device names for serial ports (serial0,
 serial1, ...). Driver model supports this numbering and permits devices
-to be locating by their 'sequence'.
+to be locating by their 'sequence'. This numbering unique identifies a
+device in its uclass, so no two devices within a particular uclass can have
+the same sequence number.
 
 Sequence numbers start from 0 but gaps are permitted. For example, a board
 may have I2C buses 0, 1, 4, 5 but no 2 or 3. The choice of how devices are
diff --git a/doc/driver-model/spi-howto.txt b/doc/driver-model/spi-howto.txt
new file mode 100644 (file)
index 0000000..719dbd5
--- /dev/null
@@ -0,0 +1,594 @@
+How to port a SPI driver to driver model
+========================================
+
+Here is a rough step-by-step guide. It is based around converting the
+exynos SPI driver to driver model (DM) and the example code is based
+around U-Boot v2014.10-rc2 (commit be9f643).
+
+It is quite long since it includes actual code examples.
+
+Before driver model, SPI drivers have their own private structure which
+contains 'struct spi_slave'. With driver model, 'struct spi_slave' still
+exists, but now it is 'per-child data' for the SPI bus. Each child of the
+SPI bus is a SPI slave. The information that was stored in the
+driver-specific slave structure can now be port in private data for the
+SPI bus.
+
+For example, struct tegra_spi_slave looks like this:
+
+struct tegra_spi_slave {
+       struct spi_slave slave;
+       struct tegra_spi_ctrl *ctrl;
+};
+
+In this case 'slave' will be in per-child data, and 'ctrl' will be in the
+SPI's buses private data.
+
+
+0. How long does this take?
+
+You should be able to complete this within 2 hours, including testing but
+excluding preparing the patches. The API is basically the same as before
+with only minor changes:
+
+- methods to set speed and mode are separated out
+- cs_info is used to get information on a chip select
+
+
+1. Enable driver mode for SPI and SPI flash
+
+Add these to your board config:
+
+#define CONFIG_DM_SPI
+#define CONFIG_DM_SPI_FLASH
+
+
+2. Add the skeleton
+
+Put this code at the bottom of your existing driver file:
+
+struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
+                       unsigned int max_hz, unsigned int mode)
+{
+       return NULL;
+}
+
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
+                                     int spi_node)
+{
+       return NULL;
+}
+
+static int exynos_spi_ofdata_to_platdata(struct udevice *dev)
+{
+       return -ENODEV;
+}
+
+static int exynos_spi_probe(struct udevice *dev)
+{
+       return -ENODEV;
+}
+
+static int exynos_spi_remove(struct udevice *dev)
+{
+       return -ENODEV;
+}
+
+static int exynos_spi_claim_bus(struct udevice *dev)
+{
+
+       return -ENODEV;
+}
+
+static int exynos_spi_release_bus(struct udevice *dev)
+{
+
+       return -ENODEV;
+}
+
+static int exynos_spi_xfer(struct udevice *dev, unsigned int bitlen,
+                           const void *dout, void *din, unsigned long flags)
+{
+
+       return -ENODEV;
+}
+
+static int exynos_spi_set_speed(struct udevice *dev, uint speed)
+{
+       return -ENODEV;
+}
+
+static int exynos_spi_set_mode(struct udevice *dev, uint mode)
+{
+       return -ENODEV;
+}
+
+static int exynos_cs_info(struct udevice *bus, uint cs,
+                         struct spi_cs_info *info)
+{
+       return -ENODEV;
+}
+
+static const struct dm_spi_ops exynos_spi_ops = {
+       .claim_bus      = exynos_spi_claim_bus,
+       .release_bus    = exynos_spi_release_bus,
+       .xfer           = exynos_spi_xfer,
+       .set_speed      = exynos_spi_set_speed,
+       .set_mode       = exynos_spi_set_mode,
+       .cs_info        = exynos_cs_info,
+};
+
+static const struct udevice_id exynos_spi_ids[] = {
+       { .compatible = "samsung,exynos-spi" },
+       { }
+};
+
+U_BOOT_DRIVER(exynos_spi) = {
+       .name   = "exynos_spi",
+       .id     = UCLASS_SPI,
+       .of_match = exynos_spi_ids,
+       .ops    = &exynos_spi_ops,
+       .ofdata_to_platdata = exynos_spi_ofdata_to_platdata,
+       .probe  = exynos_spi_probe,
+       .remove = exynos_spi_remove,
+};
+
+
+3. Replace 'exynos' in the above code with your driver name
+
+
+4. #ifdef out all of the code in your driver except for the above
+
+This will allow you to get it building, which means you can work
+incrementally. Since all the methods return an error initially, there is
+less chance that you will accidentally leave something in.
+
+Also, even though your conversion is basically a rewrite, it might help
+reviewers if you leave functions in the same place in the file,
+particularly for large drivers.
+
+
+5. Add some includes
+
+Add these includes to your driver:
+
+#include <dm.h>
+#include <errno.h>
+
+
+6. Build
+
+At this point you should be able to build U-Boot for your board with the
+empty SPI driver. You still have empty methods in your driver, but we will
+write these one by one.
+
+If you have spi_init() functions or the like that are called from your
+board then the build will fail. Remove these calls and make a note of the
+init that needs to be done.
+
+
+7. Set up your platform data structure
+
+This will hold the information your driver to operate, like its hardware
+address or maximum frequency.
+
+You may already have a struct like this, or you may need to create one
+from some of the #defines or global variables in the driver.
+
+Note that this information is not the run-time information. It should not
+include state that changes. It should be fixed throughout the live of
+U-Boot. Run-time information comes later.
+
+Here is what was in the exynos spi driver:
+
+struct spi_bus {
+       enum periph_id periph_id;
+       s32 frequency;          /* Default clock frequency, -1 for none */
+       struct exynos_spi *regs;
+       int inited;             /* 1 if this bus is ready for use */
+       int node;
+       uint deactivate_delay_us;       /* Delay to wait after deactivate */
+};
+
+Of these, inited is handled by DM and node is the device tree node, which
+DM tells you. The name is not quite right. So in this case we would use:
+
+struct exynos_spi_platdata {
+       enum periph_id periph_id;
+       s32 frequency;          /* Default clock frequency, -1 for none */
+       struct exynos_spi *regs;
+       uint deactivate_delay_us;       /* Delay to wait after deactivate */
+};
+
+
+8a. Write ofdata_to_platdata()   [for device tree only]
+
+This method will convert information in the device tree node into a C
+structure in your driver (called platform data). If you are not using
+device tree, go to 8b.
+
+DM will automatically allocate the struct for us when we are using device
+tree, but we need to tell it the size:
+
+U_BOOT_DRIVER(spi_exynos) = {
+...
+       .platdata_auto_alloc_size = sizeof(struct exynos_spi_platdata),
+
+
+Here is a sample function. It gets a pointer to the platform data and
+fills in the fields from device tree.
+
+static int exynos_spi_ofdata_to_platdata(struct udevice *bus)
+{
+       struct exynos_spi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
+
+       plat->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
+       plat->periph_id = pinmux_decode_periph_id(blob, node);
+
+       if (plat->periph_id == PERIPH_ID_NONE) {
+               debug("%s: Invalid peripheral ID %d\n", __func__,
+                       plat->periph_id);
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       /* Use 500KHz as a suitable default */
+       plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+                                       500000);
+       plat->deactivate_delay_us = fdtdec_get_int(blob, node,
+                                       "spi-deactivate-delay", 0);
+       debug("%s: regs=%p, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
+             __func__, plat->regs, plat->periph_id, plat->frequency,
+              plat->deactivate_delay_us);
+
+       return 0;
+}
+
+
+8b. Add the platform data  [non-device-tree only]
+
+Specify this data in a U_BOOT_DEVICE() declaration in your board file:
+
+struct exynos_spi_platdata platdata_spi0 = {
+       .periph_id = ...
+       .frequency = ...
+       .regs = ...
+       .deactivate_delay_us = ...
+};
+
+U_BOOT_DEVICE(board_spi0) = {
+       .name = "exynos_spi",
+       .platdata = &platdata_spi0,
+};
+
+You will unfortunately need to put the struct into a header file in this
+case so that your board file can use it.
+
+
+9. Add the device private data
+
+Most devices have some private data which they use to keep track of things
+while active. This is the run-time information and needs to be stored in
+a structure. There is probably a structure in the driver that includes a
+'struct spi_slave', so you can use that.
+
+struct exynos_spi_slave {
+       struct spi_slave slave;
+       struct exynos_spi *regs;
+       unsigned int freq;              /* Default frequency */
+       unsigned int mode;
+       enum periph_id periph_id;       /* Peripheral ID for this device */
+       unsigned int fifo_size;
+       int skip_preamble;
+       struct spi_bus *bus;            /* Pointer to our SPI bus info */
+       ulong last_transaction_us;      /* Time of last transaction end */
+};
+
+
+We should rename this to make its purpose more obvious, and get rid of
+the slave structure, so we have:
+
+struct exynos_spi_priv {
+       struct exynos_spi *regs;
+       unsigned int freq;              /* Default frequency */
+       unsigned int mode;
+       enum periph_id periph_id;       /* Peripheral ID for this device */
+       unsigned int fifo_size;
+       int skip_preamble;
+       ulong last_transaction_us;      /* Time of last transaction end */
+};
+
+
+DM can auto-allocate this also:
+
+U_BOOT_DRIVER(spi_exynos) = {
+...
+       .priv_auto_alloc_size = sizeof(struct exynos_spi_priv),
+
+
+Note that this is created before the probe method is called, and destroyed
+after the remove method is called. It will be zeroed when the probe
+method is called.
+
+
+10. Add the probe() and remove() methods
+
+Note: It's a good idea to build repeatedly as you are working, to avoid a
+huge amount of work getting things compiling at the end.
+
+The probe method is supposed to set up the hardware. U-Boot used to use
+spi_setup_slave() to do this. So take a look at this function and see
+what you can copy out to set things up.
+
+
+static int exynos_spi_probe(struct udevice *bus)
+{
+       struct exynos_spi_platdata *plat = dev_get_platdata(bus);
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+       priv->regs = plat->regs;
+       if (plat->periph_id == PERIPH_ID_SPI1 ||
+           plat->periph_id == PERIPH_ID_SPI2)
+               priv->fifo_size = 64;
+       else
+               priv->fifo_size = 256;
+
+       priv->skip_preamble = 0;
+       priv->last_transaction_us = timer_get_us();
+       priv->freq = plat->frequency;
+       priv->periph_id = plat->periph_id;
+
+       return 0;
+}
+
+This implementation doesn't actually touch the hardware, which is somewhat
+unusual for a driver. In this case we will do that when the device is
+claimed by something that wants to use the SPI bus.
+
+For remove we could shut down the clocks, but in this case there is
+nothing to do. DM frees any memory that it allocated, so we can just
+remove exynos_spi_remove() and its reference in U_BOOT_DRIVER.
+
+
+11. Implement set_speed()
+
+This should set up clocks so that the SPI bus is running at the right
+speed. With the old API spi_claim_bus() would normally do this and several
+of the following functions, so let's look at that function:
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+       struct exynos_spi *regs = spi_slave->regs;
+       u32 reg = 0;
+       int ret;
+
+       ret = set_spi_clk(spi_slave->periph_id,
+                                       spi_slave->freq);
+       if (ret < 0) {
+               debug("%s: Failed to setup spi clock\n", __func__);
+               return ret;
+       }
+
+       exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
+
+       spi_flush_fifo(slave);
+
+       reg = readl(&regs->ch_cfg);
+       reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
+
+       if (spi_slave->mode & SPI_CPHA)
+               reg |= SPI_CH_CPHA_B;
+
+       if (spi_slave->mode & SPI_CPOL)
+               reg |= SPI_CH_CPOL_L;
+
+       writel(reg, &regs->ch_cfg);
+       writel(SPI_FB_DELAY_180, &regs->fb_clk);
+
+       return 0;
+}
+
+
+It sets up the speed, mode, pinmux, feedback delay and clears the FIFOs.
+With DM these will happen in separate methods.
+
+
+Here is an example for the speed part:
+
+static int exynos_spi_set_speed(struct udevice *bus, uint speed)
+{
+       struct exynos_spi_platdata *plat = bus->platdata;
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+       int ret;
+
+       if (speed > plat->frequency)
+               speed = plat->frequency;
+       ret = set_spi_clk(priv->periph_id, speed);
+       if (ret)
+               return ret;
+       priv->freq = speed;
+       debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
+
+       return 0;
+}
+
+
+12. Implement set_mode()
+
+This should adjust the SPI mode (polarity, etc.). Again this code probably
+comes from the old spi_claim_bus(). Here is an example:
+
+
+static int exynos_spi_set_mode(struct udevice *bus, uint mode)
+{
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+       uint32_t reg;
+
+       reg = readl(&priv->regs->ch_cfg);
+       reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
+
+       if (mode & SPI_CPHA)
+               reg |= SPI_CH_CPHA_B;
+
+       if (mode & SPI_CPOL)
+               reg |= SPI_CH_CPOL_L;
+
+       writel(reg, &priv->regs->ch_cfg);
+       priv->mode = mode;
+       debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
+
+       return 0;
+}
+
+
+13. Implement claim_bus()
+
+This is where a client wants to make use of the bus, so claims it first.
+At this point we need to make sure everything is set up ready for data
+transfer. Note that this function is wholly internal to the driver - at
+present the SPI uclass never calls it.
+
+Here again we look at the old claim function and see some code that is
+needed. It is anything unrelated to speed and mode:
+
+static int exynos_spi_claim_bus(struct udevice *bus)
+{
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+       exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE);
+       spi_flush_fifo(priv->regs);
+
+       writel(SPI_FB_DELAY_180, &priv->regs->fb_clk);
+
+       return 0;
+}
+
+The spi_flush_fifo() function is in the removed part of the code, so we
+need to expose it again (perhaps with an #endif before it and '#if 0'
+after it). It only needs access to priv->regs which is why we have
+passed that in:
+
+/**
+ * Flush spi tx, rx fifos and reset the SPI controller
+ *
+ * @param regs Pointer to SPI registers
+ */
+static void spi_flush_fifo(struct exynos_spi *regs)
+{
+       clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
+       clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+       setbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
+}
+
+
+14. Implement release_bus()
+
+This releases the bus - in our example the old code in spi_release_bus()
+is a call to spi_flush_fifo, so we add:
+
+static int exynos_spi_release_bus(struct udevice *bus)
+{
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+       spi_flush_fifo(priv->regs);
+
+       return 0;
+}
+
+
+15. Implement xfer()
+
+This is the final method that we need to create, and it is where all the
+work happens. The method parameters are the same as the old spi_xfer() with
+the addition of a 'struct udevice' so conversion is pretty easy. Start
+by copying the contents of spi_xfer() to your new xfer() method and proceed
+from there.
+
+If (flags & SPI_XFER_BEGIN) is non-zero then xfer() normally calls an
+activate function, something like this:
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+       /* If it's too soon to do another transaction, wait */
+       if (spi_slave->bus->deactivate_delay_us &&
+           spi_slave->last_transaction_us) {
+               ulong delay_us;         /* The delay completed so far */
+               delay_us = timer_get_us() - spi_slave->last_transaction_us;
+               if (delay_us < spi_slave->bus->deactivate_delay_us)
+                       udelay(spi_slave->bus->deactivate_delay_us - delay_us);
+       }
+
+       clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+       debug("Activate CS, bus %d\n", spi_slave->slave.bus);
+       spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
+}
+
+The new version looks like this:
+
+static void spi_cs_activate(struct udevice *dev)
+{
+       struct udevice *bus = dev->parent;
+       struct exynos_spi_platdata *pdata = dev_get_platdata(bus);
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+       /* If it's too soon to do another transaction, wait */
+       if (pdata->deactivate_delay_us &&
+           priv->last_transaction_us) {
+               ulong delay_us;         /* The delay completed so far */
+               delay_us = timer_get_us() - priv->last_transaction_us;
+               if (delay_us < pdata->deactivate_delay_us)
+                       udelay(pdata->deactivate_delay_us - delay_us);
+       }
+
+       clrbits_le32(&priv->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+       debug("Activate CS, bus '%s'\n", bus->name);
+       priv->skip_preamble = priv->mode & SPI_PREAMBLE;
+}
+
+All we have really done here is change the pointers and print the device name
+instead of the bus number. Other local static functions can be treated in
+the same way.
+
+
+16. Set up the per-child data and child pre-probe function
+
+To minimise the pain and complexity of the SPI subsystem while the driver
+model change-over is in place, struct spi_slave is used to reference a
+SPI bus slave, even though that slave is actually a struct udevice. In fact
+struct spi_slave is the device's child data. We need to make sure this space
+is available. It is possible to allocate more space that struct spi_slave
+needs, but this is the minimum.
+
+U_BOOT_DRIVER(exynos_spi) = {
+...
+       .per_child_auto_alloc_size      = sizeof(struct spi_slave),
+}
+
+
+17. Optional: Set up cs_info() if you want it
+
+Sometimes it is useful to know whether a SPI chip select is valid, but this
+is not obvious from outside the driver. In this case you can provide a
+method for cs_info() to deal with this. If you don't provide it, then the
+device tree will be used to determine what chip selects are valid.
+
+Return -ENODEV if the supplied chip select is invalid, or 0 if it is valid.
+If you don't provide the cs_info() method, -ENODEV is assumed for all
+chip selects that do not appear in the device tree.
+
+
+18. Test it
+
+Now that you have the code written and it compiles, try testing it using
+the 'sf test' command. You may need to enable CONFIG_CMD_SF_TEST for your
+board.
+
+
+19. Prepare patches and send them to the mailing lists
+
+You can use 'tools/patman/patman' to prepare, check and send patches for
+your work. See the README for details.
index ef3ab8f726a1326e0e878bd75ae3254e08dd6b26..539cdbfafec0d8f63d3cd298323525f2f3e04cb7 100644 (file)
                };
        };
 };
+
+
+
+For x86 a setup node is also required: see x86-fit-boot.txt.
+
+/dts-v1/;
+
+/ {
+       description = "Simple image with single Linux kernel on x86";
+       #address-cells = <1>;
+
+       images {
+               kernel@1 {
+                       description = "Vanilla Linux kernel";
+                       data = /incbin/("./image.bin.lzo");
+                       type = "kernel";
+                       arch = "x86";
+                       os = "linux";
+                       compression = "lzo";
+                       load = <0x01000000>;
+                       entry = <0x00000000>;
+                       hash@2 {
+                               algo = "sha1";
+                       };
+               };
+
+               setup@1 {
+                       description = "Linux setup.bin";
+                       data = /incbin/("./setup.bin");
+                       type = "x86_setup";
+                       arch = "x86";
+                       os = "linux";
+                       compression = "none";
+                       load = <0x00090000>;
+                       entry = <0x00090000>;
+                       hash@2 {
+                               algo = "sha1";
+                       };
+               };
+       };
+
+       configurations {
+               default = "config@1";
+               config@1 {
+                       description = "Boot Linux kernel";
+                       kernel = "kernel@1";
+                       setup = "setup@1";
+               };
+       };
+};
index 9ed6f65e599383f837cc611e43d2c05a659b956c..b47ce73b8323a4034bbd58c77ce50d49f5492b38 100644 (file)
@@ -55,7 +55,7 @@ FIT is formally a flattened device tree (in the libfdt meaning), which
 conforms to bindings defined in this document.
 
 .its   - image tree source
-.itb   - image tree blob
+.fit   - flattened image tree blob
 
 c) Image building procedure
 
@@ -101,15 +101,15 @@ Root node of the uImage Tree should have the following layout:
     |
     o images
     | |
-    | o img@1 {...}
-    | o img@2 {...}
+    | o image@1 {...}
+    | o image@2 {...}
     | ...
     |
     o configurations
-      |- default = "cfg@1"
+      |- default = "conf@1"
       |
-      o cfg@1 {...}
-      o cfg@2 {...}
+      o conf@1 {...}
+      o conf@2 {...}
       ...
 
 
@@ -159,7 +159,7 @@ the '/images' node should have the following layout:
   - description : Textual description of the component sub-image
   - type : Name of component sub-image type, supported types are:
     "standalone", "kernel", "ramdisk", "firmware", "script", "filesystem",
-    "flat_dt".
+    "flat_dt" and others (see uimage_type in common/images.c).
   - data : Path to the external file which contains this node's binary data.
   - compression : Compression used by included data. Supported compressions
     are "gzip" and "bzip2". If no compression is used compression property
@@ -173,7 +173,8 @@ the '/images' node should have the following layout:
   - arch : Architecture name, mandatory for types: "standalone", "kernel",
     "firmware", "ramdisk" and "fdt". Valid architecture names are: "alpha",
     "arm", "i386", "ia64", "mips", "mips64", "ppc", "s390", "sh", "sparc",
-    "sparc64", "m68k", "microblaze", "nios2", "blackfin", "avr32", "st200".
+    "sparc64", "m68k", "microblaze", "nios2", "blackfin", "avr32", "st200",
+    "sandbox".
   - entry : entry point address, address size is determined by
     '#address-cells' property of the root node. Mandatory for for types:
     "standalone" and "kernel".
@@ -246,6 +247,8 @@ o config@1
     node of a "ramdisk" type).
   - fdt : Unit name of the corresponding fdt blob (component image node of a
     "fdt type").
+  - setup : Unit name of the corresponding setup binary (used for booting
+    an x86 kernel). This contains the setup.bin file built by the kernel.
 
 The FDT blob is required to properly boot FDT based kernel, so the minimal
 configuration for 2.6 FDT kernel is (kernel, fdt) pair.
diff --git a/doc/uImage.FIT/x86-fit-boot.txt b/doc/uImage.FIT/x86-fit-boot.txt
new file mode 100644 (file)
index 0000000..61c10ff
--- /dev/null
@@ -0,0 +1,276 @@
+Booting Linux on x86 with FIT
+=============================
+
+Background
+----------
+
+(corrections to the text below are welcome)
+
+Generally Linux x86 uses its own very complex booting method. There is a setup
+binary which contains all sorts of parameters and a compressed self-extracting
+binary for the kernel itself, often with a small built-in serial driver to
+display decompression progress.
+
+The x86 CPU has various processor modes. I am no expert on these, but my
+understanding is that an x86 CPU (even a really new one) starts up in a 16-bit
+'real' mode where only 1MB of memory is visible, moves to 32-bit 'protected'
+mode where 4GB is visible (or more with special memory access techniques) and
+then to 64-bit 'long' mode if 64-bit execution is required.
+
+Partly the self-extracting nature of Linux was introduced to cope with boot
+loaders that were barely capable of loading anything. Even changing to 32-bit
+mode was something of a challenge, so putting this logic in the kernel seemed
+to make sense.
+
+Bit by bit more and more logic has been added to this post-boot pre-Linux
+wrapper:
+
+- Changing to 32-bit mode
+- Decompression
+- Serial output (with drivers for various chips)
+- Load address randomisation
+- Elf loader complete with relocation (for the above)
+- Random number generator via 3 methods (again for the above)
+- Some sort of EFI mini-loader (1000+ glorious lines of code)
+- Locating and tacking on a device tree and ramdisk
+
+To my mind, if you sit back and look at things from first principles, this
+doesn't make a huge amount of sense. Any boot loader worth its salts already
+has most of the above features and more besides. The boot loader already knows
+the layout of memory, has a serial driver, can decompress things, includes an
+ELF loader and supports device tree and ramdisks. The decision to duplicate
+all these features in a Linux wrapper caters for the lowest common
+denominator: a boot loader which consists of a BIOS call to load something off
+disk, followed by a jmp instruction.
+
+(Aside: On ARM systems, we worry that the boot loader won't know where to load
+the kernel. It might be easier to just provide that information in the image,
+or in the boot loader rather than adding a self-relocator to put it in the
+right place. Or just use ELF?
+
+As a result, the x86 kernel boot process is needlessly complex. The file
+format is also complex, and obfuscates the contents to a degree that it is
+quite a challenge to extract anything from it. This bzImage format has become
+so prevalent that is actually isn't possible to produce the 'raw' kernel build
+outputs with the standard Makefile (as it is on ARM for example, at least at
+the time of writing).
+
+This document describes an alternative boot process which uses simple raw
+images which are loaded into the right place by the boot loader and then
+executed.
+
+
+Build the kernel
+----------------
+
+Note: these instructions assume a 32-bit kernel. U-Boot does not currently
+support booting a 64-bit kernel as it has no way of going into 64-bit mode on
+x86.
+
+You can build the kernel as normal with 'make'. This will create a file called
+'vmlinux'. This is a standard ELF file and you can look at it if you like:
+
+$ objdump -h vmlinux
+
+vmlinux:     file format elf32-i386
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         00416850  81000000  01000000  00001000  2**5
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
+  1 .notes        00000024  81416850  01416850  00417850  2**2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 __ex_table    00000c50  81416880  01416880  00417880  2**3
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+  3 .rodata       00154b9e  81418000  01418000  00419000  2**5
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+  4 __bug_table   0000597c  8156cba0  0156cba0  0056dba0  2**0
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+  5 .pci_fixup    00001b80  8157251c  0157251c  0057351c  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+  6 .tracedata    00000024  8157409c  0157409c  0057509c  2**0
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+  7 __ksymtab     00007ec0  815740c0  015740c0  005750c0  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+  8 __ksymtab_gpl 00004a28  8157bf80  0157bf80  0057cf80  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+  9 __ksymtab_strings 0001d6fc  815809a8  015809a8  005819a8  2**0
+                  CONTENTS, ALLOC, LOAD, READONLY, DATA
+ 10 __init_rodata 00001c3c  8159e0a4  0159e0a4  0059f0a4  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+ 11 __param       00000ff0  8159fce0  0159fce0  005a0ce0  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+ 12 __modver      00000330  815a0cd0  015a0cd0  005a1cd0  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+ 13 .data         00063000  815a1000  015a1000  005a2000  2**12
+                  CONTENTS, ALLOC, LOAD, RELOC, DATA
+ 14 .init.text    0002f104  81604000  01604000  00605000  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
+ 15 .init.data    00040cdc  81634000  01634000  00635000  2**12
+                  CONTENTS, ALLOC, LOAD, RELOC, DATA
+ 16 .x86_cpu_dev.init 0000001c  81674cdc  01674cdc  00675cdc  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+ 17 .altinstructions 0000267c  81674cf8  01674cf8  00675cf8  2**0
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+ 18 .altinstr_replacement 00000942  81677374  01677374  00678374  2**0
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+ 19 .iommu_table  00000014  81677cb8  01677cb8  00678cb8  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+ 20 .apicdrivers  00000004  81677cd0  01677cd0  00678cd0  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, DATA
+ 21 .exit.text    00001a80  81677cd8  01677cd8  00678cd8  2**0
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
+ 22 .data..percpu 00007880  8167a000  0167a000  0067b000  2**12
+                  CONTENTS, ALLOC, LOAD, RELOC, DATA
+ 23 .smp_locks    00003000  81682000  01682000  00683000  2**2
+                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
+ 24 .bss          000a1000  81685000  01685000  00686000  2**12
+                  ALLOC
+ 25 .brk          00424000  81726000  01726000  00686000  2**0
+                  ALLOC
+ 26 .comment      00000049  00000000  00000000  00686000  2**0
+                  CONTENTS, READONLY
+ 27 .GCC.command.line 0003e055  00000000  00000000  00686049  2**0
+                  CONTENTS, READONLY
+ 28 .debug_aranges 0000f4c8  00000000  00000000  006c40a0  2**3
+                  CONTENTS, RELOC, READONLY, DEBUGGING
+ 29 .debug_info   0440b0df  00000000  00000000  006d3568  2**0
+                  CONTENTS, RELOC, READONLY, DEBUGGING
+ 30 .debug_abbrev 0022a83b  00000000  00000000  04ade647  2**0
+                  CONTENTS, READONLY, DEBUGGING
+ 31 .debug_line   004ead0d  00000000  00000000  04d08e82  2**0
+                  CONTENTS, RELOC, READONLY, DEBUGGING
+ 32 .debug_frame  0010a960  00000000  00000000  051f3b90  2**2
+                  CONTENTS, RELOC, READONLY, DEBUGGING
+ 33 .debug_str    001b442d  00000000  00000000  052fe4f0  2**0
+                  CONTENTS, READONLY, DEBUGGING
+ 34 .debug_loc    007c7fa9  00000000  00000000  054b291d  2**0
+                  CONTENTS, RELOC, READONLY, DEBUGGING
+ 35 .debug_ranges 00098828  00000000  00000000  05c7a8c8  2**3
+                  CONTENTS, RELOC, READONLY, DEBUGGING
+
+There is also the setup binary mentioned earlier. This is at
+arch/x86/boot/setup.bin and is about 12KB in size. It includes the command
+line and various settings need by the kernel. Arguably the boot loader should
+provide all of this also, but setting it up is some complex that the kernel
+helps by providing a head start.
+
+As you can see the code loads to address 0x01000000 and everything else
+follows after that. We could load this image using the 'bootelf' command but
+we would still need to provide the setup binary. This is not supported by
+U-Boot although I suppose you could mostly script it. This would permit the
+use of a relocatable kernel.
+
+All we need to boot is the vmlinux file and the setup.bin file.
+
+
+Create a FIT
+------------
+
+To create a FIT you will need a source file describing what should go in the
+FIT. See kernel.its for an example for x86. Put this into a file called
+image.its.
+
+Note that setup is loaded to the special address of 0x90000 (a special address
+you just have to know) and the kernel is loaded to 0x01000000 (the address you
+saw above). This means that you will need to load your FIT to a different
+address so that U-Boot doesn't overwrite it when decompressing. Something like
+0x02000000 will do so you can set CONFIG_SYS_LOAD_ADDR to that.
+
+In that example the kernel is compressed with lzo. Also we need to provide a
+flat binary, not an ELF. So the steps needed to set things are are:
+
+   # Create a flat binary
+   objcopy -O binary vmlinux vmlinux.bin
+
+   # Compress it into LZO format
+   lzop vmlinux.bin
+
+   # Build a FIT image
+   mkimage -f image.its image.fit
+
+(be careful to run the mkimage from your U-Boot tools directory since it
+will have x86_setup support.)
+
+You can take a look at the resulting fit file if you like:
+
+$ dumpimage -l image.fit
+FIT description: Simple image with single Linux kernel on x86
+Created:         Tue Oct  7 10:57:24 2014
+ Image 0 (kernel@1)
+  Description:  Vanilla Linux kernel
+  Created:      Tue Oct  7 10:57:24 2014
+  Type:         Kernel Image
+  Compression:  lzo compressed
+  Data Size:    4591767 Bytes = 4484.15 kB = 4.38 MB
+  Architecture: Intel x86
+  OS:           Linux
+  Load Address: 0x01000000
+  Entry Point:  0x00000000
+  Hash algo:    sha1
+  Hash value:   446b5163ebfe0fb6ee20cbb7a8501b263cd92392
+ Image 1 (setup@1)
+  Description:  Linux setup.bin
+  Created:      Tue Oct  7 10:57:24 2014
+  Type:         x86 setup.bin
+  Compression:  uncompressed
+  Data Size:    12912 Bytes = 12.61 kB = 0.01 MB
+  Hash algo:    sha1
+  Hash value:   a1f2099cf47ff9816236cd534c77af86e713faad
+ Default Configuration: 'config@1'
+ Configuration 0 (config@1)
+  Description:  Boot Linux kernel
+  Kernel:       kernel@1
+
+
+Booting the FIT
+---------------
+
+To make it boot you need to load it and then use 'bootm' to boot it. A
+suitable script to do this from a network server is:
+
+   bootp
+   tftp image.fit
+   bootm
+
+This will load the image from the network and boot it. The command line (from
+the 'bootargs' environment variable) will be passed to the kernel.
+
+If you want a ramdisk you can add it as normal with FIT. If you want a device
+tree then x86 doesn't normally use those - it has ACPI instead.
+
+
+Why Bother?
+-----------
+
+1. It demystifies the process of booting an x86 kernel
+2. It allows use of the standard U-Boot boot file format
+3. It allows U-Boot to perform decompression - problems will provide an error
+message and you are still in the boot loader. It is possible to investigate.
+4. It avoids all the pre-loader code in the kernel which is quite complex to
+follow
+5. You can use verified/secure boot and other features which haven't yet been
+added to the pre-Linux
+6. It makes x86 more like other architectures in the way it boots a kernel.
+You can potentially use the same file format for the kernel, and the same
+procedure for building and packaging it.
+
+
+References
+----------
+
+In the Linux kernel, Documentation/x86/boot.txt defines the boot protocol for
+the kernel including the setup.bin format. This is handled in U-Boot in
+arch/x86/lib/zimage.c and arch/x86/lib/bootm.c.
+
+The procedure for entering 64-bit mode on x86 seems to be described here:
+
+   http://wiki.osdev.org/64-bit_Higher_Half_Kernel_with_GRUB_2
+
+Various files in the same directory as this file describe the FIT format.
+
+
+--
+Simon Glass
+sjg@chromium.org
+7-Oct-2014
index 574bc40b10e138a09200b8e3187d5295696b485f..e54d564bf764d0a6015bf84fc1c6cfd3999eeacd 100644 (file)
@@ -12,7 +12,7 @@
 #if defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
 #elif defined(CONFIG_KIRKWOOD)
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #endif
 
 /* SATA port registers */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d2799dc861ff5a661ff6717c985285f263ebd1e9 100644 (file)
@@ -0,0 +1,6 @@
+config DM
+       bool "Enable Driver Model"
+       depends on !SPL_BUILD
+       help
+         This config option enables Driver Model.
+         To use legacy drivers, say N.
index c7905b14409fcf4fe56653655960de8407c5348b..151c2398a4d47fce304d43a6ae775befd379baa2 100644 (file)
@@ -5,3 +5,4 @@
 #
 
 obj-y := device.o lists.o root.o uclass.o util.o
+obj-$(CONFIG_OF_CONTROL) += simple-bus.o
index 32e80e82b59c99f9ac5734c8f3dadc7c3b0c5f28..49faa29dc1a0eecaa84e76371b8301c2eef14d7b 100644 (file)
@@ -232,7 +232,7 @@ static void device_free(struct udevice *dev)
        }
 }
 
-int device_probe(struct udevice *dev)
+int device_probe_child(struct udevice *dev, void *parent_priv)
 {
        struct driver *drv;
        int size = 0;
@@ -282,6 +282,8 @@ int device_probe(struct udevice *dev)
                                ret = -ENOMEM;
                                goto fail;
                        }
+                       if (parent_priv)
+                               memcpy(dev->parent_priv, parent_priv, size);
                }
 
                ret = device_probe(dev->parent);
@@ -335,6 +337,11 @@ fail:
        return ret;
 }
 
+int device_probe(struct udevice *dev)
+{
+       return device_probe_child(dev, NULL);
+}
+
 int device_remove(struct udevice *dev)
 {
        struct driver *drv;
@@ -514,3 +521,30 @@ int device_get_child_by_of_offset(struct udevice *parent, int seq,
        ret = device_find_child_by_of_offset(parent, seq, &dev);
        return device_get_device_tail(dev, ret, devp);
 }
+
+int device_find_first_child(struct udevice *parent, struct udevice **devp)
+{
+       if (list_empty(&parent->child_head)) {
+               *devp = NULL;
+       } else {
+               *devp = list_first_entry(&parent->child_head, struct udevice,
+                                        sibling_node);
+       }
+
+       return 0;
+}
+
+int device_find_next_child(struct udevice **devp)
+{
+       struct udevice *dev = *devp;
+       struct udevice *parent = dev->parent;
+
+       if (list_is_last(&dev->sibling_node, &parent->child_head)) {
+               *devp = NULL;
+       } else {
+               *devp = list_entry(dev->sibling_node.next, struct udevice,
+                                  sibling_node);
+       }
+
+       return 0;
+}
index 699f94b435f213a0e78e91e4d2e854ae45473e7b..3a1ea8565449699a39ba5684dbecfbf71e30780b 100644 (file)
@@ -24,19 +24,12 @@ struct driver *lists_driver_lookup_name(const char *name)
                ll_entry_start(struct driver, driver);
        const int n_ents = ll_entry_count(struct driver, driver);
        struct driver *entry;
-       int len;
 
        if (!drv || !n_ents)
                return NULL;
 
-       len = strlen(name);
-
        for (entry = drv; entry != drv + n_ents; entry++) {
-               if (strncmp(name, entry->name, len))
-                       continue;
-
-               /* Full match */
-               if (len == strlen(entry->name))
+               if (!strcmp(name, entry->name))
                        return entry;
        }
 
diff --git a/drivers/core/simple-bus.c b/drivers/core/simple-bus.c
new file mode 100644 (file)
index 0000000..3ea4d82
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int simple_bus_post_bind(struct udevice *dev)
+{
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+UCLASS_DRIVER(simple_bus) = {
+       .id             = UCLASS_SIMPLE_BUS,
+       .name           = "simple_bus",
+       .post_bind      = simple_bus_post_bind,
+};
+
+static const struct udevice_id generic_simple_bus_ids[] = {
+       { .compatible = "simple-bus" },
+       { }
+};
+
+U_BOOT_DRIVER(simple_bus_drv) = {
+       .name   = "generic_simple_bus",
+       .id     = UCLASS_SIMPLE_BUS,
+       .of_match = generic_simple_bus_ids,
+};
index 61ca17e564a25dff143da7c26b8d886dab90de04..901b06ed2baaf5f4b0cbdb71d3ca40170de33991 100644 (file)
@@ -60,10 +60,6 @@ static int uclass_add(enum uclass_id id, struct uclass **ucp)
                        id);
                return -ENOENT;
        }
-       if (uc_drv->ops) {
-               dm_warn("No ops for uclass id %d\n", id);
-               return -EINVAL;
-       }
        uc = calloc(1, sizeof(*uc));
        if (!uc)
                return -ENOMEM;
index 91f6df220b1dd7f11aabdaddb28fa7e3db32b44e..c3d3c3bcd85355b77dc8cb1d4c945a589f550781 100644 (file)
@@ -9,6 +9,7 @@
 #include <errno.h>
 #include <div64.h>
 #include <dfu.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 static long dfu_get_medium_size_sf(struct dfu_entity *dfu)
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d21302f8da95316cdf7891556a73bb0de576b8e1 100644 (file)
@@ -0,0 +1,6 @@
+config DM_GPIO
+       bool "Enable Driver Model for GPIO drivers"
+       depends on DM
+       help
+         If you want to use driver model for GPIO drivers, say Y.
+         To use legacy GPIO drivers, say N.
index 97b51371145e81de9f268a33f001c72d6f63ff98..0244c01882863903596f76f153a11cbbaf98dc3e 100644 (file)
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 
-inline int gpio_is_valid(unsigned gpio)
-{
-       return (gpio < BCM2835_GPIO_COUNT);
-}
-
-int gpio_request(unsigned gpio, const char *label)
-{
-       return !gpio_is_valid(gpio);
-}
+struct bcm2835_gpios {
+       struct bcm2835_gpio_regs *reg;
+};
 
-int gpio_free(unsigned gpio)
+static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
 {
-       return 0;
-}
-
-int gpio_direction_input(unsigned gpio)
-{
-       struct bcm2835_gpio_regs *reg =
-               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
        unsigned val;
 
-       val = readl(&reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+       val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
        val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
        val |= (BCM2835_GPIO_INPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
-       writel(val, &reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+       writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
 
        return 0;
 }
 
-int gpio_direction_output(unsigned gpio, int value)
+static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned gpio,
+                                        int value)
 {
-       struct bcm2835_gpio_regs *reg =
-               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
        unsigned val;
 
        gpio_set_value(gpio, value);
 
-       val = readl(&reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+       val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
        val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
        val |= (BCM2835_GPIO_OUTPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
-       writel(val, &reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+       writel(val, &gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
 
        return 0;
 }
 
-int gpio_get_value(unsigned gpio)
+static bool bcm2835_gpio_is_output(const struct bcm2835_gpios *gpios, int gpio)
+{
+       u32 val;
+
+       val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+       val &= BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio);
+       return val ? true : false;
+}
+
+static int bcm2835_get_value(const struct bcm2835_gpios *gpios, unsigned gpio)
 {
-       struct bcm2835_gpio_regs *reg =
-               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
        unsigned val;
 
-       val = readl(&reg->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]);
+       val = readl(&gpios->reg->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]);
 
        return (val >> BCM2835_GPIO_COMMON_SHIFT(gpio)) & 0x1;
 }
 
-int gpio_set_value(unsigned gpio, int value)
+static int bcm2835_gpio_get_value(struct udevice *dev, unsigned gpio)
+{
+       const struct bcm2835_gpios *gpios = dev_get_priv(dev);
+
+       return bcm2835_get_value(gpios, gpio);
+}
+
+static int bcm2835_gpio_set_value(struct udevice *dev, unsigned gpio,
+                                 int value)
 {
-       struct bcm2835_gpio_regs *reg =
-               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
-       u32 *output_reg = value ? reg->gpset : reg->gpclr;
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
+       u32 *output_reg = value ? gpios->reg->gpset : gpios->reg->gpclr;
 
        writel(1 << BCM2835_GPIO_COMMON_SHIFT(gpio),
                                &output_reg[BCM2835_GPIO_COMMON_BANK(gpio)]);
 
        return 0;
 }
+
+static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
+
+       /* GPIOF_FUNC is not implemented yet */
+       if (bcm2835_gpio_is_output(gpios, offset))
+               return GPIOF_OUTPUT;
+       else
+               return GPIOF_INPUT;
+}
+
+
+static const struct dm_gpio_ops gpio_bcm2835_ops = {
+       .direction_input        = bcm2835_gpio_direction_input,
+       .direction_output       = bcm2835_gpio_direction_output,
+       .get_value              = bcm2835_gpio_get_value,
+       .set_value              = bcm2835_gpio_set_value,
+       .get_function           = bcm2835_gpio_get_function,
+};
+
+static int bcm2835_gpio_probe(struct udevice *dev)
+{
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
+       struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev);
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+       uc_priv->bank_name = "GPIO";
+       uc_priv->gpio_count = BCM2835_GPIO_COUNT;
+       gpios->reg = (struct bcm2835_gpio_regs *)plat->base;
+
+       return 0;
+}
+
+U_BOOT_DRIVER(gpio_bcm2835) = {
+       .name   = "gpio_bcm2835",
+       .id     = UCLASS_GPIO,
+       .ops    = &gpio_bcm2835_ops,
+       .probe  = bcm2835_gpio_probe,
+       .priv_auto_alloc_size = sizeof(struct bcm2835_gpios),
+};
index f1bbc587961709dec3922c52c76585227acecd9b..45e9a5ad2278378814b7351c5d70dd5c53fbf287 100644 (file)
@@ -7,7 +7,9 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
+#include <malloc.h>
 #include <asm/gpio.h>
+#include <linux/ctype.h>
 
 /**
  * gpio_to_device() - Convert global GPIO number to device, number
@@ -43,35 +45,47 @@ static int gpio_to_device(unsigned int gpio, struct udevice **devp,
 int gpio_lookup_name(const char *name, struct udevice **devp,
                     unsigned int *offsetp, unsigned int *gpiop)
 {
-       struct gpio_dev_priv *uc_priv;
+       struct gpio_dev_priv *uc_priv = NULL;
        struct udevice *dev;
+       ulong offset;
+       int numeric;
        int ret;
 
        if (devp)
                *devp = NULL;
+       numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
        for (ret = uclass_first_device(UCLASS_GPIO, &dev);
             dev;
             ret = uclass_next_device(&dev)) {
-               ulong offset;
                int len;
 
                uc_priv = dev->uclass_priv;
+               if (numeric != -1) {
+                       offset = numeric - uc_priv->gpio_base;
+                       /* Allow GPIOs to be numbered from 0 */
+                       if (offset >= 0 && offset < uc_priv->gpio_count)
+                               break;
+               }
+
                len = uc_priv->bank_name ? strlen(uc_priv->bank_name) : 0;
 
                if (!strncasecmp(name, uc_priv->bank_name, len)) {
-                       if (strict_strtoul(name + len, 10, &offset))
-                               continue;
-                       if (devp)
-                               *devp = dev;
-                       if (offsetp)
-                               *offsetp = offset;
-                       if (gpiop)
-                               *gpiop = uc_priv->gpio_base + offset;
-                       return 0;
+                       if (!strict_strtoul(name + len, 10, &offset))
+                               break;
                }
        }
 
-       return ret ? ret : -EINVAL;
+       if (!dev)
+               return ret ? ret : -EINVAL;
+
+       if (devp)
+               *devp = dev;
+       if (offsetp)
+               *offsetp = offset;
+       if (gpiop)
+               *gpiop = uc_priv->gpio_base + offset;
+
+       return 0;
 }
 
 /**
@@ -79,24 +93,62 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
  * gpio:       GPIO number
  * label:      Name for the requested GPIO
  *
+ * The label is copied and allocated so the caller does not need to keep
+ * the pointer around.
+ *
  * This function implements the API that's compatible with current
  * GPIO API used in U-Boot. The request is forwarded to particular
  * GPIO driver. Returns 0 on success, negative value on error.
  */
 int gpio_request(unsigned gpio, const char *label)
 {
+       struct gpio_dev_priv *uc_priv;
        unsigned int offset;
        struct udevice *dev;
+       char *str;
        int ret;
 
        ret = gpio_to_device(gpio, &dev, &offset);
        if (ret)
                return ret;
 
-       if (!gpio_get_ops(dev)->request)
-               return 0;
+       uc_priv = dev->uclass_priv;
+       if (uc_priv->name[offset])
+               return -EBUSY;
+       str = strdup(label);
+       if (!str)
+               return -ENOMEM;
+       if (gpio_get_ops(dev)->request) {
+               ret = gpio_get_ops(dev)->request(dev, offset, label);
+               if (ret) {
+                       free(str);
+                       return ret;
+               }
+       }
+       uc_priv->name[offset] = str;
+
+       return 0;
+}
+
+/**
+ * gpio_requestf() - [COMPAT] Request GPIO
+ * @gpio:      GPIO number
+ * @fmt:       Format string for the requested GPIO
+ * @...:       Arguments for the printf() format string
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_requestf(unsigned gpio, const char *fmt, ...)
+{
+       va_list args;
+       char buf[40];
 
-       return gpio_get_ops(dev)->request(dev, offset, label);
+       va_start(args, fmt);
+       vscnprintf(buf, sizeof(buf), fmt, args);
+       va_end(args);
+       return gpio_request(gpio, buf);
 }
 
 /**
@@ -109,6 +161,7 @@ int gpio_request(unsigned gpio, const char *label)
  */
 int gpio_free(unsigned gpio)
 {
+       struct gpio_dev_priv *uc_priv;
        unsigned int offset;
        struct udevice *dev;
        int ret;
@@ -117,9 +170,34 @@ int gpio_free(unsigned gpio)
        if (ret)
                return ret;
 
-       if (!gpio_get_ops(dev)->free)
-               return 0;
-       return gpio_get_ops(dev)->free(dev, offset);
+       uc_priv = dev->uclass_priv;
+       if (!uc_priv->name[offset])
+               return -ENXIO;
+       if (gpio_get_ops(dev)->free) {
+               ret = gpio_get_ops(dev)->free(dev, offset);
+               if (ret)
+                       return ret;
+       }
+
+       free(uc_priv->name[offset]);
+       uc_priv->name[offset] = NULL;
+
+       return 0;
+}
+
+static int check_reserved(struct udevice *dev, unsigned offset,
+                         const char *func)
+{
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+       if (!uc_priv->name[offset]) {
+               printf("%s: %s: error: gpio %s%d not reserved\n",
+                      dev->name, func,
+                      uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+               return -EBUSY;
+       }
+
+       return 0;
 }
 
 /**
@@ -139,8 +217,9 @@ int gpio_direction_input(unsigned gpio)
        ret = gpio_to_device(gpio, &dev, &offset);
        if (ret)
                return ret;
+       ret = check_reserved(dev, offset, "dir_input");
 
-       return gpio_get_ops(dev)->direction_input(dev, offset);
+       return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
 }
 
 /**
@@ -161,8 +240,10 @@ int gpio_direction_output(unsigned gpio, int value)
        ret = gpio_to_device(gpio, &dev, &offset);
        if (ret)
                return ret;
+       ret = check_reserved(dev, offset, "dir_output");
 
-       return gpio_get_ops(dev)->direction_output(dev, offset, value);
+       return ret ? ret :
+               gpio_get_ops(dev)->direction_output(dev, offset, value);
 }
 
 /**
@@ -183,8 +264,9 @@ int gpio_get_value(unsigned gpio)
        ret = gpio_to_device(gpio, &dev, &offset);
        if (ret)
                return ret;
+       ret = check_reserved(dev, offset, "get_value");
 
-       return gpio_get_ops(dev)->get_value(dev, offset);
+       return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
 }
 
 /**
@@ -205,8 +287,9 @@ int gpio_set_value(unsigned gpio, int value)
        ret = gpio_to_device(gpio, &dev, &offset);
        if (ret)
                return ret;
+       ret = check_reserved(dev, offset, "set_value");
 
-       return gpio_get_ops(dev)->set_value(dev, offset, value);
+       return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
 }
 
 const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
@@ -221,8 +304,94 @@ const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
        return priv->bank_name;
 }
 
+static const char * const gpio_function[GPIOF_COUNT] = {
+       "input",
+       "output",
+       "unused",
+       "unknown",
+       "func",
+};
+
+int get_function(struct udevice *dev, int offset, bool skip_unused,
+                const char **namep)
+{
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct dm_gpio_ops *ops = gpio_get_ops(dev);
+
+       BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+       if (!device_active(dev))
+               return -ENODEV;
+       if (offset < 0 || offset >= uc_priv->gpio_count)
+               return -EINVAL;
+       if (namep)
+               *namep = uc_priv->name[offset];
+       if (skip_unused && !uc_priv->name[offset])
+               return GPIOF_UNUSED;
+       if (ops->get_function) {
+               int ret;
+
+               ret = ops->get_function(dev, offset);
+               if (ret < 0)
+                       return ret;
+               if (ret >= ARRAY_SIZE(gpio_function))
+                       return -ENODATA;
+               return ret;
+       }
+
+       return GPIOF_UNKNOWN;
+}
+
+int gpio_get_function(struct udevice *dev, int offset, const char **namep)
+{
+       return get_function(dev, offset, true, namep);
+}
+
+int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep)
+{
+       return get_function(dev, offset, false, namep);
+}
+
+int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize)
+{
+       struct dm_gpio_ops *ops = gpio_get_ops(dev);
+       struct gpio_dev_priv *priv;
+       char *str = buf;
+       int func;
+       int ret;
+       int len;
+
+       BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function));
+
+       *buf = 0;
+       priv = dev->uclass_priv;
+       ret = gpio_get_raw_function(dev, offset, NULL);
+       if (ret < 0)
+               return ret;
+       func = ret;
+       len = snprintf(str, buffsize, "%s%d: %s",
+                      priv->bank_name ? priv->bank_name : "",
+                      offset, gpio_function[func]);
+       if (func == GPIOF_INPUT || func == GPIOF_OUTPUT ||
+           func == GPIOF_UNUSED) {
+               const char *label;
+               bool used;
+
+               ret = ops->get_value(dev, offset);
+               if (ret < 0)
+                       return ret;
+               used = gpio_get_function(dev, offset, &label) != GPIOF_UNUSED;
+               snprintf(str + len, buffsize - len, ": %d [%c]%s%s",
+                        ret,
+                        used ? 'x' : ' ',
+                        used ? " " : "",
+                        label ? label : "");
+       }
+
+       return 0;
+}
+
 /* We need to renumber the GPIOs when any driver is probed/removed */
-static int gpio_renumber(void)
+static int gpio_renumber(struct udevice *removed_dev)
 {
        struct gpio_dev_priv *uc_priv;
        struct udevice *dev;
@@ -237,7 +406,7 @@ static int gpio_renumber(void)
        /* Ensure that we have a base for each bank */
        base = 0;
        uclass_foreach_dev(dev, uc) {
-               if (device_active(dev)) {
+               if (device_active(dev) && dev != removed_dev) {
                        uc_priv = dev->uclass_priv;
                        uc_priv->gpio_base = base;
                        base += uc_priv->gpio_count;
@@ -249,12 +418,27 @@ static int gpio_renumber(void)
 
 static int gpio_post_probe(struct udevice *dev)
 {
-       return gpio_renumber();
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+       uc_priv->name = calloc(uc_priv->gpio_count, sizeof(char *));
+       if (!uc_priv->name)
+               return -ENOMEM;
+
+       return gpio_renumber(NULL);
 }
 
 static int gpio_pre_remove(struct udevice *dev)
 {
-       return gpio_renumber();
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       int i;
+
+       for (i = 0; i < uc_priv->gpio_count; i++) {
+               if (uc_priv->name[i])
+                       free(uc_priv->name[i]);
+       }
+       free(uc_priv->name);
+
+       return gpio_renumber(dev);
 }
 
 UCLASS_DRIVER(gpio) = {
index 7d9fac72337fc329ac12d2c80ad21f03b9e8fe7e..d3381b0369c1a4122f30c0e80aecd154d4e4e896 100644 (file)
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
 #include <pci.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 
+#define GPIO_PER_BANK  32
+
 /* Where in config space is the register that points to the GPIO registers? */
 #define PCI_CFG_GPIOBASE 0x48
 
-#define NUM_BANKS 3
-
-/* Within the I/O space, where are the registers to control the GPIOs? */
-static struct {
-       u8 use_sel;
-       u8 io_sel;
-       u8 lvl;
-} gpio_bank[NUM_BANKS] = {
-       { 0x00, 0x04, 0x0c },           /* Bank 0 */
-       { 0x30, 0x34, 0x38 },           /* Bank 1 */
-       { 0x40, 0x44, 0x48 }            /* Bank 2 */
+struct ich6_bank_priv {
+       /* These are I/O addresses */
+       uint32_t use_sel;
+       uint32_t io_sel;
+       uint32_t lvl;
 };
 
-static pci_dev_t dev;                  /* handle for 0:1f:0 */
-static u32 gpiobase;                   /* offset into I/O space */
-static int found_it_once;              /* valid GPIO device? */
-static u32 lock[NUM_BANKS];            /* "lock" for access to pins */
-
-static int bad_arg(int num, int *bank, int *bitnum)
-{
-       int i = num / 32;
-       int j = num % 32;
-
-       if (num < 0 || i > NUM_BANKS) {
-               debug("%s: bogus gpio num: %d\n", __func__, num);
-               return -1;
-       }
-       *bank = i;
-       *bitnum = j;
-       return 0;
-}
-
-static int mark_gpio(int bank, int bitnum)
-{
-       if (lock[bank] & (1UL << bitnum)) {
-               debug("%s: %d.%d already marked\n", __func__, bank, bitnum);
-               return -1;
-       }
-       lock[bank] |= (1 << bitnum);
-       return 0;
-}
-
-static void clear_gpio(int bank, int bitnum)
-{
-       lock[bank] &= ~(1 << bitnum);
-}
-
-static int notmine(int num, int *bank, int *bitnum)
-{
-       if (bad_arg(num, bank, bitnum))
-               return -1;
-       return !(lock[*bank] & (1UL << *bitnum));
-}
-
-static int gpio_init(void)
+static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 {
+       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+       pci_dev_t pci_dev;                      /* handle for 0:1f:0 */
        u8 tmpbyte;
        u16 tmpword;
        u32 tmplong;
-
-       /* Have we already done this? */
-       if (found_it_once)
-               return 0;
+       u32 gpiobase;
+       int offset;
 
        /* Where should it be? */
-       dev = PCI_BDF(0, 0x1f, 0);
+       pci_dev = PCI_BDF(0, 0x1f, 0);
 
        /* Is the device present? */
-       pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword);
+       pci_read_config_word(pci_dev, PCI_VENDOR_ID, &tmpword);
        if (tmpword != PCI_VENDOR_ID_INTEL) {
                debug("%s: wrong VendorID\n", __func__);
-               return -1;
+               return -ENODEV;
        }
 
-       pci_read_config_word(dev, PCI_DEVICE_ID, &tmpword);
+       pci_read_config_word(pci_dev, PCI_DEVICE_ID, &tmpword);
        debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
        /*
         * We'd like to validate the Device ID too, but pretty much any
@@ -118,37 +76,37 @@ static int gpio_init(void)
         */
 
        /* I/O should already be enabled (it's a RO bit). */
-       pci_read_config_word(dev, PCI_COMMAND, &tmpword);
+       pci_read_config_word(pci_dev, PCI_COMMAND, &tmpword);
        if (!(tmpword & PCI_COMMAND_IO)) {
                debug("%s: device IO not enabled\n", __func__);
-               return -1;
+               return -ENODEV;
        }
 
        /* Header Type must be normal (bits 6-0 only; see spec.) */
-       pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte);
+       pci_read_config_byte(pci_dev, PCI_HEADER_TYPE, &tmpbyte);
        if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
                debug("%s: invalid Header type\n", __func__);
-               return -1;
+               return -ENODEV;
        }
 
        /* Base Class must be a bridge device */
-       pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte);
+       pci_read_config_byte(pci_dev, PCI_CLASS_CODE, &tmpbyte);
        if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
                debug("%s: invalid class\n", __func__);
-               return -1;
+               return -ENODEV;
        }
        /* Sub Class must be ISA */
-       pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte);
+       pci_read_config_byte(pci_dev, PCI_CLASS_SUB_CODE, &tmpbyte);
        if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
                debug("%s: invalid subclass\n", __func__);
-               return -1;
+               return -ENODEV;
        }
 
        /* Programming Interface must be 0x00 (no others exist) */
-       pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte);
+       pci_read_config_byte(pci_dev, PCI_CLASS_PROG, &tmpbyte);
        if (tmpbyte != 0x00) {
                debug("%s: invalid interface type\n", __func__);
-               return -1;
+               return -ENODEV;
        }
 
        /*
@@ -156,11 +114,11 @@ static int gpio_init(void)
         * that it was unused (or undocumented). Check that it looks
         * okay: not all ones or zeros, and mapped to I/O space (bit 0).
         */
-       pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong);
+       pci_read_config_dword(pci_dev, PCI_CFG_GPIOBASE, &tmplong);
        if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
            !(tmplong & 0x00000001)) {
                debug("%s: unexpected GPIOBASE value\n", __func__);
-               return -1;
+               return -ENODEV;
        }
 
        /*
@@ -170,105 +128,137 @@ static int gpio_init(void)
         * an I/O address, not a memory address, so mask that off.
         */
        gpiobase = tmplong & 0xfffffffe;
+       offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
+       if (offset == -1) {
+               debug("%s: Invalid register offset %d\n", __func__, offset);
+               return -EINVAL;
+       }
+       plat->base_addr = gpiobase + offset;
+       plat->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
+                                     "bank-name", NULL);
 
-       /* Finally. These are the droids we're looking for. */
-       found_it_once = 1;
        return 0;
 }
 
-int gpio_request(unsigned num, const char *label /* UNUSED */)
+int ich6_gpio_probe(struct udevice *dev)
 {
-       u32 tmplong;
-       int i = 0, j = 0;
+       struct ich6_bank_platdata *plat = dev_get_platdata(dev);
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct ich6_bank_priv *bank = dev_get_priv(dev);
+
+       uc_priv->gpio_count = GPIO_PER_BANK;
+       uc_priv->bank_name = plat->bank_name;
+       bank->use_sel = plat->base_addr;
+       bank->io_sel = plat->base_addr + 4;
+       bank->lvl = plat->base_addr + 8;
 
-       /* Is the hardware ready? */
-       if (gpio_init())
-               return -1;
+       return 0;
+}
 
-       if (bad_arg(num, &i, &j))
-               return -1;
+int ich6_gpio_request(struct udevice *dev, unsigned offset, const char *label)
+{
+       struct ich6_bank_priv *bank = dev_get_priv(dev);
+       u32 tmplong;
 
        /*
         * Make sure that the GPIO pin we want isn't already in use for some
         * built-in hardware function. We have to check this for every
         * requested pin.
         */
-       tmplong = inl(gpiobase + gpio_bank[i].use_sel);
-       if (!(tmplong & (1UL << j))) {
+       tmplong = inl(bank->use_sel);
+       if (!(tmplong & (1UL << offset))) {
                debug("%s: gpio %d is reserved for internal use\n", __func__,
-                     num);
-               return -1;
+                     offset);
+               return -EPERM;
        }
 
-       return mark_gpio(i, j);
-}
-
-int gpio_free(unsigned num)
-{
-       int i = 0, j = 0;
-
-       if (notmine(num, &i, &j))
-               return -1;
-
-       clear_gpio(i, j);
        return 0;
 }
 
-int gpio_direction_input(unsigned num)
+static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
+       struct ich6_bank_priv *bank = dev_get_priv(dev);
        u32 tmplong;
-       int i = 0, j = 0;
-
-       if (notmine(num, &i, &j))
-               return -1;
 
-       tmplong = inl(gpiobase + gpio_bank[i].io_sel);
-       tmplong |= (1UL << j);
-       outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+       tmplong = inl(bank->io_sel);
+       tmplong |= (1UL << offset);
+       outl(bank->io_sel, tmplong);
        return 0;
 }
 
-int gpio_direction_output(unsigned num, int value)
+static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
+                                      int value)
 {
+       struct ich6_bank_priv *bank = dev_get_priv(dev);
        u32 tmplong;
-       int i = 0, j = 0;
 
-       if (notmine(num, &i, &j))
-               return -1;
-
-       tmplong = inl(gpiobase + gpio_bank[i].io_sel);
-       tmplong &= ~(1UL << j);
-       outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+       tmplong = inl(bank->io_sel);
+       tmplong &= ~(1UL << offset);
+       outl(bank->io_sel, tmplong);
        return 0;
 }
 
-int gpio_get_value(unsigned num)
+static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
+
 {
+       struct ich6_bank_priv *bank = dev_get_priv(dev);
        u32 tmplong;
-       int i = 0, j = 0;
        int r;
 
-       if (notmine(num, &i, &j))
-               return -1;
-
-       tmplong = inl(gpiobase + gpio_bank[i].lvl);
-       r = (tmplong & (1UL << j)) ? 1 : 0;
+       tmplong = inl(bank->lvl);
+       r = (tmplong & (1UL << offset)) ? 1 : 0;
        return r;
 }
 
-int gpio_set_value(unsigned num, int value)
+static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
+                              int value)
 {
+       struct ich6_bank_priv *bank = dev_get_priv(dev);
        u32 tmplong;
-       int i = 0, j = 0;
 
-       if (notmine(num, &i, &j))
-               return -1;
-
-       tmplong = inl(gpiobase + gpio_bank[i].lvl);
+       tmplong = inl(bank->lvl);
        if (value)
-               tmplong |= (1UL << j);
+               tmplong |= (1UL << offset);
        else
-               tmplong &= ~(1UL << j);
-       outl(gpiobase + gpio_bank[i].lvl, tmplong);
+               tmplong &= ~(1UL << offset);
+       outl(bank->lvl, tmplong);
        return 0;
 }
+
+static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+       struct ich6_bank_priv *bank = dev_get_priv(dev);
+       u32 mask = 1UL << offset;
+
+       if (!(inl(bank->use_sel) & mask))
+               return GPIOF_FUNC;
+       if (inl(bank->io_sel) & mask)
+               return GPIOF_INPUT;
+       else
+               return GPIOF_OUTPUT;
+}
+
+static const struct dm_gpio_ops gpio_ich6_ops = {
+       .request                = ich6_gpio_request,
+       .direction_input        = ich6_gpio_direction_input,
+       .direction_output       = ich6_gpio_direction_output,
+       .get_value              = ich6_gpio_get_value,
+       .set_value              = ich6_gpio_set_value,
+       .get_function           = ich6_gpio_get_function,
+};
+
+static const struct udevice_id intel_ich6_gpio_ids[] = {
+       { .compatible = "intel,ich6-gpio" },
+       { }
+};
+
+U_BOOT_DRIVER(gpio_ich6) = {
+       .name   = "gpio_ich6",
+       .id     = UCLASS_GPIO,
+       .of_match = intel_ich6_gpio_ids,
+       .ops    = &gpio_ich6_ops,
+       .ofdata_to_platdata     = gpio_ich6_ofdata_to_platdata,
+       .probe  = ich6_gpio_probe,
+       .priv_auto_alloc_size = sizeof(struct ich6_bank_priv),
+       .platdata_auto_alloc_size = sizeof(struct ich6_bank_platdata),
+};
index 0af75a84ea7ab6ea5251549d43d40bbed96e40f2..43b27e3fea1bc86f5fbef46f969a7f8ff0322286 100644 (file)
@@ -16,7 +16,7 @@
 #include <common.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <asm/arch/gpio.h>
 
 static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
@@ -36,7 +36,7 @@ void __set_direction(unsigned pin, int input)
        u = readl(GPIO_IO_CONF(pin));
 }
 
-void __set_level(unsigned pin, int high)
+static void __set_level(unsigned pin, int high)
 {
        u32 u;
 
@@ -48,7 +48,7 @@ void __set_level(unsigned pin, int high)
        writel(u, GPIO_OUT(pin));
 }
 
-void __set_blinking(unsigned pin, int blink)
+static void __set_blinking(unsigned pin, int blink)
 {
        u32 u;
 
index 6a572d5454b39e4905da9094edd01f47cf451035..8bb9e39b7231e522f87eaf9612ad5abf383931e7 100644 (file)
@@ -8,16 +8,29 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <malloc.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
-#include <errno.h>
 
 enum mxc_gpio_direction {
        MXC_GPIO_DIRECTION_IN,
        MXC_GPIO_DIRECTION_OUT,
 };
 
+#define GPIO_PER_BANK                  32
+
+struct mxc_gpio_plat {
+       struct gpio_regs *regs;
+};
+
+struct mxc_bank_info {
+       struct gpio_regs *regs;
+};
+
+#ifndef CONFIG_DM_GPIO
 #define GPIO_TO_PORT(n)                (n / 32)
 
 /* GPIO port description */
@@ -134,3 +147,176 @@ int gpio_direction_output(unsigned gpio, int value)
 
        return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
 }
+#endif
+
+#ifdef CONFIG_DM_GPIO
+static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
+{
+       u32 val;
+
+       val = readl(&regs->gpio_dir);
+
+       return val & (1 << offset) ? 1 : 0;
+}
+
+static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
+                                   enum mxc_gpio_direction direction)
+{
+       u32 l;
+
+       l = readl(&regs->gpio_dir);
+
+       switch (direction) {
+       case MXC_GPIO_DIRECTION_OUT:
+               l |= 1 << offset;
+               break;
+       case MXC_GPIO_DIRECTION_IN:
+               l &= ~(1 << offset);
+       }
+       writel(l, &regs->gpio_dir);
+}
+
+static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
+                                   int value)
+{
+       u32 l;
+
+       l = readl(&regs->gpio_dr);
+       if (value)
+               l |= 1 << offset;
+       else
+               l &= ~(1 << offset);
+       writel(l, &regs->gpio_dr);
+}
+
+static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
+{
+       return (readl(&regs->gpio_psr) >> offset) & 0x01;
+}
+
+/* set GPIO pin 'gpio' as an input */
+static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+
+       /* Configure GPIO direction as input. */
+       mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
+
+       return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
+                                      int value)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+
+       /* Configure GPIO output value. */
+       mxc_gpio_bank_set_value(bank->regs, offset, value);
+
+       /* Configure GPIO direction as output. */
+       mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
+
+       return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+
+       return mxc_gpio_bank_get_value(bank->regs, offset);
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
+                                int value)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+
+       mxc_gpio_bank_set_value(bank->regs, offset, value);
+
+       return 0;
+}
+
+static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+
+       /* GPIOF_FUNC is not implemented yet */
+       if (mxc_gpio_is_output(bank->regs, offset))
+               return GPIOF_OUTPUT;
+       else
+               return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops gpio_mxc_ops = {
+       .direction_input        = mxc_gpio_direction_input,
+       .direction_output       = mxc_gpio_direction_output,
+       .get_value              = mxc_gpio_get_value,
+       .set_value              = mxc_gpio_set_value,
+       .get_function           = mxc_gpio_get_function,
+};
+
+static const struct mxc_gpio_plat mxc_plat[] = {
+       { (struct gpio_regs *)GPIO1_BASE_ADDR },
+       { (struct gpio_regs *)GPIO2_BASE_ADDR },
+       { (struct gpio_regs *)GPIO3_BASE_ADDR },
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
+               defined(CONFIG_MX53) || defined(CONFIG_MX6)
+       { (struct gpio_regs *)GPIO4_BASE_ADDR },
+#endif
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+       { (struct gpio_regs *)GPIO5_BASE_ADDR },
+       { (struct gpio_regs *)GPIO6_BASE_ADDR },
+#endif
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+       { (struct gpio_regs *)GPIO7_BASE_ADDR },
+#endif
+};
+
+static int mxc_gpio_probe(struct udevice *dev)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+       struct mxc_gpio_plat *plat = dev_get_platdata(dev);
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       int banknum;
+       char name[18], *str;
+
+       banknum = plat - mxc_plat;
+       sprintf(name, "GPIO%d_", banknum + 1);
+       str = strdup(name);
+       if (!str)
+               return -ENOMEM;
+       uc_priv->bank_name = str;
+       uc_priv->gpio_count = GPIO_PER_BANK;
+       bank->regs = plat->regs;
+
+       return 0;
+}
+
+U_BOOT_DRIVER(gpio_mxc) = {
+       .name   = "gpio_mxc",
+       .id     = UCLASS_GPIO,
+       .ops    = &gpio_mxc_ops,
+       .probe  = mxc_gpio_probe,
+       .priv_auto_alloc_size = sizeof(struct mxc_bank_info),
+};
+
+U_BOOT_DEVICES(mxc_gpios) = {
+       { "gpio_mxc", &mxc_plat[0] },
+       { "gpio_mxc", &mxc_plat[1] },
+       { "gpio_mxc", &mxc_plat[2] },
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
+               defined(CONFIG_MX53) || defined(CONFIG_MX6)
+       { "gpio_mxc", &mxc_plat[3] },
+#endif
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+       { "gpio_mxc", &mxc_plat[4] },
+       { "gpio_mxc", &mxc_plat[5] },
+#endif
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+       { "gpio_mxc", &mxc_plat[6] },
+#endif
+};
+#endif
index 13dcf798730f4313e6767dc8078b05a454e6adb2..f3a7ccb51e98f28ee1b9dd72906dac4b93e0c407 100644 (file)
@@ -19,6 +19,7 @@
  * Written by Juha Yrjölä <juha.yrjola@nokia.com>
  */
 #include <common.h>
+#include <dm.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/errno.h>
 #define OMAP_GPIO_DIR_OUT      0
 #define OMAP_GPIO_DIR_IN       1
 
-static inline const struct gpio_bank *get_gpio_bank(int gpio)
-{
-       return &omap_gpio_bank[gpio >> 5];
-}
+#ifdef CONFIG_DM_GPIO
+
+#define GPIO_PER_BANK                  32
+
+struct gpio_bank {
+       /* TODO(sjg@chromium.org): Can we use a struct here? */
+       void *base;     /* address of registers in physical memory */
+       enum gpio_method method;
+};
+
+#endif
 
 static inline int get_gpio_index(int gpio)
 {
@@ -41,15 +49,6 @@ int gpio_is_valid(int gpio)
        return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
 }
 
-static int check_gpio(int gpio)
-{
-       if (!gpio_is_valid(gpio)) {
-               printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
-               return -1;
-       }
-       return 0;
-}
-
 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
                                int is_input)
 {
@@ -118,6 +117,48 @@ static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
        __raw_writel(l, reg);
 }
 
+static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
+{
+       void *reg = bank->base;
+       int input;
+
+       switch (bank->method) {
+       case METHOD_GPIO_24XX:
+               input = _get_gpio_direction(bank, gpio);
+               switch (input) {
+               case OMAP_GPIO_DIR_IN:
+                       reg += OMAP_GPIO_DATAIN;
+                       break;
+               case OMAP_GPIO_DIR_OUT:
+                       reg += OMAP_GPIO_DATAOUT;
+                       break;
+               default:
+                       return -1;
+               }
+               break;
+       default:
+               return -1;
+       }
+
+       return (__raw_readl(reg) & (1 << gpio)) != 0;
+}
+
+#ifndef CONFIG_DM_GPIO
+
+static inline const struct gpio_bank *get_gpio_bank(int gpio)
+{
+       return &omap_gpio_bank[gpio >> 5];
+}
+
+static int check_gpio(int gpio)
+{
+       if (!gpio_is_valid(gpio)) {
+               printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
+               return -1;
+       }
+       return 0;
+}
+
 /**
  * Set value of the specified gpio
  */
@@ -139,32 +180,12 @@ int gpio_set_value(unsigned gpio, int value)
 int gpio_get_value(unsigned gpio)
 {
        const struct gpio_bank *bank;
-       void *reg;
-       int input;
 
        if (check_gpio(gpio) < 0)
                return -1;
        bank = get_gpio_bank(gpio);
-       reg = bank->base;
-       switch (bank->method) {
-       case METHOD_GPIO_24XX:
-               input = _get_gpio_direction(bank, get_gpio_index(gpio));
-               switch (input) {
-               case OMAP_GPIO_DIR_IN:
-                       reg += OMAP_GPIO_DATAIN;
-                       break;
-               case OMAP_GPIO_DIR_OUT:
-                       reg += OMAP_GPIO_DATAOUT;
-                       break;
-               default:
-                       return -1;
-               }
-               break;
-       default:
-               return -1;
-       }
-       return (__raw_readl(reg)
-                       & (1 << get_gpio_index(gpio))) != 0;
+
+       return _get_gpio_value(bank, get_gpio_index(gpio));
 }
 
 /**
@@ -220,3 +241,95 @@ int gpio_free(unsigned gpio)
 {
        return 0;
 }
+
+#else /* new driver model interface CONFIG_DM_GPIO */
+
+/* set GPIO pin 'gpio' as an input */
+static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+       struct gpio_bank *bank = dev_get_priv(dev);
+
+       /* Configure GPIO direction as input. */
+       _set_gpio_direction(bank, offset, 1);
+
+       return 0;
+}
+
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
+                                      int value)
+{
+       struct gpio_bank *bank = dev_get_priv(dev);
+
+       _set_gpio_dataout(bank, offset, value);
+       _set_gpio_direction(bank, offset, 0);
+
+       return 0;
+}
+
+/* read GPIO IN value of pin 'gpio' */
+static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+       struct gpio_bank *bank = dev_get_priv(dev);
+
+       return _get_gpio_value(bank, offset);
+}
+
+/* write GPIO OUT value to pin 'gpio' */
+static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
+                                int value)
+{
+       struct gpio_bank *bank = dev_get_priv(dev);
+
+       _set_gpio_dataout(bank, offset, value);
+
+       return 0;
+}
+
+static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+       struct gpio_bank *bank = dev_get_priv(dev);
+
+       /* GPIOF_FUNC is not implemented yet */
+       if (_get_gpio_direction(bank->base, offset) == OMAP_GPIO_DIR_OUT)
+               return GPIOF_OUTPUT;
+       else
+               return GPIOF_INPUT;
+}
+
+static const struct dm_gpio_ops gpio_omap_ops = {
+       .direction_input        = omap_gpio_direction_input,
+       .direction_output       = omap_gpio_direction_output,
+       .get_value              = omap_gpio_get_value,
+       .set_value              = omap_gpio_set_value,
+       .get_function           = omap_gpio_get_function,
+};
+
+static int omap_gpio_probe(struct udevice *dev)
+{
+       struct gpio_bank *bank = dev_get_priv(dev);
+       struct omap_gpio_platdata *plat = dev_get_platdata(dev);
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       char name[18], *str;
+
+       sprintf(name, "GPIO%d_", plat->bank_index);
+       str = strdup(name);
+       if (!str)
+               return -ENOMEM;
+       uc_priv->bank_name = str;
+       uc_priv->gpio_count = GPIO_PER_BANK;
+       bank->base = (void *)plat->base;
+       bank->method = plat->method;
+
+       return 0;
+}
+
+U_BOOT_DRIVER(gpio_omap) = {
+       .name   = "gpio_omap",
+       .id     = UCLASS_GPIO,
+       .ops    = &gpio_omap_ops,
+       .probe  = omap_gpio_probe,
+       .priv_auto_alloc_size = sizeof(struct gpio_bank),
+};
+
+#endif /* CONFIG_DM_GPIO */
index db7b67373101636b61034b3fc90d2b147a33219a..6c41a42c177351adcd0d6f96ff81ae2a0f1036ee 100644 (file)
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
-#include <asm/arch/gpio.h>
+#include <dm/device-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 #define S5P_GPIO_GET_PIN(x)    (x % GPIO_PER_BANK)
 
-#define CON_MASK(x)            (0xf << ((x) << 2))
-#define CON_SFR(x, v)          ((v) << ((x) << 2))
+#define CON_MASK(val)                  (0xf << ((val) << 2))
+#define CON_SFR(gpio, cfg)             ((cfg) << ((gpio) << 2))
+#define CON_SFR_UNSHIFT(val, gpio)     ((val) >> ((gpio) << 2))
+
+#define DAT_MASK(gpio)                 (0x1 << (gpio))
+#define DAT_SET(gpio)                  (0x1 << (gpio))
 
-#define DAT_MASK(x)            (0x1 << (x))
-#define DAT_SET(x)             (0x1 << (x))
+#define PULL_MASK(gpio)                (0x3 << ((gpio) << 1))
+#define PULL_MODE(gpio, pull)          ((pull) << ((gpio) << 1))
 
-#define PULL_MASK(x)           (0x3 << ((x) << 1))
-#define PULL_MODE(x, v)                ((v) << ((x) << 1))
+#define DRV_MASK(gpio)                 (0x3 << ((gpio) << 1))
+#define DRV_SET(gpio, mode)            ((mode) << ((gpio) << 1))
+#define RATE_MASK(gpio)                (0x1 << (gpio + 16))
+#define RATE_SET(gpio)                 (0x1 << (gpio + 16))
 
-#define DRV_MASK(x)            (0x3 << ((x) << 1))
-#define DRV_SET(x, m)          ((m) << ((x) << 1))
-#define RATE_MASK(x)           (0x1 << (x + 16))
-#define RATE_SET(x)            (0x1 << (x + 16))
+/* Platform data for each bank */
+struct exynos_gpio_platdata {
+       struct s5p_gpio_bank *bank;
+       const char *bank_name;  /* Name of port, e.g. 'gpa0" */
+};
 
-#define name_to_gpio(n) s5p_name_to_gpio(n)
-static inline int s5p_name_to_gpio(const char *name)
+/* Information about each bank at run-time */
+struct exynos_bank_info {
+       struct s5p_gpio_bank *bank;
+};
+
+static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
 {
-       unsigned num, irregular_set_number, irregular_bank_base;
-       const struct gpio_name_num_table *tabp;
-       char this_bank, bank_name, irregular_bank_name;
-       char *endp;
-
-       /*
-        * The gpio name starts with either 'g' or 'gp' followed by the bank
-        * name character. Skip one or two characters depending on the prefix.
-        */
-       if (name[0] == 'g' && name[1] == 'p')
-               name += 2;
-       else if (name[0] == 'g')
-               name++;
-       else
-               return -1; /* Name must start with 'g' */
-
-       bank_name = *name++;
-       if (!*name)
-               return -1; /* At least one digit is required/expected. */
-
-       /*
-        * On both exynos5 and exynos5420 architectures there is a bank of
-        * GPIOs which does not fall into the regular address pattern. Those
-        * banks are c4 on Exynos5 and y7 on Exynos5420. The rest of the below
-        * assignments help to handle these irregularities.
-        */
-#if defined(CONFIG_EXYNOS4) || defined(CONFIG_EXYNOS5)
-       if (cpu_is_exynos5()) {
-               if (proid_is_exynos5420()) {
-                       tabp = exynos5420_gpio_table;
-                       irregular_bank_name = 'y';
-                       irregular_set_number = '7';
-                       irregular_bank_base = EXYNOS5420_GPIO_Y70;
-               } else {
-                       tabp = exynos5_gpio_table;
-                       irregular_bank_name = 'c';
-                       irregular_set_number = '4';
-                       irregular_bank_base = EXYNOS5_GPIO_C40;
-               }
-       } else {
-               if (proid_is_exynos4412())
-                       tabp = exynos4x12_gpio_table;
-               else
-                       tabp = exynos4_gpio_table;
-               irregular_bank_name = 0;
-               irregular_set_number = 0;
-               irregular_bank_base = 0;
-       }
-#else
-       if (cpu_is_s5pc110())
-               tabp = s5pc110_gpio_table;
-       else
-               tabp = s5pc100_gpio_table;
-       irregular_bank_name = 0;
-       irregular_set_number = 0;
-       irregular_bank_base = 0;
-#endif
+       const struct gpio_info *data;
+       unsigned int upto;
+       int i, count;
+
+       data = get_gpio_data();
+       count = get_bank_num();
+       upto = 0;
 
-       this_bank = tabp->bank;
-       do {
-               if (bank_name == this_bank) {
-                       unsigned pin_index; /* pin number within the bank */
-                       if ((bank_name == irregular_bank_name) &&
-                           (name[0] == irregular_set_number)) {
-                               pin_index = name[1] - '0';
-                               /* Irregular sets have 8 pins. */
-                               if (pin_index >= GPIO_PER_BANK)
-                                       return -1;
-                               num = irregular_bank_base + pin_index;
-                       } else {
-                               pin_index = simple_strtoul(name, &endp, 8);
-                               pin_index -= tabp->bank_offset;
-                               /*
-                                * Sanity check: bunk 'z' has no set number,
-                                * for all other banks there must be exactly
-                                * two octal digits, and the resulting number
-                                * should not exceed the number of pins in the
-                                * bank.
-                                */
-                               if (((bank_name != 'z') && !name[1]) ||
-                                   *endp ||
-                                   (pin_index >= tabp->bank_size))
-                                       return -1;
-                               num = tabp->base + pin_index;
-                       }
-                       return num;
+       for (i = 0; i < count; i++) {
+               debug("i=%d, upto=%d\n", i, upto);
+               if (gpio < data->max_gpio) {
+                       struct s5p_gpio_bank *bank;
+                       bank = (struct s5p_gpio_bank *)data->reg_addr;
+                       bank += (gpio - upto) / GPIO_PER_BANK;
+                       debug("gpio=%d, bank=%p\n", gpio, bank);
+                       return bank;
                }
-               this_bank = (++tabp)->bank;
-       } while (this_bank);
 
-       return -1;
+               upto = data->max_gpio;
+               data++;
+       }
+
+       return NULL;
 }
 
 static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
@@ -143,16 +92,23 @@ static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
        writel(value, &bank->dat);
 }
 
-static void s5p_gpio_direction_output(struct s5p_gpio_bank *bank,
-                                     int gpio, int en)
+#ifdef CONFIG_SPL_BUILD
+/* Common GPIO API - SPL does not support driver model yet */
+int gpio_set_value(unsigned gpio, int value)
 {
-       s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_OUTPUT);
-       s5p_gpio_set_value(bank, gpio, en);
-}
+       s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
+                          s5p_gpio_get_pin(gpio), value);
 
-static void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
+       return 0;
+}
+#else
+static int s5p_gpio_get_cfg_pin(struct s5p_gpio_bank *bank, int gpio)
 {
-       s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_INPUT);
+       unsigned int value;
+
+       value = readl(&bank->con);
+       value &= CON_MASK(gpio);
+       return CON_SFR_UNSHIFT(value, gpio);
 }
 
 static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
@@ -162,6 +118,7 @@ static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
        value = readl(&bank->dat);
        return !!(value & DAT_MASK(gpio));
 }
+#endif /* CONFIG_SPL_BUILD */
 
 static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
 {
@@ -222,78 +179,63 @@ static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
        writel(value, &bank->drv);
 }
 
-struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
-{
-       const struct gpio_info *data;
-       unsigned int upto;
-       int i, count;
-
-       data = get_gpio_data();
-       count = get_bank_num();
-       upto = 0;
-
-       for (i = 0; i < count; i++) {
-               debug("i=%d, upto=%d\n", i, upto);
-               if (gpio < data->max_gpio) {
-                       struct s5p_gpio_bank *bank;
-                       bank = (struct s5p_gpio_bank *)data->reg_addr;
-                       bank += (gpio - upto) / GPIO_PER_BANK;
-                       debug("gpio=%d, bank=%p\n", gpio, bank);
-                       return bank;
-               }
-
-               upto = data->max_gpio;
-               data++;
-       }
-
-       return NULL;
-}
-
 int s5p_gpio_get_pin(unsigned gpio)
 {
        return S5P_GPIO_GET_PIN(gpio);
 }
 
-/* Common GPIO API */
-
-int gpio_request(unsigned gpio, const char *label)
+/* Driver model interface */
+#ifndef CONFIG_SPL_BUILD
+/* set GPIO pin 'gpio' as an input */
+static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
-       return 0;
-}
+       struct exynos_bank_info *state = dev_get_priv(dev);
 
-int gpio_free(unsigned gpio)
-{
-       return 0;
-}
+       /* Configure GPIO direction as input. */
+       s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
 
-int gpio_direction_input(unsigned gpio)
-{
-       s5p_gpio_direction_input(s5p_gpio_get_bank(gpio),
-                               s5p_gpio_get_pin(gpio));
        return 0;
 }
 
-int gpio_direction_output(unsigned gpio, int value)
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
+                                      int value)
 {
-       s5p_gpio_direction_output(s5p_gpio_get_bank(gpio),
-                                s5p_gpio_get_pin(gpio), value);
+       struct exynos_bank_info *state = dev_get_priv(dev);
+
+       /* Configure GPIO output value. */
+       s5p_gpio_set_value(state->bank, offset, value);
+
+       /* Configure GPIO direction as output. */
+       s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_OUTPUT);
+
        return 0;
 }
 
-int gpio_get_value(unsigned gpio)
+/* read GPIO IN value of pin 'gpio' */
+static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
 {
-       return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio),
-                                      s5p_gpio_get_pin(gpio));
+       struct exynos_bank_info *state = dev_get_priv(dev);
+
+       return s5p_gpio_get_value(state->bank, offset);
 }
 
-int gpio_set_value(unsigned gpio, int value)
+/* write GPIO OUT value to pin 'gpio' */
+static int exynos_gpio_set_value(struct udevice *dev, unsigned offset,
+                                int value)
 {
-       s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
-                         s5p_gpio_get_pin(gpio), value);
+       struct exynos_bank_info *state = dev_get_priv(dev);
+
+       s5p_gpio_set_value(state->bank, offset, value);
 
        return 0;
 }
+#endif /* nCONFIG_SPL_BUILD */
 
+/*
+ * There is no common GPIO API for pull, drv, pin, rate (yet). These
+ * functions are kept here to preserve function ordering for review.
+ */
 void gpio_set_pull(int gpio, int mode)
 {
        s5p_gpio_set_pull(s5p_gpio_get_bank(gpio),
@@ -317,3 +259,112 @@ void gpio_set_rate(int gpio, int mode)
        s5p_gpio_set_rate(s5p_gpio_get_bank(gpio),
                          s5p_gpio_get_pin(gpio), mode);
 }
+
+#ifndef CONFIG_SPL_BUILD
+static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+       struct exynos_bank_info *state = dev_get_priv(dev);
+       int cfg;
+
+       cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
+       if (cfg == S5P_GPIO_OUTPUT)
+               return GPIOF_OUTPUT;
+       else if (cfg == S5P_GPIO_INPUT)
+               return GPIOF_INPUT;
+       else
+               return GPIOF_FUNC;
+}
+
+static const struct dm_gpio_ops gpio_exynos_ops = {
+       .direction_input        = exynos_gpio_direction_input,
+       .direction_output       = exynos_gpio_direction_output,
+       .get_value              = exynos_gpio_get_value,
+       .set_value              = exynos_gpio_set_value,
+       .get_function           = exynos_gpio_get_function,
+};
+
+static int gpio_exynos_probe(struct udevice *dev)
+{
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct exynos_bank_info *priv = dev->priv;
+       struct exynos_gpio_platdata *plat = dev->platdata;
+
+       /* Only child devices have ports */
+       if (!plat)
+               return 0;
+
+       priv->bank = plat->bank;
+
+       uc_priv->gpio_count = GPIO_PER_BANK;
+       uc_priv->bank_name = plat->bank_name;
+
+       return 0;
+}
+
+/**
+ * We have a top-level GPIO device with no actual GPIOs. It has a child
+ * device for each Exynos GPIO bank.
+ */
+static int gpio_exynos_bind(struct udevice *parent)
+{
+       struct exynos_gpio_platdata *plat = parent->platdata;
+       struct s5p_gpio_bank *bank, *base;
+       const void *blob = gd->fdt_blob;
+       int node;
+
+       /* If this is a child device, there is nothing to do here */
+       if (plat)
+               return 0;
+
+       base = (struct s5p_gpio_bank *)fdtdec_get_addr(gd->fdt_blob,
+                                                  parent->of_offset, "reg");
+       for (node = fdt_first_subnode(blob, parent->of_offset), bank = base;
+            node > 0;
+            node = fdt_next_subnode(blob, node), bank++) {
+               struct exynos_gpio_platdata *plat;
+               struct udevice *dev;
+               fdt_addr_t reg;
+               int ret;
+
+               if (!fdtdec_get_bool(blob, node, "gpio-controller"))
+                       continue;
+               plat = calloc(1, sizeof(*plat));
+               if (!plat)
+                       return -ENOMEM;
+               reg = fdtdec_get_addr(blob, node, "reg");
+               if (reg != FDT_ADDR_T_NONE)
+                       bank = (struct s5p_gpio_bank *)((ulong)base + reg);
+               plat->bank = bank;
+               plat->bank_name = fdt_get_name(blob, node, NULL);
+               debug("dev at %p: %s\n", bank, plat->bank_name);
+
+               ret = device_bind(parent, parent->driver,
+                                       plat->bank_name, plat, -1, &dev);
+               if (ret)
+                       return ret;
+               dev->of_offset = parent->of_offset;
+       }
+
+       return 0;
+}
+
+static const struct udevice_id exynos_gpio_ids[] = {
+       { .compatible = "samsung,s5pc100-pinctrl" },
+       { .compatible = "samsung,s5pc110-pinctrl" },
+       { .compatible = "samsung,exynos4210-pinctrl" },
+       { .compatible = "samsung,exynos4x12-pinctrl" },
+       { .compatible = "samsung,exynos5250-pinctrl" },
+       { .compatible = "samsung,exynos5420-pinctrl" },
+       { }
+};
+
+U_BOOT_DRIVER(gpio_exynos) = {
+       .name   = "gpio_exynos",
+       .id     = UCLASS_GPIO,
+       .of_match = exynos_gpio_ids,
+       .bind   = gpio_exynos_bind,
+       .probe = gpio_exynos_probe,
+       .priv_auto_alloc_size = sizeof(struct exynos_bank_info),
+       .ops    = &gpio_exynos_ops,
+};
+#endif
index 75ada5d3871a844935c22b1bb9557f2e3229c84f..53c80d5be65dd85c0dbe20d2e1823e0400a4937f 100644 (file)
@@ -14,7 +14,6 @@ DECLARE_GLOBAL_DATA_PTR;
 /* Flags for each GPIO */
 #define GPIOF_OUTPUT   (1 << 0)        /* Currently set as an output */
 #define GPIOF_HIGH     (1 << 1)        /* Currently set high */
-#define GPIOF_RESERVED (1 << 2)        /* Is in use / requested */
 
 struct gpio_state {
        const char *label;      /* label given by requester */
@@ -54,18 +53,6 @@ static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag,
        return 0;
 }
 
-static int check_reserved(struct udevice *dev, unsigned offset,
-                         const char *func)
-{
-       if (!get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
-               printf("sandbox_gpio: %s: error: offset %u not reserved\n",
-                      func, offset);
-               return -1;
-       }
-
-       return 0;
-}
-
 /*
  * Back-channel sandbox-internal-only access to GPIO state
  */
@@ -101,9 +88,6 @@ static int sb_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
        debug("%s: offset:%u\n", __func__, offset);
 
-       if (check_reserved(dev, offset, __func__))
-               return -1;
-
        return sandbox_gpio_set_direction(dev, offset, 0);
 }
 
@@ -113,9 +97,6 @@ static int sb_gpio_direction_output(struct udevice *dev, unsigned offset,
 {
        debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
-       if (check_reserved(dev, offset, __func__))
-               return -1;
-
        return sandbox_gpio_set_direction(dev, offset, 1) |
                sandbox_gpio_set_value(dev, offset, value);
 }
@@ -125,9 +106,6 @@ static int sb_gpio_get_value(struct udevice *dev, unsigned offset)
 {
        debug("%s: offset:%u\n", __func__, offset);
 
-       if (check_reserved(dev, offset, __func__))
-               return -1;
-
        return sandbox_gpio_get_value(dev, offset);
 }
 
@@ -136,9 +114,6 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
        debug("%s: offset:%u, value = %d\n", __func__, offset, value);
 
-       if (check_reserved(dev, offset, __func__))
-               return -1;
-
        if (!sandbox_gpio_get_direction(dev, offset)) {
                printf("sandbox_gpio: error: set_value on input gpio %u\n",
                       offset);
@@ -148,69 +123,19 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
        return sandbox_gpio_set_value(dev, offset, value);
 }
 
-static int sb_gpio_request(struct udevice *dev, unsigned offset,
-                          const char *label)
+static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
 {
-       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-       struct gpio_state *state = dev_get_priv(dev);
-
-       debug("%s: offset:%u, label:%s\n", __func__, offset, label);
-
-       if (offset >= uc_priv->gpio_count) {
-               printf("sandbox_gpio: error: invalid gpio %u\n", offset);
-               return -1;
-       }
-
-       if (get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
-               printf("sandbox_gpio: error: gpio %u already reserved\n",
-                      offset);
-               return -1;
-       }
-
-       state[offset].label = label;
-       return set_gpio_flag(dev, offset, GPIOF_RESERVED, 1);
-}
-
-static int sb_gpio_free(struct udevice *dev, unsigned offset)
-{
-       struct gpio_state *state = dev_get_priv(dev);
-
-       debug("%s: offset:%u\n", __func__, offset);
-
-       if (check_reserved(dev, offset, __func__))
-               return -1;
-
-       state[offset].label = NULL;
-       return set_gpio_flag(dev, offset, GPIOF_RESERVED, 0);
-}
-
-static int sb_gpio_get_state(struct udevice *dev, unsigned int offset,
-                            char *buf, int bufsize)
-{
-       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-       struct gpio_state *state = dev_get_priv(dev);
-       const char *label;
-
-       label = state[offset].label;
-       snprintf(buf, bufsize, "%s%d: %s: %d [%c]%s%s",
-                uc_priv->bank_name ? uc_priv->bank_name : "", offset,
-                sandbox_gpio_get_direction(dev, offset) ? "out" : " in",
-                sandbox_gpio_get_value(dev, offset),
-                get_gpio_flag(dev, offset, GPIOF_RESERVED) ? 'x' : ' ',
-                label ? " " : "",
-                label ? label : "");
-
-       return 0;
+       if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
+               return GPIOF_OUTPUT;
+       return GPIOF_INPUT;
 }
 
 static const struct dm_gpio_ops gpio_sandbox_ops = {
-       .request                = sb_gpio_request,
-       .free                   = sb_gpio_free,
        .direction_input        = sb_gpio_direction_input,
        .direction_output       = sb_gpio_direction_output,
        .get_value              = sb_gpio_get_value,
        .set_value              = sb_gpio_set_value,
-       .get_state              = sb_gpio_get_state,
+       .get_function           = sb_gpio_get_function,
 };
 
 static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
@@ -239,6 +164,13 @@ static int gpio_sandbox_probe(struct udevice *dev)
        return 0;
 }
 
+static int gpio_sandbox_remove(struct udevice *dev)
+{
+       free(dev->priv);
+
+       return 0;
+}
+
 static const struct udevice_id sandbox_gpio_ids[] = {
        { .compatible = "sandbox,gpio" },
        { }
@@ -250,5 +182,6 @@ U_BOOT_DRIVER(gpio_sandbox) = {
        .of_match = sandbox_gpio_ids,
        .ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
        .probe  = gpio_sandbox_probe,
+       .remove = gpio_sandbox_remove,
        .ops    = &gpio_sandbox_ops,
 };
index 1cc4abb8a938b16ccc1322a6adcc903bc064b299..88f7ef5bf04d9abce9605cd7e8e161a11b135a8d 100644 (file)
@@ -39,7 +39,6 @@ struct tegra_gpio_platdata {
 
 /* Information about each port at run-time */
 struct tegra_port_info {
-       char label[TEGRA_GPIOS_PER_PORT][GPIO_NAME_SIZE];
        struct gpio_ctlr_bank *bank;
        int base_gpio;          /* Port number for this port (0, 1,.., n-1) */
 };
@@ -132,21 +131,6 @@ static void set_level(unsigned gpio, int high)
        writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
 }
 
-static int check_reserved(struct udevice *dev, unsigned offset,
-                         const char *func)
-{
-       struct tegra_port_info *state = dev_get_priv(dev);
-       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-
-       if (!*state->label[offset]) {
-               printf("tegra_gpio: %s: error: gpio %s%d not reserved\n",
-                      func, uc_priv->bank_name, offset);
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
 int tegra_spl_gpio_direction_output(int gpio, int value)
 {
@@ -171,56 +155,16 @@ static int tegra_gpio_request(struct udevice *dev, unsigned offset,
 {
        struct tegra_port_info *state = dev_get_priv(dev);
 
-       if (*state->label[offset])
-               return -EBUSY;
-
-       strncpy(state->label[offset], label, GPIO_NAME_SIZE);
-       state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
-
        /* Configure as a GPIO */
        set_config(state->base_gpio + offset, 1);
 
        return 0;
 }
 
-static int tegra_gpio_free(struct udevice *dev, unsigned offset)
-{
-       struct tegra_port_info *state = dev_get_priv(dev);
-       int ret;
-
-       ret = check_reserved(dev, offset, __func__);
-       if (ret)
-               return ret;
-       state->label[offset][0] = '\0';
-
-       return 0;
-}
-
-/* read GPIO OUT value of pin 'gpio' */
-static int tegra_gpio_get_output_value(unsigned gpio)
-{
-       struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
-       struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
-       int val;
-
-       debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n",
-               gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
-
-       val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
-
-       return (val >> GPIO_BIT(gpio)) & 1;
-}
-
-
 /* set GPIO pin 'gpio' as an input */
 static int tegra_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
        struct tegra_port_info *state = dev_get_priv(dev);
-       int ret;
-
-       ret = check_reserved(dev, offset, __func__);
-       if (ret)
-               return ret;
 
        /* Configure GPIO direction as input. */
        set_direction(state->base_gpio + offset, 0);
@@ -234,11 +178,6 @@ static int tegra_gpio_direction_output(struct udevice *dev, unsigned offset,
 {
        struct tegra_port_info *state = dev_get_priv(dev);
        int gpio = state->base_gpio + offset;
-       int ret;
-
-       ret = check_reserved(dev, offset, __func__);
-       if (ret)
-               return ret;
 
        /* Configure GPIO output value. */
        set_level(gpio, value);
@@ -254,13 +193,8 @@ static int tegra_gpio_get_value(struct udevice *dev, unsigned offset)
 {
        struct tegra_port_info *state = dev_get_priv(dev);
        int gpio = state->base_gpio + offset;
-       int ret;
        int val;
 
-       ret = check_reserved(dev, offset, __func__);
-       if (ret)
-               return ret;
-
        debug("%s: pin = %d (port %d:bit %d)\n", __func__,
              gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
 
@@ -274,11 +208,6 @@ static int tegra_gpio_set_value(struct udevice *dev, unsigned offset, int value)
 {
        struct tegra_port_info *state = dev_get_priv(dev);
        int gpio = state->base_gpio + offset;
-       int ret;
-
-       ret = check_reserved(dev, offset, __func__);
-       if (ret)
-               return ret;
 
        debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
              gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
@@ -314,8 +243,6 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
        struct tegra_port_info *state = dev_get_priv(dev);
        int gpio = state->base_gpio + offset;
 
-       if (!*state->label[offset])
-               return GPIOF_UNUSED;
        if (!get_config(gpio))
                return GPIOF_FUNC;
        else if (get_direction(gpio))
@@ -324,50 +251,13 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
                return GPIOF_INPUT;
 }
 
-static int tegra_gpio_get_state(struct udevice *dev, unsigned int offset,
-                               char *buf, int bufsize)
-{
-       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
-       struct tegra_port_info *state = dev_get_priv(dev);
-       int gpio = state->base_gpio + offset;
-       const char *label;
-       int is_output;
-       int is_gpio;
-       int size;
-
-       label = state->label[offset];
-       is_gpio = get_config(gpio); /* GPIO, not SFPIO */
-       size = snprintf(buf, bufsize, "%s%d: ",
-                       uc_priv->bank_name ? uc_priv->bank_name : "", offset);
-       buf += size;
-       bufsize -= size;
-       if (is_gpio) {
-               is_output = get_direction(gpio);
-
-               snprintf(buf, bufsize, "%s: %d [%c]%s%s",
-                        is_output ? "out" : " in",
-                        is_output ?
-                               tegra_gpio_get_output_value(gpio) :
-                               tegra_gpio_get_value(dev, offset),
-                        *label ? 'x' : ' ',
-                        *label ? " " : "",
-                        label);
-       } else {
-               snprintf(buf, bufsize, "sfpio");
-       }
-
-       return 0;
-}
-
 static const struct dm_gpio_ops gpio_tegra_ops = {
        .request                = tegra_gpio_request,
-       .free                   = tegra_gpio_free,
        .direction_input        = tegra_gpio_direction_input,
        .direction_output       = tegra_gpio_direction_output,
        .get_value              = tegra_gpio_get_value,
        .set_value              = tegra_gpio_set_value,
        .get_function           = tegra_gpio_get_function,
-       .get_state              = tegra_gpio_get_state,
 };
 
 /**
index c891ebd39e243ebc5540e7db6291ed88f7e84678..e085a7095eaf55ef62bc9c47283bcfe20636740a 100644 (file)
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include "designware_i2c.h"
+#include <i2c.h>
 
 #ifdef CONFIG_I2C_MULTI_BUS
 static unsigned int bus_initialized[CONFIG_SYS_I2C_BUS_MAX];
@@ -76,16 +77,20 @@ static void set_speed(int i2c_spd)
  *
  * Set the i2c speed.
  */
-int i2c_set_bus_speed(int speed)
+int i2c_set_bus_speed(unsigned int speed)
 {
+       int i2c_spd;
+
        if (speed >= I2C_MAX_SPEED)
-               set_speed(IC_SPEED_MODE_MAX);
+               i2c_spd = IC_SPEED_MODE_MAX;
        else if (speed >= I2C_FAST_SPEED)
-               set_speed(IC_SPEED_MODE_FAST);
+               i2c_spd = IC_SPEED_MODE_FAST;
        else
-               set_speed(IC_SPEED_MODE_STANDARD);
+               i2c_spd = IC_SPEED_MODE_STANDARD;
 
-       return 0;
+       set_speed(i2c_spd);
+
+       return i2c_spd;
 }
 
 /*
@@ -93,7 +98,7 @@ int i2c_set_bus_speed(int speed)
  *
  * Gets the i2c speed.
  */
-int i2c_get_bus_speed(void)
+unsigned int i2c_get_bus_speed(void)
 {
        u32 cntl;
 
@@ -429,7 +434,7 @@ int i2c_set_bus_num(unsigned int bus)
        return 0;
 }
 
-int i2c_get_bus_num(void)
+unsigned int i2c_get_bus_num(void)
 {
        return current_bus;
 }
index ab3ffa0fc1535b89101f40877b5e4355b69ea1f2..9b2ca1e81ba33a7f94e539a020336015b30592fa 100644 (file)
@@ -20,8 +20,8 @@
 
 #if defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
-#elif defined(CONFIG_KIRKWOOD)
-#include <asm/arch/kirkwood.h>
+#elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARMADA_XP))
+#include <asm/arch/soc.h>
 #elif defined(CONFIG_SUNXI)
 #include <asm/arch/i2c.h>
 #else
index 257b72f0f7cdf71b40afc10a2d18a9d48fdf700d..562211e7deb6504b65a0a3a088ea7572e5cc93b0 100644 (file)
@@ -471,8 +471,8 @@ static void tegra_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
 }
 
 /* i2c write version without the register address */
-int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer, int len,
-                  bool end_with_repeated_start)
+static int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
+                         int len, bool end_with_repeated_start)
 {
        int rc;
 
@@ -493,7 +493,8 @@ int i2c_write_data(struct i2c_bus *bus, uchar chip, uchar *buffer, int len,
 }
 
 /* i2c read version without the register address */
-int i2c_read_data(struct i2c_bus *bus, uchar chip, uchar *buffer, int len)
+static int i2c_read_data(struct i2c_bus *bus, uchar chip, uchar *buffer,
+                               int len)
 {
        int rc;
 
index 7e36db0a71a0b74ffbf2ff4b3fedd1ac99718241..0ef94f7a00bb26c72bfb2d07b60f63dc9030d77b 100644 (file)
@@ -181,7 +181,7 @@ static void kbd_wait_for_fifo_init(struct keyb *config)
  * @param input                Input configuration
  * @return 1, to indicate that we have something to look at
  */
-int tegra_kbc_check(struct input_config *input)
+static int tegra_kbc_check(struct input_config *input)
 {
        kbd_wait_for_fifo_init(&config);
        check_for_keys(&config);
index 068373b94263a999098d6af4d6d7038b0a4c7995..521edfd5de5cf5698ff98c1627e30703c3649282 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <i2c.h>
 #include <cros_ec.h>
 #include <fdtdec.h>
@@ -24,6 +25,8 @@
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm-generic/gpio.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
 
 #ifdef DEBUG_TRACE
 #define debug_trace(fmt, b...) debug(fmt, #b)
@@ -38,7 +41,9 @@ enum {
        CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
 };
 
+#ifndef CONFIG_DM_CROS_EC
 static struct cros_ec_dev static_dev, *last_dev;
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -204,6 +209,9 @@ static int send_command_proto3(struct cros_ec_dev *dev,
                               const void *dout, int dout_len,
                               uint8_t **dinp, int din_len)
 {
+#ifdef CONFIG_DM_CROS_EC
+       struct dm_cros_ec_ops *ops;
+#endif
        int out_bytes, in_bytes;
        int rv;
 
@@ -218,6 +226,10 @@ static int send_command_proto3(struct cros_ec_dev *dev,
        if (in_bytes < 0)
                return in_bytes;
 
+#ifdef CONFIG_DM_CROS_EC
+       ops = dm_cros_ec_get_ops(dev->dev);
+       rv = ops->packet(dev->dev, out_bytes, in_bytes);
+#else
        switch (dev->interface) {
 #ifdef CONFIG_CROS_EC_SPI
        case CROS_EC_IF_SPI:
@@ -235,6 +247,7 @@ static int send_command_proto3(struct cros_ec_dev *dev,
                debug("%s: Unsupported interface\n", __func__);
                rv = -1;
        }
+#endif
        if (rv < 0)
                return rv;
 
@@ -246,6 +259,9 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
                        const void *dout, int dout_len,
                        uint8_t **dinp, int din_len)
 {
+#ifdef CONFIG_DM_CROS_EC
+       struct dm_cros_ec_ops *ops;
+#endif
        int ret = -1;
 
        /* Handle protocol version 3 support */
@@ -254,6 +270,11 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
                                           dout, dout_len, dinp, din_len);
        }
 
+#ifdef CONFIG_DM_CROS_EC
+       ops = dm_cros_ec_get_ops(dev->dev);
+       ret = ops->command(dev->dev, cmd, cmd_version,
+                          (const uint8_t *)dout, dout_len, dinp, din_len);
+#else
        switch (dev->interface) {
 #ifdef CONFIG_CROS_EC_SPI
        case CROS_EC_IF_SPI:
@@ -280,6 +301,7 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
        default:
                ret = -1;
        }
+#endif
 
        return ret;
 }
@@ -990,6 +1012,7 @@ int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state)
        return 0;
 }
 
+#ifndef CONFIG_DM_CROS_EC
 /**
  * Decode EC interface details from the device tree and allocate a suitable
  * device.
@@ -1055,11 +1078,61 @@ static int cros_ec_decode_fdt(const void *blob, int node,
 
        return 0;
 }
+#endif
 
-int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_register(struct udevice *dev)
 {
+       struct cros_ec_dev *cdev = dev->uclass_priv;
+       const void *blob = gd->fdt_blob;
+       int node = dev->of_offset;
        char id[MSG_BYTES];
+
+       cdev->dev = dev;
+       fdtdec_decode_gpio(blob, node, "ec-interrupt", &cdev->ec_int);
+       cdev->optimise_flash_write = fdtdec_get_bool(blob, node,
+                                                    "optimise-flash-write");
+
+       /* we will poll the EC interrupt line */
+       fdtdec_setup_gpio(&cdev->ec_int);
+       if (fdt_gpio_isvalid(&cdev->ec_int)) {
+               gpio_request(cdev->ec_int.gpio, "cros-ec-irq");
+               gpio_direction_input(cdev->ec_int.gpio);
+       }
+
+       if (cros_ec_check_version(cdev)) {
+               debug("%s: Could not detect CROS-EC version\n", __func__);
+               return -CROS_EC_ERR_CHECK_VERSION;
+       }
+
+       if (cros_ec_read_id(cdev, id, sizeof(id))) {
+               debug("%s: Could not read KBC ID\n", __func__);
+               return -CROS_EC_ERR_READ_ID;
+       }
+
+       /* Remember this device for use by the cros_ec command */
+       debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
+
+       return 0;
+}
+#else
+int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
+{
        struct cros_ec_dev *dev;
+       char id[MSG_BYTES];
+#ifdef CONFIG_DM_CROS_EC
+       struct udevice *udev;
+       int ret;
+
+       ret = uclass_find_device(UCLASS_CROS_EC, 0, &udev);
+       if (!ret)
+               device_remove(udev);
+       ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
+       if (ret)
+               return ret;
+       dev = udev->uclass_priv;
+       return 0;
+#else
        int node = 0;
 
        *cros_ecp = NULL;
@@ -1108,11 +1181,14 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
        default:
                return 0;
        }
+#endif
 
        /* we will poll the EC interrupt line */
        fdtdec_setup_gpio(&dev->ec_int);
-       if (fdt_gpio_isvalid(&dev->ec_int))
+       if (fdt_gpio_isvalid(&dev->ec_int)) {
+               gpio_request(dev->ec_int.gpio, "cros-ec-irq");
                gpio_direction_input(dev->ec_int.gpio);
+       }
 
        if (cros_ec_check_version(dev)) {
                debug("%s: Could not detect CROS-EC version\n", __func__);
@@ -1125,11 +1201,15 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
        }
 
        /* Remember this device for use by the cros_ec command */
-       last_dev = *cros_ecp = dev;
+       *cros_ecp = dev;
+#ifndef CONFIG_DM_CROS_EC
+       last_dev = dev;
+#endif
        debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
 
        return 0;
 }
+#endif
 
 int cros_ec_decode_region(int argc, char * const argv[])
 {
@@ -1147,15 +1227,10 @@ int cros_ec_decode_region(int argc, char * const argv[])
        return -1;
 }
 
-int cros_ec_decode_ec_flash(const void *blob, struct fdt_cros_ec *config)
+int cros_ec_decode_ec_flash(const void *blob, int node,
+                           struct fdt_cros_ec *config)
 {
-       int flash_node, node;
-
-       node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
-       if (node < 0) {
-               debug("Failed to find chrome-ec node'\n");
-               return -1;
-       }
+       int flash_node;
 
        flash_node = fdt_subnode_offset(blob, node, "flash");
        if (flash_node < 0) {
@@ -1516,7 +1591,10 @@ static int cros_ec_i2c_passthrough(struct cros_ec_dev *dev, int flag,
 
 static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       struct cros_ec_dev *dev = last_dev;
+       struct cros_ec_dev *dev;
+#ifdef CONFIG_DM_CROS_EC
+       struct udevice *udev;
+#endif
        const char *cmd;
        int ret = 0;
 
@@ -1525,19 +1603,31 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        cmd = argv[1];
        if (0 == strcmp("init", cmd)) {
+#ifndef CONFIG_DM_CROS_EC
                ret = cros_ec_init(gd->fdt_blob, &dev);
                if (ret) {
                        printf("Could not init cros_ec device (err %d)\n", ret);
                        return 1;
                }
+#endif
                return 0;
        }
 
+#ifdef CONFIG_DM_CROS_EC
+       ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
+       if (ret) {
+               printf("Cannot get cros-ec device (err=%d)\n", ret);
+               return 1;
+       }
+       dev = udev->uclass_priv;
+#else
        /* Just use the last allocated device; there should be only one */
        if (!last_dev) {
                printf("No CROS-EC device available\n");
                return 1;
        }
+       dev = last_dev;
+#endif
        if (0 == strcmp("id", cmd)) {
                char id[MSG_BYTES];
 
@@ -1794,3 +1884,11 @@ U_BOOT_CMD(
        "crosec i2c mw chip address[.0, .1, .2] value [count] - write to I2C passthru (fill)"
 );
 #endif
+
+#ifdef CONFIG_DM_CROS_EC
+UCLASS_DRIVER(cros_ec) = {
+       .id             = UCLASS_CROS_EC,
+       .name           = "cros_ec",
+       .per_device_auto_alloc_size = sizeof(struct cros_ec_dev),
+};
+#endif
index 0e02671c93d46652864d9e83bf4a7d3d9f658e2e..07624a136fa47def2c330ae229c25a1cd822a3dc 100644 (file)
@@ -54,7 +54,7 @@ int cros_ec_lpc_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
        int csum;
        int i;
 
-       if (dout_len > EC_HOST_PARAM_SIZE) {
+       if (dout_len > EC_PROTO2_MAX_PARAM_SIZE) {
                debug("%s: Cannot send %d bytes\n", __func__, dout_len);
                return -1;
        }
@@ -159,7 +159,7 @@ int cros_ec_lpc_init(struct cros_ec_dev *dev, const void *blob)
        byte = 0xff;
        byte &= inb(EC_LPC_ADDR_HOST_CMD);
        byte &= inb(EC_LPC_ADDR_HOST_DATA);
-       for (i = 0; i < EC_HOST_PARAM_SIZE && (byte == 0xff); i++)
+       for (i = 0; i < EC_PROTO2_MAX_PARAM_SIZE && (byte == 0xff); i++)
                byte &= inb(EC_LPC_ADDR_HOST_PARAM + i);
        if (byte == 0xff) {
                debug("%s: CROS_EC device not found on LPC bus\n",
index 8a04af557d035e6211865e4f2e1662d105d4447d..99cc5297cfb866acddd6495c088b681171d2c8f1 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <cros_ec.h>
+#include <dm.h>
 #include <ec_commands.h>
 #include <errno.h>
 #include <hash.h>
@@ -85,7 +86,7 @@ struct ec_state {
        struct ec_keymatrix_entry *matrix;      /* the key matrix info */
        uint8_t keyscan[KEYBOARD_COLS];
        bool recovery_req;
-} s_state, *state;
+} s_state, *g_state;
 
 /**
  * cros_ec_read_state() - read the sandbox EC state from the state file
@@ -138,7 +139,7 @@ static int cros_ec_read_state(const void *blob, int node)
  */
 static int cros_ec_write_state(void *blob, int node)
 {
-       struct ec_state *ec = &s_state;
+       struct ec_state *ec = g_state;
 
        /* We are guaranteed enough space to write basic properties */
        fdt_setprop_u32(blob, node, "current-image", ec->current_image);
@@ -369,7 +370,7 @@ static int process_cmd(struct ec_state *ec,
                struct fmap_entry *entry;
                int ret, size;
 
-               entry = &state->ec_config.region[EC_FLASH_REGION_RW];
+               entry = &ec->ec_config.region[EC_FLASH_REGION_RW];
 
                switch (req->cmd) {
                case EC_VBOOT_HASH_RECALC:
@@ -426,7 +427,7 @@ static int process_cmd(struct ec_state *ec,
                case EC_FLASH_REGION_RO:
                case EC_FLASH_REGION_RW:
                case EC_FLASH_REGION_WP_RO:
-                       entry = &state->ec_config.region[req->region];
+                       entry = &ec->ec_config.region[req->region];
                        resp->offset = entry->offset;
                        resp->size = entry->length;
                        len = sizeof(*resp);
@@ -466,16 +467,24 @@ static int process_cmd(struct ec_state *ec,
        return len;
 }
 
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_sandbox_packet(struct udevice *udev, int out_bytes, int in_bytes)
+{
+       struct cros_ec_dev *dev = udev->uclass_priv;
+       struct ec_state *ec = dev_get_priv(dev->dev);
+#else
 int cros_ec_sandbox_packet(struct cros_ec_dev *dev, int out_bytes,
                           int in_bytes)
 {
+       struct ec_state *ec = &s_state;
+#endif
        struct ec_host_request *req_hdr = (struct ec_host_request *)dev->dout;
        const void *req_data = req_hdr + 1;
        struct ec_host_response *resp_hdr = (struct ec_host_response *)dev->din;
        void *resp_data = resp_hdr + 1;
        int len;
 
-       len = process_cmd(&s_state, req_hdr, req_data, resp_hdr, resp_data);
+       len = process_cmd(ec, req_hdr, req_data, resp_hdr, resp_data);
        if (len < 0)
                return len;
 
@@ -498,7 +507,11 @@ int cros_ec_sandbox_decode_fdt(struct cros_ec_dev *dev, const void *blob)
 
 void cros_ec_check_keyboard(struct cros_ec_dev *dev)
 {
+#ifdef CONFIG_DM_CROS_EC
+       struct ec_state *ec = dev_get_priv(dev->dev);
+#else
        struct ec_state *ec = &s_state;
+#endif
        ulong start;
 
        printf("Press keys for EC to detect on reset (ESC=recovery)...");
@@ -512,6 +525,52 @@ void cros_ec_check_keyboard(struct cros_ec_dev *dev)
        }
 }
 
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_probe(struct udevice *dev)
+{
+       struct ec_state *ec = dev->priv;
+       struct cros_ec_dev *cdev = dev->uclass_priv;
+       const void *blob = gd->fdt_blob;
+       int node;
+       int err;
+
+       memcpy(ec, &s_state, sizeof(*ec));
+       err = cros_ec_decode_ec_flash(blob, dev->of_offset, &ec->ec_config);
+       if (err)
+               return err;
+
+       node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
+       if (node < 0) {
+               debug("%s: No cros_ec keyboard found\n", __func__);
+       } else if (keyscan_read_fdt_matrix(ec, blob, node)) {
+               debug("%s: Could not read key matrix\n", __func__);
+               return -1;
+       }
+
+       /* If we loaded EC data, check that the length matches */
+       if (ec->flash_data &&
+           ec->flash_data_len != ec->ec_config.flash.length) {
+               printf("EC data length is %x, expected %x, discarding data\n",
+                      ec->flash_data_len, ec->ec_config.flash.length);
+               os_free(ec->flash_data);
+               ec->flash_data = NULL;
+       }
+
+       /* Otherwise allocate the memory */
+       if (!ec->flash_data) {
+               ec->flash_data_len = ec->ec_config.flash.length;
+               ec->flash_data = os_malloc(ec->flash_data_len);
+               if (!ec->flash_data)
+                       return -ENOMEM;
+       }
+
+       cdev->dev = dev;
+       g_state = ec;
+       return cros_ec_register(dev);
+}
+
+#else
+
 /**
  * Initialize sandbox EC emulation.
  *
@@ -525,8 +584,13 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob)
        int node;
        int err;
 
-       state = &s_state;
-       err = cros_ec_decode_ec_flash(blob, &ec->ec_config);
+       node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
+       if (node < 0) {
+               debug("Failed to find chrome-ec node'\n");
+               return -1;
+       }
+
+       err = cros_ec_decode_ec_flash(blob, node, &ec->ec_config);
        if (err)
                return err;
 
@@ -557,3 +621,24 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob)
 
        return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_CROS_EC
+struct dm_cros_ec_ops cros_ec_ops = {
+       .packet = cros_ec_sandbox_packet,
+};
+
+static const struct udevice_id cros_ec_ids[] = {
+       { .compatible = "google,cros-ec" },
+       { }
+};
+
+U_BOOT_DRIVER(cros_ec_sandbox) = {
+       .name           = "cros_ec",
+       .id             = UCLASS_CROS_EC,
+       .of_match       = cros_ec_ids,
+       .probe          = cros_ec_probe,
+       .priv_auto_alloc_size = sizeof(struct ec_state),
+       .ops            = &cros_ec_ops,
+};
+#endif
index 015333f139a209fd686a4ac173aba02baeeb1b33..e403664bb561755184c60e9020e028b84169d40f 100644 (file)
 
 #include <common.h>
 #include <cros_ec.h>
+#include <dm.h>
+#include <errno.h>
 #include <spi.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_spi_packet(struct udevice *udev, int out_bytes, int in_bytes)
+{
+       struct cros_ec_dev *dev = udev->uclass_priv;
+#else
 int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes)
 {
+#endif
+       struct spi_slave *slave = dev_get_parentdata(dev->dev);
        int rv;
 
        /* Do the transfer */
-       if (spi_claim_bus(dev->spi)) {
+       if (spi_claim_bus(slave)) {
                debug("%s: Cannot claim SPI bus\n", __func__);
                return -1;
        }
 
-       rv = spi_xfer(dev->spi, max(out_bytes, in_bytes) * 8,
+       rv = spi_xfer(slave, max(out_bytes, in_bytes) * 8,
                      dev->dout, dev->din,
                      SPI_XFER_BEGIN | SPI_XFER_END);
 
-       spi_release_bus(dev->spi);
+       spi_release_bus(slave);
 
        if (rv) {
                debug("%s: Cannot complete SPI transfer\n", __func__);
@@ -56,10 +67,19 @@ int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes)
  * @param din_len      Maximum size of response in bytes
  * @return number of bytes in response, or -1 on error
  */
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_spi_command(struct udevice *udev, uint8_t cmd, int cmd_version,
+                    const uint8_t *dout, int dout_len,
+                    uint8_t **dinp, int din_len)
+{
+       struct cros_ec_dev *dev = udev->uclass_priv;
+#else
 int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
                     const uint8_t *dout, int dout_len,
                     uint8_t **dinp, int din_len)
 {
+#endif
+       struct spi_slave *slave = dev_get_parentdata(dev->dev);
        int in_bytes = din_len + 4;     /* status, length, checksum, trailer */
        uint8_t *out;
        uint8_t *p;
@@ -92,7 +112,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
         */
        memset(dev->din, '\0', in_bytes);
 
-       if (spi_claim_bus(dev->spi)) {
+       if (spi_claim_bus(slave)) {
                debug("%s: Cannot claim SPI bus\n", __func__);
                return -1;
        }
@@ -113,10 +133,10 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
        p = dev->din + sizeof(int64_t) - 2;
        len = dout_len + 4;
        cros_ec_dump_data("out", cmd, out, len);
-       rv = spi_xfer(dev->spi, max(len, in_bytes) * 8, out, p,
+       rv = spi_xfer(slave, max(len, in_bytes) * 8, out, p,
                      SPI_XFER_BEGIN | SPI_XFER_END);
 
-       spi_release_bus(dev->spi);
+       spi_release_bus(slave);
 
        if (rv) {
                debug("%s: Cannot complete SPI transfer\n", __func__);
@@ -146,6 +166,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
        return len;
 }
 
+#ifndef CONFIG_DM_CROS_EC
 int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
 {
        /* Decode interface-specific FDT params */
@@ -165,11 +186,59 @@ int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
  */
 int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
 {
-       dev->spi = spi_setup_slave_fdt(blob, dev->node, dev->parent_node);
-       if (!dev->spi) {
+       int ret;
+
+       ret = spi_setup_slave_fdt(blob, dev->node, dev->parent_node,
+                                 &slave);
+       if (ret) {
                debug("%s: Could not setup SPI slave\n", __func__);
-               return -1;
+               return ret;
        }
 
        return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_probe(struct udevice *dev)
+{
+       struct spi_slave *slave = dev_get_parentdata(dev);
+       int ret;
+
+       /*
+        * TODO(sjg@chromium.org)
+        *
+        * This is really horrible at present. It is an artifact of removing
+        * the child_pre_probe() method for SPI. Everything here could go in
+        * an automatic function, except that spi_get_bus_and_cs() wants to
+        * set it up manually and call device_probe_child().
+        *
+        * The solution may be to re-enable the child_pre_probe() method for
+        * SPI and have it do nothing if the child is already passed in via
+        * device_probe_child().
+        */
+       slave->dev = dev;
+       ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
+       if (ret)
+               return ret;
+       return cros_ec_register(dev);
+}
+
+struct dm_cros_ec_ops cros_ec_ops = {
+       .packet = cros_ec_spi_packet,
+       .command = cros_ec_spi_command,
+};
+
+static const struct udevice_id cros_ec_ids[] = {
+       { .compatible = "google,cros-ec" },
+       { }
+};
+
+U_BOOT_DRIVER(cros_ec_spi) = {
+       .name           = "cros_ec",
+       .id             = UCLASS_CROS_EC,
+       .of_match       = cros_ec_ids,
+       .probe          = cros_ec_probe,
+       .ops            = &cros_ec_ops,
+};
+#endif
index 82079d67cd8fc07565e5b8c57cc7e7c8234793b7..92f7d8942f02d1420e397664afcb99b938a3dafc 100644 (file)
@@ -40,6 +40,7 @@
 #include <malloc.h>
 #include <sdhci.h>
 #include <asm/arch/timer.h>
+#include <asm/arch-bcm2835/sdhci.h>
 
 /* 400KHz is max freq for card ID etc. Use that as min */
 #define MIN_FREQ 400000
index d34e74357f0a4e74055f0280e969b6eda6add4c6..9f98c3f37c9790858a873b90fdcf27845fce15bc 100644 (file)
@@ -14,7 +14,7 @@
 #include <mmc.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <mvebu_mmc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
index 5b0c3020693c325a396b6726fd01d920776122f3..ef2cbf9e2fa574cd2846c280149cca2cf1dbc28b 100644 (file)
@@ -67,14 +67,19 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
 #ifdef OMAP_HSMMC_USE_GPIO
 static int omap_mmc_setup_gpio_in(int gpio, const char *label)
 {
-       if (!gpio_is_valid(gpio))
-               return -1;
+       int ret;
 
-       if (gpio_request(gpio, label) < 0)
+#ifndef CONFIG_DM_GPIO
+       if (!gpio_is_valid(gpio))
                return -1;
+#endif
+       ret = gpio_request(gpio, label);
+       if (ret)
+               return ret;
 
-       if (gpio_direction_input(gpio) < 0)
-               return -1;
+       ret = gpio_direction_input(gpio);
+       if (ret)
+               return ret;
 
        return gpio;
 }
index 637dd972a5b3612d74b0ec3b6924f9f8544aa344..0dea45d079f33e9c4f8b3b55288d7f508e4abc2d 100644 (file)
@@ -102,6 +102,7 @@ struct sdhci_host sdhci_host[SDHCI_MAX_HOSTS];
 
 static int do_sdhci_init(struct sdhci_host *host)
 {
+       char str[20];
        int dev_id, flag;
        int err = 0;
 
@@ -109,6 +110,8 @@ static int do_sdhci_init(struct sdhci_host *host)
        dev_id = host->index + PERIPH_ID_SDMMC0;
 
        if (fdt_gpio_isvalid(&host->pwr_gpio)) {
+               sprintf(str, "sdhci%d_power", host->index & 0xf);
+               gpio_request(host->pwr_gpio.gpio, str);
                gpio_direction_output(host->pwr_gpio.gpio, 1);
                err = exynos_pinmux_config(dev_id, flag);
                if (err) {
@@ -118,7 +121,9 @@ static int do_sdhci_init(struct sdhci_host *host)
        }
 
        if (fdt_gpio_isvalid(&host->cd_gpio)) {
-               gpio_direction_output(host->cd_gpio.gpio, 0xf);
+               sprintf(str, "sdhci%d_cd", host->index & 0xf);
+               gpio_request(host->cd_gpio.gpio, str);
+               gpio_direction_output(host->cd_gpio.gpio, 1);
                if (gpio_get_value(host->cd_gpio.gpio))
                        return -ENODEV;
 
index 3125d13ba3ce8e8e2552248e41c059bd31e5fb3c..de88e19609f37aaba48665e9bff60f6a7b63f31b 100644 (file)
@@ -124,7 +124,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
 #endif
 #define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT       100
 
-int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
+static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
                       struct mmc_data *data)
 {
        struct sdhci_host *host = mmc->priv;
@@ -355,7 +355,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
        sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 }
 
-void sdhci_set_ios(struct mmc *mmc)
+static void sdhci_set_ios(struct mmc *mmc)
 {
        u32 ctrl;
        struct sdhci_host *host = mmc->priv;
@@ -393,7 +393,7 @@ void sdhci_set_ios(struct mmc *mmc)
        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 }
 
-int sdhci_init(struct mmc *mmc)
+static int sdhci_init(struct mmc *mmc)
 {
        struct sdhci_host *host = mmc->priv;
 
index ca9c4aa15feea77686f8d5e87b7f24bdb8e1be89..2bd36b0ee704a86308bfa0d3c7faa68cc506249a 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/mmc.h>
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <mmc.h>
 
@@ -292,7 +293,7 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
                                /* Transfer Complete */
                                debug("r/w is done\n");
                                break;
-                       } else if (get_timer(start) > 2000UL) {
+                       } else if (get_timer(start) > 8000UL) {
                                writel(mask, &host->reg->norintsts);
                                printf("%s: MMC Timeout\n"
                                       "    Interrupt status        0x%08x\n"
@@ -508,7 +509,7 @@ static int tegra_mmc_core_init(struct mmc *mmc)
        return 0;
 }
 
-int tegra_mmc_getcd(struct mmc *mmc)
+static int tegra_mmc_getcd(struct mmc *mmc)
 {
        struct mmc_host *host = mmc->priv;
 
index 9b3175d87fbdabff14d922ce4c64d620b9aa60f4..50983b837b2238b781477f13b559502047b1ad6e 100644 (file)
@@ -63,6 +63,12 @@ flash_info_t flash_info[CFI_MAX_FLASH_BANKS];        /* FLASH chips info */
 #define CONFIG_SYS_FLASH_CFI_WIDTH     FLASH_CFI_8BIT
 #endif
 
+#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
+#define __maybe_weak __weak
+#else
+#define __maybe_weak static
+#endif
+
 /*
  * 0xffff is an undefined value for the configuration register. When
  * this value is returned, the configuration register shall not be
@@ -81,14 +87,12 @@ static u16 cfi_flash_config_reg(int i)
 int cfi_flash_num_flash_banks = CONFIG_SYS_MAX_FLASH_BANKS_DETECT;
 #endif
 
-static phys_addr_t __cfi_flash_bank_addr(int i)
+__weak phys_addr_t cfi_flash_bank_addr(int i)
 {
        return ((phys_addr_t [])CONFIG_SYS_FLASH_BANKS_LIST)[i];
 }
-phys_addr_t cfi_flash_bank_addr(int i)
-       __attribute__((weak, alias("__cfi_flash_bank_addr")));
 
-static unsigned long __cfi_flash_bank_size(int i)
+__weak unsigned long cfi_flash_bank_size(int i)
 {
 #ifdef CONFIG_SYS_FLASH_BANKS_SIZES
        return ((unsigned long [])CONFIG_SYS_FLASH_BANKS_SIZES)[i];
@@ -96,71 +100,49 @@ static unsigned long __cfi_flash_bank_size(int i)
        return 0;
 #endif
 }
-unsigned long cfi_flash_bank_size(int i)
-       __attribute__((weak, alias("__cfi_flash_bank_size")));
 
-static void __flash_write8(u8 value, void *addr)
+__maybe_weak void flash_write8(u8 value, void *addr)
 {
        __raw_writeb(value, addr);
 }
 
-static void __flash_write16(u16 value, void *addr)
+__maybe_weak void flash_write16(u16 value, void *addr)
 {
        __raw_writew(value, addr);
 }
 
-static void __flash_write32(u32 value, void *addr)
+__maybe_weak void flash_write32(u32 value, void *addr)
 {
        __raw_writel(value, addr);
 }
 
-static void __flash_write64(u64 value, void *addr)
+__maybe_weak void flash_write64(u64 value, void *addr)
 {
        /* No architectures currently implement __raw_writeq() */
        *(volatile u64 *)addr = value;
 }
 
-static u8 __flash_read8(void *addr)
+__maybe_weak u8 flash_read8(void *addr)
 {
        return __raw_readb(addr);
 }
 
-static u16 __flash_read16(void *addr)
+__maybe_weak u16 flash_read16(void *addr)
 {
        return __raw_readw(addr);
 }
 
-static u32 __flash_read32(void *addr)
+__maybe_weak u32 flash_read32(void *addr)
 {
        return __raw_readl(addr);
 }
 
-static u64 __flash_read64(void *addr)
+__maybe_weak u64 flash_read64(void *addr)
 {
        /* No architectures currently implement __raw_readq() */
        return *(volatile u64 *)addr;
 }
 
-#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
-void flash_write8(u8 value, void *addr)__attribute__((weak, alias("__flash_write8")));
-void flash_write16(u16 value, void *addr)__attribute__((weak, alias("__flash_write16")));
-void flash_write32(u32 value, void *addr)__attribute__((weak, alias("__flash_write32")));
-void flash_write64(u64 value, void *addr)__attribute__((weak, alias("__flash_write64")));
-u8 flash_read8(void *addr)__attribute__((weak, alias("__flash_read8")));
-u16 flash_read16(void *addr)__attribute__((weak, alias("__flash_read16")));
-u32 flash_read32(void *addr)__attribute__((weak, alias("__flash_read32")));
-u64 flash_read64(void *addr)__attribute__((weak, alias("__flash_read64")));
-#else
-#define flash_write8   __flash_write8
-#define flash_write16  __flash_write16
-#define flash_write32  __flash_write32
-#define flash_write64  __flash_write64
-#define flash_read8    __flash_read8
-#define flash_read16   __flash_read16
-#define flash_read32   __flash_read32
-#define flash_read64   __flash_read64
-#endif
-
 /*-----------------------------------------------------------------------
  */
 #if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) || (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
index 3e5fb0cd65a243d77fe2759556bab0f9209beec1..4fc34d6b9fca6d7b41ff44f52912da85532d1b9b 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <common.h>
 #include <asm/io.h>
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <nand.h>
 
 /* NAND Flash Soc registers */
index db1599e9a641402e811c9e6172e35909098a0769..40d670563c1e447c172f075eabda3d304433f693 100644 (file)
@@ -75,7 +75,7 @@ static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
 
 #ifdef CONFIG_SPL_BUILD
 /* Check wait pin as dev ready indicator */
-int omap_spl_dev_ready(struct mtd_info *mtd)
+static int omap_spl_dev_ready(struct mtd_info *mtd)
 {
        return gpmc_cfg->status & (1 << 8);
 }
@@ -161,23 +161,6 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
        return 0;
 }
 
-/*
- * omap_reverse_list - re-orders list elements in reverse order [internal]
- * @list:      pointer to start of list
- * @length:    length of list
-*/
-void omap_reverse_list(u8 *list, unsigned int length)
-{
-       unsigned int i, j;
-       unsigned int half_length = length / 2;
-       u8 tmp;
-       for (i = 0, j = length - 1; i < half_length; i++, j--) {
-               tmp = list[i];
-               list[i] = list[j];
-               list[j] = tmp;
-       }
-}
-
 /*
  * omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
  * @mtd:       MTD device structure
@@ -350,6 +333,23 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
 }
 
 #ifdef CONFIG_NAND_OMAP_ELM
+/*
+ * omap_reverse_list - re-orders list elements in reverse order [internal]
+ * @list:      pointer to start of list
+ * @length:    length of list
+*/
+static void omap_reverse_list(u8 *list, unsigned int length)
+{
+       unsigned int i, j;
+       unsigned int half_length = length / 2;
+       u8 tmp;
+       for (i = 0, j = length - 1; i < half_length; i++, j--) {
+               tmp = list[i];
+               list[i] = list[j];
+               list[j] = tmp;
+       }
+}
+
 /*
  * omap_correct_data_bch - Compares the ecc read from nand spare area
  * with ECC registers values and corrects one bit error if it has occured
index 9e18fb41de624b4684e19e435c5513525c38de5e..15789a07d8f674786e201581784a7ffb9c37bfed 100644 (file)
@@ -5,13 +5,18 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-$(CONFIG_DM_SPI_FLASH) += sf-uclass.o
+
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_SPI_LOAD)     += spi_spl_load.o
 obj-$(CONFIG_SPL_SPI_BOOT)     += fsl_espi_spl.o
 endif
 
+#ifndef CONFIG_DM_SPI
+obj-$(CONFIG_SPI_FLASH) += sf_probe.o
+#endif
 obj-$(CONFIG_CMD_SF) += sf.o
-obj-$(CONFIG_SPI_FLASH) += sf_params.o sf_probe.o sf_ops.o
+obj-$(CONFIG_SPI_FLASH) += sf_ops.o sf_params.o
 obj-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.o
 obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
 obj-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o
index d50da37c89af4418b5a6ad52c297007f6bb3dfc3..a23032cca58df0fdc2f304ce8aabaef253bd54fd 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <spi.h>
 #include <spi_flash.h>
 #include "sf_internal.h"
 
index 98e0a34d4e3b2fa74017fff981b80f47d0736271..1cf2f98310a17493a5a99cce29caa652cb9aabd1 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <spi.h>
 #include <os.h>
 #include <asm/getopt.h>
 #include <asm/spi.h>
 #include <asm/state.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/uclass-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 /*
  * The different states that our SPI flash transitions between.
@@ -34,12 +40,14 @@ enum sandbox_sf_state {
        SF_ERASE, /* erase the flash */
        SF_READ_STATUS, /* read the flash's status register */
        SF_READ_STATUS1, /* read the flash's status register upper 8 bits*/
+       SF_WRITE_STATUS, /* write the flash's status register */
 };
 
 static const char *sandbox_sf_state_name(enum sandbox_sf_state state)
 {
        static const char * const states[] = {
                "CMD", "ID", "ADDR", "READ", "WRITE", "ERASE", "READ_STATUS",
+               "READ_STATUS1", "WRITE_STATUS",
        };
        return states[state];
 }
@@ -58,6 +66,7 @@ static u8 sandbox_sf_0xff[0x1000];
 
 /* Internal state data for each SPI flash */
 struct sandbox_spi_flash {
+       unsigned int cs;        /* Chip select we are attached to */
        /*
         * As we receive data over the SPI bus, our flash transitions
         * between states.  For example, we start off in the SF_CMD
@@ -84,71 +93,124 @@ struct sandbox_spi_flash {
        int fd;
 };
 
-static int sandbox_sf_setup(void **priv, const char *spec)
+struct sandbox_spi_flash_plat_data {
+       const char *filename;
+       const char *device_name;
+       int bus;
+       int cs;
+};
+
+/**
+ * This is a very strange probe function. If it has platform data (which may
+ * have come from the device tree) then this function gets the filename and
+ * device type from there. Failing that it looks at the command line
+ * parameter.
+ */
+static int sandbox_sf_probe(struct udevice *dev)
 {
        /* spec = idcode:file */
-       struct sandbox_spi_flash *sbsf;
+       struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
        const char *file;
        size_t len, idname_len;
        const struct spi_flash_params *data;
-
-       file = strchr(spec, ':');
-       if (!file) {
-               printf("sandbox_sf: unable to parse file\n");
-               goto error;
+       struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev);
+       struct sandbox_state *state = state_get_current();
+       struct udevice *bus = dev->parent;
+       const char *spec = NULL;
+       int ret = 0;
+       int cs = -1;
+       int i;
+
+       debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev);
+       if (bus->seq >= 0 && bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) {
+               for (i = 0; i < CONFIG_SANDBOX_SPI_MAX_CS; i++) {
+                       if (state->spi[bus->seq][i].emul == dev)
+                               cs = i;
+               }
+       }
+       if (cs == -1) {
+               printf("Error: Unknown chip select for device '%s'",
+                      dev->name);
+               return -EINVAL;
+       }
+       debug("found at cs %d\n", cs);
+
+       if (!pdata->filename) {
+               struct sandbox_state *state = state_get_current();
+
+               assert(bus->seq != -1);
+               if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS)
+                       spec = state->spi[bus->seq][cs].spec;
+               if (!spec)
+                       return -ENOENT;
+
+               file = strchr(spec, ':');
+               if (!file) {
+                       printf("sandbox_sf: unable to parse file\n");
+                       ret = -EINVAL;
+                       goto error;
+               }
+               idname_len = file - spec;
+               pdata->filename = file + 1;
+               pdata->device_name = spec;
+               ++file;
+       } else {
+               spec = strchr(pdata->device_name, ',');
+               if (spec)
+                       spec++;
+               else
+                       spec = pdata->device_name;
+               idname_len = strlen(spec);
        }
-       idname_len = file - spec;
-       ++file;
+       debug("%s: device='%s'\n", __func__, spec);
 
        for (data = spi_flash_params_table; data->name; data++) {
                len = strlen(data->name);
                if (idname_len != len)
                        continue;
-               if (!memcmp(spec, data->name, len))
+               if (!strncasecmp(spec, data->name, len))
                        break;
        }
        if (!data->name) {
                printf("sandbox_sf: unknown flash '%*s'\n", (int)idname_len,
                       spec);
+               ret = -EINVAL;
                goto error;
        }
 
        if (sandbox_sf_0xff[0] == 0x00)
                memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff));
 
-       sbsf = calloc(sizeof(*sbsf), 1);
-       if (!sbsf) {
-               printf("sandbox_sf: out of memory\n");
-               goto error;
-       }
-
-       sbsf->fd = os_open(file, 02);
+       sbsf->fd = os_open(pdata->filename, 02);
        if (sbsf->fd == -1) {
                free(sbsf);
-               printf("sandbox_sf: unable to open file '%s'\n", file);
+               printf("sandbox_sf: unable to open file '%s'\n",
+                      pdata->filename);
+               ret = -EIO;
                goto error;
        }
 
        sbsf->data = data;
+       sbsf->cs = cs;
 
-       *priv = sbsf;
        return 0;
 
  error:
-       return 1;
+       return ret;
 }
 
-static void sandbox_sf_free(void *priv)
+static int sandbox_sf_remove(struct udevice *dev)
 {
-       struct sandbox_spi_flash *sbsf = priv;
+       struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
 
        os_close(sbsf->fd);
-       free(sbsf);
+
+       return 0;
 }
 
-static void sandbox_sf_cs_activate(void *priv)
+static void sandbox_sf_cs_activate(struct udevice *dev)
 {
-       struct sandbox_spi_flash *sbsf = priv;
+       struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
 
        debug("sandbox_sf: CS activated; state is fresh!\n");
 
@@ -160,11 +222,24 @@ static void sandbox_sf_cs_activate(void *priv)
        sbsf->cmd = SF_CMD;
 }
 
-static void sandbox_sf_cs_deactivate(void *priv)
+static void sandbox_sf_cs_deactivate(struct udevice *dev)
 {
        debug("sandbox_sf: CS deactivated; cmd done processing!\n");
 }
 
+/*
+ * There are times when the data lines are allowed to tristate.  What
+ * is actually sensed on the line depends on the hardware.  It could
+ * always be 0xFF/0x00 (if there are pull ups/downs), or things could
+ * float and so we'd get garbage back.  This func encapsulates that
+ * scenario so we can worry about the details here.
+ */
+static void sandbox_spi_tristate(u8 *buf, uint len)
+{
+       /* XXX: make this into a user config option ? */
+       memset(buf, 0xff, len);
+}
+
 /* Figure out what command this stream is telling us to do */
 static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
                                  u8 *tx)
@@ -172,7 +247,8 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
        enum sandbox_sf_state oldstate = sbsf->state;
 
        /* We need to output a byte for the cmd byte we just ate */
-       sandbox_spi_tristate(tx, 1);
+       if (tx)
+               sandbox_spi_tristate(tx, 1);
 
        sbsf->cmd = rx[0];
        switch (sbsf->cmd) {
@@ -200,6 +276,9 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
                debug(" write enabled\n");
                sbsf->status |= STAT_WEL;
                break;
+       case CMD_WRITE_STATUS:
+               sbsf->state = SF_WRITE_STATUS;
+               break;
        default: {
                int flags = sbsf->data->flags;
 
@@ -216,7 +295,7 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
                        sbsf->erase_size = 64 << 10;
                } else {
                        debug(" cmd unknown: %#x\n", sbsf->cmd);
-                       return 1;
+                       return -EIO;
                }
                sbsf->state = SF_ADDR;
                break;
@@ -246,20 +325,27 @@ int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size)
        return 0;
 }
 
-static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
-               uint bytes)
+static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
+                          const void *rxp, void *txp, unsigned long flags)
 {
-       struct sandbox_spi_flash *sbsf = priv;
+       struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
+       const uint8_t *rx = rxp;
+       uint8_t *tx = txp;
        uint cnt, pos = 0;
+       int bytes = bitlen / 8;
        int ret;
 
        debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state,
              sandbox_sf_state_name(sbsf->state), bytes);
 
+       if ((flags & SPI_XFER_BEGIN))
+               sandbox_sf_cs_activate(dev);
+
        if (sbsf->state == SF_CMD) {
                /* Figure out the initial state */
-               if (sandbox_sf_process_cmd(sbsf, rx, tx))
-                       return 1;
+               ret = sandbox_sf_process_cmd(sbsf, rx, tx);
+               if (ret)
+                       return ret;
                ++pos;
        }
 
@@ -290,7 +376,9 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
                                sbsf->off = (sbsf->off << 8) | rx[pos];
                        debug("addr:%06x\n", sbsf->off);
 
-                       sandbox_spi_tristate(&tx[pos++], 1);
+                       if (tx)
+                               sandbox_spi_tristate(&tx[pos], 1);
+                       pos++;
 
                        /* See if we're done processing */
                        if (sbsf->addr_bytes <
@@ -300,7 +388,7 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
                        /* Next state! */
                        if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) {
                                puts("sandbox_sf: os_lseek() failed");
-                               return 1;
+                               return -EIO;
                        }
                        switch (sbsf->cmd) {
                        case CMD_READ_ARRAY_FAST:
@@ -326,10 +414,11 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
 
                        cnt = bytes - pos;
                        debug(" tx: read(%u)\n", cnt);
+                       assert(tx);
                        ret = os_read(sbsf->fd, tx + pos, cnt);
                        if (ret < 0) {
-                               puts("sandbox_spi: os_read() failed\n");
-                               return 1;
+                               puts("sandbox_sf: os_read() failed\n");
+                               return -EIO;
                        }
                        pos += ret;
                        break;
@@ -345,6 +434,10 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
                        memset(tx + pos, sbsf->status >> 8, cnt);
                        pos += cnt;
                        break;
+               case SF_WRITE_STATUS:
+                       debug(" write status: %#x (ignored)\n", rx[pos]);
+                       pos = bytes;
+                       break;
                case SF_WRITE:
                        /*
                         * XXX: need to handle exotic behavior:
@@ -359,11 +452,12 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
 
                        cnt = bytes - pos;
                        debug(" rx: write(%u)\n", cnt);
-                       sandbox_spi_tristate(&tx[pos], cnt);
+                       if (tx)
+                               sandbox_spi_tristate(&tx[pos], cnt);
                        ret = os_write(sbsf->fd, rx + pos, cnt);
                        if (ret < 0) {
                                puts("sandbox_spi: os_write() failed\n");
-                               return 1;
+                               return -EIO;
                        }
                        pos += ret;
                        sbsf->status &= ~STAT_WEL;
@@ -388,7 +482,8 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
                              sbsf->erase_size);
 
                        cnt = bytes - pos;
-                       sandbox_spi_tristate(&tx[pos], cnt);
+                       if (tx)
+                               sandbox_spi_tristate(&tx[pos], cnt);
                        pos += cnt;
 
                        /*
@@ -410,17 +505,33 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx,
        }
 
  done:
-       return pos == bytes ? 0 : 1;
+       if (flags & SPI_XFER_END)
+               sandbox_sf_cs_deactivate(dev);
+       return pos == bytes ? 0 : -EIO;
+}
+
+int sandbox_sf_ofdata_to_platdata(struct udevice *dev)
+{
+       struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev);
+       const void *blob = gd->fdt_blob;
+       int node = dev->of_offset;
+
+       pdata->filename = fdt_getprop(blob, node, "sandbox,filename", NULL);
+       pdata->device_name = fdt_getprop(blob, node, "compatible", NULL);
+       if (!pdata->filename || !pdata->device_name) {
+               debug("%s: Missing properties, filename=%s, device_name=%s\n",
+                     __func__, pdata->filename, pdata->device_name);
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
-static const struct sandbox_spi_emu_ops sandbox_sf_ops = {
-       .setup         = sandbox_sf_setup,
-       .free          = sandbox_sf_free,
-       .cs_activate   = sandbox_sf_cs_activate,
-       .cs_deactivate = sandbox_sf_cs_deactivate,
+static const struct dm_spi_emul_ops sandbox_sf_emul_ops = {
        .xfer          = sandbox_sf_xfer,
 };
 
+#ifdef CONFIG_SPI_FLASH
 static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state,
                                     const char *arg)
 {
@@ -438,8 +549,141 @@ static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state,
         * spec here, but the problem is that no U-Boot init has been done
         * yet. Perhaps we can figure something out.
         */
-       state->spi[bus][cs].ops = &sandbox_sf_ops;
        state->spi[bus][cs].spec = spec;
        return 0;
 }
 SANDBOX_CMDLINE_OPT(spi_sf, 1, "connect a SPI flash: <bus>:<cs>:<id>:<file>");
+
+int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
+                        struct udevice *bus, int of_offset, const char *spec)
+{
+       struct udevice *emul;
+       char name[20], *str;
+       struct driver *drv;
+       int ret;
+
+       /* now the emulator */
+       strncpy(name, spec, sizeof(name) - 6);
+       name[sizeof(name) - 6] = '\0';
+       strcat(name, "-emul");
+       str = strdup(name);
+       if (!str)
+               return -ENOMEM;
+       drv = lists_driver_lookup_name("sandbox_sf_emul");
+       if (!drv) {
+               puts("Cannot find sandbox_sf_emul driver\n");
+               return -ENOENT;
+       }
+       ret = device_bind(bus, drv, str, NULL, of_offset, &emul);
+       if (ret) {
+               printf("Cannot create emul device for spec '%s' (err=%d)\n",
+                      spec, ret);
+               return ret;
+       }
+       state->spi[busnum][cs].emul = emul;
+
+       return 0;
+}
+
+void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs)
+{
+       state->spi[busnum][cs].emul = NULL;
+}
+
+static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum,
+                                 int cs, const char *spec)
+{
+       struct udevice *bus, *slave;
+       int ret;
+
+       ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, true, &bus);
+       if (ret) {
+               printf("Invalid bus %d for spec '%s' (err=%d)\n", busnum,
+                      spec, ret);
+               return ret;
+       }
+       ret = device_find_child_by_seq(bus, cs, true, &slave);
+       if (!ret) {
+               printf("Chip select %d already exists for spec '%s'\n", cs,
+                      spec);
+               return -EEXIST;
+       }
+
+       ret = spi_bind_device(bus, cs, "spi_flash_std", spec, &slave);
+       if (ret)
+               return ret;
+
+       return sandbox_sf_bind_emul(state, busnum, cs, bus, -1, spec);
+}
+
+int sandbox_spi_get_emul(struct sandbox_state *state,
+                        struct udevice *bus, struct udevice *slave,
+                        struct udevice **emulp)
+{
+       struct sandbox_spi_info *info;
+       int busnum = bus->seq;
+       int cs = spi_chip_select(slave);
+       int ret;
+
+       info = &state->spi[busnum][cs];
+       if (!info->emul) {
+               /* Use the same device tree node as the SPI flash device */
+               debug("%s: busnum=%u, cs=%u: binding SPI flash emulation: ",
+                     __func__, busnum, cs);
+               ret = sandbox_sf_bind_emul(state, busnum, cs, bus,
+                                          slave->of_offset, slave->name);
+               if (ret) {
+                       debug("failed (err=%d)\n", ret);
+                       return ret;
+               }
+               debug("OK\n");
+       }
+       *emulp = info->emul;
+
+       return 0;
+}
+
+int dm_scan_other(bool pre_reloc_only)
+{
+       struct sandbox_state *state = state_get_current();
+       int busnum, cs;
+
+       if (pre_reloc_only)
+               return 0;
+       for (busnum = 0; busnum < CONFIG_SANDBOX_SPI_MAX_BUS; busnum++) {
+               for (cs = 0; cs < CONFIG_SANDBOX_SPI_MAX_CS; cs++) {
+                       const char *spec = state->spi[busnum][cs].spec;
+                       int ret;
+
+                       if (spec) {
+                               ret = sandbox_sf_bind_bus_cs(state, busnum,
+                                                            cs, spec);
+                               if (ret) {
+                                       debug("%s: Bind failed for bus %d, cs %d\n",
+                                             __func__, busnum, cs);
+                                       return ret;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+#endif
+
+static const struct udevice_id sandbox_sf_ids[] = {
+       { .compatible = "sandbox,spi-flash" },
+       { }
+};
+
+U_BOOT_DRIVER(sandbox_sf_emul) = {
+       .name           = "sandbox_sf_emul",
+       .id             = UCLASS_SPI_EMUL,
+       .of_match       = sandbox_sf_ids,
+       .ofdata_to_platdata = sandbox_sf_ofdata_to_platdata,
+       .probe          = sandbox_sf_probe,
+       .remove         = sandbox_sf_remove,
+       .priv_auto_alloc_size = sizeof(struct sandbox_spi_flash),
+       .platdata_auto_alloc_size = sizeof(struct sandbox_spi_flash_plat_data),
+       .ops            = &sandbox_sf_emul_ops,
+};
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
new file mode 100644 (file)
index 0000000..376d815
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <dm/device-internal.h>
+#include "sf_internal.h"
+
+/*
+ * TODO(sjg@chromium.org): This is an old-style function. We should remove
+ * it when all SPI flash drivers use dm
+ */
+struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+                                 unsigned int max_hz, unsigned int spi_mode)
+{
+       struct udevice *dev;
+
+       if (spi_flash_probe_bus_cs(bus, cs, max_hz, spi_mode, &dev))
+               return NULL;
+
+       return dev->uclass_priv;
+}
+
+void spi_flash_free(struct spi_flash *flash)
+{
+       spi_flash_remove(flash->spi->dev);
+}
+
+int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
+                          unsigned int max_hz, unsigned int spi_mode,
+                          struct udevice **devp)
+{
+       struct spi_slave *slave;
+       struct udevice *bus;
+       char name[20], *str;
+       int ret;
+
+       snprintf(name, sizeof(name), "%d:%d", busnum, cs);
+       str = strdup(name);
+       ret = spi_get_bus_and_cs(busnum, cs, max_hz, spi_mode,
+                                 "spi_flash_std", str, &bus, &slave);
+       if (ret)
+               return ret;
+
+       *devp = slave->dev;
+       return 0;
+}
+
+int spi_flash_remove(struct udevice *dev)
+{
+       return device_remove(dev);
+}
+
+UCLASS_DRIVER(spi_flash) = {
+       .id             = UCLASS_SPI_FLASH,
+       .name           = "spi_flash",
+       .per_device_auto_alloc_size = sizeof(struct spi_flash),
+};
index 19d49146ebd1520d9f6a481765acdbd884b384ee..5b7670c9aaf1219e841cd2dfc5096bb62e7e3390 100644 (file)
 #ifndef _SF_INTERNAL_H_
 #define _SF_INTERNAL_H_
 
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+/* Dual SPI flash memories - see SPI_COMM_DUAL_... */
+enum spi_dual_flash {
+       SF_SINGLE_FLASH = 0,
+       SF_DUAL_STACKED_FLASH   = 1 << 0,
+       SF_DUAL_PARALLEL_FLASH  = 1 << 1,
+};
+
+/* Enum list - Full read commands */
+enum spi_read_cmds {
+       ARRAY_SLOW              = 1 << 0,
+       DUAL_OUTPUT_FAST        = 1 << 1,
+       DUAL_IO_FAST            = 1 << 2,
+       QUAD_OUTPUT_FAST        = 1 << 3,
+       QUAD_IO_FAST            = 1 << 4,
+};
+
+#define RD_EXTN        (ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST)
+#define RD_FULL        (RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST)
+
+/* sf param flags */
+enum {
+       SECT_4K         = 1 << 0,
+       SECT_32K        = 1 << 1,
+       E_FSR           = 1 << 2,
+       WR_QPP          = 1 << 3,
+};
+
 #define SPI_FLASH_3B_ADDR_LEN          3
 #define SPI_FLASH_CMD_LEN              (1 + SPI_FLASH_3B_ADDR_LEN)
 #define SPI_FLASH_16MB_BOUN            0x1000000
 #define CMD_WRITE_STATUS               0x01
 #define CMD_PAGE_PROGRAM               0x02
 #define CMD_WRITE_DISABLE              0x04
-#define CMD_READ_STATUS                        0x05
+#define CMD_READ_STATUS                0x05
 #define CMD_QUAD_PAGE_PROGRAM          0x32
 #define CMD_READ_STATUS1               0x35
 #define CMD_WRITE_ENABLE               0x06
-#define CMD_READ_CONFIG                        0x35
-#define CMD_FLAG_STATUS                        0x70
+#define CMD_READ_CONFIG                0x35
+#define CMD_FLAG_STATUS                0x70
 
 /* Read commands */
 #define CMD_READ_ARRAY_SLOW            0x03
@@ -57,7 +87,7 @@
 /* Common status */
 #define STATUS_WIP                     (1 << 0)
 #define STATUS_QEB_WINSPAN             (1 << 1)
-#define STATUS_QEB_MXIC                        (1 << 6)
+#define STATUS_QEB_MXIC                (1 << 6)
 #define STATUS_PEC                     (1 << 7)
 
 #ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
 
 /* Flash timeout values */
 #define SPI_FLASH_PROG_TIMEOUT         (2 * CONFIG_SYS_HZ)
-#define SPI_FLASH_PAGE_ERASE_TIMEOUT   (5 * CONFIG_SYS_HZ)
+#define SPI_FLASH_PAGE_ERASE_TIMEOUT           (5 * CONFIG_SYS_HZ)
 #define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ)
 
 /* SST specific */
 #ifdef CONFIG_SPI_FLASH_SST
-# define SST_WP                        0x01    /* Supports AAI word program */
+# define SST_WP                0x01    /* Supports AAI word program */
 # define CMD_SST_BP            0x02    /* Byte Program */
-# define CMD_SST_AAI_WP                0xAD    /* Auto Address Incr Word Program */
+# define CMD_SST_AAI_WP        0xAD    /* Auto Address Incr Word Program */
 
 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
                const void *buf);
 #endif
 
+/**
+ * struct spi_flash_params - SPI/QSPI flash device params structure
+ *
+ * @name:              Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
+ * @jedec:             Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
+ * @ext_jedec:         Device ext_jedec ID
+ * @sector_size:       Sector size of this device
+ * @nr_sectors:        No.of sectors on this device
+ * @e_rd_cmd:          Enum list for read commands
+ * @flags:             Important param, for flash specific behaviour
+ */
+struct spi_flash_params {
+       const char *name;
+       u32 jedec;
+       u16 ext_jedec;
+       u32 sector_size;
+       u32 nr_sectors;
+       u8 e_rd_cmd;
+       u16 flags;
+};
+
+extern const struct spi_flash_params spi_flash_params_table[];
+
 /* Send a single-byte command to the device and read the response */
 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
 
index 453edf0149518cd69c945adcf2b3a270ddaebb62..61545cacaabe8415bf7a1a1fa35d2e7e8294e2b9 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <common.h>
+#include <spi.h>
 #include <spi_flash.h>
 
 #include "sf_internal.h"
index 4d148d1ace3749744cbc1e9ef190f5fdcb84649a..26364269be1a5e823efc99bd498262bd1a9d3393 100644 (file)
@@ -9,6 +9,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
 #include <spi.h>
@@ -95,15 +97,15 @@ static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
        }
 }
 
-static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
-               u8 *idcode)
+static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
+                                    struct spi_flash *flash)
 {
        const struct spi_flash_params *params;
-       struct spi_flash *flash;
        u8 cmd;
        u16 jedec = idcode[1] << 8 | idcode[2];
        u16 ext_jedec = idcode[3] << 8 | idcode[4];
 
+       /* Validate params from spi_flash_params table */
        params = spi_flash_params_table;
        for (; params->name != NULL; params++) {
                if ((params->jedec >> 16) == idcode[0]) {
@@ -120,13 +122,7 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
                printf("SF: Unsupported flash IDs: ");
                printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
                       idcode[0], jedec, ext_jedec);
-               return NULL;
-       }
-
-       flash = calloc(1, sizeof(*flash));
-       if (!flash) {
-               debug("SF: Failed to allocate spi_flash\n");
-               return NULL;
+               return -EPROTONOSUPPORT;
        }
 
        /* Assign spi data */
@@ -136,13 +132,15 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
        flash->dual_flash = flash->spi->option;
 
        /* Assign spi_flash ops */
+#ifndef CONFIG_DM_SPI_FLASH
        flash->write = spi_flash_cmd_write_ops;
-#ifdef CONFIG_SPI_FLASH_SST
+#if defined(CONFIG_SPI_FLASH_SST)
        if (params->flags & SST_WP)
                flash->write = sst_write_wp;
 #endif
        flash->erase = spi_flash_cmd_erase_ops;
        flash->read = spi_flash_cmd_read_ops;
+#endif
 
        /* Compute the flash size */
        flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
@@ -227,15 +225,18 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
 #ifdef CONFIG_SPI_FLASH_BAR
        u8 curr_bank = 0;
        if (flash->size > SPI_FLASH_16MB_BOUN) {
+               int ret;
+
                flash->bank_read_cmd = (idcode[0] == 0x01) ?
                                        CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR;
                flash->bank_write_cmd = (idcode[0] == 0x01) ?
                                        CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
 
-               if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
-                                         &curr_bank, 1)) {
+               ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
+                                           &curr_bank, 1);
+               if (ret) {
                        debug("SF: fail to read bank addr register\n");
-                       return NULL;
+                       return ret;
                }
                flash->bank_curr = curr_bank;
        } else {
@@ -250,7 +251,7 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
                spi_flash_cmd_write_status(flash, 0);
 #endif
 
-       return flash;
+       return 0;
 }
 
 #ifdef CONFIG_OF_CONTROL
@@ -309,23 +310,29 @@ static int spi_enable_wp_pin(struct spi_flash *flash)
 }
 #endif
 
-static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
+/**
+ * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
+ *
+ * @spi: Bus to probe
+ * @flashp: Pointer to place to put flash info, which may be NULL if the
+ * space should be allocated
+ */
+int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
 {
-       struct spi_flash *flash = NULL;
        u8 idcode[5];
        int ret;
 
        /* Setup spi_slave */
        if (!spi) {
                printf("SF: Failed to set up slave\n");
-               return NULL;
+               return -ENODEV;
        }
 
        /* Claim spi bus */
        ret = spi_claim_bus(spi);
        if (ret) {
                debug("SF: Failed to claim SPI bus: %d\n", ret);
-               goto err_claim_bus;
+               return ret;
        }
 
        /* Read the ID codes */
@@ -340,10 +347,10 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
        print_buffer(0, idcode, 1, sizeof(idcode), 0);
 #endif
 
-       /* Validate params from spi_flash_params table */
-       flash = spi_flash_validate_params(spi, idcode);
-       if (!flash)
+       if (spi_flash_validate_params(spi, idcode, flash)) {
+               ret = -EINVAL;
                goto err_read_id;
+       }
 
        /* Set the quad enable bit - only for quad commands */
        if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
@@ -351,13 +358,15 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
            (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
                if (spi_flash_set_qeb(flash, idcode[0])) {
                        debug("SF: Fail to set QEB for %02x\n", idcode[0]);
-                       return NULL;
+                       ret = -EINVAL;
+                       goto err_read_id;
                }
        }
 
 #ifdef CONFIG_OF_CONTROL
        if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
                debug("SF: FDT decode error\n");
+               ret = -EINVAL;
                goto err_read_id;
        }
 #endif
@@ -385,32 +394,51 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
        /* Release spi bus */
        spi_release_bus(spi);
 
-       return flash;
+       return 0;
 
 err_read_id:
        spi_release_bus(spi);
-err_claim_bus:
-       spi_free_slave(spi);
-       return NULL;
+       return ret;
 }
 
-struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+#ifndef CONFIG_DM_SPI_FLASH
+struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
+{
+       struct spi_flash *flash;
+
+       /* Allocate space if needed (not used by sf-uclass */
+       flash = calloc(1, sizeof(*flash));
+       if (!flash) {
+               debug("SF: Failed to allocate spi_flash\n");
+               return NULL;
+       }
+
+       if (spi_flash_probe_slave(bus, flash)) {
+               spi_free_slave(bus);
+               free(flash);
+               return NULL;
+       }
+
+       return flash;
+}
+
+struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
                unsigned int max_hz, unsigned int spi_mode)
 {
-       struct spi_slave *spi;
+       struct spi_slave *bus;
 
-       spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
-       return spi_flash_probe_slave(spi);
+       bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
+       return spi_flash_probe_tail(bus);
 }
 
 #ifdef CONFIG_OF_SPI_FLASH
 struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
                                      int spi_node)
 {
-       struct spi_slave *spi;
+       struct spi_slave *bus;
 
-       spi = spi_setup_slave_fdt(blob, slave_node, spi_node);
-       return spi_flash_probe_slave(spi);
+       bus = spi_setup_slave_fdt(blob, slave_node, spi_node);
+       return spi_flash_probe_tail(bus);
 }
 #endif
 
@@ -419,3 +447,61 @@ void spi_flash_free(struct spi_flash *flash)
        spi_free_slave(flash->spi);
        free(flash);
 }
+
+#else /* defined CONFIG_DM_SPI_FLASH */
+
+static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
+                             void *buf)
+{
+       struct spi_flash *flash = dev->uclass_priv;
+
+       return spi_flash_cmd_read_ops(flash, offset, len, buf);
+}
+
+int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
+                       const void *buf)
+{
+       struct spi_flash *flash = dev->uclass_priv;
+
+       return spi_flash_cmd_write_ops(flash, offset, len, buf);
+}
+
+int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
+{
+       struct spi_flash *flash = dev->uclass_priv;
+
+       return spi_flash_cmd_erase_ops(flash, offset, len);
+}
+
+int spi_flash_std_probe(struct udevice *dev)
+{
+       struct spi_slave *slave = dev_get_parentdata(dev);
+       struct spi_flash *flash;
+
+       flash = dev->uclass_priv;
+       flash->dev = dev;
+       debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs);
+       return spi_flash_probe_slave(slave, flash);
+}
+
+static const struct dm_spi_flash_ops spi_flash_std_ops = {
+       .read = spi_flash_std_read,
+       .write = spi_flash_std_write,
+       .erase = spi_flash_std_erase,
+};
+
+static const struct udevice_id spi_flash_std_ids[] = {
+       { .compatible = "spi-flash" },
+       { }
+};
+
+U_BOOT_DRIVER(spi_flash_std) = {
+       .name           = "spi_flash_std",
+       .id             = UCLASS_SPI_FLASH,
+       .of_match       = spi_flash_std_ids,
+       .probe          = spi_flash_std_probe,
+       .priv_auto_alloc_size = sizeof(struct spi_flash),
+       .ops            = &spi_flash_std_ops,
+};
+
+#endif /* CONFIG_DM_SPI_FLASH */
index 59cca0f4d998d1d6b87f9b7ca0a16180f8840bcd..2e0c871219bd05ac31c63a80ba793e1dc1255899 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <common.h>
+#include <spi.h>
 #include <spi_flash.h>
 #include <spl.h>
 
index 2c4dd7cb6ad8657a500f7e7247a658591c1dab4b..fb0cf8c1cf172dce03a8dcea02d7522de26793a9 100644 (file)
@@ -41,6 +41,7 @@ obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
 obj-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o
 obj-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o
 obj-$(CONFIG_MVGBE) += mvgbe.o
+obj-$(CONFIG_MVNETA) += mvneta.o
 obj-$(CONFIG_NATSEMI) += natsemi.o
 obj-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o
 obj-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o
index 439f8ae99e364f2082ceaa2ad5f0630c21e0fe9f..08bc1afcf638be1dbde9e1c23662a829c2bfa298 100644 (file)
@@ -27,6 +27,7 @@
 #include <net.h>
 #include <miiphy.h>
 #include <malloc.h>
+#include <netdev.h>
 #include <linux/compiler.h>
 #include <asm/arch/emac_defs.h>
 #include <asm/io.h>
index 549d6486136204ed644a2c2ecba101d25db303ef..b57247032fa85aaa65ec47c9fcf7668a4cd567df 100644 (file)
@@ -11,6 +11,7 @@
 #include <common.h>
 #include <malloc.h>
 #include <net.h>
+#include <netdev.h>
 #include <miiphy.h>
 #include "fec_mxc.h"
 
@@ -179,13 +180,14 @@ static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr,
        return 0;
 }
 
-int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr)
+static int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr,
+                       int regAddr)
 {
        return fec_mdio_read(bus->priv, phyAddr, regAddr);
 }
 
-int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr,
-               u16 data)
+static int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr,
+                        int regAddr, u16 data)
 {
        return fec_mdio_write(bus->priv, phyAddr, regAddr, data);
 }
index 0cd06b6a69df68aa8e9e1410724d89844b131010..6ef6cacb6b87940421bae8d78085eb0ebb5a6e0d 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/arch/cpu.h>
 
 #if defined(CONFIG_KIRKWOOD)
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #elif defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
 #elif defined(CONFIG_DOVE)
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
new file mode 100644 (file)
index 0000000..a2a69b4
--- /dev/null
@@ -0,0 +1,1653 @@
+/*
+ * Driver for Marvell NETA network card for Armada XP and Armada 370 SoCs.
+ *
+ * U-Boot version:
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * Based on the Linux version which is:
+ * Copyright (C) 2012 Marvell
+ *
+ * Rami Rosen <rosenr@marvell.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <net.h>
+#include <netdev.h>
+#include <config.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <phy.h>
+#include <miiphy.h>
+#include <watchdog.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <linux/compat.h>
+#include <linux/mbus.h>
+
+#if !defined(CONFIG_PHYLIB)
+# error Marvell mvneta requires PHYLIB
+#endif
+
+/* Some linux -> U-Boot compatibility stuff */
+#define netdev_err(dev, fmt, args...)          \
+       printf(fmt, ##args)
+#define netdev_warn(dev, fmt, args...)         \
+       printf(fmt, ##args)
+#define netdev_info(dev, fmt, args...)         \
+       printf(fmt, ##args)
+
+#define CONFIG_NR_CPUS         1
+#define BIT(nr)                        (1UL << (nr))
+#define ETH_HLEN               14      /* Total octets in header */
+
+/* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */
+#define WRAP                   (2 + ETH_HLEN + 4 + 32)
+#define MTU                    1500
+#define RX_BUFFER_SIZE         (ALIGN(MTU + WRAP, ARCH_DMA_MINALIGN))
+
+#define MVNETA_SMI_TIMEOUT                     10000
+
+/* Registers */
+#define MVNETA_RXQ_CONFIG_REG(q)                (0x1400 + ((q) << 2))
+#define             MVNETA_RXQ_HW_BUF_ALLOC            BIT(1)
+#define      MVNETA_RXQ_PKT_OFFSET_ALL_MASK     (0xf    << 8)
+#define      MVNETA_RXQ_PKT_OFFSET_MASK(offs)   ((offs) << 8)
+#define MVNETA_RXQ_THRESHOLD_REG(q)             (0x14c0 + ((q) << 2))
+#define      MVNETA_RXQ_NON_OCCUPIED(v)         ((v) << 16)
+#define MVNETA_RXQ_BASE_ADDR_REG(q)             (0x1480 + ((q) << 2))
+#define MVNETA_RXQ_SIZE_REG(q)                  (0x14a0 + ((q) << 2))
+#define      MVNETA_RXQ_BUF_SIZE_SHIFT          19
+#define      MVNETA_RXQ_BUF_SIZE_MASK           (0x1fff << 19)
+#define MVNETA_RXQ_STATUS_REG(q)                (0x14e0 + ((q) << 2))
+#define      MVNETA_RXQ_OCCUPIED_ALL_MASK       0x3fff
+#define MVNETA_RXQ_STATUS_UPDATE_REG(q)         (0x1500 + ((q) << 2))
+#define      MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT  16
+#define      MVNETA_RXQ_ADD_NON_OCCUPIED_MAX    255
+#define MVNETA_PORT_RX_RESET                    0x1cc0
+#define      MVNETA_PORT_RX_DMA_RESET           BIT(0)
+#define MVNETA_PHY_ADDR                         0x2000
+#define      MVNETA_PHY_ADDR_MASK               0x1f
+#define MVNETA_SMI                              0x2004
+#define      MVNETA_PHY_REG_MASK                0x1f
+/* SMI register fields */
+#define     MVNETA_SMI_DATA_OFFS               0       /* Data */
+#define     MVNETA_SMI_DATA_MASK               (0xffff << MVNETA_SMI_DATA_OFFS)
+#define     MVNETA_SMI_DEV_ADDR_OFFS           16      /* PHY device address */
+#define     MVNETA_SMI_REG_ADDR_OFFS           21      /* PHY device reg addr*/
+#define     MVNETA_SMI_OPCODE_OFFS             26      /* Write/Read opcode */
+#define     MVNETA_SMI_OPCODE_READ             (1 << MVNETA_SMI_OPCODE_OFFS)
+#define     MVNETA_SMI_READ_VALID              (1 << 27)       /* Read Valid */
+#define     MVNETA_SMI_BUSY                    (1 << 28)       /* Busy */
+#define MVNETA_MBUS_RETRY                       0x2010
+#define MVNETA_UNIT_INTR_CAUSE                  0x2080
+#define MVNETA_UNIT_CONTROL                     0x20B0
+#define      MVNETA_PHY_POLLING_ENABLE          BIT(1)
+#define MVNETA_WIN_BASE(w)                      (0x2200 + ((w) << 3))
+#define MVNETA_WIN_SIZE(w)                      (0x2204 + ((w) << 3))
+#define MVNETA_WIN_REMAP(w)                     (0x2280 + ((w) << 2))
+#define MVNETA_BASE_ADDR_ENABLE                 0x2290
+#define MVNETA_PORT_CONFIG                      0x2400
+#define      MVNETA_UNI_PROMISC_MODE            BIT(0)
+#define      MVNETA_DEF_RXQ(q)                  ((q) << 1)
+#define      MVNETA_DEF_RXQ_ARP(q)              ((q) << 4)
+#define      MVNETA_TX_UNSET_ERR_SUM            BIT(12)
+#define      MVNETA_DEF_RXQ_TCP(q)              ((q) << 16)
+#define      MVNETA_DEF_RXQ_UDP(q)              ((q) << 19)
+#define      MVNETA_DEF_RXQ_BPDU(q)             ((q) << 22)
+#define      MVNETA_RX_CSUM_WITH_PSEUDO_HDR     BIT(25)
+#define      MVNETA_PORT_CONFIG_DEFL_VALUE(q)   (MVNETA_DEF_RXQ(q)       | \
+                                                MVNETA_DEF_RXQ_ARP(q)   | \
+                                                MVNETA_DEF_RXQ_TCP(q)   | \
+                                                MVNETA_DEF_RXQ_UDP(q)   | \
+                                                MVNETA_DEF_RXQ_BPDU(q)  | \
+                                                MVNETA_TX_UNSET_ERR_SUM | \
+                                                MVNETA_RX_CSUM_WITH_PSEUDO_HDR)
+#define MVNETA_PORT_CONFIG_EXTEND                0x2404
+#define MVNETA_MAC_ADDR_LOW                      0x2414
+#define MVNETA_MAC_ADDR_HIGH                     0x2418
+#define MVNETA_SDMA_CONFIG                       0x241c
+#define      MVNETA_SDMA_BRST_SIZE_16            4
+#define      MVNETA_RX_BRST_SZ_MASK(burst)       ((burst) << 1)
+#define      MVNETA_RX_NO_DATA_SWAP              BIT(4)
+#define      MVNETA_TX_NO_DATA_SWAP              BIT(5)
+#define      MVNETA_DESC_SWAP                    BIT(6)
+#define      MVNETA_TX_BRST_SZ_MASK(burst)       ((burst) << 22)
+#define MVNETA_PORT_STATUS                       0x2444
+#define      MVNETA_TX_IN_PRGRS                  BIT(1)
+#define      MVNETA_TX_FIFO_EMPTY                BIT(8)
+#define MVNETA_RX_MIN_FRAME_SIZE                 0x247c
+#define MVNETA_SERDES_CFG                       0x24A0
+#define      MVNETA_SGMII_SERDES_PROTO          0x0cc7
+#define      MVNETA_QSGMII_SERDES_PROTO                 0x0667
+#define MVNETA_TYPE_PRIO                         0x24bc
+#define      MVNETA_FORCE_UNI                    BIT(21)
+#define MVNETA_TXQ_CMD_1                         0x24e4
+#define MVNETA_TXQ_CMD                           0x2448
+#define      MVNETA_TXQ_DISABLE_SHIFT            8
+#define      MVNETA_TXQ_ENABLE_MASK              0x000000ff
+#define MVNETA_ACC_MODE                          0x2500
+#define MVNETA_CPU_MAP(cpu)                      (0x2540 + ((cpu) << 2))
+#define      MVNETA_CPU_RXQ_ACCESS_ALL_MASK      0x000000ff
+#define      MVNETA_CPU_TXQ_ACCESS_ALL_MASK      0x0000ff00
+#define MVNETA_RXQ_TIME_COAL_REG(q)              (0x2580 + ((q) << 2))
+
+/* Exception Interrupt Port/Queue Cause register */
+
+#define MVNETA_INTR_NEW_CAUSE                    0x25a0
+#define MVNETA_INTR_NEW_MASK                     0x25a4
+
+/* bits  0..7  = TXQ SENT, one bit per queue.
+ * bits  8..15 = RXQ OCCUP, one bit per queue.
+ * bits 16..23 = RXQ FREE, one bit per queue.
+ * bit  29 = OLD_REG_SUM, see old reg ?
+ * bit  30 = TX_ERR_SUM, one bit for 4 ports
+ * bit  31 = MISC_SUM,   one bit for 4 ports
+ */
+#define      MVNETA_TX_INTR_MASK(nr_txqs)        (((1 << nr_txqs) - 1) << 0)
+#define      MVNETA_TX_INTR_MASK_ALL             (0xff << 0)
+#define      MVNETA_RX_INTR_MASK(nr_rxqs)        (((1 << nr_rxqs) - 1) << 8)
+#define      MVNETA_RX_INTR_MASK_ALL             (0xff << 8)
+
+#define MVNETA_INTR_OLD_CAUSE                    0x25a8
+#define MVNETA_INTR_OLD_MASK                     0x25ac
+
+/* Data Path Port/Queue Cause Register */
+#define MVNETA_INTR_MISC_CAUSE                   0x25b0
+#define MVNETA_INTR_MISC_MASK                    0x25b4
+#define MVNETA_INTR_ENABLE                       0x25b8
+
+#define MVNETA_RXQ_CMD                           0x2680
+#define      MVNETA_RXQ_DISABLE_SHIFT            8
+#define      MVNETA_RXQ_ENABLE_MASK              0x000000ff
+#define MVETH_TXQ_TOKEN_COUNT_REG(q)             (0x2700 + ((q) << 4))
+#define MVETH_TXQ_TOKEN_CFG_REG(q)               (0x2704 + ((q) << 4))
+#define MVNETA_GMAC_CTRL_0                       0x2c00
+#define      MVNETA_GMAC_MAX_RX_SIZE_SHIFT       2
+#define      MVNETA_GMAC_MAX_RX_SIZE_MASK        0x7ffc
+#define      MVNETA_GMAC0_PORT_ENABLE            BIT(0)
+#define MVNETA_GMAC_CTRL_2                       0x2c08
+#define      MVNETA_GMAC2_PCS_ENABLE             BIT(3)
+#define      MVNETA_GMAC2_PORT_RGMII             BIT(4)
+#define      MVNETA_GMAC2_PORT_RESET             BIT(6)
+#define MVNETA_GMAC_STATUS                       0x2c10
+#define      MVNETA_GMAC_LINK_UP                 BIT(0)
+#define      MVNETA_GMAC_SPEED_1000              BIT(1)
+#define      MVNETA_GMAC_SPEED_100               BIT(2)
+#define      MVNETA_GMAC_FULL_DUPLEX             BIT(3)
+#define      MVNETA_GMAC_RX_FLOW_CTRL_ENABLE     BIT(4)
+#define      MVNETA_GMAC_TX_FLOW_CTRL_ENABLE     BIT(5)
+#define      MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE     BIT(6)
+#define      MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE     BIT(7)
+#define MVNETA_GMAC_AUTONEG_CONFIG               0x2c0c
+#define      MVNETA_GMAC_FORCE_LINK_DOWN         BIT(0)
+#define      MVNETA_GMAC_FORCE_LINK_PASS         BIT(1)
+#define      MVNETA_GMAC_CONFIG_MII_SPEED        BIT(5)
+#define      MVNETA_GMAC_CONFIG_GMII_SPEED       BIT(6)
+#define      MVNETA_GMAC_AN_SPEED_EN             BIT(7)
+#define      MVNETA_GMAC_CONFIG_FULL_DUPLEX      BIT(12)
+#define      MVNETA_GMAC_AN_DUPLEX_EN            BIT(13)
+#define MVNETA_MIB_COUNTERS_BASE                 0x3080
+#define      MVNETA_MIB_LATE_COLLISION           0x7c
+#define MVNETA_DA_FILT_SPEC_MCAST                0x3400
+#define MVNETA_DA_FILT_OTH_MCAST                 0x3500
+#define MVNETA_DA_FILT_UCAST_BASE                0x3600
+#define MVNETA_TXQ_BASE_ADDR_REG(q)              (0x3c00 + ((q) << 2))
+#define MVNETA_TXQ_SIZE_REG(q)                   (0x3c20 + ((q) << 2))
+#define      MVNETA_TXQ_SENT_THRESH_ALL_MASK     0x3fff0000
+#define      MVNETA_TXQ_SENT_THRESH_MASK(coal)   ((coal) << 16)
+#define MVNETA_TXQ_UPDATE_REG(q)                 (0x3c60 + ((q) << 2))
+#define      MVNETA_TXQ_DEC_SENT_SHIFT           16
+#define MVNETA_TXQ_STATUS_REG(q)                 (0x3c40 + ((q) << 2))
+#define      MVNETA_TXQ_SENT_DESC_SHIFT          16
+#define      MVNETA_TXQ_SENT_DESC_MASK           0x3fff0000
+#define MVNETA_PORT_TX_RESET                     0x3cf0
+#define      MVNETA_PORT_TX_DMA_RESET            BIT(0)
+#define MVNETA_TX_MTU                            0x3e0c
+#define MVNETA_TX_TOKEN_SIZE                     0x3e14
+#define      MVNETA_TX_TOKEN_SIZE_MAX            0xffffffff
+#define MVNETA_TXQ_TOKEN_SIZE_REG(q)             (0x3e40 + ((q) << 2))
+#define      MVNETA_TXQ_TOKEN_SIZE_MAX           0x7fffffff
+
+/* Descriptor ring Macros */
+#define MVNETA_QUEUE_NEXT_DESC(q, index)       \
+       (((index) < (q)->last_desc) ? ((index) + 1) : 0)
+
+/* Various constants */
+
+/* Coalescing */
+#define MVNETA_TXDONE_COAL_PKTS                16
+#define MVNETA_RX_COAL_PKTS            32
+#define MVNETA_RX_COAL_USEC            100
+
+/* The two bytes Marvell header. Either contains a special value used
+ * by Marvell switches when a specific hardware mode is enabled (not
+ * supported by this driver) or is filled automatically by zeroes on
+ * the RX side. Those two bytes being at the front of the Ethernet
+ * header, they allow to have the IP header aligned on a 4 bytes
+ * boundary automatically: the hardware skips those two bytes on its
+ * own.
+ */
+#define MVNETA_MH_SIZE                 2
+
+#define MVNETA_VLAN_TAG_LEN             4
+
+#define MVNETA_CPU_D_CACHE_LINE_SIZE    32
+#define MVNETA_TX_CSUM_MAX_SIZE                9800
+#define MVNETA_ACC_MODE_EXT            1
+
+/* Timeout constants */
+#define MVNETA_TX_DISABLE_TIMEOUT_MSEC 1000
+#define MVNETA_RX_DISABLE_TIMEOUT_MSEC 1000
+#define MVNETA_TX_FIFO_EMPTY_TIMEOUT   10000
+
+#define MVNETA_TX_MTU_MAX              0x3ffff
+
+/* Max number of Rx descriptors */
+#define MVNETA_MAX_RXD 16
+
+/* Max number of Tx descriptors */
+#define MVNETA_MAX_TXD 16
+
+/* descriptor aligned size */
+#define MVNETA_DESC_ALIGNED_SIZE       32
+
+struct mvneta_port {
+       void __iomem *base;
+       struct mvneta_rx_queue *rxqs;
+       struct mvneta_tx_queue *txqs;
+
+       u8 mcast_count[256];
+       u16 tx_ring_size;
+       u16 rx_ring_size;
+
+       phy_interface_t phy_interface;
+       unsigned int link;
+       unsigned int duplex;
+       unsigned int speed;
+
+       int init;
+       int phyaddr;
+       struct phy_device *phydev;
+       struct mii_dev *bus;
+};
+
+/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
+ * layout of the transmit and reception DMA descriptors, and their
+ * layout is therefore defined by the hardware design
+ */
+
+#define MVNETA_TX_L3_OFF_SHIFT 0
+#define MVNETA_TX_IP_HLEN_SHIFT        8
+#define MVNETA_TX_L4_UDP       BIT(16)
+#define MVNETA_TX_L3_IP6       BIT(17)
+#define MVNETA_TXD_IP_CSUM     BIT(18)
+#define MVNETA_TXD_Z_PAD       BIT(19)
+#define MVNETA_TXD_L_DESC      BIT(20)
+#define MVNETA_TXD_F_DESC      BIT(21)
+#define MVNETA_TXD_FLZ_DESC    (MVNETA_TXD_Z_PAD  | \
+                                MVNETA_TXD_L_DESC | \
+                                MVNETA_TXD_F_DESC)
+#define MVNETA_TX_L4_CSUM_FULL BIT(30)
+#define MVNETA_TX_L4_CSUM_NOT  BIT(31)
+
+#define MVNETA_RXD_ERR_CRC             0x0
+#define MVNETA_RXD_ERR_SUMMARY         BIT(16)
+#define MVNETA_RXD_ERR_OVERRUN         BIT(17)
+#define MVNETA_RXD_ERR_LEN             BIT(18)
+#define MVNETA_RXD_ERR_RESOURCE                (BIT(17) | BIT(18))
+#define MVNETA_RXD_ERR_CODE_MASK       (BIT(17) | BIT(18))
+#define MVNETA_RXD_L3_IP4              BIT(25)
+#define MVNETA_RXD_FIRST_LAST_DESC     (BIT(26) | BIT(27))
+#define MVNETA_RXD_L4_CSUM_OK          BIT(30)
+
+struct mvneta_tx_desc {
+       u32  command;           /* Options used by HW for packet transmitting.*/
+       u16  reserverd1;        /* csum_l4 (for future use)             */
+       u16  data_size;         /* Data size of transmitted packet in bytes */
+       u32  buf_phys_addr;     /* Physical addr of transmitted buffer  */
+       u32  reserved2;         /* hw_cmd - (for future use, PMT)       */
+       u32  reserved3[4];      /* Reserved - (for future use)          */
+};
+
+struct mvneta_rx_desc {
+       u32  status;            /* Info about received packet           */
+       u16  reserved1;         /* pnc_info - (for future use, PnC)     */
+       u16  data_size;         /* Size of received packet in bytes     */
+
+       u32  buf_phys_addr;     /* Physical address of the buffer       */
+       u32  reserved2;         /* pnc_flow_id  (for future use, PnC)   */
+
+       u32  buf_cookie;        /* cookie for access to RX buffer in rx path */
+       u16  reserved3;         /* prefetch_cmd, for future use         */
+       u16  reserved4;         /* csum_l4 - (for future use, PnC)      */
+
+       u32  reserved5;         /* pnc_extra PnC (for future use, PnC)  */
+       u32  reserved6;         /* hw_cmd (for future use, PnC and HWF) */
+};
+
+struct mvneta_tx_queue {
+       /* Number of this TX queue, in the range 0-7 */
+       u8 id;
+
+       /* Number of TX DMA descriptors in the descriptor ring */
+       int size;
+
+       /* Index of last TX DMA descriptor that was inserted */
+       int txq_put_index;
+
+       /* Index of the TX DMA descriptor to be cleaned up */
+       int txq_get_index;
+
+       /* Virtual address of the TX DMA descriptors array */
+       struct mvneta_tx_desc *descs;
+
+       /* DMA address of the TX DMA descriptors array */
+       dma_addr_t descs_phys;
+
+       /* Index of the last TX DMA descriptor */
+       int last_desc;
+
+       /* Index of the next TX DMA descriptor to process */
+       int next_desc_to_proc;
+};
+
+struct mvneta_rx_queue {
+       /* rx queue number, in the range 0-7 */
+       u8 id;
+
+       /* num of rx descriptors in the rx descriptor ring */
+       int size;
+
+       /* Virtual address of the RX DMA descriptors array */
+       struct mvneta_rx_desc *descs;
+
+       /* DMA address of the RX DMA descriptors array */
+       dma_addr_t descs_phys;
+
+       /* Index of the last RX DMA descriptor */
+       int last_desc;
+
+       /* Index of the next RX DMA descriptor to process */
+       int next_desc_to_proc;
+};
+
+/* U-Boot doesn't use the queues, so set the number to 1 */
+static int rxq_number = 1;
+static int txq_number = 1;
+static int rxq_def;
+
+struct buffer_location {
+       struct mvneta_tx_desc *tx_descs;
+       struct mvneta_rx_desc *rx_descs;
+       u32 rx_buffers;
+};
+
+/*
+ * All 4 interfaces use the same global buffer, since only one interface
+ * can be enabled at once
+ */
+static struct buffer_location buffer_loc;
+
+/*
+ * Page table entries are set to 1MB, or multiples of 1MB
+ * (not < 1MB). driver uses less bd's so use 1MB bdspace.
+ */
+#define BD_SPACE       (1 << 20)
+
+/* Utility/helper methods */
+
+/* Write helper method */
+static void mvreg_write(struct mvneta_port *pp, u32 offset, u32 data)
+{
+       writel(data, pp->base + offset);
+}
+
+/* Read helper method */
+static u32 mvreg_read(struct mvneta_port *pp, u32 offset)
+{
+       return readl(pp->base + offset);
+}
+
+/* Clear all MIB counters */
+static void mvneta_mib_counters_clear(struct mvneta_port *pp)
+{
+       int i;
+
+       /* Perform dummy reads from MIB counters */
+       for (i = 0; i < MVNETA_MIB_LATE_COLLISION; i += 4)
+               mvreg_read(pp, (MVNETA_MIB_COUNTERS_BASE + i));
+}
+
+/* Rx descriptors helper methods */
+
+/* Checks whether the RX descriptor having this status is both the first
+ * and the last descriptor for the RX packet. Each RX packet is currently
+ * received through a single RX descriptor, so not having each RX
+ * descriptor with its first and last bits set is an error
+ */
+static int mvneta_rxq_desc_is_first_last(u32 status)
+{
+       return (status & MVNETA_RXD_FIRST_LAST_DESC) ==
+               MVNETA_RXD_FIRST_LAST_DESC;
+}
+
+/* Add number of descriptors ready to receive new packets */
+static void mvneta_rxq_non_occup_desc_add(struct mvneta_port *pp,
+                                         struct mvneta_rx_queue *rxq,
+                                         int ndescs)
+{
+       /* Only MVNETA_RXQ_ADD_NON_OCCUPIED_MAX (255) descriptors can
+        * be added at once
+        */
+       while (ndescs > MVNETA_RXQ_ADD_NON_OCCUPIED_MAX) {
+               mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id),
+                           (MVNETA_RXQ_ADD_NON_OCCUPIED_MAX <<
+                            MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT));
+               ndescs -= MVNETA_RXQ_ADD_NON_OCCUPIED_MAX;
+       }
+
+       mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id),
+                   (ndescs << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT));
+}
+
+/* Get number of RX descriptors occupied by received packets */
+static int mvneta_rxq_busy_desc_num_get(struct mvneta_port *pp,
+                                       struct mvneta_rx_queue *rxq)
+{
+       u32 val;
+
+       val = mvreg_read(pp, MVNETA_RXQ_STATUS_REG(rxq->id));
+       return val & MVNETA_RXQ_OCCUPIED_ALL_MASK;
+}
+
+/* Update num of rx desc called upon return from rx path or
+ * from mvneta_rxq_drop_pkts().
+ */
+static void mvneta_rxq_desc_num_update(struct mvneta_port *pp,
+                                      struct mvneta_rx_queue *rxq,
+                                      int rx_done, int rx_filled)
+{
+       u32 val;
+
+       if ((rx_done <= 0xff) && (rx_filled <= 0xff)) {
+               val = rx_done |
+                 (rx_filled << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT);
+               mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), val);
+               return;
+       }
+
+       /* Only 255 descriptors can be added at once */
+       while ((rx_done > 0) || (rx_filled > 0)) {
+               if (rx_done <= 0xff) {
+                       val = rx_done;
+                       rx_done = 0;
+               } else {
+                       val = 0xff;
+                       rx_done -= 0xff;
+               }
+               if (rx_filled <= 0xff) {
+                       val |= rx_filled << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT;
+                       rx_filled = 0;
+               } else {
+                       val |= 0xff << MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT;
+                       rx_filled -= 0xff;
+               }
+               mvreg_write(pp, MVNETA_RXQ_STATUS_UPDATE_REG(rxq->id), val);
+       }
+}
+
+/* Get pointer to next RX descriptor to be processed by SW */
+static struct mvneta_rx_desc *
+mvneta_rxq_next_desc_get(struct mvneta_rx_queue *rxq)
+{
+       int rx_desc = rxq->next_desc_to_proc;
+
+       rxq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(rxq, rx_desc);
+       return rxq->descs + rx_desc;
+}
+
+/* Tx descriptors helper methods */
+
+/* Update HW with number of TX descriptors to be sent */
+static void mvneta_txq_pend_desc_add(struct mvneta_port *pp,
+                                    struct mvneta_tx_queue *txq,
+                                    int pend_desc)
+{
+       u32 val;
+
+       /* Only 255 descriptors can be added at once ; Assume caller
+        * process TX desriptors in quanta less than 256
+        */
+       val = pend_desc;
+       mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
+}
+
+/* Get pointer to next TX descriptor to be processed (send) by HW */
+static struct mvneta_tx_desc *
+mvneta_txq_next_desc_get(struct mvneta_tx_queue *txq)
+{
+       int tx_desc = txq->next_desc_to_proc;
+
+       txq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(txq, tx_desc);
+       return txq->descs + tx_desc;
+}
+
+/* Set rxq buf size */
+static void mvneta_rxq_buf_size_set(struct mvneta_port *pp,
+                                   struct mvneta_rx_queue *rxq,
+                                   int buf_size)
+{
+       u32 val;
+
+       val = mvreg_read(pp, MVNETA_RXQ_SIZE_REG(rxq->id));
+
+       val &= ~MVNETA_RXQ_BUF_SIZE_MASK;
+       val |= ((buf_size >> 3) << MVNETA_RXQ_BUF_SIZE_SHIFT);
+
+       mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), val);
+}
+
+/* Start the Ethernet port RX and TX activity */
+static void mvneta_port_up(struct mvneta_port *pp)
+{
+       int queue;
+       u32 q_map;
+
+       /* Enable all initialized TXs. */
+       mvneta_mib_counters_clear(pp);
+       q_map = 0;
+       for (queue = 0; queue < txq_number; queue++) {
+               struct mvneta_tx_queue *txq = &pp->txqs[queue];
+               if (txq->descs != NULL)
+                       q_map |= (1 << queue);
+       }
+       mvreg_write(pp, MVNETA_TXQ_CMD, q_map);
+
+       /* Enable all initialized RXQs. */
+       q_map = 0;
+       for (queue = 0; queue < rxq_number; queue++) {
+               struct mvneta_rx_queue *rxq = &pp->rxqs[queue];
+               if (rxq->descs != NULL)
+                       q_map |= (1 << queue);
+       }
+       mvreg_write(pp, MVNETA_RXQ_CMD, q_map);
+}
+
+/* Stop the Ethernet port activity */
+static void mvneta_port_down(struct mvneta_port *pp)
+{
+       u32 val;
+       int count;
+
+       /* Stop Rx port activity. Check port Rx activity. */
+       val = mvreg_read(pp, MVNETA_RXQ_CMD) & MVNETA_RXQ_ENABLE_MASK;
+
+       /* Issue stop command for active channels only */
+       if (val != 0)
+               mvreg_write(pp, MVNETA_RXQ_CMD,
+                           val << MVNETA_RXQ_DISABLE_SHIFT);
+
+       /* Wait for all Rx activity to terminate. */
+       count = 0;
+       do {
+               if (count++ >= MVNETA_RX_DISABLE_TIMEOUT_MSEC) {
+                       netdev_warn(pp->dev,
+                                   "TIMEOUT for RX stopped ! rx_queue_cmd: 0x08%x\n",
+                                   val);
+                       break;
+               }
+               mdelay(1);
+
+               val = mvreg_read(pp, MVNETA_RXQ_CMD);
+       } while (val & 0xff);
+
+       /* Stop Tx port activity. Check port Tx activity. Issue stop
+        * command for active channels only
+        */
+       val = (mvreg_read(pp, MVNETA_TXQ_CMD)) & MVNETA_TXQ_ENABLE_MASK;
+
+       if (val != 0)
+               mvreg_write(pp, MVNETA_TXQ_CMD,
+                           (val << MVNETA_TXQ_DISABLE_SHIFT));
+
+       /* Wait for all Tx activity to terminate. */
+       count = 0;
+       do {
+               if (count++ >= MVNETA_TX_DISABLE_TIMEOUT_MSEC) {
+                       netdev_warn(pp->dev,
+                                   "TIMEOUT for TX stopped status=0x%08x\n",
+                                   val);
+                       break;
+               }
+               mdelay(1);
+
+               /* Check TX Command reg that all Txqs are stopped */
+               val = mvreg_read(pp, MVNETA_TXQ_CMD);
+
+       } while (val & 0xff);
+
+       /* Double check to verify that TX FIFO is empty */
+       count = 0;
+       do {
+               if (count++ >= MVNETA_TX_FIFO_EMPTY_TIMEOUT) {
+                       netdev_warn(pp->dev,
+                                   "TX FIFO empty timeout status=0x08%x\n",
+                                   val);
+                       break;
+               }
+               mdelay(1);
+
+               val = mvreg_read(pp, MVNETA_PORT_STATUS);
+       } while (!(val & MVNETA_TX_FIFO_EMPTY) &&
+                (val & MVNETA_TX_IN_PRGRS));
+
+       udelay(200);
+}
+
+/* Enable the port by setting the port enable bit of the MAC control register */
+static void mvneta_port_enable(struct mvneta_port *pp)
+{
+       u32 val;
+
+       /* Enable port */
+       val = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
+       val |= MVNETA_GMAC0_PORT_ENABLE;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
+}
+
+/* Disable the port and wait for about 200 usec before retuning */
+static void mvneta_port_disable(struct mvneta_port *pp)
+{
+       u32 val;
+
+       /* Reset the Enable bit in the Serial Control Register */
+       val = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
+       val &= ~MVNETA_GMAC0_PORT_ENABLE;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
+
+       udelay(200);
+}
+
+/* Multicast tables methods */
+
+/* Set all entries in Unicast MAC Table; queue==-1 means reject all */
+static void mvneta_set_ucast_table(struct mvneta_port *pp, int queue)
+{
+       int offset;
+       u32 val;
+
+       if (queue == -1) {
+               val = 0;
+       } else {
+               val = 0x1 | (queue << 1);
+               val |= (val << 24) | (val << 16) | (val << 8);
+       }
+
+       for (offset = 0; offset <= 0xc; offset += 4)
+               mvreg_write(pp, MVNETA_DA_FILT_UCAST_BASE + offset, val);
+}
+
+/* Set all entries in Special Multicast MAC Table; queue==-1 means reject all */
+static void mvneta_set_special_mcast_table(struct mvneta_port *pp, int queue)
+{
+       int offset;
+       u32 val;
+
+       if (queue == -1) {
+               val = 0;
+       } else {
+               val = 0x1 | (queue << 1);
+               val |= (val << 24) | (val << 16) | (val << 8);
+       }
+
+       for (offset = 0; offset <= 0xfc; offset += 4)
+               mvreg_write(pp, MVNETA_DA_FILT_SPEC_MCAST + offset, val);
+}
+
+/* Set all entries in Other Multicast MAC Table. queue==-1 means reject all */
+static void mvneta_set_other_mcast_table(struct mvneta_port *pp, int queue)
+{
+       int offset;
+       u32 val;
+
+       if (queue == -1) {
+               memset(pp->mcast_count, 0, sizeof(pp->mcast_count));
+               val = 0;
+       } else {
+               memset(pp->mcast_count, 1, sizeof(pp->mcast_count));
+               val = 0x1 | (queue << 1);
+               val |= (val << 24) | (val << 16) | (val << 8);
+       }
+
+       for (offset = 0; offset <= 0xfc; offset += 4)
+               mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val);
+}
+
+/* This method sets defaults to the NETA port:
+ *     Clears interrupt Cause and Mask registers.
+ *     Clears all MAC tables.
+ *     Sets defaults to all registers.
+ *     Resets RX and TX descriptor rings.
+ *     Resets PHY.
+ * This method can be called after mvneta_port_down() to return the port
+ *     settings to defaults.
+ */
+static void mvneta_defaults_set(struct mvneta_port *pp)
+{
+       int cpu;
+       int queue;
+       u32 val;
+
+       /* Clear all Cause registers */
+       mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0);
+       mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
+       mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
+
+       /* Mask all interrupts */
+       mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0);
+       mvreg_write(pp, MVNETA_INTR_ENABLE, 0);
+
+       /* Enable MBUS Retry bit16 */
+       mvreg_write(pp, MVNETA_MBUS_RETRY, 0x20);
+
+       /* Set CPU queue access map - all CPUs have access to all RX
+        * queues and to all TX queues
+        */
+       for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++)
+               mvreg_write(pp, MVNETA_CPU_MAP(cpu),
+                           (MVNETA_CPU_RXQ_ACCESS_ALL_MASK |
+                            MVNETA_CPU_TXQ_ACCESS_ALL_MASK));
+
+       /* Reset RX and TX DMAs */
+       mvreg_write(pp, MVNETA_PORT_RX_RESET, MVNETA_PORT_RX_DMA_RESET);
+       mvreg_write(pp, MVNETA_PORT_TX_RESET, MVNETA_PORT_TX_DMA_RESET);
+
+       /* Disable Legacy WRR, Disable EJP, Release from reset */
+       mvreg_write(pp, MVNETA_TXQ_CMD_1, 0);
+       for (queue = 0; queue < txq_number; queue++) {
+               mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(queue), 0);
+               mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(queue), 0);
+       }
+
+       mvreg_write(pp, MVNETA_PORT_TX_RESET, 0);
+       mvreg_write(pp, MVNETA_PORT_RX_RESET, 0);
+
+       /* Set Port Acceleration Mode */
+       val = MVNETA_ACC_MODE_EXT;
+       mvreg_write(pp, MVNETA_ACC_MODE, val);
+
+       /* Update val of portCfg register accordingly with all RxQueue types */
+       val = MVNETA_PORT_CONFIG_DEFL_VALUE(rxq_def);
+       mvreg_write(pp, MVNETA_PORT_CONFIG, val);
+
+       val = 0;
+       mvreg_write(pp, MVNETA_PORT_CONFIG_EXTEND, val);
+       mvreg_write(pp, MVNETA_RX_MIN_FRAME_SIZE, 64);
+
+       /* Build PORT_SDMA_CONFIG_REG */
+       val = 0;
+
+       /* Default burst size */
+       val |= MVNETA_TX_BRST_SZ_MASK(MVNETA_SDMA_BRST_SIZE_16);
+       val |= MVNETA_RX_BRST_SZ_MASK(MVNETA_SDMA_BRST_SIZE_16);
+       val |= MVNETA_RX_NO_DATA_SWAP | MVNETA_TX_NO_DATA_SWAP;
+
+       /* Assign port SDMA configuration */
+       mvreg_write(pp, MVNETA_SDMA_CONFIG, val);
+
+       /* Enable PHY polling in hardware for U-Boot */
+       val = mvreg_read(pp, MVNETA_UNIT_CONTROL);
+       val |= MVNETA_PHY_POLLING_ENABLE;
+       mvreg_write(pp, MVNETA_UNIT_CONTROL, val);
+
+       mvneta_set_ucast_table(pp, -1);
+       mvneta_set_special_mcast_table(pp, -1);
+       mvneta_set_other_mcast_table(pp, -1);
+}
+
+/* Set unicast address */
+static void mvneta_set_ucast_addr(struct mvneta_port *pp, u8 last_nibble,
+                                 int queue)
+{
+       unsigned int unicast_reg;
+       unsigned int tbl_offset;
+       unsigned int reg_offset;
+
+       /* Locate the Unicast table entry */
+       last_nibble = (0xf & last_nibble);
+
+       /* offset from unicast tbl base */
+       tbl_offset = (last_nibble / 4) * 4;
+
+       /* offset within the above reg  */
+       reg_offset = last_nibble % 4;
+
+       unicast_reg = mvreg_read(pp, (MVNETA_DA_FILT_UCAST_BASE + tbl_offset));
+
+       if (queue == -1) {
+               /* Clear accepts frame bit at specified unicast DA tbl entry */
+               unicast_reg &= ~(0xff << (8 * reg_offset));
+       } else {
+               unicast_reg &= ~(0xff << (8 * reg_offset));
+               unicast_reg |= ((0x01 | (queue << 1)) << (8 * reg_offset));
+       }
+
+       mvreg_write(pp, (MVNETA_DA_FILT_UCAST_BASE + tbl_offset), unicast_reg);
+}
+
+/* Set mac address */
+static void mvneta_mac_addr_set(struct mvneta_port *pp, unsigned char *addr,
+                               int queue)
+{
+       unsigned int mac_h;
+       unsigned int mac_l;
+
+       if (queue != -1) {
+               mac_l = (addr[4] << 8) | (addr[5]);
+               mac_h = (addr[0] << 24) | (addr[1] << 16) |
+                       (addr[2] << 8) | (addr[3] << 0);
+
+               mvreg_write(pp, MVNETA_MAC_ADDR_LOW, mac_l);
+               mvreg_write(pp, MVNETA_MAC_ADDR_HIGH, mac_h);
+       }
+
+       /* Accept frames of this address */
+       mvneta_set_ucast_addr(pp, addr[5], queue);
+}
+
+/* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
+static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
+                               u32 phys_addr, u32 cookie)
+{
+       rx_desc->buf_cookie = cookie;
+       rx_desc->buf_phys_addr = phys_addr;
+}
+
+/* Decrement sent descriptors counter */
+static void mvneta_txq_sent_desc_dec(struct mvneta_port *pp,
+                                    struct mvneta_tx_queue *txq,
+                                    int sent_desc)
+{
+       u32 val;
+
+       /* Only 255 TX descriptors can be updated at once */
+       while (sent_desc > 0xff) {
+               val = 0xff << MVNETA_TXQ_DEC_SENT_SHIFT;
+               mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
+               sent_desc = sent_desc - 0xff;
+       }
+
+       val = sent_desc << MVNETA_TXQ_DEC_SENT_SHIFT;
+       mvreg_write(pp, MVNETA_TXQ_UPDATE_REG(txq->id), val);
+}
+
+/* Get number of TX descriptors already sent by HW */
+static int mvneta_txq_sent_desc_num_get(struct mvneta_port *pp,
+                                       struct mvneta_tx_queue *txq)
+{
+       u32 val;
+       int sent_desc;
+
+       val = mvreg_read(pp, MVNETA_TXQ_STATUS_REG(txq->id));
+       sent_desc = (val & MVNETA_TXQ_SENT_DESC_MASK) >>
+               MVNETA_TXQ_SENT_DESC_SHIFT;
+
+       return sent_desc;
+}
+
+/* Display more error info */
+static void mvneta_rx_error(struct mvneta_port *pp,
+                           struct mvneta_rx_desc *rx_desc)
+{
+       u32 status = rx_desc->status;
+
+       if (!mvneta_rxq_desc_is_first_last(status)) {
+               netdev_err(pp->dev,
+                          "bad rx status %08x (buffer oversize), size=%d\n",
+                          status, rx_desc->data_size);
+               return;
+       }
+
+       switch (status & MVNETA_RXD_ERR_CODE_MASK) {
+       case MVNETA_RXD_ERR_CRC:
+               netdev_err(pp->dev, "bad rx status %08x (crc error), size=%d\n",
+                          status, rx_desc->data_size);
+               break;
+       case MVNETA_RXD_ERR_OVERRUN:
+               netdev_err(pp->dev, "bad rx status %08x (overrun error), size=%d\n",
+                          status, rx_desc->data_size);
+               break;
+       case MVNETA_RXD_ERR_LEN:
+               netdev_err(pp->dev, "bad rx status %08x (max frame length error), size=%d\n",
+                          status, rx_desc->data_size);
+               break;
+       case MVNETA_RXD_ERR_RESOURCE:
+               netdev_err(pp->dev, "bad rx status %08x (resource error), size=%d\n",
+                          status, rx_desc->data_size);
+               break;
+       }
+}
+
+static struct mvneta_rx_queue *mvneta_rxq_handle_get(struct mvneta_port *pp,
+                                                    int rxq)
+{
+       return &pp->rxqs[rxq];
+}
+
+
+/* Drop packets received by the RXQ and free buffers */
+static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
+                                struct mvneta_rx_queue *rxq)
+{
+       int rx_done;
+
+       rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
+       if (rx_done)
+               mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
+}
+
+/* Handle rxq fill: allocates rxq skbs; called when initializing a port */
+static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
+                          int num)
+{
+       int i;
+
+       for (i = 0; i < num; i++) {
+               u32 addr;
+
+               /* U-Boot special: Fill in the rx buffer addresses */
+               addr = buffer_loc.rx_buffers + (i * RX_BUFFER_SIZE);
+               mvneta_rx_desc_fill(rxq->descs + i, addr, addr);
+       }
+
+       /* Add this number of RX descriptors as non occupied (ready to
+        * get packets)
+        */
+       mvneta_rxq_non_occup_desc_add(pp, rxq, i);
+
+       return 0;
+}
+
+/* Rx/Tx queue initialization/cleanup methods */
+
+/* Create a specified RX queue */
+static int mvneta_rxq_init(struct mvneta_port *pp,
+                          struct mvneta_rx_queue *rxq)
+
+{
+       rxq->size = pp->rx_ring_size;
+
+       /* Allocate memory for RX descriptors */
+       rxq->descs_phys = (dma_addr_t)rxq->descs;
+       if (rxq->descs == NULL)
+               return -ENOMEM;
+
+       rxq->last_desc = rxq->size - 1;
+
+       /* Set Rx descriptors queue starting address */
+       mvreg_write(pp, MVNETA_RXQ_BASE_ADDR_REG(rxq->id), rxq->descs_phys);
+       mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), rxq->size);
+
+       /* Fill RXQ with buffers from RX pool */
+       mvneta_rxq_buf_size_set(pp, rxq, RX_BUFFER_SIZE);
+       mvneta_rxq_fill(pp, rxq, rxq->size);
+
+       return 0;
+}
+
+/* Cleanup Rx queue */
+static void mvneta_rxq_deinit(struct mvneta_port *pp,
+                             struct mvneta_rx_queue *rxq)
+{
+       mvneta_rxq_drop_pkts(pp, rxq);
+
+       rxq->descs             = NULL;
+       rxq->last_desc         = 0;
+       rxq->next_desc_to_proc = 0;
+       rxq->descs_phys        = 0;
+}
+
+/* Create and initialize a tx queue */
+static int mvneta_txq_init(struct mvneta_port *pp,
+                          struct mvneta_tx_queue *txq)
+{
+       txq->size = pp->tx_ring_size;
+
+       /* Allocate memory for TX descriptors */
+       txq->descs_phys = (u32)txq->descs;
+       if (txq->descs == NULL)
+               return -ENOMEM;
+
+       txq->last_desc = txq->size - 1;
+
+       /* Set maximum bandwidth for enabled TXQs */
+       mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(txq->id), 0x03ffffff);
+       mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(txq->id), 0x3fffffff);
+
+       /* Set Tx descriptors queue starting address */
+       mvreg_write(pp, MVNETA_TXQ_BASE_ADDR_REG(txq->id), txq->descs_phys);
+       mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), txq->size);
+
+       return 0;
+}
+
+/* Free allocated resources when mvneta_txq_init() fails to allocate memory*/
+static void mvneta_txq_deinit(struct mvneta_port *pp,
+                             struct mvneta_tx_queue *txq)
+{
+       txq->descs             = NULL;
+       txq->last_desc         = 0;
+       txq->next_desc_to_proc = 0;
+       txq->descs_phys        = 0;
+
+       /* Set minimum bandwidth for disabled TXQs */
+       mvreg_write(pp, MVETH_TXQ_TOKEN_CFG_REG(txq->id), 0);
+       mvreg_write(pp, MVETH_TXQ_TOKEN_COUNT_REG(txq->id), 0);
+
+       /* Set Tx descriptors queue starting address and size */
+       mvreg_write(pp, MVNETA_TXQ_BASE_ADDR_REG(txq->id), 0);
+       mvreg_write(pp, MVNETA_TXQ_SIZE_REG(txq->id), 0);
+}
+
+/* Cleanup all Tx queues */
+static void mvneta_cleanup_txqs(struct mvneta_port *pp)
+{
+       int queue;
+
+       for (queue = 0; queue < txq_number; queue++)
+               mvneta_txq_deinit(pp, &pp->txqs[queue]);
+}
+
+/* Cleanup all Rx queues */
+static void mvneta_cleanup_rxqs(struct mvneta_port *pp)
+{
+       int queue;
+
+       for (queue = 0; queue < rxq_number; queue++)
+               mvneta_rxq_deinit(pp, &pp->rxqs[queue]);
+}
+
+
+/* Init all Rx queues */
+static int mvneta_setup_rxqs(struct mvneta_port *pp)
+{
+       int queue;
+
+       for (queue = 0; queue < rxq_number; queue++) {
+               int err = mvneta_rxq_init(pp, &pp->rxqs[queue]);
+               if (err) {
+                       netdev_err(pp->dev, "%s: can't create rxq=%d\n",
+                                  __func__, queue);
+                       mvneta_cleanup_rxqs(pp);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+/* Init all tx queues */
+static int mvneta_setup_txqs(struct mvneta_port *pp)
+{
+       int queue;
+
+       for (queue = 0; queue < txq_number; queue++) {
+               int err = mvneta_txq_init(pp, &pp->txqs[queue]);
+               if (err) {
+                       netdev_err(pp->dev, "%s: can't create txq=%d\n",
+                                  __func__, queue);
+                       mvneta_cleanup_txqs(pp);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static void mvneta_start_dev(struct mvneta_port *pp)
+{
+       /* start the Rx/Tx activity */
+       mvneta_port_enable(pp);
+}
+
+static void mvneta_adjust_link(struct eth_device *dev)
+{
+       struct mvneta_port *pp = dev->priv;
+       struct phy_device *phydev = pp->phydev;
+       int status_change = 0;
+
+       if (phydev->link) {
+               if ((pp->speed != phydev->speed) ||
+                   (pp->duplex != phydev->duplex)) {
+                       u32 val;
+
+                       val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+                       val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
+                                MVNETA_GMAC_CONFIG_GMII_SPEED |
+                                MVNETA_GMAC_CONFIG_FULL_DUPLEX |
+                                MVNETA_GMAC_AN_SPEED_EN |
+                                MVNETA_GMAC_AN_DUPLEX_EN);
+
+                       if (phydev->duplex)
+                               val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
+
+                       if (phydev->speed == SPEED_1000)
+                               val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
+                       else
+                               val |= MVNETA_GMAC_CONFIG_MII_SPEED;
+
+                       mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+
+                       pp->duplex = phydev->duplex;
+                       pp->speed  = phydev->speed;
+               }
+       }
+
+       if (phydev->link != pp->link) {
+               if (!phydev->link) {
+                       pp->duplex = -1;
+                       pp->speed = 0;
+               }
+
+               pp->link = phydev->link;
+               status_change = 1;
+       }
+
+       if (status_change) {
+               if (phydev->link) {
+                       u32 val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+                       val |= (MVNETA_GMAC_FORCE_LINK_PASS |
+                               MVNETA_GMAC_FORCE_LINK_DOWN);
+                       mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+                       mvneta_port_up(pp);
+               } else {
+                       mvneta_port_down(pp);
+               }
+       }
+}
+
+static int mvneta_open(struct eth_device *dev)
+{
+       struct mvneta_port *pp = dev->priv;
+       int ret;
+
+       ret = mvneta_setup_rxqs(pp);
+       if (ret)
+               return ret;
+
+       ret = mvneta_setup_txqs(pp);
+       if (ret)
+               return ret;
+
+       mvneta_adjust_link(dev);
+
+       mvneta_start_dev(pp);
+
+       return 0;
+}
+
+/* Initialize hw */
+static int mvneta_init(struct mvneta_port *pp)
+{
+       int queue;
+
+       /* Disable port */
+       mvneta_port_disable(pp);
+
+       /* Set port default values */
+       mvneta_defaults_set(pp);
+
+       pp->txqs = kzalloc(txq_number * sizeof(struct mvneta_tx_queue),
+                          GFP_KERNEL);
+       if (!pp->txqs)
+               return -ENOMEM;
+
+       /* U-Boot special: use preallocated area */
+       pp->txqs[0].descs = buffer_loc.tx_descs;
+
+       /* Initialize TX descriptor rings */
+       for (queue = 0; queue < txq_number; queue++) {
+               struct mvneta_tx_queue *txq = &pp->txqs[queue];
+               txq->id = queue;
+               txq->size = pp->tx_ring_size;
+       }
+
+       pp->rxqs = kzalloc(rxq_number * sizeof(struct mvneta_rx_queue),
+                          GFP_KERNEL);
+       if (!pp->rxqs) {
+               kfree(pp->txqs);
+               return -ENOMEM;
+       }
+
+       /* U-Boot special: use preallocated area */
+       pp->rxqs[0].descs = buffer_loc.rx_descs;
+
+       /* Create Rx descriptor rings */
+       for (queue = 0; queue < rxq_number; queue++) {
+               struct mvneta_rx_queue *rxq = &pp->rxqs[queue];
+               rxq->id = queue;
+               rxq->size = pp->rx_ring_size;
+       }
+
+       return 0;
+}
+
+/* platform glue : initialize decoding windows */
+static void mvneta_conf_mbus_windows(struct mvneta_port *pp)
+{
+       const struct mbus_dram_target_info *dram;
+       u32 win_enable;
+       u32 win_protect;
+       int i;
+
+       dram = mvebu_mbus_dram_info();
+       for (i = 0; i < 6; i++) {
+               mvreg_write(pp, MVNETA_WIN_BASE(i), 0);
+               mvreg_write(pp, MVNETA_WIN_SIZE(i), 0);
+
+               if (i < 4)
+                       mvreg_write(pp, MVNETA_WIN_REMAP(i), 0);
+       }
+
+       win_enable = 0x3f;
+       win_protect = 0;
+
+       for (i = 0; i < dram->num_cs; i++) {
+               const struct mbus_dram_window *cs = dram->cs + i;
+               mvreg_write(pp, MVNETA_WIN_BASE(i), (cs->base & 0xffff0000) |
+                           (cs->mbus_attr << 8) | dram->mbus_dram_target_id);
+
+               mvreg_write(pp, MVNETA_WIN_SIZE(i),
+                           (cs->size - 1) & 0xffff0000);
+
+               win_enable &= ~(1 << i);
+               win_protect |= 3 << (2 * i);
+       }
+
+       mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, win_enable);
+}
+
+/* Power up the port */
+static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
+{
+       u32 ctrl;
+
+       /* MAC Cause register should be cleared */
+       mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
+
+       ctrl = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+
+       /* Even though it might look weird, when we're configured in
+        * SGMII or QSGMII mode, the RGMII bit needs to be set.
+        */
+       switch (phy_mode) {
+       case PHY_INTERFACE_MODE_QSGMII:
+               mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
+               ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+               break;
+       case PHY_INTERFACE_MODE_SGMII:
+               mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
+               ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+               break;
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+               ctrl |= MVNETA_GMAC2_PORT_RGMII;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Cancel Port Reset */
+       ctrl &= ~MVNETA_GMAC2_PORT_RESET;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl);
+
+       while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) &
+               MVNETA_GMAC2_PORT_RESET) != 0)
+               continue;
+
+       return 0;
+}
+
+/* Device initialization routine */
+static int mvneta_probe(struct eth_device *dev)
+{
+       struct mvneta_port *pp = dev->priv;
+       int err;
+
+       pp->tx_ring_size = MVNETA_MAX_TXD;
+       pp->rx_ring_size = MVNETA_MAX_RXD;
+
+       err = mvneta_init(pp);
+       if (err < 0) {
+               dev_err(&pdev->dev, "can't init eth hal\n");
+               return err;
+       }
+
+       mvneta_conf_mbus_windows(pp);
+
+       mvneta_mac_addr_set(pp, dev->enetaddr, rxq_def);
+
+       err = mvneta_port_power_up(pp, pp->phy_interface);
+       if (err < 0) {
+               dev_err(&pdev->dev, "can't power up port\n");
+               return err;
+       }
+
+       /* Call open() now as it needs to be done before runing send() */
+       mvneta_open(dev);
+
+       return 0;
+}
+
+/* U-Boot only functions follow here */
+
+/* SMI / MDIO functions */
+
+static int smi_wait_ready(struct mvneta_port *pp)
+{
+       u32 timeout = MVNETA_SMI_TIMEOUT;
+       u32 smi_reg;
+
+       /* wait till the SMI is not busy */
+       do {
+               /* read smi register */
+               smi_reg = mvreg_read(pp, MVNETA_SMI);
+               if (timeout-- == 0) {
+                       printf("Error: SMI busy timeout\n");
+                       return -EFAULT;
+               }
+       } while (smi_reg & MVNETA_SMI_BUSY);
+
+       return 0;
+}
+
+/*
+ * smi_reg_read - miiphy_read callback function.
+ *
+ * Returns 16bit phy register value, or 0xffff on error
+ */
+static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
+{
+       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct mvneta_port *pp = dev->priv;
+       u32 smi_reg;
+       u32 timeout;
+
+       /* check parameters */
+       if (phy_adr > MVNETA_PHY_ADDR_MASK) {
+               printf("Error: Invalid PHY address %d\n", phy_adr);
+               return -EFAULT;
+       }
+
+       if (reg_ofs > MVNETA_PHY_REG_MASK) {
+               printf("Err: Invalid register offset %d\n", reg_ofs);
+               return -EFAULT;
+       }
+
+       /* wait till the SMI is not busy */
+       if (smi_wait_ready(pp) < 0)
+               return -EFAULT;
+
+       /* fill the phy address and regiser offset and read opcode */
+       smi_reg = (phy_adr << MVNETA_SMI_DEV_ADDR_OFFS)
+               | (reg_ofs << MVNETA_SMI_REG_ADDR_OFFS)
+               | MVNETA_SMI_OPCODE_READ;
+
+       /* write the smi register */
+       mvreg_write(pp, MVNETA_SMI, smi_reg);
+
+       /*wait till read value is ready */
+       timeout = MVNETA_SMI_TIMEOUT;
+
+       do {
+               /* read smi register */
+               smi_reg = mvreg_read(pp, MVNETA_SMI);
+               if (timeout-- == 0) {
+                       printf("Err: SMI read ready timeout\n");
+                       return -EFAULT;
+               }
+       } while (!(smi_reg & MVNETA_SMI_READ_VALID));
+
+       /* Wait for the data to update in the SMI register */
+       for (timeout = 0; timeout < MVNETA_SMI_TIMEOUT; timeout++)
+               ;
+
+       *data = (u16)(mvreg_read(pp, MVNETA_SMI) & MVNETA_SMI_DATA_MASK);
+
+       return 0;
+}
+
+/*
+ * smi_reg_write - imiiphy_write callback function.
+ *
+ * Returns 0 if write succeed, -EINVAL on bad parameters
+ * -ETIME on timeout
+ */
+static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
+{
+       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct mvneta_port *pp = dev->priv;
+       u32 smi_reg;
+
+       /* check parameters */
+       if (phy_adr > MVNETA_PHY_ADDR_MASK) {
+               printf("Error: Invalid PHY address %d\n", phy_adr);
+               return -EFAULT;
+       }
+
+       if (reg_ofs > MVNETA_PHY_REG_MASK) {
+               printf("Err: Invalid register offset %d\n", reg_ofs);
+               return -EFAULT;
+       }
+
+       /* wait till the SMI is not busy */
+       if (smi_wait_ready(pp) < 0)
+               return -EFAULT;
+
+       /* fill the phy addr and reg offset and write opcode and data */
+       smi_reg = (data << MVNETA_SMI_DATA_OFFS);
+       smi_reg |= (phy_adr << MVNETA_SMI_DEV_ADDR_OFFS)
+               | (reg_ofs << MVNETA_SMI_REG_ADDR_OFFS);
+       smi_reg &= ~MVNETA_SMI_OPCODE_READ;
+
+       /* write the smi register */
+       mvreg_write(pp, MVNETA_SMI, smi_reg);
+
+       return 0;
+}
+
+static int mvneta_init_u_boot(struct eth_device *dev, bd_t *bis)
+{
+       struct mvneta_port *pp = dev->priv;
+       struct phy_device *phydev;
+
+       mvneta_port_power_up(pp, pp->phy_interface);
+
+       if (!pp->init || pp->link == 0) {
+               /* Set phy address of the port */
+               mvreg_write(pp, MVNETA_PHY_ADDR, pp->phyaddr);
+               phydev = phy_connect(pp->bus, pp->phyaddr, dev,
+                                    pp->phy_interface);
+
+               pp->phydev = phydev;
+               phy_config(phydev);
+               phy_startup(phydev);
+               if (!phydev->link) {
+                       printf("%s: No link.\n", phydev->dev->name);
+                       return -1;
+               }
+
+               /* Full init on first call */
+               mvneta_probe(dev);
+               pp->init = 1;
+       } else {
+               /* Upon all following calls, this is enough */
+               mvneta_port_up(pp);
+               mvneta_port_enable(pp);
+       }
+
+       return 0;
+}
+
+static int mvneta_send(struct eth_device *dev, void *ptr, int len)
+{
+       struct mvneta_port *pp = dev->priv;
+       struct mvneta_tx_queue *txq = &pp->txqs[0];
+       struct mvneta_tx_desc *tx_desc;
+       int sent_desc;
+       u32 timeout = 0;
+
+       /* Get a descriptor for the first part of the packet */
+       tx_desc = mvneta_txq_next_desc_get(txq);
+
+       tx_desc->buf_phys_addr = (u32)ptr;
+       tx_desc->data_size = len;
+       flush_dcache_range((u32)ptr, (u32)ptr + len);
+
+       /* First and Last descriptor */
+       tx_desc->command = MVNETA_TX_L4_CSUM_NOT | MVNETA_TXD_FLZ_DESC;
+       mvneta_txq_pend_desc_add(pp, txq, 1);
+
+       /* Wait for packet to be sent (queue might help with speed here) */
+       sent_desc = mvneta_txq_sent_desc_num_get(pp, txq);
+       while (!sent_desc) {
+               if (timeout++ > 10000) {
+                       printf("timeout: packet not sent\n");
+                       return -1;
+               }
+               sent_desc = mvneta_txq_sent_desc_num_get(pp, txq);
+       }
+
+       /* txDone has increased - hw sent packet */
+       mvneta_txq_sent_desc_dec(pp, txq, sent_desc);
+       return 0;
+
+       return 0;
+}
+
+static int mvneta_recv(struct eth_device *dev)
+{
+       struct mvneta_port *pp = dev->priv;
+       int rx_done;
+       int packets_done;
+       struct mvneta_rx_queue *rxq;
+
+       /* get rx queue */
+       rxq = mvneta_rxq_handle_get(pp, rxq_def);
+       rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
+       packets_done = rx_done;
+
+       while (packets_done--) {
+               struct mvneta_rx_desc *rx_desc;
+               unsigned char *data;
+               u32 rx_status;
+               int rx_bytes;
+
+               /*
+                * No cache invalidation needed here, since the desc's are
+                * located in a uncached memory region
+                */
+               rx_desc = mvneta_rxq_next_desc_get(rxq);
+
+               rx_status = rx_desc->status;
+               if (!mvneta_rxq_desc_is_first_last(rx_status) ||
+                   (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
+                       mvneta_rx_error(pp, rx_desc);
+                       /* leave the descriptor untouched */
+                       continue;
+               }
+
+               /* 2 bytes for marvell header. 4 bytes for crc */
+               rx_bytes = rx_desc->data_size - 6;
+
+               /* give packet to stack - skip on first 2 bytes */
+               data = (u8 *)rx_desc->buf_cookie + 2;
+               /*
+                * No cache invalidation needed here, since the rx_buffer's are
+                * located in a uncached memory region
+                */
+               NetReceive(data, rx_bytes);
+       }
+
+       /* Update rxq management counters */
+       if (rx_done)
+               mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
+
+       return 0;
+}
+
+static void mvneta_halt(struct eth_device *dev)
+{
+       struct mvneta_port *pp = dev->priv;
+
+       mvneta_port_down(pp);
+       mvneta_port_disable(pp);
+}
+
+int mvneta_initialize(bd_t *bis, int base_addr, int devnum, int phy_addr)
+{
+       struct eth_device *dev;
+       struct mvneta_port *pp;
+       void *bd_space;
+
+       dev = calloc(1, sizeof(*dev));
+       if (dev == NULL)
+               return -ENOMEM;
+
+       pp = calloc(1, sizeof(*pp));
+       if (pp == NULL)
+               return -ENOMEM;
+
+       dev->priv = pp;
+
+       /*
+        * Allocate buffer area for descs and rx_buffers. This is only
+        * done once for all interfaces. As only one interface can
+        * be active. Make this area DMA save by disabling the D-cache
+        */
+       if (!buffer_loc.tx_descs) {
+               /* Align buffer area for descs and rx_buffers to 1MiB */
+               bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
+               mmu_set_region_dcache_behaviour((u32)bd_space, BD_SPACE,
+                                               DCACHE_OFF);
+               buffer_loc.tx_descs = (struct mvneta_tx_desc *)bd_space;
+               buffer_loc.rx_descs = (struct mvneta_rx_desc *)
+                       ((u32)bd_space +
+                        MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc));
+               buffer_loc.rx_buffers = (u32)
+                       (bd_space +
+                        MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc) +
+                        MVNETA_MAX_RXD * sizeof(struct mvneta_rx_desc));
+       }
+
+       sprintf(dev->name, "neta%d", devnum);
+
+       pp->base = (void __iomem *)base_addr;
+       dev->iobase = base_addr;
+       dev->init = mvneta_init_u_boot;
+       dev->halt = mvneta_halt;
+       dev->send = mvneta_send;
+       dev->recv = mvneta_recv;
+       dev->write_hwaddr = NULL;
+
+       /*
+        * The PHY interface type is configured via the
+        * board specific CONFIG_SYS_NETA_INTERFACE_TYPE
+        * define.
+        */
+       pp->phy_interface = CONFIG_SYS_NETA_INTERFACE_TYPE;
+
+       eth_register(dev);
+
+       pp->phyaddr = phy_addr;
+       miiphy_register(dev->name, smi_reg_read, smi_reg_write);
+       pp->bus = miiphy_get_dev_by_name(dev->name);
+
+       return 1;
+}
index 1d6c14f2ade7497bc7b2ded23bffce21f250a821..f1ace3c8421004d6ba0b7f2d61051a215c25372b 100644 (file)
@@ -575,7 +575,7 @@ static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
  * Description: Reads the ID registers of the PHY at @addr on the
  *   @bus, stores it in @phy_id and returns zero on success.
  */
-int __weak get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
+static int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
 {
        int phy_reg;
 
@@ -785,16 +785,13 @@ int phy_startup(struct phy_device *phydev)
        return 0;
 }
 
-static int __board_phy_config(struct phy_device *phydev)
+__weak int board_phy_config(struct phy_device *phydev)
 {
        if (phydev->drv->config)
                return phydev->drv->config(phydev);
        return 0;
 }
 
-int board_phy_config(struct phy_device *phydev)
-       __attribute__((weak, alias("__board_phy_config")));
-
 int phy_config(struct phy_device *phydev)
 {
        /* Invoke an optional board-specific helper */
index 28859f31612527ccff49ee3fbc69dbbc1caaaa54..60c333e2c0191d5ef8753075669a7edc3af95532 100644 (file)
@@ -572,7 +572,7 @@ const char * pci_class_str(u8 class)
 }
 #endif /* CONFIG_CMD_PCI || CONFIG_PCI_SCAN_SHOW */
 
-int __pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
+__weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
 {
        /*
         * Check if pci device should be skipped in configuration
@@ -591,19 +591,15 @@ int __pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
 
        return 0;
 }
-int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
-       __attribute__((weak, alias("__pci_skip_dev")));
 
 #ifdef CONFIG_PCI_SCAN_SHOW
-int __pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
+__weak int pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
 {
        if (dev == PCI_BDF(hose->first_busno, 0, 0))
                return 0;
 
        return 1;
 }
-int pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
-       __attribute__((weak, alias("__pci_print_dev")));
 #endif /* CONFIG_PCI_SCAN_SHOW */
 
 int pci_hose_scan_bus(struct pci_controller *hose, int bus)
index ce7a69bab57048d7f8e1a40a1377de96946d5e5c..ebddc124c3dae96195f31eca4bab99f60bc5204a 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef _MVRTC_H_
 #define _MVRTC_H_
 
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #include <compiler.h>
 
 /* RTC registers */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a0b6e02b5462e5fc515a28d7f40b04a46c22018d 100644 (file)
@@ -0,0 +1,12 @@
+config DM_SERIAL
+       bool "Enable Driver Model for serial drivers"
+       depends on DM
+       help
+         If you want to use driver model for serial drivers, say Y.
+         To use legacy serial drivers, say N.
+
+config UNIPHIER_SERIAL
+       bool "UniPhier on-chip UART support"
+       depends on ARCH_UNIPHIER && DM_SERIAL
+       help
+         Support for the on-chip UARTs on the Panasonic UniPhier platform.
index b4f299bb0ede65966624972b900c09142f202e24..2c19ebc2885e90c77b58302e989527a162d9c517 100644 (file)
@@ -7,8 +7,11 @@
 
 ifdef CONFIG_DM_SERIAL
 obj-y += serial-uclass.o
+obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o
 else
 obj-y += serial.o
+obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
+obj-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
 obj-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o
 endif
 
@@ -25,8 +28,6 @@ obj-$(CONFIG_IMX_SERIAL) += serial_imx.o
 obj-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o
 obj-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o
 obj-$(CONFIG_MXC_UART) += serial_mxc.o
-obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
-obj-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
 obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
 obj-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o
 obj-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o
@@ -40,6 +41,8 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o
 obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
 obj-$(CONFIG_TEGRA_SERIAL) += serial_tegra.o
 obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
+obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
+obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_USB_TTY) += usbtty.o
index 63a9ef68444d3af762213467b1b9e9524aaa4473..8f051914f54a37539d5768dd9d8ed90ff34adcf0 100644 (file)
@@ -61,13 +61,13 @@ static void ns16550_writeb(NS16550_t port, int offset, int value)
        unsigned char *addr;
 
        offset *= 1 << plat->reg_shift;
-       addr = plat->base + offset;
+       addr = map_sysmem(plat->base, 0) + offset;
        /*
         * As far as we know it doesn't make sense to support selection of
         * these options at run-time, so use the existing CONFIG options.
         */
 #ifdef CONFIG_SYS_NS16550_PORT_MAPPED
-       outb(value, addr);
+       outb(value, (ulong)addr);
 #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
        out_le32(addr, value);
 #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
@@ -85,9 +85,9 @@ static int ns16550_readb(NS16550_t port, int offset)
        unsigned char *addr;
 
        offset *= 1 << plat->reg_shift;
-       addr = plat->base + offset;
+       addr = map_sysmem(plat->base, 0) + offset;
 #ifdef CONFIG_SYS_NS16550_PORT_MAPPED
-       return inb(addr);
+       return inb((ulong)addr);
 #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN)
        return in_le32(addr);
 #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
@@ -253,7 +253,7 @@ static int ns16550_serial_getc(struct udevice *dev)
 {
        struct NS16550 *const com_port = dev_get_priv(dev);
 
-       if (!serial_in(&com_port->lsr) & UART_LSR_DR)
+       if (!(serial_in(&com_port->lsr) & UART_LSR_DR))
                return -EAGAIN;
 
        return serial_in(&com_port->rbr);
@@ -276,14 +276,15 @@ int ns16550_serial_probe(struct udevice *dev)
 {
        struct NS16550 *const com_port = dev_get_priv(dev);
 
+       com_port->plat = dev_get_platdata(dev);
        NS16550_init(com_port, -1);
 
        return 0;
 }
 
+#ifdef CONFIG_OF_CONTROL
 int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
 {
-       struct NS16550 *const com_port = dev_get_priv(dev);
        struct ns16550_platdata *plat = dev->platdata;
        fdt_addr_t addr;
 
@@ -291,13 +292,13 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
        if (addr == FDT_ADDR_T_NONE)
                return -EINVAL;
 
-       plat->base = (unsigned char *)addr;
+       plat->base = addr;
        plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
                                         "reg-shift", 1);
-       com_port->plat = plat;
 
        return 0;
 }
+#endif
 
 const struct dm_serial_ops ns16550_serial_ops = {
        .putc = ns16550_serial_putc,
index 6dde4eaf47286a3a38feb3c84a782c5421c01630..71f1a5cb91024e9fc473e2a5e61f0deb82efd3c1 100644 (file)
 #include <os.h>
 #include <serial.h>
 #include <stdio_dev.h>
+#include <watchdog.h>
 #include <dm/lists.h>
 #include <dm/device-internal.h>
 
+#include <ns16550.h>
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* The currently-selected console serial device */
@@ -47,13 +50,22 @@ static void serial_find_console_or_panic(void)
        }
 #endif
        /*
+        * Try to use CONFIG_CONS_INDEX if available (it is numbered from 1!).
+        *
         * Failing that, get the device with sequence number 0, or in extremis
         * just the first serial device we can find. But we insist on having
         * a console (even if it is silent).
         */
-       if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) &&
+#ifdef CONFIG_CONS_INDEX
+#define INDEX (CONFIG_CONS_INDEX - 1)
+#else
+#define INDEX 0
+#endif
+       if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) &&
+           uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) &&
            (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev))
                panic("No serial driver found");
+#undef INDEX
 }
 
 /* Called prior to relocation */
@@ -71,95 +83,98 @@ void serial_initialize(void)
        serial_find_console_or_panic();
 }
 
-void serial_putc(char ch)
+static void _serial_putc(struct udevice *dev, char ch)
 {
-       struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+       struct dm_serial_ops *ops = serial_get_ops(dev);
        int err;
 
        do {
-               err = ops->putc(cur_dev, ch);
+               err = ops->putc(dev, ch);
        } while (err == -EAGAIN);
        if (ch == '\n')
-               serial_putc('\r');
+               _serial_putc(dev, '\r');
 }
 
-void serial_setbrg(void)
+static void _serial_puts(struct udevice *dev, const char *str)
 {
-       struct dm_serial_ops *ops = serial_get_ops(cur_dev);
-
-       if (ops->setbrg)
-               ops->setbrg(cur_dev, gd->baudrate);
+       while (*str)
+               _serial_putc(dev, *str++);
 }
 
-void serial_puts(const char *str)
+static int _serial_getc(struct udevice *dev)
 {
-       while (*str)
-               serial_putc(*str++);
+       struct dm_serial_ops *ops = serial_get_ops(dev);
+       int err;
+
+       do {
+               err = ops->getc(dev);
+               if (err == -EAGAIN)
+                       WATCHDOG_RESET();
+       } while (err == -EAGAIN);
+
+       return err >= 0 ? err : 0;
 }
 
-int serial_tstc(void)
+static int _serial_tstc(struct udevice *dev)
 {
-       struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+       struct dm_serial_ops *ops = serial_get_ops(dev);
 
        if (ops->pending)
-               return ops->pending(cur_dev, true);
+               return ops->pending(dev, true);
 
        return 1;
 }
 
+void serial_putc(char ch)
+{
+       _serial_putc(cur_dev, ch);
+}
+
+void serial_puts(const char *str)
+{
+       _serial_puts(cur_dev, str);
+}
+
 int serial_getc(void)
 {
-       struct dm_serial_ops *ops = serial_get_ops(cur_dev);
-       int err;
+       return _serial_getc(cur_dev);
+}
 
-       do {
-               err = ops->getc(cur_dev);
-       } while (err == -EAGAIN);
+int serial_tstc(void)
+{
+       return _serial_tstc(cur_dev);
+}
 
-       return err >= 0 ? err : 0;
+void serial_setbrg(void)
+{
+       struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+
+       if (ops->setbrg)
+               ops->setbrg(cur_dev, gd->baudrate);
 }
 
 void serial_stdio_init(void)
 {
 }
 
-void serial_stub_putc(struct stdio_dev *sdev, const char ch)
+static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
 {
-       struct udevice *dev = sdev->priv;
-       struct dm_serial_ops *ops = serial_get_ops(dev);
-
-       ops->putc(dev, ch);
+       _serial_putc(sdev->priv, ch);
 }
 
 void serial_stub_puts(struct stdio_dev *sdev, const char *str)
 {
-       while (*str)
-               serial_stub_putc(sdev, *str++);
+       _serial_puts(sdev->priv, str);
 }
 
 int serial_stub_getc(struct stdio_dev *sdev)
 {
-       struct udevice *dev = sdev->priv;
-       struct dm_serial_ops *ops = serial_get_ops(dev);
-
-       int err;
-
-       do {
-               err = ops->getc(dev);
-       } while (err == -EAGAIN);
-
-       return err >= 0 ? err : 0;
+       return _serial_getc(sdev->priv);
 }
 
 int serial_stub_tstc(struct stdio_dev *sdev)
 {
-       struct udevice *dev = sdev->priv;
-       struct dm_serial_ops *ops = serial_get_ops(dev);
-
-       if (ops->pending)
-               return ops->pending(dev, true);
-
-       return 1;
+       return _serial_tstc(sdev->priv);
 }
 
 static int serial_post_probe(struct udevice *dev)
index 82fbbd92e2b259586455484b635338adc5cdf72f..18e41b2302a2181ba6f38c53ecc71c682fb5cad0 100644 (file)
@@ -157,7 +157,6 @@ serial_initfunc(sh_serial_initialize);
 serial_initfunc(arm_dcc_initialize);
 serial_initfunc(mxs_auart_initialize);
 serial_initfunc(arc_serial_initialize);
-serial_initfunc(uniphier_serial_initialize);
 
 /**
  * serial_register() - Register serial driver with serial driver core
@@ -251,33 +250,32 @@ void serial_initialize(void)
        arm_dcc_initialize();
        mxs_auart_initialize();
        arc_serial_initialize();
-       uniphier_serial_initialize();
 
        serial_assign(default_serial_console()->name);
 }
 
-int serial_stub_start(struct stdio_dev *sdev)
+static int serial_stub_start(struct stdio_dev *sdev)
 {
        struct serial_device *dev = sdev->priv;
 
        return dev->start();
 }
 
-int serial_stub_stop(struct stdio_dev *sdev)
+static int serial_stub_stop(struct stdio_dev *sdev)
 {
        struct serial_device *dev = sdev->priv;
 
        return dev->stop();
 }
 
-void serial_stub_putc(struct stdio_dev *sdev, const char ch)
+static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
 {
        struct serial_device *dev = sdev->priv;
 
        dev->putc(ch);
 }
 
-void serial_stub_puts(struct stdio_dev *sdev, const char *str)
+static void serial_stub_puts(struct stdio_dev *sdev, const char *str)
 {
        struct serial_device *dev = sdev->priv;
 
diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c
new file mode 100644 (file)
index 0000000..5c6a76c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+
+static const struct udevice_id coreboot_serial_ids[] = {
+       { .compatible = "coreboot-uart" },
+       { }
+};
+
+static int coreboot_serial_ofdata_to_platdata(struct udevice *dev)
+{
+       struct ns16550_platdata *plat = dev_get_platdata(dev);
+       int ret;
+
+       ret = ns16550_serial_ofdata_to_platdata(dev);
+       if (ret)
+               return ret;
+       plat->clock = 1843200;
+
+       return 0;
+}
+U_BOOT_DRIVER(serial_ns16550) = {
+       .name   = "serial_coreboot",
+       .id     = UCLASS_SERIAL,
+       .of_match = coreboot_serial_ids,
+       .ofdata_to_platdata = coreboot_serial_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+       .priv_auto_alloc_size = sizeof(struct NS16550),
+       .probe = ns16550_serial_probe,
+       .ops    = &ns16550_serial_ops,
+};
index 313d560afce8635f3b1f29c3ea029173b69f8c40..d6cf1d874a60c72c747489849bf58cffc915e57c 100644 (file)
@@ -5,37 +5,15 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <watchdog.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
+#include <dm/platform_data/serial_mxc.h>
 #include <serial.h>
 #include <linux/compiler.h>
 
-#define __REG(x)     (*((volatile u32 *)(x)))
-
-#ifndef CONFIG_MXC_UART_BASE
-#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
-#endif
-
-#define UART_PHYS      CONFIG_MXC_UART_BASE
-
-/* Register definitions */
-#define URXD  0x0  /* Receiver Register */
-#define UTXD  0x40 /* Transmitter Register */
-#define UCR1  0x80 /* Control Register 1 */
-#define UCR2  0x84 /* Control Register 2 */
-#define UCR3  0x88 /* Control Register 3 */
-#define UCR4  0x8c /* Control Register 4 */
-#define UFCR  0x90 /* FIFO Control Register */
-#define USR1  0x94 /* Status Register 1 */
-#define USR2  0x98 /* Status Register 2 */
-#define UESC  0x9c /* Escape Character Register */
-#define UTIM  0xa0 /* Escape Timer Register */
-#define UBIR  0xa4 /* BRM Incremental Register */
-#define UBMR  0xa8 /* BRM Modulator Register */
-#define UBRC  0xac /* Baud Rate Count Register */
-#define UTS   0xb4 /* UART Test Register (mx31) */
-
 /* UART Control Register Bit Fields.*/
 #define  URXD_CHARRDY    (1<<15)
 #define  URXD_ERR        (1<<14)
 #define  UTS_RXFULL     (1<<3)  /* RxFIFO full */
 #define  UTS_SOFTRST    (1<<0)  /* Software reset */
 
+#ifndef CONFIG_DM_SERIAL
+
+#ifndef CONFIG_MXC_UART_BASE
+#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
+#endif
+
+#define UART_PHYS      CONFIG_MXC_UART_BASE
+
+#define __REG(x)     (*((volatile u32 *)(x)))
+
+/* Register definitions */
+#define URXD  0x0  /* Receiver Register */
+#define UTXD  0x40 /* Transmitter Register */
+#define UCR1  0x80 /* Control Register 1 */
+#define UCR2  0x84 /* Control Register 2 */
+#define UCR3  0x88 /* Control Register 3 */
+#define UCR4  0x8c /* Control Register 4 */
+#define UFCR  0x90 /* FIFO Control Register */
+#define USR1  0x94 /* Status Register 1 */
+#define USR2  0x98 /* Status Register 2 */
+#define UESC  0x9c /* Escape Character Register */
+#define UTIM  0xa0 /* Escape Timer Register */
+#define UBIR  0xa4 /* BRM Incremental Register */
+#define UBMR  0xa8 /* BRM Modulator Register */
+#define UBRC  0xac /* Baud Rate Count Register */
+#define UTS   0xb4 /* UART Test Register (mx31) */
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static void mxc_serial_setbrg(void)
@@ -222,3 +227,118 @@ __weak struct serial_device *default_serial_console(void)
 {
        return &mxc_serial_drv;
 }
+#endif
+
+#ifdef CONFIG_DM_SERIAL
+
+struct mxc_uart {
+       u32 rxd;
+       u32 spare0[15];
+
+       u32 txd;
+       u32 spare1[15];
+
+       u32 cr1;
+       u32 cr2;
+       u32 cr3;
+       u32 cr4;
+
+       u32 fcr;
+       u32 sr1;
+       u32 sr2;
+       u32 esc;
+
+       u32 tim;
+       u32 bir;
+       u32 bmr;
+       u32 brc;
+
+       u32 onems;
+       u32 ts;
+};
+
+int mxc_serial_setbrg(struct udevice *dev, int baudrate)
+{
+       struct mxc_serial_platdata *plat = dev->platdata;
+       struct mxc_uart *const uart = plat->reg;
+       u32 clk = imx_get_uartclk();
+
+       writel(4 << 7, &uart->fcr); /* divide input clock by 2 */
+       writel(0xf, &uart->bir);
+       writel(clk / (2 * baudrate), &uart->bmr);
+
+       writel(UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST,
+              &uart->cr2);
+       writel(UCR1_UARTEN, &uart->cr1);
+
+       return 0;
+}
+
+static int mxc_serial_probe(struct udevice *dev)
+{
+       struct mxc_serial_platdata *plat = dev->platdata;
+       struct mxc_uart *const uart = plat->reg;
+
+       writel(0, &uart->cr1);
+       writel(0, &uart->cr2);
+       while (!(readl(&uart->cr2) & UCR2_SRST));
+       writel(0x704 | UCR3_ADNIMP, &uart->cr3);
+       writel(0x8000, &uart->cr4);
+       writel(0x2b, &uart->esc);
+       writel(0, &uart->tim);
+       writel(0, &uart->ts);
+
+       return 0;
+}
+
+static int mxc_serial_getc(struct udevice *dev)
+{
+       struct mxc_serial_platdata *plat = dev->platdata;
+       struct mxc_uart *const uart = plat->reg;
+
+       if (readl(&uart->ts) & UTS_RXEMPTY)
+               return -EAGAIN;
+
+       return readl(&uart->rxd) & URXD_RX_DATA;
+}
+
+static int mxc_serial_putc(struct udevice *dev, const char ch)
+{
+       struct mxc_serial_platdata *plat = dev->platdata;
+       struct mxc_uart *const uart = plat->reg;
+
+       if (!(readl(&uart->ts) & UTS_TXEMPTY))
+               return -EAGAIN;
+
+       writel(ch, &uart->txd);
+
+       return 0;
+}
+
+static int mxc_serial_pending(struct udevice *dev, bool input)
+{
+       struct mxc_serial_platdata *plat = dev->platdata;
+       struct mxc_uart *const uart = plat->reg;
+       uint32_t sr2 = readl(&uart->sr2);
+
+       if (input)
+               return sr2 & USR2_RDR ? 1 : 0;
+       else
+               return sr2 & USR2_TXDC ? 0 : 1;
+}
+
+static const struct dm_serial_ops mxc_serial_ops = {
+       .putc = mxc_serial_putc,
+       .pending = mxc_serial_pending,
+       .getc = mxc_serial_getc,
+       .setbrg = mxc_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_mxc) = {
+       .name   = "serial_mxc",
+       .id     = UCLASS_SERIAL,
+       .probe = mxc_serial_probe,
+       .ops    = &mxc_serial_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
+#endif
index 632da4cf70bb93c15c2a84a93815b6b6078c06c4..799ef6a667d16a1d38427be6e642633848c9a9c4 100644 (file)
@@ -119,8 +119,7 @@ static NS16550_t serial_ports[6] = {
        .puts   = eserial##port##_puts,         \
 }
 
-void
-_serial_putc(const char c,const int port)
+static void _serial_putc(const char c, const int port)
 {
        if (c == '\n')
                NS16550_putc(PORT, '\r');
@@ -128,35 +127,29 @@ _serial_putc(const char c,const int port)
        NS16550_putc(PORT, c);
 }
 
-void
-_serial_putc_raw(const char c,const int port)
+static void _serial_putc_raw(const char c, const int port)
 {
        NS16550_putc(PORT, c);
 }
 
-void
-_serial_puts (const char *s,const int port)
+static void _serial_puts(const char *s, const int port)
 {
        while (*s) {
-               _serial_putc (*s++,port);
+               _serial_putc(*s++, port);
        }
 }
 
-
-int
-_serial_getc(const int port)
+static int _serial_getc(const int port)
 {
        return NS16550_getc(PORT);
 }
 
-int
-_serial_tstc(const int port)
+static int _serial_tstc(const int port)
 {
        return NS16550_tstc(PORT);
 }
 
-void
-_serial_setbrg (const int port)
+static void _serial_setbrg(const int port)
 {
        int clock_divisor;
 
diff --git a/drivers/serial/serial_omap.c b/drivers/serial/serial_omap.c
new file mode 100644 (file)
index 0000000..265fe00
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <ns16550.h>
+#include <serial.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_OF_CONTROL
+static const struct udevice_id omap_serial_ids[] = {
+       { .compatible = "ti,omap3-uart" },
+       { }
+};
+
+static int omap_serial_ofdata_to_platdata(struct udevice *dev)
+{
+       struct ns16550_platdata *plat = dev_get_platdata(dev);
+       int ret;
+
+       ret = ns16550_serial_ofdata_to_platdata(dev);
+       if (ret)
+               return ret;
+       plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                    "clock-frequency", -1);
+       plat->reg_shift = 2;
+
+       return 0;
+}
+#endif
+
+U_BOOT_DRIVER(serial_omap_ns16550) = {
+       .name   = "serial_omap",
+       .id     = UCLASS_SERIAL,
+       .of_match = of_match_ptr(omap_serial_ids),
+       .ofdata_to_platdata = of_match_ptr(omap_serial_ofdata_to_platdata),
+       .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+       .priv_auto_alloc_size = sizeof(struct NS16550),
+       .probe = ns16550_serial_probe,
+       .ops    = &ns16550_serial_ops,
+       .flags  = DM_FLAG_PRE_RELOC,
+};
index dfb610e1a9d553429d1462335a6550f6d31afe04..38dda910217652ecf167ad52bbc53af3559e2722 100644 (file)
 /* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <watchdog.h>
 #include <asm/io.h>
 #include <serial.h>
+#include <dm/platform_data/serial_pl01x.h>
 #include <linux/compiler.h>
-#include "serial_pl01x.h"
+#include "serial_pl01x_internal.h"
+
+#ifndef CONFIG_DM_SERIAL
 
-/*
- * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1
- * Integrator CP has two UARTs, use the first one, at 38400-8-N-1
- * Versatile PB has four UARTs.
- */
-#define CONSOLE_PORT CONFIG_CONS_INDEX
 static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS;
+static enum pl01x_type pl01x_type __attribute__ ((section(".data")));
+static struct pl01x_regs *base_regs __attribute__ ((section(".data")));
 #define NUM_PORTS (sizeof(port)/sizeof(port[0]))
 
-static void pl01x_putc (int portnum, char c);
-static int pl01x_getc (int portnum);
-static int pl01x_tstc (int portnum);
-unsigned int baudrate = CONFIG_BAUDRATE;
 DECLARE_GLOBAL_DATA_PTR;
+#endif
 
-static struct pl01x_regs *pl01x_get_regs(int portnum)
-{
-       return (struct pl01x_regs *) port[portnum];
-}
-
-#ifdef CONFIG_PL010_SERIAL
-
-static int pl01x_serial_init(void)
+static int pl01x_putc(struct pl01x_regs *regs, char c)
 {
-       struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
-       unsigned int divisor;
-
-       /* First, disable everything */
-       writel(0, &regs->pl010_cr);
+       /* Wait until there is space in the FIFO */
+       if (readl(&regs->fr) & UART_PL01x_FR_TXFF)
+               return -EAGAIN;
 
-       /* Set baud rate */
-       switch (baudrate) {
-       case 9600:
-               divisor = UART_PL010_BAUD_9600;
-               break;
+       /* Send the character */
+       writel(c, &regs->dr);
 
-       case 19200:
-               divisor = UART_PL010_BAUD_9600;
-               break;
+       return 0;
+}
 
-       case 38400:
-               divisor = UART_PL010_BAUD_38400;
-               break;
+static int pl01x_getc(struct pl01x_regs *regs)
+{
+       unsigned int data;
 
-       case 57600:
-               divisor = UART_PL010_BAUD_57600;
-               break;
+       /* Wait until there is data in the FIFO */
+       if (readl(&regs->fr) & UART_PL01x_FR_RXFE)
+               return -EAGAIN;
 
-       case 115200:
-               divisor = UART_PL010_BAUD_115200;
-               break;
+       data = readl(&regs->dr);
 
-       default:
-               divisor = UART_PL010_BAUD_38400;
+       /* Check for an error flag */
+       if (data & 0xFFFFFF00) {
+               /* Clear the error */
+               writel(0xFFFFFFFF, &regs->ecr);
+               return -1;
        }
 
-       writel((divisor & 0xf00) >> 8, &regs->pl010_lcrm);
-       writel(divisor & 0xff, &regs->pl010_lcrl);
-
-       /* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */
-       writel(UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN, &regs->pl010_lcrh);
-
-       /* Finally, enable the UART */
-       writel(UART_PL010_CR_UARTEN, &regs->pl010_cr);
-
-       return 0;
+       return (int) data;
 }
 
-#endif /* CONFIG_PL010_SERIAL */
-
-#ifdef CONFIG_PL011_SERIAL
+static int pl01x_tstc(struct pl01x_regs *regs)
+{
+       WATCHDOG_RESET();
+       return !(readl(&regs->fr) & UART_PL01x_FR_RXFE);
+}
 
-static int pl01x_serial_init(void)
+static int pl01x_generic_serial_init(struct pl01x_regs *regs,
+                                    enum pl01x_type type)
 {
-       struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
-       unsigned int temp;
-       unsigned int divider;
-       unsigned int remainder;
-       unsigned int fraction;
        unsigned int lcr;
 
 #ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT
-       /* Empty RX fifo if necessary */
-       if (readl(&regs->pl011_cr) & UART_PL011_CR_UARTEN) {
-               while (!(readl(&regs->fr) & UART_PL01x_FR_RXFE))
-                       readl(&regs->dr);
+       if (type == TYPE_PL011) {
+               /* Empty RX fifo if necessary */
+               if (readl(&regs->pl011_cr) & UART_PL011_CR_UARTEN) {
+                       while (!(readl(&regs->fr) & UART_PL01x_FR_RXFE))
+                               readl(&regs->dr);
+               }
        }
 #endif
 
        /* First, disable everything */
-       writel(0, &regs->pl011_cr);
-
-       /*
-        * Set baud rate
-        *
-        * IBRD = UART_CLK / (16 * BAUD_RATE)
-        * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE))
-        */
-       temp = 16 * baudrate;
-       divider = CONFIG_PL011_CLOCK / temp;
-       remainder = CONFIG_PL011_CLOCK % temp;
-       temp = (8 * remainder) / baudrate;
-       fraction = (temp >> 1) + (temp & 1);
-
-       writel(divider, &regs->pl011_ibrd);
-       writel(fraction, &regs->pl011_fbrd);
+       writel(0, &regs->pl010_cr);
 
        /* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */
        lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN;
        writel(lcr, &regs->pl011_lcrh);
 
+       switch (type) {
+       case TYPE_PL010:
+               break;
+       case TYPE_PL011: {
 #ifdef CONFIG_PL011_SERIAL_RLCR
-       {
                int i;
 
                /*
@@ -144,90 +109,151 @@ static int pl01x_serial_init(void)
                writel(lcr, &regs->pl011_rlcr);
                /* lcrh needs to be set again for change to be effective */
                writel(lcr, &regs->pl011_lcrh);
-       }
 #endif
-       /* Finally, enable the UART */
-       writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE |
-              UART_PL011_CR_RTS, &regs->pl011_cr);
+               break;
+       }
+       default:
+               return -EINVAL;
+       }
 
        return 0;
 }
 
-#endif /* CONFIG_PL011_SERIAL */
-
-static void pl01x_serial_putc(const char c)
+static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type,
+                               int clock, int baudrate)
 {
-       if (c == '\n')
-               pl01x_putc (CONSOLE_PORT, '\r');
+       switch (type) {
+       case TYPE_PL010: {
+               unsigned int divisor;
+
+               switch (baudrate) {
+               case 9600:
+                       divisor = UART_PL010_BAUD_9600;
+                       break;
+               case 19200:
+                       divisor = UART_PL010_BAUD_9600;
+                       break;
+               case 38400:
+                       divisor = UART_PL010_BAUD_38400;
+                       break;
+               case 57600:
+                       divisor = UART_PL010_BAUD_57600;
+                       break;
+               case 115200:
+                       divisor = UART_PL010_BAUD_115200;
+                       break;
+               default:
+                       divisor = UART_PL010_BAUD_38400;
+               }
+
+               writel((divisor & 0xf00) >> 8, &regs->pl010_lcrm);
+               writel(divisor & 0xff, &regs->pl010_lcrl);
+
+               /* Finally, enable the UART */
+               writel(UART_PL010_CR_UARTEN, &regs->pl010_cr);
+               break;
+       }
+       case TYPE_PL011: {
+               unsigned int temp;
+               unsigned int divider;
+               unsigned int remainder;
+               unsigned int fraction;
 
-       pl01x_putc (CONSOLE_PORT, c);
-}
+               /*
+               * Set baud rate
+               *
+               * IBRD = UART_CLK / (16 * BAUD_RATE)
+               * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
+               *               / (16 * BAUD_RATE))
+               */
+               temp = 16 * baudrate;
+               divider = clock / temp;
+               remainder = clock % temp;
+               temp = (8 * remainder) / baudrate;
+               fraction = (temp >> 1) + (temp & 1);
+
+               writel(divider, &regs->pl011_ibrd);
+               writel(fraction, &regs->pl011_fbrd);
+
+               /* Finally, enable the UART */
+               writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
+                      UART_PL011_CR_RXE | UART_PL011_CR_RTS, &regs->pl011_cr);
+               break;
+       }
+       default:
+               return -EINVAL;
+       }
 
-static int pl01x_serial_getc(void)
-{
-       return pl01x_getc (CONSOLE_PORT);
+       return 0;
 }
 
-static int pl01x_serial_tstc(void)
+#ifndef CONFIG_DM_SERIAL
+static void pl01x_serial_init_baud(int baudrate)
 {
-       return pl01x_tstc (CONSOLE_PORT);
+       int clock = 0;
+
+#if defined(CONFIG_PL010_SERIAL)
+       pl01x_type = TYPE_PL010;
+#elif defined(CONFIG_PL011_SERIAL)
+       pl01x_type = TYPE_PL011;
+       clock = CONFIG_PL011_CLOCK;
+#endif
+       base_regs = (struct pl01x_regs *)port[CONFIG_CONS_INDEX];
+
+       pl01x_generic_serial_init(base_regs, pl01x_type);
+       pl01x_generic_setbrg(base_regs, TYPE_PL010, clock, baudrate);
 }
 
-static void pl01x_serial_setbrg(void)
+/*
+ * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1
+ * Integrator CP has two UARTs, use the first one, at 38400-8-N-1
+ * Versatile PB has four UARTs.
+ */
+int pl01x_serial_init(void)
 {
-       struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT);
+       pl01x_serial_init_baud(CONFIG_BAUDRATE);
 
-       baudrate = gd->baudrate;
-       /*
-        * Flush FIFO and wait for non-busy before changing baudrate to avoid
-        * crap in console
-        */
-       while (!(readl(&regs->fr) & UART_PL01x_FR_TXFE))
-               WATCHDOG_RESET();
-       while (readl(&regs->fr) & UART_PL01x_FR_BUSY)
-               WATCHDOG_RESET();
-       serial_init();
+       return 0;
 }
 
-static void pl01x_putc (int portnum, char c)
+static void pl01x_serial_putc(const char c)
 {
-       struct pl01x_regs *regs = pl01x_get_regs(portnum);
-
-       /* Wait until there is space in the FIFO */
-       while (readl(&regs->fr) & UART_PL01x_FR_TXFF)
-               WATCHDOG_RESET();
+       if (c == '\n')
+               while (pl01x_putc(base_regs, '\r') == -EAGAIN);
 
-       /* Send the character */
-       writel(c, &regs->dr);
+       while (pl01x_putc(base_regs, c) == -EAGAIN);
 }
 
-static int pl01x_getc (int portnum)
+static int pl01x_serial_getc(void)
 {
-       struct pl01x_regs *regs = pl01x_get_regs(portnum);
-       unsigned int data;
+       while (1) {
+               int ch = pl01x_getc(base_regs);
 
-       /* Wait until there is data in the FIFO */
-       while (readl(&regs->fr) & UART_PL01x_FR_RXFE)
-               WATCHDOG_RESET();
-
-       data = readl(&regs->dr);
+               if (ch == -EAGAIN) {
+                       WATCHDOG_RESET();
+                       continue;
+               }
 
-       /* Check for an error flag */
-       if (data & 0xFFFFFF00) {
-               /* Clear the error */
-               writel(0xFFFFFFFF, &regs->ecr);
-               return -1;
+               return ch;
        }
-
-       return (int) data;
 }
 
-static int pl01x_tstc (int portnum)
+static int pl01x_serial_tstc(void)
 {
-       struct pl01x_regs *regs = pl01x_get_regs(portnum);
+       return pl01x_tstc(base_regs);
+}
 
-       WATCHDOG_RESET();
-       return !(readl(&regs->fr) & UART_PL01x_FR_RXFE);
+static void pl01x_serial_setbrg(void)
+{
+       /*
+        * Flush FIFO and wait for non-busy before changing baudrate to avoid
+        * crap in console
+        */
+       while (!(readl(&base_regs->fr) & UART_PL01x_FR_TXFE))
+               WATCHDOG_RESET();
+       while (readl(&base_regs->fr) & UART_PL01x_FR_BUSY)
+               WATCHDOG_RESET();
+       pl01x_serial_init_baud(gd->baudrate);
 }
 
 static struct serial_device pl01x_serial_drv = {
@@ -250,3 +276,74 @@ __weak struct serial_device *default_serial_console(void)
 {
        return &pl01x_serial_drv;
 }
+
+#endif /* nCONFIG_DM_SERIAL */
+
+#ifdef CONFIG_DM_SERIAL
+
+struct pl01x_priv {
+       struct pl01x_regs *regs;
+       enum pl01x_type type;
+};
+
+static int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
+{
+       struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
+       struct pl01x_priv *priv = dev_get_priv(dev);
+
+       pl01x_generic_setbrg(priv->regs, priv->type, plat->clock, baudrate);
+
+       return 0;
+}
+
+static int pl01x_serial_probe(struct udevice *dev)
+{
+       struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
+       struct pl01x_priv *priv = dev_get_priv(dev);
+
+       priv->regs = (struct pl01x_regs *)plat->base;
+       priv->type = plat->type;
+       return pl01x_generic_serial_init(priv->regs, priv->type);
+}
+
+static int pl01x_serial_getc(struct udevice *dev)
+{
+       struct pl01x_priv *priv = dev_get_priv(dev);
+
+       return pl01x_getc(priv->regs);
+}
+
+static int pl01x_serial_putc(struct udevice *dev, const char ch)
+{
+       struct pl01x_priv *priv = dev_get_priv(dev);
+
+       return pl01x_putc(priv->regs, ch);
+}
+
+static int pl01x_serial_pending(struct udevice *dev, bool input)
+{
+       struct pl01x_priv *priv = dev_get_priv(dev);
+       unsigned int fr = readl(&priv->regs->fr);
+
+       if (input)
+               return pl01x_tstc(priv->regs);
+       else
+               return fr & UART_PL01x_FR_TXFF ? 0 : 1;
+}
+
+static const struct dm_serial_ops pl01x_serial_ops = {
+       .putc = pl01x_serial_putc,
+       .pending = pl01x_serial_pending,
+       .getc = pl01x_serial_getc,
+       .setbrg = pl01x_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_pl01x) = {
+       .name   = "serial_pl01x",
+       .id     = UCLASS_SERIAL,
+       .probe = pl01x_serial_probe,
+       .ops    = &pl01x_serial_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
+
+#endif
index c07f4c9b4737f5a64ea59e1a570e77c9850e0f7f..7afc5044a8c70f77607a5e1d351b83b2681b012b 100644 (file)
@@ -69,7 +69,7 @@ DECLARE_GLOBAL_DATA_PTR;
 static int hwflow;
 #endif
 
-void _serial_setbrg(const int dev_index)
+static void _serial_setbrg(const int dev_index)
 {
        struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
        unsigned int reg = 0;
@@ -131,7 +131,7 @@ static int serial_init_dev(const int dev_index)
  * otherwise. When the function is succesfull, the character read is
  * written into its argument c.
  */
-int _serial_getc(const int dev_index)
+static int _serial_getc(const int dev_index)
 {
        struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
 
@@ -181,7 +181,7 @@ void enable_putc(void)
 /*
  * Output a single byte to the serial port.
  */
-void _serial_putc(const char c, const int dev_index)
+static void _serial_putc(const char c, const int dev_index)
 {
        struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
 #ifdef CONFIG_MODEM_SUPPORT
@@ -212,7 +212,7 @@ static inline void serial_putc_dev(unsigned int dev_index, const char c)
 /*
  * Test whether a character is in the RX buffer
  */
-int _serial_tstc(const int dev_index)
+static int _serial_tstc(const int dev_index)
 {
        struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
 
@@ -224,7 +224,7 @@ static inline int serial_tstc_dev(unsigned int dev_index)
        return _serial_tstc(dev_index);
 }
 
-void _serial_puts(const char *s, const int dev_index)
+static void _serial_puts(const char *s, const int dev_index)
 {
        while (*s) {
                _serial_putc(*s++, dev_index);
index 98c62b4c147ef185d8a9cabb0290be854a38b892..8469afdaae9da8d18e046218a354eb789b87ddd5 100644 (file)
@@ -9,6 +9,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <fdtdec.h>
 #include <linux/compiler.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define RX_FIFO_COUNT_MASK     0xff
-#define RX_FIFO_FULL_MASK      (1 << 8)
-#define TX_FIFO_FULL_MASK      (1 << 24)
+#define RX_FIFO_COUNT_SHIFT    0
+#define RX_FIFO_COUNT_MASK     (0xff << RX_FIFO_COUNT_SHIFT)
+#define RX_FIFO_FULL           (1 << 8)
+#define TX_FIFO_COUNT_SHIFT    16
+#define TX_FIFO_COUNT_MASK     (0xff << TX_FIFO_COUNT_SHIFT)
+#define TX_FIFO_FULL           (1 << 24)
 
 /* Information about a serial port */
-struct fdt_serial {
-       u32 base_addr;  /* address of registers in physical memory */
+struct s5p_serial_platdata {
+       struct s5p_uart *reg;  /* address of registers in physical memory */
        u8 port_id;     /* uart port number */
-       u8 enabled;     /* 1 if enabled, 0 if disabled */
-} config __attribute__ ((section(".data")));
-
-static inline struct s5p_uart *s5p_get_base_uart(int dev_index)
-{
-#ifdef CONFIG_OF_CONTROL
-       return (struct s5p_uart *)(config.base_addr);
-#else
-       u32 offset = dev_index * sizeof(struct s5p_uart);
-       return (struct s5p_uart *)(samsung_get_base_uart() + offset);
-#endif
-}
+};
 
 /*
  * The coefficient, used to calculate the baudrate on S5P UARTs is
@@ -65,23 +59,13 @@ static const int udivslot[] = {
        0xffdf,
 };
 
-static void serial_setbrg_dev(const int dev_index)
+int s5p_serial_setbrg(struct udevice *dev, int baudrate)
 {
-       struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
-       u32 uclk = get_uart_clk(dev_index);
-       u32 baudrate = gd->baudrate;
+       struct s5p_serial_platdata *plat = dev->platdata;
+       struct s5p_uart *const uart = plat->reg;
+       u32 uclk = get_uart_clk(plat->port_id);
        u32 val;
 
-#if defined(CONFIG_SILENT_CONSOLE) && \
-               defined(CONFIG_OF_CONTROL) && \
-               !defined(CONFIG_SPL_BUILD)
-       if (fdtdec_get_config_int(gd->fdt_blob, "silent_console", 0))
-               gd->flags |= GD_FLG_SILENT;
-#endif
-
-       if (!config.enabled)
-               return;
-
        val = uclk / baudrate;
 
        writel(val / 16 - 1, &uart->ubrdiv);
@@ -90,15 +74,14 @@ static void serial_setbrg_dev(const int dev_index)
                writew(udivslot[val % 16], &uart->rest.slot);
        else
                writeb(val % 16, &uart->rest.value);
+
+       return 0;
 }
 
-/*
- * Initialise the serial port with the given baudrate. The settings
- * are always 8 data bits, no parity, 1 stop bit, no start bits.
- */
-static int serial_init_dev(const int dev_index)
+static int s5p_serial_probe(struct udevice *dev)
 {
-       struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
+       struct s5p_serial_platdata *plat = dev->platdata;
+       struct s5p_uart *const uart = plat->reg;
 
        /* enable FIFOs, auto clear Rx FIFO */
        writel(0x3, &uart->ufcon);
@@ -108,14 +91,11 @@ static int serial_init_dev(const int dev_index)
        /* No interrupts, no DMA, pure polling */
        writel(0x245, &uart->ucon);
 
-       serial_setbrg_dev(dev_index);
-
        return 0;
 }
 
-static int serial_err_check(const int dev_index, int op)
+static int serial_err_check(const struct s5p_uart *const uart, int op)
 {
-       struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
        unsigned int mask;
 
        /*
@@ -133,169 +113,78 @@ static int serial_err_check(const int dev_index, int op)
        return readl(&uart->uerstat) & mask;
 }
 
-/*
- * Read a single byte from the serial port. Returns 1 on success, 0
- * otherwise. When the function is succesfull, the character read is
- * written into its argument c.
- */
-static int serial_getc_dev(const int dev_index)
+static int s5p_serial_getc(struct udevice *dev)
 {
-       struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
-
-       if (!config.enabled)
-               return 0;
+       struct s5p_serial_platdata *plat = dev->platdata;
+       struct s5p_uart *const uart = plat->reg;
 
-       /* wait for character to arrive */
-       while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
-                                        RX_FIFO_FULL_MASK))) {
-               if (serial_err_check(dev_index, 0))
-                       return 0;
-       }
+       if (!(readl(&uart->ufstat) & RX_FIFO_COUNT_MASK))
+               return -EAGAIN;
 
+       serial_err_check(uart, 0);
        return (int)(readb(&uart->urxh) & 0xff);
 }
 
-/*
- * Output a single byte to the serial port.
- */
-static void serial_putc_dev(const char c, const int dev_index)
+static int s5p_serial_putc(struct udevice *dev, const char ch)
 {
-       struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
-
-       if (!config.enabled)
-               return;
-
-       /* wait for room in the tx FIFO */
-       while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
-               if (serial_err_check(dev_index, 1))
-                       return;
-       }
+       struct s5p_serial_platdata *plat = dev->platdata;
+       struct s5p_uart *const uart = plat->reg;
 
-       writeb(c, &uart->utxh);
+       if (readl(&uart->ufstat) & TX_FIFO_FULL)
+               return -EAGAIN;
 
-       /* If \n, also do \r */
-       if (c == '\n')
-               serial_putc('\r');
-}
-
-/*
- * Test whether a character is in the RX buffer
- */
-static int serial_tstc_dev(const int dev_index)
-{
-       struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
+       writeb(ch, &uart->utxh);
+       serial_err_check(uart, 1);
 
-       if (!config.enabled)
-               return 0;
-
-       return (int)(readl(&uart->utrstat) & 0x1);
+       return 0;
 }
 
-static void serial_puts_dev(const char *s, const int dev_index)
+static int s5p_serial_pending(struct udevice *dev, bool input)
 {
-       while (*s)
-               serial_putc_dev(*s++, dev_index);
-}
+       struct s5p_serial_platdata *plat = dev->platdata;
+       struct s5p_uart *const uart = plat->reg;
+       uint32_t ufstat = readl(&uart->ufstat);
 
-/* Multi serial device functions */
-#define DECLARE_S5P_SERIAL_FUNCTIONS(port) \
-static int s5p_serial##port##_init(void) { return serial_init_dev(port); } \
-static void s5p_serial##port##_setbrg(void) { serial_setbrg_dev(port); } \
-static int s5p_serial##port##_getc(void) { return serial_getc_dev(port); } \
-static int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \
-static void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \
-static void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); }
-
-#define INIT_S5P_SERIAL_STRUCTURE(port, __name) {      \
-       .name   = __name,                               \
-       .start  = s5p_serial##port##_init,              \
-       .stop   = NULL,                                 \
-       .setbrg = s5p_serial##port##_setbrg,            \
-       .getc   = s5p_serial##port##_getc,              \
-       .tstc   = s5p_serial##port##_tstc,              \
-       .putc   = s5p_serial##port##_putc,              \
-       .puts   = s5p_serial##port##_puts,              \
+       if (input)
+               return (ufstat & RX_FIFO_COUNT_MASK) >> RX_FIFO_COUNT_SHIFT;
+       else
+               return (ufstat & TX_FIFO_COUNT_MASK) >> TX_FIFO_COUNT_SHIFT;
 }
 
-DECLARE_S5P_SERIAL_FUNCTIONS(0);
-struct serial_device s5p_serial0_device =
-       INIT_S5P_SERIAL_STRUCTURE(0, "s5pser0");
-DECLARE_S5P_SERIAL_FUNCTIONS(1);
-struct serial_device s5p_serial1_device =
-       INIT_S5P_SERIAL_STRUCTURE(1, "s5pser1");
-DECLARE_S5P_SERIAL_FUNCTIONS(2);
-struct serial_device s5p_serial2_device =
-       INIT_S5P_SERIAL_STRUCTURE(2, "s5pser2");
-DECLARE_S5P_SERIAL_FUNCTIONS(3);
-struct serial_device s5p_serial3_device =
-       INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3");
-
-#ifdef CONFIG_OF_CONTROL
-int fdtdec_decode_console(int *index, struct fdt_serial *uart)
+static int s5p_serial_ofdata_to_platdata(struct udevice *dev)
 {
-       const void *blob = gd->fdt_blob;
-       int node;
+       struct s5p_serial_platdata *plat = dev->platdata;
+       fdt_addr_t addr;
 
-       node = fdt_path_offset(blob, "console");
-       if (node < 0)
-               return node;
+       addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
+       if (addr == FDT_ADDR_T_NONE)
+               return -EINVAL;
 
-       uart->base_addr = fdtdec_get_addr(blob, node, "reg");
-       if (uart->base_addr == FDT_ADDR_T_NONE)
-               return -FDT_ERR_NOTFOUND;
-
-       uart->port_id = fdtdec_get_int(blob, node, "id", -1);
-       uart->enabled = fdtdec_get_is_enabled(blob, node);
+       plat->reg = (struct s5p_uart *)addr;
+       plat->port_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "id", -1);
 
        return 0;
 }
-#endif
 
-__weak struct serial_device *default_serial_console(void)
-{
-#ifdef CONFIG_OF_CONTROL
-       int index = 0;
-
-       if ((!config.base_addr) && (fdtdec_decode_console(&index, &config))) {
-               debug("Cannot decode default console node\n");
-               return NULL;
-       }
-
-       switch (config.port_id) {
-       case 0:
-               return &s5p_serial0_device;
-       case 1:
-               return &s5p_serial1_device;
-       case 2:
-               return &s5p_serial2_device;
-       case 3:
-               return &s5p_serial3_device;
-       default:
-               debug("Unknown config.port_id: %d", config.port_id);
-               break;
-       }
-
-       return NULL;
-#else
-       config.enabled = 1;
-#if defined(CONFIG_SERIAL0)
-       return &s5p_serial0_device;
-#elif defined(CONFIG_SERIAL1)
-       return &s5p_serial1_device;
-#elif defined(CONFIG_SERIAL2)
-       return &s5p_serial2_device;
-#elif defined(CONFIG_SERIAL3)
-       return &s5p_serial3_device;
-#else
-#error "CONFIG_SERIAL? missing."
-#endif
-#endif
-}
+static const struct dm_serial_ops s5p_serial_ops = {
+       .putc = s5p_serial_putc,
+       .pending = s5p_serial_pending,
+       .getc = s5p_serial_getc,
+       .setbrg = s5p_serial_setbrg,
+};
 
-void s5p_serial_initialize(void)
-{
-       serial_register(&s5p_serial0_device);
-       serial_register(&s5p_serial1_device);
-       serial_register(&s5p_serial2_device);
-       serial_register(&s5p_serial3_device);
-}
+static const struct udevice_id s5p_serial_ids[] = {
+       { .compatible = "samsung,exynos4210-uart" },
+       { }
+};
+
+U_BOOT_DRIVER(serial_s5p) = {
+       .name   = "serial_s5p",
+       .id     = UCLASS_SERIAL,
+       .of_match = s5p_serial_ids,
+       .ofdata_to_platdata = s5p_serial_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct s5p_serial_platdata),
+       .probe = s5p_serial_probe,
+       .ops    = &s5p_serial_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
index 144a925394513d38b1677030cb97fcc5f96d84cb..7c1f27137615faa4a56f0b40f567c49a0ff73378 100644 (file)
@@ -122,7 +122,7 @@ static void handle_error(void)
        sci_out(&sh_sci, SCLSR, 0x00);
 }
 
-void serial_raw_putc(const char c)
+static void serial_raw_putc(const char c)
 {
        while (1) {
                /* Tx fifo is empty */
@@ -152,7 +152,7 @@ static int sh_serial_tstc(void)
 }
 
 
-int serial_getc_check(void)
+static int serial_getc_check(void)
 {
        unsigned short status;
 
index f8c9d921e283028c5fe199efa7b081bbfc08d09f..9114b3ed6002a1a0d9e3c6303ad07993060b07f9 100644 (file)
@@ -2,14 +2,14 @@
  * Copyright (C) 2012-2014 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
- * Based on serial_ns16550.c
- * (C) Copyright 2000
- * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
- *
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <dm/device.h>
+#include <dm/platform_data/serial-uniphier.h>
 #include <serial.h>
 
 #define UART_REG(x)                                    \
@@ -48,157 +48,104 @@ struct uniphier_serial {
 #define UART_LSR_DR    0x01            /* Data ready */
 #define UART_LSR_THRE  0x20            /* Xmit holding register empty */
 
-DECLARE_GLOBAL_DATA_PTR;
+struct uniphier_serial_private_data {
+       struct uniphier_serial __iomem *membase;
+};
+
+#define uniphier_serial_port(dev)      \
+       ((struct uniphier_serial_private_data *)dev_get_priv(dev))->membase
 
-static void uniphier_serial_init(struct uniphier_serial *port)
+int uniphier_serial_setbrg(struct udevice *dev, int baudrate)
 {
+       struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
+       struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
        const unsigned int mode_x_div = 16;
        unsigned int divisor;
 
        writeb(UART_LCR_WLS_8, &port->lcr);
 
-       divisor = DIV_ROUND_CLOSEST(CONFIG_SYS_UNIPHIER_UART_CLK,
-                                               mode_x_div * gd->baudrate);
+       divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate);
 
        writew(divisor, &port->dlr);
-}
 
-static void uniphier_serial_setbrg(struct uniphier_serial *port)
-{
-       uniphier_serial_init(port);
+       return 0;
 }
 
-static int uniphier_serial_tstc(struct uniphier_serial *port)
+static int uniphier_serial_getc(struct udevice *dev)
 {
-       return (readb(&port->lsr) & UART_LSR_DR) != 0;
-}
+       struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
 
-static int uniphier_serial_getc(struct uniphier_serial *port)
-{
-       while (!uniphier_serial_tstc(port))
-               ;
+       if (!(readb(&port->lsr) & UART_LSR_DR))
+               return -EAGAIN;
 
        return readb(&port->rbr);
 }
 
-static void uniphier_serial_putc(struct uniphier_serial *port, const char c)
+static int uniphier_serial_putc(struct udevice *dev, const char c)
 {
-       if (c == '\n')
-               uniphier_serial_putc(port, '\r');
+       struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
 
-       while (!(readb(&port->lsr) & UART_LSR_THRE))
-               ;
+       if (!(readb(&port->lsr) & UART_LSR_THRE))
+               return -EAGAIN;
 
        writeb(c, &port->thr);
+
+       return 0;
 }
 
-static struct uniphier_serial *serial_ports[4] = {
-#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE0
-       (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE0,
-#else
-       NULL,
-#endif
-#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE1
-       (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE1,
-#else
-       NULL,
-#endif
-#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE2
-       (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE2,
-#else
-       NULL,
-#endif
-#ifdef CONFIG_SYS_UNIPHIER_SERIAL_BASE3
-       (struct uniphier_serial *)CONFIG_SYS_UNIPHIER_SERIAL_BASE3,
-#else
-       NULL,
-#endif
-};
+int uniphier_serial_probe(struct udevice *dev)
+{
+       struct uniphier_serial_private_data *priv = dev_get_priv(dev);
+       struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
 
-/* Multi serial device functions */
-#define DECLARE_ESERIAL_FUNCTIONS(port) \
-       static int  eserial##port##_init(void) \
-       { \
-               uniphier_serial_init(serial_ports[port]); \
-               return 0 ; \
-       } \
-       static void eserial##port##_setbrg(void) \
-       { \
-               uniphier_serial_setbrg(serial_ports[port]); \
-       } \
-       static int  eserial##port##_getc(void) \
-       { \
-               return uniphier_serial_getc(serial_ports[port]); \
-       } \
-       static int  eserial##port##_tstc(void) \
-       { \
-               return uniphier_serial_tstc(serial_ports[port]); \
-       } \
-       static void eserial##port##_putc(const char c) \
-       { \
-               uniphier_serial_putc(serial_ports[port], c); \
-       }
-
-/* Serial device descriptor */
-#define INIT_ESERIAL_STRUCTURE(port, __name) { \
-       .name   = __name,                       \
-       .start  = eserial##port##_init,         \
-       .stop   = NULL,                         \
-       .setbrg = eserial##port##_setbrg,       \
-       .getc   = eserial##port##_getc,         \
-       .tstc   = eserial##port##_tstc,         \
-       .putc   = eserial##port##_putc,         \
-       .puts   = default_serial_puts,          \
-}
+       priv->membase = map_sysmem(plat->base, sizeof(struct uniphier_serial));
 
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
-DECLARE_ESERIAL_FUNCTIONS(0);
-struct serial_device uniphier_serial0_device =
-       INIT_ESERIAL_STRUCTURE(0, "ttyS0");
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
-DECLARE_ESERIAL_FUNCTIONS(1);
-struct serial_device uniphier_serial1_device =
-       INIT_ESERIAL_STRUCTURE(1, "ttyS1");
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
-DECLARE_ESERIAL_FUNCTIONS(2);
-struct serial_device uniphier_serial2_device =
-       INIT_ESERIAL_STRUCTURE(2, "ttyS2");
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
-DECLARE_ESERIAL_FUNCTIONS(3);
-struct serial_device uniphier_serial3_device =
-       INIT_ESERIAL_STRUCTURE(3, "ttyS3");
-#endif
+       if (!priv->membase)
+               return -ENOMEM;
 
-__weak struct serial_device *default_serial_console(void)
+       return 0;
+}
+
+int uniphier_serial_remove(struct udevice *dev)
 {
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
-       return &uniphier_serial0_device;
-#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
-       return &uniphier_serial1_device;
-#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
-       return &uniphier_serial2_device;
-#elif defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
-       return &uniphier_serial3_device;
-#else
-#error "No uniphier serial ports configured."
-#endif
+       unmap_sysmem(uniphier_serial_port(dev));
+
+       return 0;
 }
 
-void uniphier_serial_initialize(void)
+#ifdef CONFIG_OF_CONTROL
+static const struct udevice_id uniphier_uart_of_match = {
+       { .compatible = "panasonic,uniphier-uart"},
+       {},
+};
+
+static int uniphier_serial_ofdata_to_platdata(struct udevice *dev)
 {
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE0)
-       serial_register(&uniphier_serial0_device);
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE1)
-       serial_register(&uniphier_serial1_device);
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE2)
-       serial_register(&uniphier_serial2_device);
-#endif
-#if defined(CONFIG_SYS_UNIPHIER_SERIAL_BASE3)
-       serial_register(&uniphier_serial3_device);
-#endif
+       /*
+        * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com)
+        *
+        * Implement conversion code from DTB to platform data
+        * when supporting CONFIG_OF_CONTROL on UniPhir platform.
+        */
 }
+#endif
+
+static const struct dm_serial_ops uniphier_serial_ops = {
+       .setbrg = uniphier_serial_setbrg,
+       .getc = uniphier_serial_getc,
+       .putc = uniphier_serial_putc,
+};
+
+U_BOOT_DRIVER(uniphier_serial) = {
+       .name = DRIVER_NAME,
+       .id = UCLASS_SERIAL,
+       .of_match = of_match_ptr(uniphier_uart_of_match),
+       .ofdata_to_platdata = of_match_ptr(uniphier_serial_ofdata_to_platdata),
+       .probe = uniphier_serial_probe,
+       .remove = uniphier_serial_remove,
+       .priv_auto_alloc_size = sizeof(struct uniphier_serial_private_data),
+       .platdata_auto_alloc_size =
+                               sizeof(struct uniphier_serial_platform_data),
+       .ops = &uniphier_serial_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e1678e63e6adf976e4514978a3d2e1a9b6634c42 100644 (file)
@@ -0,0 +1,6 @@
+config DM_SPI
+       bool "Enable Driver Model for SPI drivers"
+       depends on DM
+       help
+         If you want to use driver model for SPI drivers, say Y.
+         To use legacy SPI drivers, say N.
index f02c35a52c0cd5100804342ca0e05a915151fd7d..eabbf27d4d0449cf0ed93d3983479cb629fd1108 100644 (file)
@@ -6,7 +6,14 @@
 #
 
 # There are many options which enable SPI, so make this library available
+ifdef CONFIG_DM_SPI
+obj-y += spi-uclass.o
+obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
+obj-$(CONFIG_SOFT_SPI) += soft_spi.o
+else
 obj-y += spi.o
+obj-$(CONFIG_SOFT_SPI) += soft_spi_legacy.o
+endif
 
 obj-$(CONFIG_EP93XX_SPI) += ep93xx_spi.o
 obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
@@ -30,11 +37,9 @@ obj-$(CONFIG_MXS_SPI) += mxs_spi.o
 obj-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
 obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
-obj-$(CONFIG_SOFT_SPI) += soft_spi.o
 obj-$(CONFIG_SH_SPI) += sh_spi.o
 obj-$(CONFIG_SH_QSPI) += sh_qspi.o
 obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
-obj-$(CONFIG_FDT_SPI) += fdt_spi.o
 obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
 obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
 obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
index 2969184ee877360da2a170b9f2ddb12722ffb08a..f078973531c1d960e5635a485e50c42170b45d80 100644 (file)
@@ -6,6 +6,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <malloc.h>
 #include <spi.h>
 #include <fdtdec.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/* Information about each SPI controller */
-struct spi_bus {
+struct exynos_spi_platdata {
        enum periph_id periph_id;
        s32 frequency;          /* Default clock frequency, -1 for none */
        struct exynos_spi *regs;
-       int inited;             /* 1 if this bus is ready for use */
-       int node;
        uint deactivate_delay_us;       /* Delay to wait after deactivate */
 };
 
-/* A list of spi buses that we know about */
-static struct spi_bus spi_bus[EXYNOS5_SPI_NUM_CONTROLLERS];
-static unsigned int bus_count;
-
-struct exynos_spi_slave {
-       struct spi_slave slave;
+struct exynos_spi_priv {
        struct exynos_spi *regs;
        unsigned int freq;              /* Default frequency */
        unsigned int mode;
        enum periph_id periph_id;       /* Peripheral ID for this device */
        unsigned int fifo_size;
        int skip_preamble;
-       struct spi_bus *bus;            /* Pointer to our SPI bus info */
        ulong last_transaction_us;      /* Time of last transaction end */
 };
 
-static struct spi_bus *spi_get_bus(unsigned dev_index)
-{
-       if (dev_index < bus_count)
-               return &spi_bus[dev_index];
-       debug("%s: invalid bus %d", __func__, dev_index);
-
-       return NULL;
-}
-
-static inline struct exynos_spi_slave *to_exynos_spi(struct spi_slave *slave)
-{
-       return container_of(slave, struct exynos_spi_slave, slave);
-}
-
-/**
- * Setup the driver private data
- *
- * @param bus          ID of the bus that the slave is attached to
- * @param cs           ID of the chip select connected to the slave
- * @param max_hz       Required spi frequency
- * @param mode         Required spi mode (clk polarity, clk phase and
- *                     master or slave)
- * @return new device or NULL
- */
-struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
-                       unsigned int max_hz, unsigned int mode)
-{
-       struct exynos_spi_slave *spi_slave;
-       struct spi_bus *bus;
-
-       if (!spi_cs_is_valid(busnum, cs)) {
-               debug("%s: Invalid bus/chip select %d, %d\n", __func__,
-                     busnum, cs);
-               return NULL;
-       }
-
-       spi_slave = spi_alloc_slave(struct exynos_spi_slave, busnum, cs);
-       if (!spi_slave) {
-               debug("%s: Could not allocate spi_slave\n", __func__);
-               return NULL;
-       }
-
-       bus = &spi_bus[busnum];
-       spi_slave->bus = bus;
-       spi_slave->regs = bus->regs;
-       spi_slave->mode = mode;
-       spi_slave->periph_id = bus->periph_id;
-       if (bus->periph_id == PERIPH_ID_SPI1 ||
-           bus->periph_id == PERIPH_ID_SPI2)
-               spi_slave->fifo_size = 64;
-       else
-               spi_slave->fifo_size = 256;
-
-       spi_slave->skip_preamble = 0;
-       spi_slave->last_transaction_us = timer_get_us();
-
-       spi_slave->freq = bus->frequency;
-       if (max_hz)
-               spi_slave->freq = min(max_hz, spi_slave->freq);
-
-       return &spi_slave->slave;
-}
-
-/**
- * Free spi controller
- *
- * @param slave        Pointer to spi_slave to which controller has to
- *             communicate with
- */
-void spi_free_slave(struct spi_slave *slave)
-{
-       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
-
-       free(spi_slave);
-}
-
 /**
  * Flush spi tx, rx fifos and reset the SPI controller
  *
- * @param slave        Pointer to spi_slave to which controller has to
- *             communicate with
+ * @param regs Pointer to SPI registers
  */
-static void spi_flush_fifo(struct spi_slave *slave)
+static void spi_flush_fifo(struct exynos_spi *regs)
 {
-       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
-       struct exynos_spi *regs = spi_slave->regs;
-
        clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
        clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
        setbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
 }
 
-/**
- * Initialize the spi base registers, set the required clock frequency and
- * initialize the gpios
- *
- * @param slave        Pointer to spi_slave to which controller has to
- *             communicate with
- * @return zero on success else a negative value
- */
-int spi_claim_bus(struct spi_slave *slave)
-{
-       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
-       struct exynos_spi *regs = spi_slave->regs;
-       u32 reg = 0;
-       int ret;
-
-       ret = set_spi_clk(spi_slave->periph_id,
-                                       spi_slave->freq);
-       if (ret < 0) {
-               debug("%s: Failed to setup spi clock\n", __func__);
-               return ret;
-       }
-
-       exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
-
-       spi_flush_fifo(slave);
-
-       reg = readl(&regs->ch_cfg);
-       reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
-
-       if (spi_slave->mode & SPI_CPHA)
-               reg |= SPI_CH_CPHA_B;
-
-       if (spi_slave->mode & SPI_CPOL)
-               reg |= SPI_CH_CPOL_L;
-
-       writel(reg, &regs->ch_cfg);
-       writel(SPI_FB_DELAY_180, &regs->fb_clk);
-
-       return 0;
-}
-
-/**
- * Reset the spi H/W and flush the tx and rx fifos
- *
- * @param slave        Pointer to spi_slave to which controller has to
- *             communicate with
- */
-void spi_release_bus(struct spi_slave *slave)
-{
-       spi_flush_fifo(slave);
-}
-
 static void spi_get_fifo_levels(struct exynos_spi *regs,
        int *rx_lvl, int *tx_lvl)
 {
@@ -208,6 +69,8 @@ static void spi_get_fifo_levels(struct exynos_spi *regs,
  */
 static void spi_request_bytes(struct exynos_spi *regs, int count, int step)
 {
+       debug("%s: regs=%p, count=%d, step=%d\n", __func__, regs, count, step);
+
        /* For word address we need to swap bytes */
        if (step == 4) {
                setbits_le32(&regs->mode_cfg,
@@ -230,10 +93,10 @@ static void spi_request_bytes(struct exynos_spi *regs, int count, int step)
        writel(count | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
 }
 
-static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
+static int spi_rx_tx(struct exynos_spi_priv *priv, int todo,
                        void **dinp, void const **doutp, unsigned long flags)
 {
-       struct exynos_spi *regs = spi_slave->regs;
+       struct exynos_spi *regs = priv->regs;
        uchar *rxp = *dinp;
        const uchar *txp = *doutp;
        int rx_lvl, tx_lvl;
@@ -245,8 +108,8 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
 
        out_bytes = in_bytes = todo;
 
-       stopping = spi_slave->skip_preamble && (flags & SPI_XFER_END) &&
-                                       !(spi_slave->mode & SPI_SLAVE);
+       stopping = priv->skip_preamble && (flags & SPI_XFER_END) &&
+                                       !(priv->mode & SPI_SLAVE);
 
        /*
         * Try to transfer words if we can. This helps read performance at
@@ -254,7 +117,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
         */
        step = 1;
        if (!((todo | (uintptr_t)rxp | (uintptr_t)txp) & 3) &&
-           !spi_slave->skip_preamble)
+           !priv->skip_preamble)
                step = 4;
 
        /*
@@ -279,7 +142,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
                 * Don't completely fill the txfifo, since we don't want our
                 * rxfifo to overflow, and it may already contain data.
                 */
-               while (tx_lvl < spi_slave->fifo_size/2 && out_bytes) {
+               while (tx_lvl < priv->fifo_size/2 && out_bytes) {
                        if (!txp)
                                temp = -1;
                        else if (step == 4)
@@ -295,9 +158,9 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
                if (rx_lvl >= step) {
                        while (rx_lvl >= step) {
                                temp = readl(&regs->rx_data);
-                               if (spi_slave->skip_preamble) {
+                               if (priv->skip_preamble) {
                                        if (temp == SPI_PREAMBLE_END_BYTE) {
-                                               spi_slave->skip_preamble = 0;
+                                               priv->skip_preamble = 0;
                                                stopping = 0;
                                        }
                                } else {
@@ -326,7 +189,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
                        txp = NULL;
                        spi_request_bytes(regs, toread, step);
                }
-               if (spi_slave->skip_preamble && get_timer(start) > 100) {
+               if (priv->skip_preamble && get_timer(start) > 100) {
                        printf("SPI timeout: in_bytes=%d, out_bytes=%d, ",
                               in_bytes, out_bytes);
                        return -1;
@@ -339,95 +202,30 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
        return 0;
 }
 
-/**
- * Transfer and receive data
- *
- * @param slave                Pointer to spi_slave to which controller has to
- *                     communicate with
- * @param bitlen       No of bits to tranfer or receive
- * @param dout         Pointer to transfer buffer
- * @param din          Pointer to receive buffer
- * @param flags                Flags for transfer begin and end
- * @return zero on success else a negative value
- */
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-            void *din, unsigned long flags)
-{
-       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
-       int upto, todo;
-       int bytelen;
-       int ret = 0;
-
-       /* spi core configured to do 8 bit transfers */
-       if (bitlen % 8) {
-               debug("Non byte aligned SPI transfer.\n");
-               return -1;
-       }
-
-       /* Start the transaction, if necessary. */
-       if ((flags & SPI_XFER_BEGIN))
-               spi_cs_activate(slave);
-
-       /*
-        * Exynos SPI limits each transfer to 65535 transfers. To keep
-        * things simple, allow a maximum of 65532 bytes. We could allow
-        * more in word mode, but the performance difference is small.
-        */
-       bytelen =  bitlen / 8;
-       for (upto = 0; !ret && upto < bytelen; upto += todo) {
-               todo = min(bytelen - upto, (1 << 16) - 4);
-               ret = spi_rx_tx(spi_slave, todo, &din, &dout, flags);
-               if (ret)
-                       break;
-       }
-
-       /* Stop the transaction, if necessary. */
-       if ((flags & SPI_XFER_END) && !(spi_slave->mode & SPI_SLAVE)) {
-               spi_cs_deactivate(slave);
-               if (spi_slave->skip_preamble) {
-                       assert(!spi_slave->skip_preamble);
-                       debug("Failed to complete premable transaction\n");
-                       ret = -1;
-               }
-       }
-
-       return ret;
-}
-
-/**
- * Validates the bus and chip select numbers
- *
- * @param bus  ID of the bus that the slave is attached to
- * @param cs   ID of the chip select connected to the slave
- * @return one on success else zero
- */
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-       return spi_get_bus(bus) && cs == 0;
-}
-
 /**
  * Activate the CS by driving it LOW
  *
  * @param slave        Pointer to spi_slave to which controller has to
  *             communicate with
  */
-void spi_cs_activate(struct spi_slave *slave)
+static void spi_cs_activate(struct udevice *dev)
 {
-       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+       struct udevice *bus = dev->parent;
+       struct exynos_spi_platdata *pdata = dev_get_platdata(bus);
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
 
        /* If it's too soon to do another transaction, wait */
-       if (spi_slave->bus->deactivate_delay_us &&
-           spi_slave->last_transaction_us) {
+       if (pdata->deactivate_delay_us &&
+           priv->last_transaction_us) {
                ulong delay_us;         /* The delay completed so far */
-               delay_us = timer_get_us() - spi_slave->last_transaction_us;
-               if (delay_us < spi_slave->bus->deactivate_delay_us)
-                       udelay(spi_slave->bus->deactivate_delay_us - delay_us);
+               delay_us = timer_get_us() - priv->last_transaction_us;
+               if (delay_us < pdata->deactivate_delay_us)
+                       udelay(pdata->deactivate_delay_us - delay_us);
        }
 
-       clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
-       debug("Activate CS, bus %d\n", spi_slave->slave.bus);
-       spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
+       clrbits_le32(&priv->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+       debug("Activate CS, bus '%s'\n", bus->name);
+       priv->skip_preamble = priv->mode & SPI_PREAMBLE;
 }
 
 /**
@@ -436,148 +234,197 @@ void spi_cs_activate(struct spi_slave *slave)
  * @param slave        Pointer to spi_slave to which controller has to
  *             communicate with
  */
-void spi_cs_deactivate(struct spi_slave *slave)
+static void spi_cs_deactivate(struct udevice *dev)
 {
-       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+       struct udevice *bus = dev->parent;
+       struct exynos_spi_platdata *pdata = dev_get_platdata(bus);
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
 
-       setbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+       setbits_le32(&priv->regs->cs_reg, SPI_SLAVE_SIG_INACT);
 
        /* Remember time of this transaction so we can honour the bus delay */
-       if (spi_slave->bus->deactivate_delay_us)
-               spi_slave->last_transaction_us = timer_get_us();
+       if (pdata->deactivate_delay_us)
+               priv->last_transaction_us = timer_get_us();
 
-       debug("Deactivate CS, bus %d\n", spi_slave->slave.bus);
+       debug("Deactivate CS, bus '%s'\n", bus->name);
 }
 
-static inline struct exynos_spi *get_spi_base(int dev_index)
+static int exynos_spi_ofdata_to_platdata(struct udevice *bus)
 {
-       if (dev_index < 3)
-               return (struct exynos_spi *)samsung_get_base_spi() + dev_index;
-       else
-               return (struct exynos_spi *)samsung_get_base_spi_isp() +
-                                       (dev_index - 3);
-}
+       struct exynos_spi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
 
-/*
- * Read the SPI config from the device tree node.
- *
- * @param blob  FDT blob to read from
- * @param node  Node offset to read from
- * @param bus   SPI bus structure to fill with information
- * @return 0 if ok, or -FDT_ERR_NOTFOUND if something was missing
- */
-#ifdef CONFIG_OF_CONTROL
-static int spi_get_config(const void *blob, int node, struct spi_bus *bus)
-{
-       bus->node = node;
-       bus->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
-       bus->periph_id = pinmux_decode_periph_id(blob, node);
+       plat->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
+       plat->periph_id = pinmux_decode_periph_id(blob, node);
 
-       if (bus->periph_id == PERIPH_ID_NONE) {
+       if (plat->periph_id == PERIPH_ID_NONE) {
                debug("%s: Invalid peripheral ID %d\n", __func__,
-                       bus->periph_id);
+                       plat->periph_id);
                return -FDT_ERR_NOTFOUND;
        }
 
        /* Use 500KHz as a suitable default */
-       bus->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+       plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
                                        500000);
-       bus->deactivate_delay_us = fdtdec_get_int(blob, node,
+       plat->deactivate_delay_us = fdtdec_get_int(blob, node,
                                        "spi-deactivate-delay", 0);
+       debug("%s: regs=%p, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
+             __func__, plat->regs, plat->periph_id, plat->frequency,
+             plat->deactivate_delay_us);
 
        return 0;
 }
 
-/*
- * Process a list of nodes, adding them to our list of SPI ports.
- *
- * @param blob          fdt blob
- * @param node_list     list of nodes to process (any <=0 are ignored)
- * @param count         number of nodes to process
- * @param is_dvc        1 if these are DVC ports, 0 if standard I2C
- * @return 0 if ok, -1 on error
- */
-static int process_nodes(const void *blob, int node_list[], int count)
+static int exynos_spi_probe(struct udevice *bus)
 {
-       int i;
+       struct exynos_spi_platdata *plat = dev_get_platdata(bus);
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
 
-       /* build the i2c_controllers[] for each controller */
-       for (i = 0; i < count; i++) {
-               int node = node_list[i];
-               struct spi_bus *bus;
+       priv->regs = plat->regs;
+       if (plat->periph_id == PERIPH_ID_SPI1 ||
+           plat->periph_id == PERIPH_ID_SPI2)
+               priv->fifo_size = 64;
+       else
+               priv->fifo_size = 256;
 
-               if (node <= 0)
-                       continue;
+       priv->skip_preamble = 0;
+       priv->last_transaction_us = timer_get_us();
+       priv->freq = plat->frequency;
+       priv->periph_id = plat->periph_id;
 
-               bus = &spi_bus[i];
-               if (spi_get_config(blob, node, bus)) {
-                       printf("exynos spi_init: failed to decode bus %d\n",
-                               i);
-                       return -1;
-               }
+       return 0;
+}
 
-               debug("spi: controller bus %d at %p, periph_id %d\n",
-                     i, bus->regs, bus->periph_id);
-               bus->inited = 1;
-               bus_count++;
-       }
+static int exynos_spi_claim_bus(struct udevice *bus)
+{
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+       exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE);
+       spi_flush_fifo(priv->regs);
+
+       writel(SPI_FB_DELAY_180, &priv->regs->fb_clk);
 
        return 0;
 }
-#endif
 
-/**
- * Set up a new SPI slave for an fdt node
- *
- * @param blob         Device tree blob
- * @param node         SPI peripheral node to use
- * @return 0 if ok, -1 on error
- */
-struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
-                                     int spi_node)
+static int exynos_spi_release_bus(struct udevice *bus)
 {
-       struct spi_bus *bus;
-       unsigned int i;
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+
+       spi_flush_fifo(priv->regs);
+
+       return 0;
+}
+
+static int exynos_spi_xfer(struct udevice *dev, unsigned int bitlen,
+                          const void *dout, void *din, unsigned long flags)
+{
+       struct udevice *bus = dev->parent;
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+       int upto, todo;
+       int bytelen;
+       int ret = 0;
+
+       /* spi core configured to do 8 bit transfers */
+       if (bitlen % 8) {
+               debug("Non byte aligned SPI transfer.\n");
+               return -1;
+       }
+
+       /* Start the transaction, if necessary. */
+       if ((flags & SPI_XFER_BEGIN))
+               spi_cs_activate(dev);
+
+       /*
+        * Exynos SPI limits each transfer to 65535 transfers. To keep
+        * things simple, allow a maximum of 65532 bytes. We could allow
+        * more in word mode, but the performance difference is small.
+        */
+       bytelen = bitlen / 8;
+       for (upto = 0; !ret && upto < bytelen; upto += todo) {
+               todo = min(bytelen - upto, (1 << 16) - 4);
+               ret = spi_rx_tx(priv, todo, &din, &dout, flags);
+               if (ret)
+                       break;
+       }
 
-       for (i = 0, bus = spi_bus; i < bus_count; i++, bus++) {
-               if (bus->node == spi_node)
-                       return spi_base_setup_slave_fdt(blob, i, slave_node);
+       /* Stop the transaction, if necessary. */
+       if ((flags & SPI_XFER_END) && !(priv->mode & SPI_SLAVE)) {
+               spi_cs_deactivate(dev);
+               if (priv->skip_preamble) {
+                       assert(!priv->skip_preamble);
+                       debug("Failed to complete premable transaction\n");
+                       ret = -1;
+               }
        }
 
-       debug("%s: Failed to find bus node %d\n", __func__, spi_node);
-       return NULL;
+       return ret;
 }
 
-/* Sadly there is no error return from this function */
-void spi_init(void)
+static int exynos_spi_set_speed(struct udevice *bus, uint speed)
 {
-       int count;
+       struct exynos_spi_platdata *plat = bus->platdata;
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+       int ret;
 
-#ifdef CONFIG_OF_CONTROL
-       int node_list[EXYNOS5_SPI_NUM_CONTROLLERS];
-       const void *blob = gd->fdt_blob;
+       if (speed > plat->frequency)
+               speed = plat->frequency;
+       ret = set_spi_clk(priv->periph_id, speed);
+       if (ret)
+               return ret;
+       priv->freq = speed;
+       debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
+
+       return 0;
+}
 
-       count = fdtdec_find_aliases_for_id(blob, "spi",
-                       COMPAT_SAMSUNG_EXYNOS_SPI, node_list,
-                       EXYNOS5_SPI_NUM_CONTROLLERS);
-       if (process_nodes(blob, node_list, count))
-               return;
+static int exynos_spi_set_mode(struct udevice *bus, uint mode)
+{
+       struct exynos_spi_priv *priv = dev_get_priv(bus);
+       uint32_t reg;
 
-#else
-       struct spi_bus *bus;
+       reg = readl(&priv->regs->ch_cfg);
+       reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
 
-       for (count = 0; count < EXYNOS5_SPI_NUM_CONTROLLERS; count++) {
-               bus = &spi_bus[count];
-               bus->regs = get_spi_base(count);
-               bus->periph_id = PERIPH_ID_SPI0 + count;
+       if (mode & SPI_CPHA)
+               reg |= SPI_CH_CPHA_B;
 
-               /* Although Exynos5 supports upto 50Mhz speed,
-                * we are setting it to 10Mhz for safe side
-                */
-               bus->frequency = 10000000;
-               bus->inited = 1;
-               bus->node = 0;
-               bus_count = EXYNOS5_SPI_NUM_CONTROLLERS;
-       }
-#endif
+       if (mode & SPI_CPOL)
+               reg |= SPI_CH_CPOL_L;
+
+       writel(reg, &priv->regs->ch_cfg);
+       priv->mode = mode;
+       debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
+
+       return 0;
 }
+
+static const struct dm_spi_ops exynos_spi_ops = {
+       .claim_bus      = exynos_spi_claim_bus,
+       .release_bus    = exynos_spi_release_bus,
+       .xfer           = exynos_spi_xfer,
+       .set_speed      = exynos_spi_set_speed,
+       .set_mode       = exynos_spi_set_mode,
+       /*
+        * cs_info is not needed, since we require all chip selects to be
+        * in the device tree explicitly
+        */
+};
+
+static const struct udevice_id exynos_spi_ids[] = {
+       { .compatible = "samsung,exynos-spi" },
+       { }
+};
+
+U_BOOT_DRIVER(exynos_spi) = {
+       .name   = "exynos_spi",
+       .id     = UCLASS_SPI,
+       .of_match = exynos_spi_ids,
+       .ops    = &exynos_spi_ops,
+       .ofdata_to_platdata = exynos_spi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct exynos_spi_platdata),
+       .priv_auto_alloc_size = sizeof(struct exynos_spi_priv),
+       .per_child_auto_alloc_size      = sizeof(struct spi_slave),
+       .probe  = exynos_spi_probe,
+};
diff --git a/drivers/spi/fdt_spi.c b/drivers/spi/fdt_spi.c
deleted file mode 100644 (file)
index 58f139a..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Common fdt based SPI driver front end
- *
- * Copyright (c) 2013 NVIDIA Corporation
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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 <malloc.h>
-#include <asm/io.h>
-#include <asm/gpio.h>
-#include <asm/arch/clock.h>
-#include <asm/arch-tegra/clk_rst.h>
-#include <asm/arch-tegra20/tegra20_sflash.h>
-#include <asm/arch-tegra20/tegra20_slink.h>
-#include <asm/arch-tegra114/tegra114_spi.h>
-#include <spi.h>
-#include <fdtdec.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct fdt_spi_driver {
-       int compat;
-       int max_ctrls;
-       int (*init)(int *node_list, int count);
-       int (*claim_bus)(struct spi_slave *slave);
-       int (*release_bus)(struct spi_slave *slave);
-       int (*cs_is_valid)(unsigned int bus, unsigned int cs);
-       struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs,
-                                       unsigned int max_hz, unsigned int mode);
-       void (*free_slave)(struct spi_slave *slave);
-       void (*cs_activate)(struct spi_slave *slave);
-       void (*cs_deactivate)(struct spi_slave *slave);
-       int (*xfer)(struct spi_slave *slave, unsigned int bitlen,
-                   const void *data_out, void *data_in, unsigned long flags);
-};
-
-static struct fdt_spi_driver fdt_spi_drivers[] = {
-#ifdef CONFIG_TEGRA20_SFLASH
-       {
-               .compat         = COMPAT_NVIDIA_TEGRA20_SFLASH,
-               .max_ctrls      = 1,
-               .init           = tegra20_spi_init,
-               .claim_bus      = tegra20_spi_claim_bus,
-               .cs_is_valid    = tegra20_spi_cs_is_valid,
-               .setup_slave    = tegra20_spi_setup_slave,
-               .free_slave     = tegra20_spi_free_slave,
-               .cs_activate    = tegra20_spi_cs_activate,
-               .cs_deactivate  = tegra20_spi_cs_deactivate,
-               .xfer           = tegra20_spi_xfer,
-       },
-#endif
-#ifdef CONFIG_TEGRA20_SLINK
-       {
-               .compat         = COMPAT_NVIDIA_TEGRA20_SLINK,
-               .max_ctrls      = CONFIG_TEGRA_SLINK_CTRLS,
-               .init           = tegra30_spi_init,
-               .claim_bus      = tegra30_spi_claim_bus,
-               .cs_is_valid    = tegra30_spi_cs_is_valid,
-               .setup_slave    = tegra30_spi_setup_slave,
-               .free_slave     = tegra30_spi_free_slave,
-               .cs_activate    = tegra30_spi_cs_activate,
-               .cs_deactivate  = tegra30_spi_cs_deactivate,
-               .xfer           = tegra30_spi_xfer,
-       },
-#endif
-#ifdef CONFIG_TEGRA114_SPI
-       {
-               .compat         = COMPAT_NVIDIA_TEGRA114_SPI,
-               .max_ctrls      = CONFIG_TEGRA114_SPI_CTRLS,
-               .init           = tegra114_spi_init,
-               .claim_bus      = tegra114_spi_claim_bus,
-               .cs_is_valid    = tegra114_spi_cs_is_valid,
-               .setup_slave    = tegra114_spi_setup_slave,
-               .free_slave     = tegra114_spi_free_slave,
-               .cs_activate    = tegra114_spi_cs_activate,
-               .cs_deactivate  = tegra114_spi_cs_deactivate,
-               .xfer           = tegra114_spi_xfer,
-       },
-#endif
-};
-
-static struct fdt_spi_driver *driver;
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-       if (!driver)
-               return 0;
-       else if (!driver->cs_is_valid)
-               return 1;
-       else
-               return driver->cs_is_valid(bus, cs);
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-               unsigned int max_hz, unsigned int mode)
-{
-       if (!driver || !driver->setup_slave)
-               return NULL;
-
-       return driver->setup_slave(bus, cs, max_hz, mode);
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
-       if (driver && driver->free_slave)
-               return driver->free_slave(slave);
-}
-
-static int spi_init_driver(struct fdt_spi_driver *driver)
-{
-       int count;
-       int node_list[driver->max_ctrls];
-
-       count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
-                                          driver->compat,
-                                          node_list,
-                                          driver->max_ctrls);
-       return driver->init(node_list, count);
-}
-
-void spi_init(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fdt_spi_drivers); i++) {
-               driver = &fdt_spi_drivers[i];
-               if (!spi_init_driver(driver))
-                       break;
-       }
-       if (i == ARRAY_SIZE(fdt_spi_drivers))
-               driver = NULL;
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
-       if (!driver)
-               return 1;
-       if (!driver->claim_bus)
-               return 0;
-
-       return driver->claim_bus(slave);
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-       if (driver && driver->release_bus)
-               driver->release_bus(slave);
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
-       if (driver && driver->cs_activate)
-               driver->cs_activate(slave);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-       if (driver && driver->cs_deactivate)
-               driver->cs_deactivate(slave);
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-            const void *data_out, void *data_in, unsigned long flags)
-{
-       if (!driver || !driver->xfer)
-               return -1;
-
-       return driver->xfer(slave, bitlen, data_out, data_in, flags);
-}
index 3d58bcc1b955d140b8dc4a3937eba4db59dc6d35..e7b0982fb654681e4b9650d7ce8fe9a9c23d8acd 100644 (file)
 #include <malloc.h>
 #include <spi.h>
 #include <asm/io.h>
-#include <asm/arch/kirkwood.h>
-#include <asm/arch/spi.h>
+#include <asm/arch/soc.h>
+#ifdef CONFIG_KIRKWOOD
 #include <asm/arch/mpp.h>
+#endif
+#include <asm/arch-mvebu/spi.h>
 
-static struct kwspi_registers *spireg = (struct kwspi_registers *)KW_SPI_BASE;
+static struct kwspi_registers *spireg =
+       (struct kwspi_registers *)MVEBU_SPI_BASE;
 
+#ifdef CONFIG_KIRKWOOD
 static u32 cs_spi_mpp_back[2];
+#endif
 
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                                unsigned int max_hz, unsigned int mode)
 {
        struct spi_slave *slave;
        u32 data;
+#ifdef CONFIG_KIRKWOOD
        static const u32 kwspi_mpp_config[2][2] = {
                { MPP0_SPI_SCn, 0 }, /* if cs == 0 */
                { MPP7_SPI_SCn, 0 } /* if cs != 0 */
        };
+#endif
 
        if (!spi_cs_is_valid(bus, cs))
                return NULL;
@@ -51,15 +58,19 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
        writel(KWSPI_SMEMRDIRQ, &spireg->irq_cause);
        writel(KWSPI_IRQMASK, &spireg->irq_mask);
 
+#ifdef CONFIG_KIRKWOOD
        /* program mpp registers to select  SPI_CSn */
        kirkwood_mpp_conf(kwspi_mpp_config[cs ? 1 : 0], cs_spi_mpp_back);
+#endif
 
        return slave;
 }
 
 void spi_free_slave(struct spi_slave *slave)
 {
+#ifdef CONFIG_KIRKWOOD
        kirkwood_mpp_conf(cs_spi_mpp_back, NULL);
+#endif
        free(slave);
 }
 
index 12e9bdad38db51fdc0fdb127d142189d06c127ae..e717424db83a9ff7dcc15bc57074c5722b66ff11 100644 (file)
@@ -9,26 +9,23 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <spi.h>
+#include <spi_flash.h>
 #include <os.h>
 
 #include <asm/errno.h>
 #include <asm/spi.h>
 #include <asm/state.h>
+#include <dm/device-internal.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 #ifndef CONFIG_SPI_IDLE_VAL
 # define CONFIG_SPI_IDLE_VAL 0xFF
 #endif
 
-struct sandbox_spi_slave {
-       struct spi_slave slave;
-       const struct sandbox_spi_emu_ops *ops;
-       void *priv;
-};
-
-#define to_sandbox_spi_slave(s) container_of(s, struct sandbox_spi_slave, slave)
-
 const char *sandbox_spi_parse_spec(const char *arg, unsigned long *bus,
                                   unsigned long *cs)
 {
@@ -45,120 +42,52 @@ const char *sandbox_spi_parse_spec(const char *arg, unsigned long *bus,
        return endp + 1;
 }
 
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-       return bus < CONFIG_SANDBOX_SPI_MAX_BUS &&
-               cs < CONFIG_SANDBOX_SPI_MAX_CS;
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
-       struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
-
-       debug("sandbox_spi: activating CS\n");
-       if (sss->ops->cs_activate)
-               sss->ops->cs_activate(sss->priv);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-       struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
-
-       debug("sandbox_spi: deactivating CS\n");
-       if (sss->ops->cs_deactivate)
-               sss->ops->cs_deactivate(sss->priv);
-}
-
-void spi_init(void)
-{
-}
-
-void spi_set_speed(struct spi_slave *slave, uint hz)
+__weak int sandbox_spi_get_emul(struct sandbox_state *state,
+                               struct udevice *bus, struct udevice *slave,
+                               struct udevice **emulp)
 {
+       return -ENOENT;
 }
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-               unsigned int max_hz, unsigned int mode)
+static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen,
+                           const void *dout, void *din, unsigned long flags)
 {
-       struct sandbox_spi_slave *sss;
+       struct udevice *bus = slave->parent;
        struct sandbox_state *state = state_get_current();
-       const char *spec;
-
-       if (!spi_cs_is_valid(bus, cs)) {
-               debug("sandbox_spi: Invalid SPI bus/cs\n");
-               return NULL;
-       }
-
-       sss = spi_alloc_slave(struct sandbox_spi_slave, bus, cs);
-       if (!sss) {
-               debug("sandbox_spi: Out of memory\n");
-               return NULL;
-       }
-
-       spec = state->spi[bus][cs].spec;
-       sss->ops = state->spi[bus][cs].ops;
-       if (!spec || !sss->ops || sss->ops->setup(&sss->priv, spec)) {
-               free(sss);
-               printf("sandbox_spi: unable to locate a slave client\n");
-               return NULL;
-       }
-
-       return &sss->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
-       struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
-
-       debug("sandbox_spi: releasing slave\n");
-
-       if (sss->ops->free)
-               sss->ops->free(sss->priv);
-
-       free(sss);
-}
-
-static int spi_bus_claim_cnt[CONFIG_SANDBOX_SPI_MAX_BUS];
-
-int spi_claim_bus(struct spi_slave *slave)
-{
-       if (spi_bus_claim_cnt[slave->bus]++) {
-               printf("sandbox_spi: error: bus already claimed: %d!\n",
-                      spi_bus_claim_cnt[slave->bus]);
-       }
-
-       return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-       if (--spi_bus_claim_cnt[slave->bus]) {
-               printf("sandbox_spi: error: bus freed too often: %d!\n",
-                      spi_bus_claim_cnt[slave->bus]);
-       }
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-               void *din, unsigned long flags)
-{
-       struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
+       struct dm_spi_emul_ops *ops;
+       struct udevice *emul;
        uint bytes = bitlen / 8, i;
-       int ret = 0;
+       int ret;
        u8 *tx = (void *)dout, *rx = din;
+       uint busnum, cs;
 
        if (bitlen == 0)
-               goto done;
+               return 0;
 
        /* we can only do 8 bit transfers */
        if (bitlen % 8) {
                printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n",
                       bitlen);
-               flags |= SPI_XFER_END;
-               goto done;
+               return -EINVAL;
        }
 
-       if (flags & SPI_XFER_BEGIN)
-               spi_cs_activate(slave);
+       busnum = bus->seq;
+       cs = spi_chip_select(slave);
+       if (busnum >= CONFIG_SANDBOX_SPI_MAX_BUS ||
+           cs >= CONFIG_SANDBOX_SPI_MAX_CS) {
+               printf("%s: busnum=%u, cs=%u: out of range\n", __func__,
+                      busnum, cs);
+               return -ENOENT;
+       }
+       ret = sandbox_spi_get_emul(state, bus, slave, &emul);
+       if (ret) {
+               printf("%s: busnum=%u, cs=%u: no emulation available (err=%d)\n",
+                      __func__, busnum, cs, ret);
+               return -ENOENT;
+       }
+       ret = device_probe(emul);
+       if (ret)
+               return ret;
 
        /* make sure rx/tx buffers are full so clients can assume */
        if (!tx) {
@@ -178,12 +107,8 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
                }
        }
 
-       debug("sandbox_spi: xfer: bytes = %u\n tx:", bytes);
-       for (i = 0; i < bytes; ++i)
-               debug(" %u:%02x", i, tx[i]);
-       debug("\n");
-
-       ret = sss->ops->xfer(sss->priv, tx, rx, bytes);
+       ops = spi_emul_get_ops(emul);
+       ret = ops->xfer(emul, bitlen, dout, din, flags);
 
        debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:",
              ret, ret ? "bad" : "good");
@@ -196,22 +121,45 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
        if (rx != din)
                free(rx);
 
- done:
-       if (flags & SPI_XFER_END)
-               spi_cs_deactivate(slave);
-
        return ret;
 }
 
-/**
- * Set up a new SPI slave for an fdt node
- *
- * @param blob         Device tree blob
- * @param node         SPI peripheral node to use
- * @return 0 if ok, -1 on error
- */
-struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
-                                     int spi_node)
+static int sandbox_spi_set_speed(struct udevice *bus, uint speed)
+{
+       return 0;
+}
+
+static int sandbox_spi_set_mode(struct udevice *bus, uint mode)
+{
+       return 0;
+}
+
+static int sandbox_cs_info(struct udevice *bus, uint cs,
+                          struct spi_cs_info *info)
 {
-       return NULL;
+       /* Always allow activity on CS 0 */
+       if (cs >= 1)
+               return -ENODEV;
+
+       return 0;
 }
+
+static const struct dm_spi_ops sandbox_spi_ops = {
+       .xfer           = sandbox_spi_xfer,
+       .set_speed      = sandbox_spi_set_speed,
+       .set_mode       = sandbox_spi_set_mode,
+       .cs_info        = sandbox_cs_info,
+};
+
+static const struct udevice_id sandbox_spi_ids[] = {
+       { .compatible = "sandbox,spi" },
+       { }
+};
+
+U_BOOT_DRIVER(spi_sandbox) = {
+       .name   = "spi_sandbox",
+       .id     = UCLASS_SPI,
+       .of_match = sandbox_spi_ids,
+       .per_child_auto_alloc_size      = sizeof(struct spi_slave),
+       .ops    = &sandbox_spi_ops,
+};
index c969be31eb31828066e2c044c825529d6412db69..558803618a272cc6e0e8b880ddd89cc8950e6e68 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Copyright (c) 2014 Google, Inc
+ *
  * (C) Copyright 2002
  * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
  *
  */
 
 #include <common.h>
-#include <spi.h>
-
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
 #include <malloc.h>
+#include <spi.h>
+#include <asm/gpio.h>
 
-/*-----------------------------------------------------------------------
- * Definitions
- */
+DECLARE_GLOBAL_DATA_PTR;
 
-#ifdef DEBUG_SPI
-#define PRINTD(fmt,args...)    printf (fmt ,##args)
-#else
-#define PRINTD(fmt,args...)
-#endif
+struct soft_spi_platdata {
+       struct fdt_gpio_state cs;
+       struct fdt_gpio_state sclk;
+       struct fdt_gpio_state mosi;
+       struct fdt_gpio_state miso;
+       int spi_delay_us;
+};
 
-struct soft_spi_slave {
-       struct spi_slave slave;
+struct soft_spi_priv {
        unsigned int mode;
 };
 
-static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave)
+static int soft_spi_scl(struct udevice *dev, int bit)
 {
-       return container_of(slave, struct soft_spi_slave, slave);
-}
+       struct soft_spi_platdata *plat = dev->platdata;
+       struct soft_spi_priv *priv = dev_get_priv(dev);
 
-/*=====================================================================*/
-/*                         Public Functions                            */
-/*=====================================================================*/
+       gpio_set_value(plat->sclk.gpio, priv->mode & SPI_CPOL ? bit : !bit);
 
-/*-----------------------------------------------------------------------
- * Initialization
- */
-void spi_init (void)
-{
-#ifdef SPI_INIT
-       volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
-
-       SPI_INIT;
-#endif
+       return 0;
 }
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-               unsigned int max_hz, unsigned int mode)
+static int soft_spi_sda(struct udevice *dev, int bit)
 {
-       struct soft_spi_slave *ss;
+       struct soft_spi_platdata *plat = dev->platdata;
 
-       if (!spi_cs_is_valid(bus, cs))
-               return NULL;
+       gpio_set_value(plat->mosi.gpio, bit);
 
-       ss = spi_alloc_slave(struct soft_spi_slave, bus, cs);
-       if (!ss)
-               return NULL;
+       return 0;
+}
 
-       ss->mode = mode;
+static int soft_spi_cs_activate(struct udevice *dev)
+{
+       struct soft_spi_platdata *plat = dev->platdata;
+       struct soft_spi_priv *priv = dev_get_priv(dev);
 
-       /* TODO: Use max_hz to limit the SCK rate */
+       gpio_set_value(plat->cs.gpio, !(priv->mode & SPI_CS_HIGH));
+       gpio_set_value(plat->sclk.gpio, priv->mode & SPI_CPOL);
+       gpio_set_value(plat->cs.gpio, priv->mode & SPI_CS_HIGH);
 
-       return &ss->slave;
+       return 0;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+static int soft_spi_cs_deactivate(struct udevice *dev)
 {
-       struct soft_spi_slave *ss = to_soft_spi(slave);
+       struct soft_spi_platdata *plat = dev->platdata;
+       struct soft_spi_priv *priv = dev_get_priv(dev);
 
-       free(ss);
+       gpio_set_value(plat->cs.gpio, !(priv->mode & SPI_CS_HIGH));
+
+       return 0;
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+static int soft_spi_claim_bus(struct udevice *dev)
 {
-#ifdef CONFIG_SYS_IMMR
-       volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
-#endif
-       struct soft_spi_slave *ss = to_soft_spi(slave);
-
        /*
         * Make sure the SPI clock is in idle state as defined for
         * this slave.
         */
-       if (ss->mode & SPI_CPOL)
-               SPI_SCL(1);
-       else
-               SPI_SCL(0);
-
-       return 0;
+       return soft_spi_scl(dev, 0);
 }
 
-void spi_release_bus(struct spi_slave *slave)
+static int soft_spi_release_bus(struct udevice *dev)
 {
        /* Nothing to do */
+       return 0;
 }
 
 /*-----------------------------------------------------------------------
@@ -111,28 +100,27 @@ void spi_release_bus(struct spi_slave *slave)
  * input data overwrites the output data (since both are buffered by
  * temporary variables, this is OK).
  */
-int  spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-               const void *dout, void *din, unsigned long flags)
+static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen,
+                        const void *dout, void *din, unsigned long flags)
 {
-#ifdef CONFIG_SYS_IMMR
-       volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
-#endif
-       struct soft_spi_slave *ss = to_soft_spi(slave);
+       struct soft_spi_priv *priv = dev_get_priv(dev);
+       struct soft_spi_platdata *plat = dev->platdata;
        uchar           tmpdin  = 0;
        uchar           tmpdout = 0;
        const u8        *txd = dout;
        u8              *rxd = din;
-       int             cpol = ss->mode & SPI_CPOL;
-       int             cpha = ss->mode & SPI_CPHA;
+       int             cpol = priv->mode & SPI_CPOL;
+       int             cpha = priv->mode & SPI_CPHA;
        unsigned int    j;
 
-       PRINTD("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
-               slave->bus, slave->cs, *(uint *)txd, *(uint *)rxd, bitlen);
+       debug("spi_xfer: slave %s:%s dout %08X din %08X bitlen %u\n",
+             dev->parent->name, dev->name, *(uint *)txd, *(uint *)rxd,
+             bitlen);
 
        if (flags & SPI_XFER_BEGIN)
-               spi_cs_activate(slave);
+               soft_spi_cs_activate(dev);
 
-       for(j = 0; j < bitlen; j++) {
+       for (j = 0; j < bitlen; j++) {
                /*
                 * Check if it is time to work on a new byte.
                 */
@@ -141,7 +129,7 @@ int  spi_xfer(struct spi_slave *slave, unsigned int bitlen,
                                tmpdout = *txd++;
                        else
                                tmpdout = 0;
-                       if(j != 0) {
+                       if (j != 0) {
                                if (rxd)
                                        *rxd++ = tmpdin;
                        }
@@ -149,19 +137,19 @@ int  spi_xfer(struct spi_slave *slave, unsigned int bitlen,
                }
 
                if (!cpha)
-                       SPI_SCL(!cpol);
-               SPI_SDA(tmpdout & 0x80);
-               SPI_DELAY;
+                       soft_spi_scl(dev, !cpol);
+               soft_spi_sda(dev, tmpdout & 0x80);
+               udelay(plat->spi_delay_us);
                if (cpha)
-                       SPI_SCL(!cpol);
+                       soft_spi_scl(dev, !cpol);
                else
-                       SPI_SCL(cpol);
+                       soft_spi_scl(dev, cpol);
                tmpdin  <<= 1;
-               tmpdin  |= SPI_READ;
+               tmpdin  |= gpio_get_value(plat->miso.gpio);
                tmpdout <<= 1;
-               SPI_DELAY;
+               udelay(plat->spi_delay_us);
                if (cpha)
-                       SPI_SCL(cpol);
+                       soft_spi_scl(dev, cpol);
        }
        /*
         * If the number of bits isn't a multiple of 8, shift the last
@@ -175,7 +163,90 @@ int  spi_xfer(struct spi_slave *slave, unsigned int bitlen,
        }
 
        if (flags & SPI_XFER_END)
-               spi_cs_deactivate(slave);
+               soft_spi_cs_deactivate(dev);
 
-       return(0);
+       return 0;
 }
+
+static int soft_spi_set_speed(struct udevice *dev, unsigned int speed)
+{
+       /* Accept any speed */
+       return 0;
+}
+
+static int soft_spi_set_mode(struct udevice *dev, unsigned int mode)
+{
+       struct soft_spi_priv *priv = dev_get_priv(dev);
+
+       priv->mode = mode;
+
+       return 0;
+}
+
+static int soft_spi_child_pre_probe(struct udevice *dev)
+{
+       struct spi_slave *slave = dev_get_parentdata(dev);
+
+       slave->dev = dev;
+       return spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, slave);
+}
+
+static const struct dm_spi_ops soft_spi_ops = {
+       .claim_bus      = soft_spi_claim_bus,
+       .release_bus    = soft_spi_release_bus,
+       .xfer           = soft_spi_xfer,
+       .set_speed      = soft_spi_set_speed,
+       .set_mode       = soft_spi_set_mode,
+};
+
+static int soft_spi_ofdata_to_platdata(struct udevice *dev)
+{
+       struct soft_spi_platdata *plat = dev->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = dev->of_offset;
+
+       if (fdtdec_decode_gpio(blob, node, "cs-gpio", &plat->cs) ||
+           fdtdec_decode_gpio(blob, node, "sclk-gpio", &plat->sclk) ||
+           fdtdec_decode_gpio(blob, node, "mosi-gpio", &plat->mosi) ||
+           fdtdec_decode_gpio(blob, node, "miso-gpio", &plat->miso))
+               return -EINVAL;
+       plat->spi_delay_us = fdtdec_get_int(blob, node, "spi-delay-us", 0);
+
+       return 0;
+}
+
+static int soft_spi_probe(struct udevice *dev)
+{
+       struct spi_slave *slave = dev_get_parentdata(dev);
+       struct soft_spi_platdata *plat = dev->platdata;
+
+       gpio_request(plat->cs.gpio, "soft_spi_cs");
+       gpio_request(plat->sclk.gpio, "soft_spi_sclk");
+       gpio_request(plat->mosi.gpio, "soft_spi_mosi");
+       gpio_request(plat->miso.gpio, "soft_spi_miso");
+
+       gpio_direction_output(plat->sclk.gpio, slave->mode & SPI_CPOL);
+       gpio_direction_output(plat->mosi.gpio, 1);
+       gpio_direction_input(plat->miso.gpio);
+       gpio_direction_output(plat->cs.gpio, !(slave->mode & SPI_CS_HIGH));
+
+       return 0;
+}
+
+static const struct udevice_id soft_spi_ids[] = {
+       { .compatible = "u-boot,soft-spi" },
+       { }
+};
+
+U_BOOT_DRIVER(soft_spi) = {
+       .name   = "soft_spi",
+       .id     = UCLASS_SPI,
+       .of_match = soft_spi_ids,
+       .ops    = &soft_spi_ops,
+       .ofdata_to_platdata = soft_spi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct soft_spi_platdata),
+       .priv_auto_alloc_size = sizeof(struct soft_spi_priv),
+       .per_child_auto_alloc_size      = sizeof(struct spi_slave),
+       .probe  = soft_spi_probe,
+       .child_pre_probe        = soft_spi_child_pre_probe,
+};
diff --git a/drivers/spi/soft_spi_legacy.c b/drivers/spi/soft_spi_legacy.c
new file mode 100644 (file)
index 0000000..941daa7
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * (C) Copyright 2002
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
+ *
+ * Influenced by code from:
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <spi.h>
+
+#include <malloc.h>
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+#ifdef DEBUG_SPI
+#define PRINTD(fmt,args...)    printf (fmt ,##args)
+#else
+#define PRINTD(fmt,args...)
+#endif
+
+struct soft_spi_slave {
+       struct spi_slave slave;
+       unsigned int mode;
+};
+
+static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave)
+{
+       return container_of(slave, struct soft_spi_slave, slave);
+}
+
+/*=====================================================================*/
+/*                         Public Functions                            */
+/*=====================================================================*/
+
+/*-----------------------------------------------------------------------
+ * Initialization
+ */
+void spi_init (void)
+{
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+               unsigned int max_hz, unsigned int mode)
+{
+       struct soft_spi_slave *ss;
+
+       if (!spi_cs_is_valid(bus, cs))
+               return NULL;
+
+       ss = spi_alloc_slave(struct soft_spi_slave, bus, cs);
+       if (!ss)
+               return NULL;
+
+       ss->mode = mode;
+
+       /* TODO: Use max_hz to limit the SCK rate */
+
+       return &ss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+       struct soft_spi_slave *ss = to_soft_spi(slave);
+
+       free(ss);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+#ifdef CONFIG_SYS_IMMR
+       volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+#endif
+       struct soft_spi_slave *ss = to_soft_spi(slave);
+
+       /*
+        * Make sure the SPI clock is in idle state as defined for
+        * this slave.
+        */
+       if (ss->mode & SPI_CPOL)
+               SPI_SCL(1);
+       else
+               SPI_SCL(0);
+
+       return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+       /* Nothing to do */
+}
+
+/*-----------------------------------------------------------------------
+ * SPI transfer
+ *
+ * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
+ * "bitlen" bits in the SPI MISO port.  That's just the way SPI works.
+ *
+ * The source of the outgoing bits is the "dout" parameter and the
+ * destination of the input bits is the "din" parameter.  Note that "dout"
+ * and "din" can point to the same memory location, in which case the
+ * input data overwrites the output data (since both are buffered by
+ * temporary variables, this is OK).
+ */
+int  spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+               const void *dout, void *din, unsigned long flags)
+{
+#ifdef CONFIG_SYS_IMMR
+       volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+#endif
+       struct soft_spi_slave *ss = to_soft_spi(slave);
+       uchar           tmpdin  = 0;
+       uchar           tmpdout = 0;
+       const u8        *txd = dout;
+       u8              *rxd = din;
+       int             cpol = ss->mode & SPI_CPOL;
+       int             cpha = ss->mode & SPI_CPHA;
+       unsigned int    j;
+
+       PRINTD("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+               slave->bus, slave->cs, *(uint *)txd, *(uint *)rxd, bitlen);
+
+       if (flags & SPI_XFER_BEGIN)
+               spi_cs_activate(slave);
+
+       for(j = 0; j < bitlen; j++) {
+               /*
+                * Check if it is time to work on a new byte.
+                */
+               if ((j % 8) == 0) {
+                       if (txd)
+                               tmpdout = *txd++;
+                       else
+                               tmpdout = 0;
+                       if(j != 0) {
+                               if (rxd)
+                                       *rxd++ = tmpdin;
+                       }
+                       tmpdin  = 0;
+               }
+
+               if (!cpha)
+                       SPI_SCL(!cpol);
+               SPI_SDA(tmpdout & 0x80);
+               SPI_DELAY;
+               if (cpha)
+                       SPI_SCL(!cpol);
+               else
+                       SPI_SCL(cpol);
+               tmpdin  <<= 1;
+               tmpdin  |= SPI_READ;
+               tmpdout <<= 1;
+               SPI_DELAY;
+               if (cpha)
+                       SPI_SCL(cpol);
+       }
+       /*
+        * If the number of bits isn't a multiple of 8, shift the last
+        * bits over to left-justify them.  Then store the last byte
+        * read in.
+        */
+       if (rxd) {
+               if ((bitlen % 8) != 0)
+                       tmpdin <<= 8 - (bitlen % 8);
+               *rxd++ = tmpdin;
+       }
+
+       if (flags & SPI_XFER_END)
+               spi_cs_deactivate(slave);
+
+       return(0);
+}
diff --git a/drivers/spi/spi-emul-uclass.c b/drivers/spi/spi-emul-uclass.c
new file mode 100644 (file)
index 0000000..b436a0e
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi.h>
+#include <spi_flash.h>
+
+UCLASS_DRIVER(spi_emul) = {
+       .id             = UCLASS_SPI_EMUL,
+       .name           = "spi_emul",
+};
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
new file mode 100644 (file)
index 0000000..13c6b77
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <spi.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <dm/root.h>
+#include <dm/lists.h>
+#include <dm/util.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int spi_set_speed_mode(struct udevice *bus, int speed, int mode)
+{
+       struct dm_spi_ops *ops;
+       int ret;
+
+       ops = spi_get_ops(bus);
+       if (ops->set_speed)
+               ret = ops->set_speed(bus, speed);
+       else
+               ret = -EINVAL;
+       if (ret) {
+               printf("Cannot set speed (err=%d)\n", ret);
+               return ret;
+       }
+
+       if (ops->set_mode)
+               ret = ops->set_mode(bus, mode);
+       else
+               ret = -EINVAL;
+       if (ret) {
+               printf("Cannot set mode (err=%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+       struct udevice *dev = slave->dev;
+       struct udevice *bus = dev->parent;
+       struct dm_spi_ops *ops = spi_get_ops(bus);
+       struct dm_spi_bus *spi = bus->uclass_priv;
+       int speed;
+       int ret;
+
+       speed = slave->max_hz;
+       if (spi->max_hz) {
+               if (speed)
+                       speed = min(speed, spi->max_hz);
+               else
+                       speed = spi->max_hz;
+       }
+       if (!speed)
+               speed = 100000;
+       ret = spi_set_speed_mode(bus, speed, slave->mode);
+       if (ret)
+               return ret;
+
+       return ops->claim_bus ? ops->claim_bus(bus) : 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+       struct udevice *dev = slave->dev;
+       struct udevice *bus = dev->parent;
+       struct dm_spi_ops *ops = spi_get_ops(bus);
+
+       if (ops->release_bus)
+               ops->release_bus(bus);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+            const void *dout, void *din, unsigned long flags)
+{
+       struct udevice *dev = slave->dev;
+       struct udevice *bus = dev->parent;
+
+       if (bus->uclass->uc_drv->id != UCLASS_SPI)
+               return -EOPNOTSUPP;
+
+       return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags);
+}
+
+int spi_post_bind(struct udevice *dev)
+{
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+int spi_post_probe(struct udevice *dev)
+{
+       struct dm_spi_bus *spi = dev->uclass_priv;
+
+       spi->max_hz = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                    "spi-max-frequency", 0);
+
+       return 0;
+}
+
+int spi_chip_select(struct udevice *dev)
+{
+       struct spi_slave *slave = dev_get_parentdata(dev);
+
+       return slave ? slave->cs : -ENOENT;
+}
+
+/**
+ * spi_find_chip_select() - Find the slave attached to chip select
+ *
+ * @bus:       SPI bus to search
+ * @cs:                Chip select to look for
+ * @devp:      Returns the slave device if found
+ * @return 0 if found, -ENODEV on error
+ */
+static int spi_find_chip_select(struct udevice *bus, int cs,
+                               struct udevice **devp)
+{
+       struct udevice *dev;
+
+       for (device_find_first_child(bus, &dev); dev;
+            device_find_next_child(&dev)) {
+               struct spi_slave store;
+               struct spi_slave *slave = dev_get_parentdata(dev);
+
+               if (!slave)  {
+                       slave = &store;
+                       spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
+                                              slave);
+               }
+               debug("%s: slave=%p, cs=%d\n", __func__, slave,
+                     slave ? slave->cs : -1);
+               if (slave && slave->cs == cs) {
+                       *devp = dev;
+                       return 0;
+               }
+       }
+
+       return -ENODEV;
+}
+
+int spi_cs_is_valid(unsigned int busnum, unsigned int cs)
+{
+       struct spi_cs_info info;
+       struct udevice *bus;
+       int ret;
+
+       ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, false, &bus);
+       if (ret) {
+               debug("%s: No bus %d\n", __func__, busnum);
+               return ret;
+       }
+
+       return spi_cs_info(bus, cs, &info);
+}
+
+int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info)
+{
+       struct spi_cs_info local_info;
+       struct dm_spi_ops *ops;
+       int ret;
+
+       if (!info)
+               info = &local_info;
+
+       /* If there is a device attached, return it */
+       info->dev = NULL;
+       ret = spi_find_chip_select(bus, cs, &info->dev);
+       if (!ret)
+               return 0;
+
+       /*
+        * Otherwise ask the driver. For the moment we don't have CS info.
+        * When we do we could provide the driver with a helper function
+        * to figure out what chip selects are valid, or just handle the
+        * request.
+        */
+       ops = spi_get_ops(bus);
+       if (ops->cs_info)
+               return ops->cs_info(bus, cs, info);
+
+       /*
+        * We could assume there is at least one valid chip select, but best
+        * to be sure and return an error in this case. The driver didn't
+        * care enough to tell us.
+        */
+       return -ENODEV;
+}
+
+int spi_bind_device(struct udevice *bus, int cs, const char *drv_name,
+                   const char *dev_name, struct udevice **devp)
+{
+       struct driver *drv;
+       int ret;
+
+       drv = lists_driver_lookup_name(drv_name);
+       if (!drv) {
+               printf("Cannot find driver '%s'\n", drv_name);
+               return -ENOENT;
+       }
+       ret = device_bind(bus, drv, dev_name, NULL, -1, devp);
+       if (ret) {
+               printf("Cannot create device named '%s' (err=%d)\n",
+                      dev_name, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int spi_find_bus_and_cs(int busnum, int cs, struct udevice **busp,
+                       struct udevice **devp)
+{
+       struct udevice *bus, *dev;
+       int ret;
+
+       ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, false, &bus);
+       if (ret) {
+               debug("%s: No bus %d\n", __func__, busnum);
+               return ret;
+       }
+       ret = spi_find_chip_select(bus, cs, &dev);
+       if (ret) {
+               debug("%s: No cs %d\n", __func__, cs);
+               return ret;
+       }
+       *busp = bus;
+       *devp = dev;
+
+       return ret;
+}
+
+int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
+                      const char *drv_name, const char *dev_name,
+                      struct udevice **busp, struct spi_slave **devp)
+{
+       struct udevice *bus, *dev;
+       struct spi_slave *slave;
+       bool created = false;
+       int ret;
+
+       ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
+       if (ret) {
+               printf("Invalid bus %d (err=%d)\n", busnum, ret);
+               return ret;
+       }
+       ret = spi_find_chip_select(bus, cs, &dev);
+
+       /*
+        * If there is no such device, create one automatically. This means
+        * that we don't need a device tree node or platform data for the
+        * SPI flash chip - we will bind to the correct driver.
+        */
+       if (ret == -ENODEV && drv_name) {
+               debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
+                     __func__, dev_name, busnum, cs, drv_name);
+               ret = spi_bind_device(bus, cs, drv_name, dev_name, &dev);
+               if (ret)
+                       return ret;
+               created = true;
+       } else if (ret) {
+               printf("Invalid chip select %d:%d (err=%d)\n", busnum, cs,
+                      ret);
+               return ret;
+       }
+
+       if (!device_active(dev)) {
+               slave = (struct spi_slave *)calloc(1,
+                                                  sizeof(struct spi_slave));
+               if (!slave) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               ret = spi_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
+                                            slave);
+               if (ret)
+                       goto err;
+               slave->cs = cs;
+               slave->dev = dev;
+               ret = device_probe_child(dev, slave);
+               free(slave);
+               if (ret)
+                       goto err;
+       }
+
+       ret = spi_set_speed_mode(bus, speed, mode);
+       if (ret)
+               goto err;
+
+       *busp = bus;
+       *devp = dev_get_parentdata(dev);
+       debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp);
+
+       return 0;
+
+err:
+       if (created) {
+               device_remove(dev);
+               device_unbind(dev);
+       }
+
+       return ret;
+}
+
+/* Compatibility function - to be removed */
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int node,
+                                     int bus_node)
+{
+       struct udevice *bus, *dev;
+       int ret;
+
+       ret = uclass_get_device_by_of_offset(UCLASS_SPI, bus_node, &bus);
+       if (ret)
+               return NULL;
+       ret = device_get_child_by_of_offset(bus, node, &dev);
+       if (ret)
+               return NULL;
+       return dev_get_parentdata(dev);
+}
+
+/* Compatibility function - to be removed */
+struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
+                                 unsigned int speed, unsigned int mode)
+{
+       struct spi_slave *slave;
+       struct udevice *dev;
+       int ret;
+
+       ret = spi_get_bus_and_cs(busnum, cs, speed, mode, NULL, 0, &dev,
+                                 &slave);
+       if (ret)
+               return NULL;
+
+       return slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+       device_remove(slave->dev);
+       slave->dev = NULL;
+}
+
+int spi_ofdata_to_platdata(const void *blob, int node,
+                          struct spi_slave *spi)
+{
+       int mode = 0;
+
+       spi->cs = fdtdec_get_int(blob, node, "reg", -1);
+       spi->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 0);
+       if (fdtdec_get_bool(blob, node, "spi-cpol"))
+               mode |= SPI_CPOL;
+       if (fdtdec_get_bool(blob, node, "spi-cpha"))
+               mode |= SPI_CPHA;
+       if (fdtdec_get_bool(blob, node, "spi-cs-high"))
+               mode |= SPI_CS_HIGH;
+       if (fdtdec_get_bool(blob, node, "spi-half-duplex"))
+               mode |= SPI_PREAMBLE;
+       spi->mode = mode;
+
+       return 0;
+}
+
+UCLASS_DRIVER(spi) = {
+       .id             = UCLASS_SPI,
+       .name           = "spi",
+       .post_bind      = spi_post_bind,
+       .post_probe     = spi_post_probe,
+       .per_device_auto_alloc_size = sizeof(struct dm_spi_bus),
+};
+
+UCLASS_DRIVER(spi_generic) = {
+       .id             = UCLASS_SPI_GENERIC,
+       .name           = "spi_generic",
+};
+
+U_BOOT_DRIVER(spi_generic_drv) = {
+       .name           = "spi_generic_drv",
+       .id             = UCLASS_SPI_GENERIC,
+};
index 810fa4718ce17b87c389a522c6cea788c9df3867..2d97625fba73b81dcb8a2ba2d55d5e1d5eef0bcb 100644 (file)
  */
 
 #include <common.h>
-#include <malloc.h>
+#include <dm.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
 #include <asm/arch/clock.h>
 #include <asm/arch-tegra/clk_rst.h>
-#include <asm/arch-tegra114/tegra114_spi.h>
 #include <spi.h>
 #include <fdtdec.h>
+#include "tegra_spi.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -104,130 +103,63 @@ struct spi_regs {
        u32 spare_ctl;  /* 18c:SPI_SPARE_CTRL register */
 };
 
-struct tegra_spi_ctrl {
+struct tegra114_spi_priv {
        struct spi_regs *regs;
        unsigned int freq;
        unsigned int mode;
        int periph_id;
        int valid;
+       int last_transaction_us;
 };
 
-struct tegra_spi_slave {
-       struct spi_slave slave;
-       struct tegra_spi_ctrl *ctrl;
-};
-
-static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA114_SPI_CTRLS];
-
-static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
+static int tegra114_spi_ofdata_to_platdata(struct udevice *bus)
 {
-       return container_of(slave, struct tegra_spi_slave, slave);
-}
+       struct tegra_spi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
 
-int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-       if (bus >= CONFIG_TEGRA114_SPI_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
-               return 0;
-       else
-               return 1;
-}
+       plat->base = fdtdec_get_addr(blob, node, "reg");
+       plat->periph_id = clock_decode_periph_id(blob, node);
 
-struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs,
-               unsigned int max_hz, unsigned int mode)
-{
-       struct tegra_spi_slave *spi;
-
-       debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__,
-               bus, cs, max_hz, mode);
-
-       if (!spi_cs_is_valid(bus, cs)) {
-               printf("SPI error: unsupported bus %d / chip select %d\n",
-                      bus, cs);
-               return NULL;
-       }
-
-       if (max_hz > TEGRA_SPI_MAX_FREQ) {
-               printf("SPI error: unsupported frequency %d Hz. Max frequency"
-                       " is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
-               return NULL;
+       if (plat->periph_id == PERIPH_ID_NONE) {
+               debug("%s: could not decode periph id %d\n", __func__,
+                     plat->periph_id);
+               return -FDT_ERR_NOTFOUND;
        }
 
-       spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs);
-       if (!spi) {
-               printf("SPI error: malloc of SPI structure failed\n");
-               return NULL;
-       }
-       spi->ctrl = &spi_ctrls[bus];
-       if (!spi->ctrl) {
-               printf("SPI error: could not find controller for bus %d\n",
-                      bus);
-               return NULL;
-       }
+       /* Use 500KHz as a suitable default */
+       plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+                                       500000);
+       plat->deactivate_delay_us = fdtdec_get_int(blob, node,
+                                       "spi-deactivate-delay", 0);
+       debug("%s: base=%#08lx, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
+             __func__, plat->base, plat->periph_id, plat->frequency,
+             plat->deactivate_delay_us);
 
-       if (max_hz < spi->ctrl->freq) {
-               debug("%s: limiting frequency from %u to %u\n", __func__,
-                     spi->ctrl->freq, max_hz);
-               spi->ctrl->freq = max_hz;
-       }
-       spi->ctrl->mode = mode;
-
-       return &spi->slave;
-}
-
-void tegra114_spi_free_slave(struct spi_slave *slave)
-{
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-
-       free(spi);
+       return 0;
 }
 
-int tegra114_spi_init(int *node_list, int count)
+static int tegra114_spi_probe(struct udevice *bus)
 {
-       struct tegra_spi_ctrl *ctrl;
-       int i;
-       int node = 0;
-       int found = 0;
-
-       for (i = 0; i < count; i++) {
-               ctrl = &spi_ctrls[i];
-               node = node_list[i];
-
-               ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
-                                                                node, "reg");
-               if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
-                       debug("%s: no spi register found\n", __func__);
-                       continue;
-               }
-               ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
-                                           "spi-max-frequency", 0);
-               if (!ctrl->freq) {
-                       debug("%s: no spi max frequency found\n", __func__);
-                       continue;
-               }
+       struct tegra_spi_platdata *plat = dev_get_platdata(bus);
+       struct tegra114_spi_priv *priv = dev_get_priv(bus);
 
-               ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
-               if (ctrl->periph_id == PERIPH_ID_NONE) {
-                       debug("%s: could not decode periph id\n", __func__);
-                       continue;
-               }
-               ctrl->valid = 1;
-               found = 1;
+       priv->regs = (struct spi_regs *)plat->base;
 
-               debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
-                     __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
-       }
+       priv->last_transaction_us = timer_get_us();
+       priv->freq = plat->frequency;
+       priv->periph_id = plat->periph_id;
 
-       return !found;
+       return 0;
 }
 
-int tegra114_spi_claim_bus(struct spi_slave *slave)
+static int tegra114_spi_claim_bus(struct udevice *bus)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct tegra114_spi_priv *priv = dev_get_priv(bus);
+       struct spi_regs *regs = priv->regs;
 
        /* Change SPI clock to correct frequency, PLLP_OUT0 source */
-       clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
-                              spi->ctrl->freq);
+       clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH, priv->freq);
 
        /* Clear stale status here */
        setbits_le32(&regs->fifo_status,
@@ -244,33 +176,64 @@ int tegra114_spi_claim_bus(struct spi_slave *slave)
 
        /* Set master mode and sw controlled CS */
        setbits_le32(&regs->command1, SPI_CMD1_M_S | SPI_CMD1_CS_SW_HW |
-                    (spi->ctrl->mode << SPI_CMD1_MODE_SHIFT));
+                    (priv->mode << SPI_CMD1_MODE_SHIFT));
        debug("%s: COMMAND1 = %08x\n", __func__, readl(&regs->command1));
 
        return 0;
 }
 
-void tegra114_spi_cs_activate(struct spi_slave *slave)
+/**
+ * Activate the CS by driving it LOW
+ *
+ * @param slave        Pointer to spi_slave to which controller has to
+ *             communicate with
+ */
+static void spi_cs_activate(struct udevice *dev)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra_spi_platdata *pdata = dev_get_platdata(bus);
+       struct tegra114_spi_priv *priv = dev_get_priv(bus);
+
+       /* If it's too soon to do another transaction, wait */
+       if (pdata->deactivate_delay_us &&
+           priv->last_transaction_us) {
+               ulong delay_us;         /* The delay completed so far */
+               delay_us = timer_get_us() - priv->last_transaction_us;
+               if (delay_us < pdata->deactivate_delay_us)
+                       udelay(pdata->deactivate_delay_us - delay_us);
+       }
 
-       clrbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL);
+       clrbits_le32(&priv->regs->command1, SPI_CMD1_CS_SW_VAL);
 }
 
-void tegra114_spi_cs_deactivate(struct spi_slave *slave)
+/**
+ * Deactivate the CS by driving it HIGH
+ *
+ * @param slave        Pointer to spi_slave to which controller has to
+ *             communicate with
+ */
+static void spi_cs_deactivate(struct udevice *dev)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra_spi_platdata *pdata = dev_get_platdata(bus);
+       struct tegra114_spi_priv *priv = dev_get_priv(bus);
+
+       setbits_le32(&priv->regs->command1, SPI_CMD1_CS_SW_VAL);
 
-       setbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL);
+       /* Remember time of this transaction so we can honour the bus delay */
+       if (pdata->deactivate_delay_us)
+               priv->last_transaction_us = timer_get_us();
+
+       debug("Deactivate CS, bus '%s'\n", bus->name);
 }
 
-int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-               const void *data_out, void *data_in, unsigned long flags)
+static int tegra114_spi_xfer(struct udevice *dev, unsigned int bitlen,
+                            const void *data_out, void *data_in,
+                            unsigned long flags)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra114_spi_priv *priv = dev_get_priv(bus);
+       struct spi_regs *regs = priv->regs;
        u32 reg, tmpdout, tmpdin = 0;
        const u8 *dout = data_out;
        u8 *din = data_in;
@@ -278,7 +241,7 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
        int ret;
 
        debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
-             __func__, slave->bus, slave->cs, dout, din, bitlen);
+             __func__, bus->seq, spi_chip_select(dev), dout, din, bitlen);
        if (bitlen % 8)
                return -1;
        num_bytes = bitlen / 8;
@@ -291,13 +254,13 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
        clrsetbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL,
                        SPI_CMD1_RX_EN | SPI_CMD1_TX_EN | SPI_CMD1_LSBY_FE |
-                       (slave->cs << SPI_CMD1_CS_SEL_SHIFT));
+                       (spi_chip_select(dev) << SPI_CMD1_CS_SEL_SHIFT));
 
        /* set xfer size to 1 block (32 bits) */
        writel(0, &regs->dma_blk);
 
        if (flags & SPI_XFER_BEGIN)
-               spi_cs_activate(slave);
+               spi_cs_activate(dev);
 
        /* handle data in 32-bit chunks */
        while (num_bytes > 0) {
@@ -383,7 +346,7 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
        }
 
        if (flags & SPI_XFER_END)
-               spi_cs_deactivate(slave);
+               spi_cs_deactivate(dev);
 
        debug("%s: transfer ended. Value=%08x, fifo_status = %08x\n",
              __func__, tmpdin, readl(&regs->fifo_status));
@@ -394,5 +357,56 @@ int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
                return -1;
        }
 
+       return ret;
+}
+
+static int tegra114_spi_set_speed(struct udevice *bus, uint speed)
+{
+       struct tegra_spi_platdata *plat = bus->platdata;
+       struct tegra114_spi_priv *priv = dev_get_priv(bus);
+
+       if (speed > plat->frequency)
+               speed = plat->frequency;
+       priv->freq = speed;
+       debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
+
        return 0;
 }
+
+static int tegra114_spi_set_mode(struct udevice *bus, uint mode)
+{
+       struct tegra114_spi_priv *priv = dev_get_priv(bus);
+
+       priv->mode = mode;
+       debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
+
+       return 0;
+}
+
+static const struct dm_spi_ops tegra114_spi_ops = {
+       .claim_bus      = tegra114_spi_claim_bus,
+       .xfer           = tegra114_spi_xfer,
+       .set_speed      = tegra114_spi_set_speed,
+       .set_mode       = tegra114_spi_set_mode,
+       /*
+        * cs_info is not needed, since we require all chip selects to be
+        * in the device tree explicitly
+        */
+};
+
+static const struct udevice_id tegra114_spi_ids[] = {
+       { .compatible = "nvidia,tegra114-spi" },
+       { }
+};
+
+U_BOOT_DRIVER(tegra114_spi) = {
+       .name   = "tegra114_spi",
+       .id     = UCLASS_SPI,
+       .of_match = tegra114_spi_ids,
+       .ops    = &tegra114_spi_ops,
+       .ofdata_to_platdata = tegra114_spi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
+       .priv_auto_alloc_size = sizeof(struct tegra114_spi_priv),
+       .per_child_auto_alloc_size      = sizeof(struct spi_slave),
+       .probe  = tegra114_spi_probe,
+};
index b5d561be34108dade5a7450391ff9824461d03c9..7d0d0f37fc70a7f5f5da821b2af8589bf59ac7a1 100644 (file)
@@ -7,15 +7,16 @@
  */
 
 #include <common.h>
-#include <malloc.h>
+#include <dm.h>
+#include <errno.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch-tegra/clk_rst.h>
-#include <asm/arch-tegra20/tegra20_sflash.h>
 #include <spi.h>
 #include <fdtdec.h>
+#include "tegra_spi.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -64,129 +65,75 @@ struct spi_regs {
        u32 rx_fifo;    /* SPI_RX_FIFO_0 register */
 };
 
-struct tegra_spi_ctrl {
+struct tegra20_sflash_priv {
        struct spi_regs *regs;
        unsigned int freq;
        unsigned int mode;
        int periph_id;
        int valid;
+       int last_transaction_us;
 };
 
-struct tegra_spi_slave {
-       struct spi_slave slave;
-       struct tegra_spi_ctrl *ctrl;
-};
-
-/* tegra20 only supports one SFLASH controller */
-static struct tegra_spi_ctrl spi_ctrls[1];
-
-static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
-{
-       return container_of(slave, struct tegra_spi_slave, slave);
-}
-
-int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs)
+int tegra20_sflash_cs_info(struct udevice *bus, unsigned int cs,
+                          struct spi_cs_info *info)
 {
        /* Tegra20 SPI-Flash - only 1 device ('bus/cs') */
-       if (bus != 0 || cs != 0)
-               return 0;
+       if (cs != 0)
+               return -ENODEV;
        else
-               return 1;
+               return 0;
 }
 
-struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs,
-                                 unsigned int max_hz, unsigned int mode)
+static int tegra20_sflash_ofdata_to_platdata(struct udevice *bus)
 {
-       struct tegra_spi_slave *spi;
+       struct tegra_spi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
 
-       if (!spi_cs_is_valid(bus, cs)) {
-               printf("SPI error: unsupported bus %d / chip select %d\n",
-                      bus, cs);
-               return NULL;
-       }
+       plat->base = fdtdec_get_addr(blob, node, "reg");
+       plat->periph_id = clock_decode_periph_id(blob, node);
 
-       if (max_hz > TEGRA_SPI_MAX_FREQ) {
-               printf("SPI error: unsupported frequency %d Hz. Max frequency"
-                       " is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
-               return NULL;
+       if (plat->periph_id == PERIPH_ID_NONE) {
+               debug("%s: could not decode periph id %d\n", __func__,
+                     plat->periph_id);
+               return -FDT_ERR_NOTFOUND;
        }
 
-       spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs);
-       if (!spi) {
-               printf("SPI error: malloc of SPI structure failed\n");
-               return NULL;
-       }
-       spi->ctrl = &spi_ctrls[bus];
-       if (!spi->ctrl) {
-               printf("SPI error: could not find controller for bus %d\n",
-                      bus);
-               return NULL;
-       }
+       /* Use 500KHz as a suitable default */
+       plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+                                       500000);
+       plat->deactivate_delay_us = fdtdec_get_int(blob, node,
+                                       "spi-deactivate-delay", 0);
+       debug("%s: base=%#08lx, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
+             __func__, plat->base, plat->periph_id, plat->frequency,
+             plat->deactivate_delay_us);
 
-       if (max_hz < spi->ctrl->freq) {
-               debug("%s: limiting frequency from %u to %u\n", __func__,
-                     spi->ctrl->freq, max_hz);
-               spi->ctrl->freq = max_hz;
-       }
-       spi->ctrl->mode = mode;
-
-       return &spi->slave;
+       return 0;
 }
 
-void tegra20_spi_free_slave(struct spi_slave *slave)
+static int tegra20_sflash_probe(struct udevice *bus)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-
-       free(spi);
-}
+       struct tegra_spi_platdata *plat = dev_get_platdata(bus);
+       struct tegra20_sflash_priv *priv = dev_get_priv(bus);
 
-int tegra20_spi_init(int *node_list, int count)
-{
-       struct tegra_spi_ctrl *ctrl;
-       int i;
-       int node = 0;
-       int found = 0;
-
-       for (i = 0; i < count; i++) {
-               ctrl = &spi_ctrls[i];
-               node = node_list[i];
-
-               ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
-                                                               node, "reg");
-               if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
-                       debug("%s: no slink register found\n", __func__);
-                       continue;
-               }
-               ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
-                                           "spi-max-frequency", 0);
-               if (!ctrl->freq) {
-                       debug("%s: no slink max frequency found\n", __func__);
-                       continue;
-               }
+       priv->regs = (struct spi_regs *)plat->base;
 
-               ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
-               if (ctrl->periph_id == PERIPH_ID_NONE) {
-                       debug("%s: could not decode periph id\n", __func__);
-                       continue;
-               }
-               ctrl->valid = 1;
-               found = 1;
+       priv->last_transaction_us = timer_get_us();
+       priv->freq = plat->frequency;
+       priv->periph_id = plat->periph_id;
 
-               debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
-                     __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
-       }
-       return !found;
+       return 0;
 }
 
-int tegra20_spi_claim_bus(struct spi_slave *slave)
+static int tegra20_sflash_claim_bus(struct udevice *bus)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct tegra20_sflash_priv *priv = dev_get_priv(bus);
+       struct spi_regs *regs = priv->regs;
        u32 reg;
 
        /* Change SPI clock to correct frequency, PLLP_OUT0 source */
-       clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
-                              spi->ctrl->freq);
+       clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH,
+                              priv->freq);
 
        /* Clear stale status here */
        reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
@@ -197,8 +144,8 @@ int tegra20_spi_claim_bus(struct spi_slave *slave)
        /*
         * Use sw-controlled CS, so we can clock in data after ReadID, etc.
         */
-       reg = (spi->ctrl->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
-       if (spi->ctrl->mode & 2)
+       reg = (priv->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
+       if (priv->mode & 2)
                reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
        clrsetbits_le32(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
                SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
@@ -215,37 +162,54 @@ int tegra20_spi_claim_bus(struct spi_slave *slave)
        return 0;
 }
 
-void tegra20_spi_cs_activate(struct spi_slave *slave)
+static void spi_cs_activate(struct udevice *dev)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra_spi_platdata *pdata = dev_get_platdata(bus);
+       struct tegra20_sflash_priv *priv = dev_get_priv(bus);
+
+       /* If it's too soon to do another transaction, wait */
+       if (pdata->deactivate_delay_us &&
+           priv->last_transaction_us) {
+               ulong delay_us;         /* The delay completed so far */
+               delay_us = timer_get_us() - priv->last_transaction_us;
+               if (delay_us < pdata->deactivate_delay_us)
+                       udelay(pdata->deactivate_delay_us - delay_us);
+       }
 
        /* CS is negated on Tegra, so drive a 1 to get a 0 */
-       setbits_le32(&regs->command, SPI_CMD_CS_VAL);
+       setbits_le32(&priv->regs->command, SPI_CMD_CS_VAL);
 }
 
-void tegra20_spi_cs_deactivate(struct spi_slave *slave)
+static void spi_cs_deactivate(struct udevice *dev)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra_spi_platdata *pdata = dev_get_platdata(bus);
+       struct tegra20_sflash_priv *priv = dev_get_priv(bus);
 
        /* CS is negated on Tegra, so drive a 0 to get a 1 */
-       clrbits_le32(&regs->command, SPI_CMD_CS_VAL);
+       clrbits_le32(&priv->regs->command, SPI_CMD_CS_VAL);
+
+       /* Remember time of this transaction so we can honour the bus delay */
+       if (pdata->deactivate_delay_us)
+               priv->last_transaction_us = timer_get_us();
 }
 
-int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-               const void *data_out, void *data_in, unsigned long flags)
+static int tegra20_sflash_xfer(struct udevice *dev, unsigned int bitlen,
+                            const void *data_out, void *data_in,
+                            unsigned long flags)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra20_sflash_priv *priv = dev_get_priv(bus);
+       struct spi_regs *regs = priv->regs;
        u32 reg, tmpdout, tmpdin = 0;
        const u8 *dout = data_out;
        u8 *din = data_in;
        int num_bytes;
        int ret;
 
-       debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
-             slave->bus, slave->cs, *(u8 *)dout, *(u8 *)din, bitlen);
+       debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
+             __func__, bus->seq, spi_chip_select(dev), dout, din, bitlen);
        if (bitlen % 8)
                return -1;
        num_bytes = bitlen / 8;
@@ -262,7 +226,7 @@ int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
        debug("spi_xfer: COMMAND = %08x\n", readl(&regs->command));
 
        if (flags & SPI_XFER_BEGIN)
-               spi_cs_activate(slave);
+               spi_cs_activate(dev);
 
        /* handle data in 32-bit chunks */
        while (num_bytes > 0) {
@@ -327,7 +291,7 @@ int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
        }
 
        if (flags & SPI_XFER_END)
-               spi_cs_deactivate(slave);
+               spi_cs_deactivate(dev);
 
        debug("spi_xfer: transfer ended. Value=%08x, status = %08x\n",
                tmpdin, readl(&regs->status));
@@ -339,3 +303,51 @@ int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
        return 0;
 }
+
+static int tegra20_sflash_set_speed(struct udevice *bus, uint speed)
+{
+       struct tegra_spi_platdata *plat = bus->platdata;
+       struct tegra20_sflash_priv *priv = dev_get_priv(bus);
+
+       if (speed > plat->frequency)
+               speed = plat->frequency;
+       priv->freq = speed;
+       debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
+
+       return 0;
+}
+
+static int tegra20_sflash_set_mode(struct udevice *bus, uint mode)
+{
+       struct tegra20_sflash_priv *priv = dev_get_priv(bus);
+
+       priv->mode = mode;
+       debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
+
+       return 0;
+}
+
+static const struct dm_spi_ops tegra20_sflash_ops = {
+       .claim_bus      = tegra20_sflash_claim_bus,
+       .xfer           = tegra20_sflash_xfer,
+       .set_speed      = tegra20_sflash_set_speed,
+       .set_mode       = tegra20_sflash_set_mode,
+       .cs_info        = tegra20_sflash_cs_info,
+};
+
+static const struct udevice_id tegra20_sflash_ids[] = {
+       { .compatible = "nvidia,tegra20-sflash" },
+       { }
+};
+
+U_BOOT_DRIVER(tegra20_sflash) = {
+       .name   = "tegra20_sflash",
+       .id     = UCLASS_SPI,
+       .of_match = tegra20_sflash_ids,
+       .ops    = &tegra20_sflash_ops,
+       .ofdata_to_platdata = tegra20_sflash_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
+       .priv_auto_alloc_size = sizeof(struct tegra20_sflash_priv),
+       .per_child_auto_alloc_size      = sizeof(struct spi_slave),
+       .probe  = tegra20_sflash_probe,
+};
index 664de6e916613f4571fadb9fbd46497a32131fce..213fa5f7939a848889e0168d1991040dd9830a61 100644 (file)
  */
 
 #include <common.h>
-#include <malloc.h>
+#include <dm.h>
 #include <asm/io.h>
-#include <asm/gpio.h>
 #include <asm/arch/clock.h>
 #include <asm/arch-tegra/clk_rst.h>
-#include <asm/arch-tegra20/tegra20_slink.h>
 #include <spi.h>
 #include <fdtdec.h>
+#include "tegra_spi.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -87,130 +86,70 @@ struct spi_regs {
        u32 rx_fifo;    /* SLINK_RX_FIFO_0 reg off 180h */
 };
 
-struct tegra_spi_ctrl {
+struct tegra30_spi_priv {
        struct spi_regs *regs;
        unsigned int freq;
        unsigned int mode;
        int periph_id;
        int valid;
+       int last_transaction_us;
 };
 
 struct tegra_spi_slave {
        struct spi_slave slave;
-       struct tegra_spi_ctrl *ctrl;
+       struct tegra30_spi_priv *ctrl;
 };
 
-static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA_SLINK_CTRLS];
-
-static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
-{
-       return container_of(slave, struct tegra_spi_slave, slave);
-}
-
-int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs)
+static int tegra30_spi_ofdata_to_platdata(struct udevice *bus)
 {
-       if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
-               return 0;
-       else
-               return 1;
-}
+       struct tegra_spi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
 
-struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs,
-               unsigned int max_hz, unsigned int mode)
-{
-       struct tegra_spi_slave *spi;
+       plat->base = fdtdec_get_addr(blob, node, "reg");
+       plat->periph_id = clock_decode_periph_id(blob, node);
 
-       debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__,
-               bus, cs, max_hz, mode);
-
-       if (!spi_cs_is_valid(bus, cs)) {
-               printf("SPI error: unsupported bus %d / chip select %d\n",
-                      bus, cs);
-               return NULL;
-       }
-
-       if (max_hz > TEGRA_SPI_MAX_FREQ) {
-               printf("SPI error: unsupported frequency %d Hz. Max frequency"
-                       " is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
-               return NULL;
+       if (plat->periph_id == PERIPH_ID_NONE) {
+               debug("%s: could not decode periph id %d\n", __func__,
+                     plat->periph_id);
+               return -FDT_ERR_NOTFOUND;
        }
 
-       spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs);
-       if (!spi) {
-               printf("SPI error: malloc of SPI structure failed\n");
-               return NULL;
-       }
-       spi->ctrl = &spi_ctrls[bus];
-       if (!spi->ctrl) {
-               printf("SPI error: could not find controller for bus %d\n",
-                      bus);
-               return NULL;
-       }
+       /* Use 500KHz as a suitable default */
+       plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+                                       500000);
+       plat->deactivate_delay_us = fdtdec_get_int(blob, node,
+                                       "spi-deactivate-delay", 0);
+       debug("%s: base=%#08lx, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
+             __func__, plat->base, plat->periph_id, plat->frequency,
+             plat->deactivate_delay_us);
 
-       if (max_hz < spi->ctrl->freq) {
-               debug("%s: limiting frequency from %u to %u\n", __func__,
-                     spi->ctrl->freq, max_hz);
-               spi->ctrl->freq = max_hz;
-       }
-       spi->ctrl->mode = mode;
-
-       return &spi->slave;
+       return 0;
 }
 
-void tegra30_spi_free_slave(struct spi_slave *slave)
+static int tegra30_spi_probe(struct udevice *bus)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-
-       free(spi);
-}
+       struct tegra_spi_platdata *plat = dev_get_platdata(bus);
+       struct tegra30_spi_priv *priv = dev_get_priv(bus);
 
-int tegra30_spi_init(int *node_list, int count)
-{
-       struct tegra_spi_ctrl *ctrl;
-       int i;
-       int node = 0;
-       int found = 0;
-
-       for (i = 0; i < count; i++) {
-               ctrl = &spi_ctrls[i];
-               node = node_list[i];
-
-               ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
-                                                               node, "reg");
-               if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
-                       debug("%s: no slink register found\n", __func__);
-                       continue;
-               }
-               ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
-                                           "spi-max-frequency", 0);
-               if (!ctrl->freq) {
-                       debug("%s: no slink max frequency found\n", __func__);
-                       continue;
-               }
+       priv->regs = (struct spi_regs *)plat->base;
 
-               ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
-               if (ctrl->periph_id == PERIPH_ID_NONE) {
-                       debug("%s: could not decode periph id\n", __func__);
-                       continue;
-               }
-               ctrl->valid = 1;
-               found = 1;
+       priv->last_transaction_us = timer_get_us();
+       priv->freq = plat->frequency;
+       priv->periph_id = plat->periph_id;
 
-               debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
-                     __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
-       }
-       return !found;
+       return 0;
 }
 
-int tegra30_spi_claim_bus(struct spi_slave *slave)
+static int tegra30_spi_claim_bus(struct udevice *bus)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct tegra30_spi_priv *priv = dev_get_priv(bus);
+       struct spi_regs *regs = priv->regs;
        u32 reg;
 
        /* Change SPI clock to correct frequency, PLLP_OUT0 source */
-       clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
-                              spi->ctrl->freq);
+       clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH,
+                              priv->freq);
 
        /* Clear stale status here */
        reg = SLINK_STAT_RDY | SLINK_STAT_RXF_FLUSH | SLINK_STAT_TXF_FLUSH | \
@@ -227,29 +166,46 @@ int tegra30_spi_claim_bus(struct spi_slave *slave)
        return 0;
 }
 
-void tegra30_spi_cs_activate(struct spi_slave *slave)
+static void spi_cs_activate(struct udevice *dev)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra_spi_platdata *pdata = dev_get_platdata(bus);
+       struct tegra30_spi_priv *priv = dev_get_priv(bus);
+
+       /* If it's too soon to do another transaction, wait */
+       if (pdata->deactivate_delay_us &&
+           priv->last_transaction_us) {
+               ulong delay_us;         /* The delay completed so far */
+               delay_us = timer_get_us() - priv->last_transaction_us;
+               if (delay_us < pdata->deactivate_delay_us)
+                       udelay(pdata->deactivate_delay_us - delay_us);
+       }
 
        /* CS is negated on Tegra, so drive a 1 to get a 0 */
-       setbits_le32(&regs->command, SLINK_CMD_CS_VAL);
+       setbits_le32(&priv->regs->command, SLINK_CMD_CS_VAL);
 }
 
-void tegra30_spi_cs_deactivate(struct spi_slave *slave)
+static void spi_cs_deactivate(struct udevice *dev)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra_spi_platdata *pdata = dev_get_platdata(bus);
+       struct tegra30_spi_priv *priv = dev_get_priv(bus);
 
        /* CS is negated on Tegra, so drive a 0 to get a 1 */
-       clrbits_le32(&regs->command, SLINK_CMD_CS_VAL);
+       clrbits_le32(&priv->regs->command, SLINK_CMD_CS_VAL);
+
+       /* Remember time of this transaction so we can honour the bus delay */
+       if (pdata->deactivate_delay_us)
+               priv->last_transaction_us = timer_get_us();
 }
 
-int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-               const void *data_out, void *data_in, unsigned long flags)
+static int tegra30_spi_xfer(struct udevice *dev, unsigned int bitlen,
+                           const void *data_out, void *data_in,
+                           unsigned long flags)
 {
-       struct tegra_spi_slave *spi = to_tegra_spi(slave);
-       struct spi_regs *regs = spi->ctrl->regs;
+       struct udevice *bus = dev->parent;
+       struct tegra30_spi_priv *priv = dev_get_priv(bus);
+       struct spi_regs *regs = priv->regs;
        u32 reg, tmpdout, tmpdin = 0;
        const u8 *dout = data_out;
        u8 *din = data_in;
@@ -257,7 +213,7 @@ int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
        int ret;
 
        debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
-             __func__, slave->bus, slave->cs, dout, din, bitlen);
+             __func__, bus->seq, spi_chip_select(dev), dout, din, bitlen);
        if (bitlen % 8)
                return -1;
        num_bytes = bitlen / 8;
@@ -276,11 +232,11 @@ int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
        clrsetbits_le32(&regs->command2, SLINK_CMD2_SS_EN_MASK,
                        SLINK_CMD2_TXEN | SLINK_CMD2_RXEN |
-                       (slave->cs << SLINK_CMD2_SS_EN_SHIFT));
+                       (spi_chip_select(dev) << SLINK_CMD2_SS_EN_SHIFT));
        debug("%s entry: COMMAND2 = %08x\n", __func__, readl(&regs->command2));
 
        if (flags & SPI_XFER_BEGIN)
-               spi_cs_activate(slave);
+               spi_cs_activate(dev);
 
        /* handle data in 32-bit chunks */
        while (num_bytes > 0) {
@@ -344,7 +300,7 @@ int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
        }
 
        if (flags & SPI_XFER_END)
-               spi_cs_deactivate(slave);
+               spi_cs_deactivate(dev);
 
        debug("%s: transfer ended. Value=%08x, status = %08x\n",
              __func__, tmpdin, readl(&regs->status));
@@ -357,3 +313,54 @@ int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
        return 0;
 }
+
+static int tegra30_spi_set_speed(struct udevice *bus, uint speed)
+{
+       struct tegra_spi_platdata *plat = bus->platdata;
+       struct tegra30_spi_priv *priv = dev_get_priv(bus);
+
+       if (speed > plat->frequency)
+               speed = plat->frequency;
+       priv->freq = speed;
+       debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
+
+       return 0;
+}
+
+static int tegra30_spi_set_mode(struct udevice *bus, uint mode)
+{
+       struct tegra30_spi_priv *priv = dev_get_priv(bus);
+
+       priv->mode = mode;
+       debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
+
+       return 0;
+}
+
+static const struct dm_spi_ops tegra30_spi_ops = {
+       .claim_bus      = tegra30_spi_claim_bus,
+       .xfer           = tegra30_spi_xfer,
+       .set_speed      = tegra30_spi_set_speed,
+       .set_mode       = tegra30_spi_set_mode,
+       /*
+        * cs_info is not needed, since we require all chip selects to be
+        * in the device tree explicitly
+        */
+};
+
+static const struct udevice_id tegra30_spi_ids[] = {
+       { .compatible = "nvidia,tegra20-slink" },
+       { }
+};
+
+U_BOOT_DRIVER(tegra30_spi) = {
+       .name   = "tegra20_slink",
+       .id     = UCLASS_SPI,
+       .of_match = tegra30_spi_ids,
+       .ops    = &tegra30_spi_ops,
+       .ofdata_to_platdata = tegra30_spi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct tegra_spi_platdata),
+       .priv_auto_alloc_size = sizeof(struct tegra30_spi_priv),
+       .per_child_auto_alloc_size      = sizeof(struct spi_slave),
+       .probe  = tegra30_spi_probe,
+};
diff --git a/drivers/spi/tegra_spi.h b/drivers/spi/tegra_spi.h
new file mode 100644 (file)
index 0000000..fb2b50f
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+struct tegra_spi_platdata {
+       enum periph_id periph_id;
+       int frequency;          /* Default clock frequency, -1 for none */
+       ulong base;
+       uint deactivate_delay_us;       /* Delay to wait after deactivate */
+};
index 6323c508375af8ce3b98009a85bfbc2f5e8a5564..936d006ba414ca2bfea76ac5ab0b0d5dccc944ab 100644 (file)
@@ -119,15 +119,12 @@ static struct descriptor {
 #define ehci_is_TDI()  (0)
 #endif
 
-int __ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg)
+__weak int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg)
 {
        return PORTSC_PSPD(reg);
 }
 
-int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg)
-       __attribute__((weak, alias("__ehci_get_port_speed")));
-
-void __ehci_set_usbmode(int index)
+__weak void ehci_set_usbmode(int index)
 {
        uint32_t tmp;
        uint32_t *reg_ptr;
@@ -141,17 +138,11 @@ void __ehci_set_usbmode(int index)
        ehci_writel(reg_ptr, tmp);
 }
 
-void ehci_set_usbmode(int index)
-       __attribute__((weak, alias("__ehci_set_usbmode")));
-
-void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
+__weak void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
 {
        mdelay(50);
 }
 
-void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
-       __attribute__((weak, alias("__ehci_powerup_fixup")));
-
 static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
 {
        uint32_t result;
@@ -1323,7 +1314,7 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
 }
 
 /* Do not free buffers associated with QHs, they're owned by someone else */
-int
+static int
 destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
 {
        struct ehci_ctrl *ctrl = dev->controller;
index 52c43fdc5aaa1fdc2a99ed3177c65c35b3a2c979..1a5fd6eefc296bfee80552530cbb7237dffd3792 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/arch/cpu.h>
 
 #if defined(CONFIG_KIRKWOOD)
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
 #elif defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
 #endif
index 923192787996f70942b766c1c9086f787ee04e3a..6aa50cb4f966c70d3495ea5588db8b42bb40bcd7 100644 (file)
@@ -944,7 +944,7 @@ static void parse_putc(const char c)
                CURSOR_SET;
 }
 
-void video_putc(struct stdio_dev *dev, const char c)
+static void video_putc(struct stdio_dev *dev, const char c)
 {
 #ifdef CONFIG_CFB_CONSOLE_ANSI
        int i;
@@ -1158,7 +1158,7 @@ void video_putc(struct stdio_dev *dev, const char c)
                flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE);
 }
 
-void video_puts(struct stdio_dev *dev, const char *s)
+static void video_puts(struct stdio_dev *dev, const char *s)
 {
        int count = strlen(s);
 
@@ -1171,14 +1171,11 @@ void video_puts(struct stdio_dev *dev, const char *s)
  * video_set_lut() if they do not support 8 bpp format.
  * Implement weak default function instead.
  */
-void __video_set_lut(unsigned int index, unsigned char r,
+__weak void video_set_lut(unsigned int index, unsigned char r,
                     unsigned char g, unsigned char b)
 {
 }
 
-void video_set_lut(unsigned int, unsigned char, unsigned char, unsigned char)
-       __attribute__ ((weak, alias("__video_set_lut")));
-
 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
 
 #define FILL_8BIT_332RGB(r,g,b)        {                       \
@@ -2240,15 +2237,12 @@ static int video_init(void)
  * Implement a weak default function for boards that optionally
  * need to skip the video initialization.
  */
-int __board_video_skip(void)
+__weak int board_video_skip(void)
 {
        /* As default, don't skip test */
        return 0;
 }
 
-int board_video_skip(void)
-       __attribute__ ((weak, alias("__board_video_skip")));
-
 int drv_video_init(void)
 {
        int skip_dev_init;
index 180a3b41499dba25c9815adb57345678772482fa..be35b982acd12f6019281248145a06124a483720 100644 (file)
@@ -58,54 +58,38 @@ static void exynos_lcd_init(vidinfo_t *vid)
        lcd_set_flush_dcache(1);
 }
 
-void __exynos_cfg_lcd_gpio(void)
+__weak void exynos_cfg_lcd_gpio(void)
 {
 }
-void exynos_cfg_lcd_gpio(void)
-       __attribute__((weak, alias("__exynos_cfg_lcd_gpio")));
 
-void __exynos_backlight_on(unsigned int onoff)
+__weak void exynos_backlight_on(unsigned int onoff)
 {
 }
-void exynos_backlight_on(unsigned int onoff)
-       __attribute__((weak, alias("__exynos_cfg_lcd_gpio")));
 
-void __exynos_reset_lcd(void)
+__weak void exynos_reset_lcd(void)
 {
 }
-void exynos_reset_lcd(void)
-       __attribute__((weak, alias("__exynos_reset_lcd")));
 
-void __exynos_lcd_power_on(void)
+__weak void exynos_lcd_power_on(void)
 {
 }
-void exynos_lcd_power_on(void)
-       __attribute__((weak, alias("__exynos_lcd_power_on")));
 
-void __exynos_cfg_ldo(void)
+__weak void exynos_cfg_ldo(void)
 {
 }
-void exynos_cfg_ldo(void)
-       __attribute__((weak, alias("__exynos_cfg_ldo")));
 
-void __exynos_enable_ldo(unsigned int onoff)
+__weak void exynos_enable_ldo(unsigned int onoff)
 {
 }
-void exynos_enable_ldo(unsigned int onoff)
-       __attribute__((weak, alias("__exynos_enable_ldo")));
 
-void __exynos_backlight_reset(void)
+__weak void exynos_backlight_reset(void)
 {
 }
-void exynos_backlight_reset(void)
-       __attribute__((weak, alias("__exynos_backlight_reset")));
 
-int __exynos_lcd_misc_init(vidinfo_t *vid)
+__weak int exynos_lcd_misc_init(vidinfo_t *vid)
 {
        return 0;
 }
-int exynos_lcd_misc_init(vidinfo_t *vid)
-       __attribute__((weak, alias("__exynos_lcd_misc_init")));
 
 static void lcd_panel_on(vidinfo_t *vid)
 {
index 8d4e9254784d8d89050f3b20bbf6ac75486fe66e..5873531953316a25799c020206328bd84280b97d 100644 (file)
@@ -379,7 +379,7 @@ static struct clk pixel_clk[] = {
 /*
  * This function resets IPU
  */
-void ipu_reset(void)
+static void ipu_reset(void)
 {
        u32 *reg;
        u32 value;
index 48fee992a180029b4adbe30e53b9f39491acde79..4faeafb6351d4d3e75376e704b479ebad4a3c6b3 100644 (file)
@@ -377,7 +377,7 @@ static struct dp_csc_param_t dp_csc_array[CSC_NUM][CSC_NUM] = {
 static enum csc_type_t fg_csc_type = CSC_NONE, bg_csc_type = CSC_NONE;
 static int color_key_4rgb = 1;
 
-void ipu_dp_csc_setup(int dp, struct dp_csc_param_t dp_csc_param,
+static void ipu_dp_csc_setup(int dp, struct dp_csc_param_t dp_csc_param,
                        unsigned char srm_mode_update)
 {
        u32 reg;
@@ -605,17 +605,6 @@ void ipu_dc_uninit(int dc_chan)
        }
 }
 
-int ipu_chan_is_interlaced(ipu_channel_t channel)
-{
-       if (channel == MEM_DC_SYNC)
-               return !!(__raw_readl(DC_WR_CH_CONF_1) &
-                         DC_WR_CH_CONF_FIELD_MODE);
-       else if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC))
-               return !!(__raw_readl(DC_WR_CH_CONF_5) &
-                         DC_WR_CH_CONF_FIELD_MODE);
-       return 0;
-}
-
 void ipu_dp_dc_enable(ipu_channel_t channel)
 {
        int di;
@@ -782,7 +771,7 @@ void ipu_init_dc_mappings(void)
        ipu_dc_map_config(4, 2, 21, 0xFC);
 }
 
-int ipu_pixfmt_to_map(uint32_t fmt)
+static int ipu_pixfmt_to_map(uint32_t fmt)
 {
        switch (fmt) {
        case IPU_PIX_FMT_GENERIC:
index b20c19c426d5cb0e1baaea409cc7c361bac0979c..1fa95314fc4621857114bcef2e98e50a60f163b7 100644 (file)
@@ -36,7 +36,7 @@ static struct fb_videomode const *gmode;
 static uint8_t gdisp;
 static uint32_t gpixfmt;
 
-void fb_videomode_to_var(struct fb_var_screeninfo *var,
+static void fb_videomode_to_var(struct fb_var_screeninfo *var,
                         const struct fb_videomode *mode)
 {
        var->xres = mode->xres;
index 60539d8a9d24fc113e9d8f839a9f84244fbe1a23..f81b51aa301feec3f13dc787c95626c2f84012a8 100644 (file)
  */
 
 /**
- * Request a gpio. This should be called before any of the other functions
- * are used on this gpio.
+ * Request a GPIO. This should be called before any of the other functions
+ * are used on this GPIO.
+ *
+ * Note: With driver model, the label is allocated so there is no need for
+ * the caller to preserve it.
  *
  * @param gp   GPIO number
  * @param label        User label for this GPIO
@@ -80,7 +83,7 @@ int gpio_get_value(unsigned gpio);
 int gpio_set_value(unsigned gpio, int value);
 
 /* State of a GPIO, as reported by get_function() */
-enum {
+enum gpio_func_t {
        GPIOF_INPUT = 0,
        GPIOF_OUTPUT,
        GPIOF_UNUSED,           /* Not claimed */
@@ -92,6 +95,66 @@ enum {
 
 struct udevice;
 
+/**
+ * gpio_get_status() - get the current GPIO status as a string
+ *
+ * Obtain the current GPIO status as a string which can be presented to the
+ * user. A typical string is:
+ *
+ * "b4:  in: 1 [x] sdmmc_cd"
+ *
+ * which means this is GPIO bank b, offset 4, currently set to input, current
+ * value 1, [x] means that it is requested and the owner is 'sdmmc_cd'
+ *
+ * @dev:       Device to check
+ * @offset:    Offset of device GPIO to check
+ * @buf:       Place to put string
+ * @buffsize:  Size of string including \0
+ */
+int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize);
+
+/**
+ * gpio_get_function() - get the current function for a GPIO pin
+ *
+ * Note this returns GPIOF_UNUSED if the GPIO is not requested.
+ *
+ * @dev:       Device to check
+ * @offset:    Offset of device GPIO to check
+ * @namep:     If non-NULL, this is set to the nane given when the GPIO
+ *             was requested, or -1 if it has not been requested
+ * @return  -ENODATA if the driver returned an unknown function,
+ * -ENODEV if the device is not active, -EINVAL if the offset is invalid.
+ * GPIOF_UNUSED if the GPIO has not been requested. Otherwise returns the
+ * function from enum gpio_func_t.
+ */
+int gpio_get_function(struct udevice *dev, int offset, const char **namep);
+
+/**
+ * gpio_get_raw_function() - get the current raw function for a GPIO pin
+ *
+ * Note this does not return GPIOF_UNUSED - it will always return the GPIO
+ * driver's view of a pin function, even if it is not correctly set up.
+ *
+ * @dev:       Device to check
+ * @offset:    Offset of device GPIO to check
+ * @namep:     If non-NULL, this is set to the nane given when the GPIO
+ *             was requested, or -1 if it has not been requested
+ * @return  -ENODATA if the driver returned an unknown function,
+ * -ENODEV if the device is not active, -EINVAL if the offset is invalid.
+ * Otherwise returns the function from enum gpio_func_t.
+ */
+int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep);
+
+/**
+ * gpio_requestf() - request a GPIO using a format string for the owner
+ *
+ * This is a helper function for gpio_request(). It allows you to provide
+ * a printf()-format string for the GPIO owner. It calls gpio_request() with
+ * the string that is created
+ */
+int gpio_requestf(unsigned gpio, const char *fmt, ...)
+               __attribute__ ((format (__printf__, 2, 3)));
+
 /**
  * struct struct dm_gpio_ops - Driver model GPIO operations
  *
@@ -102,7 +165,7 @@ struct udevice;
  * new DM GPIO API, this should be really easy to flip over to the Linux
  * GPIO API-alike interface.
  *
- * Akso it would be useful to standardise additional functions like
+ * Also it would be useful to standardise additional functions like
  * pullup, slew rate and drive strength.
  *
  * gpio_request)( and gpio_free() are optional - if NULL then they will
@@ -115,7 +178,7 @@ struct udevice;
  * SoCs there may be many banks and therefore many devices all referring
  * to the different IO addresses within the SoC.
  *
- * The uclass combines all GPIO devices togther to provide a consistent
+ * The uclass combines all GPIO devices together to provide a consistent
  * numbering from 0 to n-1, where n is the number of GPIOs in total across
  * all devices. Be careful not to confuse offset with gpio in the parameters.
  */
@@ -135,15 +198,13 @@ struct dm_gpio_ops {
         * @return current function - GPIOF_...
         */
        int (*get_function)(struct udevice *dev, unsigned offset);
-       int (*get_state)(struct udevice *dev, unsigned offset, char *state,
-                        int maxlen);
 };
 
 /**
  * struct gpio_dev_priv - information about a device used by the uclass
  *
  * The uclass combines all active GPIO devices into a unified numbering
- * scheme. To do this it maintains some private information aobut each
+ * scheme. To do this it maintains some private information about each
  * device.
  *
  * To implement driver model support in your GPIO driver, add a probe
@@ -157,11 +218,14 @@ struct dm_gpio_ops {
  * @gpio_base: Base GPIO number for this device. For the first active device
  * this will be 0; the numbering for others will follow sequentially so that
  * @gpio_base for device 1 will equal the number of GPIOs in device 0.
+ * @name: Array of pointers to the name for each GPIO in this bank. The
+ * value of the pointer will be NULL if the GPIO has not been claimed.
  */
 struct gpio_dev_priv {
        const char *bank_name;
        unsigned gpio_count;
        unsigned gpio_base;
+       char **name;
 };
 
 /* Access the GPIO operations for a device */
@@ -193,4 +257,6 @@ const char *gpio_get_bank_info(struct udevice *dev, int *offset_count);
 int gpio_lookup_name(const char *name, struct udevice **devp,
                     unsigned int *offsetp, unsigned int *gpiop);
 
+int name_to_gpio(const char *name);
+
 #endif /* _ASM_GENERIC_GPIO_H_ */
index 694d6fc080fcc5c1b6759f6e74bdf7ba9a328755..b3d1a620daeaf0041679e5caef49adbb0be4e2e8 100644 (file)
@@ -54,4 +54,6 @@ int bootm_find_ramdisk_fdt(int flag, int argc, char * const argv[]);
 int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
                    int states, bootm_headers_t *images, int boot_progress);
 
+void arch_preboot_os(void);
+
 #endif
index 87bf906b263e09a8a25527f7238cbb6352de953d..df13ab2f63eddbb075d5d2cc2bdffacccd88e68b 100644 (file)
@@ -159,6 +159,9 @@ enum bootstage_id {
        /* Next 10 IDs used by BOOTSTAGE_SUB_... */
        BOOTSTAGE_ID_FIT_RD_START = 120,        /* Ramdisk stages */
 
+       /* Next 10 IDs used by BOOTSTAGE_SUB_... */
+       BOOTSTAGE_ID_FIT_SETUP_START = 130,     /* x86 setup stages */
+
        BOOTSTAGE_ID_IDE_FIT_READ = 140,
        BOOTSTAGE_ID_IDE_FIT_READ_OK,
 
index d5020c8c45d1afc515e02433ea2513ab6b99d28e..bcf6c7e9502f479b9fe533765f28efdb97132eda 100644 (file)
@@ -636,13 +636,6 @@ struct stdio_dev;
 int serial_stub_getc(struct stdio_dev *sdev);
 int serial_stub_tstc(struct stdio_dev *sdev);
 
-void   _serial_setbrg (const int);
-void   _serial_putc   (const char, const int);
-void   _serial_putc_raw(const char, const int);
-void   _serial_puts   (const char *, const int);
-int    _serial_getc   (const int);
-int    _serial_tstc   (const int);
-
 /* $(CPU)/speed.c */
 int    get_clocks (void);
 int    get_clocks_866 (void);
index 76818f673f2810c69520067a7a10e2b34ed4515a..7d8daa2b8e5332f421b9bb616812d494927f1c71 100644 (file)
 #define CONFIG_SYS_PROMPT      "=> "
 #endif
 
-#ifndef CONFIG_SYS_HZ
-#define CONFIG_SYS_HZ          1000
-#endif
-
 #ifndef CONFIG_FIT_SIGNATURE
 #define CONFIG_IMAGE_FORMAT_LEGACY
 #endif
diff --git a/include/configs/apalis_t30.h b/include/configs/apalis_t30.h
new file mode 100644 (file)
index 0000000..3cde923
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014 Marcel Ziswiler
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <linux/sizes.h>
+
+#include "tegra30-common.h"
+
+/* High-level configuration options */
+#define V_PROMPT                       "Apalis T30 # "
+#define CONFIG_TEGRA_BOARD_STRING      "Toradex Apalis T30"
+
+/* Board-specific serial config */
+#define CONFIG_SERIAL_MULTI
+#define CONFIG_TEGRA_ENABLE_UARTA
+#define CONFIG_SYS_NS16550_COM1                NV_PA_APB_UARTA_BASE
+
+#define CONFIG_MACH_TYPE               MACH_TYPE_APALIS_T30
+
+#define CONFIG_BOARD_EARLY_INIT_F
+
+/* I2C */
+#define CONFIG_SYS_I2C_TEGRA
+#define CONFIG_SYS_I2C_INIT_BOARD
+#define CONFIG_SYS_I2C_SPEED           100000
+#define CONFIG_CMD_I2C
+#define CONFIG_SYS_I2C
+
+/* SD/MMC */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_TEGRA_MMC
+#define CONFIG_CMD_MMC
+
+/* Environment in eMMC, at the end of 2nd "boot sector" */
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_OFFSET              (-CONFIG_ENV_SIZE)
+#define CONFIG_SYS_MMC_ENV_DEV         0
+#define CONFIG_SYS_MMC_ENV_PART                2
+
+/* USB Host support */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_TEGRA
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 3
+#define CONFIG_USB_STORAGE
+#define CONFIG_CMD_USB
+
+/* USB networking support */
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+
+/* PCI host support */
+#undef CONFIG_PCI      /* just define once Tegra PCIe support got merged */
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_E1000
+#undef CONFIG_E1000_NO_NVM     /* just define once E1000 driver got fixed */
+
+/* General networking support */
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_DHCP
+
+#include "tegra-common-usb-gadget.h"
+#include "tegra-common-post.h"
+
+#endif /* __CONFIG_H */
index 7cf241e31d7725b826671d8f70c0b4df3ac119ef..f7277eb1d17a0d5f3a4c613d6033bd682c3491dd 100644 (file)
 #define CONFIG_MX6
 #define CONFIG_SYS_LITTLE_ENDIAN
 #define CONFIG_MACH_TYPE               4273
-#define CONFIG_SYS_HZ                  1000
+
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+
+#define CONFIG_DM_GPIO
+#define CONFIG_CMD_GPIO
+
+#define CONFIG_DM_SERIAL
+#define CONFIG_SYS_MALLOC_F_LEN                (1 << 10)
+#endif
 
 /* Display information on boot */
 #define CONFIG_DISPLAY_CPUINFO
index 782b9d16b7a4f7c8ab1fcf1fa6e9a9647505170e..a582e255169c8188cdcd3aac8416b530191bf2c3 100644 (file)
@@ -11,7 +11,6 @@
 
 #include "tegra30-common.h"
 
-
 #define V_PROMPT                       "Colibri T30 # "
 #define CONFIG_TEGRA_BOARD_STRING      "Toradex Colibri T30"
 
index 936be145119d1e55a810ccc95bb922cb8a9b0f72..4b90dc205de82e4130547d1be44defd1ea8c208f 100644 (file)
 #define CONFIG_ZBOOT_32
 #define CONFIG_PHYSMEM
 #define CONFIG_SYS_EARLY_PCI_INIT
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
 
 #define CONFIG_LMB
 #define CONFIG_OF_LIBFDT
@@ -39,6 +45,7 @@
 #define CONFIG_BOOTSTAGE_USER_COUNT    60
 
 #define CONFIG_LZO
+#define CONFIG_FIT
 #undef CONFIG_ZLIB
 #undef CONFIG_GZIP
 
 /*-----------------------------------------------------------------------
  * Serial Configuration
  */
-#define CONFIG_CONS_INDEX              1
+#define CONFIG_COREBOOT_SERIAL
 #define CONFIG_SYS_NS16550
-#define CONFIG_SYS_NS16550_SERIAL
-#define CONFIG_SYS_NS16550_REG_SIZE    1
-#define CONFIG_SYS_NS16550_CLK         1843200
-#define CONFIG_BAUDRATE                        9600
+#define CONFIG_BAUDRATE                        115200
 #define CONFIG_SYS_BAUDRATE_TABLE      {300, 600, 1200, 2400, 4800, \
                                         9600, 19200, 38400, 115200}
-#define CONFIG_SYS_NS16550_COM1        UART0_BASE
-#define CONFIG_SYS_NS16550_COM2        UART1_BASE
 #define CONFIG_SYS_NS16550_PORT_MAPPED
 
-#define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,eserial0\0" \
-                                       "stdout=vga,eserial0,cbmem\0" \
-                                       "stderr=vga,eserial0,cbmem\0"
+#define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,serial\0" \
+                                       "stdout=vga,serial,cbmem\0" \
+                                       "stderr=vga,serial,cbmem\0"
 
 #define CONFIG_CONSOLE_MUX
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
 
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_COMMAND_HISTORY
-#define CONFIG_AUTOCOMPLETE
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_HUSH_PARSER
 
 #define CONFIG_SUPPORT_VFAT
 /************************************************************
 #define CONFIG_CMD_EXT2
 
 #define CONFIG_CMD_ZBOOT
+#define CONFIG_CMD_ELF
 
 #define CONFIG_BOOTDELAY       2
 #define CONFIG_BOOTARGS                \
  * Miscellaneous configurable options
  */
 #define CONFIG_SYS_LONGHELP
-#define CONFIG_SYS_PROMPT                      "boot > "
-#define CONFIG_SYS_CBSIZE                      256
+#define CONFIG_SYS_CBSIZE                      512
 #define CONFIG_SYS_PBSIZE                      (CONFIG_SYS_CBSIZE + \
                                                 sizeof(CONFIG_SYS_PROMPT) + \
                                                 16)
 
 #define CONFIG_SYS_MEMTEST_START               0x00100000
 #define CONFIG_SYS_MEMTEST_END                 0x01000000
-#define CONFIG_SYS_LOAD_ADDR                   0x100000
+#define CONFIG_SYS_LOAD_ADDR                   0x02000000
 
 /*-----------------------------------------------------------------------
  * SDRAM Configuration
 #define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_MONITOR_LEN                 (256 * 1024)
 #define CONFIG_SYS_MALLOC_LEN                  (0x20000 + 128 * 1024)
-
+#define CONFIG_SYS_MALLOC_F_LEN                        (1 << 10)
 
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
  */
 #define CONFIG_PCI
 
+#define CONFIG_CROS_EC
+#define CONFIG_CROS_EC_LPC
+#define CONFIG_CMD_CROS_EC
+#define CONFIG_ARCH_EARLY_INIT_R
+
 /*-----------------------------------------------------------------------
  * USB configuration
  */
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 #define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_TFTP_TSIZE
+#define CONFIG_CMD_DHCP
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
 
 #define CONFIG_CMD_USB
 
diff --git a/include/configs/db-mv784mp-gp.h b/include/configs/db-mv784mp-gp.h
new file mode 100644 (file)
index 0000000..cb03e33
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _CONFIG_DB_MV7846MP_GP_H
+#define _CONFIG_DB_MV7846MP_GP_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_ARMADA_XP               /* SOC Family Name */
+#define CONFIG_SKIP_LOWLEVEL_INIT      /* disable board lowlevel_init */
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+
+#define        CONFIG_SYS_TEXT_BASE    0x04000000
+#define CONFIG_SYS_TCLK                250000000       /* 250MHz */
+
+/*
+ * Commands configuration
+ */
+#define CONFIG_SYS_NO_FLASH            /* Declare no flash (NOR/SPI) */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_TFTPPUT
+#define CONFIG_CMD_TIME
+
+/* I2C */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MVTWSI
+#define CONFIG_I2C_MVTWSI_BASE         MVEBU_TWSI_BASE
+#define CONFIG_SYS_I2C_SLAVE           0x0
+#define CONFIG_SYS_I2C_SPEED           100000
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_SPEED                1000000
+#define CONFIG_SF_DEFAULT_MODE         SPI_MODE_3
+#define CONFIG_SPI_FLASH_STMICRO
+
+/* Environment in SPI NOR flash */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET              (1 << 20) /* 1MiB in */
+#define CONFIG_ENV_SIZE                        (64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE           (64 << 10) /* 64KiB sectors */
+
+#define CONFIG_PHY_MARVELL             /* there is a marvell phy */
+#define CONFIG_PHY_BASE_ADDR   0x10
+#define CONFIG_SYS_NETA_INTERFACE_TYPE PHY_INTERFACE_MODE_QSGMII
+#define PHY_ANEG_TIMEOUT       8000    /* PHY needs a longer aneg time */
+#define CONFIG_RESET_PHY_R
+
+#define CONFIG_SYS_CONSOLE_INFO_QUIET  /* don't print console @ startup */
+#define CONFIG_SYS_ALT_MEMTEST
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+
+#endif /* _CONFIG_DB_MV7846MP_GP_H */
index 37bdcc0f3320a447b096ec9c553cad579929e1ca..47a8420f42d37cf8a9d9d4614a25b255254e1c82 100644 (file)
@@ -89,7 +89,6 @@
 #define CONFIG_EP93XX          1               /* in a Cirrus Logic 93xx SoC */
 
 #define CONFIG_SYS_CLK_FREQ    14745600        /* EP93xx has a 14.7456 clock */
-#define CONFIG_SYS_HZ          1000            /* decr freq: 1 ms ticks */
 #undef CONFIG_USE_IRQ                          /* Don't need IRQ/FIQ */
 
 /* Monitor configuration */
index 371f32d84095bb803422a7f22428ed8c373b7b2d..6ba9bb7a1b15252fe56049ee1af3833609dee66e 100644 (file)
 #include <linux/sizes.h>
 
 #define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
+#define CONFIG_DM_SPI
+#define CONFIG_DM_SPI_FLASH
+
 #define CONFIG_ARCH_CPU_INIT
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
index 51926f721f17e6305d408dfe2e08d1816e97a5cd..137d9b0d32f2793ba8c2571ef32ff39d240f8345 100644 (file)
@@ -23,7 +23,6 @@
 #define CONFIG_ARMV7
 #define CONFIG_ARCH_CPU_INIT
 #define CONFIG_SYS_ARCH_TIMER
-#define CONFIG_SYS_HZ                  1000
 #define CONFIG_SYS_TEXT_BASE           0x0c001000
 #define CONFIG_SPL_TARGET              "u-boot-spi.gph"
 #define CONFIG_SYS_DCACHE_OFF
index 42214262f480fd5ad748a360c2177ce139f8fe9b..d1f6ea7e7b0e6d5f1efcda54eca34af3cd3d3b3c 100644 (file)
@@ -360,7 +360,6 @@ unsigned long get_board_ddr_clk(void);
 #define CONFIG_SYS_MEMTEST_END         0x9fffffff
 
 #define CONFIG_SYS_LOAD_ADDR           0x82000000
-#define CONFIG_SYS_HZ                  1000
 
 /*
  * Stack sizes
index 5868287057399b8c830adfe03124a090493d34d7..3c73af8ac39dc6663fa0db3ed5d91eb9c3601618 100644 (file)
 #define CONFIG_SYS_MEMTEST_END         0x9fffffff
 
 #define CONFIG_SYS_LOAD_ADDR           0x82000000
-#define CONFIG_SYS_HZ                  1000
 
 /*
  * Stack sizes
index a72e1f3567d22144383bf94b306bfb0c5f1112cb..6fe032c9ff64fb6b89f107095af3b9f38ca4998b 100644 (file)
 
 #define CONFIG_NR_DRAM_BANKS           3
 
-#define CONFIG_SYS_HZ                  1000
-
 #define CONFIG_HWCONFIG
 #define HWCONFIG_BUFFER_SIZE           128
 
diff --git a/include/configs/maxbcm.h b/include/configs/maxbcm.h
new file mode 100644 (file)
index 0000000..72217bd
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _CONFIG_DB_MV7846MP_GP_H
+#define _CONFIG_DB_MV7846MP_GP_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_ARMADA_XP               /* SOC Family Name */
+#define CONFIG_SKIP_LOWLEVEL_INIT      /* disable board lowlevel_init */
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+
+#define        CONFIG_SYS_TEXT_BASE    0x04000000
+#define CONFIG_SYS_TCLK                250000000       /* 250MHz */
+
+/*
+ * Commands configuration
+ */
+#define CONFIG_SYS_NO_FLASH            /* Declare no flash (NOR/SPI) */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_TFTPPUT
+#define CONFIG_CMD_TIME
+
+/* I2C */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MVTWSI
+#define CONFIG_I2C_MVTWSI_BASE         MVEBU_TWSI_BASE
+#define CONFIG_SYS_I2C_SLAVE           0x0
+#define CONFIG_SYS_I2C_SPEED           100000
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_SPEED                1000000
+#define CONFIG_SF_DEFAULT_MODE         SPI_MODE_3
+#define CONFIG_SPI_FLASH_STMICRO
+
+/* Environment in SPI NOR flash */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET              (1 << 20) /* 1MiB in */
+#define CONFIG_ENV_SIZE                        (64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE           (64 << 10) /* 64KiB sectors */
+
+#define CONFIG_PHY_MARVELL             /* there is a marvell phy */
+#define CONFIG_PHY_BASE_ADDR   0x0
+#define CONFIG_SYS_NETA_INTERFACE_TYPE PHY_INTERFACE_MODE_SGMII
+#define PHY_ANEG_TIMEOUT       8000    /* PHY needs a longer aneg time */
+#define CONFIG_RESET_PHY_R
+
+#define CONFIG_SYS_CONSOLE_INFO_QUIET  /* don't print console @ startup */
+#define CONFIG_SYS_ALT_MEMTEST
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+
+#endif /* _CONFIG_DB_MV7846MP_GP_H */
index ab8ac60df23042084726d1bc53bcd0c07fa14fb2..91bd37d6bca60fb9dfa9bc88ff61da2fad4bf8df 100644 (file)
@@ -38,6 +38,7 @@
 
 #define CONFIG_POWER_TPS65090_EC
 #define CONFIG_CROS_EC_SPI             /* Support CROS_EC over SPI */
+#define CONFIG_DM_CROS_EC
 
 #define CONFIG_USB_XHCI
 #define CONFIG_USB_XHCI_EXYNOS
index a28d7b579a6405a1b7f32e5f9ba7816681a08045..005a853f56822b3d8630cedb51f044c96c81662b 100644 (file)
  *   SoC UART     : enable CONFIG_UNIPHIER_SERIAL
  *   On-board UART: enable CONFIG_SYS_NS16550_SERIAL
  */
-#if 1
-#define CONFIG_UNIPHIER_SERIAL
-#else
+#if 0
 #define CONFIG_SYS_NS16550_SERIAL
 #endif
 
-#define CONFIG_SYS_UNIPHIER_UART_CLK    36864000
-
 #define CONFIG_SMC911X
 
 #define CONFIG_DDR_NUM_CH0 1
index b79967f7da477c351e307f2b1dc879f8932a037e..7dd6fd2a9292d8bdd73c33b5371218f25b07f128 100644 (file)
  *   SoC UART     : enable CONFIG_UNIPHIER_SERIAL
  *   On-board UART: enable CONFIG_SYS_NS16550_SERIAL
  */
-#if 1
-#define CONFIG_UNIPHIER_SERIAL
-#else
+#if 0
 #define CONFIG_SYS_NS16550_SERIAL
 #endif
 
-#define CONFIG_SYS_UNIPHIER_UART_CLK    73728000
-
 #define CONFIG_SMC911X
 
 #define CONFIG_DDR_NUM_CH0 2
index 9d391f1d74a2650b4d53ab5730e55aa7553866cd..1062aace38a7970772e6f16ed68f8a66c664ee10 100644 (file)
  *   SoC UART     : enable CONFIG_UNIPHIER_SERIAL
  *   On-board UART: enable CONFIG_SYS_NS16550_SERIAL
  */
-#if 1
-#define CONFIG_UNIPHIER_SERIAL
-#else
+#if 0
 #define CONFIG_SYS_NS16550_SERIAL
 #endif
 
-#define CONFIG_SYS_UNIPHIER_UART_CLK    80000000
-
 #define CONFIG_SMC911X
 
 #define CONFIG_DDR_NUM_CH0 1
index 6d01b61718a36d528e65794b00a9cde81773954a..ca27f9ad787008c507241464aadbbf191286a83f 100644 (file)
  */
 #define CONFIG_MACH_TYPE               MACH_TYPE_BCM2708
 
+/* Enable driver model */
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+
 /* Memory layout */
 #define CONFIG_NR_DRAM_BANKS           1
 #define CONFIG_SYS_SDRAM_BASE          0x00000000
index 0c6e9c7878477048b4e4e69bb9f3510f33f72563..3633a355bd7f83b04bb65a30b731029376b5bff9 100644 (file)
 #define CONFIG_SYS_I2C_SOFT_SPEED      50000
 #define CONFIG_SYS_I2C_SOFT_SLAVE      0x7F
 #define CONFIG_I2C_MULTI_BUS
+#define CONFIG_SYS_I2C_INIT_BOARD
+
 #define CONFIG_SYS_MAX_I2C_BUS 7
 #define CONFIG_USB_GADGET
 #define CONFIG_USB_GADGET_S3C_UDC_OTG
 
 #define CONFIG_OF_LIBFDT
 
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
+
 #endif /* __CONFIG_H */
index 27f3d0af47105668009a9dd78677c4c2b06eb79e..4b30d148c31d4882aee8c544f2d724ca67130245 100644 (file)
  * SPI Settings
  */
 #define CONFIG_SOFT_SPI
-#define CONFIG_SOFT_SPI_MODE SPI_MODE_3
-#define CONFIG_SOFT_SPI_GPIO_SCLK EXYNOS4_GPIO_Y31
-#define CONFIG_SOFT_SPI_GPIO_MOSI EXYNOS4_GPIO_Y33
-#define CONFIG_SOFT_SPI_GPIO_MISO EXYNOS4_GPIO_Y30
-#define CONFIG_SOFT_SPI_GPIO_CS EXYNOS4_GPIO_Y43
-
-#define SPI_DELAY udelay(1)
-#undef SPI_INIT
-#define SPI_SCL(bit) universal_spi_scl(bit)
-#define SPI_SDA(bit) universal_spi_sda(bit)
-#define SPI_READ universal_spi_read()
+
 #ifndef        __ASSEMBLY__
 void universal_spi_scl(int bit);
 void universal_spi_sda(int bit);
index b5064ab37c05f2c807bb9106ec667bb0c3293501..2dee315f91e761449314c6385881a6b6fe09739f 100644 (file)
 #define I2C_MOSI       0x00004000      /* PD 17: Master Out, Slave In */
 #define I2C_MISO       0x00008000      /* PD 16: Master In, Slave Out */
 
-#undef  SPI_INIT                       /* no port initialization needed */
 #define SPI_READ        ((immr->im_ioport.iop_pdatd & I2C_MISO) != 0)
 #define SPI_SDA(bit)    do {                                           \
                        if(bit) immr->im_ioport.iop_pdatd |=  I2C_MOSI; \
index 022629f522e1630df0a1d4fc954bd24ff639e559..ee4b24473cd27b37f803f10a4b3efccd0a000d8c 100644 (file)
@@ -32,6 +32,7 @@
 #define CONFIG_DM_GPIO
 #define CONFIG_DM_TEST
 #define CONFIG_DM_SERIAL
+#define CONFIG_DM_CROS_EC
 
 #define CONFIG_SYS_STDIO_DEREGISTER
 
@@ -97,8 +98,8 @@
 #define CONFIG_CMD_SF_TEST
 #define CONFIG_CMD_SPI
 #define CONFIG_SPI_FLASH
-#define CONFIG_OF_SPI
-#define CONFIG_OF_SPI_FLASH
+#define CONFIG_DM_SPI
+#define CONFIG_DM_SPI_FLASH
 #define CONFIG_SPI_FLASH_ATMEL
 #define CONFIG_SPI_FLASH_EON
 #define CONFIG_SPI_FLASH_GIGADEVICE
index 22835ffd6403a795cb04e1bfa6390bb9c206cf5a..982d0dcea397737fa5aca1dc1b167c213c163858 100644 (file)
 
 #define CONFIG_OF_LIBFDT
 
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
+
 #endif /* __CONFIG_H */
index 1d947d7d9eab39030964f4d6b1e14e678303e55e..0c117bc5e7a8b64e7711ba4758cb16030d7637e8 100644 (file)
 /* standalone support */
 #define CONFIG_STANDALONE_LOAD_ADDR    0x42000000
 
-#define CONFIG_SYS_HZ                  1000
-
 /* baudrate */
 #define CONFIG_BAUDRATE                        115200
 
index 23e3c8af31a8a758b6027d1810f0adce4b8f558a..c3ad8beb903d9e131ae596ee98fbb725297614ec 100644 (file)
@@ -59,7 +59,7 @@
        BOARD_EXTRA_ENV_SETTINGS
 
 #if defined(CONFIG_TEGRA20_SFLASH) || defined(CONFIG_TEGRA20_SLINK) || defined(CONFIG_TEGRA114_SPI)
-#define CONFIG_FDT_SPI
+#define CONFIG_TEGRA_SPI
 #endif
 
 /* overrides for SPL build here */
 
 #define CONFIG_SKIP_LOWLEVEL_INIT
 
-/* remove devicetree support */
-#ifdef CONFIG_OF_CONTROL
-#endif
-
 /* remove I2C support */
 #ifdef CONFIG_SYS_I2C_TEGRA
 #undef CONFIG_SYS_I2C_TEGRA
index 834b3d5686c159b019b5c4661bfa943e0dc45957..5d2b12a11d1ef1e1494fa76ae14f5eeae8401797 100644 (file)
@@ -24,6 +24,8 @@
 #ifndef CONFIG_SPL_BUILD
 #define CONFIG_DM_SERIAL
 #endif
+#define CONFIG_DM_SPI
+#define CONFIG_DM_SPI_FLASH
 
 #define CONFIG_SYS_TIMER_RATE          1000000
 #define CONFIG_SYS_TIMER_COUNTER       NV_PA_TMRUS_BASE
 #define CONFIG_SYS_MEMTEST_START       (NV_PA_SDRC_CS0 + 0x600000)
 #define CONFIG_SYS_MEMTEST_END         (CONFIG_SYS_MEMTEST_START + 0x100000)
 
+#define CONFIG_USE_ARCH_MEMCPY
+
 /*-----------------------------------------------------------------------
  * Physical Memory Map
  */
 #define CONFIG_SPL_SERIAL_SUPPORT
 #define CONFIG_SPL_GPIO_SUPPORT
 
-#ifdef CONFIG_SPL_BUILD
-# define CONFIG_USE_PRIVATE_LIBGCC
-#endif
-
 #define CONFIG_SYS_GENERIC_BOARD
 
 /* Misc utility code */
index 80976e7e3b84ecddc3ea767f3416763ce37b6eda..5ed86d9365cd08aee392bbe77e7c7bf84e5c9ad6 100644 (file)
 #define CONFIG_SYS_TIMERBASE           0x48040000      /* Use Timer2 */
 #define CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC
 
+#ifndef CONFIG_SPL_BUILD
+# define CONFIG_DM
+# define CONFIG_CMD_DM
+# define CONFIG_DM_GPIO
+# define CONFIG_DM_SERIAL
+# define CONFIG_OMAP_SERIAL
+# define CONFIG_SYS_MALLOC_F_LEN       (1 << 10)
+#endif
+
 #include <asm/arch/omap.h>
 
 /* NS16550 Configuration */
 #define CONFIG_SYS_NS16550
+#ifdef CONFIG_SPL_BUILD
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE    (-4)
+#endif
 #define CONFIG_SYS_NS16550_CLK         48000000
 
 /* Network defines. */
index 3b19d3d6baf4c46f7a930e5c74c7e1afdea1f6a3..3c634ee680d02143b69fa0534143f28705b1a36b 100644 (file)
 #include <asm/arch/cpu.h>
 #include <asm/arch/omap3.h>
 
+#ifndef CONFIG_SPL_BUILD
+# define CONFIG_DM
+# define CONFIG_CMD_DM
+# define CONFIG_DM_GPIO
+# define CONFIG_DM_SERIAL
+# define CONFIG_OMAP_SERIAL
+# define CONFIG_SYS_MALLOC_F_LEN       (1 << 10)
+#endif
+
 /* The chip has SDRC controller */
 #define CONFIG_SDRC
 
 /* NS16550 Configuration */
 #define V_NS16550_CLK                  48000000        /* 48MHz (APLL96/2) */
 #define CONFIG_SYS_NS16550
-#define CONFIG_SYS_NS16550_SERIAL
-#define CONFIG_SYS_NS16550_REG_SIZE    (-4)
-#define CONFIG_SYS_NS16550_CLK         V_NS16550_CLK
+#ifdef CONFIG_SPL_BUILD
+# define CONFIG_SYS_NS16550_SERIAL
+# define CONFIG_SYS_NS16550_REG_SIZE   (-4)
+# define CONFIG_SYS_NS16550_CLK                V_NS16550_CLK
+#endif
 #define CONFIG_SYS_BAUDRATE_TABLE      {4800, 9600, 19200, 38400, 57600, \
                                        115200}
 
 /* Select serial console configuration */
 #define CONFIG_CONS_INDEX              3
+#ifdef CONFIG_SPL_BUILD
 #define CONFIG_SYS_NS16550_COM3                OMAP34XX_UART3
 #define CONFIG_SERIAL3                 3
+#endif
 
 /* Physical Memory Map */
 #define PHYS_SDRAM_1           OMAP34XX_SDRC_CS0
index 2705d2c55febe2b7d7f9b1881ae63af37a8a85ba..d97a9613ae5f3c83f56f246467a51ba1ea767f83 100644 (file)
 #define CONFIG_SYS_BARGSIZE            CONFIG_SYS_CBSIZE
 
 #define CONFIG_SYS_LOAD_ADDR           CONFIG_LOADADDR
-#define CONFIG_SYS_HZ                  1000
 
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_STACKSIZE               (128u * SZ_1K)
index 18fe277cada77b585012af8d5c0279ea834a7d0e..b18ae6dfaeb3551573ae9810fd4ef817428e209f 100644 (file)
@@ -33,18 +33,17 @@ are defined. Select only one of them."
 # define CONFIG_SUPPORT_CARD_UART_BASE (CONFIG_SUPPORT_CARD_BASE + 0x00200000)
 #endif
 
+#ifdef CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550
 #define CONFIG_SYS_NS16550_COM1                CONFIG_SUPPORT_CARD_UART_BASE
 #define CONFIG_SYS_NS16550_CLK         12288000
 #define CONFIG_SYS_NS16550_REG_SIZE    -2
+#endif
 
 #define CONFIG_SMC911X_BASE            CONFIG_SUPPORT_CARD_ETHER_BASE
 #define CONFIG_SMC911X_32_BIT
 
-#define CONFIG_SYS_UNIPHIER_SERIAL_BASE0 0x54006800
-#define CONFIG_SYS_UNIPHIER_SERIAL_BASE1 0x54006900
-#define CONFIG_SYS_UNIPHIER_SERIAL_BASE2 0x54006a00
-#define CONFIG_SYS_UNIPHIER_SERIAL_BASE3 0x54006b00
+#define CONFIG_SYS_MALLOC_F_LEN  0x7000
 
 /*-----------------------------------------------------------------------
  * MMU and Cache Setting
index 41a7c99edcfd64094d871529c7856c3adf32fcd4..fe331bc0825989a7c612a01b2fcbe20b81bdaff5 100644 (file)
@@ -99,7 +99,6 @@
 #define        CONFIG_VIDEO_BMP_GZIP
 #define        CONFIG_VIDEO_BMP_RLE8
 #define        CONFIG_SYS_VIDEO_LOGO_MAX_SIZE  (2 << 20)
-#undef SPI_INIT
 
 #define        SPI_DELAY       udelay(10)
 #define        SPI_SDA(val)    zipitz2_spi_sda(val)
index 1e4d8db96b7889e32586c665e001513523357b48..9e13146ecbb266a5b73dbb9b93b1e90317c79a06 100644 (file)
@@ -14,6 +14,7 @@
 #include <fdtdec.h>
 #include <cros_ec_message.h>
 
+#ifndef CONFIG_DM_CROS_EC
 /* Which interface is the device on? */
 enum cros_ec_interface_t {
        CROS_EC_IF_NONE,
@@ -22,9 +23,13 @@ enum cros_ec_interface_t {
        CROS_EC_IF_LPC, /* Intel Low Pin Count interface */
        CROS_EC_IF_SANDBOX,
 };
+#endif
 
 /* Our configuration information */
 struct cros_ec_dev {
+#ifdef CONFIG_DM_CROS_EC
+       struct udevice *dev;            /* Transport device */
+#else
        enum cros_ec_interface_t interface;
        struct spi_slave *spi;          /* Our SPI slave, if using SPI */
        int node;                       /* Our node */
@@ -33,6 +38,7 @@ struct cros_ec_dev {
        unsigned int addr;              /* Device address (for I2C) */
        unsigned int bus_num;           /* Bus number (for I2C) */
        unsigned int max_frequency;     /* Maximum interface frequency */
+#endif
        struct fdt_gpio_state ec_int;   /* GPIO used as EC interrupt line */
        int protocol_version;           /* Protocol version to use */
        int optimise_flash_write;       /* Don't write erased flash blocks */
@@ -233,6 +239,22 @@ int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
  */
 struct cros_ec_dev *board_get_cros_ec_dev(void);
 
+#ifdef CONFIG_DM_CROS_EC
+
+struct dm_cros_ec_ops {
+       int (*check_version)(struct udevice *dev);
+       int (*command)(struct udevice *dev, uint8_t cmd, int cmd_version,
+                      const uint8_t *dout, int dout_len,
+                      uint8_t **dinp, int din_len);
+       int (*packet)(struct udevice *dev, int out_bytes, int in_bytes);
+};
+
+#define dm_cros_ec_get_ops(dev) \
+               ((struct dm_cros_ec_ops *)(dev)->driver->ops)
+
+int cros_ec_register(struct udevice *dev);
+
+#else /* !CONFIG_DM_CROS_EC */
 
 /* Internal interfaces */
 int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob);
@@ -336,6 +358,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
 int cros_ec_spi_packet(struct cros_ec_dev *dev, int out_bytes, int in_bytes);
 int cros_ec_sandbox_packet(struct cros_ec_dev *dev, int out_bytes,
                           int in_bytes);
+#endif
 
 /**
  * Dump a block of data for a command.
@@ -489,9 +512,11 @@ int cros_ec_get_error(void);
  * Returns information from the FDT about the Chrome EC flash
  *
  * @param blob         FDT blob to use
+ * @param node         Node offset to read from
  * @param config       Structure to use to return information
  */
-int cros_ec_decode_ec_flash(const void *blob, struct fdt_cros_ec *config);
+int cros_ec_decode_ec_flash(const void *blob, int node,
+                           struct fdt_cros_ec *config);
 
 /**
  * Check the current keyboard state, in case recovery mode is requested.
index 7005d03d08f5d96adcd3f28c2a11f7f9e318ec44..44cb7ef93bfdeea682ea0602d33bf9615260ad9d 100644 (file)
@@ -65,6 +65,19 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
  */
 int device_probe(struct udevice *dev);
 
+/**
+ * device_probe() - Probe a child device, activating it
+ *
+ * Activate a device so that it is ready for use. All its parents are probed
+ * first. The child is provided with parent data if parent_priv is not NULL.
+ *
+ * @dev: Pointer to device to probe
+ * @parent_priv: Pointer to parent data. If non-NULL then this is provided to
+ * the child.
+ * @return 0 if OK, -ve on error
+ */
+int device_probe_child(struct udevice *dev, void *parent_priv);
+
 /**
  * device_remove() - Remove a device, de-activating it
  *
index c8a4072bcf7d60d2fb6cdaa24cc7fbb77946a76a..9ce95a834e75ee54d6d7edefb21ee0f848f97e0f 100644 (file)
@@ -57,7 +57,8 @@ struct driver_info;
  * @sibling_node: Next device in list of all devices
  * @flags: Flags for this device DM_FLAG_...
  * @req_seq: Requested sequence number for this device (-1 = any)
- * @seq: Allocated sequence number for this device (-1 = none)
+ * @seq: Allocated sequence number for this device (-1 = none). This is set up
+ * when the device is probed and will be unique within the device's uclass.
  */
 struct udevice {
        struct driver *driver;
@@ -96,6 +97,12 @@ struct udevice_id {
        ulong data;
 };
 
+#ifdef CONFIG_OF_CONTROL
+#define of_match_ptr(_ptr)     (_ptr)
+#else
+#define of_match_ptr(_ptr)     NULL
+#endif /* CONFIG_OF_CONTROL */
+
 /**
  * struct driver - A driver for a feature or peripheral
  *
@@ -133,6 +140,10 @@ struct udevice_id {
  * @per_child_auto_alloc_size: Each device can hold private data owned by
  * its parent. If required this will be automatically allocated if this
  * value is non-zero.
+ * TODO(sjg@chromium.org): I'm considering dropping this, and just having
+ * device_probe_child() pass it in. So far the use case for allocating it
+ * is SPI, but I found that unsatisfactory. Since it is here I will leave it
+ * until things are clearer.
  * @ops: Driver-specific operations. This is typically a list of function
  * pointers defined by the driver, to implement driver functions required by
  * the uclass.
@@ -274,4 +285,22 @@ int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
 int device_get_child_by_of_offset(struct udevice *parent, int seq,
                                  struct udevice **devp);
 
+/**
+ * device_find_first_child() - Find the first child of a device
+ *
+ * @parent: Parent device to search
+ * @devp: Returns first child device, or NULL if none
+ * @return 0
+ */
+int device_find_first_child(struct udevice *parent, struct udevice **devp);
+
+/**
+ * device_find_first_child() - Find the first child of a device
+ *
+ * @devp: Pointer to previous child device on entry. Returns pointer to next
+ *             child device, or NULL if none
+ * @return 0
+ */
+int device_find_next_child(struct udevice **devp);
+
 #endif
index 23568952467e6d5b685d84e2664561f5ca9ea942..704e33e37fb9dadc739f71312e15f79c4f9bb651 100644 (file)
@@ -38,7 +38,7 @@ struct uclass_driver *lists_uclass_lookup(enum uclass_id id);
  * This searches the U_BOOT_DEVICE() structures and creates new devices for
  * each one. The devices will have @parent as their parent.
  *
- * @parent: parent driver (root)
+ * @parent: parent device (root)
  * @early_only: If true, bind only drivers with the DM_INIT_F flag. If false
  * bind all drivers.
  */
@@ -50,7 +50,7 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only);
  * This creates a new device bound to the given device tree node, with
  * @parent as its parent.
  *
- * @parent: parent driver (root)
+ * @parent: parent device (root)
  * @blob: device tree blob
  * @offset: offset of this device tree node
  * @devp: if non-NULL, returns a pointer to the bound device
index 2bc8b147edfed01f152c1ca5e310ba8248637534..fbc8a6b3adda18424bd485a0ea39df981143f55e 100644 (file)
 #ifndef _DM_PLATDATA_H
 #define _DM_PLATDATA_H
 
+#include <linker_lists.h>
+
 /**
  * struct driver_info - Information required to instantiate a device
  *
- * @name:      Device name
+ * @name:      Driver name
  * @platdata:  Driver-specific platform data
  */
 struct driver_info {
@@ -25,4 +27,8 @@ struct driver_info {
 #define U_BOOT_DEVICE(__name)                                          \
        ll_entry_declare(struct driver_info, __name, driver_info)
 
+/* Declare a list of devices. The argument is a driver_info[] array */
+#define U_BOOT_DEVICES(__name)                                         \
+       ll_entry_declare_list(struct driver_info, __name, driver_info)
+
 #endif
diff --git a/include/dm/platform_data/serial-uniphier.h b/include/dm/platform_data/serial-uniphier.h
new file mode 100644 (file)
index 0000000..52343e3
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __PLAT_UNIPHIER_SERIAL_H
+#define __PLAT_UNIPHIER_SERIAL_H
+
+#define DRIVER_NAME    "uniphier-uart"
+
+struct uniphier_serial_platform_data {
+       unsigned long base;
+       unsigned int uartclk;
+};
+
+#endif /* __PLAT_UNIPHIER_SERIAL_H */
diff --git a/include/dm/platform_data/serial_mxc.h b/include/dm/platform_data/serial_mxc.h
new file mode 100644 (file)
index 0000000..7d3ace2
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __serial_mxc_h
+#define __serial_mxc_h
+
+/* Information about a serial port */
+struct mxc_serial_platdata {
+       struct mxc_uart *reg;  /* address of registers in physical memory */
+};
+
+#endif
diff --git a/include/dm/platform_data/serial_pl01x.h b/include/dm/platform_data/serial_pl01x.h
new file mode 100644 (file)
index 0000000..5e068f3
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __serial_pl01x_h
+#define __serial_pl01x_h
+
+enum pl01x_type {
+       TYPE_PL010,
+       TYPE_PL011,
+};
+
+/*
+ *Information about a serial port
+ *
+ * @base: Register base address
+ * @type: Port type
+ * @clock: Input clock rate, used for calculating the baud rate divisor
+ */
+struct pl01x_serial_platdata {
+       unsigned long base;
+       enum pl01x_type type;
+       unsigned int clock;
+};
+
+#endif
index 235d728bfbe62ea9af8cc3f6e946a248ce9791cd..f08c05da8147725f87900da81bf8944ff1c46ebc 100644 (file)
@@ -8,6 +8,7 @@
 #define __DM_TEST_H
 
 #include <dm.h>
+#include <malloc.h>
 
 /**
  * struct dm_test_cdata - configuration data for test instance
@@ -120,6 +121,7 @@ struct dm_test_state {
        int force_fail_alloc;
        int skip_post_probe;
        struct udevice *removed;
+       struct mallinfo start;
 };
 
 /* Test flags for each test */
@@ -177,6 +179,27 @@ int dm_check_operations(struct dm_test_state *dms, struct udevice *dev,
  */
 int dm_check_devices(struct dm_test_state *dms, int num_devices);
 
+/**
+ * dm_leak_check_start() - Prepare to check for a memory leak
+ *
+ * Call this before allocating memory to record the amount of memory being
+ * used.
+ *
+ * @dms: Overall test state
+ */
+void dm_leak_check_start(struct dm_test_state *dms);
+
+/**
+ * dm_leak_check_end() - Check that no memory has leaked
+ *
+ * Call this after dm_leak_check_start() and after you have hopefuilly freed
+ * all the memory that was allocated. This function will print an error if
+ * it sees a different amount of total memory allocated than before.
+ *
+ * @dms: Overall test state
+ */int dm_leak_check_end(struct dm_test_state *dms);
+
+
 /**
  * dm_test_main() - Run all the tests
  *
index 7f0e37b7b789cd64b48a124a0726dc4efbbe2fe4..a8944c97d03a9cfc9162a8c6289b21515862386b 100644 (file)
@@ -18,10 +18,16 @@ enum uclass_id {
        UCLASS_TEST,
        UCLASS_TEST_FDT,
        UCLASS_TEST_BUS,
+       UCLASS_SPI_EMUL,        /* sandbox SPI device emulator */
+       UCLASS_SIMPLE_BUS,
 
        /* U-Boot uclasses start here */
        UCLASS_GPIO,            /* Bank of general-purpose I/O pins */
        UCLASS_SERIAL,          /* Serial UART */
+       UCLASS_SPI,             /* SPI bus */
+       UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
+       UCLASS_SPI_FLASH,       /* SPI flash */
+       UCLASS_CROS_EC, /* Chrome OS EC */
 
        UCLASS_COUNT,
        UCLASS_INVALID = -1,
index 8d09ecff7b4e0c0c4590792391303f0eeea7f2f6..f6ec6d7e9f62f7551b869f1eb7b188e8587b44ee 100644 (file)
@@ -11,6 +11,7 @@
 #define _DM_UCLASS_H
 
 #include <dm/uclass-id.h>
+#include <linker_lists.h>
 #include <linux/list.h>
 
 /**
index 8be64a921dd75aaf835de4c1b87296ebcc2bd327..6ac3a38ef008b686221a5e213e67f5e503233846 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #ifndef __DM_UTIL_H
+#define __DM_UTIL_H
 
 void dm_warn(const char *fmt, ...);
 
index b8ecc41063b3e5b366f1688d60a32dd4f8e914fa..63d93416a3e1246975bd390b8990b6067c350f97 100644 (file)
@@ -570,4 +570,6 @@ unsigned long elf_hash(const unsigned char *name);
    that may still be in object files.  */
 #define R_PPC_TOC16             255
 
+int valid_elf_image(unsigned long addr);
+
 #endif /* _ELF_H */
index c3d1fbcf3566451419bff1a325a870a945743475..55cef94358bcd9ed1db349493941addc901d1ff4 100644 (file)
@@ -144,6 +144,8 @@ static inline u64 of_read_number(const fdt32_t *cell, int size)
 
 void of_bus_default_count_cells(void *blob, int parentoffset,
                                        int *addrc, int *sizec);
+int ft_verify_fdt(void *fdt);
+int arch_fixup_memory_node(void *blob);
 
 #endif /* ifdef CONFIG_OF_LIBFDT */
 
index 2590d3071fd0353eb7e96f667e74bb089c3a476a..4ae77be9ba7c8bf09860606645db711db0911fb2 100644 (file)
@@ -40,6 +40,27 @@ struct fdt_memory {
        fdt_addr_t end;
 };
 
+/*
+ * Information about a resource. start is the first address of the resource
+ * and end is the last address (inclusive). The length of the resource will
+ * be equal to: end - start + 1.
+ */
+struct fdt_resource {
+       fdt_addr_t start;
+       fdt_addr_t end;
+};
+
+/**
+ * Compute the size of a resource.
+ *
+ * @param res  the resource to operate on
+ * @return the size of the resource
+ */
+static inline fdt_size_t fdt_resource_size(const struct fdt_resource *res)
+{
+       return res->end - res->start + 1;
+}
+
 /**
  * Compat types that we know about and for which we might have drivers.
  * Each is named COMPAT_<dir>_<filename> where <dir> is the directory
@@ -96,6 +117,7 @@ enum fdt_compat_id {
        COMPAT_NXP_PTN3460,             /* NXP PTN3460 DP/LVDS bridge */
        COMPAT_SAMSUNG_EXYNOS_SYSMMU,   /* Exynos sysmmu */
        COMPAT_PARADE_PS8625,           /* Parade PS8622 EDP->LVDS bridge */
+       COMPAT_INTEL_LPC,               /* Intel Low Pin Count I/F */
 
        COMPAT_COUNT,
 };
@@ -597,4 +619,46 @@ struct fmap_entry {
  */
 int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
                           struct fmap_entry *entry);
+
+/**
+ * Obtain an indexed resource from a device property.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @param property     name of the property to parse
+ * @param index                index of the resource to retrieve
+ * @param res          returns the resource
+ * @return 0 if ok, negative on error
+ */
+int fdt_get_resource(const void *fdt, int node, const char *property,
+                    unsigned int index, struct fdt_resource *res);
+
+/**
+ * Obtain a named resource from a device property.
+ *
+ * Look up the index of the name in a list of strings and return the resource
+ * at that index.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @param property     name of the property to parse
+ * @param prop_names   name of the property containing the list of names
+ * @param name         the name of the entry to look up
+ * @param res          returns the resource
+ */
+int fdt_get_named_resource(const void *fdt, int node, const char *property,
+                          const char *prop_names, const char *name,
+                          struct fdt_resource *res);
+
+/**
+ * Look at the reg property of a device node that represents a PCI device
+ * and parse the bus, device and function number from it.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @param bdf          returns bus, device, function triplet
+ * @return 0 if ok, negative on error
+ */
+int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf);
+
 #endif
index c2a48e0b37853bedfcf36ed9640bf4d850778084..d5e05e97cb2fb12dc68794a2f1032eb366c79f18 100644 (file)
@@ -23,6 +23,7 @@ extern ulong ide_bus_offset[];
 #define LED_IDE2       0x02
 #define        DEVICE_LED(d)   ((d & 2) | ((d & 2) == 0)) /* depends on bit positions! */
 
+void ide_led(uchar led, uchar status);
 #endif /* CONFIG_IDE_LED */
 
 #ifdef CONFIG_SYS_64BIT_LBA
index 4347532520b7c700a9e4395dd22b7df7ffbe5e1c..a13a30289f691819c849834a1584c77a438fdc1a 100644 (file)
@@ -233,6 +233,7 @@ struct lmb;
 #define IH_TYPE_GPIMAGE                17      /* TI Keystone GPHeader Image   */
 #define IH_TYPE_ATMELIMAGE     18      /* ATMEL ROM bootable Image     */
 #define IH_TYPE_SOCFPGAIMAGE   19      /* Altera SOCFPGA Preloader     */
+#define IH_TYPE_X86_SETUP      20      /* x86 setup.bin Image          */
 
 /*
  * Compression Types
@@ -273,6 +274,7 @@ typedef struct image_info {
        ulong           image_start, image_len; /* start of image within blob, len of image */
        ulong           load;                   /* load addr for the image */
        uint8_t         comp, type, os;         /* compression, type of image, os type */
+       uint8_t         arch;                   /* CPU architecture */
 } image_info_t;
 
 /*
@@ -303,6 +305,10 @@ typedef struct bootm_headers {
        void            *fit_hdr_fdt;   /* FDT blob FIT image header */
        const char      *fit_uname_fdt; /* FDT blob subimage node unit name */
        int             fit_noffset_fdt;/* FDT blob subimage node offset */
+
+       void            *fit_hdr_setup; /* x86 setup FIT image header */
+       const char      *fit_uname_setup; /* x86 setup subimage node name */
+       int             fit_noffset_setup;/* x86 setup subimage node offset */
 #endif
 
 #ifndef USE_HOSTCC
@@ -417,6 +423,9 @@ enum fit_load_op {
        FIT_LOAD_REQUIRED,      /* Must be provided */
 };
 
+int boot_get_setup(bootm_headers_t *images, uint8_t arch, ulong *setup_start,
+                  ulong *setup_len);
+
 #ifndef USE_HOSTCC
 /* Image format types, returned by _get_format() routine */
 #define IMAGE_FORMAT_INVALID   0x00
@@ -438,6 +447,9 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
                uint8_t arch, ulong *rd_start, ulong *rd_end);
 #endif
 
+int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
+                      ulong *setup_start, ulong *setup_len);
+
 /**
  * fit_image_load() - load an image from a FIT
  *
@@ -721,6 +733,7 @@ int bootz_setup(ulong image, ulong *start, ulong *end);
 #define FIT_RAMDISK_PROP       "ramdisk"
 #define FIT_FDT_PROP           "fdt"
 #define FIT_DEFAULT_PROP       "default"
+#define FIT_SETUP_PROP         "setup"
 
 #define FIT_MAX_HASH_LEN       HASH_MAX_DIGEST_SIZE
 
index a1ef1e15df3ddbd8abec45766b9f9038f334bcc1..f3cbb637be419d16c35e59aec1aaf08f7819e310 100644 (file)
@@ -163,6 +163,31 @@ int fdt_first_subnode(const void *fdt, int offset);
  */
 int fdt_next_subnode(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_subnode - iterate over all subnodes of a parent
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *     fdt_for_each_subnode(fdt, node, parent) {
+ *             ...
+ *             use node
+ *             ...
+ *     }
+ *
+ * Note that this is implemented as a macro and node is used as iterator in
+ * the loop. It should therefore be a locally allocated variable. The parent
+ * variable on the other hand is never modified, so it can be constant or
+ * even a literal.
+ *
+ * @fdt:       FDT blob (const void *)
+ * @node:      child node (int)
+ * @parent:    parent node (int)
+ */
+#define fdt_for_each_subnode(fdt, node, parent)                \
+       for (node = fdt_first_subnode(fdt, parent);     \
+            node >= 0;                                 \
+            node = fdt_next_subnode(fdt, node))
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
@@ -857,6 +882,53 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_count_strings - count the number of strings in a string list
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @return: the number of strings in the given property
+ */
+int fdt_count_strings(const void *fdt, int node, const char *property);
+
+/**
+ * fdt_find_string - find a string in a string list and return its index
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @string: string to look up in the string list
+ * @return: the index of the string or negative on error
+ */
+int fdt_find_string(const void *fdt, int node, const char *property,
+                   const char *string);
+
+/**
+ * fdt_get_string_index() - obtain the string at a given index in a string list
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @index: index of the string to return
+ * @output: return location for the string
+ * @return: 0 if the string was found or a negative error code otherwise
+ */
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+                        int index, const char **output);
+
+/**
+ * fdt_get_string() - obtain the string at a given index in a string list
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @output: return location for the string
+ * @return: 0 if the string was found or a negative error code otherwise
+ *
+ * This is a shortcut for:
+ *
+ *     fdt_get_string_index(fdt, node, property, 0, output).
+ */
+int fdt_get_string(const void *fdt, int node, const char *property,
+                  const char **output);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
index 507d61ba9a5c0d54d60f54f966391a8a7ef6eae2..d37fba44dcafc6b1ce6813cca4e8f3d6999e95d5 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __LINKER_LISTS_H__
 #define __LINKER_LISTS_H__
 
+#include <linux/compiler.h>
+
 /*
  * There is no use in including this from ASM files, but that happens
  * anyway, e.g. PPC kgdb.S includes command.h which incluse us.
                        __attribute__((unused,                          \
                        section(".u_boot_list_2_"#_list"_2_"#_name)))
 
+/**
+ * ll_entry_declare_list() - Declare a list of link-generated array entries
+ * @_type:     Data type of each entry
+ * @_name:     Name of the entry
+ * @_list:     name of the list. Should contain only characters allowed
+ *             in a C variable name!
+ *
+ * This is like ll_entry_declare() but creates multiple entries. It should
+ * be assigned to an array.
+ *
+ * ll_entry_declare_list(struct my_sub_cmd, my_sub_cmd, cmd_sub, cmd.sub) = {
+ *     { .x = 3, .y = 4 },
+ *     { .x = 8, .y = 2 },
+ *     { .x = 1, .y = 7 }
+ * };
+ */
+#define ll_entry_declare_list(_type, _name, _list)                     \
+       _type _u_boot_list_2_##_list##_2_##_name[] __aligned(4)         \
+                       __attribute__((unused,                          \
+                       section(".u_boot_list_2_"#_list"_2_"#_name)))
+
 /**
  * We need a 0-byte-size type for iterator symbols, and the compiler
  * does not allow defining objects of C type 'void'. Using an empty
diff --git a/include/linux/mbus.h b/include/linux/mbus.h
new file mode 100644 (file)
index 0000000..717cbea
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Marvell MBUS common definitions.
+ *
+ * Copyright (C) 2008 Marvell Semiconductor
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __LINUX_MBUS_H
+#define __LINUX_MBUS_H
+
+struct resource;
+
+struct mbus_dram_target_info {
+       /*
+        * The 4-bit MBUS target ID of the DRAM controller.
+        */
+       u8              mbus_dram_target_id;
+
+       /*
+        * The base address, size, and MBUS attribute ID for each
+        * of the possible DRAM chip selects.  Peripherals are
+        * required to support at least 4 decode windows.
+        */
+       int             num_cs;
+       struct mbus_dram_window {
+               u8      cs_index;
+               u8      mbus_attr;
+               u32     base;
+               u32     size;
+       } cs[4];
+};
+
+struct mvebu_mbus_state {
+       void __iomem *mbuswins_base;
+       void __iomem *sdramwins_base;
+       struct dentry *debugfs_root;
+       struct dentry *debugfs_sdram;
+       struct dentry *debugfs_devs;
+       const struct mvebu_mbus_soc_data *soc;
+       int hw_io_coherency;
+};
+
+/* Flags for PCI/PCIe address decoding regions */
+#define MVEBU_MBUS_PCI_IO  0x1
+#define MVEBU_MBUS_PCI_MEM 0x2
+#define MVEBU_MBUS_PCI_WA  0x3
+
+/*
+ * Magic value that explicits that we don't need a remapping-capable
+ * address decoding window.
+ */
+#define MVEBU_MBUS_NO_REMAP (0xffffffff)
+
+/* Maximum size of a mbus window name */
+#define MVEBU_MBUS_MAX_WINNAME_SZ 32
+
+const struct mbus_dram_target_info *mvebu_mbus_dram_info(void);
+void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
+void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
+int mvebu_mbus_add_window_remap_by_id(unsigned int target,
+                                     unsigned int attribute,
+                                     phys_addr_t base, size_t size,
+                                     phys_addr_t remap);
+int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
+                               phys_addr_t base, size_t size);
+int mvebu_mbus_del_window(phys_addr_t base, size_t size);
+int mbus_dt_setup_win(struct mvebu_mbus_state *mbus,
+                     u32 base, u32 size, u8 target, u8 attr);
+
+#endif /* __LINUX_MBUS_H */
index 8e44855712c33be990b02ff0db8f70f67110d08d..96348d617fca34c4abfbf00759a84b8178d8aae9 100644 (file)
@@ -20,6 +20,10 @@ extern __kernel_size_t strspn(const char *,const char *);
  */
 #include <asm/string.h>
 
+#ifndef __HAVE_ARCH_BCOPY
+char *bcopy(const char *src, char *dest, int count);
+#endif
+
 #ifndef __HAVE_ARCH_STRCPY
 extern char * strcpy(char *,const char *);
 #endif
@@ -89,6 +93,9 @@ extern void * memchr(const void *,int,__kernel_size_t);
 void *memchr_inv(const void *, int, size_t);
 #endif
 
+unsigned long ustrtoul(const char *cp, char **endp, unsigned int base);
+unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base);
+
 #ifdef __cplusplus
 }
 #endif
index 7f5f9bc8ca86eb92614c24f951991f05d9dd64e5..d74a190eea066684a072e477a9fe52fb6640b20d 100644 (file)
@@ -387,6 +387,7 @@ int mmc_legacy_init(int verbose);
 
 int board_mmc_init(bd_t *bis);
 int cpu_mmc_init(bd_t *bis);
+int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
 
 /* Set block count limit because of 16 bit register limit on some hardware*/
 #ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
index a887bfb5f7a0a927f0e86eecc1fd8283f3738140..34651ab3779014ce6ec96a83b41acc0a96e60c00 100644 (file)
@@ -65,6 +65,7 @@ int mpc512x_fec_initialize(bd_t *bis);
 int mpc5xxx_fec_initialize(bd_t *bis);
 int mpc82xx_scc_enet_initialize(bd_t *bis);
 int mvgbe_initialize(bd_t *bis);
+int mvneta_initialize(bd_t *bis, int base_addr, int devnum, int phy_addr);
 int natsemi_initialize(bd_t *bis);
 int ne2k_register(void);
 int npe_initialize(bd_t *bis);
index 5784cfd97b859407c9b32fc3c4246e0674c742fd..0607379537d7ccf1038a0d322fdf29d95fbc0df4 100644 (file)
@@ -53,7 +53,7 @@
  * @clock:             UART base clock speed in Hz
  */
 struct ns16550_platdata {
-       unsigned char *base;
+       unsigned long base;
        int reg_shift;
        int clock;
 };
index 2fcc328d5bcfcbb7eb5bd740ad79b01c52830134..b4950776977e5440a75873065b753c472798a73e 100644 (file)
@@ -32,7 +32,9 @@
 #define PHY_10G_FEATURES       (PHY_GBIT_FEATURES | \
                                SUPPORTED_10000baseT_Full)
 
+#ifndef PHY_ANEG_TIMEOUT
 #define PHY_ANEG_TIMEOUT       4000
+#endif
 
 
 typedef enum {
index b673be270c8077b1d9eb73824b3fe0527d76b921..aa0a48ea62710dd019c77c75cc5350a9f61fb14d 100644 (file)
 
 #define SPI_DEFAULT_WORDLEN 8
 
+#ifdef CONFIG_DM_SPI
+struct dm_spi_bus {
+       uint max_hz;
+};
+
+#endif /* CONFIG_DM_SPI */
+
 /**
  * struct spi_slave - Representation of a SPI slave
  *
- * Drivers are expected to extend this with controller-specific data.
+ * For driver model this is the per-child data used by the SPI bus. It can
+ * be accessed using dev_get_parentdata() on the slave device. Each SPI
+ * driver should define this child data in its U_BOOT_DRIVER() definition:
+ *
+ *     .per_child_auto_alloc_size      = sizeof(struct spi_slave),
  *
- * @bus:               ID of the bus that the slave is attached to.
+ * If not using driver model, drivers are expected to extend this with
+ * controller-specific data.
+ *
+ * @dev:               SPI slave device
+ * @max_hz:            Maximum speed for this slave
+ * @mode:              SPI mode to use for this slave (see SPI mode flags)
+ * @bus:               ID of the bus that the slave is attached to. For
+ *                     driver model this is the sequence number of the SPI
+ *                     bus (bus->seq) so does not need to be stored
  * @cs:                        ID of the chip select connected to the slave.
  * @op_mode_rx:                SPI RX operation mode.
  * @op_mode_tx:                SPI TX operation mode.
  * @flags:             Indication of SPI flags.
  */
 struct spi_slave {
+#ifdef CONFIG_DM_SPI
+       struct udevice *dev;    /* struct spi_slave is dev->parentdata */
+       uint max_hz;
+       uint mode;
+#else
        unsigned int bus;
+#endif
        unsigned int cs;
        u8 op_mode_rx;
        u8 op_mode_tx;
@@ -228,8 +253,9 @@ int  spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
  * Returns: 1 if bus:cs identifies a valid chip on this board, 0
  * otherwise.
  */
-int  spi_cs_is_valid(unsigned int bus, unsigned int cs);
+int spi_cs_is_valid(unsigned int bus, unsigned int cs);
 
+#ifndef CONFIG_DM_SPI
 /**
  * Activate a SPI chipselect.
  * This function is provided by the board code when using a driver
@@ -255,6 +281,7 @@ void spi_cs_deactivate(struct spi_slave *slave);
  * @hz:                The transfer speed
  */
 void spi_set_speed(struct spi_slave *slave, uint hz);
+#endif
 
 /**
  * Write 8 bits, then read 8 bits.
@@ -305,4 +332,270 @@ struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
 struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum,
                                           int node);
 
+#ifdef CONFIG_DM_SPI
+
+/**
+ * struct spi_cs_info - Information about a bus chip select
+ *
+ * @dev:       Connected device, or NULL if none
+ */
+struct spi_cs_info {
+       struct udevice *dev;
+};
+
+/**
+ * struct struct dm_spi_ops - Driver model SPI operations
+ *
+ * The uclass interface is implemented by all SPI devices which use
+ * driver model.
+ */
+struct dm_spi_ops {
+       /**
+        * Claim the bus and prepare it for communication.
+        *
+        * The device provided is the slave device. It's parent controller
+        * will be used to provide the communication.
+        *
+        * This must be called before doing any transfers with a SPI slave. It
+        * will enable and initialize any SPI hardware as necessary, and make
+        * sure that the SCK line is in the correct idle state. It is not
+        * allowed to claim the same bus for several slaves without releasing
+        * the bus in between.
+        *
+        * @bus:        The SPI slave
+        *
+        * Returns: 0 if the bus was claimed successfully, or a negative value
+        * if it wasn't.
+        */
+       int (*claim_bus)(struct udevice *bus);
+
+       /**
+        * Release the SPI bus
+        *
+        * This must be called once for every call to spi_claim_bus() after
+        * all transfers have finished. It may disable any SPI hardware as
+        * appropriate.
+        *
+        * @bus:        The SPI slave
+        */
+       int (*release_bus)(struct udevice *bus);
+
+       /**
+        * Set the word length for SPI transactions
+        *
+        * Set the word length (number of bits per word) for SPI transactions.
+        *
+        * @bus:        The SPI slave
+        * @wordlen:    The number of bits in a word
+        *
+        * Returns: 0 on success, -ve on failure.
+        */
+       int (*set_wordlen)(struct udevice *bus, unsigned int wordlen);
+
+       /**
+        * SPI transfer
+        *
+        * This writes "bitlen" bits out the SPI MOSI port and simultaneously
+        * clocks "bitlen" bits in the SPI MISO port.  That's just the way SPI
+        * works.
+        *
+        * The source of the outgoing bits is the "dout" parameter and the
+        * destination of the input bits is the "din" parameter.  Note that
+        * "dout" and "din" can point to the same memory location, in which
+        * case the input data overwrites the output data (since both are
+        * buffered by temporary variables, this is OK).
+        *
+        * spi_xfer() interface:
+        * @dev:        The slave device to communicate with
+        * @bitlen:     How many bits to write and read.
+        * @dout:       Pointer to a string of bits to send out.  The bits are
+        *              held in a byte array and are sent MSB first.
+        * @din:        Pointer to a string of bits that will be filled in.
+        * @flags:      A bitwise combination of SPI_XFER_* flags.
+        *
+        * Returns: 0 on success, not -1 on failure
+        */
+       int (*xfer)(struct udevice *dev, unsigned int bitlen, const void *dout,
+                   void *din, unsigned long flags);
+
+       /**
+        * Set transfer speed.
+        * This sets a new speed to be applied for next spi_xfer().
+        * @bus:        The SPI bus
+        * @hz:         The transfer speed
+        * @return 0 if OK, -ve on error
+        */
+       int (*set_speed)(struct udevice *bus, uint hz);
+
+       /**
+        * Set the SPI mode/flags
+        *
+        * It is unclear if we want to set speed and mode together instead
+        * of separately.
+        *
+        * @bus:        The SPI bus
+        * @mode:       Requested SPI mode (SPI_... flags)
+        * @return 0 if OK, -ve on error
+        */
+       int (*set_mode)(struct udevice *bus, uint mode);
+
+       /**
+        * Get information on a chip select
+        *
+        * This is only called when the SPI uclass does not know about a
+        * chip select, i.e. it has no attached device. It gives the driver
+        * a chance to allow activity on that chip select even so.
+        *
+        * @bus:        The SPI bus
+        * @cs:         The chip select (0..n-1)
+        * @info:       Returns information about the chip select, if valid.
+        *              On entry info->dev is NULL
+        * @return 0 if OK (and @info is set up), -ENODEV if the chip select
+        *         is invalid, other -ve value on error
+        */
+       int (*cs_info)(struct udevice *bus, uint cs, struct spi_cs_info *info);
+};
+
+struct dm_spi_emul_ops {
+       /**
+        * SPI transfer
+        *
+        * This writes "bitlen" bits out the SPI MOSI port and simultaneously
+        * clocks "bitlen" bits in the SPI MISO port.  That's just the way SPI
+        * works. Here the device is a slave.
+        *
+        * The source of the outgoing bits is the "dout" parameter and the
+        * destination of the input bits is the "din" parameter.  Note that
+        * "dout" and "din" can point to the same memory location, in which
+        * case the input data overwrites the output data (since both are
+        * buffered by temporary variables, this is OK).
+        *
+        * spi_xfer() interface:
+        * @slave:      The SPI slave which will be sending/receiving the data.
+        * @bitlen:     How many bits to write and read.
+        * @dout:       Pointer to a string of bits sent to the device. The
+        *              bits are held in a byte array and are sent MSB first.
+        * @din:        Pointer to a string of bits that will be sent back to
+        *              the master.
+        * @flags:      A bitwise combination of SPI_XFER_* flags.
+        *
+        * Returns: 0 on success, not -1 on failure
+        */
+       int (*xfer)(struct udevice *slave, unsigned int bitlen,
+                   const void *dout, void *din, unsigned long flags);
+};
+
+/**
+ * spi_find_bus_and_cs() - Find bus and slave devices by number
+ *
+ * Given a bus number and chip select, this finds the corresponding bus
+ * device and slave device. Neither device is activated by this function,
+ * although they may have been activated previously.
+ *
+ * @busnum:    SPI bus number
+ * @cs:                Chip select to look for
+ * @busp:      Returns bus device
+ * @devp:      Return slave device
+ * @return 0 if found, -ENODEV on error
+ */
+int spi_find_bus_and_cs(int busnum, int cs, struct udevice **busp,
+                       struct udevice **devp);
+
+/**
+ * spi_get_bus_and_cs() - Find and activate bus and slave devices by number
+ *
+ * Given a bus number and chip select, this finds the corresponding bus
+ * device and slave device.
+ *
+ * If no such slave exists, and drv_name is not NULL, then a new slave device
+ * is automatically bound on this chip select.
+ *
+ * Ths new slave device is probed ready for use with the given speed and mode.
+ *
+ * @busnum:    SPI bus number
+ * @cs:                Chip select to look for
+ * @speed:     SPI speed to use for this slave
+ * @mode:      SPI mode to use for this slave
+ * @drv_name:  Name of driver to attach to this chip select
+ * @dev_name:  Name of the new device thus created
+ * @busp:      Returns bus device
+ * @devp:      Return slave device
+ * @return 0 if found, -ve on error
+ */
+int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
+                       const char *drv_name, const char *dev_name,
+                       struct udevice **busp, struct spi_slave **devp);
+
+/**
+ * spi_chip_select() - Get the chip select for a slave
+ *
+ * @return the chip select this slave is attached to
+ */
+int spi_chip_select(struct udevice *slave);
+
+/**
+ * spi_bind_device() - bind a device to a bus's chip select
+ *
+ * This binds a new device to an given chip select (which must be unused).
+ *
+ * @bus:       SPI bus to search
+ * @cs:                Chip select to attach to
+ * @drv_name:  Name of driver to attach to this chip select
+ * @dev_name:  Name of the new device thus created
+ * @devp:      Returns the newly bound device
+ */
+int spi_bind_device(struct udevice *bus, int cs, const char *drv_name,
+                   const char *dev_name, struct udevice **devp);
+
+/**
+ * spi_ofdata_to_platdata() - decode standard SPI platform data
+ *
+ * This decodes the speed and mode from a device tree node and puts it into
+ * the spi_slave structure.
+ *
+ * @blob:      Device tree blob
+ * @node:      Node offset to read from
+ * @spi:       Place to put the decoded information
+ */
+int spi_ofdata_to_platdata(const void *blob, int node, struct spi_slave *spi);
+
+/**
+ * spi_cs_info() - Check information on a chip select
+ *
+ * This checks a particular chip select on a bus to see if it has a device
+ * attached, or is even valid.
+ *
+ * @bus:       The SPI bus
+ * @cs:                The chip select (0..n-1)
+ * @info:      Returns information about the chip select, if valid
+ * @return 0 if OK (and @info is set up), -ENODEV if the chip select
+ *        is invalid, other -ve value on error
+ */
+int spi_cs_info(struct udevice *bus, uint cs, struct spi_cs_info *info);
+
+struct sandbox_state;
+
+/**
+ * sandbox_spi_get_emul() - get an emulator for a SPI slave
+ *
+ * This provides a way to attach an emulated SPI device to a particular SPI
+ * slave, so that xfer() operations on the slave will be handled by the
+ * emulator. If a emulator already exists on that chip select it is returned.
+ * Otherwise one is created.
+ *
+ * @state:     Sandbox state
+ * @bus:       SPI bus requesting the emulator
+ * @slave:     SPI slave device requesting the emulator
+ * @emuip:     Returns pointer to emulator
+ * @return 0 if OK, -ve on error
+ */
+int sandbox_spi_get_emul(struct sandbox_state *state,
+                        struct udevice *bus, struct udevice *slave,
+                        struct udevice **emulp);
+
+/* Access the serial operations for a device */
+#define spi_get_ops(dev)       ((struct dm_spi_ops *)(dev)->driver->ops)
+#define spi_emul_get_ops(dev)  ((struct dm_spi_emul_ops *)(dev)->driver->ops)
+#endif /* CONFIG_DM_SPI */
+
 #endif /* _SPI_H_ */
index 408a5b401cd91e66e88b84eab5c1dcef97681522..5913b39e268ee30598de449d03447a8205c80dae 100644 (file)
@@ -15,9 +15,8 @@
 #ifndef _SPI_FLASH_H_
 #define _SPI_FLASH_H_
 
-#include <spi.h>
+#include <dm.h>        /* Because we dereference struct udevice here */
 #include <linux/types.h>
-#include <linux/compiler.h>
 
 #ifndef CONFIG_SF_DEFAULT_SPEED
 # define CONFIG_SF_DEFAULT_SPEED       1000000
 # define CONFIG_SF_DEFAULT_BUS         0
 #endif
 
-/* sf param flags */
-#define SECT_4K                1 << 1
-#define SECT_32K       1 << 2
-#define E_FSR          1 << 3
-#define WR_QPP         1 << 4
-
-/* Enum list - Full read commands */
-enum spi_read_cmds {
-       ARRAY_SLOW = 1 << 0,
-       DUAL_OUTPUT_FAST = 1 << 1,
-       DUAL_IO_FAST = 1 << 2,
-       QUAD_OUTPUT_FAST = 1 << 3,
-       QUAD_IO_FAST = 1 << 4,
-};
-#define RD_EXTN                ARRAY_SLOW | DUAL_OUTPUT_FAST | DUAL_IO_FAST
-#define RD_FULL                RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST
-
-/* Dual SPI flash memories */
-enum spi_dual_flash {
-       SF_SINGLE_FLASH = 0,
-       SF_DUAL_STACKED_FLASH = 1 << 0,
-       SF_DUAL_PARALLEL_FLASH = 1 << 1,
-};
-
-/**
- * struct spi_flash_params - SPI/QSPI flash device params structure
- *
- * @name:              Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
- * @jedec:             Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
- * @ext_jedec:         Device ext_jedec ID
- * @sector_size:       Sector size of this device
- * @nr_sectors:                No.of sectors on this device
- * @e_rd_cmd:          Enum list for read commands
- * @flags:             Important param, for flash specific behaviour
- */
-struct spi_flash_params {
-       const char *name;
-       u32 jedec;
-       u16 ext_jedec;
-       u32 sector_size;
-       u32 nr_sectors;
-       u8 e_rd_cmd;
-       u16 flags;
-};
-
-extern const struct spi_flash_params spi_flash_params_table[];
+struct spi_slave;
 
 /**
  * struct spi_flash - SPI flash structure
  *
  * @spi:               SPI slave
  * @name:              Name of SPI flash
- * @dual_flash:                Indicates dual flash memories - dual stacked, parallel
+ * @dual_flash:        Indicates dual flash memories - dual stacked, parallel
  * @shift:             Flash shift useful in dual parallel
  * @size:              Total flash size
  * @page_size:         Write (page) size
  * @sector_size:       Sector size
- * @erase_size:                Erase size
+ * @erase_size:        Erase size
  * @bank_read_cmd:     Bank read cmd
  * @bank_write_cmd:    Bank write cmd
  * @bank_curr:         Current flash bank
@@ -97,8 +51,8 @@ extern const struct spi_flash_params spi_flash_params_table[];
  * @erase_cmd:         Erase cmd 4K, 32K, 64K
  * @read_cmd:          Read cmd - Array Fast, Extn read and quad read.
  * @write_cmd:         Write cmd - page and quad program.
- * @dummy_byte:                Dummy cycles for read operation.
- * @memory_map:                Address of read-only SPI flash access
+ * @dummy_byte:        Dummy cycles for read operation.
+ * @memory_map:        Address of read-only SPI flash access
  * @read:              Flash read ops: Read len bytes at offset into buf
  *                     Supported cmds: Fast Array Read
  * @write:             Flash write ops: Write len bytes from buf into offset
@@ -108,7 +62,12 @@ extern const struct spi_flash_params spi_flash_params_table[];
  * return 0 - Success, 1 - Failure
  */
 struct spi_flash {
+#ifdef CONFIG_DM_SPI_FLASH
+       struct spi_slave *spi;
+       struct udevice *dev;
+#else
        struct spi_slave *spi;
+#endif
        const char *name;
        u8 dual_flash;
        u8 shift;
@@ -129,12 +88,75 @@ struct spi_flash {
        u8 dummy_byte;
 
        void *memory_map;
+#ifndef CONFIG_DM_SPI_FLASH
+       /*
+        * These are not strictly needed for driver model, but keep them here
+        * whilt the transition is in progress.
+        *
+        * Normally each driver would provide its own operations, but for
+        * SPI flash most chips use the same algorithms. One approach is
+        * to create a 'common' SPI flash device which knows how to talk
+        * to most devices, and then allow other drivers to be used instead
+        * if requird, perhaps with a way of scanning through the list to
+        * find the driver that matches the device.
+        */
        int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);
        int (*write)(struct spi_flash *flash, u32 offset, size_t len,
                        const void *buf);
        int (*erase)(struct spi_flash *flash, u32 offset, size_t len);
+#endif
 };
 
+struct dm_spi_flash_ops {
+       int (*read)(struct udevice *dev, u32 offset, size_t len, void *buf);
+       int (*write)(struct udevice *dev, u32 offset, size_t len,
+                    const void *buf);
+       int (*erase)(struct udevice *dev, u32 offset, size_t len);
+};
+
+/* Access the serial operations for a device */
+#define sf_get_ops(dev) ((struct dm_spi_flash_ops *)(dev)->driver->ops)
+
+#ifdef CONFIG_DM_SPI_FLASH
+int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
+                          unsigned int max_hz, unsigned int spi_mode,
+                          struct udevice **devp);
+
+/* Compatibility function - this is the old U-Boot API */
+struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+                                 unsigned int max_hz, unsigned int spi_mode);
+
+/* Compatibility function - this is the old U-Boot API */
+void spi_flash_free(struct spi_flash *flash);
+
+int spi_flash_remove(struct udevice *flash);
+
+static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
+               size_t len, void *buf)
+{
+       return sf_get_ops(flash->dev)->read(flash->dev, offset, len, buf);
+}
+
+static inline int spi_flash_write(struct spi_flash *flash, u32 offset,
+               size_t len, const void *buf)
+{
+       return sf_get_ops(flash->dev)->write(flash->dev, offset, len, buf);
+}
+
+static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
+               size_t len)
+{
+       return sf_get_ops(flash->dev)->erase(flash->dev, offset, len);
+}
+
+struct sandbox_state;
+
+int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
+                        struct udevice *bus, int of_offset, const char *spec);
+
+void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs);
+
+#else
 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
                unsigned int max_hz, unsigned int spi_mode);
 
@@ -169,6 +191,7 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
 {
        return flash->erase(flash, offset, len);
 }
+#endif
 
 void spi_boot(void) __noreturn;
 void spi_spl_load_image(uint32_t offs, unsigned int size, void *vdst);
index a7e41da7fd4980ef2362816a63d8680cc26ef1b9..cee251faf7dcec67794b0d24f3e2b4a9fea514fb 100644 (file)
@@ -72,6 +72,8 @@ void spl_sata_load_image(void);
 int spl_load_image_fat(block_dev_desc_t *block_dev, int partition, const char *filename);
 int spl_load_image_fat_os(block_dev_desc_t *block_dev, int partition);
 
+void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image);
+
 #ifdef CONFIG_SPL_BOARD_INIT
 void spl_board_init(void);
 #endif
index 88e5da72ecc6ffe619a337b981dcb6c6af206c9a..8460439d8e772d4126b78ad616059dd38a7dabff 100644 (file)
@@ -8,4 +8,23 @@ config CC_OPTIMIZE_LIBS_FOR_SPEED
 
          If unsure, say N.
 
+config HAVE_PRIVATE_LIBGCC
+       bool
+
+config USE_PRIVATE_LIBGCC
+       bool "Use private libgcc"
+       depends on HAVE_PRIVATE_LIBGCC
+       help
+         This option allows you to use the built-in libgcc implementation
+         of U-boot instead of the one privided by the compiler.
+         If unsure, say N.
+
+config SYS_HZ
+       int
+       default 1000
+       help
+         The frequency of the timer returned by get_timer().
+         get_timer() must operate in milliseconds and this option must be
+         set to 1000.
+
 endmenu
index 06d4542029623cb7d84f764c57fb805bc84f5cd6..9714620ab3e211df006d440dc4f1abb6d03bb9b8 100644 (file)
@@ -72,6 +72,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"),
        COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
        COMPAT(PARADE_PS8625, "parade,ps8625"),
+       COMPAT(COMPAT_INTEL_LPC, "intel,lpc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
@@ -708,4 +709,75 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
 
        return 0;
 }
+
+static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
+{
+       u64 number = 0;
+
+       while (cells--)
+               number = (number << 32) | fdt32_to_cpu(*ptr++);
+
+       return number;
+}
+
+int fdt_get_resource(const void *fdt, int node, const char *property,
+                    unsigned int index, struct fdt_resource *res)
+{
+       const fdt32_t *ptr, *end;
+       int na, ns, len, parent;
+       unsigned int i = 0;
+
+       parent = fdt_parent_offset(fdt, node);
+       if (parent < 0)
+               return parent;
+
+       na = fdt_address_cells(fdt, parent);
+       ns = fdt_size_cells(fdt, parent);
+
+       ptr = fdt_getprop(fdt, node, property, &len);
+       if (!ptr)
+               return len;
+
+       end = ptr + len / sizeof(*ptr);
+
+       while (ptr + na + ns <= end) {
+               if (i == index) {
+                       res->start = res->end = fdtdec_get_number(ptr, na);
+                       res->end += fdtdec_get_number(&ptr[na], ns) - 1;
+                       return 0;
+               }
+
+               ptr += na + ns;
+               i++;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_named_resource(const void *fdt, int node, const char *property,
+                          const char *prop_names, const char *name,
+                          struct fdt_resource *res)
+{
+       int index;
+
+       index = fdt_find_string(fdt, node, prop_names, name);
+       if (index < 0)
+               return index;
+
+       return fdt_get_resource(fdt, node, property, index, res);
+}
+
+int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf)
+{
+       const fdt32_t *prop;
+       int len;
+
+       prop = fdt_getprop(fdt, node, "reg", &len);
+       if (!prop)
+               return len;
+
+       *bdf = fdt32_to_cpu(*prop) & 0xffffff;
+
+       return 0;
+}
 #endif
index 7597bad555404a276a72afd4bda981e0f4187ce7..39f4b3f8ad5ffecc59afa59f9e96a93f4e16fe5c 100644 (file)
@@ -15,14 +15,16 @@ int initcall_run_list(const init_fnc_t init_sequence[])
 
        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
                unsigned long reloc_ofs = 0;
+               int ret;
 
                if (gd->flags & GD_FLG_RELOC)
                        reloc_ofs = gd->reloc_off;
                debug("initcall: %p\n", (char *)*init_fnc_ptr - reloc_ofs);
-               if ((*init_fnc_ptr)()) {
-                       printf("initcall sequence %p failed at call %p\n",
+               ret = (*init_fnc_ptr)();
+               if (ret) {
+                       printf("initcall sequence %p failed at call %p (err=%d)\n",
                               init_sequence,
-                              (char *)*init_fnc_ptr - reloc_ofs);
+                              (char *)*init_fnc_ptr - reloc_ofs, ret);
                        return -1;
                }
        }
index 36af0435254b47cb0d2599836d1c81638266adf8..03733e574f71db1df2ebec2c08ec66dff95908d0 100644 (file)
@@ -491,6 +491,82 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
        return 0;
 }
 
+int fdt_count_strings(const void *fdt, int node, const char *property)
+{
+       int length, i, count = 0;
+       const char *list;
+
+       list = fdt_getprop(fdt, node, property, &length);
+       if (!list)
+               return -length;
+
+       for (i = 0; i < length; i++) {
+               int len = strlen(list);
+
+               list += len + 1;
+               i += len;
+               count++;
+       }
+
+       return count;
+}
+
+int fdt_find_string(const void *fdt, int node, const char *property,
+                   const char *string)
+{
+       const char *list, *end;
+       int len, index = 0;
+
+       list = fdt_getprop(fdt, node, property, &len);
+       if (!list)
+               return len;
+
+       end = list + len;
+       len = strlen(string);
+
+       while (list < end) {
+               int l = strlen(list);
+
+               if (l == len && memcmp(list, string, len) == 0)
+                       return index;
+
+               list += l + 1;
+               index++;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+                        int index, const char **output)
+{
+       const char *list;
+       int length, i;
+
+       list = fdt_getprop(fdt, node, property, &length);
+
+       for (i = 0; i < length; i++) {
+               int len = strlen(list);
+
+               if (index == 0) {
+                       *output = list;
+                       return 0;
+               }
+
+               list += len + 1;
+               i += len;
+               index--;
+       }
+
+       return FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_string(const void *fdt, int node, const char *property,
+                  const char **output)
+{
+       return fdt_get_string_index(fdt, node, property, 0, output);
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
                              const char *compatible)
 {
index 41a2be463565c6b519841902cba45b43839ef69a..031f0e1ac895289f772fb4bf538626ff065d1106 100644 (file)
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -236,7 +236,7 @@ long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size)
        return lmb_add_region(_rgn, base, size);
 }
 
-long lmb_overlaps_region(struct lmb_region *rgn, phys_addr_t base,
+static long lmb_overlaps_region(struct lmb_region *rgn, phys_addr_t base,
                                phys_size_t size)
 {
        unsigned long i;
index c7b026498be67e28f02cf070acf73a43e3c18ad4..5ebd1be48f324f8e9f21157ddd1b38f2dc85570a 100644 (file)
 #include <div64.h>
 #include <asm/io.h>
 
-#if CONFIG_SYS_HZ != 1000
-#warning "CONFIG_SYS_HZ must be 1000 and should not be defined by platforms"
-#endif
-
 #ifndef CONFIG_WD_PERIOD
 # define CONFIG_WD_PERIOD      (10 * 1000 * 1000)      /* 10 seconds default */
 #endif
index 76ffa05608adcaffb9bf3f888b4983a6a17cfcd4..eac4f7b3d0ed602c852d0f47dd9580670f8292da 100644 (file)
--- a/net/eth.c
+++ b/net/eth.c
@@ -153,7 +153,7 @@ static void eth_current_changed(void)
                setenv("ethact", NULL);
 }
 
-int eth_address_set(unsigned char *addr)
+static int eth_address_set(unsigned char *addr)
 {
        return memcmp(addr, "\0\0\0\0\0\0", 6);
 }
index 966d1cfba360ce7e7505dd5f806ce13543b0654c..0a2c53302cab1edacacd88f439b888f4837e7d4a 100644 (file)
@@ -299,6 +299,8 @@ static void tftp_complete(void)
                putc('#');
                TftpNumchars++;
        }
+       puts("  ");
+       print_size(TftpTsize, "");
 #endif
        time_start = get_timer(time_start);
        if (time_start > 0) {
index 4af5355fa5a20f9c2e763f37b269bea38d43e8ea..4194edb89e86fe2db008767dd33bd7faf4e32b79 100644 (file)
@@ -52,7 +52,7 @@ int post_init_f(void)
  * Boards with hotkey support can override this weak default function
  * by defining one in their board specific code.
  */
-int __post_hotkeys_pressed(void)
+__weak int post_hotkeys_pressed(void)
 {
 #ifdef CONFIG_SYS_POST_HOTKEYS_GPIO
        int ret;
@@ -73,9 +73,6 @@ int __post_hotkeys_pressed(void)
 
        return 0;       /* No hotkeys supported */
 }
-int post_hotkeys_pressed(void)
-       __attribute__((weak, alias("__post_hotkeys_pressed")));
-
 
 void post_bootmode_init(void)
 {
@@ -236,11 +233,9 @@ static void post_get_flags(int *test_flags)
                        test_flags[j] |= POST_SLOWTEST;
 }
 
-void __show_post_progress(unsigned int test_num, int before, int result)
+__weak void show_post_progress(unsigned int test_num, int before, int result)
 {
 }
-void show_post_progress(unsigned int, int, int)
-                       __attribute__((weak, alias("__show_post_progress")));
 
 static int post_run_single(struct post_test *test,
                                int test_flags, int flags, unsigned int i)
index 88c01d18ecf9a94fbee9b6cd273c7b6c3285fe3d..7afe437e62e11b1ed25f13c909fff68263957948 100644 (file)
@@ -216,13 +216,13 @@ $(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin
 endif
 
 quiet_cmd_u-boot-spl = LD      $@
-      cmd_u-boot-spl = cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
+      cmd_u-boot-spl = (cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
                       $(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \
                       $(patsubst $(obj)/%,%,$(u-boot-spl-main)) --end-group \
-                      $(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN)
+                      $(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN))
 
-$(obj)/$(SPL_BIN): $(u-boot-spl-init) $(u-boot-spl-main) $(obj)/u-boot-spl.lds
-       $(call cmd,u-boot-spl)
+$(obj)/$(SPL_BIN): $(u-boot-spl-init) $(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
+       $(call if_changed,u-boot-spl)
 
 $(sort $(u-boot-spl-init) $(u-boot-spl-main)): $(u-boot-spl-dirs) ;
 
index 3a963c7973da5da0e37c0ac350ea7e4b1e2d59e1..3e3040b2e2ab9210ebef73859b93e158d2875ecc 100644 (file)
@@ -297,9 +297,24 @@ do_others () {
        else
                objdir=${1%/*}
                check_enabled_subimage $1 $objdir
+
+               if [ -f "$objdir/$KCONFIG_CONFIG" ]; then
+                       timestamp_before=$(stat --printf="%Y" \
+                                               $objdir/$KCONFIG_CONFIG)
+               fi
        fi
 
        run_make_config $target $objdir
+
+       if [ "$timestamp_before" -a -f "$objdir/$KCONFIG_CONFIG" ]; then
+               timestamp_after=$(stat --printf="%Y" $objdir/$KCONFIG_CONFIG)
+
+               if [ "$timestamp_after" -gt "$timestamp_before" ]; then
+                       # $objdir/.config has been updated.
+                       # touch .config to invoke "make silentoldconfig"
+                       touch $KCONFIG_CONFIG
+               fi
+       fi
 }
 
 progname=$(basename $0)
index 5c2415e3d2a93b9307e27cbefa48d6dab9eb40c9..75d3d41536bfb47079f37a284beca95bd982b425 100644 (file)
@@ -18,4 +18,6 @@ obj-$(CONFIG_DM_TEST) += core.o
 obj-$(CONFIG_DM_TEST) += ut.o
 ifneq ($(CONFIG_SANDBOX),)
 obj-$(CONFIG_DM_GPIO) += gpio.o
+obj-$(CONFIG_DM_SPI) += spi.o
+obj-$(CONFIG_DM_SPI_FLASH) += sf.o
 endif
index 873d64e42a4eda8cbe2ccaddd15cc6f2701cf5a0..abbaccff509ce09374f30e88983252672d3c4e62 100644 (file)
@@ -140,6 +140,37 @@ static int dm_test_bus_children_funcs(struct dm_test_state *dms)
 }
 DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
+/* Test that we can iterate through children */
+static int dm_test_bus_children_iterators(struct dm_test_state *dms)
+{
+       struct udevice *bus, *dev, *child;
+
+       /* Walk through the children one by one */
+       ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+       ut_assertok(device_find_first_child(bus, &dev));
+       ut_asserteq_str("c-test@5", dev->name);
+       ut_assertok(device_find_next_child(&dev));
+       ut_asserteq_str("c-test@0", dev->name);
+       ut_assertok(device_find_next_child(&dev));
+       ut_asserteq_str("c-test@1", dev->name);
+       ut_assertok(device_find_next_child(&dev));
+       ut_asserteq_ptr(dev, NULL);
+
+       /* Move to the next child without using device_find_first_child() */
+       ut_assertok(device_find_child_by_seq(bus, 5, true, &dev));
+       ut_asserteq_str("c-test@5", dev->name);
+       ut_assertok(device_find_next_child(&dev));
+       ut_asserteq_str("c-test@0", dev->name);
+
+       /* Try a device with no children */
+       ut_assertok(device_find_first_child(dev, &child));
+       ut_asserteq_ptr(child, NULL);
+
+       return 0;
+}
+DM_TEST(dm_test_bus_children_iterators,
+       DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 /* Test that the bus can store data about each child */
 static int dm_test_bus_parent_data(struct dm_test_state *dms)
 {
index b0cfb42c85fc692a5d5ffb0ef11d22d5f5bcea90..ff5c2a749c5e37dbbcca5340dabdf18374a8e5c2 100644 (file)
@@ -67,6 +67,34 @@ static struct driver_info driver_info_pre_reloc = {
        .platdata = &test_pdata_manual,
 };
 
+void dm_leak_check_start(struct dm_test_state *dms)
+{
+       dms->start = mallinfo();
+       if (!dms->start.uordblks)
+               puts("Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c\n");
+}
+
+int dm_leak_check_end(struct dm_test_state *dms)
+{
+       struct mallinfo end;
+       int id;
+
+       /* Don't delete the root class, since we started with that */
+       for (id = UCLASS_ROOT + 1; id < UCLASS_COUNT; id++) {
+               struct uclass *uc;
+
+               uc = uclass_find(id);
+               if (!uc)
+                       continue;
+               ut_assertok(uclass_destroy(uc));
+       }
+
+       end = mallinfo();
+       ut_asserteq(dms->start.uordblks, end.uordblks);
+
+       return 0;
+}
+
 /* Test that binding with platdata occurs correctly */
 static int dm_test_autobind(struct dm_test_state *dms)
 {
@@ -377,14 +405,11 @@ static int dm_test_leak(struct dm_test_state *dms)
        int i;
 
        for (i = 0; i < 2; i++) {
-               struct mallinfo start, end;
                struct udevice *dev;
                int ret;
                int id;
 
-               start = mallinfo();
-               if (!start.uordblks)
-                       puts("Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c\n");
+               dm_leak_check_start(dms);
 
                ut_assertok(dm_scan_platdata(false));
                ut_assertok(dm_scan_fdt(gd->fdt_blob, false));
@@ -398,18 +423,7 @@ static int dm_test_leak(struct dm_test_state *dms)
                        ut_assertok(ret);
                }
 
-               /* Don't delete the root class, since we started with that */
-               for (id = UCLASS_ROOT + 1; id < UCLASS_COUNT; id++) {
-                       struct uclass *uc;
-
-                       uc = uclass_find(id);
-                       if (!uc)
-                               continue;
-                       ut_assertok(uclass_destroy(uc));
-               }
-
-               end = mallinfo();
-               ut_asserteq(start.uordblks, end.uordblks);
+               ut_assertok(dm_leak_check_end(dms));
        }
 
        return 0;
index 2b2b0b51fa74571a0e0ca200574bef48c0d7dee7..94bd0d99dc0bc1fa9b5c7033690ab6de7cc29b41 100644 (file)
@@ -7,11 +7,14 @@
 #include <common.h>
 #include <fdtdec.h>
 #include <dm.h>
+#include <dm/root.h>
 #include <dm/ut.h>
 #include <dm/test.h>
 #include <dm/util.h>
 #include <asm/gpio.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* Test that sandbox GPIOs work correctly */
 static int dm_test_gpio(struct dm_test_state *dms)
 {
@@ -39,52 +42,51 @@ static int dm_test_gpio(struct dm_test_state *dms)
 
        /* Get the operations for this device */
        ops = gpio_get_ops(dev);
-       ut_assert(ops->get_state);
+       ut_assert(ops->get_function);
 
        /* Cannot get a value until it is reserved */
-       ut_asserteq(-1, ops->get_value(dev, offset));
-
+       ut_asserteq(-EBUSY, gpio_get_value(gpio + 1));
        /*
         * Now some tests that use the 'sandbox' back door. All GPIOs
         * should default to input, include b4 that we are using here.
         */
-       ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
-       ut_asserteq_str("b4:  in: 0 [ ]", buf);
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b4: input: 0 [ ]", buf);
 
        /* Change it to an output */
        sandbox_gpio_set_direction(dev, offset, 1);
-       ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
-       ut_asserteq_str("b4: out: 0 [ ]", buf);
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b4: output: 0 [ ]", buf);
 
        sandbox_gpio_set_value(dev, offset, 1);
-       ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
-       ut_asserteq_str("b4: out: 1 [ ]", buf);
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b4: output: 1 [ ]", buf);
 
-       ut_assertok(ops->request(dev, offset, "testing"));
-       ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
-       ut_asserteq_str("b4: out: 1 [x] testing", buf);
+       ut_assertok(gpio_request(gpio, "testing"));
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b4: output: 1 [x] testing", buf);
 
        /* Change the value a bit */
        ut_asserteq(1, ops->get_value(dev, offset));
        ut_assertok(ops->set_value(dev, offset, 0));
        ut_asserteq(0, ops->get_value(dev, offset));
-       ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
-       ut_asserteq_str("b4: out: 0 [x] testing", buf);
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b4: output: 0 [x] testing", buf);
        ut_assertok(ops->set_value(dev, offset, 1));
        ut_asserteq(1, ops->get_value(dev, offset));
 
        /* Make it an input */
        ut_assertok(ops->direction_input(dev, offset));
-       ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
-       ut_asserteq_str("b4:  in: 1 [x] testing", buf);
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b4: input: 1 [x] testing", buf);
        sandbox_gpio_set_value(dev, offset, 0);
        ut_asserteq(0, sandbox_gpio_get_value(dev, offset));
-       ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
-       ut_asserteq_str("b4:  in: 0 [x] testing", buf);
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b4: input: 0 [x] testing", buf);
 
-       ut_assertok(ops->free(dev, offset));
-       ut_assertok(ops->get_state(dev, offset, buf, sizeof(buf)));
-       ut_asserteq_str("b4:  in: 0 [ ]", buf);
+       ut_assertok(gpio_free(gpio));
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b4: input: 0 [ ]", buf);
 
        /* Check the 'a' bank also */
        ut_assertok(gpio_lookup_name("a15", &dev, &offset, &gpio));
@@ -96,6 +98,18 @@ static int dm_test_gpio(struct dm_test_state *dms)
        ut_asserteq_str("a", name);
        ut_asserteq(20, offset_count);
 
+       return 0;
+}
+DM_TEST(dm_test_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that sandbox anonymous GPIOs work correctly */
+static int dm_test_gpio_anon(struct dm_test_state *dms)
+{
+       unsigned int offset, gpio;
+       struct udevice *dev;
+       const char *name;
+       int offset_count;
+
        /* And the anonymous bank */
        ut_assertok(gpio_lookup_name("14", &dev, &offset, &gpio));
        ut_asserteq_str(dev->name, "gpio_sandbox");
@@ -108,4 +122,57 @@ static int dm_test_gpio(struct dm_test_state *dms)
 
        return 0;
 }
-DM_TEST(dm_test_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+DM_TEST(dm_test_gpio_anon, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that gpio_requestf() works as expected */
+static int dm_test_gpio_requestf(struct dm_test_state *dms)
+{
+       unsigned int offset, gpio;
+       struct udevice *dev;
+       char buf[80];
+
+       ut_assertok(gpio_lookup_name("b5", &dev, &offset, &gpio));
+       ut_assertok(gpio_requestf(gpio, "testing %d %s", 1, "hi"));
+       sandbox_gpio_set_direction(dev, offset, 1);
+       sandbox_gpio_set_value(dev, offset, 1);
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b5: output: 1 [x] testing 1 hi", buf);
+
+       return 0;
+}
+DM_TEST(dm_test_gpio_requestf, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that gpio_request() copies its string */
+static int dm_test_gpio_copy(struct dm_test_state *dms)
+{
+       unsigned int offset, gpio;
+       struct udevice *dev;
+       char buf[80], name[10];
+
+       ut_assertok(gpio_lookup_name("b6", &dev, &offset, &gpio));
+       strcpy(name, "odd_name");
+       ut_assertok(gpio_request(gpio, name));
+       sandbox_gpio_set_direction(dev, offset, 1);
+       sandbox_gpio_set_value(dev, offset, 1);
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b6: output: 1 [x] odd_name", buf);
+       strcpy(name, "nothing");
+       ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
+       ut_asserteq_str("b6: output: 1 [x] odd_name", buf);
+
+       return 0;
+}
+DM_TEST(dm_test_gpio_copy, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that we don't leak memory with GPIOs */
+static int dm_test_gpio_leak(struct dm_test_state *dms)
+{
+       ut_assertok(dm_test_gpio(dms));
+       ut_assertok(dm_test_gpio_anon(dms));
+       ut_assertok(dm_test_gpio_requestf(dms));
+       ut_assertok(dm_leak_check_end(dms));
+
+       return 0;
+}
+
+DM_TEST(dm_test_gpio_leak, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/dm/sf.c b/test/dm/sf.c
new file mode 100644 (file)
index 0000000..57dd134
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <asm/state.h>
+#include <dm/ut.h>
+#include <dm/test.h>
+#include <dm/util.h>
+
+/* Test that sandbox SPI flash works correctly */
+static int dm_test_spi_flash(struct dm_test_state *dms)
+{
+       /*
+        * Create an empty test file and run the SPI flash tests. This is a
+        * long way from being a unit test, but it does test SPI device and
+        * emulator binding, probing, the SPI flash emulator including
+        * device tree decoding, plus the file-based backing store of SPI.
+        *
+        * More targeted tests could be created to perform the above steps
+        * one at a time. This might not increase test coverage much, but
+        * it would make bugs easier to find. It's not clear whether the
+        * benefit is worth the extra complexity.
+        */
+       ut_asserteq(0, run_command_list(
+               "sb save hostfs - spi.bin 0 200000;"
+               "sf probe;"
+               "sf test 0 10000", -1,  0));
+       /*
+        * Since we are about to destroy all devices, we must tell sandbox
+        * to forget the emulation device
+        */
+       sandbox_sf_unbind_emul(state_get_current(), 0, 0);
+
+       return 0;
+}
+DM_TEST(dm_test_spi_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/dm/spi.c b/test/dm/spi.c
new file mode 100644 (file)
index 0000000..61b5b25
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <dm/device-internal.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <dm/ut.h>
+#include <dm/util.h>
+#include <asm/state.h>
+
+/* Test that we can find buses and chip-selects */
+static int dm_test_spi_find(struct dm_test_state *dms)
+{
+       struct sandbox_state *state = state_get_current();
+       struct spi_slave *slave;
+       struct udevice *bus, *dev;
+       const int busnum = 0, cs = 0, mode = 0, speed = 1000000, cs_b = 1;
+       struct spi_cs_info info;
+       int of_offset;
+
+       ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_SPI, busnum,
+                                                      false, &bus));
+
+       /*
+        * spi_post_bind() will bind devices to chip selects. Check this then
+        * remove the emulation and the slave device.
+        */
+       ut_asserteq(0, uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus));
+       ut_assertok(spi_cs_info(bus, cs, &info));
+       of_offset = info.dev->of_offset;
+       sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
+       device_remove(info.dev);
+       device_unbind(info.dev);
+
+       /*
+        * Even though the device is gone, the sandbox SPI drivers always
+        * reports that CS 0 is present
+        */
+       ut_assertok(spi_cs_info(bus, cs, &info));
+       ut_asserteq_ptr(info.dev, NULL);
+
+       /* This finds nothing because we removed the device */
+       ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev));
+       ut_asserteq(-ENODEV, spi_get_bus_and_cs(busnum, cs, speed, mode,
+                                               NULL, 0, &bus, &slave));
+
+       /*
+        * This forces the device to be re-added, but there is no emulation
+        * connected so the probe will fail. We require that bus is left
+        * alone on failure, and that the spi_get_bus_and_cs() does not add
+        * a 'partially-inited' device.
+        */
+       ut_asserteq(-ENODEV, spi_find_bus_and_cs(busnum, cs, &bus, &dev));
+       ut_asserteq(-ENOENT, spi_get_bus_and_cs(busnum, cs, speed, mode,
+                                               "spi_flash_std", "name", &bus,
+                                               &slave));
+       ut_assertok(spi_cs_info(bus, cs, &info));
+       ut_asserteq_ptr(info.dev, NULL);
+
+       /* Add the emulation and try again */
+       ut_assertok(sandbox_sf_bind_emul(state, busnum, cs, bus, of_offset,
+                                        "name"));
+       ut_assertok(spi_find_bus_and_cs(busnum, cs, &bus, &dev));
+       ut_assertok(spi_get_bus_and_cs(busnum, cs, speed, mode,
+                                      "spi_flash_std", "name", &bus, &slave));
+
+       ut_assertok(spi_cs_info(bus, cs, &info));
+       ut_asserteq_ptr(info.dev, slave->dev);
+
+       /* We should be able to add something to another chip select */
+       ut_assertok(sandbox_sf_bind_emul(state, busnum, cs_b, bus, of_offset,
+                                        "name"));
+       ut_assertok(spi_get_bus_and_cs(busnum, cs_b, speed, mode,
+                                      "spi_flash_std", "name", &bus, &slave));
+       ut_assertok(spi_cs_info(bus, cs_b, &info));
+       ut_asserteq_ptr(info.dev, slave->dev);
+
+       /*
+        * Since we are about to destroy all devices, we must tell sandbox
+        * to forget the emulation device
+        */
+       sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
+       sandbox_sf_unbind_emul(state_get_current(), busnum, cs_b);
+
+       return 0;
+}
+DM_TEST(dm_test_spi_find, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test that sandbox SPI works correctly */
+static int dm_test_spi_xfer(struct dm_test_state *dms)
+{
+       struct spi_slave *slave;
+       struct udevice *bus;
+       const int busnum = 0, cs = 0, mode = 0;
+       const char dout[5] = {0x9f};
+       unsigned char din[5];
+
+       ut_assertok(spi_get_bus_and_cs(busnum, cs, 1000000, mode, NULL, 0,
+                                      &bus, &slave));
+       ut_assertok(spi_claim_bus(slave));
+       ut_assertok(spi_xfer(slave, 40, dout, din,
+                            SPI_XFER_BEGIN | SPI_XFER_END));
+       ut_asserteq(0xff, din[0]);
+       ut_asserteq(0x20, din[1]);
+       ut_asserteq(0x20, din[2]);
+       ut_asserteq(0x15, din[3]);
+       spi_release_bus(slave);
+
+       /*
+        * Since we are about to destroy all devices, we must tell sandbox
+        * to forget the emulation device
+        */
+#ifdef CONFIG_DM_SPI_FLASH
+       sandbox_sf_unbind_emul(state_get_current(), busnum, cs);
+#endif
+
+       return 0;
+}
+DM_TEST(dm_test_spi_xfer, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
index ef5aca5ac3c43800fe62b9242027cb341f4e9af7..bb99677ece9462604e4362fc514030291e30862d 100755 (executable)
@@ -4,4 +4,6 @@ NUM_CPUS=$(cat /proc/cpuinfo |grep -c processor)
 dtc -I dts -O dtb test/dm/test.dts -o test/dm/test.dtb
 make O=sandbox sandbox_config
 make O=sandbox -s -j${NUM_CPUS}
+dd if=/dev/zero of=spi.bin bs=1M count=2
 ./sandbox/u-boot -d test/dm/test.dtb -c "dm test"
+rm spi.bin
index 94ce72abfd5ced11313480ba736c88d65e01d862..90ca81092f721052df78504e7ffeb0a3a76817ef 100644 (file)
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
+#include <malloc.h>
 #include <dm/test.h>
 #include <dm/root.h>
 #include <dm/uclass-internal.h>
@@ -88,6 +89,7 @@ int dm_test_main(void)
                printf("Test: %s\n", test->name);
                ut_assertok(dm_test_init(dms));
 
+               dms->start = mallinfo();
                if (test->flags & DM_TESTF_SCAN_PDATA)
                        ut_assertok(dm_scan_platdata(false));
                if (test->flags & DM_TESTF_PROBE_TEST)
index 84895951550ffec7b1df26c4f2e782398f589ce5..1fba7925642a928fd60f10fd4ed7ee1bcc192890 100644 (file)
@@ -81,7 +81,7 @@
                compatible = "google,another-fdt-test";
        };
 
-       base-gpios {
+       gpio_a: base-gpios {
                compatible = "sandbox,gpio";
                gpio-bank-name = "a";
                num-gpios = <20>;
                gpio-bank-name = "b";
                num-gpios = <10>;
        };
+
+       spi@0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0>;
+               compatible = "sandbox,spi";
+               cs-gpios = <0>, <&gpio_a 0>;
+               spi.bin@0 {
+                       reg = <0>;
+                       compatible = "spansion,m25p16", "spi-flash";
+                       spi-max-frequency = <40000000>;
+                       sandbox,filename = "spi.bin";
+               };
+       };
+
 };
index 2b05b202a07276a3581b956e33d00a73a5d6278e..3b95964fd15cb1494c64ea6de43058b87ebaa584 100644 (file)
@@ -140,6 +140,7 @@ ubsha1-objs := os_support.o ubsha1.o lib/sha1.o
 HOSTCFLAGS_ubsha1.o := -pedantic
 
 hostprogs-$(CONFIG_KIRKWOOD) += kwboot
+hostprogs-$(CONFIG_ARMADA_XP) += kwboot
 hostprogs-y += proftool
 hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela
 
index 109d61686ec69fc958bd3b66995c83c412164eaa..1120e9b3729024fc851ddba5a3410dcc92cf29d1 100644 (file)
 /*
- * (C) Copyright 2008
- * Marvell Semiconductor <www.marvell.com>
- * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ * Image manipulator for Marvell SoCs
+ *  supports Kirkwood, Dove, Armada 370, and Armada XP
+ *
+ * (C) Copyright 2013 Thomas Petazzoni
+ * <thomas.petazzoni@free-electrons.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Not implemented: support for the register headers and secure
+ * headers in v1 images
  */
 
 #include "imagetool.h"
 #include <image.h>
+#include <stdint.h>
 #include "kwbimage.h"
 
-/*
- * Supported commands for configuration file
- */
-static table_entry_t kwbimage_cmds[] = {
-       {CMD_BOOT_FROM,         "BOOT_FROM",            "boot command", },
-       {CMD_NAND_ECC_MODE,     "NAND_ECC_MODE",        "NAND mode",    },
-       {CMD_NAND_PAGE_SIZE,    "NAND_PAGE_SIZE",       "NAND size",    },
-       {CMD_SATA_PIO_MODE,     "SATA_PIO_MODE",        "SATA mode",    },
-       {CMD_DDR_INIT_DELAY,    "DDR_INIT_DELAY",       "DDR init dly", },
-       {CMD_DATA,              "DATA",                 "Reg Write Data", },
-       {CMD_INVALID,           "",                     "",     },
+#define ALIGN_SUP(x, a) (((x) + (a - 1)) & ~(a - 1))
+
+/* Structure of the main header, version 0 (Kirkwood, Dove) */
+struct main_hdr_v0 {
+       uint8_t  blockid;               /*0     */
+       uint8_t  nandeccmode;           /*1     */
+       uint16_t nandpagesize;          /*2-3   */
+       uint32_t blocksize;             /*4-7   */
+       uint32_t rsvd1;                 /*8-11  */
+       uint32_t srcaddr;               /*12-15 */
+       uint32_t destaddr;              /*16-19 */
+       uint32_t execaddr;              /*20-23 */
+       uint8_t  satapiomode;           /*24    */
+       uint8_t  rsvd3;                 /*25    */
+       uint16_t ddrinitdelay;          /*26-27 */
+       uint16_t rsvd2;                 /*28-29 */
+       uint8_t  ext;                   /*30    */
+       uint8_t  checksum;              /*31    */
+};
+
+struct ext_hdr_v0_reg {
+       uint32_t raddr;
+       uint32_t rdata;
+};
+
+#define EXT_HDR_V0_REG_COUNT ((0x1dc - 0x20) / sizeof(struct ext_hdr_v0_reg))
+
+struct ext_hdr_v0 {
+       uint32_t              offset;
+       uint8_t               reserved[0x20 - sizeof(uint32_t)];
+       struct ext_hdr_v0_reg rcfg[EXT_HDR_V0_REG_COUNT];
+       uint8_t               reserved2[7];
+       uint8_t               checksum;
+};
+
+/* Structure of the main header, version 1 (Armada 370, Armada XP) */
+struct main_hdr_v1 {
+       uint8_t  blockid;               /* 0 */
+       uint8_t  reserved1;             /* 1 */
+       uint16_t reserved2;             /* 2-3 */
+       uint32_t blocksize;             /* 4-7 */
+       uint8_t  version;               /* 8 */
+       uint8_t  headersz_msb;          /* 9 */
+       uint16_t headersz_lsb;          /* A-B */
+       uint32_t srcaddr;               /* C-F */
+       uint32_t destaddr;              /* 10-13 */
+       uint32_t execaddr;              /* 14-17 */
+       uint8_t  reserved3;             /* 18 */
+       uint8_t  nandblocksize;         /* 19 */
+       uint8_t  nandbadblklocation;    /* 1A */
+       uint8_t  reserved4;             /* 1B */
+       uint16_t reserved5;             /* 1C-1D */
+       uint8_t  ext;                   /* 1E */
+       uint8_t  checksum;              /* 1F */
 };
 
 /*
- * Supported Boot options for configuration file
+ * Header for the optional headers, version 1 (Armada 370, Armada XP)
  */
-static table_entry_t kwbimage_bootops[] = {
-       {IBR_HDR_SPI_ID,        "spi",          "SPI Flash",    },
-       {IBR_HDR_NAND_ID,       "nand",         "NAND Flash",   },
-       {IBR_HDR_SATA_ID,       "sata",         "Sata port",    },
-       {IBR_HDR_PEX_ID,        "pex",          "PCIe port",    },
-       {IBR_HDR_UART_ID,       "uart",         "Serial port",  },
-       {-1,                    "",             "Invalid",      },
+struct opt_hdr_v1 {
+       uint8_t  headertype;
+       uint8_t  headersz_msb;
+       uint16_t headersz_lsb;
+       char     data[0];
 };
 
 /*
- * Supported NAND ecc options configuration file
+ * Various values for the opt_hdr_v1->headertype field, describing the
+ * different types of optional headers. The "secure" header contains
+ * informations related to secure boot (encryption keys, etc.). The
+ * "binary" header contains ARM binary code to be executed prior to
+ * executing the main payload (usually the bootloader). This is
+ * typically used to execute DDR3 training code. The "register" header
+ * allows to describe a set of (address, value) tuples that are
+ * generally used to configure the DRAM controller.
  */
-static table_entry_t kwbimage_eccmodes[] = {
-       {IBR_HDR_ECC_DEFAULT,           "default",      "Default mode", },
-       {IBR_HDR_ECC_FORCED_HAMMING,    "hamming",      "Hamming mode", },
-       {IBR_HDR_ECC_FORCED_RS,         "rs",           "RS mode",      },
-       {IBR_HDR_ECC_DISABLED,          "disabled",     "ECC Disabled", },
-       {-1,                            "",             "",     },
+#define OPT_HDR_V1_SECURE_TYPE   0x1
+#define OPT_HDR_V1_BINARY_TYPE   0x2
+#define OPT_HDR_V1_REGISTER_TYPE 0x3
+
+#define KWBHEADER_V1_SIZE(hdr) \
+       (((hdr)->headersz_msb << 16) | (hdr)->headersz_lsb)
+
+static struct image_cfg_element *image_cfg;
+static int cfgn;
+
+struct boot_mode {
+       unsigned int id;
+       const char *name;
+};
+
+struct boot_mode boot_modes[] = {
+       { 0x4D, "i2c"  },
+       { 0x5A, "spi"  },
+       { 0x8B, "nand" },
+       { 0x78, "sata" },
+       { 0x9C, "pex"  },
+       { 0x69, "uart" },
+       {},
 };
 
-static struct kwb_header kwbimage_header;
-static int datacmd_cnt = 0;
-static char * fname = "Unknown";
-static int lineno = -1;
+struct nand_ecc_mode {
+       unsigned int id;
+       const char *name;
+};
+
+struct nand_ecc_mode nand_ecc_modes[] = {
+       { 0x00, "default" },
+       { 0x01, "hamming" },
+       { 0x02, "rs" },
+       { 0x03, "disabled" },
+       {},
+};
+
+/* Used to identify an undefined execution or destination address */
+#define ADDR_INVALID ((uint32_t)-1)
+
+#define BINARY_MAX_ARGS 8
+
+/* In-memory representation of a line of the configuration file */
+struct image_cfg_element {
+       enum {
+               IMAGE_CFG_VERSION = 0x1,
+               IMAGE_CFG_BOOT_FROM,
+               IMAGE_CFG_DEST_ADDR,
+               IMAGE_CFG_EXEC_ADDR,
+               IMAGE_CFG_NAND_BLKSZ,
+               IMAGE_CFG_NAND_BADBLK_LOCATION,
+               IMAGE_CFG_NAND_ECC_MODE,
+               IMAGE_CFG_NAND_PAGESZ,
+               IMAGE_CFG_BINARY,
+               IMAGE_CFG_PAYLOAD,
+               IMAGE_CFG_DATA,
+       } type;
+       union {
+               unsigned int version;
+               unsigned int bootfrom;
+               struct {
+                       const char *file;
+                       unsigned int args[BINARY_MAX_ARGS];
+                       unsigned int nargs;
+               } binary;
+               const char *payload;
+               unsigned int dstaddr;
+               unsigned int execaddr;
+               unsigned int nandblksz;
+               unsigned int nandbadblklocation;
+               unsigned int nandeccmode;
+               unsigned int nandpagesz;
+               struct ext_hdr_v0_reg regdata;
+       };
+};
+
+#define IMAGE_CFG_ELEMENT_MAX 256
 
 /*
- * Report Error if xflag is set in addition to default
+ * Byte 8 of the image header contains the version number. In the v0
+ * header, byte 8 was reserved, and always set to 0. In the v1 header,
+ * byte 8 has been changed to a proper field, set to 1.
  */
-static int kwbimage_check_params(struct image_tool_params *params)
+static unsigned int image_version(void *header)
 {
-       if (!strlen (params->imagename)) {
-               printf ("Error:%s - Configuration file not specified, "
-                       "it is needed for kwbimage generation\n",
-                       params->cmdname);
-               return CFG_INVALID;
-       }
-       return  ((params->dflag && (params->fflag || params->lflag)) ||
-               (params->fflag && (params->dflag || params->lflag)) ||
-               (params->lflag && (params->dflag || params->fflag)) ||
-               (params->xflag) || !(strlen (params->imagename)));
+       unsigned char *ptr = header;
+       return ptr[8];
+}
+
+/*
+ * Utility functions to manipulate boot mode and ecc modes (convert
+ * them back and forth between description strings and the
+ * corresponding numerical identifiers).
+ */
+
+static const char *image_boot_mode_name(unsigned int id)
+{
+       int i;
+       for (i = 0; boot_modes[i].name; i++)
+               if (boot_modes[i].id == id)
+                       return boot_modes[i].name;
+       return NULL;
+}
+
+int image_boot_mode_id(const char *boot_mode_name)
+{
+       int i;
+       for (i = 0; boot_modes[i].name; i++)
+               if (!strcmp(boot_modes[i].name, boot_mode_name))
+                       return boot_modes[i].id;
+
+       return -1;
+}
+
+int image_nand_ecc_mode_id(const char *nand_ecc_mode_name)
+{
+       int i;
+       for (i = 0; nand_ecc_modes[i].name; i++)
+               if (!strcmp(nand_ecc_modes[i].name, nand_ecc_mode_name))
+                       return nand_ecc_modes[i].id;
+       return -1;
 }
 
-static uint32_t check_get_hexval (char *token)
+static struct image_cfg_element *
+image_find_option(unsigned int optiontype)
 {
-       uint32_t hexval;
+       int i;
 
-       if (!sscanf (token, "%x", &hexval)) {
-               printf ("Error:%s[%d] - Invalid hex data(%s)\n", fname,
-                       lineno, token);
-               exit (EXIT_FAILURE);
+       for (i = 0; i < cfgn; i++) {
+               if (image_cfg[i].type == optiontype)
+                       return &image_cfg[i];
        }
-       return hexval;
+
+       return NULL;
+}
+
+static unsigned int
+image_count_options(unsigned int optiontype)
+{
+       int i;
+       unsigned int count = 0;
+
+       for (i = 0; i < cfgn; i++)
+               if (image_cfg[i].type == optiontype)
+                       count++;
+
+       return count;
 }
 
 /*
- * Generates 8 bit checksum
+ * Compute a 8-bit checksum of a memory area. This algorithm follows
+ * the requirements of the Marvell SoC BootROM specifications.
  */
-static uint8_t kwbimage_checksum8 (void *start, uint32_t len, uint8_t csum)
+static uint8_t image_checksum8(void *start, uint32_t len)
 {
-       register uint8_t sum = csum;
-       volatile uint8_t *p = (volatile uint8_t *)start;
+       uint8_t csum = 0;
+       uint8_t *p = start;
 
        /* check len and return zero checksum if invalid */
        if (!len)
                return 0;
 
        do {
-               sum += *p;
+               csum += *p;
                p++;
        } while (--len);
-       return (sum);
+
+       return csum;
 }
 
-/*
- * Generates 32 bit checksum
- */
-static uint32_t kwbimage_checksum32 (uint32_t *start, uint32_t len, uint32_t csum)
+static uint32_t image_checksum32(void *start, uint32_t len)
 {
-       register uint32_t sum = csum;
-       volatile uint32_t *p = start;
+       uint32_t csum = 0;
+       uint32_t *p = start;
 
        /* check len and return zero checksum if invalid */
        if (!len)
                return 0;
 
        if (len % sizeof(uint32_t)) {
-               printf ("Error:%s[%d] - length is not in multiple of %zu\n",
-                       __FUNCTION__, len, sizeof(uint32_t));
+               fprintf(stderr, "Length %d is not in multiple of %zu\n",
+                       len, sizeof(uint32_t));
                return 0;
        }
 
        do {
-               sum += *p;
+               csum += *p;
                p++;
                len -= sizeof(uint32_t);
        } while (len > 0);
-       return (sum);
+
+       return csum;
 }
 
-static void kwbimage_check_cfgdata (char *token, enum kwbimage_cmd cmdsw,
-                                       struct kwb_header *kwbhdr)
+static void *image_create_v0(size_t *imagesz, struct image_tool_params *params,
+                            int payloadsz)
 {
-       bhr_t *mhdr = &kwbhdr->kwb_hdr;
-       extbhr_t *exthdr = &kwbhdr->kwb_exthdr;
-       int i;
+       struct image_cfg_element *e;
+       size_t headersz;
+       struct main_hdr_v0 *main_hdr;
+       struct ext_hdr_v0 *ext_hdr;
+       void *image;
+       int has_ext = 0;
+
+       /*
+        * Calculate the size of the header and the size of the
+        * payload
+        */
+       headersz  = sizeof(struct main_hdr_v0);
+
+       if (image_count_options(IMAGE_CFG_DATA) > 0) {
+               has_ext = 1;
+               headersz += sizeof(struct ext_hdr_v0);
+       }
+
+       if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
+               fprintf(stderr, "More than one payload, not possible\n");
+               return NULL;
+       }
 
-       switch (cmdsw) {
-       case CMD_BOOT_FROM:
-               i = get_table_entry_id (kwbimage_bootops,
-                               "Kwbimage boot option", token);
-
-               if (i < 0)
-                       goto INVL_DATA;
-
-               mhdr->blockid = i;
-               printf ("Preparing kirkwood boot image to boot "
-                       "from %s\n", token);
-               break;
-       case CMD_NAND_ECC_MODE:
-               i = get_table_entry_id (kwbimage_eccmodes,
-                       "NAND ecc mode", token);
-
-               if (i < 0)
-                       goto INVL_DATA;
-
-               mhdr->nandeccmode = i;
-               printf ("Nand ECC mode = %s\n", token);
-               break;
-       case CMD_NAND_PAGE_SIZE:
-               mhdr->nandpagesize =
-                       (uint16_t) check_get_hexval (token);
-               printf ("Nand page size = 0x%x\n", mhdr->nandpagesize);
-               break;
-       case CMD_SATA_PIO_MODE:
-               mhdr->satapiomode =
-                       (uint8_t) check_get_hexval (token);
-               printf ("Sata PIO mode = 0x%x\n",
-                               mhdr->satapiomode);
-               break;
-       case CMD_DDR_INIT_DELAY:
-               mhdr->ddrinitdelay =
-                       (uint16_t) check_get_hexval (token);
-               printf ("DDR init delay = %d msec\n", mhdr->ddrinitdelay);
-               break;
-       case CMD_DATA:
-               exthdr->rcfg[datacmd_cnt].raddr =
-                       check_get_hexval (token);
-
-               break;
-       case CMD_INVALID:
-               goto INVL_DATA;
-       default:
-               goto INVL_DATA;
+       image = malloc(headersz);
+       if (!image) {
+               fprintf(stderr, "Cannot allocate memory for image\n");
+               return NULL;
        }
-       return;
 
-INVL_DATA:
-       printf ("Error:%s[%d] - Invalid data\n", fname, lineno);
-       exit (EXIT_FAILURE);
+       memset(image, 0, headersz);
+
+       main_hdr = image;
+
+       /* Fill in the main header */
+       main_hdr->blocksize = payloadsz + sizeof(uint32_t);
+       main_hdr->srcaddr   = headersz;
+       main_hdr->ext       = has_ext;
+       main_hdr->destaddr  = params->addr;
+       main_hdr->execaddr  = params->ep;
+
+       e = image_find_option(IMAGE_CFG_BOOT_FROM);
+       if (e)
+               main_hdr->blockid = e->bootfrom;
+       e = image_find_option(IMAGE_CFG_NAND_ECC_MODE);
+       if (e)
+               main_hdr->nandeccmode = e->nandeccmode;
+       e = image_find_option(IMAGE_CFG_NAND_PAGESZ);
+       if (e)
+               main_hdr->nandpagesize = e->nandpagesz;
+       main_hdr->checksum = image_checksum8(image,
+                                            sizeof(struct main_hdr_v0));
+
+       /* Generate the ext header */
+       if (has_ext) {
+               int cfgi, datai;
+
+               ext_hdr = image + sizeof(struct main_hdr_v0);
+               ext_hdr->offset = 0x40;
+
+               for (cfgi = 0, datai = 0; cfgi < cfgn; cfgi++) {
+                       e = &image_cfg[cfgi];
+                       if (e->type != IMAGE_CFG_DATA)
+                               continue;
+
+                       ext_hdr->rcfg[datai].raddr = e->regdata.raddr;
+                       ext_hdr->rcfg[datai].rdata = e->regdata.rdata;
+                       datai++;
+               }
+
+               ext_hdr->checksum = image_checksum8(ext_hdr,
+                                                   sizeof(struct ext_hdr_v0));
+       }
+
+       *imagesz = headersz;
+       return image;
 }
 
-/*
- * this function sets the kwbimage header by-
- *     1. Abstracting input command line arguments data
- *     2. parses the kwbimage configuration file and update extebded header data
- *     3. calculates header, extended header and image checksums
- */
-static void kwdimage_set_ext_header (struct kwb_header *kwbhdr, char* name) {
-       bhr_t *mhdr = &kwbhdr->kwb_hdr;
-       extbhr_t *exthdr = &kwbhdr->kwb_exthdr;
-       FILE *fd = NULL;
-       int j;
-       char *line = NULL;
-       char * token, *saveptr1, *saveptr2;
-       size_t len = 0;
-       enum kwbimage_cmd cmd;
-
-       fname = name;
-       /* set dram register offset */
-       exthdr->dramregsoffs = (intptr_t)&exthdr->rcfg - (intptr_t)mhdr;
-
-       if ((fd = fopen (name, "r")) == 0) {
-               printf ("Error:%s - Can't open\n", fname);
-               exit (EXIT_FAILURE);
+static size_t image_headersz_v1(struct image_tool_params *params,
+                               int *hasext)
+{
+       struct image_cfg_element *binarye;
+       size_t headersz;
+       int ret;
+
+       /*
+        * Calculate the size of the header and the size of the
+        * payload
+        */
+       headersz = sizeof(struct main_hdr_v1);
+
+       if (image_count_options(IMAGE_CFG_BINARY) > 1) {
+               fprintf(stderr, "More than one binary blob, not supported\n");
+               return 0;
        }
 
-       /* Simple kwimage.cfg file parser */
-       lineno=0;
-       while ((getline (&line, &len, fd)) > 0) {
-               lineno++;
-               token = strtok_r (line, "\r\n", &saveptr1);
-               /* drop all lines with zero tokens (= empty lines) */
-               if (token == NULL)
-                       continue;
+       if (image_count_options(IMAGE_CFG_PAYLOAD) > 1) {
+               fprintf(stderr, "More than one payload, not possible\n");
+               return 0;
+       }
 
-               for (j = 0, cmd = CMD_INVALID, line = token; ; line = NULL) {
-                       token = strtok_r (line, " \t", &saveptr2);
-                       if (token == NULL)
-                       break;
-                       /* Drop all text starting with '#' as comments */
-                       if (token[0] == '#')
-                               break;
+       binarye = image_find_option(IMAGE_CFG_BINARY);
+       if (binarye) {
+               struct stat s;
+
+               ret = stat(binarye->binary.file, &s);
+               if (ret < 0) {
+                       char *cwd = get_current_dir_name();
+                       fprintf(stderr,
+                               "Didn't find the file '%s' in '%s' which is mandatory to generate the image\n"
+                               "This file generally contains the DDR3 training code, and should be extracted from an existing bootable\n"
+                               "image for your board. See 'kwbimage -x' to extract it from an existing image.\n",
+                               binarye->binary.file, cwd);
+                       free(cwd);
+                       return 0;
+               }
 
-                       /* Process rest as valid config command line */
-                       switch (j) {
-                       case CFG_COMMAND:
-                               cmd = get_table_entry_id (kwbimage_cmds,
-                                               "Kwbimage command", token);
+               headersz += s.st_size +
+                       binarye->binary.nargs * sizeof(unsigned int);
+               if (hasext)
+                       *hasext = 1;
+       }
 
-                               if (cmd == CMD_INVALID)
-                                       goto INVL_CMD;
-                               break;
+       /*
+        * The payload should be aligned on some reasonable
+        * boundary
+        */
+       return ALIGN_SUP(headersz, 4096);
+}
 
-                       case CFG_DATA0:
-                               kwbimage_check_cfgdata (token, cmd, kwbhdr);
-                               break;
+static void *image_create_v1(size_t *imagesz, struct image_tool_params *params,
+                            int payloadsz)
+{
+       struct image_cfg_element *e, *binarye;
+       struct main_hdr_v1 *main_hdr;
+       size_t headersz;
+       void *image, *cur;
+       int hasext = 0;
+       int ret;
+
+       /*
+        * Calculate the size of the header and the size of the
+        * payload
+        */
+       headersz = image_headersz_v1(params, &hasext);
+       if (headersz == 0)
+               return NULL;
+
+       image = malloc(headersz);
+       if (!image) {
+               fprintf(stderr, "Cannot allocate memory for image\n");
+               return NULL;
+       }
 
-                       case CFG_DATA1:
-                               if (cmd != CMD_DATA)
-                                       goto INVL_CMD;
-
-                               exthdr->rcfg[datacmd_cnt].rdata =
-                                               check_get_hexval (token);
-
-                               if (datacmd_cnt > KWBIMAGE_MAX_CONFIG ) {
-                                       printf ("Error:%s[%d] - Found more "
-                                               "than max(%zd) allowed "
-                                               "data configurations\n",
-                                               fname, lineno,
-                                               KWBIMAGE_MAX_CONFIG);
-                               exit (EXIT_FAILURE);
-                               } else
-                                       datacmd_cnt++;
-                               break;
+       memset(image, 0, headersz);
+
+       cur = main_hdr = image;
+       cur += sizeof(struct main_hdr_v1);
+
+       /* Fill the main header */
+       main_hdr->blocksize    = payloadsz - headersz + sizeof(uint32_t);
+       main_hdr->headersz_lsb = headersz & 0xFFFF;
+       main_hdr->headersz_msb = (headersz & 0xFFFF0000) >> 16;
+       main_hdr->destaddr     = params->addr;
+       main_hdr->execaddr     = params->ep;
+       main_hdr->srcaddr      = headersz;
+       main_hdr->ext          = hasext;
+       main_hdr->version      = 1;
+       e = image_find_option(IMAGE_CFG_BOOT_FROM);
+       if (e)
+               main_hdr->blockid = e->bootfrom;
+       e = image_find_option(IMAGE_CFG_NAND_BLKSZ);
+       if (e)
+               main_hdr->nandblocksize = e->nandblksz / (64 * 1024);
+       e = image_find_option(IMAGE_CFG_NAND_BADBLK_LOCATION);
+       if (e)
+               main_hdr->nandbadblklocation = e->nandbadblklocation;
+
+       binarye = image_find_option(IMAGE_CFG_BINARY);
+       if (binarye) {
+               struct opt_hdr_v1 *hdr = cur;
+               unsigned int *args;
+               size_t binhdrsz;
+               struct stat s;
+               int argi;
+               FILE *bin;
+
+               hdr->headertype = OPT_HDR_V1_BINARY_TYPE;
+
+               bin = fopen(binarye->binary.file, "r");
+               if (!bin) {
+                       fprintf(stderr, "Cannot open binary file %s\n",
+                               binarye->binary.file);
+                       return NULL;
+               }
+
+               fstat(fileno(bin), &s);
+
+               binhdrsz = sizeof(struct opt_hdr_v1) +
+                       (binarye->binary.nargs + 1) * sizeof(unsigned int) +
+                       s.st_size;
+               hdr->headersz_lsb = binhdrsz & 0xFFFF;
+               hdr->headersz_msb = (binhdrsz & 0xFFFF0000) >> 16;
+
+               cur += sizeof(struct opt_hdr_v1);
+
+               args = cur;
+               *args = binarye->binary.nargs;
+               args++;
+               for (argi = 0; argi < binarye->binary.nargs; argi++)
+                       args[argi] = binarye->binary.args[argi];
+
+               cur += (binarye->binary.nargs + 1) * sizeof(unsigned int);
+
+               ret = fread(cur, s.st_size, 1, bin);
+               if (ret != 1) {
+                       fprintf(stderr,
+                               "Could not read binary image %s\n",
+                               binarye->binary.file);
+                       return NULL;
+               }
+
+               fclose(bin);
 
-                       default:
-                               goto INVL_CMD;
+               cur += s.st_size;
+
+               /*
+                * For now, we don't support more than one binary
+                * header, and no other header types are
+                * supported. So, the binary header is necessarily the
+                * last one
+                */
+               *((unsigned char *)cur) = 0;
+
+               cur += sizeof(uint32_t);
+       }
+
+       /* Calculate and set the header checksum */
+       main_hdr->checksum = image_checksum8(main_hdr, headersz);
+
+       *imagesz = headersz;
+       return image;
+}
+
+static int image_create_config_parse_oneline(char *line,
+                                            struct image_cfg_element *el)
+{
+       char *keyword, *saveptr;
+       char deliminiters[] = " \t";
+
+       keyword = strtok_r(line, deliminiters, &saveptr);
+       if (!strcmp(keyword, "VERSION")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               el->type = IMAGE_CFG_VERSION;
+               el->version = atoi(value);
+       } else if (!strcmp(keyword, "BOOT_FROM")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               el->type = IMAGE_CFG_BOOT_FROM;
+               el->bootfrom = image_boot_mode_id(value);
+               if (el->bootfrom < 0) {
+                       fprintf(stderr,
+                               "Invalid boot media '%s'\n", value);
+                       return -1;
+               }
+       } else if (!strcmp(keyword, "NAND_BLKSZ")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               el->type = IMAGE_CFG_NAND_BLKSZ;
+               el->nandblksz = strtoul(value, NULL, 16);
+       } else if (!strcmp(keyword, "NAND_BADBLK_LOCATION")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               el->type = IMAGE_CFG_NAND_BADBLK_LOCATION;
+               el->nandbadblklocation =
+                       strtoul(value, NULL, 16);
+       } else if (!strcmp(keyword, "NAND_ECC_MODE")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               el->type = IMAGE_CFG_NAND_ECC_MODE;
+               el->nandeccmode = image_nand_ecc_mode_id(value);
+               if (el->nandeccmode < 0) {
+                       fprintf(stderr,
+                               "Invalid NAND ECC mode '%s'\n", value);
+                       return -1;
+               }
+       } else if (!strcmp(keyword, "NAND_PAGE_SIZE")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               el->type = IMAGE_CFG_NAND_PAGESZ;
+               el->nandpagesz = strtoul(value, NULL, 16);
+       } else if (!strcmp(keyword, "BINARY")) {
+               char *value = strtok_r(NULL, deliminiters, &saveptr);
+               int argi = 0;
+
+               el->type = IMAGE_CFG_BINARY;
+               el->binary.file = strdup(value);
+               while (1) {
+                       value = strtok_r(NULL, deliminiters, &saveptr);
+                       if (!value)
+                               break;
+                       el->binary.args[argi] = strtoul(value, NULL, 16);
+                       argi++;
+                       if (argi >= BINARY_MAX_ARGS) {
+                               fprintf(stderr,
+                                       "Too many argument for binary\n");
+                               return -1;
                        }
-                       j++;
                }
+               el->binary.nargs = argi;
+       } else if (!strcmp(keyword, "DATA")) {
+               char *value1 = strtok_r(NULL, deliminiters, &saveptr);
+               char *value2 = strtok_r(NULL, deliminiters, &saveptr);
+
+               if (!value1 || !value2) {
+                       fprintf(stderr,
+                               "Invalid number of arguments for DATA\n");
+                       return -1;
+               }
+
+               el->type = IMAGE_CFG_DATA;
+               el->regdata.raddr = strtoul(value1, NULL, 16);
+               el->regdata.rdata = strtoul(value2, NULL, 16);
+       } else {
+               fprintf(stderr, "Ignoring unknown line '%s'\n", line);
        }
-       if (line)
-               free (line);
 
-       fclose (fd);
-       return;
+       return 0;
+}
 
 /*
- * Invalid Command error reporring
- *
- * command CMD_DATA needs three strings on a line
- * whereas other commands need only two.
- *
- * if more than two/three (as per command type) are observed,
- * then error will be reported
+ * Parse the configuration file 'fcfg' into the array of configuration
+ * elements 'image_cfg', and return the number of configuration
+ * elements in 'cfgn'.
  */
-INVL_CMD:
-       printf ("Error:%s[%d] - Invalid command\n", fname, lineno);
-       exit (EXIT_FAILURE);
+static int image_create_config_parse(FILE *fcfg)
+{
+       int ret;
+       int cfgi = 0;
+
+       /* Parse the configuration file */
+       while (!feof(fcfg)) {
+               char *line;
+               char buf[256];
+
+               /* Read the current line */
+               memset(buf, 0, sizeof(buf));
+               line = fgets(buf, sizeof(buf), fcfg);
+               if (!line)
+                       break;
+
+               /* Ignore useless lines */
+               if (line[0] == '\n' || line[0] == '#')
+                       continue;
+
+               /* Strip final newline */
+               if (line[strlen(line) - 1] == '\n')
+                       line[strlen(line) - 1] = 0;
+
+               /* Parse the current line */
+               ret = image_create_config_parse_oneline(line,
+                                                       &image_cfg[cfgi]);
+               if (ret)
+                       return ret;
+
+               cfgi++;
+
+               if (cfgi >= IMAGE_CFG_ELEMENT_MAX) {
+                       fprintf(stderr,
+                               "Too many configuration elements in .cfg file\n");
+                       return -1;
+               }
+       }
+
+       cfgn = cfgi;
+       return 0;
+}
+
+static int image_get_version(void)
+{
+       struct image_cfg_element *e;
+
+       e = image_find_option(IMAGE_CFG_VERSION);
+       if (!e)
+               return -1;
+
+       return e->version;
+}
+
+static int image_version_file(const char *input)
+{
+       FILE *fcfg;
+       int version;
+       int ret;
+
+       fcfg = fopen(input, "r");
+       if (!fcfg) {
+               fprintf(stderr, "Could not open input file %s\n", input);
+               return -1;
+       }
+
+       image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
+                          sizeof(struct image_cfg_element));
+       if (!image_cfg) {
+               fprintf(stderr, "Cannot allocate memory\n");
+               fclose(fcfg);
+               return -1;
+       }
+
+       memset(image_cfg, 0,
+              IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
+       rewind(fcfg);
+
+       ret = image_create_config_parse(fcfg);
+       fclose(fcfg);
+       if (ret) {
+               free(image_cfg);
+               return -1;
+       }
+
+       version = image_get_version();
+       /* Fallback to version 0 is no version is provided in the cfg file */
+       if (version == -1)
+               version = 0;
+
+       free(image_cfg);
+
+       return version;
 }
 
-static void kwbimage_set_header (void *ptr, struct stat *sbuf, int ifd,
+static void kwbimage_set_header(void *ptr, struct stat *sbuf, int ifd,
                                struct image_tool_params *params)
 {
-       struct kwb_header *hdr = (struct kwb_header *)ptr;
-       bhr_t *mhdr = &hdr->kwb_hdr;
-       extbhr_t *exthdr = &hdr->kwb_exthdr;
+       FILE *fcfg;
+       void *image = NULL;
+       int version;
+       size_t headersz;
        uint32_t checksum;
+       int ret;
        int size;
 
-       /* Build and add image checksum header */
-       checksum = kwbimage_checksum32 ((uint32_t *)ptr, sbuf->st_size, 0);
+       fcfg = fopen(params->imagename, "r");
+       if (!fcfg) {
+               fprintf(stderr, "Could not open input file %s\n",
+                       params->imagename);
+               exit(EXIT_FAILURE);
+       }
+
+       image_cfg = malloc(IMAGE_CFG_ELEMENT_MAX *
+                          sizeof(struct image_cfg_element));
+       if (!image_cfg) {
+               fprintf(stderr, "Cannot allocate memory\n");
+               fclose(fcfg);
+               exit(EXIT_FAILURE);
+       }
+
+       memset(image_cfg, 0,
+              IMAGE_CFG_ELEMENT_MAX * sizeof(struct image_cfg_element));
+       rewind(fcfg);
+
+       ret = image_create_config_parse(fcfg);
+       fclose(fcfg);
+       if (ret) {
+               free(image_cfg);
+               exit(EXIT_FAILURE);
+       }
+
+       version = image_get_version();
+       /* Fallback to version 0 is no version is provided in the cfg file */
+       if (version == -1)
+               version = 0;
+
+       if (version == 0)
+               image = image_create_v0(&headersz, params, sbuf->st_size);
+       else if (version == 1)
+               image = image_create_v1(&headersz, params, sbuf->st_size);
+
+       if (!image) {
+               fprintf(stderr, "Could not create image\n");
+               free(image_cfg);
+               exit(EXIT_FAILURE);
+       }
+
+       free(image_cfg);
 
-       size = write (ifd, &checksum, sizeof(uint32_t));
+       /* Build and add image checksum header */
+       checksum = image_checksum32((uint32_t *)ptr, sbuf->st_size);
+       size = write(ifd, &checksum, sizeof(uint32_t));
        if (size != sizeof(uint32_t)) {
-               printf ("Error:%s - Checksum write %d bytes %s\n",
+               fprintf(stderr, "Error:%s - Checksum write %d bytes %s\n",
                        params->cmdname, size, params->imagefile);
-               exit (EXIT_FAILURE);
+               exit(EXIT_FAILURE);
        }
 
        sbuf->st_size += sizeof(uint32_t);
 
-       mhdr->blocksize = sbuf->st_size - sizeof(struct kwb_header);
-       mhdr->srcaddr = sizeof(struct kwb_header);
-       mhdr->destaddr= params->addr;
-       mhdr->execaddr =params->ep;
-       mhdr->ext = 0x1; /* header extension appended */
-
-       kwdimage_set_ext_header (hdr, params->imagename);
-       /* calculate checksums */
-       mhdr->checkSum = kwbimage_checksum8 ((void *)mhdr, sizeof(bhr_t), 0);
-       exthdr->checkSum = kwbimage_checksum8 ((void *)exthdr,
-                                               sizeof(extbhr_t), 0);
-}
-
-static int kwbimage_verify_header (unsigned char *ptr, int image_size,
-                       struct image_tool_params *params)
-{
-       struct kwb_header *hdr = (struct kwb_header *)ptr;
-       bhr_t *mhdr = &hdr->kwb_hdr;
-       extbhr_t *exthdr = &hdr->kwb_exthdr;
-       uint8_t calc_hdrcsum;
-       uint8_t calc_exthdrcsum;
-
-       calc_hdrcsum = kwbimage_checksum8 ((void *)mhdr,
-                       sizeof(bhr_t) - sizeof(uint8_t), 0);
-       if (calc_hdrcsum != mhdr->checkSum)
-               return -FDT_ERR_BADSTRUCTURE;   /* mhdr csum not matched */
-
-       calc_exthdrcsum = kwbimage_checksum8 ((void *)exthdr,
-                       sizeof(extbhr_t) - sizeof(uint8_t), 0);
-       if (calc_exthdrcsum != exthdr->checkSum)
-               return -FDT_ERR_BADSTRUCTURE; /* exthdr csum not matched */
+       /* Finally copy the header into the image area */
+       memcpy(ptr, image, headersz);
 
-       return 0;
+       free(image);
 }
 
-static void kwbimage_print_header (const void *ptr)
+static void kwbimage_print_header(const void *ptr)
 {
-       struct kwb_header *hdr = (struct kwb_header *) ptr;
-       bhr_t *mhdr = &hdr->kwb_hdr;
-       char *name = get_table_entry_name (kwbimage_bootops,
-                               "Kwbimage boot option",
-                               (int) mhdr->blockid);
-
-       printf ("Image Type:   Kirkwood Boot from %s Image\n", name);
-       printf ("Data Size:    ");
-       genimg_print_size (mhdr->blocksize - sizeof(uint32_t));
-       printf ("Load Address: %08x\n", mhdr->destaddr);
-       printf ("Entry Point:  %08x\n", mhdr->execaddr);
+       struct main_hdr_v0 *mhdr = (struct main_hdr_v0 *)ptr;
+
+       printf("Image Type:   MVEBU Boot from %s Image\n",
+              image_boot_mode_name(mhdr->blockid));
+       printf("Data Size:    ");
+       printf("Image version:%d\n", image_version((void *)ptr));
+       genimg_print_size(mhdr->blocksize - sizeof(uint32_t));
+       printf("Load Address: %08x\n", mhdr->destaddr);
+       printf("Entry Point:  %08x\n", mhdr->execaddr);
 }
 
-static int kwbimage_check_image_types (uint8_t type)
+static int kwbimage_check_image_types(uint8_t type)
 {
        if (type == IH_TYPE_KWBIMAGE)
                return EXIT_SUCCESS;
@@ -366,18 +807,91 @@ static int kwbimage_check_image_types (uint8_t type)
                return EXIT_FAILURE;
 }
 
+static int kwbimage_verify_header(unsigned char *ptr, int image_size,
+                                 struct image_tool_params *params)
+{
+       struct main_hdr_v0 *main_hdr;
+       struct ext_hdr_v0 *ext_hdr;
+       uint8_t checksum;
+
+       main_hdr = (void *)ptr;
+       checksum = image_checksum8(ptr,
+                                  sizeof(struct main_hdr_v0));
+       if (checksum != main_hdr->checksum)
+               return -FDT_ERR_BADSTRUCTURE;
+
+       /* Only version 0 extended header has checksum */
+       if (image_version((void *)ptr) == 0) {
+               ext_hdr = (void *)ptr + sizeof(struct main_hdr_v0);
+               checksum = image_checksum8(ext_hdr,
+                                          sizeof(struct ext_hdr_v0));
+               if (checksum != ext_hdr->checksum)
+                       return -FDT_ERR_BADSTRUCTURE;
+       }
+
+       return 0;
+}
+
+static int kwbimage_generate(struct image_tool_params *params,
+                            struct image_type_params *tparams)
+{
+       int alloc_len;
+       void *hdr;
+       int version = 0;
+
+       version = image_version_file(params->imagename);
+       if (version == 0) {
+               alloc_len = sizeof(struct main_hdr_v0) +
+                       sizeof(struct ext_hdr_v0);
+       } else {
+               alloc_len = image_headersz_v1(params, NULL);
+       }
+
+       hdr = malloc(alloc_len);
+       if (!hdr) {
+               fprintf(stderr, "%s: malloc return failure: %s\n",
+                       params->cmdname, strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       memset(hdr, 0, alloc_len);
+       tparams->header_size = alloc_len;
+       tparams->hdr = hdr;
+
+       return 0;
+}
+
+/*
+ * Report Error if xflag is set in addition to default
+ */
+static int kwbimage_check_params(struct image_tool_params *params)
+{
+       if (!strlen(params->imagename)) {
+               fprintf(stderr, "Error:%s - Configuration file not specified, "
+                       "it is needed for kwbimage generation\n",
+                       params->cmdname);
+               return CFG_INVALID;
+       }
+
+       return (params->dflag && (params->fflag || params->lflag)) ||
+               (params->fflag && (params->dflag || params->lflag)) ||
+               (params->lflag && (params->dflag || params->fflag)) ||
+               (params->xflag) || !(strlen(params->imagename));
+}
+
 /*
  * kwbimage type parameters definition
  */
 static struct image_type_params kwbimage_params = {
-       .name = "Kirkwood Boot Image support",
-       .header_size = sizeof(struct kwb_header),
-       .hdr = (void*)&kwbimage_header,
+       .name           = "Marvell MVEBU Boot Image support",
+       .header_size    = 0,            /* no fixed header size */
+       .hdr            = NULL,
+       .vrec_header    = kwbimage_generate,
        .check_image_type = kwbimage_check_image_types,
-       .verify_header = kwbimage_verify_header,
-       .print_header = kwbimage_print_header,
-       .set_header = kwbimage_set_header,
-       .check_params = kwbimage_check_params,
+       .verify_header  = kwbimage_verify_header,
+       .print_header   = kwbimage_print_header,
+       .set_header     = kwbimage_set_header,
+       .check_params   = kwbimage_check_params,
 };
 
 void init_kwb_image_type (void)
index e773f01df3f626b337c8c44390303b677feb46d0..1368b4c948ae74e977683880fc8828ea86b95bb7 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Boot a Marvell Kirkwood SoC, with Xmodem over UART0.
+ * Boot a Marvell SoC, with Xmodem over UART0.
+ *  supports Kirkwood, Dove, Armada 370, Armada XP
  *
  * (c) 2012 Daniel Stodden <daniel.stodden@gmail.com>
  *
@@ -37,9 +38,18 @@ static unsigned char kwboot_msg_boot[] = {
        0xBB, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
 };
 
+static unsigned char kwboot_msg_debug[] = {
+       0xDD, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
+};
+
+/* Defines known to work on Kirkwood */
 #define KWBOOT_MSG_REQ_DELAY   10 /* ms */
 #define KWBOOT_MSG_RSP_TIMEO   50 /* ms */
 
+/* Defines known to work on Armada XP */
+#define KWBOOT_MSG_REQ_DELAY_AXP       1000 /* ms */
+#define KWBOOT_MSG_RSP_TIMEO_AXP       1000 /* ms */
+
 /*
  * Xmodem Transfers
  */
@@ -62,6 +72,9 @@ struct kwboot_block {
 
 static int kwboot_verbose;
 
+static int msg_req_delay = KWBOOT_MSG_REQ_DELAY;
+static int msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO;
+
 static void
 kwboot_printv(const char *fmt, ...)
 {
@@ -184,6 +197,9 @@ kwboot_tty_send(int fd, const void *buf, size_t len)
        int rc;
        ssize_t n;
 
+       if (!buf)
+               return 0;
+
        rc = -1;
 
        do {
@@ -268,7 +284,10 @@ kwboot_bootmsg(int tty, void *msg)
        int rc;
        char c;
 
-       kwboot_printv("Sending boot message. Please reboot the target...");
+       if (msg == NULL)
+               kwboot_printv("Please reboot the target into UART boot mode...");
+       else
+               kwboot_printv("Sending boot message. Please reboot the target...");
 
        do {
                rc = tcflush(tty, TCIOFLUSH);
@@ -277,11 +296,11 @@ kwboot_bootmsg(int tty, void *msg)
 
                rc = kwboot_tty_send(tty, msg, 8);
                if (rc) {
-                       usleep(KWBOOT_MSG_REQ_DELAY * 1000);
+                       usleep(msg_req_delay * 1000);
                        continue;
                }
 
-               rc = kwboot_tty_recv(tty, &c, 1, KWBOOT_MSG_RSP_TIMEO);
+               rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo);
 
                kwboot_spinner();
 
@@ -292,6 +311,37 @@ kwboot_bootmsg(int tty, void *msg)
        return rc;
 }
 
+static int
+kwboot_debugmsg(int tty, void *msg)
+{
+       int rc;
+
+       kwboot_printv("Sending debug message. Please reboot the target...");
+
+       do {
+               char buf[16];
+
+               rc = tcflush(tty, TCIOFLUSH);
+               if (rc)
+                       break;
+
+               rc = kwboot_tty_send(tty, msg, 8);
+               if (rc) {
+                       usleep(msg_req_delay * 1000);
+                       continue;
+               }
+
+               rc = kwboot_tty_recv(tty, buf, 16, msg_rsp_timeo);
+
+               kwboot_spinner();
+
+       } while (rc);
+
+       kwboot_printv("\n");
+
+       return rc;
+}
+
 static int
 kwboot_xm_makeblock(struct kwboot_block *block, const void *data,
                    size_t size, int pnum)
@@ -300,6 +350,7 @@ kwboot_xm_makeblock(struct kwboot_block *block, const void *data,
        size_t n;
        int i;
 
+       block->soh = SOH;
        block->pnum = pnum;
        block->_pnum = ~block->pnum;
 
@@ -326,9 +377,15 @@ kwboot_xm_sendblock(int fd, struct kwboot_block *block)
                if (rc)
                        break;
 
-               rc = kwboot_tty_recv(fd, &c, 1, KWBOOT_BLK_RSP_TIMEO);
-               if (rc)
-                       break;
+               do {
+                       rc = kwboot_tty_recv(fd, &c, 1, KWBOOT_BLK_RSP_TIMEO);
+                       if (rc)
+                               break;
+
+                       if (c != ACK && c != NAK && c != CAN)
+                               printf("%c", c);
+
+               } while (c != ACK && c != NAK && c != CAN);
 
                if (c != ACK)
                        kwboot_progress(-1, '+');
@@ -511,7 +568,6 @@ kwboot_mmap_image(const char *path, size_t *size, int prot)
        void *img;
 
        rc = -1;
-       fd = -1;
        img = NULL;
 
        fd = open(path, O_RDONLY);
@@ -601,11 +657,16 @@ static void
 kwboot_usage(FILE *stream, char *progname)
 {
        fprintf(stream,
-               "Usage: %s -b <image> [ -p ] [ -t ] "
-               "[-B <baud> ] <TTY>\n", progname);
+               "Usage: %s [-d | -a | -b <image> | -D <image> ] [ -t ] [-B <baud> ] <TTY>\n",
+               progname);
        fprintf(stream, "\n");
-       fprintf(stream, "  -b <image>: boot <image>\n");
+       fprintf(stream,
+               "  -b <image>: boot <image> with preamble (Kirkwood, Armada 370/XP)\n");
        fprintf(stream, "  -p: patch <image> to type 0x69 (uart boot)\n");
+       fprintf(stream,
+               "  -D <image>: boot <image> without preamble (Dove)\n");
+       fprintf(stream, "  -d: enter debug mode\n");
+       fprintf(stream, "  -a: use timings for Armada XP\n");
        fprintf(stream, "\n");
        fprintf(stream, "  -t: mini terminal\n");
        fprintf(stream, "\n");
@@ -619,6 +680,7 @@ main(int argc, char **argv)
        const char *ttypath, *imgpath;
        int rv, rc, tty, term, prot, patch;
        void *bootmsg;
+       void *debugmsg;
        void *img;
        size_t size;
        speed_t speed;
@@ -626,6 +688,7 @@ main(int argc, char **argv)
        rv = 1;
        tty = -1;
        bootmsg = NULL;
+       debugmsg = NULL;
        imgpath = NULL;
        img = NULL;
        term = 0;
@@ -636,7 +699,7 @@ main(int argc, char **argv)
        kwboot_verbose = isatty(STDOUT_FILENO);
 
        do {
-               int c = getopt(argc, argv, "hb:ptB:");
+               int c = getopt(argc, argv, "hb:ptaB:dD:");
                if (c < 0)
                        break;
 
@@ -646,6 +709,15 @@ main(int argc, char **argv)
                        imgpath = optarg;
                        break;
 
+               case 'D':
+                       bootmsg = NULL;
+                       imgpath = optarg;
+                       break;
+
+               case 'd':
+                       debugmsg = kwboot_msg_debug;
+                       break;
+
                case 'p':
                        patch = 1;
                        break;
@@ -654,6 +726,11 @@ main(int argc, char **argv)
                        term = 1;
                        break;
 
+               case 'a':
+                       msg_req_delay = KWBOOT_MSG_REQ_DELAY_AXP;
+                       msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO_AXP;
+                       break;
+
                case 'B':
                        speed = kwboot_tty_speed(atoi(optarg));
                        if (speed == -1)
@@ -667,7 +744,7 @@ main(int argc, char **argv)
                }
        } while (1);
 
-       if (!bootmsg && !term)
+       if (!bootmsg && !term && !debugmsg)
                goto usage;
 
        if (patch && !imgpath)
@@ -702,7 +779,13 @@ main(int argc, char **argv)
                }
        }
 
-       if (bootmsg) {
+       if (debugmsg) {
+               rc = kwboot_debugmsg(tty, debugmsg);
+               if (rc) {
+                       perror("debugmsg");
+                       goto out;
+               }
+       } else {
                rc = kwboot_bootmsg(tty, bootmsg);
                if (rc) {
                        perror("bootmsg");