Merge git://git.denx.de/u-boot-mpc83xx
authorTom Rini <trini@konsulko.com>
Tue, 21 May 2019 11:13:35 +0000 (07:13 -0400)
committerTom Rini <trini@konsulko.com>
Tue, 21 May 2019 11:13:35 +0000 (07:13 -0400)
- Update MPC83xx platform support to current best practices, etc.

25 files changed:
arch/arm/dts/armada-370-xp.dtsi
arch/arm/dts/imx53.dtsi
arch/arm/dts/imx6q.dtsi
arch/arm/dts/imx6qdl.dtsi
arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
arch/arm/mach-sunxi/board.c
board/beckhoff/mx53cx9020/Makefile
board/beckhoff/mx53cx9020/mx53cx9020.c
board/beckhoff/mx53cx9020/mx53cx9020_video.c
board/wandboard/wandboard.c
common/splash_source.c
configs/beelink_gs1_defconfig
configs/mx53cx9020_defconfig
configs/mx6sabresd_defconfig
configs/nanopi_m1_plus_defconfig
configs/teres_i_defconfig
doc/README.splashprepare
drivers/i2c/Kconfig
drivers/i2c/mxc_i2c.c
drivers/mmc/fsl_esdhc.c
drivers/video/imx/mxc_ipuv3_fb.c
drivers/video/vidconsole-uclass.c
include/configs/mx53cx9020.h
include/video_console.h
test/dm/video.c

index e4c35d4..50fc0be 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+                       u-boot,dm-pre-reloc;
 
                        rtc: rtc@10300 {
                                compatible = "marvell,orion-rtc";
index 5ba6174..211ff5f 100644 (file)
@@ -31,6 +31,7 @@
                i2c0 = &i2c1;
                i2c1 = &i2c2;
                i2c2 = &i2c3;
+               ipu0 = &ipu;
                mmc0 = &esdhc1;
                mmc1 = &esdhc2;
                mmc2 = &esdhc3;
@@ -51,6 +52,7 @@
                compatible = "simple-bus";
                interrupt-parent = <&tzic>;
                ranges;
+               u-boot,dm-pre-reloc;
 
                aips@50000000 { /* AIPS1 */
                        compatible = "fsl,aips-bus", "simple-bus";
                                status = "disabled";
                        };
                };
+
+               ipu: ipu@18000000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,imx53-ipu";
+                       reg = <0x18000000 0x08000000>;
+                       interrupts = <11 10>;
+                       clocks = <&clks IMX5_CLK_IPU_GATE>,
+                                <&clks IMX5_CLK_IPU_DI0_GATE>,
+                                <&clks IMX5_CLK_IPU_DI1_GATE>;
+                       clock-names = "bus", "di0", "di1";
+                       resets = <&src 2>;
+                       u-boot,dm-pre-reloc;
+
+                       ipu_csi0: port@0 {
+                               reg = <0>;
+                       };
+
+                       ipu_csi1: port@1 {
+                               reg = <1>;
+                       };
+
+                       ipu_di0: port@2 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <2>;
+
+                               ipu_di0_disp0: endpoint@0 {
+                                       reg = <0>;
+                               };
+
+                               ipu_di0_lvds0: endpoint@1 {
+                                       reg = <1>;
+                                       remote-endpoint = <&lvds0_in>;
+                               };
+                       };
+
+                       ipu_di1: port@3 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <3>;
+
+                               ipu_di1_disp1: endpoint@0 {
+                                       reg = <0>;
+                               };
+
+                               ipu_di1_lvds1: endpoint@1 {
+                                       reg = <1>;
+                                       remote-endpoint = <&lvds1_in>;
+                               };
+
+                               ipu_di1_tve: endpoint@2 {
+                                       reg = <2>;
+                                       remote-endpoint = <&tve_in>;
+                               };
+                       };
+               };
+
+               tve: tve@63ff0000 {
+                               compatible = "fsl,imx53-tve";
+                               reg = <0x63ff0000 0x1000>;
+                               interrupts = <92>;
+                               clocks = <&clks IMX5_CLK_TVE_GATE>,
+                                        <&clks IMX5_CLK_IPU_DI1_SEL>;
+                               clock-names = "tve", "di_sel";
+                               status = "disabled";
+
+                               port {
+                                       tve_in: endpoint {
+                                               remote-endpoint = <&ipu_di1_tve>;
+                                       };
+                               };
+               };
+
+               src: src@53fd0000 {
+                               compatible = "fsl,imx53-src", "fsl,imx51-src";
+                               reg = <0x53fd0000 0x4000>;
+                               #reset-cells = <1>;
+               };
+
+               ldb: ldb@53fa8008 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx53-ldb";
+                               reg = <0x53fa8008 0x4>;
+                               gpr = <&gpr>;
+                               clocks = <&clks IMX5_CLK_LDB_DI0_SEL>,
+                                        <&clks IMX5_CLK_LDB_DI1_SEL>,
+                                        <&clks IMX5_CLK_IPU_DI0_SEL>,
+                                        <&clks IMX5_CLK_IPU_DI1_SEL>,
+                                        <&clks IMX5_CLK_LDB_DI0_GATE>,
+                                        <&clks IMX5_CLK_LDB_DI1_GATE>;
+                               clock-names = "di0_pll", "di1_pll",
+                                             "di0_sel", "di1_sel",
+                                             "di0", "di1";
+                               status = "disabled";
+
+                               lvds-channel@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+                                       status = "disabled";
+
+                                       port@0 {
+                                               reg = <0>;
+
+                                               lvds0_in: endpoint {
+                                                       remote-endpoint = <&ipu_di0_lvds0>;
+                                               };
+                                       };
+
+                                       port@2 {
+                                               reg = <2>;
+                                       };
+                               };
+
+                               lvds-channel@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+                                       status = "disabled";
+
+                                       port@1 {
+                                               reg = <1>;
+
+                                               lvds1_in: endpoint {
+                                                       remote-endpoint = <&ipu_di1_lvds1>;
+                                               };
+                                       };
+
+                                       port@2 {
+                                               reg = <2>;
+                                       };
+                               };
+               };
        };
 };
