1*8c0984e5SSebastian Reichel /* 2*8c0984e5SSebastian Reichel * TI BQ25890 charger driver 3*8c0984e5SSebastian Reichel * 4*8c0984e5SSebastian Reichel * Copyright (C) 2015 Intel Corporation 5*8c0984e5SSebastian Reichel * 6*8c0984e5SSebastian Reichel * This program is free software; you can redistribute it and/or modify 7*8c0984e5SSebastian Reichel * it under the terms of the GNU General Public License as published by 8*8c0984e5SSebastian Reichel * the Free Software Foundation; either version 2 of the License, or 9*8c0984e5SSebastian Reichel * (at your option) any later version. 10*8c0984e5SSebastian Reichel * 11*8c0984e5SSebastian Reichel * This program is distributed in the hope that it will be useful, 12*8c0984e5SSebastian Reichel * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*8c0984e5SSebastian Reichel * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*8c0984e5SSebastian Reichel * GNU General Public License for more details. 15*8c0984e5SSebastian Reichel * 16*8c0984e5SSebastian Reichel */ 17*8c0984e5SSebastian Reichel 18*8c0984e5SSebastian Reichel #include <linux/module.h> 19*8c0984e5SSebastian Reichel #include <linux/i2c.h> 20*8c0984e5SSebastian Reichel #include <linux/power_supply.h> 21*8c0984e5SSebastian Reichel #include <linux/regmap.h> 22*8c0984e5SSebastian Reichel #include <linux/types.h> 23*8c0984e5SSebastian Reichel #include <linux/gpio/consumer.h> 24*8c0984e5SSebastian Reichel #include <linux/interrupt.h> 25*8c0984e5SSebastian Reichel #include <linux/delay.h> 26*8c0984e5SSebastian Reichel #include <linux/usb/phy.h> 27*8c0984e5SSebastian Reichel 28*8c0984e5SSebastian Reichel #include <linux/acpi.h> 29*8c0984e5SSebastian Reichel #include <linux/of.h> 30*8c0984e5SSebastian Reichel 31*8c0984e5SSebastian Reichel #define BQ25890_MANUFACTURER "Texas Instruments" 32*8c0984e5SSebastian Reichel #define BQ25890_IRQ_PIN "bq25890_irq" 33*8c0984e5SSebastian Reichel 34*8c0984e5SSebastian Reichel #define BQ25890_ID 3 35*8c0984e5SSebastian Reichel 36*8c0984e5SSebastian Reichel enum bq25890_fields { 37*8c0984e5SSebastian Reichel F_EN_HIZ, F_EN_ILIM, F_IILIM, /* Reg00 */ 38*8c0984e5SSebastian Reichel F_BHOT, F_BCOLD, F_VINDPM_OFS, /* Reg01 */ 39*8c0984e5SSebastian Reichel F_CONV_START, F_CONV_RATE, F_BOOSTF, F_ICO_EN, 40*8c0984e5SSebastian Reichel F_HVDCP_EN, F_MAXC_EN, F_FORCE_DPM, F_AUTO_DPDM_EN, /* Reg02 */ 41*8c0984e5SSebastian Reichel F_BAT_LOAD_EN, F_WD_RST, F_OTG_CFG, F_CHG_CFG, F_SYSVMIN, /* Reg03 */ 42*8c0984e5SSebastian Reichel F_PUMPX_EN, F_ICHG, /* Reg04 */ 43*8c0984e5SSebastian Reichel F_IPRECHG, F_ITERM, /* Reg05 */ 44*8c0984e5SSebastian Reichel F_VREG, F_BATLOWV, F_VRECHG, /* Reg06 */ 45*8c0984e5SSebastian Reichel F_TERM_EN, F_STAT_DIS, F_WD, F_TMR_EN, F_CHG_TMR, 46*8c0984e5SSebastian Reichel F_JEITA_ISET, /* Reg07 */ 47*8c0984e5SSebastian Reichel F_BATCMP, F_VCLAMP, F_TREG, /* Reg08 */ 48*8c0984e5SSebastian Reichel F_FORCE_ICO, F_TMR2X_EN, F_BATFET_DIS, F_JEITA_VSET, 49*8c0984e5SSebastian Reichel F_BATFET_DLY, F_BATFET_RST_EN, F_PUMPX_UP, F_PUMPX_DN, /* Reg09 */ 50*8c0984e5SSebastian Reichel F_BOOSTV, F_BOOSTI, /* Reg0A */ 51*8c0984e5SSebastian Reichel F_VBUS_STAT, F_CHG_STAT, F_PG_STAT, F_SDP_STAT, F_VSYS_STAT, /* Reg0B */ 52*8c0984e5SSebastian Reichel F_WD_FAULT, F_BOOST_FAULT, F_CHG_FAULT, F_BAT_FAULT, 53*8c0984e5SSebastian Reichel F_NTC_FAULT, /* Reg0C */ 54*8c0984e5SSebastian Reichel F_FORCE_VINDPM, F_VINDPM, /* Reg0D */ 55*8c0984e5SSebastian Reichel F_THERM_STAT, F_BATV, /* Reg0E */ 56*8c0984e5SSebastian Reichel F_SYSV, /* Reg0F */ 57*8c0984e5SSebastian Reichel F_TSPCT, /* Reg10 */ 58*8c0984e5SSebastian Reichel F_VBUS_GD, F_VBUSV, /* Reg11 */ 59*8c0984e5SSebastian Reichel F_ICHGR, /* Reg12 */ 60*8c0984e5SSebastian Reichel F_VDPM_STAT, F_IDPM_STAT, F_IDPM_LIM, /* Reg13 */ 61*8c0984e5SSebastian Reichel F_REG_RST, F_ICO_OPTIMIZED, F_PN, F_TS_PROFILE, F_DEV_REV, /* Reg14 */ 62*8c0984e5SSebastian Reichel 63*8c0984e5SSebastian Reichel F_MAX_FIELDS 64*8c0984e5SSebastian Reichel }; 65*8c0984e5SSebastian Reichel 66*8c0984e5SSebastian Reichel /* initial field values, converted to register values */ 67*8c0984e5SSebastian Reichel struct bq25890_init_data { 68*8c0984e5SSebastian Reichel u8 ichg; /* charge current */ 69*8c0984e5SSebastian Reichel u8 vreg; /* regulation voltage */ 70*8c0984e5SSebastian Reichel u8 iterm; /* termination current */ 71*8c0984e5SSebastian Reichel u8 iprechg; /* precharge current */ 72*8c0984e5SSebastian Reichel u8 sysvmin; /* minimum system voltage limit */ 73*8c0984e5SSebastian Reichel u8 boostv; /* boost regulation voltage */ 74*8c0984e5SSebastian Reichel u8 boosti; /* boost current limit */ 75*8c0984e5SSebastian Reichel u8 boostf; /* boost frequency */ 76*8c0984e5SSebastian Reichel u8 ilim_en; /* enable ILIM pin */ 77*8c0984e5SSebastian Reichel u8 treg; /* thermal regulation threshold */ 78*8c0984e5SSebastian Reichel }; 79*8c0984e5SSebastian Reichel 80*8c0984e5SSebastian Reichel struct bq25890_state { 81*8c0984e5SSebastian Reichel u8 online; 82*8c0984e5SSebastian Reichel u8 chrg_status; 83*8c0984e5SSebastian Reichel u8 chrg_fault; 84*8c0984e5SSebastian Reichel u8 vsys_status; 85*8c0984e5SSebastian Reichel u8 boost_fault; 86*8c0984e5SSebastian Reichel u8 bat_fault; 87*8c0984e5SSebastian Reichel }; 88*8c0984e5SSebastian Reichel 89*8c0984e5SSebastian Reichel struct bq25890_device { 90*8c0984e5SSebastian Reichel struct i2c_client *client; 91*8c0984e5SSebastian Reichel struct device *dev; 92*8c0984e5SSebastian Reichel struct power_supply *charger; 93*8c0984e5SSebastian Reichel 94*8c0984e5SSebastian Reichel struct usb_phy *usb_phy; 95*8c0984e5SSebastian Reichel struct notifier_block usb_nb; 96*8c0984e5SSebastian Reichel struct work_struct usb_work; 97*8c0984e5SSebastian Reichel unsigned long usb_event; 98*8c0984e5SSebastian Reichel 99*8c0984e5SSebastian Reichel struct regmap *rmap; 100*8c0984e5SSebastian Reichel struct regmap_field *rmap_fields[F_MAX_FIELDS]; 101*8c0984e5SSebastian Reichel 102*8c0984e5SSebastian Reichel int chip_id; 103*8c0984e5SSebastian Reichel struct bq25890_init_data init_data; 104*8c0984e5SSebastian Reichel struct bq25890_state state; 105*8c0984e5SSebastian Reichel 106*8c0984e5SSebastian Reichel struct mutex lock; /* protect state data */ 107*8c0984e5SSebastian Reichel }; 108*8c0984e5SSebastian Reichel 109*8c0984e5SSebastian Reichel static const struct regmap_range bq25890_readonly_reg_ranges[] = { 110*8c0984e5SSebastian Reichel regmap_reg_range(0x0b, 0x0c), 111*8c0984e5SSebastian Reichel regmap_reg_range(0x0e, 0x13), 112*8c0984e5SSebastian Reichel }; 113*8c0984e5SSebastian Reichel 114*8c0984e5SSebastian Reichel static const struct regmap_access_table bq25890_writeable_regs = { 115*8c0984e5SSebastian Reichel .no_ranges = bq25890_readonly_reg_ranges, 116*8c0984e5SSebastian Reichel .n_no_ranges = ARRAY_SIZE(bq25890_readonly_reg_ranges), 117*8c0984e5SSebastian Reichel }; 118*8c0984e5SSebastian Reichel 119*8c0984e5SSebastian Reichel static const struct regmap_range bq25890_volatile_reg_ranges[] = { 120*8c0984e5SSebastian Reichel regmap_reg_range(0x00, 0x00), 121*8c0984e5SSebastian Reichel regmap_reg_range(0x09, 0x09), 122*8c0984e5SSebastian Reichel regmap_reg_range(0x0b, 0x0c), 123*8c0984e5SSebastian Reichel regmap_reg_range(0x0e, 0x14), 124*8c0984e5SSebastian Reichel }; 125*8c0984e5SSebastian Reichel 126*8c0984e5SSebastian Reichel static const struct regmap_access_table bq25890_volatile_regs = { 127*8c0984e5SSebastian Reichel .yes_ranges = bq25890_volatile_reg_ranges, 128*8c0984e5SSebastian Reichel .n_yes_ranges = ARRAY_SIZE(bq25890_volatile_reg_ranges), 129*8c0984e5SSebastian Reichel }; 130*8c0984e5SSebastian Reichel 131*8c0984e5SSebastian Reichel static const struct regmap_config bq25890_regmap_config = { 132*8c0984e5SSebastian Reichel .reg_bits = 8, 133*8c0984e5SSebastian Reichel .val_bits = 8, 134*8c0984e5SSebastian Reichel 135*8c0984e5SSebastian Reichel .max_register = 0x14, 136*8c0984e5SSebastian Reichel .cache_type = REGCACHE_RBTREE, 137*8c0984e5SSebastian Reichel 138*8c0984e5SSebastian Reichel .wr_table = &bq25890_writeable_regs, 139*8c0984e5SSebastian Reichel .volatile_table = &bq25890_volatile_regs, 140*8c0984e5SSebastian Reichel }; 141*8c0984e5SSebastian Reichel 142*8c0984e5SSebastian Reichel static const struct reg_field bq25890_reg_fields[] = { 143*8c0984e5SSebastian Reichel /* REG00 */ 144*8c0984e5SSebastian Reichel [F_EN_HIZ] = REG_FIELD(0x00, 7, 7), 145*8c0984e5SSebastian Reichel [F_EN_ILIM] = REG_FIELD(0x00, 6, 6), 146*8c0984e5SSebastian Reichel [F_IILIM] = REG_FIELD(0x00, 0, 5), 147*8c0984e5SSebastian Reichel /* REG01 */ 148*8c0984e5SSebastian Reichel [F_BHOT] = REG_FIELD(0x01, 6, 7), 149*8c0984e5SSebastian Reichel [F_BCOLD] = REG_FIELD(0x01, 5, 5), 150*8c0984e5SSebastian Reichel [F_VINDPM_OFS] = REG_FIELD(0x01, 0, 4), 151*8c0984e5SSebastian Reichel /* REG02 */ 152*8c0984e5SSebastian Reichel [F_CONV_START] = REG_FIELD(0x02, 7, 7), 153*8c0984e5SSebastian Reichel [F_CONV_RATE] = REG_FIELD(0x02, 6, 6), 154*8c0984e5SSebastian Reichel [F_BOOSTF] = REG_FIELD(0x02, 5, 5), 155*8c0984e5SSebastian Reichel [F_ICO_EN] = REG_FIELD(0x02, 4, 4), 156*8c0984e5SSebastian Reichel [F_HVDCP_EN] = REG_FIELD(0x02, 3, 3), 157*8c0984e5SSebastian Reichel [F_MAXC_EN] = REG_FIELD(0x02, 2, 2), 158*8c0984e5SSebastian Reichel [F_FORCE_DPM] = REG_FIELD(0x02, 1, 1), 159*8c0984e5SSebastian Reichel [F_AUTO_DPDM_EN] = REG_FIELD(0x02, 0, 0), 160*8c0984e5SSebastian Reichel /* REG03 */ 161*8c0984e5SSebastian Reichel [F_BAT_LOAD_EN] = REG_FIELD(0x03, 7, 7), 162*8c0984e5SSebastian Reichel [F_WD_RST] = REG_FIELD(0x03, 6, 6), 163*8c0984e5SSebastian Reichel [F_OTG_CFG] = REG_FIELD(0x03, 5, 5), 164*8c0984e5SSebastian Reichel [F_CHG_CFG] = REG_FIELD(0x03, 4, 4), 165*8c0984e5SSebastian Reichel [F_SYSVMIN] = REG_FIELD(0x03, 1, 3), 166*8c0984e5SSebastian Reichel /* REG04 */ 167*8c0984e5SSebastian Reichel [F_PUMPX_EN] = REG_FIELD(0x04, 7, 7), 168*8c0984e5SSebastian Reichel [F_ICHG] = REG_FIELD(0x04, 0, 6), 169*8c0984e5SSebastian Reichel /* REG05 */ 170*8c0984e5SSebastian Reichel [F_IPRECHG] = REG_FIELD(0x05, 4, 7), 171*8c0984e5SSebastian Reichel [F_ITERM] = REG_FIELD(0x05, 0, 3), 172*8c0984e5SSebastian Reichel /* REG06 */ 173*8c0984e5SSebastian Reichel [F_VREG] = REG_FIELD(0x06, 2, 7), 174*8c0984e5SSebastian Reichel [F_BATLOWV] = REG_FIELD(0x06, 1, 1), 175*8c0984e5SSebastian Reichel [F_VRECHG] = REG_FIELD(0x06, 0, 0), 176*8c0984e5SSebastian Reichel /* REG07 */ 177*8c0984e5SSebastian Reichel [F_TERM_EN] = REG_FIELD(0x07, 7, 7), 178*8c0984e5SSebastian Reichel [F_STAT_DIS] = REG_FIELD(0x07, 6, 6), 179*8c0984e5SSebastian Reichel [F_WD] = REG_FIELD(0x07, 4, 5), 180*8c0984e5SSebastian Reichel [F_TMR_EN] = REG_FIELD(0x07, 3, 3), 181*8c0984e5SSebastian Reichel [F_CHG_TMR] = REG_FIELD(0x07, 1, 2), 182*8c0984e5SSebastian Reichel [F_JEITA_ISET] = REG_FIELD(0x07, 0, 0), 183*8c0984e5SSebastian Reichel /* REG08 */ 184*8c0984e5SSebastian Reichel [F_BATCMP] = REG_FIELD(0x08, 6, 7), 185*8c0984e5SSebastian Reichel [F_VCLAMP] = REG_FIELD(0x08, 2, 4), 186*8c0984e5SSebastian Reichel [F_TREG] = REG_FIELD(0x08, 0, 1), 187*8c0984e5SSebastian Reichel /* REG09 */ 188*8c0984e5SSebastian Reichel [F_FORCE_ICO] = REG_FIELD(0x09, 7, 7), 189*8c0984e5SSebastian Reichel [F_TMR2X_EN] = REG_FIELD(0x09, 6, 6), 190*8c0984e5SSebastian Reichel [F_BATFET_DIS] = REG_FIELD(0x09, 5, 5), 191*8c0984e5SSebastian Reichel [F_JEITA_VSET] = REG_FIELD(0x09, 4, 4), 192*8c0984e5SSebastian Reichel [F_BATFET_DLY] = REG_FIELD(0x09, 3, 3), 193*8c0984e5SSebastian Reichel [F_BATFET_RST_EN] = REG_FIELD(0x09, 2, 2), 194*8c0984e5SSebastian Reichel [F_PUMPX_UP] = REG_FIELD(0x09, 1, 1), 195*8c0984e5SSebastian Reichel [F_PUMPX_DN] = REG_FIELD(0x09, 0, 0), 196*8c0984e5SSebastian Reichel /* REG0A */ 197*8c0984e5SSebastian Reichel [F_BOOSTV] = REG_FIELD(0x0A, 4, 7), 198*8c0984e5SSebastian Reichel [F_BOOSTI] = REG_FIELD(0x0A, 0, 2), 199*8c0984e5SSebastian Reichel /* REG0B */ 200*8c0984e5SSebastian Reichel [F_VBUS_STAT] = REG_FIELD(0x0B, 5, 7), 201*8c0984e5SSebastian Reichel [F_CHG_STAT] = REG_FIELD(0x0B, 3, 4), 202*8c0984e5SSebastian Reichel [F_PG_STAT] = REG_FIELD(0x0B, 2, 2), 203*8c0984e5SSebastian Reichel [F_SDP_STAT] = REG_FIELD(0x0B, 1, 1), 204*8c0984e5SSebastian Reichel [F_VSYS_STAT] = REG_FIELD(0x0B, 0, 0), 205*8c0984e5SSebastian Reichel /* REG0C */ 206*8c0984e5SSebastian Reichel [F_WD_FAULT] = REG_FIELD(0x0C, 7, 7), 207*8c0984e5SSebastian Reichel [F_BOOST_FAULT] = REG_FIELD(0x0C, 6, 6), 208*8c0984e5SSebastian Reichel [F_CHG_FAULT] = REG_FIELD(0x0C, 4, 5), 209*8c0984e5SSebastian Reichel [F_BAT_FAULT] = REG_FIELD(0x0C, 3, 3), 210*8c0984e5SSebastian Reichel [F_NTC_FAULT] = REG_FIELD(0x0C, 0, 2), 211*8c0984e5SSebastian Reichel /* REG0D */ 212*8c0984e5SSebastian Reichel [F_FORCE_VINDPM] = REG_FIELD(0x0D, 7, 7), 213*8c0984e5SSebastian Reichel [F_VINDPM] = REG_FIELD(0x0D, 0, 6), 214*8c0984e5SSebastian Reichel /* REG0E */ 215*8c0984e5SSebastian Reichel [F_THERM_STAT] = REG_FIELD(0x0E, 7, 7), 216*8c0984e5SSebastian Reichel [F_BATV] = REG_FIELD(0x0E, 0, 6), 217*8c0984e5SSebastian Reichel /* REG0F */ 218*8c0984e5SSebastian Reichel [F_SYSV] = REG_FIELD(0x0F, 0, 6), 219*8c0984e5SSebastian Reichel /* REG10 */ 220*8c0984e5SSebastian Reichel [F_TSPCT] = REG_FIELD(0x10, 0, 6), 221*8c0984e5SSebastian Reichel /* REG11 */ 222*8c0984e5SSebastian Reichel [F_VBUS_GD] = REG_FIELD(0x11, 7, 7), 223*8c0984e5SSebastian Reichel [F_VBUSV] = REG_FIELD(0x11, 0, 6), 224*8c0984e5SSebastian Reichel /* REG12 */ 225*8c0984e5SSebastian Reichel [F_ICHGR] = REG_FIELD(0x12, 0, 6), 226*8c0984e5SSebastian Reichel /* REG13 */ 227*8c0984e5SSebastian Reichel [F_VDPM_STAT] = REG_FIELD(0x13, 7, 7), 228*8c0984e5SSebastian Reichel [F_IDPM_STAT] = REG_FIELD(0x13, 6, 6), 229*8c0984e5SSebastian Reichel [F_IDPM_LIM] = REG_FIELD(0x13, 0, 5), 230*8c0984e5SSebastian Reichel /* REG14 */ 231*8c0984e5SSebastian Reichel [F_REG_RST] = REG_FIELD(0x14, 7, 7), 232*8c0984e5SSebastian Reichel [F_ICO_OPTIMIZED] = REG_FIELD(0x14, 6, 6), 233*8c0984e5SSebastian Reichel [F_PN] = REG_FIELD(0x14, 3, 5), 234*8c0984e5SSebastian Reichel [F_TS_PROFILE] = REG_FIELD(0x14, 2, 2), 235*8c0984e5SSebastian Reichel [F_DEV_REV] = REG_FIELD(0x14, 0, 1) 236*8c0984e5SSebastian Reichel }; 237*8c0984e5SSebastian Reichel 238*8c0984e5SSebastian Reichel /* 239*8c0984e5SSebastian Reichel * Most of the val -> idx conversions can be computed, given the minimum, 240*8c0984e5SSebastian Reichel * maximum and the step between values. For the rest of conversions, we use 241*8c0984e5SSebastian Reichel * lookup tables. 242*8c0984e5SSebastian Reichel */ 243*8c0984e5SSebastian Reichel enum bq25890_table_ids { 244*8c0984e5SSebastian Reichel /* range tables */ 245*8c0984e5SSebastian Reichel TBL_ICHG, 246*8c0984e5SSebastian Reichel TBL_ITERM, 247*8c0984e5SSebastian Reichel TBL_IPRECHG, 248*8c0984e5SSebastian Reichel TBL_VREG, 249*8c0984e5SSebastian Reichel TBL_BATCMP, 250*8c0984e5SSebastian Reichel TBL_VCLAMP, 251*8c0984e5SSebastian Reichel TBL_BOOSTV, 252*8c0984e5SSebastian Reichel TBL_SYSVMIN, 253*8c0984e5SSebastian Reichel 254*8c0984e5SSebastian Reichel /* lookup tables */ 255*8c0984e5SSebastian Reichel TBL_TREG, 256*8c0984e5SSebastian Reichel TBL_BOOSTI, 257*8c0984e5SSebastian Reichel }; 258*8c0984e5SSebastian Reichel 259*8c0984e5SSebastian Reichel /* Thermal Regulation Threshold lookup table, in degrees Celsius */ 260*8c0984e5SSebastian Reichel static const u32 bq25890_treg_tbl[] = { 60, 80, 100, 120 }; 261*8c0984e5SSebastian Reichel 262*8c0984e5SSebastian Reichel #define BQ25890_TREG_TBL_SIZE ARRAY_SIZE(bq25890_treg_tbl) 263*8c0984e5SSebastian Reichel 264*8c0984e5SSebastian Reichel /* Boost mode current limit lookup table, in uA */ 265*8c0984e5SSebastian Reichel static const u32 bq25890_boosti_tbl[] = { 266*8c0984e5SSebastian Reichel 500000, 700000, 1100000, 1300000, 1600000, 1800000, 2100000, 2400000 267*8c0984e5SSebastian Reichel }; 268*8c0984e5SSebastian Reichel 269*8c0984e5SSebastian Reichel #define BQ25890_BOOSTI_TBL_SIZE ARRAY_SIZE(bq25890_boosti_tbl) 270*8c0984e5SSebastian Reichel 271*8c0984e5SSebastian Reichel struct bq25890_range { 272*8c0984e5SSebastian Reichel u32 min; 273*8c0984e5SSebastian Reichel u32 max; 274*8c0984e5SSebastian Reichel u32 step; 275*8c0984e5SSebastian Reichel }; 276*8c0984e5SSebastian Reichel 277*8c0984e5SSebastian Reichel struct bq25890_lookup { 278*8c0984e5SSebastian Reichel const u32 *tbl; 279*8c0984e5SSebastian Reichel u32 size; 280*8c0984e5SSebastian Reichel }; 281*8c0984e5SSebastian Reichel 282*8c0984e5SSebastian Reichel static const union { 283*8c0984e5SSebastian Reichel struct bq25890_range rt; 284*8c0984e5SSebastian Reichel struct bq25890_lookup lt; 285*8c0984e5SSebastian Reichel } bq25890_tables[] = { 286*8c0984e5SSebastian Reichel /* range tables */ 287*8c0984e5SSebastian Reichel [TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */ 288*8c0984e5SSebastian Reichel [TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */ 289*8c0984e5SSebastian Reichel [TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */ 290*8c0984e5SSebastian Reichel [TBL_BATCMP] = { .rt = {0, 140, 20} }, /* mOhm */ 291*8c0984e5SSebastian Reichel [TBL_VCLAMP] = { .rt = {0, 224000, 32000} }, /* uV */ 292*8c0984e5SSebastian Reichel [TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */ 293*8c0984e5SSebastian Reichel [TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */ 294*8c0984e5SSebastian Reichel 295*8c0984e5SSebastian Reichel /* lookup tables */ 296*8c0984e5SSebastian Reichel [TBL_TREG] = { .lt = {bq25890_treg_tbl, BQ25890_TREG_TBL_SIZE} }, 297*8c0984e5SSebastian Reichel [TBL_BOOSTI] = { .lt = {bq25890_boosti_tbl, BQ25890_BOOSTI_TBL_SIZE} } 298*8c0984e5SSebastian Reichel }; 299*8c0984e5SSebastian Reichel 300*8c0984e5SSebastian Reichel static int bq25890_field_read(struct bq25890_device *bq, 301*8c0984e5SSebastian Reichel enum bq25890_fields field_id) 302*8c0984e5SSebastian Reichel { 303*8c0984e5SSebastian Reichel int ret; 304*8c0984e5SSebastian Reichel int val; 305*8c0984e5SSebastian Reichel 306*8c0984e5SSebastian Reichel ret = regmap_field_read(bq->rmap_fields[field_id], &val); 307*8c0984e5SSebastian Reichel if (ret < 0) 308*8c0984e5SSebastian Reichel return ret; 309*8c0984e5SSebastian Reichel 310*8c0984e5SSebastian Reichel return val; 311*8c0984e5SSebastian Reichel } 312*8c0984e5SSebastian Reichel 313*8c0984e5SSebastian Reichel static int bq25890_field_write(struct bq25890_device *bq, 314*8c0984e5SSebastian Reichel enum bq25890_fields field_id, u8 val) 315*8c0984e5SSebastian Reichel { 316*8c0984e5SSebastian Reichel return regmap_field_write(bq->rmap_fields[field_id], val); 317*8c0984e5SSebastian Reichel } 318*8c0984e5SSebastian Reichel 319*8c0984e5SSebastian Reichel static u8 bq25890_find_idx(u32 value, enum bq25890_table_ids id) 320*8c0984e5SSebastian Reichel { 321*8c0984e5SSebastian Reichel u8 idx; 322*8c0984e5SSebastian Reichel 323*8c0984e5SSebastian Reichel if (id >= TBL_TREG) { 324*8c0984e5SSebastian Reichel const u32 *tbl = bq25890_tables[id].lt.tbl; 325*8c0984e5SSebastian Reichel u32 tbl_size = bq25890_tables[id].lt.size; 326*8c0984e5SSebastian Reichel 327*8c0984e5SSebastian Reichel for (idx = 1; idx < tbl_size && tbl[idx] <= value; idx++) 328*8c0984e5SSebastian Reichel ; 329*8c0984e5SSebastian Reichel } else { 330*8c0984e5SSebastian Reichel const struct bq25890_range *rtbl = &bq25890_tables[id].rt; 331*8c0984e5SSebastian Reichel u8 rtbl_size; 332*8c0984e5SSebastian Reichel 333*8c0984e5SSebastian Reichel rtbl_size = (rtbl->max - rtbl->min) / rtbl->step + 1; 334*8c0984e5SSebastian Reichel 335*8c0984e5SSebastian Reichel for (idx = 1; 336*8c0984e5SSebastian Reichel idx < rtbl_size && (idx * rtbl->step + rtbl->min <= value); 337*8c0984e5SSebastian Reichel idx++) 338*8c0984e5SSebastian Reichel ; 339*8c0984e5SSebastian Reichel } 340*8c0984e5SSebastian Reichel 341*8c0984e5SSebastian Reichel return idx - 1; 342*8c0984e5SSebastian Reichel } 343*8c0984e5SSebastian Reichel 344*8c0984e5SSebastian Reichel static u32 bq25890_find_val(u8 idx, enum bq25890_table_ids id) 345*8c0984e5SSebastian Reichel { 346*8c0984e5SSebastian Reichel const struct bq25890_range *rtbl; 347*8c0984e5SSebastian Reichel 348*8c0984e5SSebastian Reichel /* lookup table? */ 349*8c0984e5SSebastian Reichel if (id >= TBL_TREG) 350*8c0984e5SSebastian Reichel return bq25890_tables[id].lt.tbl[idx]; 351*8c0984e5SSebastian Reichel 352*8c0984e5SSebastian Reichel /* range table */ 353*8c0984e5SSebastian Reichel rtbl = &bq25890_tables[id].rt; 354*8c0984e5SSebastian Reichel 355*8c0984e5SSebastian Reichel return (rtbl->min + idx * rtbl->step); 356*8c0984e5SSebastian Reichel } 357*8c0984e5SSebastian Reichel 358*8c0984e5SSebastian Reichel enum bq25890_status { 359*8c0984e5SSebastian Reichel STATUS_NOT_CHARGING, 360*8c0984e5SSebastian Reichel STATUS_PRE_CHARGING, 361*8c0984e5SSebastian Reichel STATUS_FAST_CHARGING, 362*8c0984e5SSebastian Reichel STATUS_TERMINATION_DONE, 363*8c0984e5SSebastian Reichel }; 364*8c0984e5SSebastian Reichel 365*8c0984e5SSebastian Reichel enum bq25890_chrg_fault { 366*8c0984e5SSebastian Reichel CHRG_FAULT_NORMAL, 367*8c0984e5SSebastian Reichel CHRG_FAULT_INPUT, 368*8c0984e5SSebastian Reichel CHRG_FAULT_THERMAL_SHUTDOWN, 369*8c0984e5SSebastian Reichel CHRG_FAULT_TIMER_EXPIRED, 370*8c0984e5SSebastian Reichel }; 371*8c0984e5SSebastian Reichel 372*8c0984e5SSebastian Reichel static int bq25890_power_supply_get_property(struct power_supply *psy, 373*8c0984e5SSebastian Reichel enum power_supply_property psp, 374*8c0984e5SSebastian Reichel union power_supply_propval *val) 375*8c0984e5SSebastian Reichel { 376*8c0984e5SSebastian Reichel int ret; 377*8c0984e5SSebastian Reichel struct bq25890_device *bq = power_supply_get_drvdata(psy); 378*8c0984e5SSebastian Reichel struct bq25890_state state; 379*8c0984e5SSebastian Reichel 380*8c0984e5SSebastian Reichel mutex_lock(&bq->lock); 381*8c0984e5SSebastian Reichel state = bq->state; 382*8c0984e5SSebastian Reichel mutex_unlock(&bq->lock); 383*8c0984e5SSebastian Reichel 384*8c0984e5SSebastian Reichel switch (psp) { 385*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_STATUS: 386*8c0984e5SSebastian Reichel if (!state.online) 387*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 388*8c0984e5SSebastian Reichel else if (state.chrg_status == STATUS_NOT_CHARGING) 389*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 390*8c0984e5SSebastian Reichel else if (state.chrg_status == STATUS_PRE_CHARGING || 391*8c0984e5SSebastian Reichel state.chrg_status == STATUS_FAST_CHARGING) 392*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_STATUS_CHARGING; 393*8c0984e5SSebastian Reichel else if (state.chrg_status == STATUS_TERMINATION_DONE) 394*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_STATUS_FULL; 395*8c0984e5SSebastian Reichel else 396*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_STATUS_UNKNOWN; 397*8c0984e5SSebastian Reichel 398*8c0984e5SSebastian Reichel break; 399*8c0984e5SSebastian Reichel 400*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_MANUFACTURER: 401*8c0984e5SSebastian Reichel val->strval = BQ25890_MANUFACTURER; 402*8c0984e5SSebastian Reichel break; 403*8c0984e5SSebastian Reichel 404*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_ONLINE: 405*8c0984e5SSebastian Reichel val->intval = state.online; 406*8c0984e5SSebastian Reichel break; 407*8c0984e5SSebastian Reichel 408*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_HEALTH: 409*8c0984e5SSebastian Reichel if (!state.chrg_fault && !state.bat_fault && !state.boost_fault) 410*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_GOOD; 411*8c0984e5SSebastian Reichel else if (state.bat_fault) 412*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 413*8c0984e5SSebastian Reichel else if (state.chrg_fault == CHRG_FAULT_TIMER_EXPIRED) 414*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; 415*8c0984e5SSebastian Reichel else if (state.chrg_fault == CHRG_FAULT_THERMAL_SHUTDOWN) 416*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 417*8c0984e5SSebastian Reichel else 418*8c0984e5SSebastian Reichel val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 419*8c0984e5SSebastian Reichel break; 420*8c0984e5SSebastian Reichel 421*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 422*8c0984e5SSebastian Reichel ret = bq25890_field_read(bq, F_ICHGR); /* read measured value */ 423*8c0984e5SSebastian Reichel if (ret < 0) 424*8c0984e5SSebastian Reichel return ret; 425*8c0984e5SSebastian Reichel 426*8c0984e5SSebastian Reichel /* converted_val = ADC_val * 50mA (table 10.3.19) */ 427*8c0984e5SSebastian Reichel val->intval = ret * 50000; 428*8c0984e5SSebastian Reichel break; 429*8c0984e5SSebastian Reichel 430*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 431*8c0984e5SSebastian Reichel val->intval = bq25890_tables[TBL_ICHG].rt.max; 432*8c0984e5SSebastian Reichel break; 433*8c0984e5SSebastian Reichel 434*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 435*8c0984e5SSebastian Reichel if (!state.online) { 436*8c0984e5SSebastian Reichel val->intval = 0; 437*8c0984e5SSebastian Reichel break; 438*8c0984e5SSebastian Reichel } 439*8c0984e5SSebastian Reichel 440*8c0984e5SSebastian Reichel ret = bq25890_field_read(bq, F_BATV); /* read measured value */ 441*8c0984e5SSebastian Reichel if (ret < 0) 442*8c0984e5SSebastian Reichel return ret; 443*8c0984e5SSebastian Reichel 444*8c0984e5SSebastian Reichel /* converted_val = 2.304V + ADC_val * 20mV (table 10.3.15) */ 445*8c0984e5SSebastian Reichel val->intval = 2304000 + ret * 20000; 446*8c0984e5SSebastian Reichel break; 447*8c0984e5SSebastian Reichel 448*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 449*8c0984e5SSebastian Reichel val->intval = bq25890_tables[TBL_VREG].rt.max; 450*8c0984e5SSebastian Reichel break; 451*8c0984e5SSebastian Reichel 452*8c0984e5SSebastian Reichel case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 453*8c0984e5SSebastian Reichel val->intval = bq25890_find_val(bq->init_data.iterm, TBL_ITERM); 454*8c0984e5SSebastian Reichel break; 455*8c0984e5SSebastian Reichel 456*8c0984e5SSebastian Reichel default: 457*8c0984e5SSebastian Reichel return -EINVAL; 458*8c0984e5SSebastian Reichel } 459*8c0984e5SSebastian Reichel 460*8c0984e5SSebastian Reichel return 0; 461*8c0984e5SSebastian Reichel } 462*8c0984e5SSebastian Reichel 463*8c0984e5SSebastian Reichel static int bq25890_get_chip_state(struct bq25890_device *bq, 464*8c0984e5SSebastian Reichel struct bq25890_state *state) 465*8c0984e5SSebastian Reichel { 466*8c0984e5SSebastian Reichel int i, ret; 467*8c0984e5SSebastian Reichel 468*8c0984e5SSebastian Reichel struct { 469*8c0984e5SSebastian Reichel enum bq25890_fields id; 470*8c0984e5SSebastian Reichel u8 *data; 471*8c0984e5SSebastian Reichel } state_fields[] = { 472*8c0984e5SSebastian Reichel {F_CHG_STAT, &state->chrg_status}, 473*8c0984e5SSebastian Reichel {F_PG_STAT, &state->online}, 474*8c0984e5SSebastian Reichel {F_VSYS_STAT, &state->vsys_status}, 475*8c0984e5SSebastian Reichel {F_BOOST_FAULT, &state->boost_fault}, 476*8c0984e5SSebastian Reichel {F_BAT_FAULT, &state->bat_fault}, 477*8c0984e5SSebastian Reichel {F_CHG_FAULT, &state->chrg_fault} 478*8c0984e5SSebastian Reichel }; 479*8c0984e5SSebastian Reichel 480*8c0984e5SSebastian Reichel for (i = 0; i < ARRAY_SIZE(state_fields); i++) { 481*8c0984e5SSebastian Reichel ret = bq25890_field_read(bq, state_fields[i].id); 482*8c0984e5SSebastian Reichel if (ret < 0) 483*8c0984e5SSebastian Reichel return ret; 484*8c0984e5SSebastian Reichel 485*8c0984e5SSebastian Reichel *state_fields[i].data = ret; 486*8c0984e5SSebastian Reichel } 487*8c0984e5SSebastian Reichel 488*8c0984e5SSebastian Reichel dev_dbg(bq->dev, "S:CHG/PG/VSYS=%d/%d/%d, F:CHG/BOOST/BAT=%d/%d/%d\n", 489*8c0984e5SSebastian Reichel state->chrg_status, state->online, state->vsys_status, 490*8c0984e5SSebastian Reichel state->chrg_fault, state->boost_fault, state->bat_fault); 491*8c0984e5SSebastian Reichel 492*8c0984e5SSebastian Reichel return 0; 493*8c0984e5SSebastian Reichel } 494*8c0984e5SSebastian Reichel 495*8c0984e5SSebastian Reichel static bool bq25890_state_changed(struct bq25890_device *bq, 496*8c0984e5SSebastian Reichel struct bq25890_state *new_state) 497*8c0984e5SSebastian Reichel { 498*8c0984e5SSebastian Reichel struct bq25890_state old_state; 499*8c0984e5SSebastian Reichel 500*8c0984e5SSebastian Reichel mutex_lock(&bq->lock); 501*8c0984e5SSebastian Reichel old_state = bq->state; 502*8c0984e5SSebastian Reichel mutex_unlock(&bq->lock); 503*8c0984e5SSebastian Reichel 504*8c0984e5SSebastian Reichel return (old_state.chrg_status != new_state->chrg_status || 505*8c0984e5SSebastian Reichel old_state.chrg_fault != new_state->chrg_fault || 506*8c0984e5SSebastian Reichel old_state.online != new_state->online || 507*8c0984e5SSebastian Reichel old_state.bat_fault != new_state->bat_fault || 508*8c0984e5SSebastian Reichel old_state.boost_fault != new_state->boost_fault || 509*8c0984e5SSebastian Reichel old_state.vsys_status != new_state->vsys_status); 510*8c0984e5SSebastian Reichel } 511*8c0984e5SSebastian Reichel 512*8c0984e5SSebastian Reichel static void bq25890_handle_state_change(struct bq25890_device *bq, 513*8c0984e5SSebastian Reichel struct bq25890_state *new_state) 514*8c0984e5SSebastian Reichel { 515*8c0984e5SSebastian Reichel int ret; 516*8c0984e5SSebastian Reichel struct bq25890_state old_state; 517*8c0984e5SSebastian Reichel 518*8c0984e5SSebastian Reichel mutex_lock(&bq->lock); 519*8c0984e5SSebastian Reichel old_state = bq->state; 520*8c0984e5SSebastian Reichel mutex_unlock(&bq->lock); 521*8c0984e5SSebastian Reichel 522*8c0984e5SSebastian Reichel if (!new_state->online) { /* power removed */ 523*8c0984e5SSebastian Reichel /* disable ADC */ 524*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, F_CONV_START, 0); 525*8c0984e5SSebastian Reichel if (ret < 0) 526*8c0984e5SSebastian Reichel goto error; 527*8c0984e5SSebastian Reichel } else if (!old_state.online) { /* power inserted */ 528*8c0984e5SSebastian Reichel /* enable ADC, to have control of charge current/voltage */ 529*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, F_CONV_START, 1); 530*8c0984e5SSebastian Reichel if (ret < 0) 531*8c0984e5SSebastian Reichel goto error; 532*8c0984e5SSebastian Reichel } 533*8c0984e5SSebastian Reichel 534*8c0984e5SSebastian Reichel return; 535*8c0984e5SSebastian Reichel 536*8c0984e5SSebastian Reichel error: 537*8c0984e5SSebastian Reichel dev_err(bq->dev, "Error communicating with the chip.\n"); 538*8c0984e5SSebastian Reichel } 539*8c0984e5SSebastian Reichel 540*8c0984e5SSebastian Reichel static irqreturn_t bq25890_irq_handler_thread(int irq, void *private) 541*8c0984e5SSebastian Reichel { 542*8c0984e5SSebastian Reichel struct bq25890_device *bq = private; 543*8c0984e5SSebastian Reichel int ret; 544*8c0984e5SSebastian Reichel struct bq25890_state state; 545*8c0984e5SSebastian Reichel 546*8c0984e5SSebastian Reichel ret = bq25890_get_chip_state(bq, &state); 547*8c0984e5SSebastian Reichel if (ret < 0) 548*8c0984e5SSebastian Reichel goto handled; 549*8c0984e5SSebastian Reichel 550*8c0984e5SSebastian Reichel if (!bq25890_state_changed(bq, &state)) 551*8c0984e5SSebastian Reichel goto handled; 552*8c0984e5SSebastian Reichel 553*8c0984e5SSebastian Reichel bq25890_handle_state_change(bq, &state); 554*8c0984e5SSebastian Reichel 555*8c0984e5SSebastian Reichel mutex_lock(&bq->lock); 556*8c0984e5SSebastian Reichel bq->state = state; 557*8c0984e5SSebastian Reichel mutex_unlock(&bq->lock); 558*8c0984e5SSebastian Reichel 559*8c0984e5SSebastian Reichel power_supply_changed(bq->charger); 560*8c0984e5SSebastian Reichel 561*8c0984e5SSebastian Reichel handled: 562*8c0984e5SSebastian Reichel return IRQ_HANDLED; 563*8c0984e5SSebastian Reichel } 564*8c0984e5SSebastian Reichel 565*8c0984e5SSebastian Reichel static int bq25890_chip_reset(struct bq25890_device *bq) 566*8c0984e5SSebastian Reichel { 567*8c0984e5SSebastian Reichel int ret; 568*8c0984e5SSebastian Reichel int rst_check_counter = 10; 569*8c0984e5SSebastian Reichel 570*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, F_REG_RST, 1); 571*8c0984e5SSebastian Reichel if (ret < 0) 572*8c0984e5SSebastian Reichel return ret; 573*8c0984e5SSebastian Reichel 574*8c0984e5SSebastian Reichel do { 575*8c0984e5SSebastian Reichel ret = bq25890_field_read(bq, F_REG_RST); 576*8c0984e5SSebastian Reichel if (ret < 0) 577*8c0984e5SSebastian Reichel return ret; 578*8c0984e5SSebastian Reichel 579*8c0984e5SSebastian Reichel usleep_range(5, 10); 580*8c0984e5SSebastian Reichel } while (ret == 1 && --rst_check_counter); 581*8c0984e5SSebastian Reichel 582*8c0984e5SSebastian Reichel if (!rst_check_counter) 583*8c0984e5SSebastian Reichel return -ETIMEDOUT; 584*8c0984e5SSebastian Reichel 585*8c0984e5SSebastian Reichel return 0; 586*8c0984e5SSebastian Reichel } 587*8c0984e5SSebastian Reichel 588*8c0984e5SSebastian Reichel static int bq25890_hw_init(struct bq25890_device *bq) 589*8c0984e5SSebastian Reichel { 590*8c0984e5SSebastian Reichel int ret; 591*8c0984e5SSebastian Reichel int i; 592*8c0984e5SSebastian Reichel struct bq25890_state state; 593*8c0984e5SSebastian Reichel 594*8c0984e5SSebastian Reichel const struct { 595*8c0984e5SSebastian Reichel enum bq25890_fields id; 596*8c0984e5SSebastian Reichel u32 value; 597*8c0984e5SSebastian Reichel } init_data[] = { 598*8c0984e5SSebastian Reichel {F_ICHG, bq->init_data.ichg}, 599*8c0984e5SSebastian Reichel {F_VREG, bq->init_data.vreg}, 600*8c0984e5SSebastian Reichel {F_ITERM, bq->init_data.iterm}, 601*8c0984e5SSebastian Reichel {F_IPRECHG, bq->init_data.iprechg}, 602*8c0984e5SSebastian Reichel {F_SYSVMIN, bq->init_data.sysvmin}, 603*8c0984e5SSebastian Reichel {F_BOOSTV, bq->init_data.boostv}, 604*8c0984e5SSebastian Reichel {F_BOOSTI, bq->init_data.boosti}, 605*8c0984e5SSebastian Reichel {F_BOOSTF, bq->init_data.boostf}, 606*8c0984e5SSebastian Reichel {F_EN_ILIM, bq->init_data.ilim_en}, 607*8c0984e5SSebastian Reichel {F_TREG, bq->init_data.treg} 608*8c0984e5SSebastian Reichel }; 609*8c0984e5SSebastian Reichel 610*8c0984e5SSebastian Reichel ret = bq25890_chip_reset(bq); 611*8c0984e5SSebastian Reichel if (ret < 0) 612*8c0984e5SSebastian Reichel return ret; 613*8c0984e5SSebastian Reichel 614*8c0984e5SSebastian Reichel /* disable watchdog */ 615*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, F_WD, 0); 616*8c0984e5SSebastian Reichel if (ret < 0) 617*8c0984e5SSebastian Reichel return ret; 618*8c0984e5SSebastian Reichel 619*8c0984e5SSebastian Reichel /* initialize currents/voltages and other parameters */ 620*8c0984e5SSebastian Reichel for (i = 0; i < ARRAY_SIZE(init_data); i++) { 621*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, init_data[i].id, 622*8c0984e5SSebastian Reichel init_data[i].value); 623*8c0984e5SSebastian Reichel if (ret < 0) 624*8c0984e5SSebastian Reichel return ret; 625*8c0984e5SSebastian Reichel } 626*8c0984e5SSebastian Reichel 627*8c0984e5SSebastian Reichel /* Configure ADC for continuous conversions. This does not enable it. */ 628*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, F_CONV_RATE, 1); 629*8c0984e5SSebastian Reichel if (ret < 0) 630*8c0984e5SSebastian Reichel return ret; 631*8c0984e5SSebastian Reichel 632*8c0984e5SSebastian Reichel ret = bq25890_get_chip_state(bq, &state); 633*8c0984e5SSebastian Reichel if (ret < 0) 634*8c0984e5SSebastian Reichel return ret; 635*8c0984e5SSebastian Reichel 636*8c0984e5SSebastian Reichel mutex_lock(&bq->lock); 637*8c0984e5SSebastian Reichel bq->state = state; 638*8c0984e5SSebastian Reichel mutex_unlock(&bq->lock); 639*8c0984e5SSebastian Reichel 640*8c0984e5SSebastian Reichel return 0; 641*8c0984e5SSebastian Reichel } 642*8c0984e5SSebastian Reichel 643*8c0984e5SSebastian Reichel static enum power_supply_property bq25890_power_supply_props[] = { 644*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_MANUFACTURER, 645*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_STATUS, 646*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_ONLINE, 647*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_HEALTH, 648*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 649*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 650*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 651*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 652*8c0984e5SSebastian Reichel POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, 653*8c0984e5SSebastian Reichel }; 654*8c0984e5SSebastian Reichel 655*8c0984e5SSebastian Reichel static char *bq25890_charger_supplied_to[] = { 656*8c0984e5SSebastian Reichel "main-battery", 657*8c0984e5SSebastian Reichel }; 658*8c0984e5SSebastian Reichel 659*8c0984e5SSebastian Reichel static const struct power_supply_desc bq25890_power_supply_desc = { 660*8c0984e5SSebastian Reichel .name = "bq25890-charger", 661*8c0984e5SSebastian Reichel .type = POWER_SUPPLY_TYPE_USB, 662*8c0984e5SSebastian Reichel .properties = bq25890_power_supply_props, 663*8c0984e5SSebastian Reichel .num_properties = ARRAY_SIZE(bq25890_power_supply_props), 664*8c0984e5SSebastian Reichel .get_property = bq25890_power_supply_get_property, 665*8c0984e5SSebastian Reichel }; 666*8c0984e5SSebastian Reichel 667*8c0984e5SSebastian Reichel static int bq25890_power_supply_init(struct bq25890_device *bq) 668*8c0984e5SSebastian Reichel { 669*8c0984e5SSebastian Reichel struct power_supply_config psy_cfg = { .drv_data = bq, }; 670*8c0984e5SSebastian Reichel 671*8c0984e5SSebastian Reichel psy_cfg.supplied_to = bq25890_charger_supplied_to; 672*8c0984e5SSebastian Reichel psy_cfg.num_supplicants = ARRAY_SIZE(bq25890_charger_supplied_to); 673*8c0984e5SSebastian Reichel 674*8c0984e5SSebastian Reichel bq->charger = power_supply_register(bq->dev, &bq25890_power_supply_desc, 675*8c0984e5SSebastian Reichel &psy_cfg); 676*8c0984e5SSebastian Reichel 677*8c0984e5SSebastian Reichel return PTR_ERR_OR_ZERO(bq->charger); 678*8c0984e5SSebastian Reichel } 679*8c0984e5SSebastian Reichel 680*8c0984e5SSebastian Reichel static void bq25890_usb_work(struct work_struct *data) 681*8c0984e5SSebastian Reichel { 682*8c0984e5SSebastian Reichel int ret; 683*8c0984e5SSebastian Reichel struct bq25890_device *bq = 684*8c0984e5SSebastian Reichel container_of(data, struct bq25890_device, usb_work); 685*8c0984e5SSebastian Reichel 686*8c0984e5SSebastian Reichel switch (bq->usb_event) { 687*8c0984e5SSebastian Reichel case USB_EVENT_ID: 688*8c0984e5SSebastian Reichel /* Enable boost mode */ 689*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, F_OTG_CFG, 1); 690*8c0984e5SSebastian Reichel if (ret < 0) 691*8c0984e5SSebastian Reichel goto error; 692*8c0984e5SSebastian Reichel break; 693*8c0984e5SSebastian Reichel 694*8c0984e5SSebastian Reichel case USB_EVENT_NONE: 695*8c0984e5SSebastian Reichel /* Disable boost mode */ 696*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, F_OTG_CFG, 0); 697*8c0984e5SSebastian Reichel if (ret < 0) 698*8c0984e5SSebastian Reichel goto error; 699*8c0984e5SSebastian Reichel 700*8c0984e5SSebastian Reichel power_supply_changed(bq->charger); 701*8c0984e5SSebastian Reichel break; 702*8c0984e5SSebastian Reichel } 703*8c0984e5SSebastian Reichel 704*8c0984e5SSebastian Reichel return; 705*8c0984e5SSebastian Reichel 706*8c0984e5SSebastian Reichel error: 707*8c0984e5SSebastian Reichel dev_err(bq->dev, "Error switching to boost/charger mode.\n"); 708*8c0984e5SSebastian Reichel } 709*8c0984e5SSebastian Reichel 710*8c0984e5SSebastian Reichel static int bq25890_usb_notifier(struct notifier_block *nb, unsigned long val, 711*8c0984e5SSebastian Reichel void *priv) 712*8c0984e5SSebastian Reichel { 713*8c0984e5SSebastian Reichel struct bq25890_device *bq = 714*8c0984e5SSebastian Reichel container_of(nb, struct bq25890_device, usb_nb); 715*8c0984e5SSebastian Reichel 716*8c0984e5SSebastian Reichel bq->usb_event = val; 717*8c0984e5SSebastian Reichel queue_work(system_power_efficient_wq, &bq->usb_work); 718*8c0984e5SSebastian Reichel 719*8c0984e5SSebastian Reichel return NOTIFY_OK; 720*8c0984e5SSebastian Reichel } 721*8c0984e5SSebastian Reichel 722*8c0984e5SSebastian Reichel static int bq25890_irq_probe(struct bq25890_device *bq) 723*8c0984e5SSebastian Reichel { 724*8c0984e5SSebastian Reichel struct gpio_desc *irq; 725*8c0984e5SSebastian Reichel 726*8c0984e5SSebastian Reichel irq = devm_gpiod_get_index(bq->dev, BQ25890_IRQ_PIN, 0, GPIOD_IN); 727*8c0984e5SSebastian Reichel if (IS_ERR(irq)) { 728*8c0984e5SSebastian Reichel dev_err(bq->dev, "Could not probe irq pin.\n"); 729*8c0984e5SSebastian Reichel return PTR_ERR(irq); 730*8c0984e5SSebastian Reichel } 731*8c0984e5SSebastian Reichel 732*8c0984e5SSebastian Reichel return gpiod_to_irq(irq); 733*8c0984e5SSebastian Reichel } 734*8c0984e5SSebastian Reichel 735*8c0984e5SSebastian Reichel static int bq25890_fw_read_u32_props(struct bq25890_device *bq) 736*8c0984e5SSebastian Reichel { 737*8c0984e5SSebastian Reichel int ret; 738*8c0984e5SSebastian Reichel u32 property; 739*8c0984e5SSebastian Reichel int i; 740*8c0984e5SSebastian Reichel struct bq25890_init_data *init = &bq->init_data; 741*8c0984e5SSebastian Reichel struct { 742*8c0984e5SSebastian Reichel char *name; 743*8c0984e5SSebastian Reichel bool optional; 744*8c0984e5SSebastian Reichel enum bq25890_table_ids tbl_id; 745*8c0984e5SSebastian Reichel u8 *conv_data; /* holds converted value from given property */ 746*8c0984e5SSebastian Reichel } props[] = { 747*8c0984e5SSebastian Reichel /* required properties */ 748*8c0984e5SSebastian Reichel {"ti,charge-current", false, TBL_ICHG, &init->ichg}, 749*8c0984e5SSebastian Reichel {"ti,battery-regulation-voltage", false, TBL_VREG, &init->vreg}, 750*8c0984e5SSebastian Reichel {"ti,termination-current", false, TBL_ITERM, &init->iterm}, 751*8c0984e5SSebastian Reichel {"ti,precharge-current", false, TBL_ITERM, &init->iprechg}, 752*8c0984e5SSebastian Reichel {"ti,minimum-sys-voltage", false, TBL_SYSVMIN, &init->sysvmin}, 753*8c0984e5SSebastian Reichel {"ti,boost-voltage", false, TBL_BOOSTV, &init->boostv}, 754*8c0984e5SSebastian Reichel {"ti,boost-max-current", false, TBL_BOOSTI, &init->boosti}, 755*8c0984e5SSebastian Reichel 756*8c0984e5SSebastian Reichel /* optional properties */ 757*8c0984e5SSebastian Reichel {"ti,thermal-regulation-threshold", true, TBL_TREG, &init->treg} 758*8c0984e5SSebastian Reichel }; 759*8c0984e5SSebastian Reichel 760*8c0984e5SSebastian Reichel /* initialize data for optional properties */ 761*8c0984e5SSebastian Reichel init->treg = 3; /* 120 degrees Celsius */ 762*8c0984e5SSebastian Reichel 763*8c0984e5SSebastian Reichel for (i = 0; i < ARRAY_SIZE(props); i++) { 764*8c0984e5SSebastian Reichel ret = device_property_read_u32(bq->dev, props[i].name, 765*8c0984e5SSebastian Reichel &property); 766*8c0984e5SSebastian Reichel if (ret < 0) { 767*8c0984e5SSebastian Reichel if (props[i].optional) 768*8c0984e5SSebastian Reichel continue; 769*8c0984e5SSebastian Reichel 770*8c0984e5SSebastian Reichel return ret; 771*8c0984e5SSebastian Reichel } 772*8c0984e5SSebastian Reichel 773*8c0984e5SSebastian Reichel *props[i].conv_data = bq25890_find_idx(property, 774*8c0984e5SSebastian Reichel props[i].tbl_id); 775*8c0984e5SSebastian Reichel } 776*8c0984e5SSebastian Reichel 777*8c0984e5SSebastian Reichel return 0; 778*8c0984e5SSebastian Reichel } 779*8c0984e5SSebastian Reichel 780*8c0984e5SSebastian Reichel static int bq25890_fw_probe(struct bq25890_device *bq) 781*8c0984e5SSebastian Reichel { 782*8c0984e5SSebastian Reichel int ret; 783*8c0984e5SSebastian Reichel struct bq25890_init_data *init = &bq->init_data; 784*8c0984e5SSebastian Reichel 785*8c0984e5SSebastian Reichel ret = bq25890_fw_read_u32_props(bq); 786*8c0984e5SSebastian Reichel if (ret < 0) 787*8c0984e5SSebastian Reichel return ret; 788*8c0984e5SSebastian Reichel 789*8c0984e5SSebastian Reichel init->ilim_en = device_property_read_bool(bq->dev, "ti,use-ilim-pin"); 790*8c0984e5SSebastian Reichel init->boostf = device_property_read_bool(bq->dev, "ti,boost-low-freq"); 791*8c0984e5SSebastian Reichel 792*8c0984e5SSebastian Reichel return 0; 793*8c0984e5SSebastian Reichel } 794*8c0984e5SSebastian Reichel 795*8c0984e5SSebastian Reichel static int bq25890_probe(struct i2c_client *client, 796*8c0984e5SSebastian Reichel const struct i2c_device_id *id) 797*8c0984e5SSebastian Reichel { 798*8c0984e5SSebastian Reichel struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 799*8c0984e5SSebastian Reichel struct device *dev = &client->dev; 800*8c0984e5SSebastian Reichel struct bq25890_device *bq; 801*8c0984e5SSebastian Reichel int ret; 802*8c0984e5SSebastian Reichel int i; 803*8c0984e5SSebastian Reichel 804*8c0984e5SSebastian Reichel if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 805*8c0984e5SSebastian Reichel dev_err(dev, "No support for SMBUS_BYTE_DATA\n"); 806*8c0984e5SSebastian Reichel return -ENODEV; 807*8c0984e5SSebastian Reichel } 808*8c0984e5SSebastian Reichel 809*8c0984e5SSebastian Reichel bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL); 810*8c0984e5SSebastian Reichel if (!bq) 811*8c0984e5SSebastian Reichel return -ENOMEM; 812*8c0984e5SSebastian Reichel 813*8c0984e5SSebastian Reichel bq->client = client; 814*8c0984e5SSebastian Reichel bq->dev = dev; 815*8c0984e5SSebastian Reichel 816*8c0984e5SSebastian Reichel mutex_init(&bq->lock); 817*8c0984e5SSebastian Reichel 818*8c0984e5SSebastian Reichel bq->rmap = devm_regmap_init_i2c(client, &bq25890_regmap_config); 819*8c0984e5SSebastian Reichel if (IS_ERR(bq->rmap)) { 820*8c0984e5SSebastian Reichel dev_err(dev, "failed to allocate register map\n"); 821*8c0984e5SSebastian Reichel return PTR_ERR(bq->rmap); 822*8c0984e5SSebastian Reichel } 823*8c0984e5SSebastian Reichel 824*8c0984e5SSebastian Reichel for (i = 0; i < ARRAY_SIZE(bq25890_reg_fields); i++) { 825*8c0984e5SSebastian Reichel const struct reg_field *reg_fields = bq25890_reg_fields; 826*8c0984e5SSebastian Reichel 827*8c0984e5SSebastian Reichel bq->rmap_fields[i] = devm_regmap_field_alloc(dev, bq->rmap, 828*8c0984e5SSebastian Reichel reg_fields[i]); 829*8c0984e5SSebastian Reichel if (IS_ERR(bq->rmap_fields[i])) { 830*8c0984e5SSebastian Reichel dev_err(dev, "cannot allocate regmap field\n"); 831*8c0984e5SSebastian Reichel return PTR_ERR(bq->rmap_fields[i]); 832*8c0984e5SSebastian Reichel } 833*8c0984e5SSebastian Reichel } 834*8c0984e5SSebastian Reichel 835*8c0984e5SSebastian Reichel i2c_set_clientdata(client, bq); 836*8c0984e5SSebastian Reichel 837*8c0984e5SSebastian Reichel bq->chip_id = bq25890_field_read(bq, F_PN); 838*8c0984e5SSebastian Reichel if (bq->chip_id < 0) { 839*8c0984e5SSebastian Reichel dev_err(dev, "Cannot read chip ID.\n"); 840*8c0984e5SSebastian Reichel return bq->chip_id; 841*8c0984e5SSebastian Reichel } 842*8c0984e5SSebastian Reichel 843*8c0984e5SSebastian Reichel if (bq->chip_id != BQ25890_ID) { 844*8c0984e5SSebastian Reichel dev_err(dev, "Chip with ID=%d, not supported!\n", bq->chip_id); 845*8c0984e5SSebastian Reichel return -ENODEV; 846*8c0984e5SSebastian Reichel } 847*8c0984e5SSebastian Reichel 848*8c0984e5SSebastian Reichel if (!dev->platform_data) { 849*8c0984e5SSebastian Reichel ret = bq25890_fw_probe(bq); 850*8c0984e5SSebastian Reichel if (ret < 0) { 851*8c0984e5SSebastian Reichel dev_err(dev, "Cannot read device properties.\n"); 852*8c0984e5SSebastian Reichel return ret; 853*8c0984e5SSebastian Reichel } 854*8c0984e5SSebastian Reichel } else { 855*8c0984e5SSebastian Reichel return -ENODEV; 856*8c0984e5SSebastian Reichel } 857*8c0984e5SSebastian Reichel 858*8c0984e5SSebastian Reichel ret = bq25890_hw_init(bq); 859*8c0984e5SSebastian Reichel if (ret < 0) { 860*8c0984e5SSebastian Reichel dev_err(dev, "Cannot initialize the chip.\n"); 861*8c0984e5SSebastian Reichel return ret; 862*8c0984e5SSebastian Reichel } 863*8c0984e5SSebastian Reichel 864*8c0984e5SSebastian Reichel if (client->irq <= 0) 865*8c0984e5SSebastian Reichel client->irq = bq25890_irq_probe(bq); 866*8c0984e5SSebastian Reichel 867*8c0984e5SSebastian Reichel if (client->irq < 0) { 868*8c0984e5SSebastian Reichel dev_err(dev, "No irq resource found.\n"); 869*8c0984e5SSebastian Reichel return client->irq; 870*8c0984e5SSebastian Reichel } 871*8c0984e5SSebastian Reichel 872*8c0984e5SSebastian Reichel /* OTG reporting */ 873*8c0984e5SSebastian Reichel bq->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 874*8c0984e5SSebastian Reichel if (!IS_ERR_OR_NULL(bq->usb_phy)) { 875*8c0984e5SSebastian Reichel INIT_WORK(&bq->usb_work, bq25890_usb_work); 876*8c0984e5SSebastian Reichel bq->usb_nb.notifier_call = bq25890_usb_notifier; 877*8c0984e5SSebastian Reichel usb_register_notifier(bq->usb_phy, &bq->usb_nb); 878*8c0984e5SSebastian Reichel } 879*8c0984e5SSebastian Reichel 880*8c0984e5SSebastian Reichel ret = devm_request_threaded_irq(dev, client->irq, NULL, 881*8c0984e5SSebastian Reichel bq25890_irq_handler_thread, 882*8c0984e5SSebastian Reichel IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 883*8c0984e5SSebastian Reichel BQ25890_IRQ_PIN, bq); 884*8c0984e5SSebastian Reichel if (ret) 885*8c0984e5SSebastian Reichel goto irq_fail; 886*8c0984e5SSebastian Reichel 887*8c0984e5SSebastian Reichel ret = bq25890_power_supply_init(bq); 888*8c0984e5SSebastian Reichel if (ret < 0) { 889*8c0984e5SSebastian Reichel dev_err(dev, "Failed to register power supply\n"); 890*8c0984e5SSebastian Reichel goto irq_fail; 891*8c0984e5SSebastian Reichel } 892*8c0984e5SSebastian Reichel 893*8c0984e5SSebastian Reichel return 0; 894*8c0984e5SSebastian Reichel 895*8c0984e5SSebastian Reichel irq_fail: 896*8c0984e5SSebastian Reichel if (!IS_ERR_OR_NULL(bq->usb_phy)) 897*8c0984e5SSebastian Reichel usb_unregister_notifier(bq->usb_phy, &bq->usb_nb); 898*8c0984e5SSebastian Reichel 899*8c0984e5SSebastian Reichel return ret; 900*8c0984e5SSebastian Reichel } 901*8c0984e5SSebastian Reichel 902*8c0984e5SSebastian Reichel static int bq25890_remove(struct i2c_client *client) 903*8c0984e5SSebastian Reichel { 904*8c0984e5SSebastian Reichel struct bq25890_device *bq = i2c_get_clientdata(client); 905*8c0984e5SSebastian Reichel 906*8c0984e5SSebastian Reichel power_supply_unregister(bq->charger); 907*8c0984e5SSebastian Reichel 908*8c0984e5SSebastian Reichel if (!IS_ERR_OR_NULL(bq->usb_phy)) 909*8c0984e5SSebastian Reichel usb_unregister_notifier(bq->usb_phy, &bq->usb_nb); 910*8c0984e5SSebastian Reichel 911*8c0984e5SSebastian Reichel /* reset all registers to default values */ 912*8c0984e5SSebastian Reichel bq25890_chip_reset(bq); 913*8c0984e5SSebastian Reichel 914*8c0984e5SSebastian Reichel return 0; 915*8c0984e5SSebastian Reichel } 916*8c0984e5SSebastian Reichel 917*8c0984e5SSebastian Reichel #ifdef CONFIG_PM_SLEEP 918*8c0984e5SSebastian Reichel static int bq25890_suspend(struct device *dev) 919*8c0984e5SSebastian Reichel { 920*8c0984e5SSebastian Reichel struct bq25890_device *bq = dev_get_drvdata(dev); 921*8c0984e5SSebastian Reichel 922*8c0984e5SSebastian Reichel /* 923*8c0984e5SSebastian Reichel * If charger is removed, while in suspend, make sure ADC is diabled 924*8c0984e5SSebastian Reichel * since it consumes slightly more power. 925*8c0984e5SSebastian Reichel */ 926*8c0984e5SSebastian Reichel return bq25890_field_write(bq, F_CONV_START, 0); 927*8c0984e5SSebastian Reichel } 928*8c0984e5SSebastian Reichel 929*8c0984e5SSebastian Reichel static int bq25890_resume(struct device *dev) 930*8c0984e5SSebastian Reichel { 931*8c0984e5SSebastian Reichel int ret; 932*8c0984e5SSebastian Reichel struct bq25890_state state; 933*8c0984e5SSebastian Reichel struct bq25890_device *bq = dev_get_drvdata(dev); 934*8c0984e5SSebastian Reichel 935*8c0984e5SSebastian Reichel ret = bq25890_get_chip_state(bq, &state); 936*8c0984e5SSebastian Reichel if (ret < 0) 937*8c0984e5SSebastian Reichel return ret; 938*8c0984e5SSebastian Reichel 939*8c0984e5SSebastian Reichel mutex_lock(&bq->lock); 940*8c0984e5SSebastian Reichel bq->state = state; 941*8c0984e5SSebastian Reichel mutex_unlock(&bq->lock); 942*8c0984e5SSebastian Reichel 943*8c0984e5SSebastian Reichel /* Re-enable ADC only if charger is plugged in. */ 944*8c0984e5SSebastian Reichel if (state.online) { 945*8c0984e5SSebastian Reichel ret = bq25890_field_write(bq, F_CONV_START, 1); 946*8c0984e5SSebastian Reichel if (ret < 0) 947*8c0984e5SSebastian Reichel return ret; 948*8c0984e5SSebastian Reichel } 949*8c0984e5SSebastian Reichel 950*8c0984e5SSebastian Reichel /* signal userspace, maybe state changed while suspended */ 951*8c0984e5SSebastian Reichel power_supply_changed(bq->charger); 952*8c0984e5SSebastian Reichel 953*8c0984e5SSebastian Reichel return 0; 954*8c0984e5SSebastian Reichel } 955*8c0984e5SSebastian Reichel #endif 956*8c0984e5SSebastian Reichel 957*8c0984e5SSebastian Reichel static const struct dev_pm_ops bq25890_pm = { 958*8c0984e5SSebastian Reichel SET_SYSTEM_SLEEP_PM_OPS(bq25890_suspend, bq25890_resume) 959*8c0984e5SSebastian Reichel }; 960*8c0984e5SSebastian Reichel 961*8c0984e5SSebastian Reichel static const struct i2c_device_id bq25890_i2c_ids[] = { 962*8c0984e5SSebastian Reichel { "bq25890", 0 }, 963*8c0984e5SSebastian Reichel {}, 964*8c0984e5SSebastian Reichel }; 965*8c0984e5SSebastian Reichel MODULE_DEVICE_TABLE(i2c, bq25890_i2c_ids); 966*8c0984e5SSebastian Reichel 967*8c0984e5SSebastian Reichel static const struct of_device_id bq25890_of_match[] = { 968*8c0984e5SSebastian Reichel { .compatible = "ti,bq25890", }, 969*8c0984e5SSebastian Reichel { }, 970*8c0984e5SSebastian Reichel }; 971*8c0984e5SSebastian Reichel MODULE_DEVICE_TABLE(of, bq25890_of_match); 972*8c0984e5SSebastian Reichel 973*8c0984e5SSebastian Reichel static const struct acpi_device_id bq25890_acpi_match[] = { 974*8c0984e5SSebastian Reichel {"BQ258900", 0}, 975*8c0984e5SSebastian Reichel {}, 976*8c0984e5SSebastian Reichel }; 977*8c0984e5SSebastian Reichel MODULE_DEVICE_TABLE(acpi, bq25890_acpi_match); 978*8c0984e5SSebastian Reichel 979*8c0984e5SSebastian Reichel static struct i2c_driver bq25890_driver = { 980*8c0984e5SSebastian Reichel .driver = { 981*8c0984e5SSebastian Reichel .name = "bq25890-charger", 982*8c0984e5SSebastian Reichel .of_match_table = of_match_ptr(bq25890_of_match), 983*8c0984e5SSebastian Reichel .acpi_match_table = ACPI_PTR(bq25890_acpi_match), 984*8c0984e5SSebastian Reichel .pm = &bq25890_pm, 985*8c0984e5SSebastian Reichel }, 986*8c0984e5SSebastian Reichel .probe = bq25890_probe, 987*8c0984e5SSebastian Reichel .remove = bq25890_remove, 988*8c0984e5SSebastian Reichel .id_table = bq25890_i2c_ids, 989*8c0984e5SSebastian Reichel }; 990*8c0984e5SSebastian Reichel module_i2c_driver(bq25890_driver); 991*8c0984e5SSebastian Reichel 992*8c0984e5SSebastian Reichel MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@intel.com>"); 993*8c0984e5SSebastian Reichel MODULE_DESCRIPTION("bq25890 charger driver"); 994*8c0984e5SSebastian Reichel MODULE_LICENSE("GPL"); 995