[PATCH v1 6/9] extcon: extcon-ptn5150: Set and get the VBUS and POLARITY property state

From: Ramuthevar,Vadivel MuruganX
Date: Tue Aug 18 2020 - 02:57:57 EST


From: Ramuthevar Vadivel Murugan <vadivel.muruganx.ramuthevar@xxxxxxxxxxxxxxx>

Set and get the VBUS and POLARITY property state.

Signed-off-by: Ramuthevar Vadivel Murugan <vadivel.muruganx.ramuthevar@xxxxxxxxxxxxxxx>
---
drivers/extcon/extcon-ptn5150.c | 75 ++++++++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 20 deletions(-)

diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c
index 31b7cbf1551d..5612dc0ef2af 100644
--- a/drivers/extcon/extcon-ptn5150.c
+++ b/drivers/extcon/extcon-ptn5150.c
@@ -64,6 +64,12 @@ static const unsigned int ptn5150_extcon_cable[] = {
EXTCON_NONE,
};

+enum {
+ POLARITY_NC,
+ POLARITY_CC1,
+ POLARITY_CC2,
+};
+
static const struct regmap_config ptn5150_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -74,9 +80,14 @@ static void ptn5150_irq_work(struct work_struct *work)
{
struct ptn5150_info *info = container_of(work,
struct ptn5150_info, irq_work);
- int ret = 0;
+ int ret = 0, x = 0;
unsigned int reg_data;
unsigned int int_status;
+ union extcon_property_value vbus_detected;
+ union extcon_property_value flipped;
+ bool host_vbus = false;
+ bool host = false;
+ bool dev = false;

if (!info->edev)
return;
@@ -90,6 +101,11 @@ static void ptn5150_irq_work(struct work_struct *work)
return;
}

+ dev_dbg(info->dev, "CC POLARITY status:%x\n", reg_data);
+ x = FIELD_GET(PTN5150_REG_INT_CABLE_ATTACH_MASK, reg_data);
+ flipped.intval = (x == POLARITY_CC2);
+ vbus_detected.intval = !!(reg_data & PTN5150_REG_CC_VBUS_DETECTION);
+
/* Clear interrupt. Read would clear the register */
ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &int_status);
if (ret) {
@@ -111,6 +127,7 @@ static void ptn5150_irq_work(struct work_struct *work)

switch (port_status) {
case PTN5150_DFP_ATTACHED:
+ dev = true;
extcon_set_state_sync(info->edev,
EXTCON_USB_HOST, false);
gpiod_set_value(info->vbus_gpiod, 0);
@@ -118,6 +135,8 @@ static void ptn5150_irq_work(struct work_struct *work)
true);
break;
case PTN5150_UFP_ATTACHED:
+ host_vbus = !vbus_detected.intval;
+ host = true;
extcon_set_state_sync(info->edev, EXTCON_USB,
false);
vbus = FIELD_GET(PTN5150_REG_CC_VBUS_DETECTION,
@@ -127,6 +146,9 @@ static void ptn5150_irq_work(struct work_struct *work)
else
gpiod_set_value(info->vbus_gpiod, 1);

+ extcon_set_property(info->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_TYPEC_POLARITY,
+ flipped);
extcon_set_state_sync(info->edev,
EXTCON_USB_HOST, true);
break;
@@ -145,6 +167,8 @@ static void ptn5150_irq_work(struct work_struct *work)
}
}

+ if (host_vbus)
+ gpiod_set_value(info->vbus_gpiod, host_vbus);
/* Clear interrupt. Read would clear the register */
ret = regmap_read(info->regmap, PTN5150_REG_INT_REG_STATUS,
&int_status);
@@ -155,6 +179,11 @@ static void ptn5150_irq_work(struct work_struct *work)
return;
}

+ extcon_set_property(info->edev, host ? EXTCON_USB_HOST : EXTCON_USB,
+ EXTCON_PROP_USB_VBUS, vbus_detected);
+ extcon_set_state_sync(info->edev, EXTCON_USB_HOST, host);
+ extcon_set_state_sync(info->edev, EXTCON_USB, dev);
+
mutex_unlock(&info->mutex);
}

@@ -227,7 +256,7 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c,
dev_err(dev, "failed to get INT GPIO\n");
return PTR_ERR(info->int_gpiod);
}
- info->vbus_gpiod = devm_gpiod_get(&i2c->dev, "vbus", GPIOD_IN);
+ info->vbus_gpiod = devm_gpiod_get_optional(&i2c->dev, "vbus", GPIOD_IN);
if (IS_ERR(info->vbus_gpiod)) {
dev_err(dev, "failed to get VBUS GPIO\n");
return PTR_ERR(info->vbus_gpiod);
@@ -250,24 +279,6 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c,
return ret;
}

- if (info->int_gpiod) {
- info->irq = gpiod_to_irq(info->int_gpiod);
- if (info->irq < 0) {
- dev_err(dev, "failed to get INTB IRQ\n");
- return info->irq;
- }
-
- ret = devm_request_threaded_irq(dev, info->irq, NULL,
- ptn5150_irq_handler,
- IRQF_TRIGGER_FALLING |
- IRQF_ONESHOT,
- i2c->name, info);
- if (ret < 0) {
- dev_err(dev, "failed to request handler for INTB IRQ\n");
- return ret;
- }
- }
-
/* Allocate extcon device */
info->edev = devm_extcon_dev_allocate(info->dev, ptn5150_extcon_cable);
if (IS_ERR(info->edev)) {
@@ -282,6 +293,30 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c,
return ret;
}

+ extcon_set_property_capability(info->edev, EXTCON_USB,
+ EXTCON_PROP_USB_VBUS);
+ extcon_set_property_capability(info->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_VBUS);
+ extcon_set_property_capability(info->edev, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_TYPEC_POLARITY);
+
+ info->irq = gpiod_to_irq(info->int_gpiod);
+ if (info->irq < 0) {
+ dev_err(dev, "failed to get INTB IRQ\n");
+ return info->irq;
+ }
+
+ ret = devm_request_threaded_irq(dev, info->irq, NULL, ptn5150_irq_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ i2c->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for INTB IRQ\n");
+ return ret;
+ }
+
+ /* PNT5150 interrupt is level based, read result once in case we */
+ schedule_work(&info->irq_work);
+
/* Initialize PTN5150 device and print vendor id and version id */
ret = ptn5150_init_dev_type(info);
if (ret)
--
2.11.0