summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.c8
-rw-r--r--drivers/block/blk-uclass.c14
-rw-r--r--drivers/clk/Kconfig3
-rw-r--r--drivers/clk/clk-uclass.c77
-rw-r--r--drivers/clk/clk.c1
-rw-r--r--drivers/clk/clk_fixed_rate.c1
-rw-r--r--drivers/clk/clk_sandbox_ccf.c15
-rw-r--r--drivers/clk/clk_stm32mp1.c37
-rw-r--r--drivers/clk/imx/Kconfig16
-rw-r--r--drivers/clk/imx/Makefile2
-rw-r--r--drivers/clk/imx/clk-composite-8m.c170
-rw-r--r--drivers/clk/imx/clk-imx8mm.c415
-rw-r--r--drivers/clk/imx/clk-pll14xx.c381
-rw-r--r--drivers/clk/imx/clk.h25
-rw-r--r--drivers/clk/meson/g12a.c1
-rw-r--r--drivers/clk/rockchip/clk_rk3328.c12
-rw-r--r--drivers/core/Kconfig2
-rw-r--r--drivers/ddr/fsl/main.c89
-rw-r--r--drivers/gpio/Kconfig5
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c2
-rw-r--r--drivers/i2c/mxc_i2c.c22
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/misc/i2c_eeprom.c8
-rw-r--r--drivers/misc/stm32_rcc.c5
-rw-r--r--drivers/misc/stm32mp_fuse.c74
-rw-r--r--drivers/mmc/Kconfig7
-rw-r--r--drivers/mmc/mmc-uclass.c7
-rw-r--r--drivers/mmc/sti_sdhci.c6
-rw-r--r--drivers/mmc/stm32_sdmmc2.c5
-rw-r--r--drivers/mtd/nand/raw/Kconfig5
-rw-r--r--drivers/net/fsl-mc/mc.c10
-rw-r--r--drivers/nvme/nvme.c29
-rw-r--r--drivers/pci/pcie_fsl.c121
-rw-r--r--drivers/pci/pcie_fsl.h10
-rw-r--r--drivers/phy/Kconfig2
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c20
-rw-r--r--drivers/pinctrl/pinctrl_stm32.c4
-rw-r--r--drivers/power/pmic/stpmic1.c107
-rw-r--r--drivers/ram/rockchip/sdram_rk3399.c159
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_ddr.h4
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_tests.c97
-rw-r--r--drivers/remoteproc/stm32_copro.c2
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/ds3231.c17
-rw-r--r--drivers/rtc/stm32_rtc.c9
-rw-r--r--drivers/serial/Kconfig4
-rw-r--r--drivers/serial/serial_stm32.c5
-rw-r--r--drivers/serial/serial_stm32.h2
48 files changed, 1692 insertions, 333 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index e3135bb75f..9a08575053 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1167,6 +1167,14 @@ int ahci_probe_scsi(struct udevice *ahci_dev, ulong base)
if (ret)
return ret;
+ /*
+ * scsi_scan_dev() scans devices up-to the number of max_id.
+ * Update max_id if the number of detected ports exceeds max_id.
+ * This allows SCSI to scan all detected ports.
+ */
+ uc_plat->max_id = max_t(unsigned long, uc_priv->n_ports,
+ uc_plat->max_id);
+
return 0;
}
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index c23b6682a6..baaf431e5e 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -208,11 +208,7 @@ int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
if (ret)
return ret;
- ret = blk_select_hwpart(dev, hwpart);
- if (!ret)
- blkcache_invalidate(if_type, devnum);
-
- return ret;
+ return blk_select_hwpart(dev, hwpart);
}
int blk_list_part(enum if_type if_type)
@@ -352,13 +348,7 @@ int blk_select_hwpart(struct udevice *dev, int hwpart)
int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
{
- int ret;
-
- ret = blk_select_hwpart(desc->bdev, hwpart);
- if (!ret)
- blkcache_invalidate(desc->if_type, desc->devnum);
-
- return ret;
+ return blk_select_hwpart(desc->bdev, hwpart);
}
int blk_first_device(int if_type, struct udevice **devp)
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a3f0171b45..95fe0aea2c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -48,7 +48,7 @@ config CLK_BOSTON
config SPL_CLK_CCF
bool "SPL Common Clock Framework [CCF] support "
- depends on SPL_CLK_IMX6Q
+ depends on SPL
help
Enable this option if you want to (re-)use the Linux kernel's Common
Clock Framework [CCF] code in U-Boot's SPL.
@@ -62,7 +62,6 @@ config SPL_CLK_COMPOSITE_CCF
config CLK_CCF
bool "Common Clock Framework [CCF] support "
- depends on CLK_IMX6Q || SANDBOX_CLK_CCF
help
Enable this option if you want to (re-)use the Linux kernel's Common
Clock Framework [CCF] code in U-Boot's clock driver.
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index c66b6f3c4e..64c181f4ad 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -449,13 +449,45 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
int clk_enable(struct clk *clk)
{
const struct clk_ops *ops = clk_dev_ops(clk->dev);
+ struct clk *clkp = NULL;
+ int ret;
debug("%s(clk=%p)\n", __func__, clk);
- if (!ops->enable)
- return -ENOSYS;
+ if (CONFIG_IS_ENABLED(CLK_CCF)) {
+ /* Take id 0 as a non-valid clk, such as dummy */
+ if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
+ if (clkp->enable_count) {
+ clkp->enable_count++;
+ return 0;
+ }
+ if (clkp->dev->parent &&
+ device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
+ ret = clk_enable(dev_get_clk_ptr(clkp->dev->parent));
+ if (ret) {
+ printf("Enable %s failed\n",
+ clkp->dev->parent->name);
+ return ret;
+ }
+ }
+ }
- return ops->enable(clk);
+ if (ops->enable) {
+ ret = ops->enable(clk);
+ if (ret) {
+ printf("Enable %s failed\n", clk->dev->name);
+ return ret;
+ }
+ }
+ if (clkp)
+ clkp->enable_count++;
+ } else {
+ if (!ops->enable)
+ return -ENOSYS;
+ return ops->enable(clk);
+ }
+
+ return 0;
}
int clk_enable_bulk(struct clk_bulk *bulk)
@@ -474,13 +506,46 @@ int clk_enable_bulk(struct clk_bulk *bulk)
int clk_disable(struct clk *clk)
{
const struct clk_ops *ops = clk_dev_ops(clk->dev);
+ struct clk *clkp = NULL;
+ int ret;
debug("%s(clk=%p)\n", __func__, clk);
- if (!ops->disable)
- return -ENOSYS;
+ if (CONFIG_IS_ENABLED(CLK_CCF)) {
+ if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
+ if (clkp->enable_count == 0) {
+ printf("clk %s already disabled\n",
+ clkp->dev->name);
+ return 0;
+ }
- return ops->disable(clk);
+ if (--clkp->enable_count > 0)
+ return 0;
+ }
+
+ if (ops->disable) {
+ ret = ops->disable(clk);
+ if (ret)
+ return ret;
+ }
+
+ if (clkp && clkp->dev->parent &&
+ device_get_uclass_id(clkp->dev) == UCLASS_CLK) {
+ ret = clk_disable(dev_get_clk_ptr(clkp->dev->parent));
+ if (ret) {
+ printf("Disable %s failed\n",
+ clkp->dev->parent->name);
+ return ret;
+ }
+ }
+ } else {
+ if (!ops->disable)
+ return -ENOSYS;
+
+ return ops->disable(clk);
+ }
+
+ return 0;
}
int clk_disable_bulk(struct clk_bulk *bulk)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 39b3087067..1cf9987f6c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -40,6 +40,7 @@ int clk_register(struct clk *clk, const char *drv_name,
return ret;
}
+ clk->enable_count = 0;
/* Store back pointer to clk from udevice */
clk->dev->uclass_priv = clk;
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 08cce0d79b..f51126793e 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -27,6 +27,7 @@ static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
/* Make fixed rate clock accessible from higher level struct clk */
dev->uclass_priv = clk;
clk->dev = dev;
+ clk->enable_count = 0;
return 0;
}
diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index e126f18d8e..9fa27229e1 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -25,6 +25,18 @@ struct clk_pllv3 {
u32 div_shift;
};
+int sandbox_clk_enable_count(struct clk *clk)
+{
+ struct clk *clkp = NULL;
+ int ret;
+
+ ret = clk_get_by_id(clk->id, &clkp);
+ if (ret)
+ return 0;
+
+ return clkp->enable_count;
+}
+
static ulong clk_pllv3_get_rate(struct clk *clk)
{
unsigned long parent_rate = clk_get_parent_rate(clk);
@@ -254,6 +266,9 @@ static int sandbox_clk_ccf_probe(struct udevice *dev)
sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels),
&reg, 0));
+ clk_dm(SANDBOX_CLK_I2C_ROOT,
+ sandbox_clk_gate2("i2c_root", "i2c", base + 0x7c, 0));
+
return 0;
}
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
index 5806d48696..e87307fa60 100644
--- a/drivers/clk/clk_stm32mp1.c
+++ b/drivers/clk/clk_stm32mp1.c
@@ -15,6 +15,8 @@
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/clock/stm32mp1-clksrc.h>
+DECLARE_GLOBAL_DATA_PTR;
+
#ifndef CONFIG_STM32MP1_TRUSTED
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
/* activate clock tree initialization in the driver */
@@ -759,9 +761,6 @@ static ulong stm32mp1_clk_get_fixed(struct stm32mp1_clk_priv *priv, int idx)
return 0;
}
- debug("%s: clk id %d = %x : %ld kHz\n", __func__, idx,
- (u32)priv->osc[idx], priv->osc[idx] / 1000);
-
return priv->osc[idx];
}
@@ -863,8 +862,6 @@ static ulong pll_get_fref_ck(struct stm32mp1_clk_priv *priv,
src = selr & RCC_SELR_SRC_MASK;
refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]);
- debug("PLL%d : selr=%x refclk = %d kHz\n",
- pll_id, selr, (u32)(refclk / 1000));
return refclk;
}
@@ -889,9 +886,6 @@ static ulong pll_get_fvco(struct stm32mp1_clk_priv *priv,
divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
- debug("PLL%d : cfgr1=%x fracr=%x DIVN=%d DIVM=%d\n",
- pll_id, cfgr1, fracr, divn, divm);
-
refclk = pll_get_fref_ck(priv, pll_id);
/* with FRACV :
@@ -908,7 +902,6 @@ static ulong pll_get_fvco(struct stm32mp1_clk_priv *priv,
} else {
fvco = (ulong)(refclk * (divn + 1) / (divm + 1));
}
- debug("PLL%d : %s = %ld\n", pll_id, __func__, fvco);
return fvco;
}
@@ -921,17 +914,13 @@ static ulong stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv,
ulong dfout;
u32 cfgr2;
- debug("%s(%d, %d)\n", __func__, pll_id, div_id);
if (div_id >= _DIV_NB)
return 0;
cfgr2 = readl(priv->base + pll[pll_id].pllxcfgr2);
divy = (cfgr2 >> RCC_PLLNCFGR2_SHIFT(div_id)) & RCC_PLLNCFGR2_DIVX_MASK;
- debug("PLL%d : cfgr2=%x DIVY=%d\n", pll_id, cfgr2, divy);
-
dfout = pll_get_fvco(priv, pll_id) / (divy + 1);
- debug(" => dfout = %d kHz\n", (u32)(dfout / 1000));
return dfout;
}
@@ -1574,9 +1563,6 @@ static void stgen_config(struct stm32mp1_clk_priv *priv)
/* need to update gd->arch.timer_rate_hz with new frequency */
timer_init();
- pr_debug("gd->arch.timer_rate_hz = %x\n",
- (u32)gd->arch.timer_rate_hz);
- pr_debug("Tick = %x\n", (u32)(get_ticks()));
}
}
@@ -1882,7 +1868,6 @@ static int pll_set_output_rate(struct udevice *dev,
if (div > 128)
div = 128;
- debug("fvco = %ld, clk_rate = %ld, div=%d\n", fvco, clk_rate, div);
/* stop the requested output */
clrbits_le32(pllxcr, 0x1 << div_id << RCC_PLLNCR_DIVEN_SHIFT);
/* change divider */
@@ -1915,6 +1900,9 @@ static ulong stm32mp1_clk_set_rate(struct clk *clk, unsigned long clk_rate)
}
p = stm32mp1_clk_get_parent(priv, clk->id);
+#ifdef DEBUG
+ debug("%s: parent = %d:%s\n", __func__, p, stm32mp1_clk_parent_name[p]);
+#endif
if (p < 0)
return -EINVAL;
@@ -1932,6 +1920,7 @@ static ulong stm32mp1_clk_set_rate(struct clk *clk, unsigned long clk_rate)
return result;
}
#endif
+
case _PLL4_Q:
/* for LTDC_PX and DSI_PX case */
return pll_set_output_rate(clk->dev, _PLL4, _DIV_Q, clk_rate);
@@ -2055,22 +2044,22 @@ static int stm32mp1_clk_probe(struct udevice *dev)
stm32mp1_clk_dump(priv);
#endif
+ gd->cpu_clk = stm32mp1_clk_get(priv, _CK_MPU);
+ gd->bus_clk = stm32mp1_clk_get(priv, _ACLK);
+ /* DDRPHYC father */
+ gd->mem_clk = stm32mp1_clk_get(priv, _PLL2_R);
#if defined(CONFIG_DISPLAY_CPUINFO)
if (gd->flags & GD_FLG_RELOC) {
char buf[32];
printf("Clocks:\n");
- printf("- MPU : %s MHz\n",
- strmhz(buf, stm32mp1_clk_get(priv, _CK_MPU)));
+ printf("- MPU : %s MHz\n", strmhz(buf, gd->cpu_clk));
printf("- MCU : %s MHz\n",
strmhz(buf, stm32mp1_clk_get(priv, _CK_MCU)));
- printf("- AXI : %s MHz\n",
- strmhz(buf, stm32mp1_clk_get(priv, _ACLK)));
+ printf("- AXI : %s MHz\n", strmhz(buf, gd->bus_clk));
printf("- PER : %s MHz\n",
strmhz(buf, stm32mp1_clk_get(priv, _CK_PER)));
- /* DDRPHYC father */
- printf("- DDR : %s MHz\n",
- strmhz(buf, stm32mp1_clk_get(priv, _PLL2_R)));
+ printf("- DDR : %s MHz\n", strmhz(buf, gd->mem_clk));
}
#endif /* CONFIG_DISPLAY_CPUINFO */
#endif
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index 3e6a980c8c..aae69cf9b0 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -20,3 +20,19 @@ config CLK_IMX8
select CLK
help
This enables support clock driver for i.MX8 platforms.
+
+config SPL_CLK_IMX8MM
+ bool "SPL clock support for i.MX8MM"
+ depends on ARCH_IMX8M && SPL
+ select SPL_CLK
+ select SPL_CLK_CCF
+ help
+ This enables SPL DM/DTS support for clock driver in i.MX8MM
+
+config CLK_IMX8MM
+ bool "Clock support for i.MX8MM"
+ depends on ARCH_IMX8M
+ select CLK
+ select CLK_CCF
+ help
+ This enables support clock driver for i.MX8MM platforms.
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 105a58ca90..5ad7967fe9 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -10,3 +10,5 @@ ifdef CONFIG_CLK_IMX8
obj-$(CONFIG_IMX8QXP) += clk-imx8qxp.o
obj-$(CONFIG_IMX8QM) += clk-imx8qm.o
endif
+obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MM) += clk-imx8mm.o clk-pll14xx.o \
+ clk-composite-8m.o
diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c
new file mode 100644
index 0000000000..95120d6559
--- /dev/null
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/clk-provider.h>
+#include <clk.h>
+#include "clk.h"
+
+#define UBOOT_DM_CLK_IMX_COMPOSITE "imx_clk_composite"
+
+#define PCG_PREDIV_SHIFT 16
+#define PCG_PREDIV_WIDTH 3
+#define PCG_PREDIV_MAX 8
+
+#define PCG_DIV_SHIFT 0
+#define PCG_DIV_WIDTH 6
+#define PCG_DIV_MAX 64
+
+#define PCG_PCS_SHIFT 24
+#define PCG_PCS_MASK 0x7
+
+#define PCG_CGC_SHIFT 28
+
+static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk *clk)
+{
+ struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk);
+ struct clk_composite *composite = (struct clk_composite *)clk->data;
+ ulong parent_rate = clk_get_parent_rate(&composite->clk);
+ unsigned long prediv_rate;
+ unsigned int prediv_value;
+ unsigned int div_value;
+
+ debug("%s: name %s prate: %lu reg: %p\n", __func__,
+ (&composite->clk)->dev->name, parent_rate, divider->reg);
+ prediv_value = readl(divider->reg) >> divider->shift;
+ prediv_value &= clk_div_mask(divider->width);
+
+ prediv_rate = divider_recalc_rate(clk, parent_rate, prediv_value,
+ NULL, divider->flags,
+ divider->width);
+
+ div_value = readl(divider->reg) >> PCG_DIV_SHIFT;
+ div_value &= clk_div_mask(PCG_DIV_WIDTH);
+
+ return divider_recalc_rate(clk, prediv_rate, div_value, NULL,
+ divider->flags, PCG_DIV_WIDTH);
+}
+
+static int imx8m_clk_composite_compute_dividers(unsigned long rate,
+ unsigned long parent_rate,
+ int *prediv, int *postdiv)
+{
+ int div1, div2;
+ int error = INT_MAX;
+ int ret = -EINVAL;
+
+ *prediv = 1;
+ *postdiv = 1;
+
+ for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) {
+ for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) {
+ int new_error = ((parent_rate / div1) / div2) - rate;
+
+ if (abs(new_error) < abs(error)) {
+ *prediv = div1;
+ *postdiv = div2;
+ error = new_error;
+ ret = 0;
+ }
+ }
+ }
+ return ret;
+}
+
+/*
+ * The clk are bound to a dev, because it is part of composite clk
+ * use composite clk to get dev
+ */
+static ulong imx8m_clk_composite_divider_set_rate(struct clk *clk,
+ unsigned long rate)
+{
+ struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk);
+ struct clk_composite *composite = (struct clk_composite *)clk->data;
+ ulong parent_rate = clk_get_parent_rate(&composite->clk);
+ int prediv_value;
+ int div_value;
+ int ret;
+ u32 val;
+
+ ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
+ &prediv_value, &div_value);
+ if (ret)
+ return ret;
+
+ val = readl(divider->reg);
+ val &= ~((clk_div_mask(divider->width) << divider->shift) |
+ (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+
+ val |= (u32)(prediv_value - 1) << divider->shift;
+ val |= (u32)(div_value - 1) << PCG_DIV_SHIFT;
+ writel(val, divider->reg);
+
+ return clk_get_rate(&composite->clk);
+}
+
+static const struct clk_ops imx8m_clk_composite_divider_ops = {
+ .get_rate = imx8m_clk_composite_divider_recalc_rate,
+ .set_rate = imx8m_clk_composite_divider_set_rate,
+};
+
+struct clk *imx8m_clk_composite_flags(const char *name,
+ const char * const *parent_names,
+ int num_parents, void __iomem *reg,
+ unsigned long flags)
+{
+ struct clk *clk = ERR_PTR(-ENOMEM);
+ struct clk_divider *div = NULL;
+ struct clk_gate *gate = NULL;
+ struct clk_mux *mux = NULL;
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ goto fail;
+
+ mux->reg = reg;
+ mux->shift = PCG_PCS_SHIFT;
+ mux->mask = PCG_PCS_MASK;
+ mux->num_parents = num_parents;
+ mux->flags = flags;
+ mux->parent_names = parent_names;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ goto fail;
+
+ div->reg = reg;
+ div->shift = PCG_PREDIV_SHIFT;
+ div->width = PCG_PREDIV_WIDTH;
+ div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ goto fail;
+
+ gate->reg = reg;
+ gate->bit_idx = PCG_CGC_SHIFT;
+ gate->flags = flags;
+
+ clk = clk_register_composite(NULL, name,
+ parent_names, num_parents,
+ &mux->clk, &clk_mux_ops, &div->clk,
+ &imx8m_clk_composite_divider_ops,
+ &gate->clk, &clk_gate_ops, flags);
+ if (IS_ERR(clk))
+ goto fail;
+
+ return clk;
+
+fail:
+ kfree(gate);
+ kfree(div);
+ kfree(mux);
+ return ERR_CAST(clk);
+}
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
new file mode 100644
index 0000000000..f4913e70ab
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <dt-bindings/clock/imx8mm-clock.h>
+
+#include "clk.h"
+
+#define PLL_1416X_RATE(_rate, _m, _p, _s) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ }
+
+#define PLL_1443X_RATE(_rate, _m, _p, _s, _k) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ .kdiv = (_k), \
+ }
+
+static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
+ PLL_1416X_RATE(1800000000U, 225, 3, 0),
+ PLL_1416X_RATE(1600000000U, 200, 3, 0),
+ PLL_1416X_RATE(1200000000U, 300, 3, 1),
+ PLL_1416X_RATE(1000000000U, 250, 3, 1),
+ PLL_1416X_RATE(800000000U, 200, 3, 1),
+ PLL_1416X_RATE(750000000U, 250, 2, 2),
+ PLL_1416X_RATE(700000000U, 350, 3, 2),
+ PLL_1416X_RATE(600000000U, 300, 3, 2),
+};
+
+static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = {
+ PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+};
+
+static struct imx_pll14xx_clk imx8mm_dram_pll __initdata = {
+ .type = PLL_1443X,
+ .rate_table = imx8mm_drampll_tbl,
+ .rate_count = ARRAY_SIZE(imx8mm_drampll_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_arm_pll __initdata = {
+ .type = PLL_1416X,
+ .rate_table = imx8mm_pll1416x_tbl,
+ .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_sys_pll __initdata = {
+ .type = PLL_1416X,
+ .rate_table = imx8mm_pll1416x_tbl,
+ .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
+};
+
+static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", };
+static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
+static const char *sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
+static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+
+static const char *imx8mm_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
+ "sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", "sys_pll1_400m",
+ "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
+
+static const char *imx8mm_enet_axi_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_250m",
+ "sys_pll2_200m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_nand_usdhc_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_200m",
+ "sys_pll1_133m", "sys_pll3_out", "sys_pll2_250m", "audio_pll1_out", };
+
+static const char *imx8mm_usdhc1_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+ "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
+
+static const char *imx8mm_usdhc2_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+ "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
+
+static const char *imx8mm_i2c1_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c2_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c3_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c4_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_wdog_sels[] = {"clock-osc-24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out",
+ "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", };
+
+static const char *imx8mm_usdhc3_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+ "sys_pll3_out", "sys_pll1_266m", "audio_pll2_clk", "sys_pll1_100m", };
+
+static ulong imx8mm_clk_get_rate(struct clk *clk)
+{
+ struct clk *c;
+ int ret;
+
+ debug("%s(#%lu)\n", __func__, clk->id);
+
+ ret = clk_get_by_id(clk->id, &c);
+ if (ret)
+ return ret;
+
+ return clk_get_rate(c);
+}
+
+static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *c;
+ int ret;
+
+ debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
+
+ ret = clk_get_by_id(clk->id, &c);
+ if (ret)
+ return ret;
+
+ return clk_set_rate(c, rate);
+}
+
+static int __imx8mm_clk_enable(struct clk *clk, bool enable)
+{
+ struct clk *c;
+ int ret;
+
+ debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
+
+ ret = clk_get_by_id(clk->id, &c);
+ if (ret)
+ return ret;
+
+ if (enable)
+ ret = clk_enable(c);
+ else
+ ret = clk_disable(c);
+
+ return ret;
+}
+
+static int imx8mm_clk_disable(struct clk *clk)
+{
+ return __imx8mm_clk_enable(clk, 0);
+}
+
+static int imx8mm_clk_enable(struct clk *clk)
+{
+ return __imx8mm_clk_enable(clk, 1);
+}
+
+static struct clk_ops imx8mm_clk_ops = {
+ .set_rate = imx8mm_clk_set_rate,
+ .get_rate = imx8mm_clk_get_rate,
+ .enable = imx8mm_clk_enable,
+ .disable = imx8mm_clk_disable,
+};
+
+static int imx8mm_clk_probe(struct udevice *dev)
+{
+ void __iomem *base;
+
+ base = (void *)ANATOP_BASE_ADDR;
+
+ clk_dm(IMX8MM_DRAM_PLL_REF_SEL,
+ imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2,
+ pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+ clk_dm(IMX8MM_ARM_PLL_REF_SEL,
+ imx_clk_mux("arm_pll_ref_sel", base + 0x84, 0, 2,
+ pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+ clk_dm(IMX8MM_SYS_PLL1_REF_SEL,
+ imx_clk_mux("sys_pll1_ref_sel", base + 0x94, 0, 2,
+ pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+ clk_dm(IMX8MM_SYS_PLL2_REF_SEL,
+ imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2,
+ pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+ clk_dm(IMX8MM_SYS_PLL3_REF_SEL,
+ imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2,
+ pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+
+ clk_dm(IMX8MM_DRAM_PLL,
+ imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel",
+ base + 0x50, &imx8mm_dram_pll));
+ clk_dm(IMX8MM_ARM_PLL,
+ imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel",
+ base + 0x84, &imx8mm_arm_pll));
+ clk_dm(IMX8MM_SYS_PLL1,
+ imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel",
+ base + 0x94, &imx8mm_sys_pll));
+ clk_dm(IMX8MM_SYS_PLL2,
+ imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel",
+ base + 0x104, &imx8mm_sys_pll));
+ clk_dm(IMX8MM_SYS_PLL3,
+ imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel",
+ base + 0x114, &imx8mm_sys_pll));
+
+ /* PLL bypass out */
+ clk_dm(IMX8MM_DRAM_PLL_BYPASS,
+ imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1,
+ dram_pll_bypass_sels,
+ ARRAY_SIZE(dram_pll_bypass_sels),
+ CLK_SET_RATE_PARENT));
+ clk_dm(IMX8MM_ARM_PLL_BYPASS,
+ imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1,
+ arm_pll_bypass_sels,
+ ARRAY_SIZE(arm_pll_bypass_sels),
+ CLK_SET_RATE_PARENT));
+ clk_dm(IMX8MM_SYS_PLL1_BYPASS,
+ imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1,
+ sys_pll1_bypass_sels,
+ ARRAY_SIZE(sys_pll1_bypass_sels),
+ CLK_SET_RATE_PARENT));
+ clk_dm(IMX8MM_SYS_PLL2_BYPASS,
+ imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1,
+ sys_pll2_bypass_sels,
+ ARRAY_SIZE(sys_pll2_bypass_sels),
+ CLK_SET_RATE_PARENT));
+ clk_dm(IMX8MM_SYS_PLL3_BYPASS,
+ imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1,
+ sys_pll3_bypass_sels,
+ ARRAY_SIZE(sys_pll3_bypass_sels),
+ CLK_SET_RATE_PARENT));
+
+ /* PLL out gate */
+ clk_dm(IMX8MM_DRAM_PLL_OUT,
+ imx_clk_gate("dram_pll_out", "dram_pll_bypass",
+ base + 0x50, 13));
+ clk_dm(IMX8MM_ARM_PLL_OUT,
+ imx_clk_gate("arm_pll_out", "arm_pll_bypass",
+ base + 0x84, 11));
+ clk_dm(IMX8MM_SYS_PLL1_OUT,
+ imx_clk_gate("sys_pll1_out", "sys_pll1_bypass",
+ base + 0x94, 11));
+ clk_dm(IMX8MM_SYS_PLL2_OUT,
+ imx_clk_gate("sys_pll2_out", "sys_pll2_bypass",
+ base + 0x104, 11));
+ clk_dm(IMX8MM_SYS_PLL3_OUT,
+ imx_clk_gate("sys_pll3_out", "sys_pll3_bypass",
+ base + 0x114, 11));
+
+ /* SYS PLL fixed output */
+ clk_dm(IMX8MM_SYS_PLL1_40M,
+ imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20));
+ clk_dm(IMX8MM_SYS_PLL1_80M,
+ imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10));
+ clk_dm(IMX8MM_SYS_PLL1_100M,
+ imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8));
+ clk_dm(IMX8MM_SYS_PLL1_133M,
+ imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6));
+ clk_dm(IMX8MM_SYS_PLL1_160M,
+ imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5));
+ clk_dm(IMX8MM_SYS_PLL1_200M,
+ imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4));
+ clk_dm(IMX8MM_SYS_PLL1_266M,
+ imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3));
+ clk_dm(IMX8MM_SYS_PLL1_400M,
+ imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2));
+ clk_dm(IMX8MM_SYS_PLL1_800M,
+ imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1));
+
+ clk_dm(IMX8MM_SYS_PLL2_50M,
+ imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20));
+ clk_dm(IMX8MM_SYS_PLL2_100M,
+ imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10));
+ clk_dm(IMX8MM_SYS_PLL2_125M,
+ imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8));
+ clk_dm(IMX8MM_SYS_PLL2_166M,
+ imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6));
+ clk_dm(IMX8MM_SYS_PLL2_200M,
+ imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5));
+ clk_dm(IMX8MM_SYS_PLL2_250M,
+ imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4));
+ clk_dm(IMX8MM_SYS_PLL2_333M,
+ imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3));
+ clk_dm(IMX8MM_SYS_PLL2_500M,
+ imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2));
+ clk_dm(IMX8MM_SYS_PLL2_1000M,
+ imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1));
+
+ base = dev_read_addr_ptr(dev);
+ if (base == (void *)FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ clk_dm(IMX8MM_CLK_A53_SRC,
+ imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3,
+ imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels)));
+ clk_dm(IMX8MM_CLK_A53_CG,
+ imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28));
+ clk_dm(IMX8MM_CLK_A53_DIV,
+ imx_clk_divider2("arm_a53_div", "arm_a53_cg",
+ base + 0x8000, 0, 3));
+
+ clk_dm(IMX8MM_CLK_AHB,
+ imx8m_clk_composite_critical("ahb", imx8mm_ahb_sels,
+ base + 0x9000));
+ clk_dm(IMX8MM_CLK_IPG_ROOT,
+ imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
+
+ clk_dm(IMX8MM_CLK_ENET_AXI,
+ imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels,
+ base + 0x8880));
+ clk_dm(IMX8MM_CLK_NAND_USDHC_BUS,
+ imx8m_clk_composite_critical("nand_usdhc_bus",
+ imx8mm_nand_usdhc_sels,
+ base + 0x8900));
+
+ /* IP */
+ clk_dm(IMX8MM_CLK_USDHC1,
+ imx8m_clk_composite("usdhc1", imx8mm_usdhc1_sels,
+ base + 0xac00));
+ clk_dm(IMX8MM_CLK_USDHC2,
+ imx8m_clk_composite("usdhc2", imx8mm_usdhc2_sels,
+ base + 0xac80));
+ clk_dm(IMX8MM_CLK_I2C1,
+ imx8m_clk_composite("i2c1", imx8mm_i2c1_sels, base + 0xad00));
+ clk_dm(IMX8MM_CLK_I2C2,
+ imx8m_clk_composite("i2c2", imx8mm_i2c2_sels, base + 0xad80));
+ clk_dm(IMX8MM_CLK_I2C3,
+ imx8m_clk_composite("i2c3", imx8mm_i2c3_sels, base + 0xae00));
+ clk_dm(IMX8MM_CLK_I2C4,
+ imx8m_clk_composite("i2c4", imx8mm_i2c4_sels, base + 0xae80));
+ clk_dm(IMX8MM_CLK_WDOG,
+ imx8m_clk_composite("wdog", imx8mm_wdog_sels, base + 0xb900));
+ clk_dm(IMX8MM_CLK_USDHC3,
+ imx8m_clk_composite("usdhc3", imx8mm_usdhc3_sels,
+ base + 0xbc80));
+
+ clk_dm(IMX8MM_CLK_I2C1_ROOT,
+ imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0));
+ clk_dm(IMX8MM_CLK_I2C2_ROOT,
+ imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0));
+ clk_dm(IMX8MM_CLK_I2C3_ROOT,
+ imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0));
+ clk_dm(IMX8MM_CLK_I2C4_ROOT,
+ imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0));
+ clk_dm(IMX8MM_CLK_OCOTP_ROOT,
+ imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0));
+ clk_dm(IMX8MM_CLK_USDHC1_ROOT,
+ imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0));
+ clk_dm(IMX8MM_CLK_USDHC2_ROOT,
+ imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0));
+ clk_dm(IMX8MM_CLK_WDOG1_ROOT,
+ imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0));
+ clk_dm(IMX8MM_CLK_WDOG2_ROOT,
+ imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0));
+ clk_dm(IMX8MM_CLK_WDOG3_ROOT,
+ imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0));
+ clk_dm(IMX8MM_CLK_USDHC3_ROOT,
+ imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0));
+
+#ifdef CONFIG_SPL_BUILD
+ struct clk *clkp, *clkp1;
+
+ clk_get_by_id(IMX8MM_CLK_WDOG1_ROOT, &clkp);
+ clk_enable(clkp);
+ clk_get_by_id(IMX8MM_CLK_WDOG2_ROOT, &clkp);
+ clk_enable(clkp);
+ clk_get_by_id(IMX8MM_CLK_WDOG3_ROOT, &clkp);
+ clk_enable(clkp);
+
+ /* Configure SYS_PLL3 to 750MHz */
+ clk_get_by_id(IMX8MM_SYS_PLL3, &clkp);
+ clk_set_rate(clkp, 750000000UL);
+ clk_enable(clkp);
+
+ /* Configure ARM to sys_pll2_500m */
+ clk_get_by_id(IMX8MM_CLK_A53_SRC, &clkp);
+ clk_get_by_id(IMX8MM_SYS_PLL2_OUT, &clkp1);
+ clk_enable(clkp1);
+ clk_get_by_id(IMX8MM_SYS_PLL2_500M, &clkp1);
+ clk_set_parent(clkp, clkp1);
+
+ /* Configure ARM PLL to 1.2GHz */
+ clk_get_by_id(IMX8MM_ARM_PLL, &clkp1);
+ clk_set_rate(clkp1, 1200000000UL);
+ clk_get_by_id(IMX8MM_ARM_PLL_OUT, &clkp1);
+ clk_enable(clkp1);
+ clk_set_parent(clkp, clkp1);
+
+ /* Configure DIV to 1.2GHz */
+ clk_get_by_id(IMX8MM_CLK_A53_DIV, &clkp1);
+ clk_set_rate(clkp1, 1200000000UL);
+#endif
+
+ return 0;
+}
+
+static const struct udevice_id imx8mm_clk_ids[] = {
+ { .compatible = "fsl,imx8mm-ccm" },
+ { },
+};
+
+U_BOOT_DRIVER(imx8mm_clk) = {
+ .name = "clk_imx8mm",
+ .id = UCLASS_CLK,
+ .of_match = imx8mm_clk_ids,
+ .ops = &imx8mm_clk_ops,
+ .probe = imx8mm_clk_probe,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
new file mode 100644
index 0000000000..2246beb21b
--- /dev/null
+++ b/drivers/clk/imx/clk-pll14xx.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2017-2019 NXP.
+ *
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/clk-provider.h>
+#include <linux/iopoll.h>
+#include <clk.h>
+#include <div64.h>
+
+#include "clk.h"
+
+#define UBOOT_DM_CLK_IMX_PLL1443X "imx_clk_pll1443x"
+#define UBOOT_DM_CLK_IMX_PLL1416X "imx_clk_pll1416x"
+
+#define GNRL_CTL 0x0
+#define DIV_CTL 0x4
+#define LOCK_STATUS BIT(31)
+#define LOCK_SEL_MASK BIT(29)
+#define CLKE_MASK BIT(11)
+#define RST_MASK BIT(9)
+#define BYPASS_MASK BIT(4)
+#define MDIV_SHIFT 12
+#define MDIV_MASK GENMASK(21, 12)
+#define PDIV_SHIFT 4
+#define PDIV_MASK GENMASK(9, 4)
+#define SDIV_SHIFT 0
+#define SDIV_MASK GENMASK(2, 0)
+#define KDIV_SHIFT 0
+#define KDIV_MASK GENMASK(15, 0)
+
+#define LOCK_TIMEOUT_US 10000
+
+struct clk_pll14xx {
+ struct clk clk;
+ void __iomem *base;
+ enum imx_pll14xx_type type;
+ const struct imx_pll14xx_rate_table *rate_table;
+ int rate_count;
+};
+
+#define to_clk_pll14xx(_clk) container_of(_clk, struct clk_pll14xx, clk)
+
+static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
+ struct clk_pll14xx *pll, unsigned long rate)
+{
+ const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
+ int i;
+
+ for (i = 0; i < pll->rate_count; i++)
+ if (rate == rate_table[i].rate)
+ return &rate_table[i];
+
+ return NULL;
+}
+
+static unsigned long clk_pll1416x_recalc_rate(struct clk *clk)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+ u64 fvco = clk_get_parent_rate(clk);
+ u32 mdiv, pdiv, sdiv, pll_div;
+
+ pll_div = readl(pll->base + 4);
+ mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
+ pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
+ sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
+
+ fvco *= mdiv;
+ do_div(fvco, pdiv << sdiv);
+
+ return fvco;
+}
+
+static unsigned long clk_pll1443x_recalc_rate(struct clk *clk)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+ u64 fvco = clk_get_parent_rate(clk);
+ u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1;
+ short int kdiv;
+
+ pll_div_ctl0 = readl(pll->base + 4);
+ pll_div_ctl1 = readl(pll->base + 8);
+ mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
+ pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
+ sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
+ kdiv = pll_div_ctl1 & KDIV_MASK;
+
+ /* fvco = (m * 65536 + k) * Fin / (p * 65536) */
+ fvco *= (mdiv * 65536 + kdiv);
+ pdiv *= 65536;
+
+ do_div(fvco, pdiv << sdiv);
+
+ return fvco;
+}
+
+static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
+ u32 pll_div)
+{
+ u32 old_mdiv, old_pdiv;
+
+ old_mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
+ old_pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
+
+ return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv;
+}
+
+static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
+ u32 pll_div_ctl0, u32 pll_div_ctl1)
+{
+ u32 old_mdiv, old_pdiv, old_kdiv;
+
+ old_mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
+ old_pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
+ old_kdiv = (pll_div_ctl1 & KDIV_MASK) >> KDIV_SHIFT;
+
+ return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+ rate->kdiv != old_kdiv;
+}
+
+static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
+ u32 pll_div_ctl0, u32 pll_div_ctl1)
+{
+ u32 old_mdiv, old_pdiv, old_kdiv;
+
+ old_mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
+ old_pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
+ old_kdiv = (pll_div_ctl1 & KDIV_MASK) >> KDIV_SHIFT;
+
+ return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+ rate->kdiv != old_kdiv;
+}
+
+static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
+{
+ u32 val;
+
+ return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US,
+ LOCK_TIMEOUT_US);
+}
+
+static ulong clk_pll1416x_set_rate(struct clk *clk, unsigned long drate)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+ const struct imx_pll14xx_rate_table *rate;
+ u32 tmp, div_val;
+ int ret;
+
+ rate = imx_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, "xxxx");
+ return -EINVAL;
+ }
+
+ tmp = readl(pll->base + 4);
+
+ if (!clk_pll1416x_mp_change(rate, tmp)) {
+ tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
+ tmp |= rate->sdiv << SDIV_SHIFT;
+ writel(tmp, pll->base + 4);
+
+ return clk_pll1416x_recalc_rate(clk);
+ }
+
+ /* Bypass clock and set lock to pll output lock */
+ tmp = readl(pll->base);
+ tmp |= LOCK_SEL_MASK;
+ writel(tmp, pll->base);
+
+ /* Enable RST */
+ tmp &= ~RST_MASK;
+ writel(tmp, pll->base);
+
+ /* Enable BYPASS */
+ tmp |= BYPASS_MASK;
+ writel(tmp, pll->base);
+
+
+ div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+ (rate->sdiv << SDIV_SHIFT);
+ writel(div_val, pll->base + 0x4);
+
+ /*
+ * According to SPEC, t3 - t2 need to be greater than
+ * 1us and 1/FREF, respectively.
+ * FREF is FIN / Prediv, the prediv is [1, 63], so choose
+ * 3us.
+ */
+ udelay(3);
+
+ /* Disable RST */
+ tmp |= RST_MASK;
+ writel(tmp, pll->base);
+
+ /* Wait Lock */
+ ret = clk_pll14xx_wait_lock(pll);
+ if (ret)
+ return ret;
+
+ /* Bypass */
+ tmp &= ~BYPASS_MASK;
+ writel(tmp, pll->base);
+
+ return clk_pll1416x_recalc_rate(clk);
+}
+
+static ulong clk_pll1443x_set_rate(struct clk *clk, unsigned long drate)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+ const struct imx_pll14xx_rate_table *rate;
+ u32 tmp, div_val;
+ int ret;
+
+ rate = imx_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, "===");
+ return -EINVAL;
+ }
+
+ tmp = readl(pll->base + 4);
+ div_val = readl(pll->base + 8);
+
+ if (!clk_pll1443x_mpk_change(rate, tmp, div_val)) {
+ tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
+ tmp |= rate->sdiv << SDIV_SHIFT;
+ writel(tmp, pll->base + 4);
+
+ return clk_pll1443x_recalc_rate(clk);
+ }
+
+ tmp = readl(pll->base);
+
+ /* Enable RST */
+ tmp &= ~RST_MASK;
+ writel(tmp, pll->base);
+
+ /* Enable BYPASS */
+ tmp |= BYPASS_MASK;
+ writel(tmp, pll->base);
+
+ div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+ (rate->sdiv << SDIV_SHIFT);
+ writel(div_val, pll->base + 0x4);
+ writel(rate->kdiv << KDIV_SHIFT, pll->base + 0x8);
+
+ /*
+ * According to SPEC, t3 - t2 need to be greater than
+ * 1us and 1/FREF, respectively.
+ * FREF is FIN / Prediv, the prediv is [1, 63], so choose
+ * 3us.
+ */
+ udelay(3);
+
+ /* Disable RST */
+ tmp |= RST_MASK;
+ writel(tmp, pll->base);
+
+ /* Wait Lock*/
+ ret = clk_pll14xx_wait_lock(pll);
+ if (ret)
+ return ret;
+
+ /* Bypass */
+ tmp &= ~BYPASS_MASK;
+ writel(tmp, pll->base);
+
+ return clk_pll1443x_recalc_rate(clk);
+}
+
+static int clk_pll14xx_prepare(struct clk *clk)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+ u32 val;
+
+ /*
+ * RESETB = 1 from 0, PLL starts its normal
+ * operation after lock time
+ */
+ val = readl(pll->base + GNRL_CTL);
+ val |= RST_MASK;
+ writel(val, pll->base + GNRL_CTL);
+
+ return clk_pll14xx_wait_lock(pll);
+}
+
+static int clk_pll14xx_unprepare(struct clk *clk)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+ u32 val;
+
+ /*
+ * Set RST to 0, power down mode is enabled and
+ * every digital block is reset
+ */
+ val = readl(pll->base + GNRL_CTL);
+ val &= ~RST_MASK;
+ writel(val, pll->base + GNRL_CTL);
+
+ return 0;
+}
+
+static const struct clk_ops clk_pll1416x_ops = {
+ .enable = clk_pll14xx_prepare,
+ .disable = clk_pll14xx_unprepare,
+ .set_rate = clk_pll1416x_set_rate,
+ .get_rate = clk_pll1416x_recalc_rate,
+};
+
+static const struct clk_ops clk_pll1443x_ops = {
+ .enable = clk_pll14xx_prepare,
+ .disable = clk_pll14xx_unprepare,
+ .set_rate = clk_pll1443x_set_rate,
+ .get_rate = clk_pll1443x_recalc_rate,
+};
+
+struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
+ void __iomem *base,
+ const struct imx_pll14xx_clk *pll_clk)
+{
+ struct clk_pll14xx *pll;
+ struct clk *clk;
+ char *type_name;
+ int ret;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ switch (pll_clk->type) {
+ case PLL_1416X:
+ type_name = UBOOT_DM_CLK_IMX_PLL1416X;
+ break;
+ case PLL_1443X:
+ type_name = UBOOT_DM_CLK_IMX_PLL1443X;
+ break;
+ default:
+ pr_err("%s: Unknown pll type for pll clk %s\n",
+ __func__, name);
+ return ERR_PTR(-EINVAL);
+ };
+
+ pll->base = base;
+ pll->type = pll_clk->type;
+ pll->rate_table = pll_clk->rate_table;
+ pll->rate_count = pll_clk->rate_count;
+
+ clk = &pll->clk;
+
+ ret = clk_register(clk, type_name, name, parent_name);
+ if (ret) {
+ pr_err("%s: failed to register pll %s %d\n",
+ __func__, name, ret);
+ kfree(pll);
+ return ERR_PTR(ret);
+ }
+
+ return clk;
+}
+
+U_BOOT_DRIVER(clk_pll1443x) = {
+ .name = UBOOT_DM_CLK_IMX_PLL1443X,
+ .id = UCLASS_CLK,
+ .ops = &clk_pll1443x_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(clk_pll1416x) = {
+ .name = UBOOT_DM_CLK_IMX_PLL1416X,
+ .id = UCLASS_CLK,
+ .ops = &clk_pll1416x_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 1d480d8722..4956e04a92 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -20,6 +20,31 @@ enum imx_pllv3_type {
IMX_PLLV3_DDR_IMX7,
};
+enum imx_pll14xx_type {
+ PLL_1416X,
+ PLL_1443X,
+};
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+struct imx_pll14xx_rate_table {
+ unsigned int rate;
+ unsigned int pdiv;
+ unsigned int mdiv;
+ unsigned int sdiv;
+ unsigned int kdiv;
+};
+
+struct imx_pll14xx_clk {
+ enum imx_pll14xx_type type;
+ const struct imx_pll14xx_rate_table *rate_table;
+ int rate_count;
+ int flags;
+};
+
+struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
+ void __iomem *base,
+ const struct imx_pll14xx_clk *pll_clk);
+
struct clk *clk_register_gate2(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx, u8 cgr_val,
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
index 112326e553..43dac1aa37 100644
--- a/drivers/clk/meson/g12a.c
+++ b/drivers/clk/meson/g12a.c
@@ -405,6 +405,7 @@ static struct clk_ops meson_clk_ops = {
static const struct udevice_id meson_clk_ids[] = {
{ .compatible = "amlogic,g12a-clkc" },
+ { .compatible = "amlogic,g12b-clkc" },
{ }
};
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index a89e2ecc4a..5957a00402 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -745,10 +745,22 @@ static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent)
return -ENOENT;
}
+static int rk3328_clk_enable(struct clk *clk)
+{
+ switch (clk->id) {
+ case HCLK_HOST0:
+ /* Required to successfully probe the ehci generic driver */
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
static struct clk_ops rk3328_clk_ops = {
.get_rate = rk3328_clk_get_rate,
.set_rate = rk3328_clk_set_rate,
.set_parent = rk3328_clk_set_parent,
+ .enable = rk3328_clk_enable,
};
static int rk3328_clk_probe(struct udevice *dev)
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 2d195ae35e..3b95b5387b 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -92,7 +92,7 @@ config DM_SEQ_ALIAS
config SPL_DM_SEQ_ALIAS
bool "Support numbered aliases in device tree in SPL"
- depends on DM
+ depends on SPL_DM
default n
help
Most boards will have a '/aliases' node containing the path to
diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c
index e1f69a1d25..0aa6aedae7 100644
--- a/drivers/ddr/fsl/main.c
+++ b/drivers/ddr/fsl/main.c
@@ -10,6 +10,7 @@
*/
#include <common.h>
+#include <dm.h>
#include <i2c.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr.h>
@@ -82,17 +83,82 @@ u8 spd_i2c_addr[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
#endif
+#if defined(CONFIG_DM_I2C)
+#define DEV_TYPE struct udevice
+#else
+/* Local udevice */
+struct ludevice {
+ u8 chip;
+};
+
+#define DEV_TYPE struct ludevice
+
+#endif
+
#define SPD_SPA0_ADDRESS 0x36
#define SPD_SPA1_ADDRESS 0x37
-static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
+static int ddr_i2c_read(DEV_TYPE *dev, unsigned int addr,
+ int alen, uint8_t *buf, int len)
{
int ret;
+
+#ifdef CONFIG_DM_I2C
+ ret = dm_i2c_read(dev, 0, buf, len);
+#else
+ ret = i2c_read(dev->chip, addr, alen, buf, len);
+#endif
+
+ return ret;
+}
+
#ifdef CONFIG_SYS_FSL_DDR4
- uint8_t dummy = 0;
+static int ddr_i2c_dummy_write(unsigned int chip_addr)
+{
+ uint8_t buf = 0;
+
+#ifdef CONFIG_DM_I2C
+ struct udevice *dev;
+ int ret;
+
+ ret = i2c_get_chip_for_busnum(CONFIG_SYS_SPD_BUS_NUM, chip_addr,
+ 1, &dev);
+ if (ret) {
+ printf("%s: Cannot find udev for a bus %d\n", __func__,
+ CONFIG_SYS_SPD_BUS_NUM);
+ return ret;
+ }
+
+ return dm_i2c_write(dev, 0, &buf, 1);
+#else
+ return i2c_write(chip_addr, 0, 1, &buf, 1);
#endif
+ return 0;
+}
+#endif
+
+static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
+{
+ int ret;
+ DEV_TYPE *dev;
+
+#if defined(CONFIG_DM_I2C)
+ ret = i2c_get_chip_for_busnum(CONFIG_SYS_SPD_BUS_NUM, i2c_address,
+ 1, &dev);
+ if (ret) {
+ printf("%s: Cannot find udev for a bus %d\n", __func__,
+ CONFIG_SYS_SPD_BUS_NUM);
+ return;
+ }
+#else /* Non DM I2C support - will be removed */
+ struct ludevice ldev = {
+ .chip = i2c_address,
+ };
+ dev = &ldev;
+
i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM);
+#endif
#ifdef CONFIG_SYS_FSL_DDR4
/*
@@ -101,18 +167,19 @@ static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
* To access the upper 256 bytes, we need to set EE page address to 1
* See Jedec standar No. 21-C for detail
*/
- i2c_write(SPD_SPA0_ADDRESS, 0, 1, &dummy, 1);
- ret = i2c_read(i2c_address, 0, 1, (uchar *)spd, 256);
+ ddr_i2c_dummy_write(SPD_SPA0_ADDRESS);
+ ret = ddr_i2c_read(dev, 0, 1, (uchar *)spd, 256);
if (!ret) {
- i2c_write(SPD_SPA1_ADDRESS, 0, 1, &dummy, 1);
- ret = i2c_read(i2c_address, 0, 1,
- (uchar *)((ulong)spd + 256),
- min(256,
- (int)sizeof(generic_spd_eeprom_t) - 256));
+ ddr_i2c_dummy_write(SPD_SPA1_ADDRESS);
+ ret = ddr_i2c_read(dev, 0, 1, (uchar *)((ulong)spd + 256),
+ min(256,
+ (int)sizeof(generic_spd_eeprom_t)
+ - 256));
}
+
#else
- ret = i2c_read(i2c_address, 0, 1, (uchar *)spd,
- sizeof(generic_spd_eeprom_t));
+ ret = ddr_i2c_read(dev, 0, 1, (uchar *)spd,
+ sizeof(generic_spd_eeprom_t));
#endif
if (ret) {
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 7d9c97f537..f2dabb554f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -139,6 +139,11 @@ config MXC_GPIO
help
Support GPIO controllers on various i.MX platforms
+config MXS_GPIO
+ bool "Freescale/NXP MXS GPIO driver"
+ help
+ Support GPIO controllers on i.MX23 and i.MX28 platforms
+
config OMAP_GPIO
bool "TI OMAP GPIO driver"
depends on ARCH_OMAP2PLUS
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 28f640042f..e8b124f4f5 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -106,7 +106,7 @@ static int i2c_mux_gpio_probe(struct udevice *dev)
}
ret = gpio_request_list_by_name(dev, "mux-gpios", gpios, mux->n_gpios,
- GPIOD_IS_OUT_ACTIVE);
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
if (ret <= 0) {
dev_err(dev, "Failed to request mux-gpios\n");
return ret;
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 23119cce65..20f6dc4ecb 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -558,6 +558,14 @@ static int i2c_read_data(struct mxc_i2c_bus *i2c_bus, uchar chip, uchar *buf,
return 0;
}
+int __enable_i2c_clk(unsigned char enable, unsigned int i2c_num)
+{
+ return 1;
+}
+
+int enable_i2c_clk(unsigned char enable, unsigned int i2c_num)
+ __attribute__((weak, alias("__enable_i2c_clk")));
+
#ifndef CONFIG_DM_I2C
/*
* Read data from I2C device
@@ -723,13 +731,6 @@ static int mxc_i2c_probe(struct i2c_adapter *adap, uint8_t chip)
return bus_i2c_write(i2c_get_base(adap), chip, 0, 0, NULL, 0);
}
-int __enable_i2c_clk(unsigned char enable, unsigned i2c_num)
-{
- return 1;
-}
-int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
- __attribute__((weak, alias("__enable_i2c_clk")));
-
void bus_i2c_init(int index, int speed, int unused,
int (*idle_bus_fn)(void *p), void *idle_bus_data)
{
@@ -916,13 +917,6 @@ static int mxc_i2c_probe(struct udevice *bus)
}
}
- ret = i2c_idle_bus(i2c_bus);
- if (ret < 0) {
- /* Disable clk */
- enable_i2c_clk(0, bus->seq);
- return ret;
- }
-
/*
* Pinmux settings are in board file now, until pinmux is supported,
* we can set pinmux here in probe function.
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index cb8b5c04db..8037b6ee2d 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -88,6 +88,7 @@ config CROS_EC
config SPL_CROS_EC
bool "Enable Chrome OS EC in SPL"
+ depends on SPL
help
Enable access to the Chrome OS EC in SPL. This is a separate
microcontroller typically available on a SPI bus on Chromebooks. It
@@ -97,6 +98,7 @@ config SPL_CROS_EC
config TPL_CROS_EC
bool "Enable Chrome OS EC in TPL"
+ depends on TPL
help
Enable access to the Chrome OS EC in TPL. This is a separate
microcontroller typically available on a SPI bus on Chromebooks. It
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c
index f25d054007..8f2349ad5a 100644
--- a/drivers/misc/i2c_eeprom.c
+++ b/drivers/misc/i2c_eeprom.c
@@ -84,6 +84,14 @@ static int i2c_eeprom_std_ofdata_to_platdata(struct udevice *dev)
static int i2c_eeprom_std_probe(struct udevice *dev)
{
+ u8 test_byte;
+ int ret;
+
+ /* Verify that the chip is functional */
+ ret = i2c_eeprom_read(dev, 0, &test_byte, 1);
+ if (ret)
+ return -ENODEV;
+
return 0;
}
diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c
index 13d70696f6..e7efcdeafa 100644
--- a/drivers/misc/stm32_rcc.c
+++ b/drivers/misc/stm32_rcc.c
@@ -68,8 +68,6 @@ static int stm32_rcc_bind(struct udevice *dev)
dev_ofnode(dev), &child);
}
-static const struct misc_ops stm32_rcc_ops = {
-};
static const struct udevice_id stm32_rcc_ids[] = {
{.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_clk_f42x },
@@ -82,8 +80,7 @@ static const struct udevice_id stm32_rcc_ids[] = {
U_BOOT_DRIVER(stm32_rcc) = {
.name = "stm32-rcc",
- .id = UCLASS_MISC,
+ .id = UCLASS_NOP,
.of_match = stm32_rcc_ids,
.bind = stm32_rcc_bind,
- .ops = &stm32_rcc_ops,
};
diff --git a/drivers/misc/stm32mp_fuse.c b/drivers/misc/stm32mp_fuse.c
index 801d946b77..0eed345973 100644
--- a/drivers/misc/stm32mp_fuse.c
+++ b/drivers/misc/stm32mp_fuse.c
@@ -20,7 +20,7 @@
*/
int fuse_read(u32 bank, u32 word, u32 *val)
{
- int ret = 0;
+ int ret;
struct udevice *dev;
switch (bank) {
@@ -32,15 +32,25 @@ int fuse_read(u32 bank, u32 word, u32 *val)
return ret;
ret = misc_read(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
val, 4);
- if (ret < 0)
- return ret;
- ret = 0;
+ if (ret != 4)
+ ret = -EINVAL;
+ else
+ ret = 0;
break;
#ifdef CONFIG_PMIC_STPMIC1
case STM32MP_NVM_BANK:
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_GET_DRIVER(stpmic1_nvm),
+ &dev);
+ if (ret)
+ return ret;
*val = 0;
- ret = stpmic1_shadow_read_byte(word, (u8 *)val);
+ ret = misc_read(dev, -word, val, 1);
+ if (ret != 1)
+ ret = -EINVAL;
+ else
+ ret = 0;
break;
#endif /* CONFIG_PMIC_STPMIC1 */
@@ -67,14 +77,24 @@ int fuse_prog(u32 bank, u32 word, u32 val)
return ret;
ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET,
&val, 4);
- if (ret < 0)
- return ret;
- ret = 0;
+ if (ret != 4)
+ ret = -EINVAL;
+ else
+ ret = 0;
break;
#ifdef CONFIG_PMIC_STPMIC1
case STM32MP_NVM_BANK:
- ret = stpmic1_nvm_write_byte(word, (u8 *)&val);
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_GET_DRIVER(stpmic1_nvm),
+ &dev);
+ if (ret)
+ return ret;
+ ret = misc_write(dev, word, &val, 1);
+ if (ret != 1)
+ ret = -EINVAL;
+ else
+ ret = 0;
break;
#endif /* CONFIG_PMIC_STPMIC1 */
@@ -100,15 +120,25 @@ int fuse_sense(u32 bank, u32 word, u32 *val)
if (ret)
return ret;
ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4);
- if (ret < 0)
- return ret;
- ret = 0;
+ if (ret != 4)
+ ret = -EINVAL;
+ else
+ ret = 0;
break;
#ifdef CONFIG_PMIC_STPMIC1
case STM32MP_NVM_BANK:
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_GET_DRIVER(stpmic1_nvm),
+ &dev);
+ if (ret)
+ return ret;
*val = 0;
- ret = stpmic1_nvm_read_byte(word, (u8 *)val);
+ ret = misc_read(dev, word, val, 1);
+ if (ret != 1)
+ ret = -EINVAL;
+ else
+ ret = 0;
break;
#endif /* CONFIG_PMIC_STPMIC1 */
@@ -135,14 +165,24 @@ int fuse_override(u32 bank, u32 word, u32 val)
return ret;
ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET,
&val, 4);
- if (ret < 0)
- return ret;
- ret = 0;
+ if (ret != 4)
+ ret = -EINVAL;
+ else
+ ret = 0;
break;
#ifdef CONFIG_PMIC_STPMIC1
case STM32MP_NVM_BANK:
- ret = stpmic1_shadow_write_byte(word, (u8 *)&val);
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_GET_DRIVER(stpmic1_nvm),
+ &dev);
+ if (ret)
+ return ret;
+ ret = misc_write(dev, -word, &val, 1);
+ if (ret != 1)
+ ret = -EINVAL;
+ else
+ ret = 0;
break;
#endif /* CONFIG_PMIC_STPMIC1 */
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c6812f6517..0ccb1ea701 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -694,6 +694,13 @@ config FSL_ESDHC_IMX
This selects support for the i.MX eSDHC (Enhanced Secure Digital Host
Controller) found on numerous Freescale/NXP SoCs.
+config FSL_USDHC
+ bool "Freescale/NXP i.MX uSDHC controller support"
+ depends on MX6 || MX7 ||ARCH_MX7ULP || IMX8 || IMX8M || TARGET_S32V234EVB
+ select FSL_ESDHC_IMX
+ help
+ This enables the Ultra Secured Digital Host Controller enhancements
+
endmenu
config SYS_FSL_ERRATUM_ESDHC111
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 551007905c..2b146ea43c 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -360,6 +360,7 @@ static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
struct udevice *mmc_dev = dev_get_parent(bdev);
struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
struct blk_desc *desc = dev_get_uclass_platdata(bdev);
+ int ret;
if (desc->hwpart == hwpart)
return 0;
@@ -367,7 +368,11 @@ static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
if (mmc->part_config == MMCPART_NOAVAILABLE)
return -EMEDIUMTYPE;
- return mmc_switch_part(mmc, hwpart);
+ ret = mmc_switch_part(mmc, hwpart);
+ if (!ret)
+ blkcache_invalidate(desc->if_type, desc->devnum);
+
+ return ret;
}
static int mmc_blk_probe(struct udevice *dev)
diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c
index 8ed47e113d..d6c75ea601 100644
--- a/drivers/mmc/sti_sdhci.c
+++ b/drivers/mmc/sti_sdhci.c
@@ -97,14 +97,14 @@ static int sti_sdhci_probe(struct udevice *dev)
SDHCI_QUIRK_NO_HISPD_BIT;
host->host_caps = MMC_MODE_DDR_52MHz;
+ host->mmc = &plat->mmc;
+ host->mmc->dev = dev;
+ host->mmc->priv = host;
ret = sdhci_setup_cfg(&plat->cfg, host, 50000000, 400000);
if (ret)
return ret;
- host->mmc = &plat->mmc;
- host->mmc->priv = host;
- host->mmc->dev = dev;
upriv->mmc = host->mmc;
return sdhci_probe(dev);
diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c
index 867ed569eb..32434a4762 100644
--- a/drivers/mmc/stm32_sdmmc2.c
+++ b/drivers/mmc/stm32_sdmmc2.c
@@ -14,6 +14,7 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <linux/iopoll.h>
+#include <watchdog.h>
struct stm32_sdmmc2_plat {
struct mmc_config cfg;
@@ -190,7 +191,7 @@ struct stm32_sdmmc2_ctx {
#define SDMMC_IDMACTRL_IDMAEN BIT(0)
#define SDMMC_CMD_TIMEOUT 0xFFFFFFFF
-#define SDMMC_BUSYD0END_TIMEOUT_US 1000000
+#define SDMMC_BUSYD0END_TIMEOUT_US 2000000
static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv,
struct mmc_data *data,
@@ -432,6 +433,8 @@ static int stm32_sdmmc2_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
u32 cmdat = data ? SDMMC_CMD_CMDTRANS : 0;
int ret, retry = 3;
+ WATCHDOG_RESET();
+
retry_cmd:
ctx.data_length = 0;
ctx.dpsm_abort = false;
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index f86035bcce..a129f44869 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -15,6 +15,11 @@ config SYS_NAND_DRIVER_ECC_LAYOUT
Omit standard ECC layouts to safe space. Select this if your driver
is known to provide its own ECC layout.
+config SYS_NAND_USE_FLASH_BBT
+ bool "Enable BBT (Bad Block Table) support"
+ help
+ Enable the BBT (Bad Block Table) usage.
+
config NAND_ATMEL
bool "Support Atmel NAND controller"
imply SYS_NAND_USE_FLASH_BBT
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index 1d96e4bdc2..c980ba4edb 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -282,6 +282,16 @@ static int mc_fixup_dpl_mac_addr(void *blob, int dpmac_id,
MC_FIXUP_DPL);
}
+void fdt_fixup_mc_ddr(u64 *base, u64 *size)
+{
+ u64 mc_size = mc_get_dram_block_size();
+
+ if (mc_size < MC_DRAM_BLOCK_DEFAULT_SIZE) {
+ *base = mc_get_dram_addr() + mc_size;
+ *size = MC_DRAM_BLOCK_DEFAULT_SIZE - mc_size;
+ }
+}
+
void fdt_fsl_mc_fixup_iommu_map_entry(void *blob)
{
u32 *prop;
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index d4965e2ef6..47f101e280 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -73,6 +73,9 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
u64 *prp_pool;
int length = total_len;
int i, nprps;
+ u32 prps_per_page = (page_size >> 3) - 1;
+ u32 num_pages;
+
length -= (page_size - offset);
if (length <= 0) {
@@ -89,15 +92,20 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
}
nprps = DIV_ROUND_UP(length, page_size);
+ num_pages = DIV_ROUND_UP(nprps, prps_per_page);
if (nprps > dev->prp_entry_num) {
free(dev->prp_pool);
- dev->prp_pool = malloc(nprps << 3);
+ /*
+ * Always increase in increments of pages. It doesn't waste
+ * much memory and reduces the number of allocations.
+ */
+ dev->prp_pool = memalign(page_size, num_pages * page_size);
if (!dev->prp_pool) {
printf("Error: malloc prp_pool fail\n");
return -ENOMEM;
}
- dev->prp_entry_num = nprps;
+ dev->prp_entry_num = prps_per_page * num_pages;
}
prp_pool = dev->prp_pool;
@@ -788,14 +796,6 @@ static int nvme_probe(struct udevice *udev)
}
memset(ndev->queues, 0, NVME_Q_NUM * sizeof(struct nvme_queue *));
- ndev->prp_pool = malloc(MAX_PRP_POOL);
- if (!ndev->prp_pool) {
- ret = -ENOMEM;
- printf("Error: %s: Out of memory!\n", udev->name);
- goto free_nvme;
- }
- ndev->prp_entry_num = MAX_PRP_POOL >> 3;
-
ndev->cap = nvme_readq(&ndev->bar->cap);
ndev->q_depth = min_t(int, NVME_CAP_MQES(ndev->cap) + 1, NVME_Q_DEPTH);
ndev->db_stride = 1 << NVME_CAP_STRIDE(ndev->cap);
@@ -805,6 +805,15 @@ static int nvme_probe(struct udevice *udev)
if (ret)
goto free_queue;
+ /* Allocate after the page size is known */
+ ndev->prp_pool = memalign(ndev->page_size, MAX_PRP_POOL);
+ if (!ndev->prp_pool) {
+ ret = -ENOMEM;
+ printf("Error: %s: Out of memory!\n", udev->name);
+ goto free_nvme;
+ }
+ ndev->prp_entry_num = MAX_PRP_POOL >> 3;
+
ret = nvme_setup_io_queues(ndev);
if (ret)
goto free_queue;
diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c
index 4d61a46cef..ab25aeee73 100644
--- a/drivers/pci/pcie_fsl.c
+++ b/drivers/pci/pcie_fsl.c
@@ -299,8 +299,9 @@ static int fsl_pcie_setup_inbound_win(struct fsl_pcie *pcie, int idx,
out_be32(&pi->piwbear, 0);
#endif
- if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_A005434))
- flag = 0;
+#ifdef CONFIG_SYS_FSL_ERRATUM_A005434
+ flag = 0;
+#endif
flag |= PIWAR_EN | PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
if (pf)
@@ -401,47 +402,47 @@ static int fsl_pcie_init_port(struct fsl_pcie *pcie)
fsl_pcie_init_atmu(pcie);
- if (IS_ENABLED(CONFIG_FSL_PCIE_DISABLE_ASPM)) {
- val_32 = 0;
- fsl_pcie_hose_read_config_dword(pcie, PCI_LCR, &val_32);
- val_32 &= ~0x03;
- fsl_pcie_hose_write_config_dword(pcie, PCI_LCR, val_32);
- udelay(1);
- }
+#ifdef CONFIG_FSL_PCIE_DISABLE_ASPM
+ val_32 = 0;
+ fsl_pcie_hose_read_config_dword(pcie, PCI_LCR, &val_32);
+ val_32 &= ~0x03;
+ fsl_pcie_hose_write_config_dword(pcie, PCI_LCR, val_32);
+ udelay(1);
+#endif
- if (IS_ENABLED(CONFIG_FSL_PCIE_RESET)) {
- u16 ltssm;
- int i;
+#ifdef CONFIG_FSL_PCIE_RESET
+ u16 ltssm;
+ int i;
- if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
+ if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
+ /* assert PCIe reset */
+ setbits_be32(&regs->pdb_stat, 0x08000000);
+ (void)in_be32(&regs->pdb_stat);
+ udelay(1000);
+ /* clear PCIe reset */
+ clrbits_be32(&regs->pdb_stat, 0x08000000);
+ asm("sync;isync");
+ for (i = 0; i < 100 && !fsl_pcie_link_up(pcie); i++)
+ udelay(1000);
+ } else {
+ fsl_pcie_hose_read_config_word(pcie, PCI_LTSSM, &ltssm);
+ if (ltssm == 1) {
/* assert PCIe reset */
setbits_be32(&regs->pdb_stat, 0x08000000);
(void)in_be32(&regs->pdb_stat);
- udelay(1000);
+ udelay(100);
/* clear PCIe reset */
clrbits_be32(&regs->pdb_stat, 0x08000000);
asm("sync;isync");
- for (i = 0; i < 100 && !fsl_pcie_link_up(pcie); i++)
+ for (i = 0; i < 100 &&
+ !fsl_pcie_link_up(pcie); i++)
udelay(1000);
- } else {
- fsl_pcie_hose_read_config_word(pcie, PCI_LTSSM, &ltssm);
- if (ltssm == 1) {
- /* assert PCIe reset */
- setbits_be32(&regs->pdb_stat, 0x08000000);
- (void)in_be32(&regs->pdb_stat);
- udelay(100);
- /* clear PCIe reset */
- clrbits_be32(&regs->pdb_stat, 0x08000000);
- asm("sync;isync");
- for (i = 0; i < 100 &&
- !fsl_pcie_link_up(pcie); i++)
- udelay(1000);
- }
}
}
+#endif
- if (IS_ENABLED(CONFIG_SYS_P4080_ERRATUM_PCIE_A003) &&
- !fsl_pcie_link_up(pcie)) {
+#ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003
+ if (!fsl_pcie_link_up(pcie)) {
serdes_corenet_t *srds_regs;
srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
@@ -460,13 +461,15 @@ static int fsl_pcie_init_port(struct fsl_pcie *pcie)
udelay(1000);
}
}
+#endif
/*
* The Read-Only Write Enable bit defaults to 1 instead of 0.
* Set to 0 to protect the read-only registers.
*/
- if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_A007815))
- clrbits_be32(&regs->dbi_ro_wr_en, 0x01);
+#ifdef CONFIG_SYS_FSL_ERRATUM_A007815
+ clrbits_be32(&regs->dbi_ro_wr_en, 0x01);
+#endif
/*
* Enable All Error Interrupts except
@@ -500,14 +503,23 @@ static int fsl_pcie_init_port(struct fsl_pcie *pcie)
static int fsl_pcie_fixup_classcode(struct fsl_pcie *pcie)
{
ccsr_fsl_pci_t *regs = pcie->regs;
+ u32 classcode_reg;
u32 val;
- setbits_be32(&regs->dbi_ro_wr_en, 0x01);
- fsl_pcie_hose_read_config_dword(pcie, PCI_CLASS_REVISION, &val);
+ if (pcie->block_rev >= PEX_IP_BLK_REV_3_0) {
+ classcode_reg = PCI_CLASS_REVISION;
+ setbits_be32(&regs->dbi_ro_wr_en, 0x01);
+ } else {
+ classcode_reg = CSR_CLASSCODE;
+ }
+
+ fsl_pcie_hose_read_config_dword(pcie, classcode_reg, &val);
val &= 0xff;
val |= PCI_CLASS_BRIDGE_PCI << 16;
- fsl_pcie_hose_write_config_dword(pcie, PCI_CLASS_REVISION, val);
- clrbits_be32(&regs->dbi_ro_wr_en, 0x01);
+ fsl_pcie_hose_write_config_dword(pcie, classcode_reg, val);
+
+ if (pcie->block_rev >= PEX_IP_BLK_REV_3_0)
+ clrbits_be32(&regs->dbi_ro_wr_en, 0x01);
return 0;
}
@@ -570,6 +582,7 @@ static int fsl_pcie_probe(struct udevice *dev)
static int fsl_pcie_ofdata_to_platdata(struct udevice *dev)
{
struct fsl_pcie *pcie = dev_get_priv(dev);
+ struct fsl_pcie_data *info;
int ret;
pcie->regs = dev_remap_addr(dev);
@@ -584,7 +597,10 @@ static int fsl_pcie_ofdata_to_platdata(struct udevice *dev)
return ret;
}
- pcie->idx = (dev_read_addr(dev) - 0xffe240000) / 0x10000;
+ info = (struct fsl_pcie_data *)dev_get_driver_data(dev);
+ pcie->info = info;
+ pcie->idx = abs((u32)(dev_read_addr(dev) & info->block_offset_mask) -
+ info->block_offset) / info->stride;
return 0;
}
@@ -594,8 +610,35 @@ static const struct dm_pci_ops fsl_pcie_ops = {
.write_config = fsl_pcie_write_config,
};
+static struct fsl_pcie_data p1_p2_data = {
+ .block_offset = 0xa000,
+ .block_offset_mask = 0xffff,
+ .stride = 0x1000,
+};
+
+static struct fsl_pcie_data p2041_data = {
+ .block_offset = 0x200000,
+ .block_offset_mask = 0x3fffff,
+ .stride = 0x1000,
+};
+
+static struct fsl_pcie_data t2080_data = {
+ .block_offset = 0x240000,
+ .block_offset_mask = 0x3fffff,
+ .stride = 0x10000,
+};
+
static const struct udevice_id fsl_pcie_ids[] = {
- { .compatible = "fsl,pcie-t2080" },
+ { .compatible = "fsl,pcie-mpc8548", .data = (ulong)&p1_p2_data },
+ { .compatible = "fsl,pcie-p1_p2", .data = (ulong)&p1_p2_data },
+ { .compatible = "fsl,pcie-p2041", .data = (ulong)&p2041_data },
+ { .compatible = "fsl,pcie-p3041", .data = (ulong)&p2041_data },
+ { .compatible = "fsl,pcie-p4080", .data = (ulong)&p2041_data },
+ { .compatible = "fsl,pcie-p5040", .data = (ulong)&p2041_data },
+ { .compatible = "fsl,pcie-t102x", .data = (ulong)&t2080_data },
+ { .compatible = "fsl,pcie-t104x", .data = (ulong)&t2080_data },
+ { .compatible = "fsl,pcie-t2080", .data = (ulong)&t2080_data },
+ { .compatible = "fsl,pcie-t4240", .data = (ulong)&t2080_data },
{ }
};
diff --git a/drivers/pci/pcie_fsl.h b/drivers/pci/pcie_fsl.h
index 5eefc31fa9..dc8368d559 100644
--- a/drivers/pci/pcie_fsl.h
+++ b/drivers/pci/pcie_fsl.h
@@ -9,6 +9,9 @@
#ifndef _PCIE_FSL_H_
#define _PCIE_FSL_H_
+/* GPEX CSR */
+#define CSR_CLASSCODE 0x474
+
#ifdef CONFIG_SYS_FSL_PCI_VER_3_X
#define FSL_PCIE_CAP_ID 0x70
#else
@@ -40,6 +43,12 @@
#define LTSSM_L0_REV3 0x11
#define LTSSM_L0 0x16
+struct fsl_pcie_data {
+ u32 block_offset; /* Offset from CCSR of 1st controller */
+ u32 block_offset_mask; /* Mask out the CCSR base */
+ u32 stride; /* Offset stride between controllers */
+};
+
struct fsl_pcie {
int idx;
struct udevice *bus;
@@ -49,6 +58,7 @@ struct fsl_pcie {
bool mode; /* RC&EP mode flag */
bool enabled; /* Enable status */
struct list_head list;
+ struct fsl_pcie_data *info;
};
extern struct list_head fsl_pcie_list;
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 3942f035eb..02312273e2 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -19,7 +19,7 @@ config PHY
config SPL_PHY
bool "PHY Core in SPL"
- depends on DM
+ depends on DM && SPL
help
PHY support in SPL.
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index 5431df9813..0b5a0433cd 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -231,23 +231,23 @@ static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin,
switch (param) {
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ ret = stmfx_pinctrl_set_type(dev, pin, 0);
+ break;
case PIN_CONFIG_BIAS_PULL_DOWN:
+ ret = stmfx_pinctrl_set_type(dev, pin, 1);
+ if (ret)
+ return ret;
ret = stmfx_pinctrl_set_pupd(dev, pin, 0);
break;
case PIN_CONFIG_BIAS_PULL_UP:
+ ret = stmfx_pinctrl_set_type(dev, pin, 1);
+ if (ret)
+ return ret;
ret = stmfx_pinctrl_set_pupd(dev, pin, 1);
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
- if (dir == GPIOF_OUTPUT)
- ret = stmfx_pinctrl_set_type(dev, pin, 1);
- else
- ret = stmfx_pinctrl_set_type(dev, pin, 0);
- break;
- case PIN_CONFIG_DRIVE_PUSH_PULL:
- if (dir == GPIOF_OUTPUT)
- ret = stmfx_pinctrl_set_type(dev, pin, 0);
- else
- ret = stmfx_pinctrl_set_type(dev, pin, 1);
+ ret = stmfx_pinctrl_set_type(dev, pin, 1);
break;
case PIN_CONFIG_OUTPUT:
ret = stmfx_gpio_direction_output(plat->gpio, pin, arg);
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index cdbe463cff..3a235ae5a7 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -1,11 +1,11 @@
#include <common.h>
#include <dm.h>
-#include <dm/lists.h>
-#include <dm/pinctrl.h>
#include <hwspinlock.h>
#include <asm/arch/gpio.h>
#include <asm/gpio.h>
#include <asm/io.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
DECLARE_GLOBAL_DATA_PTR;
diff --git a/drivers/power/pmic/stpmic1.c b/drivers/power/pmic/stpmic1.c
index c3381489dd..de31934f41 100644
--- a/drivers/power/pmic/stpmic1.c
+++ b/drivers/power/pmic/stpmic1.c
@@ -7,6 +7,7 @@
#include <dm.h>
#include <errno.h>
#include <i2c.h>
+#include <misc.h>
#include <sysreset.h>
#include <dm/device.h>
#include <dm/lists.h>
@@ -69,6 +70,7 @@ static int stpmic1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
static int stpmic1_bind(struct udevice *dev)
{
+ int ret;
#if CONFIG_IS_ENABLED(DM_REGULATOR)
ofnode regulators_node;
int children;
@@ -86,6 +88,13 @@ static int stpmic1_bind(struct udevice *dev)
dev_dbg(dev, "no child found\n");
#endif /* DM_REGULATOR */
+ if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
+ ret = device_bind_driver(dev, "stpmic1-nvm",
+ "stpmic1-nvm", NULL);
+ if (ret)
+ return ret;
+ }
+
if (CONFIG_IS_ENABLED(SYSRESET))
return device_bind_driver(dev, "stpmic1-sysreset",
"stpmic1-sysreset", NULL);
@@ -113,32 +122,38 @@ U_BOOT_DRIVER(pmic_stpmic1) = {
};
#ifndef CONFIG_SPL_BUILD
-static int stpmic1_nvm_rw(u8 addr, u8 *buf, int buf_len, enum pmic_nvm_op op)
+static int stpmic1_nvm_rw(struct udevice *dev, u8 addr, u8 *buf, int buf_len,
+ enum pmic_nvm_op op)
{
- struct udevice *dev;
unsigned long timeout;
u8 cmd = STPMIC1_NVM_CMD_READ;
- int ret;
-
- ret = uclass_get_device_by_driver(UCLASS_PMIC,
- DM_GET_DRIVER(pmic_stpmic1), &dev);
- if (ret)
- /* No PMIC on power discrete board */
- return -EOPNOTSUPP;
+ int ret, len = buf_len;
if (addr < STPMIC1_NVM_START_ADDRESS)
return -EACCES;
+ if (addr + buf_len > STPMIC1_NVM_START_ADDRESS + STPMIC1_NVM_SIZE)
+ len = STPMIC1_NVM_START_ADDRESS + STPMIC1_NVM_SIZE - addr;
- if (op == SHADOW_READ)
- return pmic_read(dev, addr, buf, buf_len);
+ if (op == SHADOW_READ) {
+ ret = pmic_read(dev, addr, buf, len);
+ if (ret < 0)
+ return ret;
+ else
+ return len;
+ }
- if (op == SHADOW_WRITE)
- return pmic_write(dev, addr, buf, buf_len);
+ if (op == SHADOW_WRITE) {
+ ret = pmic_write(dev, addr, buf, len);
+ if (ret < 0)
+ return ret;
+ else
+ return len;
+ }
if (op == NVM_WRITE) {
cmd = STPMIC1_NVM_CMD_PROGRAM;
- ret = pmic_write(dev, addr, buf, buf_len);
+ ret = pmic_write(dev, addr, buf, len);
if (ret < 0)
return ret;
}
@@ -168,69 +183,61 @@ static int stpmic1_nvm_rw(u8 addr, u8 *buf, int buf_len, enum pmic_nvm_op op)
return -ETIMEDOUT;
if (op == NVM_READ) {
- ret = pmic_read(dev, addr, buf, buf_len);
+ ret = pmic_read(dev, addr, buf, len);
if (ret < 0)
return ret;
}
- return 0;
+ return len;
}
-int stpmic1_shadow_read_byte(u8 addr, u8 *buf)
+static int stpmic1_nvm_read(struct udevice *dev, int offset,
+ void *buf, int size)
{
- return stpmic1_nvm_rw(addr, buf, 1, SHADOW_READ);
-}
+ enum pmic_nvm_op op = NVM_READ;
-int stpmic1_shadow_write_byte(u8 addr, u8 *buf)
-{
- return stpmic1_nvm_rw(addr, buf, 1, SHADOW_WRITE);
-}
+ if (offset < 0) {
+ op = SHADOW_READ;
+ offset = -offset;
+ }
-int stpmic1_nvm_read_byte(u8 addr, u8 *buf)
-{
- return stpmic1_nvm_rw(addr, buf, 1, NVM_READ);
+ return stpmic1_nvm_rw(dev->parent, offset, buf, size, op);
}
-int stpmic1_nvm_write_byte(u8 addr, u8 *buf)
+static int stpmic1_nvm_write(struct udevice *dev, int offset,
+ const void *buf, int size)
{
- return stpmic1_nvm_rw(addr, buf, 1, NVM_WRITE);
-}
+ enum pmic_nvm_op op = NVM_WRITE;
-int stpmic1_nvm_read_all(u8 *buf, int buf_len)
-{
- if (buf_len != STPMIC1_NVM_SIZE)
- return -EINVAL;
+ if (offset < 0) {
+ op = SHADOW_WRITE;
+ offset = -offset;
+ }
- return stpmic1_nvm_rw(STPMIC1_NVM_START_ADDRESS,
- buf, buf_len, NVM_READ);
+ return stpmic1_nvm_rw(dev->parent, offset, (void *)buf, size, op);
}
-int stpmic1_nvm_write_all(u8 *buf, int buf_len)
-{
- if (buf_len != STPMIC1_NVM_SIZE)
- return -EINVAL;
+static const struct misc_ops stpmic1_nvm_ops = {
+ .read = stpmic1_nvm_read,
+ .write = stpmic1_nvm_write,
+};
- return stpmic1_nvm_rw(STPMIC1_NVM_START_ADDRESS,
- buf, buf_len, NVM_WRITE);
-}
+U_BOOT_DRIVER(stpmic1_nvm) = {
+ .name = "stpmic1-nvm",
+ .id = UCLASS_MISC,
+ .ops = &stpmic1_nvm_ops,
+};
#endif /* CONFIG_SPL_BUILD */
#ifdef CONFIG_SYSRESET
static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
- struct udevice *pmic_dev;
+ struct udevice *pmic_dev = dev->parent;
int ret;
if (type != SYSRESET_POWER && type != SYSRESET_POWER_OFF)
return -EPROTONOSUPPORT;
- ret = uclass_get_device_by_driver(UCLASS_PMIC,
- DM_GET_DRIVER(pmic_stpmic1),
- &pmic_dev);
-
- if (ret)
- return -EOPNOTSUPP;
-
ret = pmic_reg_read(pmic_dev, STPMIC1_MAIN_CR);
if (ret < 0)
return ret;
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index 81fc71c051..ed70137ce7 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -1488,6 +1488,84 @@ static void dram_all_config(struct dram_info *dram,
clrsetbits_le32(&dram->cru->glb_rst_con, 0x3, 0x3);
}
+static void set_cap_relate_config(const struct chan_info *chan,
+ struct rk3399_sdram_params *params,
+ unsigned int channel)
+{
+ u32 *denali_ctl = chan->pctl->denali_ctl;
+ u32 tmp;
+ struct rk3399_msch_timings *noc_timing;
+
+ if (params->base.dramtype == LPDDR3) {
+ tmp = (8 << params->ch[channel].cap_info.bw) /
+ (8 << params->ch[channel].cap_info.dbw);
+
+ /**
+ * memdata_ratio
+ * 1 -> 0, 2 -> 1, 4 -> 2
+ */
+ clrsetbits_le32(&denali_ctl[197], 0x7,
+ (tmp >> 1));
+ clrsetbits_le32(&denali_ctl[198], 0x7 << 8,
+ (tmp >> 1) << 8);
+ }
+
+ noc_timing = &params->ch[channel].noc_timings;
+
+ /*
+ * noc timing bw relate timing is 32 bit, and real bw is 16bit
+ * actually noc reg is setting at function dram_all_config
+ */
+ if (params->ch[channel].cap_info.bw == 16 &&
+ noc_timing->ddrmode.b.mwrsize == 2) {
+ if (noc_timing->ddrmode.b.burstsize)
+ noc_timing->ddrmode.b.burstsize -= 1;
+ noc_timing->ddrmode.b.mwrsize -= 1;
+ noc_timing->ddrtimingc0.b.burstpenalty *= 2;
+ noc_timing->ddrtimingc0.b.wrtomwr *= 2;
+ }
+}
+
+static u32 calculate_ddrconfig(struct rk3399_sdram_params *params, u32 channel)
+{
+ unsigned int cs0_row = params->ch[channel].cap_info.cs0_row;
+ unsigned int col = params->ch[channel].cap_info.col;
+ unsigned int bw = params->ch[channel].cap_info.bw;
+ u16 ddr_cfg_2_rbc[] = {
+ /*
+ * [6] highest bit col
+ * [5:3] max row(14+n)
+ * [2] insertion row
+ * [1:0] col(9+n),col, data bus 32bit
+ *
+ * highbitcol, max_row, insertion_row, col
+ */
+ ((0 << 6) | (2 << 3) | (0 << 2) | 0), /* 0 */
+ ((0 << 6) | (2 << 3) | (0 << 2) | 1), /* 1 */
+ ((0 << 6) | (1 << 3) | (0 << 2) | 2), /* 2 */
+ ((0 << 6) | (0 << 3) | (0 << 2) | 3), /* 3 */
+ ((0 << 6) | (2 << 3) | (1 << 2) | 1), /* 4 */
+ ((0 << 6) | (1 << 3) | (1 << 2) | 2), /* 5 */
+ ((1 << 6) | (0 << 3) | (0 << 2) | 2), /* 6 */
+ ((1 << 6) | (1 << 3) | (0 << 2) | 2), /* 7 */
+ };
+ u32 i;
+
+ col -= (bw == 2) ? 0 : 1;
+ col -= 9;
+
+ for (i = 0; i < 4; i++) {
+ if ((col == (ddr_cfg_2_rbc[i] & 0x3)) &&
+ (cs0_row <= (((ddr_cfg_2_rbc[i] >> 3) & 0x7) + 14)))
+ break;
+ }
+
+ if (i >= 4)
+ i = -EINVAL;
+
+ return i;
+}
+
#if !defined(CONFIG_RAM_RK3399_LPDDR4)
static int default_data_training(struct dram_info *dram, u32 channel, u8 rank,
struct rk3399_sdram_params *params)
@@ -1588,84 +1666,6 @@ static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride)
rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10);
}
-static void set_cap_relate_config(const struct chan_info *chan,
- struct rk3399_sdram_params *params,
- unsigned int channel)
-{
- u32 *denali_ctl = chan->pctl->denali_ctl;
- u32 tmp;
- struct rk3399_msch_timings *noc_timing;
-
- if (params->base.dramtype == LPDDR3) {
- tmp = (8 << params->ch[channel].cap_info.bw) /
- (8 << params->ch[channel].cap_info.dbw);
-
- /**
- * memdata_ratio
- * 1 -> 0, 2 -> 1, 4 -> 2
- */
- clrsetbits_le32(&denali_ctl[197], 0x7,
- (tmp >> 1));
- clrsetbits_le32(&denali_ctl[198], 0x7 << 8,
- (tmp >> 1) << 8);
- }
-
- noc_timing = &params->ch[channel].noc_timings;
-
- /*
- * noc timing bw relate timing is 32 bit, and real bw is 16bit
- * actually noc reg is setting at function dram_all_config
- */
- if (params->ch[channel].cap_info.bw == 16 &&
- noc_timing->ddrmode.b.mwrsize == 2) {
- if (noc_timing->ddrmode.b.burstsize)
- noc_timing->ddrmode.b.burstsize -= 1;
- noc_timing->ddrmode.b.mwrsize -= 1;
- noc_timing->ddrtimingc0.b.burstpenalty *= 2;
- noc_timing->ddrtimingc0.b.wrtomwr *= 2;
- }
-}
-
-static u32 calculate_ddrconfig(struct rk3399_sdram_params *params, u32 channel)
-{
- unsigned int cs0_row = params->ch[channel].cap_info.cs0_row;
- unsigned int col = params->ch[channel].cap_info.col;
- unsigned int bw = params->ch[channel].cap_info.bw;
- u16 ddr_cfg_2_rbc[] = {
- /*
- * [6] highest bit col
- * [5:3] max row(14+n)
- * [2] insertion row
- * [1:0] col(9+n),col, data bus 32bit
- *
- * highbitcol, max_row, insertion_row, col
- */
- ((0 << 6) | (2 << 3) | (0 << 2) | 0), /* 0 */
- ((0 << 6) | (2 << 3) | (0 << 2) | 1), /* 1 */
- ((0 << 6) | (1 << 3) | (0 << 2) | 2), /* 2 */
- ((0 << 6) | (0 << 3) | (0 << 2) | 3), /* 3 */
- ((0 << 6) | (2 << 3) | (1 << 2) | 1), /* 4 */
- ((0 << 6) | (1 << 3) | (1 << 2) | 2), /* 5 */
- ((1 << 6) | (0 << 3) | (0 << 2) | 2), /* 6 */
- ((1 << 6) | (1 << 3) | (0 << 2) | 2), /* 7 */
- };
- u32 i;
-
- col -= (bw == 2) ? 0 : 1;
- col -= 9;
-
- for (i = 0; i < 4; i++) {
- if ((col == (ddr_cfg_2_rbc[i] & 0x3)) &&
- (cs0_row <= (((ddr_cfg_2_rbc[i] >> 3) & 0x7) + 14)))
- break;
- }
-
- if (i >= 4)
- i = -EINVAL;
-
- return i;
-}
-
/**
* read mr_num mode register
* rank = 1: cs0
@@ -2592,8 +2592,11 @@ static int sdram_init(struct dram_info *dram,
}
sdram_print_ddr_info(cap_info, &params->base);
+ set_memory_map(chan, channel, params);
+ cap_info->ddrconfig = calculate_ddrconfig(params, channel);
set_ddrconfig(chan, params, channel, cap_info->ddrconfig);
+ set_cap_relate_config(chan, params, channel);
}
if (params->base.num_channels == 0) {
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.h b/drivers/ram/stm32mp1/stm32mp1_ddr.h
index a8eed89e3c..52b748f3ca 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ddr.h
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr.h
@@ -197,10 +197,6 @@ void stm32mp1_edit_param(const struct stm32mp1_ddr_config *config,
char *name,
char *string);
-void stm32mp1_dump_info(
- const struct ddr_info *priv,
- const struct stm32mp1_ddr_config *config);
-
bool stm32mp1_ddr_interactive(
void *priv,
enum stm32mp1_ddr_interact_step step,
diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.c b/drivers/ram/stm32mp1/stm32mp1_tests.c
index b6fb2a9c58..581ee4897f 100644
--- a/drivers/ram/stm32mp1/stm32mp1_tests.c
+++ b/drivers/ram/stm32mp1/stm32mp1_tests.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
#include <console.h>
+#include <watchdog.h>
#include <asm/io.h>
#include <linux/log2.h>
#include "stm32mp1_tests.h"
@@ -154,6 +155,8 @@ static int test_loop_end(u32 *loop, u32 nb_loop, u32 progress)
return 1;
}
printf("loop #%d\n", *loop);
+ WATCHDOG_RESET();
+
return 0;
}
@@ -578,27 +581,29 @@ static enum test_result test_random(struct stm32mp1_ddrctl *ctl,
u32 error = 0;
unsigned int seed;
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 8 * 1024))
return TEST_ERROR;
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
return TEST_ERROR;
if (get_addr(string, argc, argv, 2, &addr))
return TEST_ERROR;
- printf("running %d loops at 0x%x\n", nb_loop, addr);
+ bufsize /= 2;
+ printf("running %d loops copy from 0x%x to 0x%x (buffer size=0x%x)\n",
+ nb_loop, addr, addr + bufsize, bufsize);
while (!error) {
seed = rand();
- for (offset = addr; offset < addr + bufsize; offset += 4)
- writel(rand(), offset);
+ for (offset = 0; offset < bufsize; offset += 4)
+ writel(rand(), addr + offset);
memcpy((void *)addr + bufsize, (void *)addr, bufsize);
srand(seed);
- for (offset = addr; offset < addr + 2 * bufsize; offset += 4) {
- if (offset == (addr + bufsize))
+ for (offset = 0; offset < 2 * bufsize; offset += 4) {
+ if (offset == bufsize)
srand(seed);
value = rand();
- error = check_addr(offset, value);
+ error = check_addr(addr + offset, value);
if (error)
break;
if (progress(offset))
@@ -607,6 +612,7 @@ static enum test_result test_random(struct stm32mp1_ddrctl *ctl,
if (test_loop_end(&loop, nb_loop, 100))
break;
}
+ putc('\n');
if (error) {
sprintf(string,
@@ -791,9 +797,9 @@ static enum test_result test_loop(const u32 *pattern, u32 *address,
int i;
int j;
enum test_result res = TEST_PASSED;
- u32 *offset, testsize, remaining;
+ u32 offset, testsize, remaining;
- offset = address;
+ offset = (u32)address;
remaining = bufsize;
while (remaining) {
testsize = bufsize > 0x1000000 ? 0x1000000 : bufsize;
@@ -809,7 +815,7 @@ static enum test_result test_loop(const u32 *pattern, u32 *address,
__asm__("stmia r1!, {R3-R10}");
__asm__("stmia r1!, {R3-R10}");
__asm__("stmia r1!, {R3-R10}");
- __asm__("subs r2, r2, #8");
+ __asm__("subs r2, r2, #128");
__asm__("bge loop2");
__asm__("pop {R0-R10}");
@@ -1238,27 +1244,38 @@ static enum test_result test_read(struct stm32mp1_ddrctl *ctl,
u32 *addr;
u32 data;
u32 loop = 0;
+ int i, size = 1024 * 1024;
bool random = false;
if (get_addr(string, argc, argv, 0, (u32 *)&addr))
return TEST_ERROR;
+ if (get_pattern(string, argc, argv, 1, &data, 0xA5A5AA55))
+ return TEST_ERROR;
+
if ((u32)addr == ADDR_INVALID) {
- printf("random ");
+ printf("running random\n");
random = true;
+ } else {
+ printf("running at 0x%08x with pattern=0x%08x\n",
+ (u32)addr, data);
+ writel(data, addr);
}
- printf("running at 0x%08x\n", (u32)addr);
-
while (1) {
- if (random)
- addr = (u32 *)(STM32_DDR_BASE +
- (rand() & (STM32_DDR_SIZE - 1) & ~0x3));
- data = readl(addr);
- if (test_loop_end(&loop, 0, 1000))
+ for (i = 0; i < size; i++) {
+ if (random)
+ addr = (u32 *)(STM32_DDR_BASE +
+ (rand() & (STM32_DDR_SIZE - 1) & ~0x3));
+ data = readl(addr);
+ }
+ if (test_loop_end(&loop, 0, 1))
break;
}
- sprintf(string, "0x%x: %x", (u32)addr, data);
+ if (random)
+ sprintf(string, "%d loops random", loop);
+ else
+ sprintf(string, "%d loops at 0x%x: %x", loop, (u32)addr, data);
return TEST_PASSED;
}
@@ -1275,31 +1292,41 @@ static enum test_result test_write(struct stm32mp1_ddrctl *ctl,
char *string, int argc, char *argv[])
{
u32 *addr;
- u32 data = 0xA5A5AA55;
+ u32 data;
u32 loop = 0;
+ int i, size = 1024 * 1024;
bool random = false;
if (get_addr(string, argc, argv, 0, (u32 *)&addr))
return TEST_ERROR;
+ if (get_pattern(string, argc, argv, 1, &data, 0xA5A5AA55))
+ return TEST_ERROR;
+
if ((u32)addr == ADDR_INVALID) {
- printf("random ");
+ printf("running random\n");
random = true;
+ } else {
+ printf("running at 0x%08x with pattern 0x%08x\n",
+ (u32)addr, data);
}
- printf("running at 0x%08x\n", (u32)addr);
-
while (1) {
- if (random) {
- addr = (u32 *)(STM32_DDR_BASE +
- (rand() & (STM32_DDR_SIZE - 1) & ~0x3));
- data = rand();
+ for (i = 0; i < size; i++) {
+ if (random) {
+ addr = (u32 *)(STM32_DDR_BASE +
+ (rand() & (STM32_DDR_SIZE - 1) & ~0x3));
+ data = rand();
+ }
+ writel(data, addr);
}
- writel(data, addr);
- if (test_loop_end(&loop, 0, 1000))
+ if (test_loop_end(&loop, 0, 1))
break;
}
- sprintf(string, "0x%x: %x", (u32)addr, data);
+ if (random)
+ sprintf(string, "%d loops random", loop);
+ else
+ sprintf(string, "%d loops at 0x%x: %x", loop, (u32)addr, data);
return TEST_PASSED;
}
@@ -1388,7 +1415,7 @@ const struct test_desc test[] = {
"Verifies r/w and memcopy(burst for pseudo random value.",
3
},
- {test_freq_pattern, "FrequencySelectivePattern ", "[size]",
+ {test_freq_pattern, "FrequencySelectivePattern", "[size]",
"write & test patterns: Mostly Zero, Mostly One and F/n",
1
},
@@ -1417,10 +1444,10 @@ const struct test_desc test[] = {
3
},
/* need to the the 2 last one (infinite) : skipped for test all */
- {test_read, "infinite read", "[addr]",
- "basic test : infinite read access", 1},
- {test_write, "infinite write", "[addr]",
- "basic test : infinite write access", 1},
+ {test_read, "infinite read", "[addr] [pattern]",
+ "basic test : infinite read access (random: addr=0xFFFFFFFF)", 2},
+ {test_write, "infinite write", "[addr] [pattern]",
+ "basic test : infinite write access (random: addr=0xFFFFFFFF)", 2},
};
const int test_nb = ARRAY_SIZE(test);
diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c
index de3b9729f3..ad941f67e8 100644
--- a/drivers/remoteproc/stm32_copro.c
+++ b/drivers/remoteproc/stm32_copro.c
@@ -243,7 +243,7 @@ static const struct dm_rproc_ops stm32_copro_ops = {
};
static const struct udevice_id stm32_copro_ids[] = {
- {.compatible = "st,stm32mp1-rproc"},
+ {.compatible = "st,stm32mp1-m4"},
{}
};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 860b73d369..8778cc7b26 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -31,6 +31,12 @@ config TPL_DM_RTC
drivers to perform the actual functions. See rtc.h for a
description of the API.
+config RTC_ENABLE_32KHZ_OUTPUT
+ bool "Enable RTC 32Khz output"
+ help
+ Some real-time clocks support the output of 32kHz square waves (such as ds3231),
+ the config symbol choose Real Time Clock device 32Khz output feature.
+
config RTC_PCF2127
bool "Enable PCF2127 driver"
depends on DM_RTC
diff --git a/drivers/rtc/ds3231.c b/drivers/rtc/ds3231.c
index 79b026af4b..fde4d860ec 100644
--- a/drivers/rtc/ds3231.c
+++ b/drivers/rtc/ds3231.c
@@ -148,11 +148,13 @@ void rtc_reset (void)
/*
* Enable 32KHz output
*/
+#ifdef CONFIG_RTC_ENABLE_32KHZ_OUTPUT
void rtc_enable_32khz_output(void)
{
rtc_write(RTC_STAT_REG_ADDR,
RTC_STAT_BIT_BB32KHZ | RTC_STAT_BIT_EN32KHZ);
}
+#endif
/*
* Helper functions
@@ -251,6 +253,21 @@ static int ds3231_probe(struct udevice *dev)
return 0;
}
+#ifdef CONFIG_RTC_ENABLE_32KHZ_OUTPUT
+int rtc_enable_32khz_output(int busnum, int chip_addr)
+{
+ int ret;
+ struct udevice *dev;
+
+ ret = i2c_get_chip_for_busnum(busnum, chip_addr, 1, &dev);
+ if (!ret)
+ ret = dm_i2c_reg_write(dev, RTC_STAT_REG_ADDR,
+ RTC_STAT_BIT_BB32KHZ |
+ RTC_STAT_BIT_EN32KHZ);
+ return ret;
+}
+#endif
+
static const struct rtc_ops ds3231_rtc_ops = {
.get = ds3231_rtc_get,
.set = ds3231_rtc_set,
diff --git a/drivers/rtc/stm32_rtc.c b/drivers/rtc/stm32_rtc.c
index abd339076a..2674714442 100644
--- a/drivers/rtc/stm32_rtc.c
+++ b/drivers/rtc/stm32_rtc.c
@@ -72,7 +72,8 @@ static int stm32_rtc_get(struct udevice *dev, struct rtc_time *tm)
tm->tm_mday = bcd2bin((dr & STM32_RTC_DATE) >> STM32_RTC_DATE_SHIFT);
tm->tm_mon = bcd2bin((dr & STM32_RTC_MONTH) >> STM32_RTC_MONTH_SHIFT);
- tm->tm_year = bcd2bin((dr & STM32_RTC_YEAR) >> STM32_RTC_YEAR_SHIFT);
+ tm->tm_year = 2000 +
+ bcd2bin((dr & STM32_RTC_YEAR) >> STM32_RTC_YEAR_SHIFT);
tm->tm_wday = bcd2bin((dr & STM32_RTC_WDAY) >> STM32_RTC_WDAY_SHIFT);
tm->tm_yday = 0;
tm->tm_isdst = 0;
@@ -174,6 +175,9 @@ static int stm32_rtc_set(struct udevice *dev, const struct rtc_time *tm)
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
+ if (tm->tm_year < 2000 || tm->tm_year > 2099)
+ return -EINVAL;
+
/* Time in BCD format */
t = (bin2bcd(tm->tm_sec) << STM32_RTC_SEC_SHIFT) & STM32_RTC_SEC;
t |= (bin2bcd(tm->tm_min) << STM32_RTC_MIN_SHIFT) & STM32_RTC_MIN;
@@ -182,7 +186,8 @@ static int stm32_rtc_set(struct udevice *dev, const struct rtc_time *tm)
/* Date in BCD format */
d = (bin2bcd(tm->tm_mday) << STM32_RTC_DATE_SHIFT) & STM32_RTC_DATE;
d |= (bin2bcd(tm->tm_mon) << STM32_RTC_MONTH_SHIFT) & STM32_RTC_MONTH;
- d |= (bin2bcd(tm->tm_year) << STM32_RTC_YEAR_SHIFT) & STM32_RTC_YEAR;
+ d |= (bin2bcd(tm->tm_year - 2000) << STM32_RTC_YEAR_SHIFT) &
+ STM32_RTC_YEAR;
d |= (bin2bcd(tm->tm_wday) << STM32_RTC_WDAY_SHIFT) & STM32_RTC_WDAY;
return stm32_rtc_set_time(dev, t, d);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 8a447fd6e3..ae2d819ba9 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -45,7 +45,7 @@ config SERIAL_PRESENT
config SPL_SERIAL_PRESENT
bool "Provide a serial driver in SPL"
- depends on DM_SERIAL
+ depends on DM_SERIAL && SPL
default y
help
In very space-constrained devices even the full UART driver is too
@@ -55,7 +55,7 @@ config SPL_SERIAL_PRESENT
config TPL_SERIAL_PRESENT
bool "Provide a serial driver in TPL"
- depends on DM_SERIAL
+ depends on DM_SERIAL && TPL
default y
help
In very space-constrained devices even the full UART driver is too
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c
index 3ab536a52a..00a8e7249b 100644
--- a/drivers/serial/serial_stm32.c
+++ b/drivers/serial/serial_stm32.c
@@ -106,10 +106,11 @@ static int stm32_serial_getc(struct udevice *dev)
if ((isr & USART_ISR_RXNE) == 0)
return -EAGAIN;
- if (isr & (USART_ISR_PE | USART_ISR_ORE)) {
+ if (isr & (USART_ISR_PE | USART_ISR_ORE | USART_ISR_FE)) {
if (!stm32f4)
setbits_le32(base + ICR_OFFSET,
- USART_ICR_PCECF | USART_ICR_ORECF);
+ USART_ICR_PCECF | USART_ICR_ORECF |
+ USART_ICR_FECF);
else
readl(base + RDR_OFFSET(stm32f4));
return -EIO;
diff --git a/drivers/serial/serial_stm32.h b/drivers/serial/serial_stm32.h
index 5549f8c536..7b0c53145e 100644
--- a/drivers/serial/serial_stm32.h
+++ b/drivers/serial/serial_stm32.h
@@ -67,6 +67,7 @@ struct stm32x7_serial_platdata {
#define USART_ISR_TXE BIT(7)
#define USART_ISR_RXNE BIT(5)
#define USART_ISR_ORE BIT(3)
+#define USART_ISR_FE BIT(1)
#define USART_ISR_PE BIT(0)
#define USART_BRR_F_MASK GENMASK(7, 0)
@@ -74,6 +75,7 @@ struct stm32x7_serial_platdata {
#define USART_BRR_M_MASK GENMASK(15, 4)
#define USART_ICR_ORECF BIT(3)
+#define USART_ICR_FECF BIT(1)
#define USART_ICR_PCECF BIT(0)
#endif