Reset controller updates for v6.17

* Support reset controllers on Kendryte K230 and SOPHGO CV1800B.
 * Add RZ/V2N USB2PHY reset controller bindings
 * Use auxiliary device creation helpers in reset-mpfs.
 * Convert nxp,lcp1850-rgu and snps,dw-reset binding docs to DT schema.
 * Enable reset-brcmstb(-rescal) on BCM2712.
 * Fix a typo in the T-HEAD TH1520 Kconfig option
 -----BEGIN PGP SIGNATURE-----
 
 iI0EABYIADUWIQRRO6F6WdpH1R0vGibVhaclGDdiwAUCaG/amxcccC56YWJlbEBw
 ZW5ndXRyb25peC5kZQAKCRDVhaclGDdiwK6oAP9aCwONI6A0uq5deV4caorQguqU
 iGU+IOup1VabI4l/JAEAq/48VrYuy/zS8jtn9jOnJD1DLkVMMhYL1+toeqqXKQ8=
 =DjB0
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmh+U0AACgkQmmx57+YA
 GNmDmQ/+Nv8gUvNO3zdVcRCZXl+SE3gjV2+l2BpXaAWylUMqBduEl7hLUpUg2PRB
 vl0cDsaIlwy8gqIbA1mMRDcHN1r0seyEbt5cVJh9VohFaoxPJ6+YzlopFvlsTDrx
 lLzhYqvvXOx+1KQInH4VQIiUzqeUFyKkw/VHHikRqe0CCIqL8PsiEUErKW0XkrDn
 SpqRpvRtZS4eGwaApzr0giiYoWhCGfkWWFWCVOHlDNvjne8XU1B3wZ60s/dYif+F
 qz0G8YAm12FTUe/yWOjM9yHWlCD2FO1amdvgZ6Ac+UetKd9gA28CiFF6EaHhUe0x
 n+c9+JNYaR/RRzj7gFCH7gRruJB29I7itpHRQ7N4fVHTsZAGY9jDOOqbhUm9WuCR
 ZaPbmoMPZk/yKQNQmlOFfPLFKBOXDF+Jw17xv85iU8dNQ0Pl5FCTz4sCNpU4x78k
 Fr+uS5r9B/8GWOCZeCwEpUY3wkz4lbOfd9df5l0Mb7JnythDqeH7y0NK0Z/dC96P
 cTv69JYqHV0bQqQm32ZAQ49U6P/8Jyq7M0uAcR4gwZ+AquTbVMWw6hANbxJcdGv0
 hG0v6Cov++AZRStPmlLZpAJ8f3S6gUMLkau3KZ/4dg29oaBuWeLI9Fr64ZCadTFF
 LJoEqlwvy3YSs/cMjtaRiMPrvJZxPD36P5rnao5XD/MfZmXJr30=
 =heN+
 -----END PGP SIGNATURE-----

Merge tag 'reset-for-v6.17' of https://git.pengutronix.de/git/pza/linux into soc/drivers

Reset controller updates for v6.17

* Support reset controllers on Kendryte K230 and SOPHGO CV1800B.
* Add RZ/V2N USB2PHY reset controller bindings
* Use auxiliary device creation helpers in reset-mpfs.
* Convert nxp,lcp1850-rgu and snps,dw-reset binding docs to DT schema.
* Enable reset-brcmstb(-rescal) on BCM2712.
* Fix a typo in the T-HEAD TH1520 Kconfig option

* tag 'reset-for-v6.17' of https://git.pengutronix.de/git/pza/linux:
  dt-bindings: reset: Convert snps,dw-reset to DT schema
  reset: brcmstb: Enable reset drivers for ARCH_BCM2835
  reset: simple: add support for Sophgo CV1800B
  dt-bindings: reset: sophgo: Add CV1800B support
  reset: mpfs: use the auxiliary device creation
  dt-bindings: reset: renesas,rzv2h-usb2phy: Document RZ/V2N SoC support
  dt-bindings: reset: convert nxp,lpc1850-rgu.txt to yaml format
  reset: thead: Fix TH1520 typo
  reset: canaan: add reset driver for Kendryte K230
  dt-bindings: reset: add support for canaan,k230-rst

