Commit 766c485b authored by Badhri Jagan Sridharan's avatar Badhri Jagan Sridharan Committed by Greg Kroah-Hartman
Browse files

usb: typec: tcpci: Add support to report vSafe0V



This change adds vbus_vsafe0v which when set, makes TCPM
query for VSAFE0V by assigning the tcpc.is_vbus_vsafe0v callback.
Also enables ALERT.ExtendedStatus which is triggered when
status of EXTENDED_STATUS.vSafe0V changes.
EXTENDED_STATUS.vSafe0V is set when vbus is at vSafe0V and
cleared otherwise.

Reviewed-by: default avatarGuenter Roeck <linux@roeck-us.net>
Acked-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: default avatarBadhri Jagan Sridharan <badhri@google.com>
Link: https://lore.kernel.org/r/20201202040840.663578-2-badhri@google.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 28b43d3d
Loading
Loading
Loading
Loading
+34 −5
Original line number Diff line number Diff line
@@ -403,6 +403,19 @@ static int tcpci_get_vbus(struct tcpc_dev *tcpc)
	return !!(reg & TCPC_POWER_STATUS_VBUS_PRES);
}

static bool tcpci_is_vbus_vsafe0v(struct tcpc_dev *tcpc)
{
	struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
	unsigned int reg;
	int ret;

	ret = regmap_read(tcpci->regmap, TCPC_EXTENDED_STATUS, &reg);
	if (ret < 0)
		return false;

	return !!(reg & TCPC_EXTENDED_STATUS_VSAFE0V);
}

static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink)
{
	struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
@@ -556,12 +569,22 @@ static int tcpci_init(struct tcpc_dev *tcpc)
		TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_CC_STATUS;
	if (tcpci->controls_vbus)
		reg |= TCPC_ALERT_POWER_STATUS;
	/* Enable VSAFE0V status interrupt when detecting VSAFE0V is supported */
	if (tcpci->data->vbus_vsafe0v) {
		reg |= TCPC_ALERT_EXTENDED_STATUS;
		ret = regmap_write(tcpci->regmap, TCPC_EXTENDED_STATUS_MASK,
				   TCPC_EXTENDED_STATUS_VSAFE0V);
		if (ret < 0)
			return ret;
	}
	return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
}

irqreturn_t tcpci_irq(struct tcpci *tcpci)
{
	u16 status;
	int ret;
	unsigned int raw;

	tcpci_read16(tcpci, TCPC_ALERT, &status);

@@ -577,15 +600,12 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci)
		tcpm_cc_change(tcpci->port);

	if (status & TCPC_ALERT_POWER_STATUS) {
		unsigned int reg;

		regmap_read(tcpci->regmap, TCPC_POWER_STATUS_MASK, &reg);

		regmap_read(tcpci->regmap, TCPC_POWER_STATUS_MASK, &raw);
		/*
		 * If power status mask has been reset, then the TCPC
		 * has reset.
		 */
		if (reg == 0xff)
		if (raw == 0xff)
			tcpm_tcpc_reset(tcpci->port);
		else
			tcpm_vbus_change(tcpci->port);
@@ -624,6 +644,12 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci)
		tcpm_pd_receive(tcpci->port, &msg);
	}

	if (status & TCPC_ALERT_EXTENDED_STATUS) {
		ret = regmap_read(tcpci->regmap, TCPC_EXTENDED_STATUS, &raw);
		if (!ret && (raw & TCPC_EXTENDED_STATUS_VSAFE0V))
			tcpm_vbus_change(tcpci->port);
	}

	if (status & TCPC_ALERT_RX_HARD_RST)
		tcpm_pd_hard_reset(tcpci->port);

@@ -701,6 +727,9 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
			tcpci_set_auto_vbus_discharge_threshold;
	}

	if (tcpci->data->vbus_vsafe0v)
		tcpci->tcpc.is_vbus_vsafe0v = tcpci_is_vbus_vsafe0v;

	err = tcpci_parse_config(tcpci);
	if (err < 0)
		return ERR_PTR(err);
+6 −0
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@
#define TCPC_TCPC_CTRL_ORIENTATION	BIT(0)
#define TCPC_TCPC_CTRL_BIST_TM		BIT(1)

#define TCPC_EXTENDED_STATUS		0x20
#define TCPC_EXTENDED_STATUS_VSAFE0V	BIT(0)

#define TCPC_ROLE_CTRL			0x1a
#define TCPC_ROLE_CTRL_DRP		BIT(6)
#define TCPC_ROLE_CTRL_RP_VAL_SHIFT	4
@@ -155,11 +158,14 @@ struct tcpci;
 *		is sourcing vbus.
 * @auto_discharge_disconnect:
 *		Optional; Enables TCPC to autonously discharge vbus on disconnect.
 * @vbus_vsafe0v:
 *		optional; Set when TCPC can detect whether vbus is at VSAFE0V.
 */
struct tcpci_data {
	struct regmap *regmap;
	unsigned char TX_BUF_BYTE_x_hidden:1;
	unsigned char auto_discharge_disconnect:1;
	unsigned char vbus_vsafe0v:1;

	int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
	int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,