Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * 1-Wire implementation for Maxim Semiconductor
0003  * MAX7211/MAX17215 standalone fuel gauge chip
0004  *
0005  * Copyright (C) 2017 Radioavionica Corporation
0006  * Author: Alex A. Mihaylov <minimumlaw@rambler.ru>
0007  *
0008  * Use consistent with the GNU GPL is permitted,
0009  * provided that this copyright notice is
0010  * preserved in its entirety in all copies and derived works.
0011  *
0012  */
0013 
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/w1.h>
0017 #include <linux/regmap.h>
0018 #include <linux/power_supply.h>
0019 
0020 #define W1_MAX1721X_FAMILY_ID       0x26
0021 #define DEF_DEV_NAME_MAX17211       "MAX17211"
0022 #define DEF_DEV_NAME_MAX17215       "MAX17215"
0023 #define DEF_DEV_NAME_UNKNOWN        "UNKNOWN"
0024 #define DEF_MFG_NAME            "MAXIM"
0025 
0026 #define PSY_MAX_NAME_LEN    32
0027 
0028 /* Number of valid register addresses in W1 mode */
0029 #define MAX1721X_MAX_REG_NR 0x1EF
0030 
0031 /* Factory settings (nonvolatile registers) (W1 specific) */
0032 #define MAX1721X_REG_NRSENSE    0x1CF   /* RSense in 10^-5 Ohm */
0033 /* Strings */
0034 #define MAX1721X_REG_MFG_STR    0x1CC
0035 #define MAX1721X_REG_MFG_NUMB   3
0036 #define MAX1721X_REG_DEV_STR    0x1DB
0037 #define MAX1721X_REG_DEV_NUMB   5
0038 /* HEX Strings */
0039 #define MAX1721X_REG_SER_HEX    0x1D8
0040 
0041 /* MAX172XX Output Registers for W1 chips */
0042 #define MAX172XX_REG_STATUS 0x000   /* status reg */
0043 #define MAX172XX_BAT_PRESENT    (1<<4)  /* battery connected bit */
0044 #define MAX172XX_REG_DEVNAME    0x021   /* chip config */
0045 #define MAX172XX_DEV_MASK   0x000F  /* chip type mask */
0046 #define MAX172X1_DEV        0x0001
0047 #define MAX172X5_DEV        0x0005
0048 #define MAX172XX_REG_TEMP   0x008   /* Temperature */
0049 #define MAX172XX_REG_BATT   0x0DA   /* Battery voltage */
0050 #define MAX172XX_REG_CURRENT    0x00A   /* Actual current */
0051 #define MAX172XX_REG_AVGCURRENT 0x00B   /* Average current */
0052 #define MAX172XX_REG_REPSOC 0x006   /* Percentage of charge */
0053 #define MAX172XX_REG_DESIGNCAP  0x018   /* Design capacity */
0054 #define MAX172XX_REG_REPCAP 0x005   /* Average capacity */
0055 #define MAX172XX_REG_TTE    0x011   /* Time to empty */
0056 #define MAX172XX_REG_TTF    0x020   /* Time to full */
0057 
0058 struct max17211_device_info {
0059     char name[PSY_MAX_NAME_LEN];
0060     struct power_supply *bat;
0061     struct power_supply_desc bat_desc;
0062     struct device *w1_dev;
0063     struct regmap *regmap;
0064     /* battery design format */
0065     unsigned int rsense; /* in tenths uOhm */
0066     char DeviceName[2 * MAX1721X_REG_DEV_NUMB + 1];
0067     char ManufacturerName[2 * MAX1721X_REG_MFG_NUMB + 1];
0068     char SerialNumber[13]; /* see get_sn_str() later for comment */
0069 };
0070 
0071 /* Convert regs value to power_supply units */
0072 
0073 static inline int max172xx_time_to_ps(unsigned int reg)
0074 {
0075     return reg * 5625 / 1000;   /* in sec. */
0076 }
0077 
0078 static inline int max172xx_percent_to_ps(unsigned int reg)
0079 {
0080     return reg / 256;   /* in percent from 0 to 100 */
0081 }
0082 
0083 static inline int max172xx_voltage_to_ps(unsigned int reg)
0084 {
0085     return reg * 1250;  /* in uV */
0086 }
0087 
0088 static inline int max172xx_capacity_to_ps(unsigned int reg)
0089 {
0090     return reg * 500;   /* in uAh */
0091 }
0092 
0093 /*
0094  * Current and temperature is signed values, so unsigned regs
0095  * value must be converted to signed type
0096  */
0097 
0098 static inline int max172xx_temperature_to_ps(unsigned int reg)
0099 {
0100     int val = (int16_t)(reg);
0101 
0102     return val * 10 / 256; /* in tenths of deg. C */
0103 }
0104 
0105 /*
0106  * Calculating current registers resolution:
0107  *
0108  * RSense stored in 10^-5 Ohm, so measurement voltage must be
0109  * in 10^-11 Volts for get current in uA.
0110  * 16 bit current reg fullscale +/-51.2mV is 102400 uV.
0111  * So: 102400 / 65535 * 10^5 = 156252
0112  */
0113 static inline int max172xx_current_to_voltage(unsigned int reg)
0114 {
0115     int val = (int16_t)(reg);
0116 
0117     return val * 156252;
0118 }
0119 
0120 
0121 static inline struct max17211_device_info *
0122 to_device_info(struct power_supply *psy)
0123 {
0124     return power_supply_get_drvdata(psy);
0125 }
0126 
0127 static int max1721x_battery_get_property(struct power_supply *psy,
0128     enum power_supply_property psp,
0129     union power_supply_propval *val)
0130 {
0131     struct max17211_device_info *info = to_device_info(psy);
0132     unsigned int reg = 0;
0133     int ret = 0;
0134 
0135     switch (psp) {
0136     case POWER_SUPPLY_PROP_PRESENT:
0137         /*
0138          * POWER_SUPPLY_PROP_PRESENT will always readable via
0139          * sysfs interface. Value return 0 if battery not
0140          * present or unaccessible via W1.
0141          */
0142         val->intval =
0143             regmap_read(info->regmap, MAX172XX_REG_STATUS,
0144             &reg) ? 0 : !(reg & MAX172XX_BAT_PRESENT);
0145         break;
0146     case POWER_SUPPLY_PROP_CAPACITY:
0147         ret = regmap_read(info->regmap, MAX172XX_REG_REPSOC, &reg);
0148         val->intval = max172xx_percent_to_ps(reg);
0149         break;
0150     case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0151         ret = regmap_read(info->regmap, MAX172XX_REG_BATT, &reg);
0152         val->intval = max172xx_voltage_to_ps(reg);
0153         break;
0154     case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
0155         ret = regmap_read(info->regmap, MAX172XX_REG_DESIGNCAP, &reg);
0156         val->intval = max172xx_capacity_to_ps(reg);
0157         break;
0158     case POWER_SUPPLY_PROP_CHARGE_AVG:
0159         ret = regmap_read(info->regmap, MAX172XX_REG_REPCAP, &reg);
0160         val->intval = max172xx_capacity_to_ps(reg);
0161         break;
0162     case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
0163         ret = regmap_read(info->regmap, MAX172XX_REG_TTE, &reg);
0164         val->intval = max172xx_time_to_ps(reg);
0165         break;
0166     case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
0167         ret = regmap_read(info->regmap, MAX172XX_REG_TTF, &reg);
0168         val->intval = max172xx_time_to_ps(reg);
0169         break;
0170     case POWER_SUPPLY_PROP_TEMP:
0171         ret = regmap_read(info->regmap, MAX172XX_REG_TEMP, &reg);
0172         val->intval = max172xx_temperature_to_ps(reg);
0173         break;
0174     /* We need signed current, so must cast info->rsense to signed type */
0175     case POWER_SUPPLY_PROP_CURRENT_NOW:
0176         ret = regmap_read(info->regmap, MAX172XX_REG_CURRENT, &reg);
0177         val->intval =
0178             max172xx_current_to_voltage(reg) / (int)info->rsense;
0179         break;
0180     case POWER_SUPPLY_PROP_CURRENT_AVG:
0181         ret = regmap_read(info->regmap, MAX172XX_REG_AVGCURRENT, &reg);
0182         val->intval =
0183             max172xx_current_to_voltage(reg) / (int)info->rsense;
0184         break;
0185     /*
0186      * Strings already received and inited by probe.
0187      * We do dummy read for check battery still available.
0188      */
0189     case POWER_SUPPLY_PROP_MODEL_NAME:
0190         ret = regmap_read(info->regmap, MAX1721X_REG_DEV_STR, &reg);
0191         val->strval = info->DeviceName;
0192         break;
0193     case POWER_SUPPLY_PROP_MANUFACTURER:
0194         ret = regmap_read(info->regmap, MAX1721X_REG_MFG_STR, &reg);
0195         val->strval = info->ManufacturerName;
0196         break;
0197     case POWER_SUPPLY_PROP_SERIAL_NUMBER:
0198         ret = regmap_read(info->regmap, MAX1721X_REG_SER_HEX, &reg);
0199         val->strval = info->SerialNumber;
0200         break;
0201     default:
0202         ret = -EINVAL;
0203     }
0204 
0205     return ret;
0206 }
0207 
0208 static enum power_supply_property max1721x_battery_props[] = {
0209     /* int */
0210     POWER_SUPPLY_PROP_PRESENT,
0211     POWER_SUPPLY_PROP_CAPACITY,
0212     POWER_SUPPLY_PROP_VOLTAGE_NOW,
0213     POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
0214     POWER_SUPPLY_PROP_CHARGE_AVG,
0215     POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
0216     POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
0217     POWER_SUPPLY_PROP_TEMP,
0218     POWER_SUPPLY_PROP_CURRENT_NOW,
0219     POWER_SUPPLY_PROP_CURRENT_AVG,
0220     /* strings */
0221     POWER_SUPPLY_PROP_MODEL_NAME,
0222     POWER_SUPPLY_PROP_MANUFACTURER,
0223     POWER_SUPPLY_PROP_SERIAL_NUMBER,
0224 };
0225 
0226 static int get_string(struct max17211_device_info *info,
0227             uint16_t reg, uint8_t nr, char *str)
0228 {
0229     unsigned int val;
0230 
0231     if (!str || !(reg == MAX1721X_REG_MFG_STR ||
0232             reg == MAX1721X_REG_DEV_STR))
0233         return -EFAULT;
0234 
0235     while (nr--) {
0236         if (regmap_read(info->regmap, reg++, &val))
0237             return -EFAULT;
0238         *str++ = val>>8 & 0x00FF;
0239         *str++ = val & 0x00FF;
0240     }
0241     return 0;
0242 }
0243 
0244 /* Maxim say: Serial number is a hex string up to 12 hex characters */
0245 static int get_sn_string(struct max17211_device_info *info, char *str)
0246 {
0247     unsigned int val[3];
0248 
0249     if (!str)
0250         return -EFAULT;
0251 
0252     if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX, &val[0]))
0253         return -EFAULT;
0254     if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX + 1, &val[1]))
0255         return -EFAULT;
0256     if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX + 2, &val[2]))
0257         return -EFAULT;
0258 
0259     snprintf(str, 13, "%04X%04X%04X", val[0], val[1], val[2]);
0260     return 0;
0261 }
0262 
0263 /*
0264  * MAX1721x registers description for w1-regmap
0265  */
0266 static const struct regmap_range max1721x_allow_range[] = {
0267     regmap_reg_range(0, 0xDF),  /* volatile data */
0268     regmap_reg_range(0x180, 0x1DF), /* non-volatile memory */
0269     regmap_reg_range(0x1E0, 0x1EF), /* non-volatile history (unused) */
0270 };
0271 
0272 static const struct regmap_range max1721x_deny_range[] = {
0273     /* volatile data unused registers */
0274     regmap_reg_range(0x24, 0x26),
0275     regmap_reg_range(0x30, 0x31),
0276     regmap_reg_range(0x33, 0x34),
0277     regmap_reg_range(0x37, 0x37),
0278     regmap_reg_range(0x3B, 0x3C),
0279     regmap_reg_range(0x40, 0x41),
0280     regmap_reg_range(0x43, 0x44),
0281     regmap_reg_range(0x47, 0x49),
0282     regmap_reg_range(0x4B, 0x4C),
0283     regmap_reg_range(0x4E, 0xAF),
0284     regmap_reg_range(0xB1, 0xB3),
0285     regmap_reg_range(0xB5, 0xB7),
0286     regmap_reg_range(0xBF, 0xD0),
0287     regmap_reg_range(0xDB, 0xDB),
0288     /* hole between volatile and non-volatile registers */
0289     regmap_reg_range(0xE0, 0x17F),
0290 };
0291 
0292 static const struct regmap_access_table max1721x_regs = {
0293     .yes_ranges = max1721x_allow_range,
0294     .n_yes_ranges   = ARRAY_SIZE(max1721x_allow_range),
0295     .no_ranges  = max1721x_deny_range,
0296     .n_no_ranges    = ARRAY_SIZE(max1721x_deny_range),
0297 };
0298 
0299 /*
0300  * Model Gauge M5 Algorithm output register
0301  * Volatile data (must not be cached)
0302  */
0303 static const struct regmap_range max1721x_volatile_allow[] = {
0304     regmap_reg_range(0, 0xDF),
0305 };
0306 
0307 static const struct regmap_access_table max1721x_volatile_regs = {
0308     .yes_ranges = max1721x_volatile_allow,
0309     .n_yes_ranges   = ARRAY_SIZE(max1721x_volatile_allow),
0310 };
0311 
0312 /*
0313  * W1-regmap config
0314  */
0315 static const struct regmap_config max1721x_regmap_w1_config = {
0316     .reg_bits = 16,
0317     .val_bits = 16,
0318     .rd_table = &max1721x_regs,
0319     .volatile_table = &max1721x_volatile_regs,
0320     .max_register = MAX1721X_MAX_REG_NR,
0321 };
0322 
0323 static int devm_w1_max1721x_add_device(struct w1_slave *sl)
0324 {
0325     struct power_supply_config psy_cfg = {};
0326     struct max17211_device_info *info;
0327 
0328     info = devm_kzalloc(&sl->dev, sizeof(*info), GFP_KERNEL);
0329     if (!info)
0330         return -ENOMEM;
0331 
0332     sl->family_data = (void *)info;
0333     info->w1_dev = &sl->dev;
0334 
0335     /*
0336      * power_supply class battery name translated from W1 slave device
0337      * unique ID (look like 26-0123456789AB) to "max1721x-0123456789AB\0"
0338      * so, 26 (device family) correspond to max1721x devices.
0339      * Device name still unique for any number of connected devices.
0340      */
0341     snprintf(info->name, sizeof(info->name),
0342         "max1721x-%012X", (unsigned int)sl->reg_num.id);
0343     info->bat_desc.name = info->name;
0344 
0345     /*
0346      * FixMe: battery device name exceed max len for thermal_zone device
0347      * name and translation to thermal_zone must be disabled.
0348      */
0349     info->bat_desc.no_thermal = true;
0350     info->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
0351     info->bat_desc.properties = max1721x_battery_props;
0352     info->bat_desc.num_properties = ARRAY_SIZE(max1721x_battery_props);
0353     info->bat_desc.get_property = max1721x_battery_get_property;
0354     psy_cfg.drv_data = info;
0355 
0356     /* regmap init */
0357     info->regmap = devm_regmap_init_w1(info->w1_dev,
0358                     &max1721x_regmap_w1_config);
0359     if (IS_ERR(info->regmap)) {
0360         int err = PTR_ERR(info->regmap);
0361 
0362         dev_err(info->w1_dev, "Failed to allocate register map: %d\n",
0363             err);
0364         return err;
0365     }
0366 
0367     /* rsense init */
0368     info->rsense = 0;
0369     if (regmap_read(info->regmap, MAX1721X_REG_NRSENSE, &info->rsense)) {
0370         dev_err(info->w1_dev, "Can't read RSense. Hardware error.\n");
0371         return -ENODEV;
0372     }
0373 
0374     if (!info->rsense) {
0375         dev_warn(info->w1_dev, "RSense not calibrated, set 10 mOhms!\n");
0376         info->rsense = 1000; /* in regs in 10^-5 */
0377     }
0378     dev_info(info->w1_dev, "RSense: %d mOhms.\n", info->rsense / 100);
0379 
0380     if (get_string(info, MAX1721X_REG_MFG_STR,
0381             MAX1721X_REG_MFG_NUMB, info->ManufacturerName)) {
0382         dev_err(info->w1_dev, "Can't read manufacturer. Hardware error.\n");
0383         return -ENODEV;
0384     }
0385 
0386     if (!info->ManufacturerName[0])
0387         strncpy(info->ManufacturerName, DEF_MFG_NAME,
0388             2 * MAX1721X_REG_MFG_NUMB);
0389 
0390     if (get_string(info, MAX1721X_REG_DEV_STR,
0391             MAX1721X_REG_DEV_NUMB, info->DeviceName)) {
0392         dev_err(info->w1_dev, "Can't read device. Hardware error.\n");
0393         return -ENODEV;
0394     }
0395     if (!info->DeviceName[0]) {
0396         unsigned int dev_name;
0397 
0398         if (regmap_read(info->regmap,
0399                 MAX172XX_REG_DEVNAME, &dev_name)) {
0400             dev_err(info->w1_dev, "Can't read device name reg.\n");
0401             return -ENODEV;
0402         }
0403 
0404         switch (dev_name & MAX172XX_DEV_MASK) {
0405         case MAX172X1_DEV:
0406             strncpy(info->DeviceName, DEF_DEV_NAME_MAX17211,
0407                 2 * MAX1721X_REG_DEV_NUMB);
0408             break;
0409         case MAX172X5_DEV:
0410             strncpy(info->DeviceName, DEF_DEV_NAME_MAX17215,
0411                 2 * MAX1721X_REG_DEV_NUMB);
0412             break;
0413         default:
0414             strncpy(info->DeviceName, DEF_DEV_NAME_UNKNOWN,
0415                 2 * MAX1721X_REG_DEV_NUMB);
0416         }
0417     }
0418 
0419     if (get_sn_string(info, info->SerialNumber)) {
0420         dev_err(info->w1_dev, "Can't read serial. Hardware error.\n");
0421         return -ENODEV;
0422     }
0423 
0424     info->bat = devm_power_supply_register(&sl->dev, &info->bat_desc,
0425                         &psy_cfg);
0426     if (IS_ERR(info->bat)) {
0427         dev_err(info->w1_dev, "failed to register battery\n");
0428         return PTR_ERR(info->bat);
0429     }
0430 
0431     return 0;
0432 }
0433 
0434 static const struct w1_family_ops w1_max1721x_fops = {
0435     .add_slave = devm_w1_max1721x_add_device,
0436 };
0437 
0438 static struct w1_family w1_max1721x_family = {
0439     .fid = W1_MAX1721X_FAMILY_ID,
0440     .fops = &w1_max1721x_fops,
0441 };
0442 
0443 module_w1_family(w1_max1721x_family);
0444 
0445 MODULE_LICENSE("GPL");
0446 MODULE_AUTHOR("Alex A. Mihaylov <minimumlaw@rambler.ru>");
0447 MODULE_DESCRIPTION("Maxim MAX17211/MAX17215 Fuel Gauage IC driver");
0448 MODULE_ALIAS("w1-family-" __stringify(W1_MAX1721X_FAMILY_ID));