build/patch/kernel/archive/rockchip64-6.4/general-add-miniDP-virtual-extcon.patch

383 lines
12 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tony <tonymckahan@gmail.com>
Date: Wed, 3 Mar 2021 07:59:25 +0100
Subject: [ARCHEOLOGY] RK3399 Typec DP (#2676)
> X-Git-Archeology: > recovered message: > * RK3399 NanoPC-T4 Add Type-C alt mode DP
> X-Git-Archeology: > recovered message: > * rk3399 rockpi 4C add mini-DP (WIP)
> X-Git-Archeology: > recovered message: > * [ rockchip64 ] revert rockPi 4C DP patch
> X-Git-Archeology: > recovered message: > Add an extension to disable it, but leave for future work.
> X-Git-Archeology: - Revision 4971535c774a1f49a811baebc083ea028ced0300: https://github.com/armbian/build/commit/4971535c774a1f49a811baebc083ea028ced0300
> X-Git-Archeology: Date: Wed, 03 Mar 2021 07:59:25 +0100
> X-Git-Archeology: From: Tony <tonymckahan@gmail.com>
> X-Git-Archeology: Subject: RK3399 Typec DP (#2676)
> X-Git-Archeology:
> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153
> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100
> X-Git-Archeology: From: Igor Pecovnik <igorpecovnik@users.noreply.github.com>
> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704)
> X-Git-Archeology:
> X-Git-Archeology: - Revision ac8fc4385594d59257ee9dffd9efa85e3497fa7d: https://github.com/armbian/build/commit/ac8fc4385594d59257ee9dffd9efa85e3497fa7d
> X-Git-Archeology: Date: Sat, 26 Feb 2022 07:46:44 +0100
> X-Git-Archeology: From: Piotr Szczepanik <piter75@gmail.com>
> X-Git-Archeology: Subject: Switch rockchip64 current to linux 5.15.y (#3489)
> X-Git-Archeology:
> X-Git-Archeology: - Revision 897674aa74bce0326ed7fe06f5336bf4709a8a1f: https://github.com/armbian/build/commit/897674aa74bce0326ed7fe06f5336bf4709a8a1f
> X-Git-Archeology: Date: Tue, 03 May 2022 08:27:32 +0200
> X-Git-Archeology: From: Igor Pecovnik <igorpecovnik@users.noreply.github.com>
> X-Git-Archeology: Subject: Bump and freeze kernel at last known working versions (#3736)
> X-Git-Archeology:
> X-Git-Archeology: - Revision 597d2dac11f00d9070a4e49d6bad1b2244e36cb3: https://github.com/armbian/build/commit/597d2dac11f00d9070a4e49d6bad1b2244e36cb3
> X-Git-Archeology: Date: Sat, 28 May 2022 07:56:22 +0200
> X-Git-Archeology: From: Jianfeng Liu <liujianfeng1994@gmail.com>
> X-Git-Archeology: Subject: update rockchip64-edge to 5.18 (#3814)
> X-Git-Archeology:
> X-Git-Archeology: - Revision 8c6641e7b79f0d50acdc306d140e586a4e923cf0: https://github.com/armbian/build/commit/8c6641e7b79f0d50acdc306d140e586a4e923cf0
> X-Git-Archeology: Date: Wed, 03 Aug 2022 22:22:55 +0200
> X-Git-Archeology: From: Jianfeng Liu <liujianfeng1994@gmail.com>
> X-Git-Archeology: Subject: update rockchip64 edge to 5.19 (#4039)
> X-Git-Archeology:
> X-Git-Archeology: - Revision 6765f734cc4a22aeaa9f99a3ad28c8c322de26f6: https://github.com/armbian/build/commit/6765f734cc4a22aeaa9f99a3ad28c8c322de26f6
> X-Git-Archeology: Date: Tue, 25 Oct 2022 11:26:51 +0200
> X-Git-Archeology: From: Igor Pecovnik <igorpecovnik@users.noreply.github.com>
> X-Git-Archeology: Subject: Bump rockchip64 edge to 6.0.y (#4337)
> X-Git-Archeology:
> X-Git-Archeology: - Revision 92f1a22d76b987afa7ba555d5b509adc51d689e7: https://github.com/armbian/build/commit/92f1a22d76b987afa7ba555d5b509adc51d689e7
> X-Git-Archeology: Date: Fri, 16 Dec 2022 13:38:13 +0100
> X-Git-Archeology: From: Igor Pecovnik <igorpecovnik@users.noreply.github.com>
> X-Git-Archeology: Subject: Re-add rockchip64 6.0 patches (#4575)
> X-Git-Archeology:
> X-Git-Archeology: - Revision 34ae84fac5d0b66a1ab2d1e51534b7beb13ef245: https://github.com/armbian/build/commit/34ae84fac5d0b66a1ab2d1e51534b7beb13ef245
> X-Git-Archeology: Date: Fri, 05 May 2023 14:22:00 +0200
> X-Git-Archeology: From: amazingfate <liujianfeng1994@gmail.com>
> X-Git-Archeology: Subject: bump rockchip64 edge to v6.3
> X-Git-Archeology:
---
drivers/extcon/Kconfig | 10 +
drivers/extcon/Makefile | 1 +
drivers/extcon/extcon-usbc-virtual-pd.c | 285 ++++++++++
3 files changed, 296 insertions(+)
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 290186e44e6b..ac0b6164d88e 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -189,4 +189,14 @@ config EXTCON_USBC_TUSB320
Say Y here to enable support for USB Type C cable detection extcon
support using a TUSB320.
+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 1b390d934ca9..57c1e65bfcfd 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -25,3 +25,4 @@ 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_TUSB320) += extcon-usbc-tusb320.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");
--
Armbian