brintos

brintos / linux-shallow public Read only

0
0
Text · 28.9 KiB · 2766352 Raw
1086 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * AXP20x PMIC USB power supply status driver4 *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/platform_device.h>19#include <linux/pm.h>20#include <linux/power_supply.h>21#include <linux/regmap.h>22#include <linux/slab.h>23#include <linux/iio/consumer.h>24#include <linux/workqueue.h>25 26#define DRVNAME "axp20x-usb-power-supply"27 28#define AXP192_USB_OTG_STATUS		0x0429 30#define AXP20X_PWR_STATUS_VBUS_PRESENT	BIT(5)31#define AXP20X_PWR_STATUS_VBUS_USED	BIT(4)32 33#define AXP717_PWR_STATUS_VBUS_GOOD	BIT(5)34 35#define AXP20X_USB_STATUS_VBUS_VALID	BIT(2)36 37#define AXP717_PMU_FAULT_VBUS		BIT(5)38#define AXP717_PMU_FAULT_VSYS		BIT(3)39 40#define AXP20X_VBUS_VHOLD_uV(b)		(4000000 + (((b) >> 3) & 7) * 100000)41#define AXP20X_VBUS_VHOLD_MASK		GENMASK(5, 3)42#define AXP20X_VBUS_VHOLD_OFFSET	343 44#define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)45#define AXP20X_ADC_EN1_VBUS_VOLT	BIT(3)46 47#define AXP717_INPUT_VOL_LIMIT_MASK	GENMASK(3, 0)48#define AXP717_INPUT_CUR_LIMIT_MASK	GENMASK(5, 0)49#define AXP717_ADC_DATA_MASK		GENMASK(14, 0)50 51#define AXP717_ADC_EN_VBUS_VOLT		BIT(2)52 53/*54 * Note do not raise the debounce time, we must report Vusb high within55 * 100ms otherwise we get Vbus errors in musb.56 */57#define DEBOUNCE_TIME			msecs_to_jiffies(50)58 59struct axp20x_usb_power;60 61struct axp_data {62	const struct power_supply_desc	*power_desc;63	const char * const		*irq_names;64	unsigned int			num_irq_names;65	const int			*curr_lim_table;66	int				curr_lim_table_size;67	struct reg_field		curr_lim_fld;68	struct reg_field		vbus_valid_bit;69	struct reg_field		vbus_mon_bit;70	struct reg_field		usb_bc_en_bit;71	struct reg_field		usb_bc_det_fld;72	struct reg_field		vbus_disable_bit;73	bool				vbus_needs_polling: 1;74	void (*axp20x_read_vbus)(struct work_struct *work);75	int (*axp20x_cfg_iio_chan)(struct platform_device *pdev,76				   struct axp20x_usb_power *power);77	int (*axp20x_cfg_adc_reg)(struct axp20x_usb_power *power);78};79 80struct axp20x_usb_power {81	struct device *dev;82	struct regmap *regmap;83	struct regmap_field *curr_lim_fld;84	struct regmap_field *vbus_valid_bit;85	struct regmap_field *vbus_mon_bit;86	struct regmap_field *usb_bc_en_bit;87	struct regmap_field *usb_bc_det_fld;88	struct regmap_field *vbus_disable_bit;89	struct power_supply *supply;90	const struct axp_data *axp_data;91	struct iio_channel *vbus_v;92	struct iio_channel *vbus_i;93	struct delayed_work vbus_detect;94	int max_input_cur;95	unsigned int old_status;96	unsigned int online;97	unsigned int num_irqs;98	unsigned int irqs[] __counted_by(num_irqs);99};100 101static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)102{103	/*104	 * Polling is only necessary while VBUS is offline. While online, a105	 * present->absent transition implies an online->offline transition106	 * and will trigger the VBUS_REMOVAL IRQ.107	 */108	if (power->axp_data->vbus_needs_polling && !power->online)109		return true;110 111	return false;112}113 114static irqreturn_t axp20x_usb_power_irq(int irq, void *devid)115{116	struct axp20x_usb_power *power = devid;117 118	power_supply_changed(power->supply);119 120	mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);121 122	return IRQ_HANDLED;123}124 125static void axp20x_usb_power_poll_vbus(struct work_struct *work)126{127	struct axp20x_usb_power *power =128		container_of(work, struct axp20x_usb_power, vbus_detect.work);129	unsigned int val;130	int ret;131 132	ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &val);133	if (ret)134		goto out;135 136	val &= (AXP20X_PWR_STATUS_VBUS_PRESENT | AXP20X_PWR_STATUS_VBUS_USED);137	if (val != power->old_status)138		power_supply_changed(power->supply);139 140	if (power->usb_bc_en_bit && (val & AXP20X_PWR_STATUS_VBUS_PRESENT) !=141		(power->old_status & AXP20X_PWR_STATUS_VBUS_PRESENT)) {142		dev_dbg(power->dev, "Cable status changed, re-enabling USB BC");143		ret = regmap_field_write(power->usb_bc_en_bit, 1);144		if (ret)145			dev_err(power->dev, "failed to enable USB BC: errno %d",146				ret);147	}148 149	power->old_status = val;150	power->online = val & AXP20X_PWR_STATUS_VBUS_USED;151 152out:153	if (axp20x_usb_vbus_needs_polling(power))154		mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);155}156 157static void axp717_usb_power_poll_vbus(struct work_struct *work)158{159	struct axp20x_usb_power *power =160		container_of(work, struct axp20x_usb_power, vbus_detect.work);161	unsigned int val;162	int ret;163 164	ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &val);165	if (ret)166		return;167 168	val &= AXP717_PWR_STATUS_VBUS_GOOD;169	if (val != power->old_status)170		power_supply_changed(power->supply);171 172	power->old_status = val;173}174 175static int axp20x_get_usb_type(struct axp20x_usb_power *power,176			       union power_supply_propval *val)177{178	unsigned int reg;179	int ret;180 181	if (!power->usb_bc_det_fld)182		return -EINVAL;183 184	ret = regmap_field_read(power->usb_bc_det_fld, &reg);185	if (ret)186		return ret;187 188	switch (reg) {189	case 1:190		val->intval = POWER_SUPPLY_USB_TYPE_SDP;191		break;192	case 2:193		val->intval = POWER_SUPPLY_USB_TYPE_CDP;194		break;195	case 3:196		val->intval = POWER_SUPPLY_USB_TYPE_DCP;197		break;198	default:199		val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;200		break;201	}202 203	return 0;204}205 206static int axp20x_usb_power_get_property(struct power_supply *psy,207	enum power_supply_property psp, union power_supply_propval *val)208{209	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);210	unsigned int input, v;211	int ret;212 213	switch (psp) {214	case POWER_SUPPLY_PROP_VOLTAGE_MIN:215		ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);216		if (ret)217			return ret;218 219		val->intval = AXP20X_VBUS_VHOLD_uV(v);220		return 0;221	case POWER_SUPPLY_PROP_VOLTAGE_NOW:222		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {223			ret = iio_read_channel_processed(power->vbus_v,224							 &val->intval);225			if (ret)226				return ret;227 228			/*229			 * IIO framework gives mV but Power Supply framework230			 * gives uV.231			 */232			val->intval *= 1000;233			return 0;234		}235 236		ret = axp20x_read_variable_width(power->regmap,237						 AXP20X_VBUS_V_ADC_H, 12);238		if (ret < 0)239			return ret;240 241		val->intval = ret * 1700; /* 1 step = 1.7 mV */242		return 0;243	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:244		ret = regmap_field_read(power->curr_lim_fld, &v);245		if (ret)246			return ret;247 248		if (v < power->axp_data->curr_lim_table_size)249			val->intval = power->axp_data->curr_lim_table[v];250		else251			val->intval = power->axp_data->curr_lim_table[252				power->axp_data->curr_lim_table_size - 1];253		return 0;254	case POWER_SUPPLY_PROP_CURRENT_NOW:255		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {256			ret = iio_read_channel_processed(power->vbus_i,257							 &val->intval);258			if (ret)259				return ret;260 261			/*262			 * IIO framework gives mA but Power Supply framework263			 * gives uA.264			 */265			val->intval *= 1000;266			return 0;267		}268 269		ret = axp20x_read_variable_width(power->regmap,270						 AXP20X_VBUS_I_ADC_H, 12);271		if (ret < 0)272			return ret;273 274		val->intval = ret * 375; /* 1 step = 0.375 mA */275		return 0;276 277	case POWER_SUPPLY_PROP_USB_TYPE:278		return axp20x_get_usb_type(power, val);279	default:280		break;281	}282 283	/* All the properties below need the input-status reg value */284	ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);285	if (ret)286		return ret;287 288	switch (psp) {289	case POWER_SUPPLY_PROP_HEALTH:290		if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) {291			val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;292			break;293		}294 295		val->intval = POWER_SUPPLY_HEALTH_GOOD;296 297		if (power->vbus_valid_bit) {298			ret = regmap_field_read(power->vbus_valid_bit, &v);299			if (ret)300				return ret;301 302			if (v == 0)303				val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;304		}305 306		break;307	case POWER_SUPPLY_PROP_PRESENT:308		val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);309		break;310	case POWER_SUPPLY_PROP_ONLINE:311		val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED);312		break;313	default:314		return -EINVAL;315	}316 317	return 0;318}319 320static int axp717_usb_power_get_property(struct power_supply *psy,321	enum power_supply_property psp, union power_supply_propval *val)322{323	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);324	unsigned int v;325	int ret;326 327	switch (psp) {328	case POWER_SUPPLY_PROP_HEALTH:329		val->intval = POWER_SUPPLY_HEALTH_GOOD;330		ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);331		if (ret)332			return ret;333 334		if (!(v & AXP717_PWR_STATUS_VBUS_GOOD))335			val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;336 337		ret = regmap_read(power->regmap, AXP717_PMU_FAULT_VBUS, &v);338		if (ret)339			return ret;340 341		v &= (AXP717_PMU_FAULT_VBUS | AXP717_PMU_FAULT_VSYS);342		if (v) {343			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;344			regmap_write(power->regmap, AXP717_PMU_FAULT_VBUS, v);345		}346 347		break;348	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:349		ret = regmap_read(power->regmap, AXP717_INPUT_CUR_LIMIT_CTRL, &v);350		if (ret)351			return ret;352 353		/* 50ma step size with 100ma offset. */354		v &= AXP717_INPUT_CUR_LIMIT_MASK;355		val->intval = (v * 50000) + 100000;356		break;357	case POWER_SUPPLY_PROP_ONLINE:358	case POWER_SUPPLY_PROP_PRESENT:359		ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);360		if (ret)361			return ret;362		val->intval = !!(v & AXP717_PWR_STATUS_VBUS_GOOD);363		break;364	case POWER_SUPPLY_PROP_USB_TYPE:365		return axp20x_get_usb_type(power, val);366	case POWER_SUPPLY_PROP_VOLTAGE_MIN:367		ret = regmap_read(power->regmap, AXP717_INPUT_VOL_LIMIT_CTRL, &v);368		if (ret)369			return ret;370 371		/* 80mv step size with 3.88v offset. */372		v &= AXP717_INPUT_VOL_LIMIT_MASK;373		val->intval = (v * 80000) + 3880000;374		break;375	case POWER_SUPPLY_PROP_VOLTAGE_NOW:376		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {377			ret = iio_read_channel_processed(power->vbus_v,378							 &val->intval);379			if (ret)380				return ret;381 382			/*383			 * IIO framework gives mV but Power Supply framework384			 * gives uV.385			 */386			val->intval *= 1000;387			return 0;388		}389 390		ret = axp20x_read_variable_width(power->regmap,391						 AXP717_VBUS_V_H, 16);392		if (ret < 0)393			return ret;394 395		val->intval = (ret % AXP717_ADC_DATA_MASK) * 1000;396		break;397	default:398		return -EINVAL;399	}400 401	return 0;402 403}404 405static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,406					    int intval)407{408	int val;409 410	switch (intval) {411	case 4000000:412	case 4100000:413	case 4200000:414	case 4300000:415	case 4400000:416	case 4500000:417	case 4600000:418	case 4700000:419		val = (intval - 4000000) / 100000;420		return regmap_update_bits(power->regmap,421					  AXP20X_VBUS_IPSOUT_MGMT,422					  AXP20X_VBUS_VHOLD_MASK,423					  val << AXP20X_VBUS_VHOLD_OFFSET);424	default:425		return -EINVAL;426	}427 428	return -EINVAL;429}430 431static int axp717_usb_power_set_voltage_min(struct axp20x_usb_power *power,432					    int intval)433{434	int val;435 436	/* Minimum value of 3.88v and maximum of 5.08v. */437	if (intval < 3880000 || intval > 5080000)438		return -EINVAL;439 440	/* step size of 80ma with 3.88v offset. */441	val = (intval - 3880000) / 80000;442	return regmap_update_bits(power->regmap,443				  AXP717_INPUT_VOL_LIMIT_CTRL,444				  AXP717_INPUT_VOL_LIMIT_MASK, val);445}446 447static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,448						    int intval)449{450	int ret;451	unsigned int reg;452	const unsigned int max = power->axp_data->curr_lim_table_size;453 454	if (intval == -1)455		return -EINVAL;456 457	if (power->max_input_cur && (intval > power->max_input_cur)) {458		dev_warn(power->dev,459			 "requested current %d clamped to max current %d\n",460			 intval, power->max_input_cur);461		intval = power->max_input_cur;462	}463 464	/*465	 * BC1.2 detection can cause a race condition if we try to set a current466	 * limit while it's in progress. When it finishes it will overwrite the467	 * current limit we just set.468	 */469	if (power->usb_bc_en_bit) {470		dev_dbg(power->dev,471			"disabling BC1.2 detection because current limit was set");472		ret = regmap_field_write(power->usb_bc_en_bit, 0);473		if (ret)474			return ret;475	}476 477	for (reg = max - 1; reg > 0; reg--)478		if (power->axp_data->curr_lim_table[reg] <= intval)479			break;480 481	dev_dbg(power->dev, "setting input current limit reg to %d (%d uA), requested %d uA",482		reg, power->axp_data->curr_lim_table[reg], intval);483 484	return regmap_field_write(power->curr_lim_fld, reg);485}486 487static int axp717_usb_power_set_input_current_limit(struct axp20x_usb_power *power,488						    int intval)489{490	int tmp;491 492	/* Minimum value of 100mA and maximum value of 3.25A*/493	if (intval < 100000 || intval > 3250000)494		return -EINVAL;495 496	if (power->max_input_cur && (intval > power->max_input_cur)) {497		dev_warn(power->dev,498			 "reqested current %d clamped to max current %d\n",499			 intval, power->max_input_cur);500		intval = power->max_input_cur;501	}502 503	/* Minimum value of 100mA with step size of 50mA. */504	tmp = (intval - 100000) / 50000;505	return regmap_update_bits(power->regmap,506				  AXP717_INPUT_CUR_LIMIT_CTRL,507				  AXP717_INPUT_CUR_LIMIT_MASK, tmp);508}509 510static int axp20x_usb_power_set_property(struct power_supply *psy,511					 enum power_supply_property psp,512					 const union power_supply_propval *val)513{514	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);515 516	switch (psp) {517	case POWER_SUPPLY_PROP_ONLINE:518		if (!power->vbus_disable_bit)519			return -EINVAL;520 521		return regmap_field_write(power->vbus_disable_bit, !val->intval);522 523	case POWER_SUPPLY_PROP_VOLTAGE_MIN:524		return axp20x_usb_power_set_voltage_min(power, val->intval);525 526	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:527		return axp20x_usb_power_set_input_current_limit(power, val->intval);528 529	default:530		return -EINVAL;531	}532}533 534static int axp717_usb_power_set_property(struct power_supply *psy,535					 enum power_supply_property psp,536					 const union power_supply_propval *val)537{538	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);539 540	switch (psp) {541	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:542		return axp717_usb_power_set_input_current_limit(power, val->intval);543 544	case POWER_SUPPLY_PROP_VOLTAGE_MIN:545		return axp717_usb_power_set_voltage_min(power, val->intval);546 547	default:548		return -EINVAL;549	}550 551	return -EINVAL;552}553 554static int axp20x_usb_power_prop_writeable(struct power_supply *psy,555					   enum power_supply_property psp)556{557	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);558 559	/*560	 * The VBUS path select flag works differently on AXP288 and newer:561	 *  - On AXP20x and AXP22x, the flag enables VBUS (ignoring N_VBUSEN).562	 *  - On AXP288 and AXP8xx, the flag disables VBUS (ignoring N_VBUSEN).563	 * We only expose the control on variants where it can be used to force564	 * the VBUS input offline.565	 */566	if (psp == POWER_SUPPLY_PROP_ONLINE)567		return power->vbus_disable_bit != NULL;568 569	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||570	       psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;571}572 573static int axp717_usb_power_prop_writeable(struct power_supply *psy,574					   enum power_supply_property psp)575{576	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||577	       psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;578}579 580static int axp20x_configure_iio_channels(struct platform_device *pdev,581					 struct axp20x_usb_power *power)582{583	power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");584	if (IS_ERR(power->vbus_v)) {585		if (PTR_ERR(power->vbus_v) == -ENODEV)586			return -EPROBE_DEFER;587		return PTR_ERR(power->vbus_v);588	}589 590	power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i");591	if (IS_ERR(power->vbus_i)) {592		if (PTR_ERR(power->vbus_i) == -ENODEV)593			return -EPROBE_DEFER;594		return PTR_ERR(power->vbus_i);595	}596 597	return 0;598}599 600static int axp717_configure_iio_channels(struct platform_device *pdev,601					 struct axp20x_usb_power *power)602{603	power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");604	if (IS_ERR(power->vbus_v)) {605		if (PTR_ERR(power->vbus_v) == -ENODEV)606			return -EPROBE_DEFER;607		return PTR_ERR(power->vbus_v);608	}609 610	return 0;611}612 613static int axp20x_configure_adc_registers(struct axp20x_usb_power *power)614{615	/* Enable vbus voltage and current measurement */616	return regmap_update_bits(power->regmap, AXP20X_ADC_EN1,617				  AXP20X_ADC_EN1_VBUS_CURR |618				  AXP20X_ADC_EN1_VBUS_VOLT,619				  AXP20X_ADC_EN1_VBUS_CURR |620				  AXP20X_ADC_EN1_VBUS_VOLT);621}622 623static int axp717_configure_adc_registers(struct axp20x_usb_power *power)624{625	/* Enable vbus voltage measurement  */626	return regmap_update_bits(power->regmap, AXP717_ADC_CH_EN_CONTROL,627				  AXP717_ADC_EN_VBUS_VOLT,628				  AXP717_ADC_EN_VBUS_VOLT);629}630 631static enum power_supply_property axp20x_usb_power_properties[] = {632	POWER_SUPPLY_PROP_HEALTH,633	POWER_SUPPLY_PROP_PRESENT,634	POWER_SUPPLY_PROP_ONLINE,635	POWER_SUPPLY_PROP_VOLTAGE_MIN,636	POWER_SUPPLY_PROP_VOLTAGE_NOW,637	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,638	POWER_SUPPLY_PROP_CURRENT_NOW,639};640 641static enum power_supply_property axp22x_usb_power_properties[] = {642	POWER_SUPPLY_PROP_HEALTH,643	POWER_SUPPLY_PROP_PRESENT,644	POWER_SUPPLY_PROP_ONLINE,645	POWER_SUPPLY_PROP_VOLTAGE_MIN,646	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,647};648 649static enum power_supply_property axp717_usb_power_properties[] = {650	POWER_SUPPLY_PROP_HEALTH,651	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,652	POWER_SUPPLY_PROP_ONLINE,653	POWER_SUPPLY_PROP_PRESENT,654	POWER_SUPPLY_PROP_USB_TYPE,655	POWER_SUPPLY_PROP_VOLTAGE_MIN,656	POWER_SUPPLY_PROP_VOLTAGE_NOW,657};658 659static enum power_supply_property axp813_usb_power_properties[] = {660	POWER_SUPPLY_PROP_HEALTH,661	POWER_SUPPLY_PROP_PRESENT,662	POWER_SUPPLY_PROP_ONLINE,663	POWER_SUPPLY_PROP_VOLTAGE_MIN,664	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,665	POWER_SUPPLY_PROP_USB_TYPE,666};667 668static const struct power_supply_desc axp20x_usb_power_desc = {669	.name = "axp20x-usb",670	.type = POWER_SUPPLY_TYPE_USB,671	.properties = axp20x_usb_power_properties,672	.num_properties = ARRAY_SIZE(axp20x_usb_power_properties),673	.property_is_writeable = axp20x_usb_power_prop_writeable,674	.get_property = axp20x_usb_power_get_property,675	.set_property = axp20x_usb_power_set_property,676};677 678static const struct power_supply_desc axp22x_usb_power_desc = {679	.name = "axp20x-usb",680	.type = POWER_SUPPLY_TYPE_USB,681	.properties = axp22x_usb_power_properties,682	.num_properties = ARRAY_SIZE(axp22x_usb_power_properties),683	.property_is_writeable = axp20x_usb_power_prop_writeable,684	.get_property = axp20x_usb_power_get_property,685	.set_property = axp20x_usb_power_set_property,686};687 688static const struct power_supply_desc axp717_usb_power_desc = {689	.name = "axp20x-usb",690	.type = POWER_SUPPLY_TYPE_USB,691	.properties = axp717_usb_power_properties,692	.num_properties = ARRAY_SIZE(axp717_usb_power_properties),693	.property_is_writeable = axp717_usb_power_prop_writeable,694	.get_property = axp717_usb_power_get_property,695	.set_property = axp717_usb_power_set_property,696	.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |697		     BIT(POWER_SUPPLY_USB_TYPE_CDP) |698		     BIT(POWER_SUPPLY_USB_TYPE_DCP) |699		     BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),700};701 702static const struct power_supply_desc axp813_usb_power_desc = {703	.name = "axp20x-usb",704	.type = POWER_SUPPLY_TYPE_USB,705	.properties = axp813_usb_power_properties,706	.num_properties = ARRAY_SIZE(axp813_usb_power_properties),707	.property_is_writeable = axp20x_usb_power_prop_writeable,708	.get_property = axp20x_usb_power_get_property,709	.set_property = axp20x_usb_power_set_property,710	.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |711		     BIT(POWER_SUPPLY_USB_TYPE_CDP) |712		     BIT(POWER_SUPPLY_USB_TYPE_DCP) |713		     BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),714};715 716static const char * const axp20x_irq_names[] = {717	"VBUS_PLUGIN",718	"VBUS_REMOVAL",719	"VBUS_VALID",720	"VBUS_NOT_VALID",721};722 723static const char * const axp22x_irq_names[] = {724	"VBUS_PLUGIN",725	"VBUS_REMOVAL",726};727 728static const char * const axp717_irq_names[] = {729	"VBUS_PLUGIN",730	"VBUS_REMOVAL",731	"VBUS_OVER_V",732};733 734static int axp192_usb_curr_lim_table[] = {735	-1,736	-1,737	500000,738	100000,739};740 741static int axp20x_usb_curr_lim_table[] = {742	900000,743	500000,744	100000,745	-1,746};747 748static int axp221_usb_curr_lim_table[] = {749	900000,750	500000,751	-1,752	-1,753};754 755static int axp813_usb_curr_lim_table[] = {756	100000,757	500000,758	900000,759	1500000,760	2000000,761	2500000,762	3000000,763	3500000,764	4000000,765};766 767static const struct axp_data axp192_data = {768	.power_desc	= &axp20x_usb_power_desc,769	.irq_names	= axp20x_irq_names,770	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),771	.curr_lim_table = axp192_usb_curr_lim_table,772	.curr_lim_table_size = ARRAY_SIZE(axp192_usb_curr_lim_table),773	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),774	.vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),775	.vbus_mon_bit   = REG_FIELD(AXP20X_VBUS_MON, 3, 3),776	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,777	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,778	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,779};780 781static const struct axp_data axp202_data = {782	.power_desc	= &axp20x_usb_power_desc,783	.irq_names	= axp20x_irq_names,784	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),785	.curr_lim_table = axp20x_usb_curr_lim_table,786	.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),787	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),788	.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),789	.vbus_mon_bit   = REG_FIELD(AXP20X_VBUS_MON, 3, 3),790	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,791	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,792	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,793};794 795static const struct axp_data axp221_data = {796	.power_desc	= &axp22x_usb_power_desc,797	.irq_names	= axp22x_irq_names,798	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),799	.curr_lim_table = axp221_usb_curr_lim_table,800	.curr_lim_table_size = ARRAY_SIZE(axp221_usb_curr_lim_table),801	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),802	.vbus_needs_polling = true,803	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,804	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,805	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,806};807 808static const struct axp_data axp223_data = {809	.power_desc	= &axp22x_usb_power_desc,810	.irq_names	= axp22x_irq_names,811	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),812	.curr_lim_table = axp20x_usb_curr_lim_table,813	.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),814	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),815	.vbus_needs_polling = true,816	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,817	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,818	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,819};820 821static const struct axp_data axp717_data = {822	.power_desc     = &axp717_usb_power_desc,823	.irq_names      = axp717_irq_names,824	.num_irq_names  = ARRAY_SIZE(axp717_irq_names),825	.curr_lim_fld   = REG_FIELD(AXP717_INPUT_CUR_LIMIT_CTRL, 0, 5),826	.usb_bc_en_bit  = REG_FIELD(AXP717_MODULE_EN_CONTROL_1, 4, 4),827	.usb_bc_det_fld = REG_FIELD(AXP717_BC_DETECT, 5, 7),828	.vbus_mon_bit   = REG_FIELD(AXP717_ADC_CH_EN_CONTROL, 2, 2),829	.vbus_needs_polling = false,830	.axp20x_read_vbus = &axp717_usb_power_poll_vbus,831	.axp20x_cfg_iio_chan = axp717_configure_iio_channels,832	.axp20x_cfg_adc_reg = axp717_configure_adc_registers,833};834 835static const struct axp_data axp813_data = {836	.power_desc	= &axp813_usb_power_desc,837	.irq_names	= axp22x_irq_names,838	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),839	.curr_lim_table = axp813_usb_curr_lim_table,840	.curr_lim_table_size = ARRAY_SIZE(axp813_usb_curr_lim_table),841	.curr_lim_fld	= REG_FIELD(AXP22X_CHRG_CTRL3, 4, 7),842	.usb_bc_en_bit	= REG_FIELD(AXP288_BC_GLOBAL, 0, 0),843	.usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7),844	.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),845	.vbus_needs_polling = true,846	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,847	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,848	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,849};850 851#ifdef CONFIG_PM_SLEEP852static int axp20x_usb_power_suspend(struct device *dev)853{854	struct axp20x_usb_power *power = dev_get_drvdata(dev);855	int i = 0;856 857	/*858	 * Allow wake via VBUS_PLUGIN only.859	 *860	 * As nested threaded IRQs are not automatically disabled during861	 * suspend, we must explicitly disable the remainder of the IRQs.862	 */863	if (device_may_wakeup(&power->supply->dev))864		enable_irq_wake(power->irqs[i++]);865	while (i < power->num_irqs)866		disable_irq(power->irqs[i++]);867 868	return 0;869}870 871static int axp20x_usb_power_resume(struct device *dev)872{873	struct axp20x_usb_power *power = dev_get_drvdata(dev);874	int i = 0;875 876	if (device_may_wakeup(&power->supply->dev))877		disable_irq_wake(power->irqs[i++]);878	while (i < power->num_irqs)879		enable_irq(power->irqs[i++]);880 881	mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);882 883	return 0;884}885#endif886 887static SIMPLE_DEV_PM_OPS(axp20x_usb_power_pm_ops, axp20x_usb_power_suspend,888						  axp20x_usb_power_resume);889 890static int axp20x_regmap_field_alloc_optional(struct device *dev,891					      struct regmap *regmap,892					      struct reg_field fdesc,893					      struct regmap_field **fieldp)894{895	struct regmap_field *field;896 897	if (fdesc.reg == 0) {898		*fieldp = NULL;899		return 0;900	}901 902	field = devm_regmap_field_alloc(dev, regmap, fdesc);903	if (IS_ERR(field))904		return PTR_ERR(field);905 906	*fieldp = field;907	return 0;908}909 910/* Optionally allow users to specify a maximum charging current. */911static void axp20x_usb_power_parse_dt(struct device *dev,912				      struct axp20x_usb_power *power)913{914	int ret;915 916	ret = device_property_read_u32(dev, "input-current-limit-microamp",917				       &power->max_input_cur);918	if (ret)919		dev_dbg(dev, "%s() no input-current-limit specified\n", __func__);920}921 922static int axp20x_usb_power_probe(struct platform_device *pdev)923{924	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);925	struct power_supply_config psy_cfg = {};926	struct axp20x_usb_power *power;927	const struct axp_data *axp_data;928	int i, irq, ret;929 930	if (!of_device_is_available(pdev->dev.of_node))931		return -ENODEV;932 933	if (!axp20x) {934		dev_err(&pdev->dev, "Parent drvdata not set\n");935		return -EINVAL;936	}937 938	axp_data = of_device_get_match_data(&pdev->dev);939 940	power = devm_kzalloc(&pdev->dev,941			     struct_size(power, irqs, axp_data->num_irq_names),942			     GFP_KERNEL);943	if (!power)944		return -ENOMEM;945 946	platform_set_drvdata(pdev, power);947 948	power->dev = &pdev->dev;949	power->axp_data = axp_data;950	power->regmap = axp20x->regmap;951	power->num_irqs = axp_data->num_irq_names;952 953	power->curr_lim_fld = devm_regmap_field_alloc(&pdev->dev, power->regmap,954						      axp_data->curr_lim_fld);955	if (IS_ERR(power->curr_lim_fld))956		return PTR_ERR(power->curr_lim_fld);957 958	axp20x_usb_power_parse_dt(&pdev->dev, power);959 960	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,961						 axp_data->vbus_valid_bit,962						 &power->vbus_valid_bit);963	if (ret)964		return ret;965 966	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,967						 axp_data->vbus_mon_bit,968						 &power->vbus_mon_bit);969	if (ret)970		return ret;971 972	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,973						 axp_data->usb_bc_en_bit,974						 &power->usb_bc_en_bit);975	if (ret)976		return ret;977 978	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,979						 axp_data->usb_bc_det_fld,980						 &power->usb_bc_det_fld);981	if (ret)982		return ret;983 984	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,985						 axp_data->vbus_disable_bit,986						 &power->vbus_disable_bit);987	if (ret)988		return ret;989 990	ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,991					   axp_data->axp20x_read_vbus);992	if (ret)993		return ret;994 995	if (power->vbus_mon_bit) {996		/* Enable vbus valid checking */997		ret = regmap_field_write(power->vbus_mon_bit, 1);998		if (ret)999			return ret;1000 1001		if (IS_ENABLED(CONFIG_AXP20X_ADC))1002			ret = axp_data->axp20x_cfg_iio_chan(pdev, power);1003		else1004			ret = axp_data->axp20x_cfg_adc_reg(power);1005 1006		if (ret)1007			return ret;1008	}1009 1010	if (power->usb_bc_en_bit) {1011		/* Enable USB Battery Charging specification detection */1012		ret = regmap_field_write(power->usb_bc_en_bit, 1);1013		if (ret)1014			return ret;1015	}1016 1017	psy_cfg.of_node = pdev->dev.of_node;1018	psy_cfg.drv_data = power;1019 1020	power->supply = devm_power_supply_register(&pdev->dev,1021						   axp_data->power_desc,1022						   &psy_cfg);1023	if (IS_ERR(power->supply))1024		return PTR_ERR(power->supply);1025 1026	/* Request irqs after registering, as irqs may trigger immediately */1027	for (i = 0; i < axp_data->num_irq_names; i++) {1028		irq = platform_get_irq_byname(pdev, axp_data->irq_names[i]);1029		if (irq < 0)1030			return irq;1031 1032		power->irqs[i] = regmap_irq_get_virq(axp20x->regmap_irqc, irq);1033		ret = devm_request_any_context_irq(&pdev->dev, power->irqs[i],1034						   axp20x_usb_power_irq, 0,1035						   DRVNAME, power);1036		if (ret < 0) {1037			dev_err(&pdev->dev, "Error requesting %s IRQ: %d\n",1038				axp_data->irq_names[i], ret);1039			return ret;1040		}1041	}1042 1043	if (axp20x_usb_vbus_needs_polling(power))1044		queue_delayed_work(system_power_efficient_wq, &power->vbus_detect, 0);1045 1046	return 0;1047}1048 1049static const struct of_device_id axp20x_usb_power_match[] = {1050	{1051		.compatible = "x-powers,axp192-usb-power-supply",1052		.data = &axp192_data,1053	}, {1054		.compatible = "x-powers,axp202-usb-power-supply",1055		.data = &axp202_data,1056	}, {1057		.compatible = "x-powers,axp221-usb-power-supply",1058		.data = &axp221_data,1059	}, {1060		.compatible = "x-powers,axp223-usb-power-supply",1061		.data = &axp223_data,1062	}, {1063		.compatible = "x-powers,axp717-usb-power-supply",1064		.data = &axp717_data,1065	}, {1066		.compatible = "x-powers,axp813-usb-power-supply",1067		.data = &axp813_data,1068	}, { /* sentinel */ }1069};1070MODULE_DEVICE_TABLE(of, axp20x_usb_power_match);1071 1072static struct platform_driver axp20x_usb_power_driver = {1073	.probe = axp20x_usb_power_probe,1074	.driver = {1075		.name		= DRVNAME,1076		.of_match_table	= axp20x_usb_power_match,1077		.pm		= &axp20x_usb_power_pm_ops,1078	},1079};1080 1081module_platform_driver(axp20x_usb_power_driver);1082 1083MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");1084MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver");1085MODULE_LICENSE("GPL");1086