usb: typec: tps6598x: mask status update

We don't need the status update unless it's plugged in.

With broken CC lines the cable sometimes shows as plugged in even when it
isn't. Look further into the status register to see if it is connected and
disable the STATUS interrupt to stop the irq storm.
Signed-off-by: default avatarAngus Ainslie <angus@akkea.ca>
parent ef903bb1
......@@ -48,6 +48,8 @@
#define TPS_TYPEC_3000mA 3000000
#define TPS_USB_5V 5000000
#define CC_INT_MASK TPS_REG_INT_STATUS_UPDATE
/* TPS_REG_SYSTEM_CONF bits */
#define TPS_SYSCONF_PORTINFO(c) ((c) & 7)
......@@ -303,6 +305,9 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
struct typec_partner_desc desc;
enum typec_pwr_opmode mode;
int ret;
u64 mask;
dev_dbg(tps->dev, "%s: status %x", __func__, status);
if (tps->partner)
return 0;
......@@ -332,6 +337,16 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
if (desc.identity)
typec_partner_set_identity(tps->partner);
ret = tps6598x_read64(tps, TPS_REG_INT_MASK1, &mask);
if (ret < 0)
return ret;
mask |= CC_INT_MASK;
ret = tps6598x_write64(tps, TPS_REG_INT_MASK1, mask);
if (ret < 0)
return ret;
dev_dbg(tps->dev, "interrupt mask updated %llx", mask);
power_supply_changed(tps->psy);
return 0;
......@@ -357,6 +372,11 @@ tps6598x_update_data_status(struct tps6598x *tps, u32 status)
static void tps6598x_disconnect(struct tps6598x *tps, u32 status)
{
int ret;
u64 mask;
dev_dbg(tps->dev, "%s: status %x", __func__, status);
if (!IS_ERR(tps->partner))
typec_unregister_partner(tps->partner);
tps->partner = NULL;
......@@ -367,6 +387,19 @@ static void tps6598x_disconnect(struct tps6598x *tps, u32 status)
memset(&tps->terms, 0, sizeof(struct tps6598x_pdo));
ret = tps6598x_read64(tps, TPS_REG_INT_MASK1, &mask);
if (ret < 0) {
dev_err(tps->dev, "Reading interrupt mask failed");
return;
}
mask &= ~CC_INT_MASK;
ret = tps6598x_write64(tps, TPS_REG_INT_MASK1, mask);
if (ret < 0) {
dev_err(tps->dev, "Writing interrupt mask failed");
return;
}
dev_dbg(tps->dev, "interrupt mask updated %llx", mask);
power_supply_changed(tps->psy);
}
......@@ -546,6 +579,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
u16 pwr_status;
bool psy_changed = false;
int ret;
u64 mask;
mutex_lock(&tps->lock);
......@@ -610,6 +644,26 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
psy_changed = true;
}
if ((event1 | event2) & TPS_REG_INT_STATUS_UPDATE) {
ret = tps6598x_read64(tps, TPS_REG_INT_MASK1, &mask);
if (ret < 0)
dev_err( tps->dev, "Reading interrupt mask failed");
dev_dbg(tps->dev, "Status update: %x %llx", status, mask);
if (!(mask & TPS_REG_INT_STATUS_UPDATE))
dev_err( tps->dev, "The interrupt is masked , how did it fire ?? %llx", mask);
if (!(status & TPS_STATUS_PLUG_PRESENT) || ((status & 0xc) != 0xc)) {
/* the status update register can fire even when masked so try
and mask it again */
mask &= ~TPS_REG_INT_STATUS_UPDATE;
ret = tps6598x_write64(tps, TPS_REG_INT_MASK1, mask);
if (ret < 0)
dev_err( tps->dev, "Writing interrupt mask failed");
else
dev_dbg( tps->dev, "interrupt mask updated %llx", mask);
}
}
err_clear_ints:
tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event1);
tps6598x_write64(tps, TPS_REG_INT_CLEAR2, event2);
......@@ -784,6 +838,7 @@ static int tps6598x_probe(struct i2c_client *client)
u32 conf;
u32 vid;
int ret;
u64 mask;
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
......@@ -897,6 +952,10 @@ static int tps6598x_probe(struct i2c_client *client)
/* set initial state */
extcon_set_state_sync(tps->extcon, EXTCON_DISP_DP, false);
ret = tps6598x_read64(tps, TPS_REG_INT_MASK1, &mask);
if (ret < 0)
dev_err(&client->dev, "failed to read irq mask%d\n", ret);
if (status & TPS_STATUS_PLUG_PRESENT) {
ret = tps6598x_read16(tps, TPS_REG_POWER_STATUS, &tps->pwr_status);
if (ret < 0) {
......@@ -906,8 +965,15 @@ static int tps6598x_probe(struct i2c_client *client)
ret = tps6598x_connect(tps, status);
if (ret)
dev_err(&client->dev, "failed to register partner\n");
} else {
mask &= ~CC_INT_MASK;
}
ret = tps6598x_write64(tps, TPS_REG_INT_MASK1, mask);
ret |= tps6598x_write64(tps, TPS_REG_INT_MASK2, 0);
if (ret < 0)
dev_err(&client->dev, "failed to write irq mask%d\n", ret);
ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
tps6598x_interrupt,
IRQF_SHARED | IRQF_ONESHOT,
......
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