w83773g.c (7007B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2017 IBM Corp. 4 * 5 * Driver for the Nuvoton W83773G SMBus temperature sensor IC. 6 * Supported models: W83773G 7 */ 8 9#include <linux/module.h> 10#include <linux/init.h> 11#include <linux/i2c.h> 12#include <linux/hwmon.h> 13#include <linux/hwmon-sysfs.h> 14#include <linux/err.h> 15#include <linux/of_device.h> 16#include <linux/regmap.h> 17 18/* W83773 has 3 channels */ 19#define W83773_CHANNELS 3 20 21/* The W83773 registers */ 22#define W83773_CONVERSION_RATE_REG_READ 0x04 23#define W83773_CONVERSION_RATE_REG_WRITE 0x0A 24#define W83773_MANUFACTURER_ID_REG 0xFE 25#define W83773_LOCAL_TEMP 0x00 26 27static const u8 W83773_STATUS[2] = { 0x02, 0x17 }; 28 29static const u8 W83773_TEMP_LSB[2] = { 0x10, 0x25 }; 30static const u8 W83773_TEMP_MSB[2] = { 0x01, 0x24 }; 31 32static const u8 W83773_OFFSET_LSB[2] = { 0x12, 0x16 }; 33static const u8 W83773_OFFSET_MSB[2] = { 0x11, 0x15 }; 34 35/* this is the number of sensors in the device */ 36static const struct i2c_device_id w83773_id[] = { 37 { "w83773g" }, 38 { } 39}; 40 41MODULE_DEVICE_TABLE(i2c, w83773_id); 42 43static const struct of_device_id __maybe_unused w83773_of_match[] = { 44 { 45 .compatible = "nuvoton,w83773g" 46 }, 47 { }, 48}; 49MODULE_DEVICE_TABLE(of, w83773_of_match); 50 51static inline long temp_of_local(s8 reg) 52{ 53 return reg * 1000; 54} 55 56static inline long temp_of_remote(s8 hb, u8 lb) 57{ 58 return (hb << 3 | lb >> 5) * 125; 59} 60 61static int get_local_temp(struct regmap *regmap, long *val) 62{ 63 unsigned int regval; 64 int ret; 65 66 ret = regmap_read(regmap, W83773_LOCAL_TEMP, ®val); 67 if (ret < 0) 68 return ret; 69 70 *val = temp_of_local(regval); 71 return 0; 72} 73 74static int get_remote_temp(struct regmap *regmap, int index, long *val) 75{ 76 unsigned int regval_high; 77 unsigned int regval_low; 78 int ret; 79 80 ret = regmap_read(regmap, W83773_TEMP_MSB[index], ®val_high); 81 if (ret < 0) 82 return ret; 83 84 ret = regmap_read(regmap, W83773_TEMP_LSB[index], ®val_low); 85 if (ret < 0) 86 return ret; 87 88 *val = temp_of_remote(regval_high, regval_low); 89 return 0; 90} 91 92static int get_fault(struct regmap *regmap, int index, long *val) 93{ 94 unsigned int regval; 95 int ret; 96 97 ret = regmap_read(regmap, W83773_STATUS[index], ®val); 98 if (ret < 0) 99 return ret; 100 101 *val = (regval & 0x04) >> 2; 102 return 0; 103} 104 105static int get_offset(struct regmap *regmap, int index, long *val) 106{ 107 unsigned int regval_high; 108 unsigned int regval_low; 109 int ret; 110 111 ret = regmap_read(regmap, W83773_OFFSET_MSB[index], ®val_high); 112 if (ret < 0) 113 return ret; 114 115 ret = regmap_read(regmap, W83773_OFFSET_LSB[index], ®val_low); 116 if (ret < 0) 117 return ret; 118 119 *val = temp_of_remote(regval_high, regval_low); 120 return 0; 121} 122 123static int set_offset(struct regmap *regmap, int index, long val) 124{ 125 int ret; 126 u8 high_byte; 127 u8 low_byte; 128 129 val = clamp_val(val, -127825, 127825); 130 /* offset value equals to (high_byte << 3 | low_byte >> 5) * 125 */ 131 val /= 125; 132 high_byte = val >> 3; 133 low_byte = (val & 0x07) << 5; 134 135 ret = regmap_write(regmap, W83773_OFFSET_MSB[index], high_byte); 136 if (ret < 0) 137 return ret; 138 139 return regmap_write(regmap, W83773_OFFSET_LSB[index], low_byte); 140} 141 142static int get_update_interval(struct regmap *regmap, long *val) 143{ 144 unsigned int regval; 145 int ret; 146 147 ret = regmap_read(regmap, W83773_CONVERSION_RATE_REG_READ, ®val); 148 if (ret < 0) 149 return ret; 150 151 *val = 16000 >> regval; 152 return 0; 153} 154 155static int set_update_interval(struct regmap *regmap, long val) 156{ 157 int rate; 158 159 /* 160 * For valid rates, interval can be calculated as 161 * interval = (1 << (8 - rate)) * 62.5; 162 * Rounded rate is therefore 163 * rate = 8 - __fls(interval * 8 / (62.5 * 7)); 164 * Use clamp_val() to avoid overflows, and to ensure valid input 165 * for __fls. 166 */ 167 val = clamp_val(val, 62, 16000) * 10; 168 rate = 8 - __fls((val * 8 / (625 * 7))); 169 return regmap_write(regmap, W83773_CONVERSION_RATE_REG_WRITE, rate); 170} 171 172static int w83773_read(struct device *dev, enum hwmon_sensor_types type, 173 u32 attr, int channel, long *val) 174{ 175 struct regmap *regmap = dev_get_drvdata(dev); 176 177 if (type == hwmon_chip) { 178 if (attr == hwmon_chip_update_interval) 179 return get_update_interval(regmap, val); 180 return -EOPNOTSUPP; 181 } 182 183 switch (attr) { 184 case hwmon_temp_input: 185 if (channel == 0) 186 return get_local_temp(regmap, val); 187 return get_remote_temp(regmap, channel - 1, val); 188 case hwmon_temp_fault: 189 return get_fault(regmap, channel - 1, val); 190 case hwmon_temp_offset: 191 return get_offset(regmap, channel - 1, val); 192 default: 193 return -EOPNOTSUPP; 194 } 195} 196 197static int w83773_write(struct device *dev, enum hwmon_sensor_types type, 198 u32 attr, int channel, long val) 199{ 200 struct regmap *regmap = dev_get_drvdata(dev); 201 202 if (type == hwmon_chip && attr == hwmon_chip_update_interval) 203 return set_update_interval(regmap, val); 204 205 if (type == hwmon_temp && attr == hwmon_temp_offset) 206 return set_offset(regmap, channel - 1, val); 207 208 return -EOPNOTSUPP; 209} 210 211static umode_t w83773_is_visible(const void *data, enum hwmon_sensor_types type, 212 u32 attr, int channel) 213{ 214 switch (type) { 215 case hwmon_chip: 216 switch (attr) { 217 case hwmon_chip_update_interval: 218 return 0644; 219 } 220 break; 221 case hwmon_temp: 222 switch (attr) { 223 case hwmon_temp_input: 224 case hwmon_temp_fault: 225 return 0444; 226 case hwmon_temp_offset: 227 return 0644; 228 } 229 break; 230 default: 231 break; 232 } 233 return 0; 234} 235 236static const struct hwmon_channel_info *w83773_info[] = { 237 HWMON_CHANNEL_INFO(chip, 238 HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL), 239 HWMON_CHANNEL_INFO(temp, 240 HWMON_T_INPUT, 241 HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_OFFSET, 242 HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_OFFSET), 243 NULL 244}; 245 246static const struct hwmon_ops w83773_ops = { 247 .is_visible = w83773_is_visible, 248 .read = w83773_read, 249 .write = w83773_write, 250}; 251 252static const struct hwmon_chip_info w83773_chip_info = { 253 .ops = &w83773_ops, 254 .info = w83773_info, 255}; 256 257static const struct regmap_config w83773_regmap_config = { 258 .reg_bits = 8, 259 .val_bits = 8, 260}; 261 262static int w83773_probe(struct i2c_client *client) 263{ 264 struct device *dev = &client->dev; 265 struct device *hwmon_dev; 266 struct regmap *regmap; 267 int ret; 268 269 regmap = devm_regmap_init_i2c(client, &w83773_regmap_config); 270 if (IS_ERR(regmap)) { 271 dev_err(dev, "failed to allocate register map\n"); 272 return PTR_ERR(regmap); 273 } 274 275 /* Set the conversion rate to 2 Hz */ 276 ret = regmap_write(regmap, W83773_CONVERSION_RATE_REG_WRITE, 0x05); 277 if (ret < 0) { 278 dev_err(&client->dev, "error writing config rate register\n"); 279 return ret; 280 } 281 282 i2c_set_clientdata(client, regmap); 283 284 hwmon_dev = devm_hwmon_device_register_with_info(dev, 285 client->name, 286 regmap, 287 &w83773_chip_info, 288 NULL); 289 return PTR_ERR_OR_ZERO(hwmon_dev); 290} 291 292static struct i2c_driver w83773_driver = { 293 .class = I2C_CLASS_HWMON, 294 .driver = { 295 .name = "w83773g", 296 .of_match_table = of_match_ptr(w83773_of_match), 297 }, 298 .probe_new = w83773_probe, 299 .id_table = w83773_id, 300}; 301 302module_i2c_driver(w83773_driver); 303 304MODULE_AUTHOR("Lei YU <mine260309@gmail.com>"); 305MODULE_DESCRIPTION("W83773G temperature sensor driver"); 306MODULE_LICENSE("GPL");