]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-tegra
authorTom Rini <trini@ti.com>
Thu, 23 Oct 2014 18:05:34 +0000 (14:05 -0400)
committerTom Rini <trini@ti.com>
Thu, 23 Oct 2014 18:05:34 +0000 (14:05 -0400)
306 files changed:
Makefile
README
arch/Kconfig
arch/arm/Kconfig
arch/arm/cpu/arm926ejs/kirkwood/Makefile
arch/arm/cpu/arm926ejs/kirkwood/cpu.c
arch/arm/cpu/arm926ejs/kirkwood/mpp.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/tegra-common/Kconfig
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-beaver.dts
arch/arm/dts/tegra30-cardhu.dts
arch/arm/dts/tegra30-colibri.dts
arch/arm/imx-common/i2c-mxv7.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-ls102xa/config.h
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-s5pc1xx/gpio.h
arch/arm/include/asm/arch-tegra114/tegra114_spi.h [deleted file]
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/imx-common/mxc_i2c.h
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/powerpc/cpu/mpc85xx/cpu_init.c
arch/powerpc/cpu/mpc85xx/fdt.c
arch/powerpc/cpu/mpc85xx/liodn.c
arch/powerpc/cpu/mpc8xxx/fdt.c
arch/powerpc/include/asm/config_mpc85xx.h
arch/powerpc/include/asm/immap_85xx.h
arch/powerpc/include/asm/types.h
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/start16.S
arch/x86/dts/link.dts
arch/x86/include/asm/bootm.h [new file with mode: 0644]
arch/x86/include/asm/config.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/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/freescale/ls1021aqds/MAINTAINERS
board/freescale/ls1021aqds/ls1021aqds.c
board/freescale/ls1021atwr/MAINTAINERS
board/freescale/ls1021atwr/ls1021atwr.c
board/iomega/iconnect/iconnect.c
board/karo/tk71/tk71.c
board/keymile/km_arm/km_arm.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/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/ti/ks2_evm/README [moved from board/ti/ks2_evm/README_K2HK with 68% similarity]
common/Makefile
common/board_r.c
common/bootm.c
common/cmd_blob.c [new file with mode: 0644]
common/cmd_bootm.c
common/cmd_sf.c
common/cmd_spi.c
common/cros_ec.c
common/env_sf.c
common/exports.c
common/image-fit.c
common/image.c
common/lcd.c
configs/db-mv784mp-gp_defconfig [new file with mode: 0644]
configs/k2e_evm_defconfig
configs/k2hk_evm_defconfig
configs/ls1021aqds_nor_SECURE_BOOT_defconfig [new file with mode: 0644]
configs/ls1021atwr_nor_SECURE_BOOT_defconfig [new file with mode: 0644]
configs/maxbcm_defconfig [new file with mode: 0644]
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/Makefile
drivers/core/device.c
drivers/core/lists.c
drivers/core/simple-bus.c [new file with mode: 0644]
drivers/core/uclass.c
drivers/crypto/Makefile
drivers/crypto/fsl/Makefile [new file with mode: 0644]
drivers/crypto/fsl/desc.h [new file with mode: 0644]
drivers/crypto/fsl/desc_constr.h [new file with mode: 0644]
drivers/crypto/fsl/error.c [new file with mode: 0644]
drivers/crypto/fsl/fsl_blob.c [new file with mode: 0644]
drivers/crypto/fsl/fsl_hash.c [new file with mode: 0644]
drivers/crypto/fsl/jobdesc.c [new file with mode: 0644]
drivers/crypto/fsl/jobdesc.h [new file with mode: 0644]
drivers/crypto/fsl/jr.c [new file with mode: 0644]
drivers/crypto/fsl/jr.h [new file with mode: 0644]
drivers/dfu/dfu_sf.c
drivers/gpio/bcm2835_gpio.c
drivers/gpio/kw_gpio.c
drivers/gpio/mxc_gpio.c
drivers/gpio/s5p_gpio.c
drivers/i2c/mvtwsi.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/mvebu_mmc.c
drivers/mmc/s5p_sdhci.c
drivers/mtd/nand/kirkwood_nand.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/mvgbe.c
drivers/net/mvneta.c [new file with mode: 0644]
drivers/power/axp152.c
drivers/rtc/mvrtc.h
drivers/serial/Makefile
drivers/serial/serial-uclass.c
drivers/serial/serial_mxc.c
drivers/serial/serial_pl01x.c
drivers/serial/serial_pl01x_internal.h [moved from drivers/serial/serial_pl01x.h with 100% similarity]
drivers/serial/serial_s5p.c
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-marvell.c
drivers/video/ipu_disp.c
drivers/video/mxc_ipuv3_fb.c
include/bootstage.h
include/compiler.h
include/config_fallbacks.h
include/configs/B4860QDS.h
include/configs/BSC9131RDB.h
include/configs/BSC9132QDS.h
include/configs/C29XPCIE.h
include/configs/P1010RDB.h
include/configs/P2041RDB.h
include/configs/T1040QDS.h
include/configs/T104xRDB.h
include/configs/T208xQDS.h
include/configs/T208xRDB.h
include/configs/T4240QDS.h
include/configs/T4240RDB.h
include/configs/cm_fx6.h
include/configs/coreboot.h
include/configs/corenet_ds.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/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/tqma6.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/uclass-id.h
include/dm/uclass.h
include/dm/util.h
include/fdtdec.h
include/fsl_sec.h [new file with mode: 0644]
include/image.h
include/libfdt.h
include/linker_lists.h
include/linux/mbus.h [new file with mode: 0644]
include/netdev.h
include/phy.h
include/serial_mxc.h [new file with mode: 0644]
include/serial_pl01x.h [new file with mode: 0644]
include/spi.h
include/spi_flash.h
lib/Kconfig
lib/fdtdec.c
lib/initcall.c
lib/libfdt/fdt_ro.c
lib/time.c
net/tftp.c
scripts/Makefile.spl
scripts/multiconfig.sh
test/dm/Makefile
test/dm/bus.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.dts
tools/Makefile
tools/kwbimage.c
tools/kwboot.c

index 8657417329ce7e029307ee77e8b764a42e3cbe26..26dacee98e07d0c203e0156bae557ea95a006d29 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@
 VERSION = 2014
 PATCHLEVEL = 10
 SUBLEVEL =
-EXTRAVERSION = -rc3
+EXTRAVERSION =
 NAME =
 
 # *DOCUMENTATION*
@@ -411,7 +411,7 @@ timestamp_h := include/generated/timestamp_autogenerated.h
 
 no-dot-config-targets := clean clobber mrproper distclean \
                         help %docs check% coccicheck \
-                        ubootversion backup tools-only
+                        ubootversion backup
 
 config-targets := 0
 mixed-targets  := 0
@@ -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 46def0086b8f3d95c77a78bda532eacdbab91c6e..3ff793266b87523c4fd22237760aadeef918a30c 100644 (file)
--- a/README
+++ b/README
@@ -544,6 +544,12 @@ The following options need to be configured:
                CONFIG_SYS_FSL_OTHER_DDR_NUM_CTRLS
                Number of controllers used for other than main memory.
 
+               CONFIG_SYS_FSL_SEC_BE
+               Defines the SEC controller register space as Big Endian
+
+               CONFIG_SYS_FSL_SEC_LE
+               Defines the SEC controller register space as Little Endian
+
 - Intel Monahans options:
                CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO
 
@@ -617,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
 
@@ -2716,6 +2715,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
@@ -2824,10 +2831,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 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)
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 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 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 {
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 dd6009af47cbef4ae3430229e775d8282cfe008a..572520a00ec5e330d5bbacd4b187967d45db8ec8 100644 (file)
@@ -16,6 +16,7 @@
                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 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;
 }
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 a500b5bc3b6581b9e72a73998d8ee3ded1d55034..f2c9687df42cb9da9cc480cc0d35b5255a400c9e 100644 (file)
@@ -19,6 +19,8 @@
 #define CONFIG_SYS_IFC_ADDR                    (CONFIG_SYS_IMMR + 0x00530000)
 #define CONFIG_SYS_FSL_ESDHC_ADDR              (CONFIG_SYS_IMMR + 0x00560000)
 #define CONFIG_SYS_FSL_SCFG_ADDR               (CONFIG_SYS_IMMR + 0x00570000)
+#define CONFIG_SYS_FSL_SEC_ADDR                        (CONFIG_SYS_IMMR + 0x700000)
+#define CONFIG_SYS_FSL_JR0_ADDR                        (CONFIG_SYS_IMMR + 0x710000)
 #define CONFIG_SYS_FSL_SERDES_ADDR             (CONFIG_SYS_IMMR + 0x00ea0000)
 #define CONFIG_SYS_FSL_GUTS_ADDR               (CONFIG_SYS_IMMR + 0x00ee0000)
 #define CONFIG_SYS_FSL_LS1_CLK_ADDR            (CONFIG_SYS_IMMR + 0x00ee1000)
@@ -66,6 +68,7 @@
 #define CONFIG_SYS_FSL_DSPI_BE
 #define CONFIG_SYS_FSL_QSPI_BE
 #define CONFIG_SYS_FSL_DCU_BE
+#define CONFIG_SYS_FSL_SEC_LE
 
 #define DCU_LAYER_MAX_NUM                      16
 
@@ -76,6 +79,7 @@
 #define CONFIG_SYS_FSL_IFC_BANK_COUNT          8
 #define CONFIG_NUM_DDR_CONTROLLERS             1
 #define CONFIG_SYS_FSL_DDR_VER                 FSL_DDR_VER_5_0
+#define CONFIG_SYS_FSL_SEC_COMPAT              5
 #else
 #error SoC not defined
 #endif
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  */
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/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_ */
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,
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 5bfab70b7edbac0d9ca15d124fab619db91c0192..85d32fc6128558ac8e169dc391b40b54c8d7b7e4 100644 (file)
@@ -27,6 +27,9 @@
 #include <hwconfig.h>
 #include <linux/compiler.h>
 #include "mp.h"
+#ifdef CONFIG_FSL_CAAM
+#include <fsl_sec.h>
+#endif
 #ifdef CONFIG_SYS_QE_FMAN_FW_IN_NAND
 #include <nand.h>
 #include <errno.h>
@@ -423,7 +426,8 @@ ulong cpu_init_f(void)
 {
        ulong flag = 0;
        extern void m8560_cpm_reset (void);
-#ifdef CONFIG_SYS_DCSRBAR_PHYS
+#if defined(CONFIG_SYS_DCSRBAR_PHYS) || \
+       (defined(CONFIG_SECURE_BOOT) && defined(CONFIG_FSL_CORENET))
        ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 #endif
 #if defined(CONFIG_SECURE_BOOT)
@@ -455,6 +459,12 @@ ulong cpu_init_f(void)
 #if defined(CONFIG_SYS_CPC_REINIT_F)
        disable_cpc_sram();
 #endif
+
+#if defined(CONFIG_FSL_CORENET)
+       /* Put PAMU in bypass mode */
+       out_be32(&gur->pamubypenr, FSL_CORENET_PAMU_BYPASS);
+#endif
+
 #endif
 
 #ifdef CONFIG_CPM2
@@ -803,7 +813,7 @@ int cpu_init_r(void)
 #ifdef CONFIG_SYS_FSL_ERRATUM_SEC_A003571
 #define MCFGR_AXIPIPE 0x000000f0
        if (IS_SVR_REV(svr, 1, 0))
-               clrbits_be32(&sec->mcfgr, MCFGR_AXIPIPE);
+               sec_clrbits32(&sec->mcfgr, MCFGR_AXIPIPE);
 #endif
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A005871
@@ -938,6 +948,10 @@ int cpu_init_r(void)
        fman_enet_init();
 #endif
 
+#ifdef CONFIG_FSL_CAAM
+       sec_init();
+#endif
+
 #if defined(CONFIG_FSL_SATA_V2) && defined(CONFIG_FSL_SATA_ERRATUM_A001)
        /*
         * For P1022/1013 Rev1.0 silicon, after power on SATA host
index 3222e26a5aa3e2ab66fc348ceb8e3782918d92c3..d4c3d9df9b8fe314fe17d97ef51d6371aaf2d09b 100644 (file)
@@ -714,7 +714,7 @@ void ft_cpu_setup(void *blob, bd_t *bd)
                ccsr_sec_t __iomem *sec;
 
                sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
-               fdt_fixup_crypto_node(blob, in_be32(&sec->secvid_ms));
+               fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
        }
 #endif
 
index 19e130e87f1986f01e46c4609997def84da433b1..7a2d4be42cec34495b814b4fafcc8ea397151913 100644 (file)
@@ -66,12 +66,12 @@ static void setup_sec_liodn_base(void)
                return;
 
        /* QILCR[QSLOM] */
-       out_be32(&sec->qilcr_ms, 0x3ff<<16);
+       sec_out32(&sec->qilcr_ms, 0x3ff<<16);
 
        base = (liodn_bases[FSL_HW_PORTAL_SEC].id[0] << 16) |
                liodn_bases[FSL_HW_PORTAL_SEC].id[1];
 
-       out_be32(&sec->qilcr_ls, base);
+       sec_out32(&sec->qilcr_ls, base);
 }
 
 #ifdef CONFIG_SYS_DPAA_FMAN
index 4cec5e118ffc7d6666fde11e988cd3f7bbf02aa2..c6b4d955496e0c69d2d1179480036f885af909fd 100644 (file)
@@ -287,8 +287,8 @@ static u8 caam_get_era(void)
        };
 
        ccsr_sec_t __iomem *sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
-       u32 secvid_ms = in_be32(&sec->secvid_ms);
-       u32 ccbvid = in_be32(&sec->ccbvid);
+       u32 secvid_ms = sec_in32(&sec->secvid_ms);
+       u32 ccbvid = sec_in32(&sec->ccbvid);
        u16 ip_id = (secvid_ms & SEC_SECVID_MS_IPID_MASK) >>
                                SEC_SECVID_MS_IPID_SHIFT;
        u8 maj_rev = (secvid_ms & SEC_SECVID_MS_MAJ_REV_MASK) >>
index 712f2ef4b3020aab86eefd459b0d9e324e068924..4c1774f503c834ee26877d58cddbd92a026865e6 100644 (file)
@@ -24,6 +24,7 @@
 
 /* IP endianness */
 #define CONFIG_SYS_FSL_IFC_BE
+#define CONFIG_SYS_FSL_SEC_BE
 
 /* Number of TLB CAM entries we have on FSL Book-E chips */
 #if defined(CONFIG_E500MC)
index dfb370e051b295d64226f203b4be23ed297e9e53..0264523d6402779e094ed5fee993f9fddcc95be0 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/fsl_dma.h>
 #include <asm/fsl_i2c.h>
 #include <fsl_ifc.h>
+#include <fsl_sec.h>
 #include <asm/fsl_lbc.h>
 #include <asm/fsl_fman.h>
 #include <fsl_immap.h>
@@ -1911,6 +1912,7 @@ defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022)
        u8      res24[64];
        u32     pblsr;          /* Preboot loader status */
        u32     pamubypenr;     /* PAMU bypass enable */
+#define FSL_CORENET_PAMU_BYPASS                0xffff0000
        u32     dmacr1;         /* DMA control */
        u8      res25[4];
        u32     gensr1;         /* General status */
@@ -2675,72 +2677,6 @@ enum {
        FSL_SRDS_B3_LANE_D = 23,
 };
 
