Merge tag 'dm-pull-5dec18' of git://git.denx.de/u-boot-dm
authorTom Rini <trini@konsulko.com>
Thu, 6 Dec 2018 01:32:25 +0000 (20:32 -0500)
committerTom Rini <trini@konsulko.com>
Thu, 6 Dec 2018 01:32:25 +0000 (20:32 -0500)
Minor sandbox enhancements  / fixes
tpm improvements to clear up v1/v2 support
buildman toolchain fixes
New serial options to set/get config

75 files changed:
README
arch/powerpc/include/asm/config.h
arch/riscv/Kconfig
arch/riscv/cpu/start.S
arch/riscv/include/asm/encoding.h
arch/riscv/lib/interrupts.c
board/AndesTech/ax25-ae350/ax25-ae350.c
board/emulation/qemu-riscv/Kconfig
board/emulation/qemu-riscv/MAINTAINERS
board/freescale/mpc8349emds/mpc8349emds.c
board/ids/ids8313/ids8313.c
cmd/Kconfig
cmd/Makefile
cmd/bmp.c
cmd/cls.c [new file with mode: 0644]
cmd/eeprom.c
cmd/ubi.c
common/board_f.c
common/board_r.c
common/lcd.c
configs/qemu-riscv32_smode_defconfig [new file with mode: 0644]
configs/qemu-riscv64_smode_defconfig [new file with mode: 0644]
doc/driver-model/spi-howto.txt
drivers/mtd/mtd_uboot.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/raw/pxa3xx_nand.c
drivers/mtd/spi/sf_mtd.c
drivers/mtd/spi/sf_probe.c
drivers/net/e1000_spi.c
drivers/pci/pci_rom.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/atmel_spi.c
drivers/spi/davinci_spi.c
drivers/spi/fsl_dspi.c
drivers/spi/fsl_espi.c
drivers/spi/lpc32xx_ssp.c
drivers/spi/meson_spifc.c [new file with mode: 0644]
drivers/spi/mtk_qspi.c [new file with mode: 0644]
drivers/spi/mxc_spi.c
drivers/spi/mxs_spi.c
drivers/spi/omap3_spi.c
drivers/spi/pl022_spi.c
drivers/spi/sh_qspi.c
drivers/spi/sh_spi.c
drivers/spi/soft_spi_legacy.c
drivers/video/video-uclass.c
drivers/video/video_bmp.c
examples/standalone/atmel_df_pow2.c
include/_exports.h
include/common.h
include/configs/M52277EVB.h
include/configs/M54418TWR.h
include/configs/M54451EVB.h
include/configs/M54455EVB.h
include/configs/MPC8536DS.h
include/configs/P1022DS.h
include/configs/UCP1020.h
include/configs/controlcenterd.h
include/configs/ids8313.h
include/configs/mx31pdk.h
include/configs/mxs.h
include/configs/p1_p2_rdb_pc.h
include/configs/p1_twr.h
include/configs/stmark2.h
include/configs/ts4800.h
include/dm/platform_data/pl022_spi.h [deleted file]
include/dm/platform_data/spi_pl022.h [new file with mode: 0644]
include/linux/mtd/mtd.h
include/regmap.h
include/spi.h
include/video.h
scripts/config_whitelist.txt
test/dm/regmap.c

diff --git a/README b/README
index a46c7c63a4fed72b16cfbaeb2620e9c1e196b396..17d56b80349a7a97e847e30ab197e768e502b268 100644 (file)
--- a/README
+++ b/README
@@ -1932,14 +1932,6 @@ The following options need to be configured:
                SPI configuration items (port pins to use, etc). For
                an example, see include/configs/sacsng.h.
 
-               CONFIG_HARD_SPI
-
-               Enables a hardware SPI driver for general-purpose reads
-               and writes.  As with CONFIG_SOFT_SPI, the board configuration
-               must define a list of chip-select function pointers.
-               Currently supported on some MPC8xxx processors.  For an
-               example, see include/configs/mpc8349emds.h.
-
                CONFIG_SYS_SPI_MXC_WAIT
                Timeout for waiting until spi transfer completed.
                default: (CONFIG_SYS_HZ/100)     /* 10 ms */
index 849a69acedcdc02d301d0aa2487cb6878a1865f5..c9c99646309e6bfba09b0d6d823de37c0d3c51b7 100644 (file)
   #define HWCONFIG_BUFFER_SIZE 256
 #endif
 
-/* CONFIG_HARD_SPI triggers SPI bus initialization in PowerPC */
-#if defined(CONFIG_MPC8XXX_SPI) || defined(CONFIG_FSL_ESPI)
-# ifndef CONFIG_HARD_SPI
-#  define CONFIG_HARD_SPI
-# endif
-#endif
-
 #define CONFIG_LMB
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
 
index 3e0af55e7152c7b334a7b045ff7a8bffb4e39d52..732a357a99b93682eb71fbbada1e31dff8ba7dda 100644 (file)
@@ -55,6 +55,11 @@ config RISCV_ISA_C
 config RISCV_ISA_A
        def_bool y
 
+config RISCV_SMODE
+       bool "Run in S-Mode"
+       help
+         Enable this option to build U-Boot for RISC-V S-Mode
+
 config 32BIT
        bool
 
index 15e1b8199a3bfef01f0cdab7058ac101e2ec9d61..64246a4e093eb65722f98b8ba783bd9a3a73ccd0 100644 (file)
@@ -38,13 +38,11 @@ _start:
        mv      s0, a0
        mv      s1, a1
 
-       li      t0, CONFIG_SYS_SDRAM_BASE
-       SREG    a2, 0(t0)
        la      t0, trap_entry
-       csrw    mtvec, t0
+       csrw    MODE_PREFIX(tvec), t0
 
        /* mask all interrupts */
-       csrw    mie, zero
+       csrw    MODE_PREFIX(ie), zero
 
        /* Enable cache */
        jal     icache_enable
@@ -166,7 +164,7 @@ fix_rela_dyn:
 */
        la      t0, trap_entry
        add     t0, t0, t6
-       csrw    mtvec, t0
+       csrw    MODE_PREFIX(tvec), t0
 
 clear_bss:
        la      t0, __bss_start         /* t0 <- rel __bss_start in FLASH */
@@ -238,17 +236,24 @@ trap_entry:
        SREG    x29, 29*REGBYTES(sp)
        SREG    x30, 30*REGBYTES(sp)
        SREG    x31, 31*REGBYTES(sp)
-       csrr    a0, mcause
-       csrr    a1, mepc
+       csrr    a0, MODE_PREFIX(cause)
+       csrr    a1, MODE_PREFIX(epc)
        mv      a2, sp
        jal     handle_trap
-       csrw    mepc, a0
+       csrw    MODE_PREFIX(epc), a0
 
+#ifdef CONFIG_RISCV_SMODE
+/*
+ * Remain in S-mode after sret
+ */
+       li      t0, SSTATUS_SPP
+#else
 /*
  * Remain in M-mode after mret
  */
        li      t0, MSTATUS_MPP
-       csrs    mstatus, t0
+#endif
+       csrs    MODE_PREFIX(status), t0
        LREG    x1, 1*REGBYTES(sp)
        LREG    x2, 2*REGBYTES(sp)
        LREG    x3, 3*REGBYTES(sp)
@@ -281,4 +286,4 @@ trap_entry:
        LREG    x30, 30*REGBYTES(sp)
        LREG    x31, 31*REGBYTES(sp)
        addi    sp, sp, 32*REGBYTES
-       mret
+       MODE_PREFIX(ret)
index 9ea50ce64079cdd14e7585f42872e4bafb3bb4f5..97cf906aa63b9ce5e4384a9b4b3e581d6d08d408 100644 (file)
@@ -7,6 +7,12 @@
 #ifndef RISCV_CSR_ENCODING_H
 #define RISCV_CSR_ENCODING_H
 
+#ifdef CONFIG_RISCV_SMODE
+#define MODE_PREFIX(__suffix)  s##__suffix
+#else
+#define MODE_PREFIX(__suffix)  m##__suffix
+#endif
+
 #define MSTATUS_UIE    0x00000001
 #define MSTATUS_SIE    0x00000002
 #define MSTATUS_HIE    0x00000004
index 903a1c4cd55766f7383b6c3eb93fff67c72ef652..3aff00697732fe5a1950d53d9a9c42f3be4ae722 100644 (file)
@@ -34,17 +34,30 @@ int disable_interrupts(void)
        return 0;
 }
 
-ulong handle_trap(ulong mcause, ulong epc, struct pt_regs *regs)
+ulong handle_trap(ulong cause, ulong epc, struct pt_regs *regs)
 {
-       ulong is_int;
+       ulong is_irq, irq;
 
-       is_int = (mcause & MCAUSE_INT);
-       if ((is_int) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_EXT))
-               external_interrupt(0);  /* handle_m_ext_interrupt */
-       else if ((is_int) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_TIMER))
-               timer_interrupt(0);     /* handle_m_timer_interrupt */
-       else
-               _exit_trap(mcause, epc, regs);
+       is_irq = (cause & MCAUSE_INT);
+       irq = (cause & ~MCAUSE_INT);
+
+       if (is_irq) {
+               switch (irq) {
+               case IRQ_M_EXT:
+               case IRQ_S_EXT:
+                       external_interrupt(0);  /* handle external interrupt */
+                       break;
+               case IRQ_M_TIMER:
+               case IRQ_S_TIMER:
+                       timer_interrupt(0);     /* handle timer interrupt */
+                       break;
+               default:
+                       _exit_trap(cause, epc, regs);
+                       break;
+               };
+       } else {
+               _exit_trap(cause, epc, regs);
+       }
 
        return epc;
 }
index 5f4ca0f5a7433372ed14b1afd68d6259d9039cf4..d343453f22d01a211a03f74d1f47a925881e1fd8 100644 (file)
@@ -14,6 +14,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+extern phys_addr_t prior_stage_fdt_address;
 /*
  * Miscellaneous platform dependent initializations
  */
@@ -66,7 +67,7 @@ ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
 
 void *board_fdt_blob_setup(void)
 {
-       void **ptr = (void *)CONFIG_SYS_SDRAM_BASE;
+       void **ptr = (void *)&prior_stage_fdt_address;
        if (fdt_magic(*ptr) == FDT_MAGIC)
                        return (void *)*ptr;
 
index 33ca253432a74328e5997c6f11843d30fc90afbf..56bb5337d4c8130bd2d22951776404791d467d3b 100644 (file)
@@ -13,7 +13,8 @@ config SYS_CONFIG_NAME
        default "qemu-riscv"
 
 config SYS_TEXT_BASE
-       default 0x80000000
+       default 0x80000000 if !RISCV_SMODE
+       default 0x80200000 if RISCV_SMODE
 
 config BOARD_SPECIFIC_OPTIONS # dummy
        def_bool y
index 3c6eb4f844aef9eee01b74c242b5456414af0fd8..c701c83d77ac9b0218d1d9fc237a8dddd8175f0f 100644 (file)
@@ -4,4 +4,6 @@ S:      Maintained
 F:     board/emulation/qemu-riscv/
 F:     include/configs/qemu-riscv.h
 F:     configs/qemu-riscv32_defconfig
+F:     configs/qemu-riscv32_smode_defconfig
 F:     configs/qemu-riscv64_defconfig
+F:     configs/qemu-riscv64_smode_defconfig
index 4ec0af4d1c5618ada62056792d246219fe591ac4..d40ed3742e02f251c24d18dec93b802d16f072d9 100644 (file)
@@ -273,7 +273,7 @@ void spi_cs_deactivate(struct spi_slave *slave)
 
        iopd->dat |=  SPI_CS_MASK;
 }
-#endif /* CONFIG_HARD_SPI */
+#endif
 
 #if defined(CONFIG_OF_BOARD_SETUP)
 int ft_board_setup(void *blob, bd_t *bd)
index a411d4e7f6fd2fb65b7d72366851ca5265bec33e..d547af4b05acfc28438aacb8ff82f33cd79e99f0 100644 (file)
@@ -208,4 +208,4 @@ void spi_cs_deactivate(struct spi_slave *slave)
        /* deactivate the spi_cs */
        setbits_be32(&iopd->dat, IDSCPLD_SPI_CS_MASK);
 }
-#endif /* CONFIG_HARD_SPI */
+#endif
index e2973b3c514e48707936260f2bbe506568d042e0..b1cd1c969072a0c64f4d654c980d7dfa56d69cc7 100644 (file)
@@ -1380,6 +1380,14 @@ config CMD_CONITRACE
          Enable the 'conitrace' command which displays the codes received
          from the console input as hexadecimal numbers.
 
+config CMD_CLS
+       bool "Enable clear screen command 'cls'"
+       depends on CFB_CONSOLE || DM_VIDEO || LCD || VIDEO
+       default y if LCD
+       help
+         Enable the 'cls' command which clears the screen contents
+         on video frame buffer.
+
 config CMD_DISPLAY
        bool "Enable the 'display' command, for character displays"
        help
