diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2018-05-10 09:17:24 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2018-05-10 09:17:24 +1000 |
commit | 2f8f13349beeeb745541dfda26d805b4e3eec239 (patch) | |
tree | 8760a02915b11a43437be9477f097d9ea7d351df | |
parent | aa6cca8becdf485a722d4b5c124fcc4daaaf1d86 (diff) | |
parent | 2b32dbbf4334e22460a6e94186239da74a21142f (diff) | |
download | linux-next-2f8f13349beeeb745541dfda26d805b4e3eec239.tar.gz |
Merge remote-tracking branch 'sunxi/sunxi/for-next'
44 files changed, 1252 insertions, 373 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt index 460ef27b1008..47d2e902ced4 100644 --- a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt +++ b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt @@ -21,6 +21,7 @@ Required properties : - "allwinner,sun50i-a64-r-ccu" - "allwinner,sun50i-h5-ccu" - "allwinner,sun50i-h6-ccu" + - "allwinner,sun50i-h6-r-ccu" - "nextthing,gr8-ccu" - reg: Must contain the registers base address and length @@ -35,7 +36,7 @@ Required properties : For the main CCU on H6, one more clock is needed: - "iosc": the SoC's internal frequency oscillator -For the PRCM CCUs on A83T/H3/A64, two more clocks are needed: +For the PRCM CCUs on A83T/H3/A64/H6, two more clocks are needed: - "pll-periph": the SoC's peripheral PLL from the main CCU - "iosc": the SoC's internal frequency oscillator diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt index d69543701d5d..e319fe5e205a 100644 --- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt @@ -4,6 +4,7 @@ Required properties: - compatible: Should be one of the following: "allwinner,sun4i-a10-sid" "allwinner,sun7i-a20-sid" + "allwinner,sun8i-a83t-sid" "allwinner,sun8i-h3-sid" "allwinner,sun50i-a64-sid" diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 7424351eb248..ec2024ea8b1e 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -997,8 +997,9 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a83t-bananapi-m3.dtb \ sun8i-a83t-cubietruck-plus.dtb \ sun8i-a83t-tbs-a711.dtb \ - sun8i-h2-plus-orangepi-r1.dtb \ sun8i-h2-plus-bananapi-m2-zero.dtb \ + sun8i-h2-plus-libretech-all-h3-cc.dtb \ + sun8i-h2-plus-orangepi-r1.dtb \ sun8i-h2-plus-orangepi-zero.dtb \ sun8i-h3-bananapi-m2-plus.dtb \ sun8i-h3-beelink-x2.dtb \ @@ -1015,6 +1016,8 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-h3-orangepi-plus.dtb \ sun8i-h3-orangepi-plus2e.dtb \ sun8i-r16-bananapi-m2m.dtb \ + sun8i-r16-nintendo-nes-classic.dtb \ + sun8i-r16-nintendo-super-nes-classic.dtb \ sun8i-r16-parrot.dtb \ sun8i-r40-bananapi-m2-ultra.dtb \ sun8i-v3s-licheepi-zero.dtb \ diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 77e8436beed4..3a1c6b45c9a1 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -76,7 +76,7 @@ allwinner,pipeline = "de_fe0-de_be0-lcd0-hdmi"; clocks = <&ccu CLK_AHB_LCD0>, <&ccu CLK_AHB_HDMI0>, <&ccu CLK_AHB_DE_BE0>, <&ccu CLK_AHB_DE_FE0>, - <&ccu CLK_DE_BE0>, <&ccu CLK_AHB_DE_FE0>, + <&ccu CLK_DE_BE0>, <&ccu CLK_DE_FE0>, <&ccu CLK_TCON0_CH1>, <&ccu CLK_HDMI>, <&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>; status = "disabled"; @@ -88,7 +88,7 @@ allwinner,pipeline = "de_fe0-de_be0-lcd0"; clocks = <&ccu CLK_AHB_LCD0>, <&ccu CLK_AHB_DE_BE0>, <&ccu CLK_AHB_DE_FE0>, <&ccu CLK_DE_BE0>, - <&ccu CLK_AHB_DE_FE0>, <&ccu CLK_TCON0_CH0>, + <&ccu CLK_DE_FE0>, <&ccu CLK_TCON0_CH0>, <&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>; status = "disabled"; }; @@ -99,7 +99,7 @@ allwinner,pipeline = "de_fe0-de_be0-lcd0-tve0"; clocks = <&ccu CLK_AHB_TVE0>, <&ccu CLK_AHB_LCD0>, <&ccu CLK_AHB_DE_BE0>, <&ccu CLK_AHB_DE_FE0>, - <&ccu CLK_DE_BE0>, <&ccu CLK_AHB_DE_FE0>, + <&ccu CLK_DE_BE0>, <&ccu CLK_DE_FE0>, <&ccu CLK_TCON0_CH1>, <&ccu CLK_DRAM_TVE0>, <&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>; status = "disabled"; diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts index eae8e267b9ef..3d7b5c848fef 100644 --- a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts +++ b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts @@ -172,8 +172,7 @@ pinctrl-0 = <&mmc0_pins_a>; vmmc-supply = <®_vcc3v3>; bus-width = <4>; - cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; - cd-inverted; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index 971f9be699a7..44f3cad3de75 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -198,6 +198,8 @@ clock-names = "ahb", "mod"; resets = <&ccu RST_BUS_NAND>; reset-names = "ahb"; + pinctrl-names = "default"; + pinctrl-0 = <&nand_pins &nand_pins_cs0 &nand_pins_rb0>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -315,6 +317,37 @@ bias-pull-up; }; + nand_pins: nand-pins { + pins = "PC0", "PC1", "PC2", "PC5", + "PC8", "PC9", "PC10", "PC11", + "PC12", "PC13", "PC14", "PC15"; + function = "nand0"; + }; + + nand_pins_cs0: nand-pins-cs0 { + pins = "PC4"; + function = "nand0"; + bias-pull-up; + }; + + nand_pins_cs1: nand-pins-cs1 { + pins = "PC3"; + function = "nand0"; + bias-pull-up; + }; + + nand_pins_rb0: nand-pins-rb0 { + pins = "PC6"; + function = "nand0"; + bias-pull-up; + }; + + nand_pins_rb1: nand-pins-rb1 { + pins = "PC7"; + function = "nand0"; + bias-pull-up; + }; + pwm0_pins: pwm0 { pins = "PH0"; function = "pwm0"; diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi index a21f2ed07a52..8d278ee001e9 100644 --- a/arch/arm/boot/dts/sun8i-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a33.dtsi @@ -236,6 +236,11 @@ #address-cells = <1>; #size-cells = <0>; reg = <1>; + + tcon0_out_dsi: endpoint@1 { + reg = <1>; + remote-endpoint = <&dsi_in_tcon0>; + }; }; }; }; @@ -280,6 +285,45 @@ #io-channel-cells = <0>; }; + dsi: dsi@1ca0000 { + compatible = "allwinner,sun6i-a31-mipi-dsi"; + reg = <0x01ca0000 0x1000>; + interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ccu CLK_BUS_MIPI_DSI>, + <&ccu CLK_DSI_SCLK>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_MIPI_DSI>; + phys = <&dphy>; + phy-names = "dphy"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + dsi_in_tcon0: endpoint { + remote-endpoint = <&tcon0_out_dsi>; + }; + }; + }; + }; + + dphy: d-phy@1ca1000 { + compatible = "allwinner,sun6i-a31-mipi-dphy"; + reg = <0x01ca1000 0x1000>; + clocks = <&ccu CLK_BUS_MIPI_DSI>, + <&ccu CLK_DSI_DPHY>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_MIPI_DSI>; + status = "disabled"; + #phy-cells = <0>; + }; + fe0: display-frontend@1e00000 { compatible = "allwinner,sun8i-a33-display-frontend"; reg = <0x01e00000 0x20000>; diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 568307639be8..2be23d600957 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -66,6 +66,8 @@ compatible = "arm,cortex-a7"; device_type = "cpu"; operating-points-v2 = <&cpu0_opp_table>; + cci-control-port = <&cci_control0>; + enable-method = "allwinner,sun8i-a83t-smp"; reg = <0>; }; @@ -73,6 +75,8 @@ compatible = "arm,cortex-a7"; device_type = "cpu"; operating-points-v2 = <&cpu0_opp_table>; + cci-control-port = <&cci_control0>; + enable-method = "allwinner,sun8i-a83t-smp"; reg = <1>; }; @@ -80,6 +84,8 @@ compatible = "arm,cortex-a7"; device_type = "cpu"; operating-points-v2 = <&cpu0_opp_table>; + cci-control-port = <&cci_control0>; + enable-method = "allwinner,sun8i-a83t-smp"; reg = <2>; }; @@ -87,6 +93,8 @@ compatible = "arm,cortex-a7"; device_type = "cpu"; operating-points-v2 = <&cpu0_opp_table>; + cci-control-port = <&cci_control0>; + enable-method = "allwinner,sun8i-a83t-smp"; reg = <3>; }; @@ -96,6 +104,8 @@ compatible = "arm,cortex-a7"; device_type = "cpu"; operating-points-v2 = <&cpu1_opp_table>; + cci-control-port = <&cci_control1>; + enable-method = "allwinner,sun8i-a83t-smp"; reg = <0x100>; }; @@ -103,6 +113,8 @@ compatible = "arm,cortex-a7"; device_type = "cpu"; operating-points-v2 = <&cpu1_opp_table>; + cci-control-port = <&cci_control1>; + enable-method = "allwinner,sun8i-a83t-smp"; reg = <0x101>; }; @@ -110,6 +122,8 @@ compatible = "arm,cortex-a7"; device_type = "cpu"; operating-points-v2 = <&cpu1_opp_table>; + cci-control-port = <&cci_control1>; + enable-method = "allwinner,sun8i-a83t-smp"; reg = <0x102>; }; @@ -117,6 +131,8 @@ compatible = "arm,cortex-a7"; device_type = "cpu"; operating-points-v2 = <&cpu1_opp_table>; + cci-control-port = <&cci_control1>; + enable-method = "allwinner,sun8i-a83t-smp"; reg = <0x103>; }; }; @@ -349,6 +365,44 @@ }; }; + cpucfg@1700000 { + compatible = "allwinner,sun8i-a83t-cpucfg"; + reg = <0x01700000 0x400>; + }; + + cci@1790000 { + compatible = "arm,cci-400"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x01790000 0x10000>; + ranges = <0x0 0x01790000 0x10000>; + + cci_control0: slave-if@4000 { + compatible = "arm,cci-400-ctrl-if"; + interface-type = "ace"; + reg = <0x4000 0x1000>; + }; + + cci_control1: slave-if@5000 { + compatible = "arm,cci-400-ctrl-if"; + interface-type = "ace"; + reg = <0x5000 0x1000>; + }; + + pmu@9000 { + compatible = "arm,cci-400-pmu,r1"; + reg = <0x9000 0x5000>; + interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + syscon: syscon@1c00000 { compatible = "allwinner,sun8i-a83t-system-controller", "syscon"; @@ -492,6 +546,11 @@ #size-cells = <0>; }; + sid: eeprom@1c14000 { + compatible = "allwinner,sun8i-a83t-sid"; + reg = <0x1c14000 0x400>; + }; + usb_otg: usb@1c19000 { compatible = "allwinner,sun8i-a83t-musb", "allwinner,sun8i-a33-musb"; @@ -928,6 +987,11 @@ #reset-cells = <1>; }; + r_cpucfg@1f01c00 { + compatible = "allwinner,sun8i-a83t-r-cpucfg"; + reg = <0x1f01c00 0x400>; + }; + r_pio: pinctrl@1f02c00 { compatible = "allwinner,sun8i-a83t-r-pinctrl"; reg = <0x01f02c00 0x400>; diff --git a/arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts b/arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts new file mode 100644 index 000000000000..4db0d4bb65eb --- /dev/null +++ b/arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 Chen-Yu Tsai <wens@csie.org> + */ + +/dts-v1/; +#include "sun8i-h3.dtsi" +#include "sunxi-libretech-all-h3-cc.dtsi" + +/ { + model = "Libre Computer Board ALL-H3-CC H2+"; + compatible = "libretech,all-h3-cc-h2-plus", "allwinner,sun8i-h2-plus"; +}; diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts index 0bc031fe4c56..84cd9c061227 100644 --- a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts +++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts @@ -89,6 +89,23 @@ gpio = <&pio 0 20 GPIO_ACTIVE_HIGH>; }; + reg_vdd_cpux: vdd-cpux-regulator { + compatible = "regulator-gpio"; + regulator-name = "vdd-cpux"; + regulator-type = "voltage"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1300000>; + regulator-ramp-delay = <50>; /* 4ms */ + + gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ + enable-active-high; + gpios-states = <1>; + states = <1100000 0 + 1300000 1>; + }; + wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; @@ -96,6 +113,10 @@ }; }; +&cpu0 { + cpu-supply = <®_vdd_cpux>; +}; + &ehci0 { status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts b/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts index b20a710da7bc..a8b2f0f1c11d 100644 --- a/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts +++ b/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts @@ -6,213 +6,9 @@ /dts-v1/; #include "sun8i-h3.dtsi" - -#include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/input/input.h> +#include "sunxi-libretech-all-h3-cc.dtsi" / { model = "Libre Computer Board ALL-H3-CC H3"; compatible = "libretech,all-h3-cc-h3", "allwinner,sun8i-h3"; - - aliases { - ethernet0 = &emac; - serial0 = &uart0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - connector { - compatible = "hdmi-connector"; - type = "a"; - - port { - hdmi_con_in: endpoint { - remote-endpoint = <&hdmi_out_con>; - }; - }; - }; - - leds { - compatible = "gpio-leds"; - - pwr_led { - label = "librecomputer:green:pwr"; - gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */ - default-state = "on"; - }; - - status_led { - label = "librecomputer:blue:status"; - gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* PA7 */ - }; - }; - - gpio_keys { - compatible = "gpio-keys"; - - power { - label = "power"; - linux,code = <KEY_POWER>; - gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ - }; - }; - - reg_vcc1v2: vcc1v2 { - compatible = "regulator-fixed"; - regulator-name = "vcc1v2"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <®_vcc5v0>; - gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ - enable-active-high; - }; - - reg_vcc3v3: vcc3v3 { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <®_vcc5v0>; - }; - - /* This represents the board's 5V input */ - reg_vcc5v0: vcc5v0 { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - }; - - reg_vcc_dram: vcc-dram { - compatible = "regulator-fixed"; - regulator-name = "vcc-dram"; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <®_vcc5v0>; - gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */ - enable-active-high; - }; - - reg_vcc_io: vcc-io { - compatible = "regulator-fixed"; - regulator-name = "vcc-io"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <®_vcc3v3>; - gpio = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */ - }; - - reg_vdd_cpux: vdd-cpux { - compatible = "regulator-fixed"; - regulator-name = "vdd-cpux"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <®_vcc5v0>; - gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ - enable-active-high; - }; -}; - -&codec { - allwinner,audio-routing = - "Line Out", "LINEOUT", - "MIC1", "Mic", - "Mic", "MBIAS"; - status = "okay"; -}; - -&de { - status = "okay"; -}; - -&ehci0 { - status = "okay"; -}; - -&ehci1 { - status = "okay"; -}; - -&ehci2 { - status = "okay"; -}; - -&ehci3 { - status = "okay"; -}; - -&emac { - phy-handle = <&int_mii_phy>; - phy-mode = "mii"; - allwinner,leds-active-low; - status = "okay"; -}; - -&hdmi { - status = "okay"; -}; - -&hdmi_out { - hdmi_out_con: endpoint { - remote-endpoint = <&hdmi_con_in>; - }; -}; - -&ir { - pinctrl-names = "default"; - pinctrl-0 = <&ir_pins_a>; - status = "okay"; -}; - -&mmc0 { - vmmc-supply = <®_vcc_io>; - bus-width = <4>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ - status = "okay"; -}; - -&ohci0 { - status = "okay"; -}; - -&ohci1 { - status = "okay"; -}; - -&ohci2 { - status = "okay"; -}; - -&ohci3 { - status = "okay"; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; -}; - -&usb_otg { - dr_mode = "host"; - status = "okay"; -}; - -&usbphy { - /* VBUS on USB ports are always on */ - usb0_vbus-supply = <®_vcc5v0>; - usb1_vbus-supply = <®_vcc5v0>; - usb2_vbus-supply = <®_vcc5v0>; - usb3_vbus-supply = <®_vcc5v0>; - status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts index 3328fe583c9b..245fd658defb 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts @@ -99,6 +99,27 @@ gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; }; }; + + reg_vdd_cpux: vdd-cpux-regulator { + compatible = "regulator-gpio"; + regulator-name = "vdd-cpux"; + regulator-type = "voltage"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1300000>; + regulator-ramp-delay = <50>; /* 4ms */ + + gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ + enable-active-high; + gpios-states = <0x1>; + states = <1100000 0x0 + 1300000 0x1>; + }; +}; + +&cpu0 { + cpu-supply = <®_vdd_cpux>; }; &de { @@ -117,6 +138,7 @@ phy-handle = <&int_mii_phy>; phy-mode = "mii"; allwinner,leds-active-low; + status = "okay"; }; &hdmi { diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index 10da8ed7db81..41d57c76f290 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -43,32 +43,62 @@ #include "sunxi-h3-h5.dtsi" / { + cpu0_opp_table: opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp@648000000 { + opp-hz = /bits/ 64 <648000000>; + opp-microvolt = <1040000 1040000 1300000>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@816000000 { + opp-hz = /bits/ 64 <816000000>; + opp-microvolt = <1100000 1100000 1300000>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@1008000000 { + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <1200000 1200000 1300000>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + }; + cpus { #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <0>; + clocks = <&ccu CLK_CPUX>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; }; cpu@1 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <1>; + operating-points-v2 = <&cpu0_opp_table>; }; cpu@2 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <2>; + operating-points-v2 = <&cpu0_opp_table>; }; cpu@3 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <3>; + operating-points-v2 = <&cpu0_opp_table>; }; }; diff --git a/arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts b/arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts new file mode 100644 index 000000000000..fc0658cfa319 --- /dev/null +++ b/arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* Copyright (c) 2016 FUKAUMI Naoki <naobsd@gmail.com> */ + +/dts-v1/; +#include "sun8i-a33.dtsi" +#include "sunxi-common-regulators.dtsi" + +/ { + model = "Nintendo NES Classic Edition"; + compatible = "nintendo,nes-classic", "allwinner,sun8i-r16", + "allwinner,sun8i-a33"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart0 { + /* + * UART0 is available on two ports: PB and PF, both are accessible. + * PF can also be used for the SD card so PB is preferred. + */ + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&nfc { + status = "okay"; + + /* 2Gb Macronix MX30LF2G18AC (3V) */ + nand@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + allwinner,rb = <0>; + nand-ecc-mode = "hw"; + nand-ecc-strength = <16>; + nand-ecc-step-size = <1024>; + }; +}; + +&usb_otg { + status = "okay"; + dr_mode = "otg"; +}; + +&usbphy { + /* VBUS is always on because it is wired to the power supply */ + usb1_vbus-supply = <®_vcc5v0>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts b/arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts new file mode 100644 index 000000000000..80761d7904ec --- /dev/null +++ b/arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 OR X11 +/* Copyright (c) 2018 Miquèl RAYNAL <miquel.raynal@bootlin.com> */ + +/dts-v1/; +#include "sun8i-r16-nintendo-nes-classic.dts" + +/ { + model = "Nintendo SuperNES Classic Edition"; + compatible = "nintendo,super-nes-classic", "nintendo,nes-classic", + "allwinner,sun8i-r16", "allwinner,sun8i-a33"; +}; diff --git a/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts b/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts index a26d72c3f9b5..35859d8f3267 100644 --- a/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts +++ b/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts @@ -87,6 +87,11 @@ }; }; +&ehci1 { + /* Terminus Tech FE 1.1s 4-port USB 2.0 hub here */ + status = "okay"; +}; + &i2c0 { status = "okay"; @@ -170,3 +175,8 @@ pinctrl-0 = <&uart0_pb_pins>; status = "okay"; }; + +&usbphy { + usb1_vbus-supply = <®_vcc5v0>; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index 1be1a02d6df2..c3bff1105e5d 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -822,6 +822,19 @@ status = "disabled"; }; + r_i2c: i2c@1f02400 { + compatible = "allwinner,sun6i-a31-i2c"; + reg = <0x01f02400 0x400>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&r_i2c_pins>; + clocks = <&r_ccu CLK_APB0_I2C>; + resets = <&r_ccu RST_APB0_I2C>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + r_pio: pinctrl@1f02c00 { compatible = "allwinner,sun8i-h3-r-pinctrl"; reg = <0x01f02c00 0x400>; @@ -837,6 +850,11 @@ pins = "PL11"; function = "s_cir_rx"; }; + + r_i2c_pins: r-i2c { + pins = "PL0", "PL1"; + function = "s_i2c"; + }; }; }; }; diff --git a/arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi b/arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi new file mode 100644 index 000000000000..f7ffdd6658a2 --- /dev/null +++ b/arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2017 Chen-Yu Tsai <wens@csie.org> + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + aliases { + ethernet0 = &emac; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + pwr_led { + label = "librecomputer:green:pwr"; + gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */ + default-state = "on"; + }; + + status_led { + label = "librecomputer:blue:status"; + gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* PA7 */ + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + power { + label = "power"; + linux,code = <KEY_POWER>; + gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ + }; + }; + + reg_vcc1v2: vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <®_vcc5v0>; + gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ + enable-active-high; + }; + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <®_vcc5v0>; + }; + + /* This represents the board's 5V input */ + reg_vcc5v0: vcc5v0 { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + reg_vcc_dram: vcc-dram { + compatible = "regulator-fixed"; + regulator-name = "vcc-dram"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <®_vcc5v0>; + gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */ + enable-active-high; + }; + + reg_vcc_io: vcc-io { + compatible = "regulator-fixed"; + regulator-name = "vcc-io"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <®_vcc3v3>; + gpio = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */ + }; + + reg_vdd_cpux: vdd-cpux { + compatible = "regulator-fixed"; + regulator-name = "vdd-cpux"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <®_vcc5v0>; + gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ + enable-active-high; + }; +}; + +&codec { + allwinner,audio-routing = + "Line Out", "LINEOUT", + "MIC1", "Mic", + "Mic", "MBIAS"; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <®_vdd_cpux>; +}; + +&de { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ehci2 { + status = "okay"; +}; + +&ehci3 { + status = "okay"; +}; + +&emac { + phy-handle = <&int_mii_phy>; + phy-mode = "mii"; + allwinner,leds-active-low; + status = "okay"; +}; + +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&ir { + pinctrl-names = "default"; + pinctrl-0 = <&ir_pins_a>; + status = "okay"; +}; + +&mmc0 { + vmmc-supply = <®_vcc_io>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&ohci2 { + status = "okay"; +}; + +&ohci3 { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + +&usbphy { + /* VBUS on USB ports are always on */ + usb0_vbus-supply = <®_vcc5v0>; + usb1_vbus-supply = <®_vcc5v0>; + usb2_vbus-supply = <®_vcc5v0>; + usb3_vbus-supply = <®_vcc5v0>; + status = "okay"; +}; diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 70b4a14ed993..1e9f7af8f70f 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_DMABOUNCE) += dmabounce.o obj-$(CONFIG_SHARP_LOCOMO) += locomo.o obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o obj-$(CONFIG_SHARP_SCOOP) += scoop.o +obj-$(CONFIG_SMP) += secure_cntvoff.o obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o CFLAGS_REMOVE_mcpm_entry.o = -pg diff --git a/arch/arm/common/secure_cntvoff.S b/arch/arm/common/secure_cntvoff.S new file mode 100644 index 000000000000..53fc7bdb6c2e --- /dev/null +++ b/arch/arm/common/secure_cntvoff.S @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2014 Renesas Electronics Corporation + * + * Initialization of CNTVOFF register from secure mode + * + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +ENTRY(secure_cntvoff_init) + .arch armv7-a + /* + * CNTVOFF has to be initialized either from non-secure Hypervisor + * mode or secure Monitor mode with SCR.NS==1. If TrustZone is enabled + * then it should be handled by the secure code. The CPU must implement + * the virtualization extensions. + */ + cps #MON_MODE + mrc p15, 0, r1, c1, c1, 0 /* Get Secure Config */ + orr r0, r1, #1 + mcr p15, 0, r0, c1, c1, 0 /* Set Non Secure bit */ + isb + mov r0, #0 + mcrr p15, 4, r0, r0, c14 /* CNTVOFF = 0 */ + isb + mcr p15, 0, r1, c1, c1, 0 /* Set Secure bit */ + isb + cps #SVC_MODE + ret lr +ENDPROC(secure_cntvoff_init) diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index cb546425da8a..e7632f536633 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -2,9 +2,6 @@ #ifndef __ASM_ARM_CPUTYPE_H #define __ASM_ARM_CPUTYPE_H -#include <linux/stringify.h> -#include <linux/kernel.h> - #define CPUID_ID 0 #define CPUID_CACHETYPE 1 #define CPUID_TCM 2 @@ -98,6 +95,11 @@ /* Qualcomm implemented cores */ #define ARM_CPU_PART_SCORPION 0x510002d0 +#ifndef __ASSEMBLY__ + +#include <linux/stringify.h> +#include <linux/kernel.h> + extern unsigned int processor_id; #ifdef CONFIG_CPU_CP15 @@ -326,4 +328,6 @@ static inline int __attribute_const__ cpuid_feature_extract_field(u32 features, #define cpuid_feature_extract(reg, field) \ cpuid_feature_extract_field(read_cpuid_ext(reg), field) +#endif /* __ASSEMBLY__ */ + #endif diff --git a/arch/arm/include/asm/secure_cntvoff.h b/arch/arm/include/asm/secure_cntvoff.h new file mode 100644 index 000000000000..1f93aee1f630 --- /dev/null +++ b/arch/arm/include/asm/secure_cntvoff.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASMARM_ARCH_CNTVOFF_H +#define __ASMARM_ARCH_CNTVOFF_H + +extern void secure_cntvoff_init(void); + +#endif diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h index 43c1ac696274..2109f123bdfb 100644 --- a/arch/arm/mach-shmobile/common.h +++ b/arch/arm/mach-shmobile/common.h @@ -2,7 +2,6 @@ #ifndef __ARCH_MACH_COMMON_H #define __ARCH_MACH_COMMON_H -extern void shmobile_init_cntvoff(void); extern void shmobile_init_delay(void); extern void shmobile_boot_vector(void); extern unsigned long shmobile_boot_fn; diff --git a/arch/arm/mach-shmobile/headsmp-apmu.S b/arch/arm/mach-shmobile/headsmp-apmu.S index 5672b5849401..d49ab194766a 100644 --- a/arch/arm/mach-shmobile/headsmp-apmu.S +++ b/arch/arm/mach-shmobile/headsmp-apmu.S @@ -11,29 +11,9 @@ #include <linux/linkage.h> #include <asm/assembler.h> -ENTRY(shmobile_init_cntvoff) - /* - * CNTVOFF has to be initialized either from non-secure Hypervisor - * mode or secure Monitor mode with SCR.NS==1. If TrustZone is enabled - * then it should be handled by the secure code - */ - cps #MON_MODE - mrc p15, 0, r1, c1, c1, 0 /* Get Secure Config */ - orr r0, r1, #1 - mcr p15, 0, r0, c1, c1, 0 /* Set Non Secure bit */ - instr_sync - mov r0, #0 - mcrr p15, 4, r0, r0, c14 /* CNTVOFF = 0 */ - instr_sync - mcr p15, 0, r1, c1, c1, 0 /* Set Secure bit */ - instr_sync - cps #SVC_MODE - ret lr -ENDPROC(shmobile_init_cntvoff) - #ifdef CONFIG_SMP ENTRY(shmobile_boot_apmu) - bl shmobile_init_cntvoff + bl secure_cntvoff_init b secondary_startup ENDPROC(shmobile_boot_apmu) #endif diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 80de6be912e1..88fdc1801d90 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -26,6 +26,7 @@ #include <linux/of_fdt.h> #include <linux/of_platform.h> #include <asm/mach/arch.h> +#include <asm/secure_cntvoff.h> #include "common.h" #include "rcar-gen2.h" @@ -70,7 +71,7 @@ void __init rcar_gen2_timer_init(void) void __iomem *base; u32 freq; - shmobile_init_cntvoff(); + secure_cntvoff_init(); if (of_machine_is_compatible("renesas,r8a7745") || of_machine_is_compatible("renesas,r8a77470") || diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index ce53ceaf4cc5..d9c8ecf88ec6 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -51,7 +51,7 @@ config MACH_SUN9I config ARCH_SUNXI_MC_SMP bool depends on SMP - default MACH_SUN9I + default MACH_SUN9I || MACH_SUN8I select ARM_CCI400_PORT_CTRL select ARM_CPU_SUSPEND diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile index 7de9cc286d53..71429aa85143 100644 --- a/arch/arm/mach-sunxi/Makefile +++ b/arch/arm/mach-sunxi/Makefile @@ -1,5 +1,5 @@ CFLAGS_mc_smp.o += -march=armv7-a obj-$(CONFIG_ARCH_SUNXI) += sunxi.o -obj-$(CONFIG_ARCH_SUNXI_MC_SMP) += mc_smp.o +obj-$(CONFIG_ARCH_SUNXI_MC_SMP) += mc_smp.o headsmp.o obj-$(CONFIG_SMP) += platsmp.o diff --git a/arch/arm/mach-sunxi/headsmp.S b/arch/arm/mach-sunxi/headsmp.S new file mode 100644 index 000000000000..32d76be98541 --- /dev/null +++ b/arch/arm/mach-sunxi/headsmp.S @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2018 Chen-Yu Tsai + * Copyright (c) 2018 Bootlin + * + * Chen-Yu Tsai <wens@csie.org> + * Mylène Josserand <mylene.josserand@bootlin.com> + * + * SMP support for sunxi based systems with Cortex A7/A15 + * + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/cputype.h> + +ENTRY(sunxi_mc_smp_cluster_cache_enable) + .arch armv7-a + /* + * Enable cluster-level coherency, in preparation for turning on the MMU. + * + * Also enable regional clock gating and L2 data latency settings for + * Cortex-A15. These settings are from the vendor kernel. + */ + mrc p15, 0, r1, c0, c0, 0 + movw r2, #(ARM_CPU_PART_MASK & 0xffff) + movt r2, #(ARM_CPU_PART_MASK >> 16) + and r1, r1, r2 + movw r2, #(ARM_CPU_PART_CORTEX_A15 & 0xffff) + movt r2, #(ARM_CPU_PART_CORTEX_A15 >> 16) + cmp r1, r2 + bne not_a15 + + /* The following is Cortex-A15 specific */ + + /* ACTLR2: Enable CPU regional clock gates */ + mrc p15, 1, r1, c15, c0, 4 + orr r1, r1, #(0x1 << 31) + mcr p15, 1, r1, c15, c0, 4 + + /* L2ACTLR */ + mrc p15, 1, r1, c15, c0, 0 + /* Enable L2, GIC, and Timer regional clock gates */ + orr r1, r1, #(0x1 << 26) + /* Disable clean/evict from being pushed to external */ + orr r1, r1, #(0x1<<3) + mcr p15, 1, r1, c15, c0, 0 + + /* L2CTRL: L2 data RAM latency */ + mrc p15, 1, r1, c9, c0, 2 + bic r1, r1, #(0x7 << 0) + orr r1, r1, #(0x3 << 0) + mcr p15, 1, r1, c9, c0, 2 + + /* End of Cortex-A15 specific setup */ + not_a15: + + /* Get value of sunxi_mc_smp_first_comer */ + adr r1, first + ldr r0, [r1] + ldr r0, [r1, r0] + + /* Skip cci_enable_port_for_self if not first comer */ + cmp r0, #0 + bxeq lr + b cci_enable_port_for_self + + .align 2 + first: .word sunxi_mc_smp_first_comer - . +ENDPROC(sunxi_mc_smp_cluster_cache_enable) + +ENTRY(sunxi_mc_smp_secondary_startup) + bl sunxi_mc_smp_cluster_cache_enable + bl secure_cntvoff_init + b secondary_startup +ENDPROC(sunxi_mc_smp_secondary_startup) + +ENTRY(sunxi_mc_smp_resume) + bl sunxi_mc_smp_cluster_cache_enable + b cpu_resume +ENDPROC(sunxi_mc_smp_resume) diff --git a/arch/arm/mach-sunxi/mc_smp.c b/arch/arm/mach-sunxi/mc_smp.c index c0246ec54a0a..b4037b603897 100644 --- a/arch/arm/mach-sunxi/mc_smp.c +++ b/arch/arm/mach-sunxi/mc_smp.c @@ -55,22 +55,35 @@ #define CPUCFG_CX_RST_CTRL_L2_RST BIT(8) #define CPUCFG_CX_RST_CTRL_CX_RST(n) BIT(4 + (n)) #define CPUCFG_CX_RST_CTRL_CORE_RST(n) BIT(n) +#define CPUCFG_CX_RST_CTRL_CORE_RST_ALL (0xf << 0) #define PRCM_CPU_PO_RST_CTRL(c) (0x4 + 0x4 * (c)) #define PRCM_CPU_PO_RST_CTRL_CORE(n) BIT(n) #define PRCM_CPU_PO_RST_CTRL_CORE_ALL 0xf #define PRCM_PWROFF_GATING_REG(c) (0x100 + 0x4 * (c)) -#define PRCM_PWROFF_GATING_REG_CLUSTER BIT(4) +/* The power off register for clusters are different from a80 and a83t */ +#define PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I BIT(0) +#define PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I BIT(4) #define PRCM_PWROFF_GATING_REG_CORE(n) BIT(n) #define PRCM_PWR_SWITCH_REG(c, cpu) (0x140 + 0x10 * (c) + 0x4 * (cpu)) #define PRCM_CPU_SOFT_ENTRY_REG 0x164 +/* R_CPUCFG registers, specific to sun8i-a83t */ +#define R_CPUCFG_CLUSTER_PO_RST_CTRL(c) (0x30 + (c) * 0x4) +#define R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(n) BIT(n) +#define R_CPUCFG_CPU_SOFT_ENTRY_REG 0x01a4 + #define CPU0_SUPPORT_HOTPLUG_MAGIC0 0xFA50392F #define CPU0_SUPPORT_HOTPLUG_MAGIC1 0x790DCA3A static void __iomem *cpucfg_base; static void __iomem *prcm_base; static void __iomem *sram_b_smp_base; +static void __iomem *r_cpucfg_base; + +extern void sunxi_mc_smp_secondary_startup(void); +extern void sunxi_mc_smp_resume(void); +static bool is_a83t; static bool sunxi_core_is_cortex_a15(unsigned int core, unsigned int cluster) { @@ -157,6 +170,16 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster) reg &= ~PRCM_CPU_PO_RST_CTRL_CORE(cpu); writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); + if (is_a83t) { + /* assert cpu power-on reset */ + reg = readl(r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + reg &= ~(R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(cpu)); + writel(reg, r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + udelay(10); + } + /* Cortex-A7: hold L1 reset disable signal low */ if (!sunxi_core_is_cortex_a15(cpu, cluster)) { reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG0(cluster)); @@ -180,17 +203,38 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster) /* open power switch */ sunxi_cpu_power_switch_set(cpu, cluster, true); + /* Handle A83T bit swap */ + if (is_a83t) { + if (cpu == 0) + cpu = 4; + } + /* clear processor power gate */ reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); reg &= ~PRCM_PWROFF_GATING_REG_CORE(cpu); writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); udelay(20); + /* Handle A83T bit swap */ + if (is_a83t) { + if (cpu == 4) + cpu = 0; + } + /* de-assert processor power-on reset */ reg = readl(prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); reg |= PRCM_CPU_PO_RST_CTRL_CORE(cpu); writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); + if (is_a83t) { + reg = readl(r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + reg |= R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(cpu); + writel(reg, r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + udelay(10); + } + /* de-assert all processor resets */ reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); reg |= CPUCFG_CX_RST_CTRL_DBG_RST(cpu); @@ -212,6 +256,14 @@ static int sunxi_cluster_powerup(unsigned int cluster) if (cluster >= SUNXI_NR_CLUSTERS) return -EINVAL; + /* For A83T, assert cluster cores resets */ + if (is_a83t) { + reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); + reg &= ~CPUCFG_CX_RST_CTRL_CORE_RST_ALL; /* Core Reset */ + writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); + udelay(10); + } + /* assert ACINACTM */ reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster)); reg |= CPUCFG_CX_CTRL_REG1_ACINACTM; @@ -222,6 +274,16 @@ static int sunxi_cluster_powerup(unsigned int cluster) reg &= ~PRCM_CPU_PO_RST_CTRL_CORE_ALL; writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); + /* assert cluster cores resets */ + if (is_a83t) { + reg = readl(r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + reg &= ~CPUCFG_CX_RST_CTRL_CORE_RST_ALL; + writel(reg, r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + udelay(10); + } + /* assert cluster resets */ reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); reg &= ~CPUCFG_CX_RST_CTRL_DBG_SOC_RST; @@ -252,7 +314,10 @@ static int sunxi_cluster_powerup(unsigned int cluster) /* clear cluster power gate */ reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); - reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER; + if (is_a83t) + reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I; + else + reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I; writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); udelay(20); @@ -300,74 +365,7 @@ static void sunxi_cluster_cache_disable_without_axi(void) } static int sunxi_mc_smp_cpu_table[SUNXI_NR_CLUSTERS][SUNXI_CPUS_PER_CLUSTER]; -static int sunxi_mc_smp_first_comer; - -/* - * Enable cluster-level coherency, in preparation for turning on the MMU. - * - * Also enable regional clock gating and L2 data latency settings for - * Cortex-A15. These settings are from the vendor kernel. - */ -static void __naked sunxi_mc_smp_cluster_cache_enable(void) -{ - asm volatile ( - "mrc p15, 0, r1, c0, c0, 0\n" - "movw r2, #" __stringify(ARM_CPU_PART_MASK & 0xffff) "\n" - "movt r2, #" __stringify(ARM_CPU_PART_MASK >> 16) "\n" - "and r1, r1, r2\n" - "movw r2, #" __stringify(ARM_CPU_PART_CORTEX_A15 & 0xffff) "\n" - "movt r2, #" __stringify(ARM_CPU_PART_CORTEX_A15 >> 16) "\n" - "cmp r1, r2\n" - "bne not_a15\n" - - /* The following is Cortex-A15 specific */ - - /* ACTLR2: Enable CPU regional clock gates */ - "mrc p15, 1, r1, c15, c0, 4\n" - "orr r1, r1, #(0x1<<31)\n" - "mcr p15, 1, r1, c15, c0, 4\n" - - /* L2ACTLR */ - "mrc p15, 1, r1, c15, c0, 0\n" - /* Enable L2, GIC, and Timer regional clock gates */ - "orr r1, r1, #(0x1<<26)\n" - /* Disable clean/evict from being pushed to external */ - "orr r1, r1, #(0x1<<3)\n" - "mcr p15, 1, r1, c15, c0, 0\n" - - /* L2CTRL: L2 data RAM latency */ - "mrc p15, 1, r1, c9, c0, 2\n" - "bic r1, r1, #(0x7<<0)\n" - "orr r1, r1, #(0x3<<0)\n" - "mcr p15, 1, r1, c9, c0, 2\n" - - /* End of Cortex-A15 specific setup */ - "not_a15:\n" - - /* Get value of sunxi_mc_smp_first_comer */ - "adr r1, first\n" - "ldr r0, [r1]\n" - "ldr r0, [r1, r0]\n" - - /* Skip cci_enable_port_for_self if not first comer */ - "cmp r0, #0\n" - "bxeq lr\n" - "b cci_enable_port_for_self\n" - - ".align 2\n" - "first: .word sunxi_mc_smp_first_comer - .\n" - ); -} - -static void __naked sunxi_mc_smp_secondary_startup(void) -{ - asm volatile( - "bl sunxi_mc_smp_cluster_cache_enable\n" - "b secondary_startup" - /* Let compiler know about sunxi_mc_smp_cluster_cache_enable */ - :: "i" (sunxi_mc_smp_cluster_cache_enable) - ); -} +int sunxi_mc_smp_first_comer; static DEFINE_SPINLOCK(boot_lock); @@ -516,7 +514,10 @@ static int sunxi_cluster_powerdown(unsigned int cluster) /* gate cluster power */ pr_debug("%s: gate cluster power\n", __func__); reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); - reg |= PRCM_PWROFF_GATING_REG_CLUSTER; + if (is_a83t) + reg |= PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I; + else + reg |= PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I; writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); udelay(20); @@ -598,8 +599,12 @@ out: return !ret; } -static bool sunxi_mc_smp_cpu_can_disable(unsigned int __unused) +static bool sunxi_mc_smp_cpu_can_disable(unsigned int cpu) { + /* CPU0 hotplug not handled for sun8i-a83t */ + if (is_a83t) + if (cpu == 0) + return false; return true; } #endif @@ -637,16 +642,6 @@ static bool __init sunxi_mc_smp_cpu_table_init(void) */ typedef typeof(cpu_reset) phys_reset_t; -static void __init __naked sunxi_mc_smp_resume(void) -{ - asm volatile( - "bl sunxi_mc_smp_cluster_cache_enable\n" - "b cpu_resume" - /* Let compiler know about sunxi_mc_smp_cluster_cache_enable */ - :: "i" (sunxi_mc_smp_cluster_cache_enable) - ); -} - static int __init nocache_trampoline(unsigned long __unused) { phys_reset_t phys_reset; @@ -692,12 +687,14 @@ struct sunxi_mc_smp_nodes { struct device_node *prcm_node; struct device_node *cpucfg_node; struct device_node *sram_node; + struct device_node *r_cpucfg_node; }; /* This structure holds SoC-specific bits tied to an enable-method string. */ struct sunxi_mc_smp_data { const char *enable_method; int (*get_smp_nodes)(struct sunxi_mc_smp_nodes *nodes); + bool is_a83t; }; static void __init sunxi_mc_smp_put_nodes(struct sunxi_mc_smp_nodes *nodes) @@ -705,6 +702,7 @@ static void __init sunxi_mc_smp_put_nodes(struct sunxi_mc_smp_nodes *nodes) of_node_put(nodes->prcm_node); of_node_put(nodes->cpucfg_node); of_node_put(nodes->sram_node); + of_node_put(nodes->r_cpucfg_node); memset(nodes, 0, sizeof(*nodes)); } @@ -734,11 +732,42 @@ static int __init sun9i_a80_get_smp_nodes(struct sunxi_mc_smp_nodes *nodes) return 0; } +static int __init sun8i_a83t_get_smp_nodes(struct sunxi_mc_smp_nodes *nodes) +{ + nodes->prcm_node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a83t-r-ccu"); + if (!nodes->prcm_node) { + pr_err("%s: PRCM not available\n", __func__); + return -ENODEV; + } + + nodes->cpucfg_node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a83t-cpucfg"); + if (!nodes->cpucfg_node) { + pr_err("%s: CPUCFG not available\n", __func__); + return -ENODEV; + } + + nodes->r_cpucfg_node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a83t-r-cpucfg"); + if (!nodes->r_cpucfg_node) { + pr_err("%s: RCPUCFG not available\n", __func__); + return -ENODEV; + } + + return 0; +} + static const struct sunxi_mc_smp_data sunxi_mc_smp_data[] __initconst = { { .enable_method = "allwinner,sun9i-a80-smp", .get_smp_nodes = sun9i_a80_get_smp_nodes, }, + { + .enable_method = "allwinner,sun8i-a83t-smp", + .get_smp_nodes = sun8i_a83t_get_smp_nodes, + .is_a83t = true, + }, }; static int __init sunxi_mc_smp_init(void) @@ -746,6 +775,7 @@ static int __init sunxi_mc_smp_init(void) struct sunxi_mc_smp_nodes nodes = { 0 }; struct device_node *node; struct resource res; + void __iomem *addr; int i, ret; /* @@ -771,6 +801,8 @@ static int __init sunxi_mc_smp_init(void) break; } + is_a83t = sunxi_mc_smp_data[i].is_a83t; + of_node_put(node); if (ret) return -ENODEV; @@ -808,12 +840,23 @@ static int __init sunxi_mc_smp_init(void) goto err_unmap_prcm; } - sram_b_smp_base = of_io_request_and_map(nodes.sram_node, 0, - "sunxi-mc-smp"); - if (IS_ERR(sram_b_smp_base)) { - ret = PTR_ERR(sram_b_smp_base); - pr_err("%s: failed to map secure SRAM\n", __func__); - goto err_unmap_release_cpucfg; + if (is_a83t) { + r_cpucfg_base = of_io_request_and_map(nodes.r_cpucfg_node, + 0, "sunxi-mc-smp"); + if (IS_ERR(r_cpucfg_base)) { + ret = PTR_ERR(r_cpucfg_base); + pr_err("%s: failed to map R-CPUCFG registers\n", + __func__); + goto err_unmap_release_cpucfg; + } + } else { + sram_b_smp_base = of_io_request_and_map(nodes.sram_node, 0, + "sunxi-mc-smp"); + if (IS_ERR(sram_b_smp_base)) { + ret = PTR_ERR(sram_b_smp_base); + pr_err("%s: failed to map secure SRAM\n", __func__); + goto err_unmap_release_cpucfg; + } } /* Configure CCI-400 for boot cluster */ @@ -821,15 +864,18 @@ static int __init sunxi_mc_smp_init(void) if (ret) { pr_err("%s: failed to configure boot cluster: %d\n", __func__, ret); - goto err_unmap_release_secure_sram; + goto err_unmap_release_sram_rcpucfg; } /* We don't need the device nodes anymore */ sunxi_mc_smp_put_nodes(&nodes); /* Set the hardware entry point address */ - writel(__pa_symbol(sunxi_mc_smp_secondary_startup), - prcm_base + PRCM_CPU_SOFT_ENTRY_REG); + if (is_a83t) + addr = r_cpucfg_base + R_CPUCFG_CPU_SOFT_ENTRY_REG; + else + addr = prcm_base + PRCM_CPU_SOFT_ENTRY_REG; + writel(__pa_symbol(sunxi_mc_smp_secondary_startup), addr); /* Actually enable multi cluster SMP */ smp_set_ops(&sunxi_mc_smp_smp_ops); @@ -838,9 +884,14 @@ static int __init sunxi_mc_smp_init(void) return 0; -err_unmap_release_secure_sram: - iounmap(sram_b_smp_base); - of_address_to_resource(nodes.sram_node, 0, &res); +err_unmap_release_sram_rcpucfg: + if (is_a83t) { + iounmap(r_cpucfg_base); + of_address_to_resource(nodes.r_cpucfg_node, 0, &res); + } else { + iounmap(sram_b_smp_base); + of_address_to_resource(nodes.sram_node, 0, &res); + } release_mem_region(res.start, resource_size(&res)); err_unmap_release_cpucfg: iounmap(cpucfg_base); diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 5e9602ce1573..de4b0e932f22 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <asm/mach/arch.h> +#include <asm/secure_cntvoff.h> static const char * const sunxi_board_dt_compat[] = { "allwinner,sun4i-a10", @@ -62,7 +63,6 @@ MACHINE_END static const char * const sun8i_board_dt_compat[] = { "allwinner,sun8i-a23", "allwinner,sun8i-a33", - "allwinner,sun8i-a83t", "allwinner,sun8i-h2-plus", "allwinner,sun8i-h3", "allwinner,sun8i-r40", @@ -75,6 +75,24 @@ DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i Family") .dt_compat = sun8i_board_dt_compat, MACHINE_END +static void __init sun8i_a83t_cntvoff_init(void) +{ +#ifdef CONFIG_SMP + secure_cntvoff_init(); +#endif +} + +static const char * const sun8i_a83t_cntvoff_board_dt_compat[] = { + "allwinner,sun8i-a83t", + NULL, +}; + +DT_MACHINE_START(SUN8I_A83T_CNTVOFF_DT, "Allwinner A83t board") + .init_early = sun8i_a83t_cntvoff_init, + .init_time = sun6i_timer_init, + .dt_compat = sun8i_a83t_cntvoff_board_dt_compat, +MACHINE_END + static const char * const sun9i_board_dt_compat[] = { "allwinner,sun9i-a80", NULL, diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index 8bebe7da5ed9..c31f90a49481 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -6,10 +6,11 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h3-cc.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo-plus2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb -dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb -dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo-plus2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb diff --git a/arch/arm64/boot/dts/allwinner/axp803.dtsi b/arch/arm64/boot/dts/allwinner/axp803.dtsi index ff8af52743ff..e5eae8bafc42 100644 --- a/arch/arm64/boot/dts/allwinner/axp803.dtsi +++ b/arch/arm64/boot/dts/allwinner/axp803.dtsi @@ -146,5 +146,10 @@ regulator-max-microvolt = <3000000>; regulator-name = "rtc-ldo"; }; + + reg_drivevbus: drivevbus { + regulator-name = "drivevbus"; + status = "disabled"; + }; }; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts index 2250dec9974c..0716b1441187 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts @@ -86,6 +86,10 @@ }; }; +&ehci0 { + status = "okay"; +}; + &ehci1 { status = "okay"; }; @@ -155,6 +159,10 @@ status = "okay"; }; +&ohci0 { + status = "okay"; +}; + &ohci1 { status = "okay"; }; @@ -167,6 +175,7 @@ reg = <0x3a3>; interrupt-parent = <&r_intc>; interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + x-powers,drive-vbus-en; /* set N_VBUSEN as output pin */ }; }; @@ -254,6 +263,11 @@ regulator-name = "vcc-wifi-io"; }; +®_drivevbus { + regulator-name = "usb0-vbus"; + status = "okay"; +}; + ®_eldo1 { regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -294,6 +308,13 @@ status = "okay"; }; +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + &usbphy { + usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ + usb0_vbus-supply = <®_drivevbus>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts new file mode 100644 index 000000000000..95e113ce8699 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 BayLibre, SAS + * Author: Neil Armstrong <narmstrong@baylibre.com> + */ + +/dts-v1/; +#include "sun50i-h5.dtsi" +#include <arm/sunxi-libretech-all-h3-cc.dtsi> + +/ { + model = "Libre Computer Board ALL-H3-CC H5"; + compatible = "libretech,all-h3-cc-h5", "allwinner,sun50i-h5"; +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi index e237c05cfdb4..62d646baac3c 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi @@ -47,7 +47,7 @@ #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { compatible = "arm,cortex-a53", "arm,armv8"; device_type = "cpu"; reg = <0>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts index d36de5eb81f3..b6f2d6b2ecae 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts @@ -22,6 +22,16 @@ }; }; +&r_i2c { + status = "okay"; + + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + #clock-cells = <0>; + }; +}; + &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_ph_pins>; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 56563150d61a..c72da8cd9ef5 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -4,6 +4,8 @@ */ #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/clock/sun50i-h6-ccu.h> +#include <dt-bindings/reset/sun50i-h6-ccu.h> / { interrupt-parent = <&gic>; @@ -115,7 +117,7 @@ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&ccu 26>, <&osc24M>, <&osc32k>; + clocks = <&ccu CLK_APB1>, <&osc24M>, <&osc32k>; clock-names = "apb", "hosc", "losc"; gpio-controller; #gpio-cells = <3>; @@ -134,8 +136,8 @@ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 70>; - resets = <&ccu 21>; + clocks = <&ccu CLK_BUS_UART0>; + resets = <&ccu RST_BUS_UART0>; status = "disabled"; }; @@ -145,8 +147,8 @@ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 71>; - resets = <&ccu 22>; + clocks = <&ccu CLK_BUS_UART1>; + resets = <&ccu RST_BUS_UART1>; status = "disabled"; }; @@ -156,8 +158,8 @@ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 72>; - resets = <&ccu 23>; + clocks = <&ccu CLK_BUS_UART2>; + resets = <&ccu RST_BUS_UART2>; status = "disabled"; }; @@ -167,9 +169,59 @@ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; reg-shift = <2>; reg-io-width = <4>; - clocks = <&ccu 73>; - resets = <&ccu 24>; + clocks = <&ccu CLK_BUS_UART3>; + resets = <&ccu RST_BUS_UART3>; status = "disabled"; }; + + r_ccu: clock@7010000 { + compatible = "allwinner,sun50i-h6-r-ccu"; + reg = <0x07010000 0x400>; + clocks = <&osc24M>, <&osc32k>, <&iosc>, + <&ccu CLK_PLL_PERIPH0>; + clock-names = "hosc", "losc", "iosc", "pll-periph"; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + r_intc: interrupt-controller@7021000 { + compatible = "allwinner,sun50i-h6-r-intc", + "allwinner,sun6i-a31-r-intc"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x07021000 0x400>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + }; + + r_pio: pinctrl@7022000 { + compatible = "allwinner,sun50i-h6-r-pinctrl"; + reg = <0x07022000 0x400>; + interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&r_ccu 2>, <&osc24M>, <&osc32k>; + clock-names = "apb", "hosc", "losc"; + gpio-controller; + #gpio-cells = <3>; + interrupt-controller; + #interrupt-cells = <3>; + + r_i2c_pins: r-i2c { + pins = "PL0", "PL1"; + function = "s_i2c"; + }; + }; + + r_i2c: i2c@7081400 { + compatible = "allwinner,sun6i-a31-i2c"; + reg = <0x07081400 0x400>; + interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&r_ccu 8>; + resets = <&r_ccu 4>; + pinctrl-names = "default"; + pinctrl-0 = <&r_i2c_pins>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; }; }; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index de6d06ac790b..23a7fdcfc4e0 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -94,7 +94,7 @@ obj-$(CONFIG_ARCH_SPRD) += sprd/ obj-$(CONFIG_ARCH_STI) += st/ obj-$(CONFIG_ARCH_STRATIX10) += socfpga/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ -obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/ +obj-$(CONFIG_SUNXI_CCU) += sunxi-ng/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-y += ti/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 79dfd296c3d1..826674d090fd 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -16,6 +16,11 @@ config SUN50I_H6_CCU default ARM64 && ARCH_SUNXI depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST +config SUN50I_H6_R_CCU + bool "Support for the Allwinner H6 PRCM CCU" + default ARM64 && ARCH_SUNXI + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST + config SUN4I_A10_CCU bool "Support for the Allwinner A10/A20 CCU" default MACH_SUN4I diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 128a40ee5c5e..49454700f2e5 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -1,28 +1,29 @@ # SPDX-License-Identifier: GPL-2.0 # Common objects -lib-$(CONFIG_SUNXI_CCU) += ccu_common.o -lib-$(CONFIG_SUNXI_CCU) += ccu_mmc_timing.o -lib-$(CONFIG_SUNXI_CCU) += ccu_reset.o +obj-y += ccu_common.o +obj-y += ccu_mmc_timing.o +obj-y += ccu_reset.o # Base clock types -lib-$(CONFIG_SUNXI_CCU) += ccu_div.o -lib-$(CONFIG_SUNXI_CCU) += ccu_frac.o -lib-$(CONFIG_SUNXI_CCU) += ccu_gate.o -lib-$(CONFIG_SUNXI_CCU) += ccu_mux.o -lib-$(CONFIG_SUNXI_CCU) += ccu_mult.o -lib-$(CONFIG_SUNXI_CCU) += ccu_phase.o -lib-$(CONFIG_SUNXI_CCU) += ccu_sdm.o +obj-y += ccu_div.o +obj-y += ccu_frac.o +obj-y += ccu_gate.o +obj-y += ccu_mux.o +obj-y += ccu_mult.o +obj-y += ccu_phase.o +obj-y += ccu_sdm.o # Multi-factor clocks -lib-$(CONFIG_SUNXI_CCU) += ccu_nk.o -lib-$(CONFIG_SUNXI_CCU) += ccu_nkm.o -lib-$(CONFIG_SUNXI_CCU) += ccu_nkmp.o -lib-$(CONFIG_SUNXI_CCU) += ccu_nm.o -lib-$(CONFIG_SUNXI_CCU) += ccu_mp.o +obj-y += ccu_nk.o +obj-y += ccu_nkm.o +obj-y += ccu_nkmp.o +obj-y += ccu_nm.o +obj-y += ccu_mp.o # SoC support obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o +obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o @@ -37,12 +38,3 @@ obj-$(CONFIG_SUN8I_R40_CCU) += ccu-sun8i-r40.o obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o - -# The lib-y file goals is supposed to work only in arch/*/lib or lib/. In our -# case, we want to use that goal, but even though lib.a will be properly -# generated, it will not be linked in, eventually resulting in a linker error -# for missing symbols. -# -# We can work around that by explicitly adding lib.a to the obj-y goal. This is -# an undocumented behaviour, but works well for now. -obj-$(CONFIG_SUNXI_CCU) += lib.a diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c new file mode 100644 index 000000000000..27554eaf6929 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.xyz> + */ + +#include <linux/clk-provider.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_nm.h" + +#include "ccu-sun50i-h6-r.h" + +/* + * Information about AR100 and AHB/APB clocks in R_CCU are gathered from + * clock definitions in the BSP source code. + */ + +static const char * const ar100_r_apb2_parents[] = { "osc24M", "osc32k", + "pll-periph0", "iosc" }; +static const struct ccu_mux_var_prediv ar100_r_apb2_predivs[] = { + { .index = 2, .shift = 0, .width = 5 }, +}; + +static struct ccu_div ar100_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + + .mux = { + .shift = 24, + .width = 2, + + .var_predivs = ar100_r_apb2_predivs, + .n_var_predivs = ARRAY_SIZE(ar100_r_apb2_predivs), + }, + + .common = { + .reg = 0x000, + .features = CCU_FEATURE_VARIABLE_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("ar100", + ar100_r_apb2_parents, + &ccu_div_ops, + 0), + }, +}; + +static CLK_FIXED_FACTOR(r_ahb_clk, "r-ahb", "ar100", 1, 1, 0); + +static struct ccu_div r_apb1_clk = { + .div = _SUNXI_CCU_DIV(0, 2), + + .common = { + .reg = 0x00c, + .hw.init = CLK_HW_INIT("r-apb1", + "r-ahb", + &ccu_div_ops, + 0), + }, +}; + +static struct ccu_div r_apb2_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + + .mux = { + .shift = 24, + .width = 2, + + .var_predivs = ar100_r_apb2_predivs, + .n_var_predivs = ARRAY_SIZE(ar100_r_apb2_predivs), + }, + + .common = { + .reg = 0x010, + .features = CCU_FEATURE_VARIABLE_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("r-apb2", + ar100_r_apb2_parents, + &ccu_div_ops, + 0), + }, +}; + +/* + * Information about the gate/resets are gathered from the clock header file + * in the BSP source code, although most of them are unused. The existence + * of the hardware block is verified with "3.1 Memory Mapping" chapter in + * "Allwinner H6 V200 User Manual V1.1"; and the parent APB buses are verified + * with "3.3.2.1 System Bus Tree" chapter inthe same document. + */ +static SUNXI_CCU_GATE(r_apb1_timer_clk, "r-apb1-timer", "r-apb1", + 0x11c, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb1_twd_clk, "r-apb1-twd", "r-apb1", + 0x12c, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb1_pwm_clk, "r-apb1-pwm", "r-apb1", + 0x13c, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb2_uart_clk, "r-apb2-uart", "r-apb2", + 0x18c, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb2_i2c_clk, "r-apb2-i2c", "r-apb2", + 0x19c, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb1_ir_clk, "r-apb1-ir", "r-apb1", + 0x1cc, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb1_w1_clk, "r-apb1-w1", "r-apb1", + 0x1cc, BIT(0), 0); + +/* Information of IR(RX) mod clock is gathered from BSP source code */ +static const char * const r_mod0_default_parents[] = { "osc32k", "osc24M" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir", + r_mod0_default_parents, 0x1c0, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +/* + * BSP didn't use the 1-wire function at all now, and the information about + * this mod clock is guessed from the IR mod clock above. The existence of + * this mod clock is proven by BSP clock header, and the dividers are verified + * by contents in the 1-wire related chapter of the User Manual. + */ + +static SUNXI_CCU_MP_WITH_MUX_GATE(w1_clk, "w1", + r_mod0_default_parents, 0x1e0, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static struct ccu_common *sun50i_h6_r_ccu_clks[] = { + &ar100_clk.common, + &r_apb1_clk.common, + &r_apb2_clk.common, + &r_apb1_timer_clk.common, + &r_apb1_twd_clk.common, + &r_apb1_pwm_clk.common, + &r_apb2_uart_clk.common, + &r_apb2_i2c_clk.common, + &r_apb1_ir_clk.common, + &r_apb1_w1_clk.common, + &ir_clk.common, + &w1_clk.common, +}; + +static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = { + .hws = { + [CLK_AR100] = &ar100_clk.common.hw, + [CLK_R_AHB] = &r_ahb_clk.hw, + [CLK_R_APB1] = &r_apb1_clk.common.hw, + [CLK_R_APB2] = &r_apb2_clk.common.hw, + [CLK_R_APB1_TIMER] = &r_apb1_timer_clk.common.hw, + [CLK_R_APB1_TWD] = &r_apb1_twd_clk.common.hw, + [CLK_R_APB1_PWM] = &r_apb1_pwm_clk.common.hw, + [CLK_R_APB2_UART] = &r_apb2_uart_clk.common.hw, + [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw, + [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw, + [CLK_R_APB1_W1] = &r_apb1_w1_clk.common.hw, + [CLK_IR] = &ir_clk.common.hw, + [CLK_W1] = &w1_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = { + [RST_R_APB1_TIMER] = { 0x11c, BIT(16) }, + [RST_R_APB1_TWD] = { 0x12c, BIT(16) }, + [RST_R_APB1_PWM] = { 0x13c, BIT(16) }, + [RST_R_APB2_UART] = { 0x18c, BIT(16) }, + [RST_R_APB2_I2C] = { 0x19c, BIT(16) }, + [RST_R_APB1_IR] = { 0x1cc, BIT(16) }, + [RST_R_APB1_W1] = { 0x1ec, BIT(16) }, +}; + +static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = { + .ccu_clks = sun50i_h6_r_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_h6_r_ccu_clks), + + .hw_clks = &sun50i_h6_r_hw_clks, + + .resets = sun50i_h6_r_ccu_resets, + .num_resets = ARRAY_SIZE(sun50i_h6_r_ccu_resets), +}; + +static void __init sunxi_r_ccu_init(struct device_node *node, + const struct sunxi_ccu_desc *desc) +{ + void __iomem *reg; + + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (IS_ERR(reg)) { + pr_err("%pOF: Could not map the clock registers\n", node); + return; + } + + sunxi_ccu_probe(node, reg, desc); +} + +static void __init sun50i_h6_r_ccu_setup(struct device_node *node) +{ + sunxi_r_ccu_init(node, &sun50i_h6_r_ccu_desc); +} +CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu", + sun50i_h6_r_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h new file mode 100644 index 000000000000..782117dc0b28 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2017 Icenowy Zheng <icenowy@aosc.xyz> + */ + +#ifndef _CCU_SUN50I_H6_R_H +#define _CCU_SUN50I_H6_R_H + +#include <dt-bindings/clock/sun50i-h6-r-ccu.h> +#include <dt-bindings/reset/sun50i-h6-r-ccu.h> + +/* AHB/APB bus clocks are not exported except APB1 for R_PIO */ +#define CLK_R_AHB 1 + +#define CLK_R_APB2 3 + +#define CLK_NUMBER (CLK_W1 + 1) + +#endif /* _CCU_SUN50I_H6_R_H */ diff --git a/include/dt-bindings/clock/sun50i-h6-r-ccu.h b/include/dt-bindings/clock/sun50i-h6-r-ccu.h new file mode 100644 index 000000000000..76136132a13e --- /dev/null +++ b/include/dt-bindings/clock/sun50i-h6-r-ccu.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.xyz> + */ + +#ifndef _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_ +#define _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_ + +#define CLK_AR100 0 + +#define CLK_R_APB1 2 + +#define CLK_R_APB1_TIMER 4 +#define CLK_R_APB1_TWD 5 +#define CLK_R_APB1_PWM 6 +#define CLK_R_APB2_UART 7 +#define CLK_R_APB2_I2C 8 +#define CLK_R_APB1_IR 9 +#define CLK_R_APB1_W1 10 + +#define CLK_IR 11 +#define CLK_W1 12 + +#endif /* _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_ */ diff --git a/include/dt-bindings/reset/sun50i-h6-r-ccu.h b/include/dt-bindings/reset/sun50i-h6-r-ccu.h new file mode 100644 index 000000000000..01c84dba49a4 --- /dev/null +++ b/include/dt-bindings/reset/sun50i-h6-r-ccu.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz> + */ + +#ifndef _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_ +#define _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_ + +#define RST_R_APB1_TIMER 0 +#define RST_R_APB1_TWD 1 +#define RST_R_APB1_PWM 2 +#define RST_R_APB2_UART 3 +#define RST_R_APB2_I2C 4 +#define RST_R_APB1_IR 5 +#define RST_R_APB1_W1 6 + +#endif /* _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_ */ |