提交 d3a9ff51 编写于 作者: G Greg Kroah-Hartman

Merge tag 'extcon-next-for-5.10-v2' of...

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

Chanwoo writes:

Detailed description for this pull request:

1. Update extcon driver with minor updates:
- Covert the devicetree binding format from txt to yaml and edit
  the bidning document for extcon-ptn5150.c.

- Clean-up the code of extcon-ptn5150.c without any behavior changes.

- Replace HTTP links with HTTPS ones on extcon-palmas.c and extcon-usb-gpio.c.

- Return the proper error code on extcon-max14577/max77693/max77843.c.

- Simplify with dev_err_probe() on extcon-palmas.c.

- Use module_platform_driver to simplify the code on extcon-axp288.c.

2. Update MAINTAINERS
- Add Krzysztof Kozlowski as maintainer of NXP PTN5150A CC/extcon driver
to provide review, feedback and testing.

* tag 'extcon-next-for-5.10-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon: (25 commits)
  extcon: axp288: Use module_platform_driver to simplify the code
  extcon: ptn5150: Do not print error during probe if nothing is attached
  extcon: ptn5150: Use defines for registers
  extcon: palmas: Simplify with dev_err_probe()
  extcon: max8997: Return error code of extcon_dev_allocate()
  extcon: max77843: Return error code of extcon_dev_allocate()
  extcon: max77693: Return error code of extcon_dev_allocate()
  extcon: max14577: Return error code of extcon_dev_allocate()
  extcon: ptn5150: Set the VBUS and POLARITY property capability
  extcon: ptn5150: Switch to GENMASK() and BIT() macros
  extcon: ptn5150: Deduplicate parts of dev_err_probe()
  extcon: Replace HTTP links with HTTPS ones
  MAINTAINERS: Add entry for NXP PTN5150A CC driver
  extcon: ptn5150: Convert to .probe_new
  extcon: ptn5150: Convert to module_i2c_driver
  extcon: ptn5150: Reduce the amount of logs on deferred probe
  extcon: ptn5150: Make 'vbus-gpios' optional
  extcon: ptn5150: Check current USB mode when probing
  extcon: ptn5150: Lower the noisiness of probe
  extcon: ptn5150: Simplify getting vbus-gpios with flags
  ...
