From 49306f99390f7285ec4bbb9936cf74a85c8b8d4f Mon Sep 17 00:00:00 2001 From: samin Date: Thu, 16 Dec 2021 18:25:49 +0800 Subject: [PATCH] reset: starfive-jh7110: Add StarFive JH7110 reset driver Add a driver for the StarFive JH7110 reset controller. Signed-off-by: samin --- drivers/reset/Kconfig | 1 + drivers/reset/Makefile | 1 + drivers/reset/starfive/Kconfig | 6 + drivers/reset/starfive/Makefile | 2 + drivers/reset/starfive/reset-starfive-jh7110.c | 260 +++++++++++++++++++++++++ include/dt-bindings/reset/starfive-jh7110.h | 187 ++++++++++++++++++ 6 files changed, 457 insertions(+) create mode 100644 drivers/reset/starfive/Kconfig create mode 100644 drivers/reset/starfive/Makefile create mode 100644 drivers/reset/starfive/reset-starfive-jh7110.c create mode 100644 include/dt-bindings/reset/starfive-jh7110.h diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index b0056ae..5b23362 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -275,6 +275,7 @@ config RESET_ZYNQ help This enables the reset controller driver for Xilinx Zynq SoCs. +source "drivers/reset/starfive/Kconfig" source "drivers/reset/sti/Kconfig" source "drivers/reset/hisilicon/Kconfig" source "drivers/reset/tegra/Kconfig" diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 21d46d8..e7edddc 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += core.o obj-y += hisilicon/ +obj-y += starfive/ obj-$(CONFIG_ARCH_STI) += sti/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o diff --git a/drivers/reset/starfive/Kconfig b/drivers/reset/starfive/Kconfig new file mode 100644 index 0000000..37c1088 --- /dev/null +++ b/drivers/reset/starfive/Kconfig @@ -0,0 +1,6 @@ +config RESET_STARFIVE_JH7110 + bool "StarFive JH7110 Reset Driver" + depends on SOC_STARFIVE || COMPILE_TEST + default SOC_STARFIVE_JH7110 + help + This enables the reset controller driver for the StarFive JH7110 SoC. diff --git a/drivers/reset/starfive/Makefile b/drivers/reset/starfive/Makefile new file mode 100644 index 0000000..a5b06a2 --- /dev/null +++ b/drivers/reset/starfive/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_RESET_STARFIVE_JH7110) += reset-starfive-jh7110.o diff --git a/drivers/reset/starfive/reset-starfive-jh7110.c b/drivers/reset/starfive/reset-starfive-jh7110.c new file mode 100644 index 0000000..412c253 --- /dev/null +++ b/drivers/reset/starfive/reset-starfive-jh7110.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Reset driver for the StarFive JH7110 SoC + * + * Copyright (C) 2021 samin + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* register offsets */ +#define SYSCRG_RESET_ASSERT0 0x2F8 +#define SYSCRG_RESET_ASSERT1 0x2FC +#define SYSCRG_RESET_ASSERT2 0x300 +#define SYSCRG_RESET_ASSERT3 0x304 +#define SYSCRG_RESET_STATUS0 0x308 +#define SYSCRG_RESET_STATUS1 0x30C +#define SYSCRG_RESET_STATUS2 0x310 +#define SYSCRG_RESET_STATUS3 0x314 + +#define STGCRG_RESET_ASSERT0 0x74 +#define STGCRG_RESET_STATUS0 0x78 + +#define AONCRG_RESET_ASSERT0 0x38 +#define AONCRG_RESET_STATUS0 0x3C + +struct reset_assert_t { + void *__iomem reg_assert; + void *__iomem reg_status; +}; + +enum JH7110_RESET_CRG_GROUP { + SYSCRG_0 = 0, + SYSCRG_1, + SYSCRG_2, + SYSCRG_3, + STGCRG_0, + AONCRG_0, +}; + +struct jh7110_reset { + struct reset_assert_t reset_assert[6]; + struct reset_controller_dev rcdev; + /* protect registers against concurrent read-modify-write */ + spinlock_t lock; + void __iomem *syscrg; + void __iomem *stgcrg; + void __iomem *aoncrg; + const u32 *asserted; +}; + +/* + * Writing a 1 to the n'th bit of the m'th ASSERT register asserts + * line 32m + n, and writing a 0 deasserts the same line. + * Most reset lines have their status inverted so a 0 bit in the STATUS + * register means the line is asserted and a 1 means it's deasserted. A few + * lines don't though, so store the expected value of the status registers when + * all lines are asserted. + */ +static const u32 jh7110_reset_asserted[6] = { + /* SYSCRG_STATUS0 */ + BIT(RSTN_U0_U7MC_RST_BUS % 32) | + BIT(RSTN_U0_U7MC_CORE0 % 32) | + BIT(RSTN_U0_U7MC_CORE1 % 32) | + BIT(RSTN_U0_U7MC_CORE2 % 32) | + BIT(RSTN_U0_U7MC_CORE3 % 32) | + BIT(RSTN_U0_U7MC_CORE4 % 32), + /* SYSCRG_STATUS1 */ + 0, + /* SYSCRG_STATUS2 */ + 0, + /* SYSCRG_STATUS3 */ + 0, + /* STGCRG */ + BIT(RSTN_U0_HIFI4_CORE % 32) | + BIT(RSTN_U0_E24_CORE % 32), + /* AONCRG */ + 0, +}; + +static inline struct jh7110_reset * +jh7110_reset_from(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct jh7110_reset, rcdev); +} + +static void jh7110_devm_reset_set(struct device *dev) +{ + struct jh7110_reset *data = dev->driver_data; + + data->reset_assert[SYSCRG_0].reg_assert = data->syscrg + SYSCRG_RESET_ASSERT0; + data->reset_assert[SYSCRG_0].reg_status = data->syscrg + SYSCRG_RESET_STATUS0; + + data->reset_assert[SYSCRG_1].reg_assert = data->syscrg + SYSCRG_RESET_ASSERT1; + data->reset_assert[SYSCRG_1].reg_status = data->syscrg + SYSCRG_RESET_STATUS1; + + data->reset_assert[SYSCRG_2].reg_assert = data->syscrg + SYSCRG_RESET_ASSERT2; + data->reset_assert[SYSCRG_2].reg_status = data->syscrg + SYSCRG_RESET_STATUS2; + + data->reset_assert[SYSCRG_3].reg_assert = data->syscrg + SYSCRG_RESET_ASSERT3; + data->reset_assert[SYSCRG_3].reg_status = data->syscrg + SYSCRG_RESET_STATUS3; + + data->reset_assert[STGCRG_0].reg_assert = data->stgcrg + STGCRG_RESET_ASSERT0; + data->reset_assert[STGCRG_0].reg_status = data->stgcrg + STGCRG_RESET_STATUS0; + + data->reset_assert[AONCRG_0].reg_assert = data->aoncrg + AONCRG_RESET_ASSERT0; + data->reset_assert[AONCRG_0].reg_status = data->aoncrg + AONCRG_RESET_STATUS0; +} + +static int jh7110_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct jh7110_reset *data = jh7110_reset_from(rcdev); + void __iomem *reg_assert, *reg_status; + unsigned long group, flags; + u32 mask, value, done; + int ret; + + group = id / 32; + mask = BIT(id % 32); + reg_assert = data->reset_assert[group].reg_assert; + reg_status = data->reset_assert[group].reg_status; + + done = data->asserted[group] & mask; + + if (!assert) + done ^= mask; + + spin_lock_irqsave(&data->lock, flags); + + value = readl(reg_assert); + if (assert) + value |= mask; + else + value &= ~mask; + writel(value, reg_assert); + + /* if the associated clock is gated, deasserting might otherwise hang forever */ + ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000); + if (ret) + dev_warn(rcdev->dev, "id:%ld group:%ld, mask:%#x assert:%#llx status:%#llx ret:%d\n", + id, group, mask, (u64)reg_assert, (u64)reg_status, ret); + + spin_unlock_irqrestore(&data->lock, flags); + return ret; +} + +static int jh7110_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return jh7110_reset_update(rcdev, id, true); +} + +static int jh7110_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return jh7110_reset_update(rcdev, id, false); +} + +static int jh7110_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = jh7110_reset_assert(rcdev, id); + if (ret) + return ret; + + return jh7110_reset_deassert(rcdev, id); +} + +static int jh7110_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct jh7110_reset *data = jh7110_reset_from(rcdev); + void __iomem *reg_status; + unsigned long group; + u32 mask, val; + + group = id / 32; + mask = BIT(id % 32); + reg_status = data->reset_assert[group].reg_status; + val = readl(reg_status); + + return !((val ^ data->asserted[group]) & mask); +} + +static const struct reset_control_ops jh7110_reset_ops = { + .assert = jh7110_reset_assert, + .deassert = jh7110_reset_deassert, + .reset = jh7110_reset_reset, + .status = jh7110_reset_status, +}; + +int __init reset_starfive_jh7110_generic_probe(struct platform_device *pdev, + const u32 *asserted, + unsigned int nr_resets) +{ + struct jh7110_reset *data; + struct device *dev = &pdev->dev; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + dev->driver_data = data; + + data->syscrg = devm_platform_ioremap_resource_byname(pdev, "syscrg"); + if (IS_ERR(data->syscrg)) + return PTR_ERR(data->syscrg); + + data->stgcrg = devm_platform_ioremap_resource_byname(pdev, "stgcrg"); + if (IS_ERR(data->stgcrg)) + return PTR_ERR(data->stgcrg); + + data->aoncrg = devm_platform_ioremap_resource_byname(pdev, "aoncrg"); + if (IS_ERR(data->aoncrg)) + return PTR_ERR(data->aoncrg); + + jh7110_devm_reset_set(dev); + + data->rcdev.ops = &jh7110_reset_ops; + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = nr_resets; + data->rcdev.dev = &pdev->dev; + data->rcdev.of_node = pdev->dev.of_node; + spin_lock_init(&data->lock); + + data->asserted = asserted; + + return devm_reset_controller_register(dev, &data->rcdev); +} +EXPORT_SYMBOL_GPL(reset_starfive_jh7110_generic_probe); + +static int __init jh7110_reset_probe(struct platform_device *pdev) +{ + return reset_starfive_jh7110_generic_probe(pdev, jh7110_reset_asserted, + RSTN_JH7110_RESET_END); +} + +static const struct of_device_id jh7110_reset_dt_ids[] = { + { .compatible = "starfive,jh7110-reset" }, + { /* sentinel */ } +}; + +static struct platform_driver jh7110_reset_driver = { + .driver = { + .name = "jh7110-reset", + .of_match_table = jh7110_reset_dt_ids, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver_probe(jh7110_reset_driver, jh7110_reset_probe); diff --git a/include/dt-bindings/reset/starfive-jh7110.h b/include/dt-bindings/reset/starfive-jh7110.h new file mode 100644 index 0000000..b8cddb2 --- /dev/null +++ b/include/dt-bindings/reset/starfive-jh7110.h @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * Copyright (C) 2021 samin + */ + +#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7110_H__ +#define __DT_BINDINGS_RESET_STARFIVE_JH7110_H__ + +/* + * group[0]: syscrg: assert0 + */ +#define RSTN_U0_JTAG2APB_PRESETN 0 +#define RSTN_U0_SYS_SYSCON_PRESETN 1 +#define RSTN_U0_SYS_IOMUX_PRESETN 2 +#define RSTN_U0_U7MC_RST_BUS 3 +#define RSTN_U0_U7MC_DEBUG 4 +#define RSTN_U0_U7MC_CORE0 5 +#define RSTN_U0_U7MC_CORE1 6 +#define RSTN_U0_U7MC_CORE2 7 +#define RSTN_U0_U7MC_CORE3 8 +#define RSTN_U0_U7MC_CORE4 9 +#define RSTN_U0_U7MC_CORE0_ST 10 +#define RSTN_U0_U7MC_CORE1_ST 11 +#define RSTN_U0_U7MC_CORE2_ST 12 +#define RSTN_U0_U7MC_CORE3_ST 13 +#define RSTN_U0_U7MC_CORE4_ST 14 +#define RSTN_U0_U7MC_TRACE_RST0 15 +#define RSTN_U0_U7MC_TRACE_RST1 16 +#define RSTN_U0_U7MC_TRACE_RST2 17 +#define RSTN_U0_U7MC_TRACE_RST3 18 +#define RSTN_U0_U7MC_TRACE_RST4 19 +#define RSTN_U0_U7MC_TRACE_COM 20 +#define RSTN_U0_IMG_GPU_APB 21 +#define RSTN_U0_IMG_GPU_DOMA 22 +#define RSTN_U0_NOC_BUS_APB_BUS_N 23 +#define RSTN_U0_NOC_BUS_AXICFG0_AXI_N 24 +#define RSTN_U0_NOC_BUS_CPU_AXI_N 25 +#define RSTN_U0_NOC_BUS_DISP_AXI_N 26 +#define RSTN_U0_NOC_BUS_GPU_AXI_N 27 +#define RSTN_U0_NOC_BUS_ISP_AXI_N 28 +#define RSTN_U0_NOC_BUS_DDRC_N 29 +#define RSTN_U0_NOC_BUS_STG_AXI_N 30 +#define RSTN_U0_NOC_BUS_VDEC_AXI_N 31 +/* + * group[1]: syscrg: assert1 + */ +#define RSTN_U0_NOC_BUS_VENC_AXI_N 32 +#define RSTN_U0_AXI_CFG1_DEC_AHB 33 +#define RSTN_U0_AXI_CFG1_DEC_MAIN 34 +#define RSTN_U0_AXI_CFG0_DEC_MAIN 35 +#define RSTN_U0_AXI_CFG0_DEC_MAIN_DIV 36 +#define RSTN_U0_AXI_CFG0_DEC_HIFI4 37 +#define RSTN_U0_DDR_AXI 38 +#define RSTN_U0_DDR_OSC 39 +#define RSTN_U0_DDR_APB 40 +#define RSTN_U0_DOM_ISP_TOP_N 41 +#define RSTN_U0_DOM_ISP_TOP_AXI 42 +#define RSTN_U0_DOM_VOUT_TOP_SRC 43 +#define RSTN_U0_CODAJ12_AXI 44 +#define RSTN_U0_CODAJ12_CORE 45 +#define RSTN_U0_CODAJ12_APB 46 +#define RSTN_U0_WAVE511_AXI 47 +#define RSTN_U0_WAVE511_BPU 48 +#define RSTN_U0_WAVE511_VCE 49 +#define RSTN_U0_WAVE511_APB 50 +#define RSTN_U0_VDEC_JPG_ARB_JPG 51 +#define RSTN_U0_VDEC_JPG_ARB_MAIN 52 +#define RSTN_U0_AXIMEM_128B_AXI 53 +#define RSTN_U0_WAVE420L_AXI 54 +#define RSTN_U0_WAVE420L_BPU 55 +#define RSTN_U0_WAVE420L_VCE 56 +#define RSTN_U0_WAVE420L_APB 57 +#define RSTN_U1_AXIMEM_128B_AXI 58 +#define RSTN_U2_AXIMEM_128B_AXI 59 +#define RSTN_U0_INTMEM_ROM_SRAM_ROM 60 +#define RSTN_U0_CDNS_QSPI_AHB 61 +#define RSTN_U0_CDNS_QSPI_APB 62 +#define RSTN_U0_CDNS_QSPI_REF 63 +/* + * group[2]: syscrg: assert2 + */ +#define RSTN_U0_DW_SDIO_AHB 64 +#define RSTN_U1_DW_SDIO_AHB 65 +#define RSTN_U1_DW_GMAC5_AXI64_A_I 66 +#define RSTN_U1_DW_GMAC5_AXI64_H_N 67 +#define RSTN_U0_MAILBOX_RRESETN 68 +#define RSTN_U0_SSP_SPI_APB 69 +#define RSTN_U1_SSP_SPI_APB 70 +#define RSTN_U2_SSP_SPI_APB 71 +#define RSTN_U3_SSP_SPI_APB 72 +#define RSTN_U4_SSP_SPI_APB 73 +#define RSTN_U5_SSP_SPI_APB 74 +#define RSTN_U6_SSP_SPI_APB 75 +#define RSTN_U0_DW_I2C_APB 76 +#define RSTN_U1_DW_I2C_APB 77 +#define RSTN_U2_DW_I2C_APB 78 +#define RSTN_U3_DW_I2C_APB 79 +#define RSTN_U4_DW_I2C_APB 80 +#define RSTN_U5_DW_I2C_APB 81 +#define RSTN_U6_DW_I2C_APB 82 +#define RSTN_U0_DW_UART_APB 83 +#define RSTN_U0_DW_UART_CORE 84 +#define RSTN_U1_DW_UART_APB 85 +#define RSTN_U1_DW_UART_CORE 86 +#define RSTN_U2_DW_UART_APB 87 +#define RSTN_U2_DW_UART_CORE 88 +#define RSTN_U3_DW_UART_APB 89 +#define RSTN_U3_DW_UART_CORE 90 +#define RSTN_U4_DW_UART_APB 91 +#define RSTN_U4_DW_UART_CORE 92 +#define RSTN_U5_DW_UART_APB 93 +#define RSTN_U5_DW_UART_CORE 94 +#define RSTN_U0_CDNS_SPDIF_APB 95 +/* + * group[3]: syscrg: assert3 + */ +#define RSTN_U0_PWMDAC_APB 96 +#define RSTN_U0_PDM_4MIC_DMIC 97 +#define RSTN_U0_PDM_4MIC_APB 98 +#define RSTN_U0_I2SRX_3CH_APB 99 +#define RSTN_U0_I2SRX_3CH_BCLK 100 +#define RSTN_U0_I2STX_4CH_APB 101 +#define RSTN_U0_I2STX_4CH_BCLK 102 +#define RSTN_U1_I2STX_4CH_APB 103 +#define RSTN_U1_I2STX_4CH_BCLK 104 +#define RSTN_U0_TDM16SLOT_AHB 105 +#define RSTN_U0_TDM16SLOT_TDM 106 +#define RSTN_U0_TDM16SLOT_APB 107 +#define RSTN_U0_PWM_8CH_APB 108 +#define RSTN_U0_DSKIT_WDT_APB 109 +#define RSTN_U0_DSKIT_WDT_CORE 110 +#define RSTN_U0_CAN_CTRL_APB 111 +#define RSTN_U0_CAN_CTRL_CORE 112 +#define RSTN_U0_CAN_CTRL_TIMER 113 +#define RSTN_U1_CAN_CTRL_APB 114 +#define RSTN_U2_CAN_CTRL_CORE 115 +#define RSTN_U3_CAN_CTRL_TIMER 116 +#define RSTN_U0_SI5_TIMER_APB 117 +#define RSTN_U0_SI5_TIMER_TIMER0 118 +#define RSTN_U0_SI5_TIMER_TIMER1 119 +#define RSTN_U0_SI5_TIMER_TIMER2 120 +#define RSTN_U0_SI5_TIMER_TIMER3 121 +#define RSTN_U0_INT_CTRL_APB 122 +#define RSTN_U0_TEMP_SENSOR_APB 123 +#define RSTN_U0_TEMP_SENSOR_TEMP 124 +#define RSTN_U0_JTAG_CERTIFICATION_N 125 +/* + * group[4]: stgcrg + */ +#define RSTN_U0_STG_SYSCON_PRESETN 128 +#define RSTN_U0_HIFI4_CORE 129 +#define RSTN_U0_HIFI4_AXI 130 +#define RSTN_U0_SEC_TOP_HRESETN 131 +#define RSTN_U0_E24_CORE 132 +#define RSTN_U0_DW_DMA1P_AXI 133 +#define RSTN_U0_DW_DMA1P_AHP 134 +#define RSTN_U0_CDN_USB_AXI 135 +#define RSTN_U0_CDN_USB_APB 136 +#define RSTN_U0_CDN_USB_UTMI_APB 137 +#define RSTN_U0_CDN_USB_PWEUP 138 +#define RSTN_U0_PLDA_PCIE_AXI_MST0 139 +#define RSTN_U0_PLDA_PCIE_AXI_SLV0 140 +#define RSTN_U0_PLDA_PCIE_AXI_SLV 141 +#define RSTN_U0_PLDA_PCIE_BRG 142 +#define RSTN_U0_PLDA_PCIE_CORE 143 +#define RSTN_U0_PLDA_PCIE_APB 144 +#define RSTN_U1_PLDA_PCIE_AXI_MST0 145 +#define RSTN_U1_PLDA_PCIE_AXI_SLV0 146 +#define RSTN_U1_PLDA_PCIE_AXI_SLV 147 +#define RSTN_U1_PLDA_PCIE_BRG 148 +#define RSTN_U1_PLDA_PCIE_CORE 149 +#define RSTN_U1_PLDA_PCIE_APB 150 +/* + * group[5]: aoncrg + */ +#define RSTN_U0_DW_GMAC5_AXI64_AXI 160 +#define RSTN_U0_DW_GMAC5_AXI64_AHB 161 +#define RSTN_U0_AON_IOMUX_PRESETN 162 +#define RSTN_U0_PMU_APB 163 +#define RSTN_U0_PMU_WKUP 164 +#define RSTN_U0_RTC_HMS_APB 165 +#define RSTN_U0_RTC_HMS_CAL 166 +#define RSTN_U0_RTC_HMS_OSC32K 167 + +#define RSTN_JH7110_RESET_END 168 + +#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_H__ */ -- 2.7.4