devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
@ 2023-08-22 10:28 Stanley Chang
  2023-08-22 10:28 ` [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C Stanley Chang
                   ` (4 more replies)
  0 siblings, 5 replies; 19+ messages in thread
From: Stanley Chang @ 2023-08-22 10:28 UTC (permalink / raw)
  To: MyungJoo Ham
  Cc: Stanley Chang, Chanwoo Choi, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-kernel, devicetree

This patch adds the extcon driver for Realtek DHC (digital home center)
RTD SoCs type-c module. This can be used to detect whether the port is
configured as a downstream or upstream facing port. And notify the status
of extcon to listeners.

Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
---
 drivers/extcon/Kconfig             |    9 +
 drivers/extcon/Makefile            |    1 +
 drivers/extcon/extcon-rtk-type-c.c | 1799 ++++++++++++++++++++++++++++
 3 files changed, 1809 insertions(+)
 create mode 100644 drivers/extcon/extcon-rtk-type-c.c

diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 0ef1971d22bb..d670434321f2 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -190,4 +190,13 @@ config EXTCON_USBC_TUSB320
 	  Say Y here to enable support for USB Type C cable detection extcon
 	  support using a TUSB320.
 
+config EXTCON_RTK_TYPE_C
+	tristate "Realtek RTD SoC extcon Type-C Driver"
+	depends on ARCH_REALTEK || COMPILE_TEST
+	help
+	  Say Y here to enable extcon support for USB Type C cable detection
+	  when using the Realtek RTD SoC USB Type-C port.
+	  The DHC (Digital Home Hub) RTD series SoC contains a type c module.
+	  This driver will detect the status of the type-c port.
+
 endif
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 1b390d934ca9..f779adb5e4c7 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_RTK_TYPE_C) += extcon-rtk-type-c.o
diff --git a/drivers/extcon/extcon-rtk-type-c.c b/drivers/extcon/extcon-rtk-type-c.c
new file mode 100644
index 000000000000..04d4d5128bdb
--- /dev/null
+++ b/drivers/extcon/extcon-rtk-type-c.c
@@ -0,0 +1,1799 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  * extcon-rtk-type-c.c - Realtek Extcon Type C driver
+ *
+ * Copyright (C) 2023 Realtek Semiconductor Corporation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/syscalls.h>
+#include <linux/suspend.h>
+#include <linux/debugfs.h>
+#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
+#include <linux/sys_soc.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/typec.h>
+
+struct cc_param {
+	u32 rp_4p7k_code;
+	u32 rp_36k_code;
+	u32 rp_12k_code;
+	u32 rd_code;
+	u32 ra_code;
+	u32 vref_2p6v;
+	u32 vref_1p23v;
+	u32 vref_0p8v;
+	u32 vref_0p66v;
+	u32 vref_0p4v;
+	u32 vref_0p2v;
+	u32 vref_1_1p6v;
+	u32 vref_0_1p6v;
+};
+
+struct type_c_cfg {
+	int parameter_ver; /* Parameter version */
+	int cc_dfp_mode;
+	struct cc_param cc1_param;
+	struct cc_param cc2_param;
+
+	u32 debounce_val;
+	bool use_defalut_parameter;
+};
+
+struct type_c_data {
+	void __iomem *reg_base;
+	struct device *dev;
+	struct extcon_dev *edev;
+
+	u32 irq;
+
+	/* rd control GPIO only for rtd1295 */
+	unsigned int rd_ctrl_gpio;
+
+	/* Parameters */
+	struct type_c_cfg *type_c_cfg;
+	u32 dfp_mode_rp_en;
+	u32 ufp_mode_rd_en;
+	u32 cc1_code;
+	u32 cc2_code;
+	u32 cc1_vref;
+	u32 cc2_vref;
+	u32 debounce; /* 1b,1us 7f,4.7us */
+
+	/* type_c state */
+	int connect_change;
+#define CONNECT_CHANGE 1
+#define CONNECT_NO_CHANGE 0
+	int cc_mode; /* cc is host or device */
+#define IN_HOST_MODE 0x10
+#define IN_DEVICE_MODE 0x20
+	int is_attach;
+#define IN_ATTACH 1
+#define TO_ATTACH 1
+#define IN_DETACH 0
+#define TO_DETACH 0
+	int at_cc1;
+#define AT_CC1 1
+#define AT_CC2 0
+
+	u32 int_status;
+	u32 cc_status;
+	/* protect the data member */
+	spinlock_t lock;
+	struct delayed_work delayed_work;
+
+	bool rd_en_at_first;
+
+	struct dentry *debug_dir;
+
+#ifdef CONFIG_TYPEC
+	struct typec_port *port;
+#endif /* CONFIG_TYPEC */
+};
+
+/* Type C register offset */
+#define USB_TYPEC_CTRL_CC1_0 0x0
+#define USB_TYPEC_CTRL_CC1_1 0x4
+#define USB_TYPEC_CTRL_CC2_0 0x8
+#define USB_TYPEC_CTRL_CC2_1 0xC
+#define USB_TYPEC_STS        0x10
+#define USB_TYPEC_CTRL       0x14
+#define USB_DBUS_PWR_CTRL    0x18
+
+#define ENABLE_CC1 0x1
+#define ENABLE_CC2 0x2
+#define DISABLE_CC 0x0
+
+/* Bit mapping USB_TYPEC_CTRL_CC1_0 and USB_TYPEC_CTRL_CC2_0 */
+#define PLR_EN BIT(29)
+#define CC_SWITCH_MASK (BIT(29) | BIT(28) | BIT(27))
+#define CC_CODE_MASK (0xfffff << 7)
+#define rp4pk_code(val) ((0x1f & (val)) << 22)
+#define code_rp4pk(val) (((val) >> 22) & 0x1f)
+#define rp36k_code(val) ((0x1f & (val)) << 17)
+#define code_rp36k(val) (((val) >> 17) & 0x1f)
+#define rp12k_code(val) ((0x1f & (val)) << 12)
+#define code_rp12k(val) (((val) >> 12) & 0x1f)
+#define rd_code(val) ((0x1f & (val)) << 7)
+#define code_rd(val) (((val) >> 7) & 0x1f)
+#define dfp_mode(val) ((0x3 & (val)) << 5)
+#define EN_RP4P7K BIT(4)
+#define EN_RP36K BIT(3)
+#define EN_RP12K BIT(2)
+#define EN_RD BIT(1)
+#define EN_CC_DET BIT(0)
+
+#define CC_MODE_UFP 0x0
+#define CC_MODE_DFP_USB 0x1
+#define CC_MODE_DFP_1_5 0x2
+#define CC_MODE_DFP_3_0 0x3
+
+/*
+ * PARAMETER_V0:
+ *  Realtek Kylin    rtd1295
+ *  Realtek Hercules rtd1395
+ *  Realtek Thor     rtd1619
+ *  Realtek Hank     rtd1319
+ *  Realtek Groot    rtd1312c
+ * PARAMETER_V1:
+ *  Realtek Stark    rtd1619b
+ *  Realtek Parker   rtd1319d
+ *  Realtek Danvers  rtd1315e
+ */
+enum parameter_version {
+	PARAMETER_V0 = 0,
+	PARAMETER_V1 = 1,
+};
+
+/* Bit mapping USB_TYPEC_CTRL_CC1_1 and USB_TYPEC_CTRL_CC2_1 */
+#define V0_vref_2p6v(val) ((0xf & (val)) << 26) /* Bit 29 for groot */
+#define V0_vref_1p23v(val) ((0xf & (val)) << 22)
+#define V0_vref_0p8v(val) ((0xf & (val)) << 18)
+#define V0_vref_0p66v(val) ((0xf & (val)) << 14)
+#define V0_vref_0p4v(val) ((0x7 & (val)) << 11)
+#define V0_vref_0p2v(val) ((0x7 & (val)) << 8)
+#define V0_vref_1_1p6v(val) ((0xf & (val)) << 4)
+#define V0_vref_0_1p6v(val) ((0xf & (val)) << 0)
+
+#define V0_decode_2p6v(val) (((val) >> 26) & 0xf) /* Bit 29 for groot */
+#define V0_decode_1p23v(val) (((val) >> 22) & 0xf)
+#define V0_decode_0p8v(val) (((val) >> 18) & 0xf)
+#define V0_decode_0p66v(val) (((val) >> 14) & 0xf)
+#define V0_decode_0p4v(val) (((val) >> 11) & 0x7)
+#define V0_decode_0p2v(val) (((val) >> 8) & 0x7)
+#define V0_decode_1_1p6v(val) (((val) >> 4) & 0xf)
+#define V0_decode_0_1p6v(val) (((val) >> 0) & 0xf)
+
+/* new Bit mapping USB_TYPEC_CTRL_CC1_1 and USB_TYPEC_CTRL_CC2_1 */
+#define V1_vref_2p6v(val) ((0xf & (val)) << 28)
+#define V1_vref_1p23v(val) ((0xf & (val)) << 24)
+#define V1_vref_0p8v(val) ((0xf & (val)) << 20)
+#define V1_vref_0p66v(val) ((0xf & (val)) << 16)
+#define V1_vref_0p4v(val) ((0xf & (val)) << 12)
+#define V1_vref_0p2v(val) ((0xf & (val)) << 8)
+#define V1_vref_1_1p6v(val) ((0xf & (val)) << 4)
+#define V1_vref_0_1p6v(val) ((0xf & (val)) << 0)
+
+#define V1_decode_2p6v(val) (((val) >> 28) & 0xf)
+#define V1_decode_1p23v(val) (((val) >> 24) & 0xf)
+#define V1_decode_0p8v(val) (((val) >> 20) & 0xf)
+#define V1_decode_0p66v(val) (((val) >> 16) & 0xf)
+#define V1_decode_0p4v(val) (((val) >> 12) & 0xf)
+#define V1_decode_0p2v(val) (((val) >> 8) & 0xf)
+#define V1_decode_1_1p6v(val) (((val) >> 4) & 0xf)
+#define V1_decode_0_1p6v(val) (((val) >> 0) & 0xf)
+
+/* Bit mapping USB_TYPEC_STS */
+#define DET_STS 0x7
+#define CC1_DET_STS (DET_STS)
+#define CC2_DET_STS (DET_STS << 3)
+#define DET_STS_RA 0x1
+#define DET_STS_RD 0x3
+#define DET_STS_RP 0x1
+#define CC1_DET_STS_RA (DET_STS_RA)
+#define CC1_DET_STS_RD (DET_STS_RD)
+#define CC1_DET_STS_RP (DET_STS_RP)
+#define CC2_DET_STS_RA (DET_STS_RA << 3)
+#define CC2_DET_STS_RD (DET_STS_RD << 3)
+#define CC2_DET_STS_RP (DET_STS_RP << 3)
+
+/* Bit mapping USB_TYPEC_CTRL */
+#define CC2_INT_EN BIT(11)
+#define CC1_INT_EN BIT(10)
+#define CC2_INT_STS BIT(9)
+#define CC1_INT_STS BIT(8)
+#define DEBOUNCE_TIME_MASK 0xff
+#define DEBOUNCE_EN BIT(0)
+#define ENABLE_TYPE_C_DETECT (CC1_INT_EN | CC2_INT_EN)
+#define ALL_CC_INT_STS (CC1_INT_STS | CC2_INT_STS)
+
+/* Parameter */
+#define DETECT_TIME 50 /* ms */
+
+static const unsigned int usb_type_c_cable[] = {
+	EXTCON_USB,
+	EXTCON_USB_HOST,
+	EXTCON_NONE,
+};
+
+enum usb_data_roles {
+	DR_NONE,
+	DR_HOST,
+	DR_DEVICE,
+};
+
+static const struct soc_device_attribute rtk_soc_kylin[] = {
+	{ .family = "Realtek Kylin", },
+	{ /* empty */ }
+};
+
+static int rtd129x_switch_type_c_plug_config(struct type_c_data *type_c,
+					     int dr_mode, int cc)
+{
+	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
+	int val_cc;
+
+#define TYPE_C_EN_SWITCH BIT(29)
+#define TYPE_C_TXRX_SEL (BIT(28) | BIT(27))
+#define TYPE_C_SWITCH_MASK (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
+#define TYPE_C_ENABLE_CC1 TYPE_C_EN_SWITCH
+#define TYPE_C_ENABLE_CC2 (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
+#define TYPE_C_DISABLE_CC ~TYPE_C_SWITCH_MASK
+
+	val_cc = readl(reg);
+	val_cc &= ~TYPE_C_SWITCH_MASK;
+
+	if (cc == DISABLE_CC) {
+		val_cc &= TYPE_C_DISABLE_CC;
+	} else if (cc == ENABLE_CC1) {
+		val_cc |= TYPE_C_ENABLE_CC1;
+	} else if (cc == ENABLE_CC2) {
+		val_cc |= TYPE_C_ENABLE_CC2;
+	} else {
+		dev_err(type_c->dev, "%s: Error cc setting cc=0x%x\n", __func__, cc);
+		return -EINVAL;
+	}
+	writel(val_cc, reg);
+
+	mdelay(1);
+
+	dev_dbg(type_c->dev, "%s: cc=0x%x val_cc=0x%x usb_typec_ctrl_cc1_0=0x%x\n",
+		__func__, cc, val_cc, readl(reg));
+
+	return 0;
+}
+
+static inline void switch_type_c_plug_config(struct type_c_data *type_c,
+					     int dr_mode, int cc)
+{
+	int ret = 0;
+
+	if (soc_device_match(rtk_soc_kylin))
+		ret = rtd129x_switch_type_c_plug_config(type_c, dr_mode, cc);
+
+	if (ret < 0)
+		dev_err(type_c->dev, "%s: Error set type c plug config\n",
+			__func__);
+}
+
+static void switch_type_c_dr_mode(struct type_c_data *type_c, int dr_mode, int cc)
+{
+	bool is_host = false;
+	bool is_device = false;
+	bool polarity = false;
+	bool vbus = false;
+	bool ss = true;
+
+	switch_type_c_plug_config(type_c, dr_mode, cc);
+	if (cc == ENABLE_CC2)
+		polarity = true;
+
+	switch (dr_mode) {
+	case USB_DR_MODE_HOST:
+		is_host = true;
+		break;
+	case USB_DR_MODE_PERIPHERAL:
+		is_device = true;
+		vbus = true;
+		break;
+	default:
+		dev_dbg(type_c->dev, "%s dr_mode=%d ==> no host or device\n",
+			__func__, dr_mode);
+		break;
+	}
+
+	dev_dbg(type_c->dev, "%s is_host=%d is_device=%d vbus=%d polarity=%d\n",
+		__func__, is_host, is_device, vbus, polarity);
+
+	/* for EXTCON_USB device mode */
+	extcon_set_state(type_c->edev, EXTCON_USB, is_device);
+	extcon_set_property(type_c->edev, EXTCON_USB,
+			    EXTCON_PROP_USB_VBUS,
+			    (union extcon_property_value)(int)vbus);
+	extcon_set_property(type_c->edev, EXTCON_USB,
+			    EXTCON_PROP_USB_TYPEC_POLARITY,
+			    (union extcon_property_value)(int)polarity);
+	extcon_set_property(type_c->edev, EXTCON_USB,
+			    EXTCON_PROP_USB_SS,
+			    (union extcon_property_value)(int)ss);
+
+	/* for EXTCON_USB_HOST host mode */
+	extcon_set_state(type_c->edev, EXTCON_USB_HOST, is_host);
+	extcon_set_property(type_c->edev, EXTCON_USB_HOST,
+			    EXTCON_PROP_USB_VBUS,
+			    (union extcon_property_value)(int)vbus);
+	extcon_set_property(type_c->edev, EXTCON_USB_HOST,
+			    EXTCON_PROP_USB_TYPEC_POLARITY,
+			    (union extcon_property_value)(int)polarity);
+	extcon_set_property(type_c->edev, EXTCON_USB_HOST,
+			    EXTCON_PROP_USB_SS,
+			    (union extcon_property_value)(int)ss);
+
+	/* sync EXTCON_USB and EXTCON_USB_HOST */
+	extcon_sync(type_c->edev, EXTCON_USB);
+	extcon_sync(type_c->edev, EXTCON_USB_HOST);
+
+#ifdef CONFIG_TYPEC
+	if (type_c->port) {
+		switch (dr_mode) {
+		case USB_DR_MODE_HOST:
+			typec_set_data_role(type_c->port, TYPEC_HOST);
+			typec_set_pwr_role(type_c->port, TYPEC_SOURCE);
+			break;
+		case USB_DR_MODE_PERIPHERAL:
+			typec_set_data_role(type_c->port, TYPEC_DEVICE);
+			typec_set_pwr_role(type_c->port, TYPEC_SINK);
+			break;
+		default:
+			dev_dbg(type_c->dev, "%s unknown dr_mode=%d\n",
+				__func__, dr_mode);
+			break;
+		}
+	}
+#endif
+}
+
+/* device attached/detached */
+static int device_attached(struct type_c_data *type_c, u32 cc)
+{
+	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
+
+	cancel_delayed_work(&type_c->delayed_work);
+
+	switch_type_c_dr_mode(type_c, USB_DR_MODE_HOST, cc);
+
+	writel(ENABLE_TYPE_C_DETECT | readl(reg), reg);
+
+	return 0;
+}
+
+static int device_detached(struct type_c_data *type_c, u32 cc)
+{
+	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
+
+	writel(~ENABLE_TYPE_C_DETECT & readl(reg), reg);
+
+	switch_type_c_dr_mode(type_c, 0, cc);
+
+	schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(DETECT_TIME));
+
+	return 0;
+}
+
+/* host connect/disconnect*/
+static int host_connected(struct type_c_data *type_c, u32 cc)
+{
+	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
+
+	cancel_delayed_work(&type_c->delayed_work);
+
+	switch_type_c_dr_mode(type_c, USB_DR_MODE_PERIPHERAL, cc);
+
+	writel(ENABLE_TYPE_C_DETECT | readl(reg), reg);
+	return 0;
+}
+
+static int host_disconnected(struct type_c_data *type_c, u32 cc)
+{
+	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
+
+	writel(~ENABLE_TYPE_C_DETECT & readl(reg), reg);
+
+	switch_type_c_dr_mode(type_c, 0, cc);
+
+	schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(DETECT_TIME));
+
+	return 0;
+}
+
+/* detect host device switch */
+static int __detect_host_device(struct type_c_data *type_c, u32 rp_or_rd_en)
+{
+	struct device *dev = type_c->dev;
+	void __iomem *reg_base = type_c->reg_base;
+	unsigned int gpio = type_c->rd_ctrl_gpio;
+	u32 cc1_config, cc2_config, default_ctrl;
+	u32 cc1_switch = 0;
+
+	default_ctrl = readl(reg_base + USB_TYPEC_CTRL) & DEBOUNCE_TIME_MASK;
+	writel(default_ctrl, reg_base + USB_TYPEC_CTRL);
+
+	cc1_config = readl(reg_base + USB_TYPEC_CTRL_CC1_0);
+	cc2_config = readl(reg_base + USB_TYPEC_CTRL_CC2_0);
+
+	cc1_config &= ~EN_CC_DET;
+	cc2_config &= ~EN_CC_DET;
+	writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
+	writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
+
+	if (soc_device_match(rtk_soc_kylin))
+		cc1_switch = cc1_config & CC_SWITCH_MASK;
+
+	cc1_config &= CC_CODE_MASK;
+	cc1_config |= rp_or_rd_en | cc1_switch;
+	cc2_config &= CC_CODE_MASK;
+	cc2_config |= rp_or_rd_en;
+	writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
+	writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
+
+	/* For kylin to disable external rd control gpio */
+	if (soc_device_match(rtk_soc_kylin)) {
+		if (gpio != -1 && gpio_is_valid(gpio)) {
+			if (gpio_direction_output(gpio, 1))
+				dev_err(dev, "%s ERROR rd_ctrl_gpio=1 fail\n", __func__);
+		}
+	}
+
+	cc1_config |= EN_CC_DET;
+	cc2_config |= EN_CC_DET;
+	writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
+	writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
+
+	return 0;
+}
+
+static int detect_device(struct type_c_data *type_c)
+{
+	return __detect_host_device(type_c, type_c->dfp_mode_rp_en);
+}
+
+static int detect_host(struct type_c_data *type_c)
+{
+	return __detect_host_device(type_c, type_c->ufp_mode_rd_en);
+}
+
+static int host_device_switch_detection(struct type_c_data *type_c)
+{
+	if (type_c->cc_mode == IN_HOST_MODE) {
+		type_c->cc_mode = IN_DEVICE_MODE;
+		detect_host(type_c);
+	} else {
+		type_c->cc_mode = IN_HOST_MODE;
+		detect_device(type_c);
+	}
+
+	return 0;
+}
+
+static int detect_type_c_state(struct type_c_data *type_c)
+{
+	struct device *dev = type_c->dev;
+	void __iomem *reg_base = type_c->reg_base;
+	u32 int_status, cc_status, cc_status_check;
+	unsigned long flags;
+
+	spin_lock_irqsave(&type_c->lock, flags);
+
+	int_status = readl(reg_base + USB_TYPEC_CTRL);
+	cc_status = readl(reg_base + USB_TYPEC_STS);
+
+	type_c->connect_change = CONNECT_NO_CHANGE;
+
+	switch (type_c->cc_mode | type_c->is_attach) {
+	case IN_HOST_MODE | IN_ATTACH:
+		if (((cc_status & CC1_DET_STS) == CC1_DET_STS) && type_c->at_cc1 == AT_CC1) {
+			dev_dbg(dev, "IN host mode and cc1 device detach (cc_status=0x%x)",
+				cc_status);
+			type_c->is_attach = TO_DETACH;
+			type_c->connect_change = CONNECT_CHANGE;
+		} else if (((cc_status & CC2_DET_STS) == CC2_DET_STS) &&
+			   type_c->at_cc1 == AT_CC2) {
+			dev_dbg(dev, "IN host mode and cc2 device detach (cc_status=0x%x)",
+				cc_status);
+			type_c->is_attach = TO_DETACH;
+			type_c->connect_change = CONNECT_CHANGE;
+		}
+		break;
+	case IN_HOST_MODE | IN_DETACH:
+		cc_status_check = readl(reg_base + USB_TYPEC_STS);
+		if (cc_status_check != (CC1_DET_STS | CC2_DET_STS)) {
+			if (in_interrupt()) {
+				mdelay(300);
+			} else {
+				spin_unlock_irqrestore(&type_c->lock, flags);
+				msleep(300);
+				spin_lock_irqsave(&type_c->lock, flags);
+			}
+			cc_status_check = readl(reg_base + USB_TYPEC_STS);
+		}
+		if (cc_status != cc_status_check) {
+			dev_warn(dev, "IN_HOST_MODE: cc_status (0x%x) != cc_status_check (0x%x)\n",
+				 cc_status, cc_status_check);
+			cc_status = readl(reg_base + USB_TYPEC_STS);
+		}
+
+		if ((cc_status & CC1_DET_STS) == CC1_DET_STS_RD) {
+			dev_dbg(dev, "IN host mode and cc1 device attach (cc_status=0x%x)",
+				cc_status);
+			type_c->is_attach = TO_ATTACH;
+			type_c->at_cc1 = AT_CC1;
+			type_c->connect_change = CONNECT_CHANGE;
+		} else if ((cc_status & CC2_DET_STS) == CC2_DET_STS_RD) {
+			dev_dbg(dev, "In host mode and cc2 device attach (cc_status=0x%x)",
+				cc_status);
+			type_c->is_attach = TO_ATTACH;
+			type_c->at_cc1 = AT_CC2;
+			type_c->connect_change = CONNECT_CHANGE;
+		}
+		break;
+	case IN_DEVICE_MODE | IN_ATTACH:
+		if ((cc_status & CC1_DET_STS) < CC1_DET_STS_RP ||
+		    (cc_status & CC2_DET_STS) < CC2_DET_STS_RP) {
+			/* Add a sw debounce to filter cc signal sent from apple pd adapter */
+			mdelay(5);
+			cc_status_check = readl(reg_base + USB_TYPEC_STS);
+
+			if (cc_status != cc_status_check) {
+				dev_dbg(dev, "IN_DEVICE_MODE: cc_status (0x%x) != cc_status_check (0x%x) maybe use a pd adapter\n",
+					cc_status, cc_status_check);
+				cc_status = cc_status_check;
+			}
+		}
+
+		if ((cc_status & CC1_DET_STS) < CC1_DET_STS_RP && type_c->at_cc1 == AT_CC1) {
+			dev_dbg(dev, "IN device mode and cc1 host disconnect (cc_status=0x%x)",
+				cc_status);
+			type_c->is_attach = TO_DETACH;
+			type_c->connect_change = CONNECT_CHANGE;
+		} else if ((cc_status & CC2_DET_STS) < CC2_DET_STS_RP &&
+			   type_c->at_cc1 == AT_CC2) {
+			dev_dbg(dev, "IN device mode and cc2 host disconnect (cc_status=0x%x)",
+				cc_status);
+			type_c->is_attach = TO_DETACH;
+			type_c->connect_change = CONNECT_CHANGE;
+		}
+		break;
+	case IN_DEVICE_MODE | IN_DETACH:
+		cc_status_check = readl(reg_base + USB_TYPEC_STS);
+		if (cc_status_check != 0x0) {
+			if (in_interrupt()) {
+				mdelay(300);
+			} else {
+				spin_unlock_irqrestore(&type_c->lock, flags);
+				msleep(300);
+				spin_lock_irqsave(&type_c->lock, flags);
+			}
+			cc_status_check = readl(reg_base + USB_TYPEC_STS);
+		}
+
+		if (cc_status != cc_status_check) {
+			dev_warn(dev, "IN_DEVICE_MODE: cc_status (0x%x) != cc_status_check (0x%x)\n",
+				 cc_status, cc_status_check);
+			cc_status = readl(reg_base + USB_TYPEC_STS);
+		}
+
+		if ((cc_status & CC1_DET_STS) >= CC1_DET_STS_RP) {
+			dev_dbg(dev, "IN device mode and cc1 host connect (cc_status=0x%x)",
+				cc_status);
+			type_c->at_cc1 = AT_CC1;
+			type_c->is_attach = TO_ATTACH;
+			type_c->connect_change = CONNECT_CHANGE;
+		} else if ((cc_status & CC2_DET_STS) >= CC2_DET_STS_RP) {
+			dev_dbg(dev, "IN device mode and cc2 host connect (cc_status=0x%x)",
+				cc_status);
+			type_c->at_cc1 = AT_CC2;
+			type_c->is_attach = TO_ATTACH;
+			type_c->connect_change = CONNECT_CHANGE;
+		}
+		break;
+	default:
+		dev_err(dev, "error host or device mode (cc_mode=%d, is_attach=%d) ",
+			type_c->cc_mode, type_c->is_attach);
+	}
+
+	type_c->int_status = int_status;
+	type_c->cc_status = cc_status;
+
+	spin_unlock_irqrestore(&type_c->lock, flags);
+	return 0;
+}
+
+static void host_device_switch(struct work_struct *work)
+{
+	struct type_c_data *type_c = container_of(work, struct type_c_data,
+						  delayed_work.work);
+	struct device *dev = type_c->dev;
+	unsigned long flags;
+	int connect_change = 0;
+	int cc_mode = 0;
+	int is_attach = 0;
+	int at_cc1 = 0;
+
+	spin_lock_irqsave(&type_c->lock, flags);
+	if (type_c->connect_change)
+		connect_change = type_c->connect_change;
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	if (!connect_change)
+		detect_type_c_state(type_c);
+
+	spin_lock_irqsave(&type_c->lock, flags);
+	if (type_c->connect_change) {
+		connect_change = type_c->connect_change;
+		cc_mode = type_c->cc_mode;
+		is_attach = type_c->is_attach;
+		at_cc1 = type_c->at_cc1;
+		type_c->connect_change = CONNECT_NO_CHANGE;
+	} else {
+		host_device_switch_detection(type_c);
+
+		schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(DETECT_TIME));
+	}
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	if (connect_change) {
+		dev_dbg(dev, "%s: usb cable connection change\n", __func__);
+		if (cc_mode == IN_HOST_MODE) {
+			if (is_attach && at_cc1)
+				device_attached(type_c, ENABLE_CC1);
+			else if (is_attach && !at_cc1)
+				device_attached(type_c, ENABLE_CC2);
+			else
+				device_detached(type_c, DISABLE_CC);
+		} else if (cc_mode == IN_DEVICE_MODE) {
+			if (is_attach && at_cc1)
+				host_connected(type_c, ENABLE_CC1);
+			else if (is_attach && !at_cc1)
+				host_connected(type_c, ENABLE_CC2);
+			else
+				host_disconnected(type_c, DISABLE_CC);
+		} else {
+			dev_err(dev, "Error: IN unknown mode %d to %s at %s (cc_status=0x%x)\n",
+				cc_mode, is_attach ? "attach" : "detach",
+				at_cc1 ? "cc1" : "cc2", type_c->cc_status);
+		}
+		dev_info(dev, "Connection change OK: IN %s mode to %s at %s (cc_status=0x%x)\n",
+			 cc_mode == IN_HOST_MODE ? "host" : "device",
+			 is_attach ? "attach" : "detach",
+			 at_cc1 ? "cc1" : "cc2", type_c->cc_status);
+	}
+}
+
+static irqreturn_t type_c_detect_irq(int irq, void *__data)
+{
+	struct type_c_data *type_c = (struct type_c_data *)__data;
+	struct device *dev = type_c->dev;
+	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
+	unsigned long flags;
+
+	detect_type_c_state(type_c);
+
+	spin_lock_irqsave(&type_c->lock, flags);
+
+	if (type_c->connect_change) {
+		dev_dbg(dev, "%s: IN %s mode to %s (at %s interrupt) int_status=0x%x, cc_status=0x%x",
+			__func__,
+			type_c->cc_mode == IN_HOST_MODE ? "host" : "device",
+			type_c->is_attach ? "attach" : "detach",
+			type_c->at_cc1 ? "cc1" : "cc2",
+			type_c->int_status, type_c->cc_status);
+
+		/* clear interrupt status */
+		writel(~ALL_CC_INT_STS & readl(reg), reg);
+
+		cancel_delayed_work(&type_c->delayed_work);
+		schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(0));
+	} else {
+		static int local_count;
+
+		if (local_count++ > 10) {
+			/* clear interrupt status */
+			writel(~ALL_CC_INT_STS & readl(reg), reg);
+			local_count = 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_TYPEC
+static int type_c_port_dr_set(struct typec_port *port,
+			      enum typec_data_role role)
+{
+	struct type_c_data *type_c = typec_get_drvdata(port);
+	u32 enable_cc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&type_c->lock, flags);
+	enable_cc = type_c->at_cc1 ? ENABLE_CC1 : ENABLE_CC2;
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	if (role == TYPEC_HOST)
+		switch_type_c_dr_mode(type_c, USB_DR_MODE_HOST, enable_cc);
+	else if (role == TYPEC_DEVICE)
+		switch_type_c_dr_mode(type_c, USB_DR_MODE_PERIPHERAL, enable_cc);
+	else
+		switch_type_c_dr_mode(type_c, 0, DISABLE_CC);
+
+	return 0;
+}
+
+static const struct typec_operations type_c_port_ops = {
+	.dr_set = type_c_port_dr_set,
+};
+#endif /* CONFIG_TYPEC */
+
+#ifdef CONFIG_DEBUG_FS
+static int type_c_parameter_show(struct seq_file *s, void *unused)
+{
+	struct type_c_data *type_c = s->private;
+	struct type_c_cfg *type_c_cfg = type_c->type_c_cfg;
+	struct cc_param *cc_param;
+	unsigned long flags;
+
+	spin_lock_irqsave(&type_c->lock, flags);
+
+	seq_printf(s, "cc_dfp_mode %s\n",
+		   ({ char *tmp;
+			switch (type_c_cfg->cc_dfp_mode) {
+			case CC_MODE_DFP_USB:
+				tmp = "CC_MODE_DFP_USB"; break;
+			case CC_MODE_DFP_1_5:
+				tmp = "CC_MODE_DFP_1_5"; break;
+			case CC_MODE_DFP_3_0:
+				tmp = "CC_MODE_DFP_3_0"; break;
+			default:
+				tmp = "?"; break;
+		   } tmp; }));
+
+	seq_printf(s, "dfp_mode_rp_en 0x%x\n", type_c->dfp_mode_rp_en);
+	seq_printf(s, "ufp_mode_rd_en 0x%x\n", type_c->ufp_mode_rd_en);
+	seq_printf(s, "cc1_code 0x%x\n", type_c->cc1_code);
+	seq_printf(s, "cc2_code 0x%x\n", type_c->cc2_code);
+	seq_printf(s, "cc1_vref 0x%x\n", type_c->cc1_vref);
+	seq_printf(s, "cc2_vref 0x%x\n", type_c->cc2_vref);
+	seq_printf(s, "debounce 0x%x\n", type_c->debounce);
+	seq_puts(s, "\n");
+
+	cc_param = &type_c_cfg->cc1_param;
+	seq_puts(s, "cc1_param:\n");
+	seq_printf(s, "  rp_4p7k_code 0x%x\n", cc_param->rp_4p7k_code);
+	seq_printf(s, "  rp_36k_code  0x%x\n", cc_param->rp_36k_code);
+	seq_printf(s, "  rp_12k_code  0x%x\n", cc_param->rp_12k_code);
+	seq_printf(s, "  rd_code      0x%x\n", cc_param->rd_code);
+	seq_printf(s, "  vref_2p6v    0x%x\n", cc_param->vref_2p6v);
+	seq_printf(s, "  vref_1p23v   0x%x\n", cc_param->vref_1p23v);
+	seq_printf(s, "  vref_0p8v    0x%x\n", cc_param->vref_0p8v);
+	seq_printf(s, "  vref_0p66v   0x%x\n", cc_param->vref_0p66v);
+	seq_printf(s, "  vref_0p4v    0x%x\n", cc_param->vref_0p4v);
+	seq_printf(s, "  vref_0p2v    0x%x\n", cc_param->vref_0p2v);
+	seq_printf(s, "  vref_1_1p6v  0x%x\n", cc_param->vref_1_1p6v);
+	seq_printf(s, "  vref_0_1p6v  0x%x\n", cc_param->vref_0_1p6v);
+
+	cc_param = &type_c_cfg->cc2_param;
+	seq_puts(s, "cc2_param:\n");
+	seq_printf(s, "  rp_4p7k_code 0x%x\n", cc_param->rp_4p7k_code);
+	seq_printf(s, "  rp_36k_code  0x%x\n", cc_param->rp_36k_code);
+	seq_printf(s, "  rp_12k_code  0x%x\n", cc_param->rp_12k_code);
+	seq_printf(s, "  rd_code      0x%x\n", cc_param->rd_code);
+	seq_printf(s, "  vref_2p6v    0x%x\n", cc_param->vref_2p6v);
+	seq_printf(s, "  vref_1p23v   0x%x\n", cc_param->vref_1p23v);
+	seq_printf(s, "  vref_0p8v    0x%x\n", cc_param->vref_0p8v);
+	seq_printf(s, "  vref_0p66v   0x%x\n", cc_param->vref_0p66v);
+	seq_printf(s, "  vref_0p4v    0x%x\n", cc_param->vref_0p4v);
+	seq_printf(s, "  vref_0p2v    0x%x\n", cc_param->vref_0p2v);
+	seq_printf(s, "  vref_1_1p6v  0x%x\n", cc_param->vref_1_1p6v);
+	seq_printf(s, "  vref_0_1p6v  0x%x\n", cc_param->vref_0_1p6v);
+
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	return 0;
+}
+
+static int type_c_parameter_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, type_c_parameter_show, inode->i_private);
+}
+
+static const struct file_operations type_c_parameter_fops = {
+	.open			= type_c_parameter_open,
+	.read			= seq_read,
+	.llseek			= seq_lseek,
+	.release		= single_release,
+};
+
+static int type_c_status_show(struct seq_file *s, void *unused)
+{
+	struct type_c_data *type_c = s->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&type_c->lock, flags);
+
+	seq_printf(s, "In %s mode %s at %s (cc_status=0x%x)\n",
+		   type_c->cc_mode == IN_HOST_MODE ? "host" : "device",
+		   type_c->is_attach ? "attach" : "detach",
+		   type_c->at_cc1 ? "cc1" : "cc2", type_c->cc_status);
+
+	seq_printf(s, "Read Register (type_c_ctrl_cc1_0=0x%x)\n",
+		   readl(type_c->reg_base + 0x0));
+	seq_printf(s, "Read Register (type_c_ctrl_cc1_1=0x%x)\n",
+		   readl(type_c->reg_base + 0x4));
+	seq_printf(s, "Read Register (type_c_ctrl_cc2_0=0x%x)\n",
+		   readl(type_c->reg_base + 0x8));
+	seq_printf(s, "Read Register (type_c_ctrl_cc2_1=0x%x)\n",
+		   readl(type_c->reg_base + 0xc));
+	seq_printf(s, "Read Register (type_c_status=0x%x)\n",
+		   readl(type_c->reg_base + 0x10));
+	seq_printf(s, "Read Register (type_c_ctrl=0x%x)\n",
+		   readl(type_c->reg_base + 0x14));
+
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	return 0;
+}
+
+static int type_c_status_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, type_c_status_show, inode->i_private);
+}
+
+static const struct file_operations type_c_status_fops = {
+	.open			= type_c_status_open,
+	.read			= seq_read,
+	.llseek			= seq_lseek,
+	.release		= single_release,
+};
+
+static inline void create_debug_files(struct type_c_data *type_c)
+{
+	type_c->debug_dir = debugfs_create_dir("type_c", usb_debug_root);
+	if (!type_c->debug_dir)
+		return;
+
+	if (!debugfs_create_file("parameter", 0444, type_c->debug_dir, type_c,
+				 &type_c_parameter_fops))
+		goto file_error;
+
+	if (!debugfs_create_file("status", 0444, type_c->debug_dir, type_c,
+				 &type_c_status_fops))
+		goto file_error;
+
+	return;
+
+file_error:
+	debugfs_remove_recursive(type_c->debug_dir);
+}
+
+static inline void remove_debug_files(struct type_c_data *type_c)
+{
+	debugfs_remove_recursive(type_c->debug_dir);
+}
+#else
+static inline void create_debug_files(struct type_c_data *type_c) { }
+static inline void remove_debug_files(struct type_c_data *type_c) { }
+#endif /* CONFIG_DEBUG_FS */
+
+/* Init and probe */
+
+static inline s8 get_value(s8 value)
+{
+	return (((s8)value & 0x8) ? (-(s8)(0x7 & value)) : ((s8)(value)));
+}
+
+static int __updated_type_c_parameter_by_efuse(struct type_c_data *type_c)
+{
+	struct type_c_cfg *type_c_cfg = type_c->type_c_cfg;
+	struct cc_param *cc_param;
+	struct nvmem_cell *cell;
+	s8 cc1_4p7k = 0;
+	s8 cc1_12k = 0;
+	s8 cc1_0p2v = 0;
+	s8 cc1_0p8v = 0;
+	s8 cc1_2p6v = 0;
+	s8 cc1_0p66v = 0;
+	s8 cc1_1p23v = 0;
+	s8 cc2_4p7k = 0;
+	s8 cc2_12k = 0;
+	s8 cc2_0p2v = 0;
+	s8 cc2_0p8v = 0;
+	s8 cc2_2p6v = 0;
+	s8 cc2_0p66v = 0;
+	s8 cc2_1p23v = 0;
+
+	cell = nvmem_cell_get(type_c->dev, "usb-cal");
+	if (IS_ERR(cell)) {
+		dev_warn(type_c->dev, "%s failed to get usb-cal: %ld\n",
+			 __func__, PTR_ERR(cell));
+	} else {
+		unsigned char *buf;
+		size_t buf_size;
+		int value_size = 4;
+		int value_mask = (BIT(value_size) - 1);
+
+		buf = nvmem_cell_read(cell, &buf_size);
+
+		cc1_0p2v = get_value((buf[0] >> value_size * 0) & value_mask);
+		cc1_0p8v = get_value((buf[0] >> value_size * 1) & value_mask);
+		cc1_2p6v = get_value((buf[1] >> value_size * 0) & value_mask);
+		cc1_0p66v = get_value((buf[1] >> value_size * 1) & value_mask);
+		cc1_1p23v = get_value((buf[2] >> value_size * 0) & value_mask);
+
+		cc2_0p2v = get_value((buf[3] >> value_size * 0) & value_mask);
+		cc2_0p8v = get_value((buf[3] >> value_size * 1) & value_mask);
+		cc2_2p6v = get_value((buf[4] >> value_size * 0) & value_mask);
+		cc2_0p66v = get_value((buf[4] >> value_size * 1) & value_mask);
+		cc2_1p23v = get_value((buf[5] >> value_size * 0) & value_mask);
+
+		cc1_4p7k = get_value((buf[6] >> value_size * 0) & value_mask);
+		cc1_12k = get_value((buf[6] >> value_size * 1) & value_mask);
+		cc2_4p7k = get_value((buf[7] >> value_size * 0) & value_mask);
+		cc2_12k = get_value((buf[7] >> value_size * 1) & value_mask);
+
+		kfree(buf);
+		nvmem_cell_put(cell);
+	}
+
+	dev_dbg(type_c->dev, "check efuse cc1_4p7k=%d cc1_12k=%d cc2_4p7k=%d cc2_12k=%d\n",
+		cc1_4p7k, cc1_12k, cc2_4p7k, cc2_12k);
+	dev_dbg(type_c->dev, "check efuse cc1_0p2v=%d cc1_0p8v=%d cc1_2p6v=%d cc1_0p66v=%d cc1_1p23v=%d\n",
+		cc1_0p2v, cc1_0p8v, cc1_2p6v, cc1_0p66v, cc1_1p23v);
+	dev_dbg(type_c->dev, "check efuse cc2_0p2v=%d cc2_0p8v=%d cc2_2p6v=%d cc2_0p66v=%d cc2_1p23v=%d\n",
+		cc2_0p2v, cc2_0p8v, cc2_2p6v, cc2_0p66v, cc2_1p23v);
+
+	cc_param = &type_c_cfg->cc1_param;
+	cc_param->rp_4p7k_code = cc_param->rp_4p7k_code + cc1_4p7k;
+	cc_param->rp_12k_code = cc_param->rp_12k_code + cc1_12k;
+
+	cc_param->vref_1p23v = cc_param->vref_1p23v + cc1_1p23v;
+	cc_param->vref_0p66v = cc_param->vref_0p66v + cc1_0p66v;
+	cc_param->vref_2p6v = cc_param->vref_2p6v + cc1_2p6v;
+	cc_param->vref_0p8v = cc_param->vref_0p8v + cc1_0p8v;
+	cc_param->vref_0p2v = cc_param->vref_0p2v + cc1_0p2v;
+
+	cc_param = &type_c_cfg->cc2_param;
+	cc_param->rp_4p7k_code = cc_param->rp_4p7k_code + cc2_4p7k;
+	cc_param->rp_12k_code = cc_param->rp_12k_code + cc2_12k;
+
+	cc_param->vref_1p23v = cc_param->vref_1p23v + cc2_1p23v;
+	cc_param->vref_0p66v = cc_param->vref_0p66v + cc2_0p66v;
+	cc_param->vref_2p6v = cc_param->vref_2p6v + cc2_2p6v;
+	cc_param->vref_0p8v = cc_param->vref_0p8v + cc2_0p8v;
+	cc_param->vref_0p2v = cc_param->vref_0p2v + cc2_0p2v;
+
+	return 0;
+}
+
+static int __updated_type_c_parameter_by_efuse_v2(struct type_c_data *type_c)
+{
+	struct type_c_cfg *type_c_cfg = type_c->type_c_cfg;
+	struct cc_param *cc_param;
+	struct nvmem_cell *cell;
+	s8 cc1_4p7k = 0;
+	s8 cc1_12k = 0;
+	s8 cc1_0p2v = 0;
+	s8 cc1_0p8v = 0;
+	s8 cc1_2p6v = 0;
+	s8 cc1_0p66v = 0;
+	s8 cc1_1p23v = 0;
+	s8 cc2_4p7k = 0;
+	s8 cc2_12k = 0;
+	s8 cc2_0p2v = 0;
+	s8 cc2_0p8v = 0;
+	s8 cc2_2p6v = 0;
+	s8 cc2_0p66v = 0;
+	s8 cc2_1p23v = 0;
+
+	cell = nvmem_cell_get(type_c->dev, "usb-type-c-cal");
+	if (IS_ERR(cell)) {
+		dev_warn(type_c->dev, "%s failed to get usb-type-c-cal: %ld\n",
+			 __func__, PTR_ERR(cell));
+	} else {
+		unsigned char *buf;
+		size_t buf_size;
+		int value_size = 0;
+		int value_mask = (BIT(value_size) - 1);
+
+		buf = nvmem_cell_read(cell, &buf_size);
+
+		value_size = 5;
+		value_mask = (BIT(value_size) - 1);
+		cc1_4p7k = buf[0] & value_mask;
+		cc1_12k = buf[1] & value_mask;
+		cc2_4p7k = buf[2] & value_mask;
+		cc2_12k = buf[3] & value_mask;
+
+		value_size = 4;
+		value_mask = (BIT(value_size) - 1);
+		cc1_0p2v = (buf[4] >> value_size * 0) & value_mask;
+		cc1_0p66v = (buf[4] >> value_size * 1) & value_mask;
+		cc1_0p8v = (buf[5] >> value_size * 0) & value_mask;
+		cc1_1p23v = (buf[5] >> value_size * 1) & value_mask;
+		cc1_2p6v = (buf[6] >> value_size * 0) & value_mask;
+
+		cc2_0p2v = (buf[6] >> value_size * 1) & value_mask;
+		cc2_0p66v = (buf[7] >> value_size * 0) & value_mask;
+		cc2_0p8v = (buf[7] >> value_size * 1) & value_mask;
+		cc2_1p23v = (buf[8] >> value_size * 0) & value_mask;
+		cc2_2p6v = (buf[8] >> value_size * 1) & value_mask;
+
+		kfree(buf);
+		nvmem_cell_put(cell);
+	}
+
+	dev_dbg(type_c->dev, "check efuse v2 cc1_4p7k=%d cc1_12k=%d cc2_4p7k=%d cc2_12k=%d\n",
+		cc1_4p7k, cc1_12k, cc2_4p7k, cc2_12k);
+	dev_dbg(type_c->dev, "check efuse v2 cc1_0p2v=%d cc1_0p8v=%d cc1_2p6v=%d cc1_0p66v=%d cc1_1p23v=%d\n",
+		cc1_0p2v, cc1_0p8v, cc1_2p6v, cc1_0p66v, cc1_1p23v);
+	dev_dbg(type_c->dev, "check efuse v2 cc2_0p2v=%d cc2_0p8v=%d cc2_2p6v=%d cc2_0p66v=%d cc2_1p23v=%d\n",
+		cc2_0p2v, cc2_0p8v, cc2_2p6v, cc2_0p66v, cc2_1p23v);
+
+	cc_param = &type_c_cfg->cc1_param;
+	if (cc1_4p7k)
+		cc_param->rp_4p7k_code = cc1_4p7k;
+	if (cc1_12k)
+		cc_param->rp_12k_code = cc1_12k;
+
+	if (cc1_1p23v)
+		cc_param->vref_1p23v = cc1_1p23v;
+	if (cc1_0p66v)
+		cc_param->vref_0p66v = cc1_0p66v;
+	if (cc1_2p6v)
+		cc_param->vref_2p6v = cc1_2p6v;
+	if (cc1_0p8v)
+		cc_param->vref_0p8v = cc1_0p8v;
+	if (cc1_0p2v)
+		cc_param->vref_0p2v = cc1_0p2v;
+
+	cc_param = &type_c_cfg->cc2_param;
+	if (cc2_4p7k)
+		cc_param->rp_4p7k_code = cc2_4p7k;
+	if (cc2_12k)
+		cc_param->rp_12k_code = cc2_12k;
+
+	if (cc2_1p23v)
+		cc_param->vref_1p23v = cc2_1p23v;
+	if (cc2_0p66v)
+		cc_param->vref_0p66v = cc2_0p66v;
+	if (cc2_2p6v)
+		cc_param->vref_2p6v = cc2_2p6v;
+	if (cc2_0p8v)
+		cc_param->vref_0p8v = cc2_0p8v;
+	if (cc2_0p2v)
+		cc_param->vref_0p2v = cc2_0p2v;
+
+	return 0;
+}
+
+static void get_default_type_c_parameter(struct type_c_data *type_c)
+{
+	void __iomem *reg;
+	int val;
+
+	type_c->dfp_mode_rp_en = dfp_mode(CC_MODE_DFP_3_0) | EN_RP4P7K;
+	type_c->ufp_mode_rd_en = EN_RD;
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
+	val = readl(reg);
+	type_c->cc1_code = CC_CODE_MASK & val;
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_0;
+	val = readl(reg);
+	type_c->cc2_code = CC_CODE_MASK & val;
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_1;
+	val = readl(reg);
+	type_c->cc1_vref = val;
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_1;
+	val = readl(reg);
+	type_c->cc2_vref = val;
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL;
+	val = readl(reg);
+	type_c->debounce = DEBOUNCE_TIME_MASK & val;
+}
+
+static int setup_type_c_parameter(struct type_c_data *type_c)
+{
+	struct type_c_cfg *type_c_cfg = type_c->type_c_cfg;
+	struct cc_param *cc_param;
+	struct soc_device_attribute rtk_soc_efuse_v1[] = {
+			{ .family = "Realtek Phoenix",},
+			{ .family = "Realtek Kylin",},
+			{ .family = "Realtek Hercules",},
+			{ .family = "Realtek Thor",},
+			{ .family = "Realtek Hank",},
+			{ .family = "Realtek Groot",},
+			{ .family = "Realtek Stark",},
+			{ .family = "Realtek Parker",},
+			{ /* empty */ }
+		};
+
+	if (type_c_cfg->use_defalut_parameter) {
+		get_default_type_c_parameter(type_c);
+		return 0;
+	}
+
+	if (soc_device_match(rtk_soc_efuse_v1))
+		__updated_type_c_parameter_by_efuse(type_c);
+	else
+		__updated_type_c_parameter_by_efuse_v2(type_c);
+
+	/*
+	 * UFP     rd     vref_ufp    : 1p23v,  0p66v, 0p2v
+	 * DFP_USB rp36k  vref_dfp_usb: 0_1p6v, 0p2v,  unused
+	 * DFP_1.5 rp12k  vref_dfp_1_5: 1_1p6v, 0p4v,  0p2v
+	 * DFP_3.0 rp4p7k vref_dfp_3_0: 2p6v,   0p8v,  0p2v
+	 */
+
+	switch (type_c_cfg->cc_dfp_mode) {
+	case CC_MODE_DFP_USB:
+		type_c->dfp_mode_rp_en = dfp_mode(CC_MODE_DFP_USB) | EN_RP36K;
+		break;
+	case CC_MODE_DFP_1_5:
+		type_c->dfp_mode_rp_en = dfp_mode(CC_MODE_DFP_1_5) | EN_RP12K;
+		break;
+	case CC_MODE_DFP_3_0:
+		type_c->dfp_mode_rp_en = dfp_mode(CC_MODE_DFP_3_0) | EN_RP4P7K;
+		break;
+	default:
+		dev_err(type_c->dev, "%s: unknown cc_dfp_mode %d\n",
+			__func__, type_c_cfg->cc_dfp_mode);
+	}
+
+	type_c->ufp_mode_rd_en = EN_RD;
+
+	cc_param = &type_c_cfg->cc1_param;
+	type_c->cc1_code = rp4pk_code(cc_param->rp_4p7k_code) |
+			   rp36k_code(cc_param->rp_36k_code) |
+			   rp12k_code(cc_param->rp_12k_code) |
+			   rd_code(cc_param->rd_code);
+
+	if (type_c_cfg->parameter_ver == PARAMETER_V0)
+		type_c->cc1_vref = V0_vref_2p6v(cc_param->vref_2p6v) |
+				   V0_vref_1p23v(cc_param->vref_1p23v) |
+				   V0_vref_0p8v(cc_param->vref_0p8v) |
+				   V0_vref_0p66v(cc_param->vref_0p66v) |
+				   V0_vref_0p4v(cc_param->vref_0p4v) |
+				   V0_vref_0p2v(cc_param->vref_0p2v) |
+				   V0_vref_1_1p6v(cc_param->vref_1_1p6v) |
+				   V0_vref_0_1p6v(cc_param->vref_0_1p6v);
+	else if (type_c_cfg->parameter_ver == PARAMETER_V1)
+		type_c->cc1_vref = V1_vref_2p6v(cc_param->vref_2p6v) |
+				   V1_vref_1p23v(cc_param->vref_1p23v) |
+				   V1_vref_0p8v(cc_param->vref_0p8v) |
+				   V1_vref_0p66v(cc_param->vref_0p66v) |
+				   V1_vref_0p4v(cc_param->vref_0p4v) |
+				   V1_vref_0p2v(cc_param->vref_0p2v) |
+				   V1_vref_1_1p6v(cc_param->vref_1_1p6v) |
+				   V1_vref_0_1p6v(cc_param->vref_0_1p6v);
+	else
+		dev_err(type_c->dev, "%s: unknown parameter_ver %d\n",
+			__func__, type_c_cfg->parameter_ver);
+
+	cc_param = &type_c_cfg->cc2_param;
+	type_c->cc2_code = rp4pk_code(cc_param->rp_4p7k_code)
+			 | rp36k_code(cc_param->rp_36k_code)
+			 | rp12k_code(cc_param->rp_12k_code)
+			 | rd_code(cc_param->rd_code);
+
+	if (type_c_cfg->parameter_ver == PARAMETER_V0)
+		type_c->cc2_vref = V0_vref_2p6v(cc_param->vref_2p6v) |
+				   V0_vref_1p23v(cc_param->vref_1p23v) |
+				   V0_vref_0p8v(cc_param->vref_0p8v) |
+				   V0_vref_0p66v(cc_param->vref_0p66v) |
+				   V0_vref_0p4v(cc_param->vref_0p4v) |
+				   V0_vref_0p2v(cc_param->vref_0p2v) |
+				   V0_vref_1_1p6v(cc_param->vref_1_1p6v) |
+				   V0_vref_0_1p6v(cc_param->vref_0_1p6v);
+	else if (type_c_cfg->parameter_ver == PARAMETER_V1)
+		type_c->cc2_vref = V1_vref_2p6v(cc_param->vref_2p6v) |
+				   V1_vref_1p23v(cc_param->vref_1p23v) |
+				   V1_vref_0p8v(cc_param->vref_0p8v) |
+				   V1_vref_0p66v(cc_param->vref_0p66v) |
+				   V1_vref_0p4v(cc_param->vref_0p4v) |
+				   V1_vref_0p2v(cc_param->vref_0p2v) |
+				   V1_vref_1_1p6v(cc_param->vref_1_1p6v) |
+				   V1_vref_0_1p6v(cc_param->vref_0_1p6v);
+	else
+		dev_err(type_c->dev, "%s: unknown parameter_ver %d\n",
+			__func__, type_c_cfg->parameter_ver);
+
+	type_c->debounce = (type_c_cfg->debounce_val << 1) | DEBOUNCE_EN;
+
+	return 0;
+}
+
+static int extcon_rtk_type_c_init(struct type_c_data *type_c)
+{
+	struct device *dev = type_c->dev;
+	unsigned long flags;
+	void __iomem *reg;
+	int val;
+
+	if ((type_c->rd_ctrl_gpio != -1) &&
+	    gpio_request(type_c->rd_ctrl_gpio, dev->of_node->name))
+		dev_err(dev, "%s ERROR Request rd_ctrl_gpio  (id=%d) fail\n",
+			__func__, type_c->rd_ctrl_gpio);
+
+	spin_lock_irqsave(&type_c->lock, flags);
+
+	/* set parameter */
+	reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
+	val = readl(reg);
+	val = (~CC_CODE_MASK & val) | (type_c->cc1_code & CC_CODE_MASK);
+	writel(val, reg);
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_0;
+	val = readl(reg);
+	val = (~CC_CODE_MASK & val) | (type_c->cc2_code & CC_CODE_MASK);
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_1;
+	writel(type_c->cc1_vref, reg);
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_1;
+	writel(type_c->cc2_vref, reg);
+
+	reg = type_c->reg_base + USB_TYPEC_CTRL;
+	val = readl(reg);
+	val = (~DEBOUNCE_TIME_MASK & val) | (type_c->debounce & DEBOUNCE_TIME_MASK);
+
+	dev_info(dev, "First check USB_DR_MODE_PERIPHERAL");
+	type_c->cc_mode = IN_DEVICE_MODE;
+	type_c->is_attach = IN_DETACH;
+	type_c->connect_change = CONNECT_NO_CHANGE;
+
+	detect_host(type_c);
+
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(0));
+
+#ifdef CONFIG_TYPEC
+	if (!type_c->port) {
+		struct typec_capability typec_cap = { };
+
+		typec_cap.revision = USB_TYPEC_REV_1_0;
+		typec_cap.pd_revision = 0x200;
+		typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE;
+		typec_cap.driver_data = type_c;
+		typec_cap.ops = &type_c_port_ops;
+
+		typec_cap.type = TYPEC_PORT_DRP;
+		typec_cap.data = TYPEC_PORT_DRD;
+
+		type_c->port = typec_register_port(type_c->dev, &typec_cap);
+		if (IS_ERR(type_c->port))
+			return PTR_ERR(type_c->port);
+	}
+#endif /* CONFIG_TYPEC */
+
+	return 0;
+}
+
+static int extcon_rtk_type_c_edev_register(struct type_c_data *type_c)
+{
+	struct device *dev = type_c->dev;
+	int ret = 0;
+
+	type_c->edev = devm_extcon_dev_allocate(dev, usb_type_c_cable);
+	if (IS_ERR(type_c->edev)) {
+		dev_err(dev, "failed to allocate extcon device\n");
+		return -ENOMEM;
+	}
+
+	ret = devm_extcon_dev_register(dev, type_c->edev);
+	if (ret < 0) {
+		dev_err(dev, "failed to register extcon device\n");
+		return ret;
+	}
+
+	extcon_set_property_capability(type_c->edev, EXTCON_USB,
+				       EXTCON_PROP_USB_VBUS);
+	extcon_set_property_capability(type_c->edev, EXTCON_USB,
+				       EXTCON_PROP_USB_TYPEC_POLARITY);
+	extcon_set_property_capability(type_c->edev, EXTCON_USB,
+				       EXTCON_PROP_USB_SS);
+
+	extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
+				       EXTCON_PROP_USB_VBUS);
+	extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
+				       EXTCON_PROP_USB_TYPEC_POLARITY);
+	extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
+				       EXTCON_PROP_USB_SS);
+
+	return ret;
+}
+
+static int extcon_rtk_type_c_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct type_c_data *type_c;
+	const struct type_c_cfg *type_c_cfg;
+	unsigned int gpio;
+	int ret = 0;
+
+	type_c = devm_kzalloc(dev, sizeof(*type_c), GFP_KERNEL);
+	if (!type_c)
+		return -ENOMEM;
+
+	type_c->reg_base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(type_c->reg_base))
+		return PTR_ERR(type_c->reg_base);
+
+	type_c->dev = dev;
+
+	type_c->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	if (type_c->irq <= 0) {
+		dev_err(&pdev->dev, "Type C driver with no IRQ. Check %s setup!\n",
+			dev_name(&pdev->dev));
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	ret = devm_request_irq(dev, type_c->irq, type_c_detect_irq,
+			       IRQF_SHARED, "type_c_detect", type_c);
+
+	spin_lock_init(&type_c->lock);
+
+	type_c->rd_ctrl_gpio = -1;
+	if (soc_device_match(rtk_soc_kylin)) {
+		gpio = of_get_named_gpio(dev->of_node, "realtek,rd-ctrl-gpio", 0);
+		if (gpio_is_valid(gpio)) {
+			type_c->rd_ctrl_gpio = gpio;
+			dev_dbg(dev, "%s get rd-ctrl-gpio (id=%d) OK\n", __func__, gpio);
+		} else {
+			dev_err(dev, "Error rd_ctrl-gpio no found");
+		}
+	}
+
+	type_c_cfg = of_device_get_match_data(dev);
+	if (!type_c_cfg) {
+		dev_err(dev, "type_c config are not assigned!\n");
+		return -EINVAL;
+	}
+
+	type_c->type_c_cfg = devm_kzalloc(dev, sizeof(*type_c_cfg), GFP_KERNEL);
+
+	memcpy(type_c->type_c_cfg, type_c_cfg, sizeof(*type_c_cfg));
+
+	if (setup_type_c_parameter(type_c)) {
+		dev_err(dev, "ERROR: %s to setup type c parameter!!", __func__);
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	INIT_DELAYED_WORK(&type_c->delayed_work, host_device_switch);
+
+	ret = extcon_rtk_type_c_init(type_c);
+	if (ret) {
+		dev_err(dev, "%s failed to init type_c\n", __func__);
+		goto err1;
+	}
+
+	platform_set_drvdata(pdev, type_c);
+
+	ret = extcon_rtk_type_c_edev_register(type_c);
+
+	create_debug_files(type_c);
+
+	return 0;
+
+err1:
+	dev_err(&pdev->dev, "%s: Probe fail, %d\n", __func__, ret);
+
+	return ret;
+}
+
+static void extcon_rtk_type_c_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct type_c_data *type_c = dev_get_drvdata(dev);
+	u32 default_ctrl;
+	unsigned long flags;
+
+	remove_debug_files(type_c);
+
+#ifdef CONFIG_TYPEC
+	if (type_c->port) {
+		typec_unregister_port(type_c->port);
+		type_c->port = NULL;
+	}
+#endif
+
+	cancel_delayed_work_sync(&type_c->delayed_work);
+	flush_delayed_work(&type_c->delayed_work);
+	WARN_ON_ONCE(delayed_work_pending(&type_c->delayed_work));
+
+	spin_lock_irqsave(&type_c->lock, flags);
+	/* disable interrupt */
+	default_ctrl = readl(type_c->reg_base + USB_TYPEC_CTRL) &
+		    DEBOUNCE_TIME_MASK;
+	writel(default_ctrl, type_c->reg_base + USB_TYPEC_CTRL);
+
+	/* disable cc detect, rp, rd */
+	writel(PLR_EN, type_c->reg_base + USB_TYPEC_CTRL_CC1_0);
+	writel(0, type_c->reg_base + USB_TYPEC_CTRL_CC2_0);
+
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	free_irq(type_c->irq, type_c);
+}
+
+static const struct type_c_cfg rtd1295_type_c_cfg = {
+	.parameter_ver = PARAMETER_V0,
+	.cc_dfp_mode = CC_MODE_DFP_3_0,
+	.cc1_param = { .rp_4p7k_code = 0xb,
+		       .rp_36k_code = 0x17,
+		       .rp_12k_code = 0x10,
+		       .rd_code = 0,
+		       .ra_code = 0,
+		       .vref_2p6v = 0x0,
+		       .vref_1p23v = 0x0,
+		       .vref_0p8v = 0x3,
+		       .vref_0p66v = 0x0,
+		       .vref_0p4v = 0x0,
+		       .vref_0p2v = 0x4,
+		       .vref_1_1p6v = 0,
+		       .vref_0_1p6v = 0 },
+	.cc2_param = { .rp_4p7k_code = 0xc,
+		       .rp_36k_code = 0x17,
+		       .rp_12k_code = 0x12,
+		       .rd_code = 0,
+		       .ra_code = 0,
+		       .vref_2p6v = 0x2,
+		       .vref_1p23v = 0x0,
+		       .vref_0p8v = 0x3,
+		       .vref_0p66v = 0x0,
+		       .vref_0p4v = 0x0,
+		       .vref_0p2v = 0x5,
+		       .vref_1_1p6v = 0,
+		       .vref_0_1p6v = 0 },
+	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+	.use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1395_type_c_cfg = {
+	.parameter_ver = PARAMETER_V0,
+	.cc_dfp_mode = CC_MODE_DFP_3_0,
+	.cc1_param = { .rp_4p7k_code = 0xc,
+		       .rp_36k_code = 0xb,
+		       .rp_12k_code = 0xe,
+		       .rd_code = 0x10,
+		       .ra_code = 0x0,
+		       .vref_2p6v = 0x0,
+		       .vref_1p23v = 0x1,
+		       .vref_0p8v = 0x0,
+		       .vref_0p66v = 0x0,
+		       .vref_0p4v = 0x3,
+		       .vref_0p2v = 0x0,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.cc2_param = { .rp_4p7k_code = 0xb,
+		       .rp_36k_code = 0x9,
+		       .rp_12k_code = 0xe,
+		       .rd_code = 0xf,
+		       .ra_code = 0x0,
+		       .vref_2p6v = 0x1,
+		       .vref_1p23v = 0x3,
+		       .vref_0p8v = 0x3,
+		       .vref_0p66v = 0x2,
+		       .vref_0p4v = 0x3,
+		       .vref_0p2v = 0x2,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+	.use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1619_type_c_cfg = {
+	.parameter_ver = PARAMETER_V0,
+	.cc_dfp_mode = CC_MODE_DFP_3_0,
+	.cc1_param = { .rp_4p7k_code = 0xc,
+		       .rp_36k_code = 0xf,
+		       .rp_12k_code = 0xe,
+		       .rd_code = 0x11,
+		       .ra_code = 0x0,
+		       .vref_2p6v = 0x5,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0xa,
+		       .vref_0p66v = 0xa,
+		       .vref_0p4v = 0x3,
+		       .vref_0p2v = 0x2,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.cc2_param = { .rp_4p7k_code = 0xc,
+		       .rp_36k_code = 0xf,
+		       .rp_12k_code = 0xe,
+		       .rd_code = 0xf,
+		       .ra_code = 0x0,
+		       .vref_2p6v = 0x5,
+		       .vref_1p23v = 0x8,
+		       .vref_0p8v = 0xa,
+		       .vref_0p66v = 0xa,
+		       .vref_0p4v = 0x3,
+		       .vref_0p2v = 0x2,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+	.use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1319_type_c_cfg = {
+	.parameter_ver = PARAMETER_V0,
+	.cc_dfp_mode = CC_MODE_DFP_1_5,
+	.cc1_param = { .rp_4p7k_code = 0x9,
+		       .rp_36k_code = 0xe,
+		       .rp_12k_code = 0x9,
+		       .rd_code = 0x9,
+		       .ra_code = 0x7,
+		       .vref_2p6v = 0x3,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x7,
+		       .vref_0p66v = 0x6,
+		       .vref_0p4v = 0x2,
+		       .vref_0p2v = 0x3,
+		       .vref_1_1p6v = 0x4,
+		       .vref_0_1p6v = 0x7 },
+	.cc2_param = { .rp_4p7k_code = 0x8,
+		       .rp_36k_code = 0xe,
+		       .rp_12k_code = 0x9,
+		       .rd_code = 0x9,
+		       .ra_code = 0x7,
+		       .vref_2p6v = 0x3,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x7,
+		       .vref_0p66v = 0x6,
+		       .vref_0p4v = 0x3,
+		       .vref_0p2v = 0x3,
+		       .vref_1_1p6v = 0x6,
+		       .vref_0_1p6v = 0x7 },
+	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+	.use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1312c_type_c_cfg = {
+	.parameter_ver = PARAMETER_V0,
+	.cc_dfp_mode = CC_MODE_DFP_1_5,
+	.cc1_param = { .rp_4p7k_code = 0xe,
+		       .rp_36k_code = 0xc,
+		       .rp_12k_code = 0xc,
+		       .rd_code = 0xa,
+		       .ra_code = 0x3,
+		       .vref_2p6v = 0xa,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x7,
+		       .vref_0p66v = 0x7,
+		       .vref_0p4v = 0x4,
+		       .vref_0p2v = 0x4,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.cc2_param = { .rp_4p7k_code = 0xe,
+		       .rp_36k_code = 0xc,
+		       .rp_12k_code = 0xc,
+		       .rd_code = 0xa,
+		       .ra_code = 0x3,
+		       .vref_2p6v = 0xa,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x7,
+		       .vref_0p66v = 0x7,
+		       .vref_0p4v = 0x4,
+		       .vref_0p2v = 0x4,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+	.use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1619b_type_c_cfg = {
+	.parameter_ver = PARAMETER_V1,
+	.cc_dfp_mode = CC_MODE_DFP_1_5,
+	.cc1_param = { .rp_4p7k_code = 0xf,
+		       .rp_36k_code = 0xf,
+		       .rp_12k_code = 0xf,
+		       .rd_code = 0xf,
+		       .ra_code = 0x7,
+		       .vref_2p6v = 0x9,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x9,
+		       .vref_0p66v = 0x8,
+		       .vref_0p4v = 0x7,
+		       .vref_0p2v = 0x9,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.cc2_param = { .rp_4p7k_code = 0xf,
+		       .rp_36k_code = 0xf,
+		       .rp_12k_code = 0xf,
+		       .rd_code = 0xf,
+		       .ra_code = 0x7,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x9,
+		       .vref_0p66v = 0x8,
+		       .vref_0p4v = 0x7,
+		       .vref_0p2v = 0x8,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+	.use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1319d_type_c_cfg = {
+	.parameter_ver = PARAMETER_V1,
+	.cc_dfp_mode = CC_MODE_DFP_1_5,
+	.cc1_param = { .rp_4p7k_code = 0xe,
+		       .rp_36k_code = 0x3,
+		       .rp_12k_code = 0xe,
+		       .rd_code = 0xf,
+		       .ra_code = 0x6,
+		       .vref_2p6v = 0x7,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x8,
+		       .vref_0p66v = 0x7,
+		       .vref_0p4v = 0x7,
+		       .vref_0p2v = 0x7,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.cc2_param = { .rp_4p7k_code = 0xe,
+		       .rp_36k_code = 0x3,
+		       .rp_12k_code = 0xe,
+		       .rd_code = 0xf,
+		       .ra_code = 0x6,
+		       .vref_2p6v = 0x7,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x8,
+		       .vref_0p66v = 0x7,
+		       .vref_0p4v = 0x7,
+		       .vref_0p2v = 0x8,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+	.use_defalut_parameter = false,
+};
+
+static const struct type_c_cfg rtd1315e_type_c_cfg = {
+	.parameter_ver = PARAMETER_V1,
+	.cc_dfp_mode = CC_MODE_DFP_1_5,
+	.cc1_param = { .rp_4p7k_code = 0xe,
+		       .rp_36k_code = 0x3,
+		       .rp_12k_code = 0xe,
+		       .rd_code = 0xf,
+		       .ra_code = 0x6,
+		       .vref_2p6v = 0x7,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x8,
+		       .vref_0p66v = 0x7,
+		       .vref_0p4v = 0x7,
+		       .vref_0p2v = 0x7,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.cc2_param = { .rp_4p7k_code = 0xe,
+		       .rp_36k_code = 0x3,
+		       .rp_12k_code = 0xe,
+		       .rd_code = 0xf,
+		       .ra_code = 0x6,
+		       .vref_2p6v = 0x7,
+		       .vref_1p23v = 0x7,
+		       .vref_0p8v = 0x8,
+		       .vref_0p66v = 0x7,
+		       .vref_0p4v = 0x7,
+		       .vref_0p2v = 0x8,
+		       .vref_1_1p6v = 0x7,
+		       .vref_0_1p6v = 0x7 },
+	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
+	.use_defalut_parameter = false,
+};
+
+static const struct of_device_id extcon_rtk_type_c_match[] = {
+	{ .compatible = "realtek,rtd1295-type-c", .data = &rtd1295_type_c_cfg },
+	{ .compatible = "realtek,rtd1312c-type-c", .data = &rtd1312c_type_c_cfg },
+	{ .compatible = "realtek,rtd1315e-type-c", .data = &rtd1315e_type_c_cfg },
+	{ .compatible = "realtek,rtd1319-type-c", .data = &rtd1319_type_c_cfg },
+	{ .compatible = "realtek,rtd1319d-type-c", .data = &rtd1319d_type_c_cfg },
+	{ .compatible = "realtek,rtd1395-type-c", .data = &rtd1395_type_c_cfg },
+	{ .compatible = "realtek,rtd1619-type-c", .data = &rtd1619_type_c_cfg },
+	{ .compatible = "realtek,rtd1619b-type-c", .data = &rtd1619b_type_c_cfg },
+	{},
+};
+MODULE_DEVICE_TABLE(of, extcon_rtk_type_c_match);
+
+#ifdef CONFIG_PM_SLEEP
+static int extcon_rtk_type_c_prepare(struct device *dev)
+{
+	struct type_c_data *type_c = dev_get_drvdata(dev);
+	u32 default_ctrl;
+	unsigned long flags;
+
+	cancel_delayed_work_sync(&type_c->delayed_work);
+	flush_delayed_work(&type_c->delayed_work);
+	WARN_ON_ONCE(delayed_work_pending(&type_c->delayed_work));
+
+	spin_lock_irqsave(&type_c->lock, flags);
+	/* disable interrupt */
+	default_ctrl = readl(type_c->reg_base + USB_TYPEC_CTRL) &
+		    DEBOUNCE_TIME_MASK;
+	writel(default_ctrl, type_c->reg_base + USB_TYPEC_CTRL);
+
+	/* disable cc detect, rp, rd */
+	writel(PLR_EN, type_c->reg_base + USB_TYPEC_CTRL_CC1_0);
+	writel(0, type_c->reg_base + USB_TYPEC_CTRL_CC2_0);
+
+	spin_unlock_irqrestore(&type_c->lock, flags);
+
+	return 0;
+}
+
+static void extcon_rtk_type_c_complete(struct device *dev)
+{
+	/* nothing */
+}
+
+static int extcon_rtk_type_c_suspend(struct device *dev)
+{
+	struct type_c_data *type_c = dev_get_drvdata(dev);
+
+	if (type_c->rd_ctrl_gpio != -1)
+		gpio_free(type_c->rd_ctrl_gpio);
+
+	return 0;
+}
+
+static int extcon_rtk_type_c_resume(struct device *dev)
+{
+	struct type_c_data *type_c = dev_get_drvdata(dev);
+
+	extcon_rtk_type_c_init(type_c);
+
+	return 0;
+}
+
+static const struct dev_pm_ops extcon_rtk_type_c_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(extcon_rtk_type_c_suspend, extcon_rtk_type_c_resume)
+	.prepare = extcon_rtk_type_c_prepare,
+	.complete = extcon_rtk_type_c_complete,
+};
+
+#define DEV_PM_OPS	(&extcon_rtk_type_c_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static struct platform_driver extcon_rtk_type_c_driver = {
+	.probe		= extcon_rtk_type_c_probe,
+	.remove_new	= extcon_rtk_type_c_remove,
+	.driver		= {
+		.name	= "extcon-rtk-type_c",
+		.of_match_table = extcon_rtk_type_c_match,
+		.pm = DEV_PM_OPS,
+	},
+};
+
+module_platform_driver(extcon_rtk_type_c_driver);
+
+MODULE_DESCRIPTION("Realtek Extcon Type C driver");
+MODULE_ALIAS("platform:extcon-rtk-type-c");
+MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
+MODULE_LICENSE("GPL");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-22 10:28 [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Stanley Chang
@ 2023-08-22 10:28 ` Stanley Chang
  2023-08-22 15:38   ` Krzysztof Kozlowski
  2023-08-22 15:35 ` [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Krzysztof Kozlowski
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 19+ messages in thread
From: Stanley Chang @ 2023-08-22 10:28 UTC (permalink / raw)
  To: MyungJoo Ham
  Cc: Stanley Chang, Chanwoo Choi, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-kernel, devicetree

Document the device-tree bindings for Realtek SoCs Type-C.
Realtek DHC (digital home center) RTD SoCs support a Type-C module.

Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
---
 .../bindings/extcon/extcon-rtk-type-c.yaml    | 77 +++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml

diff --git a/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml b/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
new file mode 100644
index 000000000000..d14b9ee544b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2023 Realtek Semiconductor Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/extcon/extcon-rtk-type-c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek DHC RTD SoCs USB Type-C detection
+
+maintainers:
+  - Stanley Chang <stanley_chang@realtek.com>
+
+description: |
+  Realtek digital home center (DHC) RTD series SoCs include a type c module.
+  This module is able to detect the state of type c connector.
+
+properties:
+  compatible:
+    enum:
+      - realtek,rtd1295-type-c
+      - realtek,rtd1312c-type-c
+      - realtek,rtd1315e-type-c
+      - realtek,rtd1319-type-c
+      - realtek,rtd1319d-type-c
+      - realtek,rtd1395-type-c
+      - realtek,rtd1619-type-c
+      - realtek,rtd1619b-type-c
+
+  reg:
+    maxItems: 1
+    description: Address and length of register set for type-c module.
+
+  interrupts:
+    maxItems: 1
+
+  nvmem-cells:
+    maxItems: 1
+    description:
+      The phandle to nvmem cell that contains the trimming data.
+      If unspecified, default value is used.
+
+  pinctrl-names:
+    const: default
+    description: A pinctrl state names "default" must be defined.
+
+  pinctrl-0:
+    description:
+      Should contain default pinctrl.
+
+  nvmem-cell-names:
+    const: usb-cal
+    description:
+      The type c parameter trimming data specified via efuse.
+
+  realtek,rd-ctrl-gpio:
+    description: The gpio node to control external Rd on board.
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    type-c@7220 {
+        compatible = "realtek,rtd1619b-type-c";
+        reg = <0x7220 0x20>;
+        interrupts = <0 60 4>;
+
+        pinctrl-names = "default";
+        pinctrl-0 = <&usb_cc1_pins>, <&usb_cc2_pins>;
+        nvmem-cells = <&otp_usb_cal>;
+        nvmem-cell-names = "usb-cal";
+    };
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-22 10:28 [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Stanley Chang
  2023-08-22 10:28 ` [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C Stanley Chang
@ 2023-08-22 15:35 ` Krzysztof Kozlowski
  2023-08-24  6:09   ` Stanley Chang[昌育德]
  2023-08-23  0:26 ` kernel test robot
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 19+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-22 15:35 UTC (permalink / raw)
  To: Stanley Chang, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel, devicetree

On 22/08/2023 12:28, Stanley Chang wrote:
> This patch adds the extcon driver for Realtek DHC (digital home center)
> RTD SoCs type-c module. This can be used to detect whether the port is
> configured as a downstream or upstream facing port. And notify the status
> of extcon to listeners.
> 
> Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
> ---
>  drivers/extcon/Kconfig             |    9 +
>  drivers/extcon/Makefile            |    1 +
>  drivers/extcon/extcon-rtk-type-c.c | 1799 ++++++++++++++++++++++++++++
>  3 files changed, 1809 insertions(+)
>  create mode 100644 drivers/extcon/extcon-rtk-type-c.c
> 


> +static struct platform_driver extcon_rtk_type_c_driver = {
> +	.probe		= extcon_rtk_type_c_probe,
> +	.remove_new	= extcon_rtk_type_c_remove,
> +	.driver		= {
> +		.name	= "extcon-rtk-type_c",
> +		.of_match_table = extcon_rtk_type_c_match,
> +		.pm = DEV_PM_OPS,
> +	},
> +};
> +
> +module_platform_driver(extcon_rtk_type_c_driver);
> +
> +MODULE_DESCRIPTION("Realtek Extcon Type C driver");
> +MODULE_ALIAS("platform:extcon-rtk-type-c");

Drop alias. You have something really missing here if you need it.

> +MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
> +MODULE_LICENSE("GPL");

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-22 10:28 ` [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C Stanley Chang
@ 2023-08-22 15:38   ` Krzysztof Kozlowski
  2023-08-24  6:03     ` Stanley Chang[昌育德]
  0 siblings, 1 reply; 19+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-22 15:38 UTC (permalink / raw)
  To: Stanley Chang, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel, devicetree

On 22/08/2023 12:28, Stanley Chang wrote:
> Document the device-tree bindings for Realtek SoCs Type-C.
> Realtek DHC (digital home center) RTD SoCs support a Type-C module.
> 
> Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
> ---
>  .../bindings/extcon/extcon-rtk-type-c.yaml    | 77 +++++++++++++++++++
>  1 file changed, 77 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml

Filename like compatible.

> 
> diff --git a/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml b/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
> new file mode 100644
> index 000000000000..d14b9ee544b9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
> @@ -0,0 +1,77 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +# Copyright 2023 Realtek Semiconductor Corporation
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/extcon/extcon-rtk-type-c.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Realtek DHC RTD SoCs USB Type-C detection

Type-c usually go to usb directory.

> +
> +maintainers:
> +  - Stanley Chang <stanley_chang@realtek.com>
> +
> +description: |

Do not need '|' unless you need to preserve formatting.

> +  Realtek digital home center (DHC) RTD series SoCs include a type c module.
> +  This module is able to detect the state of type c connector.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - realtek,rtd1295-type-c
> +      - realtek,rtd1312c-type-c
> +      - realtek,rtd1315e-type-c
> +      - realtek,rtd1319-type-c
> +      - realtek,rtd1319d-type-c
> +      - realtek,rtd1395-type-c
> +      - realtek,rtd1619-type-c
> +      - realtek,rtd1619b-type-c
> +
> +  reg:
> +    maxItems: 1
> +    description: Address and length of register set for type-c module.

Drop description, it's obvious.

> +
> +  interrupts:
> +    maxItems: 1
> +
> +  nvmem-cells:
> +    maxItems: 1
> +    description:
> +      The phandle to nvmem cell that contains the trimming data.
> +      If unspecified, default value is used.
> +
> +  pinctrl-names:
> +    const: default
> +    description: A pinctrl state names "default" must be defined.

Drop, property not needed.

> +
> +  pinctrl-0:
> +    description:
> +      Should contain default pinctrl.

Drop, property not needed.


> +
> +  nvmem-cell-names:
> +    const: usb-cal

items:
  - const: usb-cal


and move description to nvmem-cells.

> +    description:
> +      The type c parameter trimming data specified via efuse.

Keep same properties next to each other. nvmem-cells should be followed
by nvmem-cell-names.

> +
> +  realtek,rd-ctrl-gpio:
> +    description: The gpio node to control external Rd on board.

The names are always "gpios".

> +    maxItems: 1
> +

You miss here connector. Probably also VBUS supply and other supplies.

> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    type-c@7220 {
> +        compatible = "realtek,rtd1619b-type-c";
> +        reg = <0x7220 0x20>;
> +        interrupts = <0 60 4>;

Use proper defines for common constants.

> +
> +        pinctrl-names = "default";
> +        pinctrl-0 = <&usb_cc1_pins>, <&usb_cc2_pins>;
> +        nvmem-cells = <&otp_usb_cal>;
> +        nvmem-cell-names = "usb-cal";

Type-c without connector? This is incomplete.

> +    };

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-22 10:28 [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Stanley Chang
  2023-08-22 10:28 ` [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C Stanley Chang
  2023-08-22 15:35 ` [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Krzysztof Kozlowski
@ 2023-08-23  0:26 ` kernel test robot
  2023-08-23 14:15 ` kernel test robot
  2023-08-24 19:43 ` Chanwoo Choi
  4 siblings, 0 replies; 19+ messages in thread
From: kernel test robot @ 2023-08-23  0:26 UTC (permalink / raw)
  To: Stanley Chang, MyungJoo Ham
  Cc: oe-kbuild-all, Stanley Chang, Chanwoo Choi, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-kernel, devicetree

Hi Stanley,

kernel test robot noticed the following build errors:

[auto build test ERROR on chanwoo-extcon/extcon-next]
[also build test ERROR on linus/master v6.5-rc7 next-20230822]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Stanley-Chang/dt-bindings-extcon-Add-Realtek-DHC-RTD-SoC-Type-C/20230822-183332
base:   https://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon.git extcon-next
patch link:    https://lore.kernel.org/r/20230822102846.4683-1-stanley_chang%40realtek.com
patch subject: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
config: m68k-randconfig-r024-20230823 (https://download.01.org/0day-ci/archive/20230823/202308230843.294BX49W-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230823/202308230843.294BX49W-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308230843.294BX49W-lkp@intel.com/

All errors (new ones prefixed by >>):

   m68k-linux-ld: drivers/extcon/extcon-rtk-type-c.o: in function `create_debug_files':
>> drivers/extcon/extcon-rtk-type-c.c:873:(.text+0x1948): undefined reference to `usb_debug_root'


vim +873 drivers/extcon/extcon-rtk-type-c.c

   870	
   871	static inline void create_debug_files(struct type_c_data *type_c)
   872	{
 > 873		type_c->debug_dir = debugfs_create_dir("type_c", usb_debug_root);
   874		if (!type_c->debug_dir)
   875			return;
   876	
   877		if (!debugfs_create_file("parameter", 0444, type_c->debug_dir, type_c,
   878					 &type_c_parameter_fops))
   879			goto file_error;
   880	
   881		if (!debugfs_create_file("status", 0444, type_c->debug_dir, type_c,
   882					 &type_c_status_fops))
   883			goto file_error;
   884	
   885		return;
   886	
   887	file_error:
   888		debugfs_remove_recursive(type_c->debug_dir);
   889	}
   890	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-22 10:28 [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Stanley Chang
                   ` (2 preceding siblings ...)
  2023-08-23  0:26 ` kernel test robot
@ 2023-08-23 14:15 ` kernel test robot
  2023-08-24 19:43 ` Chanwoo Choi
  4 siblings, 0 replies; 19+ messages in thread
From: kernel test robot @ 2023-08-23 14:15 UTC (permalink / raw)
  To: Stanley Chang, MyungJoo Ham
  Cc: oe-kbuild-all, Stanley Chang, Chanwoo Choi, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, linux-kernel, devicetree

Hi Stanley,

kernel test robot noticed the following build errors:

[auto build test ERROR on chanwoo-extcon/extcon-next]
[also build test ERROR on linus/master v6.5-rc7 next-20230823]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Stanley-Chang/dt-bindings-extcon-Add-Realtek-DHC-RTD-SoC-Type-C/20230822-183332
base:   https://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon.git extcon-next
patch link:    https://lore.kernel.org/r/20230822102846.4683-1-stanley_chang%40realtek.com
patch subject: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
config: loongarch-randconfig-r053-20230823 (https://download.01.org/0day-ci/archive/20230823/202308232214.4VvP0avv-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230823/202308232214.4VvP0avv-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308232214.4VvP0avv-lkp@intel.com/

All errors (new ones prefixed by >>):

   loongarch64-linux-ld: drivers/extcon/extcon-rtk-type-c.o: in function `.L394':
>> extcon-rtk-type-c.c:(.text+0x2a18): undefined reference to `usb_debug_root'
>> loongarch64-linux-ld: extcon-rtk-type-c.c:(.text+0x2a1c): undefined reference to `usb_debug_root'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-22 15:38   ` Krzysztof Kozlowski
@ 2023-08-24  6:03     ` Stanley Chang[昌育德]
  2023-08-24  6:26       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 19+ messages in thread
From: Stanley Chang[昌育德] @ 2023-08-24  6:03 UTC (permalink / raw)
  To: Krzysztof Kozlowski, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Krzysztof,

> On 22/08/2023 12:28, Stanley Chang wrote:
> > Document the device-tree bindings for Realtek SoCs Type-C.
> > Realtek DHC (digital home center) RTD SoCs support a Type-C module.
> >
> > Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
> > ---
> >  .../bindings/extcon/extcon-rtk-type-c.yaml    | 77 +++++++++++++++++++
> >  1 file changed, 77 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
> 
> Filename like compatible.

I will rename.

> >
> > diff --git
> > a/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
> > b/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
> > new file mode 100644
> > index 000000000000..d14b9ee544b9
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
> > @@ -0,0 +1,77 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) # Copyright
> > +2023 Realtek Semiconductor Corporation %YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/extcon/extcon-rtk-type-c.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Realtek DHC RTD SoCs USB Type-C detection
> 
> Type-c usually go to usb directory.

This binding is not for a type-c controller.
It is an extcon device for type-c connector detection.
So I put it at extcon directory.

And I will add “connector” to the title.
title: Realtek DHC RTD SoCs USB Type-C Connector detection

> > +maintainers:
> > +  - Stanley Chang <stanley_chang@realtek.com>
> > +
> > +description: |
> 
> Do not need '|' unless you need to preserve formatting.

Ok

> > +  Realtek digital home center (DHC) RTD series SoCs include a type c
> module.
> > +  This module is able to detect the state of type c connector.
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - realtek,rtd1295-type-c
> > +      - realtek,rtd1312c-type-c
> > +      - realtek,rtd1315e-type-c
> > +      - realtek,rtd1319-type-c
> > +      - realtek,rtd1319d-type-c
> > +      - realtek,rtd1395-type-c
> > +      - realtek,rtd1619-type-c
> > +      - realtek,rtd1619b-type-c
> > +
> > +  reg:
> > +    maxItems: 1
> > +    description: Address and length of register set for type-c module.
> 
> Drop description, it's obvious.

Ok.

> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  nvmem-cells:
> > +    maxItems: 1
> > +    description:
> > +      The phandle to nvmem cell that contains the trimming data.
> > +      If unspecified, default value is used.
> > +
> > +  pinctrl-names:
> > +    const: default
> > +    description: A pinctrl state names "default" must be defined.
> 
> Drop, property not needed.

Ok

> > +
> > +  pinctrl-0:
> > +    description:
> > +      Should contain default pinctrl.
> 
> Drop, property not needed.
> 
Ok.
> 
> > +
> > +  nvmem-cell-names:
> > +    const: usb-cal
> 
> items:
>   - const: usb-cal

> 
> and move description to nvmem-cells.
> 
> > +    description:
> > +      The type c parameter trimming data specified via efuse.
> 
> Keep same properties next to each other. nvmem-cells should be followed by
> nvmem-cell-names.
> 
> > +
> > +  realtek,rd-ctrl-gpio:
> > +    description: The gpio node to control external Rd on board.
> 
> The names are always "gpios".

Do you mean "realtek,rd-ctrl-gpios" ?
> 
> > +    maxItems: 1
> > +
> 
> You miss here connector. Probably also VBUS supply and other supplies.
> 
Ok, I will add connector.

> > +required:
> > +  - compatible
> > +  - reg
> > +  - interrupts
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    type-c@7220 {
> > +        compatible = "realtek,rtd1619b-type-c";
> > +        reg = <0x7220 0x20>;
> > +        interrupts = <0 60 4>;
> 
> Use proper defines for common constants.

Ok, I will revise this.

> > +
> > +        pinctrl-names = "default";
> > +        pinctrl-0 = <&usb_cc1_pins>, <&usb_cc2_pins>;

You mention that the property of pinctrl not need in doc.
Do I need to add the property of pintrl in example?

> > +        nvmem-cells = <&otp_usb_cal>;
> > +        nvmem-cell-names = "usb-cal";
> 
> Type-c without connector? This is incomplete.

Ok, I will add connector.


Thanks,
Stanley

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-22 15:35 ` [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Krzysztof Kozlowski
@ 2023-08-24  6:09   ` Stanley Chang[昌育德]
  0 siblings, 0 replies; 19+ messages in thread
From: Stanley Chang[昌育德] @ 2023-08-24  6:09 UTC (permalink / raw)
  To: Krzysztof Kozlowski, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Krzysztof,

> 
> 
> > +static struct platform_driver extcon_rtk_type_c_driver = {
> > +     .probe          = extcon_rtk_type_c_probe,
> > +     .remove_new     = extcon_rtk_type_c_remove,
> > +     .driver         = {
> > +             .name   = "extcon-rtk-type_c",
> > +             .of_match_table = extcon_rtk_type_c_match,
> > +             .pm = DEV_PM_OPS,
> > +     },
> > +};
> > +
> > +module_platform_driver(extcon_rtk_type_c_driver);
> > +
> > +MODULE_DESCRIPTION("Realtek Extcon Type C driver");
> > +MODULE_ALIAS("platform:extcon-rtk-type-c");
> 
> Drop alias. You have something really missing here if you need it.

Okay. I will remove.

> > +MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
> > +MODULE_LICENSE("GPL");
> 
Thanks,
Stanley

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-24  6:03     ` Stanley Chang[昌育德]
@ 2023-08-24  6:26       ` Krzysztof Kozlowski
  2023-08-24  7:23         ` Stanley Chang[昌育德]
  0 siblings, 1 reply; 19+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-24  6:26 UTC (permalink / raw)
  To: Stanley Chang[昌育德], MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

On 24/08/2023 08:03, Stanley Chang[昌育德] wrote:
> Hi Krzysztof,
> 
>> On 22/08/2023 12:28, Stanley Chang wrote:
>>> Document the device-tree bindings for Realtek SoCs Type-C.
>>> Realtek DHC (digital home center) RTD SoCs support a Type-C module.
>>>
>>> Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
>>> ---
>>>  .../bindings/extcon/extcon-rtk-type-c.yaml    | 77 +++++++++++++++++++
>>>  1 file changed, 77 insertions(+)
>>>  create mode 100644
>>> Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
>>
>> Filename like compatible.
> 
> I will rename.
> 
>>>
>>> diff --git
>>> a/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
>>> b/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
>>> new file mode 100644
>>> index 000000000000..d14b9ee544b9
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/extcon/extcon-rtk-type-c.yaml
>>> @@ -0,0 +1,77 @@
>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) # Copyright
>>> +2023 Realtek Semiconductor Corporation %YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/extcon/extcon-rtk-type-c.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: Realtek DHC RTD SoCs USB Type-C detection
>>
>> Type-c usually go to usb directory.
> 
> This binding is not for a type-c controller.
> It is an extcon device for type-c connector detection.
> So I put it at extcon directory.

If this is not a type-c controller, then what is it? Explain me please
what is an "extcon device" without using any Linux subsystem naming.

> 
> And I will add “connector” to the title.
> title: Realtek DHC RTD SoCs USB Type-C Connector detection

So usb...


>>
>>> +
>>> +  realtek,rd-ctrl-gpio:
>>> +    description: The gpio node to control external Rd on board.
>>
>> The names are always "gpios".
> 
> Do you mean "realtek,rd-ctrl-gpios" ?

Yes, like all of such properties in DTS and bindings. Everywhere.

>>
>>> +    maxItems: 1
>>> +
>>
>> You miss here connector. Probably also VBUS supply and other supplies.
>>
> Ok, I will add connector.
> 
>>> +required:
>>> +  - compatible
>>> +  - reg
>>> +  - interrupts
>>> +
>>> +additionalProperties: false
>>> +
>>> +examples:
>>> +  - |
>>> +    type-c@7220 {
>>> +        compatible = "realtek,rtd1619b-type-c";
>>> +        reg = <0x7220 0x20>;
>>> +        interrupts = <0 60 4>;
>>
>> Use proper defines for common constants.
> 
> Ok, I will revise this.
> 
>>> +
>>> +        pinctrl-names = "default";
>>> +        pinctrl-0 = <&usb_cc1_pins>, <&usb_cc2_pins>;
> 
> You mention that the property of pinctrl not need in doc.
> Do I need to add the property of pintrl in example?

Does not matter.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-24  6:26       ` Krzysztof Kozlowski
@ 2023-08-24  7:23         ` Stanley Chang[昌育德]
  2023-08-24  8:43           ` Krzysztof Kozlowski
  0 siblings, 1 reply; 19+ messages in thread
From: Stanley Chang[昌育德] @ 2023-08-24  7:23 UTC (permalink / raw)
  To: Krzysztof Kozlowski, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Krzysztof,

> >>> +
> >>> +title: Realtek DHC RTD SoCs USB Type-C detection
> >>
> >> Type-c usually go to usb directory.
> >
> > This binding is not for a type-c controller.
> > It is an extcon device for type-c connector detection.
> > So I put it at extcon directory.
> 
> If this is not a type-c controller, then what is it? Explain me please what is an
> "extcon device" without using any Linux subsystem naming.

Sorry. "extcon device" may be the wrong name I'm using.

As far as I know, type-c controller supports PD detection, role detection, role swap and cc configuration.
But in our SoC, type c module only supports role detection.
So I don't think it's a type-c controller.

I found a similar driver at
drivers/extcon/extcon-usbc-cros-ec.c
It belongs to External Connector, which can detect USB Type C cables.

So our driver is an external connector driver.

> >
> > And I will add “connector” to the title.
> > title: Realtek DHC RTD SoCs USB Type-C Connector detection
> 
> So usb...

I refer to this binding, and it is in folder bindings/extcon.
docs/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml
Title: ChromeOS EC USB Type-C Cable and Accessory Detection

Thank,
Stanley

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-24  7:23         ` Stanley Chang[昌育德]
@ 2023-08-24  8:43           ` Krzysztof Kozlowski
  2023-08-24  9:23             ` Stanley Chang[昌育德]
  0 siblings, 1 reply; 19+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-24  8:43 UTC (permalink / raw)
  To: Stanley Chang[昌育德], MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

On 24/08/2023 09:23, Stanley Chang[昌育德] wrote:
> Hi Krzysztof,
> 
>>>>> +
>>>>> +title: Realtek DHC RTD SoCs USB Type-C detection
>>>>
>>>> Type-c usually go to usb directory.
>>>
>>> This binding is not for a type-c controller.
>>> It is an extcon device for type-c connector detection.
>>> So I put it at extcon directory.
>>
>> If this is not a type-c controller, then what is it? Explain me please what is an
>> "extcon device" without using any Linux subsystem naming.
> 
> Sorry. "extcon device" may be the wrong name I'm using.
> 
> As far as I know, type-c controller supports PD detection, role detection, role swap and cc configuration.
> But in our SoC, type c module only supports role detection.
> So I don't think it's a type-c controller.

So module handling some parts of "Type-C" is not a "Type-C controller"
but if such module handles a bit more, it becomes Type-C?

> 
> I found a similar driver at
> drivers/extcon/extcon-usbc-cros-ec.c
> It belongs to External Connector, which can detect USB Type C cables.

That's a driver, not a binding...

> 
> So our driver is an external connector driver.

Driver yes, not binding.

> 
>>>
>>> And I will add “connector” to the title.
>>> title: Realtek DHC RTD SoCs USB Type-C Connector detection
>>
>> So usb...
> 
> I refer to this binding, and it is in folder bindings/extcon.
> docs/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml
> Title: ChromeOS EC USB Type-C Cable and Accessory Detection

So maybe it should be moved as well?

extcon is a Linux framework. If you think extcon is a type of hardware,
then please tell me what it is exactly. Please define it. And then I
wonder why the name "extcon" is anyhow connected to Type-C USB.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-24  8:43           ` Krzysztof Kozlowski
@ 2023-08-24  9:23             ` Stanley Chang[昌育德]
  2023-08-24  9:56               ` Krzysztof Kozlowski
  0 siblings, 1 reply; 19+ messages in thread
From: Stanley Chang[昌育德] @ 2023-08-24  9:23 UTC (permalink / raw)
  To: Krzysztof Kozlowski, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Krzysztof,



> -----Original Message-----
> From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Sent: Thursday, August 24, 2023 4:43 PM
> To: Stanley Chang[昌育德] <stanley_chang@realtek.com>; MyungJoo Ham
> <myungjoo.ham@samsung.com>
> Cc: Chanwoo Choi <cw00.choi@samsung.com>; Rob Herring
> <robh+dt@kernel.org>; Krzysztof Kozlowski
> <krzysztof.kozlowski+dt@linaro.org>; Conor Dooley <conor+dt@kernel.org>;
> linux-kernel@vger.kernel.org; devicetree@vger.kernel.org
> Subject: Re: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC
> Type-C
> 
> 
> External mail.
> 
> 
> 
> On 24/08/2023 09:23, Stanley Chang[昌育德] wrote:
> > Hi Krzysztof,
> >
> >>>>> +
> >>>>> +title: Realtek DHC RTD SoCs USB Type-C detection
> >>>>
> >>>> Type-c usually go to usb directory.
> >>>
> >>> This binding is not for a type-c controller.
> >>> It is an extcon device for type-c connector detection.
> >>> So I put it at extcon directory.
> >>
> >> If this is not a type-c controller, then what is it? Explain me
> >> please what is an "extcon device" without using any Linux subsystem
> naming.
> >
> > Sorry. "extcon device" may be the wrong name I'm using.
> >
> > As far as I know, type-c controller supports PD detection, role detection, role
> swap and cc configuration.
> > But in our SoC, type c module only supports role detection.
> > So I don't think it's a type-c controller.
> 
> So module handling some parts of "Type-C" is not a "Type-C controller"
> but if such module handles a bit more, it becomes Type-C?

Due to hardware function limitation, it can't handle the full function of type-c.

> >
> > I found a similar driver at
> > drivers/extcon/extcon-usbc-cros-ec.c
> > It belongs to External Connector, which can detect USB Type C cables.
> 
> That's a driver, not a binding...
> 
> >
> > So our driver is an external connector driver.
> 
> Driver yes, not binding.
> 
> >
> >>>
> >>> And I will add “connector” to the title.
> >>> title: Realtek DHC RTD SoCs USB Type-C Connector detection
> >>
> >> So usb...
> >
> > I refer to this binding, and it is in folder bindings/extcon.
> > docs/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml
> > Title: ChromeOS EC USB Type-C Cable and Accessory Detection
> 
> So maybe it should be moved as well?
> 
> extcon is a Linux framework. If you think extcon is a type of hardware, then
> please tell me what it is exactly. Please define it. And then I wonder why the
> name "extcon" is anyhow connected to Type-C USB.
> 

Well, from my point of view. extcon stands for External Connector.
HDMI connector, micro USB connector, type-c connector are all a kind of hardware, they are external connectors.
I think the Type-C connector is a kind of extcon.
Of course, I agree that Type-C is part of USB.

So this binding can be usb or extcon, I don't think it is strictly restricted.

Thanks,
Stanley


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-24  9:23             ` Stanley Chang[昌育德]
@ 2023-08-24  9:56               ` Krzysztof Kozlowski
  2023-08-24 10:05                 ` Stanley Chang[昌育德]
  0 siblings, 1 reply; 19+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-24  9:56 UTC (permalink / raw)
  To: Stanley Chang[昌育德], MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

On 24/08/2023 11:23, Stanley Chang[昌育德] wrote:
>>>
>>>>>
>>>>> And I will add “connector” to the title.
>>>>> title: Realtek DHC RTD SoCs USB Type-C Connector detection
>>>>
>>>> So usb...
>>>
>>> I refer to this binding, and it is in folder bindings/extcon.
>>> docs/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml
>>> Title: ChromeOS EC USB Type-C Cable and Accessory Detection
>>
>> So maybe it should be moved as well?
>>
>> extcon is a Linux framework. If you think extcon is a type of hardware, then
>> please tell me what it is exactly. Please define it. And then I wonder why the
>> name "extcon" is anyhow connected to Type-C USB.
>>
> 
> Well, from my point of view. extcon stands for External Connector.

For connectors we have separate directory - connector. So no, it is not
an external connector.

Anyway type "external connector" to Wikipedia or some hardware
manufacturer website and find me examples of such hardware. It does not
exist.

> HDMI connector, micro USB connector, type-c connector are all a kind of hardware, they are external connectors.

You did not write here bindings for connector...

> I think the Type-C connector is a kind of extcon.

There is no such thing as extcon. Otherwise please show me datasheets
using this name. Show me Wikipedia article.

> Of course, I agree that Type-C is part of USB.
> 
> So this binding can be usb or extcon, I don't think it is strictly restricted.



Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C
  2023-08-24  9:56               ` Krzysztof Kozlowski
@ 2023-08-24 10:05                 ` Stanley Chang[昌育德]
  0 siblings, 0 replies; 19+ messages in thread
From: Stanley Chang[昌育德] @ 2023-08-24 10:05 UTC (permalink / raw)
  To: Krzysztof Kozlowski, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Krzysztof,


> On 24/08/2023 11:23, Stanley Chang[昌育德] wrote:
> >>>
> >>>>>
> >>>>> And I will add “connector” to the title.
> >>>>> title: Realtek DHC RTD SoCs USB Type-C Connector detection
> >>>>
> >>>> So usb...
> >>>
> >>> I refer to this binding, and it is in folder bindings/extcon.
> >>> docs/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml
> >>> Title: ChromeOS EC USB Type-C Cable and Accessory Detection
> >>
> >> So maybe it should be moved as well?
> >>
> >> extcon is a Linux framework. If you think extcon is a type of
> >> hardware, then please tell me what it is exactly. Please define it.
> >> And then I wonder why the name "extcon" is anyhow connected to Type-C
> USB.
> >>
> >
> > Well, from my point of view. extcon stands for External Connector.
> 
> For connectors we have separate directory - connector. So no, it is not an
> external connector.
> 
> Anyway type "external connector" to Wikipedia or some hardware
> manufacturer website and find me examples of such hardware. It does not
> exist.
> 
> > HDMI connector, micro USB connector, type-c connector are all a kind of
> hardware, they are external connectors.
> 
> You did not write here bindings for connector...
> 
> > I think the Type-C connector is a kind of extcon.
> 
> There is no such thing as extcon. Otherwise please show me datasheets using
> this name. Show me Wikipedia article.
> 
> > Of course, I agree that Type-C is part of USB.
> >
> > So this binding can be usb or extcon, I don't think it is strictly restricted.
> 

Well~
I have no position to argue this issue.
I agree to move this binding to usb directory
But what's up with this directory "Documentation/devicetree/bindings/extcon/" ?
What binding can be placed in this directory?

Thanks,
Stanley

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-22 10:28 [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Stanley Chang
                   ` (3 preceding siblings ...)
  2023-08-23 14:15 ` kernel test robot
@ 2023-08-24 19:43 ` Chanwoo Choi
  2023-08-25  9:39   ` Stanley Chang[昌育德]
  2023-08-29 11:15   ` Stanley Chang[昌育德]
  4 siblings, 2 replies; 19+ messages in thread
From: Chanwoo Choi @ 2023-08-24 19:43 UTC (permalink / raw)
  To: Stanley Chang, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel, devicetree

Hi,

Almost code looks good to me. I add some comment below. Please check them.

On 23. 8. 22. 19:28, Stanley Chang wrote:
> This patch adds the extcon driver for Realtek DHC (digital home center)
> RTD SoCs type-c module. This can be used to detect whether the port is
> configured as a downstream or upstream facing port. And notify the status
> of extcon to listeners.
> 
> Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
> ---
>  drivers/extcon/Kconfig             |    9 +
>  drivers/extcon/Makefile            |    1 +
>  drivers/extcon/extcon-rtk-type-c.c | 1799 ++++++++++++++++++++++++++++
>  3 files changed, 1809 insertions(+)
>  create mode 100644 drivers/extcon/extcon-rtk-type-c.c
> 
> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
> index 0ef1971d22bb..d670434321f2 100644
> --- a/drivers/extcon/Kconfig
> +++ b/drivers/extcon/Kconfig
> @@ -190,4 +190,13 @@ config EXTCON_USBC_TUSB320
>  	  Say Y here to enable support for USB Type C cable detection extcon
>  	  support using a TUSB320.
>  
> +config EXTCON_RTK_TYPE_C
> +	tristate "Realtek RTD SoC extcon Type-C Driver"
> +	depends on ARCH_REALTEK || COMPILE_TEST
> +	help
> +	  Say Y here to enable extcon support for USB Type C cable detection
> +	  when using the Realtek RTD SoC USB Type-C port.
> +	  The DHC (Digital Home Hub) RTD series SoC contains a type c module.
> +	  This driver will detect the status of the type-c port.
> +
>  endif
> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
> index 1b390d934ca9..f779adb5e4c7 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_RTK_TYPE_C) += extcon-rtk-type-c.o
> diff --git a/drivers/extcon/extcon-rtk-type-c.c b/drivers/extcon/extcon-rtk-type-c.c
> new file mode 100644
> index 000000000000..04d4d5128bdb
> --- /dev/null
> +++ b/drivers/extcon/extcon-rtk-type-c.c
> @@ -0,0 +1,1799 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + *  * extcon-rtk-type-c.c - Realtek Extcon Type C driver
> + *
> + * Copyright (C) 2023 Realtek Semiconductor Corporation
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_gpio.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/syscalls.h>
> +#include <linux/suspend.h>
> +#include <linux/debugfs.h>
> +#include <linux/extcon.h>
> +#include <linux/extcon-provider.h>
> +#include <linux/sys_soc.h>
> +#include <linux/nvmem-consumer.h>
> +#include <linux/usb/otg.h>
> +#include <linux/usb/typec.h>
> +
> +struct cc_param {
> +	u32 rp_4p7k_code;
> +	u32 rp_36k_code;
> +	u32 rp_12k_code;
> +	u32 rd_code;
> +	u32 ra_code;
> +	u32 vref_2p6v;
> +	u32 vref_1p23v;
> +	u32 vref_0p8v;
> +	u32 vref_0p66v;
> +	u32 vref_0p4v;
> +	u32 vref_0p2v;
> +	u32 vref_1_1p6v;
> +	u32 vref_0_1p6v;
> +};
> +
> +struct type_c_cfg {
> +	int parameter_ver; /* Parameter version */
> +	int cc_dfp_mode;
> +	struct cc_param cc1_param;
> +	struct cc_param cc2_param;
> +
> +	u32 debounce_val;
> +	bool use_defalut_parameter;
> +};
> +
> +struct type_c_data {
> +	void __iomem *reg_base;
> +	struct device *dev;
> +	struct extcon_dev *edev;
> +
> +	u32 irq;
> +
> +	/* rd control GPIO only for rtd1295 */
> +	unsigned int rd_ctrl_gpio;
> +
> +	/* Parameters */
> +	struct type_c_cfg *type_c_cfg;
> +	u32 dfp_mode_rp_en;
> +	u32 ufp_mode_rd_en;
> +	u32 cc1_code;
> +	u32 cc2_code;
> +	u32 cc1_vref;
> +	u32 cc2_vref;
> +	u32 debounce; /* 1b,1us 7f,4.7us */
> +
> +	/* type_c state */
> +	int connect_change;
> +#define CONNECT_CHANGE 1
> +#define CONNECT_NO_CHANGE 0
> +	int cc_mode; /* cc is host or device */
> +#define IN_HOST_MODE 0x10
> +#define IN_DEVICE_MODE 0x20
> +	int is_attach;
> +#define IN_ATTACH 1
> +#define TO_ATTACH 1
> +#define IN_DETACH 0
> +#define TO_DETACH 0
> +	int at_cc1;
> +#define AT_CC1 1
> +#define AT_CC2 0
> +
> +	u32 int_status;
> +	u32 cc_status;
> +	/* protect the data member */
> +	spinlock_t lock;
> +	struct delayed_work delayed_work;
> +
> +	bool rd_en_at_first;
> +
> +	struct dentry *debug_dir;
> +
> +#ifdef CONFIG_TYPEC
> +	struct typec_port *port;
> +#endif /* CONFIG_TYPEC */
> +};
> +
> +/* Type C register offset */
> +#define USB_TYPEC_CTRL_CC1_0 0x0
> +#define USB_TYPEC_CTRL_CC1_1 0x4
> +#define USB_TYPEC_CTRL_CC2_0 0x8
> +#define USB_TYPEC_CTRL_CC2_1 0xC
> +#define USB_TYPEC_STS        0x10
> +#define USB_TYPEC_CTRL       0x14
> +#define USB_DBUS_PWR_CTRL    0x18

nitpick.
Above defintions uses 'space' to keep the left-aligned of value.
But, below defintions doesn't keep the left-aligned of value.

I recommend that you better to use the same style for the readability.

> +
> +#define ENABLE_CC1 0x1
> +#define ENABLE_CC2 0x2
> +#define DISABLE_CC 0x0
> +
> +/* Bit mapping USB_TYPEC_CTRL_CC1_0 and USB_TYPEC_CTRL_CC2_0 */
> +#define PLR_EN BIT(29)
> +#define CC_SWITCH_MASK (BIT(29) | BIT(28) | BIT(27))
> +#define CC_CODE_MASK (0xfffff << 7)
> +#define rp4pk_code(val) ((0x1f & (val)) << 22)
> +#define code_rp4pk(val) (((val) >> 22) & 0x1f)
> +#define rp36k_code(val) ((0x1f & (val)) << 17)
> +#define code_rp36k(val) (((val) >> 17) & 0x1f)
> +#define rp12k_code(val) ((0x1f & (val)) << 12)
> +#define code_rp12k(val) (((val) >> 12) & 0x1f)
> +#define rd_code(val) ((0x1f & (val)) << 7)
> +#define code_rd(val) (((val) >> 7) & 0x1f)
> +#define dfp_mode(val) ((0x3 & (val)) << 5)
> +#define EN_RP4P7K BIT(4)
> +#define EN_RP36K BIT(3)
> +#define EN_RP12K BIT(2)
> +#define EN_RD BIT(1)
> +#define EN_CC_DET BIT(0)
> +
> +#define CC_MODE_UFP 0x0
> +#define CC_MODE_DFP_USB 0x1
> +#define CC_MODE_DFP_1_5 0x2
> +#define CC_MODE_DFP_3_0 0x3
> +
> +/*
> + * PARAMETER_V0:
> + *  Realtek Kylin    rtd1295
> + *  Realtek Hercules rtd1395
> + *  Realtek Thor     rtd1619
> + *  Realtek Hank     rtd1319
> + *  Realtek Groot    rtd1312c
> + * PARAMETER_V1:
> + *  Realtek Stark    rtd1619b
> + *  Realtek Parker   rtd1319d
> + *  Realtek Danvers  rtd1315e
> + */
> +enum parameter_version {
> +	PARAMETER_V0 = 0,
> +	PARAMETER_V1 = 1,
> +};
> +
> +/* Bit mapping USB_TYPEC_CTRL_CC1_1 and USB_TYPEC_CTRL_CC2_1 */
> +#define V0_vref_2p6v(val) ((0xf & (val)) << 26) /* Bit 29 for groot */
> +#define V0_vref_1p23v(val) ((0xf & (val)) << 22)
> +#define V0_vref_0p8v(val) ((0xf & (val)) << 18)
> +#define V0_vref_0p66v(val) ((0xf & (val)) << 14)
> +#define V0_vref_0p4v(val) ((0x7 & (val)) << 11)
> +#define V0_vref_0p2v(val) ((0x7 & (val)) << 8)
> +#define V0_vref_1_1p6v(val) ((0xf & (val)) << 4)
> +#define V0_vref_0_1p6v(val) ((0xf & (val)) << 0)
> +
> +#define V0_decode_2p6v(val) (((val) >> 26) & 0xf) /* Bit 29 for groot */
> +#define V0_decode_1p23v(val) (((val) >> 22) & 0xf)
> +#define V0_decode_0p8v(val) (((val) >> 18) & 0xf)
> +#define V0_decode_0p66v(val) (((val) >> 14) & 0xf)
> +#define V0_decode_0p4v(val) (((val) >> 11) & 0x7)
> +#define V0_decode_0p2v(val) (((val) >> 8) & 0x7)
> +#define V0_decode_1_1p6v(val) (((val) >> 4) & 0xf)
> +#define V0_decode_0_1p6v(val) (((val) >> 0) & 0xf)
> +
> +/* new Bit mapping USB_TYPEC_CTRL_CC1_1 and USB_TYPEC_CTRL_CC2_1 */
> +#define V1_vref_2p6v(val) ((0xf & (val)) << 28)
> +#define V1_vref_1p23v(val) ((0xf & (val)) << 24)
> +#define V1_vref_0p8v(val) ((0xf & (val)) << 20)
> +#define V1_vref_0p66v(val) ((0xf & (val)) << 16)
> +#define V1_vref_0p4v(val) ((0xf & (val)) << 12)
> +#define V1_vref_0p2v(val) ((0xf & (val)) << 8)
> +#define V1_vref_1_1p6v(val) ((0xf & (val)) << 4)
> +#define V1_vref_0_1p6v(val) ((0xf & (val)) << 0)
> +
> +#define V1_decode_2p6v(val) (((val) >> 28) & 0xf)
> +#define V1_decode_1p23v(val) (((val) >> 24) & 0xf)
> +#define V1_decode_0p8v(val) (((val) >> 20) & 0xf)
> +#define V1_decode_0p66v(val) (((val) >> 16) & 0xf)
> +#define V1_decode_0p4v(val) (((val) >> 12) & 0xf)
> +#define V1_decode_0p2v(val) (((val) >> 8) & 0xf)
> +#define V1_decode_1_1p6v(val) (((val) >> 4) & 0xf)
> +#define V1_decode_0_1p6v(val) (((val) >> 0) & 0xf)
> +
> +/* Bit mapping USB_TYPEC_STS */
> +#define DET_STS 0x7
> +#define CC1_DET_STS (DET_STS)
> +#define CC2_DET_STS (DET_STS << 3)
> +#define DET_STS_RA 0x1
> +#define DET_STS_RD 0x3
> +#define DET_STS_RP 0x1
> +#define CC1_DET_STS_RA (DET_STS_RA)
> +#define CC1_DET_STS_RD (DET_STS_RD)
> +#define CC1_DET_STS_RP (DET_STS_RP)
> +#define CC2_DET_STS_RA (DET_STS_RA << 3)
> +#define CC2_DET_STS_RD (DET_STS_RD << 3)
> +#define CC2_DET_STS_RP (DET_STS_RP << 3)
> +
> +/* Bit mapping USB_TYPEC_CTRL */
> +#define CC2_INT_EN BIT(11)
> +#define CC1_INT_EN BIT(10)
> +#define CC2_INT_STS BIT(9)
> +#define CC1_INT_STS BIT(8)
> +#define DEBOUNCE_TIME_MASK 0xff
> +#define DEBOUNCE_EN BIT(0)
> +#define ENABLE_TYPE_C_DETECT (CC1_INT_EN | CC2_INT_EN)
> +#define ALL_CC_INT_STS (CC1_INT_STS | CC2_INT_STS)
> +
> +/* Parameter */
> +#define DETECT_TIME 50 /* ms */
> +
> +static const unsigned int usb_type_c_cable[] = {
> +	EXTCON_USB,
> +	EXTCON_USB_HOST,
> +	EXTCON_NONE,
> +};
> +
> +enum usb_data_roles {
> +	DR_NONE,
> +	DR_HOST,
> +	DR_DEVICE,
> +};
> +
> +static const struct soc_device_attribute rtk_soc_kylin[] = {
> +	{ .family = "Realtek Kylin", },
> +	{ /* empty */ }
> +};
> +
> +static int rtd129x_switch_type_c_plug_config(struct type_c_data *type_c,
> +					     int dr_mode, int cc)
> +{
> +	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
> +	int val_cc;
> +
> +#define TYPE_C_EN_SWITCH BIT(29)
> +#define TYPE_C_TXRX_SEL (BIT(28) | BIT(27))
> +#define TYPE_C_SWITCH_MASK (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
> +#define TYPE_C_ENABLE_CC1 TYPE_C_EN_SWITCH
> +#define TYPE_C_ENABLE_CC2 (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
> +#define TYPE_C_DISABLE_CC ~TYPE_C_SWITCH_MASK
> +
> +	val_cc = readl(reg);

I'd like you to use regmap interface to access the register
by using regmap_read, regmap_write. You can create the regmap instance
via devm_regmap_init_mmio() on probe instead of using 'type_c->reg_base' 
at the multipe point.

For example,
	struct regmap_config rtk_regmap_config = {
		.reg_bits = 32,
		.val_bits = 32,
	};

	void __iomem *base;

	base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);            
	if (IS_ERR(base))                                                        
		return PTR_ERR(base);                                            
                                                                            
	regmap = devm_regmap_init_mmio(dev, base, &rtk_regmap_config);

	---

	And then just call regmap_read without any calculation between
	base address and specific register. 

	regmap_read(regmap, USB_TYPEC_CTRL_CC1_0)


> +	val_cc &= ~TYPE_C_SWITCH_MASK;
> +
> +	if (cc == DISABLE_CC) {
> +		val_cc &= TYPE_C_DISABLE_CC;
> +	} else if (cc == ENABLE_CC1) {
> +		val_cc |= TYPE_C_ENABLE_CC1;
> +	} else if (cc == ENABLE_CC2) {
> +		val_cc |= TYPE_C_ENABLE_CC2;
> +	} else {
> +		dev_err(type_c->dev, "%s: Error cc setting cc=0x%x\n", __func__, cc);
> +		return -EINVAL;
> +	}
> +	writel(val_cc, reg);
> +
> +	mdelay(1);
Maybe, it depends on h/w constraints. Better to explain the comment
of why adding delay at here. Also, this patch uses mdelay/msleep at
the multiple point. I recommend that add the comment of reason to add
mdelay/msleep.

> +
> +	dev_dbg(type_c->dev, "%s: cc=0x%x val_cc=0x%x usb_typec_ctrl_cc1_0=0x%x\n",
> +		__func__, cc, val_cc, readl(reg));
> +
> +	return 0;
> +}
> +
> +static inline void switch_type_c_plug_config(struct type_c_data *type_c,
> +					     int dr_mode, int cc)
> +{
> +	int ret = 0;
> +
> +	if (soc_device_match(rtk_soc_kylin))
> +		ret = rtd129x_switch_type_c_plug_config(type_c, dr_mode, cc);
> +
> +	if (ret < 0)
> +		dev_err(type_c->dev, "%s: Error set type c plug config\n",
> +			__func__);
> +}
> +
> +static void switch_type_c_dr_mode(struct type_c_data *type_c, int dr_mode, int cc)
> +{
> +	bool is_host = false;
> +	bool is_device = false;
> +	bool polarity = false;
> +	bool vbus = false;
> +	bool ss = true;
> +
> +	switch_type_c_plug_config(type_c, dr_mode, cc);
> +	if (cc == ENABLE_CC2)
> +		polarity = true;
> +
> +	switch (dr_mode) {
> +	case USB_DR_MODE_HOST:
> +		is_host = true;
> +		break;
> +	case USB_DR_MODE_PERIPHERAL:
> +		is_device = true;
> +		vbus = true;
> +		break;
> +	default:
> +		dev_dbg(type_c->dev, "%s dr_mode=%d ==> no host or device\n",
> +			__func__, dr_mode);
> +		break;
> +	}
> +
> +	dev_dbg(type_c->dev, "%s is_host=%d is_device=%d vbus=%d polarity=%d\n",
> +		__func__, is_host, is_device, vbus, polarity);
> +
> +	/* for EXTCON_USB device mode */
> +	extcon_set_state(type_c->edev, EXTCON_USB, is_device);
> +	extcon_set_property(type_c->edev, EXTCON_USB,
> +			    EXTCON_PROP_USB_VBUS,
> +			    (union extcon_property_value)(int)vbus);
> +	extcon_set_property(type_c->edev, EXTCON_USB,
> +			    EXTCON_PROP_USB_TYPEC_POLARITY,
> +			    (union extcon_property_value)(int)polarity);
> +	extcon_set_property(type_c->edev, EXTCON_USB,
> +			    EXTCON_PROP_USB_SS,
> +			    (union extcon_property_value)(int)ss);
> +
> +	/* for EXTCON_USB_HOST host mode */
> +	extcon_set_state(type_c->edev, EXTCON_USB_HOST, is_host);
> +	extcon_set_property(type_c->edev, EXTCON_USB_HOST,
> +			    EXTCON_PROP_USB_VBUS,
> +			    (union extcon_property_value)(int)vbus);
> +	extcon_set_property(type_c->edev, EXTCON_USB_HOST,
> +			    EXTCON_PROP_USB_TYPEC_POLARITY,
> +			    (union extcon_property_value)(int)polarity);
> +	extcon_set_property(type_c->edev, EXTCON_USB_HOST,
> +			    EXTCON_PROP_USB_SS,
> +			    (union extcon_property_value)(int)ss);
> +
> +	/* sync EXTCON_USB and EXTCON_USB_HOST */
> +	extcon_sync(type_c->edev, EXTCON_USB);
> +	extcon_sync(type_c->edev, EXTCON_USB_HOST);
> +
> +#ifdef CONFIG_TYPEC> +	if (type_c->port) {
> +		switch (dr_mode) {
> +		case USB_DR_MODE_HOST:
> +			typec_set_data_role(type_c->port, TYPEC_HOST);
> +			typec_set_pwr_role(type_c->port, TYPEC_SOURCE);
> +			break;
> +		case USB_DR_MODE_PERIPHERAL:
> +			typec_set_data_role(type_c->port, TYPEC_DEVICE);
> +			typec_set_pwr_role(type_c->port, TYPEC_SINK);
> +			break;
> +		default:
> +			dev_dbg(type_c->dev, "%s unknown dr_mode=%d\n",
> +				__func__, dr_mode);
> +			break;
> +		}
> +	}
> +#endif
> +}
> +
> +/* device attached/detached */
> +static int device_attached(struct type_c_data *type_c, u32 cc)
> +{
> +	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> +
> +	cancel_delayed_work(&type_c->delayed_work);
> +
> +	switch_type_c_dr_mode(type_c, USB_DR_MODE_HOST, cc);
> +
> +	writel(ENABLE_TYPE_C_DETECT | readl(reg), reg);
> +
> +	return 0;
> +}

device_attached() funciton is same with host_connected()
except for USR_BR_MODE_HOST, USB_DR_MODE_PERIPHERAL setting.

You can use only one function with 3rd paramer (dr_mode) as following
in order to reduce the duplicated code.
For example,
static int connector_attached(struct type_c_data *type_c, u32 cc, int dr_mode)

> +
> +static int device_detached(struct type_c_data *type_c, u32 cc)
> +{
> +	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> +
> +	writel(~ENABLE_TYPE_C_DETECT & readl(reg), reg);
> +
> +	switch_type_c_dr_mode(type_c, 0, cc);
> +
> +	schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(DETECT_TIME));
> +
> +	return 0;
> +}

device_detached is perfectly same with host_disconnected.
You can use the only one function to reduce the duplicated code

> +
> +/* host connect/disconnect*/
> +static int host_connected(struct type_c_data *type_c, u32 cc)
> +{
> +	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> +
> +	cancel_delayed_work(&type_c->delayed_work);
> +
> +	switch_type_c_dr_mode(type_c, USB_DR_MODE_PERIPHERAL, cc);
> +
> +	writel(ENABLE_TYPE_C_DETECT | readl(reg), reg);
> +	return 0;
> +}
> +
> +static int host_disconnected(struct type_c_data *type_c, u32 cc)
> +{
> +	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> +
> +	writel(~ENABLE_TYPE_C_DETECT & readl(reg), reg);
> +
> +	switch_type_c_dr_mode(type_c, 0, cc);
> +
> +	schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(DETECT_TIME));
> +
> +	return 0;
> +}
> +
> +/* detect host device switch */
> +static int __detect_host_device(struct type_c_data *type_c, u32 rp_or_rd_en)
> +{
> +	struct device *dev = type_c->dev;
> +	void __iomem *reg_base = type_c->reg_base;
> +	unsigned int gpio = type_c->rd_ctrl_gpio;
> +	u32 cc1_config, cc2_config, default_ctrl;
> +	u32 cc1_switch = 0;
> +
> +	default_ctrl = readl(reg_base + USB_TYPEC_CTRL) & DEBOUNCE_TIME_MASK;
> +	writel(default_ctrl, reg_base + USB_TYPEC_CTRL);
> +
> +	cc1_config = readl(reg_base + USB_TYPEC_CTRL_CC1_0);
> +	cc2_config = readl(reg_base + USB_TYPEC_CTRL_CC2_0);
> +
> +	cc1_config &= ~EN_CC_DET;
> +	cc2_config &= ~EN_CC_DET;
> +	writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
> +	writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
> +
> +	if (soc_device_match(rtk_soc_kylin))
> +		cc1_switch = cc1_config & CC_SWITCH_MASK;
> +
> +	cc1_config &= CC_CODE_MASK;
> +	cc1_config |= rp_or_rd_en | cc1_switch;
> +	cc2_config &= CC_CODE_MASK;
> +	cc2_config |= rp_or_rd_en;
> +	writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
> +	writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
> +
> +	/* For kylin to disable external rd control gpio */
> +	if (soc_device_match(rtk_soc_kylin)) {
> +		if (gpio != -1 && gpio_is_valid(gpio)) {
> +			if (gpio_direction_output(gpio, 1))
> +				dev_err(dev, "%s ERROR rd_ctrl_gpio=1 fail\n", __func__);
> +		}
> +	}
> +
> +	cc1_config |= EN_CC_DET;
> +	cc2_config |= EN_CC_DET;
> +	writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
> +	writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
> +
> +	return 0;
> +}
> +
> +static int detect_device(struct type_c_data *type_c)
> +{
> +	return __detect_host_device(type_c, type_c->dfp_mode_rp_en);
> +}
> +
> +static int detect_host(struct type_c_data *type_c)
> +{
> +	return __detect_host_device(type_c, type_c->ufp_mode_rd_en);
> +}
> +
> +static int host_device_switch_detection(struct type_c_data *type_c)
> +{
> +	if (type_c->cc_mode == IN_HOST_MODE) {
> +		type_c->cc_mode = IN_DEVICE_MODE;
> +		detect_host(type_c);
> +	} else {
> +		type_c->cc_mode = IN_HOST_MODE;
> +		detect_device(type_c);
> +	}
> +
> +	return 0;
> +}
> +
> +static int detect_type_c_state(struct type_c_data *type_c)
> +{
> +	struct device *dev = type_c->dev;
> +	void __iomem *reg_base = type_c->reg_base;
> +	u32 int_status, cc_status, cc_status_check;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&type_c->lock, flags);
> +
> +	int_status = readl(reg_base + USB_TYPEC_CTRL);
> +	cc_status = readl(reg_base + USB_TYPEC_STS);
> +
> +	type_c->connect_change = CONNECT_NO_CHANGE;
> +
> +	switch (type_c->cc_mode | type_c->is_attach) {
> +	case IN_HOST_MODE | IN_ATTACH:
> +		if (((cc_status & CC1_DET_STS) == CC1_DET_STS) && type_c->at_cc1 == AT_CC1) {
> +			dev_dbg(dev, "IN host mode and cc1 device detach (cc_status=0x%x)",
> +				cc_status);
> +			type_c->is_attach = TO_DETACH;
> +			type_c->connect_change = CONNECT_CHANGE;
> +		} else if (((cc_status & CC2_DET_STS) == CC2_DET_STS) &&
> +			   type_c->at_cc1 == AT_CC2) {
> +			dev_dbg(dev, "IN host mode and cc2 device detach (cc_status=0x%x)",
> +				cc_status);
> +			type_c->is_attach = TO_DETACH;
> +			type_c->connect_change = CONNECT_CHANGE;
> +		}
> +		break;
> +	case IN_HOST_MODE | IN_DETACH:
> +		cc_status_check = readl(reg_base + USB_TYPEC_STS);
> +		if (cc_status_check != (CC1_DET_STS | CC2_DET_STS)) {
> +			if (in_interrupt()) {
> +				mdelay(300);
> +			} else {
> +				spin_unlock_irqrestore(&type_c->lock, flags);
> +				msleep(300);
> +				spin_lock_irqsave(&type_c->lock, flags);
> +			}

As I commented above, it seems that there are some hardware constrains
which requires the some delay when changing the h/w state.
I recommend that you need to add the comment of why adding the delays/sleep.

> +			cc_status_check = readl(reg_base + USB_TYPEC_STS);
> +		}
> +		if (cc_status != cc_status_check) {
> +			dev_warn(dev, "IN_HOST_MODE: cc_status (0x%x) != cc_status_check (0x%x)\n",
> +				 cc_status, cc_status_check);
> +			cc_status = readl(reg_base + USB_TYPEC_STS);
> +		}
> +
> +		if ((cc_status & CC1_DET_STS) == CC1_DET_STS_RD) {
> +			dev_dbg(dev, "IN host mode and cc1 device attach (cc_status=0x%x)",
> +				cc_status);
> +			type_c->is_attach = TO_ATTACH;
> +			type_c->at_cc1 = AT_CC1;
> +			type_c->connect_change = CONNECT_CHANGE;
> +		} else if ((cc_status & CC2_DET_STS) == CC2_DET_STS_RD) {
> +			dev_dbg(dev, "In host mode and cc2 device attach (cc_status=0x%x)",
> +				cc_status);
> +			type_c->is_attach = TO_ATTACH;
> +			type_c->at_cc1 = AT_CC2;
> +			type_c->connect_change = CONNECT_CHANGE;
> +		}
> +		break;
> +	case IN_DEVICE_MODE | IN_ATTACH:
> +		if ((cc_status & CC1_DET_STS) < CC1_DET_STS_RP ||
> +		    (cc_status & CC2_DET_STS) < CC2_DET_STS_RP) {
> +			/* Add a sw debounce to filter cc signal sent from apple pd adapter */
> +			mdelay(5);
> +			cc_status_check = readl(reg_base + USB_TYPEC_STS);
> +
> +			if (cc_status != cc_status_check) {
> +				dev_dbg(dev, "IN_DEVICE_MODE: cc_status (0x%x) != cc_status_check (0x%x) maybe use a pd adapter\n",
> +					cc_status, cc_status_check);
> +				cc_status = cc_status_check;
> +			}
> +		}
> +
> +		if ((cc_status & CC1_DET_STS) < CC1_DET_STS_RP && type_c->at_cc1 == AT_CC1) {
> +			dev_dbg(dev, "IN device mode and cc1 host disconnect (cc_status=0x%x)",
> +				cc_status);
> +			type_c->is_attach = TO_DETACH;
> +			type_c->connect_change = CONNECT_CHANGE;
> +		} else if ((cc_status & CC2_DET_STS) < CC2_DET_STS_RP &&
> +			   type_c->at_cc1 == AT_CC2) {
> +			dev_dbg(dev, "IN device mode and cc2 host disconnect (cc_status=0x%x)",
> +				cc_status);
> +			type_c->is_attach = TO_DETACH;
> +			type_c->connect_change = CONNECT_CHANGE;
> +		}
> +		break;
> +	case IN_DEVICE_MODE | IN_DETACH:
> +		cc_status_check = readl(reg_base + USB_TYPEC_STS);
> +		if (cc_status_check != 0x0) {
> +			if (in_interrupt()) {
> +				mdelay(300);
> +			} else {
> +				spin_unlock_irqrestore(&type_c->lock, flags);
> +				msleep(300);
> +				spin_lock_irqsave(&type_c->lock, flags);
> +			}

ditto.

> +			cc_status_check = readl(reg_base + USB_TYPEC_STS);
> +		}
> +
> +		if (cc_status != cc_status_check) {
> +			dev_warn(dev, "IN_DEVICE_MODE: cc_status (0x%x) != cc_status_check (0x%x)\n",
> +				 cc_status, cc_status_check);
> +			cc_status = readl(reg_base + USB_TYPEC_STS);
> +		}
> +
> +		if ((cc_status & CC1_DET_STS) >= CC1_DET_STS_RP) {
> +			dev_dbg(dev, "IN device mode and cc1 host connect (cc_status=0x%x)",
> +				cc_status);
> +			type_c->at_cc1 = AT_CC1;
> +			type_c->is_attach = TO_ATTACH;
> +			type_c->connect_change = CONNECT_CHANGE;
> +		} else if ((cc_status & CC2_DET_STS) >= CC2_DET_STS_RP) {
> +			dev_dbg(dev, "IN device mode and cc2 host connect (cc_status=0x%x)",
> +				cc_status);
> +			type_c->at_cc1 = AT_CC2;
> +			type_c->is_attach = TO_ATTACH;
> +			type_c->connect_change = CONNECT_CHANGE;
> +		}
> +		break;
> +	default:
> +		dev_err(dev, "error host or device mode (cc_mode=%d, is_attach=%d) ",
> +			type_c->cc_mode, type_c->is_attach);
> +	}
> +
> +	type_c->int_status = int_status;
> +	type_c->cc_status = cc_status;
> +
> +	spin_unlock_irqrestore(&type_c->lock, flags);
> +	return 0;
> +}
> +
> +static void host_device_switch(struct work_struct *work)
> +{
> +	struct type_c_data *type_c = container_of(work, struct type_c_data,
> +						  delayed_work.work);
> +	struct device *dev = type_c->dev;
> +	unsigned long flags;
> +	int connect_change = 0;
> +	int cc_mode = 0;
> +	int is_attach = 0;
> +	int at_cc1 = 0;
> +
> +	spin_lock_irqsave(&type_c->lock, flags);
> +	if (type_c->connect_change)
> +		connect_change = type_c->connect_change;
> +	spin_unlock_irqrestore(&type_c->lock, flags);

Better to convert this code as following if type_c->connect_change is NULL,
you can reduce the lock/unlok operation of spin_lock. As you knew, spin_lock is expensive.
	
	if (type_c->connect_change) {
		spin_lock_irqsave(&type_c->lock, flags);
		connect_change = type_c->connect_change;
		spin_unlock_irqrestore(&type_c->lock, flags);
	}

> +
> +	if (!connect_change)
> +		detect_type_c_state(type_c);
> +
> +	spin_lock_irqsave(&type_c->lock, flags);
> +	if (type_c->connect_change) {
> +		connect_change = type_c->connect_change;
> +		cc_mode = type_c->cc_mode;
> +		is_attach = type_c->is_attach;
> +		at_cc1 = type_c->at_cc1;
> +		type_c->connect_change = CONNECT_NO_CHANGE;
> +	} else {
> +		host_device_switch_detection(type_c);
> +
> +		schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(DETECT_TIME));
> +	}
> +	spin_unlock_irqrestore(&type_c->lock, flags);
> +
> +	if (connect_change) {

nitpick. 
You can reduce the depth of indentation when connector_change is 0
by changing the code as following: If possible, I always to try
to reduce the indentation depth for the readability.

	if (!connect_change)
		return

	dev_dbg(dev, "%s: usb cable connection change\n", __func__);
	if (cc_mode == IN_HOST_MODE) {
		......


> +		dev_dbg(dev, "%s: usb cable connection change\n", __func__);
> +		if (cc_mode == IN_HOST_MODE) {
> +			if (is_attach && at_cc1)
> +				device_attached(type_c, ENABLE_CC1);
> +			else if (is_attach && !at_cc1)
> +				device_attached(type_c, ENABLE_CC2);
> +			else
> +				device_detached(type_c, DISABLE_CC);
> +		} else if (cc_mode == IN_DEVICE_MODE) {
> +			if (is_attach && at_cc1)
> +				host_connected(type_c, ENABLE_CC1);
> +			else if (is_attach && !at_cc1)
> +				host_connected(type_c, ENABLE_CC2);
> +			else
> +				host_disconnected(type_c, DISABLE_CC);
> +		} else {
> +			dev_err(dev, "Error: IN unknown mode %d to %s at %s (cc_status=0x%x)\n",
> +				cc_mode, is_attach ? "attach" : "detach",
> +				at_cc1 ? "cc1" : "cc2", type_c->cc_status);
> +		}
> +		dev_info(dev, "Connection change OK: IN %s mode to %s at %s (cc_status=0x%x)\n",
> +			 cc_mode == IN_HOST_MODE ? "host" : "device",
> +			 is_attach ? "attach" : "detach",
> +			 at_cc1 ? "cc1" : "cc2", type_c->cc_status);
> +	}
> +}
> +
> +static irqreturn_t type_c_detect_irq(int irq, void *__data)
> +{
> +	struct type_c_data *type_c = (struct type_c_data *)__data;
> +	struct device *dev = type_c->dev;
> +	void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> +	unsigned long flags;
> +
> +	detect_type_c_state(type_c);
> +
> +	spin_lock_irqsave(&type_c->lock, flags);
> +
> +	if (type_c->connect_change) {
> +		dev_dbg(dev, "%s: IN %s mode to %s (at %s interrupt) int_status=0x%x, cc_status=0x%x",
> +			__func__,
> +			type_c->cc_mode == IN_HOST_MODE ? "host" : "device",
> +			type_c->is_attach ? "attach" : "detach",
> +			type_c->at_cc1 ? "cc1" : "cc2",
> +			type_c->int_status, type_c->cc_status);
> +
> +		/* clear interrupt status */
> +		writel(~ALL_CC_INT_STS & readl(reg), reg);
> +
> +		cancel_delayed_work(&type_c->delayed_work);
> +		schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(0));
> +	} else {
> +		static int local_count;
> +
> +		if (local_count++ > 10) {

It seems that clear interrupt status once every 10 times.
I think that it is not generic. You need to add the comment of why trying to clear
interrupt once every 10 times.

> +			/* clear interrupt status */
> +			writel(~ALL_CC_INT_STS & readl(reg), reg);
> +			local_count = 0;
> +		}
> +	}
> +
> +	spin_unlock_irqrestore(&type_c->lock, flags);
> +
> +	return IRQ_HANDLED;
> +}

(snip)

> +
> +static int extcon_rtk_type_c_init(struct type_c_data *type_c)
> +{
> +	struct device *dev = type_c->dev;
> +	unsigned long flags;
> +	void __iomem *reg;
> +	int val;
> +
> +	if ((type_c->rd_ctrl_gpio != -1) &&

nitpick.
After getting the gpio number by using of_get_named_gpio() function,
type_c->rd_ctrl_gpio is error number which is returned of_get_named_gpio().

In order to specify the more correctly, how about changing it as following?
Because I don't use the '-1' constant variable without any constant defintion.
Someone cannot understand the meaning of '-1'.

	if (!(type_c->rd_ctrl_gpio < 0))

> +	    gpio_request(type_c->rd_ctrl_gpio, dev->of_node->name))
> +		dev_err(dev, "%s ERROR Request rd_ctrl_gpio  (id=%d) fail\n",
> +			__func__, type_c->rd_ctrl_gpio);
> +
> +	spin_lock_irqsave(&type_c->lock, flags);
> +
> +	/* set parameter */
> +	reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
> +	val = readl(reg);
> +	val = (~CC_CODE_MASK & val) | (type_c->cc1_code & CC_CODE_MASK);
> +	writel(val, reg);
> +
> +	reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_0;
> +	val = readl(reg);
> +	val = (~CC_CODE_MASK & val) | (type_c->cc2_code & CC_CODE_MASK);
> +
> +	reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_1;
> +	writel(type_c->cc1_vref, reg);
> +
> +	reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_1;
> +	writel(type_c->cc2_vref, reg);
> +
> +	reg = type_c->reg_base + USB_TYPEC_CTRL;
> +	val = readl(reg);
> +	val = (~DEBOUNCE_TIME_MASK & val) | (type_c->debounce & DEBOUNCE_TIME_MASK);
> +
> +	dev_info(dev, "First check USB_DR_MODE_PERIPHERAL");
> +	type_c->cc_mode = IN_DEVICE_MODE;
> +	type_c->is_attach = IN_DETACH;
> +	type_c->connect_change = CONNECT_NO_CHANGE;
> +
> +	detect_host(type_c);
> +
> +	spin_unlock_irqrestore(&type_c->lock, flags);
> +
> +	schedule_delayed_work(&type_c->delayed_work, msecs_to_jiffies(0));
> +
> +#ifdef CONFIG_TYPEC

Don'n need to check 'CONFIG_TYPEC' defintion wiht ifdef.
'ifdef' might make the code more complicated.

If type_c is optional, just print warning message
when typec_regiser_port returns error. 

This patch is already check whether 'type_c->port' is NULL or not
to handle the code related to typec.

> +	if (!type_c->port) {

(snip)

> +
> +		type_c->port = typec_register_port(type_c->dev, &typec_cap);
> +		if (IS_ERR(type_c->port))
> +			return PTR_ERR(type_c->port);
> +	}> +#endif /* CONFIG_TYPEC */
> +
> +	return 0;
> +}
> +
> +static int extcon_rtk_type_c_edev_register(struct type_c_data *type_c)
> +{
> +	struct device *dev = type_c->dev;
> +	int ret = 0;
> +
> +	type_c->edev = devm_extcon_dev_allocate(dev, usb_type_c_cable);
> +	if (IS_ERR(type_c->edev)) {
> +		dev_err(dev, "failed to allocate extcon device\n");
> +		return -ENOMEM;
> +	}
> +
> +	ret = devm_extcon_dev_register(dev, type_c->edev);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to register extcon device\n");
> +		return ret;
> +	}
> +
> +	extcon_set_property_capability(type_c->edev, EXTCON_USB,
> +				       EXTCON_PROP_USB_VBUS);
> +	extcon_set_property_capability(type_c->edev, EXTCON_USB,
> +				       EXTCON_PROP_USB_TYPEC_POLARITY);
> +	extcon_set_property_capability(type_c->edev, EXTCON_USB,
> +				       EXTCON_PROP_USB_SS);
> +
> +	extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
> +				       EXTCON_PROP_USB_VBUS);
> +	extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
> +				       EXTCON_PROP_USB_TYPEC_POLARITY);
> +	extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
> +				       EXTCON_PROP_USB_SS);
> +
> +	return ret;
> +}
> +
> +static int extcon_rtk_type_c_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct type_c_data *type_c;
> +	const struct type_c_cfg *type_c_cfg;
> +	unsigned int gpio;
> +	int ret = 0;
> +
> +	type_c = devm_kzalloc(dev, sizeof(*type_c), GFP_KERNEL);
> +	if (!type_c)
> +		return -ENOMEM;
> +
> +	type_c->reg_base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(type_c->reg_base))
> +		return PTR_ERR(type_c->reg_base);
> +
> +	type_c->dev = dev;
> +
> +	type_c->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> +	if (type_c->irq <= 0) {
> +		dev_err(&pdev->dev, "Type C driver with no IRQ. Check %s setup!\n",
> +			dev_name(&pdev->dev));
> +		ret = -ENODEV;
> +		goto err1;
> +	}
> +
> +	ret = devm_request_irq(dev, type_c->irq, type_c_detect_irq,
> +			       IRQF_SHARED, "type_c_detect", type_c);
> +
> +	spin_lock_init(&type_c->lock);
> +
> +	type_c->rd_ctrl_gpio = -1;
> +	if (soc_device_match(rtk_soc_kylin)) {
> +		gpio = of_get_named_gpio(dev->of_node, "realtek,rd-ctrl-gpio", 0);
> +		if (gpio_is_valid(gpio)) {
> +			type_c->rd_ctrl_gpio = gpio;
> +			dev_dbg(dev, "%s get rd-ctrl-gpio (id=%d) OK\n", __func__, gpio);
> +		} else {
> +			dev_err(dev, "Error rd_ctrl-gpio no found");
> +		}
> +	}
> +
> +	type_c_cfg = of_device_get_match_data(dev);
> +	if (!type_c_cfg) {
> +		dev_err(dev, "type_c config are not assigned!\n");
> +		return -EINVAL;
> +	}
> +
> +	type_c->type_c_cfg = devm_kzalloc(dev, sizeof(*type_c_cfg), GFP_KERNEL);
> +
> +	memcpy(type_c->type_c_cfg, type_c_cfg, sizeof(*type_c_cfg));
> +
> +	if (setup_type_c_parameter(type_c)) {
> +		dev_err(dev, "ERROR: %s to setup type c parameter!!", __func__);
> +		ret = -EINVAL;
> +		goto err1;
> +	}
> +
> +	INIT_DELAYED_WORK(&type_c->delayed_work, host_device_switch);
> +
> +	ret = extcon_rtk_type_c_init(type_c);
> +	if (ret) {
> +		dev_err(dev, "%s failed to init type_c\n", __func__);
> +		goto err1;
> +	}
> +
> +	platform_set_drvdata(pdev, type_c);
> +
> +	ret = extcon_rtk_type_c_edev_register(type_c);
> +
> +	create_debug_files(type_c);
> +
> +	return 0;
> +
> +err1:
> +	dev_err(&pdev->dev, "%s: Probe fail, %d\n", __func__, ret);
> +
> +	return ret;
> +}
> +
> +static void extcon_rtk_type_c_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct type_c_data *type_c = dev_get_drvdata(dev);
> +	u32 default_ctrl;
> +	unsigned long flags;
> +
> +	remove_debug_files(type_c);
> +
> +#ifdef CONFIG_TYPEC
> +	if (type_c->port) {
> +		typec_unregister_port(type_c->port);
> +		type_c->port = NULL;
> +	}
> +#endif
> +
> +	cancel_delayed_work_sync(&type_c->delayed_work);
> +	flush_delayed_work(&type_c->delayed_work);
> +	WARN_ON_ONCE(delayed_work_pending(&type_c->delayed_work));
> +
> +	spin_lock_irqsave(&type_c->lock, flags);
> +	/* disable interrupt */
> +	default_ctrl = readl(type_c->reg_base + USB_TYPEC_CTRL) &
> +		    DEBOUNCE_TIME_MASK;
> +	writel(default_ctrl, type_c->reg_base + USB_TYPEC_CTRL);
> +
> +	/* disable cc detect, rp, rd */
> +	writel(PLR_EN, type_c->reg_base + USB_TYPEC_CTRL_CC1_0);
> +	writel(0, type_c->reg_base + USB_TYPEC_CTRL_CC2_0);
> +
> +	spin_unlock_irqrestore(&type_c->lock, flags);
> +
> +	free_irq(type_c->irq, type_c);
> +}
> +
> +static const struct type_c_cfg rtd1295_type_c_cfg = {
> +	.parameter_ver = PARAMETER_V0,
> +	.cc_dfp_mode = CC_MODE_DFP_3_0,
> +	.cc1_param = { .rp_4p7k_code = 0xb,
> +		       .rp_36k_code = 0x17,
> +		       .rp_12k_code = 0x10,
> +		       .rd_code = 0,
> +		       .ra_code = 0,
> +		       .vref_2p6v = 0x0,
> +		       .vref_1p23v = 0x0,
> +		       .vref_0p8v = 0x3,
> +		       .vref_0p66v = 0x0,
> +		       .vref_0p4v = 0x0,
> +		       .vref_0p2v = 0x4,
> +		       .vref_1_1p6v = 0,
> +		       .vref_0_1p6v = 0 },
> +	.cc2_param = { .rp_4p7k_code = 0xc,
> +		       .rp_36k_code = 0x17,
> +		       .rp_12k_code = 0x12,
> +		       .rd_code = 0,
> +		       .ra_code = 0,
> +		       .vref_2p6v = 0x2,
> +		       .vref_1p23v = 0x0,
> +		       .vref_0p8v = 0x3,
> +		       .vref_0p66v = 0x0,
> +		       .vref_0p4v = 0x0,
> +		       .vref_0p2v = 0x5,
> +		       .vref_1_1p6v = 0,
> +		       .vref_0_1p6v = 0 },
> +	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> +	.use_defalut_parameter = false,
> +};
> +
> +static const struct type_c_cfg rtd1395_type_c_cfg = {
> +	.parameter_ver = PARAMETER_V0,
> +	.cc_dfp_mode = CC_MODE_DFP_3_0,
> +	.cc1_param = { .rp_4p7k_code = 0xc,
> +		       .rp_36k_code = 0xb,
> +		       .rp_12k_code = 0xe,
> +		       .rd_code = 0x10,
> +		       .ra_code = 0x0,
> +		       .vref_2p6v = 0x0,
> +		       .vref_1p23v = 0x1,
> +		       .vref_0p8v = 0x0,
> +		       .vref_0p66v = 0x0,
> +		       .vref_0p4v = 0x3,
> +		       .vref_0p2v = 0x0,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.cc2_param = { .rp_4p7k_code = 0xb,
> +		       .rp_36k_code = 0x9,
> +		       .rp_12k_code = 0xe,
> +		       .rd_code = 0xf,
> +		       .ra_code = 0x0,
> +		       .vref_2p6v = 0x1,
> +		       .vref_1p23v = 0x3,
> +		       .vref_0p8v = 0x3,
> +		       .vref_0p66v = 0x2,
> +		       .vref_0p4v = 0x3,
> +		       .vref_0p2v = 0x2,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> +	.use_defalut_parameter = false,
> +};
> +
> +static const struct type_c_cfg rtd1619_type_c_cfg = {
> +	.parameter_ver = PARAMETER_V0,
> +	.cc_dfp_mode = CC_MODE_DFP_3_0,
> +	.cc1_param = { .rp_4p7k_code = 0xc,
> +		       .rp_36k_code = 0xf,
> +		       .rp_12k_code = 0xe,
> +		       .rd_code = 0x11,
> +		       .ra_code = 0x0,
> +		       .vref_2p6v = 0x5,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0xa,
> +		       .vref_0p66v = 0xa,
> +		       .vref_0p4v = 0x3,
> +		       .vref_0p2v = 0x2,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.cc2_param = { .rp_4p7k_code = 0xc,
> +		       .rp_36k_code = 0xf,
> +		       .rp_12k_code = 0xe,
> +		       .rd_code = 0xf,
> +		       .ra_code = 0x0,
> +		       .vref_2p6v = 0x5,
> +		       .vref_1p23v = 0x8,
> +		       .vref_0p8v = 0xa,
> +		       .vref_0p66v = 0xa,
> +		       .vref_0p4v = 0x3,
> +		       .vref_0p2v = 0x2,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> +	.use_defalut_parameter = false,
> +};
> +
> +static const struct type_c_cfg rtd1319_type_c_cfg = {
> +	.parameter_ver = PARAMETER_V0,
> +	.cc_dfp_mode = CC_MODE_DFP_1_5,
> +	.cc1_param = { .rp_4p7k_code = 0x9,
> +		       .rp_36k_code = 0xe,
> +		       .rp_12k_code = 0x9,
> +		       .rd_code = 0x9,
> +		       .ra_code = 0x7,
> +		       .vref_2p6v = 0x3,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x7,
> +		       .vref_0p66v = 0x6,
> +		       .vref_0p4v = 0x2,
> +		       .vref_0p2v = 0x3,
> +		       .vref_1_1p6v = 0x4,
> +		       .vref_0_1p6v = 0x7 },
> +	.cc2_param = { .rp_4p7k_code = 0x8,
> +		       .rp_36k_code = 0xe,
> +		       .rp_12k_code = 0x9,
> +		       .rd_code = 0x9,
> +		       .ra_code = 0x7,
> +		       .vref_2p6v = 0x3,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x7,
> +		       .vref_0p66v = 0x6,
> +		       .vref_0p4v = 0x3,
> +		       .vref_0p2v = 0x3,
> +		       .vref_1_1p6v = 0x6,
> +		       .vref_0_1p6v = 0x7 },
> +	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> +	.use_defalut_parameter = false,
> +};
> +
> +static const struct type_c_cfg rtd1312c_type_c_cfg = {
> +	.parameter_ver = PARAMETER_V0,
> +	.cc_dfp_mode = CC_MODE_DFP_1_5,
> +	.cc1_param = { .rp_4p7k_code = 0xe,
> +		       .rp_36k_code = 0xc,
> +		       .rp_12k_code = 0xc,
> +		       .rd_code = 0xa,
> +		       .ra_code = 0x3,
> +		       .vref_2p6v = 0xa,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x7,
> +		       .vref_0p66v = 0x7,
> +		       .vref_0p4v = 0x4,
> +		       .vref_0p2v = 0x4,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.cc2_param = { .rp_4p7k_code = 0xe,
> +		       .rp_36k_code = 0xc,
> +		       .rp_12k_code = 0xc,
> +		       .rd_code = 0xa,
> +		       .ra_code = 0x3,
> +		       .vref_2p6v = 0xa,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x7,
> +		       .vref_0p66v = 0x7,
> +		       .vref_0p4v = 0x4,
> +		       .vref_0p2v = 0x4,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> +	.use_defalut_parameter = false,
> +};
> +
> +static const struct type_c_cfg rtd1619b_type_c_cfg = {
> +	.parameter_ver = PARAMETER_V1,
> +	.cc_dfp_mode = CC_MODE_DFP_1_5,
> +	.cc1_param = { .rp_4p7k_code = 0xf,
> +		       .rp_36k_code = 0xf,
> +		       .rp_12k_code = 0xf,
> +		       .rd_code = 0xf,
> +		       .ra_code = 0x7,
> +		       .vref_2p6v = 0x9,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x9,
> +		       .vref_0p66v = 0x8,
> +		       .vref_0p4v = 0x7,
> +		       .vref_0p2v = 0x9,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.cc2_param = { .rp_4p7k_code = 0xf,
> +		       .rp_36k_code = 0xf,
> +		       .rp_12k_code = 0xf,
> +		       .rd_code = 0xf,
> +		       .ra_code = 0x7,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x9,
> +		       .vref_0p66v = 0x8,
> +		       .vref_0p4v = 0x7,
> +		       .vref_0p2v = 0x8,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> +	.use_defalut_parameter = false,
> +};
> +
> +static const struct type_c_cfg rtd1319d_type_c_cfg = {
> +	.parameter_ver = PARAMETER_V1,
> +	.cc_dfp_mode = CC_MODE_DFP_1_5,
> +	.cc1_param = { .rp_4p7k_code = 0xe,
> +		       .rp_36k_code = 0x3,
> +		       .rp_12k_code = 0xe,
> +		       .rd_code = 0xf,
> +		       .ra_code = 0x6,
> +		       .vref_2p6v = 0x7,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x8,
> +		       .vref_0p66v = 0x7,
> +		       .vref_0p4v = 0x7,
> +		       .vref_0p2v = 0x7,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.cc2_param = { .rp_4p7k_code = 0xe,
> +		       .rp_36k_code = 0x3,
> +		       .rp_12k_code = 0xe,
> +		       .rd_code = 0xf,
> +		       .ra_code = 0x6,
> +		       .vref_2p6v = 0x7,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x8,
> +		       .vref_0p66v = 0x7,
> +		       .vref_0p4v = 0x7,
> +		       .vref_0p2v = 0x8,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> +	.use_defalut_parameter = false,
> +};
> +
> +static const struct type_c_cfg rtd1315e_type_c_cfg = {
> +	.parameter_ver = PARAMETER_V1,
> +	.cc_dfp_mode = CC_MODE_DFP_1_5,
> +	.cc1_param = { .rp_4p7k_code = 0xe,
> +		       .rp_36k_code = 0x3,
> +		       .rp_12k_code = 0xe,
> +		       .rd_code = 0xf,
> +		       .ra_code = 0x6,
> +		       .vref_2p6v = 0x7,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x8,
> +		       .vref_0p66v = 0x7,
> +		       .vref_0p4v = 0x7,
> +		       .vref_0p2v = 0x7,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.cc2_param = { .rp_4p7k_code = 0xe,
> +		       .rp_36k_code = 0x3,
> +		       .rp_12k_code = 0xe,
> +		       .rd_code = 0xf,
> +		       .ra_code = 0x6,
> +		       .vref_2p6v = 0x7,
> +		       .vref_1p23v = 0x7,
> +		       .vref_0p8v = 0x8,
> +		       .vref_0p66v = 0x7,
> +		       .vref_0p4v = 0x7,
> +		       .vref_0p2v = 0x8,
> +		       .vref_1_1p6v = 0x7,
> +		       .vref_0_1p6v = 0x7 },
> +	.debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> +	.use_defalut_parameter = false,
> +};
> +
> +static const struct of_device_id extcon_rtk_type_c_match[] = {
> +	{ .compatible = "realtek,rtd1295-type-c", .data = &rtd1295_type_c_cfg },
> +	{ .compatible = "realtek,rtd1312c-type-c", .data = &rtd1312c_type_c_cfg },
> +	{ .compatible = "realtek,rtd1315e-type-c", .data = &rtd1315e_type_c_cfg },
> +	{ .compatible = "realtek,rtd1319-type-c", .data = &rtd1319_type_c_cfg },
> +	{ .compatible = "realtek,rtd1319d-type-c", .data = &rtd1319d_type_c_cfg },
> +	{ .compatible = "realtek,rtd1395-type-c", .data = &rtd1395_type_c_cfg },
> +	{ .compatible = "realtek,rtd1619-type-c", .data = &rtd1619_type_c_cfg },
> +	{ .compatible = "realtek,rtd1619b-type-c", .data = &rtd1619b_type_c_cfg },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, extcon_rtk_type_c_match);
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int extcon_rtk_type_c_prepare(struct device *dev)
> +{
> +	struct type_c_data *type_c = dev_get_drvdata(dev);
> +	u32 default_ctrl;
> +	unsigned long flags;
> +
> +	cancel_delayed_work_sync(&type_c->delayed_work);
> +	flush_delayed_work(&type_c->delayed_work);
> +	WARN_ON_ONCE(delayed_work_pending(&type_c->delayed_work));
> +
> +	spin_lock_irqsave(&type_c->lock, flags);
> +	/* disable interrupt */
> +	default_ctrl = readl(type_c->reg_base + USB_TYPEC_CTRL) &
> +		    DEBOUNCE_TIME_MASK;
> +	writel(default_ctrl, type_c->reg_base + USB_TYPEC_CTRL);
> +
> +	/* disable cc detect, rp, rd */
> +	writel(PLR_EN, type_c->reg_base + USB_TYPEC_CTRL_CC1_0);
> +	writel(0, type_c->reg_base + USB_TYPEC_CTRL_CC2_0);
> +
> +	spin_unlock_irqrestore(&type_c->lock, flags);
> +
> +	return 0;
> +}
> +
> +static void extcon_rtk_type_c_complete(struct device *dev)
> +{
> +	/* nothing */
> +}
> +
> +static int extcon_rtk_type_c_suspend(struct device *dev)
> +{
> +	struct type_c_data *type_c = dev_get_drvdata(dev);
> +
> +	if (type_c->rd_ctrl_gpio != -1)

ditto.

> +		gpio_free(type_c->rd_ctrl_gpio);
> +
> +	return 0;
> +}
> +
> +static int extcon_rtk_type_c_resume(struct device *dev)
> +{
> +	struct type_c_data *type_c = dev_get_drvdata(dev);
> +
> +	extcon_rtk_type_c_init(type_c);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops extcon_rtk_type_c_pm_ops = {
> +	SET_LATE_SYSTEM_SLEEP_PM_OPS(extcon_rtk_type_c_suspend, extcon_rtk_type_c_resume)
> +	.prepare = extcon_rtk_type_c_prepare,
> +	.complete = extcon_rtk_type_c_complete,
> +};
> +
> +#define DEV_PM_OPS	(&extcon_rtk_type_c_pm_ops)
> +#else
> +#define DEV_PM_OPS	NULL
> +#endif /* CONFIG_PM_SLEEP */
> +
> +static struct platform_driver extcon_rtk_type_c_driver = {
> +	.probe		= extcon_rtk_type_c_probe,
> +	.remove_new	= extcon_rtk_type_c_remove,
> +	.driver		= {
> +		.name	= "extcon-rtk-type_c",
> +		.of_match_table = extcon_rtk_type_c_match,
> +		.pm = DEV_PM_OPS,
> +	},
> +};
> +
> +module_platform_driver(extcon_rtk_type_c_driver);
> +
> +MODULE_DESCRIPTION("Realtek Extcon Type C driver");
> +MODULE_ALIAS("platform:extcon-rtk-type-c");
> +MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
> +MODULE_LICENSE("GPL");

-- 
Best Regards,
Samsung Electronics
Chanwoo Choi


^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-24 19:43 ` Chanwoo Choi
@ 2023-08-25  9:39   ` Stanley Chang[昌育德]
  2023-08-29 11:15   ` Stanley Chang[昌育德]
  1 sibling, 0 replies; 19+ messages in thread
From: Stanley Chang[昌育德] @ 2023-08-25  9:39 UTC (permalink / raw)
  To: Chanwoo Choi, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Chanwoo,

> 
> Almost code looks good to me. I add some comment below. Please check
> them.
> 
Thanks for your review.
> 
> On 23. 8. 22. 19:28, Stanley Chang wrote:
> > This patch adds the extcon driver for Realtek DHC (digital home center)
> > RTD SoCs type-c module. This can be used to detect whether the port is
> > configured as a downstream or upstream facing port. And notify the status
> > of extcon to listeners.
> >
> > Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
> > ---
> >  drivers/extcon/Kconfig             |    9 +
> >  drivers/extcon/Makefile            |    1 +
> >  drivers/extcon/extcon-rtk-type-c.c | 1799
> ++++++++++++++++++++++++++++
> >  3 files changed, 1809 insertions(+)
> >  create mode 100644 drivers/extcon/extcon-rtk-type-c.c
> >
> > diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
> > index 0ef1971d22bb..d670434321f2 100644
> > --- a/drivers/extcon/Kconfig
> > +++ b/drivers/extcon/Kconfig
> > @@ -190,4 +190,13 @@ config EXTCON_USBC_TUSB320
> >         Say Y here to enable support for USB Type C cable detection
> extcon
> >         support using a TUSB320.
> >
> > +config EXTCON_RTK_TYPE_C
> > +     tristate "Realtek RTD SoC extcon Type-C Driver"
> > +     depends on ARCH_REALTEK || COMPILE_TEST
> > +     help
> > +       Say Y here to enable extcon support for USB Type C cable detection
> > +       when using the Realtek RTD SoC USB Type-C port.
> > +       The DHC (Digital Home Hub) RTD series SoC contains a type c
> module.
> > +       This driver will detect the status of the type-c port.
> > +
> >  endif
> > diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
> > index 1b390d934ca9..f779adb5e4c7 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_RTK_TYPE_C) += extcon-rtk-type-c.o
> > diff --git a/drivers/extcon/extcon-rtk-type-c.c
> b/drivers/extcon/extcon-rtk-type-c.c
> > new file mode 100644
> > index 000000000000..04d4d5128bdb
> > --- /dev/null
> > +++ b/drivers/extcon/extcon-rtk-type-c.c
> > @@ -0,0 +1,1799 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + *  * extcon-rtk-type-c.c - Realtek Extcon Type C driver
> > + *
> > + * Copyright (C) 2023 Realtek Semiconductor Corporation
> > + *
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/kernel.h>
> > +#include <linux/slab.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_gpio.h>
> > +#include <linux/io.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/syscalls.h>
> > +#include <linux/suspend.h>
> > +#include <linux/debugfs.h>
> > +#include <linux/extcon.h>
> > +#include <linux/extcon-provider.h>
> > +#include <linux/sys_soc.h>
> > +#include <linux/nvmem-consumer.h>
> > +#include <linux/usb/otg.h>
> > +#include <linux/usb/typec.h>
> > +
> > +struct cc_param {
> > +     u32 rp_4p7k_code;
> > +     u32 rp_36k_code;
> > +     u32 rp_12k_code;
> > +     u32 rd_code;
> > +     u32 ra_code;
> > +     u32 vref_2p6v;
> > +     u32 vref_1p23v;
> > +     u32 vref_0p8v;
> > +     u32 vref_0p66v;
> > +     u32 vref_0p4v;
> > +     u32 vref_0p2v;
> > +     u32 vref_1_1p6v;
> > +     u32 vref_0_1p6v;
> > +};
> > +
> > +struct type_c_cfg {
> > +     int parameter_ver; /* Parameter version */
> > +     int cc_dfp_mode;
> > +     struct cc_param cc1_param;
> > +     struct cc_param cc2_param;
> > +
> > +     u32 debounce_val;
> > +     bool use_defalut_parameter;
> > +};
> > +
> > +struct type_c_data {
> > +     void __iomem *reg_base;
> > +     struct device *dev;
> > +     struct extcon_dev *edev;
> > +
> > +     u32 irq;
> > +
> > +     /* rd control GPIO only for rtd1295 */
> > +     unsigned int rd_ctrl_gpio;
> > +
> > +     /* Parameters */
> > +     struct type_c_cfg *type_c_cfg;
> > +     u32 dfp_mode_rp_en;
> > +     u32 ufp_mode_rd_en;
> > +     u32 cc1_code;
> > +     u32 cc2_code;
> > +     u32 cc1_vref;
> > +     u32 cc2_vref;
> > +     u32 debounce; /* 1b,1us 7f,4.7us */
> > +
> > +     /* type_c state */
> > +     int connect_change;
> > +#define CONNECT_CHANGE 1
> > +#define CONNECT_NO_CHANGE 0
> > +     int cc_mode; /* cc is host or device */
> > +#define IN_HOST_MODE 0x10
> > +#define IN_DEVICE_MODE 0x20
> > +     int is_attach;
> > +#define IN_ATTACH 1
> > +#define TO_ATTACH 1
> > +#define IN_DETACH 0
> > +#define TO_DETACH 0
> > +     int at_cc1;
> > +#define AT_CC1 1
> > +#define AT_CC2 0
> > +
> > +     u32 int_status;
> > +     u32 cc_status;
> > +     /* protect the data member */
> > +     spinlock_t lock;
> > +     struct delayed_work delayed_work;
> > +
> > +     bool rd_en_at_first;
> > +
> > +     struct dentry *debug_dir;
> > +
> > +#ifdef CONFIG_TYPEC
> > +     struct typec_port *port;
> > +#endif /* CONFIG_TYPEC */
> > +};
> > +
> > +/* Type C register offset */
> > +#define USB_TYPEC_CTRL_CC1_0 0x0
> > +#define USB_TYPEC_CTRL_CC1_1 0x4
> > +#define USB_TYPEC_CTRL_CC2_0 0x8
> > +#define USB_TYPEC_CTRL_CC2_1 0xC
> > +#define USB_TYPEC_STS        0x10
> > +#define USB_TYPEC_CTRL       0x14
> > +#define USB_DBUS_PWR_CTRL    0x18
> 
> nitpick.
> Above defintions uses 'space' to keep the left-aligned of value.
> But, below defintions doesn't keep the left-aligned of value.
> 
> I recommend that you better to use the same style for the readability.

Ok, I will revise.

> > +
> > +#define ENABLE_CC1 0x1
> > +#define ENABLE_CC2 0x2
> > +#define DISABLE_CC 0x0
> > +
> > +/* Bit mapping USB_TYPEC_CTRL_CC1_0 and USB_TYPEC_CTRL_CC2_0 */
> > +#define PLR_EN BIT(29)
> > +#define CC_SWITCH_MASK (BIT(29) | BIT(28) | BIT(27))
> > +#define CC_CODE_MASK (0xfffff << 7)
> > +#define rp4pk_code(val) ((0x1f & (val)) << 22)
> > +#define code_rp4pk(val) (((val) >> 22) & 0x1f)
> > +#define rp36k_code(val) ((0x1f & (val)) << 17)
> > +#define code_rp36k(val) (((val) >> 17) & 0x1f)
> > +#define rp12k_code(val) ((0x1f & (val)) << 12)
> > +#define code_rp12k(val) (((val) >> 12) & 0x1f)
> > +#define rd_code(val) ((0x1f & (val)) << 7)
> > +#define code_rd(val) (((val) >> 7) & 0x1f)
> > +#define dfp_mode(val) ((0x3 & (val)) << 5)
> > +#define EN_RP4P7K BIT(4)
> > +#define EN_RP36K BIT(3)
> > +#define EN_RP12K BIT(2)
> > +#define EN_RD BIT(1)
> > +#define EN_CC_DET BIT(0)
> > +
> > +#define CC_MODE_UFP 0x0
> > +#define CC_MODE_DFP_USB 0x1
> > +#define CC_MODE_DFP_1_5 0x2
> > +#define CC_MODE_DFP_3_0 0x3
> > +
> > +/*
> > + * PARAMETER_V0:
> > + *  Realtek Kylin    rtd1295
> > + *  Realtek Hercules rtd1395
> > + *  Realtek Thor     rtd1619
> > + *  Realtek Hank     rtd1319
> > + *  Realtek Groot    rtd1312c
> > + * PARAMETER_V1:
> > + *  Realtek Stark    rtd1619b
> > + *  Realtek Parker   rtd1319d
> > + *  Realtek Danvers  rtd1315e
> > + */
> > +enum parameter_version {
> > +     PARAMETER_V0 = 0,
> > +     PARAMETER_V1 = 1,
> > +};
> > +
> > +/* Bit mapping USB_TYPEC_CTRL_CC1_1 and USB_TYPEC_CTRL_CC2_1 */
> > +#define V0_vref_2p6v(val) ((0xf & (val)) << 26) /* Bit 29 for groot */
> > +#define V0_vref_1p23v(val) ((0xf & (val)) << 22)
> > +#define V0_vref_0p8v(val) ((0xf & (val)) << 18)
> > +#define V0_vref_0p66v(val) ((0xf & (val)) << 14)
> > +#define V0_vref_0p4v(val) ((0x7 & (val)) << 11)
> > +#define V0_vref_0p2v(val) ((0x7 & (val)) << 8)
> > +#define V0_vref_1_1p6v(val) ((0xf & (val)) << 4)
> > +#define V0_vref_0_1p6v(val) ((0xf & (val)) << 0)
> > +
> > +#define V0_decode_2p6v(val) (((val) >> 26) & 0xf) /* Bit 29 for groot */
> > +#define V0_decode_1p23v(val) (((val) >> 22) & 0xf)
> > +#define V0_decode_0p8v(val) (((val) >> 18) & 0xf)
> > +#define V0_decode_0p66v(val) (((val) >> 14) & 0xf)
> > +#define V0_decode_0p4v(val) (((val) >> 11) & 0x7)
> > +#define V0_decode_0p2v(val) (((val) >> 8) & 0x7)
> > +#define V0_decode_1_1p6v(val) (((val) >> 4) & 0xf)
> > +#define V0_decode_0_1p6v(val) (((val) >> 0) & 0xf)
> > +
> > +/* new Bit mapping USB_TYPEC_CTRL_CC1_1 and
> USB_TYPEC_CTRL_CC2_1 */
> > +#define V1_vref_2p6v(val) ((0xf & (val)) << 28)
> > +#define V1_vref_1p23v(val) ((0xf & (val)) << 24)
> > +#define V1_vref_0p8v(val) ((0xf & (val)) << 20)
> > +#define V1_vref_0p66v(val) ((0xf & (val)) << 16)
> > +#define V1_vref_0p4v(val) ((0xf & (val)) << 12)
> > +#define V1_vref_0p2v(val) ((0xf & (val)) << 8)
> > +#define V1_vref_1_1p6v(val) ((0xf & (val)) << 4)
> > +#define V1_vref_0_1p6v(val) ((0xf & (val)) << 0)
> > +
> > +#define V1_decode_2p6v(val) (((val) >> 28) & 0xf)
> > +#define V1_decode_1p23v(val) (((val) >> 24) & 0xf)
> > +#define V1_decode_0p8v(val) (((val) >> 20) & 0xf)
> > +#define V1_decode_0p66v(val) (((val) >> 16) & 0xf)
> > +#define V1_decode_0p4v(val) (((val) >> 12) & 0xf)
> > +#define V1_decode_0p2v(val) (((val) >> 8) & 0xf)
> > +#define V1_decode_1_1p6v(val) (((val) >> 4) & 0xf)
> > +#define V1_decode_0_1p6v(val) (((val) >> 0) & 0xf)
> > +
> > +/* Bit mapping USB_TYPEC_STS */
> > +#define DET_STS 0x7
> > +#define CC1_DET_STS (DET_STS)
> > +#define CC2_DET_STS (DET_STS << 3)
> > +#define DET_STS_RA 0x1
> > +#define DET_STS_RD 0x3
> > +#define DET_STS_RP 0x1
> > +#define CC1_DET_STS_RA (DET_STS_RA)
> > +#define CC1_DET_STS_RD (DET_STS_RD)
> > +#define CC1_DET_STS_RP (DET_STS_RP)
> > +#define CC2_DET_STS_RA (DET_STS_RA << 3)
> > +#define CC2_DET_STS_RD (DET_STS_RD << 3)
> > +#define CC2_DET_STS_RP (DET_STS_RP << 3)
> > +
> > +/* Bit mapping USB_TYPEC_CTRL */
> > +#define CC2_INT_EN BIT(11)
> > +#define CC1_INT_EN BIT(10)
> > +#define CC2_INT_STS BIT(9)
> > +#define CC1_INT_STS BIT(8)
> > +#define DEBOUNCE_TIME_MASK 0xff
> > +#define DEBOUNCE_EN BIT(0)
> > +#define ENABLE_TYPE_C_DETECT (CC1_INT_EN | CC2_INT_EN)
> > +#define ALL_CC_INT_STS (CC1_INT_STS | CC2_INT_STS)
> > +
> > +/* Parameter */
> > +#define DETECT_TIME 50 /* ms */
> > +
> > +static const unsigned int usb_type_c_cable[] = {
> > +     EXTCON_USB,
> > +     EXTCON_USB_HOST,
> > +     EXTCON_NONE,
> > +};
> > +
> > +enum usb_data_roles {
> > +     DR_NONE,
> > +     DR_HOST,
> > +     DR_DEVICE,
> > +};
> > +
> > +static const struct soc_device_attribute rtk_soc_kylin[] = {
> > +     { .family = "Realtek Kylin", },
> > +     { /* empty */ }
> > +};
> > +
> > +static int rtd129x_switch_type_c_plug_config(struct type_c_data *type_c,
> > +                                          int dr_mode, int cc)
> > +{
> > +     void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
> > +     int val_cc;
> > +
> > +#define TYPE_C_EN_SWITCH BIT(29)
> > +#define TYPE_C_TXRX_SEL (BIT(28) | BIT(27))
> > +#define TYPE_C_SWITCH_MASK (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
> > +#define TYPE_C_ENABLE_CC1 TYPE_C_EN_SWITCH
> > +#define TYPE_C_ENABLE_CC2 (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
> > +#define TYPE_C_DISABLE_CC ~TYPE_C_SWITCH_MASK
> > +
> > +     val_cc = readl(reg);
> 
> I'd like you to use regmap interface to access the register
> by using regmap_read, regmap_write. You can create the regmap instance
> via devm_regmap_init_mmio() on probe instead of using 'type_c->reg_base'
> at the multipe point.
> 
> For example,
>         struct regmap_config rtk_regmap_config = {
>                 .reg_bits = 32,
>                 .val_bits = 32,
>         };
> 
>         void __iomem *base;
> 
>         base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
>         if (IS_ERR(base))
>                 return PTR_ERR(base);
> 
>         regmap = devm_regmap_init_mmio(dev, base,
> &rtk_regmap_config);
> 
>         ---
> 
>         And then just call regmap_read without any calculation between
>         base address and specific register.
> 
>         regmap_read(regmap, USB_TYPEC_CTRL_CC1_0)

I will study this method.

> 
> > +     val_cc &= ~TYPE_C_SWITCH_MASK;
> > +
> > +     if (cc == DISABLE_CC) {
> > +             val_cc &= TYPE_C_DISABLE_CC;
> > +     } else if (cc == ENABLE_CC1) {
> > +             val_cc |= TYPE_C_ENABLE_CC1;
> > +     } else if (cc == ENABLE_CC2) {
> > +             val_cc |= TYPE_C_ENABLE_CC2;
> > +     } else {
> > +             dev_err(type_c->dev, "%s: Error cc setting cc=0x%x\n",
> __func__, cc);
> > +             return -EINVAL;
> > +     }
> > +     writel(val_cc, reg);
> > +
> > +     mdelay(1);
> Maybe, it depends on h/w constraints. Better to explain the comment
> of why adding delay at here. Also, this patch uses mdelay/msleep at
> the multiple point. I recommend that add the comment of reason to add
> mdelay/msleep.

Ok, I will add.
> 
> > +
> > +     dev_dbg(type_c->dev, "%s: cc=0x%x val_cc=0x%x
> usb_typec_ctrl_cc1_0=0x%x\n",
> > +             __func__, cc, val_cc, readl(reg));
> > +
> > +     return 0;
> > +}
> > +
> > +static inline void switch_type_c_plug_config(struct type_c_data *type_c,
> > +                                          int dr_mode, int cc)
> > +{
> > +     int ret = 0;
> > +
> > +     if (soc_device_match(rtk_soc_kylin))
> > +             ret = rtd129x_switch_type_c_plug_config(type_c, dr_mode,
> cc);
> > +
> > +     if (ret < 0)
> > +             dev_err(type_c->dev, "%s: Error set type c plug config\n",
> > +                     __func__);
> > +}
> > +
> > +static void switch_type_c_dr_mode(struct type_c_data *type_c, int
> dr_mode, int cc)
> > +{
> > +     bool is_host = false;
> > +     bool is_device = false;
> > +     bool polarity = false;
> > +     bool vbus = false;
> > +     bool ss = true;
> > +
> > +     switch_type_c_plug_config(type_c, dr_mode, cc);
> > +     if (cc == ENABLE_CC2)
> > +             polarity = true;
> > +
> > +     switch (dr_mode) {
> > +     case USB_DR_MODE_HOST:
> > +             is_host = true;
> > +             break;
> > +     case USB_DR_MODE_PERIPHERAL:
> > +             is_device = true;
> > +             vbus = true;
> > +             break;
> > +     default:
> > +             dev_dbg(type_c->dev, "%s dr_mode=%d ==> no host or
> device\n",
> > +                     __func__, dr_mode);
> > +             break;
> > +     }
> > +
> > +     dev_dbg(type_c->dev, "%s is_host=%d is_device=%d vbus=%d
> polarity=%d\n",
> > +             __func__, is_host, is_device, vbus, polarity);
> > +
> > +     /* for EXTCON_USB device mode */
> > +     extcon_set_state(type_c->edev, EXTCON_USB, is_device);
> > +     extcon_set_property(type_c->edev, EXTCON_USB,
> > +                         EXTCON_PROP_USB_VBUS,
> > +                         (union extcon_property_value)(int)vbus);
> > +     extcon_set_property(type_c->edev, EXTCON_USB,
> > +                         EXTCON_PROP_USB_TYPEC_POLARITY,
> > +                         (union extcon_property_value)(int)polarity);
> > +     extcon_set_property(type_c->edev, EXTCON_USB,
> > +                         EXTCON_PROP_USB_SS,
> > +                         (union extcon_property_value)(int)ss);
> > +
> > +     /* for EXTCON_USB_HOST host mode */
> > +     extcon_set_state(type_c->edev, EXTCON_USB_HOST, is_host);
> > +     extcon_set_property(type_c->edev, EXTCON_USB_HOST,
> > +                         EXTCON_PROP_USB_VBUS,
> > +                         (union extcon_property_value)(int)vbus);
> > +     extcon_set_property(type_c->edev, EXTCON_USB_HOST,
> > +                         EXTCON_PROP_USB_TYPEC_POLARITY,
> > +                         (union extcon_property_value)(int)polarity);
> > +     extcon_set_property(type_c->edev, EXTCON_USB_HOST,
> > +                         EXTCON_PROP_USB_SS,
> > +                         (union extcon_property_value)(int)ss);
> > +
> > +     /* sync EXTCON_USB and EXTCON_USB_HOST */
> > +     extcon_sync(type_c->edev, EXTCON_USB);
> > +     extcon_sync(type_c->edev, EXTCON_USB_HOST);
> > +
> > +#ifdef CONFIG_TYPEC> +       if (type_c->port) {
> > +             switch (dr_mode) {
> > +             case USB_DR_MODE_HOST:
> > +                     typec_set_data_role(type_c->port, TYPEC_HOST);
> > +                     typec_set_pwr_role(type_c->port,
> TYPEC_SOURCE);
> > +                     break;
> > +             case USB_DR_MODE_PERIPHERAL:
> > +                     typec_set_data_role(type_c->port,
> TYPEC_DEVICE);
> > +                     typec_set_pwr_role(type_c->port, TYPEC_SINK);
> > +                     break;
> > +             default:
> > +                     dev_dbg(type_c->dev, "%s unknown
> dr_mode=%d\n",
> > +                             __func__, dr_mode);
> > +                     break;
> > +             }
> > +     }
> > +#endif
> > +}
> > +
> > +/* device attached/detached */
> > +static int device_attached(struct type_c_data *type_c, u32 cc)
> > +{
> > +     void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> > +
> > +     cancel_delayed_work(&type_c->delayed_work);
> > +
> > +     switch_type_c_dr_mode(type_c, USB_DR_MODE_HOST, cc);
> > +
> > +     writel(ENABLE_TYPE_C_DETECT | readl(reg), reg);
> > +
> > +     return 0;
> > +}
> 
> device_attached() funciton is same with host_connected()
> except for USR_BR_MODE_HOST, USB_DR_MODE_PERIPHERAL setting.
> 
> You can use only one function with 3rd paramer (dr_mode) as following
> in order to reduce the duplicated code.
> For example,
> static int connector_attached(struct type_c_data *type_c, u32 cc, int
> dr_mode)

I will simplify this.

> > +
> > +static int device_detached(struct type_c_data *type_c, u32 cc)
> > +{
> > +     void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> > +
> > +     writel(~ENABLE_TYPE_C_DETECT & readl(reg), reg);
> > +
> > +     switch_type_c_dr_mode(type_c, 0, cc);
> > +
> > +     schedule_delayed_work(&type_c->delayed_work,
> msecs_to_jiffies(DETECT_TIME));
> > +
> > +     return 0;
> > +}
> 
> device_detached is perfectly same with host_disconnected.
> You can use the only one function to reduce the duplicated code
> 
> > +
> > +/* host connect/disconnect*/
> > +static int host_connected(struct type_c_data *type_c, u32 cc)
> > +{
> > +     void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> > +
> > +     cancel_delayed_work(&type_c->delayed_work);
> > +
> > +     switch_type_c_dr_mode(type_c, USB_DR_MODE_PERIPHERAL, cc);
> > +
> > +     writel(ENABLE_TYPE_C_DETECT | readl(reg), reg);
> > +     return 0;
> > +}
> > +
> > +static int host_disconnected(struct type_c_data *type_c, u32 cc)
> > +{
> > +     void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> > +
> > +     writel(~ENABLE_TYPE_C_DETECT & readl(reg), reg);
> > +
> > +     switch_type_c_dr_mode(type_c, 0, cc);
> > +
> > +     schedule_delayed_work(&type_c->delayed_work,
> msecs_to_jiffies(DETECT_TIME));
> > +
> > +     return 0;
> > +}
> > +
> > +/* detect host device switch */
> > +static int __detect_host_device(struct type_c_data *type_c, u32
> rp_or_rd_en)
> > +{
> > +     struct device *dev = type_c->dev;
> > +     void __iomem *reg_base = type_c->reg_base;
> > +     unsigned int gpio = type_c->rd_ctrl_gpio;
> > +     u32 cc1_config, cc2_config, default_ctrl;
> > +     u32 cc1_switch = 0;
> > +
> > +     default_ctrl = readl(reg_base + USB_TYPEC_CTRL) &
> DEBOUNCE_TIME_MASK;
> > +     writel(default_ctrl, reg_base + USB_TYPEC_CTRL);
> > +
> > +     cc1_config = readl(reg_base + USB_TYPEC_CTRL_CC1_0);
> > +     cc2_config = readl(reg_base + USB_TYPEC_CTRL_CC2_0);
> > +
> > +     cc1_config &= ~EN_CC_DET;
> > +     cc2_config &= ~EN_CC_DET;
> > +     writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
> > +     writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
> > +
> > +     if (soc_device_match(rtk_soc_kylin))
> > +             cc1_switch = cc1_config & CC_SWITCH_MASK;
> > +
> > +     cc1_config &= CC_CODE_MASK;
> > +     cc1_config |= rp_or_rd_en | cc1_switch;
> > +     cc2_config &= CC_CODE_MASK;
> > +     cc2_config |= rp_or_rd_en;
> > +     writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
> > +     writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
> > +
> > +     /* For kylin to disable external rd control gpio */
> > +     if (soc_device_match(rtk_soc_kylin)) {
> > +             if (gpio != -1 && gpio_is_valid(gpio)) {
> > +                     if (gpio_direction_output(gpio, 1))
> > +                             dev_err(dev, "%s ERROR rd_ctrl_gpio=1
> fail\n", __func__);
> > +             }
> > +     }
> > +
> > +     cc1_config |= EN_CC_DET;
> > +     cc2_config |= EN_CC_DET;
> > +     writel(cc1_config, reg_base + USB_TYPEC_CTRL_CC1_0);
> > +     writel(cc2_config, reg_base + USB_TYPEC_CTRL_CC2_0);
> > +
> > +     return 0;
> > +}
> > +
> > +static int detect_device(struct type_c_data *type_c)
> > +{
> > +     return __detect_host_device(type_c, type_c->dfp_mode_rp_en);
> > +}
> > +
> > +static int detect_host(struct type_c_data *type_c)
> > +{
> > +     return __detect_host_device(type_c, type_c->ufp_mode_rd_en);
> > +}
> > +
> > +static int host_device_switch_detection(struct type_c_data *type_c)
> > +{
> > +     if (type_c->cc_mode == IN_HOST_MODE) {
> > +             type_c->cc_mode = IN_DEVICE_MODE;
> > +             detect_host(type_c);
> > +     } else {
> > +             type_c->cc_mode = IN_HOST_MODE;
> > +             detect_device(type_c);
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int detect_type_c_state(struct type_c_data *type_c)
> > +{
> > +     struct device *dev = type_c->dev;
> > +     void __iomem *reg_base = type_c->reg_base;
> > +     u32 int_status, cc_status, cc_status_check;
> > +     unsigned long flags;
> > +
> > +     spin_lock_irqsave(&type_c->lock, flags);
> > +
> > +     int_status = readl(reg_base + USB_TYPEC_CTRL);
> > +     cc_status = readl(reg_base + USB_TYPEC_STS);
> > +
> > +     type_c->connect_change = CONNECT_NO_CHANGE;
> > +
> > +     switch (type_c->cc_mode | type_c->is_attach) {
> > +     case IN_HOST_MODE | IN_ATTACH:
> > +             if (((cc_status & CC1_DET_STS) == CC1_DET_STS) &&
> type_c->at_cc1 == AT_CC1) {
> > +                     dev_dbg(dev, "IN host mode and cc1 device
> detach (cc_status=0x%x)",
> > +                             cc_status);
> > +                     type_c->is_attach = TO_DETACH;
> > +                     type_c->connect_change = CONNECT_CHANGE;
> > +             } else if (((cc_status & CC2_DET_STS) == CC2_DET_STS) &&
> > +                        type_c->at_cc1 == AT_CC2) {
> > +                     dev_dbg(dev, "IN host mode and cc2 device
> detach (cc_status=0x%x)",
> > +                             cc_status);
> > +                     type_c->is_attach = TO_DETACH;
> > +                     type_c->connect_change = CONNECT_CHANGE;
> > +             }
> > +             break;
> > +     case IN_HOST_MODE | IN_DETACH:
> > +             cc_status_check = readl(reg_base + USB_TYPEC_STS);
> > +             if (cc_status_check != (CC1_DET_STS | CC2_DET_STS)) {
> > +                     if (in_interrupt()) {
> > +                             mdelay(300);
> > +                     } else {
> > +                             spin_unlock_irqrestore(&type_c->lock,
> flags);
> > +                             msleep(300);
> > +                             spin_lock_irqsave(&type_c->lock, flags);
> > +                     }
> 
> As I commented above, it seems that there are some hardware constrains
> which requires the some delay when changing the h/w state.
> I recommend that you need to add the comment of why adding the
> delays/sleep.

Ok, I will add.

> > +                     cc_status_check = readl(reg_base +
> USB_TYPEC_STS);
> > +             }
> > +             if (cc_status != cc_status_check) {
> > +                     dev_warn(dev, "IN_HOST_MODE: cc_status
> (0x%x) != cc_status_check (0x%x)\n",
> > +                              cc_status, cc_status_check);
> > +                     cc_status = readl(reg_base + USB_TYPEC_STS);
> > +             }
> > +
> > +             if ((cc_status & CC1_DET_STS) == CC1_DET_STS_RD) {
> > +                     dev_dbg(dev, "IN host mode and cc1 device
> attach (cc_status=0x%x)",
> > +                             cc_status);
> > +                     type_c->is_attach = TO_ATTACH;
> > +                     type_c->at_cc1 = AT_CC1;
> > +                     type_c->connect_change = CONNECT_CHANGE;
> > +             } else if ((cc_status & CC2_DET_STS) == CC2_DET_STS_RD)
> {
> > +                     dev_dbg(dev, "In host mode and cc2 device attach
> (cc_status=0x%x)",
> > +                             cc_status);
> > +                     type_c->is_attach = TO_ATTACH;
> > +                     type_c->at_cc1 = AT_CC2;
> > +                     type_c->connect_change = CONNECT_CHANGE;
> > +             }
> > +             break;
> > +     case IN_DEVICE_MODE | IN_ATTACH:
> > +             if ((cc_status & CC1_DET_STS) < CC1_DET_STS_RP ||
> > +                 (cc_status & CC2_DET_STS) < CC2_DET_STS_RP) {
> > +                     /* Add a sw debounce to filter cc signal sent from
> apple pd adapter */
> > +                     mdelay(5);
> > +                     cc_status_check = readl(reg_base +
> USB_TYPEC_STS);
> > +
> > +                     if (cc_status != cc_status_check) {
> > +                             dev_dbg(dev, "IN_DEVICE_MODE:
> cc_status (0x%x) != cc_status_check (0x%x) maybe use a pd adapter\n",
> > +                                     cc_status, cc_status_check);
> > +                             cc_status = cc_status_check;
> > +                     }
> > +             }
> > +
> > +             if ((cc_status & CC1_DET_STS) < CC1_DET_STS_RP &&
> type_c->at_cc1 == AT_CC1) {
> > +                     dev_dbg(dev, "IN device mode and cc1 host
> disconnect (cc_status=0x%x)",
> > +                             cc_status);
> > +                     type_c->is_attach = TO_DETACH;
> > +                     type_c->connect_change = CONNECT_CHANGE;
> > +             } else if ((cc_status & CC2_DET_STS) < CC2_DET_STS_RP
> &&
> > +                        type_c->at_cc1 == AT_CC2) {
> > +                     dev_dbg(dev, "IN device mode and cc2 host
> disconnect (cc_status=0x%x)",
> > +                             cc_status);
> > +                     type_c->is_attach = TO_DETACH;
> > +                     type_c->connect_change = CONNECT_CHANGE;
> > +             }
> > +             break;
> > +     case IN_DEVICE_MODE | IN_DETACH:
> > +             cc_status_check = readl(reg_base + USB_TYPEC_STS);
> > +             if (cc_status_check != 0x0) {
> > +                     if (in_interrupt()) {
> > +                             mdelay(300);
> > +                     } else {
> > +                             spin_unlock_irqrestore(&type_c->lock,
> flags);
> > +                             msleep(300);
> > +                             spin_lock_irqsave(&type_c->lock, flags);
> > +                     }
> 
> ditto.
> 
> > +                     cc_status_check = readl(reg_base +
> USB_TYPEC_STS);
> > +             }
> > +
> > +             if (cc_status != cc_status_check) {
> > +                     dev_warn(dev, "IN_DEVICE_MODE: cc_status
> (0x%x) != cc_status_check (0x%x)\n",
> > +                              cc_status, cc_status_check);
> > +                     cc_status = readl(reg_base + USB_TYPEC_STS);
> > +             }
> > +
> > +             if ((cc_status & CC1_DET_STS) >= CC1_DET_STS_RP) {
> > +                     dev_dbg(dev, "IN device mode and cc1 host
> connect (cc_status=0x%x)",
> > +                             cc_status);
> > +                     type_c->at_cc1 = AT_CC1;
> > +                     type_c->is_attach = TO_ATTACH;
> > +                     type_c->connect_change = CONNECT_CHANGE;
> > +             } else if ((cc_status & CC2_DET_STS) >= CC2_DET_STS_RP) {
> > +                     dev_dbg(dev, "IN device mode and cc2 host
> connect (cc_status=0x%x)",
> > +                             cc_status);
> > +                     type_c->at_cc1 = AT_CC2;
> > +                     type_c->is_attach = TO_ATTACH;
> > +                     type_c->connect_change = CONNECT_CHANGE;
> > +             }
> > +             break;
> > +     default:
> > +             dev_err(dev, "error host or device mode (cc_mode=%d,
> is_attach=%d) ",
> > +                     type_c->cc_mode, type_c->is_attach);
> > +     }
> > +
> > +     type_c->int_status = int_status;
> > +     type_c->cc_status = cc_status;
> > +
> > +     spin_unlock_irqrestore(&type_c->lock, flags);
> > +     return 0;
> > +}
> > +
> > +static void host_device_switch(struct work_struct *work)
> > +{
> > +     struct type_c_data *type_c = container_of(work, struct type_c_data,
> > +
> delayed_work.work);
> > +     struct device *dev = type_c->dev;
> > +     unsigned long flags;
> > +     int connect_change = 0;
> > +     int cc_mode = 0;
> > +     int is_attach = 0;
> > +     int at_cc1 = 0;
> > +
> > +     spin_lock_irqsave(&type_c->lock, flags);
> > +     if (type_c->connect_change)
> > +             connect_change = type_c->connect_change;
> > +     spin_unlock_irqrestore(&type_c->lock, flags);
> 
> Better to convert this code as following if type_c->connect_change is NULL,
> you can reduce the lock/unlok operation of spin_lock. As you knew, spin_lock is
> expensive.
> 
>         if (type_c->connect_change) {
>                 spin_lock_irqsave(&type_c->lock, flags);
>                 connect_change = type_c->connect_change;
>                 spin_unlock_irqrestore(&type_c->lock, flags);
>         }

I want to protect type_c->connect_change.
Moving the lock to the if statement loses its original purpose.

> > +
> > +     if (!connect_change)
> > +             detect_type_c_state(type_c);
> > +
> > +     spin_lock_irqsave(&type_c->lock, flags);
> > +     if (type_c->connect_change) {
> > +             connect_change = type_c->connect_change;
> > +             cc_mode = type_c->cc_mode;
> > +             is_attach = type_c->is_attach;
> > +             at_cc1 = type_c->at_cc1;
> > +             type_c->connect_change = CONNECT_NO_CHANGE;
> > +     } else {
> > +             host_device_switch_detection(type_c);
> > +
> > +             schedule_delayed_work(&type_c->delayed_work,
> msecs_to_jiffies(DETECT_TIME));
> > +     }
> > +     spin_unlock_irqrestore(&type_c->lock, flags);
> > +
> > +     if (connect_change) {
> 
> nitpick.
> You can reduce the depth of indentation when connector_change is 0
> by changing the code as following: If possible, I always to try
> to reduce the indentation depth for the readability.
> 
>         if (!connect_change)
>                 return
> 
>         dev_dbg(dev, "%s: usb cable connection change\n", __func__);
>         if (cc_mode == IN_HOST_MODE) {
>                 ......
> 
Ok, I will revise.
> > +             dev_dbg(dev, "%s: usb cable connection change\n",
> __func__);
> > +             if (cc_mode == IN_HOST_MODE) {
> > +                     if (is_attach && at_cc1)
> > +                             device_attached(type_c, ENABLE_CC1);
> > +                     else if (is_attach && !at_cc1)
> > +                             device_attached(type_c, ENABLE_CC2);
> > +                     else
> > +                             device_detached(type_c, DISABLE_CC);
> > +             } else if (cc_mode == IN_DEVICE_MODE) {
> > +                     if (is_attach && at_cc1)
> > +                             host_connected(type_c, ENABLE_CC1);
> > +                     else if (is_attach && !at_cc1)
> > +                             host_connected(type_c, ENABLE_CC2);
> > +                     else
> > +                             host_disconnected(type_c,
> DISABLE_CC);
> > +             } else {
> > +                     dev_err(dev, "Error: IN unknown mode %d to %s
> at %s (cc_status=0x%x)\n",
> > +                             cc_mode, is_attach ? "attach" :
> "detach",
> > +                             at_cc1 ? "cc1" : "cc2",
> type_c->cc_status);
> > +             }
> > +             dev_info(dev, "Connection change OK: IN %s mode to %s at
> %s (cc_status=0x%x)\n",
> > +                      cc_mode == IN_HOST_MODE ? "host" : "device",
> > +                      is_attach ? "attach" : "detach",
> > +                      at_cc1 ? "cc1" : "cc2", type_c->cc_status);
> > +     }
> > +}
> > +
> > +static irqreturn_t type_c_detect_irq(int irq, void *__data)
> > +{
> > +     struct type_c_data *type_c = (struct type_c_data *)__data;
> > +     struct device *dev = type_c->dev;
> > +     void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL;
> > +     unsigned long flags;
> > +
> > +     detect_type_c_state(type_c);
> > +
> > +     spin_lock_irqsave(&type_c->lock, flags);
> > +
> > +     if (type_c->connect_change) {
> > +             dev_dbg(dev, "%s: IN %s mode to %s (at %s interrupt)
> int_status=0x%x, cc_status=0x%x",
> > +                     __func__,
> > +                     type_c->cc_mode == IN_HOST_MODE ? "host" :
> "device",
> > +                     type_c->is_attach ? "attach" : "detach",
> > +                     type_c->at_cc1 ? "cc1" : "cc2",
> > +                     type_c->int_status, type_c->cc_status);
> > +
> > +             /* clear interrupt status */
> > +             writel(~ALL_CC_INT_STS & readl(reg), reg);
> > +
> > +             cancel_delayed_work(&type_c->delayed_work);
> > +             schedule_delayed_work(&type_c->delayed_work,
> msecs_to_jiffies(0));
> > +     } else {
> > +             static int local_count;
> > +
> > +             if (local_count++ > 10) {
> 
> It seems that clear interrupt status once every 10 times.
> I think that it is not generic. You need to add the comment of why trying to
> clear
> interrupt once every 10 times.

I will add the comment.
> > +                     /* clear interrupt status */
> > +                     writel(~ALL_CC_INT_STS & readl(reg), reg);
> > +                     local_count = 0;
> > +             }
> > +     }
> > +
> > +     spin_unlock_irqrestore(&type_c->lock, flags);
> > +
> > +     return IRQ_HANDLED;
> > +}
> 
> (snip)
> 
> > +
> > +static int extcon_rtk_type_c_init(struct type_c_data *type_c)
> > +{
> > +     struct device *dev = type_c->dev;
> > +     unsigned long flags;
> > +     void __iomem *reg;
> > +     int val;
> > +
> > +     if ((type_c->rd_ctrl_gpio != -1) &&
> 
> nitpick.
> After getting the gpio number by using of_get_named_gpio() function,
> type_c->rd_ctrl_gpio is error number which is returned of_get_named_gpio().
> 
> In order to specify the more correctly, how about changing it as following?
> Because I don't use the '-1' constant variable without any constant defintion.
> Someone cannot understand the meaning of '-1'.
> 
>         if (!(type_c->rd_ctrl_gpio < 0))

I will revise.

> > +         gpio_request(type_c->rd_ctrl_gpio, dev->of_node->name))
> > +             dev_err(dev, "%s ERROR Request rd_ctrl_gpio  (id=%d)
> fail\n",
> > +                     __func__, type_c->rd_ctrl_gpio);
> > +
> > +     spin_lock_irqsave(&type_c->lock, flags);
> > +
> > +     /* set parameter */
> > +     reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
> > +     val = readl(reg);
> > +     val = (~CC_CODE_MASK & val) | (type_c->cc1_code &
> CC_CODE_MASK);
> > +     writel(val, reg);
> > +
> > +     reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_0;
> > +     val = readl(reg);
> > +     val = (~CC_CODE_MASK & val) | (type_c->cc2_code &
> CC_CODE_MASK);
> > +
> > +     reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_1;
> > +     writel(type_c->cc1_vref, reg);
> > +
> > +     reg = type_c->reg_base + USB_TYPEC_CTRL_CC2_1;
> > +     writel(type_c->cc2_vref, reg);
> > +
> > +     reg = type_c->reg_base + USB_TYPEC_CTRL;
> > +     val = readl(reg);
> > +     val = (~DEBOUNCE_TIME_MASK & val) | (type_c->debounce &
> DEBOUNCE_TIME_MASK);
> > +
> > +     dev_info(dev, "First check USB_DR_MODE_PERIPHERAL");
> > +     type_c->cc_mode = IN_DEVICE_MODE;
> > +     type_c->is_attach = IN_DETACH;
> > +     type_c->connect_change = CONNECT_NO_CHANGE;
> > +
> > +     detect_host(type_c);
> > +
> > +     spin_unlock_irqrestore(&type_c->lock, flags);
> > +
> > +     schedule_delayed_work(&type_c->delayed_work,
> msecs_to_jiffies(0));
> > +
> > +#ifdef CONFIG_TYPEC
> 
> Don'n need to check 'CONFIG_TYPEC' defintion wiht ifdef.
> 'ifdef' might make the code more complicated.
> 
> If type_c is optional, just print warning message
> when typec_regiser_port returns error.
> 
> This patch is already check whether 'type_c->port' is NULL or not
> to handle the code related to typec.

If I remove check 'CONFIG_TYPEC' definition,
it will fail the build when CONFIG_TYPEC=n.
Another option is to select CONFIG_TYPEC in Kconfig.

> > +     if (!type_c->port) {
> 
> (snip)
> 
> > +
> > +             type_c->port = typec_register_port(type_c->dev,
> &typec_cap);
> > +             if (IS_ERR(type_c->port))
> > +                     return PTR_ERR(type_c->port);
> > +     }> +#endif /* CONFIG_TYPEC */
> > +
> > +     return 0;
> > +}
> > +
> > +static int extcon_rtk_type_c_edev_register(struct type_c_data *type_c)
> > +{
> > +     struct device *dev = type_c->dev;
> > +     int ret = 0;
> > +
> > +     type_c->edev = devm_extcon_dev_allocate(dev, usb_type_c_cable);
> > +     if (IS_ERR(type_c->edev)) {
> > +             dev_err(dev, "failed to allocate extcon device\n");
> > +             return -ENOMEM;
> > +     }
> > +
> > +     ret = devm_extcon_dev_register(dev, type_c->edev);
> > +     if (ret < 0) {
> > +             dev_err(dev, "failed to register extcon device\n");
> > +             return ret;
> > +     }
> > +
> > +     extcon_set_property_capability(type_c->edev, EXTCON_USB,
> > +                                    EXTCON_PROP_USB_VBUS);
> > +     extcon_set_property_capability(type_c->edev, EXTCON_USB,
> > +
> EXTCON_PROP_USB_TYPEC_POLARITY);
> > +     extcon_set_property_capability(type_c->edev, EXTCON_USB,
> > +                                    EXTCON_PROP_USB_SS);
> > +
> > +     extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
> > +                                    EXTCON_PROP_USB_VBUS);
> > +     extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
> > +
> EXTCON_PROP_USB_TYPEC_POLARITY);
> > +     extcon_set_property_capability(type_c->edev, EXTCON_USB_HOST,
> > +                                    EXTCON_PROP_USB_SS);
> > +
> > +     return ret;
> > +}
> > +
> > +static int extcon_rtk_type_c_probe(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct type_c_data *type_c;
> > +     const struct type_c_cfg *type_c_cfg;
> > +     unsigned int gpio;
> > +     int ret = 0;
> > +
> > +     type_c = devm_kzalloc(dev, sizeof(*type_c), GFP_KERNEL);
> > +     if (!type_c)
> > +             return -ENOMEM;
> > +
> > +     type_c->reg_base = devm_platform_ioremap_resource(pdev, 0);
> > +     if (IS_ERR(type_c->reg_base))
> > +             return PTR_ERR(type_c->reg_base);
> > +
> > +     type_c->dev = dev;
> > +
> > +     type_c->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> > +     if (type_c->irq <= 0) {
> > +             dev_err(&pdev->dev, "Type C driver with no IRQ. Check %s
> setup!\n",
> > +                     dev_name(&pdev->dev));
> > +             ret = -ENODEV;
> > +             goto err1;
> > +     }
> > +
> > +     ret = devm_request_irq(dev, type_c->irq, type_c_detect_irq,
> > +                            IRQF_SHARED, "type_c_detect", type_c);
> > +
> > +     spin_lock_init(&type_c->lock);
> > +
> > +     type_c->rd_ctrl_gpio = -1;
> > +     if (soc_device_match(rtk_soc_kylin)) {
> > +             gpio = of_get_named_gpio(dev->of_node,
> "realtek,rd-ctrl-gpio", 0);
> > +             if (gpio_is_valid(gpio)) {
> > +                     type_c->rd_ctrl_gpio = gpio;
> > +                     dev_dbg(dev, "%s get rd-ctrl-gpio (id=%d) OK\n",
> __func__, gpio);
> > +             } else {
> > +                     dev_err(dev, "Error rd_ctrl-gpio no found");
> > +             }
> > +     }
> > +
> > +     type_c_cfg = of_device_get_match_data(dev);
> > +     if (!type_c_cfg) {
> > +             dev_err(dev, "type_c config are not assigned!\n");
> > +             return -EINVAL;
> > +     }
> > +
> > +     type_c->type_c_cfg = devm_kzalloc(dev, sizeof(*type_c_cfg),
> GFP_KERNEL);
> > +
> > +     memcpy(type_c->type_c_cfg, type_c_cfg, sizeof(*type_c_cfg));
> > +
> > +     if (setup_type_c_parameter(type_c)) {
> > +             dev_err(dev, "ERROR: %s to setup type c parameter!!",
> __func__);
> > +             ret = -EINVAL;
> > +             goto err1;
> > +     }
> > +
> > +     INIT_DELAYED_WORK(&type_c->delayed_work, host_device_switch);
> > +
> > +     ret = extcon_rtk_type_c_init(type_c);
> > +     if (ret) {
> > +             dev_err(dev, "%s failed to init type_c\n", __func__);
> > +             goto err1;
> > +     }
> > +
> > +     platform_set_drvdata(pdev, type_c);
> > +
> > +     ret = extcon_rtk_type_c_edev_register(type_c);
> > +
> > +     create_debug_files(type_c);
> > +
> > +     return 0;
> > +
> > +err1:
> > +     dev_err(&pdev->dev, "%s: Probe fail, %d\n", __func__, ret);
> > +
> > +     return ret;
> > +}
> > +
> > +static void extcon_rtk_type_c_remove(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct type_c_data *type_c = dev_get_drvdata(dev);
> > +     u32 default_ctrl;
> > +     unsigned long flags;
> > +
> > +     remove_debug_files(type_c);
> > +
> > +#ifdef CONFIG_TYPEC
> > +     if (type_c->port) {
> > +             typec_unregister_port(type_c->port);
> > +             type_c->port = NULL;
> > +     }
> > +#endif
> > +
> > +     cancel_delayed_work_sync(&type_c->delayed_work);
> > +     flush_delayed_work(&type_c->delayed_work);
> > +     WARN_ON_ONCE(delayed_work_pending(&type_c->delayed_work));
> > +
> > +     spin_lock_irqsave(&type_c->lock, flags);
> > +     /* disable interrupt */
> > +     default_ctrl = readl(type_c->reg_base + USB_TYPEC_CTRL) &
> > +                 DEBOUNCE_TIME_MASK;
> > +     writel(default_ctrl, type_c->reg_base + USB_TYPEC_CTRL);
> > +
> > +     /* disable cc detect, rp, rd */
> > +     writel(PLR_EN, type_c->reg_base + USB_TYPEC_CTRL_CC1_0);
> > +     writel(0, type_c->reg_base + USB_TYPEC_CTRL_CC2_0);
> > +
> > +     spin_unlock_irqrestore(&type_c->lock, flags);
> > +
> > +     free_irq(type_c->irq, type_c);
> > +}
> > +
> > +static const struct type_c_cfg rtd1295_type_c_cfg = {
> > +     .parameter_ver = PARAMETER_V0,
> > +     .cc_dfp_mode = CC_MODE_DFP_3_0,
> > +     .cc1_param = { .rp_4p7k_code = 0xb,
> > +                    .rp_36k_code = 0x17,
> > +                    .rp_12k_code = 0x10,
> > +                    .rd_code = 0,
> > +                    .ra_code = 0,
> > +                    .vref_2p6v = 0x0,
> > +                    .vref_1p23v = 0x0,
> > +                    .vref_0p8v = 0x3,
> > +                    .vref_0p66v = 0x0,
> > +                    .vref_0p4v = 0x0,
> > +                    .vref_0p2v = 0x4,
> > +                    .vref_1_1p6v = 0,
> > +                    .vref_0_1p6v = 0 },
> > +     .cc2_param = { .rp_4p7k_code = 0xc,
> > +                    .rp_36k_code = 0x17,
> > +                    .rp_12k_code = 0x12,
> > +                    .rd_code = 0,
> > +                    .ra_code = 0,
> > +                    .vref_2p6v = 0x2,
> > +                    .vref_1p23v = 0x0,
> > +                    .vref_0p8v = 0x3,
> > +                    .vref_0p66v = 0x0,
> > +                    .vref_0p4v = 0x0,
> > +                    .vref_0p2v = 0x5,
> > +                    .vref_1_1p6v = 0,
> > +                    .vref_0_1p6v = 0 },
> > +     .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> > +     .use_defalut_parameter = false,
> > +};
> > +
> > +static const struct type_c_cfg rtd1395_type_c_cfg = {
> > +     .parameter_ver = PARAMETER_V0,
> > +     .cc_dfp_mode = CC_MODE_DFP_3_0,
> > +     .cc1_param = { .rp_4p7k_code = 0xc,
> > +                    .rp_36k_code = 0xb,
> > +                    .rp_12k_code = 0xe,
> > +                    .rd_code = 0x10,
> > +                    .ra_code = 0x0,
> > +                    .vref_2p6v = 0x0,
> > +                    .vref_1p23v = 0x1,
> > +                    .vref_0p8v = 0x0,
> > +                    .vref_0p66v = 0x0,
> > +                    .vref_0p4v = 0x3,
> > +                    .vref_0p2v = 0x0,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .cc2_param = { .rp_4p7k_code = 0xb,
> > +                    .rp_36k_code = 0x9,
> > +                    .rp_12k_code = 0xe,
> > +                    .rd_code = 0xf,
> > +                    .ra_code = 0x0,
> > +                    .vref_2p6v = 0x1,
> > +                    .vref_1p23v = 0x3,
> > +                    .vref_0p8v = 0x3,
> > +                    .vref_0p66v = 0x2,
> > +                    .vref_0p4v = 0x3,
> > +                    .vref_0p2v = 0x2,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> > +     .use_defalut_parameter = false,
> > +};
> > +
> > +static const struct type_c_cfg rtd1619_type_c_cfg = {
> > +     .parameter_ver = PARAMETER_V0,
> > +     .cc_dfp_mode = CC_MODE_DFP_3_0,
> > +     .cc1_param = { .rp_4p7k_code = 0xc,
> > +                    .rp_36k_code = 0xf,
> > +                    .rp_12k_code = 0xe,
> > +                    .rd_code = 0x11,
> > +                    .ra_code = 0x0,
> > +                    .vref_2p6v = 0x5,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0xa,
> > +                    .vref_0p66v = 0xa,
> > +                    .vref_0p4v = 0x3,
> > +                    .vref_0p2v = 0x2,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .cc2_param = { .rp_4p7k_code = 0xc,
> > +                    .rp_36k_code = 0xf,
> > +                    .rp_12k_code = 0xe,
> > +                    .rd_code = 0xf,
> > +                    .ra_code = 0x0,
> > +                    .vref_2p6v = 0x5,
> > +                    .vref_1p23v = 0x8,
> > +                    .vref_0p8v = 0xa,
> > +                    .vref_0p66v = 0xa,
> > +                    .vref_0p4v = 0x3,
> > +                    .vref_0p2v = 0x2,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> > +     .use_defalut_parameter = false,
> > +};
> > +
> > +static const struct type_c_cfg rtd1319_type_c_cfg = {
> > +     .parameter_ver = PARAMETER_V0,
> > +     .cc_dfp_mode = CC_MODE_DFP_1_5,
> > +     .cc1_param = { .rp_4p7k_code = 0x9,
> > +                    .rp_36k_code = 0xe,
> > +                    .rp_12k_code = 0x9,
> > +                    .rd_code = 0x9,
> > +                    .ra_code = 0x7,
> > +                    .vref_2p6v = 0x3,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x7,
> > +                    .vref_0p66v = 0x6,
> > +                    .vref_0p4v = 0x2,
> > +                    .vref_0p2v = 0x3,
> > +                    .vref_1_1p6v = 0x4,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .cc2_param = { .rp_4p7k_code = 0x8,
> > +                    .rp_36k_code = 0xe,
> > +                    .rp_12k_code = 0x9,
> > +                    .rd_code = 0x9,
> > +                    .ra_code = 0x7,
> > +                    .vref_2p6v = 0x3,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x7,
> > +                    .vref_0p66v = 0x6,
> > +                    .vref_0p4v = 0x3,
> > +                    .vref_0p2v = 0x3,
> > +                    .vref_1_1p6v = 0x6,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> > +     .use_defalut_parameter = false,
> > +};
> > +
> > +static const struct type_c_cfg rtd1312c_type_c_cfg = {
> > +     .parameter_ver = PARAMETER_V0,
> > +     .cc_dfp_mode = CC_MODE_DFP_1_5,
> > +     .cc1_param = { .rp_4p7k_code = 0xe,
> > +                    .rp_36k_code = 0xc,
> > +                    .rp_12k_code = 0xc,
> > +                    .rd_code = 0xa,
> > +                    .ra_code = 0x3,
> > +                    .vref_2p6v = 0xa,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x7,
> > +                    .vref_0p66v = 0x7,
> > +                    .vref_0p4v = 0x4,
> > +                    .vref_0p2v = 0x4,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .cc2_param = { .rp_4p7k_code = 0xe,
> > +                    .rp_36k_code = 0xc,
> > +                    .rp_12k_code = 0xc,
> > +                    .rd_code = 0xa,
> > +                    .ra_code = 0x3,
> > +                    .vref_2p6v = 0xa,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x7,
> > +                    .vref_0p66v = 0x7,
> > +                    .vref_0p4v = 0x4,
> > +                    .vref_0p2v = 0x4,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> > +     .use_defalut_parameter = false,
> > +};
> > +
> > +static const struct type_c_cfg rtd1619b_type_c_cfg = {
> > +     .parameter_ver = PARAMETER_V1,
> > +     .cc_dfp_mode = CC_MODE_DFP_1_5,
> > +     .cc1_param = { .rp_4p7k_code = 0xf,
> > +                    .rp_36k_code = 0xf,
> > +                    .rp_12k_code = 0xf,
> > +                    .rd_code = 0xf,
> > +                    .ra_code = 0x7,
> > +                    .vref_2p6v = 0x9,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x9,
> > +                    .vref_0p66v = 0x8,
> > +                    .vref_0p4v = 0x7,
> > +                    .vref_0p2v = 0x9,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .cc2_param = { .rp_4p7k_code = 0xf,
> > +                    .rp_36k_code = 0xf,
> > +                    .rp_12k_code = 0xf,
> > +                    .rd_code = 0xf,
> > +                    .ra_code = 0x7,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x9,
> > +                    .vref_0p66v = 0x8,
> > +                    .vref_0p4v = 0x7,
> > +                    .vref_0p2v = 0x8,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> > +     .use_defalut_parameter = false,
> > +};
> > +
> > +static const struct type_c_cfg rtd1319d_type_c_cfg = {
> > +     .parameter_ver = PARAMETER_V1,
> > +     .cc_dfp_mode = CC_MODE_DFP_1_5,
> > +     .cc1_param = { .rp_4p7k_code = 0xe,
> > +                    .rp_36k_code = 0x3,
> > +                    .rp_12k_code = 0xe,
> > +                    .rd_code = 0xf,
> > +                    .ra_code = 0x6,
> > +                    .vref_2p6v = 0x7,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x8,
> > +                    .vref_0p66v = 0x7,
> > +                    .vref_0p4v = 0x7,
> > +                    .vref_0p2v = 0x7,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .cc2_param = { .rp_4p7k_code = 0xe,
> > +                    .rp_36k_code = 0x3,
> > +                    .rp_12k_code = 0xe,
> > +                    .rd_code = 0xf,
> > +                    .ra_code = 0x6,
> > +                    .vref_2p6v = 0x7,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x8,
> > +                    .vref_0p66v = 0x7,
> > +                    .vref_0p4v = 0x7,
> > +                    .vref_0p2v = 0x8,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> > +     .use_defalut_parameter = false,
> > +};
> > +
> > +static const struct type_c_cfg rtd1315e_type_c_cfg = {
> > +     .parameter_ver = PARAMETER_V1,
> > +     .cc_dfp_mode = CC_MODE_DFP_1_5,
> > +     .cc1_param = { .rp_4p7k_code = 0xe,
> > +                    .rp_36k_code = 0x3,
> > +                    .rp_12k_code = 0xe,
> > +                    .rd_code = 0xf,
> > +                    .ra_code = 0x6,
> > +                    .vref_2p6v = 0x7,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x8,
> > +                    .vref_0p66v = 0x7,
> > +                    .vref_0p4v = 0x7,
> > +                    .vref_0p2v = 0x7,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .cc2_param = { .rp_4p7k_code = 0xe,
> > +                    .rp_36k_code = 0x3,
> > +                    .rp_12k_code = 0xe,
> > +                    .rd_code = 0xf,
> > +                    .ra_code = 0x6,
> > +                    .vref_2p6v = 0x7,
> > +                    .vref_1p23v = 0x7,
> > +                    .vref_0p8v = 0x8,
> > +                    .vref_0p66v = 0x7,
> > +                    .vref_0p4v = 0x7,
> > +                    .vref_0p2v = 0x8,
> > +                    .vref_1_1p6v = 0x7,
> > +                    .vref_0_1p6v = 0x7 },
> > +     .debounce_val = 0x7f, /* 1b,1us 7f,4.7us */
> > +     .use_defalut_parameter = false,
> > +};
> > +
> > +static const struct of_device_id extcon_rtk_type_c_match[] = {
> > +     { .compatible = "realtek,rtd1295-type-c", .data =
> &rtd1295_type_c_cfg },
> > +     { .compatible = "realtek,rtd1312c-type-c", .data =
> &rtd1312c_type_c_cfg },
> > +     { .compatible = "realtek,rtd1315e-type-c", .data =
> &rtd1315e_type_c_cfg },
> > +     { .compatible = "realtek,rtd1319-type-c", .data =
> &rtd1319_type_c_cfg },
> > +     { .compatible = "realtek,rtd1319d-type-c", .data =
> &rtd1319d_type_c_cfg },
> > +     { .compatible = "realtek,rtd1395-type-c", .data =
> &rtd1395_type_c_cfg },
> > +     { .compatible = "realtek,rtd1619-type-c", .data =
> &rtd1619_type_c_cfg },
> > +     { .compatible = "realtek,rtd1619b-type-c", .data =
> &rtd1619b_type_c_cfg },
> > +     {},
> > +};
> > +MODULE_DEVICE_TABLE(of, extcon_rtk_type_c_match);
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int extcon_rtk_type_c_prepare(struct device *dev)
> > +{
> > +     struct type_c_data *type_c = dev_get_drvdata(dev);
> > +     u32 default_ctrl;
> > +     unsigned long flags;
> > +
> > +     cancel_delayed_work_sync(&type_c->delayed_work);
> > +     flush_delayed_work(&type_c->delayed_work);
> > +     WARN_ON_ONCE(delayed_work_pending(&type_c->delayed_work));
> > +
> > +     spin_lock_irqsave(&type_c->lock, flags);
> > +     /* disable interrupt */
> > +     default_ctrl = readl(type_c->reg_base + USB_TYPEC_CTRL) &
> > +                 DEBOUNCE_TIME_MASK;
> > +     writel(default_ctrl, type_c->reg_base + USB_TYPEC_CTRL);
> > +
> > +     /* disable cc detect, rp, rd */
> > +     writel(PLR_EN, type_c->reg_base + USB_TYPEC_CTRL_CC1_0);
> > +     writel(0, type_c->reg_base + USB_TYPEC_CTRL_CC2_0);
> > +
> > +     spin_unlock_irqrestore(&type_c->lock, flags);
> > +
> > +     return 0;
> > +}
> > +
> > +static void extcon_rtk_type_c_complete(struct device *dev)
> > +{
> > +     /* nothing */
> > +}
> > +
> > +static int extcon_rtk_type_c_suspend(struct device *dev)
> > +{
> > +     struct type_c_data *type_c = dev_get_drvdata(dev);
> > +
> > +     if (type_c->rd_ctrl_gpio != -1)
> 
> ditto.
> 
> > +             gpio_free(type_c->rd_ctrl_gpio);
> > +
> > +     return 0;
> > +}
> > +
> > +static int extcon_rtk_type_c_resume(struct device *dev)
> > +{
> > +     struct type_c_data *type_c = dev_get_drvdata(dev);
> > +
> > +     extcon_rtk_type_c_init(type_c);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct dev_pm_ops extcon_rtk_type_c_pm_ops = {
> > +     SET_LATE_SYSTEM_SLEEP_PM_OPS(extcon_rtk_type_c_suspend,
> extcon_rtk_type_c_resume)
> > +     .prepare = extcon_rtk_type_c_prepare,
> > +     .complete = extcon_rtk_type_c_complete,
> > +};
> > +
> > +#define DEV_PM_OPS   (&extcon_rtk_type_c_pm_ops)
> > +#else
> > +#define DEV_PM_OPS   NULL
> > +#endif /* CONFIG_PM_SLEEP */
> > +
> > +static struct platform_driver extcon_rtk_type_c_driver = {
> > +     .probe          = extcon_rtk_type_c_probe,
> > +     .remove_new     = extcon_rtk_type_c_remove,
> > +     .driver         = {
> > +             .name   = "extcon-rtk-type_c",
> > +             .of_match_table = extcon_rtk_type_c_match,
> > +             .pm = DEV_PM_OPS,
> > +     },
> > +};
> > +
> > +module_platform_driver(extcon_rtk_type_c_driver);
> > +
> > +MODULE_DESCRIPTION("Realtek Extcon Type C driver");
> > +MODULE_ALIAS("platform:extcon-rtk-type-c");
> > +MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
> > +MODULE_LICENSE("GPL");
> 

Thanks,
Stanley

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-24 19:43 ` Chanwoo Choi
  2023-08-25  9:39   ` Stanley Chang[昌育德]
@ 2023-08-29 11:15   ` Stanley Chang[昌育德]
  2023-08-29 19:18     ` Chanwoo Choi
  1 sibling, 1 reply; 19+ messages in thread
From: Stanley Chang[昌育德] @ 2023-08-29 11:15 UTC (permalink / raw)
  To: Chanwoo Choi, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Chanwoo,

> > +static int rtd129x_switch_type_c_plug_config(struct type_c_data *type_c,
> > +                                          int dr_mode, int cc)
> > +{
> > +     void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
> > +     int val_cc;
> > +
> > +#define TYPE_C_EN_SWITCH BIT(29)
> > +#define TYPE_C_TXRX_SEL (BIT(28) | BIT(27))
> > +#define TYPE_C_SWITCH_MASK (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
> > +#define TYPE_C_ENABLE_CC1 TYPE_C_EN_SWITCH
> > +#define TYPE_C_ENABLE_CC2 (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
> > +#define TYPE_C_DISABLE_CC ~TYPE_C_SWITCH_MASK
> > +
> > +     val_cc = readl(reg);
> 
> I'd like you to use regmap interface to access the register
> by using regmap_read, regmap_write. You can create the regmap instance
> via devm_regmap_init_mmio() on probe instead of using 'type_c->reg_base'
> at the multipe point.
> 
> For example,
>         struct regmap_config rtk_regmap_config = {
>                 .reg_bits = 32,
>                 .val_bits = 32,
>         };
> 
>         void __iomem *base;
> 
>         base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
>         if (IS_ERR(base))
>                 return PTR_ERR(base);
> 
>         regmap = devm_regmap_init_mmio(dev, base,
> &rtk_regmap_config);
> 
>         ---
> 
>         And then just call regmap_read without any calculation between
>         base address and specific register.
> 
>         regmap_read(regmap, USB_TYPEC_CTRL_CC1_0)
> 

I studied mmio's regmap.

It only changed one encoding method. And simplifies the calculation between the base address and the specific register.
If the register is 32-bit aligned, other operations look the same as readl/writel.
I think regmap is more simplified if the read registers are not 32-bit aligned, e.g. nvmem read/write.

So it would be more intuitive for me to keep writel/readl here

> 
> > +     val_cc &= ~TYPE_C_SWITCH_MASK;
> > +
> > +     if (cc == DISABLE_CC) {
> > +             val_cc &= TYPE_C_DISABLE_CC;
> > +     } else if (cc == ENABLE_CC1) {
> > +             val_cc |= TYPE_C_ENABLE_CC1;
> > +     } else if (cc == ENABLE_CC2) {
> > +             val_cc |= TYPE_C_ENABLE_CC2;
> > +     } else {
> > +             dev_err(type_c->dev, "%s: Error cc setting cc=0x%x\n",
> __func__, cc);
> > +             return -EINVAL;
> > +     }
> > +     writel(val_cc, reg);
> > +

Thanks,
Stanley

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-29 11:15   ` Stanley Chang[昌育德]
@ 2023-08-29 19:18     ` Chanwoo Choi
  2023-08-30  3:59       ` Stanley Chang[昌育德]
  0 siblings, 1 reply; 19+ messages in thread
From: Chanwoo Choi @ 2023-08-29 19:18 UTC (permalink / raw)
  To: Stanley Chang[昌育德], MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Stanley,

On 23. 8. 29. 20:15, Stanley Chang[昌育德] wrote:
> Hi Chanwoo,
> 
>>> +static int rtd129x_switch_type_c_plug_config(struct type_c_data *type_c,
>>> +                                          int dr_mode, int cc)
>>> +{
>>> +     void __iomem *reg = type_c->reg_base + USB_TYPEC_CTRL_CC1_0;
>>> +     int val_cc;
>>> +
>>> +#define TYPE_C_EN_SWITCH BIT(29)
>>> +#define TYPE_C_TXRX_SEL (BIT(28) | BIT(27))
>>> +#define TYPE_C_SWITCH_MASK (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
>>> +#define TYPE_C_ENABLE_CC1 TYPE_C_EN_SWITCH
>>> +#define TYPE_C_ENABLE_CC2 (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
>>> +#define TYPE_C_DISABLE_CC ~TYPE_C_SWITCH_MASK
>>> +
>>> +     val_cc = readl(reg);
>>
>> I'd like you to use regmap interface to access the register
>> by using regmap_read, regmap_write. You can create the regmap instance
>> via devm_regmap_init_mmio() on probe instead of using 'type_c->reg_base'
>> at the multipe point.
>>
>> For example,
>>         struct regmap_config rtk_regmap_config = {
>>                 .reg_bits = 32,
>>                 .val_bits = 32,
>>         };
>>
>>         void __iomem *base;
>>
>>         base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
>>         if (IS_ERR(base))
>>                 return PTR_ERR(base);
>>
>>         regmap = devm_regmap_init_mmio(dev, base,
>> &rtk_regmap_config);
>>
>>         ---
>>
>>         And then just call regmap_read without any calculation between
>>         base address and specific register.
>>
>>         regmap_read(regmap, USB_TYPEC_CTRL_CC1_0)
>>
> 
> I studied mmio's regmap.
> 
> It only changed one encoding method. And simplifies the calculation between the base address and the specific register.

The regmap provides the consistent interface to access register
regardless of mmio/i2c/spi and so on. It is the advantage of regmap.

And regmap provides the like register dump via debugfs,
is able to specify the kind of register like writable, readable, volatile type.
It is possible to specify the more detailed register information in device driver
in order to improve the readability. It allows you to express more detail of this device
than just working.


> If the register is 32-bit aligned, other operations look the same as readl/writel.
> I think regmap is more simplified if the read registers are not 32-bit aligned, e.g. nvmem read/write.

I'm sorry. I don't understand of what is accurate meaning.
Could you please explain your opinion more detailed with example of this patch?

> So it would be more intuitive for me to keep writel/readl here
> 
>>
>>> +     val_cc &= ~TYPE_C_SWITCH_MASK;
>>> +
>>> +     if (cc == DISABLE_CC) {
>>> +             val_cc &= TYPE_C_DISABLE_CC;
>>> +     } else if (cc == ENABLE_CC1) {
>>> +             val_cc |= TYPE_C_ENABLE_CC1;
>>> +     } else if (cc == ENABLE_CC2) {
>>> +             val_cc |= TYPE_C_ENABLE_CC2;
>>> +     } else {
>>> +             dev_err(type_c->dev, "%s: Error cc setting cc=0x%x\n",
>> __func__, cc);
>>> +             return -EINVAL;
>>> +     }
>>> +     writel(val_cc, reg);
>>> +
> 
> Thanks,
> Stanley

-- 
Best Regards,
Samsung Electronics
Chanwoo Choi


^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver
  2023-08-29 19:18     ` Chanwoo Choi
@ 2023-08-30  3:59       ` Stanley Chang[昌育德]
  0 siblings, 0 replies; 19+ messages in thread
From: Stanley Chang[昌育德] @ 2023-08-30  3:59 UTC (permalink / raw)
  To: Chanwoo Choi, MyungJoo Ham
  Cc: Chanwoo Choi, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org

Hi Chanwoo,

> >>> +#define TYPE_C_EN_SWITCH BIT(29)
> >>> +#define TYPE_C_TXRX_SEL (BIT(28) | BIT(27)) #define
> >>> +TYPE_C_SWITCH_MASK (TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL)
> #define
> >>> +TYPE_C_ENABLE_CC1 TYPE_C_EN_SWITCH #define
> TYPE_C_ENABLE_CC2
> >>> +(TYPE_C_EN_SWITCH | TYPE_C_TXRX_SEL) #define TYPE_C_DISABLE_CC
> >>> +~TYPE_C_SWITCH_MASK
> >>> +
> >>> +     val_cc = readl(reg);
> >>
> >> I'd like you to use regmap interface to access the register by using
> >> regmap_read, regmap_write. You can create the regmap instance via
> >> devm_regmap_init_mmio() on probe instead of using 'type_c->reg_base'
> >> at the multipe point.
> >>
> >> For example,
> >>         struct regmap_config rtk_regmap_config = {
> >>                 .reg_bits = 32,
> >>                 .val_bits = 32,
> >>         };
> >>
> >>         void __iomem *base;
> >>
> >>         base = devm_platform_get_and_ioremap_resource(pdev, 0,
> &res);
> >>         if (IS_ERR(base))
> >>                 return PTR_ERR(base);
> >>
> >>         regmap = devm_regmap_init_mmio(dev, base,
> >> &rtk_regmap_config);
> >>
> >>         ---
> >>
> >>         And then just call regmap_read without any calculation between
> >>         base address and specific register.
> >>
> >>         regmap_read(regmap, USB_TYPEC_CTRL_CC1_0)
> >>
> >
> > I studied mmio's regmap.
> >
> > It only changed one encoding method. And simplifies the calculation
> between the base address and the specific register.
> 
> The regmap provides the consistent interface to access register regardless of
> mmio/i2c/spi and so on. It is the advantage of regmap.
> 
> And regmap provides the like register dump via debugfs, is able to specify the
> kind of register like writable, readable, volatile type.
> It is possible to specify the more detailed register information in device driver
> in order to improve the readability. It allows you to express more detail of this
> device than just working.

These are all advantages of regmap, I agree.
I haven't delved into regmap yet.

> 
> > If the register is 32-bit aligned, other operations look the same as
> readl/writel.
> > I think regmap is more simplified if the read registers are not 32-bit aligned,
> e.g. nvmem read/write.
> 
> I'm sorry. I don't understand of what is accurate meaning.
> Could you please explain your opinion more detailed with example of this
> patch?

Sorry, I misunderstood regmap, I thought he could read register like read otp tables by nvmem regardless of his bitness and size.
So my answer should be incorrect.

Thank,
Stanley

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2023-08-30  4:00 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-22 10:28 [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Stanley Chang
2023-08-22 10:28 ` [PATCH v1 2/2] dt-bindings: extcon: Add Realtek DHC RTD SoC Type-C Stanley Chang
2023-08-22 15:38   ` Krzysztof Kozlowski
2023-08-24  6:03     ` Stanley Chang[昌育德]
2023-08-24  6:26       ` Krzysztof Kozlowski
2023-08-24  7:23         ` Stanley Chang[昌育德]
2023-08-24  8:43           ` Krzysztof Kozlowski
2023-08-24  9:23             ` Stanley Chang[昌育德]
2023-08-24  9:56               ` Krzysztof Kozlowski
2023-08-24 10:05                 ` Stanley Chang[昌育德]
2023-08-22 15:35 ` [PATCH v1 1/2] extcon: add Realtek DHC RTD SoC Type-C driver Krzysztof Kozlowski
2023-08-24  6:09   ` Stanley Chang[昌育德]
2023-08-23  0:26 ` kernel test robot
2023-08-23 14:15 ` kernel test robot
2023-08-24 19:43 ` Chanwoo Choi
2023-08-25  9:39   ` Stanley Chang[昌育德]
2023-08-29 11:15   ` Stanley Chang[昌育德]
2023-08-29 19:18     ` Chanwoo Choi
2023-08-30  3:59       ` Stanley Chang[昌育德]

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).