diff options
| -rw-r--r-- | Documentation/hwmon/ltc4215 | 7 | ||||
| -rw-r--r-- | Documentation/hwmon/ltc4245 | 7 | ||||
| -rw-r--r-- | drivers/hwmon/ltc4215.c | 47 | ||||
| -rw-r--r-- | drivers/hwmon/ltc4245.c | 131 |
4 files changed, 18 insertions, 174 deletions
diff --git a/Documentation/hwmon/ltc4215 b/Documentation/hwmon/ltc4215 index 2e6a21eb656..c196a184625 100644 --- a/Documentation/hwmon/ltc4215 +++ b/Documentation/hwmon/ltc4215 | |||
| @@ -22,12 +22,13 @@ Usage Notes | |||
| 22 | ----------- | 22 | ----------- |
| 23 | 23 | ||
| 24 | This driver does not probe for LTC4215 devices, due to the fact that some | 24 | This driver does not probe for LTC4215 devices, due to the fact that some |
| 25 | of the possible addresses are unfriendly to probing. You will need to use | 25 | of the possible addresses are unfriendly to probing. You will have to |
| 26 | the "force" parameter to tell the driver where to find the device. | 26 | instantiate the devices explicitly. |
| 27 | 27 | ||
| 28 | Example: the following will load the driver for an LTC4215 at address 0x44 | 28 | Example: the following will load the driver for an LTC4215 at address 0x44 |
| 29 | on I2C bus #0: | 29 | on I2C bus #0: |
| 30 | $ modprobe ltc4215 force=0,0x44 | 30 | $ modprobe ltc4215 |
| 31 | $ echo ltc4215 0x44 > /sys/bus/i2c/devices/i2c-0/new_device | ||
| 31 | 32 | ||
| 32 | 33 | ||
| 33 | Sysfs entries | 34 | Sysfs entries |
diff --git a/Documentation/hwmon/ltc4245 b/Documentation/hwmon/ltc4245 index bae7a3adc5d..02838a47d86 100644 --- a/Documentation/hwmon/ltc4245 +++ b/Documentation/hwmon/ltc4245 | |||
| @@ -23,12 +23,13 @@ Usage Notes | |||
| 23 | ----------- | 23 | ----------- |
| 24 | 24 | ||
| 25 | This driver does not probe for LTC4245 devices, due to the fact that some | 25 | This driver does not probe for LTC4245 devices, due to the fact that some |
| 26 | of the possible addresses are unfriendly to probing. You will need to use | 26 | of the possible addresses are unfriendly to probing. You will have to |
| 27 | the "force" parameter to tell the driver where to find the device. | 27 | instantiate the devices explicitly. |
| 28 | 28 | ||
| 29 | Example: the following will load the driver for an LTC4245 at address 0x23 | 29 | Example: the following will load the driver for an LTC4245 at address 0x23 |
| 30 | on I2C bus #1: | 30 | on I2C bus #1: |
| 31 | $ modprobe ltc4245 force=1,0x23 | 31 | $ modprobe ltc4245 |
| 32 | $ echo ltc4245 0x23 > /sys/bus/i2c/devices/i2c-1/new_device | ||
| 32 | 33 | ||
| 33 | 34 | ||
| 34 | Sysfs entries | 35 | Sysfs entries |
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c index 6c9a04136e0..00d975eb5b8 100644 --- a/drivers/hwmon/ltc4215.c +++ b/drivers/hwmon/ltc4215.c | |||
| @@ -20,11 +20,6 @@ | |||
| 20 | #include <linux/hwmon.h> | 20 | #include <linux/hwmon.h> |
| 21 | #include <linux/hwmon-sysfs.h> | 21 | #include <linux/hwmon-sysfs.h> |
| 22 | 22 | ||
| 23 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
| 24 | |||
| 25 | /* Insmod parameters */ | ||
| 26 | I2C_CLIENT_INSMOD_1(ltc4215); | ||
| 27 | |||
| 28 | /* Here are names of the chip's registers (a.k.a. commands) */ | 23 | /* Here are names of the chip's registers (a.k.a. commands) */ |
| 29 | enum ltc4215_cmd { | 24 | enum ltc4215_cmd { |
| 30 | LTC4215_CONTROL = 0x00, /* rw */ | 25 | LTC4215_CONTROL = 0x00, /* rw */ |
| @@ -246,9 +241,13 @@ static const struct attribute_group ltc4215_group = { | |||
| 246 | static int ltc4215_probe(struct i2c_client *client, | 241 | static int ltc4215_probe(struct i2c_client *client, |
| 247 | const struct i2c_device_id *id) | 242 | const struct i2c_device_id *id) |
| 248 | { | 243 | { |
| 244 | struct i2c_adapter *adapter = client->adapter; | ||
| 249 | struct ltc4215_data *data; | 245 | struct ltc4215_data *data; |
| 250 | int ret; | 246 | int ret; |
| 251 | 247 | ||
| 248 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 249 | return -ENODEV; | ||
| 250 | |||
| 252 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 251 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
| 253 | if (!data) { | 252 | if (!data) { |
| 254 | ret = -ENOMEM; | 253 | ret = -ENOMEM; |
| @@ -294,56 +293,20 @@ static int ltc4215_remove(struct i2c_client *client) | |||
| 294 | return 0; | 293 | return 0; |
| 295 | } | 294 | } |
| 296 | 295 | ||
| 297 | static int ltc4215_detect(struct i2c_client *client, | ||
| 298 | int kind, | ||
| 299 | struct i2c_board_info *info) | ||
| 300 | { | ||
| 301 | struct i2c_adapter *adapter = client->adapter; | ||
| 302 | |||
| 303 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 304 | return -ENODEV; | ||
| 305 | |||
| 306 | if (kind < 0) { /* probed detection - check the chip type */ | ||
| 307 | s32 v; /* 8 bits from the chip, or -ERRNO */ | ||
| 308 | |||
| 309 | /* | ||
| 310 | * Register 0x01 bit b7 is reserved, expect 0 | ||
| 311 | * Register 0x03 bit b6 and b7 are reserved, expect 0 | ||
| 312 | */ | ||
| 313 | v = i2c_smbus_read_byte_data(client, LTC4215_ALERT); | ||
| 314 | if (v < 0 || (v & (1 << 7)) != 0) | ||
| 315 | return -ENODEV; | ||
| 316 | |||
| 317 | v = i2c_smbus_read_byte_data(client, LTC4215_FAULT); | ||
| 318 | if (v < 0 || (v & ((1 << 6) | (1 << 7))) != 0) | ||
| 319 | return -ENODEV; | ||
| 320 | } | ||
| 321 | |||
| 322 | strlcpy(info->type, "ltc4215", I2C_NAME_SIZE); | ||
| 323 | dev_info(&adapter->dev, "ltc4215 %s at address 0x%02x\n", | ||
| 324 | kind < 0 ? "probed" : "forced", | ||
| 325 | client->addr); | ||
| 326 | |||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | static const struct i2c_device_id ltc4215_id[] = { | 296 | static const struct i2c_device_id ltc4215_id[] = { |
| 331 | { "ltc4215", ltc4215 }, | 297 | { "ltc4215", 0 }, |
| 332 | { } | 298 | { } |
| 333 | }; | 299 | }; |
| 334 | MODULE_DEVICE_TABLE(i2c, ltc4215_id); | 300 | MODULE_DEVICE_TABLE(i2c, ltc4215_id); |
| 335 | 301 | ||
| 336 | /* This is the driver that will be inserted */ | 302 | /* This is the driver that will be inserted */ |
| 337 | static struct i2c_driver ltc4215_driver = { | 303 | static struct i2c_driver ltc4215_driver = { |
| 338 | .class = I2C_CLASS_HWMON, | ||
| 339 | .driver = { | 304 | .driver = { |
| 340 | .name = "ltc4215", | 305 | .name = "ltc4215", |
| 341 | }, | 306 | }, |
| 342 | .probe = ltc4215_probe, | 307 | .probe = ltc4215_probe, |
| 343 | .remove = ltc4215_remove, | 308 | .remove = ltc4215_remove, |
| 344 | .id_table = ltc4215_id, | 309 | .id_table = ltc4215_id, |
| 345 | .detect = ltc4215_detect, | ||
| 346 | .address_data = &addr_data, | ||
| 347 | }; | 310 | }; |
| 348 | 311 | ||
| 349 | static int __init ltc4215_init(void) | 312 | static int __init ltc4215_init(void) |
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index e3896433361..65c232a9d0c 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c | |||
| @@ -22,15 +22,6 @@ | |||
| 22 | #include <linux/hwmon.h> | 22 | #include <linux/hwmon.h> |
| 23 | #include <linux/hwmon-sysfs.h> | 23 | #include <linux/hwmon-sysfs.h> |
| 24 | 24 | ||
| 25 | /* Valid addresses are 0x20 - 0x3f | ||
| 26 | * | ||
| 27 | * For now, we do not probe, since some of these addresses | ||
| 28 | * are known to be unfriendly to probing */ | ||
| 29 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
| 30 | |||
| 31 | /* Insmod parameters */ | ||
| 32 | I2C_CLIENT_INSMOD_1(ltc4245); | ||
| 33 | |||
| 34 | /* Here are names of the chip's registers (a.k.a. commands) */ | 25 | /* Here are names of the chip's registers (a.k.a. commands) */ |
| 35 | enum ltc4245_cmd { | 26 | enum ltc4245_cmd { |
| 36 | LTC4245_STATUS = 0x00, /* readonly */ | 27 | LTC4245_STATUS = 0x00, /* readonly */ |
| @@ -369,9 +360,13 @@ static const struct attribute_group ltc4245_group = { | |||
| 369 | static int ltc4245_probe(struct i2c_client *client, | 360 | static int ltc4245_probe(struct i2c_client *client, |
| 370 | const struct i2c_device_id *id) | 361 | const struct i2c_device_id *id) |
| 371 | { | 362 | { |
| 363 | struct i2c_adapter *adapter = client->adapter; | ||
| 372 | struct ltc4245_data *data; | 364 | struct ltc4245_data *data; |
| 373 | int ret; | 365 | int ret; |
| 374 | 366 | ||
| 367 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 368 | return -ENODEV; | ||
| 369 | |||
| 375 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 370 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
| 376 | if (!data) { | 371 | if (!data) { |
| 377 | ret = -ENOMEM; | 372 | ret = -ENOMEM; |
| @@ -418,136 +413,20 @@ static int ltc4245_remove(struct i2c_client *client) | |||
| 418 | return 0; | 413 | return 0; |
| 419 | } | 414 | } |
| 420 | 415 | ||
| 421 | /* Check that some bits in a control register appear at all possible | ||
| 422 | * locations without changing value | ||
| 423 | * | ||
| 424 | * @client: the i2c client to use | ||
| 425 | * @reg: the register to read | ||
| 426 | * @bits: the bits to check (0xff checks all bits, | ||
| 427 | * 0x03 checks only the last two bits) | ||
| 428 | * | ||
| 429 | * return -ERRNO if the register read failed | ||
| 430 | * return -ENODEV if the register value doesn't stay constant at all | ||
| 431 | * possible addresses | ||
| 432 | * | ||
| 433 | * return 0 for success | ||
| 434 | */ | ||
| 435 | static int ltc4245_check_control_reg(struct i2c_client *client, u8 reg, u8 bits) | ||
| 436 | { | ||
| 437 | int i; | ||
| 438 | s32 v, voff1, voff2; | ||
| 439 | |||
| 440 | /* Read register and check for error */ | ||
| 441 | v = i2c_smbus_read_byte_data(client, reg); | ||
| 442 | if (v < 0) | ||
| 443 | return v; | ||
| 444 | |||
| 445 | v &= bits; | ||
| 446 | |||
| 447 | for (i = 0x00; i < 0xff; i += 0x20) { | ||
| 448 | |||
| 449 | voff1 = i2c_smbus_read_byte_data(client, reg + i); | ||
| 450 | if (voff1 < 0) | ||
| 451 | return voff1; | ||
| 452 | |||
| 453 | voff2 = i2c_smbus_read_byte_data(client, reg + i + 0x08); | ||
| 454 | if (voff2 < 0) | ||
| 455 | return voff2; | ||
| 456 | |||
| 457 | voff1 &= bits; | ||
| 458 | voff2 &= bits; | ||
| 459 | |||
| 460 | if (v != voff1 || v != voff2) | ||
| 461 | return -ENODEV; | ||
| 462 | } | ||
| 463 | |||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | |||
| 467 | static int ltc4245_detect(struct i2c_client *client, | ||
| 468 | int kind, | ||
| 469 | struct i2c_board_info *info) | ||
| 470 | { | ||
| 471 | struct i2c_adapter *adapter = client->adapter; | ||
| 472 | |||
| 473 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 474 | return -ENODEV; | ||
| 475 | |||
| 476 | if (kind < 0) { /* probed detection - check the chip type */ | ||
| 477 | s32 v; /* 8 bits from the chip, or -ERRNO */ | ||
| 478 | |||
| 479 | /* Chip registers 0x00-0x07 are control registers | ||
| 480 | * Chip registers 0x10-0x1f are data registers | ||
| 481 | * | ||
| 482 | * Address bits b7-b5 are ignored. This makes the chip "repeat" | ||
| 483 | * in steps of 0x20. Any control registers should appear with | ||
| 484 | * the same values across all duplicated addresses. | ||
| 485 | * | ||
| 486 | * Register 0x02 bit b2 is reserved, expect 0 | ||
| 487 | * Register 0x07 bits b7 to b4 are reserved, expect 0 | ||
| 488 | * | ||
| 489 | * Registers 0x01, 0x02 are control registers and should not | ||
| 490 | * change on their own. | ||
| 491 | * | ||
| 492 | * Register 0x06 bits b6 and b7 are control bits, and should | ||
| 493 | * not change on their own. | ||
| 494 | * | ||
| 495 | * Register 0x07 bits b3 to b0 are control bits, and should | ||
| 496 | * not change on their own. | ||
| 497 | */ | ||
| 498 | |||
| 499 | /* read register 0x02 reserved bit, expect 0 */ | ||
| 500 | v = i2c_smbus_read_byte_data(client, LTC4245_CONTROL); | ||
| 501 | if (v < 0 || (v & 0x04) != 0) | ||
| 502 | return -ENODEV; | ||
| 503 | |||
| 504 | /* read register 0x07 reserved bits, expect 0 */ | ||
| 505 | v = i2c_smbus_read_byte_data(client, LTC4245_ADCADR); | ||
| 506 | if (v < 0 || (v & 0xf0) != 0) | ||
| 507 | return -ENODEV; | ||
| 508 | |||
| 509 | /* check that the alert register appears at all locations */ | ||
| 510 | if (ltc4245_check_control_reg(client, LTC4245_ALERT, 0xff)) | ||
| 511 | return -ENODEV; | ||
| 512 | |||
| 513 | /* check that the control register appears at all locations */ | ||
| 514 | if (ltc4245_check_control_reg(client, LTC4245_CONTROL, 0xff)) | ||
| 515 | return -ENODEV; | ||
| 516 | |||
| 517 | /* check that register 0x06 bits b6 and b7 stay constant */ | ||
| 518 | if (ltc4245_check_control_reg(client, LTC4245_GPIO, 0xc0)) | ||
| 519 | return -ENODEV; | ||
| 520 | |||
| 521 | /* check that register 0x07 bits b3-b0 stay constant */ | ||
| 522 | if (ltc4245_check_control_reg(client, LTC4245_ADCADR, 0x0f)) | ||
| 523 | return -ENODEV; | ||
| 524 | } | ||
| 525 | |||
| 526 | strlcpy(info->type, "ltc4245", I2C_NAME_SIZE); | ||
| 527 | dev_info(&adapter->dev, "ltc4245 %s at address 0x%02x\n", | ||
| 528 | kind < 0 ? "probed" : "forced", | ||
| 529 | client->addr); | ||
| 530 | |||
| 531 | return 0; | ||
| 532 | } | ||
| 533 | |||
| 534 | static const struct i2c_device_id ltc4245_id[] = { | 416 | static const struct i2c_device_id ltc4245_id[] = { |
| 535 | { "ltc4245", ltc4245 }, | 417 | { "ltc4245", 0 }, |
| 536 | { } | 418 | { } |
| 537 | }; | 419 | }; |
| 538 | MODULE_DEVICE_TABLE(i2c, ltc4245_id); | 420 | MODULE_DEVICE_TABLE(i2c, ltc4245_id); |
| 539 | 421 | ||
| 540 | /* This is the driver that will be inserted */ | 422 | /* This is the driver that will be inserted */ |
| 541 | static struct i2c_driver ltc4245_driver = { | 423 | static struct i2c_driver ltc4245_driver = { |
| 542 | .class = I2C_CLASS_HWMON, | ||
| 543 | .driver = { | 424 | .driver = { |
| 544 | .name = "ltc4245", | 425 | .name = "ltc4245", |
| 545 | }, | 426 | }, |
| 546 | .probe = ltc4245_probe, | 427 | .probe = ltc4245_probe, |
| 547 | .remove = ltc4245_remove, | 428 | .remove = ltc4245_remove, |
| 548 | .id_table = ltc4245_id, | 429 | .id_table = ltc4245_id, |
| 549 | .detect = ltc4245_detect, | ||
| 550 | .address_data = &addr_data, | ||
| 551 | }; | 430 | }; |
| 552 | 431 | ||
| 553 | static int __init ltc4245_init(void) | 432 | static int __init ltc4245_init(void) |
