]> git.ipfire.org Git - people/arne_f/kernel.git/commitdiff
sunxi: hdmi thermal dma pmw enable
authorImport from armbian <no@mail>
Thu, 1 Mar 2018 10:13:24 +0000 (11:13 +0100)
committerArne Fitzenreiter <arne_f@ipfire.org>
Fri, 14 May 2021 13:17:16 +0000 (15:17 +0200)
14 files changed:
Documentation/devicetree/bindings/clock/sun8i-de2.txt
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
arch/arm64/boot/dts/allwinner/axp803.dtsi
arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
drivers/clk/sunxi-ng/ccu-sun8i-de2.c
drivers/dma/sun6i-dma.c
drivers/pwm/pwm-sun4i.c

index 631d27cd89d6205b1b4cf180df7148c8b8e6bb6e..a7d558a2b9b2a7508a630e21b0c17fad75dba5eb 100644 (file)
@@ -4,22 +4,28 @@ Allwinner Display Engine 2.0 Clock Control Binding
 Required properties :
 - compatible: must contain one of the following compatibles:
                - "allwinner,sun8i-a83t-de2-clk"
+               - "allwinner,sun8i-h3-de2-clk"
                - "allwinner,sun8i-v3s-de2-clk"
+               - "allwinner,sun50i-a64-de2-clk"
                - "allwinner,sun50i-h5-de2-clk"
 
 - reg: Must contain the registers base address and length
 - clocks: phandle to the clocks feeding the display engine subsystem.
          Three are needed:
-  - "mod": the display engine module clock
+  - "mod": the display engine module clock (on A83T it's the DE PLL)
   - "bus": the bus clock for the whole display engine subsystem
 - clock-names: Must contain the clock names described just above
 - resets: phandle to the reset control for the display engine subsystem.
 - #clock-cells : must contain 1
 - #reset-cells : must contain 1
 
+Additional required properties for "allwinner,sun50i-a64-de2-clk" :
+- allwinner,sram: See Documentation/devicetree/bindings/sram/sunxi-sram.txt,
+                 should be the SRAM C section on A64 SoC.
+
 Example:
 de2_clocks: clock@1000000 {
-       compatible = "allwinner,sun8i-a83t-de2-clk";
+       compatible = "allwinner,sun8i-h3-de2-clk";
        reg = <0x01000000 0x100000>;
        clocks = <&ccu CLK_BUS_DE>,
                 <&ccu CLK_DE>;
index 92441086cabad07cb9bfe44095cfbd605ef03e38..84739924bc77eaeee0db62f918eaefeb5174ab15 100644 (file)
@@ -87,18 +87,19 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-h3-tcon
    * allwinner,sun8i-v3s-tcon
+   * allwinner,sun50i-a64-tcon0
+   * allwinner,sun50i-a64-tcon1
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
  - clocks: phandles to the clocks feeding the TCON. Three are needed:
    - 'ahb': the interface clocks
-   - 'tcon-ch0': The clock driving the TCON channel 0
  - resets: phandles to the reset controllers driving the encoder
    - "lcd": the reset line for the TCON channel 0
 
  - clock-names: the clock names mentioned above
  - reset-names: the reset names mentioned above
- - clock-output-names: Name of the pixel clock created
 
 - ports: A ports node with endpoint definitions as defined in
   Documentation/devicetree/bindings/media/video-interfaces.txt. The
@@ -112,7 +113,25 @@ Required properties:
   channel the endpoint is associated to. If that property is not
   present, the endpoint number will be used as the channel number.
 
-On SoCs other than the A33 and V3s, there is one more clock required:
+For the following compatibles:
+   * allwinner,sun5i-a13-tcon
+   * allwinner,sun6i-a31-tcon
+   * allwinner,sun6i-a31s-tcon
+   * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-v3s-tcon
+   * allwinner,snu50i-a64-tcon0
+there is one more clock and one more property required:
+ - clocks:
+   - 'tcon-ch0': The clock driving the TCON channel 0
+ - clock-output-names: Name of the pixel clock created
+
+For the following compatibles:
+   * allwinner,sun5i-a13-tcon
+   * allwinner,sun6i-a31-tcon
+   * allwinner,sun6i-a31s-tcon
+   * allwinner,sun8i-h3-tcon
+   * allwinner,sun50i-a64-tcon1
+there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
 DRC
@@ -207,6 +226,10 @@ supported.
 Required properties:
   - compatible: value must be one of:
     * allwinner,sun8i-v3s-de2-mixer
+    * allwinner,sun8i-h3-de2-mixer0
+    * allwinner,sun8i-h3-de2-mixer1
+    * allwinner,sun50i-a64-de2-mixer0
+    * allwinner,sun50i-a64-de2-mixer1
   - reg: base address and size of the memory-mapped region.
   - clocks: phandles to the clocks feeding the mixer
     * bus: the mixer interface clock
@@ -218,7 +241,6 @@ Required properties:
   Documentation/devicetree/bindings/media/video-interfaces.txt. The
   first port should be the input endpoints, the second one the output
 
-
 Display Engine Pipeline
 -----------------------
 
@@ -233,7 +255,9 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-h3-display-engine
     * allwinner,sun8i-v3s-display-engine
+    * allwinner,sun50i-a64-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
     frontends (DE 1.0) or mixers (DE 2.0) available.
index ff8af52743ff4c2e714e233d5fd21e38d4c2d9f9..3a8615231b7c8e3edd61deb2ee8a4e46ef7b4148 100644 (file)
        interrupt-controller;
        #interrupt-cells = <1>;
 
+       ac_power_supply: ac-power-supply {
+               compatible = "x-powers,axp221-ac-power-supply";
+               status = "disabled";
+       };
+
+       battery_power_supply: battery-power-supply {
+               compatible = "x-powers,axp803-battery-power-supply";
+               status = "disabled";
+       };
+
        regulators {
                /* Default work frequency for buck regulators */
                x-powers,dcdc-freq = <3000>;
                        regulator-name = "rtc-ldo";
                };
        };
+
+       usb_power_supply: usb_power_supply {
+               compatible = "x-powers,axp803-usb-power-supply";
+               status = "disabled";
+       };
 };
index 45bdbfb961261becf2fb940fb9da19ee0f99560a..19b6817c46ba9bdeb7447dc6d6b287b5c7ec7fcc 100644 (file)
        };
 };
 
+&de {
+       status = "okay";
+};
+
+&ehci0 {
+       status = "okay";
+};
+
 &ehci1 {
        status = "okay";
 };
        pinctrl-0 = <&rgmii_pins>;
        phy-mode = "rgmii";
        phy-handle = <&ext_rgmii_phy>;
+       phy-supply = <&reg_dc1sw>;
+       status = "okay";
+};
+
+&hdmi {
+       hvcc-supply = <&reg_dldo1>;
        status = "okay";
 };
 
        bias-pull-up;
 };
 
