The StarFive SoC has a single reset controller, which seems to control
reset of all clocks and peripherals. It differs from the ones supported
by the Linux reset-simple driver in that it has a dedicated status
registers that needs to be polled to verify the reset has completed.

Also special is that most resets (> 70) are synchronous. As the reset
status poll would just time out without the clock, have the reset
controller enable the clock as part of the reset. OS can decide later,
which clocks to disable again.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 arch/riscv/Kconfig.socs                       |   1 +
 drivers/reset/Kconfig                         |   6 +
 drivers/reset/Makefile                        |   1 +
 drivers/reset/reset-starfive-vic.c            | 234 ++++++++++++++++++
 .../reset-controller/starfive-jh7100.h        | 126 ++++++++++
 include/soc/starfive/rstgen.h                 |  41 +++
 6 files changed, 409 insertions(+)
 create mode 100644 drivers/reset/reset-starfive-vic.c
 create mode 100644 include/dt-bindings/reset-controller/starfive-jh7100.h
 create mode 100644 include/soc/starfive/rstgen.h

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index c112fcc82e1a..e5603b001c74 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -49,6 +49,7 @@ endif
 
 config SOC_STARFIVE
        bool "StarFive SoCs"
+       select ARCH_HAS_RESET_CONTROLLER
        help
          This enables support for SiFive SoC platform hardware.
 
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 316ece9e7176..9429f107bb67 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -27,4 +27,10 @@ config RESET_STM32
        help
          This enables the reset controller driver for STM32MP and STM32 MCUs.
 
+config RESET_STARFIVE
+       bool "StarFive Controller Driver" if COMPILE_TEST
+       default SOC_STARFIVE
+       help
+         This enables the reset controller driver for the StarFive JH7100.
+
 endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 8460c4b154f5..ce494baae58e 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o
 obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
 obj-$(CONFIG_RESET_STM32) += reset-stm32.o
