* [PATCH 1/2] extcon: add driver for TI TUSB320 @ 2020-10-08 22:39 ` Michael Auchter 2020-10-08 22:39 ` [PATCH 2/2] dt-bindings: extcon: add binding for TUSB320 Michael Auchter 2020-10-09 1:05 ` [PATCH 1/2] extcon: add driver for TI TUSB320 Chanwoo Choi 0 siblings, 2 replies; 6+ messages in thread From: Michael Auchter @ 2020-10-08 22:39 UTC (permalink / raw) To: MyungJoo Ham, Chanwoo Choi; +Cc: Michael Auchter, linux-kernel This patch adds an extcon driver for the TI TUSB320 USB Type-C device. This can be used to detect whether the port is configured as a downstream or upstream facing port. Signed-off-by: Michael Auchter <michael.auchter@ni.com> --- drivers/extcon/Kconfig | 7 ++ drivers/extcon/Makefile | 1 + drivers/extcon/extcon-usbc-tusb320.c | 180 +++++++++++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100644 drivers/extcon/extcon-usbc-tusb320.c diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index aac507bff135..241acaf8b882 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -186,4 +186,11 @@ config EXTCON_USBC_CROS_EC Say Y here to enable USB Type C cable detection extcon support when using Chrome OS EC based USB Type-C ports. +config EXTCON_USBC_TUSB320 + tristate "TI TUSB320 USB-C extcon support" + depends on GPIOLIB || COMPILE_TEST + help + Say Y here to enable support for USB Type C cable detection extcon + support using a TUSB320. + endif diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 52096fd8a216..fe10a1b7d18b 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o +obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c new file mode 100644 index 000000000000..217d6f416ff6 --- /dev/null +++ b/drivers/extcon/extcon-usbc-tusb320.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * drivers/extcon/extcon-tusb320.c - TUSB320 extcon driver + * + * Copyright (C) 2020 National Instruments Corporation + * Author: Michael Auchter <michael.auchter@ni.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/extcon-provider.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/i2c.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/workqueue.h> + +#define TUSB320_REG_9 0x9 +#define TUSB320_REG_9_INTERRUPT_STATUS BIT(4) +#define TUSB320_REG_9_GET_ATTACHED_STATE(reg) (((reg) >> 6) & 0x3) +#define TUSB320_REG_9_GET_CABLE_DIR(reg) (((reg) >> 5) & 1) +#define TUSB320_ATTACHED_STATE_NONE 0x0 +#define TUSB320_ATTACHED_STATE_DFP 0x1 +#define TUSB320_ATTACHED_STATE_UFP 0x2 +#define TUSB320_ATTACHED_STATE_ACC 0x3 + +static const char * const tusb_attached_states[] = { + [TUSB320_ATTACHED_STATE_NONE] = "not attached", + [TUSB320_ATTACHED_STATE_DFP] = "downstream facing port", + [TUSB320_ATTACHED_STATE_UFP] = "upstream facing port", + [TUSB320_ATTACHED_STATE_ACC] = "accessory", +}; + +static const unsigned int tusb320_extcon_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_NONE, +}; + +static int tusb320_check_signature(struct i2c_client *client) +{ + static const char sig[] = { '\0', 'T', 'U', 'S', 'B', '3', '2', '0' }; + int i, ret; + + for (i = 0; i < sizeof(sig); i++) { + ret = i2c_smbus_read_byte_data(client, sizeof(sig) - 1 - i); + if (ret < 0) + return ret; + if (ret != sig[i]) { + dev_err(&client->dev, "signature mismatch!\n"); + return -ENODEV; + } + } + + return 0; +} + +static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) +{ + struct i2c_client *client = dev_id; + struct extcon_dev *edev = i2c_get_clientdata(client); + int reg, state, polarity; + + reg = i2c_smbus_read_byte_data(client, TUSB320_REG_9); + if (reg < 0) { + dev_err(&client->dev, "error during i2c read: %d\n", reg); + return IRQ_NONE; + } + + if (!(reg & TUSB320_REG_9_INTERRUPT_STATUS)) + return IRQ_NONE; + + state = TUSB320_REG_9_GET_ATTACHED_STATE(reg); + polarity = TUSB320_REG_9_GET_CABLE_DIR(reg); + + dev_dbg(&client->dev, "attached state: %s, polarity: %d\n", + tusb_attached_states[state], polarity); + + extcon_set_state(edev, EXTCON_USB, + state == TUSB320_ATTACHED_STATE_UFP); + extcon_set_state(edev, EXTCON_USB_HOST, + state == TUSB320_ATTACHED_STATE_DFP); + extcon_set_property(edev, EXTCON_USB, + EXTCON_PROP_USB_TYPEC_POLARITY, + (union extcon_property_value)polarity); + extcon_set_property(edev, EXTCON_USB_HOST, + EXTCON_PROP_USB_TYPEC_POLARITY, + (union extcon_property_value)polarity); + extcon_sync(edev, EXTCON_USB); + extcon_sync(edev, EXTCON_USB_HOST); + + i2c_smbus_write_byte_data(client, TUSB320_REG_9, reg); + + return IRQ_HANDLED; +} + +static int tusb320_extcon_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct extcon_dev *edev; + int ret; + + ret = tusb320_check_signature(client); + if (ret) + return ret; + + edev = devm_extcon_dev_allocate(&client->dev, tusb320_extcon_cable); + if (IS_ERR(edev)) { + dev_err(&client->dev, "failed to allocate extcon device\n"); + return -ENOMEM; + } + i2c_set_clientdata(client, edev); + + ret = devm_extcon_dev_register(&client->dev, edev); + if (ret < 0) { + dev_err(&client->dev, "failed to register extcon device\n"); + return ret; + } + + extcon_set_property_capability(edev, EXTCON_USB, + EXTCON_PROP_USB_TYPEC_POLARITY); + extcon_set_property_capability(edev, EXTCON_USB_HOST, + EXTCON_PROP_USB_TYPEC_POLARITY); + + /* update initial state */ + tusb320_irq_handler(client->irq, client); + + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, tusb320_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev_name(&client->dev), client); + + return ret; +} + +static const struct of_device_id tusb320_extcon_dt_match[] = { + { .compatible = "ti,tusb320", }, + { } +}; +MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match); + +static const struct i2c_device_id tusb320_i2c_id[] = { + { "tusb320", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tusb320_i2c_id); + +static struct i2c_driver tusb320_extcon_driver = { + .probe = tusb320_extcon_probe, + .driver = { + .name = "extcon-tusb320", + .of_match_table = tusb320_extcon_dt_match, + }, +}; + +static int __init tusb320_init(void) +{ + return i2c_add_driver(&tusb320_extcon_driver); +} +subsys_initcall(tusb320_init); + +static void __exit tusb320_exit(void) +{ + i2c_del_driver(&tusb320_extcon_driver); +} +module_exit(tusb320_exit); + +MODULE_AUTHOR("Michael Auchter <michael.auchter@ni.com>"); +MODULE_DESCRIPTION("TI TUSB320 extcon driver"); +MODULE_LICENSE("GPL v2"); -- 2.25.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] dt-bindings: extcon: add binding for TUSB320 2020-10-08 22:39 ` [PATCH 1/2] extcon: add driver for TI TUSB320 Michael Auchter @ 2020-10-08 22:39 ` Michael Auchter 2020-10-09 1:02 ` Chanwoo Choi 2020-10-09 1:05 ` [PATCH 1/2] extcon: add driver for TI TUSB320 Chanwoo Choi 1 sibling, 1 reply; 6+ messages in thread From: Michael Auchter @ 2020-10-08 22:39 UTC (permalink / raw) To: MyungJoo Ham, Chanwoo Choi, Rob Herring, Michael Auchter Cc: linux-kernel, devicetree Add a device tree binding for the TI TUSB320. Signed-off-by: Michael Auchter <michael.auchter@ni.com> --- .../bindings/extcon/extcon-usbc-tusb320.yaml | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Documentation/devicetree/bindings/extcon/extcon-usbc-tusb320.yaml diff --git a/Documentation/devicetree/bindings/extcon/extcon-usbc-tusb320.yaml b/Documentation/devicetree/bindings/extcon/extcon-usbc-tusb320.yaml new file mode 100644 index 000000000000..57f1bcbf1295 --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/extcon-usbc-tusb320.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/extcon/extcon-usbc-tusb320.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI TUSB320 USB Type-C CC Logic controller + +maintainers: + - Michael Auchter <michael.auchter@ni.com> + +properties: + compatible: + const: ti,tusb320 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + extcon@61 { + compatible = "ti,tusb320"; + reg = <0x61>; + interrupt-parent = <&gpio>; + interrupts = <27 1>; + }; + }; +... -- 2.25.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] dt-bindings: extcon: add binding for TUSB320 2020-10-08 22:39 ` [PATCH 2/2] dt-bindings: extcon: add binding for TUSB320 Michael Auchter @ 2020-10-09 1:02 ` Chanwoo Choi 0 siblings, 0 replies; 6+ messages in thread From: Chanwoo Choi @ 2020-10-09 1:02 UTC (permalink / raw) To: Michael Auchter, MyungJoo Ham, Rob Herring; +Cc: linux-kernel, devicetree On 10/9/20 7:39 AM, Michael Auchter wrote: > Add a device tree binding for the TI TUSB320. > > Signed-off-by: Michael Auchter <michael.auchter@ni.com> > --- > .../bindings/extcon/extcon-usbc-tusb320.yaml | 41 +++++++++++++++++++ > 1 file changed, 41 insertions(+) > create mode 100644 Documentation/devicetree/bindings/extcon/extcon-usbc-tusb320.yaml > > diff --git a/Documentation/devicetree/bindings/extcon/extcon-usbc-tusb320.yaml b/Documentation/devicetree/bindings/extcon/extcon-usbc-tusb320.yaml > new file mode 100644 > index 000000000000..57f1bcbf1295 > --- /dev/null > +++ b/Documentation/devicetree/bindings/extcon/extcon-usbc-tusb320.yaml > @@ -0,0 +1,41 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: https://protect2.fireeye.com/v1/url?k=24582026-79962192-2459ab69-000babdfecba-1931f18c81ab64e5&q=1&e=8094c8b6-bc5c-4c39-b23a-4f81a9cccae3&u=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fextcon%2Fextcon-usbc-tusb320.yaml%23 > +$schema: https://protect2.fireeye.com/v1/url?k=8c20f14c-d1eef0f8-8c217a03-000babdfecba-6159bd3aeb5a40ca&q=1&e=8094c8b6-bc5c-4c39-b23a-4f81a9cccae3&u=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23 > + > +title: TI TUSB320 USB Type-C CC Logic controller > + > +maintainers: > + - Michael Auchter <michael.auchter@ni.com> > + > +properties: > + compatible: > + const: ti,tusb320 > + > + reg: > + maxItems: 1 > + > + interrupts: > + maxItems: 1 > + > +required: > + - compatible > + - reg > + - interrupts > + > +additionalProperties: false > + > +examples: > + - | > + i2c0 { > + #address-cells = <1>; > + #size-cells = <0>; > + extcon@61 { Better to use 'tusb320' instead of 'extcon' word because extcon doesn't represent the hardware. > + compatible = "ti,tusb320"; > + reg = <0x61>; > + interrupt-parent = <&gpio>; > + interrupts = <27 1>; > + }; > + }; > +... > -- Best Regards, Chanwoo Choi Samsung Electronics ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] extcon: add driver for TI TUSB320 2020-10-08 22:39 ` [PATCH 1/2] extcon: add driver for TI TUSB320 Michael Auchter 2020-10-08 22:39 ` [PATCH 2/2] dt-bindings: extcon: add binding for TUSB320 Michael Auchter @ 2020-10-09 1:05 ` Chanwoo Choi 1 sibling, 0 replies; 6+ messages in thread From: Chanwoo Choi @ 2020-10-09 1:05 UTC (permalink / raw) To: Michael Auchter, MyungJoo Ham; +Cc: linux-kernel Hi, Almost looks good to me. I added some comments. On 10/9/20 7:39 AM, Michael Auchter wrote: > This patch adds an extcon driver for the TI TUSB320 USB Type-C device. > This can be used to detect whether the port is configured as a > downstream or upstream facing port. > > Signed-off-by: Michael Auchter <michael.auchter@ni.com> > --- > drivers/extcon/Kconfig | 7 ++ > drivers/extcon/Makefile | 1 + > drivers/extcon/extcon-usbc-tusb320.c | 180 +++++++++++++++++++++++++++ > 3 files changed, 188 insertions(+) > create mode 100644 drivers/extcon/extcon-usbc-tusb320.c > > diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig > index aac507bff135..241acaf8b882 100644 > --- a/drivers/extcon/Kconfig > +++ b/drivers/extcon/Kconfig > @@ -186,4 +186,11 @@ config EXTCON_USBC_CROS_EC > Say Y here to enable USB Type C cable detection extcon support when > using Chrome OS EC based USB Type-C ports. > > +config EXTCON_USBC_TUSB320 > + tristate "TI TUSB320 USB-C extcon support" > + depends on GPIOLIB || COMPILE_TEST > + help > + Say Y here to enable support for USB Type C cable detection extcon > + support using a TUSB320. > + > endif > diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile > index 52096fd8a216..fe10a1b7d18b 100644 > --- a/drivers/extcon/Makefile > +++ b/drivers/extcon/Makefile > @@ -25,3 +25,4 @@ obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o > obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o > obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o > obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o > +obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o > diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c > new file mode 100644 > index 000000000000..217d6f416ff6 > --- /dev/null > +++ b/drivers/extcon/extcon-usbc-tusb320.c > @@ -0,0 +1,180 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/** > + * drivers/extcon/extcon-tusb320.c - TUSB320 extcon driver > + * > + * Copyright (C) 2020 National Instruments Corporation > + * Author: Michael Auchter <michael.auchter@ni.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. You don't need to additional license info below 'author' because you added '// SPDX-License-Identifier: GPL-2.0' at the first line. > + */ > + > +#include <linux/extcon-provider.h> > +#include <linux/init.h> > +#include <linux/interrupt.h> > +#include <linux/i2c.h> > +#include <linux/irq.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/slab.h> > +#include <linux/workqueue.h> > + > +#define TUSB320_REG_9 0x9 > +#define TUSB320_REG_9_INTERRUPT_STATUS BIT(4) > +#define TUSB320_REG_9_GET_ATTACHED_STATE(reg) (((reg) >> 6) & 0x3) You need to define what is meaning of '6' and '0x3'. #define TUSB30_xxx_SHIFT 6 #define TUSB30_xxx_MASK 0x3 > +#define TUSB320_REG_9_GET_CABLE_DIR(reg) (((reg) >> 5) & 1) ditto. #define TUSB30_xxx__SHIFT 5 #define TUSB30_xxx_MASK 0x1 > +#define TUSB320_ATTACHED_STATE_NONE 0x0 > +#define TUSB320_ATTACHED_STATE_DFP 0x1 > +#define TUSB320_ATTACHED_STATE_UFP 0x2 > +#define TUSB320_ATTACHED_STATE_ACC 0x3 > + nitpick. For the indentation, how about editing as following: #define TUSB320_REG_9 0x9 #define TUSB320_REG_9_INTERRUPT_STATUS BIT(4) #define TUSB320_REG_9_GET_ATTACHED_STATE(reg) (((reg) >> 6) & 0x3) #define TUSB320_REG_9_GET_CABLE_DIR(reg) (((reg) >> 5) & 1) #define TUSB320_ATTACHED_STATE_NONE 0x0 #define TUSB320_ATTACHED_STATE_DFP 0x1 #define TUSB320_ATTACHED_STATE_UFP 0x2 #define TUSB320_ATTACHED_STATE_ACC 0x3 > +static const char * const tusb_attached_states[] = { > + [TUSB320_ATTACHED_STATE_NONE] = "not attached", > + [TUSB320_ATTACHED_STATE_DFP] = "downstream facing port", > + [TUSB320_ATTACHED_STATE_UFP] = "upstream facing port", > + [TUSB320_ATTACHED_STATE_ACC] = "accessory", > +}; > + > +static const unsigned int tusb320_extcon_cable[] = { > + EXTCON_USB, > + EXTCON_USB_HOST, > + EXTCON_NONE, > +}; > + > +static int tusb320_check_signature(struct i2c_client *client) > +{ > + static const char sig[] = { '\0', 'T', 'U', 'S', 'B', '3', '2', '0' }; > + int i, ret; > + > + for (i = 0; i < sizeof(sig); i++) { > + ret = i2c_smbus_read_byte_data(client, sizeof(sig) - 1 - i); > + if (ret < 0) > + return ret; > + if (ret != sig[i]) { > + dev_err(&client->dev, "signature mismatch!\n"); > + return -ENODEV; > + } > + } > + > + return 0; > +} > + > +static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) > +{ > + struct i2c_client *client = dev_id; > + struct extcon_dev *edev = i2c_get_clientdata(client); > + int reg, state, polarity; > + > + reg = i2c_smbus_read_byte_data(client, TUSB320_REG_9); > + if (reg < 0) { > + dev_err(&client->dev, "error during i2c read: %d\n", reg); > + return IRQ_NONE; > + } > + > + if (!(reg & TUSB320_REG_9_INTERRUPT_STATUS)) > + return IRQ_NONE; > + > + state = TUSB320_REG_9_GET_ATTACHED_STATE(reg); > + polarity = TUSB320_REG_9_GET_CABLE_DIR(reg); > + > + dev_dbg(&client->dev, "attached state: %s, polarity: %d\n", > + tusb_attached_states[state], polarity); > + > + extcon_set_state(edev, EXTCON_USB, > + state == TUSB320_ATTACHED_STATE_UFP); > + extcon_set_state(edev, EXTCON_USB_HOST, > + state == TUSB320_ATTACHED_STATE_DFP); > + extcon_set_property(edev, EXTCON_USB, > + EXTCON_PROP_USB_TYPEC_POLARITY, > + (union extcon_property_value)polarity); > + extcon_set_property(edev, EXTCON_USB_HOST, > + EXTCON_PROP_USB_TYPEC_POLARITY, > + (union extcon_property_value)polarity); > + extcon_sync(edev, EXTCON_USB); > + extcon_sync(edev, EXTCON_USB_HOST); > + > + i2c_smbus_write_byte_data(client, TUSB320_REG_9, reg); > + > + return IRQ_HANDLED; > +} > + > +static int tusb320_extcon_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct extcon_dev *edev; > + int ret; I recommend that you better to use regmap_i2c with devm_regmap_init_i2c() function instead of using i2c_smbus_*() function. You can refer regmap_i2c usage on drivers/extcon/extcon-sm5502.c. > + > + ret = tusb320_check_signature(client); > + if (ret) > + return ret; > + > + edev = devm_extcon_dev_allocate(&client->dev, tusb320_extcon_cable); > + if (IS_ERR(edev)) { > + dev_err(&client->dev, "failed to allocate extcon device\n"); > + return -ENOMEM; > + } > + i2c_set_clientdata(client, edev); > + > + ret = devm_extcon_dev_register(&client->dev, edev); > + if (ret < 0) { > + dev_err(&client->dev, "failed to register extcon device\n"); > + return ret; > + } > + > + extcon_set_property_capability(edev, EXTCON_USB, > + EXTCON_PROP_USB_TYPEC_POLARITY); > + extcon_set_property_capability(edev, EXTCON_USB_HOST, > + EXTCON_PROP_USB_TYPEC_POLARITY); > + > + /* update initial state */ > + tusb320_irq_handler(client->irq, client); > + > + ret = devm_request_threaded_irq(&client->dev, client->irq, > + NULL, tusb320_irq_handler, > + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, > + dev_name(&client->dev), client); > + > + return ret; > +} > + > +static const struct of_device_id tusb320_extcon_dt_match[] = { > + { .compatible = "ti,tusb320", }, > + { } > +}; > +MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match); > + > +static const struct i2c_device_id tusb320_i2c_id[] = { > + { "tusb320", 0 }, > + { } > +}; > +MODULE_DEVICE_TABLE(i2c, tusb320_i2c_id); > + > +static struct i2c_driver tusb320_extcon_driver = { > + .probe = tusb320_extcon_probe, > + .driver = { > + .name = "extcon-tusb320", > + .of_match_table = tusb320_extcon_dt_match, > + }, > +}; > + > +static int __init tusb320_init(void) > +{ > + return i2c_add_driver(&tusb320_extcon_driver); > +} > +subsys_initcall(tusb320_init); > + > +static void __exit tusb320_exit(void) > +{ > + i2c_del_driver(&tusb320_extcon_driver); > +} > +module_exit(tusb320_exit); > + > +MODULE_AUTHOR("Michael Auchter <michael.auchter@ni.com>"); > +MODULE_DESCRIPTION("TI TUSB320 extcon driver"); > +MODULE_LICENSE("GPL v2"); > -- Best Regards, Chanwoo Choi Samsung Electronics ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <CGME20201015140757epcas1p43b728b2b67e9ded476a46de127e2ce8b@epcas1p4.samsung.com>]
* [PATCH 1/2] extcon: add driver for TI TUSB320 @ 2020-10-15 14:07 ` Michael Auchter 2020-10-19 10:24 ` Chanwoo Choi 0 siblings, 1 reply; 6+ messages in thread From: Michael Auchter @ 2020-10-15 14:07 UTC (permalink / raw) To: MyungJoo Ham, Chanwoo Choi; +Cc: Michael Auchter, linux-kernel This patch adds an extcon driver for the TI TUSB320 USB Type-C device. This can be used to detect whether the port is configured as a downstream or upstream facing port. Signed-off-by: Michael Auchter <michael.auchter@ni.com> --- Changes since v1: - Drop license text that's redundant with SPDX tag - Cleanup, sort list of includes - Add additional register defines - Switch to use regmap API - Fix Kconfig to depend on I2C, not GPIOLIB since v2: - Drop unused irq.h - Fix spaces in definitions - Return PTR_ERR(priv->edev) instead of -ENOMEM - Remove unused i2c_device_id table - use client->name instead of dev_name() in request_irq to be more descriptive drivers/extcon/Kconfig | 8 ++ drivers/extcon/Makefile | 1 + drivers/extcon/extcon-usbc-tusb320.c | 184 +++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 drivers/extcon/extcon-usbc-tusb320.c diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index aac507bff135..af58ebca2bf6 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -186,4 +186,12 @@ config EXTCON_USBC_CROS_EC Say Y here to enable USB Type C cable detection extcon support when using Chrome OS EC based USB Type-C ports. +config EXTCON_USBC_TUSB320 + tristate "TI TUSB320 USB-C extcon support" + depends on I2C + select REGMAP_I2C + help + Say Y here to enable support for USB Type C cable detection extcon + support using a TUSB320. + endif diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 52096fd8a216..fe10a1b7d18b 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o +obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c new file mode 100644 index 000000000000..805af73b4152 --- /dev/null +++ b/drivers/extcon/extcon-usbc-tusb320.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * drivers/extcon/extcon-tusb320.c - TUSB320 extcon driver + * + * Copyright (C) 2020 National Instruments Corporation + * Author: Michael Auchter <michael.auchter@ni.com> + */ + +#include <linux/extcon-provider.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#define TUSB320_REG9 0x9 +#define TUSB320_REG9_ATTACHED_STATE_SHIFT 6 +#define TUSB320_REG9_ATTACHED_STATE_MASK 0x3 +#define TUSB320_REG9_CABLE_DIRECTION BIT(5) +#define TUSB320_REG9_INTERRUPT_STATUS BIT(4) +#define TUSB320_ATTACHED_STATE_NONE 0x0 +#define TUSB320_ATTACHED_STATE_DFP 0x1 +#define TUSB320_ATTACHED_STATE_UFP 0x2 +#define TUSB320_ATTACHED_STATE_ACC 0x3 + +struct tusb320_priv { + struct device *dev; + struct regmap *regmap; + struct extcon_dev *edev; +}; + +static const char * const tusb_attached_states[] = { + [TUSB320_ATTACHED_STATE_NONE] = "not attached", + [TUSB320_ATTACHED_STATE_DFP] = "downstream facing port", + [TUSB320_ATTACHED_STATE_UFP] = "upstream facing port", + [TUSB320_ATTACHED_STATE_ACC] = "accessory", +}; + +static const unsigned int tusb320_extcon_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_NONE, +}; + +static int tusb320_check_signature(struct tusb320_priv *priv) +{ + static const char sig[] = { '\0', 'T', 'U', 'S', 'B', '3', '2', '0' }; + unsigned val; + int i, ret; + + for (i = 0; i < sizeof(sig); i++) { + ret = regmap_read(priv->regmap, sizeof(sig) - 1 - i, &val); + if (ret < 0) + return ret; + if (val != sig[i]) { + dev_err(priv->dev, "signature mismatch!\n"); + return -ENODEV; + } + } + + return 0; +} + +static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) +{ + struct tusb320_priv *priv = dev_id; + int state, polarity; + unsigned reg; + + if (regmap_read(priv->regmap, TUSB320_REG9, ®)) { + dev_err(priv->dev, "error during i2c read!\n"); + return IRQ_NONE; + } + + if (!(reg & TUSB320_REG9_INTERRUPT_STATUS)) + return IRQ_NONE; + + state = (reg >> TUSB320_REG9_ATTACHED_STATE_SHIFT) & + TUSB320_REG9_ATTACHED_STATE_MASK; + polarity = !!(reg & TUSB320_REG9_CABLE_DIRECTION); + + dev_dbg(priv->dev, "attached state: %s, polarity: %d\n", + tusb_attached_states[state], polarity); + + extcon_set_state(priv->edev, EXTCON_USB, + state == TUSB320_ATTACHED_STATE_UFP); + extcon_set_state(priv->edev, EXTCON_USB_HOST, + state == TUSB320_ATTACHED_STATE_DFP); + extcon_set_property(priv->edev, EXTCON_USB, + EXTCON_PROP_USB_TYPEC_POLARITY, + (union extcon_property_value)polarity); + extcon_set_property(priv->edev, EXTCON_USB_HOST, + EXTCON_PROP_USB_TYPEC_POLARITY, + (union extcon_property_value)polarity); + extcon_sync(priv->edev, EXTCON_USB); + extcon_sync(priv->edev, EXTCON_USB_HOST); + + regmap_write(priv->regmap, TUSB320_REG9, reg); + + return IRQ_HANDLED; +} + +static const struct regmap_config tusb320_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int tusb320_extcon_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tusb320_priv *priv; + int ret; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->dev = &client->dev; + + priv->regmap = devm_regmap_init_i2c(client, &tusb320_regmap_config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + ret = tusb320_check_signature(priv); + if (ret) + return ret; + + priv->edev = devm_extcon_dev_allocate(priv->dev, tusb320_extcon_cable); + if (IS_ERR(priv->edev)) { + dev_err(priv->dev, "failed to allocate extcon device\n"); + return PTR_ERR(priv->edev); + } + + ret = devm_extcon_dev_register(priv->dev, priv->edev); + if (ret < 0) { + dev_err(priv->dev, "failed to register extcon device\n"); + return ret; + } + + extcon_set_property_capability(priv->edev, EXTCON_USB, + EXTCON_PROP_USB_TYPEC_POLARITY); + extcon_set_property_capability(priv->edev, EXTCON_USB_HOST, + EXTCON_PROP_USB_TYPEC_POLARITY); + + /* update initial state */ + tusb320_irq_handler(client->irq, priv); + + ret = devm_request_threaded_irq(priv->dev, client->irq, NULL, + tusb320_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + client->name, priv); + + return ret; +} + +static const struct of_device_id tusb320_extcon_dt_match[] = { + { .compatible = "ti,tusb320", }, + { } +}; +MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match); + +static struct i2c_driver tusb320_extcon_driver = { + .probe = tusb320_extcon_probe, + .driver = { + .name = "extcon-tusb320", + .of_match_table = tusb320_extcon_dt_match, + }, +}; + +static int __init tusb320_init(void) +{ + return i2c_add_driver(&tusb320_extcon_driver); +} +subsys_initcall(tusb320_init); + +static void __exit tusb320_exit(void) +{ + i2c_del_driver(&tusb320_extcon_driver); +} +module_exit(tusb320_exit); + +MODULE_AUTHOR("Michael Auchter <michael.auchter@ni.com>"); +MODULE_DESCRIPTION("TI TUSB320 extcon driver"); +MODULE_LICENSE("GPL v2"); -- 2.25.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] extcon: add driver for TI TUSB320 2020-10-15 14:07 ` Michael Auchter @ 2020-10-19 10:24 ` Chanwoo Choi 0 siblings, 0 replies; 6+ messages in thread From: Chanwoo Choi @ 2020-10-19 10:24 UTC (permalink / raw) To: Michael Auchter, MyungJoo Ham; +Cc: linux-kernel On 10/15/20 11:07 PM, Michael Auchter wrote: > This patch adds an extcon driver for the TI TUSB320 USB Type-C device. > This can be used to detect whether the port is configured as a > downstream or upstream facing port. > > Signed-off-by: Michael Auchter <michael.auchter@ni.com> > --- > Changes since v1: > - Drop license text that's redundant with SPDX tag > - Cleanup, sort list of includes > - Add additional register defines > - Switch to use regmap API > - Fix Kconfig to depend on I2C, not GPIOLIB > since v2: > - Drop unused irq.h > - Fix spaces in definitions > - Return PTR_ERR(priv->edev) instead of -ENOMEM > - Remove unused i2c_device_id table > - use client->name instead of dev_name() in request_irq to be more > descriptive > > drivers/extcon/Kconfig | 8 ++ > drivers/extcon/Makefile | 1 + > drivers/extcon/extcon-usbc-tusb320.c | 184 +++++++++++++++++++++++++++ > 3 files changed, 193 insertions(+) > create mode 100644 drivers/extcon/extcon-usbc-tusb320.c > > diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig > index aac507bff135..af58ebca2bf6 100644 > --- a/drivers/extcon/Kconfig > +++ b/drivers/extcon/Kconfig > @@ -186,4 +186,12 @@ config EXTCON_USBC_CROS_EC > Say Y here to enable USB Type C cable detection extcon support when > using Chrome OS EC based USB Type-C ports. > > +config EXTCON_USBC_TUSB320 > + tristate "TI TUSB320 USB-C extcon support" > + depends on I2C > + select REGMAP_I2C > + help > + Say Y here to enable support for USB Type C cable detection extcon > + support using a TUSB320. > + > endif > diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile > index 52096fd8a216..fe10a1b7d18b 100644 > --- a/drivers/extcon/Makefile > +++ b/drivers/extcon/Makefile > @@ -25,3 +25,4 @@ obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o > obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o > obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o > obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o > +obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o > diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c > new file mode 100644 > index 000000000000..805af73b4152 > --- /dev/null > +++ b/drivers/extcon/extcon-usbc-tusb320.c > @@ -0,0 +1,184 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/** > + * drivers/extcon/extcon-tusb320.c - TUSB320 extcon driver > + * > + * Copyright (C) 2020 National Instruments Corporation > + * Author: Michael Auchter <michael.auchter@ni.com> > + */ > + > +#include <linux/extcon-provider.h> > +#include <linux/i2c.h> > +#include <linux/init.h> > +#include <linux/interrupt.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/regmap.h> > + > +#define TUSB320_REG9 0x9 > +#define TUSB320_REG9_ATTACHED_STATE_SHIFT 6 > +#define TUSB320_REG9_ATTACHED_STATE_MASK 0x3 > +#define TUSB320_REG9_CABLE_DIRECTION BIT(5) > +#define TUSB320_REG9_INTERRUPT_STATUS BIT(4) > +#define TUSB320_ATTACHED_STATE_NONE 0x0 > +#define TUSB320_ATTACHED_STATE_DFP 0x1 > +#define TUSB320_ATTACHED_STATE_UFP 0x2 > +#define TUSB320_ATTACHED_STATE_ACC 0x3 > + > +struct tusb320_priv { > + struct device *dev; > + struct regmap *regmap; > + struct extcon_dev *edev; > +}; > + > +static const char * const tusb_attached_states[] = { > + [TUSB320_ATTACHED_STATE_NONE] = "not attached", > + [TUSB320_ATTACHED_STATE_DFP] = "downstream facing port", > + [TUSB320_ATTACHED_STATE_UFP] = "upstream facing port", > + [TUSB320_ATTACHED_STATE_ACC] = "accessory", > +}; > + > +static const unsigned int tusb320_extcon_cable[] = { > + EXTCON_USB, > + EXTCON_USB_HOST, > + EXTCON_NONE, > +}; > + > +static int tusb320_check_signature(struct tusb320_priv *priv) > +{ > + static const char sig[] = { '\0', 'T', 'U', 'S', 'B', '3', '2', '0' }; > + unsigned val; > + int i, ret; > + > + for (i = 0; i < sizeof(sig); i++) { > + ret = regmap_read(priv->regmap, sizeof(sig) - 1 - i, &val); > + if (ret < 0) > + return ret; > + if (val != sig[i]) { > + dev_err(priv->dev, "signature mismatch!\n"); > + return -ENODEV; > + } > + } > + > + return 0; > +} > + > +static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) > +{ > + struct tusb320_priv *priv = dev_id; > + int state, polarity; > + unsigned reg; > + > + if (regmap_read(priv->regmap, TUSB320_REG9, ®)) { > + dev_err(priv->dev, "error during i2c read!\n"); > + return IRQ_NONE; > + } > + > + if (!(reg & TUSB320_REG9_INTERRUPT_STATUS)) > + return IRQ_NONE; > + > + state = (reg >> TUSB320_REG9_ATTACHED_STATE_SHIFT) & > + TUSB320_REG9_ATTACHED_STATE_MASK; > + polarity = !!(reg & TUSB320_REG9_CABLE_DIRECTION); > + > + dev_dbg(priv->dev, "attached state: %s, polarity: %d\n", > + tusb_attached_states[state], polarity); > + > + extcon_set_state(priv->edev, EXTCON_USB, > + state == TUSB320_ATTACHED_STATE_UFP); > + extcon_set_state(priv->edev, EXTCON_USB_HOST, > + state == TUSB320_ATTACHED_STATE_DFP); > + extcon_set_property(priv->edev, EXTCON_USB, > + EXTCON_PROP_USB_TYPEC_POLARITY, > + (union extcon_property_value)polarity); > + extcon_set_property(priv->edev, EXTCON_USB_HOST, > + EXTCON_PROP_USB_TYPEC_POLARITY, > + (union extcon_property_value)polarity); > + extcon_sync(priv->edev, EXTCON_USB); > + extcon_sync(priv->edev, EXTCON_USB_HOST); > + > + regmap_write(priv->regmap, TUSB320_REG9, reg); > + > + return IRQ_HANDLED; > +} > + > +static const struct regmap_config tusb320_regmap_config = { > + .reg_bits = 8, > + .val_bits = 8, > +}; > + > +static int tusb320_extcon_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct tusb320_priv *priv; > + int ret; > + > + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + priv->dev = &client->dev; > + > + priv->regmap = devm_regmap_init_i2c(client, &tusb320_regmap_config); > + if (IS_ERR(priv->regmap)) > + return PTR_ERR(priv->regmap); > + > + ret = tusb320_check_signature(priv); > + if (ret) > + return ret; > + > + priv->edev = devm_extcon_dev_allocate(priv->dev, tusb320_extcon_cable); > + if (IS_ERR(priv->edev)) { > + dev_err(priv->dev, "failed to allocate extcon device\n"); > + return PTR_ERR(priv->edev); > + } > + > + ret = devm_extcon_dev_register(priv->dev, priv->edev); > + if (ret < 0) { > + dev_err(priv->dev, "failed to register extcon device\n"); > + return ret; > + } > + > + extcon_set_property_capability(priv->edev, EXTCON_USB, > + EXTCON_PROP_USB_TYPEC_POLARITY); > + extcon_set_property_capability(priv->edev, EXTCON_USB_HOST, > + EXTCON_PROP_USB_TYPEC_POLARITY); > + > + /* update initial state */ > + tusb320_irq_handler(client->irq, priv); > + > + ret = devm_request_threaded_irq(priv->dev, client->irq, NULL, > + tusb320_irq_handler, > + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, > + client->name, priv); > + > + return ret; > +} > + > +static const struct of_device_id tusb320_extcon_dt_match[] = { > + { .compatible = "ti,tusb320", }, > + { } > +}; > +MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match); > + > +static struct i2c_driver tusb320_extcon_driver = { > + .probe = tusb320_extcon_probe, > + .driver = { > + .name = "extcon-tusb320", > + .of_match_table = tusb320_extcon_dt_match, > + }, > +}; > + > +static int __init tusb320_init(void) > +{ > + return i2c_add_driver(&tusb320_extcon_driver); > +} > +subsys_initcall(tusb320_init); > + > +static void __exit tusb320_exit(void) > +{ > + i2c_del_driver(&tusb320_extcon_driver); > +} > +module_exit(tusb320_exit); > + > +MODULE_AUTHOR("Michael Auchter <michael.auchter@ni.com>"); > +MODULE_DESCRIPTION("TI TUSB320 extcon driver"); > +MODULE_LICENSE("GPL v2"); > Applied them. Thanks. -- Best Regards, Chanwoo Choi Samsung Electronics ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-10-19 10:10 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <CGME20201008223958epcas1p106e9e643db81b66ac242e91f63510486@epcas1p1.samsung.com> 2020-10-08 22:39 ` [PATCH 1/2] extcon: add driver for TI TUSB320 Michael Auchter 2020-10-08 22:39 ` [PATCH 2/2] dt-bindings: extcon: add binding for TUSB320 Michael Auchter 2020-10-09 1:02 ` Chanwoo Choi 2020-10-09 1:05 ` [PATCH 1/2] extcon: add driver for TI TUSB320 Chanwoo Choi [not found] <CGME20201015140757epcas1p43b728b2b67e9ded476a46de127e2ce8b@epcas1p4.samsung.com> 2020-10-15 14:07 ` Michael Auchter 2020-10-19 10:24 ` Chanwoo Choi
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).