-&mdio {
+&external_mdio {
        ext_rgmii_phy: ethernet-phy@1 {
                compatible = "ethernet-phy-ieee802.3-c22";
                reg = <1>;
        };
 };
 
+&mixer1 {
+       status = "okay";
+};
+
 &mmc0 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc0_pins>;
        status = "okay";
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &ohci1 {
        status = "okay";
 };
 
 #include "axp803.dtsi"
 
+&reg_aldo1 {
+       regulator-min-microvolt = <2800000>;
+       regulator-max-microvolt = <2800000>;
+       regulator-name = "vcc-csi";
+};
+
 &reg_aldo2 {
        regulator-always-on;
        regulator-min-microvolt = <1800000>;
 
 &reg_aldo3 {
        regulator-always-on;
-       regulator-min-microvolt = <3000000>;
-       regulator-max-microvolt = <3000000>;
+       regulator-min-microvolt = <2700000>;
+       regulator-max-microvolt = <3300000>;
        regulator-name = "vcc-pll-avcc";
 };
 
 &reg_dc1sw {
+       regulator-always-on;
        regulator-name = "vcc-phy";
 };
 
        regulator-name = "vcc-wifi";
 };
 
+&reg_dldo3 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "avdd-csi";
+};
+
 &reg_dldo4 {
        regulator-min-microvolt = <1800000>;
        regulator-max-microvolt = <3300000>;
        regulator-name = "cpvdd";
 };
 
+&reg_eldo3 {
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-name = "vdd-1v8-csi";
+};
+
 &reg_fldo1 {
        regulator-min-microvolt = <1200000>;
        regulator-max-microvolt = <1200000>;
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
+&tcon1 {
+       status = "okay";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index aa0b3844ad63e895595b22c215bafa351be01a90..fa05f3881d4ca7eddabb0d06a4a0113cc24ebc4e 100644 (file)
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index 2ef779b027572ee6a314f9d0c6a2bf83ac53b21e..389a38704f660ea221c4861ff0a7ad408a2cb799 100644 (file)
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index 6ecb70062a6fa47e911385ae09d506579fa5a016..376d7bfaec31b406014b7d1487506c68e411d3bb 100644 (file)
        compatible = "xunlong,orangepi-win", "allwinner,sun50i-a64";
 
        aliases {
+               ethernet0 = &emac;
                serial0 = &uart0;
+               serial1 = &uart1;
        };
 
        chosen {
                stdout-path = "serial0:115200n8";
        };
 
-       reg_vcc3v3: vcc3v3 {
-               compatible = "regulator-fixed";
-               regulator-name = "vcc3v3";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-       };
-
-       reg_usb1_vbus: usb1-vbus {
-               compatible = "regulator-fixed";
-               regulator-name = "usb1-vbus";
-               regulator-min-microvolt = <5000000>;
-               regulator-max-microvolt = <5000000>;
-               regulator-boot-on;
-               enable-active-high;
-               gpio = <&pio 3 7 GPIO_ACTIVE_HIGH>;
-               status = "okay";
-       };
-
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
                reset-gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
        };
 };
 
+&de {
+       status = "okay";
+};
+
 &ehci0 {
        status = "okay";
 };
        status = "okay";
 };
 
+&emac {
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins>;
+       phy-mode = "rgmii";
+       phy-handle = <&ext_rgmii_phy>;
+       phy-supply = <&reg_dc1sw>;
+       status = "okay";
+};
+
+&hdmi {
+       hvcc-supply = <&reg_dldo1>;
+       status = "okay";
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+       status = "okay";
+};
+
+&i2c1_pins {
+       bias-pull-up;
+};
+
+&external_mdio {
+       ext_rgmii_phy: ethernet-phy@1 {
+               compatible = "ethernet-phy-ieee802.3-c22";
+               reg = <1>;
+       };
+};
+
+&mixer1 {
+       status = "okay";
+};
+
 &mmc0 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc0_pins>;
-       vmmc-supply = <&reg_vcc3v3>;
+       vmmc-supply = <&reg_dcdc1>;
        cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
        cd-inverted;
+       disable-wp;
+       bus-width = <4>;
        status = "okay";
 };
 
        };
 };
 
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&reg_dcdc1>;
+       bus-width = <8>;
+       non-removable;
+       cap-mmc-hw-reset;
+       status = "okay";
+};
+
 &ohci0 {
        status = "okay";
 };
         axp803: pmic@3a3 {
                 compatible = "x-powers,axp803";
                 reg = <0x3a3>;
-                interrupt-parent = <&nmi_intc>;
+                interrupt-parent = <&r_intc>;
                 interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
         };
 };
 
-#include <arm/axp803.dtsi>
+#include "axp803.dtsi"
 
 &reg_aldo1 {
        regulator-min-microvolt = <2800000>;
 
 &reg_dcdc2 {
        regulator-always-on;
-       regulator-min-microvolt = <1000000>;
+       regulator-min-microvolt = <1040000>;
        regulator-max-microvolt = <1300000>;
        regulator-name = "vdd-cpux";
 };
 &reg_dldo1 {
        regulator-min-microvolt = <3300000>;
        regulator-max-microvolt = <3300000>;
-       regulator-name = "vcc-hdmi";
+       regulator-name = "vcc-hdmi-dsi";
 };
 
 &reg_dldo2 {
        regulator-name = "vcc-1v2-hsic";
 };
 
+/*
+ * The A64 chip cannot work without this regulator off, although
+ * it seems to be only driving the AR100 core.
+ * Maybe we don't still know well about CPUs domain.
+ */
 &reg_fldo2 {
        regulator-always-on;
        regulator-min-microvolt = <1100000>;
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
+&tcon1 {
+       status = "okay";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
        status = "okay";
 };
 
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+       status = "okay";
+};
+
 &usbphy {
-       usb1_vbus-supply = <&reg_usb1_vbus>;
        status = "okay";
 };
 
index 806442d3e846881d01e3c971da41af1db869b14f..5bb28070f023cbb5dd4b70b126241edccf752191 100644 (file)
        chosen {
                stdout-path = "serial0:115200n8";
        };
+
+       wifi_pwrseq: wifi_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
+       };
+};
+
+&de {
+       status = "okay";
 };
 
 &ehci0 {
        pinctrl-0 = <&rmii_pins>;
        phy-mode = "rmii";
        phy-handle = <&ext_rmii_phy1>;
+       phy-supply = <&reg_dc1sw>;
        status = "okay";
+};
 
+&hdmi {
+       hvcc-supply = <&reg_dldo1>;
+       status = "okay";
 };
 
 &i2c1 {
        };
 };
 
+&mixer1 {
+       status = "okay";
+};
+
 &mmc0 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc0_pins>;
        status = "okay";
 };
 
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       vmmc-supply = <&reg_dldo4>;
+       vqmmc-supply = <&reg_eldo1>;
+       mmc-pwrseq = <&wifi_pwrseq>;
+       non-removable;
+       bus-width = <4>;
+       status = "okay";
+};
+
 &ohci0 {
        status = "okay";
 };
 
 #include "axp803.dtsi"
 