+obj-$(CONFIG_RESET_STARFIVE) += reset-starfive-vic.o
diff --git a/drivers/reset/reset-starfive-vic.c 
b/drivers/reset/reset-starfive-vic.c
new file mode 100644
index 000000000000..bcf615da0a13
--- /dev/null
+++ b/drivers/reset/reset-starfive-vic.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Ahmad Fatoum, Pengutronix
+ *
+ * StarFive Reset Controller driver
+ */
+#define pr_fmt(fmt) "reset-starfive: " fmt
+
+#include <common.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/reset-controller.h>
+#include <soc/starfive/rstgen.h>
+#include <dt-bindings/reset-controller/starfive-jh7100.h>
+#include <dt-bindings/clock/starfive-jh7100.h>
+
+struct starfive_rstgen {
+       void __iomem *base;
+       struct reset_controller_dev rcdev;
+       const struct starfive_rstgen_ops *ops;
+       struct device_node *clknp;
+       const int *sync_resets;
+};
+
+static struct starfive_rstgen *to_starfive_rstgen(struct reset_controller_dev 
*rcdev)
+{
+       return container_of(rcdev, struct starfive_rstgen, rcdev);
+}
+
+static const int jh7110_rstgen_sync_resets[RSTN_END] = {
+       [RSTN_SGDMA2P_AHB]   = CLK_SGDMA2P_AHB,
+       [RSTN_SGDMA2P_AXI]   = CLK_SGDMA2P_AXI,
+       [RSTN_DMA2PNOC_AXI]  = CLK_DMA2PNOC_AXI,
+       [RSTN_DLA_AXI]       = CLK_DLA_AXI,
+       [RSTN_DLANOC_AXI]    = CLK_DLANOC_AXI,
+       [RSTN_DLA_APB]       = CLK_DLA_APB,
+       [RSTN_VDECBRG_MAIN]  = CLK_VDECBRG_MAIN,
+       [RSTN_VDEC_AXI]      = CLK_VDEC_AXI,
+       [RSTN_VDEC_BCLK]     = CLK_VDEC_BCLK,
+       [RSTN_VDEC_CCLK]     = CLK_VDEC_CCLK,
+       [RSTN_VDEC_APB]      = CLK_VDEC_APB,
+       [RSTN_JPEG_AXI]      = CLK_JPEG_AXI,
+       [RSTN_JPEG_CCLK]     = CLK_JPEG_CCLK,
+       [RSTN_JPEG_APB]      = CLK_JPEG_APB,
+       [RSTN_JPCGC300_MAIN] = CLK_JPCGC300_MAIN,
+       [RSTN_GC300_2X]      = CLK_GC300_2X,
+       [RSTN_GC300_AXI]     = CLK_GC300_AXI,
+       [RSTN_GC300_AHB]     = CLK_GC300_AHB,
+       [RSTN_VENC_AXI]      = CLK_VENC_AXI,
+       [RSTN_VENCBRG_MAIN]  = CLK_VENCBRG_MAIN,
+       [RSTN_VENC_BCLK]     = CLK_VENC_BCLK,
+       [RSTN_VENC_CCLK]     = CLK_VENC_CCLK,
+       [RSTN_VENC_APB]      = CLK_VENC_APB,
+       [RSTN_DDRPHY_APB]    = CLK_DDRPHY_APB,
+       [RSTN_USB_AXI]       = CLK_USB_AXI,
+       [RSTN_SGDMA1P_AXI]   = CLK_SGDMA1P_AXI,
+       [RSTN_DMA1P_AXI]     = CLK_DMA1P_AXI,
+       [RSTN_NNE_AHB]       = CLK_NNE_AHB,
+       [RSTN_NNE_AXI]       = CLK_NNE_AXI,
+       [RSTN_NNENOC_AXI]    = CLK_NNENOC_AXI,
+       [RSTN_DLASLV_AXI]    = CLK_DLASLV_AXI,
+       [RSTN_VOUT_SRC]      = CLK_VOUT_SRC,
+       [RSTN_DISP_AXI]      = CLK_DISP_AXI,
+       [RSTN_DISPNOC_AXI]   = CLK_DISPNOC_AXI,
+       [RSTN_SDIO0_AHB]     = CLK_SDIO0_AHB,
+       [RSTN_SDIO1_AHB]     = CLK_SDIO1_AHB,
+       [RSTN_GMAC_AHB]      = CLK_GMAC_AHB,
+       [RSTN_SPI2AHB_AHB]   = CLK_SPI2AHB_AHB,
+       [RSTN_SPI2AHB_CORE]  = CLK_SPI2AHB_CORE,
+       [RSTN_EZMASTER_AHB]  = CLK_EZMASTER_AHB,
+       [RSTN_SEC_AHB]       = CLK_SEC_AHB,
+       [RSTN_AES]           = CLK_AES,
+       [RSTN_PKA]           = CLK_PKA,
+       [RSTN_SHA]           = CLK_SHA,
+       [RSTN_TRNG_APB]      = CLK_TRNG_APB,
+       [RSTN_OTP_APB]       = CLK_OTP_APB,
+       [RSTN_UART0_APB]     = CLK_UART0_APB,
+       [RSTN_UART0_CORE]    = CLK_UART0_CORE,
+       [RSTN_UART1_APB]     = CLK_UART1_APB,
+       [RSTN_UART1_CORE]    = CLK_UART1_CORE,
+       [RSTN_SPI0_APB]      = CLK_SPI0_APB,
+       [RSTN_SPI0_CORE]     = CLK_SPI0_CORE,
+       [RSTN_SPI1_APB]      = CLK_SPI1_APB,
+       [RSTN_SPI1_CORE]     = CLK_SPI1_CORE,
+       [RSTN_I2C0_APB]      = CLK_I2C0_APB,
+       [RSTN_I2C0_CORE]     = CLK_I2C0_CORE,
+       [RSTN_I2C1_APB]      = CLK_I2C1_APB,
+       [RSTN_I2C1_CORE]     = CLK_I2C1_CORE,
+       [RSTN_GPIO_APB]      = CLK_GPIO_APB,
+       [RSTN_UART2_APB]     = CLK_UART2_APB,
+       [RSTN_UART2_CORE]    = CLK_UART2_CORE,
+       [RSTN_UART3_APB]     = CLK_UART3_APB,
+       [RSTN_UART3_CORE]    = CLK_UART3_CORE,
+       [RSTN_SPI2_APB]      = CLK_SPI2_APB,
+       [RSTN_SPI2_CORE]     = CLK_SPI2_CORE,
+       [RSTN_SPI3_APB]      = CLK_SPI3_APB,
+       [RSTN_SPI3_CORE]     = CLK_SPI3_CORE,
+       [RSTN_I2C2_APB]      = CLK_I2C2_APB,
+       [RSTN_I2C2_CORE]     = CLK_I2C2_CORE,
+       [RSTN_I2C3_APB]      = CLK_I2C3_APB,
+       [RSTN_I2C3_CORE]     = CLK_I2C3_CORE,
+       [RSTN_WDTIMER_APB]   = CLK_WDTIMER_APB,
+       [RSTN_WDT]           = CLK_WDT_CORE,
+       [RSTN_VP6INTC_APB]   = CLK_VP6INTC_APB,
+       [RSTN_TEMP_APB]      = CLK_TEMP_APB,
+       [RSTN_TEMP_SENSE]    = CLK_TEMP_SENSE,
+};
+
+static struct clk *starfive_reset_clk_get(struct starfive_rstgen *priv, 
unsigned id)
+{
+       struct of_phandle_args clkspec = {
+               .np = priv->clknp,
+               .args_count = 1,
+       };
+
+       if (!priv->sync_resets || !priv->sync_resets[id])
+               return 0;
+
+       clkspec.args[0] = priv->sync_resets[id];
+
+       pr_debug("synchronous reset=%u clk=%u\n", id, priv->sync_resets[id]);
+
+       return of_clk_get_from_provider(&clkspec);
+}
+
+static int starfive_reset_clk_enable(struct starfive_rstgen *priv, unsigned id)
+{
+       return clk_enable(starfive_reset_clk_get(priv, id));
+}
+
+static void starfive_reset_clk_disable(struct starfive_rstgen *priv, unsigned 
id)
+{
+       clk_disable(starfive_reset_clk_get(priv, id));
+}
+
+static int starfive_rstgen(struct starfive_rstgen *priv, unsigned id, bool 
assert)
+{
+       void __iomem *base = priv->base;
+
+       __starfive_rstgen(base, id, assert);
+
+       return wait_on_timeout(NSEC_PER_MSEC, __starfive_rstgen_asserted(base, 
id) == assert);
+}
+
+static int starfive_rstgen_assert(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       struct starfive_rstgen *priv = to_starfive_rstgen(rcdev);
+       int ret;
+
+       starfive_reset_clk_enable(priv, id);
+       ret = starfive_rstgen(priv, id, true);
+       starfive_reset_clk_disable(priv, id);
+
+       return ret;
+}
+
+static int starfive_rstgen_deassert(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       struct starfive_rstgen *priv = to_starfive_rstgen(rcdev);
+       int ret;
+
+       starfive_reset_clk_enable(priv, id);
+       ret = starfive_rstgen(priv, id, false);
+       starfive_reset_clk_disable(priv, id);
+
+       return ret;
+}
+
+static int starfive_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+       struct starfive_rstgen *priv = to_starfive_rstgen(rcdev);
+       int ret;
+
+       starfive_reset_clk_enable(priv, id);
+
+       ret = starfive_rstgen(priv, id, true);
+       if (ret)
+               goto out;
+
+       udelay(2);
+
+       ret = starfive_rstgen(priv, id, false);
+
+out:
+       starfive_reset_clk_disable(priv, id);
+
+       return ret;
+}
+
+static const struct reset_control_ops starfive_rstgen_ops = {
+       .assert         = starfive_rstgen_assert,
+       .deassert       = starfive_rstgen_deassert,
+       .reset          = starfive_reset,
+};
+
+static int starfive_rstgen_probe(struct device_d *dev)
+{
+       struct starfive_rstgen *priv;
+       struct resource *iores;
+
+       priv = xzalloc(sizeof(*priv));
+
+       iores = dev_request_mem_resource(dev, 0);
+       if (IS_ERR(iores))
+               return PTR_ERR(iores);
+
+       if ((priv->sync_resets = device_get_match_data(dev))) {
+               priv->clknp = of_find_compatible_node(NULL, NULL, 
"starfive,jh7100-clkgen");
+               if (!priv->clknp)
+                       return -ENODEV;
+       }
+
+       priv->base = IOMEM(iores->start);
+       priv->rcdev.nr_resets = RSTN_END;
+       priv->rcdev.ops = &starfive_rstgen_ops;
+       priv->rcdev.of_node = dev->device_node;
+
+       return reset_controller_register(&priv->rcdev);
+}
+
+static const struct of_device_id starfive_rstgen_reset_dt_ids[] = {
+       { .compatible = "starfive,jh7100-rstgen", .data = 
jh7110_rstgen_sync_resets },
+       { /* sentinel */ },
+};
+
+static struct driver_d starfive_rstgen_reset_driver = {
+       .name = "starfive_rstgen",
+       .probe = starfive_rstgen_probe,
+       .of_compatible = starfive_rstgen_reset_dt_ids,
+};
+core_platform_driver(starfive_rstgen_reset_driver);
diff --git a/include/dt-bindings/reset-controller/starfive-jh7100.h 
b/include/dt-bindings/reset-controller/starfive-jh7100.h
new file mode 100644
index 000000000000..390a528576b9
--- /dev/null
+++ b/include/dt-bindings/reset-controller/starfive-jh7100.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 OR X11 */
+/*
+ * Copyright (c) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_STARFIVE_JH7100
+#define _DT_BINDINGS_RESET_CONTROLLER_STARFIVE_JH7100
+
+#define RSTN_DOM3AHB_BUS       0
+#define RSTN_DOM7AHB_BUS       1
+#define RST_U74                        2
+#define RSTN_U74_AXI           3
+#define RSTN_SGDMA2P_AHB       4
+#define RSTN_SGDMA2P_AXI       5
+#define RSTN_DMA2PNOC_AXI      6
+#define RSTN_DLA_AXI           7
+#define RSTN_DLANOC_AXI                8
+#define RSTN_DLA_APB           9
+#define RST_VP6_DRESET         10
+#define RST_VP6_BRESET         11
+#define RSTN_VP6_AXI           12
+#define RSTN_VDECBRG_MAIN      13
+#define RSTN_VDEC_AXI          14
+#define RSTN_VDEC_BCLK         15
+#define RSTN_VDEC_CCLK         16
+#define RSTN_VDEC_APB          17
+#define RSTN_JPEG_AXI          18
+#define RSTN_JPEG_CCLK         19
+#define RSTN_JPEG_APB          20
+#define RSTN_JPCGC300_MAIN     21
+#define RSTN_GC300_2X          22
+#define RSTN_GC300_AXI         23
+#define RSTN_GC300_AHB         24
+#define RSTN_VENC_AXI          25
+#define RSTN_VENCBRG_MAIN      26
+#define RSTN_VENC_BCLK         27
+#define RSTN_VENC_CCLK         28
+#define RSTN_VENC_APB          29
+#define RSTN_DDRPHY_APB                30
+#define RSTN_NOC_ROB           31
+#define RSTN_NOC_COG           32
+#define RSTN_HIFI4_AXI         33
+#define RSTN_HIFI4NOC_AXI      34
+#define RST_HIFI4_drESET       35
+#define RST_HIFI4_bRESET       36
+#define RSTN_USB_AXI           37
+#define RSTN_USBNOC_AXI                38
+#define RSTN_SGDMA1P_AXI       39
+#define RSTN_DMA1P_AXI         40
+#define RSTN_X2C_AXI           41
+#define RSTN_NNE_AHB           42
+#define RSTN_NNE_AXI           43
+#define RSTN_NNENOC_AXI                44
+#define RSTN_DLASLV_AXI                45
+#define RSTN_DSPX2C_AXI                46
+#define RSTN_VIN_SRC           47
+#define RSTN_ISPSLV_AXI                48
+#define RSTN_VIN_AXI           49
+#define RSTN_VINNOC_AXI                50
+#define RSTN_ISP0_AXI          51
+#define RSTN_ISP0NOC_AXI       52
+#define RSTN_ISP1_AXI          53
+#define RSTN_ISP1NOC_AXI       54
+#define RSTN_VOUT_SRC          55
+#define RSTN_DISP_AXI          56
+#define RSTN_DISPNOC_AXI       57
+#define RSTN_SDIO0_AHB         58
+#define RSTN_SDIO1_AHB         59
+#define RSTN_GMAC_AHB          60
+#define RSTN_SPI2AHB_AHB       61
+#define RSTN_SPI2AHB_CORE      62
+#define RSTN_EZMASTER_AHB      63
+#define RST_E24                        64
+#define RSTN_QSPI_AHB          65
+#define RSTN_QSPI_CORE         66
+#define RSTN_QSPI_APB          67
+#define RSTN_SEC_AHB           68
+#define RSTN_AES               69
+#define RSTN_PKA               70
+#define RSTN_SHA               71
+#define RSTN_TRNG_APB          72
+#define RSTN_OTP_APB           73
+#define RSTN_UART0_APB         74
+#define RSTN_UART0_CORE                75
+#define RSTN_UART1_APB         76
+#define RSTN_UART1_CORE                77
+#define RSTN_SPI0_APB          78
+#define RSTN_SPI0_CORE         79
+#define RSTN_SPI1_APB          80
+#define RSTN_SPI1_CORE         81
+#define RSTN_I2C0_APB          82
+#define RSTN_I2C0_CORE         83
+#define RSTN_I2C1_APB          84
+#define RSTN_I2C1_CORE         85
+#define RSTN_GPIO_APB          86
+#define RSTN_UART2_APB         87
+#define RSTN_UART2_CORE                88
+#define RSTN_UART3_APB         89
+#define RSTN_UART3_CORE                90
+#define RSTN_SPI2_APB          91
+#define RSTN_SPI2_CORE         92
+#define RSTN_SPI3_APB          93
+#define RSTN_SPI3_CORE         94
+#define RSTN_I2C2_APB          95
+#define RSTN_I2C2_CORE         96
+#define RSTN_I2C3_APB          97
+#define RSTN_I2C3_CORE         98
+#define RSTN_WDTIMER_APB       99
+#define RSTN_WDT               100
+#define RSTN_TIMER0            101
+#define RSTN_TIMER1            102
+#define RSTN_TIMER2            103
+#define RSTN_TIMER3            104
+#define RSTN_TIMER4            105
+#define RSTN_TIMER5            106
+#define RSTN_TIMER6            107
+#define RSTN_VP6INTC_APB       108
+#define RSTN_PWM_APB           109
+#define RSTN_MSI_APB           110
+#define RSTN_TEMP_APB          111
+#define RSTN_TEMP_SENSE                112
+#define RSTN_SYSERR_APB                113
+
+#define RSTN_END               114
+
+#endif
diff --git a/include/soc/starfive/rstgen.h b/include/soc/starfive/rstgen.h
new file mode 100644
index 000000000000..7a674aabe9f2
--- /dev/null
+++ b/include/soc/starfive/rstgen.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __SOC_STARFIVE_RSTGEN_H_
+#define __SOC_STARFIVE_RSTGEN_H_
+
+#include <dt-bindings/reset-controller/starfive-jh7100.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+#define STARFIVE_RSTGEN_STATUS 0x10
+
+static inline void __iomem *starfive_rstgen_bank(void __iomem *base, unsigned 
long *id)
+{
+       void __iomem *bank = base + *id / (4 * BITS_PER_BYTE) * 4;
+       *id %= 4 * BITS_PER_BYTE;
+       return bank;
+}
+
+static inline void __starfive_rstgen(void __iomem *base, unsigned long id, 
bool assert)
+{
+       void __iomem *bank = starfive_rstgen_bank(base, &id);
+       u32 val;
+
+       val = readl(bank);
+
+       if (assert)
+               val |= BIT(id);
+       else
+               val &= ~BIT(id);
+
+       writel(val, bank);
+}
+
+static bool __starfive_rstgen_asserted(void __iomem *base, unsigned long id)
+{
+       void __iomem *bank = starfive_rstgen_bank(base, &id);
+
+       return !(readl(bank + STARFIVE_RSTGEN_STATUS) & BIT(id));
+}
+
+#endif
-- 
2.29.2


_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to