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:
Родитель
e2f38ff2f4
Коммит
4dbc6a4ef0
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче