summaryrefslogtreecommitdiff
path: root/drivers/clk/sifive/fu540-prci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/sifive/fu540-prci.c')
-rw-r--r--drivers/clk/sifive/fu540-prci.c73
1 files changed, 58 insertions, 15 deletions
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
index 00c31fc04e..c5148e9a37 100644
--- a/drivers/clk/sifive/fu540-prci.c
+++ b/drivers/clk/sifive/fu540-prci.c
@@ -30,11 +30,15 @@
#include <common.h>
#include <asm/io.h>
+#include <asm/arch/reset.h>
#include <clk-uclass.h>
#include <clk.h>
#include <div64.h>
#include <dm.h>
#include <errno.h>
+#include <reset-uclass.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -132,6 +136,7 @@
/* DEVICESRESETREG */
#define PRCI_DEVICESRESETREG_OFFSET 0x28
+#define PRCI_DEVICERESETCNT 5
#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK \
(0x1 << PRCI_RST_DDR_CTRL_N)
@@ -525,6 +530,41 @@ static const struct __prci_clock_ops sifive_fu540_prci_tlclksel_clk_ops = {
.recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
};
+static int __prci_consumer_reset(const char *rst_name, bool trigger)
+{
+ struct udevice *dev;
+ struct reset_ctl rst_sig;
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_RESET,
+ DM_GET_DRIVER(sifive_reset),
+ &dev);
+ if (ret) {
+ dev_err(dev, "Reset driver not found: %d\n", ret);
+ return ret;
+ }
+
+ ret = reset_get_by_name(dev, rst_name, &rst_sig);
+ if (ret) {
+ dev_err(dev, "failed to get %s reset\n", rst_name);
+ return ret;
+ }
+
+ if (reset_valid(&rst_sig)) {
+ if (trigger)
+ ret = reset_deassert(&rst_sig);
+ else
+ ret = reset_assert(&rst_sig);
+ if (ret) {
+ dev_err(dev, "failed to trigger reset id = %ld\n",
+ rst_sig.id);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
/**
* __prci_ddr_release_reset() - Release DDR reset
* @pd: struct __prci_data * for the PRCI containing the DDRCLK mux reg
@@ -532,19 +572,20 @@ static const struct __prci_clock_ops sifive_fu540_prci_tlclksel_clk_ops = {
*/
static void __prci_ddr_release_reset(struct __prci_data *pd)
{
- u32 v;
-
- v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
- v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
- __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
+ /* Release DDR ctrl reset */
+ __prci_consumer_reset("ddr_ctrl", true);
/* HACK to get the '1 full controller clock cycle'. */
asm volatile ("fence");
- v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
- v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
- PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
- PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
- __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
+
+ /* Release DDR AXI reset */
+ __prci_consumer_reset("ddr_axi", true);
+
+ /* Release DDR AHB reset */
+ __prci_consumer_reset("ddr_ahb", true);
+
+ /* Release DDR PHY reset */
+ __prci_consumer_reset("ddr_phy", true);
/* HACK to get the '1 full controller clock cycle'. */
asm volatile ("fence");
@@ -564,12 +605,8 @@ static void __prci_ddr_release_reset(struct __prci_data *pd)
*/
static void __prci_ethernet_release_reset(struct __prci_data *pd)
{
- u32 v;
-
/* Release GEMGXL reset */
- v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
- v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
- __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
+ __prci_consumer_reset("gemgxl_reset", true);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK, PRCI_PROCMONCFG_OFFSET,
@@ -754,6 +791,11 @@ static struct clk_ops sifive_fu540_prci_ops = {
.disable = sifive_fu540_prci_disable,
};
+static int sifive_fu540_clk_bind(struct udevice *dev)
+{
+ return sifive_reset_bind(dev, PRCI_DEVICERESETCNT);
+}
+
static const struct udevice_id sifive_fu540_prci_ids[] = {
{ .compatible = "sifive,fu540-c000-prci" },
{ }
@@ -766,4 +808,5 @@ U_BOOT_DRIVER(sifive_fu540_prci) = {
.probe = sifive_fu540_prci_probe,
.ops = &sifive_fu540_prci_ops,
.priv_auto_alloc_size = sizeof(struct __prci_data),
+ .bind = sifive_fu540_clk_bind,
};