Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * DA9150 Fuel-Gauge Driver
0004  *
0005  * Copyright (c) 2015 Dialog Semiconductor
0006  *
0007  * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/of.h>
0014 #include <linux/of_platform.h>
0015 #include <linux/slab.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/delay.h>
0018 #include <linux/power_supply.h>
0019 #include <linux/list.h>
0020 #include <asm/div64.h>
0021 #include <linux/mfd/da9150/core.h>
0022 #include <linux/mfd/da9150/registers.h>
0023 #include <linux/devm-helpers.h>
0024 
0025 /* Core2Wire */
0026 #define DA9150_QIF_READ     (0x0 << 7)
0027 #define DA9150_QIF_WRITE    (0x1 << 7)
0028 #define DA9150_QIF_CODE_MASK    0x7F
0029 
0030 #define DA9150_QIF_BYTE_SIZE    8
0031 #define DA9150_QIF_BYTE_MASK    0xFF
0032 #define DA9150_QIF_SHORT_SIZE   2
0033 #define DA9150_QIF_LONG_SIZE    4
0034 
0035 /* QIF Codes */
0036 #define DA9150_QIF_UAVG         6
0037 #define DA9150_QIF_UAVG_SIZE        DA9150_QIF_LONG_SIZE
0038 #define DA9150_QIF_IAVG         8
0039 #define DA9150_QIF_IAVG_SIZE        DA9150_QIF_LONG_SIZE
0040 #define DA9150_QIF_NTCAVG       12
0041 #define DA9150_QIF_NTCAVG_SIZE      DA9150_QIF_LONG_SIZE
0042 #define DA9150_QIF_SHUNT_VAL        36
0043 #define DA9150_QIF_SHUNT_VAL_SIZE   DA9150_QIF_SHORT_SIZE
0044 #define DA9150_QIF_SD_GAIN      38
0045 #define DA9150_QIF_SD_GAIN_SIZE     DA9150_QIF_LONG_SIZE
0046 #define DA9150_QIF_FCC_MAH      40
0047 #define DA9150_QIF_FCC_MAH_SIZE     DA9150_QIF_SHORT_SIZE
0048 #define DA9150_QIF_SOC_PCT      43
0049 #define DA9150_QIF_SOC_PCT_SIZE     DA9150_QIF_SHORT_SIZE
0050 #define DA9150_QIF_CHARGE_LIMIT     44
0051 #define DA9150_QIF_CHARGE_LIMIT_SIZE    DA9150_QIF_SHORT_SIZE
0052 #define DA9150_QIF_DISCHARGE_LIMIT  45
0053 #define DA9150_QIF_DISCHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE
0054 #define DA9150_QIF_FW_MAIN_VER      118
0055 #define DA9150_QIF_FW_MAIN_VER_SIZE DA9150_QIF_SHORT_SIZE
0056 #define DA9150_QIF_E_FG_STATUS      126
0057 #define DA9150_QIF_E_FG_STATUS_SIZE DA9150_QIF_SHORT_SIZE
0058 #define DA9150_QIF_SYNC         127
0059 #define DA9150_QIF_SYNC_SIZE        DA9150_QIF_SHORT_SIZE
0060 #define DA9150_QIF_MAX_CODES        128
0061 
0062 /* QIF Sync Timeout */
0063 #define DA9150_QIF_SYNC_TIMEOUT     1000
0064 #define DA9150_QIF_SYNC_RETRIES     10
0065 
0066 /* QIF E_FG_STATUS */
0067 #define DA9150_FG_IRQ_LOW_SOC_MASK  (1 << 0)
0068 #define DA9150_FG_IRQ_HIGH_SOC_MASK (1 << 1)
0069 #define DA9150_FG_IRQ_SOC_MASK  \
0070     (DA9150_FG_IRQ_LOW_SOC_MASK | DA9150_FG_IRQ_HIGH_SOC_MASK)
0071 
0072 /* Private data */
0073 struct da9150_fg {
0074     struct da9150 *da9150;
0075     struct device *dev;
0076 
0077     struct mutex io_lock;
0078 
0079     struct power_supply *battery;
0080     struct delayed_work work;
0081     u32 interval;
0082 
0083     int warn_soc;
0084     int crit_soc;
0085     int soc;
0086 };
0087 
0088 /* Battery Properties */
0089 static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size)
0090 
0091 {
0092     u8 buf[DA9150_QIF_LONG_SIZE];
0093     u8 read_addr;
0094     u32 res = 0;
0095     int i;
0096 
0097     /* Set QIF code (READ mode) */
0098     read_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_READ;
0099 
0100     da9150_read_qif(fg->da9150, read_addr, size, buf);
0101     for (i = 0; i < size; ++i)
0102         res |= (buf[i] << (i * DA9150_QIF_BYTE_SIZE));
0103 
0104     return res;
0105 }
0106 
0107 static void da9150_fg_write_attr(struct da9150_fg *fg, u8 code, u8 size,
0108                  u32 val)
0109 
0110 {
0111     u8 buf[DA9150_QIF_LONG_SIZE];
0112     u8 write_addr;
0113     int i;
0114 
0115     /* Set QIF code (WRITE mode) */
0116     write_addr = (code & DA9150_QIF_CODE_MASK) | DA9150_QIF_WRITE;
0117 
0118     for (i = 0; i < size; ++i) {
0119         buf[i] = (val >> (i * DA9150_QIF_BYTE_SIZE)) &
0120              DA9150_QIF_BYTE_MASK;
0121     }
0122     da9150_write_qif(fg->da9150, write_addr, size, buf);
0123 }
0124 
0125 /* Trigger QIF Sync to update QIF readable data */
0126 static void da9150_fg_read_sync_start(struct da9150_fg *fg)
0127 {
0128     int i = 0;
0129     u32 res = 0;
0130 
0131     mutex_lock(&fg->io_lock);
0132 
0133     /* Check if QIF sync already requested, and write to sync if not */
0134     res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
0135                   DA9150_QIF_SYNC_SIZE);
0136     if (res > 0)
0137         da9150_fg_write_attr(fg, DA9150_QIF_SYNC,
0138                      DA9150_QIF_SYNC_SIZE, 0);
0139 
0140     /* Wait for sync to complete */
0141     res = 0;
0142     while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
0143         usleep_range(DA9150_QIF_SYNC_TIMEOUT,
0144                  DA9150_QIF_SYNC_TIMEOUT * 2);
0145         res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
0146                       DA9150_QIF_SYNC_SIZE);
0147     }
0148 
0149     /* Check if sync completed */
0150     if (res == 0)
0151         dev_err(fg->dev, "Failed to perform QIF read sync!\n");
0152 }
0153 
0154 /*
0155  * Should always be called after QIF sync read has been performed, and all
0156  * attributes required have been accessed.
0157  */
0158 static inline void da9150_fg_read_sync_end(struct da9150_fg *fg)
0159 {
0160     mutex_unlock(&fg->io_lock);
0161 }
0162 
0163 /* Sync read of single QIF attribute */
0164 static u32 da9150_fg_read_attr_sync(struct da9150_fg *fg, u8 code, u8 size)
0165 {
0166     u32 val;
0167 
0168     da9150_fg_read_sync_start(fg);
0169     val = da9150_fg_read_attr(fg, code, size);
0170     da9150_fg_read_sync_end(fg);
0171 
0172     return val;
0173 }
0174 
0175 /* Wait for QIF Sync, write QIF data and wait for ack */
0176 static void da9150_fg_write_attr_sync(struct da9150_fg *fg, u8 code, u8 size,
0177                       u32 val)
0178 {
0179     int i = 0;
0180     u32 res = 0, sync_val;
0181 
0182     mutex_lock(&fg->io_lock);
0183 
0184     /* Check if QIF sync already requested */
0185     res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
0186                   DA9150_QIF_SYNC_SIZE);
0187 
0188     /* Wait for an existing sync to complete */
0189     while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
0190         usleep_range(DA9150_QIF_SYNC_TIMEOUT,
0191                  DA9150_QIF_SYNC_TIMEOUT * 2);
0192         res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
0193                       DA9150_QIF_SYNC_SIZE);
0194     }
0195 
0196     if (res == 0) {
0197         dev_err(fg->dev, "Timeout waiting for existing QIF sync!\n");
0198         mutex_unlock(&fg->io_lock);
0199         return;
0200     }
0201 
0202     /* Write value for QIF code */
0203     da9150_fg_write_attr(fg, code, size, val);
0204 
0205     /* Wait for write acknowledgment */
0206     i = 0;
0207     sync_val = res;
0208     while ((res == sync_val) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
0209         usleep_range(DA9150_QIF_SYNC_TIMEOUT,
0210                  DA9150_QIF_SYNC_TIMEOUT * 2);
0211         res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
0212                       DA9150_QIF_SYNC_SIZE);
0213     }
0214 
0215     mutex_unlock(&fg->io_lock);
0216 
0217     /* Check write was actually successful */
0218     if (res != (sync_val + 1))
0219         dev_err(fg->dev, "Error performing QIF sync write for code %d\n",
0220             code);
0221 }
0222 
0223 /* Power Supply attributes */
0224 static int da9150_fg_capacity(struct da9150_fg *fg,
0225                   union power_supply_propval *val)
0226 {
0227     val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
0228                            DA9150_QIF_SOC_PCT_SIZE);
0229 
0230     if (val->intval > 100)
0231         val->intval = 100;
0232 
0233     return 0;
0234 }
0235 
0236 static int da9150_fg_current_avg(struct da9150_fg *fg,
0237                  union power_supply_propval *val)
0238 {
0239     u32 iavg, sd_gain, shunt_val;
0240     u64 div, res;
0241 
0242     da9150_fg_read_sync_start(fg);
0243     iavg = da9150_fg_read_attr(fg, DA9150_QIF_IAVG,
0244                    DA9150_QIF_IAVG_SIZE);
0245     shunt_val = da9150_fg_read_attr(fg, DA9150_QIF_SHUNT_VAL,
0246                     DA9150_QIF_SHUNT_VAL_SIZE);
0247     sd_gain = da9150_fg_read_attr(fg, DA9150_QIF_SD_GAIN,
0248                       DA9150_QIF_SD_GAIN_SIZE);
0249     da9150_fg_read_sync_end(fg);
0250 
0251     div = (u64) (sd_gain * shunt_val * 65536ULL);
0252     do_div(div, 1000000);
0253     res = (u64) (iavg * 1000000ULL);
0254     do_div(res, div);
0255 
0256     val->intval = (int) res;
0257 
0258     return 0;
0259 }
0260 
0261 static int da9150_fg_voltage_avg(struct da9150_fg *fg,
0262                  union power_supply_propval *val)
0263 {
0264     u64 res;
0265 
0266     val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_UAVG,
0267                            DA9150_QIF_UAVG_SIZE);
0268 
0269     res = (u64) (val->intval * 186ULL);
0270     do_div(res, 10000);
0271     val->intval = (int) res;
0272 
0273     return 0;
0274 }
0275 
0276 static int da9150_fg_charge_full(struct da9150_fg *fg,
0277                  union power_supply_propval *val)
0278 {
0279     val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_FCC_MAH,
0280                            DA9150_QIF_FCC_MAH_SIZE);
0281 
0282     val->intval = val->intval * 1000;
0283 
0284     return 0;
0285 }
0286 
0287 /*
0288  * Temperature reading from device is only valid if battery/system provides
0289  * valid NTC to associated pin of DA9150 chip.
0290  */
0291 static int da9150_fg_temp(struct da9150_fg *fg,
0292               union power_supply_propval *val)
0293 {
0294     val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_NTCAVG,
0295                            DA9150_QIF_NTCAVG_SIZE);
0296 
0297     val->intval = (val->intval * 10) / 1048576;
0298 
0299     return 0;
0300 }
0301 
0302 static enum power_supply_property da9150_fg_props[] = {
0303     POWER_SUPPLY_PROP_CAPACITY,
0304     POWER_SUPPLY_PROP_CURRENT_AVG,
0305     POWER_SUPPLY_PROP_VOLTAGE_AVG,
0306     POWER_SUPPLY_PROP_CHARGE_FULL,
0307     POWER_SUPPLY_PROP_TEMP,
0308 };
0309 
0310 static int da9150_fg_get_prop(struct power_supply *psy,
0311                   enum power_supply_property psp,
0312                   union power_supply_propval *val)
0313 {
0314     struct da9150_fg *fg = dev_get_drvdata(psy->dev.parent);
0315     int ret;
0316 
0317     switch (psp) {
0318     case POWER_SUPPLY_PROP_CAPACITY:
0319         ret = da9150_fg_capacity(fg, val);
0320         break;
0321     case POWER_SUPPLY_PROP_CURRENT_AVG:
0322         ret = da9150_fg_current_avg(fg, val);
0323         break;
0324     case POWER_SUPPLY_PROP_VOLTAGE_AVG:
0325         ret = da9150_fg_voltage_avg(fg, val);
0326         break;
0327     case POWER_SUPPLY_PROP_CHARGE_FULL:
0328         ret = da9150_fg_charge_full(fg, val);
0329         break;
0330     case POWER_SUPPLY_PROP_TEMP:
0331         ret = da9150_fg_temp(fg, val);
0332         break;
0333     default:
0334         ret = -EINVAL;
0335         break;
0336     }
0337 
0338     return ret;
0339 }
0340 
0341 /* Repeated SOC check */
0342 static bool da9150_fg_soc_changed(struct da9150_fg *fg)
0343 {
0344     union power_supply_propval val;
0345 
0346     da9150_fg_capacity(fg, &val);
0347     if (val.intval != fg->soc) {
0348         fg->soc = val.intval;
0349         return true;
0350     }
0351 
0352     return false;
0353 }
0354 
0355 static void da9150_fg_work(struct work_struct *work)
0356 {
0357     struct da9150_fg *fg = container_of(work, struct da9150_fg, work.work);
0358 
0359     /* Report if SOC has changed */
0360     if (da9150_fg_soc_changed(fg))
0361         power_supply_changed(fg->battery);
0362 
0363     schedule_delayed_work(&fg->work, msecs_to_jiffies(fg->interval));
0364 }
0365 
0366 /* SOC level event configuration */
0367 static void da9150_fg_soc_event_config(struct da9150_fg *fg)
0368 {
0369     int soc;
0370 
0371     soc = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
0372                        DA9150_QIF_SOC_PCT_SIZE);
0373 
0374     if (soc > fg->warn_soc) {
0375         /* If SOC > warn level, set discharge warn level event */
0376         da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT,
0377                       DA9150_QIF_DISCHARGE_LIMIT_SIZE,
0378                       fg->warn_soc + 1);
0379     } else if ((soc <= fg->warn_soc) && (soc > fg->crit_soc)) {
0380         /*
0381          * If SOC <= warn level, set discharge crit level event,
0382          * and set charge warn level event.
0383          */
0384         da9150_fg_write_attr_sync(fg, DA9150_QIF_DISCHARGE_LIMIT,
0385                       DA9150_QIF_DISCHARGE_LIMIT_SIZE,
0386                       fg->crit_soc + 1);
0387 
0388         da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT,
0389                       DA9150_QIF_CHARGE_LIMIT_SIZE,
0390                       fg->warn_soc);
0391     } else if (soc <= fg->crit_soc) {
0392         /* If SOC <= crit level, set charge crit level event */
0393         da9150_fg_write_attr_sync(fg, DA9150_QIF_CHARGE_LIMIT,
0394                       DA9150_QIF_CHARGE_LIMIT_SIZE,
0395                       fg->crit_soc);
0396     }
0397 }
0398 
0399 static irqreturn_t da9150_fg_irq(int irq, void *data)
0400 {
0401     struct da9150_fg *fg = data;
0402     u32 e_fg_status;
0403 
0404     /* Read FG IRQ status info */
0405     e_fg_status = da9150_fg_read_attr(fg, DA9150_QIF_E_FG_STATUS,
0406                       DA9150_QIF_E_FG_STATUS_SIZE);
0407 
0408     /* Handle warning/critical threhold events */
0409     if (e_fg_status & DA9150_FG_IRQ_SOC_MASK)
0410         da9150_fg_soc_event_config(fg);
0411 
0412     /* Clear any FG IRQs */
0413     da9150_fg_write_attr(fg, DA9150_QIF_E_FG_STATUS,
0414                  DA9150_QIF_E_FG_STATUS_SIZE, e_fg_status);
0415 
0416     return IRQ_HANDLED;
0417 }
0418 
0419 static struct da9150_fg_pdata *da9150_fg_dt_pdata(struct device *dev)
0420 {
0421     struct device_node *fg_node = dev->of_node;
0422     struct da9150_fg_pdata *pdata;
0423 
0424     pdata = devm_kzalloc(dev, sizeof(struct da9150_fg_pdata), GFP_KERNEL);
0425     if (!pdata)
0426         return NULL;
0427 
0428     of_property_read_u32(fg_node, "dlg,update-interval",
0429                  &pdata->update_interval);
0430     of_property_read_u8(fg_node, "dlg,warn-soc-level",
0431                 &pdata->warn_soc_lvl);
0432     of_property_read_u8(fg_node, "dlg,crit-soc-level",
0433                 &pdata->crit_soc_lvl);
0434 
0435     return pdata;
0436 }
0437 
0438 static const struct power_supply_desc fg_desc = {
0439     .name       = "da9150-fg",
0440     .type       = POWER_SUPPLY_TYPE_BATTERY,
0441     .properties = da9150_fg_props,
0442     .num_properties = ARRAY_SIZE(da9150_fg_props),
0443     .get_property   = da9150_fg_get_prop,
0444 };
0445 
0446 static int da9150_fg_probe(struct platform_device *pdev)
0447 {
0448     struct device *dev = &pdev->dev;
0449     struct da9150 *da9150 = dev_get_drvdata(dev->parent);
0450     struct da9150_fg_pdata *fg_pdata = dev_get_platdata(dev);
0451     struct da9150_fg *fg;
0452     int ver, irq, ret = 0;
0453 
0454     fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL);
0455     if (fg == NULL)
0456         return -ENOMEM;
0457 
0458     platform_set_drvdata(pdev, fg);
0459     fg->da9150 = da9150;
0460     fg->dev = dev;
0461 
0462     mutex_init(&fg->io_lock);
0463 
0464     /* Enable QIF */
0465     da9150_set_bits(da9150, DA9150_CORE2WIRE_CTRL_A, DA9150_FG_QIF_EN_MASK,
0466             DA9150_FG_QIF_EN_MASK);
0467 
0468     fg->battery = devm_power_supply_register(dev, &fg_desc, NULL);
0469     if (IS_ERR(fg->battery)) {
0470         ret = PTR_ERR(fg->battery);
0471         return ret;
0472     }
0473 
0474     ver = da9150_fg_read_attr(fg, DA9150_QIF_FW_MAIN_VER,
0475                   DA9150_QIF_FW_MAIN_VER_SIZE);
0476     dev_info(dev, "Version: 0x%x\n", ver);
0477 
0478     /* Handle DT data if provided */
0479     if (dev->of_node) {
0480         fg_pdata = da9150_fg_dt_pdata(dev);
0481         dev->platform_data = fg_pdata;
0482     }
0483 
0484     /* Handle any pdata provided */
0485     if (fg_pdata) {
0486         fg->interval = fg_pdata->update_interval;
0487 
0488         if (fg_pdata->warn_soc_lvl > 100)
0489             dev_warn(dev, "Invalid SOC warning level provided, Ignoring");
0490         else
0491             fg->warn_soc = fg_pdata->warn_soc_lvl;
0492 
0493         if ((fg_pdata->crit_soc_lvl > 100) ||
0494             (fg_pdata->crit_soc_lvl >= fg_pdata->warn_soc_lvl))
0495             dev_warn(dev, "Invalid SOC critical level provided, Ignoring");
0496         else
0497             fg->crit_soc = fg_pdata->crit_soc_lvl;
0498 
0499 
0500     }
0501 
0502     /* Configure initial SOC level events */
0503     da9150_fg_soc_event_config(fg);
0504 
0505     /*
0506      * If an interval period has been provided then setup repeating
0507      * work for reporting data updates.
0508      */
0509     if (fg->interval) {
0510         ret = devm_delayed_work_autocancel(dev, &fg->work,
0511                            da9150_fg_work);
0512         if (ret) {
0513             dev_err(dev, "Failed to init work\n");
0514             return ret;
0515         }
0516 
0517         schedule_delayed_work(&fg->work,
0518                       msecs_to_jiffies(fg->interval));
0519     }
0520 
0521     /* Register IRQ */
0522     irq = platform_get_irq_byname(pdev, "FG");
0523     if (irq < 0)
0524         return irq;
0525 
0526     ret = devm_request_threaded_irq(dev, irq, NULL, da9150_fg_irq,
0527                     IRQF_ONESHOT, "FG", fg);
0528     if (ret) {
0529         dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
0530         return ret;
0531     }
0532 
0533     return 0;
0534 }
0535 
0536 static int da9150_fg_resume(struct platform_device *pdev)
0537 {
0538     struct da9150_fg *fg = platform_get_drvdata(pdev);
0539 
0540     /*
0541      * Trigger SOC check to happen now so as to indicate any value change
0542      * since last check before suspend.
0543      */
0544     if (fg->interval)
0545         flush_delayed_work(&fg->work);
0546 
0547     return 0;
0548 }
0549 
0550 static struct platform_driver da9150_fg_driver = {
0551     .driver = {
0552         .name = "da9150-fuel-gauge",
0553     },
0554     .probe = da9150_fg_probe,
0555     .resume = da9150_fg_resume,
0556 };
0557 
0558 module_platform_driver(da9150_fg_driver);
0559 
0560 MODULE_DESCRIPTION("Fuel-Gauge Driver for DA9150");
0561 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
0562 MODULE_LICENSE("GPL");