index 5ec2f9e8ebfdf42533b9079470bd73b47d0f0f4e..49986437ba5803a819a1d7f2415f7d30c36337e2 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_CMD_BTRFS) += btrfs.o
 obj-$(CONFIG_CMD_CACHE) += cache.o
 obj-$(CONFIG_CMD_CBFS) += cbfs.o
 obj-$(CONFIG_CMD_CLK) += clk.o
+obj-$(CONFIG_CMD_CLS) += cls.o
 obj-$(CONFIG_CMD_CONFIG) += config.o
 obj-$(CONFIG_CMD_CONITRACE) += conitrace.o
 obj-$(CONFIG_CMD_CONSOLE) += console.o
index 02bdf48b4d422ced97dea7587f07d74c0aee6d6e..b8af784590dd58adb463b143b88acff98b1f6820 100644 (file)
--- a/cmd/bmp.c
+++ b/cmd/bmp.c
@@ -124,8 +124,14 @@ static int do_bmp_display(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar
                break;
        case 4:
                addr = simple_strtoul(argv[1], NULL, 16);
-               x = simple_strtoul(argv[2], NULL, 10);
-               y = simple_strtoul(argv[3], NULL, 10);
+               if (!strcmp(argv[2], "m"))
+                       x = BMP_ALIGN_CENTER;
+               else
+                       x = simple_strtoul(argv[2], NULL, 10);
+               if (!strcmp(argv[3], "m"))
+                       y = BMP_ALIGN_CENTER;
+               else
+                       y = simple_strtoul(argv[3], NULL, 10);
                break;
        default:
                return CMD_RET_USAGE;
@@ -249,9 +255,11 @@ int bmp_display(ulong addr, int x, int y)
        if (!ret) {
                bool align = false;
 
-# ifdef CONFIG_SPLASH_SCREEN_ALIGN
-               align = true;
-# endif /* CONFIG_SPLASH_SCREEN_ALIGN */
+               if (CONFIG_IS_ENABLED(SPLASH_SCREEN_ALIGN) ||
+                   x == BMP_ALIGN_CENTER ||
+                   y == BMP_ALIGN_CENTER)
+                       align = true;
+
                ret = video_bmp_display(dev, addr, x, y, align);
        }
 #elif defined(CONFIG_LCD)
diff --git a/cmd/cls.c b/cmd/cls.c
new file mode 100644 (file)
index 0000000..f1ce6e8
--- /dev/null
+++ b/cmd/cls.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
+ *
+ * cls - clear screen command
+ */
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <lcd.h>
+#include <video.h>
+
+static int do_video_clear(cmd_tbl_t *cmdtp, int flag, int argc,
+                         char *const argv[])
+{
+#if defined(CONFIG_DM_VIDEO)
+       struct udevice *dev;
+
+       if (uclass_first_device_err(UCLASS_VIDEO, &dev))
+               return CMD_RET_FAILURE;
+
+       if (video_clear(dev))
+               return CMD_RET_FAILURE;
+#elif defined(CONFIG_CFB_CONSOLE)
+       video_clear();
+#elif defined(CONFIG_LCD)
+       lcd_clear();
+#else
+       return CMD_RET_FAILURE;
+#endif
+       return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(cls,        1, 1, do_video_clear, "clear screen", "");
index e88cb131a16d0bf08017ea1d3a36df724f696541..6c29b33ba34c9fe1e52603d60765aed0612a5379 100644 (file)
@@ -66,11 +66,6 @@ __weak int eeprom_write_enable(unsigned dev_addr, int state)
 
 void eeprom_init(int bus)
 {
-       /* SPI EEPROM */
-#if defined(CONFIG_MPC8XX_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
-       spi_init_f();
-#endif
-
        /* I2C EEPROM */
 #if defined(CONFIG_SYS_I2C)
        if (bus >= 0)
@@ -129,14 +124,6 @@ static int eeprom_rw_block(unsigned offset, uchar *addr, unsigned alen,
 {
        int ret = 0;
 
-       /* SPI */
-#if defined(CONFIG_MPC8XX_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
-       if (read)
-               spi_read(addr, alen, buffer, len);
-       else
-               spi_write(addr, alen, buffer, len);
-#else  /* I2C */
-
 #if defined(CONFIG_DM_I2C) && defined(CONFIG_SYS_I2C_EEPROM_BUS)
        struct udevice *dev;
 
@@ -162,7 +149,6 @@ static int eeprom_rw_block(unsigned offset, uchar *addr, unsigned alen,
                ret = i2c_read(addr[0], offset, alen - 1, buffer, len);
        else
                ret = i2c_write(addr[0], offset, alen - 1, buffer, len);
-#endif
 #endif /* CONFIG_DM_I2C && CONFIG_SYS_I2C_EEPROM_BUS */
        if (ret)
                ret = CMD_RET_FAILURE;
index 2b74a9814463f084037fa42c83ba6a6cc2f4b327..a12ac703ebe54ffe840d0452589f16ee2fe1ff20 100644 (file)
--- a/cmd/ubi.c
+++ b/cmd/ubi.c
@@ -101,7 +101,6 @@ static int ubi_check(char *name)
        return 1;
 }
 
-
 static int verify_mkvol_req(const struct ubi_device *ubi,
                            const struct ubi_mkvol_req *req)
 {
@@ -415,7 +414,7 @@ static int ubi_dev_scan(struct mtd_info *info, const char *vid_header_offset)
        return 0;
 }
 
-int ubi_detach(void)
+static int ubi_detach(void)
 {
 #ifdef CONFIG_CMD_UBIFS
        /*
@@ -473,7 +472,6 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        if (argc < 2)
                return CMD_RET_USAGE;
 
-
        if (strcmp(argv[1], "detach") == 0) {
                if (argc < 2)
                        return CMD_RET_USAGE;
@@ -481,7 +479,6 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                return ubi_detach();
        }
 
-
        if (strcmp(argv[1], "part") == 0) {
                const char *vid_header_offset = NULL;
 
index 835b7247c58d634bf7655ca87d96e85acd788ae4..149a7229e8fa982d53ce003c67ddb2db7d45e2e1 100644 (file)
@@ -24,7 +24,6 @@
 #include <os.h>
 #include <post.h>
 #include <relocate.h>
-#include <spi.h>
 #ifdef CONFIG_SPL
 #include <spl.h>
 #endif
@@ -262,16 +261,6 @@ __weak int init_func_vid(void)
 }
 #endif
 
-#if defined(CONFIG_HARD_SPI)
-static int init_func_spi(void)
-{
-       puts("SPI:   ");
-       spi_init();
-       puts("ready\n");
-       return 0;
-}
-#endif
-
 static int setup_mon_len(void)
 {
 #if defined(__ARM__) || defined(__MICROBLAZE__)
@@ -912,9 +901,6 @@ static const init_fnc_t init_sequence_f[] = {
 #endif
 #if defined(CONFIG_VID) && !defined(CONFIG_SPL)
        init_func_vid,
-#endif
-#if defined(CONFIG_HARD_SPI)
-       init_func_spi,
 #endif
        announce_dram_init,
        dram_init,              /* configure available RAM banks */
index 21d3b3c64c648806e13ff7c4937fbfb7714f48b2..5f3d27aa9f391b0b93b10795d2c20324112091ef 100644 (file)
@@ -36,7 +36,6 @@
 #include <onenand_uboot.h>
 #include <scsi.h>
 #include <serial.h>
-#include <spi.h>
 #include <stdio_dev.h>
 #include <timer.h>
 #include <trace.h>
@@ -379,20 +378,6 @@ static int initr_flash(void)
 }
 #endif
 
-#if defined(CONFIG_PPC) && !defined(CONFIG_DM_SPI)
-static int initr_spi(void)
-{
-       /* MPC8xx does this here */
-#ifdef CONFIG_MPC8XX_SPI
-#if !defined(CONFIG_ENV_IS_IN_EEPROM)
-       spi_init_f();
-#endif
-       spi_init_r();
-#endif
-       return 0;
-}
-#endif
-
 #ifdef CONFIG_CMD_NAND
 /* go init the NAND */
 static int initr_nand(void)
@@ -744,9 +729,6 @@ static init_fnc_t init_sequence_r[] = {
        /* initialize higher level parts of CPU like time base and timers */
        cpu_init_r,
 #endif
-#if defined(CONFIG_PPC) && !defined(CONFIG_DM_SPI)
-       initr_spi,
-#endif
 #ifdef CONFIG_CMD_NAND
        initr_nand,
 #endif
index 2e2bef3848f3702d6ba09eeb65f1a6cd24f5906a..cd630405d44a3345438e88787b602d7a7e822b26 100644 (file)
@@ -242,14 +242,6 @@ void lcd_clear(void)
        lcd_sync();
 }
 
-static int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc,
-                       char *const argv[])
-{
-       lcd_clear();
-       return 0;
-}
-U_BOOT_CMD(cls,        1, 1, do_lcd_clear, "clear screen", "");
-
 static int lcd_init(void *lcdbase)
 {
        debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
@@ -389,7 +381,6 @@ static inline void lcd_logo_plot(int x, int y) {}
 
 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
-#define BMP_ALIGN_CENTER       0x7FFF
 
 static void splash_align_axis(int *axis, unsigned long panel_size,
                                        unsigned long picture_size)
diff --git a/configs/qemu-riscv32_smode_defconfig b/configs/qemu-riscv32_smode_defconfig
new file mode 100644 (file)
index 0000000..0a84ec1
--- /dev/null
@@ -0,0 +1,10 @@
+CONFIG_RISCV=y
+CONFIG_TARGET_QEMU_VIRT=y
+CONFIG_RISCV_SMODE=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+# CONFIG_CMD_MII is not set
+CONFIG_OF_PRIOR_STAGE=y
diff --git a/configs/qemu-riscv64_smode_defconfig b/configs/qemu-riscv64_smode_defconfig
new file mode 100644 (file)
index 0000000..b012443
--- /dev/null
@@ -0,0 +1,11 @@
+CONFIG_RISCV=y
+CONFIG_TARGET_QEMU_VIRT=y
+CONFIG_ARCH_RV64I=y
+CONFIG_RISCV_SMODE=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+# CONFIG_CMD_MII is not set
+CONFIG_OF_PRIOR_STAGE=y
index 1955ffe284eafd4aec984ad1aedac49ff11e6d29..38c26f642bc9929283dea057cdef15937e40ce02 100644 (file)
@@ -163,11 +163,6 @@ At this point you should be able to build U-Boot for your board with the
 empty SPI driver. You still have empty methods in your driver, but we will
 write these one by one.
 
-If you have spi_init() functions or the like that are called from your
-board then the build will fail. Remove these calls and make a note of the
-init that needs to be done.
-
-
 7. Set up your platform data structure
 
 This will hold the information your driver to operate, like its hardware
index 5ca560c968794852384b5e8d4e5e024c5df20e01..d638f700d041e32757f1e3dea3a005085cfd2a12 100644 (file)
 
 #define MTD_NAME_MAX_LEN 20
 
+void board_mtdparts_default(const char **mtdids, const char **mtdparts);
+
+static const char *get_mtdids(void)
+{
+       __maybe_unused const char *mtdparts = NULL;
+       const char *mtdids = env_get("mtdids");
+
+       if (mtdids)
+               return mtdids;
+
+#if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
+       board_mtdparts_default(&mtdids, &mtdparts);
+#elif defined(MTDIDS_DEFAULT)
+       mtdids = MTDIDS_DEFAULT;
+#elif defined(CONFIG_MTDIDS_DEFAULT)
+       mtdids = CONFIG_MTDIDS_DEFAULT;
+#endif
+
+       if (mtdids)
+               env_set("mtdids", mtdids);
+
+       return mtdids;
+}
 
 /**
  * mtd_search_alternate_name - Search an alternate name for @mtdname thanks to
@@ -34,7 +57,7 @@ int mtd_search_alternate_name(const char *mtdname, char *altname,
        const char *mtdids, *equal, *comma, *dev_id, *mtd_id;
        int dev_id_len, mtd_id_len;
 
-       mtdids = env_get("mtdids");
+       mtdids = get_mtdids();
        if (!mtdids)
                return -EINVAL;
 
@@ -92,30 +115,6 @@ static void mtd_probe_uclass_mtd_devs(void) { }
 #endif
 
 #if defined(CONFIG_MTD_PARTITIONS)
-extern void board_mtdparts_default(const char **mtdids,
-                                  const char **mtdparts);
-
-static const char *get_mtdids(void)
-{
-       __maybe_unused const char *mtdparts = NULL;
-       const char *mtdids = env_get("mtdids");
-
-       if (mtdids)
-               return mtdids;
-
-#if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
-       board_mtdparts_default(&mtdids, &mtdparts);
-#elif defined(MTDIDS_DEFAULT)
-       mtdids = MTDIDS_DEFAULT;
-#elif defined(CONFIG_MTDIDS_DEFAULT)
-       mtdids = CONFIG_MTDIDS_DEFAULT;
-#endif
-
-       if (mtdids)
-               env_set("mtdids", mtdids);
-
-       return mtdids;
-}
 
 #define MTDPARTS_MAXLEN         512
 
@@ -150,20 +149,74 @@ static const char *get_mtdparts(void)
        return mtdparts;
 }
 
+static int mtd_del_parts(struct mtd_info *mtd, bool quiet)
+{
+       int ret;
+
+       if (!mtd_has_partitions(mtd))
+               return 0;
+
+       /* do not delete partitions if they are in use. */
+       if (mtd_partitions_used(mtd)) {
+               if (!quiet)
+                       printf("\"%s\" partitions still in use, can't delete them\n",
+                              mtd->name);
+               return -EACCES;
+       }
+
+       ret = del_mtd_partitions(mtd);
+       if (ret)
+               return ret;
+
+       return 1;
+}
+
+static bool mtd_del_all_parts_failed;
+
+static void mtd_del_all_parts(void)
+{
+       struct mtd_info *mtd;
+       int ret = 0;
+
+       mtd_del_all_parts_failed = false;
+
+       /*
+        * It is not safe to remove entries from the mtd_for_each_device loop
+        * as it uses idr indexes and the partitions removal is done in bulk
+        * (all partitions of one device at the same time), so break and
+        * iterate from start each time a new partition is found and deleted.
+        */
+       do {
+               mtd_for_each_device(mtd) {
+                       ret = mtd_del_parts(mtd, false);
+                       if (ret > 0)
+                               break;
+                       else if (ret < 0)
+                               mtd_del_all_parts_failed = true;
+               }
+       } while (ret > 0);
+}
+
 int mtd_probe_devices(void)
 {
        static char *old_mtdparts;
        static char *old_mtdids;
        const char *mtdparts = get_mtdparts();
        const char *mtdids = get_mtdids();
-       bool remaining_partitions = true;
+       const char *mtdparts_next = mtdparts;
        struct mtd_info *mtd;
 
        mtd_probe_uclass_mtd_devs();
 
-       /* Check if mtdparts/mtdids changed since last call, otherwise: exit */
+       /*
+        * Check if mtdparts/mtdids changed, if the MTD dev list was updated
+        * or if our previous attempt to delete existing partititions failed.
+        * In any of these cases we want to update the partitions, otherwise,
+        * everything is up-to-date and we can return 0 directly.
+        */
        if ((!mtdparts && !old_mtdparts && !mtdids && !old_mtdids) ||
            (mtdparts && old_mtdparts && mtdids && old_mtdids &&
+            !mtd_dev_list_updated() && !mtd_del_all_parts_failed &&
             !strcmp(mtdparts, old_mtdparts) &&
             !strcmp(mtdids, old_mtdids)))
                return 0;
@@ -174,55 +227,55 @@ int mtd_probe_devices(void)
        old_mtdparts = strdup(mtdparts);
        old_mtdids = strdup(mtdids);
 
-       /* If at least one partition is still in use, do not delete anything */
-       mtd_for_each_device(mtd) {
-               if (mtd->usecount) {
-                       printf("Partition \"%s\" already in use, aborting\n",
-                              mtd->name);
-                       return -EACCES;
-               }
-       }
+       /*
+        * Remove all old parts. Note that partition removal can fail in case
+        * one of the partition is still being used by an MTD user, so this
+        * does not guarantee that all old partitions are gone.
+        */
+       mtd_del_all_parts();
 
        /*
-        * Everything looks clear, remove all partitions. It is not safe to
-        * remove entries from the mtd_for_each_device loop as it uses idr
-        * indexes and the partitions removal is done in bulk (all partitions of
-        * one device at the same time), so break and iterate from start each
-        * time a new partition is found and deleted.
+        * Call mtd_dev_list_updated() to clear updates generated by our own
+        * parts removal loop.
         */
-       while (remaining_partitions) {
-               remaining_partitions = false;
-               mtd_for_each_device(mtd) {
-                       if (!mtd_is_partition(mtd) && mtd_has_partitions(mtd)) {
-                               del_mtd_partitions(mtd);
-                               remaining_partitions = true;
-                               break;
-                       }
-               }
-       }
+       mtd_dev_list_updated();
 
        /* If either mtdparts or mtdids is empty, then exit */
        if (!mtdparts || !mtdids)
                return 0;
 
        /* Start the parsing by ignoring the extra 'mtdparts=' prefix, if any */
-       if (strstr(mtdparts, "mtdparts="))
+       if (!strncmp(mtdparts, "mtdparts=", sizeof("mtdparts=") - 1))
                mtdparts += 9;
 
        /* For each MTD device in mtdparts */
-       while (mtdparts[0] != '\0') {
+       for (; mtdparts[0] != '\0'; mtdparts = mtdparts_next) {
                char mtd_name[MTD_NAME_MAX_LEN], *colon;
                struct mtd_partition *parts;
-               int mtd_name_len, nparts;
-               int ret;
+               unsigned int mtd_name_len;
+               int nparts, ret;
+
+               mtdparts_next = strchr(mtdparts, ';');
+               if (!mtdparts_next)
+                       mtdparts_next = mtdparts + strlen(mtdparts);
+               else
+                       mtdparts_next++;
 
                colon = strchr(mtdparts, ':');
+               if (colon > mtdparts_next)
+                       colon = NULL;
+
                if (!colon) {
                        printf("Wrong mtdparts: %s\n", mtdparts);
                        return -EINVAL;
                }
 
-               mtd_name_len = colon - mtdparts;
+               mtd_name_len = (unsigned int)(colon - mtdparts);
+               if (mtd_name_len + 1 > sizeof(mtd_name)) {
+                       printf("MTD name too long: %s\n", mtdparts);
+                       return -EINVAL;
+               }
+
                strncpy(mtd_name, mtdparts, mtd_name_len);
                mtd_name[mtd_name_len] = '\0';
                /* Move the pointer forward (including the ':') */
@@ -249,14 +302,22 @@ int mtd_probe_devices(void)
                        if (ret || IS_ERR_OR_NULL(mtd)) {
                                printf("Could not find a valid device for %s\n",
                                       mtd_name);
-                               mtdparts = strchr(mtdparts, ';');
-                               if (mtdparts)
-                                       mtdparts++;
-
+                               mtdparts = mtdparts_next;
                                continue;
                        }
                }
 
+               /*
+                * Call mtd_del_parts() again, even if it's already been called
+                * in mtd_del_all_parts(). We need to know if old partitions are
+                * still around (because they are still being used by someone),
+                * and if they are, we shouldn't create new partitions, so just
+                * skip this MTD device and try the next one.
+                */
+               ret = mtd_del_parts(mtd, true);
+               if (ret < 0)
+                       continue;
+
                /*
                 * Parse the MTD device partitions. It will update the mtdparts
                 * pointer, create an array of parts (that must be freed), and
@@ -281,6 +342,12 @@ int mtd_probe_devices(void)
                put_mtd_device(mtd);
        }
 
+       /*
+        * Call mtd_dev_list_updated() to clear updates generated by our own
+        * parts registration loop.
+        */
+       mtd_dev_list_updated();
+
        return 0;
 }
 #else
index fb6c779abbfe18b1c2f16375c1965bf228fb75ea..cb7ca38d0744d237c4eb5c760b9518abf8fc83e0 100644 (file)
@@ -87,14 +87,17 @@ struct idr_layer {
 
 struct idr {
        struct idr_layer id[MAX_IDR_ID];
+       bool updated;
 };
 
 #define DEFINE_IDR(name)       struct idr name;
 
 void idr_remove(struct idr *idp, int id)
 {
-       if (idp->id[id].used)
+       if (idp->id[id].used) {
                idp->id[id].used = 0;
+               idp->updated = true;
+       }
 
        return;
 }
@@ -134,6 +137,7 @@ int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask)
                if (idl->used == 0) {
                        idl->used = 1;
                        idl->ptr = ptr;
+                       idp->updated = true;
                        return i;
                }
                i++;
@@ -155,6 +159,16 @@ struct mtd_info *__mtd_next_device(int i)
 }
 EXPORT_SYMBOL_GPL(__mtd_next_device);
 
+bool mtd_dev_list_updated(void)
+{
+       if (mtd_idr.updated) {
+               mtd_idr.updated = false;
+               return true;
+       }
+
+       return false;
+}
+
 #ifndef __UBOOT__
 static LIST_HEAD(mtd_notifiers);
 
@@ -514,6 +528,13 @@ int del_mtd_device(struct mtd_info *mtd)
        struct mtd_notifier *not;
 #endif
 
+       ret = del_mtd_partitions(mtd);
+       if (ret) {
+               debug("Failed to delete MTD partitions attached to %s (err %d)\n",
+                     mtd->name, ret);
+               return ret;
+       }
+
        mutex_lock(&mtd_table_mutex);
 
        if (idr_find(&mtd_idr, mtd->index) != mtd) {
index 4d2ac8107f01c564cf9165454f1e6203b99b06a3..fd8d8e5ea7295ac44c2bb25677d2e3df06f6d1cc 100644 (file)
@@ -63,6 +63,18 @@ char *kstrdup(const char *s, gfp_t gfp)
 #define MTD_SIZE_REMAINING             (~0LLU)
 #define MTD_OFFSET_NOT_SPECIFIED       (~0LLU)
 
+bool mtd_partitions_used(struct mtd_info *master)
+{
+       struct mtd_info *slave;
+
+       list_for_each_entry(slave, &master->partitions, node) {
+               if (slave->usecount)
+                       return true;
+       }
+
+       return false;
+}
+
 /**
  * mtd_parse_partition - Parse @mtdparts partition definition, fill @partition
  *                       with it and update the @mtdparts string pointer.
index 4c783f1e1e4bc805954f078ce359f18084e0ab69..4d2712df4c7a483243943171277e1f80dda15698 100644 (file)
@@ -195,6 +195,7 @@ struct pxa3xx_nand_info {
 
        int                     cs;
        int                     use_ecc;        /* use HW ECC ? */
+       int                     force_raw;      /* prevent use_ecc to be set */
        int                     ecc_bch;        /* using BCH ECC? */
        int                     use_spare;      /* use spare ? */
        int                     need_wait;
@@ -326,14 +327,14 @@ static struct nand_ecclayout ecc_layout_2KB_bch4bit = {
 static struct nand_ecclayout ecc_layout_2KB_bch8bit = {
        .eccbytes = 64,
        .eccpos = {
-               64,  65,  66,  67,  68,  69,  70,  71,
-               72,  73,  74,  75,  76,  77,  78,  79,
-               80,  81,  82,  83,  84,  85,  86,  87,
-               88,  89,  90,  91,  92,  93,  94,  95,
-               96,  97,  98,  99,  100, 101, 102, 103,
-               104, 105, 106, 107, 108, 109, 110, 111,
-               112, 113, 114, 115, 116, 117, 118, 119,
-               120, 121, 122, 123, 124, 125, 126, 127},
+               32, 33, 34, 35, 36, 37, 38, 39,
+               40, 41, 42, 43, 44, 45, 46, 47,
+               48, 49, 50, 51, 52, 53, 54, 55,
+               56, 57, 58, 59, 60, 61, 62, 63,
+               64, 65, 66, 67, 68, 69, 70, 71,
+               72, 73, 74, 75, 76, 77, 78, 79,
+               80, 81, 82, 83, 84, 85, 86, 87,
+               88, 89, 90, 91, 92, 93, 94, 95},
        .oobfree = { {1, 4}, {6, 26} }
 };
 
@@ -579,7 +580,7 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
 
 static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
 {
-       if (info->ecc_bch) {
+       if (info->ecc_bch && !info->force_raw) {
                u32 ts;
 
                /*
@@ -612,12 +613,22 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
 
 static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
+       int data_len = info->step_chunk_size;
+
+       /*
+        * In raw mode, include the spare area and the ECC bytes that are not
+        * consumed by the controller in the data section. Do not reorganize
+        * here, do it in the ->read_page_raw() handler instead.
+        */
+       if (info->force_raw)
+               data_len += info->step_spare_size + info->ecc_size;
+
        switch (info->state) {
        case STATE_PIO_WRITING:
                if (info->step_chunk_size)
                        writesl(info->mmio_base + NDDB,
                                info->data_buff + info->data_buff_pos,
-                               DIV_ROUND_UP(info->step_chunk_size, 4));
+                               DIV_ROUND_UP(data_len, 4));
 
                if (info->step_spare_size)
                        writesl(info->mmio_base + NDDB,
@@ -628,7 +639,10 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
                if (info->step_chunk_size)
                        drain_fifo(info,
                                   info->data_buff + info->data_buff_pos,
-                                  DIV_ROUND_UP(info->step_chunk_size, 4));
+                                  DIV_ROUND_UP(data_len, 4));
+
+               if (info->force_raw)
+                       break;
 
                if (info->step_spare_size)
                        drain_fifo(info,
@@ -642,7 +656,7 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
        }
 
        /* Update buffer pointers for multi-page read/write */
-       info->data_buff_pos += info->step_chunk_size;
+       info->data_buff_pos += data_len;
        info->oob_buff_pos += info->step_spare_size;
 }
 
@@ -796,7 +810,8 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
        case NAND_CMD_READ0:
        case NAND_CMD_READOOB:
        case NAND_CMD_PAGEPROG:
-               info->use_ecc = 1;
+               if (!info->force_raw)
+                       info->use_ecc = 1;
                break;
        case NAND_CMD_PARAM:
                info->use_spare = 0;
@@ -866,7 +881,13 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
                 * which is either naked-read or last-read according to the
                 * state.
                 */
-               if (mtd->writesize == info->chunk_size) {
+               if (info->force_raw) {
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8) |
+                                      NDCB0_LEN_OVRD |
+                                      NDCB0_EXT_CMD_TYPE(ext_cmd_type);
+                       info->ndcb3 = info->step_chunk_size +
+                                     info->step_spare_size + info->ecc_size;
+               } else if (mtd->writesize == info->chunk_size) {
                        info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
                } else if (mtd->writesize > info->chunk_size) {
                        info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8)
@@ -1216,6 +1237,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 {
        struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
        struct pxa3xx_nand_info *info = host->info_data;
+       int bf;
 
        chip->read_buf(mtd, buf, mtd->writesize);
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1223,12 +1245,30 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
        if (info->retcode == ERR_CORERR && info->use_ecc) {
                mtd->ecc_stats.corrected += info->ecc_err_cnt;
 
-       } else if (info->retcode == ERR_UNCORERR) {
+       } else if (info->retcode == ERR_UNCORERR && info->ecc_bch) {
                /*
-                * for blank page (all 0xff), HW will calculate its ECC as
-                * 0, which is different from the ECC information within
-                * OOB, ignore such uncorrectable errors
+                * Empty pages will trigger uncorrectable errors. Re-read the
+                * entire page in raw mode and check for bits not being "1".
+                * If there are more than the supported strength, then it means
+                * this is an actual uncorrectable error.
                 */
+               chip->ecc.read_page_raw(mtd, chip, buf, oob_required, page);
+               bf = nand_check_erased_ecc_chunk(buf, mtd->writesize,
+                                                chip->oob_poi, mtd->oobsize,
+                                                NULL, 0, chip->ecc.strength);
+               if (bf < 0) {
+                       mtd->ecc_stats.failed++;
+               } else if (bf) {
+                       mtd->ecc_stats.corrected += bf;
+                       info->max_bitflips = max_t(unsigned int,
+                                                  info->max_bitflips, bf);
+                       info->retcode = ERR_CORERR;
+               } else {
+                       info->retcode = ERR_NONE;
+               }
+
+       } else if (info->retcode == ERR_UNCORERR && !info->ecc_bch) {
+               /* Raw read is not supported with Hamming ECC engine */
                if (is_buf_blank(buf, mtd->writesize))
                        info->retcode = ERR_NONE;
                else
@@ -1238,6 +1278,69 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
        return info->max_bitflips;
 }
 
+static int pxa3xx_nand_read_page_raw(struct mtd_info *mtd,
+                                    struct nand_chip *chip, uint8_t *buf,
+                                    int oob_required, int page)
+{
+       struct pxa3xx_nand_host *host = chip->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
+       int chunk, ecc_off_buf;
+
+       if (!info->ecc_bch)
+               return -ENOTSUPP;
+
+       /*
+        * Set the force_raw boolean, then re-call ->cmdfunc() that will run
+        * pxa3xx_nand_start(), which will actually disable the ECC engine.
+        */
+       info->force_raw = true;
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+
+       ecc_off_buf = (info->nfullchunks * info->spare_size) +
+                     info->last_spare_size;
+       for (chunk = 0; chunk < info->nfullchunks; chunk++) {
+               chip->read_buf(mtd,
+                              buf + (chunk * info->chunk_size),
+                              info->chunk_size);
+               chip->read_buf(mtd,
+                              chip->oob_poi +
+                              (chunk * (info->spare_size)),
+                              info->spare_size);
+               chip->read_buf(mtd,
+                              chip->oob_poi + ecc_off_buf +
+                              (chunk * (info->ecc_size)),
+                              info->ecc_size - 2);
+       }
+
+       if (info->ntotalchunks > info->nfullchunks) {
+               chip->read_buf(mtd,
+                              buf + (info->nfullchunks * info->chunk_size),
+                              info->last_chunk_size);
+               chip->read_buf(mtd,
+                              chip->oob_poi +
+                              (info->nfullchunks * (info->spare_size)),
+                              info->last_spare_size);
+               chip->read_buf(mtd,
+                              chip->oob_poi + ecc_off_buf +
+                              (info->nfullchunks * (info->ecc_size)),
+                              info->ecc_size - 2);
+       }
+
+       info->force_raw = false;
+
+       return 0;
+}
+
+static int pxa3xx_nand_read_oob_raw(struct mtd_info *mtd,
+                                   struct nand_chip *chip, int page)
+{
+       /* Invalidate page cache */
+       chip->pagebuf = -1;
+
+       return chip->ecc.read_page_raw(mtd, chip, chip->buffers->databuf, true,
+                                      page);
+}
+
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd_to_nand(mtd);
@@ -1488,7 +1591,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
                info->chunk_size = 1024;
                info->spare_size = 0;
                info->last_chunk_size = 1024;
-               info->last_spare_size = 64;
+               info->last_spare_size = 32;
                info->ecc_size = 32;
                ecc->mode = NAND_ECC_HW;
                ecc->size = info->chunk_size;
@@ -1669,6 +1772,8 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info)
 
                nand_set_controller_data(chip, host);
                chip->ecc.read_page     = pxa3xx_nand_read_page_hwecc;
+               chip->ecc.read_page_raw = pxa3xx_nand_read_page_raw;
+               chip->ecc.read_oob_raw  = pxa3xx_nand_read_oob_raw;
                chip->ecc.write_page    = pxa3xx_nand_write_page_hwecc;
                chip->controller        = &info->controller;
                chip->waitfunc          = pxa3xx_nand_waitfunc;
index 58d7e44399037e3433b703c2dda6c7354f3c8cb4..68c36002bee26fa475d023b9711bd699dfa2c916 100644 (file)
@@ -10,6 +10,7 @@
 #include <spi_flash.h>
 
 static struct mtd_info sf_mtd_info;
+static bool sf_mtd_registered;
 static char sf_mtd_name[8];
 
 static int spi_flash_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
@@ -17,6 +18,9 @@ static int spi_flash_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
        struct spi_flash *flash = mtd->priv;
        int err;
 
+       if (!flash)
+               return -ENODEV;
+
        instr->state = MTD_ERASING;
 
        err = spi_flash_erase(flash, instr->addr, instr->len);
@@ -38,6 +42,9 @@ static int spi_flash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_flash *flash = mtd->priv;
        int err;
 
+       if (!flash)
+               return -ENODEV;
+
        err = spi_flash_read(flash, from, len, buf);
        if (!err)
                *retlen = len;
@@ -51,6 +58,9 @@ static int spi_flash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
        struct spi_flash *flash = mtd->priv;
        int err;
 
+       if (!flash)
+               return -ENODEV;
+
        err = spi_flash_write(flash, to, len, buf);
        if (!err)
                *retlen = len;
@@ -73,6 +83,17 @@ static int spi_flash_mtd_number(void)
 
 int spi_flash_mtd_register(struct spi_flash *flash)
 {
+       int ret;
+
+       if (sf_mtd_registered) {
+               ret = del_mtd_device(&sf_mtd_info);
+               if (ret)
+                       return ret;
+
+               sf_mtd_registered = false;
+       }
+
+       sf_mtd_registered = false;
        memset(&sf_mtd_info, 0, sizeof(sf_mtd_info));
        sprintf(sf_mtd_name, "nor%d", spi_flash_mtd_number());
 
@@ -94,10 +115,33 @@ int spi_flash_mtd_register(struct spi_flash *flash)
        sf_mtd_info.numeraseregions = 0;
        sf_mtd_info.erasesize = flash->sector_size;
 
-       return add_mtd_device(&sf_mtd_info);
+       ret = add_mtd_device(&sf_mtd_info);
+       if (!ret)
+               sf_mtd_registered = true;
+
+       return ret;
 }
 
 void spi_flash_mtd_unregister(void)
 {
-       del_mtd_device(&sf_mtd_info);
+       int ret;
+
+       if (!sf_mtd_registered)
+               return;
+
+       ret = del_mtd_device(&sf_mtd_info);
+       if (!ret) {
+               sf_mtd_registered = false;
+               return;
+       }
+
+       /*
+        * Setting mtd->priv to NULL is the best we can do. Thanks to that,
+        * the MTD layer can still call mtd hooks without risking a
+        * use-after-free bug. Still, things should be fixed to prevent the
+        * spi_flash object from being destroyed when del_mtd_device() fails.
+        */
+       sf_mtd_info.priv = NULL;
+       printf("Failed to unregister MTD %s and the spi_flash object is going away: you're in deep trouble!",
+              sf_mtd_info.name);
 }
index 5a2e932de8f80c107cb74ab048458ccae188714e..00f8558e7019e9f7b6f2cf0a6d4c2b4a2916c497 100644 (file)
@@ -144,6 +144,14 @@ static int spi_flash_std_probe(struct udevice *dev)
        return spi_flash_probe_slave(flash);
 }
 
+static int spi_flash_std_remove(struct udevice *dev)
+{
+#ifdef CONFIG_SPI_FLASH_MTD
+       spi_flash_mtd_unregister();
+#endif
+       return 0;
+}
+
 static const struct dm_spi_flash_ops spi_flash_std_ops = {
        .read = spi_flash_std_read,
        .write = spi_flash_std_write,
@@ -161,6 +169,7 @@ U_BOOT_DRIVER(spi_flash_std) = {
        .id             = UCLASS_SPI_FLASH,
        .of_match       = spi_flash_std_ids,
        .probe          = spi_flash_std_probe,
+       .remove         = spi_flash_std_remove,
        .priv_auto_alloc_size = sizeof(struct spi_flash),
        .ops            = &spi_flash_std_ops,
 };
index b38f4df9f31e584f707428fdcd2cf33757f94420..aecd290d72939f4a34a6348a85aec0c99e48b0c2 100644 (file)
@@ -77,9 +77,6 @@ static inline struct e1000_hw *e1000_hw_from_spi(struct spi_slave *spi)
        return container_of(spi, struct e1000_hw, spi);
 }
 
-/* Not sure why all of these are necessary */
-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)
 {
index eaacd4066e8297f31a989a87584c1a2c058e5f36..7d9b75c2c457aa2b6502990fb449dca579e07d6c 100644 (file)
@@ -331,6 +331,7 @@ int vbe_setup_video_priv(struct vesa_mode_info *vesa,
                return log_msg_ret("No x resolution", -ENXIO);
        uc_priv->xsize = vesa->x_resolution;
        uc_priv->ysize = vesa->y_resolution;
+       uc_priv->line_length = vesa->bytes_per_scanline;
        switch (vesa->bits_per_pixel) {
        case 32:
        case 24:
index 516188ea88e141fb421f8ee45b973f21ed59f22d..a7bb5b35c294d92edaf000c8d3b8873678eee7fd 100644 (file)
@@ -116,6 +116,20 @@ config ICH_SPI
          access the SPI NOR flash on platforms embedding this Intel
          ICH IP core.
 
+config MESON_SPIFC
+       bool "Amlogic Meson SPI Flash Controller driver"
+       depends on ARCH_MESON
+       help
+         Enable the Amlogic Meson SPI Flash Controller SPIFC) driver.
+         This driver can be used to access the SPI NOR flash chips on
+         Amlogic Meson SoCs.
+
+config MPC8XX_SPI
+       bool "MPC8XX SPI Driver"
+       depends on MPC8xx
+       help
+         Enable support for SPI on MPC8XX
+
 config MT7621_SPI
        bool "MediaTek MT7621 SPI driver"
        depends on ARCH_MT7620
@@ -124,6 +138,13 @@ config MT7621_SPI
          the SPI NOR flash on platforms embedding this Ralink / MediaTek
          SPI core, like MT7621/7628/7688.
 
+config MTK_QSPI
+       bool "Mediatek QSPI driver"
+       help
+         Enable the Mediatek QSPI driver. This driver can be
+         used to access the SPI NOR flash on platforms embedding this
+         Mediatek QSPI IP core.
+
 config MVEBU_A3700_SPI
        bool "Marvell Armada 3700 SPI driver"
        select CLK_ARMADA_3720
@@ -328,12 +349,6 @@ config LPC32XX_SSP
        help
          Enable support for SPI on LPC32xx
 
-config MPC8XX_SPI
-       bool "MPC8XX SPI Driver"
-       depends on MPC8xx
-       help
-         Enable support for SPI on MPC8XX
-
 config MPC8XXX_SPI
        bool "MPC8XXX SPI Driver"
        help
index 7242ea7e4045a44c15260366f010af92ec80210f..392a92579578b61652ba7bdef44c0f9f9edeec34 100644 (file)
@@ -31,8 +31,10 @@ obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
 obj-$(CONFIG_ICH_SPI) +=  ich.o
 obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
+obj-$(CONFIG_MESON_SPIFC) += meson_spifc.o
 obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
+obj-$(CONFIG_MTK_QSPI) += mtk_qspi.o
 obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o
 obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
index 1db8bbef2bbdc196ae76ccda759433b572886073..cf4de9ee1aaf4712e13a6cb6dbeb5f7c2c3ae480 100644 (file)
@@ -34,11 +34,6 @@ static int spi_has_wdrbt(struct atmel_spi_slave *slave)
        return (ATMEL_SPI_VERSION_REV(ver) >= 0x210);
 }
 
-void spi_init()
-{
-
-}
-
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                        unsigned int max_hz, unsigned int mode)
 {
index 07fa5e3b8a113baefe97f1fdb8ed836037e317d9..4d2c106440b3af635446305aceac10c05b03ce69 100644 (file)
@@ -388,11 +388,6 @@ void spi_cs_deactivate(struct spi_slave *slave)
        /* do nothing */
 }
 
-void spi_init(void)
-{
-       /* do nothing */
-}
-
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                        unsigned int max_hz, unsigned int mode)
 {
index f7ed8fbe08b7733583e705751d892f85649d91da..764c94215e7cebc8766f44974807e5081fe5ea79 100644 (file)
@@ -390,11 +390,6 @@ static int fsl_dspi_cfg_speed(struct fsl_dspi_priv *priv, uint speed)
        return 0;
 }
 #ifndef CONFIG_DM_SPI
-void spi_init(void)
-{
-       /* Nothing to do */
-}
-
 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 {
        if (((cs >= 0) && (cs < 8)) && ((bus >= 0) && (bus < 8)))
index e9941593f5fdc08ee2b4e4b2cd30c7ce3bd4dc2e..7444ae1a068bce1cc3eddc64a922d5ab831dfc33 100644 (file)
@@ -118,11 +118,6 @@ void spi_free_slave(struct spi_slave *slave)
        free(fsl);
 }
 
-void spi_init(void)
-{
-
-}
-
 int spi_claim_bus(struct spi_slave *slave)
 {
        struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
index ce12eee65715890429258b81aaef45cbf16521fe..4b09366317afb5b2de11aa13fc322d38349ceaaf 100644 (file)
@@ -47,15 +47,6 @@ static inline struct lpc32xx_spi_slave *to_lpc32xx_spi_slave(
        return container_of(slave, struct lpc32xx_spi_slave, slave);
 }
 
-/* spi_init is called during boot when CONFIG_CMD_SPI is defined */
-void spi_init(void)
-{
-       /*
-        *  nothing to do: clocking was enabled in lpc32xx_ssp_enable()
-        * and configuration will be done in spi_setup_slave()
-       */
-}
-
 /* the following is called in sequence by do_spi_xfer() */
 
 struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode)
diff --git a/drivers/spi/meson_spifc.c b/drivers/spi/meson_spifc.c
new file mode 100644 (file)
index 0000000..3d55169
--- /dev/null
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
+ * Copyright (C) 2018 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Amlogic Meson SPI Flash Controller driver
+ */
+
+#include <common.h>
+#include <spi.h>
+#include <clk.h>
+#include <dm.h>
+#include <regmap.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/bitfield.h>
+
+/* register map */
+#define REG_CMD                        0x00
+#define REG_ADDR               0x04
+#define REG_CTRL               0x08
+#define REG_CTRL1              0x0c
+#define REG_STATUS             0x10
+#define REG_CTRL2              0x14
+#define REG_CLOCK              0x18
+#define REG_USER               0x1c
+#define REG_USER1              0x20
+#define REG_USER2              0x24
+#define REG_USER3              0x28
+#define REG_USER4              0x2c
+#define REG_SLAVE              0x30
+#define REG_SLAVE1             0x34
+#define REG_SLAVE2             0x38
+#define REG_SLAVE3             0x3c
+#define REG_C0                 0x40
+#define REG_B8                 0x60
+#define REG_MAX                        0x7c
+
+/* register fields */
+#define CMD_USER               BIT(18)
+#define CTRL_ENABLE_AHB                BIT(17)
+#define CLOCK_SOURCE           BIT(31)
+#define CLOCK_DIV_SHIFT                12
+#define CLOCK_DIV_MASK         (0x3f << CLOCK_DIV_SHIFT)
+#define CLOCK_CNT_HIGH_SHIFT   6
+#define CLOCK_CNT_HIGH_MASK    (0x3f << CLOCK_CNT_HIGH_SHIFT)
+#define CLOCK_CNT_LOW_SHIFT    0
+#define CLOCK_CNT_LOW_MASK     (0x3f << CLOCK_CNT_LOW_SHIFT)
+#define USER_DIN_EN_MS         BIT(0)
+#define USER_CMP_MODE          BIT(2)
+#define USER_CLK_NOT_INV       BIT(7)
+#define USER_UC_DOUT_SEL       BIT(27)
+#define USER_UC_DIN_SEL                BIT(28)
+#define USER_UC_MASK           ((BIT(5) - 1) << 27)
+#define USER1_BN_UC_DOUT_SHIFT 17
+#define USER1_BN_UC_DOUT_MASK  (0xff << 16)
+#define USER1_BN_UC_DIN_SHIFT  8
+#define USER1_BN_UC_DIN_MASK   (0xff << 8)
+#define USER4_CS_POL_HIGH      BIT(23)
+#define USER4_IDLE_CLK_HIGH    BIT(29)
+#define USER4_CS_ACT           BIT(30)
+#define SLAVE_TRST_DONE                BIT(4)
+#define SLAVE_OP_MODE          BIT(30)
+#define SLAVE_SW_RST           BIT(31)
+
+#define SPIFC_BUFFER_SIZE      64
+
+struct meson_spifc_priv {
+       struct regmap                   *regmap;
+       struct clk                      clk;
+};
+
+/**
+ * meson_spifc_drain_buffer() - copy data from device buffer to memory
+ * @spifc:     the Meson SPI device
+ * @buf:       the destination buffer
+ * @len:       number of bytes to copy
+ */
+static void meson_spifc_drain_buffer(struct meson_spifc_priv *spifc,
+                                    u8 *buf, int len)
+{
+       u32 data;
+       int i = 0;
+
+       while (i < len) {
+               regmap_read(spifc->regmap, REG_C0 + i, &data);
+
+               if (len - i >= 4) {
+                       *((u32 *)buf) = data;
+                       buf += 4;
+               } else {
+                       memcpy(buf, &data, len - i);
+                       break;
+               }
+               i += 4;
+       }
+}
+
+/**
+ * meson_spifc_fill_buffer() - copy data from memory to device buffer
+ * @spifc:     the Meson SPI device
+ * @buf:       the source buffer
+ * @len:       number of bytes to copy
+ */
+static void meson_spifc_fill_buffer(struct meson_spifc_priv *spifc,
+                                   const u8 *buf, int len)
+{
+       u32 data = 0;
+       int i = 0;
+
+       while (i < len) {
+               if (len - i >= 4)
+                       data = *(u32 *)buf;
+               else
+                       memcpy(&data, buf, len - i);
+
+               regmap_write(spifc->regmap, REG_C0 + i, data);
+
+               buf += 4;
+               i += 4;
+       }
+}
+
+/**
+ * meson_spifc_txrx() - transfer a chunk of data
+ * @spifc:     the Meson SPI device
+ * @dout:      data buffer for TX
+ * @din:       data buffer for RX
+ * @offset:    offset of the data to transfer
+ * @len:       length of the data to transfer
+ * @last_xfer: whether this is the last transfer of the message
+ * @last_chunk:        whether this is the last chunk of the transfer
+ * Return:     0 on success, a negative value on error
+ */
+static int meson_spifc_txrx(struct meson_spifc_priv *spifc,
+                           const u8 *dout, u8 *din, int offset,
+                           int len, bool last_xfer, bool last_chunk)
+{
+       bool keep_cs = true;
+       u32 data;
+       int ret;
+
+       if (dout)
+               meson_spifc_fill_buffer(spifc, dout + offset, len);
+
+       /* enable DOUT stage */
+       regmap_update_bits(spifc->regmap, REG_USER, USER_UC_MASK,
+                          USER_UC_DOUT_SEL);
+       regmap_write(spifc->regmap, REG_USER1,
+                    (8 * len - 1) << USER1_BN_UC_DOUT_SHIFT);
+
+       /* enable data input during DOUT */
+       regmap_update_bits(spifc->regmap, REG_USER, USER_DIN_EN_MS,
+                          USER_DIN_EN_MS);
+
+       if (last_chunk && last_xfer)
+               keep_cs = false;
+
+       regmap_update_bits(spifc->regmap, REG_USER4, USER4_CS_ACT,
+                          keep_cs ? USER4_CS_ACT : 0);
+
+       /* clear transition done bit */
+       regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_TRST_DONE, 0);
+       /* start transfer */
+       regmap_update_bits(spifc->regmap, REG_CMD, CMD_USER, CMD_USER);
+
+       /* wait for the current operation to terminate */
+       ret = regmap_read_poll_timeout(spifc->regmap, REG_SLAVE, data,
+                                      (data & SLAVE_TRST_DONE),
+                                      0, 5 * CONFIG_SYS_HZ);
+
+       if (!ret && din)
+               meson_spifc_drain_buffer(spifc, din + offset, len);
+
+       return ret;
+}
+
+/**
+ * meson_spifc_xfer() - perform a single transfer
+ * @dev:       the SPI controller device
+ * @bitlen:    length of the transfer
+ * @dout:      data buffer for TX
+ * @din:       data buffer for RX
+ * @flags:     transfer flags
+ * Return:     0 on success, a negative value on error
+ */
+static int meson_spifc_xfer(struct udevice *slave, unsigned int bitlen,
+                           const void *dout, void *din, unsigned long flags)
+{
+       struct meson_spifc_priv *spifc = dev_get_priv(slave->parent);
+       int blen = bitlen / 8;
+       int len, done = 0, ret = 0;
+
+       if (bitlen % 8)
+               return -EINVAL;
+
+       debug("xfer len %d (%d) dout %p din %p\n", bitlen, blen, dout, din);
+
+       regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB, 0);
+
+       while (done < blen && !ret) {
+               len = min_t(int, blen - done, SPIFC_BUFFER_SIZE);
+               ret = meson_spifc_txrx(spifc, dout, din, done, len,
+                                      flags & SPI_XFER_END,
+                                      done + len >= blen);
+               done += len;
+       }
+
+       regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB,
+                          CTRL_ENABLE_AHB);
+
+       return ret;
+}
+
+/**
+ * meson_spifc_set_speed() - program the clock divider
+ * @dev:       the SPI controller device
+ * @speed:     desired speed in Hz
+ */
+static int meson_spifc_set_speed(struct udevice *dev, uint speed)
+{
+       struct meson_spifc_priv *spifc = dev_get_priv(dev);
+       unsigned long parent, value;
+       int n;
+
+       parent = clk_get_rate(&spifc->clk);
+       n = max_t(int, parent / speed - 1, 1);
+
+       debug("parent %lu, speed %u, n %d\n", parent, speed, n);
+
+       value = (n << CLOCK_DIV_SHIFT) & CLOCK_DIV_MASK;
+       value |= (n << CLOCK_CNT_LOW_SHIFT) & CLOCK_CNT_LOW_MASK;
+       value |= (((n + 1) / 2 - 1) << CLOCK_CNT_HIGH_SHIFT) &
+               CLOCK_CNT_HIGH_MASK;
+
+       regmap_write(spifc->regmap, REG_CLOCK, value);
+
+       return 0;
+}
+
+/**
+ * meson_spifc_set_mode() - setups the SPI bus mode
+ * @dev:       the SPI controller device
+ * @mode:      desired mode bitfield
+ * Return:     0 on success, -ENODEV on error
+ */
+static int meson_spifc_set_mode(struct udevice *dev, uint mode)
+{
+       struct meson_spifc_priv *spifc = dev_get_priv(dev);
+
+       if (mode & (SPI_CPHA | SPI_RX_QUAD | SPI_RX_DUAL |
+                   SPI_TX_QUAD | SPI_TX_DUAL))
+               return -ENODEV;
+
+       regmap_update_bits(spifc->regmap, REG_USER, USER_CLK_NOT_INV,
+                          mode & SPI_CPOL ? USER_CLK_NOT_INV : 0);
+
+       regmap_update_bits(spifc->regmap, REG_USER4, USER4_CS_POL_HIGH,
+                          mode & SPI_CS_HIGH ? USER4_CS_POL_HIGH : 0);
+
+       return 0;
+}
+
+/**
+ * meson_spifc_hw_init() - reset and initialize the SPI controller
+ * @spifc:     the Meson SPI device
+ */
+static void meson_spifc_hw_init(struct meson_spifc_priv *spifc)
+{
+       /* reset device */
+       regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_SW_RST,
+                          SLAVE_SW_RST);
+       /* disable compatible mode */
+       regmap_update_bits(spifc->regmap, REG_USER, USER_CMP_MODE, 0);
+       /* set master mode */
+       regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_OP_MODE, 0);
+}
+
+static const struct dm_spi_ops meson_spifc_ops = {
+       .xfer           = meson_spifc_xfer,
+       .set_speed      = meson_spifc_set_speed,
+       .set_mode       = meson_spifc_set_mode,
+};
+
+static int meson_spifc_probe(struct udevice *dev)
+{
+       struct meson_spifc_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
+       if (ret)
+               return ret;
+
+       ret = clk_get_by_index(dev, 0, &priv->clk);
+       if (ret)
+               return ret;
+
+       ret = clk_enable(&priv->clk);
+       if (ret)
+               return ret;
+
+       meson_spifc_hw_init(priv);
+
+       return 0;
+}
+
+static const struct udevice_id meson_spifc_ids[] = {
+       { .compatible = "amlogic,meson-gxbb-spifc", },
+       { }
+};
+
+U_BOOT_DRIVER(meson_spifc) = {
+       .name           = "meson_spifc",
+       .id             = UCLASS_SPI,
+       .of_match       = meson_spifc_ids,
+       .ops            = &meson_spifc_ops,
+       .probe          = meson_spifc_probe,
+       .priv_auto_alloc_size = sizeof(struct meson_spifc_priv),
+};
diff --git a/drivers/spi/mtk_qspi.c b/drivers/spi/mtk_qspi.c
new file mode 100644 (file)
index 0000000..b510733
--- /dev/null
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018  MediaTek, Inc.
+ * Author : Guochun.Mao@mediatek.com
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+
+/* Register Offset */
+struct mtk_qspi_regs {
+       u32 cmd;
+       u32 cnt;
+       u32 rdsr;
+       u32 rdata;
+       u32 radr[3];
+       u32 wdata;
+       u32 prgdata[6];
+       u32 shreg[10];
+       u32 cfg[2];
+       u32 shreg10;
+       u32 mode_mon;
+       u32 status[4];
+       u32 flash_time;
+       u32 flash_cfg;
+       u32 reserved_0[3];
+       u32 sf_time;
+       u32 pp_dw_data;
+       u32 reserved_1;
+       u32 delsel_0[2];
+       u32 intrstus;
+       u32 intren;
+       u32 reserved_2;
+       u32 cfg3;
+       u32 reserved_3;
+       u32 chksum;
+       u32 aaicmd;
+       u32 wrprot;
+       u32 radr3;
+       u32 dual;
+       u32 delsel_1[3];
+};
+
+struct mtk_qspi_platdata {
+       fdt_addr_t reg_base;
+       fdt_addr_t mem_base;
+};
+
+struct mtk_qspi_priv {
+       struct mtk_qspi_regs *regs;
+       unsigned long *mem_base;
+       u8 op;
+       u8 tx[3]; /* only record max 3 bytes paras, when it's address. */
+       u32 txlen; /* dout buffer length  - op code length */
+       u8 *rx;
+       u32 rxlen;
+};
+
+#define MTK_QSPI_CMD_POLLINGREG_US 500000
+#define MTK_QSPI_WRBUF_SIZE        256
+#define MTK_QSPI_COMMAND_ENABLE    0x30
+
+/* NOR flash controller commands */
+#define MTK_QSPI_RD_TRIGGER        BIT(0)
+#define MTK_QSPI_READSTATUS        BIT(1)
+#define MTK_QSPI_PRG_CMD           BIT(2)
+#define MTK_QSPI_WR_TRIGGER        BIT(4)
+#define MTK_QSPI_WRITESTATUS       BIT(5)
+#define MTK_QSPI_AUTOINC           BIT(7)
+
+#define MTK_QSPI_MAX_RX_TX_SHIFT   0x6
+#define MTK_QSPI_MAX_SHIFT         0x8
+
+#define MTK_QSPI_WR_BUF_ENABLE     0x1
+#define MTK_QSPI_WR_BUF_DISABLE    0x0
+
+static int mtk_qspi_execute_cmd(struct mtk_qspi_priv *priv, u8 cmd)
+{
+       u8 tmp;
+       u8 val = cmd & ~MTK_QSPI_AUTOINC;
+
+       writeb(cmd, &priv->regs->cmd);
+
+       return readb_poll_timeout(&priv->regs->cmd, tmp, !(val & tmp),
+                                 MTK_QSPI_CMD_POLLINGREG_US);
+}
+
+static int mtk_qspi_tx_rx(struct mtk_qspi_priv *priv)
+{
+       int len = 1 + priv->txlen + priv->rxlen;
+       int i, ret, idx;
+
+       if (len > MTK_QSPI_MAX_SHIFT)
+               return -ERR_INVAL;
+
+       writeb(len * 8, &priv->regs->cnt);
+
+       /* start at PRGDATA5, go down to PRGDATA0 */
+       idx = MTK_QSPI_MAX_RX_TX_SHIFT - 1;
+
+       /* opcode */
+       writeb(priv->op, &priv->regs->prgdata[idx]);
+       idx--;
+
+       /* program TX data */
+       for (i = 0; i < priv->txlen; i++, idx--)
+               writeb(priv->tx[i], &priv->regs->prgdata[idx]);
+
+       /* clear out rest of TX registers */
+       while (idx >= 0) {
+               writeb(0, &priv->regs->prgdata[idx]);
+               idx--;
+       }
+
+       ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_PRG_CMD);
+       if (ret)
+               return ret;
+
+       /* restart at first RX byte */
+       idx = priv->rxlen - 1;
+
+       /* read out RX data */
+       for (i = 0; i < priv->rxlen; i++, idx--)
+               priv->rx[i] = readb(&priv->regs->shreg[idx]);
+
+       return 0;
+}
+
+static int mtk_qspi_read(struct mtk_qspi_priv *priv,
+                        u32 addr, u8 *buf, u32 len)
+{
+       memcpy(buf, (u8 *)priv->mem_base + addr, len);
+       return 0;
+}
+
+static void mtk_qspi_set_addr(struct mtk_qspi_priv *priv, u32 addr)
+{
+       int i;
+
+       for (i = 0; i < 3; i++) {
+               writeb(addr & 0xff, &priv->regs->radr[i]);
+               addr >>= 8;
+       }
+}
+
+static int mtk_qspi_write_single_byte(struct mtk_qspi_priv *priv,
+                                     u32 addr, u32 length, const u8 *data)
+{
+       int i, ret;
+
+       mtk_qspi_set_addr(priv, addr);
+
+       for (i = 0; i < length; i++) {
+               writeb(*data++, &priv->regs->wdata);
+               ret = mtk_qspi_execute_cmd(priv, MTK_QSPI_WR_TRIGGER);
+               if (ret < 0)
+                       return ret;
+       }
+       return 0;
+}
+
+static int mtk_qspi_write_buffer(struct mtk_qspi_priv *priv, u32 addr,
+                                const u8 *buf)
+{
+       int i, data;
+
+       mtk_qspi_set_addr(priv, addr);
+
+       for (i = 0; i < MTK_QSPI_WRBUF_SIZE; i += 4) {
+               data = buf[i + 3] << 24 | buf[i + 2] << 16 |
+                      buf[i + 1] << 8 | buf[i];
+               writel(data, &priv->regs->pp_dw_data);
+       }
+
+       return mtk_qspi_execute_cmd(priv, MTK_QSPI_WR_TRIGGER);
+}
+
+static int mtk_qspi_write(struct mtk_qspi_priv *priv,
+                         u32 addr, const u8 *buf, u32 len)
+{
+       int ret;
+
+       /* setting pre-fetch buffer for page program */
+       writel(MTK_QSPI_WR_BUF_ENABLE, &priv->regs->cfg[1]);
+       while (len >= MTK_QSPI_WRBUF_SIZE) {
+               ret = mtk_qspi_write_buffer(priv, addr, buf);
+               if (ret < 0)
+                       return ret;
+
+               len -= MTK_QSPI_WRBUF_SIZE;
+               addr += MTK_QSPI_WRBUF_SIZE;
+               buf += MTK_QSPI_WRBUF_SIZE;
+       }
+       /* disable pre-fetch buffer for page program */
+       writel(MTK_QSPI_WR_BUF_DISABLE, &priv->regs->cfg[1]);
+
+       if (len)
+               return mtk_qspi_write_single_byte(priv, addr, len, buf);
+
+       return 0;
+}
+
+static int mtk_qspi_claim_bus(struct udevice *dev)
+{
+       /* nothing to do */
+       return 0;
+}
+
+static int mtk_qspi_release_bus(struct udevice *dev)
+{
+       /* nothing to do */
+       return 0;
+}
+
+static int mtk_qspi_transfer(struct mtk_qspi_priv *priv, unsigned int bitlen,
+                            const void *dout, void *din, unsigned long flags)
+{
+       u32 bytes = DIV_ROUND_UP(bitlen, 8);
+       u32 addr;
+
+       if (!bytes)
+               return -ERR_INVAL;
+
+       if (dout) {
+               if (flags & SPI_XFER_BEGIN) {
+                       /* parse op code and potential paras first */
+                       priv->op = *(u8 *)dout;
+                       if (bytes > 1)
+                               memcpy(priv->tx, (u8 *)dout + 1,
+                                      bytes <= 4 ? bytes - 1 : 3);
+                       priv->txlen = bytes - 1;
+               }
+
+               if (flags == SPI_XFER_ONCE) {
+                       /* operations without receiving or sending data.
+                        * for example: erase, write flash register or write
+                        * enable...
+                        */
+                       priv->rx = NULL;
+                       priv->rxlen = 0;
+                       return mtk_qspi_tx_rx(priv);
+               }
+
+               if (flags & SPI_XFER_END) {
+                       /* here, dout should be data to be written.
+                        * and priv->tx should be filled 3Bytes address.
+                        */
+                       addr = priv->tx[0] << 16 | priv->tx[1] << 8 |
+                              priv->tx[2];
+                       return mtk_qspi_write(priv, addr, (u8 *)dout, bytes);
+               }
+       }
+
+       if (din) {
+               if (priv->txlen >= 3) {
+                       /* if run to here, priv->tx[] should be the address
+                        * where read data from,
+                        * and, din is the buf to receive data.
+                        */
+                       addr = priv->tx[0] << 16 | priv->tx[1] << 8 |
+                              priv->tx[2];
+                       return mtk_qspi_read(priv, addr, (u8 *)din, bytes);
+               }
+
+               /* should be reading flash's register */
+               priv->rx = (u8 *)din;
+               priv->rxlen = bytes;
+               return mtk_qspi_tx_rx(priv);
+       }
+
+       return 0;
+}
+
+static int mtk_qspi_xfer(struct udevice *dev, unsigned int bitlen,
+                        const void *dout, void *din, unsigned long flags)
+{
+       struct udevice *bus = dev->parent;
+       struct mtk_qspi_priv *priv = dev_get_priv(bus);
+
+       return  mtk_qspi_transfer(priv, bitlen, dout, din, flags);
+}
+
+static int mtk_qspi_set_speed(struct udevice *bus, uint speed)
+{
+       /* nothing to do */
+       return 0;
+}
+
+static int mtk_qspi_set_mode(struct udevice *bus, uint mode)
+{
+       /* nothing to do */
+       return 0;
+}
+
+static int mtk_qspi_ofdata_to_platdata(struct udevice *bus)
+{
+       struct resource res_reg, res_mem;
+       struct mtk_qspi_platdata *plat = bus->platdata;
+       int ret;
+
+       ret = dev_read_resource_byname(bus, "reg_base", &res_reg);
+       if (ret) {
+               debug("can't get reg_base resource(ret = %d)\n", ret);
+               return -ENOMEM;
+       }
+
+       ret = dev_read_resource_byname(bus, "mem_base", &res_mem);
+       if (ret) {
+               debug("can't get map_base resource(ret = %d)\n", ret);
+               return -ENOMEM;
+       }
+
+       plat->mem_base = res_mem.start;
+       plat->reg_base = res_reg.start;
+
+       return 0;
+}
+
+static int mtk_qspi_probe(struct udevice *bus)
+{
+       struct mtk_qspi_platdata *plat = dev_get_platdata(bus);
+       struct mtk_qspi_priv *priv = dev_get_priv(bus);
+
+       priv->regs = (struct mtk_qspi_regs *)plat->reg_base;
+       priv->mem_base = (unsigned long *)plat->mem_base;
+
+       writel(MTK_QSPI_COMMAND_ENABLE, &priv->regs->wrprot);
+
+       return 0;
+}
+
+static const struct dm_spi_ops mtk_qspi_ops = {
+       .claim_bus      = mtk_qspi_claim_bus,
+       .release_bus    = mtk_qspi_release_bus,
+       .xfer           = mtk_qspi_xfer,
+       .set_speed      = mtk_qspi_set_speed,
+       .set_mode       = mtk_qspi_set_mode,
+};
+
+static const struct udevice_id mtk_qspi_ids[] = {
+       { .compatible = "mediatek,mt7629-qspi" },
+       { }
+};
+
+U_BOOT_DRIVER(mtk_qspi) = {
+       .name     = "mtk_qspi",
+       .id       = UCLASS_SPI,
+       .of_match = mtk_qspi_ids,
+       .ops      = &mtk_qspi_ops,
+       .ofdata_to_platdata       = mtk_qspi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct mtk_qspi_platdata),
+       .priv_auto_alloc_size     = sizeof(struct mtk_qspi_priv),
+       .probe    = mtk_qspi_probe,
+};
index 0dccc38b82d241a23874dea24ee1f17351522e9d..b2636909ce6510a0dfc7c42cba46b13be93aa9eb 100644 (file)
@@ -400,10 +400,6 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
        return mxc_spi_xfer_internal(mxcs, bitlen, dout, din, flags);
 }
 
