Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: (ams) Convert to a new-style i2c driver

The legacy i2c binding model is phasing out, so the ams driver needs
to be converted to a new-style i2c driver. Here is a naive approach of
this conversion. Basically it is moving the i2c device creation from
the ams driver to the i2c-powermac driver. This should work, but I
suspect we could come up with something cleaner by declaring the i2c
device as part of the platform setup. This could be done later by
someone more familiar with openfirmware-based platforms than I am
myself.

One nice thing brought by this conversion is that the ams driver
should be loaded automatically on systems where is is needed (at
least when the I2C interface to the chip is used) providing
coldplug-aware user-space environment.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Stelian Pop <stelian@popies.net>
Cc: Michael Hanselmann <linux-kernel@hansmi.ch>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Jean Delvare and committed by
Jean Delvare
810ad7b6 47064d64

+48 -41
+18 -38
drivers/hwmon/ams/ams-i2c.c
··· 60 60 AMS_CMD_START, 61 61 }; 62 62 63 - static int ams_i2c_attach(struct i2c_adapter *adapter); 64 - static int ams_i2c_detach(struct i2c_adapter *adapter); 63 + static int ams_i2c_probe(struct i2c_client *client, 64 + const struct i2c_device_id *id); 65 + static int ams_i2c_remove(struct i2c_client *client); 66 + 67 + static const struct i2c_device_id ams_id[] = { 68 + { "ams", 0 }, 69 + { } 70 + }; 71 + MODULE_DEVICE_TABLE(i2c, ams_id); 65 72 66 73 static struct i2c_driver ams_i2c_driver = { 67 74 .driver = { 68 75 .name = "ams", 69 76 .owner = THIS_MODULE, 70 77 }, 71 - .attach_adapter = ams_i2c_attach, 72 - .detach_adapter = ams_i2c_detach, 78 + .probe = ams_i2c_probe, 79 + .remove = ams_i2c_remove, 80 + .id_table = ams_id, 73 81 }; 74 82 75 83 static s32 ams_i2c_read(u8 reg) 76 84 { 77 - return i2c_smbus_read_byte_data(&ams_info.i2c_client, reg); 85 + return i2c_smbus_read_byte_data(ams_info.i2c_client, reg); 78 86 } 79 87 80 88 static int ams_i2c_write(u8 reg, u8 value) 81 89 { 82 - return i2c_smbus_write_byte_data(&ams_info.i2c_client, reg, value); 90 + return i2c_smbus_write_byte_data(ams_info.i2c_client, reg, value); 83 91 } 84 92 85 93 static int ams_i2c_cmd(enum ams_i2c_cmd cmd) ··· 160 152 *z = ams_i2c_read(AMS_DATAZ); 161 153 } 162 154 163 - static int ams_i2c_attach(struct i2c_adapter *adapter) 155 + static int ams_i2c_probe(struct i2c_client *client, 156 + const struct i2c_device_id *id) 164 157 { 165 - unsigned long bus; 166 158 int vmaj, vmin; 167 159 int result; 168 160 ··· 170 162 if (unlikely(ams_info.has_device)) 171 163 return -ENODEV; 172 164 173 - if (strncmp(adapter->name, "uni-n", 5)) 174 - return -ENODEV; 175 - 176 - bus = simple_strtoul(adapter->name + 6, NULL, 10); 177 - if (bus != ams_info.i2c_bus) 178 - return -ENODEV; 179 - 180 - ams_info.i2c_client.addr = ams_info.i2c_address; 181 - ams_info.i2c_client.adapter = adapter; 182 - ams_info.i2c_client.driver = &ams_i2c_driver; 183 - strcpy(ams_info.i2c_client.name, "Apple Motion Sensor"); 165 + ams_info.i2c_client = client; 184 166 185 167 if (ams_i2c_cmd(AMS_CMD_RESET)) { 186 168 printk(KERN_INFO "ams: Failed to reset the device\n"); ··· 235 237 return 0; 236 238 } 237 239 238 - static int ams_i2c_detach(struct i2c_adapter *adapter) 240 + static int ams_i2c_remove(struct i2c_client *client) 239 241 { 240 242 if (ams_info.has_device) { 241 243 /* Disable interrupts */ ··· 259 261 260 262 int __init ams_i2c_init(struct device_node *np) 261 263 { 262 - char *tmp_bus; 263 264 int result; 264 - const u32 *prop; 265 265 266 266 mutex_lock(&ams_info.lock); 267 267 ··· 271 275 ams_info.clear_irq = ams_i2c_clear_irq; 272 276 ams_info.bustype = BUS_I2C; 273 277 274 - /* look for bus either using "reg" or by path */ 275 - prop = of_get_property(ams_info.of_node, "reg", NULL); 276 - if (!prop) { 277 - result = -ENODEV; 278 - 279 - goto exit; 280 - } 281 - 282 - tmp_bus = strstr(ams_info.of_node->full_name, "/i2c-bus@"); 283 - if (tmp_bus) 284 - ams_info.i2c_bus = *(tmp_bus + 9) - '0'; 285 - else 286 - ams_info.i2c_bus = ((*prop) >> 8) & 0x0f; 287 - ams_info.i2c_address = ((*prop) & 0xff) >> 1; 288 - 289 278 result = i2c_add_driver(&ams_i2c_driver); 290 279 291 - exit: 292 280 mutex_unlock(&ams_info.lock); 293 281 294 282 return result;
+1 -3
drivers/hwmon/ams/ams.h
··· 46 46 47 47 #ifdef CONFIG_SENSORS_AMS_I2C 48 48 /* I2C properties */ 49 - int i2c_bus; 50 - int i2c_address; 51 - struct i2c_client i2c_client; 49 + struct i2c_client *i2c_client; 52 50 #endif 53 51 54 52 /* Joystick emulation */
+29
drivers/i2c/busses/i2c-powermac.c
··· 259 259 } 260 260 261 261 printk(KERN_INFO "PowerMac i2c bus %s registered\n", name); 262 + 263 + if (!strncmp(basename, "uni-n", 5)) { 264 + struct device_node *np; 265 + const u32 *prop; 266 + struct i2c_board_info info; 267 + 268 + /* Instantiate I2C motion sensor if present */ 269 + np = of_find_node_by_name(NULL, "accelerometer"); 270 + if (np && of_device_is_compatible(np, "AAPL,accelerometer_1") && 271 + (prop = of_get_property(np, "reg", NULL))) { 272 + int i2c_bus; 273 + const char *tmp_bus; 274 + 275 + /* look for bus either using "reg" or by path */ 276 + tmp_bus = strstr(np->full_name, "/i2c-bus@"); 277 + if (tmp_bus) 278 + i2c_bus = *(tmp_bus + 9) - '0'; 279 + else 280 + i2c_bus = ((*prop) >> 8) & 0x0f; 281 + 282 + if (pmac_i2c_get_channel(bus) == i2c_bus) { 283 + memset(&info, 0, sizeof(struct i2c_board_info)); 284 + info.addr = ((*prop) & 0xff) >> 1; 285 + strlcpy(info.type, "ams", I2C_NAME_SIZE); 286 + i2c_new_device(adapter, &info); 287 + } 288 + } 289 + } 290 + 262 291 return rc; 263 292 } 264 293