-/* Security Engine Block (MS = Most Sig., LS = Least Sig.) */
-#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
-typedef struct ccsr_sec {
-       u32     res0;
-       u32     mcfgr;          /* Master CFG Register */
-       u8      res1[0x8];
-       struct {
-               u32     ms;     /* Job Ring LIODN Register, MS */
-               u32     ls;     /* Job Ring LIODN Register, LS */
-       } jrliodnr[4];
-       u8      res2[0x30];
-       struct {
-               u32     ms;     /* RTIC LIODN Register, MS */
-               u32     ls;     /* RTIC LIODN Register, LS */
-       } rticliodnr[4];
-       u8      res3[0x1c];
-       u32     decorr;         /* DECO Request Register */
-       struct {
-               u32     ms;     /* DECO LIODN Register, MS */
-               u32     ls;     /* DECO LIODN Register, LS */
-       } decoliodnr[8];
-       u8      res4[0x40];
-       u32     dar;            /* DECO Avail Register */
-       u32     drr;            /* DECO Reset Register */
-       u8      res5[0xe78];
-       u32     crnr_ms;        /* CHA Revision Number Register, MS */
-       u32     crnr_ls;        /* CHA Revision Number Register, LS */
-       u32     ctpr_ms;        /* Compile Time Parameters Register, MS */
-       u32     ctpr_ls;        /* Compile Time Parameters Register, LS */
-       u8      res6[0x10];
-       u32     far_ms;         /* Fault Address Register, MS */
-       u32     far_ls;         /* Fault Address Register, LS */
-       u32     falr;           /* Fault Address LIODN Register */
-       u32     fadr;           /* Fault Address Detail Register */
-       u8      res7[0x4];
-       u32     csta;           /* CAAM Status Register */
-       u8      res8[0x8];
-       u32     rvid;           /* Run Time Integrity Checking Version ID Reg.*/
-       u32     ccbvid;         /* CHA Cluster Block Version ID Register */
-       u32     chavid_ms;      /* CHA Version ID Register, MS */
-       u32     chavid_ls;      /* CHA Version ID Register, LS */
-       u32     chanum_ms;      /* CHA Number Register, MS */
-       u32     chanum_ls;      /* CHA Number Register, LS */
-       u32     secvid_ms;      /* SEC Version ID Register, MS */
-       u32     secvid_ls;      /* SEC Version ID Register, LS */
-       u8      res9[0x6020];
-       u32     qilcr_ms;       /* Queue Interface LIODN CFG Register, MS */
-       u32     qilcr_ls;       /* Queue Interface LIODN CFG Register, LS */
-       u8      res10[0x8fd8];
-} ccsr_sec_t;
-
-#define SEC_CTPR_MS_AXI_LIODN          0x08000000
-#define SEC_CTPR_MS_QI                 0x02000000
-#define SEC_RVID_MA                    0x0f000000
-#define SEC_CHANUM_MS_JRNUM_MASK       0xf0000000
-#define SEC_CHANUM_MS_JRNUM_SHIFT      28
-#define SEC_CHANUM_MS_DECONUM_MASK     0x0f000000
-#define SEC_CHANUM_MS_DECONUM_SHIFT    24
-#define SEC_SECVID_MS_IPID_MASK        0xffff0000
-#define SEC_SECVID_MS_IPID_SHIFT       16
-#define SEC_SECVID_MS_MAJ_REV_MASK     0x0000ff00
-#define SEC_SECVID_MS_MAJ_REV_SHIFT    8
-#define SEC_CCBVID_ERA_MASK            0xff000000
-#define SEC_CCBVID_ERA_SHIFT           24
-#endif
-
 typedef struct ccsr_qman {
 #ifdef CONFIG_SYS_FSL_QMAN_V3
        u8      res0[0x200];
@@ -2940,6 +2876,7 @@ struct ccsr_sfp_regs {
 #define CONFIG_SYS_MPC85xx_SATA1_OFFSET                0x220000
 #define CONFIG_SYS_MPC85xx_SATA2_OFFSET                0x221000
 #define CONFIG_SYS_FSL_SEC_OFFSET              0x300000
+#define CONFIG_SYS_FSL_JR0_OFFSET              0x301000
 #define CONFIG_SYS_FSL_CORENET_PME_OFFSET      0x316000
 #define CONFIG_SYS_FSL_QMAN_OFFSET             0x318000
 #define CONFIG_SYS_FSL_BMAN_OFFSET             0x31a000
@@ -3000,8 +2937,10 @@ struct ccsr_sfp_regs {
 #define CONFIG_SYS_MPC85xx_ESDHC_OFFSET                0x2e000
 #if defined(CONFIG_PPC_C29X)
 #define CONFIG_SYS_FSL_SEC_OFFSET              0x80000
+#define CONFIG_SYS_FSL_JR0_OFFSET               0x81000
 #else
 #define CONFIG_SYS_FSL_SEC_OFFSET              0x30000
+#define CONFIG_SYS_FSL_JR0_OFFSET               0x31000
 #endif
 #define CONFIG_SYS_MPC85xx_SERDES2_OFFSET      0xE3100
 #define CONFIG_SYS_MPC85xx_SERDES1_OFFSET      0xE3000
@@ -3106,6 +3045,8 @@ struct ccsr_sfp_regs {
        (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_USB2_PHY_OFFSET)
 #define CONFIG_SYS_FSL_SEC_ADDR \
        (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_SEC_OFFSET)
+#define CONFIG_SYS_FSL_JR0_ADDR \
+       (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_JR0_OFFSET)
 #define CONFIG_SYS_FSL_FM1_ADDR \
        (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_FM1_OFFSET)
 #define CONFIG_SYS_FSL_FM1_DTSEC1_ADDR \
index b27a6b753a06cb02f55d187badc8e2f915af761d..b29ce792f7231a0b3e25cb1ff3b172c9fa522553 100644 (file)
@@ -41,8 +41,12 @@ typedef unsigned long long u64;
 
 #define BITS_PER_LONG 32
 
+#ifdef CONFIG_PHYS_64BIT
+typedef unsigned long long dma_addr_t;
+#else
 /* DMA addresses are 32-bits wide */
 typedef u32 dma_addr_t;
+#endif
 
 #ifdef CONFIG_PHYS_64BIT
 typedef unsigned long long phys_addr_t;
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 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 4a37dac4ea9adc470005da949b281f0e18923ef6..67ce52a102eff53565f71c29a3ec0f0d249a045f 100644 (file)
                        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/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 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..2f0e92f123a5acaa06a6c2f031cec72766d06099 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);
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 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..f77ff48a1c3fb69f7bc04ec22f8cf95ac291122b 100644 (file)
@@ -9,11 +9,13 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fsl_esdhc.h>
 #include <miiphy.h>
 #include <netdev.h>
 #include <fdt_support.h>
 #include <sata.h>
+#include <serial_mxc.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/iomux.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 ccf45131b8735da2a8081a6de39ddd1e393a7e54..e30e94471b1d2feb6f3447ed093e606db93ec866 100644 (file)
@@ -5,3 +5,4 @@ F:      board/freescale/ls1021aqds/
 F:     include/configs/ls1021aqds.h
 F:     configs/ls1021aqds_nor_defconfig
 F:     configs/ls1021aqds_ddr4_nor_defconfig
+F:     configs/ls1021aqds_nor_SECURE_BOOT_defconfig
index 12e83f764546e5ae5b372de84b569036c9373079..5fafc8567207d3d777f40567dfb90aec92670196 100644 (file)
@@ -13,6 +13,7 @@
 #include <mmc.h>
 #include <fsl_esdhc.h>
 #include <fsl_ifc.h>
+#include <fsl_sec.h>
 
 #include "../common/qixis.h"
 #include "ls1021aqds_qixis.h"
@@ -213,6 +214,15 @@ int config_serdes_mux(void)
        return 0;
 }
 
+#if defined(CONFIG_MISC_INIT_R)
+int misc_init_r(void)
+{
+#ifdef CONFIG_FSL_CAAM
+       return sec_init();
+#endif
+}
+#endif
+
 int board_init(void)
 {
        struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
index 4e5bc15a0d6cb61fb43889f270f7f58261688256..8def0e5ac4b8ba0f6f538d40d5b6a2e0fb952d69 100644 (file)
@@ -4,3 +4,4 @@ S:      Maintained
 F:     board/freescale/ls1021atwr/
 F:     include/configs/ls1021atwr.h
 F:     configs/ls1021atwr_nor_defconfig
+F:     configs/ls1021atwr_nor_SECURE_BOOT_defconfig
index b522ff28e5eb8e7c87ffd6c10430beaa5798669b..50d564055b173ddd2ee46db63b2797168e7e2544 100644 (file)
@@ -16,6 +16,7 @@
 #include <netdev.h>
 #include <fsl_mdio.h>
 #include <tsec.h>
+#include <fsl_sec.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -280,6 +281,15 @@ int board_init(void)
        return 0;
 }
 
+#if defined(CONFIG_MISC_INIT_R)
+int misc_init_r(void)
+{
+#ifdef CONFIG_FSL_CAAM
+       return sec_init();
+#endif
+}
+#endif
+
 void ft_board_setup(void *blob, bd_t *bd)
 {
        ft_cpu_setup(blob, bd);
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 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
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..03f055dad2aa4d2ff72b26f36b5a23e01849d6a6 100644 (file)
@@ -114,9 +114,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
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 220bb90dc1ae025ddf37e8fe9636201843c00650..447c940f63154aa560881046a1d742b6bc1e7d5e 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..e1fc123fcc4ea154cd4e189460a8afb3e1713399 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>
@@ -87,9 +87,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);
 
similarity index 68%
rename from board/ti/ks2_evm/README_K2HK
rename to board/ti/ks2_evm/README
index 7426b8dc9775d8c7f9e193f8c1c761abaf975ef0..a551e2869a3858f17111cb8f5614522c1b24ec97 100644 (file)
@@ -1,46 +1,56 @@
-U-Boot port for Texas Instruments XTCIEVMK2X
-============================================
+U-Boot port for Texas Instruments Keystone II EVM boards
+========================================================
 
 Author: Murali Karicheri <m-karicheri2@ti.com>
 
-This README has information on the u-boot port for XTCIEVMK2X EVM board.
+This README has information on the u-boot port for K2HK, K2E boards.
 Documentation for this board can be found at
-  http://www.advantech.com/Support/TI-EVM/EVMK2HX_sd.aspx
+http://www.advantech.com/Support/TI-EVM/EVMK2HX_sd.aspx
+https://www.einfochips.com/index.php/partnerships/texas-instruments/k2e-evm.html
 
-The board is based on Texas Instruments Keystone2 family of SoCs : K2H, K2K.
+The K2HK board is based on Texas Instruments Keystone2 family of SoCs: K2H, K2K.
 More details on these SoCs are available at company websites
  K2K: http://www.ti.com/product/tci6638k2k
  K2H: http://www.ti.com/product/tci6638k2h
 
+The K2E SoC details are available at
+ K2E http://www.ti.com/lit/ds/symlink/66ak2e05.pdf
+
 Board configuration:
 ====================
 
-Some of the peripherals that are configured by u-boot are:-
+Some of the peripherals that are configured by u-boot
++------+-------+-------+-----------+-----------+-------+-------+----+
+|      |DDR3   |NAND   |MSM SRAM   |ETH ports  |UART   |I2C    |SPI |
++------+-------+-------+-----------+-----------+-------+-------+----+
+|K2HK  |2      |512MB  |6MB       |4(2)       |2      |3      |3   |
+|K2E   |4      |512MB  |2MB       |8(2)       |2      |3      |3   |
++------+-------+-------+-----------+-----------+-------+-------+----+
 
-1. 2GB DDR3 (can support 8GB SO DIMM as well)
-2. 512M NAND (over ti emif16 bus)
-3. 6MB MSM SRAM (part of the SoC)
-4. two 1GBit Ethernet ports (SoC supports upto 4)
-5. two UART ports
-6. three i2c interfaces
-7. three spi interfaces (only 1 interface supported in driver)
+There are only 2 eth port installed on the boards.
 
-There are seperate PLLs to drive clocks to Tetris ARM and Peripherals.
+There are separate PLLs to drive clocks to Tetris ARM and Peripherals.
 To bring up SMP Linux on this board, there is a boot monitor
 code that will be installed in MSMC SRAM. There is command available
 to install this image from u-boot.
 
 The port related files can be found at following folders
  keystone2 SoC related files: arch/arm/cpu/armv7/keystone/
- K2HK evm board files: board/ti/k2hk_evm/
+ EVMs board files: board/ti/k2s_evm/
+
+Board configuration files:
+include/configs/k2hk_evm.h
+include/configs/k2e_evm.h
 
-board configuration file: include/configs/k2hk_evm.h
+As u-boot is migrating to Kconfig there is also board defconfig files
+configs/k2e_evm_defconfig
+configs/k2hk_evm_defconfig
 
 Supported boot modes:
  - SPI NOR boot
  - AEMIF NAND boot
 
-Supported image formats:-
+Supported image formats:
  - u-boot.bin: for loading and running u-boot.bin through Texas instruments
                code composure studio (CCS)
  - u-boot-spi.gph: gpimage for programming SPI NOR flash for SPI NOR boot
@@ -48,29 +58,32 @@ Supported image formats:-
 
 Build instructions:
 ===================
+Examples for k2hk, for k2e just replace k2hk prefix accordingly.
+Don't forget to add ARCH=arm and CROSS_COMPILE.
 
 To build u-boot.bin
-  >make k2hk_evm_config
+  >make k2hk_evm_defconfig
   >make u-boot-spi.gph
 
 To build u-boot-spi.gph
-  >make k2hk_evm_config
+  >make k2hk_evm_defconfig
   >make u-boot-spi.gph
 
 To build u-boot-nand.gph
-  >make k2hk_evm_config
+  >make k2hk_evm_defconfig
   >make u-boot-nand.gph
 
-Load and Run U-Boot on K2HK EVM using CCS
+Load and Run U-Boot on keystone EVMs using CCS
 =========================================
 
 Need Code Composer Studio (CCS) installed on a PC to load and run u-boot.bin
 on EVM. See instructions at below link for installing CCS on a Windows PC.
 http://processors.wiki.ti.com/index.php/MCSDK_UG_Chapter_Getting_Started#
 Installing_Code_Composer_Studio
-Use u-boot.bin from the build folder for loading annd running u-boot binary
+Use u-boot.bin from the build folder for loading and running u-boot binary
 on EVM. Follow instructions at
-http://processors.wiki.ti.com/index.php/EVMK2H_Hardware_Setup
+K2HK http://processors.wiki.ti.com/index.php/EVMK2H_Hardware_Setup
+K2E  http://processors.wiki.ti.com/index.php/EVMK2E_Hardware_Setup
 to configure SW1 dip switch to use "No Boot/JTAG DSP Little Endian Boot Mode"
 and Power ON the EVM.  Follow instructions to connect serial port of EVM to
 PC and start TeraTerm or Hyper Terminal.
@@ -82,7 +95,7 @@ The instructions provided in the above link uses a script for
 loading the u-boot binary on the target EVM. Instead do the following:-
 
 1. Right click to "Texas Instruments XDS2xx USB Emulator_0/CortexA15_1 core (D
-   isconnected: Unknown)" at the debug window (This is created once Target
+   is connected: Unknown)" at the debug window (This is created once Target
    configuration is launched) and select "Connect Target".
 2. Once target connect is successful, choose Tools->Load Memory option from the
    top level menu. At the Load Memory window, choose the file u-boot.bin
@@ -109,28 +122,28 @@ Hit any key to stop autoboot:  0
 SPI NOR Flash programming instructions
 ======================================
 U-Boot image can be flashed to first 512KB of the NOR flash using following
-instructions:-
+instructions:
 
 1. Start CCS and run U-boot as described above.
 2. Suspend Target. Select Run -> Suspend from top level menu
    CortexA15_1 (Free Running)"
 3. Load u-boot-spi.gph binary from build folder on to DDR address 0x87000000
-   through CCS as described in step 2 of "Load and Run U-Boot on K2HK EVM
+   through CCS as described in step 2 of "Load and Run U-Boot on K2HK/K2E EVM
    using CCS", but using address 0x87000000.
-4. Free Run the target as desribed earlier (step 4) to get u-boot prompt
+4. Free Run the target as described earlier (step 4) to get u-boot prompt
 5. At the U-Boot console type following to setup u-boot environment variables.
    setenv addr_uboot 0x87000000
    setenv filesize <size in hex of u-boot-spi.gph rounded to hex 0x10000>
    run burn_uboot_spi
    Once u-boot prompt is available, Power OFF the EVM. Set the SW1 dip switch
    to "SPI Little Endian Boot mode" as per instruction at
-   http://processors.wiki.ti.com/index.php/EVMK2H_Hardware_Setup.
+   http://processors.wiki.ti.com/index.php/*_Hardware_Setup.
 6. Power ON the EVM. The EVM now boots with u-boot image on the NOR flash.
 
 AEMIF NAND Flash programming instructions
 ======================================
 U-Boot image can be flashed to first 1024KB of the NAND flash using following
-instructions:-
+instructions:
 
 1. Start CCS and run U-boot as described above.
 2. Suspend Target. Select Run -> Suspend from top level menu
@@ -138,11 +151,11 @@ instructions:-
 3. Load u-boot-nand.gph binary from build folder on to DDR address 0x87000000
    through CCS as described in step 2 of "Load and Run U-Boot on K2HK EVM
    using CCS", but using address 0x87000000.
-4. Free Run the target as desribed earlier (step 4) to get u-boot prompt
+4. Free Run the target as described earlier (step 4) to get u-boot prompt
 5. At the U-Boot console type following to setup u-boot environment variables.
    setenv filesize <size in hex of u-boot-nand.gph rounded to hex 0x10000>
    run burn_uboot_nand
    Once u-boot prompt is available, Power OFF the EVM. Set the SW1 dip switch
    to "ARM NAND Boot mode" as per instruction at
-   http://processors.wiki.ti.com/index.php/EVMK2H_Hardware_Setup.
+   http://processors.wiki.ti.com/index.php/*_Hardware_Setup.
 6. Power ON the EVM. The EVM now boots with u-boot image on the NAND flash.
index b19d3793b467b0e8d88ffb6ae287a1ebf1b9a833..c84b3bc102a418d3f62bd68934c6f7aa53286c11 100644 (file)
@@ -265,4 +265,6 @@ obj-y += aboot.o
 obj-y += fb_mmc.o
 endif
 
+obj-$(CONFIG_CMD_BLOB) += cmd_blob.o
+
 CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null)
