Commit b195b20b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'extcon-next-for-5.13' of...

Merge tag 'extcon-next-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next

Chanwoo writes:

Update extcon next for v5.13

Detailed description for this pull request:

1. Update extcon provider driver
- Add the support of charging interrupt to detect charger connector
for extcon-max8997.c

- Detect OTG when USB_ID pin is connected to ground for extcon-sm5502.c

- Add the support for VBUS detection for extcon-qcom-spmi-misc.c
and replace qcom,pm8941-misc binding document with yaml style.

* tag 'extcon-next-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon:
  extcon: qcom-spmi: Add support for VBUS detection
  bindings: pm8941-misc: Add support for VBUS detection
  bindings: pm8941-misc: Convert bindings to YAML
  extcon: sm5502: Detect OTG when USB_ID is connected to ground
  extcon: max8997: Add CHGINS and CHGRM interrupt handling
parents d7ea31ca 7b1222b2
Qualcomm's PM8941 USB ID Extcon device
Some Qualcomm PMICs have a "misc" module that can be used to detect when
the USB ID pin has been pulled low or high.
PROPERTIES
- compatible:
Usage: required
Value type: <string>
Definition: Should contain "qcom,pm8941-misc";
- reg:
Usage: required
Value type: <u32>
Definition: Should contain the offset to the misc address space
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: Should contain the usb id interrupt
- interrupt-names:
Usage: required
Value type: <stringlist>
Definition: Should contain the string "usb_id" for the usb id interrupt
Example:
pmic {
usb_id: misc@900 {
compatible = "qcom,pm8941-misc";
reg = <0x900>;
interrupts = <0x0 0x9 0 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "usb_id";
};
}
usb-controller {
extcon = <&usb_id>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/extcon/qcom,pm8941-misc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. PM8941 USB ID Extcon device
maintainers:
- Guru Das Srinagesh <gurus@codeaurora.org>
description: |
Some Qualcomm PMICs have a "misc" module that can be used to detect when
the USB ID pin has been pulled low or high.
properties:
compatible:
items:
- const: qcom,pm8941-misc
reg:
maxItems: 1
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
items:
- const: usb_id
- const: usb_vbus
required:
- compatible
- reg
- interrupts
- interrupt-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
pmic {
#address-cells = <1>;
#size-cells = <0>;
interrupt-controller;
#interrupt-cells = <4>;
usb_id: misc@900 {
compatible = "qcom,pm8941-misc";
reg = <0x900>;
interrupts = <0x0 0x9 0 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "usb_id";
};
};
usb-controller {
extcon = <&usb_id>;
};
...@@ -44,6 +44,8 @@ static struct max8997_muic_irq muic_irqs[] = { ...@@ -44,6 +44,8 @@ static struct max8997_muic_irq muic_irqs[] = {
{ MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" }, { MAX8997_MUICIRQ_ChgDetRun, "muic-CHGDETRUN" },
{ MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" }, { MAX8997_MUICIRQ_ChgTyp, "muic-CHGTYP" },
{ MAX8997_MUICIRQ_OVP, "muic-OVP" }, { MAX8997_MUICIRQ_OVP, "muic-OVP" },
{ MAX8997_PMICIRQ_CHGINS, "pmic-CHGINS" },
{ MAX8997_PMICIRQ_CHGRM, "pmic-CHGRM" },
}; };
/* Define supported cable type */ /* Define supported cable type */
...@@ -538,6 +540,8 @@ static void max8997_muic_irq_work(struct work_struct *work) ...@@ -538,6 +540,8 @@ static void max8997_muic_irq_work(struct work_struct *work)
case MAX8997_MUICIRQ_DCDTmr: case MAX8997_MUICIRQ_DCDTmr:
case MAX8997_MUICIRQ_ChgDetRun: case MAX8997_MUICIRQ_ChgDetRun:
case MAX8997_MUICIRQ_ChgTyp: case MAX8997_MUICIRQ_ChgTyp:
case MAX8997_PMICIRQ_CHGINS:
case MAX8997_PMICIRQ_CHGRM:
/* Handle charger cable */ /* Handle charger cable */
ret = max8997_muic_chg_handler(info); ret = max8997_muic_chg_handler(info);
break; break;
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/** /**
* extcon-qcom-spmi-misc.c - Qualcomm USB extcon driver to support USB ID * extcon-qcom-spmi-misc.c - Qualcomm USB extcon driver to support USB ID
* detection based on extcon-usb-gpio.c. * and VBUS detection based on extcon-usb-gpio.c.
* *
* Copyright (C) 2016 Linaro, Ltd. * Copyright (C) 2016 Linaro, Ltd.
* Stephen Boyd <stephen.boyd@linaro.org> * Stephen Boyd <stephen.boyd@linaro.org>
...@@ -21,30 +21,56 @@ ...@@ -21,30 +21,56 @@
struct qcom_usb_extcon_info { struct qcom_usb_extcon_info {
struct extcon_dev *edev; struct extcon_dev *edev;
int irq; int id_irq;
int vbus_irq;
struct delayed_work wq_detcable; struct delayed_work wq_detcable;
unsigned long debounce_jiffies; unsigned long debounce_jiffies;
}; };
static const unsigned int qcom_usb_extcon_cable[] = { static const unsigned int qcom_usb_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST, EXTCON_USB_HOST,
EXTCON_NONE, EXTCON_NONE,
}; };
static void qcom_usb_extcon_detect_cable(struct work_struct *work) static void qcom_usb_extcon_detect_cable(struct work_struct *work)
{ {
bool id; bool state = false;
int ret; int ret;
union extcon_property_value val;
struct qcom_usb_extcon_info *info = container_of(to_delayed_work(work), struct qcom_usb_extcon_info *info = container_of(to_delayed_work(work),
struct qcom_usb_extcon_info, struct qcom_usb_extcon_info,
wq_detcable); wq_detcable);
if (info->id_irq > 0) {
/* check ID and update cable state */ /* check ID and update cable state */
ret = irq_get_irqchip_state(info->irq, IRQCHIP_STATE_LINE_LEVEL, &id); ret = irq_get_irqchip_state(info->id_irq,
IRQCHIP_STATE_LINE_LEVEL, &state);
if (ret) if (ret)
return; return;
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !id); if (!state) {
val.intval = true;
extcon_set_property(info->edev, EXTCON_USB_HOST,
EXTCON_PROP_USB_SS, val);
}
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !state);
}
if (info->vbus_irq > 0) {
/* check VBUS and update cable state */
ret = irq_get_irqchip_state(info->vbus_irq,
IRQCHIP_STATE_LINE_LEVEL, &state);
if (ret)
return;
if (state) {
val.intval = true;
extcon_set_property(info->edev, EXTCON_USB,
EXTCON_PROP_USB_SS, val);
}
extcon_set_state_sync(info->edev, EXTCON_USB, state);
}
} }
static irqreturn_t qcom_usb_irq_handler(int irq, void *dev_id) static irqreturn_t qcom_usb_irq_handler(int irq, void *dev_id)
...@@ -79,14 +105,22 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev) ...@@ -79,14 +105,22 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
return ret; return ret;
} }
ret = extcon_set_property_capability(info->edev,
EXTCON_USB, EXTCON_PROP_USB_SS);
ret |= extcon_set_property_capability(info->edev,
EXTCON_USB_HOST, EXTCON_PROP_USB_SS);
if (ret) {
dev_err(dev, "failed to register extcon props rc=%d\n",
ret);
return ret;
}
info->debounce_jiffies = msecs_to_jiffies(USB_ID_DEBOUNCE_MS); info->debounce_jiffies = msecs_to_jiffies(USB_ID_DEBOUNCE_MS);
INIT_DELAYED_WORK(&info->wq_detcable, qcom_usb_extcon_detect_cable); INIT_DELAYED_WORK(&info->wq_detcable, qcom_usb_extcon_detect_cable);
info->irq = platform_get_irq_byname(pdev, "usb_id"); info->id_irq = platform_get_irq_byname(pdev, "usb_id");
if (info->irq < 0) if (info->id_irq > 0) {
return info->irq; ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
ret = devm_request_threaded_irq(dev, info->irq, NULL,
qcom_usb_irq_handler, qcom_usb_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
...@@ -95,6 +129,25 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev) ...@@ -95,6 +129,25 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
dev_err(dev, "failed to request handler for ID IRQ\n"); dev_err(dev, "failed to request handler for ID IRQ\n");
return ret; return ret;
} }
}
info->vbus_irq = platform_get_irq_byname(pdev, "usb_vbus");
if (info->vbus_irq > 0) {
ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
qcom_usb_irq_handler,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
pdev->name, info);
if (ret < 0) {
dev_err(dev, "failed to request handler for VBUS IRQ\n");
return ret;
}
}
if (info->id_irq < 0 && info->vbus_irq < 0) {
dev_err(dev, "ID and VBUS IRQ not found\n");
return -EINVAL;
}
platform_set_drvdata(pdev, info); platform_set_drvdata(pdev, info);
device_init_wakeup(dev, 1); device_init_wakeup(dev, 1);
...@@ -120,8 +173,12 @@ static int qcom_usb_extcon_suspend(struct device *dev) ...@@ -120,8 +173,12 @@ static int qcom_usb_extcon_suspend(struct device *dev)
struct qcom_usb_extcon_info *info = dev_get_drvdata(dev); struct qcom_usb_extcon_info *info = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
if (device_may_wakeup(dev)) if (device_may_wakeup(dev)) {
ret = enable_irq_wake(info->irq); if (info->id_irq > 0)
ret = enable_irq_wake(info->id_irq);
if (info->vbus_irq > 0)
ret = enable_irq_wake(info->vbus_irq);
}
return ret; return ret;
} }
...@@ -131,8 +188,12 @@ static int qcom_usb_extcon_resume(struct device *dev) ...@@ -131,8 +188,12 @@ static int qcom_usb_extcon_resume(struct device *dev)
struct qcom_usb_extcon_info *info = dev_get_drvdata(dev); struct qcom_usb_extcon_info *info = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
if (device_may_wakeup(dev)) if (device_may_wakeup(dev)) {
ret = disable_irq_wake(info->irq); if (info->id_irq > 0)
ret = disable_irq_wake(info->id_irq);
if (info->vbus_irq > 0)
ret = disable_irq_wake(info->vbus_irq);
}
return ret; return ret;
} }
......
...@@ -144,6 +144,7 @@ enum sm5502_muic_acc_type { ...@@ -144,6 +144,7 @@ enum sm5502_muic_acc_type {
SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE = 0x3e, /* | 001|11110| */ SM5502_MUIC_ADC_AUDIO_TYPE1_FULL_REMOTE = 0x3e, /* | 001|11110| */
SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END = 0x5e, /* | 010|11110| */ SM5502_MUIC_ADC_AUDIO_TYPE1_SEND_END = 0x5e, /* | 010|11110| */
/* |Dev Type1|--ADC| */ /* |Dev Type1|--ADC| */
SM5502_MUIC_ADC_GROUND_USB_OTG = 0x80, /* | 100|00000| */
SM5502_MUIC_ADC_OPEN_USB = 0x5f, /* | 010|11111| */ SM5502_MUIC_ADC_OPEN_USB = 0x5f, /* | 010|11111| */
SM5502_MUIC_ADC_OPEN_TA = 0xdf, /* | 110|11111| */ SM5502_MUIC_ADC_OPEN_TA = 0xdf, /* | 110|11111| */
SM5502_MUIC_ADC_OPEN_USB_OTG = 0xff, /* | 111|11111| */ SM5502_MUIC_ADC_OPEN_USB_OTG = 0xff, /* | 111|11111| */
...@@ -291,11 +292,27 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) ...@@ -291,11 +292,27 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
* connected with to MUIC device. * connected with to MUIC device.
*/ */
cable_type = adc & SM5502_REG_ADC_MASK; cable_type = adc & SM5502_REG_ADC_MASK;
if (cable_type == SM5502_MUIC_ADC_GROUND)
return SM5502_MUIC_ADC_GROUND;
switch (cable_type) { switch (cable_type) {
case SM5502_MUIC_ADC_GROUND: case SM5502_MUIC_ADC_GROUND:
ret = regmap_read(info->regmap, SM5502_REG_DEV_TYPE1,
&dev_type1);
if (ret) {
dev_err(info->dev, "failed to read DEV_TYPE1 reg\n");
return ret;
}
switch (dev_type1) {
case SM5502_REG_DEV_TYPE1_USB_OTG_MASK:
cable_type = SM5502_MUIC_ADC_GROUND_USB_OTG;
break;
default:
dev_dbg(info->dev,
"cannot identify the cable type: adc(0x%x), dev_type1(0x%x)\n",
adc, dev_type1);
return -EINVAL;
}
break;
case SM5502_MUIC_ADC_SEND_END_BUTTON: case SM5502_MUIC_ADC_SEND_END_BUTTON:
case SM5502_MUIC_ADC_REMOTE_S1_BUTTON: case SM5502_MUIC_ADC_REMOTE_S1_BUTTON:
case SM5502_MUIC_ADC_REMOTE_S2_BUTTON: case SM5502_MUIC_ADC_REMOTE_S2_BUTTON:
...@@ -396,6 +413,7 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, ...@@ -396,6 +413,7 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
con_sw = DM_DP_SWITCH_OPEN; con_sw = DM_DP_SWITCH_OPEN;
vbus_sw = VBUSIN_SWITCH_VBUSOUT; vbus_sw = VBUSIN_SWITCH_VBUSOUT;
break; break;
case SM5502_MUIC_ADC_GROUND_USB_OTG:
case SM5502_MUIC_ADC_OPEN_USB_OTG: case SM5502_MUIC_ADC_OPEN_USB_OTG:
id = EXTCON_USB_HOST; id = EXTCON_USB_HOST;
con_sw = DM_DP_SWITCH_USB; con_sw = DM_DP_SWITCH_USB;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment