1*5bff79daSAndreas Kemnade // SPDX-License-Identifier: GPL-2.0-or-later 2*5bff79daSAndreas Kemnade /* ROHM BD71815, BD71828 and BD71878 Charger driver */ 3*5bff79daSAndreas Kemnade 4*5bff79daSAndreas Kemnade #include <linux/interrupt.h> 5*5bff79daSAndreas Kemnade #include <linux/kernel.h> 6*5bff79daSAndreas Kemnade #include <linux/mfd/rohm-bd71815.h> 7*5bff79daSAndreas Kemnade #include <linux/mfd/rohm-bd71828.h> 8*5bff79daSAndreas Kemnade #include <linux/module.h> 9*5bff79daSAndreas Kemnade #include <linux/mod_devicetable.h> 10*5bff79daSAndreas Kemnade #include <linux/platform_device.h> 11*5bff79daSAndreas Kemnade #include <linux/property.h> 12*5bff79daSAndreas Kemnade #include <linux/power_supply.h> 13*5bff79daSAndreas Kemnade #include <linux/slab.h> 14*5bff79daSAndreas Kemnade 15*5bff79daSAndreas Kemnade /* common defines */ 16*5bff79daSAndreas Kemnade #define BD7182x_MASK_VBAT_U 0x1f 17*5bff79daSAndreas Kemnade #define BD7182x_MASK_VDCIN_U 0x0f 18*5bff79daSAndreas Kemnade #define BD7182x_MASK_IBAT_U 0x3f 19*5bff79daSAndreas Kemnade #define BD7182x_MASK_CURDIR_DISCHG 0x80 20*5bff79daSAndreas Kemnade #define BD7182x_MASK_CHG_STATE 0x7f 21*5bff79daSAndreas Kemnade #define BD7182x_MASK_BAT_TEMP 0x07 22*5bff79daSAndreas Kemnade #define BD7182x_MASK_DCIN_DET BIT(0) 23*5bff79daSAndreas Kemnade #define BD7182x_MASK_CONF_PON BIT(0) 24*5bff79daSAndreas Kemnade #define BD71815_MASK_CONF_XSTB BIT(1) 25*5bff79daSAndreas Kemnade #define BD7182x_MASK_BAT_STAT 0x3f 26*5bff79daSAndreas Kemnade #define BD7182x_MASK_DCIN_STAT 0x07 27*5bff79daSAndreas Kemnade 28*5bff79daSAndreas Kemnade #define BD7182x_MASK_WDT_AUTO 0x40 29*5bff79daSAndreas Kemnade #define BD7182x_MASK_VBAT_ALM_LIMIT_U 0x01 30*5bff79daSAndreas Kemnade #define BD7182x_MASK_CHG_EN 0x01 31*5bff79daSAndreas Kemnade 32*5bff79daSAndreas Kemnade #define BD7182x_DCIN_COLLAPSE_DEFAULT 0x36 33*5bff79daSAndreas Kemnade 34*5bff79daSAndreas Kemnade #define MAX_CURRENT_DEFAULT 890000 /* uA */ 35*5bff79daSAndreas Kemnade #define AC_NAME "bd71828_ac" 36*5bff79daSAndreas Kemnade #define BAT_NAME "bd71828_bat" 37*5bff79daSAndreas Kemnade 38*5bff79daSAndreas Kemnade #define BAT_OPEN 0x7 39*5bff79daSAndreas Kemnade 40*5bff79daSAndreas Kemnade /* 41*5bff79daSAndreas Kemnade * VBAT Low voltage detection Threshold 42*5bff79daSAndreas Kemnade * 0x00D4*16mV = 212*0.016 = 3.392v 43*5bff79daSAndreas Kemnade */ 44*5bff79daSAndreas Kemnade #define VBAT_LOW_TH 0x00D4 45*5bff79daSAndreas Kemnade 46*5bff79daSAndreas Kemnade struct pwr_regs { 47*5bff79daSAndreas Kemnade u8 vbat_avg; 48*5bff79daSAndreas Kemnade u8 ibat; 49*5bff79daSAndreas Kemnade u8 ibat_avg; 50*5bff79daSAndreas Kemnade u8 btemp_vth; 51*5bff79daSAndreas Kemnade u8 chg_state; 52*5bff79daSAndreas Kemnade u8 bat_temp; 53*5bff79daSAndreas Kemnade u8 dcin_stat; 54*5bff79daSAndreas Kemnade u8 dcin_collapse_limit; 55*5bff79daSAndreas Kemnade u8 chg_set1; 56*5bff79daSAndreas Kemnade u8 chg_en; 57*5bff79daSAndreas Kemnade u8 vbat_alm_limit_u; 58*5bff79daSAndreas Kemnade u8 conf; 59*5bff79daSAndreas Kemnade u8 vdcin; 60*5bff79daSAndreas Kemnade }; 61*5bff79daSAndreas Kemnade 62*5bff79daSAndreas Kemnade static const struct pwr_regs pwr_regs_bd71828 = { 63*5bff79daSAndreas Kemnade .vbat_avg = BD71828_REG_VBAT_U, 64*5bff79daSAndreas Kemnade .ibat = BD71828_REG_IBAT_U, 65*5bff79daSAndreas Kemnade .ibat_avg = BD71828_REG_IBAT_AVG_U, 66*5bff79daSAndreas Kemnade .btemp_vth = BD71828_REG_VM_BTMP_U, 67*5bff79daSAndreas Kemnade .chg_state = BD71828_REG_CHG_STATE, 68*5bff79daSAndreas Kemnade .bat_temp = BD71828_REG_BAT_TEMP, 69*5bff79daSAndreas Kemnade .dcin_stat = BD71828_REG_DCIN_STAT, 70*5bff79daSAndreas Kemnade .dcin_collapse_limit = BD71828_REG_DCIN_CLPS, 71*5bff79daSAndreas Kemnade .chg_set1 = BD71828_REG_CHG_SET1, 72*5bff79daSAndreas Kemnade .chg_en = BD71828_REG_CHG_EN, 73*5bff79daSAndreas Kemnade .vbat_alm_limit_u = BD71828_REG_ALM_VBAT_LIMIT_U, 74*5bff79daSAndreas Kemnade .conf = BD71828_REG_CONF, 75*5bff79daSAndreas Kemnade .vdcin = BD71828_REG_VDCIN_U, 76*5bff79daSAndreas Kemnade }; 77*5bff79daSAndreas Kemnade 78*5bff79daSAndreas Kemnade static const struct pwr_regs pwr_regs_bd71815 = { 79*5bff79daSAndreas Kemnade .vbat_avg = BD71815_REG_VM_SA_VBAT_U, 80*5bff79daSAndreas Kemnade /* BD71815 does not have separate current and current avg */ 81*5bff79daSAndreas Kemnade .ibat = BD71815_REG_CC_CURCD_U, 82*5bff79daSAndreas Kemnade .ibat_avg = BD71815_REG_CC_CURCD_U, 83*5bff79daSAndreas Kemnade 84*5bff79daSAndreas Kemnade .btemp_vth = BD71815_REG_VM_BTMP, 85*5bff79daSAndreas Kemnade .chg_state = BD71815_REG_CHG_STATE, 86*5bff79daSAndreas Kemnade .bat_temp = BD71815_REG_BAT_TEMP, 87*5bff79daSAndreas Kemnade .dcin_stat = BD71815_REG_DCIN_STAT, 88*5bff79daSAndreas Kemnade .dcin_collapse_limit = BD71815_REG_DCIN_CLPS, 89*5bff79daSAndreas Kemnade .chg_set1 = BD71815_REG_CHG_SET1, 90*5bff79daSAndreas Kemnade .chg_en = BD71815_REG_CHG_SET1, 91*5bff79daSAndreas Kemnade .vbat_alm_limit_u = BD71815_REG_ALM_VBAT_TH_U, 92*5bff79daSAndreas Kemnade .conf = BD71815_REG_CONF, 93*5bff79daSAndreas Kemnade 94*5bff79daSAndreas Kemnade .vdcin = BD71815_REG_VM_DCIN_U, 95*5bff79daSAndreas Kemnade }; 96*5bff79daSAndreas Kemnade 97*5bff79daSAndreas Kemnade struct bd71828_power { 98*5bff79daSAndreas Kemnade struct regmap *regmap; 99*5bff79daSAndreas Kemnade enum rohm_chip_type chip_type; 100*5bff79daSAndreas Kemnade struct device *dev; 101*5bff79daSAndreas Kemnade struct power_supply *ac; 102*5bff79daSAndreas Kemnade struct power_supply *bat; 103*5bff79daSAndreas Kemnade 104*5bff79daSAndreas Kemnade const struct pwr_regs *regs; 105*5bff79daSAndreas Kemnade /* Reg val to uA */ 106*5bff79daSAndreas Kemnade int curr_factor; 107*5bff79daSAndreas Kemnade int rsens; 108*5bff79daSAndreas Kemnade int (*get_temp)(struct bd71828_power *pwr, int *temp); 109*5bff79daSAndreas Kemnade int (*bat_inserted)(struct bd71828_power *pwr); 110*5bff79daSAndreas Kemnade }; 111*5bff79daSAndreas Kemnade 112*5bff79daSAndreas Kemnade static int bd7182x_write16(struct bd71828_power *pwr, int reg, u16 val) 113*5bff79daSAndreas Kemnade { 114*5bff79daSAndreas Kemnade __be16 tmp; 115*5bff79daSAndreas Kemnade 116*5bff79daSAndreas Kemnade tmp = cpu_to_be16(val); 117*5bff79daSAndreas Kemnade 118*5bff79daSAndreas Kemnade return regmap_bulk_write(pwr->regmap, reg, &tmp, sizeof(tmp)); 119*5bff79daSAndreas Kemnade } 120*5bff79daSAndreas Kemnade 121*5bff79daSAndreas Kemnade static int bd7182x_read16_himask(struct bd71828_power *pwr, int reg, int himask, 122*5bff79daSAndreas Kemnade u16 *val) 123*5bff79daSAndreas Kemnade { 124*5bff79daSAndreas Kemnade struct regmap *regmap = pwr->regmap; 125*5bff79daSAndreas Kemnade int ret; 126*5bff79daSAndreas Kemnade __be16 rvals; 127*5bff79daSAndreas Kemnade u8 *tmp = (u8 *)&rvals; 128*5bff79daSAndreas Kemnade 129*5bff79daSAndreas Kemnade ret = regmap_bulk_read(regmap, reg, &rvals, sizeof(*val)); 130*5bff79daSAndreas Kemnade if (!ret) { 131*5bff79daSAndreas Kemnade *tmp &= himask; 132*5bff79daSAndreas Kemnade *val = be16_to_cpu(rvals); 133*5bff79daSAndreas Kemnade } 134*5bff79daSAndreas Kemnade 135*5bff79daSAndreas Kemnade return ret; 136*5bff79daSAndreas Kemnade } 137*5bff79daSAndreas Kemnade 138*5bff79daSAndreas Kemnade static int bd71828_get_vbat(struct bd71828_power *pwr, int *vcell) 139*5bff79daSAndreas Kemnade { 140*5bff79daSAndreas Kemnade u16 tmp_vcell; 141*5bff79daSAndreas Kemnade int ret; 142*5bff79daSAndreas Kemnade 143*5bff79daSAndreas Kemnade ret = bd7182x_read16_himask(pwr, pwr->regs->vbat_avg, 144*5bff79daSAndreas Kemnade BD7182x_MASK_VBAT_U, &tmp_vcell); 145*5bff79daSAndreas Kemnade if (ret) 146*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Failed to read battery average voltage\n"); 147*5bff79daSAndreas Kemnade else 148*5bff79daSAndreas Kemnade *vcell = ((int)tmp_vcell) * 1000; 149*5bff79daSAndreas Kemnade 150*5bff79daSAndreas Kemnade return ret; 151*5bff79daSAndreas Kemnade } 152*5bff79daSAndreas Kemnade 153*5bff79daSAndreas Kemnade static int bd71828_get_current_ds_adc(struct bd71828_power *pwr, int *curr, int *curr_avg) 154*5bff79daSAndreas Kemnade { 155*5bff79daSAndreas Kemnade __be16 tmp_curr; 156*5bff79daSAndreas Kemnade char *tmp = (char *)&tmp_curr; 157*5bff79daSAndreas Kemnade int dir = 1; 158*5bff79daSAndreas Kemnade int regs[] = { pwr->regs->ibat, pwr->regs->ibat_avg }; 159*5bff79daSAndreas Kemnade int *vals[] = { curr, curr_avg }; 160*5bff79daSAndreas Kemnade int ret, i; 161*5bff79daSAndreas Kemnade 162*5bff79daSAndreas Kemnade for (dir = 1, i = 0; i < ARRAY_SIZE(regs); i++) { 163*5bff79daSAndreas Kemnade ret = regmap_bulk_read(pwr->regmap, regs[i], &tmp_curr, 164*5bff79daSAndreas Kemnade sizeof(tmp_curr)); 165*5bff79daSAndreas Kemnade if (ret) 166*5bff79daSAndreas Kemnade break; 167*5bff79daSAndreas Kemnade 168*5bff79daSAndreas Kemnade if (*tmp & BD7182x_MASK_CURDIR_DISCHG) 169*5bff79daSAndreas Kemnade dir = -1; 170*5bff79daSAndreas Kemnade 171*5bff79daSAndreas Kemnade *tmp &= BD7182x_MASK_IBAT_U; 172*5bff79daSAndreas Kemnade 173*5bff79daSAndreas Kemnade *vals[i] = dir * ((int)be16_to_cpu(tmp_curr)) * pwr->curr_factor; 174*5bff79daSAndreas Kemnade } 175*5bff79daSAndreas Kemnade 176*5bff79daSAndreas Kemnade return ret; 177*5bff79daSAndreas Kemnade } 178*5bff79daSAndreas Kemnade 179*5bff79daSAndreas Kemnade /* Unit is tenths of degree C */ 180*5bff79daSAndreas Kemnade static int bd71815_get_temp(struct bd71828_power *pwr, int *temp) 181*5bff79daSAndreas Kemnade { 182*5bff79daSAndreas Kemnade struct regmap *regmap = pwr->regmap; 183*5bff79daSAndreas Kemnade int ret; 184*5bff79daSAndreas Kemnade int t; 185*5bff79daSAndreas Kemnade 186*5bff79daSAndreas Kemnade ret = regmap_read(regmap, pwr->regs->btemp_vth, &t); 187*5bff79daSAndreas Kemnade if (ret) 188*5bff79daSAndreas Kemnade return ret; 189*5bff79daSAndreas Kemnade 190*5bff79daSAndreas Kemnade t = 200 - t; 191*5bff79daSAndreas Kemnade 192*5bff79daSAndreas Kemnade if (t > 200) { 193*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Failed to read battery temperature\n"); 194*5bff79daSAndreas Kemnade return -ENODATA; 195*5bff79daSAndreas Kemnade } 196*5bff79daSAndreas Kemnade 197*5bff79daSAndreas Kemnade return 0; 198*5bff79daSAndreas Kemnade } 199*5bff79daSAndreas Kemnade 200*5bff79daSAndreas Kemnade /* Unit is tenths of degree C */ 201*5bff79daSAndreas Kemnade static int bd71828_get_temp(struct bd71828_power *pwr, int *temp) 202*5bff79daSAndreas Kemnade { 203*5bff79daSAndreas Kemnade u16 t; 204*5bff79daSAndreas Kemnade int ret; 205*5bff79daSAndreas Kemnade int tmp = 200 * 10000; 206*5bff79daSAndreas Kemnade 207*5bff79daSAndreas Kemnade ret = bd7182x_read16_himask(pwr, pwr->regs->btemp_vth, 208*5bff79daSAndreas Kemnade BD71828_MASK_VM_BTMP_U, &t); 209*5bff79daSAndreas Kemnade if (ret) 210*5bff79daSAndreas Kemnade return ret; 211*5bff79daSAndreas Kemnade 212*5bff79daSAndreas Kemnade if (t > 3200) { 213*5bff79daSAndreas Kemnade dev_err(pwr->dev, 214*5bff79daSAndreas Kemnade "Failed to read battery temperature\n"); 215*5bff79daSAndreas Kemnade return -ENODATA; 216*5bff79daSAndreas Kemnade } 217*5bff79daSAndreas Kemnade 218*5bff79daSAndreas Kemnade tmp -= 625ULL * (unsigned int)t; 219*5bff79daSAndreas Kemnade *temp = tmp / 1000; 220*5bff79daSAndreas Kemnade 221*5bff79daSAndreas Kemnade return ret; 222*5bff79daSAndreas Kemnade } 223*5bff79daSAndreas Kemnade 224*5bff79daSAndreas Kemnade static int bd71828_charge_status(struct bd71828_power *pwr, 225*5bff79daSAndreas Kemnade int *s, int *h) 226*5bff79daSAndreas Kemnade { 227*5bff79daSAndreas Kemnade unsigned int state; 228*5bff79daSAndreas Kemnade int status, health; 229*5bff79daSAndreas Kemnade int ret = 1; 230*5bff79daSAndreas Kemnade 231*5bff79daSAndreas Kemnade ret = regmap_read(pwr->regmap, pwr->regs->chg_state, &state); 232*5bff79daSAndreas Kemnade if (ret) { 233*5bff79daSAndreas Kemnade dev_err(pwr->dev, "charger status reading failed (%d)\n", ret); 234*5bff79daSAndreas Kemnade return ret; 235*5bff79daSAndreas Kemnade } 236*5bff79daSAndreas Kemnade 237*5bff79daSAndreas Kemnade state &= BD7182x_MASK_CHG_STATE; 238*5bff79daSAndreas Kemnade 239*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "CHG_STATE %d\n", state); 240*5bff79daSAndreas Kemnade 241*5bff79daSAndreas Kemnade switch (state) { 242*5bff79daSAndreas Kemnade case 0x00: 243*5bff79daSAndreas Kemnade status = POWER_SUPPLY_STATUS_DISCHARGING; 244*5bff79daSAndreas Kemnade health = POWER_SUPPLY_HEALTH_GOOD; 245*5bff79daSAndreas Kemnade break; 246*5bff79daSAndreas Kemnade case 0x01: 247*5bff79daSAndreas Kemnade case 0x02: 248*5bff79daSAndreas Kemnade case 0x03: 249*5bff79daSAndreas Kemnade case 0x0E: 250*5bff79daSAndreas Kemnade status = POWER_SUPPLY_STATUS_CHARGING; 251*5bff79daSAndreas Kemnade health = POWER_SUPPLY_HEALTH_GOOD; 252*5bff79daSAndreas Kemnade break; 253*5bff79daSAndreas Kemnade case 0x0F: 254*5bff79daSAndreas Kemnade status = POWER_SUPPLY_STATUS_FULL; 255*5bff79daSAndreas Kemnade health = POWER_SUPPLY_HEALTH_GOOD; 256*5bff79daSAndreas Kemnade break; 257*5bff79daSAndreas Kemnade case 0x10: 258*5bff79daSAndreas Kemnade case 0x11: 259*5bff79daSAndreas Kemnade case 0x12: 260*5bff79daSAndreas Kemnade case 0x13: 261*5bff79daSAndreas Kemnade case 0x14: 262*5bff79daSAndreas Kemnade case 0x20: 263*5bff79daSAndreas Kemnade case 0x21: 264*5bff79daSAndreas Kemnade case 0x22: 265*5bff79daSAndreas Kemnade case 0x23: 266*5bff79daSAndreas Kemnade case 0x24: 267*5bff79daSAndreas Kemnade status = POWER_SUPPLY_STATUS_NOT_CHARGING; 268*5bff79daSAndreas Kemnade health = POWER_SUPPLY_HEALTH_OVERHEAT; 269*5bff79daSAndreas Kemnade break; 270*5bff79daSAndreas Kemnade case 0x30: 271*5bff79daSAndreas Kemnade case 0x31: 272*5bff79daSAndreas Kemnade case 0x32: 273*5bff79daSAndreas Kemnade case 0x40: 274*5bff79daSAndreas Kemnade status = POWER_SUPPLY_STATUS_DISCHARGING; 275*5bff79daSAndreas Kemnade health = POWER_SUPPLY_HEALTH_GOOD; 276*5bff79daSAndreas Kemnade break; 277*5bff79daSAndreas Kemnade case 0x7f: 278*5bff79daSAndreas Kemnade default: 279*5bff79daSAndreas Kemnade status = POWER_SUPPLY_STATUS_NOT_CHARGING; 280*5bff79daSAndreas Kemnade health = POWER_SUPPLY_HEALTH_DEAD; 281*5bff79daSAndreas Kemnade break; 282*5bff79daSAndreas Kemnade } 283*5bff79daSAndreas Kemnade 284*5bff79daSAndreas Kemnade if (s) 285*5bff79daSAndreas Kemnade *s = status; 286*5bff79daSAndreas Kemnade if (h) 287*5bff79daSAndreas Kemnade *h = health; 288*5bff79daSAndreas Kemnade 289*5bff79daSAndreas Kemnade return ret; 290*5bff79daSAndreas Kemnade } 291*5bff79daSAndreas Kemnade 292*5bff79daSAndreas Kemnade static int get_chg_online(struct bd71828_power *pwr, int *chg_online) 293*5bff79daSAndreas Kemnade { 294*5bff79daSAndreas Kemnade int r, ret; 295*5bff79daSAndreas Kemnade 296*5bff79daSAndreas Kemnade ret = regmap_read(pwr->regmap, pwr->regs->dcin_stat, &r); 297*5bff79daSAndreas Kemnade if (ret) { 298*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Failed to read DCIN status\n"); 299*5bff79daSAndreas Kemnade return ret; 300*5bff79daSAndreas Kemnade } 301*5bff79daSAndreas Kemnade *chg_online = ((r & BD7182x_MASK_DCIN_DET) != 0); 302*5bff79daSAndreas Kemnade 303*5bff79daSAndreas Kemnade return 0; 304*5bff79daSAndreas Kemnade } 305*5bff79daSAndreas Kemnade 306*5bff79daSAndreas Kemnade static int get_bat_online(struct bd71828_power *pwr, int *bat_online) 307*5bff79daSAndreas Kemnade { 308*5bff79daSAndreas Kemnade int r, ret; 309*5bff79daSAndreas Kemnade 310*5bff79daSAndreas Kemnade ret = regmap_read(pwr->regmap, pwr->regs->bat_temp, &r); 311*5bff79daSAndreas Kemnade if (ret) { 312*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Failed to read battery temperature\n"); 313*5bff79daSAndreas Kemnade return ret; 314*5bff79daSAndreas Kemnade } 315*5bff79daSAndreas Kemnade *bat_online = ((r & BD7182x_MASK_BAT_TEMP) != BAT_OPEN); 316*5bff79daSAndreas Kemnade 317*5bff79daSAndreas Kemnade return 0; 318*5bff79daSAndreas Kemnade } 319*5bff79daSAndreas Kemnade 320*5bff79daSAndreas Kemnade static int bd71828_bat_inserted(struct bd71828_power *pwr) 321*5bff79daSAndreas Kemnade { 322*5bff79daSAndreas Kemnade int ret, val; 323*5bff79daSAndreas Kemnade 324*5bff79daSAndreas Kemnade ret = regmap_read(pwr->regmap, pwr->regs->conf, &val); 325*5bff79daSAndreas Kemnade if (ret) { 326*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Failed to read CONF register\n"); 327*5bff79daSAndreas Kemnade return 0; 328*5bff79daSAndreas Kemnade } 329*5bff79daSAndreas Kemnade ret = val & BD7182x_MASK_CONF_PON; 330*5bff79daSAndreas Kemnade 331*5bff79daSAndreas Kemnade if (ret) 332*5bff79daSAndreas Kemnade regmap_update_bits(pwr->regmap, pwr->regs->conf, 333*5bff79daSAndreas Kemnade BD7182x_MASK_CONF_PON, 0); 334*5bff79daSAndreas Kemnade 335*5bff79daSAndreas Kemnade return ret; 336*5bff79daSAndreas Kemnade } 337*5bff79daSAndreas Kemnade 338*5bff79daSAndreas Kemnade static int bd71815_bat_inserted(struct bd71828_power *pwr) 339*5bff79daSAndreas Kemnade { 340*5bff79daSAndreas Kemnade int ret, val; 341*5bff79daSAndreas Kemnade 342*5bff79daSAndreas Kemnade ret = regmap_read(pwr->regmap, pwr->regs->conf, &val); 343*5bff79daSAndreas Kemnade if (ret) { 344*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Failed to read CONF register\n"); 345*5bff79daSAndreas Kemnade return ret; 346*5bff79daSAndreas Kemnade } 347*5bff79daSAndreas Kemnade 348*5bff79daSAndreas Kemnade ret = !(val & BD71815_MASK_CONF_XSTB); 349*5bff79daSAndreas Kemnade if (ret) 350*5bff79daSAndreas Kemnade regmap_write(pwr->regmap, pwr->regs->conf, val | 351*5bff79daSAndreas Kemnade BD71815_MASK_CONF_XSTB); 352*5bff79daSAndreas Kemnade 353*5bff79daSAndreas Kemnade return ret; 354*5bff79daSAndreas Kemnade } 355*5bff79daSAndreas Kemnade 356*5bff79daSAndreas Kemnade static int bd71828_init_hardware(struct bd71828_power *pwr) 357*5bff79daSAndreas Kemnade { 358*5bff79daSAndreas Kemnade int ret; 359*5bff79daSAndreas Kemnade 360*5bff79daSAndreas Kemnade /* TODO: Collapse limit should come from device-tree ? */ 361*5bff79daSAndreas Kemnade ret = regmap_write(pwr->regmap, pwr->regs->dcin_collapse_limit, 362*5bff79daSAndreas Kemnade BD7182x_DCIN_COLLAPSE_DEFAULT); 363*5bff79daSAndreas Kemnade if (ret) { 364*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Failed to write DCIN collapse limit\n"); 365*5bff79daSAndreas Kemnade return ret; 366*5bff79daSAndreas Kemnade } 367*5bff79daSAndreas Kemnade 368*5bff79daSAndreas Kemnade ret = pwr->bat_inserted(pwr); 369*5bff79daSAndreas Kemnade if (ret < 0) 370*5bff79daSAndreas Kemnade return ret; 371*5bff79daSAndreas Kemnade 372*5bff79daSAndreas Kemnade if (ret) { 373*5bff79daSAndreas Kemnade /* WDT_FST auto set */ 374*5bff79daSAndreas Kemnade ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_set1, 375*5bff79daSAndreas Kemnade BD7182x_MASK_WDT_AUTO, 376*5bff79daSAndreas Kemnade BD7182x_MASK_WDT_AUTO); 377*5bff79daSAndreas Kemnade if (ret) 378*5bff79daSAndreas Kemnade return ret; 379*5bff79daSAndreas Kemnade 380*5bff79daSAndreas Kemnade ret = bd7182x_write16(pwr, pwr->regs->vbat_alm_limit_u, 381*5bff79daSAndreas Kemnade VBAT_LOW_TH); 382*5bff79daSAndreas Kemnade if (ret) 383*5bff79daSAndreas Kemnade return ret; 384*5bff79daSAndreas Kemnade 385*5bff79daSAndreas Kemnade /* 386*5bff79daSAndreas Kemnade * On BD71815 "we mask the power-state" from relax detection. 387*5bff79daSAndreas Kemnade * I am unsure what the impact of the power-state would be if 388*5bff79daSAndreas Kemnade * we didn't - but this is what the vendor driver did - and 389*5bff79daSAndreas Kemnade * that driver has been used in few projects so I just assume 390*5bff79daSAndreas Kemnade * this is needed. 391*5bff79daSAndreas Kemnade */ 392*5bff79daSAndreas Kemnade if (pwr->chip_type == ROHM_CHIP_TYPE_BD71815) { 393*5bff79daSAndreas Kemnade ret = regmap_set_bits(pwr->regmap, 394*5bff79daSAndreas Kemnade BD71815_REG_REX_CTRL_1, 395*5bff79daSAndreas Kemnade REX_PMU_STATE_MASK); 396*5bff79daSAndreas Kemnade if (ret) 397*5bff79daSAndreas Kemnade return ret; 398*5bff79daSAndreas Kemnade } 399*5bff79daSAndreas Kemnade } 400*5bff79daSAndreas Kemnade 401*5bff79daSAndreas Kemnade return 0; 402*5bff79daSAndreas Kemnade } 403*5bff79daSAndreas Kemnade 404*5bff79daSAndreas Kemnade static int bd71828_charger_get_property(struct power_supply *psy, 405*5bff79daSAndreas Kemnade enum power_supply_property psp, 406*5bff79daSAndreas Kemnade union power_supply_propval *val) 407*5bff79daSAndreas Kemnade { 408*5bff79daSAndreas Kemnade struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent); 409*5bff79daSAndreas Kemnade u32 vot; 410*5bff79daSAndreas Kemnade u16 tmp; 411*5bff79daSAndreas Kemnade int online; 412*5bff79daSAndreas Kemnade int ret; 413*5bff79daSAndreas Kemnade 414*5bff79daSAndreas Kemnade switch (psp) { 415*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_ONLINE: 416*5bff79daSAndreas Kemnade ret = get_chg_online(pwr, &online); 417*5bff79daSAndreas Kemnade if (!ret) 418*5bff79daSAndreas Kemnade val->intval = online; 419*5bff79daSAndreas Kemnade break; 420*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_VOLTAGE_NOW: 421*5bff79daSAndreas Kemnade ret = bd7182x_read16_himask(pwr, pwr->regs->vdcin, 422*5bff79daSAndreas Kemnade BD7182x_MASK_VDCIN_U, &tmp); 423*5bff79daSAndreas Kemnade if (ret) 424*5bff79daSAndreas Kemnade return ret; 425*5bff79daSAndreas Kemnade 426*5bff79daSAndreas Kemnade vot = tmp; 427*5bff79daSAndreas Kemnade /* 5 milli volt steps */ 428*5bff79daSAndreas Kemnade val->intval = 5000 * vot; 429*5bff79daSAndreas Kemnade break; 430*5bff79daSAndreas Kemnade default: 431*5bff79daSAndreas Kemnade return -EINVAL; 432*5bff79daSAndreas Kemnade } 433*5bff79daSAndreas Kemnade 434*5bff79daSAndreas Kemnade return 0; 435*5bff79daSAndreas Kemnade } 436*5bff79daSAndreas Kemnade 437*5bff79daSAndreas Kemnade static int bd71828_battery_get_property(struct power_supply *psy, 438*5bff79daSAndreas Kemnade enum power_supply_property psp, 439*5bff79daSAndreas Kemnade union power_supply_propval *val) 440*5bff79daSAndreas Kemnade { 441*5bff79daSAndreas Kemnade struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent); 442*5bff79daSAndreas Kemnade int ret = 0; 443*5bff79daSAndreas Kemnade int status, health, tmp, curr, curr_avg, chg_en; 444*5bff79daSAndreas Kemnade 445*5bff79daSAndreas Kemnade if (psp == POWER_SUPPLY_PROP_STATUS || 446*5bff79daSAndreas Kemnade psp == POWER_SUPPLY_PROP_HEALTH || 447*5bff79daSAndreas Kemnade psp == POWER_SUPPLY_PROP_CHARGE_TYPE) 448*5bff79daSAndreas Kemnade ret = bd71828_charge_status(pwr, &status, &health); 449*5bff79daSAndreas Kemnade else if (psp == POWER_SUPPLY_PROP_CURRENT_AVG || 450*5bff79daSAndreas Kemnade psp == POWER_SUPPLY_PROP_CURRENT_NOW) 451*5bff79daSAndreas Kemnade ret = bd71828_get_current_ds_adc(pwr, &curr, &curr_avg); 452*5bff79daSAndreas Kemnade if (ret) 453*5bff79daSAndreas Kemnade return ret; 454*5bff79daSAndreas Kemnade 455*5bff79daSAndreas Kemnade switch (psp) { 456*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_STATUS: 457*5bff79daSAndreas Kemnade val->intval = status; 458*5bff79daSAndreas Kemnade break; 459*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_HEALTH: 460*5bff79daSAndreas Kemnade val->intval = health; 461*5bff79daSAndreas Kemnade break; 462*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_PRESENT: 463*5bff79daSAndreas Kemnade ret = get_bat_online(pwr, &tmp); 464*5bff79daSAndreas Kemnade if (!ret) 465*5bff79daSAndreas Kemnade val->intval = tmp; 466*5bff79daSAndreas Kemnade break; 467*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_VOLTAGE_NOW: 468*5bff79daSAndreas Kemnade ret = bd71828_get_vbat(pwr, &tmp); 469*5bff79daSAndreas Kemnade val->intval = tmp; 470*5bff79daSAndreas Kemnade break; 471*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_TECHNOLOGY: 472*5bff79daSAndreas Kemnade val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 473*5bff79daSAndreas Kemnade break; 474*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_CURRENT_AVG: 475*5bff79daSAndreas Kemnade val->intval = curr_avg; 476*5bff79daSAndreas Kemnade break; 477*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_CURRENT_NOW: 478*5bff79daSAndreas Kemnade val->intval = curr; 479*5bff79daSAndreas Kemnade break; 480*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_CURRENT_MAX: 481*5bff79daSAndreas Kemnade val->intval = MAX_CURRENT_DEFAULT; 482*5bff79daSAndreas Kemnade break; 483*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_TEMP: 484*5bff79daSAndreas Kemnade ret = pwr->get_temp(pwr, &val->intval); 485*5bff79daSAndreas Kemnade break; 486*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 487*5bff79daSAndreas Kemnade ret = regmap_read(pwr->regmap, pwr->regs->chg_en, &chg_en); 488*5bff79daSAndreas Kemnade if (ret) 489*5bff79daSAndreas Kemnade return ret; 490*5bff79daSAndreas Kemnade 491*5bff79daSAndreas Kemnade val->intval = (chg_en & BD7182x_MASK_CHG_EN) ? 492*5bff79daSAndreas Kemnade POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO : 493*5bff79daSAndreas Kemnade POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE; 494*5bff79daSAndreas Kemnade break; 495*5bff79daSAndreas Kemnade default: 496*5bff79daSAndreas Kemnade ret = -EINVAL; 497*5bff79daSAndreas Kemnade break; 498*5bff79daSAndreas Kemnade } 499*5bff79daSAndreas Kemnade 500*5bff79daSAndreas Kemnade return ret; 501*5bff79daSAndreas Kemnade } 502*5bff79daSAndreas Kemnade 503*5bff79daSAndreas Kemnade static int bd71828_battery_set_property(struct power_supply *psy, 504*5bff79daSAndreas Kemnade enum power_supply_property psp, 505*5bff79daSAndreas Kemnade const union power_supply_propval *val) 506*5bff79daSAndreas Kemnade { 507*5bff79daSAndreas Kemnade struct bd71828_power *pwr = dev_get_drvdata(psy->dev.parent); 508*5bff79daSAndreas Kemnade int ret = 0; 509*5bff79daSAndreas Kemnade 510*5bff79daSAndreas Kemnade switch (psp) { 511*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 512*5bff79daSAndreas Kemnade if (val->intval == POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) 513*5bff79daSAndreas Kemnade ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_en, 514*5bff79daSAndreas Kemnade BD7182x_MASK_CHG_EN, 515*5bff79daSAndreas Kemnade BD7182x_MASK_CHG_EN); 516*5bff79daSAndreas Kemnade else 517*5bff79daSAndreas Kemnade ret = regmap_update_bits(pwr->regmap, pwr->regs->chg_en, 518*5bff79daSAndreas Kemnade BD7182x_MASK_CHG_EN, 519*5bff79daSAndreas Kemnade 0); 520*5bff79daSAndreas Kemnade break; 521*5bff79daSAndreas Kemnade default: 522*5bff79daSAndreas Kemnade return -EINVAL; 523*5bff79daSAndreas Kemnade } 524*5bff79daSAndreas Kemnade 525*5bff79daSAndreas Kemnade return ret; 526*5bff79daSAndreas Kemnade } 527*5bff79daSAndreas Kemnade 528*5bff79daSAndreas Kemnade static int bd71828_battery_property_is_writeable(struct power_supply *psy, 529*5bff79daSAndreas Kemnade enum power_supply_property psp) 530*5bff79daSAndreas Kemnade { 531*5bff79daSAndreas Kemnade switch (psp) { 532*5bff79daSAndreas Kemnade case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: 533*5bff79daSAndreas Kemnade return true; 534*5bff79daSAndreas Kemnade default: 535*5bff79daSAndreas Kemnade return false; 536*5bff79daSAndreas Kemnade } 537*5bff79daSAndreas Kemnade } 538*5bff79daSAndreas Kemnade 539*5bff79daSAndreas Kemnade /** @brief ac properties */ 540*5bff79daSAndreas Kemnade static const enum power_supply_property bd71828_charger_props[] = { 541*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_ONLINE, 542*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_VOLTAGE_NOW, 543*5bff79daSAndreas Kemnade }; 544*5bff79daSAndreas Kemnade 545*5bff79daSAndreas Kemnade static const enum power_supply_property bd71828_battery_props[] = { 546*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_STATUS, 547*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_HEALTH, 548*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_VOLTAGE_NOW, 549*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_HEALTH, 550*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_PRESENT, 551*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_TECHNOLOGY, 552*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_TEMP, 553*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_CURRENT_AVG, 554*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_CURRENT_NOW, 555*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_CURRENT_MAX, 556*5bff79daSAndreas Kemnade POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, 557*5bff79daSAndreas Kemnade }; 558*5bff79daSAndreas Kemnade 559*5bff79daSAndreas Kemnade /** @brief powers supplied by bd71828_ac */ 560*5bff79daSAndreas Kemnade static char *bd71828_ac_supplied_to[] = { 561*5bff79daSAndreas Kemnade BAT_NAME, 562*5bff79daSAndreas Kemnade }; 563*5bff79daSAndreas Kemnade 564*5bff79daSAndreas Kemnade static const struct power_supply_desc bd71828_ac_desc = { 565*5bff79daSAndreas Kemnade .name = AC_NAME, 566*5bff79daSAndreas Kemnade .type = POWER_SUPPLY_TYPE_MAINS, 567*5bff79daSAndreas Kemnade .properties = bd71828_charger_props, 568*5bff79daSAndreas Kemnade .num_properties = ARRAY_SIZE(bd71828_charger_props), 569*5bff79daSAndreas Kemnade .get_property = bd71828_charger_get_property, 570*5bff79daSAndreas Kemnade }; 571*5bff79daSAndreas Kemnade 572*5bff79daSAndreas Kemnade static const struct power_supply_desc bd71828_bat_desc = { 573*5bff79daSAndreas Kemnade .name = BAT_NAME, 574*5bff79daSAndreas Kemnade .type = POWER_SUPPLY_TYPE_BATTERY, 575*5bff79daSAndreas Kemnade .charge_behaviours = BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) | 576*5bff79daSAndreas Kemnade BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE), 577*5bff79daSAndreas Kemnade .properties = bd71828_battery_props, 578*5bff79daSAndreas Kemnade .num_properties = ARRAY_SIZE(bd71828_battery_props), 579*5bff79daSAndreas Kemnade .get_property = bd71828_battery_get_property, 580*5bff79daSAndreas Kemnade .set_property = bd71828_battery_set_property, 581*5bff79daSAndreas Kemnade .property_is_writeable = bd71828_battery_property_is_writeable, 582*5bff79daSAndreas Kemnade }; 583*5bff79daSAndreas Kemnade 584*5bff79daSAndreas Kemnade #define RSENS_CURR 10000000LLU 585*5bff79daSAndreas Kemnade 586*5bff79daSAndreas Kemnade #define BD_ISR_NAME(name) \ 587*5bff79daSAndreas Kemnade bd7181x_##name##_isr 588*5bff79daSAndreas Kemnade 589*5bff79daSAndreas Kemnade #define BD_ISR_BAT(name, print, run_gauge) \ 590*5bff79daSAndreas Kemnade static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ 591*5bff79daSAndreas Kemnade { \ 592*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; \ 593*5bff79daSAndreas Kemnade \ 594*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "%s\n", print); \ 595*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); \ 596*5bff79daSAndreas Kemnade \ 597*5bff79daSAndreas Kemnade return IRQ_HANDLED; \ 598*5bff79daSAndreas Kemnade } 599*5bff79daSAndreas Kemnade 600*5bff79daSAndreas Kemnade #define BD_ISR_AC(name, print, run_gauge) \ 601*5bff79daSAndreas Kemnade static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ 602*5bff79daSAndreas Kemnade { \ 603*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; \ 604*5bff79daSAndreas Kemnade \ 605*5bff79daSAndreas Kemnade power_supply_changed(pwr->ac); \ 606*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "%s\n", print); \ 607*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); \ 608*5bff79daSAndreas Kemnade \ 609*5bff79daSAndreas Kemnade return IRQ_HANDLED; \ 610*5bff79daSAndreas Kemnade } 611*5bff79daSAndreas Kemnade 612*5bff79daSAndreas Kemnade #define BD_ISR_DUMMY(name, print) \ 613*5bff79daSAndreas Kemnade static irqreturn_t BD_ISR_NAME(name)(int irq, void *data) \ 614*5bff79daSAndreas Kemnade { \ 615*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; \ 616*5bff79daSAndreas Kemnade \ 617*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "%s\n", print); \ 618*5bff79daSAndreas Kemnade \ 619*5bff79daSAndreas Kemnade return IRQ_HANDLED; \ 620*5bff79daSAndreas Kemnade } 621*5bff79daSAndreas Kemnade 622*5bff79daSAndreas Kemnade BD_ISR_BAT(chg_state_changed, "CHG state changed", true) 623*5bff79daSAndreas Kemnade /* DCIN voltage changes */ 624*5bff79daSAndreas Kemnade BD_ISR_AC(dcin_removed, "DCIN removed", true) 625*5bff79daSAndreas Kemnade BD_ISR_AC(clps_out, "DCIN voltage back to normal", true) 626*5bff79daSAndreas Kemnade BD_ISR_AC(clps_in, "DCIN voltage collapsed", false) 627*5bff79daSAndreas Kemnade BD_ISR_AC(dcin_ovp_res, "DCIN voltage normal", true) 628*5bff79daSAndreas Kemnade BD_ISR_AC(dcin_ovp_det, "DCIN OVER VOLTAGE", true) 629*5bff79daSAndreas Kemnade 630*5bff79daSAndreas Kemnade BD_ISR_DUMMY(dcin_mon_det, "DCIN voltage below threshold") 631*5bff79daSAndreas Kemnade BD_ISR_DUMMY(dcin_mon_res, "DCIN voltage above threshold") 632*5bff79daSAndreas Kemnade 633*5bff79daSAndreas Kemnade BD_ISR_DUMMY(vsys_uv_res, "VSYS under-voltage cleared") 634*5bff79daSAndreas Kemnade BD_ISR_DUMMY(vsys_uv_det, "VSYS under-voltage") 635*5bff79daSAndreas Kemnade BD_ISR_DUMMY(vsys_low_res, "'VSYS low' cleared") 636*5bff79daSAndreas Kemnade BD_ISR_DUMMY(vsys_low_det, "VSYS low") 637*5bff79daSAndreas Kemnade BD_ISR_DUMMY(vsys_mon_res, "VSYS mon - resumed") 638*5bff79daSAndreas Kemnade BD_ISR_DUMMY(vsys_mon_det, "VSYS mon - detected") 639*5bff79daSAndreas Kemnade BD_ISR_BAT(chg_wdg_temp, "charger temperature watchdog triggered", true) 640*5bff79daSAndreas Kemnade BD_ISR_BAT(chg_wdg, "charging watchdog triggered", true) 641*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_removed, "Battery removed", true) 642*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_det, "Battery detected", true) 643*5bff79daSAndreas Kemnade /* TODO: Verify the meaning of these interrupts */ 644*5bff79daSAndreas Kemnade BD_ISR_BAT(rechg_det, "Recharging", true) 645*5bff79daSAndreas Kemnade BD_ISR_BAT(rechg_res, "Recharge ending", true) 646*5bff79daSAndreas Kemnade BD_ISR_DUMMY(temp_transit, "Temperature transition") 647*5bff79daSAndreas Kemnade BD_ISR_BAT(therm_rmv, "bd71815-therm-rmv", false) 648*5bff79daSAndreas Kemnade BD_ISR_BAT(therm_det, "bd71815-therm-det", true) 649*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_dead, "bd71815-bat-dead", false) 650*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_short_res, "bd71815-bat-short-res", true) 651*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_short, "bd71815-bat-short-det", false) 652*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_low_res, "bd71815-bat-low-res", true) 653*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_low, "bd71815-bat-low-det", true) 654*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_ov_res, "bd71815-bat-over-res", true) 655*5bff79daSAndreas Kemnade /* What should we do here? */ 656*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_ov, "bd71815-bat-over-det", false) 657*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_mon_res, "bd71815-bat-mon-res", true) 658*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_mon, "bd71815-bat-mon-det", true) 659*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_cc_mon, "bd71815-bat-cc-mon2", false) 660*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_oc1_res, "bd71815-bat-oc1-res", true) 661*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_oc1, "bd71815-bat-oc1-det", false) 662*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_oc2_res, "bd71815-bat-oc2-res", true) 663*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_oc2, "bd71815-bat-oc2-det", false) 664*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_oc3_res, "bd71815-bat-oc3-res", true) 665*5bff79daSAndreas Kemnade BD_ISR_BAT(bat_oc3, "bd71815-bat-oc3-det", false) 666*5bff79daSAndreas Kemnade BD_ISR_BAT(temp_bat_low_res, "bd71815-temp-bat-low-res", true) 667*5bff79daSAndreas Kemnade BD_ISR_BAT(temp_bat_low, "bd71815-temp-bat-low-det", true) 668*5bff79daSAndreas Kemnade BD_ISR_BAT(temp_bat_hi_res, "bd71815-temp-bat-hi-res", true) 669*5bff79daSAndreas Kemnade BD_ISR_BAT(temp_bat_hi, "bd71815-temp-bat-hi-det", true) 670*5bff79daSAndreas Kemnade 671*5bff79daSAndreas Kemnade static irqreturn_t bd7182x_dcin_removed(int irq, void *data) 672*5bff79daSAndreas Kemnade { 673*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 674*5bff79daSAndreas Kemnade 675*5bff79daSAndreas Kemnade power_supply_changed(pwr->ac); 676*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "DCIN removed\n"); 677*5bff79daSAndreas Kemnade 678*5bff79daSAndreas Kemnade return IRQ_HANDLED; 679*5bff79daSAndreas Kemnade } 680*5bff79daSAndreas Kemnade 681*5bff79daSAndreas Kemnade static irqreturn_t bd718x7_chg_done(int irq, void *data) 682*5bff79daSAndreas Kemnade { 683*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 684*5bff79daSAndreas Kemnade 685*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 686*5bff79daSAndreas Kemnade 687*5bff79daSAndreas Kemnade return IRQ_HANDLED; 688*5bff79daSAndreas Kemnade } 689*5bff79daSAndreas Kemnade 690*5bff79daSAndreas Kemnade static irqreturn_t bd7182x_dcin_detected(int irq, void *data) 691*5bff79daSAndreas Kemnade { 692*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 693*5bff79daSAndreas Kemnade 694*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "DCIN inserted\n"); 695*5bff79daSAndreas Kemnade power_supply_changed(pwr->ac); 696*5bff79daSAndreas Kemnade 697*5bff79daSAndreas Kemnade return IRQ_HANDLED; 698*5bff79daSAndreas Kemnade } 699*5bff79daSAndreas Kemnade 700*5bff79daSAndreas Kemnade static irqreturn_t bd71828_vbat_low_res(int irq, void *data) 701*5bff79daSAndreas Kemnade { 702*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 703*5bff79daSAndreas Kemnade 704*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "VBAT LOW Resumed\n"); 705*5bff79daSAndreas Kemnade 706*5bff79daSAndreas Kemnade return IRQ_HANDLED; 707*5bff79daSAndreas Kemnade } 708*5bff79daSAndreas Kemnade 709*5bff79daSAndreas Kemnade static irqreturn_t bd71828_vbat_low_det(int irq, void *data) 710*5bff79daSAndreas Kemnade { 711*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 712*5bff79daSAndreas Kemnade 713*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "VBAT LOW Detected\n"); 714*5bff79daSAndreas Kemnade 715*5bff79daSAndreas Kemnade return IRQ_HANDLED; 716*5bff79daSAndreas Kemnade } 717*5bff79daSAndreas Kemnade 718*5bff79daSAndreas Kemnade static irqreturn_t bd71828_temp_bat_hi_det(int irq, void *data) 719*5bff79daSAndreas Kemnade { 720*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 721*5bff79daSAndreas Kemnade 722*5bff79daSAndreas Kemnade dev_warn(pwr->dev, "Overtemp Detected\n"); 723*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 724*5bff79daSAndreas Kemnade 725*5bff79daSAndreas Kemnade return IRQ_HANDLED; 726*5bff79daSAndreas Kemnade } 727*5bff79daSAndreas Kemnade 728*5bff79daSAndreas Kemnade static irqreturn_t bd71828_temp_bat_hi_res(int irq, void *data) 729*5bff79daSAndreas Kemnade { 730*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 731*5bff79daSAndreas Kemnade 732*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "Overtemp Resumed\n"); 733*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 734*5bff79daSAndreas Kemnade 735*5bff79daSAndreas Kemnade return IRQ_HANDLED; 736*5bff79daSAndreas Kemnade } 737*5bff79daSAndreas Kemnade 738*5bff79daSAndreas Kemnade static irqreturn_t bd71828_temp_bat_low_det(int irq, void *data) 739*5bff79daSAndreas Kemnade { 740*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 741*5bff79daSAndreas Kemnade 742*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "Lowtemp Detected\n"); 743*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 744*5bff79daSAndreas Kemnade 745*5bff79daSAndreas Kemnade return IRQ_HANDLED; 746*5bff79daSAndreas Kemnade } 747*5bff79daSAndreas Kemnade 748*5bff79daSAndreas Kemnade static irqreturn_t bd71828_temp_bat_low_res(int irq, void *data) 749*5bff79daSAndreas Kemnade { 750*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 751*5bff79daSAndreas Kemnade 752*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "Lowtemp Resumed\n"); 753*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 754*5bff79daSAndreas Kemnade 755*5bff79daSAndreas Kemnade return IRQ_HANDLED; 756*5bff79daSAndreas Kemnade } 757*5bff79daSAndreas Kemnade 758*5bff79daSAndreas Kemnade static irqreturn_t bd71828_temp_vf_det(int irq, void *data) 759*5bff79daSAndreas Kemnade { 760*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 761*5bff79daSAndreas Kemnade 762*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "VF Detected\n"); 763*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 764*5bff79daSAndreas Kemnade 765*5bff79daSAndreas Kemnade return IRQ_HANDLED; 766*5bff79daSAndreas Kemnade } 767*5bff79daSAndreas Kemnade 768*5bff79daSAndreas Kemnade static irqreturn_t bd71828_temp_vf_res(int irq, void *data) 769*5bff79daSAndreas Kemnade { 770*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 771*5bff79daSAndreas Kemnade 772*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "VF Resumed\n"); 773*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 774*5bff79daSAndreas Kemnade 775*5bff79daSAndreas Kemnade return IRQ_HANDLED; 776*5bff79daSAndreas Kemnade } 777*5bff79daSAndreas Kemnade 778*5bff79daSAndreas Kemnade static irqreturn_t bd71828_temp_vf125_det(int irq, void *data) 779*5bff79daSAndreas Kemnade { 780*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 781*5bff79daSAndreas Kemnade 782*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "VF125 Detected\n"); 783*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 784*5bff79daSAndreas Kemnade 785*5bff79daSAndreas Kemnade return IRQ_HANDLED; 786*5bff79daSAndreas Kemnade } 787*5bff79daSAndreas Kemnade 788*5bff79daSAndreas Kemnade static irqreturn_t bd71828_temp_vf125_res(int irq, void *data) 789*5bff79daSAndreas Kemnade { 790*5bff79daSAndreas Kemnade struct bd71828_power *pwr = (struct bd71828_power *)data; 791*5bff79daSAndreas Kemnade 792*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "VF125 Resumed\n"); 793*5bff79daSAndreas Kemnade power_supply_changed(pwr->bat); 794*5bff79daSAndreas Kemnade 795*5bff79daSAndreas Kemnade return IRQ_HANDLED; 796*5bff79daSAndreas Kemnade } 797*5bff79daSAndreas Kemnade 798*5bff79daSAndreas Kemnade struct bd7182x_irq_res { 799*5bff79daSAndreas Kemnade const char *name; 800*5bff79daSAndreas Kemnade irq_handler_t handler; 801*5bff79daSAndreas Kemnade }; 802*5bff79daSAndreas Kemnade 803*5bff79daSAndreas Kemnade #define BDIRQ(na, hn) { .name = (na), .handler = (hn) } 804*5bff79daSAndreas Kemnade 805*5bff79daSAndreas Kemnade static int bd7182x_get_irqs(struct platform_device *pdev, 806*5bff79daSAndreas Kemnade struct bd71828_power *pwr) 807*5bff79daSAndreas Kemnade { 808*5bff79daSAndreas Kemnade int i, irq, ret; 809*5bff79daSAndreas Kemnade static const struct bd7182x_irq_res bd71815_irqs[] = { 810*5bff79daSAndreas Kemnade BDIRQ("bd71815-dcin-rmv", BD_ISR_NAME(dcin_removed)), 811*5bff79daSAndreas Kemnade BDIRQ("bd71815-dcin-clps-out", BD_ISR_NAME(clps_out)), 812*5bff79daSAndreas Kemnade BDIRQ("bd71815-dcin-clps-in", BD_ISR_NAME(clps_in)), 813*5bff79daSAndreas Kemnade BDIRQ("bd71815-dcin-ovp-res", BD_ISR_NAME(dcin_ovp_res)), 814*5bff79daSAndreas Kemnade BDIRQ("bd71815-dcin-ovp-det", BD_ISR_NAME(dcin_ovp_det)), 815*5bff79daSAndreas Kemnade BDIRQ("bd71815-dcin-mon-res", BD_ISR_NAME(dcin_mon_res)), 816*5bff79daSAndreas Kemnade BDIRQ("bd71815-dcin-mon-det", BD_ISR_NAME(dcin_mon_det)), 817*5bff79daSAndreas Kemnade 818*5bff79daSAndreas Kemnade BDIRQ("bd71815-vsys-uv-res", BD_ISR_NAME(vsys_uv_res)), 819*5bff79daSAndreas Kemnade BDIRQ("bd71815-vsys-uv-det", BD_ISR_NAME(vsys_uv_det)), 820*5bff79daSAndreas Kemnade BDIRQ("bd71815-vsys-low-res", BD_ISR_NAME(vsys_low_res)), 821*5bff79daSAndreas Kemnade BDIRQ("bd71815-vsys-low-det", BD_ISR_NAME(vsys_low_det)), 822*5bff79daSAndreas Kemnade BDIRQ("bd71815-vsys-mon-res", BD_ISR_NAME(vsys_mon_res)), 823*5bff79daSAndreas Kemnade BDIRQ("bd71815-vsys-mon-det", BD_ISR_NAME(vsys_mon_det)), 824*5bff79daSAndreas Kemnade BDIRQ("bd71815-chg-wdg-temp", BD_ISR_NAME(chg_wdg_temp)), 825*5bff79daSAndreas Kemnade BDIRQ("bd71815-chg-wdg", BD_ISR_NAME(chg_wdg)), 826*5bff79daSAndreas Kemnade BDIRQ("bd71815-rechg-det", BD_ISR_NAME(rechg_det)), 827*5bff79daSAndreas Kemnade BDIRQ("bd71815-rechg-res", BD_ISR_NAME(rechg_res)), 828*5bff79daSAndreas Kemnade BDIRQ("bd71815-ranged-temp-transit", BD_ISR_NAME(temp_transit)), 829*5bff79daSAndreas Kemnade BDIRQ("bd71815-chg-state-change", BD_ISR_NAME(chg_state_changed)), 830*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-temp-normal", bd71828_temp_bat_hi_res), 831*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-temp-erange", bd71828_temp_bat_hi_det), 832*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-rmv", BD_ISR_NAME(bat_removed)), 833*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-det", BD_ISR_NAME(bat_det)), 834*5bff79daSAndreas Kemnade 835*5bff79daSAndreas Kemnade /* Add ISRs for these */ 836*5bff79daSAndreas Kemnade BDIRQ("bd71815-therm-rmv", BD_ISR_NAME(therm_rmv)), 837*5bff79daSAndreas Kemnade BDIRQ("bd71815-therm-det", BD_ISR_NAME(therm_det)), 838*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-dead", BD_ISR_NAME(bat_dead)), 839*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-short-res", BD_ISR_NAME(bat_short_res)), 840*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-short-det", BD_ISR_NAME(bat_short)), 841*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-low-res", BD_ISR_NAME(bat_low_res)), 842*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-low-det", BD_ISR_NAME(bat_low)), 843*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-over-res", BD_ISR_NAME(bat_ov_res)), 844*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-over-det", BD_ISR_NAME(bat_ov)), 845*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-mon-res", BD_ISR_NAME(bat_mon_res)), 846*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-mon-det", BD_ISR_NAME(bat_mon)), 847*5bff79daSAndreas Kemnade /* cc-mon 1 & 3 ? */ 848*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-cc-mon2", BD_ISR_NAME(bat_cc_mon)), 849*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-oc1-res", BD_ISR_NAME(bat_oc1_res)), 850*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-oc1-det", BD_ISR_NAME(bat_oc1)), 851*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-oc2-res", BD_ISR_NAME(bat_oc2_res)), 852*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-oc2-det", BD_ISR_NAME(bat_oc2)), 853*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-oc3-res", BD_ISR_NAME(bat_oc3_res)), 854*5bff79daSAndreas Kemnade BDIRQ("bd71815-bat-oc3-det", BD_ISR_NAME(bat_oc3)), 855*5bff79daSAndreas Kemnade BDIRQ("bd71815-temp-bat-low-res", BD_ISR_NAME(temp_bat_low_res)), 856*5bff79daSAndreas Kemnade BDIRQ("bd71815-temp-bat-low-det", BD_ISR_NAME(temp_bat_low)), 857*5bff79daSAndreas Kemnade BDIRQ("bd71815-temp-bat-hi-res", BD_ISR_NAME(temp_bat_hi_res)), 858*5bff79daSAndreas Kemnade BDIRQ("bd71815-temp-bat-hi-det", BD_ISR_NAME(temp_bat_hi)), 859*5bff79daSAndreas Kemnade /* 860*5bff79daSAndreas Kemnade * TODO: add rest of the IRQs and re-check the handling. 861*5bff79daSAndreas Kemnade * Check the bd71815-bat-cc-mon1, bd71815-bat-cc-mon3, 862*5bff79daSAndreas Kemnade * bd71815-bat-low-res, bd71815-bat-low-det, 863*5bff79daSAndreas Kemnade * bd71815-bat-hi-res, bd71815-bat-hi-det. 864*5bff79daSAndreas Kemnade */ 865*5bff79daSAndreas Kemnade }; 866*5bff79daSAndreas Kemnade static const struct bd7182x_irq_res bd71828_irqs[] = { 867*5bff79daSAndreas Kemnade BDIRQ("bd71828-chg-done", bd718x7_chg_done), 868*5bff79daSAndreas Kemnade BDIRQ("bd71828-pwr-dcin-in", bd7182x_dcin_detected), 869*5bff79daSAndreas Kemnade BDIRQ("bd71828-pwr-dcin-out", bd7182x_dcin_removed), 870*5bff79daSAndreas Kemnade BDIRQ("bd71828-vbat-normal", bd71828_vbat_low_res), 871*5bff79daSAndreas Kemnade BDIRQ("bd71828-vbat-low", bd71828_vbat_low_det), 872*5bff79daSAndreas Kemnade BDIRQ("bd71828-btemp-hi", bd71828_temp_bat_hi_det), 873*5bff79daSAndreas Kemnade BDIRQ("bd71828-btemp-cool", bd71828_temp_bat_hi_res), 874*5bff79daSAndreas Kemnade BDIRQ("bd71828-btemp-lo", bd71828_temp_bat_low_det), 875*5bff79daSAndreas Kemnade BDIRQ("bd71828-btemp-warm", bd71828_temp_bat_low_res), 876*5bff79daSAndreas Kemnade BDIRQ("bd71828-temp-hi", bd71828_temp_vf_det), 877*5bff79daSAndreas Kemnade BDIRQ("bd71828-temp-norm", bd71828_temp_vf_res), 878*5bff79daSAndreas Kemnade BDIRQ("bd71828-temp-125-over", bd71828_temp_vf125_det), 879*5bff79daSAndreas Kemnade BDIRQ("bd71828-temp-125-under", bd71828_temp_vf125_res), 880*5bff79daSAndreas Kemnade }; 881*5bff79daSAndreas Kemnade int num_irqs; 882*5bff79daSAndreas Kemnade const struct bd7182x_irq_res *irqs; 883*5bff79daSAndreas Kemnade 884*5bff79daSAndreas Kemnade switch (pwr->chip_type) { 885*5bff79daSAndreas Kemnade case ROHM_CHIP_TYPE_BD71828: 886*5bff79daSAndreas Kemnade irqs = &bd71828_irqs[0]; 887*5bff79daSAndreas Kemnade num_irqs = ARRAY_SIZE(bd71828_irqs); 888*5bff79daSAndreas Kemnade break; 889*5bff79daSAndreas Kemnade case ROHM_CHIP_TYPE_BD71815: 890*5bff79daSAndreas Kemnade irqs = &bd71815_irqs[0]; 891*5bff79daSAndreas Kemnade num_irqs = ARRAY_SIZE(bd71815_irqs); 892*5bff79daSAndreas Kemnade break; 893*5bff79daSAndreas Kemnade default: 894*5bff79daSAndreas Kemnade return -EINVAL; 895*5bff79daSAndreas Kemnade } 896*5bff79daSAndreas Kemnade 897*5bff79daSAndreas Kemnade for (i = 0; i < num_irqs; i++) { 898*5bff79daSAndreas Kemnade irq = platform_get_irq_byname(pdev, irqs[i].name); 899*5bff79daSAndreas Kemnade 900*5bff79daSAndreas Kemnade ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 901*5bff79daSAndreas Kemnade irqs[i].handler, 0, 902*5bff79daSAndreas Kemnade irqs[i].name, pwr); 903*5bff79daSAndreas Kemnade if (ret) 904*5bff79daSAndreas Kemnade break; 905*5bff79daSAndreas Kemnade } 906*5bff79daSAndreas Kemnade 907*5bff79daSAndreas Kemnade return ret; 908*5bff79daSAndreas Kemnade } 909*5bff79daSAndreas Kemnade 910*5bff79daSAndreas Kemnade #define RSENS_DEFAULT_30MOHM 30000 /* 30 mOhm in uOhms*/ 911*5bff79daSAndreas Kemnade 912*5bff79daSAndreas Kemnade static int bd7182x_get_rsens(struct bd71828_power *pwr) 913*5bff79daSAndreas Kemnade { 914*5bff79daSAndreas Kemnade u64 tmp = RSENS_CURR; 915*5bff79daSAndreas Kemnade int rsens_ohm = RSENS_DEFAULT_30MOHM; 916*5bff79daSAndreas Kemnade struct fwnode_handle *node = NULL; 917*5bff79daSAndreas Kemnade 918*5bff79daSAndreas Kemnade if (pwr->dev->parent) 919*5bff79daSAndreas Kemnade node = dev_fwnode(pwr->dev->parent); 920*5bff79daSAndreas Kemnade 921*5bff79daSAndreas Kemnade if (node) { 922*5bff79daSAndreas Kemnade int ret; 923*5bff79daSAndreas Kemnade u32 rs; 924*5bff79daSAndreas Kemnade 925*5bff79daSAndreas Kemnade ret = fwnode_property_read_u32(node, 926*5bff79daSAndreas Kemnade "rohm,charger-sense-resistor-micro-ohms", 927*5bff79daSAndreas Kemnade &rs); 928*5bff79daSAndreas Kemnade if (ret) { 929*5bff79daSAndreas Kemnade if (ret == -EINVAL) { 930*5bff79daSAndreas Kemnade rs = RSENS_DEFAULT_30MOHM; 931*5bff79daSAndreas Kemnade } else { 932*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Bad RSENS dt property\n"); 933*5bff79daSAndreas Kemnade return ret; 934*5bff79daSAndreas Kemnade } 935*5bff79daSAndreas Kemnade } 936*5bff79daSAndreas Kemnade if (!rs) { 937*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Bad RSENS value\n"); 938*5bff79daSAndreas Kemnade return -EINVAL; 939*5bff79daSAndreas Kemnade } 940*5bff79daSAndreas Kemnade 941*5bff79daSAndreas Kemnade rsens_ohm = (int)rs; 942*5bff79daSAndreas Kemnade } 943*5bff79daSAndreas Kemnade 944*5bff79daSAndreas Kemnade /* Reg val to uA */ 945*5bff79daSAndreas Kemnade do_div(tmp, rsens_ohm); 946*5bff79daSAndreas Kemnade 947*5bff79daSAndreas Kemnade pwr->curr_factor = tmp; 948*5bff79daSAndreas Kemnade pwr->rsens = rsens_ohm; 949*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "Setting rsens to %u micro ohm\n", pwr->rsens); 950*5bff79daSAndreas Kemnade dev_dbg(pwr->dev, "Setting curr-factor to %u\n", pwr->curr_factor); 951*5bff79daSAndreas Kemnade 952*5bff79daSAndreas Kemnade return 0; 953*5bff79daSAndreas Kemnade } 954*5bff79daSAndreas Kemnade 955*5bff79daSAndreas Kemnade static int bd71828_power_probe(struct platform_device *pdev) 956*5bff79daSAndreas Kemnade { 957*5bff79daSAndreas Kemnade struct bd71828_power *pwr; 958*5bff79daSAndreas Kemnade struct power_supply_config ac_cfg = {}; 959*5bff79daSAndreas Kemnade struct power_supply_config bat_cfg = {}; 960*5bff79daSAndreas Kemnade int ret; 961*5bff79daSAndreas Kemnade struct regmap *regmap; 962*5bff79daSAndreas Kemnade 963*5bff79daSAndreas Kemnade regmap = dev_get_regmap(pdev->dev.parent, NULL); 964*5bff79daSAndreas Kemnade if (!regmap) { 965*5bff79daSAndreas Kemnade dev_err(&pdev->dev, "No parent regmap\n"); 966*5bff79daSAndreas Kemnade return -EINVAL; 967*5bff79daSAndreas Kemnade } 968*5bff79daSAndreas Kemnade 969*5bff79daSAndreas Kemnade pwr = devm_kzalloc(&pdev->dev, sizeof(*pwr), GFP_KERNEL); 970*5bff79daSAndreas Kemnade if (!pwr) 971*5bff79daSAndreas Kemnade return -ENOMEM; 972*5bff79daSAndreas Kemnade 973*5bff79daSAndreas Kemnade pwr->regmap = regmap; 974*5bff79daSAndreas Kemnade pwr->dev = &pdev->dev; 975*5bff79daSAndreas Kemnade pwr->chip_type = platform_get_device_id(pdev)->driver_data; 976*5bff79daSAndreas Kemnade 977*5bff79daSAndreas Kemnade switch (pwr->chip_type) { 978*5bff79daSAndreas Kemnade case ROHM_CHIP_TYPE_BD71828: 979*5bff79daSAndreas Kemnade pwr->bat_inserted = bd71828_bat_inserted; 980*5bff79daSAndreas Kemnade pwr->get_temp = bd71828_get_temp; 981*5bff79daSAndreas Kemnade pwr->regs = &pwr_regs_bd71828; 982*5bff79daSAndreas Kemnade break; 983*5bff79daSAndreas Kemnade case ROHM_CHIP_TYPE_BD71815: 984*5bff79daSAndreas Kemnade pwr->bat_inserted = bd71815_bat_inserted; 985*5bff79daSAndreas Kemnade pwr->get_temp = bd71815_get_temp; 986*5bff79daSAndreas Kemnade pwr->regs = &pwr_regs_bd71815; 987*5bff79daSAndreas Kemnade break; 988*5bff79daSAndreas Kemnade default: 989*5bff79daSAndreas Kemnade dev_err(pwr->dev, "Unknown PMIC\n"); 990*5bff79daSAndreas Kemnade return -EINVAL; 991*5bff79daSAndreas Kemnade } 992*5bff79daSAndreas Kemnade 993*5bff79daSAndreas Kemnade ret = bd7182x_get_rsens(pwr); 994*5bff79daSAndreas Kemnade if (ret) 995*5bff79daSAndreas Kemnade return dev_err_probe(&pdev->dev, ret, "sense resistor missing\n"); 996*5bff79daSAndreas Kemnade 997*5bff79daSAndreas Kemnade dev_set_drvdata(&pdev->dev, pwr); 998*5bff79daSAndreas Kemnade bd71828_init_hardware(pwr); 999*5bff79daSAndreas Kemnade 1000*5bff79daSAndreas Kemnade bat_cfg.drv_data = pwr; 1001*5bff79daSAndreas Kemnade bat_cfg.fwnode = dev_fwnode(&pdev->dev); 1002*5bff79daSAndreas Kemnade 1003*5bff79daSAndreas Kemnade ac_cfg.supplied_to = bd71828_ac_supplied_to; 1004*5bff79daSAndreas Kemnade ac_cfg.num_supplicants = ARRAY_SIZE(bd71828_ac_supplied_to); 1005*5bff79daSAndreas Kemnade ac_cfg.drv_data = pwr; 1006*5bff79daSAndreas Kemnade 1007*5bff79daSAndreas Kemnade pwr->ac = devm_power_supply_register(&pdev->dev, &bd71828_ac_desc, 1008*5bff79daSAndreas Kemnade &ac_cfg); 1009*5bff79daSAndreas Kemnade if (IS_ERR(pwr->ac)) 1010*5bff79daSAndreas Kemnade return dev_err_probe(&pdev->dev, PTR_ERR(pwr->ac), 1011*5bff79daSAndreas Kemnade "failed to register ac\n"); 1012*5bff79daSAndreas Kemnade 1013*5bff79daSAndreas Kemnade pwr->bat = devm_power_supply_register(&pdev->dev, &bd71828_bat_desc, 1014*5bff79daSAndreas Kemnade &bat_cfg); 1015*5bff79daSAndreas Kemnade if (IS_ERR(pwr->bat)) 1016*5bff79daSAndreas Kemnade return dev_err_probe(&pdev->dev, PTR_ERR(pwr->bat), 1017*5bff79daSAndreas Kemnade "failed to register bat\n"); 1018*5bff79daSAndreas Kemnade 1019*5bff79daSAndreas Kemnade ret = bd7182x_get_irqs(pdev, pwr); 1020*5bff79daSAndreas Kemnade if (ret) 1021*5bff79daSAndreas Kemnade return dev_err_probe(&pdev->dev, ret, "failed to request IRQs"); 1022*5bff79daSAndreas Kemnade 1023*5bff79daSAndreas Kemnade /* Configure wakeup capable */ 1024*5bff79daSAndreas Kemnade device_set_wakeup_capable(pwr->dev, 1); 1025*5bff79daSAndreas Kemnade device_set_wakeup_enable(pwr->dev, 1); 1026*5bff79daSAndreas Kemnade 1027*5bff79daSAndreas Kemnade return 0; 1028*5bff79daSAndreas Kemnade } 1029*5bff79daSAndreas Kemnade 1030*5bff79daSAndreas Kemnade static const struct platform_device_id bd71828_charger_id[] = { 1031*5bff79daSAndreas Kemnade { "bd71815-power", ROHM_CHIP_TYPE_BD71815 }, 1032*5bff79daSAndreas Kemnade { "bd71828-power", ROHM_CHIP_TYPE_BD71828 }, 1033*5bff79daSAndreas Kemnade { }, 1034*5bff79daSAndreas Kemnade }; 1035*5bff79daSAndreas Kemnade MODULE_DEVICE_TABLE(platform, bd71828_charger_id); 1036*5bff79daSAndreas Kemnade 1037*5bff79daSAndreas Kemnade static struct platform_driver bd71828_power_driver = { 1038*5bff79daSAndreas Kemnade .driver = { 1039*5bff79daSAndreas Kemnade .name = "bd718xx-power", 1040*5bff79daSAndreas Kemnade }, 1041*5bff79daSAndreas Kemnade .probe = bd71828_power_probe, 1042*5bff79daSAndreas Kemnade .id_table = bd71828_charger_id, 1043*5bff79daSAndreas Kemnade }; 1044*5bff79daSAndreas Kemnade 1045*5bff79daSAndreas Kemnade module_platform_driver(bd71828_power_driver); 1046*5bff79daSAndreas Kemnade 1047*5bff79daSAndreas Kemnade MODULE_AUTHOR("Cong Pham <cpham2403@gmail.com>"); 1048*5bff79daSAndreas Kemnade MODULE_DESCRIPTION("ROHM BD718(15/28/78) PMIC Battery Charger driver"); 1049*5bff79daSAndreas Kemnade MODULE_LICENSE("GPL"); 1050