index d038f41..71543a4 100644 (file)
@@ -9,6 +9,7 @@
 / {
        aliases {
                ipu1 = &ipu2;
+               video1 = &ipu2;
                spi4 = &ecspi5;
        };
 
index c0a9478..83eeb5c 100644 (file)
@@ -33,6 +33,7 @@
                i2c1 = &i2c2;
                i2c2 = &i2c3;
                ipu0 = &ipu1;
+               video0 = &ipu1;
                mmc0 = &usdhc1;
                mmc1 = &usdhc2;
                mmc2 = &usdhc3;
index 41a9b0f..6392cb0 100644 (file)
@@ -60,6 +60,7 @@
 #define SUNXI_RTC_BASE                 0x07000000
 #define SUNXI_R_CPUCFG_BASE            0x07000400
 #define SUNXI_PRCM_BASE                        0x07010000
+#define SUNXI_R_WDOG_BASE              0x07020400
 #define SUNXI_R_PIO_BASE               0x07022000
 #define SUNXI_R_UART_BASE              0x07080000
 #define SUNXI_R_TWI_BASE               0x07081400
index 7f5b633..8e9bb63 100644 (file)
@@ -289,9 +289,14 @@ void reset_cpu(ulong addr)
                writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
        }
 #elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
+#if defined(CONFIG_MACH_SUN50I_H6)
+       /* WDOG is broken for some H6 rev. use the R_WDOG instead */
        static const struct sunxi_wdog *wdog =
-                ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
-
+               (struct sunxi_wdog *)SUNXI_R_WDOG_BASE;
+#else
+       static const struct sunxi_wdog *wdog =
+               ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
+#endif
        /* Set the watchdog for its shortest interval (.5s) and wait */
        writel(WDT_CFG_RESET, &wdog->cfg);
        writel(WDT_MODE_EN, &wdog->mode);
index 423a553..7f15fc5 100644 (file)
@@ -4,4 +4,4 @@
 # Patrick Bruenn <p.bruenn@beckhoff.com>
 
 obj-y               += mx53cx9020.o
-obj-$(CONFIG_VIDEO) += mx53cx9020_video.o
+obj-$(CONFIG_DM_VIDEO) += mx53cx9020_video.o
index 79d8a62..9450d92 100644 (file)
@@ -8,26 +8,12 @@
  */
 
 #include <common.h>
-#include <dm.h>
-#include <asm/io.h>
-#include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
-#include <asm/arch/crm_regs.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/iomux-mx53.h>
-#include <asm/arch/clock.h>
 #include <asm/mach-imx/mx5_video.h>
 #include <ACEX1K.h>
-#include <netdev.h>
-#include <i2c.h>
-#include <mmc.h>
-#include <fsl_esdhc.h>
 #include <asm/gpio.h>
