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

axp20x_usb_power.c (17425B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * AXP20x PMIC USB power supply status driver
      4 *
      5 * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
      6 * Copyright (C) 2014 Bruno Prémont <bonbons@linux-vserver.org>
      7 */
      8
      9#include <linux/bitops.h>
     10#include <linux/device.h>
     11#include <linux/devm-helpers.h>
     12#include <linux/init.h>
     13#include <linux/interrupt.h>
     14#include <linux/kernel.h>
     15#include <linux/mfd/axp20x.h>
     16#include <linux/module.h>
     17#include <linux/of.h>
     18#include <linux/of_device.h>
     19#include <linux/platform_device.h>
     20#include <linux/pm.h>
     21#include <linux/power_supply.h>
     22#include <linux/regmap.h>
     23#include <linux/slab.h>
     24#include <linux/iio/consumer.h>
     25#include <linux/workqueue.h>
     26
     27#define DRVNAME "axp20x-usb-power-supply"
     28
     29#define AXP20X_PWR_STATUS_VBUS_PRESENT	BIT(5)
     30#define AXP20X_PWR_STATUS_VBUS_USED	BIT(4)
     31
     32#define AXP20X_USB_STATUS_VBUS_VALID	BIT(2)
     33
     34#define AXP20X_VBUS_PATH_SEL		BIT(7)
     35#define AXP20X_VBUS_PATH_SEL_OFFSET	7
     36
     37#define AXP20X_VBUS_VHOLD_uV(b)		(4000000 + (((b) >> 3) & 7) * 100000)
     38#define AXP20X_VBUS_VHOLD_MASK		GENMASK(5, 3)
     39#define AXP20X_VBUS_VHOLD_OFFSET	3
     40#define AXP20X_VBUS_CLIMIT_MASK		3
     41#define AXP20X_VBUS_CLIMIT_900mA	0
     42#define AXP20X_VBUS_CLIMIT_500mA	1
     43#define AXP20X_VBUS_CLIMIT_100mA	2
     44#define AXP20X_VBUS_CLIMIT_NONE		3
     45
     46#define AXP813_VBUS_CLIMIT_900mA	0
     47#define AXP813_VBUS_CLIMIT_1500mA	1
     48#define AXP813_VBUS_CLIMIT_2000mA	2
     49#define AXP813_VBUS_CLIMIT_2500mA	3
     50
     51#define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)
     52#define AXP20X_ADC_EN1_VBUS_VOLT	BIT(3)
     53
     54#define AXP20X_VBUS_MON_VBUS_VALID	BIT(3)
     55
     56#define AXP813_BC_EN		BIT(0)
     57
     58/*
     59 * Note do not raise the debounce time, we must report Vusb high within
     60 * 100ms otherwise we get Vbus errors in musb.
     61 */
     62#define DEBOUNCE_TIME			msecs_to_jiffies(50)
     63
     64struct axp20x_usb_power {
     65	struct regmap *regmap;
     66	struct power_supply *supply;
     67	enum axp20x_variants axp20x_id;
     68	struct iio_channel *vbus_v;
     69	struct iio_channel *vbus_i;
     70	struct delayed_work vbus_detect;
     71	unsigned int old_status;
     72	unsigned int online;
     73	unsigned int num_irqs;
     74	unsigned int irqs[];
     75};
     76
     77static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
     78{
     79	/*
     80	 * Polling is only necessary while VBUS is offline. While online, a
     81	 * present->absent transition implies an online->offline transition
     82	 * and will trigger the VBUS_REMOVAL IRQ.
     83	 */
     84	if (power->axp20x_id >= AXP221_ID && !power->online)
     85		return true;
     86
     87	return false;
     88}
     89
     90static irqreturn_t axp20x_usb_power_irq(int irq, void *devid)
     91{
     92	struct axp20x_usb_power *power = devid;
     93
     94	power_supply_changed(power->supply);
     95
     96	mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
     97
     98	return IRQ_HANDLED;
     99}
    100
    101static void axp20x_usb_power_poll_vbus(struct work_struct *work)
    102{
    103	struct axp20x_usb_power *power =
    104		container_of(work, struct axp20x_usb_power, vbus_detect.work);
    105	unsigned int val;
    106	int ret;
    107
    108	ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &val);
    109	if (ret)
    110		goto out;
    111
    112	val &= (AXP20X_PWR_STATUS_VBUS_PRESENT | AXP20X_PWR_STATUS_VBUS_USED);
    113	if (val != power->old_status)
    114		power_supply_changed(power->supply);
    115
    116	power->old_status = val;
    117	power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
    118
    119out:
    120	if (axp20x_usb_vbus_needs_polling(power))
    121		mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
    122}
    123
    124static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val)
    125{
    126	unsigned int v;
    127	int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
    128
    129	if (ret)
    130		return ret;
    131
    132	switch (v & AXP20X_VBUS_CLIMIT_MASK) {
    133	case AXP20X_VBUS_CLIMIT_100mA:
    134		if (power->axp20x_id == AXP221_ID)
    135			*val = -1; /* No 100mA limit */
    136		else
    137			*val = 100000;
    138		break;
    139	case AXP20X_VBUS_CLIMIT_500mA:
    140		*val = 500000;
    141		break;
    142	case AXP20X_VBUS_CLIMIT_900mA:
    143		*val = 900000;
    144		break;
    145	case AXP20X_VBUS_CLIMIT_NONE:
    146		*val = -1;
    147		break;
    148	}
    149
    150	return 0;
    151}
    152
    153static int axp813_get_current_max(struct axp20x_usb_power *power, int *val)
    154{
    155	unsigned int v;
    156	int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
    157
    158	if (ret)
    159		return ret;
    160
    161	switch (v & AXP20X_VBUS_CLIMIT_MASK) {
    162	case AXP813_VBUS_CLIMIT_900mA:
    163		*val = 900000;
    164		break;
    165	case AXP813_VBUS_CLIMIT_1500mA:
    166		*val = 1500000;
    167		break;
    168	case AXP813_VBUS_CLIMIT_2000mA:
    169		*val = 2000000;
    170		break;
    171	case AXP813_VBUS_CLIMIT_2500mA:
    172		*val = 2500000;
    173		break;
    174	}
    175	return 0;
    176}
    177
    178static int axp20x_usb_power_get_property(struct power_supply *psy,
    179	enum power_supply_property psp, union power_supply_propval *val)
    180{
    181	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
    182	unsigned int input, v;
    183	int ret;
    184
    185	switch (psp) {
    186	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
    187		ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
    188		if (ret)
    189			return ret;
    190
    191		val->intval = AXP20X_VBUS_VHOLD_uV(v);
    192		return 0;
    193	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
    194		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
    195			ret = iio_read_channel_processed(power->vbus_v,
    196							 &val->intval);
    197			if (ret)
    198				return ret;
    199
    200			/*
    201			 * IIO framework gives mV but Power Supply framework
    202			 * gives uV.
    203			 */
    204			val->intval *= 1000;
    205			return 0;
    206		}
    207
    208		ret = axp20x_read_variable_width(power->regmap,
    209						 AXP20X_VBUS_V_ADC_H, 12);
    210		if (ret < 0)
    211			return ret;
    212
    213		val->intval = ret * 1700; /* 1 step = 1.7 mV */
    214		return 0;
    215	case POWER_SUPPLY_PROP_CURRENT_MAX:
    216		if (power->axp20x_id == AXP813_ID)
    217			return axp813_get_current_max(power, &val->intval);
    218		return axp20x_get_current_max(power, &val->intval);
    219	case POWER_SUPPLY_PROP_CURRENT_NOW:
    220		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
    221			ret = iio_read_channel_processed(power->vbus_i,
    222							 &val->intval);
    223			if (ret)
    224				return ret;
    225
    226			/*
    227			 * IIO framework gives mA but Power Supply framework
    228			 * gives uA.
    229			 */
    230			val->intval *= 1000;
    231			return 0;
    232		}
    233
    234		ret = axp20x_read_variable_width(power->regmap,
    235						 AXP20X_VBUS_I_ADC_H, 12);
    236		if (ret < 0)
    237			return ret;
    238
    239		val->intval = ret * 375; /* 1 step = 0.375 mA */
    240		return 0;
    241	default:
    242		break;
    243	}
    244
    245	/* All the properties below need the input-status reg value */
    246	ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);
    247	if (ret)
    248		return ret;
    249
    250	switch (psp) {
    251	case POWER_SUPPLY_PROP_HEALTH:
    252		if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
    253			val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
    254			break;
    255		}
    256
    257		val->intval = POWER_SUPPLY_HEALTH_GOOD;
    258
    259		if (power->axp20x_id == AXP202_ID) {
    260			ret = regmap_read(power->regmap,
    261					  AXP20X_USB_OTG_STATUS, &v);
    262			if (ret)
    263				return ret;
    264
    265			if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
    266				val->intval =
    267					POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
    268		}
    269		break;
    270	case POWER_SUPPLY_PROP_PRESENT:
    271		val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
    272		break;
    273	case POWER_SUPPLY_PROP_ONLINE:
    274		val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED);
    275		break;
    276	default:
    277		return -EINVAL;
    278	}
    279
    280	return 0;
    281}
    282
    283static int axp813_usb_power_set_online(struct axp20x_usb_power *power,
    284				       int intval)
    285{
    286	int val = !intval << AXP20X_VBUS_PATH_SEL_OFFSET;
    287
    288	return regmap_update_bits(power->regmap,
    289				  AXP20X_VBUS_IPSOUT_MGMT,
    290				  AXP20X_VBUS_PATH_SEL, val);
    291}
    292
    293static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
    294					    int intval)
    295{
    296	int val;
    297
    298	switch (intval) {
    299	case 4000000:
    300	case 4100000:
    301	case 4200000:
    302	case 4300000:
    303	case 4400000:
    304	case 4500000:
    305	case 4600000:
    306	case 4700000:
    307		val = (intval - 4000000) / 100000;
    308		return regmap_update_bits(power->regmap,
    309					  AXP20X_VBUS_IPSOUT_MGMT,
    310					  AXP20X_VBUS_VHOLD_MASK,
    311					  val << AXP20X_VBUS_VHOLD_OFFSET);
    312	default:
    313		return -EINVAL;
    314	}
    315
    316	return -EINVAL;
    317}
    318
    319static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power,
    320					    int intval)
    321{
    322	int val;
    323
    324	switch (intval) {
    325	case 900000:
    326		return regmap_update_bits(power->regmap,
    327					  AXP20X_VBUS_IPSOUT_MGMT,
    328					  AXP20X_VBUS_CLIMIT_MASK,
    329					  AXP813_VBUS_CLIMIT_900mA);
    330	case 1500000:
    331	case 2000000:
    332	case 2500000:
    333		val = (intval - 1000000) / 500000;
    334		return regmap_update_bits(power->regmap,
    335					  AXP20X_VBUS_IPSOUT_MGMT,
    336					  AXP20X_VBUS_CLIMIT_MASK, val);
    337	default:
    338		return -EINVAL;
    339	}
    340
    341	return -EINVAL;
    342}
    343
    344static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power,
    345					    int intval)
    346{
    347	int val;
    348
    349	switch (intval) {
    350	case 100000:
    351		if (power->axp20x_id == AXP221_ID)
    352			return -EINVAL;
    353		fallthrough;
    354	case 500000:
    355	case 900000:
    356		val = (900000 - intval) / 400000;
    357		return regmap_update_bits(power->regmap,
    358					  AXP20X_VBUS_IPSOUT_MGMT,
    359					  AXP20X_VBUS_CLIMIT_MASK, val);
    360	default:
    361		return -EINVAL;
    362	}
    363
    364	return -EINVAL;
    365}
    366
    367static int axp20x_usb_power_set_property(struct power_supply *psy,
    368					 enum power_supply_property psp,
    369					 const union power_supply_propval *val)
    370{
    371	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
    372
    373	switch (psp) {
    374	case POWER_SUPPLY_PROP_ONLINE:
    375		if (power->axp20x_id != AXP813_ID)
    376			return -EINVAL;
    377		return axp813_usb_power_set_online(power, val->intval);
    378
    379	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
    380		return axp20x_usb_power_set_voltage_min(power, val->intval);
    381
    382	case POWER_SUPPLY_PROP_CURRENT_MAX:
    383		if (power->axp20x_id == AXP813_ID)
    384			return axp813_usb_power_set_current_max(power,
    385								val->intval);
    386		return axp20x_usb_power_set_current_max(power, val->intval);
    387
    388	default:
    389		return -EINVAL;
    390	}
    391
    392	return -EINVAL;
    393}
    394
    395static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
    396					   enum power_supply_property psp)
    397{
    398	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
    399
    400	/*
    401	 * The VBUS path select flag works differently on AXP288 and newer:
    402	 *  - On AXP20x and AXP22x, the flag enables VBUS (ignoring N_VBUSEN).
    403	 *  - On AXP288 and AXP8xx, the flag disables VBUS (ignoring N_VBUSEN).
    404	 * We only expose the control on variants where it can be used to force
    405	 * the VBUS input offline.
    406	 */
    407	if (psp == POWER_SUPPLY_PROP_ONLINE)
    408		return power->axp20x_id == AXP813_ID;
    409
    410	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
    411	       psp == POWER_SUPPLY_PROP_CURRENT_MAX;
    412}
    413
    414static enum power_supply_property axp20x_usb_power_properties[] = {
    415	POWER_SUPPLY_PROP_HEALTH,
    416	POWER_SUPPLY_PROP_PRESENT,
    417	POWER_SUPPLY_PROP_ONLINE,
    418	POWER_SUPPLY_PROP_VOLTAGE_MIN,
    419	POWER_SUPPLY_PROP_VOLTAGE_NOW,
    420	POWER_SUPPLY_PROP_CURRENT_MAX,
    421	POWER_SUPPLY_PROP_CURRENT_NOW,
    422};
    423
    424static enum power_supply_property axp22x_usb_power_properties[] = {
    425	POWER_SUPPLY_PROP_HEALTH,
    426	POWER_SUPPLY_PROP_PRESENT,
    427	POWER_SUPPLY_PROP_ONLINE,
    428	POWER_SUPPLY_PROP_VOLTAGE_MIN,
    429	POWER_SUPPLY_PROP_CURRENT_MAX,
    430};
    431
    432static const struct power_supply_desc axp20x_usb_power_desc = {
    433	.name = "axp20x-usb",
    434	.type = POWER_SUPPLY_TYPE_USB,
    435	.properties = axp20x_usb_power_properties,
    436	.num_properties = ARRAY_SIZE(axp20x_usb_power_properties),
    437	.property_is_writeable = axp20x_usb_power_prop_writeable,
    438	.get_property = axp20x_usb_power_get_property,
    439	.set_property = axp20x_usb_power_set_property,
    440};
    441
    442static const struct power_supply_desc axp22x_usb_power_desc = {
    443	.name = "axp20x-usb",
    444	.type = POWER_SUPPLY_TYPE_USB,
    445	.properties = axp22x_usb_power_properties,
    446	.num_properties = ARRAY_SIZE(axp22x_usb_power_properties),
    447	.property_is_writeable = axp20x_usb_power_prop_writeable,
    448	.get_property = axp20x_usb_power_get_property,
    449	.set_property = axp20x_usb_power_set_property,
    450};
    451
    452static const char * const axp20x_irq_names[] = {
    453	"VBUS_PLUGIN",
    454	"VBUS_REMOVAL",
    455	"VBUS_VALID",
    456	"VBUS_NOT_VALID",
    457};
    458
    459static const char * const axp22x_irq_names[] = {
    460	"VBUS_PLUGIN",
    461	"VBUS_REMOVAL",
    462};
    463
    464struct axp_data {
    465	const struct power_supply_desc	*power_desc;
    466	const char * const		*irq_names;
    467	unsigned int			num_irq_names;
    468	enum axp20x_variants		axp20x_id;
    469};
    470
    471static const struct axp_data axp202_data = {
    472	.power_desc	= &axp20x_usb_power_desc,
    473	.irq_names	= axp20x_irq_names,
    474	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),
    475	.axp20x_id	= AXP202_ID,
    476};
    477
    478static const struct axp_data axp221_data = {
    479	.power_desc	= &axp22x_usb_power_desc,
    480	.irq_names	= axp22x_irq_names,
    481	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
    482	.axp20x_id	= AXP221_ID,
    483};
    484
    485static const struct axp_data axp223_data = {
    486	.power_desc	= &axp22x_usb_power_desc,
    487	.irq_names	= axp22x_irq_names,
    488	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
    489	.axp20x_id	= AXP223_ID,
    490};
    491
    492static const struct axp_data axp813_data = {
    493	.power_desc	= &axp22x_usb_power_desc,
    494	.irq_names	= axp22x_irq_names,
    495	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
    496	.axp20x_id	= AXP813_ID,
    497};
    498
    499#ifdef CONFIG_PM_SLEEP
    500static int axp20x_usb_power_suspend(struct device *dev)
    501{
    502	struct axp20x_usb_power *power = dev_get_drvdata(dev);
    503	int i = 0;
    504
    505	/*
    506	 * Allow wake via VBUS_PLUGIN only.
    507	 *
    508	 * As nested threaded IRQs are not automatically disabled during
    509	 * suspend, we must explicitly disable the remainder of the IRQs.
    510	 */
    511	if (device_may_wakeup(&power->supply->dev))
    512		enable_irq_wake(power->irqs[i++]);
    513	while (i < power->num_irqs)
    514		disable_irq(power->irqs[i++]);
    515
    516	return 0;
    517}
    518
    519static int axp20x_usb_power_resume(struct device *dev)
    520{
    521	struct axp20x_usb_power *power = dev_get_drvdata(dev);
    522	int i = 0;
    523
    524	if (device_may_wakeup(&power->supply->dev))
    525		disable_irq_wake(power->irqs[i++]);
    526	while (i < power->num_irqs)
    527		enable_irq(power->irqs[i++]);
    528
    529	mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
    530
    531	return 0;
    532}
    533#endif
    534
    535static SIMPLE_DEV_PM_OPS(axp20x_usb_power_pm_ops, axp20x_usb_power_suspend,
    536						  axp20x_usb_power_resume);
    537
    538static int configure_iio_channels(struct platform_device *pdev,
    539				  struct axp20x_usb_power *power)
    540{
    541	power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
    542	if (IS_ERR(power->vbus_v)) {
    543		if (PTR_ERR(power->vbus_v) == -ENODEV)
    544			return -EPROBE_DEFER;
    545		return PTR_ERR(power->vbus_v);
    546	}
    547
    548	power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i");
    549	if (IS_ERR(power->vbus_i)) {
    550		if (PTR_ERR(power->vbus_i) == -ENODEV)
    551			return -EPROBE_DEFER;
    552		return PTR_ERR(power->vbus_i);
    553	}
    554
    555	return 0;
    556}
    557
    558static int configure_adc_registers(struct axp20x_usb_power *power)
    559{
    560	/* Enable vbus voltage and current measurement */
    561	return regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
    562				  AXP20X_ADC_EN1_VBUS_CURR |
    563				  AXP20X_ADC_EN1_VBUS_VOLT,
    564				  AXP20X_ADC_EN1_VBUS_CURR |
    565				  AXP20X_ADC_EN1_VBUS_VOLT);
    566}
    567
    568static int axp20x_usb_power_probe(struct platform_device *pdev)
    569{
    570	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
    571	struct power_supply_config psy_cfg = {};
    572	struct axp20x_usb_power *power;
    573	const struct axp_data *axp_data;
    574	int i, irq, ret;
    575
    576	if (!of_device_is_available(pdev->dev.of_node))
    577		return -ENODEV;
    578
    579	if (!axp20x) {
    580		dev_err(&pdev->dev, "Parent drvdata not set\n");
    581		return -EINVAL;
    582	}
    583
    584	axp_data = of_device_get_match_data(&pdev->dev);
    585
    586	power = devm_kzalloc(&pdev->dev,
    587			     struct_size(power, irqs, axp_data->num_irq_names),
    588			     GFP_KERNEL);
    589	if (!power)
    590		return -ENOMEM;
    591
    592	platform_set_drvdata(pdev, power);
    593
    594	power->axp20x_id = axp_data->axp20x_id;
    595	power->regmap = axp20x->regmap;
    596	power->num_irqs = axp_data->num_irq_names;
    597
    598	ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
    599					   axp20x_usb_power_poll_vbus);
    600	if (ret)
    601		return ret;
    602
    603	if (power->axp20x_id == AXP202_ID) {
    604		/* Enable vbus valid checking */
    605		ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
    606					 AXP20X_VBUS_MON_VBUS_VALID,
    607					 AXP20X_VBUS_MON_VBUS_VALID);
    608		if (ret)
    609			return ret;
    610
    611		if (IS_ENABLED(CONFIG_AXP20X_ADC))
    612			ret = configure_iio_channels(pdev, power);
    613		else
    614			ret = configure_adc_registers(power);
    615
    616		if (ret)
    617			return ret;
    618	}
    619
    620	if (power->axp20x_id == AXP813_ID) {
    621		/* Enable USB Battery Charging specification detection */
    622		ret = regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL,
    623				   AXP813_BC_EN, AXP813_BC_EN);
    624		if (ret)
    625			return ret;
    626	}
    627
    628	psy_cfg.of_node = pdev->dev.of_node;
    629	psy_cfg.drv_data = power;
    630
    631	power->supply = devm_power_supply_register(&pdev->dev,
    632						   axp_data->power_desc,
    633						   &psy_cfg);
    634	if (IS_ERR(power->supply))
    635		return PTR_ERR(power->supply);
    636
    637	/* Request irqs after registering, as irqs may trigger immediately */
    638	for (i = 0; i < axp_data->num_irq_names; i++) {
    639		irq = platform_get_irq_byname(pdev, axp_data->irq_names[i]);
    640		if (irq < 0)
    641			return irq;
    642
    643		power->irqs[i] = regmap_irq_get_virq(axp20x->regmap_irqc, irq);
    644		ret = devm_request_any_context_irq(&pdev->dev, power->irqs[i],
    645						   axp20x_usb_power_irq, 0,
    646						   DRVNAME, power);
    647		if (ret < 0) {
    648			dev_err(&pdev->dev, "Error requesting %s IRQ: %d\n",
    649				axp_data->irq_names[i], ret);
    650			return ret;
    651		}
    652	}
    653
    654	if (axp20x_usb_vbus_needs_polling(power))
    655		queue_delayed_work(system_power_efficient_wq, &power->vbus_detect, 0);
    656
    657	return 0;
    658}
    659
    660static const struct of_device_id axp20x_usb_power_match[] = {
    661	{
    662		.compatible = "x-powers,axp202-usb-power-supply",
    663		.data = &axp202_data,
    664	}, {
    665		.compatible = "x-powers,axp221-usb-power-supply",
    666		.data = &axp221_data,
    667	}, {
    668		.compatible = "x-powers,axp223-usb-power-supply",
    669		.data = &axp223_data,
    670	}, {
    671		.compatible = "x-powers,axp813-usb-power-supply",
    672		.data = &axp813_data,
    673	}, { /* sentinel */ }
    674};
    675MODULE_DEVICE_TABLE(of, axp20x_usb_power_match);
    676
    677static struct platform_driver axp20x_usb_power_driver = {
    678	.probe = axp20x_usb_power_probe,
    679	.driver = {
    680		.name		= DRVNAME,
    681		.of_match_table	= axp20x_usb_power_match,
    682		.pm		= &axp20x_usb_power_pm_ops,
    683	},
    684};
    685
    686module_platform_driver(axp20x_usb_power_driver);
    687
    688MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
    689MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver");
    690MODULE_LICENSE("GPL");