summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/adc/rockchip-saradc.c2
-rw-r--r--drivers/bootcount/Kconfig10
-rw-r--r--drivers/clk/Makefile2
-rw-r--r--drivers/clk/clk_k210.c (renamed from drivers/clk/clk_kendryte.c)4
-rw-r--r--drivers/i2c/i2c-uclass.c2
-rw-r--r--drivers/misc/atsha204a-i2c.c8
-rw-r--r--drivers/misc/mxc_ocotp.c2
-rw-r--r--drivers/mmc/fsl_esdhc_imx.c25
-rw-r--r--drivers/mmc/rockchip_sdhci.c117
-rw-r--r--drivers/mmc/sdhci.c18
-rw-r--r--drivers/mmc/xenon_sdhci.c7
-rw-r--r--drivers/mtd/nand/raw/mxs_nand.c71
-rw-r--r--drivers/mtd/nand/raw/mxs_nand_dt.c2
-rw-r--r--drivers/mtd/nand/raw/stm32_fmc2_nand.c9
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/pinctrl-k210.c (renamed from drivers/pinctrl/pinctrl-kendryte.c)25
-rw-r--r--drivers/ram/rockchip/sdram_rk3188.c2
-rw-r--r--drivers/ram/rockchip/sdram_rk3288.c2
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_ddr.c25
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_ddr_regs.h6
-rw-r--r--drivers/spi/designware_spi.c20
-rw-r--r--drivers/usb/gadget/dwc2_udc_otg.c5
-rw-r--r--drivers/video/stm32/stm32_ltdc.c11
-rw-r--r--drivers/video/video-uclass.c7
-rw-r--r--drivers/video/video_bmp.c70
25 files changed, 382 insertions, 72 deletions
diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c
index e464d33f226..e0cbab6aa06 100644
--- a/drivers/adc/rockchip-saradc.c
+++ b/drivers/adc/rockchip-saradc.c
@@ -131,7 +131,7 @@ int rockchip_saradc_of_to_plat(struct udevice *dev)
}
priv->data = data;
- uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;;
+ uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;
uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig
index 509d01d41ef..66ce4cc29ba 100644
--- a/drivers/bootcount/Kconfig
+++ b/drivers/bootcount/Kconfig
@@ -68,15 +68,15 @@ config BOOTCOUNT_ENV
"bootcount" is stored in the environment. To prevent a
saveenv on all reboots, the environment variable
"upgrade_available" is used. If "upgrade_available" is
- 0, "bootcount" is always 0, if "upgrade_available" is
- 1 "bootcount" is incremented in the environment.
+ 0, "bootcount" is always 0. If "upgrade_available" is 1,
+ "bootcount" is incremented in the environment.
So the Userspace Application must set the "upgrade_available"
- and "bootcount" variable to 0, if a boot was successfully.
+ and "bootcount" variables to 0, if the system booted successfully.
config BOOTCOUNT_RAM
bool "Boot counter in RAM"
help
- Store the bootcount in DRAM protected against against bit errors
+ Store the bootcount in DRAM protected against bit errors
due to short power loss or holding a system in RESET.
config BOOTCOUNT_I2C
@@ -173,7 +173,7 @@ config BOOTCOUNT_BOOTLIMIT
help
Set the Maximum number of reboot cycles allowed without the boot
counter being cleared.
- If set to 0 do not set a boot limit in the environment.
+ If set to 0, do not set a boot limit in the environment.
config BOOTCOUNT_ALEN
int "I2C address length"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f922a7c323d..bb4eee5d99b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -29,7 +29,7 @@ obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
obj-$(CONFIG_CLK_CDCE9XX) += clk-cdce9xx.o
obj-$(CONFIG_CLK_EXYNOS) += exynos/
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
-obj-$(CONFIG_CLK_K210) += clk_kendryte.o
+obj-$(CONFIG_CLK_K210) += clk_k210.o
obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
obj-$(CONFIG_CLK_MPFS) += microchip/
obj-$(CONFIG_CLK_MVEBU) += mvebu/
diff --git a/drivers/clk/clk_kendryte.c b/drivers/clk/clk_k210.c
index 97efda5b6f0..1961efaa5e7 100644
--- a/drivers/clk/clk_kendryte.c
+++ b/drivers/clk/clk_k210.c
@@ -14,7 +14,7 @@
#include <serial.h>
#include <dt-bindings/clock/k210-sysctl.h>
#include <dt-bindings/mfd/k210-sysctl.h>
-#include <kendryte/pll.h>
+#include <k210/pll.h>
#include <linux/bitfield.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -1271,7 +1271,7 @@ static int k210_clk_probe(struct udevice *dev)
}
static const struct udevice_id k210_clk_ids[] = {
- { .compatible = "kendryte,k210-clk" },
+ { .compatible = "canaan,k210-clk" },
{ },
};
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 5539becc197..335911c46bb 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -280,7 +280,7 @@ static int i2c_probe_chip(struct udevice *bus, uint chip_addr,
if (ops->probe_chip) {
ret = ops->probe_chip(bus, chip_addr, chip_flags);
- if (!ret || ret != -ENOSYS)
+ if (ret != -ENOSYS)
return ret;
}
diff --git a/drivers/misc/atsha204a-i2c.c b/drivers/misc/atsha204a-i2c.c
index 715dabb2799..b89463babb5 100644
--- a/drivers/misc/atsha204a-i2c.c
+++ b/drivers/misc/atsha204a-i2c.c
@@ -240,10 +240,10 @@ int atsha204a_wakeup(struct udevice *dev)
}
debug("success\n");
- break;
+ return 0;
}
- return 0;
+ return -ETIMEDOUT;
}
int atsha204a_idle(struct udevice *dev)
@@ -280,6 +280,7 @@ static int atsha204a_transaction(struct udevice *dev, struct atsha204a_req *req,
}
do {
+ udelay(ATSHA204A_EXECTIME);
res = atsha204a_recv_resp(dev, resp);
if (!res || res == -EMSGSIZE || res == -EBADMSG)
break;
@@ -287,7 +288,6 @@ static int atsha204a_transaction(struct udevice *dev, struct atsha204a_req *req,
debug("ATSHA204A transaction polling for response "
"(timeout = %d)\n", timeout);
- udelay(ATSHA204A_EXECTIME);
timeout -= ATSHA204A_EXECTIME;
} while (timeout > 0);
@@ -388,7 +388,7 @@ static int atsha204a_of_to_plat(struct udevice *dev)
fdt_addr_t *priv = dev_get_priv(dev);
fdt_addr_t addr;
- addr = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), "reg");
+ addr = dev_read_addr(dev);
if (addr == FDT_ADDR_T_NONE) {
debug("Can't get ATSHA204A I2C base address\n");
return -ENXIO;
diff --git a/drivers/misc/mxc_ocotp.c b/drivers/misc/mxc_ocotp.c
index b1893a5c7eb..8ee18f29d9b 100644
--- a/drivers/misc/mxc_ocotp.c
+++ b/drivers/misc/mxc_ocotp.c
@@ -6,7 +6,7 @@
* Based on Dirk Behme's
* https://github.com/dirkbehme/u-boot-imx6/blob/28b17e9/drivers/misc/imx_otp.c,
* which is based on Freescale's
- * http://git.freescale.com/git/cgit.cgi/imx/uboot-imx.git/tree/drivers/misc/imx_otp.c?h=imx_v2009.08_1.1.0&id=9aa74e6,
+ * https://source.codeaurora.org/external/imx/uboot-imx/tree/drivers/misc/imx_otp.c?id=9aa74e6,
* which is:
* Copyright (C) 2011 Freescale Semiconductor, Inc.
*/
diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
index 697e3c641d0..02208a5ade4 100644
--- a/drivers/mmc/fsl_esdhc_imx.c
+++ b/drivers/mmc/fsl_esdhc_imx.c
@@ -827,13 +827,16 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
struct mmc *mmc = &plat->mmc;
u32 irqstaten = esdhc_read32(&regs->irqstaten);
u32 irqsigen = esdhc_read32(&regs->irqsigen);
- int i, ret = -ETIMEDOUT;
- u32 val, mixctrl;
+ int i, err, ret = -ETIMEDOUT;
+ u32 val, mixctrl, tmp;
/* clock tuning is not needed for upto 52MHz */
if (mmc->clock <= 52000000)
return 0;
+ /* make sure the card clock keep on */
+ esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+
/* This is readw/writew SDHCI_HOST_CONTROL2 when tuning */
if (priv->flags & ESDHC_FLAG_STD_TUNING) {
val = esdhc_read32(&regs->autoc12err);
@@ -893,6 +896,12 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
esdhc_stop_tuning(mmc);
+ /* change to default setting, let host control the card clock */
+ esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+ err = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100);
+ if (err)
+ dev_warn(dev, "card clock not gate off as expect.\n");
+
return ret;
}
#endif
@@ -1567,14 +1576,24 @@ static int __maybe_unused fsl_esdhc_set_enhanced_strobe(struct udevice *dev)
static int fsl_esdhc_wait_dat0(struct udevice *dev, int state,
int timeout_us)
{
- int ret;
+ int ret, err;
u32 tmp;
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
struct fsl_esdhc *regs = priv->esdhc_regs;
+ /* make sure the card clock keep on */
+ esdhc_setbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+
ret = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp,
!!(tmp & PRSSTAT_DAT0) == !!state,
timeout_us);
+
+ /* change to default setting, let host control the card clock */
+ esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
+ err = readx_poll_timeout(esdhc_read32, &regs->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100);
+ if (err)
+ dev_warn(dev, "card clock not gate off as expect.\n");
+
return ret;
}
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index b91df05de4f..f3f9d83ba36 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -22,6 +22,8 @@
#include <asm/arch-rockchip/clock.h>
#include <asm/arch-rockchip/hardware.h>
+/* DWCMSHC specific Mode Select value */
+#define DWCMSHC_CTRL_HS400 0x7
/* 400KHz is max freq for card ID etc. Use that as min */
#define EMMC_MIN_FREQ 400000
#define KHz (1000)
@@ -42,6 +44,17 @@
((((x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\
PHYCTRL_DLLRDY_DONE)
+#define ARASAN_VENDOR_REGISTER 0x78
+#define ARASAN_VENDOR_ENHANCED_STROBE BIT(0)
+
+/* DWC IP vendor area 1 pointer */
+#define DWCMSHC_P_VENDOR_AREA1 0xe8
+#define DWCMSHC_AREA1_MASK GENMASK(11, 0)
+/* Offset inside the vendor area 1 */
+#define DWCMSHC_EMMC_CONTROL 0x2c
+#define DWCMSHC_CARD_IS_EMMC BIT(0)
+#define DWCMSHC_ENHANCED_STROBE BIT(8)
+
/* Rockchip specific Registers */
#define DWCMSHC_EMMC_DLL_CTRL 0x800
#define DWCMSHC_EMMC_DLL_CTRL_RESET BIT(1)
@@ -57,8 +70,14 @@
#define DWCMSHC_EMMC_DLL_INC_VALUE 2
#define DWCMSHC_EMMC_DLL_INC 8
#define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
-#define DLL_TXCLK_TAPNUM_DEFAULT 0x10
-#define DLL_STRBIN_TAPNUM_DEFAULT 0x3
+#define DLL_TXCLK_TAPNUM_DEFAULT 0xA
+
+#define DLL_STRBIN_TAPNUM_DEFAULT 0x8
+#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24)
+#define DLL_STRBIN_DELAY_NUM_SEL BIT(26)
+#define DLL_STRBIN_DELAY_NUM_OFFSET 16
+#define DLL_STRBIN_DELAY_NUM_DEFAULT 0x16
+
#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
#define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
@@ -117,6 +136,19 @@ struct sdhci_data {
* Return: 0 if successful, -ve on error
*/
int (*set_ios_post)(struct sdhci_host *host);
+
+ /**
+ * set_enhanced_strobe() - Set HS400 Enhanced Strobe config
+ *
+ * This is the set_enhanced_strobe() SDHCI operation that should
+ * be used for the hardware this driver data is associated with.
+ * Normally, this is used to set any host-specific configuration
+ * necessary for HS400 ES.
+ *
+ * @host: SDHCI host structure
+ * Return: 0 if successful, -ve on error
+ */
+ int (*set_enhanced_strobe)(struct sdhci_host *host);
};
static int rk3399_emmc_phy_init(struct udevice *dev)
@@ -206,6 +238,21 @@ static int rk3399_emmc_get_phy(struct udevice *dev)
return 0;
}
+static int rk3399_sdhci_set_enhanced_strobe(struct sdhci_host *host)
+{
+ struct mmc *mmc = host->mmc;
+ u32 vendor;
+
+ vendor = sdhci_readl(host, ARASAN_VENDOR_REGISTER);
+ if (mmc->selected_mode == MMC_HS_400_ES)
+ vendor |= ARASAN_VENDOR_ENHANCED_STROBE;
+ else
+ vendor &= ~ARASAN_VENDOR_ENHANCED_STROBE;
+ sdhci_writel(host, vendor, ARASAN_VENDOR_REGISTER);
+
+ return 0;
+}
+
static void rk3399_sdhci_set_control_reg(struct sdhci_host *host)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
@@ -217,6 +264,15 @@ static void rk3399_sdhci_set_control_reg(struct sdhci_host *host)
rk3399_emmc_phy_power_off(priv->phy);
sdhci_set_control_reg(host);
+
+ /*
+ * Reinitializing the device tries to set it to lower-speed modes
+ * first, which fails if the Enhanced Strobe bit is set, making
+ * the device impossible to use. Set the correct value here to
+ * let reinitialization attempts succeed.
+ */
+ if (CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT))
+ rk3399_sdhci_set_enhanced_strobe(host);
};
static int rk3399_sdhci_set_ios_post(struct sdhci_host *host)
@@ -287,7 +343,8 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
extra = DWCMSHC_EMMC_DLL_DLYENA |
- DLL_STRBIN_TAPNUM_DEFAULT;
+ DLL_STRBIN_TAPNUM_DEFAULT |
+ DLL_STRBIN_TAPNUM_FROM_SW;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
} else {
/* reset the clock phase when the frequency is lower than 100MHz */
@@ -295,7 +352,15 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
+ /*
+ * Before switching to hs400es mode, the driver will enable
+ * enhanced strobe first. PHY needs to configure the parameters
+ * of enhanced strobe first.
+ */
+ extra = DWCMSHC_EMMC_DLL_DLYENA |
+ DLL_STRBIN_DELAY_NUM_SEL |
+ DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET;
+ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
}
return 0;
@@ -306,11 +371,30 @@ static int rk3568_emmc_get_phy(struct udevice *dev)
return 0;
}
+static int rk3568_sdhci_set_enhanced_strobe(struct sdhci_host *host)
+{
+ struct mmc *mmc = host->mmc;
+ u32 vendor;
+ int reg;
+
+ reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
+ + DWCMSHC_EMMC_CONTROL;
+
+ vendor = sdhci_readl(host, reg);
+ if (mmc->selected_mode == MMC_HS_400_ES)
+ vendor |= DWCMSHC_ENHANCED_STROBE;
+ else
+ vendor &= ~DWCMSHC_ENHANCED_STROBE;
+ sdhci_writel(host, vendor, reg);
+
+ return 0;
+}
+
static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
{
struct mmc *mmc = host->mmc;
uint clock = mmc->tran_speed;
- u32 reg;
+ u32 reg, vendor_reg;
if (!clock)
clock = mmc->clock;
@@ -320,8 +404,15 @@ static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) {
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
reg &= ~SDHCI_CTRL_UHS_MASK;
- reg |= SDHCI_CTRL_HS400;
+ reg |= DWCMSHC_CTRL_HS400;
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
+
+ vendor_reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
+ + DWCMSHC_EMMC_CONTROL;
+ /* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */
+ reg = sdhci_readw(host, vendor_reg);
+ reg |= DWCMSHC_CARD_IS_EMMC;
+ sdhci_writew(host, reg, vendor_reg);
} else {
sdhci_set_uhs_timing(host);
}
@@ -409,10 +500,22 @@ static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
return ret;
}
+static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host)
+{
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+
+ if (data->set_enhanced_strobe)
+ return data->set_enhanced_strobe(host);
+
+ return -ENOTSUPP;
+}
+
static struct sdhci_ops rockchip_sdhci_ops = {
.set_ios_post = rockchip_sdhci_set_ios_post,
.platform_execute_tuning = &rockchip_sdhci_execute_tuning,
.set_control_reg = rockchip_sdhci_set_control_reg,
+ .set_enhanced_strobe = rockchip_sdhci_set_enhanced_strobe,
};
static int rockchip_sdhci_probe(struct udevice *dev)
@@ -495,12 +598,14 @@ static const struct sdhci_data rk3399_data = {
.emmc_phy_init = rk3399_emmc_phy_init,
.set_control_reg = rk3399_sdhci_set_control_reg,
.set_ios_post = rk3399_sdhci_set_ios_post,
+ .set_enhanced_strobe = rk3399_sdhci_set_enhanced_strobe,
};
static const struct sdhci_data rk3568_data = {
.get_phy = rk3568_emmc_get_phy,
.emmc_phy_init = rk3568_emmc_phy_init,
.set_ios_post = rk3568_sdhci_set_ios_post,
+ .set_enhanced_strobe = rk3568_sdhci_set_enhanced_strobe,
};
static const struct udevice_id sdhci_ids[] = {
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 766e4a6b0c5..bf989a594f7 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -513,6 +513,7 @@ void sdhci_set_uhs_timing(struct sdhci_host *host)
reg |= SDHCI_CTRL_UHS_SDR104;
break;
case MMC_HS_400:
+ case MMC_HS_400_ES:
reg |= SDHCI_CTRL_HS400;
break;
default:
@@ -666,6 +667,7 @@ static int sdhci_set_ios(struct mmc *mmc)
mmc->selected_mode == MMC_DDR_52 ||
mmc->selected_mode == MMC_HS_200 ||
mmc->selected_mode == MMC_HS_400 ||
+ mmc->selected_mode == MMC_HS_400_ES ||
mmc->selected_mode == UHS_SDR25 ||
mmc->selected_mode == UHS_SDR50 ||
mmc->selected_mode == UHS_SDR104 ||
@@ -799,6 +801,19 @@ static int sdhci_wait_dat0(struct udevice *dev, int state,
return -ETIMEDOUT;
}
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+static int sdhci_set_enhanced_strobe(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+ struct sdhci_host *host = mmc->priv;
+
+ if (host->ops && host->ops->set_enhanced_strobe)
+ return host->ops->set_enhanced_strobe(host);
+
+ return -ENOTSUPP;
+}
+#endif
+
const struct dm_mmc_ops sdhci_ops = {
.send_cmd = sdhci_send_command,
.set_ios = sdhci_set_ios,
@@ -808,6 +823,9 @@ const struct dm_mmc_ops sdhci_ops = {
.execute_tuning = sdhci_execute_tuning,
#endif
.wait_dat0 = sdhci_wait_dat0,
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+ .set_enhanced_strobe = sdhci_set_enhanced_strobe,
+#endif
};
#else
static const struct mmc_ops sdhci_ops = {
diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c
index e292f2903d8..2f8805096c1 100644
--- a/drivers/mmc/xenon_sdhci.c
+++ b/drivers/mmc/xenon_sdhci.c
@@ -439,6 +439,8 @@ static const struct sdhci_ops xenon_sdhci_ops = {
.set_ios_post = xenon_sdhci_set_ios_post
};
+static struct dm_mmc_ops xenon_mmc_ops;
+
static int xenon_sdhci_probe(struct udevice *dev)
{
struct xenon_sdhci_plat *plat = dev_get_plat(dev);
@@ -452,6 +454,9 @@ static int xenon_sdhci_probe(struct udevice *dev)
host->mmc->dev = dev;
upriv->mmc = host->mmc;
+ xenon_mmc_ops = sdhci_ops;
+ xenon_mmc_ops.wait_dat0 = NULL;
+
/* Set quirks */
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR;
@@ -568,7 +573,7 @@ U_BOOT_DRIVER(xenon_sdhci_drv) = {
.id = UCLASS_MMC,
.of_match = xenon_sdhci_ids,
.of_to_plat = xenon_sdhci_of_to_plat,
- .ops = &sdhci_ops,
+ .ops = &xenon_mmc_ops,
.bind = xenon_sdhci_bind,
.probe = xenon_sdhci_probe,
.remove = xenon_sdhci_remove,
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 748056a43e6..ee5d7fde9ce 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -195,6 +195,7 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
unsigned int block_mark_bit_offset;
+ int corr, ds_corr;
/* The default for the length of Galois Field. */
geo->gf_len = 13;
@@ -225,6 +226,17 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
nand_info->max_ecc_strength_supported);
+ /* check ecc strength, same as nand_ecc_is_strong_enough() did*/
+ if (chip->ecc_step_ds) {
+ corr = mtd->writesize * geo->ecc_strength /
+ geo->ecc_chunkn_size;
+ ds_corr = mtd->writesize * chip->ecc_strength_ds /
+ chip->ecc_step_ds;
+ if (corr < ds_corr ||
+ geo->ecc_strength < chip->ecc_strength_ds)
+ return -EINVAL;
+ }
+
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+ MXS_NAND_METADATA_SIZE * 8);
@@ -1111,6 +1123,7 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+ int err;
if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
printf("unsupported NAND chip, minimum ecc required %d\n"
@@ -1118,19 +1131,57 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
return -EINVAL;
}
- if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
- mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) {
- dev_warn(mtd->dev, "use legacy bch geometry\n");
- return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+ /* use the legacy bch setting by default */
+ if ((!nand_info->use_minimum_ecc && mtd->oobsize < 1024) ||
+ !(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) {
+ dev_dbg(mtd->dev, "use legacy bch geometry\n");
+ err = mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+ if (!err)
+ return 0;
}
- if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
- return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+ /* for large oob nand */
+ if (mtd->oobsize > 1024) {
+ dev_dbg(mtd->dev, "use large oob bch geometry\n");
+ err = mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+ if (!err)
+ return 0;
+ }
- return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
- chip->ecc_strength_ds, chip->ecc_step_ds);
+ /* otherwise use the minimum ecc nand chips required */
+ dev_dbg(mtd->dev, "use minimum ecc bch geometry\n");
+ err = mxs_nand_calc_ecc_layout_by_info(geo, mtd, chip->ecc_strength_ds,
+ chip->ecc_step_ds);
- return 0;
+ if (err)
+ dev_err(mtd->dev, "none of the bch geometry setting works\n");
+
+ return err;
+}
+
+void mxs_nand_dump_geo(struct mtd_info *mtd)
+{
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+ struct bch_geometry *geo = &nand_info->bch_geometry;
+
+ dev_dbg(mtd->dev, "BCH Geometry :\n"
+ "GF Length\t\t: %u\n"
+ "ECC Strength\t\t: %u\n"
+ "ECC for Meta\t\t: %u\n"
+ "ECC Chunk0 Size\t\t: %u\n"
+ "ECC Chunkn Size\t\t: %u\n"
+ "ECC Chunk Count\t\t: %u\n"
+ "Block Mark Byte Offset\t: %u\n"
+ "Block Mark Bit Offset\t: %u\n",
+ geo->gf_len,
+ geo->ecc_strength,
+ geo->ecc_for_meta,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
+ geo->ecc_chunk_count,
+ geo->block_mark_byte_offset,
+ geo->block_mark_bit_offset);
}
/*
@@ -1159,6 +1210,8 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
if (ret)
return ret;
+ mxs_nand_dump_geo(mtd);
+
/* Configure BCH and set NFC geometry */
mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
index 878796d5552..b9833a646f0 100644
--- a/drivers/mtd/nand/raw/mxs_nand_dt.c
+++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
@@ -92,8 +92,6 @@ static int mxs_nand_dt_probe(struct udevice *dev)
info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc");
- info->legacy_bch_geometry = dev_read_bool(dev, "fsl,legacy-bch-geometry");
-
if (IS_ENABLED(CONFIG_CLK) && IS_ENABLED(CONFIG_IMX8)) {
/* Assigned clock already set clock */
struct clk gpmi_clk;
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index eee65949d77..fb3279b405e 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -12,6 +12,7 @@
#include <log.h>
#include <nand.h>
#include <reset.h>
+#include <asm/gpio.h>
#include <dm/device_compat.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
@@ -149,6 +150,7 @@ struct stm32_fmc2_timings {
struct stm32_fmc2_nand {
struct nand_chip chip;
struct stm32_fmc2_timings timings;
+ struct gpio_desc wp_gpio;
int ncs;
int cs_used[FMC2_MAX_CE];
};
@@ -824,6 +826,9 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node)
nand->cs_used[i] = cs[i];
}
+ gpio_request_by_name_nodev(node, "wp-gpios", 0, &nand->wp_gpio,
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+
nand->chip.flash_node = node;
return 0;
@@ -972,6 +977,10 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev)
chip->ecc.size = FMC2_ECC_STEP_SIZE;
chip->ecc.strength = FMC2_ECC_BCH8;
+ /* Disable Write Protect */
+ if (dm_gpio_is_valid(&nand->wp_gpio))
+ dm_gpio_set_value(&nand->wp_gpio, 0);
+
ret = nand_scan_ident(mtd, nand->ncs, NULL);
if (ret)
return ret;
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index ddddd13433c..030c38f5cc1 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_PINCTRL_PIC32) += pinctrl_pic32.o
obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/
-obj-$(CONFIG_PINCTRL_K210) += pinctrl-kendryte.o
+obj-$(CONFIG_PINCTRL_K210) += pinctrl-k210.o
obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_MTK) += mediatek/
obj-$(CONFIG_PINCTRL_MSCC) += mscc/
diff --git a/drivers/pinctrl/pinctrl-kendryte.c b/drivers/pinctrl/pinctrl-k210.c
index 09d51ca6769..13f0a342686 100644
--- a/drivers/pinctrl/pinctrl-kendryte.c
+++ b/drivers/pinctrl/pinctrl-k210.c
@@ -511,7 +511,7 @@ static int k210_pc_get_drive(unsigned max_strength_ua)
{
int i;
- for (i = K210_PC_DRIVE_MAX; i; i--)
+ for (i = K210_PC_DRIVE_MAX; i >= 0; i--)
if (k210_pc_drive_strength[i] < max_strength_ua)
return i;
@@ -536,7 +536,7 @@ static int k210_pc_pinconf_set(struct udevice *dev, unsigned pin_selector,
break;
case PIN_CONFIG_BIAS_PULL_UP:
if (argument)
- val |= K210_PC_PD;
+ val |= K210_PC_PU;
else
return -EINVAL;
break;
@@ -679,6 +679,7 @@ static int k210_pc_probe(struct udevice *dev)
{
int ret, i, j;
struct k210_pc_priv *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args args;
priv->fpioa = dev_read_addr_ptr(dev);
if (!priv->fpioa)
@@ -692,15 +693,23 @@ static int k210_pc_probe(struct udevice *dev)
if (ret && ret != -ENOSYS && ret != -ENOTSUPP)
goto err;
- priv->sysctl = syscon_regmap_lookup_by_phandle(dev, "kendryte,sysctl");
+ ret = dev_read_phandle_with_args(dev, "canaan,k210-sysctl-power",
+ NULL, 1, 0, &args);
+ if (ret)
+ goto err;
+
+ if (args.args_count != 1) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ priv->sysctl = syscon_node_to_regmap(args.node);
if (IS_ERR(priv->sysctl)) {
- ret = -ENODEV;
+ ret = PTR_ERR(priv->sysctl);
goto err;
}
- ret = dev_read_u32(dev, "kendryte,power-offset", &priv->power_offset);
- if (ret)
- goto err;
+ priv->power_offset = args.args[0];
debug("%s: fpioa = %p sysctl = %p power offset = %x\n", __func__,
priv->fpioa, (void *)priv->sysctl->ranges[0].start,
@@ -726,7 +735,7 @@ err:
}
static const struct udevice_id k210_pc_ids[] = {
- { .compatible = "kendryte,k210-fpioa" },
+ { .compatible = "canaan,k210-fpioa" },
{ }
};
diff --git a/drivers/ram/rockchip/sdram_rk3188.c b/drivers/ram/rockchip/sdram_rk3188.c
index d9ed8adfcfd..be8ba4464d4 100644
--- a/drivers/ram/rockchip/sdram_rk3188.c
+++ b/drivers/ram/rockchip/sdram_rk3188.c
@@ -762,7 +762,7 @@ static int sdram_init(struct dram_info *dram,
* CS1, n=2
* CS0 & CS1, n = 3
*/
- sdram_params->ch[channel].rank = 2,
+ sdram_params->ch[channel].rank = 2;
clrsetbits_le32(&publ->pgcr, 0xF << 18,
(sdram_params->ch[channel].rank | 1) << 18);
diff --git a/drivers/ram/rockchip/sdram_rk3288.c b/drivers/ram/rockchip/sdram_rk3288.c
index f3e4a2808ab..227a3cc6a88 100644
--- a/drivers/ram/rockchip/sdram_rk3288.c
+++ b/drivers/ram/rockchip/sdram_rk3288.c
@@ -862,7 +862,7 @@ static int sdram_init(struct dram_info *dram,
* CS1, n=2
* CS0 & CS1, n = 3
*/
- sdram_params->ch[channel].rank = 2,
+ sdram_params->ch[channel].rank = 2;
clrsetbits_le32(&publ->pgcr, 0xF << 18,
(sdram_params->ch[channel].rank | 1) << 18);
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c
index 4d78aa5cb13..528a171b454 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ddr.c
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c
@@ -27,6 +27,8 @@
#define RCC_DDRITFCR_DPHYAPBRST (BIT(17))
#define RCC_DDRITFCR_DPHYRST (BIT(18))
#define RCC_DDRITFCR_DPHYCTLRST (BIT(19))
+#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20)
+#define RCC_DDRITFCR_DDRCKMOD_ASR BIT(20)
struct reg_desc {
const char *name;
@@ -651,6 +653,26 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
wait_sw_done_ack(ctl);
}
+static void stm32mp1_asr_enable(struct ddr_info *priv)
+{
+ struct stm32mp1_ddrctl *ctl = priv->ctl;
+
+ clrsetbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCKMOD_MASK,
+ RCC_DDRITFCR_DDRCKMOD_ASR);
+
+ start_sw_done(ctl);
+
+ setbits_le32(&ctl->hwlpctl, DDRCTRL_HWLPCTL_HW_LP_EN);
+ writel(DDRCTRL_PWRTMG_POWERDOWN_TO_X32(0x10) |
+ DDRCTRL_PWRTMG_SELFREF_TO_X32(0x01),
+ &ctl->pwrtmg);
+ setbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE);
+ setbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_EN);
+
+ setbits_le32(&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
+ wait_sw_done_ack(ctl);
+}
+
/* board-specific DDR power initializations. */
__weak int board_ddr_power_init(enum ddr_type ddr_type)
{
@@ -822,6 +844,9 @@ start:
stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3,
config->c_reg.pwrctl);
+/* Enable auto-self-refresh, which saves a bit of power at runtime. */
+ stm32mp1_asr_enable(priv);
+
/* enable uMCTL2 AXI port 0 and 1 */
setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h b/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
index f1a26e31f6c..42be1ba57c7 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
@@ -265,8 +265,14 @@ struct stm32mp1_ddrphy {
#define DDRCTRL_PWRCTL_SELFREF_EN BIT(0)
#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1)
+#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3)
#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5)
+#define DDRCTRL_PWRTMG_SELFREF_TO_X32(n) (((n) & 0xff) << 16)
+#define DDRCTRL_PWRTMG_POWERDOWN_TO_X32(n) ((n) & 0x1f)
+
+#define DDRCTRL_HWLPCTL_HW_LP_EN BIT(0)
+
#define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0)
#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK GENMASK(27, 16)
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index fc22f540fe6..47bea0b376a 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -194,6 +194,20 @@ static int dw_spi_apb_init(struct udevice *bus, struct dw_spi_priv *priv)
return 0;
}
+static int dw_spi_apb_k210_init(struct udevice *bus, struct dw_spi_priv *priv)
+{
+ /*
+ * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is
+ * documented to have a 32 word deep TX and RX FIFO, which
+ * spi_hw_init() detects. However, when the RX FIFO is filled up to
+ * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid
+ * this problem by force setting fifo_len to 31.
+ */
+ priv->fifo_len = 31;
+
+ return dw_spi_apb_init(bus, priv);
+}
+
static int dw_spi_dwc_init(struct udevice *bus, struct dw_spi_priv *priv)
{
priv->max_xfer = 32;
@@ -252,7 +266,7 @@ static int dw_spi_of_to_plat(struct udevice *bus)
static void spi_hw_init(struct udevice *bus, struct dw_spi_priv *priv)
{
dw_write(priv, DW_SPI_SSIENR, 0);
- dw_write(priv, DW_SPI_IMR, 0xff);
+ dw_write(priv, DW_SPI_IMR, 0);
dw_write(priv, DW_SPI_SSIENR, 1);
/*
@@ -758,8 +772,8 @@ static const struct udevice_id dw_spi_ids[] = {
*/
{ .compatible = "altr,socfpga-spi", .data = (ulong)dw_spi_apb_init },
{ .compatible = "altr,socfpga-arria10-spi", .data = (ulong)dw_spi_apb_init },
- { .compatible = "canaan,kendryte-k210-spi", .data = (ulong)dw_spi_apb_init },
- { .compatible = "canaan,kendryte-k210-ssi", .data = (ulong)dw_spi_dwc_init },
+ { .compatible = "canaan,k210-spi", .data = (ulong)dw_spi_apb_k210_init},
+ { .compatible = "canaan,k210-ssi", .data = (ulong)dw_spi_dwc_init },
{ .compatible = "intel,stratix10-spi", .data = (ulong)dw_spi_apb_init },
{ .compatible = "intel,agilex-spi", .data = (ulong)dw_spi_apb_init },
{ .compatible = "mscc,ocelot-spi", .data = (ulong)dw_spi_apb_init },
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 2748270ad6a..77988f78ab3 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -996,8 +996,9 @@ static int dwc2_udc_otg_of_to_plat(struct udevice *dev)
plat->rx_fifo_sz = dev_read_u32_default(dev, "g-rx-fifo-size", 0);
plat->np_tx_fifo_sz = dev_read_u32_default(dev, "g-np-tx-fifo-size", 0);
- plat->tx_fifo_sz_nb =
- dev_read_size(dev, "g-tx-fifo-size") / sizeof(u32);
+ ret = dev_read_size(dev, "g-tx-fifo-size");
+ if (ret > 0)
+ plat->tx_fifo_sz_nb = ret / sizeof(u32);
if (plat->tx_fifo_sz_nb > DWC2_MAX_HW_ENDPOINTS)
plat->tx_fifo_sz_nb = DWC2_MAX_HW_ENDPOINTS;
if (plat->tx_fifo_sz_nb) {
diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c
index 87e5fd54d9a..e741e74739c 100644
--- a/drivers/video/stm32/stm32_ltdc.c
+++ b/drivers/video/stm32/stm32_ltdc.c
@@ -338,6 +338,7 @@ static int stm32_ltdc_probe(struct udevice *dev)
struct display_timing timings;
struct clk pclk;
struct reset_ctl rst;
+ ulong rate;
int ret;
priv->regs = (void *)dev_read_addr(dev);
@@ -375,13 +376,13 @@ static int stm32_ltdc_probe(struct udevice *dev)
}
}
- ret = clk_set_rate(&pclk, timings.pixelclock.typ);
- if (ret)
- dev_warn(dev, "fail to set pixel clock %d hz\n",
- timings.pixelclock.typ);
+ rate = clk_set_rate(&pclk, timings.pixelclock.typ);
+ if (IS_ERR_VALUE(rate))
+ dev_warn(dev, "fail to set pixel clock %d hz, ret=%ld\n",
+ timings.pixelclock.typ, rate);
dev_dbg(dev, "Set pixel clock req %d hz get %ld hz\n",
- timings.pixelclock.typ, clk_get_rate(&pclk));
+ timings.pixelclock.typ, rate);
ret = reset_get_by_index(dev, 0, &rst);
if (ret) {
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 5215114b2d8..9ae032e9c2d 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -33,7 +33,8 @@
* information represents the requires size and alignment of the frame buffer
* for the device. The values can be an over-estimate but cannot be too
* small. The actual values will be suppled (in the same manner) by the bind()
- * method after relocation.
+ * method after relocation. Additionally driver can allocate frame buffer
+ * itself by setting plat->base.
*
* This information is then picked up by video_reserve() which works out how
* much memory is needed for all devices. This is allocated between
@@ -78,6 +79,10 @@ static ulong alloc_fb(struct udevice *dev, ulong *addrp)
if (!plat->size)
return 0;
+ /* Allow drivers to allocate the frame buffer themselves */
+ if (plat->base)
+ return 0;
+
align = plat->align ? plat->align : 1 << 20;
base = *addrp - plat->size;
base &= ~(align - 1);
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index c8c3fd3549d..4d2d961696a 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -31,6 +31,18 @@ static uint get_bmp_col_16bpp(struct bmp_color_table_entry cte)
}
/**
+ * get_bmp_col_x2r10g10b10() - Convert a colour-table entry into a x2r10g10b10 pixel value
+ *
+ * Return: value to write to the x2r10g10b10 frame buffer for this palette entry
+ */
+static u32 get_bmp_col_x2r10g10b10(struct bmp_color_table_entry *cte)
+{
+ return ((cte->red << 22U) |
+ (cte->green << 12U) |
+ (cte->blue << 2U));
+}
+
+/**
* write_pix8() - Write a pixel from a BMP image into the framebuffer
*
* This handles frame buffers with 8, 16, 24 or 32 bits per pixel
@@ -42,8 +54,8 @@ static uint get_bmp_col_16bpp(struct bmp_color_table_entry cte)
* which is either written directly (bpix == 8) or used to look up the
* palette to get a colour to write
*/
-static void write_pix8(u8 *fb, uint bpix, struct bmp_color_table_entry *palette,
- u8 *bmap)
+static void write_pix8(u8 *fb, uint bpix, enum video_format eformat,
+ struct bmp_color_table_entry *palette, u8 *bmap)
{
if (bpix == 8) {
*fb++ = *bmap;
@@ -57,6 +69,8 @@ static void write_pix8(u8 *fb, uint bpix, struct bmp_color_table_entry *palette,
*fb++ = cte->red;
*fb++ = cte->green;
*fb++ = cte->blue;
+ } else if (eformat == VIDEO_X2R10G10B10) {
+ *(u32 *)fb = get_bmp_col_x2r10g10b10(cte);
} else {
*fb++ = cte->blue;
*fb++ = cte->green;
@@ -66,28 +80,29 @@ static void write_pix8(u8 *fb, uint bpix, struct bmp_color_table_entry *palette,
}
}
-static void draw_unencoded_bitmap(u8 **fbp, uint bpix, uchar *bmap,
+static void draw_unencoded_bitmap(u8 **fbp, uint bpix,
+ enum video_format eformat, uchar *bmap,
struct bmp_color_table_entry *palette,
int cnt)
{
u8 *fb = *fbp;
while (cnt > 0) {
- write_pix8(fb, bpix, palette, bmap++);
+ write_pix8(fb, bpix, eformat, palette, bmap++);
fb += bpix / 8;
cnt--;
}
*fbp = fb;
}
-static void draw_encoded_bitmap(u8 **fbp, uint bpix,
+static void draw_encoded_bitmap(u8 **fbp, uint bpix, enum video_format eformat,
struct bmp_color_table_entry *palette, u8 *bmap,
int cnt)
{
u8 *fb = *fbp;
while (cnt > 0) {
- write_pix8(fb, bpix, palette, bmap);
+ write_pix8(fb, bpix, eformat, palette, bmap);
fb += bpix / 8;
cnt--;
}
@@ -106,6 +121,7 @@ static void video_display_rle8_bitmap(struct udevice *dev,
int x, y;
int decode = 1;
uint bytes_per_pixel = bpix / 8;
+ enum video_format eformat = priv->format;
debug("%s\n", __func__);
bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset);
@@ -148,7 +164,7 @@ static void video_display_rle8_bitmap(struct udevice *dev,
else
cnt = runlen;
draw_unencoded_bitmap(
- &fb, bpix,
+ &fb, bpix, eformat,
bmap, palette, cnt);
}
x += runlen;
@@ -173,8 +189,9 @@ static void video_display_rle8_bitmap(struct udevice *dev,
cnt = width - x;
else
cnt = runlen;
- draw_encoded_bitmap(&fb, bpix, palette,
- &bmap[1], cnt);
+ draw_encoded_bitmap(&fb, bpix, eformat,
+ palette, &bmap[1],
+ cnt);
}
x += runlen;
}
@@ -224,6 +241,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
unsigned long width, height, byte_width;
unsigned long pwidth = priv->xsize;
unsigned colours, bpix, bmp_bpix;
+ enum video_format eformat;
struct bmp_color_table_entry *palette;
int hdr_size;
int ret;
@@ -245,6 +263,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
colours = 1 << bmp_bpix;
bpix = VNBITS(priv->bpix);
+ eformat = priv->format;
if (bpix != 1 && bpix != 8 && bpix != 16 && bpix != 32) {
printf("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
@@ -312,7 +331,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
for (i = 0; i < height; ++i) {
WATCHDOG_RESET();
for (j = 0; j < width; j++) {
- write_pix8(fb, bpix, palette, bmap);
+ write_pix8(fb, bpix, eformat, palette, bmap);
bmap++;
fb += bpix / 8;
}
@@ -345,6 +364,16 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
(bmap[0] >> 3);
bmap += 3;
fb += 2;
+ } else if (eformat == VIDEO_X2R10G10B10) {
+ u32 pix;
+
+ pix = *bmap++ << 2U;
+ pix |= *bmap++ << 12U;
+ pix |= *bmap++ << 22U;
+ *fb++ = pix & 0xff;
+ *fb++ = (pix >> 8) & 0xff;
+ *fb++ = (pix >> 16) & 0xff;
+ *fb++ = pix >> 24;
} else {
*fb++ = *bmap++;
*fb++ = *bmap++;
@@ -361,10 +390,23 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
if (IS_ENABLED(CONFIG_BMP_32BPP)) {
for (i = 0; i < height; ++i) {
for (j = 0; j < width; j++) {
- *fb++ = *bmap++;
- *fb++ = *bmap++;
- *fb++ = *bmap++;
- *fb++ = *bmap++;
+ if (eformat == VIDEO_X2R10G10B10) {
+ u32 pix;
+
+ pix = *bmap++ << 2U;
+ pix |= *bmap++ << 12U;
+ pix |= *bmap++ << 22U;
+ pix |= (*bmap++ >> 6) << 30U;
+ *fb++ = pix & 0xff;
+ *fb++ = (pix >> 8) & 0xff;
+ *fb++ = (pix >> 16) & 0xff;
+ *fb++ = pix >> 24;
+ } else {
+ *fb++ = *bmap++;
+ *fb++ = *bmap++;
+ *fb++ = *bmap++;
+ *fb++ = *bmap++;
+ }
}
fb -= priv->line_length + width * (bpix / 8);
}