-#include <linux/fb.h>
-#include <ipu_pixfmt.h>
-#include <input.h>
-#include <fs.h>
-#include <dm/platform_data/serial_mxc.h>
 
 enum LED_GPIOS {
        GPIO_SD1_CD = IMX_GPIO_NR(1, 1),
@@ -91,6 +77,9 @@ void weim_cs0_settings(u32 mode)
 
 static void setup_gpio_eim(void)
 {
+       gpio_request(GPIO_C3_STATUS, "GPIO_C3_STATUS");
+       gpio_request(GPIO_C3_DONE, "GPIO_C3_DONE");
+       gpio_request(GPIO_C3_CONFIG, "GPIO_C3_CONFIG");
        gpio_direction_input(GPIO_C3_STATUS);
        gpio_direction_input(GPIO_C3_DONE);
        gpio_direction_output(GPIO_C3_CONFIG, 1);
@@ -100,6 +89,7 @@ static void setup_gpio_eim(void)
 
 static void setup_gpio_sups(void)
 {
+       gpio_request(GPIO_SUPS_INT, "GPIO_SUPS_INT");
        gpio_direction_input(GPIO_SUPS_INT);
 
        static const int BLINK_INTERVALL = 50000;
@@ -116,6 +106,16 @@ static void setup_gpio_sups(void)
 
 static void setup_gpio_leds(void)
 {
+       gpio_request(GPIO_LED_SD2_R, "GPIO_LED_SD2_R");
+       gpio_request(GPIO_LED_SD2_B, "GPIO_LED_SD2_B");
+       gpio_request(GPIO_LED_SD2_G, "GPIO_LED_SD2_G");
+       gpio_request(GPIO_LED_SD1_R, "GPIO_LED_SD1_R");
+       gpio_request(GPIO_LED_SD1_B, "GPIO_LED_SD1_B");
+       gpio_request(GPIO_LED_SD1_G, "GPIO_LED_SD1_G");
+       gpio_request(GPIO_LED_PWR_R, "GPIO_LED_PWR_R");
+       gpio_request(GPIO_LED_PWR_B, "GPIO_LED_PWR_B");
+       gpio_request(GPIO_LED_PWR_G, "GPIO_LED_PWR_G");
+
        gpio_direction_output(GPIO_LED_SD2_R, 0);
        gpio_direction_output(GPIO_LED_SD2_B, 0);
        gpio_direction_output(GPIO_LED_SD2_G, 0);
@@ -136,55 +136,6 @@ int board_ehci_hcd_init(int port)
 }
 #endif
 
-#ifdef CONFIG_FSL_ESDHC
-struct fsl_esdhc_cfg esdhc_cfg[2] = {
-       {MMC_SDHC1_BASE_ADDR},
-       {MMC_SDHC2_BASE_ADDR},
-};
-
-int board_mmc_getcd(struct mmc *mmc)
-{
-       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
-       int ret;
-
-       gpio_direction_input(GPIO_SD1_CD);
-       gpio_direction_input(GPIO_SD2_CD);
-
-       if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
-               ret = !gpio_get_value(GPIO_SD1_CD);
-       else
-               ret = !gpio_get_value(GPIO_SD2_CD);
-
-       return ret;
-}
-
-int board_mmc_init(bd_t *bis)
-{
-       u32 index;
-       int ret;
-
-       esdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
-       esdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
-
-       for (index = 0; index < CONFIG_SYS_FSL_ESDHC_NUM; index++) {
-               switch (index) {
-               case 0:
-                       break;
-               case 1:
-                       break;
-               default:
-                       printf("Warning: you configured more ESDHC controller(%d) as supported by the board(2)\n",
-                              CONFIG_SYS_FSL_ESDHC_NUM);
-                       return -EINVAL;
-               }
-               ret = fsl_esdhc_initialize(bis, &esdhc_cfg[index]);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-#endif
 
 static int power_init(void)
 {
@@ -212,29 +163,21 @@ static void clock_1GHz(void)
 
 int board_early_init_f(void)
 {
-       setup_gpio_leds();
-       setup_gpio_sups();
-       setup_gpio_eim();
-       setup_iomux_lcd();
 
        return 0;
 }
 
-/*
- * Do not overwrite the console
- * Use always serial for U-Boot console
- */
-int overwrite_console(void)
-{
-       return 1;
-}
-
 int board_init(void)
 {
        gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
 
        mxc_set_sata_internal_clock();
 
+       setup_gpio_leds();
+       setup_gpio_sups();
+       setup_gpio_eim();
+       setup_iomux_lcd();
+
        return 0;
 }
 
index 4055bcc..bf47290 100644 (file)
@@ -8,41 +8,39 @@
  */
 
 #include <common.h>
-#include <linux/list.h>
-#include <asm/gpio.h>
 #include <asm/arch/iomux-mx53.h>
-#include <linux/fb.h>
-#include <ipu_pixfmt.h>
+#include <asm/gpio.h>
+#include <asm/mach-imx/video.h>
 
 #define CX9020_DVI_PWD IMX_GPIO_NR(6, 1)
 
-static struct fb_videomode const vga_640x480 = {
-       .name = "VESA_VGA_640x480",
-       .refresh = 60,
-       .xres = 640,
-       .yres = 480,
-       .pixclock = 39721,      /* picosecond (25.175 MHz) */
-       .left_margin = 40,
-       .right_margin = 60,
-       .upper_margin = 10,
-       .lower_margin = 10,
-       .hsync_len = 20,
-       .vsync_len = 10,
-       .sync = 0,
-       .vmode = FB_VMODE_NONINTERLACED
-};
+struct display_info_t const displays[] = {{
+       .bus    = -1,
+       .addr   = 0,
+       .pixfmt = IPU_PIX_FMT_RGB24,
+       .detect = NULL,
+       .enable = NULL,
+       .mode   = {
+               .name           = "DVI",
+               .refresh = 60,
+               .xres = 640,
+               .yres = 480,
+               .pixclock = 39721,      /* picosecond (25.175 MHz) */
+               .left_margin = 40,
+               .right_margin = 60,
+               .upper_margin = 10,
+               .lower_margin = 10,
+               .hsync_len = 20,
+               .vsync_len = 10,
+               .sync = 0,
+               .vmode = FB_VMODE_NONINTERLACED
+} } };
+size_t display_count = ARRAY_SIZE(displays);
 
 void setup_iomux_lcd(void)
 {
        /* Turn on DVI_PWD */
        imx_iomux_v3_setup_pad(MX53_PAD_CSI0_DAT15__GPIO6_1);
+       gpio_request(CX9020_DVI_PWD, "CX9020_DVI_PWD");
        gpio_direction_output(CX9020_DVI_PWD, 1);
 }
-
-int board_video_skip(void)
-{
-       const int ret = ipuv3_fb_init(&vga_640x480, 0, IPU_PIX_FMT_RGB24);
-       if (ret)
-               printf("VESA VG 640x480 cannot be configured: %d\n", ret);
-       return ret;
-}
index 69fbc8b..9d7a94f 100644 (file)
@@ -46,6 +46,15 @@ DECLARE_GLOBAL_DATA_PTR;
 #define ETH_PHY_AR8035_POWER   IMX_GPIO_NR(7, 13)
 #define REV_DETECTION          IMX_GPIO_NR(2, 28)
 
+/* Speed defined in Kconfig is only applicable when not using DM_I2C.  */
+#ifdef CONFIG_DM_I2C
+#define I2C1_SPEED_NON_DM      0
+#define I2C2_SPEED_NON_DM      0
+#else
+#define I2C1_SPEED_NON_DM      CONFIG_SYS_MXC_I2C1_SPEED
+#define I2C2_SPEED_NON_DM      CONFIG_SYS_MXC_I2C2_SPEED
+#endif
+
 static bool with_pmic;
 
 int dram_init(void)
@@ -463,13 +472,13 @@ int board_init(void)
        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 
 #if defined(CONFIG_VIDEO_IPUV3)
-       setup_i2c(1, CONFIG_SYS_MXC_I2C1_SPEED, 0x7f, &mx6dl_i2c2_pad_info);
+       setup_i2c(1, I2C1_SPEED_NON_DM, 0x7f, &mx6dl_i2c2_pad_info);
        if (is_mx6dq() || is_mx6dqp()) {
-               setup_i2c(1, CONFIG_SYS_MXC_I2C1_SPEED, 0x7f, &mx6q_i2c2_pad_info);
-               setup_i2c(2, CONFIG_SYS_MXC_I2C2_SPEED, 0x7f, &mx6q_i2c3_pad_info);
+               setup_i2c(1, I2C1_SPEED_NON_DM, 0x7f, &mx6q_i2c2_pad_info);
+               setup_i2c(2, I2C2_SPEED_NON_DM, 0x7f, &mx6q_i2c3_pad_info);
        } else {
-               setup_i2c(1, CONFIG_SYS_MXC_I2C1_SPEED, 0x7f, &mx6dl_i2c2_pad_info);
-               setup_i2c(2, CONFIG_SYS_MXC_I2C2_SPEED, 0x7f, &mx6dl_i2c3_pad_info);
+               setup_i2c(1, I2C1_SPEED_NON_DM, 0x7f, &mx6dl_i2c2_pad_info);
+               setup_i2c(2, I2C2_SPEED_NON_DM, 0x7f, &mx6dl_i2c3_pad_info);
        }
 
        setup_display();
index 62763b9..8f276a3 100644 (file)
@@ -303,8 +303,12 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr)
 {
        int res;
        int node_offset;
-       int splash_offset;
-       int splash_size;
+       const char *splash_file;
+       const void *internal_splash_data;
+       size_t internal_splash_size;
+       int external_splash_addr;
+       int external_splash_size;
+       bool is_splash_external = false;
        struct image_header *img_header;
        const u32 *fit_header;
        u32 fit_size;
@@ -335,36 +339,51 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr)
                return -EINVAL;
        }
 
-       node_offset = fit_image_get_node(fit_header, location->name);
+       /* Get the splash image node */
+       splash_file = env_get("splashfile");
+       if (!splash_file)
+               splash_file = SPLASH_SOURCE_DEFAULT_FILE_NAME;
+
+       node_offset = fit_image_get_node(fit_header, splash_file);
        if (node_offset < 0) {
                debug("Could not find splash image '%s' in FIT\n",
-                     location->name);
+                     splash_file);
                return -ENOENT;
        }
 
-       res = fit_image_get_data_offset(fit_header, node_offset,
-                                       &splash_offset);
-       if (res < 0) {
-               printf("Failed to load splash image (err=%d)\n", res);
-               return res;
+       /* Extract the splash data from FIT */
+       /* 1. Test if splash is in FIT internal data. */
+       if (!fit_image_get_data(fit_header, node_offset, &internal_splash_data, &internal_splash_size))
+               memmove((void *)bmp_load_addr, internal_splash_data, internal_splash_size);
+       /* 2. Test if splash is in FIT external data with fixed position. */
+       else if (!fit_image_get_data_position(fit_header, node_offset, &external_splash_addr))
+               is_splash_external = true;
+       /* 3. Test if splash is in FIT external data with offset. */
+       else if (!fit_image_get_data_offset(fit_header, node_offset, &external_splash_addr)) {
+               /* Align data offset to 4-byte boundary */
+               fit_size = ALIGN(fdt_totalsize(fit_header), 4);
+               /* External splash offset means the offset by end of FIT header */
+               external_splash_addr += location->offset + fit_size;
+               is_splash_external = true;
+       } else {
+               printf("Failed to get splash image from FIT\n");
+               return -ENODATA;
        }
 
-       res = fit_image_get_data_size(fit_header, node_offset, &splash_size);
-       if (res < 0) {
-               printf("Failed to load splash image (err=%d)\n", res);
-               return res;
+       if (is_splash_external) {
+               res = fit_image_get_data_size(fit_header, node_offset, &external_splash_size);
+               if (res < 0) {
+                       printf("Failed to get size of splash image (err=%d)\n", res);
+                       return res;
+               }
+
+               /* Read in the splash data */
+               location->offset = external_splash_addr;
+               res = splash_storage_read_raw(location, bmp_load_addr, external_splash_size);
+               if (res < 0)
+                       return res;
        }
 
-       /* Align data offset to 4-byte boundrary */
-       fit_size = fdt_totalsize(fit_header);
-       fit_size = (fit_size + 3) & ~3;
-
-       /* Read in the splash data */
-       location->offset = (location->offset + fit_size + splash_offset);
-       res = splash_storage_read_raw(location, bmp_load_addr , splash_size);
-       if (res < 0)
-               return res;
-
        return 0;
 }
 #endif /* CONFIG_FIT */
index ef4dd29..437e2d9 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_PSCI_RESET is not set
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_TEXT_BASE=0x20060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
index 90ea9a6..b809066 100644 (file)
@@ -24,13 +24,14 @@ CONFIG_DEFAULT_DEVICE_TREE="imx53-cx9020"
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_FPGA_ALTERA=y
 CONFIG_FPGA_CYCLON2=y
+CONFIG_DM=y
 CONFIG_DM_MMC=y
+CONFIG_DM_GPIO=y
 CONFIG_FSL_ESDHC=y
 CONFIG_FEC_MXC=y
 CONFIG_MII=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_IMX5=y
 CONFIG_MXC_UART=y
+CONFIG_DM_VIDEO=y
 CONFIG_VIDEO_IPUV3=y
-CONFIG_VIDEO=y
-# CONFIG_VIDEO_SW_CURSOR is not set
index d3ed3c4..0fda6fc 100644 (file)
@@ -4,13 +4,13 @@ CONFIG_SYS_TEXT_BASE=0x17800000
 CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_TARGET_MX6SABRESD=y
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_SPL_LIBDISK_SUPPORT=y
-# CONFIG_SYS_MALLOC_F is not set
 CONFIG_FIT=y
 CONFIG_SPL_FIT_PRINT=y
 CONFIG_SPL_LOAD_FIT=y
@@ -63,6 +63,7 @@ CONFIG_OF_LIST="imx6q-sabresd imx6qp-sabresd imx6dl-sabresd"
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_SPL_MULTI_DTB_FIT=y
 CONFIG_SPL_OF_LIST="imx6dl-sabresd imx6q-sabresd imx6qp-sabresd"
+CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_SPL_DM=y
index ad94d58..90edbd9 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
+CONFIG_MACPWR="PD6"
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
@@ -12,6 +13,7 @@ CONFIG_SPL_TEXT_BASE=0x60
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus"
+CONFIG_SUN8I_EMAC=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
index 421a8d3..1b57a48 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_DRAM_ZQ=3881949
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB1_VBUS_PIN="PL7"
 CONFIG_I2C0_ENABLE=y
+CONFIG_SPL_TEXT_BASE=0x10060
 # CONFIG_CMD_FLASH is not set
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
index f1418de..3cb5b5a 100644 (file)
@@ -26,6 +26,9 @@ screen data is loaded as a file. The name of the splash screen file can be
 controlled with the environment variable "splashfile".
 
 To enable loading the splash image from a FIT image, CONFIG_FIT must be
-enabled. Struct splash_location field 'name' should match the splash image
-name within the FIT and the FIT should start at the 'offset' field address in
-the specified storage.
+enabled. The FIT image has to start at the 'offset' field address in the
+selected splash location. The name of splash image within the FIT shall be
+specified by the environment variable "splashfile".
+
+In case the environment variable "splashfile" is not defined the default name
+'splash.bmp' will be used.
index 2156240..095a9bc 100644 (file)
@@ -161,7 +161,10 @@ config SYS_I2C_MXC
          channels and operating on standard mode up to 100 kbits/s and fast
          mode up to 400 kbits/s.
 
-if SYS_I2C_MXC
+# These settings are not used with DM_I2C, however SPL doesn't use
+# DM_I2C even if DM_I2C is enabled, and so might use these settings even
+# when main u-boot does not!
+if SYS_I2C_MXC && (!DM_I2C || SPL)
 config SYS_I2C_MXC_I2C1
        bool "NXP MXC I2C1"
        help
index 5420afb..23119cc 100644 (file)
@@ -482,8 +482,13 @@ static int i2c_write_data(struct mxc_i2c_bus *i2c_bus, u8 chip, const u8 *buf,
        return ret;
 }
 
+/* Will generate a STOP after the last byte if "last" is true, i.e. this is the
+ * final message of a transaction.  If not, it switches the bus back to TX mode
+ * and does not send a STOP, leaving the bus in a state where a repeated start
+ * and address can be sent for another message.
+ */
 static int i2c_read_data(struct mxc_i2c_bus *i2c_bus, uchar chip, uchar *buf,
-                        int len)
+                        int len, bool last)
 {
        int ret;
        unsigned int temp;
@@ -513,17 +518,31 @@ static int i2c_read_data(struct mxc_i2c_bus *i2c_bus, uchar chip, uchar *buf,
                        return ret;
                }
 
-               /*
-                * It must generate STOP before read I2DR to prevent
-                * controller from generating another clock cycle
-                */
                if (i == (len - 1)) {
-                       i2c_imx_stop(i2c_bus);
+                       /* Final byte has already been received by master!  When
+                        * we read it from I2DR, the master will start another
+                        * cycle.  We must program it first to send a STOP or
+                        * switch to TX to avoid this.
+                        */
+                       if (last) {
+                               i2c_imx_stop(i2c_bus);
+                       } else {
+                               /* Final read, no stop, switch back to tx */
+                               temp = readb(base + (I2CR << reg_shift));
+                               temp |= I2CR_MTX | I2CR_TX_NO_AK;
+                               writeb(temp, base + (I2CR << reg_shift));
+                       }
                } else if (i == (len - 2)) {
+                       /* Master has already recevied penultimate byte.  When
+                        * we read it from I2DR, master will start RX of final
+                        * byte.  We must set TX_NO_AK now so it does not ACK
+                        * that final byte.
+                        */
                        temp = readb(base + (I2CR << reg_shift));
                        temp |= I2CR_TX_NO_AK;
                        writeb(temp, base + (I2CR << reg_shift));
                }
+
                writeb(I2SR_IIF_CLEAR, base + (I2SR << reg_shift));
                buf[i] = readb(base + (I2DR << reg_shift));
        }
@@ -533,13 +552,34 @@ static int i2c_read_data(struct mxc_i2c_bus *i2c_bus, uchar chip, uchar *buf,
                debug(" 0x%02x", buf[ret]);
        debug("\n");
 
-       i2c_imx_stop(i2c_bus);
+       /* It is not clear to me that this is necessary */
+       if (last)
+               i2c_imx_stop(i2c_bus);
        return 0;
 }
 
 #ifndef CONFIG_DM_I2C
 /*
  * Read data from I2C device
+ *
+ * The transactions use the syntax defined in the Linux kernel I2C docs.
+ *
+ * If alen is > 0, then this function will send a transaction of the form:
+ *     S Chip Wr [A] Addr [A] S Chip Rd [A] [data] A ... NA P
+ * This is a normal I2C register read: writing the register address, then doing
+ * a repeated start and reading the data.
+ *
+ * If alen == 0, then we get this transaction:
+ *     S Chip Wr [A] S Chip Rd [A] [data] A ... NA P
+ * This is somewhat unusual, though valid, transaction.  It addresses the chip
+ * in write mode, but doesn't actually write any register address or data, then
+ * does a repeated start and reads data.
+ *
+ * If alen < 0, then we get this transaction:
+ *     S Chip Rd [A] [data] A ... NA P
+ * The chip is addressed in read mode and then data is read.  No register
+ * address is written first.  This is perfectly valid on most devices and
+ * required on some (usually those that don't act like an array of registers).
  */
 static int bus_i2c_read(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
                        int alen, u8 *buf, int len)
@@ -566,7 +606,7 @@ static int bus_i2c_read(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
                return ret;
        }
 
-       ret = i2c_read_data(i2c_bus, chip, buf, len);
+       ret = i2c_read_data(i2c_bus, chip, buf, len, true);
 
        i2c_imx_stop(i2c_bus);
        return ret;
@@ -574,6 +614,20 @@ static int bus_i2c_read(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
 
 /*
  * Write data to I2C device
+ *
+ * If alen > 0, we get this transaction:
+ *    S Chip Wr [A] addr [A] data [A] ... [A] P
+ * An ordinary write register command.
+ *
+ * If alen == 0, then we get this:
+ *    S Chip Wr [A] data [A] ... [A] P
+ * This is a simple I2C write.
+ *
+ * If alen < 0, then we get this:
+ *    S data [A] ... [A] P
+ * This is most likely NOT something that should be used.  It doesn't send the
+ * chip address first, so in effect, the first byte of data will be used as the
+ * address.
  */
 static int bus_i2c_write(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
                         int alen, const u8 *buf, int len)
@@ -881,6 +935,7 @@ static int mxc_i2c_probe(struct udevice *bus)
        return 0;
 }
 
+/* Sends: S Addr Wr [A|NA] P */
 static int mxc_i2c_probe_chip(struct udevice *bus, u32 chip_addr,
                              u32 chip_flags)
 {
@@ -905,42 +960,54 @@ static int mxc_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
        ulong base = i2c_bus->base;
        int reg_shift = i2c_bus->driver_data & I2C_QUIRK_FLAG ?
                VF610_I2C_REGSHIFT : IMX_I2C_REGSHIFT;
+       int read_mode;
 
-       /*
-        * Here the 3rd parameter addr and the 4th one alen are set to 0,
-        * because here we only want to send out chip address. The register
-        * address is wrapped in msg.
+       /* Here address len is set to -1 to not send any address at first.
+        * Otherwise i2c_init_transfer will send the chip address with write
+        * mode set.  This is wrong if the 1st message is read.
         */
-       ret = i2c_init_transfer(i2c_bus, msg->addr, 0, 0);
+       ret = i2c_init_transfer(i2c_bus, msg->addr, 0, -1);
        if (ret < 0) {
                debug("i2c_init_transfer error: %d\n", ret);
                return ret;
        }
 
+       read_mode = -1; /* So it's always different on the first message */
        for (; nmsgs > 0; nmsgs--, msg++) {
-               bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
-               debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
-               if (msg->flags & I2C_M_RD)
-                       ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
-                                           msg->len);
-               else {
-                       ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
-                                            msg->len);
-                       if (ret)
-                               break;
-                       if (next_is_read) {
-                               /* Reuse ret */
+               const int msg_is_read = !!(msg->flags & I2C_M_RD);
+
+               debug("i2c_xfer: chip=0x%x, len=0x%x, dir=%c\n", msg->addr,
+                     msg->len, msg_is_read ? 'R' : 'W');
+
+               if (msg_is_read != read_mode) {
+                       /* Send repeated start if not 1st message */
+                       if (read_mode != -1) {
+                               debug("i2c_xfer: [RSTART]\n");
                                ret = readb(base + (I2CR << reg_shift));
                                ret |= I2CR_RSTA;
                                writeb(ret, base + (I2CR << reg_shift));
-
-                               ret = tx_byte(i2c_bus, (msg->addr << 1) | 1);
-                               if (ret < 0) {
-                                       i2c_imx_stop(i2c_bus);
-                                       break;
-                               }
                        }
+                       debug("i2c_xfer: [ADDR %02x | %c]\n", msg->addr,
+                             msg_is_read ? 'R' : 'W');
+                       ret = tx_byte(i2c_bus, (msg->addr << 1) | msg_is_read);
+                       if (ret < 0) {
+                               debug("i2c_xfer: [STOP]\n");
+                               i2c_imx_stop(i2c_bus);
+                               break;
+                       }
+                       read_mode = msg_is_read;
                }
+
+               if (msg->flags & I2C_M_RD)
+                       ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
+                                           msg->len, nmsgs == 1 ||
+                                                     (msg->flags & I2C_M_STOP));
+               else
+                       ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
+                                            msg->len);
+
+               if (ret < 0)
+                       break;
        }
 
        if (ret)
index 1b7de74..377b267 100644 (file)
@@ -621,31 +621,18 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
 #else
        int pre_div = 2;
 #endif
+       int ddr_pre_div = mmc->ddr_mode ? 2 : 1;
        int sdhc_clk = priv->sdhc_clk;
        uint clk;
 
-       /*
-        * For ddr mode, usdhc need to enable DDR mode first, after select
-        * this DDR mode, usdhc will automatically divide the usdhc clock
-        */
-       if (mmc->ddr_mode) {
-               writel(readl(&regs->mixctrl) | MIX_CTRL_DDREN, &regs->mixctrl);
-               sdhc_clk >>= 1;
-       }
-
        if (clock < mmc->cfg->f_min)
                clock = mmc->cfg->f_min;
 
-       if (sdhc_clk / 16 > clock) {
-               for (; pre_div < 256; pre_div *= 2)
-                       if ((sdhc_clk / pre_div) <= (clock * 16))
-                               break;
-       } else
-               pre_div = 1;
+       while (sdhc_clk / (16 * pre_div * ddr_pre_div) > clock && pre_div < 256)
+               pre_div *= 2;
 
-       for (div = 1; div <= 16; div++)
-               if ((sdhc_clk / (div * pre_div)) <= clock)
-                       break;
+       while (sdhc_clk / (div * pre_div * ddr_pre_div) > clock && div < 16)
+               div++;
 
        pre_div >>= 1;
        div -= 1;
index 3e38d4b..29ecac4 100644 (file)
@@ -678,13 +678,14 @@ static int ipuv3_video_bind(struct udevice *dev)
        struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
 
        plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
-                    (1 << LCD_MAX_LOG2_BPP) / 8;
+                    (1 << VIDEO_BPP32) / 8;
 
        return 0;
 }
 
 static const struct udevice_id ipuv3_video_ids[] = {
        { .compatible = "fsl,imx6q-ipu" },
+       { .compatible = "fsl,imx53-ipu" },
        { }
 };
 
index c31303b..af88588 100644 (file)
@@ -529,6 +529,20 @@ int vidconsole_put_char(struct udevice *dev, char ch)
        return 0;
 }
 