index 7e1a76d97f73be5d2eb3d347dffbb82d301b7522..3affb6362f4531ebd3f313248df1fbd7c588e7bf 100644 (file)
@@ -354,7 +354,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 */
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) {
diff --git a/common/cmd_blob.c b/common/cmd_blob.c
new file mode 100644 (file)
index 0000000..82ecaf0
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *
+ * Command for encapsulating/decapsulating blob of memory.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * blob_decap() - Decapsulate the data as a blob
+ * @key_mod:   - Pointer to key modifier/key
+ * @src:       - Address of data to be decapsulated
+ * @dst:       - Address of data to be decapsulated
+ * @len:       - Size of data to be decapsulated
+ *
+ * Returns zero on success,and negative on error.
+ */
+__weak int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
+{
+       return 0;
+}
+
+/**
+ * blob_encap() - Encapsulate the data as a blob
+ * @key_mod:   - Pointer to key modifier/key
+ * @src:       - Address of data to be encapsulated
+ * @dst:       - Address of data to be encapsulated
+ * @len:       - Size of data to be encapsulated
+ *
+ * Returns zero on success,and negative on error.
+ */
+__weak int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
+{
+       return 0;
+}
+
+/**
+ * do_blob() - Handle the "blob" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_blob(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       uint32_t key_addr, src_addr, dst_addr, len;
+       uint8_t *km_ptr, *src_ptr, *dst_ptr;
+       int enc, ret = 0;
+
+       if (argc != 6)
+               return CMD_RET_USAGE;
+
+       if (!strncmp(argv[1], "enc", 3))
+               enc = 1;
+       else if (!strncmp(argv[1], "dec", 3))
+               enc = 0;
+       else
+               return CMD_RET_USAGE;
+
+       src_addr = simple_strtoul(argv[2], NULL, 16);
+       dst_addr = simple_strtoul(argv[3], NULL, 16);
+       len = simple_strtoul(argv[4], NULL, 16);
+       key_addr = simple_strtoul(argv[5], NULL, 16);
+
+       km_ptr = (uint8_t *)key_addr;
+       src_ptr = (uint8_t *)src_addr;
+       dst_ptr = (uint8_t *)dst_addr;
+
+       if (enc)
+               ret = blob_encap(km_ptr, src_ptr, dst_ptr, len);
+       else
+               ret = blob_decap(km_ptr, src_ptr, dst_ptr, len);
+
+       return ret;
+}
+
+/***************************************************/
+static char blob_help_text[] =
+       "enc src dst len km - Encapsulate and create blob of data\n"
+       "                          $len bytes long at address $src and\n"
+       "                          store the result at address $dst.\n"
+       "                          $km is the 16 byte key modifier\n"
+       "                          is also required for generation/use as\n"
+       "                          key for cryptographic operation. Key\n"
+       "                          modifier should be 16 byte long.\n"
+       "blob dec src dst len km - Decapsulate the  blob of data at address\n"
+       "                          $src and store result of $len byte at\n"
+       "                          addr $dst.\n"
+       "                          $km is the 16 byte key modifier\n"
+       "                          is also required for generation/use as\n"
+       "                          key for cryptographic operation. Key\n"
+       "                          modifier should be 16 byte long.\n";
+
+U_BOOT_CMD(
+       blob, 6, 1, do_blob,
+       "Blob encapsulation/decryption",
+       blob_help_text
+);
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 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 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 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..2016d1e7dda85a34c5d1c787015bd309ed6061da 100644 (file)
@@ -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 217ec9dbd2e9ec3cefdaea4a63e5be2725b445dc..689d30eb25c9ad898237c92bd7401bfea0a7976b 100644 (file)
@@ -1023,7 +1023,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
 
        switch (bmp_bpix) {
        case 1: /* pass through */
-       case 8:
+       case 8: {
 #ifdef CONFIG_LCD_BMP_RLE8
                u32 compression = get_unaligned_le32(&bmp->header.compression);
                if (compression == BMP_BI_RLE8) {
@@ -1056,7 +1056,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
                        fb -= byte_width + lcd_line_length;
                }
                break;
-
+       }
 #if defined(CONFIG_BMP_16BPP)
        case 16:
                for (i = 0; i < height; ++i) {
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
index be8d2ee5e90ed5e3257c5a5c916cb1220bb63dad..9e702198becc245db090ee65490e56535f143f13 100644 (file)
@@ -1,3 +1,4 @@
-CONFIG_ARM=y
-CONFIG_ARCH_KEYSTONE=y
-CONFIG_TARGET_K2E_EVM=y
+CONFIG_SPL=y
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_KEYSTONE=y
++S:CONFIG_TARGET_K2E_EVM=y
index eee3335487fda99f83966ef5ede884e3f18392e8..e04e3151b65ff44769a75e748281401f18d6bee4 100644 (file)
@@ -1,3 +1,4 @@
-CONFIG_ARM=y
-CONFIG_ARCH_KEYSTONE=y
-CONFIG_TARGET_K2HK_EVM=y
+CONFIG_SPL=y
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_KEYSTONE=y
++S:CONFIG_TARGET_K2HK_EVM=y
diff --git a/configs/ls1021aqds_nor_SECURE_BOOT_defconfig b/configs/ls1021aqds_nor_SECURE_BOOT_defconfig
new file mode 100644 (file)
index 0000000..2b47995
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_SYS_EXTRA_OPTIONS="SECURE_BOOT"
+CONFIG_ARM=y
+CONFIG_TARGET_LS1021AQDS=y
diff --git a/configs/ls1021atwr_nor_SECURE_BOOT_defconfig b/configs/ls1021atwr_nor_SECURE_BOOT_defconfig
new file mode 100644 (file)
index 0000000..eeeb0d5
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_SYS_EXTRA_OPTIONS="SECURE_BOOT"
+CONFIG_ARM=y
+CONFIG_TARGET_LS1021ATWR=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
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..8dfcf75c3d369219b8cbc15782723013b94b0129 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 22 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
@@ -358,7 +359,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 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 b8077953c5617ed8c8b232570efabfa9c10e9fa2..7b792371811eb37e7dadcf39310e65f955237678 100644 (file)
@@ -6,3 +6,4 @@
 #
 
 obj-$(CONFIG_EXYNOS_ACE_SHA)   += ace_sha.o
+obj-y += fsl/
diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
new file mode 100644 (file)
index 0000000..cb13d2e
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Copyright 2014 Freescale Semiconductor, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# Version 2 as published by the Free Software Foundation.
+#
+
+obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
+obj-$(CONFIG_CMD_BLOB) += fsl_blob.o
diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h
new file mode 100644 (file)
index 0000000..504f2b0
--- /dev/null
@@ -0,0 +1,651 @@
+/*
+ * CAAM descriptor composition header
+ * Definitions to support CAAM descriptor instruction generation
+ *
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Based on desc.h file in linux drivers/crypto/caam
+ */
+
+#ifndef DESC_H
+#define DESC_H
+
+/* Max size of any CAAM descriptor in 32-bit words, inclusive of header */
+#define MAX_CAAM_DESCSIZE      64
+
+/* Block size of any entity covered/uncovered with a KEK/TKEK */
+#define KEK_BLOCKSIZE          16
+/*
+ * Supported descriptor command types as they show up
+ * inside a descriptor command word.
+ */
+#define CMD_SHIFT              27
+#define CMD_MASK               0xf8000000
+
+#define CMD_KEY                        (0x00 << CMD_SHIFT)
+#define CMD_SEQ_KEY            (0x01 << CMD_SHIFT)
+#define CMD_LOAD               (0x02 << CMD_SHIFT)
+#define CMD_SEQ_LOAD           (0x03 << CMD_SHIFT)
+#define CMD_FIFO_LOAD          (0x04 << CMD_SHIFT)
+#define CMD_SEQ_FIFO_LOAD      (0x05 << CMD_SHIFT)
+#define CMD_STORE              (0x0a << CMD_SHIFT)
+#define CMD_SEQ_STORE          (0x0b << CMD_SHIFT)
+#define CMD_FIFO_STORE         (0x0c << CMD_SHIFT)
+#define CMD_SEQ_FIFO_STORE     (0x0d << CMD_SHIFT)
+#define CMD_MOVE_LEN           (0x0e << CMD_SHIFT)
+#define CMD_MOVE               (0x0f << CMD_SHIFT)
+#define CMD_OPERATION          (0x10 << CMD_SHIFT)
+#define CMD_SIGNATURE          (0x12 << CMD_SHIFT)
+#define CMD_JUMP               (0x14 << CMD_SHIFT)
+#define CMD_MATH               (0x15 << CMD_SHIFT)
+#define CMD_DESC_HDR           (0x16 << CMD_SHIFT)
+#define CMD_SHARED_DESC_HDR    (0x17 << CMD_SHIFT)
+#define CMD_SEQ_IN_PTR         (0x1e << CMD_SHIFT)
+#define CMD_SEQ_OUT_PTR                (0x1f << CMD_SHIFT)
+
+/* General-purpose class selector for all commands */
+#define CLASS_SHIFT            25
+#define CLASS_MASK             (0x03 << CLASS_SHIFT)
+
+#define CLASS_NONE             (0x00 << CLASS_SHIFT)
+#define CLASS_1                        (0x01 << CLASS_SHIFT)
+#define CLASS_2                        (0x02 << CLASS_SHIFT)
+#define CLASS_BOTH             (0x03 << CLASS_SHIFT)
+
+/*
+ * Descriptor header command constructs
+ * Covers shared, job, and trusted descriptor headers
+ */
+
+/*
+ * Do Not Run - marks a descriptor inexecutable if there was
+ * a preceding error somewhere
+ */
+#define HDR_DNR                        0x01000000
+
+/*
+ * ONE - should always be set. Combination of ONE (always
+ * set) and ZRO (always clear) forms an endianness sanity check
+ */
+#define HDR_ONE                        0x00800000
+#define HDR_ZRO                        0x00008000
+
+/* Start Index or SharedDesc Length */
+#define HDR_START_IDX_MASK     0x3f
+#define HDR_START_IDX_SHIFT    16
+
+/* If shared descriptor header, 6-bit length */
+#define HDR_DESCLEN_SHR_MASK   0x3f
+
+/* If non-shared header, 7-bit length */
+#define HDR_DESCLEN_MASK       0x7f
+
+/* This is a TrustedDesc (if not SharedDesc) */
+#define HDR_TRUSTED            0x00004000
+
+/* Make into TrustedDesc (if not SharedDesc) */
+#define HDR_MAKE_TRUSTED       0x00002000
+
+/* Save context if self-shared (if SharedDesc) */
+#define HDR_SAVECTX            0x00001000
+
+/* Next item points to SharedDesc */
+#define HDR_SHARED             0x00001000
+
+/*
+ * Reverse Execution Order - execute JobDesc first, then
+ * execute SharedDesc (normally SharedDesc goes first).
+ */
+#define HDR_REVERSE            0x00000800
+
+/* Propogate DNR property to SharedDesc */
+#define HDR_PROP_DNR           0x00000800
+
+/* JobDesc/SharedDesc share property */
+#define HDR_SD_SHARE_MASK      0x03
+#define HDR_SD_SHARE_SHIFT     8
+#define HDR_JD_SHARE_MASK      0x07
+#define HDR_JD_SHARE_SHIFT     8
+
+#define HDR_SHARE_NEVER                (0x00 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_WAIT         (0x01 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_SERIAL       (0x02 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_ALWAYS       (0x03 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_DEFER                (0x04 << HDR_SD_SHARE_SHIFT)
+
+/* JobDesc/SharedDesc descriptor length */
+#define HDR_JD_LENGTH_MASK     0x7f
+#define HDR_SD_LENGTH_MASK     0x3f
+
+/*
+ * KEY/SEQ_KEY Command Constructs
+ */
+
+/* Key Destination Class: 01 = Class 1, 02 - Class 2 */
+#define KEY_DEST_CLASS_SHIFT   25      /* use CLASS_1 or CLASS_2 */
+#define KEY_DEST_CLASS_MASK    (0x03 << KEY_DEST_CLASS_SHIFT)
+
+/* Scatter-Gather Table/Variable Length Field */
+#define KEY_SGF                        0x01000000
+#define KEY_VLF                        0x01000000
+
+/* Immediate - Key follows command in the descriptor */
+#define KEY_IMM                        0x00800000
+
+/*
+ * Encrypted - Key is encrypted either with the KEK, or
+ * with the TDKEK if TK is set
+ */
+#define KEY_ENC                        0x00400000
+
+/*
+ * No Write Back - Do not allow key to be FIFO STOREd
+ */
+#define KEY_NWB                        0x00200000
+
+/*
+ * Enhanced Encryption of Key
+ */
+#define KEY_EKT                        0x00100000
+
+/*
+ * Encrypted with Trusted Key
+ */
+#define KEY_TK                 0x00008000
+
+/*
+ * KDEST - Key Destination: 0 - class key register,
+ * 1 - PKHA 'e', 2 - AFHA Sbox, 3 - MDHA split-key
+ */
+#define KEY_DEST_SHIFT         16
+#define KEY_DEST_MASK          (0x03 << KEY_DEST_SHIFT)
+
+#define KEY_DEST_CLASS_REG     (0x00 << KEY_DEST_SHIFT)
+#define KEY_DEST_PKHA_E                (0x01 << KEY_DEST_SHIFT)
+#define KEY_DEST_AFHA_SBOX     (0x02 << KEY_DEST_SHIFT)
+#define KEY_DEST_MDHA_SPLIT    (0x03 << KEY_DEST_SHIFT)
+
+/* Length in bytes */
+#define KEY_LENGTH_MASK                0x000003ff
+
+/*
+ * LOAD/SEQ_LOAD/STORE/SEQ_STORE Command Constructs
+ */
+
+/*
+ * Load/Store Destination: 0 = class independent CCB,
+ * 1 = class 1 CCB, 2 = class 2 CCB, 3 = DECO
+ */
+#define LDST_CLASS_SHIFT       25
+#define LDST_CLASS_MASK                (0x03 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_IND_CCB     (0x00 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_1_CCB       (0x01 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_2_CCB       (0x02 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_DECO                (0x03 << LDST_CLASS_SHIFT)
+
+/* Scatter-Gather Table/Variable Length Field */
+#define LDST_SGF               0x01000000
+#define LDST_VLF               LDST_SGF
+
+/* Immediate - Key follows this command in descriptor */
+#define LDST_IMM_MASK          1
+#define LDST_IMM_SHIFT         23
+#define LDST_IMM               (LDST_IMM_MASK << LDST_IMM_SHIFT)
+
+/* SRC/DST - Destination for LOAD, Source for STORE */
+#define LDST_SRCDST_SHIFT      16
+#define LDST_SRCDST_MASK       (0x7f << LDST_SRCDST_SHIFT)
+
+#define LDST_SRCDST_BYTE_CONTEXT       (0x20 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_BYTE_KEY           (0x40 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_BYTE_INFIFO                (0x7c << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_BYTE_OUTFIFO       (0x7e << LDST_SRCDST_SHIFT)
+
+#define LDST_SRCDST_WORD_MODE_REG      (0x00 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_KEYSZ_REG     (0x01 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DATASZ_REG    (0x02 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_ICVSZ_REG     (0x03 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_CHACTRL       (0x06 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECOCTRL      (0x06 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_IRQCTRL       (0x07 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_PCLOVRD  (0x07 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_CLRW          (0x08 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH0    (0x08 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_STAT          (0x09 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH1    (0x09 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH2    (0x0a << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_AAD_SZ   (0x0b << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH3    (0x0b << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_ALTDS_CLASS1  (0x0f << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_A_SZ     (0x10 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_B_SZ     (0x11 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_N_SZ     (0x12 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_E_SZ     (0x13 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_CLASS_CTX     (0x20 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DESCBUF       (0x40 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DESCBUF_JOB   (0x41 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DESCBUF_SHARED        (0x42 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DESCBUF_JOB_WE        (0x45 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DESCBUF_SHARED_WE (0x46 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_INFO_FIFO     (0x7a << LDST_SRCDST_SHIFT)
+
+/* Offset in source/destination */
+#define LDST_OFFSET_SHIFT      8
+#define LDST_OFFSET_MASK       (0xff << LDST_OFFSET_SHIFT)
+
+/* LDOFF definitions used when DST = LDST_SRCDST_WORD_DECOCTRL */
+/* These could also be shifted by LDST_OFFSET_SHIFT - this reads better */
+#define LDOFF_CHG_SHARE_SHIFT          0
+#define LDOFF_CHG_SHARE_MASK           (0x3 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_NEVER          (0x1 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_OK_PROP                (0x2 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_OK_NO_PROP     (0x3 << LDOFF_CHG_SHARE_SHIFT)
+
+#define LDOFF_ENABLE_AUTO_NFIFO                (1 << 2)
+#define LDOFF_DISABLE_AUTO_NFIFO       (1 << 3)
+
+#define LDOFF_CHG_NONSEQLIODN_SHIFT    4
+#define LDOFF_CHG_NONSEQLIODN_MASK     (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_SEQ      (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_NON_SEQ  (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_TRUSTED  (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+
+#define LDOFF_CHG_SEQLIODN_SHIFT       6
+#define LDOFF_CHG_SEQLIODN_MASK                (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_SEQ         (0x1 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_NON_SEQ     (0x2 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_TRUSTED     (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
+
+/* Data length in bytes        */
+#define LDST_LEN_SHIFT         0
+#define LDST_LEN_MASK          (0xff << LDST_LEN_SHIFT)
+
+/* Special Length definitions when dst=deco-ctrl */
+#define LDLEN_ENABLE_OSL_COUNT         (1 << 7)
+#define LDLEN_RST_CHA_OFIFO_PTR                (1 << 6)
+#define LDLEN_RST_OFIFO                        (1 << 5)
+#define LDLEN_SET_OFIFO_OFF_VALID      (1 << 4)
+#define LDLEN_SET_OFIFO_OFF_RSVD       (1 << 3)
+#define LDLEN_SET_OFIFO_OFFSET_SHIFT   0
+#define LDLEN_SET_OFIFO_OFFSET_MASK    (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
+
+/*
+ * FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE
+ * Command Constructs
+ */
+
+/*
+ * Load Destination: 0 = skip (SEQ_FIFO_LOAD only),
+ * 1 = Load for Class1, 2 = Load for Class2, 3 = Load both
+ * Store Source: 0 = normal, 1 = Class1key, 2 = Class2key
+ */
+#define FIFOLD_CLASS_SHIFT     25
+#define FIFOLD_CLASS_MASK      (0x03 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_SKIP      (0x00 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_CLASS1    (0x01 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_CLASS2    (0x02 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_BOTH      (0x03 << FIFOLD_CLASS_SHIFT)
+
+#define FIFOST_CLASS_SHIFT     25
+#define FIFOST_CLASS_MASK      (0x03 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_NORMAL    (0x00 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT)
+
+/*
+ * Scatter-Gather Table/Variable Length Field
+ * If set for FIFO_LOAD, refers to a SG table. Within
+ * SEQ_FIFO_LOAD, is variable input sequence
+ */
+#define FIFOLDST_SGF_SHIFT     24
+#define FIFOLDST_SGF_MASK      (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_VLF_MASK      (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_SGF           (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_VLF           (1 << FIFOLDST_SGF_SHIFT)
+
+/* Immediate - Data follows command in descriptor */
+#define FIFOLD_IMM_SHIFT       23
+#define FIFOLD_IMM_MASK                (1 << FIFOLD_IMM_SHIFT)
+#define FIFOLD_IMM             (1 << FIFOLD_IMM_SHIFT)
+
+/* Continue - Not the last FIFO store to come */
+#define FIFOST_CONT_SHIFT      23
+#define FIFOST_CONT_MASK       (1 << FIFOST_CONT_SHIFT)
+
+/*
+ * Extended Length - use 32-bit extended length that
+ * follows the pointer field. Illegal with IMM set
+ */
+#define FIFOLDST_EXT_SHIFT     22
+#define FIFOLDST_EXT_MASK      (1 << FIFOLDST_EXT_SHIFT)
+#define FIFOLDST_EXT           (1 << FIFOLDST_EXT_SHIFT)
+
+/* Input data type.*/
+#define FIFOLD_TYPE_SHIFT      16
+#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */
+#define FIFOLD_TYPE_MASK       (0x3f << FIFOLD_TYPE_SHIFT)
+
+/* PK types */
+#define FIFOLD_TYPE_PK         (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_MASK    (0x30 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_TYPEMASK (0x0f << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A0      (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A1      (0x01 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A2      (0x02 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A3      (0x03 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B0      (0x04 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B1      (0x05 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B2      (0x06 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B3      (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_N       (0x08 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A       (0x0c << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B       (0x0d << FIFOLD_TYPE_SHIFT)
+
+/* Other types. Need to OR in last/flush bits as desired */
+#define FIFOLD_TYPE_MSG_MASK   (0x38 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG                (0x10 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG1OUT2   (0x18 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_IV         (0x20 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_BITDATA    (0x28 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_AAD                (0x30 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_ICV                (0x38 << FIFOLD_TYPE_SHIFT)
+
+/* Last/Flush bits for use with "other" types above */
+#define FIFOLD_TYPE_ACT_MASK   (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_NOACTION   (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_FLUSH1     (0x01 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST1      (0x02 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2      (0x04 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2FLUSH1 (0x05 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LASTBOTH   (0x06 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_NOINFOFIFO (0x0F << FIFOLD_TYPE_SHIFT)
+
+#define FIFOLDST_LEN_MASK      0xffff
+#define FIFOLDST_EXT_LEN_MASK  0xffffffff
+
+/* Output data types */
+#define FIFOST_TYPE_SHIFT      16
+#define FIFOST_TYPE_MASK       (0x3f << FIFOST_TYPE_SHIFT)
+
+#define FIFOST_TYPE_PKHA_A0     (0x00 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A1     (0x01 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A2     (0x02 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A3     (0x03 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B0     (0x04 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B1     (0x05 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B2     (0x06 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B3     (0x07 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_N      (0x08 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A      (0x0c << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B      (0x0d << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_AF_SBOX_JKEK (0x10 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_AF_SBOX_TKEK (0x21 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_E_JKEK         (0x22 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_E_TKEK         (0x23 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_KEK     (0x24 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_TKEK    (0x25 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SPLIT_KEK   (0x26 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SPLIT_TKEK  (0x27 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_OUTFIFO_KEK         (0x28 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_OUTFIFO_TKEK (0x29 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_MESSAGE_DATA (0x30 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_RNGSTORE    (0x34 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_RNGFIFO     (0x35 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SKIP        (0x3f << FIFOST_TYPE_SHIFT)
+
+/*
+ * OPERATION Command Constructs
+ */
+
+/* Operation type selectors - OP TYPE */
+#define OP_TYPE_SHIFT          24
+#define OP_TYPE_MASK           (0x07 << OP_TYPE_SHIFT)
+
+#define OP_TYPE_UNI_PROTOCOL   (0x00 << OP_TYPE_SHIFT)
+#define OP_TYPE_PK             (0x01 << OP_TYPE_SHIFT)
+#define OP_TYPE_CLASS1_ALG     (0x02 << OP_TYPE_SHIFT)
+#define OP_TYPE_CLASS2_ALG     (0x04 << OP_TYPE_SHIFT)
+#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT)
+#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
+
+/* ProtocolID selectors - PROTID */
+#define OP_PCLID_SHIFT         16
+#define OP_PCLID_MASK          (0xff << 16)
+
+/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
+#define OP_PCLID_BLOB          (0x0d << OP_PCLID_SHIFT)
+#define OP_PCLID_SECRETKEY     (0x11 << OP_PCLID_SHIFT)
+#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
+
+/* For non-protocol/alg-only op commands */
+#define OP_ALG_TYPE_SHIFT      24
+#define OP_ALG_TYPE_MASK       (0x7 << OP_ALG_TYPE_SHIFT)
+#define OP_ALG_TYPE_CLASS1     2
+#define OP_ALG_TYPE_CLASS2     4
+
+#define OP_ALG_ALGSEL_SHIFT    16
+#define OP_ALG_ALGSEL_MASK     (0xff << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SUBMASK  (0x0f << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_AES      (0x10 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_DES      (0x20 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_3DES     (0x21 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_ARC4     (0x30 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_MD5      (0x40 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SHA1     (0x41 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SHA224   (0x42 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SHA256   (0x43 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SHA384   (0x44 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SHA512   (0x45 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_RNG      (0x50 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SNOW     (0x60 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SNOW_F8  (0x60 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_KASUMI   (0x70 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_CRC      (0x90 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_ALGSEL_SNOW_F9  (0xA0 << OP_ALG_ALGSEL_SHIFT)
+
+#define OP_ALG_AAI_SHIFT       4
+#define OP_ALG_AAI_MASK                (0x1ff << OP_ALG_AAI_SHIFT)
+
+/* randomizer AAI set */
+#define OP_ALG_AAI_RNG         (0x00 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG_NZB     (0x10 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG_OBP     (0x20 << OP_ALG_AAI_SHIFT)
+
+/* RNG4 AAI set */
+#define OP_ALG_AAI_RNG4_SH_0   (0x00 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SH_1   (0x01 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_PS     (0x40 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_AI     (0x80 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SK     (0x100 << OP_ALG_AAI_SHIFT)
+
+/* hmac/smac AAI set */
+#define OP_ALG_AAI_HASH                (0x00 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_HMAC                (0x01 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_SMAC                (0x02 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_HMAC_PRECOMP        (0x04 << OP_ALG_AAI_SHIFT)
+
+#define OP_ALG_AS_SHIFT                2
+#define OP_ALG_AS_MASK         (0x3 << OP_ALG_AS_SHIFT)
+#define OP_ALG_AS_UPDATE       (0 << OP_ALG_AS_SHIFT)
+#define OP_ALG_AS_INIT         (1 << OP_ALG_AS_SHIFT)
+#define OP_ALG_AS_FINALIZE     (2 << OP_ALG_AS_SHIFT)
+#define OP_ALG_AS_INITFINAL    (3 << OP_ALG_AS_SHIFT)
+
+#define OP_ALG_ICV_SHIFT       1
+#define OP_ALG_ICV_MASK                (1 << OP_ALG_ICV_SHIFT)
+#define OP_ALG_ICV_OFF         (0 << OP_ALG_ICV_SHIFT)
+#define OP_ALG_ICV_ON          (1 << OP_ALG_ICV_SHIFT)
+
+#define OP_ALG_DIR_SHIFT       0
+#define OP_ALG_DIR_MASK                1
+#define OP_ALG_DECRYPT         0
+#define OP_ALG_ENCRYPT         1
+
+/* PKHA algorithm type set */
+#define OP_ALG_PK              0x00800000
+#define OP_ALG_PK_FUN_MASK     0x3f /* clrmem, modmath, or cpymem */
+
+/* PKHA mode modular-arithmetic functions */
+#define OP_ALG_PKMODE_MOD_EXPO         0x006
+
+/*
+ * SEQ_IN_PTR Command Constructs
+ */
+
+/* Release Buffers */
+#define SQIN_RBS       0x04000000
+
+/* Sequence pointer is really a descriptor */
+#define SQIN_INL       0x02000000
+
+/* Sequence pointer is a scatter-gather table */
+#define SQIN_SGF       0x01000000
+
+/* Appends to a previous pointer */
+#define SQIN_PRE       0x00800000
+
+/* Use extended length following pointer */
+#define SQIN_EXT       0x00400000
+
+/* Restore sequence with pointer/length */
+#define SQIN_RTO       0x00200000
+
+/* Replace job descriptor */
+#define SQIN_RJD       0x00100000
+
+#define SQIN_LEN_SHIFT          0
+#define SQIN_LEN_MASK          (0xffff << SQIN_LEN_SHIFT)
+
+/*
+ * SEQ_OUT_PTR Command Constructs
+ */
+
+/* Sequence pointer is a scatter-gather table */
+#define SQOUT_SGF      0x01000000
+
+/* Appends to a previous pointer */
+#define SQOUT_PRE      SQIN_PRE
+
+/* Restore sequence with pointer/length */
+#define SQOUT_RTO       SQIN_RTO
+
+/* Use extended length following pointer */
+#define SQOUT_EXT      0x00400000
+
+#define SQOUT_LEN_SHIFT                0
+#define SQOUT_LEN_MASK         (0xffff << SQOUT_LEN_SHIFT)
+
+/*
+ * MOVE Command Constructs
+ */
+
+#define MOVE_AUX_SHIFT         25
+#define MOVE_AUX_MASK          (3 << MOVE_AUX_SHIFT)
+#define MOVE_AUX_MS            (2 << MOVE_AUX_SHIFT)
+#define MOVE_AUX_LS            (1 << MOVE_AUX_SHIFT)
+
+#define MOVE_WAITCOMP_SHIFT    24
+#define MOVE_WAITCOMP_MASK     (1 << MOVE_WAITCOMP_SHIFT)
+#define MOVE_WAITCOMP          (1 << MOVE_WAITCOMP_SHIFT)
+
+#define MOVE_SRC_SHIFT         20
+#define MOVE_SRC_MASK          (0x0f << MOVE_SRC_SHIFT)
+#define MOVE_SRC_CLASS1CTX     (0x00 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_CLASS2CTX     (0x01 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_OUTFIFO       (0x02 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_DESCBUF       (0x03 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH0         (0x04 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH1         (0x05 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH2         (0x06 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH3         (0x07 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_INFIFO                (0x08 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_INFIFO_CL     (0x09 << MOVE_SRC_SHIFT)
+
+#define MOVE_DEST_SHIFT                16
+#define MOVE_DEST_MASK         (0x0f << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1CTX    (0x00 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2CTX    (0x01 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_OUTFIFO      (0x02 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_DESCBUF      (0x03 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH0                (0x04 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH1                (0x05 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH2                (0x06 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH3                (0x07 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_INFIFO_NOINFO (0x0a << MOVE_DEST_SHIFT)
+#define MOVE_DEST_PK_A         (0x0c << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1KEY    (0x0d << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2KEY    (0x0e << MOVE_DEST_SHIFT)
+
+#define MOVE_OFFSET_SHIFT      8
+#define MOVE_OFFSET_MASK       (0xff << MOVE_OFFSET_SHIFT)
+
+#define MOVE_LEN_SHIFT         0
+#define MOVE_LEN_MASK          (0xff << MOVE_LEN_SHIFT)
+
+#define MOVELEN_MRSEL_SHIFT    0
+#define MOVELEN_MRSEL_MASK     (0x3 << MOVE_LEN_SHIFT)
+
+/*
+ * JUMP Command Constructs
+ */
+
+#define JUMP_CLASS_SHIFT       25
+#define JUMP_CLASS_MASK                (3 << JUMP_CLASS_SHIFT)
+#define JUMP_CLASS_NONE                0
+#define JUMP_CLASS_CLASS1      (1 << JUMP_CLASS_SHIFT)
+#define JUMP_CLASS_CLASS2      (2 << JUMP_CLASS_SHIFT)
+#define JUMP_CLASS_BOTH                (3 << JUMP_CLASS_SHIFT)
+
+#define JUMP_JSL_SHIFT         24
+#define JUMP_JSL_MASK          (1 << JUMP_JSL_SHIFT)
+#define JUMP_JSL               (1 << JUMP_JSL_SHIFT)
+
+#define JUMP_TYPE_SHIFT                22
+#define JUMP_TYPE_MASK         (0x03 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_LOCAL                (0x00 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_NONLOCAL     (0x01 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_HALT         (0x02 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_HALT_USER    (0x03 << JUMP_TYPE_SHIFT)
+
+#define JUMP_TEST_SHIFT                16
+#define JUMP_TEST_MASK         (0x03 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_ALL          (0x00 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_INVALL       (0x01 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_ANY          (0x02 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_INVANY       (0x03 << JUMP_TEST_SHIFT)
+
+/* Condition codes. JSL bit is factored in */
+#define JUMP_COND_SHIFT                8
+#define JUMP_COND_MASK         (0x100ff << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_0         (0x80 << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_GCD_1     (0x40 << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_PRIME     (0x20 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_N       (0x08 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_Z       (0x04 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_C       (0x02 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_NV      (0x01 << JUMP_COND_SHIFT)
+
+#define JUMP_COND_JRP          ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_SHRD         ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_SELF         ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_CALM         ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NIP          ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NIFP         ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NOP          ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NCP          ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL)
+
+#define JUMP_OFFSET_SHIFT      0
+#define JUMP_OFFSET_MASK       (0xff << JUMP_OFFSET_SHIFT)
+
+#define OP_ALG_RNG4_SHIFT      4
+#define OP_ALG_RNG4_MAS                (0x1f3 << OP_ALG_RNG4_SHIFT)
+#define OP_ALG_RNG4_SK         (0x100 << OP_ALG_RNG4_SHIFT)
+
+#endif /* DESC_H */
diff --git a/drivers/crypto/fsl/desc_constr.h b/drivers/crypto/fsl/desc_constr.h
new file mode 100644 (file)
index 0000000..f9cae91
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * caam descriptor construction helper functions
+ *
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Based on desc_constr.h file in linux drivers/crypto/caam
+ */
+
+#include <linux/compat.h>
+#include "desc.h"
+
+#define IMMEDIATE (1 << 23)
+#define CAAM_CMD_SZ sizeof(u32)
+#define CAAM_PTR_SZ sizeof(dma_addr_t)
+#define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
+#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
+
+#ifdef DEBUG
+#define PRINT_POS do { printf("%02d: %s\n", desc_len(desc),\
+                             &__func__[sizeof("append")]); \
+                    } while (0)
+#else
+#define PRINT_POS
+#endif
+
+#define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
+                              LDST_SRCDST_WORD_DECOCTRL | \
+                              (LDOFF_CHG_SHARE_OK_NO_PROP << \
+                               LDST_OFFSET_SHIFT))
+#define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
+                               LDST_SRCDST_WORD_DECOCTRL | \
+                               (LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
+#define ENABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
+                              LDST_SRCDST_WORD_DECOCTRL | \
+                              (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
+
+static inline int desc_len(u32 *desc)
+{
+       return *desc & HDR_DESCLEN_MASK;
+}
+
+static inline int desc_bytes(void *desc)
+{
+       return desc_len(desc) * CAAM_CMD_SZ;
+}
+
+static inline u32 *desc_end(u32 *desc)
+{
+       return desc + desc_len(desc);
+}
+
+static inline void init_desc(u32 *desc, u32 options)
+{
+       *desc = (options | HDR_ONE) + 1;
+}
+
+static inline void init_job_desc(u32 *desc, u32 options)
+{
+       init_desc(desc, CMD_DESC_HDR | options);
+}
+
+static inline void append_ptr(u32 *desc, dma_addr_t ptr)
+{
+       dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
+
+       *offset = ptr;
+
+       (*desc) += CAAM_PTR_SZ / CAAM_CMD_SZ;
+}
+
+static inline void append_data(u32 *desc, void *data, int len)
+{
+       u32 *offset = desc_end(desc);
+
+       if (len) /* avoid sparse warning: memcpy with byte count of 0 */
+               memcpy(offset, data, len);
+
+       (*desc) += (len + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
+}
+
+static inline void append_cmd(u32 *desc, u32 command)
+{
+       u32 *cmd = desc_end(desc);
+
+       *cmd = command;
+
+       (*desc)++;
+}
+
+#define append_u32 append_cmd
+
+static inline void append_u64(u32 *desc, u64 data)
+{
+       u32 *offset = desc_end(desc);
+
+       *offset = upper_32_bits(data);
+       *(++offset) = lower_32_bits(data);
+
+       (*desc) += 2;
+}
+
+/* Write command without affecting header, and return pointer to next word */
+static inline u32 *write_cmd(u32 *desc, u32 command)
+{
+       *desc = command;
+
+       return desc + 1;
+}
+
+static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len,
+                                 u32 command)
+{
+       append_cmd(desc, command | len);
+       append_ptr(desc, ptr);
+}
+
+/* Write length after pointer, rather than inside command */
+static inline void append_cmd_ptr_extlen(u32 *desc, dma_addr_t ptr,
+                                        unsigned int len, u32 command)
+{
+       append_cmd(desc, command);
+       if (!(command & (SQIN_RTO | SQIN_PRE)))
+               append_ptr(desc, ptr);
+       append_cmd(desc, len);
+}
+
+static inline void append_cmd_data(u32 *desc, void *data, int len,
+                                  u32 command)
+{
+       append_cmd(desc, command | IMMEDIATE | len);
+       append_data(desc, data, len);
+}
+
+#define APPEND_CMD_RET(cmd, op) \
+static inline u32 *append_##cmd(u32 *desc, u32 options) \
+{ \
+       u32 *cmd = desc_end(desc); \
+       PRINT_POS; \
+       append_cmd(desc, CMD_##op | options); \
+       return cmd; \
+}
+APPEND_CMD_RET(jump, JUMP)
+APPEND_CMD_RET(move, MOVE)
+
+static inline void set_jump_tgt_here(u32 *desc, u32 *jump_cmd)
+{
+       *jump_cmd = *jump_cmd | (desc_len(desc) - (jump_cmd - desc));
+}
+
+static inline void set_move_tgt_here(u32 *desc, u32 *move_cmd)
+{
+       *move_cmd &= ~MOVE_OFFSET_MASK;
+       *move_cmd = *move_cmd | ((desc_len(desc) << (MOVE_OFFSET_SHIFT + 2)) &
+                                MOVE_OFFSET_MASK);
+}
+
+#define APPEND_CMD(cmd, op) \
+static inline void append_##cmd(u32 *desc, u32 options) \
+{ \
+       PRINT_POS; \
+       append_cmd(desc, CMD_##op | options); \
+}
+APPEND_CMD(operation, OPERATION)
+
+#define APPEND_CMD_LEN(cmd, op) \
+static inline void append_##cmd(u32 *desc, unsigned int len, u32 options) \
+{ \
+       PRINT_POS; \
+       append_cmd(desc, CMD_##op | len | options); \
+}
+APPEND_CMD_LEN(seq_store, SEQ_STORE)
+APPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_LOAD)
+APPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
+
+#define APPEND_CMD_PTR(cmd, op) \
+static inline void append_##cmd(u32 *desc, dma_addr_t ptr, unsigned int len, \
+                               u32 options) \
+{ \
+       PRINT_POS; \
+       append_cmd_ptr(desc, ptr, len, CMD_##op | options); \
+}
+APPEND_CMD_PTR(key, KEY)
+APPEND_CMD_PTR(load, LOAD)
+APPEND_CMD_PTR(fifo_load, FIFO_LOAD)
+APPEND_CMD_PTR(fifo_store, FIFO_STORE)
+
+static inline void append_store(u32 *desc, dma_addr_t ptr, unsigned int len,
+                               u32 options)
+{
+       u32 cmd_src;
+
+       cmd_src = options & LDST_SRCDST_MASK;
+
+       append_cmd(desc, CMD_STORE | options | len);
+
+       /* The following options do not require pointer */
+       if (!(cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED ||
+             cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB    ||
+             cmd_src == LDST_SRCDST_WORD_DESCBUF_JOB_WE ||
+             cmd_src == LDST_SRCDST_WORD_DESCBUF_SHARED_WE))
+               append_ptr(desc, ptr);
+}
+
+#define APPEND_SEQ_PTR_INTLEN(cmd, op) \
+static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, dma_addr_t ptr, \
+                                                unsigned int len, \
+                                                u32 options) \
+{ \
+       PRINT_POS; \
+       if (options & (SQIN_RTO | SQIN_PRE)) \
+               append_cmd(desc, CMD_SEQ_##op##_PTR | len | options); \
+       else \
+               append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \
+}
+APPEND_SEQ_PTR_INTLEN(in, IN)
+APPEND_SEQ_PTR_INTLEN(out, OUT)
+
+#define APPEND_CMD_PTR_TO_IMM(cmd, op) \
+static inline void append_##cmd##_as_imm(u32 *desc, void *data, \
+                                        unsigned int len, u32 options) \
+{ \
+       PRINT_POS; \
+       append_cmd_data(desc, data, len, CMD_##op | options); \
+}
+APPEND_CMD_PTR_TO_IMM(load, LOAD);
+APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
+
+#define APPEND_CMD_PTR_EXTLEN(cmd, op) \
+static inline void append_##cmd##_extlen(u32 *desc, dma_addr_t ptr, \
+                                        unsigned int len, u32 options) \
+{ \
+       PRINT_POS; \
+       append_cmd_ptr_extlen(desc, ptr, len, CMD_##op | SQIN_EXT | options); \
+}
+APPEND_CMD_PTR_EXTLEN(seq_in_ptr, SEQ_IN_PTR)
+APPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR)
+
+/*
+ * Determine whether to store length internally or externally depending on
+ * the size of its type
+ */
+#define APPEND_CMD_PTR_LEN(cmd, op, type) \
+static inline void append_##cmd(u32 *desc, dma_addr_t ptr, \
+                               type len, u32 options) \
+{ \
+       PRINT_POS; \
+       if (sizeof(type) > sizeof(u16)) \
+               append_##cmd##_extlen(desc, ptr, len, options); \
+       else \
+               append_##cmd##_intlen(desc, ptr, len, options); \
+}
+APPEND_CMD_PTR_LEN(seq_in_ptr, SEQ_IN_PTR, u32)
+APPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_PTR, u32)
+
+/*
+ * 2nd variant for commands whose specified immediate length differs
+ * from length of immediate data provided, e.g., split keys
+ */
+#define APPEND_CMD_PTR_TO_IMM2(cmd, op) \
+static inline void append_##cmd##_as_imm(u32 *desc, void *data, \
+                                        unsigned int data_len, \
+                                        unsigned int len, u32 options) \
+{ \
+       PRINT_POS; \
+       append_cmd(desc, CMD_##op | IMMEDIATE | len | options); \
+       append_data(desc, data, data_len); \
+}
+APPEND_CMD_PTR_TO_IMM2(key, KEY);
+
+#define APPEND_CMD_RAW_IMM(cmd, op, type) \
+static inline void append_##cmd##_imm_##type(u32 *desc, type immediate, \
+                                            u32 options) \
+{ \
+       PRINT_POS; \
+       append_cmd(desc, CMD_##op | IMMEDIATE | options | sizeof(type)); \
+       append_cmd(desc, immediate); \
+}
+APPEND_CMD_RAW_IMM(load, LOAD, u32);
diff --git a/drivers/crypto/fsl/error.c b/drivers/crypto/fsl/error.c
new file mode 100644 (file)
index 0000000..28cdcdd
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * CAAM Error Reporting
+ *
+ * Copyright 2009-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Derived from error.c file in linux drivers/crypto/caam
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include "desc.h"
+#include "jr.h"
+
+#define CAAM_ERROR_STR_MAX 302
+
+#define JRSTA_SSRC_SHIFT            28
+#define JRSTA_CCBERR_CHAID_MASK     0x00f0
+#define JRSTA_CCBERR_CHAID_SHIFT    4
+#define JRSTA_CCBERR_ERRID_MASK     0x000
+#define JRSTA_CCBERR_CHAID_RNG      (0x05 << JRSTA_CCBERR_CHAID_SHIFT)
+
+#define JRSTA_DECOERR_JUMP          0x08000000
+#define JRSTA_DECOERR_INDEX_SHIFT   8
+#define JRSTA_DECOERR_INDEX_MASK    0xff00
+#define JRSTA_DECOERR_ERROR_MASK    0x00ff
+
+
+static const struct {
+       u8 value;
+       const char *error_text;
+} desc_error_list[] = {
+       { 0x00, "No error." },
+       { 0x01, "SGT Length Error. The descriptor is trying to read" \
+               " more data than is contained in the SGT table." },
+       { 0x02, "SGT Null Entry Error." },
+       { 0x03, "Job Ring Control Error. Bad value in Job Ring Control reg." },
+       { 0x04, "Invalid Descriptor Command." },
+       { 0x05, "Reserved." },
+       { 0x06, "Invalid KEY Command" },
+       { 0x07, "Invalid LOAD Command" },
+       { 0x08, "Invalid STORE Command" },
+       { 0x09, "Invalid OPERATION Command" },
+       { 0x0A, "Invalid FIFO LOAD Command" },
+       { 0x0B, "Invalid FIFO STORE Command" },
+       { 0x0C, "Invalid MOVE/MOVE_LEN Command" },
+       { 0x0D, "Invalid JUMP Command" },
+       { 0x0E, "Invalid MATH Command" },
+       { 0x0F, "Invalid SIGNATURE Command" },
+       { 0x10, "Invalid Sequence Command" },
+       { 0x11, "Skip data type invalid. The type must be 0xE or 0xF."},
+       { 0x12, "Shared Descriptor Header Error" },
+       { 0x13, "Header Error. Invalid length or parity, or other problems." },
+       { 0x14, "Burster Error. Burster has gotten to an illegal state" },
+       { 0x15, "Context Register Length Error" },
+       { 0x16, "DMA Error" },
+       { 0x17, "Reserved." },
+       { 0x1A, "Job failed due to JR reset" },
+       { 0x1B, "Job failed due to Fail Mode" },
+       { 0x1C, "DECO Watchdog timer timeout error" },
+       { 0x1D, "DECO tried to copy a key from another DECO but" \
+               " the other DECO's Key Registers were locked" },
+       { 0x1E, "DECO attempted to copy data from a DECO" \
+               "that had an unmasked Descriptor error" },
+       { 0x1F, "LIODN error" },
+       { 0x20, "DECO has completed a reset initiated via the DRR register" },
+       { 0x21, "Nonce error" },
+       { 0x22, "Meta data is too large (> 511 bytes) for TLS decap" },
+       { 0x23, "Read Input Frame error" },
+       { 0x24, "JDKEK, TDKEK or TDSK not loaded error" },
+       { 0x80, "DNR (do not run) error" },
+       { 0x81, "undefined protocol command" },
+       { 0x82, "invalid setting in PDB" },
+       { 0x83, "Anti-replay LATE error" },
+       { 0x84, "Anti-replay REPLAY error" },
+       { 0x85, "Sequence number overflow" },
+       { 0x86, "Sigver invalid signature" },
+       { 0x87, "DSA Sign Illegal test descriptor" },
+       { 0x88, "Protocol Format Error" },
+       { 0x89, "Protocol Size Error" },
+       { 0xC1, "Blob Command error: Undefined mode" },
+       { 0xC2, "Blob Command error: Secure Memory Blob mode error" },
+       { 0xC4, "Blob Command error: Black Blob key or input size error" },
+       { 0xC5, "Blob Command error: Invalid key destination" },
+       { 0xC8, "Blob Command error: Trusted/Secure mode error" },
+       { 0xF0, "IPsec TTL or hop limit field is 0, or was decremented to 0" },
+       { 0xF1, "3GPP HFN matches or exceeds the Threshold" },
+};
+
+static const char * const cha_id_list[] = {
+       "",
+       "AES",
+       "DES",
+       "ARC4",
+       "MDHA",
+       "RNG",
+       "SNOW f8",
+       "Kasumi f8/9",
+       "PKHA",
+       "CRCA",
+       "SNOW f9",
+       "ZUCE",
+       "ZUCA",
+};
+
+static const char * const err_id_list[] = {
+       "No error.",
+       "Mode error.",
+       "Data size error.",
+       "Key size error.",
+       "PKHA A memory size error.",
+       "PKHA B memory size error.",
+       "Data arrived out of sequence error.",
+       "PKHA divide-by-zero error.",
+       "PKHA modulus even error.",
+       "DES key parity error.",
+       "ICV check failed.",
+       "Hardware error.",
+       "Unsupported CCM AAD size.",
+       "Class 1 CHA is not reset",
+       "Invalid CHA combination was selected",
+       "Invalid CHA selected.",
+};
+
+static const char * const rng_err_id_list[] = {
+       "",
+       "",
+       "",
+       "Instantiate",
+       "Not instantiated",
+       "Test instantiate",
+       "Prediction resistance",
+       "Prediction resistance and test request",
+       "Uninstantiate",
+       "Secure key generation",
+};
+
+static void report_ccb_status(const u32 status,
+                             const char *error)
+{
+       u8 cha_id = (status & JRSTA_CCBERR_CHAID_MASK) >>
+                   JRSTA_CCBERR_CHAID_SHIFT;
+       u8 err_id = status & JRSTA_CCBERR_ERRID_MASK;
+       u8 idx = (status & JRSTA_DECOERR_INDEX_MASK) >>
+                 JRSTA_DECOERR_INDEX_SHIFT;
+       char *idx_str;
+       const char *cha_str = "unidentified cha_id value 0x";
+       char cha_err_code[3] = { 0 };
+       const char *err_str = "unidentified err_id value 0x";
+       char err_err_code[3] = { 0 };
+
+       if (status & JRSTA_DECOERR_JUMP)
+               idx_str = "jump tgt desc idx";
+       else
+               idx_str = "desc idx";
+
+       if (cha_id < ARRAY_SIZE(cha_id_list))
+               cha_str = cha_id_list[cha_id];
+       else
+               snprintf(cha_err_code, sizeof(cha_err_code), "%02x", cha_id);
+
+       if ((cha_id << JRSTA_CCBERR_CHAID_SHIFT) == JRSTA_CCBERR_CHAID_RNG &&
+           err_id < ARRAY_SIZE(rng_err_id_list) &&
+           strlen(rng_err_id_list[err_id])) {
+               /* RNG-only error */
+               err_str = rng_err_id_list[err_id];
+       } else if (err_id < ARRAY_SIZE(err_id_list)) {
+               err_str = err_id_list[err_id];
+       } else {
+               snprintf(err_err_code, sizeof(err_err_code), "%02x", err_id);
+       }
+
+       debug("%08x: %s: %s %d: %s%s: %s%s\n",
+              status, error, idx_str, idx,
+               cha_str, cha_err_code,
+               err_str, err_err_code);
+}
+
+static void report_jump_status(const u32 status,
+                              const char *error)
+{
+       debug("%08x: %s: %s() not implemented\n",
+              status, error, __func__);
+}
+
+static void report_deco_status(const u32 status,
+                              const char *error)
+{
+       u8 err_id = status & JRSTA_DECOERR_ERROR_MASK;
+       u8 idx = (status & JRSTA_DECOERR_INDEX_MASK) >>
+                 JRSTA_DECOERR_INDEX_SHIFT;
+       char *idx_str;
+       const char *err_str = "unidentified error value 0x";
+       char err_err_code[3] = { 0 };
+       int i;
+
+       if (status & JRSTA_DECOERR_JUMP)
+               idx_str = "jump tgt desc idx";
+       else
+               idx_str = "desc idx";
+
+       for (i = 0; i < ARRAY_SIZE(desc_error_list); i++)
+               if (desc_error_list[i].value == err_id)
+                       break;
+
+       if (i != ARRAY_SIZE(desc_error_list) && desc_error_list[i].error_text)
+               err_str = desc_error_list[i].error_text;
+       else
+               snprintf(err_err_code, sizeof(err_err_code), "%02x", err_id);
+
+       debug("%08x: %s: %s %d: %s%s\n",
+              status, error, idx_str, idx, err_str, err_err_code);
+}
+
+static void report_jr_status(const u32 status,
+                            const char *error)
+{
+       debug("%08x: %s: %s() not implemented\n",
+              status, error, __func__);
+}
+
+static void report_cond_code_status(const u32 status,
+                                   const char *error)
+{
+       debug("%08x: %s: %s() not implemented\n",
+              status, error, __func__);
+}
+
+void caam_jr_strstatus(u32 status)
+{
+       static const struct stat_src {
+               void (*report_ssed)(const u32 status,
+                                   const char *error);
+               const char *error;
+       } status_src[] = {
+               { NULL, "No error" },
+               { NULL, NULL },
+               { report_ccb_status, "CCB" },
+               { report_jump_status, "Jump" },
+               { report_deco_status, "DECO" },
+               { NULL, NULL },
+               { report_jr_status, "Job Ring" },
+               { report_cond_code_status, "Condition Code" },
+       };
+       u32 ssrc = status >> JRSTA_SSRC_SHIFT;
+       const char *error = status_src[ssrc].error;
+
+       /*
+        * If there is no further error handling function, just
+        * print the error code, error string and exit. Otherwise
+        * call the handler function.
+        */
+       if (!status_src[ssrc].report_ssed)
+               debug("%08x: %s:\n", status, status_src[ssrc].error);
+       else
+               status_src[ssrc].report_ssed(status, error);
+}
diff --git a/drivers/crypto/fsl/fsl_blob.c b/drivers/crypto/fsl/fsl_blob.c
new file mode 100644 (file)
index 0000000..bc01075
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include "jobdesc.h"
+#include "desc.h"
+#include "jr.h"
+
+int blob_decrypt(u8 *key_mod, u8 *src, u8 *dst, u8 len)
+{
+       int ret, i = 0;
+       u32 *desc;
+
+       printf("\nDecapsulating data to form blob\n");
+       desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE);
+       if (!desc) {
+               debug("Not enough memory for descriptor allocation\n");
+               return -1;
+       }
+
+       inline_cnstr_jobdesc_blob_decap(desc, key_mod, src, dst, len);
+
+       for (i = 0; i < 14; i++)
+               printf("%x\n", *(desc + i));
+       ret = run_descriptor_jr(desc);
+
+       if (ret)
+               printf("Error in Decapsulation %d\n", ret);
+
+       free(desc);
+       return ret;
+}
+
+int blob_encrypt(u8 *key_mod, u8 *src, u8 *dst, u8 len)
+{
+       int ret, i = 0;
+       u32 *desc;
+
+       printf("\nEncapsulating data to form blob\n");
+       desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE);
+       if (!desc) {
+               debug("Not enough memory for descriptor allocation\n");
+               return -1;
+       }
+
+       inline_cnstr_jobdesc_blob_encap(desc, key_mod, src, dst, len);
+       for (i = 0; i < 14; i++)
+               printf("%x\n", *(desc + i));
+       ret = run_descriptor_jr(desc);
+
+       if (ret)
+               printf("Error in Encapsulation %d\n", ret);
+
+       free(desc);
+       return ret;
+}
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
new file mode 100644 (file)
index 0000000..d77f257
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include "jobdesc.h"
+#include "desc.h"
+#include "jr.h"
+
+#define CRYPTO_MAX_ALG_NAME    80
+#define SHA1_DIGEST_SIZE        20
+#define SHA256_DIGEST_SIZE      32
+
+struct caam_hash_template {
+       char name[CRYPTO_MAX_ALG_NAME];
+       unsigned int digestsize;
+       u32 alg_type;
+};
+
+enum caam_hash_algos {
+       SHA1 = 0,
+       SHA256
+};
+
+static struct caam_hash_template driver_hash[] = {
+       {
+               .name = "sha1",
+               .digestsize = SHA1_DIGEST_SIZE,
+               .alg_type = OP_ALG_ALGSEL_SHA1,
+       },
+       {
+               .name = "sha256",
+               .digestsize = SHA256_DIGEST_SIZE,
+               .alg_type = OP_ALG_ALGSEL_SHA256,
+       },
+};
+
+int caam_hash(const unsigned char *pbuf, unsigned int buf_len,
+             unsigned char *pout, enum caam_hash_algos algo)
+{
+       int ret = 0;
+       uint32_t *desc;
+
+       desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE);
+       if (!desc) {
+               debug("Not enough memory for descriptor allocation\n");
+               return -1;
+       }
+
+       inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout,
+                                 driver_hash[algo].alg_type,
+                                 driver_hash[algo].digestsize,
+                                 0);
+
+       ret = run_descriptor_jr(desc);
+
+       free(desc);
+       return ret;
+}
+
+void hw_sha256(const unsigned char *pbuf, unsigned int buf_len,
+                       unsigned char *pout, unsigned int chunk_size)
+{
+       if (caam_hash(pbuf, buf_len, pout, SHA256))
+               printf("CAAM was not setup properly or it is faulty\n");
+}
+
+void hw_sha1(const unsigned char *pbuf, unsigned int buf_len,
+                       unsigned char *pout, unsigned int chunk_size)
+{
+       if (caam_hash(pbuf, buf_len, pout, SHA1))
+               printf("CAAM was not setup properly or it is faulty\n");
+}
diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c
new file mode 100644 (file)
index 0000000..1386bae
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * SEC Descriptor Construction Library
+ * Basic job descriptor construction
+ *
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include "desc_constr.h"
+#include "jobdesc.h"
+
+#define KEY_BLOB_SIZE                  32
+#define MAC_SIZE                       16
+
+void inline_cnstr_jobdesc_hash(uint32_t *desc,
+                         const uint8_t *msg, uint32_t msgsz, uint8_t *digest,
+                         u32 alg_type, uint32_t alg_size, int sg_tbl)
+{
+       /* SHA 256 , output is of length 32 words */
+       uint32_t storelen = alg_size;
+       u32 options;
+       dma_addr_t dma_addr_in, dma_addr_out;
+
+       dma_addr_in = virt_to_phys((void *)msg);
+       dma_addr_out = virt_to_phys((void *)digest);
+
+       init_job_desc(desc, 0);
+       append_operation(desc, OP_TYPE_CLASS2_ALG |
+                        OP_ALG_AAI_HASH | OP_ALG_AS_INITFINAL |
+                        OP_ALG_ENCRYPT | OP_ALG_ICV_OFF | alg_type);
+
+       options = LDST_CLASS_2_CCB | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2;
+       if (sg_tbl)
+               options |= FIFOLDST_SGF;
+       if (msgsz > 0xffff) {
+               options |= FIFOLDST_EXT;
+               append_fifo_load(desc, dma_addr_in, 0, options);
+               append_cmd(desc, msgsz);
+       } else {
+               append_fifo_load(desc, dma_addr_in, msgsz, options);
+       }
+
+       append_store(desc, dma_addr_out, storelen,
+                    LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_CONTEXT);
+}
+
+void inline_cnstr_jobdesc_blob_encap(uint32_t *desc, uint8_t *key_idnfr,
+                                    uint8_t *plain_txt, uint8_t *enc_blob,
+                                    uint32_t in_sz)
+{
+       dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
+       uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
+       /* output blob will have 32 bytes key blob in beginning and
+        * 16 byte HMAC identifier at end of data blob */
+       uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE;
+
+       dma_addr_key_idnfr = virt_to_phys((void *)key_idnfr);
+       dma_addr_in     = virt_to_phys((void *)plain_txt);
+       dma_addr_out    = virt_to_phys((void *)enc_blob);
+
+       init_job_desc(desc, 0);
+
+       append_key(desc, dma_addr_key_idnfr, key_sz, CLASS_2);
+
+       append_seq_in_ptr(desc, dma_addr_in, in_sz, 0);
+
+       append_seq_out_ptr(desc, dma_addr_out, out_sz, 0);
+
+       append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
+}
+
+void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr,
+                                    uint8_t *enc_blob, uint8_t *plain_txt,
+                                    uint32_t out_sz)
+{
+       dma_addr_t dma_addr_key_idnfr, dma_addr_in, dma_addr_out;
+       uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
+       uint32_t in_sz = out_sz + KEY_BLOB_SIZE + MAC_SIZE;
+
+       dma_addr_key_idnfr = virt_to_phys((void *)key_idnfr);
+       dma_addr_in     = virt_to_phys((void *)enc_blob);
+       dma_addr_out    = virt_to_phys((void *)plain_txt);
+
+       init_job_desc(desc, 0);
+
+       append_key(desc, dma_addr_key_idnfr, key_sz, CLASS_2);
+
+       append_seq_in_ptr(desc, dma_addr_in, in_sz, 0);
+
+       append_seq_out_ptr(desc, dma_addr_out, out_sz, 0);
+
+       append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
+}
+
+/*
+ * Descriptor to instantiate RNG State Handle 0 in normal mode and
+ * load the JDKEK, TDKEK and TDSK registers
+ */
+void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc)
+{
+       u32 *jump_cmd;
+
+       init_job_desc(desc, 0);
+
+       /* INIT RNG in non-test mode */
+       append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+                        OP_ALG_AS_INIT);
+
+       /* wait for done */
+       jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
+       set_jump_tgt_here(desc, jump_cmd);
+
+       /*
+        * load 1 to clear written reg:
+        * resets the done interrrupt and returns the RNG to idle.
+        */
+       append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+       /* generate secure keys (non-test) */
+       append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+                        OP_ALG_RNG4_SK);
+}
diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h
new file mode 100644 (file)
index 0000000..3cf7226
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#ifndef __JOBDESC_H
+#define __JOBDESC_H
+
+#include <common.h>
+#include <asm/io.h>
+
+#define KEY_IDNFR_SZ_BYTES             16
+
+void inline_cnstr_jobdesc_hash(uint32_t *desc,
+                         const uint8_t *msg, uint32_t msgsz, uint8_t *digest,
+                         u32 alg_type, uint32_t alg_size, int sg_tbl);
+
+void inline_cnstr_jobdesc_blob_encap(uint32_t *desc, uint8_t *key_idnfr,
+                                    uint8_t *plain_txt, uint8_t *enc_blob,
+                                    uint32_t in_sz);
+
+void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr,
+                                    uint8_t *enc_blob, uint8_t *plain_txt,
+                                    uint32_t out_sz);
+
+void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc);
+#endif
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
new file mode 100644 (file)
index 0000000..29681e1
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Based on CAAM driver in drivers/crypto/caam in Linux
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include "fsl_sec.h"
+#include "jr.h"
+#include "jobdesc.h"
+
+#define CIRC_CNT(head, tail, size)     (((head) - (tail)) & (size - 1))
+#define CIRC_SPACE(head, tail, size)   CIRC_CNT((tail), (head) + 1, (size))
+
+struct jobring jr;
+
+static inline void start_jr0(void)
+{
+       ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+       u32 ctpr_ms = sec_in32(&sec->ctpr_ms);
+       u32 scfgr = sec_in32(&sec->scfgr);
+
+       if (ctpr_ms & SEC_CTPR_MS_VIRT_EN_INCL) {
+               /* VIRT_EN_INCL = 1 & VIRT_EN_POR = 1 or
+                * VIRT_EN_INCL = 1 & VIRT_EN_POR = 0 & SEC_SCFGR_VIRT_EN = 1
+                */
+               if ((ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR) ||
+                   (!(ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR) &&
+                                       (scfgr & SEC_SCFGR_VIRT_EN)))
+                       sec_out32(&sec->jrstartr, CONFIG_JRSTARTR_JR0);
+       } else {
+               /* VIRT_EN_INCL = 0 && VIRT_EN_POR_VALUE = 1 */
+               if (ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR)
+                       sec_out32(&sec->jrstartr, CONFIG_JRSTARTR_JR0);
+       }
+}
+
+static inline void jr_reset_liodn(void)
+{
+       ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+       sec_out32(&sec->jrliodnr[0].ls, 0);
+}
+
+static inline void jr_disable_irq(void)
+{
+       struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
+       uint32_t jrcfg = sec_in32(&regs->jrcfg1);
+
+       jrcfg = jrcfg | JR_INTMASK;
+
+       sec_out32(&regs->jrcfg1, jrcfg);
+}
+
+static void jr_initregs(void)
+{
+       struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
+       phys_addr_t ip_base = virt_to_phys((void *)jr.input_ring);
+       phys_addr_t op_base = virt_to_phys((void *)jr.output_ring);
+
+#ifdef CONFIG_PHYS_64BIT
+       sec_out32(&regs->irba_h, ip_base >> 32);
+#else
+       sec_out32(&regs->irba_h, 0x0);
+#endif
+       sec_out32(&regs->irba_l, (uint32_t)ip_base);
+#ifdef CONFIG_PHYS_64BIT
+       sec_out32(&regs->orba_h, op_base >> 32);
+#else
+       sec_out32(&regs->orba_h, 0x0);
+#endif
+       sec_out32(&regs->orba_l, (uint32_t)op_base);
+       sec_out32(&regs->ors, JR_SIZE);
+       sec_out32(&regs->irs, JR_SIZE);
+
+       if (!jr.irq)
+               jr_disable_irq();
+}
+
+static int jr_init(void)
+{
+       memset(&jr, 0, sizeof(struct jobring));
+
+       jr.jq_id = DEFAULT_JR_ID;
+       jr.irq = DEFAULT_IRQ;
+
+#ifdef CONFIG_FSL_CORENET
+       jr.liodn = DEFAULT_JR_LIODN;
+#endif
+       jr.size = JR_SIZE;
+       jr.input_ring = (dma_addr_t *)malloc(JR_SIZE * sizeof(dma_addr_t));
+       if (!jr.input_ring)
+               return -1;
+       jr.output_ring =
+           (struct op_ring *)malloc(JR_SIZE * sizeof(struct op_ring));
+       if (!jr.output_ring)
+               return -1;
+
+       memset(jr.input_ring, 0, JR_SIZE * sizeof(dma_addr_t));
+       memset(jr.output_ring, 0, JR_SIZE * sizeof(struct op_ring));
+
+       start_jr0();
+
+       jr_initregs();
+
+       return 0;
+}
+
+static int jr_sw_cleanup(void)
+{
+       jr.head = 0;
+       jr.tail = 0;
+       jr.read_idx = 0;
+       jr.write_idx = 0;
+       memset(jr.info, 0, sizeof(jr.info));
+       memset(jr.input_ring, 0, jr.size * sizeof(dma_addr_t));
+       memset(jr.output_ring, 0, jr.size * sizeof(struct op_ring));
+
+       return 0;
+}
+
+static int jr_hw_reset(void)
+{
+       struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
+       uint32_t timeout = 100000;
+       uint32_t jrint, jrcr;
+
+       sec_out32(&regs->jrcr, JRCR_RESET);
+       do {
+               jrint = sec_in32(&regs->jrint);
+       } while (((jrint & JRINT_ERR_HALT_MASK) ==
+                 JRINT_ERR_HALT_INPROGRESS) && --timeout);
+
+       jrint = sec_in32(&regs->jrint);
+       if (((jrint & JRINT_ERR_HALT_MASK) !=
+            JRINT_ERR_HALT_INPROGRESS) && timeout == 0)
+               return -1;
+
+       timeout = 100000;
+       sec_out32(&regs->jrcr, JRCR_RESET);
+       do {
+               jrcr = sec_in32(&regs->jrcr);
+       } while ((jrcr & JRCR_RESET) && --timeout);
+
+       if (timeout == 0)
+               return -1;
+
+       return 0;
+}
+
+/* -1 --- error, can't enqueue -- no space available */
+static int jr_enqueue(uint32_t *desc_addr,
+              void (*callback)(uint32_t desc, uint32_t status, void *arg),
+              void *arg)
+{
+       struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
+       int head = jr.head;
+       dma_addr_t desc_phys_addr = virt_to_phys(desc_addr);
+
+       if (sec_in32(&regs->irsa) == 0 ||
+           CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0)
+               return -1;
+
+       jr.input_ring[head] = desc_phys_addr;
+       jr.info[head].desc_phys_addr = desc_phys_addr;
+       jr.info[head].desc_addr = (uint32_t)desc_addr;
+       jr.info[head].callback = (void *)callback;
+       jr.info[head].arg = arg;
+       jr.info[head].op_done = 0;
+
+       jr.head = (head + 1) & (jr.size - 1);
+
+       sec_out32(&regs->irja, 1);
+
+       return 0;
+}
+
+static int jr_dequeue(void)
+{
+       struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
+       int head = jr.head;
+       int tail = jr.tail;
+       int idx, i, found;
+       void (*callback)(uint32_t desc, uint32_t status, void *arg);
+       void *arg = NULL;
+
+       while (sec_in32(&regs->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) {
+               found = 0;
+
+               dma_addr_t op_desc = jr.output_ring[jr.tail].desc;
+               uint32_t status = jr.output_ring[jr.tail].status;
+               uint32_t desc_virt;
+
+               for (i = 0; CIRC_CNT(head, tail + i, jr.size) >= 1; i++) {
+                       idx = (tail + i) & (jr.size - 1);
+                       if (op_desc == jr.info[idx].desc_phys_addr) {
+                               desc_virt = jr.info[idx].desc_addr;
+                               found = 1;
+                               break;
+                       }
+               }
+
+               /* Error condition if match not found */
+               if (!found)
+                       return -1;
+
+               jr.info[idx].op_done = 1;
+               callback = (void *)jr.info[idx].callback;
+               arg = jr.info[idx].arg;
+
+               /* When the job on tail idx gets done, increment
+                * tail till the point where job completed out of oredr has
+                * been taken into account
+                */
+               if (idx == tail)
+                       do {
+                               tail = (tail + 1) & (jr.size - 1);
+                       } while (jr.info[tail].op_done);
+
+               jr.tail = tail;
+               jr.read_idx = (jr.read_idx + 1) & (jr.size - 1);
+
+               sec_out32(&regs->orjr, 1);
+               jr.info[idx].op_done = 0;
+
+               callback(desc_virt, status, arg);
+       }
+
+       return 0;
+}
+
+static void desc_done(uint32_t desc, uint32_t status, void *arg)
+{
+       struct result *x = arg;
+       x->status = status;
+       caam_jr_strstatus(status);
+       x->done = 1;
+}
+
+int run_descriptor_jr(uint32_t *desc)
+{
+       unsigned long long timeval = get_ticks();
+       unsigned long long timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
+       struct result op;
+       int ret = 0;
+
+       memset(&op, sizeof(op), 0);
+
+       ret = jr_enqueue(desc, desc_done, &op);
+       if (ret) {
+               debug("Error in SEC enq\n");
+               ret = JQ_ENQ_ERR;
+               goto out;
+       }
+
+       timeval = get_ticks();
+       timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
+       while (op.done != 1) {
+               ret = jr_dequeue();
+               if (ret) {
+                       debug("Error in SEC deq\n");
+                       ret = JQ_DEQ_ERR;
+                       goto out;
+               }
+
+               if ((get_ticks() - timeval) > timeout) {
+                       debug("SEC Dequeue timed out\n");
+                       ret = JQ_DEQ_TO_ERR;
+                       goto out;
+               }
+       }
+
+       if (!op.status) {
+               debug("Error %x\n", op.status);
+               ret = op.status;
+       }
+out:
+       return ret;
+}
+
+int jr_reset(void)
+{
+       if (jr_hw_reset() < 0)
+               return -1;
+
+       /* Clean up the jobring structure maintained by software */
+       jr_sw_cleanup();
+
+       return 0;
+}
+
+int sec_reset(void)
+{
+       ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+       uint32_t mcfgr = sec_in32(&sec->mcfgr);
+       uint32_t timeout = 100000;
+
+       mcfgr |= MCFGR_SWRST;
+       sec_out32(&sec->mcfgr, mcfgr);
+
+       mcfgr |= MCFGR_DMA_RST;
+       sec_out32(&sec->mcfgr, mcfgr);
+       do {
+               mcfgr = sec_in32(&sec->mcfgr);
+       } while ((mcfgr & MCFGR_DMA_RST) == MCFGR_DMA_RST && --timeout);
+
+       if (timeout == 0)
+               return -1;
+
+       timeout = 100000;
+       do {
+               mcfgr = sec_in32(&sec->mcfgr);
+       } while ((mcfgr & MCFGR_SWRST) == MCFGR_SWRST && --timeout);
+
+       if (timeout == 0)
+               return -1;
+
+       return 0;
+}
+
+static int instantiate_rng(void)
+{
+       struct result op;
+       u32 *desc;
+       u32 rdsta_val;
+       int ret = 0;
+       ccsr_sec_t __iomem *sec =
+                       (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+       struct rng4tst __iomem *rng =
+                       (struct rng4tst __iomem *)&sec->rng;
+
+       memset(&op, 0, sizeof(struct result));
+
+       desc = malloc(sizeof(int) * 6);
+       if (!desc) {
+               printf("cannot allocate RNG init descriptor memory\n");
+               return -1;
+       }
+
+       inline_cnstr_jobdesc_rng_instantiation(desc);
+       ret = run_descriptor_jr(desc);
+
+       if (ret)
+               printf("RNG: Instantiation failed with error %x\n", ret);
+
+       rdsta_val = sec_in32(&rng->rdsta);
+       if (op.status || !(rdsta_val & RNG_STATE0_HANDLE_INSTANTIATED))
+               return -1;
+
+       return ret;
+}
+
+static u8 get_rng_vid(void)
+{
+       ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+       u32 cha_vid = sec_in32(&sec->chavid_ls);
+
+       return (cha_vid & SEC_CHAVID_RNG_LS_MASK) >> SEC_CHAVID_LS_RNG_SHIFT;
+}
+
+/*
+ * By default, the TRNG runs for 200 clocks per sample;
+ * 1200 clocks per sample generates better entropy.
+ */
+static void kick_trng(int ent_delay)
+{
+       ccsr_sec_t __iomem *sec =
+                       (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+       struct rng4tst __iomem *rng =
+                       (struct rng4tst __iomem *)&sec->rng;
+       u32 val;
+
+       /* put RNG4 into program mode */
+       sec_setbits32(&rng->rtmctl, RTMCTL_PRGM);
+       /* rtsdctl bits 0-15 contain "Entropy Delay, which defines the
+        * length (in system clocks) of each Entropy sample taken
+        * */
+       val = sec_in32(&rng->rtsdctl);
+       val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+             (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
+       sec_out32(&rng->rtsdctl, val);
+       /* min. freq. count, equal to 1/4 of the entropy sample length */
+       sec_out32(&rng->rtfreqmin, ent_delay >> 2);
+       /* max. freq. count, equal to 8 times the entropy sample length */
+       sec_out32(&rng->rtfreqmax, ent_delay << 3);
+       /* put RNG4 into run mode */
+       sec_clrbits32(&rng->rtmctl, RTMCTL_PRGM);
+}
+
+static int rng_init(void)
+{
+       int ret, ent_delay = RTSDCTL_ENT_DLY_MIN;
+       ccsr_sec_t __iomem *sec =
+                       (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+       struct rng4tst __iomem *rng =
+                       (struct rng4tst __iomem *)&sec->rng;
+
+       u32 rdsta = sec_in32(&rng->rdsta);
+
+       /* Check if RNG state 0 handler is already instantiated */
+       if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED)
+               return 0;
+
+       do {
+               /*
+                * If either of the SH's were instantiated by somebody else
+                * then it is assumed that the entropy
+                * parameters are properly set and thus the function
+                * setting these (kick_trng(...)) is skipped.
+                * Also, if a handle was instantiated, do not change
+                * the TRNG parameters.
+                */
+               kick_trng(ent_delay);
+               ent_delay += 400;
+               /*
+                * if instantiate_rng(...) fails, the loop will rerun
+                * and the kick_trng(...) function will modfiy the
+                * upper and lower limits of the entropy sampling
+                * interval, leading to a sucessful initialization of
+                * the RNG.
+                */
+               ret = instantiate_rng();
+       } while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+       if (ret) {
+               printf("RNG: Failed to instantiate RNG\n");
+               return ret;
+       }
+
+        /* Enable RDB bit so that RNG works faster */
+       sec_setbits32(&sec->scfgr, SEC_SCFGR_RDBENABLE);
+
+       return ret;
+}
+
+int sec_init(void)
+{
+       int ret = 0;
+
+#ifdef CONFIG_PHYS_64BIT
+       ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+       uint32_t mcr = sec_in32(&sec->mcfgr);
+
+       sec_out32(&sec->mcfgr, mcr | 1 << MCFGR_PS_SHIFT);
+#endif
+       ret = jr_init();
+       if (ret < 0) {
+               printf("SEC initialization failed\n");
+               return -1;
+       }
+
+       if (get_rng_vid() >= 4) {
+               if (rng_init() < 0) {
+                       printf("RNG instantiation failed\n");
+                       return -1;
+               }
+               printf("SEC: RNG instantiated\n");
+       }
+
+       return ret;
+}
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
new file mode 100644 (file)
index 0000000..cce2c58
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ */
+
+#ifndef __JR_H
+#define __JR_H
+
+#include <linux/compiler.h>
+
+#define JR_SIZE 4
+/* Timeout currently defined as 90 sec */
+#define CONFIG_SEC_DEQ_TIMEOUT 90000000U
+
+#define DEFAULT_JR_ID          0
+#define DEFAULT_JR_LIODN       0
+#define DEFAULT_IRQ            0       /* Interrupts not to be configured */
+
+#define MCFGR_SWRST       ((uint32_t)(1)<<31) /* Software Reset */
+#define MCFGR_DMA_RST     ((uint32_t)(1)<<28) /* DMA Reset */
+#define MCFGR_PS_SHIFT          16
+#define JR_INTMASK       0x00000001
+#define JRCR_RESET                  0x01
+#define JRINT_ERR_HALT_INPROGRESS   0x4
+#define JRINT_ERR_HALT_MASK         0xc
+#define JRNSLIODN_SHIFT                16
+#define JRNSLIODN_MASK         0x0fff0000
+#define JRSLIODN_SHIFT         0
+#define JRSLIODN_MASK          0x00000fff
+
+#define JQ_DEQ_ERR             -1
+#define JQ_DEQ_TO_ERR          -2
+#define JQ_ENQ_ERR             -3
+
+struct op_ring {
+       dma_addr_t desc;
+       uint32_t status;
+} __packed;
+
+struct jr_info {
+       void (*callback)(dma_addr_t desc, uint32_t status, void *arg);
+       dma_addr_t desc_phys_addr;
+       uint32_t desc_addr;
+       uint32_t desc_len;
+       uint32_t op_done;
+       void *arg;
+};
+
+struct jobring {
+       int jq_id;
+       int irq;
+       int liodn;
+       /* Head is the index where software would enq the descriptor in
+        * the i/p ring
+        */
+       int head;
+       /* Tail index would be used by s/w ehile enqueuing to determine if
+        * there is any space left in the s/w maintained i/p rings
+        */
+       /* Also in case of deq tail will be incremented only in case of
+        * in-order job completion
+        */
+       int tail;
+       /* Read index of the output ring. It may not match with tail in case
+        * of out of order completetion
+        */
+       int read_idx;
+       /* Write index to input ring. Would be always equal to head */
+       int write_idx;
+       /* Size of the rings. */
+       int size;
+       /* The ip and output rings have to be accessed by SEC. So the
+        * pointers will ahve to point to the housekeeping region provided
+        * by SEC
+        */
+       /*Circular  Ring of i/p descriptors */
+       dma_addr_t *input_ring;
+       /* Circular Ring of o/p descriptors */
+       /* Circula Ring containing info regarding descriptors in i/p
+        * and o/p ring
+        */
+       /* This ring can be on the stack */
+       struct jr_info info[JR_SIZE];
+       struct op_ring *output_ring;
+};
+
+struct result {
+       int done;
+       uint32_t status;
+};
+
+void caam_jr_strstatus(u32 status);
+int run_descriptor_jr(uint32_t *desc);
+
+#endif
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 97b51371145e81de9f268a33f001c72d6f63ff98..332cfc2b231835ca7c4ffd9f0ead44b2a8351730 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)
+#define GPIO_NAME_SIZE         20
+
+struct bcm2835_gpios {
+       char label[BCM2835_GPIO_COUNT][GPIO_NAME_SIZE];
+       struct bcm2835_gpio_regs *reg;
+};
+
+/**
+ * gpio_is_requested() - check if a GPIO has been requested
+ *
+ * @bank:      Bank to check
+ * @offset:    GPIO offset within bank to check
+ * @return true if marked as requested, false if not
+ */
+static inline bool gpio_is_requested(struct bcm2835_gpios *gpios, int offset)
 {
-       return (gpio < BCM2835_GPIO_COUNT);
+       return *gpios->label[offset] != '\0';
 }
 
-int gpio_request(unsigned gpio, const char *label)
+static int check_requested(struct udevice *dev, unsigned offset,
+                          const char *func)
 {
-       return !gpio_is_valid(gpio);
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+       if (!gpio_is_requested(gpios, offset)) {
+               printf("omap_gpio: %s: error: gpio %s%d not requested\n",
+                      func, uc_priv->bank_name, offset);
+               return -EPERM;
+       }
+
+       return 0;
 }
 
-int gpio_free(unsigned gpio)
+static int bcm2835_gpio_request(struct udevice *dev, unsigned offset,
+                               const char *label)
 {
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
+
+       if (gpio_is_requested(gpios, offset))
+               return -EBUSY;
+
+       strncpy(gpios->label[offset], label, GPIO_NAME_SIZE);
+       gpios->label[offset][GPIO_NAME_SIZE - 1] = '\0';
+
        return 0;
 }
 
-int gpio_direction_input(unsigned gpio)
+static int bcm2835_gpio_free(struct udevice *dev, unsigned offset)
 {
-       struct bcm2835_gpio_regs *reg =
-               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
+       int ret;
+
+       ret = check_requested(dev, offset, __func__);
+       if (ret)
+               return ret;
+       gpios->label[offset][0] = '\0';
+
+       return 0;
+}
+
+static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio)
+{
+       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)
 {
-       struct bcm2835_gpio_regs *reg =
-               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
-       u32 *output_reg = value ? reg->gpset : reg->gpclr;
+       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_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);
+
+       if (!gpio_is_requested(gpios, offset))
+               return GPIOF_UNUSED;
+
+       /* GPIOF_FUNC is not implemented yet */
+       if (bcm2835_gpio_is_output(gpios, offset))
+               return GPIOF_OUTPUT;
+       else
+               return GPIOF_INPUT;
+}
+
+static int bcm2835_gpio_get_state(struct udevice *dev, unsigned int offset,
+                                 char *buf, int bufsize)
+{
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct bcm2835_gpios *gpios = dev_get_priv(dev);
+       const char *label;
+       bool requested;
+       bool is_output;
+       int size;
+
+       label = gpios->label[offset];
+       is_output = bcm2835_gpio_is_output(gpios, offset);
+       size = snprintf(buf, bufsize, "%s%d: ",
+                       uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+       buf += size;
+       bufsize -= size;
+       requested = gpio_is_requested(gpios, offset);
+       snprintf(buf, bufsize, "%s: %d [%c]%s%s",
+                is_output ? "out" : " in",
+                bcm2835_get_value(gpios, offset),
+                requested ? 'x' : ' ',
+                requested ? " " : "",
+                label);
+
+       return 0;
+}
+
+static const struct dm_gpio_ops gpio_bcm2835_ops = {
+       .request                = bcm2835_gpio_request,
+       .free                   = bcm2835_gpio_free,
+       .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,
+       .get_state              = bcm2835_gpio_get_state,
+};
+
+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 0af75a84ea7ab6ea5251549d43d40bbed96e40f2..4fca0894e67f3ca0a088dcb214b17df3d9d97c0b 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)];
index 6a572d5454b39e4905da9094edd01f47cf451035..3f7b7d24416b4bb59b31f9d4a02fe3c41039ac20 100644 (file)
@@ -8,16 +8,31 @@
  * 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_NAME_SIZE                 20
