cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wcove.c (17512B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * typec_wcove.c - WhiskeyCove PMIC USB Type-C PHY driver
      4 *
      5 * Copyright (C) 2017 Intel Corporation
      6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
      7 */
      8
      9#include <linux/acpi.h>
     10#include <linux/module.h>
     11#include <linux/usb/tcpm.h>
     12#include <linux/interrupt.h>
     13#include <linux/platform_device.h>
     14#include <linux/mfd/intel_soc_pmic.h>
     15
     16/* Register offsets */
     17#define WCOVE_CHGRIRQ0		0x4e09
     18
     19#define USBC_CONTROL1		0x7001
     20#define USBC_CONTROL2		0x7002
     21#define USBC_CONTROL3		0x7003
     22#define USBC_CC1_CTRL		0x7004
     23#define USBC_CC2_CTRL		0x7005
     24#define USBC_STATUS1		0x7007
     25#define USBC_STATUS2		0x7008
     26#define USBC_STATUS3		0x7009
     27#define USBC_CC1		0x700a
     28#define USBC_CC2		0x700b
     29#define USBC_CC1_STATUS		0x700c
     30#define USBC_CC2_STATUS		0x700d
     31#define USBC_IRQ1		0x7015
     32#define USBC_IRQ2		0x7016
     33#define USBC_IRQMASK1		0x7017
     34#define USBC_IRQMASK2		0x7018
     35#define USBC_PDCFG2		0x701a
     36#define USBC_PDCFG3		0x701b
     37#define USBC_PDSTATUS		0x701c
     38#define USBC_RXSTATUS		0x701d
     39#define USBC_RXINFO		0x701e
     40#define USBC_TXCMD		0x701f
     41#define USBC_TXINFO		0x7020
     42#define USBC_RX_DATA		0x7028
     43#define USBC_TX_DATA		0x7047
     44
     45/* Register bits */
     46
     47#define USBC_CONTROL1_MODE_MASK		0x3
     48#define   USBC_CONTROL1_MODE_SNK	0
     49#define   USBC_CONTROL1_MODE_SNKACC	1
     50#define   USBC_CONTROL1_MODE_SRC	2
     51#define   USBC_CONTROL1_MODE_SRCACC	3
     52#define   USBC_CONTROL1_MODE_DRP	4
     53#define   USBC_CONTROL1_MODE_DRPACC	5
     54#define   USBC_CONTROL1_MODE_TEST	7
     55#define USBC_CONTROL1_CURSRC_MASK	0xc
     56#define   USBC_CONTROL1_CURSRC_UA_0	(0 << 3)
     57#define   USBC_CONTROL1_CURSRC_UA_80	(1 << 3)
     58#define   USBC_CONTROL1_CURSRC_UA_180	(2 << 3)
     59#define   USBC_CONTROL1_CURSRC_UA_330	(3 << 3)
     60#define USBC_CONTROL1_DRPTOGGLE_RANDOM	0xe0
     61
     62#define USBC_CONTROL2_UNATT_SNK		BIT(0)
     63#define USBC_CONTROL2_UNATT_SRC		BIT(1)
     64#define USBC_CONTROL2_DIS_ST		BIT(2)
     65
     66#define USBC_CONTROL3_DET_DIS		BIT(0)
     67#define USBC_CONTROL3_PD_DIS		BIT(1)
     68#define USBC_CONTROL3_RESETPHY		BIT(2)
     69
     70#define USBC_CC_CTRL_PU_EN		BIT(0)
     71#define USBC_CC_CTRL_VCONN_EN		BIT(1)
     72#define USBC_CC_CTRL_TX_EN		BIT(2)
     73#define USBC_CC_CTRL_PD_EN		BIT(3)
     74#define USBC_CC_CTRL_CDET_EN		BIT(4)
     75#define USBC_CC_CTRL_RDET_EN		BIT(5)
     76#define USBC_CC_CTRL_ADC_EN		BIT(6)
     77#define USBC_CC_CTRL_VBUSOK		BIT(7)
     78
     79#define USBC_STATUS1_DET_ONGOING	BIT(6)
     80#define USBC_STATUS1_RSLT(r)		((r) & 0xf)
     81#define USBC_RSLT_NOTHING		0
     82#define USBC_RSLT_SRC_DEFAULT		1
     83#define USBC_RSLT_SRC_1_5A		2
     84#define USBC_RSLT_SRC_3_0A		3
     85#define USBC_RSLT_SNK			4
     86#define USBC_RSLT_DEBUG_ACC		5
     87#define USBC_RSLT_AUDIO_ACC		6
     88#define USBC_RSLT_UNDEF			15
     89#define USBC_STATUS1_ORIENT(r)		(((r) >> 4) & 0x3)
     90#define USBC_ORIENT_NORMAL		1
     91#define USBC_ORIENT_REVERSE		2
     92
     93#define USBC_STATUS2_VBUS_REQ		BIT(5)
     94
     95#define UCSC_CC_STATUS_SNK_RP		BIT(0)
     96#define UCSC_CC_STATUS_PWRDEFSNK	BIT(1)
     97#define UCSC_CC_STATUS_PWR_1P5A_SNK	BIT(2)
     98#define UCSC_CC_STATUS_PWR_3A_SNK	BIT(3)
     99#define UCSC_CC_STATUS_SRC_RP		BIT(4)
    100#define UCSC_CC_STATUS_RX(r)		(((r) >> 5) & 0x3)
    101#define   USBC_CC_STATUS_RD		1
    102#define   USBC_CC_STATUS_RA		2
    103
    104#define USBC_IRQ1_ADCDONE1		BIT(2)
    105#define USBC_IRQ1_OVERTEMP		BIT(1)
    106#define USBC_IRQ1_SHORT			BIT(0)
    107
    108#define USBC_IRQ2_CC_CHANGE		BIT(7)
    109#define USBC_IRQ2_RX_PD			BIT(6)
    110#define USBC_IRQ2_RX_HR			BIT(5)
    111#define USBC_IRQ2_RX_CR			BIT(4)
    112#define USBC_IRQ2_TX_SUCCESS		BIT(3)
    113#define USBC_IRQ2_TX_FAIL		BIT(2)
    114
    115#define USBC_IRQMASK1_ALL	(USBC_IRQ1_ADCDONE1 | USBC_IRQ1_OVERTEMP | \
    116				 USBC_IRQ1_SHORT)
    117
    118#define USBC_IRQMASK2_ALL	(USBC_IRQ2_CC_CHANGE | USBC_IRQ2_RX_PD | \
    119				 USBC_IRQ2_RX_HR | USBC_IRQ2_RX_CR | \
    120				 USBC_IRQ2_TX_SUCCESS | USBC_IRQ2_TX_FAIL)
    121
    122#define USBC_PDCFG2_SOP			BIT(0)
    123#define USBC_PDCFG2_SOP_P		BIT(1)
    124#define USBC_PDCFG2_SOP_PP		BIT(2)
    125#define USBC_PDCFG2_SOP_P_DEBUG		BIT(3)
    126#define USBC_PDCFG2_SOP_PP_DEBUG	BIT(4)
    127
    128#define USBC_PDCFG3_DATAROLE_SHIFT	1
    129#define USBC_PDCFG3_SOP_SHIFT		2
    130
    131#define USBC_RXSTATUS_RXCLEAR		BIT(0)
    132#define USBC_RXSTATUS_RXDATA		BIT(7)
    133
    134#define USBC_RXINFO_RXBYTES(i)		(((i) >> 3) & 0x1f)
    135
    136#define USBC_TXCMD_BUF_RDY		BIT(0)
    137#define USBC_TXCMD_START		BIT(1)
    138#define USBC_TXCMD_NOP			(0 << 5)
    139#define USBC_TXCMD_MSG			(1 << 5)
    140#define USBC_TXCMD_CR			(2 << 5)
    141#define USBC_TXCMD_HR			(3 << 5)
    142#define USBC_TXCMD_BIST			(4 << 5)
    143
    144#define USBC_TXINFO_RETRIES(d)		(d << 3)
    145
    146struct wcove_typec {
    147	struct mutex lock; /* device lock */
    148	struct device *dev;
    149	struct regmap *regmap;
    150	guid_t guid;
    151
    152	bool vbus;
    153
    154	struct tcpc_dev tcpc;
    155	struct tcpm_port *tcpm;
    156};
    157
    158#define tcpc_to_wcove(_tcpc_) container_of(_tcpc_, struct wcove_typec, tcpc)
    159
    160enum wcove_typec_func {
    161	WCOVE_FUNC_DRIVE_VBUS = 1,
    162	WCOVE_FUNC_ORIENTATION,
    163	WCOVE_FUNC_ROLE,
    164	WCOVE_FUNC_DRIVE_VCONN,
    165};
    166
    167enum wcove_typec_orientation {
    168	WCOVE_ORIENTATION_NORMAL,
    169	WCOVE_ORIENTATION_REVERSE,
    170};
    171
    172enum wcove_typec_role {
    173	WCOVE_ROLE_HOST,
    174	WCOVE_ROLE_DEVICE,
    175};
    176
    177#define WCOVE_DSM_UUID		"482383f0-2876-4e49-8685-db66211af037"
    178
    179static int wcove_typec_func(struct wcove_typec *wcove,
    180			    enum wcove_typec_func func, int param)
    181{
    182	union acpi_object *obj;
    183	union acpi_object tmp;
    184	union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
    185
    186	tmp.type = ACPI_TYPE_INTEGER;
    187	tmp.integer.value = param;
    188
    189	obj = acpi_evaluate_dsm(ACPI_HANDLE(wcove->dev), &wcove->guid, 1, func,
    190				&argv4);
    191	if (!obj) {
    192		dev_err(wcove->dev, "%s: failed to evaluate _DSM\n", __func__);
    193		return -EIO;
    194	}
    195
    196	ACPI_FREE(obj);
    197	return 0;
    198}
    199
    200static int wcove_init(struct tcpc_dev *tcpc)
    201{
    202	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    203	int ret;
    204
    205	ret = regmap_write(wcove->regmap, USBC_CONTROL1, 0);
    206	if (ret)
    207		return ret;
    208
    209	/* Unmask everything */
    210	ret = regmap_write(wcove->regmap, USBC_IRQMASK1, 0);
    211	if (ret)
    212		return ret;
    213
    214	return regmap_write(wcove->regmap, USBC_IRQMASK2, 0);
    215}
    216
    217static int wcove_get_vbus(struct tcpc_dev *tcpc)
    218{
    219	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    220	unsigned int cc1ctrl;
    221	int ret;
    222
    223	ret = regmap_read(wcove->regmap, USBC_CC1_CTRL, &cc1ctrl);
    224	if (ret)
    225		return ret;
    226
    227	wcove->vbus = !!(cc1ctrl & USBC_CC_CTRL_VBUSOK);
    228
    229	return wcove->vbus;
    230}
    231
    232static int wcove_set_vbus(struct tcpc_dev *tcpc, bool on, bool sink)
    233{
    234	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    235
    236	return wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VBUS, on);
    237}
    238
    239static int wcove_set_vconn(struct tcpc_dev *tcpc, bool on)
    240{
    241	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    242
    243	return wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VCONN, on);
    244}
    245
    246static enum typec_cc_status wcove_to_typec_cc(unsigned int cc)
    247{
    248	if (cc & UCSC_CC_STATUS_SNK_RP) {
    249		if (cc & UCSC_CC_STATUS_PWRDEFSNK)
    250			return TYPEC_CC_RP_DEF;
    251		else if (cc & UCSC_CC_STATUS_PWR_1P5A_SNK)
    252			return TYPEC_CC_RP_1_5;
    253		else if (cc & UCSC_CC_STATUS_PWR_3A_SNK)
    254			return TYPEC_CC_RP_3_0;
    255	} else {
    256		switch (UCSC_CC_STATUS_RX(cc)) {
    257		case USBC_CC_STATUS_RD:
    258			return TYPEC_CC_RD;
    259		case USBC_CC_STATUS_RA:
    260			return TYPEC_CC_RA;
    261		default:
    262			break;
    263		}
    264	}
    265	return TYPEC_CC_OPEN;
    266}
    267
    268static int wcove_get_cc(struct tcpc_dev *tcpc, enum typec_cc_status *cc1,
    269			enum typec_cc_status *cc2)
    270{
    271	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    272	unsigned int cc1_status;
    273	unsigned int cc2_status;
    274	int ret;
    275
    276	ret = regmap_read(wcove->regmap, USBC_CC1_STATUS, &cc1_status);
    277	if (ret)
    278		return ret;
    279
    280	ret = regmap_read(wcove->regmap, USBC_CC2_STATUS, &cc2_status);
    281	if (ret)
    282		return ret;
    283
    284	*cc1 = wcove_to_typec_cc(cc1_status);
    285	*cc2 = wcove_to_typec_cc(cc2_status);
    286
    287	return 0;
    288}
    289
    290static int wcove_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
    291{
    292	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    293	unsigned int ctrl;
    294
    295	switch (cc) {
    296	case TYPEC_CC_RD:
    297		ctrl = USBC_CONTROL1_MODE_SNK;
    298		break;
    299	case TYPEC_CC_RP_DEF:
    300		ctrl = USBC_CONTROL1_CURSRC_UA_80 | USBC_CONTROL1_MODE_SRC;
    301		break;
    302	case TYPEC_CC_RP_1_5:
    303		ctrl = USBC_CONTROL1_CURSRC_UA_180 | USBC_CONTROL1_MODE_SRC;
    304		break;
    305	case TYPEC_CC_RP_3_0:
    306		ctrl = USBC_CONTROL1_CURSRC_UA_330 | USBC_CONTROL1_MODE_SRC;
    307		break;
    308	case TYPEC_CC_OPEN:
    309		ctrl = 0;
    310		break;
    311	default:
    312		return -EINVAL;
    313	}
    314
    315	return regmap_write(wcove->regmap, USBC_CONTROL1, ctrl);
    316}
    317
    318static int wcove_set_polarity(struct tcpc_dev *tcpc, enum typec_cc_polarity pol)
    319{
    320	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    321
    322	return wcove_typec_func(wcove, WCOVE_FUNC_ORIENTATION, pol);
    323}
    324
    325static int wcove_set_current_limit(struct tcpc_dev *tcpc, u32 max_ma, u32 mv)
    326{
    327	return 0;
    328}
    329
    330static int wcove_set_roles(struct tcpc_dev *tcpc, bool attached,
    331			   enum typec_role role, enum typec_data_role data)
    332{
    333	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    334	unsigned int val;
    335	int ret;
    336
    337	ret = wcove_typec_func(wcove, WCOVE_FUNC_ROLE, data == TYPEC_HOST ?
    338			       WCOVE_ROLE_HOST : WCOVE_ROLE_DEVICE);
    339	if (ret)
    340		return ret;
    341
    342	val = role;
    343	val |= data << USBC_PDCFG3_DATAROLE_SHIFT;
    344	val |= PD_REV20 << USBC_PDCFG3_SOP_SHIFT;
    345
    346	return regmap_write(wcove->regmap, USBC_PDCFG3, val);
    347}
    348
    349static int wcove_set_pd_rx(struct tcpc_dev *tcpc, bool on)
    350{
    351	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    352
    353	return regmap_write(wcove->regmap, USBC_PDCFG2,
    354			    on ? USBC_PDCFG2_SOP : 0);
    355}
    356
    357static int wcove_pd_transmit(struct tcpc_dev *tcpc,
    358			     enum tcpm_transmit_type type,
    359			     const struct pd_message *msg,
    360			     unsigned int negotiated_rev)
    361{
    362	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    363	unsigned int info = 0;
    364	unsigned int cmd;
    365	int ret;
    366
    367	ret = regmap_read(wcove->regmap, USBC_TXCMD, &cmd);
    368	if (ret)
    369		return ret;
    370
    371	if (!(cmd & USBC_TXCMD_BUF_RDY)) {
    372		dev_warn(wcove->dev, "%s: Last transmission still ongoing!",
    373			 __func__);
    374		return -EBUSY;
    375	}
    376
    377	if (msg) {
    378		const u8 *data = (void *)msg;
    379		int i;
    380
    381		for (i = 0; i < pd_header_cnt_le(msg->header) * 4 + 2; i++) {
    382			ret = regmap_write(wcove->regmap, USBC_TX_DATA + i,
    383					   data[i]);
    384			if (ret)
    385				return ret;
    386		}
    387	}
    388
    389	switch (type) {
    390	case TCPC_TX_SOP:
    391	case TCPC_TX_SOP_PRIME:
    392	case TCPC_TX_SOP_PRIME_PRIME:
    393	case TCPC_TX_SOP_DEBUG_PRIME:
    394	case TCPC_TX_SOP_DEBUG_PRIME_PRIME:
    395		info = type + 1;
    396		cmd = USBC_TXCMD_MSG;
    397		break;
    398	case TCPC_TX_HARD_RESET:
    399		cmd = USBC_TXCMD_HR;
    400		break;
    401	case TCPC_TX_CABLE_RESET:
    402		cmd = USBC_TXCMD_CR;
    403		break;
    404	case TCPC_TX_BIST_MODE_2:
    405		cmd = USBC_TXCMD_BIST;
    406		break;
    407	default:
    408		return -EINVAL;
    409	}
    410
    411	/* NOTE Setting maximum number of retries (7) */
    412	ret = regmap_write(wcove->regmap, USBC_TXINFO,
    413			   info | USBC_TXINFO_RETRIES(7));
    414	if (ret)
    415		return ret;
    416
    417	return regmap_write(wcove->regmap, USBC_TXCMD, cmd | USBC_TXCMD_START);
    418}
    419
    420static int wcove_start_toggling(struct tcpc_dev *tcpc,
    421				enum typec_port_type port_type,
    422				enum typec_cc_status cc)
    423{
    424	struct wcove_typec *wcove = tcpc_to_wcove(tcpc);
    425	unsigned int usbc_ctrl;
    426
    427	if (port_type != TYPEC_PORT_DRP)
    428		return -EOPNOTSUPP;
    429
    430	usbc_ctrl = USBC_CONTROL1_MODE_DRP | USBC_CONTROL1_DRPTOGGLE_RANDOM;
    431
    432	switch (cc) {
    433	case TYPEC_CC_RP_1_5:
    434		usbc_ctrl |= USBC_CONTROL1_CURSRC_UA_180;
    435		break;
    436	case TYPEC_CC_RP_3_0:
    437		usbc_ctrl |= USBC_CONTROL1_CURSRC_UA_330;
    438		break;
    439	default:
    440		usbc_ctrl |= USBC_CONTROL1_CURSRC_UA_80;
    441		break;
    442	}
    443
    444	return regmap_write(wcove->regmap, USBC_CONTROL1, usbc_ctrl);
    445}
    446
    447static int wcove_read_rx_buffer(struct wcove_typec *wcove, void *msg)
    448{
    449	unsigned int info;
    450	int ret;
    451	int i;
    452
    453	ret = regmap_read(wcove->regmap, USBC_RXINFO, &info);
    454	if (ret)
    455		return ret;
    456
    457	/* FIXME: Check that USBC_RXINFO_RXBYTES(info) matches the header */
    458
    459	for (i = 0; i < USBC_RXINFO_RXBYTES(info); i++) {
    460		ret = regmap_read(wcove->regmap, USBC_RX_DATA + i, msg + i);
    461		if (ret)
    462			return ret;
    463	}
    464
    465	return regmap_write(wcove->regmap, USBC_RXSTATUS,
    466			    USBC_RXSTATUS_RXCLEAR);
    467}
    468
    469static irqreturn_t wcove_typec_irq(int irq, void *data)
    470{
    471	struct wcove_typec *wcove = data;
    472	unsigned int usbc_irq1 = 0;
    473	unsigned int usbc_irq2 = 0;
    474	unsigned int cc1ctrl;
    475	int ret;
    476
    477	mutex_lock(&wcove->lock);
    478
    479	/* Read.. */
    480	ret = regmap_read(wcove->regmap, USBC_IRQ1, &usbc_irq1);
    481	if (ret)
    482		goto err;
    483
    484	ret = regmap_read(wcove->regmap, USBC_IRQ2, &usbc_irq2);
    485	if (ret)
    486		goto err;
    487
    488	ret = regmap_read(wcove->regmap, USBC_CC1_CTRL, &cc1ctrl);
    489	if (ret)
    490		goto err;
    491
    492	if (!wcove->tcpm)
    493		goto err;
    494
    495	/* ..check.. */
    496	if (usbc_irq1 & USBC_IRQ1_OVERTEMP) {
    497		dev_err(wcove->dev, "VCONN Switch Over Temperature!\n");
    498		wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VCONN, false);
    499		/* REVISIT: Report an error? */
    500	}
    501
    502	if (usbc_irq1 & USBC_IRQ1_SHORT) {
    503		dev_err(wcove->dev, "VCONN Switch Short Circuit!\n");
    504		wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VCONN, false);
    505		/* REVISIT: Report an error? */
    506	}
    507
    508	if (wcove->vbus != !!(cc1ctrl & USBC_CC_CTRL_VBUSOK))
    509		tcpm_vbus_change(wcove->tcpm);
    510
    511	/* REVISIT: See if tcpm code can be made to consider Type-C HW FSMs */
    512	if (usbc_irq2 & USBC_IRQ2_CC_CHANGE)
    513		tcpm_cc_change(wcove->tcpm);
    514
    515	if (usbc_irq2 & USBC_IRQ2_RX_PD) {
    516		unsigned int status;
    517
    518		/*
    519		 * FIXME: Need to check if TX is ongoing and report
    520		 * TX_DIREGARDED if needed?
    521		 */
    522
    523		ret = regmap_read(wcove->regmap, USBC_RXSTATUS, &status);
    524		if (ret)
    525			goto err;
    526
    527		/* Flush all buffers */
    528		while (status & USBC_RXSTATUS_RXDATA) {
    529			struct pd_message msg;
    530
    531			ret = wcove_read_rx_buffer(wcove, &msg);
    532			if (ret) {
    533				dev_err(wcove->dev, "%s: RX read failed\n",
    534					__func__);
    535				goto err;
    536			}
    537
    538			tcpm_pd_receive(wcove->tcpm, &msg);
    539
    540			ret = regmap_read(wcove->regmap, USBC_RXSTATUS,
    541					  &status);
    542			if (ret)
    543				goto err;
    544		}
    545	}
    546
    547	if (usbc_irq2 & USBC_IRQ2_RX_HR)
    548		tcpm_pd_hard_reset(wcove->tcpm);
    549
    550	/* REVISIT: if (usbc_irq2 & USBC_IRQ2_RX_CR) */
    551
    552	if (usbc_irq2 & USBC_IRQ2_TX_SUCCESS)
    553		tcpm_pd_transmit_complete(wcove->tcpm, TCPC_TX_SUCCESS);
    554
    555	if (usbc_irq2 & USBC_IRQ2_TX_FAIL)
    556		tcpm_pd_transmit_complete(wcove->tcpm, TCPC_TX_FAILED);
    557
    558err:
    559	/* ..and clear. */
    560	if (usbc_irq1) {
    561		ret = regmap_write(wcove->regmap, USBC_IRQ1, usbc_irq1);
    562		if (ret)
    563			dev_WARN(wcove->dev, "%s failed to clear IRQ1\n",
    564				 __func__);
    565	}
    566
    567	if (usbc_irq2) {
    568		ret = regmap_write(wcove->regmap, USBC_IRQ2, usbc_irq2);
    569		if (ret)
    570			dev_WARN(wcove->dev, "%s failed to clear IRQ2\n",
    571				 __func__);
    572	}
    573
    574	/* REVISIT: Clear WhiskeyCove CHGR Type-C interrupt */
    575	regmap_write(wcove->regmap, WCOVE_CHGRIRQ0, BIT(5));
    576
    577	mutex_unlock(&wcove->lock);
    578	return IRQ_HANDLED;
    579}
    580
    581/*
    582 * The following power levels should be safe to use with Joule board.
    583 */
    584static const u32 src_pdo[] = {
    585	PDO_FIXED(5000, 1500, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |
    586		  PDO_FIXED_USB_COMM),
    587};
    588
    589static const u32 snk_pdo[] = {
    590	PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |
    591		  PDO_FIXED_USB_COMM),
    592	PDO_VAR(5000, 12000, 3000),
    593};
    594
    595static const struct property_entry wcove_props[] = {
    596	PROPERTY_ENTRY_STRING("data-role", "dual"),
    597	PROPERTY_ENTRY_STRING("power-role", "dual"),
    598	PROPERTY_ENTRY_STRING("try-power-role", "sink"),
    599	PROPERTY_ENTRY_U32_ARRAY("source-pdos", src_pdo),
    600	PROPERTY_ENTRY_U32_ARRAY("sink-pdos", snk_pdo),
    601	PROPERTY_ENTRY_U32("op-sink-microwatt", 15000000),
    602	{ }
    603};
    604
    605static int wcove_typec_probe(struct platform_device *pdev)
    606{
    607	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
    608	struct wcove_typec *wcove;
    609	int irq;
    610	int ret;
    611
    612	wcove = devm_kzalloc(&pdev->dev, sizeof(*wcove), GFP_KERNEL);
    613	if (!wcove)
    614		return -ENOMEM;
    615
    616	mutex_init(&wcove->lock);
    617	wcove->dev = &pdev->dev;
    618	wcove->regmap = pmic->regmap;
    619
    620	irq = platform_get_irq(pdev, 0);
    621	if (irq < 0)
    622		return irq;
    623
    624	irq = regmap_irq_get_virq(pmic->irq_chip_data_chgr, irq);
    625	if (irq < 0)
    626		return irq;
    627
    628	ret = guid_parse(WCOVE_DSM_UUID, &wcove->guid);
    629	if (ret)
    630		return ret;
    631
    632	if (!acpi_check_dsm(ACPI_HANDLE(&pdev->dev), &wcove->guid, 0, 0x1f)) {
    633		dev_err(&pdev->dev, "Missing _DSM functions\n");
    634		return -ENODEV;
    635	}
    636
    637	wcove->tcpc.init = wcove_init;
    638	wcove->tcpc.get_vbus = wcove_get_vbus;
    639	wcove->tcpc.set_vbus = wcove_set_vbus;
    640	wcove->tcpc.set_cc = wcove_set_cc;
    641	wcove->tcpc.get_cc = wcove_get_cc;
    642	wcove->tcpc.set_polarity = wcove_set_polarity;
    643	wcove->tcpc.set_vconn = wcove_set_vconn;
    644	wcove->tcpc.set_current_limit = wcove_set_current_limit;
    645	wcove->tcpc.start_toggling = wcove_start_toggling;
    646
    647	wcove->tcpc.set_pd_rx = wcove_set_pd_rx;
    648	wcove->tcpc.set_roles = wcove_set_roles;
    649	wcove->tcpc.pd_transmit = wcove_pd_transmit;
    650
    651	wcove->tcpc.fwnode = fwnode_create_software_node(wcove_props, NULL);
    652	if (IS_ERR(wcove->tcpc.fwnode))
    653		return PTR_ERR(wcove->tcpc.fwnode);
    654
    655	wcove->tcpm = tcpm_register_port(wcove->dev, &wcove->tcpc);
    656	if (IS_ERR(wcove->tcpm)) {
    657		fwnode_remove_software_node(wcove->tcpc.fwnode);
    658		return PTR_ERR(wcove->tcpm);
    659	}
    660
    661	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
    662					wcove_typec_irq, IRQF_ONESHOT,
    663					"wcove_typec", wcove);
    664	if (ret) {
    665		tcpm_unregister_port(wcove->tcpm);
    666		fwnode_remove_software_node(wcove->tcpc.fwnode);
    667		return ret;
    668	}
    669
    670	platform_set_drvdata(pdev, wcove);
    671	return 0;
    672}
    673
    674static int wcove_typec_remove(struct platform_device *pdev)
    675{
    676	struct wcove_typec *wcove = platform_get_drvdata(pdev);
    677	unsigned int val;
    678
    679	/* Mask everything */
    680	regmap_read(wcove->regmap, USBC_IRQMASK1, &val);
    681	regmap_write(wcove->regmap, USBC_IRQMASK1, val | USBC_IRQMASK1_ALL);
    682	regmap_read(wcove->regmap, USBC_IRQMASK2, &val);
    683	regmap_write(wcove->regmap, USBC_IRQMASK2, val | USBC_IRQMASK2_ALL);
    684
    685	tcpm_unregister_port(wcove->tcpm);
    686	fwnode_remove_software_node(wcove->tcpc.fwnode);
    687
    688	return 0;
    689}
    690
    691static struct platform_driver wcove_typec_driver = {
    692	.driver = {
    693		.name		= "bxt_wcove_usbc",
    694	},
    695	.probe			= wcove_typec_probe,
    696	.remove			= wcove_typec_remove,
    697};
    698
    699module_platform_driver(wcove_typec_driver);
    700
    701MODULE_AUTHOR("Intel Corporation");
    702MODULE_LICENSE("GPL v2");
    703MODULE_DESCRIPTION("WhiskeyCove PMIC USB Type-C PHY driver");
    704MODULE_ALIAS("platform:bxt_wcove_usbc");