+&ac_power_supply {
+       status = "okay";
+};
+
+&battery_power_supply {
+       status = "okay";
+};
+
 &reg_aldo2 {
        regulator-always-on;
        regulator-min-microvolt = <1800000>;
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
+&tcon1 {
+       status = "okay";
+};
+
 /* On Exp and Euler connectors */
 &uart0 {
        pinctrl-names = "default";
index 0eb2acedf8c3bc5ff2b4bbde4cddfde4d8c204ad..f9f9484948fd0e2cdc29270bf126a66cc4722989 100644 (file)
@@ -47,6 +47,8 @@
 
 #include "sun50i-a64-sopine.dtsi"
 
+#include <dt-bindings/gpio/gpio.h>
+
 / {
        model = "SoPine with baseboard";
        compatible = "pine64,sopine-baseboard", "pine64,sopine",
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
        };
+
+       wifi_pwrseq: wifi_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
+       };
+};
+
+&de {
+       status = "okay";
 };
 
 &ehci0 {
        pinctrl-0 = <&rgmii_pins>;
        phy-mode = "rgmii";
        phy-handle = <&ext_rgmii_phy>;
+       phy-supply = <&reg_dc1sw>;
+       status = "okay";
+};
+
+&hdmi {
+       hvcc-supply = <&reg_dldo1>;
        status = "okay";
 };
 
        };
 };
 
+&mixer1 {
+       status = "okay";
+};
+
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       vmmc-supply = <&reg_dldo4>;
+       vqmmc-supply = <&reg_eldo1>;
+       mmc-pwrseq = <&wifi_pwrseq>;
+       non-removable;
+       bus-width = <4>;
+       status = "okay";
+};
+
 &mmc2 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc2_pins>;
        regulator-name = "vcc-wifi";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
+&tcon1 {
+       status = "okay";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index 466a80f79641d9cbe6bae7f57c63ce2bba003916..8134c6831e3fe1e879662eae18add38004eea87c 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/clock/sun8i-de2.h>
 #include <dt-bindings/clock/sun50i-a64-ccu.h>
 #include <dt-bindings/clock/sun8i-r-ccu.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/sun8i-de2.h>
 #include <dt-bindings/reset/sun50i-a64-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+#include <dt-bindings/clock/sun8i-r-ccu.h>
+#include <dt-bindings/reset/sun8i-r-ccu.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
        interrupt-parent = <&gic>;
        #address-cells = <1>;
        #size-cells = <1>;
 
+       chosen {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               simplefb_lcd: framebuffer-lcd {
+                       compatible = "allwinner,simple-framebuffer",
+                                    "simple-framebuffer";
+                       allwinner,pipeline = "mixer0-lcd0";
+                       clocks = <&display_clocks CLK_BUS_MIXER0>,
+                                <&ccu CLK_BUS_TCON0>, <&ccu CLK_BUS_TCON0>,
+                                <&display_clocks CLK_MIXER0>,
+                                <&ccu CLK_TCON0>;
+                       status = "disabled";
+               };
+
+               simplefb_hdmi: framebuffer-hdmi {
+                       compatible = "allwinner,simple-framebuffer",
+                                    "simple-framebuffer";
+                       allwinner,pipeline = "mixer1-lcd1-hdmi";
+                       clocks = <&display_clocks CLK_BUS_MIXER1>,
+                                <&ccu CLK_BUS_TCON1>, <&ccu CLK_BUS_HDMI>,
+                                <&display_clocks CLK_MIXER1>,
+                                <&ccu CLK_TCON1>, <&ccu CLK_HDMI>,
+                                <&ccu CLK_HDMI_DDC>;
+                       status = "disabled";
+               };
+       };
+
+       cpu_opp_table: opp_table {
+               compatible = "operating-points-v2";
+               opp-shared;
+
+               opp@408000000 {
+                       opp-hz = /bits/ 64 <408000000>;
+                       opp-microvolt = <1000000 1000000 1300000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               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 = <1080000 1080000 1300000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@912000000 {
+                      opp-hz = /bits/ 64 <912000000>;
+                      opp-microvolt = <1120000 1120000 1300000>;
+                      clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@960000000 {
+                      opp-hz = /bits/ 64 <960000000>;
+                      opp-microvolt = <1160000 1160000 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 */
+               };
+
+               opp@1056000000 {
+                      opp-hz = /bits/ 64 <1056000000>;
+                      opp-microvolt = <1240000 1240000 1300000>;
+                      clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@1104000000 {
+                      opp-hz = /bits/ 64 <1104000000>;
+                      opp-microvolt = <1260000 1260000 1300000>;
+                      clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@1152000000 {
+                      opp-hz = /bits/ 64 <1152000000>;
+                      opp-microvolt = <1300000 1300000 1300000>;
+                      clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                        device_type = "cpu";
                        reg = <0>;
                        enable-method = "psci";
+                       operating-points-v2 = <&cpu_opp_table>;
+                       cpu-supply = <&reg_cpu_fallback>;
+                       #cooling-cells = <2>;
                };
 
                cpu1: cpu@1 {
                        device_type = "cpu";
                        reg = <1>;
                        enable-method = "psci";
+                       operating-points-v2 = <&cpu_opp_table>;
                };
 
                cpu2: cpu@2 {
                        device_type = "cpu";
                        reg = <2>;
                        enable-method = "psci";
+                       operating-points-v2 = <&cpu_opp_table>;
                };
 
                cpu3: cpu@3 {
                        device_type = "cpu";
                        reg = <3>;
                        enable-method = "psci";
+                       operating-points-v2 = <&cpu_opp_table>;
                };
        };
 
+       de: display-engine {
+               compatible = "allwinner,sun50i-a64-display-engine";
+               allwinner,pipelines = <&mixer0>,
+                                     <&mixer1>;
+               status = "disabled";
+       };
+
        osc24M: osc24M_clk {
                #clock-cells = <0>;
                compatible = "fixed-clock";
                method = "smc";
        };
 
+       thermal-zones {
+               cpu-thermal {
+                       /* milliseconds */
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+                       thermal-sensors = <&ths>;
+
+                       trips {
+                               cpu_warm: cpu_warm {
+                                       temperature = <65000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               cpu_hot_pre: cpu_hot_pre {
+                                       temperature = <70000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               cpu_hot: cpu_hot {
+                                       temperature = <75000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               cpu_very_hot_pre: cpu_very_hot_pre {
+                                       temperature = <85000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               cpu_very_hot: cpu_very_hot {
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               cpu_crit: cpu_crit {
+                                       temperature = <105000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+
+                       cooling-maps {
+                               cpu_warm_limit_cpu {
+                                       trip = <&cpu_warm>;
+                                       cooling-device = <&cpu0 THERMAL_NO_LIMIT 2>;
+                               };
+
+                               cpu_hot_pre_limit_cpu {
+                                       trip = <&cpu_hot_pre>;
+                                       cooling-device = <&cpu0 2 3>;
+                               };
+
+                               cpu_hot_limit_cpu {
+                                       trip = <&cpu_hot>;
+                                       cooling-device = <&cpu0 3 4>;
+                               };
+
+                               cpu_very_hot_pre_limit_cpu {
+                                       trip = <&cpu_very_hot>;
+                                       cooling-device = <&cpu0 5 6>;
+                               };
+
+                               cpu_very_hot_limit_cpu {
+                                       trip = <&cpu_very_hot>;
+                                       cooling-device = <&cpu0 7 THERMAL_NO_LIMIT>;
+                               };
+                       };
+               };
+       };
+
+       reg_cpu_fallback: reg_cpu_fallback  {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd-cpux-dummy";
+               regulator-min-microvolt = <1100000>;
+               regulator-max-microvolt = <1100000>;
+       };
+
+       reserved-memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               cma: linux,cma {
+                       compatible = "shared-dma-pool";
+                       reusable;
+                       size = <0x4000000>;
+                       alignment = <0x2000>;
+                       linux,cma-default;
+               };
+       };
        timer {
                compatible = "arm,armv8-timer";
                fsl,erratum-a008585;
                #size-cells = <1>;
                ranges;
 
+               ths: thermal-sensor@1c25000 {
+                       compatible = "allwinner,sun50i-h5-ths";
+                       reg = <0x01c25000 0x100>;
+                       clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>;
+                       clock-names = "bus", "mod";
+                       resets = <&ccu RST_BUS_THS>;
+                       #thermal-sensor-cells = <0>;
+                       #io-channel-cells = <0>;
+               };
+
+               display_clocks: clock@1000000 {
+                       compatible = "allwinner,sun50i-a64-de2-clk";
+                       reg = <0x01000000 0x100000>;
+                       clocks = <&ccu CLK_DE>,
+                                <&ccu CLK_BUS_DE>;
+                       clock-names = "mod",
+                                     "bus";
+                       resets = <&ccu RST_BUS_DE>;
+                       allwinner,sram = <&de2_sram 1>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               mixer0: mixer@1100000 {
+                       compatible = "allwinner,sun50i-a64-de2-mixer0";
+                       reg = <0x01100000 0x100000>;
+                       clocks = <&display_clocks CLK_MIXER0>,
+                                <&display_clocks CLK_BUS_MIXER0>;
+                       clock-names = "mod",
+                                     "bus";
+                       resets = <&display_clocks RST_MIXER0>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               mixer0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       mixer0_out_tcon0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon0_in_mixer0>;
+                                       };
+
+                                       mixer0_out_tcon1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tcon1_in_mixer0>;
+                                       };
+                               };
+                       };
+               };
+
+               mixer1: mixer@1200000 {
+                       compatible = "allwinner,sun50i-a64-de2-mixer1";
+                       reg = <0x01200000 0x100000>;
+                       clocks = <&display_clocks CLK_MIXER1>,
+                                <&display_clocks CLK_BUS_MIXER1>;
+                       clock-names = "mod",
+                                     "bus";
+                       resets = <&display_clocks RST_MIXER1>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               mixer1_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       mixer1_out_tcon1: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon1_in_mixer1>;
+                                       };
+
+                                       mixer1_out_tcon0: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tcon0_in_mixer1>;
+                                       };
+                               };
+                       };
+               };
+
+               tcon0: lcd-controller@01c0c000 {
+                       compatible = "allwinner,sun50i-a64-tcon0";
+                       reg = <0x01c0c000 0x1000>;
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_TCON0>,
+                                <&ccu CLK_TCON0>;
+                       clock-names = "ahb",
+                                     "tcon-ch0";
+                       clock-output-names = "tcon-pixel-clock";
+                       resets = <&ccu RST_BUS_TCON0>;
+                       reset-names = "lcd";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               tcon0_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       tcon0_in_mixer0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&mixer0_out_tcon0>;
+                                       };
+
+                                       tcon0_in_mixer1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&mixer1_out_tcon0>;
+                                       };
+                               };
+
+                               tcon0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+                               };
+                       };
+               };
+
+               tcon1: lcd-controller@1c0d000 {
+                       compatible = "allwinner,sun50i-a64-tcon1";
+                       reg = <0x01c0d000 0x1000>;
+                       interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_TCON1>,
+                                <&ccu CLK_TCON1>;
+                       clock-names = "ahb",
+                                     "tcon-ch1";
+                       resets = <&ccu RST_BUS_TCON1>;
+                       reset-names = "lcd";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               tcon1_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       tcon1_in_mixer1: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&mixer1_out_tcon1>;
+                                       };
+
+                                       tcon1_in_mixer0: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&mixer0_out_tcon1>;
+                                       };
+                               };
+
+                               tcon1_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       tcon1_out_hdmi: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&hdmi_in_tcon1>;
+                                       };
+                               };
+                       };
+               };
+
                syscon: syscon@1c00000 {
                        compatible = "allwinner,sun50i-a64-system-controller",
                                "syscon";
                        reg = <0x01c00000 0x1000>;
                };
 