Link: https://lore.kernel.org/r/20250710152513.1346298-1-p.zabel@pengutronix.de
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2025-07-21 16:48:32 +02:00
commit ed82b8d657
13 changed files with 672 additions and 172 deletions

View File

@ -0,0 +1,39 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/canaan,k230-rst.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Canaan Kendryte K230 Reset Controller
maintainers:
- Junhui Liu <junhui.liu@pigmoral.tech>
description:
The Canaan Kendryte K230 reset controller is part of the SoC's system
controller and controls the reset registers for CPUs and various peripherals.
properties:
compatible:
const: canaan,k230-rst
reg:
maxItems: 1
'#reset-cells':
const: 1
required:
- compatible
- reg
- '#reset-cells'
additionalProperties: false
examples:
- |
reset-controller@91101000 {
compatible = "canaan,k230-rst";
reg = <0x91101000 0x1000>;
#reset-cells = <1>;
};

View File

@ -1,83 +0,0 @@
NXP LPC1850 Reset Generation Unit (RGU)
========================================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required properties:
- compatible: Should be "nxp,lpc1850-rgu"
- reg: register base and length
- clocks: phandle and clock specifier to RGU clocks
- clock-names: should contain "delay" and "reg"
- #reset-cells: should be 1
See table below for valid peripheral reset numbers. Numbers not
in the table below are either reserved or not applicable for
normal operation.
Reset Peripheral
9 System control unit (SCU)
12 ARM Cortex-M0 subsystem core (LPC43xx only)
13 CPU core
16 LCD controller
17 USB0
18 USB1
19 DMA
20 SDIO
21 External memory controller (EMC)
22 Ethernet
25 Flash bank A
27 EEPROM
28 GPIO
29 Flash bank B
32 Timer0
33 Timer1
34 Timer2
35 Timer3
36 Repetitive Interrupt timer (RIT)
37 State Configurable Timer (SCT)
38 Motor control PWM (MCPWM)
39 QEI
40 ADC0
41 ADC1
42 DAC
44 USART0
45 UART1
46 USART2
47 USART3
48 I2C0
49 I2C1
50 SSP0
51 SSP1
52 I2S0 and I2S1
53 Serial Flash Interface (SPIFI)
54 C_CAN1
55 C_CAN0
56 ARM Cortex-M0 application core (LPC4370 only)
57 SGPIO (LPC43xx only)
58 SPI (LPC43xx only)
60 ADCHS (12-bit ADC) (LPC4370 only)
Refer to NXP LPC18xx or LPC43xx user manual for more details about
the reset signals and the connected block/peripheral.
Reset provider example:
rgu: reset-controller@40053000 {
compatible = "nxp,lpc1850-rgu";
reg = <0x40053000 0x1000>;
clocks = <&cgu BASE_SAFE_CLK>, <&ccu1 CLK_CPU_BUS>;
clock-names = "delay", "reg";
#reset-cells = <1>;
};
Reset consumer example:
mac: ethernet@40010000 {
compatible = "nxp,lpc1850-dwmac", "snps,dwmac-3.611", "snps,dwmac";
reg = <0x40010000 0x2000>;
interrupts = <5>;
interrupt-names = "macirq";
clocks = <&ccu1 CLK_CPU_ETHERNET>;
clock-names = "stmmaceth";
resets = <&rgu 22>;
reset-names = "stmmaceth";
};

View File

