[2/2] usb: typec: mux: Add ITE IT5205 Alternate Mode Passive MUX driver
Commit Message
The ITE IT5202 is a USB Type-C Alternate Mode Passive MUX, used for
muxing the SBU lines of a Type-C port with DisplayPort altmode and
also providing an orientation switch.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
drivers/usb/typec/mux/Kconfig | 10 ++
drivers/usb/typec/mux/Makefile | 1 +
drivers/usb/typec/mux/it5205.c | 292 +++++++++++++++++++++++++++++++++
3 files changed, 303 insertions(+)
create mode 100644 drivers/usb/typec/mux/it5205.c
Comments
On Fri, 19 Jan 2024 at 12:46, AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> The ITE IT5202 is a USB Type-C Alternate Mode Passive MUX, used for
> muxing the SBU lines of a Type-C port with DisplayPort altmode and
> also providing an orientation switch.
>
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
> drivers/usb/typec/mux/Kconfig | 10 ++
> drivers/usb/typec/mux/Makefile | 1 +
> drivers/usb/typec/mux/it5205.c | 292 +++++++++++++++++++++++++++++++++
> 3 files changed, 303 insertions(+)
> create mode 100644 drivers/usb/typec/mux/it5205.c
>
> diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig
> index d2cb5e733e57..399c7b0983df 100644
> --- a/drivers/usb/typec/mux/Kconfig
> +++ b/drivers/usb/typec/mux/Kconfig
> @@ -36,6 +36,16 @@ config TYPEC_MUX_INTEL_PMC
> control the USB role switch and also the multiplexer/demultiplexer
> switches used with USB Type-C Alternate Modes.
>
> +config TYPEC_MUX_IT5205
> + tristate "ITE IT5205 Type-C USB Alt Mode Passive MUX driver"
> + depends on I2C
> + select REGMAP_I2C
> + help
> + Driver for the ITE IT5205 Type-C USB Alternate Mode Passive MUX
> + which provides support for muxing DisplayPort and sideband signals
> + on a common USB Type-C connector.
> + If compiled as a module, the module will be named it5205.
> +
> config TYPEC_MUX_NB7VPQ904M
> tristate "On Semiconductor NB7VPQ904M Type-C redriver driver"
> depends on I2C
> diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile
> index 57dc9ac6f8dc..bb96f30267af 100644
> --- a/drivers/usb/typec/mux/Makefile
> +++ b/drivers/usb/typec/mux/Makefile
> @@ -4,6 +4,7 @@ obj-$(CONFIG_TYPEC_MUX_FSA4480) += fsa4480.o
> obj-$(CONFIG_TYPEC_MUX_GPIO_SBU) += gpio-sbu-mux.o
> obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o
> obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o
> +obj-$(CONFIG_TYPEC_MUX_IT5205) += it5205.o
> obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o
> obj-$(CONFIG_TYPEC_MUX_PTN36502) += ptn36502.o
> obj-$(CONFIG_TYPEC_MUX_WCD939X_USBSS) += wcd939x-usbss.o
> diff --git a/drivers/usb/typec/mux/it5205.c b/drivers/usb/typec/mux/it5205.c
> new file mode 100644
> index 000000000000..99203b8a086d
> --- /dev/null
> +++ b/drivers/usb/typec/mux/it5205.c
> @@ -0,0 +1,292 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * ITE IT5205 Type-C USB alternate mode passive mux
> + *
> + * Copyright (c) 2020 MediaTek Inc.
> + * Copyright (c) 2024 Collabora Ltd.
> + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> + *
> + */
> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/mutex.h>
> +#include <linux/of_platform.h>
> +#include <linux/regmap.h>
> +#include <linux/usb/typec.h>
> +#include <linux/usb/typec_mux.h>
> +#include <linux/usb/typec_dp.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/gpio.h>
> +#include <linux/usb/tcpm.h>
I'd say, it is a usual custom to sort this list.
[skipped]
> +
> +static int it5205_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
> +{
> + struct it5205 *it = typec_mux_get_drvdata(mux);
> + u8 val;
> +
> + switch (state->mode) {
> + case TYPEC_STATE_USB:
> + val = IT5205_USB;
> + break;
> + case TYPEC_DP_STATE_C:
> + fallthrough;
> + case TYPEC_DP_STATE_E:
> + val = IT5205_DP;
> + break;
> + case TYPEC_DP_STATE_D:
> + val = IT5205_DP_USB;
> + break;
> + case TYPEC_STATE_SAFE:
> + fallthrough;
> + default:
> + val = 0;
> + break;
> + }
Please add a check for state->altmode. All states at TYPEC_STATE_MODAL
and above (which includes TYPEC_DP_STATE_[CDE]) are only relevant with
connection to the particular typec->altmode SVID.
> +
> + return regmap_update_bits(it->regmap, IT5205_REG_MUXCR,
> + IT5205_DP_USB_CTRL_MASK, val);
> +}
> +
> +static irqreturn_t it5205_irq_handler(int irq, void *data)
> +{
> + struct it5205 *it = data;
> + int ret;
> + u32 val;
> +
> + ret = regmap_read(it->regmap, IT5205_REG_ISR, &val);
> + if (ret)
> + return IRQ_NONE;
> +
> + if (val & IT5205_ISR_CSBU_OVP) {
> + dev_warn(&it->client->dev, "Overvoltage detected!\n");
Will it cut the voltage automatically?
> +
> + /* Reset CSBU */
> + regmap_update_bits(it->regmap, IT5205_REG_CSBUSR,
> + IT5205_CSBUSR_SWITCH, 0);
> + regmap_update_bits(it->regmap, IT5205_REG_CSBUSR,
> + IT5205_CSBUSR_SWITCH, IT5205_CSBUSR_SWITCH);
> + }
> +
> + return IRQ_HANDLED;
> +}
The rest LGTM
Il 19/01/24 12:44, Dmitry Baryshkov ha scritto:
> On Fri, 19 Jan 2024 at 12:46, AngeloGioacchino Del Regno
> <angelogioacchino.delregno@collabora.com> wrote:
>>
>> The ITE IT5202 is a USB Type-C Alternate Mode Passive MUX, used for
>> muxing the SBU lines of a Type-C port with DisplayPort altmode and
>> also providing an orientation switch.
>>
>> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> ---
>> drivers/usb/typec/mux/Kconfig | 10 ++
>> drivers/usb/typec/mux/Makefile | 1 +
>> drivers/usb/typec/mux/it5205.c | 292 +++++++++++++++++++++++++++++++++
>> 3 files changed, 303 insertions(+)
>> create mode 100644 drivers/usb/typec/mux/it5205.c
>>
>> diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig
>> index d2cb5e733e57..399c7b0983df 100644
>> --- a/drivers/usb/typec/mux/Kconfig
>> +++ b/drivers/usb/typec/mux/Kconfig
>> @@ -36,6 +36,16 @@ config TYPEC_MUX_INTEL_PMC
>> control the USB role switch and also the multiplexer/demultiplexer
>> switches used with USB Type-C Alternate Modes.
>>
>> +config TYPEC_MUX_IT5205
>> + tristate "ITE IT5205 Type-C USB Alt Mode Passive MUX driver"
>> + depends on I2C
>> + select REGMAP_I2C
>> + help
>> + Driver for the ITE IT5205 Type-C USB Alternate Mode Passive MUX
>> + which provides support for muxing DisplayPort and sideband signals
>> + on a common USB Type-C connector.
>> + If compiled as a module, the module will be named it5205.
>> +
>> config TYPEC_MUX_NB7VPQ904M
>> tristate "On Semiconductor NB7VPQ904M Type-C redriver driver"
>> depends on I2C
>> diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile
>> index 57dc9ac6f8dc..bb96f30267af 100644
>> --- a/drivers/usb/typec/mux/Makefile
>> +++ b/drivers/usb/typec/mux/Makefile
>> @@ -4,6 +4,7 @@ obj-$(CONFIG_TYPEC_MUX_FSA4480) += fsa4480.o
>> obj-$(CONFIG_TYPEC_MUX_GPIO_SBU) += gpio-sbu-mux.o
>> obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o
>> obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o
>> +obj-$(CONFIG_TYPEC_MUX_IT5205) += it5205.o
>> obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o
>> obj-$(CONFIG_TYPEC_MUX_PTN36502) += ptn36502.o
>> obj-$(CONFIG_TYPEC_MUX_WCD939X_USBSS) += wcd939x-usbss.o
>> diff --git a/drivers/usb/typec/mux/it5205.c b/drivers/usb/typec/mux/it5205.c
>> new file mode 100644
>> index 000000000000..99203b8a086d
>> --- /dev/null
>> +++ b/drivers/usb/typec/mux/it5205.c
>> @@ -0,0 +1,292 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * ITE IT5205 Type-C USB alternate mode passive mux
>> + *
>> + * Copyright (c) 2020 MediaTek Inc.
>> + * Copyright (c) 2024 Collabora Ltd.
>> + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> + *
>> + */
>> +#include <linux/i2c.h>
>> +#include <linux/kernel.h>
>> +#include <linux/delay.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/mutex.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/regmap.h>
>> +#include <linux/usb/typec.h>
>> +#include <linux/usb/typec_mux.h>
>> +#include <linux/usb/typec_dp.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/gpio.h>
>> +#include <linux/usb/tcpm.h>
>
> I'd say, it is a usual custom to sort this list.
>
Oh, whoops. Totally forgot to do that, sorry - thanks for pointing that out!
Done for v2.
> [skipped]
>
>> +
>> +static int it5205_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
>> +{
>> + struct it5205 *it = typec_mux_get_drvdata(mux);
>> + u8 val;
>> +
>> + switch (state->mode) {
>> + case TYPEC_STATE_USB:
>> + val = IT5205_USB;
>> + break;
>> + case TYPEC_DP_STATE_C:
>> + fallthrough;
>> + case TYPEC_DP_STATE_E:
>> + val = IT5205_DP;
>> + break;
>> + case TYPEC_DP_STATE_D:
>> + val = IT5205_DP_USB;
>> + break;
>> + case TYPEC_STATE_SAFE:
>> + fallthrough;
>> + default:
>> + val = 0;
>> + break;
>> + }
>
> Please add a check for state->altmode. All states at TYPEC_STATE_MODAL
> and above (which includes TYPEC_DP_STATE_[CDE]) are only relevant with
> connection to the particular typec->altmode SVID.
>
Done for v2.
>> +
>> + return regmap_update_bits(it->regmap, IT5205_REG_MUXCR,
>> + IT5205_DP_USB_CTRL_MASK, val);
>> +}
>> +
>> +static irqreturn_t it5205_irq_handler(int irq, void *data)
>> +{
>> + struct it5205 *it = data;
>> + int ret;
>> + u32 val;
>> +
>> + ret = regmap_read(it->regmap, IT5205_REG_ISR, &val);
>> + if (ret)
>> + return IRQ_NONE;
>> +
>> + if (val & IT5205_ISR_CSBU_OVP) {
>> + dev_warn(&it->client->dev, "Overvoltage detected!\n");
>
> Will it cut the voltage automatically?
>
As far as I understand, yes.
Unfortunately, there's no datasheet.
>> +
>> + /* Reset CSBU */
>> + regmap_update_bits(it->regmap, IT5205_REG_CSBUSR,
>> + IT5205_CSBUSR_SWITCH, 0);
>> + regmap_update_bits(it->regmap, IT5205_REG_CSBUSR,
>> + IT5205_CSBUSR_SWITCH, IT5205_CSBUSR_SWITCH);
>> + }
>> +
>> + return IRQ_HANDLED;
>> +}
>
> The rest LGTM
>
>
@@ -36,6 +36,16 @@ config TYPEC_MUX_INTEL_PMC
control the USB role switch and also the multiplexer/demultiplexer
switches used with USB Type-C Alternate Modes.
+config TYPEC_MUX_IT5205
+ tristate "ITE IT5205 Type-C USB Alt Mode Passive MUX driver"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Driver for the ITE IT5205 Type-C USB Alternate Mode Passive MUX
+ which provides support for muxing DisplayPort and sideband signals
+ on a common USB Type-C connector.
+ If compiled as a module, the module will be named it5205.
+
config TYPEC_MUX_NB7VPQ904M
tristate "On Semiconductor NB7VPQ904M Type-C redriver driver"
depends on I2C
@@ -4,6 +4,7 @@ obj-$(CONFIG_TYPEC_MUX_FSA4480) += fsa4480.o
obj-$(CONFIG_TYPEC_MUX_GPIO_SBU) += gpio-sbu-mux.o
obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o
obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o
+obj-$(CONFIG_TYPEC_MUX_IT5205) += it5205.o
obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o
obj-$(CONFIG_TYPEC_MUX_PTN36502) += ptn36502.o
obj-$(CONFIG_TYPEC_MUX_WCD939X_USBSS) += wcd939x-usbss.o
new file mode 100644
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ITE IT5205 Type-C USB alternate mode passive mux
+ *
+ * Copyright (c) 2020 MediaTek Inc.
+ * Copyright (c) 2024 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ *
+ */
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/usb/typec.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio.h>
+#include <linux/usb/tcpm.h>
+
+#define IT5205_REG_CHIP_ID(x) (0x4 + (x))
+#define IT5205FN_CHIP_ID 0x35323035 /* "5205" */
+
+/* MUX power down register */
+#define IT5205_REG_MUXPDR 0x10
+#define IT5205_MUX_POWER_DOWN BIT(0)
+
+/* MUX control register */
+#define IT5205_REG_MUXCR 0x11
+#define IT5205_POLARITY_INVERTED BIT(4)
+#define IT5205_DP_USB_CTRL_MASK GENMASK(3, 0)
+#define IT5205_DP 0x0f
+#define IT5205_DP_USB 0x03
+#define IT5205_USB 0x07
+
+/* Vref Select Register */
+#define IT5205_REG_VSR 0x10
+#define IT5205_VREF_SELECT_MASK GENMASK(5, 4)
+#define IT5205_VREF_SELECT_3_3V 0x00
+#define IT5205_VREF_SELECT_OFF 0x20
+
+/* CSBU Over Voltage Protection Register */
+#define IT5205_REG_CSBUOVPSR 0x1e
+#define IT5205_OVP_SELECT_MASK GENMASK(5, 4)
+#define IT5205_OVP_3_90V 0x00
+#define IT5205_OVP_3_68V 0x10
+#define IT5205_OVP_3_62V 0x20
+#define IT5205_OVP_3_57V 0x30
+
+/* CSBU Switch Register */
+#define IT5205_REG_CSBUSR 0x22
+#define IT5205_CSBUSR_SWITCH BIT(0)
+
+/* Interrupt Switch Register */
+#define IT5205_REG_ISR 0x25
+#define IT5205_ISR_CSBU_MASK BIT(4)
+#define IT5205_ISR_CSBU_OVP BIT(0)
+
+struct it5205 {
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct typec_switch_dev *sw;
+ struct typec_mux_dev *mux;
+};
+
+static int it5205_switch_set(struct typec_switch_dev *sw, enum typec_orientation orientation)
+{
+ struct it5205 *it = typec_switch_get_drvdata(sw);
+
+ switch (orientation) {
+ case TYPEC_ORIENTATION_NORMAL:
+ regmap_update_bits(it->regmap, IT5205_REG_MUXCR,
+ IT5205_POLARITY_INVERTED, 0);
+ break;
+ case TYPEC_ORIENTATION_REVERSE:
+ regmap_update_bits(it->regmap, IT5205_REG_MUXCR,
+ IT5205_POLARITY_INVERTED, IT5205_POLARITY_INVERTED);
+ break;
+ case TYPEC_ORIENTATION_NONE:
+ fallthrough;
+ default:
+ regmap_write(it->regmap, IT5205_REG_MUXCR, 0);
+ break;
+ }
+
+ return 0;
+}
+
+static int it5205_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
+{
+ struct it5205 *it = typec_mux_get_drvdata(mux);
+ u8 val;
+
+ switch (state->mode) {
+ case TYPEC_STATE_USB:
+ val = IT5205_USB;
+ break;
+ case TYPEC_DP_STATE_C:
+ fallthrough;
+ case TYPEC_DP_STATE_E:
+ val = IT5205_DP;
+ break;
+ case TYPEC_DP_STATE_D:
+ val = IT5205_DP_USB;
+ break;
+ case TYPEC_STATE_SAFE:
+ fallthrough;
+ default:
+ val = 0;
+ break;
+ }
+
+ return regmap_update_bits(it->regmap, IT5205_REG_MUXCR,
+ IT5205_DP_USB_CTRL_MASK, val);
+}
+
+static irqreturn_t it5205_irq_handler(int irq, void *data)
+{
+ struct it5205 *it = data;
+ int ret;
+ u32 val;
+
+ ret = regmap_read(it->regmap, IT5205_REG_ISR, &val);
+ if (ret)
+ return IRQ_NONE;
+
+ if (val & IT5205_ISR_CSBU_OVP) {
+ dev_warn(&it->client->dev, "Overvoltage detected!\n");
+
+ /* Reset CSBU */
+ regmap_update_bits(it->regmap, IT5205_REG_CSBUSR,
+ IT5205_CSBUSR_SWITCH, 0);
+ regmap_update_bits(it->regmap, IT5205_REG_CSBUSR,
+ IT5205_CSBUSR_SWITCH, IT5205_CSBUSR_SWITCH);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void it5205_enable_ovp(struct it5205 *it)
+{
+ /* Select Vref 3.3v */
+ regmap_update_bits(it->regmap, IT5205_REG_VSR,
+ IT5205_VREF_SELECT_MASK, IT5205_VREF_SELECT_3_3V);
+
+ /* Trigger OVP at 3.68V */
+ regmap_update_bits(it->regmap, IT5205_REG_CSBUOVPSR,
+ IT5205_OVP_SELECT_MASK, IT5205_OVP_3_68V);
+
+ /* Unmask OVP interrupt */
+ regmap_update_bits(it->regmap, IT5205_REG_ISR,
+ IT5205_ISR_CSBU_MASK, 0);
+
+ /* Enable CSBU Interrupt */
+ regmap_update_bits(it->regmap, IT5205_REG_CSBUSR,
+ IT5205_CSBUSR_SWITCH, IT5205_CSBUSR_SWITCH);
+}
+
+static const struct regmap_config it5205_regmap = {
+ .max_register = 0x2f,
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int it5205_probe(struct i2c_client *client)
+{
+ struct typec_switch_desc sw_desc = { };
+ struct typec_mux_desc mux_desc = { };
+ struct device *dev = &client->dev;
+ struct it5205 *it;
+ u32 val, chipid = 0;
+ int i, ret;
+
+ it = devm_kzalloc(dev, sizeof(*it), GFP_KERNEL);
+ if (!it)
+ return -ENOMEM;
+
+ ret = devm_regulator_get_enable(dev, "vcc");
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get regulator\n");
+
+ it->client = client;
+
+ it->regmap = devm_regmap_init_i2c(client, &it5205_regmap);
+ if (IS_ERR(it->regmap))
+ return dev_err_probe(dev, PTR_ERR(it->regmap),
+ "Failed to init regmap\n");
+
+ /* IT5205 needs a long time to power up after enabling regulator */
+ msleep(50);
+
+ /* Unset poweroff bit */
+ ret = regmap_write(it->regmap, IT5205_REG_MUXPDR, 0);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set power on\n");
+
+ /* Read the 32 bits ChipID */
+ for (i = 3; i >= 0; i--) {
+ ret = regmap_read(it->regmap, IT5205_REG_CHIP_ID(i), &val);
+ if (ret)
+ return ret;
+
+ chipid |= val << (i * 8);
+ }
+
+ if (chipid != IT5205FN_CHIP_ID)
+ return dev_err_probe(dev, -EINVAL,
+ "Unknown ChipID 0x%x\n", chipid);
+
+ /* Initialize as USB mode with default (non-inverted) polarity */
+ ret = regmap_write(it->regmap, IT5205_REG_MUXCR, IT5205_USB);
+ if (ret)
+ return dev_err_probe(dev, ret, "Cannot set mode to USB\n");
+
+ sw_desc.drvdata = it;
+ sw_desc.fwnode = dev_fwnode(dev);
+ sw_desc.set = it5205_switch_set;
+
+ it->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(it->sw))
+ return dev_err_probe(dev, PTR_ERR(it->sw),
+ "failed to register typec switch\n");
+
+ mux_desc.drvdata = it;
+ mux_desc.fwnode = dev_fwnode(dev);
+ mux_desc.set = it5205_mux_set;
+
+ it->mux = typec_mux_register(dev, &mux_desc);
+ if (IS_ERR(it->mux)) {
+ typec_switch_unregister(it->sw);
+ return dev_err_probe(dev, PTR_ERR(it->mux),
+ "failed to register typec mux\n");
+ }
+
+ i2c_set_clientdata(client, it);
+
+ if (of_property_read_bool(dev->of_node, "ite,ovp-enable") && client->irq) {
+ it5205_enable_ovp(it);
+
+ ret = devm_request_threaded_irq(dev, client->irq, NULL,
+ it5205_irq_handler,
+ IRQF_ONESHOT, dev_name(dev), it);
+ if (ret) {
+ typec_mux_unregister(it->mux);
+ typec_switch_unregister(it->sw);
+ return dev_err_probe(dev, ret, "Failed to request irq\n");
+ }
+ }
+
+ return 0;
+}
+
+static void it5205_remove(struct i2c_client *client)
+{
+ struct it5205 *it = i2c_get_clientdata(client);
+
+ typec_mux_unregister(it->mux);
+ typec_switch_unregister(it->sw);
+}
+
+static const struct i2c_device_id it5205_table[] = {
+ { "it5205" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, it5205_table);
+
+static const struct of_device_id it5205_of_table[] = {
+ { .compatible = "ite,it5205" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, it5205_match_table);
+
+static struct i2c_driver it5205_driver = {
+ .driver = {
+ .name = "it5205",
+ .of_match_table = it5205_of_table,
+ },
+ .probe = it5205_probe,
+ .remove = it5205_remove,
+ .id_table = it5205_table,
+};
+module_i2c_driver(it5205_driver);
+
+MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>");
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_DESCRIPTION("ITE IT5205 alternate mode passive MUX driver");
+MODULE_LICENSE("GPL");