/*
* TI BQ24257 charger driver
*
* Copyright (C) 2015 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Datasheets:
* http://www.ti.com/product/bq24250
* http://www.ti.com/product/bq24251
* http://www.ti.com/product/bq24257
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/acpi.h>
#include <linux/of.h>
#define BQ24257_REG_1 0x00
#define BQ24257_REG_2 0x01
#define BQ24257_REG_3 0x02
#define BQ24257_REG_4 0x03
#define BQ24257_REG_5 0x04
#define BQ24257_REG_6 0x05
#define BQ24257_REG_7 0x06
#define BQ24257_MANUFACTURER "Texas Instruments"
#define BQ24257_PG_GPIO "pg"
#define BQ24257_ILIM_SET_DELAY 1000 /* msec */
/*
* When adding support for new devices make sure that enum bq2425x_chip and
* bq2425x_chip_name[] always stay in sync!
*/
enum bq2425x_chip {
BQ24250,
BQ24251,
BQ24257,
};
static const char *const bq2425x_chip_name[] = {
"bq24250",
"bq24251",
"bq24257",
};
enum bq24257_fields {
F_WD_FAULT, F_WD_EN, F_STAT, F_FAULT, /* REG 1 */
F_RESET, F_IILIMIT, F_EN_STAT, F_EN_TERM, F_CE, F_HZ_MODE, /* REG 2 */
F_VBAT, F_USB_DET, /* REG 3 */
F_ICHG, F_ITERM, /* REG 4 */
F_LOOP_STATUS, F_LOW_CHG, F_DPDM_EN, F_CE_STATUS, F_VINDPM, /* REG 5 */
F_X2_TMR_EN, F_TMR, F_SYSOFF, F_TS_EN, F_TS_STAT, /* REG 6 */
F_VOVP, F_CLR_VDP, F_FORCE_BATDET, F_FORCE_PTM, /* REG 7 */
F_MAX_FIELDS
};
/* initial field values, converted from uV/uA */
struct bq24257_init_data {
u8 ichg; /* charge current */
u8 vbat; /* regulation voltage */
u8 iterm; /* termination current */
u8 iilimit; /* input current limit */
u8 vovp; /* over voltage protection voltage */
u8 vindpm; /* VDMP input threshold voltage */
};
struct bq24257_state {
u8 status;
u8 fault;
bool power_good;
};
struct bq24257_device {
struct i2c_client *client;
struct device *dev;
struct power_supply *charger;
enum bq2425x_chip chip;
struct regmap *rmap;
struct regmap_field *rmap_fields[F_MAX_FIELDS];
struct gpio_desc *pg;
struct delayed_work iilimit_setup_work;
struct bq24257_init_data init_data;
struct bq24257_state state;
struct mutex lock; /* protect state data */
bool iilimit_autoset_enable;
};
static bool bq24257_is_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case BQ24257_REG_2:
case BQ24257_REG_4:
return false;
default:
return true;
}
}
static const struct regmap_config bq24257_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = BQ24257_REG_7,
.cache_type = REGCACHE_RBTREE,
.volatile_reg = bq24257_is_volatile_reg,
};
static const struct reg_field bq24257_reg_fields[] = {
/* REG 1 */
[F_WD_FAULT] = REG_FIELD(BQ24257_REG_1, 7, 7),
[F_WD_EN] = REG_FIELD(BQ24257_REG_1, 6, 6),
[