-void spi_init(void)
-{
-}
-
 /*
  * Some SPI devices require active chip-select over multiple
  * transactions, we achieve this using a GPIO. Still, the SPI
index 006fe8281c5bd1a691b39a2ad0adde1e89a9757a..5065e407f82466ba45ea6f8336179d3d5952c936 100644 (file)
@@ -39,10 +39,6 @@ static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
        return container_of(slave, struct mxs_spi_slave, slave);
 }
 
-void spi_init(void)
-{
-}
-
 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 {
        /* MXS SPI: 4 ports and 3 chip selects maximum */
index ecf54bb7148e7d8ca9b80b3d850b92e5e8cd1289..c7fcf050a58738090eb7876d7622c52c949690fd 100644 (file)
@@ -461,11 +461,6 @@ static inline struct omap3_spi_priv *to_omap3_spi(struct spi_slave *slave)
        return container_of(slave, struct omap3_spi_priv, slave);
 }
 
-void spi_init(void)
-{
-       /* do nothing */
-}
-
 void spi_free_slave(struct spi_slave *slave)
 {
        struct omap3_spi_priv *priv = to_omap3_spi(slave);
index 86b71d2e21abdab4fa08d60ba8c36122a2a53d45..32bb8c8d2127f6663341e5f825b71a05a7fa9230 100644 (file)
@@ -9,16 +9,11 @@
  * Driver for ARM PL022 SPI Controller.
  */
 
-#include <asm/io.h>
 #include <clk.h>
 #include <common.h>
 #include <dm.h>
-#include <dm/platform_data/pl022_spi.h>
-#include <fdtdec.h>
-#include <linux/bitops.h>
-#include <linux/bug.h>
+#include <dm/platform_data/spi_pl022.h>
 #include <linux/io.h>
-#include <linux/kernel.h>
 #include <spi.h>
 
 #define SSP_CR0                0x000
 
 struct pl022_spi_slave {
        void *base;
-#if !CONFIG_IS_ENABLED(OF_PLATDATA)
-       struct clk clk;
-#else
        unsigned int freq;
-#endif
 };
 
 /*
@@ -96,30 +87,13 @@ static int pl022_is_supported(struct pl022_spi_slave *ps)
        return 0;
 }
 
-#if !CONFIG_IS_ENABLED(OF_PLATDATA)
-static int pl022_spi_ofdata_to_platdata(struct udevice *bus)
-{
-       struct pl022_spi_pdata *plat = bus->platdata;
-       const void *fdt = gd->fdt_blob;
-       int node = dev_of_offset(bus);
-
-       plat->addr = fdtdec_get_addr_size(fdt, node, "reg", &plat->size);
-
-       return clk_get_by_index(bus, 0, &plat->clk);
-}
-#endif
-
 static int pl022_spi_probe(struct udevice *bus)
 {
        struct pl022_spi_pdata *plat = dev_get_platdata(bus);
        struct pl022_spi_slave *ps = dev_get_priv(bus);
 
        ps->base = ioremap(plat->addr, plat->size);
-#if !CONFIG_IS_ENABLED(OF_PLATDATA)
-       ps->clk = plat->clk;
-#else
        ps->freq = plat->freq;
-#endif
 
        /* Check the PL022 version */
        if (!pl022_is_supported(ps))
@@ -240,11 +214,7 @@ static int pl022_spi_set_speed(struct udevice *bus, uint speed)
        u16 scr = SSP_SCR_MIN, cr0 = 0, cpsr = SSP_CPSR_MIN, best_scr = scr,
            best_cpsr = cpsr;
        u32 min, max, best_freq = 0, tmp;
-#if !CONFIG_IS_ENABLED(OF_PLATDATA)
-       u32 rate = clk_get_rate(&ps->clk);
-#else
        u32 rate = ps->freq;
-#endif
        bool found = false;
 
        max = spi_rate(rate, SSP_CPSR_MIN, SSP_SCR_MIN);
@@ -316,6 +286,25 @@ static const struct dm_spi_ops pl022_spi_ops = {
 };
 
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int pl022_spi_ofdata_to_platdata(struct udevice *bus)
+{
+       struct pl022_spi_pdata *plat = bus->platdata;
+       const void *fdt = gd->fdt_blob;
+       int node = dev_of_offset(bus);
+       struct clk clkdev;
+       int ret;
+
+       plat->addr = fdtdec_get_addr_size(fdt, node, "reg", &plat->size);
+
+       ret = clk_get_by_index(bus, 0, &clkdev);
+       if (ret)
+               return ret;
+
+       plat->freq = clk_get_rate(&clkdev);
+
+       return 0;
+}
+
 static const struct udevice_id pl022_spi_ids[] = {
        { .compatible = "arm,pl022-spi" },
        { }
@@ -327,11 +316,9 @@ U_BOOT_DRIVER(pl022_spi) = {
        .id     = UCLASS_SPI,
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
        .of_match = pl022_spi_ids,
-#endif
-       .ops    = &pl022_spi_ops,
-#if !CONFIG_IS_ENABLED(OF_PLATDATA)
        .ofdata_to_platdata = pl022_spi_ofdata_to_platdata,
 #endif
+       .ops    = &pl022_spi_ops,
        .platdata_auto_alloc_size = sizeof(struct pl022_spi_pdata),
        .priv_auto_alloc_size = sizeof(struct pl022_spi_slave),
        .probe  = pl022_spi_probe,
index 64dfd748d67a12f32f577ac2e128ba0298a9a99a..5ae203d8d4f87c734933e934b9871e120f28fa70 100644 (file)
@@ -247,11 +247,6 @@ void spi_cs_deactivate(struct spi_slave *slave)
        sh_qspi_cs_deactivate(ss);
 }
 
-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)
 {
index bc2bd638e6f5ac6bd0b0543b3af2fbc6d1955bcd..c58fd0ebc43812c8d5f64dc828fa4accf2bc42ac 100644 (file)
@@ -66,10 +66,6 @@ static int write_fifo_empty_wait(struct sh_spi *ss)
        return 0;
 }
 
-void spi_init(void)
-{
-}
-
 static void sh_spi_set_cs(struct sh_spi *ss, unsigned int cs)
 {
        unsigned long val = 0;
index 0aac0c065daa5442630ba29289b5cdfea04503fd..cc5ab5f991dae090880a0ecedbc3e4a31f7477c1 100644 (file)
@@ -36,13 +36,6 @@ static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave)
 /*                         Public Functions                            */
 /*=====================================================================*/
 
-/*-----------------------------------------------------------------------
- * Initialization
- */
-void spi_init (void)
-{
-}
-
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
                unsigned int max_hz, unsigned int mode)
 {
index b6551b69d3ae2cc039032909dae539919807953c..f307cf243bdcb876b355b2e9c30990fbaf1bd318 100644 (file)
@@ -226,7 +226,9 @@ static int video_post_probe(struct udevice *dev)
 
        /* Set up the line and display size */
        priv->fb = map_sysmem(plat->base, plat->size);
-       priv->line_length = priv->xsize * VNBYTES(priv->bpix);
+       if (!priv->line_length)
+               priv->line_length = priv->xsize * VNBYTES(priv->bpix);
+
        priv->fb_size = priv->line_length * priv->ysize;
 
        /* Set up colors  */
index 1377e190817dfb95bb03f450e60337daaf9f2feb..2898b0b55d759492d5b3a6379d357acdf615dbb0 100644 (file)
@@ -7,6 +7,7 @@
 #include <bmp_layout.h>
 #include <dm.h>
 #include <mapmem.h>
+#include <splash.h>
 #include <video.h>
 #include <watchdog.h>
 #include <asm/unaligned.h>
@@ -140,8 +141,6 @@ __weak void fb_put_word(uchar **fb, uchar **from)
 }
 #endif /* CONFIG_BMP_16BPP */
 
