440 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for MAX31730 3-Channel Remote Temperature Sensor4 *5 * Copyright (c) 2019 Guenter Roeck <linux@roeck-us.net>6 */7 8#include <linux/bits.h>9#include <linux/err.h>10#include <linux/i2c.h>11#include <linux/init.h>12#include <linux/hwmon.h>13#include <linux/module.h>14#include <linux/of.h>15#include <linux/slab.h>16 17/* Addresses scanned */18static const unsigned short normal_i2c[] = { 0x1c, 0x1d, 0x1e, 0x1f, 0x4c,19 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };20 21/* The MAX31730 registers */22#define MAX31730_REG_TEMP 0x0023#define MAX31730_REG_CONF 0x1324#define MAX31730_STOP BIT(7)25#define MAX31730_EXTRANGE BIT(1)26#define MAX31730_REG_TEMP_OFFSET 0x1627#define MAX31730_TEMP_OFFSET_BASELINE 0x7728#define MAX31730_REG_OFFSET_ENABLE 0x1729#define MAX31730_REG_TEMP_MAX 0x2030#define MAX31730_REG_TEMP_MIN 0x3031#define MAX31730_REG_STATUS_HIGH 0x3232#define MAX31730_REG_STATUS_LOW 0x3333#define MAX31730_REG_CHANNEL_ENABLE 0x3534#define MAX31730_REG_TEMP_FAULT 0x3635 36#define MAX31730_REG_MFG_ID 0x5037#define MAX31730_MFG_ID 0x4d38#define MAX31730_REG_MFG_REV 0x5139#define MAX31730_MFG_REV 0x0140 41#define MAX31730_TEMP_MIN (-128000)42#define MAX31730_TEMP_MAX 12793743 44/* Each client has this additional data */45struct max31730_data {46 struct i2c_client *client;47 u8 orig_conf;48 u8 current_conf;49 u8 offset_enable;50 u8 channel_enable;51};52 53/*-----------------------------------------------------------------------*/54 55static inline long max31730_reg_to_mc(s16 temp)56{57 return DIV_ROUND_CLOSEST((temp >> 4) * 1000, 16);58}59 60static int max31730_write_config(struct max31730_data *data, u8 set_mask,61 u8 clr_mask)62{63 u8 value;64 65 clr_mask |= MAX31730_EXTRANGE;66 value = data->current_conf & ~clr_mask;67 value |= set_mask;68 69 if (data->current_conf != value) {70 s32 err;71 72 err = i2c_smbus_write_byte_data(data->client, MAX31730_REG_CONF,73 value);74 if (err)75 return err;76 data->current_conf = value;77 }78 return 0;79}80 81static int max31730_set_enable(struct i2c_client *client, int reg,82 u8 *confdata, int channel, bool enable)83{84 u8 regval = *confdata;85 int err;86 87 if (enable)88 regval |= BIT(channel);89 else90 regval &= ~BIT(channel);91 92 if (regval != *confdata) {93 err = i2c_smbus_write_byte_data(client, reg, regval);94 if (err)95 return err;96 *confdata = regval;97 }98 return 0;99}100 101static int max31730_set_offset_enable(struct max31730_data *data, int channel,102 bool enable)103{104 return max31730_set_enable(data->client, MAX31730_REG_OFFSET_ENABLE,105 &data->offset_enable, channel, enable);106}107 108static int max31730_set_channel_enable(struct max31730_data *data, int channel,109 bool enable)110{111 return max31730_set_enable(data->client, MAX31730_REG_CHANNEL_ENABLE,112 &data->channel_enable, channel, enable);113}114 115static int max31730_read(struct device *dev, enum hwmon_sensor_types type,116 u32 attr, int channel, long *val)117{118 struct max31730_data *data = dev_get_drvdata(dev);119 int regval, reg, offset;120 121 if (type != hwmon_temp)122 return -EINVAL;123 124 switch (attr) {125 case hwmon_temp_input:126 if (!(data->channel_enable & BIT(channel)))127 return -ENODATA;128 reg = MAX31730_REG_TEMP + (channel * 2);129 break;130 case hwmon_temp_max:131 reg = MAX31730_REG_TEMP_MAX + (channel * 2);132 break;133 case hwmon_temp_min:134 reg = MAX31730_REG_TEMP_MIN;135 break;136 case hwmon_temp_enable:137 *val = !!(data->channel_enable & BIT(channel));138 return 0;139 case hwmon_temp_offset:140 if (!channel)141 return -EINVAL;142 if (!(data->offset_enable & BIT(channel))) {143 *val = 0;144 return 0;145 }146 offset = i2c_smbus_read_byte_data(data->client,147 MAX31730_REG_TEMP_OFFSET);148 if (offset < 0)149 return offset;150 *val = (offset - MAX31730_TEMP_OFFSET_BASELINE) * 125;151 return 0;152 case hwmon_temp_fault:153 regval = i2c_smbus_read_byte_data(data->client,154 MAX31730_REG_TEMP_FAULT);155 if (regval < 0)156 return regval;157 *val = !!(regval & BIT(channel));158 return 0;159 case hwmon_temp_min_alarm:160 regval = i2c_smbus_read_byte_data(data->client,161 MAX31730_REG_STATUS_LOW);162 if (regval < 0)163 return regval;164 *val = !!(regval & BIT(channel));165 return 0;166 case hwmon_temp_max_alarm:167 regval = i2c_smbus_read_byte_data(data->client,168 MAX31730_REG_STATUS_HIGH);169 if (regval < 0)170 return regval;171 *val = !!(regval & BIT(channel));172 return 0;173 default:174 return -EINVAL;175 }176 regval = i2c_smbus_read_word_swapped(data->client, reg);177 if (regval < 0)178 return regval;179 180 *val = max31730_reg_to_mc(regval);181 182 return 0;183}184 185static int max31730_write(struct device *dev, enum hwmon_sensor_types type,186 u32 attr, int channel, long val)187{188 struct max31730_data *data = dev_get_drvdata(dev);189 int reg, err;190 191 if (type != hwmon_temp)192 return -EINVAL;193 194 switch (attr) {195 case hwmon_temp_max:196 reg = MAX31730_REG_TEMP_MAX + channel * 2;197 break;198 case hwmon_temp_min:199 reg = MAX31730_REG_TEMP_MIN;200 break;201 case hwmon_temp_enable:202 if (val != 0 && val != 1)203 return -EINVAL;204 return max31730_set_channel_enable(data, channel, val);205 case hwmon_temp_offset:206 val = clamp_val(val, -14875, 17000) + 14875;207 val = DIV_ROUND_CLOSEST(val, 125);208 err = max31730_set_offset_enable(data, channel,209 val != MAX31730_TEMP_OFFSET_BASELINE);210 if (err)211 return err;212 return i2c_smbus_write_byte_data(data->client,213 MAX31730_REG_TEMP_OFFSET, val);214 default:215 return -EINVAL;216 }217 218 val = clamp_val(val, MAX31730_TEMP_MIN, MAX31730_TEMP_MAX);219 val = DIV_ROUND_CLOSEST(val << 4, 1000) << 4;220 221 return i2c_smbus_write_word_swapped(data->client, reg, (u16)val);222}223 224static umode_t max31730_is_visible(const void *data,225 enum hwmon_sensor_types type,226 u32 attr, int channel)227{228 switch (type) {229 case hwmon_temp:230 switch (attr) {231 case hwmon_temp_input:232 case hwmon_temp_min_alarm:233 case hwmon_temp_max_alarm:234 case hwmon_temp_fault:235 return 0444;236 case hwmon_temp_min:237 return channel ? 0444 : 0644;238 case hwmon_temp_offset:239 case hwmon_temp_enable:240 case hwmon_temp_max:241 return 0644;242 }243 break;244 default:245 break;246 }247 return 0;248}249 250static const struct hwmon_channel_info * const max31730_info[] = {251 HWMON_CHANNEL_INFO(chip,252 HWMON_C_REGISTER_TZ),253 HWMON_CHANNEL_INFO(temp,254 HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |255 HWMON_T_ENABLE |256 HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM,257 HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |258 HWMON_T_OFFSET | HWMON_T_ENABLE |259 HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM |260 HWMON_T_FAULT,261 HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |262 HWMON_T_OFFSET | HWMON_T_ENABLE |263 HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM |264 HWMON_T_FAULT,265 HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |266 HWMON_T_OFFSET | HWMON_T_ENABLE |267 HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM |268 HWMON_T_FAULT269 ),270 NULL271};272 273static const struct hwmon_ops max31730_hwmon_ops = {274 .is_visible = max31730_is_visible,275 .read = max31730_read,276 .write = max31730_write,277};278 279static const struct hwmon_chip_info max31730_chip_info = {280 .ops = &max31730_hwmon_ops,281 .info = max31730_info,282};283 284static void max31730_remove(void *data)285{286 struct max31730_data *max31730 = data;287 struct i2c_client *client = max31730->client;288 289 i2c_smbus_write_byte_data(client, MAX31730_REG_CONF,290 max31730->orig_conf);291}292 293static int294max31730_probe(struct i2c_client *client)295{296 struct device *dev = &client->dev;297 struct device *hwmon_dev;298 struct max31730_data *data;299 int status, err;300 301 if (!i2c_check_functionality(client->adapter,302 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))303 return -EIO;304 305 data = devm_kzalloc(dev, sizeof(struct max31730_data), GFP_KERNEL);306 if (!data)307 return -ENOMEM;308 309 data->client = client;310 311 /* Cache original configuration and enable status */312 status = i2c_smbus_read_byte_data(client, MAX31730_REG_CHANNEL_ENABLE);313 if (status < 0)314 return status;315 data->channel_enable = status;316 317 status = i2c_smbus_read_byte_data(client, MAX31730_REG_OFFSET_ENABLE);318 if (status < 0)319 return status;320 data->offset_enable = status;321 322 status = i2c_smbus_read_byte_data(client, MAX31730_REG_CONF);323 if (status < 0)324 return status;325 data->orig_conf = status;326 data->current_conf = status;327 328 err = max31730_write_config(data,329 data->channel_enable ? 0 : MAX31730_STOP,330 data->channel_enable ? MAX31730_STOP : 0);331 if (err)332 return err;333 334 dev_set_drvdata(dev, data);335 336 err = devm_add_action_or_reset(dev, max31730_remove, data);337 if (err)338 return err;339 340 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,341 data,342 &max31730_chip_info,343 NULL);344 return PTR_ERR_OR_ZERO(hwmon_dev);345}346 347static const struct i2c_device_id max31730_ids[] = {348 { "max31730" },349 { }350};351MODULE_DEVICE_TABLE(i2c, max31730_ids);352 353static const struct of_device_id __maybe_unused max31730_of_match[] = {354 {355 .compatible = "maxim,max31730",356 },357 { },358};359MODULE_DEVICE_TABLE(of, max31730_of_match);360 361static bool max31730_check_reg_temp(struct i2c_client *client,362 int reg)363{364 int regval;365 366 regval = i2c_smbus_read_byte_data(client, reg + 1);367 return regval < 0 || (regval & 0x0f);368}369 370/* Return 0 if detection is successful, -ENODEV otherwise */371static int max31730_detect(struct i2c_client *client,372 struct i2c_board_info *info)373{374 struct i2c_adapter *adapter = client->adapter;375 int regval;376 int i;377 378 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |379 I2C_FUNC_SMBUS_WORD_DATA))380 return -ENODEV;381 382 regval = i2c_smbus_read_byte_data(client, MAX31730_REG_MFG_ID);383 if (regval != MAX31730_MFG_ID)384 return -ENODEV;385 regval = i2c_smbus_read_byte_data(client, MAX31730_REG_MFG_REV);386 if (regval != MAX31730_MFG_REV)387 return -ENODEV;388 389 /* lower 4 bit of temperature and limit registers must be 0 */390 if (max31730_check_reg_temp(client, MAX31730_REG_TEMP_MIN))391 return -ENODEV;392 393 for (i = 0; i < 4; i++) {394 if (max31730_check_reg_temp(client, MAX31730_REG_TEMP + i * 2))395 return -ENODEV;396 if (max31730_check_reg_temp(client,397 MAX31730_REG_TEMP_MAX + i * 2))398 return -ENODEV;399 }400 401 strscpy(info->type, "max31730", I2C_NAME_SIZE);402 403 return 0;404}405 406static int max31730_suspend(struct device *dev)407{408 struct max31730_data *data = dev_get_drvdata(dev);409 410 return max31730_write_config(data, MAX31730_STOP, 0);411}412 413static int max31730_resume(struct device *dev)414{415 struct max31730_data *data = dev_get_drvdata(dev);416 417 return max31730_write_config(data, 0, MAX31730_STOP);418}419 420static DEFINE_SIMPLE_DEV_PM_OPS(max31730_pm_ops, max31730_suspend, max31730_resume);421 422static struct i2c_driver max31730_driver = {423 .class = I2C_CLASS_HWMON,424 .driver = {425 .name = "max31730",426 .of_match_table = of_match_ptr(max31730_of_match),427 .pm = pm_sleep_ptr(&max31730_pm_ops),428 },429 .probe = max31730_probe,430 .id_table = max31730_ids,431 .detect = max31730_detect,432 .address_list = normal_i2c,433};434 435module_i2c_driver(max31730_driver);436 437MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");438MODULE_DESCRIPTION("MAX31730 driver");439MODULE_LICENSE("GPL");440