@ -0,0 +1,101 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/nxp,lpc1850-rgu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP LPC1850 Reset Generation Unit (RGU)
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
const: nxp,lpc1850-rgu
reg:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: delay
- const: reg
'#reset-cells':
const: 1
description: |
See table below for valid peripheral reset numbers. Numbers not
in the table below are either reserved or not applicable for
normal operation.
Reset Peripheral
9 System control unit (SCU)
12 ARM Cortex-M0 subsystem core (LPC43xx only)
13 CPU core
16 LCD controller
17 USB0
18 USB1
19 DMA
20 SDIO
21 External memory controller (EMC)
22 Ethernet
25 Flash bank A
27 EEPROM
28 GPIO
29 Flash bank B
32 Timer0
33 Timer1
34 Timer2
35 Timer3
36 Repetitive Interrupt timer (RIT)
37 State Configurable Timer (SCT)
38 Motor control PWM (MCPWM)
39 QEI
40 ADC0
41 ADC1
42 DAC
44 USART0
45 UART1
46 USART2
47 USART3
48 I2C0
49 I2C1
50 SSP0
51 SSP1
52 I2S0 and I2S1
53 Serial Flash Interface (SPIFI)
54 C_CAN1
55 C_CAN0
56 ARM Cortex-M0 application core (LPC4370 only)
57 SGPIO (LPC43xx only)
58 SPI (LPC43xx only)
60 ADCHS (12-bit ADC) (LPC4370 only)
Refer to NXP LPC18xx or LPC43xx user manual for more details about
the reset signals and the connected block/peripheral.
required:
- compatible
- reg
- clocks
- clock-names
- '#reset-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/lpc18xx-ccu.h>
#include <dt-bindings/clock/lpc18xx-cgu.h>
reset-controller@40053000 {
compatible = "nxp,lpc1850-rgu";
reg = <0x40053000 0x1000>;
clocks = <&cgu BASE_SAFE_CLK>, <&ccu1 CLK_CPU_BUS>;
clock-names = "delay", "reg";
#reset-cells = <1>;
};

View File

@ -15,7 +15,12 @@ description:
properties:
compatible:
const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P)
oneOf:
- items:
- const: renesas,r9a09g056-usb2phy-reset # RZ/V2N
- const: renesas,r9a09g057-usb2phy-reset
- const: renesas,r9a09g057-usb2phy-reset # RZ/V2H(P)
reg:
maxItems: 1

View File

@ -1,30 +0,0 @@
Synopsys DesignWare Reset controller
=======================================
Please also refer to reset.txt in this directory for common reset
controller binding usage.
Required properties:
- compatible: should be one of the following.
"snps,dw-high-reset" - for active high configuration
"snps,dw-low-reset" - for active low configuration
- reg: physical base address of the controller and length of memory mapped
region.
- #reset-cells: must be 1.
example:
dw_rst_1: reset-controller@0000 {
compatible = "snps,dw-high-reset";
reg = <0x0000 0x4>;
#reset-cells = <1>;
};
dw_rst_2: reset-controller@1000 {
compatible = "snps,dw-low-reset";
reg = <0x1000 0x8>;
#reset-cells = <1>;
};

View File

@ -0,0 +1,39 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/snps,dw-reset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Synopsys DesignWare Reset controller
maintainers:
- Philipp Zabel <p.zabel@pengutronix.de>
properties:
compatible:
enum:
- snps,dw-high-reset
- snps,dw-low-reset
reg:
maxItems: 1
'#reset-cells':
const: 1
reset-controller: true
required:
- compatible
- reg
- '#reset-cells'
additionalProperties: false
examples:
- |
reset-controller@0 {
compatible = "snps,dw-high-reset";
reg = <0x0000 0x4>;
#reset-cells = <1>;
};

View File

@ -16,7 +16,9 @@ properties:
- enum:
- sophgo,sg2044-reset
- const: sophgo,sg2042-reset
- const: sophgo,sg2042-reset
- enum:
- sophgo,cv1800b-reset
- sophgo,sg2042-reset
reg:
maxItems: 1

View File

