1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * sbtsi_temp.c - hwmon driver for a SBI Temperature Sensor Interface (SB-TSI) 4 * compliant AMD SoC temperature device. 5 * 6 * Copyright (c) 2020, Google Inc. 7 * Copyright (c) 2020, Kun Yi <kunyi@google.com> 8 */ 9 10 #include <linux/err.h> 11 #include <linux/i2c.h> 12 #include <linux/init.h> 13 #include <linux/hwmon.h> 14 #include <linux/module.h> 15 #include <linux/mutex.h> 16 #include <linux/of.h> 17 #include <linux/bitfield.h> 18 19 /* 20 * SB-TSI registers only support SMBus byte data access. "_INT" registers are 21 * the integer part of a temperature value or limit, and "_DEC" registers are 22 * corresponding decimal parts. 23 */ 24 #define SBTSI_REG_TEMP_INT 0x01 /* RO */ 25 #define SBTSI_REG_STATUS 0x02 /* RO */ 26 #define SBTSI_REG_CONFIG 0x03 /* RO */ 27 #define SBTSI_REG_TEMP_HIGH_INT 0x07 /* RW */ 28 #define SBTSI_REG_TEMP_LOW_INT 0x08 /* RW */ 29 #define SBTSI_REG_TEMP_DEC 0x10 /* RW */ 30 #define SBTSI_REG_TEMP_HIGH_DEC 0x13 /* RW */ 31 #define SBTSI_REG_TEMP_LOW_DEC 0x14 /* RW */ 32 33 /* 34 * Bit for reporting value with temperature measurement range. 35 * bit == 0: Use default temperature range (0C to 255.875C). 36 * bit == 1: Use extended temperature range (-49C to +206.875C). 37 */ 38 #define SBTSI_CONFIG_EXT_RANGE_SHIFT 2 39 /* 40 * ReadOrder bit specifies the reading order of integer and decimal part of 41 * CPU temperature for atomic reads. If bit == 0, reading integer part triggers 42 * latching of the decimal part, so integer part should be read first. 43 * If bit == 1, read order should be reversed. 44 */ 45 #define SBTSI_CONFIG_READ_ORDER_SHIFT 5 46 47 #define SBTSI_TEMP_EXT_RANGE_ADJ 49000 48 49 #define SBTSI_TEMP_MIN 0 50 #define SBTSI_TEMP_MAX 255875 51 52 /* Each client has this additional data */ 53 struct sbtsi_data { 54 struct i2c_client *client; 55 struct mutex lock; 56 bool ext_range_mode; 57 bool read_order; 58 }; 59 60 /* 61 * From SB-TSI spec: CPU temperature readings and limit registers encode the 62 * temperature in increments of 0.125 from 0 to 255.875. The "high byte" 63 * register encodes the base-2 of the integer portion, and the upper 3 bits of 64 * the "low byte" encode in base-2 the decimal portion. 65 * 66 * e.g. INT=0x19, DEC=0x20 represents 25.125 degrees Celsius 67 * 68 * Therefore temperature in millidegree Celsius = 69 * (INT + DEC / 256) * 1000 = (INT * 8 + DEC / 32) * 125 70 */ 71 static inline int sbtsi_reg_to_mc(s32 integer, s32 decimal) 72 { 73 return ((integer << 3) + (decimal >> 5)) * 125; 74 } 75 76 /* 77 * Inversely, given temperature in millidegree Celsius 78 * INT = (TEMP / 125) / 8 79 * DEC = ((TEMP / 125) % 8) * 32 80 * Caller have to make sure temp doesn't exceed 255875, the max valid value. 81 */ 82 static inline void sbtsi_mc_to_reg(s32 temp, u8 *integer, u8 *decimal) 83 { 84 temp /= 125; 85 *integer = temp >> 3; 86 *decimal = (temp & 0x7) << 5; 87 } 88 89 static int sbtsi_read(struct device *dev, enum hwmon_sensor_types type, 90 u32 attr, int channel, long *val) 91 { 92 struct sbtsi_data *data = dev_get_drvdata(dev); 93 s32 temp_int, temp_dec; 94 95 switch (attr) { 96 case hwmon_temp_input: 97 mutex_lock(&data->lock); 98 if (data->read_order) { 99 temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_DEC); 100 temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_INT); 101 } else { 102 temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_INT); 103 temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_DEC); 104 } 105 mutex_unlock(&data->lock); 106 break; 107 case hwmon_temp_max: 108 mutex_lock(&data->lock); 109 temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_HIGH_INT); 110 temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_HIGH_DEC); 111 mutex_unlock(&data->lock); 112 break; 113 case hwmon_temp_min: 114 mutex_lock(&data->lock); 115 temp_int = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_LOW_INT); 116 temp_dec = i2c_smbus_read_byte_data(data->client, SBTSI_REG_TEMP_LOW_DEC); 117 mutex_unlock(&data->lock); 118 break; 119 default: 120 return -EINVAL; 121 } 122 123 124 if (temp_int < 0) 125 return temp_int; 126 if (temp_dec < 0) 127 return temp_dec; 128 129 *val = sbtsi_reg_to_mc(temp_int, temp_dec); 130 if (data->ext_range_mode) 131 *val -= SBTSI_TEMP_EXT_RANGE_ADJ; 132 133 return 0; 134 } 135 136 static int sbtsi_write(struct device *dev, enum hwmon_sensor_types type, 137 u32 attr, int channel, long val) 138 { 139 struct sbtsi_data *data = dev_get_drvdata(dev); 140 int reg_int, reg_dec, err; 141 u8 temp_int, temp_dec; 142 143 switch (attr) { 144 case hwmon_temp_max: 145 reg_int = SBTSI_REG_TEMP_HIGH_INT; 146 reg_dec = SBTSI_REG_TEMP_HIGH_DEC; 147 break; 148 case hwmon_temp_min: 149 reg_int = SBTSI_REG_TEMP_LOW_INT; 150 reg_dec = SBTSI_REG_TEMP_LOW_DEC; 151 break; 152 default: 153 return -EINVAL; 154 } 155 156 if (data->ext_range_mode) 157 val += SBTSI_TEMP_EXT_RANGE_ADJ; 158 val = clamp_val(val, SBTSI_TEMP_MIN, SBTSI_TEMP_MAX); 159 sbtsi_mc_to_reg(val, &temp_int, &temp_dec); 160 161 mutex_lock(&data->lock); 162 err = i2c_smbus_write_byte_data(data->client, reg_int, temp_int); 163 if (err) 164 goto exit; 165 166 err = i2c_smbus_write_byte_data(data->client, reg_dec, temp_dec); 167 exit: 168 mutex_unlock(&data->lock); 169 return err; 170 } 171 172 static umode_t sbtsi_is_visible(const void *data, 173 enum hwmon_sensor_types type, 174 u32 attr, int channel) 175 { 176 switch (type) { 177 case hwmon_temp: 178 switch (attr) { 179 case hwmon_temp_input: 180 return 0444; 181 case hwmon_temp_min: 182 return 0644; 183 case hwmon_temp_max: 184 return 0644; 185 } 186 break; 187 default: 188 break; 189 } 190 return 0; 191 } 192 193 static const struct hwmon_channel_info * const sbtsi_info[] = { 194 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), 195 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX), 196 NULL 197 }; 198 199 static const struct hwmon_ops sbtsi_hwmon_ops = { 200 .is_visible = sbtsi_is_visible, 201 .read = sbtsi_read, 202 .write = sbtsi_write, 203 }; 204 205 static const struct hwmon_chip_info sbtsi_chip_info = { 206 .ops = &sbtsi_hwmon_ops, 207 .info = sbtsi_info, 208 }; 209 210 static int sbtsi_probe(struct i2c_client *client) 211 { 212 struct device *dev = &client->dev; 213 struct device *hwmon_dev; 214 struct sbtsi_data *data; 215 int err; 216 217 data = devm_kzalloc(dev, sizeof(struct sbtsi_data), GFP_KERNEL); 218 if (!data) 219 return -ENOMEM; 220 221 data->client = client; 222 mutex_init(&data->lock); 223 224 err = i2c_smbus_read_byte_data(data->client, SBTSI_REG_CONFIG); 225 if (err < 0) 226 return err; 227 data->ext_range_mode = FIELD_GET(BIT(SBTSI_CONFIG_EXT_RANGE_SHIFT), err); 228 data->read_order = FIELD_GET(BIT(SBTSI_CONFIG_READ_ORDER_SHIFT), err); 229 230 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data, 231 &sbtsi_chip_info, NULL); 232 233 return PTR_ERR_OR_ZERO(hwmon_dev); 234 } 235 236 static const struct i2c_device_id sbtsi_id[] = { 237 {"sbtsi"}, 238 {} 239 }; 240 MODULE_DEVICE_TABLE(i2c, sbtsi_id); 241 242 static const struct of_device_id __maybe_unused sbtsi_of_match[] = { 243 { 244 .compatible = "amd,sbtsi", 245 }, 246 { }, 247 }; 248 MODULE_DEVICE_TABLE(of, sbtsi_of_match); 249 250 static struct i2c_driver sbtsi_driver = { 251 .driver = { 252 .name = "sbtsi", 253 .of_match_table = of_match_ptr(sbtsi_of_match), 254 }, 255 .probe = sbtsi_probe, 256 .id_table = sbtsi_id, 257 }; 258 259 module_i2c_driver(sbtsi_driver); 260 261 MODULE_AUTHOR("Kun Yi <kunyi@google.com>"); 262 MODULE_DESCRIPTION("Hwmon driver for AMD SB-TSI emulated sensor"); 263 MODULE_LICENSE("GPL"); 264