+               dma: dma-controller@1c02000 {
+                       compatible = "allwinner,sun50i-a64-dma";
+                       reg = <0x01c02000 0x1000>;
+                       interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_DMA>;
+                       dma-channels = <8>;
+                       dma-requests = <27>;
+                       resets = <&ccu RST_BUS_DMA>;
+                       #dma-cells = <1>;
+               };
+
+               sram-controller@1c00000 {
+                       compatible = "allwinner,sun50i-a64-sram-controller";
+                       reg = <0x01c00000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       sram_c: sram@18000 {
+                               compatible = "mmio-sram";
+                               reg = <0x00018000 0x28000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x00018000 0x28000>;
+
+                               de2_sram: sram-section@0 {
+                                       compatible = "allwinner,sun50i-a64-sram-c";
+                                       reg = <0x0000 0x28000>;
+                               };
+                       };
+               };
+
                mmc0: mmc@1c0f000 {
                        compatible = "allwinner,sun50i-a64-mmc";
                        reg = <0x01c0f000 0x1000>;
                                function = "i2c1";
                        };
 
+                       lcd_rgb666_pins: lcd-rgb666 {
+                               pins = "PD0", "PD1", "PD2", "PD3", "PD4",
+                                      "PD5", "PD6", "PD7", "PD8", "PD9",
+                                      "PD10", "PD11", "PD12", "PD13",
+                                      "PD14", "PD15", "PD16", "PD17",
+                                      "PD18", "PD19", "PD20", "PD21";
+                               function = "lcd0";
+                       };
+
                        mmc0_pins: mmc0-pins {
                                pins = "PF0", "PF1", "PF2", "PF3",
                                       "PF4", "PF5";
                                bias-pull-up;
                        };
 
+                       pwm0_pins: pwm0 {
+                               pins = "PD22";
+                               function = "pwm";
+                       };
+
                        rmii_pins: rmii_pins {
                                pins = "PD10", "PD11", "PD13", "PD14", "PD17",
                                       "PD18", "PD19", "PD20", "PD22", "PD23";
                        };
                };
 
