jc42.c (41be702a542a0d14bb0b1c16e824fa9ed27616ec) | jc42.c (d397276b0c833b0089cb19d94fbc35a43ada58a7) |
---|---|
1/* 2 * jc42.c - driver for Jedec JC42.4 compliant temperature sensors 3 * 4 * Copyright (c) 2010 Ericsson AB. 5 * 6 * Derived from lm77.c by Andras BALI <drewie@freemail.hu>. 7 * 8 * JC42.4 compliant temperature sensors are typically used on memory modules. --- 162 unchanged lines hidden (view full) --- 171 u16 orig_config; /* original configuration */ 172 u16 config; /* current configuration */ 173 u16 temp_input; /* Temperatures */ 174 u16 temp_crit; 175 u16 temp_min; 176 u16 temp_max; 177}; 178 | 1/* 2 * jc42.c - driver for Jedec JC42.4 compliant temperature sensors 3 * 4 * Copyright (c) 2010 Ericsson AB. 5 * 6 * Derived from lm77.c by Andras BALI <drewie@freemail.hu>. 7 * 8 * JC42.4 compliant temperature sensors are typically used on memory modules. --- 162 unchanged lines hidden (view full) --- 171 u16 orig_config; /* original configuration */ 172 u16 config; /* current configuration */ 173 u16 temp_input; /* Temperatures */ 174 u16 temp_crit; 175 u16 temp_min; 176 u16 temp_max; 177}; 178 |
179static int jc42_probe(struct i2c_client *client, 180 const struct i2c_device_id *id); 181static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info); 182static int jc42_remove(struct i2c_client *client); 183 184static struct jc42_data *jc42_update_device(struct device *dev); 185 186static const struct i2c_device_id jc42_id[] = { 187 { "jc42", 0 }, 188 { } 189}; 190MODULE_DEVICE_TABLE(i2c, jc42_id); 191 192#ifdef CONFIG_PM 193 194static int jc42_suspend(struct device *dev) 195{ 196 struct jc42_data *data = dev_get_drvdata(dev); 197 198 data->config |= JC42_CFG_SHUTDOWN; 199 i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG, 200 data->config); 201 return 0; 202} 203 204static int jc42_resume(struct device *dev) 205{ 206 struct jc42_data *data = dev_get_drvdata(dev); 207 208 data->config &= ~JC42_CFG_SHUTDOWN; 209 i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG, 210 data->config); 211 return 0; 212} 213 214static const struct dev_pm_ops jc42_dev_pm_ops = { 215 .suspend = jc42_suspend, 216 .resume = jc42_resume, 217}; 218 219#define JC42_DEV_PM_OPS (&jc42_dev_pm_ops) 220#else 221#define JC42_DEV_PM_OPS NULL 222#endif /* CONFIG_PM */ 223 224/* This is the driver that will be inserted */ 225static struct i2c_driver jc42_driver = { 226 .class = I2C_CLASS_SPD, 227 .driver = { 228 .name = "jc42", 229 .pm = JC42_DEV_PM_OPS, 230 }, 231 .probe = jc42_probe, 232 .remove = jc42_remove, 233 .id_table = jc42_id, 234 .detect = jc42_detect, 235 .address_list = normal_i2c, 236}; 237 | |
238#define JC42_TEMP_MIN_EXTENDED (-40000) 239#define JC42_TEMP_MIN 0 240#define JC42_TEMP_MAX 125000 241 242static u16 jc42_temp_to_reg(int temp, bool extended) 243{ 244 int ntemp = clamp_val(temp, 245 extended ? JC42_TEMP_MIN_EXTENDED : --- 10 unchanged lines hidden (view full) --- 256 /* sign extend register */ 257 if (reg & 0x1000) 258 reg |= 0xf000; 259 260 /* convert from 0.0625 to 0.001 resolution */ 261 return reg * 125 / 2; 262} 263 | 179#define JC42_TEMP_MIN_EXTENDED (-40000) 180#define JC42_TEMP_MIN 0 181#define JC42_TEMP_MAX 125000 182 183static u16 jc42_temp_to_reg(int temp, bool extended) 184{ 185 int ntemp = clamp_val(temp, 186 extended ? JC42_TEMP_MIN_EXTENDED : --- 10 unchanged lines hidden (view full) --- 197 /* sign extend register */ 198 if (reg & 0x1000) 199 reg |= 0xf000; 200 201 /* convert from 0.0625 to 0.001 resolution */ 202 return reg * 125 / 2; 203} 204 |
205static struct jc42_data *jc42_update_device(struct device *dev) 206{ 207 struct jc42_data *data = dev_get_drvdata(dev); 208 struct i2c_client *client = data->client; 209 struct jc42_data *ret = data; 210 int val; 211 212 mutex_lock(&data->update_lock); 213 214 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { 215 val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP); 216 if (val < 0) { 217 ret = ERR_PTR(val); 218 goto abort; 219 } 220 data->temp_input = val; 221 222 val = i2c_smbus_read_word_swapped(client, 223 JC42_REG_TEMP_CRITICAL); 224 if (val < 0) { 225 ret = ERR_PTR(val); 226 goto abort; 227 } 228 data->temp_crit = val; 229 230 val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_LOWER); 231 if (val < 0) { 232 ret = ERR_PTR(val); 233 goto abort; 234 } 235 data->temp_min = val; 236 237 val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_UPPER); 238 if (val < 0) { 239 ret = ERR_PTR(val); 240 goto abort; 241 } 242 data->temp_max = val; 243 244 data->last_updated = jiffies; 245 data->valid = true; 246 } 247abort: 248 mutex_unlock(&data->update_lock); 249 return ret; 250} 251 |
|
264/* sysfs stuff */ 265 266/* read routines for temperature limits */ 267#define show(value) \ 268static ssize_t show_##value(struct device *dev, \ 269 struct device_attribute *attr, \ 270 char *buf) \ 271{ \ --- 260 unchanged lines hidden (view full) --- 532 533 config = (data->orig_config & ~JC42_CFG_HYST_MASK) 534 | (data->config & JC42_CFG_HYST_MASK); 535 i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); 536 } 537 return 0; 538} 539 | 252/* sysfs stuff */ 253 254/* read routines for temperature limits */ 255#define show(value) \ 256static ssize_t show_##value(struct device *dev, \ 257 struct device_attribute *attr, \ 258 char *buf) \ 259{ \ --- 260 unchanged lines hidden (view full) --- 520 521 config = (data->orig_config & ~JC42_CFG_HYST_MASK) 522 | (data->config & JC42_CFG_HYST_MASK); 523 i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); 524 } 525 return 0; 526} 527 |
540static struct jc42_data *jc42_update_device(struct device *dev) | 528#ifdef CONFIG_PM 529 530static int jc42_suspend(struct device *dev) |
541{ 542 struct jc42_data *data = dev_get_drvdata(dev); | 531{ 532 struct jc42_data *data = dev_get_drvdata(dev); |
543 struct i2c_client *client = data->client; 544 struct jc42_data *ret = data; 545 int val; | |
546 | 533 |
547 mutex_lock(&data->update_lock); | 534 data->config |= JC42_CFG_SHUTDOWN; 535 i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG, 536 data->config); 537 return 0; 538} |
548 | 539 |
549 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { 550 val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP); 551 if (val < 0) { 552 ret = ERR_PTR(val); 553 goto abort; 554 } 555 data->temp_input = val; | 540static int jc42_resume(struct device *dev) 541{ 542 struct jc42_data *data = dev_get_drvdata(dev); |
556 | 543 |
557 val = i2c_smbus_read_word_swapped(client, 558 JC42_REG_TEMP_CRITICAL); 559 if (val < 0) { 560 ret = ERR_PTR(val); 561 goto abort; 562 } 563 data->temp_crit = val; | 544 data->config &= ~JC42_CFG_SHUTDOWN; 545 i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG, 546 data->config); 547 return 0; 548} |
564 | 549 |
565 val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_LOWER); 566 if (val < 0) { 567 ret = ERR_PTR(val); 568 goto abort; 569 } 570 data->temp_min = val; | 550static const struct dev_pm_ops jc42_dev_pm_ops = { 551 .suspend = jc42_suspend, 552 .resume = jc42_resume, 553}; |
571 | 554 |
572 val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_UPPER); 573 if (val < 0) { 574 ret = ERR_PTR(val); 575 goto abort; 576 } 577 data->temp_max = val; | 555#define JC42_DEV_PM_OPS (&jc42_dev_pm_ops) 556#else 557#define JC42_DEV_PM_OPS NULL 558#endif /* CONFIG_PM */ |
578 | 559 |
579 data->last_updated = jiffies; 580 data->valid = true; 581 } 582abort: 583 mutex_unlock(&data->update_lock); 584 return ret; 585} | 560static const struct i2c_device_id jc42_id[] = { 561 { "jc42", 0 }, 562 { } 563}; 564MODULE_DEVICE_TABLE(i2c, jc42_id); |
586 | 565 |
566static struct i2c_driver jc42_driver = { 567 .class = I2C_CLASS_SPD, 568 .driver = { 569 .name = "jc42", 570 .pm = JC42_DEV_PM_OPS, 571 }, 572 .probe = jc42_probe, 573 .remove = jc42_remove, 574 .id_table = jc42_id, 575 .detect = jc42_detect, 576 .address_list = normal_i2c, 577}; 578 |
|
587module_i2c_driver(jc42_driver); 588 589MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); 590MODULE_DESCRIPTION("JC42 driver"); 591MODULE_LICENSE("GPL"); | 579module_i2c_driver(jc42_driver); 580 581MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); 582MODULE_DESCRIPTION("JC42 driver"); 583MODULE_LICENSE("GPL"); |