RK3399 Typec DP (#2676)
* RK3399 NanoPC-T4 Add Type-C alt mode DP * rk3399 rockpi 4C add mini-DP (WIP) * [ rockchip64 ] revert rockPi 4C DP patch Add an extension to disable it, but leave for future work.
This commit is contained in:
parent
4bda055a9b
commit
4971535c77
@ -7355,6 +7355,7 @@ CONFIG_EXTCON_PTN5150=m
|
||||
# CONFIG_EXTCON_SM5502 is not set
|
||||
CONFIG_EXTCON_USB_GPIO=y
|
||||
# CONFIG_EXTCON_USBC_CROS_EC is not set
|
||||
CONFIG_EXTCON_USBC_VIRTUAL_PD=y
|
||||
# CONFIG_MEMORY is not set
|
||||
CONFIG_IIO=y
|
||||
CONFIG_IIO_BUFFER=y
|
||||
|
||||
@ -0,0 +1,183 @@
|
||||
From 5b697589bfd64a14ef1c991cffb5179ccb6cf880 Mon Sep 17 00:00:00 2001
|
||||
From: tonymac32 <tonymckahan@gmail.com>
|
||||
Date: Wed, 17 Feb 2021 00:54:00 -0500
|
||||
Subject: [PATCH] Patching something
|
||||
|
||||
Signed-off-by: tonymac32 <tonymckahan@gmail.com>
|
||||
---
|
||||
.../boot/dts/rockchip/rk3399-nanopc-t4.dts | 83 +++++++++++++++++++
|
||||
.../boot/dts/rockchip/rk3399-nanopi4.dtsi | 27 +++---
|
||||
2 files changed, 98 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts b/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
|
||||
index e0d75617b..bbe200ab6 100644
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
|
||||
@@ -66,6 +66,12 @@ fan: pwm-fan {
|
||||
};
|
||||
};
|
||||
|
||||
+&cdn_dp {
|
||||
+ status = "okay";
|
||||
+ extcon = <&fusb0>;
|
||||
+ phys = <&tcphy0_dp>;
|
||||
+};
|
||||
+
|
||||
&cpu_thermal {
|
||||
trips {
|
||||
cpu_warm: cpu_warm {
|
||||
@@ -94,6 +100,50 @@ map3 {
|
||||
};
|
||||
};
|
||||
|
||||
+&fusb0 {
|
||||
+
|
||||
+ connector {
|
||||
+ compatible = "usb-c-connector";
|
||||
+ label = "USB-C";
|
||||
+ power-role = "dual";
|
||||
+ data-role = "dual";
|
||||
+ try-power-role = "sink";
|
||||
+ source-pdos = <PDO_FIXED(5000, 1200, PDO_FIXED_USB_COMM)>;
|
||||
+ sink-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)>;
|
||||
+ op-sink-microwatt = <5000000>;
|
||||
+
|
||||
+ extcon-cables = <1 2 5 6 9 10 12 44>;
|
||||
+ typec-altmodes = <0xff01 1 0x001c0000 1>;
|
||||
+
|
||||
+ ports {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ port@0 {
|
||||
+ reg = <0>;
|
||||
+ usb_con_hs: endpoint {
|
||||
+ remote-endpoint =
|
||||
+ <&u2phy0_typec_hs>;
|
||||
+ };
|
||||
+ };
|
||||
+ port@1 {
|
||||
+ reg = <1>;
|
||||
+
|
||||
+ usb_con_ss: endpoint {
|
||||
+ remote-endpoint =
|
||||
+ <&tcphy0_typec_ss>;
|
||||
+ };
|
||||
+ };
|
||||
+ port@2 {
|
||||
+ reg = <2>;
|
||||
+ usb_con_dp: endpoint {
|
||||
+ remote-endpoint =
|
||||
+ <&tcphy0_typec_dp>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&pcie0 {
|
||||
num-lanes = <4>;
|
||||
vpcie3v3-supply = <&vcc3v3_sys>;
|
||||
@@ -113,14 +163,47 @@ &sdhci {
|
||||
mmc-hs400-enhanced-strobe;
|
||||
};
|
||||
|
||||
+&tcphy0 {
|
||||
+ extcon = <&fusb0>;
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&tcphy0_dp {
|
||||
+ port {
|
||||
+ tcphy0_typec_dp: endpoint {
|
||||
+ remote-endpoint = <&usb_con_dp>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&tcphy0_usb3 {
|
||||
+ port {
|
||||
+ tcphy0_typec_ss: endpoint {
|
||||
+ remote-endpoint = <&usb_con_ss>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&u2phy0_host {
|
||||
phy-supply = <&vcc5v0_host0>;
|
||||
};
|
||||
|
||||
+&u2phy0_otg {
|
||||
+ port {
|
||||
+ u2phy0_typec_hs: endpoint {
|
||||
+ remote-endpoint = <&usb_con_hs>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&u2phy1_host {
|
||||
phy-supply = <&vcc5v0_host0>;
|
||||
};
|
||||
|
||||
+&usbdrd_dwc3_0 {
|
||||
+ extcon = <&fusb0>;
|
||||
+};
|
||||
+
|
||||
&vcc5v0_sys {
|
||||
vin-supply = <&vcc12v0_sys>;
|
||||
};
|
||||
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
|
||||
index 86e802fd8..9c2e8c8ae 100644
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi4.dtsi
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
/dts-v1/;
|
||||
#include <dt-bindings/input/linux-event-codes.h>
|
||||
+#include <dt-bindings/usb/pd.h>
|
||||
#include "rk3399.dtsi"
|
||||
#include "rk3399-opp.dtsi"
|
||||
|
||||
@@ -706,26 +707,28 @@ &tsadc {
|
||||
|
||||
&u2phy0 {
|
||||
status = "okay";
|
||||
-};
|
||||
+ extcon = <&fusb0>;
|
||||
|
||||
-&u2phy0_host {
|
||||
- status = "okay";
|
||||
-};
|
||||
+ u2phy0_otg: otg-port {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
|
||||
-&u2phy0_otg {
|
||||
- status = "okay";
|
||||
+ u2phy0_host: host-port {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
};
|
||||
|
||||
&u2phy1 {
|
||||
status = "okay";
|
||||
-};
|
||||
+
|
||||
+ u2phy1_otg: otg-port {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
|
||||
-&u2phy1_host {
|
||||
- status = "okay";
|
||||
-};
|
||||
+ u2phy1_host: host-port {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
|
||||
-&u2phy1_otg {
|
||||
- status = "okay";
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
--
|
||||
Created with Armbian build tools https://github.com/armbian/build
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts
|
||||
index 4c7ebb1c5d2d..19a648add355 100644
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4c.dts
|
||||
@@ -11,6 +11,22 @@
|
||||
/ {
|
||||
model = "Radxa ROCK Pi 4C";
|
||||
compatible = "radxa,rockpi4c", "radxa,rockpi4", "rockchip,rk3399";
|
||||
+
|
||||
+ virtual_pd: virtual-pd {
|
||||
+ compatible = "linux,extcon-usbc-virtual-pd";
|
||||
+ det-gpios = <&gpio4 RK_PD1 GPIO_ACTIVE_LOW>; /* DP_HPD */
|
||||
+ vpd-data-role = "display-port";
|
||||
+ vpd-super-speed;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&cdn_dp {
|
||||
+ extcon = <&virtual_pd>;
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&tcphy0 {
|
||||
+ extcon = <&virtual_pd>;
|
||||
};
|
||||
|
||||
&sdio0 {
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
diff --git a/Documentation/devicetree/bindings/extcon/extcon-usbc-virtual-pd.yaml b/Documentation/devicetree/bindings/extcon/extcon-usbc-virtual-pd.yaml
|
||||
new file mode 100644
|
||||
index 000000000000..8110fbe2ddc2
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/extcon/extcon-usbc-virtual-pd.yaml
|
||||
@@ -0,0 +1,66 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/extcon/extcon-usbc-virtual-pd.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Type-C Virtual PD extcon
|
||||
+
|
||||
+maintainers:
|
||||
+ - Jagan Teki <jagan@amarulasolutions.com>
|
||||
+
|
||||
+description: |
|
||||
+ USB Type-C protocol supports various modes of operations includes PD,
|
||||
+ USB3, and Altmode. If the platform design supports a Type-C connector
|
||||
+ then configuring these modes can be done via enumeration.
|
||||
+
|
||||
+ However, there are some platforms that design these modes as separate
|
||||
+ protocol connectors like design Display Port from on-chip USB3 controller.
|
||||
+ So we can access Type-C Altmode Display Port via onboard Display Port
|
||||
+ connector instead of a Type-C connector. These kinds of platforms require
|
||||
+ an explicit extcon driver in order to handle Power Delivery and
|
||||
+ Port Detection.
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ const: linux,extcon-usbc-virtual-pd
|
||||
+
|
||||
+ det-gpios:
|
||||
+ description: Detect GPIO pin. Pin can be Display Port Detect or USB ID.
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ vpd-polarity:
|
||||
+ description: USB Type-C Polarity. false for Normal and true for Flip.
|
||||
+ type: boolean
|
||||
+
|
||||
+ vpd-super-speed:
|
||||
+ description: USB Super Speed. false for USB2 and true for USB3.
|
||||
+ type: boolean
|
||||
+
|
||||
+ vpd-data-role:
|
||||
+ description: USB Data roles for Virtual Type-C.
|
||||
+ $ref: /schemas/types.yaml#definitions/string
|
||||
+
|
||||
+ enum:
|
||||
+ - host
|
||||
+ - device
|
||||
+ - display-port
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - det-gpios
|
||||
+ - vpd-data-role
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ #include <dt-bindings/gpio/gpio.h>
|
||||
+ #include <dt-bindings/pinctrl/rockchip.h>
|
||||
+
|
||||
+ virtual_pd: virtual-pd {
|
||||
+ compatible = "linux,extcon-usbc-virtual-pd";
|
||||
+ det-gpios = <&gpio4 RK_PD1 GPIO_ACTIVE_LOW>;
|
||||
+ vpd-data-role = "display-port";
|
||||
+ vpd-super-speed;
|
||||
+ };
|
||||
|
||||
@ -0,0 +1,337 @@
|
||||
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||
index 68f21d46614c..aeb161b19dae 100644
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -6466,6 +6466,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git
|
||||
F: Documentation/filesystems/ext4/
|
||||
F: fs/ext4/
|
||||
|
||||
+EXTCON DRIVER FOR TYPE-C VIRTUAL PD
|
||||
+M: Jagan Teki <jagan@amarulasolutions.com>
|
||||
+S: Maintained
|
||||
+F: Documentation/devicetree/bindings/extcon/extcon-usbc-virtual-pd.yaml
|
||||
+F: drivers/extcon/extcon-usbc-virtual-pd.c
|
||||
+
|
||||
Extended Verification Module (EVM)
|
||||
M: Mimi Zohar <zohar@linux.ibm.com>
|
||||
L: linux-integrity@vger.kernel.org
|
||||
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
|
||||
index aac507bff135..edd6c3c52699 100644
|
||||
--- a/drivers/extcon/Kconfig
|
||||
+++ b/drivers/extcon/Kconfig
|
||||
@@ -186,4 +186,14 @@ config EXTCON_USBC_CROS_EC
|
||||
Say Y here to enable USB Type C cable detection extcon support when
|
||||
using Chrome OS EC based USB Type-C ports.
|
||||
|
||||
+config EXTCON_USBC_VIRTUAL_PD
|
||||
+ tristate "Virtual Type-C PD EXTCON support"
|
||||
+ depends on GPIOLIB || COMPILE_TEST
|
||||
+ help
|
||||
+ Say Y here to enable Virtual Type-C PD extcon driver support, if
|
||||
+ hardware platform designed Type-C modes separately.
|
||||
+
|
||||
+ Example, of designing Display Port separately from Type-C Altmode
|
||||
+ instead of accessing Altmode Display Port in Type-C connector.
|
||||
+
|
||||
endif
|
||||
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
|
||||
index 52096fd8a216..c35191eef0e1 100644
|
||||
--- a/drivers/extcon/Makefile
|
||||
+++ b/drivers/extcon/Makefile
|
||||
@@ -25,3 +25,4 @@ obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o
|
||||
obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
|
||||
obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o
|
||||
obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o
|
||||
+obj-$(CONFIG_EXTCON_USBC_VIRTUAL_PD) += extcon-usbc-virtual-pd.o
|
||||
diff --git a/drivers/extcon/extcon-usbc-virtual-pd.c b/drivers/extcon/extcon-usbc-virtual-pd.c
|
||||
new file mode 100644
|
||||
index 000000000000..e0713670e33d
|
||||
--- /dev/null
|
||||
+++ b/drivers/extcon/extcon-usbc-virtual-pd.c
|
||||
@@ -0,0 +1,285 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Type-C Virtual PD Extcon driver
|
||||
+ *
|
||||
+ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
|
||||
+ * Copyright (c) 2019 Radxa Limited
|
||||
+ * Copyright (c) 2019 Amarula Solutions(India)
|
||||
+ */
|
||||
+
|
||||
+#include <linux/extcon-provider.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_gpio.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+static const unsigned int vpd_cable[] = {
|
||||
+ EXTCON_USB,
|
||||
+ EXTCON_USB_HOST,
|
||||
+ EXTCON_DISP_DP,
|
||||
+ EXTCON_NONE,
|
||||
+};
|
||||
+
|
||||
+enum vpd_data_role {
|
||||
+ DR_NONE,
|
||||
+ DR_HOST,
|
||||
+ DR_DEVICE,
|
||||
+ DR_DISPLAY_PORT,
|
||||
+};
|
||||
+
|
||||
+enum vpd_polarity {
|
||||
+ POLARITY_NORMAL,
|
||||
+ POLARITY_FLIP,
|
||||
+};
|
||||
+
|
||||
+enum vpd_usb_ss {
|
||||
+ USB_SS_USB2,
|
||||
+ USB_SS_USB3,
|
||||
+};
|
||||
+
|
||||
+struct vpd_extcon {
|
||||
+ struct device *dev;
|
||||
+ struct extcon_dev *extcon;
|
||||
+ struct gpio_desc *det_gpio;
|
||||
+
|
||||
+ u8 polarity;
|
||||
+ u8 usb_ss;
|
||||
+ enum vpd_data_role data_role;
|
||||
+
|
||||
+ int irq;
|
||||
+ bool enable_irq;
|
||||
+ struct work_struct work;
|
||||
+ struct delayed_work irq_work;
|
||||
+};
|
||||
+
|
||||
+static void vpd_extcon_irq_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct vpd_extcon *vpd = container_of(work, struct vpd_extcon, irq_work.work);
|
||||
+ bool host_connected = false, device_connected = false, dp_connected = false;
|
||||
+ union extcon_property_value property;
|
||||
+ int det;
|
||||
+
|
||||
+ det = vpd->det_gpio ? gpiod_get_raw_value(vpd->det_gpio) : 0;
|
||||
+ if (det) {
|
||||
+ device_connected = (vpd->data_role == DR_DEVICE) ? true : false;
|
||||
+ host_connected = (vpd->data_role == DR_HOST) ? true : false;
|
||||
+ dp_connected = (vpd->data_role == DR_DISPLAY_PORT) ? true : false;
|
||||
+ }
|
||||
+
|
||||
+ extcon_set_state(vpd->extcon, EXTCON_USB, host_connected);
|
||||
+ extcon_set_state(vpd->extcon, EXTCON_USB_HOST, device_connected);
|
||||
+ extcon_set_state(vpd->extcon, EXTCON_DISP_DP, dp_connected);
|
||||
+
|
||||
+ property.intval = vpd->polarity;
|
||||
+ extcon_set_property(vpd->extcon, EXTCON_USB,
|
||||
+ EXTCON_PROP_USB_TYPEC_POLARITY, property);
|
||||
+ extcon_set_property(vpd->extcon, EXTCON_USB_HOST,
|
||||
+ EXTCON_PROP_USB_TYPEC_POLARITY, property);
|
||||
+ extcon_set_property(vpd->extcon, EXTCON_DISP_DP,
|
||||
+ EXTCON_PROP_USB_TYPEC_POLARITY, property);
|
||||
+
|
||||
+ property.intval = vpd->usb_ss;
|
||||
+ extcon_set_property(vpd->extcon, EXTCON_USB,
|
||||
+ EXTCON_PROP_USB_SS, property);
|
||||
+ extcon_set_property(vpd->extcon, EXTCON_USB_HOST,
|
||||
+ EXTCON_PROP_USB_SS, property);
|
||||
+ extcon_set_property(vpd->extcon, EXTCON_DISP_DP,
|
||||
+ EXTCON_PROP_USB_SS, property);
|
||||
+
|
||||
+ extcon_sync(vpd->extcon, EXTCON_USB);
|
||||
+ extcon_sync(vpd->extcon, EXTCON_USB_HOST);
|
||||
+ extcon_sync(vpd->extcon, EXTCON_DISP_DP);
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t vpd_extcon_irq_handler(int irq, void *dev_id)
|
||||
+{
|
||||
+ struct vpd_extcon *vpd = dev_id;
|
||||
+
|
||||
+ schedule_delayed_work(&vpd->irq_work, msecs_to_jiffies(10));
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static enum vpd_data_role vpd_extcon_data_role(struct vpd_extcon *vpd)
|
||||
+{
|
||||
+ const char *const data_roles[] = {
|
||||
+ [DR_NONE] = "NONE",
|
||||
+ [DR_HOST] = "host",
|
||||
+ [DR_DEVICE] = "device",
|
||||
+ [DR_DISPLAY_PORT] = "display-port",
|
||||
+ };
|
||||
+ struct device *dev = vpd->dev;
|
||||
+ int ret;
|
||||
+ const char *dr;
|
||||
+
|
||||
+ ret = device_property_read_string(dev, "vpd-data-role", &dr);
|
||||
+ if (ret < 0)
|
||||
+ return DR_NONE;
|
||||
+
|
||||
+ ret = match_string(data_roles, ARRAY_SIZE(data_roles), dr);
|
||||
+
|
||||
+ return (ret < 0) ? DR_NONE : ret;
|
||||
+}
|
||||
+
|
||||
+static int vpd_extcon_parse_dts(struct vpd_extcon *vpd)
|
||||
+{
|
||||
+ struct device *dev = vpd->dev;
|
||||
+ bool val = false;
|
||||
+ int ret;
|
||||
+
|
||||
+ val = device_property_read_bool(dev, "vpd-polarity");
|
||||
+ if (val)
|
||||
+ vpd->polarity = POLARITY_FLIP;
|
||||
+ else
|
||||
+ vpd->polarity = POLARITY_NORMAL;
|
||||
+
|
||||
+ val = device_property_read_bool(dev, "vpd-super-speed");
|
||||
+ if (val)
|
||||
+ vpd->usb_ss = USB_SS_USB3;
|
||||
+ else
|
||||
+ vpd->usb_ss = USB_SS_USB2;
|
||||
+
|
||||
+ vpd->data_role = vpd_extcon_data_role(vpd);
|
||||
+
|
||||
+ vpd->det_gpio = devm_gpiod_get_optional(dev, "det", GPIOD_OUT_LOW);
|
||||
+ if (IS_ERR(vpd->det_gpio)) {
|
||||
+ ret = PTR_ERR(vpd->det_gpio);
|
||||
+ dev_warn(dev, "failed to get det gpio: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ vpd->irq = gpiod_to_irq(vpd->det_gpio);
|
||||
+ if (vpd->irq < 0) {
|
||||
+ dev_err(dev, "failed to get irq for gpio: %d\n", vpd->irq);
|
||||
+ return vpd->irq;
|
||||
+ }
|
||||
+
|
||||
+ ret = devm_request_threaded_irq(dev, vpd->irq, NULL,
|
||||
+ vpd_extcon_irq_handler,
|
||||
+ IRQF_TRIGGER_FALLING |
|
||||
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
+ NULL, vpd);
|
||||
+ if (ret)
|
||||
+ dev_err(dev, "failed to request gpio irq\n");
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int vpd_extcon_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct vpd_extcon *vpd;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ int ret;
|
||||
+
|
||||
+ vpd = devm_kzalloc(dev, sizeof(*vpd), GFP_KERNEL);
|
||||
+ if (!vpd)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ vpd->dev = dev;
|
||||
+ ret = vpd_extcon_parse_dts(vpd);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ INIT_DELAYED_WORK(&vpd->irq_work, vpd_extcon_irq_work);
|
||||
+
|
||||
+ vpd->extcon = devm_extcon_dev_allocate(dev, vpd_cable);
|
||||
+ if (IS_ERR(vpd->extcon)) {
|
||||
+ dev_err(dev, "allocat extcon failed\n");
|
||||
+ return PTR_ERR(vpd->extcon);
|
||||
+ }
|
||||
+
|
||||
+ ret = devm_extcon_dev_register(dev, vpd->extcon);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "register extcon failed: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ extcon_set_property_capability(vpd->extcon, EXTCON_USB,
|
||||
+ EXTCON_PROP_USB_VBUS);
|
||||
+ extcon_set_property_capability(vpd->extcon, EXTCON_USB_HOST,
|
||||
+ EXTCON_PROP_USB_VBUS);
|
||||
+
|
||||
+ extcon_set_property_capability(vpd->extcon, EXTCON_USB,
|
||||
+ EXTCON_PROP_USB_TYPEC_POLARITY);
|
||||
+ extcon_set_property_capability(vpd->extcon, EXTCON_USB_HOST,
|
||||
+ EXTCON_PROP_USB_TYPEC_POLARITY);
|
||||
+ extcon_set_property_capability(vpd->extcon, EXTCON_USB,
|
||||
+ EXTCON_PROP_USB_SS);
|
||||
+ extcon_set_property_capability(vpd->extcon, EXTCON_USB_HOST,
|
||||
+ EXTCON_PROP_USB_SS);
|
||||
+
|
||||
+ extcon_set_property_capability(vpd->extcon, EXTCON_DISP_DP,
|
||||
+ EXTCON_PROP_USB_SS);
|
||||
+ extcon_set_property_capability(vpd->extcon, EXTCON_DISP_DP,
|
||||
+ EXTCON_PROP_USB_TYPEC_POLARITY);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, vpd);
|
||||
+
|
||||
+ vpd_extcon_irq_work(&vpd->irq_work.work);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vpd_extcon_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct vpd_extcon *vpd = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ cancel_delayed_work_sync(&vpd->irq_work);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+static int vpd_extcon_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct vpd_extcon *vpd = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (!vpd->enable_irq) {
|
||||
+ disable_irq_nosync(vpd->irq);
|
||||
+ vpd->enable_irq = true;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vpd_extcon_resume(struct device *dev)
|
||||
+{
|
||||
+ struct vpd_extcon *vpd = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (vpd->enable_irq) {
|
||||
+ enable_irq(vpd->irq);
|
||||
+ vpd->enable_irq = false;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static SIMPLE_DEV_PM_OPS(vpd_extcon_pm_ops,
|
||||
+ vpd_extcon_suspend, vpd_extcon_resume);
|
||||
+
|
||||
+static const struct of_device_id vpd_extcon_dt_match[] = {
|
||||
+ { .compatible = "linux,extcon-usbc-virtual-pd", },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver vpd_extcon_driver = {
|
||||
+ .probe = vpd_extcon_probe,
|
||||
+ .remove = vpd_extcon_remove,
|
||||
+ .driver = {
|
||||
+ .name = "extcon-usbc-virtual-pd",
|
||||
+ .pm = &vpd_extcon_pm_ops,
|
||||
+ .of_match_table = vpd_extcon_dt_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(vpd_extcon_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Jagan Teki <jagan@amarulasolutions.com>");
|
||||
+MODULE_DESCRIPTION("Type-C Virtual PD extcon driver");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user