From 7768cf83e001b2230291884095aed873bcc5a4d9 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sat, 7 Oct 2023 15:53:04 +0800 Subject: [PATCH 01/24] riscv: Add SOPHGO SOC family Kconfig support ANBZ: #20835 commit d0366abc9de5ba41225a71d37036206149319223 upstream. The first SoC in the SOPHGO series is SG2042, which contains 64 RISC-V cores. Reviewed-by: Guo Ren Reviewed-by: Conor Dooley Acked-by: Chao Wei Signed-off-by: Chen Wang Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/15d8e87c4595c30b3b55522de9894b352c2b58e8.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/Kconfig.socs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 30fd6a512828..e08e91c49abe 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -22,6 +22,11 @@ config SOC_SIFIVE help This enables support for SiFive SoC platform hardware. +config ARCH_SOPHGO + bool "Sophgo SoCs" + help + This enables support for Sophgo SoC platform hardware. + config ARCH_STARFIVE def_bool SOC_STARFIVE -- Gitee From 1cff03852d24b444ba53a132a8d36ab104a02911 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sat, 7 Oct 2023 15:53:57 +0800 Subject: [PATCH 02/24] dt-bindings: vendor-prefixes: add milkv/sophgo ANBZ: #20835 commit 07f9b764062904f0c0fd6e54e58535f34ac3ac6f upstream. Add new vendor strings to dt bindings. These new vendor strings are used by - SOPHGO's SG2042 SoC [1] - Milk-V Pioneer board [2], which uses SG2042 chip. Link: https://en.sophgo.com/product/introduce/sg2042.html [1] Link: https://milkv.io/pioneer [2] Reviewed-by: Guo Ren Reviewed-by: Conor Dooley Acked-by: Chao Wei Signed-off-by: Chen Wang Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/0aa38ae82ccefe7f3e83a73df93cee75f309efc0.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 7ab77b7e52be..953a8d3ceefe 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -865,6 +865,8 @@ patternProperties: description: MikroElektronika d.o.o. "^mikrotik,.*": description: MikroTik + "^milkv,.*": + description: MilkV Technology Co., Ltd "^miniand,.*": description: Miniand Tech "^minix,.*": @@ -1279,6 +1281,8 @@ patternProperties: description: Solomon Systech Limited "^sony,.*": description: Sony Corporation + "^sophgo,.*": + description: Sophgo Technology Inc. "^sourceparts,.*": description: Source Parts Inc. "^spansion,.*": -- Gitee From 2dbdefc862886c0ad1d4f665299f9394277874e6 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sat, 7 Oct 2023 15:54:59 +0800 Subject: [PATCH 03/24] dt-bindings: riscv: add sophgo sg2042 bindings ANBZ: #20835 commit 1589534b1951c1e38694355324b9364098d79146 upstream. Add DT binding documentation for the SOPHGO's SG2042 Soc [1] and the Milk-V Pioneer board [2]. Link: https://en.sophgo.com/product/introduce/sg2042.html [1] Link: https://milkv.io/pioneer [2] Acked-by: Chao Wei Reviewed-by: Guo Ren Reviewed-by: Krzysztof Kozlowski Signed-off-by: Chen Wang Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/230fa937009078bfda56a2f84392d20b848d9944.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../devicetree/bindings/riscv/sophgo.yaml | 28 +++++++++++++++++++ MAINTAINERS | 6 ++++ 2 files changed, 34 insertions(+) create mode 100644 Documentation/devicetree/bindings/riscv/sophgo.yaml diff --git a/Documentation/devicetree/bindings/riscv/sophgo.yaml b/Documentation/devicetree/bindings/riscv/sophgo.yaml new file mode 100644 index 000000000000..8adb5f39ca53 --- /dev/null +++ b/Documentation/devicetree/bindings/riscv/sophgo.yaml @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/riscv/sophgo.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo SoC-based boards + +maintainers: + - Chao Wei + - Chen Wang + +description: + Sophgo SoC-based boards + +properties: + $nodename: + const: '/' + compatible: + oneOf: + - items: + - enum: + - milkv,pioneer + - const: sophgo,sg2042 + +additionalProperties: true + +... diff --git a/MAINTAINERS b/MAINTAINERS index 57cd0d32be24..43cda46224d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20109,6 +20109,12 @@ F: drivers/char/sonypi.c F: drivers/platform/x86/sony-laptop.c F: include/linux/sony-laptop.h +SOPHGO DEVICETREES +M: Chao Wei +M: Chen Wang +S: Maintained +F: Documentation/devicetree/bindings/riscv/sophgo.yaml + SOUND M: Jaroslav Kysela M: Takashi Iwai -- Gitee From 797e7c3b81632634b965ae47da8d3a8866457f23 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sat, 7 Oct 2023 15:55:27 +0800 Subject: [PATCH 04/24] dt-bindings: riscv: Add T-HEAD C920 compatibles ANBZ: #20835 commit b965d9a965943e5c07bdda0734aaeecca9ab86b3 upstream. The C920 is RISC-V CPU cores from T-HEAD Semiconductor. Notably, the C920 core is used in the SOPHGO's SG2042 SoC. Acked-by: Chao Wei Reviewed-by: Guo Ren Reviewed-by: Conor Dooley Signed-off-by: Chen Wang Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/0783d4e9c9fcea8a84a8a7245f87168d4b698149.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- Documentation/devicetree/bindings/riscv/cpus.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml index 97e8441eda1c..f392e367d673 100644 --- a/Documentation/devicetree/bindings/riscv/cpus.yaml +++ b/Documentation/devicetree/bindings/riscv/cpus.yaml @@ -47,6 +47,7 @@ properties: - sifive,u74-mc - thead,c906 - thead,c910 + - thead,c920 - const: riscv - items: - enum: -- Gitee From 97c6e05222c695d3179df0e5b80890ee74d637aa Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sat, 7 Oct 2023 15:55:46 +0800 Subject: [PATCH 05/24] dt-bindings: interrupt-controller: Add Sophgo SG2042 PLIC ANBZ: #20835 commit d975794dddd2ec44f142302c7fd3b86eebec0bee upstream. Add compatible string for SOPHGO SG2042 plic. Acked-by: Chao Wei Reviewed-by: Guo Ren Acked-by: Conor Dooley Signed-off-by: Chen Wang Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/c639a1cd1e09c908c44f14d2156b643e577f0831.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../bindings/interrupt-controller/sifive,plic-1.0.0.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml index dc1f28e55266..16f9c4760c0f 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml @@ -65,6 +65,7 @@ properties: - items: - enum: - allwinner,sun20i-d1-plic + - sophgo,sg2042-plic - thead,th1520-plic - const: thead,c900-plic - items: -- Gitee From 815b50b0a4effaf0601e8e467ee2b41036e7f0de Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Sat, 7 Oct 2023 15:56:03 +0800 Subject: [PATCH 06/24] dt-bindings: timer: Add Sophgo sg2042 CLINT timer ANBZ: #20835 commit 4734449f73115c33733b136e225657107c03faf5 upstream. The clint of Sophgo's sg2042 is based off IP designed by T-HEAD, but Sophgo changes this IP layout to fit its cpu design and is incompatible with the standard sifive clint. The timer and ipi device are on the different address, and can not be handled by the sifive,clint dt-bindings. If we use the same compatible string for mswi and timer of the sg2042 clint like sifive,clint, the DT may be like this: mswi: interrupt-controller@94000000 { compatible = "sophgo,sg2042-clint", "thead,c900-clint"; interrupts-extended = <&cpu1intc 3>; reg = <0x94000000 0x00010000>; }; timer: timer@ac000000 { compatible = "sophgo,sg2042-clint", "thead,c900-clint"; interrupts-extended = <&cpu1intc 7>; reg = <0xac000000 0x00010000>; }; Since the address of mswi and timer are different, it is hard to merge them directly. So we need two DT nodes to handle both devices. If we use this DT for SBI, it will parse the mswi device in the timer initialization as the compatible string is the same, so will mswi. As they are different devices, this incorrect initialization will cause the system unusable. There is a more robust ACLINT spec. can handle this situation, but the spec. seems to be abandoned and will not be frozen in the predictable future. So it is not the time to add ACLINT spec in the kernel bindings. Instead, using vendor bindings is more acceptable. Add new vendor specific compatible strings to identify timer of sg2042 clint. Signed-off-by: Inochi Amaoto Signed-off-by: Chen Wang Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/c48106ebe00c0418ffb9fd5f3a827055cf97d1db.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../timer/thead,c900-aclint-mtimer.yaml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml diff --git a/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml b/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml new file mode 100644 index 000000000000..fbd235650e52 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/timer/thead,c900-aclint-mtimer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo CLINT Timer + +maintainers: + - Inochi Amaoto + +properties: + compatible: + items: + - enum: + - sophgo,sg2042-aclint-mtimer + - const: thead,c900-aclint-mtimer + + reg: + maxItems: 1 + + interrupts-extended: + minItems: 1 + maxItems: 4095 + +additionalProperties: false + +required: + - compatible + - reg + - interrupts-extended + +examples: + - | + timer@ac000000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + interrupts-extended = <&cpu1intc 7>, + <&cpu2intc 7>, + <&cpu3intc 7>, + <&cpu4intc 7>; + reg = <0xac000000 0x00010000>; + }; +... -- Gitee From 6aa45b1d0fe8b59551b561f79590f58620636be8 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Sat, 7 Oct 2023 15:56:22 +0800 Subject: [PATCH 07/24] dt-bindings: interrupt-controller: Add Sophgo sg2042 CLINT mswi ANBZ: #20835 commit 942e02e150721413b43068a8073819ad2b7d6314 upstream. The clint of Sophgo's sg2042 is based off IP designed by T-HEAD, and implements the not yet frozen ACLINT spec. This spec seems to be abandoned, and will not be frozen in the predictable future. Frozen specs required by the RISC-V maintainers before merging content relating to those extensions, therefore a generic compatible is not appropriate. Instead, add new vendor specific compatible strings to identify mswi of sg2042 clint. Signed-off-by: Inochi Amaoto Signed-off-by: Chen Wang [conor: re-wrote commit message to drop irrelevant sifive,clint discussion] Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/4db57bcb69b9182c171598eb8d65151a347cfe8f.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../thead,c900-aclint-mswi.yaml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml diff --git a/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml new file mode 100644 index 000000000000..065f2544b63b --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/thead,c900-aclint-mswi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo sg2042 CLINT Machine-level Software Interrupt Device + +maintainers: + - Inochi Amaoto + +properties: + compatible: + items: + - enum: + - sophgo,sg2042-aclint-mswi + - const: thead,c900-aclint-mswi + + reg: + maxItems: 1 + + interrupts-extended: + minItems: 1 + maxItems: 4095 + +additionalProperties: false + +required: + - compatible + - reg + - interrupts-extended + +examples: + - | + interrupt-controller@94000000 { + compatible = "sophgo,sg2042-aclint-mswi", "thead,c900-aclint-mswi"; + interrupts-extended = <&cpu1intc 3>, + <&cpu2intc 3>, + <&cpu3intc 3>, + <&cpu4intc 3>; + reg = <0x94000000 0x00010000>; + }; +... -- Gitee From 128a88910daff72b80451084fb6423b48b5974ac Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sat, 7 Oct 2023 15:57:10 +0800 Subject: [PATCH 08/24] riscv: dts: add initial Sophgo SG2042 SoC device tree ANBZ: #20835 commit 967a94a92aaaaf2d85179e1b7c7b1f0fd6bff7ac upstream. Milk-V Pioneer motherboard is powered by SG2042. SG2042 is server grade chip with high performance, low power consumption and high data throughput. Key features: - 64 RISC-V cpu cores - 4 cores per cluster, 16 clusters on chip - More info is available at [1]. Currently only support booting into console with only uart, other features will be added soon later. Reviewed-by: Guo Ren Acked-by: Chao Wei Co-developed-by: Xiaoguang Xing Signed-off-by: Xiaoguang Xing Co-developed-by: Inochi Amaoto Signed-off-by: Inochi Amaoto Signed-off-by: Chen Wang Link: https://en.sophgo.com/product/introduce/sg2042.html [1] Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/8a5f5a98a289fb94e23347ac5b19f8aa70093855.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- MAINTAINERS | 1 + arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi | 2000 +++++++++++++++++++ arch/riscv/boot/dts/sophgo/sg2042.dtsi | 325 +++ 3 files changed, 2326 insertions(+) create mode 100644 arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi create mode 100644 arch/riscv/boot/dts/sophgo/sg2042.dtsi diff --git a/MAINTAINERS b/MAINTAINERS index 43cda46224d3..4a147f430338 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20113,6 +20113,7 @@ SOPHGO DEVICETREES M: Chao Wei M: Chen Wang S: Maintained +F: arch/riscv/boot/dts/sophgo/ F: Documentation/devicetree/bindings/riscv/sophgo.yaml SOUND diff --git a/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi b/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi new file mode 100644 index 000000000000..b136b6c4128c --- /dev/null +++ b/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi @@ -0,0 +1,2000 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved. + */ + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <50000000>; + + cpu-map { + socket0 { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + core1 { + cpu = <&cpu1>; + }; + core2 { + cpu = <&cpu2>; + }; + core3 { + cpu = <&cpu3>; + }; + }; + + cluster1 { + core0 { + cpu = <&cpu4>; + }; + core1 { + cpu = <&cpu5>; + }; + core2 { + cpu = <&cpu6>; + }; + core3 { + cpu = <&cpu7>; + }; + }; + + cluster2 { + core0 { + cpu = <&cpu16>; + }; + core1 { + cpu = <&cpu17>; + }; + core2 { + cpu = <&cpu18>; + }; + core3 { + cpu = <&cpu19>; + }; + }; + + cluster3 { + core0 { + cpu = <&cpu20>; + }; + core1 { + cpu = <&cpu21>; + }; + core2 { + cpu = <&cpu22>; + }; + core3 { + cpu = <&cpu23>; + }; + }; + + cluster4 { + core0 { + cpu = <&cpu8>; + }; + core1 { + cpu = <&cpu9>; + }; + core2 { + cpu = <&cpu10>; + }; + core3 { + cpu = <&cpu11>; + }; + }; + + cluster5 { + core0 { + cpu = <&cpu12>; + }; + core1 { + cpu = <&cpu13>; + }; + core2 { + cpu = <&cpu14>; + }; + core3 { + cpu = <&cpu15>; + }; + }; + + cluster6 { + core0 { + cpu = <&cpu24>; + }; + core1 { + cpu = <&cpu25>; + }; + core2 { + cpu = <&cpu26>; + }; + core3 { + cpu = <&cpu27>; + }; + }; + + cluster7 { + core0 { + cpu = <&cpu28>; + }; + core1 { + cpu = <&cpu29>; + }; + core2 { + cpu = <&cpu30>; + }; + core3 { + cpu = <&cpu31>; + }; + }; + + cluster8 { + core0 { + cpu = <&cpu32>; + }; + core1 { + cpu = <&cpu33>; + }; + core2 { + cpu = <&cpu34>; + }; + core3 { + cpu = <&cpu35>; + }; + }; + + cluster9 { + core0 { + cpu = <&cpu36>; + }; + core1 { + cpu = <&cpu37>; + }; + core2 { + cpu = <&cpu38>; + }; + core3 { + cpu = <&cpu39>; + }; + }; + + cluster10 { + core0 { + cpu = <&cpu48>; + }; + core1 { + cpu = <&cpu49>; + }; + core2 { + cpu = <&cpu50>; + }; + core3 { + cpu = <&cpu51>; + }; + }; + + cluster11 { + core0 { + cpu = <&cpu52>; + }; + core1 { + cpu = <&cpu53>; + }; + core2 { + cpu = <&cpu54>; + }; + core3 { + cpu = <&cpu55>; + }; + }; + + cluster12 { + core0 { + cpu = <&cpu40>; + }; + core1 { + cpu = <&cpu41>; + }; + core2 { + cpu = <&cpu42>; + }; + core3 { + cpu = <&cpu43>; + }; + }; + + cluster13 { + core0 { + cpu = <&cpu44>; + }; + core1 { + cpu = <&cpu45>; + }; + core2 { + cpu = <&cpu46>; + }; + core3 { + cpu = <&cpu47>; + }; + }; + + cluster14 { + core0 { + cpu = <&cpu56>; + }; + core1 { + cpu = <&cpu57>; + }; + core2 { + cpu = <&cpu58>; + }; + core3 { + cpu = <&cpu59>; + }; + }; + + cluster15 { + core0 { + cpu = <&cpu60>; + }; + core1 { + cpu = <&cpu61>; + }; + core2 { + cpu = <&cpu62>; + }; + core3 { + cpu = <&cpu63>; + }; + }; + }; + }; + + cpu0: cpu@0 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <0>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache0>; + mmu-type = "riscv,sv39"; + + cpu0_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu1: cpu@1 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <1>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache0>; + mmu-type = "riscv,sv39"; + + cpu1_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu2: cpu@2 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <2>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache0>; + mmu-type = "riscv,sv39"; + + cpu2_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu3: cpu@3 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <3>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache0>; + mmu-type = "riscv,sv39"; + + cpu3_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu4: cpu@4 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <4>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache1>; + mmu-type = "riscv,sv39"; + + cpu4_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu5: cpu@5 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <5>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache1>; + mmu-type = "riscv,sv39"; + + cpu5_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu6: cpu@6 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <6>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache1>; + mmu-type = "riscv,sv39"; + + cpu6_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu7: cpu@7 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <7>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache1>; + mmu-type = "riscv,sv39"; + + cpu7_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu8: cpu@8 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <8>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache4>; + mmu-type = "riscv,sv39"; + + cpu8_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu9: cpu@9 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <9>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache4>; + mmu-type = "riscv,sv39"; + + cpu9_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu10: cpu@10 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <10>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache4>; + mmu-type = "riscv,sv39"; + + cpu10_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu11: cpu@11 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <11>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache4>; + mmu-type = "riscv,sv39"; + + cpu11_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu12: cpu@12 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <12>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache5>; + mmu-type = "riscv,sv39"; + + cpu12_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu13: cpu@13 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <13>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache5>; + mmu-type = "riscv,sv39"; + + cpu13_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu14: cpu@14 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <14>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache5>; + mmu-type = "riscv,sv39"; + + cpu14_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu15: cpu@15 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <15>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache5>; + mmu-type = "riscv,sv39"; + + cpu15_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu16: cpu@16 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <16>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache2>; + mmu-type = "riscv,sv39"; + + cpu16_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu17: cpu@17 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <17>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache2>; + mmu-type = "riscv,sv39"; + + cpu17_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu18: cpu@18 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <18>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache2>; + mmu-type = "riscv,sv39"; + + cpu18_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu19: cpu@19 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <19>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache2>; + mmu-type = "riscv,sv39"; + + cpu19_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu20: cpu@20 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <20>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache3>; + mmu-type = "riscv,sv39"; + + cpu20_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu21: cpu@21 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <21>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache3>; + mmu-type = "riscv,sv39"; + + cpu21_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu22: cpu@22 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <22>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache3>; + mmu-type = "riscv,sv39"; + + cpu22_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu23: cpu@23 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <23>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache3>; + mmu-type = "riscv,sv39"; + + cpu23_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu24: cpu@24 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <24>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache6>; + mmu-type = "riscv,sv39"; + + cpu24_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu25: cpu@25 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <25>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache6>; + mmu-type = "riscv,sv39"; + + cpu25_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu26: cpu@26 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <26>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache6>; + mmu-type = "riscv,sv39"; + + cpu26_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu27: cpu@27 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <27>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache6>; + mmu-type = "riscv,sv39"; + + cpu27_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu28: cpu@28 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <28>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache7>; + mmu-type = "riscv,sv39"; + + cpu28_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu29: cpu@29 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <29>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache7>; + mmu-type = "riscv,sv39"; + + cpu29_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu30: cpu@30 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <30>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache7>; + mmu-type = "riscv,sv39"; + + cpu30_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu31: cpu@31 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <31>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache7>; + mmu-type = "riscv,sv39"; + + cpu31_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu32: cpu@32 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <32>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache8>; + mmu-type = "riscv,sv39"; + + cpu32_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu33: cpu@33 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <33>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache8>; + mmu-type = "riscv,sv39"; + + cpu33_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu34: cpu@34 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <34>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache8>; + mmu-type = "riscv,sv39"; + + cpu34_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu35: cpu@35 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <35>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache8>; + mmu-type = "riscv,sv39"; + + cpu35_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu36: cpu@36 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <36>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache9>; + mmu-type = "riscv,sv39"; + + cpu36_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu37: cpu@37 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <37>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache9>; + mmu-type = "riscv,sv39"; + + cpu37_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu38: cpu@38 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <38>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache9>; + mmu-type = "riscv,sv39"; + + cpu38_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu39: cpu@39 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <39>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache9>; + mmu-type = "riscv,sv39"; + + cpu39_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu40: cpu@40 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <40>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache12>; + mmu-type = "riscv,sv39"; + + cpu40_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu41: cpu@41 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <41>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache12>; + mmu-type = "riscv,sv39"; + + cpu41_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu42: cpu@42 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <42>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache12>; + mmu-type = "riscv,sv39"; + + cpu42_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu43: cpu@43 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <43>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache12>; + mmu-type = "riscv,sv39"; + + cpu43_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu44: cpu@44 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <44>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache13>; + mmu-type = "riscv,sv39"; + + cpu44_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu45: cpu@45 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <45>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache13>; + mmu-type = "riscv,sv39"; + + cpu45_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu46: cpu@46 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <46>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache13>; + mmu-type = "riscv,sv39"; + + cpu46_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu47: cpu@47 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <47>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache13>; + mmu-type = "riscv,sv39"; + + cpu47_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu48: cpu@48 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <48>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache10>; + mmu-type = "riscv,sv39"; + + cpu48_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu49: cpu@49 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <49>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache10>; + mmu-type = "riscv,sv39"; + + cpu49_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu50: cpu@50 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <50>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache10>; + mmu-type = "riscv,sv39"; + + cpu50_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu51: cpu@51 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <51>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache10>; + mmu-type = "riscv,sv39"; + + cpu51_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu52: cpu@52 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <52>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache11>; + mmu-type = "riscv,sv39"; + + cpu52_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu53: cpu@53 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <53>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache11>; + mmu-type = "riscv,sv39"; + + cpu53_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu54: cpu@54 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <54>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache11>; + mmu-type = "riscv,sv39"; + + cpu54_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu55: cpu@55 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <55>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache11>; + mmu-type = "riscv,sv39"; + + cpu55_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu56: cpu@56 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <56>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache14>; + mmu-type = "riscv,sv39"; + + cpu56_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu57: cpu@57 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <57>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache14>; + mmu-type = "riscv,sv39"; + + cpu57_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu58: cpu@58 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <58>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache14>; + mmu-type = "riscv,sv39"; + + cpu58_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu59: cpu@59 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <59>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache14>; + mmu-type = "riscv,sv39"; + + cpu59_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu60: cpu@60 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <60>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache15>; + mmu-type = "riscv,sv39"; + + cpu60_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu61: cpu@61 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <61>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache15>; + mmu-type = "riscv,sv39"; + + cpu61_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu62: cpu@62 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <62>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache15>; + mmu-type = "riscv,sv39"; + + cpu62_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + cpu63: cpu@63 { + compatible = "thead,c920", "riscv"; + device_type = "cpu"; + riscv,isa = "rv64imafdc"; + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", + "zicntr", "zicsr", "zifencei", + "zihpm"; + reg = <63>; + i-cache-block-size = <64>; + i-cache-size = <65536>; + i-cache-sets = <512>; + d-cache-block-size = <64>; + d-cache-size = <65536>; + d-cache-sets = <512>; + next-level-cache = <&l2_cache15>; + mmu-type = "riscv,sv39"; + + cpu63_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + l2_cache0: cache-controller-0 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache1: cache-controller-1 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache2: cache-controller-2 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache3: cache-controller-3 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache4: cache-controller-4 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache5: cache-controller-5 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache6: cache-controller-6 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache7: cache-controller-7 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache8: cache-controller-8 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache9: cache-controller-9 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache10: cache-controller-10 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache11: cache-controller-11 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache12: cache-controller-12 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache13: cache-controller-13 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache14: cache-controller-14 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + + l2_cache15: cache-controller-15 { + compatible = "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-size = <1048576>; + cache-sets = <1024>; + cache-unified; + }; + }; +}; diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi new file mode 100644 index 000000000000..93256540d078 --- /dev/null +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved. + */ + +/dts-v1/; +#include + +#include "sg2042-cpus.dtsi" + +/ { + compatible = "sophgo,sg2042"; + #address-cells = <2>; + #size-cells = <2>; + dma-noncoherent; + + aliases { + serial0 = &uart0; + }; + + soc: soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clint_mswi: interrupt-controller@7094000000 { + compatible = "sophgo,sg2042-aclint-mswi", "thead,c900-aclint-mswi"; + reg = <0x00000070 0x94000000 0x00000000 0x00004000>; + interrupts-extended = <&cpu0_intc 3>, + <&cpu1_intc 3>, + <&cpu2_intc 3>, + <&cpu3_intc 3>, + <&cpu4_intc 3>, + <&cpu5_intc 3>, + <&cpu6_intc 3>, + <&cpu7_intc 3>, + <&cpu8_intc 3>, + <&cpu9_intc 3>, + <&cpu10_intc 3>, + <&cpu11_intc 3>, + <&cpu12_intc 3>, + <&cpu13_intc 3>, + <&cpu14_intc 3>, + <&cpu15_intc 3>, + <&cpu16_intc 3>, + <&cpu17_intc 3>, + <&cpu18_intc 3>, + <&cpu19_intc 3>, + <&cpu20_intc 3>, + <&cpu21_intc 3>, + <&cpu22_intc 3>, + <&cpu23_intc 3>, + <&cpu24_intc 3>, + <&cpu25_intc 3>, + <&cpu26_intc 3>, + <&cpu27_intc 3>, + <&cpu28_intc 3>, + <&cpu29_intc 3>, + <&cpu30_intc 3>, + <&cpu31_intc 3>, + <&cpu32_intc 3>, + <&cpu33_intc 3>, + <&cpu34_intc 3>, + <&cpu35_intc 3>, + <&cpu36_intc 3>, + <&cpu37_intc 3>, + <&cpu38_intc 3>, + <&cpu39_intc 3>, + <&cpu40_intc 3>, + <&cpu41_intc 3>, + <&cpu42_intc 3>, + <&cpu43_intc 3>, + <&cpu44_intc 3>, + <&cpu45_intc 3>, + <&cpu46_intc 3>, + <&cpu47_intc 3>, + <&cpu48_intc 3>, + <&cpu49_intc 3>, + <&cpu50_intc 3>, + <&cpu51_intc 3>, + <&cpu52_intc 3>, + <&cpu53_intc 3>, + <&cpu54_intc 3>, + <&cpu55_intc 3>, + <&cpu56_intc 3>, + <&cpu57_intc 3>, + <&cpu58_intc 3>, + <&cpu59_intc 3>, + <&cpu60_intc 3>, + <&cpu61_intc 3>, + <&cpu62_intc 3>, + <&cpu63_intc 3>; + }; + + clint_mtimer0: timer@70ac000000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac000000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu0_intc 7>, + <&cpu1_intc 7>, + <&cpu2_intc 7>, + <&cpu3_intc 7>; + }; + + clint_mtimer1: timer@70ac010000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac010000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu4_intc 7>, + <&cpu5_intc 7>, + <&cpu6_intc 7>, + <&cpu7_intc 7>; + }; + + clint_mtimer2: timer@70ac020000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac020000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu8_intc 7>, + <&cpu9_intc 7>, + <&cpu10_intc 7>, + <&cpu11_intc 7>; + }; + + clint_mtimer3: timer@70ac030000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac030000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu12_intc 7>, + <&cpu13_intc 7>, + <&cpu14_intc 7>, + <&cpu15_intc 7>; + }; + + clint_mtimer4: timer@70ac040000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac040000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu16_intc 7>, + <&cpu17_intc 7>, + <&cpu18_intc 7>, + <&cpu19_intc 7>; + }; + + clint_mtimer5: timer@70ac050000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac050000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu20_intc 7>, + <&cpu21_intc 7>, + <&cpu22_intc 7>, + <&cpu23_intc 7>; + }; + + clint_mtimer6: timer@70ac060000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac060000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu24_intc 7>, + <&cpu25_intc 7>, + <&cpu26_intc 7>, + <&cpu27_intc 7>; + }; + + clint_mtimer7: timer@70ac070000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac070000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu28_intc 7>, + <&cpu29_intc 7>, + <&cpu30_intc 7>, + <&cpu31_intc 7>; + }; + + clint_mtimer8: timer@70ac080000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac080000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu32_intc 7>, + <&cpu33_intc 7>, + <&cpu34_intc 7>, + <&cpu35_intc 7>; + }; + + clint_mtimer9: timer@70ac090000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac090000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu36_intc 7>, + <&cpu37_intc 7>, + <&cpu38_intc 7>, + <&cpu39_intc 7>; + }; + + clint_mtimer10: timer@70ac0a0000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac0a0000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu40_intc 7>, + <&cpu41_intc 7>, + <&cpu42_intc 7>, + <&cpu43_intc 7>; + }; + + clint_mtimer11: timer@70ac0b0000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac0b0000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu44_intc 7>, + <&cpu45_intc 7>, + <&cpu46_intc 7>, + <&cpu47_intc 7>; + }; + + clint_mtimer12: timer@70ac0c0000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac0c0000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu48_intc 7>, + <&cpu49_intc 7>, + <&cpu50_intc 7>, + <&cpu51_intc 7>; + }; + + clint_mtimer13: timer@70ac0d0000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac0d0000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu52_intc 7>, + <&cpu53_intc 7>, + <&cpu54_intc 7>, + <&cpu55_intc 7>; + }; + + clint_mtimer14: timer@70ac0e0000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac0e0000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu56_intc 7>, + <&cpu57_intc 7>, + <&cpu58_intc 7>, + <&cpu59_intc 7>; + }; + + clint_mtimer15: timer@70ac0f0000 { + compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; + reg = <0x00000070 0xac0f0000 0x00000000 0x00007ff8>; + interrupts-extended = <&cpu60_intc 7>, + <&cpu61_intc 7>, + <&cpu62_intc 7>, + <&cpu63_intc 7>; + }; + + intc: interrupt-controller@7090000000 { + compatible = "sophgo,sg2042-plic", "thead,c900-plic"; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x00000070 0x90000000 0x00000000 0x04000000>; + interrupt-controller; + interrupts-extended = + <&cpu0_intc 11>, <&cpu0_intc 9>, + <&cpu1_intc 11>, <&cpu1_intc 9>, + <&cpu2_intc 11>, <&cpu2_intc 9>, + <&cpu3_intc 11>, <&cpu3_intc 9>, + <&cpu4_intc 11>, <&cpu4_intc 9>, + <&cpu5_intc 11>, <&cpu5_intc 9>, + <&cpu6_intc 11>, <&cpu6_intc 9>, + <&cpu7_intc 11>, <&cpu7_intc 9>, + <&cpu8_intc 11>, <&cpu8_intc 9>, + <&cpu9_intc 11>, <&cpu9_intc 9>, + <&cpu10_intc 11>, <&cpu10_intc 9>, + <&cpu11_intc 11>, <&cpu11_intc 9>, + <&cpu12_intc 11>, <&cpu12_intc 9>, + <&cpu13_intc 11>, <&cpu13_intc 9>, + <&cpu14_intc 11>, <&cpu14_intc 9>, + <&cpu15_intc 11>, <&cpu15_intc 9>, + <&cpu16_intc 11>, <&cpu16_intc 9>, + <&cpu17_intc 11>, <&cpu17_intc 9>, + <&cpu18_intc 11>, <&cpu18_intc 9>, + <&cpu19_intc 11>, <&cpu19_intc 9>, + <&cpu20_intc 11>, <&cpu20_intc 9>, + <&cpu21_intc 11>, <&cpu21_intc 9>, + <&cpu22_intc 11>, <&cpu22_intc 9>, + <&cpu23_intc 11>, <&cpu23_intc 9>, + <&cpu24_intc 11>, <&cpu24_intc 9>, + <&cpu25_intc 11>, <&cpu25_intc 9>, + <&cpu26_intc 11>, <&cpu26_intc 9>, + <&cpu27_intc 11>, <&cpu27_intc 9>, + <&cpu28_intc 11>, <&cpu28_intc 9>, + <&cpu29_intc 11>, <&cpu29_intc 9>, + <&cpu30_intc 11>, <&cpu30_intc 9>, + <&cpu31_intc 11>, <&cpu31_intc 9>, + <&cpu32_intc 11>, <&cpu32_intc 9>, + <&cpu33_intc 11>, <&cpu33_intc 9>, + <&cpu34_intc 11>, <&cpu34_intc 9>, + <&cpu35_intc 11>, <&cpu35_intc 9>, + <&cpu36_intc 11>, <&cpu36_intc 9>, + <&cpu37_intc 11>, <&cpu37_intc 9>, + <&cpu38_intc 11>, <&cpu38_intc 9>, + <&cpu39_intc 11>, <&cpu39_intc 9>, + <&cpu40_intc 11>, <&cpu40_intc 9>, + <&cpu41_intc 11>, <&cpu41_intc 9>, + <&cpu42_intc 11>, <&cpu42_intc 9>, + <&cpu43_intc 11>, <&cpu43_intc 9>, + <&cpu44_intc 11>, <&cpu44_intc 9>, + <&cpu45_intc 11>, <&cpu45_intc 9>, + <&cpu46_intc 11>, <&cpu46_intc 9>, + <&cpu47_intc 11>, <&cpu47_intc 9>, + <&cpu48_intc 11>, <&cpu48_intc 9>, + <&cpu49_intc 11>, <&cpu49_intc 9>, + <&cpu50_intc 11>, <&cpu50_intc 9>, + <&cpu51_intc 11>, <&cpu51_intc 9>, + <&cpu52_intc 11>, <&cpu52_intc 9>, + <&cpu53_intc 11>, <&cpu53_intc 9>, + <&cpu54_intc 11>, <&cpu54_intc 9>, + <&cpu55_intc 11>, <&cpu55_intc 9>, + <&cpu56_intc 11>, <&cpu56_intc 9>, + <&cpu57_intc 11>, <&cpu57_intc 9>, + <&cpu58_intc 11>, <&cpu58_intc 9>, + <&cpu59_intc 11>, <&cpu59_intc 9>, + <&cpu60_intc 11>, <&cpu60_intc 9>, + <&cpu61_intc 11>, <&cpu61_intc 9>, + <&cpu62_intc 11>, <&cpu62_intc 9>, + <&cpu63_intc 11>, <&cpu63_intc 9>; + riscv,ndev = <224>; + }; + + uart0: serial@7040000000 { + compatible = "snps,dw-apb-uart"; + reg = <0x00000070 0x40000000 0x00000000 0x00001000>; + interrupt-parent = <&intc>; + interrupts = <112 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <500000000>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + }; +}; -- Gitee From 4ff61c2a097f2f2d4d52fdc2712a019cdfaa5995 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sat, 7 Oct 2023 15:57:31 +0800 Subject: [PATCH 09/24] riscv: dts: sophgo: add Milk-V Pioneer board device tree ANBZ: #20835 commit 9439a0e8b6bb83e46e8d30d2cf00558ffd1ee41e upstream. Milk-V Pioneer [1] is a developer motherboard based on SG2042 in a standard mATX form factor. Currently only support booting into console with only uart enabled, other features will be added soon later. Link: https://milkv.io/pioneer [1] Reviewed-by: Guo Ren Acked-by: Chao Wei Signed-off-by: Chen Wang Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/990193b3a3f3d7854d4d652a034fd33cd759d33f.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/boot/dts/Makefile | 1 + arch/riscv/boot/dts/sophgo/Makefile | 2 ++ .../boot/dts/sophgo/sg2042-milkv-pioneer.dts | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 arch/riscv/boot/dts/sophgo/Makefile create mode 100644 arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile index f60a280abb15..72030fd727af 100644 --- a/arch/riscv/boot/dts/Makefile +++ b/arch/riscv/boot/dts/Makefile @@ -4,6 +4,7 @@ subdir-y += canaan subdir-y += microchip subdir-y += renesas subdir-y += sifive +subdir-y += sophgo subdir-y += starfive subdir-y += thead diff --git a/arch/riscv/boot/dts/sophgo/Makefile b/arch/riscv/boot/dts/sophgo/Makefile new file mode 100644 index 000000000000..73af15f42ec2 --- /dev/null +++ b/arch/riscv/boot/dts/sophgo/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_SOPHGO) += sg2042-milkv-pioneer.dtb diff --git a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts new file mode 100644 index 000000000000..49b4b9c2c101 --- /dev/null +++ b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved. + */ + +#include "sg2042.dtsi" + +/ { + model = "Milk-V Pioneer"; + compatible = "milkv,pioneer", "sophgo,sg2042"; + + chosen { + stdout-path = "serial0"; + }; +}; + +&uart0 { + status = "okay"; +}; -- Gitee From 68561f9c6dd6c5288386f966c26dbfe35bb3e01d Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Sat, 7 Oct 2023 15:57:52 +0800 Subject: [PATCH 10/24] riscv: defconfig: enable SOPHGO SoC ANBZ: #20835 commit c32ab7bd6191d64998dced3ba567b8737d217861 upstream. Enable SOPHGO SoC config in defconfig to allow the default upstream kernel to boot on Milk-V Pioneer board. Acked-by: Chao Wei Acked-by: Conor Dooley Reviewed-by: Guo Ren Signed-off-by: Chen Wang [conor: fix the ordering] Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/53553d9a75740f528c4ea22860055bfb642a2cac.1696663037.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/configs/defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index ab86ec3b9eab..1edf3cd886c5 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig @@ -27,10 +27,11 @@ CONFIG_EXPERT=y CONFIG_PROFILING=y CONFIG_SOC_MICROCHIP_POLARFIRE=y CONFIG_ARCH_RENESAS=y -CONFIG_ARCH_THEAD=y CONFIG_SOC_SIFIVE=y +CONFIG_ARCH_SOPHGO=y CONFIG_SOC_STARFIVE=y CONFIG_ARCH_SUNXI=y +CONFIG_ARCH_THEAD=y CONFIG_SOC_VIRT=y CONFIG_SMP=y CONFIG_HOTPLUG_CPU=y -- Gitee From 77acc79f7e4352acf5cf731756f5f607b9c6dfb8 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Mon, 4 Dec 2023 17:51:08 +0800 Subject: [PATCH 11/24] dt-bindings: timer: thead,c900-aclint-mtimer: separate mtime and mtimecmp regs ANBZ: #20835 commit b91cf01cf3e63a627b3b65f4284dcf9a4deb80f9 upstream. The timer registers of aclint don't follow the clint layout and can be mapped on any different offset. As sg2042 uses separated timer and mswi for its clint, it should follow the aclint spec and have separated registers. The previous patch introduced a new type of T-HEAD aclint timer which has clint timer layout. Although it has the clint timer layout, it should follow the aclint spec and uses the separated mtime and mtimecmp regs. So a ABI change is needed to make the timer fit the aclint spec. To make T-HEAD aclint timer more closer to the aclint spec, use regs-names to represent the mtimecmp register, which can avoid hack for unsupport mtime register of T-HEAD aclint timer. Also, as T-HEAD aclint only supports mtimecmp, it is unnecessary to implement the whole aclint spec. To make this binding T-HEAD specific, only add reg-name for existed register. For details, see the discussion in the last link. Signed-off-by: Inochi Amaoto Fixes: 4734449f7311 ("dt-bindings: timer: Add Sophgo sg2042 CLINT timer") Link: https://lists.infradead.org/pipermail/opensbi/2023-October/005693.html Link: https://github.com/riscv/riscv-aclint/blob/main/riscv-aclint.adoc Link: https://lore.kernel.org/all/IA1PR20MB4953F9D77FFC76A9D236922DBBB6A@IA1PR20MB4953.namprd20.prod.outlook.com/ Acked-by: Conor Dooley Acked-by: Guo Ren Link: https://lore.kernel.org/r/IA1PR20MB49531ED1BCC00D6B265C2D10BB86A@IA1PR20MB4953.namprd20.prod.outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../bindings/timer/thead,c900-aclint-mtimer.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml b/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml index fbd235650e52..2e92bcdeb423 100644 --- a/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml +++ b/Documentation/devicetree/bindings/timer/thead,c900-aclint-mtimer.yaml @@ -17,7 +17,12 @@ properties: - const: thead,c900-aclint-mtimer reg: - maxItems: 1 + items: + - description: MTIMECMP Registers + + reg-names: + items: + - const: mtimecmp interrupts-extended: minItems: 1 @@ -28,6 +33,7 @@ additionalProperties: false required: - compatible - reg + - reg-names - interrupts-extended examples: @@ -39,5 +45,6 @@ examples: <&cpu3intc 7>, <&cpu4intc 7>; reg = <0xac000000 0x00010000>; + reg-names = "mtimecmp"; }; ... -- Gitee From b59703c6a0066338b33fc9a5dc38a9ef0c49996a Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Mon, 4 Dec 2023 17:51:09 +0800 Subject: [PATCH 12/24] riscv: dts: sophgo: separate sg2042 mtime and mtimecmp to fit aclint format ANBZ: #20835 commit 1f4a994be2c3d13852fd5c1054f292bd303352cc upstream. Change the timer layout in the dtb to fit the format that needed by the SBI. Signed-off-by: Inochi Amaoto Fixes: 967a94a92aaa ("riscv: dts: add initial Sophgo SG2042 SoC device tree") Reviewed-by: Chen Wang Reviewed-by: Guo Ren Link: https://lore.kernel.org/r/IA1PR20MB4953669C097D9C9E24B549FFBB86A@IA1PR20MB4953.namprd20.prod.outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/boot/dts/sophgo/sg2042.dtsi | 80 +++++++++++++++----------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index 93256540d078..ead1cc35d88b 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -93,144 +93,160 @@ clint_mswi: interrupt-controller@7094000000 { <&cpu63_intc 3>; }; - clint_mtimer0: timer@70ac000000 { + clint_mtimer0: timer@70ac004000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac000000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac004000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu0_intc 7>, <&cpu1_intc 7>, <&cpu2_intc 7>, <&cpu3_intc 7>; }; - clint_mtimer1: timer@70ac010000 { + clint_mtimer1: timer@70ac014000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac010000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac014000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu4_intc 7>, <&cpu5_intc 7>, <&cpu6_intc 7>, <&cpu7_intc 7>; }; - clint_mtimer2: timer@70ac020000 { + clint_mtimer2: timer@70ac024000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac020000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac024000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu8_intc 7>, <&cpu9_intc 7>, <&cpu10_intc 7>, <&cpu11_intc 7>; }; - clint_mtimer3: timer@70ac030000 { + clint_mtimer3: timer@70ac034000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac030000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac034000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu12_intc 7>, <&cpu13_intc 7>, <&cpu14_intc 7>, <&cpu15_intc 7>; }; - clint_mtimer4: timer@70ac040000 { + clint_mtimer4: timer@70ac044000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac040000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac044000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu16_intc 7>, <&cpu17_intc 7>, <&cpu18_intc 7>, <&cpu19_intc 7>; }; - clint_mtimer5: timer@70ac050000 { + clint_mtimer5: timer@70ac054000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac050000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac054000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu20_intc 7>, <&cpu21_intc 7>, <&cpu22_intc 7>, <&cpu23_intc 7>; }; - clint_mtimer6: timer@70ac060000 { + clint_mtimer6: timer@70ac064000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac060000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac064000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu24_intc 7>, <&cpu25_intc 7>, <&cpu26_intc 7>, <&cpu27_intc 7>; }; - clint_mtimer7: timer@70ac070000 { + clint_mtimer7: timer@70ac074000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac070000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac074000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu28_intc 7>, <&cpu29_intc 7>, <&cpu30_intc 7>, <&cpu31_intc 7>; }; - clint_mtimer8: timer@70ac080000 { + clint_mtimer8: timer@70ac084000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac080000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac084000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu32_intc 7>, <&cpu33_intc 7>, <&cpu34_intc 7>, <&cpu35_intc 7>; }; - clint_mtimer9: timer@70ac090000 { + clint_mtimer9: timer@70ac094000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac090000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac094000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu36_intc 7>, <&cpu37_intc 7>, <&cpu38_intc 7>, <&cpu39_intc 7>; }; - clint_mtimer10: timer@70ac0a0000 { + clint_mtimer10: timer@70ac0a4000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac0a0000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac0a4000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu40_intc 7>, <&cpu41_intc 7>, <&cpu42_intc 7>, <&cpu43_intc 7>; }; - clint_mtimer11: timer@70ac0b0000 { + clint_mtimer11: timer@70ac0b4000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac0b0000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac0b4000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu44_intc 7>, <&cpu45_intc 7>, <&cpu46_intc 7>, <&cpu47_intc 7>; }; - clint_mtimer12: timer@70ac0c0000 { + clint_mtimer12: timer@70ac0c4000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac0c0000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac0c4000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu48_intc 7>, <&cpu49_intc 7>, <&cpu50_intc 7>, <&cpu51_intc 7>; }; - clint_mtimer13: timer@70ac0d0000 { + clint_mtimer13: timer@70ac0d4000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac0d0000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac0d4000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu52_intc 7>, <&cpu53_intc 7>, <&cpu54_intc 7>, <&cpu55_intc 7>; }; - clint_mtimer14: timer@70ac0e0000 { + clint_mtimer14: timer@70ac0e4000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac0e0000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac0e4000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu56_intc 7>, <&cpu57_intc 7>, <&cpu58_intc 7>, <&cpu59_intc 7>; }; - clint_mtimer15: timer@70ac0f0000 { + clint_mtimer15: timer@70ac0f4000 { compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; - reg = <0x00000070 0xac0f0000 0x00000000 0x00007ff8>; + reg = <0x00000070 0xac0f4000 0x00000000 0x0000c000>; + reg-names = "mtimecmp"; interrupts-extended = <&cpu60_intc 7>, <&cpu61_intc 7>, <&cpu62_intc 7>, -- Gitee From 09d7c297894c550489b80960e383685fdecaaec6 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Tue, 30 Jan 2024 09:49:45 +0800 Subject: [PATCH 13/24] dt-bindings: reset: sophgo: support SG2042 ANBZ: #20835 commit 41197eb5f993d5572ea533c9378c49ca81e24c8e upstream. Add bindings for the reset generator on the SOPHGO SG2042 RISC-V SoC. Signed-off-by: Chen Wang Reviewed-by: Krzysztof Kozlowski Fixes: 1ce7587e507e ("riscv: dts: add reset generator for Sophgo SG2042 SoC") Reviewed-by: Inochi Amaoto Link: https://lore.kernel.org/r/35c348437b6e18972ccaf90d9c38040caccd1f11.1706577450.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../bindings/reset/sophgo,sg2042-reset.yaml | 35 ++++++++ .../dt-bindings/reset/sophgo,sg2042-reset.h | 87 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/sophgo,sg2042-reset.yaml create mode 100644 include/dt-bindings/reset/sophgo,sg2042-reset.h diff --git a/Documentation/devicetree/bindings/reset/sophgo,sg2042-reset.yaml b/Documentation/devicetree/bindings/reset/sophgo,sg2042-reset.yaml new file mode 100644 index 000000000000..76e1931f0908 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/sophgo,sg2042-reset.yaml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/reset/sophgo,sg2042-reset.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo SG2042 SoC Reset Controller + +maintainers: + - Chen Wang + +properties: + compatible: + const: sophgo,sg2042-reset + + reg: + maxItems: 1 + + "#reset-cells": + const: 1 + +required: + - compatible + - reg + - "#reset-cells" + +additionalProperties: false + +examples: + - | + rstgen: reset-controller@c00 { + compatible = "sophgo,sg2042-reset"; + reg = <0xc00 0xc>; + #reset-cells = <1>; + }; diff --git a/include/dt-bindings/reset/sophgo,sg2042-reset.h b/include/dt-bindings/reset/sophgo,sg2042-reset.h new file mode 100644 index 000000000000..9ab0980625c1 --- /dev/null +++ b/include/dt-bindings/reset/sophgo,sg2042-reset.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved. + */ + +#ifndef __DT_BINDINGS_RESET_SOPHGO_SG2042_H_ +#define __DT_BINDINGS_RESET_SOPHGO_SG2042_H_ + +#define RST_MAIN_AP 0 +#define RST_RISCV_CPU 1 +#define RST_RISCV_LOW_SPEED_LOGIC 2 +#define RST_RISCV_CMN 3 +#define RST_HSDMA 4 +#define RST_SYSDMA 5 +#define RST_EFUSE0 6 +#define RST_EFUSE1 7 +#define RST_RTC 8 +#define RST_TIMER 9 +#define RST_WDT 10 +#define RST_AHB_ROM0 11 +#define RST_AHB_ROM1 12 +#define RST_I2C0 13 +#define RST_I2C1 14 +#define RST_I2C2 15 +#define RST_I2C3 16 +#define RST_GPIO0 17 +#define RST_GPIO1 18 +#define RST_GPIO2 19 +#define RST_PWM 20 +#define RST_AXI_SRAM0 21 +#define RST_AXI_SRAM1 22 +#define RST_SF0 23 +#define RST_SF1 24 +#define RST_LPC 25 +#define RST_ETH0 26 +#define RST_EMMC 27 +#define RST_SD 28 +#define RST_UART0 29 +#define RST_UART1 30 +#define RST_UART2 31 +#define RST_UART3 32 +#define RST_SPI0 33 +#define RST_SPI1 34 +#define RST_DBG_I2C 35 +#define RST_PCIE0 36 +#define RST_PCIE1 37 +#define RST_DDR0 38 +#define RST_DDR1 39 +#define RST_DDR2 40 +#define RST_DDR3 41 +#define RST_FAU0 42 +#define RST_FAU1 43 +#define RST_FAU2 44 +#define RST_RXU0 45 +#define RST_RXU1 46 +#define RST_RXU2 47 +#define RST_RXU3 48 +#define RST_RXU4 49 +#define RST_RXU5 50 +#define RST_RXU6 51 +#define RST_RXU7 52 +#define RST_RXU8 53 +#define RST_RXU9 54 +#define RST_RXU10 55 +#define RST_RXU11 56 +#define RST_RXU12 57 +#define RST_RXU13 58 +#define RST_RXU14 59 +#define RST_RXU15 60 +#define RST_RXU16 61 +#define RST_RXU17 62 +#define RST_RXU18 63 +#define RST_RXU19 64 +#define RST_RXU20 65 +#define RST_RXU21 66 +#define RST_RXU22 67 +#define RST_RXU23 68 +#define RST_RXU24 69 +#define RST_RXU25 70 +#define RST_RXU26 71 +#define RST_RXU27 72 +#define RST_RXU28 73 +#define RST_RXU29 74 +#define RST_RXU30 75 +#define RST_RXU31 76 + +#endif /* __DT_BINDINGS_RESET_SOPHGO_SG2042_H_ */ -- Gitee From fa98f09ae3dc8a72e8b6b8a9e632d3787080223c Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Tue, 30 Jan 2024 09:50:08 +0800 Subject: [PATCH 14/24] reset: simple: add support for Sophgo SG2042 ANBZ: #20835 commit a6166a4da5e46a01e6ad5b0bb079d77ac653f594 upstream. Reuse reset-simple driver for the Sophgo SG2042 reset generator. Signed-off-by: Chen Wang Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/1cfd7b3ba447942784c4f7aa595e962399e9f617.1706577450.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- drivers/reset/Kconfig | 3 ++- drivers/reset/reset-simple.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index ccd59ddd7610..2034f69d5953 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -213,7 +213,7 @@ config RESET_SCMI config RESET_SIMPLE bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT - default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC + default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_SOPHGO || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC depends on HAS_IOMEM help This enables a simple reset controller driver for reset lines that @@ -228,6 +228,7 @@ config RESET_SIMPLE - RCC reset controller in STM32 MCUs - Allwinner SoCs - SiFive FU740 SoCs + - Sophgo SoCs config RESET_SOCFPGA bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA) diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c index 7ea5adbf2097..69b631eb8127 100644 --- a/drivers/reset/reset-simple.c +++ b/drivers/reset/reset-simple.c @@ -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,sg2042-reset", + .data = &reset_simple_active_low }, { /* sentinel */ }, }; -- Gitee From 5dd6e28644a9a2c401745db12801111a3d5be6e9 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Tue, 30 Jan 2024 09:50:32 +0800 Subject: [PATCH 15/24] riscv: dts: add reset generator for Sophgo SG2042 SoC ANBZ: #20835 commit 1ce7587e507e1762df1dadc22affcd41376040d5 upstream. Add reset generator node to device tree for SG2042. Signed-off-by: Chen Wang Reviewed-by: Inochi Amaoto Link: https://lore.kernel.org/r/b2f5d7cd2d3fccfc00cf4563d2dd7363b0fa2fca.1706577450.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/boot/dts/sophgo/sg2042.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index ead1cc35d88b..eeb341e16bfd 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -6,6 +6,8 @@ /dts-v1/; #include +#include + #include "sg2042-cpus.dtsi" / { @@ -327,6 +329,12 @@ intc: interrupt-controller@7090000000 { riscv,ndev = <224>; }; + rstgen: reset-controller@7030013000 { + compatible = "sophgo,sg2042-reset"; + reg = <0x00000070 0x30013000 0x00000000 0x0000000c>; + #reset-cells = <1>; + }; + uart0: serial@7040000000 { compatible = "snps,dw-apb-uart"; reg = <0x00000070 0x40000000 0x00000000 0x00001000>; -- Gitee From 276cce7ab54088e4e68048ed2f74e6b1e9ee6be7 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Tue, 30 Jan 2024 09:50:51 +0800 Subject: [PATCH 16/24] riscv: dts: add resets property for uart node ANBZ: #20835 commit 08573ba006ab7bc29c183e0b3c362a0b34f1d87b upstream. Add resets property for uart0 for completeness, although it is deasserted by default. Signed-off-by: Chen Wang Reviewed-by: Inochi Amaoto Link: https://lore.kernel.org/r/807f75e433a0f900da40ebb6a448349c98580072.1706577450.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/boot/dts/sophgo/sg2042.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index eeb341e16bfd..81fda312f988 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -343,6 +343,7 @@ uart0: serial@7040000000 { clock-frequency = <500000000>; reg-shift = <2>; reg-io-width = <4>; + resets = <&rstgen RST_UART0>; status = "disabled"; }; }; -- Gitee From 5045cbe6fa75c01138867ce6019dfd5542bae461 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Thu, 6 Jun 2024 16:36:25 +0800 Subject: [PATCH 17/24] dt-bindings: clock: sophgo: add pll clocks for SG2042 ANBZ: #20835 commit 88a26c3c2405626e0083a49609c5e8cd6c453d87 upstream. Add bindings for the pll clocks for Sophgo SG2042. Signed-off-by: Chen Wang Reviewed-by: Rob Herring Reviewed-by: Guo Ren Link: https://lore.kernel.org/r/a8da4870e3a966df01e1ac78d76005e42dd45ef2.1717661798.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../bindings/clock/sophgo,sg2042-pll.yaml | 53 +++++++++++++++++++ include/dt-bindings/clock/sophgo,sg2042-pll.h | 14 +++++ 2 files changed, 67 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sophgo,sg2042-pll.yaml create mode 100644 include/dt-bindings/clock/sophgo,sg2042-pll.h diff --git a/Documentation/devicetree/bindings/clock/sophgo,sg2042-pll.yaml b/Documentation/devicetree/bindings/clock/sophgo,sg2042-pll.yaml new file mode 100644 index 000000000000..1a417a627dd2 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sophgo,sg2042-pll.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/sophgo,sg2042-pll.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo SG2042 PLL Clock Generator + +maintainers: + - Chen Wang + +properties: + compatible: + const: sophgo,sg2042-pll + + reg: + maxItems: 1 + + clocks: + items: + - description: Oscillator(Clock Generation IC) for Main/Fixed PLL (25 MHz) + - description: Oscillator(Clock Generation IC) for DDR PLL 0 (25 MHz) + - description: Oscillator(Clock Generation IC) for DDR PLL 1 (25 MHz) + + clock-names: + items: + - const: cgi_main + - const: cgi_dpll0 + - const: cgi_dpll1 + + '#clock-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@10000000 { + compatible = "sophgo,sg2042-pll"; + reg = <0x10000000 0x10000>; + clocks = <&cgi_main>, <&cgi_dpll0>, <&cgi_dpll1>; + clock-names = "cgi_main", "cgi_dpll0", "cgi_dpll1"; + #clock-cells = <1>; + }; diff --git a/include/dt-bindings/clock/sophgo,sg2042-pll.h b/include/dt-bindings/clock/sophgo,sg2042-pll.h new file mode 100644 index 000000000000..2d519b3bf51c --- /dev/null +++ b/include/dt-bindings/clock/sophgo,sg2042-pll.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved. + */ + +#ifndef __DT_BINDINGS_SOPHGO_SG2042_PLL_H__ +#define __DT_BINDINGS_SOPHGO_SG2042_PLL_H__ + +#define MPLL_CLK 0 +#define FPLL_CLK 1 +#define DPLL0_CLK 2 +#define DPLL1_CLK 3 + +#endif /* __DT_BINDINGS_SOPHGO_SG2042_PLL_H__ */ -- Gitee From cbc5636dc780f702094d14ef1e89b4f12abf0fb1 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Thu, 6 Jun 2024 16:36:44 +0800 Subject: [PATCH 18/24] dt-bindings: clock: sophgo: add RP gate clocks for SG2042 ANBZ: #20835 commit 5a7144d61d73d801540f8846d8e1b9fa52a5559c upstream. Add bindings for the gate clocks of RP subsystem for Sophgo SG2042. Signed-off-by: Chen Wang Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/8f096a8a763605973719d7d194c00f919634ea2d.1717661798.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../bindings/clock/sophgo,sg2042-rpgate.yaml | 49 ++++++++++++++++ .../dt-bindings/clock/sophgo,sg2042-rpgate.h | 58 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sophgo,sg2042-rpgate.yaml create mode 100644 include/dt-bindings/clock/sophgo,sg2042-rpgate.h diff --git a/Documentation/devicetree/bindings/clock/sophgo,sg2042-rpgate.yaml b/Documentation/devicetree/bindings/clock/sophgo,sg2042-rpgate.yaml new file mode 100644 index 000000000000..1491fb8ef6a3 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sophgo,sg2042-rpgate.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/sophgo,sg2042-rpgate.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo SG2042 Gate Clock Generator for RP(riscv processors) subsystem + +maintainers: + - Chen Wang + +properties: + compatible: + const: sophgo,sg2042-rpgate + + reg: + maxItems: 1 + + clocks: + items: + - description: Gate clock for RP subsystem + + clock-names: + items: + - const: rpgate + + '#clock-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@20000000 { + compatible = "sophgo,sg2042-rpgate"; + reg = <0x20000000 0x10000>; + clocks = <&clkgen 85>; + clock-names = "rpgate"; + #clock-cells = <1>; + }; diff --git a/include/dt-bindings/clock/sophgo,sg2042-rpgate.h b/include/dt-bindings/clock/sophgo,sg2042-rpgate.h new file mode 100644 index 000000000000..8b4522d5f559 --- /dev/null +++ b/include/dt-bindings/clock/sophgo,sg2042-rpgate.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved. + */ + +#ifndef __DT_BINDINGS_SOPHGO_SG2042_RPGATE_H__ +#define __DT_BINDINGS_SOPHGO_SG2042_RPGATE_H__ + +#define GATE_CLK_RXU0 0 +#define GATE_CLK_RXU1 1 +#define GATE_CLK_RXU2 2 +#define GATE_CLK_RXU3 3 +#define GATE_CLK_RXU4 4 +#define GATE_CLK_RXU5 5 +#define GATE_CLK_RXU6 6 +#define GATE_CLK_RXU7 7 +#define GATE_CLK_RXU8 8 +#define GATE_CLK_RXU9 9 +#define GATE_CLK_RXU10 10 +#define GATE_CLK_RXU11 11 +#define GATE_CLK_RXU12 12 +#define GATE_CLK_RXU13 13 +#define GATE_CLK_RXU14 14 +#define GATE_CLK_RXU15 15 +#define GATE_CLK_RXU16 16 +#define GATE_CLK_RXU17 17 +#define GATE_CLK_RXU18 18 +#define GATE_CLK_RXU19 19 +#define GATE_CLK_RXU20 20 +#define GATE_CLK_RXU21 21 +#define GATE_CLK_RXU22 22 +#define GATE_CLK_RXU23 23 +#define GATE_CLK_RXU24 24 +#define GATE_CLK_RXU25 25 +#define GATE_CLK_RXU26 26 +#define GATE_CLK_RXU27 27 +#define GATE_CLK_RXU28 28 +#define GATE_CLK_RXU29 29 +#define GATE_CLK_RXU30 30 +#define GATE_CLK_RXU31 31 +#define GATE_CLK_MP0 32 +#define GATE_CLK_MP1 33 +#define GATE_CLK_MP2 34 +#define GATE_CLK_MP3 35 +#define GATE_CLK_MP4 36 +#define GATE_CLK_MP5 37 +#define GATE_CLK_MP6 38 +#define GATE_CLK_MP7 39 +#define GATE_CLK_MP8 40 +#define GATE_CLK_MP9 41 +#define GATE_CLK_MP10 42 +#define GATE_CLK_MP11 43 +#define GATE_CLK_MP12 44 +#define GATE_CLK_MP13 45 +#define GATE_CLK_MP14 46 +#define GATE_CLK_MP15 47 + +#endif /* __DT_BINDINGS_SOPHGO_SG2042_RPGATE_H__ */ -- Gitee From 212eed1a84c461b3579c97f39f258c8c4b1d9741 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Thu, 6 Jun 2024 16:37:01 +0800 Subject: [PATCH 19/24] dt-bindings: clock: sophgo: add clkgen for SG2042 ANBZ: #20835 commit 5911423798b2eba65d6ea0aff6505280b3eb55e6 upstream. Add bindings for the clock generator of divider/mux and gates working for other subsystem than RP subsystem for Sophgo SG2042. Signed-off-by: Chen Wang Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/0159f5cdd9b42ec487001fe034bf6a94f45fd182.1717661798.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../bindings/clock/sophgo,sg2042-clkgen.yaml | 61 ++++++++++ .../dt-bindings/clock/sophgo,sg2042-clkgen.h | 111 ++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sophgo,sg2042-clkgen.yaml create mode 100644 include/dt-bindings/clock/sophgo,sg2042-clkgen.h diff --git a/Documentation/devicetree/bindings/clock/sophgo,sg2042-clkgen.yaml b/Documentation/devicetree/bindings/clock/sophgo,sg2042-clkgen.yaml new file mode 100644 index 000000000000..e7a9255bcb58 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sophgo,sg2042-clkgen.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/sophgo,sg2042-clkgen.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo SG2042 Clock Generator for divider/mux/gate + +maintainers: + - Chen Wang + +properties: + compatible: + const: sophgo,sg2042-clkgen + + reg: + maxItems: 1 + + clocks: + items: + - description: Main PLL + - description: Fixed PLL + - description: DDR PLL 0 + - description: DDR PLL 1 + + clock-names: + items: + - const: mpll + - const: fpll + - const: dpll0 + - const: dpll1 + + '#clock-cells': + const: 1 + description: + See for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@30012000 { + compatible = "sophgo,sg2042-clkgen"; + reg = <0x30012000 0x1000>; + clocks = <&pllclk 0>, + <&pllclk 1>, + <&pllclk 2>, + <&pllclk 3>; + clock-names = "mpll", + "fpll", + "dpll0", + "dpll1"; + #clock-cells = <1>; + }; diff --git a/include/dt-bindings/clock/sophgo,sg2042-clkgen.h b/include/dt-bindings/clock/sophgo,sg2042-clkgen.h new file mode 100644 index 000000000000..84f7857317a2 --- /dev/null +++ b/include/dt-bindings/clock/sophgo,sg2042-clkgen.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved. + */ + +#ifndef __DT_BINDINGS_SOPHGO_SG2042_CLKGEN_H__ +#define __DT_BINDINGS_SOPHGO_SG2042_CLKGEN_H__ + +#define DIV_CLK_MPLL_RP_CPU_NORMAL_0 0 +#define DIV_CLK_MPLL_AXI_DDR_0 1 +#define DIV_CLK_FPLL_DDR01_1 2 +#define DIV_CLK_FPLL_DDR23_1 3 +#define DIV_CLK_FPLL_RP_CPU_NORMAL_1 4 +#define DIV_CLK_FPLL_50M_A53 5 +#define DIV_CLK_FPLL_TOP_RP_CMN_DIV2 6 +#define DIV_CLK_FPLL_UART_500M 7 +#define DIV_CLK_FPLL_AHB_LPC 8 +#define DIV_CLK_FPLL_EFUSE 9 +#define DIV_CLK_FPLL_TX_ETH0 10 +#define DIV_CLK_FPLL_PTP_REF_I_ETH0 11 +#define DIV_CLK_FPLL_REF_ETH0 12 +#define DIV_CLK_FPLL_EMMC 13 +#define DIV_CLK_FPLL_SD 14 +#define DIV_CLK_FPLL_TOP_AXI0 15 +#define DIV_CLK_FPLL_TOP_AXI_HSPERI 16 +#define DIV_CLK_FPLL_AXI_DDR_1 17 +#define DIV_CLK_FPLL_DIV_TIMER1 18 +#define DIV_CLK_FPLL_DIV_TIMER2 19 +#define DIV_CLK_FPLL_DIV_TIMER3 20 +#define DIV_CLK_FPLL_DIV_TIMER4 21 +#define DIV_CLK_FPLL_DIV_TIMER5 22 +#define DIV_CLK_FPLL_DIV_TIMER6 23 +#define DIV_CLK_FPLL_DIV_TIMER7 24 +#define DIV_CLK_FPLL_DIV_TIMER8 25 +#define DIV_CLK_FPLL_100K_EMMC 26 +#define DIV_CLK_FPLL_100K_SD 27 +#define DIV_CLK_FPLL_GPIO_DB 28 +#define DIV_CLK_DPLL0_DDR01_0 29 +#define DIV_CLK_DPLL1_DDR23_0 30 + +#define GATE_CLK_RP_CPU_NORMAL_DIV0 31 +#define GATE_CLK_AXI_DDR_DIV0 32 + +#define GATE_CLK_RP_CPU_NORMAL_DIV1 33 +#define GATE_CLK_A53_50M 34 +#define GATE_CLK_TOP_RP_CMN_DIV2 35 +#define GATE_CLK_HSDMA 36 +#define GATE_CLK_EMMC_100M 37 +#define GATE_CLK_SD_100M 38 +#define GATE_CLK_TX_ETH0 39 +#define GATE_CLK_PTP_REF_I_ETH0 40 +#define GATE_CLK_REF_ETH0 41 +#define GATE_CLK_UART_500M 42 +#define GATE_CLK_EFUSE 43 + +#define GATE_CLK_AHB_LPC 44 +#define GATE_CLK_AHB_ROM 45 +#define GATE_CLK_AHB_SF 46 + +#define GATE_CLK_APB_UART 47 +#define GATE_CLK_APB_TIMER 48 +#define GATE_CLK_APB_EFUSE 49 +#define GATE_CLK_APB_GPIO 50 +#define GATE_CLK_APB_GPIO_INTR 51 +#define GATE_CLK_APB_SPI 52 +#define GATE_CLK_APB_I2C 53 +#define GATE_CLK_APB_WDT 54 +#define GATE_CLK_APB_PWM 55 +#define GATE_CLK_APB_RTC 56 + +#define GATE_CLK_AXI_PCIE0 57 +#define GATE_CLK_AXI_PCIE1 58 +#define GATE_CLK_SYSDMA_AXI 59 +#define GATE_CLK_AXI_DBG_I2C 60 +#define GATE_CLK_AXI_SRAM 61 +#define GATE_CLK_AXI_ETH0 62 +#define GATE_CLK_AXI_EMMC 63 +#define GATE_CLK_AXI_SD 64 +#define GATE_CLK_TOP_AXI0 65 +#define GATE_CLK_TOP_AXI_HSPERI 66 + +#define GATE_CLK_TIMER1 67 +#define GATE_CLK_TIMER2 68 +#define GATE_CLK_TIMER3 69 +#define GATE_CLK_TIMER4 70 +#define GATE_CLK_TIMER5 71 +#define GATE_CLK_TIMER6 72 +#define GATE_CLK_TIMER7 73 +#define GATE_CLK_TIMER8 74 +#define GATE_CLK_100K_EMMC 75 +#define GATE_CLK_100K_SD 76 +#define GATE_CLK_GPIO_DB 77 + +#define GATE_CLK_AXI_DDR_DIV1 78 +#define GATE_CLK_DDR01_DIV1 79 +#define GATE_CLK_DDR23_DIV1 80 + +#define GATE_CLK_DDR01_DIV0 81 +#define GATE_CLK_DDR23_DIV0 82 + +#define GATE_CLK_DDR01 83 +#define GATE_CLK_DDR23 84 +#define GATE_CLK_RP_CPU_NORMAL 85 +#define GATE_CLK_AXI_DDR 86 + +#define MUX_CLK_DDR01 87 +#define MUX_CLK_DDR23 88 +#define MUX_CLK_RP_CPU_NORMAL 89 +#define MUX_CLK_AXI_DDR 90 + +#endif /* __DT_BINDINGS_SOPHGO_SG2042_CLKGEN_H__ */ -- Gitee From 5408b3344217c8a44c8b9aa24f7a00560386cfc7 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Thu, 6 Jun 2024 16:37:21 +0800 Subject: [PATCH 20/24] clk: sophgo: Add SG2042 clock driver ANBZ: #20835 commit 48cf7e01386e7e35ea12255bc401bdd484c34e7d upstream. Add a driver for the SOPHGO SG2042 clocks. Signed-off-by: Chen Wang Link: https://lore.kernel.org/r/4d5f67d428fd9ed92355801ab54fdf86de011499.1717661798.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sophgo/Kconfig | 30 + drivers/clk/sophgo/Makefile | 4 + drivers/clk/sophgo/clk-sg2042-clkgen.c | 1151 ++++++++++++++++++++++++ drivers/clk/sophgo/clk-sg2042-pll.c | 569 ++++++++++++ drivers/clk/sophgo/clk-sg2042-rpgate.c | 290 ++++++ drivers/clk/sophgo/clk-sg2042.h | 18 + 8 files changed, 2064 insertions(+) create mode 100644 drivers/clk/sophgo/Kconfig create mode 100644 drivers/clk/sophgo/Makefile create mode 100644 drivers/clk/sophgo/clk-sg2042-clkgen.c create mode 100644 drivers/clk/sophgo/clk-sg2042-pll.c create mode 100644 drivers/clk/sophgo/clk-sg2042-rpgate.c create mode 100644 drivers/clk/sophgo/clk-sg2042.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c30099866174..f3ec23f22e3e 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -490,6 +490,7 @@ source "drivers/clk/rockchip/Kconfig" source "drivers/clk/samsung/Kconfig" source "drivers/clk/sifive/Kconfig" source "drivers/clk/socfpga/Kconfig" +source "drivers/clk/sophgo/Kconfig" source "drivers/clk/sprd/Kconfig" source "drivers/clk/starfive/Kconfig" source "drivers/clk/sunxi/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 18969cbd4bb1..acac827d906a 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -117,6 +117,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-y += socfpga/ +obj-y += sophgo/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-y += sprd/ obj-$(CONFIG_ARCH_STI) += st/ diff --git a/drivers/clk/sophgo/Kconfig b/drivers/clk/sophgo/Kconfig new file mode 100644 index 000000000000..dad5568f10fc --- /dev/null +++ b/drivers/clk/sophgo/Kconfig @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 +# common clock support for SOPHGO SoC family. + +config CLK_SOPHGO_SG2042_PLL + tristate "Sophgo SG2042 PLL clock support" + depends on ARCH_SOPHGO || COMPILE_TEST + help + This driver supports the PLL clock controller on the + Sophgo SG2042 SoC. This clock IP uses three oscillators with + frequency of 25 MHz as input, which are used for Main/Fixed + PLL, DDR PLL 0 and DDR PLL 1 respectively. + +config CLK_SOPHGO_SG2042_CLKGEN + tristate "Sophgo SG2042 Clock Generator support" + depends on CLK_SOPHGO_SG2042_PLL + help + This driver supports the Clock Generator on the + Sophgo SG2042 SoC. This clock IP depends on SG2042 PLL clock + because it uses PLL clocks as input. + This driver provides clock function such as DIV/Mux/Gate. + +config CLK_SOPHGO_SG2042_RPGATE + tristate "Sophgo SG2042 RP subsystem clock controller support" + depends on CLK_SOPHGO_SG2042_CLKGEN + help + This driver supports the RP((Riscv Processors)) subsystem clock + controller on the Sophgo SG2042 SoC. + This clock IP depends on SG2042 Clock Generator because it uses + clock from Clock Generator IP as input. + This driver provides Gate function for RP. diff --git a/drivers/clk/sophgo/Makefile b/drivers/clk/sophgo/Makefile new file mode 100644 index 000000000000..a6003f4d5311 --- /dev/null +++ b/drivers/clk/sophgo/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_CLK_SOPHGO_SG2042_CLKGEN) += clk-sg2042-clkgen.o +obj-$(CONFIG_CLK_SOPHGO_SG2042_PLL) += clk-sg2042-pll.o +obj-$(CONFIG_CLK_SOPHGO_SG2042_RPGATE) += clk-sg2042-rpgate.o diff --git a/drivers/clk/sophgo/clk-sg2042-clkgen.c b/drivers/clk/sophgo/clk-sg2042-clkgen.c new file mode 100644 index 000000000000..9c648f1f38d5 --- /dev/null +++ b/drivers/clk/sophgo/clk-sg2042-clkgen.c @@ -0,0 +1,1151 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sophgo SG2042 Clock Generator Driver + * + * Copyright (C) 2024 Sophgo Technology Inc. + * Copyright (C) 2024 Chen Wang + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-sg2042.h" + +/* Registers defined in SYS_CTRL */ +#define R_PLL_BEGIN 0xC0 +#define R_PLL_STAT (0xC0 - R_PLL_BEGIN) +#define R_PLL_CLKEN_CONTROL (0xC4 - R_PLL_BEGIN) +#define R_MPLL_CONTROL (0xE8 - R_PLL_BEGIN) +#define R_FPLL_CONTROL (0xF4 - R_PLL_BEGIN) +#define R_DPLL0_CONTROL (0xF8 - R_PLL_BEGIN) +#define R_DPLL1_CONTROL (0xFC - R_PLL_BEGIN) + +/* Registers defined in CLOCK */ +#define R_CLKENREG0 0x00 +#define R_CLKENREG1 0x04 +#define R_CLKSELREG0 0x20 +#define R_CLKDIVREG0 0x40 +#define R_CLKDIVREG1 0x44 +#define R_CLKDIVREG2 0x48 +#define R_CLKDIVREG3 0x4C +#define R_CLKDIVREG4 0x50 +#define R_CLKDIVREG5 0x54 +#define R_CLKDIVREG6 0x58 +#define R_CLKDIVREG7 0x5C +#define R_CLKDIVREG8 0x60 +#define R_CLKDIVREG9 0x64 +#define R_CLKDIVREG10 0x68 +#define R_CLKDIVREG11 0x6C +#define R_CLKDIVREG12 0x70 +#define R_CLKDIVREG13 0x74 +#define R_CLKDIVREG14 0x78 +#define R_CLKDIVREG15 0x7C +#define R_CLKDIVREG16 0x80 +#define R_CLKDIVREG17 0x84 +#define R_CLKDIVREG18 0x88 +#define R_CLKDIVREG19 0x8C +#define R_CLKDIVREG20 0x90 +#define R_CLKDIVREG21 0x94 +#define R_CLKDIVREG22 0x98 +#define R_CLKDIVREG23 0x9C +#define R_CLKDIVREG24 0xA0 +#define R_CLKDIVREG25 0xA4 +#define R_CLKDIVREG26 0xA8 +#define R_CLKDIVREG27 0xAC +#define R_CLKDIVREG28 0xB0 +#define R_CLKDIVREG29 0xB4 +#define R_CLKDIVREG30 0xB8 + +/* All following shift value are the same for all DIV registers */ +#define SHIFT_DIV_RESET_CTRL 0 +#define SHIFT_DIV_FACTOR_SEL 3 +#define SHIFT_DIV_FACTOR 16 + +/** + * struct sg2042_divider_clock - Divider clock + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @reg: used for readl/writel. + * **NOTE**: DIV registers are ALL in CLOCK! + * @lock: spinlock to protect register access, modification of + * frequency can only be served one at the time + * @offset_ctrl: offset of divider control registers + * @shift: shift of "Clock Divider Factor" in divider control register + * @width: width of "Clock Divider Factor" in divider control register + * @div_flags: private flags for this clock, not for framework-specific + * @initval: In the divider control register, we can configure whether + * to use the value of "Clock Divider Factor" or just use + * the initial value pre-configured by IC. BIT[3] controls + * this and by default (value is 0), means initial value + * is used. + * **NOTE** that we cannot read the initial value (default + * value when poweron) and default value of "Clock Divider + * Factor" is zero, which I think is a hardware design flaw + * and should be sync-ed with the initial value. So in + * software we have to add a configuration item (initval) + * to manually configure this value and use it when BIT[3] + * is zero. + */ +struct sg2042_divider_clock { + struct clk_hw hw; + + unsigned int id; + + void __iomem *reg; + /* protect register access */ + spinlock_t *lock; + + u32 offset_ctrl; + u8 shift; + u8 width; + u8 div_flags; + u32 initval; +}; + +#define to_sg2042_clk_divider(_hw) \ + container_of(_hw, struct sg2042_divider_clock, hw) + +/** + * struct sg2042_gate_clock - Gate clock + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @offset_enable: offset of gate enable registers + * @bit_idx: which bit in the register controls gating of this clock + */ +struct sg2042_gate_clock { + struct clk_hw hw; + + unsigned int id; + + u32 offset_enable; + u8 bit_idx; +}; + +/** + * struct sg2042_mux_clock - Mux clock + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @offset_select: offset of mux selection registers + * **NOTE**: MUX registers are ALL in CLOCK! + * @shift: shift of "Clock Select" in mux selection register + * @width: width of "Clock Select" in mux selection register + * @clk_nb: used for notification + * @original_index: set by notifier callback + */ +struct sg2042_mux_clock { + struct clk_hw hw; + + unsigned int id; + + u32 offset_select; + u8 shift; + u8 width; + + struct notifier_block clk_nb; + u8 original_index; +}; + +#define to_sg2042_mux_nb(_nb) container_of(_nb, struct sg2042_mux_clock, clk_nb) + +static unsigned long sg2042_clk_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw); + unsigned long ret_rate; + u32 val; + + if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) { + val = divider->initval; + } else { + val = readl(divider->reg) >> divider->shift; + val &= clk_div_mask(divider->width); + } + + ret_rate = divider_recalc_rate(hw, parent_rate, val, NULL, + divider->div_flags, divider->width); + + pr_debug("--> %s: divider_recalc_rate: ret_rate = %ld\n", + clk_hw_get_name(hw), ret_rate); + return ret_rate; +} + +static long sg2042_clk_divider_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw); + unsigned long ret_rate; + u32 bestdiv; + + /* if read only, just return current value */ + if (divider->div_flags & CLK_DIVIDER_READ_ONLY) { + if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) { + bestdiv = divider->initval; + } else { + bestdiv = readl(divider->reg) >> divider->shift; + bestdiv &= clk_div_mask(divider->width); + } + ret_rate = DIV_ROUND_UP_ULL((u64)*prate, bestdiv); + } else { + ret_rate = divider_round_rate(hw, rate, prate, NULL, + divider->width, divider->div_flags); + } + + pr_debug("--> %s: divider_round_rate: val = %ld\n", + clk_hw_get_name(hw), ret_rate); + return ret_rate; +} + +static int sg2042_clk_divider_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw); + unsigned long flags = 0; + u32 val, val2, value; + + value = divider_get_val(rate, parent_rate, NULL, + divider->width, divider->div_flags); + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + else + __acquire(divider->lock); + + /* + * The sequence of clock frequency modification is: + * Assert to reset divider. + * Modify the value of Clock Divide Factor (and High Wide if needed). + * De-assert to restore divided clock with new frequency. + */ + val = readl(divider->reg); + + /* assert */ + val &= ~BIT(SHIFT_DIV_RESET_CTRL); + writel(val, divider->reg); + + if (divider->div_flags & CLK_DIVIDER_HIWORD_MASK) { + val = clk_div_mask(divider->width) << (divider->shift + 16); + } else { + val = readl(divider->reg); + val &= ~(clk_div_mask(divider->width) << divider->shift); + } + val |= value << divider->shift; + val |= BIT(SHIFT_DIV_FACTOR_SEL); + writel(val, divider->reg); + val2 = val; + + /* de-assert */ + val |= BIT(SHIFT_DIV_RESET_CTRL); + writel(val, divider->reg); + + if (divider->lock) + spin_unlock_irqrestore(divider->lock, flags); + else + __release(divider->lock); + + pr_debug("--> %s: divider_set_rate: register val = 0x%x\n", + clk_hw_get_name(hw), val2); + return 0; +} + +static const struct clk_ops sg2042_clk_divider_ops = { + .recalc_rate = sg2042_clk_divider_recalc_rate, + .round_rate = sg2042_clk_divider_round_rate, + .set_rate = sg2042_clk_divider_set_rate, +}; + +static const struct clk_ops sg2042_clk_divider_ro_ops = { + .recalc_rate = sg2042_clk_divider_recalc_rate, + .round_rate = sg2042_clk_divider_round_rate, +}; + +/* + * Clock initialization macro naming rules: + * FW: use CLK_HW_INIT_FW_NAME + * HW: use CLK_HW_INIT_HW + * HWS: use CLK_HW_INIT_HWS + * RO: means Read-Only + */ +#define SG2042_DIV_FW(_id, _name, _parent, \ + _r_ctrl, _shift, _width, \ + _div_flag, _initval) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_FW_NAME( \ + _name, \ + _parent, \ + &sg2042_clk_divider_ops, \ + 0), \ + .offset_ctrl = _r_ctrl, \ + .shift = _shift, \ + .width = _width, \ + .div_flags = _div_flag, \ + .initval = _initval, \ + } + +#define SG2042_DIV_FW_RO(_id, _name, _parent, \ + _r_ctrl, _shift, _width, \ + _div_flag, _initval) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_FW_NAME( \ + _name, \ + _parent, \ + &sg2042_clk_divider_ro_ops, \ + 0), \ + .offset_ctrl = _r_ctrl, \ + .shift = _shift, \ + .width = _width, \ + .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \ + .initval = _initval, \ + } + +#define SG2042_DIV_HW(_id, _name, _parent, \ + _r_ctrl, _shift, _width, \ + _div_flag, _initval) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_HW( \ + _name, \ + _parent, \ + &sg2042_clk_divider_ops, \ + 0), \ + .offset_ctrl = _r_ctrl, \ + .shift = _shift, \ + .width = _width, \ + .div_flags = _div_flag, \ + .initval = _initval, \ + } + +#define SG2042_DIV_HW_RO(_id, _name, _parent, \ + _r_ctrl, _shift, _width, \ + _div_flag, _initval) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_HW( \ + _name, \ + _parent, \ + &sg2042_clk_divider_ro_ops, \ + 0), \ + .offset_ctrl = _r_ctrl, \ + .shift = _shift, \ + .width = _width, \ + .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \ + .initval = _initval, \ + } + +#define SG2042_DIV_HWS(_id, _name, _parent, \ + _r_ctrl, _shift, _width, \ + _div_flag, _initval) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_HWS( \ + _name, \ + _parent, \ + &sg2042_clk_divider_ops, \ + 0), \ + .offset_ctrl = _r_ctrl, \ + .shift = _shift, \ + .width = _width, \ + .div_flags = _div_flag, \ + .initval = _initval, \ + } + +#define SG2042_DIV_HWS_RO(_id, _name, _parent, \ + _r_ctrl, _shift, _width, \ + _div_flag, _initval) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_HWS( \ + _name, \ + _parent, \ + &sg2042_clk_divider_ro_ops, \ + 0), \ + .offset_ctrl = _r_ctrl, \ + .shift = _shift, \ + .width = _width, \ + .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \ + .initval = _initval, \ + } + +#define SG2042_GATE_HWS(_id, _name, _parent, _flags, \ + _r_enable, _bit_idx) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_HWS( \ + _name, \ + _parent, \ + NULL, \ + _flags), \ + .offset_enable = _r_enable, \ + .bit_idx = _bit_idx, \ + } + +#define SG2042_GATE_HW(_id, _name, _parent, _flags, \ + _r_enable, _bit_idx) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_HW( \ + _name, \ + _parent, \ + NULL, \ + _flags), \ + .offset_enable = _r_enable, \ + .bit_idx = _bit_idx, \ + } + +#define SG2042_GATE_FW(_id, _name, _parent, _flags, \ + _r_enable, _bit_idx) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_FW_NAME( \ + _name, \ + _parent, \ + NULL, \ + _flags), \ + .offset_enable = _r_enable, \ + .bit_idx = _bit_idx, \ + } + +#define SG2042_MUX(_id, _name, _parents, _flags, _r_select, _shift, _width) { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_PARENTS_HW( \ + _name, \ + _parents, \ + NULL, \ + _flags), \ + .offset_select = _r_select, \ + .shift = _shift, \ + .width = _width, \ + } + +/* + * Clock items in the array are sorted according to the clock-tree diagram, + * from top to bottom, from upstream to downstream. Read TRM for details. + */ + +/* updated during probe/registration */ +static const struct clk_hw *clk_gate_ddr01_div0[] = { NULL }; +static const struct clk_hw *clk_gate_ddr01_div1[] = { NULL }; +static const struct clk_hw *clk_gate_ddr23_div0[] = { NULL }; +static const struct clk_hw *clk_gate_ddr23_div1[] = { NULL }; +static const struct clk_hw *clk_gate_rp_cpu_normal_div0[] = { NULL }; +static const struct clk_hw *clk_gate_rp_cpu_normal_div1[] = { NULL }; +static const struct clk_hw *clk_gate_axi_ddr_div0[] = { NULL }; +static const struct clk_hw *clk_gate_axi_ddr_div1[] = { NULL }; + +static const struct sg2042_gate_clock sg2042_gate_clks_level_1[] = { + SG2042_GATE_FW(GATE_CLK_DDR01_DIV0, "clk_gate_ddr01_div0", "dpll0", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + R_CLKDIVREG27, 4), + SG2042_GATE_FW(GATE_CLK_DDR01_DIV1, "clk_gate_ddr01_div1", "fpll", + CLK_IS_CRITICAL, + R_CLKDIVREG28, 4), + + SG2042_GATE_FW(GATE_CLK_DDR23_DIV0, "clk_gate_ddr23_div0", "dpll1", + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + R_CLKDIVREG29, 4), + SG2042_GATE_FW(GATE_CLK_DDR23_DIV1, "clk_gate_ddr23_div1", "fpll", + CLK_IS_CRITICAL, + R_CLKDIVREG30, 4), + + SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV0, + "clk_gate_rp_cpu_normal_div0", "mpll", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKDIVREG0, 4), + SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV1, + "clk_gate_rp_cpu_normal_div1", "fpll", + CLK_IS_CRITICAL, + R_CLKDIVREG1, 4), + + SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV0, "clk_gate_axi_ddr_div0", "mpll", + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKDIVREG25, 4), + SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV1, "clk_gate_axi_ddr_div1", "fpll", + CLK_IS_CRITICAL, + R_CLKDIVREG26, 4), +}; + +#define DEF_DIVFLAG (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO) + +static struct sg2042_divider_clock sg2042_div_clks_level_1[] = { + SG2042_DIV_HWS_RO(DIV_CLK_DPLL0_DDR01_0, + "clk_div_ddr01_0", clk_gate_ddr01_div0, + R_CLKDIVREG27, 16, 5, DEF_DIVFLAG, 1), + SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR01_1, + "clk_div_ddr01_1", clk_gate_ddr01_div1, + R_CLKDIVREG28, 16, 5, DEF_DIVFLAG, 1), + + SG2042_DIV_HWS_RO(DIV_CLK_DPLL1_DDR23_0, + "clk_div_ddr23_0", clk_gate_ddr23_div0, + R_CLKDIVREG29, 16, 5, DEF_DIVFLAG, 1), + SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR23_1, + "clk_div_ddr23_1", clk_gate_ddr23_div1, + R_CLKDIVREG30, 16, 5, DEF_DIVFLAG, 1), + + SG2042_DIV_HWS(DIV_CLK_MPLL_RP_CPU_NORMAL_0, + "clk_div_rp_cpu_normal_0", clk_gate_rp_cpu_normal_div0, + R_CLKDIVREG0, 16, 5, DEF_DIVFLAG, 1), + SG2042_DIV_HWS(DIV_CLK_FPLL_RP_CPU_NORMAL_1, + "clk_div_rp_cpu_normal_1", clk_gate_rp_cpu_normal_div1, + R_CLKDIVREG1, 16, 5, DEF_DIVFLAG, 1), + + SG2042_DIV_HWS(DIV_CLK_MPLL_AXI_DDR_0, + "clk_div_axi_ddr_0", clk_gate_axi_ddr_div0, + R_CLKDIVREG25, 16, 5, DEF_DIVFLAG, 2), + SG2042_DIV_HWS(DIV_CLK_FPLL_AXI_DDR_1, + "clk_div_axi_ddr_1", clk_gate_axi_ddr_div1, + R_CLKDIVREG26, 16, 5, DEF_DIVFLAG, 1), +}; + +/* + * Note: regarding names for mux clock, "0/1" or "div0/div1" means the + * first/second parent input source, not the register value. + * For example: + * "clk_div_ddr01_0" is the name of Clock divider 0 control of DDR01, and + * "clk_gate_ddr01_div0" is the gate clock in front of the "clk_div_ddr01_0", + * they are both controlled by register CLKDIVREG27; + * "clk_div_ddr01_1" is the name of Clock divider 1 control of DDR01, and + * "clk_gate_ddr01_div1" is the gate clock in front of the "clk_div_ddr01_1", + * they are both controlled by register CLKDIVREG28; + * While for register value of mux selection, use Clock Select for DDR01’s clock + * as example, see CLKSELREG0, bit[2]. + * 1: Select in_dpll0_clk as clock source, correspondng to the parent input + * source from "clk_div_ddr01_0". + * 0: Select in_fpll_clk as clock source, corresponding to the parent input + * source from "clk_div_ddr01_1". + * So we need a table to define the array of register values corresponding to + * the parent index and tell CCF about this when registering mux clock. + */ +static const u32 sg2042_mux_table[] = {1, 0}; + +/* Aliases just for easy reading */ +#define clk_div_ddr01_0 (&sg2042_div_clks_level_1[0].hw) +#define clk_div_ddr01_1 (&sg2042_div_clks_level_1[1].hw) +#define clk_div_ddr23_0 (&sg2042_div_clks_level_1[2].hw) +#define clk_div_ddr23_1 (&sg2042_div_clks_level_1[3].hw) +#define clk_div_rp_cpu_normal_0 (&sg2042_div_clks_level_1[4].hw) +#define clk_div_rp_cpu_normal_1 (&sg2042_div_clks_level_1[5].hw) +#define clk_div_axi_ddr_0 (&sg2042_div_clks_level_1[6].hw) +#define clk_div_axi_ddr_1 (&sg2042_div_clks_level_1[7].hw) + +static const struct clk_hw *clk_mux_ddr01_p[] = { + clk_div_ddr01_0, + clk_div_ddr01_1, +}; + +static const struct clk_hw *clk_mux_ddr23_p[] = { + clk_div_ddr23_0, + clk_div_ddr23_1, +}; + +static const struct clk_hw *clk_mux_rp_cpu_normal_p[] = { + clk_div_rp_cpu_normal_0, + clk_div_rp_cpu_normal_1, +}; + +static const struct clk_hw *clk_mux_axi_ddr_p[] = { + clk_div_axi_ddr_0, + clk_div_axi_ddr_1, +}; + +/* Mux clocks to be updated during probe/registration */ +static const struct clk_hw *clk_mux_ddr01[] = { NULL }; +static const struct clk_hw *clk_mux_ddr23[] = { NULL }; +static const struct clk_hw *clk_mux_rp_cpu_normal[] = { NULL }; +static const struct clk_hw *clk_mux_axi_ddr[] = { NULL }; + +static struct sg2042_mux_clock sg2042_mux_clks[] = { + SG2042_MUX(MUX_CLK_DDR01, "clk_mux_ddr01", clk_mux_ddr01_p, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY, + R_CLKSELREG0, 2, 1), + SG2042_MUX(MUX_CLK_DDR23, "clk_mux_ddr23", clk_mux_ddr23_p, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY, + R_CLKSELREG0, 3, 1), + SG2042_MUX(MUX_CLK_RP_CPU_NORMAL, "clk_mux_rp_cpu_normal", clk_mux_rp_cpu_normal_p, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + R_CLKSELREG0, 0, 1), + SG2042_MUX(MUX_CLK_AXI_DDR, "clk_mux_axi_ddr", clk_mux_axi_ddr_p, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + R_CLKSELREG0, 1, 1), +}; + +/* Aliases just for easy reading */ +#define clk_div_top_rp_cmn_div2 (&sg2042_div_clks_level_2[0].hw) +#define clk_div_50m_a53 (&sg2042_div_clks_level_2[1].hw) +#define clk_div_timer1 (&sg2042_div_clks_level_2[2].hw) +#define clk_div_timer2 (&sg2042_div_clks_level_2[3].hw) +#define clk_div_timer3 (&sg2042_div_clks_level_2[4].hw) +#define clk_div_timer4 (&sg2042_div_clks_level_2[5].hw) +#define clk_div_timer5 (&sg2042_div_clks_level_2[6].hw) +#define clk_div_timer6 (&sg2042_div_clks_level_2[7].hw) +#define clk_div_timer7 (&sg2042_div_clks_level_2[8].hw) +#define clk_div_timer8 (&sg2042_div_clks_level_2[9].hw) +#define clk_div_uart_500m (&sg2042_div_clks_level_2[10].hw) +#define clk_div_ahb_lpc (&sg2042_div_clks_level_2[11].hw) +#define clk_div_efuse (&sg2042_div_clks_level_2[12].hw) +#define clk_div_tx_eth0 (&sg2042_div_clks_level_2[13].hw) +#define clk_div_ptp_ref_i_eth0 (&sg2042_div_clks_level_2[14].hw) +#define clk_div_ref_eth0 (&sg2042_div_clks_level_2[15].hw) +#define clk_div_emmc (&sg2042_div_clks_level_2[16].hw) +#define clk_div_sd (&sg2042_div_clks_level_2[17].hw) +#define clk_div_top_axi0 (&sg2042_div_clks_level_2[18].hw) +#define clk_div_100k_emmc (&sg2042_div_clks_level_2[19].hw) +#define clk_div_100k_sd (&sg2042_div_clks_level_2[20].hw) +#define clk_div_gpio_db (&sg2042_div_clks_level_2[21].hw) +#define clk_div_top_axi_hsperi (&sg2042_div_clks_level_2[22].hw) + +static struct sg2042_divider_clock sg2042_div_clks_level_2[] = { + SG2042_DIV_HWS(DIV_CLK_FPLL_TOP_RP_CMN_DIV2, + "clk_div_top_rp_cmn_div2", clk_mux_rp_cpu_normal, + R_CLKDIVREG3, 16, 16, DEF_DIVFLAG, 2), + + SG2042_DIV_FW(DIV_CLK_FPLL_50M_A53, "clk_div_50m_a53", "fpll", + R_CLKDIVREG2, 16, 8, DEF_DIVFLAG, 20), + /* downstream of div_50m_a53 */ + SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER1, "clk_div_timer1", clk_div_50m_a53, + R_CLKDIVREG6, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER2, "clk_div_timer2", clk_div_50m_a53, + R_CLKDIVREG7, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER3, "clk_div_timer3", clk_div_50m_a53, + R_CLKDIVREG8, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER4, "clk_div_timer4", clk_div_50m_a53, + R_CLKDIVREG9, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER5, "clk_div_timer5", clk_div_50m_a53, + R_CLKDIVREG10, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER6, "clk_div_timer6", clk_div_50m_a53, + R_CLKDIVREG11, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER7, "clk_div_timer7", clk_div_50m_a53, + R_CLKDIVREG12, 16, 16, DEF_DIVFLAG, 1), + SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER8, "clk_div_timer8", clk_div_50m_a53, + R_CLKDIVREG13, 16, 16, DEF_DIVFLAG, 1), + + /* + * Set clk_div_uart_500m as RO, because the width of CLKDIVREG4 is too + * narrow for us to produce 115200. Use UART internal divider directly. + */ + SG2042_DIV_FW_RO(DIV_CLK_FPLL_UART_500M, "clk_div_uart_500m", "fpll", + R_CLKDIVREG4, 16, 7, DEF_DIVFLAG, 2), + SG2042_DIV_FW(DIV_CLK_FPLL_AHB_LPC, "clk_div_ahb_lpc", "fpll", + R_CLKDIVREG5, 16, 16, DEF_DIVFLAG, 5), + SG2042_DIV_FW(DIV_CLK_FPLL_EFUSE, "clk_div_efuse", "fpll", + R_CLKDIVREG14, 16, 7, DEF_DIVFLAG, 40), + SG2042_DIV_FW(DIV_CLK_FPLL_TX_ETH0, "clk_div_tx_eth0", "fpll", + R_CLKDIVREG16, 16, 11, DEF_DIVFLAG, 8), + SG2042_DIV_FW(DIV_CLK_FPLL_PTP_REF_I_ETH0, + "clk_div_ptp_ref_i_eth0", "fpll", + R_CLKDIVREG17, 16, 8, DEF_DIVFLAG, 20), + SG2042_DIV_FW(DIV_CLK_FPLL_REF_ETH0, "clk_div_ref_eth0", "fpll", + R_CLKDIVREG18, 16, 8, DEF_DIVFLAG, 40), + SG2042_DIV_FW(DIV_CLK_FPLL_EMMC, "clk_div_emmc", "fpll", + R_CLKDIVREG19, 16, 5, DEF_DIVFLAG, 10), + SG2042_DIV_FW(DIV_CLK_FPLL_SD, "clk_div_sd", "fpll", + R_CLKDIVREG21, 16, 5, DEF_DIVFLAG, 10), + + SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI0, "clk_div_top_axi0", "fpll", + R_CLKDIVREG23, 16, 5, DEF_DIVFLAG, 10), + /* downstream of div_top_axi0 */ + SG2042_DIV_HW(DIV_CLK_FPLL_100K_EMMC, "clk_div_100k_emmc", clk_div_top_axi0, + R_CLKDIVREG20, 16, 16, DEF_DIVFLAG, 1000), + SG2042_DIV_HW(DIV_CLK_FPLL_100K_SD, "clk_div_100k_sd", clk_div_top_axi0, + R_CLKDIVREG22, 16, 16, DEF_DIVFLAG, 1000), + SG2042_DIV_HW(DIV_CLK_FPLL_GPIO_DB, "clk_div_gpio_db", clk_div_top_axi0, + R_CLKDIVREG15, 16, 16, DEF_DIVFLAG, 1000), + + SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI_HSPERI, + "clk_div_top_axi_hsperi", "fpll", + R_CLKDIVREG24, 16, 5, DEF_DIVFLAG, 4), +}; + +/* Gate clocks to be updated during probe/registration */ +static const struct clk_hw *clk_gate_rp_cpu_normal[] = { NULL }; +static const struct clk_hw *clk_gate_top_rp_cmn_div2[] = { NULL }; + +static const struct sg2042_gate_clock sg2042_gate_clks_level_2[] = { + SG2042_GATE_HWS(GATE_CLK_DDR01, "clk_gate_ddr01", clk_mux_ddr01, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 14), + + SG2042_GATE_HWS(GATE_CLK_DDR23, "clk_gate_ddr23", clk_mux_ddr23, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 15), + + SG2042_GATE_HWS(GATE_CLK_RP_CPU_NORMAL, + "clk_gate_rp_cpu_normal", clk_mux_rp_cpu_normal, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG0, 0), + + SG2042_GATE_HWS(GATE_CLK_AXI_DDR, "clk_gate_axi_ddr", clk_mux_axi_ddr, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 13), + + /* upon are gate clocks directly downstream of muxes */ + + /* downstream of clk_div_top_rp_cmn_div2 */ + SG2042_GATE_HW(GATE_CLK_TOP_RP_CMN_DIV2, + "clk_gate_top_rp_cmn_div2", clk_div_top_rp_cmn_div2, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 2), + SG2042_GATE_HWS(GATE_CLK_HSDMA, "clk_gate_hsdma", clk_gate_top_rp_cmn_div2, + CLK_SET_RATE_PARENT, R_CLKENREG1, 10), + + /* + * downstream of clk_gate_rp_cpu_normal + * + * FIXME: there should be one 1/2 DIV between clk_gate_rp_cpu_normal + * and clk_gate_axi_pcie0/clk_gate_axi_pcie1. + * But the 1/2 DIV is fixed and no configurable register exported, so + * when reading from these two clocks, the rate value are still the + * same as that of clk_gate_rp_cpu_normal, it's not correct. + * This just affects the value read. + */ + SG2042_GATE_HWS(GATE_CLK_AXI_PCIE0, + "clk_gate_axi_pcie0", clk_gate_rp_cpu_normal, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 8), + SG2042_GATE_HWS(GATE_CLK_AXI_PCIE1, + "clk_gate_axi_pcie1", clk_gate_rp_cpu_normal, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 9), + + /* downstream of div_50m_a53 */ + SG2042_GATE_HW(GATE_CLK_A53_50M, "clk_gate_a53_50m", clk_div_50m_a53, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 1), + SG2042_GATE_HW(GATE_CLK_TIMER1, "clk_gate_timer1", clk_div_timer1, + CLK_SET_RATE_PARENT, R_CLKENREG0, 12), + SG2042_GATE_HW(GATE_CLK_TIMER2, "clk_gate_timer2", clk_div_timer2, + CLK_SET_RATE_PARENT, R_CLKENREG0, 13), + SG2042_GATE_HW(GATE_CLK_TIMER3, "clk_gate_timer3", clk_div_timer3, + CLK_SET_RATE_PARENT, R_CLKENREG0, 14), + SG2042_GATE_HW(GATE_CLK_TIMER4, "clk_gate_timer4", clk_div_timer4, + CLK_SET_RATE_PARENT, R_CLKENREG0, 15), + SG2042_GATE_HW(GATE_CLK_TIMER5, "clk_gate_timer5", clk_div_timer5, + CLK_SET_RATE_PARENT, R_CLKENREG0, 16), + SG2042_GATE_HW(GATE_CLK_TIMER6, "clk_gate_timer6", clk_div_timer6, + CLK_SET_RATE_PARENT, R_CLKENREG0, 17), + SG2042_GATE_HW(GATE_CLK_TIMER7, "clk_gate_timer7", clk_div_timer7, + CLK_SET_RATE_PARENT, R_CLKENREG0, 18), + SG2042_GATE_HW(GATE_CLK_TIMER8, "clk_gate_timer8", clk_div_timer8, + CLK_SET_RATE_PARENT, R_CLKENREG0, 19), + + /* gate clocks downstream from div clocks one-to-one */ + SG2042_GATE_HW(GATE_CLK_UART_500M, "clk_gate_uart_500m", clk_div_uart_500m, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 4), + SG2042_GATE_HW(GATE_CLK_AHB_LPC, "clk_gate_ahb_lpc", clk_div_ahb_lpc, + CLK_SET_RATE_PARENT, R_CLKENREG0, 7), + SG2042_GATE_HW(GATE_CLK_EFUSE, "clk_gate_efuse", clk_div_efuse, + CLK_SET_RATE_PARENT, R_CLKENREG0, 20), + SG2042_GATE_HW(GATE_CLK_TX_ETH0, "clk_gate_tx_eth0", clk_div_tx_eth0, + CLK_SET_RATE_PARENT, R_CLKENREG0, 30), + SG2042_GATE_HW(GATE_CLK_PTP_REF_I_ETH0, + "clk_gate_ptp_ref_i_eth0", clk_div_ptp_ref_i_eth0, + CLK_SET_RATE_PARENT, R_CLKENREG1, 0), + SG2042_GATE_HW(GATE_CLK_REF_ETH0, "clk_gate_ref_eth0", clk_div_ref_eth0, + CLK_SET_RATE_PARENT, R_CLKENREG1, 1), + SG2042_GATE_HW(GATE_CLK_EMMC_100M, "clk_gate_emmc", clk_div_emmc, + CLK_SET_RATE_PARENT, R_CLKENREG1, 3), + SG2042_GATE_HW(GATE_CLK_SD_100M, "clk_gate_sd", clk_div_sd, + CLK_SET_RATE_PARENT, R_CLKENREG1, 6), + + /* downstream of clk_div_top_axi0 */ + SG2042_GATE_HW(GATE_CLK_AHB_ROM, "clk_gate_ahb_rom", clk_div_top_axi0, + 0, R_CLKENREG0, 8), + SG2042_GATE_HW(GATE_CLK_AHB_SF, "clk_gate_ahb_sf", clk_div_top_axi0, + 0, R_CLKENREG0, 9), + SG2042_GATE_HW(GATE_CLK_AXI_SRAM, "clk_gate_axi_sram", clk_div_top_axi0, + CLK_IGNORE_UNUSED, R_CLKENREG0, 10), + SG2042_GATE_HW(GATE_CLK_APB_TIMER, "clk_gate_apb_timer", clk_div_top_axi0, + CLK_IGNORE_UNUSED, R_CLKENREG0, 11), + SG2042_GATE_HW(GATE_CLK_APB_EFUSE, "clk_gate_apb_efuse", clk_div_top_axi0, + 0, R_CLKENREG0, 21), + SG2042_GATE_HW(GATE_CLK_APB_GPIO, "clk_gate_apb_gpio", clk_div_top_axi0, + 0, R_CLKENREG0, 22), + SG2042_GATE_HW(GATE_CLK_APB_GPIO_INTR, + "clk_gate_apb_gpio_intr", clk_div_top_axi0, + CLK_IS_CRITICAL, R_CLKENREG0, 23), + SG2042_GATE_HW(GATE_CLK_APB_I2C, "clk_gate_apb_i2c", clk_div_top_axi0, + 0, R_CLKENREG0, 26), + SG2042_GATE_HW(GATE_CLK_APB_WDT, "clk_gate_apb_wdt", clk_div_top_axi0, + 0, R_CLKENREG0, 27), + SG2042_GATE_HW(GATE_CLK_APB_PWM, "clk_gate_apb_pwm", clk_div_top_axi0, + 0, R_CLKENREG0, 28), + SG2042_GATE_HW(GATE_CLK_APB_RTC, "clk_gate_apb_rtc", clk_div_top_axi0, + 0, R_CLKENREG0, 29), + SG2042_GATE_HW(GATE_CLK_TOP_AXI0, "clk_gate_top_axi0", clk_div_top_axi0, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 11), + /* downstream of DIV clocks which are sourced from clk_div_top_axi0 */ + SG2042_GATE_HW(GATE_CLK_GPIO_DB, "clk_gate_gpio_db", clk_div_gpio_db, + CLK_SET_RATE_PARENT, R_CLKENREG0, 24), + SG2042_GATE_HW(GATE_CLK_100K_EMMC, "clk_gate_100k_emmc", clk_div_100k_emmc, + CLK_SET_RATE_PARENT, R_CLKENREG1, 4), + SG2042_GATE_HW(GATE_CLK_100K_SD, "clk_gate_100k_sd", clk_div_100k_sd, + CLK_SET_RATE_PARENT, R_CLKENREG1, 7), + + /* downstream of clk_div_top_axi_hsperi */ + SG2042_GATE_HW(GATE_CLK_SYSDMA_AXI, + "clk_gate_sysdma_axi", clk_div_top_axi_hsperi, + CLK_SET_RATE_PARENT, R_CLKENREG0, 3), + SG2042_GATE_HW(GATE_CLK_APB_UART, + "clk_gate_apb_uart", clk_div_top_axi_hsperi, + CLK_SET_RATE_PARENT, R_CLKENREG0, 5), + SG2042_GATE_HW(GATE_CLK_AXI_DBG_I2C, + "clk_gate_axi_dbg_i2c", clk_div_top_axi_hsperi, + CLK_SET_RATE_PARENT, R_CLKENREG0, 6), + SG2042_GATE_HW(GATE_CLK_APB_SPI, + "clk_gate_apb_spi", clk_div_top_axi_hsperi, + CLK_SET_RATE_PARENT, R_CLKENREG0, 25), + SG2042_GATE_HW(GATE_CLK_AXI_ETH0, + "clk_gate_axi_eth0", clk_div_top_axi_hsperi, + CLK_SET_RATE_PARENT, R_CLKENREG0, 31), + SG2042_GATE_HW(GATE_CLK_AXI_EMMC, + "clk_gate_axi_emmc", clk_div_top_axi_hsperi, + CLK_SET_RATE_PARENT, R_CLKENREG1, 2), + SG2042_GATE_HW(GATE_CLK_AXI_SD, + "clk_gate_axi_sd", clk_div_top_axi_hsperi, + CLK_SET_RATE_PARENT, R_CLKENREG1, 5), + SG2042_GATE_HW(GATE_CLK_TOP_AXI_HSPERI, + "clk_gate_top_axi_hsperi", clk_div_top_axi_hsperi, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + R_CLKENREG1, 12), +}; + +static DEFINE_SPINLOCK(sg2042_clk_lock); + +static int sg2042_clk_register_divs(struct device *dev, + struct sg2042_clk_data *clk_data, + struct sg2042_divider_clock div_clks[], + int num_div_clks) +{ + struct sg2042_divider_clock *div; + struct clk_hw *hw; + int i, ret = 0; + + for (i = 0; i < num_div_clks; i++) { + div = &div_clks[i]; + + if (div->div_flags & CLK_DIVIDER_HIWORD_MASK) { + if (div->width + div->shift > 16) { + pr_warn("divider value exceeds LOWORD field\n"); + ret = -EINVAL; + break; + } + } + + div->reg = clk_data->iobase + div->offset_ctrl; + div->lock = &sg2042_clk_lock; + + hw = &div->hw; + ret = devm_clk_hw_register(dev, hw); + if (ret) { + pr_err("failed to register clock %s\n", div->hw.init->name); + break; + } + + clk_data->onecell_data.hws[div->id] = hw; + } + + return ret; +} + +static int sg2042_clk_register_gates(struct device *dev, + struct sg2042_clk_data *clk_data, + const struct sg2042_gate_clock gate_clks[], + int num_gate_clks) +{ + const struct sg2042_gate_clock *gate; + struct clk_hw *hw; + int i, ret = 0; + + for (i = 0; i < num_gate_clks; i++) { + gate = &gate_clks[i]; + hw = __devm_clk_hw_register_gate + (dev, + NULL, + gate->hw.init->name, + NULL, + gate->hw.init->parent_hws[0], + NULL, + gate->hw.init->flags, + clk_data->iobase + gate->offset_enable, + gate->bit_idx, + 0, + &sg2042_clk_lock); + if (IS_ERR(hw)) { + pr_err("failed to register clock %s\n", gate->hw.init->name); + ret = PTR_ERR(hw); + break; + } + + clk_data->onecell_data.hws[gate->id] = hw; + + /* Updated some clocks which take the role of parent */ + switch (gate->id) { + case GATE_CLK_RP_CPU_NORMAL: + *clk_gate_rp_cpu_normal = hw; + break; + case GATE_CLK_TOP_RP_CMN_DIV2: + *clk_gate_top_rp_cmn_div2 = hw; + break; + } + } + + return ret; +} + +static int sg2042_clk_register_gates_fw(struct device *dev, + struct sg2042_clk_data *clk_data, + const struct sg2042_gate_clock gate_clks[], + int num_gate_clks) +{ + const struct sg2042_gate_clock *gate; + struct clk_hw *hw; + int i, ret = 0; + + for (i = 0; i < num_gate_clks; i++) { + gate = &gate_clks[i]; + hw = devm_clk_hw_register_gate_parent_data + (dev, + gate->hw.init->name, + gate->hw.init->parent_data, + gate->hw.init->flags, + clk_data->iobase + gate->offset_enable, + gate->bit_idx, + 0, + &sg2042_clk_lock); + if (IS_ERR(hw)) { + pr_err("failed to register clock %s\n", gate->hw.init->name); + ret = PTR_ERR(hw); + break; + } + + clk_data->onecell_data.hws[gate->id] = hw; + + /* Updated some clocks which take the role of parent */ + switch (gate->id) { + case GATE_CLK_DDR01_DIV0: + *clk_gate_ddr01_div0 = hw; + break; + case GATE_CLK_DDR01_DIV1: + *clk_gate_ddr01_div1 = hw; + break; + case GATE_CLK_DDR23_DIV0: + *clk_gate_ddr23_div0 = hw; + break; + case GATE_CLK_DDR23_DIV1: + *clk_gate_ddr23_div1 = hw; + break; + case GATE_CLK_RP_CPU_NORMAL_DIV0: + *clk_gate_rp_cpu_normal_div0 = hw; + break; + case GATE_CLK_RP_CPU_NORMAL_DIV1: + *clk_gate_rp_cpu_normal_div1 = hw; + break; + case GATE_CLK_AXI_DDR_DIV0: + *clk_gate_axi_ddr_div0 = hw; + break; + case GATE_CLK_AXI_DDR_DIV1: + *clk_gate_axi_ddr_div1 = hw; + break; + } + } + + return ret; +} + +static int sg2042_mux_notifier_cb(struct notifier_block *nb, + unsigned long event, + void *data) +{ + struct sg2042_mux_clock *mux = to_sg2042_mux_nb(nb); + const struct clk_ops *ops = &clk_mux_ops; + struct clk_notifier_data *ndata = data; + struct clk_hw *hw; + int ret = 0; + + hw = __clk_get_hw(ndata->clk); + + /* To switch to fpll before changing rate and restore after that */ + if (event == PRE_RATE_CHANGE) { + mux->original_index = ops->get_parent(hw); + + /* + * "1" is the array index of the second parent input source of + * mux. For SG2042, it's fpll for all mux clocks. + * "0" is the array index of the frist parent input source of + * mux, For SG2042, it's mpll. + * FIXME, any good idea to avoid magic number? + */ + if (mux->original_index == 0) + ret = ops->set_parent(hw, 1); + } else if (event == POST_RATE_CHANGE) { + ret = ops->set_parent(hw, mux->original_index); + } + + return notifier_from_errno(ret); +} + +static int sg2042_clk_register_muxs(struct device *dev, + struct sg2042_clk_data *clk_data, + struct sg2042_mux_clock mux_clks[], + int num_mux_clks) +{ + struct sg2042_mux_clock *mux; + struct clk_hw *hw; + int i, ret = 0; + + for (i = 0; i < num_mux_clks; i++) { + mux = &mux_clks[i]; + + hw = __devm_clk_hw_register_mux + (dev, + NULL, + mux->hw.init->name, + mux->hw.init->num_parents, + NULL, + mux->hw.init->parent_hws, + NULL, + mux->hw.init->flags, + clk_data->iobase + mux->offset_select, + mux->shift, + BIT(mux->width) - 1, + 0, + sg2042_mux_table, + &sg2042_clk_lock); + if (IS_ERR(hw)) { + pr_err("failed to register clock %s\n", mux->hw.init->name); + ret = PTR_ERR(hw); + break; + } + + clk_data->onecell_data.hws[mux->id] = hw; + + /* Updated some clocks which takes the role of parent */ + switch (mux->id) { + case MUX_CLK_DDR01: + *clk_mux_ddr01 = hw; + break; + case MUX_CLK_DDR23: + *clk_mux_ddr23 = hw; + break; + case MUX_CLK_RP_CPU_NORMAL: + *clk_mux_rp_cpu_normal = hw; + break; + case MUX_CLK_AXI_DDR: + *clk_mux_axi_ddr = hw; + break; + } + + /* + * FIXME: Theoretically, we should set parent for the + * mux, but seems hardware has done this for us with + * default value, so we don't set parent again here. + */ + + if (!(mux->hw.init->flags & CLK_MUX_READ_ONLY)) { + mux->clk_nb.notifier_call = sg2042_mux_notifier_cb; + ret = devm_clk_notifier_register(dev, hw->clk, &mux->clk_nb); + if (ret) { + pr_err("failed to register clock notifier for %s\n", + mux->hw.init->name); + break; + } + } + } + + return ret; +} + +static int sg2042_init_clkdata(struct platform_device *pdev, + int num_clks, + struct sg2042_clk_data **pp_clk_data) +{ + struct sg2042_clk_data *clk_data = NULL; + + clk_data = devm_kzalloc(&pdev->dev, + struct_size(clk_data, onecell_data.hws, num_clks), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->iobase = devm_platform_ioremap_resource(pdev, 0); + if (WARN_ON(IS_ERR(clk_data->iobase))) + return PTR_ERR(clk_data->iobase); + + clk_data->onecell_data.num = num_clks; + + *pp_clk_data = clk_data; + + return 0; +} + +static int sg2042_clkgen_probe(struct platform_device *pdev) +{ + struct sg2042_clk_data *clk_data = NULL; + int num_clks; + int ret; + + num_clks = ARRAY_SIZE(sg2042_div_clks_level_1) + + ARRAY_SIZE(sg2042_div_clks_level_2) + + ARRAY_SIZE(sg2042_gate_clks_level_1) + + ARRAY_SIZE(sg2042_gate_clks_level_2) + + ARRAY_SIZE(sg2042_mux_clks); + + ret = sg2042_init_clkdata(pdev, num_clks, &clk_data); + if (ret) + goto error_out; + + /* level-1 gates */ + ret = sg2042_clk_register_gates_fw(&pdev->dev, clk_data, + sg2042_gate_clks_level_1, + ARRAY_SIZE(sg2042_gate_clks_level_1)); + if (ret) + goto error_out; + + /* level-1 div */ + ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_1, + ARRAY_SIZE(sg2042_div_clks_level_1)); + if (ret) + goto error_out; + + /* mux */ + ret = sg2042_clk_register_muxs(&pdev->dev, clk_data, sg2042_mux_clks, + ARRAY_SIZE(sg2042_mux_clks)); + if (ret) + goto error_out; + + /* level 2 div */ + ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_2, + ARRAY_SIZE(sg2042_div_clks_level_2)); + if (ret) + goto error_out; + + /* level 2 gate */ + ret = sg2042_clk_register_gates(&pdev->dev, clk_data, sg2042_gate_clks_level_2, + ARRAY_SIZE(sg2042_gate_clks_level_2)); + if (ret) + goto error_out; + + return devm_of_clk_add_hw_provider(&pdev->dev, + of_clk_hw_onecell_get, + &clk_data->onecell_data); + +error_out: + pr_err("%s failed error number %d\n", __func__, ret); + return ret; +} + +static const struct of_device_id sg2042_clkgen_match[] = { + { .compatible = "sophgo,sg2042-clkgen" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sg2042_clkgen_match); + +static struct platform_driver sg2042_clkgen_driver = { + .probe = sg2042_clkgen_probe, + .driver = { + .name = "clk-sophgo-sg2042-clkgen", + .of_match_table = sg2042_clkgen_match, + .suppress_bind_attrs = true, + }, +}; +module_platform_driver(sg2042_clkgen_driver); + +MODULE_AUTHOR("Chen Wang"); +MODULE_DESCRIPTION("Sophgo SG2042 clock generator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/sophgo/clk-sg2042-pll.c b/drivers/clk/sophgo/clk-sg2042-pll.c new file mode 100644 index 000000000000..e202781a50bb --- /dev/null +++ b/drivers/clk/sophgo/clk-sg2042-pll.c @@ -0,0 +1,569 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sophgo SG2042 PLL clock Driver + * + * Copyright (C) 2024 Sophgo Technology Inc. + * Copyright (C) 2024 Chen Wang + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-sg2042.h" + +/* Registers defined in SYS_CTRL */ +#define R_PLL_BEGIN 0xC0 +#define R_PLL_STAT (0xC0 - R_PLL_BEGIN) +#define R_PLL_CLKEN_CONTROL (0xC4 - R_PLL_BEGIN) +#define R_MPLL_CONTROL (0xE8 - R_PLL_BEGIN) +#define R_FPLL_CONTROL (0xF4 - R_PLL_BEGIN) +#define R_DPLL0_CONTROL (0xF8 - R_PLL_BEGIN) +#define R_DPLL1_CONTROL (0xFC - R_PLL_BEGIN) + +/** + * struct sg2042_pll_clock - PLL clock + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @base: used for readl/writel. + * **NOTE**: PLL registers are all in SYS_CTRL! + * @lock: spinlock to protect register access, modification + * of frequency can only be served one at the time. + * @offset_ctrl: offset of pll control registers + * @shift_status_lock: shift of XXX_LOCK in pll status register + * @shift_status_updating: shift of UPDATING_XXX in pll status register + * @shift_enable: shift of XXX_CLK_EN in pll enable register + */ +struct sg2042_pll_clock { + struct clk_hw hw; + + unsigned int id; + void __iomem *base; + /* protect register access */ + spinlock_t *lock; + + u32 offset_ctrl; + u8 shift_status_lock; + u8 shift_status_updating; + u8 shift_enable; +}; + +#define to_sg2042_pll_clk(_hw) container_of(_hw, struct sg2042_pll_clock, hw) + +#define KHZ 1000UL +#define MHZ (KHZ * KHZ) + +#define REFDIV_MIN 1 +#define REFDIV_MAX 63 +#define FBDIV_MIN 16 +#define FBDIV_MAX 320 + +#define PLL_FREF_SG2042 (25 * MHZ) + +#define PLL_FOUTPOSTDIV_MIN (16 * MHZ) +#define PLL_FOUTPOSTDIV_MAX (3200 * MHZ) + +#define PLL_FOUTVCO_MIN (800 * MHZ) +#define PLL_FOUTVCO_MAX (3200 * MHZ) + +struct sg2042_pll_ctrl { + unsigned long freq; + unsigned int fbdiv; + unsigned int postdiv1; + unsigned int postdiv2; + unsigned int refdiv; +}; + +#define PLLCTRL_FBDIV_MASK GENMASK(27, 16) +#define PLLCTRL_POSTDIV2_MASK GENMASK(14, 12) +#define PLLCTRL_POSTDIV1_MASK GENMASK(10, 8) +#define PLLCTRL_REFDIV_MASK GENMASK(5, 0) + +static inline u32 sg2042_pll_ctrl_encode(struct sg2042_pll_ctrl *ctrl) +{ + return FIELD_PREP(PLLCTRL_FBDIV_MASK, ctrl->fbdiv) | + FIELD_PREP(PLLCTRL_POSTDIV2_MASK, ctrl->postdiv2) | + FIELD_PREP(PLLCTRL_POSTDIV1_MASK, ctrl->postdiv1) | + FIELD_PREP(PLLCTRL_REFDIV_MASK, ctrl->refdiv); +} + +static inline void sg2042_pll_ctrl_decode(unsigned int reg_value, + struct sg2042_pll_ctrl *ctrl) +{ + ctrl->fbdiv = FIELD_GET(PLLCTRL_FBDIV_MASK, reg_value); + ctrl->refdiv = FIELD_GET(PLLCTRL_REFDIV_MASK, reg_value); + ctrl->postdiv1 = FIELD_GET(PLLCTRL_POSTDIV1_MASK, reg_value); + ctrl->postdiv2 = FIELD_GET(PLLCTRL_POSTDIV2_MASK, reg_value); +} + +static inline int sg2042_pll_enable(struct sg2042_pll_clock *pll, bool en) +{ + u32 value; + + if (en) { + /* wait pll lock */ + if (readl_poll_timeout_atomic(pll->base + R_PLL_STAT, + value, + ((value >> pll->shift_status_lock) & 0x1), + 0, + 100000)) + pr_warn("%s not locked\n", pll->hw.init->name); + + /* wait pll updating */ + if (readl_poll_timeout_atomic(pll->base + R_PLL_STAT, + value, + !((value >> pll->shift_status_updating) & 0x1), + 0, + 100000)) + pr_warn("%s still updating\n", pll->hw.init->name); + + /* enable pll */ + value = readl(pll->base + R_PLL_CLKEN_CONTROL); + writel(value | (1 << pll->shift_enable), pll->base + R_PLL_CLKEN_CONTROL); + } else { + /* disable pll */ + value = readl(pll->base + R_PLL_CLKEN_CONTROL); + writel(value & (~(1 << pll->shift_enable)), pll->base + R_PLL_CLKEN_CONTROL); + } + + return 0; +} + +/** + * sg2042_pll_recalc_rate() - Calculate rate for plls + * @reg_value: current register value + * @parent_rate: parent frequency + * + * This function is used to calculate below "rate" in equation + * rate = (parent_rate/REFDIV) x FBDIV/POSTDIV1/POSTDIV2 + * = (parent_rate x FBDIV) / (REFDIV x POSTDIV1 x POSTDIV2) + * + * Return: The rate calculated. + */ +static unsigned long sg2042_pll_recalc_rate(unsigned int reg_value, + unsigned long parent_rate) +{ + struct sg2042_pll_ctrl ctrl_table; + u64 numerator, denominator; + + sg2042_pll_ctrl_decode(reg_value, &ctrl_table); + + numerator = parent_rate * ctrl_table.fbdiv; + denominator = ctrl_table.refdiv * ctrl_table.postdiv1 * ctrl_table.postdiv2; + do_div(numerator, denominator); + return numerator; +} + +/** + * sg2042_pll_get_postdiv_1_2() - Based on input rate/prate/fbdiv/refdiv, + * look up the postdiv1_2 table to get the closest postdiiv combination. + * @rate: FOUTPOSTDIV + * @prate: parent rate, i.e. FREF + * @fbdiv: FBDIV + * @refdiv: REFDIV + * @postdiv1: POSTDIV1, output + * @postdiv2: POSTDIV2, output + * + * postdiv1_2 contains all the possible combination lists of POSTDIV1 and POSTDIV2 + * for example: + * postdiv1_2[0] = {2, 4, 8}, where div1 = 2, div2 = 4 , div1 * div2 = 8 + * + * See TRM: + * FOUTPOSTDIV = FREF * FBDIV / REFDIV / (POSTDIV1 * POSTDIV2) + * So we get following formula to get POSTDIV1 and POSTDIV2: + * POSTDIV = (prate/REFDIV) x FBDIV/rate + * above POSTDIV = POSTDIV1*POSTDIV2 + * + * Return: + * %0 - OK + * %-EINVAL - invalid argument, which means Failed to get the postdivs. + */ +static int sg2042_pll_get_postdiv_1_2(unsigned long rate, + unsigned long prate, + unsigned int fbdiv, + unsigned int refdiv, + unsigned int *postdiv1, + unsigned int *postdiv2) +{ + int index; + u64 tmp0; + + /* POSTDIV_RESULT_INDEX point to 3rd element in the array postdiv1_2 */ + #define POSTDIV_RESULT_INDEX 2 + + static const int postdiv1_2[][3] = { + {2, 4, 8}, {3, 3, 9}, {2, 5, 10}, {2, 6, 12}, + {2, 7, 14}, {3, 5, 15}, {4, 4, 16}, {3, 6, 18}, + {4, 5, 20}, {3, 7, 21}, {4, 6, 24}, {5, 5, 25}, + {4, 7, 28}, {5, 6, 30}, {5, 7, 35}, {6, 6, 36}, + {6, 7, 42}, {7, 7, 49} + }; + + /* prate/REFDIV and result save to tmp0 */ + tmp0 = prate; + do_div(tmp0, refdiv); + + /* ((prate/REFDIV) x FBDIV) and result save to tmp0 */ + tmp0 *= fbdiv; + + /* ((prate/REFDIV) x FBDIV)/rate and result save to tmp0 */ + do_div(tmp0, rate); + + /* tmp0 is POSTDIV1*POSTDIV2, now we calculate div1 and div2 value */ + if (tmp0 <= 7) { + /* (div1 * div2) <= 7, no need to use array search */ + *postdiv1 = tmp0; + *postdiv2 = 1; + return 0; + } + + /* (div1 * div2) > 7, use array search */ + for (index = 0; index < ARRAY_SIZE(postdiv1_2); index++) { + if (tmp0 > postdiv1_2[index][POSTDIV_RESULT_INDEX]) { + continue; + } else { + /* found it */ + *postdiv1 = postdiv1_2[index][1]; + *postdiv2 = postdiv1_2[index][0]; + return 0; + } + } + pr_warn("%s can not find in postdiv array!\n", __func__); + return -EINVAL; +} + +/** + * sg2042_get_pll_ctl_setting() - Based on the given FOUTPISTDIV and the input + * FREF to calculate the REFDIV/FBDIV/PSTDIV1/POSTDIV2 combination for pllctrl + * register. + * @req_rate: expected output clock rate, i.e. FOUTPISTDIV + * @parent_rate: input parent clock rate, i.e. FREF + * @best: output to hold calculated combination of REFDIV/FBDIV/PSTDIV1/POSTDIV2 + * + * Return: + * %0 - OK + * %-EINVAL - invalid argument + */ +static int sg2042_get_pll_ctl_setting(struct sg2042_pll_ctrl *best, + unsigned long req_rate, + unsigned long parent_rate) +{ + unsigned int fbdiv, refdiv, postdiv1, postdiv2; + unsigned long foutpostdiv; + u64 foutvco; + int ret; + u64 tmp; + + if (parent_rate != PLL_FREF_SG2042) { + pr_err("INVALID FREF: %ld\n", parent_rate); + return -EINVAL; + } + + if (req_rate < PLL_FOUTPOSTDIV_MIN || req_rate > PLL_FOUTPOSTDIV_MAX) { + pr_alert("INVALID FOUTPOSTDIV: %ld\n", req_rate); + return -EINVAL; + } + + memset(best, 0, sizeof(struct sg2042_pll_ctrl)); + + for (refdiv = REFDIV_MIN; refdiv < REFDIV_MAX + 1; refdiv++) { + /* required by hardware: FREF/REFDIV must > 10 */ + tmp = parent_rate; + do_div(tmp, refdiv); + if (tmp <= 10) + continue; + + for (fbdiv = FBDIV_MIN; fbdiv < FBDIV_MAX + 1; fbdiv++) { + /* + * FOUTVCO = FREF*FBDIV/REFDIV validation + * required by hardware, FOUTVCO must [800MHz, 3200MHz] + */ + foutvco = parent_rate * fbdiv; + do_div(foutvco, refdiv); + if (foutvco < PLL_FOUTVCO_MIN || foutvco > PLL_FOUTVCO_MAX) + continue; + + ret = sg2042_pll_get_postdiv_1_2(req_rate, parent_rate, + fbdiv, refdiv, + &postdiv1, &postdiv2); + if (ret) + continue; + + /* + * FOUTPOSTDIV = FREF*FBDIV/REFDIV/(POSTDIV1*POSTDIV2) + * = FOUTVCO/(POSTDIV1*POSTDIV2) + */ + tmp = foutvco; + do_div(tmp, (postdiv1 * postdiv2)); + foutpostdiv = (unsigned long)tmp; + /* Iterative to approach the expected value */ + if (abs_diff(foutpostdiv, req_rate) < abs_diff(best->freq, req_rate)) { + best->freq = foutpostdiv; + best->refdiv = refdiv; + best->fbdiv = fbdiv; + best->postdiv1 = postdiv1; + best->postdiv2 = postdiv2; + if (foutpostdiv == req_rate) + return 0; + } + continue; + } + } + + if (best->freq == 0) + return -EINVAL; + else + return 0; +} + +/** + * sg2042_clk_pll_recalc_rate() - recalc_rate callback for pll clks + * @hw: ccf use to hook get sg2042_pll_clock + * @parent_rate: parent rate + * + * The is function will be called through clk_get_rate + * and return current rate after decoding reg value + * + * Return: Current rate recalculated. + */ +static unsigned long sg2042_clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sg2042_pll_clock *pll = to_sg2042_pll_clk(hw); + unsigned long rate; + u32 value; + + value = readl(pll->base + pll->offset_ctrl); + rate = sg2042_pll_recalc_rate(value, parent_rate); + + pr_debug("--> %s: pll_recalc_rate: val = %ld\n", + clk_hw_get_name(hw), rate); + return rate; +} + +static long sg2042_clk_pll_round_rate(struct clk_hw *hw, + unsigned long req_rate, + unsigned long *prate) +{ + struct sg2042_pll_ctrl pctrl_table; + unsigned int value; + long proper_rate; + int ret; + + ret = sg2042_get_pll_ctl_setting(&pctrl_table, req_rate, *prate); + if (ret) { + proper_rate = 0; + goto out; + } + + value = sg2042_pll_ctrl_encode(&pctrl_table); + proper_rate = (long)sg2042_pll_recalc_rate(value, *prate); + +out: + pr_debug("--> %s: pll_round_rate: val = %ld\n", + clk_hw_get_name(hw), proper_rate); + return proper_rate; +} + +static int sg2042_clk_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + req->rate = sg2042_clk_pll_round_rate(hw, min(req->rate, req->max_rate), + &req->best_parent_rate); + pr_debug("--> %s: pll_determine_rate: val = %ld\n", + clk_hw_get_name(hw), req->rate); + return 0; +} + +static int sg2042_clk_pll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct sg2042_pll_clock *pll = to_sg2042_pll_clk(hw); + struct sg2042_pll_ctrl pctrl_table; + unsigned long flags; + u32 value; + int ret; + + spin_lock_irqsave(pll->lock, flags); + if (sg2042_pll_enable(pll, 0)) { + pr_warn("Can't disable pll(%s), status error\n", pll->hw.init->name); + goto out; + } + ret = sg2042_get_pll_ctl_setting(&pctrl_table, rate, parent_rate); + if (ret) { + pr_warn("%s: Can't find a proper pll setting\n", pll->hw.init->name); + goto out2; + } + + value = sg2042_pll_ctrl_encode(&pctrl_table); + + /* write the value to top register */ + writel(value, pll->base + pll->offset_ctrl); + +out2: + sg2042_pll_enable(pll, 1); +out: + spin_unlock_irqrestore(pll->lock, flags); + + pr_debug("--> %s: pll_set_rate: val = 0x%x\n", + clk_hw_get_name(hw), value); + return ret; +} + +static const struct clk_ops sg2042_clk_pll_ops = { + .recalc_rate = sg2042_clk_pll_recalc_rate, + .round_rate = sg2042_clk_pll_round_rate, + .determine_rate = sg2042_clk_pll_determine_rate, + .set_rate = sg2042_clk_pll_set_rate, +}; + +static const struct clk_ops sg2042_clk_pll_ro_ops = { + .recalc_rate = sg2042_clk_pll_recalc_rate, + .round_rate = sg2042_clk_pll_round_rate, +}; + +/* + * Clock initialization macro naming rules: + * FW: use CLK_HW_INIT_FW_NAME + * RO: means Read-Only + */ +#define SG2042_PLL_FW(_id, _name, _parent, _r_ctrl, _shift) \ + { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_FW_NAME( \ + _name, \ + _parent, \ + &sg2042_clk_pll_ops, \ + CLK_GET_RATE_NOCACHE | CLK_GET_ACCURACY_NOCACHE),\ + .offset_ctrl = _r_ctrl, \ + .shift_status_lock = 8 + (_shift), \ + .shift_status_updating = _shift, \ + .shift_enable = _shift, \ + } + +#define SG2042_PLL_FW_RO(_id, _name, _parent, _r_ctrl, _shift) \ + { \ + .id = _id, \ + .hw.init = CLK_HW_INIT_FW_NAME( \ + _name, \ + _parent, \ + &sg2042_clk_pll_ro_ops, \ + CLK_GET_RATE_NOCACHE | CLK_GET_ACCURACY_NOCACHE),\ + .offset_ctrl = _r_ctrl, \ + .shift_status_lock = 8 + (_shift), \ + .shift_status_updating = _shift, \ + .shift_enable = _shift, \ + } + +static struct sg2042_pll_clock sg2042_pll_clks[] = { + SG2042_PLL_FW(MPLL_CLK, "mpll_clock", "cgi_main", R_MPLL_CONTROL, 0), + SG2042_PLL_FW_RO(FPLL_CLK, "fpll_clock", "cgi_main", R_FPLL_CONTROL, 3), + SG2042_PLL_FW_RO(DPLL0_CLK, "dpll0_clock", "cgi_dpll0", R_DPLL0_CONTROL, 4), + SG2042_PLL_FW_RO(DPLL1_CLK, "dpll1_clock", "cgi_dpll1", R_DPLL1_CONTROL, 5), +}; + +static DEFINE_SPINLOCK(sg2042_clk_lock); + +static int sg2042_clk_register_plls(struct device *dev, + struct sg2042_clk_data *clk_data, + struct sg2042_pll_clock pll_clks[], + int num_pll_clks) +{ + struct sg2042_pll_clock *pll; + struct clk_hw *hw; + int i, ret = 0; + + for (i = 0; i < num_pll_clks; i++) { + pll = &pll_clks[i]; + /* assign these for ops usage during registration */ + pll->base = clk_data->iobase; + pll->lock = &sg2042_clk_lock; + + hw = &pll->hw; + ret = devm_clk_hw_register(dev, hw); + if (ret) { + pr_err("failed to register clock %s\n", pll->hw.init->name); + break; + } + + clk_data->onecell_data.hws[pll->id] = hw; + } + + return ret; +} + +static int sg2042_init_clkdata(struct platform_device *pdev, + int num_clks, + struct sg2042_clk_data **pp_clk_data) +{ + struct sg2042_clk_data *clk_data; + + clk_data = devm_kzalloc(&pdev->dev, + struct_size(clk_data, onecell_data.hws, num_clks), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->iobase = devm_platform_ioremap_resource(pdev, 0); + if (WARN_ON(IS_ERR(clk_data->iobase))) + return PTR_ERR(clk_data->iobase); + + clk_data->onecell_data.num = num_clks; + + *pp_clk_data = clk_data; + + return 0; +} + +static int sg2042_pll_probe(struct platform_device *pdev) +{ + struct sg2042_clk_data *clk_data = NULL; + int num_clks; + int ret; + + num_clks = ARRAY_SIZE(sg2042_pll_clks); + + ret = sg2042_init_clkdata(pdev, num_clks, &clk_data); + if (ret) + goto error_out; + + ret = sg2042_clk_register_plls(&pdev->dev, clk_data, sg2042_pll_clks, + num_clks); + if (ret) + goto error_out; + + return devm_of_clk_add_hw_provider(&pdev->dev, + of_clk_hw_onecell_get, + &clk_data->onecell_data); + +error_out: + pr_err("%s failed error number %d\n", __func__, ret); + return ret; +} + +static const struct of_device_id sg2042_pll_match[] = { + { .compatible = "sophgo,sg2042-pll" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sg2042_pll_match); + +static struct platform_driver sg2042_pll_driver = { + .probe = sg2042_pll_probe, + .driver = { + .name = "clk-sophgo-sg2042-pll", + .of_match_table = sg2042_pll_match, + .suppress_bind_attrs = true, + }, +}; +module_platform_driver(sg2042_pll_driver); + +MODULE_AUTHOR("Chen Wang"); +MODULE_DESCRIPTION("Sophgo SG2042 pll clock driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/sophgo/clk-sg2042-rpgate.c b/drivers/clk/sophgo/clk-sg2042-rpgate.c new file mode 100644 index 000000000000..e02adc9a48e8 --- /dev/null +++ b/drivers/clk/sophgo/clk-sg2042-rpgate.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sophgo SG2042 RP clock Driver + * + * Copyright (C) 2024 Sophgo Technology Inc. + * Copyright (C) 2024 Chen Wang + */ + +#include +#include + +#include + +#include "clk-sg2042.h" + +#define R_SYSGATE_BEGIN 0x0368 +#define R_RP_RXU_CLK_ENABLE (0x0368 - R_SYSGATE_BEGIN) +#define R_MP0_STATUS_REG (0x0380 - R_SYSGATE_BEGIN) +#define R_MP0_CONTROL_REG (0x0384 - R_SYSGATE_BEGIN) +#define R_MP1_STATUS_REG (0x0388 - R_SYSGATE_BEGIN) +#define R_MP1_CONTROL_REG (0x038C - R_SYSGATE_BEGIN) +#define R_MP2_STATUS_REG (0x0390 - R_SYSGATE_BEGIN) +#define R_MP2_CONTROL_REG (0x0394 - R_SYSGATE_BEGIN) +#define R_MP3_STATUS_REG (0x0398 - R_SYSGATE_BEGIN) +#define R_MP3_CONTROL_REG (0x039C - R_SYSGATE_BEGIN) +#define R_MP4_STATUS_REG (0x03A0 - R_SYSGATE_BEGIN) +#define R_MP4_CONTROL_REG (0x03A4 - R_SYSGATE_BEGIN) +#define R_MP5_STATUS_REG (0x03A8 - R_SYSGATE_BEGIN) +#define R_MP5_CONTROL_REG (0x03AC - R_SYSGATE_BEGIN) +#define R_MP6_STATUS_REG (0x03B0 - R_SYSGATE_BEGIN) +#define R_MP6_CONTROL_REG (0x03B4 - R_SYSGATE_BEGIN) +#define R_MP7_STATUS_REG (0x03B8 - R_SYSGATE_BEGIN) +#define R_MP7_CONTROL_REG (0x03BC - R_SYSGATE_BEGIN) +#define R_MP8_STATUS_REG (0x03C0 - R_SYSGATE_BEGIN) +#define R_MP8_CONTROL_REG (0x03C4 - R_SYSGATE_BEGIN) +#define R_MP9_STATUS_REG (0x03C8 - R_SYSGATE_BEGIN) +#define R_MP9_CONTROL_REG (0x03CC - R_SYSGATE_BEGIN) +#define R_MP10_STATUS_REG (0x03D0 - R_SYSGATE_BEGIN) +#define R_MP10_CONTROL_REG (0x03D4 - R_SYSGATE_BEGIN) +#define R_MP11_STATUS_REG (0x03D8 - R_SYSGATE_BEGIN) +#define R_MP11_CONTROL_REG (0x03DC - R_SYSGATE_BEGIN) +#define R_MP12_STATUS_REG (0x03E0 - R_SYSGATE_BEGIN) +#define R_MP12_CONTROL_REG (0x03E4 - R_SYSGATE_BEGIN) +#define R_MP13_STATUS_REG (0x03E8 - R_SYSGATE_BEGIN) +#define R_MP13_CONTROL_REG (0x03EC - R_SYSGATE_BEGIN) +#define R_MP14_STATUS_REG (0x03F0 - R_SYSGATE_BEGIN) +#define R_MP14_CONTROL_REG (0x03F4 - R_SYSGATE_BEGIN) +#define R_MP15_STATUS_REG (0x03F8 - R_SYSGATE_BEGIN) +#define R_MP15_CONTROL_REG (0x03FC - R_SYSGATE_BEGIN) + +/** + * struct sg2042_rpgate_clock - Gate clock for RP(riscv processors) subsystem + * @hw: clk_hw for initialization + * @id: used to map clk_onecell_data + * @offset_enable: offset of gate enable registers + * @bit_idx: which bit in the register controls gating of this clock + */ +struct sg2042_rpgate_clock { + struct clk_hw hw; + + unsigned int id; + + u32 offset_enable; + u8 bit_idx; +}; + +/* + * Clock initialization macro naming rules: + * FW: use CLK_HW_INIT_FW_NAME + */ +#define SG2042_GATE_FW(_id, _name, _parent, _flags, \ + _r_enable, _bit_idx) { \ + .hw.init = CLK_HW_INIT_FW_NAME( \ + _name, \ + _parent, \ + NULL, \ + _flags), \ + .id = _id, \ + .offset_enable = _r_enable, \ + .bit_idx = _bit_idx, \ + } + +/* + * Gate clocks for RP subsystem (including the MP subsystem), which control + * registers are defined in SYS_CTRL. + */ +static const struct sg2042_rpgate_clock sg2042_gate_rp[] = { + /* downstream of clk_gate_rp_cpu_normal about rxu */ + SG2042_GATE_FW(GATE_CLK_RXU0, "clk_gate_rxu0", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 0), + SG2042_GATE_FW(GATE_CLK_RXU1, "clk_gate_rxu1", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 1), + SG2042_GATE_FW(GATE_CLK_RXU2, "clk_gate_rxu2", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 2), + SG2042_GATE_FW(GATE_CLK_RXU3, "clk_gate_rxu3", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 3), + SG2042_GATE_FW(GATE_CLK_RXU4, "clk_gate_rxu4", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 4), + SG2042_GATE_FW(GATE_CLK_RXU5, "clk_gate_rxu5", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 5), + SG2042_GATE_FW(GATE_CLK_RXU6, "clk_gate_rxu6", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 6), + SG2042_GATE_FW(GATE_CLK_RXU7, "clk_gate_rxu7", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 7), + SG2042_GATE_FW(GATE_CLK_RXU8, "clk_gate_rxu8", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 8), + SG2042_GATE_FW(GATE_CLK_RXU9, "clk_gate_rxu9", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 9), + SG2042_GATE_FW(GATE_CLK_RXU10, "clk_gate_rxu10", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 10), + SG2042_GATE_FW(GATE_CLK_RXU11, "clk_gate_rxu11", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 11), + SG2042_GATE_FW(GATE_CLK_RXU12, "clk_gate_rxu12", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 12), + SG2042_GATE_FW(GATE_CLK_RXU13, "clk_gate_rxu13", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 13), + SG2042_GATE_FW(GATE_CLK_RXU14, "clk_gate_rxu14", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 14), + SG2042_GATE_FW(GATE_CLK_RXU15, "clk_gate_rxu15", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 15), + SG2042_GATE_FW(GATE_CLK_RXU16, "clk_gate_rxu16", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 16), + SG2042_GATE_FW(GATE_CLK_RXU17, "clk_gate_rxu17", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 17), + SG2042_GATE_FW(GATE_CLK_RXU18, "clk_gate_rxu18", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 18), + SG2042_GATE_FW(GATE_CLK_RXU19, "clk_gate_rxu19", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 19), + SG2042_GATE_FW(GATE_CLK_RXU20, "clk_gate_rxu20", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 20), + SG2042_GATE_FW(GATE_CLK_RXU21, "clk_gate_rxu21", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 21), + SG2042_GATE_FW(GATE_CLK_RXU22, "clk_gate_rxu22", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 22), + SG2042_GATE_FW(GATE_CLK_RXU23, "clk_gate_rxu23", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 23), + SG2042_GATE_FW(GATE_CLK_RXU24, "clk_gate_rxu24", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 24), + SG2042_GATE_FW(GATE_CLK_RXU25, "clk_gate_rxu25", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 25), + SG2042_GATE_FW(GATE_CLK_RXU26, "clk_gate_rxu26", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 26), + SG2042_GATE_FW(GATE_CLK_RXU27, "clk_gate_rxu27", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 27), + SG2042_GATE_FW(GATE_CLK_RXU28, "clk_gate_rxu28", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 28), + SG2042_GATE_FW(GATE_CLK_RXU29, "clk_gate_rxu29", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 29), + SG2042_GATE_FW(GATE_CLK_RXU30, "clk_gate_rxu30", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 30), + SG2042_GATE_FW(GATE_CLK_RXU31, "clk_gate_rxu31", "rpgate", + 0, R_RP_RXU_CLK_ENABLE, 31), + + /* downstream of clk_gate_rp_cpu_normal about mp */ + SG2042_GATE_FW(GATE_CLK_MP0, "clk_gate_mp0", "rpgate", + CLK_IS_CRITICAL, R_MP0_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP1, "clk_gate_mp1", "rpgate", + CLK_IS_CRITICAL, R_MP1_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP2, "clk_gate_mp2", "rpgate", + CLK_IS_CRITICAL, R_MP2_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP3, "clk_gate_mp3", "rpgate", + CLK_IS_CRITICAL, R_MP3_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP4, "clk_gate_mp4", "rpgate", + CLK_IS_CRITICAL, R_MP4_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP5, "clk_gate_mp5", "rpgate", + CLK_IS_CRITICAL, R_MP5_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP6, "clk_gate_mp6", "rpgate", + CLK_IS_CRITICAL, R_MP6_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP7, "clk_gate_mp7", "rpgate", + CLK_IS_CRITICAL, R_MP7_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP8, "clk_gate_mp8", "rpgate", + CLK_IS_CRITICAL, R_MP8_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP9, "clk_gate_mp9", "rpgate", + CLK_IS_CRITICAL, R_MP9_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP10, "clk_gate_mp10", "rpgate", + CLK_IS_CRITICAL, R_MP10_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP11, "clk_gate_mp11", "rpgate", + CLK_IS_CRITICAL, R_MP11_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP12, "clk_gate_mp12", "rpgate", + CLK_IS_CRITICAL, R_MP12_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP13, "clk_gate_mp13", "rpgate", + CLK_IS_CRITICAL, R_MP13_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP14, "clk_gate_mp14", "rpgate", + CLK_IS_CRITICAL, R_MP14_CONTROL_REG, 0), + SG2042_GATE_FW(GATE_CLK_MP15, "clk_gate_mp15", "rpgate", + CLK_IS_CRITICAL, R_MP15_CONTROL_REG, 0), +}; + +static DEFINE_SPINLOCK(sg2042_clk_lock); + +static int sg2042_clk_register_rpgates(struct device *dev, + struct sg2042_clk_data *clk_data, + const struct sg2042_rpgate_clock gate_clks[], + int num_gate_clks) +{ + const struct sg2042_rpgate_clock *gate; + struct clk_hw *hw; + int i, ret = 0; + + for (i = 0; i < num_gate_clks; i++) { + gate = &gate_clks[i]; + hw = devm_clk_hw_register_gate_parent_data + (dev, + gate->hw.init->name, + gate->hw.init->parent_data, + gate->hw.init->flags, + clk_data->iobase + gate->offset_enable, + gate->bit_idx, + 0, + &sg2042_clk_lock); + if (IS_ERR(hw)) { + pr_err("failed to register clock %s\n", gate->hw.init->name); + ret = PTR_ERR(hw); + break; + } + + clk_data->onecell_data.hws[gate->id] = hw; + } + + return ret; +} + +static int sg2042_init_clkdata(struct platform_device *pdev, + int num_clks, + struct sg2042_clk_data **pp_clk_data) +{ + struct sg2042_clk_data *clk_data; + + clk_data = devm_kzalloc(&pdev->dev, + struct_size(clk_data, onecell_data.hws, num_clks), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->iobase = devm_platform_ioremap_resource(pdev, 0); + if (WARN_ON(IS_ERR(clk_data->iobase))) + return PTR_ERR(clk_data->iobase); + + clk_data->onecell_data.num = num_clks; + + *pp_clk_data = clk_data; + + return 0; +} + +static int sg2042_rpgate_probe(struct platform_device *pdev) +{ + struct sg2042_clk_data *clk_data = NULL; + int num_clks; + int ret; + + num_clks = ARRAY_SIZE(sg2042_gate_rp); + + ret = sg2042_init_clkdata(pdev, num_clks, &clk_data); + if (ret) + goto error_out; + + ret = sg2042_clk_register_rpgates(&pdev->dev, clk_data, sg2042_gate_rp, + num_clks); + if (ret) + goto error_out; + + return devm_of_clk_add_hw_provider(&pdev->dev, + of_clk_hw_onecell_get, + &clk_data->onecell_data); + +error_out: + pr_err("%s failed error number %d\n", __func__, ret); + return ret; +} + +static const struct of_device_id sg2042_rpgate_match[] = { + { .compatible = "sophgo,sg2042-rpgate" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, sg2042_rpgate_match); + +static struct platform_driver sg2042_rpgate_driver = { + .probe = sg2042_rpgate_probe, + .driver = { + .name = "clk-sophgo-sg2042-rpgate", + .of_match_table = sg2042_rpgate_match, + .suppress_bind_attrs = true, + }, +}; +module_platform_driver(sg2042_rpgate_driver); + +MODULE_AUTHOR("Chen Wang"); +MODULE_DESCRIPTION("Sophgo SG2042 rp subsystem clock driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/sophgo/clk-sg2042.h b/drivers/clk/sophgo/clk-sg2042.h new file mode 100644 index 000000000000..f13fed399c6e --- /dev/null +++ b/drivers/clk/sophgo/clk-sg2042.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _CLK_SOPHGO_SG2042_H_ +#define _CLK_SOPHGO_SG2042_H_ + +#include +#include + +/** + * struct sg2042_clk_data - Common data of clock-controller + * @iobase: base address of clock-controller + * @onecell_data: used for adding providers. + */ +struct sg2042_clk_data { + void __iomem *iobase; + struct clk_hw_onecell_data onecell_data; +}; + +#endif /* _CLK_SOPHGO_SG2042_H_ */ -- Gitee From 59279165d7b92244174e6bfbaa22dad2a9e55b07 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Thu, 6 Jun 2024 16:37:39 +0800 Subject: [PATCH 21/24] riscv: dts: add clock generator for Sophgo SG2042 SoC ANBZ: #20835 commit b1240a39511b9206293b82ac372c5114d6e15821 upstream. Add clock generator node to device tree for SG2042, and enable clock for uart. Signed-off-by: Chen Wang Reviewed-by: Guo Ren Link: https://lore.kernel.org/r/9ff7c8917a2125319316d59973a54ac12c311a19.1717661798.git.unicorn_wang@outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- .../boot/dts/sophgo/sg2042-milkv-pioneer.dts | 12 ++++ arch/riscv/boot/dts/sophgo/sg2042.dtsi | 55 ++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts index 49b4b9c2c101..80cb017974d8 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts +++ b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts @@ -14,6 +14,18 @@ chosen { }; }; +&cgi_main { + clock-frequency = <25000000>; +}; + +&cgi_dpll0 { + clock-frequency = <25000000>; +}; + +&cgi_dpll1 { + clock-frequency = <25000000>; +}; + &uart0 { status = "okay"; }; diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index 81fda312f988..34c802bd3f9b 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -4,8 +4,10 @@ */ /dts-v1/; +#include +#include +#include #include - #include #include "sg2042-cpus.dtsi" @@ -20,12 +22,60 @@ aliases { serial0 = &uart0; }; + cgi_main: oscillator0 { + compatible = "fixed-clock"; + clock-output-names = "cgi_main"; + #clock-cells = <0>; + }; + + cgi_dpll0: oscillator1 { + compatible = "fixed-clock"; + clock-output-names = "cgi_dpll0"; + #clock-cells = <0>; + }; + + cgi_dpll1: oscillator2 { + compatible = "fixed-clock"; + clock-output-names = "cgi_dpll1"; + #clock-cells = <0>; + }; + soc: soc { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; ranges; + pllclk: clock-controller@70300100c0 { + compatible = "sophgo,sg2042-pll"; + reg = <0x70 0x300100c0 0x0 0x40>; + clocks = <&cgi_main>, <&cgi_dpll0>, <&cgi_dpll1>; + clock-names = "cgi_main", "cgi_dpll0", "cgi_dpll1"; + #clock-cells = <1>; + }; + + rpgate: clock-controller@7030010368 { + compatible = "sophgo,sg2042-rpgate"; + reg = <0x70 0x30010368 0x0 0x98>; + clocks = <&clkgen GATE_CLK_RP_CPU_NORMAL>; + clock-names = "rpgate"; + #clock-cells = <1>; + }; + + clkgen: clock-controller@7030012000 { + compatible = "sophgo,sg2042-clkgen"; + reg = <0x70 0x30012000 0x0 0x1000>; + clocks = <&pllclk MPLL_CLK>, + <&pllclk FPLL_CLK>, + <&pllclk DPLL0_CLK>, + <&pllclk DPLL1_CLK>; + clock-names = "mpll", + "fpll", + "dpll0", + "dpll1"; + #clock-cells = <1>; + }; + clint_mswi: interrupt-controller@7094000000 { compatible = "sophgo,sg2042-aclint-mswi", "thead,c900-aclint-mswi"; reg = <0x00000070 0x94000000 0x00000000 0x00004000>; @@ -341,6 +391,9 @@ uart0: serial@7040000000 { interrupt-parent = <&intc>; interrupts = <112 IRQ_TYPE_LEVEL_HIGH>; clock-frequency = <500000000>; + clocks = <&clkgen GATE_CLK_UART_500M>, + <&clkgen GATE_CLK_APB_UART>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; resets = <&rstgen RST_UART0>; -- Gitee From eafc731d1bc1455d4eb6eaf29cc14acc60c09cf4 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Mon, 29 Jul 2024 10:13:33 +0800 Subject: [PATCH 22/24] riscv: dts: sophgo: Use common "interrupt-parent" for all peripherals for sg2042 ANBZ: #20835 commit 5d9e6bc82bd0705991fdcaea70cc3118efd0f2f2 upstream. As all peripherals of sg2042 share the same "interrupt-parent", there is no need to use peripherals specific "interrupt-parent". Define "interrupt-parent" in the SoC level. Signed-off-by: Inochi Amaoto Reviewed-by: Chen Wang Tested-by: Chen Wang Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/IA1PR20MB49531F6DFD2F116207C1397DBBB72@IA1PR20MB4953.namprd20.prod.outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/boot/dts/sophgo/sg2042.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index 34c802bd3f9b..c61d8061119d 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -44,6 +44,7 @@ soc: soc { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; + interrupt-parent = <&intc>; ranges; pllclk: clock-controller@70300100c0 { @@ -388,7 +389,6 @@ rstgen: reset-controller@7030013000 { uart0: serial@7040000000 { compatible = "snps,dw-apb-uart"; reg = <0x00000070 0x40000000 0x00000000 0x00001000>; - interrupt-parent = <&intc>; interrupts = <112 IRQ_TYPE_LEVEL_HIGH>; clock-frequency = <500000000>; clocks = <&clkgen GATE_CLK_UART_500M>, -- Gitee From 53d9f14379092a84b3c9e91981561e4647d30be7 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Mon, 29 Jul 2024 10:13:34 +0800 Subject: [PATCH 23/24] riscv: dts: sophgo: Add i2c device support for sg2042 ANBZ: #20835 commit c8eb04aecdd4df246fcdb655ed3d82697ab51d78 upstream. The i2c ip of sg2042 is a standard Synopsys i2c ip, which is already supported by the mainline kernel. Add i2c device node for sg2042. Signed-off-by: Inochi Amaoto Reviewed-by: Chen Wang Tested-by: Chen Wang Acked-by: Palmer Dabbelt Link: https://lore.kernel.org/r/IA1PR20MB49530E59974AF0FCA4FAB6DBBBB72@IA1PR20MB4953.namprd20.prod.outlook.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/boot/dts/sophgo/sg2042.dtsi | 52 ++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index c61d8061119d..eebd6817520e 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -47,6 +47,58 @@ soc: soc { interrupt-parent = <&intc>; ranges; + i2c0: i2c@7030005000 { + compatible = "snps,designware-i2c"; + reg = <0x70 0x30005000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_I2C>; + clock-names = "ref"; + clock-frequency = <100000>; + interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstgen RST_I2C0>; + status = "disabled"; + }; + + i2c1: i2c@7030006000 { + compatible = "snps,designware-i2c"; + reg = <0x70 0x30006000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_I2C>; + clock-names = "ref"; + clock-frequency = <100000>; + interrupts = <102 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstgen RST_I2C1>; + status = "disabled"; + }; + + i2c2: i2c@7030007000 { + compatible = "snps,designware-i2c"; + reg = <0x70 0x30007000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_I2C>; + clock-names = "ref"; + clock-frequency = <100000>; + interrupts = <103 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstgen RST_I2C2>; + status = "disabled"; + }; + + i2c3: i2c@7030008000 { + compatible = "snps,designware-i2c"; + reg = <0x70 0x30008000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_I2C>; + clock-names = "ref"; + clock-frequency = <100000>; + interrupts = <104 IRQ_TYPE_LEVEL_HIGH>; + resets = <&rstgen RST_I2C3>; + status = "disabled"; + }; + pllclk: clock-controller@70300100c0 { compatible = "sophgo,sg2042-pll"; reg = <0x70 0x300100c0 0x0 0x40>; -- Gitee From bc8583dd1d7c66014c0744e3921eb4abe1ef15cf Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Mon, 19 Aug 2024 16:08:51 +0800 Subject: [PATCH 24/24] riscv: sophgo: dts: add gpio controllers for SG2042 SoC ANBZ: #20835 commit a508d794f86ea67d371f89cc20800c656e490aac upstream. Add support for the GPIO controller of Sophgo SG2042. SG2042 uses IP from Synopsys DesignWare APB GPIO and has three GPIO controllers. Signed-off-by: Chen Wang Link: https://lore.kernel.org/r/20240819080851.1954691-1-unicornxw@gmail.com Signed-off-by: Han Gao Signed-off-by: yanan he --- arch/riscv/boot/dts/sophgo/sg2042.dtsi | 66 ++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi index eebd6817520e..6aff718dba4a 100644 --- a/arch/riscv/boot/dts/sophgo/sg2042.dtsi +++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi @@ -99,6 +99,72 @@ i2c3: i2c@7030008000 { status = "disabled"; }; + gpio0: gpio@7030009000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x70 0x30009000 0x0 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_GPIO>, + <&clkgen GATE_CLK_GPIO_DB>; + clock-names = "bus", "db"; + + port0a: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <96 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio1: gpio@703000a000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x70 0x3000a000 0x0 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_GPIO>, + <&clkgen GATE_CLK_GPIO_DB>; + clock-names = "bus", "db"; + + port1a: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <97 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + gpio2: gpio@703000b000 { + compatible = "snps,dw-apb-gpio"; + reg = <0x70 0x3000b000 0x0 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&clkgen GATE_CLK_APB_GPIO>, + <&clkgen GATE_CLK_GPIO_DB>; + clock-names = "bus", "db"; + + port2a: gpio-controller@0 { + compatible = "snps,dw-apb-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + snps,nr-gpios = <32>; + reg = <0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <98 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + pllclk: clock-controller@70300100c0 { compatible = "sophgo,sg2042-pll"; reg = <0x70 0x300100c0 0x0 0x40>; -- Gitee