diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-10-17 11:51:12 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-10-17 11:51:12 -0400 |
commit | 810ad7b62c0f075dc44ecc781b24c7f6ba388da5 (patch) | |
tree | 3ed66cd5359928823ba18eba05f575fd8c28a75e | |
parent | 47064d645bc55863c7887a7c96cde39c9a37ee5f (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.c | 56 | ||||
-rw-r--r-- | drivers/hwmon/ams/ams.h | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-powermac.c | 29 |
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 | ||
63 | static int ams_i2c_attach(struct i2c_adapter *adapter); | 63 | static int ams_i2c_probe(struct i2c_client *client, |
64 | static int ams_i2c_detach(struct i2c_adapter *adapter); | 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 | static struct i2c_driver ams_i2c_driver = { | 73 | static 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 | ||
75 | static s32 ams_i2c_read(u8 reg) | 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 | static int ams_i2c_write(u8 reg, u8 value) | 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 | static int ams_i2c_cmd(enum ams_i2c_cmd cmd) | 93 | static 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 | ||
155 | static int ams_i2c_attach(struct i2c_adapter *adapter) | 163 | static 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 | ||
240 | static int ams_i2c_detach(struct i2c_adapter *adapter) | 238 | static 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 | ||
262 | int __init ams_i2c_init(struct device_node *np) | 260 | int __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 | ||
295 | exit: | ||
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 | ||