Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
0004 
0005 #include <linux/i2c.h>
0006 #include <linux/module.h>
0007 #include <linux/power_supply.h>
0008 #include <linux/regmap.h>
0009 
0010 #define IP5XXX_SYS_CTL0         0x01
0011 #define IP5XXX_SYS_CTL0_WLED_DET_EN     BIT(4)
0012 #define IP5XXX_SYS_CTL0_WLED_EN         BIT(3)
0013 #define IP5XXX_SYS_CTL0_BOOST_EN        BIT(2)
0014 #define IP5XXX_SYS_CTL0_CHARGER_EN      BIT(1)
0015 #define IP5XXX_SYS_CTL1         0x02
0016 #define IP5XXX_SYS_CTL1_LIGHT_SHDN_EN       BIT(1)
0017 #define IP5XXX_SYS_CTL1_LOAD_PWRUP_EN       BIT(0)
0018 #define IP5XXX_SYS_CTL2         0x0c
0019 #define IP5XXX_SYS_CTL2_LIGHT_SHDN_TH       GENMASK(7, 3)
0020 #define IP5XXX_SYS_CTL3         0x03
0021 #define IP5XXX_SYS_CTL3_LONG_PRESS_TIME_SEL GENMASK(7, 6)
0022 #define IP5XXX_SYS_CTL3_BTN_SHDN_EN     BIT(5)
0023 #define IP5XXX_SYS_CTL4         0x04
0024 #define IP5XXX_SYS_CTL4_SHDN_TIME_SEL       GENMASK(7, 6)
0025 #define IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN    BIT(5)
0026 #define IP5XXX_SYS_CTL5         0x07
0027 #define IP5XXX_SYS_CTL5_NTC_DIS         BIT(6)
0028 #define IP5XXX_SYS_CTL5_WLED_MODE_SEL       BIT(1)
0029 #define IP5XXX_SYS_CTL5_BTN_SHDN_SEL        BIT(0)
0030 #define IP5XXX_CHG_CTL1         0x22
0031 #define IP5XXX_CHG_CTL1_BOOST_UVP_SEL       GENMASK(3, 2)
0032 #define IP5XXX_CHG_CTL2         0x24
0033 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL        GENMASK(6, 5)
0034 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V   (0x0 << 5)
0035 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V   (0x1 << 5)
0036 #define IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V  (0x2 << 5)
0037 #define IP5XXX_CHG_CTL2_CONST_VOLT_SEL      GENMASK(2, 1)
0038 #define IP5XXX_CHG_CTL4         0x26
0039 #define IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN     BIT(6)
0040 #define IP5XXX_CHG_CTL4A        0x25
0041 #define IP5XXX_CHG_CTL4A_CONST_CUR_SEL      GENMASK(4, 0)
0042 #define IP5XXX_MFP_CTL0         0x51
0043 #define IP5XXX_MFP_CTL1         0x52
0044 #define IP5XXX_GPIO_CTL2        0x53
0045 #define IP5XXX_GPIO_CTL2A       0x54
0046 #define IP5XXX_GPIO_CTL3        0x55
0047 #define IP5XXX_READ0            0x71
0048 #define IP5XXX_READ0_CHG_STAT           GENMASK(7, 5)
0049 #define IP5XXX_READ0_CHG_STAT_IDLE      (0x0 << 5)
0050 #define IP5XXX_READ0_CHG_STAT_TRICKLE       (0x1 << 5)
0051 #define IP5XXX_READ0_CHG_STAT_CONST_VOLT    (0x2 << 5)
0052 #define IP5XXX_READ0_CHG_STAT_CONST_CUR     (0x3 << 5)
0053 #define IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP   (0x4 << 5)
0054 #define IP5XXX_READ0_CHG_STAT_FULL      (0x5 << 5)
0055 #define IP5XXX_READ0_CHG_STAT_TIMEOUT       (0x6 << 5)
0056 #define IP5XXX_READ0_CHG_OP         BIT(4)
0057 #define IP5XXX_READ0_CHG_END            BIT(3)
0058 #define IP5XXX_READ0_CONST_VOLT_TIMEOUT     BIT(2)
0059 #define IP5XXX_READ0_CHG_TIMEOUT        BIT(1)
0060 #define IP5XXX_READ0_TRICKLE_TIMEOUT        BIT(0)
0061 #define IP5XXX_READ0_TIMEOUT            GENMASK(2, 0)
0062 #define IP5XXX_READ1            0x72
0063 #define IP5XXX_READ1_WLED_PRESENT       BIT(7)
0064 #define IP5XXX_READ1_LIGHT_LOAD         BIT(6)
0065 #define IP5XXX_READ1_VIN_OVERVOLT       BIT(5)
0066 #define IP5XXX_READ2            0x77
0067 #define IP5XXX_READ2_BTN_PRESS          BIT(3)
0068 #define IP5XXX_READ2_BTN_LONG_PRESS     BIT(1)
0069 #define IP5XXX_READ2_BTN_SHORT_PRESS        BIT(0)
0070 #define IP5XXX_BATVADC_DAT0     0xa2
0071 #define IP5XXX_BATVADC_DAT1     0xa3
0072 #define IP5XXX_BATIADC_DAT0     0xa4
0073 #define IP5XXX_BATIADC_DAT1     0xa5
0074 #define IP5XXX_BATOCV_DAT0      0xa8
0075 #define IP5XXX_BATOCV_DAT1      0xa9
0076 
0077 struct ip5xxx {
0078     struct regmap *regmap;
0079     bool initialized;
0080 };
0081 
0082 /*
0083  * The IP5xxx charger only responds on I2C when it is "awake". The charger is
0084  * generally only awake when VIN is powered or when its boost converter is
0085  * enabled. Going into shutdown resets all register values. To handle this:
0086  *  1) When any bus error occurs, assume the charger has gone into shutdown.
0087  *  2) Attempt the initialization sequence on each subsequent register access
0088  *     until it succeeds.
0089  */
0090 static int ip5xxx_read(struct ip5xxx *ip5xxx, unsigned int reg,
0091                unsigned int *val)
0092 {
0093     int ret;
0094 
0095     ret = regmap_read(ip5xxx->regmap, reg, val);
0096     if (ret)
0097         ip5xxx->initialized = false;
0098 
0099     return ret;
0100 }
0101 
0102 static int ip5xxx_update_bits(struct ip5xxx *ip5xxx, unsigned int reg,
0103                   unsigned int mask, unsigned int val)
0104 {
0105     int ret;
0106 
0107     ret = regmap_update_bits(ip5xxx->regmap, reg, mask, val);
0108     if (ret)
0109         ip5xxx->initialized = false;
0110 
0111     return ret;
0112 }
0113 
0114 static int ip5xxx_initialize(struct power_supply *psy)
0115 {
0116     struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy);
0117     int ret;
0118 
0119     if (ip5xxx->initialized)
0120         return 0;
0121 
0122     /*
0123      * Disable shutdown under light load.
0124      * Enable power on when under load.
0125      */
0126     ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL1,
0127                  IP5XXX_SYS_CTL1_LIGHT_SHDN_EN |
0128                  IP5XXX_SYS_CTL1_LOAD_PWRUP_EN,
0129                  IP5XXX_SYS_CTL1_LOAD_PWRUP_EN);
0130     if (ret)
0131         return ret;
0132 
0133     /*
0134      * Enable shutdown after a long button press (as configured below).
0135      */
0136     ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL3,
0137                  IP5XXX_SYS_CTL3_BTN_SHDN_EN,
0138                  IP5XXX_SYS_CTL3_BTN_SHDN_EN);
0139     if (ret)
0140         return ret;
0141 
0142     /*
0143      * Power on automatically when VIN is removed.
0144      */
0145     ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL4,
0146                  IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN,
0147                  IP5XXX_SYS_CTL4_VIN_PULLOUT_BOOST_EN);
0148     if (ret)
0149         return ret;
0150 
0151     /*
0152      * Enable the NTC.
0153      * Configure the button for two presses => LED, long press => shutdown.
0154      */
0155     ret = ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL5,
0156                  IP5XXX_SYS_CTL5_NTC_DIS |
0157                  IP5XXX_SYS_CTL5_WLED_MODE_SEL |
0158                  IP5XXX_SYS_CTL5_BTN_SHDN_SEL,
0159                  IP5XXX_SYS_CTL5_WLED_MODE_SEL |
0160                  IP5XXX_SYS_CTL5_BTN_SHDN_SEL);
0161     if (ret)
0162         return ret;
0163 
0164     ip5xxx->initialized = true;
0165     dev_dbg(psy->dev.parent, "Initialized after power on\n");
0166 
0167     return 0;
0168 }
0169 
0170 static const enum power_supply_property ip5xxx_battery_properties[] = {
0171     POWER_SUPPLY_PROP_STATUS,
0172     POWER_SUPPLY_PROP_CHARGE_TYPE,
0173     POWER_SUPPLY_PROP_HEALTH,
0174     POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
0175     POWER_SUPPLY_PROP_VOLTAGE_NOW,
0176     POWER_SUPPLY_PROP_VOLTAGE_OCV,
0177     POWER_SUPPLY_PROP_CURRENT_NOW,
0178     POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
0179     POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
0180     POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
0181     POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
0182 };
0183 
0184 static int ip5xxx_battery_get_status(struct ip5xxx *ip5xxx, int *val)
0185 {
0186     unsigned int rval;
0187     int ret;
0188 
0189     ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval);
0190     if (ret)
0191         return ret;
0192 
0193     switch (rval & IP5XXX_READ0_CHG_STAT) {
0194     case IP5XXX_READ0_CHG_STAT_IDLE:
0195         *val = POWER_SUPPLY_STATUS_DISCHARGING;
0196         break;
0197     case IP5XXX_READ0_CHG_STAT_TRICKLE:
0198     case IP5XXX_READ0_CHG_STAT_CONST_CUR:
0199     case IP5XXX_READ0_CHG_STAT_CONST_VOLT:
0200         *val = POWER_SUPPLY_STATUS_CHARGING;
0201         break;
0202     case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP:
0203     case IP5XXX_READ0_CHG_STAT_FULL:
0204         *val = POWER_SUPPLY_STATUS_FULL;
0205         break;
0206     case IP5XXX_READ0_CHG_STAT_TIMEOUT:
0207         *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
0208         break;
0209     default:
0210         return -EINVAL;
0211     }
0212 
0213     return 0;
0214 }
0215 
0216 static int ip5xxx_battery_get_charge_type(struct ip5xxx *ip5xxx, int *val)
0217 {
0218     unsigned int rval;
0219     int ret;
0220 
0221     ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval);
0222     if (ret)
0223         return ret;
0224 
0225     switch (rval & IP5XXX_READ0_CHG_STAT) {
0226     case IP5XXX_READ0_CHG_STAT_IDLE:
0227     case IP5XXX_READ0_CHG_STAT_CONST_VOLT_STOP:
0228     case IP5XXX_READ0_CHG_STAT_FULL:
0229     case IP5XXX_READ0_CHG_STAT_TIMEOUT:
0230         *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
0231         break;
0232     case IP5XXX_READ0_CHG_STAT_TRICKLE:
0233         *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
0234         break;
0235     case IP5XXX_READ0_CHG_STAT_CONST_CUR:
0236     case IP5XXX_READ0_CHG_STAT_CONST_VOLT:
0237         *val = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
0238         break;
0239     default:
0240         return -EINVAL;
0241     }
0242 
0243     return 0;
0244 }
0245 
0246 static int ip5xxx_battery_get_health(struct ip5xxx *ip5xxx, int *val)
0247 {
0248     unsigned int rval;
0249     int ret;
0250 
0251     ret = ip5xxx_read(ip5xxx, IP5XXX_READ0, &rval);
0252     if (ret)
0253         return ret;
0254 
0255     if (rval & IP5XXX_READ0_TIMEOUT)
0256         *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
0257     else
0258         *val = POWER_SUPPLY_HEALTH_GOOD;
0259 
0260     return 0;
0261 }
0262 
0263 static int ip5xxx_battery_get_voltage_max(struct ip5xxx *ip5xxx, int *val)
0264 {
0265     unsigned int rval;
0266     int ret;
0267 
0268     ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL2, &rval);
0269     if (ret)
0270         return ret;
0271 
0272     /*
0273      * It is not clear what this will return if
0274      * IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN is not set...
0275      */
0276     switch (rval & IP5XXX_CHG_CTL2_BAT_TYPE_SEL) {
0277     case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V:
0278         *val = 4200000;
0279         break;
0280     case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V:
0281         *val = 4300000;
0282         break;
0283     case IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V:
0284         *val = 4350000;
0285         break;
0286     default:
0287         return -EINVAL;
0288     }
0289 
0290     return 0;
0291 }
0292 
0293 static int ip5xxx_battery_read_adc(struct ip5xxx *ip5xxx,
0294                    u8 lo_reg, u8 hi_reg, int *val)
0295 {
0296     unsigned int hi, lo;
0297     int ret;
0298 
0299     ret = ip5xxx_read(ip5xxx, lo_reg, &lo);
0300     if (ret)
0301         return ret;
0302 
0303     ret = ip5xxx_read(ip5xxx, hi_reg, &hi);
0304     if (ret)
0305         return ret;
0306 
0307     *val = sign_extend32(hi << 8 | lo, 13);
0308 
0309     return 0;
0310 }
0311 
0312 static int ip5xxx_battery_get_property(struct power_supply *psy,
0313                        enum power_supply_property psp,
0314                        union power_supply_propval *val)
0315 {
0316     struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy);
0317     int raw, ret, vmax;
0318     unsigned int rval;
0319 
0320     ret = ip5xxx_initialize(psy);
0321     if (ret)
0322         return ret;
0323 
0324     switch (psp) {
0325     case POWER_SUPPLY_PROP_STATUS:
0326         return ip5xxx_battery_get_status(ip5xxx, &val->intval);
0327 
0328     case POWER_SUPPLY_PROP_CHARGE_TYPE:
0329         return ip5xxx_battery_get_charge_type(ip5xxx, &val->intval);
0330 
0331     case POWER_SUPPLY_PROP_HEALTH:
0332         return ip5xxx_battery_get_health(ip5xxx, &val->intval);
0333 
0334     case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
0335         return ip5xxx_battery_get_voltage_max(ip5xxx, &val->intval);
0336 
0337     case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0338         ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATVADC_DAT0,
0339                           IP5XXX_BATVADC_DAT1, &raw);
0340 
0341         val->intval = 2600000 + DIV_ROUND_CLOSEST(raw * 26855, 100);
0342         return 0;
0343 
0344     case POWER_SUPPLY_PROP_VOLTAGE_OCV:
0345         ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATOCV_DAT0,
0346                           IP5XXX_BATOCV_DAT1, &raw);
0347 
0348         val->intval = 2600000 + DIV_ROUND_CLOSEST(raw * 26855, 100);
0349         return 0;
0350 
0351     case POWER_SUPPLY_PROP_CURRENT_NOW:
0352         ret = ip5xxx_battery_read_adc(ip5xxx, IP5XXX_BATIADC_DAT0,
0353                           IP5XXX_BATIADC_DAT1, &raw);
0354 
0355         val->intval = DIV_ROUND_CLOSEST(raw * 745985, 1000);
0356         return 0;
0357 
0358     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0359         ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL4A, &rval);
0360         if (ret)
0361             return ret;
0362 
0363         rval &= IP5XXX_CHG_CTL4A_CONST_CUR_SEL;
0364         val->intval = 100000 * rval;
0365         return 0;
0366 
0367     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
0368         val->intval = 100000 * 0x1f;
0369         return 0;
0370 
0371     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
0372         ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax);
0373         if (ret)
0374             return ret;
0375 
0376         ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL2, &rval);
0377         if (ret)
0378             return ret;
0379 
0380         rval &= IP5XXX_CHG_CTL2_CONST_VOLT_SEL;
0381         val->intval = vmax + 14000 * (rval >> 1);
0382         return 0;
0383 
0384     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
0385         ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax);
0386         if (ret)
0387             return ret;
0388 
0389         val->intval = vmax + 14000 * 3;
0390         return 0;
0391 
0392     default:
0393         return -EINVAL;
0394     }
0395 }
0396 
0397 static int ip5xxx_battery_set_voltage_max(struct ip5xxx *ip5xxx, int val)
0398 {
0399     unsigned int rval;
0400     int ret;
0401 
0402     switch (val) {
0403     case 4200000:
0404         rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_2V;
0405         break;
0406     case 4300000:
0407         rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_3V;
0408         break;
0409     case 4350000:
0410         rval = IP5XXX_CHG_CTL2_BAT_TYPE_SEL_4_35V;
0411         break;
0412     default:
0413         return -EINVAL;
0414     }
0415 
0416     ret = ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2,
0417                  IP5XXX_CHG_CTL2_BAT_TYPE_SEL, rval);
0418     if (ret)
0419         return ret;
0420 
0421     ret = ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL4,
0422                  IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN,
0423                  IP5XXX_CHG_CTL4_BAT_TYPE_SEL_EN);
0424     if (ret)
0425         return ret;
0426 
0427     return 0;
0428 }
0429 
0430 static int ip5xxx_battery_set_property(struct power_supply *psy,
0431                        enum power_supply_property psp,
0432                        const union power_supply_propval *val)
0433 {
0434     struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy);
0435     unsigned int rval;
0436     int ret, vmax;
0437 
0438     ret = ip5xxx_initialize(psy);
0439     if (ret)
0440         return ret;
0441 
0442     switch (psp) {
0443     case POWER_SUPPLY_PROP_STATUS:
0444         switch (val->intval) {
0445         case POWER_SUPPLY_STATUS_CHARGING:
0446             rval = IP5XXX_SYS_CTL0_CHARGER_EN;
0447             break;
0448         case POWER_SUPPLY_STATUS_DISCHARGING:
0449         case POWER_SUPPLY_STATUS_NOT_CHARGING:
0450             rval = 0;
0451             break;
0452         default:
0453             return -EINVAL;
0454         }
0455         return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0,
0456                       IP5XXX_SYS_CTL0_CHARGER_EN, rval);
0457 
0458     case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
0459         return ip5xxx_battery_set_voltage_max(ip5xxx, val->intval);
0460 
0461     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0462         rval = val->intval / 100000;
0463         return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL4A,
0464                       IP5XXX_CHG_CTL4A_CONST_CUR_SEL, rval);
0465 
0466     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
0467         ret = ip5xxx_battery_get_voltage_max(ip5xxx, &vmax);
0468         if (ret)
0469             return ret;
0470 
0471         rval = ((val->intval - vmax) / 14000) << 1;
0472         return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2,
0473                       IP5XXX_CHG_CTL2_CONST_VOLT_SEL, rval);
0474 
0475     default:
0476         return -EINVAL;
0477     }
0478 }
0479 
0480 static int ip5xxx_battery_property_is_writeable(struct power_supply *psy,
0481                         enum power_supply_property psp)
0482 {
0483     return psp == POWER_SUPPLY_PROP_STATUS ||
0484            psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
0485            psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
0486            psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE;
0487 }
0488 
0489 static const struct power_supply_desc ip5xxx_battery_desc = {
0490     .name           = "ip5xxx-battery",
0491     .type           = POWER_SUPPLY_TYPE_BATTERY,
0492     .properties     = ip5xxx_battery_properties,
0493     .num_properties     = ARRAY_SIZE(ip5xxx_battery_properties),
0494     .get_property       = ip5xxx_battery_get_property,
0495     .set_property       = ip5xxx_battery_set_property,
0496     .property_is_writeable  = ip5xxx_battery_property_is_writeable,
0497 };
0498 
0499 static const enum power_supply_property ip5xxx_boost_properties[] = {
0500     POWER_SUPPLY_PROP_ONLINE,
0501     POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
0502 };
0503 
0504 static int ip5xxx_boost_get_property(struct power_supply *psy,
0505                      enum power_supply_property psp,
0506                      union power_supply_propval *val)
0507 {
0508     struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy);
0509     unsigned int rval;
0510     int ret;
0511 
0512     ret = ip5xxx_initialize(psy);
0513     if (ret)
0514         return ret;
0515 
0516     switch (psp) {
0517     case POWER_SUPPLY_PROP_ONLINE:
0518         ret = ip5xxx_read(ip5xxx, IP5XXX_SYS_CTL0, &rval);
0519         if (ret)
0520             return ret;
0521 
0522         val->intval = !!(rval & IP5XXX_SYS_CTL0_BOOST_EN);
0523         return 0;
0524 
0525     case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
0526         ret = ip5xxx_read(ip5xxx, IP5XXX_CHG_CTL1, &rval);
0527         if (ret)
0528             return ret;
0529 
0530         rval &= IP5XXX_CHG_CTL1_BOOST_UVP_SEL;
0531         val->intval = 4530000 + 100000 * (rval >> 2);
0532         return 0;
0533 
0534     default:
0535         return -EINVAL;
0536     }
0537 }
0538 
0539 static int ip5xxx_boost_set_property(struct power_supply *psy,
0540                      enum power_supply_property psp,
0541                      const union power_supply_propval *val)
0542 {
0543     struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy);
0544     unsigned int rval;
0545     int ret;
0546 
0547     ret = ip5xxx_initialize(psy);
0548     if (ret)
0549         return ret;
0550 
0551     switch (psp) {
0552     case POWER_SUPPLY_PROP_ONLINE:
0553         rval = val->intval ? IP5XXX_SYS_CTL0_BOOST_EN : 0;
0554         return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0,
0555                       IP5XXX_SYS_CTL0_BOOST_EN, rval);
0556 
0557     case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
0558         rval = ((val->intval - 4530000) / 100000) << 2;
0559         return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL1,
0560                       IP5XXX_CHG_CTL1_BOOST_UVP_SEL, rval);
0561 
0562     default:
0563         return -EINVAL;
0564     }
0565 }
0566 
0567 static int ip5xxx_boost_property_is_writeable(struct power_supply *psy,
0568                           enum power_supply_property psp)
0569 {
0570     return true;
0571 }
0572 
0573 static const struct power_supply_desc ip5xxx_boost_desc = {
0574     .name           = "ip5xxx-boost",
0575     .type           = POWER_SUPPLY_TYPE_USB,
0576     .properties     = ip5xxx_boost_properties,
0577     .num_properties     = ARRAY_SIZE(ip5xxx_boost_properties),
0578     .get_property       = ip5xxx_boost_get_property,
0579     .set_property       = ip5xxx_boost_set_property,
0580     .property_is_writeable  = ip5xxx_boost_property_is_writeable,
0581 };
0582 
0583 static const struct regmap_config ip5xxx_regmap_config = {
0584     .reg_bits       = 8,
0585     .val_bits       = 8,
0586     .max_register       = IP5XXX_BATOCV_DAT1,
0587 };
0588 
0589 static int ip5xxx_power_probe(struct i2c_client *client)
0590 {
0591     struct power_supply_config psy_cfg = {};
0592     struct device *dev = &client->dev;
0593     struct power_supply *psy;
0594     struct ip5xxx *ip5xxx;
0595 
0596     ip5xxx = devm_kzalloc(dev, sizeof(*ip5xxx), GFP_KERNEL);
0597     if (!ip5xxx)
0598         return -ENOMEM;
0599 
0600     ip5xxx->regmap = devm_regmap_init_i2c(client, &ip5xxx_regmap_config);
0601     if (IS_ERR(ip5xxx->regmap))
0602         return PTR_ERR(ip5xxx->regmap);
0603 
0604     psy_cfg.of_node = dev->of_node;
0605     psy_cfg.drv_data = ip5xxx;
0606 
0607     psy = devm_power_supply_register(dev, &ip5xxx_battery_desc, &psy_cfg);
0608     if (IS_ERR(psy))
0609         return PTR_ERR(psy);
0610 
0611     psy = devm_power_supply_register(dev, &ip5xxx_boost_desc, &psy_cfg);
0612     if (IS_ERR(psy))
0613         return PTR_ERR(psy);
0614 
0615     return 0;
0616 }
0617 
0618 static const struct of_device_id ip5xxx_power_of_match[] = {
0619     { .compatible = "injoinic,ip5108" },
0620     { .compatible = "injoinic,ip5109" },
0621     { .compatible = "injoinic,ip5207" },
0622     { .compatible = "injoinic,ip5209" },
0623     { }
0624 };
0625 MODULE_DEVICE_TABLE(of, ip5xxx_power_of_match);
0626 
0627 static struct i2c_driver ip5xxx_power_driver = {
0628     .probe_new  = ip5xxx_power_probe,
0629     .driver     = {
0630         .name       = "ip5xxx-power",
0631         .of_match_table = ip5xxx_power_of_match,
0632     }
0633 };
0634 module_i2c_driver(ip5xxx_power_driver);
0635 
0636 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
0637 MODULE_DESCRIPTION("Injoinic IP5xxx power bank IC driver");
0638 MODULE_LICENSE("GPL");