+int vidconsole_put_string(struct udevice *dev, const char *str)
+{
+       const char *s;
+       int ret;
+
+       for (s = str; *s; s++) {
+               ret = vidconsole_put_char(dev, *s);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
 {
        struct udevice *dev = sdev->priv;
@@ -541,8 +555,7 @@ static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
 {
        struct udevice *dev = sdev->priv;
 
-       while (*s)
-               vidconsole_put_char(dev, *s++);
+       vidconsole_put_string(dev, s);
        video_sync(dev->parent, false);
 }
 
index 9bf5d91..ab61a07 100644 (file)
 #define CONFIG_SYS_MMC_ENV_DEV 0
 
 /* Framebuffer and LCD */
+#define CONFIG_IMX_VIDEO_SKIP
 #define CONFIG_PREBOOT
-#define CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
-#define CONFIG_VIDEO_BMP_RLE8
-#define CONFIG_SPLASH_SCREEN
-#define CONFIG_BMP_16BPP
-#define CONFIG_VIDEO_LOGO
 
 #endif /* __CONFIG_H */
index 52a41ac..0936cea 100644 (file)
@@ -215,6 +215,22 @@ int vidconsole_set_row(struct udevice *dev, uint row, int clr);
 int vidconsole_put_char(struct udevice *dev, char ch);
 
 /**
+ * vidconsole_put_string() - Output a string to the current console position
+ *
+ * Outputs a string to the console and advances the cursor. This function
+ * handles wrapping to new lines and scrolling the console. Special
+ * characters are handled also: \n, \r, \b and \t.
+ *
+ * The device always starts with the cursor at position 0,0 (top left). It
+ * can be adjusted manually using vidconsole_position_cursor().
+ *
+ * @dev:       Device to adjust
+ * @str:       String to write
+ * @return 0 if OK, -ve on error
+ */
+int vidconsole_put_string(struct udevice *dev, const char *str);
+
+/**
  * vidconsole_position_cursor() - Move the text cursor
  *
  * @dev:       Device to adjust
index 6be5def..3151ebb 100644 (file)
@@ -97,14 +97,6 @@ static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
        return 0;
 }
 
-static void vidconsole_put_string(struct udevice *dev, const char *str)
-{
-       const char *s;
-
-       for (s = str; *s; s++)
-               vidconsole_put_char(dev, *s);
-}
-
 /* Test text output works on the video console */
 static int dm_test_video_text(struct unit_test_state *uts)
 {