Merge git://git.denx.de/u-boot-mpc83xx
- Update MPC83xx platform support to current best practices, etc.
diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi
index e4c35d4..50fc0be 100644
--- a/arch/arm/dts/armada-370-xp.dtsi
+++ b/arch/arm/dts/armada-370-xp.dtsi
@@ -102,6 +102,7 @@
#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";
diff --git a/arch/arm/dts/imx53.dtsi b/arch/arm/dts/imx53.dtsi
index 5ba6174..211ff5f 100644
--- a/arch/arm/dts/imx53.dtsi
+++ b/arch/arm/dts/imx53.dtsi
@@ -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";
@@ -283,5 +285,140 @@
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>;
+ };
+ };
+ };
};
};
diff --git a/arch/arm/dts/imx6q.dtsi b/arch/arm/dts/imx6q.dtsi
index d038f41..71543a4 100644
--- a/arch/arm/dts/imx6q.dtsi
+++ b/arch/arm/dts/imx6q.dtsi
@@ -9,6 +9,7 @@
/ {
aliases {
ipu1 = &ipu2;
+ video1 = &ipu2;
spi4 = &ecspi5;
};
diff --git a/arch/arm/dts/imx6qdl.dtsi b/arch/arm/dts/imx6qdl.dtsi
index c0a9478..83eeb5c 100644
--- a/arch/arm/dts/imx6qdl.dtsi
+++ b/arch/arm/dts/imx6qdl.dtsi
@@ -33,6 +33,7 @@
i2c1 = &i2c2;
i2c2 = &i2c3;
ipu0 = &ipu1;
+ video0 = &ipu1;
mmc0 = &usdhc1;
mmc1 = &usdhc2;
mmc2 = &usdhc3;
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index 41a9b0f..6392cb0 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -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
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 7f5b633..8e9bb63 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -289,9 +289,14 @@
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_wdog *)SUNXI_R_WDOG_BASE;
+#else
static const struct sunxi_wdog *wdog =
- ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->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);
diff --git a/board/beckhoff/mx53cx9020/Makefile b/board/beckhoff/mx53cx9020/Makefile
index 423a553..7f15fc5 100644
--- a/board/beckhoff/mx53cx9020/Makefile
+++ b/board/beckhoff/mx53cx9020/Makefile
@@ -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
diff --git a/board/beckhoff/mx53cx9020/mx53cx9020.c b/board/beckhoff/mx53cx9020/mx53cx9020.c
index 79d8a62..9450d92 100644
--- a/board/beckhoff/mx53cx9020/mx53cx9020.c
+++ b/board/beckhoff/mx53cx9020/mx53cx9020.c
@@ -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 @@
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_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_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 @@
}
#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 @@
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;
}
diff --git a/board/beckhoff/mx53cx9020/mx53cx9020_video.c b/board/beckhoff/mx53cx9020/mx53cx9020_video.c
index 4055bcc..bf47290 100644
--- a/board/beckhoff/mx53cx9020/mx53cx9020_video.c
+++ b/board/beckhoff/mx53cx9020/mx53cx9020_video.c
@@ -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;
-}
diff --git a/board/wandboard/wandboard.c b/board/wandboard/wandboard.c
index 69fbc8b..9d7a94f 100644
--- a/board/wandboard/wandboard.c
+++ b/board/wandboard/wandboard.c
@@ -46,6 +46,15 @@
#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 @@
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();
diff --git a/common/splash_source.c b/common/splash_source.c
index 62763b9..8f276a3 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -303,8 +303,12 @@
{
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,35 +339,50 @@
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;
- }
-
- 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;
+ /* 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;
}
- /* Align data offset to 4-byte boundrary */
- fit_size = fdt_totalsize(fit_header);
- fit_size = (fit_size + 3) & ~3;
+ 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 = (location->offset + fit_size + splash_offset);
- res = splash_storage_read_raw(location, bmp_load_addr , splash_size);
- if (res < 0)
- 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;
+ }
return 0;
}
diff --git a/configs/beelink_gs1_defconfig b/configs/beelink_gs1_defconfig
index ef4dd29..437e2d9 100644
--- a/configs/beelink_gs1_defconfig
+++ b/configs/beelink_gs1_defconfig
@@ -7,6 +7,7 @@
# 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
diff --git a/configs/mx53cx9020_defconfig b/configs/mx53cx9020_defconfig
index 90ea9a6..b809066 100644
--- a/configs/mx53cx9020_defconfig
+++ b/configs/mx53cx9020_defconfig
@@ -24,13 +24,14 @@
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
diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig
index d3ed3c4..0fda6fc 100644
--- a/configs/mx6sabresd_defconfig
+++ b/configs/mx6sabresd_defconfig
@@ -4,13 +4,13 @@
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_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
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index ad94d58..90edbd9 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -4,6 +4,7 @@
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_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
diff --git a/configs/teres_i_defconfig b/configs/teres_i_defconfig
index 421a8d3..1b57a48 100644
--- a/configs/teres_i_defconfig
+++ b/configs/teres_i_defconfig
@@ -7,6 +7,7 @@
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
diff --git a/doc/README.splashprepare b/doc/README.splashprepare
index f1418de..3cb5b5a 100644
--- a/doc/README.splashprepare
+++ b/doc/README.splashprepare
@@ -26,6 +26,9 @@
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.
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 2156240..095a9bc 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -161,7 +161,10 @@
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
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 5420afb..23119cc 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -482,8 +482,13 @@
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 @@
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 @@
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 @@
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 @@
/*
* 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 @@
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 @@
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)
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 1b7de74..377b267 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -621,31 +621,18 @@
#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(®s->mixctrl) | MIX_CTRL_DDREN, ®s->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;
diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c
index 3e38d4b..29ecac4 100644
--- a/drivers/video/imx/mxc_ipuv3_fb.c
+++ b/drivers/video/imx/mxc_ipuv3_fb.c
@@ -678,13 +678,14 @@
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" },
{ }
};
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index c31303b..af88588 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -529,6 +529,20 @@
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 @@
{
struct udevice *dev = sdev->priv;
- while (*s)
- vidconsole_put_char(dev, *s++);
+ vidconsole_put_string(dev, s);
video_sync(dev->parent, false);
}
diff --git a/include/configs/mx53cx9020.h b/include/configs/mx53cx9020.h
index 9bf5d91..ab61a07 100644
--- a/include/configs/mx53cx9020.h
+++ b/include/configs/mx53cx9020.h
@@ -159,11 +159,7 @@
#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 */
diff --git a/include/video_console.h b/include/video_console.h
index 52a41ac..0936cea 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -215,6 +215,22 @@
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
diff --git a/test/dm/video.c b/test/dm/video.c
index 6be5def..3151ebb 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -97,14 +97,6 @@
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)
{