+               pwm: pwm@01c21400 {
+                       compatible = "allwinner,sun50i-a64-pwm";
+                       reg = <0x01c21400 0x8>;
+                       clocks = <&osc24M>;
+                       #pwm-cells = <3>;
+                       status = "disabled";
+               };
+
                spi0: spi@01c68000 {
                        compatible = "allwinner,sun8i-h3-spi";
                        reg = <0x01c68000 0x1000>;
                        mdio: mdio {
                                #address-cells = <1>;
                                #size-cells = <0>;
+                               compatible = "snps,dwmac-mdio";
                        };
+
+                       mdio-mux {
+                               compatible = "allwinner,sun8i-h3-mdio-mux";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               mdio-parent-bus = <&mdio>;
+                               /* Only one MDIO is usable at the time */
+                               internal_mdio: mdio@1 {
+                                       compatible = "allwinner,sun50i-a64-emac";
+                                       reg = <1>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       int_mii_phy: ethernet-phy@1 {
+                                               compatible = "ethernet-phy-ieee802.3-c22";
+                                               reg = <1>;
+                                               clocks = <&ccu CLK_BUS_EMAC>;
+                                               resets = <&ccu RST_BUS_EMAC>;
+                                       };
+                               };
+
+                               external_mdio: mdio@2 {
+                                       reg = <2>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+                       };
+               };
+
+               mali: gpu@1c40000 {
+                       compatible = "allwinner,sun50i-a64-mali",
+                                    "allwinner,sun7i-a20-mali", "arm,mali-400";
+                       reg = <0x01c40000 0x10000>;
+                       interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "gp",
+                                         "gpmmu",
+                                         "pp0",
+                                         "ppmmu0",
+                                         "pp1",
+                                         "ppmmu1",
+                                         "pmu";
+                       clocks = <&ccu CLK_BUS_GPU>, <&ccu CLK_GPU>;
+                       clock-names = "bus", "core";
+                       resets = <&ccu RST_BUS_GPU>;
+                       memory-region = <&cma>;
+
+                       assigned-clocks = <&ccu CLK_GPU>;
+                       assigned-clock-rates = <384000000>;
                };
 
                gic: interrupt-controller@1c81000 {
                        #interrupt-cells = <3>;
                };
 
+               hdmi: hdmi@1ee0000 {
+                       compatible = "allwinner,h3-dw-hdmi";
+                       reg = <0x01ee0000 0x10000>,
+                             <0x01ef0000 0x10000>;
+                       reg-io-width = <1>;
+                       interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI>,
+                                <&ccu CLK_HDMI_DDC>;
+                       clock-names = "iahb", "isfr", "iddc";
+                       resets = <&ccu RST_BUS_HDMI0>, <&ccu RST_BUS_HDMI1>;
+                       reset-names = "hdmi", "ddc";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       hdmi_in_tcon1: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon1_out_hdmi>;
+                                       };
+                               };
+                       };
+               };
+
                rtc: rtc@1f00000 {
                        compatible = "allwinner,sun6i-a31-rtc";
                        reg = <0x01f00000 0x54>;
                        #reset-cells = <1>;
                };
 
+               r_i2c: i2c@1f02400 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x01f02400 0x400>;
+                       interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&r_ccu CLK_APB0_I2C>;
+                       resets = <&r_ccu RST_APB0_I2C>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
                r_pio: pinctrl@01f02c00 {
                        compatible = "allwinner,sun50i-a64-r-pinctrl";
                        reg = <0x01f02c00 0x400>;
                                pins = "PL0", "PL1";
                                function = "s_rsb";
                        };
+
+                       r_i2c_pins_a: i2c-a {
+                               pins = "PL8", "PL9";
+                               function = "s_i2c";
+                       };
                };
 
                r_rsb: rsb@1f03400 {
index 7e3cd0bd597dca0f4447f180ca1074afeb7fe71a..e1c9104a336e8b8206b17eb1cbbc0c91359edf41 100644 (file)
@@ -519,7 +519,7 @@ static struct ccu_div tcon1_clk = {
                .hw.init        = CLK_HW_INIT_PARENTS("tcon1",
                                                      tcon1_parents,
                                                      &ccu_div_ops,
-                                                     CLK_SET_RATE_PARENT),
+                                                     0),
        },
 };
 
index 5cdaf52669e443de01829f699bd72231db6bbf05..38b029b7bb5a1ee98ff2d0b4b2f6d8c2fe020ccd 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
+#include <linux/soc/sunxi/sunxi_sram.h>
 
 #include "ccu_common.h"
 #include "ccu_div.h"
@@ -46,6 +47,13 @@ static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
 static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
                   CLK_SET_RATE_PARENT);
 
+static SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4,
+                  CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4,
+                  CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4,
+                  CLK_SET_RATE_PARENT);
+
 static struct ccu_common *sun8i_a83t_de2_clks[] = {
        &mixer0_clk.common,
        &mixer1_clk.common,
@@ -55,6 +63,20 @@ static struct ccu_common *sun8i_a83t_de2_clks[] = {
        &bus_mixer1_clk.common,
        &bus_wb_clk.common,
 
+       &mixer0_div_a83_clk.common,
+       &mixer1_div_a83_clk.common,
+       &wb_div_a83_clk.common,
+};
+
+static struct ccu_common *sun8i_h3_de2_clks[] = {
+       &mixer0_clk.common,
+       &mixer1_clk.common,
+       &wb_clk.common,
+
+       &bus_mixer0_clk.common,
+       &bus_mixer1_clk.common,
+       &bus_wb_clk.common,
+
        &mixer0_div_clk.common,
        &mixer1_div_clk.common,
        &wb_div_clk.common,
@@ -72,6 +94,23 @@ static struct ccu_common *sun8i_v3s_de2_clks[] = {
 };
 
 static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = {
+       .hws    = {
+               [CLK_MIXER0]            = &mixer0_clk.common.hw,
+               [CLK_MIXER1]            = &mixer1_clk.common.hw,
+               [CLK_WB]                = &wb_clk.common.hw,
+
+               [CLK_BUS_MIXER0]        = &bus_mixer0_clk.common.hw,
+               [CLK_BUS_MIXER1]        = &bus_mixer1_clk.common.hw,
+               [CLK_BUS_WB]            = &bus_wb_clk.common.hw,
+
+               [CLK_MIXER0_DIV]        = &mixer0_div_a83_clk.common.hw,
+               [CLK_MIXER1_DIV]        = &mixer1_div_a83_clk.common.hw,
+               [CLK_WB_DIV]            = &wb_div_a83_clk.common.hw,
+       },
+       .num    = CLK_NUMBER,
+};
+
+static struct clk_hw_onecell_data sun8i_h3_de2_hw_clks = {
        .hws    = {
                [CLK_MIXER0]            = &mixer0_clk.common.hw,
                [CLK_MIXER1]            = &mixer1_clk.common.hw,
@@ -128,11 +167,21 @@ static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
        .num_resets     = ARRAY_SIZE(sun8i_a83t_de2_resets),
 };
 
+static const struct sunxi_ccu_desc sun8i_h3_de2_clk_desc = {
+       .ccu_clks       = sun8i_h3_de2_clks,
+       .num_ccu_clks   = ARRAY_SIZE(sun8i_h3_de2_clks),
+
+       .hw_clks        = &sun8i_h3_de2_hw_clks,
+
+       .resets         = sun8i_a83t_de2_resets,
+       .num_resets     = ARRAY_SIZE(sun8i_a83t_de2_resets),
+};
+
 static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
-       .ccu_clks       = sun8i_a83t_de2_clks,
-       .num_ccu_clks   = ARRAY_SIZE(sun8i_a83t_de2_clks),
+       .ccu_clks       = sun8i_h3_de2_clks,
+       .num_ccu_clks   = ARRAY_SIZE(sun8i_h3_de2_clks),
 
-       .hw_clks        = &sun8i_a83t_de2_hw_clks,
+       .hw_clks        = &sun8i_h3_de2_hw_clks,
 
        .resets         = sun50i_a64_de2_resets,
        .num_resets     = ARRAY_SIZE(sun50i_a64_de2_resets),
@@ -148,6 +197,11 @@ static const struct sunxi_ccu_desc sun8i_v3s_de2_clk_desc = {
        .num_resets     = ARRAY_SIZE(sun8i_a83t_de2_resets),
 };
 
+static bool sunxi_de2_clk_has_sram(const struct device_node *node)
+{
+       return of_device_is_compatible(node, "allwinner,sun50i-a64-de2-clk");
+}
+
 static int sunxi_de2_clk_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -191,11 +245,20 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev)
                return ret;
        }
 
+       if (sunxi_de2_clk_has_sram(pdev->dev.of_node)) {
+               ret = sunxi_sram_claim(&pdev->dev);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "Error couldn't map SRAM to device\n");
+                       return ret;
+               }
+       }
+
        /* The clocks need to be enabled for us to access the registers */
        ret = clk_prepare_enable(bus_clk);
        if (ret) {
                dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
-               return ret;
+               goto err_release_sram;
        }
 
        ret = clk_prepare_enable(mod_clk);