+#define GPIO_PER_BANK                  32
+
+struct mxc_gpio_plat {
+       struct gpio_regs *regs;
+};
+
+struct mxc_bank_info {
+       char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
+       struct gpio_regs *regs;
+};
+
+#ifndef CONFIG_DM_GPIO
 #define GPIO_TO_PORT(n)                (n / 32)
 
 /* GPIO port description */
@@ -134,3 +149,290 @@ int gpio_direction_output(unsigned gpio, int value)
 
        return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
 }
+#endif
+
+#ifdef CONFIG_DM_GPIO
+/**
+ * gpio_is_requested() - check if a GPIO has been requested
+ *
+ * @bank:      Bank to check
+ * @offset:    GPIO offset within bank to check
+ * @return true if marked as requested, false if not
+ */
+static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset)
+{
+       return *bank->label[offset] != '\0';
+}
+
+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;
+}
+
+static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
+{
+       return (readl(&regs->gpio_dr) >> offset) & 0x01;
+}
+
+static int check_requested(struct udevice *dev, unsigned offset,
+                          const char *func)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+       if (!gpio_is_requested(bank, offset)) {
+               printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
+                      func, uc_priv->bank_name, offset);
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+/* 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);
+       int ret;
+
+       ret = check_requested(dev, offset, __func__);
+       if (ret)
+               return ret;
+
+       /* 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);
+       int ret;
+
+       ret = check_requested(dev, offset, __func__);
+       if (ret)
+               return ret;
+
+       /* 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);
+       int ret;
+
+       ret = check_requested(dev, offset, __func__);
+       if (ret)
+               return ret;
+
+       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);
+       int ret;
+
+       ret = check_requested(dev, offset, __func__);
+       if (ret)
+               return ret;
+
+       mxc_gpio_bank_set_value(bank->regs, offset, value);
+
+       return 0;
+}
+
+static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset,
+                             char *buf, int bufsize)
+{
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+       const char *label;
+       bool requested;
+       bool is_output;
+       int size;
+
+       label = bank->label[offset];
+       is_output = mxc_gpio_is_output(bank->regs, offset);
+       size = snprintf(buf, bufsize, "%s%d: ",
+                       uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+       buf += size;
+       bufsize -= size;
+       requested = gpio_is_requested(bank, offset);
+       snprintf(buf, bufsize, "%s: %d [%c]%s%s",
+                is_output ? "out" : " in",
+                is_output ?
+                       mxc_gpio_bank_get_output_value(bank->regs, offset) :
+                       mxc_gpio_bank_get_value(bank->regs, offset),
+                requested ? 'x' : ' ',
+                requested ? " " : "",
+                label);
+
+       return 0;
+}
+
+static int mxc_gpio_request(struct udevice *dev, unsigned offset,
+                             const char *label)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+
+       if (gpio_is_requested(bank, offset))
+               return -EBUSY;
+
+       strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
+       bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
+
+       return 0;
+}
+
+static int mxc_gpio_free(struct udevice *dev, unsigned offset)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+       int ret;
+
+       ret = check_requested(dev, offset, __func__);
+       if (ret)
+               return ret;
+       bank->label[offset][0] = '\0';
+
+       return 0;
+}
+
+static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+       struct mxc_bank_info *bank = dev_get_priv(dev);
+
+       if (!gpio_is_requested(bank, offset))
+               return GPIOF_UNUSED;
+
+       /* 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 = {
+       .request                = mxc_gpio_request,
+       .free                   = mxc_gpio_free,
+       .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,
+       .get_state              = mxc_gpio_get_state,
+};
+
+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 db7b67373101636b61034b3fc90d2b147a33219a..13d74eb951bc406a6c3aea51f2548201c16ac258 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 PULL_MASK(gpio)                (0x3 << ((gpio) << 1))
+#define PULL_MODE(gpio, pull)          ((pull) << ((gpio) << 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 DAT_MASK(x)            (0x1 << (x))
-#define DAT_SET(x)             (0x1 << (x))
+#define GPIO_NAME_SIZE                 20
 
-#define PULL_MASK(x)           (0x3 << ((x) << 1))
-#define PULL_MODE(x, v)                ((v) << ((x) << 1))
+/* 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 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))
+/* Information about each bank at run-time */
+struct exynos_bank_info {
+       char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
+       struct s5p_gpio_bank *bank;
+};
 
