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

lp8727_charger.c (14503B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Driver for LP8727 Micro/Mini USB IC with integrated charger
      4 *
      5 *			Copyright (C) 2011 Texas Instruments
      6 *			Copyright (C) 2011 National Semiconductor
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/slab.h>
     11#include <linux/interrupt.h>
     12#include <linux/i2c.h>
     13#include <linux/power_supply.h>
     14#include <linux/platform_data/lp8727.h>
     15#include <linux/of.h>
     16
     17#define LP8788_NUM_INTREGS	2
     18#define DEFAULT_DEBOUNCE_MSEC	270
     19
     20/* Registers */
     21#define LP8727_CTRL1		0x1
     22#define LP8727_CTRL2		0x2
     23#define LP8727_SWCTRL		0x3
     24#define LP8727_INT1		0x4
     25#define LP8727_INT2		0x5
     26#define LP8727_STATUS1		0x6
     27#define LP8727_STATUS2		0x7
     28#define LP8727_CHGCTRL2		0x9
     29
     30/* CTRL1 register */
     31#define LP8727_CP_EN		BIT(0)
     32#define LP8727_ADC_EN		BIT(1)
     33#define LP8727_ID200_EN		BIT(4)
     34
     35/* CTRL2 register */
     36#define LP8727_CHGDET_EN	BIT(1)
     37#define LP8727_INT_EN		BIT(6)
     38
     39/* SWCTRL register */
     40#define LP8727_SW_DM1_DM	(0x0 << 0)
     41#define LP8727_SW_DM1_HiZ	(0x7 << 0)
     42#define LP8727_SW_DP2_DP	(0x0 << 3)
     43#define LP8727_SW_DP2_HiZ	(0x7 << 3)
     44
     45/* INT1 register */
     46#define LP8727_IDNO		(0xF << 0)
     47#define LP8727_VBUS		BIT(4)
     48
     49/* STATUS1 register */
     50#define LP8727_CHGSTAT		(3 << 4)
     51#define LP8727_CHPORT		BIT(6)
     52#define LP8727_DCPORT		BIT(7)
     53#define LP8727_STAT_EOC		0x30
     54
     55/* STATUS2 register */
     56#define LP8727_TEMP_STAT	(3 << 5)
     57#define LP8727_TEMP_SHIFT	5
     58
     59/* CHGCTRL2 register */
     60#define LP8727_ICHG_SHIFT	4
     61
     62enum lp8727_dev_id {
     63	LP8727_ID_NONE,
     64	LP8727_ID_TA,
     65	LP8727_ID_DEDICATED_CHG,
     66	LP8727_ID_USB_CHG,
     67	LP8727_ID_USB_DS,
     68	LP8727_ID_MAX,
     69};
     70
     71enum lp8727_die_temp {
     72	LP8788_TEMP_75C,
     73	LP8788_TEMP_95C,
     74	LP8788_TEMP_115C,
     75	LP8788_TEMP_135C,
     76};
     77
     78struct lp8727_psy {
     79	struct power_supply *ac;
     80	struct power_supply *usb;
     81	struct power_supply *batt;
     82};
     83
     84struct lp8727_chg {
     85	struct device *dev;
     86	struct i2c_client *client;
     87	struct mutex xfer_lock;
     88	struct lp8727_psy *psy;
     89	struct lp8727_platform_data *pdata;
     90
     91	/* Charger Data */
     92	enum lp8727_dev_id devid;
     93	struct lp8727_chg_param *chg_param;
     94
     95	/* Interrupt Handling */
     96	int irq;
     97	struct delayed_work work;
     98	unsigned long debounce_jiffies;
     99};
    100
    101static int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
    102{
    103	s32 ret;
    104
    105	mutex_lock(&pchg->xfer_lock);
    106	ret = i2c_smbus_read_i2c_block_data(pchg->client, reg, len, data);
    107	mutex_unlock(&pchg->xfer_lock);
    108
    109	return (ret != len) ? -EIO : 0;
    110}
    111
    112static inline int lp8727_read_byte(struct lp8727_chg *pchg, u8 reg, u8 *data)
    113{
    114	return lp8727_read_bytes(pchg, reg, data, 1);
    115}
    116
    117static int lp8727_write_byte(struct lp8727_chg *pchg, u8 reg, u8 data)
    118{
    119	int ret;
    120
    121	mutex_lock(&pchg->xfer_lock);
    122	ret = i2c_smbus_write_byte_data(pchg->client, reg, data);
    123	mutex_unlock(&pchg->xfer_lock);
    124
    125	return ret;
    126}
    127
    128static bool lp8727_is_charger_attached(const char *name, int id)
    129{
    130	if (!strcmp(name, "ac"))
    131		return id == LP8727_ID_TA || id == LP8727_ID_DEDICATED_CHG;
    132	else if (!strcmp(name, "usb"))
    133		return id == LP8727_ID_USB_CHG;
    134
    135	return id >= LP8727_ID_TA && id <= LP8727_ID_USB_CHG;
    136}
    137
    138static int lp8727_init_device(struct lp8727_chg *pchg)
    139{
    140	u8 val;
    141	int ret;
    142	u8 intstat[LP8788_NUM_INTREGS];
    143
    144	/* clear interrupts */
    145	ret = lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS);
    146	if (ret)
    147		return ret;
    148
    149	val = LP8727_ID200_EN | LP8727_ADC_EN | LP8727_CP_EN;
    150	ret = lp8727_write_byte(pchg, LP8727_CTRL1, val);
    151	if (ret)
    152		return ret;
    153
    154	val = LP8727_INT_EN | LP8727_CHGDET_EN;
    155	return lp8727_write_byte(pchg, LP8727_CTRL2, val);
    156}
    157
    158static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg)
    159{
    160	u8 val;
    161
    162	lp8727_read_byte(pchg, LP8727_STATUS1, &val);
    163	return val & LP8727_DCPORT;
    164}
    165
    166static int lp8727_is_usb_charger(struct lp8727_chg *pchg)
    167{
    168	u8 val;
    169
    170	lp8727_read_byte(pchg, LP8727_STATUS1, &val);
    171	return val & LP8727_CHPORT;
    172}
    173
    174static inline void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)
    175{
    176	lp8727_write_byte(pchg, LP8727_SWCTRL, sw);
    177}
    178
    179static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin)
    180{
    181	struct lp8727_platform_data *pdata = pchg->pdata;
    182	u8 devid = LP8727_ID_NONE;
    183	u8 swctrl = LP8727_SW_DM1_HiZ | LP8727_SW_DP2_HiZ;
    184
    185	switch (id) {
    186	case 0x5:
    187		devid = LP8727_ID_TA;
    188		pchg->chg_param = pdata ? pdata->ac : NULL;
    189		break;
    190	case 0xB:
    191		if (lp8727_is_dedicated_charger(pchg)) {
    192			pchg->chg_param = pdata ? pdata->ac : NULL;
    193			devid = LP8727_ID_DEDICATED_CHG;
    194		} else if (lp8727_is_usb_charger(pchg)) {
    195			pchg->chg_param = pdata ? pdata->usb : NULL;
    196			devid = LP8727_ID_USB_CHG;
    197			swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP;
    198		} else if (vbusin) {
    199			devid = LP8727_ID_USB_DS;
    200			swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP;
    201		}
    202		break;
    203	default:
    204		devid = LP8727_ID_NONE;
    205		pchg->chg_param = NULL;
    206		break;
    207	}
    208
    209	pchg->devid = devid;
    210	lp8727_ctrl_switch(pchg, swctrl);
    211}
    212
    213static void lp8727_enable_chgdet(struct lp8727_chg *pchg)
    214{
    215	u8 val;
    216
    217	lp8727_read_byte(pchg, LP8727_CTRL2, &val);
    218	val |= LP8727_CHGDET_EN;
    219	lp8727_write_byte(pchg, LP8727_CTRL2, val);
    220}
    221
    222static void lp8727_delayed_func(struct work_struct *_work)
    223{
    224	struct lp8727_chg *pchg = container_of(_work, struct lp8727_chg,
    225						work.work);
    226	u8 intstat[LP8788_NUM_INTREGS];
    227	u8 idno;
    228	u8 vbus;
    229
    230	if (lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS)) {
    231		dev_err(pchg->dev, "can not read INT registers\n");
    232		return;
    233	}
    234
    235	idno = intstat[0] & LP8727_IDNO;
    236	vbus = intstat[0] & LP8727_VBUS;
    237
    238	lp8727_id_detection(pchg, idno, vbus);
    239	lp8727_enable_chgdet(pchg);
    240
    241	power_supply_changed(pchg->psy->ac);
    242	power_supply_changed(pchg->psy->usb);
    243	power_supply_changed(pchg->psy->batt);
    244}
    245
    246static irqreturn_t lp8727_isr_func(int irq, void *ptr)
    247{
    248	struct lp8727_chg *pchg = ptr;
    249
    250	schedule_delayed_work(&pchg->work, pchg->debounce_jiffies);
    251	return IRQ_HANDLED;
    252}
    253
    254static int lp8727_setup_irq(struct lp8727_chg *pchg)
    255{
    256	int ret;
    257	int irq = pchg->client->irq;
    258	unsigned delay_msec = pchg->pdata ? pchg->pdata->debounce_msec :
    259						DEFAULT_DEBOUNCE_MSEC;
    260
    261	INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func);
    262
    263	if (irq <= 0) {
    264		dev_warn(pchg->dev, "invalid irq number: %d\n", irq);
    265		return 0;
    266	}
    267
    268	ret = request_threaded_irq(irq,	NULL, lp8727_isr_func,
    269				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
    270				"lp8727_irq", pchg);
    271
    272	if (ret)
    273		return ret;
    274
    275	pchg->irq = irq;
    276	pchg->debounce_jiffies = msecs_to_jiffies(delay_msec);
    277
    278	return 0;
    279}
    280
    281static void lp8727_release_irq(struct lp8727_chg *pchg)
    282{
    283	cancel_delayed_work_sync(&pchg->work);
    284
    285	if (pchg->irq)
    286		free_irq(pchg->irq, pchg);
    287}
    288
    289static enum power_supply_property lp8727_charger_prop[] = {
    290	POWER_SUPPLY_PROP_ONLINE,
    291};
    292
    293static enum power_supply_property lp8727_battery_prop[] = {
    294	POWER_SUPPLY_PROP_STATUS,
    295	POWER_SUPPLY_PROP_HEALTH,
    296	POWER_SUPPLY_PROP_PRESENT,
    297	POWER_SUPPLY_PROP_VOLTAGE_NOW,
    298	POWER_SUPPLY_PROP_CAPACITY,
    299	POWER_SUPPLY_PROP_TEMP,
    300};
    301
    302static char *battery_supplied_to[] = {
    303	"main_batt",
    304};
    305
    306static int lp8727_charger_get_property(struct power_supply *psy,
    307				       enum power_supply_property psp,
    308				       union power_supply_propval *val)
    309{
    310	struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);
    311
    312	if (psp != POWER_SUPPLY_PROP_ONLINE)
    313		return -EINVAL;
    314
    315	val->intval = lp8727_is_charger_attached(psy->desc->name, pchg->devid);
    316
    317	return 0;
    318}
    319
    320static bool lp8727_is_high_temperature(enum lp8727_die_temp temp)
    321{
    322	switch (temp) {
    323	case LP8788_TEMP_95C:
    324	case LP8788_TEMP_115C:
    325	case LP8788_TEMP_135C:
    326		return true;
    327	default:
    328		return false;
    329	}
    330}
    331
    332static int lp8727_battery_get_property(struct power_supply *psy,
    333				       enum power_supply_property psp,
    334				       union power_supply_propval *val)
    335{
    336	struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);
    337	struct lp8727_platform_data *pdata = pchg->pdata;
    338	enum lp8727_die_temp temp;
    339	u8 read;
    340
    341	switch (psp) {
    342	case POWER_SUPPLY_PROP_STATUS:
    343		if (!lp8727_is_charger_attached(psy->desc->name, pchg->devid)) {
    344			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
    345			return 0;
    346		}
    347
    348		lp8727_read_byte(pchg, LP8727_STATUS1, &read);
    349
    350		val->intval = (read & LP8727_CHGSTAT) == LP8727_STAT_EOC ?
    351				POWER_SUPPLY_STATUS_FULL :
    352				POWER_SUPPLY_STATUS_CHARGING;
    353		break;
    354	case POWER_SUPPLY_PROP_HEALTH:
    355		lp8727_read_byte(pchg, LP8727_STATUS2, &read);
    356		temp = (read & LP8727_TEMP_STAT) >> LP8727_TEMP_SHIFT;
    357
    358		val->intval = lp8727_is_high_temperature(temp) ?
    359			POWER_SUPPLY_HEALTH_OVERHEAT :
    360			POWER_SUPPLY_HEALTH_GOOD;
    361		break;
    362	case POWER_SUPPLY_PROP_PRESENT:
    363		if (!pdata)
    364			return -EINVAL;
    365
    366		if (pdata->get_batt_present)
    367			val->intval = pdata->get_batt_present();
    368		break;
    369	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
    370		if (!pdata)
    371			return -EINVAL;
    372
    373		if (pdata->get_batt_level)
    374			val->intval = pdata->get_batt_level();
    375		break;
    376	case POWER_SUPPLY_PROP_CAPACITY:
    377		if (!pdata)
    378			return -EINVAL;
    379
    380		if (pdata->get_batt_capacity)
    381			val->intval = pdata->get_batt_capacity();
    382		break;
    383	case POWER_SUPPLY_PROP_TEMP:
    384		if (!pdata)
    385			return -EINVAL;
    386
    387		if (pdata->get_batt_temp)
    388			val->intval = pdata->get_batt_temp();
    389		break;
    390	default:
    391		break;
    392	}
    393
    394	return 0;
    395}
    396
    397static void lp8727_charger_changed(struct power_supply *psy)
    398{
    399	struct lp8727_chg *pchg = dev_get_drvdata(psy->dev.parent);
    400	u8 eoc_level;
    401	u8 ichg;
    402	u8 val;
    403
    404	/* skip if no charger exists */
    405	if (!lp8727_is_charger_attached(psy->desc->name, pchg->devid))
    406		return;
    407
    408	/* update charging parameters */
    409	if (pchg->chg_param) {
    410		eoc_level = pchg->chg_param->eoc_level;
    411		ichg = pchg->chg_param->ichg;
    412		val = (ichg << LP8727_ICHG_SHIFT) | eoc_level;
    413		lp8727_write_byte(pchg, LP8727_CHGCTRL2, val);
    414	}
    415}
    416
    417static const struct power_supply_desc lp8727_ac_desc = {
    418	.name			= "ac",
    419	.type			= POWER_SUPPLY_TYPE_MAINS,
    420	.properties		= lp8727_charger_prop,
    421	.num_properties		= ARRAY_SIZE(lp8727_charger_prop),
    422	.get_property		= lp8727_charger_get_property,
    423};
    424
    425static const struct power_supply_desc lp8727_usb_desc = {
    426	.name			= "usb",
    427	.type			= POWER_SUPPLY_TYPE_USB,
    428	.properties		= lp8727_charger_prop,
    429	.num_properties		= ARRAY_SIZE(lp8727_charger_prop),
    430	.get_property		= lp8727_charger_get_property,
    431};
    432
    433static const struct power_supply_desc lp8727_batt_desc = {
    434	.name			= "main_batt",
    435	.type			= POWER_SUPPLY_TYPE_BATTERY,
    436	.properties		= lp8727_battery_prop,
    437	.num_properties		= ARRAY_SIZE(lp8727_battery_prop),
    438	.get_property		= lp8727_battery_get_property,
    439	.external_power_changed	= lp8727_charger_changed,
    440};
    441
    442static int lp8727_register_psy(struct lp8727_chg *pchg)
    443{
    444	struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
    445	struct lp8727_psy *psy;
    446
    447	psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL);
    448	if (!psy)
    449		return -ENOMEM;
    450
    451	pchg->psy = psy;
    452
    453	psy_cfg.supplied_to = battery_supplied_to;
    454	psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
    455
    456	psy->ac = power_supply_register(pchg->dev, &lp8727_ac_desc, &psy_cfg);
    457	if (IS_ERR(psy->ac))
    458		goto err_psy_ac;
    459
    460	psy->usb = power_supply_register(pchg->dev, &lp8727_usb_desc,
    461					 &psy_cfg);
    462	if (IS_ERR(psy->usb))
    463		goto err_psy_usb;
    464
    465	psy->batt = power_supply_register(pchg->dev, &lp8727_batt_desc, NULL);
    466	if (IS_ERR(psy->batt))
    467		goto err_psy_batt;
    468
    469	return 0;
    470
    471err_psy_batt:
    472	power_supply_unregister(psy->usb);
    473err_psy_usb:
    474	power_supply_unregister(psy->ac);
    475err_psy_ac:
    476	return -EPERM;
    477}
    478
    479static void lp8727_unregister_psy(struct lp8727_chg *pchg)
    480{
    481	struct lp8727_psy *psy = pchg->psy;
    482
    483	if (!psy)
    484		return;
    485
    486	power_supply_unregister(psy->ac);
    487	power_supply_unregister(psy->usb);
    488	power_supply_unregister(psy->batt);
    489}
    490
    491#ifdef CONFIG_OF
    492static struct lp8727_chg_param
    493*lp8727_parse_charge_pdata(struct device *dev, struct device_node *np)
    494{
    495	struct lp8727_chg_param *param;
    496
    497	param = devm_kzalloc(dev, sizeof(*param), GFP_KERNEL);
    498	if (!param)
    499		goto out;
    500
    501	of_property_read_u8(np, "eoc-level", (u8 *)&param->eoc_level);
    502	of_property_read_u8(np, "charging-current", (u8 *)&param->ichg);
    503out:
    504	return param;
    505}
    506
    507static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
    508{
    509	struct device_node *np = dev->of_node;
    510	struct device_node *child;
    511	struct lp8727_platform_data *pdata;
    512	const char *type;
    513
    514	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
    515	if (!pdata)
    516		return ERR_PTR(-ENOMEM);
    517
    518	of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec);
    519
    520	/* If charging parameter is not defined, just skip parsing the dt */
    521	if (of_get_child_count(np) == 0)
    522		return pdata;
    523
    524	for_each_child_of_node(np, child) {
    525		of_property_read_string(child, "charger-type", &type);
    526
    527		if (!strcmp(type, "ac"))
    528			pdata->ac = lp8727_parse_charge_pdata(dev, child);
    529
    530		if (!strcmp(type, "usb"))
    531			pdata->usb = lp8727_parse_charge_pdata(dev, child);
    532	}
    533
    534	return pdata;
    535}
    536#else
    537static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
    538{
    539	return NULL;
    540}
    541#endif
    542
    543static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
    544{
    545	struct lp8727_chg *pchg;
    546	struct lp8727_platform_data *pdata;
    547	int ret;
    548
    549	if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
    550		return -EIO;
    551
    552	if (cl->dev.of_node) {
    553		pdata = lp8727_parse_dt(&cl->dev);
    554		if (IS_ERR(pdata))
    555			return PTR_ERR(pdata);
    556	} else {
    557		pdata = dev_get_platdata(&cl->dev);
    558	}
    559
    560	pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL);
    561	if (!pchg)
    562		return -ENOMEM;
    563
    564	pchg->client = cl;
    565	pchg->dev = &cl->dev;
    566	pchg->pdata = pdata;
    567	i2c_set_clientdata(cl, pchg);
    568
    569	mutex_init(&pchg->xfer_lock);
    570
    571	ret = lp8727_init_device(pchg);
    572	if (ret) {
    573		dev_err(pchg->dev, "i2c communication err: %d", ret);
    574		return ret;
    575	}
    576
    577	ret = lp8727_register_psy(pchg);
    578	if (ret) {
    579		dev_err(pchg->dev, "power supplies register err: %d", ret);
    580		return ret;
    581	}
    582
    583	ret = lp8727_setup_irq(pchg);
    584	if (ret) {
    585		dev_err(pchg->dev, "irq handler err: %d", ret);
    586		lp8727_unregister_psy(pchg);
    587		return ret;
    588	}
    589
    590	return 0;
    591}
    592
    593static int lp8727_remove(struct i2c_client *cl)
    594{
    595	struct lp8727_chg *pchg = i2c_get_clientdata(cl);
    596
    597	lp8727_release_irq(pchg);
    598	lp8727_unregister_psy(pchg);
    599	return 0;
    600}
    601
    602static const struct of_device_id lp8727_dt_ids[] = {
    603	{ .compatible = "ti,lp8727", },
    604	{ }
    605};
    606MODULE_DEVICE_TABLE(of, lp8727_dt_ids);
    607
    608static const struct i2c_device_id lp8727_ids[] = {
    609	{"lp8727", 0},
    610	{ }
    611};
    612MODULE_DEVICE_TABLE(i2c, lp8727_ids);
    613
    614static struct i2c_driver lp8727_driver = {
    615	.driver = {
    616		   .name = "lp8727",
    617		   .of_match_table = of_match_ptr(lp8727_dt_ids),
    618		   },
    619	.probe = lp8727_probe,
    620	.remove = lp8727_remove,
    621	.id_table = lp8727_ids,
    622};
    623module_i2c_driver(lp8727_driver);
    624
    625MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver");
    626MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");
    627MODULE_LICENSE("GPL");