* PTN5150 CC (Configuration Channel) Logic device
PTN5150 is a small thin low power CC logic chip supporting the USB Type-C
connector application with CC control logic detection and indication functions.
It is interfaced to the host controller using an I2C interface.
Required properties:
- compatible: should be "nxp,ptn5150"
- reg: specifies the I2C slave address of the device
- int-gpio: should contain a phandle and GPIO specifier for the GPIO pin
connected to the PTN5150's INTB pin.
- vbus-gpio: should contain a phandle and GPIO specifier for the GPIO pin which
is used to control VBUS.
- pinctrl-names : a pinctrl state named "default" must be defined.
- pinctrl-0 : phandle referencing pin configuration of interrupt and vbus
control.
Example:
ptn5150@1d {
compatible = "nxp,ptn5150";
reg = <0x1d>;
int-gpio = <&msmgpio 78 GPIO_ACTIVE_HIGH>;
vbus-gpio = <&msmgpio 148 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&ptn5150_default>;
status = "okay";
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/extcon/extcon-ptn5150.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: PTN5150 CC (Configuration Channel) Logic device
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
description: |
PTN5150 is a small thin low power CC logic chip supporting the USB Type-C
connector application with CC control logic detection and indication
functions. It is interfaced to the host controller using an I2C interface.
properties:
compatible:
const: nxp,ptn5150
int-gpios:
deprecated: true
description:
GPIO pin (input) connected to the PTN5150's INTB pin.
Use "interrupts" instead.
interrupts:
maxItems: 1
reg:
maxItems: 1
vbus-gpios:
description:
GPIO pin (output) used to control VBUS. If skipped, no such control
takes place.
required:
- compatible
- interrupts
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
ptn5150@1d {
compatible = "nxp,ptn5150";
reg = <0x1d>;
interrupt-parent = <&msmgpio>;
interrupts = <78 IRQ_TYPE_LEVEL_HIGH>;
vbus-gpios = <&msmgpio 148 GPIO_ACTIVE_HIGH>;
};
};
......@@ -12485,6 +12485,13 @@ F: drivers/iio/gyro/fxas21002c_core.c
F: drivers/iio/gyro/fxas21002c_i2c.c
F: drivers/iio/gyro/fxas21002c_spi.c
NXP PTN5150A CC LOGIC AND EXTCON DRIVER
M: Krzysztof Kozlowski <krzk@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml
F: drivers/extcon/extcon-ptn5150.c
NXP SGTL5000 DRIVER
M: Fabio Estevam <festevam@gmail.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
......
......@@ -491,18 +491,7 @@ static struct platform_driver axp288_extcon_driver = {
.pm = &axp288_extcon_pm_ops,
},
};
static int __init axp288_extcon_init(void)
{
return platform_driver_register(&axp288_extcon_driver);
}
module_init(axp288_extcon_init);
static void __exit axp288_extcon_exit(void)
{
platform_driver_unregister(&axp288_extcon_driver);
}
module_exit(axp288_extcon_exit);
module_platform_driver(axp288_extcon_driver);
MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
......
......@@ -713,7 +713,7 @@ static int max14577_muic_probe(struct platform_device *pdev)
max14577_extcon_cable);
if (IS_ERR(info->edev)) {
dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
return -ENOMEM;
return PTR_ERR(info->edev);
}
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
......
......@@ -1157,7 +1157,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
max77693_extcon_cable);
if (IS_ERR(info->edev)) {
dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
return -ENOMEM;
return PTR_ERR(info->edev);
}
ret = devm_extcon_dev_register(&pdev->dev, info->edev);
......
......@@ -845,7 +845,7 @@ static int max77843_muic_probe(struct platform_device *pdev)
max77843_extcon_cable);
if (IS_ERR(info->edev)) {
dev_err(&pdev->dev, "Failed to allocate memory for extcon\n");
ret = -ENODEV;
ret = PTR_ERR(info->edev);
goto err_muic_irq;
}
......
......@@ -674,7 +674,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
info->edev = devm_extcon_dev_allocate(&pdev->dev, max8997_extcon_cable);
if (IS_ERR(info->edev)) {
dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
ret = -ENOMEM;
ret = PTR_ERR(info->edev);
goto err_irq;
}
......
......@@ -2,7 +2,7 @@
/*
* Palmas USB transceiver driver
*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
* Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com
* Author: Graeme Gregory <gg@slimlogic.co.uk>
* Author: Kishon Vijay Abraham I <kishon@ti.com>
* Based on twl6030_usb.c
......@@ -205,21 +205,15 @@ static int palmas_usb_probe(struct platform_device *pdev)
palmas_usb->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id",
GPIOD_IN);
if (PTR_ERR(palmas_usb->id_gpiod) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} else if (IS_ERR(palmas_usb->id_gpiod)) {
dev_err(&pdev->dev, "failed to get id gpio\n");
return PTR_ERR(palmas_usb->id_gpiod);
}
if (IS_ERR(palmas_usb->id_gpiod))
return dev_err_probe(&pdev->dev, PTR_ERR(palmas_usb->id_gpiod),
"failed to get id gpio\n");
palmas_usb->vbus_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus",
GPIOD_IN);
if (PTR_ERR(palmas_usb->vbus_gpiod) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} else if (IS_ERR(palmas_usb->vbus_gpiod)) {
dev_err(&pdev->dev, "failed to get vbus gpio\n");
return PTR_ERR(palmas_usb->vbus_gpiod);
}
if (IS_ERR(palmas_usb->vbus_gpiod))
return dev_err_probe(&pdev->dev, PTR_ERR(palmas_usb->vbus_gpiod),
"failed to get id gpio\n");
if (palmas_usb->enable_id_detection && palmas_usb->id_gpiod) {
palmas_usb->enable_id_detection = false;
......
......@@ -5,7 +5,9 @@
// Based on extcon-sm5502.c driver
// Copyright (c) 2018-2019 by Vijai Kumar K
// Author: Vijai Kumar K <vijaikumar.kanagarajan@gmail.com>
// Copyright (c) 2020 Krzysztof Kozlowski <krzk@kernel.org>
#include <linux/bitfield.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
......@@ -17,46 +19,28 @@
#include <linux/gpio/consumer.h>
/* PTN5150 registers */
enum ptn5150_reg {
PTN5150_REG_DEVICE_ID = 0x01,
PTN5150_REG_CONTROL,
PTN5150_REG_INT_STATUS,
PTN5150_REG_CC_STATUS,
PTN5150_REG_CON_DET = 0x09,
PTN5150_REG_VCONN_STATUS,
PTN5150_REG_RESET,
PTN5150_REG_INT_MASK = 0x18,
PTN5150_REG_INT_REG_STATUS,
PTN5150_REG_END,
};
#define PTN5150_REG_DEVICE_ID 0x01
#define PTN5150_REG_CONTROL 0x02
#define PTN5150_REG_INT_STATUS 0x03
#define PTN5150_REG_CC_STATUS 0x04
#define PTN5150_REG_CON_DET 0x09
#define PTN5150_REG_VCONN_STATUS 0x0a
#define PTN5150_REG_RESET 0x0b
#define PTN5150_REG_INT_MASK 0x18
#define PTN5150_REG_INT_REG_STATUS 0x19
#define PTN5150_REG_END PTN5150_REG_INT_REG_STATUS
#define PTN5150_DFP_ATTACHED 0x1
#define PTN5150_UFP_ATTACHED 0x2
/* Define PTN5150 MASK/SHIFT constant */
#define PTN5150_REG_DEVICE_ID_VENDOR_SHIFT 0
#define PTN5150_REG_DEVICE_ID_VENDOR_MASK \
(0x3 << PTN5150_REG_DEVICE_ID_VENDOR_SHIFT)
#define PTN5150_REG_DEVICE_ID_VERSION_SHIFT 3
#define PTN5150_REG_DEVICE_ID_VERSION_MASK \
(0x1f << PTN5150_REG_DEVICE_ID_VERSION_SHIFT)
#define PTN5150_REG_CC_PORT_ATTACHMENT_SHIFT 2
#define PTN5150_REG_CC_PORT_ATTACHMENT_MASK \
(0x7 << PTN5150_REG_CC_PORT_ATTACHMENT_SHIFT)
#define PTN5150_REG_DEVICE_ID_VERSION GENMASK(7, 3)
#define PTN5150_REG_DEVICE_ID_VENDOR GENMASK(2, 0)
#define PTN5150_REG_CC_VBUS_DETECTION_SHIFT 7
#define PTN5150_REG_CC_VBUS_DETECTION_MASK \
(0x1 << PTN5150_REG_CC_VBUS_DETECTION_SHIFT)
#define PTN5150_REG_INT_CABLE_ATTACH_SHIFT 0
#define PTN5150_REG_INT_CABLE_ATTACH_MASK \
(0x1 << PTN5150_REG_INT_CABLE_ATTACH_SHIFT)
#define PTN5150_REG_INT_CABLE_DETACH_SHIFT 1
#define PTN5150_REG_INT_CABLE_DETACH_MASK \
(0x1 << PTN5150_REG_CC_CABLE_DETACH_SHIFT)
#define PTN5150_REG_CC_PORT_ATTACHMENT GENMASK(4, 2)
#define PTN5150_REG_CC_VBUS_DETECTION BIT(7)
#define PTN5150_REG_INT_CABLE_ATTACH_MASK BIT(0)
#define PTN5150_REG_INT_CABLE_DETACH_MASK BIT(1)
struct ptn5150_info {
struct device *dev;
......@@ -83,12 +67,45 @@ static const struct regmap_config ptn5150_regmap_config = {
.max_register = PTN5150_REG_END,
};
static void ptn5150_check_state(struct ptn5150_info *info)
{
unsigned int port_status, reg_data, vbus;
int ret;
ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data);
if (ret) {
dev_err(info->dev, "failed to read CC STATUS %d\n", ret);
return;
}
port_status = FIELD_GET(PTN5150_REG_CC_PORT_ATTACHMENT, reg_data);
switch (port_status) {
case PTN5150_DFP_ATTACHED:
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false);
gpiod_set_value_cansleep(info->vbus_gpiod, 0);
extcon_set_state_sync(info->edev, EXTCON_USB, true);
break;
case PTN5150_UFP_ATTACHED:
extcon_set_state_sync(info->edev, EXTCON_USB, false);
vbus = FIELD_GET(PTN5150_REG_CC_VBUS_DETECTION, reg_data);
if (vbus)
gpiod_set_value_cansleep(info->vbus_gpiod, 0);
else
gpiod_set_value_cansleep(info->vbus_gpiod, 1);
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);
break;
default:
break;
}
}
static void ptn5150_irq_work(struct work_struct *work)
{
struct ptn5150_info *info = container_of(work,
struct ptn5150_info, irq_work);
int ret = 0;
unsigned int reg_data;
unsigned int int_status;
if (!info->edev)
......@@ -96,13 +113,6 @@ static void ptn5150_irq_work(struct work_struct *work)
mutex_lock(&info->mutex);
ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data);
if (ret) {
dev_err(info->dev, "failed to read CC STATUS %d\n", ret);
mutex_unlock(&info->mutex);
return;
}
/* Clear interrupt. Read would clear the register */
ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &int_status);
if (ret) {
......@@ -116,47 +126,13 @@ static void ptn5150_irq_work(struct work_struct *work)
cable_attach = int_status & PTN5150_REG_INT_CABLE_ATTACH_MASK;
if (cable_attach) {
unsigned int port_status;
unsigned int vbus;
port_status = ((reg_data &
PTN5150_REG_CC_PORT_ATTACHMENT_MASK) >>
PTN5150_REG_CC_PORT_ATTACHMENT_SHIFT);
switch (port_status) {
case PTN5150_DFP_ATTACHED:
extcon_set_state_sync(info->edev,
EXTCON_USB_HOST, false);
gpiod_set_value(info->vbus_gpiod, 0);
extcon_set_state_sync(info->edev, EXTCON_USB,
true);
break;
case PTN5150_UFP_ATTACHED:
extcon_set_state_sync(info->edev, EXTCON_USB,
false);
vbus = ((reg_data &
PTN5150_REG_CC_VBUS_DETECTION_MASK) >>
PTN5150_REG_CC_VBUS_DETECTION_SHIFT);
if (vbus)
gpiod_set_value(info->vbus_gpiod, 0);
else
gpiod_set_value(info->vbus_gpiod, 1);
extcon_set_state_sync(info->edev,
EXTCON_USB_HOST, true);
break;
default:
dev_err(info->dev,
"Unknown Port status : %x\n",
port_status);
break;
}
ptn5150_check_state(info);
} else {
extcon_set_state_sync(info->edev,
EXTCON_USB_HOST, false);
extcon_set_state_sync(info->edev,
EXTCON_USB, false);
gpiod_set_value(info->vbus_gpiod, 0);
gpiod_set_value_cansleep(info->vbus_gpiod, 0);
}
}
......@@ -194,13 +170,10 @@ static int ptn5150_init_dev_type(struct ptn5150_info *info)
return -EINVAL;
}
vendor_id = ((reg_data & PTN5150_REG_DEVICE_ID_VENDOR_MASK) >>
PTN5150_REG_DEVICE_ID_VENDOR_SHIFT);
version_id = ((reg_data & PTN5150_REG_DEVICE_ID_VERSION_MASK) >>
PTN5150_REG_DEVICE_ID_VERSION_SHIFT);
dev_info(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
version_id, vendor_id);
vendor_id = FIELD_GET(PTN5150_REG_DEVICE_ID_VENDOR, reg_data);
version_id = FIELD_GET(PTN5150_REG_DEVICE_ID_VERSION, reg_data);
dev_dbg(info->dev, "Device type: version: 0x%x, vendor: 0x%x\n",
version_id, vendor_id);
/* Clear any existing interrupts */
ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &reg_data);
......@@ -221,8 +194,7 @@ static int ptn5150_init_dev_type(struct ptn5150_info *info)
return 0;
}
static int ptn5150_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
static int ptn5150_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
struct device_node *np = i2c->dev.of_node;
......@@ -239,20 +211,15 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c,
info->dev = &i2c->dev;
info->i2c = i2c;
info->int_gpiod = devm_gpiod_get(&i2c->dev, "int", GPIOD_IN);
if (IS_ERR(info->int_gpiod)) {
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(&i2c->dev, "vbus", GPIOD_OUT_LOW);
if (IS_ERR(info->vbus_gpiod)) {
dev_err(dev, "failed to get VBUS GPIO\n");
return PTR_ERR(info->vbus_gpiod);
}
ret = gpiod_direction_output(info->vbus_gpiod, 0);
if (ret) {
dev_err(dev, "failed to set VBUS GPIO direction\n");
return -EINVAL;
ret = PTR_ERR(info->vbus_gpiod);
if (ret == -ENOENT) {
dev_info(dev, "No VBUS GPIO, ignoring VBUS control\n");
info->vbus_gpiod = NULL;
} else {
return dev_err_probe(dev, ret, "failed to get VBUS GPIO\n");
}
}
mutex_init(&info->mutex);
......@@ -261,28 +228,34 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c,
info->regmap = devm_regmap_init_i2c(i2c, &ptn5150_regmap_config);
if (IS_ERR(info->regmap)) {
ret = PTR_ERR(info->regmap);
dev_err(info->dev, "failed to allocate register map: %d\n",
ret);
return ret;
return dev_err_probe(info->dev, PTR_ERR(info->regmap),
"failed to allocate register map\n");
}
if (info->int_gpiod) {
if (i2c->irq > 0) {
info->irq = i2c->irq;
} else {
info->int_gpiod = devm_gpiod_get(&i2c->dev, "int", GPIOD_IN);
if (IS_ERR(info->int_gpiod)) {
return dev_err_probe(dev, PTR_ERR(info->int_gpiod),
"failed to get INT GPIO\n");
}
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;
}
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 */
......@@ -299,11 +272,26 @@ 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);
/* Initialize PTN5150 device and print vendor id and version id */
ret = ptn5150_init_dev_type(info);
if (ret)
return -EINVAL;
/*
* Update current extcon state if for example OTG connection was there
* before the probe
*/
mutex_lock(&info->mutex);
ptn5150_check_state(info);
mutex_unlock(&info->mutex);
return 0;
}
......@@ -324,16 +312,12 @@ static struct i2c_driver ptn5150_i2c_driver = {
.name = "ptn5150",
.of_match_table = ptn5150_dt_match,
},
.probe = ptn5150_i2c_probe,
.probe_new = ptn5150_i2c_probe,
.id_table = ptn5150_i2c_id,
};
static int __init ptn5150_i2c_init(void)
{
return i2c_add_driver(&ptn5150_i2c_driver);
}
subsys_initcall(ptn5150_i2c_init);
module_i2c_driver(ptn5150_i2c_driver);
MODULE_DESCRIPTION("NXP PTN5150 CC logic Extcon driver");
MODULE_AUTHOR("Vijai Kumar K <vijaikumar.kanagarajan@gmail.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_LICENSE("GPL v2");
......@@ -2,7 +2,7 @@
/**
* drivers/extcon/extcon-usb-gpio.c - USB GPIO extcon driver
*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com
* Author: Roger Quadros <rogerq@ti.com>
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册