-#define name_to_gpio(n) s5p_name_to_gpio(n)
-static inline int s5p_name_to_gpio(const char *name)
+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;
 
-       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;
+       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;
                }
-               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 +95,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 +121,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 +182,156 @@ 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)
+int s5p_gpio_get_pin(unsigned gpio)
 {
-       const struct gpio_info *data;
-       unsigned int upto;
-       int i, count;
+       return S5P_GPIO_GET_PIN(gpio);
+}
 
-       data = get_gpio_data();
-       count = get_bank_num();
-       upto = 0;
+/* Driver model interface */
+#ifndef CONFIG_SPL_BUILD
+static int exynos_gpio_get_state(struct udevice *dev, unsigned int offset,
+                               char *buf, int bufsize)
+{
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+       struct exynos_bank_info *state = dev_get_priv(dev);
+       const char *label;
+       bool is_output;
+       int size;
+       int cfg;
+
+       label = state->label[offset];
+       cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
+       is_output = cfg == S5P_GPIO_OUTPUT;
+       size = snprintf(buf, bufsize, "%s%d: ",
+                       uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+       buf += size;
+       bufsize -= size;
+       if (is_output || cfg == S5P_GPIO_INPUT) {
+               snprintf(buf, bufsize, "%s: %d [%c]%s%s",
+                        is_output ? "out" : " in",
+                        s5p_gpio_get_value(state->bank, offset),
+                        *label ? 'x' : ' ',
+                        *label ? " " : "",
+                        label);
+       } else {
+               snprintf(buf, bufsize, "sfpio");
+       }
 
-       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;
-               }
+       return 0;
+}
 