@@ -224,6 +287,10 @@ err_disable_mod_clk:
        clk_disable_unprepare(mod_clk);
 err_disable_bus_clk:
        clk_disable_unprepare(bus_clk);
+err_release_sram:
+       if (sunxi_de2_clk_has_sram(pdev->dev.of_node))
+               sunxi_sram_release(&pdev->dev);
+
        return ret;
 }
 
@@ -232,21 +299,22 @@ static const struct of_device_id sunxi_de2_clk_ids[] = {
                .compatible = "allwinner,sun8i-a83t-de2-clk",
                .data = &sun8i_a83t_de2_clk_desc,
        },
+       {
+               .compatible = "allwinner,sun8i-h3-de2-clk",
+               .data = &sun8i_h3_de2_clk_desc,
+       },
        {
                .compatible = "allwinner,sun8i-v3s-de2-clk",
                .data = &sun8i_v3s_de2_clk_desc,
        },
+       {
+               .compatible = "allwinner,sun50i-a64-de2-clk",
+               .data = &sun50i_a64_de2_clk_desc,
+       },
        {
                .compatible = "allwinner,sun50i-h5-de2-clk",
                .data = &sun50i_a64_de2_clk_desc,
        },
-       /*
-        * The Allwinner A64 SoC needs some bit to be poke in syscon to make
-        * DE2 really working.
-        * So there's currently no A64 compatible here.
-        * H5 shares the same reset line with A64, so here H5 is using the
-        * clock description of A64.
-        */
        { }
 };
 
index bcd496edc70f2b7c40cc35cfe09b021f7e1e82ae..0cd13f17fc1107d5a36ba2a5b0d3fd9d4c027ee3 100644 (file)
 
 #define DMA_STAT               0x30
 
+/* Offset between DMA_IRQ_EN and DMA_IRQ_STAT limits number of channels */
+#define DMA_MAX_CHANNELS       (DMA_IRQ_CHAN_NR * 0x10 / 4)
+
 /*
  * sun8i specific registers
  */
 #define SUN8I_DMA_GATE         0x20
 #define SUN8I_DMA_GATE_ENABLE  0x4
 
+#define SUNXI_H3_SECURE_REG            0x20
+#define SUNXI_H3_DMA_GATE              0x28
+#define SUNXI_H3_DMA_GATE_ENABLE       0x4
 /*
  * Channels specific registers
  */
 #define DMA_CHAN_LLI_ADDR      0x08
 
 #define DMA_CHAN_CUR_CFG       0x0c
-#define DMA_CHAN_CFG_SRC_DRQ(x)                ((x) & 0x1f)
+#define DMA_CHAN_MAX_DRQ               0x1f
+#define DMA_CHAN_CFG_SRC_DRQ(x)                ((x) & DMA_CHAN_MAX_DRQ)
 #define DMA_CHAN_CFG_SRC_IO_MODE       BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
-#define DMA_CHAN_CFG_SRC_BURST(x)      (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_H3(x)   (((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)      (((x) & 0x3) << 9)
 
 #define DMA_CHAN_CFG_DST_DRQ(x)                (DMA_CHAN_CFG_SRC_DRQ(x) << 16)
 #define DMA_CHAN_CFG_DST_IO_MODE       (DMA_CHAN_CFG_SRC_IO_MODE << 16)
 #define DMA_CHAN_CFG_DST_LINEAR_MODE   (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
-#define DMA_CHAN_CFG_DST_BURST(x)      (DMA_CHAN_CFG_SRC_BURST(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_A31(x)  (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_H3(x)   (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
 #define DMA_CHAN_CFG_DST_WIDTH(x)      (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
 
 #define DMA_CHAN_CUR_SRC       0x10
@@ -90,6 +99,9 @@
 #define NORMAL_WAIT    8
 #define DRQ_SDRAM      1
 
+/* forward declaration */
+struct sun6i_dma_dev;
+
 /*
  * Hardware channels / ports representation
  *
@@ -111,7 +123,12 @@ struct sun6i_dma_config {
         * however these SoCs really have and need this bit, as seen in the
         * BSP kernel source code.
         */
