Skip to content

Commit

Permalink
extcon: usbc-tusb320: Add support for TUSB320L
Browse files Browse the repository at this point in the history
TUSB320L is a newer chip with additional features, and it has additional steps
in its mode changing sequence:
 - Disable CC state machine,
 - Write to mode register,
 - Wait for 5 ms,
 - Re-enable CC state machine.
It also has an additional register that a revision number can be read from.

Add support for the mode changing sequence, and read the revision number during
probe and print it as info.

Signed-off-by: Yassine Oudjana <y.oudjana@protonmail.com>
  • Loading branch information
Tooniis authored and intel-lab-lkp committed Jul 27, 2021
1 parent d6015b5 commit db60f91
Showing 1 changed file with 56 additions and 5 deletions.
61 changes: 56 additions & 5 deletions drivers/extcon/extcon-usbc-tusb320.c
Expand Up @@ -21,10 +21,13 @@
#define TUSB320_REG9_INTERRUPT_STATUS BIT(4)

#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,
Expand All @@ -39,9 +42,16 @@ enum tusb320_mode {
TUSB320_MODE_DRP,
};

enum tusb320_type {
TYPE_TUSB320,
TYPE_TUSB320L,
};


struct tusb320_priv {
struct device *dev;
struct regmap *regmap;
enum tusb320_type type;
struct extcon_dev *edev;

enum tusb320_attached_state state;
Expand Down Expand Up @@ -90,8 +100,19 @@ 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)
if(priv->type == TYPE_TUSB320L) {
/* 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;
}
}

/* Mode cannot be changed on TUSB320 while cable is attached */
if(priv->type == TYPE_TUSB320 && priv->state != TUSB320_ATTACHED_STATE_NONE)
return -EBUSY;

/* Write mode */
Expand All @@ -100,10 +121,21 @@ static int tusb320_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode)
mode << TUSB320_REGA_MODE_SELECT_SHIFT);
if(ret) {
dev_err(priv->dev, "failed to write mode: %d\n", ret);
return ret;
goto err;
}

return 0;
msleep(5);
err:
if(priv->type == TYPE_TUSB320L) {
/* 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)
Expand Down Expand Up @@ -188,6 +220,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);
Expand All @@ -203,12 +237,28 @@ 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->type = (enum tusb320_type)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->type == TYPE_TUSB320L) {
ret = regmap_read(priv->regmap, TUSB320L_REGA0_REVISION, &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");
Expand Down Expand Up @@ -237,7 +287,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 = (void *)TYPE_TUSB320, },
{ .compatible = "ti,tusb320l", .data = (void *)TYPE_TUSB320L, },
{ }
};
MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match);
Expand Down

0 comments on commit db60f91

Please sign in to comment.