diff options
author | Jean Delvare <khali@linux-fr.org> | 2007-05-01 17:26:31 -0400 |
---|---|---|
committer | Jean Delvare <khali@hyperion.delvare> | 2007-05-01 17:26:31 -0400 |
commit | 12b5053ac58709c7d475888bc18d1f61958afc4e (patch) | |
tree | 13a6afc6ad6d3f22568045ba71277c1331fd4283 | |
parent | 0f3b48385213355a2d4408bec1b481ffcf0e8638 (diff) |
i2c: Add i2c_new_probed_device()
Add a new helper function to instantiate an i2c device. It is meant as a
replacement for i2c_new_device() when you don't know for sure at which
address your I2C/SMBus device lives. This happens frequently on TV
adapters for example, you know there is a tuner chip on the bus, but
depending on the exact board model and revision, it can live at different
addresses. So, the new i2c_new_probed_device() function will probe the bus
according to a list of addresses, and as soon as one of these addresses
responds, it will call i2c_new_device() on that one address.
This function will make it possible to port the old i2c drivers to the
new model quickly.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r-- | drivers/i2c/i2c-core.c | 63 | ||||
-rw-r--r-- | include/linux/i2c.h | 9 |
2 files changed, 72 insertions, 0 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 18124398b464..0fd4acbffb78 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -1092,6 +1092,69 @@ int i2c_probe(struct i2c_adapter *adapter, | |||
1092 | } | 1092 | } |
1093 | EXPORT_SYMBOL(i2c_probe); | 1093 | EXPORT_SYMBOL(i2c_probe); |
1094 | 1094 | ||
1095 | struct i2c_client * | ||
1096 | i2c_new_probed_device(struct i2c_adapter *adap, | ||
1097 | struct i2c_board_info *info, | ||
1098 | unsigned short const *addr_list) | ||
1099 | { | ||
1100 | int i; | ||
1101 | |||
1102 | /* Stop here if the bus doesn't support probing */ | ||
1103 | if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) { | ||
1104 | dev_err(&adap->dev, "Probing not supported\n"); | ||
1105 | return NULL; | ||
1106 | } | ||
1107 | |||
1108 | mutex_lock(&adap->clist_lock); | ||
1109 | for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { | ||
1110 | /* Check address validity */ | ||
1111 | if (addr_list[i] < 0x03 || addr_list[i] > 0x77) { | ||
1112 | dev_warn(&adap->dev, "Invalid 7-bit address " | ||
1113 | "0x%02x\n", addr_list[i]); | ||
1114 | continue; | ||
1115 | } | ||
1116 | |||
1117 | /* Check address availability */ | ||
1118 | if (__i2c_check_addr(adap, addr_list[i])) { | ||
1119 | dev_dbg(&adap->dev, "Address 0x%02x already in " | ||
1120 | "use, not probing\n", addr_list[i]); | ||
1121 | continue; | ||
1122 | } | ||
1123 | |||
1124 | /* Test address responsiveness | ||
1125 | The default probe method is a quick write, but it is known | ||
1126 | to corrupt the 24RF08 EEPROMs due to a state machine bug, | ||
1127 | and could also irreversibly write-protect some EEPROMs, so | ||
1128 | for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte | ||
1129 | read instead. Also, some bus drivers don't implement | ||
1130 | quick write, so we fallback to a byte read it that case | ||
1131 | too. */ | ||
1132 | if ((addr_list[i] & ~0x07) == 0x30 | ||
1133 | || (addr_list[i] & ~0x0f) == 0x50 | ||
1134 | || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) { | ||
1135 | if (i2c_smbus_xfer(adap, addr_list[i], 0, | ||
1136 | I2C_SMBUS_READ, 0, | ||
1137 | I2C_SMBUS_BYTE, NULL) >= 0) | ||
1138 | break; | ||
1139 | } else { | ||
1140 | if (i2c_smbus_xfer(adap, addr_list[i], 0, | ||
1141 | I2C_SMBUS_WRITE, 0, | ||
1142 | I2C_SMBUS_QUICK, NULL) >= 0) | ||
1143 | break; | ||
1144 | } | ||
1145 | } | ||
1146 | mutex_unlock(&adap->clist_lock); | ||
1147 | |||
1148 | if (addr_list[i] == I2C_CLIENT_END) { | ||
1149 | dev_dbg(&adap->dev, "Probing failed, no device found\n"); | ||
1150 | return NULL; | ||
1151 | } | ||
1152 | |||
1153 | info->addr = addr_list[i]; | ||
1154 | return i2c_new_device(adap, info); | ||
1155 | } | ||
1156 | EXPORT_SYMBOL_GPL(i2c_new_probed_device); | ||
1157 | |||
1095 | struct i2c_adapter* i2c_get_adapter(int id) | 1158 | struct i2c_adapter* i2c_get_adapter(int id) |
1096 | { | 1159 | { |
1097 | struct i2c_adapter *adapter; | 1160 | struct i2c_adapter *adapter; |
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 36d6814a6df4..da95ce79d075 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
@@ -245,6 +245,15 @@ struct i2c_board_info { | |||
245 | extern struct i2c_client * | 245 | extern struct i2c_client * |
246 | i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); | 246 | i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); |
247 | 247 | ||
248 | /* If you don't know the exact address of an I2C device, use this variant | ||
249 | * instead, which can probe for device presence in a list of possible | ||
250 | * addresses. | ||
251 | */ | ||
252 | extern struct i2c_client * | ||
253 | i2c_new_probed_device(struct i2c_adapter *adap, | ||
254 | struct i2c_board_info *info, | ||
255 | unsigned short const *addr_list); | ||
256 | |||
248 | extern void i2c_unregister_device(struct i2c_client *); | 257 | extern void i2c_unregister_device(struct i2c_client *); |
249 | 258 | ||
250 | /* Mainboard arch_initcall() code should register all its I2C devices. | 259 | /* Mainboard arch_initcall() code should register all its I2C devices. |