Commit 462a5ac6 authored by Guido Gunther's avatar Guido Gunther Committed by Martin Kepplinger
Browse files

usb: typec: tps6589x: Handle DP alt mode changes via extcon



This allows to signal the DP core when an alt mode got negotiated.  The
(not yet mainlne) cadence/mhdp driver uses this to enable DP only when
an alt mode got negotiated to save power on the Librem 5.
Signed-off-by: Guido Gunther's avatarGuido Günther <agx@sigxcpu.org>
parent b322fa07
......@@ -64,6 +64,7 @@ config TYPEC_HD3SS3220
config TYPEC_TPS6598X
tristate "TI TPS6598x USB Power Delivery controller driver"
depends on I2C
select EXTCON
select POWER_SUPPLY
select REGMAP_I2C
select USB_ROLE_SWITCH
......
......@@ -10,6 +10,8 @@
#include <linux/i2c.h>
#include <linux/acpi.h>
#include <linux/extcon.h>
#include <linux/extcon-provider.h>
#include <linux/module.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
......@@ -97,6 +99,8 @@ struct tps6598x {
u32 data_status;
u16 pwr_status;
bool dp;
struct extcon_dev *extcon;
};
static enum power_supply_property tps6598x_psy_props[] = {
......@@ -264,9 +268,18 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
static int
tps6598x_update_data_status(struct tps6598x *tps, u32 status)
{
bool dp;
tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status),
!!(tps->data_status & TPS_DATA_STATUS_DATA_CONNECTION));
trace_tps6598x_data_status(tps->data_status);
dp = !!(tps->data_status & TPS_DATA_STATUS_DP_CONNECTION);
if (tps->dp != dp) {
tps->dp = dp;
extcon_set_state_sync(tps->extcon, EXTCON_DISP_DP, tps->dp);
extcon_sync(tps->extcon, EXTCON_DISP_DP);
}
return 0;
}
......@@ -575,6 +588,11 @@ static int devm_tps6598_psy_register(struct tps6598x *tps)
return PTR_ERR_OR_ZERO(tps->psy);
}
static const unsigned int tps6598x_extcon_cable[] = {
EXTCON_DISP_DP,
EXTCON_NONE,
};
static int tps6598x_probe(struct i2c_client *client)
{
struct typec_capability typec_cap = { };
......@@ -680,6 +698,23 @@ static int tps6598x_probe(struct i2c_client *client)
}
fwnode_handle_put(fwnode);
tps->extcon = devm_extcon_dev_allocate(tps->dev, tps6598x_extcon_cable);
if (IS_ERR(tps->extcon)) {
dev_err(tps->dev, "failed to allocate memory for extcon\n");
ret = PTR_ERR(tps->extcon);
goto err_role_put;
}
/* Register extcon device */
ret = devm_extcon_dev_register(tps->dev, tps->extcon);
if (ret) {
dev_err(tps->dev, "failed to register extcon device: %d\n", ret);
goto err_role_put;
}
/* set initial state */
extcon_set_state_sync(tps->extcon, EXTCON_DISP_DP, false);
if (status & TPS_STATUS_PLUG_PRESENT) {
ret = tps6598x_read16(tps, TPS_REG_POWER_STATUS, &tps->pwr_status);
if (ret < 0) {
......
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