root/drivers/hwmon/da9052-hwmon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. volt_reg_to_mv
  2. input_reg_to_mv
  3. vbbat_reg_to_mv
  4. input_tsireg_to_mv
  5. da9052_enable_vddout_channel
  6. da9052_disable_vddout_channel
  7. da9052_vddout_show
  8. da9052_ich_show
  9. da9052_tbat_show
  10. da9052_vbat_show
  11. da9052_misc_channel_show
  12. da9052_request_tsi_read
  13. da9052_get_tsi_result
  14. __da9052_read_tsi
  15. da9052_tsi_show
  16. da9052_tjunc_show
  17. da9052_vbbat_show
  18. label_show
  19. da9052_channel_is_visible
  20. da9052_tsi_datardy_irq
  21. da9052_hwmon_probe
  22. da9052_hwmon_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * HWMON Driver for Dialog DA9052
   4  *
   5  * Copyright(c) 2012 Dialog Semiconductor Ltd.
   6  *
   7  * Author: David Dajun Chen <dchen@diasemi.com>
   8  */
   9 
  10 #include <linux/err.h>
  11 #include <linux/hwmon.h>
  12 #include <linux/hwmon-sysfs.h>
  13 #include <linux/init.h>
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/slab.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/property.h>
  19 
  20 #include <linux/mfd/da9052/da9052.h>
  21 #include <linux/mfd/da9052/reg.h>
  22 #include <linux/regulator/consumer.h>
  23 
  24 struct da9052_hwmon {
  25         struct da9052           *da9052;
  26         struct mutex            hwmon_lock;
  27         bool                    tsi_as_adc;
  28         int                     tsiref_mv;
  29         struct regulator        *tsiref;
  30         struct completion       tsidone;
  31 };
  32 
  33 static const char * const input_names[] = {
  34         [DA9052_ADC_VDDOUT]     =       "VDDOUT",
  35         [DA9052_ADC_ICH]        =       "CHARGING CURRENT",
  36         [DA9052_ADC_TBAT]       =       "BATTERY TEMP",
  37         [DA9052_ADC_VBAT]       =       "BATTERY VOLTAGE",
  38         [DA9052_ADC_IN4]        =       "ADC IN4",
  39         [DA9052_ADC_IN5]        =       "ADC IN5",
  40         [DA9052_ADC_IN6]        =       "ADC IN6",
  41         [DA9052_ADC_TSI_XP]     =       "ADC TS X+",
  42         [DA9052_ADC_TSI_YP]     =       "ADC TS Y+",
  43         [DA9052_ADC_TSI_XN]     =       "ADC TS X-",
  44         [DA9052_ADC_TSI_YN]     =       "ADC TS Y-",
  45         [DA9052_ADC_TJUNC]      =       "BATTERY JUNCTION TEMP",
  46         [DA9052_ADC_VBBAT]      =       "BACK-UP BATTERY VOLTAGE",
  47 };
  48 
  49 /* Conversion function for VDDOUT and VBAT */
  50 static inline int volt_reg_to_mv(int value)
  51 {
  52         return DIV_ROUND_CLOSEST(value * 2000, 1023) + 2500;
  53 }
  54 
  55 /* Conversion function for ADC channels 4, 5 and 6 */
  56 static inline int input_reg_to_mv(int value)
  57 {
  58         return DIV_ROUND_CLOSEST(value * 2500, 1023);
  59 }
  60 
  61 /* Conversion function for VBBAT */
  62 static inline int vbbat_reg_to_mv(int value)
  63 {
  64         return DIV_ROUND_CLOSEST(value * 5000, 1023);
  65 }
  66 
  67 static inline int input_tsireg_to_mv(struct da9052_hwmon *hwmon, int value)
  68 {
  69         return DIV_ROUND_CLOSEST(value * hwmon->tsiref_mv, 1023);
  70 }
  71 
  72 static inline int da9052_enable_vddout_channel(struct da9052 *da9052)
  73 {
  74         return da9052_reg_update(da9052, DA9052_ADC_CONT_REG,
  75                                  DA9052_ADCCONT_AUTOVDDEN,
  76                                  DA9052_ADCCONT_AUTOVDDEN);
  77 }
  78 
  79 static inline int da9052_disable_vddout_channel(struct da9052 *da9052)
  80 {
  81         return da9052_reg_update(da9052, DA9052_ADC_CONT_REG,
  82                                  DA9052_ADCCONT_AUTOVDDEN, 0);
  83 }
  84 
  85 static ssize_t da9052_vddout_show(struct device *dev,
  86                                   struct device_attribute *devattr, char *buf)
  87 {
  88         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
  89         int ret, vdd;
  90 
  91         mutex_lock(&hwmon->hwmon_lock);
  92 
  93         ret = da9052_enable_vddout_channel(hwmon->da9052);
  94         if (ret < 0)
  95                 goto hwmon_err;
  96 
  97         vdd = da9052_reg_read(hwmon->da9052, DA9052_VDD_RES_REG);
  98         if (vdd < 0) {
  99                 ret = vdd;
 100                 goto hwmon_err_release;
 101         }
 102 
 103         ret = da9052_disable_vddout_channel(hwmon->da9052);
 104         if (ret < 0)
 105                 goto hwmon_err;
 106 
 107         mutex_unlock(&hwmon->hwmon_lock);
 108         return sprintf(buf, "%d\n", volt_reg_to_mv(vdd));
 109 
 110 hwmon_err_release:
 111         da9052_disable_vddout_channel(hwmon->da9052);
 112 hwmon_err:
 113         mutex_unlock(&hwmon->hwmon_lock);
 114         return ret;
 115 }
 116 
 117 static ssize_t da9052_ich_show(struct device *dev,
 118                                struct device_attribute *devattr, char *buf)
 119 {
 120         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 121         int ret;
 122 
 123         ret = da9052_reg_read(hwmon->da9052, DA9052_ICHG_AV_REG);
 124         if (ret < 0)
 125                 return ret;
 126 
 127         /* Equivalent to 3.9mA/bit in register ICHG_AV */
 128         return sprintf(buf, "%d\n", DIV_ROUND_CLOSEST(ret * 39, 10));
 129 }
 130 
 131 static ssize_t da9052_tbat_show(struct device *dev,
 132                                 struct device_attribute *devattr, char *buf)
 133 {
 134         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 135 
 136         return sprintf(buf, "%d\n", da9052_adc_read_temp(hwmon->da9052));
 137 }
 138 
 139 static ssize_t da9052_vbat_show(struct device *dev,
 140                                 struct device_attribute *devattr, char *buf)
 141 {
 142         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 143         int ret;
 144 
 145         ret = da9052_adc_manual_read(hwmon->da9052, DA9052_ADC_VBAT);
 146         if (ret < 0)
 147                 return ret;
 148 
 149         return sprintf(buf, "%d\n", volt_reg_to_mv(ret));
 150 }
 151 
 152 static ssize_t da9052_misc_channel_show(struct device *dev,
 153                                         struct device_attribute *devattr,
 154                                         char *buf)
 155 {
 156         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 157         int channel = to_sensor_dev_attr(devattr)->index;
 158         int ret;
 159 
 160         ret = da9052_adc_manual_read(hwmon->da9052, channel);
 161         if (ret < 0)
 162                 return ret;
 163 
 164         return sprintf(buf, "%d\n", input_reg_to_mv(ret));
 165 }
 166 
 167 static int da9052_request_tsi_read(struct da9052_hwmon *hwmon, int channel)
 168 {
 169         u8 val = DA9052_TSICONTB_TSIMAN;
 170 
 171         switch (channel) {
 172         case DA9052_ADC_TSI_XP:
 173                 val |= DA9052_TSICONTB_TSIMUX_XP;
 174                 break;
 175         case DA9052_ADC_TSI_YP:
 176                 val |= DA9052_TSICONTB_TSIMUX_YP;
 177                 break;
 178         case DA9052_ADC_TSI_XN:
 179                 val |= DA9052_TSICONTB_TSIMUX_XN;
 180                 break;
 181         case DA9052_ADC_TSI_YN:
 182                 val |= DA9052_TSICONTB_TSIMUX_YN;
 183                 break;
 184         }
 185 
 186         return da9052_reg_write(hwmon->da9052, DA9052_TSI_CONT_B_REG, val);
 187 }
 188 
 189 static int da9052_get_tsi_result(struct da9052_hwmon *hwmon, int channel)
 190 {
 191         u8 regs[3];
 192         int msb, lsb, err;
 193 
 194         /* block read to avoid separation of MSB and LSB */
 195         err = da9052_group_read(hwmon->da9052, DA9052_TSI_X_MSB_REG,
 196                                 ARRAY_SIZE(regs), regs);
 197         if (err)
 198                 return err;
 199 
 200         switch (channel) {
 201         case DA9052_ADC_TSI_XP:
 202         case DA9052_ADC_TSI_XN:
 203                 msb = regs[0] << DA9052_TSILSB_TSIXL_BITS;
 204                 lsb = regs[2] & DA9052_TSILSB_TSIXL;
 205                 lsb >>= DA9052_TSILSB_TSIXL_SHIFT;
 206                 break;
 207         case DA9052_ADC_TSI_YP:
 208         case DA9052_ADC_TSI_YN:
 209                 msb = regs[1] << DA9052_TSILSB_TSIYL_BITS;
 210                 lsb = regs[2] & DA9052_TSILSB_TSIYL;
 211                 lsb >>= DA9052_TSILSB_TSIYL_SHIFT;
 212                 break;
 213         default:
 214                 return -EINVAL;
 215         }
 216 
 217         return msb | lsb;
 218 }
 219 
 220 
 221 static ssize_t __da9052_read_tsi(struct device *dev, int channel)
 222 {
 223         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 224         int ret;
 225 
 226         reinit_completion(&hwmon->tsidone);
 227 
 228         ret = da9052_request_tsi_read(hwmon, channel);
 229         if (ret < 0)
 230                 return ret;
 231 
 232         /* Wait for an conversion done interrupt */
 233         if (!wait_for_completion_timeout(&hwmon->tsidone,
 234                                          msecs_to_jiffies(500)))
 235                 return -ETIMEDOUT;
 236 
 237         return da9052_get_tsi_result(hwmon, channel);
 238 }
 239 
 240 static ssize_t da9052_tsi_show(struct device *dev,
 241                                struct device_attribute *devattr, char *buf)
 242 {
 243         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 244         int channel = to_sensor_dev_attr(devattr)->index;
 245         int ret;
 246 
 247         mutex_lock(&hwmon->da9052->auxadc_lock);
 248         ret = __da9052_read_tsi(dev, channel);
 249         mutex_unlock(&hwmon->da9052->auxadc_lock);
 250 
 251         if (ret < 0)
 252                 return ret;
 253         else
 254                 return sprintf(buf, "%d\n", input_tsireg_to_mv(hwmon, ret));
 255 }
 256 
 257 static ssize_t da9052_tjunc_show(struct device *dev,
 258                                  struct device_attribute *devattr, char *buf)
 259 {
 260         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 261         int tjunc;
 262         int toffset;
 263 
 264         tjunc = da9052_reg_read(hwmon->da9052, DA9052_TJUNC_RES_REG);
 265         if (tjunc < 0)
 266                 return tjunc;
 267 
 268         toffset = da9052_reg_read(hwmon->da9052, DA9052_T_OFFSET_REG);
 269         if (toffset < 0)
 270                 return toffset;
 271 
 272         /*
 273          * Degrees celsius = 1.708 * (TJUNC_RES - T_OFFSET) - 108.8
 274          * T_OFFSET is a trim value used to improve accuracy of the result
 275          */
 276         return sprintf(buf, "%d\n", 1708 * (tjunc - toffset) - 108800);
 277 }
 278 
 279 static ssize_t da9052_vbbat_show(struct device *dev,
 280                                  struct device_attribute *devattr, char *buf)
 281 {
 282         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 283         int ret;
 284 
 285         ret = da9052_adc_manual_read(hwmon->da9052, DA9052_ADC_VBBAT);
 286         if (ret < 0)
 287                 return ret;
 288 
 289         return sprintf(buf, "%d\n", vbbat_reg_to_mv(ret));
 290 }
 291 
 292 static ssize_t label_show(struct device *dev,
 293                           struct device_attribute *devattr, char *buf)
 294 {
 295         return sprintf(buf, "%s\n",
 296                        input_names[to_sensor_dev_attr(devattr)->index]);
 297 }
 298 
 299 static umode_t da9052_channel_is_visible(struct kobject *kobj,
 300                                          struct attribute *attr, int index)
 301 {
 302         struct device *dev = container_of(kobj, struct device, kobj);
 303         struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 304         struct device_attribute *dattr = container_of(attr,
 305                                 struct device_attribute, attr);
 306         struct sensor_device_attribute *sattr = to_sensor_dev_attr(dattr);
 307 
 308         if (!hwmon->tsi_as_adc) {
 309                 switch (sattr->index) {
 310                 case DA9052_ADC_TSI_XP:
 311                 case DA9052_ADC_TSI_YP:
 312                 case DA9052_ADC_TSI_XN:
 313                 case DA9052_ADC_TSI_YN:
 314                         return 0;
 315                 }
 316         }
 317 
 318         return attr->mode;
 319 }
 320 
 321 static SENSOR_DEVICE_ATTR_RO(in0_input, da9052_vddout, DA9052_ADC_VDDOUT);
 322 static SENSOR_DEVICE_ATTR_RO(in0_label, label, DA9052_ADC_VDDOUT);
 323 static SENSOR_DEVICE_ATTR_RO(in3_input, da9052_vbat, DA9052_ADC_VBAT);
 324 static SENSOR_DEVICE_ATTR_RO(in3_label, label, DA9052_ADC_VBAT);
 325 static SENSOR_DEVICE_ATTR_RO(in4_input, da9052_misc_channel, DA9052_ADC_IN4);
 326 static SENSOR_DEVICE_ATTR_RO(in4_label, label, DA9052_ADC_IN4);
 327 static SENSOR_DEVICE_ATTR_RO(in5_input, da9052_misc_channel, DA9052_ADC_IN5);
 328 static SENSOR_DEVICE_ATTR_RO(in5_label, label, DA9052_ADC_IN5);
 329 static SENSOR_DEVICE_ATTR_RO(in6_input, da9052_misc_channel, DA9052_ADC_IN6);
 330 static SENSOR_DEVICE_ATTR_RO(in6_label, label, DA9052_ADC_IN6);
 331 static SENSOR_DEVICE_ATTR_RO(in9_input, da9052_vbbat, DA9052_ADC_VBBAT);
 332 static SENSOR_DEVICE_ATTR_RO(in9_label, label, DA9052_ADC_VBBAT);
 333 
 334 static SENSOR_DEVICE_ATTR_RO(in70_input, da9052_tsi, DA9052_ADC_TSI_XP);
 335 static SENSOR_DEVICE_ATTR_RO(in70_label, label, DA9052_ADC_TSI_XP);
 336 static SENSOR_DEVICE_ATTR_RO(in71_input, da9052_tsi, DA9052_ADC_TSI_XN);
 337 static SENSOR_DEVICE_ATTR_RO(in71_label, label, DA9052_ADC_TSI_XN);
 338 static SENSOR_DEVICE_ATTR_RO(in72_input, da9052_tsi, DA9052_ADC_TSI_YP);
 339 static SENSOR_DEVICE_ATTR_RO(in72_label, label, DA9052_ADC_TSI_YP);
 340 static SENSOR_DEVICE_ATTR_RO(in73_input, da9052_tsi, DA9052_ADC_TSI_YN);
 341 static SENSOR_DEVICE_ATTR_RO(in73_label, label, DA9052_ADC_TSI_YN);
 342 
 343 static SENSOR_DEVICE_ATTR_RO(curr1_input, da9052_ich, DA9052_ADC_ICH);
 344 static SENSOR_DEVICE_ATTR_RO(curr1_label, label, DA9052_ADC_ICH);
 345 
 346 static SENSOR_DEVICE_ATTR_RO(temp2_input, da9052_tbat, DA9052_ADC_TBAT);
 347 static SENSOR_DEVICE_ATTR_RO(temp2_label, label, DA9052_ADC_TBAT);
 348 static SENSOR_DEVICE_ATTR_RO(temp8_input, da9052_tjunc, DA9052_ADC_TJUNC);
 349 static SENSOR_DEVICE_ATTR_RO(temp8_label, label, DA9052_ADC_TJUNC);
 350 
 351 static struct attribute *da9052_attrs[] = {
 352         &sensor_dev_attr_in0_input.dev_attr.attr,
 353         &sensor_dev_attr_in0_label.dev_attr.attr,
 354         &sensor_dev_attr_in3_input.dev_attr.attr,
 355         &sensor_dev_attr_in3_label.dev_attr.attr,
 356         &sensor_dev_attr_in4_input.dev_attr.attr,
 357         &sensor_dev_attr_in4_label.dev_attr.attr,
 358         &sensor_dev_attr_in5_input.dev_attr.attr,
 359         &sensor_dev_attr_in5_label.dev_attr.attr,
 360         &sensor_dev_attr_in6_input.dev_attr.attr,
 361         &sensor_dev_attr_in6_label.dev_attr.attr,
 362         &sensor_dev_attr_in70_input.dev_attr.attr,
 363         &sensor_dev_attr_in70_label.dev_attr.attr,
 364         &sensor_dev_attr_in71_input.dev_attr.attr,
 365         &sensor_dev_attr_in71_label.dev_attr.attr,
 366         &sensor_dev_attr_in72_input.dev_attr.attr,
 367         &sensor_dev_attr_in72_label.dev_attr.attr,
 368         &sensor_dev_attr_in73_input.dev_attr.attr,
 369         &sensor_dev_attr_in73_label.dev_attr.attr,
 370         &sensor_dev_attr_in9_input.dev_attr.attr,
 371         &sensor_dev_attr_in9_label.dev_attr.attr,
 372         &sensor_dev_attr_curr1_input.dev_attr.attr,
 373         &sensor_dev_attr_curr1_label.dev_attr.attr,
 374         &sensor_dev_attr_temp2_input.dev_attr.attr,
 375         &sensor_dev_attr_temp2_label.dev_attr.attr,
 376         &sensor_dev_attr_temp8_input.dev_attr.attr,
 377         &sensor_dev_attr_temp8_label.dev_attr.attr,
 378         NULL
 379 };
 380 
 381 static const struct attribute_group da9052_group = {
 382         .attrs = da9052_attrs,
 383         .is_visible = da9052_channel_is_visible,
 384 };
 385 __ATTRIBUTE_GROUPS(da9052);
 386 
 387 static irqreturn_t da9052_tsi_datardy_irq(int irq, void *data)
 388 {
 389         struct da9052_hwmon *hwmon = data;
 390 
 391         complete(&hwmon->tsidone);
 392         return IRQ_HANDLED;
 393 }
 394 
 395 static int da9052_hwmon_probe(struct platform_device *pdev)
 396 {
 397         struct device *dev = &pdev->dev;
 398         struct da9052_hwmon *hwmon;
 399         struct device *hwmon_dev;
 400         int err;
 401 
 402         hwmon = devm_kzalloc(dev, sizeof(struct da9052_hwmon), GFP_KERNEL);
 403         if (!hwmon)
 404                 return -ENOMEM;
 405 
 406         platform_set_drvdata(pdev, hwmon);
 407 
 408         mutex_init(&hwmon->hwmon_lock);
 409         hwmon->da9052 = dev_get_drvdata(pdev->dev.parent);
 410 
 411         init_completion(&hwmon->tsidone);
 412 
 413         hwmon->tsi_as_adc =
 414                 device_property_read_bool(pdev->dev.parent, "dlg,tsi-as-adc");
 415 
 416         if (hwmon->tsi_as_adc) {
 417                 hwmon->tsiref = devm_regulator_get(pdev->dev.parent, "tsiref");
 418                 if (IS_ERR(hwmon->tsiref)) {
 419                         err = PTR_ERR(hwmon->tsiref);
 420                         dev_err(&pdev->dev, "failed to get tsiref: %d", err);
 421                         return err;
 422                 }
 423 
 424                 err = regulator_enable(hwmon->tsiref);
 425                 if (err)
 426                         return err;
 427 
 428                 hwmon->tsiref_mv = regulator_get_voltage(hwmon->tsiref);
 429                 if (hwmon->tsiref_mv < 0) {
 430                         err = hwmon->tsiref_mv;
 431                         goto exit_regulator;
 432                 }
 433 
 434                 /* convert from microvolt (DT) to millivolt (hwmon) */
 435                 hwmon->tsiref_mv /= 1000;
 436 
 437                 /* TSIREF limits from datasheet */
 438                 if (hwmon->tsiref_mv < 1800 || hwmon->tsiref_mv > 2600) {
 439                         dev_err(hwmon->da9052->dev, "invalid TSIREF voltage: %d",
 440                                 hwmon->tsiref_mv);
 441                         err = -ENXIO;
 442                         goto exit_regulator;
 443                 }
 444 
 445                 /* disable touchscreen features */
 446                 da9052_reg_write(hwmon->da9052, DA9052_TSI_CONT_A_REG, 0x00);
 447 
 448                 /* Sample every 1ms */
 449                 da9052_reg_update(hwmon->da9052, DA9052_ADC_CONT_REG,
 450                                           DA9052_ADCCONT_ADCMODE,
 451                                           DA9052_ADCCONT_ADCMODE);
 452 
 453                 err = da9052_request_irq(hwmon->da9052, DA9052_IRQ_TSIREADY,
 454                                          "tsiready-irq", da9052_tsi_datardy_irq,
 455                                          hwmon);
 456                 if (err) {
 457                         dev_err(&pdev->dev, "Failed to register TSIRDY IRQ: %d",
 458                                 err);
 459                         goto exit_regulator;
 460                 }
 461         }
 462 
 463         hwmon_dev = devm_hwmon_device_register_with_groups(dev, "da9052",
 464                                                            hwmon,
 465                                                            da9052_groups);
 466         err = PTR_ERR_OR_ZERO(hwmon_dev);
 467         if (err)
 468                 goto exit_irq;
 469 
 470         return 0;
 471 
 472 exit_irq:
 473         if (hwmon->tsi_as_adc)
 474                 da9052_free_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, hwmon);
 475 exit_regulator:
 476         if (hwmon->tsiref)
 477                 regulator_disable(hwmon->tsiref);
 478 
 479         return err;
 480 }
 481 
 482 static int da9052_hwmon_remove(struct platform_device *pdev)
 483 {
 484         struct da9052_hwmon *hwmon = platform_get_drvdata(pdev);
 485 
 486         if (hwmon->tsi_as_adc) {
 487                 da9052_free_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, hwmon);
 488                 regulator_disable(hwmon->tsiref);
 489         }
 490 
 491         return 0;
 492 }
 493 
 494 static struct platform_driver da9052_hwmon_driver = {
 495         .probe = da9052_hwmon_probe,
 496         .remove = da9052_hwmon_remove,
 497         .driver = {
 498                 .name = "da9052-hwmon",
 499         },
 500 };
 501 
 502 module_platform_driver(da9052_hwmon_driver);
 503 
 504 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
 505 MODULE_DESCRIPTION("DA9052 HWMON driver");
 506 MODULE_LICENSE("GPL");
 507 MODULE_ALIAS("platform:da9052-hwmon");

/* [<][>][^][v][top][bottom][index][help] */