-               upto = data->max_gpio;
-               data++;
+static int check_reserved(struct udevice *dev, unsigned offset,
+                         const char *func)
+{
+       struct exynos_bank_info *state = dev_get_priv(dev);
+       struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+
+       if (!*state->label[offset]) {
+               printf("exynos_gpio: %s: error: gpio %s%d not reserved\n",
+                      func, uc_priv->bank_name, offset);
+               return -EPERM;
        }
 
-       return NULL;
+       return 0;
 }
 
-int s5p_gpio_get_pin(unsigned gpio)
+/* set GPIO pin 'gpio' as an input */
+static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
 {
-       return S5P_GPIO_GET_PIN(gpio);
-}
+       struct exynos_bank_info *state = dev_get_priv(dev);
+       int ret;
 
-/* Common GPIO API */
+       ret = check_reserved(dev, offset, __func__);
+       if (ret)
+               return ret;
+
+       /* Configure GPIO direction as input. */
+       s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
 
-int gpio_request(unsigned gpio, const char *label)
-{
        return 0;
 }
 
-int gpio_free(unsigned gpio)
+/* set GPIO pin 'gpio' as an output, with polarity 'value' */
+static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
+                                      int value)
 {
+       struct exynos_bank_info *state = dev_get_priv(dev);
+       int ret;
+
+       ret = check_reserved(dev, offset, __func__);
+       if (ret)
+               return ret;
+
+       /* 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_direction_input(unsigned gpio)
+/* read GPIO IN value of pin 'gpio' */
+static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
 {
-       s5p_gpio_direction_input(s5p_gpio_get_bank(gpio),
-                               s5p_gpio_get_pin(gpio));
-       return 0;
+       struct exynos_bank_info *state = dev_get_priv(dev);
+       int ret;
+
+       ret = check_reserved(dev, offset, __func__);
+       if (ret)
+               return ret;
+
+       return s5p_gpio_get_value(state->bank, offset);
 }
 
-int gpio_direction_output(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_direction_output(s5p_gpio_get_bank(gpio),
-                                s5p_gpio_get_pin(gpio), value);
+       struct exynos_bank_info *state = dev_get_priv(dev);
+       int ret;
+
+       ret = check_reserved(dev, offset, __func__);
+       if (ret)
+               return ret;
+
+       s5p_gpio_set_value(state->bank, offset, value);
+
        return 0;
 }
 
-int gpio_get_value(unsigned gpio)
+static int exynos_gpio_request(struct udevice *dev, unsigned offset,
+                             const char *label)
 {
-       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);
+
+       if (*state->label[offset])
+               return -EBUSY;
+
+       strncpy(state->label[offset], label, GPIO_NAME_SIZE);
+       state->label[offset][GPIO_NAME_SIZE - 1] = '\0';
+
+       return 0;
 }
 
