usb: typec: ucsi: save power data objects in PD mode

When connected to a PD-capable power-source, read & save all partner
power data objects (PDOs) by using GET_PDOS UCSI command.
Also, save the current power contract in request data object (RDO)
for that connector.

Signed-off-by: K V, Abhilash <abhilash.k.v@intel.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20200423132058.6972-6-heikki.krogerus@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
K V, Abhilash 2020-04-23 16:20:57 +03:00 committed by Greg Kroah-Hartman
parent e2f38ff2f4
commit 4dbc6a4ef0
2 changed files with 35 additions and 0 deletions

View file

@ -492,19 +492,45 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
}
}
static void ucsi_get_pdos(struct ucsi_connector *con, int is_partner)
{
struct ucsi *ucsi = con->ucsi;
u64 command;
int ret;
command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num);
command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner);
command |= UCSI_GET_PDOS_NUM_PDOS(UCSI_MAX_PDOS - 1);
command |= UCSI_GET_PDOS_SRC_PDOS;
ret = ucsi_run_command(ucsi, command, con->src_pdos,
sizeof(con->src_pdos));
if (ret < 0) {
dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret);
return;
}
con->num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */
if (ret == 0)
dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n");
}
static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
{
switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
con->rdo = con->status.request_data_obj;
typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD);
ucsi_get_pdos(con, 1);
break;
case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5:
con->rdo = 0;
typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_1_5A);
break;
case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0:
con->rdo = 0;
typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_3_0A);
break;
default:
con->rdo = 0;
typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_USB);
break;
}

View file

@ -130,6 +130,11 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
#define UCSI_GET_ALTMODE_OFFSET(_r_) ((u64)(_r_) << 32)
#define UCSI_GET_ALTMODE_NUM_ALTMODES(_r_) ((u64)(_r_) << 40)
/* GET_PDOS command bits */
#define UCSI_GET_PDOS_PARTNER_PDO(_r_) ((u64)(_r_) << 23)
#define UCSI_GET_PDOS_NUM_PDOS(_r_) ((u64)(_r_) << 32)
#define UCSI_GET_PDOS_SRC_PDOS ((u64)1 << 34)
/* -------------------------------------------------------------------------- */
/* Error information returned by PPM in response to GET_ERROR_STATUS command. */
@ -294,6 +299,7 @@ struct ucsi {
#define UCSI_MAX_SVID 5
#define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6)
#define UCSI_MAX_PDOS (4)
struct ucsi_connector {
int num;
@ -313,6 +319,9 @@ struct ucsi_connector {
struct ucsi_connector_status status;
struct ucsi_connector_capability cap;
u32 rdo;
u32 src_pdos[UCSI_MAX_PDOS];
int num_pdos;
};
int ucsi_send_command(struct ucsi *ucsi, u64 command,