summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Licenses/README2
-rw-r--r--Makefile10
-rw-r--r--README22
-rw-r--r--arch/arm/cpu/arm926ejs/at91/eflash.c2
-rw-r--r--arch/arm/cpu/arm926ejs/kirkwood/cpu.c2
-rw-r--r--arch/arm/cpu/armv7/at91/sama5d3_devices.c12
-rw-r--r--arch/arm/cpu/armv7/exynos/clock.c61
-rw-r--r--arch/arm/cpu/armv7/exynos/pinmux.c23
-rw-r--r--arch/arm/cpu/armv7/nonsec_virt.S18
-rw-r--r--arch/arm/cpu/armv7/omap5/hw_data.c10
-rw-r--r--arch/arm/cpu/armv7/omap5/prcm-regs.c1
-rw-r--r--arch/arm/cpu/armv7/virt-v7.c20
-rw-r--r--arch/arm/dts/exynos5250.dtsi19
-rw-r--r--arch/arm/include/asm/arch-at91/at91_common.h1
-rw-r--r--arch/arm/include/asm/arch-at91/atmel_usba_udc.h64
-rw-r--r--arch/arm/include/asm/arch-at91/sama5d3.h2
-rw-r--r--arch/arm/include/asm/arch-exynos/clk.h5
-rw-r--r--arch/arm/include/asm/arch-exynos/clock.h4
-rw-r--r--arch/arm/include/asm/arch-exynos/cpu.h4
-rw-r--r--arch/arm/include/asm/arch-exynos/i2s-regs.h6
-rw-r--r--arch/arm/include/asm/arch-exynos/periph.h1
-rw-r--r--arch/arm/include/asm/arch-exynos/spi.h11
-rw-r--r--arch/arm/include/asm/arch-omap5/ehci.h15
-rw-r--r--arch/arm/include/asm/arch-omap5/omap.h3
-rw-r--r--arch/arm/include/asm/arch-omap5/spl.h1
-rw-r--r--arch/arm/include/asm/omap_common.h1
-rw-r--r--arch/powerpc/cpu/mpc85xx/cmd_errata.c3
-rw-r--r--arch/powerpc/cpu/mpc85xx/start.S8
-rw-r--r--arch/powerpc/cpu/ppc4xx/4xx_pci.c2
-rw-r--r--arch/powerpc/cpu/ppc4xx/4xx_uart.c2
-rw-r--r--arch/powerpc/cpu/ppc4xx/miiphy.c2
-rw-r--r--arch/powerpc/cpu/ppc4xx/start.S2
-rw-r--r--arch/powerpc/include/asm/config_mpc85xx.h21
-rw-r--r--arch/powerpc/include/asm/ppc405.h2
-rw-r--r--arch/powerpc/include/asm/ppc440.h2
-rw-r--r--arch/powerpc/include/asm/ppc4xx-emac.h2
-rw-r--r--arch/powerpc/include/asm/ppc4xx-mal.h2
-rw-r--r--arch/powerpc/include/asm/ppc4xx.h2
-rw-r--r--board/RPXlite_dw/README4
-rw-r--r--board/atmel/sama5d3xek/sama5d3xek.c13
-rw-r--r--board/cray/L1/init.S2
-rw-r--r--board/csb272/init.S2
-rw-r--r--board/csb472/init.S2
-rw-r--r--board/esd/pci405/writeibm.S2
-rw-r--r--board/freescale/mx28evk/README4
-rw-r--r--board/jse/init.S2
-rw-r--r--board/mpl/common/pci.c2
-rw-r--r--board/mpl/mip405/init.S2
-rw-r--r--board/mpl/pip405/init.S2
-rw-r--r--board/samsung/dts/exynos5250-smdk5250.dts13
-rw-r--r--board/samsung/dts/exynos5250-snow.dts14
-rw-r--r--board/sbc8349/README2
-rw-r--r--board/sc3/init.S2
-rw-r--r--board/ti/dra7xx/mux_data.h10
-rw-r--r--board/w7o/init.S2
-rw-r--r--boards.cfg2
-rw-r--r--common/cmd_bootm.c9
-rw-r--r--common/cmd_dfu.c19
-rw-r--r--common/cmd_ext2.c5
-rw-r--r--common/cmd_ext4.c5
-rw-r--r--common/cmd_fat.c5
-rw-r--r--common/cmd_fs.c6
-rw-r--r--common/cmd_gpt.c4
-rw-r--r--common/cmd_mmc.c4
-rw-r--r--common/cmd_mtdparts.c9
-rw-r--r--common/cmd_pxe.c20
-rw-r--r--common/cmd_sf.c13
-rw-r--r--common/cmd_usb_mass_storage.c1
-rw-r--r--common/image-fdt.c2
-rw-r--r--common/image-fit.c8
-rw-r--r--common/image.c8
-rw-r--r--common/spl/spl_mmc.c17
-rw-r--r--disk/part_efi.c3
-rw-r--r--doc/README.JFFS2_NAND2
-rw-r--r--doc/README.hwconfig2
-rw-r--r--doc/SPI/README.ti_qspi_dra_test48
-rw-r--r--doc/SPI/README.ti_qspi_flash47
-rw-r--r--doc/SPI/status.txt31
-rw-r--r--doc/git-mailrc2
-rw-r--r--doc/uImage.FIT/command_syntax_extensions.txt2
-rw-r--r--doc/uImage.FIT/source_file_format.txt2
-rw-r--r--drivers/block/sym53c8xx.c2
-rw-r--r--drivers/dfu/Makefile1
-rw-r--r--drivers/dfu/dfu.c34
-rw-r--r--drivers/dfu/dfu_mmc.c9
-rw-r--r--drivers/dfu/dfu_nand.c7
-rw-r--r--drivers/dfu/dfu_ram.c77
-rw-r--r--drivers/mmc/Makefile2
-rw-r--r--drivers/mmc/dw_mmc.c9
-rw-r--r--drivers/mmc/mmc.c205
-rw-r--r--drivers/mmc/mmc_private.h45
-rw-r--r--drivers/mmc/mmc_write.c179
-rw-r--r--drivers/mmc/omap_hsmmc.c41
-rw-r--r--drivers/mmc/s5p_sdhci.c4
-rw-r--r--drivers/mmc/sdhci.c18
-rw-r--r--drivers/mtd/spi/Makefile15
-rw-r--r--drivers/mtd/spi/atmel.c544
-rw-r--r--drivers/mtd/spi/eon.c60
-rw-r--r--drivers/mtd/spi/gigadevice.c65
-rw-r--r--drivers/mtd/spi/macronix.c98
-rw-r--r--drivers/mtd/spi/ramtron.c122
-rw-r--r--drivers/mtd/spi/sf.c54
-rw-r--r--drivers/mtd/spi/sf_internal.h (renamed from drivers/mtd/spi/spi_flash_internal.h)140
-rw-r--r--drivers/mtd/spi/sf_ops.c405
-rw-r--r--drivers/mtd/spi/sf_probe.c363
-rw-r--r--drivers/mtd/spi/spansion.c141
-rw-r--r--drivers/mtd/spi/spi_flash.c615
-rw-r--r--drivers/mtd/spi/sst.c238
-rw-r--r--drivers/mtd/spi/stmicro.c202
-rw-r--r--drivers/mtd/spi/winbond.c141
-rw-r--r--drivers/net/4xx_enet.c2
-rw-r--r--drivers/net/npe/miiphy.c2
-rw-r--r--drivers/net/phy/smsc.c2
-rw-r--r--drivers/pci/pci_auto.c2
-rw-r--r--drivers/power/power_core.c19
-rw-r--r--drivers/sound/max98095.c155
-rw-r--r--drivers/sound/max98095.h10
-rw-r--r--drivers/sound/samsung-i2s.c65
-rw-r--r--drivers/sound/sound.c28
-rw-r--r--drivers/sound/wm8994.c167
-rw-r--r--drivers/sound/wm8994_registers.h39
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/exynos_spi.c107
-rw-r--r--drivers/spi/mxs_spi.c12
-rw-r--r--drivers/spi/ti_qspi.c311
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c1306
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.h326
-rw-r--r--drivers/usb/gadget/config.c6
-rw-r--r--drivers/usb/gadget/ether.c5
-rw-r--r--drivers/usb/gadget/f_dfu.h3
-rw-r--r--drivers/usb/gadget/g_dnl.c5
-rw-r--r--drivers/usb/host/ehci-hcd.c38
-rw-r--r--examples/standalone/README.smc91111_eeprom6
-rw-r--r--fs/fs.c16
-rw-r--r--include/common.h12
-rw-r--r--include/configs/P2041RDB.h4
-rw-r--r--include/configs/am335x_evm.h6
-rw-r--r--include/configs/dra7xx_evm.h19
-rw-r--r--include/configs/eXalion.h2
-rw-r--r--include/configs/sacsng.h2
-rw-r--r--include/configs/sama5d3xek.h8
-rw-r--r--include/configs/top9000.h1
-rw-r--r--include/dfu.h35
-rw-r--r--include/fs.h4
-rw-r--r--include/i2s.h1
-rw-r--r--include/libfdt.h4
-rw-r--r--include/linux/fb.h1
-rw-r--r--include/linux/usb/atmel_usba_udc.h26
-rw-r--r--include/linux/usb/gadget.h1
-rw-r--r--include/miiphy.h2
-rw-r--r--include/mmc.h4
-rw-r--r--include/sdhci.h3
-rw-r--r--include/spi.h100
-rw-r--r--include/spi_flash.h103
-rw-r--r--include/usb_mass_storage.h9
-rw-r--r--lib/hashtable.c2
-rw-r--r--post/board/lwmon5/sysmon.c2
-rw-r--r--tools/buildman/README22
-rw-r--r--tools/buildman/board.py13
-rw-r--r--tools/buildman/bsettings.py3
-rw-r--r--tools/buildman/builder.py1
-rwxr-xr-xtools/buildman/buildman.py13
-rw-r--r--tools/buildman/test.py10
-rw-r--r--tools/buildman/toolchain.py81
-rwxr-xr-xtools/checkpatch.pl4
-rw-r--r--tools/fit_image.c2
167 files changed, 4757 insertions, 2940 deletions
diff --git a/Licenses/README b/Licenses/README
index 4196125..9f61192 100644
--- a/Licenses/README
+++ b/Licenses/README
@@ -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
diff --git a/Makefile b/Makefile
index 1365db6..b09bfcc 100644
--- 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
--- 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.
diff --git a/arch/arm/cpu/arm926ejs/at91/eflash.c b/arch/arm/cpu/arm926ejs/at91/eflash.c
index 3e21cdb..3f39264 100644
--- a/arch/arm/cpu/arm926ejs/at91/eflash.c
+++ b/arch/arm/cpu/arm926ejs/at91/eflash.c
@@ -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!
*/
diff --git a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c
index cde3172..d4711c0 100644
--- a/arch/arm/cpu/arm926ejs/kirkwood/cpu.c
+++ b/arch/arm/cpu/arm926ejs/kirkwood/cpu.c
@@ -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);
diff --git a/arch/arm/cpu/armv7/at91/sama5d3_devices.c b/arch/arm/cpu/armv7/at91/sama5d3_devices.c
index e55e1c6..51f0a6d 100644
--- a/arch/arm/cpu/armv7/at91/sama5d3_devices.c
+++ b/arch/arm/cpu/armv7/at91/sama5d3_devices.c
@@ -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
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 0cb1a61..36fedd6 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -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)
diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
index 1b05ebf..8002bce 100644
--- a/arch/arm/cpu/armv7/exynos/pinmux.c
+++ b/arch/arm/cpu/armv7/exynos/pinmux.c
@@ -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;
}
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
index 358348f..24b4c18 100644
--- a/arch/arm/cpu/armv7/nonsec_virt.S
+++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -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>
diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c
index fbbc486..a1b249e 100644
--- a/arch/arm/cpu/armv7/omap5/hw_data.c
+++ b/arch/arm/cpu/armv7/omap5/hw_data.c
@@ -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);
diff --git a/arch/arm/cpu/armv7/omap5/prcm-regs.c b/arch/arm/cpu/armv7/omap5/prcm-regs.c
index 5a3d52c..7a7cade 100644
--- a/arch/arm/cpu/armv7/omap5/prcm-regs.c
+++ b/arch/arm/cpu/armv7/omap5/prcm-regs.c
@@ -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,
diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c
index 6de7fe7..2cd604f 100644
--- a/arch/arm/cpu/armv7/virt-v7.c
+++ b/arch/arm/cpu/armv7/virt-v7.c
@@ -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>
diff --git a/arch/arm/dts/exynos5250.dtsi b/arch/arm/dts/exynos5250.dtsi
index 4fff5e3..1c5474f 100644
--- a/arch/arm/dts/exynos5250.dtsi
+++ b/arch/arm/dts/exynos5250.dtsi
@@ -93,9 +93,28 @@
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 {
diff --git a/arch/arm/include/asm/arch-at91/at91_common.h b/arch/arm/include/asm/arch-at91/at91_common.h
index 9f54fdd..abcb97d 100644
--- a/arch/arm/include/asm/arch-at91/at91_common.h
+++ b/arch/arm/include/asm/arch-at91/at91_common.h
@@ -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
index 0000000..6f540d2
--- /dev/null
+++ b/arch/arm/include/asm/arch-at91/atmel_usba_udc.h
@@ -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
diff --git a/arch/arm/include/asm/arch-at91/sama5d3.h b/arch/arm/include/asm/arch-at91/sama5d3.h
index fefee5e..123a627 100644
--- a/arch/arm/include/asm/arch-at91/sama5d3.h
+++ b/arch/arm/include/asm/arch-at91/sama5d3.h
@@ -120,7 +120,7 @@
#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
diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
index 71075bd..1d6fa93 100644
--- a/arch/arm/include/asm/arch-exynos/clk.h
+++ b/arch/arm/include/asm/arch-exynos/clk.h
@@ -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);
diff --git a/arch/arm/include/asm/arch-exynos/clock.h b/arch/arm/include/asm/arch-exynos/clock.h
index 2b97b9a..cf26eef 100644
--- a/arch/arm/include/asm/arch-exynos/clock.h
+++ b/arch/arm/include/asm/arch-exynos/clock.h
@@ -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
diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
index cb924fb..4b67191 100644
--- a/arch/arm/include/asm/arch-exynos/cpu.h
+++ b/arch/arm/include/asm/arch-exynos/cpu.h
@@ -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
@@ -85,10 +86,12 @@
#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 */
diff --git a/arch/arm/include/asm/arch-exynos/i2s-regs.h b/arch/arm/include/asm/arch-exynos/i2s-regs.h
index 613b9b7..4a4a7a0 100644
--- a/arch/arm/include/asm/arch-exynos/i2s-regs.h
+++ b/arch/arm/include/asm/arch-exynos/i2s-regs.h
@@ -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__ */
diff --git a/arch/arm/include/asm/arch-exynos/periph.h b/arch/arm/include/asm/arch-exynos/periph.h
index 9952155..64bd8b7 100644
--- a/arch/arm/include/asm/arch-exynos/periph.h
+++ b/arch/arm/include/asm/arch-exynos/periph.h
@@ -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
diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h
index fb23aa6..147c1a7 100644
--- a/arch/arm/include/asm/arch-exynos/spi.h
+++ b/arch/arm/include/asm/arch-exynos/spi.h
@@ -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
diff --git a/arch/arm/include/asm/arch-omap5/ehci.h b/arch/arm/include/asm/arch-omap5/ehci.h
index 3921e4a..63aaa02 100644
--- a/arch/arm/include/asm/arch-omap5/ehci.h
+++ b/arch/arm/include/asm/arch-omap5/ehci.h
@@ -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
diff --git a/arch/arm/include/asm/arch-omap5/omap.h b/arch/arm/include/asm/arch-omap5/omap.h
index e9a51d3..414d37a 100644
--- a/arch/arm/include/asm/arch-omap5/omap.h
+++ b/arch/arm/include/asm/arch-omap5/omap.h
@@ -61,6 +61,9 @@
/* GPMC */
#define OMAP54XX_GPMC_BASE 0x50000000
+/* QSPI */
+#define QSPI_BASE 0x4B300000
+
/*
* Hardware Register Details
*/
diff --git a/arch/arm/include/asm/arch-omap5/spl.h b/arch/arm/include/asm/arch-omap5/spl.h
index fe8b0c0..57f0de5 100644
--- a/arch/arm/include/asm/arch-omap5/spl.h
+++ b/arch/arm/include/asm/arch-omap5/spl.h
@@ -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
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index 61fee9f..3a998cc 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -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;
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index eea264b..c441bd2 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -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))
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
index ad57a9c..be4f4ae 100644
--- a/arch/powerpc/cpu/mpc85xx/start.S
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -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.
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_pci.c b/arch/powerpc/cpu/ppc4xx/4xx_pci.c
index 5584e0f..08781a1 100644
--- a/arch/powerpc/cpu/ppc4xx/4xx_pci.c
+++ b/arch/powerpc/cpu/ppc4xx/4xx_pci.c
@@ -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
*
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_uart.c b/arch/powerpc/cpu/ppc4xx/4xx_uart.c
index 50c28a0..c02058f 100644
--- a/arch/powerpc/cpu/ppc4xx/4xx_uart.c
+++ b/arch/powerpc/cpu/ppc4xx/4xx_uart.c
@@ -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>
diff --git a/arch/powerpc/cpu/ppc4xx/miiphy.c b/arch/powerpc/cpu/ppc4xx/miiphy.c
index e4a9db6..10147de 100644
--- a/arch/powerpc/cpu/ppc4xx/miiphy.c
+++ b/arch/powerpc/cpu/ppc4xx/miiphy.c
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier: GPL-2.0 IBM-pibs
*/
/*-----------------------------------------------------------------------------+
|
diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S
index d9d8cbf..38bbc5a 100644
--- a/arch/powerpc/cpu/ppc4xx/start.S
+++ b/arch/powerpc/cpu/ppc4xx/start.S
@@ -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
*/
/*
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index 15e44de..bec8966 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -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
@@ -108,6 +111,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
#elif defined(CONFIG_MPC8572)
#define CONFIG_MAX_CPUS 2
@@ -117,6 +121,7 @@
#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
@@ -135,6 +140,7 @@
#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
@@ -149,6 +155,7 @@
#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)
@@ -164,6 +171,7 @@
#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)
@@ -176,6 +184,7 @@
#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
@@ -205,6 +214,7 @@
#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
@@ -216,6 +226,7 @@
#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
@@ -230,6 +241,7 @@
#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
@@ -241,6 +253,7 @@
#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
@@ -254,6 +267,7 @@
#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
@@ -268,6 +282,7 @@
#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)
@@ -283,6 +298,7 @@
#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)
@@ -293,6 +309,7 @@
#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
@@ -307,6 +324,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
#elif defined(CONFIG_PPC_P2041) /* also supports P2040 */
#define CONFIG_SYS_FSL_QORIQ_CHASSIS1
@@ -506,6 +524,7 @@
#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
@@ -525,6 +544,7 @@
#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
@@ -658,6 +678,7 @@
#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
diff --git a/arch/powerpc/include/asm/ppc405.h b/arch/powerpc/include/asm/ppc405.h
index 8bb342b..f2ed16a 100644
--- a/arch/powerpc/include/asm/ppc405.h
+++ b/arch/powerpc/include/asm/ppc405.h
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier: GPL-2.0 IBM-pibs
*/
#ifndef __PPC405_H__
diff --git a/arch/powerpc/include/asm/ppc440.h b/arch/powerpc/include/asm/ppc440.h
index 0f5bc8d..0cfa88b 100644
--- a/arch/powerpc/include/asm/ppc440.h
+++ b/arch/powerpc/include/asm/ppc440.h
@@ -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__
diff --git a/arch/powerpc/include/asm/ppc4xx-emac.h b/arch/powerpc/include/asm/ppc4xx-emac.h
index e6eb332..76fa95c 100644
--- a/arch/powerpc/include/asm/ppc4xx-emac.h
+++ b/arch/powerpc/include/asm/ppc4xx-emac.h
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier: GPL-2.0 IBM-pibs
*/
/*----------------------------------------------------------------------------+
|
diff --git a/arch/powerpc/include/asm/ppc4xx-mal.h b/arch/powerpc/include/asm/ppc4xx-mal.h
index d15290d..ef8b174 100644
--- a/arch/powerpc/include/asm/ppc4xx-mal.h
+++ b/arch/powerpc/include/asm/ppc4xx-mal.h
@@ -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
*/
/*----------------------------------------------------------------------------+
|
diff --git a/arch/powerpc/include/asm/ppc4xx.h b/arch/powerpc/include/asm/ppc4xx.h
index 8d703c6..e6a3bff 100644
--- a/arch/powerpc/include/asm/ppc4xx.h
+++ b/arch/powerpc/include/asm/ppc4xx.h
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier: GPL-2.0 IBM-pibs
*/
#ifndef __PPC4XX_H__
diff --git a/board/RPXlite_dw/README b/board/RPXlite_dw/README
index 14296b2..9e2d0f4 100644
--- a/board/RPXlite_dw/README
+++ b/board/RPXlite_dw/README
@@ -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 \
diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c
index 97caf64..b0965ef 100644
--- a/board/atmel/sama5d3xek/sama5d3xek.c
+++ b/board/atmel/sama5d3xek/sama5d3xek.c
@@ -21,6 +21,10 @@
#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;
}
diff --git a/board/cray/L1/init.S b/board/cray/L1/init.S
index 82f21b0..44c688d 100644
--- a/board/cray/L1/init.S
+++ b/board/cray/L1/init.S
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier: GPL-2.0 IBM-pibs
*/
/*----------------------------------------------------------------------------- */
diff --git a/board/csb272/init.S b/board/csb272/init.S
index b1283aa..5961978 100644
--- a/board/csb272/init.S
+++ b/board/csb272/init.S
@@ -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>
diff --git a/board/csb472/init.S b/board/csb472/init.S
index f5805b7..1ebc9ea 100644
--- a/board/csb472/init.S
+++ b/board/csb472/init.S
@@ -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>
diff --git a/board/esd/pci405/writeibm.S b/board/esd/pci405/writeibm.S
index 38acca1..03eaf97 100644
--- a/board/esd/pci405/writeibm.S
+++ b/board/esd/pci405/writeibm.S
@@ -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 */
diff --git a/board/freescale/mx28evk/README b/board/freescale/mx28evk/README
index 524f3fc..0389a1d 100644
--- a/board/freescale/mx28evk/README
+++ b/board/freescale/mx28evk/README
@@ -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.
diff --git a/board/jse/init.S b/board/jse/init.S
index 7b918b5..4e449fe 100644
--- a/board/jse/init.S
+++ b/board/jse/init.S
@@ -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 */
diff --git a/board/mpl/common/pci.c b/board/mpl/common/pci.c
index 6ab263a..cd969cb 100644
--- a/board/mpl/common/pci.c
+++ b/board/mpl/common/pci.c
@@ -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
diff --git a/board/mpl/mip405/init.S b/board/mpl/mip405/init.S
index bf886c0..642f17c 100644
--- a/board/mpl/mip405/init.S
+++ b/board/mpl/mip405/init.S
@@ -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
diff --git a/board/mpl/pip405/init.S b/board/mpl/pip405/init.S
index 9ed2799..95fed34 100644
--- a/board/mpl/pip405/init.S
+++ b/board/mpl/pip405/init.S
@@ -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
diff --git a/board/samsung/dts/exynos5250-smdk5250.dts b/board/samsung/dts/exynos5250-smdk5250.dts
index 1e94c7f..b1bba96 100644
--- a/board/samsung/dts/exynos5250-smdk5250.dts
+++ b/board/samsung/dts/exynos5250-smdk5250.dts
@@ -36,6 +36,7 @@
mmc3 = "/mmc@12230000";
serial0 = "/serial@12C30000";
console = "/serial@12C30000";
+ i2s = "/sound@3830000";
};
sromc@12250000 {
@@ -49,16 +50,14 @@
};
};
- 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>;
diff --git a/board/samsung/dts/exynos5250-snow.dts b/board/samsung/dts/exynos5250-snow.dts
index 7832e4e..9b7e57e 100644
--- a/board/samsung/dts/exynos5250-snow.dts
+++ b/board/samsung/dts/exynos5250-snow.dts
@@ -36,6 +36,7 @@
mmc3 = "/mmc@12230000";
serial0 = "/serial@12C30000";
console = "/serial@12C30000";
+ i2s = "/sound@3830000";
};
i2c4: i2c@12ca0000 {
@@ -65,16 +66,15 @@
};
};
- 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>;
diff --git a/board/sbc8349/README b/board/sbc8349/README
index 2c35919..e2d60cc 100644
--- a/board/sbc8349/README
+++ b/board/sbc8349/README
@@ -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
diff --git a/board/sc3/init.S b/board/sc3/init.S
index 9921f8f..46323d2 100644
--- a/board/sc3/init.S
+++ b/board/sc3/init.S
@@ -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>
diff --git a/board/ti/dra7xx/mux_data.h b/board/ti/dra7xx/mux_data.h
index 0a86594..6965cc5 100644
--- a/board/ti/dra7xx/mux_data.h
+++ b/board/ti/dra7xx/mux_data.h
@@ -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_ */
diff --git a/board/w7o/init.S b/board/w7o/init.S
index 490411e..54eda32 100644
--- a/board/w7o/init.S
+++ b/board/w7o/init.S
@@ -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>
diff --git a/boards.cfg b/boards.cfg
index a475f52..85143c6 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -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
###########################################################################################################
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index b07b0f4..166b901 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -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)
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
index 793c422..7ce92ce 100644
--- a/common/cmd_dfu.c
+++ b/common/cmd_dfu.c
@@ -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);
diff --git a/common/cmd_ext2.c b/common/cmd_ext2.c
index 1731919..5a4bcc1 100644
--- a/common/cmd_ext2.c
+++ b/common/cmd_ext2.c
@@ -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."
);
diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c
index 4a27cd9..8289d25 100644
--- a/common/cmd_ext4.c
+++ b/common/cmd_ext4.c
@@ -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");
diff --git a/common/cmd_fat.c b/common/cmd_fat.c
index f6d7aff..a12d8fa 100644
--- a/common/cmd_fat.c
+++ b/common/cmd_fat.c
@@ -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[])
diff --git a/common/cmd_fs.c b/common/cmd_fs.c
index a681d03..91a205a 100644
--- a/common/cmd_fs.c
+++ b/common/cmd_fs.c
@@ -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[])
diff --git a/common/cmd_gpt.c b/common/cmd_gpt.c
index 06767aa..a46f5cc 100644
--- a/common/cmd_gpt.c
+++ b/common/cmd_gpt.c
@@ -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"
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 1cdeb44..67a94a7 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -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 */
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index 3023479..f791372 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -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
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index a2fb50a..c5f4a22 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -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);
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 4af0f0a..3f60979 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -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;
}
diff --git a/common/cmd_usb_mass_storage.c b/common/cmd_usb_mass_storage.c
index 33a4715..ccf7195 100644
--- a/common/cmd_usb_mass_storage.c
+++ b/common/cmd_usb_mass_storage.c
@@ -5,7 +5,6 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#include <errno.h>
#include <common.h>
#include <command.h>
#include <g_dnl.h>
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 2e22cca..6f9ce7d 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -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;
}
diff --git a/common/image-fit.c b/common/image-fit.c
index 199b4ed..cf4b67e 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -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;
}
diff --git a/common/image.c b/common/image.c
index 2c88091..b0ae58f 100644
--- a/common/image.c
+++ b/common/image.c
@@ -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
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index f27b4c2..fc2f226 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -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();
}
diff --git a/disk/part_efi.c b/disk/part_efi.c
index b7524d6..9c33ae7 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -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;
}
diff --git a/doc/README.JFFS2_NAND b/doc/README.JFFS2_NAND
index 5018ae8..09788d5 100644
--- a/doc/README.JFFS2_NAND
+++ b/doc/README.JFFS2_NAND
@@ -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
diff --git a/doc/README.hwconfig b/doc/README.hwconfig
index cf54965..b6ddb43 100644
--- a/doc/README.hwconfig
+++ b/doc/README.hwconfig
@@ -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
index 0000000..fe37857
--- /dev/null
+++ b/doc/SPI/README.ti_qspi_dra_test
@@ -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
index 0000000..1b86d01
--- /dev/null
+++ b/doc/SPI/README.ti_qspi_flash
@@ -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
index 0000000..62c3c85
--- /dev/null
+++ b/doc/SPI/status.txt
@@ -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.
diff --git a/doc/git-mailrc b/doc/git-mailrc
index 2cacaa0..251586e 100644
--- a/doc/git-mailrc
+++ b/doc/git-mailrc
@@ -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
diff --git a/doc/uImage.FIT/command_syntax_extensions.txt b/doc/uImage.FIT/command_syntax_extensions.txt
index 002818c..6c99b1c 100644
--- a/doc/uImage.FIT/command_syntax_extensions.txt
+++ b/doc/uImage.FIT/command_syntax_extensions.txt
@@ -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:
diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt
index 6d20707..160b2d0 100644
--- a/doc/uImage.FIT/source_file_format.txt
+++ b/doc/uImage.FIT/source_file_format.txt
@@ -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.
diff --git a/drivers/block/sym53c8xx.c b/drivers/block/sym53c8xx.c
index c538e37..6f1ac85 100644
--- a/drivers/block/sym53c8xx.c
+++ b/drivers/block/sym53c8xx.c
@@ -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)
{
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index fca370a..de9e44e 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -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))
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index d73d510..56b21c7 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -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];
}
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 0871a77..f942758 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -13,16 +13,11 @@
#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];
diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
index 0ec12cf..edbf5a9 100644
--- a/drivers/dfu/dfu_nand.c
+++ b/drivers/dfu/dfu_nand.c
@@ -19,12 +19,7 @@
#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
index 0000000..335a8e1
--- /dev/null
+++ b/drivers/dfu/dfu_ram.c
@@ -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;
+}
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index bedf833..06280d1 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -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)
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index a82ee17..9a803a0 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -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);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 5502675..84dae4d 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -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
index 0000000..16dcf9f
--- /dev/null
+++ b/drivers/mmc/mmc_private.h
@@ -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
index 0000000..aa2fdef
--- /dev/null
+++ b/drivers/mmc/mmc_write.c
@@ -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;
+}
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 975b2c5..d3a8b53 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -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;
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index 7f89403..40ff873 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -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);
}
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 4261991..dfb2eee 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -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;
}
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index 191138a..86ffc59 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -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
index f34df43..0000000
--- a/drivers/mtd/spi/atmel.c
+++ /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
index 25cfc12..0000000
--- a/drivers/mtd/spi/eon.c
+++ /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
index b42581a..0000000
--- a/drivers/mtd/spi/gigadevice.c
+++ /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
index 70435eb..0000000
--- a/drivers/mtd/spi/macronix.c
+++ /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;
-}
diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c
index 38f9d69..d50da37 100644
--- a/drivers/mtd/spi/ramtron.c
+++ b/drivers/mtd/spi/ramtron.c
@@ -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
index 0000000..ddbdda0
--- /dev/null
+++ b/drivers/mtd/spi/sf.c
@@ -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);
+}
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/sf_internal.h
index af1afa9..12d02f9 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -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
@@ -48,6 +49,21 @@
#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
index 0000000..2396e22
--- /dev/null
+++ b/drivers/mtd/spi/sf_ops.c
@@ -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
index 0000000..4251b1b
--- /dev/null
+++ b/drivers/mtd/spi/sf_probe.c
@@ -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
index fa7ac8c..0000000
--- a/drivers/mtd/spi/spansion.c
+++ /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
index 5d5055f..0000000
--- a/drivers/mtd/spi/spi_flash.c
+++ /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
index 256867c..0000000
--- a/drivers/mtd/spi/sst.c
+++ /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
index c5fa64e..0000000
--- a/drivers/mtd/spi/stmicro.c
+++ /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
index b31911a..0000000
--- a/drivers/mtd/spi/winbond.c
+++ /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;
-}
diff --git a/drivers/net/4xx_enet.c b/drivers/net/4xx_enet.c
index c98867d..381ec42 100644
--- a/drivers/net/4xx_enet.c
+++ b/drivers/net/4xx_enet.c
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier: GPL-2.0 IBM-pibs
*/
/*-----------------------------------------------------------------------------+
*
diff --git a/drivers/net/npe/miiphy.c b/drivers/net/npe/miiphy.c
index 07fcb60..002fb81 100644
--- a/drivers/net/npe/miiphy.c
+++ b/drivers/net/npe/miiphy.c
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: GPL-2.0 ibm-pibs
+ * SPDX-License-Identifier: GPL-2.0 IBM-pibs
*/
/*-----------------------------------------------------------------------------+
|
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 5936f9b..60ed92d 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -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>
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index c4ed8ba..86ba6b5 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -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) {
diff --git a/drivers/power/power_core.c b/drivers/power/power_core.c
index d79971b..29ccc83 100644
--- a/drivers/power/power_core.c
+++ b/drivers/power/power_core.c
@@ -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;
diff --git a/drivers/sound/max98095.c b/drivers/sound/max98095.c
index d69db58..febf419 100644
--- a/drivers/sound/max98095.c
+++ b/drivers/sound/max98095.c
@@ -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;
diff --git a/drivers/sound/max98095.h b/drivers/sound/max98095.h
index ae5eb14..44b1e3a 100644
--- a/drivers/sound/max98095.h
+++ b/drivers/sound/max98095.h
@@ -11,6 +11,12 @@
#ifndef _MAX98095_H
#define _MAX98095_H
+/* Available audio interface ports in wm8994 codec */
+enum en_max_audio_interface {
+ AIF1 = 1,
+ AIF2,
+};
+
/*
* MAX98095 Registers Definition
*/
@@ -305,7 +311,7 @@
*
* @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
diff --git a/drivers/sound/samsung-i2s.c b/drivers/sound/samsung-i2s.c
index 49921e5..47f155f 100644
--- a/drivers/sound/samsung-i2s.c
+++ b/drivers/sound/samsung-i2s.c
@@ -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);
diff --git a/drivers/sound/sound.c b/drivers/sound/sound.c
index 6fcc75d..9b8ce5a 100644
--- a/drivers/sound/sound.c
+++ b/drivers/sound/sound.c
@@ -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,
diff --git a/drivers/sound/wm8994.c b/drivers/sound/wm8994.c
index 37e354c..f8e9a6e 100644
--- a/drivers/sound/wm8994.c
+++ b/drivers/sound/wm8994.c
@@ -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;
diff --git a/drivers/sound/wm8994_registers.h b/drivers/sound/wm8994_registers.h
index 1e987c2..0aba2fd 100644
--- a/drivers/sound/wm8994_registers.h
+++ b/drivers/sound/wm8994_registers.h
@@ -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
@@ -82,6 +85,20 @@
/* 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)
*/
@@ -91,6 +108,12 @@
/* 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
@@ -170,6 +193,9 @@
/*
* 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
@@ -254,6 +280,8 @@
/* 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
@@ -261,6 +289,8 @@
/* 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
@@ -285,11 +315,12 @@
* 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
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 91d24ce..e5941b0 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -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
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index efc8b1e..699c57e 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -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;
}
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
index 3cf7142..2b9f395 100644
--- a/drivers/spi/mxs_spi.c
+++ b/drivers/spi/mxs_spi.c
@@ -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
index 0000000..5a5b482
--- /dev/null
+++ b/drivers/spi/ti_qspi.c
@@ -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;
+}
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 4c2a39a..1590c4a 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -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
index 0000000..c99208d
--- /dev/null
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -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
index 0000000..92e462d
--- /dev/null
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -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 */
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index f563afe..014a679 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -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;
}
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 579893c..700d5fb 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -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
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
index 34a4dde..cc2c455 100644
--- a/drivers/usb/gadget/f_dfu.h
+++ b/drivers/usb/gadget/f_dfu.h
@@ -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_ */
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index a3e05a8..40868c0 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -7,7 +7,6 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#include <errno.h>
#include <common.h>
#include <malloc.h>
@@ -15,11 +14,11 @@
#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:
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index fdad739..3ae04c0 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -36,6 +36,12 @@
#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);
}
diff --git a/examples/standalone/README.smc91111_eeprom b/examples/standalone/README.smc91111_eeprom
index 28e7e69..a2d52e7 100644
--- a/examples/standalone/README.smc91111_eeprom
+++ b/examples/standalone/README.smc91111_eeprom
@@ -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
--- 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;
diff --git a/include/common.h b/include/common.h
index 4d2a56d..bed4316 100644
--- a/include/common.h
+++ b/include/common.h
@@ -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)
diff --git a/include/configs/P2041RDB.h b/include/configs/P2041RDB.h
index 905bacf..862614b 100644
--- a/include/configs/P2041RDB.h
+++ b/include/configs/P2041RDB.h
@@ -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
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 2f06ca2..e8e5275 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -100,6 +100,7 @@
"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} " \
@@ -327,6 +328,11 @@
"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.
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index 7b120de..51e0e80 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -48,4 +48,23 @@
#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 */
diff --git a/include/configs/eXalion.h b/include/configs/eXalion.h
index c2d04a2..7321b60 100644
--- a/include/configs/eXalion.h
+++ b/include/configs/eXalion.h
@@ -119,7 +119,7 @@
#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 */
diff --git a/include/configs/sacsng.h b/include/configs/sacsng.h
index d63d0c4..0feef1e 100644
--- a/include/configs/sacsng.h
+++ b/include/configs/sacsng.h
@@ -305,7 +305,7 @@
#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" \
diff --git a/include/configs/sama5d3xek.h b/include/configs/sama5d3xek.h
index 76fa500..79c0068 100644
--- a/include/configs/sama5d3xek.h
+++ b/include/configs/sama5d3xek.h
@@ -162,6 +162,14 @@
#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
diff --git a/include/configs/top9000.h b/include/configs/top9000.h
index 65dabde..a6d6928 100644
--- a/include/configs/top9000.h
+++ b/include/configs/top9000.h
@@ -120,7 +120,6 @@
#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
diff --git a/include/dfu.h b/include/dfu.h
index 47b9055..b2ecf1b 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -14,11 +14,13 @@
#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_ */
diff --git a/include/fs.h b/include/fs.h
index c837bae..7d9403e 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -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 */
diff --git a/include/i2s.h b/include/i2s.h
index aee52e7..8dd2cc3 100644
--- a/include/i2s.h
+++ b/include/i2s.h
@@ -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 */
};
/*
diff --git a/include/libfdt.h b/include/libfdt.h
index 765d84f..9eefaaf 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -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.
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 3858f8f..111372c 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -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
index 0000000..be29ef0
--- /dev/null
+++ b/include/linux/usb/atmel_usba_udc.h
@@ -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 */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 220d068..a8a5763 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -18,6 +18,7 @@
#ifndef __LINUX_USB_GADGET_H
#define __LINUX_USB_GADGET_H
+#include <errno.h>
#include <linux/list.h>
struct usb_ep;
diff --git a/include/miiphy.h b/include/miiphy.h
index 657b496..088797e 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -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.
*/
diff --git a/include/mmc.h b/include/mmc.h
index 228d771..214b9ed 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -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);
diff --git a/include/sdhci.h b/include/sdhci.h
index b18b873..74d06ae 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -192,6 +192,8 @@
#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.
*/
@@ -210,6 +212,7 @@
#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;
diff --git a/include/spi.h b/include/spi.h
index c0dab57..5164d43 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -25,29 +25,33 @@
#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.
*
diff --git a/include/spi_flash.h b/include/spi_flash.h
index bfc59aa..1ff5af4 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -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_
@@ -17,75 +19,52 @@
#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);
diff --git a/include/usb_mass_storage.h b/include/usb_mass_storage.h
index 35cdcc3..e08deb4 100644
--- a/include/usb_mass_storage.h
+++ b/include/usb_mass_storage.h
@@ -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__ */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 644330a..c5a2b08 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -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
diff --git a/post/board/lwmon5/sysmon.c b/post/board/lwmon5/sysmon.c
index da37d66..cca1a26 100644
--- a/post/board/lwmon5/sysmon.c
+++ b/post/board/lwmon5/sysmon.c
@@ -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
*/
diff --git a/tools/buildman/README b/tools/buildman/README
index 734ada6..f63f278 100644
--- a/tools/buildman/README
+++ b/tools/buildman/README
@@ -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
=============
diff --git a/tools/buildman/board.py b/tools/buildman/board.py
index a388896..1d3db20 100644
--- a/tools/buildman/board.py
+++ b/tools/buildman/board.py
@@ -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)
diff --git a/tools/buildman/bsettings.py b/tools/buildman/bsettings.py
index c801130..9164798 100644
--- a/tools/buildman/bsettings.py
+++ b/tools/buildman/bsettings.py
@@ -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
diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py
index 29da67a..4a2d753 100644
--- a/tools/buildman/builder.py
+++ b/tools/buildman/builder.py
@@ -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:
diff --git a/tools/buildman/buildman.py b/tools/buildman/buildman.py
index 6fba2f2..43895b8 100755
--- a/tools/buildman/buildman.py
+++ b/tools/buildman/buildman.py
@@ -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)
diff --git a/tools/buildman/test.py b/tools/buildman/test.py
index bcdedfb..068784a 100644
--- a/tools/buildman/test.py
+++ b/tools/buildman/test.py
@@ -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:
diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py
index dfa1d00..a292338 100644
--- a/tools/buildman/toolchain.py
+++ b/tools/buildman/toolchain.py
@@ -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
diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl
index 896e2bc..88c5bc7 100755
--- a/tools/checkpatch.pl
+++ b/tools/checkpatch.pl
@@ -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
}
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 47beaaf..0400a60 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -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)