-       bool gate_needed;
+       void (*clock_autogate_enable)(struct sun6i_dma_dev *);
+       void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
+       u32 src_burst_lengths;
+       u32 dst_burst_lengths;
+       u32 src_addr_widths;
+       u32 dst_addr_widths;
 };
 
 /*
@@ -175,6 +192,9 @@ struct sun6i_dma_dev {
        struct sun6i_pchan      *pchans;
        struct sun6i_vchan      *vchans;
        const struct sun6i_dma_config *cfg;
+       u32                     num_pchans;
+       u32                     num_vchans;
+       u32                     max_request;
 };
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -251,8 +271,12 @@ static inline s8 convert_burst(u32 maxburst)
        switch (maxburst) {
        case 1:
                return 0;
+       case 4:
+               return 1;
        case 8:
                return 2;
+       case 16:
+               return 3;
        default:
                return -EINVAL;
        }
@@ -260,11 +284,29 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-       if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
-           (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
-               return -EINVAL;
+       return ilog2(addr_width);
+}
+
+static void sun6i_enable_clock_autogate_a23(struct sun6i_dma_dev *sdev)
+{
+       writel(SUN8I_DMA_GATE_ENABLE, sdev->base + SUN8I_DMA_GATE);
+}
+
+static void sun6i_enable_clock_autogate_h3(struct sun6i_dma_dev *sdev)
+{
+       writel(SUNXI_H3_DMA_GATE_ENABLE, sdev->base + SUNXI_H3_DMA_GATE);
+}
 
-       return addr_width >> 1;
+static void sun6i_set_burst_length_a31(u32 *p_cfg, s8 src_burst, s8 dst_burst)
+{
+       *p_cfg |= DMA_CHAN_CFG_SRC_BURST_A31(src_burst) |
+                 DMA_CHAN_CFG_DST_BURST_A31(dst_burst);
+}
+
+static void sun6i_set_burst_length_h3(u32 *p_cfg, s8 src_burst, s8 dst_burst)
+{
+       *p_cfg |= DMA_CHAN_CFG_SRC_BURST_H3(src_burst) |
+                 DMA_CHAN_CFG_DST_BURST_H3(dst_burst);
 }
 
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
@@ -399,7 +441,6 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
 static void sun6i_dma_tasklet(unsigned long data)
 {
        struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
-       const struct sun6i_dma_config *cfg = sdev->cfg;
        struct sun6i_vchan *vchan;
        struct sun6i_pchan *pchan;
        unsigned int pchan_alloc = 0;
@@ -427,7 +468,7 @@ static void sun6i_dma_tasklet(unsigned long data)
        }
 
        spin_lock_irq(&sdev->lock);
-       for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+       for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
                pchan = &sdev->pchans[pchan_idx];
 
                if (pchan->vchan || list_empty(&sdev->pending))
@@ -448,7 +489,7 @@ static void sun6i_dma_tasklet(unsigned long data)
        }
        spin_unlock_irq(&sdev->lock);
 
-       for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+       for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
                if (!(pchan_alloc & BIT(pchan_idx)))
                        continue;
 
@@ -470,7 +511,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
        int i, j, ret = IRQ_NONE;
        u32 status;
 
-       for (i = 0; i < sdev->cfg->nr_max_channels / DMA_IRQ_CHAN_NR; i++) {
+       for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
                status = readl(sdev->base + DMA_IRQ_STAT(i));
                if (!status)
                        continue;
@@ -510,47 +551,49 @@ static int set_config(struct sun6i_dma_dev *sdev,
                        enum dma_transfer_direction direction,
                        u32 *p_cfg)
 {
+       enum dma_slave_buswidth src_addr_width, dst_addr_width;
+       u32 src_maxburst, dst_maxburst;
        s8 src_width, dst_width, src_burst, dst_burst;
 
+       src_addr_width = sconfig->src_addr_width;
+       dst_addr_width = sconfig->dst_addr_width;
+       src_maxburst = sconfig->src_maxburst;
+       dst_maxburst = sconfig->dst_maxburst;
+
        switch (direction) {
        case DMA_MEM_TO_DEV:
-               src_burst = convert_burst(sconfig->src_maxburst ?
-                                       sconfig->src_maxburst : 8);
-               src_width = convert_buswidth(sconfig->src_addr_width !=
-                                               DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-                               sconfig->src_addr_width :
-                               DMA_SLAVE_BUSWIDTH_4_BYTES);
-               dst_burst = convert_burst(sconfig->dst_maxburst);
-               dst_width = convert_buswidth(sconfig->dst_addr_width);
+               if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+                       src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               src_maxburst = src_maxburst ? src_maxburst : 8;
                break;
        case DMA_DEV_TO_MEM:
-               src_burst = convert_burst(sconfig->src_maxburst);
-               src_width = convert_buswidth(sconfig->src_addr_width);
-               dst_burst = convert_burst(sconfig->dst_maxburst ?
-                                       sconfig->dst_maxburst : 8);
-               dst_width = convert_buswidth(sconfig->dst_addr_width !=
-                                               DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-                               sconfig->dst_addr_width :
-                               DMA_SLAVE_BUSWIDTH_4_BYTES);
+               if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+                       dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               dst_maxburst = dst_maxburst ? dst_maxburst : 8;
                break;
        default:
                return -EINVAL;
        }
 
-       if (src_burst < 0)
-               return src_burst;
-       if (src_width < 0)
-               return src_width;
-       if (dst_burst < 0)
-               return dst_burst;
-       if (dst_width < 0)
-               return dst_width;
-
-       *p_cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
-               DMA_CHAN_CFG_SRC_WIDTH(src_width) |
-               DMA_CHAN_CFG_DST_BURST(dst_burst) |
+       if (!(BIT(src_addr_width) & sdev->slave.src_addr_widths))
+               return -EINVAL;
+       if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths))
+               return -EINVAL;
+       if (!(BIT(src_maxburst) & sdev->cfg->src_burst_lengths))
+               return -EINVAL;
+       if (!(BIT(dst_maxburst) & sdev->cfg->dst_burst_lengths))
+               return -EINVAL;
+
+       src_width = convert_buswidth(src_addr_width);
+       dst_width = convert_buswidth(dst_addr_width);
+       dst_burst = convert_burst(dst_maxburst);
+       src_burst = convert_burst(src_maxburst);
+
+       *p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
                DMA_CHAN_CFG_DST_WIDTH(dst_width);
 
+       sdev->cfg->set_burst_length(p_cfg, src_burst, dst_burst);
+
        return 0;
 }
 
@@ -593,11 +636,11 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
                DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
                DMA_CHAN_CFG_DST_LINEAR_MODE |
                DMA_CHAN_CFG_SRC_LINEAR_MODE |
-               DMA_CHAN_CFG_SRC_BURST(burst) |
                DMA_CHAN_CFG_SRC_WIDTH(width) |
-               DMA_CHAN_CFG_DST_BURST(burst) |
                DMA_CHAN_CFG_DST_WIDTH(width);
 
+       sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst);
+
        sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
 
        sun6i_dma_dump_lli(vchan, v_lli);
@@ -948,7 +991,7 @@ static struct dma_chan *sun6i_dma_of_xlate(struct of_phandle_args *dma_spec,
        struct dma_chan *chan;
        u8 port = dma_spec->args[0];
 
-       if (port > sdev->cfg->nr_max_requests)
+       if (port > sdev->max_request)
                return NULL;
 
        chan = dma_get_any_slave_channel(&sdev->slave);
@@ -981,7 +1024,7 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev *sdev)
 {
        int i;
 
-       for (i = 0; i < sdev->cfg->nr_max_vchans; i++) {
+       for (i = 0; i < sdev->num_vchans; i++) {
                struct sun6i_vchan *vchan = &sdev->vchans[i];
 
                list_del(&vchan->vc.chan.device_node);
@@ -1009,6 +1052,15 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
        .nr_max_channels = 16,
        .nr_max_requests = 30,
        .nr_max_vchans   = 53,
+       .set_burst_length = sun6i_set_burst_length_a31,
+       .src_burst_lengths = BIT(1) | BIT(8),
+       .dst_burst_lengths = BIT(1) | BIT(8),
+       .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+       .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
 };
 
 /*
@@ -1020,24 +1072,76 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
        .nr_max_channels = 8,
        .nr_max_requests = 24,
        .nr_max_vchans   = 37,
-       .gate_needed     = true,
+       .clock_autogate_enable = sun6i_enable_clock_autogate_a23,
+       .set_burst_length = sun6i_set_burst_length_a31,
+       .src_burst_lengths = BIT(1) | BIT(8),
+       .dst_burst_lengths = BIT(1) | BIT(8),
+       .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+       .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
        .nr_max_channels = 8,
        .nr_max_requests = 28,
        .nr_max_vchans   = 39,
+       .clock_autogate_enable = sun6i_enable_clock_autogate_a23,
+       .set_burst_length = sun6i_set_burst_length_a31,
+       .src_burst_lengths = BIT(1) | BIT(8),
+       .dst_burst_lengths = BIT(1) | BIT(8),
+       .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+       .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
+ * It also supports additional burst lengths and bus widths,
+ * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
        .nr_max_channels = 12,
        .nr_max_requests = 27,
        .nr_max_vchans   = 34,
+       .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+       .set_burst_length = sun6i_set_burst_length_h3,
+       .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+       .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+       .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+       .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+};
+
+/*
+ * The A64 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_a64_dma_cfg = {
+       .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+       .set_burst_length = sun6i_set_burst_length_h3,
+       .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+       .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+       .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+       .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
 };
 
 /*
@@ -1049,7 +1153,16 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
        .nr_max_channels = 8,
        .nr_max_requests = 23,
        .nr_max_vchans   = 24,
-       .gate_needed     = true,
+       .clock_autogate_enable = sun6i_enable_clock_autogate_a23,
+       .set_burst_length = sun6i_set_burst_length_a31,
+       .src_burst_lengths = BIT(1) | BIT(8),
+       .dst_burst_lengths = BIT(1) | BIT(8),
+       .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+       .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                            BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                            BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
 };
 
 static const struct of_device_id sun6i_dma_match[] = {
@@ -1058,13 +1171,14 @@ static const struct of_device_id sun6i_dma_match[] = {
        { .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg },
        { .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
        { .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
+       { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dma_match);
 
 static int sun6i_dma_probe(struct platform_device *pdev)
 {
-       const struct of_device_id *device;
+       struct device_node *np = pdev->dev.of_node;
        struct sun6i_dma_dev *sdc;
        struct resource *res;
        int ret, i;
@@ -1073,10 +1187,9 @@ static int sun6i_dma_probe(struct platform_device *pdev)
        if (!sdc)
                return -ENOMEM;
 
-       device = of_match_device(sun6i_dma_match, &pdev->dev);
-       if (!device)
+       sdc->cfg = of_device_get_match_data(&pdev->dev);
+       if (!sdc->cfg)
                return -ENODEV;
-       sdc->cfg = device->data;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        sdc->base = devm_ioremap_resource(&pdev->dev, res);
@@ -1129,37 +1242,57 @@ static int sun6i_dma_probe(struct platform_device *pdev)
        sdc->slave.device_pause                 = sun6i_dma_pause;
        sdc->slave.device_resume                = sun6i_dma_resume;
        sdc->slave.device_terminate_all         = sun6i_dma_terminate_all;
-       sdc->slave.src_addr_widths              = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
-                                                 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
-                                                 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
-       sdc->slave.dst_addr_widths              = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
-                                                 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
-                                                 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+       sdc->slave.src_addr_widths              = sdc->cfg->src_addr_widths;
+       sdc->slave.dst_addr_widths              = sdc->cfg->dst_addr_widths;
        sdc->slave.directions                   = BIT(DMA_DEV_TO_MEM) |
                                                  BIT(DMA_MEM_TO_DEV);
        sdc->slave.residue_granularity          = DMA_RESIDUE_GRANULARITY_BURST;
        sdc->slave.dev = &pdev->dev;
 
-       sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels,
+       sdc->num_pchans = sdc->cfg->nr_max_channels;
+       sdc->num_vchans = sdc->cfg->nr_max_vchans;
+       sdc->max_request = sdc->cfg->nr_max_requests;
+
+       ret = of_property_read_u32(np, "dma-channels", &sdc->num_pchans);
+       if (ret && !sdc->num_pchans) {
+               dev_err(&pdev->dev, "Can't get dma-channels.\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
+       if (ret && !sdc->max_request) {
+               dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
+                        DMA_CHAN_MAX_DRQ);
+               sdc->max_request = DMA_CHAN_MAX_DRQ;
+       }
+
+       /*
+        * If the number of vchans is not specified, derive it from the
+        * highest port number, at most one channel per port and direction.
+        */
+       if (!sdc->num_vchans)
+               sdc->num_vchans = 2 * (sdc->max_request + 1);
+
+       sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
                                   sizeof(struct sun6i_pchan), GFP_KERNEL);
        if (!sdc->pchans)
                return -ENOMEM;
 
