Commit 4dbc6a4e authored by K V, Abhilash's avatar K V, Abhilash Committed by Greg Kroah-Hartman
Browse files

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: default avatarK V, Abhilash <abhilash.k.v@intel.com>
Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20200423132058.6972-6-heikki.krogerus@linux.intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e2f38ff2
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -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;
	}
+9 −0
Original line number Diff line number Diff line
@@ -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,