-#define BMP_ALIGN_CENTER       0x7fff
-
 /**
  * video_splash_align_axis() - Align a single coordinate
  *
index 2e14aba390e62d0974330c16069792f52f769568..b7bd243730bb0ce69ab8701dbfaec0566a849a00 100644 (file)
@@ -126,8 +126,6 @@ int atmel_df_pow2(int argc, char * const argv[])
                return 1;
        }
 
-       spi_init();
-
        while (1) {
                struct spi_slave *slave;
                char *line, *p;
index 5416041243d67c025b6c79f9f58b1bde40bb2680..c15050e30b775a5a8c6f16cbe06c89127f47be9a 100644 (file)
 #endif
 
 #if !defined(CONFIG_CMD_SPI) || defined(CONFIG_DM_SPI)
-       EXPORT_FUNC(dummy, void, spi_init, void)
        EXPORT_FUNC(dummy, void, spi_setup_slave, void)
        EXPORT_FUNC(dummy, void, spi_free_slave, void)
 #else
-       EXPORT_FUNC(spi_init, void, spi_init, void)
        EXPORT_FUNC(spi_setup_slave, struct spi_slave *, spi_setup_slave,
                    unsigned int, unsigned int, unsigned int, unsigned int)
        EXPORT_FUNC(spi_free_slave, void, spi_free_slave, struct spi_slave *)
index 20c99da1aa95194284c76d073d87aaeaf890e335..657cc404cfaf3335fa206b1c1158ba39da19529b 100644 (file)
@@ -287,13 +287,6 @@ int  eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned c
 # define CONFIG_SYS_DEF_EEPROM_ADDR CONFIG_SYS_I2C_EEPROM_ADDR
 #endif
 
-#if defined(CONFIG_MPC8XX_SPI)
-extern void spi_init_f (void);
-extern void spi_init_r (void);
-extern ssize_t spi_read         (uchar *, int, uchar *, int);
-extern ssize_t spi_write (uchar *, int, uchar *, int);
-#endif
-
 /* $(BOARD)/$(BOARD).c */
 int board_early_init_f (void);
 int board_fix_fdt (void *rw_fdt_blob); /* manipulate the U-Boot fdt before its relocation */
index 11cb3955da5fe444746e34d7a1836bc99a1d99f7..83d774527adcfc6ad39d621990d31a98f3da1925 100644 (file)
 
 /* DSPI and Serial Flash */
 #define CONFIG_CF_DSPI
-#define CONFIG_HARD_SPI
 #define CONFIG_SYS_SBFHDR_SIZE         0x7
 #ifdef CONFIG_CMD_SPI
 #      define CONFIG_SYS_DSPI_CS2
index f08896ef0a05108819640504b9aae0c5b072ab8a..4b8ef38c0befc7fb6b3cc4d31515fb474b45adcf 100644 (file)
 /* DSPI and Serial Flash */
 #define CONFIG_CF_DSPI
 #define CONFIG_SERIAL_FLASH
-#define CONFIG_HARD_SPI
 #define CONFIG_SYS_SBFHDR_SIZE         0x7
 #ifdef CONFIG_CMD_SPI
 
index 16becbdbedd81e3051d908adbb12d6206fcd3e0a..87cdbae1dbf56e0ffdc5a54abec1fa89c8660143 100644 (file)
 /* DSPI and Serial Flash */
 #define CONFIG_CF_DSPI
 #define CONFIG_SERIAL_FLASH
-#define CONFIG_HARD_SPI
 #define CONFIG_SYS_SBFHDR_SIZE         0x7
 #ifdef CONFIG_CMD_SPI
 