-       sdc->vchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_vchans,
+       sdc->vchans = devm_kcalloc(&pdev->dev, sdc->num_vchans,
                                   sizeof(struct sun6i_vchan), GFP_KERNEL);
        if (!sdc->vchans)
                return -ENOMEM;
 
        tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
 
-       for (i = 0; i < sdc->cfg->nr_max_channels; i++) {
+       for (i = 0; i < sdc->num_pchans; i++) {
                struct sun6i_pchan *pchan = &sdc->pchans[i];
 
                pchan->idx = i;
                pchan->base = sdc->base + 0x100 + i * 0x40;
        }
 
-       for (i = 0; i < sdc->cfg->nr_max_vchans; i++) {
+       for (i = 0; i < sdc->num_vchans; i++) {
                struct sun6i_vchan *vchan = &sdc->vchans[i];
 
                INIT_LIST_HEAD(&vchan->node);
@@ -1199,8 +1332,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
                goto err_dma_unregister;
        }
 
-       if (sdc->cfg->gate_needed)
-               writel(SUN8I_DMA_GATE_ENABLE, sdc->base + SUN8I_DMA_GATE);
+       if (sdc->cfg->clock_autogate_enable)
+               sdc->cfg->clock_autogate_enable(sdc);
 
        return 0;
 
index 6d23f1d1c9b73373e84ea4a954da634cbd7911dc..f8b8d54d90c4943ad9a0137afc7a7005097c31ad 100644 (file)
@@ -341,6 +341,12 @@ static const struct sun4i_pwm_data sun4i_pwm_data_h3 = {
        .npwm = 1,
 };
 
+static const struct sun4i_pwm_data sun4i_pwm_data_a64 = {
+       .has_prescaler_bypass = true,
+       .has_rdy = true,
+       .npwm = 1,
+};
+
 static const struct of_device_id sun4i_pwm_dt_ids[] = {
        {
                .compatible = "allwinner,sun4i-a10-pwm",
@@ -357,6 +363,9 @@ static const struct of_device_id sun4i_pwm_dt_ids[] = {
        }, {
                .compatible = "allwinner,sun8i-h3-pwm",
                .data = &sun4i_pwm_data_h3,
+       }, {
+               .compatible = "allwinner,sun50i-a64-pwm",
+               .data = &sun4i_pwm_data_a64,
        }, {
                /* sentinel */
        },