From dbf95776199d6ae835f22bcb28af833821d3e2b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= <megi@xff.cz>
Date: Wed, 8 Jul 2020 00:58:16 +0200
Subject: arm64: dts: sun50i-a64-pinephone: Add Type-C support for all PP
 variants 1.0-1.2

There are differences in GPIO and how VBUS is handled. Describe them
in DTS. Thankfully we can support both unmodded and modded variants
of 1.0 and 1.1 boards with one DTS. No need for more subvariants.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 .../allwinner/sun50i-a64-pinephone-1.0.dts    | 86 +++++++++++++++++++
 .../allwinner/sun50i-a64-pinephone-1.1.dts    | 86 +++++++++++++++++++
 .../allwinner/sun50i-a64-pinephone-1.2.dts    | 60 +++++++++++++
 .../dts/allwinner/sun50i-a64-pinephone.dtsi   | 68 ++++++++++++++-
 4 files changed, 299 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
index 219f720b8b7d..498ae493d176 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
@@ -8,6 +8,92 @@
 / {
 	model = "Pine64 PinePhone Developer Batch (1.0)";
 	compatible = "pine64,pinephone-1.0", "pine64,pinephone", "allwinner,sun50i-a64";
+
+	reg_vbus: usb0-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb0-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */
+		enable-active-high;
+		vin-supply = <&reg_drivevbus>;
+	};
+};
+
+&axp803 {
+	x-powers,drive-vbus-en;
+};
+
+&i2c0 {
+	hdmi-bridge@28 {
+		compatible = "analogix,anx7688";
+		reg = <0x28>;
+
+		interrupt-parent = <&r_pio>;
+		interrupts = <0 11 IRQ_TYPE_EDGE_FALLING>; /* PL11 */
+
+		enable-gpios = <&pio 3 10 GPIO_ACTIVE_LOW>; /* PD10 */
+		reset-gpios = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */
+
+		cabledet-gpios = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+
+		avdd10-supply = <&reg_anx1v0>;
+		dvdd10-supply = <&reg_anx1v0>;
+		/* This is for the HW hack variant, but will also work for non-modified version. */
+		avdd18-supply = <&reg_ldo_io1>;
+		dvdd18-supply = <&reg_ldo_io1>;
+		avdd33-supply = <&reg_dldo1>;
+		vconn-supply = <&reg_vconn5v0>;
+		hdmi_vt-supply = <&reg_dldo1>;
+
+		source-caps = <
+			PDO_FIXED(5000, 500, PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE)
+		>;
+
+		sink-caps = <
+			PDO_FIXED(5000, 3000, PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE)
+		>;
+
+		/*
+		 * ANX7688 can't enable/disable USB-5V <-> DCIN switch by
+		 * itself, and PMIC's N_VBUSEN is not connected anywhere either,
+		 * so we need to configure everything in software:
+		 *
+		 * - get the VBUS status from ANX7688 via I2C
+		 * - configure PMIC to let it know vbus drive status (via
+		 *   reg_drivevbus)
+		 * - enable VBUS switch and USB-5V regulator (via reg_vbus
+		 *   and reg_usb_5v)
+		 */
+		vbus-supply = <&reg_vbus>;
+		vbus_in-supply = <&usb_power_supply>;
+
+		port {
+			typec0_dr_sw: endpoint {
+				remote-endpoint = <&usb0_drd_sw>;
+			};
+		};
+	};
+};
+
+/*
+ * The N_VBUSEN pin is disconnected, but we need to inform the PMIC about
+ * the VBUS status anyway. To avoid the pin from floating and to inform
+ * the PMIC, about VBUS status, we couple reg_drivevbus with reg_vbus.
+ */
+&reg_drivevbus {
+	vin-supply = <&reg_usb_5v>;
+	status = "okay";
+};
+
+&usbphy {
+	usb-role-switch;
+
+	port {
+		usb0_drd_sw: endpoint {
+			remote-endpoint = <&typec0_dr_sw>;
+		};
+	};
 };
 
 &codec_analog {
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
index 723af64a9cee..73275308f484 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
@@ -8,6 +8,20 @@
 / {
 	model = "Pine64 PinePhone Braveheart (1.1)";
 	compatible = "pine64,pinephone-1.1", "pine64,pinephone", "allwinner,sun50i-a64";
+
+	reg_vbus: usb0-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb0-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */
+		enable-active-high;
+		vin-supply = <&reg_drivevbus>;
+	};
+};
+
+&axp803 {
+	x-powers,drive-vbus-en;
 };
 
 &backlight {
@@ -33,7 +47,79 @@ &codec_analog {
 	allwinner,internal-bias-resistor;
 };
 
+&i2c0 {
+	hdmi-bridge@28 {
+		compatible = "analogix,anx7688";
+		reg = <0x28>;
+
+		interrupt-parent = <&r_pio>;
+		interrupts = <0 11 IRQ_TYPE_EDGE_FALLING>; /* PL11 */
+
+		enable-gpios = <&pio 3 10 GPIO_ACTIVE_LOW>; /* PD10 */
+		reset-gpios = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */
+
+		cabledet-gpios = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+
+		avdd10-supply = <&reg_anx1v0>;
+		dvdd10-supply = <&reg_anx1v0>;
+		/* This is for the HW hack variant, but will also work for non-modified version. */
+		avdd18-supply = <&reg_ldo_io1>;
+		dvdd18-supply = <&reg_ldo_io1>;
+		avdd33-supply = <&reg_dldo1>;
+		vconn-supply = <&reg_vconn5v0>;
+		hdmi_vt-supply = <&reg_dldo1>;
+
+		source-caps = <
+			PDO_FIXED(5000, 500, PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE)
+		>;
+
+		sink-caps = <
+			PDO_FIXED(5000, 3000, PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE)
+		>;
+
+		/*
+		 * ANX7688 can't enable/disable USB-5V <-> DCIN switch by
+		 * itself, and PMIC's N_VBUSEN is not connected anywhere either,
+		 * so we need to configure everything in software:
+		 *
+		 * - get the VBUS status from ANX7688 via I2C
+		 * - configure PMIC to let it know vbus drive status (via
+		 *   reg_drivevbus)
+		 * - enable VBUS switch and USB-5V regulator (via reg_vbus
+		 *   and reg_usb_5v)
+		 */
+		vbus-supply = <&reg_vbus>;
+		vbus_in-supply = <&usb_power_supply>;
+
+		port {
+			typec0_dr_sw: endpoint {
+				remote-endpoint = <&usb0_drd_sw>;
+			};
+		};
+	};
+};
+
+/*
+ * The N_VBUSEN pin is disconnected, but we need to inform the PMIC about
+ * the VBUS status anyway. To avoid the pin from floating and to inform
+ * the PMIC, about VBUS status, we couple reg_drivevbus with reg_vbus.
+ */
+&reg_drivevbus {
+	vin-supply = <&reg_usb_5v>;
+	status = "okay";
+};
+
 &sgm3140 {
 	enable-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
 	flash-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */
 };
+
+&usbphy {
+	usb-role-switch;
+
+	port {
+		usb0_drd_sw: endpoint {
+			remote-endpoint = <&typec0_dr_sw>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
index 4e7e237cb46a..40127186606f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
@@ -48,7 +48,67 @@ &mmc1 {
 	mmc-pwrseq = <&wifi_pwrseq>;
 };
 
+&i2c0 {
+	hdmi-bridge@28 {
+		compatible = "analogix,anx7688";
+		reg = <0x28>;
+
+		interrupt-parent = <&r_pio>;
+		interrupts = <0 11 IRQ_TYPE_EDGE_FALLING>; /* PL11 */
+
+		enable-gpios = <&pio 3 10 GPIO_ACTIVE_LOW>; /* PD10 */
+		reset-gpios = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */
+
+		cabledet-gpios = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+
+		avdd10-supply = <&reg_anx1v0>;
+		dvdd10-supply = <&reg_anx1v0>;
+		avdd18-supply = <&reg_ldo_io1>;
+		dvdd18-supply = <&reg_ldo_io1>;
+		avdd33-supply = <&reg_dcdc1>;
+		vconn-supply = <&reg_vconn5v0>;
+		hdmi_vt-supply = <&reg_dldo1>;
+
+		source-caps = <
+			PDO_FIXED(5000, 500, PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE)
+		>;
+
+		sink-caps = <
+			PDO_FIXED(5000, 3000, PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE)
+		>;
+
+		/*
+		 * ANX7688 will enable/disable USB-5V <-> DCIN switch by itself
+		 * via VBUS_CTRL pin. The driver just has to enable the USB-5V
+		 * so that the switch has power.
+		 */
+		vbus-supply = <&reg_usb_5v>;
+		vbus_in-supply = <&usb_power_supply>;
+
+		port {
+			typec0_dr_sw: endpoint {
+				remote-endpoint = <&usb0_drd_sw>;
+			};
+		};
+	};
+};
+
+&reg_anx1v0 {
+	gpio = <&pio 3 11 GPIO_ACTIVE_HIGH>; /* PD11 */
+	enable-active-high;
+};
+
 &sgm3140 {
 	enable-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
 	flash-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */
 };
+
+&usbphy {
+	usb-role-switch;
+
+	port {
+		usb0_drd_sw: endpoint {
+			remote-endpoint = <&typec0_dr_sw>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
index 5d55c6f82352..e8f6c016e1b3 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
@@ -10,6 +10,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/leds/common.h>
 #include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/usb/pd.h>
 
 / {
 	chassis-type = "handset";
@@ -70,6 +71,24 @@ led2: led-2 {
 		};
 	};
 
+	hdmi-connector {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&hdmi_out_con>;
+			};
+		};
+	};
+
+	reg_anx1v0: anx1v0 {
+		compatible = "regulator-fixed";
+		regulator-name = "anx1v0";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+	};
+
 	multi-led {
 		compatible = "leds-group-multicolor";
 		color = <LED_COLOR_ID_RGB>;
@@ -85,6 +104,24 @@ reg_ps: ps-regulator {
 		regulator-boot-on;
 	};
 
+	reg_usb_5v: usb-5v {
+		compatible = "regulator-fixed";
+		regulator-name = "usb-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 3 8 GPIO_ACTIVE_HIGH>; /* PD8 */
+		enable-active-high;
+	};
+
+	reg_vbat_bb: vbat-bb {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat-bb";
+		regulator-min-microvolt = <3500000>;
+		regulator-max-microvolt = <3500000>;
+		gpio = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
+		enable-active-high;
+	};
+
 	reg_vbat_wifi: vbat-wifi {
 		compatible = "regulator-fixed";
 		regulator-min-microvolt = <3300000>;
@@ -92,6 +129,16 @@ reg_vbat_wifi: vbat-wifi {
 		regulator-name = "vbat-wifi";
 	};
 
+	/* This is a charge pump for CC1 and CC2 pins on USB-C connector. */
+	reg_vconn5v0: vconn5v0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vconn5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 3 9 GPIO_ACTIVE_HIGH>; /* PD9 */
+		enable-active-high;
+	};
+
 	sgm3140: led-controller {
 		compatible = "sgmicro,sgm3140";
 		vin-supply = <&reg_dcdc1>;
@@ -207,6 +254,21 @@ &ehci1 {
 	status = "okay";
 };
 
+&hdmi {
+	hvcc-supply = <&reg_dldo1>;
+	status = "okay";
+};
+
+&hdmi_out {
+	hdmi_out_con: endpoint {
+		remote-endpoint = <&hdmi_con_in>;
+	};
+};
+
+&sound_hdmi {
+	status = "okay";
+};
+
 &i2c_csi {
 	gc2145: front-camera@3c {
 		compatible = "galaxycore,gc2145";
@@ -330,6 +392,10 @@ &i2c2 {
 	status = "okay";
 };
 
+&i2s2 {
+	status = "okay";
+};
+
 &lradc {
 	vref-supply = <&reg_aldo3>;
 	wakeup-source;
@@ -623,7 +689,7 @@ &uart3 {
 };
 
 &usb_otg {
-	dr_mode = "peripheral";
+	dr_mode = "otg";
 	status = "okay";
 };
 
-- 
2.35.3

