Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'sunplus/newsoc' into arm/newsoc

Merge "Sunplus SP7021 SoC support" from Qin Jian, applied
as patches:

"Sunplus SP7021 is an ARM Cortex A7 (4 cores) based SoC. It integrates many
peripherals (ex: UART, I2C, SPI, SDIO, eMMC, USB, SD card and etc.) into a
single chip. It is designed for industrial control.

SP7021 consists of two chips (dies) in a package. One is called C-chip
(computing chip). It is a 4-core ARM Cortex A7 CPU. It adopts high-level
process (22 nm) for high performance computing. The other is called P-
chip (peripheral chip). It has many peripherals and an ARM A926 added
especially for real-time control. P-chip is made for customers. It adopts
low-level process (ex: 0.11 um) to reduce cost.

Refer to (for documentations):
https://sunplus-tibbo.atlassian.net/wiki/spaces/doc/overview

Refer to (applications):
https://tibbo.com/store/plus1.html

Refer to (applications):
http://www.sinovoip.com.cn/ecp_view.asp?id=586"

I left out the clock controller driver, which is still not fully
reviewed. There have been 20 revisions of the platform code, and
everything else looks good enough, so I hope it's we can simplify
the process by separating it out again.

Link: https://lore.kernel.org/linux-arm-kernel/0c10fa4ccf3da5d92784b9bbd4177d1d2f1d62a0.1656396767.git.qinjian@cqplus1.com/

* sunplus/newsoc:
ARM: dts: Add Sunplus SP7021-Demo-V3 board device tree
ARM: sp7021_defconfig: Add Sunplus SP7021 defconfig
ARM: sunplus: Add initial support for Sunplus SP7021 SoC
irqchip: Add Sunplus SP7021 interrupt controller driver
dt-bindings: interrupt-controller: Add bindings for SP7021 interrupt controller
dt-bindings: clock: Add bindings for SP7021 clock driver
reset: Add Sunplus SP7021 reset driver
dt-bindings: reset: Add bindings for SP7021 reset driver
dt-bindings: arm: sunplus: Add bindings for Sunplus SP7021 SoC boards

