aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/Kconfig1
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/microchip/Kconfig5
-rw-r--r--drivers/clk/microchip/Makefile1
-rw-r--r--drivers/clk/microchip/mpfs_clk.c123
-rw-r--r--drivers/clk/microchip/mpfs_clk.h44
-rw-r--r--drivers/clk/microchip/mpfs_clk_cfg.c152
-rw-r--r--drivers/clk/microchip/mpfs_clk_periph.c187
-rw-r--r--drivers/core/uclass.c19
-rw-r--r--drivers/mtd/mtdcore.c2
-rw-r--r--drivers/net/macb.c144
-rw-r--r--drivers/net/macb.h6
-rw-r--r--drivers/power/regulator/Kconfig2
-rw-r--r--drivers/ram/k3-j721e/lpddr4.c14
-rw-r--r--drivers/ram/k3-j721e/lpddr4_private.h20
-rw-r--r--drivers/serial/Kconfig16
-rw-r--r--drivers/serial/serial-uclass.c9
-rw-r--r--drivers/timer/andes_plmt_timer.c21
-rw-r--r--drivers/timer/riscv_timer.c21
-rw-r--r--drivers/timer/sifive_clint_timer.c21
-rw-r--r--drivers/video/Kconfig2
21 files changed, 772 insertions, 39 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index db06f276ec..4aeaa0cd58 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -165,6 +165,7 @@ source "drivers/clk/exynos/Kconfig"
source "drivers/clk/imx/Kconfig"
source "drivers/clk/kendryte/Kconfig"
source "drivers/clk/meson/Kconfig"
+source "drivers/clk/microchip/Kconfig"
source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/owl/Kconfig"
source "drivers/clk/renesas/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f8383e523d..645709b855 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_INTEL) += intel/
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
obj-$(CONFIG_CLK_K210) += kendryte/
obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
+obj-$(CONFIG_CLK_MPFS) += microchip/
obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o
obj-$(CONFIG_CLK_OWL) += owl/
obj-$(CONFIG_CLK_RENESAS) += renesas/
diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig
new file mode 100644
index 0000000000..b70241559d
--- /dev/null
+++ b/drivers/clk/microchip/Kconfig
@@ -0,0 +1,5 @@
+config CLK_MPFS
+ bool "Clock support for Microchip PolarFire SoC"
+ depends on CLK && CLK_CCF
+ help
+ This enables support clock driver for Microchip PolarFire SoC platform.
diff --git a/drivers/clk/microchip/Makefile b/drivers/clk/microchip/Makefile
new file mode 100644
index 0000000000..904b345d75
--- /dev/null
+++ b/drivers/clk/microchip/Makefile
@@ -0,0 +1 @@
+obj-y += mpfs_clk.o mpfs_clk_cfg.o mpfs_clk_periph.o
diff --git a/drivers/clk/microchip/mpfs_clk.c b/drivers/clk/microchip/mpfs_clk.c
new file mode 100644
index 0000000000..722c79b7c0
--- /dev/null
+++ b/drivers/clk/microchip/mpfs_clk.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Microchip Technology Inc.
+ * Padmarao Begari <padmarao.begari@microchip.com>
+ */
+#include <common.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <log.h>
+#include <dm/device.h>
+#include <dm/devres.h>
+#include <dm/uclass.h>
+#include <linux/err.h>
+
+#include "mpfs_clk.h"
+
+/* All methods are delegated to CCF clocks */
+
+static ulong mpfs_clk_get_rate(struct clk *clk)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return clk_get_rate(c);
+}
+
+static ulong mpfs_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return clk_set_rate(c, rate);
+}
+
+static int mpfs_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct clk *c, *p;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+
+ err = clk_get_by_id(parent->id, &p);
+ if (err)
+ return err;
+
+ return clk_set_parent(c, p);
+}
+
+static int mpfs_clk_endisable(struct clk *clk, bool enable)
+{
+ struct clk *c;
+ int err = clk_get_by_id(clk->id, &c);
+
+ if (err)
+ return err;
+ return enable ? clk_enable(c) : clk_disable(c);
+}
+
+static int mpfs_clk_enable(struct clk *clk)
+{
+ return mpfs_clk_endisable(clk, true);
+}
+
+static int mpfs_clk_disable(struct clk *clk)
+{
+ return mpfs_clk_endisable(clk, false);
+}
+
+static int mpfs_clk_probe(struct udevice *dev)
+{
+ int ret;
+ void __iomem *base;
+ u32 clk_rate;
+ const char *parent_clk_name;
+ struct clk *clk = dev_get_priv(dev);
+
+ base = dev_read_addr_ptr(dev);
+ if (!base)
+ return -EINVAL;
+
+ ret = clk_get_by_index(dev, 0, clk);
+ if (ret)
+ return ret;
+
+ dev_read_u32(clk->dev, "clock-frequency", &clk_rate);
+ parent_clk_name = clk->dev->name;
+
+ ret = mpfs_clk_register_cfgs(base, clk_rate, parent_clk_name);
+ if (ret)
+ return ret;
+
+ ret = mpfs_clk_register_periphs(base, clk_rate, "clk_ahb");
+
+ return ret;
+}
+
+static const struct clk_ops mpfs_clk_ops = {
+ .set_rate = mpfs_clk_set_rate,
+ .get_rate = mpfs_clk_get_rate,
+ .set_parent = mpfs_clk_set_parent,
+ .enable = mpfs_clk_enable,
+ .disable = mpfs_clk_disable,
+};
+
+static const struct udevice_id mpfs_of_match[] = {
+ { .compatible = "microchip,mpfs-clkcfg" },
+ { }
+};
+
+U_BOOT_DRIVER(mpfs_clk) = {
+ .name = "mpfs_clk",
+ .id = UCLASS_CLK,
+ .of_match = mpfs_of_match,
+ .ops = &mpfs_clk_ops,
+ .probe = mpfs_clk_probe,
+ .priv_auto = sizeof(struct clk),
+};
diff --git a/drivers/clk/microchip/mpfs_clk.h b/drivers/clk/microchip/mpfs_clk.h
new file mode 100644
index 0000000000..8e3fc55ae3
--- /dev/null
+++ b/drivers/clk/microchip/mpfs_clk.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Microchip Technology Inc.
+ * Padmarao Begari <padmarao.begari@microchip.com>
+ */
+#ifndef __MICROCHIP_MPFS_CLK_H
+#define __MICROCHIP_MPFS_CLK_H
+
+#include <linux/clk-provider.h>
+/**
+ * mpfs_clk_register_cfgs() - register configuration clocks
+ *
+ * @base: base address of the mpfs system register.
+ * @clk_rate: the mpfs pll clock rate.
+ * @parent_name: a pointer to parent clock name.
+ * @return zero on success, or a negative error code.
+ */
+int mpfs_clk_register_cfgs(void __iomem *base, u32 clk_rate,
+ const char *parent_name);
+/**
+ * mpfs_clk_register_periphs() - register peripheral clocks
+ *
+ * @base: base address of the mpfs system register.
+ * @clk_rate: the mpfs pll clock rate.
+ * @parent_name: a pointer to parent clock name.
+ * @return zero on success, or a negative error code.
+ */
+int mpfs_clk_register_periphs(void __iomem *base, u32 clk_rate,
+ const char *parent_name);
+/**
+ * divider_get_val() - get the clock divider value
+ *
+ * @rate: requested clock rate.
+ * @parent_rate: parent clock rate.
+ * @table: a pointer to clock divider table.
+ * @width: width of the divider bit field.
+ * @flags: common clock framework flags.
+ * @return divider value on success, or a negative error code.
+ */
+int divider_get_val(unsigned long rate, unsigned long parent_rate,
+ const struct clk_div_table *table,
+ u8 width, unsigned long flags);
+
+#endif /* __MICROCHIP_MPFS_CLK_H */
diff --git a/drivers/clk/microchip/mpfs_clk_cfg.c b/drivers/clk/microchip/mpfs_clk_cfg.c
new file mode 100644
index 0000000000..fefddd1413
--- /dev/null
+++ b/drivers/clk/microchip/mpfs_clk_cfg.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Microchip Technology Inc.
+ * Padmarao Begari <padmarao.begari@microchip.com>
+ */
+#include <common.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <asm/io.h>
+#include <dm/device.h>
+#include <dm/devres.h>
+#include <dm/uclass.h>
+#include <dt-bindings/clock/microchip-mpfs-clock.h>
+#include <linux/err.h>
+
+#include "mpfs_clk.h"
+
+#define MPFS_CFG_CLOCK "mpfs_cfg_clock"
+
+#define REG_CLOCK_CONFIG_CR 0x08
+
+/* CPU and AXI clock divisors */
+static const struct clk_div_table mpfs_div_cpu_axi_table[] = {
+ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
+ { 0, 0 }
+};
+
+/* AHB clock divisors */
+static const struct clk_div_table mpfs_div_ahb_table[] = {
+ { 1, 2 }, { 2, 4}, { 3, 8 },
+ { 0, 0 }
+};
+
+/**
+ * struct mpfs_cfg_clock - per instance of configuration clock
+ * @id: index of a configuration clock
+ * @name: name of a configuration clock
+ * @shift: shift to the divider bit field of a configuration clock
+ * @width: width of the divider bit field of a configation clock
+ * @table: clock divider table instance
+ * @flags: common clock framework flags
+ */
+struct mpfs_cfg_clock {
+ unsigned int id;
+ const char *name;
+ u8 shift;
+ u8 width;
+ const struct clk_div_table *table;
+ unsigned long flags;
+};
+
+/**
+ * struct mpfs_cfg_hw_clock - hardware configuration clock (cpu, axi, ahb)
+ * @cfg: configuration clock instance
+ * @sys_base: base address of the mpfs system register
+ * @prate: the pll clock rate
+ * @hw: clock instance
+ */
+struct mpfs_cfg_hw_clock {
+ struct mpfs_cfg_clock cfg;
+ void __iomem *sys_base;
+ u32 prate;
+ struct clk hw;
+};
+
+#define to_mpfs_cfg_clk(_hw) container_of(_hw, struct mpfs_cfg_hw_clock, hw)
+
+static ulong mpfs_cfg_clk_recalc_rate(struct clk *hw)
+{
+ struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw);
+ struct mpfs_cfg_clock *cfg = &cfg_hw->cfg;
+ void __iomem *base_addr = cfg_hw->sys_base;
+ unsigned long rate;
+ u32 val;
+
+ val = readl(base_addr + REG_CLOCK_CONFIG_CR) >> cfg->shift;
+ val &= clk_div_mask(cfg->width);
+ rate = cfg_hw->prate / (1u << val);
+ hw->rate = rate;
+
+ return rate;
+}
+
+static ulong mpfs_cfg_clk_set_rate(struct clk *hw, ulong rate)
+{
+ struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw);
+ struct mpfs_cfg_clock *cfg = &cfg_hw->cfg;
+ void __iomem *base_addr = cfg_hw->sys_base;
+ u32 val;
+ int divider_setting;
+
+ divider_setting = divider_get_val(rate, cfg_hw->prate, cfg->table, cfg->width, cfg->flags);
+
+ if (divider_setting < 0)
+ return divider_setting;
+
+ val = readl(base_addr + REG_CLOCK_CONFIG_CR);
+ val &= ~(clk_div_mask(cfg->width) << cfg_hw->cfg.shift);
+ val |= divider_setting << cfg->shift;
+ writel(val, base_addr + REG_CLOCK_CONFIG_CR);
+
+ return clk_get_rate(hw);
+}
+
+#define CLK_CFG(_id, _name, _shift, _width, _table, _flags) { \
+ .cfg.id = _id, \
+ .cfg.name = _name, \
+ .cfg.shift = _shift, \
+ .cfg.width = _width, \
+ .cfg.table = _table, \
+ .cfg.flags = _flags, \
+ }
+
+static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = {
+ CLK_CFG(CLK_CPU, "clk_cpu", 0, 2, mpfs_div_cpu_axi_table, 0),
+ CLK_CFG(CLK_AXI, "clk_axi", 2, 2, mpfs_div_cpu_axi_table, 0),
+ CLK_CFG(CLK_AHB, "clk_ahb", 4, 2, mpfs_div_ahb_table, 0),
+};
+
+int mpfs_clk_register_cfgs(void __iomem *base, u32 clk_rate,
+ const char *parent_name)
+{
+ int ret;
+ int i, id, num_clks;
+ const char *name;
+ struct clk *hw;
+
+ num_clks = ARRAY_SIZE(mpfs_cfg_clks);
+ for (i = 0; i < num_clks; i++) {
+ hw = &mpfs_cfg_clks[i].hw;
+ mpfs_cfg_clks[i].sys_base = base;
+ mpfs_cfg_clks[i].prate = clk_rate;
+ name = mpfs_cfg_clks[i].cfg.name;
+ ret = clk_register(hw, MPFS_CFG_CLOCK, name, parent_name);
+ if (ret)
+ ERR_PTR(ret);
+ id = mpfs_cfg_clks[i].cfg.id;
+ clk_dm(id, hw);
+ }
+ return 0;
+}
+
+const struct clk_ops mpfs_cfg_clk_ops = {
+ .set_rate = mpfs_cfg_clk_set_rate,
+ .get_rate = mpfs_cfg_clk_recalc_rate,
+};
+
+U_BOOT_DRIVER(mpfs_cfg_clock) = {
+ .name = MPFS_CFG_CLOCK,
+ .id = UCLASS_CLK,
+ .ops = &mpfs_cfg_clk_ops,
+};
diff --git a/drivers/clk/microchip/mpfs_clk_periph.c b/drivers/clk/microchip/mpfs_clk_periph.c
new file mode 100644
index 0000000000..61d90eb4a8
--- /dev/null
+++ b/drivers/clk/microchip/mpfs_clk_periph.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Microchip Technology Inc.
+ * Padmarao Begari <padmarao.begari@microchip.com>
+ */
+#include <common.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <asm/io.h>
+#include <dm/device.h>
+#include <dm/devres.h>
+#include <dm/uclass.h>
+#include <dt-bindings/clock/microchip-mpfs-clock.h>
+#include <linux/err.h>
+
+#include "mpfs_clk.h"
+
+#define MPFS_PERIPH_CLOCK "mpfs_periph_clock"
+
+#define REG_CLOCK_CONFIG_CR 0x08
+#define REG_SUBBLK_CLOCK_CR 0x84
+#define REG_SUBBLK_RESET_CR 0x88
+
+#define CFG_CPU_SHIFT 0x0
+#define CFG_AXI_SHIFT 0x2
+#define CFG_AHB_SHIFT 0x4
+#define CFG_WIDTH 0x2
+
+/**
+ * struct mpfs_periph_clock - per instance of peripheral clock
+ * @id: index of a peripheral clock
+ * @name: name of a peripheral clock
+ * @shift: shift to a peripheral clock bit field
+ * @flags: common clock framework flags
+ */
+struct mpfs_periph_clock {
+ unsigned int id;
+ const char *name;
+ u8 shift;
+ unsigned long flags;
+};
+
+/**
+ * struct mpfs_periph_hw_clock - hardware peripheral clock
+ * @periph: peripheral clock instance
+ * @sys_base: base address of the mpfs system register
+ * @prate: the pll clock rate
+ * @hw: clock instance
+ */
+struct mpfs_periph_hw_clock {
+ struct mpfs_periph_clock periph;
+ void __iomem *sys_base;
+ u32 prate;
+ struct clk hw;
+};
+
+#define to_mpfs_periph_clk(_hw) container_of(_hw, struct mpfs_periph_hw_clock, hw)
+
+static int mpfs_periph_clk_enable(struct clk *hw)
+{
+ struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw);
+ struct mpfs_periph_clock *periph = &periph_hw->periph;
+ void __iomem *base_addr = periph_hw->sys_base;
+ u32 reg, val;
+
+ if (periph->flags != CLK_IS_CRITICAL) {
+ reg = readl(base_addr + REG_SUBBLK_RESET_CR);
+ val = reg & ~(1u << periph->shift);
+ writel(val, base_addr + REG_SUBBLK_RESET_CR);
+
+ reg = readl(base_addr + REG_SUBBLK_CLOCK_CR);
+ val = reg | (1u << periph->shift);
+ writel(val, base_addr + REG_SUBBLK_CLOCK_CR);
+ }
+
+ return 0;
+}
+
+static int mpfs_periph_clk_disable(struct clk *hw)
+{
+ struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw);
+ struct mpfs_periph_clock *periph = &periph_hw->periph;
+ void __iomem *base_addr = periph_hw->sys_base;
+ u32 reg, val;
+
+ if (periph->flags != CLK_IS_CRITICAL) {
+ reg = readl(base_addr + REG_SUBBLK_RESET_CR);
+ val = reg | (1u << periph->shift);
+ writel(val, base_addr + REG_SUBBLK_RESET_CR);
+
+ reg = readl(base_addr + REG_SUBBLK_CLOCK_CR);
+ val = reg & ~(1u << periph->shift);
+ writel(val, base_addr + REG_SUBBLK_CLOCK_CR);
+ }
+
+ return 0;
+}
+
+static ulong mpfs_periph_clk_recalc_rate(struct clk *hw)
+{
+ struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw);
+ void __iomem *base_addr = periph_hw->sys_base;
+ unsigned long rate;
+ u32 val;
+
+ val = readl(base_addr + REG_CLOCK_CONFIG_CR) >> CFG_AHB_SHIFT;
+ val &= clk_div_mask(CFG_WIDTH);
+ rate = periph_hw->prate / (1u << val);
+ hw->rate = rate;
+
+ return rate;
+}
+
+#define CLK_PERIPH(_id, _name, _shift, _flags) { \
+ .periph.id = _id, \
+ .periph.name = _name, \
+ .periph.shift = _shift, \
+ .periph.flags = _flags, \
+ }
+
+static struct mpfs_periph_hw_clock mpfs_periph_clks[] = {
+ CLK_PERIPH(CLK_ENVM, "clk_periph_envm", 0, CLK_IS_CRITICAL),
+ CLK_PERIPH(CLK_MAC0, "clk_periph_mac0", 1, 0),
+ CLK_PERIPH(CLK_MAC1, "clk_periph_mac1", 2, 0),
+ CLK_PERIPH(CLK_MMC, "clk_periph_mmc", 3, 0),
+ CLK_PERIPH(CLK_TIMER, "clk_periph_timer", 4, 0),
+ CLK_PERIPH(CLK_MMUART0, "clk_periph_mmuart0", 5, 0),
+ CLK_PERIPH(CLK_MMUART1, "clk_periph_mmuart1", 6, 0),
+ CLK_PERIPH(CLK_MMUART2, "clk_periph_mmuart2", 7, 0),
+ CLK_PERIPH(CLK_MMUART3, "clk_periph_mmuart3", 8, 0),
+ CLK_PERIPH(CLK_MMUART4, "clk_periph_mmuart4", 9, 0),
+ CLK_PERIPH(CLK_SPI0, "clk_periph_spi0", 10, 0),
+ CLK_PERIPH(CLK_SPI1, "clk_periph_spi1", 11, 0),
+ CLK_PERIPH(CLK_I2C0, "clk_periph_i2c0", 12, 0),
+ CLK_PERIPH(CLK_I2C1, "clk_periph_i2c1", 13, 0),
+ CLK_PERIPH(CLK_CAN0, "clk_periph_can0", 14, 0),
+ CLK_PERIPH(CLK_CAN1, "clk_periph_can1", 15, 0),
+ CLK_PERIPH(CLK_USB, "clk_periph_usb", 16, 0),
+ CLK_PERIPH(CLK_RTC, "clk_periph_rtc", 18, 0),
+ CLK_PERIPH(CLK_QSPI, "clk_periph_qspi", 19, 0),
+ CLK_PERIPH(CLK_GPIO0, "clk_periph_gpio0", 20, 0),
+ CLK_PERIPH(CLK_GPIO1, "clk_periph_gpio1", 21, 0),
+ CLK_PERIPH(CLK_GPIO2, "clk_periph_gpio2", 22, 0),
+ CLK_PERIPH(CLK_DDRC, "clk_periph_ddrc", 23, CLK_IS_CRITICAL),
+ CLK_PERIPH(CLK_FIC0, "clk_periph_fic0", 24, 0),
+ CLK_PERIPH(CLK_FIC1, "clk_periph_fic1", 25, 0),
+ CLK_PERIPH(CLK_FIC2, "clk_periph_fic2", 26, 0),
+ CLK_PERIPH(CLK_FIC3, "clk_periph_fic3", 27, 0),
+ CLK_PERIPH(CLK_ATHENA, "clk_periph_athena", 28, 0),
+ CLK_PERIPH(CLK_CFM, "clk_periph_cfm", 29, 0),
+};
+
+int mpfs_clk_register_periphs(void __iomem *base, u32 clk_rate,
+ const char *parent_name)
+{
+ int ret;
+ int i, id, num_clks;
+ const char *name;
+ struct clk *hw;
+
+ num_clks = ARRAY_SIZE(mpfs_periph_clks);
+ for (i = 0; i < num_clks; i++) {
+ hw = &mpfs_periph_clks[i].hw;
+ mpfs_periph_clks[i].sys_base = base;
+ mpfs_periph_clks[i].prate = clk_rate;
+ name = mpfs_periph_clks[i].periph.name;
+ ret = clk_register(hw, MPFS_PERIPH_CLOCK, name, parent_name);
+ if (ret)
+ ERR_PTR(ret);
+ id = mpfs_periph_clks[i].periph.id;
+ clk_dm(id, hw);
+ }
+
+ return 0;
+}
+
+const struct clk_ops mpfs_periph_clk_ops = {
+ .enable = mpfs_periph_clk_enable,
+ .disable = mpfs_periph_clk_disable,
+ .get_rate = mpfs_periph_clk_recalc_rate,
+};
+
+U_BOOT_DRIVER(mpfs_periph_clock) = {
+ .name = MPFS_PERIPH_CLOCK,
+ .id = UCLASS_CLK,
+ .ops = &mpfs_periph_clk_ops,
+};
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index cdb975d5b3..f38122d54b 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -757,6 +757,25 @@ int uclass_pre_remove_device(struct udevice *dev)
}
#endif
+int uclass_probe_all(enum uclass_id id)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_first_device(id, &dev);
+ if (ret || !dev)
+ return ret;
+
+ /* Scanning uclass to probe all devices */
+ while (dev) {
+ ret = uclass_next_device(&dev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
UCLASS_DRIVER(nop) = {
.id = UCLASS_NOP,
.name = "nop",
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 1a4dec34d9..0d1f94c6cb 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -9,8 +9,6 @@
*/
#ifndef __UBOOT__
-#include <log.h>
-#include <dm/devres.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index e287c29e69..2225b33ff6 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -83,7 +83,16 @@ struct macb_dma_desc {
u32 ctrl;
};
-#define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc))
+struct macb_dma_desc_64 {
+ u32 addrh;
+ u32 unused;
+};
+
+#define HW_DMA_CAP_32B 0
+#define HW_DMA_CAP_64B 1
+
+#define DMA_DESC_SIZE 16
+#define DMA_DESC_BYTES(n) ((n) * DMA_DESC_SIZE)
#define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE))
#define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE))
#define MACB_TX_DUMMY_DMA_DESC_SIZE (DMA_DESC_BYTES(1))
@@ -137,6 +146,7 @@ struct macb_device {
struct macb_config {
unsigned int dma_burst_length;
+ unsigned int hw_dma_cap;
int (*clk_init)(struct udevice *dev, ulong rate);
};
@@ -307,6 +317,24 @@ static inline void macb_invalidate_rx_buffer(struct macb_device *macb)
#if defined(CONFIG_CMD_NET)
+static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc *desc)
+{
+ return (struct macb_dma_desc_64 *)((void *)desc
+ + sizeof(struct macb_dma_desc));
+}
+
+static void macb_set_addr(struct macb_device *macb, struct macb_dma_desc *desc,
+ ulong addr)
+{
+ struct macb_dma_desc_64 *desc_64;
+
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+ desc_64 = macb_64b_desc(desc);
+ desc_64->addrh = upper_32_bits(addr);
+ }
+ desc->addr = lower_32_bits(addr);
+}
+
static int _macb_send(struct macb_device *macb, const char *name, void *packet,
int length)
{
@@ -325,8 +353,12 @@ static int _macb_send(struct macb_device *macb, const char *name, void *packet,
macb->tx_head++;
}
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+ tx_head = tx_head * 2;
+
macb->tx_ring[tx_head].ctrl = ctrl;
- macb->tx_ring[tx_head].addr = paddr;
+ macb_set_addr(macb, &macb->tx_ring[tx_head], paddr);
+
barrier();
macb_flush_ring_desc(macb, TX);
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
@@ -363,19 +395,28 @@ static void reclaim_rx_buffers(struct macb_device *macb,
unsigned int new_tail)
{
unsigned int i;
+ unsigned int count;
i = macb->rx_tail;
macb_invalidate_ring_desc(macb, RX);
while (i > new_tail) {
- macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED);
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+ count = i * 2;
+ else
+ count = i;
+ macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED);
i++;
if (i > MACB_RX_RING_SIZE)
i = 0;
}
while (i < new_tail) {
- macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED);
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+ count = i * 2;
+ else
+ count = i;
+ macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED);
i++;
}
@@ -390,16 +431,25 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp)
void *buffer;
int length;
u32 status;
+ u8 flag = false;
macb->wrapped = false;
for (;;) {
macb_invalidate_ring_desc(macb, RX);
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+ next_rx_tail = next_rx_tail * 2;
+
if (!(macb->rx_ring[next_rx_tail].addr & MACB_BIT(RX_USED)))
return -EAGAIN;
status = macb->rx_ring[next_rx_tail].ctrl;
if (status & MACB_BIT(RX_SOF)) {
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+ next_rx_tail = next_rx_tail / 2;
+ flag = true;
+ }
+
if (next_rx_tail != macb->rx_tail)
reclaim_rx_buffers(macb, next_rx_tail);
macb->wrapped = false;
@@ -426,11 +476,22 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp)
*packetp = buffer;
}
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+ if (!flag)
+ next_rx_tail = next_rx_tail / 2;
+ }
+
if (++next_rx_tail >= MACB_RX_RING_SIZE)
next_rx_tail = 0;
macb->next_rx_tail = next_rx_tail;
return length;
} else {
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+ if (!flag)
+ next_rx_tail = next_rx_tail / 2;
+ flag = false;
+ }
+
if (++next_rx_tail >= MACB_RX_RING_SIZE) {
macb->wrapped = true;
next_rx_tail = 0;
@@ -470,6 +531,12 @@ static int macb_phy_find(struct macb_device *macb, const char *name)
int i;
u16 phy_id;
+ phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
+ if (phy_id != 0xffff) {
+ printf("%s: PHY present at %d\n", name, macb->phy_addr);
+ return 0;
+ }
+
/* Search for PHY... */
for (i = 0; i < 32; i++) {
macb->phy_addr = i;
@@ -718,6 +785,7 @@ static int gmac_init_multi_queues(struct macb_device *macb)
{
int i, num_queues = 1;
u32 queue_mask;
+ unsigned long paddr;
/* bit 0 is never set but queue 0 always exists */
queue_mask = gem_readl(macb, DCFG6) & 0xff;
@@ -731,10 +799,18 @@ static int gmac_init_multi_queues(struct macb_device *macb)
macb->dummy_desc->addr = 0;
flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma +
ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN));
-
- for (i = 1; i < num_queues; i++)
- gem_writel_queue_TBQP(macb, macb->dummy_desc_dma, i - 1);
-
+ paddr = macb->dummy_desc_dma;
+
+ for (i = 1; i < num_queues; i++) {
+ gem_writel_queue_TBQP(macb, lower_32_bits(paddr), i - 1);
+ gem_writel_queue_RBQP(macb, lower_32_bits(paddr), i - 1);
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+ gem_writel_queue_TBQPH(macb, upper_32_bits(paddr),
+ i - 1);
+ gem_writel_queue_RBQPH(macb, upper_32_bits(paddr),
+ i - 1);
+ }
+ }
return 0;
}
@@ -760,6 +836,9 @@ static void gmac_configure_dma(struct macb_device *macb)
dmacfg &= ~GEM_BIT(ENDIA_DESC);
dmacfg &= ~GEM_BIT(ADDR64);
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+ dmacfg |= GEM_BIT(ADDR64);
+
gem_writel(macb, DMACFG, dmacfg);
}
@@ -775,6 +854,7 @@ static int _macb_init(struct macb_device *macb, const char *name)
unsigned long paddr;
int ret;
int i;
+ int count;
/*
* macb_halt should have been called at some point before now,
@@ -786,20 +866,28 @@ static int _macb_init(struct macb_device *macb, const char *name)
for (i = 0; i < MACB_RX_RING_SIZE; i++) {
if (i == (MACB_RX_RING_SIZE - 1))
paddr |= MACB_BIT(RX_WRAP);
- macb->rx_ring[i].addr = paddr;
- macb->rx_ring[i].ctrl = 0;
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+ count = i * 2;
+ else
+ count = i;
+ macb->rx_ring[count].ctrl = 0;
+ macb_set_addr(macb, &macb->rx_ring[count], paddr);
paddr += macb->rx_buffer_size;
}
macb_flush_ring_desc(macb, RX);
macb_flush_rx_buffer(macb);
for (i = 0; i < MACB_TX_RING_SIZE; i++) {
- macb->tx_ring[i].addr = 0;
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+ count = i * 2;
+ else
+ count = i;
+ macb_set_addr(macb, &macb->tx_ring[count], 0);
if (i == (MACB_TX_RING_SIZE - 1))
- macb->tx_ring[i].ctrl = MACB_BIT(TX_USED) |
+ macb->tx_ring[count].ctrl = MACB_BIT(TX_USED) |
MACB_BIT(TX_WRAP);
else
- macb->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+ macb->tx_ring[count].ctrl = MACB_BIT(TX_USED);
}
macb_flush_ring_desc(macb, TX);
@@ -812,8 +900,12 @@ static int _macb_init(struct macb_device *macb, const char *name)
gem_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT);
#endif
- macb_writel(macb, RBQP, macb->rx_ring_dma);
- macb_writel(macb, TBQP, macb->tx_ring_dma);
+ macb_writel(macb, RBQP, lower_32_bits(macb->rx_ring_dma));
+ macb_writel(macb, TBQP, lower_32_bits(macb->tx_ring_dma));
+ if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+ macb_writel(macb, RBQPH, upper_32_bits(macb->rx_ring_dma));
+ macb_writel(macb, TBQPH, upper_32_bits(macb->tx_ring_dma));
+ }
if (macb_is_gem(macb)) {
/* Initialize DMA properties */
@@ -1217,6 +1309,7 @@ static int macb_enable_clk(struct udevice *dev)
static const struct macb_config default_gem_config = {
.dma_burst_length = 16,
+ .hw_dma_cap = HW_DMA_CAP_32B,
.clk_init = NULL,
};
@@ -1224,11 +1317,12 @@ static int macb_eth_probe(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
struct macb_device *macb = dev_get_priv(dev);
+ struct ofnode_phandle_args phandle_args;
const char *phy_mode;
int ret;
- phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
- NULL);
+ phy_mode = dev_read_prop(dev, "phy-mode", NULL);
+
if (phy_mode)
macb->phy_interface = phy_get_interface_by_name(phy_mode);
if (macb->phy_interface == -1) {
@@ -1236,6 +1330,12 @@ static int macb_eth_probe(struct udevice *dev)
return -EINVAL;
}
+ /* Read phyaddr from DT */
+ if (!dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+ &phandle_args))
+ macb->phy_addr = ofnode_read_u32_default(phandle_args.node,
+ "reg", -1);
+
macb->regs = (void *)pdata->iobase;
macb->is_big_endian = (cpu_to_be32(0x12345678) == 0x12345678);
@@ -1304,13 +1404,21 @@ static int macb_eth_of_to_plat(struct udevice *dev)
return macb_late_eth_of_to_plat(dev);
}
+static const struct macb_config microchip_config = {
+ .dma_burst_length = 16,
+ .hw_dma_cap = HW_DMA_CAP_64B,
+ .clk_init = NULL,
+};
+
static const struct macb_config sama5d4_config = {
.dma_burst_length = 4,
+ .hw_dma_cap = HW_DMA_CAP_32B,
.clk_init = NULL,
};
static const struct macb_config sifive_config = {
.dma_burst_length = 16,
+ .hw_dma_cap = HW_DMA_CAP_32B,
.clk_init = macb_sifive_clk_init,
};
@@ -1324,6 +1432,8 @@ static const struct udevice_id macb_eth_ids[] = {
{ .compatible = "cdns,zynq-gem" },
{ .compatible = "sifive,fu540-c000-gem",
.data = (ulong)&sifive_config },
+ { .compatible = "microchip,mpfs-mss-gem",
+ .data = (ulong)&microchip_config },
{ }
};
diff --git a/drivers/net/macb.h b/drivers/net/macb.h
index 9b16383eba..72b84ae96e 100644
--- a/drivers/net/macb.h
+++ b/drivers/net/macb.h
@@ -768,5 +768,11 @@
#define GEM_RX_CSUM_CHECKED_MASK 2
#define gem_writel_queue_TBQP(port, value, queue_num) \
writel((value), (port)->regs + GEM_TBQP(queue_num))
+#define gem_writel_queue_TBQPH(port, value, queue_num) \
+ writel((value), (port)->regs + GEM_TBQPH(queue_num))
+#define gem_writel_queue_RBQP(port, value, queue_num) \
+ writel((value), (port)->regs + GEM_RBQP(queue_num))
+#define gem_writel_queue_RBQPH(port, value, queue_num) \
+ writel((value), (port)->regs + GEM_RBQPH(queue_num))
#endif /* __DRIVERS_MACB_H__ */
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index d431102462..fbbea18c7d 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -18,7 +18,7 @@ config DM_REGULATOR
config SPL_DM_REGULATOR
bool "Enable regulators for SPL"
- depends on DM_REGULATOR
+ depends on DM_REGULATOR && SPL_POWER_SUPPORT
---help---
Regulators are seldom needed in SPL. Even if they are accessed, some
code space can be saved by accessing the PMIC registers directly.
diff --git a/drivers/ram/k3-j721e/lpddr4.c b/drivers/ram/k3-j721e/lpddr4.c
index fc80fb1e2c..68043d7cb6 100644
--- a/drivers/ram/k3-j721e/lpddr4.c
+++ b/drivers/ram/k3-j721e/lpddr4.c
@@ -719,7 +719,7 @@ uint32_t lpddr4_checkctlinterrupt(const lpddr4_privatedata * pd,
/* MISRA compliance (Shifting operation) check */
if (fieldshift < WORD_SHIFT) {
- if (((ctlirqstatus >> fieldshift) & BIT_MASK) > 0U) {
+ if ((ctlirqstatus >> fieldshift) & LPDDR4_BIT_MASK) {
*irqstatus = true;
} else {
*irqstatus = false;
@@ -746,11 +746,11 @@ uint32_t lpddr4_ackctlinterrupt(const lpddr4_privatedata * pd,
if (localinterrupt > WORD_SHIFT) {
localinterrupt =
(localinterrupt - (uint32_t) WORD_SHIFT);
- regval = ((uint32_t) BIT_MASK << localinterrupt);
+ regval = (uint32_t)LPDDR4_BIT_MASK << localinterrupt;
CPS_REG_WRITE(&(ctlregbase->LPDDR4__INT_ACK_1__REG),
regval);
} else {
- regval = ((uint32_t) BIT_MASK << localinterrupt);
+ regval = (uint32_t)LPDDR4_BIT_MASK << localinterrupt;
CPS_REG_WRITE(&(ctlregbase->LPDDR4__INT_ACK_0__REG),
regval);
}
@@ -823,7 +823,7 @@ uint32_t lpddr4_checkphyindepinterrupt(const lpddr4_privatedata * pd,
phyindepirqstatus =
CPS_REG_READ(&(ctlregbase->LPDDR4__PI_INT_STATUS__REG));
*irqstatus =
- (((phyindepirqstatus >> (uint32_t) intr) & BIT_MASK) > 0U);
+ !!((phyindepirqstatus >> (uint32_t)intr) & LPDDR4_BIT_MASK);
}
return result;
}
@@ -841,7 +841,7 @@ uint32_t lpddr4_ackphyindepinterrupt(const lpddr4_privatedata * pd,
lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase;
/* Write 1 to the requested bit to ACk the interrupt */
- regval = ((uint32_t) BIT_MASK << ui32shiftinterrupt);
+ regval = (uint32_t)LPDDR4_BIT_MASK << ui32shiftinterrupt;
CPS_REG_WRITE(&(ctlregbase->LPDDR4__PI_INT_ACK__REG), regval);
}
@@ -894,7 +894,7 @@ static void lpddr4_checkwrlvlerror(lpddr4_ctlregs * ctlregbase,
(volatile uint32_t
*)(&(ctlregbase->LPDDR4__PHY_WRLVL_ERROR_OBS_0__REG));
/* PHY_WRLVL_ERROR_OBS_X[1:0] should be zero */
- errbitmask = (BIT_MASK << 1) | (BIT_MASK);
+ errbitmask = (LPDDR4_BIT_MASK << 1) | LPDDR4_BIT_MASK;
for (snum = 0U; snum < DSLICE_NUM; snum++) {
regval = CPS_REG_READ(regaddress);
if ((regval & errbitmask) != 0U) {
@@ -1054,7 +1054,7 @@ static void lpddr4_seterrors(lpddr4_ctlregs * ctlregbase,
lpddr4_debuginfo * debuginfo, bool * errfoundptr)
{
- uint32_t errbitmask = (BIT_MASK << 0x1U) | (BIT_MASK);
+ uint32_t errbitmask = (LPDDR4_BIT_MASK << 0x1U) | LPDDR4_BIT_MASK;
/* Check PLL observation registers for PLL lock errors */
debuginfo->pllerror =
diff --git a/drivers/ram/k3-j721e/lpddr4_private.h b/drivers/ram/k3-j721e/lpddr4_private.h
index 42c923464a..3d5017ea47 100644
--- a/drivers/ram/k3-j721e/lpddr4_private.h
+++ b/drivers/ram/k3-j721e/lpddr4_private.h
@@ -14,9 +14,9 @@
#define VERSION_0 (0x54d5da40U)
#define VERSION_1 (0xc1865a1U)
-#define BIT_MASK (0x1U)
-#define BYTE_MASK (0xffU)
-#define NIBBLE_MASK (0xfU)
+#define LPDDR4_BIT_MASK (0x1U)
+#define BYTE_MASK (0xffU)
+#define NIBBLE_MASK (0xfU)
#define WORD_SHIFT (32U)
#define WORD_MASK (0xffffffffU)
@@ -46,11 +46,15 @@
#define IO_CALIB_DONE ((uint32_t)0x1U << 23U)
#define IO_CALIB_FIELD ((uint32_t)NIBBLE_MASK << 28U)
#define IO_CALIB_STATE ((uint32_t)0xBU << 28U)
-#define RX_CAL_DONE ((uint32_t)BIT_MASK << 4U)
-#define CA_TRAIN_RL (((uint32_t)BIT_MASK << 5U) | ((uint32_t)BIT_MASK << 4U))
+#define RX_CAL_DONE ((uint32_t)LPDDR4_BIT_MASK << 4U)
+#define CA_TRAIN_RL (((uint32_t)LPDDR4_BIT_MASK << 5U) | \
+ ((uint32_t)LPDDR4_BIT_MASK << 4U))
#define WR_LVL_STATE (((uint32_t)NIBBLE_MASK) << 13U)
-#define GATE_LVL_ERROR_FIELDS (((uint32_t)BIT_MASK << 7U) | ((uint32_t)BIT_MASK << 6U))
-#define READ_LVL_ERROR_FIELDS ((((uint32_t)NIBBLE_MASK) << 28U) | (((uint32_t)BYTE_MASK) << 16U))
-#define DQ_LVL_STATUS (((uint32_t)BIT_MASK << 26U) | (((uint32_t)BYTE_MASK) << 18U))
+#define GATE_LVL_ERROR_FIELDS (((uint32_t)LPDDR4_BIT_MASK << 7U) | \
+ ((uint32_t)LPDDR4_BIT_MASK << 6U))
+#define READ_LVL_ERROR_FIELDS ((((uint32_t)NIBBLE_MASK) << 28U) | \
+ (((uint32_t)BYTE_MASK) << 16U))
+#define DQ_LVL_STATUS (((uint32_t)LPDDR4_BIT_MASK << 26U) | \
+ (((uint32_t)BYTE_MASK) << 18U))
#endif /* LPDDR4_PRIV_H */
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b4805a2e4e..129494322c 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -134,6 +134,22 @@ config SERIAL_SEARCH_ALL
If unsure, say N.
+config SERIAL_PROBE_ALL
+ bool "Probe all available serial devices"
+ depends on DM_SERIAL
+ default n
+ help
+ The serial subsystem only probes for a single serial device,
+ but does not probe for other remaining serial devices.
+ With this option set, we make probing and searching for
+ all available devices optional.
+ Normally, U-Boot talks to one serial port at a time, but SBSA
+ compliant UART devices like PL011 require initialization
+ by firmware and to let the kernel use serial port for sending
+ and receiving the characters.
+
+ If unsure, say N.
+
config SPL_DM_SERIAL
bool "Enable Driver Model for serial drivers in SPL"
depends on DM_SERIAL && SPL_DM
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 58a6541d8c..ead0193ad4 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -172,6 +172,15 @@ int serial_init(void)
/* Called after relocation */
int serial_initialize(void)
{
+ /* Scanning uclass to probe devices */
+ if (IS_ENABLED(CONFIG_SERIAL_PROBE_ALL)) {
+ int ret;
+
+ ret = uclass_probe_all(UCLASS_SERIAL);
+ if (ret)
+ return ret;
+ }
+
return serial_init();
}
diff --git a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
index db2cf86f63..a3797b22c7 100644
--- a/drivers/timer/andes_plmt_timer.c
+++ b/drivers/timer/andes_plmt_timer.c
@@ -18,11 +18,30 @@
/* mtime register */
#define MTIME_REG(base) ((ulong)(base))
-static u64 andes_plmt_get_count(struct udevice *dev)
+static u64 notrace andes_plmt_get_count(struct udevice *dev)
{
return readq((void __iomem *)MTIME_REG(dev_get_priv(dev)));
}
+#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY)
+/**
+ * timer_early_get_rate() - Get the timer rate before driver model
+ */
+unsigned long notrace timer_early_get_rate(void)
+{
+ return RISCV_MMODE_TIMER_FREQ;
+}
+
+/**
+ * timer_early_get_count() - Get the timer count before driver model
+ *
+ */
+u64 notrace timer_early_get_count(void)
+{
+ return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE));
+}
+#endif
+
static const struct timer_ops andes_plmt_ops = {
.get_count = andes_plmt_get_count,
};
diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
index 21ae184057..3627ed79b8 100644
--- a/drivers/timer/riscv_timer.c
+++ b/drivers/timer/riscv_timer.c
@@ -16,7 +16,7 @@
#include <timer.h>
#include <asm/csr.h>
-static u64 riscv_timer_get_count(struct udevice *dev)
+static u64 notrace riscv_timer_get_count(struct udevice *dev)
{
__maybe_unused u32 hi, lo;
@@ -31,6 +31,25 @@ static u64 riscv_timer_get_count(struct udevice *dev)
return ((u64)hi << 32) | lo;
}
+#if CONFIG_IS_ENABLED(RISCV_SMODE) && IS_ENABLED(CONFIG_TIMER_EARLY)
+/**
+ * timer_early_get_rate() - Get the timer rate before driver model
+ */
+unsigned long notrace timer_early_get_rate(void)
+{
+ return RISCV_SMODE_TIMER_FREQ;
+}
+
+/**
+ * timer_early_get_count() - Get the timer count before driver model
+ *
+ */
+u64 notrace timer_early_get_count(void)
+{
+ return riscv_timer_get_count(NULL);
+}
+#endif
+
static int riscv_timer_probe(struct udevice *dev)
{
struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
diff --git a/drivers/timer/sifive_clint_timer.c b/drivers/timer/sifive_clint_timer.c
index de23b85404..de7b4b95c9 100644
--- a/drivers/timer/sifive_clint_timer.c
+++ b/drivers/timer/sifive_clint_timer.c
@@ -15,11 +15,30 @@
/* mtime register */
#define MTIME_REG(base) ((ulong)(base) + 0xbff8)
-static u64 sifive_clint_get_count(struct udevice *dev)
+static u64 notrace sifive_clint_get_count(struct udevice *dev)
{
return readq((void __iomem *)MTIME_REG(dev_get_priv(dev)));
}
+#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY)
+/**
+ * timer_early_get_rate() - Get the timer rate before driver model
+ */
+unsigned long notrace timer_early_get_rate(void)
+{
+ return RISCV_MMODE_TIMER_FREQ;
+}
+
+/**
+ * timer_early_get_count() - Get the timer count before driver model
+ *
+ */
+u64 notrace timer_early_get_count(void)
+{
+ return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE));
+}
+#endif
+
static const struct timer_ops sifive_clint_ops = {
.get_count = sifive_clint_get_count,
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d39d9b2291..d782eb806a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -199,7 +199,7 @@ config PANEL
config SIMPLE_PANEL
bool "Enable simple panel support"
- depends on PANEL
+ depends on PANEL && BACKLIGHT
default y
help
This turns on a simple panel driver that enables a compatible