aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-10-17 11:51:12 -0400
committerJean Delvare <khali@mahadeva.delvare>2008-10-17 11:51:12 -0400
commit810ad7b62c0f075dc44ecc781b24c7f6ba388da5 (patch)
tree3ed66cd5359928823ba18eba05f575fd8c28a75e
parent47064d645bc55863c7887a7c96cde39c9a37ee5f (diff)
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>
-rw-r--r--drivers/hwmon/ams/ams-i2c.c56
-rw-r--r--drivers/hwmon/ams/ams.h4
-rw-r--r--drivers/i2c/busses/i2c-powermac.c29
3 files changed, 48 insertions, 41 deletions
diff --git a/drivers/hwmon/ams/ams-i2c.c b/drivers/hwmon/ams/ams-i2c.c
index 957760536a4c..da26de01068e 100644
--- a/drivers/hwmon/ams/ams-i2c.c
+++ b/drivers/hwmon/ams/ams-i2c.c
@@ -60,26 +60,34 @@ enum ams_i2c_cmd {
60 AMS_CMD_START, 60 AMS_CMD_START,
61}; 61};
62 62
63static int ams_i2c_attach(struct i2c_adapter *adapter); 63static int ams_i2c_probe(struct i2c_client *client,
64static int ams_i2c_detach(struct i2c_adapter *adapter); 64 const struct i2c_device_id *id);
65static int ams_i2c_remove(struct i2c_client *client);
66
67static const struct i2c_device_id ams_id[] = {
68 { "ams", 0 },
69 { }
70};
71MODULE_DEVICE_TABLE(i2c, ams_id);
65 72
66static struct i2c_driver ams_i2c_driver = { 73static struct i2c_driver ams_i2c_driver = {
67 .driver = { 74 .driver = {
68 .name = "ams", 75 .name = "ams",
69 .owner = THIS_MODULE, 76 .owner = THIS_MODULE,
70 }, 77 },
71 .attach_adapter = ams_i2c_attach, 78 .probe = ams_i2c_probe,
72 .detach_adapter = ams_i2c_detach, 79 .remove = ams_i2c_remove,
80 .id_table = ams_id,
73}; 81};
74 82
75static s32 ams_i2c_read(u8 reg) 83static 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
80static int ams_i2c_write(u8 reg, u8 value) 88static 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
85static int ams_i2c_cmd(enum ams_i2c_cmd cmd) 93static int ams_i2c_cmd(enum ams_i2c_cmd cmd)
@@ -152,9 +160,9 @@ static void ams_i2c_get_xyz(s8 *x, s8 *y, s8 *z)
152 *z = ams_i2c_read(AMS_DATAZ); 160 *z = ams_i2c_read(AMS_DATAZ);
153} 161}
154 162
155static int ams_i2c_attach(struct i2c_adapter *adapter) 163static int ams_i2c_probe(struct i2c_client *client,
164 const struct i2c_device_id *id)
156{ 165{
157 unsigned long bus;
158 int vmaj, vmin; 166 int vmaj, vmin;
159 int result; 167 int result;
160 168
@@ -162,17 +170,7 @@ static int ams_i2c_attach(struct i2c_adapter *adapter)
162 if (unlikely(ams_info.has_device)) 170 if (unlikely(ams_info.has_device))
163 return -ENODEV; 171 return -ENODEV;
164 172
165 if (strncmp(adapter->name, "uni-n", 5)) 173 ams_info.i2c_client = client;
166 return -ENODEV;
167
168 bus = simple_strtoul(adapter->name + 6, NULL, 10);
169 if (bus != ams_info.i2c_bus)
170 return -ENODEV;
171
172 ams_info.i2c_client.addr = ams_info.i2c_address;
173 ams_info.i2c_client.adapter = adapter;
174 ams_info.i2c_client.driver = &ams_i2c_driver;
175 strcpy(ams_info.i2c_client.name, "Apple Motion Sensor");
176 174
177 if (ams_i2c_cmd(AMS_CMD_RESET)) { 175 if (ams_i2c_cmd(AMS_CMD_RESET)) {
178 printk(KERN_INFO "ams: Failed to reset the device\n"); 176 printk(KERN_INFO "ams: Failed to reset the device\n");
@@ -237,7 +235,7 @@ static int ams_i2c_attach(struct i2c_adapter *adapter)
237 return 0; 235 return 0;
238} 236}
239 237
240static int ams_i2c_detach(struct i2c_adapter *adapter) 238static int ams_i2c_remove(struct i2c_client *client)
241{ 239{
242 if (ams_info.has_device) { 240 if (ams_info.has_device) {
243 /* Disable interrupts */ 241 /* Disable interrupts */
@@ -261,9 +259,7 @@ static void ams_i2c_exit(void)
261 259
262int __init ams_i2c_init(struct device_node *np) 260int __init ams_i2c_init(struct device_node *np)
263{ 261{
264 char *tmp_bus;
265 int result; 262 int result;
266 const u32 *prop;
267 263
268 mutex_lock(&ams_info.lock); 264 mutex_lock(&ams_info.lock);
269 265
@@ -275,24 +271,8 @@ int __init ams_i2c_init(struct device_node *np)
275 ams_info.clear_irq = ams_i2c_clear_irq; 271 ams_info.clear_irq = ams_i2c_clear_irq;
276 ams_info.bustype = BUS_I2C; 272 ams_info.bustype = BUS_I2C;
277 273
278 /* look for bus either using "reg" or by path */
279 prop = of_get_property(ams_info.of_node, "reg", NULL);
280 if (!prop) {
281 result = -ENODEV;
282
283 goto exit;
284 }
285
286 tmp_bus = strstr(ams_info.of_node->full_name, "/i2c-bus@");
287 if (tmp_bus)
288 ams_info.i2c_bus = *(tmp_bus + 9) - '0';
289 else
290 ams_info.i2c_bus = ((*prop) >> 8) & 0x0f;
291 ams_info.i2c_address = ((*prop) & 0xff) >> 1;
292
293 result = i2c_add_driver(&ams_i2c_driver); 274 result = i2c_add_driver(&ams_i2c_driver);
294 275
295exit:
296 mutex_unlock(&ams_info.lock); 276 mutex_unlock(&ams_info.lock);
297 277
298 return result; 278 return result;
diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h
index 221ef6915a5f..5ed387b0bd9a 100644
--- a/drivers/hwmon/ams/ams.h
+++ b/drivers/hwmon/ams/ams.h
@@ -46,9 +46,7 @@ struct ams {
46 46
47#ifdef CONFIG_SENSORS_AMS_I2C 47#ifdef CONFIG_SENSORS_AMS_I2C
48 /* I2C properties */ 48 /* I2C properties */
49 int i2c_bus; 49 struct i2c_client *i2c_client;
50 int i2c_address;
51 struct i2c_client i2c_client;
52#endif 50#endif
53 51
54 /* Joystick emulation */ 52 /* Joystick emulation */
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 0e7b1c6724aa..60ca91745e55 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -259,6 +259,35 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
259 } 259 }
260 260
261 printk(KERN_INFO "PowerMac i2c bus %s registered\n", name); 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 return rc; 291 return rc;
263} 292}
264 293