]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge samsung, imx, tegra into u-boot-arm/master
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>
Sat, 22 Dec 2012 10:59:14 +0000 (11:59 +0100)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Sat, 22 Dec 2012 10:59:14 +0000 (11:59 +0100)
This commit merges branches from samsung, imx and tegra
meant to fix merge issues between u-boot/master and
u-boot-arm/master, as well as a few manual merge fixes.

202 files changed:
Makefile
README
arch/arm/cpu/arm1136/cpu.c
arch/arm/cpu/arm1176/s3c64xx/Makefile
arch/arm/cpu/arm1176/s3c64xx/init.c [new file with mode: 0644]
arch/arm/cpu/arm926ejs/mxs/clock.c
arch/arm/cpu/armv7/cache_v7.c
arch/arm/cpu/armv7/exynos/clock.c
arch/arm/cpu/armv7/exynos/pinmux.c
arch/arm/cpu/armv7/s5p-common/Makefile
arch/arm/cpu/armv7/tegra20/Makefile
arch/arm/cpu/armv7/tegra20/display.c [new file with mode: 0644]
arch/arm/cpu/armv7/tegra20/pwm.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/funcmux.c
arch/arm/cpu/tegra20-common/pinmux.c
arch/arm/dts/tegra20.dtsi
arch/arm/include/asm/arch-exynos/clk.h
arch/arm/include/asm/arch-exynos/clock.h
arch/arm/include/asm/arch-exynos/cpu.h
arch/arm/include/asm/arch-exynos/gpio.h
arch/arm/include/asm/arch-exynos/i2s-regs.h [new file with mode: 0644]
arch/arm/include/asm/arch-exynos/periph.h
arch/arm/include/asm/arch-exynos/sound.h [new file with mode: 0644]
arch/arm/include/asm/arch-exynos/spi.h [new file with mode: 0644]
arch/arm/include/asm/arch-mxs/clock.h
arch/arm/include/asm/arch-s5pc1xx/gpio.h
arch/arm/include/asm/arch-tegra20/dc.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra20/display.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra20/pinmux.h
arch/arm/include/asm/arch-tegra20/pwm.h [new file with mode: 0644]
arch/arm/include/asm/system.h
arch/arm/lib/board.c
arch/arm/lib/cache-cp15.c
arch/m68k/include/asm/string.h
arch/m68k/lib/board.c
arch/microblaze/lib/board.c
arch/mips/cpu/mips64/start.S
arch/mips/include/asm/bitops.h
arch/mips/lib/board.c
arch/powerpc/cpu/mpc85xx/mp.c
arch/powerpc/include/asm/string.h
arch/powerpc/lib/board.c
arch/sparc/include/asm/string.h
arch/sparc/lib/board.c
board/Marvell/db64360/db64360.c
board/Marvell/db64460/db64460.c
board/compal/paz00/paz00.c
board/compulab/dts/tegra20-trimslice.dts
board/compulab/trimslice/trimslice.c
board/esd/cpci750/cpci750.c
board/esd/pmc440/cmd_pmc440.c
board/gw8260/gw8260.c
board/nvidia/common/board.c
board/nvidia/dts/tegra20-seaboard.dts
board/nvidia/harmony/harmony.c
board/nvidia/seaboard/seaboard.c
board/prodrive/p3mx/p3mx.c
board/samsung/smdk5250/Makefile
board/samsung/smdk5250/smdk5250.c
board/samsung/smdk5250/spl_boot.c [moved from board/samsung/smdk5250/mmc_boot.c with 66% similarity]
board/samsung/trats/trats.c
board/samsung/universal_c210/Makefile
board/samsung/universal_c210/lowlevel_init.S [deleted file]
board/samsung/universal_c210/universal.c
common/Makefile
common/cmd_bootm.c
common/cmd_gettime.c [new file with mode: 0644]
common/cmd_gpt.c [new file with mode: 0644]
common/cmd_hash.c [new file with mode: 0644]
common/cmd_i2c.c
common/cmd_io.c [new file with mode: 0644]
common/cmd_nvedit.c
common/cmd_read.c [new file with mode: 0644]
common/cmd_sha1sum.c
common/cmd_sound.c [new file with mode: 0644]
common/cmd_spl.c
common/cmd_tpm.c
common/console.c
common/edid.c [new file with mode: 0644]
common/env_attr.c [new file with mode: 0644]
common/env_callback.c [new file with mode: 0644]
common/env_common.c
common/env_dataflash.c
common/env_eeprom.c
common/env_fat.c
common/env_flags.c [new file with mode: 0644]
common/env_flash.c
common/env_mmc.c
common/env_nand.c
common/env_nvram.c
common/env_onenand.c
common/env_sf.c
common/fdt_support.c
common/hash.c [new file with mode: 0644]
common/image.c
common/lcd.c
common/main.c
common/stdio.c
disk/part_efi.c
doc/README.gpt [new file with mode: 0644]
doc/README.silent
doc/device-tree-bindings/pwm/tegra20-pwm.txt [new file with mode: 0644]
doc/device-tree-bindings/video/displaymode.txt [new file with mode: 0644]
doc/device-tree-bindings/video/tegra20-dc.txt [new file with mode: 0644]
drivers/gpio/s5p_gpio.c
drivers/i2c/designware_i2c.c
drivers/i2c/designware_i2c.h
drivers/i2c/mxc_i2c.c
drivers/i2c/mxs_i2c.c
drivers/i2c/omap24xx_i2c.c
drivers/i2c/s3c24x0_i2c.c
drivers/i2c/soft_i2c.c
drivers/input/tegra-kbc.c
drivers/mmc/tegra_mmc.c
drivers/mtd/nand/mxs_nand.c
drivers/net/e1000.c
drivers/net/e1000.h
drivers/net/phy/marvell.c
drivers/net/sh_eth.c
drivers/net/sh_eth.h
drivers/power/pmic/Makefile
drivers/power/pmic/pmic_max77686.c [new file with mode: 0644]
drivers/serial/s3c64xx.c
drivers/serial/serial.c
drivers/sound/Makefile [new file with mode: 0644]
drivers/sound/samsung-i2s.c [new file with mode: 0644]
drivers/sound/sound.c [new file with mode: 0644]
drivers/sound/wm8994.c [new file with mode: 0644]
drivers/sound/wm8994.h [new file with mode: 0644]
drivers/sound/wm8994_registers.h [new file with mode: 0644]
drivers/spi/Makefile
drivers/spi/exynos_spi.c [new file with mode: 0644]
drivers/video/Makefile
drivers/video/exynos_fb.c
drivers/video/ld9040.c [new file with mode: 0644]
drivers/video/tegra.c [new file with mode: 0644]
drivers/watchdog/Makefile
drivers/watchdog/s5p_wdt.c [moved from arch/arm/cpu/armv7/s5p-common/wdt.c with 100% similarity]
include/asm-generic/gpio.h
include/command.h
include/common.h
include/config_cmd_all.h
include/configs/CRAYL1.h
include/configs/GEN860T.h
include/configs/TOP860.h
include/configs/ep8260.h
include/configs/harmony.h
include/configs/m28evk.h
include/configs/mx28evk.h
include/configs/omap3_evm.h
include/configs/palmld.h
include/configs/palmtc.h
include/configs/paz00.h
include/configs/s5pc210_universal.h
include/configs/seaboard.h
include/configs/smdk5250.h
include/configs/tec.h
include/configs/tegra-common-post.h
include/configs/tegra20-common.h
include/configs/trats.h
include/configs/trimslice.h
include/configs/utx8245.h
include/configs/ventana.h
include/configs/whistler.h
include/configs/zipitz2.h
include/edid.h [new file with mode: 0644]
include/env_attr.h [new file with mode: 0644]
include/env_callback.h [new file with mode: 0644]
include/env_default.h
include/env_flags.h [new file with mode: 0644]
include/environment.h
include/exports.h
include/fdtdec.h
include/hash.h [new file with mode: 0644]
include/i2s.h [new file with mode: 0644]
include/image.h
include/lcd.h
include/ld9040.h [new file with mode: 0644]
include/linux/linux_string.h [new file with mode: 0644]
include/linux/string.h
include/part.h
include/part_efi.h [moved from disk/part_efi.h with 66% similarity]
include/power/max77686_pmic.h [new file with mode: 0644]
include/power/max8998_pmic.h
include/search.h
include/sha1.h
include/sha256.h
include/sound.h [new file with mode: 0644]
lib/Makefile
lib/fdtdec.c
lib/hashtable.c
lib/linux_string.c [new file with mode: 0644]
lib/sha1.c
lib/sha256.c
lib/string.c
lib/vsprintf.c
net/link_local.c
net/net.c
net/tftp.c
tools/env/Makefile
tools/env/fw_env.c
tools/fit_image.c

index d3766b901744b3a855c3e2d03a32e108bb810da3..a7b6cd1cbad361ecfa6f71faff567ebae86c449d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@
 VERSION = 2013
 PATCHLEVEL = 01
 SUBLEVEL =
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 ifneq "$(SUBLEVEL)" ""
 U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 else
@@ -316,6 +316,7 @@ LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
 endif
 LIBS-y += drivers/rtc/librtc.o
 LIBS-y += drivers/serial/libserial.o
+LIBS-y += drivers/sound/libsound.o
 LIBS-$(CONFIG_GENERIC_LPC_TPM) += drivers/tpm/libtpm.o
 LIBS-y += drivers/twserial/libtws.o
 LIBS-y += drivers/usb/eth/libusb_eth.o
diff --git a/README b/README
index 5a86ae9c5f9188dd53a8b54ce3eb9554f2485f41..653ef6aa4a55d57686165e56eeec847dcd40b3f1 100644 (file)
--- a/README
+++ b/README
@@ -815,6 +815,8 @@ The following options need to be configured:
                CONFIG_CMD_EDITENV        edit env variable
                CONFIG_CMD_EEPROM       * EEPROM read/write support
                CONFIG_CMD_ELF          * bootelf, bootvx
+               CONFIG_CMD_ENV_CALLBACK * display details about env callbacks
+               CONFIG_CMD_ENV_FLAGS    * display details about env flags
                CONFIG_CMD_EXPORTENV    * export the environment
                CONFIG_CMD_EXT2         * ext2 command support
                CONFIG_CMD_EXT4         * ext4 command support
@@ -824,8 +826,10 @@ 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_GETTIME      * Get time since boot
                CONFIG_CMD_GO           * the 'go' command (exec code)
                CONFIG_CMD_GREPENV      * search environment
+               CONFIG_CMD_HASH         * calculate hash / digest
                CONFIG_CMD_HWFLOW       * RTS/CTS hw flow control
                CONFIG_CMD_I2C          * I2C serial bus support
                CONFIG_CMD_IDE          * IDE harddisk support
@@ -860,6 +864,7 @@ The following options need to be configured:
                CONFIG_CMD_PING         * send ICMP ECHO_REQUEST to network
                                          host
                CONFIG_CMD_PORTIO       * Port I/O
+               CONFIG_CMD_READ         * Read raw data from partition
                CONFIG_CMD_REGINFO      * Register dump
                CONFIG_CMD_RUN            run command in env variable
                CONFIG_CMD_SAVES        * save S record dump
@@ -1481,10 +1486,29 @@ CBFS (Coreboot Filesystem) support
                Normally display is black on white background; define
                CONFIG_SYS_WHITE_ON_BLACK to get it inverted.
 
+               CONFIG_LCD_ALIGNMENT
+
+               Normally the LCD is page-aligned (tyically 4KB). If this is
+               defined then the LCD will be aligned to this value instead.
+               For ARM it is sometimes useful to use MMU_SECTION_SIZE
+               here, since it is cheaper to change data cache settings on
+               a per-section basis.
+
+               CONFIG_CONSOLE_SCROLL_LINES
+
+               When the console need to be scrolled, this is the number of
+               lines to scroll by. It defaults to 1. Increasing this makes
+               the console jump but can help speed up operation when scrolling
+               is slow.
+
                CONFIG_LCD_BMP_RLE8
 
                Support drawing of RLE8-compressed bitmaps on the LCD.
 
+               CONFIG_I2C_EDID
+
+               Enables an 'i2c edid' command which can read EDID
+               information over I2C from an attached LCD display.
 
 - Splash Screen Support: CONFIG_SPLASH_SCREEN
 
@@ -2179,6 +2203,11 @@ CBFS (Coreboot Filesystem) support
                serial# is unaffected by this, i. e. it remains
                read-only.]
 
+               The same can be accomplished in a more flexible way
+               for any variable by configuring the type of access
+               to allow for those variables in the ".flags" variable
+               or define CONFIG_ENV_FLAGS_LIST_STATIC.
+
 - Protected RAM:
                CONFIG_PRAM
 
@@ -2409,6 +2438,23 @@ CBFS (Coreboot Filesystem) support
                A better solution is to properly configure the firewall,
                but sometimes that is not allowed.
 
+- Hashing support:
+               CONFIG_CMD_HASH
+
+               This enables a generic 'hash' command which can produce
+               hashes / digests from a few algorithms (e.g. SHA1, SHA256).
+
+               CONFIG_HASH_VERIFY
+
+               Enable the hash verify command (hash -v). This adds to code
+               size a little.
+
+               CONFIG_SHA1 - support SHA1 hashing
+               CONFIG_SHA256 - support SHA256 hashing
+
+               Note: There is also a sha1sum command, which should perhaps
+               be deprecated in favour of 'hash sha1'.
+
 - Show boot progress:
                CONFIG_SHOW_BOOT_PROGRESS
 
@@ -2943,9 +2989,6 @@ Configuration Settings:
                non page size aligned address and this could cause major
                problems.
 
-- CONFIG_SYS_TFTP_LOADADDR:
-               Default load address for network file downloads
-
 - CONFIG_SYS_LOADS_BAUD_CHANGE:
                Enable temporary baudrate change while serial download
 
@@ -3087,6 +3130,49 @@ Configuration Settings:
        cases. This setting can be used to tune behaviour; see
        lib/hashtable.c for details.
 
+- CONFIG_ENV_FLAGS_LIST_DEFAULT
+- CONFIG_ENV_FLAGS_LIST_STATIC
+       Enable validation of the values given to enviroment variables when
+       calling env set.  Variables can be restricted to only decimal,
+       hexadecimal, or boolean.  If CONFIG_CMD_NET is also defined,
+       the variables can also be restricted to IP address or MAC address.
+
+       The format of the list is:
+               type_attribute = [s|d|x|b|i|m]
+               access_atribute = [a|r|o|c]
+               attributes = type_attribute[access_atribute]
+               entry = variable_name[:attributes]
+               list = entry[,list]
+
+       The type attributes are:
+               s - String (default)
+               d - Decimal
+               x - Hexadecimal
+               b - Boolean ([1yYtT|0nNfF])
+               i - IP address
+               m - MAC address
+
+       The access attributes are:
+               a - Any (default)
+               r - Read-only
+               o - Write-once
+               c - Change-default
+
+       - CONFIG_ENV_FLAGS_LIST_DEFAULT
+               Define this to a list (string) to define the ".flags"
+               envirnoment variable in the default or embedded environment.
+
+       - CONFIG_ENV_FLAGS_LIST_STATIC
+               Define this to a list (string) to define validation that
+               should be done if an entry is not found in the ".flags"
+               environment variable.  To override a setting in the static
+               list, simply add an entry for the same variable name to the
+               ".flags" variable.
+
+- CONFIG_ENV_ACCESS_IGNORE_FORCE
+       If defined, don't allow the -f switch to env set override variable
+       access flags.
+
 The following definitions that deal with the placement and management
 of environment data (variable area); in general, we support the
 following configurations:
@@ -4188,6 +4274,36 @@ Please note that changes to some configuration parameters may take
 only effect after the next boot (yes, that's just like Windoze :-).
 
 
+Callback functions for environment variables:
+---------------------------------------------
+
+For some environment variables, the behavior of u-boot needs to change
+when their values are changed.  This functionailty allows functions to
+be associated with arbitrary variables.  On creation, overwrite, or
+deletion, the callback will provide the opportunity for some side
+effect to happen or for the change to be rejected.
+
+The callbacks are named and associated with a function using the
+U_BOOT_ENV_CALLBACK macro in your board or driver code.
+
+These callbacks are associated with variables in one of two ways.  The
+static list can be added to by defining CONFIG_ENV_CALLBACK_LIST_STATIC
+in the board configuration to a string that defines a list of
+associations.  The list must be in the following format:
+
+       entry = variable_name[:callback_name]
+       list = entry[,list]
+
+If the callback name is not specified, then the callback is deleted.
+Spaces are also allowed anywhere in the list.
+
+Callbacks can also be associated by defining the ".callbacks" variable
+with the same list format above.  Any association in ".callbacks" will
+override any association in the static list. You can define
+CONFIG_ENV_CALLBACK_LIST_DEFAULT to a list (string) to define the
+".callbacks" envirnoment variable in the default or embedded environment.
+
+
 Command Line Parsing:
 =====================
 
index b98e3d9face97006d5588901eecb152b2d799701..32a4c244c5748a231f0c33bb9509998aeba6ccb9 100644 (file)
@@ -141,16 +141,6 @@ void flush_cache(unsigned long start, unsigned long size)
        flush_dcache_range(start, start + size);
 }
 
-void enable_caches(void)
-{
-#ifndef CONFIG_SYS_ICACHE_OFF
-       icache_enable();
-#endif
-#ifndef CONFIG_SYS_DCACHE_OFF
-       dcache_enable();
-#endif
-}
-
 #else /* #ifndef CONFIG_SYS_DCACHE_OFF */
 void invalidate_dcache_all(void)
 {
@@ -172,3 +162,15 @@ void flush_cache(unsigned long start, unsigned long size)
 {
 }
 #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
+
+#if !defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF)
+void enable_caches(void)
+{
+#ifndef CONFIG_SYS_ICACHE_OFF
+       icache_enable();
+#endif
+#ifndef CONFIG_SYS_DCACHE_OFF
+       dcache_enable();
+#endif
+}
+#endif
index 0785b194c50cd4894f6031ba03d98a67af0f9870..266a0739ce8840afafa5f500e36c035f4d665abd 100644 (file)
@@ -31,7 +31,7 @@ LIB   = $(obj)lib$(SOC).o
 SOBJS  = reset.o
 
 COBJS-$(CONFIG_S3C6400)        += cpu_init.o speed.o
-COBJS-y        += timer.o
+COBJS-y        += timer.o init.o
 
 OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
 
diff --git a/arch/arm/cpu/arm1176/s3c64xx/init.c b/arch/arm/cpu/arm1176/s3c64xx/init.c
new file mode 100644 (file)
index 0000000..f113d8e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * (C) Copyright 2012 Ashok Kumar Reddy Kourla
+ * ashokkourla2000@gmail.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.
+ */
+
+#include<common.h>
+
+int arch_cpu_init(void)
+{
+       icache_enable();
+
+       return 0;
+}
index bfea6abeb0714e38dc02351bb32fd6ec7031fef2..4ff19c37efe91ac7247f2b48c0d78097de9fd9e1 100644 (file)
@@ -333,6 +333,8 @@ uint32_t mxc_get_clock(enum mxc_clock clk)
                return mx28_get_sspclk(MXC_SSPCLK2);
        case MXC_SSP3_CLK:
                return mx28_get_sspclk(MXC_SSPCLK3);
+       case MXC_XTAL_CLK:
+               return XTAL_FREQ_KHZ * 1000;
        }
 
        return 0;
index 1b4e808a79c74ff91f955bf24ec2007e27250828..5f6d0396f3af877c5cbc7abf4eef9f16c28a9699 100644 (file)
@@ -297,6 +297,12 @@ void arm_init_before_mmu(void)
        v7_inval_tlb();
 }
 
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+       flush_dcache_range(start, stop);
+       v7_inval_tlb();
+}
+
 /*
  * Flush range from all levels of d-cache/unified-cache used:
  * Affects the range [start, start + size - 1]
@@ -329,6 +335,11 @@ void arm_init_before_mmu(void)
 void  flush_cache(unsigned long start, unsigned long size)
 {
 }
+
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+}
+
 #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
 
 #ifndef CONFIG_SYS_ICACHE_OFF
index 4f3b451be9955cc6e09047b5daedbe39ea2c412f..74599798c435ff84ee4e05117c13936e57351ed7 100644 (file)
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/clk.h>
-
-/* exynos4: return pll clock frequency */
-static unsigned long exynos4_get_pll_clk(int pllreg)
+#include <asm/arch/periph.h>
+
+/* Epll Clock division values to achive different frequency output */
+static struct set_epll_con_val exynos5_epll_div[] = {
+       { 192000000, 0, 48, 3, 1, 0 },
+       { 180000000, 0, 45, 3, 1, 0 },
+       {  73728000, 1, 73, 3, 3, 47710 },
+       {  67737600, 1, 90, 4, 3, 20762 },
+       {  49152000, 0, 49, 3, 3, 9961 },
+       {  45158400, 0, 45, 3, 3, 10381 },
+       { 180633600, 0, 45, 3, 1, 10381 }
+};
+
+/* exynos: return pll clock frequency */
+static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
 {
-       struct exynos4_clock *clk =
-               (struct exynos4_clock *)samsung_get_base_clock();
-       unsigned long r, m, p, s, k = 0, mask, fout;
+       unsigned long m, p, s = 0, mask, fout;
        unsigned int freq;
-
-       switch (pllreg) {
-       case APLL:
-               r = readl(&clk->apll_con0);
-               break;
-       case MPLL:
-               r = readl(&clk->mpll_con0);
-               break;
-       case EPLL:
-               r = readl(&clk->epll_con0);
-               k = readl(&clk->epll_con1);
-               break;
-       case VPLL:
-               r = readl(&clk->vpll_con0);
-               k = readl(&clk->vpll_con1);
-               break;
-       default:
-               printf("Unsupported PLL (%d)\n", pllreg);
-               return 0;
-       }
-
        /*
         * APLL_CON: MIDV [25:16]
         * MPLL_CON: MIDV [25:16]
         * EPLL_CON: MIDV [24:16]
         * VPLL_CON: MIDV [24:16]
+        * BPLL_CON: MIDV [25:16]: Exynos5
         */
-       if (pllreg == APLL || pllreg == MPLL)
+       if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)
                mask = 0x3ff;
        else
                mask = 0x1ff;
@@ -92,13 +82,43 @@ static unsigned long exynos4_get_pll_clk(int pllreg)
        return fout;
 }
 
+/* exynos4: return pll clock frequency */
+static unsigned long exynos4_get_pll_clk(int pllreg)
+{
+       struct exynos4_clock *clk =
+               (struct exynos4_clock *)samsung_get_base_clock();
+       unsigned long r, k = 0;
+
+       switch (pllreg) {
+       case APLL:
+               r = readl(&clk->apll_con0);
+               break;
+       case MPLL:
+               r = readl(&clk->mpll_con0);
+               break;
+       case EPLL:
+               r = readl(&clk->epll_con0);
+               k = readl(&clk->epll_con1);
+               break;
+       case VPLL:
+               r = readl(&clk->vpll_con0);
+               k = readl(&clk->vpll_con1);
+               break;
+       default:
+               printf("Unsupported PLL (%d)\n", pllreg);
+               return 0;
+       }
+
+       return exynos_get_pll_clk(pllreg, r, k);
+}
+
 /* exynos5: return pll clock frequency */
 static unsigned long exynos5_get_pll_clk(int pllreg)
 {
        struct exynos5_clock *clk =
                (struct exynos5_clock *)samsung_get_base_clock();
-       unsigned long r, m, p, s, k = 0, mask, fout;
-       unsigned int freq, pll_div2_sel, fout_sel;
+       unsigned long r, k = 0, fout;
+       unsigned int pll_div2_sel, fout_sel;
 
        switch (pllreg) {
        case APLL:
@@ -123,41 +143,7 @@ static unsigned long exynos5_get_pll_clk(int pllreg)
                return 0;
        }
 
-       /*
-        * APLL_CON: MIDV [25:16]
-        * MPLL_CON: MIDV [25:16]
-        * EPLL_CON: MIDV [24:16]
-        * VPLL_CON: MIDV [24:16]
-        * BPLL_CON: MIDV [25:16]
-        */
-       if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL)
-               mask = 0x3ff;
-       else
-               mask = 0x1ff;
-
-       m = (r >> 16) & mask;
-
-       /* PDIV [13:8] */
-       p = (r >> 8) & 0x3f;
-       /* SDIV [2:0] */
-       s = r & 0x7;
-
-       freq = CONFIG_SYS_CLK_FREQ;
-
-       if (pllreg == EPLL) {
-               k = k & 0xffff;
-               /* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
-               fout = (m + k / 65536) * (freq / (p * (1 << s)));
-       } else if (pllreg == VPLL) {
-               k = k & 0xfff;
-               /* 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 = exynos_get_pll_clk(pllreg, r, k);
 
        /* According to the user manual, in EVT1 MPLL and BPLL always gives
         * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/
@@ -732,6 +718,224 @@ static unsigned long exynos5_get_i2c_clk(void)
        return aclk_66;
 }
 
+int exynos5_set_epll_clk(unsigned long rate)
+{
+       unsigned int epll_con, epll_con_k;
+       unsigned int i;
+       unsigned int lockcnt;
+       unsigned int start;
+       struct exynos5_clock *clk =
+               (struct exynos5_clock *)samsung_get_base_clock();
+
+       epll_con = readl(&clk->epll_con0);
+       epll_con &= ~((EPLL_CON0_LOCK_DET_EN_MASK <<
+                       EPLL_CON0_LOCK_DET_EN_SHIFT) |
+               EPLL_CON0_MDIV_MASK << EPLL_CON0_MDIV_SHIFT |
+               EPLL_CON0_PDIV_MASK << EPLL_CON0_PDIV_SHIFT |
+               EPLL_CON0_SDIV_MASK << EPLL_CON0_SDIV_SHIFT);
+
+       for (i = 0; i < ARRAY_SIZE(exynos5_epll_div); i++) {
+               if (exynos5_epll_div[i].freq_out == rate)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(exynos5_epll_div))
+               return -1;
+
+       epll_con_k = exynos5_epll_div[i].k_dsm << 0;
+       epll_con |= exynos5_epll_div[i].en_lock_det <<
+                               EPLL_CON0_LOCK_DET_EN_SHIFT;
+       epll_con |= exynos5_epll_div[i].m_div << EPLL_CON0_MDIV_SHIFT;
+       epll_con |= exynos5_epll_div[i].p_div << EPLL_CON0_PDIV_SHIFT;
+       epll_con |= exynos5_epll_div[i].s_div << EPLL_CON0_SDIV_SHIFT;
+
+       /*
+        * Required period ( in cycles) to genarate a stable clock output.
+        * The maximum clock time can be up to 3000 * PDIV cycles of PLLs
+        * frequency input (as per spec)
+        */
+       lockcnt = 3000 * exynos5_epll_div[i].p_div;
+
+       writel(lockcnt, &clk->epll_lock);
+       writel(epll_con, &clk->epll_con0);
+       writel(epll_con_k, &clk->epll_con1);
+
+       start = get_timer(0);
+
+        while (!(readl(&clk->epll_con0) &
+                       (0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT))) {
+               if (get_timer(start) > TIMEOUT_EPLL_LOCK) {
+                       debug("%s: Timeout waiting for EPLL lock\n", __func__);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+void exynos5_set_i2s_clk_source(void)
+{
+       struct exynos5_clock *clk =
+               (struct exynos5_clock *)samsung_get_base_clock();
+
+       clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
+                       (CLK_SRC_SCLK_EPLL));
+}
+
+int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
+                                       unsigned int dst_frq)
+{
+       struct exynos5_clock *clk =
+               (struct exynos5_clock *)samsung_get_base_clock();
+       unsigned int div;
+
+       if ((dst_frq == 0) || (src_frq == 0)) {
+               debug("%s: Invalid requency input for prescaler\n", __func__);
+               debug("src frq = %d des frq = %d ", src_frq, dst_frq);
+               return -1;
+       }
+
+       div = (src_frq / dst_frq);
+       if (div > AUDIO_1_RATIO_MASK) {
+               debug("%s: Frequency ratio is out of range\n", __func__);
+               debug("src frq = %d des frq = %d ", src_frq, dst_frq);
+               return -1;
+       }
+       clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
+                               (div & AUDIO_1_RATIO_MASK));
+       return 0;
+}
+
+/**
+ * Linearly searches for the most accurate main and fine stage clock scalars
+ * (divisors) for a specified target frequency and scalar bit sizes by checking
+ * all multiples of main_scalar_bits values. Will always return scalars up to or
+ * slower than target.
+ *
+ * @param main_scalar_bits     Number of main scalar bits, must be > 0 and < 32
+ * @param fine_scalar_bits     Number of fine scalar bits, must be > 0 and < 32
+ * @param input_freq           Clock frequency to be scaled in Hz
+ * @param target_freq          Desired clock frequency in Hz
+ * @param best_fine_scalar     Pointer to store the fine stage divisor
+ *
+ * @return best_main_scalar    Main scalar for desired frequency or -1 if none
+ * found
+ */
+static int clock_calc_best_scalar(unsigned int main_scaler_bits,
+       unsigned int fine_scalar_bits, unsigned int input_rate,
+       unsigned int target_rate, unsigned int *best_fine_scalar)
+{
+       int i;
+       int best_main_scalar = -1;
+       unsigned int best_error = target_rate;
+       const unsigned int cap = (1 << fine_scalar_bits) - 1;
+       const unsigned int loops = 1 << main_scaler_bits;
+
+       debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
+                       target_rate, cap);
+
+       assert(best_fine_scalar != NULL);
+       assert(main_scaler_bits <= fine_scalar_bits);
+
+       *best_fine_scalar = 1;
+
+       if (input_rate == 0 || target_rate == 0)
+               return -1;
+
+       if (target_rate >= input_rate)
+               return 1;
+
+       for (i = 1; i <= loops; i++) {
+               const unsigned int effective_div = max(min(input_rate / i /
+                                                       target_rate, cap), 1);
+               const unsigned int effective_rate = input_rate / i /
+                                                       effective_div;
+               const int error = target_rate - effective_rate;
+
+               debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
+                               effective_rate, error);
+
+               if (error >= 0 && error <= best_error) {
+                       best_error = error;
+                       best_main_scalar = i;
+                       *best_fine_scalar = effective_div;
+               }
+       }
+
+       return best_main_scalar;
+}
+
+static int exynos5_set_spi_clk(enum periph_id periph_id,
+                                       unsigned int rate)
+{
+       struct exynos5_clock *clk =
+               (struct exynos5_clock *)samsung_get_base_clock();
+       int main;
+       unsigned int fine;
+       unsigned shift, pre_shift;
+       unsigned mask = 0xff;
+       u32 *reg;
+
+       main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
+       if (main < 0) {
+               debug("%s: Cannot set clock rate for periph %d",
+                               __func__, periph_id);
+               return -1;
+       }
+       main = main - 1;
+       fine = fine - 1;
+
+       switch (periph_id) {
+       case PERIPH_ID_SPI0:
+               reg = &clk->div_peric1;
+               shift = 0;
+               pre_shift = 8;
+               break;
+       case PERIPH_ID_SPI1:
+               reg = &clk->div_peric1;
+               shift = 16;
+               pre_shift = 24;
+               break;
+       case PERIPH_ID_SPI2:
+               reg = &clk->div_peric2;
+               shift = 0;
+               pre_shift = 8;
+               break;
+       case PERIPH_ID_SPI3:
+               reg = &clk->sclk_div_isp;
+               shift = 0;
+               pre_shift = 4;
+               break;
+       case PERIPH_ID_SPI4:
+               reg = &clk->sclk_div_isp;
+               shift = 12;
+               pre_shift = 16;
+               break;
+       default:
+               debug("%s: Unsupported peripheral ID %d\n", __func__,
+                     periph_id);
+               return -1;
+       }
+       clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
+       clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
+
+       return 0;
+}
+
+static unsigned long exynos4_get_i2c_clk(void)
+{
+       struct exynos4_clock *clk =
+               (struct exynos4_clock *)samsung_get_base_clock();
+       unsigned long sclk, aclk_100;
+       unsigned int ratio;
+
+       sclk = get_pll_clk(APLL);
+
+       ratio = (readl(&clk->div_top)) >> 4;
+       ratio &= 0xf;
+       aclk_100 = sclk / (ratio + 1);
+       return aclk_100;
+}
+
 unsigned long get_pll_clk(int pllreg)
 {
        if (cpu_is_exynos5())
@@ -752,6 +956,8 @@ unsigned long get_i2c_clk(void)
 {
        if (cpu_is_exynos5()) {
                return exynos5_get_i2c_clk();
+       } else if (cpu_is_exynos4()) {
+               return exynos4_get_i2c_clk();
        } else {
                debug("I2C clock is not set for this CPU\n");
                return 0;
@@ -803,3 +1009,34 @@ void set_mipi_clk(void)
        if (cpu_is_exynos4())
                exynos4_set_mipi_clk();
 }
+
+int set_spi_clk(int periph_id, unsigned int rate)
+{
+       if (cpu_is_exynos5())
+               return exynos5_set_spi_clk(periph_id, rate);
+       else
+               return 0;
+}
+
+int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
+{
+
+       if (cpu_is_exynos5())
+               return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq);
+       else
+               return 0;
+}
+
+void set_i2s_clk_source(void)
+{
+       if (cpu_is_exynos5())
+               exynos5_set_i2s_clk_source();
+}
+
+int set_epll_clk(unsigned long rate)
+{
+       if (cpu_is_exynos5())
+               return exynos5_set_epll_clk(rate);
+       else
+               return 0;
+}
index 7776add9db3de7fb3212c43e959d6603534c1c2d..20a4b8414a9f5aff3d6a93844f1f8e2f6045706e 100644 (file)
@@ -112,6 +112,7 @@ static int exynos5_mmc_config(int peripheral, int flags)
                s5p_gpio_set_pull(bank, i, GPIO_PULL_UP);
                s5p_gpio_set_drv(bank, i, GPIO_DRV_4X);
        }
+
        return 0;
 }
 
@@ -230,6 +231,59 @@ static void exynos5_i2c_config(int peripheral, int flags)
        }
 }
 
+static void exynos5_i2s_config(int peripheral)
+{
+       int i;
+       struct exynos5_gpio_part1 *gpio1 =
+               (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1();
+
+       for (i = 0; i < 5; i++)
+               s5p_gpio_cfg_pin(&gpio1->b0, i, GPIO_FUNC(0x02));
+}
+
+void exynos5_spi_config(int peripheral)
+{
+       int cfg = 0, pin = 0, i;
+       struct s5p_gpio_bank *bank = NULL;
+       struct exynos5_gpio_part1 *gpio1 =
+               (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1();
+       struct exynos5_gpio_part2 *gpio2 =
+               (struct exynos5_gpio_part2 *) samsung_get_base_gpio_part2();
+
+       switch (peripheral) {
+       case PERIPH_ID_SPI0:
+               bank = &gpio1->a2;
+               cfg = GPIO_FUNC(0x2);
+               pin = 0;
+               break;
+       case PERIPH_ID_SPI1:
+               bank = &gpio1->a2;
+               cfg = GPIO_FUNC(0x2);
+               pin = 4;
+               break;
+       case PERIPH_ID_SPI2:
+               bank = &gpio1->b1;
+               cfg = GPIO_FUNC(0x5);
+               pin = 1;
+               break;
+       case PERIPH_ID_SPI3:
+               bank = &gpio2->f1;
+               cfg = GPIO_FUNC(0x2);
+               pin = 0;
+               break;
+       case PERIPH_ID_SPI4:
+               for (i = 0; i < 2; i++) {
+                       s5p_gpio_cfg_pin(&gpio2->f0, i + 2, GPIO_FUNC(0x4));
+                       s5p_gpio_cfg_pin(&gpio2->e0, i + 4, GPIO_FUNC(0x4));
+               }
+               break;
+       }
+       if (peripheral != PERIPH_ID_SPI4) {
+               for (i = pin; i < pin + 4; i++)
+                       s5p_gpio_cfg_pin(bank, i, cfg);
+       }
+}
+
 static int exynos5_pinmux_config(int peripheral, int flags)
 {
        switch (peripheral) {
@@ -257,6 +311,78 @@ static int exynos5_pinmux_config(int peripheral, int flags)
        case PERIPH_ID_I2C7:
                exynos5_i2c_config(peripheral, flags);
                break;
+       case PERIPH_ID_I2S1:
+               exynos5_i2s_config(peripheral);
+               break;
+       case PERIPH_ID_SPI0:
+       case PERIPH_ID_SPI1:
+       case PERIPH_ID_SPI2:
+       case PERIPH_ID_SPI3:
+       case PERIPH_ID_SPI4:
+               exynos5_spi_config(peripheral);
+               break;
+       default:
+               debug("%s: invalid peripheral %d", __func__, peripheral);
+               return -1;
+       }
+
+       return 0;
+}
+
+static void exynos4_i2c_config(int peripheral, int flags)
+{
+       struct exynos4_gpio_part1 *gpio1 =
+               (struct exynos4_gpio_part1 *) samsung_get_base_gpio_part1();
+
+       switch (peripheral) {
+       case PERIPH_ID_I2C0:
+               s5p_gpio_cfg_pin(&gpio1->d1, 0, GPIO_FUNC(0x2));
+               s5p_gpio_cfg_pin(&gpio1->d1, 1, GPIO_FUNC(0x2));
+               break;
+       case PERIPH_ID_I2C1:
+               s5p_gpio_cfg_pin(&gpio1->d1, 2, GPIO_FUNC(0x2));
+               s5p_gpio_cfg_pin(&gpio1->d1, 3, GPIO_FUNC(0x2));
+               break;
+       case PERIPH_ID_I2C2:
+               s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3));
+               s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3));
+               break;
+       case PERIPH_ID_I2C3:
+               s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3));
+               s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3));
+               break;
+       case PERIPH_ID_I2C4:
+               s5p_gpio_cfg_pin(&gpio1->b, 2, GPIO_FUNC(0x3));
+               s5p_gpio_cfg_pin(&gpio1->b, 3, GPIO_FUNC(0x3));
+               break;
+       case PERIPH_ID_I2C5:
+               s5p_gpio_cfg_pin(&gpio1->b, 6, GPIO_FUNC(0x3));
+               s5p_gpio_cfg_pin(&gpio1->b, 7, GPIO_FUNC(0x3));
+               break;
+       case PERIPH_ID_I2C6:
+               s5p_gpio_cfg_pin(&gpio1->c1, 3, GPIO_FUNC(0x4));
+               s5p_gpio_cfg_pin(&gpio1->c1, 4, GPIO_FUNC(0x4));
+               break;
+       case PERIPH_ID_I2C7:
+               s5p_gpio_cfg_pin(&gpio1->d0, 2, GPIO_FUNC(0x3));
+               s5p_gpio_cfg_pin(&gpio1->d0, 3, GPIO_FUNC(0x3));
+               break;
+       }
+}
+
+static int exynos4_pinmux_config(int peripheral, int flags)
+{
+       switch (peripheral) {
+       case PERIPH_ID_I2C0:
+       case PERIPH_ID_I2C1:
+       case PERIPH_ID_I2C2:
+       case PERIPH_ID_I2C3:
+       case PERIPH_ID_I2C4:
+       case PERIPH_ID_I2C5:
+       case PERIPH_ID_I2C6:
+       case PERIPH_ID_I2C7:
+               exynos4_i2c_config(peripheral, flags);
+               break;
        default:
                debug("%s: invalid peripheral %d", __func__, peripheral);
                return -1;
@@ -269,6 +395,8 @@ int exynos_pinmux_config(int peripheral, int flags)
 {
        if (cpu_is_exynos5())
                return exynos5_pinmux_config(peripheral, flags);
+       else if (cpu_is_exynos4())
+               return exynos4_pinmux_config(peripheral, flags);
        else {
                debug("pinmux functionality not supported\n");
                return -1;
index f975f3f06c9fbca7f1fe904eae34d5f57f2dde4a..17053995bd61aa21e26ee20b8917528b09400c41 100644 (file)
@@ -28,7 +28,6 @@ LIB   = $(obj)libs5p-common.o
 COBJS-y                += cpu_info.o
 COBJS-y                += timer.o
 COBJS-y                += sromc.o
-COBJS-y                += wdt.o
 COBJS-$(CONFIG_PWM)    += pwm.o
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
index 09a0314d0d9e664b799e4d131871a49b83c3c72e..54ed8c48b40814a6436a7fb0918ea3e1504a02a1 100644 (file)
@@ -28,6 +28,8 @@ include $(TOPDIR)/config.mk
 LIB    =  $(obj)lib$(SOC).o
 
 COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
+COBJS-$(CONFIG_PWM_TEGRA) += pwm.o
+COBJS-$(CONFIG_VIDEO_TEGRA) += display.o
 
 COBJS  := $(COBJS-y)
 SRCS   := $(COBJS:.o=.c)
diff --git a/arch/arm/cpu/armv7/tegra20/display.c b/arch/arm/cpu/armv7/tegra20/display.c
new file mode 100644 (file)
index 0000000..031f9a8
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ *  (C) Copyright 2010
+ *  NVIDIA Corporation <www.nvidia.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 <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch/display.h>
+#include <asm/arch/dc.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/timer.h>
+
+static struct fdt_disp_config config;
+
+static void update_window(struct dc_ctlr *dc, struct disp_ctl_win *win)
+{
+       unsigned h_dda, v_dda;
+       unsigned long val;
+
+       val = readl(&dc->cmd.disp_win_header);
+       val |= WINDOW_A_SELECT;
+       writel(val, &dc->cmd.disp_win_header);
+
+       writel(win->fmt, &dc->win.color_depth);
+
+       clrsetbits_le32(&dc->win.byte_swap, BYTE_SWAP_MASK,
+                       BYTE_SWAP_NOSWAP << BYTE_SWAP_SHIFT);
+
+       val = win->out_x << H_POSITION_SHIFT;
+       val |= win->out_y << V_POSITION_SHIFT;
+       writel(val, &dc->win.pos);
+
+       val = win->out_w << H_SIZE_SHIFT;
+       val |= win->out_h << V_SIZE_SHIFT;
+       writel(val, &dc->win.size);
+
+       val = (win->w * win->bpp / 8) << H_PRESCALED_SIZE_SHIFT;
+       val |= win->h << V_PRESCALED_SIZE_SHIFT;
+       writel(val, &dc->win.prescaled_size);
+
+       writel(0, &dc->win.h_initial_dda);
+       writel(0, &dc->win.v_initial_dda);
+
+       h_dda = (win->w * 0x1000) / max(win->out_w - 1, 1);
+       v_dda = (win->h * 0x1000) / max(win->out_h - 1, 1);
+
+       val = h_dda << H_DDA_INC_SHIFT;
+       val |= v_dda << V_DDA_INC_SHIFT;
+       writel(val, &dc->win.dda_increment);
+
+       writel(win->stride, &dc->win.line_stride);
+       writel(0, &dc->win.buf_stride);
+
+       val = WIN_ENABLE;
+       if (win->bpp < 24)
+               val |= COLOR_EXPAND;
+       writel(val, &dc->win.win_opt);
+
+       writel((unsigned long)win->phys_addr, &dc->winbuf.start_addr);
+       writel(win->x, &dc->winbuf.addr_h_offset);
+       writel(win->y, &dc->winbuf.addr_v_offset);
+
+       writel(0xff00, &dc->win.blend_nokey);
+       writel(0xff00, &dc->win.blend_1win);
+
+       val = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
+       val |= GENERAL_UPDATE | WIN_A_UPDATE;
+       writel(val, &dc->cmd.state_ctrl);
+}
+
+static void write_pair(struct fdt_disp_config *config, int item, u32 *reg)
+{
+       writel(config->horiz_timing[item] |
+                       (config->vert_timing[item] << 16), reg);
+}
+
+static int update_display_mode(struct dc_disp_reg *disp,
+               struct fdt_disp_config *config)
+{
+       unsigned long val;
+       unsigned long rate;
+       unsigned long div;
+
+       writel(0x0, &disp->disp_timing_opt);
+       write_pair(config, FDT_LCD_TIMING_REF_TO_SYNC, &disp->ref_to_sync);
+       write_pair(config, FDT_LCD_TIMING_SYNC_WIDTH, &disp->sync_width);
+       write_pair(config, FDT_LCD_TIMING_BACK_PORCH, &disp->back_porch);
+       write_pair(config, FDT_LCD_TIMING_FRONT_PORCH, &disp->front_porch);
+
+       writel(config->width | (config->height << 16), &disp->disp_active);
+
+       val = DE_SELECT_ACTIVE << DE_SELECT_SHIFT;
+       val |= DE_CONTROL_NORMAL << DE_CONTROL_SHIFT;
+       writel(val, &disp->data_enable_opt);
+
+       val = DATA_FORMAT_DF1P1C << DATA_FORMAT_SHIFT;
+       val |= DATA_ALIGNMENT_MSB << DATA_ALIGNMENT_SHIFT;
+       val |= DATA_ORDER_RED_BLUE << DATA_ORDER_SHIFT;
+       writel(val, &disp->disp_interface_ctrl);
+
+       /*
+        * The pixel clock divider is in 7.1 format (where the bottom bit
+        * represents 0.5). Here we calculate the divider needed to get from
+        * the display clock (typically 600MHz) to the pixel clock. We round
+        * up or down as requried.
+        */
+       rate = clock_get_periph_rate(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL);
+       div = ((rate * 2 + config->pixel_clock / 2) / config->pixel_clock) - 2;
+       debug("Display clock %lu, divider %lu\n", rate, div);
+
+       writel(0x00010001, &disp->shift_clk_opt);
+
+       val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT;
+       val |= div << SHIFT_CLK_DIVIDER_SHIFT;
+       writel(val, &disp->disp_clk_ctrl);
+
+       return 0;
+}
+
+/* Start up the display and turn on power to PWMs */
+static void basic_init(struct dc_cmd_reg *cmd)
+{
+       u32 val;
+
+       writel(0x00000100, &cmd->gen_incr_syncpt_ctrl);
+       writel(0x0000011a, &cmd->cont_syncpt_vsync);
+       writel(0x00000000, &cmd->int_type);
+       writel(0x00000000, &cmd->int_polarity);
+       writel(0x00000000, &cmd->int_mask);
+       writel(0x00000000, &cmd->int_enb);
+
+       val = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE;
+       val |= PW3_ENABLE | PW4_ENABLE | PM0_ENABLE;
+       val |= PM1_ENABLE;
+       writel(val, &cmd->disp_pow_ctrl);
+
+       val = readl(&cmd->disp_cmd);
+       val |= CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT;
+       writel(val, &cmd->disp_cmd);
+}
+
+static void basic_init_timer(struct dc_disp_reg *disp)
+{
+       writel(0x00000020, &disp->mem_high_pri);
+       writel(0x00000001, &disp->mem_high_pri_timer);
+}
+
+static const u32 rgb_enb_tab[PIN_REG_COUNT] = {
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
+
+static const u32 rgb_polarity_tab[PIN_REG_COUNT] = {
+       0x00000000,
+       0x01000000,
+       0x00000000,
+       0x00000000,
+};
+
+static const u32 rgb_data_tab[PIN_REG_COUNT] = {
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
+
+static const u32 rgb_sel_tab[PIN_OUTPUT_SEL_COUNT] = {
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00210222,
+       0x00002200,
+       0x00020000,
+};
+
+static void rgb_enable(struct dc_com_reg *com)
+{
+       int i;
+
+       for (i = 0; i < PIN_REG_COUNT; i++) {
+               writel(rgb_enb_tab[i], &com->pin_output_enb[i]);
+               writel(rgb_polarity_tab[i], &com->pin_output_polarity[i]);
+               writel(rgb_data_tab[i], &com->pin_output_data[i]);
+       }
+
+       for (i = 0; i < PIN_OUTPUT_SEL_COUNT; i++)
+               writel(rgb_sel_tab[i], &com->pin_output_sel[i]);
+}
+
+int setup_window(struct disp_ctl_win *win, struct fdt_disp_config *config)
+{
+       win->x = 0;
+       win->y = 0;
+       win->w = config->width;
+       win->h = config->height;
+       win->out_x = 0;
+       win->out_y = 0;
+       win->out_w = config->width;
+       win->out_h = config->height;
+       win->phys_addr = config->frame_buffer;
+       win->stride = config->width * (1 << config->log2_bpp) / 8;
+       debug("%s: depth = %d\n", __func__, config->log2_bpp);
+       switch (config->log2_bpp) {
+       case 5:
+       case 24:
+               win->fmt = COLOR_DEPTH_R8G8B8A8;
+               win->bpp = 32;
+               break;
+       case 4:
+               win->fmt = COLOR_DEPTH_B5G6R5;
+               win->bpp = 16;
+               break;
+
+       default:
+               debug("Unsupported LCD bit depth");
+               return -1;
+       }
+
+       return 0;
+}
+
+struct fdt_disp_config *tegra_display_get_config(void)
+{
+       return config.valid ? &config : NULL;
+}
+
+static void debug_timing(const char *name, unsigned int timing[])
+{
+#ifdef DEBUG
+       int i;
+
+       debug("%s timing: ", name);
+       for (i = 0; i < FDT_LCD_TIMING_COUNT; i++)
+               debug("%d ", timing[i]);
+       debug("\n");
+#endif
+}
+
+/**
+ * Decode panel information from the fdt, according to a standard binding
+ *
+ * @param blob         fdt blob
+ * @param node         offset of fdt node to read from
+ * @param config       structure to store fdt config into
+ * @return 0 if ok, -ve on error
+ */
+static int tegra_decode_panel(const void *blob, int node,
+                             struct fdt_disp_config *config)
+{
+       int front, back, ref;
+
+       config->width = fdtdec_get_int(blob, node, "xres", -1);
+       config->height = fdtdec_get_int(blob, node, "yres", -1);
+       config->pixel_clock = fdtdec_get_int(blob, node, "clock", 0);
+       if (!config->pixel_clock || config->width == -1 ||
+                       config->height == -1) {
+               debug("%s: Pixel parameters missing\n", __func__);
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       back = fdtdec_get_int(blob, node, "left-margin", -1);
+       front = fdtdec_get_int(blob, node, "right-margin", -1);
+       ref = fdtdec_get_int(blob, node, "hsync-len", -1);
+       if ((back | front | ref) == -1) {
+               debug("%s: Horizontal parameters missing\n", __func__);
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       /* Use a ref-to-sync of 1 always, and take this from the front porch */
+       config->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1;
+       config->horiz_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref;
+       config->horiz_timing[FDT_LCD_TIMING_BACK_PORCH] = back;
+       config->horiz_timing[FDT_LCD_TIMING_FRONT_PORCH] = front -
+               config->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC];
+       debug_timing("horiz", config->horiz_timing);
+
+       back = fdtdec_get_int(blob, node, "upper-margin", -1);
+       front = fdtdec_get_int(blob, node, "lower-margin", -1);
+       ref = fdtdec_get_int(blob, node, "vsync-len", -1);
+       if ((back | front | ref) == -1) {
+               debug("%s: Vertical parameters missing\n", __func__);
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       config->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1;
+       config->vert_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref;
+       config->vert_timing[FDT_LCD_TIMING_BACK_PORCH] = back;
+       config->vert_timing[FDT_LCD_TIMING_FRONT_PORCH] = front -
+               config->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC];
+       debug_timing("vert", config->vert_timing);
+
+       return 0;
+}
+
+/**
+ * Decode the display controller information from the fdt.
+ *
+ * @param blob         fdt blob
+ * @param config       structure to store fdt config into
+ * @return 0 if ok, -ve on error
+ */
+static int tegra_display_decode_config(const void *blob,
+                                      struct fdt_disp_config *config)
+{
+       int node, rgb;
+       int bpp, bit;
+
+       /* TODO: Support multiple controllers */
+       node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_DC);
+       if (node < 0) {
+               debug("%s: Cannot find display controller node in fdt\n",
+                     __func__);
+               return node;
+       }
+       config->disp = (struct disp_ctlr *)fdtdec_get_addr(blob, node, "reg");
+       if (!config->disp) {
+               debug("%s: No display controller address\n", __func__);
+               return -1;
+       }
+
+       rgb = fdt_subnode_offset(blob, node, "rgb");
+
+       config->panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel");
+       if (!config->panel_node < 0) {
+               debug("%s: Cannot find panel information\n", __func__);
+               return -1;
+       }
+
+       if (tegra_decode_panel(blob, config->panel_node, config)) {
+               debug("%s: Failed to decode panel information\n", __func__);
+               return -1;
+       }
+
+       bpp = fdtdec_get_int(blob, config->panel_node, "nvidia,bits-per-pixel",
+                            -1);
+       bit = ffs(bpp) - 1;
+       if (bpp == (1 << bit))
+               config->log2_bpp = bit;
+       else
+               config->log2_bpp = bpp;
+       if (bpp == -1) {
+               debug("%s: Pixel bpp parameters missing\n", __func__);
+               return -FDT_ERR_NOTFOUND;
+       }
+       config->bpp = bpp;
+
+       config->valid = 1;      /* we have a valid configuration */
+
+       return 0;
+}
+
+int tegra_display_probe(const void *blob, void *default_lcd_base)
+{
+       struct disp_ctl_win window;
+       struct dc_ctlr *dc;
+
+       if (tegra_display_decode_config(blob, &config))
+               return -1;
+
+       config.frame_buffer = (u32)default_lcd_base;
+
+       dc = (struct dc_ctlr *)config.disp;
+
+       /*
+        * A header file for clock constants was NAKed upstream.
+        * TODO: Put this into the FDT and fdt_lcd struct when we have clock
+        * support there
+        */
+       clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_PERIPH,
+                              144 * 1000000);
+       clock_start_periph_pll(PERIPH_ID_DISP1, CLOCK_ID_CGENERAL,
+                              600 * 1000000);
+       basic_init(&dc->cmd);
+       basic_init_timer(&dc->disp);
+       rgb_enable(&dc->com);
+
+       if (config.pixel_clock)
+               update_display_mode(&dc->disp, &config);
+
+       if (setup_window(&window, &config))
+               return -1;
+
+       update_window(dc, &window);
+
+       return 0;
+}
diff --git a/arch/arm/cpu/armv7/tegra20/pwm.c b/arch/arm/cpu/armv7/tegra20/pwm.c
new file mode 100644 (file)
index 0000000..b655c5c
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Tegra2 pulse width frequency modulator definitions
+ *
+ * Copyright (c) 2011 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 <fdtdec.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pwm.h>
+
+struct pwm_info {
+       struct pwm_ctlr *pwm;           /* Registers for our pwm controller */
+       int pwm_node;                   /* PWM device tree node */
+} local;
+
+void pwm_enable(unsigned channel, int rate, int pulse_width, int freq_divider)
+{
+       u32 reg;
+
+       assert(channel < PWM_NUM_CHANNELS);
+
+       /* TODO: Can we use clock_adjust_periph_pll_div() here? */
+       clock_start_periph_pll(PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ, rate);
+
+       reg = PWM_ENABLE_MASK;
+       reg |= pulse_width << PWM_WIDTH_SHIFT;
+       reg |= freq_divider << PWM_DIVIDER_SHIFT;
+       writel(reg, &local.pwm[channel].control);
+       debug("%s: channel=%d, rate=%d\n", __func__, channel, rate);
+}
+
+int pwm_request(const void *blob, int node, const char *prop_name)
+{
+       int pwm_node;
+       u32 data[3];
+
+       if (fdtdec_get_int_array(blob, node, prop_name, data,
+                       ARRAY_SIZE(data))) {
+               debug("%s: Cannot decode PWM property '%s'\n", __func__,
+                     prop_name);
+               return -1;
+       }
+
+       pwm_node = fdt_node_offset_by_phandle(blob, data[0]);
+       if (pwm_node != local.pwm_node) {
+               debug("%s: PWM property '%s' phandle %d not recognised"
+                     "- expecting %d\n", __func__, prop_name, data[0],
+                     local.pwm_node);
+               return -1;
+       }
+       if (data[1] >= PWM_NUM_CHANNELS) {
+               debug("%s: PWM property '%s': invalid channel %u\n", __func__,
+                     prop_name, data[1]);
+               return -1;
+       }
+
+       /*
+        * TODO: We could maintain a list of requests, but it might not be
+        * worth it for U-Boot.
+        */
+       return data[1];
+}
+
+int pwm_init(const void *blob)
+{
+       local.pwm_node = fdtdec_next_compatible(blob, 0,
+                                               COMPAT_NVIDIA_TEGRA20_PWM);
+       if (local.pwm_node < 0) {
+               debug("%s: Cannot find device tree node\n", __func__);
+               return -1;
+       }
+
+       local.pwm = (struct pwm_ctlr *)fdtdec_get_addr(blob, local.pwm_node,
+                                                      "reg");
+       if (local.pwm == (struct pwm_ctlr *)FDT_ADDR_T_NONE) {
+               debug("%s: Cannot find pwm reg address\n", __func__);
+               return -1;
+       }
+       debug("Tegra PWM at %p, node %d\n", local.pwm, local.pwm_node);
+
+       return 0;
+}
index 00b8029ebad252be08d43916ba37592ac9f87897..ece7ad9ec954333a9bc9a85769adc97d82b2fe08 100644 (file)
 #include <asm/arch/funcmux.h>
 #include <asm/arch/pinmux.h>
 
+/*
+ * The PINMUX macro is used to set up pinmux tables.
+ */
+#define PINMUX(grp, mux, pupd, tri)                   \
+       {PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
+
+static const struct pingroup_config disp1_default[] = {
+       PINMUX(LDI,   DISPA,      NORMAL,    NORMAL),
+       PINMUX(LHP0,  DISPA,      NORMAL,    NORMAL),
+       PINMUX(LHP1,  DISPA,      NORMAL,    NORMAL),
+       PINMUX(LHP2,  DISPA,      NORMAL,    NORMAL),
+       PINMUX(LHS,   DISPA,      NORMAL,    NORMAL),
+       PINMUX(LM0,   RSVD4,      NORMAL,    NORMAL),
+       PINMUX(LPP,   DISPA,      NORMAL,    NORMAL),
+       PINMUX(LPW0,  DISPA,      NORMAL,    NORMAL),
+       PINMUX(LPW2,  DISPA,      NORMAL,    NORMAL),
+       PINMUX(LSC0,  DISPA,      NORMAL,    NORMAL),
+       PINMUX(LSPI,  DISPA,      NORMAL,    NORMAL),
+       PINMUX(LVP1,  DISPA,      NORMAL,    NORMAL),
+       PINMUX(LVS,   DISPA,      NORMAL,    NORMAL),
+       PINMUX(SLXD,  SPDIF,      NORMAL,    NORMAL),
+};
+
+
 int funcmux_select(enum periph_id id, int config)
 {
        int bad_config = config != FUNCMUX_DEFAULT;
@@ -257,6 +281,19 @@ int funcmux_select(enum periph_id id, int config)
                        break;
                }
                break;
+       case PERIPH_ID_DISP1:
+               if (config == FUNCMUX_DEFAULT) {
+                       int i;
+
+                       for (i = PINGRP_LD0; i <= PINGRP_LD17; i++) {
+                               pinmux_set_func(i, PMUX_FUNC_DISPA);
+                               pinmux_tristate_disable(i);
+                               pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
+                       }
+                       pinmux_config_table(disp1_default,
+                                           ARRAY_SIZE(disp1_default));
+               }
+               break;
 
        default:
                debug("%s: invalid periph_id %d", __func__, id);
index 08b83055dbb74b4e660c3865e4930a04f41049c8..a2a09169e54bc46acbdc0b2bc5f89478a775b2be 100644 (file)
@@ -554,7 +554,7 @@ void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
        writel(reg, muxctl);
 }
 
-void pinmux_config_pingroup(struct pingroup_config *config)
+void pinmux_config_pingroup(const struct pingroup_config *config)
 {
        enum pmux_pingrp pin = config->pingroup;
 
@@ -563,7 +563,7 @@ void pinmux_config_pingroup(struct pingroup_config *config)
        pinmux_set_tristate(pin, config->tristate);
 }
 
-void pinmux_config_table(struct pingroup_config *config, int len)
+void pinmux_config_table(const struct pingroup_config *config, int len)
 {
        int i;
 
index d936b1e7e6a1d32ff1aa8728cf550b6c44d69b5b..636ec2c1fe7da999c29542bee5b0089f5e6081ba 100644 (file)
                compatible = "nvidia,tegra20-nand";
                reg = <0x70008000 0x100>;
        };
+
+       pwm: pwm@7000a000 {
+               compatible = "nvidia,tegra20-pwm";
+               reg = <0x7000a000 0x100>;
+               #pwm-cells = <2>;
+       };
+
+       host1x {
+               compatible = "nvidia,tegra20-host1x", "simple-bus";
+               reg = <0x50000000 0x00024000>;
+               interrupts = <0 65 0x04   /* mpcore syncpt */
+                             0 67 0x04>; /* mpcore general */
+               status = "disabled";
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               ranges = <0x54000000 0x54000000 0x04000000>;
+
+               /* video-encoding/decoding */
+               mpe {
+                       reg = <0x54040000 0x00040000>;
+                       interrupts = <0 68 0x04>;
+                       status = "disabled";
+               };
+
+               /* video input */
+               vi {
+                       reg = <0x54080000 0x00040000>;
+                       interrupts = <0 69 0x04>;
+                       status = "disabled";
+               };
+
+               /* EPP */
+               epp {
+                       reg = <0x540c0000 0x00040000>;
+                       interrupts = <0 70 0x04>;
+                       status = "disabled";
+               };
+
+               /* ISP */
+               isp {
+                       reg = <0x54100000 0x00040000>;
+                       interrupts = <0 71 0x04>;
+                       status = "disabled";
+               };
+
+               /* 2D engine */
+               gr2d {
+                       reg = <0x54140000 0x00040000>;
+                       interrupts = <0 72 0x04>;
+                       status = "disabled";
+               };
+
+               /* 3D engine */
+               gr3d {
+                       reg = <0x54180000 0x00040000>;
+                       status = "disabled";
+               };
+
+               /* display controllers */
+               dc@54200000 {
+                       compatible = "nvidia,tegra20-dc";
+                       reg = <0x54200000 0x00040000>;
+                       interrupts = <0 73 0x04>;
+                       status = "disabled";
+
+                       rgb {
+                               status = "disabled";
+                       };
+               };
+
+               dc@54240000 {
+                       compatible = "nvidia,tegra20-dc";
+                       reg = <0x54240000 0x00040000>;
+                       interrupts = <0 74 0x04>;
+                       status = "disabled";
+
+                       rgb {
+                               status = "disabled";
+                       };
+               };
+
+               /* outputs */
+               hdmi {
+                       compatible = "nvidia,tegra20-hdmi";
+                       reg = <0x54280000 0x00040000>;
+                       interrupts = <0 75 0x04>;
+                       status = "disabled";
+               };
+
+               tvo {
+                       compatible = "nvidia,tegra20-tvo";
+                       reg = <0x542c0000 0x00040000>;
+                       interrupts = <0 76 0x04>;
+                       status = "disabled";
+               };
+
+               dsi {
+                       compatible = "nvidia,tegra20-dsi";
+                       reg = <0x54300000 0x00040000>;
+                       status = "disabled";
+               };
+       };
+
 };
index 552902573ff3536b895a6ad5b9e6a543a4395ee7..cd12323509a844c26c5de4c539b46bc854856d91 100644 (file)
@@ -38,5 +38,9 @@ void set_mmc_clk(int dev_index, unsigned int div);
 unsigned long get_lcd_clk(void);
 void set_lcd_clk(void);
 void set_mipi_clk(void);
+void set_i2s_clk_source(void);
+int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq);
+int set_epll_clk(unsigned long rate);
+int set_spi_clk(int periph_id, unsigned int rate);
 
 #endif
index fce38efbb259892d9511a12b893e41197061792c..ff6781aae45a41e616f81e5d5816f32a66e57ec2 100644 (file)
@@ -595,9 +595,38 @@ struct exynos5_clock {
        unsigned int    pll_div2_sel;
        unsigned char   res123[0xf5d8];
 };
+
+/* structure for epll configuration used in audio clock configuration */
+struct set_epll_con_val {
+       unsigned int freq_out;          /* frequency out */
+       unsigned int en_lock_det;       /* enable lock detect */
+       unsigned int m_div;             /* m divider value */
+       unsigned int p_div;             /* p divider value */
+       unsigned int s_div;             /* s divider value */
+       unsigned int k_dsm;             /* k value of delta signal modulator */
+};
 #endif
 
 #define MPLL_FOUT_SEL_SHIFT    4
+#define EXYNOS5_EPLLCON0_LOCKED_SHIFT  29  /* EPLL Locked bit position*/
+#define TIMEOUT_EPLL_LOCK              1000
+
+#define AUDIO_0_RATIO_MASK             0x0f
+#define AUDIO_1_RATIO_MASK             0x0f
+
+#define AUDIO1_SEL_MASK                        0xf
+#define CLK_SRC_SCLK_EPLL              0x7
+
+/* CON0 bit-fields */
+#define EPLL_CON0_MDIV_MASK            0x1ff
+#define EPLL_CON0_PDIV_MASK            0x3f
+#define EPLL_CON0_SDIV_MASK            0x7
+#define EPLL_CON0_MDIV_SHIFT           16
+#define EPLL_CON0_PDIV_SHIFT           8
+#define EPLL_CON0_SDIV_SHIFT           0
+#define EPLL_CON0_LOCK_DET_EN_SHIFT    28
+#define EPLL_CON0_LOCK_DET_EN_MASK     1
+
 #define MPLL_FOUT_SEL_MASK     0x1
 #define BPLL_FOUT_SEL_SHIFT    0
 #define BPLL_FOUT_SEL_MASK     0x1
index 2cd4ae152624bd5e7a213fd9a66a0768f33a1da1..f06af2eb8592597944aa3b7393396545b9c45541 100644 (file)
@@ -28,6 +28,8 @@
 #define EXYNOS4_ADDR_BASE              0x10000000
 
 /* EXYNOS4 */
+#define EXYNOS4_I2C_SPACING            0x10000
+
 #define EXYNOS4_GPIO_PART3_BASE                0x03860000
 #define EXYNOS4_PRO_ID                 0x10000000
 #define EXYNOS4_SYSREG_BASE            0x10010000
 #define EXYNOS4_UART_BASE              0x13800000
 #define EXYNOS4_I2C_BASE               0x13860000
 #define EXYNOS4_ADC_BASE               0x13910000
+#define EXYNOS4_SPI_BASE               0x13920000
 #define EXYNOS4_PWMTIMER_BASE          0x139D0000
 #define EXYNOS4_MODEM_BASE             0x13A00000
 #define EXYNOS4_USBPHY_CONTROL         0x10020704
+#define EXYNOS4_I2S_BASE               0xE2100000
 
 #define EXYNOS4_GPIO_PART4_BASE                DEVICE_NOT_AVAILABLE
 #define EXYNOS4_DP_BASE                        DEVICE_NOT_AVAILABLE
+#define EXYNOS4_SPI_ISP_BASE           DEVICE_NOT_AVAILABLE
 
 /* EXYNOS5 */
 #define EXYNOS5_I2C_SPACING            0x10000
 #define EXYNOS5_SROMC_BASE             0x12250000
 #define EXYNOS5_UART_BASE              0x12C00000
 #define EXYNOS5_I2C_BASE               0x12C60000
+#define EXYNOS5_SPI_BASE               0x12D20000
+#define EXYNOS5_I2S_BASE               0x12D60000
 #define EXYNOS5_PWMTIMER_BASE          0x12DD0000
+#define EXYNOS5_SPI_ISP_BASE           0x131A0000
 #define EXYNOS5_GPIO_PART2_BASE                0x13400000
 #define EXYNOS5_FIMD_BASE              0x14400000
 #define EXYNOS5_DP_BASE                        0x145B0000
@@ -139,6 +147,15 @@ static inline int cpu_is_##type(void)                      \
 IS_SAMSUNG_TYPE(exynos4, 0x4)
 IS_SAMSUNG_TYPE(exynos5, 0x5)
 
+#define IS_EXYNOS_TYPE(type, id)                       \
+static inline int proid_is_##type(void)                        \
+{                                                      \
+       return s5p_cpu_id == id;                        \
+}
+
+IS_EXYNOS_TYPE(exynos4210, 0x4210)
+IS_EXYNOS_TYPE(exynos5250, 0x5250)
+
 #define SAMSUNG_BASE(device, base)                             \
 static inline unsigned int samsung_get_base_##device(void)     \
 {                                                              \
@@ -156,6 +173,7 @@ SAMSUNG_BASE(dp, DP_BASE)
 SAMSUNG_BASE(sysreg, SYSREG_BASE)
 SAMSUNG_BASE(fimd, FIMD_BASE)
 SAMSUNG_BASE(i2c, I2C_BASE)
+SAMSUNG_BASE(i2s, I2S_BASE)
 SAMSUNG_BASE(mipi_dsim, MIPI_DSIM_BASE)
 SAMSUNG_BASE(gpio_part1, GPIO_PART1_BASE)
 SAMSUNG_BASE(gpio_part2, GPIO_PART2_BASE)
@@ -173,6 +191,8 @@ SAMSUNG_BASE(usb_ehci, USB_HOST_EHCI_BASE)
 SAMSUNG_BASE(usb_otg, USBOTG_BASE)
 SAMSUNG_BASE(watchdog, WATCHDOG_BASE)
 SAMSUNG_BASE(power, POWER_BASE)
+SAMSUNG_BASE(spi, SPI_BASE)
+SAMSUNG_BASE(spi_isp, SPI_ISP_BASE)
 #endif
 
 #endif /* _EXYNOS4_CPU_H */
index 97be4eac052d122573bbd750e0081a2bda611420..4db8fd640e0f78006d040f5abe53c1100585269f 100644 (file)
@@ -207,6 +207,25 @@ static inline unsigned int s5p_gpio_base(int nr)
        return 0;
 }
 
+static inline unsigned int s5p_gpio_part_max(int nr)
+{
+       if (cpu_is_exynos5()) {
+               if (nr < EXYNOS5_GPIO_PART1_MAX)
+                       return 0;
+               else if (nr < EXYNOS5_GPIO_PART2_MAX)
+                       return EXYNOS5_GPIO_PART1_MAX;
+               else
+                       return EXYNOS5_GPIO_PART2_MAX;
+
+       } else if (cpu_is_exynos4()) {
+               if (nr < EXYNOS4_GPIO_PART1_MAX)
+                       return 0;
+               else
+                       return EXYNOS4_GPIO_PART1_MAX;
+       }
+
+       return 0;
+}
 #endif
 
 /* Pin configurations */
diff --git a/arch/arm/include/asm/arch-exynos/i2s-regs.h b/arch/arm/include/asm/arch-exynos/i2s-regs.h
new file mode 100644 (file)
index 0000000..2326ca0
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * R. Chandrasekar <rcsekar@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
+ */
+
+#ifndef __I2S_REGS_H__
+#define __I2S_REGS_H__
+
+#define CON_TXFIFO_FULL                (1 << 8)
+#define CON_TXCH_PAUSE         (1 << 4)
+#define CON_ACTIVE             (1 << 0)
+
+#define MOD_BLCP_SHIFT         24
+#define MOD_BLCP_16BIT         (0 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_8BIT          (1 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_24BIT         (2 << MOD_BLCP_SHIFT)
+#define MOD_BLCP_MASK          (3 << MOD_BLCP_SHIFT)
+
+#define MOD_BLC_16BIT          (0 << 13)
+#define MOD_BLC_8BIT           (1 << 13)
+#define MOD_BLC_24BIT          (2 << 13)
+#define MOD_BLC_MASK           (3 << 13)
+
+#define MOD_SLAVE              (1 << 11)
+#define MOD_MASK               (3 << 8)
+#define MOD_LR_LLOW            (0 << 7)
+#define MOD_LR_RLOW            (1 << 7)
+#define MOD_SDF_IIS            (0 << 5)
+#define MOD_SDF_MSB            (1 << 5)
+#define MOD_SDF_LSB            (2 << 5)
+#define MOD_SDF_MASK           (3 << 5)
+#define MOD_RCLK_256FS         (0 << 3)
+#define MOD_RCLK_512FS         (1 << 3)
+#define MOD_RCLK_384FS         (2 << 3)
+#define MOD_RCLK_768FS         (3 << 3)
+#define MOD_RCLK_MASK          (3 << 3)
+#define MOD_BCLK_32FS          (0 << 1)
+#define MOD_BCLK_48FS          (1 << 1)
+#define MOD_BCLK_16FS          (2 << 1)
+#define MOD_BCLK_24FS          (3 << 1)
+#define MOD_BCLK_MASK          (3 << 1)
+
+#define MOD_CDCLKCON           (1 << 12)
+
+#define FIC_TXFLUSH            (1 << 15)
+#define FIC_RXFLUSH            (1 << 7)
+
+#endif /* __I2S_REGS_H__ */
index b861d7d58425060a3a90d545e42efaa27f82177d..13abd2d703a58d7dacb42dd533aff3b4a6c0a8bf 100644 (file)
@@ -38,11 +38,18 @@ enum periph_id {
        PERIPH_ID_I2C5,
        PERIPH_ID_I2C6,
        PERIPH_ID_I2C7,
+       PERIPH_ID_I2S1,
        PERIPH_ID_SDMMC0,
        PERIPH_ID_SDMMC1,
        PERIPH_ID_SDMMC2,
        PERIPH_ID_SDMMC3,
+       PERIPH_ID_SDMMC4,
        PERIPH_ID_SROMC,
+       PERIPH_ID_SPI0,
+       PERIPH_ID_SPI1,
+       PERIPH_ID_SPI2,
+       PERIPH_ID_SPI3,
+       PERIPH_ID_SPI4,
        PERIPH_ID_UART0,
        PERIPH_ID_UART1,
        PERIPH_ID_UART2,
diff --git a/arch/arm/include/asm/arch-exynos/sound.h b/arch/arm/include/asm/arch-exynos/sound.h
new file mode 100644 (file)
index 0000000..d1bd2f6
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Rajeshwari Shinde <rajeshwari.s@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
+ */
+
+
+#ifndef __SOUND_ARCH_H__
+#define __SOUND_ARCH_H__
+
+/* I2S values */
+#define I2S_PLL_CLK            192000000
+#define I2S_SAMPLING_RATE      48000
+#define I2S_BITS_PER_SAMPLE    16
+#define I2S_CHANNELS           2
+#define I2S_RFS                        256
+#define I2S_BFS                        32
+
+/* I2C values */
+#define AUDIO_I2C_BUS          1
+#define AUDIO_I2C_REG          0x1a
+
+/* Audio Codec */
+#define AUDIO_CODEC            "wm8994"
+
+#define AUDIO_COMPAT           1
+#endif
diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h
new file mode 100644 (file)
index 0000000..7cab1e9
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Padmavathi Venna <padma.v@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_EXYNOS_COMMON_SPI_H_
+#define __ASM_ARCH_EXYNOS_COMMON_SPI_H_
+
+#ifndef __ASSEMBLY__
+
+/* SPI peripheral register map; padded to 64KB */
+struct exynos_spi {
+       unsigned int            ch_cfg;         /* 0x00 */
+       unsigned char           reserved0[4];
+       unsigned int            mode_cfg;       /* 0x08 */
+       unsigned int            cs_reg;         /* 0x0c */
+       unsigned char           reserved1[4];
+       unsigned int            spi_sts;        /* 0x14 */
+       unsigned int            tx_data;        /* 0x18 */
+       unsigned int            rx_data;        /* 0x1c */
+       unsigned int            pkt_cnt;        /* 0x20 */
+       unsigned char           reserved2[4];
+       unsigned char           reserved3[4];
+       unsigned int            fb_clk;         /* 0x2c */
+       unsigned char           padding[0xffd0];
+};
+
+#define EXYNOS_SPI_MAX_FREQ    50000000
+
+#define SPI_TIMEOUT_MS         10
+
+/* SPI_CHCFG */
+#define SPI_CH_HS_EN           (1 << 6)
+#define SPI_CH_RST             (1 << 5)
+#define SPI_SLAVE_MODE         (1 << 4)
+#define SPI_CH_CPOL_L          (1 << 3)
+#define SPI_CH_CPHA_B          (1 << 2)
+#define SPI_RX_CH_ON           (1 << 1)
+#define SPI_TX_CH_ON           (1 << 0)
+
+/* SPI_MODECFG */
+#define SPI_MODE_CH_WIDTH_WORD (0x2 << 29)
+#define SPI_MODE_BUS_WIDTH_WORD        (0x2 << 17)
+
+/* SPI_CSREG */
+#define SPI_SLAVE_SIG_INACT    (1 << 0)
+
+/* SPI_STS */
+#define SPI_ST_TX_DONE         (1 << 25)
+#define SPI_FIFO_LVL_MASK      0x1ff
+#define SPI_TX_LVL_OFFSET      6
+#define SPI_RX_LVL_OFFSET      15
+
+/* Feedback Delay */
+#define SPI_CLK_BYPASS         (0 << 0)
+#define SPI_FB_DELAY_90                (1 << 0)
+#define SPI_FB_DELAY_180       (2 << 0)
+#define SPI_FB_DELAY_270       (3 << 0)
+
+/* Packet Count */
+#define SPI_PACKET_CNT_EN      (1 << 16)
+
+#endif /* __ASSEMBLY__ */
+#endif
index 1700fe39155f7a8fd982a38237f72b2eeb0e2a4e..3d39ef235d611ce17c3f466db61ce667e734bc99 100644 (file)
@@ -35,6 +35,7 @@ enum mxc_clock {
        MXC_SSP1_CLK,
        MXC_SSP2_CLK,
        MXC_SSP3_CLK,
+       MXC_XTAL_CLK,
 };
 
 enum mxs_ioclock {
index 76b901b3977bbc5110f45ad47546400e479775ed..00e498d834b3dea2164cbdfc0dcdec40999fa16f 100644 (file)
@@ -143,7 +143,12 @@ static inline unsigned int s5p_gpio_base(int nr)
        return S5PC110_GPIO_BASE;
 }
 
-#define s5pc110_gpio_get_nr(bank, pin) \
+static inline unsigned int s5p_gpio_part_max(int nr)
+{
+       return 0;
+}
+
+#define s5pc110_gpio_get_nr(bank, pin)   \
        ((((((unsigned int)&(((struct s5pc110_gpio *)S5PC110_GPIO_BASE)->bank))\
            - S5PC110_GPIO_BASE) / sizeof(struct s5p_gpio_bank)) \
          * GPIO_PER_BANK) + pin)
diff --git a/arch/arm/include/asm/arch-tegra20/dc.h b/arch/arm/include/asm/arch-tegra20/dc.h
new file mode 100644 (file)
index 0000000..37934e1
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+ *  (C) Copyright 2010
+ *  NVIDIA Corporation <www.nvidia.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 __ASM_ARCH_TEGRA_DC_H
+#define __ASM_ARCH_TEGRA_DC_H
+
+/* Register definitions for the Tegra display controller */
+
+/* CMD register 0x000 ~ 0x43 */
+struct dc_cmd_reg {
+       /* Address 0x000 ~ 0x002 */
+       uint gen_incr_syncpt;           /* _CMD_GENERAL_INCR_SYNCPT_0 */
+       uint gen_incr_syncpt_ctrl;      /* _CMD_GENERAL_INCR_SYNCPT_CNTRL_0 */
+       uint gen_incr_syncpt_err;       /* _CMD_GENERAL_INCR_SYNCPT_ERROR_0 */
+
+       uint reserved0[5];              /* reserved_0[5] */
+
+       /* Address 0x008 ~ 0x00a */
+       uint win_a_incr_syncpt;         /* _CMD_WIN_A_INCR_SYNCPT_0 */
+       uint win_a_incr_syncpt_ctrl;    /* _CMD_WIN_A_INCR_SYNCPT_CNTRL_0 */
+       uint win_a_incr_syncpt_err;     /* _CMD_WIN_A_INCR_SYNCPT_ERROR_0 */
+
+       uint reserved1[5];              /* reserved_1[5] */
+
+       /* Address 0x010 ~ 0x012 */
+       uint win_b_incr_syncpt;         /* _CMD_WIN_B_INCR_SYNCPT_0 */
+       uint win_b_incr_syncpt_ctrl;    /* _CMD_WIN_B_INCR_SYNCPT_CNTRL_0 */
+       uint win_b_incr_syncpt_err;     /* _CMD_WIN_B_INCR_SYNCPT_ERROR_0 */
+
+       uint reserved2[5];              /* reserved_2[5] */
+
+       /* Address 0x018 ~ 0x01a */
+       uint win_c_incr_syncpt;         /* _CMD_WIN_C_INCR_SYNCPT_0 */
+       uint win_c_incr_syncpt_ctrl;    /* _CMD_WIN_C_INCR_SYNCPT_CNTRL_0 */
+       uint win_c_incr_syncpt_err;     /* _CMD_WIN_C_INCR_SYNCPT_ERROR_0 */
+
+       uint reserved3[13];             /* reserved_3[13] */
+
+       /* Address 0x028 */
+       uint cont_syncpt_vsync;         /* _CMD_CONT_SYNCPT_VSYNC_0 */
+
+       uint reserved4[7];              /* reserved_4[7] */
+
+       /* Address 0x030 ~ 0x033 */
+       uint ctxsw;                     /* _CMD_CTXSW_0 */
+       uint disp_cmd_opt0;             /* _CMD_DISPLAY_COMMAND_OPTION0_0 */
+       uint disp_cmd;                  /* _CMD_DISPLAY_COMMAND_0 */
+       uint sig_raise;                 /* _CMD_SIGNAL_RAISE_0 */
+
+       uint reserved5[2];              /* reserved_0[2] */
+
+       /* Address 0x036 ~ 0x03e */
+       uint disp_pow_ctrl;             /* _CMD_DISPLAY_POWER_CONTROL_0 */
+       uint int_stat;                  /* _CMD_INT_STATUS_0 */
+       uint int_mask;                  /* _CMD_INT_MASK_0 */
+       uint int_enb;                   /* _CMD_INT_ENABLE_0 */
+       uint int_type;                  /* _CMD_INT_TYPE_0 */
+       uint int_polarity;              /* _CMD_INT_POLARITY_0 */
+       uint sig_raise1;                /* _CMD_SIGNAL_RAISE1_0 */
+       uint sig_raise2;                /* _CMD_SIGNAL_RAISE2_0 */
+       uint sig_raise3;                /* _CMD_SIGNAL_RAISE3_0 */
+
+       uint reserved6;                 /* reserved_6 */
+
+       /* Address 0x040 ~ 0x043 */
+       uint state_access;              /* _CMD_STATE_ACCESS_0 */
+       uint state_ctrl;                /* _CMD_STATE_CONTROL_0 */
+       uint disp_win_header;           /* _CMD_DISPLAY_WINDOW_HEADER_0 */
+       uint reg_act_ctrl;              /* _CMD_REG_ACT_CONTROL_0 */
+};
+
+enum {
+       PIN_REG_COUNT           = 4,
+       PIN_OUTPUT_SEL_COUNT    = 7,
+};
+
+/* COM register 0x300 ~ 0x329 */
+struct dc_com_reg {
+       /* Address 0x300 ~ 0x301 */
+       uint crc_ctrl;                  /* _COM_CRC_CONTROL_0 */
+       uint crc_checksum;              /* _COM_CRC_CHECKSUM_0 */
+
+       /* _COM_PIN_OUTPUT_ENABLE0/1/2/3_0: Address 0x302 ~ 0x305 */
+       uint pin_output_enb[PIN_REG_COUNT];
+
+       /* _COM_PIN_OUTPUT_POLARITY0/1/2/3_0: Address 0x306 ~ 0x309 */
+       uint pin_output_polarity[PIN_REG_COUNT];
+
+       /* _COM_PIN_OUTPUT_DATA0/1/2/3_0: Address 0x30a ~ 0x30d */
+       uint pin_output_data[PIN_REG_COUNT];
+
+       /* _COM_PIN_INPUT_ENABLE0_0: Address 0x30e ~ 0x311 */
+       uint pin_input_enb[PIN_REG_COUNT];
+
+       /* Address 0x312 ~ 0x313 */
+       uint pin_input_data0;           /* _COM_PIN_INPUT_DATA0_0 */
+       uint pin_input_data1;           /* _COM_PIN_INPUT_DATA1_0 */
+
+       /* _COM_PIN_OUTPUT_SELECT0/1/2/3/4/5/6_0: Address 0x314 ~ 0x31a */
+       uint pin_output_sel[PIN_OUTPUT_SEL_COUNT];
+
+       /* Address 0x31b ~ 0x329 */
+       uint pin_misc_ctrl;             /* _COM_PIN_MISC_CONTROL_0 */
+       uint pm0_ctrl;                  /* _COM_PM0_CONTROL_0 */
+       uint pm0_duty_cycle;            /* _COM_PM0_DUTY_CYCLE_0 */
+       uint pm1_ctrl;                  /* _COM_PM1_CONTROL_0 */
+       uint pm1_duty_cycle;            /* _COM_PM1_DUTY_CYCLE_0 */
+       uint spi_ctrl;                  /* _COM_SPI_CONTROL_0 */
+       uint spi_start_byte;            /* _COM_SPI_START_BYTE_0 */
+       uint hspi_wr_data_ab;           /* _COM_HSPI_WRITE_DATA_AB_0 */
+       uint hspi_wr_data_cd;           /* _COM_HSPI_WRITE_DATA_CD */
+       uint hspi_cs_dc;                /* _COM_HSPI_CS_DC_0 */
+       uint scratch_reg_a;             /* _COM_SCRATCH_REGISTER_A_0 */
+       uint scratch_reg_b;             /* _COM_SCRATCH_REGISTER_B_0 */
+       uint gpio_ctrl;                 /* _COM_GPIO_CTRL_0 */
+       uint gpio_debounce_cnt;         /* _COM_GPIO_DEBOUNCE_COUNTER_0 */
+       uint crc_checksum_latched;      /* _COM_CRC_CHECKSUM_LATCHED_0 */
+};
+
+enum dc_disp_h_pulse_pos {
+       H_PULSE0_POSITION_A,
+       H_PULSE0_POSITION_B,
+       H_PULSE0_POSITION_C,
+       H_PULSE0_POSITION_D,
+       H_PULSE0_POSITION_COUNT,
+};
+
+struct _disp_h_pulse {
+       /* _DISP_H_PULSE0/1/2_CONTROL_0 */
+       uint h_pulse_ctrl;
+       /* _DISP_H_PULSE0/1/2_POSITION_A/B/C/D_0 */
+       uint h_pulse_pos[H_PULSE0_POSITION_COUNT];
+};
+
+enum dc_disp_v_pulse_pos {
+       V_PULSE0_POSITION_A,
+       V_PULSE0_POSITION_B,
+       V_PULSE0_POSITION_C,
+       V_PULSE0_POSITION_COUNT,
+};
+
+struct _disp_v_pulse0 {
+       /* _DISP_H_PULSE0/1_CONTROL_0 */
+       uint v_pulse_ctrl;
+       /* _DISP_H_PULSE0/1_POSITION_A/B/C_0 */
+       uint v_pulse_pos[V_PULSE0_POSITION_COUNT];
+};
+
+struct _disp_v_pulse2 {
+       /* _DISP_H_PULSE2/3_CONTROL_0 */
+       uint v_pulse_ctrl;
+       /* _DISP_H_PULSE2/3_POSITION_A_0 */
+       uint v_pulse_pos_a;
+};
+
+enum dc_disp_h_pulse_reg {
+       H_PULSE0,
+       H_PULSE1,
+       H_PULSE2,
+       H_PULSE_COUNT,
+};
+
+enum dc_disp_pp_select {
+       PP_SELECT_A,
+       PP_SELECT_B,
+       PP_SELECT_C,
+       PP_SELECT_D,
+       PP_SELECT_COUNT,
+};
+
+/* DISP register 0x400 ~ 0x4c1 */
+struct dc_disp_reg {
+       /* Address 0x400 ~ 0x40a */
+       uint disp_signal_opt0;          /* _DISP_DISP_SIGNAL_OPTIONS0_0 */
+       uint disp_signal_opt1;          /* _DISP_DISP_SIGNAL_OPTIONS1_0 */
+       uint disp_win_opt;              /* _DISP_DISP_WIN_OPTIONS_0 */
+       uint mem_high_pri;              /* _DISP_MEM_HIGH_PRIORITY_0 */
+       uint mem_high_pri_timer;        /* _DISP_MEM_HIGH_PRIORITY_TIMER_0 */
+       uint disp_timing_opt;           /* _DISP_DISP_TIMING_OPTIONS_0 */
+       uint ref_to_sync;               /* _DISP_REF_TO_SYNC_0 */
+       uint sync_width;                /* _DISP_SYNC_WIDTH_0 */
+       uint back_porch;                /* _DISP_BACK_PORCH_0 */
+       uint disp_active;               /* _DISP_DISP_ACTIVE_0 */
+       uint front_porch;               /* _DISP_FRONT_PORCH_0 */
+
+       /* Address 0x40b ~ 0x419: _DISP_H_PULSE0/1/2_  */
+       struct _disp_h_pulse h_pulse[H_PULSE_COUNT];
+
+       /* Address 0x41a ~ 0x421 */
+       struct _disp_v_pulse0 v_pulse0; /* _DISP_V_PULSE0_ */
+       struct _disp_v_pulse0 v_pulse1; /* _DISP_V_PULSE1_ */
+
+       /* Address 0x422 ~ 0x425 */
+       struct _disp_v_pulse2 v_pulse3; /* _DISP_V_PULSE2_ */
+       struct _disp_v_pulse2 v_pulse4; /* _DISP_V_PULSE3_ */
+
+       /* Address 0x426 ~ 0x429 */
+       uint m0_ctrl;                   /* _DISP_M0_CONTROL_0 */
+       uint m1_ctrl;                   /* _DISP_M1_CONTROL_0 */
+       uint di_ctrl;                   /* _DISP_DI_CONTROL_0 */
+       uint pp_ctrl;                   /* _DISP_PP_CONTROL_0 */
+
+       /* Address 0x42a ~ 0x42d: _DISP_PP_SELECT_A/B/C/D_0 */
+       uint pp_select[PP_SELECT_COUNT];
+
+       /* Address 0x42e ~ 0x435 */
+       uint disp_clk_ctrl;             /* _DISP_DISP_CLOCK_CONTROL_0 */
+       uint disp_interface_ctrl;       /* _DISP_DISP_INTERFACE_CONTROL_0 */
+       uint disp_color_ctrl;           /* _DISP_DISP_COLOR_CONTROL_0 */
+       uint shift_clk_opt;             /* _DISP_SHIFT_CLOCK_OPTIONS_0 */
+       uint data_enable_opt;           /* _DISP_DATA_ENABLE_OPTIONS_0 */
+       uint serial_interface_opt;      /* _DISP_SERIAL_INTERFACE_OPTIONS_0 */
+       uint lcd_spi_opt;               /* _DISP_LCD_SPI_OPTIONS_0 */
+       uint border_color;              /* _DISP_BORDER_COLOR_0 */
+
+       /* Address 0x436 ~ 0x439 */
+       uint color_key0_lower;          /* _DISP_COLOR_KEY0_LOWER_0 */
+       uint color_key0_upper;          /* _DISP_COLOR_KEY0_UPPER_0 */
+       uint color_key1_lower;          /* _DISP_COLOR_KEY1_LOWER_0 */
+       uint color_key1_upper;          /* _DISP_COLOR_KEY1_UPPER_0 */
+
+       uint reserved0[2];              /* reserved_0[2] */
+
+       /* Address 0x43c ~ 0x442 */
+       uint cursor_foreground;         /* _DISP_CURSOR_FOREGROUND_0 */
+       uint cursor_background;         /* _DISP_CURSOR_BACKGROUND_0 */
+       uint cursor_start_addr;         /* _DISP_CURSOR_START_ADDR_0 */
+       uint cursor_start_addr_ns;      /* _DISP_CURSOR_START_ADDR_NS_0 */
+       uint cursor_pos;                /* _DISP_CURSOR_POSITION_0 */
+       uint cursor_pos_ns;             /* _DISP_CURSOR_POSITION_NS_0 */
+       uint seq_ctrl;                  /* _DISP_INIT_SEQ_CONTROL_0 */
+
+       /* Address 0x442 ~ 0x446 */
+       uint spi_init_seq_data_a;       /* _DISP_SPI_INIT_SEQ_DATA_A_0 */
+       uint spi_init_seq_data_b;       /* _DISP_SPI_INIT_SEQ_DATA_B_0 */
+       uint spi_init_seq_data_c;       /* _DISP_SPI_INIT_SEQ_DATA_C_0 */
+       uint spi_init_seq_data_d;       /* _DISP_SPI_INIT_SEQ_DATA_D_0 */
+
+       uint reserved1[0x39];           /* reserved1[0x39], */
+
+       /* Address 0x480 ~ 0x484 */
+       uint dc_mccif_fifoctrl;         /* _DISP_DC_MCCIF_FIFOCTRL_0 */
+       uint mccif_disp0a_hyst;         /* _DISP_MCCIF_DISPLAY0A_HYST_0 */
+       uint mccif_disp0b_hyst;         /* _DISP_MCCIF_DISPLAY0B_HYST_0 */
+       uint mccif_disp0c_hyst;         /* _DISP_MCCIF_DISPLAY0C_HYST_0 */
+       uint mccif_disp1b_hyst;         /* _DISP_MCCIF_DISPLAY1B_HYST_0 */
+
+       uint reserved2[0x3b];           /* reserved2[0x3b] */
+
+       /* Address 0x4c0 ~ 0x4c1 */
+       uint dac_crt_ctrl;              /* _DISP_DAC_CRT_CTRL_0 */
+       uint disp_misc_ctrl;            /* _DISP_DISP_MISC_CONTROL_0 */
+};
+
+enum dc_winc_filter_p {
+       WINC_FILTER_COUNT       = 0x10,
+};
+
+/* Window A/B/C register 0x500 ~ 0x628 */
+struct dc_winc_reg {
+
+       /* Address 0x500 */
+       uint color_palette;             /* _WINC_COLOR_PALETTE_0 */
+
+       uint reserved0[0xff];           /* reserved_0[0xff] */
+
+       /* Address 0x600 */
+       uint palette_color_ext;         /* _WINC_PALETTE_COLOR_EXT_0 */
+
+       /* _WINC_H_FILTER_P00~0F_0 */
+       /* Address 0x601 ~ 0x610 */
+       uint h_filter_p[WINC_FILTER_COUNT];
+
+       /* Address 0x611 ~ 0x618 */
+       uint csc_yof;                   /* _WINC_CSC_YOF_0 */
+       uint csc_kyrgb;                 /* _WINC_CSC_KYRGB_0 */
+       uint csc_kur;                   /* _WINC_CSC_KUR_0 */
+       uint csc_kvr;                   /* _WINC_CSC_KVR_0 */
+       uint csc_kug;                   /* _WINC_CSC_KUG_0 */
+       uint csc_kvg;                   /* _WINC_CSC_KVG_0 */
+       uint csc_kub;                   /* _WINC_CSC_KUB_0 */
+       uint csc_kvb;                   /* _WINC_CSC_KVB_0 */
+
+       /* Address 0x619 ~ 0x628: _WINC_V_FILTER_P00~0F_0 */
+       uint v_filter_p[WINC_FILTER_COUNT];
+};
+
+/* WIN A/B/C Register 0x700 ~ 0x714*/
+struct dc_win_reg {
+       /* Address 0x700 ~ 0x714 */
+       uint win_opt;                   /* _WIN_WIN_OPTIONS_0 */
+       uint byte_swap;                 /* _WIN_BYTE_SWAP_0 */
+       uint buffer_ctrl;               /* _WIN_BUFFER_CONTROL_0 */
+       uint color_depth;               /* _WIN_COLOR_DEPTH_0 */
+       uint pos;                       /* _WIN_POSITION_0 */
+       uint size;                      /* _WIN_SIZE_0 */
+       uint prescaled_size;            /* _WIN_PRESCALED_SIZE_0 */
+       uint h_initial_dda;             /* _WIN_H_INITIAL_DDA_0 */
+       uint v_initial_dda;             /* _WIN_V_INITIAL_DDA_0 */
+       uint dda_increment;             /* _WIN_DDA_INCREMENT_0 */
+       uint line_stride;               /* _WIN_LINE_STRIDE_0 */
+       uint buf_stride;                /* _WIN_BUF_STRIDE_0 */
+       uint uv_buf_stride;             /* _WIN_UV_BUF_STRIDE_0 */
+       uint buffer_addr_mode;          /* _WIN_BUFFER_ADDR_MODE_0 */
+       uint dv_ctrl;                   /* _WIN_DV_CONTROL_0 */
+       uint blend_nokey;               /* _WIN_BLEND_NOKEY_0 */
+       uint blend_1win;                /* _WIN_BLEND_1WIN_0 */
+       uint blend_2win_x;              /* _WIN_BLEND_2WIN_X_0 */
+       uint blend_2win_y;              /* _WIN_BLEND_2WIN_Y_0 */
+       uint blend_3win_xy;             /* _WIN_BLEND_3WIN_XY_0 */
+       uint hp_fetch_ctrl;             /* _WIN_HP_FETCH_CONTROL_0 */
+};
+
+/* WINBUF A/B/C Register 0x800 ~ 0x80a */
+struct dc_winbuf_reg {
+       /* Address 0x800 ~ 0x80a */
+       uint start_addr;                /* _WINBUF_START_ADDR_0 */
+       uint start_addr_ns;             /* _WINBUF_START_ADDR_NS_0 */
+       uint start_addr_u;              /* _WINBUF_START_ADDR_U_0 */
+       uint start_addr_u_ns;           /* _WINBUF_START_ADDR_U_NS_0 */
+       uint start_addr_v;              /* _WINBUF_START_ADDR_V_0 */
+       uint start_addr_v_ns;           /* _WINBUF_START_ADDR_V_NS_0 */
+       uint addr_h_offset;             /* _WINBUF_ADDR_H_OFFSET_0 */
+       uint addr_h_offset_ns;          /* _WINBUF_ADDR_H_OFFSET_NS_0 */
+       uint addr_v_offset;             /* _WINBUF_ADDR_V_OFFSET_0 */
+       uint addr_v_offset_ns;          /* _WINBUF_ADDR_V_OFFSET_NS_0 */
+       uint uflow_status;              /* _WINBUF_UFLOW_STATUS_0 */
+};
+
+/* Display Controller (DC_) regs */
+struct dc_ctlr {
+       struct dc_cmd_reg cmd;          /* CMD register 0x000 ~ 0x43 */
+       uint reserved0[0x2bc];
+
+       struct dc_com_reg com;          /* COM register 0x300 ~ 0x329 */
+       uint reserved1[0xd6];
+
+       struct dc_disp_reg disp;        /* DISP register 0x400 ~ 0x4c1 */
+       uint reserved2[0x3e];
+
+       struct dc_winc_reg winc;        /* Window A/B/C 0x500 ~ 0x628 */
+       uint reserved3[0xd7];
+
+       struct dc_win_reg win;          /* WIN A/B/C 0x700 ~ 0x714*/
+       uint reserved4[0xeb];
+
+       struct dc_winbuf_reg winbuf;    /* WINBUF A/B/C 0x800 ~ 0x80a */
+};
+
+#define BIT(pos)       (1U << pos)
+
+/* DC_CMD_DISPLAY_COMMAND 0x032 */
+#define CTRL_MODE_SHIFT                5
+#define CTRL_MODE_MASK         (0x3 << CTRL_MODE_SHIFT)
+enum {
+       CTRL_MODE_STOP,
+       CTRL_MODE_C_DISPLAY,
+       CTRL_MODE_NC_DISPLAY,
+};
+
+/* _WIN_COLOR_DEPTH_0 */
+enum win_color_depth_id {
+       COLOR_DEPTH_P1,
+       COLOR_DEPTH_P2,
+       COLOR_DEPTH_P4,
+       COLOR_DEPTH_P8,
+       COLOR_DEPTH_B4G4R4A4,
+       COLOR_DEPTH_B5G5R5A,
+       COLOR_DEPTH_B5G6R5,
+       COLOR_DEPTH_AB5G5R5,
+       COLOR_DEPTH_B8G8R8A8 = 12,
+       COLOR_DEPTH_R8G8B8A8,
+       COLOR_DEPTH_B6x2G6x2R6x2A8,
+       COLOR_DEPTH_R6x2G6x2B6x2A8,
+       COLOR_DEPTH_YCbCr422,
+       COLOR_DEPTH_YUV422,
+       COLOR_DEPTH_YCbCr420P,
+       COLOR_DEPTH_YUV420P,
+       COLOR_DEPTH_YCbCr422P,
+       COLOR_DEPTH_YUV422P,
+       COLOR_DEPTH_YCbCr422R,
+       COLOR_DEPTH_YUV422R,
+       COLOR_DEPTH_YCbCr422RA,
+       COLOR_DEPTH_YUV422RA,
+};
+
+/* DC_CMD_DISPLAY_POWER_CONTROL 0x036 */
+#define PW0_ENABLE             BIT(0)
+#define PW1_ENABLE             BIT(2)
+#define PW2_ENABLE             BIT(4)
+#define PW3_ENABLE             BIT(6)
+#define PW4_ENABLE             BIT(8)
+#define PM0_ENABLE             BIT(16)
+#define PM1_ENABLE             BIT(18)
+#define SPI_ENABLE             BIT(24)
+#define HSPI_ENABLE            BIT(25)
+
+/* DC_CMD_STATE_CONTROL 0x041 */
+#define GENERAL_ACT_REQ                BIT(0)
+#define WIN_A_ACT_REQ          BIT(1)
+#define WIN_B_ACT_REQ          BIT(2)
+#define WIN_C_ACT_REQ          BIT(3)
+#define GENERAL_UPDATE         BIT(8)
+#define WIN_A_UPDATE           BIT(9)
+#define WIN_B_UPDATE           BIT(10)
+#define WIN_C_UPDATE           BIT(11)
+
+/* DC_CMD_DISPLAY_WINDOW_HEADER 0x042 */
+#define WINDOW_A_SELECT                BIT(4)
+#define WINDOW_B_SELECT                BIT(5)
+#define WINDOW_C_SELECT                BIT(6)
+
+/* DC_DISP_DISP_CLOCK_CONTROL 0x42e */
+#define SHIFT_CLK_DIVIDER_SHIFT        0
+#define SHIFT_CLK_DIVIDER_MASK (0xff << SHIFT_CLK_DIVIDER_SHIFT)
+#define        PIXEL_CLK_DIVIDER_SHIFT 8
+#define        PIXEL_CLK_DIVIDER_MSK   (0xf << PIXEL_CLK_DIVIDER_SHIFT)
+enum {
+       PIXEL_CLK_DIVIDER_PCD1,
+       PIXEL_CLK_DIVIDER_PCD1H,
+       PIXEL_CLK_DIVIDER_PCD2,
+       PIXEL_CLK_DIVIDER_PCD3,
+       PIXEL_CLK_DIVIDER_PCD4,
+       PIXEL_CLK_DIVIDER_PCD6,
+       PIXEL_CLK_DIVIDER_PCD8,
+       PIXEL_CLK_DIVIDER_PCD9,
+       PIXEL_CLK_DIVIDER_PCD12,
+       PIXEL_CLK_DIVIDER_PCD16,
+       PIXEL_CLK_DIVIDER_PCD18,
+       PIXEL_CLK_DIVIDER_PCD24,
+       PIXEL_CLK_DIVIDER_PCD13,
+};
+
+/* DC_DISP_DISP_INTERFACE_CONTROL 0x42f */
+#define DATA_FORMAT_SHIFT      0
+#define DATA_FORMAT_MASK       (0xf << DATA_FORMAT_SHIFT)
+enum {
+       DATA_FORMAT_DF1P1C,
+       DATA_FORMAT_DF1P2C24B,
+       DATA_FORMAT_DF1P2C18B,
+       DATA_FORMAT_DF1P2C16B,
+       DATA_FORMAT_DF2S,
+       DATA_FORMAT_DF3S,
+       DATA_FORMAT_DFSPI,
+       DATA_FORMAT_DF1P3C24B,
+       DATA_FORMAT_DF1P3C18B,
+};
+#define DATA_ALIGNMENT_SHIFT   8
+enum {
+       DATA_ALIGNMENT_MSB,
+       DATA_ALIGNMENT_LSB,
+};
+#define DATA_ORDER_SHIFT       9
+enum {
+       DATA_ORDER_RED_BLUE,
+       DATA_ORDER_BLUE_RED,
+};
+
+/* DC_DISP_DATA_ENABLE_OPTIONS 0x432 */
+#define DE_SELECT_SHIFT                0
+#define DE_SELECT_MASK         (0x3 << DE_SELECT_SHIFT)
+#define DE_SELECT_ACTIVE_BLANK 0x0
+#define DE_SELECT_ACTIVE       0x1
+#define DE_SELECT_ACTIVE_IS    0x2
+#define DE_CONTROL_SHIFT       2
+#define DE_CONTROL_MASK                (0x7 << DE_CONTROL_SHIFT)
+enum {
+       DE_CONTROL_ONECLK,
+       DE_CONTROL_NORMAL,
+       DE_CONTROL_EARLY_EXT,
+       DE_CONTROL_EARLY,
+       DE_CONTROL_ACTIVE_BLANK,
+};
+
+/* DC_WIN_WIN_OPTIONS 0x700 */
+#define H_DIRECTION            BIT(0)
+enum {
+       H_DIRECTION_INCREMENT,
+       H_DIRECTION_DECREMENT,
+};
+#define V_DIRECTION            BIT(2)
+enum {
+       V_DIRECTION_INCREMENT,
+       V_DIRECTION_DECREMENT,
+};
+#define COLOR_EXPAND           BIT(6)
+#define CP_ENABLE              BIT(16)
+#define DV_ENABLE              BIT(20)
+#define WIN_ENABLE             BIT(30)
+
+/* DC_WIN_BYTE_SWAP 0x701 */
+#define BYTE_SWAP_SHIFT                0
+#define BYTE_SWAP_MASK         (3 << BYTE_SWAP_SHIFT)
+enum {
+       BYTE_SWAP_NOSWAP,
+       BYTE_SWAP_SWAP2,
+       BYTE_SWAP_SWAP4,
+       BYTE_SWAP_SWAP4HW
+};
+
+/* DC_WIN_POSITION 0x704 */
+#define H_POSITION_SHIFT       0
+#define H_POSITION_MASK                (0x1FFF << H_POSITION_SHIFT)
+#define V_POSITION_SHIFT       16
+#define V_POSITION_MASK                (0x1FFF << V_POSITION_SHIFT)
+
+/* DC_WIN_SIZE 0x705 */
+#define H_SIZE_SHIFT           0
+#define H_SIZE_MASK            (0x1FFF << H_SIZE_SHIFT)
+#define V_SIZE_SHIFT           16
+#define V_SIZE_MASK            (0x1FFF << V_SIZE_SHIFT)
+
+/* DC_WIN_PRESCALED_SIZE 0x706 */
+#define H_PRESCALED_SIZE_SHIFT 0
+#define H_PRESCALED_SIZE_MASK  (0x7FFF << H_PRESCALED_SIZE)
+#define V_PRESCALED_SIZE_SHIFT 16
+#define V_PRESCALED_SIZE_MASK  (0x1FFF << V_PRESCALED_SIZE)
+
+/* DC_WIN_DDA_INCREMENT 0x709 */
+#define H_DDA_INC_SHIFT                0
+#define H_DDA_INC_MASK         (0xFFFF << H_DDA_INC_SHIFT)
+#define V_DDA_INC_SHIFT                16
+#define V_DDA_INC_MASK         (0xFFFF << V_DDA_INC_SHIFT)
+
+#endif /* __ASM_ARCH_TEGRA_DC_H */
diff --git a/arch/arm/include/asm/arch-tegra20/display.h b/arch/arm/include/asm/arch-tegra20/display.h
new file mode 100644 (file)
index 0000000..c870959
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ *  (C) Copyright 2010
+ *  NVIDIA Corporation <www.nvidia.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 __ASM_ARCH_TEGRA_DISPLAY_H
+#define __ASM_ARCH_TEGRA_DISPLAY_H
+
+#include <asm/arch/dc.h>
+#include <fdtdec.h>
+
+/* This holds information about a window which can be displayed */
+struct disp_ctl_win {
+       enum win_color_depth_id fmt;    /* Color depth/format */
+       unsigned        bpp;            /* Bits per pixel */
+       phys_addr_t     phys_addr;      /* Physical address in memory */
+       unsigned        x;              /* Horizontal address offset (bytes) */
+       unsigned        y;              /* Veritical address offset (bytes) */
+       unsigned        w;              /* Width of source window */
+       unsigned        h;              /* Height of source window */
+       unsigned        stride;         /* Number of bytes per line */
+       unsigned        out_x;          /* Left edge of output window (col) */
+       unsigned        out_y;          /* Top edge of output window (row) */
+       unsigned        out_w;          /* Width of output window in pixels */
+       unsigned        out_h;          /* Height of output window in pixels */
+};
+
+#define FDT_LCD_TIMINGS        4
+
+enum {
+       FDT_LCD_TIMING_REF_TO_SYNC,
+       FDT_LCD_TIMING_SYNC_WIDTH,
+       FDT_LCD_TIMING_BACK_PORCH,
+       FDT_LCD_TIMING_FRONT_PORCH,
+
+       FDT_LCD_TIMING_COUNT,
+};
+
+enum lcd_cache_t {
+       FDT_LCD_CACHE_OFF               = 0,
+       FDT_LCD_CACHE_WRITE_THROUGH     = 1 << 0,
+       FDT_LCD_CACHE_WRITE_BACK        = 1 << 1,
+       FDT_LCD_CACHE_FLUSH             = 1 << 2,
+       FDT_LCD_CACHE_WRITE_BACK_FLUSH  = FDT_LCD_CACHE_WRITE_BACK |
+                                               FDT_LCD_CACHE_FLUSH,
+};
+
+/* Information about the display controller */
+struct fdt_disp_config {
+       int valid;                      /* config is valid */
+       int width;                      /* width in pixels */
+       int height;                     /* height in pixels */
+       int bpp;                        /* number of bits per pixel */
+
+       /*
+        * log2 of number of bpp, in general, unless it bpp is 24 in which
+        * case this field holds 24 also! This is a U-Boot thing.
+        */
+       int log2_bpp;
+       struct disp_ctlr *disp;         /* Display controller to use */
+       fdt_addr_t frame_buffer;        /* Address of frame buffer */
+       unsigned pixel_clock;           /* Pixel clock in Hz */
+       uint horiz_timing[FDT_LCD_TIMING_COUNT];        /* Horizontal timing */
+       uint vert_timing[FDT_LCD_TIMING_COUNT];         /* Vertical timing */
+       int panel_node;                 /* node offset of panel information */
+};
+
+/* Information about the LCD panel */
+struct fdt_panel_config {
+       int pwm_channel;                /* PWM channel to use for backlight */
+       enum lcd_cache_t cache_type;
+
+       struct fdt_gpio_state backlight_en;     /* GPIO for backlight enable */
+       struct fdt_gpio_state lvds_shutdown;    /* GPIO for lvds shutdown */
+       struct fdt_gpio_state backlight_vdd;    /* GPIO for backlight vdd */
+       struct fdt_gpio_state panel_vdd;        /* GPIO for panel vdd */
+       /*
+        * Panel required timings
+        * Timing 1: delay between panel_vdd-rise and data-rise
+        * Timing 2: delay between data-rise and backlight_vdd-rise
+        * Timing 3: delay between backlight_vdd and pwm-rise
+        * Timing 4: delay between pwm-rise and backlight_en-rise
+        */
+       uint panel_timings[FDT_LCD_TIMINGS];
+};
+
+/**
+ * Register a new display based on device tree configuration.
+ *
+ * The frame buffer can be positioned by U-Boot or overriden by the fdt.
+ * You should pass in the U-Boot address here, and check the contents of
+ * struct fdt_disp_config to see what was actually chosen.
+ *
+ * @param blob                 Device tree blob
+ * @param default_lcd_base     Default address of LCD frame buffer
+ * @return 0 if ok, -1 on error (unsupported bits per pixel)
+ */
+int tegra_display_probe(const void *blob, void *default_lcd_base);
+
+/**
+ * Return the current display configuration
+ *
+ * @return pointer to display configuration, or NULL if there is no valid
+ * config
+ */
+struct fdt_disp_config *tegra_display_get_config(void);
+
+/**
+ * Perform the next stage of the LCD init if it is time to do so.
+ *
+ * LCD init can be time-consuming because of the number of delays we need
+ * while waiting for the backlight power supply, etc. This function can
+ * be called at various times during U-Boot operation to advance the
+ * initialization of the LCD to the next stage if sufficient time has
+ * passed since the last stage. It keeps track of what stage it is up to
+ * and the time that it is permitted to move to the next stage.
+ *
+ * The final call should have wait=1 to complete the init.
+ *
+ * @param blob fdt blob containing LCD information
+ * @param wait 1 to wait until all init is complete, and then return
+ *             0 to return immediately, potentially doing nothing if it is
+ *             not yet time for the next init.
+ */
+int tegra_lcd_check_next_stage(const void *blob, int wait);
+
+/**
+ * Set up the maximum LCD size so we can size the frame buffer.
+ *
+ * @param blob fdt blob containing LCD information
+ */
+void tegra_lcd_early_init(const void *blob);
+
+#endif /*__ASM_ARCH_TEGRA_DISPLAY_H*/
index 03fa7ca643b78af7d6e4dc11b1a6a15009391ee5..797e158e68ae49b14cf646a76add1d5098eff8da 100644 (file)
@@ -339,7 +339,7 @@ void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd);
 void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func);
 
 /* Set the complete configuration for a pin group */
-void pinmux_config_pingroup(struct pingroup_config *config);
+void pinmux_config_pingroup(const struct pingroup_config *config);
 
 void pinmux_set_tristate(enum pmux_pingrp pin, int enable);
 
@@ -349,6 +349,6 @@ void pinmux_set_tristate(enum pmux_pingrp pin, int enable);
  * @param config       List of config items
  * @param len          Number of config items in list
  */
-void pinmux_config_table(struct pingroup_config *config, int len);
+void pinmux_config_table(const struct pingroup_config *config, int len);
 
 #endif /* PINMUX_H */
diff --git a/arch/arm/include/asm/arch-tegra20/pwm.h b/arch/arm/include/asm/arch-tegra20/pwm.h
new file mode 100644 (file)
index 0000000..9e03837
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Tegra pulse width frequency modulator definitions
+ *
+ * Copyright (c) 2011 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 __ASM_ARCH_TEGRA_PWM_H
+#define __ASM_ARCH_TEGRA_PWM_H
+
+/* This is a single PWM channel */
+struct pwm_ctlr {
+       uint control;           /* Control register */
+       uint reserved[3];       /* Space space */
+};
+
+#define PWM_NUM_CHANNELS       4
+
+/* PWM_CONTROLLER_PWM_CSR_0/1/2/3_0 */
+#define PWM_ENABLE_SHIFT       31
+#define PWM_ENABLE_MASK        (0x1 << PWM_ENABLE_SHIFT)
+
+#define PWM_WIDTH_SHIFT        16
+#define PWM_WIDTH_MASK         (0x7FFF << PWM_WIDTH_SHIFT)
+
+#define PWM_DIVIDER_SHIFT      0
+#define PWM_DIVIDER_MASK       (0x1FFF << PWM_DIVIDER_SHIFT)
+
+/**
+ * Program the PWM with the given parameters.
+ *
+ * @param channel      PWM channel to update
+ * @param rate         Clock rate to use for PWM
+ * @param pulse_width  high pulse width: 0=always low, 1=1/256 pulse high,
+ *                     n = n/256 pulse high
+ * @param freq_divider frequency divider value (1 to use rate as is)
+ */
+void pwm_enable(unsigned channel, int rate, int pulse_width, int freq_divider);
+
+/**
+ * Request a pwm channel as referenced by a device tree node.
+ *
+ * This channel can then be passed to pwm_enable().
+ *
+ * @param blob         Device tree blob
+ * @param node         Node containing reference to pwm
+ * @param prop_name    Property name of pwm reference
+ * @return channel number, if ok, else -1
+ */
+int pwm_request(const void *blob, int node, const char *prop_name);
+
+/**
+ * Set up the pwm controller, by looking it up in the fdt.
+ *
+ * @return 0 if ok, -1 if the device tree node was not found or invalid.
+ */
+int pwm_init(const void *blob);
+
+#endif /* __ASM_ARCH_TEGRA_PWM_H */
index 2b28a261ba0218692cf0a121807d44429ce026af..78ca8e0a6dc10741469753edff8d73cc96b61d29 100644 (file)
@@ -75,6 +75,37 @@ static inline void set_cr(unsigned int val)
        isb();
 }
 
+/* options available for data cache on each page */
+enum dcache_option {
+       DCACHE_OFF = 0x12,
+       DCACHE_WRITETHROUGH = 0x1a,
+       DCACHE_WRITEBACK = 0x1e,
+};
+
+/* Size of an MMU section */
+enum {
+       MMU_SECTION_SHIFT       = 20,
+       MMU_SECTION_SIZE        = 1 << MMU_SECTION_SHIFT,
+};
+
+/**
+ * Change the cache settings for a region.
+ *
+ * \param start                start address of memory region to change
+ * \param size         size of memory region to change
+ * \param option       dcache option to select
+ */
+void mmu_set_region_dcache_behaviour(u32 start, int size,
+                                    enum dcache_option option);
+
+/**
+ * Register an update to the page tables, and flush the TLB
+ *
+ * \param start                start address of update in page table
+ * \param stop         stop address of update in page table
+ */
+void mmu_page_table_flush(unsigned long start, unsigned long stop);
+
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
index 22a4d9cc0e59d4c877fb8892e2f960b0cad32843..e0cb6353a3feb95fc35734875d53e16b633c3cd7 100644 (file)
@@ -540,15 +540,13 @@ void board_init_r(gd_t *id, ulong dest_addr)
        flash_size = flash_init();
        if (flash_size > 0) {
 # ifdef CONFIG_SYS_FLASH_CHECKSUM
-               char *s = getenv("flashchecksum");
-
                print_size(flash_size, "");
                /*
                 * Compute and print flash CRC if flashchecksum is set to 'y'
                 *
                 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
                 */
-               if (s && (*s == 'y')) {
+               if (getenv_yesno("flashchecksum") == 1) {
                        printf("  CRC: %08X", crc32(0,
                                (const unsigned char *) CONFIG_SYS_FLASH_BASE,
                                flash_size));
index 939de10e039153d0fd1ef29cb962366d5357a355..6edf815d4d7b85f9b6197260b9b870acb01b586f 100644 (file)
 
 #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
 
-#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
-#define CACHE_SETUP    0x1a
-#else
-#define CACHE_SETUP    0x1e
-#endif
-
 DECLARE_GLOBAL_DATA_PTR;
 
 void __arm_init_before_mmu(void)
@@ -50,9 +44,41 @@ static void cp_delay (void)
        asm volatile("" : : : "memory");
 }
 
-static inline void dram_bank_mmu_setup(int bank)
+void set_section_dcache(int section, enum dcache_option option)
 {
        u32 *page_table = (u32 *)gd->tlb_addr;
+       u32 value;
+
+       value = (section << MMU_SECTION_SHIFT) | (3 << 10);
+       value |= option;
+       page_table[section] = value;
+}
+
+void __mmu_page_table_flush(unsigned long start, unsigned long stop)
+{
+       debug("%s: Warning: not implemented\n", __func__);
+}
+
+void mmu_page_table_flush(unsigned long start, unsigned long stop)
+       __attribute__((weak, alias("__mmu_page_table_flush")));
+
+void mmu_set_region_dcache_behaviour(u32 start, int size,
+                                    enum dcache_option option)
+{
+       u32 *page_table = (u32 *)gd->tlb_addr;
+       u32 upto, end;
+
+       end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
+       start = start >> MMU_SECTION_SHIFT;
+       debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
+             option);
+       for (upto = start; upto < end; upto++)
+               set_section_dcache(upto, option);
+       mmu_page_table_flush((u32)&page_table[start], (u32)&page_table[end]);
+}
+
+static inline void dram_bank_mmu_setup(int bank)
+{
        bd_t *bd = gd->bd;
        int     i;
 
@@ -60,21 +86,24 @@ static inline void dram_bank_mmu_setup(int bank)
        for (i = bd->bi_dram[bank].start >> 20;
             i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >> 20;
             i++) {
-               page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP;
+#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
+               set_section_dcache(i, DCACHE_WRITETHROUGH);
+#else
+               set_section_dcache(i, DCACHE_WRITEBACK);
+#endif
        }
 }
 
 /* to activate the MMU we need to set up virtual memory: use 1M areas */
 static inline void mmu_setup(void)
 {
-       u32 *page_table = (u32 *)gd->tlb_addr;
        int i;
        u32 reg;
 
        arm_init_before_mmu();
        /* Set up an identity-mapping for all 4GB, rw for everyone */
        for (i = 0; i < 4096; i++)
-               page_table[i] = i << 20 | (3 << 10) | 0x12;
+               set_section_dcache(i, DCACHE_OFF);
 
        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
                dram_bank_mmu_setup(i);
@@ -82,7 +111,7 @@ static inline void mmu_setup(void)
 
        /* Copy the page table address to cp15 */
        asm volatile("mcr p15, 0, %0, c2, c0, 0"
-                    : : "r" (page_table) : "memory");
+                    : : "r" (gd->tlb_addr) : "memory");
        /* Set the access control to all-supervisor */
        asm volatile("mcr p15, 0, %0, c3, c0, 0"
                     : : "r" (~0));
index e0773a88285a726c45a6f61f7a4f47557e227221..ecf5e56e1078d1fb583ca6421d16d919144bdd91 100644 (file)
@@ -16,7 +16,7 @@
 #endif
 
 extern int strcasecmp(const char *, const char *);
-extern int strncasecmp(const char *, const char *, int);
+extern int strncasecmp(const char *, const char *, __kernel_size_t);
 extern char * strcpy(char *,const char *);
 extern char * strncpy(char *,const char *, __kernel_size_t);
 extern __kernel_size_t strlen(const char *);
index 02d73fda6111045052d5be20e1efe19e833bbc14..794b8679fefe2696bef4a8857f5b6d036b0c8882 100644 (file)
@@ -462,8 +462,7 @@ void board_init_r (gd_t *id, ulong dest_addr)
                 *
                 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
                 */
-               s = getenv ("flashchecksum");
-               if (s && (*s == 'y')) {
+               if (getenv_yesno("flashchecksum") == 1) {
                        printf ("  CRC: %08X",
                                        crc32 (0,
                                                   (const unsigned char *) CONFIG_SYS_FLASH_BASE,
index efd63cd341213de1c81865cb6994b64367af5916..a7c2f7623392fc1fce53dd2eb992a6f74d8620d7 100644 (file)
@@ -74,7 +74,6 @@ void board_init_f(ulong not_used)
        gd = (gd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
        bd = (bd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET \
                                                - GENERATED_BD_INFO_SIZE);
-       __maybe_unused char *s;
 #if defined(CONFIG_CMD_FLASH)
        ulong flash_size = 0;
 #endif
@@ -143,8 +142,7 @@ void board_init_f(ulong not_used)
                 *
                 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
                 */
-               s = getenv ("flashchecksum");
-               if (s && (*s == 'y')) {
+               if (getenv_yesno("flashchecksum") == 1) {
                        printf ("  CRC: %08X",
                                crc32(0, (const u8 *)bd->bi_flashstart,
                                                        flash_size)
index 4112de7026a51f8c854a14414f9d9f920b7ef28f..2b8d531e73b84ef9d2e0280165ed1668dad9d318 100644 (file)
@@ -108,7 +108,12 @@ reset:
        mtc0    t0, CP0_CONFIG
 #endif
 
-       /* Initialize $gp */
+       /*
+        * Initialize $gp, force 8 byte alignment of bal instruction to forbid
+        * the compiler to put nop's between bal and _gp. This is required to
+        * keep _gp and ra aligned to 8 byte.
+        */
+       .align  3
        bal     1f
         nop
        .dword  _gp
index 1c8f4c05003ba83ff0aacf66d94268d901dbf21a..f2dc5335690de97517c58ff5bbaf7627fbc3636f 100644 (file)
@@ -566,7 +566,7 @@ static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
  * @nr: bit number to test
  * @addr: Address to start counting from
  */
-static __inline__ int test_bit(int nr, volatile void *addr)
+static __inline__ int test_bit(int nr, const volatile void *addr)
 {
        return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0;
 }
index 7ddd77832cc5f165111d5b553d212002fa6d1047..d79e1837d9a37c21c07556618a22dc9c60e173e7 100644 (file)
@@ -24,6 +24,7 @@
 #include <common.h>
 #include <command.h>
 #include <malloc.h>
+#include <serial.h>
 #include <stdio_dev.h>
 #include <version.h>
 #include <net.h>
@@ -46,7 +47,7 @@ static char *failed = "*** failed ***\n";
  * mips_io_port_base is the begin of the address space to which x86 style
  * I/O ports are mapped.
  */
-unsigned long mips_io_port_base = -1;
+const unsigned long mips_io_port_base = -1;
 
 int __board_early_init_f(void)
 {
@@ -262,6 +263,8 @@ void board_init_r(gd_t *id, ulong dest_addr)
 
        monitor_flash_len = (ulong)&uboot_end_data - dest_addr;
 
+       serial_initialize();
+
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
        /*
         * We have to relocate the command table manually
index e1197ac9e5e70ac9e843298d9bf5e367a7fdb6be..43d4836303d4f02149ce6f9f117dbf5e395be17b 100644 (file)
@@ -46,10 +46,8 @@ u32 get_my_id()
  */
 int hold_cores_in_reset(int verbose)
 {
-       const char *s = getenv("mp_holdoff");
-
        /* Default to no, overriden by 'y', 'yes', 'Y', 'Yes', or '1' */
-       if (s && (*s == 'y' || *s == 'Y' || *s == '1')) {
+       if (getenv_yesno("mp_holdoff") == 1) {
                if (verbose) {
                        puts("Secondary cores are being held in reset.\n");
                        puts("See 'mp_holdoff' environment variable\n");
index d912a6b5fed2649156f0658a7e8d1a500f8dc550..036805ede2990800288d83ff52bee364d0147b8e 100644 (file)
@@ -14,7 +14,7 @@
 #define __HAVE_ARCH_MEMCHR
 
 extern int strcasecmp(const char *, const char *);
-extern int strncasecmp(const char *, const char *, int);
+extern int strncasecmp(const char *, const char *, __kernel_size_t);
 extern char * strcpy(char *,const char *);
 extern char * strncpy(char *,const char *, __kernel_size_t);
 extern __kernel_size_t strlen(const char *);
index 1b051e11c4928b84ef5ee57b7d65d9fe7244749b..6a7bf4b6c21588a02b3d3bb57ed751948e5ceb73 100644 (file)
@@ -739,16 +739,13 @@ void board_init_r(gd_t *id, ulong dest_addr)
                flash_size = 0;
        } else if ((flash_size = flash_init()) > 0) {
 #ifdef CONFIG_SYS_FLASH_CHECKSUM
-               char *s;
-
                print_size(flash_size, "");
                /*
                 * Compute and print flash CRC if flashchecksum is set to 'y'
                 *
                 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
                 */
-               s = getenv("flashchecksum");
-               if (s && (*s == 'y')) {
+               if (getenv_yesno("flashchecksum") == 1) {
                        printf("  CRC: %08X",
                               crc32(0,
                                     (const unsigned char *)
@@ -841,9 +838,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
         * "i2cfast" into account
         */
        {
-               char *s = getenv("i2cfast");
-
-               if (s && ((*s == 'y') || (*s == 'Y'))) {
+               if (getenv_yesno("i2cfast") == 1) {
                        bd->bi_iic_fast[0] = 1;
                        bd->bi_iic_fast[1] = 1;
                }
index c6bbc203d5dc78f9cae96af7f18f22f89e8acbb8..af6faea234c9229f6c274b057e8911c28fcfb24a 100644 (file)
@@ -40,7 +40,7 @@
 */
 
 extern int strcasecmp(const char *, const char *);
-extern int strncasecmp(const char *, const char *, int);
+extern int strncasecmp(const char *, const char *, __kernel_size_t);
 extern char *strcpy(char *, const char *);
 extern char *strncpy(char *, const char *, __kernel_size_t);
 extern __kernel_size_t strlen(const char *);
index 32d025a34237c89c443314035f58c3f6264105f3..1b5e995b15aaae971624fa0b584084c182f646f0 100644 (file)
@@ -284,8 +284,7 @@ void board_init_f(ulong bootflag)
                 *
                 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
                 */
-               s = getenv("flashchecksum");
-               if (s && (*s == 'y')) {
+               if (getenv_yesno("flashchecksum") == 1) {
                        printf("  CRC: %08lX",
                               crc32(0, (const unsigned char *)CONFIG_SYS_FLASH_BASE,
                                     flash_size)
index 6cae68601d34bffdad9760746b0c97600066fbfa..38769e03c536b27ff3b4d6b89a9b11e2bf909141 100644 (file)
@@ -834,15 +834,11 @@ int mem_test_walk (void)
 /*********************************************************************/
 int testdram (void)
 {
-       char *s;
        int rundata, runaddress, runwalk;
 
-       s = getenv ("testdramdata");
-       rundata = (s && (*s == 'y')) ? 1 : 0;
-       s = getenv ("testdramaddress");
-       runaddress = (s && (*s == 'y')) ? 1 : 0;
-       s = getenv ("testdramwalk");
-       runwalk = (s && (*s == 'y')) ? 1 : 0;
+       rundata = getenv_yesno("testdramdata") == 1;
+       runaddress = getenv_yesno("testdramaddress") == 1;
+       runwalk = getenv_yesno("testdramwalk") == 1;
 
 /*    rundata = 1; */
 /*    runaddress = 0; */
index d4f58b3216adf0bdc1e622a71a769c1b64d01ab8..ddb7ed5551d83ebd8ea39e0afcede78730efea3a 100644 (file)
@@ -834,15 +834,11 @@ int mem_test_walk (void)
 /*********************************************************************/
 int testdram (void)
 {
-       char *s;
        int rundata, runaddress, runwalk;
 
-       s = getenv ("testdramdata");
-       rundata = (s && (*s == 'y')) ? 1 : 0;
-       s = getenv ("testdramaddress");
-       runaddress = (s && (*s == 'y')) ? 1 : 0;
-       s = getenv ("testdramwalk");
-       runwalk = (s && (*s == 'y')) ? 1 : 0;
+       rundata = getenv_yesno("testdramdata") == 1;
+       runaddress = getenv_yesno("testdramaddress") == 1;
+       runwalk = getenv_yesno("testdramwalk") == 1;
 
 /*    rundata = 1; */
 /*    runaddress = 0; */
index 0725989de06938a4f259bb0630f450befd1dda25..6492d4168e1dacc08f13b4320b062c724d23906a 100644 (file)
@@ -61,9 +61,8 @@ int board_mmc_init(bd_t *bd)
        pin_mux_mmc();
 
        debug("board_mmc_init: init eMMC\n");
-       /* init dev 0, eMMC chip, with 4-bit bus */
-       /* The board has an 8-bit bus, but 8-bit doesn't work yet */
-       tegra_mmc_init(0, 4, -1, -1);
+       /* init dev 0, eMMC chip, with 8-bit bus */
+       tegra_mmc_init(0, 8, -1, -1);
 
        debug("board_mmc_init: init SD slot\n");
        /* init dev 3, SD slot, with 4-bit bus */
index db79e7796d09c0351d08207b6a38aef6641633fe..4450674a75989f8f87fe763acdf0535364b3492e 100644 (file)
@@ -8,6 +8,7 @@
 
        aliases {
                usb0 = "/usb@c5008000";
+               usb1 = "/usb@c5000000";
        };
 
        memory {
@@ -48,7 +49,7 @@
        };
 
        usb@c5000000 {
-               status = "disabled";
+               nvidia,vbus-gpio = <&gpio 170 0>; /* PV2 */
        };
 
        usb@c5004000 {
index 9ef66fd86535d45b113aed417b6557c3bcc43626..8f4dd09faa345c08088cbdd79612037bbdb0db33 100644 (file)
 #include <mmc.h>
 #endif
 
+void pin_mux_usb(void)
+{
+       /*
+        * USB1 internal/external mux GPIO, which masquerades as a VBUS GPIO
+        * in the current device tree.
+        */
+       pinmux_tristate_disable(PINGRP_UAC);
+}
 
 void pin_mux_spi(void)
 {
index 98051fb3fbe426985b2a0c2e8ab1a318135d84c5..d7deae4a541c81790a065c6174a9bd12998fea4b 100644 (file)
@@ -953,22 +953,18 @@ int mem_test_walk (void)
 /*********************************************************************/
 int testdram (void)
 {
-       char *s;
        int rundata    = 0;
        int runaddress = 0;
        int runwalk    = 0;
 
 #ifdef CONFIG_SYS_DRAM_TEST_DATA
-       s = getenv ("testdramdata");
-       rundata = (s && (*s == 'y')) ? 1 : 0;
+       rundata = getenv_yesno("testdramdata") == 1;
 #endif
 #ifdef CONFIG_SYS_DRAM_TEST_ADDRESS
-       s = getenv ("testdramaddress");
-       runaddress = (s && (*s == 'y')) ? 1 : 0;
+       runaddress = getenv_yesno("testdramaddress") == 1;
 #endif
 #ifdef CONFIG_SYS_DRAM_TEST_WALK
-       s = getenv ("testdramwalk");
-       runwalk = (s && (*s == 'y')) ? 1 : 0;
+       runwalk = getenv_yesno("testdramwalk") == 1;
 #endif
 
        if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) {
index f1ffb7b540782d0578ca2cf0c4dd6bc5610c5352..e9a78a303ca9797624ea531db49261b759d5ce4c 100644 (file)
@@ -391,7 +391,7 @@ int do_painit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        nextbase -= ((CONFIG_ENV_SIZE + 4096 - 1) & ~(4096 - 1));
        envp = (env_t *)nextbase;
        res = (char *)envp->data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
index 77a1e1d3ac1624779e169ce77984eed5f8d8f1a9..64c54d5e8453554729447567b177f5836d37a0b5 100644 (file)
@@ -544,15 +544,11 @@ int mem_test_walk (void)
 /*********************************************************************/
 int testdram (void)
 {
-       char *s;
        int rundata, runaddress, runwalk;
 
-       s = getenv ("testdramdata");
-       rundata = (s && (*s == 'y')) ? 1 : 0;
-       s = getenv ("testdramaddress");
-       runaddress = (s && (*s == 'y')) ? 1 : 0;
-       s = getenv ("testdramwalk");
-       runwalk = (s && (*s == 'y')) ? 1 : 0;
+       rundata = getenv_yesno("testdramdata") == 1;
+       runaddress = getenv_yesno("testdramaddress") == 1;
+       runwalk = getenv_yesno("testdramwalk") == 1;
 
        if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) {
                printf ("Testing RAM ... ");
index 2c7cd0d401f790d0cba72ed32c89e37891e30ffd..76ec6876e21b51d4ea4da512109c2fc76215cfc1 100644 (file)
 #include <linux/compiler.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/display.h>
 #include <asm/arch/emc.h>
 #include <asm/arch/funcmux.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/pmu.h>
+#include <asm/arch/pwm.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch/usb.h>
 #include <asm/arch-tegra/board.h>
@@ -118,6 +120,13 @@ int board_init(void)
 #ifdef CONFIG_TEGRA_SPI
        pin_mux_spi();
        spi_init();
+#endif
+#ifdef CONFIG_PWM_TEGRA
+       if (pwm_init(gd->fdt_blob))
+               debug("%s: Failed to init pwm\n", __func__);
+#endif
+#ifdef CONFIG_LCD
+       tegra_lcd_check_next_stage(gd->fdt_blob, 0);
 #endif
        /* boot param addr */
        gd->bd->bi_boot_params = (NV_PA_SDRAM_BASE + 0x100);
@@ -144,6 +153,9 @@ int board_init(void)
        pin_mux_usb();
        board_usb_init(gd->fdt_blob);
 #endif
+#ifdef CONFIG_LCD
+       tegra_lcd_check_next_stage(gd->fdt_blob, 0);
+#endif
 
 #ifdef CONFIG_TEGRA_NAND
        pin_mux_nand();
@@ -174,7 +186,19 @@ int board_early_init_f(void)
        /* Initialize periph GPIOs */
        gpio_early_init();
        gpio_early_init_uart();
+#ifdef CONFIG_LCD
+       tegra_lcd_early_init(gd->fdt_blob);
+#endif
 
        return 0;
 }
 #endif /* EARLY_INIT */
+
+int board_late_init(void)
+{
+#ifdef CONFIG_LCD
+       /* Make sure we finish initing the LCD */
+       tegra_lcd_check_next_stage(gd->fdt_blob, 1);
+#endif
+       return 0;
+}
index 25a63a05d0ca3439d505a616926da39973753942..dd98ca48e9f26bcb54e0ba49cf43f4544534745b 100644 (file)
                        compatible = "hynix,hy27uf4g2b", "nand-flash";
                };
        };
+
+       host1x {
+               status = "okay";
+               dc@54200000 {
+                       status = "okay";
+                       rgb {
+                               status = "okay";
+                               nvidia,panel = <&lcd_panel>;
+                       };
+               };
+       };
+
+       lcd_panel: panel {
+               /* Seaboard has 1366x768 */
+               clock = <70600000>;
+               xres = <1366>;
+               yres = <768>;
+               left-margin = <58>;
+               right-margin = <58>;
+               hsync-len = <58>;
+               lower-margin = <4>;
+               upper-margin = <4>;
+               vsync-len = <4>;
+               hsync-active-high;
+               nvidia,bits-per-pixel = <16>;
+               nvidia,pwm = <&pwm 2 0>;
+               nvidia,backlight-enable-gpios = <&gpio 28 0>;   /* PD4 */
+               nvidia,lvds-shutdown-gpios = <&gpio 10 0>;      /* PB2 */
+               nvidia,backlight-vdd-gpios = <&gpio 176 0>;     /* PW0 */
+               nvidia,panel-vdd-gpios = <&gpio 22 0>;          /* PC6 */
+               nvidia,panel-timings = <400 4 203 17 15>;
+       };
+
 };
index c7590ac6cff8292e814a412fe04a5a75dd8e91a9..93430edd3bdb489b75bc7f2ad4ba7ed0573655d8 100644 (file)
@@ -64,9 +64,8 @@ int board_mmc_init(bd_t *bd)
        pin_mux_mmc();
 
        debug("board_mmc_init: init SD slot J26\n");
-       /* init dev 0, SD slot J26, with 4-bit bus */
-       /* The board has an 8-bit bus, but 8-bit doesn't work yet */
-       tegra_mmc_init(0, 4, GPIO_PI6, GPIO_PH2);
+       /* init dev 0, SD slot J26, with 8-bit bus */
+       tegra_mmc_init(0, 8, GPIO_PI6, GPIO_PH2);
 
        debug("board_mmc_init: init SD slot J5\n");
        /* init dev 2, SD slot J5, with 4-bit bus */
index c412c077da02f26022d2b4381e3b306b3e5e1bfe..3e33da0afc37976fe8c04e170a78532c4b962e5a 100644 (file)
@@ -71,9 +71,8 @@ int board_mmc_init(bd_t *bd)
        pin_mux_mmc();
 
        debug("board_mmc_init: init eMMC\n");
-       /* init dev 0, eMMC chip, with 4-bit bus */
-       /* The board has an 8-bit bus, but 8-bit doesn't work yet */
-       tegra_mmc_init(0, 4, -1, -1);
+       /* init dev 0, eMMC chip, with 8-bit bus */
+       tegra_mmc_init(0, 8, -1, -1);
 
        debug("board_mmc_init: init SD slot\n");
        /* init dev 1, SD slot, with 4-bit bus */
index 389affcde0fda0718c954bb638a1eddad1d5f63d..c3fd19169c95beaa8d22a2ac148c4bcbdfa5b4a8 100644 (file)
@@ -768,22 +768,18 @@ int mem_test_walk (void)
 /*********************************************************************/
 int testdram (void)
 {
-       char *s;
        int rundata    = 0;
        int runaddress = 0;
        int runwalk    = 0;
 
 #ifdef CONFIG_SYS_DRAM_TEST_DATA
-       s = getenv ("testdramdata");
-       rundata = (s && (*s == 'y')) ? 1 : 0;
+       rundata = getenv_yesno("testdramdata") == 1;
 #endif
 #ifdef CONFIG_SYS_DRAM_TEST_ADDRESS
-       s = getenv ("testdramaddress");
-       runaddress = (s && (*s == 'y')) ? 1 : 0;
+       runaddress = getenv_yesno("testdramaddress") == 1;
 #endif
 #ifdef CONFIG_SYS_DRAM_TEST_WALK
-       s = getenv ("testdramwalk");
-       runwalk = (s && (*s == 'y')) ? 1 : 0;
+       runwalk = getenv_yesno("testdramwalk") == 1;
 #endif
 
        if ((rundata == 1) || (runaddress == 1) || (runwalk == 1))
index 1474fa8a15a7b3825c356a843f5626a1851765e2..47c6a5a46b51b805bddedd5f06ff9de33bd61e47 100644 (file)
@@ -36,7 +36,7 @@ COBJS += smdk5250.o
 endif
 
 ifdef CONFIG_SPL_BUILD
-COBJS  += mmc_boot.o
+COBJS  += spl_boot.o
 endif
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS:.o=.c)
index a5816e445c80308f9843728c6ea64428088d03fb..9c926d6ecf2e9ae6f1db1bc390633b6cf3cb14d0 100644 (file)
 #include <asm/io.h>
 #include <i2c.h>
 #include <netdev.h>
+#include <spi.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/sromc.h>
+#include <power/pmic.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -63,6 +65,9 @@ static int smc9115_pre_init(void)
 int board_init(void)
 {
        gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
+#ifdef CONFIG_EXYNOS_SPI
+       spi_init();
+#endif
        return 0;
 }
 
@@ -79,6 +84,16 @@ int dram_init(void)
        return 0;
 }
 
+#if defined(CONFIG_POWER)
+int power_init_board(void)
+{
+       if (pmic_init(I2C_PMIC))
+               return -1;
+       else
+               return 0;
+}
+#endif
+
 void dram_init_banksize(void)
 {
        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
similarity index 66%
rename from board/samsung/smdk5250/mmc_boot.c
rename to board/samsung/smdk5250/spl_boot.c
index 449a919d5f223a632d3c1b00b78fe99bbdb421f9..d8f3c1e184881f8c1a2a32a509a3269ecc61b169 100644 (file)
 #include<common.h>
 #include<config.h>
 
+enum boot_mode {
+       BOOT_MODE_MMC = 4,
+       BOOT_MODE_SERIAL = 20,
+       /* 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);
+
 /*
 * Copy U-boot from mmc to RAM:
 * COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains
 */
 void copy_uboot_to_ram(void)
 {
-       u32 (*copy_bl2)(u32, u32, u32) = (void *) *(u32 *)COPY_BL2_FNPTR_ADDR;
+       spi_copy_func_t spi_copy;
+       enum boot_mode bootmode;
+       u32 (*copy_bl2)(u32, u32, u32);
+
+       bootmode = readl(EXYNOS5_POWER_BASE) & OM_STAT;
 
-       copy_bl2(BL2_START_OFFSET, BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE);
+       switch (bootmode) {
+       case BOOT_MODE_SERIAL:
+               spi_copy = *(spi_copy_func_t *)EXYNOS_COPY_SPI_FNPTR_ADDR;
+               spi_copy(SPI_FLASH_UBOOT_POS, CONFIG_BL2_SIZE,
+                                               CONFIG_SYS_TEXT_BASE);
+               break;
+       case BOOT_MODE_MMC:
+               copy_bl2 = (void *) *(u32 *)COPY_BL2_FNPTR_ADDR;
+               copy_bl2(BL2_START_OFFSET, BL2_SIZE_BLOC_COUNT,
+                                               CONFIG_SYS_TEXT_BASE);
+               break;
+       default:
+               break;
+       }
 }
 
 void board_init_f(unsigned long bootflag)
index e540190984740da822678724a71ffed0764b1cb2..472402942442da0c16e2d530e33c89e36fed7927 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/pinmux.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/mipi_dsim.h>
@@ -361,7 +362,9 @@ int power_init_board(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_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);
 
        return 0;
 }
@@ -372,6 +375,10 @@ void dram_init_banksize(void)
        gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
        gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
        gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
+       gd->bd->bi_dram[2].start = PHYS_SDRAM_3;
+       gd->bd->bi_dram[2].size = PHYS_SDRAM_3_SIZE;
+       gd->bd->bi_dram[3].start = PHYS_SDRAM_4;
+       gd->bd->bi_dram[3].size = PHYS_SDRAM_4_SIZE;
 }
 
 static unsigned int get_hw_revision(void)
@@ -419,54 +426,22 @@ int board_mmc_init(bd_t *bis)
 {
        struct exynos4_gpio_part2 *gpio =
                (struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2();
-       int i, err;
+       int err;
 
        /* eMMC_EN: SD_0_CDn: GPK0[2] Output High */
        s5p_gpio_direction_output(&gpio->k0, 2, 1);
        s5p_gpio_set_pull(&gpio->k0, 2, GPIO_PULL_NONE);
 
-       /*
-        * eMMC GPIO:
-        * SDR 8-bit@48MHz at MMC0
-        * GPK0[0]      SD_0_CLK(2)
-        * GPK0[1]      SD_0_CMD(2)
-        * GPK0[2]      SD_0_CDn        -> Not used
-        * GPK0[3:6]    SD_0_DATA[0:3](2)
-        * GPK1[3:6]    SD_0_DATA[0:3](3)
-        *
-        * DDR 4-bit@26MHz at MMC4
-        * GPK0[0]      SD_4_CLK(3)
-        * GPK0[1]      SD_4_CMD(3)
-        * GPK0[2]      SD_4_CDn        -> Not used
-        * GPK0[3:6]    SD_4_DATA[0:3](3)
-        * GPK1[3:6]    SD_4_DATA[4:7](4)
-        */
-       for (i = 0; i < 7; i++) {
-               if (i == 2)
-                       continue;
-               /* GPK0[0:6] special function 2 */
-               s5p_gpio_cfg_pin(&gpio->k0, i, 0x2);
-               /* GPK0[0:6] pull disable */
-               s5p_gpio_set_pull(&gpio->k0, i, GPIO_PULL_NONE);
-               /* GPK0[0:6] drv 4x */
-               s5p_gpio_set_drv(&gpio->k0, i, GPIO_DRV_4X);
-       }
-
-       for (i = 3; i < 7; i++) {
-               /* GPK1[3:6] special function 3 */
-               s5p_gpio_cfg_pin(&gpio->k1, i, 0x3);
-               /* GPK1[3:6] pull disable */
-               s5p_gpio_set_pull(&gpio->k1, i, GPIO_PULL_NONE);
-               /* GPK1[3:6] drv 4x */
-               s5p_gpio_set_drv(&gpio->k1, i, GPIO_DRV_4X);
-       }
-
        /*
         * MMC device init
         * mmc0  : eMMC (8-bit buswidth)
         * mmc2  : SD card (4-bit buswidth)
         */
-       err = s5p_mmc_init(0, 8);
+       err = exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE);
+       if (err)
+               debug("SDMMC0 not configured\n");
+       else
+               err = s5p_mmc_init(0, 8);
 
        /* T-flash detect */
        s5p_gpio_cfg_pin(&gpio->x3, 4, 0xf);
@@ -477,24 +452,11 @@ int board_mmc_init(bd_t *bis)
         * GPX3[4] T-flash detect pin
         */
        if (!s5p_gpio_get_value(&gpio->x3, 4)) {
-               /*
-                * SD card GPIO:
-                * GPK2[0]      SD_2_CLK(2)
-                * GPK2[1]      SD_2_CMD(2)
-                * GPK2[2]      SD_2_CDn        -> Not used
-                * GPK2[3:6]    SD_2_DATA[0:3](2)
-                */
-               for (i = 0; i < 7; i++) {
-                       if (i == 2)
-                               continue;
-                       /* GPK2[0:6] special function 2 */
-                       s5p_gpio_cfg_pin(&gpio->k2, i, 0x2);
-                       /* GPK2[0:6] pull disable */
-                       s5p_gpio_set_pull(&gpio->k2, i, GPIO_PULL_NONE);
-                       /* GPK2[0:6] drv 4x */
-                       s5p_gpio_set_drv(&gpio->k2, i, GPIO_DRV_4X);
-               }
-               err = s5p_mmc_init(2, 4);
+               err = exynos_pinmux_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE);
+               if (err)
+                       debug("SDMMC2 not configured\n");
+               else
+                       err = s5p_mmc_init(2, 4);
        }
 
        return err;
@@ -629,6 +591,10 @@ static void board_power_init(void)
        writel(0, (unsigned int)&pwr->lcd1_configuration);
        writel(0, (unsigned int)&pwr->gps_configuration);
        writel(0, (unsigned int)&pwr->gps_alive_configuration);
+
+       /* It is necessary to power down core 1 */
+       /* to successfully boot CPU1 in kernel */
+       writel(0, (unsigned int)&pwr->arm_core1_configuration);
 }
 
 static void board_uart_init(void)
index bfec08fa8ea6c2676a5e06e9c92c467ff4c540a2..587cc1b8c70dded76858e4151908e4f6e40c6627 100644 (file)
@@ -26,7 +26,6 @@ include $(TOPDIR)/config.mk
 LIB    = $(obj)lib$(BOARD).o
 
 COBJS-y        := universal.o onenand.o
-SOBJS  := lowlevel_init.o
 
 SRCS    := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y))
diff --git a/board/samsung/universal_c210/lowlevel_init.S b/board/samsung/universal_c210/lowlevel_init.S
deleted file mode 100644 (file)
index dc7f69e..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Lowlevel setup for universal board based on EXYNOS4210
- *
- * Copyright (C) 2010 Samsung Electronics
- * Kyungmin Park <kyungmin.park@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 <config.h>
-#include <version.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/clock.h>
-
-/*
- * Register usages:
- *
- * r5 has zero always
- * r7 has GPIO part1 base 0x11400000
- * r6 has GPIO part2 base 0x11000000
- */
-
-       .globl lowlevel_init
-lowlevel_init:
-       mov     r11, lr
-
-       /* r5 has always zero */
-       mov     r5, #0
-
-       ldr     r7, =EXYNOS4_GPIO_PART1_BASE
-       ldr     r6, =EXYNOS4_GPIO_PART2_BASE
-
-       /* System Timer */
-       ldr     r0, =EXYNOS4_SYSTIMER_BASE
-       ldr     r1, =0x5000
-       str     r1, [r0, #0x0]
-       ldr     r1, =0xffffffff
-       str     r1, [r0, #0x8]
-       ldr     r1, =0x49
-       str     r1, [r0, #0x4]
-
-       /* PMIC manual reset */
-       /* nPOWER: XEINT_23: GPX2[7] */
-       add     r0, r6, #0xC40                  @ EXYNOS4_GPIO_X2_OFFSET
-       ldr     r1, [r0, #0x0]
-       bic     r1, r1, #(0xf << 28)            @ 28 = 7 * 4-bit
-       orr     r1, r1, #(0x1 << 28)            @ Output
-       str     r1, [r0, #0x0]
-
-       ldr     r1, [r0, #0x4]
-       orr     r1, r1, #(1 << 7)               @ 7 = 7 * 1-bit
-       str     r1, [r0, #0x4]
-
-       /* init system clock */
-       bl      system_clock_init
-
-       /* Disable Watchdog */
-       ldr     r0, =EXYNOS4_WATCHDOG_BASE              @0x10060000
-       str     r5, [r0]
-
-       /* UART */
-       bl      uart_asm_init
-
-       /* PMU init */
-       bl      system_power_init
-
-       bl      tzpc_init
-
-       mov     lr, r11
-       mov     pc, lr
-       nop
-       nop
-       nop
-
-/*
- * uart_asm_init: Initialize UART's pins
- */
-uart_asm_init:
-       /*
-        * setup UART0-UART4 GPIOs (part1)
-        * GPA1CON[3] = I2C_3_SCL (3)
-        * GPA1CON[2] = I2C_3_SDA (3)
-        */
-       mov     r0, r7
-       ldr     r1, =0x22222222
-       str     r1, [r0, #0x00]                 @ EXYNOS4_GPIO_A0_OFFSET
-       ldr     r1, =0x00223322
-       str     r1, [r0, #0x20]                 @ EXYNOS4_GPIO_A1_OFFSET
-
-       /* UART_SEL GPY4[7] (part2) at EXYNOS4 */
-       add     r0, r6, #0x1A0                  @ EXYNOS4_GPIO_Y4_OFFSET
-       ldr     r1, [r0, #0x0]
-       bic     r1, r1, #(0xf << 28)            @ 28 = 7 * 4-bit
-       orr     r1, r1, #(0x1 << 28)
-       str     r1, [r0, #0x0]
-
-       ldr     r1, [r0, #0x8]
-       bic     r1, r1, #(0x3 << 14)            @ 14 = 7 * 2-bit
-       orr     r1, r1, #(0x3 << 14)            @ Pull-up enabled
-       str     r1, [r0, #0x8]
-
-       ldr     r1, [r0, #0x4]
-       orr     r1, r1, #(1 << 7)               @ 7 = 7 * 1-bit
-       str     r1, [r0, #0x4]
-
-       mov     pc, lr
-       nop
-       nop
-       nop
-
-system_clock_init:
-       ldr     r0, =EXYNOS4_CLOCK_BASE
-
-       /* APLL(1), MPLL(1), CORE(0), HPM(0) */
-       ldr     r1, =0x0101
-       ldr     r2, =0x14200                    @ CLK_SRC_CPU
-       str     r1, [r0, r2]
-
-       /* wait ?us */
-       mov     r1, #0x10000
-1:     subs    r1, r1, #1
-       bne     1b
-
-       /*
-        * CLK_SRC_TOP0
-        * MUX_ONENAND_SEL[28]  0: DOUT133, 1: DOUT166
-        * MUX_VPLL_SEL[8]      0: FINPLL,  1: FOUTVPLL
-        * MUX_EPLL_SEL[4]      0: FINPLL,  1: FOUTEPLL
-        */
-       ldr     r1, =0x10000110
-       ldr     r2, =0x0C210                    @ CLK_SRC_TOP
-       str     r1, [r0, r2]
-
-       /* SATA: SCLKMPLL(0), MMC[0:4]: SCLKMPLL(6) */
-       ldr     r1, =0x0066666
-       ldr     r2, =0x0C240                    @ CLK_SRC_FSYS
-       str     r1, [r0, r2]
-       /* UART[0:5], PWM: SCLKMPLL(6) */
-       ldr     r1, =0x6666666
-       ldr     r2, =0x0C250                    @ CLK_SRC_PERIL0_OFFSET
-       str     r1, [r0, r2]
-
-       /* CPU0: CORE, COREM0, COREM1, PERI, ATB, PCLK_DBG, APLL */
-       ldr     r1, =0x0133730
-       ldr     r2, =0x14500                    @ CLK_DIV_CPU0
-       str     r1, [r0, r2]
-       /* CPU1: COPY, HPM */
-       ldr     r1, =0x03
-       ldr     r2, =0x14504                    @ CLK_DIV_CPU1
-       str     r1, [r0, r2]
-       /* DMC0: ACP, ACP_PCLK, DPHY, DMC, DMCD, DMCP, COPY2 CORE_TIMER */
-       ldr     r1, =0x13111113
-       ldr     r2, =0x10500                    @ CLK_DIV_DMC0
-       str     r1, [r0, r2]
-       /* DMC1: PWI, DVSEM, DPM */
-       ldr     r1, =0x01010100
-       ldr     r2, =0x10504                    @ CLK_DIV_DMC1
-       str     r1, [r0, r2]
-       /* LEFTBUS: GDL, GPL */
-       ldr     r1, =0x13
-       ldr     r2, =0x04500                    @ CLK_DIV_LEFTBUS
-       str     r1, [r0, r2]
-       /* RIGHHTBUS: GDR, GPR */
-       ldr     r1, =0x13
-       ldr     r2, =0x08500                    @ CLK_DIV_RIGHTBUS
-       str     r1, [r0, r2]
-       /*
-        * CLK_DIV_TOP
-        * ONENAND_RATIOD[18:16]: 0 SCLK_ONENAND = MOUTONENAND / (n + 1)
-        * ACLK_200, ACLK_100, ACLK_160, ACLK_133,
-        */
-       ldr     r1, =0x00005473
-       ldr     r2, =0x0C510                    @ CLK_DIV_TOP
-       str     r1, [r0, r2]
-       /* MMC[0:1] */
-       ldr     r1, =0x000f000f                 /* 800(MPLL) / (15 + 1) */
-       ldr     r2, =0x0C544                    @ CLK_DIV_FSYS1
-       str     r1, [r0, r2]
-       /* MMC[2:3] */
-       ldr     r1, =0x000f000f                 /* 800(MPLL) / (15 + 1) */
-       ldr     r2, =0x0C548                    @ CLK_DIV_FSYS2
-       str     r1, [r0, r2]
-       /* MMC4 */
-       ldr     r1, =0x000f                     /* 800(MPLL) / (15 + 1) */
-       ldr     r2, =0x0C54C                    @ CLK_DIV_FSYS3
-       str     r1, [r0, r2]
-       /* UART[0:5] */
-       ldr     r1, =0x774777
-       ldr     r2, =0x0C550                    @ CLK_DIV_PERIL0
-       str     r1, [r0, r2]
-       /* SLIMBUS: ???, PWM */
-       ldr     r1, =0x8
-       ldr     r2, =0x0C55C                    @ CLK_DIV_PERIL3
-       str     r1, [r0, r2]
-
-       /* PLL Setting */
-       ldr     r1, =0x1C20
-       ldr     r2, =0x14000                    @ APLL_LOCK
-       str     r1, [r0, r2]
-       ldr     r2, =0x14008                    @ MPLL_LOCK
-       str     r1, [r0, r2]
-       ldr     r2, =0x0C010                    @ EPLL_LOCK
-       str     r1, [r0, r2]
-       ldr     r2, =0x0C020                    @ VPLL_LOCK
-       str     r1, [r0, r2]
-
-       /* APLL */
-       ldr     r1, =0x8000001c
-       ldr     r2, =0x14104                    @ APLL_CON1
-       str     r1, [r0, r2]
-       ldr     r1, =0x80c80601                 @ 800MHz
-       ldr     r2, =0x14100                    @ APLL_CON0
-       str     r1, [r0, r2]
-       /* MPLL */
-       ldr     r1, =0x8000001C
-       ldr     r2, =0x1410C                    @ MPLL_CON1
-       str     r1, [r0, r2]
-       ldr     r1, =0x80c80601                 @ 800MHz
-       ldr     r2, =0x14108                    @ MPLL_CON0
-       str     r1, [r0, r2]
-       /* EPLL */
-       ldr     r1, =0x0
-       ldr     r2, =0x0C114                    @ EPLL_CON1
-       str     r1, [r0, r2]
-       ldr     r1, =0x80300302                 @ 96MHz
-       ldr     r2, =0x0C110                    @ EPLL_CON0
-       str     r1, [r0, r2]
-       /* VPLL */
-       ldr     r1, =0x11000400
-       ldr     r2, =0x0C124                    @ VPLL_CON1
-       str     r1, [r0, r2]
-       ldr     r1, =0x80350302                 @ 108MHz
-       ldr     r2, =0x0C120                    @ VPLL_CON0
-       str     r1, [r0, r2]
-
-       /*
-        * SMMUJPEG[11], JPEG[6], CSIS1[5]              : 0111 1001
-        * Turn off all
-        */
-       ldr     r1, =0xFFF80000
-       ldr     r2, =0x0C920                    @ CLK_GATE_IP_CAM
-       str     r1, [r0, r2]
-
-       /* Turn off all */
-       ldr     r1, =0xFFFFFFC0
-       ldr     r2, =0x0C924                    @ CLK_GATE_IP_VP
-       str     r1, [r0, r2]
-
-       /* Turn off all */
-       ldr     r1, =0xFFFFFFE0
-       ldr     r2, =0x0C928                    @ CLK_GATE_IP_MFC
-       str     r1, [r0, r2]
-
-       /* Turn off all */
-       ldr     r1, =0xFFFFFFFC
-       ldr     r2, =0x0C92C                    @ CLK_GATE_IP_G3D
-       str     r1, [r0, r2]
-
-       /* Turn off all */
-       ldr     r1, =0xFFFFFC00
-       ldr     r2, =0x0C930                    @ CLK_GATE_IP_IMAGE
-       str     r1, [r0, r2]
-
-       /* DSIM0[3], MDNIE0[2], MIE0[1]                 : 0001 */
-       ldr     r1, =0xFFFFFFF1
-       ldr     r2, =0x0C934                    @ CLK_GATE_IP_LCD0
-       str     r1, [r0, r2]
-
-       /* Turn off all */
-       ldr     r1, =0xFFFFFFC0
-       ldr     r2, =0x0C938                    @ CLK_GATE_IP_LCD1
-       str     r1, [r0, r2]
-
-       /*
-        * SMMUPCIE[18], NFCON[16]                      : 1111 1010
-        * PCIE[14],  SATA[10], SDMMC43[9:8]            : 1011 1000
-        * SDMMC1[6], TSI[4], SATAPHY[3], PCIEPHY[2]    : 1010 0011
-        */
-       ldr     r1, =0xFFFAB8A3
-       ldr     r2, =0x0C940                    @ CLK_GATE_IP_FSYS
-       str     r1, [r0, r2]
-
-       /* Turn off all */
-       ldr     r1, =0xFFFFFFFC
-       ldr     r2, =0x0C94C                    @ CLK_GATE_IP_GPS
-       str     r1, [r0, r2]
-
-       /*
-        * AC97[27], SPDIF[26], SLIMBUS[25]             : 1111 0001
-        * I2C2[8]                                      : 1111 1110
-        */
-       ldr     r1, =0xF1FFFEFF
-       ldr     r2, =0x0C950                    @ CLK_GATE_IP_PERIL
-       str     r1, [r0, r2]
-
-       /*
-        * KEYIF[16]                                    : 1111 1110
-        */
-       ldr     r1, =0xFFFEFFFF
-       ldr     r2, =0x0C960                    @ CLK_GATE_IP_PERIR
-       str     r1, [r0, r2]
-
-       /* LCD1[5], G3D[3], MFC[2], TV[1]               : 1101 0001 */
-       ldr     r1, =0xFFFFFFD1
-       ldr     r2, =0x0C970                    @ CLK_GATE_BLOCK
-       str     r1, [r0, r2]
-       mov     pc, lr
-       nop
-       nop
-       nop
-
-system_power_init:
-       ldr     r0, =EXYNOS4_POWER_BASE         @ 0x10020000
-
-       ldr     r2, =0x330C                     @ PS_HOLD_CONTROL
-       ldr     r1, [r0, r2]
-       orr     r1, r1, #(0x3 << 8)             @ Data High, Output En
-       str     r1, [r0, r2]
-
-       /* Power Down */
-       add     r2, r0, #0x3000
-       str     r5, [r2, #0xC20]                @ TV_CONFIGURATION
-       str     r5, [r2, #0xC40]                @ MFC_CONFIGURATION
-       str     r5, [r2, #0xC60]                @ G3D_CONFIGURATION
-       str     r5, [r2, #0xCA0]                @ LCD1_CONFIGURATION
-       str     r5, [r2, #0xCE0]                @ GPS_CONFIGURATION
-
-       mov     pc, lr
-       nop
-       nop
-       nop
-
-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]
-
-       mov     pc, lr
index 36a047217c57cbdac1b07196fbb137bf0eb7f2d1..e742707f79659dca95b19fb4b6b91f27f093e0e8 100644 (file)
  */
 
 #include <common.h>
+#include <spi.h>
+#include <lcd.h>
 #include <asm/io.h>
+#include <asm/gpio.h>
 #include <asm/arch/adc.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/watchdog.h>
+#include <libtizen.h>
+#include <ld9040.h>
 #include <power/pmic.h>
 #include <usb/s3c_udc.h>
 #include <asm/arch/cpu.h>
@@ -48,21 +55,7 @@ static int get_hwrev(void)
        return board_rev & 0xFF;
 }
 
-static void check_hw_revision(void);
-
-int board_init(void)
-{
-       gpio1 = (struct exynos4_gpio_part1 *) EXYNOS4_GPIO_PART1_BASE;
-       gpio2 = (struct exynos4_gpio_part2 *) EXYNOS4_GPIO_PART2_BASE;
-
-       gd->bd->bi_arch_number = MACH_TYPE_UNIVERSAL_C210;
-       gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
-
-       check_hw_revision();
-       printf("HW Revision:\t0x%x\n", board_rev);
-
-       return 0;
-}
+static void init_pmic_lcd(void);
 
 int power_init_board(void)
 {
@@ -72,6 +65,8 @@ int power_init_board(void)
        if (ret)
                return ret;
 
+       init_pmic_lcd();
+
        return 0;
 }
 
@@ -186,7 +181,7 @@ int checkboard(void)
 #ifdef CONFIG_GENERIC_MMC
 int board_mmc_init(bd_t *bis)
 {
-       int i, err;
+       int err;
 
        switch (get_hwrev()) {
        case 0:
@@ -209,75 +204,30 @@ int board_mmc_init(bd_t *bis)
        }
 
        /*
-        * eMMC GPIO:
-        * SDR 8-bit@48MHz at MMC0
-        * GPK0[0]      SD_0_CLK(2)
-        * GPK0[1]      SD_0_CMD(2)
-        * GPK0[2]      SD_0_CDn        -> Not used
-        * GPK0[3:6]    SD_0_DATA[0:3](2)
-        * GPK1[3:6]    SD_0_DATA[0:3](3)
-        *
-        * DDR 4-bit@26MHz at MMC4
-        * GPK0[0]      SD_4_CLK(3)
-        * GPK0[1]      SD_4_CMD(3)
-        * GPK0[2]      SD_4_CDn        -> Not used
-        * GPK0[3:6]    SD_4_DATA[0:3](3)
-        * GPK1[3:6]    SD_4_DATA[4:7](4)
+        * MMC device init
+        * mmc0  : eMMC (8-bit buswidth)
+        * mmc2  : SD card (4-bit buswidth)
         */
-       for (i = 0; i < 7; i++) {
-               if (i == 2)
-                       continue;
-               /* GPK0[0:6] special function 2 */
-               s5p_gpio_cfg_pin(&gpio2->k0, i, 0x2);
-               /* GPK0[0:6] pull disable */
-               s5p_gpio_set_pull(&gpio2->k0, i, GPIO_PULL_NONE);
-               /* GPK0[0:6] drv 4x */
-               s5p_gpio_set_drv(&gpio2->k0, i, GPIO_DRV_4X);
-       }
-
-       for (i = 3; i < 7; i++) {
-               /* GPK1[3:6] special function 3 */
-               s5p_gpio_cfg_pin(&gpio2->k1, i, 0x3);
-               /* GPK1[3:6] pull disable */
-               s5p_gpio_set_pull(&gpio2->k1, i, GPIO_PULL_NONE);
-               /* GPK1[3:6] drv 4x */
-               s5p_gpio_set_drv(&gpio2->k1, i, GPIO_DRV_4X);
-       }
+       err = exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE);
+       if (err)
+               debug("SDMMC0 not configured\n");
+       else
+               err = s5p_mmc_init(0, 8);
 
        /* T-flash detect */
        s5p_gpio_cfg_pin(&gpio2->x3, 4, 0xf);
        s5p_gpio_set_pull(&gpio2->x3, 4, GPIO_PULL_UP);
 
-       /*
-        * MMC device init
-        * mmc0  : eMMC (8-bit buswidth)
-        * mmc2  : SD card (4-bit buswidth)
-        */
-       err = s5p_mmc_init(0, 8);
-
        /*
         * Check the T-flash  detect pin
         * GPX3[4] T-flash detect pin
         */
        if (!s5p_gpio_get_value(&gpio2->x3, 4)) {
-               /*
-                * SD card GPIO:
-                * GPK2[0]      SD_2_CLK(2)
-                * GPK2[1]      SD_2_CMD(2)
-                * GPK2[2]      SD_2_CDn        -> Not used
-                * GPK2[3:6]    SD_2_DATA[0:3](2)
-                */
-               for (i = 0; i < 7; i++) {
-                       if (i == 2)
-                               continue;
-                       /* GPK2[0:6] special function 2 */
-                       s5p_gpio_cfg_pin(&gpio2->k2, i, 0x2);
-                       /* GPK2[0:6] pull disable */
-                       s5p_gpio_set_pull(&gpio2->k2, i, GPIO_PULL_NONE);
-                       /* GPK2[0:6] drv 4x */
-                       s5p_gpio_set_drv(&gpio2->k2, i, GPIO_DRV_4X);
-               }
-               err = s5p_mmc_init(2, 4);
+               err = exynos_pinmux_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE);
+               if (err)
+                       debug("SDMMC2 not configured\n");
+               else
+                       err = s5p_mmc_init(2, 4);
        }
 
        return err;
@@ -331,3 +281,242 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
        .usb_flags = PHY0_SLEEP,
 };
 #endif
+
+int board_early_init_f(void)
+{
+       wdt_stop();
+
+       return 0;
+}
+
+#ifdef CONFIG_SOFT_SPI
+static void soft_spi_init(void)
+{
+       gpio_direction_output(CONFIG_SOFT_SPI_GPIO_SCLK,
+               CONFIG_SOFT_SPI_MODE & SPI_CPOL);
+       gpio_direction_output(CONFIG_SOFT_SPI_GPIO_MOSI, 1);
+       gpio_direction_input(CONFIG_SOFT_SPI_GPIO_MISO);
+       gpio_direction_output(CONFIG_SOFT_SPI_GPIO_CS,
+               !(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+       gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
+               !(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
+       SPI_SCL(1);
+       gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
+               CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+       gpio_set_value(CONFIG_SOFT_SPI_GPIO_CS,
+               !(CONFIG_SOFT_SPI_MODE & SPI_CS_HIGH));
+}
+
+int  spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+       return bus == 0 && cs == 0;
+}
+
+void universal_spi_scl(int bit)
+{
+       gpio_set_value(CONFIG_SOFT_SPI_GPIO_SCLK, bit);
+}
+
+void universal_spi_sda(int bit)
+{
+       gpio_set_value(CONFIG_SOFT_SPI_GPIO_MOSI, bit);
+}
+
+int universal_spi_read(void)
+{
+       return gpio_get_value(CONFIG_SOFT_SPI_GPIO_MISO);
+}
+#endif
+
+static void init_pmic_lcd(void)
+{
+       unsigned char val;
+       int ret = 0;
+
+       struct pmic *p = pmic_get("MAX8998_PMIC");
+
+       if (!p)
+               return;
+
+       if (pmic_probe(p))
+               return;
+
+       /* LDO7 1.8V */
+       val = 0x02; /* (1800 - 1600) / 100; */
+       ret |= pmic_reg_write(p,  MAX8998_REG_LDO7, val);
+
+       /* LDO17 3.0V */
+       val = 0xe; /* (3000 - 1600) / 100; */
+       ret |= pmic_reg_write(p,  MAX8998_REG_LDO17, val);
+
+       /* Disable unneeded regulators */
+       /*
+        * ONOFF1
+        * Buck1 ON, Buck2 OFF, Buck3 ON, Buck4 ON
+        * LDO2 ON, LDO3 OFF, LDO4 OFF, LDO5 ON
+        */
+       val = 0xB9;
+       ret |= pmic_reg_write(p,  MAX8998_REG_ONOFF1, val);
+
+       /* ONOFF2
+        * LDO6 OFF, LDO7 ON, LDO8 OFF, LDO9 ON,
+        * LDO10 OFF, LDO11 OFF, LDO12 OFF, LDO13 OFF
+        */
+       val = 0x50;
+       ret |= pmic_reg_write(p,  MAX8998_REG_ONOFF2, val);
+
+       /* ONOFF3
+        * LDO14 OFF, LDO15 OFF, LGO16 OFF, LDO17 OFF
+        * EPWRHOLD OFF, EBATTMON OFF, ELBCNFG2 OFF, ELBCNFG1 OFF
+        */
+       val = 0x00;
+       ret |= pmic_reg_write(p,  MAX8998_REG_ONOFF3, val);
+
+       if (ret)
+               puts("LCD pmic initialisation error!\n");
+}
+
+static void lcd_cfg_gpio(void)
+{
+       unsigned int i, f3_end = 4;
+
+       for (i = 0; i < 8; i++) {
+               /* set GPF0,1,2[0:7] for RGB Interface and Data lines (32bit) */
+               s5p_gpio_cfg_pin(&gpio1->f0, i, GPIO_FUNC(2));
+               s5p_gpio_cfg_pin(&gpio1->f1, i, GPIO_FUNC(2));
+               s5p_gpio_cfg_pin(&gpio1->f2, i, GPIO_FUNC(2));
+               /* pull-up/down disable */
+               s5p_gpio_set_pull(&gpio1->f0, i, GPIO_PULL_NONE);
+               s5p_gpio_set_pull(&gpio1->f1, i, GPIO_PULL_NONE);
+               s5p_gpio_set_pull(&gpio1->f2, i, GPIO_PULL_NONE);
+
+               /* drive strength to max (24bit) */
+               s5p_gpio_set_drv(&gpio1->f0, i, GPIO_DRV_4X);
+               s5p_gpio_set_rate(&gpio1->f0, i, GPIO_DRV_SLOW);
+               s5p_gpio_set_drv(&gpio1->f1, i, GPIO_DRV_4X);
+               s5p_gpio_set_rate(&gpio1->f1, i, GPIO_DRV_SLOW);
+               s5p_gpio_set_drv(&gpio1->f2, i, GPIO_DRV_4X);
+               s5p_gpio_set_rate(&gpio1->f0, i, GPIO_DRV_SLOW);
+       }
+
+       for (i = 0; i < f3_end; i++) {
+               /* set GPF3[0:3] for RGB Interface and Data lines (32bit) */
+               s5p_gpio_cfg_pin(&gpio1->f3, i, GPIO_FUNC(2));
+               /* pull-up/down disable */
+               s5p_gpio_set_pull(&gpio1->f3, i, GPIO_PULL_NONE);
+               /* drive strength to max (24bit) */
+               s5p_gpio_set_drv(&gpio1->f3, i, GPIO_DRV_4X);
+               s5p_gpio_set_rate(&gpio1->f3, i, GPIO_DRV_SLOW);
+       }
+
+       /* gpio pad configuration for LCD reset. */
+       s5p_gpio_cfg_pin(&gpio2->y4, 5, GPIO_OUTPUT);
+
+       spi_init();
+}
+
+static void reset_lcd(void)
+{
+       s5p_gpio_set_value(&gpio2->y4, 5, 1);
+       udelay(10000);
+       s5p_gpio_set_value(&gpio2->y4, 5, 0);
+       udelay(10000);
+       s5p_gpio_set_value(&gpio2->y4, 5, 1);
+       udelay(100);
+}
+
+static void lcd_power_on(void)
+{
+       struct pmic *p = pmic_get("MAX8998_PMIC");
+
+       if (!p)
+               return;
+
+       if (pmic_probe(p))
+               return;
+
+       pmic_set_output(p, MAX8998_REG_ONOFF3, MAX8998_LDO17, LDO_ON);
+       pmic_set_output(p, MAX8998_REG_ONOFF2, MAX8998_LDO7, LDO_ON);
+}
+
+vidinfo_t panel_info = {
+       .vl_freq        = 60,
+       .vl_col         = 480,
+       .vl_row         = 800,
+       .vl_width       = 480,
+       .vl_height      = 800,
+       .vl_clkp        = CONFIG_SYS_HIGH,
+       .vl_hsp         = CONFIG_SYS_HIGH,
+       .vl_vsp         = CONFIG_SYS_HIGH,
+       .vl_dp          = CONFIG_SYS_HIGH,
+
+       .vl_bpix        = 5,    /* Bits per pixel */
+
+       /* LD9040 LCD Panel */
+       .vl_hspw        = 2,
+       .vl_hbpd        = 16,
+       .vl_hfpd        = 16,
+
+       .vl_vspw        = 2,
+       .vl_vbpd        = 8,
+       .vl_vfpd        = 8,
+       .vl_cmd_allow_len = 0xf,
+
+       .win_id         = 0,
+       .cfg_gpio       = lcd_cfg_gpio,
+       .backlight_on   = NULL,
+       .lcd_power_on   = lcd_power_on,
+       .reset_lcd      = reset_lcd,
+       .dual_lcd_enabled = 0,
+
+       .init_delay     = 0,
+       .power_on_delay = 10000,
+       .reset_delay    = 10000,
+       .interface_mode = FIMD_RGB_INTERFACE,
+       .mipi_enabled   = 0,
+};
+
+void init_panel_info(vidinfo_t *vid)
+{
+       vid->logo_on    = 1;
+       vid->resolution = HD_RESOLUTION;
+       vid->rgb_mode   = MODE_RGB_P;
+
+#ifdef CONFIG_TIZEN
+       get_tizen_logo_info(vid);
+#endif
+
+       /* for LD9040. */
+       vid->pclk_name = 1;     /* MPLL */
+       vid->sclk_div = 1;
+
+       vid->cfg_ldo = ld9040_cfg_ldo;
+       vid->enable_ldo = ld9040_enable_ldo;
+
+       setenv("lcdinfo", "lcd=ld9040");
+}
+
+int board_init(void)
+{
+       gpio1 = (struct exynos4_gpio_part1 *) EXYNOS4_GPIO_PART1_BASE;
+       gpio2 = (struct exynos4_gpio_part2 *) EXYNOS4_GPIO_PART2_BASE;
+
+       gd->bd->bi_arch_number = MACH_TYPE_UNIVERSAL_C210;
+       gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+#ifdef CONFIG_SOFT_SPI
+       soft_spi_init();
+#endif
+       check_hw_revision();
+       printf("HW Revision:\t0x%x\n", board_rev);
+
+       return 0;
+}
index c29a7d82e3318673a605f6cac79bab1e4e8e0ba0..54fcc815889c2165d900d89802c8650cea74c188 100644 (file)
@@ -30,6 +30,7 @@ ifndef CONFIG_SPL_BUILD
 COBJS-y += main.o
 COBJS-y += command.o
 COBJS-y += exports.o
+COBJS-y += hash.o
 COBJS-$(CONFIG_SYS_HUSH_PARSER) += hush.o
 COBJS-y += s_record.o
 COBJS-y += xyzModem.o
@@ -43,7 +44,10 @@ 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
 XCOBJS-$(CONFIG_ENV_IS_EMBEDDED) += env_embedded.o
@@ -75,6 +79,7 @@ COBJS-$(CONFIG_CMD_CONSOLE) += cmd_console.o
 COBJS-$(CONFIG_CMD_CPLBINFO) += cmd_cplbinfo.o
 COBJS-$(CONFIG_DATAFLASH_MMC_SELECT) += cmd_dataflash_mmc_mux.o
 COBJS-$(CONFIG_CMD_DATE) += cmd_date.o
+COBJS-$(CONFIG_CMD_SOUND) += cmd_sound.o
 ifdef CONFIG_4xx
 COBJS-$(CONFIG_CMD_SETGETDCR) += cmd_dcr.o
 endif
@@ -100,8 +105,10 @@ ifdef CONFIG_FPGA
 COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o
 endif
 COBJS-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o
+COBJS-$(CONFIG_CMD_GETTIME) += cmd_gettime.o
 COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o
 COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o
+COBJS-$(CONFIG_CMD_HASH) += cmd_hash.o
 COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o
 COBJS-$(CONFIG_CMD_IMMAP) += cmd_immap.o
 COBJS-$(CONFIG_CMD_INI) += cmd_ini.o
@@ -117,6 +124,7 @@ COBJS-$(CONFIG_LOGBUFFER) += cmd_log.o
 COBJS-$(CONFIG_ID_EEPROM) += cmd_mac.o
 COBJS-$(CONFIG_CMD_MD5SUM) += cmd_md5sum.o
 COBJS-$(CONFIG_CMD_MEMORY) += cmd_mem.o
+COBJS-$(CONFIG_CMD_IO) += cmd_io.o
 COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
 COBJS-$(CONFIG_MII) += miiphyutil.o
 COBJS-$(CONFIG_CMD_MII) += miiphyutil.o
@@ -141,6 +149,7 @@ endif
 COBJS-y += cmd_pcmcia.o
 COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o
 COBJS-$(CONFIG_CMD_PXE) += cmd_pxe.o
+COBJS-$(CONFIG_CMD_READ) += cmd_read.o
 COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o
 COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o
 COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o
@@ -184,6 +193,7 @@ COBJS-$(CONFIG_BOOTSTAGE) += bootstage.o
 COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o
 COBJS-y += flash.o
 COBJS-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o
+COBJS-$(CONFIG_I2C_EDID) += edid.o
 COBJS-$(CONFIG_KALLSYMS) += kallsyms.o
 COBJS-$(CONFIG_LCD) += lcd.o
 COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o
@@ -192,6 +202,7 @@ COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
 COBJS-$(CONFIG_UPDATE_TFTP) += update.o
 COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
 COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
+COBJS-$(CONFIG_CMD_GPT) += cmd_gpt.o
 endif
 
 ifdef CONFIG_SPL_BUILD
@@ -200,7 +211,10 @@ 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
 endif
index 4dbe952bb0f56b92f40b0a67dd594f83d987e804..f7595c0311955b58acffa6efd2b19a209576ec48 100644 (file)
@@ -537,7 +537,7 @@ static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
                }
                        break;
 #endif
-#if defined(CONFIG_OF_LIBFDT)
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
                case BOOTM_STATE_FDT:
                {
                        boot_fdt_add_mem_rsv_regions(&images.lmb,
diff --git a/common/cmd_gettime.c b/common/cmd_gettime.c
new file mode 100644 (file)
index 0000000..d7d36a9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * (C) Copyright 2001
+ * 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
+ */
+
+/*
+ * Get Timer overflows after 2^32 / CONFIG_SYS_HZ (32Khz) = 131072 sec
+ */
+#include <common.h>
+#include <command.h>
+
+static int do_gettime(cmd_tbl_t *cmdtp, int flag, int argc,
+                     char * const argv[])
+{
+       unsigned long int val = get_timer(0);
+
+#ifdef CONFIG_SYS_HZ
+       printf("Timer val: %lu\n", val);
+       printf("Seconds : %lu\n", val / CONFIG_SYS_HZ);
+       printf("Remainder : %lu\n", val % CONFIG_SYS_HZ);
+       printf("sys_hz = %lu\n", (unsigned long int)CONFIG_SYS_HZ);
+#else
+       printf("CONFIG_SYS_HZ not defined");
+       printf("Timer Val %lu", val);
+#endif
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       gettime,        1,      1,      do_gettime,
+       "get timer val elapsed,\n",
+       "get time elapsed from uboot start\n"
+);
diff --git a/common/cmd_gpt.c b/common/cmd_gpt.c
new file mode 100644 (file)
index 0000000..da7705d
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * cmd_gpt.c -- GPT (GUID Partition Table) handling command
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ * author: Piotr Wilczek <p.wilczek@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <command.h>
+#include <mmc.h>
+#include <part_efi.h>
+#include <exports.h>
+#include <linux/ctype.h>
+
+#ifndef CONFIG_PARTITION_UUIDS
+#error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled
+#endif
+
+/**
+ * extract_env(): Expand env name from string format '&{env_name}'
+ *                and return pointer to the env (if the env is set)
+ *
+ * @param str - pointer to string
+ * @param env - pointer to pointer to extracted env
+ *
+ * @return - zero on successful expand and env is set
+ */
+static char extract_env(const char *str, char **env)
+{
+       char *e, *s;
+
+       if (!str || strlen(str) < 4)
+               return -1;
+
+       if ((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}')) {
+               s = strdup(str);
+               if (s == NULL)
+                       return -1;
+               memset(s + strlen(s) - 1, '\0', 1);
+               memmove(s, s + 2, strlen(s) - 1);
+               e = getenv(s);
+               free(s);
+               if (e == NULL) {
+                       printf("Environmental '%s' not set\n", str);
+                       return -1; /* env not set */
+               }
+               *env = e;
+               return 0;
+       }
+
+       return -1;
+}
+
+/**
+ * extract_val(): Extract value from a key=value pair list (comma separated).
+ *                Only value for the given key is returend.
+ *                Function allocates memory for the value, remember to free!
+ *
+ * @param str - pointer to string with key=values pairs
+ * @param key - pointer to the key to search for
+ *
+ * @return - pointer to allocated string with the value
+ */
+static char *extract_val(const char *str, const char *key)
+{
+       char *v, *k;
+       char *s, *strcopy;
+       char *new = NULL;
+
+       strcopy = strdup(str);
+       if (strcopy == NULL)
+               return NULL;
+
+       s = strcopy;
+       while (s) {
+               v = strsep(&s, ",");
+               if (!v)
+                       break;
+               k = strsep(&v, "=");
+               if (!k)
+                       break;
+               if  (strcmp(k, key) == 0) {
+                       new = strdup(v);
+                       break;
+               }
+       }
+
+       free(strcopy);
+
+       return new;
+}
+
+/**
+ * set_gpt_info(): Fill partition information from string
+ *             function allocates memory, remember to free!
+ *
+ * @param dev_desc - pointer block device descriptor
+ * @param str_part - pointer to string with partition information
+ * @param str_disk_guid - pointer to pointer to allocated string with disk guid
+ * @param partitions - pointer to pointer to allocated partitions array
+ * @param parts_count - number of partitions
+ *
+ * @return - zero on success, otherwise error
+ *
+ */
+static int set_gpt_info(block_dev_desc_t *dev_desc,
+                       const char *str_part,
+                       char **str_disk_guid,
+                       disk_partition_t **partitions,
+                       u8 *parts_count)
+{
+       char *tok, *str, *s;
+       int i;
+       char *val, *p;
+       int p_count;
+       disk_partition_t *parts;
+       int errno = 0;
+
+       debug("%s: MMC lba num: 0x%x %d\n", __func__,
+             (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba);
+
+       if (str_part == NULL)
+               return -1;
+
+       str = strdup(str_part);
+
+       /* extract disk guid */
+       s = str;
+       tok = strsep(&s, ";");
+       val = extract_val(tok, "uuid_disk");
+       if (!val) {
+               free(str);
+               return -2;
+       }
+       if (extract_env(val, &p))
+               p = val;
+       *str_disk_guid = strdup(p);
+       free(val);
+
+       if (strlen(s) == 0)
+               return -3;
+
+       i = strlen(s) - 1;
+       if (s[i] == ';')
+               s[i] = '\0';
+
+       /* calculate expected number of partitions */
+       p_count = 1;
+       p = s;
+       while (*p) {
+               if (*p++ == ';')
+                       p_count++;
+       }
+
+       /* allocate memory for partitions */
+       parts = calloc(sizeof(disk_partition_t), p_count);
+
+       /* retrive partions data from string */
+       for (i = 0; i < p_count; i++) {
+               tok = strsep(&s, ";");
+
+               if (tok == NULL)
+                       break;
+
+               /* uuid */
+               val = extract_val(tok, "uuid");
+               if (!val) { /* 'uuid' is mandatory */
+                       errno = -4;
+                       goto err;
+               }
+               if (extract_env(val, &p))
+                       p = val;
+               if (strlen(p) >= sizeof(parts[i].uuid)) {
+                       printf("Wrong uuid format for partition %d\n", i);
+                       errno = -4;
+                       goto err;
+               }
+               strcpy((char *)parts[i].uuid, p);
+               free(val);
+
+               /* name */
+               val = extract_val(tok, "name");
+               if (!val) { /* name is mandatory */
+                       errno = -4;
+                       goto err;
+               }
+               if (extract_env(val, &p))
+                       p = val;
+               if (strlen(p) >= sizeof(parts[i].name)) {
+                       errno = -4;
+                       goto err;
+               }
+               strcpy((char *)parts[i].name, p);
+               free(val);
+
+               /* size */
+               val = extract_val(tok, "size");
+               if (!val) { /* 'size' is mandatory */
+                       errno = -4;
+                       goto err;
+               }
+               if (extract_env(val, &p))
+                       p = val;
+               parts[i].size = ustrtoul(p, &p, 0);
+               parts[i].size /= dev_desc->blksz;
+               free(val);
+
+               /* start address */
+               val = extract_val(tok, "start");
+               if (val) { /* start address is optional */
+                       if (extract_env(val, &p))
+                               p = val;
+                       parts[i].start = ustrtoul(p, &p, 0);
+                       parts[i].start /= dev_desc->blksz;
+                       free(val);
+               }
+       }
+
+       *parts_count = p_count;
+       *partitions = parts;
+       free(str);
+
+       return 0;
+err:
+       free(str);
+       free(*str_disk_guid);
+       free(parts);
+
+       return errno;
+}
+
+static int gpt_mmc_default(int dev, const char *str_part)
+{
+       int ret;
+       char *str_disk_guid;
+       u8 part_count = 0;
+       disk_partition_t *partitions = NULL;
+
+       struct mmc *mmc = find_mmc_device(dev);
+
+       if (mmc == NULL) {
+               printf("%s: mmc dev %d NOT available\n", __func__, dev);
+               return CMD_RET_FAILURE;
+       }
+
+       if (!str_part)
+               return -1;
+
+       /* fill partitions */
+       ret = set_gpt_info(&mmc->block_dev, str_part,
+                       &str_disk_guid, &partitions, &part_count);
+       if (ret) {
+               if (ret == -1)
+                       printf("No partition list provided\n");
+               if (ret == -2)
+                       printf("Missing disk guid\n");
+               if ((ret == -3) || (ret == -4))
+                       printf("Partition list incomplete\n");
+               return -1;
+       }
+
+       /* save partitions layout to disk */
+       gpt_restore(&mmc->block_dev, str_disk_guid, partitions, part_count);
+       free(str_disk_guid);
+       free(partitions);
+
+       return 0;
+}
+
+/**
+ * do_gpt(): Perform GPT operations
+ *
+ * @param cmdtp - command name
+ * @param flag
+ * @param argc
+ * @param argv
+ *
+ * @return zero on success; otherwise error
+ */
+static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       int ret = CMD_RET_SUCCESS;
+       int dev = 0;
+       char *pstr;
+
+       if (argc < 5)
+               return CMD_RET_USAGE;
+
+       /* command: 'write' */
+       if ((strcmp(argv[1], "write") == 0) && (argc == 5)) {
+               /* device: 'mmc' */
+               if (strcmp(argv[2], "mmc") == 0) {
+                       /* check if 'dev' is a number */
+                       for (pstr = argv[3]; *pstr != '\0'; pstr++)
+                               if (!isdigit(*pstr)) {
+                                       printf("'%s' is not a number\n",
+                                               argv[3]);
+                                       return CMD_RET_USAGE;
+                               }
+                       dev = (int)simple_strtoul(argv[3], NULL, 10);
+                       /* write to mmc */
+                       if (gpt_mmc_default(dev, argv[4]))
+                               return CMD_RET_FAILURE;
+               }
+       } else {
+               return CMD_RET_USAGE;
+       }
+       return ret;
+}
+
+U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
+       "GUID Partition Table",
+       "<command> <interface> <dev> <partions_list>\n"
+       " - GUID partition table restoration\n"
+       " Restore GPT information on a device connected\n"
+       " to interface\n"
+);
diff --git a/common/cmd_hash.c b/common/cmd_hash.c
new file mode 100644 (file)
index 0000000..689c608
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * (C) Copyright 2011
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@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.
+ *
+ * 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 <hash.h>
+
+static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+#ifdef CONFIG_HASH_VERIFY
+       int verify = 0;
+
+       if (!strcmp(argv[1], "-v")) {
+               verify = 1;
+               argc--;
+               argv++;
+       }
+#endif
+       /* Move forward to 'algorithm' parameter */
+       argc--;
+       argv++;
+       return hash_command(*argv, verify, cmdtp, flag, argc - 1, argv + 1);
+}
+
+#ifdef CONFIG_HASH_VERIFY
+U_BOOT_CMD(
+       hash,   6,      1,      do_hash,
+       "compute hash message digest",
+       "algorithm address count [[*]sum_dest]\n"
+               "    - compute message digest [save to env var / *address]\n"
+       "hash -v algorithm address count [*]sum\n"
+               "    - verify hash of memory area with env var / *address"
+);
+#else
+U_BOOT_CMD(
+       hash,   5,      1,      do_hash,
+       "compute message digest",
+       "algorithm address count [[*]sum_dest]\n"
+               "    - compute message digest [save to env var / *address]"
+);
+#endif
index 4438db594cfe007efc8f79e1882acfd6b42133c5..438079447479773abab4b615894a0d69c9a216b4 100644 (file)
 
 #include <common.h>
 #include <command.h>
+#include <edid.h>
 #include <environment.h>
 #include <i2c.h>
 #include <malloc.h>
 #include <asm/byteorder.h>
+#include <linux/compiler.h>
 
 /* Display values from last command.
  * Memory modify remembered values are different from display memory.
@@ -132,35 +134,65 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define DISP_LINE_LEN  16
 
-/* implement possible board specific board init */
-static void __def_i2c_init_board(void)
+/**
+ * i2c_init_board() - Board-specific I2C bus init
+ *
+ * This function is the default no-op implementation of I2C bus
+ * initialization. This function can be overriden by board-specific
+ * implementation if needed.
+ */
+__weak
+void i2c_init_board(void)
 {
        return;
 }
-void i2c_init_board(void)
-       __attribute__((weak, alias("__def_i2c_init_board")));
 
 /* TODO: Implement architecture-specific get/set functions */
-static unsigned int __def_i2c_get_bus_speed(void)
+
+/**
+ * i2c_get_bus_speed() - Return I2C bus speed
+ *
+ * This function is the default implementation of function for retrieveing
+ * the current I2C bus speed in Hz.
+ *
+ * A driver implementing runtime switching of I2C bus speed must override
+ * this function to report the speed correctly. Simple or legacy drivers
+ * can use this fallback.
+ *
+ * Returns I2C bus speed in Hz.
+ */
+__weak
+unsigned int i2c_get_bus_speed(void)
 {
        return CONFIG_SYS_I2C_SPEED;
 }
-unsigned int i2c_get_bus_speed(void)
-       __attribute__((weak, alias("__def_i2c_get_bus_speed")));
 
-static int __def_i2c_set_bus_speed(unsigned int speed)
+/**
+ * i2c_set_bus_speed() - Configure I2C bus speed
+ * @speed:     Newly set speed of the I2C bus in Hz
+ *
+ * This function is the default implementation of function for setting
+ * the I2C bus speed in Hz.
+ *
+ * A driver implementing runtime switching of I2C bus speed must override
+ * this function to report the speed correctly. Simple or legacy drivers
+ * can use this fallback.
+ *
+ * Returns zero on success, negative value on error.
+ */
+__weak
+int i2c_set_bus_speed(unsigned int speed)
 {
        if (speed != CONFIG_SYS_I2C_SPEED)
                return -1;
 
        return 0;
 }
-int i2c_set_bus_speed(unsigned int)
-       __attribute__((weak, alias("__def_i2c_set_bus_speed")));
 
-/*
- * get_alen: small parser helper function to get address length
- * returns the address length
+/**
+ * get_alen() - Small parser helper function to get address length
+ *
+ * Returns the address length.
  */
 static uint get_alen(char *arg)
 {
@@ -178,11 +210,19 @@ static uint get_alen(char *arg)
        return alen;
 }
 
-/*
+/**
+ * do_i2c_read() - Handle the "i2c read" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
  * Syntax:
  *     i2c read {i2c_chip} {devaddr}{.0, .1, .2} {len} {memaddr}
  */
-
 static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        u_char  chip;
@@ -271,7 +311,16 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
        return 0;
 }
 
-/*
+/**
+ * do_i2c_md() - Handle the "i2c md" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
  * Syntax:
  *     i2c md {i2c_chip} {addr}{.0, .1, .2} {len}
  */
@@ -363,8 +412,15 @@ static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
        return 0;
 }
 
-
-/* Write (fill) memory
+/**
+ * do_i2c_mw() - Handle the "i2c mw" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
  *
  * Syntax:
  *     i2c mw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}]
@@ -421,10 +477,20 @@ static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 #endif
        }
 
-       return (0);
+       return 0;
 }
 
-/* Calculate a CRC on memory
+/**
+ * do_i2c_crc() - Handle the "i2c crc32" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Calculate a CRC on memory
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
  *
  * Syntax:
  *     i2c crc32 {i2c_chip} {addr}{.0, .1, .2} {count}
@@ -481,13 +547,22 @@ static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
        return 0;
 }
 
-/* Modify memory.
+/**
+ * mod_i2c_mem() - Handle the "i2c mm" and "i2c nm" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Modify memory.
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
  *
  * Syntax:
  *     i2c mm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
  *     i2c nm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
  */
-
 static int
 mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
 {
@@ -603,7 +678,16 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg
        return 0;
 }
 
-/*
+/**
+ * do_i2c_probe() - Handle the "i2c probe" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
  * Syntax:
  *     i2c probe {addr}
  *
@@ -657,7 +741,16 @@ static int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
        return (0 == found);
 }
 
-/*
+/**
+ * do_i2c_loop() - Handle the "i2c loop" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
  * Syntax:
  *     i2c loop {i2c_chip} {addr}{.0, .1, .2} [{length}] [{delay}]
  *     {length} - Number of bytes to read
@@ -718,6 +811,8 @@ static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
 /*
  * The SDRAM command is separately configured because many
  * (most?) embedded boards don't use SDRAM DIMMs.
+ *
+ * FIXME: Document and probably move elsewhere!
  */
 #if defined(CONFIG_CMD_SDRAM)
 static void print_ddr2_tcyc (u_char const b)
@@ -1246,7 +1341,48 @@ static int do_sdram (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 }
 #endif
 
+/*
+ * Syntax:
+ *     i2c edid {i2c_chip}
+ */
+#if defined(CONFIG_I2C_EDID)
+int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       u_char chip;
+       struct edid1_info edid;
+
+       if (argc < 2) {
+               cmd_usage(cmdtp);
+               return 1;
+       }
+
+       chip = simple_strtoul(argv[1], NULL, 16);
+       if (i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) {
+               puts("Error reading EDID content.\n");
+               return 1;
+       }
+
+       if (edid_check_info(&edid)) {
+               puts("Content isn't valid EDID.\n");
+               return 1;
+       }
+
+       edid_print_info(&edid);
+       return 0;
+
+}
+#endif /* CONFIG_I2C_EDID */
+
 #if defined(CONFIG_I2C_MUX)
+/**
+ * do_i2c_add_bus() - Handle the "i2c bus" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero always.
+ */
 static int do_i2c_add_bus(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
        int ret=0;
@@ -1276,6 +1412,16 @@ static int do_i2c_add_bus(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar
 #endif  /* CONFIG_I2C_MUX */
 
 #if defined(CONFIG_I2C_MULTI_BUS)
+/**
+ * do_i2c_bus_num() - Handle the "i2c dev" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
 static int do_i2c_bus_num(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
        int bus_idx, ret=0;
@@ -1294,6 +1440,16 @@ static int do_i2c_bus_num(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar
 }
 #endif  /* CONFIG_I2C_MULTI_BUS */
 
+/**
+ * do_i2c_bus_speed() - Handle the "i2c speed" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
 static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
        int speed, ret=0;
@@ -1311,16 +1467,45 @@ static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const
        return ret;
 }
 
+/**
+ * do_i2c_mm() - Handle the "i2c mm" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
 static int do_i2c_mm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
        return mod_i2c_mem (cmdtp, 1, flag, argc, argv);
 }
 
+/**
+ * do_i2c_nm() - Handle the "i2c nm" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
 static int do_i2c_nm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
        return mod_i2c_mem (cmdtp, 0, flag, argc, argv);
 }
 
+/**
+ * do_i2c_reset() - Handle the "i2c reset" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero always.
+ */
 static int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
        i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
@@ -1335,6 +1520,9 @@ static cmd_tbl_t cmd_i2c_sub[] = {
 #if defined(CONFIG_I2C_MULTI_BUS)
        U_BOOT_CMD_MKENT(dev, 1, 1, do_i2c_bus_num, "", ""),
 #endif  /* CONFIG_I2C_MULTI_BUS */
+#if defined(CONFIG_I2C_EDID)
+       U_BOOT_CMD_MKENT(edid, 1, 1, do_edid, "", ""),
+#endif  /* CONFIG_I2C_EDID */
        U_BOOT_CMD_MKENT(loop, 3, 1, do_i2c_loop, "", ""),
        U_BOOT_CMD_MKENT(md, 3, 1, do_i2c_md, "", ""),
        U_BOOT_CMD_MKENT(mm, 2, 1, do_i2c_mm, "", ""),
@@ -1356,6 +1544,16 @@ void i2c_reloc(void) {
 }
 #endif
 
+/**
+ * do_i2c() - Handle the "i2c" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
 static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
        cmd_tbl_t *c;
@@ -1385,6 +1583,9 @@ static char i2c_help_text[] =
 #if defined(CONFIG_I2C_MULTI_BUS)
        "i2c dev [dev] - show or set current I2C bus\n"
 #endif  /* CONFIG_I2C_MULTI_BUS */
+#if defined(CONFIG_I2C_EDID)
+       "i2c edid chip - print EDID configuration information\n"
+#endif  /* CONFIG_I2C_EDID */
        "i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device\n"
        "i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device\n"
        "i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)\n"
diff --git a/common/cmd_io.c b/common/cmd_io.c
new file mode 100644 (file)
index 0000000..6450cb5
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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
+ */
+
+/*
+ * IO space access commands.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+
+/*
+ * IO Display
+ *
+ * Syntax:
+ *     iod{.b, .w, .l} {addr}
+ */
+int do_io_iod(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       ulong addr;
+       int size;
+
+       if (argc != 2)
+               return CMD_RET_USAGE;
+
+       size = cmd_get_data_size(argv[0], 4);
+       if (size < 0)
+               return 1;
+
+       addr = simple_strtoul(argv[1], NULL, 16);
+
+       printf("%04x: ", (u16) addr);
+
+       if (size == 4)
+               printf("%08x\n", inl(addr));
+       else if (size == 2)
+               printf("%04x\n", inw(addr));
+       else
+               printf("%02x\n", inb(addr));
+
+       return 0;
+}
+
+int do_io_iow(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       ulong addr, size, val;
+
+       if (argc != 3)
+               return CMD_RET_USAGE;
+
+       size = cmd_get_data_size(argv[0], 4);
+       if (size < 0)
+               return 1;
+
+       addr = simple_strtoul(argv[1], NULL, 16);
+       val = simple_strtoul(argv[2], NULL, 16);
+
+       if (size == 4)
+               outl((u32) val, addr);
+       else if (size == 2)
+               outw((u16) val, addr);
+       else
+               outb((u8) val, addr);
+
+       return 0;
+}
+
+/**************************************************/
+U_BOOT_CMD(iod, 2, 0, do_io_iod,
+          "IO space display", "[.b, .w, .l] address [# of objects]");
+
+U_BOOT_CMD(iow, 3, 0, do_io_iow,
+          "IO space modify (auto-incrementing address)",
+          "[.b, .w, .l] address");
index 006131f45c1b20b793a9ced9bdc95383043a87e9..7633f0c44a7e3ecb4c8828fbb62af4ede1d9fa21 100644 (file)
 #include <errno.h>
 #include <malloc.h>
 #include <watchdog.h>
-#include <serial.h>
 #include <linux/stddef.h>
 #include <asm/byteorder.h>
-#if defined(CONFIG_CMD_NET)
-#include <net.h>
-#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -76,16 +72,6 @@ SPI_FLASH|NVRAM|MMC|FAT|REMOTE} or CONFIG_ENV_IS_NOWHERE
  */
 #define        MAX_ENV_SIZE    (1 << 20)       /* 1 MiB */
 
-ulong load_addr = CONFIG_SYS_LOAD_ADDR;        /* Default Load Address */
-ulong save_addr;                       /* Default Save Address */
-ulong save_size;                       /* Default Save Size (in bytes) */
-
-/*
- * 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]))
-
 /*
  * This variable is incremented on each do_env_set(), so it can
  * be used via get_env_id() as an indication, if the environment
@@ -106,7 +92,7 @@ int get_env_id(void)
  *
  * Returns 0 in case of error, or length of printed string
  */
-static int env_print(char *name)
+static int env_print(char *name, int flag)
 {
        char *res = NULL;
        size_t len;
@@ -116,7 +102,7 @@ static int env_print(char *name)
 
                e.key = name;
                e.data = NULL;
-               hsearch_r(e, FIND, &ep, &env_htab);
+               hsearch_r(e, FIND, &ep, &env_htab, flag);
                if (ep == NULL)
                        return 0;
                len = printf("%s=%s\n", ep->key, ep->data);
@@ -124,7 +110,7 @@ static int env_print(char *name)
        }
 
        /* print whole list */
-       len = hexport_r(&env_htab, '\n', &res, 0, 0, NULL);
+       len = hexport_r(&env_htab, '\n', flag, &res, 0, 0, NULL);
 
        if (len > 0) {
                puts(res);
@@ -141,10 +127,17 @@ static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc,
 {
        int i;
        int rcode = 0;
+       int env_flag = H_HIDE_DOT;
+
+       if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'a') {
+               argc--;
+               argv++;
+               env_flag &= ~H_HIDE_DOT;
+       }
 
        if (argc == 1) {
                /* print all env vars */
-               rcode = env_print(NULL);
+               rcode = env_print(NULL, env_flag);
                if (!rcode)
                        return 1;
                printf("\nEnvironment size: %d/%ld bytes\n",
@@ -153,8 +146,9 @@ static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc,
        }
 
        /* print selected env vars */
+       env_flag &= ~H_HIDE_DOT;
        for (i = 1; i < argc; ++i) {
-               int rc = env_print(argv[i]);
+               int rc = env_print(argv[i], env_flag);
                if (!rc) {
                        printf("## Error: \"%s\" not defined\n", argv[i]);
                        ++rcode;
@@ -197,138 +191,33 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 #endif
 #endif /* CONFIG_SPL_BUILD */
 
-/*
- * Perform consistency checking before setting, replacing, or deleting an
- * environment variable, then (if successful) apply the changes to internals so
- * to make them effective.  Code for this function was taken out of
- * _do_env_set(), which now calls it instead.
- * Also called as a callback function by himport_r().
- * Returns 0 in case of success, 1 in case of failure.
- * When (flag & H_FORCE) is set, do not print out any error message and force
- * overwriting of write-once variables.
- */
-
-int env_check_apply(const char *name, const char *oldval,
-                       const char *newval, int flag)
-{
-       int   console = -1;
-
-       /* Default value for NULL to protect string-manipulating functions */
-       newval = newval ? : "";
-
-       /* Check for console redirection */
-       if (strcmp(name, "stdin") == 0)
-               console = stdin;
-       else if (strcmp(name, "stdout") == 0)
-               console = stdout;
-       else if (strcmp(name, "stderr") == 0)
-               console = stderr;
-
-       if (console != -1) {
-               if ((newval == NULL) || (*newval == '\0')) {
-                       /* We cannot delete stdin/stdout/stderr */
-                       if ((flag & H_FORCE) == 0)
-                               printf("Can't delete \"%s\"\n", name);
-                       return 1;
-               }
-
-#ifdef CONFIG_CONSOLE_MUX
-               if (iomux_doenv(console, newval))
-                       return 1;
-#else
-               /* Try assigning specified device */
-               if (console_assign(console, newval) < 0)
-                       return 1;
-#endif /* CONFIG_CONSOLE_MUX */
-       }
-
-       /*
-        * Some variables like "ethaddr" and "serial#" can be set only once and
-        * cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined.
-        */
-#ifndef CONFIG_ENV_OVERWRITE
-       if (oldval != NULL &&                   /* variable exists */
-               (flag & H_FORCE) == 0) {        /* and we are not forced */
-               if (strcmp(name, "serial#") == 0 ||
-                   (strcmp(name, "ethaddr") == 0
-#if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
-                    && strcmp(oldval, __stringify(CONFIG_ETHADDR)) != 0
-#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
-                       )) {
-                       printf("Can't overwrite \"%s\"\n", name);
-                       return 1;
-               }
-       }
-#endif
-       /*
-        * When we change baudrate, or we are doing an env default -a
-        * (which will erase all variables prior to calling this),
-        * we want the baudrate to actually change - for real.
-        */
-       if (oldval != NULL ||                   /* variable exists */
-               (flag & H_NOCLEAR) == 0) {      /* or env is clear */
-               /*
-                * Switch to new baudrate if new baudrate is supported
-                */
-               if (strcmp(name, "baudrate") == 0) {
-                       int baudrate = simple_strtoul(newval, NULL, 10);
-                       int i;
-                       for (i = 0; i < N_BAUDRATES; ++i) {
-                               if (baudrate == baudrate_table[i])
-                                       break;
-                       }
-                       if (i == N_BAUDRATES) {
-                               if ((flag & H_FORCE) == 0)
-                                       printf("## Baudrate %d bps not "
-                                               "supported\n", baudrate);
-                               return 1;
-                       }
-                       if (gd->baudrate == baudrate) {
-                               /* If unchanged, we just say it's OK */
-                               return 0;
-                       }
-                       printf("## Switch baudrate to %d bps and"
-                               "press ENTER ...\n", baudrate);
-                       udelay(50000);
-                       gd->baudrate = baudrate;
-#if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
-                       gd->bd->bi_baudrate = baudrate;
-#endif
-
-                       serial_setbrg();
-                       udelay(50000);
-                       while (getc() != '\r')
-                               ;
-               }
-       }
-
-       /*
-        * Some variables should be updated when the corresponding
-        * entry in the environment is changed
-        */
-       if (strcmp(name, "loadaddr") == 0) {
-               load_addr = simple_strtoul(newval, NULL, 16);
-               return 0;
-       }
-#if defined(CONFIG_CMD_NET)
-       else if (strcmp(name, "bootfile") == 0) {
-               copy_filename(BootFile, newval, sizeof(BootFile));
-               return 0;
-       }
-#endif
-       return 0;
-}
-
 /*
  * Set a new environment variable,
  * or replace or delete an existing one.
-*/
+ */
 static int _do_env_set(int flag, int argc, char * const argv[])
 {
        int   i, len;
        char  *name, *value, *s;
        ENTRY e, *ep;
+       int env_flag = H_INTERACTIVE;
+
+       debug("Initial value for argc=%d\n", argc);
+       while (argc > 1 && **(argv + 1) == '-') {
+               char *arg = *++argv;
 
+               --argc;
+               while (*++arg) {
+                       switch (*arg) {
+                       case 'f':               /* force */
+                               env_flag |= H_FORCE;
+                               break;
+                       default:
+                               return CMD_RET_USAGE;
+                       }
+               }
+       }
+       debug("Final value for argc=%d\n", argc);
        name = argv[1];
        value = argv[2];
 
@@ -339,25 +228,10 @@ static int _do_env_set(int flag, int argc, char * const argv[])
        }
 
        env_id++;
-       /*
-        * search if variable with this name already exists
-        */
-       e.key = name;
-       e.data = NULL;
-       hsearch_r(e, FIND, &ep, &env_htab);
-
-       /*
-        * Perform requested checks. Notice how since we are overwriting
-        * a single variable, we need to set H_NOCLEAR
-        */
-       if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
-               debug("check function did not approve, refusing\n");
-               return 1;
-       }
 
        /* Delete only ? */
        if (argc < 3 || argv[2] == NULL) {
-               int rc = hdelete_r(name, &env_htab, 0);
+               int rc = hdelete_r(name, &env_htab, env_flag);
                return !rc;
        }
 
@@ -384,7 +258,7 @@ static int _do_env_set(int flag, int argc, char * const argv[])
 
        e.key   = name;
        e.data  = value;
-       hsearch_r(e, ENTER, &ep, &env_htab);
+       hsearch_r(e, ENTER, &ep, &env_htab, env_flag);
        free(value);
        if (!ep) {
                printf("## Error inserting \"%s\" variable, errno=%d\n",
@@ -511,6 +385,153 @@ int do_env_ask(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 }
 #endif
 
+#if defined(CONFIG_CMD_ENV_CALLBACK)
+static int print_static_binding(const char *var_name, const char *callback_name)
+{
+       printf("\t%-20s %-20s\n", var_name, callback_name);
+
+       return 0;
+}
+
+static int print_active_callback(ENTRY *entry)
+{
+       struct env_clbk_tbl *clbkp;
+       int i;
+       int num_callbacks;
+
+       if (entry->callback == NULL)
+               return 0;
+
+       /* look up the callback in the linker-list */
+       num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
+       for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
+            i < num_callbacks;
+            i++, clbkp++) {
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+               if (entry->callback == clbkp->callback + gd->reloc_off)
+#else
+               if (entry->callback == clbkp->callback)
+#endif
+                       break;
+       }
+
+       if (i == num_callbacks)
+               /* this should probably never happen, but just in case... */
+               printf("\t%-20s %p\n", entry->key, entry->callback);
+       else
+               printf("\t%-20s %-20s\n", entry->key, clbkp->name);
+
+       return 0;
+}
+
+/*
+ * Print the callbacks available and what they are bound to
+ */
+int do_env_callback(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       struct env_clbk_tbl *clbkp;
+       int i;
+       int num_callbacks;
+
+       /* Print the available callbacks */
+       puts("Available callbacks:\n");
+       puts("\tCallback Name\n");
+       puts("\t-------------\n");
+       num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
+       for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
+            i < num_callbacks;
+            i++, clbkp++)
+               printf("\t%s\n", clbkp->name);
+       puts("\n");
+
+       /* Print the static bindings that may exist */
+       puts("Static callback bindings:\n");
+       printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
+       printf("\t%-20s %-20s\n", "-------------", "-------------");
+       env_attr_walk(ENV_CALLBACK_LIST_STATIC, print_static_binding);
+       puts("\n");
+
+       /* walk through each variable and print the callback if it has one */
+       puts("Active callback bindings:\n");
+       printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
+       printf("\t%-20s %-20s\n", "-------------", "-------------");
+       hwalk_r(&env_htab, print_active_callback);
+       return 0;
+}
+#endif
+
+#if defined(CONFIG_CMD_ENV_FLAGS)
+static int print_static_flags(const char *var_name, const char *flags)
+{
+       enum env_flags_vartype type = env_flags_parse_vartype(flags);
+       enum env_flags_varaccess access = env_flags_parse_varaccess(flags);
+
+       printf("\t%-20s %-20s %-20s\n", var_name,
+               env_flags_get_vartype_name(type),
+               env_flags_get_varaccess_name(access));
+
+       return 0;
+}
+
+static int print_active_flags(ENTRY *entry)
+{
+       enum env_flags_vartype type;
+       enum env_flags_varaccess access;
+
+       if (entry->flags == 0)
+               return 0;
+
+       type = (enum env_flags_vartype)
+               (entry->flags & ENV_FLAGS_VARTYPE_BIN_MASK);
+       access = env_flags_parse_varaccess_from_binflags(entry->flags);
+       printf("\t%-20s %-20s %-20s\n", entry->key,
+               env_flags_get_vartype_name(type),
+               env_flags_get_varaccess_name(access));
+
+       return 0;
+}
+
+/*
+ * Print the flags available and what variables have flags
+ */
+int do_env_flags(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       /* Print the available variable types */
+       printf("Available variable type flags (position %d):\n",
+               ENV_FLAGS_VARTYPE_LOC);
+       puts("\tFlag\tVariable Type Name\n");
+       puts("\t----\t------------------\n");
+       env_flags_print_vartypes();
+       puts("\n");
+
+       /* Print the available variable access types */
+       printf("Available variable access flags (position %d):\n",
+               ENV_FLAGS_VARACCESS_LOC);
+       puts("\tFlag\tVariable Access Name\n");
+       puts("\t----\t--------------------\n");
+       env_flags_print_varaccess();
+       puts("\n");
+
+       /* Print the static flags that may exist */
+       puts("Static flags:\n");
+       printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
+               "Variable Access");
+       printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
+               "---------------");
+       env_attr_walk(ENV_FLAGS_LIST_STATIC, print_static_flags);
+       puts("\n");
+
+       /* walk through each variable and print the flags if non-default */
+       puts("Active flags:\n");
+       printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
+               "Variable Access");
+       printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
+               "---------------");
+       hwalk_r(&env_htab, print_active_flags);
+       return 0;
+}
+#endif
+
 /*
  * Interactively edit an environment variable
  */
@@ -552,7 +573,7 @@ char *getenv(const char *name)
 
                e.key   = name;
                e.data  = NULL;
-               hsearch_r(e, FIND, &ep, &env_htab);
+               hsearch_r(e, FIND, &ep, &env_htab, 0);
 
                return ep ? ep->data : NULL;
        }
@@ -704,8 +725,36 @@ static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
 static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
                         int argc, char * const argv[])
 {
-       printf("Not implemented yet\n");
-       return 0;
+       int env_flag = H_INTERACTIVE;
+       int ret = 0;
+
+       debug("Initial value for argc=%d\n", argc);
+       while (argc > 1 && **(argv + 1) == '-') {
+               char *arg = *++argv;
+
+               --argc;
+               while (*++arg) {
+                       switch (*arg) {
+                       case 'f':               /* force */
+                               env_flag |= H_FORCE;
+                               break;
+                       default:
+                               return CMD_RET_USAGE;
+                       }
+               }
+       }
+       debug("Final value for argc=%d\n", argc);
+
+       env_id++;
+
+       while (--argc > 0) {
+               char *name = *++argv;
+
+               if (!hdelete_r(name, &env_htab, env_flag))
+                       ret = 1;
+       }
+
+       return ret;
 }
 
 #ifdef CONFIG_CMD_EXPORTENV
@@ -812,7 +861,7 @@ NXTARG:             ;
        argv++;
 
        if (sep) {              /* export as text file */
-               len = hexport_r(&env_htab, sep, &addr, size, argc, argv);
+               len = hexport_r(&env_htab, sep, 0, &addr, size, argc, argv);
                if (len < 0) {
                        error("Cannot export environment: errno = %d\n", errno);
                        return 1;
@@ -830,7 +879,7 @@ NXTARG:             ;
        else                    /* export as raw binary data */
                res = addr;
 
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, argc, argv);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, argc, argv);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
@@ -951,7 +1000,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
        }
 
        if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
-                       0, NULL, 0 /* do_apply */) == 0) {
+                       0, NULL) == 0) {
                error("Environment import failed: errno = %d\n", errno);
                return 1;
        }
@@ -974,10 +1023,16 @@ static cmd_tbl_t cmd_env_sub[] = {
        U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""),
 #endif
        U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""),
-       U_BOOT_CMD_MKENT(delete, 2, 0, do_env_delete, "", ""),
+       U_BOOT_CMD_MKENT(delete, CONFIG_SYS_MAXARGS, 0, do_env_delete, "", ""),
 #if defined(CONFIG_CMD_EDITENV)
        U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""),
 #endif
+#if defined(CONFIG_CMD_ENV_CALLBACK)
+       U_BOOT_CMD_MKENT(callbacks, 1, 0, do_env_callback, "", ""),
+#endif
+#if defined(CONFIG_CMD_ENV_FLAGS)
+       U_BOOT_CMD_MKENT(flags, 1, 0, do_env_flags, "", ""),
+#endif
 #if defined(CONFIG_CMD_EXPORTENV)
        U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""),
 #endif
@@ -1027,22 +1082,29 @@ static int do_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 static char env_help_text[] =
 #if defined(CONFIG_CMD_ASKENV)
        "ask name [message] [size] - ask for environment variable\nenv "
+#endif
+#if defined(CONFIG_CMD_ENV_CALLBACK)
+       "callbacks - print callbacks and their associated variables\nenv "
 #endif
        "default [-f] -a - [forcibly] reset default environment\n"
        "env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
+       "env delete [-f] var [...] - [forcibly] delete variable(s)\n"
 #if defined(CONFIG_CMD_EDITENV)
        "env edit name - edit environment variable\n"
 #endif
 #if defined(CONFIG_CMD_EXPORTENV)
        "env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n"
 #endif
+#if defined(CONFIG_CMD_ENV_FLAGS)
+       "env flags - print variables that have non-default flags\n"
+#endif
 #if defined(CONFIG_CMD_GREPENV)
        "env grep string [...] - search environment\n"
 #endif
 #if defined(CONFIG_CMD_IMPORTENV)
        "env import [-d] [-t | -b | -c] addr [size] - import environment\n"
 #endif
-       "env print [name ...] - print environment\n"
+       "env print [-a | name ...] - print environment\n"
 #if defined(CONFIG_CMD_RUN)
        "env run var [...] - run commands in an environment variable\n"
 #endif
@@ -1074,7 +1136,7 @@ U_BOOT_CMD_COMPLETE(
 U_BOOT_CMD_COMPLETE(
        printenv, CONFIG_SYS_MAXARGS, 1,        do_env_print,
        "print environment variables",
-       "\n    - print values of all environment variables\n"
+       "[-a]\n    - print [all] values of all environment variables\n"
        "printenv name ...\n"
        "    - print value of environment variable 'name'",
        var_complete
@@ -1093,10 +1155,10 @@ U_BOOT_CMD_COMPLETE(
 U_BOOT_CMD_COMPLETE(
        setenv, CONFIG_SYS_MAXARGS, 0,  do_env_set,
        "set environment variables",
-       "name value ...\n"
-       "    - set environment variable 'name' to 'value ...'\n"
-       "setenv name\n"
-       "    - delete environment variable 'name'",
+       "[-f] name value ...\n"
+       "    - [forcibly] set environment variable 'name' to 'value ...'\n"
+       "setenv [-f] name\n"
+       "    - [forcibly] delete environment variable 'name'",
        var_complete
 );
 
diff --git a/common/cmd_read.c b/common/cmd_read.c
new file mode 100644 (file)
index 0000000..f0fc9bf
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 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.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <part.h>
+
+int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       char *ep;
+       block_dev_desc_t *dev_desc = NULL;
+       int dev;
+       int part = 0;
+       disk_partition_t part_info;
+       ulong offset = 0u;
+       ulong limit = 0u;
+       void *addr;
+       uint blk;
+       uint cnt;
+
+       if (argc != 6) {
+               cmd_usage(cmdtp);
+               return 1;
+       }
+
+       dev = (int)simple_strtoul(argv[2], &ep, 16);
+       if (*ep) {
+               if (*ep != ':') {
+                       printf("Invalid block device %s\n", argv[2]);
+                       return 1;
+               }
+               part = (int)simple_strtoul(++ep, NULL, 16);
+       }
+
+       dev_desc = get_dev(argv[1], dev);
+       if (dev_desc == NULL) {
+               printf("Block device %s %d not supported\n", argv[1], dev);
+               return 1;
+       }
+
+       addr = (void *)simple_strtoul(argv[3], NULL, 16);
+       blk = simple_strtoul(argv[4], NULL, 16);
+       cnt = simple_strtoul(argv[5], NULL, 16);
+
+       if (part != 0) {
+               if (get_partition_info(dev_desc, part, &part_info)) {
+                       printf("Cannot find partition %d\n", part);
+                       return 1;
+               }
+               offset = part_info.start;
+               limit = part_info.size;
+       } else {
+               /* Largest address not available in block_dev_desc_t. */
+               limit = ~0;
+       }
+
+       if (cnt + blk > limit) {
+               printf("Read out of range\n");
+               return 1;
+       }
+
+       if (dev_desc->block_read(dev, offset + blk, cnt, addr) < 0) {
+               printf("Error reading blocks\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       read,   6,      0,      do_read,
+       "Load binary data from a partition",
+       "<interface> <dev[:part]> addr blk# cnt"
+);
index 8db5456c9583ec8cf6b927f9760a748d72f4f1ed..fe927ab248f3fa3aafdc0dbbc1b974f78cef798c 100644 (file)
 
 #include <common.h>
 #include <command.h>
+#include <hash.h>
 #include <sha1.h>
 
-/*
- * Store the resulting sum to an address or variable
- */
-static void store_result(const u8 *sum, const char *dest)
-{
-       unsigned int i;
-
-       if (*dest == '*') {
-               u8 *ptr;
-
-               ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16);
-               for (i = 0; i < 20; i++)
-                       *ptr++ = sum[i];
-       } else {
-               char str_output[41];
-               char *str_ptr = str_output;
-
-               for (i = 0; i < 20; i++) {
-                       sprintf(str_ptr, "%02x", sum[i]);
-                       str_ptr += 2;
-               }
-               str_ptr = '\0';
-               setenv(dest, str_output);
-       }
-}
-
-#ifdef CONFIG_SHA1SUM_VERIFY
-static int parse_verify_sum(char *verify_str, u8 *vsum)
-{
-       if (*verify_str == '*') {
-               u8 *ptr;
-
-               ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16);
-               memcpy(vsum, ptr, 20);
-       } else {
-               unsigned int i;
-               char *vsum_str;
-
-               if (strlen(verify_str) == 40)
-                       vsum_str = verify_str;
-               else {
-                       vsum_str = getenv(verify_str);
-                       if (vsum_str == NULL || strlen(vsum_str) != 40)
-                               return 1;
-               }
-
-               for (i = 0; i < 20; i++) {
-                       char *nullp = vsum_str + (i + 1) * 2;
-                       char end = *nullp;
-
-                       *nullp = '\0';
-                       *(u8 *)(vsum + i) =
-                               simple_strtoul(vsum_str + (i * 2), NULL, 16);
-                       *nullp = end;
-               }
-       }
-       return 0;
-}
-
 int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       ulong addr, len;
-       unsigned int i;
-       u8 output[20];
-       u8 vsum[20];
        int verify = 0;
        int ac;
        char * const *av;
@@ -102,75 +40,16 @@ int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        av = argv + 1;
        ac = argc - 1;
+#ifdef CONFIG_SHA1SUM_VERIFY
        if (strcmp(*av, "-v") == 0) {
                verify = 1;
                av++;
                ac--;
-               if (ac < 3)
-                       return CMD_RET_USAGE;
        }
+#endif
 
-       addr = simple_strtoul(*av++, NULL, 16);
-       len = simple_strtoul(*av++, NULL, 16);
-
-       sha1_csum_wd((unsigned char *) addr, len, output, CHUNKSZ_SHA1);
-
-       if (!verify) {
-               printf("SHA1 for %08lx ... %08lx ==> ", addr, addr + len - 1);
-               for (i = 0; i < 20; i++)
-                       printf("%02x", output[i]);
-               printf("\n");
-
-               if (ac > 2)
-                       store_result(output, *av);
-       } else {
-               char *verify_str = *av++;
-
-               if (parse_verify_sum(verify_str, vsum)) {
-                       printf("ERROR: %s does not contain a valid SHA1 sum\n",
-                               verify_str);
-                       return 1;
-               }
-               if (memcmp(output, vsum, 20) != 0) {
-                       printf("SHA1 for %08lx ... %08lx ==> ", addr,
-                               addr + len - 1);
-                       for (i = 0; i < 20; i++)
-                               printf("%02x", output[i]);
-                       printf(" != ");
-                       for (i = 0; i < 20; i++)
-                               printf("%02x", vsum[i]);
-                       printf(" ** ERROR **\n");
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-#else
-static int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-       unsigned long addr, len;
-       unsigned int i;
-       u8 output[20];
-
-       if (argc < 3)
-               return CMD_RET_USAGE;
-
-       addr = simple_strtoul(argv[1], NULL, 16);
-       len = simple_strtoul(argv[2], NULL, 16);
-
-       sha1_csum_wd((unsigned char *) addr, len, output, CHUNKSZ_SHA1);
-       printf("SHA1 for %08lx ... %08lx ==> ", addr, addr + len - 1);
-       for (i = 0; i < 20; i++)
-               printf("%02x", output[i]);
-       printf("\n");
-
-       if (argc > 3)
-               store_result(output, argv[3]);
-
-       return 0;
+       return hash_command("sha1", verify, cmdtp, flag, ac, av);
 }
-#endif
 
 #ifdef CONFIG_SHA1SUM_VERIFY
 U_BOOT_CMD(
diff --git a/common/cmd_sound.c b/common/cmd_sound.c
new file mode 100644 (file)
index 0000000..459d1eb
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Rajeshwari Shinde <rajeshwari.s@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 <command.h>
+#include <fdtdec.h>
+#include <sound.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Initilaise sound subsystem */
+static int do_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       int ret;
+
+       ret = sound_init();
+       if (ret) {
+               printf("Initialise Audio driver failed\n");
+               return CMD_RET_FAILURE;
+       }
+
+       return 0;
+}
+
+/* play sound from buffer */
+static int do_play(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       int ret = 0;
+       int msec = 1000;
+       int freq = 400;
+
+       if (argc > 1)
+               msec = simple_strtoul(argv[1], NULL, 10);
+       if (argc > 2)
+               freq = simple_strtoul(argv[2], NULL, 10);
+
+       ret = sound_play(msec, freq);
+       if (ret) {
+               printf("play failed");
+               return CMD_RET_FAILURE;
+       }
+
+       return 0;
+}
+
+static cmd_tbl_t cmd_sound_sub[] = {
+       U_BOOT_CMD_MKENT(init, 0, 1, do_init, "", ""),
+       U_BOOT_CMD_MKENT(play, 2, 1, do_play, "", ""),
+};
+
+/* process sound command */
+static int do_sound(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       cmd_tbl_t *c;
+
+       if (argc < 1)
+               return CMD_RET_USAGE;
+
+       /* Strip off leading 'sound' command argument */
+       argc--;
+       argv++;
+
+       c = find_cmd_tbl(argv[0], &cmd_sound_sub[0], ARRAY_SIZE(cmd_sound_sub));
+
+       if (c)
+               return c->cmd(cmdtp, flag, argc, argv);
+       else
+               return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+       sound, 4, 1, do_sound,
+       "sound sub-system",
+       "init - initialise the sound driver\n"
+       "sound play [len] [freq] - play a sound for len ms at freq hz\n"
+);
index 9ec054af3b359b6048df6d5f503307cec156697c..e3c543b46a54724eade6cb92f99dbc3381a5e1ed 100644 (file)
@@ -130,10 +130,12 @@ static int spl_export(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                if (call_bootm(argc, argv, subcmd_list[(int)c->cmd]))
                        return -1;
                switch ((int)c->cmd) {
+#ifdef CONFIG_OF_LIBFDT
                case SPL_EXPORT_FDT:
                        printf("Argument image is now in RAM: 0x%p\n",
                                (void *)images.ft_addr);
                        break;
+#endif
                case SPL_EXPORT_ATAGS:
                        printf("Argument image is now in RAM at: 0x%p\n",
                                (void *)gd->bd->bi_boot_params);
index 6f5cd4895d8cedea527612471d2eeaee5bcc9b30..0970a6fc191cab170cef254551b6a29b67dec0e6 100644 (file)
@@ -63,19 +63,68 @@ static int tpm_process(int argc, char * const argv[], cmd_tbl_t *cmdtp)
        return rv;
 }
 
-static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+#define CHECK(exp) do {                                                        \
+               int _rv = exp;                                          \
+               if (_rv) {                                              \
+                       printf("CHECK: %s %d %x\n", #exp, __LINE__, _rv);\
+               }                                                       \
+       } while (0)
+
+static int tpm_process_stress(int repeat_count)
 {
+       int i;
        int rv = 0;
+       u8 request[] = {0x0, 0xc1,
+                       0x0, 0x0, 0x0, 0x16,
+                       0x0, 0x0, 0x0, 0x65,
+                       0x0, 0x0, 0x0, 0x4,
+                       0x0, 0x0, 0x0, 0x4,
+                       0x0, 0x0, 0x1, 0x9};
+       u8 response[MAX_TRANSACTION_SIZE];
+       u32 rlength = MAX_TRANSACTION_SIZE;
+
+       CHECK(tis_init());
+
+       for (i = 0; i < repeat_count; i++) {
+               CHECK(tis_open());
+               rv = tis_sendrecv(request, sizeof(request), response, &rlength);
+               if (rv) {
+                       printf("tpm test failed at step %d with 0x%x\n", i, rv);
+                       CHECK(tis_close());
+                       break;
+               }
+               CHECK(tis_close());
+               if ((response[6] || response[7] || response[8] || response[9])
+                   && response[9] != 0x26) {
+                       /* Ignore postinit errors */
+                       printf("tpm command failed at step %d\n"
+                              "tpm error code: %02x%02x%02x%02x\n", i,
+                              response[6], response[7],
+                              response[8], response[9]);
+                       rv = -1;
+                       break;
+               }
+       }
+       return rv;
+}
 
-       /*
-        * Verify that in case it is present, the first argument, it is
-        * exactly one character in size.
-        */
-       if (argc < 7) {
+
+static int do_tpm_many(cmd_tbl_t *cmdtp, int flag,
+                      int argc, char * const argv[], int repeat_count)
+
+{
+       int rv = 0;
+
+       if (argc < 7 && repeat_count == 0) {
                puts("command should be at least six bytes in size\n");
                return -1;
        }
 
+       if (repeat_count > 0) {
+               rv = tpm_process_stress(repeat_count);
+               return rv;
+       }
+
        if (tis_init()) {
                puts("tis_init() failed!\n");
                return -1;
@@ -96,8 +145,40 @@ static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        return rv;
 }
 
+
+static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       return do_tpm_many(cmdtp, flag, argc, argv, 0);
+}
+
+
 U_BOOT_CMD(tpm, MAX_TRANSACTION_SIZE, 1, do_tpm,
           "<byte> [<byte> ...]   - write data and read response",
           "send arbitrary data (at least 6 bytes) to the TPM "
           "device and read the response"
 );
+
+static int do_tpm_stress(cmd_tbl_t *cmdtp, int flag,
+                        int argc, char * const argv[])
+{
+       long unsigned int n;
+       int rv;
+
+       if (argc != 2) {
+               puts("usage: tpm_stress <count>\n");
+               return -1;
+       }
+
+       rv = strict_strtoul(argv[1], 10, &n);
+       if (rv) {
+               puts("tpm_stress: bad count");
+               return -1;
+       }
+
+       return do_tpm_many(cmdtp, flag, argc, argv, n);
+}
+
+U_BOOT_CMD(tpm_stress, 2, 1, do_tpm_stress,
+          "<n>   - stress-test communication with TPM",
+          "Repeat a TPM transaction (request-response) N times"
+);
index 1177f7d396b889effbb9973b77966a013f15ee96..bf7317869097a8bf84bf9929bacdf90ff8f693a3 100644 (file)
 #include <common.h>
 #include <stdarg.h>
 #include <malloc.h>
+#include <serial.h>
 #include <stdio_dev.h>
 #include <exports.h>
+#include <environment.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static int on_console(const char *name, const char *value, enum env_op op,
+       int flags)
+{
+       int console = -1;
+
+       /* Check for console redirection */
+       if (strcmp(name, "stdin") == 0)
+               console = stdin;
+       else if (strcmp(name, "stdout") == 0)
+               console = stdout;
+       else if (strcmp(name, "stderr") == 0)
+               console = stderr;
+
+       /* if not actually setting a console variable, we don't care */
+       if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0)
+               return 0;
+
+       switch (op) {
+       case env_op_create:
+       case env_op_overwrite:
+
+#ifdef CONFIG_CONSOLE_MUX
+               if (iomux_doenv(console, value))
+                       return 1;
+#else
+               /* Try assigning specified device */
+               if (console_assign(console, value) < 0)
+                       return 1;
+#endif /* CONFIG_CONSOLE_MUX */
+               return 0;
+
+       case env_op_delete:
+               if ((flags & H_FORCE) == 0)
+                       printf("Can't delete \"%s\"\n", name);
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+U_BOOT_ENV_CALLBACK(console, on_console);
+
+#ifdef CONFIG_SILENT_CONSOLE
+static int on_silent(const char *name, const char *value, enum env_op op,
+       int flags)
+{
+#ifndef CONFIG_SILENT_CONSOLE_UPDATE_ON_SET
+       if (flags & H_INTERACTIVE)
+               return 0;
+#endif
+#ifndef CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC
+       if ((flags & H_INTERACTIVE) == 0)
+               return 0;
+#endif
+
+       if (value != NULL)
+               gd->flags |= GD_FLG_SILENT;
+       else
+               gd->flags &= ~GD_FLG_SILENT;
+
+       return 0;
+}
+U_BOOT_ENV_CALLBACK(silent, on_silent);
+#endif
+
 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
 /*
  * if overwrite_console returns 1, the stdin, stderr and stdout
@@ -591,7 +658,6 @@ int console_init_f(void)
 
 void stdio_print_current_devices(void)
 {
-#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
        /* Print information */
        puts("In:    ");
        if (stdio_devices[stdin] == NULL) {
@@ -613,7 +679,6 @@ void stdio_print_current_devices(void)
        } else {
                printf ("%s\n", stdio_devices[stderr]->name);
        }
-#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
 }
 
 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
@@ -683,9 +748,9 @@ int console_init_r(void)
 done:
 #endif
 
-       gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */
-
+#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
        stdio_print_current_devices();
+#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
 
 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
        /* set the environment variables (will overwrite previous env settings) */
@@ -694,6 +759,8 @@ done:
        }
 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
 
+       gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */
+
 #if 0
        /* If nothing usable installed, use only the initial console */
        if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
@@ -758,15 +825,17 @@ int console_init_r(void)
 #endif
        }
 
-       gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */
-
+#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
        stdio_print_current_devices();
+#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
 
        /* Setting environment variables */
        for (i = 0; i < 3; i++) {
                setenv(stdio_names[i], stdio_devices[i]->name);
        }
 
+       gd->flags |= GD_FLG_DEVINIT;    /* device initialization completed */
+
 #if 0
        /* If nothing usable installed, use only the initial console */
        if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
diff --git a/common/edid.c b/common/edid.c
new file mode 100644 (file)
index 0000000..c82c298
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * (C) Copyright 2010
+ * Petr Stetiar <ynezz@true.cz>
+ *
+ * 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
+ *
+ * Contains stolen code from ddcprobe project which is:
+ * Copyright (C) Nalin Dahyabhai <bigfun@pobox.com>
+ *
+ */
+
+#include <common.h>
+#include <edid.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+
+int edid_check_info(struct edid1_info *edid_info)
+{
+       if ((edid_info == NULL) || (edid_info->version == 0))
+               return -1;
+
+       if (memcmp(edid_info->header, "\x0\xff\xff\xff\xff\xff\xff\x0", 8))
+               return -1;
+
+       if (edid_info->version == 0xff && edid_info->revision == 0xff)
+               return -1;
+
+       return 0;
+}
+
+int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin,
+                   unsigned int *hmax, unsigned int *vmin,
+                   unsigned int *vmax)
+{
+       int i;
+       struct edid_monitor_descriptor *monitor;
+
+       *hmin = *hmax = *vmin = *vmax = 0;
+       if (edid_check_info(edid))
+               return -1;
+
+       for (i = 0; i < ARRAY_SIZE(edid->monitor_details.descriptor); i++) {
+               monitor = &edid->monitor_details.descriptor[i];
+               if (monitor->type == EDID_MONITOR_DESCRIPTOR_RANGE) {
+                       *hmin = monitor->data.range_data.horizontal_min;
+                       *hmax = monitor->data.range_data.horizontal_max;
+                       *vmin = monitor->data.range_data.vertical_min;
+                       *vmax = monitor->data.range_data.vertical_max;
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+/**
+ * Snip the tailing whitespace/return of a string.
+ *
+ * @param string       The string to be snipped
+ * @return the snipped string
+ */
+static char *snip(char *string)
+{
+       char *s;
+
+       /*
+        * This is always a 13 character buffer
+        * and it's not always terminated.
+        */
+       string[12] = '\0';
+       s = &string[strlen(string) - 1];
+
+       while (s >= string && (isspace(*s) || *s == '\n' || *s == '\r' ||
+                       *s == '\0'))
+               *(s--) = '\0';
+
+       return string;
+}
+
+/**
+ * Print an EDID monitor descriptor block
+ *
+ * @param monitor      The EDID monitor descriptor block
+ * @have_timing                Modifies to 1 if the desciptor contains timing info
+ */
+static void edid_print_dtd(struct edid_monitor_descriptor *monitor,
+                          unsigned int *have_timing)
+{
+       unsigned char *bytes = (unsigned char *)monitor;
+       struct edid_detailed_timing *timing =
+                       (struct edid_detailed_timing *)monitor;
+
+       if (bytes[0] == 0 && bytes[1] == 0) {
+               if (monitor->type == EDID_MONITOR_DESCRIPTOR_SERIAL)
+                       printf("Monitor serial number: %s\n",
+                              snip(monitor->data.string));
+               else if (monitor->type == EDID_MONITOR_DESCRIPTOR_ASCII)
+                       printf("Monitor ID: %s\n",
+                              snip(monitor->data.string));
+               else if (monitor->type == EDID_MONITOR_DESCRIPTOR_NAME)
+                       printf("Monitor name: %s\n",
+                              snip(monitor->data.string));
+               else if (monitor->type == EDID_MONITOR_DESCRIPTOR_RANGE)
+                       printf("Monitor range limits, horizontal sync: "
+                              "%d-%d kHz, vertical refresh: "
+                              "%d-%d Hz, max pixel clock: "
+                              "%d MHz\n",
+                              monitor->data.range_data.horizontal_min,
+                              monitor->data.range_data.horizontal_max,
+                              monitor->data.range_data.vertical_min,
+                              monitor->data.range_data.vertical_max,
+                              monitor->data.range_data.pixel_clock_max * 10);
+       } else {
+               uint32_t pixclock, h_active, h_blanking, v_active, v_blanking;
+               uint32_t h_total, v_total, vfreq;
+
+               pixclock = EDID_DETAILED_TIMING_PIXEL_CLOCK(*timing);
+               h_active = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*timing);
+               h_blanking = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*timing);
+               v_active = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*timing);
+               v_blanking = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*timing);
+
+               h_total = h_active + h_blanking;
+               v_total = v_active + v_blanking;
+               if (v_total * h_total)
+                       vfreq = pixclock / (v_total * h_total);
+               else
+                       vfreq = 1; /* Error case */
+               printf("\t%dx%d\%c\t%d Hz (detailed)\n", h_active,
+                      v_active, h_active > 1000 ? ' ' : '\t', vfreq);
+               *have_timing = 1;
+       }
+}
+
+/**
+ * Get the manufacturer name from an EDID info.
+ *
+ * @param edid_info     The EDID info to be printed
+ * @param name         Returns the string of the manufacturer name
+ */
+static void edid_get_manufacturer_name(struct edid1_info *edid, char *name)
+{
+       name[0] = EDID1_INFO_MANUFACTURER_NAME_CHAR1(*edid) + 'A' - 1;
+       name[1] = EDID1_INFO_MANUFACTURER_NAME_CHAR2(*edid) + 'A' - 1;
+       name[2] = EDID1_INFO_MANUFACTURER_NAME_CHAR3(*edid) + 'A' - 1;
+       name[3] = '\0';
+}
+
+void edid_print_info(struct edid1_info *edid_info)
+{
+       int i;
+       char manufacturer[4];
+       unsigned int have_timing = 0;
+       uint32_t serial_number;
+
+       if (edid_check_info(edid_info)) {
+               printf("Not a valid EDID\n");
+               return;
+       }
+
+       printf("EDID version: %d.%d\n",
+              edid_info->version, edid_info->revision);
+
+       printf("Product ID code: %04x\n", EDID1_INFO_PRODUCT_CODE(*edid_info));
+
+       edid_get_manufacturer_name(edid_info, manufacturer);
+       printf("Manufacturer: %s\n", manufacturer);
+
+       serial_number = EDID1_INFO_SERIAL_NUMBER(*edid_info);
+       if (serial_number != 0xffffffff) {
+               if (strcmp(manufacturer, "MAG") == 0)
+                       serial_number -= 0x7000000;
+               if (strcmp(manufacturer, "OQI") == 0)
+                       serial_number -= 456150000;
+               if (strcmp(manufacturer, "VSC") == 0)
+                       serial_number -= 640000000;
+       }
+       printf("Serial number: %08x\n", serial_number);
+       printf("Manufactured in week: %d year: %d\n",
+              edid_info->week, edid_info->year + 1990);
+
+       printf("Video input definition: %svoltage level %d%s%s%s%s%s\n",
+              EDID1_INFO_VIDEO_INPUT_DIGITAL(*edid_info) ?
+              "digital signal, " : "analog signal, ",
+              EDID1_INFO_VIDEO_INPUT_VOLTAGE_LEVEL(*edid_info),
+              EDID1_INFO_VIDEO_INPUT_BLANK_TO_BLACK(*edid_info) ?
+              ", blank to black" : "",
+              EDID1_INFO_VIDEO_INPUT_SEPARATE_SYNC(*edid_info) ?
+              ", separate sync" : "",
+              EDID1_INFO_VIDEO_INPUT_COMPOSITE_SYNC(*edid_info) ?
+              ", composite sync" : "",
+              EDID1_INFO_VIDEO_INPUT_SYNC_ON_GREEN(*edid_info) ?
+              ", sync on green" : "",
+              EDID1_INFO_VIDEO_INPUT_SERRATION_V(*edid_info) ?
+              ", serration v" : "");
+
+       printf("Monitor is %s\n",
+              EDID1_INFO_FEATURE_RGB(*edid_info) ? "RGB" : "non-RGB");
+
+       printf("Maximum visible display size: %d cm x %d cm\n",
+              edid_info->max_size_horizontal,
+              edid_info->max_size_vertical);
+
+       printf("Power management features: %s%s, %s%s, %s%s\n",
+              EDID1_INFO_FEATURE_ACTIVE_OFF(*edid_info) ?
+              "" : "no ", "active off",
+              EDID1_INFO_FEATURE_SUSPEND(*edid_info) ? "" : "no ", "suspend",
+              EDID1_INFO_FEATURE_STANDBY(*edid_info) ? "" : "no ", "standby");
+
+       printf("Estabilished timings:\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_720X400_70(*edid_info))
+               printf("\t720x400\t\t70 Hz (VGA 640x400, IBM)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_720X400_88(*edid_info))
+               printf("\t720x400\t\t88 Hz (XGA2)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_640X480_60(*edid_info))
+               printf("\t640x480\t\t60 Hz (VGA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_640X480_67(*edid_info))
+               printf("\t640x480\t\t67 Hz (Mac II, Apple)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_640X480_72(*edid_info))
+               printf("\t640x480\t\t72 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_640X480_75(*edid_info))
+               printf("\t640x480\t\t75 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_800X600_56(*edid_info))
+               printf("\t800x600\t\t56 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_800X600_60(*edid_info))
+               printf("\t800x600\t\t60 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_800X600_72(*edid_info))
+               printf("\t800x600\t\t72 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_800X600_75(*edid_info))
+               printf("\t800x600\t\t75 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_832X624_75(*edid_info))
+               printf("\t832x624\t\t75 Hz (Mac II)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_87I(*edid_info))
+               printf("\t1024x768\t87 Hz Interlaced (8514A)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_60(*edid_info))
+               printf("\t1024x768\t60 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_70(*edid_info))
+               printf("\t1024x768\t70 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_75(*edid_info))
+               printf("\t1024x768\t75 Hz (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_1280X1024_75(*edid_info))
+               printf("\t1280x1024\t75 (VESA)\n");
+       if (EDID1_INFO_ESTABLISHED_TIMING_1152X870_75(*edid_info))
+               printf("\t1152x870\t75 (Mac II)\n");
+
+       /* Standard timings. */
+       printf("Standard timings:\n");
+       for (i = 0; i < ARRAY_SIZE(edid_info->standard_timings); i++) {
+               unsigned int aspect = 10000;
+               unsigned int x, y;
+               unsigned char xres, vfreq;
+
+               xres = EDID1_INFO_STANDARD_TIMING_XRESOLUTION(*edid_info, i);
+               vfreq = EDID1_INFO_STANDARD_TIMING_VFREQ(*edid_info, i);
+               if ((xres != vfreq) ||
+                   ((xres != 0) && (xres != 1)) ||
+                   ((vfreq != 0) && (vfreq != 1))) {
+                       switch (EDID1_INFO_STANDARD_TIMING_ASPECT(*edid_info,
+                                       i)) {
+                       case ASPECT_625:
+                               aspect = 6250;
+                               break;
+                       case ASPECT_75:
+                               aspect = 7500;
+                               break;
+                       case ASPECT_8:
+                               aspect = 8000;
+                               break;
+                       case ASPECT_5625:
+                               aspect = 5625;
+                               break;
+                       }
+                       x = (xres + 31) * 8;
+                       y = x * aspect / 10000;
+                       printf("\t%dx%d%c\t%d Hz\n", x, y,
+                              x > 1000 ? ' ' : '\t', (vfreq & 0x3f) + 60);
+                       have_timing = 1;
+               }
+       }
+
+       /* Detailed timing information. */
+       for (i = 0; i < ARRAY_SIZE(edid_info->monitor_details.descriptor);
+                       i++) {
+               edid_print_dtd(&edid_info->monitor_details.descriptor[i],
+                              &have_timing);
+       }
+
+       if (!have_timing)
+               printf("\tNone\n");
+}
diff --git a/common/env_attr.c b/common/env_attr.c
new file mode 100644 (file)
index 0000000..210c98d
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * (C) Copyright 2012
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.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
+ */
+
+#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */
+#include <stdint.h>
+#include <stdio.h>
+#include <linux/linux_string.h>
+#else
+#include <common.h>
+#endif
+
+#include <env_attr.h>
+#include <errno.h>
+#include <linux/string.h>
+#include <malloc.h>
+
+/*
+ * Iterate through the whole list calling the callback for each found element.
+ * "attr_list" takes the form:
+ *     attributes = [^,:\s]*
+ *     entry = name[:attributes]
+ *     list = entry[,list]
+ */
+int env_attr_walk(const char *attr_list,
+       int (*callback)(const char *name, const char *attributes))
+{
+       const char *entry, *entry_end;
+       char *name, *attributes;
+
+       if (!attr_list)
+               /* list not found */
+               return 1;
+
+       entry = attr_list;
+       do {
+               char *entry_cpy = NULL;
+
+               entry_end = strchr(entry, ENV_ATTR_LIST_DELIM);
+               /* check if this is the last entry in the list */
+               if (entry_end == NULL) {
+                       int entry_len = strlen(entry);
+
+                       if (entry_len) {
+                               /*
+                                * allocate memory to copy the entry into since
+                                * we will need to inject '\0' chars and squash
+                                * white-space before calling the callback
+                                */
+                               entry_cpy = malloc(entry_len + 1);
+                               if (entry_cpy)
+                                       /* copy the rest of the list */
+                                       strcpy(entry_cpy, entry);
+                               else
+                                       return -ENOMEM;
+                       }
+               } else {
+                       int entry_len = entry_end - entry;
+
+                       if (entry_len) {
+                               /*
+                                * allocate memory to copy the entry into since
+                                * we will need to inject '\0' chars and squash
+                                * white-space before calling the callback
+                                */
+                               entry_cpy = malloc(entry_len + 1);
+                               if (entry_cpy) {
+                                       /* copy just this entry and null term */
+                                       strncpy(entry_cpy, entry, entry_len);
+                                       entry_cpy[entry_len] = '\0';
+                               } else
+                                       return -ENOMEM;
+                       }
+               }
+
+               /* check if there is anything to process (e.g. not ",,,") */
+               if (entry_cpy != NULL) {
+                       attributes = strchr(entry_cpy, ENV_ATTR_SEP);
+                       /* check if there is a ':' */
+                       if (attributes != NULL) {
+                               /* replace the ':' with '\0' to term name */
+                               *attributes++ = '\0';
+                               /* remove white-space from attributes */
+                               attributes = strim(attributes);
+                       }
+                       /* remove white-space from name */
+                       name = strim(entry_cpy);
+
+                       /* only call the callback if there is a name */
+                       if (strlen(name) != 0) {
+                               int retval = 0;
+
+                               retval = callback(name, attributes);
+                               if (retval) {
+                                       free(entry_cpy);
+                                       return retval;
+                               }
+                       }
+               }
+
+               free(entry_cpy);
+               entry = entry_end + 1;
+       } while (entry_end != NULL);
+
+       return 0;
+}
+
+/*
+ * Search for the last matching string in another string with the option to
+ * start looking at a certain point (i.e. ignore anything beyond that point).
+ */
+static char *reverse_strstr(const char *searched, const char *search_for,
+       const char *searched_start)
+{
+       char *result = NULL;
+
+       if (*search_for == '\0')
+               return (char *)searched;
+
+       for (;;) {
+               char *match = strstr(searched, search_for);
+
+               /*
+                * Stop looking if no new match is found or looking past the
+                * searched_start pointer
+                */
+               if (match == NULL || (searched_start != NULL &&
+                   match + strlen(search_for) > searched_start))
+                       break;
+
+               result = match;
+               searched = match + 1;
+       }
+
+       return result;
+}
+
+/*
+ * Retrieve the attributes string associated with a single name in the list
+ * There is no protection on attributes being too small for the value
+ */
+int env_attr_lookup(const char *attr_list, const char *name, char *attributes)
+{
+       const char *entry = NULL;
+
+       if (!attributes)
+               /* bad parameter */
+               return -1;
+       if (!attr_list)
+               /* list not found */
+               return 1;
+
+       entry = reverse_strstr(attr_list, name, NULL);
+       while (entry != NULL) {
+               const char *prevch = entry - 1;
+               const char *nextch = entry + strlen(name);
+
+               /* Skip spaces */
+               while (*prevch == ' ')
+                       prevch--;
+               while (*nextch == ' ')
+                       nextch++;
+
+               /* check for an exact match */
+               if ((entry == attr_list ||
+                    *prevch == ENV_ATTR_LIST_DELIM) &&
+                   (*nextch == ENV_ATTR_SEP ||
+                    *nextch == ENV_ATTR_LIST_DELIM ||
+                    *nextch == '\0'))
+                       break;
+
+               entry = reverse_strstr(attr_list, name, entry);
+       }
+       if (entry != NULL) {
+               int len;
+
+               /* skip the name */
+               entry += strlen(name);
+               /* skip spaces */
+               while (*entry == ' ')
+                       entry++;
+               if (*entry != ENV_ATTR_SEP)
+                       len = 0;
+               else {
+                       const char *delim;
+                       static const char delims[] = {
+                               ENV_ATTR_LIST_DELIM, ' ', '\0'};
+
+                       /* skip the attr sep */
+                       entry += 1;
+                       /* skip spaces */
+                       while (*entry == ' ')
+                               entry++;
+
+                       delim = strpbrk(entry, delims);
+                       if (delim == NULL)
+                               len = strlen(entry);
+                       else
+                               len = delim - entry;
+                       memcpy(attributes, entry, len);
+               }
+               attributes[len] = '\0';
+
+               /* success */
+               return 0;
+       }
+
+       /* not found in list */
+       return 2;
+}
diff --git a/common/env_callback.c b/common/env_callback.c
new file mode 100644 (file)
index 0000000..78ca367
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * (C) Copyright 2012
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.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 <environment.h>
+
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+/*
+ * Look up a callback function pointer by name
+ */
+struct env_clbk_tbl *find_env_callback(const char *name)
+{
+       struct env_clbk_tbl *clbkp;
+       int i;
+       int num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
+
+       if (name == NULL)
+               return NULL;
+
+       /* look up the callback in the linker-list */
+       for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
+            i < num_callbacks;
+            i++, clbkp++) {
+               if (strcmp(name, clbkp->name) == 0)
+                       return clbkp;
+       }
+
+       return NULL;
+}
+
+/*
+ * Look for a possible callback for a newly added variable
+ * This is called specifically when the variable did not exist in the hash
+ * previously, so the blanket update did not find this variable.
+ */
+void env_callback_init(ENTRY *var_entry)
+{
+       const char *var_name = var_entry->key;
+       const char *callback_list = getenv(ENV_CALLBACK_VAR);
+       char callback_name[256] = "";
+       struct env_clbk_tbl *clbkp;
+       int ret = 1;
+
+       /* look in the ".callbacks" var for a reference to this variable */
+       if (callback_list != NULL)
+               ret = env_attr_lookup(callback_list, var_name, callback_name);
+
+       /* only if not found there, look in the static list */
+       if (ret)
+               ret = env_attr_lookup(ENV_CALLBACK_LIST_STATIC, var_name,
+                       callback_name);
+
+       /* if an association was found, set the callback pointer */
+       if (!ret && strlen(callback_name)) {
+               clbkp = find_env_callback(callback_name);
+               if (clbkp != NULL)
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+                       var_entry->callback = clbkp->callback + gd->reloc_off;
+#else
+                       var_entry->callback = clbkp->callback;
+#endif
+       }
+}
+
+/*
+ * Called on each existing env var prior to the blanket update since removing
+ * a callback association should remove its callback.
+ */
+static int clear_callback(ENTRY *entry)
+{
+       entry->callback = NULL;
+
+       return 0;
+}
+
+/*
+ * Call for each element in the list that associates variables to callbacks
+ */
+static int set_callback(const char *name, const char *value)
+{
+       ENTRY e, *ep;
+       struct env_clbk_tbl *clbkp;
+
+       e.key   = name;
+       e.data  = NULL;
+       hsearch_r(e, FIND, &ep, &env_htab, 0);
+
+       /* does the env variable actually exist? */
+       if (ep != NULL) {
+               /* the assocaition delares no callback, so remove the pointer */
+               if (value == NULL || strlen(value) == 0)
+                       ep->callback = NULL;
+               else {
+                       /* assign the requested callback */
+                       clbkp = find_env_callback(value);
+                       if (clbkp != NULL)
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+                               ep->callback = clbkp->callback + gd->reloc_off;
+#else
+                               ep->callback = clbkp->callback;
+#endif
+               }
+       }
+
+       return 0;
+}
+
+static int on_callbacks(const char *name, const char *value, enum env_op op,
+       int flags)
+{
+       /* remove all callbacks */
+       hwalk_r(&env_htab, clear_callback);
+
+       /* configure any static callback bindings */
+       env_attr_walk(ENV_CALLBACK_LIST_STATIC, set_callback);
+       /* configure any dynamic callback bindings */
+       env_attr_walk(value, set_callback);
+
+       return 0;
+}
+U_BOOT_ENV_CALLBACK(callbacks, on_callbacks);
index 3d3cb70a6d60a21de660a20b260a20c447270ed9..906b41fccada86dc41d58d23ad42f74e7d5476b2 100644 (file)
@@ -40,7 +40,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #include <env_default.h>
 
 struct hsearch_data env_htab = {
-       .apply = env_check_apply,
+       .change_ok = env_flags_validate,
 };
 
 static uchar __env_get_char_spec(int index)
@@ -81,13 +81,42 @@ const uchar *env_get_addr(int index)
                return &default_environment[index];
 }
 
+/*
+ * Read an environment variable as a boolean
+ * Return -1 if variable does not exist (default to true)
+ */
+int getenv_yesno(const char *var)
+{
+       char *s = getenv(var);
+
+       if (s == NULL)
+               return -1;
+       return (*s == '1' || *s == 'y' || *s == 'Y' || *s == 't' || *s == 'T') ?
+               1 : 0;
+}
+
+/*
+ * Look up the variable from the default environment
+ */
+char *getenv_default(const char *name)
+{
+       char *ret_val;
+       unsigned long really_valid = gd->env_valid;
+       unsigned long real_gd_flags = gd->flags;
+
+       /* Pretend that the image is bad. */
+       gd->flags &= ~GD_FLG_ENV_READY;
+       gd->env_valid = 0;
+       ret_val = getenv(name);
+       gd->env_valid = really_valid;
+       gd->flags = real_gd_flags;
+       return ret_val;
+}
+
 void set_default_env(const char *s)
 {
-       /*
-        * By default, do not apply changes as they will eventually
-        * be applied by someone else
-        */
-       int do_apply = 0;
+       int flags = 0;
+
        if (sizeof(default_environment) > ENV_SIZE) {
                puts("*** Error - default environment is too large\n\n");
                return;
@@ -99,14 +128,7 @@ void set_default_env(const char *s)
                                "using default environment\n\n",
                                s + 1);
                } else {
-                       /*
-                        * This set_to_default was explicitly asked for
-                        * by the user, as opposed to being a recovery
-                        * mechanism.  Therefore we check every single
-                        * variable and apply changes to the system
-                        * right away (e.g. baudrate, console).
-                        */
-                       do_apply = 1;
+                       flags = H_INTERACTIVE;
                        puts(s);
                }
        } else {
@@ -114,8 +136,8 @@ void set_default_env(const char *s)
        }
 
        if (himport_r(&env_htab, (char *)default_environment,
-                       sizeof(default_environment), '\0', 0,
-                       0, NULL, do_apply) == 0)
+                       sizeof(default_environment), '\0', flags,
+                       0, NULL) == 0)
                error("Environment import failed: errno = %d\n", errno);
 
        gd->flags |= GD_FLG_ENV_READY;
@@ -130,8 +152,8 @@ int set_default_vars(int nvars, char * const vars[])
         * (and use \0 as a separator)
         */
        return himport_r(&env_htab, (const char *)default_environment,
-                               sizeof(default_environment), '\0', H_NOCLEAR,
-                               nvars, vars, 1 /* do_apply */);
+                               sizeof(default_environment), '\0',
+                               H_NOCLEAR | H_INTERACTIVE, nvars, vars);
 }
 
 #ifndef CONFIG_SPL_BUILD
@@ -155,7 +177,7 @@ int env_import(const char *buf, int check)
        }
 
        if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
-                       0, NULL, 0 /* do_apply */)) {
+                       0, NULL)) {
                gd->flags |= GD_FLG_ENV_READY;
                return 1;
        }
@@ -172,6 +194,7 @@ void env_relocate(void)
 {
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
        env_reloc();
+       env_htab.change_ok += gd->reloc_off;
 #endif
        if (gd->env_valid == 0) {
 #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
index 3c5af37bf50c290afb33f111b945d539926bf0dd..38c96157b9fa66a41c53c6722cbab2127565c84e 100644 (file)
@@ -60,7 +60,7 @@ int saveenv(void)
        char    *res;
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
index b66bba29f53fd53251abab1dc724e88c26ff15b5..45c935b6df7895844ae9914e01b69ffe6fa2333e 100644 (file)
@@ -139,7 +139,7 @@ int saveenv(void)
        BUG_ON(env_ptr != NULL);
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
index 6ef531821e015788a605836fe608077c70d17d9c..c0f18ab97dfde66b32a8a8cb7fe7437fcdfa3410 100644 (file)
@@ -61,7 +61,7 @@ int saveenv(void)
        int err;
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
diff --git a/common/env_flags.c b/common/env_flags.c
new file mode 100644 (file)
index 0000000..336cae4
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * (C) Copyright 2012
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.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 <linux/string.h>
+#include <linux/ctype.h>
+
+#ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */
+#include <stdint.h>
+#include <stdio.h>
+#include "fw_env.h"
+#include <env_attr.h>
+#include <env_flags.h>
+#define getenv fw_getenv
+#else
+#include <common.h>
+#include <environment.h>
+#endif
+
+#ifdef CONFIG_CMD_NET
+#define ENV_FLAGS_NET_VARTYPE_REPS "im"
+#else
+#define ENV_FLAGS_NET_VARTYPE_REPS ""
+#endif
+
+static const char env_flags_vartype_rep[] = "sdxb" ENV_FLAGS_NET_VARTYPE_REPS;
+static const char env_flags_varaccess_rep[] = "aroc";
+static const int env_flags_varaccess_mask[] = {
+       0,
+       ENV_FLAGS_VARACCESS_PREVENT_DELETE |
+               ENV_FLAGS_VARACCESS_PREVENT_CREATE |
+               ENV_FLAGS_VARACCESS_PREVENT_OVERWR,
+       ENV_FLAGS_VARACCESS_PREVENT_DELETE |
+               ENV_FLAGS_VARACCESS_PREVENT_OVERWR,
+       ENV_FLAGS_VARACCESS_PREVENT_DELETE |
+               ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR};
+
+#ifdef CONFIG_CMD_ENV_FLAGS
+static const char * const env_flags_vartype_names[] = {
+       "string",
+       "decimal",
+       "hexadecimal",
+       "boolean",
+#ifdef CONFIG_CMD_NET
+       "IP address",
+       "MAC address",
+#endif
+};
+static const char * const env_flags_varaccess_names[] = {
+       "any",
+       "read-only",
+       "write-once",
+       "change-default",
+};
+
+/*
+ * Print the whole list of available type flags.
+ */
+void env_flags_print_vartypes(void)
+{
+       enum env_flags_vartype curtype = (enum env_flags_vartype)0;
+
+       while (curtype != env_flags_vartype_end) {
+               printf("\t%c   -\t%s\n", env_flags_vartype_rep[curtype],
+                       env_flags_vartype_names[curtype]);
+               curtype++;
+       }
+}
+
+/*
+ * Print the whole list of available access flags.
+ */
+void env_flags_print_varaccess(void)
+{
+       enum env_flags_varaccess curaccess = (enum env_flags_varaccess)0;
+
+       while (curaccess != env_flags_varaccess_end) {
+               printf("\t%c   -\t%s\n", env_flags_varaccess_rep[curaccess],
+                       env_flags_varaccess_names[curaccess]);
+               curaccess++;
+       }
+}
+
+/*
+ * Return the name of the type.
+ */
+const char *env_flags_get_vartype_name(enum env_flags_vartype type)
+{
+       return env_flags_vartype_names[type];
+}
+
+/*
+ * Return the name of the access.
+ */
+const char *env_flags_get_varaccess_name(enum env_flags_varaccess access)
+{
+       return env_flags_varaccess_names[access];
+}
+#endif /* CONFIG_CMD_ENV_FLAGS */
+
+/*
+ * Parse the flags string from a .flags attribute list into the vartype enum.
+ */
+enum env_flags_vartype env_flags_parse_vartype(const char *flags)
+{
+       char *type;
+
+       if (strlen(flags) <= ENV_FLAGS_VARTYPE_LOC)
+               return env_flags_vartype_string;
+
+       type = strchr(env_flags_vartype_rep,
+               flags[ENV_FLAGS_VARTYPE_LOC]);
+
+       if (type != NULL)
+               return (enum env_flags_vartype)
+                       (type - &env_flags_vartype_rep[0]);
+
+       printf("## Warning: Unknown environment variable type '%c'\n",
+               flags[ENV_FLAGS_VARTYPE_LOC]);
+       return env_flags_vartype_string;
+}
+
+/*
+ * Parse the flags string from a .flags attribute list into the varaccess enum.
+ */
+enum env_flags_varaccess env_flags_parse_varaccess(const char *flags)
+{
+       char *access;
+
+       if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC)
+               return env_flags_varaccess_any;
+
+       access = strchr(env_flags_varaccess_rep,
+               flags[ENV_FLAGS_VARACCESS_LOC]);
+
+       if (access != NULL)
+               return (enum env_flags_varaccess)
+                       (access - &env_flags_varaccess_rep[0]);
+
+       printf("## Warning: Unknown environment variable access method '%c'\n",
+               flags[ENV_FLAGS_VARACCESS_LOC]);
+       return env_flags_varaccess_any;
+}
+
+/*
+ * Parse the binary flags from a hash table entry into the varaccess enum.
+ */
+enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags)
+{
+       int i;
+
+       for (i = 0; i < sizeof(env_flags_varaccess_mask); i++)
+               if (env_flags_varaccess_mask[i] ==
+                   (binflags & ENV_FLAGS_VARACCESS_BIN_MASK))
+                       return (enum env_flags_varaccess)i;
+
+       printf("Warning: Non-standard access flags. (0x%x)\n",
+               binflags & ENV_FLAGS_VARACCESS_BIN_MASK);
+
+       return env_flags_varaccess_any;
+}
+
+static inline int is_hex_prefix(const char *value)
+{
+       return value[0] == '0' && (value[1] == 'x' || value[1] == 'X');
+}
+
+static void skip_num(int hex, const char *value, const char **end,
+       int max_digits)
+{
+       int i;
+
+       if (hex && is_hex_prefix(value))
+               value += 2;
+
+       for (i = max_digits; i != 0; i--) {
+               if (hex && !isxdigit(*value))
+                       break;
+               if (!hex && !isdigit(*value))
+                       break;
+               value++;
+       }
+       if (end != NULL)
+               *end = value;
+}
+
+/*
+ * Based on the declared type enum, validate that the value string complies
+ * with that format
+ */
+static int _env_flags_validate_type(const char *value,
+       enum env_flags_vartype type)
+{
+       const char *end;
+#ifdef CONFIG_CMD_NET
+       const char *cur;
+       int i;
+#endif
+
+       switch (type) {
+       case env_flags_vartype_string:
+               break;
+       case env_flags_vartype_decimal:
+               skip_num(0, value, &end, -1);
+               if (*end != '\0')
+                       return -1;
+               break;
+       case env_flags_vartype_hex:
+               skip_num(1, value, &end, -1);
+               if (*end != '\0')
+                       return -1;
+               if (value + 2 == end && is_hex_prefix(value))
+                       return -1;
+               break;
+       case env_flags_vartype_bool:
+               if (value[0] != '1' && value[0] != 'y' && value[0] != 't' &&
+                   value[0] != 'Y' && value[0] != 'T' &&
+                   value[0] != '0' && value[0] != 'n' && value[0] != 'f' &&
+                   value[0] != 'N' && value[0] != 'F')
+                       return -1;
+               if (value[1] != '\0')
+                       return -1;
+               break;
+#ifdef CONFIG_CMD_NET
+       case env_flags_vartype_ipaddr:
+               cur = value;
+               for (i = 0; i < 4; i++) {
+                       skip_num(0, cur, &end, 3);
+                       if (cur == end)
+                               return -1;
+                       if (i != 3 && *end != '.')
+                               return -1;
+                       if (i == 3 && *end != '\0')
+                               return -1;
+                       cur = end + 1;
+               }
+               break;
+       case env_flags_vartype_macaddr:
+               cur = value;
+               for (i = 0; i < 6; i++) {
+                       skip_num(1, cur, &end, 2);
+                       if (cur == end)
+                               return -1;
+                       if (cur + 2 == end && is_hex_prefix(cur))
+                               return -1;
+                       if (i != 5 && *end != ':')
+                               return -1;
+                       if (i == 5 && *end != '\0')
+                               return -1;
+                       cur = end + 1;
+               }
+               break;
+#endif
+       case env_flags_vartype_end:
+               return -1;
+       }
+
+       /* OK */
+       return 0;
+}
+
+/*
+ * Look for flags in a provided list and failing that the static list
+ */
+static inline int env_flags_lookup(const char *flags_list, const char *name,
+       char *flags)
+{
+       int ret = 1;
+
+       if (!flags)
+               /* bad parameter */
+               return -1;
+
+       /* try the env first */
+       if (flags_list)
+               ret = env_attr_lookup(flags_list, name, flags);
+
+       if (ret != 0)
+               /* if not found in the env, look in the static list */
+               ret = env_attr_lookup(ENV_FLAGS_LIST_STATIC, name, flags);
+
+       return ret;
+}
+
+#ifdef USE_HOSTCC /* Functions only used from tools/env */
+/*
+ * Look up any flags directly from the .flags variable and the static list
+ * and convert them to the vartype enum.
+ */
+enum env_flags_vartype env_flags_get_type(const char *name)
+{
+       const char *flags_list = getenv(ENV_FLAGS_VAR);
+       char flags[ENV_FLAGS_ATTR_MAX_LEN + 1];
+
+       if (env_flags_lookup(flags_list, name, flags))
+               return env_flags_vartype_string;
+
+       if (strlen(flags) <= ENV_FLAGS_VARTYPE_LOC)
+               return env_flags_vartype_string;
+
+       return env_flags_parse_vartype(flags);
+}
+
+/*
+ * Look up the access of a variable directly from the .flags var.
+ */
+enum env_flags_varaccess env_flags_get_varaccess(const char *name)
+{
+       const char *flags_list = getenv(ENV_FLAGS_VAR);
+       char flags[ENV_FLAGS_ATTR_MAX_LEN + 1];
+
+       if (env_flags_lookup(flags_list, name, flags))
+               return env_flags_varaccess_any;
+
+       if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC)
+               return env_flags_varaccess_any;
+
+       return env_flags_parse_varaccess(flags);
+}
+
+/*
+ * Validate that the proposed new value for "name" is valid according to the
+ * defined flags for that variable, if any.
+ */
+int env_flags_validate_type(const char *name, const char *value)
+{
+       enum env_flags_vartype type;
+
+       if (value == NULL)
+               return 0;
+       type = env_flags_get_type(name);
+       if (_env_flags_validate_type(value, type) < 0) {
+               printf("## Error: flags type check failure for "
+                       "\"%s\" <= \"%s\" (type: %c)\n",
+                       name, value, env_flags_vartype_rep[type]);
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * Validate that the proposed access to variable "name" is valid according to
+ * the defined flags for that variable, if any.
+ */
+int env_flags_validate_varaccess(const char *name, int check_mask)
+{
+       enum env_flags_varaccess access;
+       int access_mask;
+
+       access = env_flags_get_varaccess(name);
+       access_mask = env_flags_varaccess_mask[access];
+
+       return (check_mask & access_mask) != 0;
+}
+
+/*
+ * Validate the parameters to "env set" directly
+ */
+int env_flags_validate_env_set_params(int argc, char * const argv[])
+{
+       if ((argc >= 3) && argv[2] != NULL) {
+               enum env_flags_vartype type = env_flags_get_type(argv[1]);
+
+               /*
+                * we don't currently check types that need more than
+                * one argument
+                */
+               if (type != env_flags_vartype_string && argc > 3) {
+                       printf("## Error: too many parameters for setting "
+                               "\"%s\"\n", argv[1]);
+                       return -1;
+               }
+               return env_flags_validate_type(argv[1], argv[2]);
+       }
+       /* ok */
+       return 0;
+}
+
+#else /* !USE_HOSTCC - Functions only used from lib/hashtable.c */
+
+/*
+ * Parse the flag charachters from the .flags attribute list into the binary
+ * form to be stored in the environment entry->flags field.
+ */
+static int env_parse_flags_to_bin(const char *flags)
+{
+       int binflags;
+
+       binflags = env_flags_parse_vartype(flags) & ENV_FLAGS_VARTYPE_BIN_MASK;
+       binflags |= env_flags_varaccess_mask[env_flags_parse_varaccess(flags)];
+
+       return binflags;
+}
+
+/*
+ * Look for possible flags for a newly added variable
+ * This is called specifically when the variable did not exist in the hash
+ * previously, so the blanket update did not find this variable.
+ */
+void env_flags_init(ENTRY *var_entry)
+{
+       const char *var_name = var_entry->key;
+       const char *flags_list = getenv(ENV_FLAGS_VAR);
+       char flags[ENV_FLAGS_ATTR_MAX_LEN + 1] = "";
+       int ret = 1;
+
+       /* look in the ".flags" and static for a reference to this variable */
+       ret = env_flags_lookup(flags_list, var_name, flags);
+
+       /* if any flags were found, set the binary form to the entry */
+       if (!ret && strlen(flags))
+               var_entry->flags = env_parse_flags_to_bin(flags);
+}
+
+/*
+ * Called on each existing env var prior to the blanket update since removing
+ * a flag in the flag list should remove its flags.
+ */
+static int clear_flags(ENTRY *entry)
+{
+       entry->flags = 0;
+
+       return 0;
+}
+
+/*
+ * Call for each element in the list that defines flags for a variable
+ */
+static int set_flags(const char *name, const char *value)
+{
+       ENTRY e, *ep;
+
+       e.key   = name;
+       e.data  = NULL;
+       hsearch_r(e, FIND, &ep, &env_htab, 0);
+
+       /* does the env variable actually exist? */
+       if (ep != NULL) {
+               /* the flag list is empty, so clear the flags */
+               if (value == NULL || strlen(value) == 0)
+                       ep->flags = 0;
+               else
+                       /* assign the requested flags */
+                       ep->flags = env_parse_flags_to_bin(value);
+       }
+
+       return 0;
+}
+
+static int on_flags(const char *name, const char *value, enum env_op op,
+       int flags)
+{
+       /* remove all flags */
+       hwalk_r(&env_htab, clear_flags);
+
+       /* configure any static flags */
+       env_attr_walk(ENV_FLAGS_LIST_STATIC, set_flags);
+       /* configure any dynamic flags */
+       env_attr_walk(value, set_flags);
+
+       return 0;
+}
+U_BOOT_ENV_CALLBACK(flags, on_flags);
+
+/*
+ * Perform consistency checking before creating, overwriting, or deleting an
+ * environment variable. Called as a callback function by hsearch_r() and
+ * hdelete_r(). Returns 0 in case of success, 1 in case of failure.
+ * When (flag & H_FORCE) is set, do not print out any error message and force
+ * overwriting of write-once variables.
+ */
+
+int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op,
+       int flag)
+{
+       const char *name;
+       const char *oldval = NULL;
+
+       if (op != env_op_create)
+               oldval = item->data;
+
+       name = item->key;
+
+       /* Default value for NULL to protect string-manipulating functions */
+       newval = newval ? : "";
+
+       /* validate the value to match the variable type */
+       if (op != env_op_delete) {
+               enum env_flags_vartype type = (enum env_flags_vartype)
+                       (ENV_FLAGS_VARTYPE_BIN_MASK & item->flags);
+
+               if (_env_flags_validate_type(newval, type) < 0) {
+                       printf("## Error: flags type check failure for "
+                               "\"%s\" <= \"%s\" (type: %c)\n",
+                               name, newval, env_flags_vartype_rep[type]);
+                       return -1;
+               }
+       }
+
+       /* check for access permission */
+#ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE
+       if (flag & H_FORCE)
+               return 0;
+#endif
+       switch (op) {
+       case env_op_delete:
+               if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_DELETE) {
+                       printf("## Error: Can't delete \"%s\"\n", name);
+                       return 1;
+               }
+               break;
+       case env_op_overwrite:
+               if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_OVERWR) {
+                       printf("## Error: Can't overwrite \"%s\"\n", name);
+                       return 1;
+               } else if (item->flags &
+                   ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR) {
+                       const char *defval = getenv_default(name);
+
+                       if (defval == NULL)
+                               defval = "";
+                       printf("oldval: %s  defval: %s\n", oldval, defval);
+                       if (strcmp(oldval, defval) != 0) {
+                               printf("## Error: Can't overwrite \"%s\"\n",
+                                       name);
+                               return 1;
+                       }
+               }
+               break;
+       case env_op_create:
+               if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_CREATE) {
+                       printf("## Error: Can't create \"%s\"\n", name);
+                       return 1;
+               }
+               break;
+       }
+
+       return 0;
+}
+
+#endif
index aa970d44007a18d2fd8d1a4a26acd3d362bcb626..e07d336a48b9940bc0987255554f68ff27fd52cd 100644 (file)
@@ -142,7 +142,7 @@ int saveenv(void)
                goto done;
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                goto done;
@@ -275,7 +275,7 @@ int saveenv(void)
                goto done;
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                goto done;
index a2ff90bf485eeb4d47b02a8e22865b7fec381ad3..ce2167121004303ac4972f64cd31db37d16c6ccd 100644 (file)
@@ -130,7 +130,7 @@ int saveenv(void)
        }
 
        res = (char *)&env_new->data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                ret = 1;
index 79e803370505dd8e996621d56757e44690817662..22e72a20b07b74ce8552a31e2d02b4b619d9fe6e 100644 (file)
@@ -186,7 +186,7 @@ int saveenv(void)
                return 1;
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
@@ -239,7 +239,7 @@ int saveenv(void)
                return 1;
 
        res = (char *)&env_new->data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
index 6483db39d3388fc672985d0fde867ade43b55b5a..eab0e7be0ecb90bc11f842dbe521e3df3c60f9dc 100644 (file)
@@ -90,7 +90,7 @@ int saveenv(void)
        int     rcode = 0;
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
index da35071251f8941861392afdd0963e9a097b6243..faa903d2f0251cd2459daef22d6d6514124dc86c 100644 (file)
@@ -95,7 +95,7 @@ int saveenv(void)
        };
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
index bbd472fcf281eb2340ab3fe65b8c73c4506556ba..d9e9085461bb6759b0b0ee0cc2f717d6653ede99 100644 (file)
@@ -79,7 +79,7 @@ int saveenv(void)
        }
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                return 1;
@@ -277,7 +277,7 @@ int saveenv(void)
        }
 
        res = (char *)&env_new.data;
-       len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL);
+       len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
        if (len < 0) {
                error("Cannot export environment: errno = %d\n", errno);
                goto done;
index 963ea90234699c29ad19eb0d8f855513a70539b0..6b9fa0550f18e5694cd9f1e83911c52c089920d8 100644 (file)
@@ -1315,7 +1315,7 @@ int fdt_set_status_by_alias(void *fdt, const char* alias,
        return fdt_set_node_status(fdt, offset, status, error_code);
 }
 
-#if defined(CONFIG_VIDEO)
+#if defined(CONFIG_VIDEO) || defined(CONFIG_LCD)
 int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
 {
        int noff;
diff --git a/common/hash.c b/common/hash.c
new file mode 100644 (file)
index 0000000..e3a6e43
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * (C) Copyright 2011
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@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.
+ *
+ * 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 <hash.h>
+#include <sha1.h>
+#include <sha256.h>
+
+/*
+ * These are the hash algorithms we support. Chips which support accelerated
+ * crypto could perhaps add named version of these algorithms here.
+ */
+static struct hash_algo hash_algo[] = {
+#ifdef CONFIG_SHA1
+       {
+               "SHA1",
+               SHA1_SUM_LEN,
+               sha1_csum_wd,
+               CHUNKSZ_SHA1,
+       },
+#endif
+#ifdef CONFIG_SHA256
+       {
+               "SHA256",
+               SHA256_SUM_LEN,
+               sha256_csum_wd,
+               CHUNKSZ_SHA256,
+       },
+#endif
+};
+
+/**
+ * store_result: Store the resulting sum to an address or variable
+ *
+ * @algo:              Hash algorithm being used
+ * @sum:               Hash digest (algo->digest_size bytes)
+ * @dest:              Destination, interpreted as a hex address if it starts
+ *                     with * or otherwise as an environment variable.
+ */
+static void store_result(struct hash_algo *algo, const u8 *sum,
+                        const char *dest)
+{
+       unsigned int i;
+
+       if (*dest == '*') {
+               u8 *ptr;
+
+               ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16);
+               memcpy(ptr, sum, algo->digest_size);
+       } else {
+               char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1];
+               char *str_ptr = str_output;
+
+               for (i = 0; i < algo->digest_size; i++) {
+                       sprintf(str_ptr, "%02x", sum[i]);
+                       str_ptr += 2;
+               }
+               str_ptr = '\0';
+               setenv(dest, str_output);
+       }
+}
+
+/**
+ * parse_verify_sum: Parse a hash verification parameter
+ *
+ * @algo:              Hash algorithm being used
+ * @verify_str:                Argument to parse. If it starts with * then it is
+ *                     interpreted as a hex address containing the hash.
+ *                     If the length is exactly the right number of hex digits
+ *                     for the digest size, then we assume it is a hex digest.
+ *                     Otherwise we assume it is an environment variable, and
+ *                     look up its value (it must contain a hex digest).
+ * @vsum:              Returns binary digest value (algo->digest_size bytes)
+ * @return 0 if ok, non-zero on error
+ */
+static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum)
+{
+       if (*verify_str == '*') {
+               u8 *ptr;
+
+               ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16);
+               memcpy(vsum, ptr, algo->digest_size);
+       } else {
+               unsigned int i;
+               char *vsum_str;
+               int digits = algo->digest_size * 2;
+
+               /*
+                * As with the original code from sha1sum.c, we assume that a
+                * string which matches the digest size exactly is a hex
+                * string and not an environment variable.
+                */
+               if (strlen(verify_str) == digits)
+                       vsum_str = verify_str;
+               else {
+                       vsum_str = getenv(verify_str);
+                       if (vsum_str == NULL || strlen(vsum_str) != digits) {
+                               printf("Expected %d hex digits in env var\n",
+                                      digits);
+                               return 1;
+                       }
+               }
+
+               for (i = 0; i < algo->digest_size; i++) {
+                       char *nullp = vsum_str + (i + 1) * 2;
+                       char end = *nullp;
+
+                       *nullp = '\0';
+                       vsum[i] = simple_strtoul(vsum_str + (i * 2), NULL, 16);
+                       *nullp = end;
+               }
+       }
+       return 0;
+}
+
+static struct hash_algo *find_hash_algo(const char *name)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
+               if (!strcasecmp(name, hash_algo[i].name))
+                       return &hash_algo[i];
+       }
+
+       return NULL;
+}
+
+static void show_hash(struct hash_algo *algo, ulong addr, ulong len,
+                     u8 *output)
+{
+       int i;
+
+       printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1);
+       for (i = 0; i < algo->digest_size; i++)
+               printf("%02x", output[i]);
+}
+
+int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
+                int argc, char * const argv[])
+{
+       struct hash_algo *algo;
+       ulong addr, len;
+       u8 output[HASH_MAX_DIGEST_SIZE];
+       u8 vsum[HASH_MAX_DIGEST_SIZE];
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       algo = find_hash_algo(algo_name);
+       if (!algo) {
+               printf("Unknown hash algorithm '%s'\n", algo_name);
+               return CMD_RET_USAGE;
+       }
+       addr = simple_strtoul(*argv++, NULL, 16);
+       len = simple_strtoul(*argv++, NULL, 16);
+       argc -= 2;
+
+       if (algo->digest_size > HASH_MAX_DIGEST_SIZE) {
+               puts("HASH_MAX_DIGEST_SIZE exceeded\n");
+               return 1;
+       }
+
+       algo->hash_func_ws((const unsigned char *)addr, len, output,
+                          algo->chunk_size);
+
+       /* Try to avoid code bloat when verify is not needed */
+#ifdef CONFIG_HASH_VERIFY
+       if (verify) {
+#else
+       if (0) {
+#endif
+               if (!argc)
+                       return CMD_RET_USAGE;
+               if (parse_verify_sum(algo, *argv, vsum)) {
+                       printf("ERROR: %s does not contain a valid %s sum\n",
+                               *argv, algo->name);
+                       return 1;
+               }
+               if (memcmp(output, vsum, algo->digest_size) != 0) {
+                       int i;
+
+                       show_hash(algo, addr, len, output);
+                       printf(" != ");
+                       for (i = 0; i < algo->digest_size; i++)
+                               printf("%02x", vsum[i]);
+                       puts(" ** ERROR **\n");
+                       return 1;
+               }
+       } else {
+               show_hash(algo, addr, len, output);
+               printf("\n");
+
+               if (argc)
+                       store_result(algo, output, *argv);
+       }
+
+       return 0;
+}
index e93b6e89cf9da48a130c265a83b575eba4a0c737..95498e6186e2290cc79a6cb1c9ac84b446b3a6fb 100644 (file)
@@ -43,6 +43,7 @@
 #include <rtc.h>
 #endif
 
+#include <environment.h>
 #include <image.h>
 
 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
@@ -416,11 +417,25 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch,
 /* Shared dual-format routines */
 /*****************************************************************************/
 #ifndef USE_HOSTCC
-int getenv_yesno(char *var)
+ulong load_addr = CONFIG_SYS_LOAD_ADDR;        /* Default Load Address */
+ulong save_addr;                       /* Default Save Address */
+ulong save_size;                       /* Default Save Size (in bytes) */
+
+static int on_loadaddr(const char *name, const char *value, enum env_op op,
+       int flags)
 {
-       char *s = getenv(var);
-       return (s && (*s == 'n')) ? 0 : 1;
+       switch (op) {
+       case env_op_create:
+       case env_op_overwrite:
+               load_addr = simple_strtoul(value, NULL, 16);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
 }
+U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr);
 
 ulong getenv_bootm_low(void)
 {
index 4c83a8bf0355d2912840e06046b7f0c2a4aaed80..4778655a26ae1982223be91014d957eee22164d6 100644 (file)
 # endif
 #endif
 
+#ifndef CONFIG_LCD_ALIGNMENT
+#define CONFIG_LCD_ALIGNMENT PAGE_SIZE
+#endif
+
+/* By default we scroll by a single line */
+#ifndef CONFIG_CONSOLE_SCROLL_LINES
+#define CONFIG_CONSOLE_SCROLL_LINES 1
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong lcd_setmem (ulong addr);
@@ -90,6 +99,9 @@ static void lcd_setbgcolor(int color);
 
 char lcd_is_enabled = 0;
 
+static char lcd_flush_dcache;  /* 1 to flush dcache after each lcd update */
+
+
 #ifdef NOT_USED_SO_FAR
 static void lcd_getcolreg(ushort regno,
                                ushort *red, ushort *green, ushort *blue);
@@ -98,15 +110,46 @@ static int lcd_getfgcolor(void);
 
 /************************************************************************/
 
+/* Flush LCD activity to the caches */
+void lcd_sync(void)
+{
+       /*
+        * flush_dcache_range() is declared in common.h but it seems that some
+        * architectures do not actually implement it. Is there a way to find
+        * out whether it exists? For now, ARM is safe.
+        */
+#if defined(CONFIG_ARM) && !defined(CONFIG_SYS_DCACHE_OFF)
+       int line_length;
+
+       if (lcd_flush_dcache)
+               flush_dcache_range((u32)lcd_base,
+                       (u32)(lcd_base + lcd_get_size(&line_length)));
+#endif
+}
+
+void lcd_set_flush_dcache(int flush)
+{
+       lcd_flush_dcache = (flush != 0);
+}
+
 /*----------------------------------------------------------------------*/
 
 static void console_scrollup(void)
 {
-       /* Copy up rows ignoring the first one */
-       memcpy(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE);
+       const int rows = CONFIG_CONSOLE_SCROLL_LINES;
 
-       /* Clear the last one */
-       memset(CONSOLE_ROW_LAST, COLOR_MASK(lcd_color_bg), CONSOLE_ROW_SIZE);
+       /* Copy up rows ignoring those that will be overwritten */
+       memcpy(CONSOLE_ROW_FIRST,
+              lcd_console_address + CONSOLE_ROW_SIZE * rows,
+              CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
+
+       /* Clear the last rows */
+       memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
+               COLOR_MASK(lcd_color_bg),
+              CONSOLE_ROW_SIZE * rows);
+
+       lcd_sync();
+       console_row -= rows;
 }
 
 /*----------------------------------------------------------------------*/
@@ -135,7 +178,8 @@ static inline void console_newline(void)
        if (console_row >= CONSOLE_ROWS) {
                /* Scroll everything up */
                console_scrollup();
-               --console_row;
+       } else {
+               lcd_sync();
        }
 }
 
@@ -191,6 +235,7 @@ void lcd_puts(const char *s)
        while (*s) {
                lcd_putc(*s++);
        }
+       lcd_sync();
 }
 
 /*----------------------------------------------------------------------*/
@@ -326,6 +371,12 @@ static void test_pattern(void)
 /* ** GENERIC Initialization Routines                                  */
 /************************************************************************/
 
+int lcd_get_size(int *line_length)
+{
+       *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
+       return *line_length * panel_info.vl_row;
+}
+
 int drv_lcd_init (void)
 {
        struct stdio_dev lcddev;
@@ -333,7 +384,7 @@ int drv_lcd_init (void)
 
        lcd_base = (void *)(gd->fb_base);
 
-       lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
+       lcd_get_size(&lcd_line_length);
 
        lcd_init(lcd_base);             /* LCD initialization */
 
@@ -352,13 +403,6 @@ int drv_lcd_init (void)
 }
 
 /*----------------------------------------------------------------------*/
-static
-int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
-{
-       lcd_clear();
-       return 0;
-}
-
 void lcd_clear(void)
 {
 #if LCD_BPP == LCD_MONOCHROME
@@ -400,6 +444,14 @@ void lcd_clear(void)
 
        console_col = 0;
        console_row = 0;
+       lcd_sync();
+}
+
+static int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       lcd_clear();
+       return 0;
 }
 
 U_BOOT_CMD(
@@ -445,15 +497,16 @@ static int lcd_init(void *lcdbase)
 ulong lcd_setmem(ulong addr)
 {
        ulong size;
-       int line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
+       int line_length;
 
        debug("LCD panel info: %d x %d, %d bit/pix\n", panel_info.vl_col,
                panel_info.vl_row, NBITS(panel_info.vl_bpix));
 
-       size = line_length * panel_info.vl_row;
+       size = lcd_get_size(&line_length);
 
-       /* Round up to nearest full page */
-       size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+       /* Round up to nearest full page, or MMU section if defined */
+       size = ALIGN(size, CONFIG_LCD_ALIGNMENT);
+       addr = ALIGN(addr - CONFIG_LCD_ALIGNMENT + 1, CONFIG_LCD_ALIGNMENT);
 
        /* Allocate pages for the frame buffer. */
        addr -= size;
@@ -610,6 +663,7 @@ void bitmap_plot(int x, int y)
        }
 
        WATCHDOG_RESET();
+       lcd_sync();
 }
 #else
 static inline void bitmap_plot(int x, int y) {}
@@ -975,6 +1029,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
                break;
        };
 
+       lcd_sync();
        return 0;
 }
 #endif
index 5362781f18700ee7e98547e07a5f673635b52666..5d8454ea0e5a6407882e4b0e06a27426270036f2 100644 (file)
@@ -376,6 +376,8 @@ void main_loop (void)
        char bcs_set[16];
 #endif /* CONFIG_BOOTCOUNT_LIMIT */
 
+       bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
+
 #ifdef CONFIG_BOOTCOUNT_LIMIT
        bootcount = bootcount_load();
        bootcount++;
@@ -1139,8 +1141,16 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout)
                                        puts (tab_seq+(col&07));
                                        col += 8 - (col&07);
                                } else {
-                                       ++col;          /* echo input           */
-                                       putc (c);
+                                       char buf[2];
+
+                                       /*
+                                        * Echo input using puts() to force am
+                                        * LCD flush if we are using an LCD
+                                        */
+                                       ++col;
+                                       buf[0] = c;
+                                       buf[1] = '\0';
+                                       puts(buf);
                                }
                                *p++ = c;
                                ++n;
index 9f48e5f5034da70cda786d8569a7287780868c9c..97ff9cf4a6a49f533f90240e9469bd4063986a11 100644 (file)
@@ -135,7 +135,6 @@ struct stdio_dev* stdio_clone(struct stdio_dev *dev)
                return NULL;
 
        memcpy(_dev, dev, sizeof(struct stdio_dev));
-       strncpy(_dev->name, dev->name, 16);
 
        return _dev;
 }
index a3873cebb33712d2ad016eb522eff8d6427b2096..76650173309624ed21eaa98a2b7a0dd3b7ef2fe3 100644 (file)
 #include <command.h>
 #include <ide.h>
 #include <malloc.h>
-#include "part_efi.h"
+#include <part_efi.h>
 #include <linux/ctype.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #if defined(CONFIG_CMD_IDE) || \
     defined(CONFIG_CMD_SATA) || \
     defined(CONFIG_CMD_SCSI) || \
     defined(CONFIG_MMC) || \
     defined(CONFIG_SYSTEMACE)
 
-/* Convert char[2] in little endian format to the host format integer
- */
-static inline unsigned short le16_to_int(unsigned char *le16)
-{
-       return ((le16[1] << 8) + le16[0]);
-}
-
-/* Convert char[4] in little endian format to the host format integer
- */
-static inline unsigned long le32_to_int(unsigned char *le32)
-{
-       return ((le32[3] << 24) + (le32[2] << 16) + (le32[1] << 8) + le32[0]);
-}
-
-/* Convert char[8] in little endian format to the host format integer
- */
-static inline unsigned long long le64_to_int(unsigned char *le64)
-{
-       return (((unsigned long long)le64[7] << 56) +
-               ((unsigned long long)le64[6] << 48) +
-               ((unsigned long long)le64[5] << 40) +
-               ((unsigned long long)le64[4] << 32) +
-               ((unsigned long long)le64[3] << 24) +
-               ((unsigned long long)le64[2] << 16) +
-               ((unsigned long long)le64[1] << 8) +
-               (unsigned long long)le64[0]);
-}
-
 /**
  * efi_crc32() - EFI version of crc32 function
  * @buf: buffer to calculate crc32 of
@@ -79,7 +53,7 @@ static inline unsigned long long le64_to_int(unsigned char *le64)
  *
  * Description: Returns EFI-style CRC32 value for @buf
  */
-static inline unsigned long efi_crc32(const void *buf, unsigned long len)
+static inline u32 efi_crc32(const void *buf, u32 len)
 {
        return crc32(0, buf, len);
 }
@@ -90,13 +64,10 @@ static inline unsigned long efi_crc32(const void *buf, unsigned long len)
 
 static int pmbr_part_valid(struct partition *part);
 static int is_pmbr_valid(legacy_mbr * mbr);
-
 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
                                gpt_header * pgpt_head, gpt_entry ** pgpt_pte);
-
 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
                                gpt_header * pgpt_head);
-
 static int is_pte_valid(gpt_entry * pte);
 
 static char *print_efiname(gpt_entry *pte)
@@ -142,6 +113,7 @@ static inline int is_bootable(gpt_entry *p)
                        sizeof(efi_guid_t));
 }
 
+#ifdef CONFIG_EFI_PARTITION
 /*
  * Public Functions (include/part.h)
  */
@@ -171,14 +143,14 @@ void print_part_efi(block_dev_desc_t * dev_desc)
        printf("\tType UUID\n");
        printf("\tPartition UUID\n");
 
-       for (i = 0; i < le32_to_int(gpt_head->num_partition_entries); i++) {
+       for (i = 0; i < le32_to_cpu(gpt_head->num_partition_entries); i++) {
                /* Stop at the first non valid PTE */
                if (!is_pte_valid(&gpt_pte[i]))
                        break;
 
                printf("%3d\t0x%08llx\t0x%08llx\t\"%s\"\n", (i + 1),
-                       le64_to_int(gpt_pte[i].starting_lba),
-                       le64_to_int(gpt_pte[i].ending_lba),
+                       le64_to_cpu(gpt_pte[i].starting_lba),
+                       le64_to_cpu(gpt_pte[i].ending_lba),
                        print_efiname(&gpt_pte[i]));
                printf("\tattrs:\t0x%016llx\n", gpt_pte[i].attributes.raw);
                uuid_string(gpt_pte[i].partition_type_guid.b, uuid);
@@ -211,7 +183,7 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
                return -1;
        }
 
-       if (part > le32_to_int(gpt_head->num_partition_entries) ||
+       if (part > le32_to_cpu(gpt_head->num_partition_entries) ||
            !is_pte_valid(&gpt_pte[part - 1])) {
                printf("%s: *** ERROR: Invalid partition number %d ***\n",
                        __func__, part);
@@ -219,9 +191,9 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
        }
 
        /* The ulong casting limits the maximum disk size to 2 TB */
-       info->start = (ulong) le64_to_int(gpt_pte[part - 1].starting_lba);
+       info->start = (u64)le64_to_cpu(gpt_pte[part - 1].starting_lba);
        /* The ending LBA is inclusive, to calculate size, add 1 to it */
-       info->size = ((ulong)le64_to_int(gpt_pte[part - 1].ending_lba) + 1)
+       info->size = ((u64)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1)
                     - info->start;
        info->blksz = GPT_BLOCK_SIZE;
 
@@ -253,6 +225,281 @@ int test_part_efi(block_dev_desc_t * dev_desc)
        return 0;
 }
 
+/**
+ * set_protective_mbr(): Set the EFI protective MBR
+ * @param dev_desc - block device descriptor
+ *
+ * @return - zero on success, otherwise error
+ */
+static int set_protective_mbr(block_dev_desc_t *dev_desc)
+{
+       legacy_mbr *p_mbr;
+
+       /* Setup the Protective MBR */
+       p_mbr = calloc(1, sizeof(p_mbr));
+       if (p_mbr == NULL) {
+               printf("%s: calloc failed!\n", __func__);
+               return -1;
+       }
+       /* Append signature */
+       p_mbr->signature = MSDOS_MBR_SIGNATURE;
+       p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
+       p_mbr->partition_record[0].start_sect = 1;
+       p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba;
+
+       /* Write MBR sector to the MMC device */
+       if (dev_desc->block_write(dev_desc->dev, 0, 1, p_mbr) != 1) {
+               printf("** Can't write to device %d **\n",
+                       dev_desc->dev);
+               free(p_mbr);
+               return -1;
+       }
+
+       free(p_mbr);
+       return 0;
+}
+
+/**
+ * string_uuid(); Convert UUID stored as string to bytes
+ *
+ * @param uuid - UUID represented as string
+ * @param dst - GUID buffer
+ *
+ * @return return 0 on successful conversion
+ */
+static int string_uuid(char *uuid, u8 *dst)
+{
+       efi_guid_t guid;
+       u16 b, c, d;
+       u64 e;
+       u32 a;
+       u8 *p;
+       u8 i;
+
+       const u8 uuid_str_len = 36;
+
+       /* The UUID is written in text: */
+       /* 1        9    14   19   24 */
+       /* xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */
+
+       debug("%s: uuid: %s\n", __func__, uuid);
+
+       if (strlen(uuid) != uuid_str_len)
+               return -1;
+
+       for (i = 0; i < uuid_str_len; i++) {
+               if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
+                       if (uuid[i] != '-')
+                               return -1;
+               } else {
+                       if (!isxdigit(uuid[i]))
+                               return -1;
+               }
+       }
+
+       a = (u32)simple_strtoul(uuid, NULL, 16);
+       b = (u16)simple_strtoul(uuid + 9, NULL, 16);
+       c = (u16)simple_strtoul(uuid + 14, NULL, 16);
+       d = (u16)simple_strtoul(uuid + 19, NULL, 16);
+       e = (u64)simple_strtoull(uuid + 24, NULL, 16);
+
+       p = (u8 *) &e;
+       guid = EFI_GUID(a, b, c, d >> 8, d & 0xFF,
+                       *(p + 5), *(p + 4), *(p + 3),
+                       *(p + 2), *(p + 1) , *p);
+
+       memcpy(dst, guid.b, sizeof(efi_guid_t));
+
+       return 0;
+}
+
+int write_gpt_table(block_dev_desc_t *dev_desc,
+               gpt_header *gpt_h, gpt_entry *gpt_e)
+{
+       const int pte_blk_num = (gpt_h->num_partition_entries
+               * sizeof(gpt_entry)) / dev_desc->blksz;
+
+       u32 calc_crc32;
+       u64 val;
+
+       debug("max lba: %x\n", (u32) dev_desc->lba);
+       /* Setup the Protective MBR */
+       if (set_protective_mbr(dev_desc) < 0)
+               goto err;
+
+       /* Generate CRC for the Primary GPT Header */
+       calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
+                             le32_to_cpu(gpt_h->num_partition_entries) *
+                             le32_to_cpu(gpt_h->sizeof_partition_entry));
+       gpt_h->partition_entry_array_crc32 = cpu_to_le32(calc_crc32);
+
+       calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
+                             le32_to_cpu(gpt_h->header_size));
+       gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
+
+       /* Write the First GPT to the block right after the Legacy MBR */
+       if (dev_desc->block_write(dev_desc->dev, 1, 1, gpt_h) != 1)
+               goto err;
+
+       if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_num, gpt_e)
+           != pte_blk_num)
+               goto err;
+
+       /* recalculate the values for the Second GPT Header */
+       val = le64_to_cpu(gpt_h->my_lba);
+       gpt_h->my_lba = gpt_h->alternate_lba;
+       gpt_h->alternate_lba = cpu_to_le64(val);
+       gpt_h->header_crc32 = 0;
+
+       calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
+                             le32_to_cpu(gpt_h->header_size));
+       gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
+
+       if (dev_desc->block_write(dev_desc->dev,
+                                 le32_to_cpu(gpt_h->last_usable_lba + 1),
+                                 pte_blk_num, gpt_e) != pte_blk_num)
+               goto err;
+
+       if (dev_desc->block_write(dev_desc->dev,
+                                 le32_to_cpu(gpt_h->my_lba), 1, gpt_h) != 1)
+               goto err;
+
+       debug("GPT successfully written to block device!\n");
+       return 0;
+
+ err:
+       printf("** Can't write to device %d **\n", dev_desc->dev);
+       return -1;
+}
+
+int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
+               disk_partition_t *partitions, int parts)
+{
+       u32 offset = (u32)le32_to_cpu(gpt_h->first_usable_lba);
+       ulong start;
+       int i, k;
+       size_t name_len;
+#ifdef CONFIG_PARTITION_UUIDS
+       char *str_uuid;
+#endif
+
+       for (i = 0; i < parts; i++) {
+               /* partition starting lba */
+               start = partitions[i].start;
+               if (start && (start < offset)) {
+                       printf("Partition overlap\n");
+                       return -1;
+               }
+               if (start) {
+                       gpt_e[i].starting_lba = cpu_to_le64(start);
+                       offset = start + partitions[i].size;
+               } else {
+                       gpt_e[i].starting_lba = cpu_to_le64(offset);
+                       offset += partitions[i].size;
+               }
+               if (offset >= gpt_h->last_usable_lba) {
+                       printf("Partitions layout exceds disk size\n");
+                       return -1;
+               }
+               /* partition ending lba */
+               if ((i == parts - 1) && (partitions[i].size == 0))
+                       /* extend the last partition to maximuim */
+                       gpt_e[i].ending_lba = gpt_h->last_usable_lba;
+               else
+                       gpt_e[i].ending_lba = cpu_to_le64(offset - 1);
+
+               /* partition type GUID */
+               memcpy(gpt_e[i].partition_type_guid.b,
+                       &PARTITION_BASIC_DATA_GUID, 16);
+
+#ifdef CONFIG_PARTITION_UUIDS
+               str_uuid = partitions[i].uuid;
+               if (string_uuid(str_uuid, gpt_e[i].unique_partition_guid.b)) {
+                       printf("Partition no. %d: invalid guid: %s\n",
+                               i, str_uuid);
+                       return -1;
+               }
+#endif
+
+               /* partition attributes */
+               memset(&gpt_e[i].attributes, 0,
+                      sizeof(gpt_entry_attributes));
+
+               /* partition name */
+               name_len = sizeof(gpt_e[i].partition_name)
+                       / sizeof(efi_char16_t);
+               for (k = 0; k < name_len; k++)
+                       gpt_e[i].partition_name[k] =
+                               (efi_char16_t)(partitions[i].name[k]);
+
+               debug("%s: name: %s offset[%d]: 0x%x size[%d]: 0x%lx\n",
+                     __func__, partitions[i].name, i,
+                     offset, i, partitions[i].size);
+       }
+
+       return 0;
+}
+
+int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h,
+               char *str_guid, int parts_count)
+{
+       gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE);
+       gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1);
+       gpt_h->header_size = cpu_to_le32(sizeof(gpt_header));
+       gpt_h->my_lba = cpu_to_le64(1);
+       gpt_h->alternate_lba = cpu_to_le64(dev_desc->lba - 1);
+       gpt_h->first_usable_lba = cpu_to_le64(34);
+       gpt_h->last_usable_lba = cpu_to_le64(dev_desc->lba - 34);
+       gpt_h->partition_entry_lba = cpu_to_le64(2);
+       gpt_h->num_partition_entries = cpu_to_le32(GPT_ENTRY_NUMBERS);
+       gpt_h->sizeof_partition_entry = cpu_to_le32(sizeof(gpt_entry));
+       gpt_h->header_crc32 = 0;
+       gpt_h->partition_entry_array_crc32 = 0;
+
+       if (string_uuid(str_guid, gpt_h->disk_guid.b))
+               return -1;
+
+       return 0;
+}
+
+int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
+               disk_partition_t *partitions, int parts_count)
+{
+       int ret;
+
+       gpt_header *gpt_h = calloc(1, sizeof(gpt_header));
+       if (gpt_h == NULL) {
+               printf("%s: calloc failed!\n", __func__);
+               return -1;
+       }
+
+       gpt_entry *gpt_e = calloc(GPT_ENTRY_NUMBERS, sizeof(gpt_entry));
+       if (gpt_e == NULL) {
+               printf("%s: calloc failed!\n", __func__);
+               free(gpt_h);
+               return -1;
+       }
+
+       /* Generate Primary GPT header (LBA1) */
+       ret = gpt_fill_header(dev_desc, gpt_h, str_disk_guid, parts_count);
+       if (ret)
+               goto err;
+
+       /* Generate partition entries */
+       ret = gpt_fill_pte(gpt_h, gpt_e, partitions, parts_count);
+       if (ret)
+               goto err;
+
+       /* Write GPT partition table */
+       ret = write_gpt_table(dev_desc, gpt_h, gpt_e);
+
+err:
+       free(gpt_e);
+       free(gpt_h);
+       return ret;
+}
+#endif
+
 /*
  * Private functions
  */
@@ -264,7 +511,7 @@ int test_part_efi(block_dev_desc_t * dev_desc)
 static int pmbr_part_valid(struct partition *part)
 {
        if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
-               le32_to_int(part->start_sect) == 1UL) {
+               le32_to_cpu(part->start_sect) == 1UL) {
                return 1;
        }
 
@@ -283,9 +530,8 @@ static int is_pmbr_valid(legacy_mbr * mbr)
 {
        int i = 0;
 
-       if (!mbr || le16_to_int(mbr->signature) != MSDOS_MBR_SIGNATURE) {
+       if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
                return 0;
-       }
 
        for (i = 0; i < 4; i++) {
                if (pmbr_part_valid(&mbr->partition_record[i])) {
@@ -308,8 +554,8 @@ static int is_pmbr_valid(legacy_mbr * mbr)
 static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
                        gpt_header * pgpt_head, gpt_entry ** pgpt_pte)
 {
-       unsigned char crc32_backup[4] = { 0 };
-       unsigned long calc_crc32;
+       u32 crc32_backup = 0;
+       u32 calc_crc32;
        unsigned long long lastlba;
 
        if (!dev_desc || !pgpt_head) {
@@ -324,54 +570,54 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
        }
 
        /* Check the GPT header signature */
-       if (le64_to_int(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
+       if (le64_to_cpu(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
                printf("GUID Partition Table Header signature is wrong:"
                        "0x%llX != 0x%llX\n",
-                       (unsigned long long)le64_to_int(pgpt_head->signature),
-                       (unsigned long long)GPT_HEADER_SIGNATURE);
+                       le64_to_cpu(pgpt_head->signature),
+                       GPT_HEADER_SIGNATURE);
                return 0;
        }
 
        /* Check the GUID Partition Table CRC */
-       memcpy(crc32_backup, pgpt_head->header_crc32, sizeof(crc32_backup));
-       memset(pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
+       memcpy(&crc32_backup, &pgpt_head->header_crc32, sizeof(crc32_backup));
+       memset(&pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
 
        calc_crc32 = efi_crc32((const unsigned char *)pgpt_head,
-               le32_to_int(pgpt_head->header_size));
+               le32_to_cpu(pgpt_head->header_size));
 
-       memcpy(pgpt_head->header_crc32, crc32_backup, sizeof(crc32_backup));
+       memcpy(&pgpt_head->header_crc32, &crc32_backup, sizeof(crc32_backup));
 
-       if (calc_crc32 != le32_to_int(crc32_backup)) {
+       if (calc_crc32 != le32_to_cpu(crc32_backup)) {
                printf("GUID Partition Table Header CRC is wrong:"
-                       "0x%08lX != 0x%08lX\n",
-                       le32_to_int(crc32_backup), calc_crc32);
+                       "0x%x != 0x%x\n",
+                      le32_to_cpu(crc32_backup), calc_crc32);
                return 0;
        }
 
        /* Check that the my_lba entry points to the LBA that contains the GPT */
-       if (le64_to_int(pgpt_head->my_lba) != lba) {
+       if (le64_to_cpu(pgpt_head->my_lba) != lba) {
                printf("GPT: my_lba incorrect: %llX != %llX\n",
-                       (unsigned long long)le64_to_int(pgpt_head->my_lba),
-                       (unsigned long long)lba);
+                       le64_to_cpu(pgpt_head->my_lba),
+                       lba);
                return 0;
        }
 
        /* Check the first_usable_lba and last_usable_lba are within the disk. */
        lastlba = (unsigned long long)dev_desc->lba;
-       if (le64_to_int(pgpt_head->first_usable_lba) > lastlba) {
+       if (le64_to_cpu(pgpt_head->first_usable_lba) > lastlba) {
                printf("GPT: first_usable_lba incorrect: %llX > %llX\n",
-                       le64_to_int(pgpt_head->first_usable_lba), lastlba);
+                       le64_to_cpu(pgpt_head->first_usable_lba), lastlba);
                return 0;
        }
-       if (le64_to_int(pgpt_head->last_usable_lba) > lastlba) {
+       if (le64_to_cpu(pgpt_head->last_usable_lba) > lastlba) {
                printf("GPT: last_usable_lba incorrect: %llX > %llX\n",
-                       le64_to_int(pgpt_head->last_usable_lba), lastlba);
+                       (u64) le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
                return 0;
        }
 
        debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n",
-               le64_to_int(pgpt_head->first_usable_lba),
-               le64_to_int(pgpt_head->last_usable_lba), lastlba);
+               le64_to_cpu(pgpt_head->first_usable_lba),
+               le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
 
        /* Read and allocate Partition Table Entries */
        *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
@@ -382,13 +628,13 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
 
        /* Check the GUID Partition Table Entry Array CRC */
        calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte,
-               le32_to_int(pgpt_head->num_partition_entries) *
-               le32_to_int(pgpt_head->sizeof_partition_entry));
+               le32_to_cpu(pgpt_head->num_partition_entries) *
+               le32_to_cpu(pgpt_head->sizeof_partition_entry));
 
-       if (calc_crc32 != le32_to_int(pgpt_head->partition_entry_array_crc32)) {
+       if (calc_crc32 != le32_to_cpu(pgpt_head->partition_entry_array_crc32)) {
                printf("GUID Partition Table Entry Array CRC is wrong:"
-                       "0x%08lX != 0x%08lX\n",
-                       le32_to_int(pgpt_head->partition_entry_array_crc32),
+                       "0x%x != 0x%x\n",
+                       le32_to_cpu(pgpt_head->partition_entry_array_crc32),
                        calc_crc32);
 
                free(*pgpt_pte);
@@ -419,12 +665,12 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
                return NULL;
        }
 
-       count = le32_to_int(pgpt_head->num_partition_entries) *
-               le32_to_int(pgpt_head->sizeof_partition_entry);
+       count = le32_to_cpu(pgpt_head->num_partition_entries) *
+               le32_to_cpu(pgpt_head->sizeof_partition_entry);
 
-       debug("%s: count = %lu * %lu = %zu\n", __func__,
-               le32_to_int(pgpt_head->num_partition_entries),
-               le32_to_int(pgpt_head->sizeof_partition_entry), count);
+       debug("%s: count = %u * %u = %zu\n", __func__,
+             (u32) le32_to_cpu(pgpt_head->num_partition_entries),
+             (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry), count);
 
        /* Allocate memory for PTE, remember to FREE */
        if (count != 0) {
@@ -440,7 +686,7 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
 
        /* Read GPT Entries from device */
        if (dev_desc->block_read (dev_desc->dev,
-               (unsigned long)le64_to_int(pgpt_head->partition_entry_lba),
+               le64_to_cpu(pgpt_head->partition_entry_lba),
                (lbaint_t) (count / GPT_BLOCK_SIZE), pte)
                != (count / GPT_BLOCK_SIZE)) {
 
diff --git a/doc/README.gpt b/doc/README.gpt
new file mode 100644 (file)
index 0000000..a9c58b4
--- /dev/null
@@ -0,0 +1,201 @@
+#
+#  Copyright (C) 2012 Samsung Electronics
+#
+#  Lukasz Majewski <l.majewski@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
+
+
+Glossary:
+========
+- UUID -(Universally Unique Identifier)
+- GUID - (Globally Unique ID)
+- EFI - (Extensible Firmware Interface)
+- UEFI - (Unified EFI) - EFI evolution
+- GPT (GUID Partition Table) - it is the EFI standard part
+- partitions - lists of available partitions (defined at u-boot):
+  ./include/configs/{target}.h
+
+Introduction:
+=============
+This document describes the GPT partition table format and usage of
+the gpt command in u-boot.
+
+
+UUID introduction:
+====================
+
+GPT for marking disks/partitions is using the UUID. It is supposed to be a
+globally unique value. A UUID is a 16-byte (128-bit) number. The number of
+theoretically possible UUIDs is therefore about 3 x 10^38.
+More often UUID is displayed as 32 hexadecimal digits, in 5 groups,
+separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters
+(32 digits and 4 hyphens)
+
+For instance, GUID of Linux data partition: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
+
+Historically there are 5 methods to generate this number. The oldest one is
+combining machine's MAC address and timer (epoch) value.
+
+Successive versions are using MD5 hash, random numbers and SHA-1 hash. All major
+OSes and programming languages are providing libraries to compute UUID (e.g.
+uuid command line tool).
+
+GPT brief explanation:
+======================
+
+       Layout:
+       -------
+
+       --------------------------------------------------
+       LBA 0          |Protective MBR                   |
+       ----------------------------------------------------------
+       LBA 1          |Primary GPT Header               | Primary
+       -------------------------------------------------- GPT
+       LBA 2          |Entry 1|Entry 2| Entry 3| Entry 4|
+       --------------------------------------------------
+       LBA 3          |Entries 5 - 128                  |
+                      |                                 |
+                      |                                 |
+       ----------------------------------------------------------
+       LBA 34         |Partition 1                      |
+                      |                                 |
+                      -----------------------------------
+                      |Partition 2                      |
+                      |                                 |
+                      -----------------------------------
+                      |Partition n                      |
+                      |                                 |
+       ----------------------------------------------------------
+       LBA -34        |Entry 1|Entry 2| Entry 3| Entry 4| Secondary
+       -------------------------------------------------- (bkp)
+       LBA -33        |Entries 5 - 128                  | GPT
+                      |                                 |
+                      |                                 |
+       LBA -2         |                                 |
+       --------------------------------------------------
+       LBA -1         |Secondary GPT Header             |
+       ----------------------------------------------------------
+
+
+For a legacy reasons, GPT's LBA 0 sector has a MBR structure. It is called
+"protective MBR".
+Its first partition entry ID has 0xEE value, and disk software, which is not
+handling the GPT sees it as a storage device without free space.
+
+It is possible to define 128 linearly placed partition entries.
+
+"LBA -1" means the last addressable block (in the mmc subsystem:
+"dev_desc->lba - 1")
+
+Primary/Secondary GPT header:
+----------------------------
+Offset  Size    Description
+
+0       8 B     Signature ("EFI PART", 45 46 49 20 50 41 52 54)
+8       4 B     Revision (For version 1.0, the value is 00 00 01 00)
+12      4 B     Header size (in bytes, usually 5C 00 00 00 meaning 92 bytes)
+16      4 B     CRC32 of header (0 to header size), with this field zeroed
+               during calculation
+20      4 B     Reserved (ZERO);
+24      8 B     Current LBA (location of this header copy)
+32      8 B     Backup LBA (location of the other header copy)
+40      8 B     First usable LBA for partitions (primary partition table last
+               LBA + 1)
+48      8 B     Last usable LBA (secondary partition table first LBA - 1)
+56      16 B    Disk GUID (also referred as UUID on UNIXes)
+72      8 B     Partition entries starting LBA (always 2 in primary copy)
+80      4 B     Number of partition entries
+84      4 B     Size of a partition entry (usually 128)
+88      4 B     CRC32 of partition array
+92      *       Reserved; must be ZERO (420 bytes for a 512-byte LBA)
+
+TOTAL: 512 B
+
+
+
+IMPORTANT:
+
+GPT headers and partition entries are protected by CRC32 (the POSIX CRC32).
+
+Primary GPT header and Secondary GPT header have swapped values of "Current LBA"
+and "Backup LBA" and therefore different CRC32 check-sum.
+
+CRC32 for GPT headers (field "CRC of header") are calculated up till
+"Header size" (92), NOT 512 bytes.
+
+CRC32 for partition entries (field "CRC32 of partition array") is calculated for
+the whole array entry ( Number_of_partition_entries *
+sizeof(partition_entry_size (usually 128)))
+
+Observe, how Secondary GPT is placed in the memory. It is NOT a mirror reflect
+of the Primary.
+
+
+          Partition Entry Format:
+          ----------------------
+          Offset  Size    Description
+
+          0       16 B    Partition type GUID
+          16      16 B    Unique partition GUID
+          32      8  B    First LBA (Little Endian)
+          40      8  B    Last LBA (inclusive)
+          48      8  B    Attribute flags [+]
+          56      72 B    Partition name (text)
+
+          Attribute flags:
+          Bit 0  - System partition
+          Bit 60 - Read-only
+          Bit 62 - Hidden
+          Bit 63 - Not mount
+
+
+Creating GPT partitions in U-Boot:
+==============
+
+To restore GUID partition table one needs to:
+1. Define partition layout in the environment.
+   Format of partitions layout:
+     "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...;
+       name=kernel,size=60MiB,uuid=...;"
+     or
+     "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name},
+       size=${uboot_size},uuid=${uboot_uuid};"
+
+   Fields 'name', 'size' and 'uuid' are mandatory for every partition.
+   The field 'start' is optional.
+
+2. Define 'CONFIG_EFI_PARTITION' and 'CONFIG_CMD_GPT'
+
+2. From u-boot prompt type:
+   gpt write mmc 0 $partitions
+
+
+Useful info:
+============
+
+Two programs, namely: 'fdisk' and 'parted' are recommended to work with GPT
+recovery. Parted is able to handle GUID partitions. Unfortunately the 'fdisk'
+hasn't got such ability.
+Please, pay attention at -l switch for parted.
+
+"uuid" program is recommended to generate UUID string. Moreover it can decode
+(-d switch) passed in UUID string. It can be used to generate partitions UUID
+passed to u-boot environment variables.
index a26e3df0da606af9c278f70a4e90d87417ef5c57..70202cece97fe8a53b49251ca8f64a9cef26ee1e 100644 (file)
@@ -1,9 +1,15 @@
 The config option CONFIG_SILENT_CONSOLE can be used to quiet messages
 on the console.  If the option has been enabled, the output can be
-silenced by setting the environment variable "silent".  The variable
-is latched into the global data at an early stage in the boot process
-so deleting it with "setenv" will not take effect until the system is
-restarted.
+silenced by setting the environment variable "silent".
+
+- CONFIG_SILENT_CONSOLE_UPDATE_ON_SET
+       When the "silent" variable is changed with env set, the change
+       will take effect immediately.
+
+- CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC
+       Some environments are not available until relocation (e.g. NAND)
+       so this will make the value in the flash env take effect at
+       relocation.
 
 The following actions are taken if "silent" is set at boot time:
 
diff --git a/doc/device-tree-bindings/pwm/tegra20-pwm.txt b/doc/device-tree-bindings/pwm/tegra20-pwm.txt
new file mode 100644 (file)
index 0000000..01438ec
--- /dev/null
@@ -0,0 +1,18 @@
+Tegra SoC PWFM controller
+
+Required properties:
+- compatible: should be one of:
+  - "nvidia,tegra20-pwm"
+  - "nvidia,tegra30-pwm"
+- reg: physical base address and length of the controller's registers
+- #pwm-cells: On Tegra the number of cells used to specify a PWM is 2. The
+  first cell specifies the per-chip index of the PWM to use and the second
+  cell is the period in nanoseconds.
+
+Example:
+
+       pwm: pwm@7000a000 {
+               compatible = "nvidia,tegra20-pwm";
+               reg = <0x7000a000 0x100>;
+               #pwm-cells = <2>;
+       };
diff --git a/doc/device-tree-bindings/video/displaymode.txt b/doc/device-tree-bindings/video/displaymode.txt
new file mode 100644 (file)
index 0000000..45ca42d
--- /dev/null
@@ -0,0 +1,42 @@
+videomode bindings
+==================
+
+(from http://lists.freedesktop.org/archives/dri-devel/2012-July/024875.html)
+
+Required properties:
+ - xres, yres: Display resolution
+ - left-margin, right-margin, hsync-len: Horizontal Display timing
+   parameters in pixels
+ - upper-margin, lower-margin, vsync-len: Vertical display timing
+   parameters in lines
+ - clock: display clock in Hz
+
+Optional properties:
+ - width-mm, height-mm: Display dimensions in mm
+ - hsync-active-high (bool): Hsync pulse is active high
+ - vsync-active-high (bool): Vsync pulse is active high
+ - interlaced (bool): This is an interlaced mode
+ - doublescan (bool): This is a doublescan mode
+
+There are different ways of describing a display mode. The devicetree
+representation corresponds to the one used by the Linux Framebuffer
+framework described here in Documentation/fb/framebuffer.txt. This
+representation has been chosen because it's the only format which does
+not allow for inconsistent parameters. Unlike the Framebuffer framework
+the devicetree has the clock in Hz instead of ps.
+
+Example:
+
+       display@0 {
+               /* 1920x1080p24 */
+               clock = <52000000>;
+               xres = <1920>;
+               yres = <1080>;
+               left-margin = <25>;
+               right-margin = <25>;
+               hsync-len = <25>;
+               lower-margin = <2>;
+               upper-margin = <2>;
+               vsync-len = <2>;
+               hsync-active-high;
+       };
diff --git a/doc/device-tree-bindings/video/tegra20-dc.txt b/doc/device-tree-bindings/video/tegra20-dc.txt
new file mode 100644 (file)
index 0000000..4731c3f
--- /dev/null
@@ -0,0 +1,85 @@
+Display Controller
+------------------
+
+(there isn't yet a generic binding in Linux, so this describes what is in
+U-Boot, and may change based on Linux activity)
+
+The device node for a display device is as described in the document
+"Open Firmware Recommended Practice : Universal Serial Bus" with the
+following modifications and additions :
+
+Required properties :
+ - compatible : Should be "nvidia,tegra20-dc"
+
+Required subnode 'rgb' is as follows:
+
+Required properties (rgb) :
+ - nvidia,panel : phandle of LCD panel information
+
+
+The panel node describes the panel itself. This has the properties listed in
+displaymode.txt as well as:
+
+Required properties (panel) :
+ - nvidia,bits-per-pixel: number of bits per pixel (depth)
+ - nvidia,pwm : pwm to use to set display contrast (see tegra20-pwm.txt)
+ - nvidia,panel-timings: 4 cells containing required timings in ms:
+       * delay before asserting panel_vdd
+       * delay between panel_vdd-rise and data-rise
+       * delay between data-rise and backlight_vdd-rise
+       * delay between backlight_vdd and pwm-rise
+       * delay between pwm-rise and backlight_en-rise
+
+Optional GPIO properies all have (phandle, GPIO number, flags):
+ - nvidia,backlight-enable-gpios: backlight enable GPIO
+ - nvidia,lvds-shutdown-gpios: LVDS power shutdown GPIO
+ - nvidia,backlight-vdd-gpios: backlight power GPIO
+ - nvidia,panel-vdd-gpios: panel power GPIO
+
+Example:
+
+host1x {
+       compatible = "nvidia,tegra20-host1x", "simple-bus";
+       reg = <0x50000000 0x00024000>;
+       interrupts = <0 65 0x04   /* mpcore syncpt */
+                       0 67 0x04>; /* mpcore general */
+
+       #address-cells = <1>;
+       #size-cells = <1>;
+       status = "okay";
+
+       ranges = <0x54000000 0x54000000 0x04000000>;
+
+       dc@54200000 {
+               compatible = "nvidia,tegra20-dc";
+               reg = <0x54200000 0x00040000>;
+               interrupts = <0 73 0x04>;
+               status = "okay";
+
+               rgb {
+                       status = "okay";
+                       nvidia,panel = <&lcd_panel>;
+               };
+       };
+};
+
+lcd_panel: panel {
+       /* Seaboard has 1366x768 */
+       clock = <70600000>;
+       xres = <1366>;
+       yres = <768>;
+       left-margin = <58>;
+       right-margin = <58>;
+       hsync-len = <58>;
+       lower-margin = <4>;
+       upper-margin = <4>;
+       vsync-len = <4>;
+       hsync-active-high;
+       nvidia,bits-per-pixel = <16>;
+       nvidia,pwm = <&pwm 2 0>;
+       nvidia,backlight-enable-gpios = <&gpio 28 0>;   /* PD4 */
+       nvidia,lvds-shutdown-gpios = <&gpio 10 0>;      /* PB2 */
+       nvidia,backlight-vdd-gpios = <&gpio 176 0>;     /* PW0 */
+       nvidia,panel-vdd-gpios = <&gpio 22 0>;          /* PC6 */
+       nvidia,panel-timings = <400 4 203 17 15>;
+};
index 47f321392791cfc093c6f6b14b8433c500f7e032..656bf4a06c22072f2c228cb69cf174ee7b089b3b 100644 (file)
@@ -144,9 +144,11 @@ void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
 
 struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio)
 {
-       int bank = gpio / GPIO_PER_BANK;
-       bank *= sizeof(struct s5p_gpio_bank);
+       int bank;
+       unsigned g = gpio - s5p_gpio_part_max(gpio);
 
+       bank = g / GPIO_PER_BANK;
+       bank *= sizeof(struct s5p_gpio_bank);
        return (struct s5p_gpio_bank *) (s5p_gpio_base(gpio) + bank);
 }
 
index bf64a2a643ab2871c053188d7f3f8dd061aaeb58..665387091ae351f4e2701be96a0b23ae7f339f95 100644 (file)
 #include <asm/arch/hardware.h>
 #include "designware_i2c.h"
 
-static struct i2c_regs *const i2c_regs_p =
+#ifdef CONFIG_I2C_MULTI_BUS
+static unsigned int bus_initialized[CONFIG_SYS_I2C_BUS_MAX];
+static unsigned int current_bus = 0;
+#endif
+
+static struct i2c_regs *i2c_regs_p =
     (struct i2c_regs *)CONFIG_SYS_I2C_BASE;
 
 /*
@@ -39,7 +44,6 @@ static void set_speed(int i2c_spd)
 {
        unsigned int cntl;
        unsigned int hcnt, lcnt;
-       unsigned int high, low;
        unsigned int enbl;
 
        /* to set speed cltr must be disabled */
@@ -47,39 +51,38 @@ static void set_speed(int i2c_spd)
        enbl &= ~IC_ENABLE_0B;
        writel(enbl, &i2c_regs_p->ic_enable);
 
-
        cntl = (readl(&i2c_regs_p->ic_con) & (~IC_CON_SPD_MSK));
 
        switch (i2c_spd) {
        case IC_SPEED_MODE_MAX:
                cntl |= IC_CON_SPD_HS;
-               high = MIN_HS_SCL_HIGHTIME;
-               low = MIN_HS_SCL_LOWTIME;
+               hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
+               writel(hcnt, &i2c_regs_p->ic_hs_scl_hcnt);
+               lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
+               writel(lcnt, &i2c_regs_p->ic_hs_scl_lcnt);
                break;
 
        case IC_SPEED_MODE_STANDARD:
                cntl |= IC_CON_SPD_SS;
-               high = MIN_SS_SCL_HIGHTIME;
-               low = MIN_SS_SCL_LOWTIME;
+               hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
+               writel(hcnt, &i2c_regs_p->ic_ss_scl_hcnt);
+               lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
+               writel(lcnt, &i2c_regs_p->ic_ss_scl_lcnt);
                break;
 
        case IC_SPEED_MODE_FAST:
        default:
                cntl |= IC_CON_SPD_FS;
-               high = MIN_FS_SCL_HIGHTIME;
-               low = MIN_FS_SCL_LOWTIME;
+               hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
+               writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt);
+               lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
+               writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt);
                break;
        }
 
        writel(cntl, &i2c_regs_p->ic_con);
 
-       hcnt = (IC_CLK * high) / NANO_TO_MICRO;
-       writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt);
-
-       lcnt = (IC_CLK * low) / NANO_TO_MICRO;
-       writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt);
-
-       /* re-enable i2c ctrl back now that speed is set */
+       /* Enable back i2c now speed set */
        enbl |= IC_ENABLE_0B;
        writel(enbl, &i2c_regs_p->ic_enable);
 }
@@ -150,6 +153,10 @@ void i2c_init(int speed, int slaveadd)
        enbl = readl(&i2c_regs_p->ic_enable);
        enbl |= IC_ENABLE_0B;
        writel(enbl, &i2c_regs_p->ic_enable);
+
+#ifdef CONFIG_I2C_MULTI_BUS
+       bus_initialized[current_bus] = 1;
+#endif
 }
 
 /*
@@ -274,7 +281,10 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 
        start_time_rx = get_timer(0);
        while (len) {
-               writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
+               if (len == 1)
+                       writel(IC_CMD | IC_STOP, &i2c_regs_p->ic_cmd_data);
+               else
+                       writel(IC_CMD, &i2c_regs_p->ic_cmd_data);
 
                if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) {
                        *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data);
@@ -313,9 +323,11 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
        start_time_tx = get_timer(0);
        while (len) {
                if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) {
-                       writel(*buffer, &i2c_regs_p->ic_cmd_data);
+                       if (--len == 0)
+                               writel(*buffer | IC_STOP, &i2c_regs_p->ic_cmd_data);
+                       else
+                               writel(*buffer, &i2c_regs_p->ic_cmd_data);
                        buffer++;
-                       len--;
                        start_time_tx = get_timer(0);
 
                } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
@@ -344,3 +356,74 @@ int i2c_probe(uchar chip)
 
        return ret;
 }
+
+#ifdef CONFIG_I2C_MULTI_BUS
+int i2c_set_bus_num(unsigned int bus)
+{
+       switch (bus) {
+       case 0:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE;
+               break;
+#ifdef CONFIG_SYS_I2C_BASE1
+       case 1:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE1;
+               break;
+#endif
+#ifdef CONFIG_SYS_I2C_BASE2
+       case 2:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE2;
+               break;
+#endif
+#ifdef CONFIG_SYS_I2C_BASE3
+       case 3:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE3;
+               break;
+#endif
+#ifdef CONFIG_SYS_I2C_BASE4
+       case 4:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE4;
+               break;
+#endif
+#ifdef CONFIG_SYS_I2C_BASE5
+       case 5:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE5;
+               break;
+#endif
+#ifdef CONFIG_SYS_I2C_BASE6
+       case 6:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE6;
+               break;
+#endif
+#ifdef CONFIG_SYS_I2C_BASE7
+       case 7:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE7;
+               break;
+#endif
+#ifdef CONFIG_SYS_I2C_BASE8
+       case 8:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE8;
+               break;
+#endif
+#ifdef CONFIG_SYS_I2C_BASE9
+       case 9:
+               i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE9;
+               break;
+#endif
+       default:
+               printf("Bad bus: %d\n", bus);
+               return -1;
+       }
+
+       current_bus = bus;
+
+       if (!bus_initialized[current_bus])
+               i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+       return 0;
+}
+
+int i2c_get_bus_num(void)
+{
+       return current_bus;
+}
+#endif
index 03b520ed43a0a48def984d0a98db0e89c1c71c29..2faf4a8717a31f1868dfa70cebb0f12b1b7d5694 100644 (file)
@@ -60,14 +60,16 @@ struct i2c_regs {
        u32 ic_tx_abrt_source;
 };
 
+#if !defined(IC_CLK)
 #define IC_CLK                 166
+#endif
 #define NANO_TO_MICRO          1000
 
 /* High and low times in different speed modes (in ns) */
 #define MIN_SS_SCL_HIGHTIME    4000
-#define MIN_SS_SCL_LOWTIME     5000
-#define MIN_FS_SCL_HIGHTIME    800
-#define MIN_FS_SCL_LOWTIME     1700
+#define MIN_SS_SCL_LOWTIME     4700
+#define MIN_FS_SCL_HIGHTIME    600
+#define MIN_FS_SCL_LOWTIME     1300
 #define MIN_HS_SCL_HIGHTIME    60
 #define MIN_HS_SCL_LOWTIME     160
 
@@ -95,6 +97,7 @@ struct i2c_regs {
 
 /* i2c data buffer and command register definitions */
 #define IC_CMD                 0x0100
+#define IC_STOP                        0x0200
 
 /* i2c interrupt status register definitions */
 #define IC_GEN_CALL            0x0800
index 18270b9de64f065dd583dadd8bf8b44acaafaeaa..a73b10b9c49f662c167276f3d97abcc7517e75dd 100644 (file)
@@ -115,7 +115,7 @@ static uint8_t i2c_imx_get_clk(unsigned int rate)
 /*
  * Set I2C Bus speed
  */
-int bus_i2c_set_bus_speed(void *base, int speed)
+static int bus_i2c_set_bus_speed(void *base, int speed)
 {
        struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base;
        u8 clk_idx = i2c_imx_get_clk(speed);
@@ -133,7 +133,7 @@ int bus_i2c_set_bus_speed(void *base, int speed)
 /*
  * Get I2C Speed
  */
-unsigned int bus_i2c_get_bus_speed(void *base)
+static unsigned int bus_i2c_get_bus_speed(void *base)
 {
        struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base;
        u8 clk_idx = readb(&i2c_regs->ifdr);
index 2a193c220d7b41252dd35b5870dfee8c07b59706..b907f7b379bb6c6bb02aabffdff363f4560bc23c 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <i2c.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
@@ -40,6 +41,7 @@ void mxs_i2c_reset(void)
 {
        struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
        int ret;
+       int speed = i2c_get_bus_speed();
 
        ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
        if (ret) {
@@ -53,6 +55,8 @@ void mxs_i2c_reset(void)
                &i2c_regs->hw_i2c_ctrl1_clr);
 
        writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set);
+
+       i2c_set_bus_speed(speed);
 }
 
 void mxs_i2c_setup_read(uint8_t chip, int len)
@@ -210,37 +214,65 @@ int i2c_probe(uchar chip)
        return ret;
 }
 
-void i2c_init(int speed, int slaveadd)
+int i2c_set_bus_speed(unsigned int speed)
 {
        struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
+       /*
+        * The timing derivation algorithm. There is no documentation for this
+        * algorithm available, it was derived by using the scope and fiddling
+        * with constants until the result observed on the scope was good enough
+        * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be
+        * possible to assume the algorithm works for other frequencies as well.
+        *
+        * Note it was necessary to cap the frequency on both ends as it's not
+        * possible to configure completely arbitrary frequency for the I2C bus
+        * clock.
+        */
+       uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
+       uint32_t base = ((clk / speed) - 38) / 2;
+       uint16_t high_count = base + 3;
+       uint16_t low_count = base - 3;
+       uint16_t rcv_count = (high_count * 3) / 4;
+       uint16_t xmit_count = low_count / 4;
+
+       if (speed > 540000) {
+               printf("MXS I2C: Speed too high (%d Hz)\n", speed);
+               return -EINVAL;
+       }
 
-       mxs_i2c_reset();
-
-       switch (speed) {
-       case 100000:
-               writel((0x0078 << I2C_TIMING0_HIGH_COUNT_OFFSET) |
-                       (0x0030 << I2C_TIMING0_RCV_COUNT_OFFSET),
-                       &i2c_regs->hw_i2c_timing0);
-               writel((0x0080 << I2C_TIMING1_LOW_COUNT_OFFSET) |
-                       (0x0030 << I2C_TIMING1_XMIT_COUNT_OFFSET),
-                       &i2c_regs->hw_i2c_timing1);
-               break;
-       case 400000:
-               writel((0x000f << I2C_TIMING0_HIGH_COUNT_OFFSET) |
-                       (0x0007 << I2C_TIMING0_RCV_COUNT_OFFSET),
-                       &i2c_regs->hw_i2c_timing0);
-               writel((0x001f << I2C_TIMING1_LOW_COUNT_OFFSET) |
-                       (0x000f << I2C_TIMING1_XMIT_COUNT_OFFSET),
-                       &i2c_regs->hw_i2c_timing1);
-               break;
-       default:
-               printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed);
-               return;
+       if (speed < 12000) {
+               printf("MXS I2C: Speed too low (%d Hz)\n", speed);
+               return -EINVAL;
        }
 
-       writel((0x0015 << I2C_TIMING2_BUS_FREE_OFFSET) |
-               (0x000d << I2C_TIMING2_LEADIN_COUNT_OFFSET),
+       writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0);
+       writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1);
+
+       writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) |
+               (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET),
                &i2c_regs->hw_i2c_timing2);
 
+       return 0;
+}
+
+unsigned int i2c_get_bus_speed(void)
+{
+       struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
+       uint32_t clk = mxc_get_clock(MXC_XTAL_CLK);
+       uint32_t timing0;
+
+       timing0 = readl(&i2c_regs->hw_i2c_timing0);
+       /*
+        * This is a reverse version of the algorithm presented in
+        * i2c_set_bus_speed(). Please refer there for details.
+        */
+       return clk / ((((timing0 >> 16) - 3) * 2) + 38);
+}
+
+void i2c_init(int speed, int slaveadd)
+{
+       mxs_i2c_reset();
+       i2c_set_bus_speed(speed);
+
        return;
 }
index 094305fdf932111b406a5546f707c5d28e4e89aa..af454f901c7b05b6c770dbc6bf47508b3fc166e0 100644 (file)
@@ -179,7 +179,8 @@ static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u8 *value)
                if (status & I2C_STAT_XRDY) {
                        w = tmpbuf[i++];
 #if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
-       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX))
+       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
+       defined(CONFIG_OMAP54XX))
                        w |= tmpbuf[i++] << 8;
 #endif
                        writew(w, &i2c_base->data);
@@ -209,7 +210,8 @@ static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u8 *value)
                }
                if (status & I2C_STAT_RRDY) {
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
-       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
+       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
+       defined(CONFIG_OMAP54XX)
                        *value = readb(&i2c_base->data);
 #else
                        *value = readw(&i2c_base->data);
@@ -239,7 +241,8 @@ static void flush_fifo(void)
                stat = readw(&i2c_base->stat);
                if (stat == I2C_STAT_RRDY) {
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
-       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
+       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
+       defined(CONFIG_OMAP54XX)
                        readb(&i2c_base->data);
 #else
                        readw(&i2c_base->data);
@@ -289,7 +292,8 @@ int i2c_probe(uchar chip)
                if (status & I2C_STAT_RRDY) {
                        res = 0;
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
-    defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)
+       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
+       defined(CONFIG_OMAP54XX)
                        readb(&i2c_base->data);
 #else
                        readw(&i2c_base->data);
@@ -376,7 +380,8 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
                if (status & I2C_STAT_XRDY) {
                        w = (i < 0) ? tmpbuf[2+i] : buffer[i];
 #if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
-       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX))
+       defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \
+       defined(CONFIG_OMAP54XX))
                        w |= ((++i < 0) ? tmpbuf[2+i] : buffer[i]) << 8;
 #endif
                        writew(w, &i2c_base->data);
index 9bc4c7f1d1c714a06d1a482631065feee0a928ee..90d297a28422ac9a4c7e568bfe1bd2edc2f26dff 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include <common.h>
-#ifdef CONFIG_EXYNOS5
+#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 #include <asm/arch/clk.h>
 #include <asm/arch/cpu.h>
 #else
@@ -62,7 +62,7 @@
 
 static unsigned int g_current_bus;     /* Stores Current I2C Bus */
 
-#ifndef CONFIG_EXYNOS5
+#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
 static int GetI2CSDA(void)
 {
        struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
@@ -121,7 +121,12 @@ static void ReadWriteByte(struct s3c24x0_i2c *i2c)
 
 static struct s3c24x0_i2c *get_base_i2c(void)
 {
-#ifdef CONFIG_EXYNOS5
+#ifdef CONFIG_EXYNOS4
+       struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
+                                                       + (EXYNOS4_I2C_SPACING
+                                                       * g_current_bus));
+       return i2c;
+#elif defined CONFIG_EXYNOS5
        struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
                                                        + (EXYNOS5_I2C_SPACING
                                                        * g_current_bus));
@@ -134,7 +139,7 @@ static struct s3c24x0_i2c *get_base_i2c(void)
 static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
 {
        ulong freq, pres = 16, div;
-#ifdef CONFIG_EXYNOS5
+#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
        freq = get_i2c_clk();
 #else
        freq = get_PCLK();
@@ -188,7 +193,7 @@ unsigned int i2c_get_bus_num(void)
 void i2c_init(int speed, int slaveadd)
 {
        struct s3c24x0_i2c *i2c;
-#ifndef CONFIG_EXYNOS5
+#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
        struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
 #endif
        int i;
@@ -204,7 +209,7 @@ void i2c_init(int speed, int slaveadd)
                i--;
        }
 
-#ifndef CONFIG_EXYNOS5
+#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
        if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
 #ifdef CONFIG_S3C2410
                ulong old_gpecon = readl(&gpio->gpecon);
@@ -248,7 +253,7 @@ void i2c_init(int speed, int slaveadd)
                writel(old_gpecon, &gpio->pgcon);
 #endif
        }
-#endif /* #ifndef CONFIG_EXYNOS5 */
+#endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */
        i2c_ch_init(i2c, speed, slaveadd);
 }
 
index 1595c0714a825efaca42f8210de6b41bc6b5ee6f..ae3c57392b8d011bcd36d862e3c062b751920b0f 100644 (file)
@@ -30,6 +30,9 @@
 #include <ioports.h>
 #include <asm/io.h>
 #endif
+#if defined(CONFIG_AVR32)
+#include <asm/arch/portmux.h>
+#endif
 #if defined(CONFIG_AT91FAMILY)
 #include <asm/io.h>
 #include <asm/arch/hardware.h>
index ab7a9e33ee0bf86e1539bc8e90a2b250d13c8f36..88471d3edf253e432458a44fb0c8d5ed29317d47 100644 (file)
@@ -63,6 +63,7 @@ static struct keyb {
        struct kbc_tegra *kbc;          /* tegra keyboard controller */
        unsigned char inited;           /* 1 if keyboard has been inited */
        unsigned char first_scan;       /* 1 if this is our first key scan */
+       unsigned char created;          /* 1 if driver has been created */
 
        /*
         * After init we must wait a short time before polling the keyboard.
@@ -306,6 +307,10 @@ static void tegra_kbc_open(void)
  */
 static int init_tegra_keyboard(void)
 {
+       /* check if already created */
+       if (config.created)
+               return 0;
+
 #ifdef CONFIG_OF_CONTROL
        int     node;
 
@@ -349,6 +354,7 @@ static int init_tegra_keyboard(void)
        config_kbc_gpio(config.kbc);
 
        tegra_kbc_open();
+       config.created = 1;
        debug("%s: Tegra keyboard ready\n", __func__);
 
        return 0;
@@ -357,6 +363,8 @@ static int init_tegra_keyboard(void)
 int drv_keyboard_init(void)
 {
        struct stdio_dev dev;
+       char *stdinname = getenv("stdin");
+       int error;
 
        if (input_init(&config.input, 0)) {
                debug("%s: Cannot set up input\n", __func__);
@@ -372,5 +380,13 @@ int drv_keyboard_init(void)
        dev.start = init_tegra_keyboard;
 
        /* Register the device. init_tegra_keyboard() will be called soon */
-       return input_stdio_register(&dev);
+       error = input_stdio_register(&dev);
+       if (error)
+               return error;
+#ifdef CONFIG_CONSOLE_MUX
+       error = iomux_doenv(stdin, stdinname);
+       if (error)
+               return error;
+#endif
+       return 0;
 }
index b141eafc7bb16ae0cdeeb704068b92b1e15a4983..d749ab095e3eecfe1d4070f5b37eacf5a9d3933b 100644 (file)
@@ -565,10 +565,11 @@ int tegra_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio)
        mmc->getcd = tegra_mmc_getcd;
 
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+       mmc->host_caps = 0;
        if (bus_width == 8)
-               mmc->host_caps = MMC_MODE_8BIT;
-       else
-               mmc->host_caps = MMC_MODE_4BIT;
+               mmc->host_caps |= MMC_MODE_8BIT;
+       if (bus_width >= 4)
+               mmc->host_caps |= MMC_MODE_4BIT;
        mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC;
 
        /*
index 4701be846c6f2005d4358cb1e4e6b9c6fd051d3f..e38e15125407bb0f2361ac04e96edae893294c7d 100644 (file)
@@ -1058,6 +1058,8 @@ int mxs_nand_init(struct mxs_nand_info *info)
 {
        struct mxs_gpmi_regs *gpmi_regs =
                (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
+       struct mxs_bch_regs *bch_regs =
+               (struct mxs_bch_regs *)MXS_BCH_BASE;
        int i = 0, j;
 
        info->desc = malloc(sizeof(struct mxs_dma_desc *) *
@@ -1081,6 +1083,7 @@ int mxs_nand_init(struct mxs_nand_info *info)
 
        /* Reset the GPMI block. */
        mxs_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+       mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
 
        /*
         * Choose NAND mode, set IRQ polarity, disable write protection and
index 2d4da4b386dd98caa822a3ecfa8417e396a0fc96..8ba98b27d52283be000f0896f838ca5e13eba591 100644 (file)
@@ -1688,6 +1688,16 @@ e1000_init_hw(struct eth_device *nic)
                E1000_WRITE_REG(hw, TXDCTL, ctrl);
        }
 
+       /* Set the receive descriptor write back policy */
+
+       if (hw->mac_type >= e1000_82571) {
+               ctrl = E1000_READ_REG(hw, RXDCTL);
+               ctrl =
+                   (ctrl & ~E1000_RXDCTL_WTHRESH) |
+                   E1000_RXDCTL_FULL_RX_DESC_WB;
+               E1000_WRITE_REG(hw, RXDCTL, ctrl);
+       }
+
        switch (hw->mac_type) {
        default:
                break;
index fd1d8f8717f2c90dc5b45cd869b52edfe6a224f9..1bbae5085ac9dac0fbf431c1c4bb8f231e50e9c1 100644 (file)
@@ -1551,6 +1551,7 @@ struct e1000_hw {
 #define E1000_RXDCTL_HTHRESH 0x00003F00        /* RXDCTL Host Threshold */
 #define E1000_RXDCTL_WTHRESH 0x003F0000        /* RXDCTL Writeback Threshold */
 #define E1000_RXDCTL_GRAN    0x01000000        /* RXDCTL Granularity */
+#define E1000_RXDCTL_FULL_RX_DESC_WB 0x01010000        /* GRAN=1, WTHRESH=1 */
 
 /* Transmit Descriptor Control */
 #define E1000_TXDCTL_PTHRESH 0x0000003F        /* TXDCTL Prefetch Threshold */
index e51e799e2933803ddc73401e6400b9db8a2d0b78..4b271989acbbaf5dbc8c4333e705f29ab0f9d642 100644 (file)
@@ -425,6 +425,16 @@ static struct phy_driver M88E1118_driver = {
        .shutdown = &genphy_shutdown,
 };
 
+static struct phy_driver M88E1118R_driver = {
+       .name = "Marvell 88E1118R",
+       .uid = 0x1410e40,
+       .mask = 0xffffff0,
+       .features = PHY_GBIT_FEATURES,
+       .config = &m88e1118_config,
+       .startup = &m88e1118_startup,
+       .shutdown = &genphy_shutdown,
+};
+
 static struct phy_driver M88E1121R_driver = {
        .name = "Marvell 88E1121R",
        .uid = 0x1410cb0,
@@ -461,6 +471,7 @@ int phy_marvell_init(void)
        phy_register(&M88E1145_driver);
        phy_register(&M88E1121R_driver);
        phy_register(&M88E1118_driver);
+       phy_register(&M88E1118R_driver);
        phy_register(&M88E1111S_driver);
        phy_register(&M88E1011S_driver);
 
index 2d9cc328b5919683481f6621533731a32afa5bd2..e6fc8c8bf6e44f5cb2e7cebf6b9866681aaac8ef 100644 (file)
@@ -417,7 +417,7 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
                printf(SHETHER_NAME ": 100Base/");
 #if defined(SH_ETH_TYPE_GETHER)
                sh_eth_write(eth, GECMR_100B, GECMR);
-#elif defined(CONFIG_CPU_SH7757)
+#elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
                sh_eth_write(eth, 1, RTRATE);
 #elif defined(CONFIG_CPU_SH7724)
                val = ECMR_RTM;
@@ -426,7 +426,7 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
                printf(SHETHER_NAME ": 10Base/");
 #if defined(SH_ETH_TYPE_GETHER)
                sh_eth_write(eth, GECMR_10B, GECMR);
-#elif defined(CONFIG_CPU_SH7757)
+#elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
                sh_eth_write(eth, 0, RTRATE);
 #endif
        }
index 61d2df9063f5b00e727b1b8594477020b6717483..568fafe5f51fc4318ce1a3c3976e3a72e54c34fe 100644 (file)
@@ -288,7 +288,7 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
 #if defined(CONFIG_CPU_SH7763) || defined(CONFIG_CPU_SH7734)
 #define SH_ETH_TYPE_GETHER
 #define BASE_IO_ADDR   0xfee00000
-#elif defined(CONFIG_CPU_SH7757)
+#elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
 #if defined(CONFIG_SH_ETHER_USE_GETHER)
 #define SH_ETH_TYPE_GETHER
 #define BASE_IO_ADDR   0xfee00000
@@ -346,7 +346,7 @@ enum DMAC_T_BIT {
 
 /* GECMR */
 enum GECMR_BIT {
-#if defined(CONFIG_CPU_SH7757)
+#if defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
        GECMR_1000B = 0x20, GECMR_100B = 0x01, GECMR_10B = 0x00,
 #else
        GECMR_1000B = 0x01, GECMR_100B = 0x04, GECMR_10B = 0x00,
index e19a9a81950cb7a9480f340e98724e6589e00976..14d426f560d8ec46e136a8c270d70c3a2514e75e 100644 (file)
@@ -28,6 +28,7 @@ LIB   := $(obj)libpmic.o
 COBJS-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
 COBJS-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
 COBJS-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
+COBJS-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
 
 COBJS  := $(COBJS-y)
 SRCS   := $(COBJS:.o=.c)
diff --git a/drivers/power/pmic/pmic_max77686.c b/drivers/power/pmic/pmic_max77686.c
new file mode 100644 (file)
index 0000000..fce0183
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Rajeshwari Shinde <rajeshwari.s@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 <power/pmic.h>
+#include <power/max77686_pmic.h>
+#include <errno.h>
+
+int pmic_init(unsigned char bus)
+{
+       static const char name[] = "MAX77686_PMIC";
+       struct pmic *p = pmic_alloc();
+
+       if (!p) {
+               printf("%s: POWER allocation error!\n", __func__);
+               return -ENOMEM;
+       }
+
+       puts("Board PMIC init\n");
+       p->name = name;
+       p->interface = PMIC_I2C;
+       p->number_of_regs = PMIC_NUM_OF_REGS;
+       p->hw.i2c.addr = MAX77686_I2C_ADDR;
+       p->hw.i2c.tx_num = 1;
+       p->bus = bus;
+
+       return 0;
+}
index f53c2bf003e32644cc384378693e463972b997c9..b590992dc81d6ea0c6004d0c85cd79a00751ec6a 100644 (file)
@@ -22,7 +22,8 @@
  */
 
 #include <common.h>
-
+#include <linux/compiler.h>
+#include <serial.h>
 #include <asm/arch/s3c6400.h>
 
 DECLARE_GLOBAL_DATA_PTR;
index f5f43a6ddc05e6c463843a497c4b53a768464a1f..1f8955a0fdb586c9cae12783d3e440641a8e8266 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <common.h>
+#include <environment.h>
 #include <serial.h>
 #include <stdio_dev.h>
 #include <post.h>
@@ -32,6 +33,11 @@ DECLARE_GLOBAL_DATA_PTR;
 
 static struct serial_device *serial_devices;
 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
@@ -45,6 +51,70 @@ static void serial_null(void)
 {
 }
 
+/**
+ * on_baudrate() - Update the actual baudrate when the env var changes
+ *
+ * This will check for a valid baudrate and only apply it if valid.
+ */
+static int on_baudrate(const char *name, const char *value, enum env_op op,
+       int flags)
+{
+       int i;
+       int baudrate;
+
+       switch (op) {
+       case env_op_create:
+       case env_op_overwrite:
+               /*
+                * Switch to new baudrate if new baudrate is supported
+                */
+               baudrate = simple_strtoul(value, NULL, 10);
+
+               /* Not actually changing */
+               if (gd->baudrate == baudrate)
+                       return 0;
+
+               for (i = 0; i < N_BAUDRATES; ++i) {
+                       if (baudrate == baudrate_table[i])
+                               break;
+               }
+               if (i == N_BAUDRATES) {
+                       if ((flags & H_FORCE) == 0)
+                               printf("## Baudrate %d bps not supported\n",
+                                       baudrate);
+                       return 1;
+               }
+               if ((flags & H_INTERACTIVE) != 0) {
+                       printf("## Switch baudrate to %d"
+                               " bps and press ENTER ...\n", baudrate);
+                       udelay(50000);
+               }
+
+               gd->baudrate = baudrate;
+#if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
+               gd->bd->bi_baudrate = baudrate;
+#endif
+
+               serial_setbrg();
+
+               udelay(50000);
+
+               if ((flags & H_INTERACTIVE) != 0)
+                       while (1) {
+                               if (getc() == '\r')
+                                       break;
+                       }
+
+               return 0;
+       case env_op_delete:
+               printf("## Baudrate may not be deleted\n");
+               return 1;
+       default:
+               return 0;
+       }
+}
+U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
+
 /**
  * serial_initfunc() - Forward declare of driver registration routine
  * @name:      Name of the real driver registration routine.
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
new file mode 100644 (file)
index 0000000..8fdffb1
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# R. Chandrasekar <rcsekar@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 $(TOPDIR)/config.mk
+
+LIB    := $(obj)libsound.o
+
+COBJS-$(CONFIG_SOUND)  += sound.o
+COBJS-$(CONFIG_I2S)    += samsung-i2s.o
+COBJS-$(CONFIG_SOUND_WM8994)   += wm8994.o
+
+COBJS  := $(COBJS-y)
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+all:   $(LIB)
+
+$(LIB):        $(obj).depend $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#
diff --git a/drivers/sound/samsung-i2s.c b/drivers/sound/samsung-i2s.c
new file mode 100644 (file)
index 0000000..9f3117d
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * R. Chandrasekar <rcsekar@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 <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/i2s-regs.h>
+#include <asm/io.h>
+#include <common.h>
+#include <sound.h>
+#include <i2s.h>
+
+#define FIC_TX2COUNT(x)                (((x) >>  24) & 0xf)
+#define FIC_TX1COUNT(x)                (((x) >>  16) & 0xf)
+#define FIC_TXCOUNT(x)         (((x) >>  8) & 0xf)
+#define FIC_RXCOUNT(x)         (((x) >>  0) & 0xf)
+#define FICS_TXCOUNT(x)                (((x) >>  8) & 0x7f)
+
+#define TIMEOUT_I2S_TX         100     /* i2s transfer timeout */
+
+/*
+ * Sets the frame size for I2S LR clock
+ *
+ * @param i2s_reg      i2s regiter address
+ * @param rfs          Frame Size
+ */
+static void i2s_set_lr_framesize(struct i2s_reg *i2s_reg, unsigned int rfs)
+{
+       unsigned int mod = readl(&i2s_reg->mod);
+
+       mod &= ~MOD_RCLK_MASK;
+
+       switch (rfs) {
+       case 768:
+               mod |= MOD_RCLK_768FS;
+               break;
+       case 512:
+               mod |= MOD_RCLK_512FS;
+               break;
+       case 384:
+               mod |= MOD_RCLK_384FS;
+               break;
+       default:
+               mod |= MOD_RCLK_256FS;
+               break;
+       }
+
+       writel(mod, &i2s_reg->mod);
+}
+
+/*
+ * Sets the i2s transfer control
+ *
+ * @param i2s_reg      i2s regiter address
+ * @param on           1 enable tx , 0 disable tx transfer
+ */
+static void i2s_txctrl(struct i2s_reg *i2s_reg, int on)
+{
+       unsigned int con = readl(&i2s_reg->con);
+       unsigned int mod = readl(&i2s_reg->mod) & ~MOD_MASK;
+
+       if (on) {
+               con |= CON_ACTIVE;
+               con &= ~CON_TXCH_PAUSE;
+
+       } else {
+
+               con |=  CON_TXCH_PAUSE;
+               con &= ~CON_ACTIVE;
+       }
+
+       writel(mod, &i2s_reg->mod);
+       writel(con, &i2s_reg->con);
+}
+
+/*
+ * set the bit clock frame size (in multiples of LRCLK)
+ *
+ * @param i2s_reg      i2s regiter address
+ * @param bfs          bit Frame Size
+ */
+static void i2s_set_bitclk_framesize(struct i2s_reg *i2s_reg, unsigned bfs)
+{
+       unsigned int mod = readl(&i2s_reg->mod);
+
+       mod &= ~MOD_BCLK_MASK;
+
+       switch (bfs) {
+       case 48:
+               mod |= MOD_BCLK_48FS;
+               break;
+       case 32:
+               mod |= MOD_BCLK_32FS;
+               break;
+       case 24:
+               mod |= MOD_BCLK_24FS;
+               break;
+       case 16:
+               mod |= MOD_BCLK_16FS;
+               break;
+       default:
+               return;
+       }
+       writel(mod, &i2s_reg->mod);
+}
+
+/*
+ * flushes the i2stx fifo
+ *
+ * @param i2s_reg      i2s regiter address
+ * @param flush                Tx fifo flush command (0x00 - do not flush
+ *                             0x80 - flush tx fifo)
+ */
+void i2s_fifo(struct i2s_reg *i2s_reg, unsigned int flush)
+{
+       /* Flush the FIFO */
+       setbits_le32(&i2s_reg->fic, flush);
+       clrbits_le32(&i2s_reg->fic, flush);
+}
+
+/*
+ * Set System Clock direction
+ *
+ * @param i2s_reg      i2s regiter address
+ * @param dir          Clock direction
+ *
+ * @return             int value 0 for success, -1 in case of error
+ */
+int i2s_set_sysclk_dir(struct i2s_reg *i2s_reg, int dir)
+{
+       unsigned int mod = readl(&i2s_reg->mod);
+
+       if (dir == SND_SOC_CLOCK_IN)
+               mod |= MOD_CDCLKCON;
+       else
+               mod &= ~MOD_CDCLKCON;
+
+       writel(mod, &i2s_reg->mod);
+
+       return 0;
+}
+
+/*
+ * Sets I2S Clcok format
+ *
+ * @param fmt          i2s clock properties
+ * @param i2s_reg      i2s regiter address
+ *
+ * @return             int value 0 for success, -1 in case of error
+ */
+int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt)
+{
+       unsigned int mod = readl(&i2s_reg->mod);
+       unsigned int tmp = 0;
+       unsigned int ret = 0;
+
+       /* Format is priority */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_RIGHT_J:
+               tmp |= MOD_LR_RLOW;
+               tmp |= MOD_SDF_MSB;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               tmp |= MOD_LR_RLOW;
+               tmp |= MOD_SDF_LSB;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               tmp |= MOD_SDF_IIS;
+               break;
+       default:
+               debug("%s: Invalid format priority [0x%x]\n", __func__,
+                       (fmt & SND_SOC_DAIFMT_FORMAT_MASK));
+               return -1;
+       }
+
+       /*
+        * INV flag is relative to the FORMAT flag - if set it simply
+        * flips the polarity specified by the Standard
+        */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               if (tmp & MOD_LR_RLOW)
+                       tmp &= ~MOD_LR_RLOW;
+               else
+                       tmp |= MOD_LR_RLOW;
+               break;
+       default:
+               debug("%s: Invalid clock ploarity input [0x%x]\n", __func__,
+                       (fmt & SND_SOC_DAIFMT_INV_MASK));
+               return -1;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               tmp |= MOD_SLAVE;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               /* Set default source clock in Master mode */
+               ret = i2s_set_sysclk_dir(i2s_reg, SND_SOC_CLOCK_OUT);
+               if (ret != 0) {
+                       debug("%s:set i2s clock direction failed\n", __func__);
+                       return -1;
+               }
+               break;
+       default:
+               debug("%s: Invalid master selection [0x%x]\n", __func__,
+                       (fmt & SND_SOC_DAIFMT_MASTER_MASK));
+               return -1;
+       }
+
+       mod &= ~(MOD_SDF_MASK | MOD_LR_RLOW | MOD_SLAVE);
+       mod |= tmp;
+       writel(mod, &i2s_reg->mod);
+
+       return 0;
+}
+
+/*
+ * Sets the sample width in bits
+ *
+ * @param blc          samplewidth (size of sample in bits)
+ * @param i2s_reg      i2s regiter address
+ *
+ * @return             int value 0 for success, -1 in case of error
+ */
+int i2s_set_samplesize(struct i2s_reg *i2s_reg, unsigned int blc)
+{
+       unsigned int mod = readl(&i2s_reg->mod);
+
+       mod &= ~MOD_BLCP_MASK;
+       mod &= ~MOD_BLC_MASK;
+
+       switch (blc) {
+       case 8:
+               mod |= MOD_BLCP_8BIT;
+               mod |= MOD_BLC_8BIT;
+               break;
+       case 16:
+               mod |= MOD_BLCP_16BIT;
+               mod |= MOD_BLC_16BIT;
+               break;
+       case 24:
+               mod |= MOD_BLCP_24BIT;
+               mod |= MOD_BLC_24BIT;
+               break;
+       default:
+               debug("%s: Invalid sample size input [0x%x]\n",
+                       __func__, blc);
+               return -1;
+       }
+       writel(mod, &i2s_reg->mod);
+
+       return 0;
+}
+
+int i2s_transfer_tx_data(struct i2stx_info *pi2s_tx, unsigned int *data,
+                               unsigned long data_size)
+{
+       int i;
+       int start;
+       struct i2s_reg *i2s_reg =
+                               (struct i2s_reg *)pi2s_tx->base_address;
+
+       if (data_size < FIFO_LENGTH) {
+               debug("%s : Invalid data size\n", __func__);
+               return -1; /* invalid pcm data size */
+       }
+
+       /* fill the tx buffer before stating the tx transmit */
+       for (i = 0; i < FIFO_LENGTH; i++)
+               writel(*data++, &i2s_reg->txd);
+
+       data_size -= FIFO_LENGTH;
+       i2s_txctrl(i2s_reg, I2S_TX_ON);
+
+       while (data_size > 0) {
+               start = get_timer(0);
+               if (!(CON_TXFIFO_FULL & (readl(&i2s_reg->con)))) {
+                       writel(*data++, &i2s_reg->txd);
+                       data_size--;
+               } else {
+                       if (get_timer(start) > TIMEOUT_I2S_TX) {
+                               i2s_txctrl(i2s_reg, I2S_TX_OFF);
+                               debug("%s: I2S Transfer Timeout\n", __func__);
+                               return -1;
+                       }
+               }
+       }
+       i2s_txctrl(i2s_reg, I2S_TX_OFF);
+
+       return 0;
+}
+
+int i2s_tx_init(struct i2stx_info *pi2s_tx)
+{
+       int ret;
+       struct i2s_reg *i2s_reg =
+                               (struct i2s_reg *)pi2s_tx->base_address;
+
+       /* Initialize GPIO for I2s */
+       exynos_pinmux_config(PERIPH_ID_I2S1, 0);
+
+       /* Set EPLL Clock */
+       ret = set_epll_clk(pi2s_tx->audio_pll_clk);
+       if (ret != 0) {
+               debug("%s: epll clock set rate falied\n", __func__);
+               return -1;
+       }
+
+       /* Select Clk Source for Audio1 */
+       set_i2s_clk_source();
+
+       /* Set Prescaler to get MCLK */
+       set_i2s_clk_prescaler(pi2s_tx->audio_pll_clk,
+                               (pi2s_tx->samplingrate * (pi2s_tx->rfs)));
+
+       /* Configure I2s format */
+       ret = i2s_set_fmt(i2s_reg, (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                               SND_SOC_DAIFMT_CBM_CFM));
+       if (ret == 0) {
+               i2s_set_lr_framesize(i2s_reg, pi2s_tx->rfs);
+               ret = i2s_set_samplesize(i2s_reg, pi2s_tx->bitspersample);
+               if (ret != 0) {
+                       debug("%s:set sample rate failed\n", __func__);
+                       return -1;
+               }
+
+               i2s_set_bitclk_framesize(i2s_reg, pi2s_tx->bfs);
+               /* disable i2s transfer flag and flush the fifo */
+               i2s_txctrl(i2s_reg, I2S_TX_OFF);
+               i2s_fifo(i2s_reg, FIC_TXFLUSH);
+       } else {
+               debug("%s: failed\n", __func__);
+       }
+
+       return ret;
+}
diff --git a/drivers/sound/sound.c b/drivers/sound/sound.c
new file mode 100644 (file)
index 0000000..4c74534
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * R. Chandrasekar <rcsekar@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 <malloc.h>
+#include <common.h>
+#include <asm/io.h>
+#include <i2c.h>
+#include <i2s.h>
+#include <sound.h>
+#include "wm8994.h"
+#include <asm/arch/sound.h>
+
+/* defines */
+#define SOUND_400_HZ 400
+#define SOUND_BITS_IN_BYTE 8
+
+static struct i2stx_info g_i2stx_pri;
+static struct sound_codec_info g_codec_info;
+
+/*
+ * get_sound_fdt_values gets fdt values for i2s parameters
+ *
+ * @param i2stx_info   i2s transmitter transfer param structure
+ * @param blob         FDT blob
+ */
+static void get_sound_i2s_values(struct i2stx_info *i2s)
+{
+       i2s->base_address = samsung_get_base_i2s();
+       i2s->audio_pll_clk = I2S_PLL_CLK;
+       i2s->samplingrate = I2S_SAMPLING_RATE;
+       i2s->bitspersample = I2S_BITS_PER_SAMPLE;
+       i2s->channels = I2S_CHANNELS;
+       i2s->rfs = I2S_RFS;
+       i2s->bfs = I2S_BFS;
+}
+
+/*
+ * Gets fdt values for wm8994 config parameters
+ *
+ * @param pcodec_info  codec information structure
+ * @param blob         FDT blob
+ * @return             int value, 0 for success
+ */
+static int get_sound_wm8994_values(struct sound_codec_info *pcodec_info)
+{
+       int error = 0;
+
+       switch (AUDIO_COMPAT) {
+       case AUDIO_COMPAT_SPI:
+               debug("%s: Support not added for SPI interface\n", __func__);
+               return -1;
+               break;
+       case AUDIO_COMPAT_I2C:
+               pcodec_info->i2c_bus = AUDIO_I2C_BUS;
+               pcodec_info->i2c_dev_addr = AUDIO_I2C_REG;
+               debug("i2c dev addr = %d\n", pcodec_info->i2c_dev_addr);
+               break;
+       default:
+               debug("%s: Unknown compat id %d\n", __func__, AUDIO_COMPAT);
+               return -1;
+       }
+
+       if (error == -1) {
+               debug("fail to get wm8994 codec node properties\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Gets fdt values for codec config parameters
+ *
+ * @param pcodec_info  codec information structure
+ * @param blob         FDT blob
+ * @return             int value, 0 for success
+ */
+static int get_sound_codec_values(struct sound_codec_info *pcodec_info)
+{
+       int error = 0;
+       const char *codectype;
+
+       codectype =  AUDIO_CODEC;
+
+       if (!strcmp(codectype, "wm8994")) {
+               pcodec_info->codec_type = CODEC_WM_8994;
+               error = get_sound_wm8994_values(pcodec_info);
+       } else {
+               error = -1;
+       }
+
+       if (error == -1) {
+               debug("fail to get sound codec node properties\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int sound_init(void)
+{
+       int ret;
+       struct i2stx_info *pi2s_tx = &g_i2stx_pri;
+       struct sound_codec_info *pcodec_info = &g_codec_info;
+
+       /* Get the I2S Values */
+       get_sound_i2s_values(pi2s_tx);
+
+       /* Get the codec Values */
+       if (get_sound_codec_values(pcodec_info) < 0)
+               return -1;
+
+       ret = i2s_tx_init(pi2s_tx);
+       if (ret) {
+               debug("%s: Failed to init i2c transmit: ret=%d\n", __func__,
+                     ret);
+               return ret;
+       }
+
+       /* Check the codec type and initialise the same */
+       if (pcodec_info->codec_type == CODEC_WM_8994) {
+               ret = wm8994_init(pcodec_info, WM8994_AIF2,
+                       pi2s_tx->samplingrate,
+                       (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+                       pi2s_tx->bitspersample, pi2s_tx->channels);
+       } else {
+               debug("%s: Unknown code type %d\n", __func__,
+                     pcodec_info->codec_type);
+               return -1;
+       }
+       if (ret) {
+               debug("%s: Codec init failed\n", __func__);
+               return -1;
+       }
+
+       return ret;
+}
+
+/*
+ * Generates square wave sound data for 1 second
+ *
+ * @param data          data buffer pointer
+ * @param size          size of the buffer
+ * @param freq          frequency of the wave
+ */
+static void sound_prepare_buffer(unsigned short *data, int size, uint32_t freq)
+{
+       const int sample = 48000;
+       const unsigned short amplitude = 16000; /* between 1 and 32767 */
+       const int period = freq ? sample / freq : 0;
+       const int half = period / 2;
+
+       assert(freq);
+
+       /* Make sure we don't overflow our buffer */
+       if (size % 2)
+               size--;
+
+       while (size) {
+               int i;
+               for (i = 0; size && i < half; i++) {
+                       size -= 2;
+                       *data++ = amplitude;
+                       *data++ = amplitude;
+               }
+               for (i = 0; size && i < period - half; i++) {
+                       size -= 2;
+                       *data++ = -amplitude;
+                       *data++ = -amplitude;
+               }
+       }
+}
+
+int sound_play(uint32_t msec, uint32_t frequency)
+{
+       unsigned int *data;
+       unsigned long data_size;
+       unsigned int ret = 0;
+
+       /*Buffer length computation */
+       data_size = g_i2stx_pri.samplingrate * g_i2stx_pri.channels;
+       data_size *= (g_i2stx_pri.bitspersample / SOUND_BITS_IN_BYTE);
+       data = malloc(data_size);
+
+       if (data == NULL) {
+               debug("%s: malloc failed\n", __func__);
+               return -1;
+       }
+
+       sound_prepare_buffer((unsigned short *)data,
+                               data_size / sizeof(unsigned short), frequency);
+
+       while (msec >= 1000) {
+               ret = i2s_transfer_tx_data(&g_i2stx_pri, data,
+                                          (data_size / sizeof(int)));
+               msec -= 1000;
+       }
+       if (msec) {
+               unsigned long size =
+                       (data_size * msec) / (sizeof(int) * 1000);
+
+               ret = i2s_transfer_tx_data(&g_i2stx_pri, data, size);
+       }
+
+       free(data);
+
+       return ret;
+}
diff --git a/drivers/sound/wm8994.c b/drivers/sound/wm8994.c
new file mode 100644 (file)
index 0000000..293903a
--- /dev/null
@@ -0,0 +1,792 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * R. Chandrasekar <rcsekar@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 <asm/arch/clk.h>
+#include <asm/arch/cpu.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <common.h>
+#include <div64.h>
+#include <i2c.h>
+#include <i2s.h>
+#include <sound.h>
+#include "wm8994.h"
+#include "wm8994_registers.h"
+
+/* defines for wm8994 system clock selection */
+#define SEL_MCLK1      0x00
+#define SEL_MCLK2      0x08
+#define SEL_FLL1       0x10
+#define SEL_FLL2       0x18
+
+/* fll config to configure fll */
+struct wm8994_fll_config {
+       int src;        /* Source */
+       int in;         /* Input frequency in Hz */
+       int out;        /* output frequency in Hz */
+};
+
+/* codec private data */
+struct wm8994_priv {
+       enum wm8994_type type;          /* codec type of wolfson */
+       int revision;                   /* Revision */
+       int sysclk[WM8994_MAX_AIF];     /* System clock frequency in Hz  */
+       int mclk[WM8994_MAX_AIF];       /* master clock frequency in Hz */
+       int aifclk[WM8994_MAX_AIF];     /* audio interface clock in Hz   */
+       struct wm8994_fll_config fll[2]; /* fll config to configure fll */
+};
+
+/* wm 8994 supported sampling rate values */
+static unsigned int src_rate[] = {
+                        8000, 11025, 12000, 16000, 22050, 24000,
+                        32000, 44100, 48000, 88200, 96000
+};
+
+/* op clock divisions */
+static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
+
+/* lr clock frame size ratio */
+static int fs_ratios[] = {
+       64, 128, 192, 256, 348, 512, 768, 1024, 1408, 1536
+};
+
+/* bit clock divisors */
+static int bclk_divs[] = {
+       10, 15, 20, 30, 40, 50, 60, 80, 110, 120, 160, 220, 240, 320, 440, 480,
+       640, 880, 960, 1280, 1760, 1920
+};
+
+static struct wm8994_priv g_wm8994_info;
+static unsigned char g_wm8994_i2c_dev_addr;
+
+/*
+ * Initialise I2C for wm 8994
+ *
+ * @param bus no       i2c bus number in which wm8994 is connected
+ */
+static void wm8994_i2c_init(int bus_no)
+{
+       i2c_set_bus_num(bus_no);
+}
+
+/*
+ * Writes value to a device register through i2c
+ *
+ * @param reg  reg number to be write
+ * @param data data to be writen to the above registor
+ *
+ * @return     int value 1 for change, 0 for no change or negative error code.
+ */
+static int wm8994_i2c_write(unsigned int reg, unsigned short data)
+{
+       unsigned char val[2];
+
+       val[0] = (unsigned char)((data >> 8) & 0xff);
+       val[1] = (unsigned char)(data & 0xff);
+       debug("Write Addr : 0x%04X, Data :  0x%04X\n", reg, data);
+
+       return i2c_write(g_wm8994_i2c_dev_addr, reg, 2, val, 2);
+}
+
+/*
+ * Read a value from a device register through i2c
+ *
+ * @param reg  reg number to be read
+ * @param data address of read data to be stored
+ *
+ * @return     int value 0 for success, -1 in case of error.
+ */
+static unsigned int  wm8994_i2c_read(unsigned int reg , unsigned short *data)
+{
+       unsigned char val[2];
+       int ret;
+
+       ret = i2c_read(g_wm8994_i2c_dev_addr, reg, 2, val, 2);
+       if (ret != 0) {
+               debug("%s: Error while reading register %#04x\n",
+                     __func__, reg);
+               return -1;
+       }
+
+       *data = val[0];
+       *data <<= 8;
+       *data |= val[1];
+
+       return 0;
+}
+
+/*
+ * update device register bits through i2c
+ *
+ * @param reg  codec register
+ * @param mask register mask
+ * @param value        new value
+ *
+ * @return int value 1 if change in the register value,
+ * 0 for no change or negative error code.
+ */
+static int wm8994_update_bits(unsigned int reg, unsigned short mask,
+                                               unsigned short value)
+{
+       int change , ret = 0;
+       unsigned short old, new;
+
+       if (wm8994_i2c_read(reg, &old) != 0)
+               return -1;
+       new = (old & ~mask) | (value & mask);
+       change  = (old != new) ? 1 : 0;
+       if (change)
+               ret = wm8994_i2c_write(reg, new);
+       if (ret < 0)
+               return ret;
+
+       return change;
+}
+
+/*
+ * Sets i2s set format
+ *
+ * @param aif_id       Interface ID
+ * @param fmt          i2S format
+ *
+ * @return -1 for error and 0  Success.
+ */
+int wm8994_set_fmt(int aif_id, unsigned int fmt)
+{
+       int ms_reg;
+       int aif_reg;
+       int ms = 0;
+       int aif = 0;
+       int aif_clk = 0;
+       int error = 0;
+
+       switch (aif_id) {
+       case 1:
+               ms_reg = WM8994_AIF1_MASTER_SLAVE;
+               aif_reg = WM8994_AIF1_CONTROL_1;
+               aif_clk = WM8994_AIF1_CLOCKING_1;
+               break;
+       case 2:
+               ms_reg = WM8994_AIF2_MASTER_SLAVE;
+               aif_reg = WM8994_AIF2_CONTROL_1;
+               aif_clk = WM8994_AIF2_CLOCKING_1;
+               break;
+       default:
+               debug("%s: Invalid audio interface selection\n", __func__);
+               return -1;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               ms = WM8994_AIF1_MSTR;
+               break;
+       default:
+               debug("%s: Invalid i2s master selection\n", __func__);
+               return -1;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_B:
+               aif |= WM8994_AIF1_LRCLK_INV;
+       case SND_SOC_DAIFMT_DSP_A:
+               aif |= 0x18;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               aif |= 0x10;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               aif |= 0x8;
+               break;
+       default:
+               debug("%s: Invalid i2s format selection\n", __func__);
+               return -1;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               /* frame inversion not valid for DSP modes */
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       aif |= WM8994_AIF1_BCLK_INV;
+                       break;
+               default:
+                       debug("%s: Invalid i2s frame inverse selection\n",
+                             __func__);
+                       return -1;
+               }
+               break;
+
+       case SND_SOC_DAIFMT_I2S:
+       case SND_SOC_DAIFMT_RIGHT_J:
+       case SND_SOC_DAIFMT_LEFT_J:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       aif |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       aif |= WM8994_AIF1_BCLK_INV;
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       aif |= WM8994_AIF1_LRCLK_INV;
+                       break;
+               default:
+                       debug("%s: Invalid i2s clock polarity selection\n",
+                             __func__);
+                       return -1;
+               }
+               break;
+       default:
+               debug("%s: Invalid i2s format selection\n", __func__);
+               return -1;
+       }
+
+       error = wm8994_update_bits(aif_reg, WM8994_AIF1_BCLK_INV |
+                       WM8994_AIF1_LRCLK_INV_MASK | WM8994_AIF1_FMT_MASK, aif);
+
+       error |= wm8994_update_bits(ms_reg, WM8994_AIF1_MSTR_MASK, ms);
+       error |= wm8994_update_bits(aif_clk, WM8994_AIF1CLK_ENA_MASK,
+                                               WM8994_AIF1CLK_ENA);
+       if (error < 0) {
+               debug("%s: codec register access error\n", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Sets hw params FOR WM8994
+ *
+ * @param wm8994               wm8994 information pointer
+ * @param aif_id               Audio interface ID
+ * @param sampling_rate                Sampling rate
+ * @param bits_per_sample      Bits per sample
+ * @param Channels             Channels in the given audio input
+ *
+ * @return -1 for error  and 0  Success.
+ */
+static int wm8994_hw_params(struct wm8994_priv *wm8994, int aif_id,
+               unsigned int sampling_rate, unsigned int bits_per_sample,
+               unsigned int channels)
+{
+       int aif1_reg;
+       int aif2_reg;
+       int bclk_reg;
+       int bclk = 0;
+       int rate_reg;
+       int aif1 = 0;
+       int aif2 = 0;
+       int rate_val = 0;
+       int id = aif_id - 1;
+       int i, cur_val, best_val, bclk_rate, best;
+       unsigned short reg_data;
+       int ret = 0;
+
+       switch (aif_id) {
+       case 1:
+               aif1_reg = WM8994_AIF1_CONTROL_1;
+               aif2_reg = WM8994_AIF1_CONTROL_2;
+               bclk_reg = WM8994_AIF1_BCLK;
+               rate_reg = WM8994_AIF1_RATE;
+               break;
+       case 2:
+               aif1_reg = WM8994_AIF2_CONTROL_1;
+               aif2_reg = WM8994_AIF2_CONTROL_2;
+               bclk_reg = WM8994_AIF2_BCLK;
+               rate_reg = WM8994_AIF2_RATE;
+               break;
+       default:
+               return -1;
+       }
+
+       bclk_rate = sampling_rate * 32;
+       switch (bits_per_sample) {
+       case 16:
+               bclk_rate *= 16;
+               break;
+       case 20:
+               bclk_rate *= 20;
+               aif1 |= 0x20;
+               break;
+       case 24:
+               bclk_rate *= 24;
+               aif1 |= 0x40;
+               break;
+       case 32:
+               bclk_rate *= 32;
+               aif1 |= 0x60;
+               break;
+       default:
+               return -1;
+       }
+
+       /* Try to find an appropriate sample rate; look for an exact match. */
+       for (i = 0; i < ARRAY_SIZE(src_rate); i++)
+               if (src_rate[i] == sampling_rate)
+                       break;
+
+       if (i == ARRAY_SIZE(src_rate)) {
+               debug("%s: Could not get the best matching samplingrate\n",
+                     __func__);
+               return -1;
+       }
+
+       rate_val |= i << WM8994_AIF1_SR_SHIFT;
+
+       /* AIFCLK/fs ratio; look for a close match in either direction */
+       best = 0;
+       best_val = abs((fs_ratios[0] * sampling_rate)
+                                               - wm8994->aifclk[id]);
+
+       for (i = 1; i < ARRAY_SIZE(fs_ratios); i++) {
+               cur_val = abs((fs_ratios[i] * sampling_rate)
+                                       - wm8994->aifclk[id]);
+               if (cur_val >= best_val)
+                       continue;
+               best = i;
+               best_val = cur_val;
+       }
+
+       rate_val |= best;
+
+       /*
+        * We may not get quite the right frequency if using
+        * approximate clocks so look for the closest match that is
+        * higher than the target (we need to ensure that there enough
+        * BCLKs to clock out the samples).
+        */
+       best = 0;
+       for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
+               cur_val = (wm8994->aifclk[id] * 10 / bclk_divs[i]) - bclk_rate;
+               if (cur_val < 0) /* BCLK table is sorted */
+                       break;
+               best = i;
+       }
+
+       if (i ==  ARRAY_SIZE(bclk_divs)) {
+               debug("%s: Could not get the best matching bclk division\n",
+                     __func__);
+               return -1;
+       }
+
+       bclk_rate = wm8994->aifclk[id] * 10 / bclk_divs[best];
+       bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT;
+
+       if (wm8994_i2c_read(aif1_reg, &reg_data) != 0) {
+               debug("%s: AIF1 register read Failed\n", __func__);
+               return -1;
+       }
+
+       if ((channels == 1) && ((reg_data & 0x18) == 0x18))
+               aif2 |= WM8994_AIF1_MONO;
+
+       if (wm8994->aifclk[id] == 0) {
+               debug("%s:Audio interface clock not set\n", __func__);
+               return -1;
+       }
+
+       ret = wm8994_update_bits(aif1_reg, WM8994_AIF1_WL_MASK, aif1);
+       ret |= wm8994_update_bits(aif2_reg, WM8994_AIF1_MONO, aif2);
+       ret |= wm8994_update_bits(bclk_reg, WM8994_AIF1_BCLK_DIV_MASK, bclk);
+       ret |= wm8994_update_bits(rate_reg, WM8994_AIF1_SR_MASK |
+                               WM8994_AIF1CLK_RATE_MASK, rate_val);
+
+       debug("rate vale = %x , bclk val= %x\n", rate_val, bclk);
+
+       if (ret < 0) {
+               debug("%s: codec register access error\n", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Configures Audio interface Clock
+ *
+ * @param wm8994       wm8994 information pointer
+ * @param aif          Audio Interface ID
+ *
+ * @return -1 for error  and 0  Success.
+ */
+static int configure_aif_clock(struct wm8994_priv *wm8994, int aif)
+{
+       int rate;
+       int reg1 = 0;
+       int offset;
+       int ret;
+
+       /* AIF(1/0) register adress offset calculated */
+       if (aif)
+               offset = 4;
+       else
+               offset = 0;
+
+       switch (wm8994->sysclk[aif]) {
+       case WM8994_SYSCLK_MCLK1:
+               reg1 |= SEL_MCLK1;
+               rate = wm8994->mclk[0];
+               break;
+
+       case WM8994_SYSCLK_MCLK2:
+               reg1 |= SEL_MCLK2;
+               rate = wm8994->mclk[1];
+               break;
+
+       case WM8994_SYSCLK_FLL1:
+               reg1 |= SEL_FLL1;
+               rate = wm8994->fll[0].out;
+               break;
+
+       case WM8994_SYSCLK_FLL2:
+               reg1 |= SEL_FLL2;
+               rate = wm8994->fll[1].out;
+               break;
+
+       default:
+               debug("%s: Invalid input clock selection [%d]\n",
+                     __func__, wm8994->sysclk[aif]);
+               return -1;
+       }
+
+       /* if input clock frequenct is more than 135Mhz then divide */
+       if (rate >= WM8994_MAX_INPUT_CLK_FREQ) {
+               rate /= 2;
+               reg1 |= WM8994_AIF1CLK_DIV;
+       }
+
+       wm8994->aifclk[aif] = rate;
+
+       ret = wm8994_update_bits(WM8994_AIF1_CLOCKING_1 + offset,
+                               WM8994_AIF1CLK_SRC_MASK | WM8994_AIF1CLK_DIV,
+                               reg1);
+
+       ret |= wm8994_update_bits(WM8994_CLOCKING_1,
+                       WM8994_SYSCLK_SRC | WM8994_AIF2DSPCLK_ENA_MASK |
+                       WM8994_SYSDSPCLK_ENA_MASK, WM8994_SYSCLK_SRC |
+                       WM8994_AIF2DSPCLK_ENA | WM8994_SYSDSPCLK_ENA);
+
+       if (ret < 0) {
+               debug("%s: codec register access error\n", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Configures Audio interface  for the given frequency
+ *
+ * @param wm8994       wm8994 information
+ * @param aif_id       Audio Interface
+ * @param clk_id       Input Clock ID
+ * @param freq         Sampling frequency in Hz
+ *
+ * @return -1 for error and 0 success.
+ */
+static int wm8994_set_sysclk(struct wm8994_priv *wm8994, int aif_id,
+                               int clk_id, unsigned int freq)
+{
+       int i;
+       int ret = 0;
+
+       wm8994->sysclk[aif_id - 1] = clk_id;
+
+       switch (clk_id) {
+       case WM8994_SYSCLK_MCLK1:
+               wm8994->mclk[0] = freq;
+               if (aif_id == 2) {
+                       ret = wm8994_update_bits(WM8994_AIF1_CLOCKING_2 ,
+                       WM8994_AIF2DAC_DIV_MASK , 0);
+               }
+               break;
+
+       case WM8994_SYSCLK_MCLK2:
+               /* TODO: Set GPIO AF */
+               wm8994->mclk[1] = freq;
+               break;
+
+       case WM8994_SYSCLK_FLL1:
+       case WM8994_SYSCLK_FLL2:
+               break;
+
+       case WM8994_SYSCLK_OPCLK:
+               /*
+                * Special case - a division (times 10) is given and
+                * no effect on main clocking.
+                */
+               if (freq) {
+                       for (i = 0; i < ARRAY_SIZE(opclk_divs); i++)
+                               if (opclk_divs[i] == freq)
+                                       break;
+                       if (i == ARRAY_SIZE(opclk_divs)) {
+                               debug("%s frequency divisor not found\n",
+                                       __func__);
+                               return -1;
+                       }
+                       ret = wm8994_update_bits(WM8994_CLOCKING_2,
+                                           WM8994_OPCLK_DIV_MASK, i);
+                       ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_2,
+                                           WM8994_OPCLK_ENA, WM8994_OPCLK_ENA);
+               } else {
+                       ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_2,
+                                           WM8994_OPCLK_ENA, 0);
+               }
+
+       default:
+               debug("%s Invalid input clock selection [%d]\n",
+                     __func__, clk_id);
+               return -1;
+       }
+
+       ret |= configure_aif_clock(wm8994, aif_id - 1);
+
+       if (ret < 0) {
+               debug("%s: codec register access error\n", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Initializes Volume for AIF2 to HP path
+ *
+ * @returns -1 for error  and 0 Success.
+ *
+ */
+static int wm8994_init_volume_aif2_dac1(void)
+{
+       int ret;
+
+       /* Unmute AIF2DAC */
+       ret = wm8994_update_bits(WM8994_AIF2_DAC_FILTERS_1,
+                       WM8994_AIF2DAC_MUTE_MASK, 0);
+
+
+       ret |= wm8994_update_bits(WM8994_AIF2_DAC_LEFT_VOLUME,
+                       WM8994_AIF2DAC_VU_MASK | WM8994_AIF2DACL_VOL_MASK,
+                       WM8994_AIF2DAC_VU | 0xff);
+
+       ret |= wm8994_update_bits(WM8994_AIF2_DAC_RIGHT_VOLUME,
+                       WM8994_AIF2DAC_VU_MASK | WM8994_AIF2DACR_VOL_MASK,
+                       WM8994_AIF2DAC_VU | 0xff);
+
+
+       ret |= wm8994_update_bits(WM8994_DAC1_LEFT_VOLUME,
+                       WM8994_DAC1_VU_MASK | WM8994_DAC1L_VOL_MASK |
+                       WM8994_DAC1L_MUTE_MASK, WM8994_DAC1_VU | 0xc0);
+
+       ret |= wm8994_update_bits(WM8994_DAC1_RIGHT_VOLUME,
+                       WM8994_DAC1_VU_MASK | WM8994_DAC1R_VOL_MASK |
+                       WM8994_DAC1R_MUTE_MASK, WM8994_DAC1_VU | 0xc0);
+       /* Head Phone Volume */
+       ret |= wm8994_i2c_write(WM8994_LEFT_OUTPUT_VOLUME, 0x12D);
+       ret |= wm8994_i2c_write(WM8994_RIGHT_OUTPUT_VOLUME, 0x12D);
+
+       if (ret < 0) {
+               debug("%s: codec register access error\n", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Intialise wm8994 codec device
+ *
+ * @param wm8994       wm8994 information
+ *
+ * @returns -1 for error  and 0 Success.
+ */
+static int wm8994_device_init(struct wm8994_priv *wm8994)
+{
+       const char *devname;
+       unsigned short reg_data;
+       int ret;
+
+       wm8994_i2c_write(WM8994_SOFTWARE_RESET, WM8994_SW_RESET);/* Reset */
+
+       ret = wm8994_i2c_read(WM8994_SOFTWARE_RESET, &reg_data);
+       if (ret < 0) {
+               debug("Failed to read ID register\n");
+               goto err;
+       }
+
+       if (reg_data == WM8994_ID) {
+               devname = "WM8994";
+               debug("Device registered as type %d\n", wm8994->type);
+               wm8994->type = WM8994;
+       } else {
+               debug("Device is not a WM8994, ID is %x\n", ret);
+               ret = -1;
+               goto err;
+       }
+
+       ret = wm8994_i2c_read(WM8994_CHIP_REVISION, &reg_data);
+       if (ret < 0) {
+               debug("Failed to read revision register: %d\n", ret);
+               goto err;
+       }
+       wm8994->revision = reg_data;
+       debug("%s revision %c\n", devname, 'A' + wm8994->revision);
+
+       /* VMID Selection */
+       ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_1,
+                       WM8994_VMID_SEL_MASK | WM8994_BIAS_ENA_MASK, 0x3);
+
+       /* Charge Pump Enable */
+       ret |= wm8994_update_bits(WM8994_CHARGE_PUMP_1, WM8994_CP_ENA_MASK,
+                                       WM8994_CP_ENA);
+
+       /* Head Phone Power Enable */
+       ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_1,
+                       WM8994_HPOUT1L_ENA_MASK, WM8994_HPOUT1L_ENA);
+
+       ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_1,
+                               WM8994_HPOUT1R_ENA_MASK, WM8994_HPOUT1R_ENA);
+
+       /* Power enable for AIF2 and DAC1 */
+       ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_5,
+               WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK |
+               WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK,
+               WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA | WM8994_DAC1L_ENA |
+               WM8994_DAC1R_ENA);
+
+       /* Head Phone Initialisation */
+       ret |= wm8994_update_bits(WM8994_ANALOGUE_HP_1,
+               WM8994_HPOUT1L_DLY_MASK | WM8994_HPOUT1R_DLY_MASK,
+               WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_DLY);
+
+       ret |= wm8994_update_bits(WM8994_DC_SERVO_1,
+                       WM8994_DCS_ENA_CHAN_0_MASK |
+                       WM8994_DCS_ENA_CHAN_1_MASK , WM8994_DCS_ENA_CHAN_0 |
+                       WM8994_DCS_ENA_CHAN_1);
+
+       ret |= wm8994_update_bits(WM8994_ANALOGUE_HP_1,
+                       WM8994_HPOUT1L_DLY_MASK |
+                       WM8994_HPOUT1R_DLY_MASK | WM8994_HPOUT1L_OUTP_MASK |
+                       WM8994_HPOUT1R_OUTP_MASK |
+                       WM8994_HPOUT1L_RMV_SHORT_MASK |
+                       WM8994_HPOUT1R_RMV_SHORT_MASK, WM8994_HPOUT1L_DLY |
+                       WM8994_HPOUT1R_DLY | WM8994_HPOUT1L_OUTP |
+                       WM8994_HPOUT1R_OUTP | WM8994_HPOUT1L_RMV_SHORT |
+                       WM8994_HPOUT1R_RMV_SHORT);
+
+       /* MIXER Config DAC1 to HP */
+       ret |= wm8994_update_bits(WM8994_OUTPUT_MIXER_1,
+                       WM8994_DAC1L_TO_HPOUT1L_MASK, WM8994_DAC1L_TO_HPOUT1L);
+
+       ret |= wm8994_update_bits(WM8994_OUTPUT_MIXER_2,
+                       WM8994_DAC1R_TO_HPOUT1R_MASK, WM8994_DAC1R_TO_HPOUT1R);
+
+       /* Routing AIF2 to DAC1 */
+       ret |= wm8994_update_bits(WM8994_DAC1_LEFT_MIXER_ROUTING,
+                       WM8994_AIF2DACL_TO_DAC1L_MASK,
+                       WM8994_AIF2DACL_TO_DAC1L);
+
+       ret |= wm8994_update_bits(WM8994_DAC1_RIGHT_MIXER_ROUTING,
+                       WM8994_AIF2DACR_TO_DAC1R_MASK,
+                       WM8994_AIF2DACR_TO_DAC1R);
+
+        /* GPIO Settings for AIF2 */
+        /* B CLK */
+       ret |= wm8994_update_bits(WM8994_GPIO_3, WM8994_GPIO_DIR_MASK |
+                               WM8994_GPIO_FUNCTION_MASK ,
+                               WM8994_GPIO_DIR_OUTPUT |
+                               WM8994_GPIO_FUNCTION_I2S_CLK);
+
+       /* LR CLK */
+       ret |= wm8994_update_bits(WM8994_GPIO_4, WM8994_GPIO_DIR_MASK |
+                               WM8994_GPIO_FUNCTION_MASK,
+                               WM8994_GPIO_DIR_OUTPUT |
+                               WM8994_GPIO_FUNCTION_I2S_CLK);
+
+       /* DATA */
+       ret |= wm8994_update_bits(WM8994_GPIO_5, WM8994_GPIO_DIR_MASK |
+                               WM8994_GPIO_FUNCTION_MASK,
+                               WM8994_GPIO_DIR_OUTPUT |
+                               WM8994_GPIO_FUNCTION_I2S_CLK);
+
+       ret |= wm8994_init_volume_aif2_dac1();
+       if (ret < 0)
+               goto err;
+
+       debug("%s: Codec chip init ok\n", __func__);
+       return 0;
+err:
+       debug("%s: Codec chip init error\n", __func__);
+       return -1;
+}
+
+/*wm8994 Device Initialisation */
+int wm8994_init(struct sound_codec_info *pcodec_info,
+                       enum en_audio_interface aif_id,
+                       int sampling_rate, int mclk_freq,
+                       int bits_per_sample, unsigned int channels)
+{
+       int ret = 0;
+
+       /* shift the device address by 1 for 7 bit addressing */
+       g_wm8994_i2c_dev_addr = pcodec_info->i2c_dev_addr;
+       wm8994_i2c_init(pcodec_info->i2c_bus);
+
+       if (pcodec_info->codec_type == CODEC_WM_8994)
+               g_wm8994_info.type = WM8994;
+       else {
+               debug("%s: Codec id [%d] not defined\n", __func__,
+                               pcodec_info->codec_type);
+               return -1;
+       }
+
+       ret = wm8994_device_init(&g_wm8994_info);
+       if (ret < 0) {
+               debug("%s: wm8994 codec chip init failed\n", __func__);
+               return ret;
+       }
+
+       ret =  wm8994_set_sysclk(&g_wm8994_info, aif_id, WM8994_SYSCLK_MCLK1,
+                                                       mclk_freq);
+       if (ret < 0) {
+               debug("%s: wm8994 codec set sys clock failed\n", __func__);
+               return ret;
+       }
+
+       ret = wm8994_hw_params(&g_wm8994_info, aif_id, sampling_rate,
+                                               bits_per_sample, channels);
+
+       if (ret == 0) {
+               ret = wm8994_set_fmt(aif_id, SND_SOC_DAIFMT_I2S |
+                                               SND_SOC_DAIFMT_NB_NF |
+                                               SND_SOC_DAIFMT_CBS_CFS);
+       }
+       return ret;
+}
diff --git a/drivers/sound/wm8994.h b/drivers/sound/wm8994.h
new file mode 100644 (file)
index 0000000..a8f0de1
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * R. Chadrasekar <rcsekar@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
+ */
+
+#ifndef __WM8994_H__
+#define __WM8994_H__
+
+/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
+#define WM8994_SYSCLK_MCLK1    1
+#define WM8994_SYSCLK_MCLK2    2
+#define WM8994_SYSCLK_FLL1     3
+#define WM8994_SYSCLK_FLL2     4
+
+/*  Avilable audi interface ports in wm8994 codec */
+enum en_audio_interface {
+        WM8994_AIF1 = 1,
+        WM8994_AIF2,
+        WM8994_AIF3
+};
+
+/* OPCLK is also configured with set_dai_sysclk, specify division*10 as rate. */
+#define WM8994_SYSCLK_OPCLK    5
+
+#define WM8994_FLL1    1
+#define WM8994_FLL2    2
+
+#define WM8994_FLL_SRC_MCLK1   1
+#define WM8994_FLL_SRC_MCLK2   2
+#define WM8994_FLL_SRC_LRCLK   3
+#define WM8994_FLL_SRC_BCLK    4
+
+/* maximum available digital interfac in the dac to configure */
+#define WM8994_MAX_AIF                 2
+
+#define WM8994_MAX_INPUT_CLK_FREQ      13500000
+#define WM8994_ID                      0x8994
+
+enum wm8994_vmid_mode {
+       WM8994_VMID_NORMAL,
+       WM8994_VMID_FORCE,
+};
+
+/* wm 8994 family devices */
+enum wm8994_type {
+       WM8994 = 0,
+       WM8958 = 1,
+       WM1811 = 2,
+};
+
+/*
+ * intialise wm8994 sound codec device for the given configuration
+ *
+ * @param pcodec_info          pointer value of the sound codec info structure
+ *                             parsed from device tree
+ * @param aif_id               enum value of codec interface port in which
+ *                             soc i2s is connected
+ * @param sampling_rate                Sampling rate ranges between from 8khz to 96khz
+ * @param mclk_freq            Master clock frequency.
+ * @param bits_per_sample      bits per Sample can be 16 or 24
+ * @param channels             Number of channnels, maximum 2
+ *
+ * @returns -1 for error  and 0  Success.
+ */
+int wm8994_init(struct sound_codec_info *pcodec_info,
+                       enum en_audio_interface aif_id,
+                       int sampling_rate, int mclk_freq,
+                       int bits_per_sample, unsigned int channels);
+#endif /*__WM8994_H__ */
diff --git a/drivers/sound/wm8994_registers.h b/drivers/sound/wm8994_registers.h
new file mode 100644 (file)
index 0000000..f455b11
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * (C) Copyright 2012 Samsung Electronics
+ *
+ *  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 __WM8994_REGISTERS_H__
+#define __WM8994_REGISTERS_H__
+
+/*
+ * Register values.
+ */
+#define WM8994_SOFTWARE_RESET                   0x00
+#define WM8994_POWER_MANAGEMENT_1               0x01
+#define WM8994_POWER_MANAGEMENT_2               0x02
+#define WM8994_POWER_MANAGEMENT_5               0x05
+#define WM8994_LEFT_OUTPUT_VOLUME               0x1C
+#define WM8994_RIGHT_OUTPUT_VOLUME              0x1D
+#define WM8994_OUTPUT_MIXER_1                   0x2D
+#define WM8994_OUTPUT_MIXER_2                   0x2E
+#define WM8994_CHARGE_PUMP_1                    0x4C
+#define WM8994_DC_SERVO_1                       0x54
+#define WM8994_ANALOGUE_HP_1                    0x60
+#define WM8994_CHIP_REVISION                    0x100
+#define WM8994_AIF1_CLOCKING_1                  0x200
+#define WM8994_AIF1_CLOCKING_2                  0x201
+#define WM8994_AIF2_CLOCKING_1                  0x204
+#define WM8994_CLOCKING_1                       0x208
+#define WM8994_CLOCKING_2                       0x209
+#define WM8994_AIF1_RATE                        0x210
+#define WM8994_AIF2_RATE                        0x211
+#define WM8994_RATE_STATUS                      0x212
+#define WM8994_AIF1_CONTROL_1                   0x300
+#define WM8994_AIF1_CONTROL_2                   0x301
+#define WM8994_AIF1_MASTER_SLAVE                0x302
+#define WM8994_AIF1_BCLK                        0x303
+#define WM8994_AIF2_CONTROL_1                   0x310
+#define WM8994_AIF2_CONTROL_2                   0x311
+#define WM8994_AIF2_MASTER_SLAVE                0x312
+#define WM8994_AIF2_BCLK                        0x313
+#define WM8994_AIF2_DAC_LEFT_VOLUME             0x502
+#define WM8994_AIF2_DAC_RIGHT_VOLUME            0x503
+#define WM8994_AIF2_DAC_FILTERS_1               0x520
+#define WM8994_DAC1_LEFT_MIXER_ROUTING          0x601
+#define WM8994_DAC1_RIGHT_MIXER_ROUTING         0x602
+#define WM8994_DAC1_LEFT_VOLUME                 0x610
+#define WM8994_DAC1_RIGHT_VOLUME                0x611
+#define WM8994_GPIO_3                           0x702
+#define WM8994_GPIO_4                           0x703
+#define WM8994_GPIO_5                           0x704
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+/* SW_RESET */
+#define WM8994_SW_RESET                              1
+/*
+ * R1 (0x01) - Power Management (1)
+ */
+/* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA                      0x0200
+/* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_MASK                 0x0200
+/* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA                      0x0100
+/* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_MASK                 0x0100
+/* VMID_SEL - [2:1] */
+#define WM8994_VMID_SEL_MASK                    0x0006
+/* BIAS_ENA */
+#define WM8994_BIAS_ENA                         0x0001
+/* BIAS_ENA */
+#define WM8994_BIAS_ENA_MASK                    0x0001
+
+/*
+ * R2 (0x02) - Power Management (2)
+ */
+/* OPCLK_ENA */
+#define WM8994_OPCLK_ENA                        0x0800
+
+/*
+ * R5 (0x05) - Power Management (5)
+ */
+/* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA                     0x2000
+#define WM8994_AIF2DACL_ENA_MASK                0x2000
+/* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA                     0x1000
+#define WM8994_AIF2DACR_ENA_MASK                0x1000
+/* DAC1L_ENA */
+#define WM8994_DAC1L_ENA                        0x0002
+#define WM8994_DAC1L_ENA_MASK                   0x0002
+/* DAC1R_ENA */
+#define WM8994_DAC1R_ENA                        0x0001
+#define WM8994_DAC1R_ENA_MASK                   0x0001
+
+/*
+ * R45 (0x2D) - Output Mixer (1)
+ */
+/* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L                 0x0100
+#define WM8994_DAC1L_TO_HPOUT1L_MASK            0x0100
+
+/*
+ * R46 (0x2E) - Output Mixer (2)
+ */
+/* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R                 0x0100
+#define WM8994_DAC1R_TO_HPOUT1R_MASK            0x0100
+
+/*
+ * R76 (0x4C) - Charge Pump (1)
+ */
+/* CP_ENA */
+#define WM8994_CP_ENA                           0x8000
+#define WM8994_CP_ENA_MASK                      0x8000
+/*
+ * R84 (0x54) - DC Servo (1)
+ */
+/* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1                   0x0002
+#define WM8994_DCS_ENA_CHAN_1_MASK              0x0002
+/* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0                   0x0001
+#define WM8994_DCS_ENA_CHAN_0_MASK              0x0001
+
+/*
+ * R96 (0x60) - Analogue HP (1)
+ */
+/* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT                0x0080
+#define WM8994_HPOUT1L_RMV_SHORT_MASK           0x0080
+/* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP                     0x0040
+#define WM8994_HPOUT1L_OUTP_MASK                0x0040
+/* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY                      0x0020
+#define WM8994_HPOUT1L_DLY_MASK                 0x0020
+/* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT                0x0008
+#define WM8994_HPOUT1R_RMV_SHORT_MASK           0x0008
+/* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP                     0x0004
+#define WM8994_HPOUT1R_OUTP_MASK                0x0004
+/* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY                      0x0002
+#define WM8994_HPOUT1R_DLY_MASK                 0x0002
+
+/*
+ * R512 (0x200) - AIF1 Clocking (1)
+ */
+/* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_SRC_MASK                 0x0018
+/* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV                      0x0002
+/* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA                      0x0001
+#define WM8994_AIF1CLK_ENA_MASK                 0x0001
+
+/*
+ * R517 (0x205) - AIF2 Clocking (2)
+ */
+/* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2DAC_DIV_MASK                 0x0038
+
+/*
+ * R520 (0x208) - Clocking (1)
+ */
+/* AIF2DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA                   0x0004
+#define WM8994_AIF2DSPCLK_ENA_MASK              0x0004
+/* SYSDSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA                    0x0002
+#define WM8994_SYSDSPCLK_ENA_MASK               0x0002
+/* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC                       0x0001
+
+/*
+ * R521 (0x209) - Clocking (2)
+ */
+/* OPCLK_DIV - [2:0] */
+#define WM8994_OPCLK_DIV_MASK                   0x0007
+
+/*
+ * R528 (0x210) - AIF1 Rate
+ */
+/* AIF1_SR - [7:4] */
+#define WM8994_AIF1_SR_MASK                     0x00F0
+#define WM8994_AIF1_SR_SHIFT                         4
+/* AIF1CLK_RATE - [3:0] */
+#define WM8994_AIF1CLK_RATE_MASK                0x000F
+
+/*
+ * R768 (0x300) - AIF1 Control (1)
+ */
+/* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV                    0x0100
+/* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV                   0x0080
+#define WM8994_AIF1_LRCLK_INV_MASK              0x0080
+/* AIF1_WL - [6:5] */
+#define WM8994_AIF1_WL_MASK                     0x0060
+/* AIF1_FMT - [4:3] */
+#define WM8994_AIF1_FMT_MASK                    0x0018
+
+/*
+ * R769 (0x301) - AIF1 Control (2)
+ */
+/* AIF1_MONO */
+#define WM8994_AIF1_MONO                        0x0100
+
+/*
+ * R770 (0x302) - AIF1 Master/Slave
+ */
+/* AIF1_MSTR */
+#define WM8994_AIF1_MSTR                        0x4000
+#define WM8994_AIF1_MSTR_MASK                   0x4000
+
+/*
+ * R771 (0x303) - AIF1 BCLK
+ */
+/* AIF1_BCLK_DIV - [8:4] */
+#define WM8994_AIF1_BCLK_DIV_MASK               0x01F0
+#define WM8994_AIF1_BCLK_DIV_SHIFT                   4
+
+/*
+ * R1282 (0x502) - AIF2 DAC Left Volume
+ */
+/* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU                       0x0100
+#define WM8994_AIF2DAC_VU_MASK                  0x0100
+/* AIF2DACL_VOL - [7:0] */
+#define WM8994_AIF2DACL_VOL_MASK                0x00FF
+
+/*
+ * R1283 (0x503) - AIF2 DAC Right Volume
+ */
+/* AIF2DACR_VOL - [7:0] */
+#define WM8994_AIF2DACR_VOL_MASK                0x00FF
+
+/*
+ * R1312 (0x520) - AIF2 DAC Filters (1)
+ */
+/* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_MASK                0x0200
+
+/*
+ * R1537 (0x601) - DAC1 Left Mixer Routing
+ */
+/* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L                0x0004
+#define WM8994_AIF2DACL_TO_DAC1L_MASK           0x0004
+
+/*
+ * R1538 (0x602) - DAC1 Right Mixer Routing
+ */
+/* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R                0x0004
+#define WM8994_AIF2DACR_TO_DAC1R_MASK           0x0004
+
+/*
+ * R1552 (0x610) - DAC1 Left Volume
+ */
+/* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_MASK                  0x0200
+/* DAC1_VU */
+#define WM8994_DAC1_VU                          0x0100
+#define WM8994_DAC1_VU_MASK                     0x0100
+/* DAC1L_VOL - [7:0] */
+#define WM8994_DAC1L_VOL_MASK                   0x00FF
+
+/*
+ * R1553 (0x611) - DAC1 Right Volume
+ */
+/* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_MASK                  0x0200
+/* DAC1R_VOL - [7:0] */
+#define WM8994_DAC1R_VOL_MASK                   0x00FF
+
+/*
+ *  GPIO
+ */
+/* OUTPUT PIN */
+#define WM8994_GPIO_DIR_OUTPUT                   0x8000
+/* GPIO PIN MASK */
+#define WM8994_GPIO_DIR_MASK                     0xFFE0
+/* I2S CLK */
+#define WM8994_GPIO_FUNCTION_I2S_CLK             0x0000
+/* GPn FN */
+#define WM8994_GPIO_FUNCTION_MASK                0x001F
+#endif
index f0b82c67f5babf48f1891d3e58e789ae29cce2d4..824d357d94818ea9c05fa5b0d437aff181b50195 100644 (file)
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_BFIN_SPI) += bfin_spi.o
 COBJS-$(CONFIG_CF_SPI) += cf_spi.o
 COBJS-$(CONFIG_CF_QSPI) += cf_qspi.o
 COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
+COBJS-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
 COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
new file mode 100644 (file)
index 0000000..3e6c18f
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Padmavathi Venna <padma.v@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch-exynos/spi.h>
+#include <asm/io.h>
+
+/* Information about each SPI controller */
+struct spi_bus {
+       enum periph_id periph_id;
+       s32 frequency;          /* Default clock frequency, -1 for none */
+       struct exynos_spi *regs;
+       int inited;             /* 1 if this bus is ready for use */
+};
+
+/* A list of spi buses that we know about */
+static struct spi_bus spi_bus[EXYNOS5_SPI_NUM_CONTROLLERS];
+
+struct exynos_spi_slave {
+       struct spi_slave slave;
+       struct exynos_spi *regs;
+       unsigned int freq;              /* Default frequency */
+       unsigned int mode;
+       enum periph_id periph_id;       /* Peripheral ID for this device */
+       unsigned int fifo_size;
+};
+
+static struct spi_bus *spi_get_bus(unsigned dev_index)
+{
+       if (dev_index < EXYNOS5_SPI_NUM_CONTROLLERS)
+               return &spi_bus[dev_index];
+       debug("%s: invalid bus %d", __func__, dev_index);
+
+       return NULL;
+}
+
+static inline struct exynos_spi_slave *to_exynos_spi(struct spi_slave *slave)
+{
+       return container_of(slave, struct exynos_spi_slave, slave);
+}
+
+/**
+ * Setup the driver private data
+ *
+ * @param bus          ID of the bus that the slave is attached to
+ * @param cs           ID of the chip select connected to the slave
+ * @param max_hz       Required spi frequency
+ * @param mode         Required spi mode (clk polarity, clk phase and
+ *                     master or slave)
+ * @return new device or NULL
+ */
+struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
+                       unsigned int max_hz, unsigned int mode)
+{
+       struct exynos_spi_slave *spi_slave;
+       struct spi_bus *bus;
+
+       if (!spi_cs_is_valid(busnum, cs)) {
+               debug("%s: Invalid bus/chip select %d, %d\n", __func__,
+                     busnum, cs);
+               return NULL;
+       }
+
+       spi_slave = malloc(sizeof(*spi_slave));
+       if (!spi_slave) {
+               debug("%s: Could not allocate spi_slave\n", __func__);
+               return NULL;
+       }
+
+       bus = &spi_bus[busnum];
+       spi_slave->slave.bus = busnum;
+       spi_slave->slave.cs = cs;
+       spi_slave->regs = bus->regs;
+       spi_slave->mode = mode;
+       spi_slave->periph_id = bus->periph_id;
+       if (bus->periph_id == PERIPH_ID_SPI1 ||
+           bus->periph_id == PERIPH_ID_SPI2)
+               spi_slave->fifo_size = 64;
+       else
+               spi_slave->fifo_size = 256;
+
+       spi_slave->freq = bus->frequency;
+       if (max_hz)
+               spi_slave->freq = min(max_hz, spi_slave->freq);
+
+       return &spi_slave->slave;
+}
+
+/**
+ * Free spi controller
+ *
+ * @param slave        Pointer to spi_slave to which controller has to
+ *             communicate with
+ */
+void spi_free_slave(struct spi_slave *slave)
+{
+       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+       free(spi_slave);
+}
+
+/**
+ * Flush spi tx, rx fifos and reset the SPI controller
+ *
+ * @param slave        Pointer to spi_slave to which controller has to
+ *             communicate with
+ */
+static void spi_flush_fifo(struct spi_slave *slave)
+{
+       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+       struct exynos_spi *regs = spi_slave->regs;
+
+       clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
+       clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+       setbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
+}
+
+/**
+ * Initialize the spi base registers, set the required clock frequency and
+ * initialize the gpios
+ *
+ * @param slave        Pointer to spi_slave to which controller has to
+ *             communicate with
+ * @return zero on success else a negative value
+ */
+int spi_claim_bus(struct spi_slave *slave)
+{
+       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+       struct exynos_spi *regs = spi_slave->regs;
+       u32 reg = 0;
+       int ret;
+
+       ret = set_spi_clk(spi_slave->periph_id,
+                                       spi_slave->freq);
+       if (ret < 0) {
+               debug("%s: Failed to setup spi clock\n", __func__);
+               return ret;
+       }
+
+       exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
+
+       spi_flush_fifo(slave);
+
+       reg = readl(&regs->ch_cfg);
+       reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
+
+       if (spi_slave->mode & SPI_CPHA)
+               reg |= SPI_CH_CPHA_B;
+
+       if (spi_slave->mode & SPI_CPOL)
+               reg |= SPI_CH_CPOL_L;
+
+       writel(reg, &regs->ch_cfg);
+       writel(SPI_FB_DELAY_180, &regs->fb_clk);
+
+       return 0;
+}
+
+/**
+ * Reset the spi H/W and flush the tx and rx fifos
+ *
+ * @param slave        Pointer to spi_slave to which controller has to
+ *             communicate with
+ */
+void spi_release_bus(struct spi_slave *slave)
+{
+       spi_flush_fifo(slave);
+}
+
+static void spi_get_fifo_levels(struct exynos_spi *regs,
+       int *rx_lvl, int *tx_lvl)
+{
+       uint32_t spi_sts = readl(&regs->spi_sts);
+
+       *rx_lvl = (spi_sts >> SPI_RX_LVL_OFFSET) & SPI_FIFO_LVL_MASK;
+       *tx_lvl = (spi_sts >> SPI_TX_LVL_OFFSET) & SPI_FIFO_LVL_MASK;
+}
+
+/**
+ * If there's something to transfer, do a software reset and set a
+ * transaction size.
+ *
+ * @param regs SPI peripheral registers
+ * @param count        Number of bytes to transfer
+ */
+static void spi_request_bytes(struct exynos_spi *regs, int count)
+{
+       assert(count && count < (1 << 16));
+       setbits_le32(&regs->ch_cfg, SPI_CH_RST);
+       clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+       writel(count | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
+}
+
+static void spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
+                       void **dinp, void const **doutp)
+{
+       struct exynos_spi *regs = spi_slave->regs;
+       uchar *rxp = *dinp;
+       const uchar *txp = *doutp;
+       int rx_lvl, tx_lvl;
+       uint out_bytes, in_bytes;
+
+       out_bytes = in_bytes = todo;
+
+       /*
+        * If there's something to send, do a software reset and set a
+        * transaction size.
+        */
+       spi_request_bytes(regs, todo);
+
+       /*
+        * Bytes are transmitted/received in pairs. Wait to receive all the
+        * data because then transmission will be done as well.
+        */
+       while (in_bytes) {
+               int temp;
+
+               /* Keep the fifos full/empty. */
+               spi_get_fifo_levels(regs, &rx_lvl, &tx_lvl);
+               if (tx_lvl < spi_slave->fifo_size && out_bytes) {
+                       temp = txp ? *txp++ : 0xff;
+                       writel(temp, &regs->tx_data);
+                       out_bytes--;
+               }
+               if (rx_lvl > 0 && in_bytes) {
+                       temp = readl(&regs->rx_data);
+                       if (rxp)
+                               *rxp++ = temp;
+                       in_bytes--;
+               }
+       }
+       *dinp = rxp;
+       *doutp = txp;
+}
+
+/**
+ * Transfer and receive data
+ *
+ * @param slave                Pointer to spi_slave to which controller has to
+ *                     communicate with
+ * @param bitlen       No of bits to tranfer or receive
+ * @param dout         Pointer to transfer buffer
+ * @param din          Pointer to receive buffer
+ * @param flags                Flags for transfer begin and end
+ * @return zero on success else a negative value
+ */
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+            void *din, unsigned long flags)
+{
+       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+       int upto, todo;
+       int bytelen;
+
+       /* spi core configured to do 8 bit transfers */
+       if (bitlen % 8) {
+               debug("Non byte aligned SPI transfer.\n");
+               return -1;
+       }
+
+       /* Start the transaction, if necessary. */
+       if ((flags & SPI_XFER_BEGIN))
+               spi_cs_activate(slave);
+
+       /* Exynos SPI limits each transfer to 65535 bytes */
+       bytelen =  bitlen / 8;
+       for (upto = 0; upto < bytelen; upto += todo) {
+               todo = min(bytelen - upto, (1 << 16) - 1);
+               spi_rx_tx(spi_slave, todo, &din, &dout);
+       }
+
+       /* Stop the transaction, if necessary. */
+       if ((flags & SPI_XFER_END))
+               spi_cs_deactivate(slave);
+
+       return 0;
+}
+
+/**
+ * Validates the bus and chip select numbers
+ *
+ * @param bus  ID of the bus that the slave is attached to
+ * @param cs   ID of the chip select connected to the slave
+ * @return one on success else zero
+ */
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+       return spi_get_bus(bus) && cs == 0;
+}
+
+/**
+ * Activate the CS by driving it LOW
+ *
+ * @param slave        Pointer to spi_slave to which controller has to
+ *             communicate with
+ */
+void spi_cs_activate(struct spi_slave *slave)
+{
+       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+       clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+       debug("Activate CS, bus %d\n", spi_slave->slave.bus);
+}
+
+/**
+ * Deactivate the CS by driving it HIGH
+ *
+ * @param slave        Pointer to spi_slave to which controller has to
+ *             communicate with
+ */
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+       struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+       setbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+       debug("Deactivate CS, bus %d\n", spi_slave->slave.bus);
+}
+
+static inline struct exynos_spi *get_spi_base(int dev_index)
+{
+       if (dev_index < 3)
+               return (struct exynos_spi *)samsung_get_base_spi() + dev_index;
+       else
+               return (struct exynos_spi *)samsung_get_base_spi_isp() +
+                                       (dev_index - 3);
+}
+
+/* Sadly there is no error return from this function */
+void spi_init(void)
+{
+       int i;
+       struct spi_bus *bus;
+
+       for (i = 0; i < EXYNOS5_SPI_NUM_CONTROLLERS; i++) {
+               bus = &spi_bus[i];
+               bus->regs = get_spi_base(i);
+               bus->periph_id = PERIPH_ID_SPI0 + i;
+
+               /* Although Exynos5 supports upto 50Mhz speed,
+                * we are setting it to 10Mhz for safe side
+                */
+               bus->frequency = 10000000;
+               bus->inited = 1;
+       }
+}
index cc3022a2c73a9e8c6578b8ac99951ae50976633a..170a358b5283849207827f21d7eb49dc419d9acf 100644 (file)
@@ -37,6 +37,7 @@ COBJS-$(CONFIG_EXYNOS_PWM_BL) += exynos_pwm_bl.o
 COBJS-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o
 COBJS-$(CONFIG_S6E8AX0) += s6e8ax0.o
 COBJS-$(CONFIG_S6E63D6) += s6e63d6.o
+COBJS-$(CONFIG_LD9040) += ld9040.o
 COBJS-$(CONFIG_SED156X) += sed156x.o
 COBJS-$(CONFIG_VIDEO_AMBA) += amba.o
 COBJS-$(CONFIG_VIDEO_COREBOOT) += coreboot_fb.o
@@ -50,6 +51,7 @@ COBJS-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o
 COBJS-$(CONFIG_VIDEO_SED13806) += sed13806.o
 COBJS-$(CONFIG_VIDEO_SM501) += sm501.o
 COBJS-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
+COBJS-$(CONFIG_VIDEO_TEGRA) += tegra.o
 COBJS-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 
 COBJS  := $(sort $(COBJS-y))
index e31a0fd500abef1bc46c9e0518e7bc2e8639db3d..d9a3f9ab18976ba597d779ec9e0fab6ffcc70414 100644 (file)
@@ -70,8 +70,19 @@ static void draw_logo(void)
        int x, y;
        ulong addr;
 
-       x = ((panel_width - panel_info.logo_width) >> 1);
-       y = ((panel_height - panel_info.logo_height) >> 1) - 4;
+       if (panel_width >= panel_info.logo_width) {
+               x = ((panel_width - panel_info.logo_width) >> 1);
+       } else {
+               x = 0;
+               printf("Warning: image width is bigger than display width\n");
+       }
+
+       if (panel_height >= panel_info.logo_height) {
+               y = ((panel_height - panel_info.logo_height) >> 1) - 4;
+       } else {
+               y = 0;
+               printf("Warning: image height is bigger than display height\n");
+       }
 
        addr = panel_info.logo_addr;
        bmp_display(addr, x, y);
diff --git a/drivers/video/ld9040.c b/drivers/video/ld9040.c
new file mode 100644 (file)
index 0000000..c01ae12
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * ld9040 AMOLED LCD panel driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Donghwa Lee <dh09.lee@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 <spi.h>
+
+static const unsigned char SEQ_SWRESET[] = {
+       0x01,
+};
+
+static const unsigned char SEQ_USER_SETTING[] = {
+       0xF0, 0x5A, 0x5A
+};
+
+static const unsigned char SEQ_ELVSS_ON[] = {
+       0xB1, 0x0D, 0x00, 0x16,
+};
+
+static const unsigned char SEQ_TEMP_SWIRE[] = {
+       0xB2, 0x06, 0x06, 0x06, 0x06,
+};
+
+static const unsigned char SEQ_GTCON[] = {
+       0xF7, 0x09, 0x00, 0x00,
+};
+
+static const unsigned char SEQ_PANEL_CONDITION[] = {
+       0xF8, 0x05, 0x65, 0x96, 0x71, 0x7D, 0x19, 0x3B,
+       0x0D, 0x19, 0x7E, 0x0D, 0xE2, 0x00, 0x00, 0x7E,
+       0x7D, 0x07, 0x07, 0x20, 0x20, 0x20, 0x02, 0x02,
+};
+
+static const unsigned char SEQ_GAMMA_SET1[] = {
+       0xF9, 0x00, 0xA7, 0xB4, 0xAE, 0xBF, 0x00, 0x91,
+       0x00, 0xB2, 0xB4, 0xAA, 0xBB, 0x00, 0xAC, 0x00,
+       0xB3, 0xB1, 0xAA, 0xBC, 0x00, 0xB3,
+};
+
+static const unsigned char SEQ_GAMMA_CTRL[] = {
+       0xFB, 0x02, 0x5A,
+};
+
+static const unsigned char SEQ_APON[] = {
+       0xF3, 0x00, 0x00, 0x00, 0x0A, 0x02,
+};
+
+static const unsigned char SEQ_DISPCTL[] = {
+       0xF2, 0x02, 0x08, 0x08, 0x10, 0x10,
+};
+
+static const unsigned char SEQ_MANPWR[] = {
+       0xB0, 0x04,
+};
+
+static const unsigned char SEQ_PWR_CTRL[] = {
+       0xF4, 0x0A, 0x87, 0x25, 0x6A, 0x44, 0x02, 0x88,
+};
+
+static const unsigned char SEQ_SLPOUT[] = {
+       0x11,
+};
+
+static const unsigned char SEQ_SLPIN[] = {
+       0x10,
+};
+
+static const unsigned char SEQ_DISPON[] = {
+       0x29,
+};
+
+static const unsigned char SEQ_DISPOFF[] = {
+       0x28,
+};
+
+static void ld9040_spi_write(const unsigned char *wbuf, unsigned int size_cmd)
+{
+       int i = 0;
+
+       /*
+        * Data are transmitted in 9-bit words:
+        * the first bit is command/parameter, the other are the value.
+        * The value's LSB is shifted to MSB position, to be sent as 9th bit
+        */
+
+       unsigned int data_out = 0, data_in = 0;
+       for (i = 0; i < size_cmd; i++) {
+               data_out = wbuf[i] >> 1;
+               if (i != 0)
+                       data_out += 0x0080;
+               if (wbuf[i] & 0x01)
+                       data_out += 0x8000;
+               spi_xfer(NULL, 9, &data_out, &data_in, SPI_XFER_BEGIN);
+       }
+}
+
+void ld9040_cfg_ldo(void)
+{
+       udelay(10);
+
+       ld9040_spi_write(SEQ_USER_SETTING,
+                                       ARRAY_SIZE(SEQ_USER_SETTING));
+       ld9040_spi_write(SEQ_PANEL_CONDITION,
+                                       ARRAY_SIZE(SEQ_PANEL_CONDITION));
+       ld9040_spi_write(SEQ_DISPCTL, ARRAY_SIZE(SEQ_DISPCTL));
+       ld9040_spi_write(SEQ_MANPWR, ARRAY_SIZE(SEQ_MANPWR));
+       ld9040_spi_write(SEQ_PWR_CTRL, ARRAY_SIZE(SEQ_PWR_CTRL));
+       ld9040_spi_write(SEQ_ELVSS_ON, ARRAY_SIZE(SEQ_ELVSS_ON));
+       ld9040_spi_write(SEQ_GTCON, ARRAY_SIZE(SEQ_GTCON));
+       ld9040_spi_write(SEQ_GAMMA_SET1, ARRAY_SIZE(SEQ_GAMMA_SET1));
+       ld9040_spi_write(SEQ_GAMMA_CTRL, ARRAY_SIZE(SEQ_GAMMA_CTRL));
+       ld9040_spi_write(SEQ_SLPOUT, ARRAY_SIZE(SEQ_SLPOUT));
+
+       udelay(120);
+}
+
+void ld9040_enable_ldo(unsigned int onoff)
+{
+       if (onoff)
+               ld9040_spi_write(SEQ_DISPON, ARRAY_SIZE(SEQ_DISPON));
+       else
+               ld9040_spi_write(SEQ_DISPOFF, ARRAY_SIZE(SEQ_DISPOFF));
+}
diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c
new file mode 100644 (file)
index 0000000..750a283
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2011 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 <fdtdec.h>
+#include <lcd.h>
+
+#include <asm/system.h>
+#include <asm/gpio.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/funcmux.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/pwm.h>
+#include <asm/arch/display.h>
+#include <asm/arch-tegra/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* These are the stages we go throuh in enabling the LCD */
+enum stage_t {
+       STAGE_START,
+       STAGE_PANEL_VDD,
+       STAGE_LVDS,
+       STAGE_BACKLIGHT_VDD,
+       STAGE_PWM,
+       STAGE_BACKLIGHT_EN,
+       STAGE_DONE,
+};
+
+static enum stage_t stage;     /* Current stage we are at */
+static unsigned long timer_next; /* Time we can move onto next stage */
+
+/* Our LCD config, set up in handle_stage() */
+static struct fdt_panel_config config;
+struct fdt_disp_config *disp_config;   /* Display controller config */
+
+enum {
+       /* Maximum LCD size we support */
+       LCD_MAX_WIDTH           = 1366,
+       LCD_MAX_HEIGHT          = 768,
+       LCD_MAX_LOG2_BPP        = 4,            /* 2^4 = 16 bpp */
+};
+
+int lcd_line_length;
+int lcd_color_fg;
+int lcd_color_bg;
+
+void *lcd_base;                        /* Start of framebuffer memory  */
+void *lcd_console_address;     /* Start of console buffer      */
+
+short console_col;
+short console_row;
+
+vidinfo_t panel_info = {
+       /* Insert a value here so that we don't end up in the BSS */
+       .vl_col = -1,
+};
+
+char lcd_cursor_enabled;
+
+ushort lcd_cursor_width;
+ushort lcd_cursor_height;
+
+#ifndef CONFIG_OF_CONTROL
+#error "You must enable CONFIG_OF_CONTROL to get Tegra LCD support"
+#endif
+
+void lcd_cursor_size(ushort width, ushort height)
+{
+       lcd_cursor_width = width;
+       lcd_cursor_height = height;
+}
+
+void lcd_toggle_cursor(void)
+{
+       ushort x, y;
+       uchar *dest;
+       ushort row;
+
+       x = console_col * lcd_cursor_width;
+       y = console_row * lcd_cursor_height;
+       dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) /
+                       8);
+
+       for (row = 0; row < lcd_cursor_height; ++row, dest += lcd_line_length) {
+               ushort *d = (ushort *)dest;
+               ushort color;
+               int i;
+
+               for (i = 0; i < lcd_cursor_width; ++i) {
+                       color = *d;
+                       color ^= lcd_color_fg;
+                       *d = color;
+                       ++d;
+               }
+       }
+}
+
+void lcd_cursor_on(void)
+{
+       lcd_cursor_enabled = 1;
+       lcd_toggle_cursor();
+}
+void lcd_cursor_off(void)
+{
+       lcd_cursor_enabled = 0;
+       lcd_toggle_cursor();
+}
+
+char lcd_is_cursor_enabled(void)
+{
+       return lcd_cursor_enabled;
+}
+
+static void update_panel_size(struct fdt_disp_config *config)
+{
+       panel_info.vl_col = config->width;
+       panel_info.vl_row = config->height;
+       panel_info.vl_bpix = config->log2_bpp;
+}
+
+/*
+ *  Main init function called by lcd driver.
+ *  Inits and then prints test pattern if required.
+ */
+
+void lcd_ctrl_init(void *lcdbase)
+{
+       int line_length, size;
+       int type = DCACHE_OFF;
+
+       assert(disp_config);
+
+       lcd_base = (void *)disp_config->frame_buffer;
+
+       /* Make sure that we can acommodate the selected LCD */
+       assert(disp_config->width <= LCD_MAX_WIDTH);
+       assert(disp_config->height <= LCD_MAX_HEIGHT);
+       assert(disp_config->log2_bpp <= LCD_MAX_LOG2_BPP);
+       if (disp_config->width <= LCD_MAX_WIDTH
+                       && disp_config->height <= LCD_MAX_HEIGHT
+                       && disp_config->log2_bpp <= LCD_MAX_LOG2_BPP)
+               update_panel_size(disp_config);
+       size = lcd_get_size(&line_length);
+
+       /* Set up the LCD caching as requested */
+       if (config.cache_type & FDT_LCD_CACHE_WRITE_THROUGH)
+               type = DCACHE_WRITETHROUGH;
+       else if (config.cache_type & FDT_LCD_CACHE_WRITE_BACK)
+               type = DCACHE_WRITEBACK;
+       mmu_set_region_dcache_behaviour(disp_config->frame_buffer, size, type);
+
+       /* Enable flushing after LCD writes if requested */
+       lcd_set_flush_dcache(config.cache_type & FDT_LCD_CACHE_FLUSH);
+
+       debug("LCD frame buffer at %p\n", lcd_base);
+}
+
+ulong calc_fbsize(void)
+{
+       return (panel_info.vl_col * panel_info.vl_row *
+               NBITS(panel_info.vl_bpix)) / 8;
+}
+
+void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
+{
+}
+
+void tegra_lcd_early_init(const void *blob)
+{
+       /*
+        * Go with the maximum size for now. We will fix this up after
+        * relocation. These values are only used for memory alocation.
+        */
+       panel_info.vl_col = LCD_MAX_WIDTH;
+       panel_info.vl_row = LCD_MAX_HEIGHT;
+       panel_info.vl_bpix = LCD_MAX_LOG2_BPP;
+}
+
+/**
+ * Decode the panel information from the fdt.
+ *
+ * @param blob         fdt blob
+ * @param config       structure to store fdt config into
+ * @return 0 if ok, -ve on error
+ */
+static int fdt_decode_lcd(const void *blob, struct fdt_panel_config *config)
+{
+       int display_node;
+
+       disp_config = tegra_display_get_config();
+       if (!disp_config) {
+               debug("%s: Display controller is not configured\n", __func__);
+               return -1;
+       }
+       display_node = disp_config->panel_node;
+       if (display_node < 0) {
+               debug("%s: No panel configuration available\n", __func__);
+               return -1;
+       }
+
+       config->pwm_channel = pwm_request(blob, display_node, "nvidia,pwm");
+       if (config->pwm_channel < 0) {
+               debug("%s: Unable to request PWM channel\n", __func__);
+               return -1;
+       }
+
+       config->cache_type = fdtdec_get_int(blob, display_node,
+                                           "nvidia,cache-type",
+                                           FDT_LCD_CACHE_WRITE_BACK_FLUSH);
+
+       /* These GPIOs are all optional */
+       fdtdec_decode_gpio(blob, display_node, "nvidia,backlight-enable-gpios",
+                           &config->backlight_en);
+       fdtdec_decode_gpio(blob, display_node, "nvidia,lvds-shutdown-gpios",
+                          &config->lvds_shutdown);
+       fdtdec_decode_gpio(blob, display_node, "nvidia,backlight-vdd-gpios",
+                          &config->backlight_vdd);
+       fdtdec_decode_gpio(blob, display_node, "nvidia,panel-vdd-gpios",
+                          &config->panel_vdd);
+
+       return fdtdec_get_int_array(blob, display_node, "nvidia,panel-timings",
+                       config->panel_timings, FDT_LCD_TIMINGS);
+}
+
+/**
+ * Handle the next stage of device init
+ */
+static int handle_stage(const void *blob)
+{
+       debug("%s: stage %d\n", __func__, stage);
+
+       /* do the things for this stage */
+       switch (stage) {
+       case STAGE_START:
+               /* Initialize the Tegra display controller */
+               if (tegra_display_probe(gd->fdt_blob, (void *)gd->fb_base)) {
+                       printf("%s: Failed to probe display driver\n",
+                       __func__);
+                       return -1;
+               }
+
+               /* get panel details */
+               if (fdt_decode_lcd(blob, &config)) {
+                       printf("No valid LCD information in device tree\n");
+                       return -1;
+               }
+
+               /*
+                * It is possible that the FDT has requested that the LCD be
+                * disabled. We currently don't support this. It would require
+                * changes to U-Boot LCD subsystem to have LCD support
+                * compiled in but not used. An easier option might be to
+                * still have a frame buffer, but leave the backlight off and
+                * remove all mention of lcd in the stdout environment
+                * variable.
+                */
+
+               funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT);
+
+               fdtdec_setup_gpio(&config.panel_vdd);
+               fdtdec_setup_gpio(&config.lvds_shutdown);
+               fdtdec_setup_gpio(&config.backlight_vdd);
+               fdtdec_setup_gpio(&config.backlight_en);
+
+               /*
+                * TODO: If fdt includes output flag we can omit this code
+                * since fdtdec_setup_gpio will do it for us.
+                */
+               if (fdt_gpio_isvalid(&config.panel_vdd))
+                       gpio_direction_output(config.panel_vdd.gpio, 0);
+               if (fdt_gpio_isvalid(&config.lvds_shutdown))
+                       gpio_direction_output(config.lvds_shutdown.gpio, 0);
+               if (fdt_gpio_isvalid(&config.backlight_vdd))
+                       gpio_direction_output(config.backlight_vdd.gpio, 0);
+               if (fdt_gpio_isvalid(&config.backlight_en))
+                       gpio_direction_output(config.backlight_en.gpio, 0);
+               break;
+       case STAGE_PANEL_VDD:
+               if (fdt_gpio_isvalid(&config.panel_vdd))
+                       gpio_direction_output(config.panel_vdd.gpio, 1);
+               break;
+       case STAGE_LVDS:
+               if (fdt_gpio_isvalid(&config.lvds_shutdown))
+                       gpio_set_value(config.lvds_shutdown.gpio, 1);
+               break;
+       case STAGE_BACKLIGHT_VDD:
+               if (fdt_gpio_isvalid(&config.backlight_vdd))
+                       gpio_set_value(config.backlight_vdd.gpio, 1);
+               break;
+       case STAGE_PWM:
+               /* Enable PWM at 15/16 high, 32768 Hz with divider 1 */
+               pinmux_set_func(PINGRP_GPU, PMUX_FUNC_PWM);
+               pinmux_tristate_disable(PINGRP_GPU);
+
+               pwm_enable(config.pwm_channel, 32768, 0xdf, 1);
+               break;
+       case STAGE_BACKLIGHT_EN:
+               if (fdt_gpio_isvalid(&config.backlight_en))
+                       gpio_set_value(config.backlight_en.gpio, 1);
+               break;
+       case STAGE_DONE:
+               break;
+       }
+
+       /* set up timer for next stage */
+       timer_next = timer_get_us();
+       if (stage < FDT_LCD_TIMINGS)
+               timer_next += config.panel_timings[stage] * 1000;
+
+       /* move to next stage */
+       stage++;
+       return 0;
+}
+
+int tegra_lcd_check_next_stage(const void *blob, int wait)
+{
+       if (stage == STAGE_DONE)
+               return 0;
+
+       do {
+               /* wait if we need to */
+               debug("%s: stage %d\n", __func__, stage);
+               if (stage != STAGE_START) {
+                       int delay = timer_next - timer_get_us();
+
+                       if (delay > 0) {
+                               if (wait)
+                                       udelay(delay);
+                               else
+                                       return 0;
+                       }
+               }
+
+               if (handle_stage(blob))
+                       return -1;
+       } while (wait && stage != STAGE_DONE);
+       if (stage == STAGE_DONE)
+               debug("%s: LCD init complete\n", __func__);
+
+       return 0;
+}
+
+void lcd_enable(void)
+{
+       /*
+        * Backlight and power init will be done separately in
+        * tegra_lcd_check_next_stage(), which should be called in
+        * board_late_init().
+        *
+        * U-Boot code supports only colour depth, selected at compile time.
+        * The device tree setting should match this. Otherwise the display
+        * will not look right, and U-Boot may crash.
+        */
+       if (disp_config->log2_bpp != LCD_BPP) {
+               printf("%s: Error: LCD depth configured in FDT (%d = %dbpp)"
+                       " must match setting of LCD_BPP (%d)\n", __func__,
+                      disp_config->log2_bpp, disp_config->bpp, LCD_BPP);
+       }
+}
index 923acb9f3af40b8eb8329fbf146979d290102844..bc091239104afa042ec4516d32bdc9a51c139dac 100644 (file)
@@ -28,6 +28,7 @@ LIB   := $(obj)libwatchdog.o
 COBJS-$(CONFIG_AT91SAM9_WATCHDOG) += at91sam9_wdt.o
 COBJS-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
 COBJS-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o
+COBJS-$(CONFIG_S5P)               += s5p_wdt.o
 
 COBJS  := $(COBJS-y)
 SRCS   := $(COBJS:.o=.c)
index 23c964940312efc36f4dffac82292a141c1050b6..bfedbe44596aa31fb2266f7e052a63401f06d181 100644 (file)
  */
 
 /**
- * Request ownership of a GPIO.
+ * Request a gpio. This should be called before any of the other functions
+ * are used on this gpio.
  *
- * @param gpio GPIO number
- * @param label        Name given to the GPIO
+ * @param gp   GPIO number
+ * @param label        User label for this GPIO
  * @return 0 if ok, -1 on error
  */
 int gpio_request(unsigned gpio, const char *label);
@@ -93,14 +94,4 @@ int gpio_get_value(unsigned gpio);
  * @return 0 if ok, -1 on error
  */
 int gpio_set_value(unsigned gpio, int value);
-
-/**
- * Request a gpio. This should be called before any of the other functions
- * are used on this gpio.
- *
- * @param gp   GPIO number
- * @param label        User label for this GPIO
- * @return 0 if ok, -1 on error
- */
-int gpio_request(unsigned gpio, const char *label);
 #endif /* _ASM_GENERIC_GPIO_H_ */
index 10bc2606c717f600de2af73e9857c4926ccd510e..476e7cffc2856523df090a54d73b03926e1b73ba 100644 (file)
@@ -89,10 +89,10 @@ extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *
  */
 
 #if defined(CONFIG_CMD_MEMORY)         \
-    || defined(CONFIG_CMD_I2C)         \
-    || defined(CONFIG_CMD_ITEST)       \
-    || defined(CONFIG_CMD_PCI)         \
-    || defined(CONFIG_CMD_PORTIO)
+       || defined(CONFIG_CMD_I2C)      \
+       || defined(CONFIG_CMD_ITEST)    \
+       || defined(CONFIG_CMD_PCI)      \
+       || defined(CONFIG_CMD_PORTIO)
 #define CMD_DATA_SIZE
 extern int cmd_get_data_size(char* arg, int default_size);
 #endif
index 5e3c5eeee14313f02f0ff90a410497b4f25ec595..d0bf1e8ab234b8c66e017a6eef944c1dc3637ec2 100644 (file)
@@ -340,6 +340,11 @@ int        envmatch     (uchar *, int);
 char   *getenv      (const char *);
 int    getenv_f     (const char *name, char *buf, unsigned len);
 ulong getenv_ulong(const char *name, int base, ulong default_val);
+/*
+ * Read an environment variable as a boolean
+ * Return -1 if variable does not exist (default to true)
+ */
+int getenv_yesno(const char *var);
 int    saveenv      (void);
 int    setenv       (const char *, const char *);
 int setenv_ulong(const char *varname, ulong value);
index f434cd08910e5f71ffaaa07ae512681b6117788b..e82f6421c0af6e2cd91eaf0c88e9fae371f620cf 100644 (file)
 #define CONFIG_CMD_FDOS                /* Floppy DOS support           */
 #define CONFIG_CMD_FLASH       /* flinfo, erase, protect       */
 #define CONFIG_CMD_FPGA                /* FPGA configuration Support   */
+#define CONFIG_CMD_GETTIME     /* Get time since boot         */
+#define CONFIG_CMD_HASH                /* calculate hash / digest      */
 #define CONFIG_CMD_HWFLOW      /* RTS/CTS hw flow control      */
 #define CONFIG_CMD_I2C         /* I2C serial bus support       */
 #define CONFIG_CMD_IDE         /* IDE harddisk support         */
 #define CONFIG_CMD_IMI         /* iminfo                       */
 #define CONFIG_CMD_IMLS                /* List all found images        */
 #define CONFIG_CMD_IMMAP       /* IMMR dump support            */
+#define CONFIG_CMD_IO          /* Access to X86 IO space       */
 #define CONFIG_CMD_IRQ         /* irqinfo                      */
 #define CONFIG_CMD_ITEST       /* Integer (and string) test    */
 #define CONFIG_CMD_JFFS2       /* JFFS2 Support                */
@@ -70,6 +73,7 @@
 #define CONFIG_CMD_REGINFO     /* Register dump                */
 #define CONFIG_CMD_REISER      /* Reiserfs support             */
 #define CONFIG_CMD_RARP                /* rarpboot support             */
+#define CONFIG_CMD_READ                /* Read data from partition     */
 #define CONFIG_CMD_RUN         /* run command in env variable  */
 #define CONFIG_CMD_SAVEENV     /* saveenv                      */
 #define CONFIG_CMD_SAVES       /* save S record dump           */
index 1daec6967780ce4863b583b8cef832eb23603df3..6bceccbc14b355b009fc276181753e506fcaf298 100644 (file)
 
 
 #define CONFIG_SYS_LOAD_ADDR           0x100000        /* where to load what we get from TFTP */
-#define CONFIG_SYS_TFTP_LOADADDR       CONFIG_SYS_LOAD_ADDR
 #define CONFIG_SYS_EXTBDINFO           1               /* To use extended board_into (bd_t) */
 #define CONFIG_SYS_DRAM_TEST           1
 
index b98caccb817f22b65dad63b0cc06f97751d71ce5..9a649ca125fec2ca3682c93aa18ab1d35075ce00 100644 (file)
 #undef CONFIG_LOADS_ECHO
 #define        CONFIG_SYS_LOADS_BAUD_CHANGE
 
-/*
- * Set default load address for tftp network downloads
- */
-#define        CONFIG_SYS_TFTP_LOADADDR                                0x01000000
-
 /*
  * Turn off the watchdog timer
  */
index 36921ca8b9ce05980153a215aecceea4835de839..4849f94c99184e1b1c200baf220f3f9796950403 100644 (file)
 #define CONFIG_IPADDR                                  10.0.4.111
 
 #define CONFIG_SYS_LOAD_ADDR           0x00100000      /* default load address */
-#define        CONFIG_SYS_TFTP_LOADADDR        0x00100000
 
 /*
  * For booting Linux, the board info and command line data
index ccfe032ca731fe7e79a57bddd9f14ae0cd2b52f7..5a87cc5d3d6c627f26d9f8518122e125fa08531b 100644 (file)
 #define        CONFIG_CLOCKS_IN_MHZ    1      /* clocks passsed to Linux in MHz */
 
 #define CONFIG_SYS_LOAD_ADDR     0x00100000   /* default load address */
-#define CONFIG_SYS_TFTP_LOADADDR 0x00100000   /* default load address for network file downloads */
 
 #define CONFIG_SYS_HZ            1000         /* decrementer freq: 1 ms ticks */
 
index 040bfe48eb08e63693b12c24f103f3432b4e3f8a..8d1fd47afe7683f903e9bb137efa6b4b7e391b20 100644 (file)
 
 #define CONFIG_DOS_PARTITION
 #define CONFIG_EFI_PARTITION
+#define CONFIG_FS_EXT4
+#define CONFIG_FS_FAT
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
 
 /* NAND support */
 #define CONFIG_CMD_NAND
 #define CONFIG_TEGRA_NAND
 #define CONFIG_SYS_MAX_NAND_DEVICE     1
-#define CONFIG_SYS_NAND_BASE   NV_PA_NAND_BASE
 
 /* Environment in NAND (which is 512M), aligned to start of last sector */
 #define CONFIG_ENV_IS_IN_NAND
index b49ec8c7dd61fd4139a145bb62f2f730b23c025f..3f37e8430c516b3367904ab62c14c9daa12143b4 100644 (file)
                "if tftp ${update_nand_full_filename} ; then "          \
                "run update_nand_get_fcb_size ; "                       \
                "nand scrub -y 0x0 ${filesize} ; "                      \
-               "nand write.raw ${loadaddr} 0x0 ${update_nand_fcb} ; "  \
+               "nand write.raw ${loadaddr} 0x0 ${fcb_sz} ; "   \
                "setexpr update_off ${loadaddr} + ${update_nand_fcb} ; " \
                "setexpr update_sz ${filesize} - ${update_nand_fcb} ; " \
                "nand write ${update_off} ${update_nand_fcb} ${update_sz} ; " \
index 8b89b25f74d73e9282d7cfb0927271efd53bbd6b..cdf3e1508e2471ce85a3a1e33d4097cefbf9b099 100644 (file)
                "if tftp ${update_nand_full_filename} ; then " \
                "run update_nand_get_fcb_size ; " \
                "nand scrub -y 0x0 ${filesize} ; " \
-               "nand write.raw ${loadaddr} 0x0 ${update_nand_fcb} ; " \
+               "nand write.raw ${loadaddr} 0x0 ${fcb_sz} ; " \
                "setexpr update_off ${loadaddr} + ${update_nand_fcb} ; " \
                "setexpr update_sz ${filesize} - ${update_nand_fcb} ; " \
                "nand write ${update_off} ${update_nand_fcb} ${update_sz} ; " \
index b4d925ed9008431710f73222a32261c9e73f64af..fc6e78208c5ddcc23dee32190f3663651cc77b75 100644 (file)
 #define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME       "u-boot.img"
 
 /* Partition tables */
-/* Only need DOS partition support for SPL, currently */
-#ifndef CONFIG_SPL_BUILD
 #define CONFIG_EFI_PARTITION
-#endif
 #define CONFIG_DOS_PARTITION
 
 /* USB
index c5dd494059e2ff922b300cf4e07169b1bc782735..3f9802ca0f52eb9613bbc52ab1ab41a3bef423a8 100644 (file)
@@ -28,6 +28,9 @@
 #define        CONFIG_CPU_PXA27X               1       /* Marvell PXA270 CPU */
 #define        CONFIG_PALMLD           1       /* Palm LifeDrive board */
 
+/* we will never enable dcache, because we have to setup MMU first */
+#define CONFIG_SYS_DCACHE_OFF
+
 /*
  * Environment settings
  */
index 9c948c547355075935c56e64d4dc25dca130d4df..64771e7e8d8967fa22f893e4bc34077e53130f8d 100644 (file)
@@ -30,6 +30,9 @@
 #define        CONFIG_CPU_PXA25X                       1       /* Intel PXA255 CPU */
 #define        CONFIG_PALMTC                   1       /* Palm Tungsten|C board */
 
+/* we will never enable dcache, because we have to setup MMU first */
+#define CONFIG_SYS_DCACHE_OFF
+
 /*
  * Environment settings
  */
index 5603de9625330c1abbf73b1b21f4620c50597cfe..38c79cfc2b58a00383d4b19c9ba127492df969cf 100644 (file)
 
 #define CONFIG_DOS_PARTITION
 #define CONFIG_EFI_PARTITION
+#define CONFIG_FS_EXT4
+#define CONFIG_FS_FAT
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
 
 /* Environment in eMMC, at the end of 2nd "boot sector" */
 #define CONFIG_ENV_IS_IN_MMC
index 894f38bd7db05804f09c6edb046dbe5cb8234e63..eb13bb3a671c0461419880ca291e95191d18b64c 100644 (file)
@@ -34,6 +34,7 @@
 #define CONFIG_S5P             1       /* which is in a S5P Family */
 #define CONFIG_EXYNOS4210      1       /* which is in a EXYNOS4210 */
 #define CONFIG_UNIVERSAL       1       /* working with Universal */
+#define CONFIG_TIZEN           1       /* TIZEN lib */
 
 #include <asm/arch/cpu.h>              /* get chip and board defs */
 
@@ -56,6 +57,8 @@
 #define CONFIG_INITRD_TAG
 #define CONFIG_REVISION_TAG
 #define CONFIG_CMDLINE_EDITING
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_BOARD_EARLY_INIT_F
 
 /* Size of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN          (CONFIG_ENV_SIZE + (1 << 20))
 #define CONFIG_USB_GADGET_S3C_UDC_OTG
 #define CONFIG_USB_GADGET_DUALSPEED
 
+/*
+ * SPI Settings
+ */
+#define CONFIG_SOFT_SPI
+#define CONFIG_SOFT_SPI_MODE SPI_MODE_3
+#define CONFIG_SOFT_SPI_GPIO_SCLK exynos4_gpio_part2_get_nr(y3, 1)
+#define CONFIG_SOFT_SPI_GPIO_MOSI exynos4_gpio_part2_get_nr(y3, 3)
+#define CONFIG_SOFT_SPI_GPIO_MISO exynos4_gpio_part2_get_nr(y3, 0)
+#define CONFIG_SOFT_SPI_GPIO_CS exynos4_gpio_part2_get_nr(y4, 3)
+
+#define SPI_DELAY udelay(1)
+#undef SPI_INIT
+#define SPI_SCL(bit) universal_spi_scl(bit)
+#define SPI_SDA(bit) universal_spi_sda(bit)
+#define SPI_READ universal_spi_read()
+#ifndef        __ASSEMBLY__
+void universal_spi_scl(int bit);
+void universal_spi_sda(int bit);
+int universal_spi_read(void);
+#endif
+
+/*
+ * LCD Settings
+ */
+#define CONFIG_EXYNOS_FB
+#define CONFIG_LCD
+#define CONFIG_CMD_BMP
+#define CONFIG_BMP_32BPP
+#define CONFIG_LD9040
+#define CONFIG_EXYNOS_MIPI_DSIM
+#define CONFIG_VIDEO_BMP_GZIP
+#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE ((520 * 120 * 4) + (1 << 12))
+
 #endif /* __CONFIG_H */
index ab10bd0abc7e57a24e2115eb3fd3698899016dd6..de0c777819b2b4a41d18dbd3188a611df2390306 100644 (file)
@@ -54,6 +54,7 @@
 #define CONFIG_MACH_TYPE               MACH_TYPE_SEABOARD
 
 #define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_LATE_INIT         /* Make sure LCD init is complete */
 
 /* I2C */
 #define CONFIG_TEGRA_I2C
 
 #define CONFIG_DOS_PARTITION
 #define CONFIG_EFI_PARTITION
+#define CONFIG_FS_EXT4
+#define CONFIG_FS_FAT
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
 
 /* Environment in eMMC, at the end of 2nd "boot sector" */
 #define CONFIG_ENV_IS_IN_MMC
 /* USB keyboard */
 #define CONFIG_USB_KEYBOARD
 
-#include "tegra-common-post.h"
+/* LCD support */
+#define CONFIG_LCD
+#define CONFIG_PWM_TEGRA
+#define CONFIG_VIDEO_TEGRA
+#define LCD_BPP                                LCD_COLOR16
+#define CONFIG_SYS_WHITE_ON_BLACK
+#define CONFIG_CONSOLE_SCROLL_LINES    10
 
 /* NAND support */
 #define CONFIG_CMD_NAND
 /* Max number of NAND devices */
 #define CONFIG_SYS_MAX_NAND_DEVICE     1
 
-/* Somewhat oddly, the NAND base address must be a config option */
-#define CONFIG_SYS_NAND_BASE   NV_PA_NAND_BASE
+#include "tegra-common-post.h"
+
 #endif /* __CONFIG_H */
index c0f86228b08a0fb4df48d70180144af2990b76c2..75c25c00348fd87bef18728baa528a1ab69850a6 100644 (file)
@@ -65,7 +65,7 @@
 #define INFORM1_OFFSET                 0x804
 
 /* Size of malloc() pool */
-#define CONFIG_SYS_MALLOC_LEN          (CONFIG_ENV_SIZE + (1 << 20))
+#define CONFIG_SYS_MALLOC_LEN          (CONFIG_ENV_SIZE + (4 << 20))
 
 /* select serial console configuration */
 #define CONFIG_SERIAL3                 /* use SERIAL 3 */
 #undef CONFIG_CMD_IMLS
 #define CONFIG_IDENT_STRING            " for SMDK5250"
 
-#define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_SYS_MMC_ENV_DEV         0
 
 #define CONFIG_SECURE_BL1_ONLY
 /* U-boot copy size from boot Media to DRAM.*/
 #define BL2_START_OFFSET       (CONFIG_BL2_OFFSET/512)
 #define BL2_SIZE_BLOC_COUNT    (CONFIG_BL2_SIZE/512)
+
+#define OM_STAT                                (0x1f << 1)
+#define EXYNOS_COPY_SPI_FNPTR_ADDR     0x02020058
+#define SPI_FLASH_UBOOT_POS            (CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE)
+
 #define CONFIG_DOS_PARTITION
 
 #define CONFIG_IRAM_STACK      0x02050000
 #define CONFIG_I2C_MULTI_BUS
 #define CONFIG_MAX_I2C_NUM     8
 #define CONFIG_SYS_I2C_SLAVE    0x0
+#define CONFIG_I2C_EDID
+
+/* PMIC */
+#define CONFIG_PMIC
+#define CONFIG_PMIC_I2C
+#define CONFIG_PMIC_MAX77686
+
+/* SPI */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_SPI_FLASH
+
+#ifdef CONFIG_SPI_FLASH
+#define CONFIG_EXYNOS_SPI
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_SPI_FLASH_WINBOND
+#define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
+#define CONFIG_SF_DEFAULT_SPEED                50000000
+#define EXYNOS5_SPI_NUM_CONTROLLERS    5
+#endif
+
+#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SPI_MODE    SPI_MODE_0
+#define CONFIG_ENV_SECT_SIZE   CONFIG_ENV_SIZE
+#define CONFIG_ENV_SPI_BUS     1
+#define CONFIG_ENV_SPI_MAX_HZ  50000000
+#endif
+
+/* PMIC */
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_MAX77686
+
+/* SPI */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_SPI_FLASH
+
+#ifdef CONFIG_SPI_FLASH
+#define CONFIG_EXYNOS_SPI
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_SPI_FLASH_WINBOND
+#define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
+#define CONFIG_SF_DEFAULT_SPEED                50000000
+#define EXYNOS5_SPI_NUM_CONTROLLERS    5
+#endif
+
+#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SPI_MODE    SPI_MODE_0
+#define CONFIG_ENV_SECT_SIZE   CONFIG_ENV_SIZE
+#define CONFIG_ENV_SPI_BUS     1
+#define CONFIG_ENV_SPI_MAX_HZ  50000000
+#endif
 
 /* Ethernet Controllor Driver */
 #ifdef CONFIG_CMD_NET
 #define CONFIG_ENV_SROM_BANK           1
 #endif /*CONFIG_CMD_NET*/
 
+/* Enable PXE Support */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_CMD_PXE
+#define CONFIG_MENU
+#endif
+
+/* Sound */
+#define CONFIG_CMD_SOUND
+#ifdef CONFIG_CMD_SOUND
+#define CONFIG_SOUND
+#define CONFIG_I2S
+#define CONFIG_SOUND_WM8994
+#endif
+
 /* Enable devicetree support */
 #define CONFIG_OF_LIBFDT
 
+/* SHA hashing */
+#define CONFIG_CMD_HASH
+#define CONFIG_HASH_VERIFY
+#define CONFIG_SHA1
+#define CONFIG_SHA256
+
 #endif /* __CONFIG_H */
index 140d2e66327c7c880d42356415c7b40c7620fbd7..200cf66647c02dcbdc331d28d2a838d197ea4721 100644 (file)
@@ -54,7 +54,6 @@
 #define CONFIG_CMD_NAND
 #define CONFIG_TEGRA_NAND
 #define CONFIG_SYS_MAX_NAND_DEVICE     1
-#define CONFIG_SYS_NAND_BASE           NV_PA_NAND_BASE
 
 /* Environment in NAND, aligned to start of last sector */
 #define CONFIG_ENV_IS_IN_NAND
index 6f310bee601328b3eab4e492e1c9cbe5b1a6ca80..ee40cc2a3e0e26a38d3ddf58bf5f74c01db5c190 100644 (file)
 
 #else
 
-#ifdef CONFIG_CMD_EXT2
-#define BOOT_FSTYPE_EXT2 "ext2 "
-#else
-#define BOOT_FSTYPE_EXT2 ""
-#endif
-
-#ifdef CONFIG_CMD_FAT
-#define BOOT_FSTYPE_FAT "fat"
-#else
-#define BOOT_FSTYPE_FAT ""
-#endif
-
 #ifdef CONFIG_CMD_MMC
 #define BOOTCMDS_MMC \
        "mmc_boot=" \
@@ -98,7 +86,7 @@
        "rootpart=1\0" \
        \
        "script_boot="                                                    \
-               "if ${fs}load ${devtype} ${devnum}:${rootpart} "          \
+               "if load ${devtype} ${devnum}:${rootpart} "               \
                                "${scriptaddr} ${prefix}${script}; then " \
                        "echo ${script} found! Executing ...;"            \
                        "source ${scriptaddr};"                           \
        \
        "scan_boot="                                                      \
                "echo Scanning ${devtype} ${devnum}...; "                 \
-               "for fs in ${boot_fstypes}; do "                          \
-                       "for prefix in ${boot_prefixes}; do "             \
-                               "for script in ${boot_scripts}; do "      \
-                                       "run script_boot; "               \
-                               "done; "                                  \
+               "for prefix in ${boot_prefixes}; do "                     \
+                       "for script in ${boot_scripts}; do "              \
+                               "run script_boot; "                       \
                        "done; "                                          \
                "done;\0"                                                 \
        \
                BOOT_TARGETS_DHCP " " \
                "\0" \
        \
-       "boot_fstypes=" \
-               BOOT_FSTYPE_EXT2 " " \
-               BOOT_FSTYPE_FAT " " \
-               "\0" \
-       \
        "boot_prefixes=/ /boot/\0" \
        \
        "boot_scripts=boot.scr.uimg boot.scr\0" \
 
 #define TEGRA_DEVICE_SETTINGS \
        "stdin=serial" STDIN_KBD_KBC STDIN_KBD_USB "\0" \
-       "stdout=serial\0" \
-       "stderr=serial\0" \
+       "stdout=serial,lcd\0" \
+       "stderr=serial,lcd\0" \
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
        TEGRA_DEVICE_SETTINGS \
 #ifdef CONFIG_EFI_PARTITION
 #undef CONFIG_EFI_PARTITION
 #endif
+#ifdef CONFIG_CMD_FS_GENERIC
+#undef CONFIG_CMD_FS_GENERIC
+#endif
+#ifdef CONFIG_CMD_EXT4
+#undef CONFIG_CMD_EXT4
+#endif
 #ifdef CONFIG_CMD_EXT2
 #undef CONFIG_CMD_EXT2
 #endif
 #ifdef CONFIG_CMD_FAT
 #undef CONFIG_CMD_FAT
 #endif
+#ifdef CONFIG_FS_EXT4
+#undef CONFIG_FS_EXT4
+#endif
+#ifdef CONFIG_FS_FAT
+#undef CONFIG_FS_FAT
+#endif
 
 /* remove USB */
 #ifdef CONFIG_USB_EHCI
index 5c0833a4d8ccfa32e4a893d5d05d337e426e6557..fe07f72260de43ef37cd982fab60fa9ccb9ff0bc 100644 (file)
@@ -38,6 +38,9 @@
 
 #include <asm/arch/tegra.h>            /* get chip and board defs */
 
+/* Align LCD to 1MB boundary */
+#define CONFIG_LCD_ALIGNMENT   MMU_SECTION_SIZE
+
 /*
  * Display CPU and Board information
  */
index 355029e8d835a0d4a495c4c1e694472c0e031055..6efee5c47707b4c1678ba06786df90e4deff4a8d 100644 (file)
@@ -98,6 +98,7 @@
 #undef CONFIG_CMD_MTDPARTS
 #define CONFIG_CMD_MMC
 #define CONFIG_CMD_DFU
+#define CONFIG_CMD_GPT
 
 /* FAT */
 #define CONFIG_CMD_FAT
 #define CONFIG_BOOTBLOCK               "10"
 #define CONFIG_ENV_COMMON_BOOT         "${console} ${meminfo}"
 
+/* Tizen - partitions definitions */
+#define PARTS_CSA              "csa-mmc"
+#define PARTS_BOOTLOADER       "u-boot"
+#define PARTS_BOOT             "boot"
+#define PARTS_ROOT             "platform"
+#define PARTS_DATA             "data"
+#define PARTS_CSC              "csc"
+#define PARTS_UMS              "ums"
+
+#define PARTS_DEFAULT \
+       "uuid_disk=${uuid_gpt_disk};" \
+       "name="PARTS_CSA",size=8MiB,uuid=${uuid_gpt_"PARTS_CSA"};" \
+       "name="PARTS_BOOTLOADER",size=60MiB," \
+               "uuid=${uuid_gpt_"PARTS_BOOTLOADER"};" \
+       "name="PARTS_BOOT",size=100MiB,uuid=${uuid_gpt_"PARTS_BOOT"};" \
+       "name="PARTS_ROOT",size=1GiB,uuid=${uuid_gpt_"PARTS_ROOT"};" \
+       "name="PARTS_DATA",size=3GiB,uuid=${uuid_gpt_"PARTS_DATA"};" \
+       "name="PARTS_CSC",size=150MiB,uuid=${uuid_gpt_"PARTS_CSC"};" \
+       "name="PARTS_UMS",size=-,uuid=${uuid_gpt_"PARTS_UMS"}\0" \
+
 #define CONFIG_DFU_ALT \
        "dfu_alt_info=" \
        "u-boot mmc 80 400;" \
        "mmcbootpart=2\0" \
        "mmcrootpart=3\0" \
        "opts=always_resume=1\0" \
-       CONFIG_DFU_ALT
+       "partitions=" PARTS_DEFAULT \
+       CONFIG_DFU_ALT \
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP            /* undef to save memory */
 
 #define CONFIG_SYS_HZ                  1000
 
-/* TRATS has 2 banks of DRAM */
-#define CONFIG_NR_DRAM_BANKS   2
-#define PHYS_SDRAM_1           CONFIG_SYS_SDRAM_BASE   /* LDDDR2 DMC 0 */
-#define PHYS_SDRAM_1_SIZE      (512 << 20)             /* 512 MB in CS 0 */
-#define PHYS_SDRAM_2           0x50000000              /* LPDDR2 DMC 1 */
-#define PHYS_SDRAM_2_SIZE      (512 << 20)             /* 512 MB in CS 0 */
+/* TRATS has 4 banks of DRAM */
+#define CONFIG_NR_DRAM_BANKS   4
+#define SDRAM_BANK_SIZE                (256UL << 20UL) /* 256 MB */
+#define PHYS_SDRAM_1           CONFIG_SYS_SDRAM_BASE
+#define PHYS_SDRAM_1_SIZE      SDRAM_BANK_SIZE
+#define PHYS_SDRAM_2           (CONFIG_SYS_SDRAM_BASE + SDRAM_BANK_SIZE)
+#define PHYS_SDRAM_2_SIZE      SDRAM_BANK_SIZE
+#define PHYS_SDRAM_3           (CONFIG_SYS_SDRAM_BASE + (2 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_3_SIZE      SDRAM_BANK_SIZE
+#define PHYS_SDRAM_4           (CONFIG_SYS_SDRAM_BASE + (3 * SDRAM_BANK_SIZE))
+#define PHYS_SDRAM_4_SIZE      SDRAM_BANK_SIZE
 
 #define CONFIG_SYS_MEM_TOP_HIDE                (1 << 20)       /* ram console */
 
 
 #define CONFIG_DOS_PARTITION
 
+/* GPT */
+#define CONFIG_EFI_PARTITION
+#define CONFIG_PARTITION_UUIDS
+
 #define CONFIG_SYS_INIT_SP_ADDR        (CONFIG_SYS_LOAD_ADDR - GENERATED_GBL_DATA_SIZE)
 #define CONFIG_SYS_CACHELINE_SIZE       32
 
index eeb0dbe237b2bea407d9a0f8ca25e24f7ce102cc..334d3a3b8b8eee353ee5be23d678ed3fb56067ef 100644 (file)
 
 #define CONFIG_DOS_PARTITION
 #define CONFIG_EFI_PARTITION
+#define CONFIG_FS_EXT4
+#define CONFIG_FS_FAT
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
 
 /* Environment in SPI */
 #define CONFIG_ENV_IS_IN_SPI_FLASH
@@ -80,6 +83,7 @@
 #define CONFIG_ENV_OFFSET              (512 * 1024)
 
 /* USB Host support */
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 3
 #define CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_TEGRA
 #define CONFIG_USB_STORAGE
index d203bb4dd7fc3fa35eabeea467412534692c4da6..66568c8d004b63bc52d4df7dadae752184585238 100644 (file)
@@ -65,7 +65,6 @@
 #define CONFIG_BOOTARGS                "root=/dev/ram console=ttyS0,57600" /* RAMdisk */
 #define CONFIG_ETHADDR         00:AA:00:14:00:05       /* UTX5 */
 #define CONFIG_SERVERIP                10.8.17.105     /* Spree */
-#define CONFIG_SYS_TFTP_LOADADDR       10000
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
        "kernel_addr=FFA00000\0" \
index 4c9b31cce30d497864828ba23dcf0d7fee37f440..b55ebc9bfc00a890496dcac8a17d813f14b7a5f5 100644 (file)
 
 #define CONFIG_DOS_PARTITION
 #define CONFIG_EFI_PARTITION
+#define CONFIG_FS_EXT4
+#define CONFIG_FS_FAT
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
 
 /* Environment in eMMC, at the end of 2nd "boot sector" */
 #define CONFIG_ENV_IS_IN_MMC
index 1c7803b2660f47e073fa29242499bca0c1233e54..1e554d81647b52aa91a9715d5c0bbdd5eebb575e 100644 (file)
 
 #define CONFIG_DOS_PARTITION
 #define CONFIG_EFI_PARTITION
+#define CONFIG_FS_EXT4
+#define CONFIG_FS_FAT
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
 
 /*
  * Environment in eMMC, at the end of 2nd "boot sector". Note: This assumes
index bf6394a90ae90d6cff7bcb8c53008dc71ca50847..b92f70b538d72552572e038e697206ad6b7d9858 100644 (file)
@@ -41,6 +41,9 @@
 #define CONFIG_ENV_ADDR                        0x40000
 #define CONFIG_ENV_SIZE                        0x20000
 
+/* we will never enable dcache, because we have to setup MMU first */
+#define CONFIG_SYS_DCACHE_OFF
+
 #define        CONFIG_SYS_MALLOC_LEN           (128*1024)
 #define        CONFIG_ARCH_CPU_INIT
 
diff --git a/include/edid.h b/include/edid.h
new file mode 100644 (file)
index 0000000..4788de9
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * (C) Copyright 2010
+ * Petr Stetiar <ynezz@true.cz>
+ *
+ * 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
+ *
+ * Contains stolen code from ddcprobe project which is:
+ * Copyright (C) Nalin Dahyabhai <bigfun@pobox.com>
+ *
+ */
+
+#ifndef __EDID_H_
+#define __EDID_H_
+
+#include <linux/types.h>
+
+#define GET_BIT(_x, _pos) \
+       (((_x) >> (_pos)) & 1)
+#define GET_BITS(_x, _pos_msb, _pos_lsb) \
+       (((_x) >> (_pos_lsb)) & ((1 << ((_pos_msb) - (_pos_lsb) + 1)) - 1))
+
+/* Aspect ratios used in EDID info. */
+enum edid_aspect {
+       ASPECT_625 = 0,
+       ASPECT_75,
+       ASPECT_8,
+       ASPECT_5625,
+};
+
+/* Detailed timing information used in EDID v1.x */
+struct edid_detailed_timing {
+       unsigned char pixel_clock[2];
+#define EDID_DETAILED_TIMING_PIXEL_CLOCK(_x) \
+       (((((uint32_t)(_x).pixel_clock[1]) << 8) + \
+        (_x).pixel_clock[0]) * 10000)
+       unsigned char horizontal_active;
+       unsigned char horizontal_blanking;
+       unsigned char horizontal_active_blanking_hi;
+#define EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(_x) \
+       ((GET_BITS((_x).horizontal_active_blanking_hi, 7, 4) << 8) + \
+        (_x).horizontal_active)
+#define EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(_x) \
+       ((GET_BITS((_x).horizontal_active_blanking_hi, 3, 0) << 8) + \
+        (_x).horizontal_blanking)
+       unsigned char vertical_active;
+       unsigned char vertical_blanking;
+       unsigned char vertical_active_blanking_hi;
+#define EDID_DETAILED_TIMING_VERTICAL_ACTIVE(_x) \
+       ((GET_BITS((_x).vertical_active_blanking_hi, 7, 4) << 8) + \
+        (_x).vertical_active)
+#define EDID_DETAILED_TIMING_VERTICAL_BLANKING(_x) \
+       ((GET_BITS((_x).vertical_active_blanking_hi, 3, 0) << 8) + \
+        (_x).vertical_blanking)
+       unsigned char hsync_offset;
+       unsigned char hsync_pulse_width;
+       unsigned char sync_offset_pulse_width;
+       unsigned char hsync_vsync_offset_pulse_width_hi;
+#define EDID_DETAILED_TIMING_HSYNC_OFFSET(_x) \
+       ((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 7, 6) << 8) + \
+        (_x).hsync_offset)
+#define EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(_x) \
+       ((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 5, 4) << 8) + \
+        (_x).hsync_pulse_width)
+#define EDID_DETAILED_TIMING_VSYNC_OFFSET(_x) \
+       ((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 3, 2) << 4) + \
+        GET_BITS((_x).vsync_offset_pulse_width, 7, 4))
+#define EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(_x) \
+       ((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 1, 0) << 4) + \
+        GET_BITS((_x).vsync_offset_pulse_width, 3, 0))
+       unsigned char himage_size;
+       unsigned char vimage_size;
+       unsigned char himage_vimage_size_hi;
+#define EDID_DETAILED_TIMING_HIMAGE_SIZE(_x) \
+       ((GET_BITS((_x).himage_vimage_size_hi, 7, 4) << 8) + (_x).himage_size)
+#define EDID_DETAILED_TIMING_VIMAGE_SIZE(_x) \
+       ((GET_BITS((_x).himage_vimage_size_hi, 3, 0) << 8) + (_x).vimage_size)
+       unsigned char hborder;
+       unsigned char vborder;
+       unsigned char flags;
+#define EDID_DETAILED_TIMING_FLAG_INTERLACED(_x) \
+       GET_BIT((_x).flags, 7)
+#define EDID_DETAILED_TIMING_FLAG_STEREO(_x) \
+       GET_BITS((_x).flags, 6, 5)
+#define EDID_DETAILED_TIMING_FLAG_DIGITAL_COMPOSITE(_x) \
+       GET_BITS((_x).flags, 4, 3)
+#define EDID_DETAILED_TIMING_FLAG_POLARITY(_x) \
+       GET_BITS((_x).flags, 2, 1)
+#define EDID_DETAILED_TIMING_FLAG_INTERLEAVED(_x) \
+       GET_BIT((_x).flags, 0)
+} __attribute__ ((__packed__));
+
+enum edid_monitor_descriptor_types {
+       EDID_MONITOR_DESCRIPTOR_SERIAL = 0xff,
+       EDID_MONITOR_DESCRIPTOR_ASCII = 0xfe,
+       EDID_MONITOR_DESCRIPTOR_RANGE = 0xfd,
+       EDID_MONITOR_DESCRIPTOR_NAME = 0xfc,
+};
+
+struct edid_monitor_descriptor {
+       uint16_t zero_flag_1;
+       unsigned char zero_flag_2;
+       unsigned char type;
+       unsigned char zero_flag_3;
+       union {
+               char string[13];
+               struct {
+                       unsigned char vertical_min;
+                       unsigned char vertical_max;
+                       unsigned char horizontal_min;
+                       unsigned char horizontal_max;
+                       unsigned char pixel_clock_max;
+                       unsigned char gtf_data[8];
+               } range_data;
+       } data;
+} __attribute__ ((__packed__));
+
+struct edid1_info {
+       unsigned char header[8];
+       unsigned char manufacturer_name[2];
+#define EDID1_INFO_MANUFACTURER_NAME_ZERO(_x) \
+       GET_BIT(((_x).manufacturer_name[0]), 7)
+#define EDID1_INFO_MANUFACTURER_NAME_CHAR1(_x) \
+       GET_BITS(((_x).manufacturer_name[0]), 6, 2)
+#define EDID1_INFO_MANUFACTURER_NAME_CHAR2(_x) \
+       ((GET_BITS(((_x).manufacturer_name[0]), 1, 0) << 3) + \
+        GET_BITS(((_x).manufacturer_name[1]), 7, 5))
+#define EDID1_INFO_MANUFACTURER_NAME_CHAR3(_x) \
+       GET_BITS(((_x).manufacturer_name[1]), 4, 0)
+       unsigned char product_code[2];
+#define EDID1_INFO_PRODUCT_CODE(_x) \
+       (((uint16_t)(_x).product_code[1] << 8) + (_x).product_code[0])
+       unsigned char serial_number[4];
+#define EDID1_INFO_SERIAL_NUMBER(_x) \
+       (((uint32_t)(_x).serial_number[3] << 24) + \
+        ((_x).serial_number[2] << 16) + ((_x).serial_number[1] << 8) + \
+        (_x).serial_number[0])
+       unsigned char week;
+       unsigned char year;
+       unsigned char version;
+       unsigned char revision;
+       unsigned char video_input_definition;
+#define EDID1_INFO_VIDEO_INPUT_DIGITAL(_x) \
+       GET_BIT(((_x).video_input_definition), 7)
+#define EDID1_INFO_VIDEO_INPUT_VOLTAGE_LEVEL(_x) \
+       GET_BITS(((_x).video_input_definition), 6, 5)
+#define EDID1_INFO_VIDEO_INPUT_BLANK_TO_BLACK(_x) \
+       GET_BIT(((_x).video_input_definition), 4)
+#define EDID1_INFO_VIDEO_INPUT_SEPARATE_SYNC(_x) \
+       GET_BIT(((_x).video_input_definition), 3)
+#define EDID1_INFO_VIDEO_INPUT_COMPOSITE_SYNC(_x) \
+       GET_BIT(((_x).video_input_definition), 2)
+#define EDID1_INFO_VIDEO_INPUT_SYNC_ON_GREEN(_x) \
+       GET_BIT(((_x).video_input_definition), 1)
+#define EDID1_INFO_VIDEO_INPUT_SERRATION_V(_x) \
+       GET_BIT(((_x).video_input_definition), 0)
+       unsigned char max_size_horizontal;
+       unsigned char max_size_vertical;
+       unsigned char gamma;
+       unsigned char feature_support;
+#define EDID1_INFO_FEATURE_STANDBY(_x) \
+       GET_BIT(((_x).feature_support), 7)
+#define EDID1_INFO_FEATURE_SUSPEND(_x) \
+       GET_BIT(((_x).feature_support), 6)
+#define EDID1_INFO_FEATURE_ACTIVE_OFF(_x) \
+       GET_BIT(((_x).feature_support), 5)
+#define EDID1_INFO_FEATURE_DISPLAY_TYPE(_x) \
+       GET_BITS(((_x).feature_support), 4, 3)
+#define EDID1_INFO_FEATURE_RGB(_x) \
+       GET_BIT(((_x).feature_support), 2)
+#define EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(_x) \
+       GET_BIT(((_x).feature_support), 1)
+#define EDID1_INFO_FEATURE_DEFAULT_GTF_SUPPORT(_x) \
+       GET_BIT(((_x).feature_support), 0)
+       unsigned char color_characteristics[10];
+       unsigned char established_timings[3];
+#define EDID1_INFO_ESTABLISHED_TIMING_720X400_70(_x) \
+       GET_BIT(((_x).established_timings[0]), 7)
+#define EDID1_INFO_ESTABLISHED_TIMING_720X400_88(_x) \
+       GET_BIT(((_x).established_timings[0]), 6)
+#define EDID1_INFO_ESTABLISHED_TIMING_640X480_60(_x) \
+       GET_BIT(((_x).established_timings[0]), 5)
+#define EDID1_INFO_ESTABLISHED_TIMING_640X480_67(_x) \
+       GET_BIT(((_x).established_timings[0]), 4)
+#define EDID1_INFO_ESTABLISHED_TIMING_640X480_72(_x) \
+       GET_BIT(((_x).established_timings[0]), 3)
+#define EDID1_INFO_ESTABLISHED_TIMING_640X480_75(_x) \
+       GET_BIT(((_x).established_timings[0]), 2)
+#define EDID1_INFO_ESTABLISHED_TIMING_800X600_56(_x) \
+       GET_BIT(((_x).established_timings[0]), 1)
+#define EDID1_INFO_ESTABLISHED_TIMING_800X600_60(_x) \
+       GET_BIT(((_x).established_timings[0]), 0)
+#define EDID1_INFO_ESTABLISHED_TIMING_800X600_72(_x) \
+       GET_BIT(((_x).established_timings[1]), 7)
+#define EDID1_INFO_ESTABLISHED_TIMING_800X600_75(_x) \
+       GET_BIT(((_x).established_timings[1]), 6)
+#define EDID1_INFO_ESTABLISHED_TIMING_832X624_75(_x) \
+       GET_BIT(((_x).established_timings[1]), 5)
+#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_87I(_x) \
+       GET_BIT(((_x).established_timings[1]), 4)
+#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_60(_x) \
+       GET_BIT(((_x).established_timings[1]), 3)
+#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_70(_x) \
+       GET_BIT(((_x).established_timings[1]), 2)
+#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_75(_x) \
+       GET_BIT(((_x).established_timings[1]), 1)
+#define EDID1_INFO_ESTABLISHED_TIMING_1280X1024_75(_x) \
+       GET_BIT(((_x).established_timings[1]), 0)
+#define EDID1_INFO_ESTABLISHED_TIMING_1152X870_75(_x) \
+       GET_BIT(((_x).established_timings[2]), 7)
+       struct {
+               unsigned char xresolution;
+               unsigned char aspect_vfreq;
+       } __attribute__((__packed__)) standard_timings[8];
+#define EDID1_INFO_STANDARD_TIMING_XRESOLUTION(_x, _i) \
+       (((_x).standard_timings[_i]).xresolution)
+#define EDID1_INFO_STANDARD_TIMING_ASPECT(_x, _i) \
+       GET_BITS(((_x).standard_timings[_i].aspect_vfreq), 7, 6)
+#define EDID1_INFO_STANDARD_TIMING_VFREQ(_x, _i) \
+       GET_BITS(((_x).standard_timings[_i].aspect_vfreq), 5, 0)
+       union {
+               unsigned char timing[72];
+               struct edid_monitor_descriptor descriptor[4];
+       } monitor_details;
+       unsigned char extension_flag;
+       unsigned char checksum;
+} __attribute__ ((__packed__));
+
+/**
+ * Print the EDID info.
+ *
+ * @param edid_info    The EDID info to be printed
+ */
+void edid_print_info(struct edid1_info *edid_info);
+
+/**
+ * Check the EDID info.
+ *
+ * @param info  The EDID info to be checked
+ * @return 0 on valid, or -1 on invalid
+ */
+int edid_check_info(struct edid1_info *info);
+
+/**
+ * Get the horizontal and vertical rate ranges of the monitor.
+ *
+ * @param edid The EDID info
+ * @param hmin Returns the minimum horizontal rate
+ * @param hmax Returns the maxium horizontal rate
+ * @param vmin Returns the minimum vertical rate
+ * @param vmax Returns the maxium vertical rate
+ * @return 0 on success, or -1 on error
+ */
+int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin,
+                   unsigned int *hmax, unsigned int *vmin,
+                   unsigned int *vmax);
+
+#endif /* __EDID_H_ */
diff --git a/include/env_attr.h b/include/env_attr.h
new file mode 100644 (file)
index 0000000..6ef114f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2012
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.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 __ENV_ATTR_H__
+#define __ENV_ATTR_H__
+
+#define ENV_ATTR_LIST_DELIM    ','
+#define ENV_ATTR_SEP           ':'
+
+/*
+ * env_attr_walk takes as input an "attr_list" that takes the form:
+ *     attributes = [^,:\s]*
+ *     entry = name[:attributes]
+ *     list = entry[,list]
+ * It will call the "callback" function with the "name" and attribute as "value"
+ * The callback may return a non-0 to abort the list walk.
+ * This return value will be passed through to the caller.
+ * 0 is returned on success.
+ */
+extern int env_attr_walk(const char *attr_list,
+       int (*callback)(const char *name, const char *value));
+
+/*
+ * env_attr_lookup takes as input an "attr_list" with the same form as above.
+ * It also takes as input a "name" to look for.
+ * If the name is found in the list, it's value is copied into "attributes".
+ * There is no protection on attributes being too small for the value.
+ * It returns -1 if attributes is NULL, 1 if "name" is not found, 2 if
+ * "attr_list" is NULL.
+ * Returns 0 on success.
+ */
+extern int env_attr_lookup(const char *attr_list, const char *name,
+       char *attributes);
+
+#endif /* __ENV_ATTR_H__ */
diff --git a/include/env_callback.h b/include/env_callback.h
new file mode 100644 (file)
index 0000000..47fdc6f
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2012
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.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 __ENV_CALLBACK_H__
+#define __ENV_CALLBACK_H__
+
+#include <env_flags.h>
+#include <linker_lists.h>
+#include <search.h>
+
+#define ENV_CALLBACK_VAR ".callbacks"
+
+/* Board configs can define additional static callback bindings */
+#ifndef CONFIG_ENV_CALLBACK_LIST_STATIC
+#define CONFIG_ENV_CALLBACK_LIST_STATIC
+#endif
+
+#ifdef CONFIG_SILENT_CONSOLE
+#define SILENT_CALLBACK "silent:silent,"
+#else
+#define SILENT_CALLBACK
+#endif
+
+/*
+ * This list of callback bindings is static, but may be overridden by defining
+ * a new association in the ".callbacks" environment variable.
+ */
+#define ENV_CALLBACK_LIST_STATIC ENV_CALLBACK_VAR ":callbacks," \
+       ENV_FLAGS_VAR ":flags," \
+       "baudrate:baudrate," \
+       "bootfile:bootfile," \
+       "loadaddr:loadaddr," \
+       SILENT_CALLBACK \
+       "stdin:console,stdout:console,stderr:console," \
+       CONFIG_ENV_CALLBACK_LIST_STATIC
+
+struct env_clbk_tbl {
+       const char *name;               /* Callback name */
+       int (*callback)(const char *name, const char *value, enum env_op op,
+               int flags);
+};
+
+struct env_clbk_tbl *find_env_callback(const char *);
+void env_callback_init(ENTRY *var_entry);
+
+/*
+ * Define a callback that can be associated with variables.
+ * when associated through the ".callbacks" environment variable, the callback
+ * will be executed any time the variable is inserted, overwritten, or deleted.
+ */
+#define U_BOOT_ENV_CALLBACK(name, callback) \
+       ll_entry_declare(struct env_clbk_tbl, name, env_clbk, env_clbk) = \
+       {#name, callback}
+
+#endif /* __ENV_CALLBACK_H__ */
index a1db73a2c559324c2360bded35188335a7da51ee..39c5b7c6aa3b0e09c006d91bf6ec57567f4d3b22 100644 (file)
@@ -24,6 +24,8 @@
  * MA 02111-1307 USA
  */
 
+#include <env_callback.h>
+
 #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
 env_t environment __PPCENV__ = {
        ENV_CRC,        /* CRC Sum */
@@ -36,6 +38,12 @@ static char default_environment[] = {
 #else
 const uchar default_environment[] = {
 #endif
+#ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT
+       ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
+#endif
+#ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT
+       ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
+#endif
 #ifdef CONFIG_BOOTARGS
        "bootargs="     CONFIG_BOOTARGS                 "\0"
 #endif
diff --git a/include/env_flags.h b/include/env_flags.h
new file mode 100644 (file)
index 0000000..d1aa144
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * (C) Copyright 2012
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.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 __ENV_FLAGS_H__
+#define __ENV_FLAGS_H__
+
+enum env_flags_vartype {
+       env_flags_vartype_string,
+       env_flags_vartype_decimal,
+       env_flags_vartype_hex,
+       env_flags_vartype_bool,
+#ifdef CONFIG_CMD_NET
+       env_flags_vartype_ipaddr,
+       env_flags_vartype_macaddr,
+#endif
+       env_flags_vartype_end
+};
+
+enum env_flags_varaccess {
+       env_flags_varaccess_any,
+       env_flags_varaccess_readonly,
+       env_flags_varaccess_writeonce,
+       env_flags_varaccess_changedefault,
+       env_flags_varaccess_end
+};
+
+#define ENV_FLAGS_VAR ".flags"
+#define ENV_FLAGS_ATTR_MAX_LEN 2
+#define ENV_FLAGS_VARTYPE_LOC 0
+#define ENV_FLAGS_VARACCESS_LOC 1
+
+#ifndef CONFIG_ENV_FLAGS_LIST_STATIC
+#define CONFIG_ENV_FLAGS_LIST_STATIC ""
+#endif
+
+#ifdef CONFIG_CMD_NET
+#ifdef CONFIG_ENV_OVERWRITE
+#define ETHADDR_FLAGS "ethaddr:ma,"
+#else
+#ifdef CONFIG_OVERWRITE_ETHADDR_ONCE
+#define ETHADDR_FLAGS "ethaddr:mc,"
+#else
+#define ETHADDR_FLAGS "ethaddr:mo,"
+#endif
+#endif
+#else
+#define ETHADDR_FLAGS ""
+#endif
+
+#ifndef CONFIG_ENV_OVERWRITE
+#define SERIAL_FLAGS "serial#:so,"
+#else
+#define SERIAL_FLAGS ""
+#endif
+
+#define ENV_FLAGS_LIST_STATIC \
+       ETHADDR_FLAGS \
+       SERIAL_FLAGS \
+       CONFIG_ENV_FLAGS_LIST_STATIC
+
+#ifdef CONFIG_CMD_ENV_FLAGS
+/*
+ * Print the whole list of available type flags.
+ */
+void env_flags_print_vartypes(void);
+/*
+ * Print the whole list of available access flags.
+ */
+void env_flags_print_varaccess(void);
+/*
+ * Return the name of the type.
+ */
+const char *env_flags_get_vartype_name(enum env_flags_vartype type);
+/*
+ * Return the name of the access.
+ */
+const char *env_flags_get_varaccess_name(enum env_flags_varaccess access);
+#endif
+
+/*
+ * Parse the flags string from a .flags attribute list into the vartype enum.
+ */
+enum env_flags_vartype env_flags_parse_vartype(const char *flags);
+/*
+ * Parse the flags string from a .flags attribute list into the varaccess enum.
+ */
+enum env_flags_varaccess env_flags_parse_varaccess(const char *flags);
+/*
+ * Parse the binary flags from a hash table entry into the varaccess enum.
+ */
+enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags);
+
+#ifdef USE_HOSTCC
+/*
+ * Look up the type of a variable directly from the .flags var.
+ */
+enum env_flags_vartype env_flags_get_type(const char *name);
+/*
+ * Look up the access of a variable directly from the .flags var.
+ */
+enum env_flags_varaccess env_flags_get_access(const char *name);
+/*
+ * Validate the newval for its type to conform with the requirements defined by
+ * its flags (directly looked at the .flags var).
+ */
+int env_flags_validate_type(const char *name, const char *newval);
+/*
+ * Validate the newval for its access to conform with the requirements defined
+ * by its flags (directly looked at the .flags var).
+ */
+int env_flags_validate_access(const char *name, int check_mask);
+/*
+ * Validate that the proposed access to variable "name" is valid according to
+ * the defined flags for that variable, if any.
+ */
+int env_flags_validate_varaccess(const char *name, int check_mask);
+/*
+ * Validate the parameters passed to "env set" for type compliance
+ */
+int env_flags_validate_env_set_params(int argc, char * const argv[]);
+
+#else /* !USE_HOSTCC */
+
+#include <search.h>
+
+/*
+ * When adding a variable to the environment, initialize the flags for that
+ * variable.
+ */
+void env_flags_init(ENTRY *var_entry);
+
+/*
+ * Validate the newval for to conform with the requirements defined by its flags
+ */
+int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op,
+       int flag);
+
+#endif /* USE_HOSTCC */
+
+/*
+ * These are the binary flags used in the environment entry->flags variable to
+ * decribe properties of veriables in the table
+ */
+#define ENV_FLAGS_VARTYPE_BIN_MASK                     0x00000007
+/* The actual variable type values use the enum value (within the mask) */
+#define ENV_FLAGS_VARACCESS_PREVENT_DELETE             0x00000008
+#define ENV_FLAGS_VARACCESS_PREVENT_CREATE             0x00000010
+#define ENV_FLAGS_VARACCESS_PREVENT_OVERWR             0x00000020
+#define ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR      0x00000040
+#define ENV_FLAGS_VARACCESS_BIN_MASK                   0x00000078
+
+#endif /* __ENV_FLAGS_H__ */
index e8ab7033bf7e75166d2e008985215da45146471d..e64b43d2d94834760553dc9a0cd06f632022394b 100644 (file)
@@ -164,6 +164,9 @@ extern void env_reloc(void);
 
 #ifndef DO_DEPS_ONLY
 
+#include <env_attr.h>
+#include <env_callback.h>
+#include <env_flags.h>
 #include <search.h>
 
 extern struct hsearch_data env_htab;
@@ -178,6 +181,9 @@ unsigned char env_get_char_memory(int index);
 /* Function that updates CRC of the enironment */
 void env_crc_update(void);
 
+/* Look up the variable from the default environment */
+char *getenv_default(const char *name);
+
 /* [re]set to the default environment */
 void set_default_env(const char *s);
 
@@ -187,15 +193,6 @@ int set_default_vars(int nvars, char * const vars[]);
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
-/*
- * Check if variable "name" can be changed from oldval to newval,
- * and if so, apply the changes (e.g. baudrate).
- * When (flag & H_FORCE) is set, it does not print out any error
- * message and forces overwriting of write-once variables.
- */
-int env_check_apply(const char *name, const char *oldval,
-                       const char *newval, int flag);
-
 #endif /* DO_DEPS_ONLY */
 
 #endif /* _ENVIRONMENT_H_ */
index 63aa4b264a17e70687c5e2aab8851d374f2a9b45..6cf31aa5e794c0c6fb186bb6ee3705136cc40a2b 100644 (file)
@@ -23,7 +23,7 @@ char *getenv (const char *name);
 int setenv (const char *varname, const char *varvalue);
 long simple_strtol(const char *cp,char **endp,unsigned int base);
 int strcmp(const char * cs,const char * ct);
-int ustrtoul(const char *cp, char **endp, unsigned int base);
+unsigned long ustrtoul(const char *cp, char **endp, unsigned int base);
 #if defined(CONFIG_CMD_I2C)
 int i2c_write (uchar, uint, int , uchar* , int);
 int i2c_read (uchar, uint, int , uchar* , int);
index 5164ce24e61e2686ae6fb664862dfc8363a4238f..70d0e979d127b38f9358218d214a3e7b69d55c38 100644 (file)
@@ -68,6 +68,8 @@ enum fdt_compat_id {
        COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */
        COMPAT_NVIDIA_TEGRA20_KBC,      /* Tegra20 Keyboard */
        COMPAT_NVIDIA_TEGRA20_NAND,     /* Tegra2 NAND controller */
+       COMPAT_NVIDIA_TEGRA20_PWM,      /* Tegra 2 PWM controller */
+       COMPAT_NVIDIA_TEGRA20_DC,       /* Tegra 2 Display controller */
 
        COMPAT_COUNT,
 };
diff --git a/include/hash.h b/include/hash.h
new file mode 100644 (file)
index 0000000..34ba558
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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 _HASH_H
+#define _HASH_H
+
+#ifdef CONFIG_SHA1SUM_VERIFY
+#define CONFIG_HASH_VERIFY
+#endif
+
+struct hash_algo {
+       const char *name;                       /* Name of algorithm */
+       int digest_size;                        /* Length of digest */
+       /**
+        * hash_func_ws: Generic hashing function
+        *
+        * This is the generic prototype for a hashing function. We only
+        * have the watchdog version at present.
+        *
+        * @input:      Input buffer
+        * @ilen:       Input buffer length
+        * @output:     Checksum result (length depends on algorithm)
+        * @chunk_sz:   Trigger watchdog after processing this many bytes
+        */
+       void (*hash_func_ws)(const unsigned char *input, unsigned int ilen,
+               unsigned char *output, unsigned int chunk_sz);
+       int chunk_size;                         /* Watchdog chunk size */
+};
+
+/*
+ * Maximum digest size for all algorithms we support. Having this value
+ * avoids a malloc() or C99 local declaration in common/cmd_hash.c.
+ */
+#define HASH_MAX_DIGEST_SIZE   32
+
+/**
+ * hash_command: Process a hash command for a particular algorithm
+ *
+ * This common function is used to implement specific hash commands.
+ *
+ * @algo_name:         Hash algorithm being used
+ * @verify:            Non-zero to enable verify mode
+ * @cmdtp:             Pointer to command table entry
+ * @flag:              Some flags normally 0 (see CMD_FLAG_.. above)
+ * @argc:              Number of arguments (arg 0 must be the command text)
+ * @argv:              Arguments
+ */
+int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
+                int argc, char * const argv[]);
+
+#endif
diff --git a/include/i2s.h b/include/i2s.h
new file mode 100644 (file)
index 0000000..75ae75c
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * R. Chandrasekar <rcsekar@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
+ */
+
+#ifndef __I2S_H__
+#define __I2S_H__
+
+/*
+ * DAI hardware audio formats.
+ *
+ * Describes the physical PCM data formating and clocking. Add new formats
+ * to the end.
+ */
+#define SND_SOC_DAIFMT_I2S             1 /* I2S mode */
+#define SND_SOC_DAIFMT_RIGHT_J         2 /* Right Justified mode */
+#define SND_SOC_DAIFMT_LEFT_J          3 /* Left Justified mode */
+#define SND_SOC_DAIFMT_DSP_A           4 /* L data MSB after FRM LRC */
+#define SND_SOC_DAIFMT_DSP_B           5 /* L data MSB during FRM LRC */
+#define SND_SOC_DAIFMT_AC97            6 /* AC97 */
+#define SND_SOC_DAIFMT_PDM             7 /* Pulse density modulation */
+
+/* left and right justified also known as MSB and LSB respectively */
+#define SND_SOC_DAIFMT_MSB             SND_SOC_DAIFMT_LEFT_J
+#define SND_SOC_DAIFMT_LSB             SND_SOC_DAIFMT_RIGHT_J
+
+/*
+ * DAI hardware signal inversions.
+ *
+ * Specifies whether the DAI can also support inverted clocks for the specified
+ * format.
+ */
+#define SND_SOC_DAIFMT_NB_NF   (1 << 8) /* normal bit clock + frame */
+#define SND_SOC_DAIFMT_NB_IF   (2 << 8) /* normal BCLK + inv FRM */
+#define SND_SOC_DAIFMT_IB_NF   (3 << 8) /* invert BCLK + nor FRM */
+#define SND_SOC_DAIFMT_IB_IF   (4 << 8) /* invert BCLK + FRM */
+
+/*
+ * DAI hardware clock masters.
+ *
+ * This is wrt the codec, the inverse is true for the interface
+ * i.e. if the codec is clk and FRM master then the interface is
+ * clk and frame slave.
+ */
+#define SND_SOC_DAIFMT_CBM_CFM (1 << 12) /* codec clk & FRM master */
+#define SND_SOC_DAIFMT_CBS_CFM (2 << 12) /* codec clk slave & FRM master */
+#define SND_SOC_DAIFMT_CBM_CFS (3 << 12) /* codec clk master & frame slave */
+#define SND_SOC_DAIFMT_CBS_CFS (4 << 12) /* codec clk & FRM slave */
+
+#define SND_SOC_DAIFMT_FORMAT_MASK     0x000f
+#define SND_SOC_DAIFMT_CLOCK_MASK      0x00f0
+#define SND_SOC_DAIFMT_INV_MASK                0x0f00
+#define SND_SOC_DAIFMT_MASTER_MASK     0xf000
+
+/*
+ * Master Clock Directions
+ */
+#define SND_SOC_CLOCK_IN               0
+#define SND_SOC_CLOCK_OUT              1
+
+/* I2S Tx Control */
+#define I2S_TX_ON      1
+#define I2S_TX_OFF     0
+
+#define FIFO_LENGTH    64
+
+/* I2s Registers */
+struct i2s_reg {
+       unsigned int con;       /* base + 0 , Control register */
+       unsigned int mod;       /* Mode register */
+       unsigned int fic;       /* FIFO control register */
+       unsigned int psr;       /* Reserved */
+       unsigned int txd;       /* Transmit data register */
+       unsigned int rxd;       /* Receive Data Register */
+};
+
+/* This structure stores the i2s related information */
+struct i2stx_info {
+       unsigned int rfs;               /* LR clock frame size */
+       unsigned int bfs;               /* Bit slock frame size */
+       unsigned int audio_pll_clk;     /* Audio pll frequency in Hz */
+       unsigned int samplingrate;      /* sampling rate */
+       unsigned int bitspersample;     /* bits per sample */
+       unsigned int channels;          /* audio channels */
+       unsigned int base_address;      /* I2S Register Base */
+};
+
+/*
+ * Sends the given data through i2s tx
+ *
+ * @param pi2s_tx      pointer of i2s transmitter parameter structure.
+ * @param data         address of the data buffer
+ * @param data_size    array size of the int buffer (total size / size of int)
+ *
+ * @return             int value 0 for success, -1 in case of error
+ */
+int i2s_transfer_tx_data(struct i2stx_info *pi2s_tx, unsigned *data,
+                               unsigned long data_size);
+
+/*
+ * Initialise i2s transmiter
+ *
+ * @param pi2s_tx      pointer of i2s transmitter parameter structure.
+ *
+ * @return             int value 0 for success, -1 in case of error
+ */
+int i2s_tx_init(struct i2stx_info *pi2s_tx);
+
+#endif /* __I2S_H__ */
index f54d98330634acb99c56c791d674c3cdb6816c70..b958b18a4de2fd8fc6e8638c90149f74ced088ad 100644 (file)
@@ -460,7 +460,6 @@ static inline void image_set_name(image_header_t *hdr, const char *name)
 int image_check_hcrc(const image_header_t *hdr);
 int image_check_dcrc(const image_header_t *hdr);
 #ifndef USE_HOSTCC
-int getenv_yesno(char *var);
 ulong getenv_bootm_low(void);
 phys_size_t getenv_bootm_size(void);
 phys_size_t getenv_bootm_mapsize(void);
index 2517d39d4144a5f3d760c9bcb53029b3460c4316..c24164a9de0c74cf4cfb910ed695b1c6aa71f42d 100644 (file)
@@ -57,6 +57,14 @@ extern void lcd_initcolregs (void);
 extern struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp);
 extern int bmp_display(ulong addr, int x, int y);
 
+/**
+ * Set whether we need to flush the dcache when changing the LCD image. This
+ * defaults to off.
+ *
+ * @param flush                non-zero to flush cache after update, 0 to skip
+ */
+void lcd_set_flush_dcache(int flush);
+
 #if defined CONFIG_MPC823
 /*
  * LCD controller stucture for MPC823 CPU
@@ -333,6 +341,9 @@ void lcd_position_cursor(unsigned col, unsigned row);
 /* Allow boards to customize the information displayed */
 void lcd_show_board_info(void);
 
+/* Return the size of the LCD frame buffer, and the line length */
+int lcd_get_size(int *line_length);
+
 /************************************************************************/
 /* ** BITMAP DISPLAY SUPPORT                                           */
 /************************************************************************/
diff --git a/include/ld9040.h b/include/ld9040.h
new file mode 100644 (file)
index 0000000..fe99390
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * ld9040 AMOLED LCD panel driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Donghwa Lee <dh09.lee@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
+ */
+
+#ifndef __LD9040_H_
+#define __LD9040_H_
+
+void ld9040_cfg_ldo(void);
+void ld9040_enable_ldo(unsigned int onoff);
+
+#endif /* __LD9040_H_ */
diff --git a/include/linux/linux_string.h b/include/linux/linux_string.h
new file mode 100644 (file)
index 0000000..192b4c9
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _LINUX_LINUX_STRING_H_
+#define _LINUX_LINUX_STRING_H_
+
+extern char * skip_spaces(const char *);
+
+extern char *strim(char *);
+
+#endif
index 9a8cbc24cdceeef5612dcdeca82fe788b3d33f56..e9b134d1428f43786bce85d8f7dc4a6fc72d1907 100644 (file)
@@ -38,8 +38,11 @@ extern int strcmp(const char *,const char *);
 #ifndef __HAVE_ARCH_STRNCMP
 extern int strncmp(const char *,const char *,__kernel_size_t);
 #endif
-#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */
-extern int strnicmp(const char *, const char *, __kernel_size_t);
+#ifndef __HAVE_ARCH_STRCASECMP
+int strcasecmp(const char *s1, const char *s2);
+#endif
+#ifndef __HAVE_ARCH_STRNCASECMP
+extern int strncasecmp(const char *s1, const char *s2, __kernel_size_t len);
 #endif
 #ifndef __HAVE_ARCH_STRCHR
 extern char * strchr(const char *,int);
@@ -47,10 +50,7 @@ extern char * strchr(const char *,int);
 #ifndef __HAVE_ARCH_STRRCHR
 extern char * strrchr(const char *,int);
 #endif
-extern char * skip_spaces(const char *);
-
-extern char *strim(char *);
-
+#include <linux/linux_string.h>
 #ifndef __HAVE_ARCH_STRSTR
 extern char * strstr(const char *,const char *);
 #endif
index 27ea283f1edc4e583c7d329f441f190f02e4b6f0..c58a734ada0196fce6c75af2a195f660c98f10b6 100644 (file)
@@ -176,10 +176,62 @@ int   test_part_amiga (block_dev_desc_t *dev_desc);
 #endif
 
 #ifdef CONFIG_EFI_PARTITION
+#include <part_efi.h>
 /* disk/part_efi.c */
 int get_partition_info_efi (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
 void print_part_efi (block_dev_desc_t *dev_desc);
 int   test_part_efi (block_dev_desc_t *dev_desc);
+
+/**
+ * write_gpt_table() - Write the GUID Partition Table to disk
+ *
+ * @param dev_desc - block device descriptor
+ * @param gpt_h - pointer to GPT header representation
+ * @param gpt_e - pointer to GPT partition table entries
+ *
+ * @return - zero on success, otherwise error
+ */
+int write_gpt_table(block_dev_desc_t *dev_desc,
+                 gpt_header *gpt_h, gpt_entry *gpt_e);
+
+/**
+ * gpt_fill_pte(): Fill the GPT partition table entry
+ *
+ * @param gpt_h - GPT header representation
+ * @param gpt_e - GPT partition table entries
+ * @param partitions - list of partitions
+ * @param parts - number of partitions
+ *
+ * @return zero on success
+ */
+int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
+               disk_partition_t *partitions, int parts);
+
+/**
+ * gpt_fill_header(): Fill the GPT header
+ *
+ * @param dev_desc - block device descriptor
+ * @param gpt_h - GPT header representation
+ * @param str_guid - disk guid string representation
+ * @param parts_count - number of partitions
+ *
+ * @return - error on str_guid conversion error
+ */
+int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h,
+               char *str_guid, int parts_count);
+
+/**
+ * gpt_restore(): Restore GPT partition table
+ *
+ * @param dev_desc - block device descriptor
+ * @param str_disk_guid - disk GUID
+ * @param partitions - list of partitions
+ * @param parts - number of partitions
+ *
+ * @return zero on success
+ */
+int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
+               disk_partition_t *partitions, const int parts_count);
 #endif
 
 #endif /* _PART_H */
similarity index 66%
rename from disk/part_efi.h
rename to include/part_efi.h
index 4e28d1dcb66c1e15d8b9b8f40b2ba9b61ca7c896..6de0a3258aa0e2257d452d429ec7cc9b4b9ee310 100644 (file)
@@ -29,6 +29,8 @@
  * http://developer.intel.com/technology/efi/efi.htm
 */
 
+#include <linux/compiler.h>
+
 #ifndef _DISK_PART_EFI_H
 #define _DISK_PART_EFI_H
 
@@ -41,6 +43,8 @@
 #define GPT_HEADER_REVISION_V1 0x00010000
 #define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL
 #define GPT_ENTRY_NAME "gpt"
+#define GPT_ENTRY_NUMBERS              128
+#define GPT_ENTRY_SIZE                 128
 
 #define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
        ((efi_guid_t) \
                0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
 
 /* linux/include/efi.h */
-typedef unsigned short efi_char16_t;
+typedef u16 efi_char16_t;
 
 typedef struct {
-       unsigned char b[16];
+       u8 b[16];
 } efi_guid_t;
 
 /* based on linux/include/genhd.h */
 struct partition {
-       unsigned char boot_ind;         /* 0x80 - active */
-       unsigned char head;             /* starting head */
-       unsigned char sector;           /* starting sector */
-       unsigned char cyl;              /* starting cylinder */
-       unsigned char sys_ind;          /* What partition type */
-       unsigned char end_head;         /* end head */
-       unsigned char end_sector;       /* end sector */
-       unsigned char end_cyl;          /* end cylinder */
-       unsigned char start_sect[4];    /* starting sector counting from 0 */
-       unsigned char nr_sects[4];      /* nr of sectors in partition */
-} __attribute__ ((packed));
+       u8 boot_ind;            /* 0x80 - active */
+       u8 head;                /* starting head */
+       u8 sector;              /* starting sector */
+       u8 cyl;                 /* starting cylinder */
+       u8 sys_ind;             /* What partition type */
+       u8 end_head;            /* end head */
+       u8 end_sector;          /* end sector */
+       u8 end_cyl;             /* end cylinder */
+       __le32 start_sect;      /* starting sector counting from 0 */
+       __le32 nr_sects;        /* nr of sectors in partition */
+} __packed;
 
 /* based on linux/fs/partitions/efi.h */
 typedef struct _gpt_header {
-       unsigned char signature[8];
-       unsigned char revision[4];
-       unsigned char header_size[4];
-       unsigned char header_crc32[4];
-       unsigned char reserved1[4];
-       unsigned char my_lba[8];
-       unsigned char alternate_lba[8];
-       unsigned char first_usable_lba[8];
-       unsigned char last_usable_lba[8];
+       __le64 signature;
+       __le32 revision;
+       __le32 header_size;
+       __le32 header_crc32;
+       __le32 reserved1;
+       __le64 my_lba;
+       __le64 alternate_lba;
+       __le64 first_usable_lba;
+       __le64 last_usable_lba;
        efi_guid_t disk_guid;
-       unsigned char partition_entry_lba[8];
-       unsigned char num_partition_entries[4];
-       unsigned char sizeof_partition_entry[4];
-       unsigned char partition_entry_array_crc32[4];
-       unsigned char reserved2[GPT_BLOCK_SIZE - 92];
-} __attribute__ ((packed)) gpt_header;
+       __le64 partition_entry_lba;
+       __le32 num_partition_entries;
+       __le32 sizeof_partition_entry;
+       __le32 partition_entry_array_crc32;
+       u8 reserved2[GPT_BLOCK_SIZE - 92];
+} __packed gpt_header;
 
 typedef union _gpt_entry_attributes {
        struct {
-               unsigned long long required_to_function:1;
-               unsigned long long no_block_io_protocol:1;
-               unsigned long long legacy_bios_bootable:1;
-               unsigned long long reserved:45;
-               unsigned long long type_guid_specific:16;
+               u64 required_to_function:1;
+               u64 no_block_io_protocol:1;
+               u64 legacy_bios_bootable:1;
+               u64 reserved:45;
+               u64 type_guid_specific:16;
        } fields;
        unsigned long long raw;
-} __attribute__ ((packed)) gpt_entry_attributes;
+} __packed gpt_entry_attributes;
 
 #define PARTNAME_SZ    (72 / sizeof(efi_char16_t))
 typedef struct _gpt_entry {
        efi_guid_t partition_type_guid;
        efi_guid_t unique_partition_guid;
-       unsigned char starting_lba[8];
-       unsigned char ending_lba[8];
+       __le64 starting_lba;
+       __le64 ending_lba;
        gpt_entry_attributes attributes;
        efi_char16_t partition_name[PARTNAME_SZ];
-}
-__attribute__ ((packed)) gpt_entry;
+} __packed gpt_entry;
 
 typedef struct _legacy_mbr {
-       unsigned char boot_code[440];
-       unsigned char unique_mbr_signature[4];
-       unsigned char unknown[2];
+       u8 boot_code[440];
+       __le32 unique_mbr_signature;
+       __le16 unknown;
        struct partition partition_record[4];
-       unsigned char signature[2];
-} __attribute__ ((packed)) legacy_mbr;
+       __le16 signature;
+} __packed legacy_mbr;
 
 #endif /* _DISK_PART_EFI_H */
diff --git a/include/power/max77686_pmic.h b/include/power/max77686_pmic.h
new file mode 100644 (file)
index 0000000..d949ace
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Rajeshwari Shinde <rajeshwari.s@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
+ */
+
+#ifndef __MAX77686_H_
+#define __MAX77686_H_
+
+enum {
+       MAX77686_REG_PMIC_ID            = 0x0,
+       MAX77686_REG_PMIC_INTSRC,
+       MAX77686_REG_PMIC_INT1,
+       MAX77686_REG_PMIC_INT2,
+       MAX77686_REG_PMIC_INT1MSK,
+       MAX77686_REG_PMIC_INT2MSK,
+
+       MAX77686_REG_PMIC_STATUS1,
+       MAX77686_REG_PMIC_STATUS2,
+
+       MAX77686_REG_PMIC_PWRON,
+       MAX77686_REG_PMIC_ONOFFDELAY,
+       MAX77686_REG_PMIC_MRSTB,
+
+       MAX77686_REG_PMIC_BUCK1CRTL     = 0x10,
+       MAX77686_REG_PMIC_BUCK1OUT,
+       MAX77686_REG_PMIC_BUCK2CTRL1,
+       MAX77686_REG_PMIC_BUCK234FREQ,
+       MAX77686_REG_PMIC_BUCK2DVS1,
+       MAX77686_REG_PMIC_BUCK2DVS2,
+       MAX77686_REG_PMIC_BUCK2DVS3,
+       MAX77686_REG_PMIC_BUCK2DVS4,
+       MAX77686_REG_PMIC_BUCK2DVS5,
+       MAX77686_REG_PMIC_BUCK2DVS6,
+       MAX77686_REG_PMIC_BUCK2DVS7,
+       MAX77686_REG_PMIC_BUCK2DVS8,
+       MAX77686_REG_PMIC_BUCK3CTRL,
+       MAX77686_REG_PMIC_BUCK3DVS1,
+       MAX77686_REG_PMIC_BUCK3DVS2,
+       MAX77686_REG_PMIC_BUCK3DVS3,
+       MAX77686_REG_PMIC_BUCK3DVS4,
+       MAX77686_REG_PMIC_BUCK3DVS5,
+       MAX77686_REG_PMIC_BUCK3DVS6,
+       MAX77686_REG_PMIC_BUCK3DVS7,
+       MAX77686_REG_PMIC_BUCK3DVS8,
+       MAX77686_REG_PMIC_BUCK4CTRL1,
+       MAX77686_REG_PMIC_BUCK4DVS1     = 0x28,
+       MAX77686_REG_PMIC_BUCK4DVS2,
+       MAX77686_REG_PMIC_BUCK4DVS3,
+       MAX77686_REG_PMIC_BUCK4DVS4,
+       MAX77686_REG_PMIC_BUCK4DVS5,
+       MAX77686_REG_PMIC_BUCK4DVS6,
+       MAX77686_REG_PMIC_BUCK4DVS7,
+       MAX77686_REG_PMIC_BUCK4DVS8,
+       MAX77686_REG_PMIC_BUCK5CTRL,
+       MAX77686_REG_PMIC_BUCK5OUT,
+       MAX77686_REG_PMIC_BUCK6CRTL,
+       MAX77686_REG_PMIC_BUCK6OUT,
+       MAX77686_REG_PMIC_BUCK7CRTL,
+       MAX77686_REG_PMIC_BUCK7OUT,
+       MAX77686_REG_PMIC_BUCK8CRTL,
+       MAX77686_REG_PMIC_BUCK8OUT,
+       MAX77686_REG_PMIC_BUCK9CRTL,
+       MAX77686_REG_PMIC_BUCK9OUT,
+
+       MAX77686_REG_PMIC_LDO1CTRL1     = 0x40,
+       MAX77686_REG_PMIC_LDO2CTRL1,
+       MAX77686_REG_PMIC_LDO3CTRL1,
+       MAX77686_REG_PMIC_LDO4CTRL1,
+       MAX77686_REG_PMIC_LDO5CTRL1,
+       MAX77686_REG_PMIC_LDO6CTRL1,
+       MAX77686_REG_PMIC_LDO7CTRL1,
+       MAX77686_REG_PMIC_LDO8CTRL1,
+       MAX77686_REG_PMIC_LDO9CTRL1,
+       MAX77686_REG_PMIC_LDO10CTRL1,
+       MAX77686_REG_PMIC_LDO11CTRL1,
+       MAX77686_REG_PMIC_LDO12CTRL1,
+       MAX77686_REG_PMIC_LDO13CTRL1,
+       MAX77686_REG_PMIC_LDO14CTRL1,
+       MAX77686_REG_PMIC_LDO15CTRL1,
+       MAX77686_REG_PMIC_LDO16CTRL1,
+       MAX77686_REG_PMIC_LDO17CTRL1,
+       MAX77686_REG_PMIC_LDO18CTRL1,
+       MAX77686_REG_PMIC_LDO19CTRL1,
+       MAX77686_REG_PMIC_LDO20CTRL1,
+       MAX77686_REG_PMIC_LDO21CTRL1,
+       MAX77686_REG_PMIC_LDO22CTRL1,
+       MAX77686_REG_PMIC_LDO23CTRL1,
+       MAX77686_REG_PMIC_LDO24CTRL1,
+       MAX77686_REG_PMIC_LDO25CTRL1,
+       MAX77686_REG_PMIC_LDO26CTRL1,
+       MAX77686_REG_PMIC_LDO1CTRL2,
+       MAX77686_REG_PMIC_LDO2CTRL2,
+       MAX77686_REG_PMIC_LDO3CTRL2,
+       MAX77686_REG_PMIC_LDO4CTRL2,
+       MAX77686_REG_PMIC_LDO5CTRL2,
+       MAX77686_REG_PMIC_LDO6CTRL2,
+       MAX77686_REG_PMIC_LDO7CTRL2,
+       MAX77686_REG_PMIC_LDO8CTRL2,
+       MAX77686_REG_PMIC_LDO9CTRL2,
+       MAX77686_REG_PMIC_LDO10CTRL2,
+       MAX77686_REG_PMIC_LDO11CTRL2,
+       MAX77686_REG_PMIC_LDO12CTRL2,
+       MAX77686_REG_PMIC_LDO13CTRL2,
+       MAX77686_REG_PMIC_LDO14CTRL2,
+       MAX77686_REG_PMIC_LDO15CTRL2,
+       MAX77686_REG_PMIC_LDO16CTRL2,
+       MAX77686_REG_PMIC_LDO17CTRL2,
+       MAX77686_REG_PMIC_LDO18CTRL2,
+       MAX77686_REG_PMIC_LDO19CTRL2,
+       MAX77686_REG_PMIC_LDO20CTRL2,
+       MAX77686_REG_PMIC_LDO21CTRL2,
+       MAX77686_REG_PMIC_LDO22CTRL2,
+       MAX77686_REG_PMIC_LDO23CTRL2,
+       MAX77686_REG_PMIC_LDO24CTRL2,
+       MAX77686_REG_PMIC_LDO25CTRL2,
+       MAX77686_REG_PMIC_LDO26CTRL2,
+
+       MAX77686_REG_PMIC_BBAT          = 0x7e,
+       MAX77686_REG_PMIC_32KHZ,
+
+       PMIC_NUM_OF_REGS,
+};
+
+/* I2C device address for pmic max77686 */
+#define MAX77686_I2C_ADDR (0x12 >> 1)
+
+enum {
+       REG_DISABLE = 0,
+       REG_ENABLE
+};
+
+enum {
+       LDO_OFF = 0,
+       LDO_ON,
+
+       DIS_LDO = (0x00 << 6),
+       EN_LDO = (0x3 << 6),
+};
+
+#endif /* __MAX77686_PMIC_H_ */
index ca21f882c29344aae475cc967fc55255619ad3fe..0e559f986aa92257e4aea2392c357c36c4e023cc 100644 (file)
@@ -76,7 +76,9 @@ enum {
 
 #define MAX8998_LDO3           (1 << 2)
 #define MAX8998_LDO4           (1 << 1)
+#define MAX8998_LDO7           (1 << 6)
 #define MAX8998_LDO8           (1 << 5)
+#define MAX8998_LDO17          (1 << 4)
 #define MAX8998_SAFEOUT1       (1 << 4)
 
 #define MAX8998_I2C_ADDR        (0xCC >> 1)
index 93e1cbc6d0bd6be5bcc6cecc36ddcee20d1e0e17..13d3be6291701a3170dbd3a15e873b6cc7378c82 100644 (file)
 
 #define __set_errno(val) do { errno = val; } while (0)
 
+enum env_op {
+       env_op_create,
+       env_op_delete,
+       env_op_overwrite,
+};
+
 /* Action which shall be performed in the call the hsearch.  */
 typedef enum {
        FIND,
@@ -41,6 +47,9 @@ typedef enum {
 typedef struct entry {
        const char *key;
        char *data;
+       int (*callback)(const char *name, const char *value, enum env_op op,
+               int flags);
+       int flags;
 } ENTRY;
 
 /* Opaque type for internal use.  */
@@ -59,21 +68,20 @@ struct hsearch_data {
        unsigned int filled;
 /*
  * Callback function which will check whether the given change for variable
- * "name" from "oldval" to "newval" may be applied or not, and possibly apply
- * such change.
+ * "item" to "newval" may be applied or not, and possibly apply such change.
  * When (flag & H_FORCE) is set, it shall not print out any error message and
  * shall force overwriting of write-once variables.
 .* Must return 0 for approval, 1 for denial.
  */
-       int (*apply)(const char *name, const char *oldval,
-                       const char *newval, int flag);
+       int (*change_ok)(const ENTRY *__item, const char *newval, enum env_op,
+               int flag);
 };
 
 /* Create a new hashing table which will at most contain NEL elements.  */
 extern int hcreate_r(size_t __nel, struct hsearch_data *__htab);
 
 /* Destroy current internal hashing table.  */
-extern void hdestroy_r(struct hsearch_data *__htab, int do_apply);
+extern void hdestroy_r(struct hsearch_data *__htab);
 
 /*
  * Search for entry matching ITEM.key in internal hash table.  If
@@ -82,7 +90,7 @@ extern void hdestroy_r(struct hsearch_data *__htab, int do_apply);
  * ITEM.data.
  * */
 extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
-                    struct hsearch_data *__htab);
+                    struct hsearch_data *__htab, int __flag);
 
 /*
  * Search for an entry matching `MATCH'.  Otherwise, Same semantics
@@ -99,10 +107,10 @@ extern int hstrstr_r(const char *__match, int __last_idx, ENTRY ** __retval,
 
 /* Search and delete entry matching ITEM.key in internal hash table. */
 extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
-                       int do_apply);
+                    int __flag);
 
 extern ssize_t hexport_r(struct hsearch_data *__htab,
-                    const char __sep, char **__resp, size_t __size,
+                    const char __sep, int __flag, char **__resp, size_t __size,
                     int argc, char * const argv[]);
 
 /*
@@ -113,10 +121,15 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
  */
 extern int himport_r(struct hsearch_data *__htab,
                     const char *__env, size_t __size, const char __sep,
-                    int __flag, int nvars, char * const vars[], int do_apply);
+                    int __flag, int nvars, char * const vars[]);
+
+/* Walk the whole table calling the callback on each element */
+extern int hwalk_r(struct hsearch_data *__htab, int (*callback)(ENTRY *));
 
-/* Flags for himport_r() */
-#define        H_NOCLEAR       (1 << 0) /* do not clear hash table before importing */
-#define        H_FORCE         (1 << 1) /* overwrite read-only/write-once variables */
+/* Flags for himport_r(), hexport_r(), hdelete_r(), and hsearch_r() */
+#define H_NOCLEAR      (1 << 0) /* do not clear hash table before importing */
+#define H_FORCE                (1 << 1) /* overwrite read-only/write-once variables */
+#define H_INTERACTIVE  (1 << 2) /* indicate that an import is user directed */
+#define H_HIDE_DOT     (1 << 3) /* don't print env vars that begin with '.' */
 
 #endif /* search.h */
index 734d1fb153dc7d448e7f08e9e54f44e033b184bc..da09dab9769af05a80c7f42c42e1f489fe32cb66 100644 (file)
@@ -59,7 +59,8 @@ void sha1_starts( sha1_context *ctx );
  * \param input    buffer holding the  data
  * \param ilen    length of the input data
  */
-void sha1_update( sha1_context *ctx, unsigned char *input, int ilen );
+void sha1_update(sha1_context *ctx, const unsigned char *input,
+                unsigned int ilen);
 
 /**
  * \brief         SHA-1 final digest
@@ -76,8 +77,8 @@ void sha1_finish( sha1_context *ctx, unsigned char output[20] );
  * \param ilen    length of the input data
  * \param output   SHA-1 checksum result
  */
-void sha1_csum( unsigned char *input, int ilen,
-               unsigned char output[20] );
+void sha1_csum(const unsigned char *input, unsigned int ilen,
+               unsigned char *output);
 
 /**
  * \brief         Output = SHA-1( input buffer ), with watchdog triggering
@@ -87,17 +88,8 @@ void sha1_csum( unsigned char *input, int ilen,
  * \param output   SHA-1 checksum result
  * \param chunk_sz watchdog triggering period (in bytes of input processed)
  */
-void sha1_csum_wd (unsigned char *input, int ilen,
-               unsigned char output[20], unsigned int chunk_sz);
-
-/**
- * \brief         Output = SHA-1( file contents )
- *
- * \param path    input file name
- * \param output   SHA-1 checksum result
- * \return        0 if successful, or 1 if fopen failed
- */
-int sha1_file( char *path, unsigned char output[20] );
+void sha1_csum_wd(const unsigned char *input, unsigned int ilen,
+               unsigned char *output, unsigned int chunk_sz);
 
 /**
  * \brief         Output = HMAC-SHA-1( input buffer, hmac key )
@@ -108,9 +100,9 @@ int sha1_file( char *path, unsigned char output[20] );
  * \param ilen    length of the input data
  * \param output   HMAC-SHA-1 result
  */
-void sha1_hmac( unsigned char *key, int keylen,
-               unsigned char *input, int ilen,
-               unsigned char output[20] );
+void sha1_hmac(const unsigned char *key, int keylen,
+               const unsigned char *input, unsigned int ilen,
+               unsigned char *output);
 
 /**
  * \brief         Checkup routine
index e38ea898c3e825c7c72c683a78bf328f764ff946..beadab35ffc445a6b7d19b41cc9dc85f095facdd 100644 (file)
@@ -3,6 +3,9 @@
 
 #define SHA256_SUM_LEN 32
 
+/* Reset watchdog each time we process this many bytes */
+#define CHUNKSZ_SHA256 (64 * 1024)
+
 typedef struct {
        uint32_t total[2];
        uint32_t state[8];
@@ -10,7 +13,10 @@ typedef struct {
 } sha256_context;
 
 void sha256_starts(sha256_context * ctx);
-void sha256_update(sha256_context * ctx, uint8_t * input, uint32_t length);
+void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length);
 void sha256_finish(sha256_context * ctx, uint8_t digest[SHA256_SUM_LEN]);
 
+void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
+               unsigned char *output, unsigned int chunk_sz);
+
 #endif /* _SHA256_H */
diff --git a/include/sound.h b/include/sound.h
new file mode 100644 (file)
index 0000000..ea0b115
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * R. Chandrasekar < rcsekar@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
+ */
+
+#ifndef __SOUND_H__
+#define __SOUND_H__
+
+/* sound codec enum */
+enum en_sound_codec {
+       CODEC_WM_8994,
+       CODEC_WM_8995,
+       CODEC_MAX
+};
+
+/* sound codec enum */
+enum sound_compat {
+       AUDIO_COMPAT_SPI,
+       AUDIO_COMPAT_I2C,
+};
+
+/* Codec information structure to store the info from device tree */
+struct sound_codec_info {
+       int i2c_bus;
+       int i2c_dev_addr;
+       enum en_sound_codec codec_type;
+};
+
+/*
+ * Initialises audio sub system
+ *
+ * @return     int value 0 for success, -1 for error
+ */
+int sound_init(void);
+
+/*
+ * plays the pcm data buffer in pcm_data.h through i2s1 to make the
+ * sine wave sound
+ *
+ * @return     int 0 for success, -1 for error
+ */
+int sound_play(uint32_t msec, uint32_t frequency);
+
+#endif  /* __SOUND__H__ */
index f83f6e8d8c50cf410632ba7f17635047355606c0..86ca1a6ec1db0b16e2c3a036ddf3ba977ed034e2 100644 (file)
@@ -69,6 +69,7 @@ endif
 COBJS-y += crc32.o
 COBJS-y += ctype.o
 COBJS-y += div64.o
+COBJS-y += linux_string.o
 COBJS-y += string.o
 COBJS-y += time.o
 COBJS-$(CONFIG_BOOTP_PXE) += uuid.o
index 348144aa705836f3f9ca2a6eb4e0ff7bd63f0d6e..6dba4389f23c231c9b9b34a330b7afeb753689b1 100644 (file)
@@ -43,6 +43,8 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
        COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"),
        COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
+       COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
+       COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
index 94a7b61717a8b9f0ecc6312c9dfda2130a6e6767..07ebfb218f8a6f152d915e448a2c2304a53b9f02 100644 (file)
@@ -54,7 +54,9 @@
 #define        CONFIG_ENV_MAX_ENTRIES 512
 #endif
 
-#include "search.h"
+#include <env_callback.h>
+#include <env_flags.h>
+#include <search.h>
 
 /*
  * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
  * Instead the interface of all functions is extended to take an argument
  * which describes the current status.
  */
+
 typedef struct _ENTRY {
        int used;
        ENTRY entry;
 } _ENTRY;
 
 
+static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
+       int idx);
+
 /*
  * hcreate()
  */
@@ -142,7 +148,7 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
  * be freed and the local static variable can be marked as not used.
  */
 
-void hdestroy_r(struct hsearch_data *htab, int do_apply)
+void hdestroy_r(struct hsearch_data *htab)
 {
        int i;
 
@@ -156,10 +162,7 @@ void hdestroy_r(struct hsearch_data *htab, int do_apply)
        for (i = 1; i <= htab->size; ++i) {
                if (htab->table[i].used > 0) {
                        ENTRY *ep = &htab->table[i].entry;
-                       if (do_apply && htab->apply != NULL) {
-                               /* deletion is always forced */
-                               htab->apply(ep->key, ep->data, NULL, H_FORCE);
-                       }
+
                        free((void *)ep->key);
                        free(ep->data);
                }
@@ -250,14 +253,65 @@ int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
        return 0;
 }
 
+/*
+ * Compare an existing entry with the desired key, and overwrite if the action
+ * is ENTER.  This is simply a helper function for hsearch_r().
+ */
+static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
+       ENTRY **retval, struct hsearch_data *htab, int flag,
+       unsigned int hval, unsigned int idx)
+{
+       if (htab->table[idx].used == hval
+           && strcmp(item.key, htab->table[idx].entry.key) == 0) {
+               /* Overwrite existing value? */
+               if ((action == ENTER) && (item.data != NULL)) {
+                       /* check for permission */
+                       if (htab->change_ok != NULL && htab->change_ok(
+                           &htab->table[idx].entry, item.data,
+                           env_op_overwrite, flag)) {
+                               debug("change_ok() rejected setting variable "
+                                       "%s, skipping it!\n", item.key);
+                               __set_errno(EPERM);
+                               *retval = NULL;
+                               return 0;
+                       }
+
+                       /* If there is a callback, call it */
+                       if (htab->table[idx].entry.callback &&
+                           htab->table[idx].entry.callback(item.key,
+                           item.data, env_op_overwrite, flag)) {
+                               debug("callback() rejected setting variable "
+                                       "%s, skipping it!\n", item.key);
+                               __set_errno(EINVAL);
+                               *retval = NULL;
+                               return 0;
+                       }
+
+                       free(htab->table[idx].entry.data);
+                       htab->table[idx].entry.data = strdup(item.data);
+                       if (!htab->table[idx].entry.data) {
+                               __set_errno(ENOMEM);
+                               *retval = NULL;
+                               return 0;
+                       }
+               }
+               /* return found entry */
+               *retval = &htab->table[idx].entry;
+               return idx;
+       }
+       /* keep searching */
+       return -1;
+}
+
 int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
-             struct hsearch_data *htab)
+             struct hsearch_data *htab, int flag)
 {
        unsigned int hval;
        unsigned int count;
        unsigned int len = strlen(item.key);
        unsigned int idx;
        unsigned int first_deleted = 0;
+       int ret;
 
        /* Compute an value for the given string. Perhaps use a better method. */
        hval = len;
@@ -289,23 +343,10 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
                    && !first_deleted)
                        first_deleted = idx;
 
-               if (htab->table[idx].used == hval
-                   && strcmp(item.key, htab->table[idx].entry.key) == 0) {
-                       /* Overwrite existing value? */
-                       if ((action == ENTER) && (item.data != NULL)) {
-                               free(htab->table[idx].entry.data);
-                               htab->table[idx].entry.data =
-                                       strdup(item.data);
-                               if (!htab->table[idx].entry.data) {
-                                       __set_errno(ENOMEM);
-                                       *retval = NULL;
-                                       return 0;
-                               }
-                       }
-                       /* return found entry */
-                       *retval = &htab->table[idx].entry;
-                       return idx;
-               }
+               ret = _compare_and_overwrite_entry(item, action, retval, htab,
+                       flag, hval, idx);
+               if (ret != -1)
+                       return ret;
 
                /*
                 * Second hash function:
@@ -331,23 +372,10 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
                                break;
 
                        /* If entry is found use it. */
-                       if ((htab->table[idx].used == hval)
-                           && strcmp(item.key, htab->table[idx].entry.key) == 0) {
-                               /* Overwrite existing value? */
-                               if ((action == ENTER) && (item.data != NULL)) {
-                                       free(htab->table[idx].entry.data);
-                                       htab->table[idx].entry.data =
-                                               strdup(item.data);
-                                       if (!htab->table[idx].entry.data) {
-                                               __set_errno(ENOMEM);
-                                               *retval = NULL;
-                                               return 0;
-                                       }
-                               }
-                               /* return found entry */
-                               *retval = &htab->table[idx].entry;
-                               return idx;
-                       }
+                       ret = _compare_and_overwrite_entry(item, action, retval,
+                               htab, flag, hval, idx);
+                       if (ret != -1)
+                               return ret;
                }
                while (htab->table[idx].used);
        }
@@ -383,6 +411,34 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 
                ++htab->filled;
 
+               /* This is a new entry, so look up a possible callback */
+               env_callback_init(&htab->table[idx].entry);
+               /* Also look for flags */
+               env_flags_init(&htab->table[idx].entry);
+
+               /* check for permission */
+               if (htab->change_ok != NULL && htab->change_ok(
+                   &htab->table[idx].entry, item.data, env_op_create, flag)) {
+                       debug("change_ok() rejected setting variable "
+                               "%s, skipping it!\n", item.key);
+                       _hdelete(item.key, htab, &htab->table[idx].entry, idx);
+                       __set_errno(EPERM);
+                       *retval = NULL;
+                       return 0;
+               }
+
+               /* If there is a callback, call it */
+               if (htab->table[idx].entry.callback &&
+                   htab->table[idx].entry.callback(item.key, item.data,
+                   env_op_create, flag)) {
+                       debug("callback() rejected setting variable "
+                               "%s, skipping it!\n", item.key);
+                       _hdelete(item.key, htab, &htab->table[idx].entry, idx);
+                       __set_errno(EINVAL);
+                       *retval = NULL;
+                       return 0;
+               }
+
                /* return new entry */
                *retval = &htab->table[idx].entry;
                return 1;
@@ -404,7 +460,21 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
  * do that.
  */
 
-int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)
+static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
+       int idx)
+{
+       /* free used ENTRY */
+       debug("hdelete: DELETING key \"%s\"\n", key);
+       free((void *)ep->key);
+       free(ep->data);
+       ep->callback = NULL;
+       ep->flags = 0;
+       htab->table[idx].used = -1;
+
+       --htab->filled;
+}
+
+int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
 {
        ENTRY e, *ep;
        int idx;
@@ -413,20 +483,31 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)
 
        e.key = (char *)key;
 
-       if ((idx = hsearch_r(e, FIND, &ep, htab)) == 0) {
+       idx = hsearch_r(e, FIND, &ep, htab, 0);
+       if (idx == 0) {
                __set_errno(ESRCH);
                return 0;       /* not found */
        }
 
-       /* free used ENTRY */
-       debug("hdelete: DELETING key \"%s\"\n", key);
-       if (do_apply && htab->apply != NULL)
-               htab->apply(ep->key, ep->data, NULL, H_FORCE);
-       free((void *)ep->key);
-       free(ep->data);
-       htab->table[idx].used = -1;
+       /* Check for permission */
+       if (htab->change_ok != NULL &&
+           htab->change_ok(ep, NULL, env_op_delete, flag)) {
+               debug("change_ok() rejected deleting variable "
+                       "%s, skipping it!\n", key);
+               __set_errno(EPERM);
+               return 0;
+       }
 
-       --htab->filled;
+       /* If there is a callback, call it */
+       if (htab->table[idx].entry.callback &&
+           htab->table[idx].entry.callback(key, NULL, env_op_delete, flag)) {
+               debug("callback() rejected deleting variable "
+                       "%s, skipping it!\n", key);
+               __set_errno(EINVAL);
+               return 0;
+       }
+
+       _hdelete(key, htab, ep, idx);
 
        return 1;
 }
@@ -482,7 +563,7 @@ static int cmpkey(const void *p1, const void *p2)
        return (strcmp(e1->key, e2->key));
 }
 
-ssize_t hexport_r(struct hsearch_data *htab, const char sep,
+ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
                 char **resp, size_t size,
                 int argc, char * const argv[])
 {
@@ -519,6 +600,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
                        if ((argc > 0) && (found == 0))
                                continue;
 
+                       if ((flag & H_HIDE_DOT) && ep->key[0] == '.')
+                               continue;
+
                        list[n++] = ep;
 
                        totlen += strlen(ep->key) + 2;
@@ -674,7 +758,7 @@ static int drop_var_from_set(const char *name, int nvars, char * vars[])
 
 int himport_r(struct hsearch_data *htab,
                const char *env, size_t size, const char sep, int flag,
-               int nvars, char * const vars[], int do_apply)
+               int nvars, char * const vars[])
 {
        char *data, *sp, *dp, *name, *value;
        char *localvars[nvars];
@@ -704,7 +788,7 @@ int himport_r(struct hsearch_data *htab,
                debug("Destroy Hash Table: %p table = %p\n", htab,
                       htab->table);
                if (htab->table)
-                       hdestroy_r(htab, do_apply);
+                       hdestroy_r(htab);
        }
 
        /*
@@ -770,7 +854,7 @@ int himport_r(struct hsearch_data *htab,
                        if (!drop_var_from_set(name, nvars, localvars))
                                continue;
 
-                       if (hdelete_r(name, htab, do_apply) == 0)
+                       if (hdelete_r(name, htab, flag) == 0)
                                debug("DELETE ERROR ##############################\n");
 
                        continue;
@@ -794,30 +878,10 @@ int himport_r(struct hsearch_data *htab,
                e.key = name;
                e.data = value;
 
-               /* if there is an apply function, check what it has to say */
-               if (do_apply && htab->apply != NULL) {
-                       debug("searching before calling cb function"
-                               " for  %s\n", name);
-                       /*
-                        * Search for variable in existing env, so to pass
-                        * its previous value to the apply callback
-                        */
-                       hsearch_r(e, FIND, &rv, htab);
-                       debug("previous value was %s\n", rv ? rv->data : "");
-                       if (htab->apply(name, rv ? rv->data : NULL,
-                               value, flag)) {
-                               debug("callback function refused to set"
-                                       " variable %s, skipping it!\n", name);
-                               continue;
-                       }
-               }
-
-               hsearch_r(e, ENTER, &rv, htab);
-               if (rv == NULL) {
+               hsearch_r(e, ENTER, &rv, htab, flag);
+               if (rv == NULL)
                        printf("himport_r: can't insert \"%s=%s\" into hash table\n",
                                name, value);
-                       return 0;
-               }
 
                debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
                        htab, htab->filled, htab->size,
@@ -839,7 +903,7 @@ int himport_r(struct hsearch_data *htab,
                 * b) if the variable was not present in current env, we notify
                 *    it might be a typo
                 */
-               if (hdelete_r(localvars[i], htab, do_apply) == 0)
+               if (hdelete_r(localvars[i], htab, flag) == 0)
                        printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);
                else
                        printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
@@ -848,3 +912,27 @@ int himport_r(struct hsearch_data *htab,
        debug("INSERT: done\n");
        return 1;               /* everything OK */
 }
+
+/*
+ * hwalk_r()
+ */
+
+/*
+ * Walk all of the entries in the hash, calling the callback for each one.
+ * this allows some generic operation to be performed on each element.
+ */
+int hwalk_r(struct hsearch_data *htab, int (*callback)(ENTRY *))
+{
+       int i;
+       int retval;
+
+       for (i = 1; i <= htab->size; ++i) {
+               if (htab->table[i].used > 0) {
+                       retval = callback(&htab->table[i].entry);
+                       if (retval)
+                               return retval;
+               }
+       }
+
+       return 0;
+}
diff --git a/lib/linux_string.c b/lib/linux_string.c
new file mode 100644 (file)
index 0000000..d5a5e08
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#ifdef USE_HOSTCC
+#include <stdio.h>
+#endif
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+
+/**
+ * skip_spaces - Removes leading whitespace from @str.
+ * @str: The string to be stripped.
+ *
+ * Returns a pointer to the first non-whitespace character in @str.
+ */
+char *skip_spaces(const char *str)
+{
+       while (isspace(*str))
+               ++str;
+       return (char *)str;
+}
+
+/**
+ * strim - Removes leading and trailing whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Note that the first trailing whitespace is replaced with a %NUL-terminator
+ * in the given string @s. Returns a pointer to the first non-whitespace
+ * character in @s.
+ */
+char *strim(char *s)
+{
+       size_t size;
+       char *end;
+
+       s = skip_spaces(s);
+       size = strlen(s);
+       if (!size)
+               return s;
+
+       end = s + size - 1;
+       while (end >= s && isspace(*end))
+               end--;
+       *(end + 1) = '\0';
+
+       return s;
+}
index da5bc16f3c65def17421c4042431ad500aa5111c..a121224855f4786f9ca92de5396bd1262301c6bc 100644 (file)
@@ -73,7 +73,7 @@ void sha1_starts (sha1_context * ctx)
        ctx->state[4] = 0xC3D2E1F0;
 }
 
-static void sha1_process (sha1_context * ctx, unsigned char data[64])
+static void sha1_process(sha1_context *ctx, const unsigned char data[64])
 {
        unsigned long temp, W[16], A, B, C, D, E;
 
@@ -230,7 +230,8 @@ static void sha1_process (sha1_context * ctx, unsigned char data[64])
 /*
  * SHA-1 process buffer
  */
-void sha1_update (sha1_context * ctx, unsigned char *input, int ilen)
+void sha1_update(sha1_context *ctx, const unsigned char *input,
+                unsigned int ilen)
 {
        int fill;
        unsigned long left;
@@ -305,7 +306,8 @@ void sha1_finish (sha1_context * ctx, unsigned char output[20])
 /*
  * Output = SHA-1( input buffer )
  */
-void sha1_csum (unsigned char *input, int ilen, unsigned char output[20])
+void sha1_csum(const unsigned char *input, unsigned int ilen,
+              unsigned char *output)
 {
        sha1_context ctx;
 
@@ -318,12 +320,12 @@ void sha1_csum (unsigned char *input, int ilen, unsigned char output[20])
  * Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz'
  * bytes of input processed.
  */
-void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20],
-                       unsigned int chunk_sz)
+void sha1_csum_wd(const unsigned char *input, unsigned int ilen,
+                 unsigned char *output, unsigned int chunk_sz)
 {
        sha1_context ctx;
 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
-       unsigned char *end, *curr;
+       const unsigned char *end, *curr;
        int chunk;
 #endif
 
@@ -350,8 +352,9 @@ void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20],
 /*
  * Output = HMAC-SHA-1( input buffer, hmac key )
  */
-void sha1_hmac (unsigned char *key, int keylen,
-               unsigned char *input, int ilen, unsigned char output[20])
+void sha1_hmac(const unsigned char *key, int keylen,
+              const unsigned char *input, unsigned int ilen,
+              unsigned char *output)
 {
        int i;
        sha1_context ctx;
index deb63a40b6d7218145e807850ff51cce488a7e4b..ab2db4890ae7eb4bc432320bb2a044a0d56aa518 100644 (file)
@@ -60,7 +60,7 @@ void sha256_starts(sha256_context * ctx)
        ctx->state[7] = 0x5BE0CD19;
 }
 
-void sha256_process(sha256_context * ctx, uint8_t data[64])
+static void sha256_process(sha256_context *ctx, const uint8_t data[64])
 {
        uint32_t temp1, temp2;
        uint32_t W[64];
@@ -191,7 +191,7 @@ void sha256_process(sha256_context * ctx, uint8_t data[64])
        ctx->state[7] += H;
 }
 
-void sha256_update(sha256_context * ctx, uint8_t * input, uint32_t length)
+void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
 {
        uint32_t left, fill;
 
@@ -260,3 +260,36 @@ void sha256_finish(sha256_context * ctx, uint8_t digest[32])
        PUT_UINT32_BE(ctx->state[6], digest, 24);
        PUT_UINT32_BE(ctx->state[7], digest, 28);
 }
+
+/*
+ * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz'
+ * bytes of input processed.
+ */
+void sha256_csum_wd(const unsigned char *input, unsigned int ilen,
+               unsigned char *output, unsigned int chunk_sz)
+{
+       sha256_context ctx;
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+       unsigned char *end, *curr;
+       int chunk;
+#endif
+
+       sha256_starts(&ctx);
+
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+       curr = input;
+       end = input + ilen;
+       while (curr < end) {
+               chunk = end - curr;
+               if (chunk > chunk_sz)
+                       chunk = chunk_sz;
+               sha256_update(&ctx, curr, chunk);
+               curr += chunk;
+               WATCHDOG_RESET();
+       }
+#else
+       sha256_update(&ctx, input, ilen);
+#endif
+
+       sha256_finish(&ctx, output);
+}
index c3ad055e2caeca752ba4238f65578edb0abfb814..09dfae03c247554deb48c29ce98693ffd9c25f9d 100644 (file)
 #include <malloc.h>
 
 
-#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */
 /**
- * strnicmp - Case insensitive, length-limited string comparison
+ * strncasecmp - Case insensitive, length-limited string comparison
  * @s1: One string
  * @s2: The other string
  * @len: the maximum number of characters to compare
  */
-int strnicmp(const char *s1, const char *s2, size_t len)
+int strncasecmp(const char *s1, const char *s2, size_t len)
 {
        /* Yes, Virginia, it had better be unsigned */
        unsigned char c1, c2;
@@ -52,7 +51,16 @@ int strnicmp(const char *s1, const char *s2, size_t len)
        }
        return (int)c1 - (int)c2;
 }
-#endif
+
+/**
+ * strcasecmp - Case insensitive string comparison
+ * @s1: One string
+ * @s2: The other string
+ */
+int strcasecmp(const char *s1, const char *s2)
+{
+       return strncasecmp(s1, s2, -1U);
+}
 
 char * ___strtok;
 
@@ -214,45 +222,6 @@ char * strrchr(const char * s, int c)
 }
 #endif
 
-
-/**
- * skip_spaces - Removes leading whitespace from @str.
- * @str: The string to be stripped.
- *
- * Returns a pointer to the first non-whitespace character in @str.
- */
-char *skip_spaces(const char *str)
-{
-       while (isspace(*str))
-               ++str;
-       return (char *)str;
-}
-
-/**
- * strim - Removes leading and trailing whitespace from @s.
- * @s: The string to be stripped.
- *
- * Note that the first trailing whitespace is replaced with a %NUL-terminator
- * in the given string @s. Returns a pointer to the first non-whitespace
- * character in @s.
- */
-char *strim(char *s)
-{
-       size_t size;
-       char *end;
-
-       s = skip_spaces(s);
-       size = strlen(s);
-       if (!size)
-               return s;
-
-       end = s + size - 1;
-       while (end >= s && isspace(*end))
-               end--;
-       *(end + 1) = '\0';
-
-       return s;
-}
 #ifndef __HAVE_ARCH_STRLEN
 /**
  * strlen - Find the length of a string
index b7a79c0e0c90ea6a5bd275a4bdf0fd3853c5d610..3c432f8764fb7cf679e4e7260247eee6d9938853 100644 (file)
@@ -103,7 +103,7 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)
        return simple_strtoul(cp, endp, base);
 }
 
-int ustrtoul(const char *cp, char **endp, unsigned int base)
+unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)
 {
        unsigned long result = simple_strtoul(cp, endp, base);
        switch (**endp) {
index d52f13adb45deca75d52cabaaecc592963b2ca5f..1ba796ebdf949999f8663ff30049c1c085d43f56 100644 (file)
@@ -103,7 +103,7 @@ static void configure_wait(void)
 void link_local_start(void)
 {
        ip = getenv_IPaddr("llipaddr");
-       if (ip != 0 && (ip & IN_CLASSB_NET) != LINKLOCAL_ADDR) {
+       if (ip != 0 && (ntohl(ip) & IN_CLASSB_NET) != LINKLOCAL_ADDR) {
                puts("invalid link address");
                net_set_state(NETLOOP_FAIL);
                return;
index 82c4cc91179a547f14887c8d1f5e1cf13f84a5af..a40cde1e94e46367d727e30d40187b2630f60f15 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -82,6 +82,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <environment.h>
 #include <net.h>
 #if defined(CONFIG_STATUS_LED)
 #include <miiphy.h>
@@ -208,32 +209,46 @@ static int NetTryCount;
 
 /**********************************************************************/
 
+static int on_bootfile(const char *name, const char *value, enum env_op op,
+       int flags)
+{
+       switch (op) {
+       case env_op_create:
+       case env_op_overwrite:
+               copy_filename(BootFile, value, sizeof(BootFile));
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+U_BOOT_ENV_CALLBACK(bootfile, on_bootfile);
+
 /*
  * Check if autoload is enabled. If so, use either NFS or TFTP to download
  * the boot file.
  */
 void net_auto_load(void)
 {
+#if defined(CONFIG_CMD_NFS)
        const char *s = getenv("autoload");
 
-       if (s != NULL) {
-               if (*s == 'n') {
-                       /*
-                        * Just use BOOTP/RARP to configure system;
-                        * Do not use TFTP to load the bootfile.
-                        */
-                       net_set_state(NETLOOP_SUCCESS);
-                       return;
-               }
-#if defined(CONFIG_CMD_NFS)
-               if (strcmp(s, "NFS") == 0) {
-                       /*
-                        * Use NFS to load the bootfile.
-                        */
-                       NfsStart();
-                       return;
-               }
+       if (s != NULL && strcmp(s, "NFS") == 0) {
+               /*
+                * Use NFS to load the bootfile.
+                */
+               NfsStart();
+               return;
+       }
 #endif
+       if (getenv_yesno("autoload") == 0) {
+               /*
+                * Just use BOOTP/RARP to configure system;
+                * Do not use TFTP to load the bootfile.
+                */
+               net_set_state(NETLOOP_SUCCESS);
+               return;
        }
        TftpStart(TFTPGET);
 }
index 59a8ebb3cf339b3c40ff24846c13406e5dc0b9a4..09790eb7cf8202c051d594b5243aa3f843746691 100644 (file)
@@ -40,6 +40,7 @@
 
 static ulong TftpTimeoutMSecs = TIMEOUT;
 static int TftpTimeoutCountMax = TIMEOUT_COUNT;
+static ulong time_start;   /* Record time we started tftp */
 
 /*
  * These globals govern the timeout behavior when attempting a connection to a
@@ -299,6 +300,12 @@ static void tftp_complete(void)
                TftpNumchars++;
        }
 #endif
+       time_start = get_timer(time_start);
+       if (time_start > 0) {
+               puts("\n\t ");  /* Line up with "Loading: " */
+               print_size(NetBootFileXferSize /
+                       time_start * 1000, "/s");
+       }
        puts("\ndone\n");
        net_set_state(NETLOOP_SUCCESS);
 }
@@ -775,6 +782,7 @@ void TftpStart(enum proto_t protocol)
                TftpState = STATE_SEND_RRQ;
        }
 
+       time_start = get_timer(0);
        TftpTimeoutCountMax = TftpRRQTimeoutCountMax;
 
        NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
index ab73c8c744b6401c4eb88b1e5083fbfc8794ce35..0e798e09403168d67abc327432f39fcecd5c7b26 100644 (file)
 include $(TOPDIR)/config.mk
 
 HOSTSRCS := $(SRCTREE)/lib/crc32.c  fw_env.c  fw_env_main.c
+HOSTSRCS += $(SRCTREE)/lib/ctype.c $(SRCTREE)/lib/linux_string.c
+HOSTSRCS += $(SRCTREE)/common/env_attr.c $(SRCTREE)/common/env_flags.c
 HEADERS        := fw_env.h $(OBJTREE)/include/config.h
 
 # Compile for a hosted environment on the target
 HOSTCPPFLAGS  = -idirafter $(SRCTREE)/include \
                -idirafter $(OBJTREE)/include2 \
                -idirafter $(OBJTREE)/include \
+               -idirafter $(SRCTREE)/tools/env \
                -DUSE_HOSTCC \
                -DTEXT_BASE=$(TEXT_BASE)
 
index 9b023e807bc446bebf10caf2864d92dbed8469b3..90c7a5d3f39fa37f76005f354976e8f9c8c1270e 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 #include <errno.h>
+#include <env_flags.h>
 #include <fcntl.h>
 #include <linux/stringify.h>
 #include <stdio.h>
@@ -180,6 +181,32 @@ char *fw_getenv (char *name)
        return NULL;
 }
 
+/*
+ * Search the default environment for a variable.
+ * Return the value, if found, or NULL, if not found.
+ */
+char *fw_getdefenv(char *name)
+{
+       char *env, *nxt;
+
+       for (env = default_environment; *env; env = nxt + 1) {
+               char *val;
+
+               for (nxt = env; *nxt; ++nxt) {
+                       if (nxt >= &default_environment[ENV_SIZE]) {
+                               fprintf(stderr, "## Error: "
+                                       "default environment not terminated\n");
+                               return NULL;
+                       }
+               }
+               val = envmatch(name, env);
+               if (!val)
+                       continue;
+               return val;
+       }
+       return NULL;
+}
+
 /*
  * Print the current definition of one, or more, or all
  * environment variables
@@ -281,6 +308,7 @@ int fw_env_write(char *name, char *value)
        int len;
        char *env, *nxt;
        char *oldval = NULL;
+       int deleting, creating, overwriting;
 
        /*
         * search if variable with this name already exists
@@ -298,27 +326,49 @@ int fw_env_write(char *name, char *value)
                        break;
        }
 
-       /*
-        * Delete any existing definition
-        */
-       if (oldval) {
-#ifndef CONFIG_ENV_OVERWRITE
-               /*
-                * Ethernet Address and serial# can be set only once
-                */
-               if (
-                   (strcmp(name, "serial#") == 0) ||
-                   ((strcmp(name, "ethaddr") == 0)
-#if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
-                   && (strcmp(oldval, __stringify(CONFIG_ETHADDR)) != 0)
-#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
-                  ) ) {
-                       fprintf (stderr, "Can't overwrite \"%s\"\n", name);
+       deleting = (oldval && !(value && strlen(value)));
+       creating = (!oldval && (value && strlen(value)));
+       overwriting = (oldval && (value && strlen(value)));
+
+       /* check for permission */
+       if (deleting) {
+               if (env_flags_validate_varaccess(name,
+                   ENV_FLAGS_VARACCESS_PREVENT_DELETE)) {
+                       printf("Can't delete \"%s\"\n", name);
+                       errno = EROFS;
+                       return -1;
+               }
+       } else if (overwriting) {
+               if (env_flags_validate_varaccess(name,
+                   ENV_FLAGS_VARACCESS_PREVENT_OVERWR)) {
+                       printf("Can't overwrite \"%s\"\n", name);
+                       errno = EROFS;
+                       return -1;
+               } else if (env_flags_validate_varaccess(name,
+                   ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR)) {
+                       const char *defval = fw_getdefenv(name);
+
+                       if (defval == NULL)
+                               defval = "";
+                       if (strcmp(oldval, defval)
+                           != 0) {
+                               printf("Can't overwrite \"%s\"\n", name);
+                               errno = EROFS;
+                               return -1;
+                       }
+               }
+       } else if (creating) {
+               if (env_flags_validate_varaccess(name,
+                   ENV_FLAGS_VARACCESS_PREVENT_CREATE)) {
+                       printf("Can't create \"%s\"\n", name);
                        errno = EROFS;
                        return -1;
                }
-#endif /* CONFIG_ENV_OVERWRITE */
+       } else
+               /* Nothing to do */
+               return 0;
 
+       if (deleting || overwriting) {
                if (*++nxt == '\0') {
                        *env = '\0';
                } else {
@@ -395,6 +445,9 @@ int fw_setenv(int argc, char *argv[])
 
        name = argv[1];
 
+       if (env_flags_validate_env_set_params(argc, argv) < 0)
+               return 1;
+
        len = 0;
        for (i = 2; i < argc; ++i) {
                char *val = argv[i];
@@ -516,6 +569,11 @@ int fw_parse_script(char *fname)
                        name, val ? val : " removed");
 #endif
 
+               if (env_flags_validate_type(name, val) < 0) {
+                       ret = -1;
+                       break;
+               }
+
                /*
                 * If there is an error setting a variable,
                 * try to save the environment and returns an error
index ef9ffeeec599a9e04cb5d73c02f18d07825a94bb..76bbba125a84f03421502f4159e5e99673671a31 100644 (file)
@@ -80,7 +80,7 @@ static int fit_handle_file (struct mkimage_params *params)
        }
        sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX);
 
-       /* dtc -I dts -O -p 200 datafile > tmpfile */
+       /* 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);