+1423
+29
Documentation/devicetree/bindings/arm/sunplus,sp7021.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + # Copyright (C) Sunplus Co., Ltd. 2021 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/arm/sunplus,sp7021.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Sunplus SP7021 Boards 9 + 10 + maintainers: 11 + - qinjian <qinjian@cqplus1.com> 12 + 13 + description: | 14 + ARM platforms using Sunplus SP7021, an ARM Cortex A7 (4-cores) based SoC. 15 + Wiki: https://sunplus-tibbo.atlassian.net/wiki/spaces/doc/overview 16 + 17 + properties: 18 + $nodename: 19 + const: '/' 20 + compatible: 21 + items: 22 + - enum: 23 + - sunplus,sp7021-achip 24 + - sunplus,sp7021-demo-v3 25 + - const: sunplus,sp7021 26 + 27 + additionalProperties: true 28 + 29 + ...
+52
Documentation/devicetree/bindings/clock/sunplus,sp7021-clkc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + # Copyright (C) Sunplus Co., Ltd. 2021 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/clock/sunplus,sp7021-clkc.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Sunplus SP7021 SoC Clock Controller 9 + 10 + maintainers: 11 + - Qin Jian <qinjian@cqplus1.com> 12 + 13 + properties: 14 + compatible: 15 + const: sunplus,sp7021-clkc 16 + 17 + reg: 18 + maxItems: 3 19 + 20 + clocks: 21 + maxItems: 1 22 + 23 + "#clock-cells": 24 + const: 1 25 + 26 + required: 27 + - compatible 28 + - reg 29 + - clocks 30 + - "#clock-cells" 31 + 32 + additionalProperties: false 33 + 34 + examples: 35 + - | 36 + extclk: osc0 { 37 + compatible = "fixed-clock"; 38 + #clock-cells = <0>; 39 + clock-frequency = <27000000>; 40 + clock-output-names = "extclk"; 41 + }; 42 + 43 + clkc: clock-controller@9c000004 { 44 + compatible = "sunplus,sp7021-clkc"; 45 + reg = <0x9c000004 0x28>, 46 + <0x9c000200 0x44>, 47 + <0x9c000268 0x08>; 48 + clocks = <&extclk>; 49 + #clock-cells = <1>; 50 + }; 51 + 52 + ...
+62
Documentation/devicetree/bindings/interrupt-controller/sunplus,sp7021-intc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + # Copyright (C) Sunplus Co., Ltd. 2021 3 + %YAML 1.2 4 + --- 5 + $id: http://devicetree.org/schemas/interrupt-controller/sunplus,sp7021-intc.yaml# 6 + $schema: http://devicetree.org/meta-schemas/core.yaml# 7 + 8 + title: Sunplus SP7021 SoC Interrupt Controller 9 + 10 + maintainers: 11 + - Qin Jian <qinjian@cqplus1.com> 12 + 13 + properties: 14 + compatible: 15 + items: 16 + - const: sunplus,sp7021-intc 17 + 18 + reg: 19 + maxItems: 2 20 + description: 21 + Specifies base physical address(s) and size of the controller regs. 22 + The 1st region include type/polarity/priority/mask regs. 23 + The 2nd region include clear/masked_ext0/masked_ext1/group regs. 24 + 25 + interrupt-controller: true 26 + 27 + "#interrupt-cells": 28 + const: 2 29 + description: 30 + The first cell is the IRQ number, the second cell is the trigger 31 + type as defined in interrupt.txt in this directory. 32 + 33 + interrupts: 34 + maxItems: 2 35 + description: 36 + EXT_INT0 & EXT_INT1, 2 interrupts references to primary interrupt 37 + controller. 38 + 39 + required: 40 + - compatible 41 + - reg 42 + - interrupt-controller 43 + - "#interrupt-cells" 44 + - interrupts 45 + 46 + additionalProperties: false 47 + 48 + examples: 49 + - | 50 + #include <dt-bindings/interrupt-controller/arm-gic.h> 51 + 52 + intc: interrupt-controller@9c000780 { 53 + compatible = "sunplus,sp7021-intc"; 54 + reg = <0x9c000780 0x80>, <0x9c000a80 0x80>; 55 + interrupt-controller; 56 + #interrupt-cells = <2>; 57 + interrupt-parent = <&gic>; 58 + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, /* EXT_INT0 */ 59 + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; /* EXT_INT1 */ 60 + }; 61 + 62 + ...
+38
Documentation/devicetree/bindings/reset/sunplus,reset.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + # Copyright (C) Sunplus Co., Ltd. 2021 3 + %YAML 1.2 4 + --- 5 + $id: "http://devicetree.org/schemas/reset/sunplus,reset.yaml#" 6 + $schema: "http://devicetree.org/meta-schemas/core.yaml#" 7 + 8 + title: Sunplus SoC Reset Controller 9 + 10 + maintainers: 11 + - Qin Jian <qinjian@cqplus1.com> 12 + 13 + properties: 14 + compatible: 15 + const: sunplus,sp7021-reset 16 + 17 + reg: 18 + maxItems: 1 19 + 20 + "#reset-cells": 21 + const: 1 22 + 23 + required: 24 + - compatible 25 + - reg 26 + - "#reset-cells" 27 + 28 + additionalProperties: false 29 + 30 + examples: 31 + - | 32 + rstc: reset@9c000054 { 33 + compatible = "sunplus,sp7021-reset"; 34 + reg = <0x9c000054 0x28>; 35 + #reset-cells = <1>; 36 + }; 37 + 38 + ...
+17
MAINTAINERS
··· 2825 2825 N: stm32 2826 2826 N: stm 2827 2827 2828 + ARM/SUNPLUS SP7021 SOC SUPPORT 2829 + M: Qin Jian <qinjian@cqplus1.com> 2830 + L: linux-arm-kernel@lists.infradead.org (moderated for mon-subscribers) 2831 + S: Maintained 2832 + W: https://sunplus-tibbo.atlassian.net/wiki/spaces/doc/overview 2833 + F: Documentation/devicetree/bindings/arm/sunplus,sp7021.yaml 2834 + F: Documentation/devicetree/bindings/clock/sunplus,sp7021-clkc.yaml 2835 + F: Documentation/devicetree/bindings/interrupt-controller/sunplus,sp7021-intc.yaml 2836 + F: Documentation/devicetree/bindings/reset/sunplus,reset.yaml 2837 + F: arch/arm/boot/dts/sunplus-sp7021*.dts* 2838 + F: arch/arm/configs/sp7021_*defconfig 2839 + F: arch/arm/mach-sunplus/ 2840 + F: drivers/irqchip/irq-sp7021-intc.c 2841 + F: drivers/reset/reset-sunplus.c 2842 + F: include/dt-bindings/clock/sunplus,sp7021-clkc.h 2843 + F: include/dt-bindings/reset/sunplus,sp7021-reset.h 2844 + 2828 2845 ARM/Synaptics SoC support 2829 2846 M: Jisheng Zhang <jszhang@kernel.org> 2830 2847 M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+2
arch/arm/Kconfig
··· 588 588 589 589 source "arch/arm/mach-stm32/Kconfig" 590 590 591 + source "arch/arm/mach-sunplus/Kconfig" 592 + 591 593 source "arch/arm/mach-sunxi/Kconfig" 592 594 593 595 source "arch/arm/mach-tegra/Kconfig"
+1
arch/arm/Makefile
··· 215 215 machine-$(CONFIG_ARCH_INTEL_SOCFPGA) += socfpga 216 216 machine-$(CONFIG_ARCH_STI) += sti 217 217 machine-$(CONFIG_ARCH_STM32) += stm32 218 + machine-$(CONFIG_ARCH_SUNPLUS) += sunplus 218 219 machine-$(CONFIG_ARCH_SUNXI) += sunxi 219 220 machine-$(CONFIG_ARCH_TEGRA) += tegra 220 221 machine-$(CONFIG_ARCH_U8500) += ux500
+2
arch/arm/boot/dts/Makefile
··· 79 79 at91-vinco.dtb 80 80 dtb-$(CONFIG_SOC_SAMA7G5) += \ 81 81 at91-sama7g5ek.dtb 82 + dtb-$(CONFIG_SOC_SP7021) += \ 83 + sunplus-sp7021-demo-v3.dtb 82 84 dtb-$(CONFIG_ARCH_AXXIA) += \ 83 85 axm5516-amarillo.dtb 84 86 dtb-$(CONFIG_ARCH_BCM2835) += \
+84
arch/arm/boot/dts/sunplus-sp7021-achip.dtsi
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Device Tree Source for Sunplus SP7021 4 + * 5 + * Copyright (C) 2021 Sunplus Technology Co. 6 + */ 7 + 8 + #include "sunplus-sp7021.dtsi" 9 + #include <dt-bindings/interrupt-controller/arm-gic.h> 10 + 11 + / { 12 + compatible = "sunplus,sp7021-achip", "sunplus,sp7021"; 13 + model = "Sunplus SP7021 (CA7)"; 14 + #address-cells = <1>; 15 + #size-cells = <1>; 16 + interrupt-parent = <&gic>; 17 + 18 + cpus { 19 + #address-cells = <1>; 20 + #size-cells = <0>; 21 + 22 + cpu0: cpu@0 { 23 + compatible = "arm,cortex-a7"; 24 + device_type = "cpu"; 25 + reg = <0>; 26 + clock-frequency = <931000000>; 27 + }; 28 + cpu1: cpu@1 { 29 + compatible = "arm,cortex-a7"; 30 + device_type = "cpu"; 31 + reg = <1>; 32 + clock-frequency = <931000000>; 33 + }; 34 + cpu2: cpu@2 { 35 + compatible = "arm,cortex-a7"; 36 + device_type = "cpu"; 37 + reg = <2>; 38 + clock-frequency = <931000000>; 39 + }; 40 + cpu3: cpu@3 { 41 + compatible = "arm,cortex-a7"; 42 + device_type = "cpu"; 43 + reg = <3>; 44 + clock-frequency = <931000000>; 45 + }; 46 + }; 47 + 48 + gic: interrupt-controller@9f101000 { 49 + compatible = "arm,cortex-a7-gic"; 50 + interrupt-controller; 51 + #interrupt-cells = <3>; 52 + reg = <0x9f101000 0x1000>, 53 + <0x9f102000 0x2000>, 54 + <0x9f104000 0x2000>, 55 + <0x9f106000 0x2000>; 56 + }; 57 + 58 + timer { 59 + compatible = "arm,armv7-timer"; 60 + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, 61 + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, 62 + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, 63 + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; 64 + clock-frequency = <XTAL>; 65 + arm,cpu-registers-not-fw-configured; 66 + }; 67 + 68 + arm-pmu { 69 + compatible = "arm,cortex-a7-pmu"; 70 + interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>, 71 + <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>, 72 + <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>, 73 + <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>; 74 + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; 75 + }; 76 + 77 + soc@9c000000 { 78 + intc: interrupt-controller@780 { 79 + interrupt-parent = <&gic>; 80 + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, /* EXT_INT0 */ 81 + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; /* EXT_INT1 */ 82 + }; 83 + }; 84 + };
+30
arch/arm/boot/dts/sunplus-sp7021-demo-v3.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Device Tree Source for Sunplus SP7021 Demo V3 SBC board 4 + * 5 + * Copyright (C) Sunplus Technology Co. 6 + */ 7 + 8 + /dts-v1/; 9 + 10 + #include "sunplus-sp7021-achip.dtsi" 11 + 12 + / { 13 + compatible = "sunplus,sp7021-demo-v3", "sunplus,sp7021"; 14 + model = "Sunplus SP7021/CA7/Demo_V3"; 15 + #address-cells = <1>; 16 + #size-cells = <1>; 17 + 18 + aliases { 19 + serial0 = &uart0; 20 + }; 21 + 22 + chosen { 23 + stdout-path = "serial0:115200n8"; 24 + }; 25 + 26 + memory@0 { 27 + device_type = "memory"; 28 + reg = <0x00000000 0x20000000>; 29 + }; 30 + };
+310
arch/arm/boot/dts/sunplus-sp7021.dtsi
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Device Tree Source for Sunplus SP7021 4 + * 5 + * Copyright (C) 2021 Sunplus Technology Co. 6 + */ 7 + 8 + #include <dt-bindings/clock/sunplus,sp7021-clkc.h> 9 + #include <dt-bindings/interrupt-controller/irq.h> 10 + #include <dt-bindings/reset/sunplus,sp7021-reset.h> 11 + #include <dt-bindings/pinctrl/sppctl-sp7021.h> 12 + #include <dt-bindings/gpio/gpio.h> 13 + 14 + #define XTAL 27000000 15 + 16 + / { 17 + compatible = "sunplus,sp7021"; 18 + model = "Sunplus SP7021"; 19 + 20 + clocks { 21 + extclk: osc0 { 22 + compatible = "fixed-clock"; 23 + #clock-cells = <0>; 24 + clock-frequency = <XTAL>; 25 + clock-output-names = "extclk"; 26 + }; 27 + }; 28 + 29 + soc@9c000000 { 30 + compatible = "simple-bus"; 31 + #address-cells = <1>; 32 + #size-cells = <1>; 33 + ranges = <0 0x9c000000 0x400000>; 34 + interrupt-parent = <&intc>; 35 + 36 + clkc: clock-controller@4 { 37 + compatible = "sunplus,sp7021-clkc"; 38 + reg = <0x4 0x28>, 39 + <0x200 0x44>, 40 + <0x268 0x04>; 41 + clocks = <&extclk>; 42 + #clock-cells = <1>; 43 + }; 44 + 45 + intc: interrupt-controller@780 { 46 + compatible = "sunplus,sp7021-intc"; 47 + reg = <0x780 0x80>, <0xa80 0x80>; 48 + interrupt-controller; 49 + #interrupt-cells = <2>; 50 + }; 51 + 52 + otp: otp@af00 { 53 + compatible = "sunplus,sp7021-ocotp"; 54 + reg = <0xaf00 0x34>, <0xaf80 0x58>; 55 + reg-names = "hb_gpio", "otprx"; 56 + clocks = <&clkc CLK_OTPRX>; 57 + resets = <&rstc RST_OTPRX>; 58 + #address-cells = <1>; 59 + #size-cells = <1>; 60 + 61 + therm_calib: thermal-calibration@14 { 62 + reg = <0x14 0x3>; 63 + }; 64 + disc_vol: disconnect-voltage@18 { 65 + reg = <0x18 0x2>; 66 + }; 67 + mac_addr0: mac-address0@34 { 68 + reg = <0x34 0x6>; 69 + }; 70 + mac_addr1: mac-address1@3a { 71 + reg = <0x3a 0x6>; 72 + }; 73 + }; 74 + 75 + pctl: pinctrl@100 { 76 + compatible = "sunplus,sp7021-pctl"; 77 + reg = <0x100 0x100>, 78 + <0x300 0x100>, 79 + <0x32e4 0x1C>, 80 + <0x80 0x20>; 81 + reg-names = "moon2", "gpioxt", "first", "moon1"; 82 + gpio-controller; 83 + #gpio-cells = <2>; 84 + clocks = <&clkc CLK_GPIO>; 85 + resets = <&rstc RST_GPIO>; 86 + 87 + emac_pins: pinmux-emac-pins { 88 + sunplus,pins = < 89 + SPPCTL_IOPAD(49,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_CLK_OUT,0) 90 + SPPCTL_IOPAD(44,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_MAC_SMI_MDC,0) 91 + SPPCTL_IOPAD(43,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_MAC_SMI_MDIO,0) 92 + SPPCTL_IOPAD(52,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P0_MAC_RMII_TXEN,0) 93 + SPPCTL_IOPAD(50,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P0_MAC_RMII_TXD0,0) 94 + SPPCTL_IOPAD(51,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P0_MAC_RMII_TXD1,0) 95 + SPPCTL_IOPAD(46,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P0_MAC_RMII_CRSDV,0) 96 + SPPCTL_IOPAD(47,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P0_MAC_RMII_RXD0,0) 97 + SPPCTL_IOPAD(48,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P0_MAC_RMII_RXD1,0) 98 + SPPCTL_IOPAD(45,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P0_MAC_RMII_RXER,0) 99 + SPPCTL_IOPAD(59,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P1_MAC_RMII_TXEN,0) 100 + SPPCTL_IOPAD(57,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P1_MAC_RMII_TXD0,0) 101 + SPPCTL_IOPAD(58,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P1_MAC_RMII_TXD1,0) 102 + SPPCTL_IOPAD(54,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P1_MAC_RMII_CRSDV,0) 103 + SPPCTL_IOPAD(55,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P1_MAC_RMII_RXD0,0) 104 + SPPCTL_IOPAD(56,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P1_MAC_RMII_RXD1,0) 105 + SPPCTL_IOPAD(53,SPPCTL_PCTL_G_PMUX,MUXF_L2SW_P1_MAC_RMII_RXER,0) 106 + >; 107 + sunplus,zerofunc = < 108 + MUXF_L2SW_LED_FLASH0 109 + MUXF_L2SW_LED_FLASH1 110 + MUXF_L2SW_LED_ON0 111 + MUXF_L2SW_LED_ON1 112 + MUXF_DAISY_MODE 113 + >; 114 + }; 115 + 116 + emmc_pins: pinmux-emmc-pins { 117 + function = "CARD0_EMMC"; 118 + groups = "CARD0_EMMC"; 119 + }; 120 + 121 + leds_pins: pinmux-leds-pins { 122 + sunplus,pins = < SPPCTL_IOPAD(0,SPPCTL_PCTL_G_GPIO,0,SPPCTL_PCTL_L_OUT) >; 123 + }; 124 + 125 + sdcard_pins: pinmux-sdcard-pins { 126 + function = "SD_CARD"; 127 + groups = "SD_CARD"; 128 + sunplus,pins = < SPPCTL_IOPAD(91, SPPCTL_PCTL_G_GPIO, 0, 0) >; 129 + }; 130 + 131 + spi0_pins: pinmux-spi0-pins { 132 + sunplus,pins = < 133 + SPPCTL_IOPAD(26,SPPCTL_PCTL_G_GPIO,0,0) 134 + SPPCTL_IOPAD(28,SPPCTL_PCTL_G_GPIO,0,0) 135 + SPPCTL_IOPAD(23,SPPCTL_PCTL_G_PMUX,MUXF_SPI0S_DO,0) 136 + SPPCTL_IOPAD(25,SPPCTL_PCTL_G_PMUX,MUXF_SPI0S_DI,0) 137 + SPPCTL_IOPAD(27,SPPCTL_PCTL_G_PMUX,MUXF_SPI0S_CLK,0) 138 + >; 139 + }; 140 + 141 + uart0_pins: pinmux-uart0-pins { 142 + function = "UA0"; 143 + groups = "UA0"; 144 + }; 145 + 146 + uart1_pins: pinmux-uart1-pins { 147 + sunplus,pins = < 148 + SPPCTL_IOPAD(14,SPPCTL_PCTL_G_PMUX,MUXF_UA4_TX,0) 149 + SPPCTL_IOPAD(16,SPPCTL_PCTL_G_PMUX,MUXF_UA4_RX,0) 150 + >; 151 + }; 152 + 153 + uart2_pins: pinmux-uart2-pins { 154 + sunplus,pins = < 155 + SPPCTL_IOPAD(16,SPPCTL_PCTL_G_PMUX,MUXF_UA2_TX,0) 156 + SPPCTL_IOPAD(17,SPPCTL_PCTL_G_PMUX,MUXF_UA2_RX,0) 157 + SPPCTL_IOPAD(18,SPPCTL_PCTL_G_PMUX,MUXF_UA2_RTS,0) 158 + SPPCTL_IOPAD(19,SPPCTL_PCTL_G_PMUX,MUXF_UA2_CTS,0) 159 + >; 160 + }; 161 + 162 + uart4_pins: pinmux-uart4-pins { 163 + sunplus,pins = < 164 + SPPCTL_IOPAD(22,SPPCTL_PCTL_G_PMUX,MUXF_UA4_TX,0) 165 + SPPCTL_IOPAD(20,SPPCTL_PCTL_G_PMUX,MUXF_UA4_RX,0) 166 + SPPCTL_IOPAD(23,SPPCTL_PCTL_G_PMUX,MUXF_UA4_RTS,0) 167 + SPPCTL_IOPAD(21,SPPCTL_PCTL_G_PMUX,MUXF_UA4_CTS,0) 168 + >; 169 + }; 170 + }; 171 + 172 + rstc: reset@54 { 173 + compatible = "sunplus,sp7021-reset"; 174 + reg = <0x54 0x28>; 175 + #reset-cells = <1>; 176 + }; 177 + 178 + rtc: rtc@3a00 { 179 + compatible = "sunplus,sp7021-rtc"; 180 + reg = <0x3a00 0x80>; 181 + reg-names = "rtc"; 182 + clocks = <&clkc CLK_RTC>; 183 + resets = <&rstc RST_RTC>; 184 + interrupts = <163 IRQ_TYPE_EDGE_RISING>; 185 + }; 186 + 187 + spi_controller0: spi@2d80 { 188 + compatible = "sunplus,sp7021-spi"; 189 + reg = <0x2d80 0x80>, <0x2e00 0x80>; 190 + reg-names = "master", "slave"; 191 + interrupts = <144 IRQ_TYPE_LEVEL_HIGH>, 192 + <146 IRQ_TYPE_LEVEL_HIGH>, 193 + <145 IRQ_TYPE_LEVEL_HIGH>; 194 + interrupt-names = "dma_w", "master_risc", "slave_risc"; 195 + clocks = <&clkc CLK_SPI_COMBO_0>; 196 + resets = <&rstc RST_SPI_COMBO_0>; 197 + 198 + pinctrl-names = "default"; 199 + pinctrl-0 = <&spi0_pins>; 200 + cs-gpios = <&pctl 26 GPIO_ACTIVE_LOW>, 201 + <&pctl 28 GPIO_ACTIVE_LOW>; 202 + }; 203 + 204 + spi_controller1: spi@f480 { 205 + compatible = "sunplus,sp7021-spi"; 206 + reg = <0xf480 0x80>, <0xf500 0x80>; 207 + reg-names = "master", "slave"; 208 + interrupts = <67 IRQ_TYPE_LEVEL_HIGH>, 209 + <69 IRQ_TYPE_LEVEL_HIGH>, 210 + <68 IRQ_TYPE_LEVEL_HIGH>; 211 + interrupt-names = "dma_w", "master_risc", "slave_risc"; 212 + clocks = <&clkc CLK_SPI_COMBO_1>; 213 + resets = <&rstc RST_SPI_COMBO_1>; 214 + spi-max-frequency = <25000000>; 215 + status = "disabled"; 216 + }; 217 + 218 + spi_controller2: spi@f600 { 219 + compatible = "sunplus,sp7021-spi"; 220 + reg = <0xf600 0x80>, <0xf680 0x80>; 221 + reg-names = "master", "slave"; 222 + interrupts = <70 IRQ_TYPE_LEVEL_HIGH>, 223 + <72 IRQ_TYPE_LEVEL_HIGH>, 224 + <71 IRQ_TYPE_LEVEL_HIGH>; 225 + interrupt-names = "dma_w", "master_risc", "slave_risc"; 226 + clocks = <&clkc CLK_SPI_COMBO_2>; 227 + resets = <&rstc RST_SPI_COMBO_2>; 228 + spi-max-frequency = <25000000>; 229 + status = "disabled"; 230 + }; 231 + 232 + spi_controller3: spi@f780 { 233 + compatible = "sunplus,sp7021-spi"; 234 + reg = <0xf780 0x80>, <0xf800 0x80>; 235 + reg-names = "master", "slave"; 236 + interrupts = <73 IRQ_TYPE_LEVEL_HIGH>, 237 + <75 IRQ_TYPE_LEVEL_HIGH>, 238 + <74 IRQ_TYPE_LEVEL_HIGH>; 239 + interrupt-names = "dma_w", "master_risc", "slave_risc"; 240 + clocks = <&clkc CLK_SPI_COMBO_3>; 241 + resets = <&rstc RST_SPI_COMBO_3>; 242 + spi-max-frequency = <25000000>; 243 + status = "disabled"; 244 + }; 245 + 246 + uart0: serial@900 { 247 + compatible = "sunplus,sp7021-uart"; 248 + reg = <0x900 0x80>; 249 + interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; 250 + clocks = <&clkc CLK_UA0>; 251 + resets = <&rstc RST_UA0>; 252 + pinctrl-names = "default"; 253 + pinctrl-0 = <&uart0_pins>; 254 + }; 255 + 256 + uart1: serial@980 { 257 + compatible = "sunplus,sp7021-uart"; 258 + reg = <0x980 0x80>; 259 + interrupts = <54 IRQ_TYPE_LEVEL_HIGH>; 260 + clocks = <&clkc CLK_UA1>; 261 + resets = <&rstc RST_UA1>; 262 + pinctrl-names = "default"; 263 + pinctrl-0 = <&uart1_pins>; 264 + status = "disabled"; 265 + }; 266 + 267 + uart2: serial@800 { 268 + compatible = "sunplus,sp7021-uart"; 269 + reg = <0x800 0x80>; 270 + interrupts = <55 IRQ_TYPE_LEVEL_HIGH>; 271 + clocks = <&clkc CLK_UA2>; 272 + resets = <&rstc RST_UA2>; 273 + pinctrl-names = "default"; 274 + pinctrl-0 = <&uart2_pins>; 275 + status = "disabled"; 276 + }; 277 + 278 + uart3: serial@880 { 279 + compatible = "sunplus,sp7021-uart"; 280 + reg = <0x880 0x80>; 281 + interrupts = <56 IRQ_TYPE_LEVEL_HIGH>; 282 + clocks = <&clkc CLK_UA3>; 283 + resets = <&rstc RST_UA3>; 284 + status = "disabled"; 285 + }; 286 + 287 + uart4: serial@8780 { 288 + compatible = "sunplus,sp7021-uart"; 289 + reg = <0x8780 0x80>; 290 + interrupts = <134 IRQ_TYPE_LEVEL_HIGH>; 291 + clocks = <&clkc CLK_UA4>; 292 + resets = <&rstc RST_UA4>; 293 + pinctrl-names = "default"; 294 + pinctrl-0 = <&uart4_pins>; 295 + status = "disabled"; 296 + }; 297 + }; 298 + 299 + leds { 300 + compatible = "gpio-leds"; 301 + pinctrl-names = "default"; 302 + pinctrl-0 = <&leds_pins>; 303 + system-led { 304 + label = "system-led"; 305 + gpios = <&pctl 0 GPIO_ACTIVE_HIGH>; 306 + default-state = "off"; 307 + linux,default-trigger = "heartbeat"; 308 + }; 309 + }; 310 + };
+1
arch/arm/configs/multi_v7_defconfig
··· 94 94 CONFIG_MACH_SPEAR1340=y 95 95 CONFIG_ARCH_STI=y 96 96 CONFIG_ARCH_STM32=y 97 + CONFIG_ARCH_SUNPLUS=y 97 98 CONFIG_ARCH_SUNXI=y 98 99 CONFIG_ARCH_TEGRA=y 99 100 CONFIG_ARCH_UNIPHIER=y
+59
arch/arm/configs/sp7021_defconfig
··· 1 + CONFIG_SYSVIPC=y 2 + CONFIG_NO_HZ_IDLE=y 3 + CONFIG_HIGH_RES_TIMERS=y 4 + CONFIG_PREEMPT=y 5 + CONFIG_IKCONFIG=y 6 + CONFIG_IKCONFIG_PROC=y 7 + CONFIG_LOG_BUF_SHIFT=14 8 + # CONFIG_RD_GZIP is not set 9 + # CONFIG_RD_BZIP2 is not set 10 + # CONFIG_RD_LZMA is not set 11 + # CONFIG_RD_XZ is not set 12 + # CONFIG_RD_LZO is not set 13 + # CONFIG_RD_LZ4 is not set 14 + CONFIG_CC_OPTIMIZE_FOR_SIZE=y 15 + CONFIG_PERF_EVENTS=y 16 + CONFIG_SLAB=y 17 + CONFIG_ARCH_SUNPLUS=y 18 + # CONFIG_VDSO is not set 19 + CONFIG_SMP=y 20 + CONFIG_THUMB2_KERNEL=y 21 + CONFIG_FORCE_MAX_ZONEORDER=12 22 + CONFIG_VFP=y 23 + CONFIG_NEON=y 24 + CONFIG_MODULES=y 25 + CONFIG_MODULE_UNLOAD=y 26 + CONFIG_MODVERSIONS=y 27 + # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set 28 + CONFIG_UEVENT_HELPER=y 29 + CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" 30 + CONFIG_DEVTMPFS=y 31 + CONFIG_DEVTMPFS_MOUNT=y 32 + CONFIG_BLK_DEV_LOOP=y 33 + CONFIG_INPUT_SPARSEKMAP=y 34 + CONFIG_INPUT_EVDEV=y 35 + # CONFIG_INPUT_KEYBOARD is not set 36 + # CONFIG_INPUT_MOUSE is not set 37 + # CONFIG_LEGACY_PTYS is not set 38 + # CONFIG_HW_RANDOM is not set 39 + # CONFIG_HWMON is not set 40 + # CONFIG_IOMMU_SUPPORT is not set 41 + CONFIG_RESET_CONTROLLER=y 42 + CONFIG_EXT4_FS=y 43 + # CONFIG_DNOTIFY is not set 44 + CONFIG_FANOTIFY=y 45 + CONFIG_VFAT_FS=y 46 + CONFIG_FAT_DEFAULT_IOCHARSET="utf8" 47 + CONFIG_EXFAT_FS=y 48 + CONFIG_TMPFS=y 49 + CONFIG_TMPFS_POSIX_ACL=y 50 + # CONFIG_MISC_FILESYSTEMS is not set 51 + CONFIG_NLS_CODEPAGE_437=y 52 + CONFIG_NLS_ASCII=y 53 + CONFIG_NLS_ISO8859_1=y 54 + CONFIG_NLS_UTF8=y 55 + CONFIG_PRINTK_TIME=y 56 + CONFIG_DYNAMIC_DEBUG=y 57 + CONFIG_MAGIC_SYSRQ=y 58 + CONFIG_DEBUG_FS=y 59 + CONFIG_DEBUG_USER=y
+27
arch/arm/mach-sunplus/Kconfig
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + 3 + menuconfig ARCH_SUNPLUS 4 + bool "Sunplus SoCs" 5 + depends on ARCH_MULTI_V7 6 + help 7 + Support for Sunplus SoC family: SP7021 and succeeding SoC-based systems, 8 + such as the Banana Pi BPI-F2S development board (and derivatives). 9 + (<http://www.sinovoip.com.cn/ecp_view.asp?id=586>) 10 + (<https://tibbo.com/store/plus1.html>) 11 + 12 + config SOC_SP7021 13 + bool "Sunplus SP7021 SoC support" 14 + depends on ARCH_SUNPLUS 15 + default ARCH_SUNPLUS 16 + select HAVE_ARM_ARCH_TIMER 17 + select ARM_GIC 18 + select ARM_PSCI 19 + select PINCTRL 20 + select PINCTRL_SPPCTL 21 + select SERIAL_SUNPLUS 22 + select SERIAL_SUNPLUS_CONSOLE 23 + help 24 + Support for Sunplus SP7021 SoC. It is based on ARM 4-core 25 + Cortex-A7 with various peripherals (e.g.: I2C, SPI, SDIO, 26 + Ethernet, etc.), FPGA interface, chip-to-chip bus. 27 + It is designed for industrial control.
+8
arch/arm/mach-sunplus/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # Makefile for the linux kernel. 4 + # 5 + 6 + # Object file lists. 7 + 8 + obj-$(CONFIG_SOC_SP7021) += sp7021.o
+16
arch/arm/mach-sunplus/sp7021.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + /* 3 + * Copyright (C) Sunplus Technology Co., Ltd. 4 + * All rights reserved. 5 + */ 6 + #include <linux/kernel.h> 7 + #include <asm/mach/arch.h> 8 + 9 + static const char *sp7021_compat[] __initconst = { 10 + "sunplus,sp7021", 11 + NULL 12 + }; 13 + 14 + DT_MACHINE_START(SP7021_DT, "SP7021") 15 + .dt_compat = sp7021_compat, 16 + MACHINE_END
+9
drivers/irqchip/Kconfig
··· 627 627 help 628 628 Support for Microchip External Interrupt Controller. 629 629 630 + config SUNPLUS_SP7021_INTC 631 + bool "Sunplus SP7021 interrupt controller" if COMPILE_TEST 632 + default SOC_SP7021 633 + help 634 + Support for the Sunplus SP7021 Interrupt Controller IP core. 635 + SP7021 SoC has 2 Chips: C-Chip & P-Chip. This is used as a 636 + chained controller, routing all interrupt source in P-Chip to 637 + the primary controller on C-Chip. 638 + 630 639 endmenu
+1
drivers/irqchip/Makefile
··· 115 115 obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o 116 116 obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o 117 117 obj-$(CONFIG_MCHP_EIC) += irq-mchp-eic.o 118 + obj-$(CONFIG_SUNPLUS_SP7021_INTC) += irq-sp7021-intc.o
+278
drivers/irqchip/irq-sp7021-intc.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + /* 3 + * Copyright (C) Sunplus Technology Co., Ltd. 4 + * All rights reserved. 5 + */ 6 + #include <linux/irq.h> 7 + #include <linux/irqdomain.h> 8 + #include <linux/io.h> 9 + #include <linux/irqchip.h> 10 + #include <linux/irqchip/chained_irq.h> 11 + #include <linux/of_address.h> 12 + #include <linux/of_irq.h> 13 + 14 + #define SP_INTC_HWIRQ_MIN 0 15 + #define SP_INTC_HWIRQ_MAX 223 16 + 17 + #define SP_INTC_NR_IRQS (SP_INTC_HWIRQ_MAX - SP_INTC_HWIRQ_MIN + 1) 18 + #define SP_INTC_NR_GROUPS DIV_ROUND_UP(SP_INTC_NR_IRQS, 32) 19 + #define SP_INTC_REG_SIZE (SP_INTC_NR_GROUPS * 4) 20 + 21 + /* REG_GROUP_0 regs */ 22 + #define REG_INTR_TYPE (sp_intc.g0) 23 + #define REG_INTR_POLARITY (REG_INTR_TYPE + SP_INTC_REG_SIZE) 24 + #define REG_INTR_PRIORITY (REG_INTR_POLARITY + SP_INTC_REG_SIZE) 25 + #define REG_INTR_MASK (REG_INTR_PRIORITY + SP_INTC_REG_SIZE) 26 + 27 + /* REG_GROUP_1 regs */ 28 + #define REG_INTR_CLEAR (sp_intc.g1) 29 + #define REG_MASKED_EXT1 (REG_INTR_CLEAR + SP_INTC_REG_SIZE) 30 + #define REG_MASKED_EXT0 (REG_MASKED_EXT1 + SP_INTC_REG_SIZE) 31 + #define REG_INTR_GROUP (REG_INTR_CLEAR + 31 * 4) 32 + 33 + #define GROUP_MASK (BIT(SP_INTC_NR_GROUPS) - 1) 34 + #define GROUP_SHIFT_EXT1 (0) 35 + #define GROUP_SHIFT_EXT0 (8) 36 + 37 + /* 38 + * When GPIO_INT0~7 set to edge trigger, doesn't work properly. 39 + * WORKAROUND: change it to level trigger, and toggle the polarity 40 + * at ACK/Handler to make the HW work. 41 + */ 42 + #define GPIO_INT0_HWIRQ 120 43 + #define GPIO_INT7_HWIRQ 127 44 + #define IS_GPIO_INT(irq) \ 45 + ({ \ 46 + u32 i = irq; \ 47 + (i >= GPIO_INT0_HWIRQ) && (i <= GPIO_INT7_HWIRQ); \ 48 + }) 49 + 50 + /* index of states */ 51 + enum { 52 + _IS_EDGE = 0, 53 + _IS_LOW, 54 + _IS_ACTIVE 55 + }; 56 + 57 + #define STATE_BIT(irq, idx) (((irq) - GPIO_INT0_HWIRQ) * 3 + (idx)) 58 + #define ASSIGN_STATE(irq, idx, v) assign_bit(STATE_BIT(irq, idx), sp_intc.states, v) 59 + #define TEST_STATE(irq, idx) test_bit(STATE_BIT(irq, idx), sp_intc.states) 60 + 61 + static struct sp_intctl { 62 + /* 63 + * REG_GROUP_0: include type/polarity/priority/mask regs. 64 + * REG_GROUP_1: include clear/masked_ext0/masked_ext1/group regs. 65 + */ 66 + void __iomem *g0; // REG_GROUP_0 base 67 + void __iomem *g1; // REG_GROUP_1 base 68 + 69 + struct irq_domain *domain; 70 + raw_spinlock_t lock; 71 + 72 + /* 73 + * store GPIO_INT states 74 + * each interrupt has 3 states: is_edge, is_low, is_active 75 + */ 76 + DECLARE_BITMAP(states, (GPIO_INT7_HWIRQ - GPIO_INT0_HWIRQ + 1) * 3); 77 + } sp_intc; 78 + 79 + static struct irq_chip sp_intc_chip; 80 + 81 + static void sp_intc_assign_bit(u32 hwirq, void __iomem *base, bool value) 82 + { 83 + u32 offset, mask; 84 + unsigned long flags; 85 + void __iomem *reg; 86 + 87 + offset = (hwirq / 32) * 4; 88 + reg = base + offset; 89 + 90 + raw_spin_lock_irqsave(&sp_intc.lock, flags); 91 + mask = readl_relaxed(reg); 92 + if (value) 93 + mask |= BIT(hwirq % 32); 94 + else 95 + mask &= ~BIT(hwirq % 32); 96 + writel_relaxed(mask, reg); 97 + raw_spin_unlock_irqrestore(&sp_intc.lock, flags); 98 + } 99 + 100 + static void sp_intc_ack_irq(struct irq_data *d) 101 + { 102 + u32 hwirq = d->hwirq; 103 + 104 + if (unlikely(IS_GPIO_INT(hwirq) && TEST_STATE(hwirq, _IS_EDGE))) { // WORKAROUND 105 + sp_intc_assign_bit(hwirq, REG_INTR_POLARITY, !TEST_STATE(hwirq, _IS_LOW)); 106 + ASSIGN_STATE(hwirq, _IS_ACTIVE, true); 107 + } 108 + 109 + sp_intc_assign_bit(hwirq, REG_INTR_CLEAR, 1); 110 + } 111 + 112 + static void sp_intc_mask_irq(struct irq_data *d) 113 + { 114 + sp_intc_assign_bit(d->hwirq, REG_INTR_MASK, 0); 115 + } 116 + 117 + static void sp_intc_unmask_irq(struct irq_data *d) 118 + { 119 + sp_intc_assign_bit(d->hwirq, REG_INTR_MASK, 1); 120 + } 121 + 122 + static int sp_intc_set_type(struct irq_data *d, unsigned int type) 123 + { 124 + u32 hwirq = d->hwirq; 125 + bool is_edge = !(type & IRQ_TYPE_LEVEL_MASK); 126 + bool is_low = (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING); 127 + 128 + irq_set_handler_locked(d, is_edge ? handle_edge_irq : handle_level_irq); 129 + 130 + if (unlikely(IS_GPIO_INT(hwirq) && is_edge)) { // WORKAROUND 131 + /* store states */ 132 + ASSIGN_STATE(hwirq, _IS_EDGE, is_edge); 133 + ASSIGN_STATE(hwirq, _IS_LOW, is_low); 134 + ASSIGN_STATE(hwirq, _IS_ACTIVE, false); 135 + /* change to level */ 136 + is_edge = false; 137 + } 138 + 139 + sp_intc_assign_bit(hwirq, REG_INTR_TYPE, is_edge); 140 + sp_intc_assign_bit(hwirq, REG_INTR_POLARITY, is_low); 141 + 142 + return 0; 143 + } 144 + 145 + static int sp_intc_get_ext_irq(int ext_num) 146 + { 147 + void __iomem *base = ext_num ? REG_MASKED_EXT1 : REG_MASKED_EXT0; 148 + u32 shift = ext_num ? GROUP_SHIFT_EXT1 : GROUP_SHIFT_EXT0; 149 + u32 groups; 150 + u32 pending_group; 151 + u32 group; 152 + u32 pending_irq; 153 + 154 + groups = readl_relaxed(REG_INTR_GROUP); 155 + pending_group = (groups >> shift) & GROUP_MASK; 156 + if (!pending_group) 157 + return -1; 158 + 159 + group = fls(pending_group) - 1; 160 + pending_irq = readl_relaxed(base + group * 4); 161 + if (!pending_irq) 162 + return -1; 163 + 164 + return (group * 32) + fls(pending_irq) - 1; 165 + } 166 + 167 + static void sp_intc_handle_ext_cascaded(struct irq_desc *desc) 168 + { 169 + struct irq_chip *chip = irq_desc_get_chip(desc); 170 + int ext_num = (uintptr_t)irq_desc_get_handler_data(desc); 171 + int hwirq; 172 + 173 + chained_irq_enter(chip, desc); 174 + 175 + while ((hwirq = sp_intc_get_ext_irq(ext_num)) >= 0) { 176 + if (unlikely(IS_GPIO_INT(hwirq) && TEST_STATE(hwirq, _IS_ACTIVE))) { // WORKAROUND 177 + ASSIGN_STATE(hwirq, _IS_ACTIVE, false); 178 + sp_intc_assign_bit(hwirq, REG_INTR_POLARITY, TEST_STATE(hwirq, _IS_LOW)); 179 + } else { 180 + generic_handle_domain_irq(sp_intc.domain, hwirq); 181 + } 182 + } 183 + 184 + chained_irq_exit(chip, desc); 185 + } 186 + 187 + static struct irq_chip sp_intc_chip = { 188 + .name = "sp_intc", 189 + .irq_ack = sp_intc_ack_irq, 190 + .irq_mask = sp_intc_mask_irq, 191 + .irq_unmask = sp_intc_unmask_irq, 192 + .irq_set_type = sp_intc_set_type, 193 + }; 194 + 195 + static int sp_intc_irq_domain_map(struct irq_domain *domain, 196 + unsigned int irq, irq_hw_number_t hwirq) 197 + { 198 + irq_set_chip_and_handler(irq, &sp_intc_chip, handle_level_irq); 199 + irq_set_chip_data(irq, &sp_intc_chip); 200 + irq_set_noprobe(irq); 201 + 202 + return 0; 203 + } 204 + 205 + static const struct irq_domain_ops sp_intc_dm_ops = { 206 + .xlate = irq_domain_xlate_twocell, 207 + .map = sp_intc_irq_domain_map, 208 + }; 209 + 210 + static int sp_intc_irq_map(struct device_node *node, int i) 211 + { 212 + unsigned int irq; 213 + 214 + irq = irq_of_parse_and_map(node, i); 215 + if (!irq) 216 + return -ENOENT; 217 + 218 + irq_set_chained_handler_and_data(irq, sp_intc_handle_ext_cascaded, (void *)(uintptr_t)i); 219 + 220 + return 0; 221 + } 222 + 223 + static int __init sp_intc_init_dt(struct device_node *node, struct device_node *parent) 224 + { 225 + int i, ret; 226 + 227 + sp_intc.g0 = of_iomap(node, 0); 228 + if (!sp_intc.g0) 229 + return -ENXIO; 230 + 231 + sp_intc.g1 = of_iomap(node, 1); 232 + if (!sp_intc.g1) { 233 + ret = -ENXIO; 234 + goto out_unmap0; 235 + } 236 + 237 + ret = sp_intc_irq_map(node, 0); // EXT_INT0 238 + if (ret) 239 + goto out_unmap1; 240 + 241 + ret = sp_intc_irq_map(node, 1); // EXT_INT1 242 + if (ret) 243 + goto out_unmap1; 244 + 245 + /* initial regs */ 246 + for (i = 0; i < SP_INTC_NR_GROUPS; i++) { 247 + /* all mask */ 248 + writel_relaxed(0, REG_INTR_MASK + i * 4); 249 + /* all edge */ 250 + writel_relaxed(~0, REG_INTR_TYPE + i * 4); 251 + /* all high-active */ 252 + writel_relaxed(0, REG_INTR_POLARITY + i * 4); 253 + /* all EXT_INT0 */ 254 + writel_relaxed(~0, REG_INTR_PRIORITY + i * 4); 255 + /* all clear */ 256 + writel_relaxed(~0, REG_INTR_CLEAR + i * 4); 257 + } 258 + 259 + sp_intc.domain = irq_domain_add_linear(node, SP_INTC_NR_IRQS, 260 + &sp_intc_dm_ops, &sp_intc); 261 + if (!sp_intc.domain) { 262 + ret = -ENOMEM; 263 + goto out_unmap1; 264 + } 265 + 266 + raw_spin_lock_init(&sp_intc.lock); 267 + 268 + return 0; 269 + 270 + out_unmap1: 271 + iounmap(sp_intc.g1); 272 + out_unmap0: 273 + iounmap(sp_intc.g0); 274 + 275 + return ret; 276 + } 277 + 278 + IRQCHIP_DECLARE(sp_intc, "sunplus,sp7021-intc", sp_intc_init_dt);
+9
drivers/reset/Kconfig
··· 231 231 help 232 232 This enables the reset controller driver for the StarFive JH7100 SoC. 233 233 234 + config RESET_SUNPLUS 235 + bool "Sunplus SoCs Reset Driver" if COMPILE_TEST 236 + default ARCH_SUNPLUS 237 + help 238 + This enables the reset driver support for Sunplus SoCs. 239 + The reset lines that can be asserted and deasserted by toggling bits 240 + in a contiguous, exclusive register space. The register is HIWORD_MASKED, 241 + which means each register holds 16 reset lines. 242 + 234 243 config RESET_SUNXI 235 244 bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI 236 245 default ARCH_SUNXI
+1
drivers/reset/Makefile
··· 30 30 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o 31 31 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o 32 32 obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o 33 + obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o 33 34 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o 34 35 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o 35 36 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
+212
drivers/reset/reset-sunplus.c
··· 1 + // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + /* 3 + * SP7021 reset driver 4 + * 5 + * Copyright (C) Sunplus Technology Co., Ltd. 6 + * All rights reserved. 7 + */ 8 + 9 + #include <linux/io.h> 10 + #include <linux/init.h> 11 + #include <linux/mod_devicetable.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/reset-controller.h> 14 + #include <linux/reboot.h> 15 + 16 + /* HIWORD_MASK_REG BITS */ 17 + #define BITS_PER_HWM_REG 16 18 + 19 + /* resets HW info: reg_index_shift */ 20 + static const u32 sp_resets[] = { 21 + /* SP7021: mo_reset0 ~ mo_reset9 */ 22 + 0x00, 23 + 0x02, 24 + 0x03, 25 + 0x04, 26 + 0x05, 27 + 0x06, 28 + 0x07, 29 + 0x08, 30 + 0x09, 31 + 0x0a, 32 + 0x0b, 33 + 0x0d, 34 + 0x0e, 35 + 0x0f, 36 + 0x10, 37 + 0x12, 38 + 0x14, 39 + 0x15, 40 + 0x16, 41 + 0x17, 42 + 0x18, 43 + 0x19, 44 + 0x1a, 45 + 0x1b, 46 + 0x1c, 47 + 0x1d, 48 + 0x1e, 49 + 0x1f, 50 + 0x20, 51 + 0x21, 52 + 0x22, 53 + 0x23, 54 + 0x24, 55 + 0x25, 56 + 0x26, 57 + 0x2a, 58 + 0x2b, 59 + 0x2d, 60 + 0x2e, 61 + 0x30, 62 + 0x31, 63 + 0x32, 64 + 0x33, 65 + 0x3d, 66 + 0x3e, 67 + 0x3f, 68 + 0x42, 69 + 0x44, 70 + 0x4b, 71 + 0x4c, 72 + 0x4d, 73 + 0x4e, 74 + 0x4f, 75 + 0x50, 76 + 0x55, 77 + 0x60, 78 + 0x61, 79 + 0x6a, 80 + 0x6f, 81 + 0x70, 82 + 0x73, 83 + 0x74, 84 + 0x86, 85 + 0x8a, 86 + 0x8b, 87 + 0x8d, 88 + 0x8e, 89 + 0x8f, 90 + 0x90, 91 + 0x92, 92 + 0x93, 93 + 0x94, 94 + 0x95, 95 + 0x96, 96 + 0x97, 97 + 0x98, 98 + 0x99, 99 + }; 100 + 101 + struct sp_reset { 102 + struct reset_controller_dev rcdev; 103 + struct notifier_block notifier; 104 + void __iomem *base; 105 + }; 106 + 107 + static inline struct sp_reset *to_sp_reset(struct reset_controller_dev *rcdev) 108 + { 109 + return container_of(rcdev, struct sp_reset, rcdev); 110 + } 111 + 112 + static int sp_reset_update(struct reset_controller_dev *rcdev, 113 + unsigned long id, bool assert) 114 + { 115 + struct sp_reset *reset = to_sp_reset(rcdev); 116 + int index = sp_resets[id] / BITS_PER_HWM_REG; 117 + int shift = sp_resets[id] % BITS_PER_HWM_REG; 118 + u32 val; 119 + 120 + val = (1 << (16 + shift)) | (assert << shift); 121 + writel(val, reset->base + (index * 4)); 122 + 123 + return 0; 124 + } 125 + 126 + static int sp_reset_assert(struct reset_controller_dev *rcdev, 127 + unsigned long id) 128 + { 129 + return sp_reset_update(rcdev, id, true); 130 + } 131 + 132 + static int sp_reset_deassert(struct reset_controller_dev *rcdev, 133 + unsigned long id) 134 + { 135 + return sp_reset_update(rcdev, id, false); 136 + } 137 + 138 + static int sp_reset_status(struct reset_controller_dev *rcdev, 139 + unsigned long id) 140 + { 141 + struct sp_reset *reset = to_sp_reset(rcdev); 142 + int index = sp_resets[id] / BITS_PER_HWM_REG; 143 + int shift = sp_resets[id] % BITS_PER_HWM_REG; 144 + u32 reg; 145 + 146 + reg = readl(reset->base + (index * 4)); 147 + 148 + return !!(reg & BIT(shift)); 149 + } 150 + 151 + static const struct reset_control_ops sp_reset_ops = { 152 + .assert = sp_reset_assert, 153 + .deassert = sp_reset_deassert, 154 + .status = sp_reset_status, 155 + }; 156 + 157 + static int sp_restart(struct notifier_block *nb, unsigned long mode, 158 + void *cmd) 159 + { 160 + struct sp_reset *reset = container_of(nb, struct sp_reset, notifier); 161 + 162 + sp_reset_assert(&reset->rcdev, 0); 163 + sp_reset_deassert(&reset->rcdev, 0); 164 + 165 + return NOTIFY_DONE; 166 + } 167 + 168 + static int sp_reset_probe(struct platform_device *pdev) 169 + { 170 + struct device *dev = &pdev->dev; 171 + struct sp_reset *reset; 172 + struct resource *res; 173 + int ret; 174 + 175 + reset = devm_kzalloc(dev, sizeof(*reset), GFP_KERNEL); 176 + if (!reset) 177 + return -ENOMEM; 178 + 179 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 180 + reset->base = devm_ioremap_resource(dev, res); 181 + if (IS_ERR(reset->base)) 182 + return PTR_ERR(reset->base); 183 + 184 + reset->rcdev.ops = &sp_reset_ops; 185 + reset->rcdev.owner = THIS_MODULE; 186 + reset->rcdev.of_node = dev->of_node; 187 + reset->rcdev.nr_resets = resource_size(res) / 4 * BITS_PER_HWM_REG; 188 + 189 + ret = devm_reset_controller_register(dev, &reset->rcdev); 190 + if (ret) 191 + return ret; 192 + 193 + reset->notifier.notifier_call = sp_restart; 194 + reset->notifier.priority = 192; 195 + 196 + return register_restart_handler(&reset->notifier); 197 + } 198 + 199 + static const struct of_device_id sp_reset_dt_ids[] = { 200 + {.compatible = "sunplus,sp7021-reset",}, 201 + { /* sentinel */ }, 202 + }; 203 + 204 + static struct platform_driver sp_reset_driver = { 205 + .probe = sp_reset_probe, 206 + .driver = { 207 + .name = "sunplus-reset", 208 + .of_match_table = sp_reset_dt_ids, 209 + .suppress_bind_attrs = true, 210 + }, 211 + }; 212 + builtin_platform_driver(sp_reset_driver);
+88
include/dt-bindings/clock/sunplus,sp7021-clkc.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + /* 3 + * Copyright (C) Sunplus Technology Co., Ltd. 4 + * All rights reserved. 5 + */ 6 + #ifndef _DT_BINDINGS_CLOCK_SUNPLUS_SP7021_H 7 + #define _DT_BINDINGS_CLOCK_SUNPLUS_SP7021_H 8 + 9 + /* gates */ 10 + #define CLK_RTC 0 11 + #define CLK_OTPRX 1 12 + #define CLK_NOC 2 13 + #define CLK_BR 3 14 + #define CLK_SPIFL 4 15 + #define CLK_PERI0 5 16 + #define CLK_PERI1 6 17 + #define CLK_STC0 7 18 + #define CLK_STC_AV0 8 19 + #define CLK_STC_AV1 9 20 + #define CLK_STC_AV2 10 21 + #define CLK_UA0 11 22 + #define CLK_UA1 12 23 + #define CLK_UA2 13 24 + #define CLK_UA3 14 25 + #define CLK_UA4 15 26 + #define CLK_HWUA 16 27 + #define CLK_DDC0 17 28 + #define CLK_UADMA 18 29 + #define CLK_CBDMA0 19 30 + #define CLK_CBDMA1 20 31 + #define CLK_SPI_COMBO_0 21 32 + #define CLK_SPI_COMBO_1 22 33 + #define CLK_SPI_COMBO_2 23 34 + #define CLK_SPI_COMBO_3 24 35 + #define CLK_AUD 25 36 + #define CLK_USBC0 26 37 + #define CLK_USBC1 27 38 + #define CLK_UPHY0 28 39 + #define CLK_UPHY1 29 40 + #define CLK_I2CM0 30 41 + #define CLK_I2CM1 31 42 + #define CLK_I2CM2 32 43 + #define CLK_I2CM3 33 44 + #define CLK_PMC 34 45 + #define CLK_CARD_CTL0 35 46 + #define CLK_CARD_CTL1 36 47 + #define CLK_CARD_CTL4 37 48 + #define CLK_BCH 38 49 + #define CLK_DDFCH 39 50 + #define CLK_CSIIW0 40 51 + #define CLK_CSIIW1 41 52 + #define CLK_MIPICSI0 42 53 + #define CLK_MIPICSI1 43 54 + #define CLK_HDMI_TX 44 55 + #define CLK_VPOST 45 56 + #define CLK_TGEN 46 57 + #define CLK_DMIX 47 58 + #define CLK_TCON 48 59 + #define CLK_GPIO 49 60 + #define CLK_MAILBOX 50 61 + #define CLK_SPIND 51 62 + #define CLK_I2C2CBUS 52 63 + #define CLK_SEC 53 64 + #define CLK_DVE 54 65 + #define CLK_GPOST0 55 66 + #define CLK_OSD0 56 67 + #define CLK_DISP_PWM 57 68 + #define CLK_UADBG 58 69 + #define CLK_FIO_CTL 59 70 + #define CLK_FPGA 60 71 + #define CLK_L2SW 61 72 + #define CLK_ICM 62 73 + #define CLK_AXI_GLOBAL 63 74 + 75 + /* plls */ 76 + #define PLL_A 64 77 + #define PLL_E 65 78 + #define PLL_E_2P5 66 79 + #define PLL_E_25 67 80 + #define PLL_E_112P5 68 81 + #define PLL_F 69 82 + #define PLL_TV 70 83 + #define PLL_TV_A 71 84 + #define PLL_SYS 72 85 + 86 + #define CLK_MAX 73 87 + 88 + #endif
+87
include/dt-bindings/reset/sunplus,sp7021-reset.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + /* 3 + * Copyright (C) Sunplus Technology Co., Ltd. 4 + * All rights reserved. 5 + */ 6 + #ifndef _DT_BINDINGS_RST_SUNPLUS_SP7021_H 7 + #define _DT_BINDINGS_RST_SUNPLUS_SP7021_H 8 + 9 + #define RST_SYSTEM 0 10 + #define RST_RTC 1 11 + #define RST_IOCTL 2 12 + #define RST_IOP 3 13 + #define RST_OTPRX 4 14 + #define RST_NOC 5 15 + #define RST_BR 6 16 + #define RST_RBUS_L00 7 17 + #define RST_SPIFL 8 18 + #define RST_SDCTRL0 9 19 + #define RST_PERI0 10 20 + #define RST_A926 11 21 + #define RST_UMCTL2 12 22 + #define RST_PERI1 13 23 + #define RST_DDR_PHY0 14 24 + #define RST_ACHIP 15 25 + #define RST_STC0 16 26 + #define RST_STC_AV0 17 27 + #define RST_STC_AV1 18 28 + #define RST_STC_AV2 19 29 + #define RST_UA0 20 30 + #define RST_UA1 21 31 + #define RST_UA2 22 32 + #define RST_UA3 23 33 + #define RST_UA4 24 34 + #define RST_HWUA 25 35 + #define RST_DDC0 26 36 + #define RST_UADMA 27 37 + #define RST_CBDMA0 28 38 + #define RST_CBDMA1 29 39 + #define RST_SPI_COMBO_0 30 40 + #define RST_SPI_COMBO_1 31 41 + #define RST_SPI_COMBO_2 32 42 + #define RST_SPI_COMBO_3 33 43 + #define RST_AUD 34 44 + #define RST_USBC0 35 45 + #define RST_USBC1 36 46 + #define RST_UPHY0 37 47 + #define RST_UPHY1 38 48 + #define RST_I2CM0 39 49 + #define RST_I2CM1 40 50 + #define RST_I2CM2 41 51 + #define RST_I2CM3 42 52 + #define RST_PMC 43 53 + #define RST_CARD_CTL0 44 54 + #define RST_CARD_CTL1 45 55 + #define RST_CARD_CTL4 46 56 + #define RST_BCH 47 57 + #define RST_DDFCH 48 58 + #define RST_CSIIW0 49 59 + #define RST_CSIIW1 50 60 + #define RST_MIPICSI0 51 61 + #define RST_MIPICSI1 52 62 + #define RST_HDMI_TX 53 63 + #define RST_VPOST 54 64 + #define RST_TGEN 55 65 + #define RST_DMIX 56 66 + #define RST_TCON 57 67 + #define RST_INTERRUPT 58 68 + #define RST_RGST 59 69 + #define RST_GPIO 60 70 + #define RST_RBUS_TOP 61 71 + #define RST_MAILBOX 62 72 + #define RST_SPIND 63 73 + #define RST_I2C2CBUS 64 74 + #define RST_SEC 65 75 + #define RST_DVE 66 76 + #define RST_GPOST0 67 77 + #define RST_OSD0 68 78 + #define RST_DISP_PWM 69 79 + #define RST_UADBG 70 80 + #define RST_DUMMY_MASTER 71 81 + #define RST_FIO_CTL 72 82 + #define RST_FPGA 73 83 + #define RST_L2SW 74 84 + #define RST_ICM 75 85 + #define RST_AXI_GLOBAL 76 86 + 87 + #endif