Merge branch 'master' of git://git.denx.de/u-boot-arm
authorTom Rini <trini@ti.com>
Tue, 8 Oct 2013 13:51:48 +0000 (09:51 -0400)
committerTom Rini <trini@ti.com>
Tue, 8 Oct 2013 13:51:48 +0000 (09:51 -0400)
167 files changed:
Licenses/README
Makefile
README
arch/arm/cpu/arm926ejs/at91/eflash.c
arch/arm/cpu/arm926ejs/kirkwood/cpu.c
arch/arm/cpu/armv7/at91/sama5d3_devices.c
arch/arm/cpu/armv7/exynos/clock.c
arch/arm/cpu/armv7/exynos/pinmux.c
arch/arm/cpu/armv7/nonsec_virt.S
arch/arm/cpu/armv7/omap5/hw_data.c
arch/arm/cpu/armv7/omap5/prcm-regs.c
arch/arm/cpu/armv7/virt-v7.c
arch/arm/dts/exynos5250.dtsi
arch/arm/include/asm/arch-at91/at91_common.h
arch/arm/include/asm/arch-at91/atmel_usba_udc.h [new file with mode: 0644]
arch/arm/include/asm/arch-at91/sama5d3.h
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/i2s-regs.h
arch/arm/include/asm/arch-exynos/periph.h
arch/arm/include/asm/arch-exynos/spi.h
arch/arm/include/asm/arch-omap5/ehci.h
arch/arm/include/asm/arch-omap5/omap.h
arch/arm/include/asm/arch-omap5/spl.h
arch/arm/include/asm/omap_common.h
arch/powerpc/cpu/mpc85xx/cmd_errata.c
arch/powerpc/cpu/mpc85xx/start.S
arch/powerpc/cpu/ppc4xx/4xx_pci.c
arch/powerpc/cpu/ppc4xx/4xx_uart.c
arch/powerpc/cpu/ppc4xx/miiphy.c
arch/powerpc/cpu/ppc4xx/start.S
arch/powerpc/include/asm/config_mpc85xx.h
arch/powerpc/include/asm/ppc405.h
arch/powerpc/include/asm/ppc440.h
arch/powerpc/include/asm/ppc4xx-emac.h
arch/powerpc/include/asm/ppc4xx-mal.h
arch/powerpc/include/asm/ppc4xx.h
board/RPXlite_dw/README
board/atmel/sama5d3xek/sama5d3xek.c
board/cray/L1/init.S
board/csb272/init.S
board/csb472/init.S
board/esd/pci405/writeibm.S
board/freescale/mx28evk/README
board/jse/init.S
board/mpl/common/pci.c
board/mpl/mip405/init.S
board/mpl/pip405/init.S
board/samsung/dts/exynos5250-smdk5250.dts
board/samsung/dts/exynos5250-snow.dts
board/sbc8349/README
board/sc3/init.S
board/ti/dra7xx/mux_data.h
board/w7o/init.S
boards.cfg
common/cmd_bootm.c
common/cmd_dfu.c
common/cmd_ext2.c
common/cmd_ext4.c
common/cmd_fat.c
common/cmd_fs.c
common/cmd_gpt.c
common/cmd_mmc.c
common/cmd_mtdparts.c
common/cmd_pxe.c
common/cmd_sf.c
common/cmd_usb_mass_storage.c
common/image-fdt.c
common/image-fit.c
common/image.c
common/spl/spl_mmc.c
disk/part_efi.c
doc/README.JFFS2_NAND
doc/README.hwconfig
doc/SPI/README.ti_qspi_dra_test [new file with mode: 0644]
doc/SPI/README.ti_qspi_flash [new file with mode: 0644]
doc/SPI/status.txt [new file with mode: 0644]
doc/git-mailrc
doc/uImage.FIT/command_syntax_extensions.txt
doc/uImage.FIT/source_file_format.txt
drivers/block/sym53c8xx.c
drivers/dfu/Makefile
drivers/dfu/dfu.c
drivers/dfu/dfu_mmc.c
drivers/dfu/dfu_nand.c
drivers/dfu/dfu_ram.c [new file with mode: 0644]
drivers/mmc/Makefile
drivers/mmc/dw_mmc.c
drivers/mmc/mmc.c
drivers/mmc/mmc_private.h [new file with mode: 0644]
drivers/mmc/mmc_write.c [new file with mode: 0644]
drivers/mmc/omap_hsmmc.c
drivers/mmc/s5p_sdhci.c
drivers/mmc/sdhci.c
drivers/mtd/spi/Makefile
drivers/mtd/spi/atmel.c [deleted file]
drivers/mtd/spi/eon.c [deleted file]
drivers/mtd/spi/gigadevice.c [deleted file]
drivers/mtd/spi/macronix.c [deleted file]
drivers/mtd/spi/ramtron.c
drivers/mtd/spi/sf.c [new file with mode: 0644]
drivers/mtd/spi/sf_internal.h [moved from drivers/mtd/spi/spi_flash_internal.h with 62% similarity]
drivers/mtd/spi/sf_ops.c [new file with mode: 0644]
drivers/mtd/spi/sf_probe.c [new file with mode: 0644]
drivers/mtd/spi/spansion.c [deleted file]
drivers/mtd/spi/spi_flash.c [deleted file]
drivers/mtd/spi/sst.c [deleted file]
drivers/mtd/spi/stmicro.c [deleted file]
drivers/mtd/spi/winbond.c [deleted file]
drivers/net/4xx_enet.c
drivers/net/npe/miiphy.c
drivers/net/phy/smsc.c
drivers/pci/pci_auto.c
drivers/power/power_core.c
drivers/sound/max98095.c
drivers/sound/max98095.h
drivers/sound/samsung-i2s.c
drivers/sound/sound.c
drivers/sound/wm8994.c
drivers/sound/wm8994_registers.h
drivers/spi/Makefile
drivers/spi/exynos_spi.c
drivers/spi/mxs_spi.c
drivers/spi/ti_qspi.c [new file with mode: 0644]
drivers/usb/gadget/Makefile
drivers/usb/gadget/atmel_usba_udc.c [new file with mode: 0644]
drivers/usb/gadget/atmel_usba_udc.h [new file with mode: 0644]
drivers/usb/gadget/config.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/f_dfu.h
drivers/usb/gadget/g_dnl.c
drivers/usb/host/ehci-hcd.c
examples/standalone/README.smc91111_eeprom
fs/fs.c
include/common.h
include/configs/P2041RDB.h
include/configs/am335x_evm.h
include/configs/dra7xx_evm.h
include/configs/eXalion.h
include/configs/sacsng.h
include/configs/sama5d3xek.h
include/configs/top9000.h
include/dfu.h
include/fs.h
include/i2s.h
include/libfdt.h
include/linux/fb.h
include/linux/usb/atmel_usba_udc.h [new file with mode: 0644]
include/linux/usb/gadget.h
include/miiphy.h
include/mmc.h
include/sdhci.h
include/spi.h
include/spi_flash.h
include/usb_mass_storage.h
lib/hashtable.c
post/board/lwmon5/sysmon.c
tools/buildman/README
tools/buildman/board.py
tools/buildman/bsettings.py
tools/buildman/builder.py
tools/buildman/buildman.py
tools/buildman/test.py
tools/buildman/toolchain.py
tools/checkpatch.pl
tools/fit_image.c

index 4196125..9f61192 100644 (file)
@@ -52,5 +52,5 @@ GNU Lesser General Public License v2.1 or later       LGPL-2.1+       Y               lgpl-2.1.txt            http:
 eCos license version 2.0                       eCos-2.0                        eCos-2.0.txt            http://www.gnu.org/licenses/ecos-license.html
 BSD 2-Clause License                           BSD-2-Clause    Y               bsd-2-clause.txt        http://spdx.org/licenses/BSD-2-Clause
 BSD 3-clause "New" or "Revised" License                BSD-3-Clause    Y               bsd-3-clause.txt        http://spdx.org/licenses/BSD-3-Clause#licenseText
-IBM PIBS (PowerPC Initialization and           ibm-pibs                        ibm-pibs.txt
+IBM PIBS (PowerPC Initialization and           IBM-pibs                        ibm-pibs.txt
        Boot Software) license
index 1365db6..b09bfcc 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@
 VERSION = 2013
 PATCHLEVEL = 10
 SUBLEVEL =
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
 ifneq "$(SUBLEVEL)" ""
 U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 else
@@ -45,13 +45,13 @@ endif
 
 #########################################################################
 #
-# U-boot build supports producing a object files to the separate external
+# U-boot build supports generating object files in a separate external
 # directory. Two use cases are supported:
 #
 # 1) Add O= to the make command line
 # 'make O=/tmp/build all'
 #
-# 2) Set environement variable BUILD_DIR to point to the desired location
+# 2) Set environment variable BUILD_DIR to point to the desired location
 # 'export BUILD_DIR=/tmp/build'
 # 'make'
 #
@@ -59,7 +59,7 @@ endif
 # 'export BUILD_DIR=/tmp/build'
 # './MAKEALL'
 #
-# Command line 'O=' setting overrides BUILD_DIR environent variable.
+# Command line 'O=' setting overrides BUILD_DIR environment variable.
 #
 # When none of the above methods is used the local build is performed and
 # the object files are placed in the source directory.
@@ -838,7 +838,7 @@ unconfig:
 
 sinclude $(obj).boards.depend
 $(obj).boards.depend:  boards.cfg
-       @awk '(NF && $$1 !~ /^#/) { print $$7 ": " $$7 "_config; $$(MAKE) -d" }' $< > $@
+       @awk '(NF && $$1 !~ /^#/) { print $$7 ": " $$7 "_config; $$(MAKE)" }' $< > $@
 
 #
 # Functions to generate common board directory names
diff --git a/README b/README
index 0bb1ad5..cee8e2f 100644 (file)
--- a/README
+++ b/README
@@ -151,9 +151,6 @@ Directory Hierarchy:
   /blackfin            Files generic to Analog Devices Blackfin architecture
     /cpu               CPU specific files
     /lib               Architecture specific library files
-  /x86                 Files generic to x86 architecture
-    /cpu               CPU specific files
-    /lib               Architecture specific library files
   /m68k                        Files generic to m68k architecture
     /cpu               CPU specific files
       /mcf52x2         Files specific to Freescale ColdFire MCF52x2 CPUs
@@ -177,6 +174,9 @@ Directory Hierarchy:
   /nios2               Files generic to Altera NIOS2 architecture
     /cpu               CPU specific files
     /lib               Architecture specific library files
+  /openrisc            Files generic to OpenRISC architecture
+    /cpu               CPU specific files
+    /lib               Architecture specific library files
   /powerpc             Files generic to PowerPC architecture
     /cpu               CPU specific files
       /74xx_7xx                Files specific to Freescale MPC74xx and 7xx CPUs
@@ -199,12 +199,16 @@ Directory Hierarchy:
       /leon2           Files specific to Gaisler LEON2 SPARC CPU
       /leon3           Files specific to Gaisler LEON3 SPARC CPU
     /lib               Architecture specific library files
+  /x86                 Files generic to x86 architecture
+    /cpu               CPU specific files
+    /lib               Architecture specific library files
 /api                   Machine/arch independent API for external apps
 /board                 Board dependent files
 /common                        Misc architecture independent functions
 /disk                  Code for disk drive partition handling
 /doc                   Documentation (don't expect too much)
 /drivers               Commonly used device drivers
+/dts                   Contains Makefile for building internal U-Boot fdt.
 /examples              Example code for standalone applications, etc.
 /fs                    Filesystem code (cramfs, ext2, jffs2, etc.)
 /include               Header Files
@@ -214,7 +218,7 @@ Directory Hierarchy:
   /lzo                 Library files to support LZO decompression
 /net                   Networking code
 /post                  Power On Self Test
-/rtc                   Real Time Clock drivers
+/spl                   Secondary Program Loader framework
 /tools                 Tools to build S-Record or U-Boot images, etc.
 
 Software Configuration:
@@ -1403,6 +1407,12 @@ The following options need to be configured:
                CONFIG_DFU_NAND
                This enables support for exposing NAND devices via DFU.
 
+               CONFIG_DFU_RAM
+               This enables support for exposing RAM via DFU.
+               Note: DFU spec refer to non-volatile memory usage, but
+               allow usages beyond the scope of spec - here RAM usage,
+               one that would help mostly the developer.
+
                CONFIG_SYS_DFU_DATA_BUF_SIZE
                Dfu transfer uses a buffer before writing data to the
                raw storage device. Make the size (in bytes) of this buffer
@@ -3358,7 +3368,7 @@ Configuration Settings:
                the Linux kernel; all data that must be processed by
                the Linux kernel (bd_info, boot arguments, FDT blob if
                used) must be put below this limit, unless "bootm_low"
-               enviroment variable is defined and non-zero. In such case
+               environment variable is defined and non-zero. In such case
                all data for the Linux kernel must be between "bootm_low"
                and "bootm_low" + CONFIG_SYS_BOOTMAPSZ.  The environment
                variable "bootm_mapsize" will override the value of
@@ -3471,7 +3481,7 @@ Configuration Settings:
 
 - CONFIG_ENV_FLAGS_LIST_DEFAULT
 - CONFIG_ENV_FLAGS_LIST_STATIC
-       Enable validation of the values given to enviroment variables when
+       Enable validation of the values given to environment 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.
index 3e21cdb..3f39264 100644 (file)
@@ -28,7 +28,7 @@
  * by u-Boot commands.
  *
  * Note: Redundant environment will not work in this flash since
- * it does use partial page writes. Make sure the environent spans
+ * it does use partial page writes. Make sure the environment spans
  * whole pages!
  */
 
index cde3172..d4711c0 100644 (file)
@@ -302,7 +302,7 @@ int arch_cpu_init(void)
        /*
         * Configures the I/O voltage of the pads connected to Egigabit
         * Ethernet interface to 1.8V
-        * By defult it is set to 3.3V
+        * By default it is set to 3.3V
         */
        reg = readl(KW_REG_MPP_OUT_DRV_REG);
        reg |= (1 << 7);
index e55e1c6..51f0a6d 100644 (file)
@@ -202,3 +202,15 @@ void at91_lcd_hw_init(void)
        at91_periph_clk_enable(ATMEL_ID_LCDC);
 }
 #endif
+
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+void at91_udp_hw_init(void)
+{
+       struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+
+       /* Enable UPLL clock */
+       writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
+       /* Enable UDPHS clock */
+       at91_periph_clk_enable(ATMEL_ID_UDPHS);
+}
+#endif
index 0cb1a61..36fedd6 100644 (file)
@@ -282,6 +282,9 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
                src = readl(&clk->src_peric0);
                div = readl(&clk->div_peric3);
                break;
+       case PERIPH_ID_I2S0:
+               src = readl(&clk->src_mau);
+               div = readl(&clk->div_mau);
        case PERIPH_ID_SPI0:
        case PERIPH_ID_SPI1:
                src = readl(&clk->src_peric1);
@@ -1146,17 +1149,29 @@ int exynos5_set_epll_clk(unsigned long rate)
        return 0;
 }
 
-void exynos5_set_i2s_clk_source(void)
+int exynos5_set_i2s_clk_source(unsigned int i2s_id)
 {
        struct exynos5_clock *clk =
                (struct exynos5_clock *)samsung_get_base_clock();
-
-       clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
-                       (CLK_SRC_SCLK_EPLL));
+       unsigned int *audio_ass = (unsigned int *)samsung_get_base_audio_ass();
+
+       if (i2s_id == 0) {
+               setbits_le32(&clk->src_top2, CLK_SRC_MOUT_EPLL);
+               clrsetbits_le32(&clk->src_mau, AUDIO0_SEL_MASK,
+                               (CLK_SRC_SCLK_EPLL));
+               setbits_le32(audio_ass, AUDIO_CLKMUX_ASS);
+       } else if (i2s_id == 1) {
+               clrsetbits_le32(&clk->src_peric1, AUDIO1_SEL_MASK,
+                               (CLK_SRC_SCLK_EPLL));
+       } else {
+               return -1;
+       }
+       return 0;
 }
 
 int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
-                                       unsigned int dst_frq)
+                                 unsigned int dst_frq,
+                                 unsigned int i2s_id)
 {
        struct exynos5_clock *clk =
                (struct exynos5_clock *)samsung_get_base_clock();
@@ -1169,13 +1184,27 @@ int exynos5_set_i2s_clk_prescaler(unsigned int src_frq,
        }
 
        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);
+       if (i2s_id == 0) {
+               if (div > AUDIO_0_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_mau, AUDIO_0_RATIO_MASK,
+                               (div & AUDIO_0_RATIO_MASK));
+       } else if(i2s_id == 1) {
+               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));
+       } else {
                return -1;
        }
-       clrsetbits_le32(&clk->div_peric4, AUDIO_1_RATIO_MASK,
-                               (div & AUDIO_1_RATIO_MASK));
        return 0;
 }
 
@@ -1415,19 +1444,21 @@ int set_spi_clk(int periph_id, unsigned int rate)
                return 0;
 }
 
-int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq)
+int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
+                         unsigned int i2s_id)
 {
-
        if (cpu_is_exynos5())
-               return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq);
+               return exynos5_set_i2s_clk_prescaler(src_frq, dst_frq, i2s_id);
        else
                return 0;
 }
 
-void set_i2s_clk_source(void)
+int set_i2s_clk_source(unsigned int i2s_id)
 {
        if (cpu_is_exynos5())
-               exynos5_set_i2s_clk_source();
+               return exynos5_set_i2s_clk_source(i2s_id);
+       else
+               return 0;
 }
 
 int set_epll_clk(unsigned long rate)
index 1b05ebf..8002bce 100644 (file)
@@ -220,10 +220,20 @@ static void exynos5_i2s_config(int peripheral)
 {
        int i;
        struct exynos5_gpio_part1 *gpio1 =
-               (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1();
+               (struct exynos5_gpio_part1 *)samsung_get_base_gpio_part1();
+       struct exynos5_gpio_part4 *gpio4 =
+               (struct exynos5_gpio_part4 *)samsung_get_base_gpio_part4();
 
-       for (i = 0; i < 5; i++)
-               s5p_gpio_cfg_pin(&gpio1->b0, i, GPIO_FUNC(0x02));
+       switch (peripheral) {
+       case PERIPH_ID_I2S0:
+               for (i = 0; i < 5; i++)
+                       s5p_gpio_cfg_pin(&gpio4->z, i, GPIO_FUNC(0x02));
+               break;
+       case PERIPH_ID_I2S1:
+               for (i = 0; i < 5; i++)
+                       s5p_gpio_cfg_pin(&gpio1->b0, i, GPIO_FUNC(0x02));
+               break;
+       }
 }
 
 void exynos5_spi_config(int peripheral)
@@ -296,6 +306,7 @@ static int exynos5_pinmux_config(int peripheral, int flags)
        case PERIPH_ID_I2C7:
                exynos5_i2c_config(peripheral, flags);
                break;
+       case PERIPH_ID_I2S0:
        case PERIPH_ID_I2S1:
                exynos5_i2s_config(peripheral);
                break;
@@ -463,11 +474,11 @@ static int exynos4_pinmux_config(int peripheral, int flags)
 
 int exynos_pinmux_config(int peripheral, int flags)
 {
-       if (cpu_is_exynos5())
+       if (cpu_is_exynos5()) {
                return exynos5_pinmux_config(peripheral, flags);
-       else if (cpu_is_exynos4())
+       } else if (cpu_is_exynos4()) {
                return exynos4_pinmux_config(peripheral, flags);
-       else {
+       else {
                debug("pinmux functionality not supported\n");
                return -1;
        }
index 358348f..24b4c18 100644 (file)
@@ -3,23 +3,7 @@
  *
  * Copyright (c) 2013  Andre Przywara <andre.przywara@linaro.org>
  *
- * 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
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <config.h>
index fbbc486..a1b249e 100644 (file)
@@ -170,7 +170,7 @@ static const struct dpll_params per_dpll_params_768mhz_es2[NUM_SYS_CLKS] = {
 
 static const struct dpll_params per_dpll_params_768mhz_dra7xx[NUM_SYS_CLKS] = {
        {32, 0, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},             /* 12 MHz   */
-       {96, 4, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},             /* 20 MHz   */
+       {96, 4, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1},              /* 20 MHz   */
        {160, 6, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},            /* 16.8 MHz */
        {20, 0, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},             /* 19.2 MHz */
        {192, 12, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},           /* 26 MHz   */
@@ -426,6 +426,10 @@ void enable_basic_clocks(void)
 #ifdef CONFIG_DRIVER_TI_CPSW
                (*prcm)->cm_gmac_gmac_clkctrl,
 #endif
+
+#ifdef CONFIG_TI_QSPI
+               (*prcm)->cm_l4per_qspi_clkctrl,
+#endif
                0
        };
 
@@ -454,6 +458,10 @@ void enable_basic_clocks(void)
                         clk_modules_explicit_en_essential,
                         1);
 
+#ifdef CONFIG_TI_QSPI
+       setbits_le32((*prcm)->cm_l4per_qspi_clkctrl, (1<<24));
+#endif
+
        /* Enable SCRM OPT clocks for PER and CORE dpll */
        setbits_le32((*prcm)->cm_wkupaon_scrm_clkctrl,
                        OPTFCLKEN_SCRM_PER_MASK);
index 5a3d52c..7a7cade 100644 (file)
@@ -921,6 +921,7 @@ struct prcm_regs const dra7xx_prcm = {
        .cm_l4per_gpio8_clkctrl                 = 0x4a009818,
        .cm_l4per_mmcsd3_clkctrl                = 0x4a009820,
        .cm_l4per_mmcsd4_clkctrl                = 0x4a009828,
+       .cm_l4per_qspi_clkctrl                  = 0x4a009838,
        .cm_l4per_uart1_clkctrl                 = 0x4a009840,
        .cm_l4per_uart2_clkctrl                 = 0x4a009848,
        .cm_l4per_uart3_clkctrl                 = 0x4a009850,
index 6de7fe7..2cd604f 100644 (file)
@@ -1,28 +1,12 @@
 /*
  * (C) Copyright 2013
- * Andre Przywara, Linaro
+ * Andre Przywara, Linaro <andre.przywara@linaro.org>
  *
  * Routines to transition ARMv7 processors from secure into non-secure state
  * and from non-secure SVC into HYP mode
  * needed to enable ARMv7 virtualization for current hypervisors
  *
- * 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
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
index 4fff5e3..1c5474f 100644 (file)
                interrupts = <0 63 0>;
        };
 
+       sound@3830000 {
+               compatible = "samsung,exynos-sound";
+               reg = <0x3830000 0x50>;
+               samsung,i2s-epll-clock-frequency = <192000000>;
+               samsung,i2s-sampling-rate = <48000>;
+               samsung,i2s-bits-per-sample = <16>;
+               samsung,i2s-channels = <2>;
+               samsung,i2s-lr-clk-framesize = <256>;
+               samsung,i2s-bit-clk-framesize = <32>;
+               samsung,i2s-id = <0>;
+       };
+
        sound@12d60000 {
                compatible = "samsung,exynos-sound";
                reg = <0x12d60000 0x20>;
+               samsung,i2s-epll-clock-frequency = <192000000>;
+               samsung,i2s-sampling-rate = <48000>;
+               samsung,i2s-bits-per-sample = <16>;
+               samsung,i2s-channels = <2>;
+               samsung,i2s-lr-clk-framesize = <256>;
+               samsung,i2s-bit-clk-framesize = <32>;
+               samsung,i2s-id = <1>;
        };
 
        spi@12d20000 {
index 9f54fdd..abcb97d 100644 (file)
@@ -19,6 +19,7 @@ void at91_serial2_hw_init(void);
 void at91_seriald_hw_init(void);
 void at91_spi0_hw_init(unsigned long cs_mask);
 void at91_spi1_hw_init(unsigned long cs_mask);
+void at91_udp_hw_init(void);
 void at91_uhp_hw_init(void);
 void at91_lcd_hw_init(void);
 
diff --git a/arch/arm/include/asm/arch-at91/atmel_usba_udc.h b/arch/arm/include/asm/arch-at91/atmel_usba_udc.h
new file mode 100644 (file)
index 0000000..6f540d2
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2005-2013 Atmel Corporation
+ *                        Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __ATMEL_USBA_UDC_H__
+#define __ATMEL_USBA_UDC_H__
+
+#include <linux/usb/atmel_usba_udc.h>
+
+#define EP(nam, idx, maxpkt, maxbk, dma, isoc)         \
+       [idx] = {                                       \
+               .name   = nam,                          \
+               .index  = idx,                          \
+               .fifo_size      = maxpkt,               \
+               .nr_banks       = maxbk,                \
+               .can_dma        = dma,                  \
+               .can_isoc       = isoc,                 \
+       }
+
+#if defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \
+       defined(CONFIG_AT91SAM9X5)
+static struct usba_ep_data usba_udc_ep[] = {
+       EP("ep0", 0, 64, 1, 0, 0),
+       EP("ep1", 1, 1024, 2, 1, 1),
+       EP("ep2", 2, 1024, 2, 1, 1),
+       EP("ep3", 3, 1024, 3, 1, 0),
+       EP("ep4", 4, 1024, 3, 1, 0),
+       EP("ep5", 5, 1024, 3, 1, 1),
+       EP("ep6", 6, 1024, 3, 1, 1),
+};
+#elif defined(CONFIG_SAMA5D3)
+static struct usba_ep_data usba_udc_ep[] = {
+       EP("ep0", 0, 64, 1, 0, 0),
+       EP("ep1", 1, 1024, 3, 1, 0),
+       EP("ep2", 2, 1024, 3, 1, 0),
+       EP("ep3", 3, 1024, 2, 1, 0),
+       EP("ep4", 4, 1024, 2, 1, 0),
+       EP("ep5", 5, 1024, 2, 1, 0),
+       EP("ep6", 6, 1024, 2, 1, 0),
+       EP("ep7", 7, 1024, 2, 1, 0),
+       EP("ep8", 8, 1024, 2, 0, 0),
+       EP("ep9", 9, 1024, 2, 0, 0),
+       EP("ep10", 10, 1024, 2, 0, 0),
+       EP("ep11", 11, 1024, 2, 0, 0),
+       EP("ep12", 12, 1024, 2, 0, 0),
+       EP("ep13", 13, 1024, 2, 0, 0),
+       EP("ep14", 14, 1024, 2, 0, 0),
+       EP("ep15", 15, 1024, 2, 0, 0),
+};
+#else
+# error "NO usba_udc_ep defined"
+#endif
+
+#undef EP
+
+struct usba_platform_data pdata = {
+       .num_ep = ARRAY_SIZE(usba_udc_ep),
+       .ep     = usba_udc_ep,
+};
+
+#endif
index fefee5e..123a627 100644 (file)
 #define ATMEL_BASE_USART3      0xf8024000
 #define ATMEL_BASE_UART1       0xf8028000
 #define ATMEL_BASE_EMAC                0xf802c000
-#define ATMEL_BASE_UDHPS       0xf8030000
+#define ATMEL_BASE_UDPHS       0xf8030000
 #define ATMEL_BASE_SHA         0xf8034000
 #define ATMEL_BASE_AES         0xf8038000
 #define ATMEL_BASE_TDES                0xf803c000
index 71075bd..1d6fa93 100644 (file)
@@ -31,8 +31,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_i2s_clk_source(unsigned int i2s_id);
+int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,
+                               unsigned int i2s_id);
 int set_epll_clk(unsigned long rate);
 int set_spi_clk(int periph_id, unsigned int rate);
 
index 2b97b9a..cf26eef 100644 (file)
@@ -876,8 +876,12 @@ struct set_epll_con_val {
 #define AUDIO_0_RATIO_MASK             0x0f
 #define AUDIO_1_RATIO_MASK             0x0f
 
+#define AUDIO0_SEL_MASK                        0xf
 #define AUDIO1_SEL_MASK                        0xf
+
 #define CLK_SRC_SCLK_EPLL              0x7
+#define CLK_SRC_MOUT_EPLL              (1<<12)
+#define AUDIO_CLKMUX_ASS               (1<<0)
 
 /* CON0 bit-fields */
 #define EPLL_CON0_MDIV_MASK            0x1ff
index cb924fb..4b67191 100644 (file)
@@ -50,6 +50,7 @@
 #define EXYNOS4_SPI_ISP_BASE           DEVICE_NOT_AVAILABLE
 #define EXYNOS4_ACE_SFR_BASE           DEVICE_NOT_AVAILABLE
 #define EXYNOS4_DMC_PHY_BASE           DEVICE_NOT_AVAILABLE
+#define EXYNOS4_AUDIOSS_BASE           DEVICE_NOT_AVAILABLE
 
 /* EXYNOS4X12 */
 #define EXYNOS4X12_GPIO_PART3_BASE     0x03860000
 #define EXYNOS4X12_SPI_ISP_BASE                DEVICE_NOT_AVAILABLE
 #define EXYNOS4X12_ACE_SFR_BASE                DEVICE_NOT_AVAILABLE
 #define EXYNOS4X12_DMC_PHY_BASE                DEVICE_NOT_AVAILABLE
+#define EXYNOS4X12_AUDIOSS_BASE                DEVICE_NOT_AVAILABLE
 
 /* EXYNOS5 Common*/
 #define EXYNOS5_I2C_SPACING            0x10000
 
+#define EXYNOS5_AUDIOSS_BASE           0x03810000
 #define EXYNOS5_GPIO_PART4_BASE                0x03860000
 #define EXYNOS5_PRO_ID                 0x10000000
 #define EXYNOS5_CLOCK_BASE             0x10010000
@@ -226,6 +229,7 @@ SAMSUNG_BASE(spi_isp, SPI_ISP_BASE)
 SAMSUNG_BASE(tzpc, TZPC_BASE)
 SAMSUNG_BASE(dmc_ctrl, DMC_CTRL_BASE)
 SAMSUNG_BASE(dmc_phy, DMC_PHY_BASE)
+SAMSUNG_BASE(audio_ass, AUDIOSS_BASE)
 #endif
 
 #endif /* _EXYNOS4_CPU_H */
index 613b9b7..4a4a7a0 100644 (file)
@@ -8,10 +8,12 @@
 #ifndef __I2S_REGS_H__
 #define __I2S_REGS_H__
 
+#define CON_RESET              (1 << 31)
 #define CON_TXFIFO_FULL                (1 << 8)
 #define CON_TXCH_PAUSE         (1 << 4)
 #define CON_ACTIVE             (1 << 0)
 
+#define MOD_OP_CLK             (3 << 30)
 #define MOD_BLCP_SHIFT         24
 #define MOD_BLCP_16BIT         (0 << MOD_BLCP_SHIFT)
 #define MOD_BLCP_8BIT          (1 << MOD_BLCP_SHIFT)
@@ -24,6 +26,7 @@
 #define MOD_BLC_MASK           (3 << 13)
 
 #define MOD_SLAVE              (1 << 11)
+#define MOD_RCLKSRC            (0 << 10)
 #define MOD_MASK               (3 << 8)
 #define MOD_LR_LLOW            (0 << 7)
 #define MOD_LR_RLOW            (1 << 7)
@@ -47,4 +50,7 @@
 #define FIC_TXFLUSH            (1 << 15)
 #define FIC_RXFLUSH            (1 << 7)
 
+#define PSREN                  (1 << 15)
+#define PSVAL                  (3 << 8)
+
 #endif /* __I2S_REGS_H__ */
index 9952155..64bd8b7 100644 (file)
@@ -34,6 +34,7 @@ enum periph_id {
        PERIPH_ID_SDMMC1,
        PERIPH_ID_SDMMC2,
        PERIPH_ID_SDMMC3,
+       PERIPH_ID_I2S0 = 98,
        PERIPH_ID_I2S1 = 99,
 
        /* Since following peripherals do
index fb23aa6..147c1a7 100644 (file)
@@ -22,7 +22,7 @@ struct exynos_spi {
        unsigned int            rx_data;        /* 0x1c */
        unsigned int            pkt_cnt;        /* 0x20 */
        unsigned char           reserved2[4];
-       unsigned char           reserved3[4];
+       unsigned int            swap_cfg;       /* 0x28 */
        unsigned int            fb_clk;         /* 0x2c */
        unsigned char           padding[0xffd0];
 };
@@ -62,5 +62,14 @@ struct exynos_spi {
 /* Packet Count */
 #define SPI_PACKET_CNT_EN      (1 << 16)
 
+/* Swap config */
+#define SPI_TX_SWAP_EN         (1 << 0)
+#define SPI_TX_BYTE_SWAP       (1 << 2)
+#define SPI_TX_HWORD_SWAP      (1 << 3)
+#define SPI_TX_BYTE_SWAP       (1 << 2)
+#define SPI_RX_SWAP_EN         (1 << 4)
+#define SPI_RX_BYTE_SWAP       (1 << 6)
+#define SPI_RX_HWORD_SWAP      (1 << 7)
+
 #endif /* __ASSEMBLY__ */
 #endif
index 3921e4a..63aaa02 100644 (file)
@@ -2,20 +2,7 @@
  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com*
  * Author: Govindraj R <govindraj.raja@ti.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
+ * SPDX-License-Identifier: GPL-2.0+
  */
 
 #ifndef _EHCI_H
index e9a51d3..414d37a 100644 (file)
@@ -61,6 +61,9 @@
 /* GPMC */
 #define OMAP54XX_GPMC_BASE     0x50000000
 
+/* QSPI */
+#define QSPI_BASE              0x4B300000
+
 /*
  * Hardware Register Details
  */
index fe8b0c0..57f0de5 100644 (file)
@@ -15,6 +15,7 @@
 #define BOOT_DEVICE_MMC1        5
 #define BOOT_DEVICE_MMC2        6
 #define BOOT_DEVICE_MMC2_2     7
+#define BOOT_DEVICE_SPI                10
 
 #define MMC_BOOT_DEVICES_START BOOT_DEVICE_MMC1
 #define MMC_BOOT_DEVICES_END   BOOT_DEVICE_MMC2_2
index 61fee9f..3a998cc 100644 (file)
@@ -266,6 +266,7 @@ struct prcm_regs {
        u32 cm_l4per_mmcsd4_clkctrl;
        u32 cm_l4per_msprohg_clkctrl;
        u32 cm_l4per_slimbus2_clkctrl;
+       u32 cm_l4per_qspi_clkctrl;
        u32 cm_l4per_uart1_clkctrl;
        u32 cm_l4per_uart2_clkctrl;
        u32 cm_l4per_uart3_clkctrl;
index eea264b..c441bd2 100644 (file)
@@ -252,6 +252,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #ifdef CONFIG_SYS_FSL_ERRATUM_A005812
        puts("Work-around for Erratum A-005812 enabled\n");
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A005125
+       puts("Work-around for Erratum A005125 enabled\n");
+#endif
 #ifdef CONFIG_SYS_FSL_ERRATUM_I2C_A004447
        if ((SVR_SOC_VER(svr) == SVR_8548 && IS_SVR_REV(svr, 3, 1)) ||
            (SVR_REV(svr) <= CONFIG_SYS_FSL_A004447_SVR_REV))
index ad57a9c..be4f4ae 100644 (file)
@@ -108,6 +108,14 @@ _start_e500:
        isync
 2:
 #endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A005125
+       msync
+       isync
+       mfspr   r3, SPRN_HDBCR0
+       oris    r3, r3, 0x0080
+       mtspr   SPRN_HDBCR0, r3
+#endif
+
 
 #if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_E500MC)
        /* ISBC uses L2 as stack.
index 5584e0f..08781a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  *
  *  File Name:   405gp_pci.c
  *
index 50c28a0..c02058f 100644 (file)
@@ -5,7 +5,7 @@
  * (C) Copyright 2010
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 
 #include <common.h>
index e4a9db6..10147de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*-----------------------------------------------------------------------------+
   |
index d9d8cbf..38bbc5a 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (c) 2008 Nuovation System Designs, LLC
  *    Grant Erickson <gerickson@nuovations.com>
  *
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 
 /*
index 15e44de..bec8966 100644 (file)
@@ -34,6 +34,7 @@
 #define CONFIG_SYS_PPC_E500_DEBUG_TLB  1
 #define CONFIG_SYS_FSL_SEC_COMPAT      2
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_MPC8540)
 #define CONFIG_MAX_CPUS                        1
@@ -52,6 +53,7 @@
 #define CONFIG_SYS_PPC_E500_DEBUG_TLB  0
 #define CONFIG_SYS_FSL_SEC_COMPAT      2
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_MPC8548)
 #define CONFIG_MAX_CPUS                        1
@@ -67,6 +69,7 @@
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
 #define CONFIG_SYS_FSL_RMU
 #define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM       2
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 #define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
 #define CONFIG_SYS_FSL_A004447_SVR_REV 0x00
 
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
 #define CONFIG_SYS_FSL_RMU
 #define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM       2
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_MPC8572)
 #define CONFIG_MAX_CPUS                        2
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_SYS_FSL_ERRATUM_DDR_115
 #define CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_P1010)
 #define CONFIG_MAX_CPUS                        1
 #define CONFIG_SYS_FSL_ERRATUM_P1010_A003549
 #define CONFIG_SYS_FSL_ERRATUM_SEC_A003571
 #define CONFIG_SYS_FSL_ERRATUM_IFC_A003399
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 #define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
 #define CONFIG_SYS_FSL_A004447_SVR_REV 0x10
 
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 /* P1012 is single core version of P1021 */
 #elif defined(CONFIG_P1012)
 #define QE_MURAM_SIZE                  0x6000UL
 #define MAX_QE_RISC                    1
 #define QE_NUM_OF_SNUM                 28
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 /* P1013 is single core version of P1022 */
 #elif defined(CONFIG_P1013)
 #define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_FSL_SATA_ERRATUM_A001
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_P1014)
 #define CONFIG_MAX_CPUS                        1
 #define CONFIG_SYS_FM_MURAM_SIZE       0x10000
 #define CONFIG_SYS_FSL_PCIE_COMPAT     "fsl,qoriq-pcie-v2.2"
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff600000
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_P1020)
 #define CONFIG_MAX_CPUS                        2
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_P1021)
 #define CONFIG_MAX_CPUS                        2
 #define QE_MURAM_SIZE                  0x6000UL
 #define MAX_QE_RISC                    1
 #define QE_NUM_OF_SNUM                 28
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_P1022)
 #define CONFIG_MAX_CPUS                        2
 #define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_FSL_SATA_ERRATUM_A001
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_P1023)
 #define CONFIG_MAX_CPUS                        2
 #define CONFIG_SYS_FM_MURAM_SIZE       0x10000
 #define CONFIG_SYS_FSL_PCIE_COMPAT     "fsl,qoriq-pcie-v2.2"
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff600000
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 #define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
 #define CONFIG_SYS_FSL_A004447_SVR_REV 0x11
 
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 /* P1025 is lower end variant of P1021 */
 #elif defined(CONFIG_P1025)
 #define QE_MURAM_SIZE                  0x6000UL
 #define MAX_QE_RISC                    1
 #define QE_NUM_OF_SNUM                 28
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 /* P2010 is single core version of P2020 */
 #elif defined(CONFIG_P2010)
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_P2020)
 #define CONFIG_MAX_CPUS                        2
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
 #define CONFIG_SYS_FSL_RMU
 #define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM       2
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_PPC_P2041) /* also supports P2040 */
 #define CONFIG_SYS_FSL_QORIQ_CHASSIS1
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
 #define CONFIG_NAND_FSL_IFC
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #elif defined(CONFIG_BSC9132)
 #define CONFIG_MAX_CPUS                        2
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_SYS_FSL_ESDHC_P1010_BROKEN_SDCLK
 #define CONFIG_SYS_FSL_PCIE_COMPAT     "fsl,qoriq-pcie-v2.2"
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 #define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
 #define CONFIG_SYS_FSL_A004447_SVR_REV 0x11
 
 #define CONFIG_NUM_DDR_CONTROLLERS     1
 #define CONFIG_SYS_FSL_IFC_BANK_COUNT  8
 #define CONFIG_SYS_CCSRBAR_DEFAULT     0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_A005125
 
 #else
 #error Processor type not defined for this platform
index 8bb342b..f2ed16a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 
 #ifndef        __PPC405_H__
index 0f5bc8d..0cfa88b 100644 (file)
@@ -9,7 +9,7 @@
  * (C) Copyright 2010
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 
 #ifndef __PPC440_H__
index e6eb332..76fa95c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*----------------------------------------------------------------------------+
 |
index d15290d..ef8b174 100644 (file)
@@ -1,6 +1,6 @@
 /* include/mal.h, openbios_walnut, walnut_bios 8/6/99 08:48:40 */
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*----------------------------------------------------------------------------+
 |
index 8d703c6..e6a3bff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 
 #ifndef        __PPC4XX_H__
index 14296b2..9e2d0f4 100644 (file)
@@ -87,9 +87,9 @@ u-boot>
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-A word on the U-Boot enviroment variable setting and usage :
+A word on the U-Boot environment variable setting and usage :
 
-In the beginning, you could just need very simple defult environment variable setting,
+In the beginning, you could just need very simple default environment variable setting,
 like[include/configs/RPXlite.h] :
 
 #define CONFIG_BOOTCOMMAND                                                      \
index 97caf64..b0965ef 100644 (file)
 #include <net.h>
 #include <netdev.h>
 
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+#include <asm/arch/atmel_usba_udc.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* ------------------------------------------------------------------------- */
@@ -170,6 +174,9 @@ int board_init(void)
 #ifdef CONFIG_CMD_USB
        sama5d3xek_usb_hw_init();
 #endif
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+       at91_udp_hw_init();
+#endif
 #ifdef CONFIG_GENERIC_ATMEL_MCI
        sama5d3xek_mci_hw_init();
 #endif
@@ -221,6 +228,12 @@ int board_eth_init(bd_t *bis)
        if (has_gmac())
                rc = macb_eth_initialize(0, (void *)ATMEL_BASE_GMAC, 0x00);
 #endif
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+       usba_udc_probe(&pdata);
+#ifdef CONFIG_USB_ETH_RNDIS
+       usb_eth_initialize(bis);
+#endif
+#endif
 
        return rc;
 }
index 82f21b0..44c688d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 
 /*----------------------------------------------------------------------------- */
index b1283aa..5961978 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 #include <config.h>
 #include <asm/ppc4xx.h>
index f5805b7..1ebc9ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 #include <config.h>
 #include <asm/ppc4xx.h>
index 38acca1..03eaf97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*----------------------------------------------------------------------------- */
 /* Function:     ext_bus_cntlr_init */
index 524f3fc..0389a1d 100644 (file)
@@ -29,11 +29,11 @@ Environment Storage
 
 There are two targets for mx28evk:
 
-"make mx28evk_config"          - store enviroment variables into MMC
+"make mx28evk_config"          - store environment variables into MMC
 
 or
 
-"make mx28evk_nand_config"     - store enviroment variables into NAND flash
+"make mx28evk_nand_config"     - store environment variables into NAND flash
 
 Choose the target accordingly.
 
index 7b918b5..4e449fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*------------------------------------------------------------------------- */
 /* Function:     ext_bus_cntlr_init */
index 6ab263a..cd969cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*
  * Adapted for PIP405 03.07.01
index bf886c0..642f17c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*-----------------------------------------------------------------------------
  * Function:     ext_bus_cntlr_init
index 9ed2799..95fed34 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*-----------------------------------------------------------------------------
  * Function:     ext_bus_cntlr_init
index 1e94c7f..b1bba96 100644 (file)
@@ -36,6 +36,7 @@
                mmc3 = "/mmc@12230000";
                serial0 = "/serial@12C30000";
                console = "/serial@12C30000";
+               i2s = "/sound@3830000";
        };
 
        sromc@12250000 {
                };
        };
 
-       sound@12d60000 {
-               samsung,i2s-epll-clock-frequency = <192000000>;
-               samsung,i2s-sampling-rate = <48000>;
-               samsung,i2s-bits-per-sample = <16>;
-               samsung,i2s-channels = <2>;
-               samsung,i2s-lr-clk-framesize = <256>;
-               samsung,i2s-bit-clk-framesize = <32>;
+       sound@3830000 {
                samsung,codec-type = "wm8994";
        };
 
+       sound@12d60000 {
+               status = "disabled";
+       };
+
        i2c@12c70000 {
                soundcodec@1a {
                        reg = <0x1a>;
index 7832e4e..9b7e57e 100644 (file)
@@ -36,6 +36,7 @@
                mmc3 = "/mmc@12230000";
                serial0 = "/serial@12C30000";
                console = "/serial@12C30000";
+               i2s = "/sound@3830000";
        };
 
        i2c4: i2c@12ca0000 {
                };
        };
 
-       sound@12d60000 {
-               samsung,i2s-epll-clock-frequency = <192000000>;
-               samsung,i2s-sampling-rate = <48000>;
-               samsung,i2s-bits-per-sample = <16>;
-               samsung,i2s-channels = <2>;
-               samsung,i2s-lr-clk-framesize = <256>;
-               samsung,i2s-bit-clk-framesize = <32>;
+       sound@3830000 {
                samsung,codec-type = "max98095";
+               codec-enable-gpio = <&gpio 0xb7 0>;
        };
 
+        sound@12d60000 {
+                status = "disabled";
+        };
+
        i2c@12cd0000 {
                soundcodec@22 {
                        reg = <0x22>;
index 2c35919..e2d60cc 100644 (file)
@@ -50,7 +50,7 @@ is a summary of that information:
     trying to preserve your old environment settings and user flash).
   - Set the start address of the erase/flash process to FF80_0000
   - Set the target RAM required to 64kB.
-  - Select sectors for erasing (see note on enviroment below)
+  - Select sectors for erasing (see note on environment below)
   - Select Erase and Reprogram.
 
 Note that some versions of the register files used with Workbench
index 9921f8f..46323d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 #include <config.h>
 #include <asm/ppc4xx.h>
index 0a86594..6965cc5 100644 (file)
@@ -51,5 +51,15 @@ const struct pad_conf_entry core_padconf_array_essential[] = {
        {RGMII0_RXD2, (IEN | M0) },
        {RGMII0_RXD1, (IEN | M0) },
        {RGMII0_RXD0, (IEN | M0) },
+       {GPMC_A13, (IEN | PDIS | M1)},  /* QSPI1_RTCLK */
+       {GPMC_A14, (IEN | PDIS | M1)},  /* QSPI1_D[3] */
+       {GPMC_A15, (IEN | PDIS | M1)},  /* QSPI1_D[2] */
+       {GPMC_A16, (IEN | PDIS | M1)},  /* QSPI1_D[1] */
+       {GPMC_A17, (IEN | PDIS | M1)},  /* QSPI1_D[0] */
+       {GPMC_A18, (M1)},  /* QSPI1_SCLK */
+       {GPMC_A3, (IEN | PDIS | M1)},   /* QSPI1_CS2 */
+       {GPMC_A4, (IEN | PDIS | M1)},   /* QSPI1_CS3 */
+       {GPMC_CS2, (IEN | PTU | PDIS | M1)},    /* QSPI1_CS0 */
+       {GPMC_CS3, (IEN | PTU | PDIS | M1)},    /* QSPI1_CS1*/
 };
 #endif /* _MUX_DATA_DRA7XX_H_ */
index 490411e..54eda32 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 #include <config.h>
 #include <asm/ppc4xx.h>
index a475f52..85143c6 100644 (file)
@@ -38,7 +38,7 @@
 # It can be used from a shell:
 #      tools/reformat.py -i -d '-' -s 8 <boards.cfg >boards0.cfg && mv boards0.cfg boards.cfg
 # It can directly be invoked from vim:
-#      :%tools/reformat.py -i -d '-' -s 8
+#      :%!tools/reformat.py -i -d '-' -s 8
 #
 # Status, Arch, CPU:SPLCPU, SoC, Vendor, Board name, Target, Options, Maintainers
 ###########################################################################################################
index b07b0f4..166b901 100644 (file)
@@ -558,6 +558,7 @@ static ulong bootm_disable_interrupts(void)
 #ifdef CONFIG_NETCONSOLE
        /* Stop the ethernet stack if NetConsole could have left it up */
        eth_halt();
+       eth_unregister(eth_get_dev());
 #endif
 
 #if defined(CONFIG_CMD_USB)
@@ -799,8 +800,12 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
                BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
-               BOOTM_STATE_LOADOS | BOOTM_STATE_OS_PREP |
-               BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO, &images, 1);
+               BOOTM_STATE_LOADOS |
+#if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
+               BOOTM_STATE_OS_CMDLINE |
+#endif
+               BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
+               BOOTM_STATE_OS_GO, &images, 1);
 }
 
 int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
index 793c422..7ce92ce 100644 (file)
@@ -9,34 +9,20 @@
  */
 
 #include <common.h>
-#include <command.h>
-#include <malloc.h>
 #include <dfu.h>
-#include <asm/errno.h>
 #include <g_dnl.h>
 
 static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       const char *str_env;
        char *s = "dfu";
        int ret, i = 0;
-       char *env_bkp;
 
        if (argc < 3)
                return CMD_RET_USAGE;
 
-       str_env = getenv("dfu_alt_info");
-       if (str_env == NULL) {
-               printf("%s: \"dfu_alt_info\" env variable not defined!\n",
-                      __func__);
-               return CMD_RET_FAILURE;
-       }
-
-       env_bkp = strdup(str_env);
-       ret = dfu_config_entities(env_bkp, argv[1],
-                           (int)simple_strtoul(argv[2], NULL, 10));
+       ret = dfu_init_env_entities(argv[1], simple_strtoul(argv[2], NULL, 10));
        if (ret)
-               return CMD_RET_FAILURE;
+               return ret;
 
        if (argc > 3 && strcmp(argv[3], "list") == 0) {
                dfu_show_entities();
@@ -67,7 +53,6 @@ exit:
        g_dnl_unregister();
 done:
        dfu_free_entities();
-       free(env_bkp);
 
        if (dfu_reset())
                run_command("reset", 0);
index 1731919..5a4bcc1 100644 (file)
@@ -32,7 +32,7 @@ int do_ext2ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  */
 int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       return do_load(cmdtp, flag, argc, argv, FS_TYPE_EXT, 16);
+       return do_load(cmdtp, flag, argc, argv, FS_TYPE_EXT);
 }
 
 U_BOOT_CMD(
@@ -47,6 +47,5 @@ U_BOOT_CMD(
        "load binary file from a Ext2 filesystem",
        "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
        "    - load binary file 'filename' from 'dev' on 'interface'\n"
-       "      to address 'addr' from ext2 filesystem.\n"
-       "      All numeric parameters are assumed to be hex."
+       "      to address 'addr' from ext2 filesystem."
 );
index 4a27cd9..8289d25 100644 (file)
@@ -45,7 +45,7 @@
 int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc,
                                                char *const argv[])
 {
-       return do_load(cmdtp, flag, argc, argv, FS_TYPE_EXT, 16);
+       return do_load(cmdtp, flag, argc, argv, FS_TYPE_EXT);
 }
 
 int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
@@ -122,5 +122,4 @@ U_BOOT_CMD(ext4load, 6, 0, do_ext4_load,
           "load binary file from a Ext4 filesystem",
           "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
           "    - load binary file 'filename' from 'dev' on 'interface'\n"
-          "      to address 'addr' from ext4 filesystem.\n"
-          "      All numeric parameters are assumed to be hex.");
+          "      to address 'addr' from ext4 filesystem");
index f6d7aff..a12d8fa 100644 (file)
@@ -19,7 +19,7 @@
 
 int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       return do_load(cmdtp, flag, argc, argv, FS_TYPE_FAT, 16);
+       return do_load(cmdtp, flag, argc, argv, FS_TYPE_FAT);
 }
 
 
@@ -35,8 +35,7 @@ U_BOOT_CMD(
        "      the load stops on end of file.\n"
        "      If either 'pos' or 'bytes' are not aligned to\n"
        "      ARCH_DMA_MINALIGN then a misaligned buffer warning will\n"
-       "      be printed and performance will suffer for the load.\n"
-       "      All numeric parameters are assumed to be hex."
+       "      be printed and performance will suffer for the load."
 );
 
 static int do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
index a681d03..91a205a 100644 (file)
@@ -22,7 +22,7 @@
 
 int do_load_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       return do_load(cmdtp, flag, argc, argv, FS_TYPE_ANY, 0);
+       return do_load(cmdtp, flag, argc, argv, FS_TYPE_ANY);
 }
 
 U_BOOT_CMD(
@@ -34,9 +34,7 @@ U_BOOT_CMD(
        "      'bytes' gives the size to load in bytes.\n"
        "      If 'bytes' is 0 or omitted, the file is read until the end.\n"
        "      'pos' gives the file byte position to start reading from.\n"
-       "      If 'pos' is 0 or omitted, the file is read from the start.\n"
-       "      All numeric parameters are assumed to be decimal,\n"
-       "      unless specified otherwise using a leading \"0x\"."
+       "      If 'pos' is 0 or omitted, the file is read from the start."
 );
 
 int do_ls_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
index 06767aa..a46f5cc 100644 (file)
@@ -161,7 +161,7 @@ static int set_gpt_info(block_dev_desc_t *dev_desc,
        /* allocate memory for partitions */
        parts = calloc(sizeof(disk_partition_t), p_count);
 
-       /* retrive partions data from string */
+       /* retrieve partitions data from string */
        for (i = 0; i < p_count; i++) {
                tok = strsep(&s, ";");
 
@@ -316,7 +316,7 @@ static int do_gpt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
        "GUID Partition Table",
-       "<command> <interface> <dev> <partions_list>\n"
+       "<command> <interface> <dev> <partitions_list>\n"
        " - GUID partition table restoration\n"
        " Restore GPT information on a device connected\n"
        " to interface\n"
index 1cdeb44..67a94a7 100644 (file)
@@ -260,7 +260,7 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                                if (!ret)
                                        mmc->part_num = part;
 
-                               printf("switch to partions #%d, %s\n",
+                               printf("switch to partitions #%d, %s\n",
                                                part, (!ret) ? "OK" : "ERROR");
                        }
                }
@@ -421,7 +421,7 @@ U_BOOT_CMD(
        "mmc close <dev> <boot_partition>\n"
        " - Enable boot_part for booting and disable access to boot_part\n"
        "mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n"
-       " - change sizes of boot and RPMB partions of specified device\n"
+       " - change sizes of boot and RPMB partitions of specified device\n"
 #endif
        );
 #endif /* !CONFIG_GENERIC_MMC */
index 3023479..f791372 100644 (file)
@@ -381,10 +381,9 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 
 
 /**
- * Performs sanity check for supplied partition. Offset and size are verified
- * to be within valid range. Partition type is checked and either
- * parts_validate_nor() or parts_validate_nand() is called with the argument
- * of part.
+ * Performs sanity check for supplied partition. Offset and size are
+ * verified to be within valid range. Partition type is checked and
+ * part_validate_eraseblock() is called with the argument of part.
  *
  * @param id of the parent device
  * @param part partition to validate
@@ -420,7 +419,7 @@ static int part_validate(struct mtdids *id, struct part_info *part)
 }
 
 /**
- * Delete selected partition from the partion list of the specified device.
+ * Delete selected partition from the partition list of the specified device.
  *
  * @param dev device to delete partition from
  * @param part partition to delete
index a2fb50a..c5f4a22 100644 (file)
@@ -572,7 +572,7 @@ static int label_localboot(struct pxe_label *label)
  * If the label specifies an 'append' line, its contents will overwrite that
  * of the 'bootargs' environment variable.
  */
-static int label_boot(struct pxe_label *label)
+static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
 {
        char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
        char initrd_str[22];
@@ -684,11 +684,11 @@ static int label_boot(struct pxe_label *label)
        if (bootm_argv[3])
                bootm_argc = 4;
 
-       do_bootm(NULL, 0, bootm_argc, bootm_argv);
+       do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
 
 #ifdef CONFIG_CMD_BOOTZ
        /* Try booting a zImage if do_bootm returns */
-       do_bootz(NULL, 0, bootm_argc, bootm_argv);
+       do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
 #endif
        return 1;
 }
@@ -1355,7 +1355,7 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
 /*
  * Try to boot any labels we have yet to attempt to boot.
  */
-static void boot_unattempted_labels(struct pxe_menu *cfg)
+static void boot_unattempted_labels(cmd_tbl_t *cmdtp, struct pxe_menu *cfg)
 {
        struct list_head *pos;
        struct pxe_label *label;
@@ -1364,7 +1364,7 @@ static void boot_unattempted_labels(struct pxe_menu *cfg)
                label = list_entry(pos, struct pxe_label, list);
 
                if (!label->attempted)
-                       label_boot(label);
+                       label_boot(cmdtp, label);
        }
 }
 
@@ -1380,7 +1380,7 @@ static void boot_unattempted_labels(struct pxe_menu *cfg)
  * If this function returns, there weren't any labels that successfully
  * booted, or the user interrupted the menu selection via ctrl+c.
  */
-static void handle_pxe_menu(struct pxe_menu *cfg)
+static void handle_pxe_menu(cmd_tbl_t *cmdtp, struct pxe_menu *cfg)
 {
        void *choice;
        struct menu *m;
@@ -1406,14 +1406,14 @@ static void handle_pxe_menu(struct pxe_menu *cfg)
         */
 
        if (err == 1) {
-               err = label_boot(choice);
+               err = label_boot(cmdtp, choice);
                if (!err)
                        return;
        } else if (err != -ENOENT) {
                return;
        }
 
-       boot_unattempted_labels(cfg);
+       boot_unattempted_labels(cmdtp, cfg);
 }
 
 /*
@@ -1453,7 +1453,7 @@ do_pxe_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                return 1;
        }
 
-       handle_pxe_menu(cfg);
+       handle_pxe_menu(cmdtp, cfg);
 
        destroy_pxe_menu(cfg);
 
@@ -1559,7 +1559,7 @@ int do_sysboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        if (prompt)
                cfg->prompt = 1;
 
-       handle_pxe_menu(cfg);
+       handle_pxe_menu(cmdtp, cfg);
 
        destroy_pxe_menu(cfg);
 
index 4af0f0a..3f60979 100644 (file)
@@ -152,8 +152,10 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
 {
        debug("offset=%#x, sector_size=%#x, len=%#zx\n",
              offset, flash->sector_size, len);
-       if (spi_flash_read(flash, offset, len, cmp_buf))
+       /* Read the entire sector so to allow for rewriting */
+       if (spi_flash_read(flash, offset, flash->sector_size, cmp_buf))
                return "read";
+       /* Compare only what is meaningful (len) */
        if (memcmp(cmp_buf, buf, len) == 0) {
                debug("Skip region %x size %zx: no change\n",
                      offset, len);
@@ -163,8 +165,17 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
        /* Erase the entire sector */
        if (spi_flash_erase(flash, offset, flash->sector_size))
                return "erase";
+       /* Write the initial part of the block from the source */
        if (spi_flash_write(flash, offset, len, buf))
                return "write";
+       /* If it's a partial sector, rewrite the existing part */
+       if (len != flash->sector_size) {
+               /* Rewrite the original data to the end of the sector */
+               if (spi_flash_write(flash, offset + len,
+                                   flash->sector_size - len, &cmp_buf[len]))
+                       return "write";
+       }
+
        return NULL;
 }
 
index 33a4715..ccf7195 100644 (file)
@@ -5,7 +5,6 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
-#include <errno.h>
 #include <common.h>
 #include <command.h>
 #include <g_dnl.h>
index 2e22cca..6f9ce7d 100644 (file)
@@ -55,7 +55,7 @@ static const image_header_t *image_get_fdt(ulong fdt_addr)
                fdt_error("uImage is compressed");
                return NULL;
        }
-       if (fdt_check_header((char *)image_get_data(fdt_hdr)) != 0) {
+       if (fdt_check_header((void *)image_get_data(fdt_hdr)) != 0) {
                fdt_error("uImage data is not a fdt");
                return NULL;
        }
index 199b4ed..cf4b67e 100644 (file)
@@ -58,7 +58,7 @@ static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
  * @conf_name double pointer to a char, will hold pointer to a configuration
  * unit name
  *
- * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
+ * fit_parse_conf() expects configuration spec in the form of [<addr>]#<conf>,
  * where <addr> is a FIT image address that contains configuration
  * with a <conf> unit name.
  *
@@ -84,7 +84,7 @@ int fit_parse_conf(const char *spec, ulong addr_curr,
  * subimage
  * @image_name: double pointer to a char, will hold pointer to a subimage name
  *
- * fit_parse_subimage() expects subimage spec in the for of
+ * fit_parse_subimage() expects subimage spec in the form of
  * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
  * subimage with a <subimg> unit name.
  *
@@ -1331,7 +1331,7 @@ int fit_conf_find_compat(const void *fit, const void *fdt)
  *
  * When NULL is provided in second argument fit_conf_get_node() will search
  * for a default configuration node instead. Default configuration node unit
- * name is retrived from FIT_DEFAULT_PROP property of the '/configurations'
+ * name is retrieved from FIT_DEFAULT_PROP property of the '/configurations'
  * node.
  *
  * returns:
@@ -1596,7 +1596,7 @@ int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr,
        len = (ulong)size;
 
        /* verify that image data is a proper FDT blob */
-       if (image_type == IH_TYPE_FLATDT && fdt_check_header((char *)buf)) {
+       if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
                puts("Subimage data is not a FDT");
                return -ENOEXEC;
        }
index 2c88091..b0ae58f 100644 (file)
@@ -652,17 +652,13 @@ int genimg_get_format(const void *img_addr)
 {
        ulong format = IMAGE_FORMAT_INVALID;
        const image_header_t *hdr;
-#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
-       char *fit_hdr;
-#endif
 
        hdr = (const image_header_t *)img_addr;
        if (image_check_magic(hdr))
                format = IMAGE_FORMAT_LEGACY;
 #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
        else {
-               fit_hdr = (char *)img_addr;
-               if (fdt_check_header(fit_hdr) == 0)
+               if (fdt_check_header(img_addr) == 0)
                        format = IMAGE_FORMAT_FIT;
        }
 #endif
@@ -965,7 +961,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
  * @initrd_end: pointer to a ulong variable, will hold final init ramdisk
  *      end address (after possible relocation)
  *
- * boot_ramdisk_high() takes a relocation hint from "initrd_high" environement
+ * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment
  * variable and if requested ramdisk data is moved to a specified location.
  *
  * Initrd_start and initrd_end are set to final (after relocation) ramdisk
index f27b4c2..fc2f226 100644 (file)
@@ -9,7 +9,6 @@
 #include <common.h>
 #include <spl.h>
 #include <asm/u-boot.h>
-#include <asm/utils.h>
 #include <mmc.h>
 #include <fat.h>
 #include <version.h>
@@ -45,8 +44,10 @@ static int mmc_load_image_raw(struct mmc *mmc, unsigned long sector)
                                        (void *)spl_image.load_addr);
 
 end:
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
        if (err == 0)
                printf("spl: mmc blk read err - %lu\n", err);
+#endif
 
        return (err == 0);
 }
@@ -58,7 +59,9 @@ static int mmc_load_image_raw_os(struct mmc *mmc)
                                       CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
                                       CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
                                       (void *)CONFIG_SYS_SPL_ARGS_ADDR)) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                printf("mmc args blk read error\n");
+#endif
                return -1;
        }
 
@@ -84,9 +87,11 @@ static int mmc_load_image_fat(struct mmc *mmc, const char *filename)
        err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0);
 
 end:
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
        if (err <= 0)
                printf("spl: error reading image %s, err - %d\n",
                       filename, err);
+#endif
 
        return (err <= 0);
 }
@@ -99,8 +104,10 @@ static int mmc_load_image_fat_os(struct mmc *mmc)
        err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME,
                            (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0);
        if (err <= 0) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                printf("spl: error reading image %s, err - %d\n",
                       CONFIG_SPL_FAT_LOAD_ARGS_NAME, err);
+#endif
                return -1;
        }
 
@@ -120,13 +127,17 @@ void spl_mmc_load_image(void)
        /* We register only one device. So, the dev id is always 0 */
        mmc = find_mmc_device(0);
        if (!mmc) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                puts("spl: mmc device not found!!\n");
+#endif
                hang();
        }
 
        err = mmc_init(mmc);
        if (err) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                printf("spl: mmc init failed: err - %d\n", err);
+#endif
                hang();
        }
 
@@ -145,7 +156,9 @@ void spl_mmc_load_image(void)
                err = fat_register_device(&mmc->block_dev,
                                          CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION);
                if (err) {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                        printf("spl: fat register err - %d\n", err);
+#endif
                        hang();
                }
 
@@ -155,7 +168,9 @@ void spl_mmc_load_image(void)
                err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
 #endif
        } else {
+#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
                puts("spl: wrong MMC boot mode\n");
+#endif
                hang();
        }
 
index b7524d6..9c33ae7 100644 (file)
@@ -164,8 +164,9 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
 
        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",
+               debug("%s: *** ERROR: Invalid partition number %d ***\n",
                        __func__, part);
+               free(gpt_pte);
                return -1;
        }
 
index 5018ae8..09788d5 100644 (file)
@@ -1,6 +1,6 @@
 JFFS2 NAND support:
 
-To ebable, use the following #define in the board configuration file:
+To enable, use the following #define in the board configuration file:
 
 #define CONFIG_JFFS2_NAND 1
 
index cf54965..b6ddb43 100644 (file)
@@ -18,7 +18,7 @@ Current implementation details/limitations:
    U-Boot. But I haven't bothered yet.
 
 2. Since we don't implement a hwconfig command, i.e. we're working
-   with the environement directly, there is no way to tell that
+   with the environment directly, there is no way to tell that
    toggling a particular option will need a reboot to take
    effect. So, for now it's advised to always reboot the
    target after modifying the hwconfig variable.
diff --git a/doc/SPI/README.ti_qspi_dra_test b/doc/SPI/README.ti_qspi_dra_test
new file mode 100644 (file)
index 0000000..fe37857
--- /dev/null
@@ -0,0 +1,48 @@
+-------------------------------------------------
+   Simple steps used to test the QSPI at U-Boot
+-------------------------------------------------
+
+For #1, build the patched U-Boot and load MLO/u-boot.img
+
+----------------------------------
+Boot from another medium like MMC
+----------------------------------
+
+U-Boot# mmc dev 0
+mmc0 is current device
+U-Boot# fatload mmc 0 0x82000000 MLO
+reading MLO
+55872 bytes read in 8 ms (6.7 MiB/s)
+U-Boot# fatload mmc 0 0x83000000 u-boot.img
+reading u-boot.img
+248600 bytes read in 19 ms (12.5 MiB/s)
+
+--------------------------------------------------
+Commands to erase/write u-boot/mlo to flash device
+--------------------------------------------------
+U-Boot# sf probe 0
+SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB, mapped at 5c000000
+SF: Warning - Only lower 16MiB accessible, Full access #define CONFIG_SPI_FLASH_BAR
+U-Boot# sf erase 0 0x10000
+SF: 65536 bytes @ 0x0 Erased: OK
+U-Boot# sf erase 0x20000 0x10000
+SF: 65536 bytes @ 0x20000 Erased: OK
+U-Boot# sf erase 0x30000 0x10000
+SF: 65536 bytes @ 0x30000 Erased: OK
+U-Boot# sf erase 0x40000 0x10000
+SF: 65536 bytes @ 0x40000 Erased: OK
+U-Boot# sf erase 0x50000 0x10000
+SF: 65536 bytes @ 0x50000 Erased: OK
+U-Boot# sf erase 0x60000 0x10000
+SF: 65536 bytes @ 0x60000 Erased: OK
+U-Boot# sf write 82000000 0 0x10000
+SF: 65536 bytes @ 0x0 Written: OK
+U-Boot# sf write 83000000 0x20000 0x60000
+SF: 393216 bytes @ 0x20000 Written: OK
+
+For #2, set sysboot to QSPI-1 boot mode(SYSBOOT[5:0] = 100110) and power
+on. ROM should find the GP header at offset 0 and load/execute SPL. SPL
+then detects that ROM was in QSPI-1 mode (boot code 10) and attempts to
+find a U-Boot image header at offset 0x20000 (set in the config file)
+and proceeds to load that image using the U-Boot image payload offset/size
+from the header. It will then start U-Boot.
diff --git a/doc/SPI/README.ti_qspi_flash b/doc/SPI/README.ti_qspi_flash
new file mode 100644 (file)
index 0000000..1b86d01
--- /dev/null
@@ -0,0 +1,47 @@
+QSPI U-boot support
+------------------
+
+Host processor is connected to serial flash device via qpsi
+interface. QSPI is a kind of spi module that allows single,
+dual and quad read access to external spi devices. The module
+has a memory mapped interface which provide direct interface
+for accessing data form external spi devices.
+
+The one QSPI in the device is primarily intended for fast booting
+from Quad SPI flash devices.
+
+Usecase
+-------
+
+MLO/u-boot.img will be flashed from SD/MMC to the flash device
+using serial flash erase and write commands. Then, switch settings
+will be changed to qspi boot. Then, the ROM code will read MLO
+from the predefined location in the flash, where it was flashed and
+execute it after storing it in SDRAM. Then, the MLO will read
+u-boot.img from flash and execute it from SDRAM.
+
+SPI mode
+-------
+SPI mode uses mtd spi framework for transfer and reception of data.
+Can be used in:
+1. Normal mode: use single pin for transfers
+2. Dual Mode: use two pins for transfers.
+3. Quad mode: use four pin for transfer
+
+Memory mapped read mode
+-----------------------
+In this, SPI controller is configured using configuration port and then
+controler is switched to memory mapped port for data read.
+
+Driver
+------
+drivers/qspi/ti_qspi.c
+    - Newly created file which is responsible for configuring the
+       qspi controller and also for providing the low level api which
+       is responsible for transferring the datas from host controller
+       to flash device and vice versa.
+
+Testing
+-------
+A seperated file named README.dra_qspi_test has been created which gives all the
+details about the commands required to test qspi at u-boot level.
diff --git a/doc/SPI/status.txt b/doc/SPI/status.txt
new file mode 100644 (file)
index 0000000..62c3c85
--- /dev/null
@@ -0,0 +1,31 @@
+Status on SPI subsystem:
+=======================
+
+SPI COMMAND (common/cmd_sf, cmd_spi):
+-
+
+SPI FLASH (drivers/mtd/spi):
+- sf_probe.c: SPI flash probing code.
+- sf_ops.c: SPI flash operations code.
+- sf.c: SPI flash interface, which interacts controller driver.
+- Bank Address Register (Accessing flashes > 16Mbytes in 3-byte addressing)
+- Added memory_mapped support for read operations.
+- Common probe support for all supported flash vendors except, ramtron.
+
+SPI DRIVERS (drivers/spi):
+-
+
+TODO:
+- Runtime detection of spi_flash params, SFDP(if possible)
+- Add support for multibus build/accessing.
+- Extended read commands support(dual read, dual IO read)
+- Quad Page Program support.
+- Quad Read support(quad fast read, quad IO read)
+- Dual flash connection topology support(accessing two spi flash memories with single cs)
+- Banking support on dual flash connection topology.
+- Need proper cleanups on spi_flash and drivers.
+
+--
+Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
+18-09-2013.
+07-10-2013.
index 2cacaa0..251586e 100644 (file)
@@ -18,6 +18,7 @@ alias galak          Kumar Gala <galak@kernel.crashing.org>
 alias gruss          Graeme Russ <graeme.russ@gmail.com>
 alias hs             Heiko Schocher <hs@denx.de>
 alias iwamatsu       Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+alias jagan         Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
 alias jasonjin       Jason Jin <jason.jin@freescale.com>
 alias jhersh         Joe Hershberger <joe.hershberger@gmail.com>
 alias kimphill       Kim Phillips <kim.phillips@freescale.com>
@@ -106,5 +107,6 @@ alias i2c            uboot, hs
 alias mmc            uboot, panto
 alias nand           uboot, scottwood
 alias net            uboot, jhersh
+alias spi           uboot, jagan
 alias usb            uboot, marex
 alias video          uboot, ag
index 002818c..6c99b1c 100644 (file)
@@ -170,7 +170,7 @@ bootm 200000
 
 In case of the new uImage argument syntax, the address portion of any argument
 can be omitted. If <addr3> is omitted, then it is assumed that image at
-<addr2> should be used. Similarly, when <addr2> is omitted, is is assumed that
+<addr2> should be used. Similarly, when <addr2> is omitted, it is assumed that
 image at <addr1> should be used. If <addr1> is omitted, it is assumed that the
 current image address is to be used. For example, consider the following
 commands:
index 6d20707..160b2d0 100644 (file)
@@ -62,7 +62,7 @@ c) Image building procedure
 The following picture shows how the new uImage is prepared. Input consists of
 image source file (.its) and a set of data files. Image is created with the
 help of standard U-boot mkimage tool which in turn uses dtc (device tree
-compiler) to produce image tree blob (.itb).  Resulting .itb file is is the
+compiler) to produce image tree blob (.itb).  Resulting .itb file is the
 actual binary of a new uImage.
 
 
index c538e37..6f1ac85 100644 (file)
@@ -248,7 +248,7 @@ void scsi_print_error (ccb * pccb)
 
 /******************************************************************************
  * sets-up the SCSI controller
- * the base memory address is retrived via the pci_read_config_dword
+ * the base memory address is retrieved via the pci_read_config_dword
  */
 void scsi_low_level_init(int busdevfunc)
 {
index fca370a..de9e44e 100644 (file)
@@ -12,6 +12,7 @@ LIB   = $(obj)libdfu.o
 COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
 COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
 COBJS-$(CONFIG_DFU_NAND) += dfu_nand.o
+COBJS-$(CONFIG_DFU_RAM) += dfu_ram.o
 
 SRCS    := $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y))
index d73d510..56b21c7 100644 (file)
@@ -41,6 +41,29 @@ static int dfu_find_alt_num(const char *s)
        return ++i;
 }
 
+int dfu_init_env_entities(char *interface, int dev)
+{
+       const char *str_env;
+       char *env_bkp;
+       int ret;
+
+       str_env = getenv("dfu_alt_info");
+       if (!str_env) {
+               error("\"dfu_alt_info\" env variable not defined!\n");
+               return -EINVAL;
+       }
+
+       env_bkp = strdup(str_env);
+       ret = dfu_config_entities(env_bkp, interface, dev);
+       if (ret) {
+               error("DFU entities configuration failed!\n");
+               return ret;
+       }
+
+       free(env_bkp);
+       return 0;
+}
+
 static unsigned char *dfu_buf;
 static unsigned long dfu_buf_size = CONFIG_SYS_DFU_DATA_BUF_SIZE;
 
@@ -153,8 +176,8 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
 
        /* we should be in buffer now (if not then size too large) */
        if ((dfu->i_buf + size) > dfu->i_buf_end) {
-               printf("%s: Wrong size! [%d] [%d] - %d\n",
-                      __func__, dfu->i_blk_seq_num, blk_seq_num, size);
+               error("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf,
+                     size, dfu->i_buf_end);
                return -1;
        }
 
@@ -325,6 +348,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
        } else if (strcmp(interface, "nand") == 0) {
                if (dfu_fill_entity_nand(dfu, s))
                        return -1;
+       } else if (strcmp(interface, "ram") == 0) {
+               if (dfu_fill_entity_ram(dfu, s))
+                       return -1;
        } else {
                printf("%s: Device %s not (yet) supported!\n",
                       __func__,  interface);
@@ -374,14 +400,14 @@ int dfu_config_entities(char *env, char *interface, int num)
 
 const char *dfu_get_dev_type(enum dfu_device_type t)
 {
-       const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND" };
+       const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM" };
        return dev_t[t];
 }
 
 const char *dfu_get_layout(enum dfu_layout l)
 {
        const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2",
-                                          "EXT3", "EXT4" };
+                                          "EXT3", "EXT4", "RAM_ADDR" };
        return dfu_layout[l];
 }
 
index 0871a77..f942758 100644 (file)
 #include <div64.h>
 #include <dfu.h>
 
-enum dfu_mmc_op {
-       DFU_OP_READ = 1,
-       DFU_OP_WRITE,
-};
-
 static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
                                dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE];
 static long dfu_file_buf_len;
 
-static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
+static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
                        u64 offset, void *buf, long *len)
 {
        char cmd_buf[DFU_CMD_BUF_SIZE];
@@ -65,7 +60,7 @@ static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len)
        return 0;
 }
 
-static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
+static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
                        void *buf, long *len)
 {
        char cmd_buf[DFU_CMD_BUF_SIZE];
index 0ec12cf..edbf5a9 100644 (file)
 #include <jffs2/load_kernel.h>
 #include <nand.h>
 
-enum dfu_nand_op {
-       DFU_OP_READ = 1,
-       DFU_OP_WRITE,
-};
-
-static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,
+static int nand_block_op(enum dfu_op op, struct dfu_entity *dfu,
                        u64 offset, void *buf, long *len)
 {
        loff_t start, lim;
diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c
new file mode 100644 (file)
index 0000000..335a8e1
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2013
+ * Afzal Mohammed <afzal.mohd.ma@gmail.com>
+ *
+ * Reference: dfu_mmc.c
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <dfu.h>
+
+static int dfu_transfer_medium_ram(enum dfu_op op, struct dfu_entity *dfu,
+                                  u64 offset, void *buf, long *len)
+{
+       if (dfu->layout != DFU_RAM_ADDR) {
+               error("unsupported layout: %s\n", dfu_get_layout(dfu->layout));
+               return  -EINVAL;
+       }
+
+       if (offset > dfu->data.ram.size) {
+               error("request exceeds allowed area\n");
+               return -EINVAL;
+       }
+
+       if (op == DFU_OP_WRITE)
+               memcpy(dfu->data.ram.start + offset, buf, *len);
+       else
+               memcpy(buf, dfu->data.ram.start + offset, *len);
+
+       return 0;
+}
+
+static int dfu_write_medium_ram(struct dfu_entity *dfu, u64 offset,
+                               void *buf, long *len)
+{
+       return dfu_transfer_medium_ram(DFU_OP_WRITE, dfu, offset, buf, len);
+}
+
+static int dfu_read_medium_ram(struct dfu_entity *dfu, u64 offset,
+                              void *buf, long *len)
+{
+       if (!*len) {
+               *len = dfu->data.ram.size;
+               return 0;
+       }
+
+       return dfu_transfer_medium_ram(DFU_OP_READ, dfu, offset, buf, len);
+}
+
+int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s)
+{
+       char *st;
+
+       dfu->dev_type = DFU_DEV_RAM;
+       st = strsep(&s, " ");
+       if (strcmp(st, "ram")) {
+               error("unsupported device: %s\n", st);
+               return -ENODEV;
+       }
+
+       dfu->layout = DFU_RAM_ADDR;
+       dfu->data.ram.start = (void *)simple_strtoul(s, &s, 16);
+       s++;
+       dfu->data.ram.size = simple_strtoul(s, &s, 16);
+
+       dfu->write_medium = dfu_write_medium_ram;
+       dfu->read_medium = dfu_read_medium_ram;
+
+       dfu->inited = 0;
+
+       return 0;
+}
index bedf833..06280d1 100644 (file)
@@ -34,6 +34,8 @@ COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
 COBJS-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
 ifdef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
+else
+COBJS-$(CONFIG_GENERIC_MMC) += mmc_write.o
 endif
 
 COBJS  := $(COBJS-y)
index a82ee17..9a803a0 100644 (file)
@@ -41,12 +41,11 @@ static void dwmci_set_idma_desc(struct dwmci_idmac *idmac,
 }
 
 static void dwmci_prepare_data(struct dwmci_host *host,
-               struct mmc_data *data)
+               struct mmc_data *data, struct dwmci_idmac *cur_idmac)
 {
        unsigned long ctrl;
        unsigned int i = 0, flags, cnt, blk_cnt;
        ulong data_start, data_end, start_addr;
-       ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, data->blocks);
 
 
        blk_cnt = data->blocks;
@@ -73,7 +72,7 @@ static void dwmci_prepare_data(struct dwmci_host *host,
                dwmci_set_idma_desc(cur_idmac, flags, cnt,
                                start_addr + (i * PAGE_SIZE));
 
-               if(blk_cnt < 8)
+               if (blk_cnt <= 8)
                        break;
                blk_cnt -= 8;
                cur_idmac++;
@@ -111,6 +110,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
                struct mmc_data *data)
 {
        struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
+       ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
+                                data ? DIV_ROUND_UP(data->blocks, 8) : 0);
        int flags = 0, i;
        unsigned int timeout = 100000;
        u32 retry = 10000;
@@ -127,7 +128,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
 
        if (data)
-               dwmci_prepare_data(host, data);
+               dwmci_prepare_data(host, data, cur_idmac);
 
        dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
index 5502675..84dae4d 100644 (file)
@@ -15,6 +15,7 @@
 #include <malloc.h>
 #include <linux/list.h>
 #include <div64.h>
+#include "mmc_private.h"
 
 /* Set block count limit because of 16 bit register limit on some hardware*/
 #ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
@@ -52,14 +53,10 @@ int __board_mmc_getcd(struct mmc *mmc) {
 int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
        alias("__board_mmc_getcd")));
 
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
-                       struct mmc_data *data)
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
-       struct mmc_data backup;
        int ret;
 
-       memset(&backup, 0, sizeof(backup));
-
 #ifdef CONFIG_MMC_TRACE
        int i;
        u8 *ptr;
@@ -114,7 +111,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        return ret;
 }
 
-static int mmc_send_status(struct mmc *mmc, int timeout)
+int mmc_send_status(struct mmc *mmc, int timeout)
 {
        struct mmc_cmd cmd;
        int err, retries = 5;
@@ -135,8 +132,10 @@ static int mmc_send_status(struct mmc *mmc, int timeout)
                             MMC_STATE_PRG)
                                break;
                        else if (cmd.response[0] & MMC_STATUS_MASK) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                                printf("Status Error: 0x%08X\n",
                                        cmd.response[0]);
+#endif
                                return COMM_ERR;
                        }
                } else if (--retries < 0)
@@ -151,14 +150,16 @@ static int mmc_send_status(struct mmc *mmc, int timeout)
        printf("CURR STATE:%d\n", status);
 #endif
        if (timeout <= 0) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                printf("Timeout waiting card ready\n");
+#endif
                return TIMEOUT;
        }
 
        return 0;
 }
 
-static int mmc_set_blocklen(struct mmc *mmc, int len)
+int mmc_set_blocklen(struct mmc *mmc, int len)
 {
        struct mmc_cmd cmd;
 
@@ -181,179 +182,13 @@ struct mmc *find_mmc_device(int dev_num)
                        return m;
        }
 
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
        printf("MMC Device %d not found\n", dev_num);
+#endif
 
        return NULL;
 }
 
-static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
-{
-       struct mmc_cmd cmd;
-       ulong end;
-       int err, start_cmd, end_cmd;
-
-       if (mmc->high_capacity)
-               end = start + blkcnt - 1;
-       else {
-               end = (start + blkcnt - 1) * mmc->write_bl_len;
-               start *= mmc->write_bl_len;
-       }
-
-       if (IS_SD(mmc)) {
-               start_cmd = SD_CMD_ERASE_WR_BLK_START;
-               end_cmd = SD_CMD_ERASE_WR_BLK_END;
-       } else {
-               start_cmd = MMC_CMD_ERASE_GROUP_START;
-               end_cmd = MMC_CMD_ERASE_GROUP_END;
-       }
-
-       cmd.cmdidx = start_cmd;
-       cmd.cmdarg = start;
-       cmd.resp_type = MMC_RSP_R1;
-
-       err = mmc_send_cmd(mmc, &cmd, NULL);
-       if (err)
-               goto err_out;
-
-       cmd.cmdidx = end_cmd;
-       cmd.cmdarg = end;
-
-       err = mmc_send_cmd(mmc, &cmd, NULL);
-       if (err)
-               goto err_out;
-
-       cmd.cmdidx = MMC_CMD_ERASE;
-       cmd.cmdarg = SECURE_ERASE;
-       cmd.resp_type = MMC_RSP_R1b;
-
-       err = mmc_send_cmd(mmc, &cmd, NULL);
-       if (err)
-               goto err_out;
-
-       return 0;
-
-err_out:
-       puts("mmc erase failed\n");
-       return err;
-}
-
-static unsigned long
-mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
-{
-       int err = 0;
-       struct mmc *mmc = find_mmc_device(dev_num);
-       lbaint_t blk = 0, blk_r = 0;
-       int timeout = 1000;
-
-       if (!mmc)
-               return -1;
-
-       if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
-               printf("\n\nCaution! Your devices Erase group is 0x%x\n"
-                      "The erase range would be change to "
-                      "0x" LBAF "~0x" LBAF "\n\n",
-                      mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
-                      ((start + blkcnt + mmc->erase_grp_size)
-                      & ~(mmc->erase_grp_size - 1)) - 1);
-
-       while (blk < blkcnt) {
-               blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
-                       mmc->erase_grp_size : (blkcnt - blk);
-               err = mmc_erase_t(mmc, start + blk, blk_r);
-               if (err)
-                       break;
-
-               blk += blk_r;
-
-               /* Waiting for the ready status */
-               if (mmc_send_status(mmc, timeout))
-                       return 0;
-       }
-
-       return blk;
-}
-
-static ulong
-mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
-{
-       struct mmc_cmd cmd;
-       struct mmc_data data;
-       int timeout = 1000;
-
-       if ((start + blkcnt) > mmc->block_dev.lba) {
-               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
-                       start + blkcnt, mmc->block_dev.lba);
-               return 0;
-       }
-
-       if (blkcnt == 0)
-               return 0;
-       else if (blkcnt == 1)
-               cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
-       else
-               cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
-
-       if (mmc->high_capacity)
-               cmd.cmdarg = start;
-       else
-               cmd.cmdarg = start * mmc->write_bl_len;
-
-       cmd.resp_type = MMC_RSP_R1;
-
-       data.src = src;
-       data.blocks = blkcnt;
-       data.blocksize = mmc->write_bl_len;
-       data.flags = MMC_DATA_WRITE;
-
-       if (mmc_send_cmd(mmc, &cmd, &data)) {
-               printf("mmc write failed\n");
-               return 0;
-       }
-
-       /* SPI multiblock writes terminate using a special
-        * token, not a STOP_TRANSMISSION request.
-        */
-       if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
-               cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
-               cmd.cmdarg = 0;
-               cmd.resp_type = MMC_RSP_R1b;
-               if (mmc_send_cmd(mmc, &cmd, NULL)) {
-                       printf("mmc fail to send stop cmd\n");
-                       return 0;
-               }
-       }
-
-       /* Waiting for the ready status */
-       if (mmc_send_status(mmc, timeout))
-               return 0;
-
-       return blkcnt;
-}
-
-static ulong
-mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
-{
-       lbaint_t cur, blocks_todo = blkcnt;
-
-       struct mmc *mmc = find_mmc_device(dev_num);
-       if (!mmc)
-               return 0;
-
-       if (mmc_set_blocklen(mmc, mmc->write_bl_len))
-               return 0;
-
-       do {
-               cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
-               if(mmc_write_blocks(mmc, start, cur, src) != cur)
-                       return 0;
-               blocks_todo -= cur;
-               start += cur;
-               src += cur * mmc->write_bl_len;
-       } while (blocks_todo > 0);
-
-       return blkcnt;
-}
-
 static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
                           lbaint_t blkcnt)
 {
@@ -385,7 +220,9 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
                cmd.cmdarg = 0;
                cmd.resp_type = MMC_RSP_R1b;
                if (mmc_send_cmd(mmc, &cmd, NULL)) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                        printf("mmc fail to send stop cmd\n");
+#endif
                        return 0;
                }
        }
@@ -405,8 +242,10 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
                return 0;
 
        if ((start + blkcnt) > mmc->block_dev.lba) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
                        start + blkcnt, mmc->block_dev.lba);
+#endif
                return 0;
        }
 
@@ -1268,6 +1107,7 @@ static int mmc_startup(struct mmc *mmc)
        mmc->block_dev.blksz = mmc->read_bl_len;
        mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
        mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
        sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
                mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
                (mmc->cid[3] >> 16) & 0xffff);
@@ -1277,6 +1117,11 @@ static int mmc_startup(struct mmc *mmc)
                (mmc->cid[2] >> 24) & 0xff);
        sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
                (mmc->cid[2] >> 16) & 0xf);
+#else
+       mmc->block_dev.vendor[0] = 0;
+       mmc->block_dev.product[0] = 0;
+       mmc->block_dev.revision[0] = 0;
+#endif
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
        init_part(&mmc->block_dev);
 #endif
@@ -1343,7 +1188,9 @@ int mmc_start_init(struct mmc *mmc)
 
        if (mmc_getcd(mmc) == 0) {
                mmc->has_init = 0;
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                printf("MMC: no card present\n");
+#endif
                return NO_CARD_ERR;
        }
 
@@ -1378,7 +1225,9 @@ int mmc_start_init(struct mmc *mmc)
                err = mmc_send_op_cond(mmc);
 
                if (err && err != IN_PROGRESS) {
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
                        printf("Card did not respond to voltage select!\n");
+#endif
                        return UNUSABLE_ERR;
                }
        }
@@ -1434,6 +1283,8 @@ static int __def_mmc_init(bd_t *bis)
 int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
 int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
 
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
+
 void print_mmc_devices(char separator)
 {
        struct mmc *m;
@@ -1451,6 +1302,10 @@ void print_mmc_devices(char separator)
        printf("\n");
 }
 
+#else
+void print_mmc_devices(char separator) { }
+#endif
+
 int get_mmc_num(void)
 {
        return cur_dev_num;
diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
new file mode 100644 (file)
index 0000000..16dcf9f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008,2010 Freescale Semiconductor, Inc
+ * Andy Fleming
+ *
+ * Based (loosely) on the Linux code
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _MMC_PRIVATE_H_
+#define _MMC_PRIVATE_H_
+
+#include <mmc.h>
+
+extern int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+                       struct mmc_data *data);
+extern int mmc_send_status(struct mmc *mmc, int timeout);
+extern int mmc_set_blocklen(struct mmc *mmc, int len);
+
+#ifndef CONFIG_SPL_BUILD
+
+extern unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt);
+
+extern ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt,
+               const void *src);
+
+#else /* CONFIG_SPL_BUILD */
+
+/* SPL will never write or erase, declare dummies to reduce code size. */
+
+static inline unsigned long mmc_berase(int dev_num, lbaint_t start,
+               lbaint_t blkcnt)
+{
+       return 0;
+}
+
+static inline ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt,
+               const void *src)
+{
+       return 0;
+}
+
+#endif /* CONFIG_SPL_BUILD */
+
+#endif /* _MMC_PRIVATE_H_ */
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
new file mode 100644 (file)
index 0000000..aa2fdef
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2008, Freescale Semiconductor, Inc
+ * Andy Fleming
+ *
+ * Based vaguely on the Linux code
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <part.h>
+#include "mmc_private.h"
+
+static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
+{
+       struct mmc_cmd cmd;
+       ulong end;
+       int err, start_cmd, end_cmd;
+
+       if (mmc->high_capacity) {
+               end = start + blkcnt - 1;
+       } else {
+               end = (start + blkcnt - 1) * mmc->write_bl_len;
+               start *= mmc->write_bl_len;
+       }
+
+       if (IS_SD(mmc)) {
+               start_cmd = SD_CMD_ERASE_WR_BLK_START;
+               end_cmd = SD_CMD_ERASE_WR_BLK_END;
+       } else {
+               start_cmd = MMC_CMD_ERASE_GROUP_START;
+               end_cmd = MMC_CMD_ERASE_GROUP_END;
+       }
+
+       cmd.cmdidx = start_cmd;
+       cmd.cmdarg = start;
+       cmd.resp_type = MMC_RSP_R1;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err)
+               goto err_out;
+
+       cmd.cmdidx = end_cmd;
+       cmd.cmdarg = end;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err)
+               goto err_out;
+
+       cmd.cmdidx = MMC_CMD_ERASE;
+       cmd.cmdarg = SECURE_ERASE;
+       cmd.resp_type = MMC_RSP_R1b;
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err)
+               goto err_out;
+
+       return 0;
+
+err_out:
+       puts("mmc erase failed\n");
+       return err;
+}
+
+unsigned long mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
+{
+       int err = 0;
+       struct mmc *mmc = find_mmc_device(dev_num);
+       lbaint_t blk = 0, blk_r = 0;
+       int timeout = 1000;
+
+       if (!mmc)
+               return -1;
+
+       if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
+               printf("\n\nCaution! Your devices Erase group is 0x%x\n"
+                      "The erase range would be change to "
+                      "0x" LBAF "~0x" LBAF "\n\n",
+                      mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
+                      ((start + blkcnt + mmc->erase_grp_size)
+                      & ~(mmc->erase_grp_size - 1)) - 1);
+
+       while (blk < blkcnt) {
+               blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
+                       mmc->erase_grp_size : (blkcnt - blk);
+               err = mmc_erase_t(mmc, start + blk, blk_r);
+               if (err)
+                       break;
+
+               blk += blk_r;
+
+               /* Waiting for the ready status */
+               if (mmc_send_status(mmc, timeout))
+                       return 0;
+       }
+
+       return blk;
+}
+
+static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
+               lbaint_t blkcnt, const void *src)
+{
+       struct mmc_cmd cmd;
+       struct mmc_data data;
+       int timeout = 1000;
+
+       if ((start + blkcnt) > mmc->block_dev.lba) {
+               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
+                      start + blkcnt, mmc->block_dev.lba);
+               return 0;
+       }
+
+       if (blkcnt == 0)
+               return 0;
+       else if (blkcnt == 1)
+               cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
+       else
+               cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
+
+       if (mmc->high_capacity)
+               cmd.cmdarg = start;
+       else
+               cmd.cmdarg = start * mmc->write_bl_len;
+
+       cmd.resp_type = MMC_RSP_R1;
+
+       data.src = src;
+       data.blocks = blkcnt;
+       data.blocksize = mmc->write_bl_len;
+       data.flags = MMC_DATA_WRITE;
+
+       if (mmc_send_cmd(mmc, &cmd, &data)) {
+               printf("mmc write failed\n");
+               return 0;
+       }
+
+       /* SPI multiblock writes terminate using a special
+        * token, not a STOP_TRANSMISSION request.
+        */
+       if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
+               cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
+               cmd.cmdarg = 0;
+               cmd.resp_type = MMC_RSP_R1b;
+               if (mmc_send_cmd(mmc, &cmd, NULL)) {
+                       printf("mmc fail to send stop cmd\n");
+                       return 0;
+               }
+       }
+
+       /* Waiting for the ready status */
+       if (mmc_send_status(mmc, timeout))
+               return 0;
+
+       return blkcnt;
+}
+
+ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src)
+{
+       lbaint_t cur, blocks_todo = blkcnt;
+
+       struct mmc *mmc = find_mmc_device(dev_num);
+       if (!mmc)
+               return 0;
+
+       if (mmc_set_blocklen(mmc, mmc->write_bl_len))
+               return 0;
+
+       do {
+               cur = (blocks_todo > mmc->b_max) ?  mmc->b_max : blocks_todo;
+               if (mmc_write_blocks(mmc, start, cur, src) != cur)
+                       return 0;
+               blocks_todo -= cur;
+               start += cur;
+               src += cur * mmc->write_bl_len;
+       } while (blocks_todo > 0);
+
+       return blkcnt;
+}
index 975b2c5..d3a8b53 100644 (file)
@@ -288,6 +288,30 @@ static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit)
 
        mmc_reg_out(&mmc_base->sysctl, bit, bit);
 
+       /*
+        * CMD(DAT) lines reset procedures are slightly different
+        * for OMAP3 and OMAP4(AM335x,OMAP5,DRA7xx).
+        * According to OMAP3 TRM:
+        * Set SRC(SRD) bit in MMCHS_SYSCTL register to 0x1 and wait until it
+        * returns to 0x0.
+        * According to OMAP4(AM335x,OMAP5,DRA7xx) TRMs, CMD(DATA) lines reset
+        * procedure steps must be as follows:
+        * 1. Initiate CMD(DAT) line reset by writing 0x1 to SRC(SRD) bit in
+        *    MMCHS_SYSCTL register (SD_SYSCTL for AM335x).
+        * 2. Poll the SRC(SRD) bit until it is set to 0x1.
+        * 3. Wait until the SRC (SRD) bit returns to 0x0
+        *    (reset procedure is completed).
+        */
+#if defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
+       defined(CONFIG_AM33XX)
+       if (!(readl(&mmc_base->sysctl) & bit)) {
+               start = get_timer(0);
+               while (!(readl(&mmc_base->sysctl) & bit)) {
+                       if (get_timer(0) - start > MAX_RETRY_MS)
+                               return;
+               }
+       }
+#endif
        start = get_timer(0);
        while ((readl(&mmc_base->sysctl) & bit) != 0) {
                if (get_timer(0) - start > MAX_RETRY_MS) {
@@ -376,6 +400,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        }
 
        writel(cmd->cmdarg, &mmc_base->arg);
+       udelay(20);             /* To fix "No status update" error on eMMC */
        writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd);
 
        start = get_timer(0);
@@ -480,7 +505,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
        unsigned int count;
 
        /*
-        * Start Polled Read
+        * Start Polled Write
         */
        count = (size > MMCSD_SECTOR_SIZE) ? MMCSD_SECTOR_SIZE : size;
        count /= 4;
@@ -586,6 +611,8 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 {
        struct mmc *mmc = &hsmmc_dev[dev_index];
        struct omap_hsmmc_data *priv_data = &hsmmc_dev_data[dev_index];
+       uint host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
+                            MMC_MODE_HC;
 
        sprintf(mmc->name, "OMAP SD/MMC");
        mmc->send_cmd = mmc_send_cmd;
@@ -600,11 +627,20 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
 #ifdef OMAP_HSMMC2_BASE
        case 1:
                priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE;
+#if (defined(CONFIG_OMAP44XX) || defined(CONFIG_OMAP54XX) || \
+     defined(CONFIG_DRA7XX)) && defined(CONFIG_HSMMC2_8BIT)
+               /* Enable 8-bit interface for eMMC on OMAP4/5 or DRA7XX */
+               host_caps_val |= MMC_MODE_8BIT;
+#endif
                break;
 #endif
 #ifdef OMAP_HSMMC3_BASE
        case 2:
                priv_data->base_addr = (struct hsmmc *)OMAP_HSMMC3_BASE;
+#if defined(CONFIG_DRA7XX) && defined(CONFIG_HSMMC3_8BIT)
+               /* Enable 8-bit interface for eMMC on DRA7XX */
+               host_caps_val |= MMC_MODE_8BIT;
+#endif
                break;
 #endif
        default:
@@ -620,8 +656,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
                mmc->getwp = omap_mmc_getwp;
 
        mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
-       mmc->host_caps = (MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS |
-                               MMC_MODE_HC) & ~host_caps_mask;
+       mmc->host_caps = host_caps_val & ~host_caps_mask;
 
        mmc->f_min = 400000;
 
index 7f89403..40ff873 100644 (file)
@@ -72,7 +72,7 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
 
        host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
                SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR |
-               SDHCI_QUIRK_WAIT_SEND_CMD;
+               SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8;
        host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
        host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
@@ -81,6 +81,8 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
        host->index = index;
 
        host->host_caps = MMC_MODE_HC;
+       if (bus_width == 8)
+               host->host_caps |= MMC_MODE_8BIT;
 
        return add_sdhci(host, 52000000, 400000);
 }
index 4261991..dfb2eee 100644 (file)
@@ -68,10 +68,9 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
        unsigned int stat, rdy, mask, timeout, block = 0;
 #ifdef CONFIG_MMC_SDMA
        unsigned char ctrl;
-       ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
+       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
        ctrl &= ~SDHCI_CTRL_DMA_MASK;
-       ctrl |= SDHCI_CTRL_SDMA;
-       sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
+       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 #endif
 
        timeout = 1000000;
@@ -254,7 +253,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
        if (clock == 0)
                return 0;
 
-       if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
+       if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
                /* Version 3.00 divisors must be a multiple of 2. */
                if (mmc->f_max <= clock)
                        div = 1;
@@ -347,10 +346,11 @@ void sdhci_set_ios(struct mmc *mmc)
        ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
        if (mmc->bus_width == 8) {
                ctrl &= ~SDHCI_CTRL_4BITBUS;
-               if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
+               if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) ||
+                               (host->quirks & SDHCI_QUIRK_USE_WIDE8))
                        ctrl |= SDHCI_CTRL_8BITBUS;
        } else {
-               if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
+               if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
                        ctrl &= ~SDHCI_CTRL_8BITBUS;
                if (mmc->bus_width == 4)
                        ctrl |= SDHCI_CTRL_4BITBUS;
@@ -437,7 +437,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
        if (max_clk)
                mmc->f_max = max_clk;
        else {
-               if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
+               if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
                        mmc->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
                                >> SDHCI_CLOCK_BASE_SHIFT;
                else
@@ -452,7 +452,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
        if (min_clk)
                mmc->f_min = min_clk;
        else {
-               if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
+               if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
                        mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_300;
                else
                        mmc->f_min = mmc->f_max / SDHCI_MAX_DIV_SPEC_200;
@@ -470,7 +470,7 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
                mmc->voltages |= host->voltages;
 
        mmc->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
-       if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
+       if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
                if (caps & SDHCI_CAN_DO_8BIT)
                        mmc->host_caps |= MMC_MODE_8BIT;
        }
index 191138a..86ffc59 100644 (file)
@@ -14,16 +14,11 @@ COBJS-$(CONFIG_SPL_SPI_LOAD)        += spi_spl_load.o
 COBJS-$(CONFIG_SPL_SPI_BOOT)   += fsl_espi_spl.o
 endif
 
-COBJS-$(CONFIG_SPI_FLASH)      += spi_flash.o
-COBJS-$(CONFIG_SPI_FLASH_ATMEL)        += atmel.o
-COBJS-$(CONFIG_SPI_FLASH_EON)  += eon.o
-COBJS-$(CONFIG_SPI_FLASH_GIGADEVICE)   += gigadevice.o
-COBJS-$(CONFIG_SPI_FLASH_MACRONIX)     += macronix.o
-COBJS-$(CONFIG_SPI_FLASH_SPANSION)     += spansion.o
-COBJS-$(CONFIG_SPI_FLASH_SST)  += sst.o
-COBJS-$(CONFIG_SPI_FLASH_STMICRO)      += stmicro.o
-COBJS-$(CONFIG_SPI_FLASH_WINBOND)      += winbond.o
-COBJS-$(CONFIG_SPI_FRAM_RAMTRON)       += ramtron.o
+ifdef CONFIG_CMD_SF
+COBJS-y        += sf.o
+endif
+COBJS-$(CONFIG_SPI_FLASH) += sf_probe.o sf_ops.o
+COBJS-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.o
 COBJS-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o
 
 COBJS  := $(COBJS-y)
diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c
deleted file mode 100644 (file)
index f34df43..0000000
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * Atmel SPI DataFlash support
- *
- * Copyright (C) 2008 Atmel Corporation
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-/* AT45-specific commands */
-#define CMD_AT45_READ_STATUS           0xd7
-#define CMD_AT45_ERASE_PAGE            0x81
-#define CMD_AT45_LOAD_PROG_BUF1                0x82
-#define CMD_AT45_LOAD_BUF1             0x84
-#define CMD_AT45_LOAD_PROG_BUF2                0x85
-#define CMD_AT45_LOAD_BUF2             0x87
-#define CMD_AT45_PROG_BUF1             0x88
-#define CMD_AT45_PROG_BUF2             0x89
-
-/* AT45 status register bits */
-#define AT45_STATUS_P2_PAGE_SIZE       (1 << 0)
-#define AT45_STATUS_READY              (1 << 7)
-
-/* DataFlash family IDs, as obtained from the second idcode byte */
-#define DF_FAMILY_AT26F                        0
-#define DF_FAMILY_AT45                 1
-#define DF_FAMILY_AT26DF               2       /* AT25DF and AT26DF */
-
-struct atmel_spi_flash_params {
-       u8              idcode1;
-       /* Log2 of page size in power-of-two mode */
-       u8              l2_page_size;
-       u8              pages_per_block;
-       u8              blocks_per_sector;
-       u8              nr_sectors;
-       const char      *name;
-};
-
-/* spi_flash needs to be first so upper layers can free() it */
-struct atmel_spi_flash {
-       struct spi_flash flash;
-       const struct atmel_spi_flash_params *params;
-};
-
-static inline struct atmel_spi_flash *
-to_atmel_spi_flash(struct spi_flash *flash)
-{
-       return container_of(flash, struct atmel_spi_flash, flash);
-}
-
-static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
-       {
-               .idcode1                = 0x22,
-               .l2_page_size           = 8,
-               .pages_per_block        = 8,
-               .blocks_per_sector      = 16,
-               .nr_sectors             = 4,
-               .name                   = "AT45DB011D",
-       },
-       {
-               .idcode1                = 0x23,
-               .l2_page_size           = 8,
-               .pages_per_block        = 8,
-               .blocks_per_sector      = 16,
-               .nr_sectors             = 8,
-               .name                   = "AT45DB021D",
-       },
-       {
-               .idcode1                = 0x24,
-               .l2_page_size           = 8,
-               .pages_per_block        = 8,
-               .blocks_per_sector      = 32,
-               .nr_sectors             = 8,
-               .name                   = "AT45DB041D",
-       },
-       {
-               .idcode1                = 0x25,
-               .l2_page_size           = 8,
-               .pages_per_block        = 8,
-               .blocks_per_sector      = 32,
-               .nr_sectors             = 16,
-               .name                   = "AT45DB081D",
-       },
-       {
-               .idcode1                = 0x26,
-               .l2_page_size           = 9,
-               .pages_per_block        = 8,
-               .blocks_per_sector      = 32,
-               .nr_sectors             = 16,
-               .name                   = "AT45DB161D",
-       },
-       {
-               .idcode1                = 0x27,
-               .l2_page_size           = 9,
-               .pages_per_block        = 8,
-               .blocks_per_sector      = 64,
-               .nr_sectors             = 64,
-               .name                   = "AT45DB321D",
-       },
-       {
-               .idcode1                = 0x28,
-               .l2_page_size           = 10,
-               .pages_per_block        = 8,
-               .blocks_per_sector      = 32,
-               .nr_sectors             = 32,
-               .name                   = "AT45DB642D",
-       },
-       {
-               .idcode1                = 0x47,
-               .l2_page_size           = 8,
-               .pages_per_block        = 16,
-               .blocks_per_sector      = 16,
-               .nr_sectors             = 64,
-               .name                   = "AT25DF321",
-       },
-};
-
-static int at45_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 cmd = CMD_AT45_READ_STATUS;
-       u8 status;
-
-       timebase = get_timer(0);
-
-       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-       if (ret)
-               return -1;
-
-       do {
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret)
-                       return -1;
-
-               if (status & AT45_STATUS_READY)
-                       break;
-       } while (get_timer(timebase) < timeout);
-
-       /* Deactivate CS */
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if (status & AT45_STATUS_READY)
-               return 0;
-
-       /* Timed out */
-       return -1;
-}
-
-/*
- * Assemble the address part of a command for AT45 devices in
- * non-power-of-two page size mode.
- */
-static void at45_build_address(struct atmel_spi_flash *asf, u8 *cmd, u32 offset)
-{
-       unsigned long page_addr;
-       unsigned long byte_addr;
-       unsigned long page_size;
-       unsigned int page_shift;
-
-       /*
-        * The "extra" space per page is the power-of-two page size
-        * divided by 32.
-        */
-       page_shift = asf->params->l2_page_size;
-       page_size = (1 << page_shift) + (1 << (page_shift - 5));
-       page_shift++;
-       page_addr = offset / page_size;
-       byte_addr = offset % page_size;
-
-       cmd[0] = page_addr >> (16 - page_shift);
-       cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8);
-       cmd[2] = byte_addr;
-}
-
-static int dataflash_read_fast_at45(struct spi_flash *flash,
-               u32 offset, size_t len, void *buf)
-{
-       struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-       u8 cmd[5];
-
-       cmd[0] = CMD_READ_ARRAY_FAST;
-       at45_build_address(asf, cmd + 1, offset);
-       cmd[4] = 0x00;
-
-       return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
-/*
- * TODO: the two write funcs (_p2/_at45) should get unified ...
- */
-static int dataflash_write_p2(struct spi_flash *flash,
-               u32 offset, size_t len, const void *buf)
-{
-       struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-       unsigned long page_size;
-       u32 addr = offset;
-       size_t chunk_len;
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * TODO: This function currently uses only page buffer #1.  We can
-        * speed this up by using both buffers and loading one buffer while
-        * the other is being programmed into main memory.
-        */
-
-       page_size = (1 << asf->params->l2_page_size);
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       for (actual = 0; actual < len; actual += chunk_len) {
-               chunk_len = min(len - actual, page_size - (addr % page_size));
-
-               /* Use the same address bits for both commands */
-               cmd[0] = CMD_AT45_LOAD_BUF1;
-               cmd[1] = addr >> 16;
-               cmd[2] = addr >> 8;
-               cmd[3] = addr;
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4,
-                               buf + actual, chunk_len);
-               if (ret < 0) {
-                       debug("SF: Loading AT45 buffer failed\n");
-                       goto out;
-               }
-
-               cmd[0] = CMD_AT45_PROG_BUF1;
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: AT45 page programming failed\n");
-                       goto out;
-               }
-
-               ret = at45_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: AT45 page programming timed out\n");
-                       goto out;
-               }
-
-               addr += chunk_len;
-       }
-
-       debug("SF: AT45: Successfully programmed %zu bytes @ 0x%x\n",
-             len, offset);
-       ret = 0;
-
-out:
-       spi_release_bus(flash->spi);
-       return ret;
-}
-
-static int dataflash_write_at45(struct spi_flash *flash,
-               u32 offset, size_t len, const void *buf)
-{
-       struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-       unsigned long page_addr;
-       unsigned long byte_addr;
-       unsigned long page_size;
-       unsigned int page_shift;
-       size_t chunk_len;
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * TODO: This function currently uses only page buffer #1.  We can
-        * speed this up by using both buffers and loading one buffer while
-        * the other is being programmed into main memory.
-        */
-
-       page_shift = asf->params->l2_page_size;
-       page_size = (1 << page_shift) + (1 << (page_shift - 5));
-       page_shift++;
-       page_addr = offset / page_size;
-       byte_addr = offset % page_size;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       for (actual = 0; actual < len; actual += chunk_len) {
-               chunk_len = min(len - actual, page_size - byte_addr);
-
-               /* Use the same address bits for both commands */
-               cmd[0] = CMD_AT45_LOAD_BUF1;
-               cmd[1] = page_addr >> (16 - page_shift);
-               cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8);
-               cmd[3] = byte_addr;
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4,
-                               buf + actual, chunk_len);
-               if (ret < 0) {
-                       debug("SF: Loading AT45 buffer failed\n");
-                       goto out;
-               }
-
-               cmd[0] = CMD_AT45_PROG_BUF1;
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: AT45 page programming failed\n");
-                       goto out;
-               }
-
-               ret = at45_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: AT45 page programming timed out\n");
-                       goto out;
-               }
-
-               page_addr++;
-               byte_addr = 0;
-       }
-
-       debug("SF: AT45: Successfully programmed %zu bytes @ 0x%x\n",
-             len, offset);
-       ret = 0;
-
-out:
-       spi_release_bus(flash->spi);
-       return ret;
-}
-
-/*
- * TODO: the two erase funcs (_p2/_at45) should get unified ...
- */
-static int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len)
-{
-       struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-       unsigned long page_size;
-
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * TODO: This function currently uses page erase only. We can
-        * probably speed things up by using block and/or sector erase
-        * when possible.
-        */
-
-       page_size = (1 << asf->params->l2_page_size);
-
-       if (offset % page_size || len % page_size) {
-               debug("SF: Erase offset/length not multiple of page size\n");
-               return -1;
-       }
-
-       cmd[0] = CMD_AT45_ERASE_PAGE;
-       cmd[3] = 0x00;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       for (actual = 0; actual < len; actual += page_size) {
-               cmd[1] = offset >> 16;
-               cmd[2] = offset >> 8;
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: AT45 page erase failed\n");
-                       goto out;
-               }
-
-               ret = at45_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: AT45 page erase timed out\n");
-                       goto out;
-               }
-
-               offset += page_size;
-       }
-
-       debug("SF: AT45: Successfully erased %zu bytes @ 0x%x\n",
-             len, offset);
-       ret = 0;
-
-out:
-       spi_release_bus(flash->spi);
-       return ret;
-}
-
-static int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len)
-{
-       struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-       unsigned long page_addr;
-       unsigned long page_size;
-       unsigned int page_shift;
-       size_t actual;
-       int ret;
-       u8 cmd[4];
-
-       /*
-        * TODO: This function currently uses page erase only. We can
-        * probably speed things up by using block and/or sector erase
-        * when possible.
-        */
-
-       page_shift = asf->params->l2_page_size;
-       page_size = (1 << page_shift) + (1 << (page_shift - 5));
-       page_shift++;
-       page_addr = offset / page_size;
-
-       if (offset % page_size || len % page_size) {
-               debug("SF: Erase offset/length not multiple of page size\n");
-               return -1;
-       }
-
-       cmd[0] = CMD_AT45_ERASE_PAGE;
-       cmd[3] = 0x00;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       for (actual = 0; actual < len; actual += page_size) {
-               cmd[1] = page_addr >> (16 - page_shift);
-               cmd[2] = page_addr << (page_shift - 8);
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-               if (ret < 0) {
-                       debug("SF: AT45 page erase failed\n");
-                       goto out;
-               }
-
-               ret = at45_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-               if (ret < 0) {
-                       debug("SF: AT45 page erase timed out\n");
-                       goto out;
-               }
-
-               page_addr++;
-       }
-
-       debug("SF: AT45: Successfully erased %zu bytes @ 0x%x\n",
-             len, offset);
-       ret = 0;
-
-out:
-       spi_release_bus(flash->spi);
-       return ret;
-}
-
-struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
-{
-       const struct atmel_spi_flash_params *params;
-       unsigned page_size;
-       unsigned int family;
-       struct atmel_spi_flash *asf;
-       unsigned int i;
-       int ret;
-       u8 status;
-
-       for (i = 0; i < ARRAY_SIZE(atmel_spi_flash_table); i++) {
-               params = &atmel_spi_flash_table[i];
-               if (params->idcode1 == idcode[1])
-                       break;
-       }
-
-       if (i == ARRAY_SIZE(atmel_spi_flash_table)) {
-               debug("SF: Unsupported DataFlash ID %02x\n",
-                     idcode[1]);
-               return NULL;
-       }
-
-       asf = spi_flash_alloc(struct atmel_spi_flash, spi, params->name);
-       if (!asf) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-
-       asf->params = params;
-
-       /* Assuming power-of-two page size initially. */
-       page_size = 1 << params->l2_page_size;
-
-       family = idcode[1] >> 5;
-
-       switch (family) {
-       case DF_FAMILY_AT45:
-               /*
-                * AT45 chips have configurable page size. The status
-                * register indicates which configuration is active.
-                */
-               ret = spi_flash_cmd(spi, CMD_AT45_READ_STATUS, &status, 1);
-               if (ret)
-                       goto err;
-
-               debug("SF: AT45 status register: %02x\n", status);
-
-               if (!(status & AT45_STATUS_P2_PAGE_SIZE)) {
-                       asf->flash.read = dataflash_read_fast_at45;
-                       asf->flash.write = dataflash_write_at45;
-                       asf->flash.erase = dataflash_erase_at45;
-                       page_size += 1 << (params->l2_page_size - 5);
-               } else {
-                       asf->flash.write = dataflash_write_p2;
-                       asf->flash.erase = dataflash_erase_p2;
-               }
-
-               asf->flash.page_size = page_size;
-               asf->flash.sector_size = page_size;
-               break;
-
-       case DF_FAMILY_AT26F:
-       case DF_FAMILY_AT26DF:
-               asf->flash.page_size = page_size;
-               asf->flash.sector_size = 4096;
-               /* clear SPRL# bit for locked flash */
-               spi_flash_cmd_write_status(&asf->flash, 0);
-               break;
-
-       default:
-               debug("SF: Unsupported DataFlash family %u\n", family);
-               goto err;
-       }
-
-       asf->flash.size = page_size * params->pages_per_block
-                               * params->blocks_per_sector
-                               * params->nr_sectors;
-
-       return &asf->flash;
-
-err:
-       free(asf);
-       return NULL;
-}
diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c
deleted file mode 100644 (file)
index 25cfc12..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * (C) Copyright 2010, ucRobotics Inc.
- * Author: Chong Huang <chuang@ucrobotics.com>
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct eon_spi_flash_params {
-       u8 idcode1;
-       u16 nr_sectors;
-       const char *name;
-};
-
-static const struct eon_spi_flash_params eon_spi_flash_table[] = {
-       {
-               .idcode1 = 0x16,
-               .nr_sectors = 1024,
-               .name = "EN25Q32B",
-       },
-       {
-               .idcode1 = 0x18,
-               .nr_sectors = 4096,
-               .name = "EN25Q128",
-       },
-};
-
-struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
-{
-       const struct eon_spi_flash_params *params;
-       struct spi_flash *flash;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(eon_spi_flash_table); ++i) {
-               params = &eon_spi_flash_table[i];
-               if (params->idcode1 == idcode[2])
-                       break;
-       }
-
-       if (i == ARRAY_SIZE(eon_spi_flash_table)) {
-               debug("SF: Unsupported EON ID %02x\n", idcode[1]);
-               return NULL;
-       }
-
-       flash = spi_flash_alloc_base(spi, params->name);
-       if (!flash) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-
-       flash->page_size = 256;
-       flash->sector_size = 256 * 16 * 16;
-       flash->size = 256 * 16 * params->nr_sectors;
-
-       return flash;
-}
diff --git a/drivers/mtd/spi/gigadevice.c b/drivers/mtd/spi/gigadevice.c
deleted file mode 100644 (file)
index b42581a..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Gigadevice SPI flash driver
- * Copyright 2013, Samsung Electronics Co., Ltd.
- * Author: Banajit Goswami <banajit.g@samsung.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct gigadevice_spi_flash_params {
-       uint16_t        id;
-       uint16_t        nr_blocks;
-       const char      *name;
-};
-
-static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = {
-       {
-               .id                     = 0x6016,
-               .nr_blocks              = 64,
-               .name                   = "GD25LQ",
-       },
-       {
-               .id                     = 0x4017,
-               .nr_blocks              = 128,
-               .name                   = "GD25Q64B",
-       },
-};
-
-struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
-{
-       const struct gigadevice_spi_flash_params *params;
-       struct spi_flash *flash;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(gigadevice_spi_flash_table); i++) {
-               params = &gigadevice_spi_flash_table[i];
-               if (params->id == ((idcode[1] << 8) | idcode[2]))
-                       break;
-       }
-
-       if (i == ARRAY_SIZE(gigadevice_spi_flash_table)) {
-               debug("SF: Unsupported Gigadevice ID %02x%02x\n",
-                     idcode[1], idcode[2]);
-               return NULL;
-       }
-
-       flash = spi_flash_alloc_base(spi, params->name);
-       if (!flash) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-       /* page_size */
-       flash->page_size = 256;
-       /* sector_size = page_size * pages_per_sector */
-       flash->sector_size = flash->page_size * 16;
-       /* size = sector_size * sector_per_block * number of blocks */
-       flash->size = flash->sector_size * 16 * params->nr_blocks;
-
-       return flash;
-}
diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c
deleted file mode 100644 (file)
index 70435eb..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2009(C) Marvell International Ltd. and its affiliates
- * Prafulla Wadaskar <prafulla@marvell.com>
- *
- * Based on drivers/mtd/spi/stmicro.c
- *
- * Copyright 2008, Network Appliance Inc.
- * Jason McMullan <mcmullan@netapp.com>
- *
- * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct macronix_spi_flash_params {
-       u16 idcode;
-       u16 nr_blocks;
-       const char *name;
-};
-
-static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
-       {
-               .idcode = 0x2013,
-               .nr_blocks = 8,
-               .name = "MX25L4005",
-       },
-       {
-               .idcode = 0x2014,
-               .nr_blocks = 16,
-               .name = "MX25L8005",
-       },
-       {
-               .idcode = 0x2015,
-               .nr_blocks = 32,
-               .name = "MX25L1605D",
-       },
-       {
-               .idcode = 0x2016,
-               .nr_blocks = 64,
-               .name = "MX25L3205D",
-       },
-       {
-               .idcode = 0x2017,
-               .nr_blocks = 128,
-               .name = "MX25L6405D",
-       },
-       {
-               .idcode = 0x2018,
-               .nr_blocks = 256,
-               .name = "MX25L12805D",
-       },
-       {
-               .idcode = 0x2618,
-               .nr_blocks = 256,
-               .name = "MX25L12855E",
-       },
-};
-
-struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
-{
-       const struct macronix_spi_flash_params *params;
-       struct spi_flash *flash;
-       unsigned int i;
-       u16 id = idcode[2] | idcode[1] << 8;
-
-       for (i = 0; i < ARRAY_SIZE(macronix_spi_flash_table); i++) {
-               params = &macronix_spi_flash_table[i];
-               if (params->idcode == id)
-                       break;
-       }
-
-       if (i == ARRAY_SIZE(macronix_spi_flash_table)) {
-               debug("SF: Unsupported Macronix ID %04x\n", id);
-               return NULL;
-       }
-
-       flash = spi_flash_alloc_base(spi, params->name);
-       if (!flash) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-
-       flash->page_size = 256;
-       flash->sector_size = 256 * 16 * 16;
-       flash->size = flash->sector_size * params->nr_blocks;
-
-       /* Clear BP# bits for read-only flash */
-       spi_flash_cmd_write_status(flash, 0);
-
-       return flash;
-}
index 38f9d69..d50da37 100644 (file)
@@ -36,7 +36,7 @@
 #include <common.h>
 #include <malloc.h>
 #include <spi_flash.h>
-#include "spi_flash_internal.h"
+#include "sf_internal.h"
 
 /*
  * Properties of supported FRAMs
@@ -214,7 +214,8 @@ static int ramtron_erase(struct spi_flash *flash, u32 offset, size_t len)
  * nore: we are called here with idcode pointing to the first non-0x7f byte
  * already!
  */
-struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode)
+static struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi,
+               u8 *idcode)
 {
        const struct ramtron_spi_fram_params *params;
        struct ramtron_spi_fram *sn;
@@ -270,7 +271,7 @@ struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode)
        return NULL;
 
 found:
-       sn = spi_flash_alloc(struct ramtron_spi_fram, spi, params->name);
+       sn = malloc(sizeof(*sn));
        if (!sn) {
                debug("SF: Failed to allocate memory\n");
                return NULL;
@@ -285,3 +286,118 @@ found:
 
        return &sn->flash;
 }
+
+/*
+ * The following table holds all device probe functions
+ * (All flashes are removed and implemented a common probe at
+ *  spi_flash_probe.c)
+ *
+ * shift:  number of continuation bytes before the ID
+ * idcode: the expected IDCODE or 0xff for non JEDEC devices
+ * probe:  the function to call
+ *
+ * Non JEDEC devices should be ordered in the table such that
+ * the probe functions with best detection algorithms come first.
+ *
+ * Several matching entries are permitted, they will be tried
+ * in sequence until a probe function returns non NULL.
+ *
+ * IDCODE_CONT_LEN may be redefined if a device needs to declare a
+ * larger "shift" value.  IDCODE_PART_LEN generally shouldn't be
+ * changed.  This is the max number of bytes probe functions may
+ * examine when looking up part-specific identification info.
+ *
+ * Probe functions will be given the idcode buffer starting at their
+ * manu id byte (the "idcode" in the table below).  In other words,
+ * all of the continuation bytes will be skipped (the "shift" below).
+ */
+#define IDCODE_CONT_LEN 0
+#define IDCODE_PART_LEN 5
+static const struct {
+       const u8 shift;
+       const u8 idcode;
+       struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
+} flashes[] = {
+       /* Keep it sorted by define name */
+#ifdef CONFIG_SPI_FRAM_RAMTRON
+       { 6, 0xc2, spi_fram_probe_ramtron, },
+# undef IDCODE_CONT_LEN
+# define IDCODE_CONT_LEN 6
+#endif
+#ifdef CONFIG_SPI_FRAM_RAMTRON_NON_JEDEC
+       { 0, 0xff, spi_fram_probe_ramtron, },
+#endif
+};
+#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
+
+struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+               unsigned int max_hz, unsigned int spi_mode)
+{
+       struct spi_slave *spi;
+       struct spi_flash *flash = NULL;
+       int ret, i, shift;
+       u8 idcode[IDCODE_LEN], *idp;
+
+       spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
+       if (!spi) {
+               printf("SF: Failed to set up slave\n");
+               return NULL;
+       }
+
+       ret = spi_claim_bus(spi);
+       if (ret) {
+               debug("SF: Failed to claim SPI bus: %d\n", ret);
+               goto err_claim_bus;
+       }
+
+       /* Read the ID codes */
+       ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
+       if (ret)
+               goto err_read_id;
+
+#ifdef DEBUG
+       printf("SF: Got idcodes\n");
+       print_buffer(0, idcode, 1, sizeof(idcode), 0);
+#endif
+
+       /* count the number of continuation bytes */
+       for (shift = 0, idp = idcode;
+            shift < IDCODE_CONT_LEN && *idp == 0x7f;
+            ++shift, ++idp)
+               continue;
+
+       /* search the table for matches in shift and id */
+       for (i = 0; i < ARRAY_SIZE(flashes); ++i)
+               if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
+                       /* we have a match, call probe */
+                       flash = flashes[i].probe(spi, idp);
+                       if (flash)
+                               break;
+               }
+
+       if (!flash) {
+               printf("SF: Unsupported manufacturer %02x\n", *idp);
+               goto err_manufacturer_probe;
+       }
+
+       printf("SF: Detected %s with total size ", flash->name);
+       print_size(flash->size, "");
+       puts("\n");
+
+       spi_release_bus(spi);
+
+       return flash;
+
+err_manufacturer_probe:
+err_read_id:
+       spi_release_bus(spi);
+err_claim_bus:
+       spi_free_slave(spi);
+       return NULL;
+}
+
+void spi_flash_free(struct spi_flash *flash)
+{
+       spi_free_slave(flash->spi);
+       free(flash);
+}
diff --git a/drivers/mtd/spi/sf.c b/drivers/mtd/spi/sf.c
new file mode 100644 (file)
index 0000000..ddbdda0
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * SPI flash interface
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <spi.h>
+
+static int spi_flash_read_write(struct spi_slave *spi,
+                               const u8 *cmd, size_t cmd_len,
+                               const u8 *data_out, u8 *data_in,
+                               size_t data_len)
+{
+       unsigned long flags = SPI_XFER_BEGIN;
+       int ret;
+
+       if (data_len == 0)
+               flags |= SPI_XFER_END;
+
+       ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
+       if (ret) {
+               debug("SF: Failed to send command (%zu bytes): %d\n",
+                     cmd_len, ret);
+       } else if (data_len != 0) {
+               ret = spi_xfer(spi, data_len * 8, data_out, data_in,
+                                       SPI_XFER_END);
+               if (ret)
+                       debug("SF: Failed to transfer %zu bytes of data: %d\n",
+                             data_len, ret);
+       }
+
+       return ret;
+}
+
+int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
+               size_t cmd_len, void *data, size_t data_len)
+{
+       return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len);
+}
+
+int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
+{
+       return spi_flash_cmd_read(spi, &cmd, 1, response, len);
+}
+
+int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
+               const void *data, size_t data_len)
+{
+       return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
+}
similarity index 62%
rename from drivers/mtd/spi/spi_flash_internal.h
rename to drivers/mtd/spi/sf_internal.h
index af1afa9..12d02f9 100644 (file)
@@ -2,42 +2,43 @@
  * SPI flash internal definitions
  *
  * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
-/* Common parameters -- kind of high, but they should only occur when there
- * is a problem (and well your system already is broken), so err on the side
- * of caution in case we're dealing with slower SPI buses and/or processors.
- */
-#define SPI_FLASH_PROG_TIMEOUT         (2 * CONFIG_SYS_HZ)
-#define SPI_FLASH_PAGE_ERASE_TIMEOUT   (5 * CONFIG_SYS_HZ)
-#define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ)
+#ifndef _SPI_FLASH_INTERNAL_H_
+#define _SPI_FLASH_INTERNAL_H_
 
-/* Common commands */
-#define CMD_READ_ID                    0x9f
+#define SPI_FLASH_16MB_BOUN            0x1000000
 
-#define CMD_READ_ARRAY_SLOW            0x03
-#define CMD_READ_ARRAY_FAST            0x0b
+/* SECT flags */
+#define SECT_4K                                (1 << 1)
+#define SECT_32K                       (1 << 2)
+#define E_FSR                          (1 << 3)
+
+/* Erase commands */
+#define CMD_ERASE_4K                   0x20
+#define CMD_ERASE_32K                  0x52
+#define CMD_ERASE_CHIP                 0xc7
+#define CMD_ERASE_64K                  0xd8
 
+/* Write commands */
 #define CMD_WRITE_STATUS               0x01
 #define CMD_PAGE_PROGRAM               0x02
 #define CMD_WRITE_DISABLE              0x04
 #define CMD_READ_STATUS                        0x05
-#define CMD_FLAG_STATUS                        0x70
 #define CMD_WRITE_ENABLE               0x06
-#define CMD_ERASE_4K                   0x20
-#define CMD_ERASE_32K                  0x52
-#define CMD_ERASE_64K                  0xd8
-#define CMD_ERASE_CHIP                 0xc7
-
-#define SPI_FLASH_16MB_BOUN            0x1000000
+#define CMD_READ_CONFIG                        0x35
+#define CMD_FLAG_STATUS                        0x70
 
-/* Manufacture ID's */
-#define SPI_FLASH_SPANSION_IDCODE0     0x01
-#define SPI_FLASH_STMICRO_IDCODE0      0x20
-#define SPI_FLASH_WINBOND_IDCODE0      0xef
+/* Read commands */
+#define CMD_READ_ARRAY_SLOW            0x03
+#define CMD_READ_ARRAY_FAST            0x0b
+#define CMD_READ_ID                    0x9f
 
-#ifdef CONFIG_SPI_FLASH_BAR
 /* Bank addr access commands */
+#ifdef CONFIG_SPI_FLASH_BAR
 # define CMD_BANKADDR_BRWR             0x17
 # define CMD_BANKADDR_BRRD             0x16
 # define CMD_EXTNADDR_WREAR            0xC5
 #define STATUS_WIP                     0x01
 #define STATUS_PEC                     0x80
 
+/* Flash timeout values */
+#define SPI_FLASH_PROG_TIMEOUT         (2 * CONFIG_SYS_HZ)
+#define SPI_FLASH_PAGE_ERASE_TIMEOUT   (5 * CONFIG_SYS_HZ)
+#define SPI_FLASH_SECTOR_ERASE_TIMEOUT (10 * CONFIG_SYS_HZ)
+
+/* SST specific */
+#ifdef CONFIG_SPI_FLASH_SST
+# define SST_WP                        0x01    /* Supports AAI word program */
+# define CMD_SST_BP            0x02    /* Byte Program */
+# define CMD_SST_AAI_WP                0xAD    /* Auto Address Incr Word Program */
+
+int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
+               const void *buf);
+#endif
+
 /* Send a single-byte command to the device and read the response */
 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
 
@@ -58,9 +74,6 @@ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
 int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
                size_t cmd_len, void *data, size_t data_len);
 
-int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
-               size_t len, void *data);
-
 /*
  * Send a multi-byte command to the device followed by (optional)
  * data. Used for programming the flash array, etc.
@@ -68,46 +81,34 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
 int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
                const void *data, size_t data_len);
 
-/*
- * Write the requested data out breaking it up into multiple write
- * commands as needed per the write size.
- */
-int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
-               size_t len, const void *buf);
 
-/*
- * Enable writing on the SPI flash.
- */
+/* Flash erase(sectors) operation, support all possible erase commands */
+int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
+
+/* Program the status register */
+int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr);
+
+/* Set quad enbale bit */
+int spi_flash_set_qeb(struct spi_flash *flash);
+
+/* Enable writing on the SPI flash */
 static inline int spi_flash_cmd_write_enable(struct spi_flash *flash)
 {
        return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0);
 }
 
-/*
- * Disable writing on the SPI flash.
- */
+/* Disable writing on the SPI flash */
 static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
 {
        return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
 }
 
-/* Program the status register. */
-int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr);
-
-#ifdef CONFIG_SPI_FLASH_BAR
-/* Program the bank address register */
-int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel);
-
-/* Configure the BAR - discover the bank cmds */
-int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0);
-#endif
-
 /*
- * Same as spi_flash_cmd_read() except it also claims/releases the SPI
- * bus. Used as common part of the ->read() operation.
+ * Send the read status command to the device and wait for the wip
+ * (write-in-progress) bit to clear itself.
  */
-int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
-               size_t cmd_len, void *data, size_t data_len);
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
+
 /*
  * Used for spi_flash write operation
  * - SPI claim
@@ -120,21 +121,22 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
                size_t cmd_len, const void *buf, size_t buf_len);
 
 /*
- * Send the read status command to the device and wait for the wip
- * (write-in-progress) bit to clear itself.
+ * Flash write operation, support all possible write commands.
+ * Write the requested data out breaking it up into multiple write
+ * commands as needed per the write size.
  */
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
+int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
+               size_t len, const void *buf);
+
+/*
+ * Same as spi_flash_cmd_read() except it also claims/releases the SPI
+ * bus. Used as common part of the ->read() operation.
+ */
+int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
+               size_t cmd_len, void *data, size_t data_len);
+
+/* Flash read operation, support all possible read commands */
+int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
+               size_t len, void *data);
 
-/* Erase sectors. */
-int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len);
-
-/* Manufacturer-specific probe functions */
-struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode);
+#endif /* _SPI_FLASH_INTERNAL_H_ */
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
new file mode 100644 (file)
index 0000000..2396e22
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * SPI flash operations
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <watchdog.h>
+
+#include "sf_internal.h"
+
+static void spi_flash_addr(u32 addr, u8 *cmd)
+{
+       /* cmd[0] is actual command */
+       cmd[1] = addr >> 16;
+       cmd[2] = addr >> 8;
+       cmd[3] = addr >> 0;
+}
+
+int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
+{
+       u8 cmd;
+       int ret;
+
+       cmd = CMD_WRITE_STATUS;
+       ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1);
+       if (ret < 0) {
+               debug("SF: fail to write status register\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_SPI_FLASH_BAR
+static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
+{
+       u8 cmd;
+       int ret;
+
+       if (flash->bank_curr == bank_sel) {
+               debug("SF: not require to enable bank%d\n", bank_sel);
+               return 0;
+       }
+
+       cmd = flash->bank_write_cmd;
+       ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
+       if (ret < 0) {
+               debug("SF: fail to write bank register\n");
+               return ret;
+       }
+       flash->bank_curr = bank_sel;
+
+       return 0;
+}
+#endif
+
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+{
+       struct spi_slave *spi = flash->spi;
+       unsigned long timebase;
+       int ret;
+       u8 status;
+       u8 check_status = 0x0;
+       u8 poll_bit = STATUS_WIP;
+       u8 cmd = flash->poll_cmd;
+
+       if (cmd == CMD_FLAG_STATUS) {
+               poll_bit = STATUS_PEC;
+               check_status = poll_bit;
+       }
+
+       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
+       if (ret) {
+               debug("SF: fail to read %s status register\n",
+                     cmd == CMD_READ_STATUS ? "read" : "flag");
+               return ret;
+       }
+
+       timebase = get_timer(0);
+       do {
+               WATCHDOG_RESET();
+
+               ret = spi_xfer(spi, 8, NULL, &status, 0);
+               if (ret)
+                       return -1;
+
+               if ((status & poll_bit) == check_status)
+                       break;
+
+       } while (get_timer(timebase) < timeout);
+
+       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+
+       if ((status & poll_bit) == check_status)
+               return 0;
+
+       /* Timed out */
+       debug("SF: time out!\n");
+       return -1;
+}
+
+int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
+               size_t cmd_len, const void *buf, size_t buf_len)
+{
+       struct spi_slave *spi = flash->spi;
+       unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
+       int ret;
+
+       if (buf == NULL)
+               timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
+
+       ret = spi_claim_bus(flash->spi);
+       if (ret) {
+               debug("SF: unable to claim SPI bus\n");
+               return ret;
+       }
+
+       ret = spi_flash_cmd_write_enable(flash);
+       if (ret < 0) {
+               debug("SF: enabling write failed\n");
+               return ret;
+       }
+
+       ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
+       if (ret < 0) {
+               debug("SF: write cmd failed\n");
+               return ret;
+       }
+
+       ret = spi_flash_cmd_wait_ready(flash, timeout);
+       if (ret < 0) {
+               debug("SF: write %s timed out\n",
+                     timeout == SPI_FLASH_PROG_TIMEOUT ?
+                       "program" : "page erase");
+               return ret;
+       }
+
+       spi_release_bus(spi);
+
+       return ret;
+}
+
+int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
+{
+       u32 erase_size;
+       u8 cmd[4];
+       int ret = -1;
+
+       erase_size = flash->erase_size;
+       if (offset % erase_size || len % erase_size) {
+               debug("SF: Erase offset/length not multiple of erase size\n");
+               return -1;
+       }
+
+       cmd[0] = flash->erase_cmd;
+       while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+               u8 bank_sel;
+
+               bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+               if (ret) {
+                       debug("SF: fail to set bank%d\n", bank_sel);
+                       return ret;
+               }
+#endif
+               spi_flash_addr(offset, cmd);
+
+               debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
+                     cmd[2], cmd[3], offset);
+
+               ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
+               if (ret < 0) {
+                       debug("SF: erase failed\n");
+                       break;
+               }
+
+               offset += erase_size;
+               len -= erase_size;
+       }
+
+       return ret;
+}
+
+int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
+               size_t len, const void *buf)
+{
+       unsigned long byte_addr, page_size;
+       size_t chunk_len, actual;
+       u8 cmd[4];
+       int ret = -1;
+
+       page_size = flash->page_size;
+
+       cmd[0] = CMD_PAGE_PROGRAM;
+       for (actual = 0; actual < len; actual += chunk_len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+               u8 bank_sel;
+
+               bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+               if (ret) {
+                       debug("SF: fail to set bank%d\n", bank_sel);
+                       return ret;
+               }
+#endif
+               byte_addr = offset % page_size;
+               chunk_len = min(len - actual, page_size - byte_addr);
+
+               if (flash->spi->max_write_size)
+                       chunk_len = min(chunk_len, flash->spi->max_write_size);
+
+               spi_flash_addr(offset, cmd);
+
+               debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
+                     buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
+
+               ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
+                                       buf + actual, chunk_len);
+               if (ret < 0) {
+                       debug("SF: write failed\n");
+                       break;
+               }
+
+               offset += chunk_len;
+       }
+
+       return ret;
+}
+
+int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
+               size_t cmd_len, void *data, size_t data_len)
+{
+       struct spi_slave *spi = flash->spi;
+       int ret;
+
+       ret = spi_claim_bus(flash->spi);
+       if (ret) {
+               debug("SF: unable to claim SPI bus\n");
+               return ret;
+       }
+
+       ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
+       if (ret < 0) {
+               debug("SF: read cmd failed\n");
+               return ret;
+       }
+
+       spi_release_bus(spi);
+
+       return ret;
+}
+
+int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
+               size_t len, void *data)
+{
+       u8 cmd[5], bank_sel = 0;
+       u32 remain_len, read_len;
+       int ret = -1;
+
+       /* Handle memory-mapped SPI */
+       if (flash->memory_map) {
+               spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP);
+               memcpy(data, flash->memory_map + offset, len);
+               spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
+               return 0;
+       }
+
+       cmd[0] = CMD_READ_ARRAY_FAST;
+       cmd[4] = 0x00;
+
+       while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+               bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+               if (ret) {
+                       debug("SF: fail to set bank%d\n", bank_sel);
+                       return ret;
+               }
+#endif
+               remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset);
+               if (len < remain_len)
+                       read_len = len;
+               else
+                       read_len = remain_len;
+
+               spi_flash_addr(offset, cmd);
+
+               ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
+                                                       data, read_len);
+               if (ret < 0) {
+                       debug("SF: read failed\n");
+                       break;
+               }
+
+               offset += read_len;
+               len -= read_len;
+               data += read_len;
+       }
+
+       return ret;
+}
+
+#ifdef CONFIG_SPI_FLASH_SST
+static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
+{
+       int ret;
+       u8 cmd[4] = {
+               CMD_SST_BP,
+               offset >> 16,
+               offset >> 8,
+               offset,
+       };
+
+       debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
+             spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
+
+       ret = spi_flash_cmd_write_enable(flash);
+       if (ret)
+               return ret;
+
+       ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
+       if (ret)
+               return ret;
+
+       return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+}
+
+int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
+               const void *buf)
+{
+       size_t actual, cmd_len;
+       int ret;
+       u8 cmd[4];
+
+       ret = spi_claim_bus(flash->spi);
+       if (ret) {
+               debug("SF: Unable to claim SPI bus\n");
+               return ret;
+       }
+
+       /* If the data is not word aligned, write out leading single byte */
+       actual = offset % 2;
+       if (actual) {
+               ret = sst_byte_write(flash, offset, buf);
+               if (ret)
+                       goto done;
+       }
+       offset += actual;
+
+       ret = spi_flash_cmd_write_enable(flash);
+       if (ret)
+               goto done;
+
+       cmd_len = 4;
+       cmd[0] = CMD_SST_AAI_WP;
+       cmd[1] = offset >> 16;
+       cmd[2] = offset >> 8;
+       cmd[3] = offset;
+
+       for (; actual < len - 1; actual += 2) {
+               debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
+                     spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
+                     cmd[0], offset);
+
+               ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
+                                       buf + actual, 2);
+               if (ret) {
+                       debug("SF: sst word program failed\n");
+                       break;
+               }
+
+               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+               if (ret)
+                       break;
+
+               cmd_len = 1;
+               offset += 2;
+       }
+
+       if (!ret)
+               ret = spi_flash_cmd_write_disable(flash);
+
+       /* If there is a single trailing byte, write it out */
+       if (!ret && actual != len)
+               ret = sst_byte_write(flash, offset, buf + actual);
+
+ done:
+       debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
+             ret ? "failure" : "success", len, offset - actual);
+
+       spi_release_bus(flash->spi);
+       return ret;
+}
+#endif
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
new file mode 100644 (file)
index 0000000..4251b1b
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * SPI flash probing
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <spi.h>
+#include <spi_flash.h>
+
+#include "sf_internal.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * struct spi_flash_params - SPI/QSPI flash device params structure
+ *
+ * @name:              Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
+ * @jedec:             Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
+ * @ext_jedec:         Device ext_jedec ID
+ * @sector_size:       Sector size of this device
+ * @nr_sectors:        No.of sectors on this device
+ * @flags:             Importent param, for flash specific behaviour
+ */
+struct spi_flash_params {
+       const char *name;
+       u32 jedec;
+       u16 ext_jedec;
+       u32 sector_size;
+       u32 nr_sectors;
+       u16 flags;
+};
+
+static const struct spi_flash_params spi_flash_params_table[] = {
+#ifdef CONFIG_SPI_FLASH_ATMEL          /* ATMEL */
+       {"AT45DB011D",     0x1f2200, 0x0,       64 * 1024,     4,              SECT_4K},
+       {"AT45DB021D",     0x1f2300, 0x0,       64 * 1024,     8,              SECT_4K},
+       {"AT45DB041D",     0x1f2400, 0x0,       64 * 1024,     8,              SECT_4K},
+       {"AT45DB081D",     0x1f2500, 0x0,       64 * 1024,    16,              SECT_4K},
+       {"AT45DB161D",     0x1f2600, 0x0,       64 * 1024,    32,              SECT_4K},
+       {"AT45DB321D",     0x1f2700, 0x0,       64 * 1024,    64,              SECT_4K},
+       {"AT45DB641D",     0x1f2800, 0x0,       64 * 1024,   128,              SECT_4K},
+#endif
+#ifdef CONFIG_SPI_FLASH_EON            /* EON */
+       {"EN25Q32B",       0x1c3016, 0x0,       64 * 1024,    64,                    0},
+       {"EN25Q64",        0x1c3017, 0x0,       64 * 1024,   128,              SECT_4K},
+       {"EN25Q128B",      0x1c3018, 0x0,       64 * 1024,   256,                    0},
+       {"EN25S64",        0x1c3817, 0x0,       64 * 1024,   128,                    0},
+#endif
+#ifdef CONFIG_SPI_FLASH_GIGADEVICE     /* GIGADEVICE */
+       {"GD25Q64B",       0xc84017, 0x0,       64 * 1024,   128,              SECT_4K},
+       {"GD25LQ32",       0xc86016, 0x0,       64 * 1024,    64,              SECT_4K},
+#endif
+#ifdef CONFIG_SPI_FLASH_MACRONIX       /* MACRONIX */
+       {"MX25L4005",      0xc22013, 0x0,       64 * 1024,     8,                    0},
+       {"MX25L8005",      0xc22014, 0x0,       64 * 1024,    16,                    0},
+       {"MX25L1605D",     0xc22015, 0x0,       64 * 1024,    32,                    0},
+       {"MX25L3205D",     0xc22016, 0x0,       64 * 1024,    64,                    0},
+       {"MX25L6405D",     0xc22017, 0x0,       64 * 1024,   128,                    0},
+       {"MX25L12805",     0xc22018, 0x0,       64 * 1024,   256,                    0},
+       {"MX25L25635F",    0xc22019, 0x0,       64 * 1024,   512,                    0},
+       {"MX25L51235F",    0xc2201A, 0x0,       64 * 1024,  1024,                    0},
+       {"MX25L12855E",    0xc22618, 0x0,       64 * 1024,   256,                    0},
+#endif
+#ifdef CONFIG_SPI_FLASH_SPANSION       /* SPANSION */
+       {"S25FL008A",      0x010213, 0x0,       64 * 1024,    16,                    0},
+       {"S25FL016A",      0x010214, 0x0,       64 * 1024,    32,                    0},
+       {"S25FL032A",      0x010215, 0x0,       64 * 1024,    64,                    0},
+       {"S25FL064A",      0x010216, 0x0,       64 * 1024,   128,                    0},
+       {"S25FL128P_256K", 0x012018, 0x0300,   256 * 1024,    64,                    0},
+       {"S25FL128P_64K",  0x012018, 0x0301,    64 * 1024,   256,                    0},
+       {"S25FL032P",      0x010215, 0x4d00,    64 * 1024,    64,                    0},
+       {"S25FL064P",      0x010216, 0x4d00,    64 * 1024,   128,                    0},
+       {"S25FL128S_64K",  0x012018, 0x4d01,    64 * 1024,   256,                    0},
+       {"S25FL256S_256K", 0x010219, 0x4d00,    64 * 1024,   512,                    0},
+       {"S25FL256S_64K",  0x010219, 0x4d01,    64 * 1024,   512,                    0},
+       {"S25FL512S_256K", 0x010220, 0x4d00,    64 * 1024,  1024,                    0},
+       {"S25FL512S_64K",  0x010220, 0x4d01,    64 * 1024,  1024,                    0},
+#endif
+#ifdef CONFIG_SPI_FLASH_STMICRO                /* STMICRO */
+       {"M25P10",         0x202011, 0x0,       32 * 1024,     4,                    0},
+       {"M25P20",         0x202012, 0x0,       64 * 1024,     4,                    0},
+       {"M25P40",         0x202013, 0x0,       64 * 1024,     8,                    0},
+       {"M25P80",         0x202014, 0x0,       64 * 1024,    16,                    0},
+       {"M25P16",         0x202015, 0x0,       64 * 1024,    32,                    0},
+       {"M25P32",         0x202016, 0x0,       64 * 1024,    64,                    0},
+       {"M25P64",         0x202017, 0x0,       64 * 1024,   128,                    0},
+       {"M25P128",        0x202018, 0x0,      256 * 1024,    64,                    0},
+       {"N25Q32",         0x20ba16, 0x0,       64 * 1024,    64,              SECT_4K},
+       {"N25Q32A",        0x20bb16, 0x0,       64 * 1024,    64,              SECT_4K},
+       {"N25Q64",         0x20ba17, 0x0,       64 * 1024,   128,              SECT_4K},
+       {"N25Q64A",        0x20bb17, 0x0,       64 * 1024,   128,              SECT_4K},
+       {"N25Q128",        0x20ba18, 0x0,       64 * 1024,   256,              SECT_4K},
+       {"N25Q128A",       0x20bb18, 0x0,       64 * 1024,   256,              SECT_4K},
+       {"N25Q256",        0x20ba19, 0x0,       64 * 1024,   512,              SECT_4K},
+       {"N25Q256A",       0x20bb19, 0x0,       64 * 1024,   512,              SECT_4K},
+       {"N25Q512",        0x20ba20, 0x0,       64 * 1024,  1024,      E_FSR | SECT_4K},
+       {"N25Q512A",       0x20bb20, 0x0,       64 * 1024,  1024,      E_FSR | SECT_4K},
+       {"N25Q1024",       0x20ba21, 0x0,       64 * 1024,  2048,      E_FSR | SECT_4K},
+       {"N25Q1024A",      0x20bb21, 0x0,       64 * 1024,  2048,      E_FSR | SECT_4K},
+#endif
+#ifdef CONFIG_SPI_FLASH_SST            /* SST */
+       {"SST25VF040B",    0xbf258d, 0x0,       64 * 1024,     8,     SECT_4K | SST_WP},
+       {"SST25VF080B",    0xbf258e, 0x0,       64 * 1024,    16,     SECT_4K | SST_WP},
+       {"SST25VF016B",    0xbf2541, 0x0,       64 * 1024,    32,     SECT_4K | SST_WP},
+       {"SST25VF032B",    0xbf254a, 0x0,       64 * 1024,    64,     SECT_4K | SST_WP},
+       {"SST25VF064C",    0xbf254b, 0x0,       64 * 1024,   128,              SECT_4K},
+       {"SST25WF512",     0xbf2501, 0x0,       64 * 1024,     1,     SECT_4K | SST_WP},
+       {"SST25WF010",     0xbf2502, 0x0,       64 * 1024,     2,     SECT_4K | SST_WP},
+       {"SST25WF020",     0xbf2503, 0x0,       64 * 1024,     4,     SECT_4K | SST_WP},
+       {"SST25WF040",     0xbf2504, 0x0,       64 * 1024,     8,     SECT_4K | SST_WP},
+       {"SST25WF080",     0xbf2505, 0x0,       64 * 1024,    16,     SECT_4K | SST_WP},
+#endif
+#ifdef CONFIG_SPI_FLASH_WINBOND                /* WINBOND */
+       {"W25P80",         0xef2014, 0x0,       64 * 1024,    16,                   0},
+       {"W25P16",         0xef2015, 0x0,       64 * 1024,    32,                   0},
+       {"W25P32",         0xef2016, 0x0,       64 * 1024,    64,                   0},
+       {"W25X40",         0xef3013, 0x0,       64 * 1024,     8,             SECT_4K},
+       {"W25X16",         0xef3015, 0x0,       64 * 1024,    32,             SECT_4K},
+       {"W25X32",         0xef3016, 0x0,       64 * 1024,    64,             SECT_4K},
+       {"W25X64",         0xef3017, 0x0,       64 * 1024,   128,             SECT_4K},
+       {"W25Q80BL",       0xef4014, 0x0,       64 * 1024,    16,             SECT_4K},
+       {"W25Q16CL",       0xef4015, 0x0,       64 * 1024,    32,             SECT_4K},
+       {"W25Q32BV",       0xef4016, 0x0,       64 * 1024,    64,             SECT_4K},
+       {"W25Q64CV",       0xef4017, 0x0,       64 * 1024,   128,             SECT_4K},
+       {"W25Q128BV",      0xef4018, 0x0,       64 * 1024,   256,             SECT_4K},
+       {"W25Q256",        0xef4019, 0x0,       64 * 1024,   512,             SECT_4K},
+       {"W25Q80BW",       0xef5014, 0x0,       64 * 1024,    16,             SECT_4K},
+       {"W25Q16DW",       0xef6015, 0x0,       64 * 1024,    32,             SECT_4K},
+       {"W25Q32DW",       0xef6016, 0x0,       64 * 1024,    64,             SECT_4K},
+       {"W25Q64DW",       0xef6017, 0x0,       64 * 1024,   128,             SECT_4K},
+       {"W25Q128FW",      0xef6018, 0x0,       64 * 1024,   256,             SECT_4K},
+#endif
+       /*
+        * Note:
+        * Below paired flash devices has similar spi_flash_params params.
+        * (S25FL129P_64K, S25FL128S_64K)
+        * (W25Q80BL, W25Q80BV)
+        * (W25Q16CL, W25Q16DV)
+        * (W25Q32BV, W25Q32FV_SPI)
+        * (W25Q64CV, W25Q64FV_SPI)
+        * (W25Q128BV, W25Q128FV_SPI)
+        * (W25Q32DW, W25Q32FV_QPI)
+        * (W25Q64DW, W25Q64FV_QPI)
+        * (W25Q128FW, W25Q128FV_QPI)
+        */
+};
+
+static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
+               u8 *idcode)
+{
+       const struct spi_flash_params *params;
+       struct spi_flash *flash;
+       int i;
+       u16 jedec = idcode[1] << 8 | idcode[2];
+       u16 ext_jedec = idcode[3] << 8 | idcode[4];
+
+       /* Get the flash id (jedec = manuf_id + dev_id, ext_jedec) */
+       for (i = 0; i < ARRAY_SIZE(spi_flash_params_table); i++) {
+               params = &spi_flash_params_table[i];
+               if ((params->jedec >> 16) == idcode[0]) {
+                       if ((params->jedec & 0xFFFF) == jedec) {
+                               if (params->ext_jedec == 0)
+                                       break;
+                               else if (params->ext_jedec == ext_jedec)
+                                       break;
+                       }
+               }
+       }
+
+       if (i == ARRAY_SIZE(spi_flash_params_table)) {
+               printf("SF: Unsupported flash IDs: ");
+               printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
+                      idcode[0], jedec, ext_jedec);
+               return NULL;
+       }
+
+       flash = malloc(sizeof(*flash));
+       if (!flash) {
+               debug("SF: Failed to allocate spi_flash\n");
+               return NULL;
+       }
+       memset(flash, '\0', sizeof(*flash));
+
+       flash->spi = spi;
+       flash->name = params->name;
+       flash->memory_map = spi->memory_map;
+
+       /* Assign spi_flash ops */
+       flash->write = spi_flash_cmd_write_ops;
+#ifdef CONFIG_SPI_FLASH_SST
+       if (params->flags & SST_WP)
+               flash->write = sst_write_wp;
+#endif
+       flash->erase = spi_flash_cmd_erase_ops;
+       flash->read = spi_flash_cmd_read_ops;
+
+       /* Compute the flash size */
+       flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256;
+       flash->sector_size = params->sector_size;
+       flash->size = flash->sector_size * params->nr_sectors;
+
+       /* Compute erase sector and command */
+       if (params->flags & SECT_4K) {
+               flash->erase_cmd = CMD_ERASE_4K;
+               flash->erase_size = 4096;
+       } else if (params->flags & SECT_32K) {
+               flash->erase_cmd = CMD_ERASE_32K;
+               flash->erase_size = 32768;
+       } else {
+               flash->erase_cmd = CMD_ERASE_64K;
+               flash->erase_size = flash->sector_size;
+       }
+
+       /* Poll cmd seclection */
+       flash->poll_cmd = CMD_READ_STATUS;
+#ifdef CONFIG_SPI_FLASH_STMICRO
+       if (params->flags & E_FSR)
+               flash->poll_cmd = CMD_FLAG_STATUS;
+#endif
+
+       /* Configure the BAR - discover bank cmds and read current bank */
+#ifdef CONFIG_SPI_FLASH_BAR
+       u8 curr_bank = 0;
+       if (flash->size > SPI_FLASH_16MB_BOUN) {
+               flash->bank_read_cmd = (idcode[0] == 0x01) ?
+                                       CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR;
+               flash->bank_write_cmd = (idcode[0] == 0x01) ?
+                                       CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
+
+               if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
+                                         &curr_bank, 1)) {
+                       debug("SF: fail to read bank addr register\n");
+                       return NULL;
+               }
+               flash->bank_curr = curr_bank;
+       } else {
+               flash->bank_curr = curr_bank;
+       }
+#endif
+
+       /* Flash powers up read-only, so clear BP# bits */
+#if defined(CONFIG_SPI_FLASH_ATMEL) || \
+       defined(CONFIG_SPI_FLASH_MACRONIX) || \
+       defined(CONFIG_SPI_FLASH_SST)
+               spi_flash_cmd_write_status(flash, 0);
+#endif
+
+       return flash;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
+{
+       fdt_addr_t addr;
+       fdt_size_t size;
+       int node;
+
+       /* If there is no node, do nothing */
+       node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
+       if (node < 0)
+               return 0;
+
+       addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
+       if (addr == FDT_ADDR_T_NONE) {
+               debug("%s: Cannot decode address\n", __func__);
+               return 0;
+       }
+
+       if (flash->size != size) {
+               debug("%s: Memory map must cover entire device\n", __func__);
+               return -1;
+       }
+       flash->memory_map = (void *)addr;
+
+       return 0;
+}
+#endif /* CONFIG_OF_CONTROL */
+
+struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+               unsigned int max_hz, unsigned int spi_mode)
+{
+       struct spi_slave *spi;
+       struct spi_flash *flash = NULL;
+       u8 idcode[5];
+       int ret;
+
+       /* Setup spi_slave */
+       spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
+       if (!spi) {
+               printf("SF: Failed to set up slave\n");
+               return NULL;
+       }
+
+       /* Claim spi bus */
+       ret = spi_claim_bus(spi);
+       if (ret) {
+               debug("SF: Failed to claim SPI bus: %d\n", ret);
+               goto err_claim_bus;
+       }
+
+       /* Read the ID codes */
+       ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
+       if (ret) {
+               printf("SF: Failed to get idcodes\n");
+               goto err_read_id;
+       }
+
+#ifdef DEBUG
+       printf("SF: Got idcodes\n");
+       print_buffer(0, idcode, 1, sizeof(idcode), 0);
+#endif
+
+       /* Validate params from spi_flash_params table */
+       flash = spi_flash_validate_params(spi, idcode);
+       if (!flash)
+               goto err_read_id;
+
+#ifdef CONFIG_OF_CONTROL
+       if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
+               debug("SF: FDT decode error\n");
+               goto err_read_id;
+       }
+#endif
+#ifndef CONFIG_SPL_BUILD
+       printf("SF: Detected %s with page size ", flash->name);
+       print_size(flash->page_size, ", erase size ");
+       print_size(flash->erase_size, ", total ");
+       print_size(flash->size, "");
+       if (flash->memory_map)
+               printf(", mapped at %p", flash->memory_map);
+       puts("\n");
+#endif
+#ifndef CONFIG_SPI_FLASH_BAR
+       if (flash->size > SPI_FLASH_16MB_BOUN) {
+               puts("SF: Warning - Only lower 16MiB accessible,");
+               puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
+       }
+#endif
+
+       /* Release spi bus */
+       spi_release_bus(spi);
+
+       return flash;
+
+err_read_id:
+       spi_release_bus(spi);
+err_claim_bus:
+       spi_free_slave(spi);
+       return NULL;
+}
+
+void spi_flash_free(struct spi_flash *flash)
+{
+       spi_free_slave(flash->spi);
+       free(flash);
+}
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
deleted file mode 100644 (file)
index fa7ac8c..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2009 Freescale Semiconductor, Inc.
- *
- * Author: Mingkai Hu (Mingkai.hu@freescale.com)
- * Based on stmicro.c by Wolfgang Denk (wd@denx.de),
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com),
- * and  Jason McMullan (mcmullan@netapp.com)
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct spansion_spi_flash_params {
-       u16 idcode1;
-       u16 idcode2;
-       u16 pages_per_sector;
-       u16 nr_sectors;
-       const char *name;
-};
-
-static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
-       {
-               .idcode1 = 0x0213,
-               .idcode2 = 0,
-               .pages_per_sector = 256,
-               .nr_sectors = 16,
-               .name = "S25FL008A",
-       },
-       {
-               .idcode1 = 0x0214,
-               .idcode2 = 0,
-               .pages_per_sector = 256,
-               .nr_sectors = 32,
-               .name = "S25FL016A",
-       },
-       {
-               .idcode1 = 0x0215,
-               .idcode2 = 0,
-               .pages_per_sector = 256,
-               .nr_sectors = 64,
-               .name = "S25FL032A",
-       },
-       {
-               .idcode1 = 0x0216,
-               .idcode2 = 0,
-               .pages_per_sector = 256,
-               .nr_sectors = 128,
-               .name = "S25FL064A",
-       },
-       {
-               .idcode1 = 0x2018,
-               .idcode2 = 0x0301,
-               .pages_per_sector = 256,
-               .nr_sectors = 256,
-               .name = "S25FL128P_64K",
-       },
-       {
-               .idcode1 = 0x2018,
-               .idcode2 = 0x0300,
-               .pages_per_sector = 1024,
-               .nr_sectors = 64,
-               .name = "S25FL128P_256K",
-       },
-       {
-               .idcode1 = 0x0215,
-               .idcode2 = 0x4d00,
-               .pages_per_sector = 256,
-               .nr_sectors = 64,
-               .name = "S25FL032P",
-       },
-       {
-               .idcode1 = 0x0216,
-               .idcode2 = 0x4d00,
-               .pages_per_sector = 256,
-               .nr_sectors = 128,
-               .name = "S25FL064P",
-       },
-       {
-               .idcode1 = 0x2018,
-               .idcode2 = 0x4d01,
-               .pages_per_sector = 256,
-               .nr_sectors = 256,
-               .name = "S25FL129P_64K/S25FL128S_64K",
-       },
-       {
-               .idcode1 = 0x0219,
-               .idcode2 = 0x4d01,
-               .pages_per_sector = 256,
-               .nr_sectors = 512,
-               .name = "S25FL256S_64K",
-       },
-       {
-               .idcode1 = 0x0220,
-               .idcode2 = 0x4d01,
-               .pages_per_sector = 256,
-               .nr_sectors = 1024,
-               .name = "S25FL512S_64K",
-       },
-};
-
-struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
-{
-       const struct spansion_spi_flash_params *params;
-       struct spi_flash *flash;
-       unsigned int i;
-       unsigned short jedec, ext_jedec;
-
-       jedec = idcode[1] << 8 | idcode[2];
-       ext_jedec = idcode[3] << 8 | idcode[4];
-
-       for (i = 0; i < ARRAY_SIZE(spansion_spi_flash_table); i++) {
-               params = &spansion_spi_flash_table[i];
-               if (params->idcode1 == jedec) {
-                       if (params->idcode2 == ext_jedec)
-                               break;
-               }
-       }
-
-       if (i == ARRAY_SIZE(spansion_spi_flash_table)) {
-               debug("SF: Unsupported SPANSION ID %04x %04x\n",
-                     jedec, ext_jedec);
-               return NULL;
-       }
-
-       flash = spi_flash_alloc_base(spi, params->name);
-       if (!flash) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-
-       flash->page_size = 256;
-       flash->sector_size = 256 * params->pages_per_sector;
-       flash->size = flash->sector_size * params->nr_sectors;
-
-       return flash;
-}
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
deleted file mode 100644 (file)
index 5d5055f..0000000
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * SPI flash interface
- *
- * Copyright (C) 2008 Atmel Corporation
- * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <fdtdec.h>
-#include <malloc.h>
-#include <spi.h>
-#include <spi_flash.h>
-#include <watchdog.h>
-
-#include "spi_flash_internal.h"
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static void spi_flash_addr(u32 addr, u8 *cmd)
-{
-       /* cmd[0] is actual command */
-       cmd[1] = addr >> 16;
-       cmd[2] = addr >> 8;
-       cmd[3] = addr >> 0;
-}
-
-static int spi_flash_read_write(struct spi_slave *spi,
-                               const u8 *cmd, size_t cmd_len,
-                               const u8 *data_out, u8 *data_in,
-                               size_t data_len)
-{
-       unsigned long flags = SPI_XFER_BEGIN;
-       int ret;
-
-       if (data_len == 0)
-               flags |= SPI_XFER_END;
-
-       ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
-       if (ret) {
-               debug("SF: Failed to send command (%zu bytes): %d\n",
-                     cmd_len, ret);
-       } else if (data_len != 0) {
-               ret = spi_xfer(spi, data_len * 8, data_out, data_in,
-                                       SPI_XFER_END);
-               if (ret)
-                       debug("SF: Failed to transfer %zu bytes of data: %d\n",
-                             data_len, ret);
-       }
-
-       return ret;
-}
-
-int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
-{
-       return spi_flash_cmd_read(spi, &cmd, 1, response, len);
-}
-
-int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
-               size_t cmd_len, void *data, size_t data_len)
-{
-       return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len);
-}
-
-int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
-               const void *data, size_t data_len)
-{
-       return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
-}
-
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timebase;
-       int ret;
-       u8 status;
-       u8 check_status = 0x0;
-       u8 poll_bit = STATUS_WIP;
-       u8 cmd = flash->poll_cmd;
-
-       if (cmd == CMD_FLAG_STATUS) {
-               poll_bit = STATUS_PEC;
-               check_status = poll_bit;
-       }
-
-       ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-       if (ret) {
-               debug("SF: fail to read %s status register\n",
-                     cmd == CMD_READ_STATUS ? "read" : "flag");
-               return ret;
-       }
-
-       timebase = get_timer(0);
-       do {
-               WATCHDOG_RESET();
-
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret)
-                       return -1;
-
-               if ((status & poll_bit) == check_status)
-                       break;
-
-       } while (get_timer(timebase) < timeout);
-
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-       if ((status & poll_bit) == check_status)
-               return 0;
-
-       /* Timed out */
-       debug("SF: time out!\n");
-       return -1;
-}
-
-int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
-               size_t cmd_len, const void *buf, size_t buf_len)
-{
-       struct spi_slave *spi = flash->spi;
-       unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
-       int ret;
-
-       if (buf == NULL)
-               timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: unable to claim SPI bus\n");
-               return ret;
-       }
-
-       ret = spi_flash_cmd_write_enable(flash);
-       if (ret < 0) {
-               debug("SF: enabling write failed\n");
-               return ret;
-       }
-
-       ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
-       if (ret < 0) {
-               debug("SF: write cmd failed\n");
-               return ret;
-       }
-
-       ret = spi_flash_cmd_wait_ready(flash, timeout);
-       if (ret < 0) {
-               debug("SF: write %s timed out\n",
-                     timeout == SPI_FLASH_PROG_TIMEOUT ?
-                       "program" : "page erase");
-               return ret;
-       }
-
-       spi_release_bus(spi);
-
-       return ret;
-}
-
-int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
-{
-       u32 erase_size;
-       u8 cmd[4];
-       int ret = -1;
-
-       erase_size = flash->sector_size;
-       if (offset % erase_size || len % erase_size) {
-               debug("SF: Erase offset/length not multiple of erase size\n");
-               return -1;
-       }
-
-       if (erase_size == 4096)
-               cmd[0] = CMD_ERASE_4K;
-       else
-               cmd[0] = CMD_ERASE_64K;
-
-       while (len) {
-#ifdef CONFIG_SPI_FLASH_BAR
-               u8 bank_sel;
-
-               bank_sel = offset / SPI_FLASH_16MB_BOUN;
-
-               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
-               if (ret) {
-                       debug("SF: fail to set bank%d\n", bank_sel);
-                       return ret;
-               }
-#endif
-               spi_flash_addr(offset, cmd);
-
-               debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
-                     cmd[2], cmd[3], offset);
-
-               ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
-               if (ret < 0) {
-                       debug("SF: erase failed\n");
-                       break;
-               }
-
-               offset += erase_size;
-               len -= erase_size;
-       }
-
-       return ret;
-}
-
-int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
-               size_t len, const void *buf)
-{
-       unsigned long byte_addr, page_size;
-       size_t chunk_len, actual;
-       u8 cmd[4];
-       int ret = -1;
-
-       page_size = flash->page_size;
-
-       cmd[0] = CMD_PAGE_PROGRAM;
-       for (actual = 0; actual < len; actual += chunk_len) {
-#ifdef CONFIG_SPI_FLASH_BAR
-               u8 bank_sel;
-
-               bank_sel = offset / SPI_FLASH_16MB_BOUN;
-
-               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
-               if (ret) {
-                       debug("SF: fail to set bank%d\n", bank_sel);
-                       return ret;
-               }
-#endif
-               byte_addr = offset % page_size;
-               chunk_len = min(len - actual, page_size - byte_addr);
-
-               if (flash->spi->max_write_size)
-                       chunk_len = min(chunk_len, flash->spi->max_write_size);
-
-               spi_flash_addr(offset, cmd);
-
-               debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
-                     buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
-               ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
-                                       buf + actual, chunk_len);
-               if (ret < 0) {
-                       debug("SF: write failed\n");
-                       break;
-               }
-
-               offset += chunk_len;
-       }
-
-       return ret;
-}
-
-int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
-               size_t cmd_len, void *data, size_t data_len)
-{
-       struct spi_slave *spi = flash->spi;
-       int ret;
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: unable to claim SPI bus\n");
-               return ret;
-       }
-
-       ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
-       if (ret < 0) {
-               debug("SF: read cmd failed\n");
-               return ret;
-       }
-
-       spi_release_bus(spi);
-
-       return ret;
-}
-
-int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
-               size_t len, void *data)
-{
-       u8 cmd[5], bank_sel = 0;
-       u32 remain_len, read_len;
-       int ret = -1;
-
-       /* Handle memory-mapped SPI */
-       if (flash->memory_map) {
-               memcpy(data, flash->memory_map + offset, len);
-               return 0;
-       }
-
-       cmd[0] = CMD_READ_ARRAY_FAST;
-       cmd[4] = 0x00;
-
-       while (len) {
-#ifdef CONFIG_SPI_FLASH_BAR
-               bank_sel = offset / SPI_FLASH_16MB_BOUN;
-
-               ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
-               if (ret) {
-                       debug("SF: fail to set bank%d\n", bank_sel);
-                       return ret;
-               }
-#endif
-               remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset);
-               if (len < remain_len)
-                       read_len = len;
-               else
-                       read_len = remain_len;
-
-               spi_flash_addr(offset, cmd);
-
-               ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
-                                                       data, read_len);
-               if (ret < 0) {
-                       debug("SF: read failed\n");
-                       break;
-               }
-
-               offset += read_len;
-               len -= read_len;
-               data += read_len;
-       }
-
-       return ret;
-}
-
-int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
-{
-       u8 cmd;
-       int ret;
-
-       cmd = CMD_WRITE_STATUS;
-       ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1);
-       if (ret < 0) {
-               debug("SF: fail to write status register\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-#ifdef CONFIG_SPI_FLASH_BAR
-int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
-{
-       u8 cmd;
-       int ret;
-
-       if (flash->bank_curr == bank_sel) {
-               debug("SF: not require to enable bank%d\n", bank_sel);
-               return 0;
-       }
-
-       cmd = flash->bank_write_cmd;
-       ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
-       if (ret < 0) {
-               debug("SF: fail to write bank register\n");
-               return ret;
-       }
-       flash->bank_curr = bank_sel;
-
-       return 0;
-}
-
-int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0)
-{
-       u8 cmd;
-       u8 curr_bank = 0;
-
-       /* discover bank cmds */
-       switch (idcode0) {
-       case SPI_FLASH_SPANSION_IDCODE0:
-               flash->bank_read_cmd = CMD_BANKADDR_BRRD;
-               flash->bank_write_cmd = CMD_BANKADDR_BRWR;
-               break;
-       case SPI_FLASH_STMICRO_IDCODE0:
-       case SPI_FLASH_WINBOND_IDCODE0:
-               flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
-               flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
-               break;
-       default:
-               printf("SF: Unsupported bank commands %02x\n", idcode0);
-               return -1;
-       }
-
-       /* read the bank reg - on which bank the flash is in currently */
-       cmd = flash->bank_read_cmd;
-       if (flash->size > SPI_FLASH_16MB_BOUN) {
-               if (spi_flash_read_common(flash, &cmd, 1, &curr_bank, 1)) {
-                       debug("SF: fail to read bank addr register\n");
-                       return -1;
-               }
-               flash->bank_curr = curr_bank;
-       } else {
-               flash->bank_curr = curr_bank;
-       }
-
-       return 0;
-}
-#endif
-
-#ifdef CONFIG_OF_CONTROL
-int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
-{
-       fdt_addr_t addr;
-       fdt_size_t size;
-       int node;
-
-       /* If there is no node, do nothing */
-       node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
-       if (node < 0)
-               return 0;
-
-       addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
-       if (addr == FDT_ADDR_T_NONE) {
-               debug("%s: Cannot decode address\n", __func__);
-               return 0;
-       }
-
-       if (flash->size != size) {
-               debug("%s: Memory map must cover entire device\n", __func__);
-               return -1;
-       }
-       flash->memory_map = (void *)addr;
-
-       return 0;
-}
-#endif /* CONFIG_OF_CONTROL */
-
-/*
- * The following table holds all device probe functions
- *
- * shift:  number of continuation bytes before the ID
- * idcode: the expected IDCODE or 0xff for non JEDEC devices
- * probe:  the function to call
- *
- * Non JEDEC devices should be ordered in the table such that
- * the probe functions with best detection algorithms come first.
- *
- * Several matching entries are permitted, they will be tried
- * in sequence until a probe function returns non NULL.
- *
- * IDCODE_CONT_LEN may be redefined if a device needs to declare a
- * larger "shift" value.  IDCODE_PART_LEN generally shouldn't be
- * changed.  This is the max number of bytes probe functions may
- * examine when looking up part-specific identification info.
- *
- * Probe functions will be given the idcode buffer starting at their
- * manu id byte (the "idcode" in the table below).  In other words,
- * all of the continuation bytes will be skipped (the "shift" below).
- */
-#define IDCODE_CONT_LEN 0
-#define IDCODE_PART_LEN 5
-static const struct {
-       const u8 shift;
-       const u8 idcode;
-       struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
-} flashes[] = {
-       /* Keep it sorted by define name */
-#ifdef CONFIG_SPI_FLASH_ATMEL
-       { 0, 0x1f, spi_flash_probe_atmel, },
-#endif
-#ifdef CONFIG_SPI_FLASH_EON
-       { 0, 0x1c, spi_flash_probe_eon, },
-#endif
-#ifdef CONFIG_SPI_FLASH_GIGADEVICE
-       { 0, 0xc8, spi_flash_probe_gigadevice, },
-#endif
-#ifdef CONFIG_SPI_FLASH_MACRONIX
-       { 0, 0xc2, spi_flash_probe_macronix, },
-#endif
-#ifdef CONFIG_SPI_FLASH_SPANSION
-       { 0, 0x01, spi_flash_probe_spansion, },
-#endif
-#ifdef CONFIG_SPI_FLASH_SST
-       { 0, 0xbf, spi_flash_probe_sst, },
-#endif
-#ifdef CONFIG_SPI_FLASH_STMICRO
-       { 0, 0x20, spi_flash_probe_stmicro, },
-#endif
-#ifdef CONFIG_SPI_FLASH_WINBOND
-       { 0, 0xef, spi_flash_probe_winbond, },
-#endif
-#ifdef CONFIG_SPI_FRAM_RAMTRON
-       { 6, 0xc2, spi_fram_probe_ramtron, },
-# undef IDCODE_CONT_LEN
-# define IDCODE_CONT_LEN 6
-#endif
-       /* Keep it sorted by best detection */
-#ifdef CONFIG_SPI_FLASH_STMICRO
-       { 0, 0xff, spi_flash_probe_stmicro, },
-#endif
-#ifdef CONFIG_SPI_FRAM_RAMTRON_NON_JEDEC
-       { 0, 0xff, spi_fram_probe_ramtron, },
-#endif
-};
-#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
-
-struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
-               unsigned int max_hz, unsigned int spi_mode)
-{
-       struct spi_slave *spi;
-       struct spi_flash *flash = NULL;
-       int ret, i, shift;
-       u8 idcode[IDCODE_LEN], *idp;
-
-       spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
-       if (!spi) {
-               printf("SF: Failed to set up slave\n");
-               return NULL;
-       }
-
-       ret = spi_claim_bus(spi);
-       if (ret) {
-               debug("SF: Failed to claim SPI bus: %d\n", ret);
-               goto err_claim_bus;
-       }
-
-       /* Read the ID codes */
-       ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
-       if (ret)
-               goto err_read_id;
-
-#ifdef DEBUG
-       printf("SF: Got idcodes\n");
-       print_buffer(0, idcode, 1, sizeof(idcode), 0);
-#endif
-
-       /* count the number of continuation bytes */
-       for (shift = 0, idp = idcode;
-            shift < IDCODE_CONT_LEN && *idp == 0x7f;
-            ++shift, ++idp)
-               continue;
-
-       /* search the table for matches in shift and id */
-       for (i = 0; i < ARRAY_SIZE(flashes); ++i)
-               if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
-                       /* we have a match, call probe */
-                       flash = flashes[i].probe(spi, idp);
-                       if (flash)
-                               break;
-               }
-
-       if (!flash) {
-               printf("SF: Unsupported manufacturer %02x\n", *idp);
-               goto err_manufacturer_probe;
-       }
-
-#ifdef CONFIG_SPI_FLASH_BAR
-       /* Configure the BAR - disover bank cmds and read current bank  */
-       ret = spi_flash_bank_config(flash, *idp);
-       if (ret < 0)
-               goto err_manufacturer_probe;
-#endif
-
-#ifdef CONFIG_OF_CONTROL
-       if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
-               debug("SF: FDT decode error\n");
-               goto err_manufacturer_probe;
-       }
-#endif
-#ifndef CONFIG_SPL_BUILD
-       printf("SF: Detected %s with page size ", flash->name);
-       print_size(flash->sector_size, ", total ");
-       print_size(flash->size, "");
-       if (flash->memory_map)
-               printf(", mapped at %p", flash->memory_map);
-       puts("\n");
-#endif
-#ifndef CONFIG_SPI_FLASH_BAR
-       if (flash->size > SPI_FLASH_16MB_BOUN) {
-               puts("SF: Warning - Only lower 16MiB accessible,");
-               puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
-       }
-#endif
-
-       spi_release_bus(spi);
-
-       return flash;
-
-err_manufacturer_probe:
-err_read_id:
-       spi_release_bus(spi);
-err_claim_bus:
-       spi_free_slave(spi);
-       return NULL;
-}
-
-void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,
-                        const char *name)
-{
-       struct spi_flash *flash;
-       void *ptr;
-
-       ptr = malloc(size);
-       if (!ptr) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-       memset(ptr, '\0', size);
-       flash = (struct spi_flash *)(ptr + offset);
-
-       /* Set up some basic fields - caller will sort out sizes */
-       flash->spi = spi;
-       flash->name = name;
-       flash->poll_cmd = CMD_READ_STATUS;
-
-       flash->read = spi_flash_cmd_read_fast;
-       flash->write = spi_flash_cmd_write_multi;
-       flash->erase = spi_flash_cmd_erase;
-
-       return flash;
-}
-
-void spi_flash_free(struct spi_flash *flash)
-{
-       spi_free_slave(flash->spi);
-       free(flash);
-}
diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c
deleted file mode 100644 (file)
index 256867c..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Driver for SST serial flashes
- *
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- * Copyright 2008, Network Appliance Inc.
- * Jason McMullan <mcmullan@netapp.com>
- * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
- * Copyright (c) 2008-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-#define CMD_SST_BP             0x02    /* Byte Program */
-#define CMD_SST_AAI_WP         0xAD    /* Auto Address Incr Word Program */
-
-#define SST_SR_WIP             (1 << 0)        /* Write-in-Progress */
-#define SST_SR_WEL             (1 << 1)        /* Write enable */
-#define SST_SR_BP0             (1 << 2)        /* Block Protection 0 */
-#define SST_SR_BP1             (1 << 3)        /* Block Protection 1 */
-#define SST_SR_BP2             (1 << 4)        /* Block Protection 2 */
-#define SST_SR_AAI             (1 << 6)        /* Addressing mode */
-#define SST_SR_BPL             (1 << 7)        /* BP bits lock */
-
-#define SST_FEAT_WP            (1 << 0)        /* Supports AAI word program */
-#define SST_FEAT_MBP           (1 << 1)        /* Supports multibyte program */
-
-struct sst_spi_flash_params {
-       u8 idcode1;
-       u8 flags;
-       u16 nr_sectors;
-       const char *name;
-};
-
-struct sst_spi_flash {
-       struct spi_flash flash;
-       const struct sst_spi_flash_params *params;
-};
-
-static const struct sst_spi_flash_params sst_spi_flash_table[] = {
-       {
-               .idcode1 = 0x8d,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 128,
-               .name = "SST25VF040B",
-       },
-       {
-               .idcode1 = 0x8e,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 256,
-               .name = "SST25VF080B",
-       },
-       {
-               .idcode1 = 0x41,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 512,
-               .name = "SST25VF016B",
-       },
-       {
-               .idcode1 = 0x4a,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 1024,
-               .name = "SST25VF032B",
-       },
-       {
-               .idcode1 = 0x4b,
-               .flags = SST_FEAT_MBP,
-               .nr_sectors = 2048,
-               .name = "SST25VF064C",
-       },
-       {
-               .idcode1 = 0x01,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 16,
-               .name = "SST25WF512",
-       },
-       {
-               .idcode1 = 0x02,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 32,
-               .name = "SST25WF010",
-       },
-       {
-               .idcode1 = 0x03,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 64,
-               .name = "SST25WF020",
-       },
-       {
-               .idcode1 = 0x04,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 128,
-               .name = "SST25WF040",
-       },
-       {
-               .idcode1 = 0x05,
-               .flags = SST_FEAT_WP,
-               .nr_sectors = 256,
-               .name = "SST25WF080",
-       },
-};
-
-static int
-sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
-{
-       int ret;
-       u8 cmd[4] = {
-               CMD_SST_BP,
-               offset >> 16,
-               offset >> 8,
-               offset,
-       };
-
-       debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
-             spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
-
-       ret = spi_flash_cmd_write_enable(flash);
-       if (ret)
-               return ret;
-
-       ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
-       if (ret)
-               return ret;
-
-       return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-}
-
-static int
-sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
-{
-       size_t actual, cmd_len;
-       int ret;
-       u8 cmd[4];
-
-       ret = spi_claim_bus(flash->spi);
-       if (ret) {
-               debug("SF: Unable to claim SPI bus\n");
-               return ret;
-       }
-
-       /* If the data is not word aligned, write out leading single byte */
-       actual = offset % 2;
-       if (actual) {
-               ret = sst_byte_write(flash, offset, buf);
-               if (ret)
-                       goto done;
-       }
-       offset += actual;
-
-       ret = spi_flash_cmd_write_enable(flash);
-       if (ret)
-               goto done;
-
-       cmd_len = 4;
-       cmd[0] = CMD_SST_AAI_WP;
-       cmd[1] = offset >> 16;
-       cmd[2] = offset >> 8;
-       cmd[3] = offset;
-
-       for (; actual < len - 1; actual += 2) {
-               debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
-                     spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
-                     cmd[0], offset);
-
-               ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
-                                       buf + actual, 2);
-               if (ret) {
-                       debug("SF: sst word program failed\n");
-                       break;
-               }
-
-               ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-               if (ret)
-                       break;
-
-               cmd_len = 1;
-               offset += 2;
-       }
-
-       if (!ret)
-               ret = spi_flash_cmd_write_disable(flash);
-
-       /* If there is a single trailing byte, write it out */
-       if (!ret && actual != len)
-               ret = sst_byte_write(flash, offset, buf + actual);
-
- done:
-       debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
-             ret ? "failure" : "success", len, offset - actual);
-
-       spi_release_bus(flash->spi);
-       return ret;
-}
-
-struct spi_flash *
-spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
-{
-       const struct sst_spi_flash_params *params;
-       struct sst_spi_flash *stm;
-       size_t i;
-
-       for (i = 0; i < ARRAY_SIZE(sst_spi_flash_table); ++i) {
-               params = &sst_spi_flash_table[i];
-               if (params->idcode1 == idcode[2])
-                       break;
-       }
-
-       if (i == ARRAY_SIZE(sst_spi_flash_table)) {
-               debug("SF: Unsupported SST ID %02x\n", idcode[1]);
-               return NULL;
-       }
-
-       stm = spi_flash_alloc(struct sst_spi_flash, spi, params->name);
-       if (!stm) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-
-       stm->params = params;
-
-       if (stm->params->flags & SST_FEAT_WP)
-               stm->flash.write = sst_write_wp;
-       stm->flash.page_size = 256;
-       stm->flash.sector_size = 4096;
-       stm->flash.size = stm->flash.sector_size * params->nr_sectors;
-
-       /* Flash powers up read-only, so clear BP# bits */
-       spi_flash_cmd_write_status(&stm->flash, 0);
-
-       return &stm->flash;
-}
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
deleted file mode 100644 (file)
index c5fa64e..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * Copyright 2008, Network Appliance Inc.
- * Jason McMullan <mcmullan@netapp.com>
- *
- * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-/* M25Pxx-specific commands */
-#define CMD_M25PXX_RES 0xab    /* Release from DP, and Read Signature */
-
-struct stmicro_spi_flash_params {
-       u16 id;
-       u16 pages_per_sector;
-       u16 nr_sectors;
-       const char *name;
-};
-
-static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
-       {
-               .id = 0x2011,
-               .pages_per_sector = 128,
-               .nr_sectors = 4,
-               .name = "M25P10",
-       },
-       {
-               .id = 0x2015,
-               .pages_per_sector = 256,
-               .nr_sectors = 32,
-               .name = "M25P16",
-       },
-       {
-               .id = 0x2012,
-               .pages_per_sector = 256,
-               .nr_sectors = 4,
-               .name = "M25P20",
-       },
-       {
-               .id = 0x2016,
-               .pages_per_sector = 256,
-               .nr_sectors = 64,
-               .name = "M25P32",
-       },
-       {
-               .id = 0x2013,
-               .pages_per_sector = 256,
-               .nr_sectors = 8,
-               .name = "M25P40",
-       },
-       {
-               .id = 0x2017,
-               .pages_per_sector = 256,
-               .nr_sectors = 128,
-               .name = "M25P64",
-       },
-       {
-               .id = 0x2014,
-               .pages_per_sector = 256,
-               .nr_sectors = 16,
-               .name = "M25P80",
-       },
-       {
-               .id = 0x2018,
-               .pages_per_sector = 1024,
-               .nr_sectors = 64,
-               .name = "M25P128",
-       },
-       {
-               .id = 0xba16,
-               .pages_per_sector = 256,
-               .nr_sectors = 64,
-               .name = "N25Q32",
-       },
-       {
-               .id = 0xbb16,
-               .pages_per_sector = 256,
-               .nr_sectors = 64,
-               .name = "N25Q32A",
-       },
-       {
-               .id = 0xba17,
-               .pages_per_sector = 256,
-               .nr_sectors = 128,
-               .name = "N25Q064",
-       },
-       {
-               .id = 0xbb17,
-               .pages_per_sector = 256,
-               .nr_sectors = 128,
-               .name = "N25Q64A",
-       },
-       {
-               .id = 0xba18,
-               .pages_per_sector = 256,
-               .nr_sectors = 256,
-               .name = "N25Q128",
-       },
-       {
-               .id = 0xbb18,
-               .pages_per_sector = 256,
-               .nr_sectors = 256,
-               .name = "N25Q128A",
-       },
-       {
-               .id = 0xba19,
-               .pages_per_sector = 256,
-               .nr_sectors = 512,
-               .name = "N25Q256",
-       },
-       {
-               .id = 0xbb19,
-               .pages_per_sector = 256,
-               .nr_sectors = 512,
-               .name = "N25Q256A",
-       },
-       {
-               .id = 0xba20,
-               .pages_per_sector = 256,
-               .nr_sectors = 1024,
-               .name = "N25Q512",
-       },
-       {
-               .id = 0xbb20,
-               .pages_per_sector = 256,
-               .nr_sectors = 1024,
-               .name = "N25Q512A",
-       },
-       {
-               .id = 0xba21,
-               .pages_per_sector = 256,
-               .nr_sectors = 2048,
-               .name = "N25Q1024",
-       },
-       {
-               .id = 0xbb21,
-               .pages_per_sector = 256,
-               .nr_sectors = 2048,
-               .name = "N25Q1024A",
-       },
-};
-
-struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode)
-{
-       const struct stmicro_spi_flash_params *params;
-       struct spi_flash *flash;
-       unsigned int i;
-       u16 id;
-
-       if (idcode[0] == 0xff) {
-               i = spi_flash_cmd(spi, CMD_M25PXX_RES,
-                                 idcode, 4);
-               if (i)
-                       return NULL;
-               if ((idcode[3] & 0xf0) == 0x10) {
-                       idcode[0] = 0x20;
-                       idcode[1] = 0x20;
-                       idcode[2] = idcode[3] + 1;
-               } else {
-                       return NULL;
-               }
-       }
-
-       id = ((idcode[1] << 8) | idcode[2]);
-
-       for (i = 0; i < ARRAY_SIZE(stmicro_spi_flash_table); i++) {
-               params = &stmicro_spi_flash_table[i];
-               if (params->id == id)
-                       break;
-       }
-
-       if (i == ARRAY_SIZE(stmicro_spi_flash_table)) {
-               debug("SF: Unsupported STMicro ID %04x\n", id);
-               return NULL;
-       }
-
-       flash = spi_flash_alloc_base(spi, params->name);
-       if (!flash) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-
-       flash->page_size = 256;
-       flash->sector_size = 256 * params->pages_per_sector;
-       flash->size = flash->sector_size * params->nr_sectors;
-
-       /* for >= 512MiB flashes, use flag status instead of read_status */
-       if (flash->size >= 0x4000000)
-               flash->poll_cmd = CMD_FLAG_STATUS;
-
-       return flash;
-}
diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
deleted file mode 100644 (file)
index b31911a..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2008, Network Appliance Inc.
- * Author: Jason McMullan <mcmullan <at> netapp.com>
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct winbond_spi_flash_params {
-       uint16_t        id;
-       uint16_t        nr_blocks;
-       const char      *name;
-};
-
-static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
-       {
-               .id                     = 0x2014,
-               .nr_blocks              = 16,
-               .name                   = "W25P80",
-       },
-       {
-               .id                     = 0x2015,
-               .nr_blocks              = 32,
-               .name                   = "W25P16",
-       },
-       {
-               .id                     = 0x2016,
-               .nr_blocks              = 64,
-               .name                   = "W25P32",
-       },
-       {
-               .id                     = 0x3013,
-               .nr_blocks              = 8,
-               .name                   = "W25X40",
-       },
-       {
-               .id                     = 0x3015,
-               .nr_blocks              = 32,
-               .name                   = "W25X16",
-       },
-       {
-               .id                     = 0x3016,
-               .nr_blocks              = 64,
-               .name                   = "W25X32",
-       },
-       {
-               .id                     = 0x3017,
-               .nr_blocks              = 128,
-               .name                   = "W25X64",
-       },
-       {
-               .id                     = 0x4014,
-               .nr_blocks              = 16,
-               .name                   = "W25Q80BL/W25Q80BV",
-       },
-       {
-               .id                     = 0x4015,
-               .nr_blocks              = 32,
-               .name                   = "W25Q16CL/W25Q16DV",
-       },
-       {
-               .id                     = 0x4016,
-               .nr_blocks              = 64,
-               .name                   = "W25Q32BV/W25Q32FV_SPI",
-       },
-       {
-               .id                     = 0x4017,
-               .nr_blocks              = 128,
-               .name                   = "W25Q64CV/W25Q64FV_SPI",
-       },
-       {
-               .id                     = 0x4018,
-               .nr_blocks              = 256,
-               .name                   = "W25Q128BV/W25Q128FV_SPI",
-       },
-       {
-               .id                     = 0x4019,
-               .nr_blocks              = 512,
-               .name                   = "W25Q256",
-       },
-       {
-               .id                     = 0x5014,
-               .nr_blocks              = 16,
-               .name                   = "W25Q80BW",
-       },
-       {
-               .id                     = 0x6015,
-               .nr_blocks              = 32,
-               .name                   = "W25Q16DW",
-       },
-       {
-               .id                     = 0x6016,
-               .nr_blocks              = 64,
-               .name                   = "W25Q32DW/W25Q32FV_QPI",
-       },
-       {
-               .id                     = 0x6017,
-               .nr_blocks              = 128,
-               .name                   = "W25Q64DW/W25Q64FV_QPI",
-       },
-       {
-               .id                     = 0x6018,
-               .nr_blocks              = 256,
-               .name                   = "W25Q128FW/W25Q128FV_QPI",
-       },
-};
-
-struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
-{
-       const struct winbond_spi_flash_params *params;
-       struct spi_flash *flash;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) {
-               params = &winbond_spi_flash_table[i];
-               if (params->id == ((idcode[1] << 8) | idcode[2]))
-                       break;
-       }
-
-       if (i == ARRAY_SIZE(winbond_spi_flash_table)) {
-               debug("SF: Unsupported Winbond ID %02x%02x\n",
-                     idcode[1], idcode[2]);
-               return NULL;
-       }
-
-       flash = spi_flash_alloc_base(spi, params->name);
-       if (!flash) {
-               debug("SF: Failed to allocate memory\n");
-               return NULL;
-       }
-
-       flash->page_size = 256;
-       flash->sector_size = (idcode[1] == 0x20) ? 65536 : 4096;
-       flash->size = 4096 * 16 * params->nr_blocks;
-
-       return flash;
-}
index c98867d..381ec42 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*-----------------------------------------------------------------------------+
  *
index 07fcb60..002fb81 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  */
 /*-----------------------------------------------------------------------------+
   |
index 5936f9b..60ed92d 100644 (file)
@@ -7,7 +7,7 @@
  *   Copyright 2010-2011 Freescale Semiconductor, Inc.
  *   author Andy Fleming
  *
- * Some code get from linux kenrel
+ * Some code copied from linux kernel
  * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
  */
 #include <miiphy.h>
index c4ed8ba..86ba6b5 100644 (file)
@@ -297,7 +297,7 @@ void pciauto_config_init(struct pci_controller *hose)
 {
        int i;
 
-       hose->pci_io = hose->pci_mem = NULL;
+       hose->pci_io = hose->pci_mem = hose->pci_prefetch = NULL;
 
        for (i = 0; i < hose->region_count; i++) {
                switch(hose->regions[i].flags) {
index d79971b..29ccc83 100644 (file)
@@ -184,18 +184,21 @@ int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                if (argc < 4)
                        return CMD_RET_USAGE;
 
+               if (!p->pbat) {
+                       printf("%s is not a battery\n", p->name);
+                       return CMD_RET_FAILURE;
+               }
+
                if (strcmp(argv[3], "state") == 0)
                        p->fg->fg_battery_check(p->pbat->fg, p);
 
                if (strcmp(argv[3], "charge") == 0) {
-                       if (p->pbat) {
-                               printf("BAT: %s charging (ctrl+c to break)\n",
-                                      p->name);
-                               if (p->low_power_mode)
-                                       p->low_power_mode();
-                               if (p->pbat->battery_charge)
-                                       p->pbat->battery_charge(p);
-                       }
+                       printf("BAT: %s charging (ctrl+c to break)\n",
+                              p->name);
+                       if (p->low_power_mode)
+                               p->low_power_mode();
+                       if (p->pbat->battery_charge)
+                               p->pbat->battery_charge(p);
                }
 
                return CMD_RET_SUCCESS;
index d69db58..febf419 100644 (file)
@@ -52,7 +52,7 @@ int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000,
 static int max98095_i2c_write(unsigned int reg, unsigned char data)
 {
        debug("%s: Write Addr : 0x%02X, Data :  0x%02X\n",
-               __func__, reg, data);
+             __func__, reg, data);
        return i2c_write(g_max98095_i2c_dev_addr, reg, 1, &data, 1);
 }
 
@@ -71,7 +71,7 @@ static unsigned int max98095_i2c_read(unsigned int reg, unsigned char *data)
        ret = i2c_read(g_max98095_i2c_dev_addr, reg, 1, data, 1);
        if (ret != 0) {
                debug("%s: Error while reading register %#04x\n",
-                       __func__, reg);
+                     __func__, reg);
                return -1;
        }
 
@@ -138,43 +138,57 @@ static int rate_value(int rate, u8 *value)
  * @return -1 for error  and 0  Success.
  */
 static int max98095_hw_params(struct max98095_priv *max98095,
-               unsigned int rate, unsigned int bits_per_sample)
+                             enum en_max_audio_interface aif_id,
+                             unsigned int rate, unsigned int bits_per_sample)
 {
        u8 regval;
        int error;
+       unsigned short M98095_DAI_CLKMODE;
+       unsigned short M98095_DAI_FORMAT;
+       unsigned short M98095_DAI_FILTERS;
+
+       if (aif_id == AIF1) {
+               M98095_DAI_CLKMODE = M98095_027_DAI1_CLKMODE;
+               M98095_DAI_FORMAT = M98095_02A_DAI1_FORMAT;
+               M98095_DAI_FILTERS = M98095_02E_DAI1_FILTERS;
+       } else {
+               M98095_DAI_CLKMODE = M98095_031_DAI2_CLKMODE;
+               M98095_DAI_FORMAT = M98095_034_DAI2_FORMAT;
+               M98095_DAI_FILTERS = M98095_038_DAI2_FILTERS;
+       }
 
        switch (bits_per_sample) {
        case 16:
-               error = max98095_update_bits(M98095_034_DAI2_FORMAT,
-                       M98095_DAI_WS, 0);
+               error = max98095_update_bits(M98095_DAI_FORMAT,
+                                            M98095_DAI_WS, 0);
                break;
        case 24:
-               error = max98095_update_bits(M98095_034_DAI2_FORMAT,
-                       M98095_DAI_WS, M98095_DAI_WS);
+               error = max98095_update_bits(M98095_DAI_FORMAT,
+                                            M98095_DAI_WS, M98095_DAI_WS);
                break;
        default:
                debug("%s: Illegal bits per sample %d.\n",
-                       __func__, bits_per_sample);
+                     __func__, bits_per_sample);
                return -1;
        }
 
        if (rate_value(rate, &regval)) {
                debug("%s: Failed to set sample rate to %d.\n",
-                       __func__, rate);
+                     __func__, rate);
                return -1;
        }
        max98095->rate = rate;
 
-       error |= max98095_update_bits(M98095_031_DAI2_CLKMODE,
-               M98095_CLKMODE_MASK, regval);
+       error |= max98095_update_bits(M98095_DAI_CLKMODE,
+                                     M98095_CLKMODE_MASK, regval);
 
        /* Update sample rate mode */
        if (rate < 50000)
-               error |= max98095_update_bits(M98095_038_DAI2_FILTERS,
-                       M98095_DAI_DHF, 0);
+               error |= max98095_update_bits(M98095_DAI_FILTERS,
+                                             M98095_DAI_DHF, 0);
        else
-               error |= max98095_update_bits(M98095_038_DAI2_FILTERS,
-                       M98095_DAI_DHF, M98095_DAI_DHF);
+               error |= max98095_update_bits(M98095_DAI_FILTERS,
+                                             M98095_DAI_DHF, M98095_DAI_DHF);
 
        if (error < 0) {
                debug("%s: Error setting hardware params.\n", __func__);
@@ -193,7 +207,7 @@ static int max98095_hw_params(struct max98095_priv *max98095,
  * @return -1 for error and 0 success.
  */
 static int max98095_set_sysclk(struct max98095_priv *max98095,
-                               unsigned int freq)
+                              unsigned int freq)
 {
        int error = 0;
 
@@ -235,22 +249,39 @@ static int max98095_set_sysclk(struct max98095_priv *max98095,
  *
  * @return -1 for error and 0  Success.
  */
-static int max98095_set_fmt(struct max98095_priv *max98095, int fmt)
+static int max98095_set_fmt(struct max98095_priv *max98095, int fmt,
+                           enum en_max_audio_interface aif_id)
 {
        u8 regval = 0;
        int error = 0;
+       unsigned short M98095_DAI_CLKCFG_HI;
+       unsigned short M98095_DAI_CLKCFG_LO;
+       unsigned short M98095_DAI_FORMAT;
+       unsigned short M98095_DAI_CLOCK;
 
        if (fmt == max98095->fmt)
                return 0;
 
        max98095->fmt = fmt;
 
+       if (aif_id == AIF1) {
+               M98095_DAI_CLKCFG_HI = M98095_028_DAI1_CLKCFG_HI;
+               M98095_DAI_CLKCFG_LO = M98095_029_DAI1_CLKCFG_LO;
+               M98095_DAI_FORMAT = M98095_02A_DAI1_FORMAT;
+               M98095_DAI_CLOCK = M98095_02B_DAI1_CLOCK;
+       } else {
+               M98095_DAI_CLKCFG_HI = M98095_032_DAI2_CLKCFG_HI;
+               M98095_DAI_CLKCFG_LO = M98095_033_DAI2_CLKCFG_LO;
+               M98095_DAI_FORMAT = M98095_034_DAI2_FORMAT;
+               M98095_DAI_CLOCK = M98095_035_DAI2_CLOCK;
+       }
+
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* Slave mode PLL */
-               error |= max98095_i2c_write(M98095_032_DAI2_CLKCFG_HI,
+               error |= max98095_i2c_write(M98095_DAI_CLKCFG_HI,
                                        0x80);
-               error |= max98095_i2c_write(M98095_033_DAI2_CLKCFG_LO,
+               error |= max98095_i2c_write(M98095_DAI_CLKCFG_LO,
                                        0x00);
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
@@ -292,12 +323,13 @@ static int max98095_set_fmt(struct max98095_priv *max98095, int fmt)
                return -1;
        }
 
-       error |= max98095_update_bits(M98095_034_DAI2_FORMAT,
-               M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI |
-               M98095_DAI_WCI, regval);
+       error |= max98095_update_bits(M98095_DAI_FORMAT,
+                                     M98095_DAI_MAS | M98095_DAI_DLY |
+                                     M98095_DAI_BCI | M98095_DAI_WCI,
+                                     regval);
 
-       error |= max98095_i2c_write(M98095_035_DAI2_CLOCK,
-               M98095_DAI_BSEL64);
+       error |= max98095_i2c_write(M98095_DAI_CLOCK,
+                                   M98095_DAI_BSEL64);
 
        if (error < 0) {
                debug("%s: Error setting i2s format.\n", __func__);
@@ -354,7 +386,8 @@ static int max98095_reset(void)
  *
  * @returns -1 for error  and 0 Success.
  */
-static int max98095_device_init(struct max98095_priv *max98095)
+static int max98095_device_init(struct max98095_priv *max98095,
+                               enum en_max_audio_interface aif_id)
 {
        unsigned char id;
        int error = 0;
@@ -374,7 +407,7 @@ static int max98095_device_init(struct max98095_priv *max98095)
        error = max98095_i2c_read(M98095_0FF_REV_ID, &id);
        if (error < 0) {
                debug("%s: Failure reading hardware revision: %d\n",
-                       __func__, id);
+                     __func__, id);
                goto err_access;
        }
        debug("%s: Hardware revision: %c\n", __func__, (id - 0x40) + 'A');
@@ -385,26 +418,28 @@ static int max98095_device_init(struct max98095_priv *max98095)
         * initialize registers to hardware default configuring audio
         * interface2 to DAC
         */
-       error |= max98095_i2c_write(M98095_048_MIX_DAC_LR,
-               M98095_DAI2M_TO_DACL|M98095_DAI2M_TO_DACR);
+       if (aif_id == AIF1)
+               error |= max98095_i2c_write(M98095_048_MIX_DAC_LR,
+                                           M98095_DAI1L_TO_DACL |
+                                           M98095_DAI1R_TO_DACR);
+       else
+               error |= max98095_i2c_write(M98095_048_MIX_DAC_LR,
+                                           M98095_DAI2M_TO_DACL |
+                                           M98095_DAI2M_TO_DACR);
 
        error |= max98095_i2c_write(M98095_092_PWR_EN_OUT,
-                       M98095_SPK_SPREADSPECTRUM);
-       error |= max98095_i2c_write(M98095_045_CFG_DSP, M98095_DSPNORMAL);
+                                   M98095_SPK_SPREADSPECTRUM);
        error |= max98095_i2c_write(M98095_04E_CFG_HP, M98095_HPNORMAL);
-
-       error |= max98095_i2c_write(M98095_02C_DAI1_IOCFG,
-                       M98095_S1NORMAL|M98095_SDATA);
-
-       error |= max98095_i2c_write(M98095_036_DAI2_IOCFG,
-                       M98095_S2NORMAL|M98095_SDATA);
-
-       error |= max98095_i2c_write(M98095_040_DAI3_IOCFG,
-                       M98095_S3NORMAL|M98095_SDATA);
+       if (aif_id == AIF1)
+               error |= max98095_i2c_write(M98095_02C_DAI1_IOCFG,
+                                           M98095_S1NORMAL | M98095_SDATA);
+       else
+               error |= max98095_i2c_write(M98095_036_DAI2_IOCFG,
+                                           M98095_S2NORMAL | M98095_SDATA);
 
        /* take the codec out of the shut down */
        error |= max98095_update_bits(M98095_097_PWR_SYS, M98095_SHDNRUN,
-                       M98095_SHDNRUN);
+                                     M98095_SHDNRUN);
        /* route DACL and DACR output to HO and Spekers */
        error |= max98095_i2c_write(M98095_050_MIX_SPK_LEFT, 0x01); /* DACL */
        error |= max98095_i2c_write(M98095_051_MIX_SPK_RIGHT, 0x01);/* DACR */
@@ -422,7 +457,10 @@ static int max98095_device_init(struct max98095_priv *max98095)
 
        /* Enable DAIs */
        error |= max98095_i2c_write(M98095_093_BIAS_CTRL, 0x30);
-       error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x07);
+       if (aif_id == AIF1)
+               error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x01);
+       else
+               error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x07);
 
 err_access:
        if (error < 0)
@@ -432,8 +470,9 @@ err_access:
 }
 
 static int max98095_do_init(struct sound_codec_info *pcodec_info,
-                       int sampling_rate, int mclk_freq,
-                       int bits_per_sample)
+                           enum en_max_audio_interface aif_id,
+                           int sampling_rate, int mclk_freq,
+                           int bits_per_sample)
 {
        int ret = 0;
 
@@ -443,15 +482,15 @@ static int max98095_do_init(struct sound_codec_info *pcodec_info,
        /* shift the device address by 1 for 7 bit addressing */
        g_max98095_i2c_dev_addr = pcodec_info->i2c_dev_addr >> 1;
 
-       if (pcodec_info->codec_type == CODEC_MAX_98095)
+       if (pcodec_info->codec_type == CODEC_MAX_98095) {
                g_max98095_info.devtype = MAX98095;
-       else {
+       else {
                debug("%s: Codec id [%d] not defined\n", __func__,
-                               pcodec_info->codec_type);
+                     pcodec_info->codec_type);
                return -1;
        }
 
-       ret = max98095_device_init(&g_max98095_info);
+       ret = max98095_device_init(&g_max98095_info, aif_id);
        if (ret < 0) {
                debug("%s: max98095 codec chip init failed\n", __func__);
                return ret;
@@ -463,14 +502,15 @@ static int max98095_do_init(struct sound_codec_info *pcodec_info,
                return ret;
        }
 
-       ret = max98095_hw_params(&g_max98095_info, sampling_rate,
-                               bits_per_sample);
+       ret = max98095_hw_params(&g_max98095_info, aif_id, sampling_rate,
+                                bits_per_sample);
 
        if (ret == 0) {
                ret = max98095_set_fmt(&g_max98095_info,
-                                       SND_SOC_DAIFMT_I2S |
-                                       SND_SOC_DAIFMT_NB_NF |
-                                       SND_SOC_DAIFMT_CBS_CFS);
+                                      SND_SOC_DAIFMT_I2S |
+                                      SND_SOC_DAIFMT_NB_NF |
+                                      SND_SOC_DAIFMT_CBS_CFS,
+                                      aif_id);
        }
 
        return ret;
@@ -529,8 +569,9 @@ static int get_max98095_codec_values(struct sound_codec_info *pcodec_info,
 }
 
 /* max98095 Device Initialisation */
-int max98095_init(const void *blob, int sampling_rate, int mclk_freq,
-                       int bits_per_sample)
+int max98095_init(const void *blob, enum en_max_audio_interface aif_id,
+                 int sampling_rate, int mclk_freq,
+                 int bits_per_sample)
 {
        int ret;
        int old_bus = i2c_get_bus_num();
@@ -538,12 +579,12 @@ int max98095_init(const void *blob, int sampling_rate, int mclk_freq,
 
        if (get_max98095_codec_values(pcodec_info, blob) < 0) {
                debug("FDT Codec values failed\n");
-                return -1;
+               return -1;
        }
 
        i2c_set_bus_num(pcodec_info->i2c_bus);
-       ret = max98095_do_init(pcodec_info, sampling_rate, mclk_freq,
-                               bits_per_sample);
+       ret = max98095_do_init(pcodec_info, aif_id, sampling_rate, mclk_freq,
+                              bits_per_sample);
        i2c_set_bus_num(old_bus);
 
        return ret;
index ae5eb14..44b1e3a 100644 (file)
 #ifndef _MAX98095_H
 #define _MAX98095_H
 
+/*  Available audio interface ports in wm8994 codec */
+enum en_max_audio_interface {
+       AIF1 = 1,
+       AIF2,
+};
+
 /*
  * MAX98095 Registers Definition
  */
  *
  * @returns -1 for error and 0 Success.
  */
-int max98095_init(const void *blob, int sampling_rate, int mclk_freq,
-                       int bits_per_sample);
+int max98095_init(const void *blob, enum en_max_audio_interface aif_id,
+                 int sampling_rate, int mclk_freq, int bits_per_sample);
 
 #endif
index 49921e5..47f155f 100644 (file)
@@ -65,9 +65,7 @@ static void i2s_txctrl(struct i2s_reg *i2s_reg, int on)
        if (on) {
                con |= CON_ACTIVE;
                con &= ~CON_TXCH_PAUSE;
-
        } else {
-
                con |=  CON_TXCH_PAUSE;
                con &= ~CON_ACTIVE;
        }
@@ -172,7 +170,7 @@ int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt)
                break;
        default:
                debug("%s: Invalid format priority [0x%x]\n", __func__,
-                       (fmt & SND_SOC_DAIFMT_FORMAT_MASK));
+                     (fmt & SND_SOC_DAIFMT_FORMAT_MASK));
                return -1;
        }
 
@@ -191,7 +189,7 @@ int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt)
                break;
        default:
                debug("%s: Invalid clock ploarity input [0x%x]\n", __func__,
-                       (fmt & SND_SOC_DAIFMT_INV_MASK));
+                     (fmt & SND_SOC_DAIFMT_INV_MASK));
                return -1;
        }
 
@@ -209,7 +207,7 @@ int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt)
                break;
        default:
                debug("%s: Invalid master selection [0x%x]\n", __func__,
-                       (fmt & SND_SOC_DAIFMT_MASTER_MASK));
+                     (fmt & SND_SOC_DAIFMT_MASTER_MASK));
                return -1;
        }
 
@@ -250,7 +248,7 @@ int i2s_set_samplesize(struct i2s_reg *i2s_reg, unsigned int blc)
                break;
        default:
                debug("%s: Invalid sample size input [0x%x]\n",
-                       __func__, blc);
+                     __func__, blc);
                return -1;
        }
        writel(mod, &i2s_reg->mod);
@@ -301,27 +299,58 @@ int i2s_tx_init(struct i2stx_info *pi2s_tx)
        int ret;
        struct i2s_reg *i2s_reg =
                                (struct i2s_reg *)pi2s_tx->base_address;
+       if (pi2s_tx->id == 0) {
+               /* Initialize GPIO for I2S-0 */
+               exynos_pinmux_config(PERIPH_ID_I2S0, 0);
+
+               /* Set EPLL Clock */
+               ret = set_epll_clk(pi2s_tx->samplingrate * pi2s_tx->rfs * 4);
+       } else if (pi2s_tx->id == 1) {
+               /* Initialize GPIO for I2S-1 */
+               exynos_pinmux_config(PERIPH_ID_I2S1, 0);
+
+               /* Set EPLL Clock */
+               ret = set_epll_clk(pi2s_tx->audio_pll_clk);
+       } else {
+               debug("%s: unsupported i2s-%d bus\n", __func__, pi2s_tx->id);
+               return -1;
+       }
 
-       /* 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__);
+               debug("%s: epll clock set rate failed\n", __func__);
                return -1;
        }
 
-       /* Select Clk Source for Audio1 */
-       set_i2s_clk_source();
+       /* Select Clk Source for Audio 0 or 1 */
+       ret = set_i2s_clk_source(pi2s_tx->id);
+       if (ret == -1) {
+               debug("%s: unsupported clock for i2s-%d\n", __func__,
+                     pi2s_tx->id);
+               return -1;
+       }
+
+       if (pi2s_tx->id == 0) {
+               /*Reset the i2s module */
+               writel(CON_RESET, &i2s_reg->con);
 
-       /* Set Prescaler to get MCLK */
-       set_i2s_clk_prescaler(pi2s_tx->audio_pll_clk,
-                               (pi2s_tx->samplingrate * (pi2s_tx->rfs)));
+               writel(MOD_OP_CLK | MOD_RCLKSRC, &i2s_reg->mod);
+               /* set i2s prescaler */
+               writel(PSREN | PSVAL, &i2s_reg->psr);
+       } else {
+               /* Set Prescaler to get MCLK */
+               ret = set_i2s_clk_prescaler(pi2s_tx->audio_pll_clk,
+                               (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+                               pi2s_tx->id);
+       }
+       if (ret == -1) {
+               debug("%s: unsupported prescalar for i2s-%d\n", __func__,
+                     pi2s_tx->id);
+               return -1;
+       }
 
        /* Configure I2s format */
        ret = i2s_set_fmt(i2s_reg, (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM));
+                         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);
index 6fcc75d..9b8ce5a 100644 (file)
@@ -36,8 +36,7 @@ static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
        int error = 0;
        int base;
 
-       node = fdtdec_next_compatible(blob, 0,
-                                       COMPAT_SAMSUNG_EXYNOS5_SOUND);
+       node = fdt_path_offset(blob, "i2s");
        if (node <= 0) {
                debug("EXYNOS_SOUND: No node for sound in device tree\n");
                return -1;
@@ -80,6 +79,11 @@ static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
                                node, "samsung,i2s-bit-clk-framesize", -1);
        error |= i2s->bfs;
        debug("bfs = %d\n", i2s->bfs);
+
+       i2s->id = fdtdec_get_int(blob, node, "samsung,i2s-id", -1);
+       error |= i2s->id;
+       debug("id = %d\n", i2s->id);
+
        if (error == -1) {
                debug("fail to get sound i2s node properties\n");
                return -1;
@@ -92,6 +96,7 @@ static int get_sound_i2s_values(struct i2stx_info *i2s, const void *blob)
        i2s->channels = I2S_CHANNELS;
        i2s->rfs = I2S_RFS;
        i2s->bfs = I2S_BFS;
+       i2s->id = 0;
 #endif
        return 0;
 }
@@ -111,7 +116,7 @@ static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
        int node;
 
        /* Get the node from FDT for sound */
-       node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SOUND);
+       node = fdt_path_offset(blob, "i2s");
        if (node <= 0) {
                debug("EXYNOS_SOUND: No node for sound in device tree\n");
                debug("node = %d\n", node);
@@ -130,14 +135,15 @@ static int codec_init(const void *blob, struct i2stx_info *pi2s_tx)
 #endif
        if (!strcmp(codectype, "wm8994")) {
                /* Check the codec type and initialise the same */
-               ret = wm8994_init(blob, WM8994_AIF2,
-                       pi2s_tx->samplingrate,
-                       (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
-                       pi2s_tx->bitspersample, pi2s_tx->channels);
+               ret = wm8994_init(blob, pi2s_tx->id + 1,
+                                 pi2s_tx->samplingrate,
+                                 (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+                                 pi2s_tx->bitspersample, pi2s_tx->channels);
        } else if (!strcmp(codectype, "max98095")) {
-               ret = max98095_init(blob, pi2s_tx->samplingrate,
-                               (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
-                               pi2s_tx->bitspersample);
+               ret = max98095_init(blob, pi2s_tx->id + 1,
+                                   pi2s_tx->samplingrate,
+                                   (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
+                                   pi2s_tx->bitspersample);
        } else {
                debug("%s: Unknown codec type %s\n", __func__, codectype);
                return -1;
@@ -230,7 +236,7 @@ int sound_play(uint32_t msec, uint32_t frequency)
        }
 
        sound_prepare_buffer((unsigned short *)data,
-                               data_size / sizeof(unsigned short), frequency);
+                            data_size / sizeof(unsigned short), frequency);
 
        while (msec >= 1000) {
                ret = i2s_transfer_tx_data(&g_i2stx_pri, data,
index 37e354c..f8e9a6e 100644 (file)
@@ -432,12 +432,12 @@ static int configure_aif_clock(struct wm8994_priv *wm8994, int aif)
        int ret;
 
        /* AIF(1/0) register adress offset calculated */
-       if (aif)
+       if (aif-1)
                offset = 4;
        else
                offset = 0;
 
-       switch (wm8994->sysclk[aif]) {
+       switch (wm8994->sysclk[aif-1]) {
        case WM8994_SYSCLK_MCLK1:
                reg1 |= SEL_MCLK1;
                rate = wm8994->mclk[0];
@@ -460,7 +460,7 @@ static int configure_aif_clock(struct wm8994_priv *wm8994, int aif)
 
        default:
                debug("%s: Invalid input clock selection [%d]\n",
-                     __func__, wm8994->sysclk[aif]);
+                     __func__, wm8994->sysclk[aif-1]);
                return -1;
        }
 
@@ -470,13 +470,18 @@ static int configure_aif_clock(struct wm8994_priv *wm8994, int aif)
                reg1 |= WM8994_AIF1CLK_DIV;
        }
 
-       wm8994->aifclk[aif] = rate;
+       wm8994->aifclk[aif-1] = 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,
+       if (aif == WM8994_AIF1)
+               ret |= wm8994_update_bits(WM8994_CLOCKING_1,
+                       WM8994_AIF1DSPCLK_ENA_MASK | WM8994_SYSDSPCLK_ENA_MASK,
+                       WM8994_AIF1DSPCLK_ENA | WM8994_SYSDSPCLK_ENA);
+       else if (aif == WM8994_AIF2)
+               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);
@@ -536,7 +541,7 @@ static int wm8994_set_sysclk(struct wm8994_priv *wm8994, int aif_id,
                                        break;
                        if (i == ARRAY_SIZE(opclk_divs)) {
                                debug("%s frequency divisor not found\n",
-                                       __func__);
+                                     __func__);
                                return -1;
                        }
                        ret = wm8994_update_bits(WM8994_CLOCKING_2,
@@ -554,7 +559,7 @@ static int wm8994_set_sysclk(struct wm8994_priv *wm8994, int aif_id,
                return -1;
        }
 
-       ret |= configure_aif_clock(wm8994, aif_id - 1);
+       ret |= configure_aif_clock(wm8994, aif_id);
 
        if (ret < 0) {
                debug("%s: codec register access error\n", __func__);
@@ -608,13 +613,46 @@ static int wm8994_init_volume_aif2_dac1(void)
 }
 
 /*
+ * Initializes Volume for AIF1 to HP path
+ *
+ * @returns -1 for error  and 0 Success.
+ *
+ */
+static int wm8994_init_volume_aif1_dac1(void)
+{
+       int ret = 0;
+
+       /* Unmute AIF1DAC */
+       ret |= wm8994_i2c_write(WM8994_AIF1_DAC_FILTERS_1, 0x0000);
+
+       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)
+static int wm8994_device_init(struct wm8994_priv *wm8994,
+                             enum en_audio_interface aif_id)
 {
        const char *devname;
        unsigned short reg_data;
@@ -661,13 +699,30 @@ static int wm8994_device_init(struct wm8994_priv *wm8994)
        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);
-
+       if (aif_id == WM8994_AIF1) {
+               ret |= wm8994_i2c_write(WM8994_POWER_MANAGEMENT_2,
+                                       WM8994_TSHUT_ENA | WM8994_MIXINL_ENA |
+                                       WM8994_MIXINR_ENA | WM8994_IN2L_ENA |
+                                       WM8994_IN2R_ENA);
+
+               ret |= wm8994_i2c_write(WM8994_POWER_MANAGEMENT_4,
+                                       WM8994_ADCL_ENA | WM8994_ADCR_ENA |
+                                       WM8994_AIF1ADC1R_ENA |
+                                       WM8994_AIF1ADC1L_ENA);
+
+               /* Power enable for AIF1 and DAC1 */
+               ret |= wm8994_i2c_write(WM8994_POWER_MANAGEMENT_5,
+                                       WM8994_AIF1DACL_ENA |
+                                       WM8994_AIF1DACR_ENA |
+                                       WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
+       } else if (aif_id == WM8994_AIF2) {
+               /* 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,
@@ -695,35 +750,49 @@ static int wm8994_device_init(struct wm8994_priv *wm8994)
        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 (aif_id == WM8994_AIF1) {
+               /* Routing AIF1 to DAC1 */
+               ret |= wm8994_i2c_write(WM8994_DAC1_LEFT_MIXER_ROUTING,
+                               WM8994_AIF1DAC1L_TO_DAC1L);
+
+               ret |= wm8994_i2c_write(WM8994_DAC1_RIGHT_MIXER_ROUTING,
+                                       WM8994_AIF1DAC1R_TO_DAC1R);
+
+               /* GPIO Settings for AIF1 */
+               ret |=  wm8994_i2c_write(WM8994_GPIO_1, WM8994_GPIO_DIR_OUTPUT
+                                        | WM8994_GPIO_FUNCTION_I2S_CLK
+                                        | WM8994_GPIO_INPUT_DEBOUNCE);
+
+               ret |= wm8994_init_volume_aif1_dac1();
+       } else if (aif_id == WM8994_AIF2) {
+               /* 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);
+
+               /* LR CLK */
+               ret |= wm8994_update_bits(WM8994_GPIO_4, WM8994_GPIO_DIR_MASK |
+                                       WM8994_GPIO_FUNCTION_MASK,
+                                       WM8994_GPIO_DIR_OUTPUT);
+
+               /* DATA */
+               ret |= wm8994_update_bits(WM8994_GPIO_5, WM8994_GPIO_DIR_MASK |
+                                       WM8994_GPIO_FUNCTION_MASK,
+                                       WM8994_GPIO_DIR_OUTPUT);
+
+               ret |= wm8994_init_volume_aif2_dac1();
+       }
+
        if (ret < 0)
                goto err;
 
@@ -795,7 +864,7 @@ static int get_codec_values(struct sound_codec_info *pcodec_info,
        return 0;
 }
 
-/*wm8994 Device Initialisation */
+/* WM8994 Device Initialisation */
 int wm8994_init(const void *blob, enum en_audio_interface aif_id,
                        int sampling_rate, int mclk_freq,
                        int bits_per_sample, unsigned int channels)
@@ -813,15 +882,15 @@ int wm8994_init(const void *blob, enum en_audio_interface aif_id,
        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)
+       if (pcodec_info->codec_type == CODEC_WM_8994) {
                g_wm8994_info.type = WM8994;
-       else {
+       else {
                debug("%s: Codec id [%d] not defined\n", __func__,
-                               pcodec_info->codec_type);
+                     pcodec_info->codec_type);
                return -1;
        }
 
-       ret = wm8994_device_init(&g_wm8994_info);
+       ret = wm8994_device_init(&g_wm8994_info, aif_id);
        if (ret < 0) {
                debug("%s: wm8994 codec chip init failed\n", __func__);
                return ret;
index 1e987c2..0aba2fd 100644 (file)
@@ -13,6 +13,7 @@
 #define WM8994_SOFTWARE_RESET                   0x00
 #define WM8994_POWER_MANAGEMENT_1               0x01
 #define WM8994_POWER_MANAGEMENT_2               0x02
+#define WM8994_POWER_MANAGEMENT_4              0x04
 #define WM8994_POWER_MANAGEMENT_5               0x05
 #define WM8994_LEFT_OUTPUT_VOLUME               0x1C
 #define WM8994_RIGHT_OUTPUT_VOLUME              0x1D
@@ -38,6 +39,7 @@
 #define WM8994_AIF2_CONTROL_2                   0x311
 #define WM8994_AIF2_MASTER_SLAVE                0x312
 #define WM8994_AIF2_BCLK                        0x313
+#define WM8994_AIF1_DAC_FILTERS_1              0x420
 #define WM8994_AIF2_DAC_LEFT_VOLUME             0x502
 #define WM8994_AIF2_DAC_RIGHT_VOLUME            0x503
 #define WM8994_AIF2_DAC_FILTERS_1               0x520
@@ -45,6 +47,7 @@
 #define WM8994_DAC1_RIGHT_MIXER_ROUTING         0x602
 #define WM8994_DAC1_LEFT_VOLUME                 0x610
 #define WM8994_DAC1_RIGHT_VOLUME                0x611
+#define WM8994_GPIO_1                          0x700
 #define WM8994_GPIO_3                           0x702
 #define WM8994_GPIO_4                           0x703
 #define WM8994_GPIO_5                           0x704
 /* OPCLK_ENA */
 #define WM8994_OPCLK_ENA                        0x0800
 
+#define WM8994_TSHUT_ENA                       0x4000
+#define WM8994_MIXINL_ENA                      0x0200
+#define WM8994_MIXINR_ENA                      0x0100
+#define WM8994_IN2L_ENA                                0x0080
+#define WM8994_IN2R_ENA                                0x0020
+
+/*
+ * R5 (0x04) - Power Management (4)
+ */
+#define WM8994_ADCL_ENA                                0x0001
+#define WM8994_ADCR_ENA                                0x0002
+#define WM8994_AIF1ADC1R_ENA                   0x0100
+#define WM8994_AIF1ADC1L_ENA                   0x0200
+
 /*
  * R5 (0x05) - Power Management (5)
  */
 /* AIF2DACR_ENA */
 #define WM8994_AIF2DACR_ENA                     0x1000
 #define WM8994_AIF2DACR_ENA_MASK                0x1000
+/* AIF1DACL_ENA */
+#define WM8994_AIF1DACL_ENA                    0x0200
+#define WM8994_AIF1DACL_ENA_MASK               0x0200
+/* AIF1DACR_ENA */
+#define WM8994_AIF1DACR_ENA                    0x0100
+#define WM8994_AIF1DACR_ENA_MASK               0x0100
 /* DAC1L_ENA */
 #define WM8994_DAC1L_ENA                        0x0002
 #define WM8994_DAC1L_ENA_MASK                   0x0002
 /*
  * R520 (0x208) - Clocking (1)
  */
+/* AIF1DSPCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA                  0x0008
+#define WM8994_AIF1DSPCLK_ENA_MASK             0x0008
 /* AIF2DSPCLK_ENA */
 #define WM8994_AIF2DSPCLK_ENA                   0x0004
 #define WM8994_AIF2DSPCLK_ENA_MASK              0x0004
 /* AIF2DACL_TO_DAC1L */
 #define WM8994_AIF2DACL_TO_DAC1L                0x0004
 #define WM8994_AIF2DACL_TO_DAC1L_MASK           0x0004
+/* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L              0x0001
 
 /*
  * R1538 (0x602) - DAC1 Right Mixer Routing
 /* AIF2DACR_TO_DAC1R */
 #define WM8994_AIF2DACR_TO_DAC1R                0x0004
 #define WM8994_AIF2DACR_TO_DAC1R_MASK           0x0004
+/* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R              0x0001
 
 /*
  * R1552 (0x610) - DAC1 Left Volume
  *  GPIO
  */
 /* OUTPUT PIN */
-#define WM8994_GPIO_DIR_OUTPUT                   0x8000
+#define WM8994_GPIO_DIR_OUTPUT                 0x8000
 /* GPIO PIN MASK */
-#define WM8994_GPIO_DIR_MASK                     0xFFE0
+#define WM8994_GPIO_DIR_MASK                   0xFFE0
 /* I2S CLK */
-#define WM8994_GPIO_FUNCTION_I2S_CLK             0x0000
+#define WM8994_GPIO_FUNCTION_I2S_CLK           0x0001
+#define WM8994_GPIO_INPUT_DEBOUNCE             0x0100
 /* GPn FN */
-#define WM8994_GPIO_FUNCTION_MASK                0x001F
+#define WM8994_GPIO_FUNCTION_MASK              0x001F
 #endif
index 91d24ce..e5941b0 100644 (file)
@@ -38,6 +38,7 @@ COBJS-$(CONFIG_FDT_SPI) += fdt_spi.o
 COBJS-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
 COBJS-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
 COBJS-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
+COBJS-$(CONFIG_TI_QSPI) += ti_qspi.o
 COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 COBJS-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
 
index efc8b1e..699c57e 100644 (file)
@@ -26,6 +26,7 @@ struct spi_bus {
        struct exynos_spi *regs;
        int inited;             /* 1 if this bus is ready for use */
        int node;
+       uint deactivate_delay_us;       /* Delay to wait after deactivate */
 };
 
 /* A list of spi buses that we know about */
@@ -40,6 +41,8 @@ struct exynos_spi_slave {
        enum periph_id periph_id;       /* Peripheral ID for this device */
        unsigned int fifo_size;
        int skip_preamble;
+       struct spi_bus *bus;            /* Pointer to our SPI bus info */
+       ulong last_transaction_us;      /* Time of last transaction end */
 };
 
 static struct spi_bus *spi_get_bus(unsigned dev_index)
@@ -85,6 +88,7 @@ struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
        }
 
        bus = &spi_bus[busnum];
+       spi_slave->bus = bus;
        spi_slave->regs = bus->regs;
        spi_slave->mode = mode;
        spi_slave->periph_id = bus->periph_id;
@@ -95,6 +99,7 @@ struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
                spi_slave->fifo_size = 256;
 
        spi_slave->skip_preamble = 0;
+       spi_slave->last_transaction_us = timer_get_us();
 
        spi_slave->freq = bus->frequency;
        if (max_hz)
@@ -199,12 +204,29 @@ static void spi_get_fifo_levels(struct exynos_spi *regs,
  *
  * @param regs SPI peripheral registers
  * @param count        Number of bytes to transfer
+ * @param step Number of bytes to transfer in each packet (1 or 4)
  */
-static void spi_request_bytes(struct exynos_spi *regs, int count)
+static void spi_request_bytes(struct exynos_spi *regs, int count, int step)
 {
+       /* For word address we need to swap bytes */
+       if (step == 4) {
+               setbits_le32(&regs->mode_cfg,
+                            SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD);
+               count /= 4;
+               setbits_le32(&regs->swap_cfg, SPI_TX_SWAP_EN | SPI_RX_SWAP_EN |
+                       SPI_TX_BYTE_SWAP | SPI_RX_BYTE_SWAP |
+                       SPI_TX_HWORD_SWAP | SPI_RX_HWORD_SWAP);
+       } else {
+               /* Select byte access and clear the swap configuration */
+               clrbits_le32(&regs->mode_cfg,
+                            SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD);
+               writel(0, &regs->swap_cfg);
+       }
+
        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);
 }
 
@@ -219,6 +241,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
        int toread;
        unsigned start = get_timer(0);
        int stopping;
+       int step;
 
        out_bytes = in_bytes = todo;
 
@@ -226,10 +249,19 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
                                        !(spi_slave->mode & SPI_SLAVE);
 
        /*
+        * Try to transfer words if we can. This helps read performance at
+        * SPI clock speeds above about 20MHz.
+        */
+       step = 1;
+       if (!((todo | (uintptr_t)rxp | (uintptr_t)txp) & 3) &&
+           !spi_slave->skip_preamble)
+               step = 4;
+
+       /*
         * If there's something to send, do a software reset and set a
         * transaction size.
         */
-       spi_request_bytes(regs, todo);
+       spi_request_bytes(regs, todo, step);
 
        /*
         * Bytes are transmitted/received in pairs. Wait to receive all the
@@ -242,24 +274,42 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
 
                /* 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;
+
+               /*
+                * Don't completely fill the txfifo, since we don't want our
+                * rxfifo to overflow, and it may already contain data.
+                */
+               while (tx_lvl < spi_slave->fifo_size/2 && out_bytes) {
+                       if (!txp)
+                               temp = -1;
+                       else if (step == 4)
+                               temp = *(uint32_t *)txp;
+                       else
+                               temp = *txp;
                        writel(temp, &regs->tx_data);
-                       out_bytes--;
+                       out_bytes -= step;
+                       if (txp)
+                               txp += step;
+                       tx_lvl += step;
                }
-               if (rx_lvl > 0) {
-                       temp = readl(&regs->rx_data);
-                       if (spi_slave->skip_preamble) {
-                               if (temp == SPI_PREAMBLE_END_BYTE) {
-                                       spi_slave->skip_preamble = 0;
-                                       stopping = 0;
+               if (rx_lvl >= step) {
+                       while (rx_lvl >= step) {
+                               temp = readl(&regs->rx_data);
+                               if (spi_slave->skip_preamble) {
+                                       if (temp == SPI_PREAMBLE_END_BYTE) {
+                                               spi_slave->skip_preamble = 0;
+                                               stopping = 0;
+                                       }
+                               } else {
+                                       if (rxp || stopping) {
+                                               *rxp = temp;
+                                               rxp += step;
+                                       }
+                                       in_bytes -= step;
                                }
-                       } else {
-                               if (rxp || stopping)
-                                       *rxp++ = temp;
-                               in_bytes--;
+                               toread -= step;
+                               rx_lvl -= step;
                        }
-                       toread--;
                } else if (!toread) {
                        /*
                         * We have run out of input data, but haven't read
@@ -271,7 +321,7 @@ static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
                        out_bytes = in_bytes;
                        toread = in_bytes;
                        txp = NULL;
-                       spi_request_bytes(regs, toread);
+                       spi_request_bytes(regs, toread, step);
                }
                if (spi_slave->skip_preamble && get_timer(start) > 100) {
                        printf("SPI timeout: in_bytes=%d, out_bytes=%d, ",
@@ -315,10 +365,14 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
        if ((flags & SPI_XFER_BEGIN))
                spi_cs_activate(slave);
 
-       /* Exynos SPI limits each transfer to 65535 bytes */
+       /*
+        * Exynos SPI limits each transfer to 65535 transfers. To keep
+        * things simple, allow a maximum of 65532 bytes. We could allow
+        * more in word mode, but the performance difference is small.
+        */
        bytelen =  bitlen / 8;
        for (upto = 0; !ret && upto < bytelen; upto += todo) {
-               todo = min(bytelen - upto, (1 << 16) - 1);
+               todo = min(bytelen - upto, (1 << 16) - 4);
                ret = spi_rx_tx(spi_slave, todo, &din, &dout, flags);
                if (ret)
                        break;
@@ -359,9 +413,22 @@ void spi_cs_activate(struct spi_slave *slave)
 {
        struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
 
+       /* If it's too soon to do another transaction, wait */
+       if (spi_slave->bus->deactivate_delay_us &&
+           spi_slave->last_transaction_us) {
+               ulong delay_us;         /* The delay completed so far */
+               delay_us = timer_get_us() - spi_slave->last_transaction_us;
+               if (delay_us < spi_slave->bus->deactivate_delay_us)
+                       udelay(spi_slave->bus->deactivate_delay_us - delay_us);
+       }
+
        clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
        debug("Activate CS, bus %d\n", spi_slave->slave.bus);
        spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
+
+       /* Remember time of this transaction so we can honour the bus delay */
+       if (spi_slave->bus->deactivate_delay_us)
+               spi_slave->last_transaction_us = timer_get_us();
 }
 
 /**
@@ -411,6 +478,8 @@ static int spi_get_config(const void *blob, int node, struct spi_bus *bus)
        /* Use 500KHz as a suitable default */
        bus->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
                                        500000);
+       bus->deactivate_delay_us = fdtdec_get_int(blob, node,
+                                       "spi-deactivate-delay", 0);
 
        return 0;
 }
index 3cf7142..2b9f395 100644 (file)
@@ -56,8 +56,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                                  unsigned int max_hz, unsigned int mode)
 {
        struct mxs_spi_slave *mxs_slave;
-       struct mxs_ssp_regs *ssp_regs;
-       int reg;
 
        if (!spi_cs_is_valid(bus, cs)) {
                printf("mxs_spi: invalid bus %d / chip select %d\n", bus, cs);
@@ -74,13 +72,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
        mxs_slave->max_khz = max_hz / 1000;
        mxs_slave->mode = mode;
        mxs_slave->regs = mxs_ssp_regs_by_bus(bus);
-       ssp_regs = mxs_slave->regs;
 
-       reg = readl(&ssp_regs->hw_ssp_ctrl0);
-       reg &= ~(MXS_SSP_CHIPSELECT_MASK);
-       reg |= cs << MXS_SSP_CHIPSELECT_SHIFT;
-
-       writel(reg, &ssp_regs->hw_ssp_ctrl0);
        return &mxs_slave->slave;
 
 err_init:
@@ -102,7 +94,9 @@ int spi_claim_bus(struct spi_slave *slave)
 
        mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
 
-       writel(SSP_CTRL0_BUS_WIDTH_ONE_BIT, &ssp_regs->hw_ssp_ctrl0);
+       writel((slave->cs << MXS_SSP_CHIPSELECT_SHIFT) |
+              SSP_CTRL0_BUS_WIDTH_ONE_BIT,
+              &ssp_regs->hw_ssp_ctrl0);
 
        reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
        reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
new file mode 100644 (file)
index 0000000..5a5b482
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * TI QSPI driver
+ *
+ * Copyright (C) 2013, Texas Instruments, Incorporated
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/omap.h>
+#include <malloc.h>
+#include <spi.h>
+
+/* ti qpsi register bit masks */
+#define QSPI_TIMEOUT                    2000000
+#define QSPI_FCLK                       192000000
+/* clock control */
+#define QSPI_CLK_EN                     (1 << 31)
+#define QSPI_CLK_DIV_MAX                0xffff
+/* command */
+#define QSPI_EN_CS(n)                   (n << 28)
+#define QSPI_WLEN(n)                    ((n-1) << 19)
+#define QSPI_3_PIN                      (1 << 18)
+#define QSPI_RD_SNGL                    (1 << 16)
+#define QSPI_WR_SNGL                    (2 << 16)
+#define QSPI_INVAL                      (4 << 16)
+#define QSPI_RD_QUAD                    (7 << 16)
+/* device control */
+#define QSPI_DD(m, n)                   (m << (3 + n*8))
+#define QSPI_CKPHA(n)                   (1 << (2 + n*8))
+#define QSPI_CSPOL(n)                   (1 << (1 + n*8))
+#define QSPI_CKPOL(n)                   (1 << (n*8))
+/* status */
+#define QSPI_WC                         (1 << 1)
+#define QSPI_BUSY                       (1 << 0)
+#define QSPI_WC_BUSY                    (QSPI_WC | QSPI_BUSY)
+#define QSPI_XFER_DONE                  QSPI_WC
+#define MM_SWITCH                       0x01
+#define MEM_CS                          0x100
+#define MEM_CS_UNSELECT                 0xfffff0ff
+#define MMAP_START_ADDR                 0x5c000000
+#define CORE_CTRL_IO                    0x4a002558
+
+#define QSPI_CMD_READ                   (0x3 << 0)
+#define QSPI_CMD_READ_QUAD              (0x6b << 0)
+#define QSPI_CMD_READ_FAST              (0x0b << 0)
+#define QSPI_SETUP0_NUM_A_BYTES         (0x2 << 8)
+#define QSPI_SETUP0_NUM_D_BYTES_NO_BITS (0x0 << 10)
+#define QSPI_SETUP0_NUM_D_BYTES_8_BITS  (0x1 << 10)
+#define QSPI_SETUP0_READ_NORMAL         (0x0 << 12)
+#define QSPI_SETUP0_READ_QUAD           (0x3 << 12)
+#define QSPI_CMD_WRITE                  (0x2 << 16)
+#define QSPI_NUM_DUMMY_BITS             (0x0 << 24)
+
+/* ti qspi register set */
+struct ti_qspi_regs {
+       u32 pid;
+       u32 pad0[3];
+       u32 sysconfig;
+       u32 pad1[3];
+       u32 int_stat_raw;
+       u32 int_stat_en;
+       u32 int_en_set;
+       u32 int_en_ctlr;
+       u32 intc_eoi;
+       u32 pad2[3];
+       u32 clk_ctrl;
+       u32 dc;
+       u32 cmd;
+       u32 status;
+       u32 data;
+       u32 setup0;
+       u32 setup1;
+       u32 setup2;
+       u32 setup3;
+       u32 memswitch;
+       u32 data1;
+       u32 data2;
+       u32 data3;
+};
+
+/* ti qspi slave */
+struct ti_qspi_slave {
+       struct spi_slave slave;
+       struct ti_qspi_regs *base;
+       unsigned int mode;
+       u32 cmd;
+       u32 dc;
+};
+
+static inline struct ti_qspi_slave *to_ti_qspi_slave(struct spi_slave *slave)
+{
+       return container_of(slave, struct ti_qspi_slave, slave);
+}
+
+static void ti_spi_setup_spi_register(struct ti_qspi_slave *qslave)
+{
+       struct spi_slave *slave = &qslave->slave;
+       u32 memval = 0;
+
+       slave->memory_map = (void *)MMAP_START_ADDR;
+
+       memval |= QSPI_CMD_READ | QSPI_SETUP0_NUM_A_BYTES |
+                       QSPI_SETUP0_NUM_D_BYTES_NO_BITS |
+                       QSPI_SETUP0_READ_NORMAL | QSPI_CMD_WRITE |
+                       QSPI_NUM_DUMMY_BITS;
+
+       writel(memval, &qslave->base->setup0);
+}
+
+static void ti_spi_set_speed(struct spi_slave *slave, uint hz)
+{
+       struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+       uint clk_div;
+
+       debug("ti_spi_set_speed: hz: %d, clock divider %d\n", hz, clk_div);
+
+       if (!hz)
+               clk_div = 0;
+       else
+               clk_div = (QSPI_FCLK / hz) - 1;
+
+       /* disable SCLK */
+       writel(readl(&qslave->base->clk_ctrl) & ~QSPI_CLK_EN,
+              &qslave->base->clk_ctrl);
+
+       /* assign clk_div values */
+       if (clk_div < 0)
+               clk_div = 0;
+       else if (clk_div > QSPI_CLK_DIV_MAX)
+               clk_div = QSPI_CLK_DIV_MAX;
+
+       /* enable SCLK */
+       writel(QSPI_CLK_EN | clk_div, &qslave->base->clk_ctrl);
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+       return 1;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+       /* CS handled in xfer */
+       return;
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+       struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+       debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
+
+       writel(qslave->cmd | QSPI_INVAL, &qslave->base->cmd);
+}
+
+void spi_init(void)
+{
+       /* nothing to do */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+                                 unsigned int max_hz, unsigned int mode)
+{
+       struct ti_qspi_slave *qslave;
+
+       qslave = spi_alloc_slave(struct ti_qspi_slave, bus, cs);
+       if (!qslave) {
+               printf("SPI_error: Fail to allocate ti_qspi_slave\n");
+               return NULL;
+       }
+
+       qslave->base = (struct ti_qspi_regs *)QSPI_BASE;
+       qslave->mode = mode;
+
+       ti_spi_set_speed(&qslave->slave, max_hz);
+
+#ifdef CONFIG_TI_SPI_MMAP
+       ti_spi_setup_spi_register(qslave);
+#endif
+
+       return &qslave->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+       struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+       free(qslave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+       struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+       debug("spi_claim_bus: bus:%i cs:%i\n", slave->bus, slave->cs);
+
+       qslave->dc = 0;
+       if (qslave->mode & SPI_CPHA)
+               qslave->dc |= QSPI_CKPHA(slave->cs);
+       if (qslave->mode & SPI_CPOL)
+               qslave->dc |= QSPI_CKPOL(slave->cs);
+       if (qslave->mode & SPI_CS_HIGH)
+               qslave->dc |= QSPI_CSPOL(slave->cs);
+
+       writel(qslave->dc, &qslave->base->dc);
+       writel(0, &qslave->base->cmd);
+       writel(0, &qslave->base->data);
+
+       return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+       struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+       debug("spi_release_bus: bus:%i cs:%i\n", slave->bus, slave->cs);
+
+       writel(0, &qslave->base->dc);
+       writel(0, &qslave->base->cmd);
+       writel(0, &qslave->base->data);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+            void *din, unsigned long flags)
+{
+       struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+       uint words = bitlen >> 3; /* fixed 8-bit word length */
+       const uchar *txp = dout;
+       uchar *rxp = din;
+       uint status;
+       int timeout, val;
+
+       debug("spi_xfer: bus:%i cs:%i bitlen:%i words:%i flags:%lx\n",
+             slave->bus, slave->cs, bitlen, words, flags);
+
+       /* Setup mmap flags */
+       if (flags & SPI_XFER_MMAP) {
+               writel(MM_SWITCH, &qslave->base->memswitch);
+               val = readl(CORE_CTRL_IO);
+               val |= MEM_CS;
+               writel(val, CORE_CTRL_IO);
+               return 0;
+       } else if (flags & SPI_XFER_MMAP_END) {
+               writel(~MM_SWITCH, &qslave->base->memswitch);
+               val = readl(CORE_CTRL_IO);
+               val &= MEM_CS_UNSELECT;
+               writel(val, CORE_CTRL_IO);
+               return 0;
+       }
+
+       if (bitlen == 0)
+               return -1;
+
+       if (bitlen % 8) {
+               debug("spi_xfer: Non byte aligned SPI transfer\n");
+               return -1;
+       }
+
+       /* Setup command reg */
+       qslave->cmd = 0;
+       qslave->cmd |= QSPI_WLEN(8);
+       qslave->cmd |= QSPI_EN_CS(slave->cs);
+       if (flags & SPI_3WIRE)
+               qslave->cmd |= QSPI_3_PIN;
+       qslave->cmd |= 0xfff;
+
+       while (words--) {
+               if (txp) {
+                       debug("tx cmd %08x dc %08x data %02x\n",
+                             qslave->cmd | QSPI_WR_SNGL, qslave->dc, *txp);
+                       writel(*txp++, &qslave->base->data);
+                       writel(qslave->cmd | QSPI_WR_SNGL,
+                              &qslave->base->cmd);
+                       status = readl(&qslave->base->status);
+                       timeout = QSPI_TIMEOUT;
+                       while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
+                               if (--timeout < 0) {
+                                       printf("spi_xfer: TX timeout!\n");
+                                       return -1;
+                               }
+                               status = readl(&qslave->base->status);
+                       }
+                       debug("tx done, status %08x\n", status);
+               }
+               if (rxp) {
+                       qslave->cmd |= QSPI_RD_SNGL;
+                       debug("rx cmd %08x dc %08x\n",
+                             qslave->cmd, qslave->dc);
+                       writel(qslave->cmd, &qslave->base->cmd);
+                       status = readl(&qslave->base->status);
+                       timeout = QSPI_TIMEOUT;
+                       while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
+                               if (--timeout < 0) {
+                                       printf("spi_xfer: RX timeout!\n");
+                                       return -1;
+                               }
+                               status = readl(&qslave->base->status);
+                       }
+                       *rxp++ = readl(&qslave->base->data);
+                       debug("rx done, status %08x, read %02x\n",
+                             status, *(rxp-1));
+               }
+       }
+
+       /* Terminate frame */
+       if (flags & SPI_XFER_END)
+               spi_cs_deactivate(slave);
+
+       return 0;
+}
index 4c2a39a..1590c4a 100644 (file)
@@ -18,10 +18,12 @@ endif
 
 # new USB gadget layer dependencies
 ifdef CONFIG_USB_GADGET
+COBJS-$(CONFIG_USB_GADGET_ATMEL_USBA) += atmel_usba_udc.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
 COBJS-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o
 COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
 COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o
+COBJS-$(CONFIG_USB_GADGET_MASS_STORAGE) += f_mass_storage.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
new file mode 100644 (file)
index 0000000..c99208d
--- /dev/null
@@ -0,0 +1,1306 @@
+/*
+ * Driver for the Atmel USBA high speed USB device controller
+ * [Original from Linux kernel: drivers/usb/gadget/atmel_usba_udc.c]
+ *
+ * Copyright (C) 2005-2013 Atmel Corporation
+ *                        Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+#include <asm/hardware.h>
+#include <linux/list.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/atmel_usba_udc.h>
+#include <malloc.h>
+#include <usb/lin_gadget_compat.h>
+
+#include "atmel_usba_udc.h"
+
+static int vbus_is_present(struct usba_udc *udc)
+{
+       /* No Vbus detection: Assume always present */
+       return 1;
+}
+
+static void next_fifo_transaction(struct usba_ep *ep, struct usba_request *req)
+{
+       unsigned int transaction_len;
+
+       transaction_len = req->req.length - req->req.actual;
+       req->last_transaction = 1;
+       if (transaction_len > ep->ep.maxpacket) {
+               transaction_len = ep->ep.maxpacket;
+               req->last_transaction = 0;
+       } else if (transaction_len == ep->ep.maxpacket && req->req.zero) {
+                       req->last_transaction = 0;
+       }
+
+       DBG(DBG_QUEUE, "%s: submit_transaction, req %p (length %d)%s\n",
+           ep->ep.name, req, transaction_len,
+           req->last_transaction ? ", done" : "");
+
+       memcpy(ep->fifo, req->req.buf + req->req.actual, transaction_len);
+       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+       req->req.actual += transaction_len;
+}
+
+static void submit_request(struct usba_ep *ep, struct usba_request *req)
+{
+       DBG(DBG_QUEUE, "%s: submit_request: req %p (length %d), dma: %d\n",
+           ep->ep.name, req, req->req.length, req->using_dma);
+
+       req->req.actual = 0;
+       req->submitted = 1;
+
+       next_fifo_transaction(ep, req);
+       if (req->last_transaction) {
+               usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+               usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+       } else {
+               usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+               usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
+       }
+}
+
+static void submit_next_request(struct usba_ep *ep)
+{
+       struct usba_request *req;
+
+       if (list_empty(&ep->queue)) {
+               usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY | USBA_RX_BK_RDY);
+               return;
+       }
+
+       req = list_entry(ep->queue.next, struct usba_request, queue);
+       if (!req->submitted)
+               submit_request(ep, req);
+}
+
+static void send_status(struct usba_udc *udc, struct usba_ep *ep)
+{
+       ep->state = STATUS_STAGE_IN;
+       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+}
+
+static void receive_data(struct usba_ep *ep)
+{
+       struct usba_udc *udc = ep->udc;
+       struct usba_request *req;
+       unsigned long status;
+       unsigned int bytecount, nr_busy;
+       int is_complete = 0;
+
+       status = usba_ep_readl(ep, STA);
+       nr_busy = USBA_BFEXT(BUSY_BANKS, status);
+
+       DBG(DBG_QUEUE, "receive data: nr_busy=%u\n", nr_busy);
+
+       while (nr_busy > 0) {
+               if (list_empty(&ep->queue)) {
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       break;
+               }
+               req = list_entry(ep->queue.next,
+                                struct usba_request, queue);
+
+               bytecount = USBA_BFEXT(BYTE_COUNT, status);
+
+               if (status & USBA_SHORT_PACKET)
+                       is_complete = 1;
+               if (req->req.actual + bytecount >= req->req.length) {
+                       is_complete = 1;
+                       bytecount = req->req.length - req->req.actual;
+               }
+
+               memcpy(req->req.buf + req->req.actual, ep->fifo, bytecount);
+               req->req.actual += bytecount;
+
+               usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+
+               if (is_complete) {
+                       DBG(DBG_QUEUE, "%s: request done\n", ep->ep.name);
+                       req->req.status = 0;
+                       list_del_init(&req->queue);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       spin_lock(&udc->lock);
+                       req->req.complete(&ep->ep, &req->req);
+                       spin_unlock(&udc->lock);
+               }
+
+               status = usba_ep_readl(ep, STA);
+               nr_busy = USBA_BFEXT(BUSY_BANKS, status);
+
+               if (is_complete && ep_is_control(ep)) {
+                       send_status(udc, ep);
+                       break;
+               }
+       }
+}
+
+static void
+request_complete(struct usba_ep *ep, struct usba_request *req, int status)
+{
+       if (req->req.status == -EINPROGRESS)
+               req->req.status = status;
+
+       DBG(DBG_GADGET | DBG_REQ, "%s: req %p complete: status %d, actual %u\n",
+           ep->ep.name, req, req->req.status, req->req.actual);
+
+       req->req.complete(&ep->ep, &req->req);
+}
+
+static void
+request_complete_list(struct usba_ep *ep, struct list_head *list, int status)
+{
+       struct usba_request *req, *tmp_req;
+
+       list_for_each_entry_safe(req, tmp_req, list, queue) {
+               list_del_init(&req->queue);
+               request_complete(ep, req, status);
+       }
+}
+
+static int
+usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       unsigned long flags, ept_cfg, maxpacket;
+       unsigned int nr_trans;
+
+       DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc);
+
+       maxpacket = usb_endpoint_maxp(desc) & 0x7ff;
+
+       if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
+             != ep->index) ||
+             ep->index == 0 ||
+             desc->bDescriptorType != USB_DT_ENDPOINT ||
+             maxpacket == 0 ||
+             maxpacket > ep->fifo_size) {
+               DBG(DBG_ERR, "ep_enable: Invalid argument");
+               return -EINVAL;
+       }
+
+       ep->is_isoc = 0;
+       ep->is_in = 0;
+
+       if (maxpacket <= 8)
+               ept_cfg = USBA_BF(EPT_SIZE, USBA_EPT_SIZE_8);
+       else
+               /* LSB is bit 1, not 0 */
+               ept_cfg = USBA_BF(EPT_SIZE, fls(maxpacket - 1) - 3);
+
+       DBG(DBG_HW, "%s: EPT_SIZE = %lu (maxpacket = %lu)\n",
+           ep->ep.name, ept_cfg, maxpacket);
+
+       if (usb_endpoint_dir_in(desc)) {
+               ep->is_in = 1;
+               ept_cfg |= USBA_EPT_DIR_IN;
+       }
+
+       switch (usb_endpoint_type(desc)) {
+       case USB_ENDPOINT_XFER_CONTROL:
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               if (!ep->can_isoc) {
+                       DBG(DBG_ERR, "ep_enable: %s is not isoc capable\n",
+                           ep->ep.name);
+                       return -EINVAL;
+               }
+
+               /*
+                * Bits 11:12 specify number of _additional_
+                * transactions per microframe.
+                */
+               nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1;
+               if (nr_trans > 3)
+                       return -EINVAL;
+
+               ep->is_isoc = 1;
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_ISO);
+
+               /*
+                * Do triple-buffering on high-bandwidth iso endpoints.
+                */
+               if (nr_trans > 1 && ep->nr_banks == 3)
+                       ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_TRIPLE);
+               else
+                       ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_DOUBLE);
+               ept_cfg |= USBA_BF(NB_TRANS, nr_trans);
+               break;
+       case USB_ENDPOINT_XFER_BULK:
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
+               break;
+       case USB_ENDPOINT_XFER_INT:
+               ept_cfg |= USBA_BF(EPT_TYPE, USBA_EPT_TYPE_INT);
+               ept_cfg |= USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE);
+               break;
+       }
+
+       spin_lock_irqsave(&ep->udc->lock, flags);
+
+       ep->desc = desc;
+       ep->ep.maxpacket = maxpacket;
+
+       usba_ep_writel(ep, CFG, ept_cfg);
+       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+
+       usba_writel(udc, INT_ENB,
+                   (usba_readl(udc, INT_ENB)
+                    | USBA_BF(EPT_INT, 1 << ep->index)));
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       DBG(DBG_HW, "EPT_CFG%d after init: %#08lx\n", ep->index,
+           (unsigned long)usba_ep_readl(ep, CFG));
+       DBG(DBG_HW, "INT_ENB after init: %#08lx\n",
+           (unsigned long)usba_readl(udc, INT_ENB));
+
+       return 0;
+}
+
+static int usba_ep_disable(struct usb_ep *_ep)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       LIST_HEAD(req_list);
+       unsigned long flags;
+
+       DBG(DBG_GADGET, "ep_disable: %s\n", ep->ep.name);
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       if (!ep->desc) {
+               spin_unlock_irqrestore(&udc->lock, flags);
+               /* REVISIT because this driver disables endpoints in
+                * reset_all_endpoints() before calling disconnect(),
+                * most gadget drivers would trigger this non-error ...
+                */
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN)
+                       DBG(DBG_ERR, "ep_disable: %s not enabled\n",
+                           ep->ep.name);
+               return -EINVAL;
+       }
+       ep->desc = NULL;
+
+       list_splice_init(&ep->queue, &req_list);
+       usba_ep_writel(ep, CFG, 0);
+       usba_ep_writel(ep, CTL_DIS, USBA_EPT_ENABLE);
+       usba_writel(udc, INT_ENB,
+                   usba_readl(udc, INT_ENB) &
+                   ~USBA_BF(EPT_INT, 1 << ep->index));
+
+       request_complete_list(ep, &req_list, -ESHUTDOWN);
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static struct usb_request *
+usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
+{
+       struct usba_request *req;
+
+       DBG(DBG_GADGET, "ep_alloc_request: %p, 0x%x\n", _ep, gfp_flags);
+
+       req = malloc(sizeof(struct usba_request));
+       if (!req)
+               return NULL;
+
+       INIT_LIST_HEAD(&req->queue);
+
+       return &req->req;
+}
+
+static void
+usba_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct usba_request *req = to_usba_req(_req);
+
+       DBG(DBG_GADGET, "ep_free_request: %p, %p\n", _ep, _req);
+
+       free(req);
+}
+
+static int
+usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
+{
+       struct usba_request *req = to_usba_req(_req);
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+       unsigned long flags;
+       int ret;
+
+       DBG(DBG_GADGET | DBG_QUEUE | DBG_REQ, "%s: queue req %p, len %u\n",
+           ep->ep.name, req, _req->length);
+
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN ||
+           !ep->desc)
+               return -ESHUTDOWN;
+
+       req->submitted = 0;
+       req->using_dma = 0;
+       req->last_transaction = 0;
+
+       _req->status = -EINPROGRESS;
+       _req->actual = 0;
+
+       /* May have received a reset since last time we checked */
+       ret = -ESHUTDOWN;
+       spin_lock_irqsave(&udc->lock, flags);
+       if (ep->desc) {
+               list_add_tail(&req->queue, &ep->queue);
+
+               if ((!ep_is_control(ep) && ep->is_in) ||
+                   (ep_is_control(ep) && (ep->state == DATA_STAGE_IN ||
+                   ep->state == STATUS_STAGE_IN)))
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
+               else
+                       usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
+
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return ret;
+}
+
+static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_request *req = to_usba_req(_req);
+
+       DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n",
+           ep->ep.name, req);
+
+       /*
+        * Errors should stop the queue from advancing until the
+        * completion function returns.
+        */
+       list_del_init(&req->queue);
+
+       request_complete(ep, req, -ECONNRESET);
+
+       /* Process the next request if any */
+       submit_next_request(ep);
+
+       return 0;
+}
+
+static int usba_ep_set_halt(struct usb_ep *_ep, int value)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       unsigned long flags;
+       int ret = 0;
+
+       DBG(DBG_GADGET, "endpoint %s: %s HALT\n", ep->ep.name,
+           value ? "set" : "clear");
+
+       if (!ep->desc) {
+               DBG(DBG_ERR, "Attempted to halt uninitialized ep %s\n",
+                   ep->ep.name);
+               return -ENODEV;
+       }
+
+       if (ep->is_isoc) {
+               DBG(DBG_ERR, "Attempted to halt isochronous ep %s\n",
+                   ep->ep.name);
+               return -ENOTTY;
+       }
+
+       spin_lock_irqsave(&udc->lock, flags);
+
+       /*
+        * We can't halt IN endpoints while there are still data to be
+        * transferred
+        */
+       if (!list_empty(&ep->queue) ||
+           ((value && ep->is_in && (usba_ep_readl(ep, STA) &
+           USBA_BF(BUSY_BANKS, -1L))))) {
+               ret = -EAGAIN;
+       } else {
+               if (value)
+                       usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
+               else
+                       usba_ep_writel(ep, CLR_STA,
+                                      USBA_FORCE_STALL | USBA_TOGGLE_CLR);
+               usba_ep_readl(ep, STA);
+       }
+
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return ret;
+}
+
+static int usba_ep_fifo_status(struct usb_ep *_ep)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+
+       return USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
+}
+
+static void usba_ep_fifo_flush(struct usb_ep *_ep)
+{
+       struct usba_ep *ep = to_usba_ep(_ep);
+       struct usba_udc *udc = ep->udc;
+
+       usba_writel(udc, EPT_RST, 1 << ep->index);
+}
+
+static const struct usb_ep_ops usba_ep_ops = {
+       .enable         = usba_ep_enable,
+       .disable        = usba_ep_disable,
+       .alloc_request  = usba_ep_alloc_request,
+       .free_request   = usba_ep_free_request,
+       .queue          = usba_ep_queue,
+       .dequeue        = usba_ep_dequeue,
+       .set_halt       = usba_ep_set_halt,
+       .fifo_status    = usba_ep_fifo_status,
+       .fifo_flush     = usba_ep_fifo_flush,
+};
+
+static int usba_udc_get_frame(struct usb_gadget *gadget)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+
+       return USBA_BFEXT(FRAME_NUMBER, usba_readl(udc, FNUM));
+}
+
+static int usba_udc_wakeup(struct usb_gadget *gadget)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+       unsigned long flags;
+       u32 ctrl;
+       int ret = -EINVAL;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (udc->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+               ctrl = usba_readl(udc, CTRL);
+               usba_writel(udc, CTRL, ctrl | USBA_REMOTE_WAKE_UP);
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return ret;
+}
+
+static int
+usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
+{
+       struct usba_udc *udc = to_usba_udc(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&udc->lock, flags);
+       if (is_selfpowered)
+               udc->devstatus |= 1 << USB_DEVICE_SELF_POWERED;
+       else
+               udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+       spin_unlock_irqrestore(&udc->lock, flags);
+
+       return 0;
+}
+
+static const struct usb_gadget_ops usba_udc_ops = {
+       .get_frame              = usba_udc_get_frame,
+       .wakeup                 = usba_udc_wakeup,
+       .set_selfpowered        = usba_udc_set_selfpowered,
+};
+
+static struct usb_endpoint_descriptor usba_ep0_desc = {
+       .bLength = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType = USB_DT_ENDPOINT,
+       .bEndpointAddress = 0,
+       .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+       .wMaxPacketSize = cpu_to_le16(64),
+       /* FIXME: I have no idea what to put here */
+       .bInterval = 1,
+};
+
+/*
+ * Called with interrupts disabled and udc->lock held.
+ */
+static void reset_all_endpoints(struct usba_udc *udc)
+{
+       struct usba_ep *ep;
+       struct usba_request *req, *tmp_req;
+
+       usba_writel(udc, EPT_RST, ~0UL);
+
+       ep = to_usba_ep(udc->gadget.ep0);
+       list_for_each_entry_safe(req, tmp_req, &ep->queue, queue) {
+               list_del_init(&req->queue);
+               request_complete(ep, req, -ECONNRESET);
+       }
+
+       /* NOTE:  normally, the next call to the gadget driver is in
+        * charge of disabling endpoints... usually disconnect().
+        * The exception would be entering a high speed test mode.
+        *
+        * FIXME remove this code ... and retest thoroughly.
+        */
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+               if (ep->desc) {
+                       spin_unlock(&udc->lock);
+                       usba_ep_disable(&ep->ep);
+                       spin_lock(&udc->lock);
+               }
+       }
+}
+
+static struct usba_ep *get_ep_by_addr(struct usba_udc *udc, u16 wIndex)
+{
+       struct usba_ep *ep;
+
+       if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
+               return to_usba_ep(udc->gadget.ep0);
+
+       list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
+               u8 bEndpointAddress;
+
+               if (!ep->desc)
+                       continue;
+               bEndpointAddress = ep->desc->bEndpointAddress;
+               if ((wIndex ^ bEndpointAddress) & USB_DIR_IN)
+                       continue;
+               if ((bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)
+                               == (wIndex & USB_ENDPOINT_NUMBER_MASK))
+                       return ep;
+       }
+
+       return NULL;
+}
+
+/* Called with interrupts disabled and udc->lock held */
+static inline void set_protocol_stall(struct usba_udc *udc, struct usba_ep *ep)
+{
+       usba_ep_writel(ep, SET_STA, USBA_FORCE_STALL);
+       ep->state = WAIT_FOR_SETUP;
+}
+
+static inline int is_stalled(struct usba_udc *udc, struct usba_ep *ep)
+{
+       if (usba_ep_readl(ep, STA) & USBA_FORCE_STALL)
+               return 1;
+       return 0;
+}
+
+static inline void set_address(struct usba_udc *udc, unsigned int addr)
+{
+       u32 regval;
+
+       DBG(DBG_BUS, "setting address %u...\n", addr);
+       regval = usba_readl(udc, CTRL);
+       regval = USBA_BFINS(DEV_ADDR, addr, regval);
+       usba_writel(udc, CTRL, regval);
+}
+
+static int do_test_mode(struct usba_udc *udc)
+{
+       static const char test_packet_buffer[] = {
+               /* JKJKJKJK * 9 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               /* JJKKJJKK * 8 */
+               0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+               /* JJKKJJKK * 8 */
+               0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
+               /* JJJJJJJKKKKKKK * 8 */
+               0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+               0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+               /* JJJJJJJK * 8 */
+               0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
+               /* {JKKKKKKK * 10}, JK */
+               0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
+       };
+       struct usba_ep *ep;
+       int test_mode;
+
+       test_mode = udc->test_mode;
+
+       /* Start from a clean slate */
+       reset_all_endpoints(udc);
+
+       switch (test_mode) {
+       case 0x0100:
+               /* Test_J */
+               usba_writel(udc, TST, USBA_TST_J_MODE);
+               DBG(DBG_ALL, "Entering Test_J mode...\n");
+               break;
+       case 0x0200:
+               /* Test_K */
+               usba_writel(udc, TST, USBA_TST_K_MODE);
+               DBG(DBG_ALL, "Entering Test_K mode...\n");
+               break;
+       case 0x0300:
+               /*
+                * Test_SE0_NAK: Force high-speed mode and set up ep0
+                * for Bulk IN transfers
+                */
+               ep = &udc->usba_ep[0];
+               usba_writel(udc, TST,
+                           USBA_BF(SPEED_CFG, USBA_SPEED_CFG_FORCE_HIGH));
+               usba_ep_writel(ep, CFG,
+                              USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
+                              | USBA_EPT_DIR_IN
+                              | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
+                              | USBA_BF(BK_NUMBER, 1));
+               if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) {
+                       set_protocol_stall(udc, ep);
+                       DBG(DBG_ALL, "Test_SE0_NAK: ep0 not mapped\n");
+               } else {
+                       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+                       DBG(DBG_ALL, "Entering Test_SE0_NAK mode...\n");
+               }
+               break;
+       case 0x0400:
+               /* Test_Packet */
+               ep = &udc->usba_ep[0];
+               usba_ep_writel(ep, CFG,
+                              USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64)
+                              | USBA_EPT_DIR_IN
+                              | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_BULK)
+                              | USBA_BF(BK_NUMBER, 1));
+               if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) {
+                       set_protocol_stall(udc, ep);
+                       DBG(DBG_ALL, "Test_Packet: ep0 not mapped\n");
+               } else {
+                       usba_ep_writel(ep, CTL_ENB, USBA_EPT_ENABLE);
+                       usba_writel(udc, TST, USBA_TST_PKT_MODE);
+                       memcpy(ep->fifo, test_packet_buffer,
+                              sizeof(test_packet_buffer));
+                       usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+                       DBG(DBG_ALL, "Entering Test_Packet mode...\n");
+               }
+               break;
+       default:
+               DBG(DBG_ERR, "Invalid test mode: 0x%04x\n", test_mode);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Avoid overly long expressions */
+static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq)
+{
+       if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
+               return true;
+       return false;
+}
+
+static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq)
+{
+       if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE))
+               return true;
+       return false;
+}
+
+static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
+{
+       if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT))
+               return true;
+       return false;
+}
+
+static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
+               struct usb_ctrlrequest *crq)
+{
+       int retval = 0;
+
+       switch (crq->bRequest) {
+       case USB_REQ_GET_STATUS: {
+               u16 status;
+
+               if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_DEVICE)) {
+                       status = cpu_to_le16(udc->devstatus);
+               } else if (crq->bRequestType
+                               == (USB_DIR_IN | USB_RECIP_INTERFACE)) {
+                       status = cpu_to_le16(0);
+               } else if (crq->bRequestType
+                               == (USB_DIR_IN | USB_RECIP_ENDPOINT)) {
+                       struct usba_ep *target;
+
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       status = 0;
+                       if (is_stalled(udc, target))
+                               status |= cpu_to_le16(1);
+               } else {
+                       goto delegate;
+               }
+
+               /* Write directly to the FIFO. No queueing is done. */
+               if (crq->wLength != cpu_to_le16(sizeof(status)))
+                       goto stall;
+               ep->state = DATA_STAGE_IN;
+               __raw_writew(status, ep->fifo);
+               usba_ep_writel(ep, SET_STA, USBA_TX_PK_RDY);
+               break;
+       }
+
+       case USB_REQ_CLEAR_FEATURE: {
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       if (feature_is_dev_remote_wakeup(crq))
+                               udc->devstatus
+                                       &= ~(1 << USB_DEVICE_REMOTE_WAKEUP);
+                       else
+                               /* Can't CLEAR_FEATURE TEST_MODE */
+                               goto stall;
+               } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
+                       struct usba_ep *target;
+
+                       if (crq->wLength != cpu_to_le16(0) ||
+                           !feature_is_ep_halt(crq))
+                               goto stall;
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       usba_ep_writel(target, CLR_STA, USBA_FORCE_STALL);
+                       if (target->index != 0)
+                               usba_ep_writel(target, CLR_STA,
+                                              USBA_TOGGLE_CLR);
+               } else {
+                       goto delegate;
+               }
+
+               send_status(udc, ep);
+               break;
+       }
+
+       case USB_REQ_SET_FEATURE: {
+               if (crq->bRequestType == USB_RECIP_DEVICE) {
+                       if (feature_is_dev_test_mode(crq)) {
+                               send_status(udc, ep);
+                               ep->state = STATUS_STAGE_TEST;
+                               udc->test_mode = le16_to_cpu(crq->wIndex);
+                               return 0;
+                       } else if (feature_is_dev_remote_wakeup(crq)) {
+                               udc->devstatus |= 1 << USB_DEVICE_REMOTE_WAKEUP;
+                       } else {
+                               goto stall;
+                       }
+               } else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
+                       struct usba_ep *target;
+
+                       if (crq->wLength != cpu_to_le16(0) ||
+                           !feature_is_ep_halt(crq))
+                               goto stall;
+
+                       target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
+                       if (!target)
+                               goto stall;
+
+                       usba_ep_writel(target, SET_STA, USBA_FORCE_STALL);
+               } else {
+                       goto delegate;
+               }
+
+               send_status(udc, ep);
+               break;
+       }
+
+       case USB_REQ_SET_ADDRESS:
+               if (crq->bRequestType != (USB_DIR_OUT | USB_RECIP_DEVICE))
+                       goto delegate;
+
+               set_address(udc, le16_to_cpu(crq->wValue));
+               send_status(udc, ep);
+               ep->state = STATUS_STAGE_ADDR;
+               break;
+
+       default:
+delegate:
+               spin_unlock(&udc->lock);
+               retval = udc->driver->setup(&udc->gadget, crq);
+               spin_lock(&udc->lock);
+       }
+
+       return retval;
+
+stall:
+       DBG(DBG_ALL, "%s: Invalid setup request: %02x.%02x v%04x i%04x l%d\n",
+           ep->ep.name, crq->bRequestType, crq->bRequest,
+           le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
+           le16_to_cpu(crq->wLength));
+       set_protocol_stall(udc, ep);
+
+       return -1;
+}
+
+static void usba_control_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
+       struct usba_request *req;
+       u32 epstatus;
+       u32 epctrl;
+
+restart:
+       epstatus = usba_ep_readl(ep, STA);
+       epctrl = usba_ep_readl(ep, CTL);
+
+       DBG(DBG_INT, "%s [%d]: s/%08x c/%08x\n",
+           ep->ep.name, ep->state, epstatus, epctrl);
+
+       req = NULL;
+       if (!list_empty(&ep->queue))
+               req = list_entry(ep->queue.next,
+                                struct usba_request, queue);
+
+       if ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
+               if (req->submitted)
+                       next_fifo_transaction(ep, req);
+               else
+                       submit_request(ep, req);
+
+               if (req->last_transaction) {
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+                       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+               }
+               goto restart;
+       }
+       if ((epstatus & epctrl) & USBA_TX_COMPLETE) {
+               usba_ep_writel(ep, CLR_STA, USBA_TX_COMPLETE);
+
+               switch (ep->state) {
+               case DATA_STAGE_IN:
+                       usba_ep_writel(ep, CTL_ENB, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = STATUS_STAGE_OUT;
+                       break;
+               case STATUS_STAGE_ADDR:
+                       /* Activate our new address */
+                       usba_writel(udc, CTRL, (usba_readl(udc, CTRL)
+                                               | USBA_FADDR_EN));
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+               case STATUS_STAGE_IN:
+                       if (req) {
+                               list_del_init(&req->queue);
+                               request_complete(ep, req, 0);
+                               submit_next_request(ep);
+                       }
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+               case STATUS_STAGE_TEST:
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       ep->state = WAIT_FOR_SETUP;
+                       if (do_test_mode(udc))
+                               set_protocol_stall(udc, ep);
+                       break;
+               default:
+                       DBG(DBG_ALL, "%s: TXCOMP: Invalid endpoint state %d\n",
+                           ep->ep.name, ep->state);
+                       set_protocol_stall(udc, ep);
+                       break;
+               }
+
+               goto restart;
+       }
+       if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
+               switch (ep->state) {
+               case STATUS_STAGE_OUT:
+                       usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+
+                       if (req) {
+                               list_del_init(&req->queue);
+                               request_complete(ep, req, 0);
+                       }
+                       ep->state = WAIT_FOR_SETUP;
+                       break;
+
+               case DATA_STAGE_OUT:
+                       receive_data(ep);
+                       break;
+
+               default:
+                       usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+                       usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                       DBG(DBG_ALL, "%s: RXRDY: Invalid endpoint state %d\n",
+                           ep->ep.name, ep->state);
+                       set_protocol_stall(udc, ep);
+                       break;
+               }
+
+               goto restart;
+       }
+       if (epstatus & USBA_RX_SETUP) {
+               union {
+                       struct usb_ctrlrequest crq;
+                       unsigned long data[2];
+               } crq;
+               unsigned int pkt_len;
+               int ret;
+
+               if (ep->state != WAIT_FOR_SETUP) {
+                       /*
+                        * Didn't expect a SETUP packet at this
+                        * point. Clean up any pending requests (which
+                        * may be successful).
+                        */
+                       int status = -EPROTO;
+
+                       /*
+                        * RXRDY and TXCOMP are dropped when SETUP
+                        * packets arrive.  Just pretend we received
+                        * the status packet.
+                        */
+                       if (ep->state == STATUS_STAGE_OUT ||
+                           ep->state == STATUS_STAGE_IN) {
+                               usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
+                               status = 0;
+                       }
+
+                       if (req) {
+                               list_del_init(&req->queue);
+                               request_complete(ep, req, status);
+                       }
+               }
+
+               pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
+               DBG(DBG_HW, "Packet length: %u\n", pkt_len);
+               if (pkt_len != sizeof(crq)) {
+                       DBG(DBG_ALL, "udc: Invalid length %u (expected %zu)\n",
+                           pkt_len, sizeof(crq));
+                       set_protocol_stall(udc, ep);
+                       return;
+               }
+
+               DBG(DBG_FIFO, "Copying ctrl request from 0x%p:\n", ep->fifo);
+               memcpy(crq.data, ep->fifo, sizeof(crq));
+
+               /* Free up one bank in the FIFO so that we can
+                * generate or receive a reply right away. */
+               usba_ep_writel(ep, CLR_STA, USBA_RX_SETUP);
+
+               if (crq.crq.bRequestType & USB_DIR_IN) {
+                       /*
+                        * The USB 2.0 spec states that "if wLength is
+                        * zero, there is no data transfer phase."
+                        * However, testusb #14 seems to actually
+                        * expect a data phase even if wLength = 0...
+                        */
+                       ep->state = DATA_STAGE_IN;
+               } else {
+                       if (crq.crq.wLength != cpu_to_le16(0))
+                               ep->state = DATA_STAGE_OUT;
+                       else
+                               ep->state = STATUS_STAGE_IN;
+               }
+
+               ret = -1;
+               if (ep->index == 0) {
+                       ret = handle_ep0_setup(udc, ep, &crq.crq);
+               } else {
+                       spin_unlock(&udc->lock);
+                       ret = udc->driver->setup(&udc->gadget, &crq.crq);
+                       spin_lock(&udc->lock);
+               }
+
+               DBG(DBG_BUS, "req %02x.%02x, length %d, state %d, ret %d\n",
+                   crq.crq.bRequestType, crq.crq.bRequest,
+                   le16_to_cpu(crq.crq.wLength), ep->state, ret);
+
+               if (ret < 0) {
+                       /* Let the host know that we failed */
+                       set_protocol_stall(udc, ep);
+               }
+       }
+}
+
+static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep)
+{
+       struct usba_request *req;
+       u32 epstatus;
+       u32 epctrl;
+
+       epstatus = usba_ep_readl(ep, STA);
+       epctrl = usba_ep_readl(ep, CTL);
+
+       DBG(DBG_INT, "%s: interrupt, status: 0x%08x\n", ep->ep.name, epstatus);
+
+       while ((epctrl & USBA_TX_PK_RDY) && !(epstatus & USBA_TX_PK_RDY)) {
+               DBG(DBG_BUS, "%s: TX PK ready\n", ep->ep.name);
+
+               if (list_empty(&ep->queue)) {
+                       DBG(DBG_INT, "ep_irq: queue empty\n");
+                       usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
+                       return;
+               }
+
+               req = list_entry(ep->queue.next, struct usba_request, queue);
+
+               if (req->submitted)
+                       next_fifo_transaction(ep, req);
+               else
+                       submit_request(ep, req);
+
+               if (req->last_transaction) {
+                       list_del_init(&req->queue);
+                       submit_next_request(ep);
+                       request_complete(ep, req, 0);
+               }
+
+               epstatus = usba_ep_readl(ep, STA);
+               epctrl = usba_ep_readl(ep, CTL);
+       }
+
+       if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
+               DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
+               receive_data(ep);
+               usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
+       }
+}
+
+static int usba_udc_irq(struct usba_udc *udc)
+{
+       u32 status, ep_status;
+
+       spin_lock(&udc->lock);
+
+       status = usba_readl(udc, INT_STA);
+       DBG(DBG_INT, "irq, status=%#08x\n", status);
+
+       if (status & USBA_DET_SUSPEND) {
+               usba_writel(udc, INT_CLR, USBA_DET_SUSPEND);
+               DBG(DBG_BUS, "Suspend detected\n");
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
+                   udc->driver && udc->driver->suspend) {
+                       spin_unlock(&udc->lock);
+                       udc->driver->suspend(&udc->gadget);
+                       spin_lock(&udc->lock);
+               }
+       }
+
+       if (status & USBA_WAKE_UP) {
+               usba_writel(udc, INT_CLR, USBA_WAKE_UP);
+               DBG(DBG_BUS, "Wake Up CPU detected\n");
+       }
+
+       if (status & USBA_END_OF_RESUME) {
+               usba_writel(udc, INT_CLR, USBA_END_OF_RESUME);
+               DBG(DBG_BUS, "Resume detected\n");
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
+                   udc->driver && udc->driver->resume) {
+                       spin_unlock(&udc->lock);
+                       udc->driver->resume(&udc->gadget);
+                       spin_lock(&udc->lock);
+               }
+       }
+
+       ep_status = USBA_BFEXT(EPT_INT, status);
+       if (ep_status) {
+               int i;
+
+               for (i = 0; i < USBA_NR_ENDPOINTS; i++)
+                       if (ep_status & (1 << i)) {
+                               if (ep_is_control(&udc->usba_ep[i]))
+                                       usba_control_irq(udc, &udc->usba_ep[i]);
+                               else
+                                       usba_ep_irq(udc, &udc->usba_ep[i]);
+                       }
+       }
+
+       if (status & USBA_END_OF_RESET) {
+               struct usba_ep *ep0;
+
+               usba_writel(udc, INT_CLR, USBA_END_OF_RESET);
+               reset_all_endpoints(udc);
+
+               if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
+                   udc->driver->disconnect) {
+                       udc->gadget.speed = USB_SPEED_UNKNOWN;
+                       spin_unlock(&udc->lock);
+                       udc->driver->disconnect(&udc->gadget);
+                       spin_lock(&udc->lock);
+               }
+
+               if (status & USBA_HIGH_SPEED)
+                       udc->gadget.speed = USB_SPEED_HIGH;
+               else
+                       udc->gadget.speed = USB_SPEED_FULL;
+
+               ep0 = &udc->usba_ep[0];
+               ep0->desc = &usba_ep0_desc;
+               ep0->state = WAIT_FOR_SETUP;
+               usba_ep_writel(ep0, CFG,
+                              (USBA_BF(EPT_SIZE, EP0_EPT_SIZE)
+                               | USBA_BF(EPT_TYPE, USBA_EPT_TYPE_CONTROL)
+                               | USBA_BF(BK_NUMBER, USBA_BK_NUMBER_ONE)));
+               usba_ep_writel(ep0, CTL_ENB,
+                              USBA_EPT_ENABLE | USBA_RX_SETUP);
+               usba_writel(udc, INT_ENB,
+                           (usba_readl(udc, INT_ENB)
+                            | USBA_BF(EPT_INT, 1)
+                            | USBA_DET_SUSPEND
+                            | USBA_END_OF_RESUME));
+
+               /*
+                * Unclear why we hit this irregularly, e.g. in usbtest,
+                * but it's clearly harmless...
+                */
+               if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED))
+                       DBG(DBG_ALL, "ODD: EP0 configuration is invalid!\n");
+       }
+
+       spin_unlock(&udc->lock);
+
+       return 0;
+}
+
+static int atmel_usba_start(struct usba_udc *udc)
+{
+       udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
+
+       udc->vbus_prev = 0;
+
+       /* If Vbus is present, enable the controller and wait for reset */
+       if (vbus_is_present(udc) && udc->vbus_prev == 0) {
+               usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+               usba_writel(udc, INT_ENB, USBA_END_OF_RESET);
+       }
+
+       return 0;
+}
+
+static int atmel_usba_stop(struct usba_udc *udc)
+{
+       udc->gadget.speed = USB_SPEED_UNKNOWN;
+       reset_all_endpoints(udc);
+
+       /* This will also disable the DP pullup */
+       usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+
+       return 0;
+}
+
+static struct usba_udc controller = {
+       .regs = (unsigned *)ATMEL_BASE_UDPHS,
+       .fifo = (unsigned *)ATMEL_BASE_UDPHS_FIFO,
+       .gadget = {
+               .ops            = &usba_udc_ops,
+               .ep_list        = LIST_HEAD_INIT(controller.gadget.ep_list),
+               .speed          = USB_SPEED_HIGH,
+               .is_dualspeed   = 1,
+               .name           = "atmel_usba_udc",
+       },
+};
+
+int usb_gadget_handle_interrupts(void)
+{
+       struct usba_udc *udc = &controller;
+
+       return usba_udc_irq(udc);
+}
+
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+       struct usba_udc *udc = &controller;
+       int ret;
+
+       if (!driver || !driver->bind || !driver->setup) {
+               printf("bad paramter\n");
+               return -EINVAL;
+       }
+
+       if (udc->driver) {
+               printf("UDC already has a gadget driver\n");
+               return -EBUSY;
+       }
+
+       atmel_usba_start(udc);
+
+       udc->driver = driver;
+
+       ret = driver->bind(&udc->gadget);
+       if (ret) {
+               error("driver->bind() returned %d\n", ret);
+               udc->driver = NULL;
+       }
+
+       return ret;
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+       struct usba_udc *udc = &controller;
+
+       if (!driver || !driver->unbind || !driver->disconnect) {
+               error("bad paramter\n");
+               return -EINVAL;
+       }
+
+       driver->disconnect(&udc->gadget);
+       driver->unbind(&udc->gadget);
+       udc->driver = NULL;
+
+       atmel_usba_stop(udc);
+
+       return 0;
+}
+
+static struct usba_ep *usba_udc_pdata(struct usba_platform_data *pdata,
+                                     struct usba_udc *udc)
+{
+       struct usba_ep *eps;
+       int i;
+
+       eps = malloc(sizeof(struct usba_ep) * pdata->num_ep);
+       if (!eps) {
+               error("failed to alloc eps\n");
+               return NULL;
+       }
+
+       udc->gadget.ep0 = &eps[0].ep;
+
+       INIT_LIST_HEAD(&udc->gadget.ep_list);
+       INIT_LIST_HEAD(&eps[0].ep.ep_list);
+
+       for (i = 0; i < pdata->num_ep; i++) {
+               struct usba_ep *ep = &eps[i];
+
+               ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
+               ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
+               ep->fifo = udc->fifo + USBA_FIFO_BASE(i);
+               ep->ep.ops = &usba_ep_ops;
+               ep->ep.name = pdata->ep[i].name;
+               ep->ep.maxpacket = pdata->ep[i].fifo_size;
+               ep->fifo_size = ep->ep.maxpacket;
+               ep->udc = udc;
+               INIT_LIST_HEAD(&ep->queue);
+               ep->nr_banks = pdata->ep[i].nr_banks;
+               ep->index = pdata->ep[i].index;
+               ep->can_dma = pdata->ep[i].can_dma;
+               ep->can_isoc = pdata->ep[i].can_isoc;
+               if (i)
+                       list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+       };
+
+       return eps;
+}
+
+int usba_udc_probe(struct usba_platform_data *pdata)
+{
+       struct usba_udc *udc;
+
+       udc = &controller;
+
+       udc->usba_ep = usba_udc_pdata(pdata, udc);
+
+       return 0;
+}
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
new file mode 100644 (file)
index 0000000..92e462d
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Register definition for Atmel USBA high speed USB device controller
+ * [Original from Linux kernel: drivers/usb/gadget/atmel_usba_udc.h]
+ *
+ * Copyright (C) 2005-2013 Atmel Corporation
+ *                        Bo Shen <voice.shen@atmel.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __LINUX_USB_GADGET_USBA_UDC_H__
+#define __LINUX_USB_GADGET_USBA_UDC_H__
+
+/* USB register offsets */
+#define USBA_CTRL                              0x0000
+#define USBA_FNUM                              0x0004
+#define USBA_INT_ENB                           0x0010
+#define USBA_INT_STA                           0x0014
+#define USBA_INT_CLR                           0x0018
+#define USBA_EPT_RST                           0x001c
+#define USBA_TST                               0x00e0
+
+/* USB endpoint register offsets */
+#define USBA_EPT_CFG                           0x0000
+#define USBA_EPT_CTL_ENB                       0x0004
+#define USBA_EPT_CTL_DIS                       0x0008
+#define USBA_EPT_CTL                           0x000c
+#define USBA_EPT_SET_STA                       0x0014
+#define USBA_EPT_CLR_STA                       0x0018
+#define USBA_EPT_STA                           0x001c
+
+/* USB DMA register offsets */
+#define USBA_DMA_NXT_DSC                       0x0000
+#define USBA_DMA_ADDRESS                       0x0004
+#define USBA_DMA_CONTROL                       0x0008
+#define USBA_DMA_STATUS                                0x000c
+
+/* Bitfields in CTRL */
+#define USBA_DEV_ADDR_OFFSET                   0
+#define USBA_DEV_ADDR_SIZE                     7
+#define USBA_FADDR_EN                          (1 <<  7)
+#define USBA_EN_USBA                           (1 <<  8)
+#define USBA_DETACH                            (1 <<  9)
+#define USBA_REMOTE_WAKE_UP                    (1 << 10)
+#define USBA_PULLD_DIS                         (1 << 11)
+
+#if defined(CONFIG_AVR32)
+#define USBA_ENABLE_MASK                       USBA_EN_USBA
+#define USBA_DISABLE_MASK                      0
+#elif defined(CONFIG_AT91FAMILY)
+#define USBA_ENABLE_MASK                       (USBA_EN_USBA | USBA_PULLD_DIS)
+#define USBA_DISABLE_MASK                      USBA_DETACH
+#endif /* CONFIG_ARCH_AT91 */
+
+/* Bitfields in FNUM */
+#define USBA_MICRO_FRAME_NUM_OFFSET            0
+#define USBA_MICRO_FRAME_NUM_SIZE              3
+#define USBA_FRAME_NUMBER_OFFSET               3
+#define USBA_FRAME_NUMBER_SIZE                 11
+#define USBA_FRAME_NUM_ERROR                   (1 << 31)
+
+/* Bitfields in INT_ENB/INT_STA/INT_CLR */
+#define USBA_HIGH_SPEED                                (1 <<  0)
+#define USBA_DET_SUSPEND                       (1 <<  1)
+#define USBA_MICRO_SOF                         (1 <<  2)
+#define USBA_SOF                               (1 <<  3)
+#define USBA_END_OF_RESET                      (1 <<  4)
+#define USBA_WAKE_UP                           (1 <<  5)
+#define USBA_END_OF_RESUME                     (1 <<  6)
+#define USBA_UPSTREAM_RESUME                   (1 <<  7)
+#define USBA_EPT_INT_OFFSET                    8
+#define USBA_EPT_INT_SIZE                      16
+#define USBA_DMA_INT_OFFSET                    24
+#define USBA_DMA_INT_SIZE                      8
+
+/* Bitfields in EPT_RST */
+#define USBA_RST_OFFSET                                0
+#define USBA_RST_SIZE                          16
+
+/* Bitfields in USBA_TST */
+#define USBA_SPEED_CFG_OFFSET                  0
+#define USBA_SPEED_CFG_SIZE                    2
+#define USBA_TST_J_MODE                                (1 <<  2)
+#define USBA_TST_K_MODE                                (1 <<  3)
+#define USBA_TST_PKT_MODE                      (1 <<  4)
+#define USBA_OPMODE2                           (1 <<  5)
+
+/* Bitfields in EPT_CFG */
+#define USBA_EPT_SIZE_OFFSET                   0
+#define USBA_EPT_SIZE_SIZE                     3
+#define USBA_EPT_DIR_IN                                (1 <<  3)
+#define USBA_EPT_TYPE_OFFSET                   4
+#define USBA_EPT_TYPE_SIZE                     2
+#define USBA_BK_NUMBER_OFFSET                  6
+#define USBA_BK_NUMBER_SIZE                    2
+#define USBA_NB_TRANS_OFFSET                   8
+#define USBA_NB_TRANS_SIZE                     2
+#define USBA_EPT_MAPPED                                (1 << 31)
+
+/* Bitfields in EPT_CTL/EPT_CTL_ENB/EPT_CTL_DIS */
+#define USBA_EPT_ENABLE                                (1 <<  0)
+#define USBA_AUTO_VALID                                (1 <<  1)
+#define USBA_INTDIS_DMA                                (1 <<  3)
+#define USBA_NYET_DIS                          (1 <<  4)
+#define USBA_DATAX_RX                          (1 <<  6)
+#define USBA_MDATA_RX                          (1 <<  7)
+/* Bits 8-15 and 31 enable interrupts for respective bits in EPT_STA */
+#define USBA_BUSY_BANK_IE                      (1 << 18)
+
+/* Bitfields in EPT_SET_STA/EPT_CLR_STA/EPT_STA */
+#define USBA_FORCE_STALL                       (1 <<  5)
+#define USBA_TOGGLE_CLR                                (1 <<  6)
+#define USBA_TOGGLE_SEQ_OFFSET                 6
+#define USBA_TOGGLE_SEQ_SIZE                   2
+#define USBA_ERR_OVFLW                         (1 <<  8)
+#define USBA_RX_BK_RDY                         (1 <<  9)
+#define USBA_KILL_BANK                         (1 <<  9)
+#define USBA_TX_COMPLETE                       (1 << 10)
+#define USBA_TX_PK_RDY                         (1 << 11)
+#define USBA_ISO_ERR_TRANS                     (1 << 11)
+#define USBA_RX_SETUP                          (1 << 12)
+#define USBA_ISO_ERR_FLOW                      (1 << 12)
+#define USBA_STALL_SENT                                (1 << 13)
+#define USBA_ISO_ERR_CRC                       (1 << 13)
+#define USBA_ISO_ERR_NBTRANS                   (1 << 13)
+#define USBA_NAK_IN                            (1 << 14)
+#define USBA_ISO_ERR_FLUSH                     (1 << 14)
+#define USBA_NAK_OUT                           (1 << 15)
+#define USBA_CURRENT_BANK_OFFSET               16
+#define USBA_CURRENT_BANK_SIZE                 2
+#define USBA_BUSY_BANKS_OFFSET                 18
+#define USBA_BUSY_BANKS_SIZE                   2
+#define USBA_BYTE_COUNT_OFFSET                 20
+#define USBA_BYTE_COUNT_SIZE                   11
+#define USBA_SHORT_PACKET                      (1 << 31)
+
+/* Bitfields in DMA_CONTROL */
+#define USBA_DMA_CH_EN                         (1 <<  0)
+#define USBA_DMA_LINK                          (1 <<  1)
+#define USBA_DMA_END_TR_EN                     (1 <<  2)
+#define USBA_DMA_END_BUF_EN                    (1 <<  3)
+#define USBA_DMA_END_TR_IE                     (1 <<  4)
+#define USBA_DMA_END_BUF_IE                    (1 <<  5)
+#define USBA_DMA_DESC_LOAD_IE                  (1 <<  6)
+#define USBA_DMA_BURST_LOCK                    (1 <<  7)
+#define USBA_DMA_BUF_LEN_OFFSET                        16
+#define USBA_DMA_BUF_LEN_SIZE                  16
+
+/* Bitfields in DMA_STATUS */
+#define USBA_DMA_CH_ACTIVE                     (1 <<  1)
+#define USBA_DMA_END_TR_ST                     (1 <<  4)
+#define USBA_DMA_END_BUF_ST                    (1 <<  5)
+#define USBA_DMA_DESC_LOAD_ST                  (1 <<  6)
+
+/* Constants for SPEED_CFG */
+#define USBA_SPEED_CFG_NORMAL                  0
+#define USBA_SPEED_CFG_FORCE_HIGH              2
+#define USBA_SPEED_CFG_FORCE_FULL              3
+
+/* Constants for EPT_SIZE */
+#define USBA_EPT_SIZE_8                                0
+#define USBA_EPT_SIZE_16                       1
+#define USBA_EPT_SIZE_32                       2
+#define USBA_EPT_SIZE_64                       3
+#define USBA_EPT_SIZE_128                      4
+#define USBA_EPT_SIZE_256                      5
+#define USBA_EPT_SIZE_512                      6
+#define USBA_EPT_SIZE_1024                     7
+
+/* Constants for EPT_TYPE */
+#define USBA_EPT_TYPE_CONTROL                  0
+#define USBA_EPT_TYPE_ISO                      1
+#define USBA_EPT_TYPE_BULK                     2
+#define USBA_EPT_TYPE_INT                      3
+
+/* Constants for BK_NUMBER */
+#define USBA_BK_NUMBER_ZERO                    0
+#define USBA_BK_NUMBER_ONE                     1
+#define USBA_BK_NUMBER_DOUBLE                  2
+#define USBA_BK_NUMBER_TRIPLE                  3
+
+/* Bit manipulation macros */
+#define USBA_BF(name, value)                                   \
+       (((value) & ((1 << USBA_##name##_SIZE) - 1))            \
+        << USBA_##name##_OFFSET)
+#define USBA_BFEXT(name, value)                                        \
+       (((value) >> USBA_##name##_OFFSET)                      \
+        & ((1 << USBA_##name##_SIZE) - 1))
+#define USBA_BFINS(name, value, old)                           \
+       (((old) & ~(((1 << USBA_##name##_SIZE) - 1)             \
+                   << USBA_##name##_OFFSET))                   \
+        | USBA_BF(name, value))
+
+/* Register access macros */
+#define usba_readl(udc, reg)                                   \
+       __raw_readl((udc)->regs + USBA_##reg)
+#define usba_writel(udc, reg, value)                           \
+       __raw_writel((value), (udc)->regs + USBA_##reg)
+#define usba_ep_readl(ep, reg)                                 \
+       __raw_readl((ep)->ep_regs + USBA_EPT_##reg)
+#define usba_ep_writel(ep, reg, value)                         \
+       __raw_writel((value), (ep)->ep_regs + USBA_EPT_##reg)
+#define usba_dma_readl(ep, reg)                                        \
+       __raw_readl((ep)->dma_regs + USBA_DMA_##reg)
+#define usba_dma_writel(ep, reg, value)                                \
+       __raw_writel((value), (ep)->dma_regs + USBA_DMA_##reg)
+
+/* Calculate base address for a given endpoint or DMA controller */
+#define USBA_EPT_BASE(x)       (0x100 + (x) * 0x20)
+#define USBA_DMA_BASE(x)       (0x300 + (x) * 0x10)
+#define USBA_FIFO_BASE(x)      ((x) << 16)
+
+/* Synth parameters */
+#define USBA_NR_ENDPOINTS      7
+
+#define EP0_FIFO_SIZE          64
+#define EP0_EPT_SIZE           USBA_EPT_SIZE_64
+#define EP0_NR_BANKS           1
+
+#define DBG_ERR                0x0001  /* report all error returns */
+#define DBG_HW         0x0002  /* debug hardware initialization */
+#define DBG_GADGET     0x0004  /* calls to/from gadget driver */
+#define DBG_INT                0x0008  /* interrupts */
+#define DBG_BUS                0x0010  /* report changes in bus state */
+#define DBG_QUEUE      0x0020  /* debug request queue processing */
+#define DBG_FIFO       0x0040  /* debug FIFO contents */
+#define DBG_DMA                0x0080  /* debug DMA handling */
+#define DBG_REQ                0x0100  /* print out queued request length */
+#define DBG_ALL                0xffff
+#define DBG_NONE       0x0000
+
+#define DEBUG_LEVEL    (DBG_ERR)
+
+#define DBG(level, fmt, ...)                                   \
+       do {                                                    \
+               if ((level) & DEBUG_LEVEL)                      \
+                       debug("udc: " fmt, ## __VA_ARGS__);     \
+       } while (0)
+
+enum usba_ctrl_state {
+       WAIT_FOR_SETUP,
+       DATA_STAGE_IN,
+       DATA_STAGE_OUT,
+       STATUS_STAGE_IN,
+       STATUS_STAGE_OUT,
+       STATUS_STAGE_ADDR,
+       STATUS_STAGE_TEST,
+};
+
+struct usba_dma_desc {
+       dma_addr_t next;
+       dma_addr_t addr;
+       u32 ctrl;
+};
+
+struct usba_ep {
+       int                                     state;
+       void                                    *ep_regs;
+       void                                    *dma_regs;
+       void                                    *fifo;
+       struct usb_ep                           ep;
+       struct usba_udc                         *udc;
+
+       struct list_head                        queue;
+
+       u16                                     fifo_size;
+       u8                                      nr_banks;
+       u8                                      index;
+       unsigned int                            can_dma:1;
+       unsigned int                            can_isoc:1;
+       unsigned int                            is_isoc:1;
+       unsigned int                            is_in:1;
+
+       const struct usb_endpoint_descriptor    *desc;
+};
+
+struct usba_request {
+       struct usb_request                      req;
+       struct list_head                        queue;
+
+       u32                                     ctrl;
+
+       unsigned int                            submitted:1;
+       unsigned int                            last_transaction:1;
+       unsigned int                            using_dma:1;
+       unsigned int                            mapped:1;
+};
+
+struct usba_udc {
+       void *regs;
+       void *fifo;
+
+       struct usb_gadget gadget;
+       struct usb_gadget_driver *driver;
+       struct platform_device *pdev;
+       int irq;
+       int vbus_pin;
+       int vbus_pin_inverted;
+       int num_ep;
+       struct usba_ep *usba_ep;
+
+       u16 devstatus;
+
+       u16 test_mode;
+       int vbus_prev;
+};
+
+static inline struct usba_ep *to_usba_ep(struct usb_ep *ep)
+{
+       return container_of(ep, struct usba_ep, ep);
+}
+
+static inline struct usba_request *to_usba_req(struct usb_request *req)
+{
+       return container_of(req, struct usba_request, req);
+}
+
+static inline struct usba_udc *to_usba_udc(struct usb_gadget *gadget)
+{
+       return container_of(gadget, struct usba_udc, gadget);
+}
+
+#define ep_is_control(ep)      ((ep)->index == 0)
+#define ep_is_idle(ep)         ((ep)->state == EP_STATE_IDLE)
+
+#endif /* __LINUX_USB_GADGET_USBA_UDC_H */
index f563afe..014a679 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <common.h>
+#include <asm/unaligned.h>
 #include <asm/errno.h>
 #include <linux/list.h>
 #include <linux/string.h>
@@ -86,7 +87,8 @@ int usb_gadget_config_buf(
        /* config descriptor first */
        if (length < USB_DT_CONFIG_SIZE || !desc)
                return -EINVAL;
-       *cp = *config;
+       /* config need not be aligned */
+       memcpy(cp, config, sizeof(*cp));
 
        /* then interface/endpoint/class/vendor/... */
        len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8 *)buf,
@@ -100,7 +102,7 @@ int usb_gadget_config_buf(
        /* patch up the config descriptor */
        cp->bLength = USB_DT_CONFIG_SIZE;
        cp->bDescriptorType = USB_DT_CONFIG;
-       cp->wTotalLength = cpu_to_le16(len);
+       put_unaligned_le16(len, &cp->wTotalLength);
        cp->bmAttributes |= USB_CONFIG_ATT_ONE;
        return len;
 }
index 579893c..700d5fb 100644 (file)
@@ -849,9 +849,10 @@ static struct usb_gadget_strings   stringtab = {
 };
 
 /*============================================================================*/
-static u8 control_req[USB_BUFSIZ];
+DEFINE_CACHE_ALIGN_BUFFER(u8, control_req, USB_BUFSIZ);
+
 #if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-static u8 status_req[STATUS_BYTECOUNT] __attribute__ ((aligned(4)));
+DEFINE_CACHE_ALIGN_BUFFER(u8, status_req, STATUS_BYTECOUNT);
 #endif
 
 
index 34a4dde..cc2c455 100644 (file)
@@ -82,7 +82,4 @@ struct dfu_function_descriptor {
        __le16                          wTransferSize;
        __le16                          bcdDFUVersion;
 } __packed;
-
-/* configuration-specific linkup */
-int dfu_add(struct usb_configuration *c);
 #endif /* __F_DFU_H_ */
index a3e05a8..40868c0 100644 (file)
@@ -7,7 +7,6 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
-#include <errno.h>
 #include <common.h>
 #include <malloc.h>
 
 #include <part.h>
 
 #include <g_dnl.h>
-#include "f_dfu.h"
+#include <usb_mass_storage.h>
+#include <dfu.h>
 
 #include "gadget_chips.h"
 #include "composite.c"
-#include "f_mass_storage.c"
 
 /*
  * One needs to define the following:
index fdad739..3ae04c0 100644 (file)
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
 #endif
 
+/*
+ * EHCI spec page 20 says that the HC may take up to 16 uFrames (= 4ms) to halt.
+ * Let's time out after 8 to have a little safety margin on top of that.
+ */
+#define HCHALT_TIMEOUT (8 * 1000)
+
 static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
 
 #define ALIGN_END_ADDR(type, ptr, size)                        \
@@ -190,6 +196,36 @@ out:
        return ret;
 }
 
+static int ehci_shutdown(struct ehci_ctrl *ctrl)
+{
+       int i, ret = 0;
+       uint32_t cmd, reg;
+
+       cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
+       cmd &= ~(CMD_PSE | CMD_ASE);
+       ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
+       ret = handshake(&ctrl->hcor->or_usbsts, STS_ASS | STS_PSS, 0,
+               100 * 1000);
+
+       if (!ret) {
+               for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) {
+                       reg = ehci_readl(&ctrl->hcor->or_portsc[i]);
+                       reg |= EHCI_PS_SUSP;
+                       ehci_writel(&ctrl->hcor->or_portsc[i], reg);
+               }
+
+               cmd &= ~CMD_RUN;
+               ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
+               ret = handshake(&ctrl->hcor->or_usbsts, STS_HALT, STS_HALT,
+                       HCHALT_TIMEOUT);
+       }
+
+       if (ret)
+               puts("EHCI failed to shut down host controller.\n");
+
+       return ret;
+}
+
 static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
 {
        uint32_t delta, next;
@@ -808,6 +844,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
                        }
                        break;
                case USB_PORT_FEAT_TEST:
+                       ehci_shutdown(ctrl);
                        reg &= ~(0xf << 16);
                        reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16;
                        ehci_writel(status_reg, reg);
@@ -878,6 +915,7 @@ unknown:
 
 int usb_lowlevel_stop(int index)
 {
+       ehci_shutdown(&ehcic[index]);
        return ehci_hcd_stop(index);
 }
 
index 28e7e69..a2d52e7 100644 (file)
@@ -154,10 +154,10 @@ The MAC address can be stored in four locations:
 
 -Boot environmental variable in Flash <- can not change, without
                                          re-flashing U-boot.
-U-Boot environental variable          <- can not change, without
+U-Boot environmental variable         <- can not change, without
                                          resetting board/U-Boot
-LAN91C111 Registers                   <- volitle
-LAN91C111 EEPROM                      <- Non Volitle
+LAN91C111 Registers                   <- volatile
+LAN91C111 EEPROM                      <- Non-volatile
 
 If you have not activated the network, and do not have a hardcoded
 or pre-assigned MAC address in U-boot, the environmental variables
diff --git a/fs/fs.c b/fs/fs.c
index 99e516a..be1855d 100644 (file)
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -231,7 +231,7 @@ int fs_write(const char *filename, ulong addr, int offset, int len)
 }
 
 int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
-               int fstype, int cmdline_base)
+               int fstype)
 {
        unsigned long addr;
        const char *addr_str;
@@ -250,7 +250,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
                return 1;
 
        if (argc >= 4) {
-               addr = simple_strtoul(argv[3], NULL, cmdline_base);
+               addr = simple_strtoul(argv[3], NULL, 16);
        } else {
                addr_str = getenv("loadaddr");
                if (addr_str != NULL)
@@ -268,11 +268,11 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
                }
        }
        if (argc >= 6)
-               bytes = simple_strtoul(argv[5], NULL, cmdline_base);
+               bytes = simple_strtoul(argv[5], NULL, 16);
        else
                bytes = 0;
        if (argc >= 7)
-               pos = simple_strtoul(argv[6], NULL, cmdline_base);
+               pos = simple_strtoul(argv[6], NULL, 16);
        else
                pos = 0;
 
@@ -313,7 +313,7 @@ int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
 }
 
 int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
-               int fstype, int cmdline_base)
+               int fstype)
 {
        unsigned long addr;
        const char *filename;
@@ -329,10 +329,10 @@ int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
                return 1;
 
        filename = argv[3];
-       addr = simple_strtoul(argv[4], NULL, cmdline_base);
-       bytes = simple_strtoul(argv[5], NULL, cmdline_base);
+       addr = simple_strtoul(argv[4], NULL, 16);
+       bytes = simple_strtoul(argv[5], NULL, 16);
        if (argc >= 7)
-               pos = simple_strtoul(argv[6], NULL, cmdline_base);
+               pos = simple_strtoul(argv[6], NULL, 16);
        else
                pos = 0;
 
index 4d2a56d..bed4316 100644 (file)
@@ -383,7 +383,7 @@ int setenv_hex(const char *varname, ulong value);
 /**
  * setenv_addr - Set an environment variable to an address in hex
  *
- * @varname:   Environmet variable to set
+ * @varname:   Environment variable to set
  * @addr:      Value to set it to
  * @return 0 if ok, 1 on error
  */
@@ -596,6 +596,12 @@ void ddr_enable_ecc(unsigned int dram_size);
 #endif
 #endif
 
+/*
+ * Return the current value of a monotonically increasing microsecond timer.
+ * Granularity may be larger than 1us if hardware does not support this.
+ */
+ulong timer_get_us(void);
+
 /* $(CPU)/cpu.c */
 static inline int cpumask_next(int cpu, unsigned int mask)
 {
@@ -1017,10 +1023,10 @@ static inline phys_addr_t map_to_sysmem(void *ptr)
  * of a function scoped static buffer.  It can not be used to create a cache
  * line aligned global buffer.
  */
-#define PAD_COUNT(s, pad) ((s - 1) / pad + 1)
+#define PAD_COUNT(s, pad) (((s) - 1) / (pad) + 1)
 #define PAD_SIZE(s, pad) (PAD_COUNT(s, pad) * pad)
 #define ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, pad)           \
-       char __##name[ROUND(PAD_SIZE(size * sizeof(type), pad), align)  \
+       char __##name[ROUND(PAD_SIZE((size) * sizeof(type), pad), align)  \
                      + (align - 1)];                                   \
                                                                        \
        type *name = (type *) ALIGN((uintptr_t)__##name, align)
index 905bacf..862614b 100644 (file)
@@ -354,10 +354,10 @@ unsigned long get_board_sys_clk(unsigned long dummy);
 #define CONFIG_SYS_I2C_FSL
 #define CONFIG_SYS_FSL_I2C_SPEED       400000
 #define CONFIG_SYS_FSL_I2C_SLAVE       0x7F
-#define CONFIG_SYS_FSL_I2C_OFFSET      0x3000
+#define CONFIG_SYS_FSL_I2C_OFFSET      0x118000
 #define CONFIG_SYS_FSL_I2C2_SPEED      400000
 #define CONFIG_SYS_FSL_I2C2_SLAVE      0x7F
-#define CONFIG_SYS_FSL_I2C2_OFFSET     0x3100
+#define CONFIG_SYS_FSL_I2C2_OFFSET     0x118100
 
 /*
  * RapidIO
index 2f06ca2..e8e5275 100644 (file)
        "loadbootenv=load mmc ${mmcdev} ${loadaddr} ${bootenv}\0" \
        "importbootenv=echo Importing environment from mmc ...; " \
                "env import -t $loadaddr $filesize\0" \
+       "dfu_alt_info_ram=" DFU_ALT_INFO_RAM "\0" \
        "ramargs=setenv bootargs console=${console} " \
                "${optargs} " \
                "root=${ramroot} " \
        "kernel part 0 8;" \
        "rootfs part 0 9"
 #endif
+#define CONFIG_DFU_RAM
+#define DFU_ALT_INFO_RAM \
+       "kernel ram 0x80200000 0xD80000;" \
+       "fdt ram 0x80F80000 0x80000;" \
+       "ramdisk ram 0x81000000 0x4000000"
 
 /*
  * Default to using SPI for environment, etc.
index 7b120de..51e0e80 100644 (file)
 #define CONFIG_PHYLIB
 #define CONFIG_PHY_ADDR                        2
 
+/* SPI */
+#undef CONFIG_OMAP3_SPI
+#define CONFIG_TI_QSPI
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_TI_SPI_MMAP
+#define CONFIG_SF_DEFAULT_SPEED                48000000
+#define CONFIG_DEFAULT_SPI_MODE                SPI_MODE_3
+
+/* SPI SPL */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_BUS             0
+#define CONFIG_SPL_SPI_CS              0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS     0x20000
+
 #endif /* __CONFIG_DRA7XX_EVM_H */
index c2d04a2..7321b60 100644 (file)
 
 #define CONFIG_ENV_IS_IN_FLASH 1
 #define CONFIG_ENV_SECT_SIZE   0x20000 /* Size of one Flash sector */
-#define CONFIG_ENV_SIZE                CONFIG_ENV_SECT_SIZE    /* Use one Flash sector for enviroment  */
+#define CONFIG_ENV_SIZE                CONFIG_ENV_SECT_SIZE    /* Use one Flash sector for environment */
 #define CONFIG_ENV_ADDR                0xFFFC0000
 #define CONFIG_ENV_OFFSET              0       /* starting right at the beginning  */
 
index d63d0c4..0feef1e 100644 (file)
 #define CONFIG_ENV_IN_OWN_SECT 1
 
 /* Define this to contain any number of null terminated strings that
- * will be part of the default enviroment compiled into the boot image.
+ * will be part of the default environment compiled into the boot image.
  */
 #define CONFIG_EXTRA_ENV_SETTINGS \
 "quiet=0\0" \
index 76fa500..79c0068 100644 (file)
 #define CONFIG_USB_STORAGE
 #endif
 
+/* USB device */
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_ATMEL_USBA
+#define CONFIG_USB_ETHER
+#define CONFIG_USB_ETH_RNDIS
+#define CONFIG_USBNET_MANUFACTURER      "Atmel SAMA5D3xEK"
+
 #if defined(CONFIG_CMD_USB) || defined(CONFIG_CMD_MMC)
 #define CONFIG_CMD_FAT
 #endif
index 65dabde..a6d6928 100644 (file)
 #define CONFIG_ATMEL_SPI0              /* SPI used for FRAM is SPI0 */
 #define FRAM_SPI_BUS           0
 #define FRAM_CS_NUM            0
-#define CONFIG_SPI_FLASH               /* RAMTRON FRAM on SPI bus */
 #define CONFIG_SPI_FRAM_RAMTRON
 #define CONFIG_SF_DEFAULT_SPEED        1000000 /* be conservative here... */
 #define CONFIG_SF_DEFAULT_MODE SPI_MODE_0
index 47b9055..b2ecf1b 100644 (file)
 #include <common.h>
 #include <linux/list.h>
 #include <mmc.h>
+#include <linux/usb/composite.h>
 
 enum dfu_device_type {
        DFU_DEV_MMC = 1,
        DFU_DEV_ONENAND,
        DFU_DEV_NAND,
+       DFU_DEV_RAM,
 };
 
 enum dfu_layout {
@@ -27,6 +29,12 @@ enum dfu_layout {
        DFU_FS_EXT2,
        DFU_FS_EXT3,
        DFU_FS_EXT4,
+       DFU_RAM_ADDR,
+};
+
+enum dfu_op {
+       DFU_OP_READ = 1,
+       DFU_OP_WRITE,
 };
 
 struct mmc_internal_data {
@@ -51,6 +59,11 @@ struct nand_internal_data {
        unsigned int ubi;
 };
 
+struct ram_internal_data {
+       void            *start;
+       unsigned int    size;
+};
+
 static inline unsigned int get_mmc_blk_size(int dev)
 {
        return find_mmc_device(dev)->read_bl_len;
@@ -62,7 +75,7 @@ static inline unsigned int get_mmc_blk_size(int dev)
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE           (1024*1024*8)   /* 8 MiB */
 #endif
 #ifndef CONFIG_SYS_DFU_MAX_FILE_SIZE
-#define CONFIG_SYS_DFU_MAX_FILE_SIZE   (4 << 20)       /* 4 MiB */
+#define CONFIG_SYS_DFU_MAX_FILE_SIZE CONFIG_SYS_DFU_DATA_BUF_SIZE
 #endif
 
 struct dfu_entity {
@@ -76,6 +89,7 @@ struct dfu_entity {
        union {
                struct mmc_internal_data mmc;
                struct nand_internal_data nand;
+               struct ram_internal_data ram;
        } data;
 
        int (*read_medium)(struct dfu_entity *dfu,
@@ -113,6 +127,7 @@ struct dfu_entity *dfu_get_entity(int alt);
 char *dfu_extract_token(char** e, int *n);
 void dfu_trigger_reset(void);
 bool dfu_reset(void);
+int dfu_init_env_entities(char *interface, int dev);
 
 int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
 int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
@@ -137,4 +152,22 @@ static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
 }
 #endif
 
+#ifdef CONFIG_DFU_RAM
+extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s);
+#else
+static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s)
+{
+       puts("RAM support not available!\n");
+       return -1;
+}
+#endif
+
+#ifdef CONFIG_DFU_FUNCTION
+int dfu_add(struct usb_configuration *c);
+#else
+int dfu_add(struct usb_configuration *c)
+{
+       return 0;
+}
+#endif
 #endif /* __DFU_ENTITY_H_ */
index c837bae..7d9403e 100644 (file)
@@ -59,10 +59,10 @@ int fs_read(const char *filename, ulong addr, int offset, int len);
  * to a specific filesystem type via the fstype parameter.
  */
 int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
-               int fstype, int cmdline_base);
+               int fstype);
 int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
                int fstype);
 int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
-               int fstype, int cmdline_base);
+               int fstype);
 
 #endif /* _FS_H */
index aee52e7..8dd2cc3 100644 (file)
@@ -85,6 +85,7 @@ struct i2stx_info {
        unsigned int bitspersample;     /* bits per sample */
        unsigned int channels;          /* audio channels */
        unsigned int base_address;      /* I2S Register Base */
+       unsigned int id;                /* I2S controller id */
 };
 
 /*
index 765d84f..9eefaaf 100644 (file)
@@ -596,9 +596,9 @@ const char *fdt_get_alias_namelen(const void *fdt,
                                  const char *name, int namelen);
 
 /**
- * fdt_get_alias - retreive the path referenced by a given alias
+ * fdt_get_alias - retrieve the path referenced by a given alias
  * @fdt: pointer to the device tree blob
- * @name: name of the alias th look up
+ * @name: name of the alias to look up
  *
  * fdt_get_alias() retrieves the value of a given alias.  That is, the
  * value of the property named 'name' in the node /aliases.
index 3858f8f..111372c 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_FB_H
 
 #include <linux/types.h>
+#include <linux/list.h>
 
 /* Definitions of frame buffers                                                */
 
diff --git a/include/linux/usb/atmel_usba_udc.h b/include/linux/usb/atmel_usba_udc.h
new file mode 100644 (file)
index 0000000..be29ef0
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Platform data definitions for Atmel USBA gadget driver
+ * [Original from Linux kernel: include/linux/usb/atmel_usba_udc.h]
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#ifndef __LINUX_USB_USBA_H__
+#define __LINUX_USB_USBA_H__
+
+struct usba_ep_data {
+       char *name;
+       int index;
+       int fifo_size;
+       int nr_banks;
+       int can_dma;
+       int can_isoc;
+};
+
+struct usba_platform_data {
+       int                     num_ep;
+       struct usba_ep_data     *ep;
+};
+
+extern int usba_udc_probe(struct usba_platform_data *pdata);
+
+#endif /* __LINUX_USB_USBA_H */
index 220d068..a8a5763 100644 (file)
@@ -18,6 +18,7 @@
 #ifndef __LINUX_USB_GADGET_H
 #define __LINUX_USB_GADGET_H
 
+#include <errno.h>
 #include <linux/list.h>
 
 struct usb_ep;
index 657b496..088797e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SPDX-License-Identifier:    GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier:    GPL-2.0 IBM-pibs
  *
  * Additions (C) Copyright 2009 Industrie Dial Face S.p.A.
  */
index 228d771..214b9ed 100644 (file)
@@ -335,7 +335,11 @@ int mmc_start_init(struct mmc *mmc);
 void mmc_set_preinit(struct mmc *mmc, int preinit);
 
 #ifdef CONFIG_GENERIC_MMC
+#ifdef CONFIG_MMC_SPI
 #define mmc_host_is_spi(mmc)   ((mmc)->host_caps & MMC_MODE_SPI)
+#else
+#define mmc_host_is_spi(mmc)   0
+#endif
 struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
 #else
 int mmc_legacy_init(int verbose);
index b18b873..74d06ae 100644 (file)
 #define   SDHCI_SPEC_200       1
 #define   SDHCI_SPEC_300       2
 
+#define SDHCI_GET_VERSION(x) (x->version & SDHCI_SPEC_VER_MASK)
+
 /*
  * End of controller registers.
  */
 #define SDHCI_QUIRK_NO_CD              (1 << 5)
 #define SDHCI_QUIRK_WAIT_SEND_CMD      (1 << 6)
 #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 7)
+#define SDHCI_QUIRK_USE_WIDE8          (1 << 8)
 
 /* to make gcc happy */
 struct sdhci_host;
index c0dab57..5164d43 100644 (file)
 #define        SPI_PREAMBLE    0x80                    /* Skip preamble bytes */
 
 /* SPI transfer flags */
-#define SPI_XFER_BEGIN 0x01                    /* Assert CS before transfer */
-#define SPI_XFER_END   0x02                    /* Deassert CS after transfer */
+#define SPI_XFER_BEGIN         0x01    /* Assert CS before transfer */
+#define SPI_XFER_END           0x02    /* Deassert CS after transfer */
+#define SPI_XFER_MMAP          0x08    /* Memory Mapped start */
+#define SPI_XFER_MMAP_END      0x10    /* Memory Mapped End */
 
 /* Header byte that marks the start of the message */
 #define SPI_PREAMBLE_END_BYTE  0xec
 
-/*-----------------------------------------------------------------------
- * Representation of a SPI slave, i.e. what we're communicating with.
+/**
+ * struct spi_slave - Representation of a SPI slave
  *
  * Drivers are expected to extend this with controller-specific data.
  *
- *   bus:      ID of the bus that the slave is attached to.
- *   cs:       ID of the chip select connected to the slave.
- *   max_write_size:   If non-zero, the maximum number of bytes which can
- *             be written at once, excluding command bytes.
+ * @bus:               ID of the bus that the slave is attached to.
+ * @cs:                        ID of the chip select connected to the slave.
+ * @max_write_size:    If non-zero, the maximum number of bytes which can
+ *                     be written at once, excluding command bytes.
+ * @memory_map:                Address of read-only SPI flash access.
  */
 struct spi_slave {
-       unsigned int    bus;
-       unsigned int    cs;
+       unsigned int bus;
+       unsigned int cs;
        unsigned int max_write_size;
+       void *memory_map;
 };
 
-/*-----------------------------------------------------------------------
+/**
  * Initialization, must be called once on start up.
  *
  * TODO: I don't think we really need this.
@@ -60,10 +64,10 @@ void spi_init(void);
  * Allocate and zero all fields in the spi slave, and set the bus/chip
  * select. Use the helper macro spi_alloc_slave() to call this.
  *
- * @offset: Offset of struct spi_slave within slave structure
- * @size: Size of slave structure
- * @bus: Bus ID of the slave chip.
- * @cs: Chip select ID of the slave chip on the specified bus.
+ * @offset:    Offset of struct spi_slave within slave structure.
+ * @size:      Size of slave structure.
+ * @bus:       Bus ID of the slave chip.
+ * @cs:                Chip select ID of the slave chip on the specified bus.
  */
 void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
                         unsigned int cs);
@@ -74,10 +78,10 @@ void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
  * Allocate and zero all fields in the spi slave, and set the bus/chip
  * select.
  *
- * @_struct: Name of structure to allocate (e.g. struct tegra_spi). This
- *     structure must contain a member 'struct spi_slave *slave'.
- * @bus: Bus ID of the slave chip.
- * @cs: Chip select ID of the slave chip on the specified bus.
+ * @_struct:   Name of structure to allocate (e.g. struct tegra_spi).
+ *             This structure must contain a member 'struct spi_slave *slave'.
+ * @bus:       Bus ID of the slave chip.
+ * @cs:                Chip select ID of the slave chip on the specified bus.
  */
 #define spi_alloc_slave(_struct, bus, cs) \
        spi_do_alloc_slave(offsetof(_struct, slave), \
@@ -89,13 +93,13 @@ void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
  * Allocate and zero all fields in the spi slave, and set the bus/chip
  * select.
  *
- * @bus: Bus ID of the slave chip.
- * @cs: Chip select ID of the slave chip on the specified bus.
+ * @bus:       Bus ID of the slave chip.
+ * @cs:                Chip select ID of the slave chip on the specified bus.
  */
 #define spi_alloc_slave_base(bus, cs) \
        spi_do_alloc_slave(0, sizeof(struct spi_slave), bus, cs)
 
-/*-----------------------------------------------------------------------
+/**
  * Set up communications parameters for a SPI slave.
  *
  * This must be called once for each slave. Note that this function
@@ -103,10 +107,10 @@ void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
  * contents of spi_slave so that the hardware can be easily
  * initialized later.
  *
- *   bus:     Bus ID of the slave chip.
- *   cs:      Chip select ID of the slave chip on the specified bus.
- *   max_hz:  Maximum SCK rate in Hz.
- *   mode:    Clock polarity, clock phase and other parameters.
+ * @bus:       Bus ID of the slave chip.
+ * @cs:                Chip select ID of the slave chip on the specified bus.
+ * @max_hz:    Maximum SCK rate in Hz.
+ * @mode:      Clock polarity, clock phase and other parameters.
  *
  * Returns: A spi_slave reference that can be used in subsequent SPI
  * calls, or NULL if one or more of the parameters are not supported.
@@ -114,14 +118,14 @@ void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                unsigned int max_hz, unsigned int mode);
 
-/*-----------------------------------------------------------------------
+/**
  * Free any memory associated with a SPI slave.
  *
- *   slave:    The SPI slave
+ * @slave:     The SPI slave
  */
 void spi_free_slave(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * Claim the bus and prepare it for communication with a given slave.
  *
  * This must be called before doing any transfers with a SPI slave. It
@@ -130,25 +134,25 @@ void spi_free_slave(struct spi_slave *slave);
  * allowed to claim the same bus for several slaves without releasing
  * the bus in between.
  *
- *   slave:    The SPI slave
+ * @slave:     The SPI slave
  *
  * Returns: 0 if the bus was claimed successfully, or a negative value
  * if it wasn't.
  */
 int spi_claim_bus(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * Release the SPI bus
  *
  * This must be called once for every call to spi_claim_bus() after
  * all transfers have finished. It may disable any SPI hardware as
  * appropriate.
  *
- *   slave:    The SPI slave
+ * @slave:     The SPI slave
  */
 void spi_release_bus(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * SPI transfer
  *
  * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
@@ -161,19 +165,19 @@ void spi_release_bus(struct spi_slave *slave);
  * temporary variables, this is OK).
  *
  * spi_xfer() interface:
- *   slave:    The SPI slave which will be sending/receiving the data.
- *   bitlen:   How many bits to write and read.
- *   dout:     Pointer to a string of bits to send out.  The bits are
+ * @slave:     The SPI slave which will be sending/receiving the data.
+ * @bitlen:    How many bits to write and read.
+ * @dout:      Pointer to a string of bits to send out.  The bits are
  *             held in a byte array and are sent MSB first.
- *   din:      Pointer to a string of bits that will be filled in.
- *   flags:    A bitwise combination of SPI_XFER_* flags.
+ * @din:       Pointer to a string of bits that will be filled in.
+ * @flags:     A bitwise combination of SPI_XFER_* flags.
  *
- *   Returns: 0 on success, not 0 on failure
+ * Returns: 0 on success, not 0 on failure
  */
 int  spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
                void *din, unsigned long flags);
 
-/*-----------------------------------------------------------------------
+/**
  * Determine if a SPI chipselect is valid.
  * This function is provided by the board if the low-level SPI driver
  * needs it to determine if a given chipselect is actually valid.
@@ -183,7 +187,7 @@ int  spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
  */
 int  spi_cs_is_valid(unsigned int bus, unsigned int cs);
 
-/*-----------------------------------------------------------------------
+/**
  * Activate a SPI chipselect.
  * This function is provided by the board code when using a driver
  * that can't control its chipselects automatically (e.g.
@@ -192,7 +196,7 @@ int  spi_cs_is_valid(unsigned int bus, unsigned int cs);
  */
 void spi_cs_activate(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * Deactivate a SPI chipselect.
  * This function is provided by the board code when using a driver
  * that can't control its chipselects automatically (e.g.
@@ -201,18 +205,18 @@ void spi_cs_activate(struct spi_slave *slave);
  */
 void spi_cs_deactivate(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * Set transfer speed.
  * This sets a new speed to be applied for next spi_xfer().
- *   slave:    The SPI slave
- *   hz:       The transfer speed
+ * @slave:     The SPI slave
+ * @hz:                The transfer speed
  */
 void spi_set_speed(struct spi_slave *slave, uint hz);
 
-/*-----------------------------------------------------------------------
+/**
  * Write 8 bits, then read 8 bits.
- *   slave:    The SPI slave we're communicating with
- *   byte:     Byte to be written
+ * @slave:     The SPI slave we're communicating with
+ * @byte:      Byte to be written
  *
  * Returns: The value that was read, or a negative value on error.
  *
index bfc59aa..1ff5af4 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Interface to SPI flash
+ * Common SPI flash Interface
  *
  * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -10,6 +11,7 @@
  * modify it under the terms of the GNU General Public License
  * version 2 as published by the Free Software Foundation. 
  */
+
 #ifndef _SPI_FLASH_H_
 #define _SPI_FLASH_H_
 
 #include <linux/types.h>
 #include <linux/compiler.h>
 
+/**
+ * struct spi_flash - SPI flash structure
+ *
+ * @spi:               SPI slave
+ * @name:              Name of SPI flash
+ * @size:              Total flash size
+ * @page_size:         Write (page) size
+ * @sector_size:       Sector size
+ * @erase_size:                Erase size
+ * @bank_read_cmd:     Bank read cmd
+ * @bank_write_cmd:    Bank write cmd
+ * @bank_curr:         Current flash bank
+ * @poll_cmd:          Poll cmd - for flash erase/program
+ * @erase_cmd:         Erase cmd 4K, 32K, 64K
+ * @memory_map:                Address of read-only SPI flash access
+ * @read:              Flash read ops: Read len bytes at offset into buf
+ *                     Supported cmds: Fast Array Read
+ * @write:             Flash write ops: Write len bytes from buf into offeset
+ *                     Supported cmds: Page Program
+ * @erase:             Flash erase ops: Erase len bytes from offset
+ *                     Supported cmds: Sector erase 4K, 32K, 64K
+ * return 0 - Sucess, 1 - Failure
+ */
 struct spi_flash {
        struct spi_slave *spi;
+       const char *name;
 
-       const char      *name;
-
-       /* Total flash size */
-       u32             size;
-       /* Write (page) size */
-       u32             page_size;
-       /* Erase (sector) size */
-       u32             sector_size;
+       u32 size;
+       u32 page_size;
+       u32 sector_size;
+       u32 erase_size;
 #ifdef CONFIG_SPI_FLASH_BAR
-       /* Bank read cmd */
-       u8              bank_read_cmd;
-       /* Bank write cmd */
-       u8              bank_write_cmd;
-       /* Current flash bank */
-       u8              bank_curr;
+       u8 bank_read_cmd;
+       u8 bank_write_cmd;
+       u8 bank_curr;
 #endif
-       /* Poll cmd - for flash erase/program */
-       u8              poll_cmd;
+       u8 poll_cmd;
+       u8 erase_cmd;
 
-       void *memory_map;       /* Address of read-only SPI flash access */
-       int             (*read)(struct spi_flash *flash, u32 offset,
-                               size_t len, void *buf);
-       int             (*write)(struct spi_flash *flash, u32 offset,
-                               size_t len, const void *buf);
-       int             (*erase)(struct spi_flash *flash, u32 offset,
-                               size_t len);
+       void *memory_map;
+       int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);
+       int (*write)(struct spi_flash *flash, u32 offset, size_t len,
+                       const void *buf);
+       int (*erase)(struct spi_flash *flash, u32 offset, size_t len);
 };
 
-/**
- * spi_flash_do_alloc - Allocate a new spi flash structure
- *
- * The structure is allocated and cleared with default values for
- * read, write and erase, which the caller can modify. The caller must set
- * up size, page_size and sector_size.
- *
- * Use the helper macro spi_flash_alloc() to call this.
- *
- * @offset: Offset of struct spi_slave within slave structure
- * @size: Size of slave structure
- * @spi: SPI slave
- * @name: Name of SPI flash device
- */
-void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,
-                        const char *name);
-
-/**
- * spi_flash_alloc - Allocate a new SPI flash structure
- *
- * @_struct: Name of structure to allocate (e.g. struct ramtron_spi_fram). This
- *     structure must contain a member 'struct spi_flash *flash'.
- * @spi: SPI slave
- * @name: Name of SPI flash device
- */
-#define spi_flash_alloc(_struct, spi, name) \
-       spi_flash_do_alloc(offsetof(_struct, flash), sizeof(_struct), \
-                               spi, name)
-
-/**
- * spi_flash_alloc_base - Allocate a new SPI flash structure with no private data
- *
- * @spi: SPI slave
- * @name: Name of SPI flash device
- */
-#define spi_flash_alloc_base(spi, name) \
-       spi_flash_do_alloc(0, sizeof(struct spi_flash), spi, name)
-
 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
                unsigned int max_hz, unsigned int spi_mode);
 void spi_flash_free(struct spi_flash *flash);
index 35cdcc3..e08deb4 100644 (file)
@@ -11,6 +11,7 @@
 #define SECTOR_SIZE            0x200
 
 #include <mmc.h>
+#include <linux/usb/composite.h>
 
 struct ums_device {
        struct mmc *mmc;
@@ -39,4 +40,12 @@ extern struct ums_board_info *board_ums_init(unsigned int,
 extern int usb_gadget_handle_interrupts(void);
 extern int fsg_main_thread(void *);
 
+#ifdef CONFIG_USB_GADGET_MASS_STORAGE
+int fsg_add(struct usb_configuration *c);
+#else
+int fsg_add(struct usb_configuration *c)
+{
+       return 0;
+}
+#endif
 #endif /* __USB_MASS_STORAGE_H__ */
index 644330a..c5a2b08 100644 (file)
@@ -817,7 +817,7 @@ int himport_r(struct hsearch_data *htab,
         * size of 8 per entry (= safety factor of ~5) should provide enough
         * safety margin for any existing environment definitions and still
         * allow for more than enough dynamic additions. Note that the
-        * "size" argument is supposed to give the maximum enviroment size
+        * "size" argument is supposed to give the maximum environment size
         * (CONFIG_ENV_SIZE).  This heuristics will result in
         * unreasonably large numbers (and thus memory footprint) for
         * big flash environments (>8,000 entries for 64 KB
index da37d66..cca1a26 100644 (file)
@@ -22,7 +22,7 @@
  *
  * LCD backlight is not enabled if temperature values are not within
  * allowed ranges (-30 .. + 80). The brightness of backlite can be
- * controlled by setting "brightness" enviroment variable. Default value is 50%
+ * controlled by setting "brightness" environment variable. Default value is 50%
  *
  * See the list of all parameters in the sysmon_table below
  */
index 734ada6..f63f278 100644 (file)
@@ -629,6 +629,28 @@ It is common when refactoring code for the rodata to decrease as the text size
 increases, and vice versa.
 
 
+Providing 'make' flags
+======================
+
+U-Boot's build system supports a few flags (such as BUILD_TAG) which affect
+the build product. These flags can be specified in the buildman settings
+file. They can also be useful when building U-Boot against other open source
+software.
+
+[make-flags]
+at91-boards=ENABLE_AT91_TEST=1
+snapper9260=${at91-boards} BUILD_TAG=442
+snapper9g45=${at91-boards} BUILD_TAG=443
+
+This will use 'make ENABLE_AT91_TEST=1 BUILD_TAG=442' for snapper9260
+and 'make ENABLE_AT91_TEST=1 BUILD_TAG=442' for snapper9g45. A special
+variable ${target} is available to access the target name (snapper9260 and
+snapper9g20 in this case). Variables are resolved recursively.
+
+It is expected that any variables added are dealt with in U-Boot's
+config.mk file and documented in the README.
+
+
 Other options
 =============
 
index a388896..1d3db20 100644 (file)
@@ -5,16 +5,17 @@
 
 class Board:
     """A particular board that we can build"""
-    def __init__(self, target, arch, cpu, board_name, vendor, soc, options):
+    def __init__(self, status, arch, cpu, soc, vendor, board_name, target, options):
         """Create a new board type.
 
         Args:
-            target: Target name (use make <target>_config to configure)
+            status: define whether the board is 'Active' or 'Orphaned'
             arch: Architecture name (e.g. arm)
             cpu: Cpu name (e.g. arm1136)
-            board_name: Name of board (e.g. integrator)
-            vendor: Name of vendor (e.g. armltd)
             soc: Name of SOC, or '' if none (e.g. mx31)
+            vendor: Name of vendor (e.g. armltd)
+            board_name: Name of board (e.g. integrator)
+            target: Target name (use make <target>_config to configure)
             options: board-specific options (e.g. integratorcp:CM1136)
         """
         self.target = target
@@ -63,8 +64,10 @@ class Boards:
                 for upto in range(len(fields)):
                     if fields[upto] == '-':
                         fields[upto] = ''
-                while len(fields) < 9:
+                while len(fields) < 8:
                     fields.append('')
+                if len(fields) > 8:
+                    fields = fields[:8]
 
                 board = Board(*fields)
                 self.AddBoard(board)
index c801130..9164798 100644 (file)
@@ -36,9 +36,6 @@ def GetItems(section):
         return settings.items(section)
     except ConfigParser.NoSectionError as e:
         print e
-        print ("Warning: No tool chains - please add a [toolchain] section "
-                "to your buildman config file %s. See README for details" %
-                config_fname)
         return []
     except:
         raise
index 29da67a..4a2d753 100644 (file)
@@ -253,6 +253,7 @@ class BuilderThread(threading.Thread):
                     args.extend(['-j', str(self.builder.num_jobs)])
                 config_args = ['%s_config' % brd.target]
                 config_out = ''
+                args.extend(self.builder.toolchains.GetMakeArguments(brd))
 
                 # If we need to reconfigure, do that now
                 if do_config:
index 6fba2f2..43895b8 100755 (executable)
@@ -32,6 +32,19 @@ import toolchain
 
 def RunTests():
     import test
+    import doctest
+
+    result = unittest.TestResult()
+    for module in ['toolchain']:
+        suite = doctest.DocTestSuite(module)
+        suite.run(result)
+
+    # TODO: Surely we can just 'print' result?
+    print result
+    for test, err in result.errors:
+        print err
+    for test, err in result.failures:
+        print err
 
     sys.argv = [sys.argv[0]]
     suite = unittest.TestLoader().loadTestsFromTestCase(test.TestBuild)
index bcdedfb..068784a 100644 (file)
@@ -60,11 +60,11 @@ commits = [
 ]
 
 boards = [
-    ['board0', 'arm', 'armv7', 'ARM Board 1', 'Tester', '', ''],
-    ['board1', 'arm', 'armv7', 'ARM Board 2', 'Tester', '', ''],
-    ['board2', 'powerpc', 'powerpc', 'PowerPC board 1', 'Tester', '', ''],
-    ['board3', 'powerpc', 'mpc5xx', 'PowerPC board 2', 'Tester', '', ''],
-    ['board4', 'sandbox', 'sandbox', 'Sandbox board', 'Tester', '', '']
+    ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 1', 'board0',  ''],
+    ['Active', 'arm', 'armv7', '', 'Tester', 'ARM Board 2', 'board1', ''],
+    ['Active', 'powerpc', 'powerpc', '', 'Tester', 'PowerPC board 1', 'board2', ''],
+    ['Active', 'powerpc', 'mpc5xx', '', 'Tester', 'PowerPC board 2', 'board3', ''],
+    ['Active', 'sandbox', 'sandbox', '', 'Tester', 'Sandbox board', 'board4', ''],
 ]
 
 class Options:
index dfa1d00..a292338 100644 (file)
@@ -3,6 +3,7 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+import re
 import glob
 import os
 
@@ -97,12 +98,18 @@ class Toolchains:
     def __init__(self):
         self.toolchains = {}
         self.paths = []
-        for name, value in bsettings.GetItems('toolchain'):
+        toolchains = bsettings.GetItems('toolchain')
+        if not toolchains:
+            print ("Warning: No tool chains - please add a [toolchain] section"
+                 " to your buildman config file %s. See README for details" %
+                 config_fname)
+
+        for name, value in toolchains:
             if '*' in value:
                 self.paths += glob.glob(value)
             else:
                 self.paths.append(value)
-
+        self._make_flags = dict(bsettings.GetItems('make-flags'))
 
     def Add(self, fname, test=True, verbose=False):
         """Add a toolchain to our list
@@ -167,3 +174,73 @@ class Toolchains:
         if not arch in self.toolchains:
             raise ValueError, ("No tool chain found for arch '%s'" % arch)
         return self.toolchains[arch]
+
+    def ResolveReferences(self, var_dict, args):
+        """Resolve variable references in a string
+
+        This converts ${blah} within the string to the value of blah.
+        This function works recursively.
+
+        Args:
+            var_dict: Dictionary containing variables and their values
+            args: String containing make arguments
+        Returns:
+            Resolved string
+
+        >>> bsettings.Setup()
+        >>> tcs = Toolchains()
+        >>> tcs.Add('fred', False)
+        >>> var_dict = {'oblique' : 'OBLIQUE', 'first' : 'fi${second}rst', \
+                        'second' : '2nd'}
+        >>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set')
+        'this=OBLIQUE_set'
+        >>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set${first}nd')
+        'this=OBLIQUE_setfi2ndrstnd'
+        """
+        re_var = re.compile('(\$\{[a-z0-9A-Z]{1,}\})')
+
+        while True:
+            m = re_var.search(args)
+            if not m:
+                break
+            lookup = m.group(0)[2:-1]
+            value = var_dict.get(lookup, '')
+            args = args[:m.start(0)] + value + args[m.end(0):]
+        return args
+
+    def GetMakeArguments(self, board):
+        """Returns 'make' arguments for a given board
+
+        The flags are in a section called 'make-flags'. Flags are named
+        after the target they represent, for example snapper9260=TESTING=1
+        will pass TESTING=1 to make when building the snapper9260 board.
+
+        References to other boards can be added in the string also. For
+        example:
+
+        [make-flags]
+        at91-boards=ENABLE_AT91_TEST=1
+        snapper9260=${at91-boards} BUILD_TAG=442
+        snapper9g45=${at91-boards} BUILD_TAG=443
+
+        This will return 'ENABLE_AT91_TEST=1 BUILD_TAG=442' for snapper9260
+        and 'ENABLE_AT91_TEST=1 BUILD_TAG=443' for snapper9g45.
+
+        A special 'target' variable is set to the board target.
+
+        Args:
+            board: Board object for the board to check.
+        Returns:
+            'make' flags for that board, or '' if none
+        """
+        self._make_flags['target'] = board.target
+        arg_str = self.ResolveReferences(self._make_flags,
+                           self._make_flags.get(board.target, ''))
+        args = arg_str.split(' ')
+        i = 0
+        while i < len(args):
+            if not args[i]:
+                del args[i]
+            else:
+                i += 1
+        return args
index 896e2bc..88c5bc7 100755 (executable)
@@ -398,7 +398,7 @@ sub top_of_kernel_tree {
        my ($root) = @_;
 
        my @tree_check = (
-               "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
+               "COPYING", "CREDITS", "Kbuild", "Makefile",
                "README", "Documentation", "arch", "include", "drivers",
                "fs", "init", "ipc", "kernel", "lib", "scripts",
        );
@@ -3701,7 +3701,7 @@ sub process {
 $vname has style problems, please review.
 
 If any of these errors are false positives, please report
-them to the maintainer, see CHECKPATCH in MAINTAINERS.
+them to the maintainer, see boards.cfg.
 EOM
        }
 
index 47beaaf..0400a60 100644 (file)
@@ -23,7 +23,7 @@ static image_header_t header;
 static int fit_verify_header (unsigned char *ptr, int image_size,
                        struct mkimage_params *params)
 {
-       return fdt_check_header ((void *)ptr);
+       return fdt_check_header(ptr);
 }
 
 static int fit_check_image_types (uint8_t type)