0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <linux/devm-helpers.h>
0038 #include <linux/module.h>
0039 #include <linux/mutex.h>
0040 #include <linux/slab.h>
0041 #include <linux/i2c.h>
0042 #include <linux/mod_devicetable.h>
0043 #include <linux/power_supply.h>
0044 #include <linux/workqueue.h>
0045
0046 #define UG3105_MOV_AVG_WINDOW 8
0047 #define UG3105_INIT_POLL_TIME (5 * HZ)
0048 #define UG3105_POLL_TIME (30 * HZ)
0049 #define UG3105_SETTLE_TIME (1 * HZ)
0050
0051 #define UG3105_INIT_POLL_COUNT 30
0052
0053 #define UG3105_REG_MODE 0x00
0054 #define UG3105_REG_CTRL1 0x01
0055 #define UG3105_REG_COULOMB_CNT 0x02
0056 #define UG3105_REG_BAT_VOLT 0x08
0057 #define UG3105_REG_BAT_CURR 0x0c
0058
0059 #define UG3105_MODE_STANDBY 0x00
0060 #define UG3105_MODE_RUN 0x10
0061
0062 #define UG3105_CTRL1_RESET_COULOMB_CNT 0x03
0063
0064 #define UG3105_CURR_HYST_UA 65000
0065
0066 #define UG3105_LOW_BAT_UV 3700000
0067 #define UG3105_FULL_BAT_HYST_UV 38000
0068
0069 struct ug3105_chip {
0070 struct i2c_client *client;
0071 struct power_supply *psy;
0072 struct power_supply_battery_info *info;
0073 struct delayed_work work;
0074 struct mutex lock;
0075 int ocv[UG3105_MOV_AVG_WINDOW];
0076 int intern_res[UG3105_MOV_AVG_WINDOW];
0077 int poll_count;
0078 int ocv_avg_index;
0079 int ocv_avg;
0080 int intern_res_poll_count;
0081 int intern_res_avg_index;
0082 int intern_res_avg;
0083 int volt;
0084 int curr;
0085 int total_coulomb_count;
0086 int uv_per_unit;
0087 int ua_per_unit;
0088 int status;
0089 int capacity;
0090 bool supplied;
0091 };
0092
0093 static int ug3105_read_word(struct i2c_client *client, u8 reg)
0094 {
0095 int val;
0096
0097 val = i2c_smbus_read_word_data(client, reg);
0098 if (val < 0)
0099 dev_err(&client->dev, "Error reading reg 0x%02x\n", reg);
0100
0101 return val;
0102 }
0103
0104 static int ug3105_get_status(struct ug3105_chip *chip)
0105 {
0106 int full = chip->info->constant_charge_voltage_max_uv - UG3105_FULL_BAT_HYST_UV;
0107
0108 if (chip->curr > UG3105_CURR_HYST_UA)
0109 return POWER_SUPPLY_STATUS_CHARGING;
0110
0111 if (chip->curr < -UG3105_CURR_HYST_UA)
0112 return POWER_SUPPLY_STATUS_DISCHARGING;
0113
0114 if (chip->supplied && chip->ocv_avg > full)
0115 return POWER_SUPPLY_STATUS_FULL;
0116
0117 return POWER_SUPPLY_STATUS_NOT_CHARGING;
0118 }
0119
0120 static int ug3105_get_capacity(struct ug3105_chip *chip)
0121 {
0122
0123
0124
0125
0126
0127 static const int ocv_capacity_tbl[23] = {
0128 3350000,
0129 3610000,
0130 3690000,
0131 3710000,
0132 3730000,
0133 3750000,
0134 3770000,
0135 3786667,
0136 3803333,
0137 3820000,
0138 3836667,
0139 3853333,
0140 3870000,
0141 3907500,
0142 3945000,
0143 3982500,
0144 4020000,
0145 4075000,
0146 4110000,
0147 4150000,
0148 4200000,
0149 4250000,
0150 4300000,
0151 };
0152 int i, ocv_diff, ocv_step;
0153
0154 if (chip->ocv_avg < ocv_capacity_tbl[0])
0155 return 0;
0156
0157 if (chip->status == POWER_SUPPLY_STATUS_FULL)
0158 return 100;
0159
0160 for (i = 1; i < ARRAY_SIZE(ocv_capacity_tbl); i++) {
0161 if (chip->ocv_avg > ocv_capacity_tbl[i])
0162 continue;
0163
0164 ocv_diff = ocv_capacity_tbl[i] - chip->ocv_avg;
0165 ocv_step = ocv_capacity_tbl[i] - ocv_capacity_tbl[i - 1];
0166
0167 if (chip->info->constant_charge_voltage_max_uv >= 4300000)
0168 return (i * 500 - ocv_diff * 500 / ocv_step) / 110;
0169 else
0170 return i * 5 - ocv_diff * 5 / ocv_step;
0171 }
0172
0173 return 100;
0174 }
0175
0176 static void ug3105_work(struct work_struct *work)
0177 {
0178 struct ug3105_chip *chip = container_of(work, struct ug3105_chip,
0179 work.work);
0180 int i, val, curr_diff, volt_diff, res, win_size;
0181 bool prev_supplied = chip->supplied;
0182 int prev_status = chip->status;
0183 int prev_volt = chip->volt;
0184 int prev_curr = chip->curr;
0185 struct power_supply *psy;
0186
0187 mutex_lock(&chip->lock);
0188
0189 psy = chip->psy;
0190 if (!psy)
0191 goto out;
0192
0193 val = ug3105_read_word(chip->client, UG3105_REG_BAT_VOLT);
0194 if (val < 0)
0195 goto out;
0196 chip->volt = val * chip->uv_per_unit;
0197
0198 val = ug3105_read_word(chip->client, UG3105_REG_BAT_CURR);
0199 if (val < 0)
0200 goto out;
0201 chip->curr = (s16)val * chip->ua_per_unit;
0202
0203 chip->ocv[chip->ocv_avg_index] =
0204 chip->volt - chip->curr * chip->intern_res_avg / 1000;
0205 chip->ocv_avg_index = (chip->ocv_avg_index + 1) % UG3105_MOV_AVG_WINDOW;
0206 chip->poll_count++;
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 chip->ocv_avg = 0;
0227 win_size = min(chip->poll_count, UG3105_MOV_AVG_WINDOW);
0228 for (i = 0; i < win_size; i++)
0229 chip->ocv_avg += chip->ocv[i];
0230 chip->ocv_avg /= win_size;
0231
0232 chip->supplied = power_supply_am_i_supplied(psy);
0233 chip->status = ug3105_get_status(chip);
0234 chip->capacity = ug3105_get_capacity(chip);
0235
0236
0237
0238
0239
0240 if (chip->supplied != prev_supplied ||
0241 chip->volt < UG3105_LOW_BAT_UV ||
0242 chip->poll_count < 2)
0243 goto out;
0244
0245
0246
0247
0248
0249
0250
0251 curr_diff = abs(chip->curr - prev_curr);
0252 if (curr_diff < UG3105_CURR_HYST_UA)
0253 goto out;
0254
0255 volt_diff = abs(chip->volt - prev_volt);
0256 res = volt_diff * 1000 / curr_diff;
0257
0258 if ((res < (chip->intern_res_avg * 2 / 3)) ||
0259 (res > (chip->intern_res_avg * 4 / 3))) {
0260 dev_dbg(&chip->client->dev, "Ignoring outlier internal resistance %d mOhm\n", res);
0261 goto out;
0262 }
0263
0264 dev_dbg(&chip->client->dev, "Internal resistance %d mOhm\n", res);
0265
0266 chip->intern_res[chip->intern_res_avg_index] = res;
0267 chip->intern_res_avg_index = (chip->intern_res_avg_index + 1) % UG3105_MOV_AVG_WINDOW;
0268 chip->intern_res_poll_count++;
0269
0270 chip->intern_res_avg = 0;
0271 win_size = min(chip->intern_res_poll_count, UG3105_MOV_AVG_WINDOW);
0272 for (i = 0; i < win_size; i++)
0273 chip->intern_res_avg += chip->intern_res[i];
0274 chip->intern_res_avg /= win_size;
0275
0276 out:
0277 mutex_unlock(&chip->lock);
0278
0279 queue_delayed_work(system_wq, &chip->work,
0280 (chip->poll_count <= UG3105_INIT_POLL_COUNT) ?
0281 UG3105_INIT_POLL_TIME : UG3105_POLL_TIME);
0282
0283 if (chip->status != prev_status && psy)
0284 power_supply_changed(psy);
0285 }
0286
0287 static enum power_supply_property ug3105_battery_props[] = {
0288 POWER_SUPPLY_PROP_STATUS,
0289 POWER_SUPPLY_PROP_PRESENT,
0290 POWER_SUPPLY_PROP_TECHNOLOGY,
0291 POWER_SUPPLY_PROP_SCOPE,
0292 POWER_SUPPLY_PROP_VOLTAGE_NOW,
0293 POWER_SUPPLY_PROP_VOLTAGE_OCV,
0294 POWER_SUPPLY_PROP_CURRENT_NOW,
0295 POWER_SUPPLY_PROP_CAPACITY,
0296 };
0297
0298 static int ug3105_get_property(struct power_supply *psy,
0299 enum power_supply_property psp,
0300 union power_supply_propval *val)
0301 {
0302 struct ug3105_chip *chip = power_supply_get_drvdata(psy);
0303 int ret = 0;
0304
0305 mutex_lock(&chip->lock);
0306
0307 if (!chip->psy) {
0308 ret = -EAGAIN;
0309 goto out;
0310 }
0311
0312 switch (psp) {
0313 case POWER_SUPPLY_PROP_STATUS:
0314 val->intval = chip->status;
0315 break;
0316 case POWER_SUPPLY_PROP_PRESENT:
0317 val->intval = 1;
0318 break;
0319 case POWER_SUPPLY_PROP_TECHNOLOGY:
0320 val->intval = chip->info->technology;
0321 break;
0322 case POWER_SUPPLY_PROP_SCOPE:
0323 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
0324 break;
0325 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0326 ret = ug3105_read_word(chip->client, UG3105_REG_BAT_VOLT);
0327 if (ret < 0)
0328 break;
0329 val->intval = ret * chip->uv_per_unit;
0330 ret = 0;
0331 break;
0332 case POWER_SUPPLY_PROP_VOLTAGE_OCV:
0333 val->intval = chip->ocv_avg;
0334 break;
0335 case POWER_SUPPLY_PROP_CURRENT_NOW:
0336 ret = ug3105_read_word(chip->client, UG3105_REG_BAT_CURR);
0337 if (ret < 0)
0338 break;
0339 val->intval = (s16)ret * chip->ua_per_unit;
0340 ret = 0;
0341 break;
0342 case POWER_SUPPLY_PROP_CAPACITY:
0343 val->intval = chip->capacity;
0344 break;
0345 default:
0346 ret = -EINVAL;
0347 }
0348
0349 out:
0350 mutex_unlock(&chip->lock);
0351 return ret;
0352 }
0353
0354 static void ug3105_external_power_changed(struct power_supply *psy)
0355 {
0356 struct ug3105_chip *chip = power_supply_get_drvdata(psy);
0357
0358 dev_dbg(&chip->client->dev, "external power changed\n");
0359 mod_delayed_work(system_wq, &chip->work, UG3105_SETTLE_TIME);
0360 }
0361
0362 static const struct power_supply_desc ug3105_psy_desc = {
0363 .name = "ug3105_battery",
0364 .type = POWER_SUPPLY_TYPE_BATTERY,
0365 .get_property = ug3105_get_property,
0366 .external_power_changed = ug3105_external_power_changed,
0367 .properties = ug3105_battery_props,
0368 .num_properties = ARRAY_SIZE(ug3105_battery_props),
0369 };
0370
0371 static void ug3105_init(struct ug3105_chip *chip)
0372 {
0373 chip->poll_count = 0;
0374 chip->ocv_avg_index = 0;
0375 chip->total_coulomb_count = 0;
0376 i2c_smbus_write_byte_data(chip->client, UG3105_REG_MODE,
0377 UG3105_MODE_RUN);
0378 i2c_smbus_write_byte_data(chip->client, UG3105_REG_CTRL1,
0379 UG3105_CTRL1_RESET_COULOMB_CNT);
0380 queue_delayed_work(system_wq, &chip->work, 0);
0381 flush_delayed_work(&chip->work);
0382 }
0383
0384 static int ug3105_probe(struct i2c_client *client)
0385 {
0386 struct power_supply_config psy_cfg = {};
0387 struct device *dev = &client->dev;
0388 u32 curr_sense_res_uohm = 10000;
0389 struct power_supply *psy;
0390 struct ug3105_chip *chip;
0391 int ret;
0392
0393 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
0394 if (!chip)
0395 return -ENOMEM;
0396
0397 chip->client = client;
0398 mutex_init(&chip->lock);
0399 ret = devm_delayed_work_autocancel(dev, &chip->work, ug3105_work);
0400 if (ret)
0401 return ret;
0402
0403 psy_cfg.drv_data = chip;
0404 psy = devm_power_supply_register(dev, &ug3105_psy_desc, &psy_cfg);
0405 if (IS_ERR(psy))
0406 return PTR_ERR(psy);
0407
0408 ret = power_supply_get_battery_info(psy, &chip->info);
0409 if (ret)
0410 return ret;
0411
0412 if (chip->info->factory_internal_resistance_uohm == -EINVAL ||
0413 chip->info->constant_charge_voltage_max_uv == -EINVAL) {
0414 dev_err(dev, "error required properties are missing\n");
0415 return -ENODEV;
0416 }
0417
0418 device_property_read_u32(dev, "upisemi,rsns-microohm", &curr_sense_res_uohm);
0419
0420
0421
0422
0423
0424 chip->uv_per_unit = 45000000/65536;
0425
0426 chip->ua_per_unit = 8100000 / curr_sense_res_uohm;
0427
0428
0429 chip->intern_res_avg = chip->info->factory_internal_resistance_uohm / 1000;
0430
0431 chip->intern_res[0] = chip->intern_res_avg;
0432 chip->intern_res_avg_index = 1;
0433 chip->intern_res_poll_count = 1;
0434
0435 mutex_lock(&chip->lock);
0436 chip->psy = psy;
0437 mutex_unlock(&chip->lock);
0438
0439 ug3105_init(chip);
0440
0441 i2c_set_clientdata(client, chip);
0442 return 0;
0443 }
0444
0445 static int __maybe_unused ug3105_suspend(struct device *dev)
0446 {
0447 struct ug3105_chip *chip = dev_get_drvdata(dev);
0448
0449 cancel_delayed_work_sync(&chip->work);
0450 i2c_smbus_write_byte_data(chip->client, UG3105_REG_MODE,
0451 UG3105_MODE_STANDBY);
0452
0453 return 0;
0454 }
0455
0456 static int __maybe_unused ug3105_resume(struct device *dev)
0457 {
0458 struct ug3105_chip *chip = dev_get_drvdata(dev);
0459
0460 ug3105_init(chip);
0461
0462 return 0;
0463 }
0464
0465 static SIMPLE_DEV_PM_OPS(ug3105_pm_ops, ug3105_suspend,
0466 ug3105_resume);
0467
0468 static const struct i2c_device_id ug3105_id[] = {
0469 { "ug3105" },
0470 { }
0471 };
0472 MODULE_DEVICE_TABLE(i2c, ug3105_id);
0473
0474 static struct i2c_driver ug3105_i2c_driver = {
0475 .driver = {
0476 .name = "ug3105",
0477 .pm = &ug3105_pm_ops,
0478 },
0479 .probe_new = ug3105_probe,
0480 .id_table = ug3105_id,
0481 };
0482 module_i2c_driver(ug3105_i2c_driver);
0483
0484 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com");
0485 MODULE_DESCRIPTION("uPI uG3105 battery monitor driver");
0486 MODULE_LICENSE("GPL");