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

axp288_charger.c (27579B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * axp288_charger.c - X-power AXP288 PMIC Charger driver
      4 *
      5 * Copyright (C) 2016-2017 Hans de Goede <hdegoede@redhat.com>
      6 * Copyright (C) 2014 Intel Corporation
      7 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
      8 */
      9
     10#include <linux/acpi.h>
     11#include <linux/bitops.h>
     12#include <linux/module.h>
     13#include <linux/device.h>
     14#include <linux/regmap.h>
     15#include <linux/workqueue.h>
     16#include <linux/delay.h>
     17#include <linux/platform_device.h>
     18#include <linux/usb/otg.h>
     19#include <linux/notifier.h>
     20#include <linux/power_supply.h>
     21#include <linux/property.h>
     22#include <linux/mfd/axp20x.h>
     23#include <linux/extcon.h>
     24#include <linux/dmi.h>
     25#include <asm/iosf_mbi.h>
     26
     27#define PS_STAT_VBUS_TRIGGER		BIT(0)
     28#define PS_STAT_BAT_CHRG_DIR		BIT(2)
     29#define PS_STAT_VBAT_ABOVE_VHOLD	BIT(3)
     30#define PS_STAT_VBUS_VALID		BIT(4)
     31#define PS_STAT_VBUS_PRESENT		BIT(5)
     32
     33#define CHRG_STAT_BAT_SAFE_MODE		BIT(3)
     34#define CHRG_STAT_BAT_VALID		BIT(4)
     35#define CHRG_STAT_BAT_PRESENT		BIT(5)
     36#define CHRG_STAT_CHARGING		BIT(6)
     37#define CHRG_STAT_PMIC_OTP		BIT(7)
     38
     39#define VBUS_ISPOUT_CUR_LIM_MASK	0x03
     40#define VBUS_ISPOUT_CUR_LIM_BIT_POS	0
     41#define VBUS_ISPOUT_CUR_LIM_900MA	0x0	/* 900mA */
     42#define VBUS_ISPOUT_CUR_LIM_1500MA	0x1	/* 1500mA */
     43#define VBUS_ISPOUT_CUR_LIM_2000MA	0x2	/* 2000mA */
     44#define VBUS_ISPOUT_CUR_NO_LIM		0x3	/* 2500mA */
     45#define VBUS_ISPOUT_VHOLD_SET_MASK	0x38
     46#define VBUS_ISPOUT_VHOLD_SET_BIT_POS	0x3
     47#define VBUS_ISPOUT_VHOLD_SET_OFFSET	4000	/* 4000mV */
     48#define VBUS_ISPOUT_VHOLD_SET_LSB_RES	100	/* 100mV */
     49#define VBUS_ISPOUT_VHOLD_SET_4400MV	0x4	/* 4400mV */
     50#define VBUS_ISPOUT_VBUS_PATH_DIS	BIT(7)
     51
     52#define CHRG_CCCV_CC_MASK		0xf		/* 4 bits */
     53#define CHRG_CCCV_CC_BIT_POS		0
     54#define CHRG_CCCV_CC_OFFSET		200		/* 200mA */
     55#define CHRG_CCCV_CC_LSB_RES		200		/* 200mA */
     56#define CHRG_CCCV_ITERM_20P		BIT(4)		/* 20% of CC */
     57#define CHRG_CCCV_CV_MASK		0x60		/* 2 bits */
     58#define CHRG_CCCV_CV_BIT_POS		5
     59#define CHRG_CCCV_CV_4100MV		0x0		/* 4.10V */
     60#define CHRG_CCCV_CV_4150MV		0x1		/* 4.15V */
     61#define CHRG_CCCV_CV_4200MV		0x2		/* 4.20V */
     62#define CHRG_CCCV_CV_4350MV		0x3		/* 4.35V */
     63#define CHRG_CCCV_CHG_EN		BIT(7)
     64
     65#define CNTL2_CC_TIMEOUT_MASK		0x3	/* 2 bits */
     66#define CNTL2_CC_TIMEOUT_OFFSET		6	/* 6 Hrs */
     67#define CNTL2_CC_TIMEOUT_LSB_RES	2	/* 2 Hrs */
     68#define CNTL2_CC_TIMEOUT_12HRS		0x3	/* 12 Hrs */
     69#define CNTL2_CHGLED_TYPEB		BIT(4)
     70#define CNTL2_CHG_OUT_TURNON		BIT(5)
     71#define CNTL2_PC_TIMEOUT_MASK		0xC0
     72#define CNTL2_PC_TIMEOUT_OFFSET		40	/* 40 mins */
     73#define CNTL2_PC_TIMEOUT_LSB_RES	10	/* 10 mins */
     74#define CNTL2_PC_TIMEOUT_70MINS		0x3
     75
     76#define CHRG_ILIM_TEMP_LOOP_EN		BIT(3)
     77#define CHRG_VBUS_ILIM_MASK		0xf0
     78#define CHRG_VBUS_ILIM_BIT_POS		4
     79#define CHRG_VBUS_ILIM_100MA		0x0	/* 100mA */
     80#define CHRG_VBUS_ILIM_500MA		0x1	/* 500mA */
     81#define CHRG_VBUS_ILIM_900MA		0x2	/* 900mA */
     82#define CHRG_VBUS_ILIM_1500MA		0x3	/* 1500mA */
     83#define CHRG_VBUS_ILIM_2000MA		0x4	/* 2000mA */
     84#define CHRG_VBUS_ILIM_2500MA		0x5	/* 2500mA */
     85#define CHRG_VBUS_ILIM_3000MA		0x6	/* 3000mA */
     86#define CHRG_VBUS_ILIM_3500MA		0x7	/* 3500mA */
     87#define CHRG_VBUS_ILIM_4000MA		0x8	/* 4000mA */
     88
     89#define CHRG_VLTFC_0C			0xA5	/* 0 DegC */
     90#define CHRG_VHTFC_45C			0x1F	/* 45 DegC */
     91
     92#define FG_CNTL_OCV_ADJ_EN		BIT(3)
     93
     94#define CV_4100MV			4100	/* 4100mV */
     95#define CV_4150MV			4150	/* 4150mV */
     96#define CV_4200MV			4200	/* 4200mV */
     97#define CV_4350MV			4350	/* 4350mV */
     98
     99#define AXP288_REG_UPDATE_INTERVAL	(60 * HZ)
    100
    101#define AXP288_EXTCON_DEV_NAME		"axp288_extcon"
    102#define USB_HOST_EXTCON_HID		"INT3496"
    103#define USB_HOST_EXTCON_NAME		"INT3496:00"
    104
    105enum {
    106	VBUS_OV_IRQ = 0,
    107	CHARGE_DONE_IRQ,
    108	CHARGE_CHARGING_IRQ,
    109	BAT_SAFE_QUIT_IRQ,
    110	BAT_SAFE_ENTER_IRQ,
    111	QCBTU_IRQ,
    112	CBTU_IRQ,
    113	QCBTO_IRQ,
    114	CBTO_IRQ,
    115	CHRG_INTR_END,
    116};
    117
    118struct axp288_chrg_info {
    119	struct platform_device *pdev;
    120	struct regmap *regmap;
    121	struct regmap_irq_chip_data *regmap_irqc;
    122	int irq[CHRG_INTR_END];
    123	struct power_supply *psy_usb;
    124	struct mutex lock;
    125
    126	/* OTG/Host mode */
    127	struct {
    128		struct work_struct work;
    129		struct extcon_dev *cable;
    130		struct notifier_block id_nb;
    131		bool id_short;
    132	} otg;
    133
    134	/* SDP/CDP/DCP USB charging cable notifications */
    135	struct {
    136		struct extcon_dev *edev;
    137		struct notifier_block nb;
    138		struct work_struct work;
    139	} cable;
    140
    141	int cc;
    142	int cv;
    143	int max_cc;
    144	int max_cv;
    145
    146	unsigned long last_updated;
    147	unsigned int input_status;
    148	unsigned int op_mode;
    149	unsigned int backend_control;
    150	bool valid;
    151};
    152
    153static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc)
    154{
    155	u8 reg_val;
    156	int ret;
    157
    158	if (cc < CHRG_CCCV_CC_OFFSET)
    159		cc = CHRG_CCCV_CC_OFFSET;
    160	else if (cc > info->max_cc)
    161		cc = info->max_cc;
    162
    163	reg_val = (cc - CHRG_CCCV_CC_OFFSET) / CHRG_CCCV_CC_LSB_RES;
    164	cc = (reg_val * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
    165	reg_val = reg_val << CHRG_CCCV_CC_BIT_POS;
    166
    167	ret = regmap_update_bits(info->regmap,
    168				AXP20X_CHRG_CTRL1,
    169				CHRG_CCCV_CC_MASK, reg_val);
    170	if (ret >= 0)
    171		info->cc = cc;
    172
    173	return ret;
    174}
    175
    176static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv)
    177{
    178	u8 reg_val;
    179	int ret;
    180
    181	if (cv <= CV_4100MV) {
    182		reg_val = CHRG_CCCV_CV_4100MV;
    183		cv = CV_4100MV;
    184	} else if (cv <= CV_4150MV) {
    185		reg_val = CHRG_CCCV_CV_4150MV;
    186		cv = CV_4150MV;
    187	} else if (cv <= CV_4200MV) {
    188		reg_val = CHRG_CCCV_CV_4200MV;
    189		cv = CV_4200MV;
    190	} else {
    191		reg_val = CHRG_CCCV_CV_4350MV;
    192		cv = CV_4350MV;
    193	}
    194
    195	reg_val = reg_val << CHRG_CCCV_CV_BIT_POS;
    196
    197	ret = regmap_update_bits(info->regmap,
    198				AXP20X_CHRG_CTRL1,
    199				CHRG_CCCV_CV_MASK, reg_val);
    200
    201	if (ret >= 0)
    202		info->cv = cv;
    203
    204	return ret;
    205}
    206
    207static int axp288_charger_get_vbus_inlmt(struct axp288_chrg_info *info)
    208{
    209	unsigned int val;
    210
    211	val = info->backend_control;
    212
    213	val >>= CHRG_VBUS_ILIM_BIT_POS;
    214	switch (val) {
    215	case CHRG_VBUS_ILIM_100MA:
    216		return 100000;
    217	case CHRG_VBUS_ILIM_500MA:
    218		return 500000;
    219	case CHRG_VBUS_ILIM_900MA:
    220		return 900000;
    221	case CHRG_VBUS_ILIM_1500MA:
    222		return 1500000;
    223	case CHRG_VBUS_ILIM_2000MA:
    224		return 2000000;
    225	case CHRG_VBUS_ILIM_2500MA:
    226		return 2500000;
    227	case CHRG_VBUS_ILIM_3000MA:
    228		return 3000000;
    229	case CHRG_VBUS_ILIM_3500MA:
    230		return 3500000;
    231	default:
    232		/* All b1xxx values map to 4000 mA */
    233		return 4000000;
    234	}
    235}
    236
    237static inline int axp288_charger_set_vbus_inlmt(struct axp288_chrg_info *info,
    238					   int inlmt)
    239{
    240	int ret;
    241	u8 reg_val;
    242
    243	if (inlmt >= 4000000)
    244		reg_val = CHRG_VBUS_ILIM_4000MA << CHRG_VBUS_ILIM_BIT_POS;
    245	else if (inlmt >= 3500000)
    246		reg_val = CHRG_VBUS_ILIM_3500MA << CHRG_VBUS_ILIM_BIT_POS;
    247	else if (inlmt >= 3000000)
    248		reg_val = CHRG_VBUS_ILIM_3000MA << CHRG_VBUS_ILIM_BIT_POS;
    249	else if (inlmt >= 2500000)
    250		reg_val = CHRG_VBUS_ILIM_2500MA << CHRG_VBUS_ILIM_BIT_POS;
    251	else if (inlmt >= 2000000)
    252		reg_val = CHRG_VBUS_ILIM_2000MA << CHRG_VBUS_ILIM_BIT_POS;
    253	else if (inlmt >= 1500000)
    254		reg_val = CHRG_VBUS_ILIM_1500MA << CHRG_VBUS_ILIM_BIT_POS;
    255	else if (inlmt >= 900000)
    256		reg_val = CHRG_VBUS_ILIM_900MA << CHRG_VBUS_ILIM_BIT_POS;
    257	else if (inlmt >= 500000)
    258		reg_val = CHRG_VBUS_ILIM_500MA << CHRG_VBUS_ILIM_BIT_POS;
    259	else
    260		reg_val = CHRG_VBUS_ILIM_100MA << CHRG_VBUS_ILIM_BIT_POS;
    261
    262	ret = regmap_update_bits(info->regmap, AXP20X_CHRG_BAK_CTRL,
    263				 CHRG_VBUS_ILIM_MASK, reg_val);
    264	if (ret < 0)
    265		dev_err(&info->pdev->dev, "charger BAK control %d\n", ret);
    266
    267	return ret;
    268}
    269
    270static int axp288_charger_vbus_path_select(struct axp288_chrg_info *info,
    271								bool enable)
    272{
    273	int ret;
    274
    275	if (enable)
    276		ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
    277					VBUS_ISPOUT_VBUS_PATH_DIS, 0);
    278	else
    279		ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
    280			VBUS_ISPOUT_VBUS_PATH_DIS, VBUS_ISPOUT_VBUS_PATH_DIS);
    281
    282	if (ret < 0)
    283		dev_err(&info->pdev->dev, "axp288 vbus path select %d\n", ret);
    284
    285	return ret;
    286}
    287
    288static int axp288_charger_enable_charger(struct axp288_chrg_info *info,
    289								bool enable)
    290{
    291	int ret;
    292
    293	if (enable)
    294		ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
    295				CHRG_CCCV_CHG_EN, CHRG_CCCV_CHG_EN);
    296	else
    297		ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
    298				CHRG_CCCV_CHG_EN, 0);
    299	if (ret < 0)
    300		dev_err(&info->pdev->dev, "axp288 enable charger %d\n", ret);
    301
    302	return ret;
    303}
    304
    305static int axp288_get_charger_health(struct axp288_chrg_info *info)
    306{
    307	if (!(info->input_status & PS_STAT_VBUS_PRESENT))
    308		return POWER_SUPPLY_HEALTH_UNKNOWN;
    309
    310	if (!(info->input_status & PS_STAT_VBUS_VALID))
    311		return POWER_SUPPLY_HEALTH_DEAD;
    312	else if (info->op_mode & CHRG_STAT_PMIC_OTP)
    313		return POWER_SUPPLY_HEALTH_OVERHEAT;
    314	else if (info->op_mode & CHRG_STAT_BAT_SAFE_MODE)
    315		return POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
    316	else
    317		return POWER_SUPPLY_HEALTH_GOOD;
    318}
    319
    320static int axp288_charger_usb_set_property(struct power_supply *psy,
    321				    enum power_supply_property psp,
    322				    const union power_supply_propval *val)
    323{
    324	struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
    325	int ret = 0;
    326	int scaled_val;
    327
    328	mutex_lock(&info->lock);
    329	switch (psp) {
    330	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
    331		scaled_val = min(val->intval, info->max_cc);
    332		scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
    333		ret = axp288_charger_set_cc(info, scaled_val);
    334		if (ret < 0) {
    335			dev_warn(&info->pdev->dev, "set charge current failed\n");
    336			goto out;
    337		}
    338		break;
    339	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
    340		scaled_val = min(val->intval, info->max_cv);
    341		scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
    342		ret = axp288_charger_set_cv(info, scaled_val);
    343		if (ret < 0) {
    344			dev_warn(&info->pdev->dev, "set charge voltage failed\n");
    345			goto out;
    346		}
    347		break;
    348	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
    349		ret = axp288_charger_set_vbus_inlmt(info, val->intval);
    350		if (ret < 0) {
    351			dev_warn(&info->pdev->dev, "set input current limit failed\n");
    352			goto out;
    353		}
    354		info->valid = false;
    355		break;
    356	default:
    357		ret = -EINVAL;
    358	}
    359
    360out:
    361	mutex_unlock(&info->lock);
    362	return ret;
    363}
    364
    365static int axp288_charger_reg_readb(struct axp288_chrg_info *info, int reg, unsigned int *ret_val)
    366{
    367	int ret;
    368
    369	ret = regmap_read(info->regmap, reg, ret_val);
    370	if (ret < 0) {
    371		dev_err(&info->pdev->dev, "Error %d on reading value from register 0x%04x\n",
    372			ret,
    373			reg);
    374		return ret;
    375	}
    376	return 0;
    377}
    378
    379static int axp288_charger_usb_update_property(struct axp288_chrg_info *info)
    380{
    381	int ret = 0;
    382
    383	if (info->valid && time_before(jiffies, info->last_updated + AXP288_REG_UPDATE_INTERVAL))
    384		return 0;
    385
    386	dev_dbg(&info->pdev->dev, "Charger updating register values...\n");
    387
    388	ret = iosf_mbi_block_punit_i2c_access();
    389	if (ret < 0)
    390		return ret;
    391
    392	ret = axp288_charger_reg_readb(info, AXP20X_PWR_INPUT_STATUS, &info->input_status);
    393	if (ret < 0)
    394		goto out;
    395
    396	ret = axp288_charger_reg_readb(info, AXP20X_PWR_OP_MODE, &info->op_mode);
    397	if (ret < 0)
    398		goto out;
    399
    400	ret = axp288_charger_reg_readb(info, AXP20X_CHRG_BAK_CTRL, &info->backend_control);
    401	if (ret < 0)
    402		goto out;
    403
    404	info->last_updated = jiffies;
    405	info->valid = true;
    406out:
    407	iosf_mbi_unblock_punit_i2c_access();
    408	return ret;
    409}
    410
    411static int axp288_charger_usb_get_property(struct power_supply *psy,
    412				    enum power_supply_property psp,
    413				    union power_supply_propval *val)
    414{
    415	struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
    416	int ret;
    417
    418	mutex_lock(&info->lock);
    419	ret = axp288_charger_usb_update_property(info);
    420	if (ret < 0)
    421		goto out;
    422
    423	switch (psp) {
    424	case POWER_SUPPLY_PROP_PRESENT:
    425		/* Check for OTG case first */
    426		if (info->otg.id_short) {
    427			val->intval = 0;
    428			break;
    429		}
    430		val->intval = (info->input_status & PS_STAT_VBUS_PRESENT) ? 1 : 0;
    431		break;
    432	case POWER_SUPPLY_PROP_ONLINE:
    433		/* Check for OTG case first */
    434		if (info->otg.id_short) {
    435			val->intval = 0;
    436			break;
    437		}
    438		val->intval = (info->input_status & PS_STAT_VBUS_VALID) ? 1 : 0;
    439		break;
    440	case POWER_SUPPLY_PROP_HEALTH:
    441		val->intval = axp288_get_charger_health(info);
    442		break;
    443	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
    444		val->intval = info->cc * 1000;
    445		break;
    446	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
    447		val->intval = info->max_cc * 1000;
    448		break;
    449	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
    450		val->intval = info->cv * 1000;
    451		break;
    452	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
    453		val->intval = info->max_cv * 1000;
    454		break;
    455	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
    456		val->intval = axp288_charger_get_vbus_inlmt(info);
    457		break;
    458	default:
    459		ret = -EINVAL;
    460	}
    461
    462out:
    463	mutex_unlock(&info->lock);
    464	return ret;
    465}
    466
    467static int axp288_charger_property_is_writeable(struct power_supply *psy,
    468		enum power_supply_property psp)
    469{
    470	int ret;
    471
    472	switch (psp) {
    473	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
    474	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
    475	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
    476		ret = 1;
    477		break;
    478	default:
    479		ret = 0;
    480	}
    481
    482	return ret;
    483}
    484
    485static enum power_supply_property axp288_usb_props[] = {
    486	POWER_SUPPLY_PROP_PRESENT,
    487	POWER_SUPPLY_PROP_ONLINE,
    488	POWER_SUPPLY_PROP_TYPE,
    489	POWER_SUPPLY_PROP_HEALTH,
    490	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
    491	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
    492	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
    493	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
    494	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
    495};
    496
    497static const struct power_supply_desc axp288_charger_desc = {
    498	.name			= "axp288_charger",
    499	.type			= POWER_SUPPLY_TYPE_USB,
    500	.properties		= axp288_usb_props,
    501	.num_properties		= ARRAY_SIZE(axp288_usb_props),
    502	.get_property		= axp288_charger_usb_get_property,
    503	.set_property		= axp288_charger_usb_set_property,
    504	.property_is_writeable	= axp288_charger_property_is_writeable,
    505};
    506
    507static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
    508{
    509	struct axp288_chrg_info *info = dev;
    510	int i;
    511
    512	for (i = 0; i < CHRG_INTR_END; i++) {
    513		if (info->irq[i] == irq)
    514			break;
    515	}
    516
    517	if (i >= CHRG_INTR_END) {
    518		dev_warn(&info->pdev->dev, "spurious interrupt!!\n");
    519		return IRQ_NONE;
    520	}
    521
    522	switch (i) {
    523	case VBUS_OV_IRQ:
    524		dev_dbg(&info->pdev->dev, "VBUS Over Voltage INTR\n");
    525		break;
    526	case CHARGE_DONE_IRQ:
    527		dev_dbg(&info->pdev->dev, "Charging Done INTR\n");
    528		break;
    529	case CHARGE_CHARGING_IRQ:
    530		dev_dbg(&info->pdev->dev, "Start Charging IRQ\n");
    531		break;
    532	case BAT_SAFE_QUIT_IRQ:
    533		dev_dbg(&info->pdev->dev,
    534			"Quit Safe Mode(restart timer) Charging IRQ\n");
    535		break;
    536	case BAT_SAFE_ENTER_IRQ:
    537		dev_dbg(&info->pdev->dev,
    538			"Enter Safe Mode(timer expire) Charging IRQ\n");
    539		break;
    540	case QCBTU_IRQ:
    541		dev_dbg(&info->pdev->dev,
    542			"Quit Battery Under Temperature(CHRG) INTR\n");
    543		break;
    544	case CBTU_IRQ:
    545		dev_dbg(&info->pdev->dev,
    546			"Hit Battery Under Temperature(CHRG) INTR\n");
    547		break;
    548	case QCBTO_IRQ:
    549		dev_dbg(&info->pdev->dev,
    550			"Quit Battery Over Temperature(CHRG) INTR\n");
    551		break;
    552	case CBTO_IRQ:
    553		dev_dbg(&info->pdev->dev,
    554			"Hit Battery Over Temperature(CHRG) INTR\n");
    555		break;
    556	default:
    557		dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n");
    558		goto out;
    559	}
    560	mutex_lock(&info->lock);
    561	info->valid = false;
    562	mutex_unlock(&info->lock);
    563	power_supply_changed(info->psy_usb);
    564out:
    565	return IRQ_HANDLED;
    566}
    567
    568/*
    569 * The HP Pavilion x2 10 series comes in a number of variants:
    570 * Bay Trail SoC    + AXP288 PMIC, Micro-USB, DMI_BOARD_NAME: "8021"
    571 * Bay Trail SoC    + AXP288 PMIC, Type-C,    DMI_BOARD_NAME: "815D"
    572 * Cherry Trail SoC + AXP288 PMIC, Type-C,    DMI_BOARD_NAME: "813E"
    573 * Cherry Trail SoC + TI PMIC,     Type-C,    DMI_BOARD_NAME: "827C" or "82F4"
    574 *
    575 * The variants with the AXP288 + Type-C connector are all kinds of special:
    576 *
    577 * 1. They use a Type-C connector which the AXP288 does not support, so when
    578 * using a Type-C charger it is not recognized. Unlike most AXP288 devices,
    579 * this model actually has mostly working ACPI AC / Battery code, the ACPI code
    580 * "solves" this by simply setting the input_current_limit to 3A.
    581 * There are still some issues with the ACPI code, so we use this native driver,
    582 * and to solve the charging not working (500mA is not enough) issue we hardcode
    583 * the 3A input_current_limit like the ACPI code does.
    584 *
    585 * 2. If no charger is connected the machine boots with the vbus-path disabled.
    586 * Normally this is done when a 5V boost converter is active to avoid the PMIC
    587 * trying to charge from the 5V boost converter's output. This is done when
    588 * an OTG host cable is inserted and the ID pin on the micro-B receptacle is
    589 * pulled low and the ID pin has an ACPI event handler associated with it
    590 * which re-enables the vbus-path when the ID pin is pulled high when the
    591 * OTG host cable is removed. The Type-C connector has no ID pin, there is
    592 * no ID pin handler and there appears to be no 5V boost converter, so we
    593 * end up not charging because the vbus-path is disabled, until we unplug
    594 * the charger which automatically clears the vbus-path disable bit and then
    595 * on the second plug-in of the adapter we start charging. To solve the not
    596 * charging on first charger plugin we unconditionally enable the vbus-path at
    597 * probe on this model, which is safe since there is no 5V boost converter.
    598 */
    599static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = {
    600	{
    601		.matches = {
    602			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
    603			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
    604			DMI_EXACT_MATCH(DMI_BOARD_NAME, "815D"),
    605		},
    606	},
    607	{
    608		.matches = {
    609			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "HP"),
    610			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
    611			DMI_EXACT_MATCH(DMI_BOARD_NAME, "813E"),
    612		},
    613	},
    614	{} /* Terminating entry */
    615};
    616
    617static void axp288_charger_extcon_evt_worker(struct work_struct *work)
    618{
    619	struct axp288_chrg_info *info =
    620	    container_of(work, struct axp288_chrg_info, cable.work);
    621	int ret, current_limit;
    622	struct extcon_dev *edev = info->cable.edev;
    623	unsigned int val;
    624
    625	ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
    626	if (ret < 0) {
    627		dev_err(&info->pdev->dev, "Error reading status (%d)\n", ret);
    628		return;
    629	}
    630
    631	/* Offline? Disable charging and bail */
    632	if (!(val & PS_STAT_VBUS_VALID)) {
    633		dev_dbg(&info->pdev->dev, "USB charger disconnected\n");
    634		axp288_charger_enable_charger(info, false);
    635		mutex_lock(&info->lock);
    636		info->valid = false;
    637		mutex_unlock(&info->lock);
    638		power_supply_changed(info->psy_usb);
    639		return;
    640	}
    641
    642	/* Determine cable/charger type */
    643	if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
    644		/* See comment above axp288_hp_x2_dmi_ids declaration */
    645		dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n");
    646		current_limit = 3000000;
    647	} else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
    648		dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
    649		current_limit = 500000;
    650	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
    651		dev_dbg(&info->pdev->dev, "USB CDP charger is connected\n");
    652		current_limit = 1500000;
    653	} else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
    654		dev_dbg(&info->pdev->dev, "USB DCP charger is connected\n");
    655		current_limit = 2000000;
    656	} else {
    657		/* Charger type detection still in progress, bail. */
    658		return;
    659	}
    660
    661	/* Set vbus current limit first, then enable charger */
    662	ret = axp288_charger_set_vbus_inlmt(info, current_limit);
    663	if (ret == 0)
    664		axp288_charger_enable_charger(info, true);
    665	else
    666		dev_err(&info->pdev->dev,
    667			"error setting current limit (%d)\n", ret);
    668
    669	mutex_lock(&info->lock);
    670	info->valid = false;
    671	mutex_unlock(&info->lock);
    672	power_supply_changed(info->psy_usb);
    673}
    674
    675static int axp288_charger_handle_cable_evt(struct notifier_block *nb,
    676					   unsigned long event, void *param)
    677{
    678	struct axp288_chrg_info *info =
    679		container_of(nb, struct axp288_chrg_info, cable.nb);
    680	schedule_work(&info->cable.work);
    681	return NOTIFY_OK;
    682}
    683
    684static void axp288_charger_otg_evt_worker(struct work_struct *work)
    685{
    686	struct axp288_chrg_info *info =
    687	    container_of(work, struct axp288_chrg_info, otg.work);
    688	struct extcon_dev *edev = info->otg.cable;
    689	int ret, usb_host = extcon_get_state(edev, EXTCON_USB_HOST);
    690
    691	dev_dbg(&info->pdev->dev, "external connector USB-Host is %s\n",
    692				usb_host ? "attached" : "detached");
    693
    694	/*
    695	 * Set usb_id_short flag to avoid running charger detection logic
    696	 * in case usb host.
    697	 */
    698	info->otg.id_short = usb_host;
    699
    700	/* Disable VBUS path before enabling the 5V boost */
    701	ret = axp288_charger_vbus_path_select(info, !info->otg.id_short);
    702	if (ret < 0)
    703		dev_warn(&info->pdev->dev, "vbus path disable failed\n");
    704}
    705
    706static int axp288_charger_handle_otg_evt(struct notifier_block *nb,
    707				   unsigned long event, void *param)
    708{
    709	struct axp288_chrg_info *info =
    710	    container_of(nb, struct axp288_chrg_info, otg.id_nb);
    711
    712	schedule_work(&info->otg.work);
    713
    714	return NOTIFY_OK;
    715}
    716
    717static int charger_init_hw_regs(struct axp288_chrg_info *info)
    718{
    719	int ret, cc, cv;
    720	unsigned int val;
    721
    722	/* Program temperature thresholds */
    723	ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C);
    724	if (ret < 0) {
    725		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
    726							AXP20X_V_LTF_CHRG, ret);
    727		return ret;
    728	}
    729
    730	ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C);
    731	if (ret < 0) {
    732		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
    733							AXP20X_V_HTF_CHRG, ret);
    734		return ret;
    735	}
    736
    737	/* Do not turn-off charger o/p after charge cycle ends */
    738	ret = regmap_update_bits(info->regmap,
    739				AXP20X_CHRG_CTRL2,
    740				CNTL2_CHG_OUT_TURNON, CNTL2_CHG_OUT_TURNON);
    741	if (ret < 0) {
    742		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
    743						AXP20X_CHRG_CTRL2, ret);
    744		return ret;
    745	}
    746
    747	/* Setup ending condition for charging to be 10% of I(chrg) */
    748	ret = regmap_update_bits(info->regmap,
    749				AXP20X_CHRG_CTRL1,
    750				CHRG_CCCV_ITERM_20P, 0);
    751	if (ret < 0) {
    752		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
    753						AXP20X_CHRG_CTRL1, ret);
    754		return ret;
    755	}
    756
    757	/* Disable OCV-SOC curve calibration */
    758	ret = regmap_update_bits(info->regmap,
    759				AXP20X_CC_CTRL,
    760				FG_CNTL_OCV_ADJ_EN, 0);
    761	if (ret < 0) {
    762		dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
    763						AXP20X_CC_CTRL, ret);
    764		return ret;
    765	}
    766
    767	if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
    768		/* See comment above axp288_hp_x2_dmi_ids declaration */
    769		ret = axp288_charger_vbus_path_select(info, true);
    770		if (ret < 0)
    771			return ret;
    772	} else {
    773		/* Set Vhold to the factory default / recommended 4.4V */
    774		val = VBUS_ISPOUT_VHOLD_SET_4400MV << VBUS_ISPOUT_VHOLD_SET_BIT_POS;
    775		ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
    776					 VBUS_ISPOUT_VHOLD_SET_MASK, val);
    777		if (ret < 0) {
    778			dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
    779				AXP20X_VBUS_IPSOUT_MGMT, ret);
    780			return ret;
    781		}
    782	}
    783
    784	/* Read current charge voltage and current limit */
    785	ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
    786	if (ret < 0) {
    787		dev_err(&info->pdev->dev, "register(%x) read error(%d)\n",
    788			AXP20X_CHRG_CTRL1, ret);
    789		return ret;
    790	}
    791
    792	/* Determine charge voltage */
    793	cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS;
    794	switch (cv) {
    795	case CHRG_CCCV_CV_4100MV:
    796		info->cv = CV_4100MV;
    797		break;
    798	case CHRG_CCCV_CV_4150MV:
    799		info->cv = CV_4150MV;
    800		break;
    801	case CHRG_CCCV_CV_4200MV:
    802		info->cv = CV_4200MV;
    803		break;
    804	case CHRG_CCCV_CV_4350MV:
    805		info->cv = CV_4350MV;
    806		break;
    807	}
    808
    809	/* Determine charge current limit */
    810	cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
    811	cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
    812	info->cc = cc;
    813
    814	/*
    815	 * Do not allow the user to configure higher settings then those
    816	 * set by the firmware
    817	 */
    818	info->max_cv = info->cv;
    819	info->max_cc = info->cc;
    820
    821	return 0;
    822}
    823
    824static void axp288_charger_cancel_work(void *data)
    825{
    826	struct axp288_chrg_info *info = data;
    827
    828	cancel_work_sync(&info->otg.work);
    829	cancel_work_sync(&info->cable.work);
    830}
    831
    832static int axp288_charger_probe(struct platform_device *pdev)
    833{
    834	int ret, i, pirq;
    835	struct axp288_chrg_info *info;
    836	struct device *dev = &pdev->dev;
    837	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
    838	struct power_supply_config charger_cfg = {};
    839	unsigned int val;
    840
    841	/*
    842	 * Normally the native AXP288 fg/charger drivers are preferred but
    843	 * on some devices the ACPI drivers should be used instead.
    844	 */
    845	if (!acpi_quirk_skip_acpi_ac_and_battery())
    846		return -ENODEV;
    847
    848	/*
    849	 * On some devices the fuelgauge and charger parts of the axp288 are
    850	 * not used, check that the fuelgauge is enabled (CC_CTRL != 0).
    851	 */
    852	ret = regmap_read(axp20x->regmap, AXP20X_CC_CTRL, &val);
    853	if (ret < 0)
    854		return ret;
    855	if (val == 0)
    856		return -ENODEV;
    857
    858	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
    859	if (!info)
    860		return -ENOMEM;
    861
    862	mutex_init(&info->lock);
    863	info->pdev = pdev;
    864	info->regmap = axp20x->regmap;
    865	info->regmap_irqc = axp20x->regmap_irqc;
    866
    867	info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
    868	if (IS_ERR(info->cable.edev)) {
    869		dev_err_probe(dev, PTR_ERR(info->cable.edev),
    870			      "extcon_get_extcon_dev(%s) failed\n",
    871			      AXP288_EXTCON_DEV_NAME);
    872		return PTR_ERR(info->cable.edev);
    873	}
    874
    875	if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
    876		info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
    877		if (IS_ERR(info->otg.cable)) {
    878			dev_err_probe(dev, PTR_ERR(info->otg.cable),
    879				      "extcon_get_extcon_dev(%s) failed\n",
    880				      USB_HOST_EXTCON_NAME);
    881			return PTR_ERR(info->otg.cable);
    882		}
    883		dev_info(dev, "Using " USB_HOST_EXTCON_HID " extcon for usb-id\n");
    884	}
    885
    886	platform_set_drvdata(pdev, info);
    887
    888	ret = charger_init_hw_regs(info);
    889	if (ret)
    890		return ret;
    891
    892	/* Register with power supply class */
    893	charger_cfg.drv_data = info;
    894	info->psy_usb = devm_power_supply_register(dev, &axp288_charger_desc,
    895						   &charger_cfg);
    896	if (IS_ERR(info->psy_usb)) {
    897		ret = PTR_ERR(info->psy_usb);
    898		dev_err(dev, "failed to register power supply: %d\n", ret);
    899		return ret;
    900	}
    901
    902	/* Cancel our work on cleanup, register this before the notifiers */
    903	ret = devm_add_action(dev, axp288_charger_cancel_work, info);
    904	if (ret)
    905		return ret;
    906
    907	/* Register for extcon notification */
    908	INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker);
    909	info->cable.nb.notifier_call = axp288_charger_handle_cable_evt;
    910	ret = devm_extcon_register_notifier_all(dev, info->cable.edev,
    911						&info->cable.nb);
    912	if (ret) {
    913		dev_err(dev, "failed to register cable extcon notifier\n");
    914		return ret;
    915	}
    916	schedule_work(&info->cable.work);
    917
    918	/* Register for OTG notification */
    919	INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
    920	info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
    921	if (info->otg.cable) {
    922		ret = devm_extcon_register_notifier(dev, info->otg.cable,
    923					EXTCON_USB_HOST, &info->otg.id_nb);
    924		if (ret) {
    925			dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n");
    926			return ret;
    927		}
    928		schedule_work(&info->otg.work);
    929	}
    930
    931	/* Register charger interrupts */
    932	for (i = 0; i < CHRG_INTR_END; i++) {
    933		pirq = platform_get_irq(info->pdev, i);
    934		if (pirq < 0)
    935			return pirq;
    936
    937		info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
    938		if (info->irq[i] < 0) {
    939			dev_warn(&info->pdev->dev,
    940				"failed to get virtual interrupt=%d\n", pirq);
    941			return info->irq[i];
    942		}
    943		ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i],
    944					NULL, axp288_charger_irq_thread_handler,
    945					IRQF_ONESHOT, info->pdev->name, info);
    946		if (ret) {
    947			dev_err(dev, "failed to request interrupt=%d\n",
    948								info->irq[i]);
    949			return ret;
    950		}
    951	}
    952
    953	return 0;
    954}
    955
    956static const struct platform_device_id axp288_charger_id_table[] = {
    957	{ .name = "axp288_charger" },
    958	{},
    959};
    960MODULE_DEVICE_TABLE(platform, axp288_charger_id_table);
    961
    962static struct platform_driver axp288_charger_driver = {
    963	.probe = axp288_charger_probe,
    964	.id_table = axp288_charger_id_table,
    965	.driver = {
    966		.name = "axp288_charger",
    967	},
    968};
    969
    970module_platform_driver(axp288_charger_driver);
    971
    972MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
    973MODULE_DESCRIPTION("X-power AXP288 Charger Driver");
    974MODULE_LICENSE("GPL v2");