]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
authorTom Rini <trini@ti.com>
Mon, 1 Jul 2013 14:11:56 +0000 (10:11 -0400)
committerTom Rini <trini@ti.com>
Mon, 1 Jul 2013 14:11:56 +0000 (10:11 -0400)
294 files changed:
.checkpatch.conf
Makefile
README
arch/arm/config.mk
arch/arm/cpu/arm920t/ep93xx/u-boot.lds
arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds
arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds
arch/arm/cpu/armv7/am33xx/board.c
arch/arm/cpu/armv7/am33xx/clock_am33xx.c
arch/arm/cpu/armv7/exynos/Makefile
arch/arm/cpu/armv7/exynos/clock.c
arch/arm/cpu/armv7/exynos/tzpc.c [moved from board/samsung/smdk5250/tzpc_init.c with 69% similarity]
arch/arm/cpu/armv7/s5p-common/Makefile
arch/arm/cpu/armv7/s5p-common/timer.c
arch/arm/cpu/ixp/u-boot.lds
arch/arm/cpu/u-boot-spl.lds
arch/arm/cpu/u-boot.lds
arch/arm/dts/exynos5250.dtsi
arch/arm/include/asm/arch-am33xx/sys_proto.h
arch/arm/include/asm/arch-exynos/cpu.h
arch/arm/include/asm/arch-exynos/dwmmc.h
arch/arm/include/asm/arch-exynos/tmu.h
arch/arm/include/asm/arch-exynos/tzpc.h
arch/arm/lib/Makefile
arch/arm/lib/bootm.c
arch/arm/lib/relocate.S
arch/arm/lib/sections.c [moved from arch/arm/lib/bss.c with 79% similarity]
arch/m68k/cpu/mcf5445x/speed.c
arch/m68k/include/asm/m5235.h
arch/m68k/lib/board.c
arch/microblaze/lib/bootm.c
arch/nios2/lib/bootm.c
arch/openrisc/lib/bootm.c
arch/powerpc/cpu/mpc85xx/Makefile
arch/powerpc/cpu/mpc85xx/cmd_errata.c
arch/powerpc/cpu/mpc85xx/cpu.c
arch/powerpc/cpu/mpc85xx/cpu_init.c
arch/powerpc/cpu/mpc85xx/cpu_init_early.c
arch/powerpc/cpu/mpc85xx/fdt.c
arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c
arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c
arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c
arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c
arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c
arch/powerpc/cpu/mpc85xx/p1010_serdes.c
arch/powerpc/cpu/mpc85xx/p1021_serdes.c
arch/powerpc/cpu/mpc85xx/p1022_serdes.c
arch/powerpc/cpu/mpc85xx/p1023_serdes.c
arch/powerpc/cpu/mpc85xx/p2020_serdes.c
arch/powerpc/cpu/mpc85xx/p2041_serdes.c
arch/powerpc/cpu/mpc85xx/p3041_serdes.c
arch/powerpc/cpu/mpc85xx/p4080_serdes.c
arch/powerpc/cpu/mpc85xx/p5020_serdes.c
arch/powerpc/cpu/mpc85xx/p5040_serdes.c
arch/powerpc/cpu/mpc85xx/start.S
arch/powerpc/cpu/mpc85xx/t1040_serdes.c
arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
arch/powerpc/cpu/mpc85xx/u-boot.lds
arch/powerpc/cpu/mpc86xx/cpu.c
arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c
arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c
arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
arch/powerpc/cpu/mpc8xxx/srio.c
arch/powerpc/include/asm/config_mpc85xx.h
arch/powerpc/include/asm/fsl_ifc.h
arch/powerpc/include/asm/fsl_law.h
arch/powerpc/include/asm/immap_85xx.h
arch/powerpc/lib/bootm.c
arch/sandbox/cpu/cpu.c
arch/sandbox/cpu/os.c
arch/x86/include/asm/global_data.h
arch/x86/include/asm/msr.h
arch/x86/include/asm/u-boot-x86.h
arch/x86/lib/bootm.c
arch/x86/lib/gcc.c
arch/x86/lib/tsc_timer.c
board/LaCie/common/cpld-gpio-bus.c [new file with mode: 0644]
board/LaCie/common/cpld-gpio-bus.h [new file with mode: 0644]
board/LaCie/net2big_v2/Makefile
board/LaCie/net2big_v2/net2big_v2.c
board/LaCie/net2big_v2/net2big_v2.h
board/actux1/u-boot.lds
board/actux2/u-boot.lds
board/actux3/u-boot.lds
board/ait/cam_enc_4xx/u-boot-spl.lds
board/atmel/at91sam9n12ek/at91sam9n12ek.c
board/davinci/da8xxevm/u-boot-spl-da850evm.lds
board/davinci/da8xxevm/u-boot-spl-hawk.lds
board/dvlhost/u-boot.lds
board/eltec/elppc/misc.c
board/freescale/b4860qds/tlb.c
board/freescale/bsc9131rdb/Makefile
board/freescale/bsc9131rdb/README
board/freescale/bsc9131rdb/law.c
board/freescale/bsc9131rdb/spl_minimal.c [new file with mode: 0644]
board/freescale/bsc9131rdb/tlb.c
board/freescale/bsc9132qds/Makefile
board/freescale/bsc9132qds/bsc9132qds.c
board/freescale/bsc9132qds/law.c
board/freescale/bsc9132qds/spl_minimal.c [new file with mode: 0644]
board/freescale/bsc9132qds/tlb.c
board/freescale/common/Makefile
board/freescale/common/pixis.c
board/freescale/mx31ads/u-boot.lds
board/freescale/p1010rdb/Makefile
board/freescale/p1010rdb/spl_minimal.c [moved from nand_spl/board/freescale/p1010rdb/nand_boot.c with 95% similarity]
board/freescale/p1010rdb/tlb.c
board/freescale/p1023rdb/Makefile [new file with mode: 0644]
board/freescale/p1023rdb/ddr.c [new file with mode: 0644]
board/freescale/p1023rdb/law.c [new file with mode: 0644]
board/freescale/p1023rdb/p1023rdb.c [new file with mode: 0644]
board/freescale/p1023rdb/tlb.c [new file with mode: 0644]
board/freescale/t4qds/tlb.c
board/ifm/ac14xx/ac14xx.c
board/isee/igep0033/board.c
board/phytec/pcm051/board.c
board/samsung/dts/exynos5250-smdk5250.dts
board/samsung/dts/exynos5250-snow.dts
board/samsung/origen/lowlevel_init.S
board/samsung/origen/origen_setup.h
board/samsung/smdk5250/Makefile
board/samsung/smdk5250/clock_init.c
board/samsung/smdk5250/clock_init.h
board/samsung/smdk5250/exynos5-dt.c [new file with mode: 0644]
board/samsung/smdk5250/lowlevel_init.S
board/samsung/smdk5250/setup.h
board/samsung/smdk5250/smdk5250.c
board/samsung/smdk5250/spl_boot.c
board/samsung/smdkv310/lowlevel_init.S
board/ti/am335x/board.c
board/ti/panda/panda.c
board/ti/ti814x/evm.c
board/vpac270/u-boot-spl.lds
boards.cfg
common/Makefile
common/board_f.c
common/board_r.c
common/bootstage.c
common/cmd_bootm.c
common/cmd_ide.c
common/cmd_mem.c
common/cmd_mmc.c
common/cmd_pxe.c
common/cmd_trace.c [new file with mode: 0644]
common/image-fdt.c
common/image-fit.c
common/image-sig.c [new file with mode: 0644]
common/image.c
common/usb_storage.c
config.mk
doc/README.plan9 [new file with mode: 0644]
doc/README.srio-pcie-boot-corenet
doc/README.trace [new file with mode: 0644]
doc/device-tree-bindings/exynos/dwmmc.txt [new file with mode: 0644]
doc/device-tree-bindings/input/cros-ec-keyb.txt [new file with mode: 0644]
doc/device-tree-bindings/misc/cros-ec.txt [new file with mode: 0644]
doc/mkimage.1
doc/uImage.FIT/sign-configs.its [new file with mode: 0644]
doc/uImage.FIT/sign-images.its [new file with mode: 0644]
doc/uImage.FIT/signature.txt [new file with mode: 0644]
doc/uImage.FIT/verified-boot.txt [new file with mode: 0644]
drivers/hwmon/lm63.c
drivers/input/Makefile
drivers/input/cros_ec_keyb.c [new file with mode: 0644]
drivers/misc/Makefile
drivers/misc/cros_ec.c [new file with mode: 0644]
drivers/misc/cros_ec_i2c.c [new file with mode: 0644]
drivers/misc/cros_ec_lpc.c [new file with mode: 0644]
drivers/misc/cros_ec_spi.c [new file with mode: 0644]
drivers/mmc/dw_mmc.c
drivers/mmc/exynos_dw_mmc.c
drivers/mmc/mmc.c
drivers/mtd/cfi_flash.c
drivers/mtd/nand/Makefile
drivers/mtd/nand/fsl_ifc_spl.c [moved from nand_spl/nand_boot_fsl_ifc.c with 88% similarity]
drivers/mtd/spi/Makefile
drivers/mtd/spi/gigadevice.c [new file with mode: 0644]
drivers/mtd/spi/spansion.c
drivers/mtd/spi/spi_flash.c
drivers/mtd/spi/spi_flash_internal.h
drivers/mtd/spi/stmicro.c
drivers/mtd/spi/winbond.c
drivers/net/Makefile
drivers/net/designware.c
drivers/net/ftgmac100.c
drivers/net/ftmac110.c [new file with mode: 0644]
drivers/net/ftmac110.h [new file with mode: 0644]
drivers/net/ks8851_mll.c [new file with mode: 0644]
drivers/net/ks8851_mll.h [new file with mode: 0644]
drivers/net/macb.c
drivers/net/macb.h
drivers/net/mvgbe.c
drivers/net/mvgbe.h
drivers/net/phy/Makefile
drivers/net/phy/atheros.c
drivers/net/phy/icplus.c [new file with mode: 0644]
drivers/net/phy/marvell.c
drivers/net/phy/micrel.c
drivers/net/phy/natsemi.c
drivers/net/phy/phy.c
drivers/net/sunxi_wemac.c [new file with mode: 0644]
drivers/pci/fsl_pci_init.c
drivers/power/exynos-tmu.c
drivers/serial/serial.c
drivers/serial/serial_s5p.c
drivers/spi/cf_qspi.c
drivers/spi/exynos_spi.c
drivers/spi/mxc_spi.c
drivers/usb/musb/musb_hcd.c
drivers/usb/musb/musb_udc.c
drivers/video/exynos_fb.c
include/asm-generic/global_data.h
include/asm-generic/sections.h
include/command.h
include/common.h
include/configs/B4860QDS.h
include/configs/BSC9131RDB.h
include/configs/BSC9132QDS.h
include/configs/P1010RDB.h
include/configs/P1023RDB.h [new file with mode: 0644]
include/configs/P2041RDB.h
include/configs/P3041DS.h
include/configs/P4080DS.h
include/configs/P5020DS.h
include/configs/a3m071.h
include/configs/ac14xx.h
include/configs/am335x_evm.h
include/configs/at91sam9n12ek.h
include/configs/coreboot.h
include/configs/dra7xx_evm.h
include/configs/exynos5250-dt.h
include/configs/lacie_kw.h
include/configs/omap4_common.h
include/configs/omap5_common.h
include/configs/omap5_uevm.h
include/configs/origen.h
include/configs/pcm051.h
include/configs/sandbox.h
include/configs/smdkv310.h
include/configs/t4qds.h
include/configs/trats.h
include/cros_ec.h [new file with mode: 0644]
include/cros_ec_message.h [new file with mode: 0644]
include/dwmmc.h
include/ec_commands.h [new file with mode: 0644]
include/fdtdec.h
include/ide.h
include/image.h
include/libfdt.h
include/linux/ethtool.h
include/linux/mii.h
include/micrel.h
include/mmc.h
include/net.h
include/netdev.h
include/part.h
include/pci.h
include/phy.h
include/rsa.h [new file with mode: 0644]
include/spi.h
include/spi_flash.h
include/trace.h [new file with mode: 0644]
include/vsprintf.h
lib/Makefile
lib/fdtdec.c
lib/libfdt/fdt_wip.c
lib/rsa/Makefile [new file with mode: 0644]
lib/rsa/rsa-sign.c [new file with mode: 0644]
lib/rsa/rsa-verify.c [new file with mode: 0644]
lib/trace.c [new file with mode: 0644]
lib/vsprintf.c
nand_spl/board/freescale/p1010rdb/Makefile [deleted file]
net/link_local.c
net/net.c
net/nfs.c
net/tftp.c
spl/Makefile
test/image/test-fit.py
test/trace/test-trace.sh [new file with mode: 0755]
test/vboot/.gitignore [new file with mode: 0644]
test/vboot/sandbox-kernel.dts [new file with mode: 0644]
test/vboot/sandbox-u-boot.dts [new file with mode: 0644]
test/vboot/sign-configs.its [new file with mode: 0644]
test/vboot/sign-images.its [new file with mode: 0644]
test/vboot/vboot_test.sh [new file with mode: 0755]
tools/.gitignore
tools/Makefile
tools/fit_image.c
tools/image-host.c
tools/mkimage.c
tools/mkimage.h
tools/pblimage.c
tools/proftool.c [new file with mode: 0644]

index d88af57129a82cf1b8cf772e9ca02d7c7a20efbb..35167e12015b202a910be77ed075af4dd8425b12 100644 (file)
@@ -18,3 +18,6 @@
 
 # Not Linux, so we don't recommend usleep_range() over udelay()
 --ignore USLEEP_RANGE
+
+# Ignore networking block comment style
+--ignore NETWORKING_BLOCK_COMMENT_STYLE
index 693b3f27646621e353e4a52a96f768d70de4d5db..ba1c10b2dc2fe5a0dfc21455785a52f9aacf560d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@
 VERSION = 2013
 PATCHLEVEL = 07
 SUBLEVEL =
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 ifneq "$(SUBLEVEL)" ""
 U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 else
@@ -247,6 +247,7 @@ OBJS := $(addprefix $(obj),$(OBJS))
 HAVE_VENDOR_COMMON_LIB = $(if $(wildcard board/$(VENDOR)/common/Makefile),y,n)
 
 LIBS-y += lib/libgeneric.o
+LIBS-y += lib/rsa/librsa.o
 LIBS-y += lib/lzma/liblzma.o
 LIBS-y += lib/lzo/liblzo.o
 LIBS-y += lib/zlib/libz.o
@@ -743,6 +744,13 @@ tools: $(VERSION_FILE) $(TIMESTAMP_FILE)
        $(MAKE) -C $@ all
 endif  # config.mk
 
+# ARM relocations should all be R_ARM_RELATIVE.
+checkarmreloc: $(obj)u-boot
+       @if test "R_ARM_RELATIVE" != \
+               "`readelf -r $< | cut -d ' ' -f 4 | grep R_ARM | sort -u`"; \
+               then echo "$< contains relocations other than \
+               R_ARM_RELATIVE"; false; fi
+
 $(VERSION_FILE):
                @mkdir -p $(dir $(VERSION_FILE))
                @( localvers='$(shell $(TOPDIR)/tools/setlocalversion $(TOPDIR))' ; \
@@ -824,7 +832,8 @@ clean:
               $(obj)tools/mk{smdk5250,}spl                               \
               $(obj)tools/mxsboot                                        \
               $(obj)tools/ncb             $(obj)tools/ubsha1             \
-              $(obj)tools/kernel-doc/docproc
+              $(obj)tools/kernel-doc/docproc                             \
+              $(obj)tools/proftool
        @rm -f $(obj)board/cray/L1/{bootscript.c,bootscript.image}        \
               $(obj)board/matrix_vision/*/bootscript.img                 \
               $(obj)board/voiceblue/eeprom                               \
diff --git a/README b/README
index cd0336c3c887a2efdaac7c4c8ed3092f2b08e276..5c343da32bdf581420c0d18e5cea3cac49c8f9e3 100644 (file)
--- a/README
+++ b/README
@@ -413,11 +413,22 @@ The following options need to be configured:
                See Freescale App Note 4493 for more information about
                this erratum.
 
+               CONFIG_A003399_NOR_WORKAROUND
+               Enables a workaround for IFC erratum A003399. It is only
+               requred during NOR boot.
+
                CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
 
                This is the value to write into CCSR offset 0x18600
                according to the A004510 workaround.
 
+               CONFIG_SYS_FSL_DSP_M2_RAM_ADDR
+               This value denotes start offset of M2 memory
+               which is directly connected to the DSP core.
+
+               CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT
+               This value denotes start offset of DSP CCSR space.
+
 - Generic CPU options:
                CONFIG_SYS_BIG_ENDIAN, CONFIG_SYS_LITTLE_ENDIAN
 
@@ -843,7 +854,7 @@ The following options need to be configured:
                CONFIG_CMD_FDOS         * Dos diskette Support
                CONFIG_CMD_FLASH          flinfo, erase, protect
                CONFIG_CMD_FPGA           FPGA device initialization support
-               CONFIG_CMD_FUSE           Device fuse support
+               CONFIG_CMD_FUSE         * Device fuse support
                CONFIG_CMD_GETTIME      * Get time since boot
                CONFIG_CMD_GO           * the 'go' command (exec code)
                CONFIG_CMD_GREPENV      * search environment
@@ -853,7 +864,7 @@ The following options need to be configured:
                CONFIG_CMD_IDE          * IDE harddisk support
                CONFIG_CMD_IMI            iminfo
                CONFIG_CMD_IMLS           List all images found in NOR flash
-               CONFIG_CMD_IMLS_NAND      List all images found in NAND flash
+               CONFIG_CMD_IMLS_NAND    * List all images found in NAND flash
                CONFIG_CMD_IMMAP        * IMMR dump support
                CONFIG_CMD_IMPORTENV    * import an environment
                CONFIG_CMD_INI          * import data from an ini file into the env
@@ -861,23 +872,24 @@ The following options need to be configured:
                CONFIG_CMD_ITEST          Integer/string test of 2 values
                CONFIG_CMD_JFFS2        * JFFS2 Support
                CONFIG_CMD_KGDB         * kgdb
-               CONFIG_CMD_LDRINFO        ldrinfo (display Blackfin loader)
+               CONFIG_CMD_LDRINFO      * ldrinfo (display Blackfin loader)
                CONFIG_CMD_LINK_LOCAL   * link-local IP address auto-configuration
                                          (169.254.*.*)
                CONFIG_CMD_LOADB          loadb
                CONFIG_CMD_LOADS          loads
-               CONFIG_CMD_MD5SUM         print md5 message digest
+               CONFIG_CMD_MD5SUM       * print md5 message digest
                                          (requires CONFIG_CMD_MEMORY and CONFIG_MD5)
                CONFIG_CMD_MEMINFO      * Display detailed memory information
                CONFIG_CMD_MEMORY         md, mm, nm, mw, cp, cmp, crc, base,
                                          loop, loopw
-               CONFIG_CMD_MEMTEST        mtest
+               CONFIG_CMD_MEMTEST      * mtest
                CONFIG_CMD_MISC           Misc functions like sleep etc
                CONFIG_CMD_MMC          * MMC memory mapped support
                CONFIG_CMD_MII          * MII utility commands
                CONFIG_CMD_MTDPARTS     * MTD partition support
                CONFIG_CMD_NAND         * NAND support
                CONFIG_CMD_NET            bootp, tftpboot, rarpboot
+               CONFIG_CMD_NFS            NFS support
                CONFIG_CMD_PCA953X      * PCA953x I2C gpio commands
                CONFIG_CMD_PCA953X_INFO * PCA953x I2C gpio info command
                CONFIG_CMD_PCI          * pciinfo
@@ -896,7 +908,7 @@ The following options need to be configured:
                CONFIG_CMD_SETGETDCR      Support for DCR Register access
                                          (4xx only)
                CONFIG_CMD_SF           * Read/write/erase SPI NOR flash
-               CONFIG_CMD_SHA1SUM        print sha1 memory digest
+               CONFIG_CMD_SHA1SUM      * print sha1 memory digest
                                          (requires CONFIG_CMD_MEMORY)
                CONFIG_CMD_SOFTSWITCH   * Soft switch setting command for BF60x
                CONFIG_CMD_SOURCE         "source" command Support
@@ -908,6 +920,7 @@ The following options need to be configured:
                CONFIG_CMD_USB          * USB support
                CONFIG_CMD_CDP          * Cisco Discover Protocol support
                CONFIG_CMD_MFSL         * Microblaze FSL support
+               CONFIG_CMD_XIMG           Load part of Multi Image
 
 
                EXAMPLE: If you want all functions except of network
@@ -1432,6 +1445,11 @@ CBFS (Coreboot Filesystem) support
                Export function i8042_kbd_init, i8042_tstc and i8042_getc
                for cfb_console. Supports cursor blinking.
 
+               CONFIG_CROS_EC_KEYB
+               Enables a Chrome OS keyboard using the CROS_EC interface.
+               This uses CROS_EC to communicate with a second microcontroller
+               which provides key scans on request.
+
 - Video support:
                CONFIG_VIDEO
 
@@ -2509,6 +2527,11 @@ CBFS (Coreboot Filesystem) support
                Define this option to include a destructive SPI flash
                test ('sf test').
 
+               CONFIG_SPI_FLASH_BAR            Ban/Extended Addr Reg
+
+               Define this option to use the Bank addr/Extended addr
+               support on SPI flashes which has size > 16Mbytes.
+
 - SystemACE Support:
                CONFIG_SYSTEMACE
 
@@ -2560,6 +2583,16 @@ CBFS (Coreboot Filesystem) support
                Note: There is also a sha1sum command, which should perhaps
                be deprecated in favour of 'hash sha1'.
 
+- Signing support:
+               CONFIG_RSA
+
+               This enables the RSA algorithm used for FIT image verification
+               in U-Boot. See doc/uImage/signature for more information.
+
+               The signing part is build into mkimage regardless of this
+               option.
+
+
 - Show boot progress:
                CONFIG_SHOW_BOOT_PROGRESS
 
@@ -2784,6 +2817,11 @@ FIT uImage format:
                most specific compatibility entry of U-Boot's fdt's root node.
                The order of entries in the configuration's fdt is ignored.
 
+               CONFIG_FIT_SIGNATURE
+               This option enables signature verification of FIT uImages,
+               using a hash signed and verified using RSA. See
+               doc/uImage.FIT/signature.txt for more details.
+
 - Standalone program support:
                CONFIG_STANDALONE_LOAD_ADDR
 
@@ -3022,6 +3060,14 @@ FIT uImage format:
                CONFIG_SPL_LIBGENERIC_SUPPORT
                Support for lib/libgeneric.o in SPL binary
 
+               CONFIG_SPL_ENV_SUPPORT
+               Support for the environment operating in SPL binary
+
+               CONFIG_SPL_NET_SUPPORT
+               Support for the net/libnet.o in SPL binary.
+               It conflicts with SPL env from storage medium specified by
+               CONFIG_ENV_IS_xxx but CONFIG_ENV_IS_NOWHERE
+
                CONFIG_SPL_PAD_TO
                Image offset to which the SPL should be padded before appending
                the SPL payload. By default, this is defined as
@@ -3964,6 +4010,9 @@ Low Level (hardware related) configuration options:
 - CONFIG_SRIO2:
                Board has SRIO 2 port available
 
+- CONFIG_SRIO_PCIE_BOOT_MASTER
+               Board can support master function for Boot from SRIO and PCIE
+
 - CONFIG_SYS_SRIOn_MEM_VIRT:
                Virtual Address of SRIO port 'n' memory region
 
@@ -4074,6 +4123,11 @@ Low Level (hardware related) configuration options:
                that is executed before the actual U-Boot. E.g. when
                compiling a NAND SPL.
 
+- CONFIG_SYS_MPC85XX_NO_RESETVEC
+               Only for 85xx systems. If this variable is specified, the section
+               .resetvec is not kept and the section .bootpg is placed in the
+               previous 4k of the .text section.
+
 - CONFIG_ARCH_MAP_SYSMEM
                Generally U-Boot (and in particular the md command) uses
                effective address. It is therefore not necessary to regard
index dc64160789cc91527cc34d46cfbc31d2a93dbdbd..e80e1ed1a3722356b5b607081e8df040c218acba 100644 (file)
@@ -109,3 +109,8 @@ ifeq ($(GAS_BUG_12532),y)
 PLATFORM_RELFLAGS += -fno-optimize-sibling-calls
 endif
 endif
+
+# check that only R_ARM_RELATIVE relocations are generated
+ifneq ($(CONFIG_SPL_BUILD),y)
+ALL-y  += checkarmreloc
+endif
index cf55bf7d4d34675ebdb8cdc91722a718da7f1b95..367c805e385a138585fa6bec21f45ac8b7c8b642 100644 (file)
@@ -31,6 +31,7 @@ SECTIONS
        . = ALIGN(4);
        .text      :
        {
+               *(.__image_copy_start)
          arch/arm/cpu/arm920t/start.o  (.text*)
                /* the EP93xx expects to find the pattern 'CRUS' at 0x1000 */
          . = 0x1000;
@@ -56,7 +57,10 @@ SECTIONS
 
        . = ALIGN(4);
 
-       __image_copy_end = .;
+       .image_copy_end :
+       {
+               *(.__image_copy_end)
+       }
 
        __bss_start = .;
        .bss : { *(.bss*) }
index 673c725ab34e888255fff77a3549075394b9cefe..f4e7525f1e24b61fcaec7d2286b0f5625dc98a22 100644 (file)
@@ -57,11 +57,6 @@ SECTIONS
                __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
-       }
-
        .bss : {
                . = ALIGN(4);
                __bss_start = .;
index 967a135b3b4843d32c7f19cea1fb6c4fe7c86a97..446d09501bc76ed442d36ff4a1406994faba9da6 100644 (file)
@@ -57,11 +57,6 @@ SECTIONS
                __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
-       }
-
        .bss : {
                . = ALIGN(4);
                __bss_start = .;
index 885fb2d20e5a516432ed07a8ecce327dded9edb0..b935a29a3ca18aeec87287c4329925037562f348 100644 (file)
@@ -149,3 +149,43 @@ int arch_misc_init(void)
 #endif
        return 0;
 }
+
+#ifdef CONFIG_SPL_BUILD
+void rtc32k_enable(void)
+{
+       struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
+
+       /*
+        * Unlock the RTC's registers.  For more details please see the
+        * RTC_SS section of the TRM.  In order to unlock we need to
+        * write these specific values (keys) in this order.
+        */
+       writel(0x83e70b13, &rtc->kick0r);
+       writel(0x95a4f1e0, &rtc->kick1r);
+
+       /* Enable the RTC 32K OSC by setting bits 3 and 6. */
+       writel((1 << 3) | (1 << 6), &rtc->osc);
+}
+
+#define UART_RESET             (0x1 << 1)
+#define UART_CLK_RUNNING_MASK  0x1
+#define UART_SMART_IDLE_EN     (0x1 << 0x3)
+
+void uart_soft_reset(void)
+{
+       struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
+       u32 regval;
+
+       regval = readl(&uart_base->uartsyscfg);
+       regval |= UART_RESET;
+       writel(regval, &uart_base->uartsyscfg);
+       while ((readl(&uart_base->uartsyssts) &
+               UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
+               ;
+
+       /* Disable smart idle */
+       regval = readl(&uart_base->uartsyscfg);
+       regval |= UART_SMART_IDLE_EN;
+       writel(regval, &uart_base->uartsyscfg);
+}
+#endif
index a1efc7520a7c149dc93b388ca84bf8fc23ac4ed7..9c4d0b439316c9353774ecb11d0a69d418a389dd 100644 (file)
@@ -246,7 +246,7 @@ static void enable_per_clocks(void)
                ;
 }
 
-static void mpu_pll_config(void)
+void mpu_pll_config_val(int mpull_m)
 {
        u32 clkmode, clksel, div_m2;
 
@@ -260,7 +260,7 @@ static void mpu_pll_config(void)
                ;
 
        clksel = clksel & (~CLK_SEL_MASK);
-       clksel = clksel | ((MPUPLL_M << CLK_SEL_SHIFT) | MPUPLL_N);
+       clksel = clksel | ((mpull_m << CLK_SEL_SHIFT) | MPUPLL_N);
        writel(clksel, &cmwkup->clkseldpllmpu);
 
        div_m2 = div_m2 & ~CLK_DIV_MASK;
@@ -274,6 +274,11 @@ static void mpu_pll_config(void)
                ;
 }
 
+static void mpu_pll_config(void)
+{
+       mpu_pll_config_val(CONFIG_SYS_MPUCLK);
+}
+
 static void core_pll_config(void)
 {
        u32 clkmode, clksel, div_m4, div_m5, div_m6;
index 9119961d95dfeab2e0415059b24c7792542e7656..b2f9152e1bf71ccc1f132300645ae344c46c2213 100644 (file)
@@ -22,7 +22,7 @@ include $(TOPDIR)/config.mk
 
 LIB    = $(obj)lib$(SOC).o
 
-COBJS  += clock.o power.o soc.o system.o pinmux.o
+COBJS  += clock.o power.o soc.o system.o pinmux.o tzpc.o
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS) $(SOBJS))
index 223660aab6d57ceb3b4118c9a898f6bd8afd025d..e1c42462e18ef424272ee96928704c21034a89ec 100644 (file)
@@ -116,10 +116,8 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
                /* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */
                fout = (m + k / 1024) * (freq / (p * (1 << s)));
        } else {
-               if (s < 1)
-                       s = 1;
-               /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
-               fout = m * (freq / (p * (1 << (s - 1))));
+               /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
+               fout = m * (freq / (p * (1 << s)));
        }
 
        return fout;
@@ -613,7 +611,7 @@ static unsigned long exynos4_get_mmc_clk(int dev_index)
                (struct exynos4_clock *)samsung_get_base_clock();
        unsigned long uclk, sclk;
        unsigned int sel, ratio, pre_ratio;
-       int shift;
+       int shift = 0;
 
        sel = readl(&clk->src_fsys);
        sel = (sel >> (dev_index << 2)) & 0xf;
@@ -662,7 +660,7 @@ static unsigned long exynos5_get_mmc_clk(int dev_index)
                (struct exynos5_clock *)samsung_get_base_clock();
        unsigned long uclk, sclk;
        unsigned int sel, ratio, pre_ratio;
-       int shift;
+       int shift = 0;
 
        sel = readl(&clk->src_fsys);
        sel = (sel >> (dev_index << 2)) & 0xf;
similarity index 69%
rename from board/samsung/smdk5250/tzpc_init.c
rename to arch/arm/cpu/armv7/exynos/tzpc.c
index c833541fd03e39a969c01dda9433effcba83b498..f5e8e9c47401f42baa19fd10a95e1e9e98aa1d13 100644 (file)
  * MA 02111-1307 USA
  */
 
+#include <common.h>
 #include <asm/arch/tzpc.h>
-#include"setup.h"
+#include <asm/io.h>
 
 /* Setting TZPC[TrustZone Protection Controller] */
 void tzpc_init(void)
 {
        struct exynos_tzpc *tzpc;
-       unsigned int addr;
+       unsigned int addr, start = 0, end = 0;
 
-       for (addr = TZPC0_BASE; addr <= TZPC9_BASE; addr += TZPC_BASE_OFFSET) {
+       start = samsung_get_base_tzpc();
+
+       if (cpu_is_exynos5())
+               end = start + ((EXYNOS5_NR_TZPC_BANKS - 1) * TZPC_BASE_OFFSET);
+       else if (cpu_is_exynos4())
+               end = start + ((EXYNOS4_NR_TZPC_BANKS - 1) * TZPC_BASE_OFFSET);
+
+       for (addr = start; addr <= end; addr += TZPC_BASE_OFFSET) {
                tzpc = (struct exynos_tzpc *)addr;
 
-               if (addr == TZPC0_BASE)
+               if (addr == start)
                        writel(R0SIZE, &tzpc->r0size);
 
                writel(DECPROTXSET, &tzpc->decprot0set);
                writel(DECPROTXSET, &tzpc->decprot1set);
 
-               if (addr != TZPC9_BASE) {
-                       writel(DECPROTXSET, &tzpc->decprot2set);
-                       writel(DECPROTXSET, &tzpc->decprot3set);
-               }
+               if (cpu_is_exynos5() && (addr == end))
+                       break;
+
+               writel(DECPROTXSET, &tzpc->decprot2set);
+               writel(DECPROTXSET, &tzpc->decprot3set);
        }
 }
index 17053995bd61aa21e26ee20b8917528b09400c41..0c38bd0d2f146debac9ca21f88973515202a81c8 100644 (file)
@@ -26,9 +26,11 @@ include $(TOPDIR)/config.mk
 LIB    = $(obj)libs5p-common.o
 
 COBJS-y                += cpu_info.o
+ifndef CONFIG_SPL_BUILD
 COBJS-y                += timer.o
 COBJS-y                += sromc.o
 COBJS-$(CONFIG_PWM)    += pwm.o
+endif
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y) $(SOBJS))
index 4adfaae656da8f378639939def0e84c24f960878..637593c3397a811103c6013117f4a4c8d5ecc439 100644 (file)
@@ -95,7 +95,7 @@ unsigned long get_timer(unsigned long base)
        return time_ms - base;
 }
 
-unsigned long timer_get_us(void)
+unsigned long __attribute__((no_instrument_function)) timer_get_us(void)
 {
        static unsigned long base_time_us;
 
index 553589ca6cbcdbcce06f804ac7507c1f906153d3..54bafda32443f7ee64da51d4df91b135cac32ddc 100644 (file)
@@ -31,6 +31,7 @@ SECTIONS
        . = ALIGN(4);
        .text :
        {
+               *(.__image_copy_start)
                arch/arm/cpu/ixp/start.o(.text*)
                *(.text*)
        }
@@ -54,17 +55,23 @@ SECTIONS
 
        . = ALIGN(4);
 
-       __image_copy_end = .;
+       .image_copy_end :
+       {
+               *(.__image_copy_end)
+       }
+
+       .rel_dyn_start :
+       {
+               *(.__rel_dyn_start)
+       }
 
        .rel.dyn : {
-               __rel_dyn_start = .;
                *(.rel*)
-               __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
+       .rel_dyn_end :
+       {
+               *(.__rel_dyn_end)
        }
 
        _end = .;
@@ -88,6 +95,7 @@ SECTIONS
                KEEP(*(.__bss_end));
        }
 
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynamic*) }
        /DISCARD/ : { *(.plt*) }
index 1408f03b2343ccb2569a9e3a7b6ad1ddf77444a2..b6ed25f7d1b9d7dc49a581f6abac5fce0a4b387a 100644 (file)
@@ -58,11 +58,6 @@ SECTIONS
                __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
-       }
-
        _end = .;
 
        .bss __rel_dyn_start (OVERLAY) : {
@@ -72,6 +67,7 @@ SECTIONS
                __bss_end = .;
        }
 
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynamic*) }
        /DISCARD/ : { *(.plt*) }
index d9bbee3b27dd39a903ef4e1092d50e4212747f71..3037885b1270ddaa5f502bfe24fdbe3b2fe829bc 100644 (file)
@@ -33,7 +33,7 @@ SECTIONS
        . = ALIGN(4);
        .text :
        {
-               __image_copy_start = .;
+               *(.__image_copy_start)
                CPUDIR/start.o (.text*)
                *(.text*)
        }
@@ -57,17 +57,23 @@ SECTIONS
 
        . = ALIGN(4);
 
-       __image_copy_end = .;
+       .image_copy_end :
+       {
+               *(.__image_copy_end)
+       }
+
+       .rel_dyn_start :
+       {
+               *(.__rel_dyn_start)
+       }
 
        .rel.dyn : {
-               __rel_dyn_start = .;
                *(.rel*)
-               __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
+       .rel_dyn_end :
+       {
+               *(.__rel_dyn_end)
        }
 
        _end = .;
@@ -101,6 +107,7 @@ SECTIONS
                KEEP(*(.__bss_end));
        }
 
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynamic*) }
        /DISCARD/ : { *(.plt*) }
index df4b231cf3a434c12be80f696db5eb7a8137318d..2d6dfff5917b3747e6ee039e85b84ccd00374f4b 100644 (file)
                #address-cells = <1>;
                #size-cells = <1>;
        };
+
+       mmc@12200000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "samsung,exynos5250-dwmmc";
+               reg = <0x12200000 0x1000>;
+               interrupts = <0 75 0>;
+       };
+
+       mmc@12210000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "samsung,exynos5250-dwmmc";
+               reg = <0x12210000 0x1000>;
+               interrupts = <0 76 0>;
+       };
+
+       mmc@12220000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "samsung,exynos5250-dwmmc";
+               reg = <0x12220000 0x1000>;
+               interrupts = <0 77 0>;
+       };
+
+       mmc@12230000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "samsung,exynos5250-dwmmc";
+               reg = <0x12230000 0x1000>;
+               interrupts = <0 78 0>;
+       };
+
+       gpio: gpio {
+       };
 };
index fedc674031d2d3321cabc02754d456106cc1bb91..307ac28245a41419807190857078e056e8ec5ecd 100644 (file)
@@ -32,6 +32,7 @@ extern struct ctrl_stat *cstat;
 u32 get_device_type(void);
 void save_omap_boot_params(void);
 void setup_clocks_for_console(void);
+void mpu_pll_config_val(int mpull_m);
 void ddr_pll_config(unsigned int ddrpll_M);
 
 void sdelay(unsigned long);
@@ -41,4 +42,7 @@ void gpmc_init(void);
 void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
                        u32 size);
 void omap_nand_switch_ecc(uint32_t, uint32_t);
+
+void rtc32k_enable(void);
+void uart_soft_reset(void);
 #endif
index f76e4897e9cd5196248962c09f601017fc1554bb..1ff7642d069c10d4d217c73c6cc6f4bde737f56e 100644 (file)
@@ -38,6 +38,7 @@
 #define EXYNOS4_CLOCK_BASE             0x10030000
 #define EXYNOS4_SYSTIMER_BASE          0x10050000
 #define EXYNOS4_WATCHDOG_BASE          0x10060000
+#define EXYNOS4_TZPC_BASE              0x10110000
 #define EXYNOS4_MIU_BASE               0x10600000
 #define EXYNOS4_DMC0_BASE              0x10400000
 #define EXYNOS4_DMC1_BASE              0x10410000
@@ -74,6 +75,7 @@
 #define EXYNOS4X12_CLOCK_BASE          0x10030000
 #define EXYNOS4X12_SYSTIMER_BASE       0x10050000
 #define EXYNOS4X12_WATCHDOG_BASE       0x10060000
+#define EXYNOS4X12_TZPC_BASE           0x10110000
 #define EXYNOS4X12_DMC0_BASE           0x10600000
 #define EXYNOS4X12_DMC1_BASE           0x10610000
 #define EXYNOS4X12_GPIO_PART4_BASE     0x106E0000
 #define EXYNOS5_POWER_BASE             0x10040000
 #define EXYNOS5_SWRESET                        0x10040400
 #define EXYNOS5_SYSREG_BASE            0x10050000
+#define EXYNOS5_TZPC_BASE              0x10100000
 #define EXYNOS5_WATCHDOG_BASE          0x101D0000
 #define EXYNOS5_ACE_SFR_BASE            0x10830000
 #define EXYNOS5_DMC_PHY0_BASE          0x10C00000
@@ -175,7 +178,7 @@ static inline char *s5p_get_cpu_name(void)
 }
 
 #define IS_SAMSUNG_TYPE(type, id)                      \
-static inline int cpu_is_##type(void)                  \
+static inline int __attribute__((no_instrument_function)) cpu_is_##type(void) \
 {                                                      \
        return (s5p_cpu_id >> 12) == id;                \
 }
@@ -184,7 +187,8 @@ IS_SAMSUNG_TYPE(exynos4, 0x4)
 IS_SAMSUNG_TYPE(exynos5, 0x5)
 
 #define IS_EXYNOS_TYPE(type, id)                       \
-static inline int proid_is_##type(void)                        \
+static inline int __attribute__((no_instrument_function)) \
+       proid_is_##type(void)                           \
 {                                                      \
        return s5p_cpu_id == id;                        \
 }
@@ -194,9 +198,10 @@ IS_EXYNOS_TYPE(exynos4412, 0x4412)
 IS_EXYNOS_TYPE(exynos5250, 0x5250)
 
 #define SAMSUNG_BASE(device, base)                             \
-static inline unsigned int samsung_get_base_##device(void)     \
+static inline unsigned int __attribute__((no_instrument_function)) \
+       samsung_get_base_##device(void) \
 {                                                              \
-       if (cpu_is_exynos4()) {                                 \
+       if (cpu_is_exynos4()) {                         \
                if (proid_is_exynos4412())                      \
                        return EXYNOS4X12_##base;               \
                return EXYNOS4_##base;                          \
@@ -233,6 +238,7 @@ SAMSUNG_BASE(watchdog, WATCHDOG_BASE)
 SAMSUNG_BASE(power, POWER_BASE)
 SAMSUNG_BASE(spi, SPI_BASE)
 SAMSUNG_BASE(spi_isp, SPI_ISP_BASE)
+SAMSUNG_BASE(tzpc, TZPC_BASE)
 #endif
 
 #endif /* _EXYNOS4_CPU_H */
index 8acdf9b7252e77bff1d3a3dd34f4b372dba2da93..3b147b86e39270c2b7fc57cfafc306729201418f 100644 (file)
 #define DWMCI_SET_DRV_CLK(x)   ((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x) ((x) << 24)
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);
-
-static inline unsigned int exynos_dwmmc_init(int index, int bus_width)
-{
-       unsigned int base = samsung_get_base_mmc() + (0x10000 * index);
-       return exynos_dwmci_init(base, bus_width, index);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel);
index 7e0158efb6549f6baae4dd48359024c9220a9ae7..cad35694f6443cea3947e3d812033b53dcb72a6a 100644 (file)
 #define __ASM_ARCH_TMU_H
 
 struct exynos5_tmu_reg {
-       unsigned triminfo;
-       unsigned rsvd1;
-       unsigned rsvd2;
-       unsigned rsvd3;
-       unsigned rsvd4;
-       unsigned triminfo_control;
-       unsigned rsvd5;
-       unsigned rsvd6;
-       unsigned tmu_control;
-       unsigned rsvd7;
-       unsigned tmu_status;
-       unsigned sampling_internal;
-       unsigned counter_value0;
-       unsigned counter_value1;
-       unsigned rsvd8;
-       unsigned rsvd9;
-       unsigned current_temp;
-       unsigned rsvd10;
-       unsigned rsvd11;
-       unsigned rsvd12;
-       unsigned threshold_temp_rise;
-       unsigned threshold_temp_fall;
-       unsigned rsvd13;
-       unsigned rsvd14;
-       unsigned past_temp3_0;
-       unsigned past_temp7_4;
-       unsigned past_temp11_8;
-       unsigned past_temp15_12;
-       unsigned inten;
-       unsigned intstat;
-       unsigned intclear;
-       unsigned rsvd15;
-       unsigned emul_con;
+       u32 triminfo;
+       u32 rsvd1[4];
+       u32 triminfo_control;
+       u32 rsvd5[2];
+       u32 tmu_control;
+       u32 rsvd7;
+       u32 tmu_status;
+       u32 sampling_internal;
+       u32 counter_value0;
+       u32 counter_value1;
+       u32 rsvd8[2];
+       u32 current_temp;
+       u32 rsvd10[3];
+       u32 threshold_temp_rise;
+       u32 threshold_temp_fall;
+       u32 rsvd13[2];
+       u32 past_temp3_0;
+       u32 past_temp7_4;
+       u32 past_temp11_8;
+       u32 past_temp15_12;
+       u32 inten;
+       u32 intstat;
+       u32 intclear;
+       u32 rsvd15;
+       u32 emul_con;
 };
 #endif /* __ASM_ARCH_TMU_H */
index c5eb4b1cc2bcda1e8c9b9e18a953b0db27aff411..4d9c3a32fb430ca1d1222b79d42ab6b7778955ea 100644 (file)
@@ -47,6 +47,26 @@ struct exynos_tzpc {
        unsigned int pcellid2;
        unsigned int pcellid3;
 };
+
+#define EXYNOS4_NR_TZPC_BANKS          6
+#define EXYNOS5_NR_TZPC_BANKS          10
+
+/* TZPC : Register Offsets */
+#define TZPC_BASE_OFFSET               0x10000
+
+/*
+ * TZPC Register Value :
+ * R0SIZE: 0x0 : Size of secured ram
+ */
+#define R0SIZE                 0x0
+
+/*
+ * TZPC Decode Protection Register Value :
+ * DECPROTXSET: 0xFF : Set Decode region to non-secure
+ */
+#define DECPROTXSET            0xFF
+void tzpc_init(void);
+
 #endif
 
 #endif
index 8ad9f66a5d50f2066a965e1b5ab3b94d0b2a79ee..9ecafb2723f8ce8c22b45dc9348c2aace9a3331b 100644 (file)
@@ -43,7 +43,7 @@ SOBJS-y += relocate.o
 ifndef CONFIG_SYS_GENERIC_BOARD
 COBJS-y        += board.o
 endif
-COBJS-y += bss.o
+COBJS-y += sections.o
 
 COBJS-y        += bootm.o
 COBJS-$(CONFIG_OF_LIBFDT) += bootm-fdt.o
index 1b6e0ace45372417af0b671aac632fce309b12f3..b22fbc998248ba95ba68883dbaee9adfa0c3f687 100644 (file)
@@ -68,12 +68,19 @@ void arch_lmb_reserve(struct lmb *lmb)
                    gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);
 }
 
-static void announce_and_cleanup(void)
+/**
+ * announce_and_cleanup() - Print message and prepare for kernel boot
+ *
+ * @fake: non-zero to do everything except actually boot
+ */
+static void announce_and_cleanup(int fake)
 {
-       printf("\nStarting kernel ...\n\n");
+       printf("\nStarting kernel ...%s\n\n", fake ?
+               "(fake run for tracing)" : "");
        bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
 #ifdef CONFIG_BOOTSTAGE_FDT
-       bootstage_fdt_add_report();
+       if (flag == BOOTM_STATE_OS_FAKE_GO)
+               bootstage_fdt_add_report();
 #endif
 #ifdef CONFIG_BOOTSTAGE_REPORT
        bootstage_report();
@@ -225,12 +232,13 @@ static void boot_prep_linux(bootm_headers_t *images)
 }
 
 /* Subcommand: GO */
-static void boot_jump_linux(bootm_headers_t *images)
+static void boot_jump_linux(bootm_headers_t *images, int flag)
 {
        unsigned long machid = gd->bd->bi_arch_number;
        char *s;
        void (*kernel_entry)(int zero, int arch, uint params);
        unsigned long r2;
+       int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
 
        kernel_entry = (void (*)(int, int, uint))images->ep;
 
@@ -243,14 +251,15 @@ static void boot_jump_linux(bootm_headers_t *images)
        debug("## Transferring control to Linux (at address %08lx)" \
                "...\n", (ulong) kernel_entry);
        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
-       announce_and_cleanup();
+       announce_and_cleanup(fake);
 
        if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
                r2 = (unsigned long)images->ft_addr;
        else
                r2 = gd->bd->bi_boot_params;
 
-       kernel_entry(0, machid, r2);
+       if (!fake)
+               kernel_entry(0, machid, r2);
 }
 
 /* Main Entry point for arm bootm implementation
@@ -270,13 +279,13 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
                return 0;
        }
 
-       if (flag & BOOTM_STATE_OS_GO) {
-               boot_jump_linux(images);
+       if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
+               boot_jump_linux(images, flag);
                return 0;
        }
 
        boot_prep_linux(images);
-       boot_jump_linux(images);
+       boot_jump_linux(images, flag);
        return 0;
 }
 
index 4446da94c55f01c5d66553dc300de05ff2a8896a..949b9e8025b994cb8e6a9d85e63a920387e11ba7 100644 (file)
  */
 
 ENTRY(relocate_code)
-       mov     r6, r0  /* save addr of destination */
-
-       ldr     r0, =_start             /* r0 <- SRC &_start */
-       subs    r9, r6, r0              /* r9 <- relocation offset */
+       ldr     r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */
+       subs    r9, r0, r1              /* r9 <- relocation offset */
        beq     relocate_done           /* skip relocation */
-       mov     r1, r6                  /* r1 <- scratch for copy loop */
-       adr     r7, relocate_code       /* r7 <- SRC &relocate_code */
-       ldr     r3, _image_copy_end_ofs /* r3 <- __image_copy_end local ofs */
-       add     r2, r7, r3              /* r2 <- SRC &__image_copy_end */
+       ldr     r2, =__image_copy_end   /* r2 <- SRC &__image_copy_end */
 
 copy_loop:
-       ldmia   r0!, {r10-r11}          /* copy from source address [r0]    */
-       stmia   r1!, {r10-r11}          /* copy to   target address [r1]    */
-       cmp     r0, r2                  /* until source end address [r2]    */
+       ldmia   r1!, {r10-r11}          /* copy from source address [r1]    */
+       stmia   r0!, {r10-r11}          /* copy to   target address [r0]    */
+       cmp     r1, r2                  /* until source end address [r2]    */
        blo     copy_loop
 
        /*
         * fix .rel.dyn relocations
         */
-       ldr     r10, _dynsym_start_ofs  /* r10 <- __dynsym_start local ofs */
-       add     r10, r10, r7            /* r10 <- SRC &__dynsym_start */
-       ldr     r2, _rel_dyn_start_ofs  /* r2 <- __rel_dyn_start local ofs */
-       add     r2, r2, r7              /* r2 <- SRC &__rel_dyn_start */
-       ldr     r3, _rel_dyn_end_ofs    /* r3 <- __rel_dyn_end local ofs */
-       add     r3, r3, r7              /* r3 <- SRC &__rel_dyn_end */
+       ldr     r2, =__rel_dyn_start    /* r2 <- SRC &__rel_dyn_start */
+       ldr     r3, =__rel_dyn_end      /* r3 <- SRC &__rel_dyn_end */
 fixloop:
-       ldr     r0, [r2]                /* r0 <- SRC location to fix up */
-       add     r0, r0, r9              /* r0 <- DST location to fix up */
-       ldr     r1, [r2, #4]
-       and     r7, r1, #0xff
-       cmp     r7, #23                 /* relative fixup? */
-       beq     fixrel
-       cmp     r7, #2                  /* absolute fixup? */
-       beq     fixabs
-       /* ignore unknown type of fixup */
-       b       fixnext
-fixabs:
-       /* absolute fix: set location to (offset) symbol value */
-       mov     r1, r1, LSR #4          /* r1 <- symbol index in .dynsym */
-       add     r1, r10, r1             /* r1 <- address of symbol in table */
-       ldr     r1, [r1, #4]            /* r1 <- symbol value */
-       add     r1, r1, r9              /* r1 <- relocated sym addr */
-       b       fixnext
-fixrel:
+       ldmia   r2!, {r0-r1}            /* (r0,r1) <- (SRC location,fixup) */
+       and     r1, r1, #0xff
+       cmp     r1, #23                 /* relative fixup? */
+       bne     fixnext
+
        /* relative fix: increase location by offset */
+       add     r0, r0, r9
        ldr     r1, [r0]
        add     r1, r1, r9
-fixnext:
        str     r1, [r0]
-       add     r2, r2, #8              /* each rel.dyn entry is 8 bytes */
+fixnext:
        cmp     r2, r3
        blo     fixloop
 
@@ -100,13 +78,4 @@ relocate_done:
         bx        lr
 #endif
 
-_image_copy_end_ofs:
-       .word __image_copy_end - relocate_code
-_rel_dyn_start_ofs:
-       .word __rel_dyn_start - relocate_code
-_rel_dyn_end_ofs:
-       .word __rel_dyn_end - relocate_code
-_dynsym_start_ofs:
-       .word __dynsym_start - relocate_code
-
 ENDPROC(relocate_code)
similarity index 79%
rename from arch/arm/lib/bss.c
rename to arch/arm/lib/sections.c
index 99eda5913760eab77955559bb9b56c453a9e1518..5921dd8d6625fcea0ef29a958a2d0b72f8f2b3cd 100644 (file)
@@ -35,5 +35,9 @@
  * aliasing warnings.
  */
 
-char __bss_start[0] __attribute__((used, section(".__bss_start")));
-char __bss_end[0] __attribute__((used, section(".__bss_end")));
+char __bss_start[0] __attribute__((section(".__bss_start")));
+char __bss_end[0] __attribute__((section(".__bss_end")));
+char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
+char __image_copy_end[0] __attribute__((section(".__image_copy_end")));
+char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));
+char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
index aa73e1f0252e33f1b9b9d95b7cf0e35fb06f15b7..0276d4d8261f5a33ef2eec430548f44b374e9f6e 100644 (file)
@@ -122,17 +122,17 @@ void setup_5441x_clocks(void)
 
        vco =  ((in_be32(&pll->pcr) & PLL_CR_FBKDIV_BITS) + 1) *
                CONFIG_SYS_INPUT_CLKSRC;
-       gd->vco_clk = vco;
+       gd->arch.vco_clk = vco;
 
-       gd->inp_clk = CONFIG_SYS_INPUT_CLKSRC;  /* Input clock */
+       gd->arch.inp_clk = CONFIG_SYS_INPUT_CLKSRC;     /* Input clock */
 
        pdr = in_be32(&pll->pdr);
        temp = (pdr & PLL_DR_OUTDIV1_BITS) + 1;
        gd->cpu_clk = vco / temp;       /* cpu clock */
-       gd->flb_clk = vco / temp;       /* FlexBus clock */
-       gd->flb_clk >>= 1;
+       gd->arch.flb_clk = vco / temp;  /* FlexBus clock */
+       gd->arch.flb_clk >>= 1;
        if (in_be16(ccm->misccr2) & 2)          /* fsys/4 */
-               gd->flb_clk >>= 1;
+               gd->arch.flb_clk >>= 1;
 
        temp = ((pdr & PLL_DR_OUTDIV2_BITS) >> 5) + 1;
        gd->bus_clk = vco / temp;       /* bus clock */
index 71a40d33d2016573b2541d4674aca2e7a2a6cbfe..a573f1cf01772f7e2c38f1463932551ed7b9dea4 100644 (file)
 #define SDRAMC_DCR_RC(x)               (((x)&0xFF)<<8)
 
 /* Bit definitions and macros for SDRAMC_DARCn */
-#define SDRAMC_DARCn_BA(x)             (((x)&0xFFFC)<<18)
+#define SDRAMC_DARCn_BA(x)             ((x)&0xFFFC0000)
 #define SDRAMC_DARCn_RE                        (0x00008000)
 #define SDRAMC_DARCn_CASL_MASK         (0x00003000)
 #define SDRAMC_DARCn_CASL_C0           (0x00000000)
index b2e306836412665a9185ebd03e0b6abd10f81701..efc9fccc1bc9f66619ec6d101e878269d24897b8 100644 (file)
@@ -403,14 +403,14 @@ void board_init_r (gd_t *id, ulong dest_addr)
 
        gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
 
-       debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
-
        WATCHDOG_RESET ();
 
        gd->reloc_off =  dest_addr - CONFIG_SYS_MONITOR_BASE;
 
        serial_initialize();
 
+       debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
+
        monitor_flash_len = (ulong)&__init_end - dest_addr;
 
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
index 38427090011b204cc4c09791a785a84fcfb3255a..b328f9497161c57424f2c3b87e63afd6cd2ba671 100644 (file)
@@ -62,8 +62,8 @@ int do_bootm_linux(int flag, int argc, char * const argv[],
 
        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
 
-       if (!of_flat_tree && argc > 3)
-               of_flat_tree = (char *)simple_strtoul(argv[3], NULL, 16);
+       if (!of_flat_tree && argc > 1)
+               of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16);
 
        /* fixup the initrd now that we know where it should be */
        if (images->rd_start && images->rd_end && of_flat_tree)
index f32be52108212477507b51b163fbe0563a0e7874..114e146d9b3d0af8ccfe0c6b685d376a1bd6c099 100644 (file)
@@ -40,8 +40,8 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima
        if (images->ft_len)
                of_flat_tree = images->ft_addr;
 #endif
-       if (!of_flat_tree && argc > 3)
-               of_flat_tree = (char *)simple_strtoul(argv[3], NULL, 16);
+       if (!of_flat_tree && argc > 1)
+               of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16);
        if (of_flat_tree)
                initrd_end = (ulong)of_flat_tree;
 
index 2c5d9aea9969650d0be7a0e4883e5121c36691e7..7f716b85982f957896c5a13b9164f5069a8fc2e0 100644 (file)
@@ -63,8 +63,8 @@ int do_bootm_linux(int flag, int argc, char * const argv[],
 
        show_boot_progress(15);
 
-       if (!of_flat_tree && argc > 3)
-               of_flat_tree = (char *)simple_strtoul(argv[3], NULL, 16);
+       if (!of_flat_tree && argc > 1)
+               of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16);
 #ifdef DEBUG
        printf("## Transferring control to Linux (at address 0x%08lx) " \
                                "ramdisk 0x%08lx, FDT 0x%08lx...\n",
index 2318064a4786fbb31a408dba45c2ebd651f554ce..4669883a3caf54bd89cd5b089e3b055e39e3265c 100644 (file)
@@ -73,6 +73,7 @@ COBJS-$(CONFIG_P1014) += ddr-gen3.o
 COBJS-$(CONFIG_P1020)  += ddr-gen3.o
 COBJS-$(CONFIG_P1021)  += ddr-gen3.o
 COBJS-$(CONFIG_P1022)  += ddr-gen3.o
+COBJS-$(CONFIG_P1023)  += ddr-gen3.o
 COBJS-$(CONFIG_P1024)  += ddr-gen3.o
 COBJS-$(CONFIG_P1025)  += ddr-gen3.o
 COBJS-$(CONFIG_P2010)  += ddr-gen3.o
index 422782ca8f209e764dc9d9c9c103609dba593a1e..a7ed87769e4cfbf19ce766ba75e4d10062f9a1b2 100644 (file)
@@ -257,6 +257,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #endif
 #ifdef CONFIG_SYS_FSL_ERRATUM_USB14
        puts("Work-around for Erratum USB14 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006593
+       puts("Work-around for Erratum A006593 enabled\n");
 #endif
        return 0;
 }
index 6ce483e17ae46eb69a29101f676af2c9f7420fe4..fbee753903fde00b21e1562f9929c43f78855c09 100644 (file)
@@ -121,16 +121,16 @@ int checkcpu (void)
        switch(ver) {
        case PVR_VER_E500_V1:
        case PVR_VER_E500_V2:
-               puts("E500");
+               puts("e500");
                break;
        case PVR_VER_E500MC:
-               puts("E500MC");
+               puts("e500mc");
                break;
        case PVR_VER_E5500:
-               puts("E5500");
+               puts("e5500");
                break;
        case PVR_VER_E6500:
-               puts("E6500");
+               puts("e6500");
                break;
        default:
                puts("Unknown");
@@ -341,7 +341,7 @@ phys_size_t initdram(int board_type)
 #if defined(CONFIG_SPD_EEPROM) || defined(CONFIG_DDR_SPD)
        return fsl_ddr_sdram_size();
 #else
-       return CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
+       return (phys_size_t)CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
 #endif
 }
 #else /* CONFIG_SYS_RAMBOOT */
index 4067f053757a66cf21e2868ffd0808d40593153f..3c8f59cdb363ce151572bcd00a75d8b765cbcd4c 100644 (file)
@@ -172,6 +172,9 @@ static void enable_cpc(void)
 #ifdef CONFIG_SYS_FSL_ERRATUM_CPC_A003
                setbits_be32(&cpc->cpchdbcr0, CPC_HDBCR0_DATA_ECC_SCRUB_DIS);
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006593
+               setbits_be32(&cpc->cpchdbcr0, 1 << (31 - 21));
+#endif
 
                out_be32(&cpc->cpccsr0, CPC_CSR0_CE | CPC_CSR0_PE);
                /* Read back to sync write */
@@ -564,7 +567,7 @@ skip_l2:
 
 #ifdef CONFIG_SYS_SRIO
        srio_init();
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER 
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
        char *s = getenv("bootmaster");
        if (s) {
                if (!strcmp(s, "SRIO1")) {
index 234fde48465bfcedb2eefb22ff4625f2a9a64cd3..837c034be90e5fecf9bfc9946b18ace5c05e8cd0 100644 (file)
@@ -25,7 +25,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) && !defined(CONFIG_SYS_RAMBOOT)
+#ifdef CONFIG_A003399_NOR_WORKAROUND
 void setup_ifc(void)
 {
        struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR;
@@ -99,7 +99,7 @@ void cpu_init_early_f(void)
 #ifdef CONFIG_SYS_FSL_ERRATUM_P1010_A003549
        ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 #endif
-#if defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) && !defined(CONFIG_SYS_RAMBOOT)
+#ifdef CONFIG_A003399_NOR_WORKAROUND
        ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
        u32  *dst, *src;
        void (*setup_ifc_sram)(void);
@@ -138,7 +138,7 @@ void cpu_init_early_f(void)
  * Work Around for IFC Erratum A003399, issue will hit only when execution
  * from NOR Flash
  */
-#if defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) && !defined(CONFIG_SYS_RAMBOOT)
+#ifdef CONFIG_A003399_NOR_WORKAROUND
 #define SRAM_BASE_ADDR (0x00000000)
        /* TLB for SRAM */
        mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(9);
@@ -180,5 +180,9 @@ void cpu_init_early_f(void)
 
        invalidate_tlb(1);
 
+#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_NAND_SPL)
+       disable_tlb(CONFIG_SYS_PPC_E500_DEBUG_TLB);
+#endif
+
        init_tlbs();
 }
index 288f7b28603641470d2464d8bea4f9397dd6685f..bb95f3d5008ce1a355e19b97afc1f9f1706e1f86 100644 (file)
@@ -663,7 +663,7 @@ void ft_cpu_setup(void *blob, bd_t *bd)
 #ifdef CONFIG_FSL_CORENET
        do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-1.0",
                "clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
-       do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-2",
+       do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-2.0",
                "clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
        do_fixup_by_compat_u32(blob, "fsl,mpic",
                "clock-frequency", get_bus_freq(0)/2, 1);
index 6dadeb8cabc7d9fc3a3d9c133d63a47b959b0a07..ec96e81ed5ecf5c5c35b00e3dd5b8be485230724 100644 (file)
@@ -228,7 +228,7 @@ void fsl_serdes_init(void)
                break;
        }
 
-       if (srds1_io_sel > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
                return;
        }
@@ -237,7 +237,7 @@ void fsl_serdes_init(void)
                serdes1_prtcl_map |= (1 << lane_prtcl);
        }
 
-       if (srds2_io_sel > ARRAY_SIZE(serdes2_cfg_tbl)) {
+       if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
                printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
                return;
        }
index 7c490972a55f9388c0f4027d31dfd0b8ee8fccf4..3483366e6d08da1116c7f925d696ac6e90ab6339 100644 (file)
@@ -68,7 +68,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
@@ -77,7 +77,7 @@ void fsl_serdes_init(void)
                serdes1_prtcl_map |= (1 << lane_prtcl);
        }
 
-       if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index 76288cd568e648eeb9ea4f76fcb7022e9af779d3..c9eea15d3cd4a097602b419fb03302a926fdbfc7 100644 (file)
@@ -53,7 +53,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL] = %x\n", srds1_cfg);
 
-       if (srds1_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds1_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL] = %d\n", srds1_cfg);
                return ;
        }
index 258263739f2770045f3d49f6e178ffa8f0022e47..49a02906202def52cbfe4e7f5152f7ce7f5c8249 100644 (file)
@@ -53,7 +53,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index f480c2609d6b629ac4a8e1cc2a1003ef3582cea9..7af6aff25957ee94639d15cb325e6277ec0f9a1b 100644 (file)
@@ -62,7 +62,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index 2ff5d9a060afc74016eac18f6e7241974d179c3b..fcccb52b68281c97b9e86bfbd89f9db807cddcca 100644 (file)
@@ -57,7 +57,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index e8a0387ca0aab0ca08855938c692e9f606b36a26..1f7dba0d6f7a57b4882d563c90e9e453cf6dd031 100644 (file)
@@ -54,7 +54,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
@@ -63,7 +63,7 @@ void fsl_serdes_init(void)
                serdes1_prtcl_map |= (1 << lane_prtcl);
        }
 
-       if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index 1849c1642cf284d94187f8fe8021a67ba1e59058..d6d2696e0702a7cca22e35d80d1a9c559470a213 100644 (file)
@@ -73,7 +73,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index e4c9c2210054a9346efe9059b6a42cb745aca487..ed4992053c031cf1c82a4117f325d927a1a9887c 100644 (file)
@@ -93,7 +93,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
@@ -102,7 +102,7 @@ void fsl_serdes_init(void)
                serdes1_prtcl_map |= (1 << lane_prtcl);
        }
 
-       if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index c8ab5d6f339a7aea12d20571a646e867f0a730a4..0b4ae90c242707be12580c2123197faded35d25a 100644 (file)
@@ -41,7 +41,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index 389ff6bd2804bebb916b0b0b5b000965b936e412..01af3337063b6e660f156c36529c89a24d3b9967 100644 (file)
@@ -61,7 +61,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index eec4ffe516ad8acdf189524649b5009e4ccf9922..87335c9444d7766c068f8e5c1d2771ca7dd3f94f 100644 (file)
@@ -90,7 +90,7 @@ int is_serdes_prtcl_valid(u32 prtcl)
        u32 svr = get_svr();
        u32 ver = SVR_SOC_VER(svr);
 
-       if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+       if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
                return 0;
 
        /* P2040[e] does not support XAUI */
index fba9ff245fdb5755a1edbd71bedba498acb2825e..a36dcd542697080df9871ccdc5116e6949f56888 100644 (file)
@@ -139,7 +139,7 @@ enum srds_prtcl serdes_get_prtcl(int cfg, int lane)
 int is_serdes_prtcl_valid(u32 prtcl) {
        int i;
 
-       if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+       if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
                return 0;
 
        for (i = 0; i < SRDS_MAX_LANES; i++) {
index 87bd7952930d87ed93e5c555e16c4bae5c188365..94ec445037248fa438b7e59ae2088580244221ad 100644 (file)
@@ -86,7 +86,7 @@ enum srds_prtcl serdes_get_prtcl(int cfg, int lane)
 int is_serdes_prtcl_valid(u32 prtcl) {
        int i;
 
-       if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+       if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
                return 0;
 
        for (i = 0; i < SRDS_MAX_LANES; i++) {
index fba9ff245fdb5755a1edbd71bedba498acb2825e..a36dcd542697080df9871ccdc5116e6949f56888 100644 (file)
@@ -139,7 +139,7 @@ enum srds_prtcl serdes_get_prtcl(int cfg, int lane)
 int is_serdes_prtcl_valid(u32 prtcl) {
        int i;
 
-       if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+       if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
                return 0;
 
        for (i = 0; i < SRDS_MAX_LANES; i++) {
index 890b88e4e337233e575923de2f8c2f98f57e1463..d646e8561c46583dceb8c5c86c8b9c969159ee14 100644 (file)
@@ -105,7 +105,7 @@ int is_serdes_prtcl_valid(u32 prtcl)
 {
        int i;
 
-       if (prtcl > ARRAY_SIZE(serdes_cfg_tbl))
+       if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
                return 0;
 
        for (i = 0; i < SRDS_MAX_LANES; i++) {
index 4f0480b768960e9d0913bd1ae6fba8d36e920476..2657982a45b9917a32adcc2a87fb8516a3464000 100644 (file)
@@ -1795,7 +1795,7 @@ clear_bss:
        stw     r0,0(r3)
        addi    r3,r3,4
        cmplw   0,r3,r4
-       bne     5b
+       blt     5b
 6:
 
        mr      r3,r9           /* Init Data pointer            */
index 8261e034767d77a023a406b5b76720832b0cf0ab..19add9f96c0a7f6705e0bb363e43330a40d59ce3 100644 (file)
@@ -81,7 +81,7 @@ int is_serdes_prtcl_valid(int serdes, u32 prtcl)
 {
        int i;
 
-       if (prtcl > (ARRAY_SIZE(serdes_cfg_tbl[serdes])))
+       if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl[serdes]))
                return 0;
 
        for (i = 0; i < SRDS_MAX_LANES; i++) {
index f2b7bffdabefeda1d6862df45aae7c6f3c6918e6..20284ed5a59569789242eee37759e02ede6281d5 100644 (file)
 #include "config.h"    /* CONFIG_BOARDDIR */
 
 OUTPUT_ARCH(powerpc)
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+PHDRS
+{
+       text PT_LOAD;
+       bss PT_LOAD;
+}
+#endif
 SECTIONS
 {
        . = CONFIG_SPL_TEXT_BASE;
@@ -60,7 +67,7 @@ SECTIONS
 #if defined(CONFIG_FSL_IFC) /* Restrict bootpg at 4K boundry for IFC */
        .bootpg ADDR(.text) + 0x1000 :
        {
-               start.o (.bootpg)
+               arch/powerpc/cpu/mpc85xx/start.o (.bootpg)
        }
 #define RESET_VECTOR_OFFSET 0x1ffc /* IFC has 8K sram */
 #elif defined(CONFIG_FSL_ELBC)
@@ -68,9 +75,16 @@ SECTIONS
 #else
 #error unknown NAND controller
 #endif
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+       .bootpg ADDR(.text) - 0x1000 :
+       {
+               KEEP(*(.bootpg))
+       } :text = 0xffff
+#else
        .resetvec ADDR(.text) + RESET_VECTOR_OFFSET : {
                KEEP(*(.resetvec))
        } = 0xffff
+#endif
 
        /*
         * Make sure that the bss segment isn't linked at 0x0, otherwise its
@@ -78,10 +92,12 @@ SECTIONS
         */
        . |= 0x10;
 
+       . = ALIGN(4);
        __bss_start = .;
        .bss : {
                *(.sbss*)
                *(.bss*)
        }
+       . = ALIGN(4);
        __bss_end = .;
 }
index 0503dce5ae4345edf6221b8d169720c05c5231e3..2643563d4dadcce2f5b9f08f4a7864ba10896ea4 100644 (file)
@@ -95,6 +95,13 @@ SECTIONS
   . = ALIGN(256);
   __init_end = .;
 
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+  .bootpg ADDR(.text) - 0x1000 :
+  {
+    KEEP(arch/powerpc/cpu/mpc85xx/start.o (.bootpg))
+  } :text = 0xffff
+  . = ADDR(.text) + 0x80000;
+#else
   .bootpg RESET_VECTOR_ADDRESS - 0xffc :
   {
     arch/powerpc/cpu/mpc85xx/start.o   (.bootpg)
@@ -116,6 +123,7 @@ SECTIONS
    */
 #if (RESET_VECTOR_ADDRESS == 0xfffffffc)
   . |= 0x10;
+#endif
 #endif
 
   __bss_start = .;
index c553415b555a5a122b5f4966d97c9915ad2efc1e..5ed3eb24f2393df830dacfdfcbc28391b988ee1b 100644 (file)
@@ -78,7 +78,7 @@ checkcpu(void)
        major = PVR_E600_MAJ(pvr);
        minor = PVR_E600_MIN(pvr);
 
-       printf("E600 Core %d", (msscr0 & 0x20) ? 1 : 0 );
+       printf("e600 Core %d", (msscr0 & 0x20) ? 1 : 0);
        if (gur->pordevsr & MPC86xx_PORDEVSR_CORE1TE)
                puts("\n    Core1Translation Enabled");
        debug(" (MSSCR0=%x, PORDEVSR=%x)", msscr0, gur->pordevsr);
index 0dc1975bf9b271445d08cc56797a9016f93ce269..0342e34654e2a5cabb580d686e623f693b588e5a 100644 (file)
@@ -64,7 +64,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
@@ -73,7 +73,7 @@ void fsl_serdes_init(void)
                serdes1_prtcl_map |= (1 << lane_prtcl);
        }
 
-       if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index 3ae9069f1b81418b96821b936c8459b6e5c27f28..21c5ddbfacc983aaef7615f6003020ac50b3e2c0 100644 (file)
@@ -73,7 +73,7 @@ void fsl_serdes_init(void)
 
        debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
 
-       if (srds_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
@@ -82,7 +82,7 @@ void fsl_serdes_init(void)
                serdes1_prtcl_map |= (1 << lane_prtcl);
        }
 
-       if (srds_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) {
+       if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
                printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
                return;
        }
index 56b319f5d4bfe28ec7c10709d0b2a44bd1ffa432..4e8a4415f5c0f4b0c00c6d30b8f0e9f61c4833d8 100644 (file)
@@ -26,7 +26,7 @@ void print_ifc_regs(void)
        int i, j;
 
        printf("IFC Controller Registers\n");
-       for (i = 0; i < FSL_IFC_BANK_COUNT; i++) {
+       for (i = 0; i < CONFIG_SYS_FSL_IFC_BANK_COUNT; i++) {
                printf("CSPR%d:0x%08X\tAMASK%d:0x%08X\tCSOR%d:0x%08X\n",
                        i, get_ifc_cspr(i), i, get_ifc_amask(i),
                        i, get_ifc_csor(i));
@@ -43,7 +43,7 @@ void init_early_memctl_regs(void)
        set_ifc_ftim(IFC_CS0, IFC_FTIM2, CONFIG_SYS_CS0_FTIM2);
        set_ifc_ftim(IFC_CS0, IFC_FTIM3, CONFIG_SYS_CS0_FTIM3);
 
-#if !defined(CONFIG_SYS_FSL_ERRATUM_IFC_A003399) || defined(CONFIG_SYS_RAMBOOT)
+#ifndef CONFIG_A003399_NOR_WORKAROUND
 #ifdef CONFIG_SYS_CSPR0_EXT
        set_ifc_cspr_ext(IFC_CS0, CONFIG_SYS_CSPR0_EXT);
 #endif
@@ -94,4 +94,60 @@ void init_early_memctl_regs(void)
        set_ifc_amask(IFC_CS3, CONFIG_SYS_AMASK3);
        set_ifc_csor(IFC_CS3, CONFIG_SYS_CSOR3);
 #endif
+
+#ifdef CONFIG_SYS_CSPR4_EXT
+       set_ifc_cspr_ext(IFC_CS4, CONFIG_SYS_CSPR4_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR4) && defined(CONFIG_SYS_CSOR4)
+       set_ifc_ftim(IFC_CS4, IFC_FTIM0, CONFIG_SYS_CS4_FTIM0);
+       set_ifc_ftim(IFC_CS4, IFC_FTIM1, CONFIG_SYS_CS4_FTIM1);
+       set_ifc_ftim(IFC_CS4, IFC_FTIM2, CONFIG_SYS_CS4_FTIM2);
+       set_ifc_ftim(IFC_CS4, IFC_FTIM3, CONFIG_SYS_CS4_FTIM3);
+
+       set_ifc_cspr(IFC_CS4, CONFIG_SYS_CSPR4);
+       set_ifc_amask(IFC_CS4, CONFIG_SYS_AMASK4);
+       set_ifc_csor(IFC_CS4, CONFIG_SYS_CSOR4);
+#endif
+
+#ifdef CONFIG_SYS_CSPR5_EXT
+       set_ifc_cspr_ext(IFC_CS5, CONFIG_SYS_CSPR5_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR5) && defined(CONFIG_SYS_CSOR5)
+       set_ifc_ftim(IFC_CS5, IFC_FTIM0, CONFIG_SYS_CS5_FTIM0);
+       set_ifc_ftim(IFC_CS5, IFC_FTIM1, CONFIG_SYS_CS5_FTIM1);
+       set_ifc_ftim(IFC_CS5, IFC_FTIM2, CONFIG_SYS_CS5_FTIM2);
+       set_ifc_ftim(IFC_CS5, IFC_FTIM3, CONFIG_SYS_CS5_FTIM3);
+
+       set_ifc_cspr(IFC_CS5, CONFIG_SYS_CSPR5);
+       set_ifc_amask(IFC_CS5, CONFIG_SYS_AMASK5);
+       set_ifc_csor(IFC_CS5, CONFIG_SYS_CSOR5);
+#endif
+
+#ifdef CONFIG_SYS_CSPR6_EXT
+       set_ifc_cspr_ext(IFC_CS6, CONFIG_SYS_CSPR6_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR6) && defined(CONFIG_SYS_CSOR6)
+       set_ifc_ftim(IFC_CS6, IFC_FTIM0, CONFIG_SYS_CS6_FTIM0);
+       set_ifc_ftim(IFC_CS6, IFC_FTIM1, CONFIG_SYS_CS6_FTIM1);
+       set_ifc_ftim(IFC_CS6, IFC_FTIM2, CONFIG_SYS_CS6_FTIM2);
+       set_ifc_ftim(IFC_CS6, IFC_FTIM3, CONFIG_SYS_CS6_FTIM3);
+
+       set_ifc_cspr(IFC_CS6, CONFIG_SYS_CSPR6);
+       set_ifc_amask(IFC_CS6, CONFIG_SYS_AMASK6);
+       set_ifc_csor(IFC_CS6, CONFIG_SYS_CSOR6);
+#endif
+
+#ifdef CONFIG_SYS_CSPR7_EXT
+       set_ifc_cspr_ext(IFC_CS7, CONFIG_SYS_CSPR7_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR7) && defined(CONFIG_SYS_CSOR7)
+       set_ifc_ftim(IFC_CS7, IFC_FTIM0, CONFIG_SYS_CS7_FTIM0);
+       set_ifc_ftim(IFC_CS7, IFC_FTIM1, CONFIG_SYS_CS7_FTIM1);
+       set_ifc_ftim(IFC_CS7, IFC_FTIM2, CONFIG_SYS_CS7_FTIM2);
+       set_ifc_ftim(IFC_CS7, IFC_FTIM3, CONFIG_SYS_CS7_FTIM3);
+
+       set_ifc_cspr(IFC_CS7, CONFIG_SYS_CSPR7);
+       set_ifc_amask(IFC_CS7, CONFIG_SYS_AMASK7);
+       set_ifc_csor(IFC_CS7, CONFIG_SYS_CSOR7);
+#endif
 }
index 6e6f7dcc3fd927a96383b6b457620f82d1d49296..90d1065deb23eb591703226952436d9e09e7824d 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/fsl_srio.h>
 #include <asm/errno.h>
 
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 #define SRIO_PORT_ACCEPT_ALL 0x10000001
 #define SRIO_IB_ATMU_AR 0x80f55000
 #define SRIO_OB_ATMU_AR_MAINT 0x80077000
@@ -299,7 +299,7 @@ void srio_init(void)
        }
 }
 
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 void srio_boot_master(int port)
 {
        struct ccsr_rio *srio = (void *)CONFIG_SYS_FSL_SRIO_ADDR;
index 1009a31b33954693fc2de55a5636dee22f9ea2a1..1d46b1423012a242a6f6752390207f06c8e36a82 100644 (file)
 #define CONFIG_SYS_FSL_SEC_COMPAT      4
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_NUM_DDR_CONTROLLERS     1
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT  4
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_SYS_FSL_PCIE_COMPAT     "fsl,qoriq-pcie-v2.2"
 #define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
-#define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS  2
 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
-#define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS  2
 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
 #define CONFIG_SYS_P4080_ERRATUM_SERDES_A005
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
-#define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS  2
 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
 #define CONFIG_SYS_FSL_ERRATUM_USB14
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
-#define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS  2
 #define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
 #define CONFIG_TSECV2
 #define CONFIG_SYS_FSL_SEC_COMPAT      4
 #define CONFIG_NUM_DDR_CONTROLLERS     1
+#define CONFIG_SYS_FSL_DSP_M2_RAM_ADDR 0xb0000000
+#define CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT     0xff600000
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT  3
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_NAND_FSL_IFC
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_TSECV2
 #define CONFIG_SYS_FSL_SEC_COMPAT      4
 #define CONFIG_NUM_DDR_CONTROLLERS     2
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT  3
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_NAND_FSL_IFC
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_SYS_FSL_SEC_COMPAT      4
 #define CONFIG_SYS_NUM_FMAN            2
 #define CONFIG_SYS_FSL_DDR_VER         FSL_DDR_VER_4_7
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT  8
 #define CONFIG_SYS_FMAN_V3
 #define CONFIG_SYS_FM_MURAM_SIZE       0x60000
 #define CONFIG_SYS_FSL_TBCLK_DIV       16
 #define CONFIG_SYS_FSL_ERRATUM_A004468
 #define CONFIG_SYS_FSL_ERRATUM_A_004934
 #define CONFIG_SYS_FSL_ERRATUM_A005871
+#define CONFIG_SYS_FSL_ERRATUM_A006593
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xfe000000
 #define CONFIG_SYS_FSL_PCI_VER_3_X
 
 #define CONFIG_SYS_FSL_SEC_COMPAT      4
 #define CONFIG_SYS_NUM_FMAN            1
 #define CONFIG_SYS_FSL_DDR_VER         FSL_DDR_VER_4_7
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT  4
 #define CONFIG_SYS_FMAN_V3
 #define CONFIG_SYS_FM_MURAM_SIZE       0x60000
 #define CONFIG_SYS_FSL_TBCLK_DIV       16
 #define CONFIG_SYS_FSL_USB1_PHY_ENABLE
 #define CONFIG_SYS_FSL_ERRATUM_A_004934
 #define CONFIG_SYS_FSL_ERRATUM_A005871
+#define CONFIG_SYS_FSL_ERRATUM_A006593
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xfe000000
 
 #ifdef CONFIG_PPC_B4860
index ba41b73cc0389b149e4c13fdc1d176a31088a9c1..3baf4ccbae4577ecd16924059d37e3cd1c9a7f08 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef __ASM_PPC_FSL_IFC_H
 #define __ASM_PPC_FSL_IFC_H
 
+#ifdef CONFIG_FSL_IFC
 #include <config.h>
 #include <common.h>
 
@@ -798,13 +799,15 @@ extern void init_early_memctl_regs(void);
 #define set_ifc_ftim(i, j, v) \
                        (out_be32(&(IFC_BASE_ADDR)->ftim_cs[i].ftim[j], v))
 
-#define FSL_IFC_BANK_COUNT     4
-
 enum ifc_chip_sel {
        IFC_CS0,
        IFC_CS1,
        IFC_CS2,
        IFC_CS3,
+       IFC_CS4,
+       IFC_CS5,
+       IFC_CS6,
+       IFC_CS7,
 };
 
 enum ifc_ftims {
@@ -907,6 +910,49 @@ struct fsl_ifc_gpcm {
        u32 res4[0x1F3];
 };
 
+#ifdef CONFIG_SYS_FSL_IFC_BANK_COUNT
+#if (CONFIG_SYS_FSL_IFC_BANK_COUNT <= 8)
+#define IFC_CSPR_REG_LEN       148
+#define IFC_AMASK_REG_LEN      144
+#define IFC_CSOR_REG_LEN       144
+#define IFC_FTIM_REG_LEN       576
+
+#define IFC_CSPR_USED_LEN      sizeof(struct fsl_ifc_cspr) * \
+                                       CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_AMASK_USED_LEN     sizeof(struct fsl_ifc_amask) * \
+                                       CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_CSOR_USED_LEN      sizeof(struct fsl_ifc_csor) * \
+                                       CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_FTIM_USED_LEN      sizeof(struct fsl_ifc_ftim) * \
+                                       CONFIG_SYS_FSL_IFC_BANK_COUNT
+#else
+#error IFC BANK count not vaild
+#endif
+#else
+#error IFC BANK count not defined
+#endif
+
+struct fsl_ifc_cspr {
+       u32 cspr_ext;
+       u32 cspr;
+       u32 res;
+};
+
+struct fsl_ifc_amask {
+       u32 amask;
+       u32 res[0x2];
+};
+
+struct fsl_ifc_csor {
+       u32 csor;
+       u32 csor_ext;
+       u32 res;
+};
+
+struct fsl_ifc_ftim {
+       u32 ftim[4];
+       u32 res[0x8];
+};
 
 /*
  * IFC Controller Registers
@@ -914,44 +960,30 @@ struct fsl_ifc_gpcm {
 struct fsl_ifc {
        u32 ifc_rev;
        u32 res1[0x2];
-       struct {
-               u32 cspr_ext;
-               u32 cspr;
-               u32 res2;
-       } cspr_cs[FSL_IFC_BANK_COUNT];
-       u32 res3[0x19];
-       struct {
-               u32 amask;
-               u32 res4[0x2];
-       } amask_cs[FSL_IFC_BANK_COUNT];
-       u32 res5[0x17];
-       struct {
-               u32 csor_ext;
-               u32 csor;
-               u32 res6;
-       } csor_cs[FSL_IFC_BANK_COUNT];
-       u32 res7[0x19];
-       struct {
-               u32 ftim[4];
-               u32 res8[0x8];
-       } ftim_cs[FSL_IFC_BANK_COUNT];
-       u32 res9[0x60];
+       struct fsl_ifc_cspr cspr_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+       u8 res2[IFC_CSPR_REG_LEN - IFC_CSPR_USED_LEN];
+       struct fsl_ifc_amask amask_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+       u8 res3[IFC_AMASK_REG_LEN - IFC_AMASK_USED_LEN];
+       struct fsl_ifc_csor csor_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+       u8 res4[IFC_CSOR_REG_LEN - IFC_CSOR_USED_LEN];
+       struct fsl_ifc_ftim ftim_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+       u8 res5[IFC_FTIM_REG_LEN - IFC_FTIM_USED_LEN];
        u32 rb_stat;
-       u32 res10[0x2];
+       u32 res6[0x2];
        u32 ifc_gcr;
-       u32 res11[0x2];
+       u32 res7[0x2];
        u32 cm_evter_stat;
-       u32 res12[0x2];
+       u32 res8[0x2];
        u32 cm_evter_en;
-       u32 res13[0x2];
+       u32 res9[0x2];
        u32 cm_evter_intr_en;
-       u32 res14[0x2];
+       u32 res10[0x2];
        u32 cm_erattr0;
        u32 cm_erattr1;
-       u32 res15[0x2];
+       u32 res11[0x2];
        u32 ifc_ccr;
        u32 ifc_csr;
-       u32 res16[0x2EB];
+       u32 res12[0x2EB];
        struct fsl_ifc_nand ifc_nand;
        struct fsl_ifc_nor ifc_nor;
        struct fsl_ifc_gpcm ifc_gpcm;
@@ -961,6 +993,7 @@ struct fsl_ifc {
 #undef CSPR_MSEL_NOR
 #define CSPR_MSEL_NOR  CSPR_MSEL_GPCM
 #endif
+#endif /* CONFIG_FSL_IFC */
 
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_PPC_FSL_IFC_H */
index 90b264d35e7292c505cc06a9a08e837639edeb7c..bea1636768d04ec12bba2d7f2a368c71a9d33618 100644 (file)
@@ -82,11 +82,16 @@ enum law_trgt_if {
 #ifndef CONFIG_MPC8641
        LAW_TRGT_IF_PCIE_1 = 0x02,
 #endif
+#if defined(CONFIG_BSC9131)
+       LAW_TRGT_IF_OCN_DSP = 0x03,
+#else
 #if !defined(CONFIG_MPC8572) && !defined(CONFIG_P2020)
        LAW_TRGT_IF_PCIE_3 = 0x03,
+#endif
 #endif
        LAW_TRGT_IF_LBC = 0x04,
        LAW_TRGT_IF_CCSR = 0x08,
+       LAW_TRGT_IF_DSP_CCSR = 0x09,
        LAW_TRGT_IF_DDR_INTRLV = 0x0b,
        LAW_TRGT_IF_RIO = 0x0c,
        LAW_TRGT_IF_RIO_2 = 0x0d,
index 4052037f56f92d5851c52e6f097f971a28ff31b7..db70d048f5bed5d6f7501b4b1ed766d1eae67d44 100644 (file)
@@ -1839,11 +1839,13 @@ typedef struct ccsr_gur {
 #define FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT  11
 #define FSL_CORENET2_RCWSR4_SRDS4_PRTCL                0x000000f8
 #define FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT  3
+#define FSL_CORENET_RCWSR6_BOOT_LOC    0x0f800000
 #elif defined(CONFIG_PPC_B4860) || defined(CONFIG_PPC_B4420)
 #define FSL_CORENET2_RCWSR4_SRDS1_PRTCL        0xfe000000
 #define FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT  25
 #define FSL_CORENET2_RCWSR4_SRDS2_PRTCL        0x00ff0000
 #define FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT  16
+#define FSL_CORENET_RCWSR6_BOOT_LOC    0x0f800000
 #elif defined(CONFIG_PPC_T1040)
 #define FSL_CORENET2_RCWSR4_SRDS1_PRTCL        0xff000000
 #define FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT  24
@@ -2160,7 +2162,7 @@ typedef struct ccsr_gur {
        u32     porbmsr;        /* POR boot mode status */
 #define MPC85xx_PORBMSR_HA             0x00070000
 #define MPC85xx_PORBMSR_HA_SHIFT       16
-#define MPC85XX_PORBMSR_ROMLOC_SHIFT   24
+#define MPC85xx_PORBMSR_ROMLOC_SHIFT   24
 #define PORBMSR_ROMLOC_SPI     0x6
 #define PORBMSR_ROMLOC_SDHC    0x7
 #define PORBMSR_ROMLOC_NAND_2K 0x9
index dd6c98cdb48990c6de15cdfbeef02639ab33ecfd..d4ad323fe9051038c72907ef441822a96d45c8e1 100644 (file)
@@ -256,11 +256,6 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima
                return 0;
        }
 
-       if (flag & BOOTM_STATE_OS_GO) {
-               boot_jump_linux(images);
-               return 0;
-       }
-
        boot_prep_linux(images);
        ret = boot_body_linux(images);
        if (ret)
index dd8d495e3fc039fd3cea297b383f34103239de8a..e9385de2a6f63c9b045714d712487efe3f38cb90 100644 (file)
@@ -37,7 +37,7 @@ void __udelay(unsigned long usec)
        os_usleep(usec);
 }
 
-unsigned long timer_get_us(void)
+unsigned long __attribute__((no_instrument_function)) timer_get_us(void)
 {
        return os_get_nsec() / 1000;
 }
index d07540776cc6a8d32fb58a18e752c738c761a06d..541e450bf602d684f22c0876b531e5a6fc586be4 100644 (file)
@@ -152,7 +152,7 @@ void os_usleep(unsigned long usec)
        usleep(usec);
 }
 
-u64 os_get_nsec(void)
+u64 __attribute__((no_instrument_function)) os_get_nsec(void)
 {
 #if defined(CLOCK_MONOTONIC) && defined(_POSIX_MONOTONIC_CLOCK)
        struct timespec tp;
index 4fdb08090a02bebda2851f4c147994043fe72d7a..9a2056a70f6a4c72a016ed564d4fa613211272de 100644 (file)
@@ -40,7 +40,7 @@ struct arch_global_data {
 #include <asm-generic/global_data.h>
 
 #ifndef __ASSEMBLY__
-static inline gd_t *get_fs_gd_ptr(void)
+static inline __attribute__((no_instrument_function)) gd_t *get_fs_gd_ptr(void)
 {
        gd_t *gd_ptr;
 
index 6030633d102da11ca649e4f212604cbbc5a24a36..b459a63ee6e1209f909b68c18195acbc2d79f228 100644 (file)
@@ -85,7 +85,8 @@ static inline unsigned long long native_read_tscp(unsigned int *aux)
 #define EAX_EDX_RET(val, low, high)    "=A" (val)
 #endif
 
-static inline unsigned long long native_read_msr(unsigned int msr)
+static inline __attribute__((no_instrument_function))
+       unsigned long long native_read_msr(unsigned int msr)
 {
        DECLARE_ARGS(val, low, high);
 
index 22e093427fdf5c9426dbb002c668da27c3ca33a4..709dc8400d64dd6c6f5507f46386e093decb411f 100644 (file)
@@ -64,7 +64,7 @@ void  board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
 void   board_init_f_r(void) __attribute__ ((noreturn));
 
 /* Read the time stamp counter */
-static inline uint64_t rdtsc(void)
+static inline __attribute__((no_instrument_function)) uint64_t rdtsc(void)
 {
        uint32_t high, low;
        __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
index 2520228b4caee000f580e461dcb9294d375b7cac..0d3250cfa304da27c10dfb12694c9331b1f11d52 100644 (file)
@@ -63,6 +63,8 @@ int do_bootm_linux(int flag, int argc, char * const argv[],
                }
 #if defined(CONFIG_FIT)
        } else if (images->fit_uname_os) {
+               int ret;
+
                ret = fit_image_get_data(images->fit_hdr_os,
                                        images->fit_noffset_os, &data, &len);
                if (ret) {
index 4043431ecaa904e0ffc5606db762c2206c3f7dcb..497ad75b7a45fca5c9b7e81c855a986e82dba85b 100644 (file)
@@ -28,7 +28,9 @@
 #define WRAP_LIBGCC_CALL(type, name) \
        type __normal_##name(type a, type b) __attribute__((regparm(0))); \
        type __wrap_##name(type a, type b); \
-       type __wrap_##name(type a, type b) { return __normal_##name(a, b); }
+       type __attribute__((no_instrument_function)) \
+               __wrap_##name(type a, type b) \
+                { return __normal_##name(a, b); }
 
 WRAP_LIBGCC_CALL(long long, __divdi3)
 WRAP_LIBGCC_CALL(unsigned long long, __udivdi3)
index c509801f9e8dee6539ac335e870748eb165aa62c..06889737d1a21dece02a26ec766ed05bd9fed3c4 100644 (file)
@@ -37,7 +37,7 @@ void timer_set_base(u64 base)
  * restart. This yields a free running counter guaranteed to take almost 6
  * years to wrap around even at 100GHz clock rate.
  */
-u64 get_ticks(void)
+u64 __attribute__((no_instrument_function)) get_ticks(void)
 {
        u64 now_tick = rdtsc();
 
@@ -50,7 +50,7 @@ u64 get_ticks(void)
 #define PLATFORM_INFO_MSR 0xce
 
 /* Get the speed of the TSC timer in MHz */
-unsigned long get_tbclk_mhz(void)
+unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
 {
        u32 ratio;
        u64 platform_info = native_read_msr(PLATFORM_INFO_MSR);
@@ -75,7 +75,7 @@ ulong get_timer(ulong base)
        return get_ms_timer() - base;
 }
 
-ulong timer_get_us(void)
+ulong __attribute__((no_instrument_function)) timer_get_us(void)
 {
        return get_ticks() / get_tbclk_mhz();
 }
diff --git a/board/LaCie/common/cpld-gpio-bus.c b/board/LaCie/common/cpld-gpio-bus.c
new file mode 100644 (file)
index 0000000..fb9bf8d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * cpld-gpio-bus.c: provides support for the CPLD GPIO bus found on some LaCie
+ * boards (as the 2Big/5Big Network v2 and the 2Big NAS). This parallel GPIO
+ * bus exposes two registers (address and data). Each of this register is made
+ * up of several dedicated GPIOs. An extra GPIO is used to notify the CPLD that
+ * the registers have been updated.
+ *
+ * Mostly this bus is used to configure the LEDs on LaCie boards.
+ *
+ * Copyright (C) 2013 Simon Guinot <simon.guinot@sequanux.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <asm/arch/gpio.h>
+#include "cpld-gpio-bus.h"
+
+static void cpld_gpio_bus_set_addr(struct cpld_gpio_bus *bus, unsigned addr)
+{
+       int pin;
+
+       for (pin = 0; pin < bus->num_addr; pin++)
+               kw_gpio_set_value(bus->addr[pin], (addr >> pin) & 1);
+}
+
+static void cpld_gpio_bus_set_data(struct cpld_gpio_bus *bus, unsigned data)
+{
+       int pin;
+
+       for (pin = 0; pin < bus->num_data; pin++)
+               kw_gpio_set_value(bus->data[pin], (data >> pin) & 1);
+}
+
+static void cpld_gpio_bus_enable_select(struct cpld_gpio_bus *bus)
+{
+       /* The transfer is enabled on the raising edge. */
+       kw_gpio_set_value(bus->enable, 0);
+       kw_gpio_set_value(bus->enable, 1);
+}
+
+void cpld_gpio_bus_write(struct cpld_gpio_bus *bus,
+                        unsigned addr, unsigned value)
+{
+       cpld_gpio_bus_set_addr(bus, addr);
+       cpld_gpio_bus_set_data(bus, value);
+       cpld_gpio_bus_enable_select(bus);
+}
diff --git a/board/LaCie/common/cpld-gpio-bus.h b/board/LaCie/common/cpld-gpio-bus.h
new file mode 100644 (file)
index 0000000..e9e9b96
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Simon Guinot <simon.guinot@sequanux.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _LACIE_CPLD_GPI0_BUS_H
+#define _LACIE_CPLD_GPI0_BUS_H
+
+struct cpld_gpio_bus {
+       unsigned *addr;
+       unsigned num_addr;
+       unsigned *data;
+       unsigned num_data;
+       unsigned enable;
+};
+
+void cpld_gpio_bus_write(struct cpld_gpio_bus *cpld_gpio_bus,
+                        unsigned addr, unsigned value);
+
+#endif /* _LACIE_CPLD_GPI0_BUS_H */
index fbae48ef24e2e83cc6100bb5715d325079dc776b..9a6dfb619b3dab3f0645bd56fa8c34a279c74bf4 100644 (file)
@@ -28,6 +28,9 @@ endif
 LIB    = $(obj)lib$(BOARD).o
 
 COBJS  := $(BOARD).o ../common/common.o
+ifneq ($(and $(CONFIG_KIRKWOOD_GPIO),$(CONFIG_NET2BIG_V2)),)
+COBJS  += ../common/cpld-gpio-bus.o
+endif
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS))
index e524f3511d2691b0ccaef26840c85b7885e01005..b133f7cb3bde856143f133f9d06de4215d2d0ef7 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <i2c.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/kirkwood.h>
 #include <asm/arch/mpp.h>
@@ -29,6 +30,7 @@
 
 #include "net2big_v2.h"
 #include "../common/common.h"
+#include "../common/cpld-gpio-bus.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -60,18 +62,18 @@ int board_early_init_f(void)
                MPP24_GPIO,             /* USB mode select */
                MPP26_GPIO,             /* USB device vbus */
                MPP28_GPIO,             /* USB enable host vbus */
-               MPP29_GPIO,             /* GPIO extension ALE */
+               MPP29_GPIO,             /* CPLD GPIO bus ALE */
                MPP34_GPIO,             /* Rear Push button 0=on 1=off */
                MPP35_GPIO,             /* Inhibit switch power-off */
                MPP36_GPIO,             /* SATA HDD1 presence */
                MPP37_GPIO,             /* SATA HDD2 presence */
                MPP40_GPIO,             /* eSATA presence */
-               MPP44_GPIO,             /* GPIO extension (data 0) */
-               MPP45_GPIO,             /* GPIO extension (data 1) */
-               MPP46_GPIO,             /* GPIO extension (data 2) */
-               MPP47_GPIO,             /* GPIO extension (addr 0) */
-               MPP48_GPIO,             /* GPIO extension (addr 1) */
-               MPP49_GPIO,             /* GPIO extension (addr 2) */
+               MPP44_GPIO,             /* CPLD GPIO bus (data 0) */
+               MPP45_GPIO,             /* CPLD GPIO bus (data 1) */
+               MPP46_GPIO,             /* CPLD GPIO bus (data 2) */
+               MPP47_GPIO,             /* CPLD GPIO bus (addr 0) */
+               MPP48_GPIO,             /* CPLD GPIO bus (addr 1) */
+               MPP49_GPIO,             /* CPLD GPIO bus (addr 2) */
                0
        };
 
@@ -92,8 +94,142 @@ int board_init(void)
 }
 
 #if defined(CONFIG_MISC_INIT_R)
+
+#if defined(CONFIG_CMD_I2C) && defined(CONFIG_SYS_I2C_G762_ADDR)
+/*
+ * Start I2C fan (GMT G762 controller)
+ */
+static void init_fan(void)
+{
+       u8 data;
+
+       i2c_set_bus_num(0);
+
+       /* Enable open-loop and PWM modes */
+       data = 0x20;
+       if (i2c_write(CONFIG_SYS_I2C_G762_ADDR,
+                     G762_REG_FAN_CMD1, 1, &data, 1) != 0)
+               goto err;
+       data = 0;
+       if (i2c_write(CONFIG_SYS_I2C_G762_ADDR,
+                     G762_REG_SET_CNT, 1, &data, 1) != 0)
+               goto err;
+       /*
+        * RPM to PWM (set_out register) fan speed conversion array:
+        * 0    0x00
+        * 1500 0x04
+        * 2800 0x08
+        * 3400 0x0C
+        * 3700 0x10
+        * 4400 0x20
+        * 4700 0x30
+        * 4800 0x50
+        * 5200 0x80
+        * 5400 0xC0
+        * 5500 0xFF
+        *
+        * Start fan at low speed (2800 RPM):
+        */
+       data = 0x08;
+       if (i2c_write(CONFIG_SYS_I2C_G762_ADDR,
+                     G762_REG_SET_OUT, 1, &data, 1) != 0)
+               goto err;
+
+       return;
+err:
+       printf("Error: failed to start I2C fan @%02x\n",
+              CONFIG_SYS_I2C_G762_ADDR);
+}
+#else
+static void init_fan(void) {}
+#endif /* CONFIG_CMD_I2C && CONFIG_SYS_I2C_G762_ADDR */
+
+#if defined(CONFIG_NET2BIG_V2) && defined(CONFIG_KIRKWOOD_GPIO)
+/*
+ * CPLD GPIO bus:
+ *
+ * - address register : bit [0-2] -> GPIO [47-49]
+ * - data register    : bit [0-2] -> GPIO [44-46]
+ * - enable register  : GPIO 29
+ */
+static unsigned cpld_gpio_bus_addr[] = { 47, 48, 49 };
+static unsigned cpld_gpio_bus_data[] = { 44, 45, 46 };
+
+static struct cpld_gpio_bus cpld_gpio_bus = {
+       .addr           = cpld_gpio_bus_addr,
+       .num_addr       = ARRAY_SIZE(cpld_gpio_bus_addr),
+       .data           = cpld_gpio_bus_data,
+       .num_data       = ARRAY_SIZE(cpld_gpio_bus_data),
+       .enable         = 29,
+};
+
+/*
+ * LEDs configuration:
+ *
+ * The LEDs are controlled by a CPLD and can be configured through
+ * the CPLD GPIO bus.
+ *
+ * Address register selection:
+ *
+ * addr | register
+ * ----------------------------
+ *   0  | front LED
+ *   1  | front LED brightness
+ *   2  | SATA LED brightness
+ *   3  | SATA0 LED
+ *   4  | SATA1 LED
+ *   5  | SATA2 LED
+ *   6  | SATA3 LED
+ *   7  | SATA4 LED
+ *
+ * Data register configuration:
+ *
+ * data | LED brightness
+ * -------------------------------------------------
+ *   0  | min (off)
+ *   -  | -
+ *   7  | max
+ *
+ * data | front LED mode
+ * -------------------------------------------------
+ *   0  | fix off
+ *   1  | fix blue on
+ *   2  | fix red on
+ *   3  | blink blue on=1 sec and blue off=1 sec
+ *   4  | blink red on=1 sec and red off=1 sec
+ *   5  | blink blue on=2.5 sec and red on=0.5 sec
+ *   6  | blink blue on=1 sec and red on=1 sec
+ *   7  | blink blue on=0.5 sec and blue off=2.5 sec
+ *
+ * data | SATA LED mode
+ * -------------------------------------------------
+ *   0  | fix off
+ *   1  | SATA activity blink
+ *   2  | fix red on
+ *   3  | blink blue on=1 sec and blue off=1 sec
+ *   4  | blink red on=1 sec and red off=1 sec
+ *   5  | blink blue on=2.5 sec and red on=0.5 sec
+ *   6  | blink blue on=1 sec and red on=1 sec
+ *   7  | fix blue on
+ */
+static void init_leds(void)
+{
+       /* Enable the front blue LED */
+       cpld_gpio_bus_write(&cpld_gpio_bus, 0, 1);
+       cpld_gpio_bus_write(&cpld_gpio_bus, 1, 3);
+
+       /* Configure SATA LEDs to blink in relation with the SATA activity */
+       cpld_gpio_bus_write(&cpld_gpio_bus, 3, 1);
+       cpld_gpio_bus_write(&cpld_gpio_bus, 4, 1);
+       cpld_gpio_bus_write(&cpld_gpio_bus, 2, 3);
+}
+#else
+static void init_leds(void) {}
+#endif /* CONFIG_NET2BIG_V2 && CONFIG_KIRKWOOD_GPIO */
+
 int misc_init_r(void)
 {
+       init_fan();
 #if defined(CONFIG_CMD_I2C) && defined(CONFIG_SYS_I2C_EEPROM_ADDR)
        if (!getenv("ethaddr")) {
                uchar mac[6];
@@ -101,9 +237,11 @@ int misc_init_r(void)
                        eth_setenv_enetaddr("ethaddr", mac);
        }
 #endif
+       init_leds();
+
        return 0;
 }
-#endif
+#endif /* CONFIG_MISC_INIT_R */
 
 #if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R)
 /* Configure and initialize PHY */
index f9778f4f0cd6b8e215e77463f57173bccfe829ed..83537d6b9ab90e6a457b45fac6b301727316bd4f 100644 (file)
@@ -32,4 +32,9 @@
 /* Buttons */
 #define NET2BIG_V2_GPIO_PUSH_BUTTON    34
 
+/* GMT G762 registers (I2C fan controller) */
+#define G762_REG_SET_CNT               0x00
+#define G762_REG_SET_OUT               0x03
+#define G762_REG_FAN_CMD1              0x04
+
 #endif /* NET2BIG_V2_H */
index ef4a25bc3cd952f163b91f6dd83079d4eb1e892a..74aec5fbcc0df477132d4185b04939d1b993c0de 100644 (file)
@@ -30,6 +30,7 @@ SECTIONS
 
        . = ALIGN (4);
        .text : {
+               *(.__image_copy_start)
                arch/arm/cpu/ixp/start.o(.text*)
                net/libnet.o(.text*)
                board/actux1/libactux1.o(.text*)
@@ -62,17 +63,23 @@ SECTIONS
 
        . = ALIGN (4);
 
-       __image_copy_end = .;
+       .image_copy_end :
+       {
+               *(.__image_copy_end)
+       }
+
+       .rel_dyn_start :
+       {
+               *(.__rel_dyn_start)
+       }
 
        .rel.dyn : {
-               __rel_dyn_start = .;
                *(.rel*)
-               __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
+       .rel_dyn_end :
+       {
+               *(.__rel_dyn_end)
        }
 
        _end = .;
@@ -96,6 +103,7 @@ SECTIONS
                KEEP(*(.__bss_end));
        }
 
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynamic*) }
        /DISCARD/ : { *(.plt*) }
index 00ad8b71cd065bc466611c9dfc9d145511d61952..c276501bd7b6dc057f4936b9f01ca0c175872a2b 100644 (file)
@@ -30,6 +30,7 @@ SECTIONS
 
        . = ALIGN (4);
        .text : {
+               *(.__image_copy_start)
                arch/arm/cpu/ixp/start.o(.text*)
                net/libnet.o(.text*)
                board/actux2/libactux2.o(.text*)
@@ -62,17 +63,23 @@ SECTIONS
 
        . = ALIGN (4);
 
-       __image_copy_end = .;
+       .image_copy_end :
+       {
+               *(.__image_copy_end)
+       }
+
+       .rel_dyn_start :
+       {
+               *(.__rel_dyn_start)
+       }
 
        .rel.dyn : {
-               __rel_dyn_start = .;
                *(.rel*)
-               __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
+       .rel_dyn_end :
+       {
+               *(.__rel_dyn_end)
        }
 
        _end = .;
@@ -96,6 +103,7 @@ SECTIONS
                KEEP(*(.__bss_end));
        }
 
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynamic*) }
        /DISCARD/ : { *(.plt*) }
index 44b990ee7ff5cb548aba07923e08e1a3ef6e77b4..5610644d79b15d968166c2eb76bca7055610637d 100644 (file)
@@ -30,6 +30,7 @@ SECTIONS
 
        . = ALIGN (4);
        .text : {
+               *(.__image_copy_start)
                arch/arm/cpu/ixp/start.o(.text*)
                net/libnet.o(.text*)
                board/actux3/libactux3.o(.text*)
@@ -62,17 +63,23 @@ SECTIONS
 
        . = ALIGN (4);
 
-       __image_copy_end = .;
+       .image_copy_end :
+       {
+               *(.__image_copy_end)
+       }
+
+       .rel_dyn_start :
+       {
+               *(.__rel_dyn_start)
+       }
 
        .rel.dyn : {
-               __rel_dyn_start = .;
                *(.rel*)
-               __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
+       .rel_dyn_end :
+       {
+               *(.__rel_dyn_end)
        }
 
        _end = .;
@@ -96,6 +103,7 @@ SECTIONS
                KEEP(*(.__bss_end));
        }
 
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynamic*) }
        /DISCARD/ : { *(.plt*) }
index 1daa1b3b9090a8d9414bb4ba65cbc87fb83ea542..39726854cd5beeb7043e46de0f4b2d1e5013c2a0 100644 (file)
@@ -54,11 +54,6 @@ SECTIONS
                __rel_dyn_end = .;
        } >.sram
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
-       } >.sram
-
        .bss :
        {
                . = ALIGN(4);
index 8752794c8435f2e242a50966b9778fdc54a3d889..3013a42a2ecf2123d0f8e963a342fdd8524d68c0 100644 (file)
@@ -33,6 +33,7 @@
 #include <lcd.h>
 #include <atmel_hlcdc.h>
 #include <atmel_mci.h>
+#include <netdev.h>
 
 #ifdef CONFIG_LCD_INFO
 #include <nand.h>
@@ -190,6 +191,30 @@ int board_mmc_init(bd_t *bd)
 }
 #endif
 
+#ifdef CONFIG_KS8851_MLL
+void at91sam9n12ek_ks8851_hw_init(void)
+{
+       struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
+
+       writel(AT91_SMC_SETUP_NWE(2) | AT91_SMC_SETUP_NCS_WR(0) |
+              AT91_SMC_SETUP_NRD(1) | AT91_SMC_SETUP_NCS_RD(0),
+              &smc->cs[2].setup);
+       writel(AT91_SMC_PULSE_NWE(7) | AT91_SMC_PULSE_NCS_WR(7) |
+              AT91_SMC_PULSE_NRD(7) | AT91_SMC_PULSE_NCS_RD(7),
+              &smc->cs[2].pulse);
+       writel(AT91_SMC_CYCLE_NWE(9) | AT91_SMC_CYCLE_NRD(9),
+              &smc->cs[2].cycle);
+       writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
+              AT91_SMC_MODE_EXNW_DISABLE |
+              AT91_SMC_MODE_BAT | AT91_SMC_MODE_DBW_16 |
+              AT91_SMC_MODE_TDF_CYCLE(1),
+              &smc->cs[2].mode);
+
+       /* Configure NCS2 PIN */
+       at91_set_b_periph(AT91_PIO_PORTD, 19, 0);
+}
+#endif
+
 int board_early_init_f(void)
 {
        /* Enable clocks for all PIOs */
@@ -217,9 +242,20 @@ int board_init(void)
        at91_lcd_hw_init();
 #endif
 
+#ifdef CONFIG_KS8851_MLL
+       at91sam9n12ek_ks8851_hw_init();
+#endif
+
        return 0;
 }
 
+#ifdef CONFIG_KS8851_MLL
+int board_eth_init(bd_t *bis)
+{
+       return ks8851_mll_initialize(0, CONFIG_KS8851_MLL_BASEADDR);
+}
+#endif
+
 int dram_init(void)
 {
        gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
index b1b8701811bf4324e77bfa15c46a8ee0be9e5010..6fa450909f5aae47ce3aab2e1964e9ee1904c609 100644 (file)
@@ -55,11 +55,6 @@ SECTIONS
                __rel_dyn_end = .;
        } >.sram
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
-       } >.sram
-
        .bss :
        {
                . = ALIGN(4);
index 596a9e08ea394ebeba09512a4501581b2901d9bf..b452f2078b5c80f3a1aaaf599cdc652b6481479d 100644 (file)
@@ -61,7 +61,6 @@ SECTIONS
        __image_copy_end = .;
        __rel_dyn_start = .;
        __rel_dyn_end = .;
-       __dynsym_start = .;
 
        __got_start = .;
        . = ALIGN(4);
index 6d4b1875c58adb56d3b39d08438a017a632124a5..f3591123230de5551a7cc0cc1236966631f115d0 100644 (file)
@@ -30,6 +30,7 @@ SECTIONS
 
        . = ALIGN (4);
        .text : {
+               *(.__image_copy_start)
                arch/arm/cpu/ixp/start.o(.text*)
                net/libnet.o(.text*)
                board/dvlhost/libdvlhost.o(.text*)
@@ -62,17 +63,23 @@ SECTIONS
 
        . = ALIGN (4);
 
-       __image_copy_end = .;
+       .image_copy_end :
+       {
+               *(.__image_copy_end)
+       }
+
+       .rel_dyn_start :
+       {
+               *(.__rel_dyn_start)
+       }
 
        .rel.dyn : {
-               __rel_dyn_start = .;
                *(.rel*)
-               __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
+       .rel_dyn_end :
+       {
+               *(.__rel_dyn_end)
        }
 
        _end = .;
@@ -96,6 +103,7 @@ SECTIONS
                KEEP(*(.__bss_end));
        }
 
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynamic*) }
        /DISCARD/ : { *(.plt*) }
index 89f1b1d3559ba9d4c6cd988d510917d574dd067b..4c3656e24dcce3a141a764fb9bb014eb07867388 100644 (file)
@@ -207,9 +207,14 @@ int misc_init_r (void)
                buf[4] = eerev.etheraddr[5];
                buf[5] = eerev.etheraddr[4];
 
-               *(unsigned short *) &buf[20] = 0x48B2;
-               *(unsigned short *) &buf[22] = 0x0004;
-               *(unsigned short *) &buf[24] = 0x1433;
+               buf[20] = 0x48;
+               buf[21] = 0xB2;
+
+               buf[22] = 0x00;
+               buf[23] = 0x04;
+
+               buf[24] = 0x14;
+               buf[25] = 0x33;
 
                printf ("\nSRom:  Writing i82559 info ........ ");
                if (eepro100_srom_store ((unsigned short *) buf) == -1)
index 29cc41bfaf0e14528d270ae7703ae0993e8e8e0e..1416f98dc6e13bbe5ee982c51a92279384eeef90 100644 (file)
@@ -52,6 +52,15 @@ struct fsl_e_tlb_entry tlb_table[] = {
        SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_ADDR, CONFIG_SYS_INIT_L3_ADDR,
                        MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                        0, 0, BOOKE_PAGESZ_1M, 1),
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+       /*
+        * SRIO_PCIE_BOOT-SLAVE. When slave boot, the address of the
+        * space is at 0xfff00000, it covered the 0xfffff000.
+        */
+       SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR,
+                     CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_W|MAS2_G,
+                     0, 0, BOOKE_PAGESZ_1M, 1),
 #else
        SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
                      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
@@ -137,6 +146,16 @@ struct fsl_e_tlb_entry tlb_table[] = {
                MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                      0, 16, BOOKE_PAGESZ_256M, 1),
 #endif
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+       /*
+        * SRIO_PCIE_BOOT-SLAVE. 1M space from 0xffe00000 for
+        * fetching ucode and ENV from master
+        */
+       SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR,
+                     CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_G,
+                     0, 17, BOOKE_PAGESZ_1M, 1),
+#endif
 };
 
 int num_tlb_entries = ARRAY_SIZE(tlb_table);
index 6f4cb268f1d4ffb70542e9f2f86e228742c7213b..2e829ad2e225930b5f5ad3d5b02f02c9c1f2c2f1 100644 (file)
@@ -24,12 +24,28 @@ include $(TOPDIR)/config.mk
 
 LIB    = $(obj)lib$(BOARD).o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-y        += spl_minimal.o tlb.o law.o
+
+else
+
 COBJS-y        += $(BOARD).o
 COBJS-y        += ddr.o
 COBJS-y        += law.o
 COBJS-y        += tlb.o
 #COBJS-y               += bsc9131rdb_mux.o
 
+endif
+
 SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y))
 SOBJS  := $(addprefix $(obj),$(SOBJS))
index 065faa378d1ff1ee3a17297d464cde498eedad6a..4902b98ba1250c79757638c8875dee9646339911 100644 (file)
@@ -89,10 +89,14 @@ NAND boot
 Building U-boot
 --------------
 To build the u-boot for BSC9131RDB:
-1. NAND Flash
+1. NAND Flash with sysclk 66MHz(J16 on RDB closed, default)
        make BSC9131RDB_NAND
-2. SPI Flash
+2. NAND Flash with sysclk 100MHz(J16 on RDB open)
+       make BSC9131RDB_NAND_SYSCLK100
+3. SPI Flash with sysclk 66MHz(J16 on RDB closed, default)
        make BSC9131RDB_SPIFLASH
+4. SPI Flash with sysclk 100MHz(J16 on RDB open)
+       make BSC9131RDB_SPIFLASH_SYSCLK100
 
 Memory map
 -----------
@@ -107,6 +111,16 @@ Memory map
  0xFF70_0000   0xFF7F_FFFF     PA CCSR                 1M
  0xFF80_0000   0xFFFF_FFFF     Boot Page & NAND Buffer 8M
 
+DDR Memory map
+---------------
+ 0x0000_0000   0x36FF_FFFF     Memory passed onto Linux
+ 0x3700_0000   0x37FF_FFFF     PowerPC-DSP shared control area
+ 0x3800_0000   0x4FFF_FFFF     DSP Private area
+
+ Out of 880M, passed onto Linux, 1hugetlb page of 256M is reserved for
+ data communcation between PowerPC and DSP core.
+ Rest is PowerPC private area.
+
 Flashing Images
 ---------------
 To place a new u-boot image in the NAND flash and then boot
index 201c1470795d1b1dc754ef5d9f36aa39bae454bd..0432780f947417235e74f11b3660a4e6068e777d 100644 (file)
 
 struct law_entry law_table[] = {
        SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_IFC),
+       SET_LAW(CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS, LAW_SIZE_1M,
+               LAW_TRGT_IF_DSP_CCSR),
+       SET_LAW(CONFIG_SYS_FSL_DSP_M2_RAM_ADDR, LAW_SIZE_16M,
+               LAW_TRGT_IF_OCN_DSP),
 };
 
 int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/board/freescale/bsc9131rdb/spl_minimal.c b/board/freescale/bsc9131rdb/spl_minimal.c
new file mode 100644 (file)
index 0000000..301115e
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2013 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 as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <ns16550.h>
+#include <asm/io.h>
+#include <nand.h>
+#include <linux/compiler.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Fixed sdram init -- doesn't use serial presence detect.
+ */
+static void sdram_init(void)
+{
+       ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+
+       __raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
+       __raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
+#if CONFIG_CHIP_SELECTS_PER_CTRL > 1
+       __raw_writel(CONFIG_SYS_DDR_CS1_BNDS, &ddr->cs1_bnds);
+       __raw_writel(CONFIG_SYS_DDR_CS1_CONFIG, &ddr->cs1_config);
+#endif
+       __raw_writel(CONFIG_SYS_DDR_TIMING_3_800, &ddr->timing_cfg_3);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_0_800, &ddr->timing_cfg_0);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_1_800, &ddr->timing_cfg_1);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_2_800, &ddr->timing_cfg_2);
+
+       __raw_writel(CONFIG_SYS_DDR_CONTROL_2, &ddr->sdram_cfg_2);
+       __raw_writel(CONFIG_SYS_DDR_MODE_1_800, &ddr->sdram_mode);
+       __raw_writel(CONFIG_SYS_DDR_MODE_2_800, &ddr->sdram_mode_2);
+
+       __raw_writel(CONFIG_SYS_DDR_INTERVAL_800, &ddr->sdram_interval);
+       __raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
+       __raw_writel(CONFIG_SYS_DDR_CLK_CTRL_800, &ddr->sdram_clk_cntl);
+
+       __raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_800, &ddr->ddr_wrlvl_cntl);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_4, &ddr->timing_cfg_4);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_5, &ddr->timing_cfg_5);
+       __raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
+
+       /* Set, but do not enable the memory */
+       __raw_writel(CONFIG_SYS_DDR_CONTROL & ~SDRAM_CFG_MEM_EN, &ddr->sdram_cfg);
+
+       asm volatile("sync;isync");
+       udelay(500);
+
+       /* Let the controller go */
+       out_be32(&ddr->sdram_cfg, in_be32(&ddr->sdram_cfg) | SDRAM_CFG_MEM_EN);
+
+       set_next_law(CONFIG_SYS_NAND_DDR_LAW, LAW_SIZE_1G, LAW_TRGT_IF_DDR_1);
+}
+
+void board_init_f(ulong bootflag)
+{
+       u32 plat_ratio;
+       ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+       /* initialize selected port with appropriate baud rate */
+       plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
+       plat_ratio >>= 1;
+       gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
+
+       NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
+                    gd->bus_clk / 16 / CONFIG_BAUDRATE);
+
+       puts("\nNAND boot... ");
+
+       /* Initialize the DDR3 */
+       sdram_init();
+
+       /* copy code to RAM and jump to it - this should not return */
+       /* NOTE - code has to be copied out of NAND buffer before
+        * other blocks can be read.
+        */
+       relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+       nand_boot();
+}
+
+void putc(char c)
+{
+       if (c == '\n')
+               NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, '\r');
+
+       NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, c);
+}
+
+void puts(const char *str)
+{
+       while (*str)
+               putc(*str++);
+}
index 5b68f4af3cc443be4f9b59cbbc879ac77e13830d..c05a556a3dcc69ba36ebbdfea96ed95e02c6f943 100644 (file)
@@ -44,15 +44,26 @@ struct fsl_e_tlb_entry tlb_table[] = {
        /* TLB 1 */
        /* *I*** - Covers boot page */
        SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
-                       MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
-                       0, 0, BOOKE_PAGESZ_4K, 1),
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 0, BOOKE_PAGESZ_4K, 1),
+#ifdef CONFIG_SPL_NAND_MINIMAL
+       SET_TLB_ENTRY(1, 0xffffe000, 0xffffe000,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 10, BOOKE_PAGESZ_4K, 1),
+#endif
 
        /* *I*G* - CCSRBAR (PA) */
        SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
                        MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                        0, 1, BOOKE_PAGESZ_1M, 1),
 
-#if defined(CONFIG_SYS_RAMBOOT)
+       /* CCSRBAR (DSP) */
+       SET_TLB_ENTRY(1, CONFIG_SYS_FSL_DSP_CCSRBAR,
+                     CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 2, BOOKE_PAGESZ_1M, 1),
+
+#if  defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
        SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
                        MAS3_SX|MAS3_SW|MAS3_SR, 0,
                        0, 8, BOOKE_PAGESZ_1G, 1),
index 267400becb14a2be4ccd82d49f7338bf6cbd45e5..72b19174bf691d4462a2df9b59b524f2a12ab69e 100644 (file)
@@ -24,11 +24,28 @@ include $(TOPDIR)/config.mk
 
 LIB    = $(obj)lib$(BOARD).o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-y        += spl_minimal.o tlb.o law.o
+
+else
+
+
 COBJS-y        += $(BOARD).o
 COBJS-y        += ddr.o
 COBJS-y        += law.o
 COBJS-y        += tlb.o
 
+endif
+
 SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y))
 SOBJS  := $(addprefix $(obj),$(SOBJS))
index 6e1b55816f21c21885ab48faf22d4d87eddd5520..ddc9d0a16a4fb8f63a049f0d4a297bb753494b7f 100644 (file)
@@ -258,7 +258,7 @@ int misc_init_r(void)
        u8 val;
        ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
        u32 porbmsr = in_be32(&gur->porbmsr);
-       u32 romloc = (porbmsr >> MPC85XX_PORBMSR_ROMLOC_SHIFT) & 0xf;
+       u32 romloc = (porbmsr >> MPC85xx_PORBMSR_ROMLOC_SHIFT) & 0xf;
 
        /*Configure 1588 clock-in source from RF Card*/
        val = QIXIS_READ_I2C(brdcfg[5]);
@@ -360,7 +360,7 @@ void ft_board_setup(void *blob, bd_t *bd)
 
        ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
        u32 porbmsr = in_be32(&gur->porbmsr);
-       u32 romloc = (porbmsr >> MPC85XX_PORBMSR_ROMLOC_SHIFT) & 0xf;
+       u32 romloc = (porbmsr >> MPC85xx_PORBMSR_ROMLOC_SHIFT) & 0xf;
 
        if (!(hwconfig("uart2") && hwconfig("usb1"))) {
                /* If uart2 is there in hwconfig remove usb node from
index dc2365851b49f974fb71806d5a30029dc8914de1..b4bce99d3d945cdec4c200615d736846785672aa 100644 (file)
 #include <asm/mmu.h>
 
 struct law_entry law_table[] = {
-#ifndef CONFIG_SYS_NO_FLASH
        SET_LAW(CONFIG_SYS_FLASH_BASE_PHYS, LAW_SIZE_128M, LAW_TRGT_IF_IFC),
-#endif
+#ifdef CONFIG_SYS_NAND_BASE_PHYS
        SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_IFC),
+#endif
+#ifdef CONFIG_SYS_FPGA_BASE_PHYS
        SET_LAW(CONFIG_SYS_FPGA_BASE_PHYS, LAW_SIZE_128K, LAW_TRGT_IF_IFC),
+#endif
 };
 
 int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/board/freescale/bsc9132qds/spl_minimal.c b/board/freescale/bsc9132qds/spl_minimal.c
new file mode 100644 (file)
index 0000000..62dee52
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2013 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 as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <ns16550.h>
+#include <asm/io.h>
+#include <nand.h>
+#include <linux/compiler.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void sdram_init(void)
+{
+       ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+#if CONFIG_DDR_CLK_FREQ == 100000000
+       __raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
+       __raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
+       __raw_writel(CONFIG_SYS_DDR_CONTROL_800 | SDRAM_CFG_32_BE, &ddr->sdram_cfg);
+       __raw_writel(CONFIG_SYS_DDR_CONTROL_2_800, &ddr->sdram_cfg_2);
+       __raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
+
+       __raw_writel(CONFIG_SYS_DDR_TIMING_3_800, &ddr->timing_cfg_3);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_0_800, &ddr->timing_cfg_0);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_1_800, &ddr->timing_cfg_1);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_2_800, &ddr->timing_cfg_2);
+       __raw_writel(CONFIG_SYS_DDR_MODE_1_800, &ddr->sdram_mode);
+       __raw_writel(CONFIG_SYS_DDR_MODE_2_800, &ddr->sdram_mode_2);
+       __raw_writel(CONFIG_SYS_DDR_INTERVAL_800, &ddr->sdram_interval);
+       __raw_writel(CONFIG_SYS_DDR_CLK_CTRL_800, &ddr->sdram_clk_cntl);
+       __raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_800, &ddr->ddr_wrlvl_cntl);
+
+       __raw_writel(CONFIG_SYS_DDR_TIMING_4_800, &ddr->timing_cfg_4);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_5_800, &ddr->timing_cfg_5);
+       __raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
+#elif CONFIG_DDR_CLK_FREQ == 133000000
+       __raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
+       __raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
+       __raw_writel(CONFIG_SYS_DDR_CONTROL_1333 | SDRAM_CFG_32_BE, &ddr->sdram_cfg);
+       __raw_writel(CONFIG_SYS_DDR_CONTROL_2_1333, &ddr->sdram_cfg_2);
+       __raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
+
+       __raw_writel(CONFIG_SYS_DDR_TIMING_3_1333, &ddr->timing_cfg_3);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_0_1333, &ddr->timing_cfg_0);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_1_1333, &ddr->timing_cfg_1);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_2_1333, &ddr->timing_cfg_2);
+       __raw_writel(CONFIG_SYS_DDR_MODE_1_1333, &ddr->sdram_mode);
+       __raw_writel(CONFIG_SYS_DDR_MODE_2_1333, &ddr->sdram_mode_2);
+       __raw_writel(CONFIG_SYS_DDR_INTERVAL_1333, &ddr->sdram_interval);
+       __raw_writel(CONFIG_SYS_DDR_CLK_CTRL_1333, &ddr->sdram_clk_cntl);
+       __raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL_1333, &ddr->ddr_wrlvl_cntl);
+
+       __raw_writel(CONFIG_SYS_DDR_TIMING_4_1333, &ddr->timing_cfg_4);
+       __raw_writel(CONFIG_SYS_DDR_TIMING_5_1333, &ddr->timing_cfg_5);
+       __raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
+#else
+       puts("Not a valid DDR Freq Found! Please Reset\n");
+#endif
+       asm volatile("sync;isync");
+       udelay(500);
+
+       /* Let the controller go */
+       out_be32(&ddr->sdram_cfg, in_be32(&ddr->sdram_cfg) | SDRAM_CFG_MEM_EN);
+
+       set_next_law(CONFIG_SYS_NAND_DDR_LAW, LAW_SIZE_1G, LAW_TRGT_IF_DDR_1);
+}
+
+void board_init_f(ulong bootflag)
+{
+       u32 plat_ratio;
+       ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+       /* initialize selected port with appropriate baud rate */
+       plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
+       plat_ratio >>= 1;
+       gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
+
+       NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
+                    gd->bus_clk / 16 / CONFIG_BAUDRATE);
+
+       puts("\nNAND boot... ");
+
+       /* Initialize the DDR3 */
+       sdram_init();
+
+       /* copy code to RAM and jump to it - this should not return */
+       /* NOTE - code has to be copied out of NAND buffer before
+        * other blocks can be read.
+        */
+       relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+       nand_boot();
+}
+
+void putc(char c)
+{
+       if (c == '\n')
+               NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, '\r');
+
+       NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, c);
+}
+
+void puts(const char *str)
+{
+       while (*str)
+               putc(*str++);
+}
index 0e4545fb12856b8d0d038827d1b9fa962c5cc2fe..0ec9a851aba6ad55a0ad5b5ce68ab9a20759a602 100644 (file)
@@ -44,14 +44,20 @@ struct fsl_e_tlb_entry tlb_table[] = {
        /* TLB 1 */
        /* *I*** - Covers boot page */
        SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
-                       MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
-                       0, 0, BOOKE_PAGESZ_4K, 1),
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 0, BOOKE_PAGESZ_4K, 1),
+#ifdef CONFIG_SPL_NAND_MINIMAL
+       SET_TLB_ENTRY(1, 0xffffe000, 0xffffe000,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 10, BOOKE_PAGESZ_4K, 1),
+#endif
 
        /* *I*G* - CCSRBAR (PA) */
        SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
                        MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                        0, 1, BOOKE_PAGESZ_1M, 1),
 
+#ifndef CONFIG_SPL_BUILD
        SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
                        MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
                        0, 3, BOOKE_PAGESZ_64M, 1),
@@ -61,12 +67,6 @@ struct fsl_e_tlb_entry tlb_table[] = {
                        MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
                        0, 4, BOOKE_PAGESZ_64M, 1),
 
-#if defined(CONFIG_SYS_RAMBOOT)
-       SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
-                       MAS3_SX|MAS3_SW|MAS3_SR, 0,
-                       0, 8, BOOKE_PAGESZ_1G, 1),
-#endif
-
 #ifdef CONFIG_PCI
        /* *I*G* - PCI */
        SET_TLB_ENTRY(1, CONFIG_SYS_PCIE1_MEM_VIRT, CONFIG_SYS_PCIE1_MEM_PHYS,
@@ -78,15 +78,26 @@ struct fsl_e_tlb_entry tlb_table[] = {
                        MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                        0, 7, BOOKE_PAGESZ_64K, 1),
 #endif
+#endif
+
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
+       SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
+                     MAS3_SX|MAS3_SW|MAS3_SR, 0,
+                     0, 8, BOOKE_PAGESZ_1G, 1),
+#endif
 
+#ifdef CONFIG_SYS_FPGA_BASE
                /* *I*G - Board FPGA  */
        SET_TLB_ENTRY(1, CONFIG_SYS_FPGA_BASE, CONFIG_SYS_FPGA_BASE_PHYS,
                        MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                        0, 9, BOOKE_PAGESZ_256K, 1),
+#endif
 
+#ifdef CONFIG_SYS_NAND_BASE_PHYS
        SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
                        MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                        0, 5, BOOKE_PAGESZ_1M, 1),
+#endif
 };
 
 int num_tlb_entries = ARRAY_SIZE(tlb_table);
index 72bb56cac4bc8ac0cb45c96a9fbdee21ec192828..37236d072b6d05a1a0821cb9c7d18895016d0f89 100644 (file)
@@ -29,6 +29,15 @@ endif
 
 LIB    = $(obj)libfreescale.o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifndef MINIMAL
 COBJS-$(CONFIG_FSL_CADMUS)     += cadmus.o
 COBJS-$(CONFIG_FSL_VIA)                += cds_via.o
 COBJS-$(CONFIG_FMAN_ENET)      += fman.o
@@ -68,6 +77,7 @@ SUBLIB-$(CONFIG_P3041DS)      += p_corenet/libp_corenet.o
 SUBLIB-$(CONFIG_P4080DS)       += p_corenet/libp_corenet.o
 SUBLIB-$(CONFIG_P5020DS)       += p_corenet/libp_corenet.o
 SUBLIB-$(CONFIG_P5040DS)       += p_corenet/libp_corenet.o
+endif
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y))
index 8d07061c36f36a67481484719ab44436eb4a9b02..fbb709de14a2faef74f04ba06d057f30af8425cd 100644 (file)
@@ -480,6 +480,7 @@ static int pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const ar
            ||  unknown_param) {
 #ifdef CONFIG_SYS_LONGHELP
                puts(cmdtp->help);
+               putc('\n');
 #endif
                return 1;
        }
@@ -512,6 +513,7 @@ static int pixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const ar
                      && set_px_mpxpll(mpxpll))) {
 #ifdef CONFIG_SYS_LONGHELP
                        puts(cmdtp->help);
+                       putc('\n');
 #endif
                        return 1;
                }
index 4969960001dda9af54bf772fa448c45250c61e1e..963d29f2dc839cb746dc60c39edb779854684e38 100644 (file)
@@ -34,6 +34,7 @@ SECTIONS
        . = ALIGN(4);
        .text      :
        {
+               *(.__image_copy_start)
          /* WARNING - the following is hand-optimized to fit within    */
          /* the sector layout of our flash chips!      XXX FIXME XXX   */
 
@@ -65,17 +66,23 @@ SECTIONS
 
        . = ALIGN(4);
 
-       __image_copy_end = .;
+       .image_copy_end :
+       {
+               *(.__image_copy_end)
+       }
+
+       .rel_dyn_start :
+       {
+               *(.__rel_dyn_start)
+       }
 
        .rel.dyn : {
-               __rel_dyn_start = .;
                *(.rel*)
-               __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
+       .rel_dyn_end :
+       {
+               *(.__rel_dyn_end)
        }
 
        _end = .;
@@ -100,6 +107,7 @@ SECTIONS
        }
 
        /DISCARD/ : { *(.bss*) }
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynsym*) }
        /DISCARD/ : { *(.dynamic*) }
index 4c705b627e622e2892006a6ecf1628faea6620fc..e6563be098901f03132c623842a435d99443e55c 100644 (file)
@@ -24,11 +24,27 @@ include $(TOPDIR)/config.mk
 
 LIB    = $(obj)lib$(BOARD).o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-y        += spl_minimal.o tlb.o law.o
+
+else
+
 COBJS-y        += $(BOARD).o
 COBJS-y        += ddr.o
 COBJS-y        += law.o
 COBJS-y        += tlb.o
 
+endif
+
 SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y))
 SOBJS  := $(addprefix $(obj),$(SOBJS))
similarity index 95%
rename from nand_spl/board/freescale/p1010rdb/nand_boot.c
rename to board/freescale/p1010rdb/spl_minimal.c
index 3c7bc2bc6536d55c2725a522346e3ae0f3d444b1..c909e0ee314b5f038dda3f91d18ee38ae6a5dd61 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
-unsigned long ddr_freq_mhz;
 
 void sdram_init(void)
 {
        ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+       ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+       u32 ddr_ratio;
+       unsigned long ddr_freq_mhz;
+
+       ddr_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO;
+       ddr_ratio = ddr_ratio >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+       ddr_freq_mhz = (CONFIG_SYS_CLK_FREQ * ddr_ratio) / 0x1000000;
+
        /* mask off E bit */
        u32 svr = SVR_SOC_VER(mfspr(SPRN_SVR));
 
@@ -81,6 +88,7 @@ void sdram_init(void)
                __raw_writel((CONFIG_SYS_DDR_CS0_BNDS >> 1) & 0x0fff0fff, &ddr->cs0_bnds);
        }
 
+       asm volatile("sync;isync");
        udelay(500);
 
        /* Let the controller go */
@@ -91,7 +99,7 @@ void sdram_init(void)
 
 void board_init_f(ulong bootflag)
 {
-       u32 plat_ratio, ddr_ratio;
+       u32 plat_ratio;
        ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
 
        /* initialize selected port with appropriate baud rate */
@@ -99,10 +107,6 @@ void board_init_f(ulong bootflag)
        plat_ratio >>= 1;
        gd->bus_clk = CONFIG_SYS_CLK_FREQ * plat_ratio;
 
-       ddr_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO;
-       ddr_ratio = ddr_ratio >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
-       ddr_freq_mhz = (CONFIG_SYS_CLK_FREQ * ddr_ratio) / 0x1000000;
-
        NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
                        gd->bus_clk / 16 / CONFIG_BAUDRATE);
 
@@ -115,8 +119,8 @@ void board_init_f(ulong bootflag)
        /* NOTE - code has to be copied out of NAND buffer before
         * other blocks can be read.
         */
-       relocate_code(CONFIG_SYS_NAND_U_BOOT_RELOC_SP, 0,
-                       CONFIG_SYS_NAND_U_BOOT_RELOC);
+
+       relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
 }
 
 void board_init_r(gd_t *gd, ulong dest_addr)
index 4256bf4e5707aec43b6cbc4bed5afed3aa8e493d..078717a5b9875a1ab0ff6bfe2ac33c208455839c 100644 (file)
@@ -44,15 +44,20 @@ struct fsl_e_tlb_entry tlb_table[] = {
        /* TLB 1 */
        /* *I*** - Covers boot page */
        SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
-                       MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
-                       0, 0, BOOKE_PAGESZ_4K, 1),
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 0, BOOKE_PAGESZ_4K, 1),
+#ifdef CONFIG_SPL_NAND_MINIMAL
+       SET_TLB_ENTRY(1, 0xffffe000, 0xffffe000,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 10, BOOKE_PAGESZ_4K, 1),
+#endif
 
        /* *I*G* - CCSRBAR */
        SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
                        MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                        0, 1, BOOKE_PAGESZ_1M, 1),
 
-#ifndef CONFIG_NAND_SPL
+#ifndef CONFIG_SPL_BUILD
 #ifndef CONFIG_SDCARD
        SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
                        MAS3_SX|MAS3_SR, MAS2_W|MAS2_G,
@@ -88,7 +93,7 @@ struct fsl_e_tlb_entry tlb_table[] = {
                        0, 7, BOOKE_PAGESZ_1M, 1),
 #endif
 
-#if defined(CONFIG_SYS_RAMBOOT)
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
        SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
                        MAS3_SX|MAS3_SW|MAS3_SR, 0,
                        0, 8, BOOKE_PAGESZ_1G, 1)
diff --git a/board/freescale/p1023rdb/Makefile b/board/freescale/p1023rdb/Makefile
new file mode 100644 (file)
index 0000000..45c4f8b
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Copyright 2013 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 as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(BOARD).o
+
+COBJS-y        += $(BOARD).o
+COBJS-y        += ddr.o
+COBJS-y        += law.o
+COBJS-y        += tlb.o
+
+SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS-y))
+SOBJS  := $(addprefix $(obj),$(SOBJS))
+
+$(LIB):        $(obj).depend $(OBJS) $(SOBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/freescale/p1023rdb/ddr.c b/board/freescale/p1023rdb/ddr.c
new file mode 100644 (file)
index 0000000..7ed275a
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/mmu.h>
+#include <asm/immap_85xx.h>
+#include <asm/processor.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+#include <asm/io.h>
+#include <asm/fsl_law.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* CONFIG_SYS_DDR_RAW_TIMING */
+/*
+ * Hynix H5TQ1G83TFR-H9C
+ */
+dimm_params_t ddr_raw_timing = {
+       .n_ranks = 1,
+       .rank_density = 536870912u,
+       .capacity = 536870912u,
+       .primary_sdram_width = 32,
+       .ec_sdram_width = 0,
+       .registered_dimm = 0,
+       .mirrored_dimm = 0,
+       .n_row_addr = 14,
+       .n_col_addr = 10,
+       .n_banks_per_sdram_device = 8,
+       .edc_config = 0,
+       .burst_lengths_bitmask = 0x0c,
+
+       .tCKmin_X_ps = 1875,
+       .caslat_X = 0x1e << 4,  /* 5,6,7,8 */
+       .tAA_ps = 13125,
+       .tWR_ps = 18000,
+       .tRCD_ps = 13125,
+       .tRRD_ps = 7500,
+       .tRP_ps = 13125,
+       .tRAS_ps = 37500,
+       .tRC_ps = 50625,
+       .tRFC_ps = 160000,
+       .tWTR_ps = 7500,
+       .tRTP_ps = 7500,
+       .refresh_rate_ps = 7800000,
+       .tFAW_ps = 37500,
+};
+
+int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
+               unsigned int controller_number,
+               unsigned int dimm_number)
+{
+       const char dimm_model[] = "Fixed DDR on board";
+
+       if ((controller_number == 0) && (dimm_number == 0)) {
+               memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t));
+               memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+               memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+       }
+
+       return 0;
+}
+
+void fsl_ddr_board_options(memctl_options_t *popts,
+                               dimm_params_t *pdimm,
+                               unsigned int ctrl_num)
+{
+       int i;
+       popts->clk_adjust = 6;
+       popts->cpo_override = 0x1f;
+       popts->write_data_delay = 2;
+       popts->half_strength_driver_enable = 1;
+       /* Write leveling override */
+       popts->wrlvl_en = 1;
+       popts->wrlvl_override = 1;
+       popts->wrlvl_sample = 0xf;
+       popts->wrlvl_start = 0x8;
+       popts->trwt_override = 1;
+       popts->trwt = 0;
+
+       for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+               popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
+               popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
+       }
+}
+
diff --git a/board/freescale/p1023rdb/law.c b/board/freescale/p1023rdb/law.c
new file mode 100644 (file)
index 0000000..331662c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+#include <asm/mmu.h>
+
+struct law_entry law_table[] = {
+       SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_LBC),
+       SET_LAW(CONFIG_SYS_QMAN_MEM_PHYS, LAW_SIZE_4M,
+               LAW_TRGT_IF_DPAA_SWP_SRAM),
+       SET_LAW(CONFIG_SYS_FLASH_BASE_PHYS, LAW_SIZE_256M, LAW_TRGT_IF_LBC),
+};
+
+int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/board/freescale/p1023rdb/p1023rdb.c b/board/freescale/p1023rdb/p1023rdb.c
new file mode 100644 (file)
index 0000000..918398b
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Authors:  Roy Zang <tie-fei.zang@freescale.com>
+ *           Chunhe Lan <Chunhe.Lan@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/cache.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_pci.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_portals.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <netdev.h>
+#include <malloc.h>
+#include <fm_eth.h>
+#include <fsl_mdio.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <asm/fsl_dtsec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_early_init_f(void)
+{
+       fsl_lbc_t *lbc = LBC_BASE_ADDR;
+
+       /* Set ABSWP to implement conversion of addresses in the LBC */
+       setbits_be32(&lbc->lbcr, CONFIG_SYS_LBC_LBCR);
+
+       return 0;
+}
+
+int checkboard(void)
+{
+       printf("Board: P1023 RDB\n");
+
+       return 0;
+}
+
+#ifdef CONFIG_PCI
+void pci_init_board(void)
+{
+       fsl_pcie_init_board(0);
+}
+#endif
+
+int board_early_init_r(void)
+{
+       const unsigned int flashbase = CONFIG_SYS_FLASH_BASE;
+       const u8 flash_esel = find_tlb_idx((void *)flashbase, 1);
+
+       /*
+        * Remap Boot flash + PROMJET region to caching-inhibited
+        * so that flash can be erased properly.
+        */
+
+       /* Flush d-cache and invalidate i-cache of any FLASH data */
+       flush_dcache();
+       invalidate_icache();
+
+       /* invalidate existing TLB entry for flash + promjet */
+       disable_tlb(flash_esel);
+
+       set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS,
+               MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+               0, flash_esel, BOOKE_PAGESZ_256M, 1);
+
+       setup_portals();
+
+       return 0;
+}
+
+unsigned long get_board_sys_clk(ulong dummy)
+{
+       return gd->bus_clk;
+}
+
+unsigned long get_board_ddr_clk(ulong dummy)
+{
+       return gd->mem_clk;
+}
+
+int board_eth_init(bd_t *bis)
+{
+       ccsr_gur_t *gur = (ccsr_gur_t *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+       struct fsl_pq_mdio_info dtsec_mdio_info;
+
+       /*
+        * Need to set dTSEC 1 pin multiplexing to TSEC. The default setting
+        * is not correct.
+        */
+       setbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_TSEC1_1);
+
+       dtsec_mdio_info.regs =
+               (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
+       dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
+
+       /* Register the 1G MDIO bus */
+       fsl_pq_mdio_init(bis, &dtsec_mdio_info);
+
+       fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR);
+       fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR);
+
+       fm_info_set_mdio(FM1_DTSEC1,
+                        miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
+       fm_info_set_mdio(FM1_DTSEC2,
+                        miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
+
+#ifdef CONFIG_FMAN_ENET
+       cpu_eth_init(bis);
+#endif
+
+       return pci_eth_init(bis);
+}
+
+#if defined(CONFIG_OF_BOARD_SETUP)
+void ft_board_setup(void *blob, bd_t *bd)
+{
+       phys_addr_t base;
+       phys_size_t size;
+
+       ft_cpu_setup(blob, bd);
+
+       base = getenv_bootm_low();
+       size = getenv_bootm_size();
+
+       fdt_fixup_memory(blob, (u64)base, (u64)size);
+
+#ifdef CONFIG_HAS_FSL_DR_USB
+       fdt_fixup_dr_usb(blob, bd);
+#endif
+
+       fdt_fixup_fman_ethernet(blob);
+}
+#endif
diff --git a/board/freescale/p1023rdb/tlb.c b/board/freescale/p1023rdb/tlb.c
new file mode 100644 (file)
index 0000000..3417c0f
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/mmu.h>
+
+struct fsl_e_tlb_entry tlb_table[] = {
+       /* TLB 0 - for temp stack in cache */
+       SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR, CONFIG_SYS_INIT_RAM_ADDR,
+                     MAS3_SX|MAS3_SW|MAS3_SR, 0,
+                     0, 0, BOOKE_PAGESZ_4K, 0),
+       SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
+                     CONFIG_SYS_INIT_RAM_ADDR + 4 * 1024,
+                     MAS3_SX|MAS3_SW|MAS3_SR, 0,
+                     0, 0, BOOKE_PAGESZ_4K, 0),
+       SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
+                     CONFIG_SYS_INIT_RAM_ADDR + 8 * 1024,
+                     MAS3_SX|MAS3_SW|MAS3_SR, 0,
+                     0, 0, BOOKE_PAGESZ_4K, 0),
+       SET_TLB_ENTRY(0, CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
+                     CONFIG_SYS_INIT_RAM_ADDR + 12 * 1024,
+                     MAS3_SX|MAS3_SW|MAS3_SR, 0,
+                     0, 0, BOOKE_PAGESZ_4K, 0),
+
+       /* TLB 1 */
+       /* *I*** - Covers boot page */
+       SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I,
+                     0, 0, BOOKE_PAGESZ_4K, 1),
+
+       /* *I*G* - CCSRBAR */
+       SET_TLB_ENTRY(1, CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 1, BOOKE_PAGESZ_4M, 1),
+
+       /* W**G* - Flash, localbus */
+       /* This will be changed to *I*G* after relocation to RAM. */
+       SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_W|MAS2_G,
+                     0, 2, BOOKE_PAGESZ_256M, 1),
+
+       /* *I*G* - PCI */
+       SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_MEM_VIRT, CONFIG_SYS_PCIE3_MEM_PHYS,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 3, BOOKE_PAGESZ_1G, 1),
+
+       /* *I*G* - PCI */
+       SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_MEM_VIRT + 0x40000000,
+                     CONFIG_SYS_PCIE3_MEM_PHYS + 0x40000000,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 4, BOOKE_PAGESZ_256M, 1),
+
+       SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_MEM_VIRT + 0x50000000,
+                     CONFIG_SYS_PCIE3_MEM_PHYS + 0x50000000,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 5, BOOKE_PAGESZ_256M, 1),
+
+       /* *I*G* - PCI I/O */
+       SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_IO_VIRT, CONFIG_SYS_PCIE3_IO_PHYS,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 6, BOOKE_PAGESZ_256K, 1),
+
+       /* Bman/Qman */
+       SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE, CONFIG_SYS_BMAN_MEM_PHYS,
+                     MAS3_SW|MAS3_SR, 0,
+                     0, 7, BOOKE_PAGESZ_1M, 1),
+       SET_TLB_ENTRY(1, CONFIG_SYS_BMAN_MEM_BASE + 0x00100000,
+                     CONFIG_SYS_BMAN_MEM_PHYS + 0x00100000,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 8, BOOKE_PAGESZ_1M, 1),
+       SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE, CONFIG_SYS_QMAN_MEM_PHYS,
+                     MAS3_SW|MAS3_SR, MAS2_M,
+                     0, 9, BOOKE_PAGESZ_1M, 1),
+       SET_TLB_ENTRY(1, CONFIG_SYS_QMAN_MEM_BASE + 0x00100000,
+                     CONFIG_SYS_QMAN_MEM_PHYS + 0x00100000,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 10, BOOKE_PAGESZ_1M, 1),
+
+       SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
+                     MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+                     0, 11, BOOKE_PAGESZ_16K, 1),
+
+#ifdef CONFIG_SYS_RAMBOOT
+       SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE,
+                     CONFIG_SYS_DDR_SDRAM_BASE,
+                     MAS3_SX|MAS3_SW|MAS3_SR, 0,
+                     0, 12, BOOKE_PAGESZ_256M, 1),
+
+       SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE + 0x10000000,
+                     CONFIG_SYS_DDR_SDRAM_BASE + 0x10000000,
+                     MAS3_SX|MAS3_SW|MAS3_SR, 0,
+                     0, 13, BOOKE_PAGESZ_256M, 1),
+#endif
+};
+
+int num_tlb_entries = ARRAY_SIZE(tlb_table);
index 92c01cf95c72a18f614a52d85355abab11592079..a138d5a9e6f4bd986c3b6615043f235cc6a937e1 100644 (file)
@@ -55,6 +55,15 @@ struct fsl_e_tlb_entry tlb_table[] = {
        SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_ADDR, CONFIG_SYS_INIT_L3_ADDR,
                        MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                        0, 0, BOOKE_PAGESZ_1M, 1),
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+       /*
+        * SRIO_PCIE_BOOT-SLAVE. When slave boot, the address of the
+        * space is at 0xfff00000, it covered the 0xfffff000.
+        */
+       SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR,
+                     CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_W|MAS2_G,
+                     0, 0, BOOKE_PAGESZ_1M, 1),
 #else
        SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
                      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
@@ -130,6 +139,16 @@ struct fsl_e_tlb_entry tlb_table[] = {
        SET_TLB_ENTRY(1, QIXIS_BASE, QIXIS_BASE_PHYS,
                      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
                      0, 17, BOOKE_PAGESZ_4K, 1),
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+       /*
+        * SRIO_PCIE_BOOT-SLAVE. 1M space from 0xffe00000 for
+        * fetching ucode and ENV from master
+        */
+       SET_TLB_ENTRY(1, CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR,
+                     CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+                     MAS3_SX|MAS3_SW|MAS3_SR, MAS2_G,
+                     0, 18, BOOKE_PAGESZ_1M, 1),
+#endif
 
 };
 
index 74425912d62ffd55a1c9cdc347eef7b78a2dd28a..dc2aff099301e8ca0e95846ae3053c3b0b2c71bd 100644 (file)
 #include <i2c.h>
 #endif
 
+static int eeprom_diag;
+static int mac_diag;
+static int gpio_diag;
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static void gpio_configure(void)
@@ -37,7 +41,7 @@ static void gpio_configure(void)
 
        /*
         * out_be32(&gpioregs->gpdir, 0xC2293020);
-        * workaround for a hardware affect: configure direction in pieces,
+        * workaround for a hardware effect: configure direction in pieces,
         * setting all outputs at once drops the reset line too low and
         * makes us lose the MII connection (breaks ethernet for us)
         */
@@ -126,8 +130,6 @@ static u32 gpio_querykbd(void)
 
 /* excerpt from the recovery's hw_info.h */
 
-static int eeprom_diag = 1;
-
 struct __attribute__ ((__packed__)) eeprom_layout {
        char    magic[3];       /** 'ifm' */
        u8      len[2];         /** content length without magic/len fields */
@@ -209,6 +211,7 @@ static int read_eeprom(void)
 int mac_read_from_eeprom(void)
 {
        const u8 *mac;
+       const char *mac_txt;
 
        if (read_eeprom()) {
                printf("I2C EEPROM read failed.\n");
@@ -230,8 +233,13 @@ int mac_read_from_eeprom(void)
 
        if (mac && is_valid_ether_addr(mac)) {
                eth_setenv_enetaddr("ethaddr", mac);
-               printf("DIAG: %s() MAC value [%s]\n",
-                       __func__, getenv("ethaddr"));
+               if (mac_diag) {
+                       mac_txt = getenv("ethaddr");
+                       if (mac_txt)
+                               printf("DIAG: MAC value [%s]\n", mac_txt);
+                       else
+                               printf("DIAG: failed to setup MAC env\n");
+               }
        }
 
        return 0;
@@ -326,42 +334,38 @@ int misc_init_r(void)
        gpio_configure();
 
        /*
-        * check the GPIO keyboard,
-        * enforced start of the recovery when
+        * enforce the start of the recovery system when
         * - the appropriate keys were pressed
-        * - a previous installation was aborted or has failed
         * - "some" external software told us to
+        * - a previous installation was aborted or has failed
         */
        want_recovery = 0;
        keys = gpio_querykbd();
-       printf("GPIO keyboard status [0x%08X]\n", keys);
-       /* XXX insist in the _exact_ combination? */
+       if (gpio_diag)
+               printf("GPIO keyboard status [0x%02X]\n", keys);
        if ((keys & GPIOKEY_BITS_RECOVERY) == GPIOKEY_BITS_RECOVERY) {
-               printf("GPIO keyboard requested RECOVERY\n");
-               /* XXX TODO
-                * refine the logic to detect the first keypress, and
-                * wait to recheck IF it was the recovery combination?
-                */
+               printf("detected recovery request (keyboard)\n");
                want_recovery = 1;
        }
-       s = getenv("install_in_progress");
+       s = getenv("want_recovery");
        if ((s != NULL) && (*s != '\0')) {
-               printf("previous installation aborted, running RECOVERY\n");
+               printf("detected recovery request (environment)\n");
                want_recovery = 1;
        }
-       s = getenv("install_failed");
+       s = getenv("install_in_progress");
        if ((s != NULL) && (*s != '\0')) {
-               printf("previous installation FAILED, running RECOVERY\n");
+               printf("previous installation has not completed\n");
                want_recovery = 1;
        }
-       s = getenv("want_recovery");
+       s = getenv("install_failed");
        if ((s != NULL) && (*s != '\0')) {
-               printf("running RECOVERY according to the request\n");
+               printf("previous installation has failed\n");
                want_recovery = 1;
        }
-
-       if (want_recovery)
+       if (want_recovery) {
+               printf("enforced start of the recovery system\n");
                setenv("bootcmd", "run recovery");
+       }
 
        /*
         * boot the recovery system without waiting; boot the
index 826ceadd81d1139a1354b9613bbff8c1acac2e71..ea3bea50f503b48a68a1f0f84e7dcbd03db7268b 100644 (file)
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-#ifdef CONFIG_SPL_BUILD
-static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
-#endif
 
 /* MII mode defines */
 #define RMII_MODE_ENABLE       0x4D
 
 static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
 
-/* UART Defines */
 #ifdef CONFIG_SPL_BUILD
-#define UART_RESET             (0x1 << 1)
-#define UART_CLK_RUNNING_MASK  0x1
-#define UART_SMART_IDLE_EN     (0x1 << 0x3)
-
-static void rtc32k_enable(void)
-{
-       struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
-
-       /*
-        * Unlock the RTC's registers.  For more details please see the
-        * RTC_SS section of the TRM.  In order to unlock we need to
-        * write these specific values (keys) in this order.
-        */
-       writel(0x83e70b13, &rtc->kick0r);
-       writel(0x95a4f1e0, &rtc->kick1r);
-
-       /* Enable the RTC 32K OSC by setting bits 3 and 6. */
-       writel((1 << 3) | (1 << 6), &rtc->osc);
-}
-
 static const struct ddr_data ddr3_data = {
        .datardsratio0 = K4B2G1646EBIH9_RD_DQS,
        .datawdsratio0 = K4B2G1646EBIH9_WR_DQS,
@@ -131,23 +107,9 @@ void s_init(void)
        /* Enable RTC32K clock */
        rtc32k_enable();
 
-       /* UART softreset */
-       u32 regval;
-
        enable_uart0_pin_mux();
 
-       regval = readl(&uart_base->uartsyscfg);
-       regval |= UART_RESET;
-       writel(regval, &uart_base->uartsyscfg);
-       while ((readl(&uart_base->uartsyssts) &
-               UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
-               ;
-
-       /* Disable smart idle */
-       regval = readl(&uart_base->uartsyscfg);
-       regval |= UART_SMART_IDLE_EN;
-       writel(regval, &uart_base->uartsyscfg);
-
+       uart_soft_reset();
        gd = &gdata;
 
        preloader_console_init();
index 93c611dfc6e65c5a4e68047cc2b3dd60df4d808e..0cca8d75b59c2cc0279865b6ae159cc4c3f8def3 100644 (file)
@@ -39,9 +39,6 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-#ifdef CONFIG_SPL_BUILD
-static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
-#endif
 
 /* MII mode defines */
 #define MII_MODE_ENABLE                0x0
@@ -50,31 +47,11 @@ static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
 
 static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
 
-/* UART defines */
 #ifdef CONFIG_SPL_BUILD
-#define UART_RESET             (0x1 << 1)
-#define UART_CLK_RUNNING_MASK  0x1
-#define UART_SMART_IDLE_EN     (0x1 << 0x3)
 
 /* DDR RAM defines */
 #define DDR_CLK_MHZ            303 /* DDR_DPLL_MULT value */
 
-static void rtc32k_enable(void)
-{
-       struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
-
-       /*
-        * Unlock the RTC's registers.  For more details please see the
-        * RTC_SS section of the TRM.  In order to unlock we need to
-        * write these specific values (keys) in this order.
-        */
-       writel(0x83e70b13, &rtc->kick0r);
-       writel(0x95a4f1e0, &rtc->kick1r);
-
-       /* Enable the RTC 32K OSC by setting bits 3 and 6. */
-       writel((1 << 3) | (1 << 6), &rtc->osc);
-}
-
 static const struct ddr_data ddr3_data = {
        .datardsratio0 = MT41J256M8HX15E_RD_DQS,
        .datawdsratio0 = MT41J256M8HX15E_WR_DQS,
@@ -141,22 +118,8 @@ void s_init(void)
        /* Enable RTC32K clock */
        rtc32k_enable();
 
-       /* UART softreset */
-       u32 regval;
-
        enable_uart0_pin_mux();
-
-       regval = readl(&uart_base->uartsyscfg);
-       regval |= UART_RESET;
-       writel(regval, &uart_base->uartsyscfg);
-       while ((readl(&uart_base->uartsyssts) & UART_CLK_RUNNING_MASK)
-               != UART_CLK_RUNNING_MASK)
-               ;
-
-       /* Disable smart idle */
-       regval = readl(&uart_base->uartsyscfg);
-       regval |= UART_SMART_IDLE_EN;
-       writel(regval, &uart_base->uartsyscfg);
+       uart_soft_reset();
 
        gd = &gdata;
 
index 8da973b30522b80086984b733ffe585bfa772751..93375a64b2f3fa43d063fcd20582fe2db6e9215f 100644 (file)
                spi2 = "/spi@12d40000";
                spi3 = "/spi@131a0000";
                spi4 = "/spi@131b0000";
+               mmc0 = "/mmc@12200000";
+               mmc1 = "/mmc@12210000";
+               mmc2 = "/mmc@12220000";
+               mmc3 = "/mmc@12230000";
        };
 
        sromc@12250000 {
                samsung,ycbcr-coeff = <0>;
                samsung,color-depth = <1>;
        };
+
+       mmc@12200000 {
+               samsung,bus-width = <8>;
+               samsung,timing = <1 3 3>;
+               samsung,removable = <0>;
+       };
+
+       mmc@12210000 {
+               status = "disabled";
+       };
+
+       mmc@12220000 {
+               samsung,bus-width = <4>;
+               samsung,timing = <1 2 3>;
+               samsung,removable = <1>;
+       };
+
+       mmc@12230000 {
+               status = "disabled";
+       };
 };
index 24658c1989bb1fae838a38152759342dca29114e..d2ccc6675d60837b38e60a7675c2503188af62f5 100644 (file)
                spi4 = "/spi@131b0000";
        };
 
+       i2c4: i2c@12ca0000 {
+               cros-ec@1e {
+                       reg = <0x1e>;
+                       compatible = "google,cros-ec";
+                       i2c-max-frequency = <100000>;
+                       ec-interrupt = <&gpio 782 1>;
+               };
+
+               power-regulator@48 {
+                       compatible = "ti,tps65090";
+                       reg = <0x48>;
+               };
+       };
+
+       spi@131b0000 {
+               spi-max-frequency = <1000000>;
+               spi-deactivate-delay = <100>;
+               cros-ec@0 {
+                       reg = <0>;
+                       compatible = "google,cros-ec";
+                       spi-max-frequency = <5000000>;
+                       ec-interrupt = <&gpio 782 1>;
+                       optimise-flash-write;
+                       status = "disabled";
+               };
+       };
+
        sound@12d60000 {
                samsung,i2s-epll-clock-frequency = <192000000>;
                samsung,i2s-sampling-rate = <48000>;
                samsung,dc-value        = <25>;
        };
 
+       cros-ec-keyb {
+               compatible = "google,cros-ec-keyb";
+               google,key-rows = <8>;
+               google,key-columns = <13>;
+               google,repeat-delay-ms = <240>;
+               google,repeat-rate-ms = <30>;
+               google,ghost-filter;
+               /*
+                * Keymap entries take the form of 0xRRCCKKKK where
+                * RR=Row CC=Column KKKK=Key Code
+                * The values below are for a US keyboard layout and
+                * are taken from the Linux driver. Note that the
+                * 102ND key is not used for US keyboards.
+                */
+               linux,keymap = <
+                       /* CAPSLCK F1         B          F10     */
+                       0x0001003a 0x0002003b 0x00030030 0x00040044
+                       /* N       =          R_ALT      ESC     */
+                       0x00060031 0x0008000d 0x000a0064 0x01010001
+                       /* F4      G          F7         H       */
+                       0x0102003e 0x01030022 0x01040041 0x01060023
+                       /* '       F9         BKSPACE    L_CTRL  */
+                       0x01080028 0x01090043 0x010b000e 0x0200001d
+                       /* TAB     F3         T          F6      */
+                       0x0201000f 0x0202003d 0x02030014 0x02040040
+                       /* ]       Y          102ND      [       */
+                       0x0205001b 0x02060015 0x02070056 0x0208001a
+                       /* F8      GRAVE      F2         5       */
+                       0x02090042 0x03010029 0x0302003c 0x03030006
+                       /* F5      6          -          \       */
+                       0x0304003f 0x03060007 0x0308000c 0x030b002b
+                       /* R_CTRL  A          D          F       */
+                       0x04000061 0x0401001e 0x04020020 0x04030021
+                       /* S       K          J          ;       */
+                       0x0404001f 0x04050025 0x04060024 0x04080027
+                       /* L       ENTER      Z          C       */
+                       0x04090026 0x040b001c 0x0501002c 0x0502002e
+                       /* V       X          ,          M       */
+                       0x0503002f 0x0504002d 0x05050033 0x05060032
+                       /* L_SHIFT /          .          SPACE   */
+                       0x0507002a 0x05080035 0x05090034 0x050B0039
+                       /* 1       3          4          2       */
+                       0x06010002 0x06020004 0x06030005 0x06040003
+                       /* 8       7          0          9       */
+                       0x06050009 0x06060008 0x0608000b 0x0609000a
+                       /* L_ALT   DOWN       RIGHT      Q       */
+                       0x060a0038 0x060b006c 0x060c006a 0x07010010
+                       /* E       R          W          I       */
+                       0x07020012 0x07030013 0x07040011 0x07050017
+                       /* U       R_SHIFT    P          O       */
+                       0x07060016 0x07070036 0x07080019 0x07090018
+                       /* UP      LEFT    */
+                       0x070b0067 0x070c0069>;
+       };
 };
index 9daa0da6143ec0051c181067d77b833c2a0407c8..be9d418265c2fda2f64928edeb542fb3d1950003 100644 (file)
@@ -87,12 +87,14 @@ lowlevel_init:
 1:
        /* for UART */
        bl uart_asm_init
+       bl arch_cpu_init
        bl tzpc_init
        pop     {pc}
 
 wakeup_reset:
        bl system_clock_init
        bl mem_ctrl_asm_init
+       bl arch_cpu_init
        bl tzpc_init
 
 exit_wakeup:
@@ -353,45 +355,3 @@ uart_asm_init:
        nop
        nop
 
-/* Setting TZPC[TrustZone Protection Controller] */
-tzpc_init:
-       ldr     r0, =TZPC0_BASE
-       mov     r1, #R0SIZE
-       str     r1, [r0]
-       mov     r1, #DECPROTXSET
-       str     r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-       ldr     r0, =TZPC1_BASE
-       str     r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-       ldr     r0, =TZPC2_BASE
-       str     r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-       ldr     r0, =TZPC3_BASE
-       str     r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-       ldr     r0, =TZPC4_BASE
-       str     r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-       ldr     r0, =TZPC5_BASE
-       str     r1, [r0, #TZPC_DECPROT0SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT1SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT2SET_OFFSET]
-       str     r1, [r0, #TZPC_DECPROT3SET_OFFSET]
-
-       mov     pc, lr
index 930b9485055693c1413524bf36a9c2b49560480d..926a4ccc2921151a09b5b9530fefece99dc27803 100644 (file)
 #define UBRDIV_OFFSET          0x28
 #define UFRACVAL_OFFSET                0x2C
 
-/* TZPC : Register Offsets */
-#define TZPC0_BASE             0x10110000
-#define TZPC1_BASE             0x10120000
-#define TZPC2_BASE             0x10130000
-#define TZPC3_BASE             0x10140000
-#define TZPC4_BASE             0x10150000
-#define TZPC5_BASE             0x10160000
-
-#define TZPC_DECPROT0SET_OFFSET        0x804
-#define TZPC_DECPROT1SET_OFFSET        0x810
-#define TZPC_DECPROT2SET_OFFSET        0x81C
-#define TZPC_DECPROT3SET_OFFSET        0x828
-
 /* CLK_SRC_CPU */
 #define MUX_HPM_SEL_MOUTAPLL           0x0
 #define MUX_HPM_SEL_SCLKMPLL           0x1
  * UBRFRACVAL = ((((800MHz*10/(115200*16) -10))%10)*16/10)
  */
 #define UFRACVAL_VAL           0x4
-
-/*
- * TZPC Register Value :
- * R0SIZE: 0x0 : Size of secured ram
- */
-#define R0SIZE                 0x0
-
-/*
- * TZPC Decode Protection Register Value :
- * DECPROTXSET: 0xFF : Set Decode region to non-secure
- */
-#define DECPROTXSET            0xFF
 #endif
index 47c6a5a46b51b805bddedd5f06ff9de33bd61e47..f2c32ee4c8777d71bfd6918b2a59d7c25c53f14f 100644 (file)
@@ -28,12 +28,15 @@ SOBJS       := lowlevel_init.o
 
 COBJS  := clock_init.o
 COBJS  += dmc_common.o dmc_init_ddr3.o
-COBJS  += tzpc_init.o
 COBJS  += smdk5250_spl.o
 
 ifndef CONFIG_SPL_BUILD
+ifdef CONFIG_OF_CONTROL
+COBJS  += exynos5-dt.o
+else
 COBJS  += smdk5250.o
 endif
+endif
 
 ifdef CONFIG_SPL_BUILD
 COBJS  += spl_boot.o
index 5b9e82fdf7bc4d2a4c3f1191fd73100b1b2889b0..b288e66f0ebef945c91fe1d5db8b426b77f5394c 100644 (file)
 #include <asm/arch/clk.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/spl.h>
+#include <asm/arch/dwmmc.h>
 
 #include "clock_init.h"
 #include "setup.h"
 
+#define FSYS1_MMC0_DIV_MASK    0xff0f
+#define FSYS1_MMC0_DIV_VAL     0x0701
+
 DECLARE_GLOBAL_DATA_PTR;
 
 struct arm_clk_ratios arm_clk_ratios[] = {
@@ -664,3 +668,17 @@ void clock_init_dp_clock(void)
        /* We run DP at 267 Mhz */
        setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1);
 }
+
+/*
+ * Set clock divisor value for booting from EMMC.
+ * Set DWMMC channel-0 clk div to operate mmc0 device at 50MHz.
+ */
+void emmc_boot_clk_div_set(void)
+{
+       struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
+       unsigned int div_mmc;
+
+       div_mmc = readl((unsigned int) &clk->div_fsys1) & ~FSYS1_MMC0_DIV_MASK;
+       div_mmc |= FSYS1_MMC0_DIV_VAL;
+       writel(div_mmc, (unsigned int) &clk->div_fsys1);
+}
index f751bcb65a6ea9f8dd16438be951a7a56a95b194..20a1d47e06de2420314f7e8e0907237e32fe3281 100644 (file)
@@ -146,4 +146,9 @@ struct mem_timings *clock_get_mem_timings(void);
  * Initialize clock for the device
  */
 void system_clock_init(void);
+
+/*
+ * Set clock divisor value for booting from EMMC.
+ */
+void emmc_boot_clk_div_set(void);
 #endif
diff --git a/board/samsung/smdk5250/exynos5-dt.c b/board/samsung/smdk5250/exynos5-dt.c
new file mode 100644 (file)
index 0000000..aacf43e
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <cros_ec.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <i2c.h>
+#include <netdev.h>
+#include <spi.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>
+#include <asm/arch/sromc.h>
+#include <power/pmic.h>
+#include <power/max77686_pmic.h>
+#include <tmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined CONFIG_EXYNOS_TMU
+/*
+ * Boot Time Thermal Analysis for SoC temperature threshold breach
+ */
+static void boot_temp_check(void)
+{
+       int temp;
+
+       switch (tmu_monitor(&temp)) {
+       /* Status TRIPPED ans WARNING means corresponding threshold breach */
+       case TMU_STATUS_TRIPPED:
+               puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n");
+               set_ps_hold_ctrl();
+               hang();
+               break;
+       case TMU_STATUS_WARNING:
+               puts("EXYNOS_TMU: WARNING! Temperature very high\n");
+               break;
+       /*
+        * TMU_STATUS_INIT means something is wrong with temperature sensing
+        * and TMU status was changed back from NORMAL to INIT.
+        */
+       case TMU_STATUS_INIT:
+       default:
+               debug("EXYNOS_TMU: Unknown TMU state\n");
+       }
+}
+#endif
+
+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;
+
+#ifdef CONFIG_USB_EHCI_EXYNOS
+int board_usb_vbus_init(void)
+{
+       struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *)
+                                               samsung_get_base_gpio_part1();
+
+       /* Enable VBUS power switch */
+       s5p_gpio_direction_output(&gpio1->x2, 6, 1);
+
+       /* VBUS turn ON time */
+       mdelay(3);
+
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_SOUND_MAX98095
+static void  board_enable_audio_codec(void)
+{
+       struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *)
+                                               samsung_get_base_gpio_part1();
+
+       /* Enable MAX98095 Codec */
+       s5p_gpio_direction_output(&gpio1->x1, 7, 1);
+       s5p_gpio_set_pull(&gpio1->x1, 7, GPIO_PULL_NONE);
+}
+#endif
+
+struct cros_ec_dev *board_get_cros_ec_dev(void)
+{
+       return local.cros_ec_dev;
+}
+
+static int board_init_cros_ec_devices(const void *blob)
+{
+       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() */
+
+       return 0;
+}
+
+int board_init(void)
+{
+       gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
+
+#if defined CONFIG_EXYNOS_TMU
+       if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) {
+               debug("%s: Failed to init TMU\n", __func__);
+               return -1;
+       }
+       boot_temp_check();
+#endif
+
+#ifdef CONFIG_EXYNOS_SPI
+       spi_init();
+#endif
+
+       if (board_init_cros_ec_devices(gd->fdt_blob))
+               return -1;
+
+#ifdef CONFIG_USB_EHCI_EXYNOS
+       board_usb_vbus_init();
+#endif
+#ifdef CONFIG_SOUND_MAX98095
+       board_enable_audio_codec();
+#endif
+       return 0;
+}
+
+int dram_init(void)
+{
+       int i;
+       u32 addr;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+               gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+       }
+       return 0;
+}
+
+#if defined(CONFIG_POWER)
+static int pmic_reg_update(struct pmic *p, int reg, uint regval)
+{
+       u32 val;
+       int ret = 0;
+
+       ret = pmic_reg_read(p, reg, &val);
+       if (ret) {
+               debug("%s: PMIC %d register read failed\n", __func__, reg);
+               return -1;
+       }
+       val |= regval;
+       ret = pmic_reg_write(p, reg, val);
+       if (ret) {
+               debug("%s: PMIC %d register write failed\n", __func__, reg);
+               return -1;
+       }
+       return 0;
+}
+
+int power_init_board(void)
+{
+       struct pmic *p;
+
+       set_ps_hold_ctrl();
+
+       i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+       if (pmic_init(I2C_PMIC))
+               return -1;
+
+       p = pmic_get("MAX77686_PMIC");
+       if (!p)
+               return -ENODEV;
+
+       if (pmic_probe(p))
+               return -1;
+
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_32KHZ, MAX77686_32KHCP_EN))
+               return -1;
+
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_BBAT,
+                           MAX77686_BBCHOSTEN | MAX77686_BBCVS_3_5V))
+               return -1;
+
+       /* VDD_MIF */
+       if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK1OUT,
+                          MAX77686_BUCK1OUT_1V)) {
+               debug("%s: PMIC %d register write failed\n", __func__,
+                     MAX77686_REG_PMIC_BUCK1OUT);
+               return -1;
+       }
+
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK1CRTL,
+                           MAX77686_BUCK1CTRL_EN))
+               return -1;
+
+       /* VDD_ARM */
+       if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK2DVS1,
+                          MAX77686_BUCK2DVS1_1_3V)) {
+               debug("%s: PMIC %d register write failed\n", __func__,
+                     MAX77686_REG_PMIC_BUCK2DVS1);
+               return -1;
+       }
+
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK2CTRL1,
+                           MAX77686_BUCK2CTRL_ON))
+               return -1;
+
+       /* VDD_INT */
+       if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK3DVS1,
+                          MAX77686_BUCK3DVS1_1_0125V)) {
+               debug("%s: PMIC %d register write failed\n", __func__,
+                     MAX77686_REG_PMIC_BUCK3DVS1);
+               return -1;
+       }
+
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK3CTRL,
+                           MAX77686_BUCK3CTRL_ON))
+               return -1;
+
+       /* VDD_G3D */
+       if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK4DVS1,
+                          MAX77686_BUCK4DVS1_1_2V)) {
+               debug("%s: PMIC %d register write failed\n", __func__,
+                     MAX77686_REG_PMIC_BUCK4DVS1);
+               return -1;
+       }
+
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK4CTRL1,
+                           MAX77686_BUCK3CTRL_ON))
+               return -1;
+
+       /* VDD_LDO2 */
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO2CTRL1,
+                           MAX77686_LD02CTRL1_1_5V | EN_LDO))
+               return -1;
+
+       /* VDD_LDO3 */
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO3CTRL1,
+                           MAX77686_LD03CTRL1_1_8V | EN_LDO))
+               return -1;
+
+       /* VDD_LDO5 */
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO5CTRL1,
+                           MAX77686_LD05CTRL1_1_8V | EN_LDO))
+               return -1;
+
+       /* VDD_LDO10 */
+       if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO10CTRL1,
+                           MAX77686_LD10CTRL1_1_8V | EN_LDO))
+               return -1;
+
+       return 0;
+}
+#endif
+
+void dram_init_banksize(void)
+{
+       int i;
+       u32 addr, size;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+               size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+
+               gd->bd->bi_dram[i].start = addr;
+               gd->bd->bi_dram[i].size = size;
+       }
+}
+
+static int decode_sromc(const void *blob, struct fdt_sromc *config)
+{
+       int err;
+       int node;
+
+       node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC);
+       if (node < 0) {
+               debug("Could not find SROMC node\n");
+               return node;
+       }
+
+       config->bank = fdtdec_get_int(blob, node, "bank", 0);
+       config->width = fdtdec_get_int(blob, node, "width", 2);
+
+       err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing,
+                       FDT_SROM_TIMING_COUNT);
+       if (err < 0) {
+               debug("Could not decode SROMC configuration Error: %s\n",
+                     fdt_strerror(err));
+               return -FDT_ERR_NOTFOUND;
+       }
+       return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_SMC911X
+       u32 smc_bw_conf, smc_bc_conf;
+       struct fdt_sromc config;
+       fdt_addr_t base_addr;
+       int node;
+
+       node = decode_sromc(gd->fdt_blob, &config);
+       if (node < 0) {
+               debug("%s: Could not find sromc configuration\n", __func__);
+               return 0;
+       }
+       node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215);
+       if (node < 0) {
+               debug("%s: Could not find lan9215 configuration\n", __func__);
+               return 0;
+       }
+
+       /* We now have a node, so any problems from now on are errors */
+       base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg");
+       if (base_addr == FDT_ADDR_T_NONE) {
+               debug("%s: Could not find lan9215 address\n", __func__);
+               return -1;
+       }
+
+       /* Ethernet needs data bus width of 16 bits */
+       if (config.width != 2) {
+               debug("%s: Unsupported bus width %d\n", __func__,
+                     config.width);
+               return -1;
+       }
+       smc_bw_conf = SROMC_DATA16_WIDTH(config.bank)
+                       | SROMC_BYTE_ENABLE(config.bank);
+
+       smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS])   |
+                       SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) |
+                       SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) |
+                       SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) |
+                       SROMC_BC_TAH(config.timing[FDT_SROM_TAH])   |
+                       SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) |
+                       SROMC_BC_PMC(config.timing[FDT_SROM_PMC]);
+
+       /* Select and configure the SROMC bank */
+       exynos_pinmux_config(PERIPH_ID_SROMC, config.bank);
+       s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf);
+       return smc911x_initialize(0, base_addr);
+#endif
+       return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+       const char *board_name;
+
+       board_name = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+       if (board_name == NULL)
+               printf("\nUnknown Board\n");
+       else
+               printf("\nBoard: %s\n", board_name);
+
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+int board_mmc_init(bd_t *bis)
+{
+       int ret;
+       /* dwmmc initializattion for available channels */
+       ret = exynos_dwmmc_init(gd->fdt_blob);
+       if (ret)
+               debug("dwmmc init failed\n");
+
+       return ret;
+}
+#endif
+
+static int board_uart_init(void)
+{
+       int err, uart_id, ret = 0;
+
+       for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
+               err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
+               if (err) {
+                       debug("UART%d not configured\n",
+                             (uart_id - PERIPH_ID_UART0));
+                       ret |= err;
+               }
+       }
+       return ret;
+}
+
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int board_early_init_f(void)
+{
+       int err;
+       err = board_uart_init();
+       if (err) {
+               debug("UART init failed\n");
+               return err;
+       }
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+       board_i2c_init(gd->fdt_blob);
+#endif
+       return err;
+}
+#endif
+
+#ifdef CONFIG_LCD
+void exynos_cfg_lcd_gpio(void)
+{
+       struct exynos5_gpio_part1 *gpio1 =
+               (struct exynos5_gpio_part1 *)samsung_get_base_gpio_part1();
+
+       /* For Backlight */
+       s5p_gpio_cfg_pin(&gpio1->b2, 0, GPIO_OUTPUT);
+       s5p_gpio_set_value(&gpio1->b2, 0, 1);
+
+       /* LCD power on */
+       s5p_gpio_cfg_pin(&gpio1->x1, 5, GPIO_OUTPUT);
+       s5p_gpio_set_value(&gpio1->x1, 5, 1);
+
+       /* Set Hotplug detect for DP */
+       s5p_gpio_cfg_pin(&gpio1->x0, 7, GPIO_FUNC(0x3));
+}
+
+void exynos_set_dp_phy(unsigned int onoff)
+{
+       set_dp_phy_ctrl(onoff);
+}
+#endif
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+       stdio_print_current_devices();
+
+       if (local.cros_ec_err) {
+               /* Force console on */
+               gd->flags &= ~GD_FLG_SILENT;
+
+               printf("cros-ec communications failure %d\n",
+                      local.cros_ec_err);
+               puts("\nPlease reset with Power+Refresh\n\n");
+               panic("Cannot init cros-ec device");
+               return -1;
+       }
+       return 0;
+}
+#endif
index bc6cb6f7386790db6395387ff9d496d919a87a4a..edc565ef723c11f390b2092f82fadf0678846401 100644 (file)
@@ -75,12 +75,14 @@ lowlevel_init:
        bl      mem_ctrl_init
 
 1:
+       bl      arch_cpu_init
        bl      tzpc_init
        ldmia   r13!, {ip,pc}
 
 wakeup_reset:
        bl      system_clock_init
        bl      mem_ctrl_init
+       bl      arch_cpu_init
        bl      tzpc_init
 
 exit_wakeup:
index 34d8bc31f4dea5503fd596dc433f598a87e24521..eb91d131092526a7af038ee29611775b9f8b39ab 100644 (file)
 #include <config.h>
 #include <asm/arch/dmc.h>
 
-/* TZPC : Register Offsets */
-#define TZPC0_BASE             0x10100000
-#define TZPC1_BASE             0x10110000
-#define TZPC2_BASE             0x10120000
-#define TZPC3_BASE             0x10130000
-#define TZPC4_BASE             0x10140000
-#define TZPC5_BASE             0x10150000
-#define TZPC6_BASE             0x10160000
-#define TZPC7_BASE             0x10170000
-#define TZPC8_BASE             0x10180000
-#define TZPC9_BASE             0x10190000
-
 /* APLL_CON1   */
 #define APLL_CON1_VAL  (0x00203800)
 
 /* CLK_GATE_IP_DISP1 */
 #define CLK_GATE_DP1_ALLOW     (1 << 4)
 
-/*
- * TZPC Register Value :
- * R0SIZE: 0x0 : Size of secured ram
- */
-#define R0SIZE                 0x0
-
-/*
- * TZPC Decode Protection Register Value :
- * DECPROTXSET: 0xFF : Set Decode region to non-secure
- */
-#define DECPROTXSET            0xFF
-
 #define DDR3PHY_CTRL_PHY_RESET (1 << 0)
 #define DDR3PHY_CTRL_PHY_RESET_OFF     (0 << 0)
 
@@ -590,5 +566,4 @@ void update_reset_dll(struct exynos5_dmc *, enum ddr_mode);
 void sdelay(unsigned long);
 void mem_ctrl_init(void);
 void system_clock_init(void);
-void tzpc_init(void);
 #endif
index 8b09e1de42f27f7bc5a271e39b6694f7cf47f37e..276fd413285c5c518822ac92b899f79e564af757 100644 (file)
@@ -29,6 +29,7 @@
 #include <netdev.h>
 #include <spi.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/dp_info.h>
 #include <power/pmic.h>
 #include <power/max77686_pmic.h>
-#include <tmu.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if defined CONFIG_EXYNOS_TMU
-/*
- * Boot Time Thermal Analysis for SoC temperature threshold breach
- */
-static void boot_temp_check(void)
-{
-       int temp;
-
-       switch (tmu_monitor(&temp)) {
-       /* Status TRIPPED ans WARNING means corresponding threshold breach */
-       case TMU_STATUS_TRIPPED:
-               puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n");
-               set_ps_hold_ctrl();
-               hang();
-               break;
-       case TMU_STATUS_WARNING:
-               puts("EXYNOS_TMU: WARNING! Temperature very high\n");
-               break;
-       /*
-        * TMU_STATUS_INIT means something is wrong with temperature sensing
-        * and TMU status was changed back from NORMAL to INIT.
-        */
-       case TMU_STATUS_INIT:
-       default:
-               debug("EXYNOS_TMU: Unknown TMU state\n");
-       }
-}
-#endif
-
 #ifdef CONFIG_USB_EHCI_EXYNOS
 int board_usb_vbus_init(void)
 {
@@ -102,14 +73,6 @@ int board_init(void)
 {
        gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
 
-#if defined CONFIG_EXYNOS_TMU
-       if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) {
-               debug("%s: Failed to init TMU\n", __func__);
-               return -1;
-       }
-       boot_temp_check();
-#endif
-
 #ifdef CONFIG_EXYNOS_SPI
        spi_init();
 #endif
@@ -124,14 +87,13 @@ int board_init(void)
 
 int dram_init(void)
 {
-       gd->ram_size    = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_3, PHYS_SDRAM_3_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_4, PHYS_SDRAM_4_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_5, PHYS_SDRAM_7_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_6, PHYS_SDRAM_7_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_7, PHYS_SDRAM_7_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_8, PHYS_SDRAM_8_SIZE);
+       int i;
+       u32 addr;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+               gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+       }
        return 0;
 }
 
@@ -254,57 +216,15 @@ int power_init_board(void)
 
 void dram_init_banksize(void)
 {
-       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
-       gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1,
-                                                       PHYS_SDRAM_1_SIZE);
-       gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
-       gd->bd->bi_dram[1].size = get_ram_size((long *)PHYS_SDRAM_2,
-                                                       PHYS_SDRAM_2_SIZE);
-       gd->bd->bi_dram[2].start = PHYS_SDRAM_3;
-       gd->bd->bi_dram[2].size = get_ram_size((long *)PHYS_SDRAM_3,
-                                                       PHYS_SDRAM_3_SIZE);
-       gd->bd->bi_dram[3].start = PHYS_SDRAM_4;
-       gd->bd->bi_dram[3].size = get_ram_size((long *)PHYS_SDRAM_4,
-                                                       PHYS_SDRAM_4_SIZE);
-       gd->bd->bi_dram[4].start = PHYS_SDRAM_5;
-       gd->bd->bi_dram[4].size = get_ram_size((long *)PHYS_SDRAM_5,
-                                                       PHYS_SDRAM_5_SIZE);
-       gd->bd->bi_dram[5].start = PHYS_SDRAM_6;
-       gd->bd->bi_dram[5].size = get_ram_size((long *)PHYS_SDRAM_6,
-                                                       PHYS_SDRAM_6_SIZE);
-       gd->bd->bi_dram[6].start = PHYS_SDRAM_7;
-       gd->bd->bi_dram[6].size = get_ram_size((long *)PHYS_SDRAM_7,
-                                                       PHYS_SDRAM_7_SIZE);
-       gd->bd->bi_dram[7].start = PHYS_SDRAM_8;
-       gd->bd->bi_dram[7].size = get_ram_size((long *)PHYS_SDRAM_8,
-                                                       PHYS_SDRAM_8_SIZE);
-}
-
-#ifdef CONFIG_OF_CONTROL
-static int decode_sromc(const void *blob, struct fdt_sromc *config)
-{
-       int err;
-       int node;
-
-       node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC);
-       if (node < 0) {
-               debug("Could not find SROMC node\n");
-               return node;
-       }
-
-       config->bank = fdtdec_get_int(blob, node, "bank", 0);
-       config->width = fdtdec_get_int(blob, node, "width", 2);
-
-       err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing,
-                       FDT_SROM_TIMING_COUNT);
-       if (err < 0) {
-               debug("Could not decode SROMC configuration\n");
-               return -FDT_ERR_NOTFOUND;
+       int i;
+       u32 addr, size;
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+               size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+               gd->bd->bi_dram[i].start = addr;
+               gd->bd->bi_dram[i].size = size;
        }
-
-       return 0;
 }
-#endif
 
 int board_eth_init(bd_t *bis)
 {
@@ -313,27 +233,6 @@ int board_eth_init(bd_t *bis)
        struct fdt_sromc config;
        fdt_addr_t base_addr;
 
-#ifdef CONFIG_OF_CONTROL
-       int node;
-
-       node = decode_sromc(gd->fdt_blob, &config);
-       if (node < 0) {
-               debug("%s: Could not find sromc configuration\n", __func__);
-               return 0;
-       }
-       node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215);
-       if (node < 0) {
-               debug("%s: Could not find lan9215 configuration\n", __func__);
-               return 0;
-       }
-
-       /* We now have a node, so any problems from now on are errors */
-       base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg");
-       if (base_addr == FDT_ADDR_T_NONE) {
-               debug("%s: Could not find lan9215 address\n", __func__);
-               return -1;
-       }
-#else
        /* Non-FDT configuration - bank number and timing parameters*/
        config.bank = CONFIG_ENV_SROM_BANK;
        config.width = 2;
@@ -346,7 +245,6 @@ int board_eth_init(bd_t *bis)
        config.timing[FDT_SROM_TACP] = 0x09;
        config.timing[FDT_SROM_PMC] = 0x01;
        base_addr = CONFIG_SMC911X_BASE;
-#endif
 
        /* Ethernet needs data bus width of 16 bits */
        if (config.width != 2) {
@@ -376,17 +274,7 @@ int board_eth_init(bd_t *bis)
 #ifdef CONFIG_DISPLAY_BOARDINFO
 int checkboard(void)
 {
-#ifdef CONFIG_OF_CONTROL
-       const char *board_name;
-
-       board_name = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
-       if (board_name == NULL)
-               printf("\nUnknown Board\n");
-       else
-               printf("\nBoard: %s\n", board_name);
-#else
        printf("\nBoard: SMDK5250\n");
-#endif
        return 0;
 }
 #endif
@@ -394,48 +282,54 @@ int checkboard(void)
 #ifdef CONFIG_GENERIC_MMC
 int board_mmc_init(bd_t *bis)
 {
-       int err;
+       int err, ret = 0, index, bus_width;
+       u32 base;
 
        err = exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE);
-       if (err) {
+       if (err)
                debug("SDMMC0 not configured\n");
-               return err;
-       }
-
-       err = s5p_mmc_init(0, 8);
-       return err;
+       ret |= err;
+
+       /*EMMC: dwmmc Channel-0 with 8 bit bus width */
+       index = 0;
+       base =  samsung_get_base_mmc() + (0x10000 * index);
+       bus_width = 8;
+       err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL);
+       if (err)
+               debug("dwmmc Channel-0 init failed\n");
+       ret |= err;
+
+       err = exynos_pinmux_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE);
+       if (err)
+               debug("SDMMC2 not configured\n");
+       ret |= err;
+
+       /*SD: dwmmc Channel-2 with 4 bit bus width */
+       index = 2;
+       base = samsung_get_base_mmc() + (0x10000 * index);
+       bus_width = 4;
+       err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL);
+       if (err)
+               debug("dwmmc Channel-2 init failed\n");
+       ret |= err;
+
+       return ret;
 }
 #endif
 
 static int board_uart_init(void)
 {
-       int err;
-
-       err = exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE);
-       if (err) {
-               debug("UART0 not configured\n");
-               return err;
+       int err, uart_id, ret = 0;
+
+       for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
+               err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
+               if (err) {
+                       debug("UART%d not configured\n",
+                             (uart_id - PERIPH_ID_UART0));
+                       ret |= err;
+               }
        }
-
-       err = exynos_pinmux_config(PERIPH_ID_UART1, PINMUX_FLAG_NONE);
-       if (err) {
-               debug("UART1 not configured\n");
-               return err;
-       }
-
-       err = exynos_pinmux_config(PERIPH_ID_UART2, PINMUX_FLAG_NONE);
-       if (err) {
-               debug("UART2 not configured\n");
-               return err;
-       }
-
-       err = exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
-       if (err) {
-               debug("UART3 not configured\n");
-               return err;
-       }
-
-       return 0;
+       return ret;
 }
 
 #ifdef CONFIG_BOARD_EARLY_INIT_F
@@ -448,7 +342,7 @@ int board_early_init_f(void)
                return err;
        }
 #ifdef CONFIG_SYS_I2C_INIT_BOARD
-       board_i2c_init(gd->fdt_blob);
+       board_i2c_init(NULL);
 #endif
        return err;
 }
@@ -477,7 +371,6 @@ void exynos_set_dp_phy(unsigned int onoff)
        set_dp_phy_ctrl(onoff);
 }
 
-#ifndef CONFIG_OF_CONTROL
 vidinfo_t panel_info = {
        .vl_freq        = 60,
        .vl_col         = 2560,
@@ -543,13 +436,9 @@ static struct exynos_dp_platform_data dp_platform_data = {
        .edp_dev_info   = &edp_info,
 };
 
-#endif
 void init_panel_info(vidinfo_t *vid)
 {
-#ifndef CONFIG_OF_CONTROL
-       vid->rgb_mode   = MODE_RGB_P,
-
+       vid->rgb_mode   = MODE_RGB_P;
        exynos_set_dp_platform_data(&dp_platform_data);
-#endif
 }
 #endif
index c0bcf460f156abf7f431928b7926fba799278c1c..98f2286f9efac619c16ba5ab162ac4aa6fb0a308 100644 (file)
 #include<common.h>
 #include<config.h>
 
+#include <asm/arch-exynos/dmc.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/clk.h>
+
+#include "clock_init.h"
+
+/* Index into irom ptr table */
+enum index {
+       MMC_INDEX,
+       EMMC44_INDEX,
+       EMMC44_END_INDEX,
+       SPI_INDEX,
+       USB_INDEX,
+};
+
+/* IROM Function Pointers Table */
+u32 irom_ptr_table[] = {
+       [MMC_INDEX] = 0x02020030,       /* iROM Function Pointer-SDMMC boot */
+       [EMMC44_INDEX] = 0x02020044,    /* iROM Function Pointer-EMMC4.4 boot*/
+       [EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer
+                                               -EMMC4.4 end boot operation */
+       [SPI_INDEX] = 0x02020058,       /* iROM Function Pointer-SPI boot */
+       [USB_INDEX] = 0x02020070,       /* iROM Function Pointer-USB boot*/
+       };
+
 enum boot_mode {
        BOOT_MODE_MMC = 4,
        BOOT_MODE_SERIAL = 20,
+       BOOT_MODE_EMMC = 8,     /* EMMC4.4 */
        /* Boot based on Operating Mode pin settings */
        BOOT_MODE_OM = 32,
        BOOT_MODE_USB,  /* Boot using USB download */
 };
 
-       typedef u32 (*spi_copy_func_t)(u32 offset, u32 nblock, u32 dst);
-       typedef u32 (*usb_copy_func_t)(void);
+void *get_irom_func(int index)
+{
+       return (void *)*(u32 *)irom_ptr_table[index];
+}
 
 /*
  * Set/clear program flow prediction and return the previous state.
@@ -55,13 +83,15 @@ static int config_branch_prediction(int set_cr_z)
 */
 void copy_uboot_to_ram(void)
 {
-       spi_copy_func_t spi_copy;
-       usb_copy_func_t usb_copy;
-
        int is_cr_z_set;
        unsigned int sec_boot_check;
        enum boot_mode bootmode = BOOT_MODE_OM;
-       u32 (*copy_bl2)(u32, u32, u32);
+
+       u32 (*spi_copy)(u32 offset, u32 nblock, u32 dst);
+       u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst);
+       u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst);
+       void (*end_bootop_from_emmc)(void);
+       u32 (*usb_copy)(void);
 
        /* Read iRAM location to check for secondary USB boot mode */
        sec_boot_check = readl(EXYNOS_IRAM_SECONDARY_BASE);
@@ -73,14 +103,24 @@ void copy_uboot_to_ram(void)
 
        switch (bootmode) {
        case BOOT_MODE_SERIAL:
-               spi_copy = *(spi_copy_func_t *)EXYNOS_COPY_SPI_FNPTR_ADDR;
+               spi_copy = get_irom_func(SPI_INDEX);
                spi_copy(SPI_FLASH_UBOOT_POS, CONFIG_BL2_SIZE,
-                                               CONFIG_SYS_TEXT_BASE);
+                        CONFIG_SYS_TEXT_BASE);
                break;
        case BOOT_MODE_MMC:
-               copy_bl2 = (void *) *(u32 *)COPY_BL2_FNPTR_ADDR;
+               copy_bl2 = get_irom_func(MMC_INDEX);
                copy_bl2(BL2_START_OFFSET, BL2_SIZE_BLOC_COUNT,
-                                               CONFIG_SYS_TEXT_BASE);
+                        CONFIG_SYS_TEXT_BASE);
+               break;
+       case BOOT_MODE_EMMC:
+               /* Set the FSYS1 clock divisor value for EMMC boot */
+               emmc_boot_clk_div_set();
+
+               copy_bl2_from_emmc = get_irom_func(EMMC44_INDEX);
+               end_bootop_from_emmc = get_irom_func(EMMC44_END_INDEX);
+
+               copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE);
+               end_bootop_from_emmc();
                break;
        case BOOT_MODE_USB:
                /*
@@ -88,8 +128,7 @@ void copy_uboot_to_ram(void)
                 * before copy from USB device to RAM
                 */
                is_cr_z_set = config_branch_prediction(0);
-               usb_copy = *(usb_copy_func_t *)
-                               EXYNOS_COPY_USB_FNPTR_ADDR;
+               usb_copy = get_irom_func(USB_INDEX);
                usb_copy();
                config_branch_prediction(is_cr_z_set);
                break;
@@ -117,5 +156,4 @@ void board_init_r(gd_t *id, ulong dest_addr)
        while (1)
                ;
 }
-
 void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {}
index 7a1ea98aed74f4d16056e26a42993c162fc167d7..31e0e2edaf1477070db420293894028e72f65cec 100644 (file)
@@ -85,12 +85,14 @@ lowlevel_init:
 1:
        /* for UART */
        bl uart_asm_init
+       bl arch_cpu_init
        bl tzpc_init
        pop     {pc}
 
 wakeup_reset:
        bl system_clock_init
        bl mem_ctrl_asm_init
+       bl arch_cpu_init
        bl tzpc_init
 
 exit_wakeup:
@@ -410,61 +412,3 @@ uart_asm_init:
        nop
        nop
        nop
-
-/* Setting TZPC[TrustZone Protection Controller] */
-tzpc_init:
-       ldr     r0, =0x10110000
-       mov     r1, #0x0
-       str     r1, [r0]
-       mov     r1, #0xff
-       str     r1, [r0, #0x0804]
-       str     r1, [r0, #0x0810]
-       str     r1, [r0, #0x081C]
-       str     r1, [r0, #0x0828]
-
-       ldr     r0, =0x10120000
-       mov     r1, #0x0
-       str     r1, [r0]
-       mov     r1, #0xff
-       str     r1, [r0, #0x0804]
-       str     r1, [r0, #0x0810]
-       str     r1, [r0, #0x081C]
-       str     r1, [r0, #0x0828]
-
-       ldr     r0, =0x10130000
-       mov     r1, #0x0
-       str     r1, [r0]
-       mov     r1, #0xff
-       str     r1, [r0, #0x0804]
-       str     r1, [r0, #0x0810]
-       str     r1, [r0, #0x081C]
-       str     r1, [r0, #0x0828]
-
-       ldr     r0, =0x10140000
-       mov     r1, #0x0
-       str     r1, [r0]
-       mov     r1, #0xff
-       str     r1, [r0, #0x0804]
-       str     r1, [r0, #0x0810]
-       str     r1, [r0, #0x081C]
-       str     r1, [r0, #0x0828]
-
-       ldr     r0, =0x10150000
-       mov     r1, #0x0
-       str     r1, [r0]
-       mov     r1, #0xff
-       str     r1, [r0, #0x0804]
-       str     r1, [r0, #0x0810]
-       str     r1, [r0, #0x081C]
-       str     r1, [r0, #0x0828]
-
-       ldr     r0, =0x10160000
-       mov     r1, #0x0
-       str     r1, [r0]
-       mov     r1, #0xff
-       str     r1, [r0, #0x0804]
-       str     r1, [r0, #0x0810]
-       str     r1, [r0, #0x081C]
-       str     r1, [r0, #0x0828]
-
-       mov     pc, lr
index 638cc4d68b2ad5238443c6c180f378e66278b826..fdbe26cde116b81e0bf7e1c41d233cd3d36e5f87 100644 (file)
@@ -38,9 +38,6 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-#ifdef CONFIG_SPL_BUILD
-static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
-#endif
 
 /* MII mode defines */
 #define MII_MODE_ENABLE                0x0
@@ -126,28 +123,7 @@ static int read_eeprom(void)
        return 0;
 }
 
-/* UART Defines */
 #ifdef CONFIG_SPL_BUILD
-#define UART_RESET             (0x1 << 1)
-#define UART_CLK_RUNNING_MASK  0x1
-#define UART_SMART_IDLE_EN     (0x1 << 0x3)
-
-static void rtc32k_enable(void)
-{
-       struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
-
-       /*
-        * Unlock the RTC's registers.  For more details please see the
-        * RTC_SS section of the TRM.  In order to unlock we need to
-        * write these specific values (keys) in this order.
-        */
-       writel(0x83e70b13, &rtc->kick0r);
-       writel(0x95a4f1e0, &rtc->kick1r);
-
-       /* Enable the RTC 32K OSC by setting bits 3 and 6. */
-       writel((1 << 3) | (1 << 6), &rtc->osc);
-}
-
 static const struct ddr_data ddr2_data = {
        .datardsratio0 = ((MT47H128M16RT25E_RD_DQS<<30) |
                          (MT47H128M16RT25E_RD_DQS<<20) |
@@ -339,9 +315,6 @@ void s_init(void)
        /* Enable RTC32K clock */
        rtc32k_enable();
 
-       /* UART softreset */
-       u32 regVal;
-
 #ifdef CONFIG_SERIAL1
        enable_uart0_pin_mux();
 #endif /* CONFIG_SERIAL1 */
@@ -361,17 +334,7 @@ void s_init(void)
        enable_uart5_pin_mux();
 #endif /* CONFIG_SERIAL6 */
 
-       regVal = readl(&uart_base->uartsyscfg);
-       regVal |= UART_RESET;
-       writel(regVal, &uart_base->uartsyscfg);
-       while ((readl(&uart_base->uartsyssts) &
-               UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
-               ;
-
-       /* Disable smart idle */
-       regVal = readl(&uart_base->uartsyscfg);
-       regVal |= UART_SMART_IDLE_EN;
-       writel(regVal, &uart_base->uartsyscfg);
+       uart_soft_reset();
 
        gd = &gdata;
 
index 90ae29e7c64bc761b0a5b0a2993cf44ecf6db882..1da5b359c020d660d99816790e9b74922abcdd6e 100644 (file)
 #endif
 
 #define PANDA_ULPI_PHY_TYPE_GPIO       182
+#define PANDA_BOARD_ID_1_GPIO          101
+#define PANDA_ES_BOARD_ID_1_GPIO        48
+#define PANDA_BOARD_ID_2_GPIO          171
+#define PANDA_ES_BOARD_ID_3_GPIO         3
+#define PANDA_ES_BOARD_ID_4_GPIO         2
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -66,6 +71,73 @@ int board_eth_init(bd_t *bis)
        return 0;
 }
 
+/*
+* Routine: get_board_revision
+* Description: Detect if we are running on a panda revision A1-A6,
+*              or an ES panda board. This can be done by reading
+*              the level of GPIOs and checking the processor revisions.
+*              This should result in:
+*                      Panda 4430:
+*              GPIO171, GPIO101, GPIO182: 0 1 1 => A1-A5
+*              GPIO171, GPIO101, GPIO182: 1 0 1 => A6
+*                      Panda ES:
+*              GPIO2, GPIO3, GPIO171, GPIO48, GPIO182: 0 0 0 1 1 => B1/B2
+*              GPIO2, GPIO3, GPIO171, GPIO48, GPIO182: 0 0 1 1 1 => B3
+*/
+int get_board_revision(void)
+{
+       int board_id0, board_id1, board_id2;
+       int board_id3, board_id4;
+       int board_id;
+
+       int processor_rev = omap_revision();
+
+       /* Setup the mux for the common board ID pins (gpio 171 and 182) */
+       writew((IEN | M3), (*ctrl)->control_padconf_core_base + UNIPRO_TX0);
+       writew((IEN | M3), (*ctrl)->control_padconf_core_base + FREF_CLK2_OUT);
+
+       board_id0 = gpio_get_value(PANDA_ULPI_PHY_TYPE_GPIO);
+       board_id2 = gpio_get_value(PANDA_BOARD_ID_2_GPIO);
+
+       if ((processor_rev >= OMAP4460_ES1_0 &&
+            processor_rev <= OMAP4460_ES1_1)) {
+               /*
+                * Setup the mux for the ES specific board ID pins (gpio 101,
+                * 2 and 3.
+                */
+               writew((IEN | M3), (*ctrl)->control_padconf_core_base +
+                               GPMC_A24);
+               writew((IEN | M3), (*ctrl)->control_padconf_core_base +
+                               UNIPRO_RY0);
+               writew((IEN | M3), (*ctrl)->control_padconf_core_base +
+                               UNIPRO_RX1);
+
+               board_id1 = gpio_get_value(PANDA_ES_BOARD_ID_1_GPIO);
+               board_id3 = gpio_get_value(PANDA_ES_BOARD_ID_3_GPIO);
+               board_id4 = gpio_get_value(PANDA_ES_BOARD_ID_4_GPIO);
+
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+               setenv("board_name", strcat(CONFIG_SYS_BOARD, "-es"));
+#endif
+               board_id = ((board_id4 << 4) | (board_id3 << 3) |
+                       (board_id2 << 2) | (board_id1 << 1) | (board_id0));
+       } else {
+               /* Setup the mux for the Ax specific board ID pins (gpio 101) */
+               writew((IEN | M3), (*ctrl)->control_padconf_core_base +
+                               FREF_CLK2_OUT);
+
+               board_id1 = gpio_get_value(PANDA_BOARD_ID_1_GPIO);
+               board_id = ((board_id2 << 2) | (board_id1 << 1) | (board_id0));
+
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+               if ((board_id >= 0x3) && (processor_rev == OMAP4430_ES2_3))
+                       setenv("board_name", strcat(CONFIG_SYS_BOARD, "-a4"));
+#endif
+       }
+
+       return board_id;
+}
+
 /**
  * @brief misc_init_r - Configure Panda board specific configurations
  * such as power configurations, ethernet initialization as phase2 of
@@ -82,11 +154,7 @@ int misc_init_r(void)
        if (omap_revision() == OMAP4430_ES1_0)
                return 0;
 
-#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
-       if (omap_revision() >= OMAP4460_ES1_0 ||
-               omap_revision() <= OMAP4460_ES1_1)
-               setenv("board_name", strcat(CONFIG_SYS_BOARD, "-es"));
-#endif
+       get_board_revision();
 
        gpio_direction_input(PANDA_ULPI_PHY_TYPE_GPIO);
        phy_type = gpio_get_value(PANDA_ULPI_PHY_TYPE_GPIO);
@@ -106,7 +174,7 @@ int misc_init_r(void)
                auxclk |= AUXCLK_ENABLE_MASK;
 
                writel(auxclk, &scrm->auxclk3);
-       } else {
+       } else {
                /* ULPI PHY supplied by auxclk1 derived from PER dpll */
                debug("ULPI PHY supplied by auxclk1\n");
 
@@ -151,9 +219,9 @@ void set_muxconf_regs_essential(void)
 
        if (omap_revision() >= OMAP4460_ES1_0)
                do_set_mux((*ctrl)->control_padconf_wkup_base,
-                                wkup_padconf_array_essential_4460,
-                                sizeof(wkup_padconf_array_essential_4460) /
-                                sizeof(struct pad_conf_entry));
+                          wkup_padconf_array_essential_4460,
+                          sizeof(wkup_padconf_array_essential_4460) /
+                          sizeof(struct pad_conf_entry));
 }
 
 void set_muxconf_regs_non_essential(void)
@@ -165,14 +233,14 @@ void set_muxconf_regs_non_essential(void)
 
        if (omap_revision() < OMAP4460_ES1_0)
                do_set_mux((*ctrl)->control_padconf_core_base,
-                               core_padconf_array_non_essential_4430,
-                               sizeof(core_padconf_array_non_essential_4430) /
-                               sizeof(struct pad_conf_entry));
+                          core_padconf_array_non_essential_4430,
+                          sizeof(core_padconf_array_non_essential_4430) /
+                          sizeof(struct pad_conf_entry));
        else
                do_set_mux((*ctrl)->control_padconf_core_base,
-                               core_padconf_array_non_essential_4460,
-                               sizeof(core_padconf_array_non_essential_4460) /
-                               sizeof(struct pad_conf_entry));
+                          core_padconf_array_non_essential_4460,
+                          sizeof(core_padconf_array_non_essential_4460) /
+                          sizeof(struct pad_conf_entry));
 
        do_set_mux((*ctrl)->control_padconf_wkup_base,
                   wkup_padconf_array_non_essential,
@@ -181,9 +249,9 @@ void set_muxconf_regs_non_essential(void)
 
        if (omap_revision() < OMAP4460_ES1_0)
                do_set_mux((*ctrl)->control_padconf_wkup_base,
-                               wkup_padconf_array_non_essential_4430,
-                               sizeof(wkup_padconf_array_non_essential_4430) /
-                               sizeof(struct pad_conf_entry));
+                          wkup_padconf_array_non_essential_4430,
+                          sizeof(wkup_padconf_array_non_essential_4430) /
+                          sizeof(struct pad_conf_entry));
 }
 
 #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_GENERIC_MMC)
index 4759b167a46ab2f51d55c0b92fa41e599627c2bd..6ad3dd8fc74adf6e910abd68ca476ec4af4b4409 100644 (file)
@@ -37,49 +37,16 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef CONFIG_SPL_BUILD
 static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
-static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
 #endif
 
 static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
 
 /* UART Defines */
 #ifdef CONFIG_SPL_BUILD
-#define UART_RESET             (0x1 << 1)
-#define UART_CLK_RUNNING_MASK  0x1
-#define UART_SMART_IDLE_EN     (0x1 << 0x3)
-
-static void rtc32k_enable(void)
-{
-       struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE;
-
-       /*
-        * Unlock the RTC's registers.  For more details please see the
-        * RTC_SS section of the TRM.  In order to unlock we need to
-        * write these specific values (keys) in this order.
-        */
-       writel(0x83e70b13, &rtc->kick0r);
-       writel(0x95a4f1e0, &rtc->kick1r);
-
-       /* Enable the RTC 32K OSC by setting bits 3 and 6. */
-       writel((1 << 3) | (1 << 6), &rtc->osc);
-}
-
 static void uart_enable(void)
 {
-       u32 regVal;
-
        /* UART softreset */
-       regVal = readl(&uart_base->uartsyscfg);
-       regVal |= UART_RESET;
-       writel(regVal, &uart_base->uartsyscfg);
-       while ((readl(&uart_base->uartsyssts) &
-               UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK)
-               ;
-
-       /* Disable smart idle */
-       regVal = readl(&uart_base->uartsyscfg);
-       regVal |= UART_SMART_IDLE_EN;
-       writel(regVal, &uart_base->uartsyscfg);
+       uart_soft_reset();
 }
 
 static void wdt_disable(void)
index 61d1154aff6a598582fd7f024db3ae50567ce87c..1a3ef9285f6052772416ee72a140af587103a713 100644 (file)
@@ -67,11 +67,6 @@ SECTIONS
                __rel_dyn_end = .;
        }
 
-       .dynsym : {
-               __dynsym_start = .;
-               *(.dynsym)
-       }
-
        . = ALIGN(0x800);
 
        _end = .;
@@ -84,6 +79,7 @@ SECTIONS
        }
 
        /DISCARD/ : { *(.bss*) }
+       /DISCARD/ : { *(.dynsym) }
        /DISCARD/ : { *(.dynstr*) }
        /DISCARD/ : { *(.dynsym*) }
        /DISCARD/ : { *(.dynamic*) }
index 1e598cb7e2f17a0c01234a9f40e4d1eda349353e..c0c428262b2f1d8f57f46cf63724d041f6a4958d 100644 (file)
@@ -831,6 +831,7 @@ P1022DS_36BIT_SPIFLASH       powerpc     mpc85xx     p1022ds             freesca
 P1022DS_SDCARD               powerpc     mpc85xx     p1022ds             freescale     -           P1022DS:SDCARD
 P1022DS_36BIT_SDCARD         powerpc     mpc85xx     p1022ds             freescale     -           P1022DS:36BIT,SDCARD
 P1022DS_36BIT                powerpc     mpc85xx     p1022ds             freescale      -           P1022DS:36BIT
+P1023RDB                     powerpc     mpc85xx     p1023rdb            freescale      -           P1023RDB
 P1023RDS                     powerpc     mpc85xx     p1023rds            freescale      -           P1023RDS
 P1023RDS_NAND                powerpc     mpc85xx     p1023rds            freescale      -           P1023RDS:NAND
 P1024RDB                     powerpc     mpc85xx     p1_p2_rdb_pc        freescale      -           p1_p2_rdb_pc:P1024RDB
@@ -900,8 +901,13 @@ P5040DS_NAND                    powerpc     mpc85xx     corenet_ds          freescale      -
 P5040DS_SDCARD              powerpc     mpc85xx     corenet_ds          freescale      -           P5040DS:RAMBOOT_PBL,SDCARD,SYS_TEXT_BASE=0xFFF80000
 P5040DS_SPIFLASH            powerpc     mpc85xx     corenet_ds          freescale      -           P5040DS:RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
 BSC9131RDB_SPIFLASH          powerpc     mpc85xx     bsc9131rdb          freescale      -           BSC9131RDB:BSC9131RDB,SPIFLASH
+BSC9131RDB_SPIFLASH_SYSCLK100 powerpc     mpc85xx     bsc9131rdb          freescale      -           BSC9131RDB:BSC9131RDB,SPIFLASH,SYS_CLK_100
+BSC9131RDB_NAND              powerpc     mpc85xx     bsc9131rdb          freescale      -           BSC9131RDB:BSC9131RDB,NAND
+BSC9131RDB_NAND_SYSCLK100    powerpc     mpc85xx     bsc9131rdb          freescale      -           BSC9131RDB:BSC9131RDB,NAND,SYS_CLK_100
 BSC9132QDS_NOR_DDRCLK100     powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SYS_CLK_100_DDR_100
 BSC9132QDS_NOR_DDRCLK133     powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SYS_CLK_100_DDR_133
+BSC9132QDS_NAND_DDRCLK100    powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,NAND,SYS_CLK_100_DDR_100
+BSC9132QDS_NAND_DDRCLK133    powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,NAND,SYS_CLK_100_DDR_133
 BSC9132QDS_SDCARD_DDRCLK100  powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SDCARD,SYS_CLK_100_DDR_100
 BSC9132QDS_SDCARD_DDRCLK133  powerpc     mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SDCARD,SYS_CLK_100_DDR_133
 BSC9132QDS_SPIFLASH_DDRCLK100 powerpc    mpc85xx     bsc9132qds          freescale      -           BSC9132QDS:BSC9132QDS,SPIFLASH,SYS_CLK_100_DDR_100
@@ -912,12 +918,14 @@ stxssa_4M                    powerpc     mpc85xx     stxssa              stx
 T4240QDS                     powerpc     mpc85xx     t4qds               freescale      -           T4240QDS:PPC_T4240
 T4240QDS_SDCARD              powerpc     mpc85xx     t4qds               freescale     -           T4240QDS:PPC_T4240,RAMBOOT_PBL,SDCARD,SYS_TEXT_BASE=0xFFF80000
 T4240QDS_SPIFLASH            powerpc     mpc85xx     t4qds               freescale     -           T4240QDS:PPC_T4240,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
+T4240QDS_SRIO_PCIE_BOOT             powerpc     mpc85xx     t4qds               freescale      -           T4240QDS:PPC_T4240,SRIO_PCIE_BOOT_SLAVE,SYS_TEXT_BASE=0xFFF80000
 T4160QDS                     powerpc     mpc85xx     t4qds               freescale      -           T4240QDS:PPC_T4160
 T4160QDS_SDCARD              powerpc     mpc85xx     t4qds               freescale     -           T4240QDS:PPC_T4160,RAMBOOT_PBL,SDCARD,SYS_TEXT_BASE=0xFFF80000
 T4160QDS_SPIFLASH            powerpc     mpc85xx     t4qds               freescale     -           T4240QDS:PPC_T4160,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
 B4860QDS                     powerpc     mpc85xx     b4860qds            freescale      -           B4860QDS:PPC_B4860
 B4860QDS_NAND               powerpc     mpc85xx     b4860qds            freescale      -           B4860QDS:PPC_B4860,RAMBOOT_PBL,NAND,SYS_TEXT_BASE=0xFFF80000
 B4860QDS_SPIFLASH            powerpc     mpc85xx     b4860qds            freescale     -           B4860QDS:PPC_B4860,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
+B4860QDS_SRIO_PCIE_BOOT             powerpc     mpc85xx     b4860qds            freescale      -           B4860QDS:PPC_B4860,SRIO_PCIE_BOOT_SLAVE,SYS_TEXT_BASE=0xFFF80000
 B4420QDS                     powerpc     mpc85xx     b4860qds            freescale     -           B4860QDS:PPC_B4420
 B4420QDS_NAND               powerpc     mpc85xx     b4860qds            freescale      -           B4860QDS:PPC_B4420,RAMBOOT_PBL,NAND,SYS_TEXT_BASE=0xFFF80000
 B4420QDS_SPIFLASH            powerpc     mpc85xx     b4860qds            freescale     -           B4860QDS:PPC_B4420,RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
index 3ba431626336189d93c4e2823c6b79b653f4f7aa..48791b7ffcf6597145262b5a28da3ec7e8323fb8 100644 (file)
@@ -44,13 +44,11 @@ COBJS-$(CONFIG_SYS_GENERIC_BOARD) += board_r.o
 COBJS-y += cmd_boot.o
 COBJS-$(CONFIG_CMD_BOOTM) += cmd_bootm.o
 COBJS-y += cmd_help.o
-COBJS-y += cmd_nvedit.o
 COBJS-y += cmd_version.o
 
 # environment
 COBJS-y += env_attr.o
 COBJS-y += env_callback.o
-COBJS-y += env_common.o
 COBJS-y += env_flags.o
 COBJS-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o
 COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += env_eeprom.o
@@ -171,6 +169,7 @@ COBJS-$(CONFIG_CMD_SPIBOOTLDR) += cmd_spibootldr.o
 COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o
 COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o
 COBJS-$(CONFIG_CMD_TIME) += cmd_time.o
+COBJS-$(CONFIG_CMD_TRACE) += cmd_trace.o
 COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o
 COBJS-$(CONFIG_CMD_TPM) += cmd_tpm.o
 COBJS-$(CONFIG_CMD_TSI148) += cmd_tsi148.o
@@ -191,14 +190,6 @@ COBJS-$(CONFIG_CMD_ZIP) += cmd_zip.o
 COBJS-$(CONFIG_CMD_ZFS) += cmd_zfs.o
 
 # others
-ifdef CONFIG_DDR_SPD
-SPD := y
-endif
-ifdef CONFIG_SPD_EEPROM
-SPD := y
-endif
-COBJS-$(SPD) += ddr_spd.o
-COBJS-$(CONFIG_HWCONFIG) += hwconfig.o
 COBJS-$(CONFIG_BOOTSTAGE) += bootstage.o
 COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o
 COBJS-y += flash.o
@@ -216,24 +207,43 @@ COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o
 endif
 
 ifdef CONFIG_SPL_BUILD
-COBJS-y += cmd_nvedit.o
-COBJS-y += env_common.o
 COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
 COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += cmd_nvedit.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_attr.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_callback.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_common.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_flags.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_nowhere.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
+# environment
+COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o
+COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o
+COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o
+ifneq ($(CONFIG_SPL_NET_SUPPORT),y)
+COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
+COBJS-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o
+COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
+COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
+COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
+else
+COBJS-y += env_nowhere.o
+endif
 endif
+# core command
+COBJS-y += cmd_nvedit.o
+#environment
+COBJS-y += env_common.o
+#others
+ifdef CONFIG_DDR_SPD
+SPD := y
+endif
+ifdef CONFIG_SPD_EEPROM
+SPD := y
+endif
+COBJS-$(SPD) += ddr_spd.o
+COBJS-$(CONFIG_HWCONFIG) += hwconfig.o
 COBJS-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
 COBJS-y += console.o
 COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-$(CONFIG_OF_LIBFDT) += image-fdt.o
 COBJS-$(CONFIG_FIT) += image-fit.o
+COBJS-$(CONFIG_FIT_SIGNATURE) += image-sig.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
 
index 8efdb6365577e519c62ef4b56fa41919b4ee94d1..ab4242a77ea487cf17e68ae413d57a6c6c1a90e5 100644 (file)
@@ -53,6 +53,7 @@
 #include <os.h>
 #include <post.h>
 #include <spi.h>
+#include <trace.h>
 #include <watchdog.h>
 #include <asm/errno.h>
 #include <asm/io.h>
@@ -500,6 +501,18 @@ static int reserve_lcd(void)
 }
 #endif /* CONFIG_LCD */
 
+static int reserve_trace(void)
+{
+#ifdef CONFIG_TRACE
+       gd->relocaddr -= CONFIG_TRACE_BUFFER_SIZE;
+       gd->trace_buff = map_sysmem(gd->relocaddr, CONFIG_TRACE_BUFFER_SIZE);
+       debug("Reserving %dk for trace data at: %08lx\n",
+             CONFIG_TRACE_BUFFER_SIZE >> 10, gd->relocaddr);
+#endif
+
+       return 0;
+}
+
 #if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) \
                && !defined(CONFIG_ARM) && !defined(CONFIG_X86)
 static int reserve_video(void)
@@ -818,8 +831,9 @@ static init_fnc_t init_sequence_f[] = {
 #ifdef CONFIG_SANDBOX
        setup_ram_buf,
 #endif
-       setup_fdt,
        setup_mon_len,
+       setup_fdt,
+       trace_early_init,
 #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
        /* TODO: can this go into arch_cpu_init()? */
        probecpu,
@@ -963,6 +977,7 @@ static init_fnc_t init_sequence_f[] = {
 #ifdef CONFIG_LCD
        reserve_lcd,
 #endif
+       reserve_trace,
        /* TODO: Why the dependency on CONFIG_8xx? */
 #if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) \
                && !defined(CONFIG_ARM) && !defined(CONFIG_X86)
index f5649c95f16f5291cecee4dc5fdf70e56fb4c759..f7a036e32f42e0adcbda61cebb566ee695dd2340 100644 (file)
@@ -58,6 +58,7 @@
 #include <serial.h>
 #include <spi.h>
 #include <stdio_dev.h>
+#include <trace.h>
 #include <watchdog.h>
 #ifdef CONFIG_ADDR_MAP
 #include <asm/mmu.h>
@@ -106,6 +107,15 @@ static int initr_secondary_cpu(void)
        return 0;
 }
 
+static int initr_trace(void)
+{
+#ifdef CONFIG_TRACE
+       trace_init(gd->trace_buff, CONFIG_TRACE_BUFFER_SIZE);
+#endif
+
+       return 0;
+}
+
 static int initr_reloc(void)
 {
        gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
@@ -711,6 +721,7 @@ static int run_main_loop(void)
  * TODO: perhaps reset the watchdog in the initcall function after each call?
  */
 init_fnc_t init_sequence_r[] = {
+       initr_trace,
        initr_reloc,
        /* TODO: could x86/PPC have this also perhaps? */
 #ifdef CONFIG_ARM
index c5c69961acc91dd8590968598deff5ba69def306..94a32a9971985f9141efd0acd2a1e6b463e87dfe 100644 (file)
@@ -49,6 +49,7 @@ static int next_id = BOOTSTAGE_ID_USER;
 enum {
        BOOTSTAGE_VERSION       = 0,
        BOOTSTAGE_MAGIC         = 0xb00757a3,
+       BOOTSTAGE_DIGITS        = 9,
 };
 
 struct bootstage_hdr {
@@ -165,21 +166,6 @@ uint32_t bootstage_accum(enum bootstage_id id)
        return duration;
 }
 
-static void print_time(unsigned long us_time)
-{
-       char str[15], *s;
-       int grab = 3;
-
-       /* We don't seem to have %'d in U-Boot */
-       sprintf(str, "%12lu", us_time);
-       for (s = str + 3; *s; s += grab) {
-               if (s != str + 3)
-                       putc(s[-1] != ' ' ? ',' : ' ');
-               printf("%.*s", grab, s);
-               grab = 3;
-       }
-}
-
 /**
  * Get a record name as a printable string
  *
@@ -208,10 +194,10 @@ static uint32_t print_time_record(enum bootstage_id id,
 
        if (prev == -1U) {
                printf("%11s", "");
-               print_time(rec->time_us);
+               print_grouped_ull(rec->time_us, BOOTSTAGE_DIGITS);
        } else {
-               print_time(rec->time_us);
-               print_time(rec->time_us - prev);
+               print_grouped_ull(rec->time_us, BOOTSTAGE_DIGITS);
+               print_grouped_ull(rec->time_us - prev, BOOTSTAGE_DIGITS);
        }
        printf("  %s\n", get_record_name(buf, sizeof(buf), rec));
 
@@ -445,9 +431,9 @@ int bootstage_unstash(void *base, int size)
        }
 
        if (hdr->count * sizeof(*rec) > hdr->size) {
-               debug("%s: Bootstage has %d records needing %d bytes, but "
+               debug("%s: Bootstage has %d records needing %lu bytes, but "
                        "only %d bytes is available\n", __func__, hdr->count,
-                     hdr->count * sizeof(*rec), hdr->size);
+                     (ulong)hdr->count * sizeof(*rec), hdr->size);
                return -1;
        }
 
index 05130b69364c900d380e45fac9c5d27712ad52e7..02a5013c04186ad8b159886f3027b2535e576ef4 100644 (file)
@@ -104,9 +104,18 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
  *  - verified image architecture (PPC) and type (KERNEL or MULTI),
  *  - loaded (first part of) image to header load address,
  *  - disabled interrupts.
+ *
+ * @flag: Flags indicating what to do (BOOTM_STATE_...)
+ * @argc: Number of arguments. Note that the arguments are shifted down
+ *      so that 0 is the first argument not processed by U-Boot, and
+ *      argc is adjusted accordingly. This avoids confusion as to how
+ *      many arguments are available for the OS.
+ * @images: Pointers to os/initrd/fdt
+ * @return 1 on error. On success the OS boots so this function does
+ * not return.
  */
 typedef int boot_os_fn(int flag, int argc, char * const argv[],
-                       bootm_headers_t *images); /* pointers to os/initrd/fdt */
+                       bootm_headers_t *images);
 
 #ifdef CONFIG_BOOTM_LINUX
 extern boot_os_fn do_bootm_linux;
@@ -199,15 +208,21 @@ static inline void boot_start_lmb(bootm_headers_t *images) { }
 
 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       const void *os_hdr;
-       int ret;
-
        memset((void *)&images, 0, sizeof(images));
        images.verify = getenv_yesno("verify");
 
        boot_start_lmb(&images);
 
        bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
+       images.state = BOOTM_STATE_START;
+
+       return 0;
+}
+
+static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
+                        char * const argv[])
+{
+       const void *os_hdr;
 
        /* get kernel image header, start address and length */
        os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
@@ -270,6 +285,8 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
                images.ep = image_get_ep(&images.legacy_hdr_os_copy);
 #if defined(CONFIG_FIT)
        } else if (images.fit_uname_os) {
+               int ret;
+
                ret = fit_image_get_entry(images.fit_hdr_os,
                                          images.fit_noffset_os, &images.ep);
                if (ret) {
@@ -287,6 +304,16 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
                images.ep += images.os.load;
        }
 
+       images.os.start = (ulong)os_hdr;
+
+       return 0;
+}
+
+static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc,
+                           char * const argv[])
+{
+       int ret;
+
        if (((images.os.type == IH_TYPE_KERNEL) ||
             (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
             (images.os.type == IH_TYPE_MULTI)) &&
@@ -312,17 +339,16 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 #endif
        }
 
-       images.os.start = (ulong)os_hdr;
-       images.state = BOOTM_STATE_START;
-
        return 0;
 }
 
 #define BOOTM_ERR_RESET                -1
 #define BOOTM_ERR_OVERLAP      -2
 #define BOOTM_ERR_UNIMPLEMENTED        -3
-static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)
+static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
+               int boot_progress)
 {
+       image_info_t os = images->os;
        uint8_t comp = os.comp;
        ulong load = os.load;
        ulong blob_start = os.start;
@@ -440,13 +466,23 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress)
                debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
                        *load_end);
 
-               return BOOTM_ERR_OVERLAP;
+               /* Check what type of image this is. */
+               if (images->legacy_hdr_valid) {
+                       if (image_get_type(&images->legacy_hdr_os_copy)
+                                       == IH_TYPE_MULTI)
+                               puts("WARNING: legacy format multi component image overwritten\n");
+                       return BOOTM_ERR_OVERLAP;
+               } else {
+                       puts("ERROR: new format image overwritten - must RESET the board to recover\n");
+                       bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
+                       return BOOTM_ERR_RESET;
+               }
        }
 
        return 0;
 }
 
-static int bootm_start_standalone(ulong iflag, int argc, char * const argv[])
+static int bootm_start_standalone(int argc, char * const argv[])
 {
        char  *s;
        int   (*appl)(int, char * const []);
@@ -457,7 +493,7 @@ static int bootm_start_standalone(ulong iflag, int argc, char * const argv[])
                return 0;
        }
        appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep);
-       (*appl)(argc-1, &argv[1]);
+       (*appl)(argc, argv);
        return 0;
 }
 
@@ -475,108 +511,225 @@ static cmd_tbl_t cmd_bootm_sub[] = {
        U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
        U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
        U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
+       U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
        U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
 };
 
+static int boot_selected_os(int argc, char * const argv[], int state,
+               bootm_headers_t *images, boot_os_fn *boot_fn)
+{
+       if (images->os.type == IH_TYPE_STANDALONE) {
+               /* This may return when 'autostart' is 'no' */
+               bootm_start_standalone(argc, argv);
+               return 0;
+       }
+#ifdef CONFIG_SILENT_CONSOLE
+       if (images->os.os == IH_OS_LINUX)
+               fixup_silent_linux();
+#endif
+       arch_preboot_os();
+       boot_fn(state, argc, argv, images);
+       if (state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
+               return 0;
+       bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
+#ifdef DEBUG
+       puts("\n## Control returned to monitor - resetting...\n");
+#endif
+       return BOOTM_ERR_RESET;
+}
+
+/**
+ * Execute selected states of the bootm command.
+ *
+ * Note the arguments to this state must be the first argument, Any 'bootm'
+ * or sub-command arguments must have already been taken.
+ *
+ * Note that if states contains more than one flag it MUST contain
+ * BOOTM_STATE_START, since this handles and consumes the command line args.
+ *
+ * Also note that aside from boot_os_fn functions and bootm_load_os no other
+ * functions we store the return value of in 'ret' may use a negative return
+ * value, without special handling.
+ *
+ * @param cmdtp                Pointer to bootm command table entry
+ * @param flag         Command flags (CMD_FLAG_...)
+ * @param argc         Number of subcommand arguments (0 = no arguments)
+ * @param argv         Arguments
+ * @param states       Mask containing states to run (BOOTM_STATE_...)
+ * @param images       Image header information
+ * @param boot_progress 1 to show boot progress, 0 to not do this
+ * @return 0 if ok, something else on error. Some errors will cause this
+ *     function to perform a reboot! If states contains BOOTM_STATE_OS_GO
+ *     then the intent is to boot an OS, so this function will not return
+ *     unless the image type is standalone.
+ */
+static int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc,
+               char * const argv[], int states, bootm_headers_t *images,
+               int boot_progress)
+{
+       boot_os_fn *boot_fn;
+       ulong iflag = 0;
+       int ret = 0;
+
+       images->state |= states;
+
+       /*
+        * Work through the states and see how far we get. We stop on
+        * any error.
+        */
+       if (states & BOOTM_STATE_START)
+               ret = bootm_start(cmdtp, flag, argc, argv);
+
+       if (!ret && (states & BOOTM_STATE_FINDOS))
+               ret = bootm_find_os(cmdtp, flag, argc, argv);
+
+       if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
+               ret = bootm_find_other(cmdtp, flag, argc, argv);
+               argc = 0;       /* consume the args */
+       }
+
+       /*
+        * We have reached the point of no return: we are going to
+        * overwrite all exception vector code, so we cannot easily
+        * recover from any failures any more...
+        */
+       iflag = disable_interrupts();
+#ifdef CONFIG_NETCONSOLE
+       /* Stop the ethernet stack if NetConsole could have left it up */
+       eth_halt();
+#endif
+
+#if defined(CONFIG_CMD_USB)
+       /*
+        * turn off USB to prevent the host controller from writing to the
+        * SDRAM while Linux is booting. This could happen (at least for OHCI
+        * controller), because the HCCA (Host Controller Communication Area)
+        * lies within the SDRAM and the host controller writes continously to
+        * this area (as busmaster!). The HccaFrameNumber is for example
+        * updated every 1 ms within the HCCA structure in SDRAM! For more
+        * details see the OpenHCI specification.
+        */
+       usb_stop();
+#endif
+
+       /* Load the OS */
+       if (!ret && (states & BOOTM_STATE_LOADOS)) {
+               ulong load_end;
+
+               ret = bootm_load_os(images, &load_end, 0);
+               if (ret && ret != BOOTM_ERR_OVERLAP)
+                       goto err;
+
+               if (ret == 0)
+                       lmb_reserve(&images->lmb, images->os.load,
+                                   (load_end - images->os.load));
+               else if (ret == BOOTM_ERR_OVERLAP)
+                       ret = 0;
+       }
+
+       /* Relocate the ramdisk */
+#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+       if (!ret && (states & BOOTM_STATE_RAMDISK)) {
+               ulong rd_len = images->rd_end - images->rd_start;
+
+               ret = boot_ramdisk_high(&images->lmb, images->rd_start,
+                       rd_len, &images->initrd_start, &images->initrd_end);
+               if (!ret) {
+                       setenv_hex("initrd_start", images->initrd_start);
+                       setenv_hex("initrd_end", images->initrd_end);
+               }
+       }
+#endif
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
+       if (!ret && (states & BOOTM_STATE_FDT)) {
+               boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
+               ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
+                                       &images->ft_len);
+       }
+#endif
+
+       /* From now on, we need the OS boot function */
+       if (ret)
+               return ret;
+       boot_fn = boot_os[images->os.os];
+       if (boot_fn == NULL) {
+               if (iflag)
+                       enable_interrupts();
+               printf("ERROR: booting os '%s' (%d) is not supported\n",
+                      genimg_get_os_name(images->os.os), images->os.os);
+               bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
+               return 1;
+       }
+
+       /* Call various other states that are not generally used */
+       if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
+               ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
+       if (!ret && (states & BOOTM_STATE_OS_BD_T))
+               ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
+       if (!ret && (states & BOOTM_STATE_OS_PREP))
+               ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
+
+#ifdef CONFIG_TRACE
+       /* Pretend to run the OS, then run a user command */
+       if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
+               char *cmd_list = getenv("fakegocmd");
+
+               ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
+                               images, boot_fn);
+               if (!ret && cmd_list)
+                       ret = run_command_list(cmd_list, -1, flag);
+       }
+#endif
+       /* Now run the OS! We hope this doesn't return */
+       if (!ret && (states & BOOTM_STATE_OS_GO)) {
+               ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
+                               images, boot_fn);
+               if (ret)
+                       goto err;
+       }
+
+       return ret;
+
+       /* Deal with any fallout */
+err:
+       if (iflag)
+               enable_interrupts();
+
+       if (ret == BOOTM_ERR_UNIMPLEMENTED)
+               bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
+       else if (ret == BOOTM_ERR_RESET)
+               do_reset(cmdtp, flag, argc, argv);
+       else
+               puts("subcommand not supported\n");
+
+       return ret;
+}
+
 static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
                        char * const argv[])
 {
        int ret = 0;
        long state;
        cmd_tbl_t *c;
-       boot_os_fn *boot_fn;
 
-       c = find_cmd_tbl(argv[1], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
+       c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
+       argc--; argv++;
 
        if (c) {
                state = (long)c->cmd;
-
-               /* treat start special since it resets the state machine */
-               if (state == BOOTM_STATE_START) {
-                       argc--;
-                       argv++;
-                       return bootm_start(cmdtp, flag, argc, argv);
-               }
+               if (state == BOOTM_STATE_START)
+                       state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
        } else {
                /* Unrecognized command */
                return CMD_RET_USAGE;
        }
 
-       if (images.state < BOOTM_STATE_START ||
-           images.state >= state) {
+       if (state != BOOTM_STATE_START && images.state >= state) {
                printf("Trying to execute a command out of order\n");
                return CMD_RET_USAGE;
        }
 
-       images.state |= state;
-       boot_fn = boot_os[images.os.os];
-
-       switch (state) {
-               ulong load_end;
-               case BOOTM_STATE_START:
-                       /* should never occur */
-                       break;
-               case BOOTM_STATE_LOADOS:
-                       ret = bootm_load_os(images.os, &load_end, 0);
-                       if (ret)
-                               return ret;
-
-                       lmb_reserve(&images.lmb, images.os.load,
-                                       (load_end - images.os.load));
-                       break;
-#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
-               case BOOTM_STATE_RAMDISK:
-               {
-                       ulong rd_len = images.rd_end - images.rd_start;
-
-                       ret = boot_ramdisk_high(&images.lmb, images.rd_start,
-                               rd_len, &images.initrd_start, &images.initrd_end);
-                       if (ret)
-                               return ret;
-
-                       setenv_hex("initrd_start", images.initrd_start);
-                       setenv_hex("initrd_end", images.initrd_end);
-               }
-                       break;
-#endif
-#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
-               case BOOTM_STATE_FDT:
-               {
-                       boot_fdt_add_mem_rsv_regions(&images.lmb,
-                                                    images.ft_addr);
-                       ret = boot_relocate_fdt(&images.lmb,
-                               &images.ft_addr, &images.ft_len);
-                       break;
-               }
-#endif
-               case BOOTM_STATE_OS_CMDLINE:
-                       ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, &images);
-                       if (ret)
-                               printf("cmdline subcommand not supported\n");
-                       break;
-               case BOOTM_STATE_OS_BD_T:
-                       ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, &images);
-                       if (ret)
-                               printf("bdt subcommand not supported\n");
-                       break;
-               case BOOTM_STATE_OS_PREP:
-                       ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, &images);
-                       if (ret)
-                               printf("prep subcommand not supported\n");
-                       break;
-               case BOOTM_STATE_OS_GO:
-                       disable_interrupts();
-#ifdef CONFIG_NETCONSOLE
-                       /*
-                        * Stop the ethernet stack if NetConsole could have
-                        * left it up
-                        */
-                       eth_halt();
-#endif
-                       arch_preboot_os();
-                       boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images);
-                       break;
-       }
+       ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
 
        return ret;
 }
@@ -587,10 +740,6 @@ static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
 
 int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       ulong           iflag;
-       ulong           load_end = 0;
-       int             ret;
-       boot_os_fn      *boot_fn;
 #ifdef CONFIG_NEEDS_MANUAL_RELOC
        static int relocated = 0;
 
@@ -611,11 +760,12 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #endif
 
        /* determine if we have a sub command */
-       if (argc > 1) {
+       argc--; argv++;
+       if (argc > 0) {
                char *endp;
 
-               simple_strtoul(argv[1], &endp, 16);
-               /* endp pointing to NULL means that argv[1] was just a
+               simple_strtoul(argv[0], &endp, 16);
+               /* endp pointing to NULL means that argv[0] was just a
                 * valid number, pass it along to the normal bootm processing
                 *
                 * If endp is ':' or '#' assume a FIT identifier so pass
@@ -627,101 +777,10 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        return do_bootm_subcommand(cmdtp, flag, argc, argv);
        }
 
-       if (bootm_start(cmdtp, flag, argc, argv))
-               return 1;
-
-       /*
-        * We have reached the point of no return: we are going to
-        * overwrite all exception vector code, so we cannot easily
-        * recover from any failures any more...
-        */
-       iflag = disable_interrupts();
-
-#ifdef CONFIG_NETCONSOLE
-       /* Stop the ethernet stack if NetConsole could have left it up */
-       eth_halt();
-#endif
-
-#if defined(CONFIG_CMD_USB)
-       /*
-        * turn off USB to prevent the host controller from writing to the
-        * SDRAM while Linux is booting. This could happen (at least for OHCI
-        * controller), because the HCCA (Host Controller Communication Area)
-        * lies within the SDRAM and the host controller writes continously to
-        * this area (as busmaster!). The HccaFrameNumber is for example
-        * updated every 1 ms within the HCCA structure in SDRAM! For more
-        * details see the OpenHCI specification.
-        */
-       usb_stop();
-#endif
-
-       ret = bootm_load_os(images.os, &load_end, 1);
-
-       if (ret < 0) {
-               if (ret == BOOTM_ERR_RESET)
-                       do_reset(cmdtp, flag, argc, argv);
-               if (ret == BOOTM_ERR_OVERLAP) {
-                       if (images.legacy_hdr_valid) {
-                               image_header_t *hdr;
-                               hdr = &images.legacy_hdr_os_copy;
-                               if (image_get_type(hdr) == IH_TYPE_MULTI)
-                                       puts("WARNING: legacy format multi "
-                                               "component image "
-                                               "overwritten\n");
-                       } else {
-                               puts("ERROR: new format image overwritten - "
-                                       "must RESET the board to recover\n");
-                               bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
-                               do_reset(cmdtp, flag, argc, argv);
-                       }
-               }
-               if (ret == BOOTM_ERR_UNIMPLEMENTED) {
-                       if (iflag)
-                               enable_interrupts();
-                       bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
-                       return 1;
-               }
-       }
-
-       lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));
-
-       if (images.os.type == IH_TYPE_STANDALONE) {
-               if (iflag)
-                       enable_interrupts();
-               /* This may return when 'autostart' is 'no' */
-               bootm_start_standalone(iflag, argc, argv);
-               return 0;
-       }
-
-       bootstage_mark(BOOTSTAGE_ID_CHECK_BOOT_OS);
-
-#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
-       if (images.os.os == IH_OS_LINUX)
-               fixup_silent_linux();
-#endif
-
-       boot_fn = boot_os[images.os.os];
-
-       if (boot_fn == NULL) {
-               if (iflag)
-                       enable_interrupts();
-               printf("ERROR: booting os '%s' (%d) is not supported\n",
-                       genimg_get_os_name(images.os.os), images.os.os);
-               bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
-               return 1;
-       }
-
-       arch_preboot_os();
-
-       boot_fn(0, argc, argv, &images);
-
-       bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
-#ifdef DEBUG
-       puts("\n## Control returned to monitor - resetting...\n");
-#endif
-       do_reset(cmdtp, flag, argc, argv);
-
-       return 1;
+       return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
+               BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
+               BOOTM_STATE_LOADOS | BOOTM_STATE_OS_PREP |
+               BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO, &images, 1);
 }
 
 int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
@@ -816,22 +875,22 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 #endif
 
        /* find out kernel image address */
-       if (argc < 2) {
+       if (argc < 1) {
                img_addr = load_addr;
                debug("*  kernel: default image load address = 0x%08lx\n",
                                load_addr);
 #if defined(CONFIG_FIT)
-       } else if (fit_parse_conf(argv[1], load_addr, &img_addr,
+       } else if (fit_parse_conf(argv[0], load_addr, &img_addr,
                                                        &fit_uname_config)) {
                debug("*  kernel: config '%s' from image at 0x%08lx\n",
                                fit_uname_config, img_addr);
-       } else if (fit_parse_subimage(argv[1], load_addr, &img_addr,
+       } else if (fit_parse_subimage(argv[0], load_addr, &img_addr,
                                                        &fit_uname_kernel)) {
                debug("*  kernel: subimage '%s' from image at 0x%08lx\n",
                                fit_uname_kernel, img_addr);
 #endif
        } else {
-               img_addr = simple_strtoul(argv[1], NULL, 16);
+               img_addr = simple_strtoul(argv[0], NULL, 16);
                debug("*  kernel: cmdline image address = 0x%08lx\n", img_addr);
        }
 
@@ -1346,6 +1405,19 @@ static void fixup_silent_linux(void)
 }
 #endif /* CONFIG_SILENT_CONSOLE */
 
+#if defined(CONFIG_BOOTM_NETBSD) || defined(CONFIG_BOOTM_PLAN9)
+static void copy_args(char *dest, int argc, char * const argv[], char delim)
+{
+       int i;
+
+       for (i = 0; i < argc; i++) {
+               if (i > 0)
+                       *dest++ = delim;
+               strcpy(dest, argv[i]);
+               dest += strlen(argv[i]);
+       }
+}
+#endif
 
 /*******************************************************************/
 /* OS booting routines */
@@ -1401,20 +1473,14 @@ static int do_bootm_netbsd(int flag, int argc, char * const argv[],
        consdev = "scc3";
 #endif
 
-       if (argc > 2) {
+       if (argc > 0) {
                ulong len;
                int   i;
 
-               for (i = 2, len = 0; i < argc; i += 1)
+               for (i = 0, len = 0; i < argc; i += 1)
                        len += strlen(argv[i]) + 1;
                cmdline = malloc(len);
-
-               for (i = 2, len = 0; i < argc; i += 1) {
-                       if (i > 2)
-                               cmdline[len++] = ' ';
-                       strcpy(&cmdline[len], argv[i]);
-                       len += strlen(argv[i]);
-               }
+               copy_args(cmdline, argc, argv, ' ');
        } else if ((cmdline = getenv("bootargs")) == NULL) {
                cmdline = "";
        }
@@ -1533,6 +1599,7 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[],
                           bootm_headers_t *images)
 {
        void (*entry_point)(void);
+       char *s;
 
        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
                return 1;
@@ -1544,6 +1611,20 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[],
        }
 #endif
 
+       /* See README.plan9 */
+       s = getenv("confaddr");
+       if (s != NULL) {
+               char *confaddr = (char *)simple_strtoul(s, NULL, 16);
+
+               if (argc > 0) {
+                       copy_args(confaddr, argc, argv, '\n');
+               } else {
+                       s = getenv("bootargs");
+                       if (s != NULL)
+                               strcpy(confaddr, s);
+               }
+       }
+
        entry_point = (void (*)(void))images->ep;
 
        printf("## Transferring control to Plan 9 (at address %08lx) ...\n",
@@ -1663,9 +1744,8 @@ static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
        int ret;
        void *zi_start, *zi_end;
 
-       memset(images, 0, sizeof(bootm_headers_t));
-
-       boot_start_lmb(images);
+       ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
+                             images, 1);
 
        /* Setup Linux kernel zImage entry point */
        if (argc < 2) {
@@ -1684,73 +1764,25 @@ static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
 
        lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
 
-       /* Find ramdisk */
-       ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH,
-                       &images->rd_start, &images->rd_end);
-       if (ret) {
-               puts("Ramdisk image is corrupt or invalid\n");
-               return 1;
-       }
-
-#if defined(CONFIG_OF_LIBFDT)
-       /* find flattened device tree */
-       ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
-                          &images->ft_addr, &images->ft_len);
-       if (ret) {
-               puts("Could not find a valid device tree\n");
-               return 1;
-       }
-
-       set_working_fdt_addr(images->ft_addr);
-#endif
+       ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_FINDOTHER,
+                             images, 1);
 
-       return 0;
+       return ret;
 }
 
-static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        bootm_headers_t images;
+       int ret;
 
        if (bootz_start(cmdtp, flag, argc, argv, &images))
                return 1;
 
-       /*
-        * We have reached the point of no return: we are going to
-        * overwrite all exception vector code, so we cannot easily
-        * recover from any failures any more...
-        */
-       disable_interrupts();
-
-#ifdef CONFIG_NETCONSOLE
-       /* Stop the ethernet stack if NetConsole could have left it up */
-       eth_halt();
-#endif
-
-#if defined(CONFIG_CMD_USB)
-       /*
-        * turn off USB to prevent the host controller from writing to the
-        * SDRAM while Linux is booting. This could happen (at least for OHCI
-        * controller), because the HCCA (Host Controller Communication Area)
-        * lies within the SDRAM and the host controller writes continously to
-        * this area (as busmaster!). The HccaFrameNumber is for example
-        * updated every 1 ms within the HCCA structure in SDRAM! For more
-        * details see the OpenHCI specification.
-        */
-       usb_stop();
-#endif
-
-#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
-       fixup_silent_linux();
-#endif
-       arch_preboot_os();
-
-       do_bootm_linux(0, argc, argv, &images);
-#ifdef DEBUG
-       puts("\n## Control returned to monitor - resetting...\n");
-#endif
-       do_reset(cmdtp, flag, argc, argv);
+       ret = do_bootm_states(cmdtp, flag, argc, argv,
+                             BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO,
+                             &images, 1);
 
-       return 1;
+       return ret;
 }
 
 #ifdef CONFIG_SYS_LONGHELP
index 78b4aa70ba7d05da59b0b1f14381a3102d6f4cf1..59e95dfa12ef0623cd20e4bb2ac8a8e3828eecde 100644 (file)
@@ -830,7 +830,7 @@ static void ide_ident(block_dev_desc_t *dev_desc)
 
 /* ------------------------------------------------------------------------- */
 
-ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer)
 {
        ulong n = 0;
        unsigned char c;
@@ -844,7 +844,7 @@ ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
                lba48 = 1;
        }
 #endif
-       debug("ide_read dev %d start %lX, blocks " LBAF " buffer at %lX\n",
+       debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n",
              device, blknr, blkcnt, (ulong) buffer);
 
        ide_led(DEVICE_LED(device), 1); /* LED on       */
@@ -934,8 +934,8 @@ ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
 
                if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
                    ATA_STAT_DRQ) {
-                       printf("Error (no IRQ) dev %d blk %ld: status %#02x\n",
-                               device, blknr, c);
+                       printf("Error (no IRQ) dev %d blk " LBAF ": status "
+                              "%#02x\n", device, blknr, c);
                        break;
                }
 
@@ -954,7 +954,7 @@ IDE_READ_E:
 /* ------------------------------------------------------------------------- */
 
 
-ulong ide_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer)
+ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt, const void *buffer)
 {
        ulong n = 0;
        unsigned char c;
@@ -1022,8 +1022,8 @@ ulong ide_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer)
 
                if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
                    ATA_STAT_DRQ) {
-                       printf("Error (no IRQ) dev %d blk %ld: status %#02x\n",
-                               device, blknr, c);
+                       printf("Error (no IRQ) dev %d blk " LBAF ": status "
+                               "%#02x\n", device, blknr, c);
                        goto WR_OUT;
                }
 
index 6df00b15d3f1823a3df9be934efea0c79326f89a..77eafa0b8920409259acb5fbde8225a575b19af0 100644 (file)
@@ -551,6 +551,8 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
                        *cp++;
        }
        unmap_sysmem(buf);
+
+       return 0;
 }
 
 #ifdef CONFIG_LOOPW
index 7d824690b7f064547a3400bd65a957538a4289f0..5f1ed430e03bc844ac4ffbf36760cf722f38ba55 100644 (file)
@@ -147,6 +147,36 @@ U_BOOT_CMD(
        "- display info of the current MMC device"
 );
 
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+       int err;
+       err = mmc_boot_part_access(mmc, ack, part_num, access);
+
+       if ((err == 0) && (access != 0)) {
+               printf("\t\t\t!!!Notice!!!\n");
+
+               printf("!You must close EMMC boot Partition");
+               printf("after all images are written\n");
+
+               printf("!EMMC boot partition has continuity");
+               printf("at image writing time.\n");
+
+               printf("!So, do not close the boot partition");
+               printf("before all images are written.\n");
+               return 0;
+       } else if ((err == 0) && (access == 0))
+               return 0;
+       else if ((err != 0) && (access != 0)) {
+               printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
+               return 1;
+       } else {
+               printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
+               return 1;
+       }
+}
+#endif
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        enum mmc_state state;
@@ -258,8 +288,74 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                                curr_device, mmc->part_num);
 
                return 0;
-       }
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+       } else if ((strcmp(argv[1], "open") == 0) ||
+                       (strcmp(argv[1], "close") == 0)) {
+               int dev;
+               struct mmc *mmc;
+               u8 part_num, access = 0;
+
+               if (argc == 4) {
+                       dev = simple_strtoul(argv[2], NULL, 10);
+                       part_num = simple_strtoul(argv[3], NULL, 10);
+               } else {
+                       return CMD_RET_USAGE;
+               }
+
+               mmc = find_mmc_device(dev);
+               if (!mmc) {
+                       printf("no mmc device at slot %x\n", dev);
+                       return 1;
+               }
 
+               if (IS_SD(mmc)) {
+                       printf("SD device cannot be opened/closed\n");
+                       return 1;
+               }
+
+               if ((part_num <= 0) || (part_num > MMC_NUM_BOOT_PARTITION)) {
+                       printf("Invalid boot partition number:\n");
+                       printf("Boot partition number cannot be <= 0\n");
+                       printf("EMMC44 supports only 2 boot partitions\n");
+                       return 1;
+               }
+
+               if (strcmp(argv[1], "open") == 0)
+                       access = part_num; /* enable R/W access to boot part*/
+               else
+                       access = 0; /* No access to boot partition */
+
+               /* acknowledge to be sent during boot operation */
+               return boot_part_access(mmc, 1, part_num, access);
+
+       } else if (strcmp(argv[1], "bootpart") == 0) {
+               int dev;
+               dev = simple_strtoul(argv[2], NULL, 10);
+
+               u32 bootsize = simple_strtoul(argv[3], NULL, 10);
+               u32 rpmbsize = simple_strtoul(argv[4], NULL, 10);
+               struct mmc *mmc = find_mmc_device(dev);
+               if (!mmc) {
+                       printf("no mmc device at slot %x\n", dev);
+                       return 1;
+               }
+
+               if (IS_SD(mmc)) {
+                       printf("It is not a EMMC device\n");
+                       return 1;
+               }
+
+               if (0 == mmc_boot_partition_size_change(mmc,
+                                                       bootsize, rpmbsize)) {
+                       printf("EMMC boot partition Size %d MB\n", bootsize);
+                       printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
+                       return 0;
+               } else {
+                       printf("EMMC boot partition Size change Failed.\n");
+                       return 1;
+               }
+#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+       }
        state = MMC_INVALID;
        if (argc == 5 && strcmp(argv[1], "read") == 0)
                state = MMC_READ;
@@ -334,5 +430,14 @@ U_BOOT_CMD(
        "mmc rescan\n"
        "mmc part - lists available partition on current mmc device\n"
        "mmc dev [dev] [part] - show or set current mmc device [partition]\n"
-       "mmc list - lists available devices");
+       "mmc list - lists available devices\n"
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+       "mmc open <dev> <boot_partition>\n"
+       " - Enable boot_part for booting and enable R/W access of boot_part\n"
+       "mmc close <dev> <boot_partition>\n"
+       " - Enable boot_part for booting and disable access to boot_part\n"
+       "mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n"
+       " - change sizes of boot and RPMB partions of specified device\n"
 #endif
+       );
+#endif /* !CONFIG_GENERIC_MMC */
index 2dbd49cbd6641352786a24110e0d3646f66f7dfc..1fb75d8ae9c1dcdf03e56bf5a3de8eaddfa1bafc 100644 (file)
 
 #define MAX_TFTP_PATH_LEN 127
 
+const char *pxe_default_paths[] = {
+#ifdef CONFIG_SYS_SOC
+       "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC,
+#endif
+       "default-" CONFIG_SYS_ARCH,
+       "default",
+       NULL
+};
+
 /*
  * Like getenv, but prints an error if envvar isn't defined in the
  * environment.  It always returns what getenv does, so it can be used in
  * place of getenv without changing error handling otherwise.
  */
-static char *from_env(char *envvar)
+static char *from_env(const char *envvar)
 {
        char *ret;
 
@@ -55,37 +64,21 @@ static char *from_env(char *envvar)
  */
 static int format_mac_pxe(char *outbuf, size_t outbuf_len)
 {
-       size_t ethaddr_len;
-       char *p, *ethaddr;
-
-       ethaddr = from_env("ethaddr");
+       uchar ethaddr[6];
 
-       if (!ethaddr)
-               return -ENOENT;
-
-       ethaddr_len = strlen(ethaddr);
-
-       /*
-        * ethaddr_len + 4 gives room for "01-", ethaddr, and a NUL byte at
-        * the end.
-        */
-       if (outbuf_len < ethaddr_len + 4) {
-               printf("outbuf is too small (%d < %d)\n",
-                               outbuf_len, ethaddr_len + 4);
+       if (outbuf_len < 21) {
+               printf("outbuf is too small (%d < 21)\n", outbuf_len);
 
                return -EINVAL;
        }
 
-       strcpy(outbuf, "01-");
-
-       for (p = outbuf + 3; *ethaddr; ethaddr++, p++) {
-               if (*ethaddr == ':')
-                       *p = '-';
-               else
-                       *p = tolower(*ethaddr);
-       }
+       if (!eth_getenv_enetaddr_by_index("eth", eth_get_dev_index(),
+                                         ethaddr))
+               return -ENOENT;
 
-       *p = '\0';
+       sprintf(outbuf, "01-%02x-%02x-%02x-%02x-%02x-%02x",
+               ethaddr[0], ethaddr[1], ethaddr[2],
+               ethaddr[3], ethaddr[4], ethaddr[5]);
 
        return 1;
 }
@@ -131,14 +124,14 @@ static int get_bootfile_path(const char *file_path, char *bootfile_path,
        return 1;
 }
 
-static int (*do_getfile)(char *file_path, char *file_addr);
+static int (*do_getfile)(const char *file_path, char *file_addr);
 
-static int do_get_tftp(char *file_path, char *file_addr)
+static int do_get_tftp(const char *file_path, char *file_addr)
 {
        char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
 
        tftp_argv[1] = file_addr;
-       tftp_argv[2] = file_path;
+       tftp_argv[2] = (void *)file_path;
 
        if (do_tftpb(NULL, 0, 3, tftp_argv))
                return -ENOENT;
@@ -148,12 +141,12 @@ static int do_get_tftp(char *file_path, char *file_addr)
 
 static char *fs_argv[5];
 
-static int do_get_ext2(char *file_path, char *file_addr)
+static int do_get_ext2(const char *file_path, char *file_addr)
 {
 #ifdef CONFIG_CMD_EXT2
        fs_argv[0] = "ext2load";
        fs_argv[3] = file_addr;
-       fs_argv[4] = file_path;
+       fs_argv[4] = (void *)file_path;
 
        if (!do_ext2load(NULL, 0, 5, fs_argv))
                return 1;
@@ -161,12 +154,12 @@ static int do_get_ext2(char *file_path, char *file_addr)
        return -ENOENT;
 }
 
-static int do_get_fat(char *file_path, char *file_addr)
+static int do_get_fat(const char *file_path, char *file_addr)
 {
 #ifdef CONFIG_CMD_FAT
        fs_argv[0] = "fatload";
        fs_argv[3] = file_addr;
-       fs_argv[4] = file_path;
+       fs_argv[4] = (void *)file_path;
 
        if (!do_fat_fsload(NULL, 0, 5, fs_argv))
                return 1;
@@ -182,7 +175,7 @@ static int do_get_fat(char *file_path, char *file_addr)
  *
  * Returns 1 for success, or < 0 on error.
  */
-static int get_relfile(char *file_path, void *file_addr)
+static int get_relfile(const char *file_path, void *file_addr)
 {
        size_t path_len;
        char relfile[MAX_TFTP_PATH_LEN+1];
@@ -221,7 +214,7 @@ static int get_relfile(char *file_path, void *file_addr)
  *
  * Returns 1 on success, or < 0 for error.
  */
-static int get_pxe_file(char *file_path, void *file_addr)
+static int get_pxe_file(const char *file_path, void *file_addr)
 {
        unsigned long config_file_size;
        char *tftp_filesize;
@@ -258,7 +251,7 @@ static int get_pxe_file(char *file_path, void *file_addr)
  *
  * Returns 1 on success or < 0 on error.
  */
-static int get_pxelinux_path(char *file, void *pxefile_addr_r)
+static int get_pxelinux_path(const char *file, void *pxefile_addr_r)
 {
        size_t base_len = strlen(PXELINUX_DIR);
        char path[MAX_TFTP_PATH_LEN+1];
@@ -355,7 +348,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        char *pxefile_addr_str;
        unsigned long pxefile_addr_r;
-       int err;
+       int err, i = 0;
 
        do_getfile = do_get_tftp;
 
@@ -376,16 +369,23 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
         * Keep trying paths until we successfully get a file we're looking
         * for.
         */
-       if (pxe_uuid_path((void *)pxefile_addr_r) > 0
-               || pxe_mac_path((void *)pxefile_addr_r) > 0
-               || pxe_ipaddr_paths((void *)pxefile_addr_r) > 0
-               || get_pxelinux_path("default", (void *)pxefile_addr_r) > 0) {
-
+       if (pxe_uuid_path((void *)pxefile_addr_r) > 0 ||
+           pxe_mac_path((void *)pxefile_addr_r) > 0 ||
+           pxe_ipaddr_paths((void *)pxefile_addr_r) > 0) {
                printf("Config file found\n");
 
                return 0;
        }
 
+       while (pxe_default_paths[i]) {
+               if (get_pxelinux_path(pxe_default_paths[i],
+                                     (void *)pxefile_addr_r) > 0) {
+                       printf("Config file found\n");
+                       return 0;
+               }
+               i++;
+       }
+
        printf("Config file not found\n");
 
        return 1;
@@ -398,7 +398,7 @@ do_pxe_get(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  *
  * Returns 1 on success or < 0 on error.
  */
-static int get_relfile_envaddr(char *file_path, char *envaddr_name)
+static int get_relfile_envaddr(const char *file_path, const char *envaddr_name)
 {
        unsigned long file_addr;
        char *envaddr;
@@ -445,14 +445,17 @@ static int get_relfile_envaddr(char *file_path, char *envaddr_name)
  * list - lets these form a list, which a pxe_menu struct will hold.
  */
 struct pxe_label {
+       char num[4];
        char *name;
        char *menu;
        char *kernel;
        char *append;
        char *initrd;
        char *fdt;
+       int ipappend;
        int attempted;
        int localboot;
+       int localboot_val;
        struct list_head list;
 };
 
@@ -533,21 +536,9 @@ static void label_destroy(struct pxe_label *label)
 static void label_print(void *data)
 {
        struct pxe_label *label = data;
-       const char *c = label->menu ? label->menu : label->kernel;
-
-       printf("%s:\t%s\n", label->name, c);
-
-       if (label->kernel)
-               printf("\t\tkernel: %s\n", label->kernel);
-
-       if (label->append)
-               printf("\t\tappend: %s\n", label->append);
+       const char *c = label->menu ? label->menu : label->name;
 
-       if (label->initrd)
-               printf("\t\tinitrd: %s\n", label->initrd);
-
-       if (label->fdt)
-               printf("\tfdt: %s\n", label->fdt);
+       printf("%s:\t%s\n", label->num, c);
 }
 
 /*
@@ -591,34 +582,43 @@ static int label_localboot(struct pxe_label *label)
  * If the label specifies an 'append' line, its contents will overwrite that
  * of the 'bootargs' environment variable.
  */
-static void label_boot(struct pxe_label *label)
+static int label_boot(struct pxe_label *label)
 {
        char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
+       char initrd_str[22];
+       char mac_str[29] = "";
+       char ip_str[68] = "";
+       char *bootargs;
        int bootm_argc = 3;
+       int len = 0;
 
        label_print(label);
 
        label->attempted = 1;
 
        if (label->localboot) {
-               label_localboot(label);
-               return;
+               if (label->localboot_val >= 0)
+                       label_localboot(label);
+               return 0;
        }
 
        if (label->kernel == NULL) {
                printf("No kernel given, skipping %s\n",
                                label->name);
-               return;
+               return 1;
        }
 
        if (label->initrd) {
                if (get_relfile_envaddr(label->initrd, "ramdisk_addr_r") < 0) {
                        printf("Skipping %s for failure retrieving initrd\n",
                                        label->name);
-                       return;
+                       return 1;
                }
 
-               bootm_argv[2] = getenv("ramdisk_addr_r");
+               bootm_argv[2] = initrd_str;
+               strcpy(bootm_argv[2], getenv("ramdisk_addr_r"));
+               strcat(bootm_argv[2], ":");
+               strcat(bootm_argv[2], getenv("filesize"));
        } else {
                bootm_argv[2] = "-";
        }
@@ -626,11 +626,43 @@ static void label_boot(struct pxe_label *label)
        if (get_relfile_envaddr(label->kernel, "kernel_addr_r") < 0) {
                printf("Skipping %s for failure retrieving kernel\n",
                                label->name);
-               return;
+               return 1;
+       }
+
+       if (label->ipappend & 0x1) {
+               sprintf(ip_str, " ip=%s:%s:%s:%s",
+                       getenv("ipaddr"), getenv("serverip"),
+                       getenv("gatewayip"), getenv("netmask"));
+               len += strlen(ip_str);
+       }
+
+       if (label->ipappend & 0x2) {
+               int err;
+               strcpy(mac_str, " BOOTIF=");
+               err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8);
+               if (err < 0)
+                       mac_str[0] = '\0';
+               len += strlen(mac_str);
        }
 
        if (label->append)
-               setenv("bootargs", label->append);
+               len += strlen(label->append);
+
+       if (len) {
+               bootargs = malloc(len + 1);
+               if (!bootargs)
+                       return 1;
+               bootargs[0] = '\0';
+               if (label->append)
+                       strcpy(bootargs, label->append);
+               strcat(bootargs, ip_str);
+               strcat(bootargs, mac_str);
+
+               setenv("bootargs", bootargs);
+               printf("append: %s\n", bootargs);
+
+               free(bootargs);
+       }
 
        bootm_argv[1] = getenv("kernel_addr_r");
 
@@ -654,7 +686,7 @@ static void label_boot(struct pxe_label *label)
                if (get_relfile_envaddr(label->fdt, "fdt_addr_r") < 0) {
                        printf("Skipping %s for failure retrieving fdt\n",
                                        label->name);
-                       return;
+                       return 1;
                }
        } else
                bootm_argv[3] = getenv("fdt_addr");
@@ -663,6 +695,12 @@ static void label_boot(struct pxe_label *label)
                bootm_argc = 4;
 
        do_bootm(NULL, 0, bootm_argc, bootm_argv);
+
+#ifdef CONFIG_CMD_BOOTZ
+       /* Try booting a zImage if do_bootm returns */
+       do_bootz(NULL, 0, bootm_argc, bootm_argv);
+#endif
+       return 1;
 }
 
 /*
@@ -685,6 +723,8 @@ enum token_type {
        T_PROMPT,
        T_INCLUDE,
        T_FDT,
+       T_ONTIMEOUT,
+       T_IPAPPEND,
        T_INVALID
 };
 
@@ -713,6 +753,8 @@ static const struct token keywords[] = {
        {"initrd", T_INITRD},
        {"include", T_INCLUDE},
        {"fdt", T_FDT},
+       {"ontimeout", T_ONTIMEOUT,},
+       {"ipappend", T_IPAPPEND,},
        {NULL, T_INVALID}
 };
 
@@ -903,7 +945,6 @@ static int parse_integer(char **c, int *dst)
 {
        struct token t;
        char *s = *c;
-       unsigned long temp;
 
        get_token(c, &t, L_SLITERAL);
 
@@ -912,12 +953,7 @@ static int parse_integer(char **c, int *dst)
                return -EINVAL;
        }
 
-       if (strict_strtoul(t.val, 10, &temp) < 0) {
-               printf("Expected unsigned integer: %s\n", t.val);
-               return -EINVAL;
-       }
-
-       *dst = (int)temp;
+       *dst = simple_strtol(t.val, NULL, 10);
 
        free(t.val);
 
@@ -1016,10 +1052,8 @@ static int parse_label_menu(char **c, struct pxe_menu *cfg,
 
        switch (t.type) {
        case T_DEFAULT:
-               if (cfg->default_label)
-                       free(cfg->default_label);
-
-               cfg->default_label = strdup(label->name);
+               if (!cfg->default_label)
+                       cfg->default_label = strdup(label->name);
 
                if (!cfg->default_label)
                        return -ENOMEM;
@@ -1108,7 +1142,12 @@ static int parse_label(char **c, struct pxe_menu *cfg)
                        break;
 
                case T_LOCALBOOT:
-                       err = parse_integer(c, &label->localboot);
+                       label->localboot = 1;
+                       err = parse_integer(c, &label->localboot_val);
+                       break;
+
+               case T_IPAPPEND:
+                       err = parse_integer(c, &label->ipappend);
                        break;
 
                case T_EOL:
@@ -1164,6 +1203,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level)
                err = 0;
                switch (t.type) {
                case T_MENU:
+                       cfg->prompt = 1;
                        err = parse_menu(&p, cfg, b, nest_level);
                        break;
 
@@ -1176,6 +1216,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level)
                        break;
 
                case T_DEFAULT:
+               case T_ONTIMEOUT:
                        err = parse_sliteral(&p, &label_name);
 
                        if (label_name) {
@@ -1193,7 +1234,7 @@ static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level)
                        break;
 
                case T_PROMPT:
-                       err = parse_integer(&p, &cfg->prompt);
+                       eol_or_eof(&p);
                        break;
 
                case T_EOL:
@@ -1276,6 +1317,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
        struct list_head *pos;
        struct menu *m;
        int err;
+       int i = 1;
+       char *default_num = NULL;
 
        /*
         * Create a menu and add items for all the labels.
@@ -1289,18 +1332,23 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
        list_for_each(pos, &cfg->labels) {
                label = list_entry(pos, struct pxe_label, list);
 
-               if (menu_item_add(m, label->name, label) != 1) {
+               sprintf(label->num, "%d", i++);
+               if (menu_item_add(m, label->num, label) != 1) {
                        menu_destroy(m);
                        return NULL;
                }
+               if (cfg->default_label &&
+                   (strcmp(label->name, cfg->default_label) == 0))
+                       default_num = label->num;
+
        }
 
        /*
         * After we've created items for each label in the menu, set the
         * menu's default label if one was specified.
         */
-       if (cfg->default_label) {
-               err = menu_default_set(m, cfg->default_label);
+       if (default_num) {
+               err = menu_default_set(m, default_num);
                if (err != 1) {
                        if (err != -ENOENT) {
                                menu_destroy(m);
@@ -1367,10 +1415,13 @@ static void handle_pxe_menu(struct pxe_menu *cfg)
         * we give up.
         */
 
-       if (err == 1)
-               label_boot(choice);
-       else if (err != -ENOENT)
+       if (err == 1) {
+               err = label_boot(choice);
+               if (!err)
+                       return;
+       } else if (err != -ENOENT) {
                return;
+       }
 
        boot_unattempted_labels(cfg);
 }
diff --git a/common/cmd_trace.c b/common/cmd_trace.c
new file mode 100644 (file)
index 0000000..ec3137a
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <trace.h>
+#include <asm/io.h>
+
+static int get_args(int argc, char * const argv[], char **buff,
+                   size_t *buff_ptr, size_t *buff_size)
+{
+       if (argc < 2)
+               return -1;
+       if (argc < 4) {
+               *buff_size = getenv_ulong("profsize", 16, 0);
+               *buff = map_sysmem(getenv_ulong("profbase", 16, 0),
+                                  *buff_size);
+               *buff_ptr = getenv_ulong("profoffset", 16, 0);
+       } else {
+               *buff_size = simple_strtoul(argv[3], NULL, 16);
+               *buff = map_sysmem(simple_strtoul(argv[2], NULL, 16),
+                                  *buff_size);
+               *buff_ptr = 0;
+       };
+       return 0;
+}
+
+static int create_func_list(int argc, char * const argv[])
+{
+       size_t buff_size, avail, buff_ptr, used;
+       unsigned int needed;
+       char *buff;
+       int err;
+
+       if (get_args(argc, argv, &buff, &buff_ptr, &buff_size))
+               return -1;
+
+       avail = buff_size - buff_ptr;
+       err = trace_list_functions(buff + buff_ptr, avail, &needed);
+       if (err)
+               printf("Error: truncated (%#x bytes needed)\n", needed);
+       used = min(avail, needed);
+       printf("Function trace dumped to %08lx, size %#zx\n",
+              (ulong)map_to_sysmem(buff + buff_ptr), used);
+       setenv_hex("profbase", map_to_sysmem(buff));
+       setenv_hex("profsize", buff_size);
+       setenv_hex("profoffset", buff_ptr + used);
+
+       return 0;
+}
+
+static int create_call_list(int argc, char * const argv[])
+{
+       size_t buff_size, avail, buff_ptr, used;
+       unsigned int needed;
+       char *buff;
+       int err;
+
+       if (get_args(argc, argv, &buff, &buff_ptr, &buff_size))
+               return -1;
+
+       avail = buff_size - buff_ptr;
+       err = trace_list_calls(buff + buff_ptr, avail, &needed);
+       if (err)
+               printf("Error: truncated (%#x bytes needed)\n", needed);
+       used = min(avail, needed);
+       printf("Call list dumped to %08lx, size %#zx\n",
+              (ulong)map_to_sysmem(buff + buff_ptr), used);
+
+       setenv_hex("profbase", map_to_sysmem(buff));
+       setenv_hex("profsize", buff_size);
+       setenv_hex("profoffset", buff_ptr + used);
+
+       return 0;
+}
+
+int do_trace(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       const char *cmd = argc < 2 ? NULL : argv[1];
+
+       if (!cmd)
+               return cmd_usage(cmdtp);
+       switch (*cmd) {
+       case 'p':
+               trace_set_enabled(0);
+               break;
+       case 'c':
+               if (create_call_list(argc, argv))
+                       return cmd_usage(cmdtp);
+               break;
+       case 'r':
+               trace_set_enabled(1);
+               break;
+       case 'f':
+               if (create_func_list(argc, argv))
+                       return cmd_usage(cmdtp);
+               break;
+       case 's':
+               trace_print_stats();
+               break;
+       default:
+               return CMD_RET_USAGE;
+       }
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       trace,  4,      1,      do_trace,
+       "trace utility commands",
+       "stats                        - display tracing statistics\n"
+       "trace pause                        - pause tracing\n"
+       "trace resume                       - resume tracing\n"
+       "trace funclist [<addr> <size>]     - dump function list into buffer\n"
+       "trace calls  [<addr> <size>]       "
+               "- dump function call trace into buffer"
+);
index 0d421d92fb66b55423b269eeca9e0d425d1f5fa2..d99f444de126813476f371d5cebcfdd28281073c 100644 (file)
@@ -248,13 +248,16 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
        ulong           default_addr;
        int             fdt_noffset;
 #endif
+       const char *select = NULL;
 
        *of_flat_tree = NULL;
        *of_size = 0;
 
-       if (argc > 3 || genimg_has_config(images)) {
+       if (argc > 2)
+               select = argv[2];
+       if (select || genimg_has_config(images)) {
 #if defined(CONFIG_FIT)
-               if (argc > 3) {
+               if (select) {
                        /*
                         * If the FDT blob comes from the FIT image and the
                         * FIT image address is omitted in the command line
@@ -268,18 +271,18 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
                        else
                                default_addr = load_addr;
 
-                       if (fit_parse_conf(argv[3], default_addr,
+                       if (fit_parse_conf(select, default_addr,
                                           &fdt_addr, &fit_uname_config)) {
                                debug("*  fdt: config '%s' from image at 0x%08lx\n",
                                      fit_uname_config, fdt_addr);
-                       } else if (fit_parse_subimage(argv[3], default_addr,
+                       } else if (fit_parse_subimage(select, default_addr,
                                   &fdt_addr, &fit_uname_fdt)) {
                                debug("*  fdt: subimage '%s' from image at 0x%08lx\n",
                                      fit_uname_fdt, fdt_addr);
                        } else
 #endif
                        {
-                               fdt_addr = simple_strtoul(argv[3], NULL, 16);
+                               fdt_addr = simple_strtoul(select, NULL, 16);
                                debug("*  fdt: cmdline image address = 0x%08lx\n",
                                      fdt_addr);
                        }
index f40f1603f316b277646afb26bd1d9ee19b9adc14..b75e119d930e5d70d6ac703f70bbef50687ee21d 100644 (file)
@@ -234,42 +234,45 @@ void fit_print_contents(const void *fit)
  * @fit: pointer to the FIT format image header
  * @noffset: offset of the hash node
  * @p: pointer to prefix string
+ * @type: Type of information to print ("hash" or "sign")
  *
  * fit_image_print_data() lists properies for the processed hash node
  *
+ * This function avoid using puts() since it prints a newline on the host
+ * but does not in U-Boot.
+ *
  * returns:
  *     no returned results
  */
-static void fit_image_print_data(const void *fit, int noffset, const char *p)
+static void fit_image_print_data(const void *fit, int noffset, const char *p,
+                                const char *type)
 {
-       char *algo;
+       const char *keyname;
        uint8_t *value;
        int value_len;
-       int i, ret;
-
-       /*
-        * Check subnode name, must be equal to "hash".
-        * Multiple hash nodes require unique unit node
-        * names, e.g. hash@1, hash@2, etc.
-        */
-       if (strncmp(fit_get_name(fit, noffset, NULL),
-                   FIT_HASH_NODENAME,
-                   strlen(FIT_HASH_NODENAME)) != 0)
-               return;
+       char *algo;
+       int required;
+       int ret, i;
 
-       debug("%s  Hash node:    '%s'\n", p,
+       debug("%s  %s node:    '%s'\n", p, type,
              fit_get_name(fit, noffset, NULL));
-
-       printf("%s  Hash algo:    ", p);
+       printf("%s  %s algo:    ", p, type);
        if (fit_image_hash_get_algo(fit, noffset, &algo)) {
                printf("invalid/unsupported\n");
                return;
        }
-       printf("%s\n", algo);
+       printf("%s", algo);
+       keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+       required = fdt_getprop(fit, noffset, "required", NULL) != NULL;
+       if (keyname)
+               printf(":%s", keyname);
+       if (required)
+               printf(" (required)");
+       printf("\n");
 
        ret = fit_image_hash_get_value(fit, noffset, &value,
                                        &value_len);
-       printf("%s  Hash value:   ", p);
+       printf("%s  %s value:   ", p, type);
        if (ret) {
                printf("unavailable\n");
        } else {
@@ -278,7 +281,18 @@ static void fit_image_print_data(const void *fit, int noffset, const char *p)
                printf("\n");
        }
 
-       debug("%s  Hash len:     %d\n", p, value_len);
+       debug("%s  %s len:     %d\n", p, type, value_len);
+
+       /* Signatures have a time stamp */
+       if (IMAGE_ENABLE_TIMESTAMP && keyname) {
+               time_t timestamp;
+
+               printf("%s  Timestamp:    ", p);
+               if (fit_get_timestamp(fit, noffset, &timestamp))
+                       printf("unavailable\n");
+               else
+                       genimg_print_time(timestamp);
+       }
 }
 
 /**
@@ -303,8 +317,12 @@ static void fit_image_print_verification_data(const void *fit, int noffset,
         * names, e.g. hash@1, hash@2, signature@1, signature@2, etc.
         */
        name = fit_get_name(fit, noffset, NULL);
-       if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
-               fit_image_print_data(fit, noffset, p);
+       if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
+               fit_image_print_data(fit, noffset, p, "Hash");
+       } else if (!strncmp(name, FIT_SIG_NODENAME,
+                               strlen(FIT_SIG_NODENAME))) {
+               fit_image_print_data(fit, noffset, p, "Sign");
+       }
 }
 
 /**
@@ -944,13 +962,23 @@ int fit_image_verify(const void *fit, int image_noffset)
 {
        const void      *data;
        size_t          size;
-       int             noffset;
+       int             noffset = 0;
        char            *err_msg = "";
+       int verify_all = 1;
+       int ret;
 
        /* Get image data and data length */
        if (fit_image_get_data(fit, image_noffset, &data, &size)) {
                err_msg = "Can't get image data/size";
-               return 0;
+               goto error;
+       }
+
+       /* Verify all required signatures */
+       if (IMAGE_ENABLE_VERIFY &&
+           fit_image_verify_required_sigs(fit, image_noffset, data, size,
+                                          gd_fdt_blob(), &verify_all)) {
+               err_msg = "Unable to verify required signature";
+               goto error;
        }
 
        /* Process all hash subnodes of the component image node */
@@ -970,6 +998,15 @@ int fit_image_verify(const void *fit, int image_noffset)
                                                 &err_msg))
                                goto error;
                        puts("+ ");
+               } else if (IMAGE_ENABLE_VERIFY && verify_all &&
+                               !strncmp(name, FIT_SIG_NODENAME,
+                                       strlen(FIT_SIG_NODENAME))) {
+                       ret = fit_image_check_sig(fit, noffset, data,
+                                                       size, -1, &err_msg);
+                       if (ret)
+                               puts("- ");
+                       else
+                               puts("+ ");
                }
        }
 
diff --git a/common/image-sig.c b/common/image-sig.c
new file mode 100644 (file)
index 0000000..5d907cf
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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
+ */
+
+#ifdef USE_HOSTCC
+#include "mkimage.h"
+#include <time.h>
+#else
+#include <common.h>
+#include <malloc.h>
+DECLARE_GLOBAL_DATA_PTR;
+#endif /* !USE_HOSTCC*/
+#include <image.h>
+#include <rsa.h>
+
+#define IMAGE_MAX_HASHED_NODES         100
+
+struct image_sig_algo image_sig_algos[] = {
+       {
+               "sha1,rsa2048",
+               rsa_sign,
+               rsa_add_verify_data,
+               rsa_verify,
+       }
+};
+
+struct image_sig_algo *image_get_sig_algo(const char *name)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) {
+               if (!strcmp(image_sig_algos[i].name, name))
+                       return &image_sig_algos[i];
+       }
+
+       return NULL;
+}
+
+/**
+ * fit_region_make_list() - Make a list of image regions
+ *
+ * Given a list of fdt_regions, create a list of image_regions. This is a
+ * simple conversion routine since the FDT and image code use different
+ * structures.
+ *
+ * @fit: FIT image
+ * @fdt_regions: Pointer to FDT regions
+ * @count: Number of FDT regions
+ * @region: Pointer to image regions, which must hold @count records. If
+ * region is NULL, then (except for an SPL build) the array will be
+ * allocated.
+ * @return: Pointer to image regions
+ */
+struct image_region *fit_region_make_list(const void *fit,
+               struct fdt_region *fdt_regions, int count,
+               struct image_region *region)
+{
+       int i;
+
+       debug("Hash regions:\n");
+       debug("%10s %10s\n", "Offset", "Size");
+
+       /*
+        * Use malloc() except in SPL (to save code size). In SPL the caller
+        * must allocate the array.
+        */
+#ifndef CONFIG_SPL_BUILD
+       if (!region)
+               region = calloc(sizeof(*region), count);
+#endif
+       if (!region)
+               return NULL;
+       for (i = 0; i < count; i++) {
+               debug("%10x %10x\n", fdt_regions[i].offset,
+                     fdt_regions[i].size);
+               region[i].data = fit + fdt_regions[i].offset;
+               region[i].size = fdt_regions[i].size;
+       }
+
+       return region;
+}
+
+static int fit_image_setup_verify(struct image_sign_info *info,
+               const void *fit, int noffset, int required_keynode,
+               char **err_msgp)
+{
+       char *algo_name;
+
+       if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
+               *err_msgp = "Can't get hash algo property";
+               return -1;
+       }
+       memset(info, '\0', sizeof(*info));
+       info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+       info->fit = (void *)fit;
+       info->node_offset = noffset;
+       info->algo = image_get_sig_algo(algo_name);
+       info->fdt_blob = gd_fdt_blob();
+       info->required_keynode = required_keynode;
+       printf("%s:%s", algo_name, info->keyname);
+
+       if (!info->algo) {
+               *err_msgp = "Unknown signature algorithm";
+               return -1;
+       }
+
+       return 0;
+}
+
+int fit_image_check_sig(const void *fit, int noffset, const void *data,
+               size_t size, int required_keynode, char **err_msgp)
+{
+       struct image_sign_info info;
+       struct image_region region;
+       uint8_t *fit_value;
+       int fit_value_len;
+
+       *err_msgp = NULL;
+       if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+                                  err_msgp))
+               return -1;
+
+       if (fit_image_hash_get_value(fit, noffset, &fit_value,
+                                    &fit_value_len)) {
+               *err_msgp = "Can't get hash value property";
+               return -1;
+       }
+
+       region.data = data;
+       region.size = size;
+
+       if (info.algo->verify(&info, &region, 1, fit_value, fit_value_len)) {
+               *err_msgp = "Verification failed";
+               return -1;
+       }
+
+       return 0;
+}
+
+static int fit_image_verify_sig(const void *fit, int image_noffset,
+               const char *data, size_t size, const void *sig_blob,
+               int sig_offset)
+{
+       int noffset;
+       char *err_msg = "";
+       int verified = 0;
+       int ret;
+
+       /* Process all hash subnodes of the component image node */
+       for (noffset = fdt_first_subnode(fit, image_noffset);
+            noffset >= 0;
+            noffset = fdt_next_subnode(fit, noffset)) {
+               const char *name = fit_get_name(fit, noffset, NULL);
+
+               if (!strncmp(name, FIT_SIG_NODENAME,
+                            strlen(FIT_SIG_NODENAME))) {
+                       ret = fit_image_check_sig(fit, noffset, data,
+                                                       size, -1, &err_msg);
+                       if (ret) {
+                               puts("- ");
+                       } else {
+                               puts("+ ");
+                               verified = 1;
+                               break;
+                       }
+               }
+       }
+
+       if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+               err_msg = "Corrupted or truncated tree";
+               goto error;
+       }
+
+       return verified ? 0 : -EPERM;
+
+error:
+       printf(" error!\n%s for '%s' hash node in '%s' image node\n",
+              err_msg, fit_get_name(fit, noffset, NULL),
+              fit_get_name(fit, image_noffset, NULL));
+       return -1;
+}
+
+int fit_image_verify_required_sigs(const void *fit, int image_noffset,
+               const char *data, size_t size, const void *sig_blob,
+               int *no_sigsp)
+{
+       int verify_count = 0;
+       int noffset;
+       int sig_node;
+
+       /* Work out what we need to verify */
+       *no_sigsp = 1;
+       sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+       if (sig_node < 0) {
+               debug("%s: No signature node found: %s\n", __func__,
+                     fdt_strerror(sig_node));
+               return 0;
+       }
+
+       for (noffset = fdt_first_subnode(sig_blob, sig_node);
+            noffset >= 0;
+            noffset = fdt_next_subnode(sig_blob, noffset)) {
+               const char *required;
+               int ret;
+
+               required = fdt_getprop(sig_blob, noffset, "required", NULL);
+               if (!required || strcmp(required, "image"))
+                       continue;
+               ret = fit_image_verify_sig(fit, image_noffset, data, size,
+                                       sig_blob, noffset);
+               if (ret) {
+                       printf("Failed to verify required signature '%s'\n",
+                              fit_get_name(sig_blob, noffset, NULL));
+                       return ret;
+               }
+               verify_count++;
+       }
+
+       if (verify_count)
+               *no_sigsp = 0;
+
+       return 0;
+}
+
+int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
+                        char **err_msgp)
+{
+       char * const exc_prop[] = {"data"};
+       const char *prop, *end, *name;
+       struct image_sign_info info;
+       const uint32_t *strings;
+       uint8_t *fit_value;
+       int fit_value_len;
+       int max_regions;
+       int i, prop_len;
+       char path[200];
+       int count;
+
+       debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
+             fit_get_name(fit, noffset, NULL),
+             fit_get_name(gd_fdt_blob(), required_keynode, NULL));
+       *err_msgp = NULL;
+       if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+                                  err_msgp))
+               return -1;
+
+       if (fit_image_hash_get_value(fit, noffset, &fit_value,
+                                    &fit_value_len)) {
+               *err_msgp = "Can't get hash value property";
+               return -1;
+       }
+
+       /* Count the number of strings in the property */
+       prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
+       end = prop ? prop + prop_len : prop;
+       for (name = prop, count = 0; name < end; name++)
+               if (!*name)
+                       count++;
+       if (!count) {
+               *err_msgp = "Can't get hashed-nodes property";
+               return -1;
+       }
+
+       /* Add a sanity check here since we are using the stack */
+       if (count > IMAGE_MAX_HASHED_NODES) {
+               *err_msgp = "Number of hashed nodes exceeds maximum";
+               return -1;
+       }
+
+       /* Create a list of node names from those strings */
+       char *node_inc[count];
+
+       debug("Hash nodes (%d):\n", count);
+       for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
+               debug("   '%s'\n", name);
+               node_inc[i] = (char *)name;
+       }
+
+       /*
+        * Each node can generate one region for each sub-node. Allow for
+        * 7 sub-nodes (hash@1, signature@1, etc.) and some extra.
+        */
+       max_regions = 20 + count * 7;
+       struct fdt_region fdt_regions[max_regions];
+
+       /* Get a list of regions to hash */
+       count = fdt_find_regions(fit, node_inc, count,
+                       exc_prop, ARRAY_SIZE(exc_prop),
+                       fdt_regions, max_regions - 1,
+                       path, sizeof(path), 0);
+       if (count < 0) {
+               *err_msgp = "Failed to hash configuration";
+               return -1;
+       }
+       if (count == 0) {
+               *err_msgp = "No data to hash";
+               return -1;
+       }
+       if (count >= max_regions - 1) {
+               *err_msgp = "Too many hash regions";
+               return -1;
+       }
+
+       /* Add the strings */
+       strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
+       if (strings) {
+               fdt_regions[count].offset = fdt_off_dt_strings(fit) +
+                               fdt32_to_cpu(strings[0]);
+               fdt_regions[count].size = fdt32_to_cpu(strings[1]);
+               count++;
+       }
+
+       /* Allocate the region list on the stack */
+       struct image_region region[count];
+
+       fit_region_make_list(fit, fdt_regions, count, region);
+       if (info.algo->verify(&info, region, count, fit_value,
+                             fit_value_len)) {
+               *err_msgp = "Verification failed";
+               return -1;
+       }
+
+       return 0;
+}
+
+static int fit_config_verify_sig(const void *fit, int conf_noffset,
+               const void *sig_blob, int sig_offset)
+{
+       int noffset;
+       char *err_msg = "";
+       int verified = 0;
+       int ret;
+
+       /* Process all hash subnodes of the component conf node */
+       for (noffset = fdt_first_subnode(fit, conf_noffset);
+            noffset >= 0;
+            noffset = fdt_next_subnode(fit, noffset)) {
+               const char *name = fit_get_name(fit, noffset, NULL);
+
+               if (!strncmp(name, FIT_SIG_NODENAME,
+                            strlen(FIT_SIG_NODENAME))) {
+                       ret = fit_config_check_sig(fit, noffset, sig_offset,
+                                                  &err_msg);
+                       if (ret) {
+                               puts("- ");
+                       } else {
+                               puts("+ ");
+                               verified = 1;
+                               break;
+                       }
+               }
+       }
+
+       if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+               err_msg = "Corrupted or truncated tree";
+               goto error;
+       }
+
+       return verified ? 0 : -EPERM;
+
+error:
+       printf(" error!\n%s for '%s' hash node in '%s' config node\n",
+              err_msg, fit_get_name(fit, noffset, NULL),
+              fit_get_name(fit, conf_noffset, NULL));
+       return -1;
+}
+
+int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
+               const void *sig_blob)
+{
+       int noffset;
+       int sig_node;
+
+       /* Work out what we need to verify */
+       sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+       if (sig_node < 0) {
+               debug("%s: No signature node found: %s\n", __func__,
+                     fdt_strerror(sig_node));
+               return 0;
+       }
+
+       for (noffset = fdt_first_subnode(sig_blob, sig_node);
+            noffset >= 0;
+            noffset = fdt_next_subnode(sig_blob, noffset)) {
+               const char *required;
+               int ret;
+
+               required = fdt_getprop(sig_blob, noffset, "required", NULL);
+               if (!required || strcmp(required, "conf"))
+                       continue;
+               ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
+                                           noffset);
+               if (ret) {
+                       printf("Failed to verify required signature '%s'\n",
+                              fit_get_name(sig_blob, noffset, NULL));
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+int fit_config_verify(const void *fit, int conf_noffset)
+{
+       return !fit_config_verify_required_sigs(fit, conf_noffset,
+                                               gd_fdt_blob());
+}
index f863502ab130d0bf08ab1f8cf8e526c31484956a..1be384f26a85964d6b6b84a110b65038e89467a8 100644 (file)
@@ -816,20 +816,23 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
        ulong           default_addr;
        int             rd_noffset;
 #endif
+       const char *select = NULL;
 
        *rd_start = 0;
        *rd_end = 0;
 
+       if (argc >= 2)
+               select = argv[1];
        /*
         * Look for a '-' which indicates to ignore the
         * ramdisk argument
         */
-       if ((argc >= 3) && (strcmp(argv[2], "-") ==  0)) {
+       if (select && strcmp(select, "-") ==  0) {
                debug("## Skipping init Ramdisk\n");
                rd_len = rd_data = 0;
-       } else if (argc >= 3 || genimg_has_config(images)) {
+       } else if (select || genimg_has_config(images)) {
 #if defined(CONFIG_FIT)
-               if (argc >= 3) {
+               if (select) {
                        /*
                         * If the init ramdisk comes from the FIT image and
                         * the FIT image address is omitted in the command
@@ -841,12 +844,12 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
                        else
                                default_addr = load_addr;
 
-                       if (fit_parse_conf(argv[2], default_addr,
-                                               &rd_addr, &fit_uname_config)) {
+                       if (fit_parse_conf(select, default_addr,
+                                          &rd_addr, &fit_uname_config)) {
                                debug("*  ramdisk: config '%s' from image at "
                                                "0x%08lx\n",
                                                fit_uname_config, rd_addr);
-                       } else if (fit_parse_subimage(argv[2], default_addr,
+                       } else if (fit_parse_subimage(select, default_addr,
                                                &rd_addr, &fit_uname_ramdisk)) {
                                debug("*  ramdisk: subimage '%s' from image at "
                                                "0x%08lx\n",
@@ -854,7 +857,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
                        } else
 #endif
                        {
-                               rd_addr = simple_strtoul(argv[2], NULL, 16);
+                               rd_addr = simple_strtoul(select, NULL, 16);
                                debug("*  ramdisk: cmdline image address = "
                                                "0x%08lx\n",
                                                rd_addr);
@@ -918,7 +921,10 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 #endif
                default:
 #ifdef CONFIG_SUPPORT_RAW_INITRD
-                       if (argc >= 3 && (end = strchr(argv[2], ':'))) {
+                       end = NULL;
+                       if (select)
+                               end = strchr(select, ':');
+                       if (end) {
                                rd_len = simple_strtoul(++end, NULL, 16);
                                rd_data = rd_addr;
                        } else
index 457970f770ce774b6c3e5f461f3216b411258951..4599d03c3ad6a3d6e6b36d25d14e6d2efce71c42 100644 (file)
@@ -170,9 +170,9 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
                      block_dev_desc_t *dev_desc);
 int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
                      struct us_data *ss);
-unsigned long usb_stor_read(int device, unsigned long blknr,
+unsigned long usb_stor_read(int device, lbaint_t blknr,
                            lbaint_t blkcnt, void *buffer);
-unsigned long usb_stor_write(int device, unsigned long blknr,
+unsigned long usb_stor_write(int device, lbaint_t blknr,
                             lbaint_t blkcnt, const void *buffer);
 struct usb_device * usb_get_dev_index(int index);
 void uhci_show_temp_int_td(void);
@@ -1054,7 +1054,7 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor,
 }
 #endif /* CONFIG_USB_BIN_FIXUP */
 
-unsigned long usb_stor_read(int device, unsigned long blknr,
+unsigned long usb_stor_read(int device, lbaint_t blknr,
                            lbaint_t blkcnt, void *buffer)
 {
        lbaint_t start, blks;
@@ -1127,7 +1127,7 @@ retry_it:
        return blkcnt;
 }
 
-unsigned long usb_stor_write(int device, unsigned long blknr,
+unsigned long usb_stor_write(int device, lbaint_t blknr,
                                lbaint_t blkcnt, const void *buffer)
 {
        lbaint_t start, blks;
index ddf350e8e9ce5788a9f3e021ada5d3966092b2c6..81c258421629359a51d0d9a43ba45e039e9b99e8 100644 (file)
--- a/config.mk
+++ b/config.mk
@@ -210,6 +210,11 @@ CPPFLAGS += -ffunction-sections -fdata-sections
 LDFLAGS_FINAL += --gc-sections
 endif
 
+# TODO(sjg@chromium.org): Is this correct on Mac OS?
+ifdef CONFIG_FIT_SIGNATURE
+HOSTLIBS       += -lssl -lcrypto
+endif
+
 ifneq ($(CONFIG_SYS_TEXT_BASE),)
 CPPFLAGS += -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE)
 endif
@@ -268,6 +273,16 @@ CFLAGS += $(CFLAGS_WARN)
 CFLAGS_STACK := $(call cc-option,-fstack-usage)
 CFLAGS += $(CFLAGS_STACK)
 
+BCURDIR = $(subst $(SRCTREE)/,,$(CURDIR:$(obj)%=%))
+
+ifeq ($(findstring examples/,$(BCURDIR)),)
+ifeq ($(CONFIG_SPL_BUILD),)
+ifdef FTRACE
+CFLAGS += -finstrument-functions -DFTRACE
+endif
+endif
+endif
+
 # $(CPPFLAGS) sets -g, which causes gcc to pass a suitable -g<format>
 # option to the assembler.
 AFLAGS_DEBUG :=
@@ -330,7 +345,6 @@ export      CONFIG_SYS_TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS
 #########################################################################
 
 # Allow boards to use custom optimize flags on a per dir/file basis
-BCURDIR = $(subst $(SRCTREE)/,,$(CURDIR:$(obj)%=%))
 ALL_AFLAGS = $(AFLAGS) $(AFLAGS_$(BCURDIR)/$(@F)) $(AFLAGS_$(BCURDIR))
 ALL_CFLAGS = $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR))
 EXTRA_CPPFLAGS = $(CPPFLAGS_$(BCURDIR)/$(@F)) $(CPPFLAGS_$(BCURDIR))
diff --git a/doc/README.plan9 b/doc/README.plan9
new file mode 100644 (file)
index 0000000..2d3d0e0
--- /dev/null
@@ -0,0 +1,18 @@
+Plan 9 from Bell Labs kernel images require additional setup to pass
+configuration information to the kernel.  An environment variable named
+confaddr must be defined with the same value as CONFADDR (see mem.h).
+Use of this facility is optional, but should be preferable to manual
+configuration.
+
+When booting an image, arguments supplied to the bootm command will be
+copied to CONFADDR.  If no arguments are specified, the contents of the
+bootargs environment variable will be copied.
+
+If no command line arguments or bootargs are defined, CONFADDR is left
+uninitialized to permit manual configuration.  For example, PC-style
+configuration could be simulated by issuing a fatload in bootcmd:
+
+  # setenv bootcmd fatload mmc 0 $confaddr plan9.ini; ...; bootm
+
+Steven Stallion
+June 2013
index cd7e7ee9b346e4c1323c33f731ee1cf035a650f0..2b1f76b8d0287a993df33f9c0d72c72564ffddd9 100644 (file)
@@ -21,13 +21,13 @@ Environment of the SRIO or PCIE boot:
        e) Slave's RCW should configure the SerDes for SRIO or PCIE boot port, set
           the boot location to SRIO or PCIE, and holdoff all the cores.
 
-       ----------        -----------             -----------
-       |                 |       |         |             |         |
-       |                 |       |         |             |         |
+       -----------       -----------             -----------
+       |         |       |         |             |         |
+       |         |       |         |             |         |
        | NorFlash|<----->| Master  |SRIO or PCIE |  Slave  |<---->[EEPROM]
-       |                 |       |         |<===========>|         |
-       |                 |       |         |             |         |
-       ----------        -----------             -----------
+       |         |       |         |<===========>|         |
+       |         |       |         |             |         |
+       -----------       -----------             -----------
 
 The example based on P4080DS platform:
        Two P4080DS platforms can be used to implement the boot from SRIO or PCIE.
@@ -87,26 +87,32 @@ How to use this feature:
           Please refer to the examples given above.
 
        2. U-Boot image's compilation.
-               For master, U-Boot image should be generated normally.
+          For master, U-Boot image should be generated normally.
 
-               For example, master U-Boot image used on P4080DS should be compiled with
+          For example, master U-Boot image used on P4080DS should be compiled with
 
                                make P4080DS_config.
 
-               For slave, U-Boot image should be generated specifically by
+          For slave, U-Boot image should be generated specifically by
 
                                make xxxx_SRIO_PCIE_BOOT_config.
 
-               For example, slave U-Boot image used on P4080DS should be compiled with
+          For example, slave U-Boot image used on P4080DS should be compiled with
 
                                make P4080DS_SRIO_PCIE_BOOT_config.
 
        3. Necessary modifications based on a specific environment.
-               For a specific environment, the addresses of the slave's U-Boot image,
-               UCode, ENV stored in master's NorFlash, and any other configurations
-               can be modified in the file:
-                                       include/configs/corenet_ds.h.
+          For a specific environment, the addresses of the slave's U-Boot image,
+          UCode, ENV stored in master's NorFlash, and any other configurations
+          can be modified in the file:
+                               include/configs/corenet_ds.h.
 
        4. Set and save the environment variable "bootmaster" with "SRIO1", "SRIO2"
           or "PCIE1", "PCIE2", "PCIE3" for master, and then restart it in order to
           perform the role as a master for boot from SRIO or PCIE.
+
+NOTE: When the Slave's ENV parameters are stored in Master's NorFlash,
+      it can fetch them through PCIE or SRIO interface. But the ENV
+      parameters can not be modified by "saveenv" or other commands under
+      the Slave's u-boot environment, because the Slave can not erase,
+      write Master's NorFlash by PCIE or SRIO link.
diff --git a/doc/README.trace b/doc/README.trace
new file mode 100644 (file)
index 0000000..b535c06
--- /dev/null
@@ -0,0 +1,361 @@
+#
+# Copyright (c) 2013 The Chromium OS Authors.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundatio; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+Tracing in U-Boot
+=================
+
+U-Boot supports a simple tracing feature which allows a record of excecution
+to be collected and sent to a host machine for analysis. At present the
+main use for this is to profile boot time.
+
+
+Overview
+--------
+
+The trace feature uses GCC's instrument-functions feature to trace all
+function entry/exit points. These are then recorded in a memory buffer.
+The memory buffer can be saved to the host over a network link using
+tftpput or by writing to an attached memory device such as MMC.
+
+On the host, the file is first converted with a tool called 'proftool',
+which extracts useful information from it. The resulting trace output
+resembles that emitted by Linux's ftrace feature, so can be visually
+displayed by pytimechart.
+
+
+Quick-start using Sandbox
+-------------------------
+
+Sandbox is a build of U-Boot that can run under Linux so it is a convenient
+way of trying out tracing before you use it on your actual board. To do
+this, follow these steps:
+
+Add the following to include/configs/sandbox.h (if not already there)
+
+#define CONFIG_TRACE
+#define CONFIG_CMD_TRACE
+#define CONFIG_TRACE_BUFFER_SIZE               (16 << 20)
+#define CONFIG_TRACE_EARLY_SIZE                (8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR                0x00100000
+
+Build sandbox U-Boot with tracing enabled:
+
+$ make FTRACE=1 O=sandbox sandbox_config
+$ make FTRACE=1 O=sandbox
+
+Run sandbox, wait for a bit of trace information to appear, and then capture
+a trace:
+
+$ ./sandbox/u-boot
+
+
+U-Boot 2013.04-rc2-00100-ga72fcef (Apr 17 2013 - 19:25:24)
+
+DRAM:  128 MiB
+trace: enabled
+Using default environment
+
+In:    serial
+Out:   serial
+Err:   serial
+=>trace stats
+        671,406 function sites
+         69,712 function calls
+              0 untracked function calls
+         73,373 traced function calls
+             16 maximum observed call depth
+             15 call depth limit
+         66,491 calls not traced due to depth
+=>trace stats
+        671,406 function sites
+      1,279,450 function calls
+              0 untracked function calls
+        950,490 traced function calls (333217 dropped due to overflow)
+             16 maximum observed call depth
+             15 call depth limit
+      1,275,767 calls not traced due to depth
+=>trace calls 0 e00000
+Call list dumped to 00000000, size 0xae0a40
+=>print
+baudrate=115200
+profbase=0
+profoffset=ae0a40
+profsize=e00000
+stderr=serial
+stdin=serial
+stdout=serial
+
+Environment size: 117/8188 bytes
+=>sb save host 0 trace 0 ${profoffset}
+11405888 bytes written in 10 ms (1.1 GiB/s)
+=>reset
+
+
+Then run proftool to convert the trace information to ftrace format.
+
+$ ./sandbox/tools/proftool -m sandbox/System.map -p trace dump-ftrace >trace.txt
+
+Finally run pytimechart to display it:
+
+$ pytimechart trace.txt
+
+Using this tool you can zoom and pan across the trace, with the function
+calls on the left and little marks representing the start and end of each
+function.
+
+
+CONFIG Options
+--------------
+
+- CONFIG_TRACE
+               Enables the trace feature in U-Boot.
+
+- CONFIG_CMD_TRACE
+               Enables the trace command.
+
+- CONFIG_TRACE_BUFFER_SIZE
+               Size of trace buffer to allocate for U-Boot. This buffer is
+               used after relocation, as a place to put function tracing
+               information. The address of the buffer is determined by
+               the relocation code.
+
+- CONFIG_TRACE_EARLY
+               Define this to start tracing early, before relocation.
+
+- CONFIG_TRACE_EARLY_SIZE
+               Size of 'early' trace buffer. Before U-Boot has relocated
+               it doesn't have a proper trace buffer. On many boards
+               you can define an area of memory to use for the trace
+               buffer until the 'real' trace buffer is available after
+               relocation. The contents of this buffer are then copied to
+               the real buffer.
+
+- CONFIG_TRACE_EARLY_ADDR
+               Address of early trace buffer
+
+
+Building U-Boot with Tracing Enabled
+------------------------------------
+
+Pass 'FTRACE=1' to the U-Boot Makefile to actually instrument the code.
+This is kept as a separate option so that it is easy to enable/disable
+instrumenting from the command line instead of having to change board
+config files.
+
+
+Collecting Trace Data
+---------------------
+
+When you run U-Boot on your board it will collect trace data up to the
+limit of the trace buffer size you have specified. Once that is exhausted
+no more data will be collected.
+
+Collecting trace data has an affect on execution time/performance. You
+will notice this particularly with trvial functions - the overhead of
+recording their execution may even exceed their normal execution time.
+In practice this doesn't matter much so long as you are aware of the
+effect. Once you have done your optimisations, turn off tracing before
+doing end-to-end timing.
+
+The best time to start tracing is right at the beginning of U-Boot. The
+best time to stop tracing is right at the end. In practice it is hard
+to achieve these ideals.
+
+This implementation enables tracing early in board_init_f(). This means
+that it captures most of the board init process, missing only the
+early architecture-specific init. However, it also misses the entire
+SPL stage if there is one.
+
+U-Boot typically ends with a 'bootm' command which loads and runs an
+OS. There is useful trace data in the execution of that bootm
+command. Therefore this implementation provides a way to collect trace
+data after bootm has finished processing, but just before it jumps to
+the OS. In practical terms, U-Boot runs the 'fakegocmd' environment
+variable at this point. This variable should have a short script which
+collects the trace data and writes it somewhere.
+
+Trace data collection relies on a microsecond timer, accesed through
+timer_get_us(). So the first think you should do is make sure that
+this produces sensible results for your board. Suitable sources for
+this timer include high resolution timers, PWMs or profile timers if
+available. Most modern SOCs have a suitable timer for this. Make sure
+that you mark this timer (and anything it calls) with
+__attribute__((no_instrument_function)) so that the trace library can
+use it without causing an infinite loop.
+
+
+Commands
+--------
+
+The trace command has variable sub-commands:
+
+- stats
+               Display tracing statistics
+
+- pause
+               Pause tracing
+
+- resume
+               Resume tracing
+
+- funclist [<addr> <size>]
+               Dump a list of functions into the buffer
+
+- calls  [<addr> <size>]
+               Dump function call trace into buffer
+
+If the address and size are not given, these are obtained from environment
+variables (see below). In any case the environment variables are updated
+after the command runs.
+
+
+Environment Variables
+---------------------
+
+The following are used:
+
+- profbase
+               Base address of trace output buffer
+
+- profoffset
+               Offset of first unwritten byte in trace output buffer
+
+- profsize
+               Size of trace output buffer
+
+All of these are set by the 'trace calls' command.
+
+These variables keep track of the amount of data written to the trace
+output buffer by the 'trace' command. The trace commands which write data
+to the output buffer can use these to specify the buffer to write to, and
+update profoffset each time. This allows successive commands to append data
+to the same buffer, for example:
+
+       trace funclist 10000 e00000
+       trace calls
+
+(the latter command appends more data to the buffer).
+
+
+- fakegocmd
+               Specifies commands to run just before booting the OS. This
+               is a useful time to write the trace data to the host for
+               processing.
+
+
+Writing Out Trace Data
+----------------------
+
+Once the trace data is in an output buffer in memory there are various ways
+to transmit it to the host. Notably you can use tftput to send the data
+over a network link:
+
+fakegocmd=trace pause; usb start; set autoload n; bootp;
+       trace calls 10000000 1000000;
+       tftpput ${profbase} ${profoffset} 192.168.1.4:/tftpboot/calls
+
+This starts up USB (to talk to an attached USB Ethernet dongle), writes
+a trace log to address 10000000 and sends it to a host machine using
+TFTP. After this, U-Boot will boot the OS normally, albeit a little
+later.
+
+
+Converting Trace Output Data
+----------------------------
+
+The trace output data is kept in a binary format which is not documented
+here. To convert it into something useful, you can use proftool.
+
+This tool must be given the U-Boot map file and the trace data received
+from running that U-Boot. It produces a text output file.
+
+Options
+       -m <map_file>
+               Specify U-Boot map file
+
+       -p <trace_file>
+               Specifiy profile/trace file
+
+Commands:
+
+- dump-ftrace
+       Write a text dump of the file in Linux ftrace format to stdout
+
+
+Viewing the Trace Data
+----------------------
+
+You can use pytimechart for this (sudo apt-get pytimechart might work on
+your Debian-style machine, and use your favourite search engine to obtain
+documentation). It expects the file to have a .txt extension. The program
+has terse user interface but is very convenient for viewing U-Boot
+profile information.
+
+
+Workflow Suggestions
+--------------------
+
+The following suggestions may be helpful if you are trying to reduce boot
+time:
+
+1. Enable CONFIG_BOOTSTAGE and CONFIG_BOOTSTAGE_REPORT. This should get
+you are helpful overall snapshot of the boot time.
+
+2. Build U-Boot with tracing and run it. Note the difference in boot time
+(it is common for tracing to add 10% to the time)
+
+3. Collect the trace information as descibed above. Use this to find where
+all the time is being spent.
+
+4. Take a look at that code and see if you can optimise it. Perhaps it is
+possible to speed up the initialisation of a device, or remove an unused
+feature.
+
+5. Rebuild, run and collect again. Compare your results.
+
+6. Keep going until you run out of steam, or your boot is fast enough.
+
+
+Configuring Trace
+-----------------
+
+There are a few parameters in the code that you may want to consider.
+There is a function call depth limit (set to 15 by default). When the
+stack depth goes above this then no tracing information is recorded.
+The maximum depth reached is recorded and displayed by the 'trace stats'
+command.
+
+
+Future Work
+-----------
+
+Tracing could be a little tidier in some areas, for example providing
+run-time configuration options for trace.
+
+Some other features that might be useful:
+
+- Trace filter to select which functions are recorded
+- Sample-based profiling using a timer interrupt
+- Better control over trace depth
+- Compression of trace information
+
+
+Simon Glass <sjg@chromium.org>
+April 2013
diff --git a/doc/device-tree-bindings/exynos/dwmmc.txt b/doc/device-tree-bindings/exynos/dwmmc.txt
new file mode 100644 (file)
index 0000000..566da3b
--- /dev/null
@@ -0,0 +1,54 @@
+* Exynos 5250 DWC_mobile_storage
+
+The Exynos 5250 provides DWC_mobile_storage interface which supports
+. Embedded Multimedia Cards (EMMC-version 4.5)
+. Secure Digital memory (SD mem-version 2.0)
+. Secure Digital I/O (SDIO-version 3.0)
+. Consumer Electronics Advanced Transport Architecture (CE-ATA-version 1.1)
+
+The Exynos 5250 DWC_mobile_storage provides four channels.
+SOC specific and Board specific properties are channel specific.
+
+Required SoC Specific Properties:
+
+- compatible: should be
+       - samsung,exynos5250-dwmmc: for exynos5250 platforms
+
+- reg: physical base address of the controller and length of memory mapped
+       region.
+
+- interrupts: The interrupt number to the cpu.
+
+Required Board Specific Properties:
+
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- samsung,bus-width: The width of the bus used to interface the devices
+       supported by DWC_mobile_storage (SD-MMC/EMMC/SDIO).
+       . Typically the bus width is 4 or 8.
+- samsung,timing: The timing values to be written into the
+       Drv/sample clock selection register of corresponding channel.
+       . It is comprised of 3 values corresponding to the 3 fileds
+         'SelClk_sample', 'SelClk_drv' and 'DIVRATIO' of CLKSEL register.
+       . SelClk_sample: Select sample clock among 8 shifted clocks.
+       . SelClk_drv: Select drv clock among 8 shifted clocks.
+       . DIVRATIO: Clock Divide ratio select.
+       . The above 3 values are used by the clock phase shifter.
+
+Example:
+
+mmc@12200000 {
+       samsung,bus-width = <8>;
+       samsung,timing = <1 3 3>;
+       samsung,removable = <1>;
+}
+In the above example,
+       . The bus width is 8
+       . Timing is comprised of 3 values as explained below
+               1 - SelClk_sample
+               3 - SelClk_drv
+               3 - DIVRATIO
+       . The 'removable' flag indicates whether the the particilar device
+         cannot be removed (always present) or it is a removable device.
+               1 - Indicates that the device is removable.
+               0 - Indicates that the device cannot be removed.
diff --git a/doc/device-tree-bindings/input/cros-ec-keyb.txt b/doc/device-tree-bindings/input/cros-ec-keyb.txt
new file mode 100644 (file)
index 0000000..3118276
--- /dev/null
@@ -0,0 +1,79 @@
+CROS_EC Keyboard
+
+The CROS_EC (Matrix Keyboard Protocol) allows communcation with a secondary
+micro used for keyboard, and possible other features.
+
+The CROS_EC keyboard uses this protocol to receive key scans and produce input
+in U-Boot.
+
+Required properties :
+- compatible : "google,cros-ec-keyb"
+- google,key-rows : Number of key rows
+- google,key-columns : Number of key columns
+
+Optional properties, in addition to those specified by the shared
+matrix-keyboard bindings:
+
+- linux,fn-keymap: a second keymap, same specification as the
+  matrix-keyboard-controller spec but to be used when the KEY_FN modifier
+  key is pressed.
+- google,repeat-delay-ms : delay in milliseconds before repeat starts
+- google,repeat-rate-ms : delay between each subsequent key press
+- google,ghost-filter : enable ghost filtering for this device
+
+Example, taken from daisy:
+
+cros-ec-keyb {
+       compatible = "google,cros-ec-keyb";
+       google,key-rows = <8>;
+       google,key-columns = <13>;
+       google,ghost-filter;
+       google,repeat-delay-ms = <240>;
+       google,repeat-rate-ms = <30>;
+       /*
+               * Keymap entries take the form of 0xRRCCKKKK where
+               * RR=Row CC=Column KKKK=Key Code
+               * The values below are for a US keyboard layout and
+               * are taken from the Linux driver. Note that the
+               * 102ND key is not used for US keyboards.
+               */
+       linux,keymap = <
+               /* CAPSLCK F1         B          F10     */
+               0x0001003a 0x0002003c 0x00030030 0x00040044
+               /* N       =          R_ALT      ESC     */
+               0x00060031 0x0008000d 0x000a0064 0x01010001
+               /* F4      G          F7         H       */
+               0x0102003e 0x01030022 0x01040041 0x01060023
+               /* '       F9         BKSPACE    L_CTRL  */
+               0x01080028 0x01090043 0x010b000e 0x0200001d
+               /* TAB     F3         T          F6      */
+               0x0201000f 0x0202003d 0x02030014 0x02040040
+               /* ]       Y          102ND      [       */
+               0x0205001b 0x02060015 0x02070056 0x0208001a
+               /* F8      GRAVE      F2         5       */
+               0x02090042 0x03010029 0x0302003c 0x03030006
+               /* F5      6          -          \       */
+               0x0304003f 0x03060007 0x0308000c 0x030b002b
+               /* R_CTRL  A          D          F       */
+               0x04000061 0x0401001e 0x04020020 0x04030021
+               /* S       K          J          ;       */
+               0x0404001f 0x04050025 0x04060024 0x04080027
+               /* L       ENTER      Z          C       */
+               0x04090026 0x040b001c 0x0501002c 0x0502002e
+               /* V       X          ,          M       */
+               0x0503002f 0x0504002d 0x05050033 0x05060032
+               /* L_SHIFT /          .          SPACE   */
+               0x0507002a 0x05080035 0x05090034 0x050B0039
+               /* 1       3          4          2       */
+               0x06010002 0x06020004 0x06030005 0x06040003
+               /* 8       7          0          9       */
+               0x06050009 0x06060008 0x0608000b 0x0609000a
+               /* L_ALT   DOWN       RIGHT      Q       */
+               0x060a0038 0x060b006c 0x060c006a 0x07010010
+               /* E       R          W          I       */
+               0x07020012 0x07030013 0x07040011 0x07050017
+               /* U       R_SHIFT    P          O       */
+               0x07060016 0x07070036 0x07080019 0x07090018
+               /* UP      LEFT    */
+               0x070b0067 0x070c0069>;
+};
diff --git a/doc/device-tree-bindings/misc/cros-ec.txt b/doc/device-tree-bindings/misc/cros-ec.txt
new file mode 100644 (file)
index 0000000..07ea7cd
--- /dev/null
@@ -0,0 +1,38 @@
+Chrome OS CROS_EC Binding
+======================
+
+The device tree node which describes the operation of the CROS_EC interface
+is as follows:
+
+Required properties :
+- compatible = "google,cros-ec"
+
+Optional properties :
+- spi-max-frequency : Sets the maximum frequency (in Hz) for SPI bus
+   operation
+- i2c-max-frequency : Sets the maximum frequency (in Hz) for I2C bus
+   operation
+- ec-interrupt : Selects the EC interrupt, defined as a GPIO according
+   to the platform
+- optimise-flash-write : Boolean property - if present then flash blocks
+   containing all 0xff will not be written, since we assume that the EC
+   uses that pattern for erased blocks
+
+The CROS_EC node should appear as a subnode of the interrupt that connects it
+to the EC (e.g. i2c, spi, lpc). The reg property (as usual) will indicate
+the unit address on that bus.
+
+
+Example
+=======
+
+       spi@131b0000 {
+               cros-ec@0 {
+                       reg = <0>;
+                       compatible = "google,cros-ec";
+                       spi-max-frequency = <5000000>;
+                       ec-interrupt = <&gpio 174 1>;
+                       optimise-flash-write;
+                       status = "disabled";
+               };
+       };
index 39652c82d0cf576ce889fdfc0f474d3060b53867..14374da88af0fff839ce105f5e25e9849e7baec9 100644 (file)
@@ -4,7 +4,17 @@
 mkimage \- Generate image for U-Boot
 .SH SYNOPSIS
 .B mkimage
-.RB [\fIoptions\fP]
+.RB "\-l [" "uimage file name" "]"
+
+.B mkimage
+.RB [\fIoptions\fP] " \-f [" "image tree source file" "]" " [" "uimage file name" "]"
+
+.B mkimage
+.RB [\fIoptions\fP] " \-F [" "uimage file name" "]"
+
+.B mkimage
+.RB [\fIoptions\fP] " (legacy mode)"
+
 .SH "DESCRIPTION"
 The
 .B mkimage
@@ -26,7 +36,8 @@ etc.
 The new
 .I FIT (Flattened Image Tree) format
 allows for more flexibility in handling images of various types and also
-enhances integrity protection of images with stronger checksums.
+enhances integrity protection of images with stronger checksums. It also
+supports verified boot.
 
 .SH "OPTIONS"
 
@@ -66,6 +77,10 @@ Set load address with a hex number.
 .BI "\-e [" "entry point" "]"
 Set entry point with a hex number.
 
+.TP
+.BI "\-l"
+List the contents of an image.
+
 .TP
 .BI "\-n [" "image name" "]"
 Set image name to 'image name'.
@@ -81,6 +96,12 @@ Set XIP (execute in place) flag.
 .P
 .B Create FIT image:
 
+.TP
+.BI "\-c [" "comment" "]"
+Specifies a comment to be added when signing. This is typically a useful
+message which describes how the image was signed or some other useful
+information.
+
 .TP
 .BI "\-D [" "dtc options" "]"
 Provide special options to the device tree compiler that is used to
@@ -91,6 +112,33 @@ create the image.
 Image tree source file that describes the structure and contents of the
 FIT image.
 
+.TP
+.BI "\-F"
+Indicates that an existing FIT image should be modified. No dtc
+compilation is performed and the -f flag should not be given.
+This can be used to sign images with additional keys after initial image
+creation.
+
+.TP
+.BI "\-k [" "key_directory" "]"
+Specifies the directory containing keys to use for signing. This directory
+should contain a private key file <name>.key for use with signing and a
+certificate <name>.crt (containing the public key) for use with verification.
+
+.TP
+.BI "\-K [" "key_destination" "]"
+Specifies a compiled device tree binary file (typically .dtb) to write
+public key information into. When a private key is used to sign an image,
+the corresponding public key is written into this file for for run-time
+verification. Typically the file here is the device tree binary used by
+CONFIG_OF_CONTROL in U-Boot.
+
+.TP
+.BI "\-r
+Specifies that keys used to sign the FIT are required. This means that they
+must be verified for the image to boot. Without this option, the verification
+will be optional (useful for testing but not for release).
+
 .SH EXAMPLES
 
 List image information:
@@ -109,10 +157,29 @@ Create FIT image with compressed PowerPC Linux kernel:
 .nf
 .B mkimage -f kernel.its kernel.itb
 .fi
+.P
+Create FIT image with compressed kernel and sign it with keys in the
+/public/signing-keys directory. Add corresponding public keys into u-boot.dtb,
+skipping those for which keys cannot be found. Also add a comment.
+.nf
+.B mkimage -f kernel.its -k /public/signing-keys -K u-boot.dtb \\\\
+-c "Kernel 3.8 image for production devices" kernel.itb
+.fi
+
+.P
+Update an existing FIT image, signing it with additional keys.
+Add corresponding public keys into u-boot.dtb. This will resign all images
+with keys that are available in the new directory. Images that request signing
+with unavailable keys are skipped.
+.nf
+.B mkimage -F -k /secret/signing-keys -K u-boot.dtb \\\\
+-c "Kernel 3.8 image for production devices" kernel.itb
+.fi
 
 .SH HOMEPAGE
 http://www.denx.de/wiki/U-Boot/WebHome
 .PP
 .SH AUTHOR
 This manual page was written by Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
-and Wolfgang Denk <wd@denx.de>
+and Wolfgang Denk <wd@denx.de>. It was updated for image signing by
+Simon Glass <sjg@chromium.org>.
diff --git a/doc/uImage.FIT/sign-configs.its b/doc/uImage.FIT/sign-configs.its
new file mode 100644 (file)
index 0000000..3c17f04
--- /dev/null
@@ -0,0 +1,45 @@
+/dts-v1/;
+
+/ {
+       description = "Chrome OS kernel image with one or more FDT blobs";
+       #address-cells = <1>;
+
+       images {
+               kernel@1 {
+                       data = /incbin/("test-kernel.bin");
+                       type = "kernel_noload";
+                       arch = "sandbox";
+                       os = "linux";
+                       compression = "lzo";
+                       load = <0x4>;
+                       entry = <0x8>;
+                       kernel-version = <1>;
+                       hash@1 {
+                               algo = "sha1";
+                       };
+               };
+               fdt@1 {
+                       description = "snow";
+                       data = /incbin/("sandbox-kernel.dtb");
+                       type = "flat_dt";
+                       arch = "sandbox";
+                       compression = "none";
+                       fdt-version = <1>;
+                       hash@1 {
+                               algo = "sha1";
+                       };
+               };
+       };
+       configurations {
+               default = "conf@1";
+               conf@1 {
+                       kernel = "kernel@1";
+                       fdt = "fdt@1";
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               key-name-hint = "dev";
+                               sign-images = "fdt", "kernel";
+                       };
+               };
+       };
+};
diff --git a/doc/uImage.FIT/sign-images.its b/doc/uImage.FIT/sign-images.its
new file mode 100644 (file)
index 0000000..f69326a
--- /dev/null
@@ -0,0 +1,42 @@
+/dts-v1/;
+
+/ {
+       description = "Chrome OS kernel image with one or more FDT blobs";
+       #address-cells = <1>;
+
+       images {
+               kernel@1 {
+                       data = /incbin/("test-kernel.bin");
+                       type = "kernel_noload";
+                       arch = "sandbox";
+                       os = "linux";
+                       compression = "none";
+                       load = <0x4>;
+                       entry = <0x8>;
+                       kernel-version = <1>;
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               key-name-hint = "dev";
+                       };
+               };
+               fdt@1 {
+                       description = "snow";
+                       data = /incbin/("sandbox-kernel.dtb");
+                       type = "flat_dt";
+                       arch = "sandbox";
+                       compression = "none";
+                       fdt-version = <1>;
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               key-name-hint = "dev";
+                       };
+               };
+       };
+       configurations {
+               default = "conf@1";
+               conf@1 {
+                       kernel = "kernel@1";
+                       fdt = "fdt@1";
+               };
+       };
+};
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
new file mode 100644 (file)
index 0000000..bc9f3fa
--- /dev/null
@@ -0,0 +1,382 @@
+U-Boot FIT Signature Verification
+=================================
+
+Introduction
+------------
+FIT supports hashing of images so that these hashes can be checked on
+loading. This protects against corruption of the image. However it does not
+prevent the substitution of one image for another.
+
+The signature feature allows the hash to be signed with a private key such
+that it can be verified using a public key later. Provided that the private
+key is kept secret and the public key is stored in a non-volatile place,
+any image can be verified in this way.
+
+See verified-boot.txt for more general information on verified boot.
+
+
+Concepts
+--------
+Some familiarity with public key cryptography is assumed in this section.
+
+The procedure for signing is as follows:
+
+   - hash an image in the FIT
+   - sign the hash with a private key to produce a signature
+   - store the resulting signature in the FIT
+
+The procedure for verification is:
+
+   - read the FIT
+   - obtain the public key
+   - extract the signature from the FIT
+   - hash the image from the FIT
+   - verify (with the public key) that the extracted signature matches the
+       hash
+
+The signing is generally performed by mkimage, as part of making a firmware
+image for the device. The verification is normally done in U-Boot on the
+device.
+
+
+Algorithms
+----------
+In principle any suitable algorithm can be used to sign and verify a hash.
+At present only one class of algorithms is supported: SHA1 hashing with RSA.
+This works by hashing the image to produce a 20-byte hash.
+
+While it is acceptable to bring in large cryptographic libraries such as
+openssl on the host side (e.g. mkimage), it is not desirable for U-Boot.
+For the run-time verification side, it is important to keep code and data
+size as small as possible.
+
+For this reason the RSA image verification uses pre-processed public keys
+which can be used with a very small amount of code - just some extraction
+of data from the FDT and exponentiation mod n. Code size impact is a little
+under 5KB on Tegra Seaboard, for example.
+
+It is relatively straightforward to add new algorithms if required. If
+another RSA variant is needed, then it can be added to the table in
+image-sig.c. If another algorithm is needed (such as DSA) then it can be
+placed alongside rsa.c, and its functions added to the table in image-sig.c
+also.
+
+
+Creating an RSA key and certificate
+-----------------------------------
+To create a new public key, size 2048 bits:
+
+$ openssl genrsa -F4 -out keys/dev.key 2048
+
+To create a certificate for this:
+
+$ openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt
+
+If you like you can look at the public key also:
+
+$ openssl rsa -in keys/dev.key -pubout
+
+
+Device Tree Bindings
+--------------------
+The following properties are required in the FIT's signature node(s) to
+allow thes signer to operate. These should be added to the .its file.
+Signature nodes sit at the same level as hash nodes and are called
+signature@1, signature@2, etc.
+
+- algo: Algorithm name (e.g. "sha1,rs2048")
+
+- key-name-hint: Name of key to use for signing. The keys will normally be in
+a single directory (parameter -k to mkimage). For a given key <name>, its
+private key is stored in <name>.key and the certificate is stored in
+<name>.crt.
+
+When the image is signed, the following properties are added (mandatory):
+
+- value: The signature data (e.g. 256 bytes for 2048-bit RSA)
+
+When the image is signed, the following properties are optional:
+
+- timestamp: Time when image was signed (standard Unix time_t format)
+
+- signer-name: Name of the signer (e.g. "mkimage")
+
+- signer-version: Version string of the signer (e.g. "2013.01")
+
+- comment: Additional information about the signer or image
+
+For config bindings (see Signed Configurations below), the following
+additional properties are optional:
+
+- sign-images: A list of images to sign, each being a property of the conf
+node that contains then. The default is "kernel,fdt" which means that these
+two images will be looked up in the config and signed if present.
+
+For config bindings, these properties are added by the signer:
+
+- hashed-nodes: A list of nodes which were hashed by the signer. Each is
+       a string - the full path to node. A typical value might be:
+
+       hashed-nodes = "/", "/configurations/conf@1", "/images/kernel@1",
+               "/images/kernel@1/hash@1", "/images/fdt@1",
+               "/images/fdt@1/hash@1";
+
+- hashed-strings: The start and size of the string region of the FIT that
+       was hashed
+
+Example: See sign-images.its for an example image tree source file and
+sign-configs.its for config signing.
+
+
+Public Key Storage
+------------------
+In order to verify an image that has been signed with a public key we need to
+have a trusted public key. This cannot be stored in the signed image, since
+it would be easy to alter. For this implementation we choose to store the
+public key in U-Boot's control FDT (using CONFIG_OF_CONTROL).
+
+Public keys should be stored as sub-nodes in a /signature node. Required
+properties are:
+
+- algo: Algorithm name (e.g. "sha1,rs2048")
+
+Optional properties are:
+
+- key-name-hint: Name of key used for signing. This is only a hint since it
+is possible for the name to be changed. Verification can proceed by checking
+all available signing keys until one matches.
+
+- required: If present this indicates that the key must be verified for the
+image / configuration to be considered valid. Only required keys are
+normally verified by the FIT image booting algorithm. Valid values are
+"image" to force verification of all images, and "conf" to force verfication
+of the selected configuration (which then relies on hashes in the images to
+verify those).
+
+Each signing algorithm has its own additional properties.
+
+For RSA the following are mandatory:
+
+- rsa,num-bits: Number of key bits (e.g. 2048)
+- rsa,modulus: Modulus (N) as a big-endian multi-word integer
+- rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer
+- rsa,n0-inverse: -1 / modulus[0] mod 2^32
+
+
+Signed Configurations
+---------------------
+While signing images is useful, it does not provide complete protection
+against several types of attack. For example, it it possible to create a
+FIT with the same signed images, but with the configuration changed such
+that a different one is selected (mix and match attack). It is also possible
+to substitute a signed image from an older FIT version into a newer FIT
+(roll-back attack).
+
+As an example, consider this FIT:
+
+/ {
+       images {
+               kernel@1 {
+                       data = <data for kernel1>
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               value = <...kernel signature 1...>
+                       };
+               };
+               kernel@2 {
+                       data = <data for kernel2>
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               value = <...kernel signature 2...>
+                       };
+               };
+               fdt@1 {
+                       data = <data for fdt1>;
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               vaue = <...fdt signature 1...>
+                       };
+               };
+               fdt@2 {
+                       data = <data for fdt2>;
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               vaue = <...fdt signature 2...>
+                       };
+               };
+       };
+       configurations {
+               default = "conf@1";
+               conf@1 {
+                       kernel = "kernel@1";
+                       fdt = "fdt@1";
+               };
+               conf@1 {
+                       kernel = "kernel@2";
+                       fdt = "fdt@2";
+               };
+       };
+};
+
+Since both kernels are signed it is easy for an attacker to add a new
+configuration 3 with kernel 1 and fdt 2:
+
+       configurations {
+               default = "conf@1";
+               conf@1 {
+                       kernel = "kernel@1";
+                       fdt = "fdt@1";
+               };
+               conf@1 {
+                       kernel = "kernel@2";
+                       fdt = "fdt@2";
+               };
+               conf@3 {
+                       kernel = "kernel@1";
+                       fdt = "fdt@2";
+               };
+       };
+
+With signed images, nothing protects against this. Whether it gains an
+advantage for the attacker is debatable, but it is not secure.
+
+To solved this problem, we support signed configurations. In this case it
+is the configurations that are signed, not the image. Each image has its
+own hash, and we include the hash in the configuration signature.
+
+So the above example is adjusted to look like this:
+
+/ {
+       images {
+               kernel@1 {
+                       data = <data for kernel1>
+                       hash@1 {
+                               algo = "sha1";
+                               value = <...kernel hash 1...>
+                       };
+               };
+               kernel@2 {
+                       data = <data for kernel2>
+                       hash@1 {
+                               algo = "sha1";
+                               value = <...kernel hash 2...>
+                       };
+               };
+               fdt@1 {
+                       data = <data for fdt1>;
+                       hash@1 {
+                               algo = "sha1";
+                               value = <...fdt hash 1...>
+                       };
+               };
+               fdt@2 {
+                       data = <data for fdt2>;
+                       hash@1 {
+                               algo = "sha1";
+                               value = <...fdt hash 2...>
+                       };
+               };
+       };
+       configurations {
+               default = "conf@1";
+               conf@1 {
+                       kernel = "kernel@1";
+                       fdt = "fdt@1";
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               value = <...conf 1 signature...>;
+                       };
+               };
+               conf@2 {
+                       kernel = "kernel@2";
+                       fdt = "fdt@2";
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               value = <...conf 1 signature...>;
+                       };
+               };
+       };
+};
+
+
+You can see that we have added hashes for all images (since they are no
+longer signed), and a signature to each configuration. In the above example,
+mkimage will sign configurations/conf@1, the kernel and fdt that are
+pointed to by the configuration (/images/kernel@1, /images/kernel@1/hash@1,
+/images/fdt@1, /images/fdt@1/hash@1) and the root structure of the image
+(so that it isn't possible to add or remove root nodes). The signature is
+written into /configurations/conf@1/signature@1/value. It can easily be
+verified later even if the FIT has been signed with other keys in the
+meantime.
+
+
+Verification
+------------
+FITs are verified when loaded. After the configuration is selected a list
+of required images is produced. If there are 'required' public keys, then
+each image must be verified against those keys. This means that every image
+that might be used by the target needs to be signed with 'required' keys.
+
+This happens automatically as part of a bootm command when FITs are used.
+
+
+Enabling FIT Verification
+-------------------------
+In addition to the options to enable FIT itself, the following CONFIGs must
+be enabled:
+
+CONFIG_FIT_SIGNATURE - enable signing and verfication in FITs
+CONFIG_RSA - enable RSA algorithm for signing
+
+
+Testing
+-------
+An easy way to test signing and verfication is to use the test script
+provided in test/vboot/vboot_test.sh. This uses sandbox (a special version
+of U-Boot which runs under Linux) to show the operation of a 'bootm'
+command loading and verifying images.
+
+A sample run is show below:
+
+$ make O=sandbox sandbox_config
+$ make O=sandbox
+$ O=sandbox ./test/vboot/vboot_test.sh
+Simple Verified Boot Test
+=========================
+
+Please see doc/uImage.FIT/verified-boot.txt for more information
+
+Build keys
+Build FIT with signed images
+Test Verified Boot Run: unsigned signatures:: OK
+Sign images
+Test Verified Boot Run: signed images: OK
+Build FIT with signed configuration
+Test Verified Boot Run: unsigned config: OK
+Sign images
+Test Verified Boot Run: signed config: OK
+
+Test passed
+
+
+Future Work
+-----------
+- Roll-back protection using a TPM is done using the tpm command. This can
+be scripted, but we might consider a default way of doing this, built into
+bootm.
+
+
+Possible Future Work
+--------------------
+- Add support for other RSA/SHA variants, such as rsa4096,sha512.
+- Other algorithms besides RSA
+- More sandbox tests for failure modes
+- Passwords for keys/certificates
+- Perhaps implement OAEP
+- Enhance bootm to permit scripted signature verification (so that a script
+can verify an image but not actually boot it)
+
+
+Simon Glass
+sjg@chromium.org
+1-1-13
diff --git a/doc/uImage.FIT/verified-boot.txt b/doc/uImage.FIT/verified-boot.txt
new file mode 100644 (file)
index 0000000..3c83fbc
--- /dev/null
@@ -0,0 +1,104 @@
+U-Boot Verified Boot
+====================
+
+Introduction
+------------
+Verified boot here means the verification of all software loaded into a
+machine during the boot process to ensure that it is authorised and correct
+for that machine.
+
+Verified boot extends from the moment of system reset to as far as you wish
+into the boot process. An example might be loading U-Boot from read-only
+memory, then loading a signed kernel, then using the kernel's dm-verity
+driver to mount a signed root filesystem.
+
+A key point is that it is possible to field-upgrade the software on machines
+which use verified boot. Since the machine will only run software that has
+been correctly signed, it is safe to read software from an updatable medium.
+It is also possible to add a secondary signed firmware image, in read-write
+memory, so that firmware can easily be upgraded in a secure manner.
+
+
+Signing
+-------
+Verified boot uses cryptographic algorithms to 'sign' software images.
+Images are signed using a private key known only to the signer, but can
+be verified using a public key. As its name suggests the public key can be
+made available without risk to the verification process. The private and
+public keys are mathematically related. For more information on how this
+works look up "public key cryptography" and "RSA" (a particular algorithm).
+
+The signing and verification process looks something like this:
+
+
+      Signing                                      Verification
+      =======                                      ============
+
+ +--------------+                   *
+ | RSA key pair |                   *             +---------------+
+ | .key  .crt   |                   *             | Public key in |
+ +--------------+       +------> public key ----->| trusted place |
+       |                |           *             +---------------+
+       |                |           *                    |
+       v                |           *                    v
+   +---------+          |           *              +--------------+
+   |         |----------+           *              |              |
+   | signer  |                      *              |    U-Boot    |
+   |         |----------+           *              |  signature   |--> yes/no
+   +---------+          |           *              | verification |
+      ^                 |           *              |              |
+      |                 |           *              +--------------+
+      |                 |           *                    ^
+ +----------+           |           *                    |
+ | Software |           +----> signed image -------------+
+ |  image   |                       *
+ +----------+                       *
+
+
+The signature algorithm relies only on the public key to do its work. Using
+this key it checks the signature that it finds in the image. If it verifies
+then we know that the image is OK.
+
+The public key from the signer allows us to verify and therefore trust
+software from updatable memory.
+
+It is critical that the public key be secure and cannot be tampered with.
+It can be stored in read-only memory, or perhaps protected by other on-chip
+crypto provided by some modern SOCs. If the public key can ben changed, then
+the verification is worthless.
+
+
+Chaining Images
+---------------
+The above method works for a signer providing images to a run-time U-Boot.
+It is also possible to extend this scheme to a second level, like this:
+
+1. Master private key is used by the signer to sign a first-stage image.
+2. Master public key is placed in read-only memory.
+2. Secondary private key is created and used to sign second-stage images.
+3. Secondary public key is placed in first stage images
+4. We use the master public key to verify the first-stage image. We then
+use the secondary public key in the first-stage image to verify the second-
+state image.
+5. This chaining process can go on indefinitely. It is recommended to use a
+different key at each stage, so that a compromise in one place will not
+affect the whole change.
+
+
+Flattened Image Tree (FIT)
+--------------------------
+The FIT format is alreay widely used in U-Boot. It is a flattened device
+tree (FDT) in a particular format, with images contained within. FITs
+include hashes to verify images, so it is relatively straightforward to
+add signatures as well.
+
+The public key can be stored in U-Boot's CONFIG_OF_CONTROL device tree in
+a standard place. Then when a FIT it loaded it can be verified using that
+public key. Multiple keys and multiple signatures are supported.
+
+See signature.txt for more information.
+
+
+Simon Glass
+sjg@chromium.org
+1-1-13
index f3adf6485997e5fde82a8c14ad0806527a0118b3..bb8e644cd948ff0f4fb0b6e929f80f0b9020b954 100644 (file)
@@ -133,8 +133,7 @@ int dtt_init_one(int sensor)
        /*
         * Setup PWM Lookup-Table
         */
-       for (i = 0; i < sizeof(pwm_lookup) / sizeof(struct pwm_lookup_entry);
-            i++) {
+       for (i = 0; i < ARRAY_SIZE(pwm_lookup); i++) {
                int address = DTT_PWM_LOOKUP_BASE + 2 * i;
                val = pwm_lookup[i].temp;
                if (is_lm64(sensor))
index 0805e8667877853add06bfc628673826c1dbf146..4331190def8e42f434800d71c92edad0d9f4607e 100644 (file)
@@ -27,6 +27,7 @@ LIB   := $(obj)libinput.o
 
 COBJS-$(CONFIG_I8042_KBD) += i8042.o
 COBJS-$(CONFIG_TEGRA_KEYBOARD) += tegra-kbc.o
+COBJS-$(CONFIG_CROS_EC_KEYB) += cros_ec_keyb.o
 ifdef CONFIG_PS2KBD
 COBJS-y += keyboard.o pc_keyb.o
 COBJS-$(CONFIG_PS2MULT) += ps2mult.o ps2ser.o
diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c
new file mode 100644 (file)
index 0000000..c197308
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Chromium OS Matrix Keyboard
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <cros_ec.h>
+#include <fdtdec.h>
+#include <input.h>
+#include <key_matrix.h>
+#include <stdio_dev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+       KBC_MAX_KEYS            = 8,    /* Maximum keys held down at once */
+};
+
+static struct keyb {
+       struct cros_ec_dev *dev;                /* The CROS_EC device */
+       struct input_config input;      /* The input layer */
+       struct key_matrix matrix;       /* The key matrix layer */
+       int key_rows;                   /* Number of keyboard rows */
+       int key_cols;                   /* Number of keyboard columns */
+       unsigned int repeat_delay_ms;   /* Time before autorepeat starts */
+       unsigned int repeat_rate_ms;    /* Autorepeat rate in ms */
+       int ghost_filter;               /* 1 to enable ghost filter, else 0 */
+       int inited;                     /* 1 if keyboard is ready */
+} config;
+
+
+/**
+ * Check the keyboard controller and return a list of key matrix positions
+ * for which a key is pressed
+ *
+ * @param config       Keyboard config
+ * @param keys         List of keys that we have detected
+ * @param max_count    Maximum number of keys to return
+ * @return number of pressed keys, 0 for none
+ */
+static int check_for_keys(struct keyb *config,
+                          struct key_matrix_key *keys, int max_count)
+{
+       struct key_matrix_key *key;
+       struct mbkp_keyscan scan;
+       unsigned int row, col, bit, data;
+       int num_keys;
+
+       if (cros_ec_scan_keyboard(config->dev, &scan)) {
+               debug("%s: keyboard scan failed\n", __func__);
+               return -1;
+       }
+
+       for (col = num_keys = bit = 0; col < config->matrix.num_cols;
+                       col++) {
+               for (row = 0; row < config->matrix.num_rows; row++) {
+                       unsigned int mask = 1 << (bit & 7);
+
+                       data = scan.data[bit / 8];
+                       if ((data & mask) && num_keys < max_count) {
+                               key = keys + num_keys++;
+                               key->row = row;
+                               key->col = col;
+                               key->valid = 1;
+                       }
+                       bit++;
+               }
+       }
+
+       return num_keys;
+}
+
+/**
+ * Test if keys are available to be read
+ *
+ * @return 0 if no keys available, 1 if keys are available
+ */
+static int kbd_tstc(void)
+{
+       /* Just get input to do this for us */
+       return config.inited ? input_tstc(&config.input) : 0;
+}
+
+/**
+ * Read a key
+ *
+ * @return ASCII key code, or 0 if no key, or -1 if error
+ */
+static int kbd_getc(void)
+{
+       /* Just get input to do this for us */
+       return config.inited ? input_getc(&config.input) : 0;
+}
+
+/**
+ * Check the keyboard, and send any keys that are pressed.
+ *
+ * This is called by input_tstc() and input_getc() when they need more
+ * characters
+ *
+ * @param input                Input configuration
+ * @return 1, to indicate that we have something to look at
+ */
+int cros_ec_kbc_check(struct input_config *input)
+{
+       static struct key_matrix_key last_keys[KBC_MAX_KEYS];
+       static int last_num_keys;
+       struct key_matrix_key keys[KBC_MAX_KEYS];
+       int keycodes[KBC_MAX_KEYS];
+       int num_keys, num_keycodes;
+       int irq_pending, sent;
+
+       /*
+        * Loop until the EC has no more keyscan records, or we have
+        * received at least one character. This means we know that tstc()
+        * will always return non-zero if keys have been pressed.
+        *
+        * Without this loop, a key release (which generates no new ascii
+        * characters) will cause us to exit this function, and just tstc()
+        * may return 0 before all keys have been read from the EC.
+        */
+       do {
+               irq_pending = cros_ec_interrupt_pending(config.dev);
+               if (irq_pending) {
+                       num_keys = check_for_keys(&config, keys, KBC_MAX_KEYS);
+                       last_num_keys = num_keys;
+                       memcpy(last_keys, keys, sizeof(keys));
+               } else {
+                       /*
+                        * EC doesn't want to be asked, so use keys from last
+                        * time.
+                        */
+                       num_keys = last_num_keys;
+                       memcpy(keys, last_keys, sizeof(keys));
+               }
+
+               if (num_keys < 0)
+                       return -1;
+               num_keycodes = key_matrix_decode(&config.matrix, keys,
+                               num_keys, keycodes, KBC_MAX_KEYS);
+               sent = input_send_keycodes(input, keycodes, num_keycodes);
+       } while (irq_pending && !sent);
+
+       return 1;
+}
+
+/**
+ * Decode MBKP keyboard details from the device tree
+ *
+ * @param blob         Device tree blob
+ * @param node         Node to decode from
+ * @param config       Configuration data read from fdt
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_keyb_decode_fdt(const void *blob, int node,
+                               struct keyb *config)
+{
+       /*
+        * Get keyboard rows and columns - at present we are limited to
+        * 8 columns by the protocol (one byte per row scan)
+        */
+       config->key_rows = fdtdec_get_int(blob, node, "google,key-rows", 0);
+       config->key_cols = fdtdec_get_int(blob, node, "google,key-columns", 0);
+       if (!config->key_rows || !config->key_cols ||
+                       config->key_rows * config->key_cols / 8
+                               > CROS_EC_KEYSCAN_COLS) {
+               debug("%s: Invalid key matrix size %d x %d\n", __func__,
+                     config->key_rows, config->key_cols);
+               return -1;
+       }
+       config->repeat_delay_ms = fdtdec_get_int(blob, node,
+                                                "google,repeat-delay-ms", 0);
+       config->repeat_rate_ms = fdtdec_get_int(blob, node,
+                                               "google,repeat-rate-ms", 0);
+       config->ghost_filter = fdtdec_get_bool(blob, node,
+                                              "google,ghost-filter");
+       return 0;
+}
+
+/**
+ * Set up the keyboard. This is called by the stdio device handler.
+ *
+ * We want to do this init when the keyboard is actually used rather than
+ * at start-up, since keyboard input may not currently be selected.
+ *
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_init_keyboard(void)
+{
+       const void *blob = gd->fdt_blob;
+       int node;
+
+       config.dev = board_get_cros_ec_dev();
+       if (!config.dev) {
+               debug("%s: no cros_ec device: cannot init keyboard\n",
+                     __func__);
+               return -1;
+       }
+       node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
+       if (node < 0) {
+               debug("%s: Node not found\n", __func__);
+               return -1;
+       }
+       if (cros_ec_keyb_decode_fdt(blob, node, &config))
+               return -1;
+       input_set_delays(&config.input, config.repeat_delay_ms,
+                        config.repeat_rate_ms);
+       if (key_matrix_init(&config.matrix, config.key_rows,
+                       config.key_cols, config.ghost_filter)) {
+               debug("%s: cannot init key matrix\n", __func__);
+               return -1;
+       }
+       if (key_matrix_decode_fdt(&config.matrix, gd->fdt_blob, node)) {
+               debug("%s: Could not decode key matrix from fdt\n", __func__);
+               return -1;
+       }
+       config.inited = 1;
+       debug("%s: Matrix keyboard %dx%d ready\n", __func__, config.key_rows,
+             config.key_cols);
+
+       return 0;
+}
+
+int drv_keyboard_init(void)
+{
+       struct stdio_dev dev;
+
+       if (input_init(&config.input, 0)) {
+               debug("%s: Cannot set up input\n", __func__);
+               return -1;
+       }
+       config.input.read_keys = cros_ec_kbc_check;
+
+       memset(&dev, '\0', sizeof(dev));
+       strcpy(dev.name, "cros-ec-keyb");
+       dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+       dev.getc = kbd_getc;
+       dev.tstc = kbd_tstc;
+       dev.start = cros_ec_init_keyboard;
+
+       /* Register the device. cros_ec_init_keyboard() will be called soon */
+       return input_stdio_register(&dev);
+}
index 5d869b47ad4d4b54c5594c3b8c24ceaf793732e7..5fbff8ab6b2bb7354ec17768321577dde51ae0df 100644 (file)
@@ -28,6 +28,10 @@ LIB  := $(obj)libmisc.o
 COBJS-$(CONFIG_ALI152X) += ali512x.o
 COBJS-$(CONFIG_DS4510)  += ds4510.o
 COBJS-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
+COBJS-$(CONFIG_CROS_EC) += cros_ec.o
+COBJS-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
+COBJS-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
+COBJS-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
 COBJS-$(CONFIG_FSL_IIM) += fsl_iim.o
 COBJS-$(CONFIG_GPIO_LED) += gpio_led.o
 COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
new file mode 100644 (file)
index 0000000..6e774d9
--- /dev/null
@@ -0,0 +1,1304 @@
+/*
+ * Chromium OS cros_ec driver
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <i2c.h>
+#include <cros_ec.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm-generic/gpio.h>
+
+#ifdef DEBUG_TRACE
+#define debug_trace(fmt, b...) debug(fmt, #b)
+#else
+#define debug_trace(fmt, b...)
+#endif
+
+enum {
+       /* Timeout waiting for a flash erase command to complete */
+       CROS_EC_CMD_TIMEOUT_MS  = 5000,
+       /* Timeout waiting for a synchronous hash to be recomputed */
+       CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
+};
+
+static struct cros_ec_dev static_dev, *last_dev;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Note: depends on enum ec_current_image */
+static const char * const ec_current_image_name[] = {"unknown", "RO", "RW"};
+
+void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, int len)
+{
+#ifdef DEBUG
+       int i;
+
+       printf("%s: ", name);
+       if (cmd != -1)
+               printf("cmd=%#x: ", cmd);
+       for (i = 0; i < len; i++)
+               printf("%02x ", data[i]);
+       printf("\n");
+#endif
+}
+
+/*
+ * Calculate a simple 8-bit checksum of a data block
+ *
+ * @param data Data block to checksum
+ * @param size Size of data block in bytes
+ * @return checksum value (0 to 255)
+ */
+int cros_ec_calc_checksum(const uint8_t *data, int size)
+{
+       int csum, i;
+
+       for (i = csum = 0; i < size; i++)
+               csum += data[i];
+       return csum & 0xff;
+}
+
+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)
+{
+       int ret;
+
+       switch (dev->interface) {
+#ifdef CONFIG_CROS_EC_SPI
+       case CROS_EC_IF_SPI:
+               ret = cros_ec_spi_command(dev, cmd, cmd_version,
+                                       (const uint8_t *)dout, dout_len,
+                                       dinp, din_len);
+               break;
+#endif
+#ifdef CONFIG_CROS_EC_I2C
+       case CROS_EC_IF_I2C:
+               ret = cros_ec_i2c_command(dev, cmd, cmd_version,
+                                       (const uint8_t *)dout, dout_len,
+                                       dinp, din_len);
+               break;
+#endif
+#ifdef CONFIG_CROS_EC_LPC
+       case CROS_EC_IF_LPC:
+               ret = cros_ec_lpc_command(dev, cmd, cmd_version,
+                                       (const uint8_t *)dout, dout_len,
+                                       dinp, din_len);
+               break;
+#endif
+       case CROS_EC_IF_NONE:
+       default:
+               ret = -1;
+       }
+
+       return ret;
+}
+
+/**
+ * Send a command to the CROS-EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev          CROS-EC device
+ * @param cmd          Command to send (EC_CMD_...)
+ * @param cmd_version  Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp          Response data (may be NULL If din_len=0).
+ *                     If not NULL, it will be updated to point to the data
+ *                     and will always be double word aligned (64-bits)
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd,
+               int cmd_version, const void *dout, int dout_len, uint8_t **dinp,
+               int din_len)
+{
+       uint8_t *din;
+       int len;
+
+       if (cmd_version != 0 && !dev->cmd_version_is_supported) {
+               debug("%s: Command version >0 unsupported\n", __func__);
+               return -1;
+       }
+       len = send_command(dev, cmd, cmd_version, dout, dout_len,
+                               &din, din_len);
+
+       /* If the command doesn't complete, wait a while */
+       if (len == -EC_RES_IN_PROGRESS) {
+               struct ec_response_get_comms_status *resp;
+               ulong start;
+
+               /* Wait for command to complete */
+               start = get_timer(0);
+               do {
+                       int ret;
+
+                       mdelay(50);     /* Insert some reasonable delay */
+                       ret = send_command(dev, EC_CMD_GET_COMMS_STATUS, 0,
+                                       NULL, 0,
+                                       (uint8_t **)&resp, sizeof(*resp));
+                       if (ret < 0)
+                               return ret;
+
+                       if (get_timer(start) > CROS_EC_CMD_TIMEOUT_MS) {
+                               debug("%s: Command %#02x timeout\n",
+                                     __func__, cmd);
+                               return -EC_RES_TIMEOUT;
+                       }
+               } while (resp->flags & EC_COMMS_STATUS_PROCESSING);
+
+               /* OK it completed, so read the status response */
+               /* not sure why it was 0 for the last argument */
+               len = send_command(dev, EC_CMD_RESEND_RESPONSE, 0,
+                               NULL, 0, &din, din_len);
+       }
+
+       debug("%s: len=%d, dinp=%p, *dinp=%p\n", __func__, len, dinp, *dinp);
+       if (dinp) {
+               /* If we have any data to return, it must be 64bit-aligned */
+               assert(len <= 0 || !((uintptr_t)din & 7));
+               *dinp = din;
+       }
+
+       return len;
+}
+
+/**
+ * Send a command to the CROS-EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev          CROS-EC device
+ * @param cmd          Command to send (EC_CMD_...)
+ * @param cmd_version  Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param din           Response data (may be NULL If din_len=0).
+ *                     It not NULL, it is a place for ec_command() to copy the
+ *      data to.
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+                     const void *dout, int dout_len,
+                     void *din, int din_len)
+{
+       uint8_t *in_buffer;
+       int len;
+
+       assert((din_len == 0) || din);
+       len = ec_command_inptr(dev, cmd, cmd_version, dout, dout_len,
+                       &in_buffer, din_len);
+       if (len > 0) {
+               /*
+                * If we were asked to put it somewhere, do so, otherwise just
+                * disregard the result.
+                */
+               if (din && in_buffer) {
+                       assert(len <= din_len);
+                       memmove(din, in_buffer, len);
+               }
+       }
+       return len;
+}
+
+int cros_ec_scan_keyboard(struct cros_ec_dev *dev, struct mbkp_keyscan *scan)
+{
+       if (ec_command(dev, EC_CMD_CROS_EC_STATE, 0, NULL, 0, scan,
+                      sizeof(scan->data)) < sizeof(scan->data))
+               return -1;
+
+       return 0;
+}
+
+int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen)
+{
+       struct ec_response_get_version *r;
+
+       if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
+                       (uint8_t **)&r, sizeof(*r)) < sizeof(*r))
+               return -1;
+
+       if (maxlen > sizeof(r->version_string_ro))
+               maxlen = sizeof(r->version_string_ro);
+
+       switch (r->current_image) {
+       case EC_IMAGE_RO:
+               memcpy(id, r->version_string_ro, maxlen);
+               break;
+       case EC_IMAGE_RW:
+               memcpy(id, r->version_string_rw, maxlen);
+               break;
+       default:
+               return -1;
+       }
+
+       id[maxlen - 1] = '\0';
+       return 0;
+}
+
+int cros_ec_read_version(struct cros_ec_dev *dev,
+                      struct ec_response_get_version **versionp)
+{
+       if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
+                       (uint8_t **)versionp, sizeof(**versionp))
+                       < sizeof(**versionp))
+               return -1;
+
+       return 0;
+}
+
+int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp)
+{
+       if (ec_command_inptr(dev, EC_CMD_GET_BUILD_INFO, 0, NULL, 0,
+                       (uint8_t **)strp, EC_HOST_PARAM_SIZE) < 0)
+               return -1;
+
+       return 0;
+}
+
+int cros_ec_read_current_image(struct cros_ec_dev *dev,
+               enum ec_current_image *image)
+{
+       struct ec_response_get_version *r;
+
+       if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
+                       (uint8_t **)&r, sizeof(*r)) < sizeof(*r))
+               return -1;
+
+       *image = r->current_image;
+       return 0;
+}
+
+static int cros_ec_wait_on_hash_done(struct cros_ec_dev *dev,
+                                 struct ec_response_vboot_hash *hash)
+{
+       struct ec_params_vboot_hash p;
+       ulong start;
+
+       start = get_timer(0);
+       while (hash->status == EC_VBOOT_HASH_STATUS_BUSY) {
+               mdelay(50);     /* Insert some reasonable delay */
+
+               p.cmd = EC_VBOOT_HASH_GET;
+               if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
+                      hash, sizeof(*hash)) < 0)
+                       return -1;
+
+               if (get_timer(start) > CROS_EC_CMD_HASH_TIMEOUT_MS) {
+                       debug("%s: EC_VBOOT_HASH_GET timeout\n", __func__);
+                       return -EC_RES_TIMEOUT;
+               }
+       }
+       return 0;
+}
+
+
+int cros_ec_read_hash(struct cros_ec_dev *dev,
+               struct ec_response_vboot_hash *hash)
+{
+       struct ec_params_vboot_hash p;
+       int rv;
+
+       p.cmd = EC_VBOOT_HASH_GET;
+       if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
+                      hash, sizeof(*hash)) < 0)
+               return -1;
+
+       /* If the EC is busy calculating the hash, fidget until it's done. */
+       rv = cros_ec_wait_on_hash_done(dev, hash);
+       if (rv)
+               return rv;
+
+       /* If the hash is valid, we're done. Otherwise, we have to kick it off
+        * again and wait for it to complete. Note that we explicitly assume
+        * that hashing zero bytes is always wrong, even though that would
+        * produce a valid hash value. */
+       if (hash->status == EC_VBOOT_HASH_STATUS_DONE && hash->size)
+               return 0;
+
+       debug("%s: No valid hash (status=%d size=%d). Compute one...\n",
+             __func__, hash->status, hash->size);
+
+       p.cmd = EC_VBOOT_HASH_RECALC;
+       p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
+       p.nonce_size = 0;
+       p.offset = EC_VBOOT_HASH_OFFSET_RW;
+
+       if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
+                      hash, sizeof(*hash)) < 0)
+               return -1;
+
+       rv = cros_ec_wait_on_hash_done(dev, hash);
+       if (rv)
+               return rv;
+
+       debug("%s: hash done\n", __func__);
+
+       return 0;
+}
+
+static int cros_ec_invalidate_hash(struct cros_ec_dev *dev)
+{
+       struct ec_params_vboot_hash p;
+       struct ec_response_vboot_hash *hash;
+
+       /* We don't have an explict command for the EC to discard its current
+        * hash value, so we'll just tell it to calculate one that we know is
+        * wrong (we claim that hashing zero bytes is always invalid).
+        */
+       p.cmd = EC_VBOOT_HASH_RECALC;
+       p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
+       p.nonce_size = 0;
+       p.offset = 0;
+       p.size = 0;
+
+       debug("%s:\n", __func__);
+
+       if (ec_command_inptr(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
+                      (uint8_t **)&hash, sizeof(*hash)) < 0)
+               return -1;
+
+       /* No need to wait for it to finish */
+       return 0;
+}
+
+int cros_ec_reboot(struct cros_ec_dev *dev, enum ec_reboot_cmd cmd,
+               uint8_t flags)
+{
+       struct ec_params_reboot_ec p;
+
+       p.cmd = cmd;
+       p.flags = flags;
+
+       if (ec_command_inptr(dev, EC_CMD_REBOOT_EC, 0, &p, sizeof(p), NULL, 0)
+                       < 0)
+               return -1;
+
+       if (!(flags & EC_REBOOT_FLAG_ON_AP_SHUTDOWN)) {
+               /*
+                * EC reboot will take place immediately so delay to allow it
+                * to complete.  Note that some reboot types (EC_REBOOT_COLD)
+                * will reboot the AP as well, in which case we won't actually
+                * get to this point.
+                */
+               /*
+                * TODO(rspangler@chromium.org): Would be nice if we had a
+                * better way to determine when the reboot is complete.  Could
+                * we poll a memory-mapped LPC value?
+                */
+               udelay(50000);
+       }
+
+       return 0;
+}
+
+int cros_ec_interrupt_pending(struct cros_ec_dev *dev)
+{
+       /* no interrupt support : always poll */
+       if (!fdt_gpio_isvalid(&dev->ec_int))
+               return 1;
+
+       return !gpio_get_value(dev->ec_int.gpio);
+}
+
+int cros_ec_info(struct cros_ec_dev *dev, struct ec_response_cros_ec_info *info)
+{
+       if (ec_command(dev, EC_CMD_CROS_EC_INFO, 0, NULL, 0, info,
+                       sizeof(*info)) < sizeof(*info))
+               return -1;
+
+       return 0;
+}
+
+int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr)
+{
+       struct ec_response_host_event_mask *resp;
+
+       /*
+        * Use the B copy of the event flags, because the main copy is already
+        * used by ACPI/SMI.
+        */
+       if (ec_command_inptr(dev, EC_CMD_HOST_EVENT_GET_B, 0, NULL, 0,
+                      (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp))
+               return -1;
+
+       if (resp->mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_INVALID))
+               return -1;
+
+       *events_ptr = resp->mask;
+       return 0;
+}
+
+int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events)
+{
+       struct ec_params_host_event_mask params;
+
+       params.mask = events;
+
+       /*
+        * Use the B copy of the event flags, so it affects the data returned
+        * by cros_ec_get_host_events().
+        */
+       if (ec_command_inptr(dev, EC_CMD_HOST_EVENT_CLEAR_B, 0,
+                      &params, sizeof(params), NULL, 0) < 0)
+               return -1;
+
+       return 0;
+}
+
+int cros_ec_flash_protect(struct cros_ec_dev *dev,
+                      uint32_t set_mask, uint32_t set_flags,
+                      struct ec_response_flash_protect *resp)
+{
+       struct ec_params_flash_protect params;
+
+       params.mask = set_mask;
+       params.flags = set_flags;
+
+       if (ec_command(dev, EC_CMD_FLASH_PROTECT, EC_VER_FLASH_PROTECT,
+                      &params, sizeof(params),
+                      resp, sizeof(*resp)) < sizeof(*resp))
+               return -1;
+
+       return 0;
+}
+
+static int cros_ec_check_version(struct cros_ec_dev *dev)
+{
+       struct ec_params_hello req;
+       struct ec_response_hello *resp;
+
+#ifdef CONFIG_CROS_EC_LPC
+       /* LPC has its own way of doing this */
+       if (dev->interface == CROS_EC_IF_LPC)
+               return cros_ec_lpc_check_version(dev);
+#endif
+
+       /*
+        * TODO(sjg@chromium.org).
+        * There is a strange oddity here with the EC. We could just ignore
+        * the response, i.e. pass the last two parameters as NULL and 0.
+        * In this case we won't read back very many bytes from the EC.
+        * On the I2C bus the EC gets upset about this and will try to send
+        * the bytes anyway. This means that we will have to wait for that
+        * to complete before continuing with a new EC command.
+        *
+        * This problem is probably unique to the I2C bus.
+        *
+        * So for now, just read all the data anyway.
+        */
+       dev->cmd_version_is_supported = 1;
+       if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
+                      (uint8_t **)&resp, sizeof(*resp)) > 0) {
+               /* It appears to understand new version commands */
+               dev->cmd_version_is_supported = 1;
+       } else {
+               dev->cmd_version_is_supported = 0;
+               if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req,
+                             sizeof(req), (uint8_t **)&resp,
+                             sizeof(*resp)) < 0) {
+                       debug("%s: Failed both old and new command style\n",
+                               __func__);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int cros_ec_test(struct cros_ec_dev *dev)
+{
+       struct ec_params_hello req;
+       struct ec_response_hello *resp;
+
+       req.in_data = 0x12345678;
+       if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
+                      (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp)) {
+               printf("ec_command_inptr() returned error\n");
+               return -1;
+       }
+       if (resp->out_data != req.in_data + 0x01020304) {
+               printf("Received invalid handshake %x\n", resp->out_data);
+               return -1;
+       }
+
+       return 0;
+}
+
+int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region,
+                     uint32_t *offset, uint32_t *size)
+{
+       struct ec_params_flash_region_info p;
+       struct ec_response_flash_region_info *r;
+       int ret;
+
+       p.region = region;
+       ret = ec_command_inptr(dev, EC_CMD_FLASH_REGION_INFO,
+                        EC_VER_FLASH_REGION_INFO,
+                        &p, sizeof(p), (uint8_t **)&r, sizeof(*r));
+       if (ret != sizeof(*r))
+               return -1;
+
+       if (offset)
+               *offset = r->offset;
+       if (size)
+               *size = r->size;
+
+       return 0;
+}
+
+int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset, uint32_t size)
+{
+       struct ec_params_flash_erase p;
+
+       p.offset = offset;
+       p.size = size;
+       return ec_command_inptr(dev, EC_CMD_FLASH_ERASE, 0, &p, sizeof(p),
+                       NULL, 0);
+}
+
+/**
+ * Write a single block to the flash
+ *
+ * Write a block of data to the EC flash. The size must not exceed the flash
+ * write block size which you can obtain from cros_ec_flash_write_burst_size().
+ *
+ * The offset starts at 0. You can obtain the region information from
+ * cros_ec_flash_offset() to find out where to write for a particular region.
+ *
+ * Attempting to write to the region where the EC is currently running from
+ * will result in an error.
+ *
+ * @param dev          CROS-EC device
+ * @param data         Pointer to data buffer to write
+ * @param offset       Offset within flash to write to.
+ * @param size         Number of bytes to write
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_flash_write_block(struct cros_ec_dev *dev,
+               const uint8_t *data, uint32_t offset, uint32_t size)
+{
+       struct ec_params_flash_write p;
+
+       p.offset = offset;
+       p.size = size;
+       assert(data && p.size <= sizeof(p.data));
+       memcpy(p.data, data, p.size);
+
+       return ec_command_inptr(dev, EC_CMD_FLASH_WRITE, 0,
+                         &p, sizeof(p), NULL, 0) >= 0 ? 0 : -1;
+}
+
+/**
+ * Return optimal flash write burst size
+ */
+static int cros_ec_flash_write_burst_size(struct cros_ec_dev *dev)
+{
+       struct ec_params_flash_write p;
+       return sizeof(p.data);
+}
+
+/**
+ * Check if a block of data is erased (all 0xff)
+ *
+ * This function is useful when dealing with flash, for checking whether a
+ * data block is erased and thus does not need to be programmed.
+ *
+ * @param data         Pointer to data to check (must be word-aligned)
+ * @param size         Number of bytes to check (must be word-aligned)
+ * @return 0 if erased, non-zero if any word is not erased
+ */
+static int cros_ec_data_is_erased(const uint32_t *data, int size)
+{
+       assert(!(size & 3));
+       size /= sizeof(uint32_t);
+       for (; size > 0; size -= 4, data++)
+               if (*data != -1U)
+                       return 0;
+
+       return 1;
+}
+
+int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data,
+                    uint32_t offset, uint32_t size)
+{
+       uint32_t burst = cros_ec_flash_write_burst_size(dev);
+       uint32_t end, off;
+       int ret;
+
+       /*
+        * TODO: round up to the nearest multiple of write size.  Can get away
+        * without that on link right now because its write size is 4 bytes.
+        */
+       end = offset + size;
+       for (off = offset; off < end; off += burst, data += burst) {
+               uint32_t todo;
+
+               /* If the data is empty, there is no point in programming it */
+               todo = min(end - off, burst);
+               if (dev->optimise_flash_write &&
+                               cros_ec_data_is_erased((uint32_t *)data, todo))
+                       continue;
+
+               ret = cros_ec_flash_write_block(dev, data, off, todo);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * Read a single block from the flash
+ *
+ * Read a block of data from the EC flash. The size must not exceed the flash
+ * write block size which you can obtain from cros_ec_flash_write_burst_size().
+ *
+ * The offset starts at 0. You can obtain the region information from
+ * cros_ec_flash_offset() to find out where to read for a particular region.
+ *
+ * @param dev          CROS-EC device
+ * @param data         Pointer to data buffer to read into
+ * @param offset       Offset within flash to read from
+ * @param size         Number of bytes to read
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_flash_read_block(struct cros_ec_dev *dev, uint8_t *data,
+                                uint32_t offset, uint32_t size)
+{
+       struct ec_params_flash_read p;
+
+       p.offset = offset;
+       p.size = size;
+
+       return ec_command(dev, EC_CMD_FLASH_READ, 0,
+                         &p, sizeof(p), data, size) >= 0 ? 0 : -1;
+}
+
+int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset,
+                   uint32_t size)
+{
+       uint32_t burst = cros_ec_flash_write_burst_size(dev);
+       uint32_t end, off;
+       int ret;
+
+       end = offset + size;
+       for (off = offset; off < end; off += burst, data += burst) {
+               ret = cros_ec_flash_read_block(dev, data, off,
+                                           min(end - off, burst));
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
+                        const uint8_t *image, int image_size)
+{
+       uint32_t rw_offset, rw_size;
+       int ret;
+
+       if (cros_ec_flash_offset(dev, EC_FLASH_REGION_RW, &rw_offset, &rw_size))
+               return -1;
+       if (image_size > rw_size)
+               return -1;
+
+       /* Invalidate the existing hash, just in case the AP reboots
+        * unexpectedly during the update. If that happened, the EC RW firmware
+        * would be invalid, but the EC would still have the original hash.
+        */
+       ret = cros_ec_invalidate_hash(dev);
+       if (ret)
+               return ret;
+
+       /*
+        * Erase the entire RW section, so that the EC doesn't see any garbage
+        * past the new image if it's smaller than the current image.
+        *
+        * TODO: could optimize this to erase just the current image, since
+        * presumably everything past that is 0xff's.  But would still need to
+        * round up to the nearest multiple of erase size.
+        */
+       ret = cros_ec_flash_erase(dev, rw_offset, rw_size);
+       if (ret)
+               return ret;
+
+       /* Write the image */
+       ret = cros_ec_flash_write(dev, image, rw_offset, image_size);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int cros_ec_read_vbnvcontext(struct cros_ec_dev *dev, uint8_t *block)
+{
+       struct ec_params_vbnvcontext p;
+       int len;
+
+       p.op = EC_VBNV_CONTEXT_OP_READ;
+
+       len = ec_command(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT,
+                       &p, sizeof(p), block, EC_VBNV_BLOCK_SIZE);
+       if (len < EC_VBNV_BLOCK_SIZE)
+               return -1;
+
+       return 0;
+}
+
+int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block)
+{
+       struct ec_params_vbnvcontext p;
+       int len;
+
+       p.op = EC_VBNV_CONTEXT_OP_WRITE;
+       memcpy(p.block, block, sizeof(p.block));
+
+       len = ec_command_inptr(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT,
+                       &p, sizeof(p), NULL, 0);
+       if (len < 0)
+               return -1;
+
+       return 0;
+}
+
+int cros_ec_set_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t state)
+{
+       struct ec_params_ldo_set params;
+
+       params.index = index;
+       params.state = state;
+
+       if (ec_command_inptr(dev, EC_CMD_LDO_SET, 0,
+                      &params, sizeof(params),
+                      NULL, 0))
+               return -1;
+
+       return 0;
+}
+
+int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state)
+{
+       struct ec_params_ldo_get params;
+       struct ec_response_ldo_get *resp;
+
+       params.index = index;
+
+       if (ec_command_inptr(dev, EC_CMD_LDO_GET, 0,
+                      &params, sizeof(params),
+                      (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp))
+               return -1;
+
+       *state = resp->state;
+
+       return 0;
+}
+
+/**
+ * Decode MBKP details from the device tree and allocate a suitable device.
+ *
+ * @param blob         Device tree blob
+ * @param node         Node to decode from
+ * @param devp         Returns a pointer to the new allocated device
+ * @return 0 if ok, -1 on error
+ */
+static int cros_ec_decode_fdt(const void *blob, int node,
+               struct cros_ec_dev **devp)
+{
+       enum fdt_compat_id compat;
+       struct cros_ec_dev *dev;
+       int parent;
+
+       /* See what type of parent we are inside (this is expensive) */
+       parent = fdt_parent_offset(blob, node);
+       if (parent < 0) {
+               debug("%s: Cannot find node parent\n", __func__);
+               return -1;
+       }
+
+       dev = &static_dev;
+       dev->node = node;
+       dev->parent_node = parent;
+
+       compat = fdtdec_lookup(blob, parent);
+       switch (compat) {
+#ifdef CONFIG_CROS_EC_SPI
+       case COMPAT_SAMSUNG_EXYNOS_SPI:
+               dev->interface = CROS_EC_IF_SPI;
+               if (cros_ec_spi_decode_fdt(dev, blob))
+                       return -1;
+               break;
+#endif
+#ifdef CONFIG_CROS_EC_I2C
+       case COMPAT_SAMSUNG_S3C2440_I2C:
+               dev->interface = CROS_EC_IF_I2C;
+               if (cros_ec_i2c_decode_fdt(dev, blob))
+                       return -1;
+               break;
+#endif
+#ifdef CONFIG_CROS_EC_LPC
+       case COMPAT_INTEL_LPC:
+               dev->interface = CROS_EC_IF_LPC;
+               break;
+#endif
+       default:
+               debug("%s: Unknown compat id %d\n", __func__, compat);
+               return -1;
+       }
+
+       fdtdec_decode_gpio(blob, node, "ec-interrupt", &dev->ec_int);
+       dev->optimise_flash_write = fdtdec_get_bool(blob, node,
+                                                   "optimise-flash-write");
+       *devp = dev;
+
+       return 0;
+}
+
+int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp)
+{
+       char id[MSG_BYTES];
+       struct cros_ec_dev *dev;
+       int node = 0;
+
+       *cros_ecp = NULL;
+       do {
+               node = fdtdec_next_compatible(blob, node,
+                                             COMPAT_GOOGLE_CROS_EC);
+               if (node < 0) {
+                       debug("%s: Node not found\n", __func__);
+                       return 0;
+               }
+       } while (!fdtdec_get_is_enabled(blob, node));
+
+       if (cros_ec_decode_fdt(blob, node, &dev)) {
+               debug("%s: Failed to decode device.\n", __func__);
+               return -CROS_EC_ERR_FDT_DECODE;
+       }
+
+       switch (dev->interface) {
+#ifdef CONFIG_CROS_EC_SPI
+       case CROS_EC_IF_SPI:
+               if (cros_ec_spi_init(dev, blob)) {
+                       debug("%s: Could not setup SPI interface\n", __func__);
+                       return -CROS_EC_ERR_DEV_INIT;
+               }
+               break;
+#endif
+#ifdef CONFIG_CROS_EC_I2C
+       case CROS_EC_IF_I2C:
+               if (cros_ec_i2c_init(dev, blob))
+                       return -CROS_EC_ERR_DEV_INIT;
+               break;
+#endif
+#ifdef CONFIG_CROS_EC_LPC
+       case CROS_EC_IF_LPC:
+               if (cros_ec_lpc_init(dev, blob))
+                       return -CROS_EC_ERR_DEV_INIT;
+               break;
+#endif
+       case CROS_EC_IF_NONE:
+       default:
+               return 0;
+       }
+
+       /* we will poll the EC interrupt line */
+       fdtdec_setup_gpio(&dev->ec_int);
+       if (fdt_gpio_isvalid(&dev->ec_int))
+               gpio_direction_input(dev->ec_int.gpio);
+
+       if (cros_ec_check_version(dev)) {
+               debug("%s: Could not detect CROS-EC version\n", __func__);
+               return -CROS_EC_ERR_CHECK_VERSION;
+       }
+
+       if (cros_ec_read_id(dev, 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 */
+       last_dev = *cros_ecp = dev;
+       debug("Google Chrome EC CROS-EC driver ready, id '%s'\n", id);
+
+       return 0;
+}
+
+#ifdef CONFIG_CMD_CROS_EC
+int cros_ec_decode_region(int argc, char * const argv[])
+{
+       if (argc > 0) {
+               if (0 == strcmp(*argv, "rw"))
+                       return EC_FLASH_REGION_RW;
+               else if (0 == strcmp(*argv, "ro"))
+                       return EC_FLASH_REGION_RO;
+
+               debug("%s: Invalid region '%s'\n", __func__, *argv);
+       } else {
+               debug("%s: Missing region parameter\n", __func__);
+       }
+
+       return -1;
+}
+
+/**
+ * Perform a flash read or write command
+ *
+ * @param dev          CROS-EC device to read/write
+ * @param is_write     1 do to a write, 0 to do a read
+ * @param argc         Number of arguments
+ * @param argv         Arguments (2 is region, 3 is address)
+ * @return 0 for ok, 1 for a usage error or -ve for ec command error
+ *     (negative EC_RES_...)
+ */
+static int do_read_write(struct cros_ec_dev *dev, int is_write, int argc,
+                        char * const argv[])
+{
+       uint32_t offset, size = -1U, region_size;
+       unsigned long addr;
+       char *endp;
+       int region;
+       int ret;
+
+       region = cros_ec_decode_region(argc - 2, argv + 2);
+       if (region == -1)
+               return 1;
+       if (argc < 4)
+               return 1;
+       addr = simple_strtoul(argv[3], &endp, 16);
+       if (*argv[3] == 0 || *endp != 0)
+               return 1;
+       if (argc > 4) {
+               size = simple_strtoul(argv[4], &endp, 16);
+               if (*argv[4] == 0 || *endp != 0)
+                       return 1;
+       }
+
+       ret = cros_ec_flash_offset(dev, region, &offset, &region_size);
+       if (ret) {
+               debug("%s: Could not read region info\n", __func__);
+               return ret;
+       }
+       if (size == -1U)
+               size = region_size;
+
+       ret = is_write ?
+               cros_ec_flash_write(dev, (uint8_t *)addr, offset, size) :
+               cros_ec_flash_read(dev, (uint8_t *)addr, offset, size);
+       if (ret) {
+               debug("%s: Could not %s region\n", __func__,
+                     is_write ? "write" : "read");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       struct cros_ec_dev *dev = last_dev;
+       const char *cmd;
+       int ret = 0;
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       cmd = argv[1];
+       if (0 == strcmp("init", cmd)) {
+               ret = cros_ec_init(gd->fdt_blob, &dev);
+               if (ret) {
+                       printf("Could not init cros_ec device (err %d)\n", ret);
+                       return 1;
+               }
+               return 0;
+       }
+
+       /* Just use the last allocated device; there should be only one */
+       if (!last_dev) {
+               printf("No CROS-EC device available\n");
+               return 1;
+       }
+       if (0 == strcmp("id", cmd)) {
+               char id[MSG_BYTES];
+
+               if (cros_ec_read_id(dev, id, sizeof(id))) {
+                       debug("%s: Could not read KBC ID\n", __func__);
+                       return 1;
+               }
+               printf("%s\n", id);
+       } else if (0 == strcmp("info", cmd)) {
+               struct ec_response_cros_ec_info info;
+
+               if (cros_ec_info(dev, &info)) {
+                       debug("%s: Could not read KBC info\n", __func__);
+                       return 1;
+               }
+               printf("rows     = %u\n", info.rows);
+               printf("cols     = %u\n", info.cols);
+               printf("switches = %#x\n", info.switches);
+       } else if (0 == strcmp("curimage", cmd)) {
+               enum ec_current_image image;
+
+               if (cros_ec_read_current_image(dev, &image)) {
+                       debug("%s: Could not read KBC image\n", __func__);
+                       return 1;
+               }
+               printf("%d\n", image);
+       } else if (0 == strcmp("hash", cmd)) {
+               struct ec_response_vboot_hash hash;
+               int i;
+
+               if (cros_ec_read_hash(dev, &hash)) {
+                       debug("%s: Could not read KBC hash\n", __func__);
+                       return 1;
+               }
+
+               if (hash.hash_type == EC_VBOOT_HASH_TYPE_SHA256)
+                       printf("type:    SHA-256\n");
+               else
+                       printf("type:    %d\n", hash.hash_type);
+
+               printf("offset:  0x%08x\n", hash.offset);
+               printf("size:    0x%08x\n", hash.size);
+
+               printf("digest:  ");
+               for (i = 0; i < hash.digest_size; i++)
+                       printf("%02x", hash.hash_digest[i]);
+               printf("\n");
+       } else if (0 == strcmp("reboot", cmd)) {
+               int region;
+               enum ec_reboot_cmd cmd;
+
+               if (argc >= 3 && !strcmp(argv[2], "cold"))
+                       cmd = EC_REBOOT_COLD;
+               else {
+                       region = cros_ec_decode_region(argc - 2, argv + 2);
+                       if (region == EC_FLASH_REGION_RO)
+                               cmd = EC_REBOOT_JUMP_RO;
+                       else if (region == EC_FLASH_REGION_RW)
+                               cmd = EC_REBOOT_JUMP_RW;
+                       else
+                               return CMD_RET_USAGE;
+               }
+
+               if (cros_ec_reboot(dev, cmd, 0)) {
+                       debug("%s: Could not reboot KBC\n", __func__);
+                       return 1;
+               }
+       } else if (0 == strcmp("events", cmd)) {
+               uint32_t events;
+
+               if (cros_ec_get_host_events(dev, &events)) {
+                       debug("%s: Could not read host events\n", __func__);
+                       return 1;
+               }
+               printf("0x%08x\n", events);
+       } else if (0 == strcmp("clrevents", cmd)) {
+               uint32_t events = 0x7fffffff;
+
+               if (argc >= 3)
+                       events = simple_strtol(argv[2], NULL, 0);
+
+               if (cros_ec_clear_host_events(dev, events)) {
+                       debug("%s: Could not clear host events\n", __func__);
+                       return 1;
+               }
+       } else if (0 == strcmp("read", cmd)) {
+               ret = do_read_write(dev, 0, argc, argv);
+               if (ret > 0)
+                       return CMD_RET_USAGE;
+       } else if (0 == strcmp("write", cmd)) {
+               ret = do_read_write(dev, 1, argc, argv);
+               if (ret > 0)
+                       return CMD_RET_USAGE;
+       } else if (0 == strcmp("erase", cmd)) {
+               int region = cros_ec_decode_region(argc - 2, argv + 2);
+               uint32_t offset, size;
+
+               if (region == -1)
+                       return CMD_RET_USAGE;
+               if (cros_ec_flash_offset(dev, region, &offset, &size)) {
+                       debug("%s: Could not read region info\n", __func__);
+                       ret = -1;
+               } else {
+                       ret = cros_ec_flash_erase(dev, offset, size);
+                       if (ret) {
+                               debug("%s: Could not erase region\n",
+                                     __func__);
+                       }
+               }
+       } else if (0 == strcmp("regioninfo", cmd)) {
+               int region = cros_ec_decode_region(argc - 2, argv + 2);
+               uint32_t offset, size;
+
+               if (region == -1)
+                       return CMD_RET_USAGE;
+               ret = cros_ec_flash_offset(dev, region, &offset, &size);
+               if (ret) {
+                       debug("%s: Could not read region info\n", __func__);
+               } else {
+                       printf("Region: %s\n", region == EC_FLASH_REGION_RO ?
+                                       "RO" : "RW");
+                       printf("Offset: %x\n", offset);
+                       printf("Size:   %x\n", size);
+               }
+       } else if (0 == strcmp("vbnvcontext", cmd)) {
+               uint8_t block[EC_VBNV_BLOCK_SIZE];
+               char buf[3];
+               int i, len;
+               unsigned long result;
+
+               if (argc <= 2) {
+                       ret = cros_ec_read_vbnvcontext(dev, block);
+                       if (!ret) {
+                               printf("vbnv_block: ");
+                               for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++)
+                                       printf("%02x", block[i]);
+                               putc('\n');
+                       }
+               } else {
+                       /*
+                        * TODO(clchiou): Move this to a utility function as
+                        * cmd_spi might want to call it.
+                        */
+                       memset(block, 0, EC_VBNV_BLOCK_SIZE);
+                       len = strlen(argv[2]);
+                       buf[2] = '\0';
+                       for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++) {
+                               if (i * 2 >= len)
+                                       break;
+                               buf[0] = argv[2][i * 2];
+                               if (i * 2 + 1 >= len)
+                                       buf[1] = '0';
+                               else
+                                       buf[1] = argv[2][i * 2 + 1];
+                               strict_strtoul(buf, 16, &result);
+                               block[i] = result;
+                       }
+                       ret = cros_ec_write_vbnvcontext(dev, block);
+               }
+               if (ret) {
+                       debug("%s: Could not %s VbNvContext\n", __func__,
+                                       argc <= 2 ?  "read" : "write");
+               }
+       } else if (0 == strcmp("test", cmd)) {
+               int result = cros_ec_test(dev);
+
+               if (result)
+                       printf("Test failed with error %d\n", result);
+               else
+                       puts("Test passed\n");
+       } else if (0 == strcmp("version", cmd)) {
+               struct ec_response_get_version *p;
+               char *build_string;
+
+               ret = cros_ec_read_version(dev, &p);
+               if (!ret) {
+                       /* Print versions */
+                       printf("RO version:    %1.*s\n",
+                              sizeof(p->version_string_ro),
+                              p->version_string_ro);
+                       printf("RW version:    %1.*s\n",
+                              sizeof(p->version_string_rw),
+                              p->version_string_rw);
+                       printf("Firmware copy: %s\n",
+                               (p->current_image <
+                                       ARRAY_SIZE(ec_current_image_name) ?
+                               ec_current_image_name[p->current_image] :
+                               "?"));
+                       ret = cros_ec_read_build_info(dev, &build_string);
+                       if (!ret)
+                               printf("Build info:    %s\n", build_string);
+               }
+       } else if (0 == strcmp("ldo", cmd)) {
+               uint8_t index, state;
+               char *endp;
+
+               if (argc < 3)
+                       return CMD_RET_USAGE;
+               index = simple_strtoul(argv[2], &endp, 10);
+               if (*argv[2] == 0 || *endp != 0)
+                       return CMD_RET_USAGE;
+               if (argc > 3) {
+                       state = simple_strtoul(argv[3], &endp, 10);
+                       if (*argv[3] == 0 || *endp != 0)
+                               return CMD_RET_USAGE;
+                       ret = cros_ec_set_ldo(dev, index, state);
+               } else {
+                       ret = cros_ec_get_ldo(dev, index, &state);
+                       if (!ret) {
+                               printf("LDO%d: %s\n", index,
+                                       state == EC_LDO_STATE_ON ?
+                                       "on" : "off");
+                       }
+               }
+
+               if (ret) {
+                       debug("%s: Could not access LDO%d\n", __func__, index);
+                       return ret;
+               }
+       } else {
+               return CMD_RET_USAGE;
+       }
+
+       if (ret < 0) {
+               printf("Error: CROS-EC command failed (error %d)\n", ret);
+               ret = 1;
+       }
+
+       return ret;
+}
+
+U_BOOT_CMD(
+       crosec, 5,      1,      do_cros_ec,
+       "CROS-EC utility command",
+       "init                Re-init CROS-EC (done on startup automatically)\n"
+       "crosec id                  Read CROS-EC ID\n"
+       "crosec info                Read CROS-EC info\n"
+       "crosec curimage            Read CROS-EC current image\n"
+       "crosec hash                Read CROS-EC hash\n"
+       "crosec reboot [rw | ro | cold]  Reboot CROS-EC\n"
+       "crosec events              Read CROS-EC host events\n"
+       "crosec clrevents [mask]    Clear CROS-EC host events\n"
+       "crosec regioninfo <ro|rw>  Read image info\n"
+       "crosec erase <ro|rw>       Erase EC image\n"
+       "crosec read <ro|rw> <addr> [<size>]   Read EC image\n"
+       "crosec write <ro|rw> <addr> [<size>]  Write EC image\n"
+       "crosec vbnvcontext [hexstring]        Read [write] VbNvContext from EC\n"
+       "crosec ldo <idx> [<state>] Switch/Read LDO state\n"
+       "crosec test                run tests on cros_ec\n"
+       "crosec version             Read CROS-EC version"
+);
+#endif
diff --git a/drivers/misc/cros_ec_i2c.c b/drivers/misc/cros_ec_i2c.c
new file mode 100644 (file)
index 0000000..b0060ac
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Chromium OS cros_ec driver - I2C interface
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <cros_ec.h>
+
+#ifdef DEBUG_TRACE
+#define debug_trace(fmt, b...) debug(fmt, #b)
+#else
+#define debug_trace(fmt, b...)
+#endif
+
+int cros_ec_i2c_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)
+{
+       int old_bus = 0;
+       /* version8, cmd8, arglen8, out8[dout_len], csum8 */
+       int out_bytes = dout_len + 4;
+       /* response8, arglen8, in8[din_len], checksum8 */
+       int in_bytes = din_len + 3;
+       uint8_t *ptr;
+       /* Receive input data, so that args will be dword aligned */
+       uint8_t *in_ptr;
+       int ret;
+
+       old_bus = i2c_get_bus_num();
+
+       /*
+        * Sanity-check I/O sizes given transaction overhead in internal
+        * buffers.
+        */
+       if (out_bytes > sizeof(dev->dout)) {
+               debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+               return -1;
+       }
+       if (in_bytes > sizeof(dev->din)) {
+               debug("%s: Cannot receive %d bytes\n", __func__, din_len);
+               return -1;
+       }
+       assert(dout_len >= 0);
+       assert(dinp);
+
+       /*
+        * Copy command and data into output buffer so we can do a single I2C
+        * burst transaction.
+        */
+       ptr = dev->dout;
+
+       /*
+        * in_ptr starts of pointing to a dword-aligned input data buffer.
+        * We decrement it back by the number of header bytes we expect to
+        * receive, so that the first parameter of the resulting input data
+        * will be dword aligned.
+        */
+       in_ptr = dev->din + sizeof(int64_t);
+       if (!dev->cmd_version_is_supported) {
+               /* Send an old-style command */
+               *ptr++ = cmd;
+               out_bytes = dout_len + 1;
+               in_bytes = din_len + 2;
+               in_ptr--;       /* Expect just a status byte */
+       } else {
+               *ptr++ = EC_CMD_VERSION0 + cmd_version;
+               *ptr++ = cmd;
+               *ptr++ = dout_len;
+               in_ptr -= 2;    /* Expect status, length bytes */
+       }
+       memcpy(ptr, dout, dout_len);
+       ptr += dout_len;
+
+       if (dev->cmd_version_is_supported)
+               *ptr++ = (uint8_t)
+                        cros_ec_calc_checksum(dev->dout, dout_len + 3);
+
+       /* Set to the proper i2c bus */
+       if (i2c_set_bus_num(dev->bus_num)) {
+               debug("%s: Cannot change to I2C bus %d\n", __func__,
+                       dev->bus_num);
+               return -1;
+       }
+
+       /* Send output data */
+       cros_ec_dump_data("out", -1, dev->dout, out_bytes);
+       ret = i2c_write(dev->addr, 0, 0, dev->dout, out_bytes);
+       if (ret) {
+               debug("%s: Cannot complete I2C write to 0x%x\n",
+                       __func__, dev->addr);
+               ret = -1;
+       }
+
+       if (!ret) {
+               ret = i2c_read(dev->addr, 0, 0, in_ptr, in_bytes);
+               if (ret) {
+                       debug("%s: Cannot complete I2C read from 0x%x\n",
+                               __func__, dev->addr);
+                       ret = -1;
+               }
+       }
+
+       /* Return to original bus number */
+       i2c_set_bus_num(old_bus);
+       if (ret)
+               return ret;
+
+       if (*in_ptr != EC_RES_SUCCESS) {
+               debug("%s: Received bad result code %d\n", __func__, *in_ptr);
+               return -(int)*in_ptr;
+       }
+
+       if (dev->cmd_version_is_supported) {
+               int len, csum;
+
+               len = in_ptr[1];
+               if (len + 3 > sizeof(dev->din)) {
+                       debug("%s: Received length %#02x too large\n",
+                             __func__, len);
+                       return -1;
+               }
+               csum = cros_ec_calc_checksum(in_ptr, 2 + len);
+               if (csum != in_ptr[2 + len]) {
+                       debug("%s: Invalid checksum rx %#02x, calced %#02x\n",
+                             __func__, in_ptr[2 + din_len], csum);
+                       return -1;
+               }
+               din_len = min(din_len, len);
+               cros_ec_dump_data("in", -1, in_ptr, din_len + 3);
+       } else {
+               cros_ec_dump_data("in (old)", -1, in_ptr, in_bytes);
+       }
+
+       /* Return pointer to dword-aligned input data, if any */
+       *dinp = dev->din + sizeof(int64_t);
+
+       return din_len;
+}
+
+int cros_ec_i2c_decode_fdt(struct cros_ec_dev *dev, const void *blob)
+{
+       /* Decode interface-specific FDT params */
+       dev->max_frequency = fdtdec_get_int(blob, dev->node,
+                                           "i2c-max-frequency", 100000);
+       dev->bus_num = i2c_get_bus_num_fdt(dev->parent_node);
+       if (dev->bus_num == -1) {
+               debug("%s: Failed to read bus number\n", __func__);
+               return -1;
+       }
+       dev->addr = fdtdec_get_int(blob, dev->node, "reg", -1);
+       if (dev->addr == -1) {
+               debug("%s: Failed to read device address\n", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Initialize I2C protocol.
+ *
+ * @param dev          CROS_EC device
+ * @param blob         Device tree blob
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob)
+{
+       i2c_init(dev->max_frequency, dev->addr);
+
+       dev->cmd_version_is_supported = 0;
+
+       return 0;
+}
diff --git a/drivers/misc/cros_ec_lpc.c b/drivers/misc/cros_ec_lpc.c
new file mode 100644 (file)
index 0000000..cf0435b
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Chromium OS cros_ec driver - LPC interface
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cros_ec.h>
+#include <asm/io.h>
+
+#ifdef DEBUG_TRACE
+#define debug_trace(fmt, b...) debug(fmt, ##b)
+#else
+#define debug_trace(fmt, b...)
+#endif
+
+static int wait_for_sync(struct cros_ec_dev *dev)
+{
+       unsigned long start;
+
+       start = get_timer(0);
+       while (inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK) {
+               if (get_timer(start) > 1000) {
+                       debug("%s: Timeout waiting for CROS_EC sync\n",
+                             __func__);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * Send a command to a LPC CROS_EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev          CROS_EC device
+ * @param cmd          Command to send (EC_CMD_...)
+ * @param cmd_version  Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp          Place to put pointer to response data
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+static int old_lpc_command(struct cros_ec_dev *dev, uint8_t cmd,
+                    const uint8_t *dout, int dout_len,
+                    uint8_t **dinp, int din_len)
+{
+       int ret, i;
+
+       if (dout_len > EC_OLD_PARAM_SIZE) {
+               debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+               return -1;
+       }
+
+       if (din_len > EC_OLD_PARAM_SIZE) {
+               debug("%s: Cannot receive %d bytes\n", __func__, din_len);
+               return -1;
+       }
+
+       if (wait_for_sync(dev)) {
+               debug("%s: Timeout waiting ready\n", __func__);
+               return -1;
+       }
+
+       debug_trace("cmd: %02x, ", cmd);
+       for (i = 0; i < dout_len; i++) {
+               debug_trace("%02x ", dout[i]);
+               outb(dout[i], EC_LPC_ADDR_OLD_PARAM + i);
+       }
+       outb(cmd, EC_LPC_ADDR_HOST_CMD);
+       debug_trace("\n");
+
+       if (wait_for_sync(dev)) {
+               debug("%s: Timeout waiting ready\n", __func__);
+               return -1;
+       }
+
+       ret = inb(EC_LPC_ADDR_HOST_DATA);
+       if (ret) {
+               debug("%s: CROS_EC result code %d\n", __func__, ret);
+               return -ret;
+       }
+
+       debug_trace("resp: %02x, ", ret);
+       for (i = 0; i < din_len; i++) {
+               dev->din[i] = inb(EC_LPC_ADDR_OLD_PARAM + i);
+               debug_trace("%02x ", dev->din[i]);
+       }
+       debug_trace("\n");
+       *dinp = dev->din;
+
+       return din_len;
+}
+
+int cros_ec_lpc_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)
+{
+       const int cmd_addr = EC_LPC_ADDR_HOST_CMD;
+       const int data_addr = EC_LPC_ADDR_HOST_DATA;
+       const int args_addr = EC_LPC_ADDR_HOST_ARGS;
+       const int param_addr = EC_LPC_ADDR_HOST_PARAM;
+
+       struct ec_lpc_host_args args;
+       uint8_t *d;
+       int csum;
+       int i;
+
+       /* Fall back to old-style command interface if args aren't supported */
+       if (!dev->cmd_version_is_supported)
+               return old_lpc_command(dev, cmd, dout, dout_len, dinp,
+                                      din_len);
+
+       if (dout_len > EC_HOST_PARAM_SIZE) {
+               debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+               return -1;
+       }
+
+       /* Fill in args */
+       args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
+       args.command_version = cmd_version;
+       args.data_size = dout_len;
+
+       /* Calculate checksum */
+       csum = cmd + args.flags + args.command_version + args.data_size;
+       for (i = 0, d = (uint8_t *)dout; i < dout_len; i++, d++)
+               csum += *d;
+
+       args.checksum = (uint8_t)csum;
+
+       if (wait_for_sync(dev)) {
+               debug("%s: Timeout waiting ready\n", __func__);
+               return -1;
+       }
+
+       /* Write args */
+       for (i = 0, d = (uint8_t *)&args; i < sizeof(args); i++, d++)
+               outb(*d, args_addr + i);
+
+       /* Write data, if any */
+       debug_trace("cmd: %02x, ver: %02x", cmd, cmd_version);
+       for (i = 0, d = (uint8_t *)dout; i < dout_len; i++, d++) {
+               outb(*d, param_addr + i);
+               debug_trace("%02x ", *d);
+       }
+
+       outb(cmd, cmd_addr);
+       debug_trace("\n");
+
+       if (wait_for_sync(dev)) {
+               debug("%s: Timeout waiting for response\n", __func__);
+               return -1;
+       }
+
+       /* Check result */
+       i = inb(data_addr);
+       if (i) {
+               debug("%s: CROS_EC result code %d\n", __func__, i);
+               return -i;
+       }
+
+       /* Read back args */
+       for (i = 0, d = (uint8_t *)&args; i < sizeof(args); i++, d++)
+               *d = inb(args_addr + i);
+
+       /*
+        * If EC didn't modify args flags, then somehow we sent a new-style
+        * command to an old EC, which means it would have read its params
+        * from the wrong place.
+        */
+       if (!(args.flags & EC_HOST_ARGS_FLAG_TO_HOST)) {
+               debug("%s: CROS_EC protocol mismatch\n", __func__);
+               return -EC_RES_INVALID_RESPONSE;
+       }
+
+       if (args.data_size > din_len) {
+               debug("%s: CROS_EC returned too much data %d > %d\n",
+                     __func__, args.data_size, din_len);
+               return -EC_RES_INVALID_RESPONSE;
+       }
+
+       /* Read data, if any */
+       for (i = 0, d = (uint8_t *)dev->din; i < args.data_size; i++, d++) {
+               *d = inb(param_addr + i);
+               debug_trace("%02x ", *d);
+       }
+       debug_trace("\n");
+
+       /* Verify checksum */
+       csum = cmd + args.flags + args.command_version + args.data_size;
+       for (i = 0, d = (uint8_t *)dev->din; i < args.data_size; i++, d++)
+               csum += *d;
+
+       if (args.checksum != (uint8_t)csum) {
+               debug("%s: CROS_EC response has invalid checksum\n", __func__);
+               return -EC_RES_INVALID_CHECKSUM;
+       }
+       *dinp = dev->din;
+
+       /* Return actual amount of data received */
+       return args.data_size;
+}
+
+/**
+ * Initialize LPC protocol.
+ *
+ * @param dev          CROS_EC device
+ * @param blob         Device tree blob
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_lpc_init(struct cros_ec_dev *dev, const void *blob)
+{
+       int byte, i;
+
+       /* See if we can find an EC at the other end */
+       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++)
+               byte &= inb(EC_LPC_ADDR_HOST_PARAM + i);
+       if (byte == 0xff) {
+               debug("%s: CROS_EC device not found on LPC bus\n",
+                       __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Test if LPC command args are supported.
+ *
+ * The cheapest way to do this is by looking for the memory-mapped
+ * flag.  This is faster than sending a new-style 'hello' command and
+ * seeing whether the EC sets the EC_HOST_ARGS_FLAG_FROM_HOST flag
+ * in args when it responds.
+ */
+int cros_ec_lpc_check_version(struct cros_ec_dev *dev)
+{
+       if (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) == 'E' &&
+                       inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1)
+                               == 'C' &&
+                       (inb(EC_LPC_ADDR_MEMMAP +
+                               EC_MEMMAP_HOST_CMD_FLAGS) &
+                               EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED)) {
+               dev->cmd_version_is_supported = 1;
+       } else {
+               /* We are going to use the old IO ports */
+               dev->cmd_version_is_supported = 0;
+       }
+       debug("lpc: version %s\n", dev->cmd_version_is_supported ?
+                       "new" : "old");
+
+       return 0;
+}
diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
new file mode 100644 (file)
index 0000000..e15c833
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Chromium OS cros_ec driver - SPI interface
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * The Matrix Keyboard Protocol driver handles talking to the keyboard
+ * controller chip. Mostly this is for keyboard functions, but some other
+ * things have slipped in, so we provide generic services to talk to the
+ * KBC.
+ */
+
+#include <common.h>
+#include <cros_ec.h>
+#include <spi.h>
+
+/**
+ * Send a command to a LPC CROS_EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev          CROS_EC device
+ * @param cmd          Command to send (EC_CMD_...)
+ * @param cmd_version  Version of command to send (EC_VER_...)
+ * @param dout         Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp         Returns pointer to response data. This will be
+ *                     untouched unless we return a value > 0.
+ * @param din_len      Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+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)
+{
+       int in_bytes = din_len + 4;     /* status, length, checksum, trailer */
+       uint8_t *out;
+       uint8_t *p;
+       int csum, len;
+       int rv;
+
+       /*
+        * Sanity-check input size to make sure it plus transaction overhead
+        * fits in the internal device buffer.
+        */
+       if (in_bytes > sizeof(dev->din)) {
+               debug("%s: Cannot receive %d bytes\n", __func__, din_len);
+               return -1;
+       }
+
+       /* We represent message length as a byte */
+       if (dout_len > 0xff) {
+               debug("%s: Cannot send %d bytes\n", __func__, dout_len);
+               return -1;
+       }
+
+       /*
+        * Clear input buffer so we don't get false hits for MSG_HEADER
+        */
+       memset(dev->din, '\0', in_bytes);
+
+       if (spi_claim_bus(dev->spi)) {
+               debug("%s: Cannot claim SPI bus\n", __func__);
+               return -1;
+       }
+
+       out = dev->dout;
+       out[0] = cmd_version;
+       out[1] = cmd;
+       out[2] = (uint8_t)dout_len;
+       memcpy(out + 3, dout, dout_len);
+       csum = cros_ec_calc_checksum(out, 3)
+              + cros_ec_calc_checksum(dout, dout_len);
+       out[3 + dout_len] = (uint8_t)csum;
+
+       /*
+        * Send output data and receive input data starting such that the
+        * message body will be dword aligned.
+        */
+       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,
+                     SPI_XFER_BEGIN | SPI_XFER_END);
+
+       spi_release_bus(dev->spi);
+
+       if (rv) {
+               debug("%s: Cannot complete SPI transfer\n", __func__);
+               return -1;
+       }
+
+       len = min(p[1], din_len);
+       cros_ec_dump_data("in", -1, p, len + 3);
+
+       /* Response code is first byte of message */
+       if (p[0] != EC_RES_SUCCESS) {
+               printf("%s: Returned status %d\n", __func__, p[0]);
+               return -(int)(p[0]);
+       }
+
+       /* Check checksum */
+       csum = cros_ec_calc_checksum(p, len + 2);
+       if (csum != p[len + 2]) {
+               debug("%s: Invalid checksum rx %#02x, calced %#02x\n", __func__,
+                     p[2 + len], csum);
+               return -1;
+       }
+
+       /* Anything else is the response data */
+       *dinp = p + 2;
+
+       return len;
+}
+
+int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
+{
+       /* Decode interface-specific FDT params */
+       dev->max_frequency = fdtdec_get_int(blob, dev->node,
+                                           "spi-max-frequency", 500000);
+       dev->cs = fdtdec_get_int(blob, dev->node, "reg", 0);
+
+       return 0;
+}
+
+/**
+ * Initialize SPI protocol.
+ *
+ * @param dev          CROS_EC device
+ * @param blob         Device tree blob
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
+{
+       dev->spi = spi_setup_slave_fdt(blob, dev->parent_node,
+                                      dev->cs, dev->max_frequency, 0);
+       if (!dev->spi) {
+               debug("%s: Could not setup SPI slave\n", __func__);
+               return -1;
+       }
+
+       return 0;
+}
index 4070d4ea5312b6eb43cd347f951f47ca4d400ac7..5da20eda5586c82dd1f1698d26e8c7042e33eed5 100644 (file)
@@ -129,13 +129,13 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        unsigned int timeout = 100000;
        u32 retry = 10000;
        u32 mask, ctrl;
+       ulong start = get_timer(0);
 
        while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
-               if (timeout == 0) {
+               if (get_timer(start) > timeout) {
                        printf("Timeout on data busy\n");
                        return TIMEOUT;
                }
-               timeout--;
        }
 
        dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
@@ -143,7 +143,6 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        if (data)
                dwmci_prepare_data(host, data);
 
-
        dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
        if (data)
@@ -231,9 +230,8 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
        int timeout = 10000;
        unsigned long sclk;
 
-       if (freq == host->clock)
+       if ((freq == host->clock) || (freq == 0))
                return 0;
-
        /*
         * If host->mmc_clk didn't define,
         * then assume that host->bus_hz is source clock value.
@@ -314,7 +312,7 @@ static void dwmci_set_ios(struct mmc *mmc)
 static int dwmci_init(struct mmc *mmc)
 {
        struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
-       u32 fifo_size, fifoth_val;
+       u32 fifo_size;
 
        dwmci_writel(host, DWMCI_PWREN, 1);
 
@@ -323,6 +321,9 @@ static int dwmci_init(struct mmc *mmc)
                return -1;
        }
 
+       /* Enumerate at 400KHz */
+       dwmci_setup_bus(host, mmc->f_min);
+
        dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
        dwmci_writel(host, DWMCI_INTMASK, 0);
 
@@ -331,13 +332,13 @@ static int dwmci_init(struct mmc *mmc)
        dwmci_writel(host, DWMCI_IDINTEN, 0);
        dwmci_writel(host, DWMCI_BMOD, 1);
 
-       fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
-       if (host->fifoth_val)
-               fifoth_val = host->fifoth_val;
-       else
-               fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
-                       TX_WMARK(fifo_size/2);
-       dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
+       if (!host->fifoth_val) {
+               fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+               fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
+               host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+                       TX_WMARK(fifo_size / 2);
+       }
+       dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
 
        dwmci_writel(host, DWMCI_CLKENA, 0);
        dwmci_writel(host, DWMCI_CLKSRC, 0);
index 72a31b73fd595267fcf91a418b0364dcfc1eeffb..4238dd933b016421e9b9afce8fa18e54f2b8871a 100644 (file)
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-static char *EXYNOS_NAME = "EXYNOS DWMMC";
+#define        DWMMC_MAX_CH_NUM                4
+#define        DWMMC_MAX_FREQ                  52000000
+#define        DWMMC_MIN_FREQ                  400000
+#define        DWMMC_MMC0_CLKSEL_VAL           0x03030001
+#define        DWMMC_MMC2_CLKSEL_VAL           0x03020001
 
+/*
+ * Function used as callback function to initialise the
+ * CLKSEL register for every mmc channel.
+ */
 static void exynos_dwmci_clksel(struct dwmci_host *host)
 {
-       u32 val;
-       val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
-               DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(0);
+       dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val);
+}
 
-       dwmci_writel(host, DWMCI_CLKSEL, val);
+unsigned int exynos_dwmci_get_clk(int dev_index)
+{
+       return get_mmc_clk(dev_index);
 }
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index)
+/*
+ * This function adds the mmc channel to be registered with mmc core.
+ * index -     mmc channel number.
+ * regbase -   register base address of mmc channel specified in 'index'.
+ * bus_width - operating bus width of mmc channel specified in 'index'.
+ * clksel -    value to be written into CLKSEL register in case of FDT.
+ *             NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
 {
        struct dwmci_host *host = NULL;
+       unsigned int div;
+       unsigned long freq, sclk;
        host = malloc(sizeof(struct dwmci_host));
        if (!host) {
                printf("dwmci_host malloc fail!\n");
                return 1;
        }
+       /* request mmc clock vlaue of 52MHz.  */
+       freq = 52000000;
+       sclk = get_mmc_clk(index);
+       div = DIV_ROUND_UP(sclk, freq);
+       /* set the clock divisor for mmc */
+       set_mmc_clk(index, div);
 
-       host->name = EXYNOS_NAME;
+       host->name = "EXYNOS DWMMC";
        host->ioaddr = (void *)regbase;
        host->buswidth = bus_width;
+
+       if (clksel) {
+               host->clksel_val = clksel;
+       } else {
+               if (0 == index)
+                       host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+               if (2 == index)
+                       host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+       }
+
        host->clksel = exynos_dwmci_clksel;
        host->dev_index = index;
+       host->mmc_clk = exynos_dwmci_get_clk;
+       /* Add the mmc channel to be registered with mmc core */
+       if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
+               debug("dwmmc%d registration failed\n", index);
+               return -1;
+       }
+       return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob)
+{
+       int index, bus_width;
+       int node_list[DWMMC_MAX_CH_NUM];
+       int err = 0, dev_id, flag, count, i;
+       u32 clksel_val, base, timing[3];
+
+       count = fdtdec_find_aliases_for_id(blob, "mmc",
+                               COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list,
+                               DWMMC_MAX_CH_NUM);
+
+       for (i = 0; i < count; i++) {
+               int node = node_list[i];
+
+               if (node <= 0)
+                       continue;
 
-       add_dwmci(host, 52000000, 400000);
+               /* Extract device id for each mmc channel */
+               dev_id = pinmux_decode_periph_id(blob, node);
 
+               /* Get the bus width from the device node */
+               bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
+               if (bus_width <= 0) {
+                       debug("DWMMC: Can't get bus-width\n");
+                       return -1;
+               }
+               if (8 == bus_width)
+                       flag = PINMUX_FLAG_8BIT_MODE;
+               else
+                       flag = PINMUX_FLAG_NONE;
+
+               /* config pinmux for each mmc channel */
+               err = exynos_pinmux_config(dev_id, flag);
+               if (err) {
+                       debug("DWMMC not configured\n");
+                       return err;
+               }
+
+               index = dev_id - PERIPH_ID_SDMMC0;
+
+               /* Get the base address from the device node */
+               base = fdtdec_get_addr(blob, node, "reg");
+               if (!base) {
+                       debug("DWMMC: Can't get base address\n");
+                       return -1;
+               }
+               /* Extract the timing info from the node */
+               err = fdtdec_get_int_array(blob, node, "samsung,timing",
+                                       timing, 3);
+               if (err) {
+                       debug("Can't get sdr-timings for divider\n");
+                       return -1;
+               }
+
+               clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+                               DWMCI_SET_DRV_CLK(timing[1]) |
+                               DWMCI_SET_DIV_RATIO(timing[2]));
+               /* Initialise each mmc channel */
+               err = exynos_dwmci_add_port(index, base, bus_width, clksel_val);
+               if (err)
+                       debug("dwmmc Channel-%d init failed\n", index);
+       }
        return 0;
 }
-
+#endif
index e6a296a5762c939736d47aed83529f113c983635..73f71957926b8c73adcd3a37ccd2917ddbbc53e1 100644 (file)
@@ -254,7 +254,7 @@ err_out:
 }
 
 static unsigned long
-mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
+mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
 {
        int err = 0;
        struct mmc *mmc = find_mmc_device(dev_num);
@@ -266,7 +266,8 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
 
        if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
                printf("\n\nCaution! Your devices Erase group is 0x%x\n"
-                       "The erase range would be change to 0x%lx~0x%lx\n\n",
+                      "The erase range would be change to "
+                      "0x" LBAF "~0x" LBAF "\n\n",
                       mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
                       ((start + blkcnt + mmc->erase_grp_size)
                       & ~(mmc->erase_grp_size - 1)) - 1);
@@ -289,14 +290,14 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
 }
 
 static ulong
-mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
+mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
 {
        struct mmc_cmd cmd;
        struct mmc_data data;
        int timeout = 1000;
 
        if ((start + blkcnt) > mmc->block_dev.lba) {
-               printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
                        start + blkcnt, mmc->block_dev.lba);
                return 0;
        }
@@ -346,7 +347,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 }
 
 static ulong
-mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
+mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
 {
        lbaint_t cur, blocks_todo = blkcnt;
 
@@ -369,7 +370,7 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
        return blkcnt;
 }
 
-static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
+static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
                           lbaint_t blkcnt)
 {
        struct mmc_cmd cmd;
@@ -408,7 +409,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
        return blkcnt;
 }
 
-static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
+static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
 {
        lbaint_t cur, blocks_todo = blkcnt;
 
@@ -420,7 +421,7 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
                return 0;
 
        if ((start + blkcnt) > mmc->block_dev.lba) {
-               printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
                        start + blkcnt, mmc->block_dev.lba);
                return 0;
        }
@@ -1503,3 +1504,137 @@ int mmc_initialize(bd_t *bis)
        do_preinit();
        return 0;
 }
+
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+/*
+ * This function changes the size of boot partition and the size of rpmb
+ * partition present on EMMC devices.
+ *
+ * Input Parameters:
+ * struct *mmc: pointer for the mmc device strcuture
+ * bootsize: size of boot partition
+ * rpmbsize: size of rpmb partition
+ *
+ * Returns 0 on success.
+ */
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+                               unsigned long rpmbsize)
+{
+       int err;
+       struct mmc_cmd cmd;
+
+       /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
+       cmd.cmdidx = MMC_CMD_RES_MAN;
+       cmd.resp_type = MMC_RSP_R1b;
+       cmd.cmdarg = MMC_CMD62_ARG1;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err) {
+               debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
+               return err;
+       }
+
+       /* Boot partition changing mode */
+       cmd.cmdidx = MMC_CMD_RES_MAN;
+       cmd.resp_type = MMC_RSP_R1b;
+       cmd.cmdarg = MMC_CMD62_ARG2;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err) {
+               debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
+               return err;
+       }
+       /* boot partition size is multiple of 128KB */
+       bootsize = (bootsize * 1024) / 128;
+
+       /* Arg: boot partition size */
+       cmd.cmdidx = MMC_CMD_RES_MAN;
+       cmd.resp_type = MMC_RSP_R1b;
+       cmd.cmdarg = bootsize;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err) {
+               debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
+               return err;
+       }
+       /* RPMB partition size is multiple of 128KB */
+       rpmbsize = (rpmbsize * 1024) / 128;
+       /* Arg: RPMB partition size */
+       cmd.cmdidx = MMC_CMD_RES_MAN;
+       cmd.resp_type = MMC_RSP_R1b;
+       cmd.cmdarg = rpmbsize;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err) {
+               debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
+               return err;
+       }
+       return 0;
+}
+
+/*
+ * This function shall form and send the commands to open / close the
+ * boot partition specified by user.
+ *
+ * Input Parameters:
+ * ack: 0x0 - No boot acknowledge sent (default)
+ *     0x1 - Boot acknowledge sent during boot operation
+ * part_num: User selects boot data that will be sent to master
+ *     0x0 - Device not boot enabled (default)
+ *     0x1 - Boot partition 1 enabled for boot
+ *     0x2 - Boot partition 2 enabled for boot
+ * access: User selects partitions to access
+ *     0x0 : No access to boot partition (default)
+ *     0x1 : R/W boot partition 1
+ *     0x2 : R/W boot partition 2
+ *     0x3 : R/W Replay Protected Memory Block (RPMB)
+ *
+ * Returns 0 on success.
+ */
+int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+       int err;
+       struct mmc_cmd cmd;
+
+       /* Boot ack enable, boot partition enable , boot partition access */
+       cmd.cmdidx = MMC_CMD_SWITCH;
+       cmd.resp_type = MMC_RSP_R1b;
+
+       cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                       (EXT_CSD_PART_CONF << 16) |
+                       ((EXT_CSD_BOOT_ACK(ack) |
+                       EXT_CSD_BOOT_PART_NUM(part_num) |
+                       EXT_CSD_PARTITION_ACCESS(access)) << 8);
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err) {
+               if (access) {
+                       debug("mmc boot partition#%d open fail:Error1 = %d\n",
+                             part_num, err);
+               } else {
+                       debug("mmc boot partition#%d close fail:Error = %d\n",
+                             part_num, err);
+               }
+               return err;
+       }
+
+       if (access) {
+               /* 4bit transfer mode at booting time. */
+               cmd.cmdidx = MMC_CMD_SWITCH;
+               cmd.resp_type = MMC_RSP_R1b;
+
+               cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                               (EXT_CSD_BOOT_BUS_WIDTH << 16) |
+                               ((1 << 0) << 8);
+
+               err = mmc_send_cmd(mmc, &cmd, NULL);
+               if (err) {
+                       debug("mmc boot partition#%d open fail:Error2 = %d\n",
+                             part_num, err);
+                       return err;
+               }
+       }
+       return 0;
+}
+#endif
index 25f875202c337deafbda8f30b530325f21c5d88c..25a5710758971ea674cf9c63e5728d993d12c94f 100644 (file)
@@ -1797,7 +1797,7 @@ static int flash_detect_legacy(phys_addr_t base, int banknum)
                        };
                        int i;
 
-                       for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
+                       for (i = 0; i < ARRAY_SIZE(modes); i++) {
                                info->vendor = modes[i];
                                info->start[0] =
                                        (ulong)map_physmem(base,
@@ -1883,8 +1883,7 @@ static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
        /* Issue FLASH reset command */
        flash_cmd_reset(info);
 
-       for (cfi_offset=0;
-            cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
+       for (cfi_offset = 0; cfi_offset < ARRAY_SIZE(flash_offset_cfi);
             cfi_offset++) {
                flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset],
                                 FLASH_CMD_CFI);
@@ -2336,7 +2335,7 @@ void flash_protect_default(void)
 #endif
 
 #if defined(CONFIG_SYS_FLASH_AUTOPROTECT_LIST)
-       for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) {
+       for (i = 0; i < ARRAY_SIZE(apl); i++) {
                debug("autoprotecting from %08lx to %08lx\n",
                      apl[i].start, apl[i].start + apl[i].size - 1);
                flash_protect(FLAG_PROTECT_SET,
index 8821704911be69ab24e1e487a1f6c98903062e14..bb81e84113cfd4073525a0af1188c98e3f054cdc 100644 (file)
@@ -83,6 +83,7 @@ COBJS-$(CONFIG_NAND_DOCG4) += docg4.o
 else  # minimal SPL drivers
 
 COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o
+COBJS-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_spl.o
 COBJS-$(CONFIG_NAND_MXC) += mxc_nand_spl.o
 
 endif # drivers
similarity index 88%
rename from nand_spl/nand_boot_fsl_ifc.c
rename to drivers/mtd/nand/fsl_ifc_spl.c
index 44972c5c09a8e678df44eef9a310f85daee33676..8537c4c6f573849631e164bbdcc390b9251ac964 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * NAND boot for FSL Integrated Flash Controller, NAND Flash Control Machine
+ * NAND boot for Freescale Integrated Flash Controller, NAND FCM
  *
  * Copyright 2011 Freescale Semiconductor, Inc.
  * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
@@ -46,9 +46,9 @@ static inline int check_read_ecc(uchar *buf, u32 *eccstat,
                                 unsigned int bufnum, int page_size)
 {
        u32 reg = eccstat[bufnum / 4];
-       int errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
+       int errors = (reg >> ((3 - bufnum % 4) * 8)) & 0xf;
 
-       if (errors == 15) { /* uncorrectable */
+       if (errors == 0xf) { /* uncorrectable */
                /* Blank pages fail hw ECC checks */
                if (is_blank(buf, page_size))
                        return 1;
@@ -123,30 +123,17 @@ static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
        csor = CONFIG_SYS_NAND_CSOR;
        cspr = CONFIG_SYS_NAND_CSPR;
 
-       if (!(csor & CSOR_NAND_ECC_DEC_EN)) {
-               /* soft ECC in SPL is unimplemented */
-               puts("WARNING: soft ECC not checked in SPL\n");
-       } else {
-               u32 hwcsor;
-
-               /* make sure board is configured with ECC on boot */
-               hwcsor = in_be32(&ifc->csor_cs[0].csor);
-               if (!(hwcsor & CSOR_NAND_ECC_DEC_EN))
-                       puts("WARNING: ECC not checked in SPL, "
-                               "check board cfg\n");
-       }
-
        port_size = (cspr & CSPR_PORT_SIZE_16) ? 16 : 8;
 
        if (csor & CSOR_NAND_PGS_4K) {
                page_size = 4096;
-               bufnum_mask = 1;
+               bufnum_mask = 0x1;
        } else if (csor & CSOR_NAND_PGS_2K) {
                page_size = 2048;
-               bufnum_mask = 3;
+               bufnum_mask = 0x3;
        } else {
                page_size = 512;
-               bufnum_mask = 15;
+               bufnum_mask = 0xf;
 
                if (port_size == 8)
                        bad_marker = 5;
@@ -174,8 +161,8 @@ static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
                out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
 
                out_be32(&ifc->ifc_nand.nand_fcr0,
-                       (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
-                       (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
+                        (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
+                        (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
        } else {
                out_be32(&ifc->ifc_nand.nand_fir0,
                         (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
@@ -185,7 +172,7 @@ static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
                out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
 
                out_be32(&ifc->ifc_nand.nand_fcr0,
-                       NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
+                        NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
        }
 
        /* Program FBCR = 0 for full page read */
@@ -206,7 +193,7 @@ static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
                        out_be32(&ifc->ifc_nand.col0, 0);
                        /* start read */
                        out_be32(&ifc->ifc_nand.nandseq_strt,
-                               IFC_NAND_SEQ_STRT_FIR_STRT);
+                                IFC_NAND_SEQ_STRT_FIR_STRT);
 
                        /* wait for read to complete */
                        nand_wait(&buf[sram_addr], bufnum, page_size);
@@ -241,7 +228,6 @@ static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
 void nand_boot(void)
 {
        __attribute__((noreturn)) void (*uboot)(void);
-
        /*
         * Load U-Boot image from NAND into RAM
         */
@@ -257,15 +243,16 @@ void nand_boot(void)
                  (uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
 #endif
 #endif
-
        /*
         * Jump to U-Boot image
         */
+#ifdef CONFIG_SPL_FLUSH_IMAGE
        /*
         * Clean d-cache and invalidate i-cache, to
         * make sure that no stale data is executed.
         */
        flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
+#endif
        uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
        uboot();
 }
index 90f83924e2bf23b9ab4c621495ca236c14a19acd..ecbb2108fb368a576b7b85e843dea59942ede4de 100644 (file)
@@ -32,6 +32,7 @@ endif
 COBJS-$(CONFIG_SPI_FLASH)      += spi_flash.o
 COBJS-$(CONFIG_SPI_FLASH_ATMEL)        += atmel.o
 COBJS-$(CONFIG_SPI_FLASH_EON)  += eon.o
+COBJS-$(CONFIG_SPI_FLASH_GIGADEVICE)   += gigadevice.o
 COBJS-$(CONFIG_SPI_FLASH_MACRONIX)     += macronix.o
 COBJS-$(CONFIG_SPI_FLASH_SPANSION)     += spansion.o
 COBJS-$(CONFIG_SPI_FLASH_SST)  += sst.o
diff --git a/drivers/mtd/spi/gigadevice.c b/drivers/mtd/spi/gigadevice.c
new file mode 100644 (file)
index 0000000..b5e1ebe
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Gigadevice SPI flash driver
+ * Copyright 2013, Samsung Electronics Co., Ltd.
+ * Author: Banajit Goswami <banajit.g@samsung.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi_flash.h>
+
+#include "spi_flash_internal.h"
+
+struct gigadevice_spi_flash_params {
+       uint16_t        id;
+       uint16_t        nr_blocks;
+       const char      *name;
+};
+
+static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = {
+       {
+               .id                     = 0x6016,
+               .nr_blocks              = 64,
+               .name                   = "GD25LQ",
+       },
+       {
+               .id                     = 0x4017,
+               .nr_blocks              = 128,
+               .name                   = "GD25Q64B",
+       },
+};
+
+struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
+{
+       const struct gigadevice_spi_flash_params *params;
+       struct spi_flash *flash;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(gigadevice_spi_flash_table); i++) {
+               params = &gigadevice_spi_flash_table[i];
+               if (params->id == ((idcode[1] << 8) | idcode[2]))
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(gigadevice_spi_flash_table)) {
+               debug("SF: Unsupported Gigadevice ID %02x%02x\n",
+                               idcode[1], idcode[2]);
+               return NULL;
+       }
+
+       flash = spi_flash_alloc_base(spi, params->name);
+       if (!flash) {
+               debug("SF: Failed to allocate memory\n");
+               return NULL;
+       }
+       /* page_size */
+       flash->page_size = 256;
+       /* sector_size = page_size * pages_per_sector */
+       flash->sector_size = flash->page_size * 16;
+       /* size = sector_size * sector_per_block * number of blocks */
+       flash->size = flash->sector_size * 16 * params->nr_blocks;
+
+       return flash;
+}
index b3ef90f136367e954aaf08a2477f9c17810fd620..3ec2151b3a9454867910524da21c1d0b9a22b277 100644 (file)
@@ -101,7 +101,7 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
                .idcode2 = 0x4d01,
                .pages_per_sector = 256,
                .nr_sectors = 256,
-               .name = "S25FL129P_64K/S25FL128S",
+               .name = "S25FL129P_64K/S25FL128S_64K",
        },
        {
                .idcode1 = 0x0219,
@@ -110,6 +110,13 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
                .nr_sectors = 512,
                .name = "S25FL256S_64K",
        },
+       {
+               .idcode1 = 0x0220,
+               .idcode2 = 0x4d01,
+               .pages_per_sector = 256,
+               .nr_sectors = 1024,
+               .name = "S25FL512S_64K",
+       },
 };
 
 struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
index 0e38f594819073f91ee6bcaa3215c64fd46233ff..6a6fe37e0eea92e27817f47ca6c79c618325612c 100644 (file)
@@ -68,17 +68,60 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
        return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
 }
 
-int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
-               size_t len, const void *buf)
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
 {
-       unsigned long page_addr, byte_addr, page_size;
-       size_t chunk_len, actual;
+       struct spi_slave *spi = flash->spi;
+       unsigned long timebase;
        int ret;
-       u8 cmd[4];
+       u8 status;
+       u8 check_status = 0x0;
+       u8 poll_bit = STATUS_WIP;
+       u8 cmd = flash->poll_cmd;
 
-       page_size = flash->page_size;
-       page_addr = offset / page_size;
-       byte_addr = offset % page_size;
+       if (cmd == CMD_FLAG_STATUS) {
+               poll_bit = STATUS_PEC;
+               check_status = poll_bit;
+       }
+
+       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
+       if (ret) {
+               debug("SF: fail to read %s status register\n",
+                       cmd == CMD_READ_STATUS ? "read" : "flag");
+               return ret;
+       }
+
+       timebase = get_timer(0);
+       do {
+               WATCHDOG_RESET();
+
+               ret = spi_xfer(spi, 8, NULL, &status, 0);
+               if (ret)
+                       return -1;
+
+               if ((status & poll_bit) == check_status)
+                       break;
+
+       } while (get_timer(timebase) < timeout);
+
+       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+
+       if ((status & poll_bit) == check_status)
+               return 0;
+
+       /* Timed out */
+       debug("SF: time out!\n");
+       return -1;
+}
+
+int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
+               size_t cmd_len, const void *buf, size_t buf_len)
+{
+       struct spi_slave *spi = flash->spi;
+       unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
+       int ret;
+
+       if (buf == NULL)
+               timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
 
        ret = spi_claim_bus(flash->spi);
        if (ret) {
@@ -86,45 +129,122 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
                return ret;
        }
 
+       ret = spi_flash_cmd_write_enable(flash);
+       if (ret < 0) {
+               debug("SF: enabling write failed\n");
+               return ret;
+       }
+
+       ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
+       if (ret < 0) {
+               debug("SF: write cmd failed\n");
+               return ret;
+       }
+
+       ret = spi_flash_cmd_wait_ready(flash, timeout);
+       if (ret < 0) {
+               debug("SF: write %s timed out\n",
+                       timeout == SPI_FLASH_PROG_TIMEOUT ?
+                       "program" : "page erase");
+               return ret;
+       }
+
+       spi_release_bus(spi);
+
+       return ret;
+}
+
+int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
+{
+       u32 erase_size;
+       u8 cmd[4];
+       int ret = -1;
+
+       erase_size = flash->sector_size;
+       if (offset % erase_size || len % erase_size) {
+               debug("SF: Erase offset/length not multiple of erase size\n");
+               return -1;
+       }
+
+       if (erase_size == 4096)
+               cmd[0] = CMD_ERASE_4K;
+       else
+               cmd[0] = CMD_ERASE_64K;
+
+       while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+               u8 bank_sel;
+
+               bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+               if (ret) {
+                       debug("SF: fail to set bank%d\n", bank_sel);
+                       return ret;
+               }
+#endif
+               spi_flash_addr(offset, cmd);
+
+               debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
+                     cmd[2], cmd[3], offset);
+
+               ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
+               if (ret < 0) {
+                       debug("SF: erase failed\n");
+                       break;
+               }
+
+               offset += erase_size;
+               len -= erase_size;
+       }
+
+       return ret;
+}
+
+int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
+               size_t len, const void *buf)
+{
+       unsigned long byte_addr, page_size;
+       size_t chunk_len, actual;
+       u8 cmd[4];
+       int ret = -1;
+
+       page_size = flash->page_size;
+
        cmd[0] = CMD_PAGE_PROGRAM;
        for (actual = 0; actual < len; actual += chunk_len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+               u8 bank_sel;
+
+               bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+               if (ret) {
+                       debug("SF: fail to set bank%d\n", bank_sel);
+                       return ret;
+               }
+#endif
+               byte_addr = offset % page_size;
                chunk_len = min(len - actual, page_size - byte_addr);
 
                if (flash->spi->max_write_size)
                        chunk_len = min(chunk_len, flash->spi->max_write_size);
 
-               cmd[1] = page_addr >> 8;
-               cmd[2] = page_addr;
-               cmd[3] = byte_addr;
+               spi_flash_addr(offset, cmd);
 
                debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
                      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
 
-               ret = spi_flash_cmd_write_enable(flash);
-               if (ret < 0) {
-                       debug("SF: enabling write failed\n");
-                       break;
-               }
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4,
-                                         buf + actual, chunk_len);
+               ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
+                                       buf + actual, chunk_len);
                if (ret < 0) {
                        debug("SF: write failed\n");
                        break;
                }
 
-               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret)
-                       break;
-
-               byte_addr += chunk_len;
-               if (byte_addr == page_size) {
-                       page_addr++;
-                       byte_addr = 0;
-               }
+               offset += chunk_len;
        }
 
-       spi_release_bus(flash->spi);
        return ret;
 }
 
@@ -134,8 +254,18 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
        struct spi_slave *spi = flash->spi;
        int ret;
 
-       spi_claim_bus(spi);
+       ret = spi_claim_bus(flash->spi);
+       if (ret) {
+               debug("SF: unable to claim SPI bus\n");
+               return ret;
+       }
+
        ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
+       if (ret < 0) {
+               debug("SF: read cmd failed\n");
+               return ret;
+       }
+
        spi_release_bus(spi);
 
        return ret;
@@ -144,7 +274,9 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
 int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
                size_t len, void *data)
 {
-       u8 cmd[5];
+       u8 cmd[5], bank_sel = 0;
+       u32 remain_len, read_len;
+       int ret = -1;
 
        /* Handle memory-mapped SPI */
        if (flash->memory_map) {
@@ -153,130 +285,114 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
        }
 
        cmd[0] = CMD_READ_ARRAY_FAST;
-       spi_flash_addr(offset, cmd);
        cmd[4] = 0x00;
 
-       return spi_flash_read_common(flash, cmd, sizeof(cmd), data, len);
-}
-
-int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
-                          u8 cmd, u8 poll_bit)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 status;
-
-       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-       if (ret) {
-               debug("SF: Failed to send command %02x: %d\n", cmd, ret);
-               return ret;
-       }
+       while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+               bank_sel = offset / SPI_FLASH_16MB_BOUN;
 
-       timebase = get_timer(0);
-       do {
-               WATCHDOG_RESET();
+               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+               if (ret) {
+                       debug("SF: fail to set bank%d\n", bank_sel);
+                       return ret;
+               }
+#endif
+               remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset);
+               if (len < remain_len)
+                       read_len = len;
+               else
+                       read_len = remain_len;
 
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret)
-                       return -1;
+               spi_flash_addr(offset, cmd);
 
-               if ((status & poll_bit) == 0)
+               ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
+                                                       data, read_len);
+               if (ret < 0) {
+                       debug("SF: read failed\n");
                        break;
+               }
 
-       } while (get_timer(timebase) < timeout);
-
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if ((status & poll_bit) == 0)
-               return 0;
-
-       /* Timed out */
-       debug("SF: time out!\n");
-       return -1;
-}
+               offset += read_len;
+               len -= read_len;
+               data += read_len;
+       }
 
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       return spi_flash_cmd_poll_bit(flash, timeout,
-               CMD_READ_STATUS, STATUS_WIP);
+       return ret;
 }
 
-int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
+int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
 {
-       u32 end, erase_size;
+       u8 cmd;
        int ret;
-       u8 cmd[4];
-
-       erase_size = flash->sector_size;
-       if (offset % erase_size || len % erase_size) {
-               debug("SF: Erase offset/length not multiple of erase size\n");
-               return -1;
-       }
 
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
+       cmd = CMD_WRITE_STATUS;
+       ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1);
+       if (ret < 0) {
+               debug("SF: fail to write status register\n");
                return ret;
        }
 
-       if (erase_size == 4096)
-               cmd[0] = CMD_ERASE_4K;
-       else
-               cmd[0] = CMD_ERASE_64K;
-       end = offset + len;
-
-       while (offset < end) {
-               spi_flash_addr(offset, cmd);
-               offset += erase_size;
-
-               debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
-                     cmd[2], cmd[3], offset);
-
-               ret = spi_flash_cmd_write_enable(flash);
-               if (ret)
-                       goto out;
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0);
-               if (ret)
-                       goto out;
-
-               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret)
-                       goto out;
-       }
-
- out:
-       spi_release_bus(flash->spi);
-       return ret;
+       return 0;
 }
 
-int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
+#ifdef CONFIG_SPI_FLASH_BAR
+int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
 {
        u8 cmd;
        int ret;
 
-       ret = spi_flash_cmd_write_enable(flash);
+       if (flash->bank_curr == bank_sel) {
+               debug("SF: not require to enable bank%d\n", bank_sel);
+               return 0;
+       }
+
+       cmd = flash->bank_write_cmd;
+       ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
        if (ret < 0) {
-               debug("SF: enabling write failed\n");
+               debug("SF: fail to write bank register\n");
                return ret;
        }
+       flash->bank_curr = bank_sel;
 
-       cmd = CMD_WRITE_STATUS;
-       ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &sr, 1);
-       if (ret) {
-               debug("SF: fail to write status register\n");
-               return ret;
+       return 0;
+}
+
+int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0)
+{
+       u8 cmd;
+       u8 curr_bank = 0;
+
+       /* discover bank cmds */
+       switch (idcode0) {
+       case SPI_FLASH_SPANSION_IDCODE0:
+               flash->bank_read_cmd = CMD_BANKADDR_BRRD;
+               flash->bank_write_cmd = CMD_BANKADDR_BRWR;
+               break;
+       case SPI_FLASH_STMICRO_IDCODE0:
+       case SPI_FLASH_WINBOND_IDCODE0:
+               flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
+               flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
+               break;
+       default:
+               printf("SF: Unsupported bank commands %02x\n", idcode0);
+               return -1;
        }
 
-       ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-       if (ret < 0) {
-               debug("SF: write status register timed out\n");
-               return ret;
+       /* read the bank reg - on which bank the flash is in currently */
+       cmd = flash->bank_read_cmd;
+       if (flash->size > SPI_FLASH_16MB_BOUN) {
+               if (spi_flash_read_common(flash, &cmd, 1, &curr_bank, 1)) {
+                       debug("SF: fail to read bank addr register\n");
+                       return -1;
+               }
+               flash->bank_curr = curr_bank;
+       } else {
+               flash->bank_curr = curr_bank;
        }
 
        return 0;
 }
+#endif
 
 #ifdef CONFIG_OF_CONTROL
 int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
@@ -342,6 +458,9 @@ static const struct {
 #ifdef CONFIG_SPI_FLASH_EON
        { 0, 0x1c, spi_flash_probe_eon, },
 #endif
+#ifdef CONFIG_SPI_FLASH_GIGADEVICE
+       { 0, 0xc8, spi_flash_probe_gigadevice, },
+#endif
 #ifdef CONFIG_SPI_FLASH_MACRONIX
        { 0, 0xc2, spi_flash_probe_macronix, },
 #endif
@@ -422,6 +541,13 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
                goto err_manufacturer_probe;
        }
 
+#ifdef CONFIG_SPI_FLASH_BAR
+       /* Configure the BAR - disover bank cmds and read current bank  */
+       ret = spi_flash_bank_config(flash, *idp);
+       if (ret < 0)
+               goto err_manufacturer_probe;
+#endif
+
 #ifdef CONFIG_OF_CONTROL
        if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
                debug("SF: FDT decode error\n");
@@ -434,6 +560,12 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
        if (flash->memory_map)
                printf(", mapped at %p", flash->memory_map);
        puts("\n");
+#ifndef CONFIG_SPI_FLASH_BAR
+       if (flash->size > SPI_FLASH_16MB_BOUN) {
+               puts("SF: Warning - Only lower 16MiB accessible,");
+               puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
+       }
+#endif
 
        spi_release_bus(spi);
 
@@ -464,6 +596,7 @@ void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,
        /* Set up some basic fields - caller will sort out sizes */
        flash->spi = spi;
        flash->name = name;
+       flash->poll_cmd = CMD_READ_STATUS;
 
        flash->read = spi_flash_cmd_read_fast;
        flash->write = spi_flash_cmd_write_multi;
index 141cfa8b26d75e6e816c7315530854a93035b803..af1afa96c9dfe5d757650b84d605d4200da8a0fa 100644 (file)
 #define CMD_PAGE_PROGRAM               0x02
 #define CMD_WRITE_DISABLE              0x04
 #define CMD_READ_STATUS                        0x05
+#define CMD_FLAG_STATUS                        0x70
 #define CMD_WRITE_ENABLE               0x06
 #define CMD_ERASE_4K                   0x20
 #define CMD_ERASE_32K                  0x52
 #define CMD_ERASE_64K                  0xd8
 #define CMD_ERASE_CHIP                 0xc7
 
+#define SPI_FLASH_16MB_BOUN            0x1000000
+
+/* Manufacture ID's */
+#define SPI_FLASH_SPANSION_IDCODE0     0x01
+#define SPI_FLASH_STMICRO_IDCODE0      0x20
+#define SPI_FLASH_WINBOND_IDCODE0      0xef
+
+#ifdef CONFIG_SPI_FLASH_BAR
+/* Bank addr access commands */
+# define CMD_BANKADDR_BRWR             0x17
+# define CMD_BANKADDR_BRRD             0x16
+# define CMD_EXTNADDR_WREAR            0xC5
+# define CMD_EXTNADDR_RDEAR            0xC8
+#endif
+
 /* Common status */
 #define STATUS_WIP                     0x01
+#define STATUS_PEC                     0x80
 
 /* 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);
@@ -77,16 +94,30 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
 /* Program the status register. */
 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr);
 
+#ifdef CONFIG_SPI_FLASH_BAR
+/* Program the bank address register */
+int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel);
+
+/* Configure the BAR - discover the bank cmds */
+int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0);
+#endif
+
 /*
  * Same as spi_flash_cmd_read() except it also claims/releases the SPI
  * bus. Used as common part of the ->read() operation.
  */
 int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
                size_t cmd_len, void *data, size_t data_len);
-
-/* Send a command to the device and wait for some bit to clear itself. */
-int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
-                          u8 cmd, u8 poll_bit);
+/*
+ * Used for spi_flash write operation
+ * - SPI claim
+ * - spi_flash_cmd_write_enable
+ * - spi_flash_cmd_write
+ * - spi_flash_cmd_wait_ready
+ * - SPI release
+ */
+int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
+               size_t cmd_len, const void *buf, size_t buf_len);
 
 /*
  * Send the read status command to the device and wait for the wip
@@ -106,3 +137,4 @@ struct spi_flash *spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode);
 struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode);
 struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode);
 struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode);
+struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode);
index 2a9972bd4ee519f97c67c7df3e6c0c4ac49fa49d..7e41ee13219ba466cdad0f0d5934685cb7b34a29 100644 (file)
@@ -140,6 +140,30 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
                .nr_sectors = 512,
                .name = "N25Q256A",
        },
+       {
+               .id = 0xba20,
+               .pages_per_sector = 256,
+               .nr_sectors = 1024,
+               .name = "N25Q512",
+       },
+       {
+               .id = 0xbb20,
+               .pages_per_sector = 256,
+               .nr_sectors = 1024,
+               .name = "N25Q512A",
+       },
+       {
+               .id = 0xba21,
+               .pages_per_sector = 256,
+               .nr_sectors = 2048,
+               .name = "N25Q1024",
+       },
+       {
+               .id = 0xbb21,
+               .pages_per_sector = 256,
+               .nr_sectors = 2048,
+               .name = "N25Q1024A",
+       },
 };
 
 struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
@@ -186,5 +210,9 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
        flash->sector_size = 256 * params->pages_per_sector;
        flash->size = flash->sector_size * params->nr_sectors;
 
+       /* for >= 512MiB flashes, use flag status instead of read_status */
+       if (flash->size >= 0x4000000)
+               flash->poll_cmd = CMD_FLAG_STATUS;
+
        return flash;
 }
index 845780849273078251da183bf66e50659a95e42d..c399bf14d1f6ec52c719ec26e55c83ea2d0ea3d4 100644 (file)
@@ -55,27 +55,27 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
        {
                .id                     = 0x4014,
                .nr_blocks              = 16,
-               .name                   = "W25Q80BL",
+               .name                   = "W25Q80BL/W25Q80BV",
        },
        {
                .id                     = 0x4015,
                .nr_blocks              = 32,
-               .name                   = "W25Q16",
+               .name                   = "W25Q16CL/W25Q16DV",
        },
        {
                .id                     = 0x4016,
                .nr_blocks              = 64,
-               .name                   = "W25Q32",
+               .name                   = "W25Q32BV/W25Q32FV_SPI",
        },
        {
                .id                     = 0x4017,
                .nr_blocks              = 128,
-               .name                   = "W25Q64",
+               .name                   = "W25Q64CV/W25Q64FV_SPI",
        },
        {
                .id                     = 0x4018,
                .nr_blocks              = 256,
-               .name                   = "W25Q128",
+               .name                   = "W25Q128BV/W25Q128FV_SPI",
        },
        {
                .id                     = 0x4019,
@@ -87,15 +87,25 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
                .nr_blocks              = 16,
                .name                   = "W25Q80BW",
        },
+       {
+               .id                     = 0x6015,
+               .nr_blocks              = 32,
+               .name                   = "W25Q16DW",
+       },
        {
                .id                     = 0x6016,
                .nr_blocks              = 64,
-               .name                   = "W25Q32DW",
+               .name                   = "W25Q32DW/W25Q32FV_QPI",
        },
        {
                .id                     = 0x6017,
                .nr_blocks              = 128,
-               .name                   = "W25Q64DW",
+               .name                   = "W25Q64DW/W25Q64FV_QPI",
+       },
+       {
+               .id                     = 0x6018,
+               .nr_blocks              = 256,
+               .name                   = "W25Q128FW/W25Q128FV_QPI",
        },
 };
 
index 786a6567a5fc9ba5dbfc2c68262a789c5338a2ea..9cf2983d1874a7ef7ac435e747d1c1e780911f42 100644 (file)
@@ -46,10 +46,12 @@ COBJS-$(CONFIG_ETHOC) += ethoc.o
 COBJS-$(CONFIG_FEC_MXC) += fec_mxc.o
 COBJS-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o
 COBJS-$(CONFIG_FTGMAC100) += ftgmac100.o
+COBJS-$(CONFIG_FTMAC110) += ftmac110.o
 COBJS-$(CONFIG_FTMAC100) += ftmac100.o
 COBJS-$(CONFIG_GRETH) += greth.o
 COBJS-$(CONFIG_INCA_IP_SWITCH) += inca-ip_sw.o
 COBJS-$(CONFIG_DRIVER_KS8695ETH) += ks8695eth.o
+COBJS-$(CONFIG_KS8851_MLL) += ks8851_mll.o
 COBJS-$(CONFIG_LAN91C96) += lan91c96.o
 COBJS-$(CONFIG_MACB) += macb.o
 COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
@@ -68,6 +70,7 @@ COBJS-$(CONFIG_RTL8169) += rtl8169.o
 COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
 COBJS-$(CONFIG_SMC91111) += smc91111.o
 COBJS-$(CONFIG_SMC911X) += smc911x.o
+COBJS-$(CONFIG_SUNXI_WEMAC) += sunxi_wemac.o
 COBJS-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
 COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
 COBJS-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o
index bf21a08bdf475afb81d6335f51cfb84cf4a7e8f9..46f6601fa32e4873f360613f003615d9393b7539 100644 (file)
@@ -113,7 +113,9 @@ static int mac_reset(struct eth_device *dev)
        int timeout = CONFIG_MACRESET_TIMEOUT;
 
        writel(DMAMAC_SRST, &dma_p->busmode);
-       writel(MII_PORTSELECT, &mac_p->conf);
+
+       if (priv->interface != PHY_INTERFACE_MODE_RGMII)
+               writel(MII_PORTSELECT, &mac_p->conf);
 
        start = get_timer(0);
        while (get_timer(start) < timeout) {
index 69ba57d3d006e7638b96106221966b7980389682..2dbb328b8859ef54b5f7e4a417830dd892e750fd 100644 (file)
 #include <malloc.h>
 #include <net.h>
 #include <asm/io.h>
+#include <asm/dma-mapping.h>
 #include <linux/mii.h>
 
 #include "ftgmac100.h"
 
 #define ETH_ZLEN       60
+#define CFG_XBUF_SIZE  1536
 
 /* RBSR - hw default init value is also 0x640 */
 #define RBSR_DEFAULT_VALUE     0x640
 #define PKTBUFSTX      4       /* must be power of 2 */
 
 struct ftgmac100_data {
-       struct ftgmac100_txdes txdes[PKTBUFSTX];
-       struct ftgmac100_rxdes rxdes[PKTBUFSRX];
+       ulong txdes_dma;
+       struct ftgmac100_txdes *txdes;
+       ulong rxdes_dma;
+       struct ftgmac100_rxdes *rxdes;
        int tx_index;
        int rx_index;
        int phy_addr;
@@ -375,13 +379,34 @@ static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
 {
        struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
        struct ftgmac100_data *priv = dev->priv;
-       struct ftgmac100_txdes *txdes = priv->txdes;
-       struct ftgmac100_rxdes *rxdes = priv->rxdes;
+       struct ftgmac100_txdes *txdes;
+       struct ftgmac100_rxdes *rxdes;
        unsigned int maccr;
+       void *buf;
        int i;
 
        debug("%s()\n", __func__);
 
+       if (!priv->txdes) {
+               txdes = dma_alloc_coherent(
+                       sizeof(*txdes) * PKTBUFSTX, &priv->txdes_dma);
+               if (!txdes)
+                       panic("ftgmac100: out of memory\n");
+               memset(txdes, 0, sizeof(*txdes) * PKTBUFSTX);
+               priv->txdes = txdes;
+       }
+       txdes = priv->txdes;
+
+       if (!priv->rxdes) {
+               rxdes = dma_alloc_coherent(
+                       sizeof(*rxdes) * PKTBUFSRX, &priv->rxdes_dma);
+               if (!rxdes)
+                       panic("ftgmac100: out of memory\n");
+               memset(rxdes, 0, sizeof(*rxdes) * PKTBUFSRX);
+               priv->rxdes = rxdes;
+       }
+       rxdes = priv->rxdes;
+
        /* set the ethernet address */
        ftgmac100_set_mac_from_env(dev);
 
@@ -397,21 +422,31 @@ static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
 
        for (i = 0; i < PKTBUFSTX; i++) {
                /* TXBUF_BADR */
-               txdes[i].txdes3 = 0;
+               if (!txdes[i].txdes2) {
+                       buf = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE);
+                       if (!buf)
+                               panic("ftgmac100: out of memory\n");
+                       txdes[i].txdes3 = virt_to_phys(buf);
+                       txdes[i].txdes2 = (uint)buf;
+               }
                txdes[i].txdes1 = 0;
        }
 
        for (i = 0; i < PKTBUFSRX; i++) {
                /* RXBUF_BADR */
-               rxdes[i].rxdes3 = (unsigned int)NetRxPackets[i];
+               if (!rxdes[i].rxdes2) {
+                       buf = NetRxPackets[i];
+                       rxdes[i].rxdes3 = virt_to_phys(buf);
+                       rxdes[i].rxdes2 = (uint)buf;
+               }
                rxdes[i].rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
        }
 
        /* transmit ring */
-       writel((unsigned int)txdes, &ftgmac100->txr_badr);
+       writel(priv->txdes_dma, &ftgmac100->txr_badr);
 
        /* receive ring */
-       writel((unsigned int)rxdes, &ftgmac100->rxr_badr);
+       writel(priv->rxdes_dma, &ftgmac100->rxr_badr);
 
        /* poll receive descriptor automatically */
        writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
@@ -466,8 +501,11 @@ static int ftgmac100_recv(struct eth_device *dev)
        debug("%s(): RX buffer %d, %x received\n",
               __func__, priv->rx_index, rxlen);
 
+       /* invalidate d-cache */
+       dma_map_single((void *)curr_des->rxdes2, rxlen, DMA_FROM_DEVICE);
+
        /* pass the packet up to the protocol layers. */
-       NetReceive((void *)curr_des->rxdes3, rxlen);
+       NetReceive((void *)curr_des->rxdes2, rxlen);
 
        /* release buffer to DMA */
        curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
@@ -485,7 +523,6 @@ static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
        struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
        struct ftgmac100_data *priv = dev->priv;
        struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
-       int start;
 
        if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
                debug("%s(): no TX descriptor available\n", __func__);
@@ -496,8 +533,8 @@ static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
 
        length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
 
-       /* initiate a transmit sequence */
-       curr_des->txdes3 = (unsigned int)packet;        /* TXBUF_BADR */
+       memcpy((void *)curr_des->txdes2, (void *)packet, length);
+       dma_map_single((void *)curr_des->txdes2, length, DMA_TO_DEVICE);
 
        /* only one descriptor on TXBUF */
        curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR;
@@ -509,15 +546,6 @@ static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
        /* start transmit */
        writel(1, &ftgmac100->txpd);
 
-       /* wait for transfer to succeed */
-       start = get_timer(0);
-       while (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
-               if (get_timer(0) >= 5) {
-                       debug("%s(): timed out\n", __func__);
-                       return -1;
-               }
-       }
-
        debug("%s(): packet sent\n", __func__);
 
        priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
diff --git a/drivers/net/ftmac110.c b/drivers/net/ftmac110.c
new file mode 100644 (file)
index 0000000..579dcc7
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ * Faraday 10/100Mbps Ethernet Controller
+ *
+ * (C) Copyright 2010 Faraday Technology
+ * Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <net.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/dma-mapping.h>
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+#include "ftmac110.h"
+
+#define CFG_RXDES_NUM   8
+#define CFG_TXDES_NUM   2
+#define CFG_XBUF_SIZE   1536
+
+#define CFG_MDIORD_TIMEOUT  (CONFIG_SYS_HZ >> 1) /* 500 ms */
+#define CFG_MDIOWR_TIMEOUT  (CONFIG_SYS_HZ >> 1) /* 500 ms */
+#define CFG_LINKUP_TIMEOUT  (CONFIG_SYS_HZ << 2) /* 4 sec */
+
+/*
+ * FTMAC110 DMA design issue
+ *
+ * Its DMA engine has a weird restriction that its Rx DMA engine
+ * accepts only 16-bits aligned address, 32-bits aligned is not
+ * acceptable. However this restriction does not apply to Tx DMA.
+ *
+ * Conclusion:
+ * (1) Tx DMA Buffer Address:
+ *     1 bytes aligned: Invalid
+ *     2 bytes aligned: O.K
+ *     4 bytes aligned: O.K (-> u-boot ZeroCopy is possible)
+ * (2) Rx DMA Buffer Address:
+ *     1 bytes aligned: Invalid
+ *     2 bytes aligned: O.K
+ *     4 bytes aligned: Invalid
+ */
+
+struct ftmac110_chip {
+       void __iomem *regs;
+       uint32_t imr;
+       uint32_t maccr;
+       uint32_t lnkup;
+       uint32_t phy_addr;
+
+       struct ftmac110_rxd *rxd;
+       ulong                rxd_dma;
+       uint32_t             rxd_idx;
+
+       struct ftmac110_txd *txd;
+       ulong                txd_dma;
+       uint32_t             txd_idx;
+};
+
+static int ftmac110_reset(struct eth_device *dev);
+
+static uint16_t mdio_read(struct eth_device *dev,
+       uint8_t phyaddr, uint8_t phyreg)
+{
+       struct ftmac110_chip *chip = dev->priv;
+       struct ftmac110_regs __iomem *regs = chip->regs;
+       uint32_t tmp, ts;
+       uint16_t ret = 0xffff;
+
+       tmp = PHYCR_READ
+               | (phyaddr << PHYCR_ADDR_SHIFT)
+               | (phyreg  << PHYCR_REG_SHIFT);
+
+       writel(tmp, &regs->phycr);
+
+       for (ts = get_timer(0); get_timer(ts) < CFG_MDIORD_TIMEOUT; ) {
+               tmp = readl(&regs->phycr);
+               if (tmp & PHYCR_READ)
+                       continue;
+               break;
+       }
+
+       if (tmp & PHYCR_READ)
+               printf("ftmac110: mdio read timeout\n");
+       else
+               ret = (uint16_t)(tmp & 0xffff);
+
+       return ret;
+}
+
+static void mdio_write(struct eth_device *dev,
+       uint8_t phyaddr, uint8_t phyreg, uint16_t phydata)
+{
+       struct ftmac110_chip *chip = dev->priv;
+       struct ftmac110_regs __iomem *regs = chip->regs;
+       uint32_t tmp, ts;
+
+       tmp = PHYCR_WRITE
+               | (phyaddr << PHYCR_ADDR_SHIFT)
+               | (phyreg  << PHYCR_REG_SHIFT);
+
+       writel(phydata, &regs->phydr);
+       writel(tmp, &regs->phycr);
+
+       for (ts = get_timer(0); get_timer(ts) < CFG_MDIOWR_TIMEOUT; ) {
+               if (readl(&regs->phycr) & PHYCR_WRITE)
+                       continue;
+               break;
+       }
+
+       if (readl(&regs->phycr) & PHYCR_WRITE)
+               printf("ftmac110: mdio write timeout\n");
+}
+
+static uint32_t ftmac110_phyqry(struct eth_device *dev)
+{
+       ulong ts;
+       uint32_t maccr;
+       uint16_t pa, tmp, bmsr, bmcr;
+       struct ftmac110_chip *chip = dev->priv;
+
+       /* Default = 100Mbps Full */
+       maccr = MACCR_100M | MACCR_FD;
+
+       /* 1. find the phy device  */
+       for (pa = 0; pa < 32; ++pa) {
+               tmp = mdio_read(dev, pa, MII_PHYSID1);
+               if (tmp == 0xFFFF || tmp == 0x0000)
+                       continue;
+               chip->phy_addr = pa;
+               break;
+       }
+       if (pa >= 32) {
+               puts("ftmac110: phy device not found!\n");
+               goto exit;
+       }
+
+       /* 2. wait until link-up & auto-negotiation complete */
+       chip->lnkup = 0;
+       bmcr = mdio_read(dev, chip->phy_addr, MII_BMCR);
+       ts = get_timer(0);
+       do {
+               bmsr = mdio_read(dev, chip->phy_addr, MII_BMSR);
+               chip->lnkup = (bmsr & BMSR_LSTATUS) ? 1 : 0;
+               if (!chip->lnkup)
+                       continue;
+               if (!(bmcr & BMCR_ANENABLE) || (bmsr & BMSR_ANEGCOMPLETE))
+                       break;
+       } while (get_timer(ts) < CFG_LINKUP_TIMEOUT);
+       if (!chip->lnkup) {
+               puts("ftmac110: link down\n");
+               goto exit;
+       }
+       if (!(bmcr & BMCR_ANENABLE))
+               puts("ftmac110: auto negotiation disabled\n");
+       else if (!(bmsr & BMSR_ANEGCOMPLETE))
+               puts("ftmac110: auto negotiation timeout\n");
+
+       /* 3. derive MACCR */
+       if ((bmcr & BMCR_ANENABLE) && (bmsr & BMSR_ANEGCOMPLETE)) {
+               tmp  = mdio_read(dev, chip->phy_addr, MII_ADVERTISE);
+               tmp &= mdio_read(dev, chip->phy_addr, MII_LPA);
+               if (tmp & LPA_100FULL)      /* 100Mbps full-duplex */
+                       maccr = MACCR_100M | MACCR_FD;
+               else if (tmp & LPA_100HALF) /* 100Mbps half-duplex */
+                       maccr = MACCR_100M;
+               else if (tmp & LPA_10FULL)  /* 10Mbps full-duplex */
+                       maccr = MACCR_FD;
+               else if (tmp & LPA_10HALF)  /* 10Mbps half-duplex */
+                       maccr = 0;
+       } else {
+               if (bmcr & BMCR_SPEED100)
+                       maccr = MACCR_100M;
+               else
+                       maccr = 0;
+               if (bmcr & BMCR_FULLDPLX)
+                       maccr |= MACCR_FD;
+       }
+
+exit:
+       printf("ftmac110: %d Mbps, %s\n",
+              (maccr & MACCR_100M) ? 100 : 10,
+              (maccr & MACCR_FD) ? "Full" : "half");
+       return maccr;
+}
+
+static int ftmac110_reset(struct eth_device *dev)
+{
+       uint8_t *a;
+       uint32_t i, maccr;
+       struct ftmac110_chip *chip = dev->priv;
+       struct ftmac110_regs __iomem *regs = chip->regs;
+
+       /* 1. MAC reset */
+       writel(MACCR_RESET, &regs->maccr);
+       for (i = get_timer(0); get_timer(i) < 1000; ) {
+               if (readl(&regs->maccr) & MACCR_RESET)
+                       continue;
+               break;
+       }
+       if (readl(&regs->maccr) & MACCR_RESET) {
+               printf("ftmac110: reset failed\n");
+               return -ENXIO;
+       }
+
+       /* 1-1. Init tx ring */
+       for (i = 0; i < CFG_TXDES_NUM; ++i) {
+               /* owned by SW */
+               chip->txd[i].ct[0] = 0;
+       }
+       chip->txd_idx = 0;
+
+       /* 1-2. Init rx ring */
+       for (i = 0; i < CFG_RXDES_NUM; ++i) {
+               /* owned by HW */
+               chip->rxd[i].ct[0] = cpu_to_le32(FTMAC110_RXCT0_OWNER);
+       }
+       chip->rxd_idx = 0;
+
+       /* 2. PHY status query */
+       maccr = ftmac110_phyqry(dev);
+
+       /* 3. Fix up the MACCR value */
+       chip->maccr = maccr | MACCR_CRCAPD | MACCR_RXALL | MACCR_RXRUNT
+               | MACCR_RXEN | MACCR_TXEN | MACCR_RXDMAEN | MACCR_TXDMAEN;
+
+       /* 4. MAC address setup */
+       a = dev->enetaddr;
+       writel(a[1] | (a[0] << 8), &regs->mac[0]);
+       writel(a[5] | (a[4] << 8) | (a[3] << 16)
+               | (a[2] << 24), &regs->mac[1]);
+
+       /* 5. MAC registers setup */
+       writel(chip->rxd_dma, &regs->rxba);
+       writel(chip->txd_dma, &regs->txba);
+       /* interrupt at each tx/rx */
+       writel(ITC_DEFAULT, &regs->itc);
+       /* no tx pool, rx poll = 1 normal cycle */
+       writel(APTC_DEFAULT, &regs->aptc);
+       /* rx threshold = [6/8 fifo, 2/8 fifo] */
+       writel(DBLAC_DEFAULT, &regs->dblac);
+       /* disable & clear all interrupt status */
+       chip->imr = 0;
+       writel(ISR_ALL, &regs->isr);
+       writel(chip->imr, &regs->imr);
+       /* enable mac */
+       writel(chip->maccr, &regs->maccr);
+
+       return 0;
+}
+
+static int ftmac110_probe(struct eth_device *dev, bd_t *bis)
+{
+       debug("ftmac110: probe\n");
+
+       if (ftmac110_reset(dev))
+               return -1;
+
+       return 0;
+}
+
+static void ftmac110_halt(struct eth_device *dev)
+{
+       struct ftmac110_chip *chip = dev->priv;
+       struct ftmac110_regs __iomem *regs = chip->regs;
+
+       writel(0, &regs->imr);
+       writel(0, &regs->maccr);
+
+       debug("ftmac110: halt\n");
+}
+
+static int ftmac110_send(struct eth_device *dev, void *pkt, int len)
+{
+       struct ftmac110_chip *chip = dev->priv;
+       struct ftmac110_regs __iomem *regs = chip->regs;
+       struct ftmac110_txd *des;
+
+       if (!chip->lnkup)
+               return 0;
+
+       if (len <= 0 || len > CFG_XBUF_SIZE) {
+               printf("ftmac110: bad tx pkt len(%d)\n", len);
+               return 0;
+       }
+
+       len = max(60, len);
+
+       des = &chip->txd[chip->txd_idx];
+       if (le32_to_cpu(des->ct[0]) & FTMAC110_TXCT0_OWNER) {
+               /* kick-off Tx DMA */
+               writel(0xffffffff, &regs->txpd);
+               printf("ftmac110: out of txd\n");
+               return 0;
+       }
+
+       memcpy(des->vbuf, (void *)pkt, len);
+       dma_map_single(des->vbuf, len, DMA_TO_DEVICE);
+
+       /* update len, fts and lts */
+       des->ct[1] &= cpu_to_le32(FTMAC110_TXCT1_END);
+       des->ct[1] |= cpu_to_le32(FTMAC110_TXCT1_LEN(len)
+               | FTMAC110_TXCT1_FTS | FTMAC110_TXCT1_LTS);
+
+       /* set owner bit and clear others */
+       des->ct[0] = cpu_to_le32(FTMAC110_TXCT0_OWNER);
+
+       /* kick-off Tx DMA */
+       writel(0xffffffff, &regs->txpd);
+
+       chip->txd_idx = (chip->txd_idx + 1) % CFG_TXDES_NUM;
+
+       return len;
+}
+
+static int ftmac110_recv(struct eth_device *dev)
+{
+       struct ftmac110_chip *chip = dev->priv;
+       struct ftmac110_rxd *des;
+       uint32_t ct0, len, rlen = 0;
+       uint8_t *buf;
+
+       if (!chip->lnkup)
+               return 0;
+
+       do {
+               des = &chip->rxd[chip->rxd_idx];
+               ct0 = le32_to_cpu(des->ct[0]);
+               if (ct0 & FTMAC110_RXCT0_OWNER)
+                       break;
+
+               len = FTMAC110_RXCT0_LEN(ct0);
+               buf = des->vbuf;
+
+               if (ct0 & FTMAC110_RXCT0_ERRMASK) {
+                       printf("ftmac110: rx error\n");
+               } else {
+                       dma_map_single(buf, len, DMA_FROM_DEVICE);
+                       NetReceive(buf, len);
+                       rlen += len;
+               }
+
+               /* owned by hardware */
+               des->ct[0] = cpu_to_le32(FTMAC110_RXCT0_OWNER);
+
+               chip->rxd_idx = (chip->rxd_idx + 1) % CFG_RXDES_NUM;
+       } while (0);
+
+       return rlen;
+}
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+
+static int ftmac110_mdio_read(
+       const char *devname, uint8_t addr, uint8_t reg, uint16_t *value)
+{
+       int ret = 0;
+       struct eth_device *dev;
+
+       dev = eth_get_dev_by_name(devname);
+       if (dev == NULL) {
+               printf("%s: no such device\n", devname);
+               ret = -1;
+       } else {
+               *value = mdio_read(dev, addr, reg);
+       }
+
+       return ret;
+}
+
+static int ftmac110_mdio_write(
+       const char *devname, uint8_t addr, uint8_t reg, uint16_t value)
+{
+       int ret = 0;
+       struct eth_device *dev;
+
+       dev = eth_get_dev_by_name(devname);
+       if (dev == NULL) {
+               printf("%s: no such device\n", devname);
+               ret = -1;
+       } else {
+               mdio_write(dev, addr, reg, value);
+       }
+
+       return ret;
+}
+
+#endif    /* #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */
+
+int ftmac110_initialize(bd_t *bis)
+{
+       int i, card_nr = 0;
+       struct eth_device *dev;
+       struct ftmac110_chip *chip;
+
+       dev = malloc(sizeof(*dev) + sizeof(*chip));
+       if (dev == NULL) {
+               panic("ftmac110: out of memory 1\n");
+               return -1;
+       }
+       chip = (struct ftmac110_chip *)(dev + 1);
+       memset(dev, 0, sizeof(*dev) + sizeof(*chip));
+
+       sprintf(dev->name, "FTMAC110#%d", card_nr);
+
+       dev->iobase = CONFIG_FTMAC110_BASE;
+       chip->regs = (void __iomem *)dev->iobase;
+       dev->priv = chip;
+       dev->init = ftmac110_probe;
+       dev->halt = ftmac110_halt;
+       dev->send = ftmac110_send;
+       dev->recv = ftmac110_recv;
+
+       if (!eth_getenv_enetaddr_by_index("eth", card_nr, dev->enetaddr))
+               eth_random_enetaddr(dev->enetaddr);
+
+       /* allocate tx descriptors (it must be 16 bytes aligned) */
+       chip->txd = dma_alloc_coherent(
+               sizeof(struct ftmac110_txd) * CFG_TXDES_NUM, &chip->txd_dma);
+       if (!chip->txd)
+               panic("ftmac110: out of memory 3\n");
+       memset(chip->txd, 0,
+              sizeof(struct ftmac110_txd) * CFG_TXDES_NUM);
+       for (i = 0; i < CFG_TXDES_NUM; ++i) {
+               void *va = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE);
+               if (!va)
+                       panic("ftmac110: out of memory 4\n");
+               chip->txd[i].vbuf  = va;
+               chip->txd[i].buf   = cpu_to_le32(virt_to_phys(va));
+               chip->txd[i].ct[1] = 0;
+               chip->txd[i].ct[0] = 0; /* owned by SW */
+       }
+       chip->txd[i - 1].ct[1] |= cpu_to_le32(FTMAC110_TXCT1_END);
+       chip->txd_idx = 0;
+
+       /* allocate rx descriptors (it must be 16 bytes aligned) */
+       chip->rxd = dma_alloc_coherent(
+               sizeof(struct ftmac110_rxd) * CFG_RXDES_NUM, &chip->rxd_dma);
+       if (!chip->rxd)
+               panic("ftmac110: out of memory 4\n");
+       memset((void *)chip->rxd, 0,
+              sizeof(struct ftmac110_rxd) * CFG_RXDES_NUM);
+       for (i = 0; i < CFG_RXDES_NUM; ++i) {
+               void *va = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE + 2);
+               if (!va)
+                       panic("ftmac110: out of memory 5\n");
+               /* it needs to be exactly 2 bytes aligned */
+               va = ((uint8_t *)va + 2);
+               chip->rxd[i].vbuf  = va;
+               chip->rxd[i].buf   = cpu_to_le32(virt_to_phys(va));
+               chip->rxd[i].ct[1] = cpu_to_le32(CFG_XBUF_SIZE);
+               chip->rxd[i].ct[0] = cpu_to_le32(FTMAC110_RXCT0_OWNER);
+       }
+       chip->rxd[i - 1].ct[1] |= cpu_to_le32(FTMAC110_RXCT1_END);
+       chip->rxd_idx = 0;
+
+       eth_register(dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+       miiphy_register(dev->name, ftmac110_mdio_read, ftmac110_mdio_write);
+#endif
+
+       card_nr++;
+
+       return card_nr;
+}
diff --git a/drivers/net/ftmac110.h b/drivers/net/ftmac110.h
new file mode 100644 (file)
index 0000000..5b2d23b
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Faraday 10/100Mbps Ethernet Controller
+ *
+ * (C) Copyright 2010 Faraday Technology
+ * Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ */
+
+#ifndef _FTMAC110_H
+#define _FTMAC110_H
+
+struct ftmac110_regs {
+       uint32_t isr;    /* 0x00: Interrups Status Register */
+       uint32_t imr;    /* 0x04: Interrupt Mask Register */
+       uint32_t mac[2]; /* 0x08: MAC Address */
+       uint32_t mht[2]; /* 0x10: Multicast Hash Table Register */
+       uint32_t txpd;   /* 0x18: Tx Poll Demand Register */
+       uint32_t rxpd;   /* 0x1c: Rx Poll Demand Register */
+       uint32_t txba;   /* 0x20: Tx Ring Base Address Register */
+       uint32_t rxba;   /* 0x24: Rx Ring Base Address Register */
+       uint32_t itc;    /* 0x28: Interrupt Timer Control Register */
+       uint32_t aptc;   /* 0x2C: Automatic Polling Timer Control Register */
+       uint32_t dblac;  /* 0x30: DMA Burst Length&Arbitration Control */
+       uint32_t revr;   /* 0x34: Revision Register */
+       uint32_t fear;   /* 0x38: Feature Register */
+       uint32_t rsvd[19];
+       uint32_t maccr;  /* 0x88: MAC Control Register */
+       uint32_t macsr;  /* 0x8C: MAC Status Register */
+       uint32_t phycr;  /* 0x90: PHY Control Register */
+       uint32_t phydr;  /* 0x94: PHY Data Register */
+       uint32_t fcr;    /* 0x98: Flow Control Register */
+       uint32_t bpr;    /* 0x9C: Back Pressure Register */
+};
+
+/*
+ * Interrupt status/mask register(ISR/IMR) bits
+ */
+#define ISR_ALL          0x3ff
+#define ISR_PHYSTCHG     (1 << 9) /* phy status change */
+#define ISR_AHBERR       (1 << 8) /* bus error */
+#define ISR_RXLOST       (1 << 7) /* rx lost */
+#define ISR_RXFIFO       (1 << 6) /* rx to fifo */
+#define ISR_TXLOST       (1 << 5) /* tx lost */
+#define ISR_TXOK         (1 << 4) /* tx to ethernet */
+#define ISR_NOTXBUF      (1 << 3) /* out of tx buffer */
+#define ISR_TXFIFO       (1 << 2) /* tx to fifo */
+#define ISR_NORXBUF      (1 << 1) /* out of rx buffer */
+#define ISR_RXOK         (1 << 0) /* rx to buffer */
+
+/*
+ * MACCR control bits
+ */
+#define MACCR_100M       (1 << 18) /* 100Mbps mode */
+#define MACCR_RXBCST     (1 << 17) /* rx broadcast packet */
+#define MACCR_RXMCST     (1 << 16) /* rx multicast packet */
+#define MACCR_FD         (1 << 15) /* full duplex */
+#define MACCR_CRCAPD     (1 << 14) /* tx crc append */
+#define MACCR_RXALL      (1 << 12) /* rx all packets */
+#define MACCR_RXFTL      (1 << 11) /* rx packet even it's > 1518 byte */
+#define MACCR_RXRUNT     (1 << 10) /* rx packet even it's < 64 byte */
+#define MACCR_RXMCSTHT   (1 << 9)  /* rx multicast hash table */
+#define MACCR_RXEN       (1 << 8)  /* rx enable */
+#define MACCR_RXINHDTX   (1 << 6)  /* rx in half duplex tx */
+#define MACCR_TXEN       (1 << 5)  /* tx enable */
+#define MACCR_CRCDIS     (1 << 4)  /* tx packet even it's crc error */
+#define MACCR_LOOPBACK   (1 << 3)  /* loop-back */
+#define MACCR_RESET      (1 << 2)  /* reset */
+#define MACCR_RXDMAEN    (1 << 1)  /* rx dma enable */
+#define MACCR_TXDMAEN    (1 << 0)  /* tx dma enable */
+
+/*
+ * PHYCR control bits
+ */
+#define PHYCR_READ       (1 << 26)
+#define PHYCR_WRITE      (1 << 27)
+#define PHYCR_REG_SHIFT  21
+#define PHYCR_ADDR_SHIFT 16
+
+/*
+ * ITC control bits
+ */
+
+/* Tx Cycle Length */
+#define ITC_TX_CYCLONG   (1 << 15) /* 100Mbps=81.92us; 10Mbps=819.2us */
+#define ITC_TX_CYCNORM   (0 << 15) /* 100Mbps=5.12us;  10Mbps=51.2us */
+/* Tx Threshold: Aggregate n interrupts as 1 interrupt */
+#define ITC_TX_THR(n)    (((n) & 0x7) << 12)
+/* Tx Interrupt Timeout = n * Tx Cycle */
+#define ITC_TX_ITMO(n)   (((n) & 0xf) << 8)
+/* Rx Cycle Length */
+#define ITC_RX_CYCLONG   (1 << 7)  /* 100Mbps=81.92us; 10Mbps=819.2us */
+#define ITC_RX_CYCNORM   (0 << 7)  /* 100Mbps=5.12us;  10Mbps=51.2us */
+/* Rx Threshold: Aggregate n interrupts as 1 interrupt */
+#define ITC_RX_THR(n)    (((n) & 0x7) << 4)
+/* Rx Interrupt Timeout = n * Rx Cycle */
+#define ITC_RX_ITMO(n)   (((n) & 0xf) << 0)
+
+#define ITC_DEFAULT \
+       (ITC_TX_THR(1) | ITC_TX_ITMO(0) | ITC_RX_THR(1) | ITC_RX_ITMO(0))
+
+/*
+ * APTC contrl bits
+ */
+
+/* Tx Cycle Length */
+#define APTC_TX_CYCLONG  (1 << 12) /* 100Mbps=81.92us; 10Mbps=819.2us */
+#define APTC_TX_CYCNORM  (0 << 12) /* 100Mbps=5.12us;  10Mbps=51.2us */
+/* Tx Poll Timeout = n * Tx Cycle, 0=No auto polling */
+#define APTC_TX_PTMO(n)  (((n) & 0xf) << 8)
+/* Rx Cycle Length */
+#define APTC_RX_CYCLONG  (1 << 4)  /* 100Mbps=81.92us; 10Mbps=819.2us */
+#define APTC_RX_CYCNORM  (0 << 4)  /* 100Mbps=5.12us;  10Mbps=51.2us */
+/* Rx Poll Timeout = n * Rx Cycle, 0=No auto polling */
+#define APTC_RX_PTMO(n)  (((n) & 0xf) << 0)
+
+#define APTC_DEFAULT     (APTC_TX_PTMO(0) | APTC_RX_PTMO(1))
+
+/*
+ * DBLAC contrl bits
+ */
+#define DBLAC_BURST_MAX_ANY  (0 << 14) /* un-limited */
+#define DBLAC_BURST_MAX_32X4 (2 << 14) /* max = 32 x 4 bytes */
+#define DBLAC_BURST_MAX_64X4 (3 << 14) /* max = 64 x 4 bytes */
+#define DBLAC_RXTHR_EN       (1 << 9)  /* enable rx threshold arbitration */
+#define DBLAC_RXTHR_HIGH(n)  (((n) & 0x7) << 6) /* upper bound = n/8 fifo */
+#define DBLAC_RXTHR_LOW(n)   (((n) & 0x7) << 3) /* lower bound = n/8 fifo */
+#define DBLAC_BURST_CAP16    (1 << 2)  /* support burst 16 */
+#define DBLAC_BURST_CAP8     (1 << 1)  /* support burst 8 */
+#define DBLAC_BURST_CAP4     (1 << 0)  /* support burst 4 */
+
+#define DBLAC_DEFAULT \
+       (DBLAC_RXTHR_EN | DBLAC_RXTHR_HIGH(6) | DBLAC_RXTHR_LOW(2))
+
+/*
+ * descriptor structure
+ */
+struct ftmac110_rxd {
+       uint32_t ct[2];
+       uint32_t buf;
+       void    *vbuf; /* reserved */
+};
+
+#define FTMAC110_RXCT0_OWNER       BIT_MASK(31) /* owner: 1=HW, 0=SW */
+#define FTMAC110_RXCT0_FRS         BIT_MASK(29) /* first pkt desc */
+#define FTMAC110_RXCT0_LRS         BIT_MASK(28) /* last pkt desc */
+#define FTMAC110_RXCT0_ODDNB       BIT_MASK(22) /* odd nibble */
+#define FTMAC110_RXCT0_RUNT        BIT_MASK(21) /* runt pkt */
+#define FTMAC110_RXCT0_FTL         BIT_MASK(20) /* frame too long */
+#define FTMAC110_RXCT0_CRC         BIT_MASK(19) /* pkt crc error */
+#define FTMAC110_RXCT0_ERR         BIT_MASK(18) /* bus error */
+#define FTMAC110_RXCT0_ERRMASK     (0x1f << 18) /* all errors */
+#define FTMAC110_RXCT0_BCST        BIT_MASK(17) /* Bcst pkt */
+#define FTMAC110_RXCT0_MCST        BIT_MASK(16) /* Mcst pkt */
+#define FTMAC110_RXCT0_LEN(x)      ((x) & 0x7ff)
+
+#define FTMAC110_RXCT1_END         BIT_MASK(31)
+#define FTMAC110_RXCT1_BUFSZ(x)    ((x) & 0x7ff)
+
+struct ftmac110_txd {
+       uint32_t ct[2];
+       uint32_t buf;
+       void    *vbuf; /* reserved */
+};
+
+#define FTMAC110_TXCT0_OWNER       BIT_MASK(31) /* owner: 1=HW, 0=SW */
+#define FTMAC110_TXCT0_COL         0x00000003   /* collision */
+
+#define FTMAC110_TXCT1_END         BIT_MASK(31) /* end of ring */
+#define FTMAC110_TXCT1_TXIC        BIT_MASK(30) /* tx done interrupt */
+#define FTMAC110_TXCT1_TX2FIC      BIT_MASK(29) /* tx fifo interrupt */
+#define FTMAC110_TXCT1_FTS         BIT_MASK(28) /* first pkt desc */
+#define FTMAC110_TXCT1_LTS         BIT_MASK(27) /* last pkt desc */
+#define FTMAC110_TXCT1_LEN(x)      ((x) & 0x7ff)
+
+#endif  /* FTMAC110_H */
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
new file mode 100644 (file)
index 0000000..b02d59a
--- /dev/null
@@ -0,0 +1,645 @@
+/*
+ * Micrel KS8851_MLL 16bit Network driver
+ * Copyright (c) 2011 Roberto Cerati <roberto.cerati@bticino.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+
+#include "ks8851_mll.h"
+
+#define DRIVERNAME                     "ks8851_mll"
+
+#define MAX_RECV_FRAMES                        32
+#define MAX_BUF_SIZE                   2048
+#define TX_BUF_SIZE                    2000
+#define RX_BUF_SIZE                    2000
+
+static const struct chip_id chip_ids[] =  {
+       {CIDER_ID, "KSZ8851"},
+       {0, NULL},
+};
+
+/*
+ * union ks_tx_hdr - tx header data
+ * @txb: The header as bytes
+ * @txw: The header as 16bit, little-endian words
+ *
+ * A dual representation of the tx header data to allow
+ * access to individual bytes, and to allow 16bit accesses
+ * with 16bit alignment.
+ */
+union ks_tx_hdr {
+       u8      txb[4];
+       __le16  txw[2];
+};
+
+/*
+ * struct ks_net - KS8851 driver private data
+ * @net_device : The network device we're bound to
+ * @txh                : temporaly buffer to save status/length.
+ * @frame_head_info    : frame header information for multi-pkt rx.
+ * @statelock  : Lock on this structure for tx list.
+ * @msg_enable : The message flags controlling driver output (see ethtool).
+ * @frame_cnt  : number of frames received.
+ * @bus_width  : i/o bus width.
+ * @irq                : irq number assigned to this device.
+ * @rc_rxqcr   : Cached copy of KS_RXQCR.
+ * @rc_txcr    : Cached copy of KS_TXCR.
+ * @rc_ier     : Cached copy of KS_IER.
+ * @sharedbus  : Multipex(addr and data bus) mode indicator.
+ * @cmd_reg_cache      : command register cached.
+ * @cmd_reg_cache_int  : command register cached. Used in the irq handler.
+ * @promiscuous        : promiscuous mode indicator.
+ * @all_mcast  : mutlicast indicator.
+ * @mcast_lst_size     : size of multicast list.
+ * @mcast_lst          : multicast list.
+ * @mcast_bits         : multicast enabed.
+ * @mac_addr           : MAC address assigned to this device.
+ * @fid                        : frame id.
+ * @extra_byte         : number of extra byte prepended rx pkt.
+ * @enabled            : indicator this device works.
+ */
+
+/* Receive multiplex framer header info */
+struct type_frame_head {
+       u16     sts;         /* Frame status */
+       u16     len;         /* Byte count */
+} fr_h_i[MAX_RECV_FRAMES];
+
+struct ks_net {
+       struct net_device       *netdev;
+       union ks_tx_hdr         txh;
+       struct type_frame_head  *frame_head_info;
+       u32                     msg_enable;
+       u32                     frame_cnt;
+       int                     bus_width;
+       int                     irq;
+       u16                     rc_rxqcr;
+       u16                     rc_txcr;
+       u16                     rc_ier;
+       u16                     sharedbus;
+       u16                     cmd_reg_cache;
+       u16                     cmd_reg_cache_int;
+       u16                     promiscuous;
+       u16                     all_mcast;
+       u16                     mcast_lst_size;
+       u8                      mcast_lst[MAX_MCAST_LST][MAC_ADDR_LEN];
+       u8                      mcast_bits[HW_MCAST_SIZE];
+       u8                      mac_addr[6];
+       u8                      fid;
+       u8                      extra_byte;
+       u8                      enabled;
+} ks_str, *ks;
+
+#define BE3             0x8000      /* Byte Enable 3 */
+#define BE2             0x4000      /* Byte Enable 2 */
+#define BE1             0x2000      /* Byte Enable 1 */
+#define BE0             0x1000      /* Byte Enable 0 */
+
+static u8 ks_rdreg8(struct eth_device *dev, u16 offset)
+{
+       u8 shift_bit = offset & 0x03;
+       u8 shift_data = (offset & 1) << 3;
+
+       writew(offset | (BE0 << shift_bit), dev->iobase + 2);
+
+       return (u8)(readw(dev->iobase) >> shift_data);
+}
+
+static u16 ks_rdreg16(struct eth_device *dev, u16 offset)
+{
+       writew(offset | ((BE1 | BE0) << (offset & 0x02)), dev->iobase + 2);
+
+       return readw(dev->iobase);
+}
+
+static void ks_wrreg8(struct eth_device *dev, u16 offset, u8 val)
+{
+       u8 shift_bit = (offset & 0x03);
+       u16 value_write = (u16)(val << ((offset & 1) << 3));
+
+       writew(offset | (BE0 << shift_bit), dev->iobase + 2);
+       writew(value_write, dev->iobase);
+}
+
+static void ks_wrreg16(struct eth_device *dev, u16 offset, u16 val)
+{
+       writew(offset | ((BE1 | BE0) << (offset & 0x02)), dev->iobase + 2);
+       writew(val, dev->iobase);
+}
+
+/*
+ * ks_inblk - read a block of data from QMU. This is called after sudo DMA mode
+ * enabled.
+ * @ks: The chip state
+ * @wptr: buffer address to save data
+ * @len: length in byte to read
+ */
+static inline void ks_inblk(struct eth_device *dev, u16 *wptr, u32 len)
+{
+       len >>= 1;
+
+       while (len--)
+               *wptr++ = readw(dev->iobase);
+}
+
+/*
+ * ks_outblk - write data to QMU. This is called after sudo DMA mode enabled.
+ * @ks: The chip information
+ * @wptr: buffer address
+ * @len: length in byte to write
+ */
+static inline void ks_outblk(struct eth_device *dev, u16 *wptr, u32 len)
+{
+       len >>= 1;
+
+       while (len--)
+               writew(*wptr++, dev->iobase);
+}
+
+static void ks_enable_int(struct eth_device *dev)
+{
+       ks_wrreg16(dev, KS_IER, ks->rc_ier);
+}
+
+static void ks_set_powermode(struct eth_device *dev, unsigned pwrmode)
+{
+       unsigned pmecr;
+
+       ks_rdreg16(dev, KS_GRR);
+       pmecr = ks_rdreg16(dev, KS_PMECR);
+       pmecr &= ~PMECR_PM_MASK;
+       pmecr |= pwrmode;
+
+       ks_wrreg16(dev, KS_PMECR, pmecr);
+}
+
+/*
+ * ks_read_config - read chip configuration of bus width.
+ * @ks: The chip information
+ */
+static void ks_read_config(struct eth_device *dev)
+{
+       u16 reg_data = 0;
+
+       /* Regardless of bus width, 8 bit read should always work. */
+       reg_data = ks_rdreg8(dev, KS_CCR) & 0x00FF;
+       reg_data |= ks_rdreg8(dev, KS_CCR + 1) << 8;
+
+       /* addr/data bus are multiplexed */
+       ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED;
+
+       /*
+        * There are garbage data when reading data from QMU,
+        * depending on bus-width.
+        */
+       if (reg_data & CCR_8BIT) {
+               ks->bus_width = ENUM_BUS_8BIT;
+               ks->extra_byte = 1;
+       } else if (reg_data & CCR_16BIT) {
+               ks->bus_width = ENUM_BUS_16BIT;
+               ks->extra_byte = 2;
+       } else {
+               ks->bus_width = ENUM_BUS_32BIT;
+               ks->extra_byte = 4;
+       }
+}
+
+/*
+ * ks_soft_reset - issue one of the soft reset to the device
+ * @ks: The device state.
+ * @op: The bit(s) to set in the GRR
+ *
+ * Issue the relevant soft-reset command to the device's GRR register
+ * specified by @op.
+ *
+ * Note, the delays are in there as a caution to ensure that the reset
+ * has time to take effect and then complete. Since the datasheet does
+ * not currently specify the exact sequence, we have chosen something
+ * that seems to work with our device.
+ */
+static void ks_soft_reset(struct eth_device *dev, unsigned op)
+{
+       /* Disable interrupt first */
+       ks_wrreg16(dev, KS_IER, 0x0000);
+       ks_wrreg16(dev, KS_GRR, op);
+       mdelay(10);     /* wait a short time to effect reset */
+       ks_wrreg16(dev, KS_GRR, 0);
+       mdelay(1);      /* wait for condition to clear */
+}
+
+void ks_enable_qmu(struct eth_device *dev)
+{
+       u16 w;
+
+       w = ks_rdreg16(dev, KS_TXCR);
+
+       /* Enables QMU Transmit (TXCR). */
+       ks_wrreg16(dev, KS_TXCR, w | TXCR_TXE);
+
+       /* Enable RX Frame Count Threshold and Auto-Dequeue RXQ Frame */
+       w = ks_rdreg16(dev, KS_RXQCR);
+       ks_wrreg16(dev, KS_RXQCR, w | RXQCR_RXFCTE);
+
+       /* Enables QMU Receive (RXCR1). */
+       w = ks_rdreg16(dev, KS_RXCR1);
+       ks_wrreg16(dev, KS_RXCR1, w | RXCR1_RXE);
+}
+
+static void ks_disable_qmu(struct eth_device *dev)
+{
+       u16 w;
+
+       w = ks_rdreg16(dev, KS_TXCR);
+
+       /* Disables QMU Transmit (TXCR). */
+       w &= ~TXCR_TXE;
+       ks_wrreg16(dev, KS_TXCR, w);
+
+       /* Disables QMU Receive (RXCR1). */
+       w = ks_rdreg16(dev, KS_RXCR1);
+       w &= ~RXCR1_RXE;
+       ks_wrreg16(dev, KS_RXCR1, w);
+}
+
+static inline void ks_read_qmu(struct eth_device *dev, u16 *buf, u32 len)
+{
+       u32 r = ks->extra_byte & 0x1;
+       u32 w = ks->extra_byte - r;
+
+       /* 1. set sudo DMA mode */
+       ks_wrreg16(dev, KS_RXFDPR, RXFDPR_RXFPAI);
+       ks_wrreg8(dev, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+
+       /*
+        * 2. read prepend data
+        *
+        * read 4 + extra bytes and discard them.
+        * extra bytes for dummy, 2 for status, 2 for len
+        */
+
+       if (r)
+               ks_rdreg8(dev, 0);
+
+       ks_inblk(dev, buf, w + 2 + 2);
+
+       /* 3. read pkt data */
+       ks_inblk(dev, buf, ALIGN(len, 4));
+
+       /* 4. reset sudo DMA Mode */
+       ks_wrreg8(dev, KS_RXQCR, (ks->rc_rxqcr & ~RXQCR_SDA) & 0xff);
+}
+
+static void ks_rcv(struct eth_device *dev, uchar **pv_data)
+{
+       struct type_frame_head *frame_hdr = ks->frame_head_info;
+       int i;
+
+       ks->frame_cnt = ks_rdreg16(dev, KS_RXFCTR) >> 8;
+
+       /* read all header information */
+       for (i = 0; i < ks->frame_cnt; i++) {
+               /* Checking Received packet status */
+               frame_hdr->sts = ks_rdreg16(dev, KS_RXFHSR);
+               /* Get packet len from hardware */
+               frame_hdr->len = ks_rdreg16(dev, KS_RXFHBCR);
+               frame_hdr++;
+       }
+
+       frame_hdr = ks->frame_head_info;
+       while (ks->frame_cnt--) {
+               if ((frame_hdr->sts & RXFSHR_RXFV) &&
+                   (frame_hdr->len < RX_BUF_SIZE) &&
+                   frame_hdr->len) {
+                       /* read data block including CRC 4 bytes */
+                       ks_read_qmu(dev, (u16 *)(*pv_data), frame_hdr->len);
+
+                       /* NetRxPackets buffer size is ok (*pv_data pointer) */
+                       NetReceive(*pv_data, frame_hdr->len);
+                       pv_data++;
+               } else {
+                       ks_wrreg16(dev, KS_RXQCR, (ks->rc_rxqcr | RXQCR_RRXEF));
+                       printf(DRIVERNAME ": bad packet\n");
+               }
+               frame_hdr++;
+       }
+}
+
+/*
+ * ks_read_selftest - read the selftest memory info.
+ * @ks: The device state
+ *
+ * Read and check the TX/RX memory selftest information.
+ */
+static int ks_read_selftest(struct eth_device *dev)
+{
+       u16 both_done = MBIR_TXMBF | MBIR_RXMBF;
+       u16 mbir;
+       int ret = 0;
+
+       mbir = ks_rdreg16(dev, KS_MBIR);
+
+       if ((mbir & both_done) != both_done) {
+               printf(DRIVERNAME ": Memory selftest not finished\n");
+               return 0;
+       }
+
+       if (mbir & MBIR_TXMBFA) {
+               printf(DRIVERNAME ": TX memory selftest fails\n");
+               ret |= 1;
+       }
+
+       if (mbir & MBIR_RXMBFA) {
+               printf(DRIVERNAME ": RX memory selftest fails\n");
+               ret |= 2;
+       }
+
+       debug(DRIVERNAME ": the selftest passes\n");
+
+       return ret;
+}
+
+static void ks_setup(struct eth_device *dev)
+{
+       u16 w;
+
+       /* Setup Transmit Frame Data Pointer Auto-Increment (TXFDPR) */
+       ks_wrreg16(dev, KS_TXFDPR, TXFDPR_TXFPAI);
+
+       /* Setup Receive Frame Data Pointer Auto-Increment */
+       ks_wrreg16(dev, KS_RXFDPR, RXFDPR_RXFPAI);
+
+       /* Setup Receive Frame Threshold - 1 frame (RXFCTFC) */
+       ks_wrreg16(dev, KS_RXFCTR, 1 & RXFCTR_THRESHOLD_MASK);
+
+       /* Setup RxQ Command Control (RXQCR) */
+       ks->rc_rxqcr = RXQCR_CMD_CNTL;
+       ks_wrreg16(dev, KS_RXQCR, ks->rc_rxqcr);
+
+       /*
+        * set the force mode to half duplex, default is full duplex
+        * because if the auto-negotiation fails, most switch uses
+        * half-duplex.
+        */
+       w = ks_rdreg16(dev, KS_P1MBCR);
+       w &= ~P1MBCR_FORCE_FDX;
+       ks_wrreg16(dev, KS_P1MBCR, w);
+
+       w = TXCR_TXFCE | TXCR_TXPE | TXCR_TXCRC | TXCR_TCGIP;
+       ks_wrreg16(dev, KS_TXCR, w);
+
+       w = RXCR1_RXFCE | RXCR1_RXBE | RXCR1_RXUE | RXCR1_RXME | RXCR1_RXIPFCC;
+
+       /* Normal mode */
+       w |= RXCR1_RXPAFMA;
+
+       ks_wrreg16(dev, KS_RXCR1, w);
+}
+
+static void ks_setup_int(struct eth_device *dev)
+{
+       ks->rc_ier = 0x00;
+
+       /* Clear the interrupts status of the hardware. */
+       ks_wrreg16(dev, KS_ISR, 0xffff);
+
+       /* Enables the interrupts of the hardware. */
+       ks->rc_ier = (IRQ_LCI | IRQ_TXI | IRQ_RXI);
+}
+
+static int ks8851_mll_detect_chip(struct eth_device *dev)
+{
+       unsigned short val, i;
+
+       ks_read_config(dev);
+
+       val = ks_rdreg16(dev, KS_CIDER);
+
+       if (val == 0xffff) {
+               /* Special case -- no chip present */
+               printf(DRIVERNAME ":  is chip mounted ?\n");
+               return -1;
+       } else if ((val & 0xfff0) != CIDER_ID) {
+               printf(DRIVERNAME ": Invalid chip id 0x%04x\n", val);
+               return -1;
+       }
+
+       debug("Read back KS8851 id 0x%x\n", val);
+
+       /* only one entry in the table */
+       val &= 0xfff0;
+       for (i = 0; chip_ids[i].id != 0; i++) {
+               if (chip_ids[i].id == val)
+                       break;
+       }
+       if (!chip_ids[i].id) {
+               printf(DRIVERNAME ": Unknown chip ID %04x\n", val);
+               return -1;
+       }
+
+       dev->priv = (void *)&chip_ids[i];
+
+       return 0;
+}
+
+static void ks8851_mll_reset(struct eth_device *dev)
+{
+       /* wake up powermode to normal mode */
+       ks_set_powermode(dev, PMECR_PM_NORMAL);
+       mdelay(1);      /* wait for normal mode to take effect */
+
+       /* Disable interrupt and reset */
+       ks_soft_reset(dev, GRR_GSR);
+
+       /* turn off the IRQs and ack any outstanding */
+       ks_wrreg16(dev, KS_IER, 0x0000);
+       ks_wrreg16(dev, KS_ISR, 0xffff);
+
+       /* shutdown RX/TX QMU */
+       ks_disable_qmu(dev);
+}
+
+static void ks8851_mll_phy_configure(struct eth_device *dev)
+{
+       u16 data;
+
+       ks_setup(dev);
+       ks_setup_int(dev);
+
+       /* Probing the phy */
+       data = ks_rdreg16(dev, KS_OBCR);
+       ks_wrreg16(dev, KS_OBCR, data | OBCR_ODS_16MA);
+
+       debug(DRIVERNAME ": phy initialized\n");
+}
+
+static void ks8851_mll_enable(struct eth_device *dev)
+{
+       ks_wrreg16(dev, KS_ISR, 0xffff);
+       ks_enable_int(dev);
+       ks_enable_qmu(dev);
+}
+
+static int ks8851_mll_init(struct eth_device *dev, bd_t *bd)
+{
+       struct chip_id *id = dev->priv;
+
+       debug(DRIVERNAME ": detected %s controller\n", id->name);
+
+       if (ks_read_selftest(dev)) {
+               printf(DRIVERNAME ": Selftest failed\n");
+               return -1;
+       }
+
+       ks8851_mll_reset(dev);
+
+       /* Configure the PHY, initialize the link state */
+       ks8851_mll_phy_configure(dev);
+
+       /* static allocation of private informations */
+       ks->frame_head_info = fr_h_i;
+
+       /* Turn on Tx + Rx */
+       ks8851_mll_enable(dev);
+
+       return 0;
+}
+
+static void ks_write_qmu(struct eth_device *dev, u8 *pdata, u16 len)
+{
+       /* start header at txb[0] to align txw entries */
+       ks->txh.txw[0] = 0;
+       ks->txh.txw[1] = cpu_to_le16(len);
+
+       /* 1. set sudo-DMA mode */
+       ks_wrreg16(dev, KS_TXFDPR, TXFDPR_TXFPAI);
+       ks_wrreg8(dev, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+       /* 2. write status/lenth info */
+       ks_outblk(dev, ks->txh.txw, 4);
+       /* 3. write pkt data */
+       ks_outblk(dev, (u16 *)pdata, ALIGN(len, 4));
+       /* 4. reset sudo-DMA mode */
+       ks_wrreg8(dev, KS_RXQCR, (ks->rc_rxqcr & ~RXQCR_SDA) & 0xff);
+       /* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */
+       ks_wrreg16(dev, KS_TXQCR, TXQCR_METFE);
+       /* 6. wait until TXQCR_METFE is auto-cleared */
+       do { } while (ks_rdreg16(dev, KS_TXQCR) & TXQCR_METFE);
+}
+
+static int ks8851_mll_send(struct eth_device *dev, void *packet, int length)
+{
+       u8 *data = (u8 *)packet;
+       u16 tmplen = (u16)length;
+       u16 retv;
+
+       /*
+        * Extra space are required:
+        * 4 byte for alignment, 4 for status/length, 4 for CRC
+        */
+       retv = ks_rdreg16(dev, KS_TXMIR) & 0x1fff;
+       if (retv >= tmplen + 12) {
+               ks_write_qmu(dev, data, tmplen);
+               return 0;
+       } else {
+               printf(DRIVERNAME ": failed to send packet: No buffer\n");
+               return -1;
+       }
+}
+
+static void ks8851_mll_halt(struct eth_device *dev)
+{
+       ks8851_mll_reset(dev);
+}
+
+/*
+ * Maximum receive ring size; that is, the number of packets
+ * we can buffer before overflow happens. Basically, this just
+ * needs to be enough to prevent a packet being discarded while
+ * we are processing the previous one.
+ */
+static int ks8851_mll_recv(struct eth_device *dev)
+{
+       u16 status;
+
+       status = ks_rdreg16(dev, KS_ISR);
+
+       ks_wrreg16(dev, KS_ISR, status);
+
+       if ((status & IRQ_RXI))
+               ks_rcv(dev, (uchar **)NetRxPackets);
+
+       if ((status & IRQ_LDI)) {
+               u16 pmecr = ks_rdreg16(dev, KS_PMECR);
+               pmecr &= ~PMECR_WKEVT_MASK;
+               ks_wrreg16(dev, KS_PMECR, pmecr | PMECR_WKEVT_LINK);
+       }
+
+       return 0;
+}
+
+static int ks8851_mll_write_hwaddr(struct eth_device *dev)
+{
+       u16 addrl, addrm, addrh;
+
+       addrh = (dev->enetaddr[0] << 8) | dev->enetaddr[1];
+       addrm = (dev->enetaddr[2] << 8) | dev->enetaddr[3];
+       addrl = (dev->enetaddr[4] << 8) | dev->enetaddr[5];
+
+       ks_wrreg16(dev, KS_MARH, addrh);
+       ks_wrreg16(dev, KS_MARM, addrm);
+       ks_wrreg16(dev, KS_MARL, addrl);
+
+       return 0;
+}
+
+int ks8851_mll_initialize(u8 dev_num, int base_addr)
+{
+       struct eth_device *dev;
+
+       dev = malloc(sizeof(*dev));
+       if (!dev) {
+               printf("Error: Failed to allocate memory\n");
+               return -1;
+       }
+       memset(dev, 0, sizeof(*dev));
+
+       dev->iobase = base_addr;
+
+       ks = &ks_str;
+
+       /* Try to detect chip. Will fail if not present. */
+       if (ks8851_mll_detect_chip(dev)) {
+               free(dev);
+               return -1;
+       }
+
+       dev->init = ks8851_mll_init;
+       dev->halt = ks8851_mll_halt;
+       dev->send = ks8851_mll_send;
+       dev->recv = ks8851_mll_recv;
+       dev->write_hwaddr = ks8851_mll_write_hwaddr;
+       sprintf(dev->name, "%s-%hu", DRIVERNAME, dev_num);
+
+       eth_register(dev);
+
+       return 0;
+}
diff --git a/drivers/net/ks8851_mll.h b/drivers/net/ks8851_mll.h
new file mode 100644 (file)
index 0000000..7f90ae4
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * drivers/net/ks8851_mll.c
+ *
+ * Supports:
+ * KS8851 16bit MLL chip from Micrel Inc.
+ *
+ * Copyright (c) 2009 Micrel Inc.
+ *
+ * modified by
+ * (c) 2011 Bticino s.p.a, Roberto Cerati <roberto.cerati@bticino.it>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _KS8851_MLL_H_
+#define _KS8851_MLL_H_
+
+#include <linux/types.h>
+
+#define KS_CCR                         0x08
+#define CCR_EEPROM                     (1 << 9)
+#define CCR_SPI                                (1 << 8)
+#define CCR_8BIT                       (1 << 7)
+#define CCR_16BIT                      (1 << 6)
+#define CCR_32BIT                      (1 << 5)
+#define CCR_SHARED                     (1 << 4)
+#define CCR_32PIN                      (1 << 0)
+
+/* MAC address registers */
+#define KS_MARL                                0x10
+#define KS_MARM                                0x12
+#define KS_MARH                                0x14
+
+#define KS_OBCR                                0x20
+#define OBCR_ODS_16MA                  (1 << 6)
+
+#define KS_EEPCR                       0x22
+#define EEPCR_EESA                     (1 << 4)
+#define EEPCR_EESB                     (1 << 3)
+#define EEPCR_EEDO                     (1 << 2)
+#define EEPCR_EESCK                    (1 << 1)
+#define EEPCR_EECS                     (1 << 0)
+
+#define KS_MBIR                                0x24
+#define MBIR_TXMBF                     (1 << 12)
+#define MBIR_TXMBFA                    (1 << 11)
+#define MBIR_RXMBF                     (1 << 4)
+#define MBIR_RXMBFA                    (1 << 3)
+
+#define KS_GRR                         0x26
+#define GRR_QMU                                (1 << 1)
+#define GRR_GSR                                (1 << 0)
+
+#define KS_WFCR                                0x2A
+#define WFCR_MPRXE                     (1 << 7)
+#define WFCR_WF3E                      (1 << 3)
+#define WFCR_WF2E                      (1 << 2)
+#define WFCR_WF1E                      (1 << 1)
+#define WFCR_WF0E                      (1 << 0)
+
+#define KS_WF0CRC0                     0x30
+#define KS_WF0CRC1                     0x32
+#define KS_WF0BM0                      0x34
+#define KS_WF0BM1                      0x36
+#define KS_WF0BM2                      0x38
+#define KS_WF0BM3                      0x3A
+
+#define KS_WF1CRC0                     0x40
+#define KS_WF1CRC1                     0x42
+#define KS_WF1BM0                      0x44
+#define KS_WF1BM1                      0x46
+#define KS_WF1BM2                      0x48
+#define KS_WF1BM3                      0x4A
+
+#define KS_WF2CRC0                     0x50
+#define KS_WF2CRC1                     0x52
+#define KS_WF2BM0                      0x54
+#define KS_WF2BM1                      0x56
+#define KS_WF2BM2                      0x58
+#define KS_WF2BM3                      0x5A
+
+#define KS_WF3CRC0                     0x60
+#define KS_WF3CRC1                     0x62
+#define KS_WF3BM0                      0x64
+#define KS_WF3BM1                      0x66
+#define KS_WF3BM2                      0x68
+#define KS_WF3BM3                      0x6A
+
+#define KS_TXCR                                0x70
+#define TXCR_TCGICMP                   (1 << 8)
+#define TXCR_TCGUDP                    (1 << 7)
+#define TXCR_TCGTCP                    (1 << 6)
+#define TXCR_TCGIP                     (1 << 5)
+#define TXCR_FTXQ                      (1 << 4)
+#define TXCR_TXFCE                     (1 << 3)
+#define TXCR_TXPE                      (1 << 2)
+#define TXCR_TXCRC                     (1 << 1)
+#define TXCR_TXE                       (1 << 0)
+
+#define KS_TXSR                                0x72
+#define TXSR_TXLC                      (1 << 13)
+#define TXSR_TXMC                      (1 << 12)
+#define TXSR_TXFID_MASK                        (0x3f << 0)
+#define TXSR_TXFID_SHIFT               (0)
+#define TXSR_TXFID_GET(_v)             (((_v) >> 0) & 0x3f)
+
+
+#define KS_RXCR1                       0x74
+#define RXCR1_FRXQ                     (1 << 15)
+#define RXCR1_RXUDPFCC                 (1 << 14)
+#define RXCR1_RXTCPFCC                 (1 << 13)
+#define RXCR1_RXIPFCC                  (1 << 12)
+#define RXCR1_RXPAFMA                  (1 << 11)
+#define RXCR1_RXFCE                    (1 << 10)
+#define RXCR1_RXEFE                    (1 << 9)
+#define RXCR1_RXMAFMA                  (1 << 8)
+#define RXCR1_RXBE                     (1 << 7)
+#define RXCR1_RXME                     (1 << 6)
+#define RXCR1_RXUE                     (1 << 5)
+#define RXCR1_RXAE                     (1 << 4)
+#define RXCR1_RXINVF                   (1 << 1)
+#define RXCR1_RXE                      (1 << 0)
+#define RXCR1_FILTER_MASK              (RXCR1_RXINVF | RXCR1_RXAE | \
+                                        RXCR1_RXMAFMA | RXCR1_RXPAFMA)
+
+#define KS_RXCR2                       0x76
+#define RXCR2_SRDBL_MASK               (0x7 << 5)
+#define RXCR2_SRDBL_SHIFT              (5)
+#define RXCR2_SRDBL_4B                 (0x0 << 5)
+#define RXCR2_SRDBL_8B                 (0x1 << 5)
+#define RXCR2_SRDBL_16B                        (0x2 << 5)
+#define RXCR2_SRDBL_32B                        (0x3 << 5)
+/* #define RXCR2_SRDBL_FRAME           (0x4 << 5) */
+#define RXCR2_IUFFP                    (1 << 4)
+#define RXCR2_RXIUFCEZ                 (1 << 3)
+#define RXCR2_UDPLFE                   (1 << 2)
+#define RXCR2_RXICMPFCC                        (1 << 1)
+#define RXCR2_RXSAF                    (1 << 0)
+
+#define KS_TXMIR                       0x78
+
+#define KS_RXFHSR                      0x7C
+#define RXFSHR_RXFV                    (1 << 15)
+#define RXFSHR_RXICMPFCS               (1 << 13)
+#define RXFSHR_RXIPFCS                 (1 << 12)
+#define RXFSHR_RXTCPFCS                        (1 << 11)
+#define RXFSHR_RXUDPFCS                        (1 << 10)
+#define RXFSHR_RXBF                    (1 << 7)
+#define RXFSHR_RXMF                    (1 << 6)
+#define RXFSHR_RXUF                    (1 << 5)
+#define RXFSHR_RXMR                    (1 << 4)
+#define RXFSHR_RXFT                    (1 << 3)
+#define RXFSHR_RXFTL                   (1 << 2)
+#define RXFSHR_RXRF                    (1 << 1)
+#define RXFSHR_RXCE                    (1 << 0)
+#define RXFSHR_ERR                     (RXFSHR_RXCE | RXFSHR_RXRF |\
+                                       RXFSHR_RXFTL | RXFSHR_RXMR |\
+                                       RXFSHR_RXICMPFCS | RXFSHR_RXIPFCS |\
+                                       RXFSHR_RXTCPFCS)
+#define KS_RXFHBCR                     0x7E
+#define RXFHBCR_CNT_MASK               0x0FFF
+
+#define KS_TXQCR                       0x80
+#define TXQCR_AETFE                    (1 << 2)
+#define TXQCR_TXQMAM                   (1 << 1)
+#define TXQCR_METFE                    (1 << 0)
+
+#define KS_RXQCR                       0x82
+#define RXQCR_RXDTTS                   (1 << 12)
+#define RXQCR_RXDBCTS                  (1 << 11)
+#define RXQCR_RXFCTS                   (1 << 10)
+#define RXQCR_RXIPHTOE                 (1 << 9)
+#define RXQCR_RXDTTE                   (1 << 7)
+#define RXQCR_RXDBCTE                  (1 << 6)
+#define RXQCR_RXFCTE                   (1 << 5)
+#define RXQCR_ADRFE                    (1 << 4)
+#define RXQCR_SDA                      (1 << 3)
+#define RXQCR_RRXEF                    (1 << 0)
+#define RXQCR_CMD_CNTL                 (RXQCR_RXFCTE|RXQCR_ADRFE)
+
+#define KS_TXFDPR                      0x84
+#define TXFDPR_TXFPAI                  (1 << 14)
+#define TXFDPR_TXFP_MASK               (0x7ff << 0)
+#define TXFDPR_TXFP_SHIFT              (0)
+
+#define KS_RXFDPR                      0x86
+#define RXFDPR_RXFPAI                  (1 << 14)
+
+#define KS_RXDTTR                      0x8C
+#define KS_RXDBCTR                     0x8E
+
+#define KS_IER                         0x90
+#define KS_ISR                         0x92
+#define IRQ_LCI                                (1 << 15)
+#define IRQ_TXI                                (1 << 14)
+#define IRQ_RXI                                (1 << 13)
+#define IRQ_RXOI                       (1 << 11)
+#define IRQ_TXPSI                      (1 << 9)
+#define IRQ_RXPSI                      (1 << 8)
+#define IRQ_TXSAI                      (1 << 6)
+#define IRQ_RXWFDI                     (1 << 5)
+#define IRQ_RXMPDI                     (1 << 4)
+#define IRQ_LDI                                (1 << 3)
+#define IRQ_EDI                                (1 << 2)
+#define IRQ_SPIBEI                     (1 << 1)
+#define IRQ_DEDI                       (1 << 0)
+
+#define KS_RXFCTR                      0x9C
+#define RXFCTR_THRESHOLD_MASK          0x00FF
+
+#define KS_RXFC                                0x9D
+#define RXFCTR_RXFC_MASK               (0xff << 8)
+#define RXFCTR_RXFC_SHIFT              (8)
+#define RXFCTR_RXFC_GET(_v)            (((_v) >> 8) & 0xff)
+#define RXFCTR_RXFCT_MASK              (0xff << 0)
+#define RXFCTR_RXFCT_SHIFT             (0)
+
+#define KS_TXNTFSR                     0x9E
+
+#define KS_MAHTR0                      0xA0
+#define KS_MAHTR1                      0xA2
+#define KS_MAHTR2                      0xA4
+#define KS_MAHTR3                      0xA6
+
+#define KS_FCLWR                       0xB0
+#define KS_FCHWR                       0xB2
+#define KS_FCOWR                       0xB4
+
+#define KS_CIDER                       0xC0
+#define CIDER_ID                       0x8870
+#define CIDER_REV_MASK                 (0x7 << 1)
+#define CIDER_REV_SHIFT                        (1)
+#define CIDER_REV_GET(_v)              (((_v) >> 1) & 0x7)
+
+#define KS_CGCR                                0xC6
+#define KS_IACR                                0xC8
+#define IACR_RDEN                      (1 << 12)
+#define IACR_TSEL_MASK                 (0x3 << 10)
+#define IACR_TSEL_SHIFT                        (10)
+#define IACR_TSEL_MIB                  (0x3 << 10)
+#define IACR_ADDR_MASK                 (0x1f << 0)
+#define IACR_ADDR_SHIFT                        (0)
+
+#define KS_IADLR                       0xD0
+#define KS_IAHDR                       0xD2
+
+#define KS_PMECR                       0xD4
+#define PMECR_PME_DELAY                        (1 << 14)
+#define PMECR_PME_POL                  (1 << 12)
+#define PMECR_WOL_WAKEUP               (1 << 11)
+#define PMECR_WOL_MAGICPKT             (1 << 10)
+#define PMECR_WOL_LINKUP               (1 << 9)
+#define PMECR_WOL_ENERGY               (1 << 8)
+#define PMECR_AUTO_WAKE_EN             (1 << 7)
+#define PMECR_WAKEUP_NORMAL            (1 << 6)
+#define PMECR_WKEVT_MASK               (0xf << 2)
+#define PMECR_WKEVT_SHIFT              (2)
+#define PMECR_WKEVT_GET(_v)            (((_v) >> 2) & 0xf)
+#define PMECR_WKEVT_ENERGY             (0x1 << 2)
+#define PMECR_WKEVT_LINK               (0x2 << 2)
+#define PMECR_WKEVT_MAGICPKT           (0x4 << 2)
+#define PMECR_WKEVT_FRAME              (0x8 << 2)
+#define PMECR_PM_MASK                  (0x3 << 0)
+#define PMECR_PM_SHIFT                 (0)
+#define PMECR_PM_NORMAL                        (0x0 << 0)
+#define PMECR_PM_ENERGY                        (0x1 << 0)
+#define PMECR_PM_SOFTDOWN              (0x2 << 0)
+#define PMECR_PM_POWERSAVE             (0x3 << 0)
+
+/* Standard MII PHY data */
+#define KS_P1MBCR                      0xE4
+#define P1MBCR_FORCE_FDX               (1 << 8)
+
+#define KS_P1MBSR                      0xE6
+#define P1MBSR_AN_COMPLETE             (1 << 5)
+#define P1MBSR_AN_CAPABLE              (1 << 3)
+#define P1MBSR_LINK_UP                 (1 << 2)
+
+#define KS_PHY1ILR                     0xE8
+#define KS_PHY1IHR                     0xEA
+#define KS_P1ANAR                      0xEC
+#define KS_P1ANLPR                     0xEE
+
+#define KS_P1SCLMD                     0xF4
+#define P1SCLMD_LEDOFF                 (1 << 15)
+#define P1SCLMD_TXIDS                  (1 << 14)
+#define P1SCLMD_RESTARTAN              (1 << 13)
+#define P1SCLMD_DISAUTOMDIX            (1 << 10)
+#define P1SCLMD_FORCEMDIX              (1 << 9)
+#define P1SCLMD_AUTONEGEN              (1 << 7)
+#define P1SCLMD_FORCE100               (1 << 6)
+#define P1SCLMD_FORCEFDX               (1 << 5)
+#define P1SCLMD_ADV_FLOW               (1 << 4)
+#define P1SCLMD_ADV_100BT_FDX          (1 << 3)
+#define P1SCLMD_ADV_100BT_HDX          (1 << 2)
+#define P1SCLMD_ADV_10BT_FDX           (1 << 1)
+#define P1SCLMD_ADV_10BT_HDX           (1 << 0)
+
+#define KS_P1CR                                0xF6
+#define P1CR_HP_MDIX                   (1 << 15)
+#define P1CR_REV_POL                   (1 << 13)
+#define P1CR_OP_100M                   (1 << 10)
+#define P1CR_OP_FDX                    (1 << 9)
+#define P1CR_OP_MDI                    (1 << 7)
+#define P1CR_AN_DONE                   (1 << 6)
+#define P1CR_LINK_GOOD                 (1 << 5)
+#define P1CR_PNTR_FLOW                 (1 << 4)
+#define P1CR_PNTR_100BT_FDX            (1 << 3)
+#define P1CR_PNTR_100BT_HDX            (1 << 2)
+#define P1CR_PNTR_10BT_FDX             (1 << 1)
+#define P1CR_PNTR_10BT_HDX             (1 << 0)
+
+/* TX Frame control */
+#define TXFR_TXIC                      (1 << 15)
+#define TXFR_TXFID_MASK                        (0x3f << 0)
+#define TXFR_TXFID_SHIFT               (0)
+
+#define KS_P1SR                                0xF8
+#define P1SR_HP_MDIX                   (1 << 15)
+#define P1SR_REV_POL                   (1 << 13)
+#define P1SR_OP_100M                   (1 << 10)
+#define P1SR_OP_FDX                    (1 << 9)
+#define P1SR_OP_MDI                    (1 << 7)
+#define P1SR_AN_DONE                   (1 << 6)
+#define P1SR_LINK_GOOD                 (1 << 5)
+#define P1SR_PNTR_FLOW                 (1 << 4)
+#define P1SR_PNTR_100BT_FDX            (1 << 3)
+#define P1SR_PNTR_100BT_HDX            (1 << 2)
+#define P1SR_PNTR_10BT_FDX             (1 << 1)
+#define P1SR_PNTR_10BT_HDX             (1 << 0)
+
+#define ENUM_BUS_NONE                  0
+#define ENUM_BUS_8BIT                  1
+#define ENUM_BUS_16BIT                 2
+#define ENUM_BUS_32BIT                 3
+
+#define MAX_MCAST_LST                  32
+#define HW_MCAST_SIZE                  8
+#define MAC_ADDR_LEN                   6
+
+/* Chip ID values */
+struct chip_id {
+       u16 id;
+       char *name;
+};
+
+#endif
index 8bacbda71966942c12944d148a7acce0d176c59b..b7802a2fed70828c7f9f38c10013a1f15d5abf25 100644 (file)
@@ -103,9 +103,15 @@ struct macb_device {
        const struct device     *dev;
        struct eth_device       netdev;
        unsigned short          phy_addr;
+       struct mii_dev          *bus;
 };
 #define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
 
+static int macb_is_gem(struct macb_device *macb)
+{
+       return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2;
+}
+
 static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)
 {
        unsigned long netctl;
@@ -163,7 +169,12 @@ static u16 macb_mdio_read(struct macb_device *macb, u8 reg)
        return MACB_BFEXT(DATA, frame);
 }
 
-#if defined(CONFIG_CMD_MII)
+void __weak arch_get_mdio_control(const char *name)
+{
+       return;
+}
+
+#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
 
 int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
 {
@@ -173,6 +184,7 @@ int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
        if ( macb->phy_addr != phy_adr )
                return -1;
 
+       arch_get_mdio_control(devname);
        *value = macb_mdio_read(macb, reg);
 
        return 0;
@@ -186,6 +198,7 @@ int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
        if ( macb->phy_addr != phy_adr )
                return -1;
 
+       arch_get_mdio_control(devname);
        macb_mdio_write(macb, reg, value);
 
        return 0;
@@ -372,11 +385,15 @@ static int macb_phy_find(struct macb_device *macb)
 static int macb_phy_init(struct macb_device *macb)
 {
        struct eth_device *netdev = &macb->netdev;
+#ifdef CONFIG_PHYLIB
+       struct phy_device *phydev;
+#endif
        u32 ncfgr;
        u16 phy_id, status, adv, lpa;
        int media, speed, duplex;
        int i;
 
+       arch_get_mdio_control(netdev->name);
 #ifdef CONFIG_MACB_SEARCH_PHY
        /* Auto-detect phy_addr */
        if (!macb_phy_find(macb)) {
@@ -391,6 +408,13 @@ static int macb_phy_init(struct macb_device *macb)
                return 0;
        }
 
+#ifdef CONFIG_PHYLIB
+       phydev->bus = macb->bus;
+       phydev->dev = netdev;
+       phydev->addr = macb->phy_addr;
+       phy_config(phydev);
+#endif
+
        status = macb_mdio_read(macb, MII_BMSR);
        if (!(status & BMSR_LSTATUS)) {
                /* Try to re-negotiate if we don't have link already. */
@@ -408,28 +432,64 @@ static int macb_phy_init(struct macb_device *macb)
                printf("%s: link down (status: 0x%04x)\n",
                       netdev->name, status);
                return 0;
-       } else {
-               adv = macb_mdio_read(macb, MII_ADVERTISE);
-               lpa = macb_mdio_read(macb, MII_LPA);
-               media = mii_nway_result(lpa & adv);
-               speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
-                        ? 1 : 0);
-               duplex = (media & ADVERTISE_FULL) ? 1 : 0;
-               printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
-                      netdev->name,
-                      speed ? "100" : "10",
-                      duplex ? "full" : "half",
-                      lpa);
-
-               ncfgr = macb_readl(macb, NCFGR);
-               ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
-               if (speed)
-                       ncfgr |= MACB_BIT(SPD);
-               if (duplex)
-                       ncfgr |= MACB_BIT(FD);
-               macb_writel(macb, NCFGR, ncfgr);
-               return 1;
        }
+
+       /* First check for GMAC */
+       if (macb_is_gem(macb)) {
+               lpa = macb_mdio_read(macb, MII_STAT1000);
+               if (lpa & (1 << 11)) {
+                       speed = 1000;
+                       duplex = 1;
+               } else {
+                      if (lpa & (1 << 10)) {
+                               speed = 1000;
+                               duplex = 1;
+                       } else {
+                               speed = 0;
+                       }
+               }
+
+               if (speed == 1000) {
+                       printf("%s: link up, %dMbps %s-duplex (lpa: 0x%04x)\n",
+                              netdev->name,
+                              speed,
+                              duplex ? "full" : "half",
+                              lpa);
+
+                       ncfgr = macb_readl(macb, NCFGR);
+                       ncfgr &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD));
+                       if (speed)
+                               ncfgr |= GEM_BIT(GBE);
+                       if (duplex)
+                               ncfgr |= MACB_BIT(FD);
+                       macb_writel(macb, NCFGR, ncfgr);
+
+                       return 1;
+               }
+       }
+
+       /* fall back for EMAC checking */
+       adv = macb_mdio_read(macb, MII_ADVERTISE);
+       lpa = macb_mdio_read(macb, MII_LPA);
+       media = mii_nway_result(lpa & adv);
+       speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
+                ? 1 : 0);
+       duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+       printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
+              netdev->name,
+              speed ? "100" : "10",
+              duplex ? "full" : "half",
+              lpa);
+
+       ncfgr = macb_readl(macb, NCFGR);
+       ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+       if (speed)
+               ncfgr |= MACB_BIT(SPD);
+       if (duplex)
+               ncfgr |= MACB_BIT(FD);
+       macb_writel(macb, NCFGR, ncfgr);
+
+       return 1;
 }
 
 static int macb_init(struct eth_device *netdev, bd_t *bd)
@@ -464,26 +524,28 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
        macb_writel(macb, RBQP, macb->rx_ring_dma);
        macb_writel(macb, TBQP, macb->tx_ring_dma);
 
+       if (macb_is_gem(macb)) {
+#ifdef CONFIG_RGMII
+               gem_writel(macb, UR, GEM_BIT(RGMII));
+#else
+               gem_writel(macb, UR, 0);
+#endif
+       } else {
        /* choose RMII or MII mode. This depends on the board */
 #ifdef CONFIG_RMII
-#if    defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
-       defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \
-       defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \
-       defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5)
+#ifdef CONFIG_AT91FAMILY
        macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
 #else
        macb_writel(macb, USRIO, 0);
 #endif
 #else
-#if    defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \
-       defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \
-       defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \
-       defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5)
+#ifdef CONFIG_AT91FAMILY
        macb_writel(macb, USRIO, MACB_BIT(CLKEN));
 #else
        macb_writel(macb, USRIO, MACB_BIT(MII));
 #endif
 #endif /* CONFIG_RMII */
+       }
 
        if (!macb_phy_init(macb))
                return -1;
@@ -527,11 +589,48 @@ static int macb_write_hwaddr(struct eth_device *dev)
        return 0;
 }
 
+static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
+{
+       u32 config;
+       unsigned long macb_hz = get_macb_pclk_rate(id);
+
+       if (macb_hz < 20000000)
+               config = MACB_BF(CLK, MACB_CLK_DIV8);
+       else if (macb_hz < 40000000)
+               config = MACB_BF(CLK, MACB_CLK_DIV16);
+       else if (macb_hz < 80000000)
+               config = MACB_BF(CLK, MACB_CLK_DIV32);
+       else
+               config = MACB_BF(CLK, MACB_CLK_DIV64);
+
+       return config;
+}
+
+static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
+{
+       u32 config;
+       unsigned long macb_hz = get_macb_pclk_rate(id);
+
+       if (macb_hz < 20000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV8);
+       else if (macb_hz < 40000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV16);
+       else if (macb_hz < 80000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV32);
+       else if (macb_hz < 120000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV48);
+       else if (macb_hz < 160000000)
+               config = GEM_BF(CLK, GEM_CLK_DIV64);
+       else
+               config = GEM_BF(CLK, GEM_CLK_DIV96);
+
+       return config;
+}
+
 int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
 {
        struct macb_device *macb;
        struct eth_device *netdev;
-       unsigned long macb_hz;
        u32 ncfgr;
 
        macb = malloc(sizeof(struct macb_device));
@@ -555,7 +654,11 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
        macb->regs = regs;
        macb->phy_addr = phy_addr;
 
-       sprintf(netdev->name, "macb%d", id);
+       if (macb_is_gem(macb))
+               sprintf(netdev->name, "gmac%d", id);
+       else
+               sprintf(netdev->name, "macb%d", id);
+
        netdev->init = macb_init;
        netdev->halt = macb_halt;
        netdev->send = macb_send;
@@ -566,22 +669,20 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
         * Do some basic initialization so that we at least can talk
         * to the PHY
         */
-       macb_hz = get_macb_pclk_rate(id);
-       if (macb_hz < 20000000)
-               ncfgr = MACB_BF(CLK, MACB_CLK_DIV8);
-       else if (macb_hz < 40000000)
-               ncfgr = MACB_BF(CLK, MACB_CLK_DIV16);
-       else if (macb_hz < 80000000)
-               ncfgr = MACB_BF(CLK, MACB_CLK_DIV32);
-       else
-               ncfgr = MACB_BF(CLK, MACB_CLK_DIV64);
+       if (macb_is_gem(macb)) {
+               ncfgr = gem_mdc_clk_div(id, macb);
+               ncfgr |= GEM_BF(DBW, 1);
+       } else {
+               ncfgr = macb_mdc_clk_div(id, macb);
+       }
 
        macb_writel(macb, NCFGR, ncfgr);
 
        eth_register(netdev);
 
-#if defined(CONFIG_CMD_MII)
+#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
        miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write);
+       macb->bus = miiphy_get_dev_by_name(netdev->name);
 #endif
        return 0;
 }
index f92a20c7015d04d496801ce7d9a5195095bbaac2..68eef00c03e67762e1369c3b2e4601b27975d5de 100644 (file)
@@ -26,6 +26,7 @@
 #define MACB_NCR                               0x0000
 #define MACB_NCFGR                             0x0004
 #define MACB_NSR                               0x0008
+#define GEM_UR                                 0x000c
 #define MACB_TSR                               0x0014
 #define MACB_RBQP                              0x0018
 #define MACB_TBQP                              0x001c
@@ -71,6 +72,7 @@
 #define MACB_TPQ                               0x00bc
 #define MACB_USRIO                             0x00c0
 #define MACB_WOL                               0x00c4
+#define MACB_MID                               0x00fc
 
 /* Bitfields in NCR */
 #define MACB_LB_OFFSET                         0
 #define MACB_IRXFCS_OFFSET                     19
 #define MACB_IRXFCS_SIZE                       1
 
+#define GEM_GBE_OFFSET                         10
+#define GEM_GBE_SIZE                           1
+#define GEM_CLK_OFFSET                         18
+#define GEM_CLK_SIZE                           3
+#define GEM_DBW_OFFSET                         21
+#define GEM_DBW_SIZE                           2
+
 /* Bitfields in NSR */
 #define MACB_NSR_LINK_OFFSET                   0
 #define MACB_NSR_LINK_SIZE                     1
 #define MACB_IDLE_OFFSET                       2
 #define MACB_IDLE_SIZE                         1
 
+/* Bitfields in UR */
+#define GEM_RGMII_OFFSET                       0
+#define GEM_RGMII_SIZE                         1
+
 /* Bitfields in TSR */
 #define MACB_UBR_OFFSET                                0
 #define MACB_UBR_SIZE                          1
 #define MACB_WOL_MTI_OFFSET                    19
 #define MACB_WOL_MTI_SIZE                      1
 
+/* Bitfields in MID */
+#define MACB_IDNUM_OFFSET                      16
+#define MACB_IDNUM_SIZE                                16
+
+/* Bitfields in DCFG1 */
 /* Constants for CLK */
 #define MACB_CLK_DIV8                          0
 #define MACB_CLK_DIV16                         1
 #define MACB_CLK_DIV32                         2
 #define MACB_CLK_DIV64                         3
 
+/* GEM specific constants for CLK */
+#define GEM_CLK_DIV8                           0
+#define GEM_CLK_DIV16                          1
+#define GEM_CLK_DIV32                          2
+#define GEM_CLK_DIV48                          3
+#define GEM_CLK_DIV64                          4
+#define GEM_CLK_DIV96                          5
+
 /* Constants for MAN register */
 #define MACB_MAN_SOF                           1
 #define MACB_MAN_WRITE                         1
 /* Bit manipulation macros */
 #define MACB_BIT(name)                                 \
        (1 << MACB_##name##_OFFSET)
-#define MACB_BF(name,value)                            \
+#define MACB_BF(name, value)                           \
        (((value) & ((1 << MACB_##name##_SIZE) - 1))    \
         << MACB_##name##_OFFSET)
-#define MACB_BFEXT(name,value)\
+#define MACB_BFEXT(name, value)\
        (((value) >> MACB_##name##_OFFSET)              \
         & ((1 << MACB_##name##_SIZE) - 1))
-#define MACB_BFINS(name,value,old)                     \
+#define MACB_BFINS(name, value, old)                   \
        (((old) & ~(((1 << MACB_##name##_SIZE) - 1)     \
                    << MACB_##name##_OFFSET))           \
-        | MACB_BF(name,value))
+        | MACB_BF(name, value))
+
+#define GEM_BIT(name)                                  \
+       (1 << GEM_##name##_OFFSET)
+#define GEM_BF(name, value)                            \
+       (((value) & ((1 << GEM_##name##_SIZE) - 1))     \
+        << GEM_##name##_OFFSET)
+#define GEM_BFEXT(name, value)\
+       (((value) >> GEM_##name##_OFFSET)               \
+        & ((1 << GEM_##name##_SIZE) - 1))
+#define GEM_BFINS(name, value, old)                    \
+       (((old) & ~(((1 << GEM_##name##_SIZE) - 1)      \
+                   << GEM_##name##_OFFSET))            \
+        | GEM_BF(name, value))
 
 /* Register access macros */
-#define macb_readl(port,reg)                           \
+#define macb_readl(port, reg)                          \
        readl((port)->regs + MACB_##reg)
-#define macb_writel(port,reg,value)                    \
+#define macb_writel(port, reg, value)                  \
        writel((value), (port)->regs + MACB_##reg)
+#define gem_readl(port, reg)                           \
+       readl((port)->regs + GEM_##reg)
+#define gem_writel(port, reg, value)                   \
+       writel((value), (port)->regs + GEM_##reg)
 
 #endif /* __DRIVERS_MACB_H__ */
index 47bf27c8ba3981d0d060ad090aacad4e41ef85e8..319fe8aba9718710984735f15471983f04a71db3 100644 (file)
@@ -43,6 +43,8 @@
 #include <asm/arch/kirkwood.h>
 #elif defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
+#elif defined(CONFIG_DOVE)
+#include <asm/arch/dove.h>
 #endif
 
 #include "mvgbe.h"
@@ -52,7 +54,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #define MV_PHY_ADR_REQUEST 0xee
 #define MVGBE_SMI_REG (((struct mvgbe_registers *)MVGBE0_BASE)->smi)
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#if defined(CONFIG_PHYLIB) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 /*
  * smi_reg_read - miiphy_read callback function.
  *
@@ -184,6 +186,25 @@ static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
 }
 #endif
 
+#if defined(CONFIG_PHYLIB)
+int mvgbe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
+                  int reg_addr)
+{
+       u16 data;
+       int ret;
+       ret = smi_reg_read(bus->name, phy_addr, reg_addr, &data);
+       if (ret)
+               return ret;
+       return data;
+}
+
+int mvgbe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
+                   int reg_addr, u16 data)
+{
+       return smi_reg_write(bus->name, phy_addr, reg_addr, data);
+}
+#endif
+
 /* Stop and checks all queues */
 static void stop_queue(u32 * qreg)
 {
@@ -467,8 +488,9 @@ static int mvgbe_init(struct eth_device *dev)
        /* Enable port Rx. */
        MVGBE_REG_WR(regs->rqc, (1 << RXUQ));
 
-#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
-        && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
+       !defined(CONFIG_PHYLIB) && \
+       defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
        /* Wait up to 5s for the link status */
        for (i = 0; i < 5; i++) {
                u16 phyadr;
@@ -647,6 +669,45 @@ static int mvgbe_recv(struct eth_device *dev)
        return 0;
 }
 
+#if defined(CONFIG_PHYLIB)
+int mvgbe_phylib_init(struct eth_device *dev, int phyid)
+{
+       struct mii_dev *bus;
+       struct phy_device *phydev;
+       int ret;
+
+       bus = mdio_alloc();
+       if (!bus) {
+               printf("mdio_alloc failed\n");
+               return -ENOMEM;
+       }
+       bus->read = mvgbe_phy_read;
+       bus->write = mvgbe_phy_write;
+       sprintf(bus->name, dev->name);
+
+       ret = mdio_register(bus);
+       if (ret) {
+               printf("mdio_register failed\n");
+               free(bus);
+               return -ENOMEM;
+       }
+
+       /* Set phy address of the port */
+       mvgbe_phy_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
+
+       phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
+       if (!phydev) {
+               printf("phy_connect failed\n");
+               return -ENODEV;
+       }
+
+       phy_config(phydev);
+       phy_startup(phydev);
+
+       return 0;
+}
+#endif
+
 int mvgbe_initialize(bd_t *bis)
 {
        struct mvgbe_device *dmvgbe;
@@ -729,7 +790,9 @@ error1:
 
                eth_register(dev);
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#if defined(CONFIG_PHYLIB)
+               mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
+#elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
                miiphy_register(dev->name, smi_reg_read, smi_reg_write);
                /* Set phy address of the port */
                miiphy_write(dev->name, MV_PHY_ADR_REQUEST,
index d8a5429de4acfbc8a589047cff46b3f88239d579..7f5d98ff5eda777a0074a14b141bf0ad3d23d29e 100644 (file)
 #define EBAR_TARGET_GUNIT                      0x00000007
 
 /* Window attrib */
+#if defined(CONFIG_DOVE)
+#define EBAR_DRAM_CS0                          0x00000000
+#define EBAR_DRAM_CS1                          0x00000000
+#define EBAR_DRAM_CS2                          0x00000000
+#define EBAR_DRAM_CS3                          0x00000000
+#else
 #define EBAR_DRAM_CS0                          0x00000E00
 #define EBAR_DRAM_CS1                          0x00000D00
 #define EBAR_DRAM_CS2                          0x00000B00
 #define EBAR_DRAM_CS3                          0x00000700
+#endif
 
 /* DRAM Target interface */
 #define EBAR_DRAM_NO_CACHE_COHERENCY           0x00000000
index af5f4b848ceefb14d535b5c79084bbfaf49ec89c..695873eaa451fee9975cade6a9abf1a2f28501a0 100644 (file)
@@ -35,6 +35,7 @@ COBJS-$(CONFIG_PHY_ATHEROS) += atheros.o
 COBJS-$(CONFIG_PHY_BROADCOM) += broadcom.o
 COBJS-$(CONFIG_PHY_DAVICOM) += davicom.o
 COBJS-$(CONFIG_PHY_ET1011C) += et1011c.o
+COBJS-$(CONFIG_PHY_ICPLUS) += icplus.o
 COBJS-$(CONFIG_PHY_LXT) += lxt.o
 COBJS-$(CONFIG_PHY_MARVELL) += marvell.o
 COBJS-$(CONFIG_PHY_MICREL) += micrel.o
index 9b3808bfa921cca0514f91ae6b74d2e2de3e9cb7..09d487971f6c9dbb02cdd5d7ddf89a1811ac5d60 100644 (file)
@@ -16,7 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  *
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011, 2013 Freescale Semiconductor, Inc.
  * author Andy Fleming
  *
  */
@@ -30,6 +30,27 @@ static int ar8021_config(struct phy_device *phydev)
        return 0;
 }
 
+static int ar8035_config(struct phy_device *phydev)
+{
+       int regval;
+
+       phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007);
+       phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
+       phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
+       regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
+       phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018));
+
+       phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
+       regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
+       phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100));
+
+       genphy_config_aneg(phydev);
+
+       phy_reset(phydev);
+
+       return 0;
+}
+
 static struct phy_driver AR8021_driver =  {
        .name = "AR8021",
        .uid = 0x4dd040,
@@ -40,9 +61,31 @@ static struct phy_driver AR8021_driver =  {
        .shutdown = genphy_shutdown,
 };
 
+static struct phy_driver AR8031_driver =  {
+       .name = "AR8031",
+       .uid = 0x4dd074,
+       .mask = 0xfffff0,
+       .features = PHY_GBIT_FEATURES,
+       .config = genphy_config,
+       .startup = genphy_startup,
+       .shutdown = genphy_shutdown,
+};
+
+static struct phy_driver AR8035_driver =  {
+       .name = "AR8035",
+       .uid = 0x4dd072,
+       .mask = 0x4fffff,
+       .features = PHY_GBIT_FEATURES,
+       .config = ar8035_config,
+       .startup = genphy_startup,
+       .shutdown = genphy_shutdown,
+};
+
 int phy_atheros_init(void)
 {
        phy_register(&AR8021_driver);
+       phy_register(&AR8031_driver);
+       phy_register(&AR8035_driver);
 
        return 0;
 }
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
new file mode 100644 (file)
index 0000000..dd5c592
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * ICPlus PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ */
+#include <phy.h>
+
+/* IP101A/G - IP1001 */
+#define IP10XX_SPEC_CTRL_STATUS         16      /* Spec. Control Register */
+#define IP1001_SPEC_CTRL_STATUS_2       20      /* IP1001 Spec. Control Reg 2 */
+#define IP1001_PHASE_SEL_MASK           3       /* IP1001 RX/TXPHASE_SEL */
+#define IP1001_APS_ON                   11      /* IP1001 APS Mode  bit */
+#define IP101A_G_APS_ON                 2       /* IP101A/G APS Mode bit */
+#define IP101A_G_IRQ_CONF_STATUS        0x11    /* Conf Info IRQ & Status Reg */
+#define IP101A_G_IRQ_PIN_USED           (1<<15) /* INTR pin used */
+#define IP101A_G_IRQ_DEFAULT            IP101A_G_IRQ_PIN_USED
+
+static int ip1001_config(struct phy_device *phydev)
+{
+       int c;
+
+       /* Enable Auto Power Saving mode */
+       c = phy_read(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2);
+       if (c < 0)
+               return c;
+       c |= IP1001_APS_ON;
+       c = phy_write(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2, c);
+       if (c < 0)
+               return c;
+
+       /* INTR pin used: speed/link/duplex will cause an interrupt */
+       c = phy_write(phydev, MDIO_DEVAD_NONE, IP101A_G_IRQ_CONF_STATUS,
+                     IP101A_G_IRQ_DEFAULT);
+       if (c < 0)
+               return c;
+
+       if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+               /*
+                * Additional delay (2ns) used to adjust RX clock phase
+                * at RGMII interface
+                */
+               c = phy_read(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS);
+               if (c < 0)
+                       return c;
+
+               c |= IP1001_PHASE_SEL_MASK;
+               c = phy_write(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS,
+                             c);
+               if (c < 0)
+                       return c;
+       }
+
+       return 0;
+}
+
+static int ip1001_startup(struct phy_device *phydev)
+{
+       genphy_update_link(phydev);
+       genphy_parse_link(phydev);
+
+       return 0;
+}
+static struct phy_driver IP1001_driver = {
+       .name = "ICPlus IP1001",
+       .uid = 0x02430d90,
+       .mask = 0x0ffffff0,
+       .features = PHY_GBIT_FEATURES,
+       .config = &ip1001_config,
+       .startup = &ip1001_startup,
+       .shutdown = &genphy_shutdown,
+};
+
+int phy_icplus_init(void)
+{
+       phy_register(&IP1001_driver);
+
+       return 0;
+}
index 46801c791903efcd36167d267a70be0b1ec978c8..8397e32e1a0f8dccecfb1c3e1f10d21103e344dc 100644 (file)
 
 #define MIIM_88E1149_PHY_PAGE  29
 
+/* 88E1310 PHY defines */
+#define MIIM_88E1310_PHY_LED_CTRL      16
+#define MIIM_88E1310_PHY_IRQ_EN                18
+#define MIIM_88E1310_PHY_RGMII_CTRL    21
+#define MIIM_88E1310_PHY_PAGE          22
+
 /* Marvell 88E1011S */
 static int m88e1011s_config(struct phy_device *phydev)
 {
@@ -394,6 +400,37 @@ static int m88e1149_config(struct phy_device *phydev)
        return 0;
 }
 
+/* Marvell 88E1310 */
+static int m88e1310_config(struct phy_device *phydev)
+{
+       u16 reg;
+
+       /* LED link and activity */
+       phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003);
+       reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL);
+       reg = (reg & ~0xf) | 0x1;
+       phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg);
+
+       /* Set LED2/INT to INT mode, low active */
+       phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003);
+       reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN);
+       reg = (reg & 0x77ff) | 0x0880;
+       phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg);
+
+       /* Set RGMII delay */
+       phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002);
+       reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL);
+       reg |= 0x0030;
+       phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg);
+
+       /* Ensure to return to page 0 */
+       phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000);
+
+       genphy_config_aneg(phydev);
+       phy_reset(phydev);
+
+       return 0;
+}
 
 static struct phy_driver M88E1011S_driver = {
        .name = "Marvell 88E1011S",
@@ -475,8 +512,19 @@ static struct phy_driver M88E1518_driver = {
        .shutdown = &genphy_shutdown,
 };
 
+static struct phy_driver M88E1310_driver = {
+       .name = "Marvell 88E1310",
+       .uid = 0x01410e90,
+       .mask = 0xffffff0,
+       .features = PHY_GBIT_FEATURES,
+       .config = &m88e1310_config,
+       .startup = &m88e1011s_startup,
+       .shutdown = &genphy_shutdown,
+};
+
 int phy_marvell_init(void)
 {
+       phy_register(&M88E1310_driver);
        phy_register(&M88E1149S_driver);
        phy_register(&M88E1145_driver);
        phy_register(&M88E1121R_driver);
index 30f3264897479c35f49cc53c3600b7f5ca46665b..aa9cbcfffc0465075ed7574e7ac76ffea908db48 100644 (file)
@@ -18,6 +18,7 @@
  *
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  * author Andy Fleming
+ * (C) 2012 NetModule AG, David Andrey, added KSZ9031
  *
  */
 #include <config.h>
@@ -52,16 +53,46 @@ static struct phy_driver KS8721_driver = {
 };
 #endif
 
+
+/**
+ * KSZ9021 - KSZ9031 common
+ */
+
+#define MII_KSZ90xx_PHY_CTL            0x1f
+#define MIIM_KSZ90xx_PHYCTL_1000       (1 << 6)
+#define MIIM_KSZ90xx_PHYCTL_100                (1 << 5)
+#define MIIM_KSZ90xx_PHYCTL_10         (1 << 4)
+#define MIIM_KSZ90xx_PHYCTL_DUPLEX     (1 << 3)
+
+static int ksz90xx_startup(struct phy_device *phydev)
+{
+       unsigned phy_ctl;
+       genphy_update_link(phydev);
+       phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
+
+       if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
+               phydev->duplex = DUPLEX_FULL;
+       else
+               phydev->duplex = DUPLEX_HALF;
+
+       if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
+               phydev->speed = SPEED_1000;
+       else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
+               phydev->speed = SPEED_100;
+       else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
+               phydev->speed = SPEED_10;
+       return 0;
+}
 #ifdef CONFIG_PHY_MICREL_KSZ9021
-/* ksz9021 PHY Registers */
+
+/*
+ * KSZ9021
+ */
+
+/* PHY Registers */
 #define MII_KSZ9021_EXTENDED_CTRL      0x0b
 #define MII_KSZ9021_EXTENDED_DATAW     0x0c
 #define MII_KSZ9021_EXTENDED_DATAR     0x0d
-#define MII_KSZ9021_PHY_CTL            0x1f
-#define MIIM_KSZ9021_PHYCTL_1000       (1 << 6)
-#define MIIM_KSZ9021_PHYCTL_100                (1 << 5)
-#define MIIM_KSZ9021_PHYCTL_10         (1 << 4)
-#define MIIM_KSZ9021_PHYCTL_DUPLEX     (1 << 3)
 
 #define CTRL1000_PREFER_MASTER         (1 << 10)
 #define CTRL1000_CONFIG_MASTER         (1 << 11)
@@ -106,37 +137,64 @@ static int ksz9021_config(struct phy_device *phydev)
        return 0;
 }
 
-static int ksz9021_startup(struct phy_device *phydev)
-{
-       unsigned phy_ctl;
-       genphy_update_link(phydev);
-       phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_PHY_CTL);
-
-       if (phy_ctl & MIIM_KSZ9021_PHYCTL_DUPLEX)
-               phydev->duplex = DUPLEX_FULL;
-       else
-               phydev->duplex = DUPLEX_HALF;
-
-       if (phy_ctl & MIIM_KSZ9021_PHYCTL_1000)
-               phydev->speed = SPEED_1000;
-       else if (phy_ctl & MIIM_KSZ9021_PHYCTL_100)
-               phydev->speed = SPEED_100;
-       else if (phy_ctl & MIIM_KSZ9021_PHYCTL_10)
-               phydev->speed = SPEED_10;
-       return 0;
-}
-
 static struct phy_driver ksz9021_driver = {
        .name = "Micrel ksz9021",
        .uid  = 0x221610,
        .mask = 0xfffff0,
        .features = PHY_GBIT_FEATURES,
        .config = &ksz9021_config,
-       .startup = &ksz9021_startup,
+       .startup = &ksz90xx_startup,
        .shutdown = &genphy_shutdown,
 };
 #endif
 
+/**
+ * KSZ9031
+ */
+/* PHY Registers */
+#define MII_KSZ9031_MMD_ACCES_CTRL     0x0d
+#define MII_KSZ9031_MMD_REG_DATA       0x0e
+
+/* Accessors to extended registers*/
+int ksz9031_phy_extended_write(struct phy_device *phydev,
+                              int devaddr, int regnum, u16 mode, u16 val)
+{
+       /*select register addr for mmd*/
+       phy_write(phydev, MDIO_DEVAD_NONE,
+                 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
+       /*select register for mmd*/
+       phy_write(phydev, MDIO_DEVAD_NONE,
+                 MII_KSZ9031_MMD_REG_DATA, regnum);
+       /*setup mode*/
+       phy_write(phydev, MDIO_DEVAD_NONE,
+                 MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
+       /*write the value*/
+       return  phy_write(phydev, MDIO_DEVAD_NONE,
+               MII_KSZ9031_MMD_REG_DATA, val);
+}
+
+int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
+                             int regnum, u16 mode)
+{
+       phy_write(phydev, MDIO_DEVAD_NONE,
+                 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
+       phy_write(phydev, MDIO_DEVAD_NONE,
+                 MII_KSZ9031_MMD_REG_DATA, regnum);
+       phy_write(phydev, MDIO_DEVAD_NONE,
+                 MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
+       return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
+}
+
+static struct phy_driver ksz9031_driver = {
+       .name = "Micrel ksz9031",
+       .uid  = 0x221620,
+       .mask = 0xfffffe,
+       .features = PHY_GBIT_FEATURES,
+       .config   = &genphy_config,
+       .startup  = &ksz90xx_startup,
+       .shutdown = &genphy_shutdown,
+};
+
 int phy_micrel_init(void)
 {
        phy_register(&KSZ804_driver);
@@ -145,5 +203,6 @@ int phy_micrel_init(void)
 #else
        phy_register(&KS8721_driver);
 #endif
+       phy_register(&ksz9031_driver);
        return 0;
 }
index ea60ac1b0e6513b930d2c3191cec090e68b5b69a..6dc7ed50598ea699b874460a9524bd1e6c7ba46f 100644 (file)
  */
 #include <phy.h>
 
+/* NatSemi DP83630 */
+
+#define DP83630_PHY_PAGESEL_REG                0x13
+#define DP83630_PHY_PTP_COC_REG                0x14
+#define DP83630_PHY_PTP_CLKOUT_EN      (1<<15)
+#define DP83630_PHY_RBR_REG            0x17
+
+static int dp83630_config(struct phy_device *phydev)
+{
+       int ptp_coc_reg;
+
+       phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+       phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PAGESEL_REG, 0x6);
+       ptp_coc_reg = phy_read(phydev, MDIO_DEVAD_NONE,
+                              DP83630_PHY_PTP_COC_REG);
+       ptp_coc_reg &= ~DP83630_PHY_PTP_CLKOUT_EN;
+       phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PTP_COC_REG,
+                 ptp_coc_reg);
+       phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PAGESEL_REG, 0);
+
+       genphy_config_aneg(phydev);
+
+       return 0;
+}
+
+static struct phy_driver DP83630_driver = {
+       .name = "NatSemi DP83630",
+       .uid = 0x20005ce1,
+       .mask = 0xfffffff0,
+       .features = PHY_BASIC_FEATURES,
+       .config = &dp83630_config,
+       .startup = &genphy_startup,
+       .shutdown = &genphy_shutdown,
+};
+
+
 /* DP83865 Link and Auto-Neg Status Register */
 #define MIIM_DP83865_LANR      0x11
 #define MIIM_DP83865_SPD_MASK  0x0018
@@ -90,6 +126,7 @@ static struct phy_driver DP83865_driver = {
 
 int phy_natsemi_init(void)
 {
+       phy_register(&DP83630_driver);
        phy_register(&DP83865_driver);
 
        return 0;
index f8c54814777882e83d17e8ad22b69abcd047f42f..7c0eaec5137f8def0cfbf92b67793f74f0dc7e60 100644 (file)
@@ -75,6 +75,10 @@ static int genphy_config_advert(struct phy_device *phydev)
                adv |= ADVERTISE_PAUSE_CAP;
        if (advertise & ADVERTISED_Asym_Pause)
                adv |= ADVERTISE_PAUSE_ASYM;
+       if (advertise & ADVERTISED_1000baseX_Half)
+               adv |= ADVERTISE_1000XHALF;
+       if (advertise & ADVERTISED_1000baseX_Full)
+               adv |= ADVERTISE_1000XFULL;
 
        if (adv != oldadv) {
                err = phy_write(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE, adv);
@@ -280,7 +284,7 @@ int genphy_update_link(struct phy_device *phydev)
  *
  * Stolen from Linux's mii.c and phy_device.c
  */
-static int genphy_parse_link(struct phy_device *phydev)
+int genphy_parse_link(struct phy_device *phydev)
 {
        int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
 
@@ -288,6 +292,7 @@ static int genphy_parse_link(struct phy_device *phydev)
        if (mii_reg & BMSR_ANEGCAPABLE) {
                u32 lpa = 0;
                u32 gblpa = 0;
+               u32 estatus = 0;
 
                /* Check for gigabit capability */
                if (mii_reg & BMSR_ERCAP) {
@@ -327,6 +332,18 @@ static int genphy_parse_link(struct phy_device *phydev)
 
                } else if (lpa & LPA_10FULL)
                        phydev->duplex = DUPLEX_FULL;
+
+               if (mii_reg & BMSR_ESTATEN)
+                       estatus = phy_read(phydev, MDIO_DEVAD_NONE,
+                                          MII_ESTATUS);
+
+               if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_XHALF |
+                               ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) {
+                       phydev->speed = SPEED_1000;
+                       if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_TFULL))
+                               phydev->duplex = DUPLEX_FULL;
+               }
+
        } else {
                u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
 
@@ -384,6 +401,10 @@ int genphy_config(struct phy_device *phydev)
                        features |= SUPPORTED_1000baseT_Full;
                if (val & ESTATUS_1000_THALF)
                        features |= SUPPORTED_1000baseT_Half;
+               if (val & ESTATUS_1000_XFULL)
+                       features |= SUPPORTED_1000baseX_Full;
+               if (val & ESTATUS_1000_XHALF)
+                       features |= SUPPORTED_1000baseX_Full;
        }
 
        phydev->supported = features;
@@ -433,6 +454,9 @@ int phy_init(void)
 #ifdef CONFIG_PHY_ET1011C
        phy_et1011c_init();
 #endif
+#ifdef CONFIG_PHY_ICPLUS
+       phy_icplus_init();
+#endif
 #ifdef CONFIG_PHY_LXT
        phy_lxt_init();
 #endif
diff --git a/drivers/net/sunxi_wemac.c b/drivers/net/sunxi_wemac.c
new file mode 100644 (file)
index 0000000..1db3529
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * sunxi_wemac.c -- Allwinner A10 ethernet driver
+ *
+ * (C) Copyright 2012, Stefan Roese <sr@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+
+/* EMAC register  */
+struct wemac_regs {
+       u32 ctl;        /* 0x00 */
+       u32 tx_mode;    /* 0x04 */
+       u32 tx_flow;    /* 0x08 */
+       u32 tx_ctl0;    /* 0x0c */
+       u32 tx_ctl1;    /* 0x10 */
+       u32 tx_ins;     /* 0x14 */
+       u32 tx_pl0;     /* 0x18 */
+       u32 tx_pl1;     /* 0x1c */
+       u32 tx_sta;     /* 0x20 */
+       u32 tx_io_data; /* 0x24 */
+       u32 tx_io_data1; /* 0x28 */
+       u32 tx_tsvl0;   /* 0x2c */
+       u32 tx_tsvh0;   /* 0x30 */
+       u32 tx_tsvl1;   /* 0x34 */
+       u32 tx_tsvh1;   /* 0x38 */
+       u32 rx_ctl;     /* 0x3c */
+       u32 rx_hash0;   /* 0x40 */
+       u32 rx_hash1;   /* 0x44 */
+       u32 rx_sta;     /* 0x48 */
+       u32 rx_io_data; /* 0x4c */
+       u32 rx_fbc;     /* 0x50 */
+       u32 int_ctl;    /* 0x54 */
+       u32 int_sta;    /* 0x58 */
+       u32 mac_ctl0;   /* 0x5c */
+       u32 mac_ctl1;   /* 0x60 */
+       u32 mac_ipgt;   /* 0x64 */
+       u32 mac_ipgr;   /* 0x68 */
+       u32 mac_clrt;   /* 0x6c */
+       u32 mac_maxf;   /* 0x70 */
+       u32 mac_supp;   /* 0x74 */
+       u32 mac_test;   /* 0x78 */
+       u32 mac_mcfg;   /* 0x7c */
+       u32 mac_mcmd;   /* 0x80 */
+       u32 mac_madr;   /* 0x84 */
+       u32 mac_mwtd;   /* 0x88 */
+       u32 mac_mrdd;   /* 0x8c */
+       u32 mac_mind;   /* 0x90 */
+       u32 mac_ssrr;   /* 0x94 */
+       u32 mac_a0;     /* 0x98 */
+       u32 mac_a1;     /* 0x9c */
+};
+
+/* SRAMC register  */
+struct sunxi_sramc_regs {
+       u32 ctrl0;
+       u32 ctrl1;
+};
+
+/* 0: Disable       1: Aborted frame enable(default) */
+#define EMAC_TX_AB_M           (0x1 << 0)
+/* 0: CPU           1: DMA(default) */
+#define EMAC_TX_TM             (0x1 << 1)
+
+#define EMAC_TX_SETUP          (0)
+
+/* 0: DRQ asserted  1: DRQ automatically(default) */
+#define EMAC_RX_DRQ_MODE       (0x1 << 1)
+/* 0: CPU           1: DMA(default) */
+#define EMAC_RX_TM             (0x1 << 2)
+/* 0: Normal(default)        1: Pass all Frames */
+#define EMAC_RX_PA             (0x1 << 4)
+/* 0: Normal(default)        1: Pass Control Frames */
+#define EMAC_RX_PCF            (0x1 << 5)
+/* 0: Normal(default)        1: Pass Frames with CRC Error */
+#define EMAC_RX_PCRCE          (0x1 << 6)
+/* 0: Normal(default)        1: Pass Frames with Length Error */
+#define EMAC_RX_PLE            (0x1 << 7)
+/* 0: Normal                 1: Pass Frames length out of range(default) */
+#define EMAC_RX_POR            (0x1 << 8)
+/* 0: Not accept             1: Accept unicast Packets(default) */
+#define EMAC_RX_UCAD           (0x1 << 16)
+/* 0: Normal(default)        1: DA Filtering */
+#define EMAC_RX_DAF            (0x1 << 17)
+/* 0: Not accept             1: Accept multicast Packets(default) */
+#define EMAC_RX_MCO            (0x1 << 20)
+/* 0: Disable(default)       1: Enable Hash filter */
+#define EMAC_RX_MHF            (0x1 << 21)
+/* 0: Not accept             1: Accept Broadcast Packets(default) */
+#define EMAC_RX_BCO            (0x1 << 22)
+/* 0: Disable(default)       1: Enable SA Filtering */
+#define EMAC_RX_SAF            (0x1 << 24)
+/* 0: Normal(default)        1: Inverse Filtering */
+#define EMAC_RX_SAIF           (0x1 << 25)
+
+#define EMAC_RX_SETUP          (EMAC_RX_POR | EMAC_RX_UCAD | EMAC_RX_DAF | \
+                                EMAC_RX_MCO | EMAC_RX_BCO)
+
+/* 0: Disable                1: Enable Receive Flow Control(default) */
+#define EMAC_MAC_CTL0_RFC      (0x1 << 2)
+/* 0: Disable                1: Enable Transmit Flow Control(default) */
+#define EMAC_MAC_CTL0_TFC      (0x1 << 3)
+
+#define EMAC_MAC_CTL0_SETUP    (EMAC_MAC_CTL0_RFC | EMAC_MAC_CTL0_TFC)
+
+/* 0: Disable                1: Enable MAC Frame Length Checking(default) */
+#define EMAC_MAC_CTL1_FLC      (0x1 << 1)
+/* 0: Disable(default)       1: Enable Huge Frame */
+#define EMAC_MAC_CTL1_HF       (0x1 << 2)
+/* 0: Disable(default)       1: Enable MAC Delayed CRC */
+#define EMAC_MAC_CTL1_DCRC     (0x1 << 3)
+/* 0: Disable                1: Enable MAC CRC(default) */
+#define EMAC_MAC_CTL1_CRC      (0x1 << 4)
+/* 0: Disable                1: Enable MAC PAD Short frames(default) */
+#define EMAC_MAC_CTL1_PC       (0x1 << 5)
+/* 0: Disable(default)       1: Enable MAC PAD Short frames and append CRC */
+#define EMAC_MAC_CTL1_VC       (0x1 << 6)
+/* 0: Disable(default)       1: Enable MAC auto detect Short frames */
+#define EMAC_MAC_CTL1_ADP      (0x1 << 7)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_PRE      (0x1 << 8)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_LPE      (0x1 << 9)
+/* 0: Disable(default)       1: Enable no back off */
+#define EMAC_MAC_CTL1_NB       (0x1 << 12)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_BNB      (0x1 << 13)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_ED       (0x1 << 14)
+
+#define EMAC_MAC_CTL1_SETUP    (EMAC_MAC_CTL1_FLC | EMAC_MAC_CTL1_CRC | \
+                                EMAC_MAC_CTL1_PC)
+
+#define EMAC_MAC_IPGT          0x15
+
+#define EMAC_MAC_NBTB_IPG1     0xC
+#define EMAC_MAC_NBTB_IPG2     0x12
+
+#define EMAC_MAC_CW            0x37
+#define EMAC_MAC_RM            0xF
+
+#define EMAC_MAC_MFL           0x0600
+
+/* Receive status */
+#define EMAC_CRCERR            (1 << 4)
+#define EMAC_LENERR            (3 << 5)
+
+#define DMA_CPU_TRRESHOLD      2000
+
+struct wemac_eth_dev {
+       u32 speed;
+       u32 duplex;
+       u32 phy_configured;
+       int link_printed;
+};
+
+struct wemac_rxhdr {
+       s16 rx_len;
+       u16 rx_status;
+};
+
+static void wemac_inblk_32bit(void *reg, void *data, int count)
+{
+       int cnt = (count + 3) >> 2;
+
+       if (cnt) {
+               u32 *buf = data;
+
+               do {
+                       u32 x = readl(reg);
+                       *buf++ = x;
+               } while (--cnt);
+       }
+}
+
+static void wemac_outblk_32bit(void *reg, void *data, int count)
+{
+       int cnt = (count + 3) >> 2;
+
+       if (cnt) {
+               const u32 *buf = data;
+
+               do {
+                       writel(*buf++, reg);
+               } while (--cnt);
+       }
+}
+
+/*
+ * Read a word from phyxcer
+ */
+static int wemac_phy_read(const char *devname, unsigned char addr,
+                         unsigned char reg, unsigned short *value)
+{
+       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+       /* issue the phy address and reg */
+       writel(addr << 8 | reg, &regs->mac_madr);
+
+       /* pull up the phy io line */
+       writel(0x1, &regs->mac_mcmd);
+
+       /* Wait read complete */
+       mdelay(1);
+
+       /* push down the phy io line */
+       writel(0x0, &regs->mac_mcmd);
+
+       /* and write data */
+       *value = readl(&regs->mac_mrdd);
+
+       return 0;
+}
+
+/*
+ * Write a word to phyxcer
+ */
+static int wemac_phy_write(const char *devname, unsigned char addr,
+                          unsigned char reg, unsigned short value)
+{
+       struct eth_device *dev = eth_get_dev_by_name(devname);
+       struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+       /* issue the phy address and reg */
+       writel(addr << 8 | reg, &regs->mac_madr);
+
+       /* pull up the phy io line */
+       writel(0x1, &regs->mac_mcmd);
+
+       /* Wait write complete */
+       mdelay(1);
+
+       /* push down the phy io line */
+       writel(0x0, &regs->mac_mcmd);
+
+       /* and write data */
+       writel(value, &regs->mac_mwtd);
+
+       return 0;
+}
+
+static void emac_setup(struct eth_device *dev)
+{
+       struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+       u32 reg_val;
+       u16 phy_val;
+       u32 duplex_flag;
+
+       /* Set up TX */
+       writel(EMAC_TX_SETUP, &regs->tx_mode);
+
+       /* Set up RX */
+       writel(EMAC_RX_SETUP, &regs->rx_ctl);
+
+       /* Set MAC */
+       /* Set MAC CTL0 */
+       writel(EMAC_MAC_CTL0_SETUP, &regs->mac_ctl0);
+
+       /* Set MAC CTL1 */
+       wemac_phy_read(dev->name, 1, 0, &phy_val);
+       debug("PHY SETUP, reg 0 value: %x\n", phy_val);
+       duplex_flag = !!(phy_val & (1 << 8));
+
+       reg_val = 0;
+       if (duplex_flag)
+               reg_val = (0x1 << 0);
+       writel(EMAC_MAC_CTL1_SETUP | reg_val, &regs->mac_ctl1);
+
+       /* Set up IPGT */
+       writel(EMAC_MAC_IPGT, &regs->mac_ipgt);
+
+       /* Set up IPGR */
+       writel(EMAC_MAC_NBTB_IPG2 | (EMAC_MAC_NBTB_IPG1 << 8), &regs->mac_ipgr);
+
+       /* Set up Collison window */
+       writel(EMAC_MAC_RM | (EMAC_MAC_CW << 8), &regs->mac_clrt);
+
+       /* Set up Max Frame Length */
+       writel(EMAC_MAC_MFL, &regs->mac_maxf);
+}
+
+static void wemac_reset(struct eth_device *dev)
+{
+       struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+       debug("resetting device\n");
+
+       /* RESET device */
+       writel(0, &regs->ctl);
+       udelay(200);
+
+       writel(1, &regs->ctl);
+       udelay(200);
+}
+
+static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
+{
+       struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+       struct wemac_eth_dev *priv = dev->priv;
+       u16 phy_reg;
+
+       /* Init EMAC */
+
+       /* Flush RX FIFO */
+       setbits_le32(&regs->rx_ctl, 0x8);
+       udelay(1);
+
+       /* Init MAC */
+
+       /* Soft reset MAC */
+       clrbits_le32(&regs->mac_ctl0, 1 << 15);
+
+       /* Set MII clock */
+       clrsetbits_le32(&regs->mac_mcfg, 0xf << 2, 0xd << 2);
+
+       /* Clear RX counter */
+       writel(0x0, &regs->rx_fbc);
+       udelay(1);
+
+       /* Set up EMAC */
+       emac_setup(dev);
+
+       writel(dev->enetaddr[0] << 16 | dev->enetaddr[1] << 8 |
+              dev->enetaddr[2], &regs->mac_a1);
+       writel(dev->enetaddr[3] << 16 | dev->enetaddr[4] << 8 |
+              dev->enetaddr[5], &regs->mac_a0);
+
+       mdelay(1);
+
+       wemac_reset(dev);
+
+       /* PHY POWER UP */
+       wemac_phy_read(dev->name, 1, 0, &phy_reg);
+       wemac_phy_write(dev->name, 1, 0, phy_reg & (~(1 << 11)));
+       mdelay(1);
+
+       wemac_phy_read(dev->name, 1, 0, &phy_reg);
+
+       priv->speed = miiphy_speed(dev->name, 0);
+       priv->duplex = miiphy_duplex(dev->name, 0);
+
+       /* Print link status only once */
+       if (!priv->link_printed) {
+               printf("ENET Speed is %d Mbps - %s duplex connection\n",
+                      priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
+               priv->link_printed = 1;
+       }
+
+       /* Set EMAC SPEED depend on PHY */
+       clrsetbits_le32(&regs->mac_supp, 1 << 8,
+                       ((phy_reg & (1 << 13)) >> 13) << 8);
+
+       /* Set duplex depend on phy */
+       clrsetbits_le32(&regs->mac_ctl1, 1 << 0,
+                       ((phy_reg & (1 << 8)) >> 8) << 0);
+
+       /* Enable RX/TX */
+       setbits_le32(&regs->ctl, 0x7);
+
+       return 0;
+}
+
+static void sunxi_wemac_eth_halt(struct eth_device *dev)
+{
+       /* Nothing to do here */
+}
+
+static int sunxi_wemac_eth_recv(struct eth_device *dev)
+{
+       struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+       struct wemac_rxhdr rxhdr;
+       u32 rxcount;
+       u32 reg_val;
+       int rx_len;
+       int rx_status;
+       int good_packet;
+
+       /* Check packet ready or not */
+
+       /*
+        * Race warning: The first packet might arrive with
+        * the interrupts disabled, but the second will fix
+        */
+       rxcount = readl(&regs->rx_fbc);
+       if (!rxcount) {
+               /* Had one stuck? */
+               rxcount = readl(&regs->rx_fbc);
+               if (!rxcount)
+                       return 0;
+       }
+
+       reg_val = readl(&regs->rx_io_data);
+       if (reg_val != 0x0143414d) {
+               /* Disable RX */
+               clrbits_le32(&regs->ctl, 1 << 2);
+
+               /* Flush RX FIFO */
+               setbits_le32(&regs->rx_ctl, 1 << 3);
+               while (readl(&regs->rx_ctl) & (1 << 3))
+                       ;
+
+               /* Enable RX */
+               setbits_le32(&regs->ctl, 1 << 2);
+
+               return 0;
+       }
+
+       /*
+        * A packet ready now
+        * Get status/length
+        */
+       good_packet = 1;
+
+       wemac_inblk_32bit(&regs->rx_io_data, &rxhdr, sizeof(rxhdr));
+
+       rx_len = rxhdr.rx_len;
+       rx_status = rxhdr.rx_status;
+
+       /* Packet Status check */
+       if (rx_len < 0x40) {
+               good_packet = 0;
+               debug("RX: Bad Packet (runt)\n");
+       }
+
+       /* rx_status is identical to RSR register. */
+       if (0 & rx_status & (EMAC_CRCERR | EMAC_LENERR)) {
+               good_packet = 0;
+               if (rx_status & EMAC_CRCERR)
+                       printf("crc error\n");
+               if (rx_status & EMAC_LENERR)
+                       printf("length error\n");
+       }
+
+       /* Move data from WEMAC */
+       if (good_packet) {
+               if (rx_len > DMA_CPU_TRRESHOLD) {
+                       printf("Received packet is too big (len=%d)\n", rx_len);
+               } else {
+                       wemac_inblk_32bit((void *)&regs->rx_io_data,
+                                         NetRxPackets[0], rx_len);
+
+                       /* Pass to upper layer */
+                       NetReceive(NetRxPackets[0], rx_len);
+                       return rx_len;
+               }
+       }
+
+       return 0;
+}
+
+static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len)
+{
+       struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+       /* Select channel 0 */
+       writel(0, &regs->tx_ins);
+
+       /* Write packet */
+       wemac_outblk_32bit((void *)&regs->tx_io_data, packet, len);
+
+       /* Set TX len */
+       writel(len, &regs->tx_pl0);
+
+       /* Start translate from fifo to phy */
+       setbits_le32(&regs->tx_ctl0, 1);
+
+       return 0;
+}
+
+int sunxi_wemac_initialize(void)
+{
+       struct sunxi_ccm_reg *const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       struct sunxi_sramc_regs *sram =
+               (struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE;
+       struct eth_device *dev;
+       struct wemac_eth_dev *priv;
+       int pin;
+
+       dev = malloc(sizeof(*dev));
+       if (dev == NULL)
+               return -ENOMEM;
+
+       priv = (struct wemac_eth_dev *)malloc(sizeof(struct wemac_eth_dev));
+       if (!priv) {
+               free(dev);
+               return -ENOMEM;
+       }
+
+       memset(dev, 0, sizeof(*dev));
+       memset(priv, 0, sizeof(struct wemac_eth_dev));
+
+       /* Map SRAM to EMAC */
+       setbits_le32(&sram->ctrl1, 0x5 << 2);
+
+       /* Configure pin mux settings for MII Ethernet */
+       for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++)
+               sunxi_gpio_set_cfgpin(pin, 2);
+
+       /* Set up clock gating */
+       setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_EMAC);
+
+       dev->iobase = SUNXI_EMAC_BASE;
+       dev->priv = priv;
+       dev->init = sunxi_wemac_eth_init;
+       dev->halt = sunxi_wemac_eth_halt;
+       dev->send = sunxi_wemac_eth_send;
+       dev->recv = sunxi_wemac_eth_recv;
+       strcpy(dev->name, "wemac");
+
+       eth_register(dev);
+
+       miiphy_register(dev->name, wemac_phy_read, wemac_phy_write);
+
+       return 0;
+}
index 77ac1f7c7b9a1a8452c064dc6abfd39fb3785ec8..621c899120af29bb4a77adbbc75423075d70f9b9 100644 (file)
@@ -211,7 +211,7 @@ static int fsl_pci_setup_inbound_windows(struct pci_controller *hose,
        return 1;
 }
 
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
 static void fsl_pcie_boot_master(pit_t *pi)
 {
        /* configure inbound window for slave's u-boot image */
@@ -388,7 +388,7 @@ void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)
        /* see if we are a PCIe or PCI controller */
        pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
 
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
        /* boot from PCIE --master */
        char *s = getenv("bootmaster");
        char pcie[6];
@@ -624,7 +624,7 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info,
        if (fsl_is_pci_agent(hose)) {
                fsl_pci_config_unlock(hose);
                hose->last_busno = hose->first_busno;
-#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
        } else {
                /* boot from PCIE --master releases slave's core 0 */
                char *s = getenv("bootmaster");
index d4b3e65a3eac0bfac781572d15e8fe6115c02cce..9a093a5bddd63d6bf15917377896edd1afe32144 100644 (file)
 /* Tmeperature threshold values for various thermal events */
 struct temperature_params {
        /* minimum value in temperature code range */
-       unsigned int min_val;
+       unsigned min_val;
        /* maximum value in temperature code range */
-       unsigned int max_val;
+       unsigned max_val;
        /* temperature threshold to start warning */
-       unsigned int start_warning;
+       unsigned start_warning;
        /* temperature threshold CPU tripping */
-       unsigned int start_tripping;
+       unsigned start_tripping;
        /* temperature threshold for HW tripping */
-       unsigned int hardware_tripping;
+       unsigned hardware_tripping;
 };
 
 /* Pre-defined values and thresholds for calibration of current temperature */
@@ -66,25 +66,27 @@ struct tmu_data {
        /* pre-defined temperature thresholds */
        struct temperature_params ts;
        /* pre-defined efuse range minimum value */
-       unsigned int efuse_min_value;
+       unsigned efuse_min_value;
        /* pre-defined efuse value for temperature calibration */
-       unsigned int efuse_value;
+       unsigned efuse_value;
        /* pre-defined efuse range maximum value */
-       unsigned int efuse_max_value;
+       unsigned efuse_max_value;
        /* current temperature sensing slope */
-       unsigned int slope;
+       unsigned slope;
 };
 
 /* TMU device specific details and status */
 struct tmu_info {
        /* base Address for the TMU */
-       unsigned tmu_base;
+       struct exynos5_tmu_reg *tmu_base;
+       /* mux Address for the TMU */
+       int tmu_mux;
        /* pre-defined values for calibration and thresholds */
        struct tmu_data data;
        /* value required for triminfo_25 calibration */
-       unsigned int te1;
+       unsigned te1;
        /* value required for triminfo_85 calibration */
-       unsigned int te2;
+       unsigned te2;
        /* Value for measured data calibration */
        int dc_value;
        /* enum value indicating status of the TMU */
@@ -103,17 +105,24 @@ static struct tmu_info gbl_info;
  */
 static int get_cur_temp(struct tmu_info *info)
 {
-       int cur_temp;
-       struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base;
+       struct exynos5_tmu_reg *reg = info->tmu_base;
+       ulong start;
+       int cur_temp = 0;
 
        /*
         * Temperature code range between min 25 and max 125.
         * May run more than once for first call as initial sensing
         * has not yet happened.
         */
-       do {
-               cur_temp = readl(&reg->current_temp) & 0xff;
-       } while (cur_temp == 0 && info->tmu_state == TMU_STATUS_NORMAL);
+       if (info->tmu_state == TMU_STATUS_NORMAL) {
+               start = get_timer(0);
+               do {
+                       cur_temp = readl(&reg->current_temp) & 0xff;
+               } while ((cur_temp == 0) || (get_timer(start) > 100));
+       }
+
+       if (cur_temp == 0)
+               return cur_temp;
 
        /* Calibrate current temperature */
        cur_temp = cur_temp - info->te1 + info->dc_value;
@@ -137,23 +146,29 @@ enum tmu_status_t tmu_monitor(int *temp)
 
        /* Read current temperature of the SOC */
        cur_temp = get_cur_temp(&gbl_info);
+
+       if (!cur_temp)
+               goto out;
+
        *temp = cur_temp;
 
        /* Temperature code lies between min 25 and max 125 */
-       if (cur_temp >= data->ts.start_tripping &&
-                       cur_temp <= data->ts.max_val) {
+       if ((cur_temp >= data->ts.start_tripping) &&
+           (cur_temp <= data->ts.max_val))
                return TMU_STATUS_TRIPPED;
-       } else if (cur_temp >= data->ts.start_warning) {
+
+       if (cur_temp >= data->ts.start_warning)
                return TMU_STATUS_WARNING;
-       } else if (cur_temp < data->ts.start_warning &&
-                       cur_temp >= data->ts.min_val) {
+
+       if ((cur_temp < data->ts.start_warning) &&
+           (cur_temp >= data->ts.min_val))
                return TMU_STATUS_NORMAL;
-       } else {
-               /* Temperature code does not lie between min 25 and max 125 */
-               gbl_info.tmu_state = TMU_STATUS_INIT;
-               debug("EXYNOS_TMU: Thermal reading failed\n");
-               return TMU_STATUS_INIT;
-       }
+
+ out:
+       /* Temperature code does not lie between min 25 and max 125 */
+       gbl_info.tmu_state = TMU_STATUS_INIT;
+       debug("EXYNOS_TMU: Thermal reading failed\n");
+       return TMU_STATUS_INIT;
 }
 
 /*
@@ -166,6 +181,7 @@ enum tmu_status_t tmu_monitor(int *temp)
 static int get_tmu_fdt_values(struct tmu_info *info, const void *blob)
 {
 #ifdef CONFIG_OF_CONTROL
+       fdt_addr_t addr;
        int node;
        int error = 0;
 
@@ -183,46 +199,58 @@ static int get_tmu_fdt_values(struct tmu_info *info, const void *blob)
         * miscalculation of register values in tmu_setup_parameters
         * may result in misleading current temperature.
         */
-       info->tmu_base = fdtdec_get_addr(blob, node, "reg");
-       if (info->tmu_base == FDT_ADDR_T_NONE) {
+       addr = fdtdec_get_addr(blob, node, "reg");
+       if (addr == FDT_ADDR_T_NONE) {
                debug("%s: Missing tmu-base\n", __func__);
                return -1;
        }
+       info->tmu_base = (struct exynos5_tmu_reg *)addr;
+
+       /* Optional field. */
+       info->tmu_mux = fdtdec_get_int(blob,
+                               node, "samsung,mux", -1);
+       /* Take default value as per the user manual b(110) */
+       if (info->tmu_mux == -1)
+               info->tmu_mux = 0x6;
+
        info->data.ts.min_val = fdtdec_get_int(blob,
                                node, "samsung,min-temp", -1);
-       error |= info->data.ts.min_val;
+       error |= (info->data.ts.min_val == -1);
        info->data.ts.max_val = fdtdec_get_int(blob,
                                node, "samsung,max-temp", -1);
-       error |= info->data.ts.max_val;
+       error |= (info->data.ts.max_val == -1);
        info->data.ts.start_warning = fdtdec_get_int(blob,
                                node, "samsung,start-warning", -1);
-       error |= info->data.ts.start_warning;
+       error |= (info->data.ts.start_warning == -1);
        info->data.ts.start_tripping = fdtdec_get_int(blob,
                                node, "samsung,start-tripping", -1);
-       error |= info->data.ts.start_tripping;
+       error |= (info->data.ts.start_tripping == -1);
        info->data.ts.hardware_tripping = fdtdec_get_int(blob,
                                node, "samsung,hw-tripping", -1);
-       error |= info->data.ts.hardware_tripping;
+       error |= (info->data.ts.hardware_tripping == -1);
        info->data.efuse_min_value = fdtdec_get_int(blob,
                                node, "samsung,efuse-min-value", -1);
-       error |= info->data.efuse_min_value;
+       error |= (info->data.efuse_min_value == -1);
        info->data.efuse_value = fdtdec_get_int(blob,
                                node, "samsung,efuse-value", -1);
-       error |= info->data.efuse_value;
+       error |= (info->data.efuse_value == -1);
        info->data.efuse_max_value = fdtdec_get_int(blob,
                                node, "samsung,efuse-max-value", -1);
-       error |= info->data.efuse_max_value;
+       error |= (info->data.efuse_max_value == -1);
        info->data.slope = fdtdec_get_int(blob,
                                node, "samsung,slope", -1);
-       error |= info->data.slope;
+       error |= (info->data.slope == -1);
        info->dc_value = fdtdec_get_int(blob,
                                node, "samsung,dc-value", -1);
-       error |= info->dc_value;
+       error |= (info->dc_value == -1);
 
-       if (error == -1) {
+       if (error) {
                debug("fail to get tmu node properties\n");
                return -1;
        }
+#else
+       /* Non DT support may never be added. Just in case  */
+       return -1;
 #endif
 
        return 0;
@@ -236,12 +264,12 @@ static int get_tmu_fdt_values(struct tmu_info *info, const void *blob)
  */
 static void tmu_setup_parameters(struct tmu_info *info)
 {
-       unsigned int te_code, con;
-       unsigned int warning_code, trip_code, hwtrip_code;
-       unsigned int cooling_temp;
-       unsigned int rising_value;
+       unsigned te_code, con;
+       unsigned warning_code, trip_code, hwtrip_code;
+       unsigned cooling_temp;
+       unsigned rising_value;
        struct tmu_data *data = &info->data;
-       struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base;
+       struct exynos5_tmu_reg *reg = info->tmu_base;
 
        /* Must reload for reading efuse value from triminfo register */
        writel(TRIMINFO_RELOAD, &reg->triminfo_control);
@@ -288,7 +316,7 @@ static void tmu_setup_parameters(struct tmu_info *info)
 
        /* TMU core enable */
        con = readl(&reg->tmu_control);
-       con |= THERM_TRIP_EN | CORE_EN;
+       con |= THERM_TRIP_EN | CORE_EN | (info->tmu_mux << 20);
 
        writel(con, &reg->tmu_control);
 
@@ -314,6 +342,5 @@ int tmu_init(const void *blob)
        tmu_setup_parameters(&gbl_info);
        gbl_info.tmu_state = TMU_STATUS_NORMAL;
 ret:
-
        return gbl_info.tmu_state;
 }
index daa80038a71ddc507fa594a95c575e6823393764..a19cec5ace7cb8cb16907d253b0270b9862e5147 100644 (file)
@@ -37,7 +37,6 @@ static struct serial_device *serial_current;
  * Table with supported baudrates (defined in config_xyz.h)
  */
 static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
-#define        N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0]))
 
 /**
  * serial_null() - Void registration routine of a serial driver
@@ -74,11 +73,11 @@ static int on_baudrate(const char *name, const char *value, enum env_op op,
                if (gd->baudrate == baudrate)
                        return 0;
 
-               for (i = 0; i < N_BAUDRATES; ++i) {
+               for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
                        if (baudrate == baudrate_table[i])
                                break;
                }
-               if (i == N_BAUDRATES) {
+               if (i == ARRAY_SIZE(baudrate_table)) {
                        if ((flags & H_FORCE) == 0)
                                printf("## Baudrate %d bps not supported\n",
                                        baudrate);
index 3c41242a8ece8984362cec6a0189e4fd83dac704..e65125ccd7422dda5dd5a5e11956701c0c43c2ae 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define RX_FIFO_COUNT_MASK     0xff
+#define RX_FIFO_FULL_MASK      (1 << 8)
+#define TX_FIFO_FULL_MASK      (1 << 24)
+
 static inline struct s5p_uart *s5p_get_base_uart(int dev_index)
 {
        u32 offset = dev_index * sizeof(struct s5p_uart);
@@ -87,8 +91,8 @@ int serial_init_dev(const int dev_index)
 {
        struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
-       /* reset and enable FIFOs, set triggers to the maximum */
-       writel(0, &uart->ufcon);
+       /* enable FIFOs */
+       writel(0x1, &uart->ufcon);
        writel(0, &uart->umcon);
        /* 8N1 */
        writel(0x3, &uart->ulcon);
@@ -130,7 +134,8 @@ int serial_getc_dev(const int dev_index)
        struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
        /* wait for character to arrive */
-       while (!(readl(&uart->utrstat) & 0x1)) {
+       while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
+                                        RX_FIFO_FULL_MASK))) {
                if (serial_err_check(dev_index, 0))
                        return 0;
        }
@@ -146,7 +151,7 @@ void serial_putc_dev(const char c, const int dev_index)
        struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
 
        /* wait for room in the tx FIFO */
-       while (!(readl(&uart->utrstat) & 0x2)) {
+       while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
                if (serial_err_check(dev_index, 1))
                        return;
        }
index a37ac4e5264b04db3dd3a558f82c428f1de88b6a..06bcf91a4aa3e6a7d346e7885592af441261d63f 100644 (file)
@@ -171,7 +171,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
        volatile qspi_t *qspi = dev->regs;
        u8 *txbuf = (u8 *)dout;
        u8 *rxbuf = (u8 *)din;
-       u32 count = ((bitlen / 8) + (bitlen % 8 ? 1 : 0));
+       u32 count = DIV_ROUND_UP(bitlen, 8);
        u32 n, i = 0;
 
        /* Sanitize arguments */
index 01378d098e53cf7065425bd4d83a5a38415ba4d5..7a25a35aa0f22fc3776e5919b916c3f01ad41a1f 100644 (file)
@@ -465,6 +465,28 @@ static int process_nodes(const void *blob, int node_list[], int count)
 }
 #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 node,
+               unsigned int cs, unsigned int max_hz, unsigned int mode)
+{
+       struct spi_bus *bus;
+       unsigned int i;
+
+       for (i = 0, bus = spi_bus; i < bus_count; i++, bus++) {
+               if (bus->node == node)
+                       return spi_setup_slave(i, cs, max_hz, mode);
+       }
+
+       debug("%s: Failed to find bus node %d\n", __func__, node);
+       return NULL;
+}
+
 /* Sadly there is no error return from this function */
 void spi_init(void)
 {
index 5bed858787f610a9c9a46bb2214665a51d60a9e9..2ea322833c29cb30275313d06292ae6292d3ffcd 100644 (file)
@@ -224,7 +224,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
        const u8 *dout, u8 *din, unsigned long flags)
 {
        struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
-       int nbytes = (bitlen + 7) / 8;
+       int nbytes = DIV_ROUND_UP(bitlen, 8);
        u32 data, cnt, i;
        struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
 
@@ -294,7 +294,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
        /* Transfer completed, clear any pending request */
        reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
 
-       nbytes = (bitlen + 7) / 8;
+       nbytes = DIV_ROUND_UP(bitlen, 8);
 
        cnt = nbytes % 32;
 
@@ -330,7 +330,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
                void *din, unsigned long flags)
 {
-       int n_bytes = (bitlen + 7) / 8;
+       int n_bytes = DIV_ROUND_UP(bitlen, 8);
        int n_bits;
        int ret;
        u32 blk_size;
index 60e03a4bf73a5d755a5d68f05b8198b4600746e8..7bb91e5abfe859b2d13aa307263f71dca9200e4d 100644 (file)
@@ -1105,8 +1105,7 @@ int usb_lowlevel_init(int index, void **controller)
 
        /* Configure all the endpoint FIFO's and start usb controller */
        musbr = musb_cfg.regs;
-       musb_configure_ep(&epinfo[0],
-                       sizeof(epinfo) / sizeof(struct musb_epinfo));
+       musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo));
        musb_start();
 
        /*
index e0b4217dc3f5060c1fe8d2489f452722d804b003..e8a2ce0419478e87ac60c1f6830a4643b2badf2b 100644 (file)
@@ -894,8 +894,7 @@ void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
                        epinfo[id * 2].epsize = endpoint->rcv_packetSize;
                }
 
-               musb_configure_ep(&epinfo[0],
-                                 sizeof(epinfo) / sizeof(struct musb_epinfo));
+               musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo));
        } else {
                if (debug_level > 0)
                        serial_printf("ERROR : %s endpoint request %d "
index ed0823bf977af0a6bc1d91fae9240479513c4d6b..c3606d5b026ad702b2290d713abffd0b390b1c22 100644 (file)
@@ -319,10 +319,10 @@ void lcd_ctrl_init(void *lcdbase)
 #ifdef CONFIG_OF_CONTROL
        if (exynos_fimd_parse_dt(gd->fdt_blob))
                debug("Can't get proper panel info\n");
-#endif
+#else
        /* initialize parameters which is specific to panel. */
        init_panel_info(&panel_info);
-
+#endif
        panel_width = panel_info.vl_width;
        panel_height = panel_info.vl_height;
 
index 3e9ca1182d7e48e2a6cd63d17f5da44da7b027e7..8cfc3fa775610ae2de9c01166da82efdade34434 100644 (file)
@@ -82,6 +82,9 @@ typedef struct global_data {
        unsigned long fdt_size; /* Space reserved for relocated FDT */
        void **jt;              /* jump table */
        char env_buf[32];       /* buffer for getenv() before reloc. */
+#ifdef CONFIG_TRACE
+       void            *trace_buff;    /* The trace buffer */
+#endif
        struct arch_global_data arch;   /* architecture-specific data */
 } gd_t;
 #endif
index 4b39844549f25fb0a164693c9a1639bfdd519146..3e32eee92c3d733d366f66bc41f6fc8583ffc6d6 100644 (file)
@@ -90,9 +90,6 @@ extern void _start(void);
 extern ulong _rel_dyn_start_ofs;
 extern ulong _rel_dyn_end_ofs;
 
-/* Start/end of the relocation symbol table, as an offset from _start */
-extern ulong _dynsym_start_ofs;
-
 /* End of the region to be relocated, as an offset form _start */
 extern ulong _image_copy_end_ofs;
 
index 65692fd2a69f59b911fc64301e82b3bd21b95b93..9e05ddc1329ae2ce60fe7b2bfc84e6da66b41445 100644 (file)
@@ -110,6 +110,8 @@ static inline int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
 }
 #endif
 
+extern int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
 extern int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
                           char *const argv[]);
 
index 126891d6587ae9060e506f5992a13029e0233baa..e5220cf67195972520d51cf96cb0e540aec7b4f2 100644 (file)
@@ -750,6 +750,10 @@ void       irq_install_handler(int, interrupt_handler_t *, void *);
 void   irq_free_handler   (int);
 void   reset_timer        (void);
 ulong  get_timer          (ulong base);
+
+/* Return value of monotonic microsecond timer */
+unsigned long timer_get_us(void);
+
 void   enable_interrupts  (void);
 int    disable_interrupts (void);
 
index c15bbd856c3fb53bc1352d17728487ae1dba078c..a823f9f3a77c5ae686b0e9abf663e9e5ed6dd697 100644 (file)
 #define CONFIG_RESET_VECTOR_ADDRESS    0xfffffffc
 #endif
 
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+/* Set 1M boot space */
+#define CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR (CONFIG_SYS_TEXT_BASE & 0xfff00000)
+#define CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS \
+               (0x300000000ull | CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR)
+#define CONFIG_RESET_VECTOR_ADDRESS 0xfffffffc
+#define CONFIG_SYS_NO_FLASH
+#endif
+
 /* High Level Configuration Options */
 #define CONFIG_BOOKE
 #define CONFIG_E500                    /* BOOKE e500 family */
@@ -63,6 +72,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1                   /* SRIO port 1 */
 #define CONFIG_SRIO2                   /* SRIO port 2 */
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #endif
 
 #define CONFIG_FSL_LAW                 /* Use common FSL init code */
 #define CONFIG_ENV_OVERWRITE
 
 #ifdef CONFIG_SYS_NO_FLASH
+#if !defined(CONFIG_SRIO_PCIE_BOOT_SLAVE) && !defined(CONFIG_RAMBOOT_PBL)
 #define CONFIG_ENV_IS_NOWHERE
+#endif
 #else
 #define CONFIG_FLASH_CFI_DRIVER
 #define CONFIG_SYS_FLASH_CFI
 #define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
 #endif
 
-#ifndef CONFIG_SYS_NO_FLASH
 #if defined(CONFIG_SPIFLASH)
 #define CONFIG_SYS_EXTRA_ENV_RELOC
 #define CONFIG_ENV_IS_IN_SPI_FLASH
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_SIZE                        CONFIG_SYS_NAND_BLOCK_SIZE
 #define CONFIG_ENV_OFFSET              (5 * CONFIG_SYS_NAND_BLOCK_SIZE)
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+#define CONFIG_ENV_IS_IN_REMOTE
+#define CONFIG_ENV_ADDR                0xffe20000
+#define CONFIG_ENV_SIZE                0x2000
+#elif defined(CONFIG_ENV_IS_NOWHERE)
+#define CONFIG_ENV_SIZE                0x2000
 #else
 #define CONFIG_ENV_IS_IN_FLASH
 #define CONFIG_ENV_ADDR                (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SECT_SIZE)
 #define CONFIG_ENV_SIZE                0x2000
 #define CONFIG_ENV_SECT_SIZE   0x20000 /* 128K (one sector) */
 #endif
-#else /* CONFIG_SYS_NO_FLASH */
-#define CONFIG_ENV_SIZE                0x2000
-#define CONFIG_ENV_SECT_SIZE   0x20000 /* 128K (one sector) */
-#endif
 
 #ifndef __ASSEMBLY__
 unsigned long get_board_sys_clk(void);
@@ -223,7 +236,7 @@ unsigned long get_board_ddr_clk(void);
 /* NOR Flash Timing Params */
 #define CONFIG_SYS_NOR_CSOR    CSOR_NOR_ADM_SHIFT(4)
 #define CONFIG_SYS_NOR_FTIM0   (FTIM0_NOR_TACSE(0x01) | \
-                               FTIM0_NOR_TEADC(0x01) | \
+                               FTIM0_NOR_TEADC(0x04) | \
                                FTIM0_NOR_TEAHC(0x20))
 #define CONFIG_SYS_NOR_FTIM1   (FTIM1_NOR_TACO(0x35) | \
                                FTIM1_NOR_TRAD_NOR(0x1A) |\
@@ -600,6 +613,16 @@ unsigned long get_board_ddr_clk(void);
 #elif defined(CONFIG_NAND)
 #define CONFIG_SYS_QE_FMAN_FW_IN_NAND
 #define CONFIG_SYS_QE_FMAN_FW_ADDR     (6 * CONFIG_SYS_NAND_BLOCK_SIZE)
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+/*
+ * Slave has no ucode locally, it can fetch this from remote. When implementing
+ * in two corenet boards, slave's ucode could be stored in master's memory
+ * space, the address can be mapped from slave TLB->slave LAW->
+ * slave SRIO or PCIE outbound window->master inbound window->
+ * master LAW->the ucode address in master's memory space.
+ */
+#define CONFIG_SYS_QE_FMAN_FW_IN_REMOTE
+#define CONFIG_SYS_QE_FMAN_FW_ADDR     0xFFE00000
 #else
 #define CONFIG_SYS_QE_FMAN_FW_IN_NOR
 #define CONFIG_SYS_QE_FMAN_FW_ADDR             0xEFF40000
index fd076e09a277eeb2d8d1d6383ab76bd739a94242..b5911c69450be70c082f88ccb2d1dff65bbd39f7 100644 (file)
 #define CONFIG_RESET_VECTOR_ADDRESS    0x1107fffc
 #endif
 
-#ifndef CONFIG_SYS_MONITOR_BASE
-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE    /* start of monitor */
+#ifdef CONFIG_NAND
+#define CONFIG_SPL
+#define CONFIG_SPL_INIT_MINIMAL
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_MINIMAL
+#define CONFIG_SPL_FLUSH_IMAGE
+#define CONFIG_SPL_TARGET              "u-boot-with-spl.bin"
+
+#define CONFIG_SYS_TEXT_BASE           0x00201000
+#define CONFIG_SPL_TEXT_BASE           0xFFFFE000
+#define CONFIG_SPL_MAX_SIZE            8192
+#define CONFIG_SPL_RELOC_TEXT_BASE     0x00100000
+#define CONFIG_SPL_RELOC_STACK         0x00100000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE    ((512 << 10) - 0x2000)
+#define CONFIG_SYS_NAND_U_BOOT_DST     (0x00200000 - CONFIG_SPL_MAX_SIZE)
+#define CONFIG_SYS_NAND_U_BOOT_START   0x00200000
+#define CONFIG_SYS_NAND_U_BOOT_OFFS    0
+#define CONFIG_SYS_LDSCRIPT    "arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
 #endif
 
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MONITOR_BASE        CONFIG_SPL_TEXT_BASE
+#else
+#define CONFIG_SYS_MONITOR_BASE        CONFIG_SYS_TEXT_BASE    /* start of monitor */
+#endif
+
+
 /* High Level Configuration Options */
 #define CONFIG_BOOKE                   /* BOOKE */
 #define CONFIG_E500                    /* BOOKE e500 family */
 #define CONFIG_ENV_OVERWRITE
 
 #define CONFIG_DDR_CLK_FREQ    66666666 /* DDRCLK on 9131 RDB */
+#if defined(CONFIG_SYS_CLK_100)
+#define CONFIG_SYS_CLK_FREQ    100000000 /* SYSCLK for 9131 RDB */
+#else
 #define CONFIG_SYS_CLK_FREQ    66666666 /* SYSCLK for 9131 RDB */
+#endif
 
 #define CONFIG_HWCONFIG
 /*
@@ -125,16 +153,21 @@ extern unsigned long get_sdram_size(void);
 
 #define CONFIG_SYS_IMMR                CONFIG_SYS_CCSRBAR      /* PQII uses */
                                                        /* CONFIG_SYS_IMMR */
+/* DSP CCSRBAR */
+#define CONFIG_SYS_FSL_DSP_CCSRBAR     CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT
+#define CONFIG_SYS_FSL_DSP_CCSRBAR_PHYS        CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT
 
 /*
  * Memory map
  *
  * 0x0000_0000 0x3FFF_FFFF     DDR                     1G cacheable
  * 0x8800_0000 0x8810_0000     IFC internal SRAM               1M
+ * 0xB000_0000 0xB0FF_FFFF     DSP core M2 memory      16M
  * 0xC100_0000 0xC13F_FFFF     MAPLE-2F                4M
  * 0xC1F0_0000 0xC1F3_FFFF     PA L2 SRAM Region 0     256K
  * 0xC1F8_0000 0xC1F9_FFFF     PA L2 SRAM Region 1     128K
  * 0xFED0_0000 0xFED0_3FFF     SEC Secured RAM         16K
+ * 0xFF60_0000 0xFF6F_FFFF     DSP CCSR                1M
  * 0xFF70_0000 0xFF7F_FFFF     PA CCSR                 1M
  * 0xFF80_0000 0xFFFF_FFFF     Boot Page & NAND flash buffer   8M
  *
@@ -214,6 +247,9 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE    1
 #define CONFIG_SYS_NS16550_CLK         get_bus_freq(0)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_NS16550_MIN_FUNCTIONS
+#endif
 
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV   /* determine from environment */
 
@@ -295,7 +331,6 @@ extern unsigned long get_sdram_size(void);
 /*
  * Environment
  */
-#if defined(CONFIG_SYS_RAMBOOT)
 #if defined(CONFIG_RAMBOOT_SPIFLASH)
 #define CONFIG_ENV_IS_IN_SPI_FLASH
 #define CONFIG_ENV_SPI_BUS     0
@@ -305,15 +340,16 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_ENV_OFFSET      0x100000        /* 1MB */
 #define CONFIG_ENV_SECT_SIZE   0x10000
 #define CONFIG_ENV_SIZE                0x2000
-#else
-#define CONFIG_ENV_IS_NOWHERE          /* Store ENV in memory only */
-#define CONFIG_ENV_ADDR                        (CONFIG_SYS_MONITOR_BASE - 0x1000)
-#define CONFIG_ENV_SIZE                        0x2000
-#endif
-#else
-#define CONFIG_ENV_IS_NOWHERE  1       /* Store ENV in memory only */
+#elif defined(CONFIG_NAND)
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_SYS_EXTRA_ENV_RELOC
+#define CONFIG_ENV_SIZE                CONFIG_SYS_NAND_BLOCK_SIZE
+#define CONFIG_ENV_OFFSET      ((512 * 1024) + CONFIG_SYS_NAND_BLOCK_SIZE)
+#define CONFIG_ENV_RANGE       (3 * CONFIG_ENV_SIZE)
+#elif defined(CONFIG_SYS_RAMBOOT)
+#define CONFIG_ENV_IS_NOWHERE  /* Store ENV in memory only */
 #define CONFIG_ENV_ADDR                (CONFIG_SYS_MONITOR_BASE - 0x1000)
-#define CONFIG_ENV_SIZE                0x400
+#define CONFIG_ENV_SIZE                0x2000
 #endif
 
 #define CONFIG_LOADS_ECHO              /* echo on for serial download */
@@ -406,7 +442,9 @@ extern unsigned long get_sdram_size(void);
        "fdtfile=bsc9131rdb.dtb\0"              \
        "bdev=sda1\0"   \
        "hwconfig=usb1:dr_mode=host,phy_type=ulpi\0"    \
-       "othbootargs=ramdisk_size=600000 \0" \
+       "bootm_size=0x37000000\0"       \
+       "othbootargs=ramdisk_size=600000 " \
+       "default_hugepagesz=256m hugepagesz=256m hugepages=1\0" \
        "usbext2boot=setenv bootargs root=/dev/ram rw " \
        "console=$consoledev,$baudrate $othbootargs; "  \
        "usb start;"                    \
index 9d15d0eb880f01641e6d6f0df8b9be1d2553335f..3aa44435a204f3a499bc638e4ec95348f0b51015 100644 (file)
 #define CONFIG_RESET_VECTOR_ADDRESS    0x1107fffc
 #endif
 
+#ifdef CONFIG_NAND
+#define CONFIG_SPL
+#define CONFIG_SPL_INIT_MINIMAL
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_MINIMAL
+#define CONFIG_SPL_FLUSH_IMAGE
+#define CONFIG_SPL_TARGET              "u-boot-with-spl.bin"
+
+#define CONFIG_SYS_TEXT_BASE           0x00201000
+#define CONFIG_SPL_TEXT_BASE           0xFFFFE000
+#define CONFIG_SPL_MAX_SIZE            8192
+#define CONFIG_SPL_RELOC_TEXT_BASE     0x00100000
+#define CONFIG_SPL_RELOC_STACK         0x00100000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE    ((512 << 10) - 0x2000)
+#define CONFIG_SYS_NAND_U_BOOT_DST     (0x00200000 - CONFIG_SPL_MAX_SIZE)
+#define CONFIG_SYS_NAND_U_BOOT_START   0x00200000
+#define CONFIG_SYS_NAND_U_BOOT_OFFS    0
+#define CONFIG_SYS_LDSCRIPT    "arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
+#endif
+
 #ifndef CONFIG_SYS_TEXT_BASE
 #define CONFIG_SYS_TEXT_BASE           0x8ff80000
 #endif
 #define CONFIG_RESET_VECTOR_ADDRESS    0x8ffffffc
 #endif
 
-#ifndef CONFIG_SYS_MONITOR_BASE
-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE    /* start of monitor */
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MONITOR_BASE        CONFIG_SPL_TEXT_BASE
+#else
+#define CONFIG_SYS_MONITOR_BASE        CONFIG_SYS_TEXT_BASE    /* start of monitor */
 #endif
 
-
 /* High Level Configuration Options */
 #define CONFIG_BOOKE                   /* BOOKE */
 #define CONFIG_E500                    /* BOOKE e500 family */
@@ -222,6 +244,10 @@ combinations. this should be removed later
  * IFC Definitions
  */
 /* NOR Flash on IFC */
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_NO_FLASH
+#endif
 #define CONFIG_SYS_FLASH_BASE          0x88000000
 #define CONFIG_SYS_MAX_FLASH_SECT      1024    /* Max number of sector: 32M */
 
@@ -302,7 +328,9 @@ combinations. this should be removed later
 
 #define CONFIG_SYS_NAND_BLOCK_SIZE     (128 * 1024)
 
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_FSL_QIXIS
+#endif
 #ifdef CONFIG_FSL_QIXIS
 #define CONFIG_SYS_FPGA_BASE   0xffb00000
 #define CONFIG_SYS_I2C_FPGA_ADDR       0x66
@@ -338,6 +366,22 @@ combinations. this should be removed later
 #endif
 
 /* Set up IFC registers for boot location NOR/NAND */
+#if defined(CONFIG_NAND)
+#define CONFIG_SYS_CSPR0               CONFIG_SYS_NAND_CSPR
+#define CONFIG_SYS_AMASK0              CONFIG_SYS_NAND_AMASK
+#define CONFIG_SYS_CSOR0               CONFIG_SYS_NAND_CSOR
+#define CONFIG_SYS_CS0_FTIM0           CONFIG_SYS_NAND_FTIM0
+#define CONFIG_SYS_CS0_FTIM1           CONFIG_SYS_NAND_FTIM1
+#define CONFIG_SYS_CS0_FTIM2           CONFIG_SYS_NAND_FTIM2
+#define CONFIG_SYS_CS0_FTIM3           CONFIG_SYS_NAND_FTIM3
+#define CONFIG_SYS_CSPR1               CONFIG_SYS_NOR_CSPR
+#define CONFIG_SYS_AMASK1              CONFIG_SYS_NOR_AMASK
+#define CONFIG_SYS_CSOR1               CONFIG_SYS_NOR_CSOR
+#define CONFIG_SYS_CS1_FTIM0           CONFIG_SYS_NOR_FTIM0
+#define CONFIG_SYS_CS1_FTIM1           CONFIG_SYS_NOR_FTIM1
+#define CONFIG_SYS_CS1_FTIM2           CONFIG_SYS_NOR_FTIM2
+#define CONFIG_SYS_CS1_FTIM3           CONFIG_SYS_NOR_FTIM3
+#else
 #define CONFIG_SYS_CSPR0               CONFIG_SYS_NOR_CSPR
 #define CONFIG_SYS_AMASK0              CONFIG_SYS_NOR_AMASK
 #define CONFIG_SYS_CSOR0               CONFIG_SYS_NOR_CSOR
@@ -352,6 +396,7 @@ combinations. this should be removed later
 #define CONFIG_SYS_CS1_FTIM1           CONFIG_SYS_NAND_FTIM1
 #define CONFIG_SYS_CS1_FTIM2           CONFIG_SYS_NAND_FTIM2
 #define CONFIG_SYS_CS1_FTIM3           CONFIG_SYS_NAND_FTIM3
+#endif
 
 #define CONFIG_BOARD_EARLY_INIT_F      /* Call board_pre_init */
 #define CONFIG_BOARD_EARLY_INIT_R
@@ -374,6 +419,9 @@ combinations. this should be removed later
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE    1
 #define CONFIG_SYS_NS16550_CLK         get_bus_freq(0)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_NS16550_MIN_FUNCTIONS
+#endif
 
 #define CONFIG_SERIAL_MULTI    1 /* Enable both serial ports */
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV   /* determine from environment */
@@ -503,7 +551,6 @@ combinations. this should be removed later
 /*
  * Environment
  */
-#if defined(CONFIG_SYS_RAMBOOT)
 #if defined(CONFIG_RAMBOOT_SDCARD)
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_SYS_MMC_ENV_DEV         0
@@ -517,11 +564,15 @@ combinations. this should be removed later
 #define CONFIG_ENV_OFFSET      0x100000        /* 1MB */
 #define CONFIG_ENV_SECT_SIZE   0x10000
 #define CONFIG_ENV_SIZE                0x2000
-#else
+#elif defined(CONFIG_NAND)
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_SIZE                CONFIG_SYS_NAND_BLOCK_SIZE
+#define CONFIG_ENV_OFFSET      ((512 * 1024) + CONFIG_SYS_NAND_BLOCK_SIZE)
+#define CONFIG_ENV_RANGE       (3 * CONFIG_ENV_SIZE)
+#elif defined(CONFIG_SYS_RAMBOOT)
 #define CONFIG_ENV_IS_NOWHERE          /* Store ENV in memory only */
 #define CONFIG_ENV_ADDR                        (CONFIG_SYS_MONITOR_BASE - 0x1000)
 #define CONFIG_ENV_SIZE                        0x2000
-#endif
 #else
 #define CONFIG_ENV_IS_IN_FLASH
 #if CONFIG_SYS_MONITOR_BASE > 0xfff80000
index 51855979050cb7ab5c04024c184e843970770418..7b28a27bc07619b8b5e4a5b366464ef1c063ad61 100644 (file)
 #define CONFIG_PHYS_64BIT
 #endif
 
-#ifdef CONFIG_P1010RDB
 #define CONFIG_P1010
+#define CONFIG_E500                    /* BOOKE e500 family */
+#include <asm/config_mpc85xx.h>
 #define CONFIG_NAND_FSL_IFC
-#endif
 
 #ifdef CONFIG_SDCARD
 #define CONFIG_RAMBOOT_SDCARD
 #define CONFIG_RESET_VECTOR_ADDRESS    0x1107fffc
 #endif
 
-#ifdef CONFIG_NAND     /* NAND Boot */
-#define CONFIG_RAMBOOT_NAND
-#define CONFIG_NAND_U_BOOT
-#define CONFIG_SYS_TEXT_BASE_SPL       0xff800000
-#ifdef CONFIG_NAND_SPL
-#define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE_SPL
-#else
-#define CONFIG_SYS_TEXT_BASE           0x11001000
-#endif /* CONFIG_NAND_SPL */
+#ifdef CONFIG_NAND
+#define CONFIG_SPL
+#define CONFIG_SPL_INIT_MINIMAL
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_MINIMAL
+#define CONFIG_SPL_FLUSH_IMAGE
+#define CONFIG_SPL_TARGET              "u-boot-with-spl.bin"
+
+#define CONFIG_SYS_TEXT_BASE           0x00201000
+#define CONFIG_SPL_TEXT_BASE           0xFFFFE000
+#define CONFIG_SPL_MAX_SIZE            8192
+#define CONFIG_SPL_RELOC_TEXT_BASE     0x00100000
+#define CONFIG_SPL_RELOC_STACK         0x00100000
+#define CONFIG_SYS_NAND_U_BOOT_SIZE    ((512 << 10) - 0x2000)
+#define CONFIG_SYS_NAND_U_BOOT_DST     (0x00200000 - CONFIG_SPL_MAX_SIZE)
+#define CONFIG_SYS_NAND_U_BOOT_START   0x00200000
+#define CONFIG_SYS_NAND_U_BOOT_OFFS    0
+#define CONFIG_SYS_LDSCRIPT    "arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
 #endif
 
 
 #define CONFIG_RESET_VECTOR_ADDRESS    0xeffffffc
 #endif
 
-#ifndef CONFIG_SYS_MONITOR_BASE
-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE    /* start of monitor */
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MONITOR_BASE        CONFIG_SPL_TEXT_BASE
+#else
+#define CONFIG_SYS_MONITOR_BASE        CONFIG_SYS_TEXT_BASE    /* start of monitor */
 #endif
 
 /* High Level Configuration Options */
@@ -242,7 +254,7 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_SYS_CCSRBAR_PHYS_LOW            CONFIG_SYS_CCSRBAR
 
 /* Don't relocate CCSRBAR while in NAND_SPL */
-#ifdef CONFIG_NAND_SPL
+#ifdef CONFIG_SPL_BUILD
 #define CONFIG_SYS_CCSR_DO_NOT_RELOCATE
 #endif
 
@@ -268,6 +280,10 @@ extern unsigned long get_sdram_size(void);
  * IFC Definitions
  */
 /* NOR Flash on IFC */
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_NO_FLASH
+#endif
+
 #define CONFIG_SYS_FLASH_BASE          0xee000000
 #define CONFIG_SYS_MAX_FLASH_SECT      256     /* 32M */
 
@@ -353,7 +369,7 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_SYS_NAND_DDR_LAW                11
 
 /* Set up IFC registers for boot location NOR/NAND */
-#if defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SECBOOT)
+#if defined(CONFIG_NAND) || defined(CONFIG_NAND_SECBOOT)
 #define CONFIG_SYS_CSPR0               CONFIG_SYS_NAND_CSPR
 #define CONFIG_SYS_AMASK0              CONFIG_SYS_NAND_AMASK
 #define CONFIG_SYS_CSOR0               CONFIG_SYS_NAND_CSOR
@@ -385,15 +401,6 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_SYS_CS1_FTIM3           CONFIG_SYS_NAND_FTIM3
 #endif
 
-/* NAND boot: 8K NAND loader config */
-#define CONFIG_SYS_NAND_SPL_SIZE       0x2000
-#define CONFIG_SYS_NAND_U_BOOT_SIZE    (512 << 10)
-#define CONFIG_SYS_NAND_U_BOOT_DST     (0x11000000 - CONFIG_SYS_NAND_SPL_SIZE)
-#define CONFIG_SYS_NAND_U_BOOT_START   0x11000000
-#define CONFIG_SYS_NAND_U_BOOT_OFFS    (0)
-#define CONFIG_SYS_NAND_U_BOOT_RELOC   0x10000
-#define CONFIG_SYS_NAND_U_BOOT_RELOC_SP        (CONFIG_SYS_NAND_U_BOOT_RELOC + 0x10000)
-
 /* CPLD on IFC */
 #define CONFIG_SYS_CPLD_BASE           0xffb00000
 
@@ -421,14 +428,20 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_SYS_CS3_FTIM3           0x0
 #endif /* CONFIG_SDCARD */
 
-#if defined(CONFIG_RAMBOOT_SDCARD) || defined(CONFIG_RAMBOOT_SPIFLASH) || \
-    defined(CONFIG_RAMBOOT_NAND)
+#if defined(CONFIG_RAMBOOT_SDCARD) || defined(CONFIG_RAMBOOT_SPIFLASH)
 #define CONFIG_SYS_RAMBOOT
 #define CONFIG_SYS_EXTRA_ENV_RELOC
 #else
 #undef CONFIG_SYS_RAMBOOT
 #endif
 
+#ifdef CONFIG_SYS_FSL_ERRATUM_IFC_A003399
+#if !defined(CONFIG_SPL) && !defined(CONFIG_SYS_RAMBOOT)\
+       && !defined(CONFIG_SECURE_BOOT)
+#define CONFIG_A003399_NOR_WORKAROUND
+#endif
+#endif
+
 #define CONFIG_BOARD_EARLY_INIT_F      /* Call board_pre_init */
 #define CONFIG_BOARD_EARLY_INIT_R
 
@@ -450,7 +463,7 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE    1
 #define CONFIG_SYS_NS16550_CLK         get_bus_freq(0)
-#ifdef CONFIG_NAND_SPL
+#ifdef CONFIG_SPL_BUILD
 #define CONFIG_NS16550_MIN_FUNCTIONS
 #endif
 
@@ -505,7 +518,7 @@ extern unsigned long get_sdram_size(void);
  * SPI interface will not be available in case of NAND boot SPI CS0 will be
  * used for SLIC
  */
-#if !defined(CONFIG_NAND_U_BOOT) || !defined(CONFIG_NAND_SECBOOT)
+#if !defined(CONFIG_NAND) || !defined(CONFIG_NAND_SECBOOT)
 /* eSPI - Enhanced SPI */
 #define CONFIG_FSL_ESPI
 #define CONFIG_SPI_FLASH
@@ -600,7 +613,6 @@ extern unsigned long get_sdram_size(void);
 /*
  * Environment
  */
-#if defined(CONFIG_SYS_RAMBOOT)
 #if defined(CONFIG_RAMBOOT_SDCARD)
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_FSL_FIXED_MMC_LOCATION
@@ -615,16 +627,15 @@ extern unsigned long get_sdram_size(void);
 #define CONFIG_ENV_OFFSET      0x100000        /* 1MB */
 #define CONFIG_ENV_SECT_SIZE   0x10000
 #define CONFIG_ENV_SIZE                0x2000
-#elif defined(CONFIG_NAND_U_BOOT)
+#elif defined(CONFIG_NAND)
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_SIZE                CONFIG_SYS_NAND_BLOCK_SIZE
-#define CONFIG_ENV_OFFSET      CONFIG_SYS_NAND_U_BOOT_SIZE
+#define CONFIG_ENV_OFFSET      ((512 * 1024) + CONFIG_SYS_NAND_BLOCK_SIZE)
 #define CONFIG_ENV_RANGE       (3 * CONFIG_ENV_SIZE)
-#else
+#elif defined(CONFIG_SYS_RAMBOOT)
 #define CONFIG_ENV_IS_NOWHERE          /* Store ENV in memory only */
 #define CONFIG_ENV_ADDR                        (CONFIG_SYS_MONITOR_BASE - 0x1000)
 #define CONFIG_ENV_SIZE                        0x2000
-#endif
 #else
 #define CONFIG_ENV_IS_IN_FLASH
 #if CONFIG_SYS_MONITOR_BASE > 0xfff80000
diff --git a/include/configs/P1023RDB.h b/include/configs/P1023RDB.h
new file mode 100644 (file)
index 0000000..fee8040
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Authors:  Roy Zang <tie-fei.zang@freescale.com>
+ *          Chunhe Lan <Chunhe.Lan@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#ifndef CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_TEXT_BASE   0xeff80000
+#endif
+
+#ifndef CONFIG_SYS_MONITOR_BASE
+#define CONFIG_SYS_MONITOR_BASE        CONFIG_SYS_TEXT_BASE    /* start of monitor */
+#endif
+
+#ifndef CONFIG_RESET_VECTOR_ADDRESS
+#define CONFIG_RESET_VECTOR_ADDRESS    0xeffffffc
+#endif
+
+/* High Level Configuration Options */
+#define CONFIG_BOOKE           /* BOOKE */
+#define CONFIG_E500            /* BOOKE e500 family */
+#define CONFIG_MPC85xx
+#define CONFIG_P1023
+#define CONFIG_MP              /* support multiple processors */
+
+#define CONFIG_FSL_ELBC                /* Has Enhanced localbus controller */
+#define CONFIG_PCI             /* Enable PCI/PCIE */
+#define CONFIG_PCI_INDIRECT_BRIDGE     /* indirect PCI bridge support */
+#define CONFIG_PCIE1           /* PCIE controler 1 (slot 1) */
+#define CONFIG_PCIE2           /* PCIE controler 2 (slot 2) */
+#define CONFIG_PCIE3           /* PCIE controler 3 (slot 3) */
+#define CONFIG_FSL_PCI_INIT    /* Use common FSL init code */
+#define CONFIG_FSL_PCIE_RESET  /* need PCIe reset errata */
+#define CONFIG_SYS_PCI_64BIT   /* enable 64-bit PCI resources */
+#define CONFIG_FSL_LAW         /* Use common FSL init code */
+
+#ifndef __ASSEMBLY__
+extern unsigned long get_clock_freq(void);
+#endif
+
+#define CONFIG_SYS_CLK_FREQ    66666666
+#define CONFIG_DDR_CLK_FREQ    CONFIG_SYS_CLK_FREQ
+
+/*
+ * These can be toggled for performance analysis, otherwise use default.
+ */
+#define CONFIG_L2_CACHE                        /* toggle L2 cache */
+#define CONFIG_BTB                     /* toggle branch predition */
+#define CONFIG_HWCONFIG
+
+#define CONFIG_ENABLE_36BIT_PHYS
+
+#define CONFIG_SYS_MEMTEST_START       0x01000000      /* memtest works on */
+#define CONFIG_SYS_MEMTEST_END         0x02000000
+
+#define CONFIG_PANIC_HANG      /* do not reset board on panic */
+
+/* Implement conversion of addresses in the LBC */
+#define CONFIG_SYS_LBC_LBCR            0x00000000
+#define CONFIG_SYS_LBC_LCRR            LCRR_CLKDIV_8
+
+/* DDR Setup */
+#define CONFIG_VERY_BIG_RAM
+#define CONFIG_SYS_DDR_SDRAM_BASE      0x00000000
+#define CONFIG_SYS_SDRAM_BASE          CONFIG_SYS_DDR_SDRAM_BASE
+
+#define CONFIG_DIMM_SLOTS_PER_CTLR     1
+#define CONFIG_CHIP_SELECTS_PER_CTRL   1
+
+#define CONFIG_DDR_SPD
+#define CONFIG_FSL_DDR3
+#define CONFIG_FSL_DDR_INTERACTIVE
+#define CONFIG_SYS_SDRAM_SIZE          512u    /* DDR is 512M */
+#define CONFIG_SYS_SPD_BUS_NUM          0
+#define SPD_EEPROM_ADDRESS              0x50
+#define CONFIG_SYS_DDR_RAW_TIMING
+
+/*
+ * Memory map
+ *
+ * 0x0000_0000 0x1fff_ffff     DDR                     512M cacheable
+ * 0x8000_0000 0xbfff_ffff     PCI Express Mem         1G non-cacheable
+ * 0xc000_0000 0xdfff_ffff     PCI                     512M non-cacheable
+ * 0xe100_0000 0xe3ff_ffff     PCI IO range            4M non-cacheable
+ * 0xff00_0000 0xff3f_ffff     DPAA_QBMAN              4M cacheable
+ * 0xff60_0000 0xff7f_ffff     CCSR                    2M non-cacheable
+ * 0xffd0_0000 0xffd0_3fff     L1 for stack            16K cacheable TLB0
+ *
+ * Localbus non-cacheable
+ *
+ * 0xec00_0000 0xefff_ffff     NOR flash               64M non-cacheable
+ * 0xffa0_0000 0xffaf_ffff     NAND                    1M non-cacheable
+ */
+
+/*
+ * Local Bus Definitions
+ */
+#define CONFIG_SYS_FLASH_BASE          0xec000000 /* start of FLASH 64M */
+#define CONFIG_SYS_FLASH_BASE_PHYS     CONFIG_SYS_FLASH_BASE
+
+#define CONFIG_FLASH_BR_PRELIM  (BR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS) \
+                               | BR_PS_16 | BR_V)
+#define CONFIG_FLASH_OR_PRELIM 0xfc000ff7
+
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_EMPTY_INFO
+#define CONFIG_SYS_MAX_FLASH_BANKS     1       /* number of banks */
+#define CONFIG_SYS_MAX_FLASH_SECT      512     /* sectors per device */
+#define CONFIG_SYS_FLASH_ERASE_TOUT    60000   /* Flash Erase Timeout (ms) */
+#define CONFIG_SYS_FLASH_WRITE_TOUT    500     /* Flash Write Timeout (ms) */
+
+#define CONFIG_BOARD_EARLY_INIT_F      /* call board_early_init_f function */
+#define CONFIG_BOARD_EARLY_INIT_R      /* call board_early_init_r function */
+
+#define CONFIG_SYS_INIT_RAM_LOCK
+#define CONFIG_SYS_INIT_RAM_ADDR       0xffd00000      /* Initial L1 address */
+#define CONFIG_SYS_INIT_RAM_SIZE       0x00004000/* Size of used area in RAM */
+#define CONFIG_SYS_GBL_DATA_OFFSET     (CONFIG_SYS_INIT_RAM_SIZE - \
+                                       GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_OFFSET      CONFIG_SYS_GBL_DATA_OFFSET
+
+#define CONFIG_SYS_MONITOR_LEN (512 * 1024)      /* Reserve 512 kB for Mon */
+#define CONFIG_SYS_MALLOC_LEN  (6 * 1024 * 1024) /* Reserved for malloc */
+
+#define CONFIG_SYS_NAND_BASE           0xffa00000
+#define CONFIG_SYS_NAND_BASE_PHYS      CONFIG_SYS_NAND_BASE
+
+#define CONFIG_SYS_NAND_BASE_LIST      { CONFIG_SYS_NAND_BASE }
+#define CONFIG_SYS_MAX_NAND_DEVICE     1
+#define CONFIG_MTD_NAND_VERIFY_WRITE
+#define CONFIG_CMD_NAND
+#define CONFIG_NAND_FSL_ELBC
+#define CONFIG_SYS_NAND_BLOCK_SIZE     (128 * 1024)
+
+/* NAND flash config */
+#define CONFIG_SYS_NAND_BR_PRELIM  (BR_PHYS_ADDR(CONFIG_SYS_NAND_BASE_PHYS) \
+                               | (2<<BR_DECC_SHIFT)    /* Use HW ECC */ \
+                               | BR_PS_8               /* Port Size = 8bit */ \
+                               | BR_MS_FCM             /* MSEL = FCM */ \
+                               | BR_V)                 /* valid */
+#define CONFIG_SYS_NAND_OR_PRELIM  (OR_AM_256KB                /* length 256K */ \
+                               | OR_FCM_PGS \
+                               | OR_FCM_CSCT \
+                               | OR_FCM_CST \
+                               | OR_FCM_CHT \
+                               | OR_FCM_SCY_1 \
+                               | OR_FCM_TRLX \
+                               | OR_FCM_EHTR)
+
+#define CONFIG_SYS_BR0_PRELIM  CONFIG_FLASH_BR_PRELIM  /* NOR Base Address */
+#define CONFIG_SYS_OR0_PRELIM  CONFIG_FLASH_OR_PRELIM  /* NOR Options */
+#define CONFIG_SYS_BR1_PRELIM  CONFIG_SYS_NAND_BR_PRELIM
+#define CONFIG_SYS_OR1_PRELIM  CONFIG_SYS_NAND_OR_PRELIM /* NAND Options */
+
+/* Serial Port */
+#define CONFIG_CONS_INDEX              1
+#undef CONFIG_SERIAL_SOFTWARE_FIFO
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE    1
+#define CONFIG_SYS_NS16550_CLK         get_bus_freq(0)
+
+#define CONFIG_SYS_BAUDRATE_TABLE      \
+       {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200}
+
+#define CONFIG_SYS_NS16550_COM1        (CONFIG_SYS_CCSRBAR + 0x4500)
+#define CONFIG_SYS_NS16550_COM2        (CONFIG_SYS_CCSRBAR + 0x4600)
+
+/* Use the HUSH parser */
+#define CONFIG_SYS_HUSH_PARSER
+
+/*
+ * Pass open firmware flat tree
+ */
+#define CONFIG_OF_LIBFDT
+#define CONFIG_OF_BOARD_SETUP
+#define CONFIG_OF_STDOUT_VIA_ALIAS
+
+/* new uImage format support */
+#define CONFIG_FIT
+#define CONFIG_FIT_VERBOSE     /* enable fit_format_{error,warning}() */
+
+/* I2C */
+#define CONFIG_FSL_I2C         /* Use FSL common I2C driver */
+#define CONFIG_HARD_I2C                /* I2C with hardware support */
+#define CONFIG_I2C_MULTI_BUS
+#define CONFIG_SYS_I2C_SPEED   400000  /* I2C speed and slave address */
+#define CONFIG_SYS_I2C_SLAVE           0x7F
+#define CONFIG_SYS_I2C_OFFSET          0x3000
+#define CONFIG_SYS_I2C2_OFFSET         0x3100
+
+/*
+ * I2C2 EEPROM
+ */
+#define CONFIG_ID_EEPROM
+#ifdef CONFIG_ID_EEPROM
+#define CONFIG_SYS_I2C_EEPROM_NXID
+#endif
+#define CONFIG_SYS_I2C_EEPROM_ADDR             0x50
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN         1
+#define CONFIG_SYS_EEPROM_BUS_NUM              0
+
+#define CONFIG_CMD_I2C
+
+/*
+ * General PCI
+ * Memory space is mapped 1-1, but I/O space must start from 0.
+ */
+
+/* controller 3, Slot 1, tgtid 3, Base address b000 */
+#define CONFIG_SYS_PCIE3_NAME          "Slot 3"
+#define CONFIG_SYS_PCIE3_MEM_VIRT      0x80000000
+#define CONFIG_SYS_PCIE3_MEM_BUS       0x80000000
+#define CONFIG_SYS_PCIE3_MEM_PHYS      0x80000000
+#define CONFIG_SYS_PCIE3_MEM_SIZE      0x20000000      /* 512M */
+#define CONFIG_SYS_PCIE3_IO_VIRT       0xffc00000
+#define CONFIG_SYS_PCIE3_IO_BUS                0x00000000
+#define CONFIG_SYS_PCIE3_IO_PHYS       0xffc00000
+#define CONFIG_SYS_PCIE3_IO_SIZE       0x00010000      /* 64k */
+
+/* controller 2, direct to uli, tgtid 2, Base address 9000 */
+#define CONFIG_SYS_PCIE2_NAME          "Slot 2"
+#define CONFIG_SYS_PCIE2_MEM_VIRT      0xa0000000
+#define CONFIG_SYS_PCIE2_MEM_BUS       0xa0000000
+#define CONFIG_SYS_PCIE2_MEM_PHYS      0xa0000000
+#define CONFIG_SYS_PCIE2_MEM_SIZE      0x20000000      /* 512M */
+#define CONFIG_SYS_PCIE2_IO_VIRT       0xffc10000
+#define CONFIG_SYS_PCIE2_IO_BUS                0x00000000
+#define CONFIG_SYS_PCIE2_IO_PHYS       0xffc10000
+#define CONFIG_SYS_PCIE2_IO_SIZE       0x00010000      /* 64k */
+
+/* controller 1, Slot 2, tgtid 1, Base address a000 */
+#define CONFIG_SYS_PCIE1_NAME          "Slot 1"
+#define CONFIG_SYS_PCIE1_MEM_VIRT      0xc0000000
+#define CONFIG_SYS_PCIE1_MEM_BUS       0xc0000000
+#define CONFIG_SYS_PCIE1_MEM_PHYS      0xc0000000
+#define CONFIG_SYS_PCIE1_MEM_SIZE      0x20000000      /* 512M */
+#define CONFIG_SYS_PCIE1_IO_VIRT       0xffc20000
+#define CONFIG_SYS_PCIE1_IO_BUS                0x00000000
+#define CONFIG_SYS_PCIE1_IO_PHYS       0xffc20000
+#define CONFIG_SYS_PCIE1_IO_SIZE       0x00010000      /* 64k */
+
+#if defined(CONFIG_PCI)
+#define CONFIG_E1000           /* Defind e1000 pci Ethernet card */
+#define CONFIG_PCI_PNP         /* do pci plug-and-play */
+#define CONFIG_PCI_SCAN_SHOW   /* show pci devices on startup */
+#endif /* CONFIG_PCI */
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_ENV_IS_IN_FLASH
+#if CONFIG_SYS_MONITOR_BASE > 0xfff80000
+#define CONFIG_ENV_ADDR                0xfff80000
+#else
+#define CONFIG_ENV_ADDR                (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SECT_SIZE)
+#endif
+#define CONFIG_ENV_SIZE                0x2000
+#define CONFIG_ENV_SECT_SIZE   0x20000 /* 128K (one sector) */
+
+#define CONFIG_LOADS_ECHO              /* echo on for serial download */
+#define CONFIG_SYS_LOADS_BAUD_CHANGE   /* allow baudrate change */
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_IRQ
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_SETEXPR
+#define CONFIG_CMD_REGINFO
+
+#if defined(CONFIG_PCI)
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_NET
+#endif
+
+/*
+ * USB
+ */
+#define CONFIG_HAS_FSL_DR_USB
+#ifdef CONFIG_HAS_FSL_DR_USB
+#define CONFIG_USB_EHCI
+
+#ifdef CONFIG_USB_EHCI
+#define CONFIG_CMD_USB
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+#define CONFIG_USB_EHCI_FSL
+#define CONFIG_USB_STORAGE
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+#endif
+#endif
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP                    /* undef to save memory */
+#define CONFIG_CMDLINE_EDITING         /* Command-line editing */
+#define CONFIG_SYS_LOAD_ADDR   0x2000000       /* default load address */
+#define CONFIG_SYS_PROMPT      "=> "           /* Monitor Command Prompt */
+#if defined(CONFIG_CMD_KGDB)
+#define CONFIG_SYS_CBSIZE      1024            /* Console I/O Buffer Size */
+#else
+#define CONFIG_SYS_CBSIZE      256             /* Console I/O Buffer Size */
+#endif
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT)+16)
+#define CONFIG_SYS_MAXARGS     16              /* max number of command args */
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE    CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_HZ  1000            /* decrementer freq: 1ms ticks */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 64 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CONFIG_SYS_BOOTMAPSZ   (64 << 20)   /* Initial Memory map for Linux*/
+#define CONFIG_SYS_BOOTM_LEN   (64 << 20)   /* Increase max gunzip size */
+
+/*
+ * Environment Configuration
+ */
+#define CONFIG_BOOTFILE                "uImage"
+#define CONFIG_UBOOTPATH       (u-boot.bin) /* U-Boot image on TFTP server */
+
+/* default location for tftp and bootm */
+#define CONFIG_LOADADDR                1000000
+
+#define CONFIG_BOOTDELAY -1    /* -1 disables auto-boot */
+
+#define CONFIG_BAUDRATE        115200
+
+/* Qman/Bman */
+#define CONFIG_SYS_DPAA_QBMAN          /* support Q/Bman */
+#define CONFIG_SYS_QMAN_MEM_BASE       0xff000000
+#define CONFIG_SYS_QMAN_MEM_PHYS       CONFIG_SYS_QMAN_MEM_BASE
+#define CONFIG_SYS_QMAN_MEM_SIZE       0x00200000
+#define CONFIG_SYS_BMAN_MEM_BASE       0xff200000
+#define CONFIG_SYS_BMAN_MEM_PHYS       CONFIG_SYS_BMAN_MEM_BASE
+#define CONFIG_SYS_BMAN_MEM_SIZE       0x00200000
+
+/* For FM */
+#define CONFIG_SYS_DPAA_FMAN
+#define CONFIG_PHY_GIGE                /* Include GbE speed/duplex detection */
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+#define CONFIG_FMAN_ENET
+#define CONFIG_PHY_ATHEROS
+#endif
+
+/* Default address of microcode for the Linux Fman driver */
+/* QE microcode/firmware address */
+#define CONFIG_SYS_QE_FMAN_FW_IN_NOR
+#define CONFIG_SYS_QE_FMAN_FW_ADDR     0xeff40000
+#define CONFIG_SYS_QE_FMAN_FW_LENGTH   0x10000
+#define CONFIG_SYS_FDT_PAD             (0x3000 + CONFIG_SYS_QE_FMAN_FW_LENGTH)
+
+#ifdef CONFIG_FMAN_ENET
+#define CONFIG_SYS_FM1_DTSEC1_PHY_ADDR 0x1
+#define CONFIG_SYS_FM1_DTSEC2_PHY_ADDR 0x2
+
+#define CONFIG_SYS_TBIPA_VALUE 8
+#define CONFIG_MII             /* MII PHY management */
+#define CONFIG_ETHPRIME                "FM1@DTSEC1"
+#endif
+
+#define CONFIG_EXTRA_ENV_SETTINGS      \
+       "hwconfig=usb1:dr_mode=host,phy_type=ulpi\0"
+
+#endif /* __CONFIG_H */
index 9cd3a7cb34d7118233422a6f6425d11457298556..4ea87173682f1aa9b9b9147917be2d76e254b2e4 100644 (file)
@@ -77,6 +77,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1                   /* SRIO port 1 */
 #define CONFIG_SRIO2                   /* SRIO port 2 */
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_DPAA_RMAN           /* RMan */
 
 #define CONFIG_FSL_LAW                 /* Use common FSL init code */
index ce8f9b0b2eba190c0e11a41bed6a4c054945fc89..dd2b9c34e4f3152d75f8fd396cca086f36cb4656 100644 (file)
@@ -40,7 +40,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1                   /* SRIO port 1 */
 #define CONFIG_SRIO2                   /* SRIO port 2 */
-
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_ICS307_REFCLK_HZ                25000000  /* ICS307 ref clk freq */
 
 #include "corenet_ds.h"
index 53979dddf26d10c7e69da2e4418f873dfc6bb29f..48acee4993f1f55fbf6049d9db01dd7038bbb71c 100644 (file)
@@ -36,7 +36,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1                   /* SRIO port 1 */
 #define CONFIG_SRIO2                   /* SRIO port 2 */
-
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_ICS307_REFCLK_HZ                33333000  /* ICS307 ref clk freq */
 
 #include "corenet_ds.h"
index 778230d3356c13ced57cc25bde618650f6c9c190..d1e27c42d4c9667b268a4f36b140dada5ed5f8f4 100644 (file)
@@ -41,7 +41,7 @@
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1                   /* SRIO port 1 */
 #define CONFIG_SRIO2                   /* SRIO port 2 */
-
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_ICS307_REFCLK_HZ                25000000  /* ICS307 ref clk freq */
 
 #include "corenet_ds.h"
index e9af8256631c301da586d48a02a4103320092760..8f29229cdca31e67123fb6794e6f480598df0f54 100644 (file)
 #define CONFIG_SPL_BSS_MAX_SIZE                (64 << 10)
 
 #define CONFIG_SPL_OS_BOOT
+#define CONFIG_SPL_ENV_SUPPORT
 /* Place patched DT blob (fdt) at this address */
 #define CONFIG_SYS_SPL_ARGS_ADDR       0x01800000
 
index 7cb10fb01e01da0e0ca35a7c22e4d776d4b2e1d9..381bcdda0d00fc5e0f25ce259cce6f38ec73c9df 100644 (file)
@@ -72,7 +72,7 @@
 #define CONFIG_SYS_MAX_RAM_SIZE                0x20000000
 
 /*
- * DDR Controller Configuration XXX TODO
+ * DDR Controller Configuration
  *
  * SYS_CFG:
  *     [31:31] MDDRC Soft Reset:       Diabled
 
 /*
  * CS related parameters
- * TODO document these
  */
 /* CS0 Flash */
 #define CONFIG_SYS_CS0_CFG             0x00031110
 #endif
 
 #define CONFIG_BAUDRATE                        115200  /* ... at 115200 bps */
-#define CONFIG_SYS_BAUDRATE_TABLE  \
-       {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 115200}
 
 #define CONSOLE_FIFO_TX_SIZE           FIFOC_PSC3_TX_SIZE
 #define CONSOLE_FIFO_TX_ADDR           FIFOC_PSC3_TX_ADDR
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_TIMESTAMP
 
-#define CONFIG_HOSTNAME                ac14xx
-#define CONFIG_BOOTFILE                "ac14xx/uImage"
-#define CONFIG_ROOTPATH                "/opt/eldk/ppc_6xx"
-
 /* default load addr for tftp and bootm */
 #define CONFIG_LOADADDR                400000
 
 #define CONFIG_BOOTDELAY       2       /* -1 disables auto-boot */
 
-/* XXX TODO need to specify the builtin environment */
+/* the builtin environment and standard greeting */
 #define CONFIG_PREBOOT "echo;" \
        "echo Type \\\"run flash_nfs\\\" to mount root filesystem over NFS;" \
        "echo"
 
 #define CONFIG_EXTRA_ENV_SETTINGS_DEVEL                                        \
-       "muster_nr=00\0"                                                \
+       "muster_nr=-00\0"                                               \
        "fromram=run ramargs addip addtty; "                            \
-               "tftp ${fdt_addr_r} k6m2/ac14xx.dtb-${muster_nr}; "     \
-               "tftp ${kernel_addr_r} k6m2/uImage-${muster_nr}; "      \
-               "tftp ${ramdisk_addr_r} k6m2/uFS-${muster_nr}; "        \
+               "tftp ${fdt_addr_r} ac14xx/ac14xx.dtb${muster_nr}; "    \
+               "tftp ${kernel_addr_r} ac14xx/uImage${muster_nr}; "     \
+               "tftp ${ramdisk_addr_r} ac14xx/uFS${muster_nr}; "       \
                "bootm ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}\0" \
        "fromnfs=run nfsargs addip addtty; "                            \
-               "tftp ${fdt_addr_r} k6m2/ac14xx.dtb-${muster_nr}; "     \
-               "tftp ${kernel_addr_r} k6m2/uImage-${muster_nr}; "      \
+               "tftp ${fdt_addr_r} ac14xx/ac14xx.dtb${muster_nr}; "    \
+               "tftp ${kernel_addr_r} ac14xx/uImage${muster_nr}; "     \
                "bootm ${kernel_addr_r} - ${fdt_addr_r}\0"              \
        "fromflash=run nfsargs addip addtty; "                          \
                "bootm fc020000 - fc000000\0"                           \
        "u-boot=ac14xx/u-boot.bin\0"                                    \
        "bootfile=ac14xx/uImage\0"                                      \
        "fdtfile=ac14xx/ac14xx.dtb\0"                                   \
-       "rootpath=/opt/eldk/ppc_6xx\n"                                  \
        "netdev=eth0\0"                                                 \
        "consdev=ttyPSC0\0"                                             \
        "hostname=ac14xx\0"                                             \
        "nfsargs=setenv bootargs root=/dev/nfs rw "                     \
-               "nfsroot=${serverip}:${rootpath}-${muster_nr}\0"        \
+               "nfsroot=${serverip}:${rootpath}${muster_nr}\0" \
        "ramargs=setenv bootargs root=/dev/ram rw\0"                    \
        "addip=setenv bootargs ${bootargs} "                            \
                "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"      \
 
 #define CONFIG_BOOTCOMMAND     "run production"
 
+#define CONFIG_ARP_TIMEOUT     200UL
+
 #define CONFIG_FIT             1
 #define CONFIG_OF_LIBFDT       1
 #define CONFIG_OF_BOARD_SETUP  1
index 737e19ee6fec2761dc8fbb738c039655536f2d74..c5a6d4b315124fbd560d6dbf700441028de93c03 100644 (file)
@@ -60,7 +60,7 @@
        "rdaddr=0x81000000\0" \
        "bootdir=/boot\0" \
        "bootfile=uImage\0" \
-       "fdtfile=\0" \
+       "fdtfile=undefined\0" \
        "console=ttyO0,115200n8\0" \
        "optargs=\0" \
        "mtdids=" MTDIDS_DEFAULT "\0" \
                "if test $board_name = A33515BB; then " \
                        "setenv fdtfile am335x-evm.dtb; fi; " \
                "if test $board_name = A335X_SK; then " \
-                       "setenv fdtfile am335x-evmsk.dtb; fi\0" \
-
+                       "setenv fdtfile am335x-evmsk.dtb; fi; " \
+               "if test $fdtfile = undefined; then " \
+                       "echo WARNING: Could not determine device tree to use; fi; \0"
 #endif
 
 #define CONFIG_BOOTCOMMAND \
 #define CONFIG_SPL_GPIO_SUPPORT
 #define CONFIG_SPL_YMODEM_SUPPORT
 #define CONFIG_SPL_NET_SUPPORT
+#define CONFIG_SPL_ENV_SUPPORT
 #define CONFIG_SPL_NET_VCI_STRING      "AM335x U-Boot SPL"
 #define CONFIG_SPL_ETH_SUPPORT
 #define CONFIG_SPL_SPI_SUPPORT
index 8d2673dacbc6e1ab9b91cfa561df7a38ec4b0243..b4b1c319606828f037e823f1cb701649f533b4bf 100644 (file)
 #define CONFIG_DOS_PARTITION
 #endif
 
+/* Ethernet */
+#define CONFIG_KS8851_MLL
+#define CONFIG_KS8851_MLL_BASEADDR     0x30000000 /* use NCS2 */
+
 #define CONFIG_SYS_LOAD_ADDR           0x22000000 /* load address */
 
 #define CONFIG_SYS_MEMTEST_START       CONFIG_SYS_SDRAM_BASE
index 2fefdc80db68e7ea5b72d6493c32ef8add701c44..288ef8df74f9493c23d6af67aac3797f079438f5 100644 (file)
  */
 #include <config_cmd_default.h>
 
+#define CONFIG_TRACE
+#define CONFIG_CMD_TRACE
+#define CONFIG_TRACE_BUFFER_SIZE       (16 << 20)
+#define CONFIG_TRACE_EARLY_SIZE                (8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR                0x01400000
+
 #define CONFIG_CMD_BDI
 #define CONFIG_CMD_BOOTD
 #define CONFIG_CMD_CONSOLE
index 0eea28c80a6dd9b8bf08bc487ab93e647a74fd42..c11f005535d03916edc1b646dd3f8452273acfaf 100644 (file)
@@ -41,4 +41,7 @@
 #define CONFIG_BAUDRATE                        115200
 
 #define CONFIG_SYS_OMAP_ABE_SYSCK
+
+#define CONSOLEDEV             "ttyO0"
+
 #endif /* __CONFIG_DRA7XX_EVM_H */
index 41d6cf9d15f7fd50ad3f087244bea6f6d23f57e8..e2a096b6439fc818b357a8e1730a5943b80500dd 100644 (file)
 #define CONFIG_OF_CONTROL
 #define CONFIG_OF_SEPARATE
 
+/* Allow tracing to be enabled */
+#define CONFIG_TRACE
+#define CONFIG_CMD_TRACE
+#define CONFIG_TRACE_BUFFER_SIZE       (16 << 20)
+#define CONFIG_TRACE_EARLY_SIZE                (8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR                0x50000000
+
 /* Keep L2 Cache Disabled */
 #define CONFIG_SYS_DCACHE_OFF
 
 #define CONFIG_BAUDRATE                        115200
 #define EXYNOS5_DEFAULT_UART_OFFSET    0x010000
 
+/* Enable keyboard */
+#define CONFIG_CROS_EC         /* CROS_EC protocol */
+#define CONFIG_CROS_EC_SPI             /* Support CROS_EC over SPI */
+#define CONFIG_CROS_EC_I2C             /* Support CROS_EC over I2C */
+#define CONFIG_CROS_EC_KEYB    /* CROS_EC keyboard input */
+#define CONFIG_CMD_CROS_EC
+#define CONFIG_KEYBOARD
+
 /* Console configuration */
 #define CONFIG_CONSOLE_MUX
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
 #define EXYNOS_DEVICE_SETTINGS \
-               "stdin=serial\0" \
+               "stdin=serial,cros-ec-keyb\0" \
                "stdout=serial,lcd\0" \
                "stderr=serial,lcd\0"
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
        EXYNOS_DEVICE_SETTINGS
 
-#define TZPC_BASE_OFFSET               0x10000
-
 /* SD/MMC configuration */
 #define CONFIG_GENERIC_MMC
 #define CONFIG_MMC
 #define CONFIG_SDHCI
 #define CONFIG_S5P_SDHCI
+#define CONFIG_DWMMC
+#define CONFIG_EXYNOS_DWMMC
+#define CONFIG_SUPPORT_EMMC_BOOT
+
 
 #define CONFIG_BOARD_EARLY_INIT_F
 
 #define SPI_FLASH_UBOOT_POS            (CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE)
 
 #define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+#define CONFIG_CMD_PART
+#define CONFIG_PARTITION_UUIDS
+
 
 #define CONFIG_IRAM_STACK      0x02050000
 
 #define CONFIG_CMD_SF
 #define CONFIG_CMD_SPI
 #define CONFIG_SPI_FLASH_WINBOND
+#define CONFIG_SPI_FLASH_GIGADEVICE
 #define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
 #define CONFIG_SF_DEFAULT_SPEED                50000000
 #define EXYNOS5_SPI_NUM_CONTROLLERS    5
index 09b5798d57896af2fc768c741cc4f552e12b7cc6..e2b3b21182f32ab8229bd84fc125b79d5f944b3b 100644 (file)
 #define CONFIG_SYS_PROMPT              "ns2> "
 #endif
 
+/*
+ * Enable platform initialisation via misc_init_r() function
+ */
+#define CONFIG_MISC_INIT_R
+
 /*
  * Ethernet Driver configuration
  */
 #ifdef CONFIG_CMD_NET
-#define CONFIG_MISC_INIT_R /* Call misc_init_r() to initialize MAC address */
 #define CONFIG_MVGBE_PORTS             {1, 0} /* enable port 0 only */
 #define CONFIG_NETCONSOLE
 #endif
 #define CONFIG_SYS_I2C_EEPROM_ADDR             0x50
 #define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS      4 /* 16-byte page size */
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN         1 /* 8-bit device address */
+#if defined(CONFIG_NET2BIG_V2)
+#define CONFIG_SYS_I2C_G762_ADDR               0x3e
+#endif
 #endif /* CONFIG_CMD_I2C */
 
 /*
index 3e5d36b21e0d552b031df9dd8ad1906d6036eeba..2fa4382c3ef54a3f39102a26eb717afcabd1bfe3 100644 (file)
        "console=ttyO2,115200n8\0" \
        "fdt_high=0xffffffff\0" \
        "fdtaddr=0x80f80000\0" \
+       "fdtfile=undefined\0" \
        "bootpart=0:2\0" \
        "bootdir=/boot\0" \
        "bootfile=zImage\0" \
                        "setenv fdtfile omap4-sdp.dtb; fi; " \
                "if test $board_name = panda; then " \
                        "setenv fdtfile omap4-panda.dtb; fi;" \
+               "if test $board_name = panda-a4; then " \
+                       "setenv fdtfile omap4-panda-a4.dtb; fi;" \
                "if test $board_name = panda-es; then " \
-                       "setenv fdtfile omap4-panda-es.dtb; fi; \0" \
+                       "setenv fdtfile omap4-panda-es.dtb; fi;" \
+               "if test $fdtfile = undefined; then " \
+                       "echo WARNING: Could not determine device tree to use; fi; \0" \
        "loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}\0" \
 
 #define CONFIG_BOOTCOMMAND \
index ddf2ad4fc2918307fe6489ef8788a36c057abc1d..b87ee422869246e3cabe68eba8d6011f5566104a 100644 (file)
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
        "loadaddr=0x82000000\0" \
-       "console=ttyO2,115200n8\0" \
+       "console=" CONSOLEDEV ",115200n8\0" \
        "fdt_high=0xffffffff\0" \
        "fdtaddr=0x80f80000\0" \
+       "fdtfile=undefined\0" \
        "bootpart=0:2\0" \
        "bootdir=/boot\0" \
        "bootfile=zImage\0" \
                "bootz ${loadaddr} - ${fdtaddr}\0" \
        "findfdt="\
                "if test $board_name = omap5_uevm; then " \
-                       "setenv fdtfile omap5-uevm.dtb; fi;\0 " \
+                       "setenv fdtfile omap5-uevm.dtb; fi; " \
+               "if test $board_name = dra7xx; then " \
+                       "setenv fdtfile dra7-evm.dtb; fi;" \
+               "if test $fdtfile = undefined; then " \
+                       "echo WARNING: Could not determine device tree to use; fi; \0" \
        "loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile};\0" \
 
 #define CONFIG_BOOTCOMMAND \
index dea05bc911cf6970ebd8197921e72625dbed0f37..46dacc207442c03d843794d4f5c6c8cf8af3b18e 100644 (file)
@@ -53,7 +53,9 @@
 #define CONFIG_PARTITION_UUIDS
 #define CONFIG_CMD_PART
 
-#define CONFIG_SYS_PROMPT              "OMAP5430 EVM # "
+#define CONFIG_SYS_PROMPT              "OMAP5432 uEVM # "
+
+#define CONSOLEDEV             "ttyO2"
 
 #define CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC       16296
 #endif /* __CONFIG_OMAP5_EVM_H */
index ff2b24d97f4305f923f5c36dbf6c3f3b32f49913..e179911d0c3baf59f1cf09d12ed42b0000f28975 100644 (file)
@@ -96,6 +96,8 @@
 #define CONFIG_SPL
 #define COPY_BL2_FNPTR_ADDR    0x02020030
 
+#define CONFIG_SPL_TEXT_BASE   0x02021410
+
 #define CONFIG_BOOTCOMMAND     "fatload mmc 0 40007000 uImage; bootm 40007000"
 
 /* Miscellaneous configurable options */
index 2ecd1050cf688d8e865995a812c1df67f14e7288..9b16c47820fb1bf24caacb06a25e776e4a67deea 100644 (file)
 #define CONFIG_SPL_GPIO_SUPPORT
 #define CONFIG_SPL_YMODEM_SUPPORT
 #define CONFIG_SPL_NET_SUPPORT
+#define CONFIG_SPL_ENV_SUPPORT
 #define CONFIG_SPL_NET_VCI_STRING      "pcm051 U-Boot SPL"
 #define CONFIG_SPL_ETH_SUPPORT
 #define CONFIG_SPL_SPI_SUPPORT
index 788207d0076f3ce2094bde7a8424e4e0872fe4a7..98dd083302724fe5592bb9bf78c83d1be7cc2055 100644 (file)
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#ifdef FTRACE
+#define CONFIG_TRACE
+#define CONFIG_CMD_TRACE
+#define CONFIG_TRACE_BUFFER_SIZE       (16 << 20)
+#define CONFIG_TRACE_EARLY_SIZE                (8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR                0x00100000
+
+#endif
+
+#define CONFIG_BOOTSTAGE
+#define CONFIG_BOOTSTAGE_REPORT
+
 /* Number of bits in a C 'long' on this architecture */
 #define CONFIG_SANDBOX_BITS_PER_LONG   64
 
@@ -30,6 +43,8 @@
 #define CONFIG_OF_LIBFDT
 #define CONFIG_LMB
 #define CONFIG_FIT
+#define CONFIG_FIT_SIGNATURE
+#define CONFIG_RSA
 #define CONFIG_CMD_FDT
 
 #define CONFIG_FS_FAT
index b796b46a7f6b8f39ad65cf309477df3bd66b9024..5e430660f12439de595c6af35e6fcc8d0abe66f5 100644 (file)
@@ -95,6 +95,8 @@
 #define CONFIG_SPL
 #define COPY_BL2_FNPTR_ADDR    0x00002488
 
+#define CONFIG_SPL_TEXT_BASE   0x02021410
+
 #define CONFIG_BOOTCOMMAND     "fatload mmc 0 40007000 uImage; bootm 40007000"
 
 /* Miscellaneous configurable options */
index aa90249f0f9e9a04277fc230bcb7ba9d1b32c590..92b2179ca7f5ad8693dd1df24f3432c9e13c1a3d 100644 (file)
 #define CONFIG_PBLRCW_CONFIG $(SRCTREE)/board/freescale/t4qds/t4_rcw.cfg
 #endif
 
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+/* Set 1M boot space */
+#define CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR (CONFIG_SYS_TEXT_BASE & 0xfff00000)
+#define CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS \
+               (0x300000000ull | CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR)
+#define CONFIG_RESET_VECTOR_ADDRESS 0xfffffffc
+#define CONFIG_SYS_NO_FLASH
+#endif
+
 #define CONFIG_CMD_REGINFO
 
 /* High Level Configuration Options */
 #define CONFIG_SYS_SRIO
 #define CONFIG_SRIO1                   /* SRIO port 1 */
 #define CONFIG_SRIO2                   /* SRIO port 2 */
+#define CONFIG_SRIO_PCIE_BOOT_MASTER
 
 #define CONFIG_FSL_LAW                 /* Use common FSL init code */
 
 #define CONFIG_ENV_OVERWRITE
 
 #ifdef CONFIG_SYS_NO_FLASH
+#if !defined(CONFIG_SRIO_PCIE_BOOT_SLAVE) && !defined(CONFIG_RAMBOOT_PBL)
 #define CONFIG_ENV_IS_NOWHERE
+#endif
 #else
 #define CONFIG_FLASH_CFI_DRIVER
 #define CONFIG_SYS_FLASH_CFI
 #define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
 #endif
 
-#ifndef CONFIG_SYS_NO_FLASH
 #if defined(CONFIG_SPIFLASH)
 #define CONFIG_SYS_EXTRA_ENV_RELOC
 #define CONFIG_ENV_IS_IN_SPI_FLASH
 #define CONFIG_ENV_IS_IN_NAND
 #define CONFIG_ENV_SIZE                        CONFIG_SYS_NAND_BLOCK_SIZE
 #define CONFIG_ENV_OFFSET              (5 * CONFIG_SYS_NAND_BLOCK_SIZE)
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+#define CONFIG_ENV_IS_IN_REMOTE
+#define CONFIG_ENV_ADDR                0xffe20000
+#define CONFIG_ENV_SIZE                0x2000
+#elif defined(CONFIG_ENV_IS_NOWHERE)
+#define CONFIG_ENV_SIZE                0x2000
 #else
 #define CONFIG_ENV_IS_IN_FLASH
 #define CONFIG_ENV_ADDR                (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SECT_SIZE)
 #define CONFIG_ENV_SIZE                0x2000
 #define CONFIG_ENV_SECT_SIZE   0x20000 /* 128K (one sector) */
 #endif
-#else /* CONFIG_SYS_NO_FLASH */
-#define CONFIG_ENV_SIZE                0x2000
-#define CONFIG_ENV_SECT_SIZE   0x20000 /* 128K (one sector) */
-#endif
-
-
 
 #define CONFIG_SYS_CLK_FREQ    get_board_sys_clk()
 #define CONFIG_DDR_CLK_FREQ    get_board_ddr_clk()
@@ -633,6 +644,16 @@ unsigned long get_board_ddr_clk(void);
 #elif defined(CONFIG_NAND)
 #define CONFIG_SYS_QE_FMAN_FW_IN_NAND
 #define CONFIG_SYS_QE_FMAN_FW_ADDR     (6 * CONFIG_SYS_NAND_BLOCK_SIZE)
+#elif defined(CONFIG_SRIO_PCIE_BOOT_SLAVE)
+/*
+ * Slave has no ucode locally, it can fetch this from remote. When implementing
+ * in two corenet boards, slave's ucode could be stored in master's memory
+ * space, the address can be mapped from slave TLB->slave LAW->
+ * slave SRIO or PCIE outbound window->master inbound window->
+ * master LAW->the ucode address in master's memory space.
+ */
+#define CONFIG_SYS_QE_FMAN_FW_IN_REMOTE
+#define CONFIG_SYS_QE_FMAN_FW_ADDR     0xFFE00000
 #else
 #define CONFIG_SYS_QE_FMAN_FW_IN_NOR
 #define CONFIG_SYS_QE_FMAN_FW_ADDR             0xEFF40000
index fd58558bebced3b8f433b270ebbce3ccbed76e34..c70838b9157d97bee9885316e032de0a6d783b14 100644 (file)
 
 #define CONFIG_DFU_ALT \
        "u-boot mmc 80 400;" \
-       "uImage ext4 0 2\0" \
+       "uImage ext4 0 2;" \
+       "exynos4210-trats.dtb ext4 0 2\0"
 
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_SYS_CONSOLE_INFO_QUIET
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
        "bootk=" \
-               "run loaduimage; bootm 0x40007FC0\0" \
+               "run loaddtb; run loaduimage; bootm 0x40007FC0 - ${fdtaddr}\0" \
        "updatemmc=" \
                "mmc boot 0 1 1 1; mmc write 0 0x42008000 0 0x200;" \
                "mmc boot 0 1 1 0\0" \
        "mmcboot=" \
                "setenv bootargs root=/dev/mmcblk${mmcdev}p${mmcrootpart} " \
                "${lpj} rootwait ${console} ${meminfo} ${opts} ${lcdinfo}; " \
-               "run loaduimage; bootm 0x40007FC0\0" \
+               "run loaddtb; run loaduimage; bootm 0x40007FC0 - ${fdtaddr}\0" \
        "bootchart=setenv opts init=/sbin/bootchartd; run bootcmd\0" \
        "boottrace=setenv opts initcall_debug; run bootcmd\0" \
        "mmcoops=mmc read 0 0x40000000 0x40 8; md 0x40000000 0x400\0" \
        "nfsroot=/nfsroot/arm\0" \
        "bootblock=" CONFIG_BOOTBLOCK "\0" \
        "loaduimage=ext4load mmc ${mmcdev}:${mmcbootpart} 0x40007FC0 uImage\0" \
+       "loaddtb=ext4load mmc ${mmcdev}:${mmcbootpart} ${fdtaddr}" \
+               "${fdtfile}\0" \
        "mmcdev=0\0" \
        "mmcbootpart=2\0" \
        "mmcrootpart=5\0" \
                   " /${splfile} ${spl_imgaddr} ${spl_imgsize};" \
                   "setenv spl_imgsize;" \
                   "setenv spl_imgaddr;" \
-                  "setenv spl_addr_tmp;\0"
+                  "setenv spl_addr_tmp;\0" \
+       "fdtaddr=40800000\0" \
+       "fdtfile=exynos4210-trats.dtb\0"
+
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP            /* undef to save memory */
 #define CONFIG_USB_GADGET_MASS_STORAGE
 #endif
 
+/* Pass open firmware flat tree */
+#define CONFIG_OF_LIBFDT    1
+
 #endif /* __CONFIG_H */
diff --git a/include/cros_ec.h b/include/cros_ec.h
new file mode 100644 (file)
index 0000000..335d5b4
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * Chromium OS cros_ec driver
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _CROS_EC_H
+#define _CROS_EC_H
+
+#include <linux/compiler.h>
+#include <ec_commands.h>
+#include <fdtdec.h>
+#include <cros_ec_message.h>
+
+/* Which interface is the device on? */
+enum cros_ec_interface_t {
+       CROS_EC_IF_NONE,
+       CROS_EC_IF_SPI,
+       CROS_EC_IF_I2C,
+       CROS_EC_IF_LPC, /* Intel Low Pin Count interface */
+};
+
+/* Our configuration information */
+struct cros_ec_dev {
+       enum cros_ec_interface_t interface;
+       struct spi_slave *spi;          /* Our SPI slave, if using SPI */
+       int node;                       /* Our node */
+       int parent_node;                /* Our parent node (interface) */
+       unsigned int cs;                /* Our chip select */
+       unsigned int addr;              /* Device address (for I2C) */
+       unsigned int bus_num;           /* Bus number (for I2C) */
+       unsigned int max_frequency;     /* Maximum interface frequency */
+       struct fdt_gpio_state ec_int;   /* GPIO used as EC interrupt line */
+       int cmd_version_is_supported;   /* Device supports command versions */
+       int optimise_flash_write;       /* Don't write erased flash blocks */
+
+       /*
+        * These two buffers will always be dword-aligned and include enough
+        * space for up to 7 word-alignment bytes also, so we can ensure that
+        * the body of the message is always dword-aligned (64-bit).
+        *
+        * We use this alignment to keep ARM and x86 happy. Probably word
+        * alignment would be OK, there might be a small performance advantage
+        * to using dword.
+        */
+       uint8_t din[ALIGN(MSG_BYTES + sizeof(int64_t), sizeof(int64_t))]
+               __aligned(sizeof(int64_t));
+       uint8_t dout[ALIGN(MSG_BYTES + sizeof(int64_t), sizeof(int64_t))]
+               __aligned(sizeof(int64_t));
+};
+
+/*
+ * Hard-code the number of columns we happen to know we have right now.  It
+ * would be more correct to call cros_ec_info() at startup and determine the
+ * actual number of keyboard cols from there.
+ */
+#define CROS_EC_KEYSCAN_COLS 13
+
+/* Information returned by a key scan */
+struct mbkp_keyscan {
+       uint8_t data[CROS_EC_KEYSCAN_COLS];
+};
+
+/**
+ * Read the ID of the CROS-EC device
+ *
+ * The ID is a string identifying the CROS-EC device.
+ *
+ * @param dev          CROS-EC device
+ * @param id           Place to put the ID
+ * @param maxlen       Maximum length of the ID field
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen);
+
+/**
+ * Read a keyboard scan from the CROS-EC device
+ *
+ * Send a message requesting a keyboard scan and return the result
+ *
+ * @param dev          CROS-EC device
+ * @param scan         Place to put the scan results
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_scan_keyboard(struct cros_ec_dev *dev, struct mbkp_keyscan *scan);
+
+/**
+ * Read which image is currently running on the CROS-EC device.
+ *
+ * @param dev          CROS-EC device
+ * @param image                Destination for image identifier
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_read_current_image(struct cros_ec_dev *dev,
+               enum ec_current_image *image);
+
+/**
+ * Read the hash of the CROS-EC device firmware.
+ *
+ * @param dev          CROS-EC device
+ * @param hash         Destination for hash information
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_read_hash(struct cros_ec_dev *dev,
+               struct ec_response_vboot_hash *hash);
+
+/**
+ * Send a reboot command to the CROS-EC device.
+ *
+ * Note that some reboot commands (such as EC_REBOOT_COLD) also reboot the AP.
+ *
+ * @param dev          CROS-EC device
+ * @param cmd          Reboot command
+ * @param flags         Flags for reboot command (EC_REBOOT_FLAG_*)
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_reboot(struct cros_ec_dev *dev, enum ec_reboot_cmd cmd,
+               uint8_t flags);
+
+/**
+ * Check if the CROS-EC device has an interrupt pending.
+ *
+ * Read the status of the external interrupt connected to the CROS-EC device.
+ * If no external interrupt is configured, this always returns 1.
+ *
+ * @param dev          CROS-EC device
+ * @return 0 if no interrupt is pending
+ */
+int cros_ec_interrupt_pending(struct cros_ec_dev *dev);
+
+enum {
+       CROS_EC_OK,
+       CROS_EC_ERR = 1,
+       CROS_EC_ERR_FDT_DECODE,
+       CROS_EC_ERR_CHECK_VERSION,
+       CROS_EC_ERR_READ_ID,
+       CROS_EC_ERR_DEV_INIT,
+};
+
+/**
+ * Set up the Chromium OS matrix keyboard protocol
+ *
+ * @param blob         Device tree blob containing setup information
+ * @param cros_ecp        Returns pointer to the cros_ec device, or NULL if none
+ * @return 0 if we got an cros_ec device and all is well (or no cros_ec is
+ *     expected), -ve if we should have an cros_ec device but failed to find
+ *     one, or init failed (-CROS_EC_ERR_...).
+ */
+int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp);
+
+/**
+ * Read information about the keyboard matrix
+ *
+ * @param dev          CROS-EC device
+ * @param info         Place to put the info structure
+ */
+int cros_ec_info(struct cros_ec_dev *dev,
+               struct ec_response_cros_ec_info *info);
+
+/**
+ * Read the host event flags
+ *
+ * @param dev          CROS-EC device
+ * @param events_ptr   Destination for event flags.  Not changed on error.
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr);
+
+/**
+ * Clear the specified host event flags
+ *
+ * @param dev          CROS-EC device
+ * @param events       Event flags to clear
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events);
+
+/**
+ * Get/set flash protection
+ *
+ * @param dev          CROS-EC device
+ * @param set_mask     Mask of flags to set; if 0, just retrieves existing
+ *                      protection state without changing it.
+ * @param set_flags    New flag values; only bits in set_mask are applied;
+ *                      ignored if set_mask=0.
+ * @param prot          Destination for updated protection state from EC.
+ * @return 0 if ok, <0 on error
+ */
+int cros_ec_flash_protect(struct cros_ec_dev *dev,
+                      uint32_t set_mask, uint32_t set_flags,
+                      struct ec_response_flash_protect *resp);
+
+
+/**
+ * Run internal tests on the cros_ec interface.
+ *
+ * @param dev          CROS-EC device
+ * @return 0 if ok, <0 if the test failed
+ */
+int cros_ec_test(struct cros_ec_dev *dev);
+
+/**
+ * Update the EC RW copy.
+ *
+ * @param dev          CROS-EC device
+ * @param image                the content to write
+ * @param imafge_size  content length
+ * @return 0 if ok, <0 if the test failed
+ */
+int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
+                        const uint8_t  *image, int image_size);
+
+/**
+ * Return a pointer to the board's CROS-EC device
+ *
+ * This should be implemented by board files.
+ *
+ * @return pointer to CROS-EC device, or NULL if none is available
+ */
+struct cros_ec_dev *board_get_cros_ec_dev(void);
+
+
+/* Internal interfaces */
+int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob);
+int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob);
+int cros_ec_lpc_init(struct cros_ec_dev *dev, const void *blob);
+
+/**
+ * Read information from the fdt for the i2c cros_ec interface
+ *
+ * @param dev          CROS-EC device
+ * @param blob         Device tree blob
+ * @return 0 if ok, -1 if we failed to read all required information
+ */
+int cros_ec_i2c_decode_fdt(struct cros_ec_dev *dev, const void *blob);
+
+/**
+ * Read information from the fdt for the spi cros_ec interface
+ *
+ * @param dev          CROS-EC device
+ * @param blob         Device tree blob
+ * @return 0 if ok, -1 if we failed to read all required information
+ */
+int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob);
+
+/**
+ * Check whether the LPC interface supports new-style commands.
+ *
+ * LPC has its own way of doing this, which involves checking LPC values
+ * visible to the host. Do this, and update dev->cmd_version_is_supported
+ * accordingly.
+ *
+ * @param dev          CROS-EC device to check
+ */
+int cros_ec_lpc_check_version(struct cros_ec_dev *dev);
+
+/**
+ * Send a command to an I2C CROS-EC device and return the reply.
+ *
+ * This rather complicated function deals with sending both old-style and
+ * new-style commands. The old ones have just a command byte and arguments.
+ * The new ones have version, command, arg-len, [args], chksum so are 3 bytes
+ * longer.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev          CROS-EC device
+ * @param cmd          Command to send (EC_CMD_...)
+ * @param cmd_version  Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp          Returns pointer to response data
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+int cros_ec_i2c_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);
+
+/**
+ * Send a command to a LPC CROS-EC device and return the reply.
+ *
+ * The device's internal input/output buffers are used.
+ *
+ * @param dev          CROS-EC device
+ * @param cmd          Command to send (EC_CMD_...)
+ * @param cmd_version  Version of command to send (EC_VER_...)
+ * @param dout          Output data (may be NULL If dout_len=0)
+ * @param dout_len      Size of output data in bytes
+ * @param dinp          Returns pointer to response data
+ * @param din_len       Maximum size of response in bytes
+ * @return number of bytes in response, or -1 on error
+ */
+int cros_ec_lpc_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);
+
+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);
+
+/**
+ * Dump a block of data for a command.
+ *
+ * @param name Name for data (e.g. 'in', 'out')
+ * @param cmd  Command number associated with data, or -1 for none
+ * @param data Data block to dump
+ * @param len  Length of data block to dump
+ */
+void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, int len);
+
+/**
+ * Calculate a simple 8-bit checksum of a data block
+ *
+ * @param data Data block to checksum
+ * @param size Size of data block in bytes
+ * @return checksum value (0 to 255)
+ */
+int cros_ec_calc_checksum(const uint8_t *data, int size);
+
+/**
+ * Decode a flash region parameter
+ *
+ * @param argc Number of params remaining
+ * @param argv List of remaining parameters
+ * @return flash region (EC_FLASH_REGION_...) or -1 on error
+ */
+int cros_ec_decode_region(int argc, char * const argv[]);
+
+int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset,
+               uint32_t size);
+
+/**
+ * Read data from the flash
+ *
+ * Read an arbitrary amount of data from the EC flash, by repeatedly reading
+ * small blocks.
+ *
+ * The offset starts at 0. You can obtain the region information from
+ * cros_ec_flash_offset() to find out where to read for a particular region.
+ *
+ * @param dev          CROS-EC device
+ * @param data         Pointer to data buffer to read into
+ * @param offset       Offset within flash to read from
+ * @param size         Number of bytes to read
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset,
+                   uint32_t size);
+
+/**
+ * Write data to the flash
+ *
+ * Write an arbitrary amount of data to the EC flash, by repeatedly writing
+ * small blocks.
+ *
+ * The offset starts at 0. You can obtain the region information from
+ * cros_ec_flash_offset() to find out where to write for a particular region.
+ *
+ * Attempting to write to the region where the EC is currently running from
+ * will result in an error.
+ *
+ * @param dev          CROS-EC device
+ * @param data         Pointer to data buffer to write
+ * @param offset       Offset within flash to write to.
+ * @param size         Number of bytes to write
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data,
+                    uint32_t offset, uint32_t size);
+
+/**
+ * Obtain position and size of a flash region
+ *
+ * @param dev          CROS-EC device
+ * @param region       Flash region to query
+ * @param offset       Returns offset of flash region in EC flash
+ * @param size         Returns size of flash region
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region,
+                     uint32_t *offset, uint32_t *size);
+
+/**
+ * Read/write VbNvContext from/to a CROS-EC device.
+ *
+ * @param dev          CROS-EC device
+ * @param block                Buffer of VbNvContext to be read/write
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_read_vbnvcontext(struct cros_ec_dev *dev, uint8_t *block);
+int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block);
+
+/**
+ * Read the version information for the EC images
+ *
+ * @param dev          CROS-EC device
+ * @param versionp     This is set to point to the version information
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_read_version(struct cros_ec_dev *dev,
+                      struct ec_response_get_version **versionp);
+
+/**
+ * Read the build information for the EC
+ *
+ * @param dev          CROS-EC device
+ * @param versionp     This is set to point to the build string
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp);
+
+/**
+ * Switch on/off a LDO / FET.
+ *
+ * @param dev          CROS-EC device
+ * @param index                index of the LDO/FET to switch
+ * @param state                new state of the LDO/FET : EC_LDO_STATE_ON|OFF
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_set_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t state);
+
+/**
+ * Read back a LDO / FET current state.
+ *
+ * @param dev          CROS-EC device
+ * @param index                index of the LDO/FET to switch
+ * @param state                current state of the LDO/FET : EC_LDO_STATE_ON|OFF
+ * @return 0 if ok, -1 on error
+ */
+int cros_ec_get_ldo(struct cros_ec_dev *dev, uint8_t index, uint8_t *state);
+#endif
diff --git a/include/cros_ec_message.h b/include/cros_ec_message.h
new file mode 100644 (file)
index 0000000..a2421c7
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Chromium OS Matrix Keyboard Message Protocol definitions
+ *
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _CROS_MESSAGE_H
+#define _CROS_MESSAGE_H
+
+/*
+ * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
+ *
+ * This is copied from the Chromium OS Open Source Embedded Controller code.
+ */
+enum {
+       /* The header byte, which follows the preamble */
+       MSG_HEADER      = 0xec,
+
+       MSG_HEADER_BYTES        = 3,
+       MSG_TRAILER_BYTES       = 2,
+       MSG_PROTO_BYTES         = MSG_HEADER_BYTES + MSG_TRAILER_BYTES,
+
+       /* Max length of messages */
+       MSG_BYTES               = EC_HOST_PARAM_SIZE + MSG_PROTO_BYTES,
+};
+
+#endif
index c8b1d408e2b069072287811f6db34f487d2773f0..e142f3ec4a31e4780bbe560f6896a8901bd34085 100644 (file)
 #define MSIZE(x)               ((x) << 28)
 #define RX_WMARK(x)            ((x) << 16)
 #define TX_WMARK(x)            (x)
+#define RX_WMARK_SHIFT         16
+#define RX_WMARK_MASK          (0xfff << RX_WMARK_SHIFT)
 
 #define DWMCI_IDMAC_OWN                (1 << 31)
 #define DWMCI_IDMAC_CH         (1 << 4)
@@ -144,6 +146,7 @@ struct dwmci_host {
        unsigned int bus_hz;
        int dev_index;
        int buswidth;
+       u32 clksel_val;
        u32 fifoth_val;
        struct mmc *mmc;
 
diff --git a/include/ec_commands.h b/include/ec_commands.h
new file mode 100644 (file)
index 0000000..12811cc
--- /dev/null
@@ -0,0 +1,1440 @@
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Host communication command constants for Chrome EC */
+
+#ifndef __CROS_EC_COMMANDS_H
+#define __CROS_EC_COMMANDS_H
+
+/*
+ * Protocol overview
+ *
+ * request:  CMD [ P0 P1 P2 ... Pn S ]
+ * response: ERR [ P0 P1 P2 ... Pn S ]
+ *
+ * where the bytes are defined as follow :
+ *      - CMD is the command code. (defined by EC_CMD_ constants)
+ *      - ERR is the error code. (defined by EC_RES_ constants)
+ *      - Px is the optional payload.
+ *        it is not sent if the error code is not success.
+ *        (defined by ec_params_ and ec_response_ structures)
+ *      - S is the checksum which is the sum of all payload bytes.
+ *
+ * On LPC, CMD and ERR are sent/received at EC_LPC_ADDR_KERNEL|USER_CMD
+ * and the payloads are sent/received at EC_LPC_ADDR_KERNEL|USER_PARAM.
+ * On I2C, all bytes are sent serially in the same message.
+ */
+
+/* Current version of this protocol */
+#define EC_PROTO_VERSION          0x00000002
+
+/* Command version mask */
+#define EC_VER_MASK(version) (1UL << (version))
+
+/* I/O addresses for ACPI commands */
+#define EC_LPC_ADDR_ACPI_DATA  0x62
+#define EC_LPC_ADDR_ACPI_CMD   0x66
+
+/* I/O addresses for host command */
+#define EC_LPC_ADDR_HOST_DATA  0x200
+#define EC_LPC_ADDR_HOST_CMD   0x204
+
+/* I/O addresses for host command args and params */
+#define EC_LPC_ADDR_HOST_ARGS  0x800
+#define EC_LPC_ADDR_HOST_PARAM 0x804
+#define EC_HOST_PARAM_SIZE     0x0fc  /* Size of param area in bytes */
+
+/* I/O addresses for host command params, old interface */
+#define EC_LPC_ADDR_OLD_PARAM  0x880
+#define EC_OLD_PARAM_SIZE      0x080  /* Size of param area in bytes */
+
+/* EC command register bit functions */
+#define EC_LPC_CMDR_DATA       (1 << 0)  /* Data ready for host to read */
+#define EC_LPC_CMDR_PENDING    (1 << 1)  /* Write pending to EC */
+#define EC_LPC_CMDR_BUSY       (1 << 2)  /* EC is busy processing a command */
+#define EC_LPC_CMDR_CMD                (1 << 3)  /* Last host write was a command */
+#define EC_LPC_CMDR_ACPI_BRST  (1 << 4)  /* Burst mode (not used) */
+#define EC_LPC_CMDR_SCI                (1 << 5)  /* SCI event is pending */
+#define EC_LPC_CMDR_SMI                (1 << 6)  /* SMI event is pending */
+
+#define EC_LPC_ADDR_MEMMAP       0x900
+#define EC_MEMMAP_SIZE         255 /* ACPI IO buffer max is 255 bytes */
+#define EC_MEMMAP_TEXT_MAX     8   /* Size of a string in the memory map */
+
+/* The offset address of each type of data in mapped memory. */
+#define EC_MEMMAP_TEMP_SENSOR      0x00 /* Temp sensors */
+#define EC_MEMMAP_FAN              0x10 /* Fan speeds */
+#define EC_MEMMAP_TEMP_SENSOR_B    0x18 /* Temp sensors (second set) */
+#define EC_MEMMAP_ID               0x20 /* 'E' 'C' */
+#define EC_MEMMAP_ID_VERSION       0x22 /* Version of data in 0x20 - 0x2f */
+#define EC_MEMMAP_THERMAL_VERSION  0x23 /* Version of data in 0x00 - 0x1f */
+#define EC_MEMMAP_BATTERY_VERSION  0x24 /* Version of data in 0x40 - 0x7f */
+#define EC_MEMMAP_SWITCHES_VERSION 0x25 /* Version of data in 0x30 - 0x33 */
+#define EC_MEMMAP_EVENTS_VERSION   0x26 /* Version of data in 0x34 - 0x3f */
+#define EC_MEMMAP_HOST_CMD_FLAGS   0x27 /* Host command interface flags */
+#define EC_MEMMAP_SWITCHES         0x30
+#define EC_MEMMAP_HOST_EVENTS      0x34
+#define EC_MEMMAP_BATT_VOLT        0x40 /* Battery Present Voltage */
+#define EC_MEMMAP_BATT_RATE        0x44 /* Battery Present Rate */
+#define EC_MEMMAP_BATT_CAP         0x48 /* Battery Remaining Capacity */
+#define EC_MEMMAP_BATT_FLAG        0x4c /* Battery State, defined below */
+#define EC_MEMMAP_BATT_DCAP        0x50 /* Battery Design Capacity */
+#define EC_MEMMAP_BATT_DVLT        0x54 /* Battery Design Voltage */
+#define EC_MEMMAP_BATT_LFCC        0x58 /* Battery Last Full Charge Capacity */
+#define EC_MEMMAP_BATT_CCNT        0x5c /* Battery Cycle Count */
+#define EC_MEMMAP_BATT_MFGR        0x60 /* Battery Manufacturer String */
+#define EC_MEMMAP_BATT_MODEL       0x68 /* Battery Model Number String */
+#define EC_MEMMAP_BATT_SERIAL      0x70 /* Battery Serial Number String */
+#define EC_MEMMAP_BATT_TYPE        0x78 /* Battery Type String */
+
+/* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR */
+#define EC_TEMP_SENSOR_ENTRIES     16
+/*
+ * Number of temp sensors at EC_MEMMAP_TEMP_SENSOR_B.
+ *
+ * Valid only if EC_MEMMAP_THERMAL_VERSION returns >= 2.
+ */
+#define EC_TEMP_SENSOR_B_ENTRIES      8
+#define EC_TEMP_SENSOR_NOT_PRESENT    0xff
+#define EC_TEMP_SENSOR_ERROR          0xfe
+#define EC_TEMP_SENSOR_NOT_POWERED    0xfd
+#define EC_TEMP_SENSOR_NOT_CALIBRATED 0xfc
+/*
+ * The offset of temperature value stored in mapped memory.  This allows
+ * reporting a temperature range of 200K to 454K = -73C to 181C.
+ */
+#define EC_TEMP_SENSOR_OFFSET      200
+
+#define EC_FAN_SPEED_ENTRIES       4       /* Number of fans at EC_MEMMAP_FAN */
+#define EC_FAN_SPEED_NOT_PRESENT   0xffff  /* Entry not present */
+#define EC_FAN_SPEED_STALLED       0xfffe  /* Fan stalled */
+
+/* Battery bit flags at EC_MEMMAP_BATT_FLAG. */
+#define EC_BATT_FLAG_AC_PRESENT   0x01
+#define EC_BATT_FLAG_BATT_PRESENT 0x02
+#define EC_BATT_FLAG_DISCHARGING  0x04
+#define EC_BATT_FLAG_CHARGING     0x08
+#define EC_BATT_FLAG_LEVEL_CRITICAL 0x10
+
+/* Switch flags at EC_MEMMAP_SWITCHES */
+#define EC_SWITCH_LID_OPEN               0x01
+#define EC_SWITCH_POWER_BUTTON_PRESSED   0x02
+#define EC_SWITCH_WRITE_PROTECT_DISABLED 0x04
+/* Recovery requested via keyboard */
+#define EC_SWITCH_KEYBOARD_RECOVERY      0x08
+/* Recovery requested via dedicated signal (from servo board) */
+#define EC_SWITCH_DEDICATED_RECOVERY     0x10
+/* Was fake developer mode switch; now unused.  Remove in next refactor. */
+#define EC_SWITCH_IGNORE0                0x20
+
+/* Host command interface flags */
+/* Host command interface supports LPC args (LPC interface only) */
+#define EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED  0x01
+
+/* Wireless switch flags */
+#define EC_WIRELESS_SWITCH_WLAN      0x01
+#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02
+
+/*
+ * This header file is used in coreboot both in C and ACPI code.  The ACPI code
+ * is pre-processed to handle constants but the ASL compiler is unable to
+ * handle actual C code so keep it separate.
+ */
+#ifndef __ACPI__
+
+/*
+ * Define __packed if someone hasn't beat us to it.  Linux kernel style
+ * checking prefers __packed over __attribute__((packed)).
+ */
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+/* LPC command status byte masks */
+/* EC has written a byte in the data register and host hasn't read it yet */
+#define EC_LPC_STATUS_TO_HOST     0x01
+/* Host has written a command/data byte and the EC hasn't read it yet */
+#define EC_LPC_STATUS_FROM_HOST   0x02
+/* EC is processing a command */
+#define EC_LPC_STATUS_PROCESSING  0x04
+/* Last write to EC was a command, not data */
+#define EC_LPC_STATUS_LAST_CMD    0x08
+/* EC is in burst mode.  Unsupported by Chrome EC, so this bit is never set */
+#define EC_LPC_STATUS_BURST_MODE  0x10
+/* SCI event is pending (requesting SCI query) */
+#define EC_LPC_STATUS_SCI_PENDING 0x20
+/* SMI event is pending (requesting SMI query) */
+#define EC_LPC_STATUS_SMI_PENDING 0x40
+/* (reserved) */
+#define EC_LPC_STATUS_RESERVED    0x80
+
+/*
+ * EC is busy.  This covers both the EC processing a command, and the host has
+ * written a new command but the EC hasn't picked it up yet.
+ */
+#define EC_LPC_STATUS_BUSY_MASK \
+       (EC_LPC_STATUS_FROM_HOST | EC_LPC_STATUS_PROCESSING)
+
+/* Host command response codes */
+enum ec_status {
+       EC_RES_SUCCESS = 0,
+       EC_RES_INVALID_COMMAND = 1,
+       EC_RES_ERROR = 2,
+       EC_RES_INVALID_PARAM = 3,
+       EC_RES_ACCESS_DENIED = 4,
+       EC_RES_INVALID_RESPONSE = 5,
+       EC_RES_INVALID_VERSION = 6,
+       EC_RES_INVALID_CHECKSUM = 7,
+       EC_RES_IN_PROGRESS = 8,         /* Accepted, command in progress */
+       EC_RES_UNAVAILABLE = 9,         /* No response available */
+       EC_RES_TIMEOUT = 10,            /* We got a timeout */
+       EC_RES_OVERFLOW = 11,           /* Table / data overflow */
+};
+
+/*
+ * Host event codes.  Note these are 1-based, not 0-based, because ACPI query
+ * EC command uses code 0 to mean "no event pending".  We explicitly specify
+ * each value in the enum listing so they won't change if we delete/insert an
+ * item or rearrange the list (it needs to be stable across platforms, not
+ * just within a single compiled instance).
+ */
+enum host_event_code {
+       EC_HOST_EVENT_LID_CLOSED = 1,
+       EC_HOST_EVENT_LID_OPEN = 2,
+       EC_HOST_EVENT_POWER_BUTTON = 3,
+       EC_HOST_EVENT_AC_CONNECTED = 4,
+       EC_HOST_EVENT_AC_DISCONNECTED = 5,
+       EC_HOST_EVENT_BATTERY_LOW = 6,
+       EC_HOST_EVENT_BATTERY_CRITICAL = 7,
+       EC_HOST_EVENT_BATTERY = 8,
+       EC_HOST_EVENT_THERMAL_THRESHOLD = 9,
+       EC_HOST_EVENT_THERMAL_OVERLOAD = 10,
+       EC_HOST_EVENT_THERMAL = 11,
+       EC_HOST_EVENT_USB_CHARGER = 12,
+       EC_HOST_EVENT_KEY_PRESSED = 13,
+       /*
+        * EC has finished initializing the host interface.  The host can check
+        * for this event following sending a EC_CMD_REBOOT_EC command to
+        * determine when the EC is ready to accept subsequent commands.
+        */
+       EC_HOST_EVENT_INTERFACE_READY = 14,
+       /* Keyboard recovery combo has been pressed */
+       EC_HOST_EVENT_KEYBOARD_RECOVERY = 15,
+
+       /* Shutdown due to thermal overload */
+       EC_HOST_EVENT_THERMAL_SHUTDOWN = 16,
+       /* Shutdown due to battery level too low */
+       EC_HOST_EVENT_BATTERY_SHUTDOWN = 17,
+
+       /*
+        * The high bit of the event mask is not used as a host event code.  If
+        * it reads back as set, then the entire event mask should be
+        * considered invalid by the host.  This can happen when reading the
+        * raw event status via EC_MEMMAP_HOST_EVENTS but the LPC interface is
+        * not initialized on the EC, or improperly configured on the host.
+        */
+       EC_HOST_EVENT_INVALID = 32
+};
+/* Host event mask */
+#define EC_HOST_EVENT_MASK(event_code) (1UL << ((event_code) - 1))
+
+/* Arguments at EC_LPC_ADDR_HOST_ARGS */
+struct ec_lpc_host_args {
+       uint8_t flags;
+       uint8_t command_version;
+       uint8_t data_size;
+       /*
+        * Checksum; sum of command + flags + command_version + data_size +
+        * all params/response data bytes.
+        */
+       uint8_t checksum;
+} __packed;
+
+/* Flags for ec_lpc_host_args.flags */
+/*
+ * Args are from host.  Data area at EC_LPC_ADDR_HOST_PARAM contains command
+ * params.
+ *
+ * If EC gets a command and this flag is not set, this is an old-style command.
+ * Command version is 0 and params from host are at EC_LPC_ADDR_OLD_PARAM with
+ * unknown length.  EC must respond with an old-style response (that is,
+ * withouth setting EC_HOST_ARGS_FLAG_TO_HOST).
+ */
+#define EC_HOST_ARGS_FLAG_FROM_HOST 0x01
+/*
+ * Args are from EC.  Data area at EC_LPC_ADDR_HOST_PARAM contains response.
+ *
+ * If EC responds to a command and this flag is not set, this is an old-style
+ * response.  Command version is 0 and response data from EC is at
+ * EC_LPC_ADDR_OLD_PARAM with unknown length.
+ */
+#define EC_HOST_ARGS_FLAG_TO_HOST   0x02
+
+/*
+ * Notes on commands:
+ *
+ * Each command is an 8-byte command value.  Commands which take params or
+ * return response data specify structs for that data.  If no struct is
+ * specified, the command does not input or output data, respectively.
+ * Parameter/response length is implicit in the structs.  Some underlying
+ * communication protocols (I2C, SPI) may add length or checksum headers, but
+ * those are implementation-dependent and not defined here.
+ */
+
+/*****************************************************************************/
+/* General / test commands */
+
+/*
+ * Get protocol version, used to deal with non-backward compatible protocol
+ * changes.
+ */
+#define EC_CMD_PROTO_VERSION 0x00
+
+struct ec_response_proto_version {
+       uint32_t version;
+} __packed;
+
+/*
+ * Hello.  This is a simple command to test the EC is responsive to
+ * commands.
+ */
+#define EC_CMD_HELLO 0x01
+
+struct ec_params_hello {
+       uint32_t in_data;  /* Pass anything here */
+} __packed;
+
+struct ec_response_hello {
+       uint32_t out_data;  /* Output will be in_data + 0x01020304 */
+} __packed;
+
+/* Get version number */
+#define EC_CMD_GET_VERSION 0x02
+
+enum ec_current_image {
+       EC_IMAGE_UNKNOWN = 0,
+       EC_IMAGE_RO,
+       EC_IMAGE_RW
+};
+
+struct ec_response_get_version {
+       /* Null-terminated version strings for RO, RW */
+       char version_string_ro[32];
+       char version_string_rw[32];
+       char reserved[32];       /* Was previously RW-B string */
+       uint32_t current_image;  /* One of ec_current_image */
+} __packed;
+
+/* Read test */
+#define EC_CMD_READ_TEST 0x03
+
+struct ec_params_read_test {
+       uint32_t offset;   /* Starting value for read buffer */
+       uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+struct ec_response_read_test {
+       uint32_t data[32];
+} __packed;
+
+/*
+ * Get build information
+ *
+ * Response is null-terminated string.
+ */
+#define EC_CMD_GET_BUILD_INFO 0x04
+
+/* Get chip info */
+#define EC_CMD_GET_CHIP_INFO 0x05
+
+struct ec_response_get_chip_info {
+       /* Null-terminated strings */
+       char vendor[32];
+       char name[32];
+       char revision[32];  /* Mask version */
+} __packed;
+
+/* Get board HW version */
+#define EC_CMD_GET_BOARD_VERSION 0x06
+
+struct ec_response_board_version {
+       uint16_t board_version;  /* A monotonously incrementing number. */
+} __packed;
+
+/*
+ * Read memory-mapped data.
+ *
+ * This is an alternate interface to memory-mapped data for bus protocols
+ * which don't support direct-mapped memory - I2C, SPI, etc.
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_READ_MEMMAP 0x07
+
+struct ec_params_read_memmap {
+       uint8_t offset;   /* Offset in memmap (EC_MEMMAP_*) */
+       uint8_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Read versions supported for a command */
+#define EC_CMD_GET_CMD_VERSIONS 0x08
+
+struct ec_params_get_cmd_versions {
+       uint8_t cmd;      /* Command to check */
+} __packed;
+
+struct ec_response_get_cmd_versions {
+       /*
+        * Mask of supported versions; use EC_VER_MASK() to compare with a
+        * desired version.
+        */
+       uint32_t version_mask;
+} __packed;
+
+/*
+ * Check EC communcations status (busy). This is needed on i2c/spi but not
+ * on lpc since it has its own out-of-band busy indicator.
+ *
+ * lpc must read the status from the command register. Attempting this on
+ * lpc will overwrite the args/parameter space and corrupt its data.
+ */
+#define EC_CMD_GET_COMMS_STATUS                0x09
+
+/* Avoid using ec_status which is for return values */
+enum ec_comms_status {
+       EC_COMMS_STATUS_PROCESSING      = 1 << 0,       /* Processing cmd */
+};
+
+struct ec_response_get_comms_status {
+       uint32_t flags;         /* Mask of enum ec_comms_status */
+} __packed;
+
+
+/*****************************************************************************/
+/* Flash commands */
+
+/* Get flash info */
+#define EC_CMD_FLASH_INFO 0x10
+
+struct ec_response_flash_info {
+       /* Usable flash size, in bytes */
+       uint32_t flash_size;
+       /*
+        * Write block size.  Write offset and size must be a multiple
+        * of this.
+        */
+       uint32_t write_block_size;
+       /*
+        * Erase block size.  Erase offset and size must be a multiple
+        * of this.
+        */
+       uint32_t erase_block_size;
+       /*
+        * Protection block size.  Protection offset and size must be a
+        * multiple of this.
+        */
+       uint32_t protect_block_size;
+} __packed;
+
+/*
+ * Read flash
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_FLASH_READ 0x11
+
+struct ec_params_flash_read {
+       uint32_t offset;   /* Byte offset to read */
+       uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Write flash */
+#define EC_CMD_FLASH_WRITE 0x12
+
+struct ec_params_flash_write {
+       uint32_t offset;   /* Byte offset to write */
+       uint32_t size;     /* Size to write in bytes */
+       /*
+        * Data to write.  Could really use EC_PARAM_SIZE - 8, but tidiest to
+        * use a power of 2 so writes stay aligned.
+        */
+       uint8_t data[64];
+} __packed;
+
+/* Erase flash */
+#define EC_CMD_FLASH_ERASE 0x13
+
+struct ec_params_flash_erase {
+       uint32_t offset;   /* Byte offset to erase */
+       uint32_t size;     /* Size to erase in bytes */
+} __packed;
+
+/*
+ * Get/set flash protection.
+ *
+ * If mask!=0, sets/clear the requested bits of flags.  Depending on the
+ * firmware write protect GPIO, not all flags will take effect immediately;
+ * some flags require a subsequent hard reset to take effect.  Check the
+ * returned flags bits to see what actually happened.
+ *
+ * If mask=0, simply returns the current flags state.
+ */
+#define EC_CMD_FLASH_PROTECT 0x15
+#define EC_VER_FLASH_PROTECT 1  /* Command version 1 */
+
+/* Flags for flash protection */
+/* RO flash code protected when the EC boots */
+#define EC_FLASH_PROTECT_RO_AT_BOOT         (1 << 0)
+/*
+ * RO flash code protected now.  If this bit is set, at-boot status cannot
+ * be changed.
+ */
+#define EC_FLASH_PROTECT_RO_NOW             (1 << 1)
+/* Entire flash code protected now, until reboot. */
+#define EC_FLASH_PROTECT_ALL_NOW            (1 << 2)
+/* Flash write protect GPIO is asserted now */
+#define EC_FLASH_PROTECT_GPIO_ASSERTED      (1 << 3)
+/* Error - at least one bank of flash is stuck locked, and cannot be unlocked */
+#define EC_FLASH_PROTECT_ERROR_STUCK        (1 << 4)
+/*
+ * Error - flash protection is in inconsistent state.  At least one bank of
+ * flash which should be protected is not protected.  Usually fixed by
+ * re-requesting the desired flags, or by a hard reset if that fails.
+ */
+#define EC_FLASH_PROTECT_ERROR_INCONSISTENT (1 << 5)
+/* Entile flash code protected when the EC boots */
+#define EC_FLASH_PROTECT_ALL_AT_BOOT        (1 << 6)
+
+struct ec_params_flash_protect {
+       uint32_t mask;   /* Bits in flags to apply */
+       uint32_t flags;  /* New flags to apply */
+} __packed;
+
+struct ec_response_flash_protect {
+       /* Current value of flash protect flags */
+       uint32_t flags;
+       /*
+        * Flags which are valid on this platform.  This allows the caller
+        * to distinguish between flags which aren't set vs. flags which can't
+        * be set on this platform.
+        */
+       uint32_t valid_flags;
+       /* Flags which can be changed given the current protection state */
+       uint32_t writable_flags;
+} __packed;
+
+/*
+ * Note: commands 0x14 - 0x19 version 0 were old commands to get/set flash
+ * write protect.  These commands may be reused with version > 0.
+ */
+
+/* Get the region offset/size */
+#define EC_CMD_FLASH_REGION_INFO 0x16
+#define EC_VER_FLASH_REGION_INFO 1
+
+enum ec_flash_region {
+       /* Region which holds read-only EC image */
+       EC_FLASH_REGION_RO,
+       /* Region which holds rewritable EC image */
+       EC_FLASH_REGION_RW,
+       /*
+        * Region which should be write-protected in the factory (a superset of
+        * EC_FLASH_REGION_RO)
+        */
+       EC_FLASH_REGION_WP_RO,
+};
+
+struct ec_params_flash_region_info {
+       uint32_t region;  /* enum ec_flash_region */
+} __packed;
+
+struct ec_response_flash_region_info {
+       uint32_t offset;
+       uint32_t size;
+} __packed;
+
+/* Read/write VbNvContext */
+#define EC_CMD_VBNV_CONTEXT 0x17
+#define EC_VER_VBNV_CONTEXT 1
+#define EC_VBNV_BLOCK_SIZE 16
+
+enum ec_vbnvcontext_op {
+       EC_VBNV_CONTEXT_OP_READ,
+       EC_VBNV_CONTEXT_OP_WRITE,
+};
+
+struct ec_params_vbnvcontext {
+       uint32_t op;
+       uint8_t block[EC_VBNV_BLOCK_SIZE];
+} __packed;
+
+struct ec_response_vbnvcontext {
+       uint8_t block[EC_VBNV_BLOCK_SIZE];
+} __packed;
+
+/*****************************************************************************/
+/* PWM commands */
+
+/* Get fan target RPM */
+#define EC_CMD_PWM_GET_FAN_TARGET_RPM 0x20
+
+struct ec_response_pwm_get_fan_rpm {
+       uint32_t rpm;
+} __packed;
+
+/* Set target fan RPM */
+#define EC_CMD_PWM_SET_FAN_TARGET_RPM 0x21
+
+struct ec_params_pwm_set_fan_target_rpm {
+       uint32_t rpm;
+} __packed;
+
+/* Get keyboard backlight */
+#define EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT 0x22
+
+struct ec_response_pwm_get_keyboard_backlight {
+       uint8_t percent;
+       uint8_t enabled;
+} __packed;
+
+/* Set keyboard backlight */
+#define EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT 0x23
+
+struct ec_params_pwm_set_keyboard_backlight {
+       uint8_t percent;
+} __packed;
+
+/* Set target fan PWM duty cycle */
+#define EC_CMD_PWM_SET_FAN_DUTY 0x24
+
+struct ec_params_pwm_set_fan_duty {
+       uint32_t percent;
+} __packed;
+
+/*****************************************************************************/
+/*
+ * Lightbar commands. This looks worse than it is. Since we only use one HOST
+ * command to say "talk to the lightbar", we put the "and tell it to do X" part
+ * into a subcommand. We'll make separate structs for subcommands with
+ * different input args, so that we know how much to expect.
+ */
+#define EC_CMD_LIGHTBAR_CMD 0x28
+
+struct rgb_s {
+       uint8_t r, g, b;
+};
+
+#define LB_BATTERY_LEVELS 4
+/* List of tweakable parameters. NOTE: It's __packed so it can be sent in a
+ * host command, but the alignment is the same regardless. Keep it that way.
+ */
+struct lightbar_params {
+       /* Timing */
+       int google_ramp_up;
+       int google_ramp_down;
+       int s3s0_ramp_up;
+       int s0_tick_delay[2];                   /* AC=0/1 */
+       int s0a_tick_delay[2];                  /* AC=0/1 */
+       int s0s3_ramp_down;
+       int s3_sleep_for;
+       int s3_ramp_up;
+       int s3_ramp_down;
+
+       /* Oscillation */
+       uint8_t new_s0;
+       uint8_t osc_min[2];                     /* AC=0/1 */
+       uint8_t osc_max[2];                     /* AC=0/1 */
+       uint8_t w_ofs[2];                       /* AC=0/1 */
+
+       /* Brightness limits based on the backlight and AC. */
+       uint8_t bright_bl_off_fixed[2];         /* AC=0/1 */
+       uint8_t bright_bl_on_min[2];            /* AC=0/1 */
+       uint8_t bright_bl_on_max[2];            /* AC=0/1 */
+
+       /* Battery level thresholds */
+       uint8_t battery_threshold[LB_BATTERY_LEVELS - 1];
+
+       /* Map [AC][battery_level] to color index */
+       uint8_t s0_idx[2][LB_BATTERY_LEVELS];   /* AP is running */
+       uint8_t s3_idx[2][LB_BATTERY_LEVELS];   /* AP is sleeping */
+
+       /* Color palette */
+       struct rgb_s color[8];                  /* 0-3 are Google colors */
+} __packed;
+
+struct ec_params_lightbar {
+       uint8_t cmd;                  /* Command (see enum lightbar_command) */
+       union {
+               struct {
+                       /* no args */
+               } dump, off, on, init, get_seq, get_params;
+
+               struct num {
+                       uint8_t num;
+               } brightness, seq, demo;
+
+               struct reg {
+                       uint8_t ctrl, reg, value;
+               } reg;
+
+               struct rgb {
+                       uint8_t led, red, green, blue;
+               } rgb;
+
+               struct lightbar_params set_params;
+       };
+} __packed;
+
+struct ec_response_lightbar {
+       union {
+               struct dump {
+                       struct {
+                               uint8_t reg;
+                               uint8_t ic0;
+                               uint8_t ic1;
+                       } vals[23];
+               } dump;
+
+               struct get_seq {
+                       uint8_t num;
+               } get_seq;
+
+               struct lightbar_params get_params;
+
+               struct {
+                       /* no return params */
+               } off, on, init, brightness, seq, reg, rgb, demo, set_params;
+       };
+} __packed;
+
+/* Lightbar commands */
+enum lightbar_command {
+       LIGHTBAR_CMD_DUMP = 0,
+       LIGHTBAR_CMD_OFF = 1,
+       LIGHTBAR_CMD_ON = 2,
+       LIGHTBAR_CMD_INIT = 3,
+       LIGHTBAR_CMD_BRIGHTNESS = 4,
+       LIGHTBAR_CMD_SEQ = 5,
+       LIGHTBAR_CMD_REG = 6,
+       LIGHTBAR_CMD_RGB = 7,
+       LIGHTBAR_CMD_GET_SEQ = 8,
+       LIGHTBAR_CMD_DEMO = 9,
+       LIGHTBAR_CMD_GET_PARAMS = 10,
+       LIGHTBAR_CMD_SET_PARAMS = 11,
+       LIGHTBAR_NUM_CMDS
+};
+
+/*****************************************************************************/
+/* Verified boot commands */
+
+/*
+ * Note: command code 0x29 version 0 was VBOOT_CMD in Link EVT; it may be
+ * reused for other purposes with version > 0.
+ */
+
+/* Verified boot hash command */
+#define EC_CMD_VBOOT_HASH 0x2A
+
+struct ec_params_vboot_hash {
+       uint8_t cmd;             /* enum ec_vboot_hash_cmd */
+       uint8_t hash_type;       /* enum ec_vboot_hash_type */
+       uint8_t nonce_size;      /* Nonce size; may be 0 */
+       uint8_t reserved0;       /* Reserved; set 0 */
+       uint32_t offset;         /* Offset in flash to hash */
+       uint32_t size;           /* Number of bytes to hash */
+       uint8_t nonce_data[64];  /* Nonce data; ignored if nonce_size=0 */
+} __packed;
+
+struct ec_response_vboot_hash {
+       uint8_t status;          /* enum ec_vboot_hash_status */
+       uint8_t hash_type;       /* enum ec_vboot_hash_type */
+       uint8_t digest_size;     /* Size of hash digest in bytes */
+       uint8_t reserved0;       /* Ignore; will be 0 */
+       uint32_t offset;         /* Offset in flash which was hashed */
+       uint32_t size;           /* Number of bytes hashed */
+       uint8_t hash_digest[64]; /* Hash digest data */
+} __packed;
+
+enum ec_vboot_hash_cmd {
+       EC_VBOOT_HASH_GET = 0,       /* Get current hash status */
+       EC_VBOOT_HASH_ABORT = 1,     /* Abort calculating current hash */
+       EC_VBOOT_HASH_START = 2,     /* Start computing a new hash */
+       EC_VBOOT_HASH_RECALC = 3,    /* Synchronously compute a new hash */
+};
+
+enum ec_vboot_hash_type {
+       EC_VBOOT_HASH_TYPE_SHA256 = 0, /* SHA-256 */
+};
+
+enum ec_vboot_hash_status {
+       EC_VBOOT_HASH_STATUS_NONE = 0, /* No hash (not started, or aborted) */
+       EC_VBOOT_HASH_STATUS_DONE = 1, /* Finished computing a hash */
+       EC_VBOOT_HASH_STATUS_BUSY = 2, /* Busy computing a hash */
+};
+
+/*
+ * Special values for offset for EC_VBOOT_HASH_START and EC_VBOOT_HASH_RECALC.
+ * If one of these is specified, the EC will automatically update offset and
+ * size to the correct values for the specified image (RO or RW).
+ */
+#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe
+#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd
+
+/*****************************************************************************/
+/* USB charging control commands */
+
+/* Set USB port charging mode */
+#define EC_CMD_USB_CHARGE_SET_MODE 0x30
+
+struct ec_params_usb_charge_set_mode {
+       uint8_t usb_port_id;
+       uint8_t mode;
+} __packed;
+
+/*****************************************************************************/
+/* Persistent storage for host */
+
+/* Maximum bytes that can be read/written in a single command */
+#define EC_PSTORE_SIZE_MAX 64
+
+/* Get persistent storage info */
+#define EC_CMD_PSTORE_INFO 0x40
+
+struct ec_response_pstore_info {
+       /* Persistent storage size, in bytes */
+       uint32_t pstore_size;
+       /* Access size; read/write offset and size must be a multiple of this */
+       uint32_t access_size;
+} __packed;
+
+/*
+ * Read persistent storage
+ *
+ * Response is params.size bytes of data.
+ */
+#define EC_CMD_PSTORE_READ 0x41
+
+struct ec_params_pstore_read {
+       uint32_t offset;   /* Byte offset to read */
+       uint32_t size;     /* Size to read in bytes */
+} __packed;
+
+/* Write persistent storage */
+#define EC_CMD_PSTORE_WRITE 0x42
+
+struct ec_params_pstore_write {
+       uint32_t offset;   /* Byte offset to write */
+       uint32_t size;     /* Size to write in bytes */
+       uint8_t data[EC_PSTORE_SIZE_MAX];
+} __packed;
+
+/*****************************************************************************/
+/* Real-time clock */
+
+/* RTC params and response structures */
+struct ec_params_rtc {
+       uint32_t time;
+} __packed;
+
+struct ec_response_rtc {
+       uint32_t time;
+} __packed;
+
+/* These use ec_response_rtc */
+#define EC_CMD_RTC_GET_VALUE 0x44
+#define EC_CMD_RTC_GET_ALARM 0x45
+
+/* These all use ec_params_rtc */
+#define EC_CMD_RTC_SET_VALUE 0x46
+#define EC_CMD_RTC_SET_ALARM 0x47
+
+/*****************************************************************************/
+/* Port80 log access */
+
+/* Get last port80 code from previous boot */
+#define EC_CMD_PORT80_LAST_BOOT 0x48
+
+struct ec_response_port80_last_boot {
+       uint16_t code;
+} __packed;
+
+/*****************************************************************************/
+/* Thermal engine commands */
+
+/* Set thershold value */
+#define EC_CMD_THERMAL_SET_THRESHOLD 0x50
+
+struct ec_params_thermal_set_threshold {
+       uint8_t sensor_type;
+       uint8_t threshold_id;
+       uint16_t value;
+} __packed;
+
+/* Get threshold value */
+#define EC_CMD_THERMAL_GET_THRESHOLD 0x51
+
+struct ec_params_thermal_get_threshold {
+       uint8_t sensor_type;
+       uint8_t threshold_id;
+} __packed;
+
+struct ec_response_thermal_get_threshold {
+       uint16_t value;
+} __packed;
+
+/* Toggle automatic fan control */
+#define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x52
+
+/* Get TMP006 calibration data */
+#define EC_CMD_TMP006_GET_CALIBRATION 0x53
+
+struct ec_params_tmp006_get_calibration {
+       uint8_t index;
+} __packed;
+
+struct ec_response_tmp006_get_calibration {
+       float s0;
+       float b0;
+       float b1;
+       float b2;
+} __packed;
+
+/* Set TMP006 calibration data */
+#define EC_CMD_TMP006_SET_CALIBRATION 0x54
+
+struct ec_params_tmp006_set_calibration {
+       uint8_t index;
+       uint8_t reserved[3];  /* Reserved; set 0 */
+       float s0;
+       float b0;
+       float b1;
+       float b2;
+} __packed;
+
+/*****************************************************************************/
+/* CROS_EC - Matrix KeyBoard Protocol */
+
+/*
+ * Read key state
+ *
+ * Returns raw data for keyboard cols; see ec_response_cros_ec_info.cols for
+ * expected response size.
+ */
+#define EC_CMD_CROS_EC_STATE 0x60
+
+/* Provide information about the matrix : number of rows and columns */
+#define EC_CMD_CROS_EC_INFO 0x61
+
+struct ec_response_cros_ec_info {
+       uint32_t rows;
+       uint32_t cols;
+       uint8_t switches;
+} __packed;
+
+/* Simulate key press */
+#define EC_CMD_CROS_EC_SIMULATE_KEY 0x62
+
+struct ec_params_cros_ec_simulate_key {
+       uint8_t col;
+       uint8_t row;
+       uint8_t pressed;
+} __packed;
+
+/* Configure keyboard scanning */
+#define EC_CMD_CROS_EC_SET_CONFIG 0x64
+#define EC_CMD_CROS_EC_GET_CONFIG 0x65
+
+/* flags */
+enum cros_ec_config_flags {
+       EC_CROS_EC_FLAGS_ENABLE = 1,    /* Enable keyboard scanning */
+};
+
+enum cros_ec_config_valid {
+       EC_CROS_EC_VALID_SCAN_PERIOD            = 1 << 0,
+       EC_CROS_EC_VALID_POLL_TIMEOUT           = 1 << 1,
+       EC_CROS_EC_VALID_MIN_POST_SCAN_DELAY    = 1 << 3,
+       EC_CROS_EC_VALID_OUTPUT_SETTLE          = 1 << 4,
+       EC_CROS_EC_VALID_DEBOUNCE_DOWN          = 1 << 5,
+       EC_CROS_EC_VALID_DEBOUNCE_UP            = 1 << 6,
+       EC_CROS_EC_VALID_FIFO_MAX_DEPTH         = 1 << 7,
+};
+
+/* Configuration for our key scanning algorithm */
+struct ec_cros_ec_config {
+       uint32_t valid_mask;            /* valid fields */
+       uint8_t flags;          /* some flags (enum cros_ec_config_flags) */
+       uint8_t valid_flags;            /* which flags are valid */
+       uint16_t scan_period_us;        /* period between start of scans */
+       /* revert to interrupt mode after no activity for this long */
+       uint32_t poll_timeout_us;
+       /*
+        * minimum post-scan relax time. Once we finish a scan we check
+        * the time until we are due to start the next one. If this time is
+        * shorter this field, we use this instead.
+        */
+       uint16_t min_post_scan_delay_us;
+       /* delay between setting up output and waiting for it to settle */
+       uint16_t output_settle_us;
+       uint16_t debounce_down_us;      /* time for debounce on key down */
+       uint16_t debounce_up_us;        /* time for debounce on key up */
+       /* maximum depth to allow for fifo (0 = no keyscan output) */
+       uint8_t fifo_max_depth;
+} __packed;
+
+struct ec_params_cros_ec_set_config {
+       struct ec_cros_ec_config config;
+} __packed;
+
+struct ec_response_cros_ec_get_config {
+       struct ec_cros_ec_config config;
+} __packed;
+
+/* Run the key scan emulation */
+#define EC_CMD_KEYSCAN_SEQ_CTRL 0x66
+
+enum ec_keyscan_seq_cmd {
+       EC_KEYSCAN_SEQ_STATUS = 0,      /* Get status information */
+       EC_KEYSCAN_SEQ_CLEAR = 1,       /* Clear sequence */
+       EC_KEYSCAN_SEQ_ADD = 2,         /* Add item to sequence */
+       EC_KEYSCAN_SEQ_START = 3,       /* Start running sequence */
+       EC_KEYSCAN_SEQ_COLLECT = 4,     /* Collect sequence summary data */
+};
+
+enum ec_collect_flags {
+       /*
+        * Indicates this scan was processed by the EC. Due to timing, some
+        * scans may be skipped.
+        */
+       EC_KEYSCAN_SEQ_FLAG_DONE        = 1 << 0,
+};
+
+struct ec_collect_item {
+       uint8_t flags;          /* some flags (enum ec_collect_flags) */
+};
+
+struct ec_params_keyscan_seq_ctrl {
+       uint8_t cmd;    /* Command to send (enum ec_keyscan_seq_cmd) */
+       union {
+               struct {
+                       uint8_t active;         /* still active */
+                       uint8_t num_items;      /* number of items */
+                       /* Current item being presented */
+                       uint8_t cur_item;
+               } status;
+               struct {
+                       /*
+                        * Absolute time for this scan, measured from the
+                        * start of the sequence.
+                        */
+                       uint32_t time_us;
+                       uint8_t scan[0];        /* keyscan data */
+               } add;
+               struct {
+                       uint8_t start_item;     /* First item to return */
+                       uint8_t num_items;      /* Number of items to return */
+               } collect;
+       };
+} __packed;
+
+struct ec_result_keyscan_seq_ctrl {
+       union {
+               struct {
+                       uint8_t num_items;      /* Number of items */
+                       /* Data for each item */
+                       struct ec_collect_item item[0];
+               } collect;
+       };
+} __packed;
+
+/*****************************************************************************/
+/* Temperature sensor commands */
+
+/* Read temperature sensor info */
+#define EC_CMD_TEMP_SENSOR_GET_INFO 0x70
+
+struct ec_params_temp_sensor_get_info {
+       uint8_t id;
+} __packed;
+
+struct ec_response_temp_sensor_get_info {
+       char sensor_name[32];
+       uint8_t sensor_type;
+} __packed;
+
+/*****************************************************************************/
+
+/*
+ * Note: host commands 0x80 - 0x87 are reserved to avoid conflict with ACPI
+ * commands accidentally sent to the wrong interface.  See the ACPI section
+ * below.
+ */
+
+/*****************************************************************************/
+/* Host event commands */
+
+/*
+ * Host event mask params and response structures, shared by all of the host
+ * event commands below.
+ */
+struct ec_params_host_event_mask {
+       uint32_t mask;
+} __packed;
+
+struct ec_response_host_event_mask {
+       uint32_t mask;
+} __packed;
+
+/* These all use ec_response_host_event_mask */
+#define EC_CMD_HOST_EVENT_GET_B         0x87
+#define EC_CMD_HOST_EVENT_GET_SMI_MASK  0x88
+#define EC_CMD_HOST_EVENT_GET_SCI_MASK  0x89
+#define EC_CMD_HOST_EVENT_GET_WAKE_MASK 0x8d
+
+/* These all use ec_params_host_event_mask */
+#define EC_CMD_HOST_EVENT_SET_SMI_MASK  0x8a
+#define EC_CMD_HOST_EVENT_SET_SCI_MASK  0x8b
+#define EC_CMD_HOST_EVENT_CLEAR         0x8c
+#define EC_CMD_HOST_EVENT_SET_WAKE_MASK 0x8e
+#define EC_CMD_HOST_EVENT_CLEAR_B       0x8f
+
+/*****************************************************************************/
+/* Switch commands */
+
+/* Enable/disable LCD backlight */
+#define EC_CMD_SWITCH_ENABLE_BKLIGHT 0x90
+
+struct ec_params_switch_enable_backlight {
+       uint8_t enabled;
+} __packed;
+
+/* Enable/disable WLAN/Bluetooth */
+#define EC_CMD_SWITCH_ENABLE_WIRELESS 0x91
+
+struct ec_params_switch_enable_wireless {
+       uint8_t enabled;
+} __packed;
+
+/*****************************************************************************/
+/* GPIO commands. Only available on EC if write protect has been disabled. */
+
+/* Set GPIO output value */
+#define EC_CMD_GPIO_SET 0x92
+
+struct ec_params_gpio_set {
+       char name[32];
+       uint8_t val;
+} __packed;
+
+/* Get GPIO value */
+#define EC_CMD_GPIO_GET 0x93
+
+struct ec_params_gpio_get {
+       char name[32];
+} __packed;
+struct ec_response_gpio_get {
+       uint8_t val;
+} __packed;
+
+/*****************************************************************************/
+/* I2C commands. Only available when flash write protect is unlocked. */
+
+/* Read I2C bus */
+#define EC_CMD_I2C_READ 0x94
+
+struct ec_params_i2c_read {
+       uint16_t addr;
+       uint8_t read_size; /* Either 8 or 16. */
+       uint8_t port;
+       uint8_t offset;
+} __packed;
+struct ec_response_i2c_read {
+       uint16_t data;
+} __packed;
+
+/* Write I2C bus */
+#define EC_CMD_I2C_WRITE 0x95
+
+struct ec_params_i2c_write {
+       uint16_t data;
+       uint16_t addr;
+       uint8_t write_size; /* Either 8 or 16. */
+       uint8_t port;
+       uint8_t offset;
+} __packed;
+
+/*****************************************************************************/
+/* Charge state commands. Only available when flash write protect unlocked. */
+
+/* Force charge state machine to stop in idle mode */
+#define EC_CMD_CHARGE_FORCE_IDLE 0x96
+
+struct ec_params_force_idle {
+       uint8_t enabled;
+} __packed;
+
+/*****************************************************************************/
+/* Console commands. Only available when flash write protect is unlocked. */
+
+/* Snapshot console output buffer for use by EC_CMD_CONSOLE_READ. */
+#define EC_CMD_CONSOLE_SNAPSHOT 0x97
+
+/*
+ * Read next chunk of data from saved snapshot.
+ *
+ * Response is null-terminated string.  Empty string, if there is no more
+ * remaining output.
+ */
+#define EC_CMD_CONSOLE_READ 0x98
+
+/*****************************************************************************/
+
+/*
+ * Cut off battery power output if the battery supports.
+ *
+ * For unsupported battery, just don't implement this command and lets EC
+ * return EC_RES_INVALID_COMMAND.
+ */
+#define EC_CMD_BATTERY_CUT_OFF 0x99
+
+/*****************************************************************************/
+/* USB port mux control. */
+
+/*
+ * Switch USB mux or return to automatic switching.
+ */
+#define EC_CMD_USB_MUX 0x9a
+
+struct ec_params_usb_mux {
+       uint8_t mux;
+} __packed;
+
+/*****************************************************************************/
+/* LDOs / FETs control. */
+
+enum ec_ldo_state {
+       EC_LDO_STATE_OFF = 0,   /* the LDO / FET is shut down */
+       EC_LDO_STATE_ON = 1,    /* the LDO / FET is ON / providing power */
+};
+
+/*
+ * Switch on/off a LDO.
+ */
+#define EC_CMD_LDO_SET 0x9b
+
+struct ec_params_ldo_set {
+       uint8_t index;
+       uint8_t state;
+} __packed;
+
+/*
+ * Get LDO state.
+ */
+#define EC_CMD_LDO_GET 0x9c
+
+struct ec_params_ldo_get {
+       uint8_t index;
+} __packed;
+
+struct ec_response_ldo_get {
+       uint8_t state;
+} __packed;
+
+/*****************************************************************************/
+/* Temporary debug commands. TODO: remove this crosbug.com/p/13849 */
+
+/*
+ * Dump charge state machine context.
+ *
+ * Response is a binary dump of charge state machine context.
+ */
+#define EC_CMD_CHARGE_DUMP 0xa0
+
+/*
+ * Set maximum battery charging current.
+ */
+#define EC_CMD_CHARGE_CURRENT_LIMIT 0xa1
+
+struct ec_params_current_limit {
+       uint32_t limit;
+} __packed;
+
+/*****************************************************************************/
+/* Smart battery pass-through */
+
+/* Get / Set 16-bit smart battery registers */
+#define EC_CMD_SB_READ_WORD   0xb0
+#define EC_CMD_SB_WRITE_WORD  0xb1
+
+/* Get / Set string smart battery parameters
+ * formatted as SMBUS "block".
+ */
+#define EC_CMD_SB_READ_BLOCK  0xb2
+#define EC_CMD_SB_WRITE_BLOCK 0xb3
+
+struct ec_params_sb_rd {
+       uint8_t reg;
+} __packed;
+
+struct ec_response_sb_rd_word {
+       uint16_t value;
+} __packed;
+
+struct ec_params_sb_wr_word {
+       uint8_t reg;
+       uint16_t value;
+} __packed;
+
+struct ec_response_sb_rd_block {
+       uint8_t data[32];
+} __packed;
+
+struct ec_params_sb_wr_block {
+       uint8_t reg;
+       uint16_t data[32];
+} __packed;
+
+/*****************************************************************************/
+/* System commands */
+
+/*
+ * TODO: this is a confusing name, since it doesn't necessarily reboot the EC.
+ * Rename to "set image" or something similar.
+ */
+#define EC_CMD_REBOOT_EC 0xd2
+
+/* Command */
+enum ec_reboot_cmd {
+       EC_REBOOT_CANCEL = 0,        /* Cancel a pending reboot */
+       EC_REBOOT_JUMP_RO = 1,       /* Jump to RO without rebooting */
+       EC_REBOOT_JUMP_RW = 2,       /* Jump to RW without rebooting */
+       /* (command 3 was jump to RW-B) */
+       EC_REBOOT_COLD = 4,          /* Cold-reboot */
+       EC_REBOOT_DISABLE_JUMP = 5,  /* Disable jump until next reboot */
+       EC_REBOOT_HIBERNATE = 6      /* Hibernate EC */
+};
+
+/* Flags for ec_params_reboot_ec.reboot_flags */
+#define EC_REBOOT_FLAG_RESERVED0      (1 << 0)  /* Was recovery request */
+#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1)  /* Reboot after AP shutdown */
+
+struct ec_params_reboot_ec {
+       uint8_t cmd;           /* enum ec_reboot_cmd */
+       uint8_t flags;         /* See EC_REBOOT_FLAG_* */
+} __packed;
+
+/*
+ * Get information on last EC panic.
+ *
+ * Returns variable-length platform-dependent panic information.  See panic.h
+ * for details.
+ */
+#define EC_CMD_GET_PANIC_INFO 0xd3
+
+/*****************************************************************************/
+/*
+ * ACPI commands
+ *
+ * These are valid ONLY on the ACPI command/data port.
+ */
+
+/*
+ * ACPI Read Embedded Controller
+ *
+ * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*).
+ *
+ * Use the following sequence:
+ *
+ *    - Write EC_CMD_ACPI_READ to EC_LPC_ADDR_ACPI_CMD
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write address to EC_LPC_ADDR_ACPI_DATA
+ *    - Wait for EC_LPC_CMDR_DATA bit to set
+ *    - Read value from EC_LPC_ADDR_ACPI_DATA
+ */
+#define EC_CMD_ACPI_READ 0x80
+
+/*
+ * ACPI Write Embedded Controller
+ *
+ * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*).
+ *
+ * Use the following sequence:
+ *
+ *    - Write EC_CMD_ACPI_WRITE to EC_LPC_ADDR_ACPI_CMD
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write address to EC_LPC_ADDR_ACPI_DATA
+ *    - Wait for EC_LPC_CMDR_PENDING bit to clear
+ *    - Write value to EC_LPC_ADDR_ACPI_DATA
+ */
+#define EC_CMD_ACPI_WRITE 0x81
+
+/*
+ * ACPI Query Embedded Controller
+ *
+ * This clears the lowest-order bit in the currently pending host events, and
+ * sets the result code to the 1-based index of the bit (event 0x00000001 = 1,
+ * event 0x80000000 = 32), or 0 if no event was pending.
+ */
+#define EC_CMD_ACPI_QUERY_EVENT 0x84
+
+/* Valid addresses in ACPI memory space, for read/write commands */
+/* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */
+#define EC_ACPI_MEM_VERSION            0x00
+/*
+ * Test location; writing value here updates test compliment byte to (0xff -
+ * value).
+ */
+#define EC_ACPI_MEM_TEST               0x01
+/* Test compliment; writes here are ignored. */
+#define EC_ACPI_MEM_TEST_COMPLIMENT    0x02
+/* Keyboard backlight brightness percent (0 - 100) */
+#define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03
+
+/* Current version of ACPI memory address space */
+#define EC_ACPI_MEM_VERSION_CURRENT 1
+
+
+/*****************************************************************************/
+/*
+ * Special commands
+ *
+ * These do not follow the normal rules for commands.  See each command for
+ * details.
+ */
+
+/*
+ * Reboot NOW
+ *
+ * This command will work even when the EC LPC interface is busy, because the
+ * reboot command is processed at interrupt level.  Note that when the EC
+ * reboots, the host will reboot too, so there is no response to this command.
+ *
+ * Use EC_CMD_REBOOT_EC to reboot the EC more politely.
+ */
+#define EC_CMD_REBOOT 0xd1  /* Think "die" */
+
+/*
+ * Resend last response (not supported on LPC).
+ *
+ * Returns EC_RES_UNAVAILABLE if there is no response available - for example,
+ * there was no previous command, or the previous command's response was too
+ * big to save.
+ */
+#define EC_CMD_RESEND_RESPONSE 0xdb
+
+/*
+ * This header byte on a command indicate version 0. Any header byte less
+ * than this means that we are talking to an old EC which doesn't support
+ * versioning. In that case, we assume version 0.
+ *
+ * Header bytes greater than this indicate a later version. For example,
+ * EC_CMD_VERSION0 + 1 means we are using version 1.
+ *
+ * The old EC interface must not use commands 0dc or higher.
+ */
+#define EC_CMD_VERSION0 0xdc
+
+#endif  /* !__ACPI__ */
+
+#endif  /* __CROS_EC_COMMANDS_H */
index 1ece6122f5dfa1e0db21b2e4809267b780db1678..d93e102ac6e9578f72e29cd8994bd31491e3d2c3 100644 (file)
@@ -84,11 +84,14 @@ enum fdt_compat_id {
        COMPAT_SAMSUNG_EXYNOS5_SOUND,   /* Exynos Sound */
        COMPAT_WOLFSON_WM8994_CODEC,    /* Wolfson WM8994 Sound Codec */
        COMPAT_SAMSUNG_EXYNOS_SPI,      /* Exynos SPI */
+       COMPAT_GOOGLE_CROS_EC,          /* Google CROS_EC Protocol */
+       COMPAT_GOOGLE_CROS_EC_KEYB,     /* Google CROS_EC Keyboard */
        COMPAT_SAMSUNG_EXYNOS_EHCI,     /* Exynos EHCI controller */
        COMPAT_SAMSUNG_EXYNOS_USB_PHY,  /* Exynos phy controller for usb2.0 */
        COMPAT_SAMSUNG_EXYNOS_TMU,      /* Exynos TMU */
        COMPAT_SAMSUNG_EXYNOS_FIMD,     /* Exynos Display controller */
        COMPAT_SAMSUNG_EXYNOS5_DP,      /* Exynos Display port controller */
+       COMPAT_SAMSUNG_EXYNOS5_DWMMC,   /* Exynos5 DWMMC controller */
        COMPAT_MAXIM_MAX77686_PMIC,     /* MAX77686 PMIC */
        COMPAT_GENERIC_SPI_FLASH,       /* Generic SPI Flash chip */
        COMPAT_MAXIM_98095_CODEC,       /* MAX98095 Codec */
index afea85cdc2cb3b5739e390d3bd02001f782fe9d3..f691a74ab46a9dc177379eb52077efdc67e81d15 100644 (file)
@@ -54,8 +54,9 @@ typedef ulong lbaint_t;
  */
 
 void ide_init(void);
-ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer);
-ulong ide_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer);
+ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer);
+ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt,
+               const void *buffer);
 
 #ifdef CONFIG_IDE_PREINIT
 int ide_preinit(void);
index 8ccc00b76a13c71a46a380459c9220fc3f9aeb89..a7b93dbef76fe8e5f8ac03e3880e84759824a43f 100644 (file)
@@ -320,13 +320,16 @@ typedef struct bootm_headers {
        int             verify;         /* getenv("verify")[0] != 'n' */
 
 #define        BOOTM_STATE_START       (0x00000001)
-#define        BOOTM_STATE_LOADOS      (0x00000002)
-#define        BOOTM_STATE_RAMDISK     (0x00000004)
-#define        BOOTM_STATE_FDT         (0x00000008)
-#define        BOOTM_STATE_OS_CMDLINE  (0x00000010)
-#define        BOOTM_STATE_OS_BD_T     (0x00000020)
-#define        BOOTM_STATE_OS_PREP     (0x00000040)
-#define        BOOTM_STATE_OS_GO       (0x00000080)
+#define        BOOTM_STATE_FINDOS      (0x00000002)
+#define        BOOTM_STATE_FINDOTHER   (0x00000004)
+#define        BOOTM_STATE_LOADOS      (0x00000008)
+#define        BOOTM_STATE_RAMDISK     (0x00000010)
+#define        BOOTM_STATE_FDT         (0x00000020)
+#define        BOOTM_STATE_OS_CMDLINE  (0x00000040)
+#define        BOOTM_STATE_OS_BD_T     (0x00000080)
+#define        BOOTM_STATE_OS_PREP     (0x00000100)
+#define        BOOTM_STATE_OS_FAKE_GO  (0x00000200)    /* 'Almost' run the OS */
+#define        BOOTM_STATE_OS_GO       (0x00000400)
        int             state;
 
 #ifdef CONFIG_LMB
@@ -667,11 +670,12 @@ int image_setup_linux(bootm_headers_t *images);
 #define FIT_IMAGES_PATH                "/images"
 #define FIT_CONFS_PATH         "/configurations"
 
-/* hash node */
+/* hash/signature node */
 #define FIT_HASH_NODENAME      "hash"
 #define FIT_ALGO_PROP          "algo"
 #define FIT_VALUE_PROP         "value"
 #define FIT_IGNORE_PROP                "uboot-ignore"
+#define FIT_SIG_NODENAME       "signature"
 
 /* image node */
 #define FIT_DATA_PROP          "data"
@@ -759,12 +763,26 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
 int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
 
 /**
- * fit_add_verification_data() - Calculate and add hashes to FIT
+ * fit_add_verification_data() - add verification data to FIT image nodes
  *
- * @fit:       Fit image to process
- * @return 0 if ok, <0 for error
+ * @keydir:    Directory containing keys
+ * @kwydest:   FDT blob to write public key information to
+ * @fit:       Pointer to the FIT format image header
+ * @comment:   Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ *
+ * Adds hash values for all component images in the FIT blob.
+ * Hashes are calculated for all component images which have hash subnodes
+ * with algorithm property set to one of the supported hash algorithms.
+ *
+ * Also add signatures if signature nodes are present.
+ *
+ * returns
+ *     0, on success
+ *     libfdt error code, on failure
  */
-int fit_add_verification_data(void *fit);
+int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+                             const char *comment, int require_keys);
 
 int fit_image_verify(const void *fit, int noffset);
 int fit_config_verify(const void *fit, int conf_noffset);
@@ -801,15 +819,19 @@ int calculate_hash(const void *data, int data_len, const char *algo,
                        uint8_t *value, int *value_len);
 
 /*
- * At present we only support verification on the device
+ * At present we only support signing on the host, and verification on the
+ * device
  */
 #if defined(CONFIG_FIT_SIGNATURE)
 # ifdef USE_HOSTCC
+#  define IMAGE_ENABLE_SIGN    1
 #  define IMAGE_ENABLE_VERIFY  0
 #else
+#  define IMAGE_ENABLE_SIGN    0
 #  define IMAGE_ENABLE_VERIFY  1
 # endif
 #else
+# define IMAGE_ENABLE_SIGN     0
 # define IMAGE_ENABLE_VERIFY   0
 #endif
 
@@ -825,6 +847,137 @@ int calculate_hash(const void *data, int data_len, const char *algo,
 #define IMAGE_ENABLE_BEST_MATCH        0
 #endif
 
+/* Information passed to the signing routines */
+struct image_sign_info {
+       const char *keydir;             /* Directory conaining keys */
+       const char *keyname;            /* Name of key to use */
+       void *fit;                      /* Pointer to FIT blob */
+       int node_offset;                /* Offset of signature node */
+       struct image_sig_algo *algo;    /* Algorithm information */
+       const void *fdt_blob;           /* FDT containing public keys */
+       int required_keynode;           /* Node offset of key to use: -1=any */
+       const char *require_keys;       /* Value for 'required' property */
+};
+
+/* A part of an image, used for hashing */
+struct image_region {
+       const void *data;
+       int size;
+};
+
+struct image_sig_algo {
+       const char *name;               /* Name of algorithm */
+
+       /**
+        * sign() - calculate and return signature for given input data
+        *
+        * @info:       Specifies key and FIT information
+        * @data:       Pointer to the input data
+        * @data_len:   Data length
+        * @sigp:       Set to an allocated buffer holding the signature
+        * @sig_len:    Set to length of the calculated hash
+        *
+        * This computes input data signature according to selected algorithm.
+        * Resulting signature value is placed in an allocated buffer, the
+        * pointer is returned as *sigp. The length of the calculated
+        * signature is returned via the sig_len pointer argument. The caller
+        * should free *sigp.
+        *
+        * @return: 0, on success, -ve on error
+        */
+       int (*sign)(struct image_sign_info *info,
+                   const struct image_region region[],
+                   int region_count, uint8_t **sigp, uint *sig_len);
+
+       /**
+        * add_verify_data() - Add verification information to FDT
+        *
+        * Add public key information to the FDT node, suitable for
+        * verification at run-time. The information added depends on the
+        * algorithm being used.
+        *
+        * @info:       Specifies key and FIT information
+        * @keydest:    Destination FDT blob for public key data
+        * @return: 0, on success, -ve on error
+        */
+       int (*add_verify_data)(struct image_sign_info *info, void *keydest);
+
+       /**
+        * verify() - Verify a signature against some data
+        *
+        * @info:       Specifies key and FIT information
+        * @data:       Pointer to the input data
+        * @data_len:   Data length
+        * @sig:        Signature
+        * @sig_len:    Number of bytes in signature
+        * @return 0 if verified, -ve on error
+        */
+       int (*verify)(struct image_sign_info *info,
+                     const struct image_region region[], int region_count,
+                     uint8_t *sig, uint sig_len);
+};
+
+/**
+ * image_get_sig_algo() - Look up a signature algortihm
+ *
+ * @param name         Name of algorithm
+ * @return pointer to algorithm information, or NULL if not found
+ */
+struct image_sig_algo *image_get_sig_algo(const char *name);
+
+/**
+ * fit_image_verify_required_sigs() - Verify signatures marked as 'required'
+ *
+ * @fit:               FIT to check
+ * @image_noffset:     Offset of image node to check
+ * @data:              Image data to check
+ * @size:              Size of image data
+ * @sig_blob:          FDT containing public keys
+ * @no_sigsp:          Returns 1 if no signatures were required, and
+ *                     therefore nothing was checked. The caller may wish
+ *                     to fall back to other mechanisms, or refuse to
+ *                     boot.
+ * @return 0 if all verified ok, <0 on error
+ */
+int fit_image_verify_required_sigs(const void *fit, int image_noffset,
+               const char *data, size_t size, const void *sig_blob,
+               int *no_sigsp);
+
+/**
+ * fit_image_check_sig() - Check a single image signature node
+ *
+ * @fit:               FIT to check
+ * @noffset:           Offset of signature node to check
+ * @data:              Image data to check
+ * @size:              Size of image data
+ * @required_keynode:  Offset in the control FDT of the required key node,
+ *                     if any. If this is given, then the image wil not
+ *                     pass verification unless that key is used. If this is
+ *                     -1 then any signature will do.
+ * @err_msgp:          In the event of an error, this will be pointed to a
+ *                     help error string to display to the user.
+ * @return 0 if all verified ok, <0 on error
+ */
+int fit_image_check_sig(const void *fit, int noffset, const void *data,
+               size_t size, int required_keynode, char **err_msgp);
+
+/**
+ * fit_region_make_list() - Make a list of regions to hash
+ *
+ * Given a list of FIT regions (offset, size) provided by libfdt, create
+ * a list of regions (void *, size) for use by the signature creationg
+ * and verification code.
+ *
+ * @fit:               FIT image to process
+ * @fdt_regions:       Regions as returned by libfdt
+ * @count:             Number of regions returned by libfdt
+ * @region:            Place to put list of regions (NULL to allocate it)
+ * @return pointer to list of regions, or NULL if out of memory
+ */
+struct image_region *fit_region_make_list(const void *fit,
+               struct fdt_region *fdt_regions, int count,
+               struct image_region *region);
+
 static inline int fit_image_check_target_arch(const void *fdt, int node)
 {
        return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT);
index c5ec2acfd82927f070923e118766aad22986b3a9..765d84f5e4574eaab187be553cdbd449bf22b819 100644 (file)
@@ -1511,4 +1511,68 @@ int fdt_del_node(void *fdt, int nodeoffset);
 
 const char *fdt_strerror(int errval);
 
+struct fdt_region {
+       int offset;
+       int size;
+};
+
+/**
+ * fdt_find_regions() - find regions in device tree
+ *
+ * Given a list of nodes to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ *
+ * Nodes which are given in 'inc' are included in the region list, as
+ * are the names of the immediate subnodes nodes (but not the properties
+ * or subnodes of those subnodes).
+ *
+ * For eaxample "/" means to include the root node, all root properties
+ * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
+ * ensures that we capture the names of the subnodes. In a hashing situation
+ * it prevents the root node from changing at all Any change to non-excluded
+ * properties, names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too.
+ *
+ * The device tree header is not included in the list.
+ *
+ * @fdt:       Device tree to check
+ * @inc:       List of node paths to included
+ * @inc_count: Number of node paths in list
+ * @exc_prop:  List of properties names to exclude
+ * @exc_prop_count:    Number of properties in exclude list
+ * @region:    Returns list of regions
+ * @max_region:        Maximum length of region list
+ * @path:      Pointer to a temporary string for the function to use for
+ *             building path names
+ * @path_len:  Length of path, must be large enough to hold the longest
+ *             path in the tree
+ * @add_string_tab:    1 to add a region for the string table
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again.
+ */
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+                    char * const exc_prop[], int exc_prop_count,
+                    struct fdt_region region[], int max_regions,
+                    char *path, int path_len, int add_string_tab);
+
 #endif /* _LIBFDT_H */
index fcb20fe1082f7047f9fe8037a514d3aea9c45742..f6dbdb096d34c220d12962fe627bc8eb3e401ea0 100644 (file)
@@ -580,6 +580,8 @@ enum ethtool_sfeatures_retval_bits {
 #define SUPPORTED_10000baseKX4_Full    (1 << 18)
 #define SUPPORTED_10000baseKR_Full     (1 << 19)
 #define SUPPORTED_10000baseR_FEC       (1 << 20)
+#define SUPPORTED_1000baseX_Half       (1 << 21)
+#define SUPPORTED_1000baseX_Full       (1 << 22)
 
 /* Indicates what features are advertised by the interface. */
 #define ADVERTISED_10baseT_Half                (1 << 0)
@@ -603,6 +605,8 @@ enum ethtool_sfeatures_retval_bits {
 #define ADVERTISED_10000baseKX4_Full   (1 << 18)
 #define ADVERTISED_10000baseKR_Full    (1 << 19)
 #define ADVERTISED_10000baseR_FEC      (1 << 20)
+#define ADVERTISED_1000baseX_Half      (1 << 21)
+#define ADVERTISED_1000baseX_Full      (1 << 22)
 
 /* The following are all involved in forcing a particular link
  * mode for the device for setting things.  When getting the
index 8b92692146d687db55c61e62c640f745176da509..66b83d83deb4fc5d285e8ad89ca27f0cab3acad4 100644 (file)
 #define EXPANSION_MFAULTS      0x0010  /* Multiple faults detected    */
 #define EXPANSION_RESV         0xffe0  /* Unused...                   */
 
+#define ESTATUS_1000_XFULL     0x8000  /* Can do 1000BX Full */
+#define ESTATUS_1000_XHALF     0x4000  /* Can do 1000BX Half */
 #define ESTATUS_1000_TFULL     0x2000  /* Can do 1000BT Full */
 #define ESTATUS_1000_THALF     0x1000  /* Can do 1000BT Half */
 
index 25e8a4624b75978c2af1f38508d9fc369c0e6db7..e1c62d83cb3d6a0cc890f7b696d6905b49c17ee7 100644 (file)
@@ -8,9 +8,20 @@
 #define MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW     0x105
 #define MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW     0x106
 #define MII_KSZ9021_EXT_ANALOG_TEST            0x107
+/* Register operations */
+#define MII_KSZ9031_MOD_REG                    0x0000
+/* Data operations */
+#define MII_KSZ9031_MOD_DATA_NO_POST_INC       0x4000
+#define MII_KSZ9031_MOD_DATA_POST_INC_RW       0x8000
+#define MII_KSZ9031_MOD_DATA_POST_INC_W                0xC000
 
 struct phy_device;
 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val);
 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum);
 
+int ksz9031_phy_extended_write(struct phy_device *phydev, int devaddr,
+                              int regnum, u16 mode, u16 val);
+int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
+                             int regnum, u16 mode);
+
 #endif
index ea198d87b7a3228d8310c49d90f18004e3ac0565..583c30e270fa1c4af7af70c089143a8494cdbb78 100644 (file)
 #define MMC_CMD_APP_CMD                        55
 #define MMC_CMD_SPI_READ_OCR           58
 #define MMC_CMD_SPI_CRC_ON_OFF         59
+#define MMC_CMD_RES_MAN                        62
+
+#define MMC_CMD62_ARG1                 0xefac62ec
+#define MMC_CMD62_ARG2                 0xcbaea7
+
 
 #define SD_CMD_SEND_RELATIVE_ADDR      3
 #define SD_CMD_SWITCH_FUNC             6
 #define EXT_CSD_PARTITIONING_SUPPORT   160     /* RO */
 #define EXT_CSD_RPMB_MULT              168     /* RO */
 #define EXT_CSD_ERASE_GROUP_DEF                175     /* R/W */
+#define EXT_CSD_BOOT_BUS_WIDTH         177
 #define EXT_CSD_PART_CONF              179     /* R/W */
 #define EXT_CSD_BUS_WIDTH              183     /* R/W */
 #define EXT_CSD_HS_TIMING              185     /* R/W */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
 #define EXT_CSD_BUS_WIDTH_8    2       /* Card is in 8 bit mode */
 
+#define EXT_CSD_BOOT_ACK_ENABLE                        (1 << 6)
+#define EXT_CSD_BOOT_PARTITION_ENABLE          (1 << 3)
+#define EXT_CSD_PARTITION_ACCESS_ENABLE                (1 << 0)
+#define EXT_CSD_PARTITION_ACCESS_DISABLE       (0 << 0)
+
+#define EXT_CSD_BOOT_ACK(x)            (x << 6)
+#define EXT_CSD_BOOT_PART_NUM(x)       (x << 3)
+#define EXT_CSD_PARTITION_ACCESS(x)    (x << 0)
+
+
 #define R1_ILLEGAL_COMMAND             (1 << 22)
 #define R1_APP_CMD                     (1 << 5)
 
 /* Maximum block size for MMC */
 #define MMC_MAX_BLOCK_LEN      512
 
+/* The number of MMC physical partitions.  These consist of:
+ * boot partitions (2), general purpose partitions (4) in MMC v4.4.
+ */
+#define MMC_NUM_BOOT_PARTITION 2
+
 struct mmc_cid {
        unsigned long psn;
        unsigned short oid;
@@ -298,6 +319,11 @@ int mmc_switch_part(int dev_num, unsigned int part_num);
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
 void spl_mmc_load(void) __noreturn;
+/* Function to change the size of boot partition and rpmb partitions */
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+                                       unsigned long rpmbsize);
+/* Function to send commands to open/close the specified boot partition */
+int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access);
 
 /**
  * Start device initialization and return immediately; it does not block on
index 23fb947292ccf3e1e1b805e86c11ac75106f3107..7673470046f596263e170d0facbdffba74540299 100644 (file)
@@ -39,7 +39,7 @@
 #define PKTALIGN       ARCH_DMA_MINALIGN
 
 /* IPv4 addresses are always 32 bits in size */
-typedef u32            IPaddr_t;
+typedef __be32         IPaddr_t;
 
 
 /**
index df454b50c3bc4fdcff762313e4b958a165e342f7..917d8746fb04c7e7175c8faafda30c41748f22b1 100644 (file)
@@ -67,10 +67,12 @@ int fecmxc_initialize(bd_t *bis);
 int fecmxc_initialize_multi(bd_t *bis, int dev_id, int phy_id, uint32_t addr);
 int ftgmac100_initialize(bd_t *bits);
 int ftmac100_initialize(bd_t *bits);
+int ftmac110_initialize(bd_t *bits);
 int greth_initialize(bd_t *bis);
 void gt6426x_eth_initialize(bd_t *bis);
 int inca_switch_initialize(bd_t *bis);
 int ks8695_eth_initialize(void);
+int ks8851_mll_initialize(u8 dev_num, int base_addr);
 int lan91c96_initialize(u8 dev_num, int base_addr);
 int macb_eth_initialize(int id, void *regs, unsigned int phy_addr);
 int mcdmafec_initialize(bd_t *bis);
@@ -93,6 +95,7 @@ int sh_eth_initialize(bd_t *bis);
 int skge_initialize(bd_t *bis);
 int smc91111_initialize(u8 dev_num, int base_addr);
 int smc911x_initialize(u8 dev_num, int base_addr);
+int sunxi_wemac_initialize(bd_t *bis);
 int tsi108_eth_initialize(bd_t *bis);
 int uec_standard_init(bd_t *bis);
 int uli526x_initialize(bd_t *bis);
index f7c7cc59fca2dccb41635e1f28666aed60234449..35c1c5b5f58bf54f573ac696c550ccad385731ea 100644 (file)
@@ -43,15 +43,15 @@ typedef struct block_dev_desc {
        char            product[20+1];  /* IDE Serial no, SCSI product */
        char            revision[8+1];  /* firmware revision */
        unsigned long   (*block_read)(int dev,
-                                     unsigned long start,
+                                     lbaint_t start,
                                      lbaint_t blkcnt,
                                      void *buffer);
        unsigned long   (*block_write)(int dev,
-                                      unsigned long start,
+                                      lbaint_t start,
                                       lbaint_t blkcnt,
                                       const void *buffer);
        unsigned long   (*block_erase)(int dev,
-                                      unsigned long start,
+                                      lbaint_t start,
                                       lbaint_t blkcnt);
        void            *priv;          /* driver private struct pointer */
 }block_dev_desc_t;
index f9c51482550d7cd6980d16d0e2659c287ec799d5..98ba151f900f0606a55d8cdf2a819b26ff199343 100644 (file)
@@ -462,7 +462,7 @@ struct pci_region {
 #define PCI_REGION_SYS_MEMORY  0x00000100      /* System memory */
 #define PCI_REGION_RO          0x00000200      /* Read-only memory */
 
-extern __inline__ void pci_set_region(struct pci_region *reg,
+static inline void pci_set_region(struct pci_region *reg,
                                      pci_addr_t bus_start,
                                      phys_addr_t phys_start,
                                      pci_size_t size,
@@ -548,7 +548,7 @@ struct pci_controller {
        void *priv_data;
 };
 
-extern __inline__ void pci_set_ops(struct pci_controller *hose,
+static inline void pci_set_ops(struct pci_controller *hose,
                                   int (*read_byte)(struct pci_controller*,
                                                    pci_dev_t, int where, u8 *),
                                   int (*read_word)(struct pci_controller*,
index 75bf3b4728d62f8c8308b3fa642306d80145471f..dbf32740bb3c252c8090b507f1f8717089825895 100644 (file)
@@ -214,6 +214,7 @@ int phy_register(struct phy_driver *drv);
 int genphy_config_aneg(struct phy_device *phydev);
 int genphy_restart_aneg(struct phy_device *phydev);
 int genphy_update_link(struct phy_device *phydev);
+int genphy_parse_link(struct phy_device *phydev);
 int genphy_config(struct phy_device *phydev);
 int genphy_startup(struct phy_device *phydev);
 int genphy_shutdown(struct phy_device *phydev);
diff --git a/include/rsa.h b/include/rsa.h
new file mode 100644 (file)
index 0000000..a5dd676
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _RSA_H
+#define _RSA_H
+
+#include <errno.h>
+#include <image.h>
+
+#if IMAGE_ENABLE_SIGN
+/**
+ * sign() - calculate and return signature for given input data
+ *
+ * @info:      Specifies key and FIT information
+ * @data:      Pointer to the input data
+ * @data_len:  Data length
+ * @sigp:      Set to an allocated buffer holding the signature
+ * @sig_len:   Set to length of the calculated hash
+ *
+ * This computes input data signature according to selected algorithm.
+ * Resulting signature value is placed in an allocated buffer, the
+ * pointer is returned as *sigp. The length of the calculated
+ * signature is returned via the sig_len pointer argument. The caller
+ * should free *sigp.
+ *
+ * @return: 0, on success, -ve on error
+ */
+int rsa_sign(struct image_sign_info *info,
+            const struct image_region region[],
+            int region_count, uint8_t **sigp, uint *sig_len);
+
+/**
+ * add_verify_data() - Add verification information to FDT
+ *
+ * Add public key information to the FDT node, suitable for
+ * verification at run-time. The information added depends on the
+ * algorithm being used.
+ *
+ * @info:      Specifies key and FIT information
+ * @keydest:   Destination FDT blob for public key data
+ * @return: 0, on success, -ve on error
+*/
+int rsa_add_verify_data(struct image_sign_info *info, void *keydest);
+#else
+static inline int rsa_sign(struct image_sign_info *info,
+               const struct image_region region[], int region_count,
+               uint8_t **sigp, uint *sig_len)
+{
+       return -ENXIO;
+}
+
+static inline int rsa_add_verify_data(struct image_sign_info *info,
+                                     void *keydest)
+{
+       return -ENXIO;
+}
+#endif
+
+#if IMAGE_ENABLE_VERIFY
+/**
+ * rsa_verify() - Verify a signature against some data
+ *
+ * Verify a RSA PKCS1.5 signature against an expected hash.
+ *
+ * @info:      Specifies key and FIT information
+ * @data:      Pointer to the input data
+ * @data_len:  Data length
+ * @sig:       Signature
+ * @sig_len:   Number of bytes in signature
+ * @return 0 if verified, -ve on error
+ */
+int rsa_verify(struct image_sign_info *info,
+              const struct image_region region[], int region_count,
+              uint8_t *sig, uint sig_len);
+#else
+static inline int rsa_verify(struct image_sign_info *info,
+               const struct image_region region[], int region_count,
+               uint8_t *sig, uint sig_len)
+{
+       return -ENXIO;
+}
+#endif
+
+#endif
index 1638b503945071c9ccbd5486a870ac1814160779..e8e654467fde1476d7ec25e4bde1e6af32802714 100644 (file)
@@ -247,4 +247,20 @@ static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte)
        return ret < 0 ? ret : din[1];
 }
 
+/**
+ * Set up a SPI slave for a particular device tree node
+ *
+ * This calls spi_setup_slave() with the correct bus number. Call
+ * spi_free_slave() to free it later.
+ *
+ * @param blob         Device tree blob
+ * @param node         SPI peripheral node to use
+ * @param cs           Chip select to use
+ * @param max_hz       Maximum SCK rate in Hz (0 for default)
+ * @param mode         Clock polarity, clock phase and other parameters
+ * @return pointer to new spi_slave structure
+ */
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int node,
+               unsigned int cs, unsigned int max_hz, unsigned int mode);
+
 #endif /* _SPI_H_ */
index 3b6a44edcef6a1e8707ecd20572f191c9f05da46..e80785f55ef578ac989ceef262391bb602abdcec 100644 (file)
@@ -38,6 +38,16 @@ struct spi_flash {
        u32             page_size;
        /* Erase (sector) size */
        u32             sector_size;
+#ifdef CONFIG_SPI_FLASH_BAR
+       /* Bank read cmd */
+       u8              bank_read_cmd;
+       /* Bank write cmd */
+       u8              bank_write_cmd;
+       /* Current flash bank */
+       u8              bank_curr;
+#endif
+       /* Poll cmd - for flash erase/program */
+       u8              poll_cmd;
 
        void *memory_map;       /* Address of read-only SPI flash access */
        int             (*read)(struct spi_flash *flash, u32 offset,
diff --git a/include/trace.h b/include/trace.h
new file mode 100644 (file)
index 0000000..8082466
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __TRACE_H
+#define __TRACE_H
+
+enum {
+       /*
+        * This affects the granularity of our trace. We can bin function
+        * entry points into groups on the basis that functions typically
+        * have a minimum size, so entry points can't appear any closer
+        * than this to each other.
+        *
+        * The value here assumes a minimum instruction size of 4 bytes,
+        * or that instructions are 2 bytes but there are at least 2 of
+        * them in every function.
+        *
+        * Increasing this value reduces the number of functions we can
+        * resolve, but reduces the size of the uintptr_t array used for
+        * our function list, which is the length of the code divided by
+        * this value.
+        */
+       FUNC_SITE_SIZE  = 4,    /* distance between function sites */
+};
+
+enum trace_chunk_type {
+       TRACE_CHUNK_FUNCS,
+       TRACE_CHUNK_CALLS,
+};
+
+/* A trace record for a function, as written to the profile output file */
+struct trace_output_func {
+       uint32_t offset;                /* Function offset into code */
+       uint32_t call_count;            /* Number of times called */
+};
+
+/* A header at the start of the trace output buffer */
+struct trace_output_hdr {
+       enum trace_chunk_type type;     /* Record type */
+       uint32_t rec_count;             /* Number of records */
+};
+
+/* Print statistics about traced function calls */
+void trace_print_stats(void);
+
+/**
+ * Dump a list of functions and call counts into a buffer
+ *
+ * Each record in the buffer is a struct trace_func_stats. The 'needed'
+ * parameter returns the number of bytes needed to complete the operation,
+ * which may be more than buff_size if your buffer is too small.
+ *
+ * @param buff         Buffer in which to place data, or NULL to count size
+ * @param buff_size    Size of buffer
+ * @param needed       Returns number of bytes used / needed
+ * @return 0 if ok, -1 on error (buffer exhausted)
+ */
+int trace_list_functions(void *buff, int buff_size, unsigned *needed);
+
+/* Flags for ftrace_record */
+enum ftrace_flags {
+       FUNCF_EXIT              = 0UL << 30,
+       FUNCF_ENTRY             = 1UL << 30,
+       FUNCF_TEXTBASE          = 2UL << 30,
+
+       FUNCF_TIMESTAMP_MASK    = 0x3fffffff,
+};
+
+#define TRACE_CALL_TYPE(call)  ((call)->flags & 0xc0000000UL)
+
+/* Information about a single function entry/exit */
+struct trace_call {
+       uint32_t func;          /* Function offset */
+       uint32_t caller;        /* Caller function offset */
+       uint32_t flags;         /* Flags and timestamp */
+};
+
+int trace_list_calls(void *buff, int buff_size, unsigned int *needed);
+
+/**
+ * Turn function tracing on and off
+ *
+ * Don't enable trace if it has not been initialised.
+ *
+ * @param enabled      1 to enable trace, 0 to disable
+ */
+void trace_set_enabled(int enabled);
+
+#ifdef CONFIG_TRACE_EARLY
+int trace_early_init(void);
+#else
+static inline int trace_early_init(void)
+{
+       return 0;
+}
+#endif
+
+/**
+ * Init the trace system
+ *
+ * This should be called after relocation with a suitably large buffer
+ * (typically as large as the U-Boot text area)
+ *
+ * @param buff         Pointer to trace buffer
+ * @param buff_size    Size of trace buffer
+ */
+int trace_init(void *buff, size_t buff_size);
+
+#endif
index 651077ca4daa8449c76d3fba4ef796e95dd1094e..6568854fbe1badc1d106fabba2dcf595667cd087 100644 (file)
@@ -178,4 +178,15 @@ int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
 #define vscnprintf(buf, size, fmt, args...) vsprintf(buf, fmt, ##args)
 #endif /* CONFIG_SYS_VSNPRINTF */
 
+/**
+ * print_grouped_ull() - print a value with digits grouped by ','
+ *
+ * This prints a value with grouped digits, like 12,345,678 to make it easier
+ * to read.
+ *
+ * @val:       Value to print
+ * @digits:    Number of digiits to print
+ */
+void print_grouped_ull(unsigned long long int_val, int digits);
+
 #endif
index 5d586098dd5e850d7a7060d2c61119b42e2ec08e..f5a8819f398d672e17a6ed2f22310a2d7782804b 100644 (file)
@@ -26,7 +26,6 @@ include $(TOPDIR)/config.mk
 LIB    = $(obj)libgeneric.o
 
 ifndef CONFIG_SPL_BUILD
-COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
 COBJS-$(CONFIG_AES) += aes.o
 COBJS-$(CONFIG_BZIP2) += bzlib.o
 COBJS-$(CONFIG_BZIP2) += bzlib_crctable.o
@@ -36,13 +35,10 @@ COBJS-$(CONFIG_BZIP2) += bzlib_huffman.o
 COBJS-$(CONFIG_USB_TTY) += circbuf.o
 COBJS-y += crc7.o
 COBJS-y += crc16.o
-COBJS-y += display_options.o
-COBJS-y += errno.o
 COBJS-$(CONFIG_OF_CONTROL) += fdtdec.o
 COBJS-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
 COBJS-$(CONFIG_GZIP) += gunzip.o
 COBJS-$(CONFIG_GZIP_COMPRESSED) += gzip.o
-COBJS-y += hashtable.o
 COBJS-y += initcall.o
 COBJS-$(CONFIG_LMB) += lmb.o
 COBJS-y += ldiv.o
@@ -60,14 +56,12 @@ endif
 
 ifdef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += crc32.o
-ifneq ($(CONFIG_SPL_SPI_FLASH_SUPPORT)$(CONFIG_SPL_NET_SUPPORT),)
-COBJS-y += display_options.o
-endif
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += errno.o
-COBJS-$(CONFIG_SPL_NET_SUPPORT) += hashtable.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
 endif
+COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
+COBJS-y += hashtable.o
+COBJS-y += errno.o
+COBJS-y += display_options.o
 COBJS-$(CONFIG_BCH) += bch.o
 COBJS-y += crc32.o
 COBJS-y += ctype.o
@@ -77,6 +71,7 @@ COBJS-y += linux_string.o
 COBJS-$(CONFIG_REGEX) += slre.o
 COBJS-y += string.o
 COBJS-y += time.o
+COBJS-$(CONFIG_TRACE) += trace.o
 COBJS-$(CONFIG_BOOTP_PXE) += uuid.o
 COBJS-y += vsprintf.o
 COBJS-$(CONFIG_RANDOM_MACADDR) += rand.o
index 005ad3d535fbdc32211bd93757858bfce26c411d..b3142685a2d273f5eb093468d34c1c7168fc59d2 100644 (file)
@@ -57,11 +57,14 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"),
        COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"),
        COMPAT(SAMSUNG_EXYNOS_SPI, "samsung,exynos-spi"),
+       COMPAT(GOOGLE_CROS_EC, "google,cros-ec"),
+       COMPAT(GOOGLE_CROS_EC_KEYB, "google,cros-ec-keyb"),
        COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
        COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
        COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
        COMPAT(SAMSUNG_EXYNOS_FIMD, "samsung,exynos-fimd"),
        COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"),
+       COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"),
        COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
        COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
        COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
index 63e67b78c882b5621d30c6a2214034ba7c40356a..b9e3c4a742119fcea67cc4e60572d4da0b5b9957 100644 (file)
@@ -120,3 +120,132 @@ int fdt_nop_node(void *fdt, int nodeoffset)
                        endoffset - nodeoffset);
        return 0;
 }
+
+#define FDT_MAX_DEPTH  32
+
+static int str_in_list(const char *str, char * const list[], int count)
+{
+       int i;
+
+       for (i = 0; i < count; i++)
+               if (!strcmp(list[i], str))
+                       return 1;
+
+       return 0;
+}
+
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+                    char * const exc_prop[], int exc_prop_count,
+                    struct fdt_region region[], int max_regions,
+                    char *path, int path_len, int add_string_tab)
+{
+       int stack[FDT_MAX_DEPTH];
+       char *end;
+       int nextoffset = 0;
+       uint32_t tag;
+       int count = 0;
+       int start = -1;
+       int depth = -1;
+       int want = 0;
+       int base = fdt_off_dt_struct(fdt);
+
+       end = path;
+       *end = '\0';
+       do {
+               const struct fdt_property *prop;
+               const char *name;
+               const char *str;
+               int include = 0;
+               int stop_at = 0;
+               int offset;
+               int len;
+
+               offset = nextoffset;
+               tag = fdt_next_tag(fdt, offset, &nextoffset);
+               stop_at = nextoffset;
+
+               switch (tag) {
+               case FDT_PROP:
+                       include = want >= 2;
+                       stop_at = offset;
+                       prop = fdt_get_property_by_offset(fdt, offset, NULL);
+                       str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+                       if (str_in_list(str, exc_prop, exc_prop_count))
+                               include = 0;
+                       break;
+
+               case FDT_NOP:
+                       include = want >= 2;
+                       stop_at = offset;
+                       break;
+
+               case FDT_BEGIN_NODE:
+                       depth++;
+                       if (depth == FDT_MAX_DEPTH)
+                               return -FDT_ERR_BADSTRUCTURE;
+                       name = fdt_get_name(fdt, offset, &len);
+                       if (end - path + 2 + len >= path_len)
+                               return -FDT_ERR_NOSPACE;
+                       if (end != path + 1)
+                               *end++ = '/';
+                       strcpy(end, name);
+                       end += len;
+                       stack[depth] = want;
+                       if (want == 1)
+                               stop_at = offset;
+                       if (str_in_list(path, inc, inc_count))
+                               want = 2;
+                       else if (want)
+                               want--;
+                       else
+                               stop_at = offset;
+                       include = want;
+                       break;
+
+               case FDT_END_NODE:
+                       include = want;
+                       want = stack[depth--];
+                       while (end > path && *--end != '/')
+                               ;
+                       *end = '\0';
+                       break;
+
+               case FDT_END:
+                       include = 1;
+                       break;
+               }
+
+               if (include && start == -1) {
+                       /* Should we merge with previous? */
+                       if (count && count <= max_regions &&
+                           offset == region[count - 1].offset +
+                                       region[count - 1].size - base)
+                               start = region[--count].offset - base;
+                       else
+                               start = offset;
+               }
+
+               if (!include && start != -1) {
+                       if (count < max_regions) {
+                               region[count].offset = base + start;
+                               region[count].size = stop_at - start;
+                       }
+                       count++;
+                       start = -1;
+               }
+       } while (tag != FDT_END);
+
+       if (nextoffset != fdt_size_dt_struct(fdt))
+               return -FDT_ERR_BADLAYOUT;
+
+       /* Add a region for the END tag and the string table */
+       if (count < max_regions) {
+               region[count].offset = base + start;
+               region[count].size = nextoffset - start;
+               if (add_string_tab)
+                       region[count].size += fdt_size_dt_strings(fdt);
+       }
+       count++;
+
+       return count;
+}
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
new file mode 100644 (file)
index 0000000..9eb3e40
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2013, Google Inc.
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = $(obj)librsa.o
+
+ifdef CONFIG_FIT_SIGNATURE
+COBJS-$(CONFIG_RSA) += rsa-verify.o
+endif
+
+COBJS  := $(sort $(COBJS-y))
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+$(LIB):        $(obj).depend $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
new file mode 100644 (file)
index 0000000..a75ae24
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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 "mkimage.h"
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include <image.h>
+#include <time.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#define HAVE_ERR_REMOVE_THREAD_STATE
+#endif
+
+static int rsa_err(const char *msg)
+{
+       unsigned long sslErr = ERR_get_error();
+
+       fprintf(stderr, "%s", msg);
+       fprintf(stderr, ": %s\n",
+               ERR_error_string(sslErr, 0));
+
+       return -1;
+}
+
+/**
+ * rsa_get_pub_key() - read a public key from a .crt file
+ *
+ * @keydir:    Directory containins the key
+ * @name       Name of key file (will have a .crt extension)
+ * @rsap       Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_pub_key(const char *keydir, const char *name, RSA **rsap)
+{
+       char path[1024];
+       EVP_PKEY *key;
+       X509 *cert;
+       RSA *rsa;
+       FILE *f;
+       int ret;
+
+       *rsap = NULL;
+       snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
+       f = fopen(path, "r");
+       if (!f) {
+               fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
+                       path, strerror(errno));
+               return -EACCES;
+       }
+
+       /* Read the certificate */
+       cert = NULL;
+       if (!PEM_read_X509(f, &cert, NULL, NULL)) {
+               rsa_err("Couldn't read certificate");
+               ret = -EINVAL;
+               goto err_cert;
+       }
+
+       /* Get the public key from the certificate. */
+       key = X509_get_pubkey(cert);
+       if (!key) {
+               rsa_err("Couldn't read public key\n");
+               ret = -EINVAL;
+               goto err_pubkey;
+       }
+
+       /* Convert to a RSA_style key. */
+       rsa = EVP_PKEY_get1_RSA(key);
+       if (!rsa) {
+               rsa_err("Couldn't convert to a RSA style key");
+               goto err_rsa;
+       }
+       fclose(f);
+       EVP_PKEY_free(key);
+       X509_free(cert);
+       *rsap = rsa;
+
+       return 0;
+
+err_rsa:
+       EVP_PKEY_free(key);
+err_pubkey:
+       X509_free(cert);
+err_cert:
+       fclose(f);
+       return ret;
+}
+
+/**
+ * rsa_get_priv_key() - read a private key from a .key file
+ *
+ * @keydir:    Directory containins the key
+ * @name       Name of key file (will have a .key extension)
+ * @rsap       Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
+{
+       char path[1024];
+       RSA *rsa;
+       FILE *f;
+
+       *rsap = NULL;
+       snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
+       f = fopen(path, "r");
+       if (!f) {
+               fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
+                       path, strerror(errno));
+               return -ENOENT;
+       }
+
+       rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
+       if (!rsa) {
+               rsa_err("Failure reading private key");
+               fclose(f);
+               return -EPROTO;
+       }
+       fclose(f);
+       *rsap = rsa;
+
+       return 0;
+}
+
+static int rsa_init(void)
+{
+       int ret;
+
+       ret = SSL_library_init();
+       if (!ret) {
+               fprintf(stderr, "Failure to init SSL library\n");
+               return -1;
+       }
+       SSL_load_error_strings();
+
+       OpenSSL_add_all_algorithms();
+       OpenSSL_add_all_digests();
+       OpenSSL_add_all_ciphers();
+
+       return 0;
+}
+
+static void rsa_remove(void)
+{
+       CRYPTO_cleanup_all_ex_data();
+       ERR_free_strings();
+#ifdef HAVE_ERR_REMOVE_THREAD_STATE
+       ERR_remove_thread_state(NULL);
+#else
+       ERR_remove_state(0);
+#endif
+       EVP_cleanup();
+}
+
+static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
+               int region_count, uint8_t **sigp, uint *sig_size)
+{
+       EVP_PKEY *key;
+       EVP_MD_CTX *context;
+       int size, ret = 0;
+       uint8_t *sig;
+       int i;
+
+       key = EVP_PKEY_new();
+       if (!key)
+               return rsa_err("EVP_PKEY object creation failed");
+
+       if (!EVP_PKEY_set1_RSA(key, rsa)) {
+               ret = rsa_err("EVP key setup failed");
+               goto err_set;
+       }
+
+       size = EVP_PKEY_size(key);
+       sig = malloc(size);
+       if (!sig) {
+               fprintf(stderr, "Out of memory for signature (%d bytes)\n",
+                       size);
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+
+       context = EVP_MD_CTX_create();
+       if (!context) {
+               ret = rsa_err("EVP context creation failed");
+               goto err_create;
+       }
+       EVP_MD_CTX_init(context);
+       if (!EVP_SignInit(context, EVP_sha1())) {
+               ret = rsa_err("Signer setup failed");
+               goto err_sign;
+       }
+
+       for (i = 0; i < region_count; i++) {
+               if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
+                       ret = rsa_err("Signing data failed");
+                       goto err_sign;
+               }
+       }
+
+       if (!EVP_SignFinal(context, sig, sig_size, key)) {
+               ret = rsa_err("Could not obtain signature");
+               goto err_sign;
+       }
+       EVP_MD_CTX_cleanup(context);
+       EVP_MD_CTX_destroy(context);
+       EVP_PKEY_free(key);
+
+       debug("Got signature: %d bytes, expected %d\n", *sig_size, size);
+       *sigp = sig;
+       *sig_size = size;
+
+       return 0;
+
+err_sign:
+       EVP_MD_CTX_destroy(context);
+err_create:
+       free(sig);
+err_alloc:
+err_set:
+       EVP_PKEY_free(key);
+       return ret;
+}
+
+int rsa_sign(struct image_sign_info *info,
+            const struct image_region region[], int region_count,
+            uint8_t **sigp, uint *sig_len)
+{
+       RSA *rsa;
+       int ret;
+
+       ret = rsa_init();
+       if (ret)
+               return ret;
+
+       ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
+       if (ret)
+               goto err_priv;
+       ret = rsa_sign_with_key(rsa, region, region_count, sigp, sig_len);
+       if (ret)
+               goto err_sign;
+
+       RSA_free(rsa);
+       rsa_remove();
+
+       return ret;
+
+err_sign:
+       RSA_free(rsa);
+err_priv:
+       rsa_remove();
+       return ret;
+}
+
+/*
+ * rsa_get_params(): - Get the important parameters of an RSA public key
+ */
+int rsa_get_params(RSA *key, uint32_t *n0_invp, BIGNUM **modulusp,
+                  BIGNUM **r_squaredp)
+{
+       BIGNUM *big1, *big2, *big32, *big2_32;
+       BIGNUM *n, *r, *r_squared, *tmp;
+       BN_CTX *bn_ctx = BN_CTX_new();
+       int ret = 0;
+
+       /* Initialize BIGNUMs */
+       big1 = BN_new();
+       big2 = BN_new();
+       big32 = BN_new();
+       r = BN_new();
+       r_squared = BN_new();
+       tmp = BN_new();
+       big2_32 = BN_new();
+       n = BN_new();
+       if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
+           !n) {
+               fprintf(stderr, "Out of memory (bignum)\n");
+               return -ENOMEM;
+       }
+
+       if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
+           !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
+               ret = -1;
+
+       /* big2_32 = 2^32 */
+       if (!BN_exp(big2_32, big2, big32, bn_ctx))
+               ret = -1;
+
+       /* Calculate n0_inv = -1 / n[0] mod 2^32 */
+       if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
+           !BN_sub(tmp, big2_32, tmp))
+               ret = -1;
+       *n0_invp = BN_get_word(tmp);
+
+       /* Calculate R = 2^(# of key bits) */
+       if (!BN_set_word(tmp, BN_num_bits(n)) ||
+           !BN_exp(r, big2, tmp, bn_ctx))
+               ret = -1;
+
+       /* Calculate r_squared = R^2 mod n */
+       if (!BN_copy(r_squared, r) ||
+           !BN_mul(tmp, r_squared, r, bn_ctx) ||
+           !BN_mod(r_squared, tmp, n, bn_ctx))
+               ret = -1;
+
+       *modulusp = n;
+       *r_squaredp = r_squared;
+
+       BN_free(big1);
+       BN_free(big2);
+       BN_free(big32);
+       BN_free(r);
+       BN_free(tmp);
+       BN_free(big2_32);
+       if (ret) {
+               fprintf(stderr, "Bignum operations failed\n");
+               return -ENOMEM;
+       }
+
+       return ret;
+}
+
+static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
+                         BIGNUM *num, int num_bits)
+{
+       int nwords = num_bits / 32;
+       int size;
+       uint32_t *buf, *ptr;
+       BIGNUM *tmp, *big2, *big32, *big2_32;
+       BN_CTX *ctx;
+       int ret;
+
+       tmp = BN_new();
+       big2 = BN_new();
+       big32 = BN_new();
+       big2_32 = BN_new();
+       if (!tmp || !big2 || !big32 || !big2_32) {
+               fprintf(stderr, "Out of memory (bignum)\n");
+               return -ENOMEM;
+       }
+       ctx = BN_CTX_new();
+       if (!tmp) {
+               fprintf(stderr, "Out of memory (bignum context)\n");
+               return -ENOMEM;
+       }
+       BN_set_word(big2, 2L);
+       BN_set_word(big32, 32L);
+       BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
+
+       size = nwords * sizeof(uint32_t);
+       buf = malloc(size);
+       if (!buf) {
+               fprintf(stderr, "Out of memory (%d bytes)\n", size);
+               return -ENOMEM;
+       }
+
+       /* Write out modulus as big endian array of integers */
+       for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
+               BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
+               *ptr = cpu_to_fdt32(BN_get_word(tmp));
+               BN_rshift(num, num, 32); /*  N = N/B */
+       }
+
+       ret = fdt_setprop(blob, noffset, prop_name, buf, size);
+       if (ret) {
+               fprintf(stderr, "Failed to write public key to FIT\n");
+               return -ENOSPC;
+       }
+       free(buf);
+       BN_free(tmp);
+       BN_free(big2);
+       BN_free(big32);
+       BN_free(big2_32);
+
+       return ret;
+}
+
+int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+{
+       BIGNUM *modulus, *r_squared;
+       uint32_t n0_inv;
+       int parent, node;
+       char name[100];
+       int ret;
+       int bits;
+       RSA *rsa;
+
+       debug("%s: Getting verification data\n", __func__);
+       ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
+       if (ret)
+               return ret;
+       ret = rsa_get_params(rsa, &n0_inv, &modulus, &r_squared);
+       if (ret)
+               return ret;
+       bits = BN_num_bits(modulus);
+       parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
+       if (parent == -FDT_ERR_NOTFOUND) {
+               parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
+               if (parent < 0) {
+                       fprintf(stderr, "Couldn't create signature node: %s\n",
+                               fdt_strerror(parent));
+                       return -EINVAL;
+               }
+       }
+
+       /* Either create or overwrite the named key node */
+       snprintf(name, sizeof(name), "key-%s", info->keyname);
+       node = fdt_subnode_offset(keydest, parent, name);
+       if (node == -FDT_ERR_NOTFOUND) {
+               node = fdt_add_subnode(keydest, parent, name);
+               if (node < 0) {
+                       fprintf(stderr, "Could not create key subnode: %s\n",
+                               fdt_strerror(node));
+                       return -EINVAL;
+               }
+       } else if (node < 0) {
+               fprintf(stderr, "Cannot select keys parent: %s\n",
+                       fdt_strerror(node));
+               return -ENOSPC;
+       }
+
+       ret = fdt_setprop_string(keydest, node, "key-name-hint",
+                                info->keyname);
+       ret |= fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
+       ret |= fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
+       ret |= fdt_add_bignum(keydest, node, "rsa,modulus", modulus, bits);
+       ret |= fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared, bits);
+       ret |= fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
+                                 info->algo->name);
+       if (info->require_keys) {
+               fdt_setprop_string(keydest, node, "required",
+                                  info->require_keys);
+       }
+       BN_free(modulus);
+       BN_free(r_squared);
+       if (ret)
+               return -EIO;
+
+       return 0;
+}
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
new file mode 100644 (file)
index 0000000..6a02689
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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 <fdtdec.h>
+#include <rsa.h>
+#include <sha1.h>
+#include <asm/byteorder.h>
+#include <asm/errno.h>
+#include <asm/unaligned.h>
+
+/**
+ * struct rsa_public_key - holder for a public key
+ *
+ * An RSA public key consists of a modulus (typically called N), the inverse
+ * and R^2, where R is 2^(# key bits).
+ */
+struct rsa_public_key {
+       uint len;               /* Length of modulus[] in number of uint32_t */
+       uint32_t n0inv;         /* -1 / modulus[0] mod 2^32 */
+       uint32_t *modulus;      /* modulus as little endian array */
+       uint32_t *rr;           /* R^2 as little endian array */
+};
+
+#define UINT64_MULT32(v, multby)  (((uint64_t)(v)) * ((uint32_t)(multby)))
+
+#define RSA2048_BYTES  (2048 / 8)
+
+/* This is the minimum/maximum key size we support, in bits */
+#define RSA_MIN_KEY_BITS       2048
+#define RSA_MAX_KEY_BITS       2048
+
+/* This is the maximum signature length that we support, in bits */
+#define RSA_MAX_SIG_BITS       2048
+
+static const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
+       0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
+       0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+       0x05, 0x00, 0x04, 0x14
+};
+
+/**
+ * subtract_modulus() - subtract modulus from the given value
+ *
+ * @key:       Key containing modulus to subtract
+ * @num:       Number to subtract modulus from, as little endian word array
+ */
+static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
+{
+       int64_t acc = 0;
+       uint i;
+
+       for (i = 0; i < key->len; i++) {
+               acc += (uint64_t)num[i] - key->modulus[i];
+               num[i] = (uint32_t)acc;
+               acc >>= 32;
+       }
+}
+
+/**
+ * greater_equal_modulus() - check if a value is >= modulus
+ *
+ * @key:       Key containing modulus to check
+ * @num:       Number to check against modulus, as little endian word array
+ * @return 0 if num < modulus, 1 if num >= modulus
+ */
+static int greater_equal_modulus(const struct rsa_public_key *key,
+                                uint32_t num[])
+{
+       uint32_t i;
+
+       for (i = key->len - 1; i >= 0; i--) {
+               if (num[i] < key->modulus[i])
+                       return 0;
+               if (num[i] > key->modulus[i])
+                       return 1;
+       }
+
+       return 1;  /* equal */
+}
+
+/**
+ * montgomery_mul_add_step() - Perform montgomery multiply-add step
+ *
+ * Operation: montgomery result[] += a * b[] / n0inv % modulus
+ *
+ * @key:       RSA key
+ * @result:    Place to put result, as little endian word array
+ * @a:         Multiplier
+ * @b:         Multiplicand, as little endian word array
+ */
+static void montgomery_mul_add_step(const struct rsa_public_key *key,
+               uint32_t result[], const uint32_t a, const uint32_t b[])
+{
+       uint64_t acc_a, acc_b;
+       uint32_t d0;
+       uint i;
+
+       acc_a = (uint64_t)a * b[0] + result[0];
+       d0 = (uint32_t)acc_a * key->n0inv;
+       acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a;
+       for (i = 1; i < key->len; i++) {
+               acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i];
+               acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] +
+                               (uint32_t)acc_a;
+               result[i - 1] = (uint32_t)acc_b;
+       }
+
+       acc_a = (acc_a >> 32) + (acc_b >> 32);
+
+       result[i - 1] = (uint32_t)acc_a;
+
+       if (acc_a >> 32)
+               subtract_modulus(key, result);
+}
+
+/**
+ * montgomery_mul() - Perform montgomery mutitply
+ *
+ * Operation: montgomery result[] = a[] * b[] / n0inv % modulus
+ *
+ * @key:       RSA key
+ * @result:    Place to put result, as little endian word array
+ * @a:         Multiplier, as little endian word array
+ * @b:         Multiplicand, as little endian word array
+ */
+static void montgomery_mul(const struct rsa_public_key *key,
+               uint32_t result[], uint32_t a[], const uint32_t b[])
+{
+       uint i;
+
+       for (i = 0; i < key->len; ++i)
+               result[i] = 0;
+       for (i = 0; i < key->len; ++i)
+               montgomery_mul_add_step(key, result, a[i], b);
+}
+
+/**
+ * pow_mod() - in-place public exponentiation
+ *
+ * @key:       RSA key
+ * @inout:     Big-endian word array containing value and result
+ */
+static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
+{
+       uint32_t *result, *ptr;
+       uint i;
+
+       /* Sanity check for stack size - key->len is in 32-bit words */
+       if (key->len > RSA_MAX_KEY_BITS / 32) {
+               debug("RSA key words %u exceeds maximum %d\n", key->len,
+                     RSA_MAX_KEY_BITS / 32);
+               return -EINVAL;
+       }
+
+       uint32_t val[key->len], acc[key->len], tmp[key->len];
+       result = tmp;  /* Re-use location. */
+
+       /* Convert from big endian byte array to little endian word array. */
+       for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
+               val[i] = get_unaligned_be32(ptr);
+
+       montgomery_mul(key, acc, val, key->rr);  /* axx = a * RR / R mod M */
+       for (i = 0; i < 16; i += 2) {
+               montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod M */
+               montgomery_mul(key, acc, tmp, tmp); /* acc = tmp^2 / R mod M */
+       }
+       montgomery_mul(key, result, acc, val);  /* result = XX * a / R mod M */
+
+       /* Make sure result < mod; result is at most 1x mod too large. */
+       if (greater_equal_modulus(key, result))
+               subtract_modulus(key, result);
+
+       /* Convert to bigendian byte array */
+       for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
+               put_unaligned_be32(result[i], ptr);
+
+       return 0;
+}
+
+static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
+               const uint32_t sig_len, const uint8_t *hash)
+{
+       const uint8_t *padding;
+       int pad_len;
+       int ret;
+
+       if (!key || !sig || !hash)
+               return -EIO;
+
+       if (sig_len != (key->len * sizeof(uint32_t))) {
+               debug("Signature is of incorrect length %d\n", sig_len);
+               return -EINVAL;
+       }
+
+       /* Sanity check for stack size */
+       if (sig_len > RSA_MAX_SIG_BITS / 8) {
+               debug("Signature length %u exceeds maximum %d\n", sig_len,
+                     RSA_MAX_SIG_BITS / 8);
+               return -EINVAL;
+       }
+
+       uint32_t buf[sig_len / sizeof(uint32_t)];
+
+       memcpy(buf, sig, sig_len);
+
+       ret = pow_mod(key, buf);
+       if (ret)
+               return ret;
+
+       /* Determine padding to use depending on the signature type. */
+       padding = padding_sha1_rsa2048;
+       pad_len = RSA2048_BYTES - SHA1_SUM_LEN;
+
+       /* Check pkcs1.5 padding bytes. */
+       if (memcmp(buf, padding, pad_len)) {
+               debug("In RSAVerify(): Padding check failed!\n");
+               return -EINVAL;
+       }
+
+       /* Check hash. */
+       if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) {
+               debug("In RSAVerify(): Hash check failed!\n");
+               return -EACCES;
+       }
+
+       return 0;
+}
+
+static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               dst[i] = fdt32_to_cpu(src[len - 1 - i]);
+}
+
+static int rsa_verify_with_keynode(struct image_sign_info *info,
+               const void *hash, uint8_t *sig, uint sig_len, int node)
+{
+       const void *blob = info->fdt_blob;
+       struct rsa_public_key key;
+       const void *modulus, *rr;
+       int ret;
+
+       if (node < 0) {
+               debug("%s: Skipping invalid node", __func__);
+               return -EBADF;
+       }
+       if (!fdt_getprop(blob, node, "rsa,n0-inverse", NULL)) {
+               debug("%s: Missing rsa,n0-inverse", __func__);
+               return -EFAULT;
+       }
+       key.len = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
+       key.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
+       modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
+       rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
+       if (!key.len || !modulus || !rr) {
+               debug("%s: Missing RSA key info", __func__);
+               return -EFAULT;
+       }
+
+       /* Sanity check for stack size */
+       if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) {
+               debug("RSA key bits %u outside allowed range %d..%d\n",
+                     key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
+               return -EFAULT;
+       }
+       key.len /= sizeof(uint32_t) * 8;
+       uint32_t key1[key.len], key2[key.len];
+
+       key.modulus = key1;
+       key.rr = key2;
+       rsa_convert_big_endian(key.modulus, modulus, key.len);
+       rsa_convert_big_endian(key.rr, rr, key.len);
+       if (!key.modulus || !key.rr) {
+               debug("%s: Out of memory", __func__);
+               return -ENOMEM;
+       }
+
+       debug("key length %d\n", key.len);
+       ret = rsa_verify_key(&key, sig, sig_len, hash);
+       if (ret) {
+               printf("%s: RSA failed to verify: %d\n", __func__, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int rsa_verify(struct image_sign_info *info,
+              const struct image_region region[], int region_count,
+              uint8_t *sig, uint sig_len)
+{
+       const void *blob = info->fdt_blob;
+       uint8_t hash[SHA1_SUM_LEN];
+       int ndepth, noffset;
+       int sig_node, node;
+       char name[100];
+       sha1_context ctx;
+       int ret, i;
+
+       sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
+       if (sig_node < 0) {
+               debug("%s: No signature node found\n", __func__);
+               return -ENOENT;
+       }
+
+       sha1_starts(&ctx);
+       for (i = 0; i < region_count; i++)
+               sha1_update(&ctx, region[i].data, region[i].size);
+       sha1_finish(&ctx, hash);
+
+       /* See if we must use a particular key */
+       if (info->required_keynode != -1) {
+               ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
+                       info->required_keynode);
+               if (!ret)
+                       return ret;
+       }
+
+       /* Look for a key that matches our hint */
+       snprintf(name, sizeof(name), "key-%s", info->keyname);
+       node = fdt_subnode_offset(blob, sig_node, name);
+       ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
+       if (!ret)
+               return ret;
+
+       /* No luck, so try each of the keys in turn */
+       for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
+                       (noffset >= 0) && (ndepth > 0);
+                       noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
+               if (ndepth == 1 && noffset != node) {
+                       ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
+                                                     noffset);
+                       if (!ret)
+                               break;
+               }
+       }
+
+       return ret;
+}
diff --git a/lib/trace.c b/lib/trace.c
new file mode 100644 (file)
index 0000000..e7455bc
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <trace.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char trace_enabled __attribute__((section(".data")));
+static char trace_inited __attribute__((section(".data")));
+
+/* The header block at the start of the trace memory area */
+struct trace_hdr {
+       int func_count;         /* Total number of function call sites */
+       u64 call_count;         /* Total number of tracked function calls */
+       u64 untracked_count;    /* Total number of untracked function calls */
+       int funcs_used;         /* Total number of functions used */
+
+       /*
+        * Call count for each function. This is indexed by the word offset
+        * of the function from gd->relocaddr
+        */
+       uintptr_t *call_accum;
+
+       /* Function trace list */
+       struct trace_call *ftrace;      /* The function call records */
+       ulong ftrace_size;      /* Num. of ftrace records we have space for */
+       ulong ftrace_count;     /* Num. of ftrace records written */
+       ulong ftrace_too_deep_count;    /* Functions that were too deep */
+
+       int depth;
+       int depth_limit;
+       int max_depth;
+};
+
+static struct trace_hdr *hdr;  /* Pointer to start of trace buffer */
+
+static inline uintptr_t __attribute__((no_instrument_function))
+               func_ptr_to_num(void *func_ptr)
+{
+       uintptr_t offset = (uintptr_t)func_ptr;
+
+#ifdef CONFIG_SANDBOX
+       offset -= (uintptr_t)&_init;
+#else
+       if (gd->flags & GD_FLG_RELOC)
+               offset -= gd->relocaddr;
+       else
+               offset -= CONFIG_SYS_TEXT_BASE;
+#endif
+       return offset / FUNC_SITE_SIZE;
+}
+
+static void __attribute__((no_instrument_function)) add_ftrace(void *func_ptr,
+                               void *caller, ulong flags)
+{
+       if (hdr->depth > hdr->depth_limit) {
+               hdr->ftrace_too_deep_count++;
+               return;
+       }
+       if (hdr->ftrace_count < hdr->ftrace_size) {
+               struct trace_call *rec = &hdr->ftrace[hdr->ftrace_count];
+
+               rec->func = func_ptr_to_num(func_ptr);
+               rec->caller = func_ptr_to_num(caller);
+               rec->flags = flags | (timer_get_us() & FUNCF_TIMESTAMP_MASK);
+       }
+       hdr->ftrace_count++;
+}
+
+static void __attribute__((no_instrument_function)) add_textbase(void)
+{
+       if (hdr->ftrace_count < hdr->ftrace_size) {
+               struct trace_call *rec = &hdr->ftrace[hdr->ftrace_count];
+
+               rec->func = CONFIG_SYS_TEXT_BASE;
+               rec->caller = 0;
+               rec->flags = FUNCF_TEXTBASE;
+       }
+       hdr->ftrace_count++;
+}
+
+/**
+ * This is called on every function entry
+ *
+ * We add to our tally for this function and add to the list of called
+ * functions.
+ *
+ * @param func_ptr     Pointer to function being entered
+ * @param caller       Pointer to function which called this function
+ */
+void __attribute__((no_instrument_function)) __cyg_profile_func_enter(
+               void *func_ptr, void *caller)
+{
+       if (trace_enabled) {
+               int func;
+
+               add_ftrace(func_ptr, caller, FUNCF_ENTRY);
+               func = func_ptr_to_num(func_ptr);
+               if (func < hdr->func_count) {
+                       hdr->call_accum[func]++;
+                       hdr->call_count++;
+               } else {
+                       hdr->untracked_count++;
+               }
+               hdr->depth++;
+               if (hdr->depth > hdr->depth_limit)
+                       hdr->max_depth = hdr->depth;
+       }
+}
+
+/**
+ * This is called on every function exit
+ *
+ * We do nothing here.
+ *
+ * @param func_ptr     Pointer to function being entered
+ * @param caller       Pointer to function which called this function
+ */
+void __attribute__((no_instrument_function)) __cyg_profile_func_exit(
+               void *func_ptr, void *caller)
+{
+       if (trace_enabled) {
+               add_ftrace(func_ptr, caller, FUNCF_EXIT);
+               hdr->depth--;
+       }
+}
+
+/**
+ * Produce a list of called functions
+ *
+ * The information is written into the supplied buffer - a header followed
+ * by a list of function records.
+ *
+ * @param buff         Buffer to place list into
+ * @param buff_size    Size of buffer
+ * @param needed       Returns size of buffer needed, which may be
+ *                     greater than buff_size if we ran out of space.
+ * @return 0 if ok, -1 if space was exhausted
+ */
+int trace_list_functions(void *buff, int buff_size, unsigned int *needed)
+{
+       struct trace_output_hdr *output_hdr = NULL;
+       void *end, *ptr = buff;
+       int func;
+       int upto;
+
+       end = buff ? buff + buff_size : NULL;
+
+       /* Place some header information */
+       if (ptr + sizeof(struct trace_output_hdr) < end)
+               output_hdr = ptr;
+       ptr += sizeof(struct trace_output_hdr);
+
+       /* Add information about each function */
+       for (func = upto = 0; func < hdr->func_count; func++) {
+               int calls = hdr->call_accum[func];
+
+               if (!calls)
+                       continue;
+
+               if (ptr + sizeof(struct trace_output_func) < end) {
+                       struct trace_output_func *stats = ptr;
+
+                       stats->offset = func * FUNC_SITE_SIZE;
+                       stats->call_count = calls;
+                       upto++;
+               }
+               ptr += sizeof(struct trace_output_func);
+       }
+
+       /* Update the header */
+       if (output_hdr) {
+               output_hdr->rec_count = upto;
+               output_hdr->type = TRACE_CHUNK_FUNCS;
+       }
+
+       /* Work out how must of the buffer we used */
+       *needed = ptr - buff;
+       if (ptr > end)
+               return -1;
+       return 0;
+}
+
+int trace_list_calls(void *buff, int buff_size, unsigned *needed)
+{
+       struct trace_output_hdr *output_hdr = NULL;
+       void *end, *ptr = buff;
+       int rec, upto;
+       int count;
+
+       end = buff ? buff + buff_size : NULL;
+
+       /* Place some header information */
+       if (ptr + sizeof(struct trace_output_hdr) < end)
+               output_hdr = ptr;
+       ptr += sizeof(struct trace_output_hdr);
+
+       /* Add information about each call */
+       count = hdr->ftrace_count;
+       if (count > hdr->ftrace_size)
+               count = hdr->ftrace_size;
+       for (rec = upto = 0; rec < count; rec++) {
+               if (ptr + sizeof(struct trace_call) < end) {
+                       struct trace_call *call = &hdr->ftrace[rec];
+                       struct trace_call *out = ptr;
+
+                       out->func = call->func * FUNC_SITE_SIZE;
+                       out->caller = call->caller * FUNC_SITE_SIZE;
+                       out->flags = call->flags;
+                       upto++;
+               }
+               ptr += sizeof(struct trace_call);
+       }
+
+       /* Update the header */
+       if (output_hdr) {
+               output_hdr->rec_count = upto;
+               output_hdr->type = TRACE_CHUNK_CALLS;
+       }
+
+       /* Work out how must of the buffer we used */
+       *needed = ptr - buff;
+       if (ptr > end)
+               return -1;
+       return 0;
+}
+
+/* Print basic information about tracing */
+void trace_print_stats(void)
+{
+       ulong count;
+
+#ifndef FTRACE
+       puts("Warning: make U-Boot with FTRACE to enable function instrumenting.\n");
+       puts("You will likely get zeroed data here\n");
+#endif
+       if (!trace_inited) {
+               printf("Trace is disabled\n");
+               return;
+       }
+       print_grouped_ull(hdr->func_count, 10);
+       puts(" function sites\n");
+       print_grouped_ull(hdr->call_count, 10);
+       puts(" function calls\n");
+       print_grouped_ull(hdr->untracked_count, 10);
+       puts(" untracked function calls\n");
+       count = min(hdr->ftrace_count, hdr->ftrace_size);
+       print_grouped_ull(count, 10);
+       puts(" traced function calls");
+       if (hdr->ftrace_count > hdr->ftrace_size) {
+               printf(" (%lu dropped due to overflow)",
+                      hdr->ftrace_count - hdr->ftrace_size);
+       }
+       puts("\n");
+       printf("%15d maximum observed call depth\n", hdr->max_depth);
+       printf("%15d call depth limit\n", hdr->depth_limit);
+       print_grouped_ull(hdr->ftrace_too_deep_count, 10);
+       puts(" calls not traced due to depth\n");
+}
+
+void __attribute__((no_instrument_function)) trace_set_enabled(int enabled)
+{
+       trace_enabled = enabled != 0;
+}
+
+/**
+ * Init the tracing system ready for used, and enable it
+ *
+ * @param buff         Pointer to trace buffer
+ * @param buff_size    Size of trace buffer
+ */
+int __attribute__((no_instrument_function)) trace_init(void *buff,
+               size_t buff_size)
+{
+       ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
+       size_t needed;
+       int was_disabled = !trace_enabled;
+
+       if (!was_disabled) {
+#ifdef CONFIG_TRACE_EARLY
+               char *end;
+               ulong used;
+
+               /*
+                * Copy over the early trace data if we have it. Disable
+                * tracing while we are doing this.
+                */
+               trace_enabled = 0;
+               hdr = map_sysmem(CONFIG_TRACE_EARLY_ADDR,
+                                CONFIG_TRACE_EARLY_SIZE);
+               end = (char *)&hdr->ftrace[hdr->ftrace_count];
+               used = end - (char *)hdr;
+               printf("trace: copying %08lx bytes of early data from %x to %08lx\n",
+                      used, CONFIG_TRACE_EARLY_ADDR,
+                      (ulong)map_to_sysmem(buff));
+               memcpy(buff, hdr, used);
+#else
+               puts("trace: already enabled\n");
+               return -1;
+#endif
+       }
+       hdr = (struct trace_hdr *)buff;
+       needed = sizeof(*hdr) + func_count * sizeof(uintptr_t);
+       if (needed > buff_size) {
+               printf("trace: buffer size %zd bytes: at least %zd needed\n",
+                      buff_size, needed);
+               return -1;
+       }
+
+       if (was_disabled)
+               memset(hdr, '\0', needed);
+       hdr->func_count = func_count;
+       hdr->call_accum = (uintptr_t *)(hdr + 1);
+
+       /* Use any remaining space for the timed function trace */
+       hdr->ftrace = (struct trace_call *)(buff + needed);
+       hdr->ftrace_size = (buff_size - needed) / sizeof(*hdr->ftrace);
+       add_textbase();
+
+       puts("trace: enabled\n");
+       hdr->depth_limit = 15;
+       trace_enabled = 1;
+       trace_inited = 1;
+       return 0;
+}
+
+#ifdef CONFIG_TRACE_EARLY
+int __attribute__((no_instrument_function)) trace_early_init(void)
+{
+       ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
+       size_t buff_size = CONFIG_TRACE_EARLY_SIZE;
+       size_t needed;
+
+       /* We can ignore additional calls to this function */
+       if (trace_enabled)
+               return 0;
+
+       hdr = map_sysmem(CONFIG_TRACE_EARLY_ADDR, CONFIG_TRACE_EARLY_SIZE);
+       needed = sizeof(*hdr) + func_count * sizeof(uintptr_t);
+       if (needed > buff_size) {
+               printf("trace: buffer size is %zd bytes, at least %zd needed\n",
+                      buff_size, needed);
+               return -1;
+       }
+
+       memset(hdr, '\0', needed);
+       hdr->call_accum = (uintptr_t *)(hdr + 1);
+       hdr->func_count = func_count;
+
+       /* Use any remaining space for the timed function trace */
+       hdr->ftrace = (struct trace_call *)((char *)hdr + needed);
+       hdr->ftrace_size = (buff_size - needed) / sizeof(*hdr->ftrace);
+       add_textbase();
+       hdr->depth_limit = 200;
+       printf("trace: early enable at %08x\n", CONFIG_TRACE_EARLY_ADDR);
+
+       trace_enabled = 1;
+       return 0;
+}
+#endif
index 533a96b85e3629a765ba807a594f8509fab9f68a..82e5c13653b68d490257a244701966051d05d2fe 100644 (file)
@@ -870,3 +870,19 @@ char *simple_itoa(ulong i)
        } while (i > 0);
        return p + 1;
 }
+
+/* We don't seem to have %'d in U-Boot */
+void print_grouped_ull(unsigned long long int_val, int digits)
+{
+       char str[21], *s;
+       int grab = 3;
+
+       digits = (digits + 2) / 3;
+       sprintf(str, "%*llu", digits * 3, int_val);
+       for (s = str; *s; s += grab) {
+               if (s != str)
+                       putc(s[-1] != ' ' ? ',' : ' ');
+               printf("%.*s", grab, s);
+               grab = 3;
+       }
+}
diff --git a/nand_spl/board/freescale/p1010rdb/Makefile b/nand_spl/board/freescale/p1010rdb/Makefile
deleted file mode 100644 (file)
index f7bdf92..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-#
-# (C) Copyright 2007
-# Stefan Roese, DENX Software Engineering, sr@denx.de.
-#
-# Copyright 2011 Freescale Semiconductor, Inc.
-#
-# See file CREDITS for list of people who contributed to this
-# project.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-# MA 02111-1307 USA
-#
-
-NAND_SPL := y
-CONFIG_SYS_TEXT_BASE_SPL := 0xff800000
-PAD_TO := 0xff802000
-
-include $(TOPDIR)/config.mk
-
-nandobj        := $(OBJTREE)/nand_spl/
-
-LDSCRIPT= $(TOPDIR)/$(CPUDIR)/u-boot-nand_spl.lds
-LDFLAGS := -T $(nandobj)u-boot-nand_spl.lds -Ttext $(CONFIG_SYS_TEXT_BASE_SPL) $(LDFLAGS) \
-          $(LDFLAGS_FINAL)
-AFLAGS += -DCONFIG_NAND_SPL
-CFLAGS += -DCONFIG_NAND_SPL
-
-SOBJS  = start.o resetvec.o ticks.o
-COBJS  = cache.o cpu_init_early.o spl_minimal.o fsl_law.o law.o \
-         nand_boot.o nand_boot_fsl_ifc.o ns16550.o tlb.o tlb_table.o
-
-SRCS   := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
-OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
-__OBJS := $(SOBJS) $(COBJS)
-LNDIR  := $(nandobj)board/$(BOARDDIR)
-
-ALL    = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin
-
-all:   $(obj).depend $(ALL)
-
-$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl
-       $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@
-
-$(nandobj)u-boot-spl.bin:      $(nandobj)u-boot-spl
-       $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
-
-$(nandobj)u-boot-spl:  $(OBJS) $(nandobj)u-boot-nand_spl.lds
-       cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) $(PLATFORM_LIBS) \
-               -Map $(nandobj)u-boot-spl.map \
-               -o $(nandobj)u-boot-spl
-
-$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT)
-       $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)board/$(BOARDDIR) \
-                -ansi -D__ASSEMBLY__ -P - <$< >$@
-
-# create symbolic links for common files
-
-$(obj)cache.c:
-       @rm -f $(obj)cache.c
-       ln -sf $(SRCTREE)/arch/powerpc/lib/cache.c $(obj)cache.c
-
-$(obj)cpu_init_early.c:
-       @rm -f $(obj)cpu_init_early.c
-       ln -sf $(SRCTREE)/$(CPUDIR)/cpu_init_early.c $(obj)cpu_init_early.c
-
-$(obj)spl_minimal.c:
-       @rm -f $(obj)spl_minimal.c
-       ln -sf $(SRCTREE)/$(CPUDIR)/spl_minimal.c $(obj)spl_minimal.c
-
-$(obj)fsl_law.c:
-       @rm -f $(obj)fsl_law.c
-       ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc8xxx/law.c $(obj)fsl_law.c
-
-$(obj)law.c:
-       @rm -f $(obj)law.c
-       ln -sf $(SRCTREE)/board/$(BOARDDIR)/law.c $(obj)law.c
-
-$(obj)nand_boot_fsl_ifc.c:
-       @rm -f $(obj)nand_boot_fsl_ifc.c
-       ln -sf $(SRCTREE)/nand_spl/nand_boot_fsl_ifc.c \
-              $(obj)nand_boot_fsl_ifc.c
-
-$(obj)ns16550.c:
-       @rm -f $(obj)ns16550.c
-       ln -sf $(SRCTREE)/drivers/serial/ns16550.c $(obj)ns16550.c
-
-$(obj)resetvec.S:
-       @rm -f $(obj)resetvec.S
-       ln -s $(SRCTREE)/$(CPUDIR)/resetvec.S $(obj)resetvec.S
-
-$(obj)fixed_ivor.S:
-       @rm -f $(obj)fixed_ivor.S
-       ln -sf $(SRCTREE)/$(CPUDIR)/fixed_ivor.S $(obj)fixed_ivor.S
-
-$(obj)start.S: $(obj)fixed_ivor.S
-       @rm -f $(obj)start.S
-       ln -sf $(SRCTREE)/$(CPUDIR)/start.S $(obj)start.S
-
-$(obj)ticks.S:
-       @rm -f $(obj)ticks.S
-       ln -sf $(SRCTREE)/arch/powerpc/lib/ticks.S $(obj)ticks.S
-
-$(obj)tlb.c:
-       @rm -f $(obj)tlb.c
-       ln -sf $(SRCTREE)/$(CPUDIR)/tlb.c $(obj)tlb.c
-
-$(obj)tlb_table.c:
-       @rm -f $(obj)tlb_table.c
-       ln -sf $(SRCTREE)/board/$(BOARDDIR)/tlb.c $(obj)tlb_table.c
-
-ifneq ($(OBJTREE), $(SRCTREE))
-$(obj)nand_boot.c:
-       @rm -f $(obj)nand_boot.c
-       ln -s $(SRCTREE)/nand_spl/board/$(BOARDDIR)/nand_boot.c $(obj)nand_boot.c
-endif
-
-#########################################################################
-
-$(obj)%.o:     $(obj)%.S
-       $(CC) $(AFLAGS) -c -o $@ $<
-
-$(obj)%.o:     $(obj)%.c
-       $(CC) $(CFLAGS) -c -o $@ $<
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
index 1ba796ebdf949999f8663ff30049c1c085d43f56..4152fae5bacba34c051bf2f877a11d435630325e 100644 (file)
@@ -206,6 +206,7 @@ void link_local_receive_arp(struct arp_hdr *arp, int len)
 {
        int source_ip_conflict;
        int target_ip_conflict;
+       IPaddr_t null_ip = 0;
 
        if (state == DISABLED)
                return;
@@ -267,10 +268,18 @@ void link_local_receive_arp(struct arp_hdr *arp, int len)
        ) {
                source_ip_conflict = 1;
        }
-       if (arp->ar_op == htons(ARPOP_REQUEST)
-        && memcmp(&arp->ar_tpa, &ip, ARP_PLEN) == 0
-        && memcmp(&arp->ar_tha, NetOurEther, ARP_HLEN) != 0
-       ) {
+
+       /*
+        * According to RFC 3927, section 2.2.1:
+        * Check if packet is an ARP probe by checking for a null source IP
+        * then check that target IP is equal to ours and source hw addr
+        * is not equal to ours. This condition should cause a conflict only
+        * during probe.
+        */
+       if (arp->ar_op == htons(ARPOP_REQUEST) &&
+           memcmp(&arp->ar_spa, &null_ip, ARP_PLEN) == 0 &&
+           memcmp(&arp->ar_tpa, &ip, ARP_PLEN) == 0 &&
+           memcmp(&arp->ar_sha, NetOurEther, ARP_HLEN) != 0) {
                target_ip_conflict = 1;
        }
 
index df94789de95f603000d91b2e14d0fec16b544e31..7663b9cd6c92541b657fb3eebcbd72ba98b9a6df 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -271,7 +271,8 @@ static void NetInitLoop(void)
 #endif
                env_changed_id = env_id;
        }
-       memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
+       if (eth_get_dev())
+               memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
 
        return;
 }
index 7f2393f6064c62976ea3bf0c5f10a2ac22e7d443..381b75f1c5b091799876aa77ec8997c97ea14fa9 100644 (file)
--- a/net/nfs.c
+++ b/net/nfs.c
 # define NFS_TIMEOUT CONFIG_NFS_TIMEOUT
 #endif
 
+#define NFS_RPC_ERR    1
+#define NFS_RPC_DROP   124
+
 static int fs_mounted;
 static unsigned long rpc_id;
 static int nfs_offset = -1;
 static int nfs_len;
+static ulong nfs_timeout = NFS_TIMEOUT;
 
 static char dirfh[NFS_FHSIZE]; /* file handle of directory */
 static char filefh[NFS_FHSIZE]; /* file handle of kernel image */
@@ -399,8 +403,10 @@ rpc_lookup_reply(int prog, uchar *pkt, unsigned len)
 
        debug("%s\n", __func__);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -428,8 +434,10 @@ nfs_mount_reply(uchar *pkt, unsigned len)
 
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -452,8 +460,10 @@ nfs_umountall_reply(uchar *pkt, unsigned len)
 
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -475,8 +485,10 @@ nfs_lookup_reply(uchar *pkt, unsigned len)
 
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -499,8 +511,10 @@ nfs_readlink_reply(uchar *pkt, unsigned len)
 
        memcpy((unsigned char *)&rpc_pkt, pkt, len);
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -534,8 +548,10 @@ nfs_read_reply(uchar *pkt, unsigned len)
 
        memcpy((uchar *)&rpc_pkt, pkt, sizeof(rpc_pkt.u.reply));
 
-       if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
-               return -1;
+       if (ntohl(rpc_pkt.u.reply.id) > rpc_id)
+               return -NFS_RPC_ERR;
+       else if (ntohl(rpc_pkt.u.reply.id) < rpc_id)
+               return -NFS_RPC_DROP;
 
        if (rpc_pkt.u.reply.rstatus  ||
            rpc_pkt.u.reply.verifier ||
@@ -574,7 +590,8 @@ NfsTimeout(void)
                NetStartAgain();
        } else {
                puts("T ");
-               NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
+               NetSetTimeout(nfs_timeout + NFS_TIMEOUT * NfsTimeoutCount,
+                             NfsTimeout);
                NfsSend();
        }
 }
@@ -583,6 +600,7 @@ static void
 NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
 {
        int rlen;
+       int reply;
 
        debug("%s\n", __func__);
 
@@ -591,19 +609,24 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
 
        switch (NfsState) {
        case STATE_PRCLOOKUP_PROG_MOUNT_REQ:
-               rpc_lookup_reply(PROG_MOUNT, pkt, len);
+               if (rpc_lookup_reply(PROG_MOUNT, pkt, len) == -NFS_RPC_DROP)
+                       break;
                NfsState = STATE_PRCLOOKUP_PROG_NFS_REQ;
                NfsSend();
                break;
 
        case STATE_PRCLOOKUP_PROG_NFS_REQ:
-               rpc_lookup_reply(PROG_NFS, pkt, len);
+               if (rpc_lookup_reply(PROG_NFS, pkt, len) == -NFS_RPC_DROP)
+                       break;
                NfsState = STATE_MOUNT_REQ;
                NfsSend();
                break;
 
        case STATE_MOUNT_REQ:
-               if (nfs_mount_reply(pkt, len)) {
+               reply = nfs_mount_reply(pkt, len);
+               if (reply == -NFS_RPC_DROP)
+                       break;
+               else if (reply == -NFS_RPC_ERR) {
                        puts("*** ERROR: Cannot mount\n");
                        /* just to be sure... */
                        NfsState = STATE_UMOUNT_REQ;
@@ -615,7 +638,10 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
                break;
 
        case STATE_UMOUNT_REQ:
-               if (nfs_umountall_reply(pkt, len)) {
+               reply = nfs_umountall_reply(pkt, len);
+               if (reply == -NFS_RPC_DROP)
+                       break;
+               else if (reply == -NFS_RPC_ERR) {
                        puts("*** ERROR: Cannot umount\n");
                        net_set_state(NETLOOP_FAIL);
                } else {
@@ -625,7 +651,10 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
                break;
 
        case STATE_LOOKUP_REQ:
-               if (nfs_lookup_reply(pkt, len)) {
+               reply = nfs_lookup_reply(pkt, len);
+               if (reply == -NFS_RPC_DROP)
+                       break;
+               else if (reply == -NFS_RPC_ERR) {
                        puts("*** ERROR: File lookup fail\n");
                        NfsState = STATE_UMOUNT_REQ;
                        NfsSend();
@@ -638,7 +667,10 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
                break;
 
        case STATE_READLINK_REQ:
-               if (nfs_readlink_reply(pkt, len)) {
+               reply = nfs_readlink_reply(pkt, len);
+               if (reply == -NFS_RPC_DROP)
+                       break;
+               else if (reply == -NFS_RPC_ERR) {
                        puts("*** ERROR: Symlink fail\n");
                        NfsState = STATE_UMOUNT_REQ;
                        NfsSend();
@@ -654,7 +686,7 @@ NfsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
 
        case STATE_READ_REQ:
                rlen = nfs_read_reply(pkt, len);
-               NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
+               NetSetTimeout(nfs_timeout, NfsTimeout);
                if (rlen > 0) {
                        nfs_offset += rlen;
                        NfsSend();
@@ -738,7 +770,7 @@ NfsStart(void)
        printf("\nLoad address: 0x%lx\n"
                "Loading: *\b", load_addr);
 
-       NetSetTimeout(NFS_TIMEOUT, NfsTimeout);
+       NetSetTimeout(nfs_timeout, NfsTimeout);
        net_set_udp_handler(NfsHandler);
 
        NfsTimeoutCount = 0;
index 09790eb7cf8202c051d594b5243aa3f843746691..6d333d559c19db8a9eac6a26ec01eaf73096babb 100644 (file)
@@ -446,8 +446,8 @@ static void
 TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
            unsigned len)
 {
-       ushort proto;
-       ushort *s;
+       __be16 proto;
+       __be16 *s;
        int i;
 
        if (dest != TftpOurPort) {
@@ -465,7 +465,7 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
                return;
        len -= 2;
        /* warning: don't use increment (++) in ntohs() macros!! */
-       s = (ushort *)pkt;
+       s = (__be16 *)pkt;
        proto = *s++;
        pkt = (uchar *)s;
        switch (ntohs(proto)) {
@@ -556,7 +556,7 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
                if (len < 2)
                        return;
                len -= 2;
-               TftpBlock = ntohs(*(ushort *)pkt);
+               TftpBlock = ntohs(*(__be16 *)pkt);
 
                update_block_number();
 
@@ -644,9 +644,9 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 
        case TFTP_ERROR:
                printf("\nTFTP error: '%s' (%d)\n",
-                      pkt + 2, ntohs(*(ushort *)pkt));
+                      pkt + 2, ntohs(*(__be16 *)pkt));
 
-               switch (ntohs(*(ushort *)pkt)) {
+               switch (ntohs(*(__be16 *)pkt)) {
                case TFTP_ERR_FILE_NOT_FOUND:
                case TFTP_ERR_ACCESS_DENIED:
                        puts("Not retrying...\n");
index d8fe948ff0a77ac3c10083fccd3a6133a6c03c6e..01873de2b16d393e82938ad4c422e206e04b958a 100644 (file)
@@ -98,6 +98,14 @@ LIBS-y += arch/$(ARCH)/cpu/tegra-common/libcputegra-common.o
 LIBS-y += $(CPUDIR)/tegra-common/libtegra-common.o
 endif
 
+ifneq ($(CONFIG_MX23)$(CONFIG_MX35),)
+LIBS-y += arch/$(ARCH)/imx-common/libimx-common.o
+endif
+
+ifeq ($(SOC),exynos)
+LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o
+endif
+
 # Add GCC lib
 ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
 PLATFORM_LIBGCC = $(SPLTREE)/arch/$(ARCH)/lib/libgcc.o
index c4e821116203df4a46d1fe6a615941833d953f92..aad9f59019ae1c4d842a750d07876f561526e69b 100755 (executable)
@@ -272,12 +272,13 @@ def set_test(name):
     test_name = name
     print name
 
-def fail(msg):
+def fail(msg, stdout):
     """Raise an error with a helpful failure message
 
     Args:
         msg: Message to display
     """
+    print stdout
     raise ValueError("Test '%s' failed: %s" % (test_name, msg))
 
 def run_fit_test(mkimage, u_boot):
@@ -341,11 +342,11 @@ def run_fit_test(mkimage, u_boot):
     set_test('Kernel load')
     stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
     if read_file(kernel) != read_file(kernel_out):
-        fail('Kernel not loaded')
+        fail('Kernel not loaded', stdout)
     if read_file(control_dtb) == read_file(fdt_out):
-        fail('FDT loaded but should be ignored')
+        fail('FDT loaded but should be ignored', stdout)
     if read_file(ramdisk) == read_file(ramdisk_out):
-        fail('Ramdisk loaded but should not be')
+        fail('Ramdisk loaded but should not be', stdout)
 
     # Find out the offset in the FIT where U-Boot has found the FDT
     line = find_matching(stdout, 'Booting using the fdt blob at ')
@@ -357,7 +358,7 @@ def run_fit_test(mkimage, u_boot):
     real_fit_offset = data.find(fdt_magic, 4)
     if fit_offset != real_fit_offset:
         fail('U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
-                (fit_offset, real_fit_offset))
+                (fit_offset, real_fit_offset), stdout)
 
     # Now a kernel and an FDT
     set_test('Kernel + FDT load')
@@ -365,11 +366,11 @@ def run_fit_test(mkimage, u_boot):
     fit = make_fit(mkimage, params)
     stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
     if read_file(kernel) != read_file(kernel_out):
-        fail('Kernel not loaded')
+        fail('Kernel not loaded', stdout)
     if read_file(control_dtb) != read_file(fdt_out):
-        fail('FDT not loaded')
+        fail('FDT not loaded', stdout)
     if read_file(ramdisk) == read_file(ramdisk_out):
-        fail('Ramdisk loaded but should not be')
+        fail('Ramdisk loaded but should not be', stdout)
 
     # Try a ramdisk
     set_test('Kernel + FDT + Ramdisk load')
@@ -378,7 +379,7 @@ def run_fit_test(mkimage, u_boot):
     fit = make_fit(mkimage, params)
     stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
     if read_file(ramdisk) != read_file(ramdisk_out):
-        fail('Ramdisk not loaded')
+        fail('Ramdisk not loaded', stdout)
 
 def run_tests():
     """Parse options, run the FIT tests and print the result"""
diff --git a/test/trace/test-trace.sh b/test/trace/test-trace.sh
new file mode 100755 (executable)
index 0000000..696a396
--- /dev/null
@@ -0,0 +1,89 @@
+# Copyright (c) 2013 The Chromium OS Authors.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+# Simple test script for tracing with sandbox
+
+OUTPUT_DIR=sandbox
+TRACE_OPT="FTRACE=1"
+
+fail() {
+       echo "Test failed: $1"
+       if [ -n ${tmp} ]; then
+               rm ${tmp}
+       fi
+       exit 1
+}
+
+build_uboot() {
+       echo "Build sandbox"
+       OPTS="O=${OUTPUT_DIR} ${TRACE_OPT}"
+       NUM_CPUS=$(grep -c processor /proc/cpuinfo)
+       make ${OPTS} sandbox_config
+       make ${OPTS} -s -j${NUM_CPUS}
+}
+
+run_trace() {
+       echo "Run trace"
+       ./${OUTPUT_DIR}/u-boot <<END
+       trace stats
+       hash sha256 0 10000
+       trace pause
+       trace stats
+       hash sha256 0 10000
+       trace stats
+       trace resume
+       hash sha256 0 10000
+       trace pause
+       trace stats
+       reset
+END
+}
+
+check_results() {
+       echo "Check results"
+
+       # Expect sha256 to run 3 times, so we see the string 6 times
+       if [ $(grep -c sha256 ${tmp}) -ne 6 ]; then
+               fail "sha256 error"
+       fi
+
+       # 4 sets of results (output of 'trace stats')
+       if [ $(grep -c "traced function calls" ${tmp}) -ne 4 ]; then
+               fail "trace output error"
+       fi
+
+       # Check trace counts. We expect to see an increase in the number of
+       # traced function calls between each 'trace stats' command, except
+       # between calls 2 and 3, where tracing is paused.
+       # This code gets the sign of the difference between each number and
+       # its predecessor.
+       counts="$(tr -d , <${tmp} | awk '/traced function calls/ { diff = $1 - upto; upto = $1; printf "%d ", diff < 0 ? -1 : (diff > 0 ? 1 : 0)}')"
+
+       if [ "${counts}" != "1 1 0 1 " ]; then
+               fail "trace collection error: ${counts}"
+       fi
+}
+
+echo "Simple trace test / sanity check using sandbox"
+echo
+tmp="$(tempfile)"
+build_uboot
+run_trace >${tmp}
+check_results ${tmp}
+rm ${tmp}
+echo "Test passed"
diff --git a/test/vboot/.gitignore b/test/vboot/.gitignore
new file mode 100644 (file)
index 0000000..4631242
--- /dev/null
@@ -0,0 +1,3 @@
+/*.dtb
+/test.fit
+/dev-keys
diff --git a/test/vboot/sandbox-kernel.dts b/test/vboot/sandbox-kernel.dts
new file mode 100644 (file)
index 0000000..a1e853c
--- /dev/null
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+       model = "Sandbox Verified Boot Test";
+       compatible = "sandbox";
+
+};
diff --git a/test/vboot/sandbox-u-boot.dts b/test/vboot/sandbox-u-boot.dts
new file mode 100644 (file)
index 0000000..a1e853c
--- /dev/null
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+       model = "Sandbox Verified Boot Test";
+       compatible = "sandbox";
+
+};
diff --git a/test/vboot/sign-configs.its b/test/vboot/sign-configs.its
new file mode 100644 (file)
index 0000000..db2ed79
--- /dev/null
@@ -0,0 +1,45 @@
+/dts-v1/;
+
+/ {
+       description = "Chrome OS kernel image with one or more FDT blobs";
+       #address-cells = <1>;
+
+       images {
+               kernel@1 {
+                       data = /incbin/("test-kernel.bin");
+                       type = "kernel_noload";
+                       arch = "sandbox";
+                       os = "linux";
+                       compression = "none";
+                       load = <0x4>;
+                       entry = <0x8>;
+                       kernel-version = <1>;
+                       hash@1 {
+                               algo = "sha1";
+                       };
+               };
+               fdt@1 {
+                       description = "snow";
+                       data = /incbin/("sandbox-kernel.dtb");
+                       type = "flat_dt";
+                       arch = "sandbox";
+                       compression = "none";
+                       fdt-version = <1>;
+                       hash@1 {
+                               algo = "sha1";
+                       };
+               };
+       };
+       configurations {
+               default = "conf@1";
+               conf@1 {
+                       kernel = "kernel@1";
+                       fdt = "fdt@1";
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               key-name-hint = "dev";
+                               sign-images = "fdt", "kernel";
+                       };
+               };
+       };
+};
diff --git a/test/vboot/sign-images.its b/test/vboot/sign-images.its
new file mode 100644 (file)
index 0000000..f69326a
--- /dev/null
@@ -0,0 +1,42 @@
+/dts-v1/;
+
+/ {
+       description = "Chrome OS kernel image with one or more FDT blobs";
+       #address-cells = <1>;
+
+       images {
+               kernel@1 {
+                       data = /incbin/("test-kernel.bin");
+                       type = "kernel_noload";
+                       arch = "sandbox";
+                       os = "linux";
+                       compression = "none";
+                       load = <0x4>;
+                       entry = <0x8>;
+                       kernel-version = <1>;
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               key-name-hint = "dev";
+                       };
+               };
+               fdt@1 {
+                       description = "snow";
+                       data = /incbin/("sandbox-kernel.dtb");
+                       type = "flat_dt";
+                       arch = "sandbox";
+                       compression = "none";
+                       fdt-version = <1>;
+                       signature@1 {
+                               algo = "sha1,rsa2048";
+                               key-name-hint = "dev";
+                       };
+               };
+       };
+       configurations {
+               default = "conf@1";
+               conf@1 {
+                       kernel = "kernel@1";
+                       fdt = "fdt@1";
+               };
+       };
+};
diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh
new file mode 100755 (executable)
index 0000000..c3cfade
--- /dev/null
@@ -0,0 +1,126 @@
+#!/bin/sh
+#
+# Copyright (c) 2013, Google Inc.
+#
+# Simple Verified Boot Test Script
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+
+set -e
+
+# Run U-Boot and report the result
+# Args:
+#      $1:     Test message
+run_uboot() {
+       echo -n "Test Verified Boot Run: $1: "
+       ${uboot} -d sandbox-u-boot.dtb >${tmp} -c '
+sb load host 0 100 test.fit;
+fdt addr 100;
+bootm 100;
+reset'
+       if ! grep -q "$2" ${tmp}; then
+               echo
+               echo "Verified boot key check failed, output follows:"
+               cat ${tmp}
+               false
+       else
+               echo "OK"
+       fi
+}
+
+echo "Simple Verified Boot Test"
+echo "========================="
+echo
+echo "Please see doc/uImage.FIT/verified-boot.txt for more information"
+echo
+
+err=0
+tmp=/tmp/vboot_test.$$
+
+dir=$(dirname $0)
+
+if [ -z ${O} ]; then
+       O=.
+fi
+O=$(readlink -f ${O})
+
+dtc="-I dts -O dtb -p 2000"
+uboot="${O}/u-boot"
+mkimage="${O}/tools/mkimage"
+keys="${dir}/dev-keys"
+echo ${mkimage} -D "${dtc}"
+
+echo "Build keys"
+mkdir -p ${keys}
+
+# Create an RSA key pair
+openssl genrsa -F4 -out ${keys}/dev.key 2048 2>/dev/null
+
+# Create a certificate containing the public key
+openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt
+
+pushd ${dir} >/dev/null
+
+# Compile our device tree files for kernel and U-Boot (CONFIG_OF_CONTROL)
+dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb
+dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
+
+# Create a number kernel image with zeroes
+head -c 5000 /dev/zero >test-kernel.bin
+
+# Build the FIT, but don't sign anything yet
+echo Build FIT with signed images
+${mkimage} -D "${dtc}" -f sign-images.its test.fit >${tmp}
+
+run_uboot "unsigned signatures:" "dev-"
+
+# Sign images with our dev keys
+echo Sign images
+${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
+
+run_uboot "signed images" "dev+"
+
+
+# Create a fresh .dtb without the public keys
+dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
+
+echo Build FIT with signed configuration
+${mkimage} -D "${dtc}" -f sign-configs.its test.fit >${tmp}
+
+run_uboot "unsigned config" "sha1+ OK"
+
+# Sign images with our dev keys
+echo Sign images
+${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
+
+run_uboot "signed config" "dev+"
+
+# Increment the first byte of the signature, which should cause failure
+sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value)
+newbyte=$(printf %x $((0x${sig:0:2} + 1)))
+sig="${newbyte} ${sig:2}"
+fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
+
+run_uboot "signed config with bad hash" "Bad Data Hash"
+
+popd >/dev/null
+
+echo
+if ${ok}; then
+       echo "Test passed"
+else
+       echo "Test failed"
+fi
index 9bce7194782f76c71e7214a81fcd8ef2e0ff2264..a7fee26cdd41087fe5e1f68482ce6b650fca62c9 100644 (file)
@@ -9,6 +9,7 @@
 /mxsboot
 /ncb
 /ncp
+/proftool
 /ubsha1
 /xway-swap-bytes
 /*.exe
index 4630f03dc53a93792d4c1e1f7f2c1fa60f6f20d2..46159b23d6f52097972c5db2afa8f31fcf1ce44c 100644 (file)
@@ -74,11 +74,13 @@ BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
 BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX)
+BIN_FILES-y += proftool(SFX)
 
 # Source files which exist outside the tools directory
 EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o
 EXT_OBJ_FILES-y += common/image.o
 EXT_OBJ_FILES-$(CONFIG_FIT) += common/image-fit.o
+EXT_OBJ_FILES-y += common/image-sig.o
 EXT_OBJ_FILES-y += lib/crc32.o
 EXT_OBJ_FILES-y += lib/md5.o
 EXT_OBJ_FILES-y += lib/sha1.o
@@ -87,6 +89,7 @@ EXT_OBJ_FILES-y += lib/sha1.o
 OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o
 OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o
 NOPED_OBJ_FILES-y += default_image.o
+NOPED_OBJ_FILES-y += proftool.o
 OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o
 NOPED_OBJ_FILES-y += fit_image.o
 OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o
@@ -122,6 +125,9 @@ LIBFDT_OBJ_FILES-y += fdt_rw.o
 LIBFDT_OBJ_FILES-y += fdt_strerror.o
 LIBFDT_OBJ_FILES-y += fdt_wip.o
 
+# RSA objects
+RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o
+
 # Generated LCD/video logo
 LOGO_H = $(OBJTREE)/include/bmp_logo.h
 LOGO_DATA_H = $(OBJTREE)/include/bmp_logo_data.h
@@ -149,8 +155,14 @@ endif # !LOGO_BMP
 HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c))
 HOSTSRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c))
 HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c))
+HOSTSRCS += $(addprefix $(SRCTREE)/lib/rsa/,$(RSA_OBJ_FILES-y:.o=.c))
 BINS   := $(addprefix $(obj),$(sort $(BIN_FILES-y)))
 LIBFDT_OBJS    := $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y))
+RSA_OBJS       := $(addprefix $(obj),$(RSA_OBJ_FILES-y))
+
+# We cannot check CONFIG_FIT_SIGNATURE here since it is not set on the host
+FIT_SIG_OBJ_FILES      := image-sig.o
+FIT_SIG_OBJS           := $(addprefix $(obj),$(FIT_SIG_OBJ_FILES))
 
 HOSTOBJS := $(addprefix $(obj),$(OBJ_FILES-y))
 NOPEDOBJS := $(addprefix $(obj),$(NOPED_OBJ_FILES-y))
@@ -180,6 +192,10 @@ $(obj)bmp_logo$(SFX):      $(obj)bmp_logo.o
        $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
        $(HOSTSTRIP) $@
 
+$(obj)proftool(SFX):   $(obj)proftool.o
+       $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+       $(HOSTSTRIP) $@
+
 $(obj)envcrc$(SFX):    $(obj)crc32.o $(obj)env_embedded.o $(obj)envcrc.o $(obj)sha1.o
        $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 
@@ -207,6 +223,7 @@ $(obj)mkimage$(SFX):        $(obj)aisimage.o \
                        $(obj)image-fit.o \
                        $(obj)image.o \
                        $(obj)image-host.o \
+                       $(FIT_SIG_OBJS) \
                        $(obj)imximage.o \
                        $(obj)kwbimage.o \
                        $(obj)pblimage.o \
@@ -216,8 +233,9 @@ $(obj)mkimage$(SFX):        $(obj)aisimage.o \
                        $(obj)omapimage.o \
                        $(obj)sha1.o \
                        $(obj)ublimage.o \
-                       $(LIBFDT_OBJS)
-       $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+                       $(LIBFDT_OBJS) \
+                       $(RSA_OBJS)
+       $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS)
        $(HOSTSTRIP) $@
 
 $(obj)mk$(BOARD)spl$(SFX):     $(obj)mkexynosspl.o
@@ -253,6 +271,9 @@ $(obj)%.o: $(SRCTREE)/lib/%.c
 $(obj)%.o: $(SRCTREE)/lib/libfdt/%.c
        $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
 
+$(obj)%.o: $(SRCTREE)/lib/rsa/%.c
+       $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
+
 subdirs:
 ifeq ($(TOOLSUBDIRS),)
        @:
index cc123dd37adf81996346e7f776f72f21dee8f4f8..281c2bda13a26e6a73dbd8619feccee869344b2e 100644 (file)
@@ -105,9 +105,11 @@ static int fit_handle_file (struct mkimage_params *params)
 {
        char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
        char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
-       int tfd;
+       int tfd, destfd = 0;
+       void *dest_blob = NULL;
        struct stat sbuf;
        void *ptr;
+       off_t destfd_size = 0;
 
        /* Flattened Image Tree (FIT) format  handling */
        debug ("FIT format handling\n");
@@ -122,29 +124,44 @@ static int fit_handle_file (struct mkimage_params *params)
        }
        sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX);
 
-       /* dtc -I dts -O dtb -p 500 datafile > tmpfile */
-       sprintf (cmd, "%s %s %s > %s",
-               MKIMAGE_DTC, params->dtc, params->datafile, tmpfile);
-       debug ("Trying to execute \"%s\"\n", cmd);
+       /* We either compile the source file, or use the existing FIT image */
+       if (params->datafile) {
+               /* dtc -I dts -O dtb -p 500 datafile > tmpfile */
+               snprintf(cmd, sizeof(cmd), "%s %s %s > %s",
+                        MKIMAGE_DTC, params->dtc, params->datafile, tmpfile);
+               debug("Trying to execute \"%s\"\n", cmd);
+       } else {
+               snprintf(cmd, sizeof(cmd), "cp %s %s",
+                        params->imagefile, tmpfile);
+       }
        if (system (cmd) == -1) {
                fprintf (stderr, "%s: system(%s) failed: %s\n",
                                params->cmdname, cmd, strerror(errno));
                goto err_system;
        }
 
+       if (params->keydest) {
+               destfd = mmap_fdt(params, params->keydest, &dest_blob, &sbuf);
+               if (destfd < 0)
+                       goto err_keydest;
+               destfd_size = sbuf.st_size;
+       }
+
        tfd = mmap_fdt(params, tmpfile, &ptr, &sbuf);
        if (tfd < 0)
                goto err_mmap;
 
        /* set hashes for images in the blob */
-       if (fit_add_verification_data(ptr)) {
-               fprintf (stderr, "%s Can't add hashes to FIT blob",
-                               params->cmdname);
+       if (fit_add_verification_data(params->keydir,
+                                     dest_blob, ptr, params->comment,
+                                     params->require_keys)) {
+               fprintf(stderr, "%s Can't add hashes to FIT blob\n",
+                       params->cmdname);
                goto err_add_hashes;
        }
 
-       /* add a timestamp at offset 0 i.e., root  */
-       if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) {
+       /* for first image creation, add a timestamp at offset 0 i.e., root  */
+       if (params->datafile && fit_set_timestamp(ptr, 0, sbuf.st_mtime)) {
                fprintf (stderr, "%s: Can't add image timestamp\n",
                                params->cmdname);
                goto err_add_timestamp;
@@ -153,6 +170,10 @@ static int fit_handle_file (struct mkimage_params *params)
 
        munmap ((void *)ptr, sbuf.st_size);
        close (tfd);
+       if (dest_blob) {
+               munmap(dest_blob, destfd_size);
+               close(destfd);
+       }
 
        if (rename (tmpfile, params->imagefile) == -1) {
                fprintf (stderr, "%s: Can't rename %s to %s: %s\n",
@@ -168,6 +189,9 @@ err_add_timestamp:
 err_add_hashes:
        munmap(ptr, sbuf.st_size);
 err_mmap:
+       if (dest_blob)
+               munmap(dest_blob, destfd_size);
+err_keydest:
 err_system:
        unlink(tmpfile);
        return -1;
index d944d0ff4e3cc1f2363b9e5fce2653ee986e0607..932384beab88915bc3c27c391ab40de76d1748a5 100644 (file)
  */
 
 #include "mkimage.h"
-#include <bootstage.h>
 #include <image.h>
-#include <sha1.h>
-#include <time.h>
-#include <u-boot/crc.h>
-#include <u-boot/md5.h>
+#include <version.h>
 
 /**
  * fit_set_hash_value - set hash value in requested has node
@@ -108,9 +104,165 @@ static int fit_image_process_hash(void *fit, const char *image_name,
 }
 
 /**
- * fit_image_add_verification_data() - calculate/set hash data for image node
+ * fit_image_write_sig() - write the signature to a FIT
  *
- * This adds hash values for a component image node.
+ * This writes the signature and signer data to the FIT.
+ *
+ * @fit: pointer to the FIT format image header
+ * @noffset: hash node offset
+ * @value: signature value to be set
+ * @value_len: signature value length
+ * @comment: Text comment to write (NULL for none)
+ *
+ * returns
+ *     0, on success
+ *     -FDT_ERR_..., on failure
+ */
+static int fit_image_write_sig(void *fit, int noffset, uint8_t *value,
+               int value_len, const char *comment, const char *region_prop,
+               int region_proplen)
+{
+       int string_size;
+       int ret;
+
+       /*
+        * Get the current string size, before we update the FIT and add
+        * more
+        */
+       string_size = fdt_size_dt_strings(fit);
+
+       ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
+       if (!ret) {
+               ret = fdt_setprop_string(fit, noffset, "signer-name",
+                                        "mkimage");
+       }
+       if (!ret) {
+               ret = fdt_setprop_string(fit, noffset, "signer-version",
+                                 PLAIN_VERSION);
+       }
+       if (comment && !ret)
+               ret = fdt_setprop_string(fit, noffset, "comment", comment);
+       if (!ret)
+               ret = fit_set_timestamp(fit, noffset, time(NULL));
+       if (region_prop && !ret) {
+               uint32_t strdata[2];
+
+               ret = fdt_setprop(fit, noffset, "hashed-nodes",
+                                  region_prop, region_proplen);
+               strdata[0] = 0;
+               strdata[1] = cpu_to_fdt32(string_size);
+               if (!ret) {
+                       ret = fdt_setprop(fit, noffset, "hashed-strings",
+                                         strdata, sizeof(strdata));
+               }
+       }
+
+       return ret;
+}
+
+static int fit_image_setup_sig(struct image_sign_info *info,
+               const char *keydir, void *fit, const char *image_name,
+               int noffset, const char *require_keys)
+{
+       const char *node_name;
+       char *algo_name;
+
+       node_name = fit_get_name(fit, noffset, NULL);
+       if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
+               printf("Can't get algo property for '%s' signature node in '%s' image node\n",
+                      node_name, image_name);
+               return -1;
+       }
+
+       memset(info, '\0', sizeof(*info));
+       info->keydir = keydir;
+       info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+       info->fit = fit;
+       info->node_offset = noffset;
+       info->algo = image_get_sig_algo(algo_name);
+       info->require_keys = require_keys;
+       if (!info->algo) {
+               printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
+                      algo_name, node_name, image_name);
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * fit_image_process_sig- Process a single subnode of the images/ node
+ *
+ * Check each subnode and process accordingly. For signature nodes we
+ * generate a signed hash of the supplised data and store it in the node.
+ *
+ * @keydir:    Directory containing keys to use for signing
+ * @keydest:   Destination FDT blob to write public keys into
+ * @fit:       pointer to the FIT format image header
+ * @image_name:        name of image being processes (used to display errors)
+ * @noffset:   subnode offset
+ * @data:      data to process
+ * @size:      size of data in bytes
+ * @comment:   Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ * @return 0 if ok, -1 on error
+ */
+static int fit_image_process_sig(const char *keydir, void *keydest,
+               void *fit, const char *image_name,
+               int noffset, const void *data, size_t size,
+               const char *comment, int require_keys)
+{
+       struct image_sign_info info;
+       struct image_region region;
+       const char *node_name;
+       uint8_t *value;
+       uint value_len;
+       int ret;
+
+       if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
+                               require_keys ? "image" : NULL))
+               return -1;
+
+       node_name = fit_get_name(fit, noffset, NULL);
+       region.data = data;
+       region.size = size;
+       ret = info.algo->sign(&info, &region, 1, &value, &value_len);
+       if (ret) {
+               printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
+                      node_name, image_name, ret);
+
+               /* We allow keys to be missing */
+               if (ret == -ENOENT)
+                       return 0;
+               return -1;
+       }
+
+       ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
+                       NULL, 0);
+       if (ret) {
+               printf("Can't write signature for '%s' signature node in '%s' image node: %s\n",
+                      node_name, image_name, fdt_strerror(ret));
+               return -1;
+       }
+       free(value);
+
+       /* Get keyname again, as FDT has changed and invalidated our pointer */
+       info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+
+       /* Write the public key into the supplied FDT file */
+       if (keydest && info.algo->add_verify_data(&info, keydest)) {
+               printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
+                      node_name, image_name);
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * fit_image_add_verification_data() - calculate/set verig. data for image node
+ *
+ * This adds hash and signature values for an component image node.
  *
  * All existing hash subnodes are checked, if algorithm property is set to
  * one of the supported hash algorithms, hash value is computed and
@@ -133,11 +285,17 @@ static int fit_image_process_hash(void *fit, const char *image_name,
  *
  * For signature details, please see doc/uImage.FIT/signature.txt
  *
+ * @keydir     Directory containing *.key and *.crt files (or NULL)
+ * @keydest    FDT Blob to write public keys into (NULL if none)
  * @fit:       Pointer to the FIT format image header
  * @image_noffset: Requested component image node
+ * @comment:   Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
  * @return: 0 on success, <0 on failure
  */
-int fit_image_add_verification_data(void *fit, int image_noffset)
+int fit_image_add_verification_data(const char *keydir, void *keydest,
+               void *fit, int image_noffset, const char *comment,
+               int require_keys)
 {
        const char *image_name;
        const void *data;
@@ -169,6 +327,12 @@ int fit_image_add_verification_data(void *fit, int image_noffset)
                             strlen(FIT_HASH_NODENAME))) {
                        ret = fit_image_process_hash(fit, image_name, noffset,
                                                data, size);
+               } else if (IMAGE_ENABLE_SIGN && keydir &&
+                          !strncmp(node_name, FIT_SIG_NODENAME,
+                               strlen(FIT_SIG_NODENAME))) {
+                       ret = fit_image_process_sig(keydir, keydest,
+                               fit, image_name, noffset, data, size,
+                               comment, require_keys);
                }
                if (ret)
                        return -1;
@@ -177,9 +341,326 @@ int fit_image_add_verification_data(void *fit, int image_noffset)
        return 0;
 }
 
-int fit_add_verification_data(void *fit)
+struct strlist {
+       int count;
+       char **strings;
+};
+
+static void strlist_init(struct strlist *list)
+{
+       memset(list, '\0', sizeof(*list));
+}
+
+static void strlist_free(struct strlist *list)
+{
+       int i;
+
+       for (i = 0; i < list->count; i++)
+               free(list->strings[i]);
+       free(list->strings);
+}
+
+static int strlist_add(struct strlist *list, const char *str)
+{
+       char *dup;
+
+       dup = strdup(str);
+       list->strings = realloc(list->strings,
+                               (list->count + 1) * sizeof(char *));
+       if (!list || !str)
+               return -1;
+       list->strings[list->count++] = dup;
+
+       return 0;
+}
+
+static const char *fit_config_get_image_list(void *fit, int noffset,
+               int *lenp, int *allow_missingp)
+{
+       static const char default_list[] = FIT_KERNEL_PROP "\0"
+                       FIT_FDT_PROP;
+       const char *prop;
+
+       /* If there is an "image" property, use that */
+       prop = fdt_getprop(fit, noffset, "sign-images", lenp);
+       if (prop) {
+               *allow_missingp = 0;
+               return *lenp ? prop : NULL;
+       }
+
+       /* Default image list */
+       *allow_missingp = 1;
+       *lenp = sizeof(default_list);
+
+       return default_list;
+}
+
+static int fit_config_get_hash_list(void *fit, int conf_noffset,
+                                   int sig_offset, struct strlist *node_inc)
+{
+       int allow_missing;
+       const char *prop, *iname, *end;
+       const char *conf_name, *sig_name;
+       char name[200], path[200];
+       int image_count;
+       int ret, len;
+
+       conf_name = fit_get_name(fit, conf_noffset, NULL);
+       sig_name = fit_get_name(fit, sig_offset, NULL);
+
+       /*
+        * Build a list of nodes we need to hash. We always need the root
+        * node and the configuration.
+        */
+       strlist_init(node_inc);
+       snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
+       if (strlist_add(node_inc, "/") ||
+           strlist_add(node_inc, name))
+               goto err_mem;
+
+       /* Get a list of images that we intend to sign */
+       prop = fit_config_get_image_list(fit, conf_noffset, &len,
+                                       &allow_missing);
+       if (!prop)
+               return 0;
+
+       /* Locate the images */
+       end = prop + len;
+       image_count = 0;
+       for (iname = prop; iname < end; iname += strlen(iname) + 1) {
+               int noffset;
+               int image_noffset;
+               int hash_count;
+
+               image_noffset = fit_conf_get_prop_node(fit, conf_noffset,
+                                                      iname);
+               if (image_noffset < 0) {
+                       printf("Failed to find image '%s' in  configuration '%s/%s'\n",
+                              iname, conf_name, sig_name);
+                       if (allow_missing)
+                               continue;
+
+                       return -ENOENT;
+               }
+
+               ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
+               if (ret < 0)
+                       goto err_path;
+               if (strlist_add(node_inc, path))
+                       goto err_mem;
+
+               snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
+                        conf_name);
+
+               /* Add all this image's hashes */
+               hash_count = 0;
+               for (noffset = fdt_first_subnode(fit, image_noffset);
+                    noffset >= 0;
+                    noffset = fdt_next_subnode(fit, noffset)) {
+                       const char *name = fit_get_name(fit, noffset, NULL);
+
+                       if (strncmp(name, FIT_HASH_NODENAME,
+                                   strlen(FIT_HASH_NODENAME)))
+                               continue;
+                       ret = fdt_get_path(fit, noffset, path, sizeof(path));
+                       if (ret < 0)
+                               goto err_path;
+                       if (strlist_add(node_inc, path))
+                               goto err_mem;
+                       hash_count++;
+               }
+
+               if (!hash_count) {
+                       printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
+                              conf_name, sig_name, iname);
+                       return -ENOMSG;
+               }
+
+               image_count++;
+       }
+
+       if (!image_count) {
+               printf("Failed to find any images for configuration '%s/%s'\n",
+                      conf_name, sig_name);
+               return -ENOMSG;
+       }
+
+       return 0;
+
+err_mem:
+       printf("Out of memory processing configuration '%s/%s'\n", conf_name,
+              sig_name);
+       return -ENOMEM;
+
+err_path:
+       printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
+              iname, conf_name, sig_name, fdt_strerror(ret));
+       return -ENOENT;
+}
+
+static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
+               struct image_region **regionp, int *region_countp,
+               char **region_propp, int *region_proplen)
 {
-       int images_noffset;
+       char * const exc_prop[] = {"data"};
+       struct strlist node_inc;
+       struct image_region *region;
+       struct fdt_region fdt_regions[100];
+       const char *conf_name, *sig_name;
+       char path[200];
+       int count, i;
+       char *region_prop;
+       int ret, len;
+
+       conf_name = fit_get_name(fit, conf_noffset, NULL);
+       sig_name = fit_get_name(fit, conf_noffset, NULL);
+       debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
+
+       /* Get a list of nodes we want to hash */
+       ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc);
+       if (ret)
+               return ret;
+
+       /* Get a list of regions to hash */
+       count = fdt_find_regions(fit, node_inc.strings, node_inc.count,
+                       exc_prop, ARRAY_SIZE(exc_prop),
+                       fdt_regions, ARRAY_SIZE(fdt_regions),
+                       path, sizeof(path), 1);
+       if (count < 0) {
+               printf("Failed to hash configuration '%s/%s': %s\n", conf_name,
+                      sig_name, fdt_strerror(ret));
+               return -EIO;
+       }
+       if (count == 0) {
+               printf("No data to hash for configuration '%s/%s': %s\n",
+                      conf_name, sig_name, fdt_strerror(ret));
+               return -EINVAL;
+       }
+
+       /* Build our list of data blocks */
+       region = fit_region_make_list(fit, fdt_regions, count, NULL);
+       if (!region) {
+               printf("Out of memory hashing configuration '%s/%s'\n",
+                      conf_name, sig_name);
+               return -ENOMEM;
+       }
+
+       /* Create a list of all hashed properties */
+       debug("Hash nodes:\n");
+       for (i = len = 0; i < node_inc.count; i++) {
+               debug("   %s\n", node_inc.strings[i]);
+               len += strlen(node_inc.strings[i]) + 1;
+       }
+       region_prop = malloc(len);
+       if (!region_prop) {
+               printf("Out of memory setting up regions for configuration '%s/%s'\n",
+                      conf_name, sig_name);
+               return -ENOMEM;
+       }
+       for (i = len = 0; i < node_inc.count;
+            len += strlen(node_inc.strings[i]) + 1, i++)
+               strcpy(region_prop + len, node_inc.strings[i]);
+       strlist_free(&node_inc);
+
+       *region_countp = count;
+       *regionp = region;
+       *region_propp = region_prop;
+       *region_proplen = len;
+
+       return 0;
+}
+
+static int fit_config_process_sig(const char *keydir, void *keydest,
+               void *fit, const char *conf_name, int conf_noffset,
+               int noffset, const char *comment, int require_keys)
+{
+       struct image_sign_info info;
+       const char *node_name;
+       struct image_region *region;
+       char *region_prop;
+       int region_proplen;
+       int region_count;
+       uint8_t *value;
+       uint value_len;
+       int ret;
+
+       node_name = fit_get_name(fit, noffset, NULL);
+       if (fit_config_get_data(fit, conf_noffset, noffset, &region,
+                               &region_count, &region_prop, &region_proplen))
+               return -1;
+
+       if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
+                               require_keys ? "conf" : NULL))
+               return -1;
+
+       ret = info.algo->sign(&info, region, region_count, &value, &value_len);
+       free(region);
+       if (ret) {
+               printf("Failed to sign '%s' signature node in '%s' conf node\n",
+                      node_name, conf_name);
+
+               /* We allow keys to be missing */
+               if (ret == -ENOENT)
+                       return 0;
+               return -1;
+       }
+
+       if (fit_image_write_sig(fit, noffset, value, value_len, comment,
+                               region_prop, region_proplen)) {
+               printf("Can't write signature for '%s' signature node in '%s' conf node\n",
+                      node_name, conf_name);
+               return -1;
+       }
+       free(value);
+       free(region_prop);
+
+       /* Get keyname again, as FDT has changed and invalidated our pointer */
+       info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+
+       /* Write the public key into the supplied FDT file */
+       if (keydest && info.algo->add_verify_data(&info, keydest)) {
+               printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
+                      node_name, conf_name);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int fit_config_add_verification_data(const char *keydir, void *keydest,
+               void *fit, int conf_noffset, const char *comment,
+               int require_keys)
+{
+       const char *conf_name;
+       int noffset;
+
+       conf_name = fit_get_name(fit, conf_noffset, NULL);
+
+       /* Process all hash subnodes of the configuration node */
+       for (noffset = fdt_first_subnode(fit, conf_noffset);
+            noffset >= 0;
+            noffset = fdt_next_subnode(fit, noffset)) {
+               const char *node_name;
+               int ret = 0;
+
+               node_name = fit_get_name(fit, noffset, NULL);
+               if (!strncmp(node_name, FIT_SIG_NODENAME,
+                            strlen(FIT_SIG_NODENAME))) {
+                       ret = fit_config_process_sig(keydir, keydest,
+                               fit, conf_name, conf_noffset, noffset, comment,
+                               require_keys);
+               }
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+                             const char *comment, int require_keys)
+{
+       int images_noffset, confs_noffset;
        int noffset;
        int ret;
 
@@ -199,7 +680,31 @@ int fit_add_verification_data(void *fit)
                 * Direct child node of the images parent node,
                 * i.e. component image node.
                 */
-               ret = fit_image_add_verification_data(fit, noffset);
+               ret = fit_image_add_verification_data(keydir, keydest,
+                               fit, noffset, comment, require_keys);
+               if (ret)
+                       return ret;
+       }
+
+       /* If there are no keys, we can't sign configurations */
+       if (!IMAGE_ENABLE_SIGN || !keydir)
+               return 0;
+
+       /* Find configurations parent node offset */
+       confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
+       if (confs_noffset < 0) {
+               printf("Can't find images parent node '%s' (%s)\n",
+                      FIT_IMAGES_PATH, fdt_strerror(confs_noffset));
+               return -ENOENT;
+       }
+
+       /* Process its subnodes, print out component images details */
+       for (noffset = fdt_first_subnode(fit, confs_noffset);
+            noffset >= 0;
+            noffset = fdt_next_subnode(fit, noffset)) {
+               ret = fit_config_add_verification_data(keydir, keydest,
+                                                      fit, noffset, comment,
+                                                      require_keys);
                if (ret)
                        return ret;
        }
index e43b09f76612e58b26e07244929d2bc7c535b5fe..d312844e9c303abf66592ff3b4e1aa7b5efa2533 100644 (file)
@@ -183,6 +183,11 @@ main (int argc, char **argv)
                                        genimg_get_arch_id (*++argv)) < 0)
                                        usage ();
                                goto NXTARG;
+                       case 'c':
+                               if (--argc <= 0)
+                                       usage();
+                               params.comment = *++argv;
+                               goto NXTARG;
                        case 'C':
                                if ((--argc <= 0) ||
                                        (params.comp =
@@ -240,19 +245,34 @@ main (int argc, char **argv)
                        case 'f':
                                if (--argc <= 0)
                                        usage ();
+                               params.datafile = *++argv;
+                               /* no break */
+                       case 'F':
                                /*
                                 * The flattened image tree (FIT) format
                                 * requires a flattened device tree image type
                                 */
                                params.type = IH_TYPE_FLATDT;
-                               params.datafile = *++argv;
                                params.fflag = 1;
                                goto NXTARG;
+                       case 'k':
+                               if (--argc <= 0)
+                                       usage();
+                               params.keydir = *++argv;
+                               goto NXTARG;
+                       case 'K':
+                               if (--argc <= 0)
+                                       usage();
+                               params.keydest = *++argv;
+                               goto NXTARG;
                        case 'n':
                                if (--argc <= 0)
                                        usage ();
                                params.imagename = *++argv;
                                goto NXTARG;
+                       case 'r':
+                               params.require_keys = 1;
+                               break;
                        case 'R':
                                if (--argc <= 0)
                                        usage();
@@ -623,8 +643,20 @@ usage ()
                         "          -d ==> use image data from 'datafile'\n"
                         "          -x ==> set XIP (execute in place)\n",
                params.cmdname);
-       fprintf (stderr, "       %s [-D dtc_options] -f fit-image.its fit-image\n",
+       fprintf(stderr, "       %s [-D dtc_options] [-f fit-image.its|-F] fit-image\n",
                params.cmdname);
+       fprintf(stderr, "          -D => set options for device tree compiler\n"
+                       "          -f => input filename for FIT source\n");
+#ifdef CONFIG_FIT_SIGNATURE
+       fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-r]\n"
+                       "          -k => set directory containing private keys\n"
+                       "          -K => write public keys to this .dtb file\n"
+                       "          -c => add comment in signature node\n"
+                       "          -F => re-sign existing FIT image\n"
+                       "          -r => mark keys used as 'required' in dtb\n");
+#else
+       fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
+#endif
        fprintf (stderr, "       %s -V ==> print version information and exit\n",
                params.cmdname);
 
index 03c6c8f5237d741cbc17793ace87fee2a855c946..1d9984e1a3dd36c9e3f9ea147a641c79ede128f2 100644 (file)
@@ -87,6 +87,10 @@ struct mkimage_params {
        char *datafile;
        char *imagefile;
        char *cmdname;
+       const char *keydir;     /* Directory holding private keys */
+       const char *keydest;    /* Destination .dtb for public key */
+       const char *comment;    /* Comment to add to signature node */
+       int require_keys;       /* 1 to mark signing keys as 'required' */
 };
 
 /*
index 508a747a3f6e4875eb9a9d7670cce06bd0e54e4a..5f39dc5bbfd22108e3f235a69a0eb22599285ec8 100644 (file)
 #include "pblimage.h"
 
 /*
- * The PBL can load up to 64 bytes at a time, so we split the U-Boot
- * image into 64 byte chunks. PBL needs a command for each piece, of
- * the form "81xxxxxx", where "xxxxxx" is the offset. SYS_TEXT_BASE
- * is 0xFFF80000 for PBL boot, and PBL only cares about low 24-bit,
- * so it starts from 0x81F80000.
+ * Initialize to an invalid value.
  */
-static uint32_t next_pbl_cmd = 0x81F80000;
+static uint32_t next_pbl_cmd = 0x82000000;
 /*
  * need to store all bytes in memory for calculating crc32, then write the
  * bytes to image file for PBL boot.
  */
-static unsigned char mem_buf[600000];
+static unsigned char mem_buf[1000000];
 static unsigned char *pmem_buf = mem_buf;
 static int pbl_size;
 static char *fname = "Unknown";
@@ -52,6 +48,27 @@ static union
 
 #define ENDIANNESS ((char)endian_test.l)
 
+/*
+ * The PBL can load up to 64 bytes at a time, so we split the U-Boot
+ * image into 64 byte chunks. PBL needs a command for each piece, of
+ * the form "81xxxxxx", where "xxxxxx" is the offset. Calculate the
+ * start offset by subtracting the size of the u-boot image from the
+ * top of the allowable 24-bit range.
+ */
+static void init_next_pbl_cmd(FILE *fp_uboot)
+{
+       struct stat st;
+       int fd = fileno(fp_uboot);
+
+       if (fstat(fd, &st) == -1) {
+               printf("Error: Could not determine u-boot image size. %s\n",
+                       strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       next_pbl_cmd = 0x82000000 - st.st_size;
+}
+
 static void generate_pbl_cmd(void)
 {
        uint32_t val = next_pbl_cmd;
@@ -80,6 +97,7 @@ static void pbl_fget(size_t size, FILE *stream)
 /* load split u-boot with PBI command 81xxxxxx. */
 static void load_uboot(FILE *fp_uboot)
 {
+       init_next_pbl_cmd(fp_uboot);
        while (next_pbl_cmd < 0x82000000) {
                generate_pbl_cmd();
                pbl_fget(64, fp_uboot);
diff --git a/tools/proftool.c b/tools/proftool.c
new file mode 100644 (file)
index 0000000..a48ed28
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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
+ */
+
+/* Decode and dump U-Boot profiling information */
+
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+
+#include <compiler.h>
+#include <trace.h>
+
+#define MAX_LINE_LEN 500
+
+enum {
+       FUNCF_TRACE     = 1 << 0,       /* Include this function in trace */
+};
+
+struct func_info {
+       unsigned long offset;
+       const char *name;
+       unsigned long code_size;
+       unsigned long call_count;
+       unsigned flags;
+       /* the section this function is in */
+       struct objsection_info *objsection;
+};
+
+enum trace_line_type {
+       TRACE_LINE_INCLUDE,
+       TRACE_LINE_EXCLUDE,
+};
+
+struct trace_configline_info {
+       struct trace_configline_info *next;
+       enum trace_line_type type;
+       const char *name;       /* identifier name / wildcard */
+       regex_t regex;          /* Regex to use if name starts with / */
+};
+
+/* The contents of the trace config file */
+struct trace_configline_info *trace_config_head;
+
+struct func_info *func_list;
+int func_count;
+struct trace_call *call_list;
+int call_count;
+int verbose;   /* Verbosity level 0=none, 1=warn, 2=notice, 3=info, 4=debug */
+unsigned long text_offset;             /* text address of first function */
+
+static void outf(int level, const char *fmt, ...)
+               __attribute__ ((format (__printf__, 2, 3)));
+#define error(fmt, b...) outf(0, fmt, ##b)
+#define warn(fmt, b...) outf(1, fmt, ##b)
+#define notice(fmt, b...) outf(2, fmt, ##b)
+#define info(fmt, b...) outf(3, fmt, ##b)
+#define debug(fmt, b...) outf(4, fmt, ##b)
+
+
+static void outf(int level, const char *fmt, ...)
+{
+       if (verbose >= level) {
+               va_list args;
+
+               va_start(args, fmt);
+               vfprintf(stderr, fmt, args);
+               va_end(args);
+       }
+}
+
+static void usage(void)
+{
+       fprintf(stderr,
+               "Usage: proftool -cds -v3 <cmd> <profdata>\n"
+               "\n"
+               "Commands\n"
+               "   dump-ftrace\t\tDump out textual data in ftrace format\n"
+               "\n"
+               "Options:\n"
+               "   -m <map>\tSpecify Systen.map file\n"
+               "   -t <trace>\tSpecific trace data file (from U-Boot)\n"
+               "   -v <0-4>\tSpecify verbosity\n");
+       exit(EXIT_FAILURE);
+}
+
+static int h_cmp_offset(const void *v1, const void *v2)
+{
+       const struct func_info *f1 = v1, *f2 = v2;
+
+       return (f1->offset / FUNC_SITE_SIZE) - (f2->offset / FUNC_SITE_SIZE);
+}
+
+static int read_system_map(FILE *fin)
+{
+       unsigned long offset, start = 0;
+       struct func_info *func;
+       char buff[MAX_LINE_LEN];
+       char symtype;
+       char symname[MAX_LINE_LEN + 1];
+       int linenum;
+       int alloced;
+
+       for (linenum = 1, alloced = func_count = 0;; linenum++) {
+               int fields = 0;
+
+               if (fgets(buff, sizeof(buff), fin))
+                       fields = sscanf(buff, "%lx %c %100s\n", &offset,
+                               &symtype, symname);
+               if (fields == 2) {
+                       continue;
+               } else if (feof(fin)) {
+                       break;
+               } else if (fields < 2) {
+                       error("Map file line %d: invalid format\n", linenum);
+                       return 1;
+               }
+
+               /* Must be a text symbol */
+               symtype = tolower(symtype);
+               if (symtype != 't' && symtype != 'w')
+                       continue;
+
+               if (func_count == alloced) {
+                       alloced += 256;
+                       func_list = realloc(func_list,
+                                       sizeof(struct func_info) * alloced);
+                       assert(func_list);
+               }
+               if (!func_count)
+                       start = offset;
+
+               func = &func_list[func_count++];
+               memset(func, '\0', sizeof(*func));
+               func->offset = offset - start;
+               func->name = strdup(symname);
+               func->flags = FUNCF_TRACE;      /* trace by default */
+
+               /* Update previous function's code size */
+               if (func_count > 1)
+                       func[-1].code_size = func->offset - func[-1].offset;
+       }
+       notice("%d functions found in map file\n", func_count);
+       text_offset = start;
+       return 0;
+}
+
+static int read_data(FILE *fin, void *buff, int size)
+{
+       int err;
+
+       err = fread(buff, 1, size, fin);
+       if (!err)
+               return 1;
+       if (err != size) {
+               error("Cannot read profile file at pos %ld\n", ftell(fin));
+               return -1;
+       }
+       return 0;
+}
+
+static struct func_info *find_func_by_offset(uint32_t offset)
+{
+       struct func_info key, *found;
+
+       key.offset = offset;
+       found = bsearch(&key, func_list, func_count, sizeof(struct func_info),
+                       h_cmp_offset);
+
+       return found;
+}
+
+/* This finds the function which contains the given offset */
+static struct func_info *find_caller_by_offset(uint32_t offset)
+{
+       int low;        /* least function that could be a match */
+       int high;       /* greated function that could be a match */
+       struct func_info key;
+
+       low = 0;
+       high = func_count - 1;
+       key.offset = offset;
+       while (high > low + 1) {
+               int mid = (low + high) / 2;
+               int result;
+
+               result = h_cmp_offset(&key, &func_list[mid]);
+               if (result > 0)
+                       low = mid;
+               else if (result < 0)
+                       high = mid;
+               else
+                       return &func_list[mid];
+       }
+
+       return low >= 0 ? &func_list[low] : NULL;
+}
+
+static int read_calls(FILE *fin, int count)
+{
+       struct trace_call *call_data;
+       int i;
+
+       notice("call count: %d\n", count);
+       call_list = (struct trace_call *)calloc(count, sizeof(*call_data));
+       if (!call_list) {
+               error("Cannot allocate call_list\n");
+               return -1;
+       }
+       call_count = count;
+
+       call_data = call_list;
+       for (i = 0; i < count; i++, call_data++) {
+               if (read_data(fin, call_data, sizeof(*call_data)))
+                       return 1;
+       }
+       return 0;
+}
+
+static int read_profile(FILE *fin, int *not_found)
+{
+       struct trace_output_hdr hdr;
+
+       *not_found = 0;
+       while (!feof(fin)) {
+               int err;
+
+               err = read_data(fin, &hdr, sizeof(hdr));
+               if (err == 1)
+                       break; /* EOF */
+               else if (err)
+                       return 1;
+
+               switch (hdr.type) {
+               case TRACE_CHUNK_FUNCS:
+                       /* Ignored at present */
+                       break;
+
+               case TRACE_CHUNK_CALLS:
+                       if (read_calls(fin, hdr.rec_count))
+                               return 1;
+                       break;
+               }
+       }
+       return 0;
+}
+
+static int read_map_file(const char *fname)
+{
+       FILE *fmap;
+       int err = 0;
+
+       fmap = fopen(fname, "r");
+       if (!fmap) {
+               error("Cannot open map file '%s'\n", fname);
+               return 1;
+       }
+       if (fmap) {
+               err = read_system_map(fmap);
+               fclose(fmap);
+       }
+       return err;
+}
+
+static int read_profile_file(const char *fname)
+{
+       int not_found = INT_MAX;
+       FILE *fprof;
+       int err;
+
+       fprof = fopen(fname, "rb");
+       if (!fprof) {
+               error("Cannot open profile data file '%s'\n",
+                     fname);
+               return 1;
+       } else {
+               err = read_profile(fprof, &not_found);
+               fclose(fprof);
+               if (err)
+                       return err;
+
+               if (not_found) {
+                       warn("%d profile functions could not be found in the map file - are you sure that your profile data and map file correspond?\n",
+                            not_found);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int regex_report_error(regex_t *regex, int err, const char *op,
+                             const char *name)
+{
+       char buf[200];
+
+       regerror(err, regex, buf, sizeof(buf));
+       error("Regex error '%s' in %s '%s'\n", buf, op, name);
+       return -1;
+}
+
+static void check_trace_config_line(struct trace_configline_info *item)
+{
+       struct func_info *func, *end;
+       int err;
+
+       debug("Checking trace config line '%s'\n", item->name);
+       for (func = func_list, end = func + func_count; func < end; func++) {
+               err = regexec(&item->regex, func->name, 0, NULL, 0);
+               debug("   - regex '%s', string '%s': %d\n", item->name,
+                     func->name, err);
+               if (err == REG_NOMATCH)
+                       continue;
+
+               if (err != REG_NOERROR) {
+                       regex_report_error(&item->regex, err, "match",
+                                          item->name);
+                       break;
+               }
+
+               /* It matches, so perform the action */
+               switch (item->type) {
+               case TRACE_LINE_INCLUDE:
+                       info("      include %s at %lx\n", func->name,
+                            text_offset + func->offset);
+                       func->flags |= FUNCF_TRACE;
+                       break;
+
+               case TRACE_LINE_EXCLUDE:
+                       info("      exclude %s at %lx\n", func->name,
+                            text_offset + func->offset);
+                       func->flags &= ~FUNCF_TRACE;
+                       break;
+               }
+       }
+}
+
+static void check_trace_config(void)
+{
+       struct trace_configline_info *line;
+
+       for (line = trace_config_head; line; line = line->next)
+               check_trace_config_line(line);
+}
+
+/**
+ * Check the functions to see if they each have an objsection. If not, then
+ * the linker must have eliminated them.
+ */
+static void check_functions(void)
+{
+       struct func_info *func, *end;
+       unsigned long removed_code_size = 0;
+       int not_found = 0;
+
+       /* Look for missing functions */
+       for (func = func_list, end = func + func_count; func < end; func++) {
+               if (!func->objsection) {
+                       removed_code_size += func->code_size;
+                       not_found++;
+               }
+       }
+
+       /* Figure out what functions we want to trace */
+       check_trace_config();
+
+       warn("%d functions removed by linker, %ld code size\n",
+            not_found, removed_code_size);
+}
+
+static int read_trace_config(FILE *fin)
+{
+       char buff[200];
+       int linenum = 0;
+       struct trace_configline_info **tailp = &trace_config_head;
+
+       while (fgets(buff, sizeof(buff), fin)) {
+               int len = strlen(buff);
+               struct trace_configline_info *line;
+               char *saveptr;
+               char *s, *tok;
+               int err;
+
+               linenum++;
+               if (len && buff[len - 1] == '\n')
+                       buff[len - 1] = '\0';
+
+               /* skip blank lines and comments */
+               for (s = buff; *s == ' ' || *s == '\t'; s++)
+                       ;
+               if (!*s || *s == '#')
+                       continue;
+
+               line = (struct trace_configline_info *)calloc(1,
+                                                             sizeof(*line));
+               if (!line) {
+                       error("Cannot allocate config line\n");
+                       return -1;
+               }
+
+               tok = strtok_r(s, " \t", &saveptr);
+               if (!tok) {
+                       error("Invalid trace config data on line %d\n",
+                             linenum);
+                       return -1;
+               }
+               if (0 == strcmp(tok, "include-func")) {
+                       line->type = TRACE_LINE_INCLUDE;
+               } else if (0 == strcmp(tok, "exclude-func")) {
+                       line->type = TRACE_LINE_EXCLUDE;
+               } else {
+                       error("Unknown command in trace config data line %d\n",
+                             linenum);
+                       return -1;
+               }
+
+               tok = strtok_r(NULL, " \t", &saveptr);
+               if (!tok) {
+                       error("Missing pattern in trace config data line %d\n",
+                             linenum);
+                       return -1;
+               }
+
+               err = regcomp(&line->regex, tok, REG_NOSUB);
+               if (err) {
+                       free(line);
+                       return regex_report_error(&line->regex, err, "compile",
+                                                 tok);
+               }
+
+               /* link this new one to the end of the list */
+               line->name = strdup(tok);
+               line->next = NULL;
+               *tailp = line;
+               tailp = &line->next;
+       }
+
+       if (!feof(fin)) {
+               error("Cannot read from trace config file at position %ld\n",
+                     ftell(fin));
+               return -1;
+       }
+       return 0;
+}
+
+static int read_trace_config_file(const char *fname)
+{
+       FILE *fin;
+       int err;
+
+       fin = fopen(fname, "r");
+       if (!fin) {
+               error("Cannot open trace_config file '%s'\n", fname);
+               return -1;
+       }
+       err = read_trace_config(fin);
+       fclose(fin);
+       return err;
+}
+
+static void out_func(ulong func_offset, int is_caller, const char *suffix)
+{
+       struct func_info *func;
+
+       func = (is_caller ? find_caller_by_offset : find_func_by_offset)
+               (func_offset);
+
+       if (func)
+               printf("%s%s", func->name, suffix);
+       else
+               printf("%lx%s", func_offset, suffix);
+}
+
+/*
+ * # tracer: function
+ * #
+ * #           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+ * #              | |      |          |         |
+ * #           bash-4251  [01] 10152.583854: path_put <-path_walk
+ * #           bash-4251  [01] 10152.583855: dput <-path_put
+ * #           bash-4251  [01] 10152.583855: _atomic_dec_and_lock <-dput
+ */
+static int make_ftrace(void)
+{
+       struct trace_call *call;
+       int missing_count = 0, skip_count = 0;
+       int i;
+
+       printf("# tracer: ftrace\n"
+               "#\n"
+               "#           TASK-PID   CPU#    TIMESTAMP  FUNCTION\n"
+               "#              | |      |          |         |\n");
+       for (i = 0, call = call_list; i < call_count; i++, call++) {
+               struct func_info *func = find_func_by_offset(call->func);
+               ulong time = call->flags & FUNCF_TIMESTAMP_MASK;
+
+               if (TRACE_CALL_TYPE(call) != FUNCF_ENTRY &&
+                   TRACE_CALL_TYPE(call) != FUNCF_EXIT)
+                       continue;
+               if (!func) {
+                       warn("Cannot find function at %lx\n",
+                            text_offset + call->func);
+                       missing_count++;
+                       continue;
+               }
+
+               if (!(func->flags & FUNCF_TRACE)) {
+                       debug("Funcion '%s' is excluded from trace\n",
+                             func->name);
+                       skip_count++;
+                       continue;
+               }
+
+               printf("%16s-%-5d [01] %lu.%06lu: ", "uboot", 1,
+                      time / 1000000, time % 1000000);
+
+               out_func(call->func, 0, " <- ");
+               out_func(call->caller, 1, "\n");
+       }
+       info("ftrace: %d functions not found, %d excluded\n", missing_count,
+            skip_count);
+
+       return 0;
+}
+
+static int prof_tool(int argc, char * const argv[],
+                    const char *prof_fname, const char *map_fname,
+                    const char *trace_config_fname)
+{
+       int err = 0;
+
+       if (read_map_file(map_fname))
+               return -1;
+       if (prof_fname && read_profile_file(prof_fname))
+               return -1;
+       if (trace_config_fname && read_trace_config_file(trace_config_fname))
+               return -1;
+
+       check_functions();
+
+       for (; argc; argc--, argv++) {
+               const char *cmd = *argv;
+
+               if (0 == strcmp(cmd, "dump-ftrace"))
+                       err = make_ftrace();
+               else
+                       warn("Unknown command '%s'\n", cmd);
+       }
+
+       return err;
+}
+
+int main(int argc, char *argv[])
+{
+       const char *map_fname = "System.map";
+       const char *prof_fname = NULL;
+       const char *trace_config_fname = NULL;
+       int opt;
+
+       verbose = 2;
+       while ((opt = getopt(argc, argv, "m:p:t:v:")) != -1) {
+               switch (opt) {
+               case 'm':
+                       map_fname = optarg;
+                       break;
+
+               case 'p':
+                       prof_fname = optarg;
+                       break;
+
+               case 't':
+                       trace_config_fname = optarg;
+                       break;
+
+               case 'v':
+                       verbose = atoi(optarg);
+                       break;
+
+               default:
+                       usage();
+               }
+       }
+       argc -= optind; argv += optind;
+       if (argc < 1)
+               usage();
+
+       debug("Debug enabled\n");
+       return prof_tool(argc, argv, prof_fname, map_fname,
+                        trace_config_fname);
+}