index 99b60d5d82301d159f06a2071f9bd02247716097..d41b7c4492953de1e382da7f7ea3b3184a91ba95 100644 (file)
 
 /* DSPI and Serial Flash */
 #define CONFIG_CF_DSPI
-#define CONFIG_HARD_SPI
 #define CONFIG_SYS_SBFHDR_SIZE         0x13
 #ifdef CONFIG_CMD_SPI
 
index 524a10fc95a8b0b0151e05c15d0c42f391233a1d..86a1233e322014416c118b96ec5073000c55695c 100644 (file)
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
 #define CONFIG_SYS_EEPROM_BUS_NUM      1
 
-/*
- * eSPI - Enhanced SPI
- */
-#define CONFIG_HARD_SPI
-
 #if defined(CONFIG_SPI_FLASH)
 #define CONFIG_SF_DEFAULT_SPEED        10000000
 #define CONFIG_SF_DEFAULT_MODE 0
index c9ed70ca4cb9761445bb215065d3c91cd54be2ee..eeb19a9fa68a7399b2ed091181deefc0a4f0092e 100644 (file)
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
 #define CONFIG_SYS_EEPROM_BUS_NUM      1
 
-/*
- * eSPI - Enhanced SPI
- */
-
-#define CONFIG_HARD_SPI
-
 #define CONFIG_SF_DEFAULT_SPEED                10000000
 #define CONFIG_SF_DEFAULT_MODE         0
 