@ -51,8 +51,8 @@ config RESET_BERLIN
config RESET_BRCMSTB
tristate "Broadcom STB reset controller"
depends on ARCH_BRCMSTB || COMPILE_TEST
default ARCH_BRCMSTB
depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
default ARCH_BRCMSTB || ARCH_BCM2835
help
This enables the reset controller driver for Broadcom STB SoCs using
a SUN_TOP_CTRL_SW_INIT style controller.
@ -60,11 +60,11 @@ config RESET_BRCMSTB
config RESET_BRCMSTB_RESCAL
tristate "Broadcom STB RESCAL reset controller"
depends on HAS_IOMEM
depends on ARCH_BRCMSTB || COMPILE_TEST
default ARCH_BRCMSTB
depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
default ARCH_BRCMSTB || ARCH_BCM2835
help
This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on
BCM7216.
BCM7216 or the BCM2712.
config RESET_EYEQ
bool "Mobileye EyeQ reset controller"
@ -140,6 +140,15 @@ config RESET_K210
Say Y if you want to control reset signals provided by this
controller.
config RESET_K230
tristate "Reset controller driver for Canaan Kendryte K230 SoC"
depends on ARCH_CANAAN || COMPILE_TEST
depends on OF
help
Support for the Canaan Kendryte K230 RISC-V SoC reset controller.
Say Y if you want to control reset signals provided by this
controller.
config RESET_LANTIQ
bool "Lantiq XWAY Reset Driver" if COMPILE_TEST
default SOC_TYPE_XWAY
@ -287,7 +296,7 @@ config RESET_SUNXI
This enables the reset driver for Allwinner SoCs.
config RESET_TH1520
tristate "T-HEAD 1520 reset controller"
tristate "T-HEAD TH1520 reset controller"
depends on ARCH_THEAD || COMPILE_TEST
select REGMAP_MMIO
help

View File

@ -20,6 +20,7 @@ obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_IMX8MP_AUDIOMIX) += reset-imx8mp-audiomix.o
obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
obj-$(CONFIG_RESET_K210) += reset-k210.o
obj-$(CONFIG_RESET_K230) += reset-k230.o
obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MCHP_SPARX5) += reset-microchip-sparx5.o

371
drivers/reset/reset-k230.c Normal file
View File

