mfd: bq2415x charger driver
A message that is not in the archive (sent off-list or not yet received): "[email protected]"
cover mfd: bq2415x charger driver
From: Aliaksei Katovich <[email protected]>
The bq2415x family of Texas Instruments charger ICs are multifunctional chips that combine voltage/current regulation with Li-Ion battery charge controller.
Given bq2415x driver implements both regulator and i2c devices within single module. Despite not being mfd core dependant this driver however is thought to belong to mfd subsystem rather than regulators or i2c one.
Also I have some concern about hardcoded i2c addresses which may well limit driver usage to some certain hardware set. Alternatively driver can be extented to support device tree or another relevant interface to eliminate this possible limit.
Implementation is based on BQ24153/6/8 datasheet.
The patch set applies cleanly to the MFD repository atgit://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git
Please review.
Aliaksei Katovich (2):
mfd: bq2415x charger driver
mfd: bq2415x compilation enablers
drivers/mfd/Kconfig | 7 + drivers/mfd/Makefile | 1 + drivers/mfd/bq2415x.c | 780 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/bq2415x.h | 88 +++++ 4 files changed, 876 insertions(+), 0 deletions(-) create mode 100644 drivers/mfd/bq2415x.c create mode 100644 include/linux/mfd/bq2415x.h
PATCH 1/2 mfd: bq2415x charger driver
In reply to a message not in the archiveFrom: Aliaksei Katovich <[email protected]>
Added driver to support TI bq24153/6 one-cell Li-Ion chargers.
--- drivers/mfd/bq2415x.c | 780 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/bq2415x.h | 88 +++++ 2 files changed, 868 insertions(+), 0 deletions(-) create mode 100644 drivers/mfd/bq2415x.c create mode 100644 include/linux/mfd/bq2415x.h
drivers/mfd/bq2415x.c new file +780 -0
@@ -0,0 +1,780 @@ +/* +* bq2415x.c - TI BQ24153/6 one-cell Li-Ion charger driver +* +* Copyright (C) 2010 Nokia Corporation +* +* Contact: Aliaksei Katovich <[email protected]> +* +* This software is distributed under the terms of the GNU General +* Public License ("GPL") as published by the Free Software Foundation, +* version 2 of that License. +*/ + +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/kernel.h> +#include <linux/regulator/driver.h> +#include <linux/mfd/bq2415x.h> + +#define BQ2415X_RESET_MASK 0x80 + +#define BQ2415X_IIN_LIMIT_500_MASK 0x40 +#define BQ2415X_IIN_LIMIT_800_MASK 0x80 +#define BQ2415X_IIN_LIMIT_UNLIM_MASK 0xc0 + +static DEFINE_MUTEX (bq2415x_dev_list_mutex); +static LIST_HEAD (bq2415x_dev_list); + +static struct i2c_client *bq2415x_cli; + +struct bq2415x_regulator { +struct i2c_client *cli; +u8 reg;/* associated register */ +u8 val_summ;/* value summand */ +u8 msk_summ;/* bit mask summand */ +u8 msk_mult;/* bit mask multiplier */ +u8 min_mask; +u8 max_mask;/* read bitmask */ +struct regulator_init_data init; +struct regulator_desc desc; +}; + +struct bq2415x_device { +struct i2c_client *cli; +struct regulator_dev *rdev[BQ2415X_MAX_REG ]; +struct list_head list; +}; + +/* i2c operations */ + +static inline int bq2415x_i2c_read (struct i2c_client *cli,u8 reg) +{ +return i2c_smbus_read_byte_data (cli, reg); +} + +static inline int bq2415x_i2c_write (struct i2c_client *cli,u8 reg,u8 val) +{ +return i2c_smbus_write_byte_data (cli, reg, val); +} + +static inline int bq2415x_enable_charger (bool flag) +{ +int res; + + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_GEN_CTL ); +if (unlikely (res <0 )) +return res; + +if (flag) + res &= ~(BQ2415X_CE |BQ2415X_HZ_MODE ); +else + res |= (BQ2415X_CE |BQ2415X_HZ_MODE ); + +return bq2415x_i2c_write (bq2415x_cli,BQ2415X_GEN_CTL , res); +} + +static inline int bq2415x_enable_stat (bool flag) +{ +int res; + + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_STS_CTL ); +if (unlikely (res <0 )) +return res; + +if (flag) + res |=BQ2415X_EN_STAT ; +else + res &= ~BQ2415X_EN_STAT ; + +return bq2415x_i2c_write (bq2415x_cli,BQ2415X_STS_CTL , res); +} + +static inline int bq2415x_enable_otg (bool flag) +{ +int res; + + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_BAT_CTL ); +if (unlikely (res <0 )) +return res; + +if (flag) + res |=BQ2415X_OTG_EN ; +else + res &= ~BQ2415X_OTG_EN ; + +return bq2415x_i2c_write (bq2415x_cli,BQ2415X_STS_CTL , res); +} + +static inline int bq2415x_otg_high (bool flag) +{ +int res; + + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_BAT_CTL ); +if (unlikely (res <0 )) +return res; + +if (flag) + res |=BQ2415X_OTG_PL ; +else + res &= ~BQ2415X_OTG_PL ; + +return bq2415x_i2c_write (bq2415x_cli,BQ2415X_STS_CTL , res); +} + +static inline int bq2415x_chg_low (bool flag) +{ +int res; + + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_SPC_CTL ); +if (unlikely (res <0 )) +return res; + +if (flag) + res |=BQ2415X_LOW_CHG ; +else + res &= ~BQ2415X_LOW_CHG ; + +return bq2415x_i2c_write (bq2415x_cli,BQ2415X_SPC_CTL , res); +} + +/** +* bq2415x_exec - execute charger specific command +* +* Returns result of command execution upon success or negative otherwise +*/ +int bq2415x_exec (enum bq2415x_cmd cmd) +{ +int res; + +if (!bq2415x_cli) +return -ENODEV ; + +switch (cmd) { +case BQ2415X_ENABLE_CHARGER : + res =bq2415x_enable_charger (true); +break ; +case BQ2415X_DISABLE_CHARGER : + res =bq2415x_enable_charger (false); +break ; +case BQ2415X_READ_STATUS : + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_STS_CTL ); +break ; +case BQ2415X_RESET_CHARGER : + res =bq2415x_i2c_write (bq2415x_cli,BQ2415X_CHG_CTL , +BQ2415X_RESET_MASK ); +break ; +case BQ2415X_RESET_WATCHDOG : + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_STS_CTL ); +if (unlikely (res <0 )) +break ; + + res |=BQ2415X_TMR_RST ; + res =bq2415x_i2c_write (bq2415x_cli,BQ2415X_STS_CTL , res); +break ; +case BQ2415X_ENABLE_STAT : + res =bq2415x_enable_stat (true); +break ; +case BQ2415X_DISABLE_STAT : + res =bq2415x_enable_stat (false); +break ; +case BQ2415X_ENABLE_OTG : + res =bq2415x_enable_otg (true); +break ; +case BQ2415X_DISABLE_OTG : + res =bq2415x_enable_otg (false); +break ; +case BQ2415X_OTG_HIGH : + res =bq2415x_otg_high (true); +break ; +case BQ2415X_OTG_LOW : + res =bq2415x_otg_high (false); +break ; +case BQ2415X_CHG_LOW : + res =bq2415x_chg_low (true); +break ; +case BQ2415X_CHG_NORM : + res =bq2415x_chg_low (false); +break ; +case BQ2415X_READ_DPM : + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_SPC_CTL ); +if (res &BQ2415X_DPM_STATUS ) + res =1 ;/* DPM mode is active */ +else + res =0 ; +break ; +case BQ2415X_READ_CD : + res =bq2415x_i2c_read (bq2415x_cli,BQ2415X_SPC_CTL ); +if (res &BQ2415X_CD_STATUS ) + res =1 ;/* CD ping at HIGH level */ +else + res =0 ; +break ; +default : + res = -ENOSYS ; + } + +return res; +} +EXPORT_SYMBOL (bq2415x_exec); + +static inline int bq2415x_vmap_index (unsigned val,unsigned div) +{ +return (val / div) -1 ; +} + +static inline int bq2415x_vmap_calc (unsigned i,unsigned summ,unsigned mult) +{ +return (i + summ) * mult; +} + +/* regulator operations */ + +static int bq2415x_list_voltage (struct regulator_dev *rdev,unsigned i) +{ +struct bq2415x_regulator *r =rdev_get_drvdata (rdev); + +if (i >= r->desc.n_voltages) +return 0 ; + +return bq2415x_vmap_calc (i, r->val_summ, r->init.constraints.min_uV); +} + +static int +bq2415x_set_voltage (struct regulator_dev *rdev,int min_uV,int max_uV) +{ +int i, res; +struct bq2415x_regulator *r =rdev_get_drvdata (rdev); + + i =bq2415x_vmap_index (max_uV, r->init.constraints.min_uV); +if (i >= r->desc.n_voltages) +return -EINVAL ; + + res =bq2415x_i2c_read (r->cli, r->reg); +if (res <0 ) +return res; + + res |=bq2415x_vmap_calc (i, r->msk_summ, r->msk_mult); +return bq2415x_i2c_write (r->cli, r->reg, res); +} + +static int bq2415x_get_voltage (struct regulator_dev *rdev) +{ +int i, ret; +struct bq2415x_regulator *r =rdev_get_drvdata (rdev); + + ret =bq2415x_i2c_read (r->cli, r->reg); +if (ret <0 ) +return ret; + + i =bq2415x_vmap_index (ret & r->max_mask, r->min_mask); +if (i >= r->desc.n_voltages) +return -EINVAL ; + +return bq2415x_vmap_calc (i, r->val_summ, r->init.constraints.min_uV); +} + +static int +bq2415x_set_current_limit (struct regulator_dev *rdev,int min_uA,int max_uA) +{ +int res; +struct bq2415x_regulator *r =rdev_get_drvdata (rdev); + + res =bq2415x_i2c_read (r->cli, r->reg); +if (res <0 ) +return res; + +if (BQ2415X_IIN_LIMIT_100 <= min_uA && max_uA <BQ2415X_IIN_LIMIT_500 ) + res &= ~BQ2415X_IIN_LIMIT_UNLIM_MASK ; +else if (BQ2415X_IIN_LIMIT_500 <= min_uA && + max_uA <BQ2415X_IIN_LIMIT_800 ) + res |=BQ2415X_IIN_LIMIT_500_MASK ; +else if (BQ2415X_IIN_LIMIT_800 <= min_uA && + max_uA <BQ2415X_IIN_LIMIT_UNLIM ) + res |=BQ2415X_IIN_LIMIT_800_MASK ; +else if (BQ2415X_IIN_LIMIT_UNLIM <= min_uA) + res |=BQ2415X_IIN_LIMIT_UNLIM_MASK ; +else +return -EINVAL ; + +return bq2415x_i2c_write (r->cli, r->reg, res); +} + +static int bq2415x_get_current_limit (struct regulator_dev *rdev) +{ +int ret; +struct bq2415x_regulator *r =rdev_get_drvdata (rdev); + + ret =bq2415x_i2c_read (r->cli, r->reg); +if (ret <0 ) +return ret; + + ret &=BQ2415X_IIN_LIMIT_UNLIM_MASK ; +if (ret ==BQ2415X_IIN_LIMIT_UNLIM_MASK ) + ret =BQ2415X_IIN_LIMIT_UNLIM ; +else if (ret ==BQ2415X_IIN_LIMIT_500_MASK ) + ret =BQ2415X_IIN_LIMIT_500 ; +else if (ret ==BQ2415X_IIN_LIMIT_800_MASK ) + ret =BQ2415X_IIN_LIMIT_800 ; +else + ret =BQ2415X_IIN_LIMIT_100 ; + +return ret; +} + +static int bq2415x_v_iterm_enable (struct regulator_dev *rdev) +{ +int val; +struct bq2415x_regulator *r =rdev_get_drvdata (rdev); + + val =bq2415x_i2c_read (r->cli,BQ2415X_GEN_CTL ); +if (val <0 ) +return val; + + val |=BQ2415X_TE ; +return bq2415x_i2c_write (r->cli,BQ2415X_GEN_CTL , val); +} + +static int bq2415x_v_iterm_disable (struct regulator_dev *rdev) +{ +int val; +struct bq2415x_regulator *r =rdev_get_drvdata (rdev); + + val =bq2415x_i2c_read (r->cli,BQ2415X_GEN_CTL ); +if (val <0 ) +return val; + + val &= ~BQ2415X_TE ; +return bq2415x_i2c_write (r->cli,BQ2415X_GEN_CTL , val); +} + +static int bq2415x_v_iterm_is_enabled (struct regulator_dev *rdev) +{ +int val; +struct bq2415x_regulator *r =rdev_get_drvdata (rdev); + + val =bq2415x_i2c_read (r->cli,BQ2415X_GEN_CTL ); +if (val <0 ) +return val; + +return val &BQ2415X_TE ; +} + +/* regulator initialization */ + +static struct regulator_ops bq2415x_c_basic_ops = { + .set_current_limit = bq2415x_set_current_limit, + .get_current_limit = bq2415x_get_current_limit, +}; + +static struct regulator_ops bq2415x_v_basic_ops = { + .list_voltage = bq2415x_list_voltage, + .set_voltage = bq2415x_set_voltage, + .get_voltage = bq2415x_get_voltage, +}; + +static struct regulator_ops bq2415x_v_iterm_ops = { + .list_voltage = bq2415x_list_voltage, + .set_voltage = bq2415x_set_voltage, + .get_voltage = bq2415x_get_voltage, + .enable = bq2415x_v_iterm_enable, + .disable = bq2415x_v_iterm_disable, + .is_enabled = bq2415x_v_iterm_is_enabled, +}; + +static struct bq2415x_regulator bq2415x_regulator[] = { + [BQ2415X_V_LOWV ] = {/* weak battery voltage */ + .reg =BQ2415X_GEN_CTL , + .val_summ =1 , + .msk_summ =1 , + .msk_mult =16 , + .min_mask =0x10 , + .max_mask =0x30 , + .init.constraints = { + .name ="V_LOWV" , + .min_uV =100000 , + .max_uV =300000 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_VOLTAGE , + .always_on =1 , + .boot_on =1 , + }, + .desc = { + .name ="V_LOWV" , + .id =BQ2415X_V_LOWV , + .n_voltages =3 , + .ops = &bq2415x_v_basic_ops, + .type =REGULATOR_VOLTAGE , + .owner =THIS_MODULE , + }, + }, + [BQ2415X_V_OREG ] = {/* battery regulation */ + .reg =BQ2415X_BAT_CTL , + .val_summ =1 , + .msk_summ =1 , + .msk_mult =4 , + .min_mask =0x04 , + .max_mask =0xfc , + .init.constraints = { + .name ="V_OREG" , + .min_uV =20000 , + .max_uV =1260000 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_VOLTAGE , + .always_on =1 , + .boot_on =1 , + }, + .desc = { + .name ="V_OREG" , + .id =BQ2415X_V_OREG , + .n_voltages =63 , + .ops = &bq2415x_v_basic_ops, + .type =REGULATOR_VOLTAGE , + .owner =THIS_MODULE , + }, + }, + [BQ2415X_V_ICHRG_VAC ] = {/* charge current sense (USB) */ + .reg =BQ2415X_CHG_CTL , + .val_summ =1 , + .msk_summ =1 , + .msk_mult =8 , + .min_mask =0x08 , + .max_mask =0x78 , + .init.constraints = { + .name ="V_ICHRG_VAC" , + .min_uV =6800 , + .max_uV =102000 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_VOLTAGE , + .always_on =1 , + .boot_on =1 , + }, + .desc = { + .name ="V_ICHRG_VAC" , + .id =BQ2415X_V_ICHRG_VAC , + .n_voltages =15 , + .ops = &bq2415x_v_basic_ops, + .type =REGULATOR_VOLTAGE , + .owner =THIS_MODULE , + }, + }, + [BQ2415X_V_ICHRG_USB ] = {/* charge current sense (VAC) */ + .reg =BQ2415X_CHG_CTL , + .val_summ =1 , + .msk_summ =2 , + .msk_mult =8 , + .min_mask =0x10 , + .max_mask =0x40 , + .init.constraints = { + .name ="V_ICHRG_USB" , + .min_uV =6800 , + .max_uV =47600 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_VOLTAGE , + .always_on =1 , + .boot_on =1 , + }, + .desc = { + .name ="V_ICHRG_USB" , + .id =BQ2415X_V_ICHRG_USB , + .n_voltages =7 , + .ops = &bq2415x_v_basic_ops, + .type =REGULATOR_VOLTAGE , + .owner =THIS_MODULE , + }, + }, + [BQ2415X_V_ITERM ] = {/* termination current sense */ + .reg =BQ2415X_CHG_CTL , + .val_summ =1 , + .msk_summ =1 , + .msk_mult =1 , + .min_mask =0x01 , + .max_mask =0x07 , + .init.constraints = { + .name ="V_ITERM" , + .min_uV =3400 , + .max_uV =23800 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_VOLTAGE | +REGULATOR_CHANGE_STATUS , + .always_on =0 , + .boot_on =0 , + }, + .desc = { + .name ="V_ITERM" , + .id =BQ2415X_V_ITERM , + .n_voltages =7 , + .ops = &bq2415x_v_iterm_ops, + .type =REGULATOR_VOLTAGE , + .owner =THIS_MODULE , + }, + }, + [BQ2415X_V_SREG ] = {/* special charger */ + .reg =BQ2415X_SPC_CTL , + .val_summ =1 , + .msk_summ =1 , + .msk_mult =1 , + .min_mask =0x01 , + .max_mask =0x07 , + .init.constraints = { + .name ="V_SREG" , + .min_uV =80000 , + .max_uV =560000 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_VOLTAGE , + .always_on =1 , + .boot_on =1 , + }, + .desc = { + .name ="V_SREG" , + .id =BQ2415X_V_SREG , + .n_voltages =7 , + .ops = &bq2415x_v_basic_ops, + .type =REGULATOR_VOLTAGE , + .owner =THIS_MODULE , + }, + }, + [BQ2415X_V_MCHRG ] = {/* maximum charge current */ + .reg =BQ2415X_SFT_CTL , + .val_summ =1 , + .msk_summ =1 , + .msk_mult =16 , + .min_mask =0x10 , + .max_mask =0xf0 , + .init.constraints = { + .name ="V_MCHRG" , + .min_uV =6800 , + .max_uV =102000 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_VOLTAGE , + .always_on =1 , + .boot_on =1 , + }, + .desc = { + .name ="V_MCHRG" , + .id =BQ2415X_V_MCHRG , + .n_voltages =15 , + .ops = &bq2415x_v_basic_ops, + .type =REGULATOR_VOLTAGE , + .owner =THIS_MODULE , + }, + }, + [BQ2415X_V_MREG ] = {/* maximum battery regulation */ + .reg =BQ2415X_SFT_CTL , + .val_summ =1 , + .msk_summ =1 , + .msk_mult =1 , + .min_mask =0x01 , + .max_mask =0x0f , + .init.constraints = { + .name ="V_MREG" , + .min_uV =20000 , + .max_uV =300000 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_VOLTAGE , + .always_on =1 , + .boot_on =1 , + }, + .desc = { + .name ="V_MREG" , + .id =BQ2415X_V_MREG , + .n_voltages =15 , + .ops = &bq2415x_v_basic_ops, + .type =REGULATOR_VOLTAGE , + .owner =THIS_MODULE , + }, + }, + [BQ2415X_I_INLIMIT ] = {/* input current limit */ + .reg =BQ2415X_GEN_CTL , + .init.constraints = { + .name ="I_INLIMIT" , + .min_uA =100000 , + .max_uA =1500000 , + .valid_modes_mask =REGULATOR_MODE_NORMAL , + .valid_ops_mask =REGULATOR_CHANGE_CURRENT , + .always_on =1 , + .boot_on =1 , + }, + .desc = { + .name ="I_INLIMIT" , + .id =BQ2415X_I_INLIMIT , + .n_voltages =4 , + .ops = &bq2415x_c_basic_ops, + .type =REGULATOR_CURRENT , + .owner =THIS_MODULE , + }, + }, +}; + +static void __init bq2415x_add_consumers (struct bq2415x_regulator *r, +struct regulator_init_data *init) +{ +int i, j, n; +struct regulator_consumer_supply *cons; + +/* count my consumers */ +for (i =0 , n =0 ; i < init->num_consumer_supplies; i++) { +if (strcmp (init->consumer_supplies[i].supply, + r->init.constraints.name) ==0 ) + n++; + } + + cons =kzalloc (sizeof (*cons) * n,GFP_KERNEL ); +if (!cons) +return ; + +/* populate my consumers table */ +for (i =0 , j =0 ; i < init->num_consumer_supplies && j < n; i++) { +if (!init->consumer_supplies[i].supply) +continue ; +if (strcmp (init->consumer_supplies[i].supply, + r->init.constraints.name) !=0 ) +continue ; + + cons[j].supply = init->consumer_supplies[i].supply; + +if (init->consumer_supplies[i].dev) + cons[j].dev = init->consumer_supplies[i].dev; +if (init->consumer_supplies[i].dev_name) + cons[j].dev_name = init->consumer_supplies[i].dev_name; + + j++; + } + + r->init.num_consumer_supplies = n; + r->init.consumer_supplies = cons; +} + +static int __devinit bq2415x_regulator_init (struct bq2415x_device *bq) +{ +int i; +struct device *dev = &bq->cli->dev; +struct bq2415x_regulator *r; +struct regulator_dev *rdev; +struct regulator_init_data *init = dev->platform_data; + +for (i =0 ; i <ARRAY_SIZE (bq2415x_regulator); i++) { + r = &bq2415x_regulator[i]; + r->cli = bq->cli; + +if (init) +bq2415x_add_consumers (r, init); + + rdev =regulator_register (&r->desc, dev, &r->init, r); +if (IS_ERR (rdev)) +return PTR_ERR (rdev); + + bq->rdev[i] = rdev; + } + +return 0 ; +} + +/* driver initialization */ + +static struct bq2415x_device *bq2415x_getdev (struct i2c_client *cli) +{ +struct bq2415x_device *pos, *dev =0 ; + +mutex_lock (&bq2415x_dev_list_mutex); +list_for_each_entry (pos, &bq2415x_dev_list, list) { +if (pos->cli == cli || + (pos->cli->addr == cli->addr && + pos->cli->adapter == cli->adapter)) { + dev = pos; +break ; + } + } +mutex_unlock (&bq2415x_dev_list_mutex); +return dev; +} + +static int bq2415x_remove (struct i2c_client *cli) +{ +int i; +struct bq2415x_device *dev =bq2415x_getdev (cli); + +if (dev) { +for (i =0 ; i <ARRAY_SIZE (dev->rdev); i++) { +if (dev->rdev[i]) +regulator_unregister (dev->rdev[i]); + } + +mutex_lock (&bq2415x_dev_list_mutex); +list_del (&dev->list); +mutex_unlock (&bq2415x_dev_list_mutex); +kfree (dev); + } + +for (i =0 ; i <ARRAY_SIZE (bq2415x_regulator); i++) +kfree (bq2415x_regulator[i].init.consumer_supplies); + +return 0 ; +} + +static int __devinit +bq2415x_probe (struct i2c_client *cli,const struct i2c_device_id *id) +{ +int rc =0 ; +struct bq2415x_device *dev; + + bq2415x_cli = cli; + +if (i2c_check_functionality (cli->adapter,I2C_FUNC_I2C ) ==0 ) { +dev_dbg (&cli->dev,"i2c is not supported\n" ); +return -EIO ; + } + + dev =bq2415x_getdev (cli); +if (dev) +return -EBUSY ; + + dev =kzalloc (sizeof (*dev),GFP_KERNEL ); +if (!dev) +return -ENOMEM ; + + dev->cli = cli; + rc =bq2415x_regulator_init (dev); +if (rc <0 ) { +bq2415x_remove (cli); + }else { +mutex_lock (&bq2415x_dev_list_mutex); +list_add (&dev->list, &bq2415x_dev_list); +mutex_unlock (&bq2415x_dev_list_mutex); + } + +return rc; +} + +static const struct i2c_device_id bq2415x_id[] = { + {"bq24156" ,0 },/* VAC charger */ + {"bq24153" ,0 },/* USB charger */ + {}, +}; +MODULE_DEVICE_TABLE (i2c, bq2415x_id); + +static struct i2c_driver bq2415x_driver = { + .driver = { + .name ="bq2415x" , + .owner =THIS_MODULE , + }, + .id_table = bq2415x_id, + .probe = bq2415x_probe, + .remove = bq2415x_remove, +}; + +static int __init bq2415x_init (void ) +{ +return i2c_add_driver (&bq2415x_driver); +} +module_init (bq2415x_init); + +static void __exit bq2415x_exit(void) +{ +i2c_del_driver (&bq2415x_driver); +} +module_exit (bq2415x_exit); + +MODULE_AUTHOR ("Aliaksei Katovich <[email protected]>" ); +MODULE_DESCRIPTION ("TI BQ24153/6 one-cell Li-Ion charger driver" ); +MODULE_LICENSE ("GPL" );
include/linux/mfd/bq2415x.h new file +88 -0
88 lines not on this page · raw message
Signature · 1 line
1.7.0.4
PATCH 2/2 mfd: bq2415x compilation enablers
In reply to a message not in the archiveFrom: Aliaksei Katovich <[email protected]>
Enable compilation of bq2415x charger driver
--- drivers/mfd/Kconfig | 7 +++++++ drivers/mfd/Makefile | 1 + 2 files changed, 8 insertions(+), 0 deletions(-)
drivers/mfd/Kconfig +7 -0
@@ -624,6 +624,13 @@ config MFD_WL1273_CORE driver connects the radio-wl1273 V4L2 module and the wl1273 audio codec. +config MFD_BQ2415X + tristate "TI bq24153/6 one-cell Li-Ion charger IC" + depends on I2C && REGULATOR + help + This driver supports TI bq24153/6 integrated switch-mode chargers + attached to i2c. + endif # MFD_SUPPORT menu "Multimedia Capabilities Port drivers"
drivers/mfd/Makefile +1 -0
@@ -83,3 +83,4 @@ obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855) += vx855.o obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o +obj-$(CONFIG_MFD_BQ2415X) += bq2415x.o
Signature · 1 line
1.7.0.4