-int gpio_set_value(unsigned gpio, int value)
+static int exynos_gpio_free(struct udevice *dev, unsigned offset)
 {
-       s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
-                         s5p_gpio_get_pin(gpio), value);
+       struct exynos_bank_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;
 }
+#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 +355,117 @@ 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;
+
+       if (!*state->label[offset])
+               return GPIOF_UNUSED;
+       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 = {
+       .request                = exynos_gpio_request,
+       .free                   = exynos_gpio_free,
+       .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,
+       .get_state              = exynos_gpio_get_state,
+};
+
+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 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 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 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 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 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 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 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 fa4ea050a55e30392178a8d61394e4b6aa5541d4..27c2c4c8da0498c37fa3436fa1818ff89e0d77f7 100644 (file)
@@ -62,7 +62,7 @@ int axp152_set_dcdc2(int mvolt)
 
 int axp152_set_dcdc3(int mvolt)
 {
-       u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 25);
+       u8 target = axp152_mvolt_to_target(mvolt, 700, 3500, 50);
 
        return axp152_write(AXP152_DCDC3_VOLTAGE, target);
 }
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 b4f299bb0ede65966624972b900c09142f202e24..17c56ea66e8e65185110bfa91b20069da675fbfa 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
index fd010cac4286261da1b4aa8a52bd729cc653d81c..1a75950d19fa4c738f7f5c881da08561d416faf2 100644 (file)
@@ -71,7 +71,7 @@ void serial_initialize(void)
        serial_find_console_or_panic();
 }
 
-void serial_putc(char ch)
+static void serial_putc_dev(struct udevice *dev, char ch)
 {
        struct dm_serial_ops *ops = serial_get_ops(cur_dev);
        int err;
@@ -83,6 +83,11 @@ void serial_putc(char ch)
                serial_putc('\r');
 }
 
+void serial_putc(char ch)
+{
+       serial_putc_dev(cur_dev, ch);
+}
+
 void serial_setbrg(void)
 {
        struct dm_serial_ops *ops = serial_get_ops(cur_dev);
@@ -107,28 +112,32 @@ int serial_tstc(void)
        return 1;
 }
 
-int serial_getc(void)
+static int serial_getc_dev(struct udevice *dev)
 {
-       struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+       struct dm_serial_ops *ops = serial_get_ops(dev);
        int err;
 
        do {
-               err = ops->getc(cur_dev);
+               err = ops->getc(dev);
        } while (err == -EAGAIN);
 
        return err >= 0 ? err : 0;
 }
 
+int serial_getc(void)
+{
+       return serial_getc_dev(cur_dev);
+}
+
 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_dev(dev, ch);
 }
 
 void serial_stub_puts(struct stdio_dev *sdev, const char *str)
@@ -140,15 +149,8 @@ void serial_stub_puts(struct stdio_dev *sdev, const char *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_dev(dev);
 }
 
 int serial_stub_tstc(struct stdio_dev *sdev)
@@ -198,7 +200,7 @@ static int serial_pre_remove(struct udevice *dev)
 #ifdef CONFIG_SYS_STDIO_DEREGISTER
        struct serial_dev_priv *upriv = dev->uclass_priv;
 
-       if (stdio_deregister_dev(upriv->sdev), 0)
+       if (stdio_deregister_dev(upriv->sdev, 0))
                return -EPERM;
 #endif
 
index 313d560afce8635f3b1f29c3ea029173b69f8c40..9ce24f9f932d932f6244479241809b8858a696a4 100644 (file)
@@ -5,37 +5,15 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <serial_mxc.h>
 #include <watchdog.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.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 dfb610e1a9d553429d1462335a6550f6d31afe04..e6313ad3d3a8d238a774543bab6777964b04627f 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 <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 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 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 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 948e1fc401facea11502734ac53e82dd70df36e5..48fee992a180029b4adbe30e53b9f39491acde79 100644 (file)
@@ -801,28 +801,6 @@ int ipu_pixfmt_to_map(uint32_t fmt)
        return -1;
 }
 
-/*
- * This function is called to adapt synchronous LCD panel to IPU restriction.
- */
-void adapt_panel_to_ipu_restricitions(uint32_t *pixel_clk,
-                                     uint16_t width, uint16_t height,
-                                     uint16_t h_start_width,
-                                     uint16_t h_end_width,
-                                     uint16_t v_start_width,
-                                     uint16_t *v_end_width)
-{
-       if (*v_end_width < 2) {
-               uint16_t total_width = width + h_start_width + h_end_width;
-               uint16_t total_height_old = height + v_start_width +
-                       (*v_end_width);
-               uint16_t total_height_new = height + v_start_width + 2;
-               *v_end_width = 2;
-               *pixel_clk = (*pixel_clk) * total_width * total_height_new /
-                       (total_width * total_height_old);
-               printf("WARNING: adapt panel end blank lines\n");
-       }
-}
-
 /*
  * This function is called to initialize a synchronous LCD panel.
  *
@@ -880,14 +858,17 @@ int32_t ipu_init_sync_panel(int disp, uint32_t pixel_clk,
        if ((v_sync_width == 0) || (h_sync_width == 0))
                return -EINVAL;
 
-       adapt_panel_to_ipu_restricitions(&pixel_clk, width, height,
-                                        h_start_width, h_end_width,
-                                        v_start_width, &v_end_width);
+       /* adapt panel to ipu restricitions */
+       if (v_end_width < 2) {
+               v_end_width = 2;
+               puts("WARNING: v_end_width (lower_margin) must be >= 2, adjusted\n");
+       }
+
        h_total = width + h_sync_width + h_start_width + h_end_width;
        v_total = height + v_sync_width + v_start_width + v_end_width;
 
        /* Init clocking */