@ -0,0 +1,371 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2022-2024 Canaan Bright Sight Co., Ltd
* Copyright (C) 2024-2025 Junhui Liu <junhui.liu@pigmoral.tech>
*
* The reset management module in the K230 SoC provides reset time control
* registers. For RST_TYPE_CPU0, RST_TYPE_CPU1 and RST_TYPE_SW_DONE, the period
* during which reset is applied or removed while the clock is stopped can be
* set up to 15 * 0.25 = 3.75 µs. For RST_TYPE_HW_DONE, that period can be set
* up to 255 * 0.25 = 63.75 µs. For RST_TYPE_FLUSH, the reset bit is
* automatically cleared by hardware when flush completes.
*
* Although this driver does not configure the reset time registers, delays have
* been added to the assert, deassert, and reset operations to cover the maximum
* reset time. Some reset types include done bits whose toggle does not
* unambiguously signal whether hardware reset removal or clock-stop period
* expiration occurred first. Delays are therefore retained for types with done
* bits to ensure safe timing.
*
* Reference: K230 Technical Reference Manual V0.3.1
* https://kendryte-download.canaan-creative.com/developer/k230/HDK/K230%E7%A1%AC%E4%BB%B6%E6%96%87%E6%A1%A3/K230_Technical_Reference_Manual_V0.3.1_20241118.pdf
*/
#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
#include <dt-bindings/reset/canaan,k230-rst.h>
/**
* enum k230_rst_type - K230 reset types
* @RST_TYPE_CPU0: Reset type for CPU0
* Automatically clears, has write enable and done bit, active high
* @RST_TYPE_CPU1: Reset type for CPU1
* Manually clears, has write enable and done bit, active high
* @RST_TYPE_FLUSH: Reset type for CPU L2 cache flush
* Automatically clears, has write enable, no done bit, active high
* @RST_TYPE_HW_DONE: Reset type for hardware auto clear
* Automatically clears, no write enable, has done bit, active high
* @RST_TYPE_SW_DONE: Reset type for software manual clear
* Manually clears, no write enable and done bit,
* active high if ID is RST_SPI2AXI, otherwise active low
*/
enum k230_rst_type {
RST_TYPE_CPU0,
RST_TYPE_CPU1,
RST_TYPE_FLUSH,
RST_TYPE_HW_DONE,
RST_TYPE_SW_DONE,
};
struct k230_rst_map {
u32 offset;
enum k230_rst_type type;
u32 done;
u32 reset;
};
struct k230_rst {
struct reset_controller_dev rcdev;
void __iomem *base;
/* protect register read-modify-write */
spinlock_t lock;
};
static const struct k230_rst_map k230_resets[] = {
[RST_CPU0] = { 0x4, RST_TYPE_CPU0, BIT(12), BIT(0) },
[RST_CPU1] = { 0xc, RST_TYPE_CPU1, BIT(12), BIT(0) },
[RST_CPU0_FLUSH] = { 0x4, RST_TYPE_FLUSH, 0, BIT(4) },
[RST_CPU1_FLUSH] = { 0xc, RST_TYPE_FLUSH, 0, BIT(4) },
[RST_AI] = { 0x14, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_VPU] = { 0x1c, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_HISYS] = { 0x2c, RST_TYPE_HW_DONE, BIT(4), BIT(0) },
[RST_HISYS_AHB] = { 0x2c, RST_TYPE_HW_DONE, BIT(5), BIT(1) },
[RST_SDIO0] = { 0x34, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_SDIO1] = { 0x34, RST_TYPE_HW_DONE, BIT(29), BIT(1) },
[RST_SDIO_AXI] = { 0x34, RST_TYPE_HW_DONE, BIT(30), BIT(2) },
[RST_USB0] = { 0x3c, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_USB1] = { 0x3c, RST_TYPE_HW_DONE, BIT(29), BIT(1) },
[RST_USB0_AHB] = { 0x3c, RST_TYPE_HW_DONE, BIT(30), BIT(0) },
[RST_USB1_AHB] = { 0x3c, RST_TYPE_HW_DONE, BIT(31), BIT(1) },
[RST_SPI0] = { 0x44, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_SPI1] = { 0x44, RST_TYPE_HW_DONE, BIT(29), BIT(1) },
[RST_SPI2] = { 0x44, RST_TYPE_HW_DONE, BIT(30), BIT(2) },
[RST_SEC] = { 0x4c, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_PDMA] = { 0x54, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_SDMA] = { 0x54, RST_TYPE_HW_DONE, BIT(29), BIT(1) },
[RST_DECOMPRESS] = { 0x5c, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_SRAM] = { 0x64, RST_TYPE_HW_DONE, BIT(28), BIT(0) },
[RST_SHRM_AXIM] = { 0x64, RST_TYPE_HW_DONE, BIT(30), BIT(2) },
[RST_SHRM_AXIS] = { 0x64, RST_TYPE_HW_DONE, BIT(31), BIT(3) },
[RST_NONAI2D] = { 0x6c, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_MCTL] = { 0x74, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_ISP] = { 0x80, RST_TYPE_HW_DONE, BIT(29), BIT(6) },
[RST_ISP_DW] = { 0x80, RST_TYPE_HW_DONE, BIT(28), BIT(5) },
[RST_DPU] = { 0x88, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_DISP] = { 0x90, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_GPU] = { 0x98, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_AUDIO] = { 0xa4, RST_TYPE_HW_DONE, BIT(31), BIT(0) },
[RST_TIMER0] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(0) },
[RST_TIMER1] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(1) },
[RST_TIMER2] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(2) },
[RST_TIMER3] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(3) },
[RST_TIMER4] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(4) },
[RST_TIMER5] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(5) },
[RST_TIMER_APB] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(6) },
[RST_HDI] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(7) },
[RST_WDT0] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(12) },
[RST_WDT1] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(13) },
[RST_WDT0_APB] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(14) },
[RST_WDT1_APB] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(15) },
[RST_TS_APB] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(16) },
[RST_MAILBOX] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(17) },
[RST_STC] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(18) },
[RST_PMU] = { 0x20, RST_TYPE_SW_DONE, 0, BIT(19) },
[RST_LOSYS_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(0) },
[RST_UART0] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(1) },
[RST_UART1] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(2) },
[RST_UART2] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(3) },
[RST_UART3] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(4) },
[RST_UART4] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(5) },
[RST_I2C0] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(6) },
[RST_I2C1] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(7) },
[RST_I2C2] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(8) },
[RST_I2C3] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(9) },
[RST_I2C4] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(10) },
[RST_JAMLINK0_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(11) },
[RST_JAMLINK1_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(12) },
[RST_JAMLINK2_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(13) },
[RST_JAMLINK3_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(14) },
[RST_CODEC_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(17) },
[RST_GPIO_DB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(18) },
[RST_GPIO_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(19) },
[RST_ADC] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(20) },
[RST_ADC_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(21) },
[RST_PWM_APB] = { 0x24, RST_TYPE_SW_DONE, 0, BIT(22) },
[RST_SHRM_APB] = { 0x64, RST_TYPE_SW_DONE, 0, BIT(1) },
[RST_CSI0] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(0) },
[RST_CSI1] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(1) },
[RST_CSI2] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(2) },
[RST_CSI_DPHY] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(3) },
[RST_ISP_AHB] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(4) },
[RST_M0] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(7) },
[RST_M1] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(8) },
[RST_M2] = { 0x80, RST_TYPE_SW_DONE, 0, BIT(9) },
[RST_SPI2AXI] = { 0xa8, RST_TYPE_SW_DONE, 0, BIT(0) }
};
static inline struct k230_rst *to_k230_rst(struct reset_controller_dev *rcdev)
{
return container_of(rcdev, struct k230_rst, rcdev);
}
static void k230_rst_clear_done(struct k230_rst *rstc, unsigned long id,
bool write_en)
{
const struct k230_rst_map *rmap = &k230_resets[id];
u32 reg;
guard(spinlock_irqsave)(&rstc->lock);
reg = readl(rstc->base + rmap->offset);
reg |= rmap->done; /* write 1 to clear */
if (write_en)
reg |= rmap->done << 16;
writel(reg, rstc->base + rmap->offset);
}
static int k230_rst_wait_and_clear_done(struct k230_rst *rstc, unsigned long id,
bool write_en)
{
const struct k230_rst_map *rmap = &k230_resets[id];
u32 reg;
int ret;
ret = readl_poll_timeout(rstc->base + rmap->offset, reg,
reg & rmap->done, 10, 1000);
if (ret) {
dev_err(rstc->rcdev.dev, "Wait for reset done timeout\n");
return ret;
}
k230_rst_clear_done(rstc, id, write_en);
return 0;
}
static void k230_rst_update(struct k230_rst *rstc, unsigned long id,
bool assert, bool write_en, bool active_low)
{
const struct k230_rst_map *rmap = &k230_resets[id];
u32 reg;
guard(spinlock_irqsave)(&rstc->lock);
reg = readl(rstc->base + rmap->offset);
if (assert ^ active_low)
reg |= rmap->reset;
else
reg &= ~rmap->reset;
if (write_en)
reg |= rmap->reset << 16;
writel(reg, rstc->base + rmap->offset);
}
static int k230_rst_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
struct k230_rst *rstc = to_k230_rst(rcdev);
switch (k230_resets[id].type) {
case RST_TYPE_CPU1:
k230_rst_update(rstc, id, true, true, false);
break;
case RST_TYPE_SW_DONE:
k230_rst_update(rstc, id, true, false,
id == RST_SPI2AXI ? false : true);
break;
case RST_TYPE_CPU0:
case RST_TYPE_FLUSH:
case RST_TYPE_HW_DONE:
return -EOPNOTSUPP;
}
/*
* The time period when reset is applied but the clock is stopped for
* RST_TYPE_CPU1 and RST_TYPE_SW_DONE can be set up to 3.75us. Delay
* 10us to ensure proper reset timing.
*/
udelay(10);
return 0;
}
static int k230_rst_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct k230_rst *rstc = to_k230_rst(rcdev);
int ret = 0;
switch (k230_resets[id].type) {
case RST_TYPE_CPU1:
k230_rst_update(rstc, id, false, true, false);
ret = k230_rst_wait_and_clear_done(rstc, id, true);
break;
case RST_TYPE_SW_DONE:
k230_rst_update(rstc, id, false, false,
id == RST_SPI2AXI ? false : true);
break;
case RST_TYPE_CPU0:
case RST_TYPE_FLUSH:
case RST_TYPE_HW_DONE:
return -EOPNOTSUPP;
}
/*
* The time period when reset is removed but the clock is stopped for
* RST_TYPE_CPU1 and RST_TYPE_SW_DONE can be set up to 3.75us. Delay
* 10us to ensure proper reset timing.
*/
udelay(10);
return ret;
}
static int k230_rst_reset(struct reset_controller_dev *rcdev, unsigned long id)
{
struct k230_rst *rstc = to_k230_rst(rcdev);
const struct k230_rst_map *rmap = &k230_resets[id];
u32 reg;
int ret = 0;
switch (rmap->type) {
case RST_TYPE_CPU0:
k230_rst_clear_done(rstc, id, true);
k230_rst_update(rstc, id, true, true, false);
ret = k230_rst_wait_and_clear_done(rstc, id, true);
/*
* The time period when reset is applied and removed but the
* clock is stopped for RST_TYPE_CPU0 can be set up to 7.5us.
* Delay 10us to ensure proper reset timing.
*/
udelay(10);
break;
case RST_TYPE_FLUSH:
k230_rst_update(rstc, id, true, true, false);
/* Wait flush request bit auto cleared by hardware */
ret = readl_poll_timeout(rstc->base + rmap->offset, reg,
!(reg & rmap->reset), 10, 1000);
if (ret)
dev_err(rcdev->dev, "Wait for flush done timeout\n");
break;
case RST_TYPE_HW_DONE:
k230_rst_clear_done(rstc, id, false);
k230_rst_update(rstc, id, true, false, false);
ret = k230_rst_wait_and_clear_done(rstc, id, false);
/*
* The time period when reset is applied and removed but the
* clock is stopped for RST_TYPE_HW_DONE can be set up to
* 127.5us. Delay 200us to ensure proper reset timing.
*/
fsleep(200);
break;
case RST_TYPE_CPU1:
case RST_TYPE_SW_DONE:
k230_rst_assert(rcdev, id);
ret = k230_rst_deassert(rcdev, id);
break;
}
return ret;
}
static const struct reset_control_ops k230_rst_ops = {
.reset = k230_rst_reset,
.assert = k230_rst_assert,
.deassert = k230_rst_deassert,
};
static int k230_rst_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct k230_rst *rstc;
rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL);
if (!rstc)
return -ENOMEM;
rstc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rstc->base))
return PTR_ERR(rstc->base);
spin_lock_init(&rstc->lock);
rstc->rcdev.dev = dev;
rstc->rcdev.owner = THIS_MODULE;
rstc->rcdev.ops = &k230_rst_ops;
rstc->rcdev.nr_resets = ARRAY_SIZE(k230_resets);
rstc->rcdev.of_node = dev->of_node;
return devm_reset_controller_register(dev, &rstc->rcdev);
}
static const struct of_device_id k230_rst_match[] = {
{ .compatible = "canaan,k230-rst", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, k230_rst_match);
static struct platform_driver k230_rst_driver = {
.probe = k230_rst_probe,
.driver = {
.name = "k230-rst",
.of_match_table = k230_rst_match,
}
};
module_platform_driver(k230_rst_driver);
MODULE_AUTHOR("Junhui Liu <junhui.liu@pigmoral.tech>");
MODULE_DESCRIPTION("Canaan K230 reset driver");
MODULE_LICENSE("GPL");

View File

@ -155,62 +155,16 @@ static int mpfs_reset_probe(struct auxiliary_device *adev,
return devm_reset_controller_register(dev, rcdev);
}
static void mpfs_reset_unregister_adev(void *_adev)
{
struct auxiliary_device *adev = _adev;
auxiliary_device_delete(adev);
auxiliary_device_uninit(adev);
}
static void mpfs_reset_adev_release(struct device *dev)
{
struct auxiliary_device *adev = to_auxiliary_dev(dev);
kfree(adev);
}
static struct auxiliary_device *mpfs_reset_adev_alloc(struct device *clk_dev)
{
struct auxiliary_device *adev;
int ret;
adev = kzalloc(sizeof(*adev), GFP_KERNEL);
if (!adev)
return ERR_PTR(-ENOMEM);
adev->name = "reset-mpfs";
adev->dev.parent = clk_dev;
adev->dev.release = mpfs_reset_adev_release;
adev->id = 666u;
ret = auxiliary_device_init(adev);
if (ret) {
kfree(adev);
return ERR_PTR(ret);
}
return adev;
}
int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base)
{
struct auxiliary_device *adev;
int ret;
adev = mpfs_reset_adev_alloc(clk_dev);
if (IS_ERR(adev))
return PTR_ERR(adev);
adev = devm_auxiliary_device_create(clk_dev, "reset-mpfs",
(__force void *)base);
if (!adev)
return -ENODEV;
ret = auxiliary_device_add(adev);
if (ret) {
auxiliary_device_uninit(adev);
return ret;
}
adev->dev.platform_data = (__force void *)base;
return devm_add_action_or_reset(clk_dev, mpfs_reset_unregister_adev, adev);
return 0;
}
EXPORT_SYMBOL_NS_GPL(mpfs_reset_controller_register, "MCHP_CLK_MPFS");

