mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 13:34:30 +00:00
Update extcon next for v5.16
Detailed description for this pull request: 1. Add support for TUSB320L and update tusb320 extcon driver - The existing extcon-usbc-tusb320 driver is updated for supporting the mode setting and reset operation. Also, this driver supports the simliar TUSB320L device at the same extcon-usbc-tusb320 extcon provider driver. 2. Use p-unit semaphone lock for register access for extcon-axp288 driver 3. Update the minor clean-up for extcon-max3355 and extcon-usb-gpio driver. -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEEsSpuqBtbWtRe4rLGnM3fLN7rz1MFAmF44TsWHGN3MDAuY2hv aUBzYW1zdW5nLmNvbQAKCRCczd8s3uvPU2wLD/48IvHZQUFatPwBgbGiKqCzCfdT 7cK8pewTGUdEFLe1kMZssy35k39KQzj8uU+leUBasZ9HCSMGv6MTj7j0RWkHyygR dkcT7jX0i1lK324pMGv/qH3BLJUJC+ayJiYf1xcOWX743ykqLl9nQSTjgRKv9nUP QErkeEn4sTWi5wn4h0ZiLvPiZKjNLeXymUoU0XDsX5ngIccMGo/J2G4fPTJRUtb6 kUN/Ep1niftu6MJVhGSjAFoyeNUWMEjNwk9E6RGLR2TW8EiNvOyiqAkx/EP+ad6p p5VrVoo1DwG/J1+VpQt+ugtOTib2GdiZ6Q5AfHxoQru93S/Yth91D83/CAPBpLOf AFLIv2uW/vrz6zvl3UDQ9JGZPQrlxhYhvkj10vi+FdxrQbW88pNTkiPBXrRsZ4jv 7zg0gX0Q8LW6nEusWuzi0UzKPA8pQAl9RnGIV9TgxpCTaWtpDT7ynyaNnGJ9fsen URZYvUs2H/UvZVgNrbJLPMY8LDQxF1fZArTT3/qBE8lgAkxg0e+zMmNP5UOamUUJ 9htr9tvOlFzI9IdOhmuMyk+yxYwsCHAkp6h+9tE7y8r+5gMdp/MmFN5RbsD9GGND uXmVUE5bqsYuQlEfquYnUX8aYWY5QLxmodlpQM2mPtVYDycg9ZR7y8Ubbb7iETYe nugbNhiJUMG+3stS6g== =qEVD -----END PGP SIGNATURE----- Merge tag 'extcon-next-for-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next Chanwoo writes: Update extcon next for v5.16 Detailed description for this pull request: 1. Add support for TUSB320L and update tusb320 extcon driver - The existing extcon-usbc-tusb320 driver is updated for supporting the mode setting and reset operation. Also, this driver supports the simliar TUSB320L device at the same extcon-usbc-tusb320 extcon provider driver. 2. Use p-unit semaphone lock for register access for extcon-axp288 driver 3. Update the minor clean-up for extcon-max3355 and extcon-usb-gpio driver. * tag 'extcon-next-for-5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon: dt-bindings: extcon: usbc-tusb320: Add TUSB320L compatible string extcon: usbc-tusb320: Add support for TUSB320L extcon: usbc-tusb320: Add support for mode setting and reset extcon: extcon-axp288: Use P-Unit semaphore lock for register accesses extcon: max3355: Drop unused include extcon: usb-gpio: Use the right includes
This commit is contained in:
commit
db788e6bf6
@ -11,7 +11,9 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,tusb320
|
||||
enum:
|
||||
- ti,tusb320
|
||||
- ti,tusb320l
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -23,7 +23,7 @@ config EXTCON_ADC_JACK
|
||||
|
||||
config EXTCON_AXP288
|
||||
tristate "X-Power AXP288 EXTCON support"
|
||||
depends on MFD_AXP20X && USB_SUPPORT && X86 && ACPI
|
||||
depends on MFD_AXP20X && USB_SUPPORT && X86 && ACPI && IOSF_MBI
|
||||
select USB_ROLE_SWITCH
|
||||
help
|
||||
Say Y here to enable support for USB peripheral detection
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/iosf_mbi.h>
|
||||
|
||||
/* Power source status register */
|
||||
#define PS_STAT_VBUS_TRIGGER BIT(0)
|
||||
@ -215,6 +216,10 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
|
||||
unsigned int cable = info->previous_cable;
|
||||
bool vbus_attach = false;
|
||||
|
||||
ret = iosf_mbi_block_punit_i2c_access();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
vbus_attach = axp288_get_vbus_attach(info);
|
||||
if (!vbus_attach)
|
||||
goto no_vbus;
|
||||
@ -253,6 +258,8 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
|
||||
}
|
||||
|
||||
no_vbus:
|
||||
iosf_mbi_unblock_punit_i2c_access();
|
||||
|
||||
extcon_set_state_sync(info->edev, info->previous_cable, false);
|
||||
if (info->previous_cable == EXTCON_CHG_USB_SDP)
|
||||
extcon_set_state_sync(info->edev, EXTCON_USB, false);
|
||||
@ -275,6 +282,8 @@ no_vbus:
|
||||
return 0;
|
||||
|
||||
dev_det_ret:
|
||||
iosf_mbi_unblock_punit_i2c_access();
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(info->dev, "failed to detect BC Mod\n");
|
||||
|
||||
@ -305,13 +314,23 @@ static irqreturn_t axp288_extcon_isr(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void axp288_extcon_enable(struct axp288_extcon_info *info)
|
||||
static int axp288_extcon_enable(struct axp288_extcon_info *info)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = iosf_mbi_block_punit_i2c_access();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
|
||||
BC_GLOBAL_RUN, 0);
|
||||
/* Enable the charger detection logic */
|
||||
regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
|
||||
BC_GLOBAL_RUN, BC_GLOBAL_RUN);
|
||||
|
||||
iosf_mbi_unblock_punit_i2c_access();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void axp288_put_role_sw(void *data)
|
||||
@ -384,10 +403,16 @@ static int axp288_extcon_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = iosf_mbi_block_punit_i2c_access();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
info->vbus_attach = axp288_get_vbus_attach(info);
|
||||
|
||||
axp288_extcon_log_rsi(info);
|
||||
|
||||
iosf_mbi_unblock_punit_i2c_access();
|
||||
|
||||
/* Initialize extcon device */
|
||||
info->edev = devm_extcon_dev_allocate(&pdev->dev,
|
||||
axp288_extcon_cables);
|
||||
@ -441,7 +466,9 @@ static int axp288_extcon_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Start charger cable type detection */
|
||||
axp288_extcon_enable(info);
|
||||
ret = axp288_extcon_enable(info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
device_init_wakeup(dev, true);
|
||||
platform_set_drvdata(pdev, info);
|
||||
|
@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/extcon-provider.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -7,18 +7,17 @@
|
||||
*/
|
||||
|
||||
#include <linux/extcon-provider.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
|
||||
|
||||
|
@ -19,15 +19,42 @@
|
||||
#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
|
||||
|
||||
#define TUSB320_REGA 0xa
|
||||
#define TUSB320L_REGA_DISABLE_TERM BIT(0)
|
||||
#define TUSB320_REGA_I2C_SOFT_RESET BIT(3)
|
||||
#define TUSB320_REGA_MODE_SELECT_SHIFT 4
|
||||
#define TUSB320_REGA_MODE_SELECT_MASK 0x3
|
||||
|
||||
#define TUSB320L_REGA0_REVISION 0xa0
|
||||
|
||||
enum tusb320_attached_state {
|
||||
TUSB320_ATTACHED_STATE_NONE,
|
||||
TUSB320_ATTACHED_STATE_DFP,
|
||||
TUSB320_ATTACHED_STATE_UFP,
|
||||
TUSB320_ATTACHED_STATE_ACC,
|
||||
};
|
||||
|
||||
enum tusb320_mode {
|
||||
TUSB320_MODE_PORT,
|
||||
TUSB320_MODE_UFP,
|
||||
TUSB320_MODE_DFP,
|
||||
TUSB320_MODE_DRP,
|
||||
};
|
||||
|
||||
struct tusb320_priv;
|
||||
|
||||
struct tusb320_ops {
|
||||
int (*set_mode)(struct tusb320_priv *priv, enum tusb320_mode mode);
|
||||
int (*get_revision)(struct tusb320_priv *priv, unsigned int *revision);
|
||||
};
|
||||
|
||||
struct tusb320_priv {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct extcon_dev *edev;
|
||||
struct tusb320_ops *ops;
|
||||
enum tusb320_attached_state state;
|
||||
};
|
||||
|
||||
static const char * const tusb_attached_states[] = {
|
||||
@ -62,6 +89,101 @@ static int tusb320_check_signature(struct tusb320_priv *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tusb320_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Mode cannot be changed while cable is attached */
|
||||
if (priv->state != TUSB320_ATTACHED_STATE_NONE)
|
||||
return -EBUSY;
|
||||
|
||||
/* Write mode */
|
||||
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
|
||||
TUSB320_REGA_MODE_SELECT_MASK << TUSB320_REGA_MODE_SELECT_SHIFT,
|
||||
mode << TUSB320_REGA_MODE_SELECT_SHIFT);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed to write mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tusb320l_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Disable CC state machine */
|
||||
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
|
||||
TUSB320L_REGA_DISABLE_TERM, 1);
|
||||
if (ret) {
|
||||
dev_err(priv->dev,
|
||||
"failed to disable CC state machine: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Write mode */
|
||||
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
|
||||
TUSB320_REGA_MODE_SELECT_MASK << TUSB320_REGA_MODE_SELECT_SHIFT,
|
||||
mode << TUSB320_REGA_MODE_SELECT_SHIFT);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed to write mode: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
msleep(5);
|
||||
err:
|
||||
/* Re-enable CC state machine */
|
||||
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
|
||||
TUSB320L_REGA_DISABLE_TERM, 0);
|
||||
if (ret)
|
||||
dev_err(priv->dev,
|
||||
"failed to re-enable CC state machine: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tusb320_reset(struct tusb320_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Set mode to default (follow PORT pin) */
|
||||
ret = priv->ops->set_mode(priv, TUSB320_MODE_PORT);
|
||||
if (ret && ret != -EBUSY) {
|
||||
dev_err(priv->dev,
|
||||
"failed to set mode to PORT: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Perform soft reset */
|
||||
ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
|
||||
TUSB320_REGA_I2C_SOFT_RESET, 1);
|
||||
if (ret) {
|
||||
dev_err(priv->dev,
|
||||
"failed to write soft reset bit: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait for chip to go through reset */
|
||||
msleep(95);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tusb320l_get_revision(struct tusb320_priv *priv, unsigned int *revision)
|
||||
{
|
||||
return regmap_read(priv->regmap, TUSB320L_REGA0_REVISION, revision);
|
||||
}
|
||||
|
||||
static struct tusb320_ops tusb320_ops = {
|
||||
.set_mode = tusb320_set_mode,
|
||||
};
|
||||
|
||||
static struct tusb320_ops tusb320l_ops = {
|
||||
.set_mode = tusb320l_set_mode,
|
||||
.get_revision = tusb320l_get_revision,
|
||||
};
|
||||
|
||||
static irqreturn_t tusb320_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct tusb320_priv *priv = dev_id;
|
||||
@ -96,6 +218,8 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id)
|
||||
extcon_sync(priv->edev, EXTCON_USB);
|
||||
extcon_sync(priv->edev, EXTCON_USB_HOST);
|
||||
|
||||
priv->state = state;
|
||||
|
||||
regmap_write(priv->regmap, TUSB320_REG9, reg);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -110,6 +234,8 @@ static int tusb320_extcon_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tusb320_priv *priv;
|
||||
const void *match_data;
|
||||
unsigned int revision;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
|
||||
@ -125,12 +251,27 @@ static int tusb320_extcon_probe(struct i2c_client *client,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
match_data = device_get_match_data(&client->dev);
|
||||
if (!match_data)
|
||||
return -EINVAL;
|
||||
|
||||
priv->ops = (struct tusb320_ops*)match_data;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (priv->ops->get_revision) {
|
||||
ret = priv->ops->get_revision(priv, &revision);
|
||||
if (ret)
|
||||
dev_warn(priv->dev,
|
||||
"failed to read revision register: %d\n", ret);
|
||||
else
|
||||
dev_info(priv->dev, "chip revision %d\n", revision);
|
||||
}
|
||||
|
||||
ret = devm_extcon_dev_register(priv->dev, priv->edev);
|
||||
if (ret < 0) {
|
||||
dev_err(priv->dev, "failed to register extcon device\n");
|
||||
@ -145,6 +286,17 @@ static int tusb320_extcon_probe(struct i2c_client *client,
|
||||
/* update initial state */
|
||||
tusb320_irq_handler(client->irq, priv);
|
||||
|
||||
/* Reset chip to its default state */
|
||||
ret = tusb320_reset(priv);
|
||||
if (ret)
|
||||
dev_warn(priv->dev, "failed to reset chip: %d\n", ret);
|
||||
else
|
||||
/*
|
||||
* State and polarity might change after a reset, so update
|
||||
* them again and make sure the interrupt status bit is cleared.
|
||||
*/
|
||||
tusb320_irq_handler(client->irq, priv);
|
||||
|
||||
ret = devm_request_threaded_irq(priv->dev, client->irq, NULL,
|
||||
tusb320_irq_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
@ -154,7 +306,8 @@ static int tusb320_extcon_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
static const struct of_device_id tusb320_extcon_dt_match[] = {
|
||||
{ .compatible = "ti,tusb320", },
|
||||
{ .compatible = "ti,tusb320", .data = &tusb320_ops, },
|
||||
{ .compatible = "ti,tusb320l", .data = &tusb320l_ops, },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match);
|
||||
|
Loading…
x
Reference in New Issue
Block a user