index 423ecd71c279c17a9f221482fde72033f20c522d..1bbe9d9b375755dd6c15c17b7372eaa336ef3706 100644 (file)
 #define CONFIG_SYS_I2C_NCT72_ADDR      0x4C
 #define CONFIG_SYS_I2C_IDT6V49205B     0x69
 
-/*
- * eSPI - Enhanced SPI
- */
-#define CONFIG_HARD_SPI
-
 #define CONFIG_SF_DEFAULT_SPEED                10000000
 #define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
 
index 4adcd956efb709682a5351c6124988d0c9eeb8cf..1908d35bcc698e59a964c8f49aaa9f7d088a2ae8 100644 (file)
 #define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
 
 #ifndef CONFIG_TRAILBLAZER
-/*
- * eSPI - Enhanced SPI
- */
-#define CONFIG_HARD_SPI
 
 #define CONFIG_SF_DEFAULT_SPEED                10000000
 #define CONFIG_SF_DEFAULT_MODE         0
index 28124dd4b12efe602cfb4f02f162a01531203bd1..7e4c497fe0ae65b22dd5a3f02d61c1593cccdf63 100644 (file)
  */
 #define CONFIG_TSEC1
 #define CONFIG_TSEC2
-#define CONFIG_HARD_SPI
 
 /*
  * NOR FLASH setup
 #define CONFIG_RTC_PCF8563
 #define CONFIG_SYS_I2C_RTC_ADDR        0x51
 
-/*
- * SPI setup
- */
-#ifdef CONFIG_HARD_SPI
-#define CONFIG_SYS_GPIO1_PRELIM
-#define CONFIG_SYS_GPIO1_DIR           0x00000001
-#define CONFIG_SYS_GPIO1_DAT           0x00000001
-#endif
-
 /*
  * Ethernet setup
  */
