sch5627.c (a54fe61639d9f3b6765fee32edda7cfceb6d705a) | sch5627.c (10655bb6df25514e0ae8406637c3b4acbc812fe5) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/*************************************************************************** 3 * Copyright (C) 2010-2012 Hans de Goede <hdegoede@redhat.com> * 4 * * 5 ***************************************************************************/ 6 7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 9#include <linux/bits.h> | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/*************************************************************************** 3 * Copyright (C) 2010-2012 Hans de Goede <hdegoede@redhat.com> * 4 * * 5 ***************************************************************************/ 6 7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 9#include <linux/bits.h> |
10#include <linux/minmax.h> |
|
10#include <linux/module.h> 11#include <linux/mod_devicetable.h> 12#include <linux/pm.h> 13#include <linux/init.h> 14#include <linux/regmap.h> 15#include <linux/slab.h> 16#include <linux/jiffies.h> 17#include <linux/platform_device.h> --- 54 unchanged lines hidden (view full) --- 72 10745, 3660, 9765, 10745, 3660 }; 73static const char * const SCH5627_IN_LABELS[SCH5627_NO_IN] = { 74 "VCC", "VTT", "VBAT", "VTR", "V_IN" }; 75 76struct sch5627_data { 77 struct regmap *regmap; 78 unsigned short addr; 79 u8 control; | 11#include <linux/module.h> 12#include <linux/mod_devicetable.h> 13#include <linux/pm.h> 14#include <linux/init.h> 15#include <linux/regmap.h> 16#include <linux/slab.h> 17#include <linux/jiffies.h> 18#include <linux/platform_device.h> --- 54 unchanged lines hidden (view full) --- 73 10745, 3660, 9765, 10745, 3660 }; 74static const char * const SCH5627_IN_LABELS[SCH5627_NO_IN] = { 75 "VCC", "VTT", "VBAT", "VTR", "V_IN" }; 76 77struct sch5627_data { 78 struct regmap *regmap; 79 unsigned short addr; 80 u8 control; |
80 u8 temp_max[SCH5627_NO_TEMPS]; 81 u8 temp_crit[SCH5627_NO_TEMPS]; 82 u16 fan_min[SCH5627_NO_FANS]; | |
83 84 struct mutex update_lock; 85 unsigned long last_battery; /* In jiffies */ 86 char temp_valid; /* !=0 if following fields are valid */ 87 char fan_valid; 88 char in_valid; 89 unsigned long temp_last_updated; /* In jiffies */ 90 unsigned long fan_last_updated; 91 unsigned long in_last_updated; 92 u16 temp[SCH5627_NO_TEMPS]; 93 u16 fan[SCH5627_NO_FANS]; 94 u16 in[SCH5627_NO_IN]; 95}; 96 97static const struct regmap_range sch5627_tunables_ranges[] = { | 81 82 struct mutex update_lock; 83 unsigned long last_battery; /* In jiffies */ 84 char temp_valid; /* !=0 if following fields are valid */ 85 char fan_valid; 86 char in_valid; 87 unsigned long temp_last_updated; /* In jiffies */ 88 unsigned long fan_last_updated; 89 unsigned long in_last_updated; 90 u16 temp[SCH5627_NO_TEMPS]; 91 u16 fan[SCH5627_NO_FANS]; 92 u16 in[SCH5627_NO_IN]; 93}; 94 95static const struct regmap_range sch5627_tunables_ranges[] = { |
96 regmap_reg_range(0x57, 0x57), 97 regmap_reg_range(0x59, 0x59), 98 regmap_reg_range(0x5B, 0x5B), 99 regmap_reg_range(0x5D, 0x5D), 100 regmap_reg_range(0x5F, 0x5F), 101 regmap_reg_range(0x61, 0x69), 102 regmap_reg_range(0x96, 0x9B), |
|
98 regmap_reg_range(0xA0, 0xA3), | 103 regmap_reg_range(0xA0, 0xA3), |
104 regmap_reg_range(0x184, 0x184), 105 regmap_reg_range(0x186, 0x186), 106 regmap_reg_range(0x1A8, 0x1A9), |
|
99}; 100 101static const struct regmap_access_table sch5627_tunables_table = { 102 .yes_ranges = sch5627_tunables_ranges, 103 .n_yes_ranges = ARRAY_SIZE(sch5627_tunables_ranges), 104}; 105 106static const struct regmap_config sch5627_regmap_config = { --- 88 unchanged lines hidden (view full) --- 195 data->in_last_updated = jiffies; 196 data->in_valid = 1; 197 } 198abort: 199 mutex_unlock(&data->update_lock); 200 return ret; 201} 202 | 107}; 108 109static const struct regmap_access_table sch5627_tunables_table = { 110 .yes_ranges = sch5627_tunables_ranges, 111 .n_yes_ranges = ARRAY_SIZE(sch5627_tunables_ranges), 112}; 113 114static const struct regmap_config sch5627_regmap_config = { --- 88 unchanged lines hidden (view full) --- 203 data->in_last_updated = jiffies; 204 data->in_valid = 1; 205 } 206abort: 207 mutex_unlock(&data->update_lock); 208 return ret; 209} 210 |
203static int sch5627_read_limits(struct sch5627_data *data) 204{ 205 int i, val; 206 207 for (i = 0; i < SCH5627_NO_TEMPS; i++) { 208 /* 209 * Note what SMSC calls ABS, is what lm_sensors calls max 210 * (aka high), and HIGH is what lm_sensors calls crit. 211 */ 212 val = sch56xx_read_virtual_reg(data->addr, 213 SCH5627_REG_TEMP_ABS[i]); 214 if (val < 0) 215 return val; 216 data->temp_max[i] = val; 217 218 val = sch56xx_read_virtual_reg(data->addr, 219 SCH5627_REG_TEMP_HIGH[i]); 220 if (val < 0) 221 return val; 222 data->temp_crit[i] = val; 223 } 224 for (i = 0; i < SCH5627_NO_FANS; i++) { 225 val = sch56xx_read_virtual_reg16(data->addr, 226 SCH5627_REG_FAN_MIN[i]); 227 if (val < 0) 228 return val; 229 data->fan_min[i] = val; 230 } 231 232 return 0; 233} 234 | |
235static int reg_to_temp(u16 reg) 236{ 237 return (reg * 625) / 10 - 64000; 238} 239 240static int reg_to_temp_limit(u8 reg) 241{ 242 return (reg - 64) * 1000; --- 4 unchanged lines hidden (view full) --- 247 if (reg == 0) 248 return -EIO; 249 if (reg == 0xffff) 250 return 0; 251 252 return 5400540 / reg; 253} 254 | 211static int reg_to_temp(u16 reg) 212{ 213 return (reg * 625) / 10 - 64000; 214} 215 216static int reg_to_temp_limit(u8 reg) 217{ 218 return (reg - 64) * 1000; --- 4 unchanged lines hidden (view full) --- 223 if (reg == 0) 224 return -EIO; 225 if (reg == 0xffff) 226 return 0; 227 228 return 5400540 / reg; 229} 230 |
231static u8 sch5627_temp_limit_to_reg(long value) 232{ 233 long limit = (value / 1000) + 64; 234 235 return clamp_val(limit, 0, U8_MAX); 236} 237 238static u16 sch5627_rpm_to_reg(long value) 239{ 240 long pulses; 241 242 if (value <= 0) 243 return U16_MAX - 1; 244 245 pulses = 5400540 / value; 246 247 return clamp_val(pulses, 1, U16_MAX - 1); 248} 249 |
|
255static umode_t sch5627_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr, 256 int channel) 257{ 258 const struct sch5627_data *data = drvdata; 259 260 /* Once the lock bit is set, the virtual registers become read-only 261 * until the next power cycle. 262 */ 263 if (data->control & SCH5627_CTRL_LOCK) 264 return 0444; 265 | 250static umode_t sch5627_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr, 251 int channel) 252{ 253 const struct sch5627_data *data = drvdata; 254 255 /* Once the lock bit is set, the virtual registers become read-only 256 * until the next power cycle. 257 */ 258 if (data->control & SCH5627_CTRL_LOCK) 259 return 0444; 260 |
266 if (type == hwmon_pwm && attr == hwmon_pwm_auto_channels_temp) 267 return 0644; | 261 switch (type) { 262 case hwmon_temp: 263 switch (attr) { 264 case hwmon_temp_max: 265 case hwmon_temp_crit: 266 return 0644; 267 default: 268 break; 269 } 270 break; 271 case hwmon_fan: 272 switch (attr) { 273 case hwmon_fan_min: 274 return 0644; 275 default: 276 break; 277 } 278 break; 279 case hwmon_pwm: 280 switch (attr) { 281 case hwmon_pwm_auto_channels_temp: 282 return 0644; 283 default: 284 break; 285 } 286 break; 287 default: 288 break; 289 } |
268 269 return 0444; 270} 271 272static int sch5627_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, 273 long *val) 274{ 275 struct sch5627_data *data = dev_get_drvdata(dev); 276 int ret, value; 277 278 switch (type) { 279 case hwmon_temp: | 290 291 return 0444; 292} 293 294static int sch5627_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, 295 long *val) 296{ 297 struct sch5627_data *data = dev_get_drvdata(dev); 298 int ret, value; 299 300 switch (type) { 301 case hwmon_temp: |
280 ret = sch5627_update_temp(data); 281 if (ret < 0) 282 return ret; | |
283 switch (attr) { 284 case hwmon_temp_input: | 302 switch (attr) { 303 case hwmon_temp_input: |
304 ret = sch5627_update_temp(data); 305 if (ret < 0) 306 return ret; 307 |
|
285 *val = reg_to_temp(data->temp[channel]); 286 return 0; 287 case hwmon_temp_max: | 308 *val = reg_to_temp(data->temp[channel]); 309 return 0; 310 case hwmon_temp_max: |
288 *val = reg_to_temp_limit(data->temp_max[channel]); | 311 ret = regmap_read(data->regmap, SCH5627_REG_TEMP_ABS[channel], &value); 312 if (ret < 0) 313 return ret; 314 315 *val = reg_to_temp_limit((u8)value); |
289 return 0; 290 case hwmon_temp_crit: | 316 return 0; 317 case hwmon_temp_crit: |
291 *val = reg_to_temp_limit(data->temp_crit[channel]); | 318 ret = regmap_read(data->regmap, SCH5627_REG_TEMP_HIGH[channel], &value); 319 if (ret < 0) 320 return ret; 321 322 *val = reg_to_temp_limit((u8)value); |
292 return 0; 293 case hwmon_temp_fault: | 323 return 0; 324 case hwmon_temp_fault: |
325 ret = sch5627_update_temp(data); 326 if (ret < 0) 327 return ret; 328 |
|
294 *val = (data->temp[channel] == 0); 295 return 0; 296 default: 297 break; 298 } 299 break; 300 case hwmon_fan: | 329 *val = (data->temp[channel] == 0); 330 return 0; 331 default: 332 break; 333 } 334 break; 335 case hwmon_fan: |
301 ret = sch5627_update_fan(data); 302 if (ret < 0) 303 return ret; | |
304 switch (attr) { 305 case hwmon_fan_input: | 336 switch (attr) { 337 case hwmon_fan_input: |
338 ret = sch5627_update_fan(data); 339 if (ret < 0) 340 return ret; 341 |
|
306 ret = reg_to_rpm(data->fan[channel]); 307 if (ret < 0) 308 return ret; | 342 ret = reg_to_rpm(data->fan[channel]); 343 if (ret < 0) 344 return ret; |
345 |
|
309 *val = ret; 310 return 0; 311 case hwmon_fan_min: | 346 *val = ret; 347 return 0; 348 case hwmon_fan_min: |
312 ret = reg_to_rpm(data->fan_min[channel]); | 349 ret = sch56xx_regmap_read16(data->regmap, SCH5627_REG_FAN_MIN[channel], 350 &value); |
313 if (ret < 0) 314 return ret; | 351 if (ret < 0) 352 return ret; |
353 354 ret = reg_to_rpm((u16)value); 355 if (ret < 0) 356 return ret; 357 |
|
315 *val = ret; 316 return 0; 317 case hwmon_fan_fault: | 358 *val = ret; 359 return 0; 360 case hwmon_fan_fault: |
361 ret = sch5627_update_fan(data); 362 if (ret < 0) 363 return ret; 364 |
|
318 *val = (data->fan[channel] == 0xffff); 319 return 0; 320 default: 321 break; 322 } 323 break; 324 case hwmon_pwm: 325 switch (attr) { --- 47 unchanged lines hidden (view full) --- 373 374 return -EOPNOTSUPP; 375} 376 377static int sch5627_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, 378 long val) 379{ 380 struct sch5627_data *data = dev_get_drvdata(dev); | 365 *val = (data->fan[channel] == 0xffff); 366 return 0; 367 default: 368 break; 369 } 370 break; 371 case hwmon_pwm: 372 switch (attr) { --- 47 unchanged lines hidden (view full) --- 420 421 return -EOPNOTSUPP; 422} 423 424static int sch5627_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, 425 long val) 426{ 427 struct sch5627_data *data = dev_get_drvdata(dev); |
428 u16 fan; 429 u8 temp; |
|
381 382 switch (type) { | 430 431 switch (type) { |
432 case hwmon_temp: 433 temp = sch5627_temp_limit_to_reg(val); 434 435 switch (attr) { 436 case hwmon_temp_max: 437 return regmap_write(data->regmap, SCH5627_REG_TEMP_ABS[channel], temp); 438 case hwmon_temp_crit: 439 return regmap_write(data->regmap, SCH5627_REG_TEMP_HIGH[channel], temp); 440 default: 441 break; 442 } 443 break; 444 case hwmon_fan: 445 switch (attr) { 446 case hwmon_fan_min: 447 fan = sch5627_rpm_to_reg(val); 448 449 return sch56xx_regmap_write16(data->regmap, SCH5627_REG_FAN_MIN[channel], 450 fan); 451 default: 452 break; 453 } 454 break; |
|
383 case hwmon_pwm: 384 switch (attr) { 385 case hwmon_pwm_auto_channels_temp: 386 /* registers are 8 bit wide */ 387 if (val > U8_MAX || val < 0) 388 return -EINVAL; 389 390 return regmap_write(data->regmap, SCH5627_REG_PWM_MAP[channel], val); --- 53 unchanged lines hidden (view full) --- 444 .ops = &sch5627_ops, 445 .info = sch5627_info, 446}; 447 448static int sch5627_probe(struct platform_device *pdev) 449{ 450 struct sch5627_data *data; 451 struct device *hwmon_dev; | 455 case hwmon_pwm: 456 switch (attr) { 457 case hwmon_pwm_auto_channels_temp: 458 /* registers are 8 bit wide */ 459 if (val > U8_MAX || val < 0) 460 return -EINVAL; 461 462 return regmap_write(data->regmap, SCH5627_REG_PWM_MAP[channel], val); --- 53 unchanged lines hidden (view full) --- 516 .ops = &sch5627_ops, 517 .info = sch5627_info, 518}; 519 520static int sch5627_probe(struct platform_device *pdev) 521{ 522 struct sch5627_data *data; 523 struct device *hwmon_dev; |
452 int err, build_code, build_id, hwmon_rev, val; | 524 int build_code, build_id, hwmon_rev, val; |
453 454 data = devm_kzalloc(&pdev->dev, sizeof(struct sch5627_data), 455 GFP_KERNEL); 456 if (!data) 457 return -ENOMEM; 458 459 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; 460 mutex_init(&data->update_lock); --- 59 unchanged lines hidden (view full) --- 520 if (IS_ERR(data->regmap)) 521 return PTR_ERR(data->regmap); 522 523 /* Trigger a Vbat voltage measurement, so that we get a valid reading 524 the first time we read Vbat */ 525 sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL, data->control | SCH5627_CTRL_VBAT); 526 data->last_battery = jiffies; 527 | 525 526 data = devm_kzalloc(&pdev->dev, sizeof(struct sch5627_data), 527 GFP_KERNEL); 528 if (!data) 529 return -ENOMEM; 530 531 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; 532 mutex_init(&data->update_lock); --- 59 unchanged lines hidden (view full) --- 592 if (IS_ERR(data->regmap)) 593 return PTR_ERR(data->regmap); 594 595 /* Trigger a Vbat voltage measurement, so that we get a valid reading 596 the first time we read Vbat */ 597 sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL, data->control | SCH5627_CTRL_VBAT); 598 data->last_battery = jiffies; 599 |
528 /* 529 * Read limits, we do this only once as reading a register on 530 * the sch5627 is quite expensive (and they don't change). 531 */ 532 err = sch5627_read_limits(data); 533 if (err) 534 return err; 535 | |
536 pr_info("found %s chip at %#hx\n", DEVNAME, data->addr); 537 pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n", 538 build_code, build_id, hwmon_rev); 539 540 hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, DEVNAME, data, 541 &sch5627_chip_info, NULL); 542 if (IS_ERR(hwmon_dev)) 543 return PTR_ERR(hwmon_dev); --- 55 unchanged lines hidden --- | 600 pr_info("found %s chip at %#hx\n", DEVNAME, data->addr); 601 pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n", 602 build_code, build_id, hwmon_rev); 603 604 hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, DEVNAME, data, 605 &sch5627_chip_info, NULL); 606 if (IS_ERR(hwmon_dev)) 607 return PTR_ERR(hwmon_dev); --- 55 unchanged lines hidden --- |