View File

@ -151,6 +151,8 @@ static const struct of_device_id reset_simple_dt_ids[] = {
{ .compatible = "snps,dw-high-reset" },
{ .compatible = "snps,dw-low-reset",
.data = &reset_simple_active_low },
{ .compatible = "sophgo,cv1800b-reset",
.data = &reset_simple_active_low },
{ .compatible = "sophgo,sg2042-reset",
.data = &reset_simple_active_low },
{ /* sentinel */ },

View File

@ -0,0 +1,90 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (C) 2023-2024 Canaan Bright Sight Co., Ltd
* Copyright (C) 2024-2025 Junhui Liu <junhui.liu@pigmoral.tech>
*/
#ifndef _DT_BINDINGS_CANAAN_K230_RST_H_
#define _DT_BINDINGS_CANAAN_K230_RST_H_
#define RST_CPU0 0
#define RST_CPU1 1
#define RST_CPU0_FLUSH 2
#define RST_CPU1_FLUSH 3
#define RST_AI 4
#define RST_VPU 5
#define RST_HISYS 6
#define RST_HISYS_AHB 7
#define RST_SDIO0 8
#define RST_SDIO1 9
#define RST_SDIO_AXI 10
#define RST_USB0 11
#define RST_USB1 12
#define RST_USB0_AHB 13
#define RST_USB1_AHB 14
#define RST_SPI0 15
#define RST_SPI1 16
#define RST_SPI2 17
#define RST_SEC 18
#define RST_PDMA 19
#define RST_SDMA 20
#define RST_DECOMPRESS 21
#define RST_SRAM 22
#define RST_SHRM_AXIM 23
#define RST_SHRM_AXIS 24
#define RST_NONAI2D 25
#define RST_MCTL 26
#define RST_ISP 27
#define RST_ISP_DW 28
#define RST_DPU 29
#define RST_DISP 30
#define RST_GPU 31
#define RST_AUDIO 32
#define RST_TIMER0 33
#define RST_TIMER1 34
#define RST_TIMER2 35
#define RST_TIMER3 36
#define RST_TIMER4 37
#define RST_TIMER5 38
#define RST_TIMER_APB 39
#define RST_HDI 40
#define RST_WDT0 41
#define RST_WDT1 42
#define RST_WDT0_APB 43
#define RST_WDT1_APB 44
#define RST_TS_APB 45
#define RST_MAILBOX 46
#define RST_STC 47
#define RST_PMU 48
#define RST_LOSYS_APB 49
#define RST_UART0 50
#define RST_UART1 51
#define RST_UART2 52
#define RST_UART3 53
#define RST_UART4 54
#define RST_I2C0 55
#define RST_I2C1 56
#define RST_I2C2 57
#define RST_I2C3 58
#define RST_I2C4 59
#define RST_JAMLINK0_APB 60
#define RST_JAMLINK1_APB 61
#define RST_JAMLINK2_APB 62
#define RST_JAMLINK3_APB 63
#define RST_CODEC_APB 64
#define RST_GPIO_DB 65
#define RST_GPIO_APB 66
#define RST_ADC 67
#define RST_ADC_APB 68
#define RST_PWM_APB 69
#define RST_SHRM_APB 70
#define RST_CSI0 71
#define RST_CSI1 72
#define RST_CSI2 73
#define RST_CSI_DPHY 74
#define RST_ISP_AHB 75
#define RST_M0 76
#define RST_M1 77
#define RST_M2 78
#define RST_SPI2AXI 79
#endif