index 7d84d160b4c3d4e7b04a0629027414b7beb6c84b..4765764f83a9edebf8e38ef9d26e9aeffc81fcb9 100644 (file)
@@ -43,7 +43,6 @@
 #define CONFIG_MXC_UART
 #define CONFIG_MXC_UART_BASE   UART1_BASE
 
-#define CONFIG_HARD_SPI
 #define CONFIG_DEFAULT_SPI_BUS 1
 #define CONFIG_DEFAULT_SPI_MODE        (SPI_MODE_0 | SPI_CS_HIGH)
 
index 9e59e7a4dcb3996089b23117a211e62aa262d998..4bb3621a42860d6112dd0f5ce9e86849608e27e4 100644 (file)
 
 /* SPI */
 #ifdef CONFIG_CMD_SPI
-#define CONFIG_HARD_SPI
 #define CONFIG_SPI_HALF_DUPLEX
 #endif
 
index 9465fb47027b141decdfc6eddd1a0632346c1584..459ecf328f20853ab0b46c78cef8ac08527b9c81 100644 (file)
 #define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3
 #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5
 
-/*
- * eSPI - Enhanced SPI
- */
-#define CONFIG_HARD_SPI
-
 #if defined(CONFIG_SPI_FLASH)
 #define CONFIG_SF_DEFAULT_SPEED        10000000
 #define CONFIG_SF_DEFAULT_MODE 0
index d018c22afdb2908bf4fa03f77d606f8ad93bdc32..4f48370648807e11024dc08a0e8584a204a43a9a 100644 (file)
@@ -214,11 +214,6 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
 #define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3
 #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5
 
-/*
- * eSPI - Enhanced SPI
- */
-#define CONFIG_HARD_SPI
-
 #if defined(CONFIG_PCI)
 /*
  * General PCI
index c408db865ebddf37f83b13d7d0de679907cf8ac2..33ddc67bf4a34e7051a3f32268875168765e7981 100644 (file)
@@ -66,7 +66,6 @@
 #define CONFIG_CF_DSPI
 #define CONFIG_SF_DEFAULT_SPEED                50000000
 #define CONFIG_SERIAL_FLASH
-#define CONFIG_HARD_SPI
 #define CONFIG_ENV_SPI_BUS             0
 #define CONFIG_ENV_SPI_CS              1
 
index 956f7795f1f525cbbf12b6004b02358b689a6e03..4e274bd4141d1151dc7c1d3e061cb6be75681380 100644 (file)
 #define CONFIG_MXC_UART
 #define CONFIG_MXC_UART_BASE   UART1_BASE
 
-/*
- * SPI Configs
- * */
-#define CONFIG_HARD_SPI /* puts SPI: ready */
-
 /*
  * MMC Configs
  * */
diff --git a/include/dm/platform_data/pl022_spi.h b/include/dm/platform_data/pl022_spi.h
deleted file mode 100644 (file)
index 77fe6da..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * (C) Copyright 2018
- * Quentin Schulz, Bootlin, quentin.schulz@bootlin.com
- *
- * Structure for use with U_BOOT_DEVICE for pl022 SPI devices or to use
- * in ofdata_to_platdata.
- */
-
-#ifndef __PL022_SPI_H__
-#define __PL022_SPI_H__
-
-#if !CONFIG_IS_ENABLED(OF_PLATDATA)
-#include <clk.h>
-#endif
-#include <fdtdec.h>
-
-struct pl022_spi_pdata {
-       fdt_addr_t addr;
-       fdt_size_t size;
-#if !CONFIG_IS_ENABLED(OF_PLATDATA)
-       struct clk clk;
-#else
-       unsigned int freq;
-#endif
-};
-
-#endif
diff --git a/include/dm/platform_data/spi_pl022.h b/include/dm/platform_data/spi_pl022.h
new file mode 100644 (file)
index 0000000..63a58ee
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018
+ * Quentin Schulz, Bootlin, quentin.schulz@bootlin.com
+ *
+ * Structure for use with U_BOOT_DEVICE for pl022 SPI devices or to use
+ * in ofdata_to_platdata.
+ */
+
+#ifndef __spi_pl022_h
+#define __spi_pl022_h
+
+#include <fdtdec.h>
+
+struct pl022_spi_pdata {
+       fdt_addr_t addr;
+       fdt_size_t size;
+       unsigned int freq;
+};
+
+#endif /* __spi_pl022_h */
index 68e5915324929f99d3ef7df83e5643d1ef7b34e6..cd1f557a2f3151834f8a8211804c0623402cc78e 100644 (file)
@@ -366,6 +366,8 @@ static inline bool mtd_has_partitions(const struct mtd_info *mtd)
        return !list_empty(&mtd->partitions);
 }
 
+bool mtd_partitions_used(struct mtd_info *master);
+
 int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
                      struct mtd_oob_region *oobecc);
 int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
@@ -562,8 +564,23 @@ unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
 /* drivers/mtd/mtdcore.h */
 int add_mtd_device(struct mtd_info *mtd);
 int del_mtd_device(struct mtd_info *mtd);
+
+#ifdef CONFIG_MTD_PARTITIONS
 int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
 int del_mtd_partitions(struct mtd_info *);
+#else
+static inline int add_mtd_partitions(struct mtd_info *mtd,
+                                    const struct mtd_partition *parts,
+                                    int nparts)
+{
+       return 0;
+}
+
+static inline int del_mtd_partitions(struct mtd_info *mtd)
+{
+       return 0;
+}
+#endif
 
 struct mtd_info *__mtd_next_device(int i);
 #define mtd_for_each_device(mtd)                       \
@@ -581,6 +598,7 @@ int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
 void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
                          const uint64_t length, uint64_t *len_incl_bad,
                          int *truncated);
+bool mtd_dev_list_updated(void);
 
 /* drivers/mtd/mtd_uboot.c */
 int mtd_search_alternate_name(const char *mtdname, char *altname,
index b2b733fda6813c207725a9958a5f2ac05e857f91..a3afb72df51b2250cd1eaaf2a38b56da5dee16aa 100644 (file)
@@ -239,6 +239,44 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
 #define regmap_get(map, type, member, valp) \
        regmap_range_get(map, 0, type, member, valp)
 
+/**
+ * regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs
+ *
+ * @map:       Regmap to read from
+ * @addr:      Offset to poll
+ * @val:       Unsigned integer variable to read the value into
+ * @cond:      Break condition (usually involving @val)
+ * @sleep_us:  Maximum time to sleep between reads in us (0 tight-loops).
+ * @timeout_ms:        Timeout in ms, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
+ * error return value in case of a error read. In the two former cases,
+ * the last read value at @addr is stored in @val. Must not be called
+ * from atomic context if sleep_us or timeout_us are used.
+ *
+ * This is modelled after the regmap_read_poll_timeout macros in linux but
+ * with millisecond timeout.
+ */
+#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_ms) \
+({ \
+       unsigned long __start = get_timer(0); \
+       int __ret; \
+       for (;;) { \
+               __ret = regmap_read((map), (addr), &(val)); \
+               if (__ret) \
+                       break; \
+               if (cond) \
+                       break; \
+               if ((timeout_ms) && get_timer(__start) > (timeout_ms)) { \
+                       __ret = regmap_read((map), (addr), &(val)); \
+                       break; \
+               } \
+               if ((sleep_us)) \
+                       udelay((sleep_us)); \
+       } \
+       __ret ?: ((cond) ? 0 : -ETIMEDOUT); \
+})
+
 /**
  * regmap_update_bits() - Perform a read/modify/write using a mask
  *
index 938627bc012b57294365cc4b5ca4691d82dbf298..92427e5f32953f37c67b0369cf6bb3b35cfa521c 100644 (file)
@@ -117,13 +117,6 @@ struct spi_slave {
 #define SPI_XFER_MMAP_END      BIT(3)  /* Memory Mapped End */
 };
 
-/**
- * Initialization, must be called once on start up.
- *
- * TODO: I don't think we really need this.
- */
-void spi_init(void);
-
 /**
  * spi_do_alloc_slave - Allocate a new SPI slave (internal)
  *
index 3f9139eea445eec966ae5ebc612e6967fbe7612a..1d57b48b173807dfb9914793e7ff283ab5962425 100644 (file)
@@ -61,7 +61,9 @@ enum video_log2_bpp {
  * @font_size: Font size in pixels (0 to use a default value)
  * @fb:                Frame buffer
  * @fb_size:   Frame buffer size
- * @line_length:       Length of each frame buffer line, in bytes
+ * @line_length:       Length of each frame buffer line, in bytes. This can be
+ *             set by the driver, but if not, the uclass will set it after
+ *             probing
  * @colour_fg: Foreground colour (pixel value)
  * @colour_bg: Background colour (pixel value)
  * @flush_dcache:      true to enable flushing of the data cache after
index bd14fe22c65573f35492878083e9a37f0bb9dc42..b8addeaf693a7330e02f73be3fdc46384b28a7cf 100644 (file)
@@ -750,7 +750,6 @@ CONFIG_G_DNL_UMS_PRODUCT_NUM
 CONFIG_G_DNL_UMS_VENDOR_NUM
 CONFIG_H264_FREQ
 CONFIG_H8300
-CONFIG_HARD_SPI
 CONFIG_HAS_ETH0
 CONFIG_HAS_ETH1
 CONFIG_HAS_ETH2
index a8d7e6829eca0c53adf580e1406bc07080548e96..9a70c159ddb9e9b4eec49f2c40088002c9cca667 100644 (file)
@@ -144,3 +144,29 @@ static int dm_test_regmap_getset(struct unit_test_state *uts)
 }
 
 DM_TEST(dm_test_regmap_getset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Read polling test */
+static int dm_test_regmap_poll(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+       struct regmap *map;
+       uint reg;
+       unsigned long start;
+
+       ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev));
+       map = syscon_get_regmap(dev);
+       ut_assertok_ptr(map);
+
+       start = get_timer(0);
+
+       ut_asserteq(-ETIMEDOUT,
+                   regmap_read_poll_timeout(map, 0, reg,
+                                            (reg == 0xcacafafa),
+                                            1, 5 * CONFIG_SYS_HZ));
+
+       ut_assert(get_timer(start) > (5 * CONFIG_SYS_HZ));
+
+       return 0;
+}
+
+DM_TEST(dm_test_regmap_poll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);