1*16d60ba8SDaniel Matyas // SPDX-License-Identifier: GPL-2.0 2*16d60ba8SDaniel Matyas /* 3*16d60ba8SDaniel Matyas * max31827.c - Support for Maxim Low-Power Switch 4*16d60ba8SDaniel Matyas * 5*16d60ba8SDaniel Matyas * Copyright (c) 2023 Daniel Matyas <daniel.matyas@analog.com> 6*16d60ba8SDaniel Matyas */ 7*16d60ba8SDaniel Matyas 8*16d60ba8SDaniel Matyas #include <linux/bitfield.h> 9*16d60ba8SDaniel Matyas #include <linux/bitops.h> 10*16d60ba8SDaniel Matyas #include <linux/delay.h> 11*16d60ba8SDaniel Matyas #include <linux/hwmon.h> 12*16d60ba8SDaniel Matyas #include <linux/i2c.h> 13*16d60ba8SDaniel Matyas #include <linux/mutex.h> 14*16d60ba8SDaniel Matyas #include <linux/regmap.h> 15*16d60ba8SDaniel Matyas 16*16d60ba8SDaniel Matyas #define MAX31827_T_REG 0x0 17*16d60ba8SDaniel Matyas #define MAX31827_CONFIGURATION_REG 0x2 18*16d60ba8SDaniel Matyas #define MAX31827_TH_REG 0x4 19*16d60ba8SDaniel Matyas #define MAX31827_TL_REG 0x6 20*16d60ba8SDaniel Matyas #define MAX31827_TH_HYST_REG 0x8 21*16d60ba8SDaniel Matyas #define MAX31827_TL_HYST_REG 0xA 22*16d60ba8SDaniel Matyas 23*16d60ba8SDaniel Matyas #define MAX31827_CONFIGURATION_1SHOT_MASK BIT(0) 24*16d60ba8SDaniel Matyas #define MAX31827_CONFIGURATION_CNV_RATE_MASK GENMASK(3, 1) 25*16d60ba8SDaniel Matyas #define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK BIT(14) 26*16d60ba8SDaniel Matyas #define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK BIT(15) 27*16d60ba8SDaniel Matyas 28*16d60ba8SDaniel Matyas #define MAX31827_12_BIT_CNV_TIME 141 29*16d60ba8SDaniel Matyas 30*16d60ba8SDaniel Matyas #define MAX31827_CNV_1_DIV_64_HZ 0x1 31*16d60ba8SDaniel Matyas #define MAX31827_CNV_1_DIV_32_HZ 0x2 32*16d60ba8SDaniel Matyas #define MAX31827_CNV_1_DIV_16_HZ 0x3 33*16d60ba8SDaniel Matyas #define MAX31827_CNV_1_DIV_4_HZ 0x4 34*16d60ba8SDaniel Matyas #define MAX31827_CNV_1_HZ 0x5 35*16d60ba8SDaniel Matyas #define MAX31827_CNV_4_HZ 0x6 36*16d60ba8SDaniel Matyas #define MAX31827_CNV_8_HZ 0x7 37*16d60ba8SDaniel Matyas 38*16d60ba8SDaniel Matyas #define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16) 39*16d60ba8SDaniel Matyas #define MAX31827_M_DGR_TO_16_BIT(x) (((x) << 4) / 1000) 40*16d60ba8SDaniel Matyas #define MAX31827_DEVICE_ENABLE(x) ((x) ? 0xA : 0x0) 41*16d60ba8SDaniel Matyas 42*16d60ba8SDaniel Matyas struct max31827_state { 43*16d60ba8SDaniel Matyas /* 44*16d60ba8SDaniel Matyas * Prevent simultaneous access to the i2c client. 45*16d60ba8SDaniel Matyas */ 46*16d60ba8SDaniel Matyas struct mutex lock; 47*16d60ba8SDaniel Matyas struct regmap *regmap; 48*16d60ba8SDaniel Matyas bool enable; 49*16d60ba8SDaniel Matyas }; 50*16d60ba8SDaniel Matyas 51*16d60ba8SDaniel Matyas static const struct regmap_config max31827_regmap = { 52*16d60ba8SDaniel Matyas .reg_bits = 8, 53*16d60ba8SDaniel Matyas .val_bits = 16, 54*16d60ba8SDaniel Matyas .max_register = 0xA, 55*16d60ba8SDaniel Matyas }; 56*16d60ba8SDaniel Matyas 57*16d60ba8SDaniel Matyas static int write_alarm_val(struct max31827_state *st, unsigned int reg, 58*16d60ba8SDaniel Matyas long val) 59*16d60ba8SDaniel Matyas { 60*16d60ba8SDaniel Matyas unsigned int cfg; 61*16d60ba8SDaniel Matyas unsigned int tmp; 62*16d60ba8SDaniel Matyas int ret; 63*16d60ba8SDaniel Matyas 64*16d60ba8SDaniel Matyas val = MAX31827_M_DGR_TO_16_BIT(val); 65*16d60ba8SDaniel Matyas 66*16d60ba8SDaniel Matyas /* 67*16d60ba8SDaniel Matyas * Before the Temperature Threshold Alarm and Alarm Hysteresis Threshold 68*16d60ba8SDaniel Matyas * register values are changed over I2C, the part must be in shutdown 69*16d60ba8SDaniel Matyas * mode. 70*16d60ba8SDaniel Matyas * 71*16d60ba8SDaniel Matyas * Mutex is used to ensure, that some other process doesn't change the 72*16d60ba8SDaniel Matyas * configuration register. 73*16d60ba8SDaniel Matyas */ 74*16d60ba8SDaniel Matyas mutex_lock(&st->lock); 75*16d60ba8SDaniel Matyas 76*16d60ba8SDaniel Matyas if (!st->enable) { 77*16d60ba8SDaniel Matyas ret = regmap_write(st->regmap, reg, val); 78*16d60ba8SDaniel Matyas goto unlock; 79*16d60ba8SDaniel Matyas } 80*16d60ba8SDaniel Matyas 81*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, MAX31827_CONFIGURATION_REG, &cfg); 82*16d60ba8SDaniel Matyas if (ret) 83*16d60ba8SDaniel Matyas goto unlock; 84*16d60ba8SDaniel Matyas 85*16d60ba8SDaniel Matyas tmp = cfg & ~(MAX31827_CONFIGURATION_1SHOT_MASK | 86*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_CNV_RATE_MASK); 87*16d60ba8SDaniel Matyas ret = regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, tmp); 88*16d60ba8SDaniel Matyas if (ret) 89*16d60ba8SDaniel Matyas goto unlock; 90*16d60ba8SDaniel Matyas 91*16d60ba8SDaniel Matyas ret = regmap_write(st->regmap, reg, val); 92*16d60ba8SDaniel Matyas if (ret) 93*16d60ba8SDaniel Matyas goto unlock; 94*16d60ba8SDaniel Matyas 95*16d60ba8SDaniel Matyas ret = regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, cfg); 96*16d60ba8SDaniel Matyas 97*16d60ba8SDaniel Matyas unlock: 98*16d60ba8SDaniel Matyas mutex_unlock(&st->lock); 99*16d60ba8SDaniel Matyas return ret; 100*16d60ba8SDaniel Matyas } 101*16d60ba8SDaniel Matyas 102*16d60ba8SDaniel Matyas static umode_t max31827_is_visible(const void *state, 103*16d60ba8SDaniel Matyas enum hwmon_sensor_types type, u32 attr, 104*16d60ba8SDaniel Matyas int channel) 105*16d60ba8SDaniel Matyas { 106*16d60ba8SDaniel Matyas if (type == hwmon_temp) { 107*16d60ba8SDaniel Matyas switch (attr) { 108*16d60ba8SDaniel Matyas case hwmon_temp_enable: 109*16d60ba8SDaniel Matyas case hwmon_temp_max: 110*16d60ba8SDaniel Matyas case hwmon_temp_min: 111*16d60ba8SDaniel Matyas case hwmon_temp_max_hyst: 112*16d60ba8SDaniel Matyas case hwmon_temp_min_hyst: 113*16d60ba8SDaniel Matyas return 0644; 114*16d60ba8SDaniel Matyas case hwmon_temp_input: 115*16d60ba8SDaniel Matyas case hwmon_temp_min_alarm: 116*16d60ba8SDaniel Matyas case hwmon_temp_max_alarm: 117*16d60ba8SDaniel Matyas return 0444; 118*16d60ba8SDaniel Matyas default: 119*16d60ba8SDaniel Matyas return 0; 120*16d60ba8SDaniel Matyas } 121*16d60ba8SDaniel Matyas } else if (type == hwmon_chip) { 122*16d60ba8SDaniel Matyas if (attr == hwmon_chip_update_interval) 123*16d60ba8SDaniel Matyas return 0644; 124*16d60ba8SDaniel Matyas } 125*16d60ba8SDaniel Matyas 126*16d60ba8SDaniel Matyas return 0; 127*16d60ba8SDaniel Matyas } 128*16d60ba8SDaniel Matyas 129*16d60ba8SDaniel Matyas static int max31827_read(struct device *dev, enum hwmon_sensor_types type, 130*16d60ba8SDaniel Matyas u32 attr, int channel, long *val) 131*16d60ba8SDaniel Matyas { 132*16d60ba8SDaniel Matyas struct max31827_state *st = dev_get_drvdata(dev); 133*16d60ba8SDaniel Matyas unsigned int uval; 134*16d60ba8SDaniel Matyas int ret = 0; 135*16d60ba8SDaniel Matyas 136*16d60ba8SDaniel Matyas switch (type) { 137*16d60ba8SDaniel Matyas case hwmon_temp: 138*16d60ba8SDaniel Matyas switch (attr) { 139*16d60ba8SDaniel Matyas case hwmon_temp_enable: 140*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, 141*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_REG, &uval); 142*16d60ba8SDaniel Matyas if (ret) 143*16d60ba8SDaniel Matyas break; 144*16d60ba8SDaniel Matyas 145*16d60ba8SDaniel Matyas uval = FIELD_GET(MAX31827_CONFIGURATION_1SHOT_MASK | 146*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_CNV_RATE_MASK, 147*16d60ba8SDaniel Matyas uval); 148*16d60ba8SDaniel Matyas *val = !!uval; 149*16d60ba8SDaniel Matyas 150*16d60ba8SDaniel Matyas break; 151*16d60ba8SDaniel Matyas case hwmon_temp_input: 152*16d60ba8SDaniel Matyas mutex_lock(&st->lock); 153*16d60ba8SDaniel Matyas 154*16d60ba8SDaniel Matyas if (!st->enable) { 155*16d60ba8SDaniel Matyas /* 156*16d60ba8SDaniel Matyas * This operation requires mutex protection, 157*16d60ba8SDaniel Matyas * because the chip configuration should not 158*16d60ba8SDaniel Matyas * be changed during the conversion process. 159*16d60ba8SDaniel Matyas */ 160*16d60ba8SDaniel Matyas 161*16d60ba8SDaniel Matyas ret = regmap_update_bits(st->regmap, 162*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_REG, 163*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_1SHOT_MASK, 164*16d60ba8SDaniel Matyas 1); 165*16d60ba8SDaniel Matyas if (ret) { 166*16d60ba8SDaniel Matyas mutex_unlock(&st->lock); 167*16d60ba8SDaniel Matyas return ret; 168*16d60ba8SDaniel Matyas } 169*16d60ba8SDaniel Matyas 170*16d60ba8SDaniel Matyas msleep(MAX31827_12_BIT_CNV_TIME); 171*16d60ba8SDaniel Matyas } 172*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, MAX31827_T_REG, &uval); 173*16d60ba8SDaniel Matyas 174*16d60ba8SDaniel Matyas mutex_unlock(&st->lock); 175*16d60ba8SDaniel Matyas 176*16d60ba8SDaniel Matyas if (ret) 177*16d60ba8SDaniel Matyas break; 178*16d60ba8SDaniel Matyas 179*16d60ba8SDaniel Matyas *val = MAX31827_16_BIT_TO_M_DGR(uval); 180*16d60ba8SDaniel Matyas 181*16d60ba8SDaniel Matyas break; 182*16d60ba8SDaniel Matyas case hwmon_temp_max: 183*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, MAX31827_TH_REG, &uval); 184*16d60ba8SDaniel Matyas if (ret) 185*16d60ba8SDaniel Matyas break; 186*16d60ba8SDaniel Matyas 187*16d60ba8SDaniel Matyas *val = MAX31827_16_BIT_TO_M_DGR(uval); 188*16d60ba8SDaniel Matyas break; 189*16d60ba8SDaniel Matyas case hwmon_temp_max_hyst: 190*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, MAX31827_TH_HYST_REG, 191*16d60ba8SDaniel Matyas &uval); 192*16d60ba8SDaniel Matyas if (ret) 193*16d60ba8SDaniel Matyas break; 194*16d60ba8SDaniel Matyas 195*16d60ba8SDaniel Matyas *val = MAX31827_16_BIT_TO_M_DGR(uval); 196*16d60ba8SDaniel Matyas break; 197*16d60ba8SDaniel Matyas case hwmon_temp_max_alarm: 198*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, 199*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_REG, &uval); 200*16d60ba8SDaniel Matyas if (ret) 201*16d60ba8SDaniel Matyas break; 202*16d60ba8SDaniel Matyas 203*16d60ba8SDaniel Matyas *val = FIELD_GET(MAX31827_CONFIGURATION_O_TEMP_STAT_MASK, 204*16d60ba8SDaniel Matyas uval); 205*16d60ba8SDaniel Matyas break; 206*16d60ba8SDaniel Matyas case hwmon_temp_min: 207*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, MAX31827_TL_REG, &uval); 208*16d60ba8SDaniel Matyas if (ret) 209*16d60ba8SDaniel Matyas break; 210*16d60ba8SDaniel Matyas 211*16d60ba8SDaniel Matyas *val = MAX31827_16_BIT_TO_M_DGR(uval); 212*16d60ba8SDaniel Matyas break; 213*16d60ba8SDaniel Matyas case hwmon_temp_min_hyst: 214*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, MAX31827_TL_HYST_REG, 215*16d60ba8SDaniel Matyas &uval); 216*16d60ba8SDaniel Matyas if (ret) 217*16d60ba8SDaniel Matyas break; 218*16d60ba8SDaniel Matyas 219*16d60ba8SDaniel Matyas *val = MAX31827_16_BIT_TO_M_DGR(uval); 220*16d60ba8SDaniel Matyas break; 221*16d60ba8SDaniel Matyas case hwmon_temp_min_alarm: 222*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, 223*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_REG, &uval); 224*16d60ba8SDaniel Matyas if (ret) 225*16d60ba8SDaniel Matyas break; 226*16d60ba8SDaniel Matyas 227*16d60ba8SDaniel Matyas *val = FIELD_GET(MAX31827_CONFIGURATION_U_TEMP_STAT_MASK, 228*16d60ba8SDaniel Matyas uval); 229*16d60ba8SDaniel Matyas break; 230*16d60ba8SDaniel Matyas default: 231*16d60ba8SDaniel Matyas ret = -EOPNOTSUPP; 232*16d60ba8SDaniel Matyas break; 233*16d60ba8SDaniel Matyas } 234*16d60ba8SDaniel Matyas 235*16d60ba8SDaniel Matyas break; 236*16d60ba8SDaniel Matyas 237*16d60ba8SDaniel Matyas case hwmon_chip: 238*16d60ba8SDaniel Matyas if (attr == hwmon_chip_update_interval) { 239*16d60ba8SDaniel Matyas ret = regmap_read(st->regmap, 240*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_REG, &uval); 241*16d60ba8SDaniel Matyas if (ret) 242*16d60ba8SDaniel Matyas break; 243*16d60ba8SDaniel Matyas 244*16d60ba8SDaniel Matyas uval = FIELD_GET(MAX31827_CONFIGURATION_CNV_RATE_MASK, 245*16d60ba8SDaniel Matyas uval); 246*16d60ba8SDaniel Matyas switch (uval) { 247*16d60ba8SDaniel Matyas case MAX31827_CNV_1_DIV_64_HZ: 248*16d60ba8SDaniel Matyas *val = 64000; 249*16d60ba8SDaniel Matyas break; 250*16d60ba8SDaniel Matyas case MAX31827_CNV_1_DIV_32_HZ: 251*16d60ba8SDaniel Matyas *val = 32000; 252*16d60ba8SDaniel Matyas break; 253*16d60ba8SDaniel Matyas case MAX31827_CNV_1_DIV_16_HZ: 254*16d60ba8SDaniel Matyas *val = 16000; 255*16d60ba8SDaniel Matyas break; 256*16d60ba8SDaniel Matyas case MAX31827_CNV_1_DIV_4_HZ: 257*16d60ba8SDaniel Matyas *val = 4000; 258*16d60ba8SDaniel Matyas break; 259*16d60ba8SDaniel Matyas case MAX31827_CNV_1_HZ: 260*16d60ba8SDaniel Matyas *val = 1000; 261*16d60ba8SDaniel Matyas break; 262*16d60ba8SDaniel Matyas case MAX31827_CNV_4_HZ: 263*16d60ba8SDaniel Matyas *val = 250; 264*16d60ba8SDaniel Matyas break; 265*16d60ba8SDaniel Matyas case MAX31827_CNV_8_HZ: 266*16d60ba8SDaniel Matyas *val = 125; 267*16d60ba8SDaniel Matyas break; 268*16d60ba8SDaniel Matyas default: 269*16d60ba8SDaniel Matyas *val = 0; 270*16d60ba8SDaniel Matyas break; 271*16d60ba8SDaniel Matyas } 272*16d60ba8SDaniel Matyas } 273*16d60ba8SDaniel Matyas break; 274*16d60ba8SDaniel Matyas 275*16d60ba8SDaniel Matyas default: 276*16d60ba8SDaniel Matyas ret = -EOPNOTSUPP; 277*16d60ba8SDaniel Matyas break; 278*16d60ba8SDaniel Matyas } 279*16d60ba8SDaniel Matyas 280*16d60ba8SDaniel Matyas return ret; 281*16d60ba8SDaniel Matyas } 282*16d60ba8SDaniel Matyas 283*16d60ba8SDaniel Matyas static int max31827_write(struct device *dev, enum hwmon_sensor_types type, 284*16d60ba8SDaniel Matyas u32 attr, int channel, long val) 285*16d60ba8SDaniel Matyas { 286*16d60ba8SDaniel Matyas struct max31827_state *st = dev_get_drvdata(dev); 287*16d60ba8SDaniel Matyas int ret; 288*16d60ba8SDaniel Matyas 289*16d60ba8SDaniel Matyas switch (type) { 290*16d60ba8SDaniel Matyas case hwmon_temp: 291*16d60ba8SDaniel Matyas switch (attr) { 292*16d60ba8SDaniel Matyas case hwmon_temp_enable: 293*16d60ba8SDaniel Matyas if (val >> 1) 294*16d60ba8SDaniel Matyas return -EINVAL; 295*16d60ba8SDaniel Matyas 296*16d60ba8SDaniel Matyas mutex_lock(&st->lock); 297*16d60ba8SDaniel Matyas /** 298*16d60ba8SDaniel Matyas * The chip should not be enabled while a conversion is 299*16d60ba8SDaniel Matyas * performed. Neither should the chip be enabled when 300*16d60ba8SDaniel Matyas * the alarm values are changed. 301*16d60ba8SDaniel Matyas */ 302*16d60ba8SDaniel Matyas 303*16d60ba8SDaniel Matyas st->enable = val; 304*16d60ba8SDaniel Matyas 305*16d60ba8SDaniel Matyas ret = regmap_update_bits(st->regmap, 306*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_REG, 307*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_1SHOT_MASK | 308*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_CNV_RATE_MASK, 309*16d60ba8SDaniel Matyas MAX31827_DEVICE_ENABLE(val)); 310*16d60ba8SDaniel Matyas 311*16d60ba8SDaniel Matyas mutex_unlock(&st->lock); 312*16d60ba8SDaniel Matyas 313*16d60ba8SDaniel Matyas return ret; 314*16d60ba8SDaniel Matyas 315*16d60ba8SDaniel Matyas case hwmon_temp_max: 316*16d60ba8SDaniel Matyas return write_alarm_val(st, MAX31827_TH_REG, val); 317*16d60ba8SDaniel Matyas 318*16d60ba8SDaniel Matyas case hwmon_temp_max_hyst: 319*16d60ba8SDaniel Matyas return write_alarm_val(st, MAX31827_TH_HYST_REG, val); 320*16d60ba8SDaniel Matyas 321*16d60ba8SDaniel Matyas case hwmon_temp_min: 322*16d60ba8SDaniel Matyas return write_alarm_val(st, MAX31827_TL_REG, val); 323*16d60ba8SDaniel Matyas 324*16d60ba8SDaniel Matyas case hwmon_temp_min_hyst: 325*16d60ba8SDaniel Matyas return write_alarm_val(st, MAX31827_TL_HYST_REG, val); 326*16d60ba8SDaniel Matyas 327*16d60ba8SDaniel Matyas default: 328*16d60ba8SDaniel Matyas return -EOPNOTSUPP; 329*16d60ba8SDaniel Matyas } 330*16d60ba8SDaniel Matyas 331*16d60ba8SDaniel Matyas case hwmon_chip: 332*16d60ba8SDaniel Matyas if (attr == hwmon_chip_update_interval) { 333*16d60ba8SDaniel Matyas if (!st->enable) 334*16d60ba8SDaniel Matyas return -EINVAL; 335*16d60ba8SDaniel Matyas 336*16d60ba8SDaniel Matyas switch (val) { 337*16d60ba8SDaniel Matyas case 125: 338*16d60ba8SDaniel Matyas val = MAX31827_CNV_8_HZ; 339*16d60ba8SDaniel Matyas break; 340*16d60ba8SDaniel Matyas case 250: 341*16d60ba8SDaniel Matyas val = MAX31827_CNV_4_HZ; 342*16d60ba8SDaniel Matyas break; 343*16d60ba8SDaniel Matyas case 1000: 344*16d60ba8SDaniel Matyas val = MAX31827_CNV_1_HZ; 345*16d60ba8SDaniel Matyas break; 346*16d60ba8SDaniel Matyas case 4000: 347*16d60ba8SDaniel Matyas val = MAX31827_CNV_1_DIV_4_HZ; 348*16d60ba8SDaniel Matyas break; 349*16d60ba8SDaniel Matyas case 16000: 350*16d60ba8SDaniel Matyas val = MAX31827_CNV_1_DIV_16_HZ; 351*16d60ba8SDaniel Matyas break; 352*16d60ba8SDaniel Matyas case 32000: 353*16d60ba8SDaniel Matyas val = MAX31827_CNV_1_DIV_32_HZ; 354*16d60ba8SDaniel Matyas break; 355*16d60ba8SDaniel Matyas case 64000: 356*16d60ba8SDaniel Matyas val = MAX31827_CNV_1_DIV_64_HZ; 357*16d60ba8SDaniel Matyas break; 358*16d60ba8SDaniel Matyas default: 359*16d60ba8SDaniel Matyas return -EINVAL; 360*16d60ba8SDaniel Matyas } 361*16d60ba8SDaniel Matyas 362*16d60ba8SDaniel Matyas val = FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK, 363*16d60ba8SDaniel Matyas val); 364*16d60ba8SDaniel Matyas 365*16d60ba8SDaniel Matyas return regmap_update_bits(st->regmap, 366*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_REG, 367*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_CNV_RATE_MASK, 368*16d60ba8SDaniel Matyas val); 369*16d60ba8SDaniel Matyas } 370*16d60ba8SDaniel Matyas break; 371*16d60ba8SDaniel Matyas 372*16d60ba8SDaniel Matyas default: 373*16d60ba8SDaniel Matyas return -EOPNOTSUPP; 374*16d60ba8SDaniel Matyas } 375*16d60ba8SDaniel Matyas 376*16d60ba8SDaniel Matyas return -EOPNOTSUPP; 377*16d60ba8SDaniel Matyas } 378*16d60ba8SDaniel Matyas 379*16d60ba8SDaniel Matyas static int max31827_init_client(struct max31827_state *st) 380*16d60ba8SDaniel Matyas { 381*16d60ba8SDaniel Matyas st->enable = true; 382*16d60ba8SDaniel Matyas 383*16d60ba8SDaniel Matyas return regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG, 384*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_1SHOT_MASK | 385*16d60ba8SDaniel Matyas MAX31827_CONFIGURATION_CNV_RATE_MASK, 386*16d60ba8SDaniel Matyas MAX31827_DEVICE_ENABLE(1)); 387*16d60ba8SDaniel Matyas } 388*16d60ba8SDaniel Matyas 389*16d60ba8SDaniel Matyas static const struct hwmon_channel_info *max31827_info[] = { 390*16d60ba8SDaniel Matyas HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_MIN | 391*16d60ba8SDaniel Matyas HWMON_T_MIN_HYST | HWMON_T_MIN_ALARM | 392*16d60ba8SDaniel Matyas HWMON_T_MAX | HWMON_T_MAX_HYST | 393*16d60ba8SDaniel Matyas HWMON_T_MAX_ALARM), 394*16d60ba8SDaniel Matyas HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL), 395*16d60ba8SDaniel Matyas NULL, 396*16d60ba8SDaniel Matyas }; 397*16d60ba8SDaniel Matyas 398*16d60ba8SDaniel Matyas static const struct hwmon_ops max31827_hwmon_ops = { 399*16d60ba8SDaniel Matyas .is_visible = max31827_is_visible, 400*16d60ba8SDaniel Matyas .read = max31827_read, 401*16d60ba8SDaniel Matyas .write = max31827_write, 402*16d60ba8SDaniel Matyas }; 403*16d60ba8SDaniel Matyas 404*16d60ba8SDaniel Matyas static const struct hwmon_chip_info max31827_chip_info = { 405*16d60ba8SDaniel Matyas .ops = &max31827_hwmon_ops, 406*16d60ba8SDaniel Matyas .info = max31827_info, 407*16d60ba8SDaniel Matyas }; 408*16d60ba8SDaniel Matyas 409*16d60ba8SDaniel Matyas static int max31827_probe(struct i2c_client *client) 410*16d60ba8SDaniel Matyas { 411*16d60ba8SDaniel Matyas struct device *dev = &client->dev; 412*16d60ba8SDaniel Matyas struct device *hwmon_dev; 413*16d60ba8SDaniel Matyas struct max31827_state *st; 414*16d60ba8SDaniel Matyas int err; 415*16d60ba8SDaniel Matyas 416*16d60ba8SDaniel Matyas if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) 417*16d60ba8SDaniel Matyas return -EOPNOTSUPP; 418*16d60ba8SDaniel Matyas 419*16d60ba8SDaniel Matyas st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); 420*16d60ba8SDaniel Matyas if (!st) 421*16d60ba8SDaniel Matyas return -ENOMEM; 422*16d60ba8SDaniel Matyas 423*16d60ba8SDaniel Matyas mutex_init(&st->lock); 424*16d60ba8SDaniel Matyas 425*16d60ba8SDaniel Matyas st->regmap = devm_regmap_init_i2c(client, &max31827_regmap); 426*16d60ba8SDaniel Matyas if (IS_ERR(st->regmap)) 427*16d60ba8SDaniel Matyas return dev_err_probe(dev, PTR_ERR(st->regmap), 428*16d60ba8SDaniel Matyas "Failed to allocate regmap.\n"); 429*16d60ba8SDaniel Matyas 430*16d60ba8SDaniel Matyas err = max31827_init_client(st); 431*16d60ba8SDaniel Matyas if (err) 432*16d60ba8SDaniel Matyas return err; 433*16d60ba8SDaniel Matyas 434*16d60ba8SDaniel Matyas hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, st, 435*16d60ba8SDaniel Matyas &max31827_chip_info, 436*16d60ba8SDaniel Matyas NULL); 437*16d60ba8SDaniel Matyas 438*16d60ba8SDaniel Matyas return PTR_ERR_OR_ZERO(hwmon_dev); 439*16d60ba8SDaniel Matyas } 440*16d60ba8SDaniel Matyas 441*16d60ba8SDaniel Matyas static const struct i2c_device_id max31827_i2c_ids[] = { 442*16d60ba8SDaniel Matyas { "max31827", 0 }, 443*16d60ba8SDaniel Matyas { } 444*16d60ba8SDaniel Matyas }; 445*16d60ba8SDaniel Matyas MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids); 446*16d60ba8SDaniel Matyas 447*16d60ba8SDaniel Matyas static const struct of_device_id max31827_of_match[] = { 448*16d60ba8SDaniel Matyas { .compatible = "adi,max31827" }, 449*16d60ba8SDaniel Matyas { } 450*16d60ba8SDaniel Matyas }; 451*16d60ba8SDaniel Matyas MODULE_DEVICE_TABLE(of, max31827_of_match); 452*16d60ba8SDaniel Matyas 453*16d60ba8SDaniel Matyas static struct i2c_driver max31827_driver = { 454*16d60ba8SDaniel Matyas .class = I2C_CLASS_HWMON, 455*16d60ba8SDaniel Matyas .driver = { 456*16d60ba8SDaniel Matyas .name = "max31827", 457*16d60ba8SDaniel Matyas .of_match_table = max31827_of_match, 458*16d60ba8SDaniel Matyas }, 459*16d60ba8SDaniel Matyas .probe_new = max31827_probe, 460*16d60ba8SDaniel Matyas .id_table = max31827_i2c_ids, 461*16d60ba8SDaniel Matyas }; 462*16d60ba8SDaniel Matyas module_i2c_driver(max31827_driver); 463*16d60ba8SDaniel Matyas 464*16d60ba8SDaniel Matyas MODULE_AUTHOR("Daniel Matyas <daniel.matyas@analog.com>"); 465*16d60ba8SDaniel Matyas MODULE_DESCRIPTION("Maxim MAX31827 low-power temperature switch driver"); 466*16d60ba8SDaniel Matyas MODULE_LICENSE("GPL"); 467