|
@@ -22,15 +22,6 @@
|
|
|
#include <linux/hwmon.h>
|
|
|
#include <linux/hwmon-sysfs.h>
|
|
|
|
|
|
-/* Valid addresses are 0x20 - 0x3f
|
|
|
- *
|
|
|
- * For now, we do not probe, since some of these addresses
|
|
|
- * are known to be unfriendly to probing */
|
|
|
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
|
|
-
|
|
|
-/* Insmod parameters */
|
|
|
-I2C_CLIENT_INSMOD_1(ltc4245);
|
|
|
-
|
|
|
/* Here are names of the chip's registers (a.k.a. commands) */
|
|
|
enum ltc4245_cmd {
|
|
|
LTC4245_STATUS = 0x00, /* readonly */
|
|
@@ -369,9 +360,13 @@ static const struct attribute_group ltc4245_group = {
|
|
|
static int ltc4245_probe(struct i2c_client *client,
|
|
|
const struct i2c_device_id *id)
|
|
|
{
|
|
|
+ struct i2c_adapter *adapter = client->adapter;
|
|
|
struct ltc4245_data *data;
|
|
|
int ret;
|
|
|
|
|
|
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
|
|
if (!data) {
|
|
|
ret = -ENOMEM;
|
|
@@ -418,136 +413,20 @@ static int ltc4245_remove(struct i2c_client *client)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* Check that some bits in a control register appear at all possible
|
|
|
- * locations without changing value
|
|
|
- *
|
|
|
- * @client: the i2c client to use
|
|
|
- * @reg: the register to read
|
|
|
- * @bits: the bits to check (0xff checks all bits,
|
|
|
- * 0x03 checks only the last two bits)
|
|
|
- *
|
|
|
- * return -ERRNO if the register read failed
|
|
|
- * return -ENODEV if the register value doesn't stay constant at all
|
|
|
- * possible addresses
|
|
|
- *
|
|
|
- * return 0 for success
|
|
|
- */
|
|
|
-static int ltc4245_check_control_reg(struct i2c_client *client, u8 reg, u8 bits)
|
|
|
-{
|
|
|
- int i;
|
|
|
- s32 v, voff1, voff2;
|
|
|
-
|
|
|
- /* Read register and check for error */
|
|
|
- v = i2c_smbus_read_byte_data(client, reg);
|
|
|
- if (v < 0)
|
|
|
- return v;
|
|
|
-
|
|
|
- v &= bits;
|
|
|
-
|
|
|
- for (i = 0x00; i < 0xff; i += 0x20) {
|
|
|
-
|
|
|
- voff1 = i2c_smbus_read_byte_data(client, reg + i);
|
|
|
- if (voff1 < 0)
|
|
|
- return voff1;
|
|
|
-
|
|
|
- voff2 = i2c_smbus_read_byte_data(client, reg + i + 0x08);
|
|
|
- if (voff2 < 0)
|
|
|
- return voff2;
|
|
|
-
|
|
|
- voff1 &= bits;
|
|
|
- voff2 &= bits;
|
|
|
-
|
|
|
- if (v != voff1 || v != voff2)
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int ltc4245_detect(struct i2c_client *client,
|
|
|
- int kind,
|
|
|
- struct i2c_board_info *info)
|
|
|
-{
|
|
|
- struct i2c_adapter *adapter = client->adapter;
|
|
|
-
|
|
|
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- if (kind < 0) { /* probed detection - check the chip type */
|
|
|
- s32 v; /* 8 bits from the chip, or -ERRNO */
|
|
|
-
|
|
|
- /* Chip registers 0x00-0x07 are control registers
|
|
|
- * Chip registers 0x10-0x1f are data registers
|
|
|
- *
|
|
|
- * Address bits b7-b5 are ignored. This makes the chip "repeat"
|
|
|
- * in steps of 0x20. Any control registers should appear with
|
|
|
- * the same values across all duplicated addresses.
|
|
|
- *
|
|
|
- * Register 0x02 bit b2 is reserved, expect 0
|
|
|
- * Register 0x07 bits b7 to b4 are reserved, expect 0
|
|
|
- *
|
|
|
- * Registers 0x01, 0x02 are control registers and should not
|
|
|
- * change on their own.
|
|
|
- *
|
|
|
- * Register 0x06 bits b6 and b7 are control bits, and should
|
|
|
- * not change on their own.
|
|
|
- *
|
|
|
- * Register 0x07 bits b3 to b0 are control bits, and should
|
|
|
- * not change on their own.
|
|
|
- */
|
|
|
-
|
|
|
- /* read register 0x02 reserved bit, expect 0 */
|
|
|
- v = i2c_smbus_read_byte_data(client, LTC4245_CONTROL);
|
|
|
- if (v < 0 || (v & 0x04) != 0)
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- /* read register 0x07 reserved bits, expect 0 */
|
|
|
- v = i2c_smbus_read_byte_data(client, LTC4245_ADCADR);
|
|
|
- if (v < 0 || (v & 0xf0) != 0)
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- /* check that the alert register appears at all locations */
|
|
|
- if (ltc4245_check_control_reg(client, LTC4245_ALERT, 0xff))
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- /* check that the control register appears at all locations */
|
|
|
- if (ltc4245_check_control_reg(client, LTC4245_CONTROL, 0xff))
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- /* check that register 0x06 bits b6 and b7 stay constant */
|
|
|
- if (ltc4245_check_control_reg(client, LTC4245_GPIO, 0xc0))
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- /* check that register 0x07 bits b3-b0 stay constant */
|
|
|
- if (ltc4245_check_control_reg(client, LTC4245_ADCADR, 0x0f))
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
-
|
|
|
- strlcpy(info->type, "ltc4245", I2C_NAME_SIZE);
|
|
|
- dev_info(&adapter->dev, "ltc4245 %s at address 0x%02x\n",
|
|
|
- kind < 0 ? "probed" : "forced",
|
|
|
- client->addr);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static const struct i2c_device_id ltc4245_id[] = {
|
|
|
- { "ltc4245", ltc4245 },
|
|
|
+ { "ltc4245", 0 },
|
|
|
{ }
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(i2c, ltc4245_id);
|
|
|
|
|
|
/* This is the driver that will be inserted */
|
|
|
static struct i2c_driver ltc4245_driver = {
|
|
|
- .class = I2C_CLASS_HWMON,
|
|
|
.driver = {
|
|
|
.name = "ltc4245",
|
|
|
},
|
|
|
.probe = ltc4245_probe,
|
|
|
.remove = ltc4245_remove,
|
|
|
.id_table = ltc4245_id,
|
|
|
- .detect = ltc4245_detect,
|
|
|
- .address_data = &addr_data,
|
|
|
};
|
|
|
|
|
|
static int __init ltc4245_init(void)
|