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

max14656_charger_detector.c (8073B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Maxim MAX14656 / AL32 USB Charger Detector driver
      4 *
      5 * Copyright (C) 2014 LG Electronics, Inc
      6 * Copyright (C) 2016 Alexander Kurz <akurz@blala.de>
      7 *
      8 * Components from Maxim AL32 Charger detection Driver for MX50 Yoshi Board
      9 * Copyright (C) Amazon Technologies Inc. All rights reserved.
     10 * Manish Lachwani (lachwani@lab126.com)
     11 */
     12#include <linux/module.h>
     13#include <linux/init.h>
     14#include <linux/delay.h>
     15#include <linux/i2c.h>
     16#include <linux/interrupt.h>
     17#include <linux/slab.h>
     18#include <linux/of_device.h>
     19#include <linux/workqueue.h>
     20#include <linux/power_supply.h>
     21#include <linux/devm-helpers.h>
     22
     23#define MAX14656_MANUFACTURER	"Maxim Integrated"
     24#define MAX14656_NAME		"max14656"
     25
     26#define MAX14656_DEVICE_ID	0x00
     27#define MAX14656_INTERRUPT_1	0x01
     28#define MAX14656_INTERRUPT_2	0x02
     29#define MAX14656_STATUS_1	0x03
     30#define MAX14656_STATUS_2	0x04
     31#define MAX14656_INTMASK_1	0x05
     32#define MAX14656_INTMASK_2	0x06
     33#define MAX14656_CONTROL_1	0x07
     34#define MAX14656_CONTROL_2	0x08
     35#define MAX14656_CONTROL_3	0x09
     36
     37#define DEVICE_VENDOR_MASK	0xf0
     38#define DEVICE_REV_MASK		0x0f
     39#define INT_EN_REG_MASK		BIT(4)
     40#define CHG_TYPE_INT_MASK	BIT(0)
     41#define STATUS1_VB_VALID_MASK	BIT(4)
     42#define STATUS1_CHG_TYPE_MASK	0xf
     43#define INT1_DCD_TIMEOUT_MASK	BIT(7)
     44#define CONTROL1_DEFAULT	0x0d
     45#define CONTROL1_INT_EN		BIT(4)
     46#define CONTROL1_INT_ACTIVE_HIGH	BIT(5)
     47#define CONTROL1_EDGE		BIT(7)
     48#define CONTROL2_DEFAULT	0x8e
     49#define CONTROL2_ADC_EN		BIT(0)
     50#define CONTROL3_DEFAULT	0x8d
     51
     52enum max14656_chg_type {
     53	MAX14656_NO_CHARGER	= 0,
     54	MAX14656_SDP_CHARGER,
     55	MAX14656_CDP_CHARGER,
     56	MAX14656_DCP_CHARGER,
     57	MAX14656_APPLE_500MA_CHARGER,
     58	MAX14656_APPLE_1A_CHARGER,
     59	MAX14656_APPLE_2A_CHARGER,
     60	MAX14656_SPECIAL_500MA_CHARGER,
     61	MAX14656_APPLE_12W,
     62	MAX14656_CHARGER_LAST
     63};
     64
     65static const struct max14656_chg_type_props {
     66	enum power_supply_type type;
     67} chg_type_props[] = {
     68	{ POWER_SUPPLY_TYPE_UNKNOWN },
     69	{ POWER_SUPPLY_TYPE_USB },
     70	{ POWER_SUPPLY_TYPE_USB_CDP },
     71	{ POWER_SUPPLY_TYPE_USB_DCP },
     72	{ POWER_SUPPLY_TYPE_USB_DCP },
     73	{ POWER_SUPPLY_TYPE_USB_DCP },
     74	{ POWER_SUPPLY_TYPE_USB_DCP },
     75	{ POWER_SUPPLY_TYPE_USB_DCP },
     76	{ POWER_SUPPLY_TYPE_USB },
     77};
     78
     79struct max14656_chip {
     80	struct i2c_client	*client;
     81	struct power_supply	*detect_psy;
     82	struct power_supply_desc psy_desc;
     83	struct delayed_work	irq_work;
     84
     85	int irq;
     86	int online;
     87};
     88
     89static int max14656_read_reg(struct i2c_client *client, int reg, u8 *val)
     90{
     91	s32 ret;
     92
     93	ret = i2c_smbus_read_byte_data(client, reg);
     94	if (ret < 0) {
     95		dev_err(&client->dev,
     96			"i2c read fail: can't read from %02x: %d\n",
     97			reg, ret);
     98		return ret;
     99	}
    100	*val = ret;
    101	return 0;
    102}
    103
    104static int max14656_write_reg(struct i2c_client *client, int reg, u8 val)
    105{
    106	s32 ret;
    107
    108	ret = i2c_smbus_write_byte_data(client, reg, val);
    109	if (ret < 0) {
    110		dev_err(&client->dev,
    111			"i2c write fail: can't write %02x to %02x: %d\n",
    112			val, reg, ret);
    113		return ret;
    114	}
    115	return 0;
    116}
    117
    118static int max14656_read_block_reg(struct i2c_client *client, u8 reg,
    119				  u8 length, u8 *val)
    120{
    121	int ret;
    122
    123	ret = i2c_smbus_read_i2c_block_data(client, reg, length, val);
    124	if (ret < 0) {
    125		dev_err(&client->dev, "failed to block read reg 0x%x: %d\n",
    126				reg, ret);
    127		return ret;
    128	}
    129
    130	return 0;
    131}
    132
    133#define        REG_TOTAL_NUM   5
    134static void max14656_irq_worker(struct work_struct *work)
    135{
    136	struct max14656_chip *chip =
    137		container_of(work, struct max14656_chip, irq_work.work);
    138
    139	u8 buf[REG_TOTAL_NUM];
    140	u8 chg_type;
    141
    142	max14656_read_block_reg(chip->client, MAX14656_DEVICE_ID,
    143				REG_TOTAL_NUM, buf);
    144
    145	if ((buf[MAX14656_STATUS_1] & STATUS1_VB_VALID_MASK) &&
    146		(buf[MAX14656_STATUS_1] & STATUS1_CHG_TYPE_MASK)) {
    147		chg_type = buf[MAX14656_STATUS_1] & STATUS1_CHG_TYPE_MASK;
    148		if (chg_type < MAX14656_CHARGER_LAST)
    149			chip->psy_desc.type = chg_type_props[chg_type].type;
    150		else
    151			chip->psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
    152		chip->online = 1;
    153	} else {
    154		chip->online = 0;
    155		chip->psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
    156	}
    157
    158	power_supply_changed(chip->detect_psy);
    159}
    160
    161static irqreturn_t max14656_irq(int irq, void *dev_id)
    162{
    163	struct max14656_chip *chip = dev_id;
    164
    165	schedule_delayed_work(&chip->irq_work, msecs_to_jiffies(100));
    166
    167	return IRQ_HANDLED;
    168}
    169
    170static int max14656_hw_init(struct max14656_chip *chip)
    171{
    172	uint8_t val = 0;
    173	uint8_t rev;
    174	struct i2c_client *client = chip->client;
    175
    176	if (max14656_read_reg(client, MAX14656_DEVICE_ID, &val))
    177		return -ENODEV;
    178
    179	if ((val & DEVICE_VENDOR_MASK) != 0x20) {
    180		dev_err(&client->dev, "wrong vendor ID %d\n",
    181			((val & DEVICE_VENDOR_MASK) >> 4));
    182		return -ENODEV;
    183	}
    184	rev = val & DEVICE_REV_MASK;
    185
    186	/* Turn on ADC_EN */
    187	if (max14656_write_reg(client, MAX14656_CONTROL_2, CONTROL2_ADC_EN))
    188		return -EINVAL;
    189
    190	/* turn on interrupts and low power mode */
    191	if (max14656_write_reg(client, MAX14656_CONTROL_1,
    192		CONTROL1_DEFAULT |
    193		CONTROL1_INT_EN |
    194		CONTROL1_INT_ACTIVE_HIGH |
    195		CONTROL1_EDGE))
    196		return -EINVAL;
    197
    198	if (max14656_write_reg(client, MAX14656_INTMASK_1, 0x3))
    199		return -EINVAL;
    200
    201	if (max14656_write_reg(client, MAX14656_INTMASK_2, 0x1))
    202		return -EINVAL;
    203
    204	dev_info(&client->dev, "detected revision %d\n", rev);
    205	return 0;
    206}
    207
    208static int max14656_get_property(struct power_supply *psy,
    209			    enum power_supply_property psp,
    210			    union power_supply_propval *val)
    211{
    212	struct max14656_chip *chip = power_supply_get_drvdata(psy);
    213
    214	switch (psp) {
    215	case POWER_SUPPLY_PROP_ONLINE:
    216		val->intval = chip->online;
    217		break;
    218	case POWER_SUPPLY_PROP_MODEL_NAME:
    219		val->strval = MAX14656_NAME;
    220		break;
    221	case POWER_SUPPLY_PROP_MANUFACTURER:
    222		val->strval = MAX14656_MANUFACTURER;
    223		break;
    224	default:
    225		return -EINVAL;
    226	}
    227
    228	return 0;
    229}
    230
    231static enum power_supply_property max14656_battery_props[] = {
    232	POWER_SUPPLY_PROP_ONLINE,
    233	POWER_SUPPLY_PROP_MODEL_NAME,
    234	POWER_SUPPLY_PROP_MANUFACTURER,
    235};
    236
    237static int max14656_probe(struct i2c_client *client,
    238			  const struct i2c_device_id *id)
    239{
    240	struct i2c_adapter *adapter = client->adapter;
    241	struct device *dev = &client->dev;
    242	struct power_supply_config psy_cfg = {};
    243	struct max14656_chip *chip;
    244	int irq = client->irq;
    245	int ret = 0;
    246
    247	if (irq <= 0) {
    248		dev_err(dev, "invalid irq number: %d\n", irq);
    249		return -ENODEV;
    250	}
    251
    252	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
    253		dev_err(dev, "No support for SMBUS_BYTE_DATA\n");
    254		return -ENODEV;
    255	}
    256
    257	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
    258	if (!chip)
    259		return -ENOMEM;
    260
    261	psy_cfg.drv_data = chip;
    262	chip->client = client;
    263	chip->online = 0;
    264	chip->psy_desc.name = MAX14656_NAME;
    265	chip->psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
    266	chip->psy_desc.properties = max14656_battery_props;
    267	chip->psy_desc.num_properties = ARRAY_SIZE(max14656_battery_props);
    268	chip->psy_desc.get_property = max14656_get_property;
    269	chip->irq = irq;
    270
    271	ret = max14656_hw_init(chip);
    272	if (ret)
    273		return -ENODEV;
    274
    275	chip->detect_psy = devm_power_supply_register(dev,
    276		       &chip->psy_desc, &psy_cfg);
    277	if (IS_ERR(chip->detect_psy)) {
    278		dev_err(dev, "power_supply_register failed\n");
    279		return -EINVAL;
    280	}
    281
    282	ret = devm_delayed_work_autocancel(dev, &chip->irq_work,
    283					   max14656_irq_worker);
    284	if (ret) {
    285		dev_err(dev, "devm_delayed_work_autocancel %d failed\n", ret);
    286		return ret;
    287	}
    288
    289	ret = devm_request_irq(dev, chip->irq, max14656_irq,
    290			       IRQF_TRIGGER_FALLING,
    291			       MAX14656_NAME, chip);
    292	if (ret) {
    293		dev_err(dev, "request_irq %d failed\n", chip->irq);
    294		return -EINVAL;
    295	}
    296	enable_irq_wake(chip->irq);
    297
    298	schedule_delayed_work(&chip->irq_work, msecs_to_jiffies(2000));
    299
    300	return 0;
    301}
    302
    303static const struct i2c_device_id max14656_id[] = {
    304	{ "max14656", 0 },
    305	{}
    306};
    307MODULE_DEVICE_TABLE(i2c, max14656_id);
    308
    309static const struct of_device_id max14656_match_table[] = {
    310	{ .compatible = "maxim,max14656", },
    311	{}
    312};
    313MODULE_DEVICE_TABLE(of, max14656_match_table);
    314
    315static struct i2c_driver max14656_i2c_driver = {
    316	.driver = {
    317		.name	= "max14656",
    318		.of_match_table = max14656_match_table,
    319	},
    320	.probe		= max14656_probe,
    321	.id_table	= max14656_id,
    322};
    323module_i2c_driver(max14656_i2c_driver);
    324
    325MODULE_DESCRIPTION("MAX14656 USB charger detector");
    326MODULE_LICENSE("GPL v2");