-       debug("pixel clk = %d\n", pixel_clk);
+       debug("pixel clk = %dHz\n", pixel_clk);
 
        if (sig.ext_clk) {
                if (!(g_di1_tvout && (disp == 1))) { /*not round div for tvout*/
index f75d77064ea5334c6211130f367987c61bd742cd..b20c19c426d5cb0e1baaea409cc7c361bac0979c 100644 (file)
@@ -258,8 +258,7 @@ static int mxcfb_set_par(struct fb_info *fbi)
        if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN)
                sig_cfg.clkidle_en = 1;
 
-       debug("pixclock = %ul Hz\n",
-               (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
+       debug("pixclock = %lu Hz\n", PICOS2KHZ(fbi->var.pixclock) * 1000UL);
 
        if (ipu_init_sync_panel(mxc_fbi->ipu_di,
                                (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
@@ -486,7 +485,7 @@ static struct fb_info *mxcfb_init_fbinfo(void)
 
 /*
  * Probe routine for the framebuffer driver. It is called during the
- * driver binding process.      The following functions are performed in
+ * driver binding process. The following functions are performed in
  * this routine: Framebuffer initialization, Memory allocation and
  * mapping, Framebuffer registration, IPU initialization.
  *
@@ -542,7 +541,7 @@ static int mxcfb_probe(u32 interface_pix_fmt, uint8_t disp,
 
        mxcfb_set_fix(fbi);
 
-       /* alocate fb first */
+       /* allocate fb first */
        if (mxcfb_map_video_memory(fbi) < 0)
                return -ENOMEM;
 
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 14519163a32bfa13d2df16a22d66735b28b52138..21036022d7a12c68916599c487e68f3ff2ea83d6 100644 (file)
 # include <machine/endian.h>
 typedef unsigned long ulong;
 #endif
+#ifdef __FreeBSD__
+# include <sys/endian.h> /* htole32 and friends */
+#endif
+
 #include <time.h>
 
 typedef uint8_t __u8;
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
index 9063c57b4092e73746553a539719875ea2f180a3..dc1a9bc1ef98d9bc2d78ea88a550f17054b4110a 100644 (file)
@@ -82,6 +82,7 @@
 #define CONFIG_SYS_FSL_CPC             /* Corenet Platform Cache */
 #define CONFIG_SYS_NUM_CPC             CONFIG_NUM_DDR_CONTROLLERS
 #define CONFIG_FSL_IFC                 /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
 #define CONFIG_PCIE1                   /* PCIE controler 1 */
 #define CONFIG_FSL_PCI_INIT            /* Use common FSL init code */
@@ -759,6 +760,12 @@ unsigned long get_board_ddr_clk(void);
 #define CONFIG_CMD_NET
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
 * USB
 */
@@ -913,4 +920,8 @@ unsigned long get_board_ddr_clk(void);
 
 #include <asm/fsl_secure_boot.h>
 
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CMD_BLOB
+#endif
+
 #endif /* __CONFIG_H */
index 56a3e9486851994c9e2cc96ee08f1434a1c38642..bc5af526c5f7eb55df3d424268980c372fe13d48 100644 (file)
@@ -55,6 +55,7 @@
 #define CONFIG_BOOKE                   /* BOOKE */
 #define CONFIG_E500                    /* BOOKE e500 family */
 #define CONFIG_FSL_IFC                 /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 
 #define CONFIG_FSL_LAW                 /* Use common FSL init code */
 #define CONFIG_TSEC_ENET
@@ -382,6 +383,12 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_KGDB_BAUDRATE   230400  /* speed to run kgdb serial port */
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 #define CONFIG_USB_EHCI
 
 #ifdef CONFIG_USB_EHCI
index aeded6d85b40c436998a39f5036525210d07cb09..989363c0fbc0def810b96a73ae07889382205656 100644 (file)
@@ -78,6 +78,7 @@
 #define CONFIG_BOOKE                   /* BOOKE */
 #define CONFIG_E500                    /* BOOKE e500 family */
 #define CONFIG_FSL_IFC                 /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_SYS_HAS_SERDES          /* common SERDES init code */
 
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
@@ -598,6 +599,12 @@ combinations. this should be removed later
 #define CONFIG_DOS_PARTITION
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
@@ -704,4 +711,8 @@ combinations. this should be removed later
 
 #include <asm/fsl_secure_boot.h>
 
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CMD_BLOB
+#endif
+
 #endif /* __CONFIG_H */
index 715616d5445b872bca0db030e343a5e2d4f3bb23..5d11278f036c01382a2bb6a77f3e1cdd377cb46b 100644 (file)
@@ -86,6 +86,7 @@
 #define CONFIG_BOOKE                   /* BOOKE */
 #define CONFIG_E500                    /* BOOKE e500 family */
 #define CONFIG_FSL_IFC                 /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_SYS_HAS_SERDES          /* common SERDES init code */
 
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
 #define CONFIG_CMD_SETEXPR
 #define CONFIG_CMD_REGINFO
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
index a373990e5d014e9a28c16f08615d22b18144e892..d378dbd1a1e2ccb4537257a329e4ced51cc01599 100644 (file)
@@ -53,7 +53,7 @@
 #ifdef CONFIG_SECURE_BOOT
 #define CONFIG_RAMBOOT_SPIFLASH
 #define CONFIG_SYS_TEXT_BASE           0x11000000
-#define CONFIG_RESET_VECTOR_ADDRESS    0x1107fffc
+#define CONFIG_RESET_VECTOR_ADDRESS    0x110bfffc
 #else
 #define CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT
 #define CONFIG_SPL_DRIVERS_MISC_SUPPORT
 #define CONFIG_BOOKE                   /* BOOKE */
 #define CONFIG_E500                    /* BOOKE e500 family */
 #define CONFIG_FSL_IFC                 /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_SYS_HAS_SERDES          /* common SERDES init code */
 
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
@@ -832,6 +833,12 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_DOS_PARTITION
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
@@ -956,4 +963,8 @@ extern unsigned long get_sdram_size(void);
 
 #include <asm/fsl_secure_boot.h>
 
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CMD_BLOB
+#endif
+
 #endif /* __CONFIG_H */
index 16f7525def40f84d526d98c3077077eb01a24195..2e11aaa13cd35156e605cf29723b6f6a6ff2d9cb 100644 (file)
@@ -49,6 +49,7 @@
 #define CONFIG_SYS_FSL_CPC             /* Corenet Platform Cache */
 #define CONFIG_SYS_NUM_CPC             CONFIG_NUM_DDR_CONTROLLERS
 #define CONFIG_FSL_ELBC                        /* Has Enhanced localbus controller */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
 #define CONFIG_PCIE1                   /* PCIE controler 1 */
 #define CONFIG_PCIE2                   /* PCIE controler 2 */
@@ -647,6 +648,12 @@ unsigned long get_board_sys_clk(unsigned long dummy);
 #define CONFIG_DOS_PARTITION
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
@@ -743,4 +750,8 @@ unsigned long get_board_sys_clk(unsigned long dummy);
 
 #include <asm/fsl_secure_boot.h>
 
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CMD_BLOB
+#endif
+
 #endif /* __CONFIG_H */
index a781ba327a2855e3a9715a0cb52935ab81a2cdcb..1d0664ddf6e828b01a2801a96f73becd06d34036 100644 (file)
@@ -58,6 +58,7 @@
 #define CONFIG_SYS_FSL_CPC             /* Corenet Platform Cache */
 #define CONFIG_SYS_NUM_CPC             CONFIG_NUM_DDR_CONTROLLERS
 #define CONFIG_FSL_IFC                 /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
 #define CONFIG_PCI_INDIRECT_BRIDGE
 #define CONFIG_PCIE1                   /* PCIE controler 1 */
@@ -716,6 +717,12 @@ unsigned long get_board_ddr_clk(void);
 #define CONFIG_CMD_NET
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
@@ -818,6 +825,7 @@ unsigned long get_board_ddr_clk(void);
 
 #ifdef CONFIG_SECURE_BOOT
 #include <asm/fsl_secure_boot.h>
+#define CONFIG_CMD_BLOB
 #endif
 
 #endif /* __CONFIG_H */
index 5e2c100d9309b1b86cbc1ffa06e43031c0ddb076..2bb86e40caf97b742f8ad39fe152a8b3b7c9dd08 100644 (file)
 #define CONFIG_SYS_FSL_CPC             /* Corenet Platform Cache */
 #define CONFIG_SYS_NUM_CPC             CONFIG_NUM_DDR_CONTROLLERS
 #define CONFIG_FSL_IFC                 /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
 #define CONFIG_PCI_INDIRECT_BRIDGE
 #define CONFIG_PCIE1                   /* PCIE controler 1 */
 #define CONFIG_CMD_NET
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
 
 #ifdef CONFIG_SECURE_BOOT
 #include <asm/fsl_secure_boot.h>
+#define CONFIG_CMD_BLOB
 #endif
 
 #endif /* __CONFIG_H */
index 395472be2bc2a6a8d19211129c696e1f57a388a2..27333589afe4f092214acd94ef6e93e3d696058a 100644 (file)
@@ -44,6 +44,7 @@
 #define CONFIG_SYS_FSL_CPC     /* Corenet Platform Cache */
 #define CONFIG_SYS_NUM_CPC     CONFIG_NUM_DDR_CONTROLLERS
 #define CONFIG_FSL_IFC         /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                /* Enable SEC/CAAM */
 #define CONFIG_FSL_LAW         /* Use common FSL init code */
 #define CONFIG_ENV_OVERWRITE
 
@@ -777,6 +778,12 @@ unsigned long get_board_ddr_clk(void);
 #define CONFIG_CMD_NET
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
@@ -909,6 +916,7 @@ unsigned long get_board_ddr_clk(void);
 
 #ifdef CONFIG_SECURE_BOOT
 #include <asm/fsl_secure_boot.h>
+#define CONFIG_CMD_BLOB
 #undef CONFIG_CMD_USB
 #endif
 
index e5936c78176972761a57b8b491e4a27c328f608d..400d979643caaf7cdaddc8ddfdae5dbf87a6169a 100644 (file)
@@ -37,6 +37,7 @@
 #define CONFIG_SYS_FSL_CPC     /* Corenet Platform Cache */
 #define CONFIG_SYS_NUM_CPC     CONFIG_NUM_DDR_CONTROLLERS
 #define CONFIG_FSL_IFC         /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                /* Enable SEC/CAAM */
 #define CONFIG_FSL_LAW         /* Use common FSL init code */
 #define CONFIG_ENV_OVERWRITE
 
@@ -736,6 +737,12 @@ unsigned long get_board_ddr_clk(void);
 #define CONFIG_CMD_NET
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
@@ -868,6 +875,7 @@ unsigned long get_board_ddr_clk(void);
 
 #ifdef CONFIG_SECURE_BOOT
 #include <asm/fsl_secure_boot.h>
+#define CONFIG_CMD_BLOB
 #undef CONFIG_CMD_USB
 #endif
 
index ca9724720d9f0ad53e574670a5f48495d268420d..1e0f5ece092067afcce0ae74cedc14e86f4c2b96 100644 (file)
@@ -15,6 +15,7 @@
 
 #define CONFIG_FSL_SATA_V2
 #define CONFIG_PCIE4
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 
 #define CONFIG_ICS307_REFCLK_HZ                25000000  /* ICS307 ref clk freq */
 
@@ -506,6 +507,12 @@ unsigned long get_board_ddr_clk(void);
 #define CONFIG_PHY_GIGE                /* Include GbE speed/duplex detection */
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
 * USB
 */
@@ -625,4 +632,8 @@ unsigned long get_board_ddr_clk(void);
 
 #include <asm/fsl_secure_boot.h>
 
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CMD_BLOB
+#endif
+
 #endif /* __CONFIG_H */
index 183255d2831ebb3c1e4a4e4e33a6cf5c0238443b..13f4bd3c539fae5629ec1adc374f875ec0417bdc 100644 (file)
@@ -47,6 +47,7 @@
 #define CONFIG_SYS_FSL_CPC             /* Corenet Platform Cache */
 #define CONFIG_SYS_NUM_CPC             CONFIG_NUM_DDR_CONTROLLERS
 #define CONFIG_FSL_IFC                 /* Enable IFC Support */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
 #define CONFIG_PCIE1                   /* PCIE controler 1 */
 #define CONFIG_PCIE2                   /* PCIE controler 2 */
@@ -668,6 +669,12 @@ unsigned long get_board_ddr_clk(void);
 #define CONFIG_DOS_PARTITION
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 #define CONFIG_BOOTDELAY       10      /* -1 disables auto-boot */
 
 #define __USB_PHY_TYPE utmi
@@ -751,6 +758,7 @@ unsigned long get_board_ddr_clk(void);
  * which is anyways not used in Secure Environment.
  */
 #undef CONFIG_CMD_USB
+#define CONFIG_CMD_BLOB
 #endif
 
 #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 936be145119d1e55a810ccc95bb922cb8a9b0f72..200b744e4f22a3a260d1b7eb24a07117d2d05908 100644 (file)
@@ -25,6 +25,7 @@
 #define CONFIG_ZBOOT_32
 #define CONFIG_PHYSMEM
 #define CONFIG_SYS_EARLY_PCI_INIT
+#define CONFIG_DISPLAY_BOARDINFO_LATE
 
 #define CONFIG_LMB
 #define CONFIG_OF_LIBFDT
@@ -39,6 +40,7 @@
 #define CONFIG_BOOTSTAGE_USER_COUNT    60
 
 #define CONFIG_LZO
+#define CONFIG_FIT
 #undef CONFIG_ZLIB
 #undef CONFIG_GZIP
 
 
 #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_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
 
index 12b32967b437a719ec3df28fa488a3fd18ce094b..72b7efa5092c51cc00016ba5777c66e647952ec7 100644 (file)
@@ -57,6 +57,7 @@
 #define CONFIG_SYS_FSL_CPC             /* Corenet Platform Cache */
 #define CONFIG_SYS_NUM_CPC             CONFIG_NUM_DDR_CONTROLLERS
 #define CONFIG_FSL_ELBC                        /* Has Enhanced localbus controller */
+#define CONFIG_FSL_CAAM                        /* Enable SEC/CAAM */
 #define CONFIG_PCI                     /* Enable PCI/PCIE */
 #define CONFIG_PCIE1                   /* PCIE controler 1 */
 #define CONFIG_PCIE2                   /* PCIE controler 2 */
 #define CONFIG_DOS_PARTITION
 #endif
 
+/* Hash command with SHA acceleration supported in hardware */
+#ifdef CONFIG_FSL_CAAM
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+#endif
+
 /*
  * Miscellaneous configurable options
  */
 
 #include <asm/fsl_secure_boot.h>
 
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CMD_BLOB
+#endif
+
 #endif /* __CONFIG_H */
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 bb4781334537b579bc07b52ab76cba69f79b5ea6..d1f6ea7e7b0e6d5f1efcda54eca34af3cd3d3b3c 100644 (file)
@@ -69,6 +69,7 @@ unsigned long get_board_ddr_clk(void);
 
 #define CONFIG_SYS_HAS_SERDES
 
+#define CONFIG_FSL_CAAM                        /* Enable CAAM */
 /*
  * IFC Definitions
  */
@@ -359,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
@@ -388,4 +388,14 @@ unsigned long get_board_ddr_clk(void);
 #define CONFIG_OF_BOARD_SETUP
 #define CONFIG_CMD_BOOTZ
 
+#define CONFIG_MISC_INIT_R
+
+/* Hash command with SHA acceleration supported in hardware */
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CMD_BLOB
+#endif
+
 #endif
index 45b2272ff5bf6f7f390ee6935bc5908b402369eb..3c73af8ac39dc6663fa0db3ed5d91eb9c3601618 100644 (file)
@@ -48,6 +48,8 @@
 
 #define CONFIG_SYS_HAS_SERDES
 
+#define CONFIG_FSL_CAAM                        /* Enable CAAM */
+
 /*
  * IFC Definitions
  */
 #define CONFIG_SYS_MEMTEST_END         0x9fffffff
 
 #define CONFIG_SYS_LOAD_ADDR           0x82000000
-#define CONFIG_SYS_HZ                  1000
 
 /*
  * Stack sizes
 #define CONFIG_OF_BOARD_SETUP
 #define CONFIG_CMD_BOOTZ
 
+#define CONFIG_MISC_INIT_R
+
+/* Hash command with SHA acceleration supported in hardware */
+#define CONFIG_CMD_HASH
+#define CONFIG_SHA_HW_ACCEL
+
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CMD_BLOB
+#endif
+
 #endif
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 2d698094800f2c7bbc50d6f7b8ef63e27b5b7742..d9475e950b798188244e15269348c1a79ec5c687 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 69726432a3c922a467b55495c31d01d831b069cb..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
 #define CONFIG_CONSOLE_MUX
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
 #define LCD_BPP                        LCD_COLOR16
+#define CONFIG_LCD_BMP_RLE8
 
 #define CONFIG_CROS_EC_KEYB
 #define CONFIG_KEYBOARD
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 9abf2683c1278466d99773088158bed914108635..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 */
index 723ef72ef41c63cd77a667b0db71836e035da25b..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_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 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 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
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 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
diff --git a/include/fsl_sec.h b/include/fsl_sec.h
new file mode 100644 (file)
index 0000000..aa850a3
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Common internal memory map for some Freescale SoCs
+ *
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ */
+
+#ifndef __FSL_SEC_H
+#define __FSL_SEC_H
+
+#include <common.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_SYS_FSL_SEC_LE
+#define sec_in32(a)       in_le32(a)
+#define sec_out32(a, v)   out_le32(a, v)
+#define sec_in16(a)       in_le16(a)
+#define sec_clrbits32     clrbits_le32
+#define sec_setbits32     setbits_le32
+#elif defined(CONFIG_SYS_FSL_SEC_BE)
+#define sec_in32(a)       in_be32(a)
+#define sec_out32(a, v)   out_be32(a, v)
+#define sec_in16(a)       in_be16(a)
+#define sec_clrbits32     clrbits_be32
+#define sec_setbits32     setbits_be32
+#else
+#error Neither CONFIG_SYS_FSL_SEC_LE nor CONFIG_SYS_FSL_SEC_BE is defined
+#endif
+
+/* Security Engine Block (MS = Most Sig., LS = Least Sig.) */
+#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
+/* RNG4 TRNG test registers */
+struct rng4tst {
+#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
+       u32 rtmctl;             /* misc. control register */
+       u32 rtscmisc;           /* statistical check misc. register */
+       u32 rtpkrrng;           /* poker range register */
+#define RTSDCTL_ENT_DLY_MIN    1200
+#define RTSDCTL_ENT_DLY_MAX    12800
+       union {
+               u32 rtpkrmax;   /* PRGM=1: poker max. limit register */
+               u32 rtpkrsq;    /* PRGM=0: poker square calc. result register */
+       };
+#define RTSDCTL_ENT_DLY_SHIFT 16
+#define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT)
+       u32 rtsdctl;            /* seed control register */
+       union {
+               u32 rtsblim;    /* PRGM=1: sparse bit limit register */
+               u32 rttotsam;   /* PRGM=0: total samples register */
+       };
+       u32 rtfreqmin;          /* frequency count min. limit register */
+       union {
+               u32 rtfreqmax;  /* PRGM=1: freq. count max. limit register */
+               u32 rtfreqcnt;  /* PRGM=0: freq. count register */
+       };
+       u32 rsvd1[40];
+#define RNG_STATE0_HANDLE_INSTANTIATED 0x00000001
+       u32 rdsta;              /*RNG DRNG Status Register*/
+       u32 rsvd2[15];
+};
+
+typedef struct ccsr_sec {
+       u32     res0;
+       u32     mcfgr;          /* Master CFG Register */
+       u8      res1[0x4];
+       u32     scfgr;
+       struct {
+               u32     ms;     /* Job Ring LIODN Register, MS */
+               u32     ls;     /* Job Ring LIODN Register, LS */
+       } jrliodnr[4];
+       u8      res2[0x2c];
+       u32     jrstartr;       /* Job Ring Start Register */
+       struct {
+               u32     ms;     /* RTIC LIODN Register, MS */
+               u32     ls;     /* RTIC LIODN Register, LS */
+       } rticliodnr[4];
+       u8      res3[0x1c];
+       u32     decorr;         /* DECO Request Register */
+       struct {
+               u32     ms;     /* DECO LIODN Register, MS */
+               u32     ls;     /* DECO LIODN Register, LS */
+       } decoliodnr[8];
+       u8      res4[0x40];
+       u32     dar;            /* DECO Avail Register */
+       u32     drr;            /* DECO Reset Register */
+       u8      res5[0x4d8];
+       struct rng4tst rng;     /* RNG Registers */
+       u8      res11[0x8a0];
+       u32     crnr_ms;        /* CHA Revision Number Register, MS */
+       u32     crnr_ls;        /* CHA Revision Number Register, LS */
+       u32     ctpr_ms;        /* Compile Time Parameters Register, MS */
+       u32     ctpr_ls;        /* Compile Time Parameters Register, LS */
+       u8      res6[0x10];
+       u32     far_ms;         /* Fault Address Register, MS */
+       u32     far_ls;         /* Fault Address Register, LS */
+       u32     falr;           /* Fault Address LIODN Register */
+       u32     fadr;           /* Fault Address Detail Register */
+       u8      res7[0x4];
+       u32     csta;           /* CAAM Status Register */
+       u8      res8[0x8];
+       u32     rvid;           /* Run Time Integrity Checking Version ID Reg.*/
+       u32     ccbvid;         /* CHA Cluster Block Version ID Register */
+       u32     chavid_ms;      /* CHA Version ID Register, MS */
+       u32     chavid_ls;      /* CHA Version ID Register, LS */
+       u32     chanum_ms;      /* CHA Number Register, MS */
+       u32     chanum_ls;      /* CHA Number Register, LS */
+       u32     secvid_ms;      /* SEC Version ID Register, MS */
+       u32     secvid_ls;      /* SEC Version ID Register, LS */
+       u8      res9[0x6020];
+       u32     qilcr_ms;       /* Queue Interface LIODN CFG Register, MS */
+       u32     qilcr_ls;       /* Queue Interface LIODN CFG Register, LS */
+       u8      res10[0x8fd8];
+} ccsr_sec_t;
+
+#define SEC_CTPR_MS_AXI_LIODN          0x08000000
+#define SEC_CTPR_MS_QI                 0x02000000
+#define SEC_CTPR_MS_VIRT_EN_INCL       0x00000001
+#define SEC_CTPR_MS_VIRT_EN_POR                0x00000002
+#define SEC_RVID_MA                    0x0f000000
+#define SEC_CHANUM_MS_JRNUM_MASK       0xf0000000
+#define SEC_CHANUM_MS_JRNUM_SHIFT      28
+#define SEC_CHANUM_MS_DECONUM_MASK     0x0f000000
+#define SEC_CHANUM_MS_DECONUM_SHIFT    24
+#define SEC_SECVID_MS_IPID_MASK        0xffff0000
+#define SEC_SECVID_MS_IPID_SHIFT       16
+#define SEC_SECVID_MS_MAJ_REV_MASK     0x0000ff00
+#define SEC_SECVID_MS_MAJ_REV_SHIFT    8
+#define SEC_CCBVID_ERA_MASK            0xff000000
+#define SEC_CCBVID_ERA_SHIFT           24
+#define SEC_SCFGR_RDBENABLE            0x00000400
+#define SEC_SCFGR_VIRT_EN              0x00008000
+#define SEC_CHAVID_LS_RNG_SHIFT                16
+#define SEC_CHAVID_RNG_LS_MASK         0x000f0000
+
+#define CONFIG_JRSTARTR_JR0            0x00000001
+
+struct jr_regs {
+#ifdef CONFIG_SYS_FSL_SEC_LE
+       u32 irba_l;
+       u32 irba_h;
+#else
+       u32 irba_h;
+       u32 irba_l;
+#endif
+       u32 rsvd1;
+       u32 irs;
+       u32 rsvd2;
+       u32 irsa;
+       u32 rsvd3;
+       u32 irja;
+#ifdef CONFIG_SYS_FSL_SEC_LE
+       u32 orba_l;
+       u32 orba_h;
+#else
+       u32 orba_h;
+       u32 orba_l;
+#endif
+       u32 rsvd4;
+       u32 ors;
+       u32 rsvd5;
+       u32 orjr;
+       u32 rsvd6;
+       u32 orsf;
+       u32 rsvd7;
+       u32 jrsta;
+       u32 rsvd8;
+       u32 jrint;
+       u32 jrcfg0;
+       u32 jrcfg1;
+       u32 rsvd9;
+       u32 irri;
+       u32 rsvd10;
+       u32 orwi;
+       u32 rsvd11;
+       u32 jrcr;
+};
+
+int sec_init(void);
+#endif
+
+#endif /* __FSL_SEC_H */
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 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 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 {
diff --git a/include/serial_mxc.h b/include/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/serial_pl01x.h b/include/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 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 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 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 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 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)
 {
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 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");