diff options
author | Jean Delvare <khali@linux-fr.org> | 2009-06-15 12:01:51 -0400 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-06-15 12:01:51 -0400 |
commit | 351ca3e31197929535418f5affc761cd9fb07428 (patch) | |
tree | e8602108fa3402081f2fd4210dee62c141ed7fab /drivers/macintosh | |
parent | 1b9f37d488f09342610b29ac1c8e734e540932ab (diff) |
windfarm: Convert to new-style i2c drivers
The legacy i2c binding model is going away soon, so convert the
macintosh windfarm drivers to the new model or they will break.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Tested-by: Johannes Berg <johannes@sipsolutions.net>
Tested-by: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/macintosh')
-rw-r--r-- | drivers/macintosh/windfarm_lm75_sensor.c | 129 | ||||
-rw-r--r-- | drivers/macintosh/windfarm_max6690_sensor.c | 103 | ||||
-rw-r--r-- | drivers/macintosh/windfarm_smu_sat.c | 109 |
3 files changed, 197 insertions, 144 deletions
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index b92b959fe16e..529886c7a826 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c | |||
@@ -37,34 +37,22 @@ | |||
37 | struct wf_lm75_sensor { | 37 | struct wf_lm75_sensor { |
38 | int ds1775 : 1; | 38 | int ds1775 : 1; |
39 | int inited : 1; | 39 | int inited : 1; |
40 | struct i2c_client i2c; | 40 | struct i2c_client *i2c; |
41 | struct wf_sensor sens; | 41 | struct wf_sensor sens; |
42 | }; | 42 | }; |
43 | #define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens) | 43 | #define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens) |
44 | #define i2c_to_lm75(c) container_of(c, struct wf_lm75_sensor, i2c) | ||
45 | |||
46 | static int wf_lm75_attach(struct i2c_adapter *adapter); | ||
47 | static int wf_lm75_detach(struct i2c_client *client); | ||
48 | |||
49 | static struct i2c_driver wf_lm75_driver = { | ||
50 | .driver = { | ||
51 | .name = "wf_lm75", | ||
52 | }, | ||
53 | .attach_adapter = wf_lm75_attach, | ||
54 | .detach_client = wf_lm75_detach, | ||
55 | }; | ||
56 | 44 | ||
57 | static int wf_lm75_get(struct wf_sensor *sr, s32 *value) | 45 | static int wf_lm75_get(struct wf_sensor *sr, s32 *value) |
58 | { | 46 | { |
59 | struct wf_lm75_sensor *lm = wf_to_lm75(sr); | 47 | struct wf_lm75_sensor *lm = wf_to_lm75(sr); |
60 | s32 data; | 48 | s32 data; |
61 | 49 | ||
62 | if (lm->i2c.adapter == NULL) | 50 | if (lm->i2c == NULL) |
63 | return -ENODEV; | 51 | return -ENODEV; |
64 | 52 | ||
65 | /* Init chip if necessary */ | 53 | /* Init chip if necessary */ |
66 | if (!lm->inited) { | 54 | if (!lm->inited) { |
67 | u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(&lm->i2c, 1); | 55 | u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(lm->i2c, 1); |
68 | 56 | ||
69 | DBG("wf_lm75: Initializing %s, cfg was: %02x\n", | 57 | DBG("wf_lm75: Initializing %s, cfg was: %02x\n", |
70 | sr->name, cfg); | 58 | sr->name, cfg); |
@@ -73,7 +61,7 @@ static int wf_lm75_get(struct wf_sensor *sr, s32 *value) | |||
73 | * the firmware for now | 61 | * the firmware for now |
74 | */ | 62 | */ |
75 | cfg_new = cfg & ~0x01; | 63 | cfg_new = cfg & ~0x01; |
76 | i2c_smbus_write_byte_data(&lm->i2c, 1, cfg_new); | 64 | i2c_smbus_write_byte_data(lm->i2c, 1, cfg_new); |
77 | lm->inited = 1; | 65 | lm->inited = 1; |
78 | 66 | ||
79 | /* If we just powered it up, let's wait 200 ms */ | 67 | /* If we just powered it up, let's wait 200 ms */ |
@@ -81,7 +69,7 @@ static int wf_lm75_get(struct wf_sensor *sr, s32 *value) | |||
81 | } | 69 | } |
82 | 70 | ||
83 | /* Read temperature register */ | 71 | /* Read temperature register */ |
84 | data = (s32)le16_to_cpu(i2c_smbus_read_word_data(&lm->i2c, 0)); | 72 | data = (s32)le16_to_cpu(i2c_smbus_read_word_data(lm->i2c, 0)); |
85 | data <<= 8; | 73 | data <<= 8; |
86 | *value = data; | 74 | *value = data; |
87 | 75 | ||
@@ -92,12 +80,6 @@ static void wf_lm75_release(struct wf_sensor *sr) | |||
92 | { | 80 | { |
93 | struct wf_lm75_sensor *lm = wf_to_lm75(sr); | 81 | struct wf_lm75_sensor *lm = wf_to_lm75(sr); |
94 | 82 | ||
95 | /* check if client is registered and detach from i2c */ | ||
96 | if (lm->i2c.adapter) { | ||
97 | i2c_detach_client(&lm->i2c); | ||
98 | lm->i2c.adapter = NULL; | ||
99 | } | ||
100 | |||
101 | kfree(lm); | 83 | kfree(lm); |
102 | } | 84 | } |
103 | 85 | ||
@@ -107,59 +89,77 @@ static struct wf_sensor_ops wf_lm75_ops = { | |||
107 | .owner = THIS_MODULE, | 89 | .owner = THIS_MODULE, |
108 | }; | 90 | }; |
109 | 91 | ||
110 | static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter, | 92 | static int wf_lm75_probe(struct i2c_client *client, |
111 | u8 addr, int ds1775, | 93 | const struct i2c_device_id *id) |
112 | const char *loc) | ||
113 | { | 94 | { |
114 | struct wf_lm75_sensor *lm; | 95 | struct wf_lm75_sensor *lm; |
115 | int rc; | 96 | int rc; |
116 | 97 | ||
117 | DBG("wf_lm75: creating %s device at address 0x%02x\n", | ||
118 | ds1775 ? "ds1775" : "lm75", addr); | ||
119 | |||
120 | lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL); | 98 | lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL); |
121 | if (lm == NULL) | 99 | if (lm == NULL) |
122 | return NULL; | 100 | return -ENODEV; |
101 | |||
102 | lm->inited = 0; | ||
103 | lm->ds1775 = id->driver_data; | ||
104 | lm->i2c = client; | ||
105 | lm->sens.name = client->dev.platform_data; | ||
106 | lm->sens.ops = &wf_lm75_ops; | ||
107 | i2c_set_clientdata(client, lm); | ||
108 | |||
109 | rc = wf_register_sensor(&lm->sens); | ||
110 | if (rc) { | ||
111 | i2c_set_clientdata(client, NULL); | ||
112 | kfree(lm); | ||
113 | } | ||
114 | |||
115 | return rc; | ||
116 | } | ||
117 | |||
118 | static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter, | ||
119 | u8 addr, int ds1775, | ||
120 | const char *loc) | ||
121 | { | ||
122 | struct i2c_board_info info; | ||
123 | struct i2c_client *client; | ||
124 | char *name; | ||
125 | |||
126 | DBG("wf_lm75: creating %s device at address 0x%02x\n", | ||
127 | ds1775 ? "ds1775" : "lm75", addr); | ||
123 | 128 | ||
124 | /* Usual rant about sensor names not beeing very consistent in | 129 | /* Usual rant about sensor names not beeing very consistent in |
125 | * the device-tree, oh well ... | 130 | * the device-tree, oh well ... |
126 | * Add more entries below as you deal with more setups | 131 | * Add more entries below as you deal with more setups |
127 | */ | 132 | */ |
128 | if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY")) | 133 | if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY")) |
129 | lm->sens.name = "hd-temp"; | 134 | name = "hd-temp"; |
130 | else if (!strcmp(loc, "Incoming Air Temp")) | 135 | else if (!strcmp(loc, "Incoming Air Temp")) |
131 | lm->sens.name = "incoming-air-temp"; | 136 | name = "incoming-air-temp"; |
132 | else if (!strcmp(loc, "ODD Temp")) | 137 | else if (!strcmp(loc, "ODD Temp")) |
133 | lm->sens.name = "optical-drive-temp"; | 138 | name = "optical-drive-temp"; |
134 | else if (!strcmp(loc, "HD Temp")) | 139 | else if (!strcmp(loc, "HD Temp")) |
135 | lm->sens.name = "hard-drive-temp"; | 140 | name = "hard-drive-temp"; |
136 | else | 141 | else |
137 | goto fail; | 142 | goto fail; |
138 | 143 | ||
139 | lm->inited = 0; | 144 | memset(&info, 0, sizeof(struct i2c_board_info)); |
140 | lm->sens.ops = &wf_lm75_ops; | 145 | info.addr = (addr >> 1) & 0x7f; |
141 | lm->ds1775 = ds1775; | 146 | info.platform_data = name; |
142 | lm->i2c.addr = (addr >> 1) & 0x7f; | 147 | strlcpy(info.type, ds1775 ? "wf_ds1775" : "wf_lm75", I2C_NAME_SIZE); |
143 | lm->i2c.adapter = adapter; | ||
144 | lm->i2c.driver = &wf_lm75_driver; | ||
145 | strncpy(lm->i2c.name, lm->sens.name, I2C_NAME_SIZE-1); | ||
146 | |||
147 | rc = i2c_attach_client(&lm->i2c); | ||
148 | if (rc) { | ||
149 | printk(KERN_ERR "windfarm: failed to attach %s %s to i2c," | ||
150 | " err %d\n", ds1775 ? "ds1775" : "lm75", | ||
151 | lm->i2c.name, rc); | ||
152 | goto fail; | ||
153 | } | ||
154 | 148 | ||
155 | if (wf_register_sensor(&lm->sens)) { | 149 | client = i2c_new_device(adapter, &info); |
156 | i2c_detach_client(&lm->i2c); | 150 | if (client == NULL) { |
151 | printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n", | ||
152 | ds1775 ? "ds1775" : "lm75", name); | ||
157 | goto fail; | 153 | goto fail; |
158 | } | 154 | } |
159 | 155 | ||
160 | return lm; | 156 | /* |
157 | * Let i2c-core delete that device on driver removal. | ||
158 | * This is safe because i2c-core holds the core_lock mutex for us. | ||
159 | */ | ||
160 | list_add_tail(&client->detected, &client->driver->clients); | ||
161 | return client; | ||
161 | fail: | 162 | fail: |
162 | kfree(lm); | ||
163 | return NULL; | 163 | return NULL; |
164 | } | 164 | } |
165 | 165 | ||
@@ -202,21 +202,38 @@ static int wf_lm75_attach(struct i2c_adapter *adapter) | |||
202 | return 0; | 202 | return 0; |
203 | } | 203 | } |
204 | 204 | ||
205 | static int wf_lm75_detach(struct i2c_client *client) | 205 | static int wf_lm75_remove(struct i2c_client *client) |
206 | { | 206 | { |
207 | struct wf_lm75_sensor *lm = i2c_to_lm75(client); | 207 | struct wf_lm75_sensor *lm = i2c_get_clientdata(client); |
208 | 208 | ||
209 | DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name); | 209 | DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name); |
210 | 210 | ||
211 | /* Mark client detached */ | 211 | /* Mark client detached */ |
212 | lm->i2c.adapter = NULL; | 212 | lm->i2c = NULL; |
213 | 213 | ||
214 | /* release sensor */ | 214 | /* release sensor */ |
215 | wf_unregister_sensor(&lm->sens); | 215 | wf_unregister_sensor(&lm->sens); |
216 | 216 | ||
217 | i2c_set_clientdata(client, NULL); | ||
217 | return 0; | 218 | return 0; |
218 | } | 219 | } |
219 | 220 | ||
221 | static const struct i2c_device_id wf_lm75_id[] = { | ||
222 | { "wf_lm75", 0 }, | ||
223 | { "wf_ds1775", 1 }, | ||
224 | { } | ||
225 | }; | ||
226 | |||
227 | static struct i2c_driver wf_lm75_driver = { | ||
228 | .driver = { | ||
229 | .name = "wf_lm75", | ||
230 | }, | ||
231 | .attach_adapter = wf_lm75_attach, | ||
232 | .probe = wf_lm75_probe, | ||
233 | .remove = wf_lm75_remove, | ||
234 | .id_table = wf_lm75_id, | ||
235 | }; | ||
236 | |||
220 | static int __init wf_lm75_sensor_init(void) | 237 | static int __init wf_lm75_sensor_init(void) |
221 | { | 238 | { |
222 | /* Don't register on old machines that use therm_pm72 for now */ | 239 | /* Don't register on old machines that use therm_pm72 for now */ |
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index e207a90d6b27..e2a55ecda2b2 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c | |||
@@ -26,34 +26,22 @@ | |||
26 | #define MAX6690_EXTERNAL_TEMP 1 | 26 | #define MAX6690_EXTERNAL_TEMP 1 |
27 | 27 | ||
28 | struct wf_6690_sensor { | 28 | struct wf_6690_sensor { |
29 | struct i2c_client i2c; | 29 | struct i2c_client *i2c; |
30 | struct wf_sensor sens; | 30 | struct wf_sensor sens; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | #define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens) | 33 | #define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens) |
34 | #define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c) | ||
35 | |||
36 | static int wf_max6690_attach(struct i2c_adapter *adapter); | ||
37 | static int wf_max6690_detach(struct i2c_client *client); | ||
38 | |||
39 | static struct i2c_driver wf_max6690_driver = { | ||
40 | .driver = { | ||
41 | .name = "wf_max6690", | ||
42 | }, | ||
43 | .attach_adapter = wf_max6690_attach, | ||
44 | .detach_client = wf_max6690_detach, | ||
45 | }; | ||
46 | 34 | ||
47 | static int wf_max6690_get(struct wf_sensor *sr, s32 *value) | 35 | static int wf_max6690_get(struct wf_sensor *sr, s32 *value) |
48 | { | 36 | { |
49 | struct wf_6690_sensor *max = wf_to_6690(sr); | 37 | struct wf_6690_sensor *max = wf_to_6690(sr); |
50 | s32 data; | 38 | s32 data; |
51 | 39 | ||
52 | if (max->i2c.adapter == NULL) | 40 | if (max->i2c == NULL) |
53 | return -ENODEV; | 41 | return -ENODEV; |
54 | 42 | ||
55 | /* chip gets initialized by firmware */ | 43 | /* chip gets initialized by firmware */ |
56 | data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP); | 44 | data = i2c_smbus_read_byte_data(max->i2c, MAX6690_EXTERNAL_TEMP); |
57 | if (data < 0) | 45 | if (data < 0) |
58 | return data; | 46 | return data; |
59 | *value = data << 16; | 47 | *value = data << 16; |
@@ -64,10 +52,6 @@ static void wf_max6690_release(struct wf_sensor *sr) | |||
64 | { | 52 | { |
65 | struct wf_6690_sensor *max = wf_to_6690(sr); | 53 | struct wf_6690_sensor *max = wf_to_6690(sr); |
66 | 54 | ||
67 | if (max->i2c.adapter) { | ||
68 | i2c_detach_client(&max->i2c); | ||
69 | max->i2c.adapter = NULL; | ||
70 | } | ||
71 | kfree(max); | 55 | kfree(max); |
72 | } | 56 | } |
73 | 57 | ||
@@ -77,19 +61,40 @@ static struct wf_sensor_ops wf_max6690_ops = { | |||
77 | .owner = THIS_MODULE, | 61 | .owner = THIS_MODULE, |
78 | }; | 62 | }; |
79 | 63 | ||
80 | static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr, | 64 | static int wf_max6690_probe(struct i2c_client *client, |
81 | const char *loc) | 65 | const struct i2c_device_id *id) |
82 | { | 66 | { |
83 | struct wf_6690_sensor *max; | 67 | struct wf_6690_sensor *max; |
84 | char *name; | 68 | int rc; |
85 | 69 | ||
86 | max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); | 70 | max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); |
87 | if (max == NULL) { | 71 | if (max == NULL) { |
88 | printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: " | 72 | printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: " |
89 | "no memory\n", loc); | 73 | "no memory\n"); |
90 | return; | 74 | return -ENOMEM; |
75 | } | ||
76 | |||
77 | max->i2c = client; | ||
78 | max->sens.name = client->dev.platform_data; | ||
79 | max->sens.ops = &wf_max6690_ops; | ||
80 | i2c_set_clientdata(client, max); | ||
81 | |||
82 | rc = wf_register_sensor(&max->sens); | ||
83 | if (rc) { | ||
84 | i2c_set_clientdata(client, NULL); | ||
85 | kfree(max); | ||
91 | } | 86 | } |
92 | 87 | ||
88 | return rc; | ||
89 | } | ||
90 | |||
91 | static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter, | ||
92 | u8 addr, const char *loc) | ||
93 | { | ||
94 | struct i2c_board_info info; | ||
95 | struct i2c_client *client; | ||
96 | char *name; | ||
97 | |||
93 | if (!strcmp(loc, "BACKSIDE")) | 98 | if (!strcmp(loc, "BACKSIDE")) |
94 | name = "backside-temp"; | 99 | name = "backside-temp"; |
95 | else if (!strcmp(loc, "NB Ambient")) | 100 | else if (!strcmp(loc, "NB Ambient")) |
@@ -99,27 +104,26 @@ static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr, | |||
99 | else | 104 | else |
100 | goto fail; | 105 | goto fail; |
101 | 106 | ||
102 | max->sens.ops = &wf_max6690_ops; | 107 | memset(&info, 0, sizeof(struct i2c_board_info)); |
103 | max->sens.name = name; | 108 | info.addr = addr >> 1; |
104 | max->i2c.addr = addr >> 1; | 109 | info.platform_data = name; |
105 | max->i2c.adapter = adapter; | 110 | strlcpy(info.type, "wf_max6690", I2C_NAME_SIZE); |
106 | max->i2c.driver = &wf_max6690_driver; | ||
107 | strncpy(max->i2c.name, name, I2C_NAME_SIZE-1); | ||
108 | 111 | ||
109 | if (i2c_attach_client(&max->i2c)) { | 112 | client = i2c_new_device(adapter, &info); |
113 | if (client == NULL) { | ||
110 | printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n"); | 114 | printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n"); |
111 | goto fail; | 115 | goto fail; |
112 | } | 116 | } |
113 | 117 | ||
114 | if (wf_register_sensor(&max->sens)) { | 118 | /* |
115 | i2c_detach_client(&max->i2c); | 119 | * Let i2c-core delete that device on driver removal. |
116 | goto fail; | 120 | * This is safe because i2c-core holds the core_lock mutex for us. |
117 | } | 121 | */ |
118 | 122 | list_add_tail(&client->detected, &client->driver->clients); | |
119 | return; | 123 | return client; |
120 | 124 | ||
121 | fail: | 125 | fail: |
122 | kfree(max); | 126 | return NULL; |
123 | } | 127 | } |
124 | 128 | ||
125 | static int wf_max6690_attach(struct i2c_adapter *adapter) | 129 | static int wf_max6690_attach(struct i2c_adapter *adapter) |
@@ -154,16 +158,31 @@ static int wf_max6690_attach(struct i2c_adapter *adapter) | |||
154 | return 0; | 158 | return 0; |
155 | } | 159 | } |
156 | 160 | ||
157 | static int wf_max6690_detach(struct i2c_client *client) | 161 | static int wf_max6690_remove(struct i2c_client *client) |
158 | { | 162 | { |
159 | struct wf_6690_sensor *max = i2c_to_6690(client); | 163 | struct wf_6690_sensor *max = i2c_get_clientdata(client); |
160 | 164 | ||
161 | max->i2c.adapter = NULL; | 165 | max->i2c = NULL; |
162 | wf_unregister_sensor(&max->sens); | 166 | wf_unregister_sensor(&max->sens); |
163 | 167 | ||
164 | return 0; | 168 | return 0; |
165 | } | 169 | } |
166 | 170 | ||
171 | static const struct i2c_device_id wf_max6690_id[] = { | ||
172 | { "wf_max6690", 0 }, | ||
173 | { } | ||
174 | }; | ||
175 | |||
176 | static struct i2c_driver wf_max6690_driver = { | ||
177 | .driver = { | ||
178 | .name = "wf_max6690", | ||
179 | }, | ||
180 | .attach_adapter = wf_max6690_attach, | ||
181 | .probe = wf_max6690_probe, | ||
182 | .remove = wf_max6690_remove, | ||
183 | .id_table = wf_max6690_id, | ||
184 | }; | ||
185 | |||
167 | static int __init wf_max6690_sensor_init(void) | 186 | static int __init wf_max6690_sensor_init(void) |
168 | { | 187 | { |
169 | /* Don't register on old machines that use therm_pm72 for now */ | 188 | /* Don't register on old machines that use therm_pm72 for now */ |
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index 7847e981ac33..5da729e58f99 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c | |||
@@ -39,7 +39,7 @@ struct wf_sat { | |||
39 | struct mutex mutex; | 39 | struct mutex mutex; |
40 | unsigned long last_read; /* jiffies when cache last updated */ | 40 | unsigned long last_read; /* jiffies when cache last updated */ |
41 | u8 cache[16]; | 41 | u8 cache[16]; |
42 | struct i2c_client i2c; | 42 | struct i2c_client *i2c; |
43 | struct device_node *node; | 43 | struct device_node *node; |
44 | }; | 44 | }; |
45 | 45 | ||
@@ -54,18 +54,6 @@ struct wf_sat_sensor { | |||
54 | }; | 54 | }; |
55 | 55 | ||
56 | #define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) | 56 | #define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) |
57 | #define i2c_to_sat(c) container_of(c, struct wf_sat, i2c) | ||
58 | |||
59 | static int wf_sat_attach(struct i2c_adapter *adapter); | ||
60 | static int wf_sat_detach(struct i2c_client *client); | ||
61 | |||
62 | static struct i2c_driver wf_sat_driver = { | ||
63 | .driver = { | ||
64 | .name = "wf_smu_sat", | ||
65 | }, | ||
66 | .attach_adapter = wf_sat_attach, | ||
67 | .detach_client = wf_sat_detach, | ||
68 | }; | ||
69 | 57 | ||
70 | struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | 58 | struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, |
71 | unsigned int *size) | 59 | unsigned int *size) |
@@ -81,13 +69,13 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | |||
81 | if (sat_id > 1 || (sat = sats[sat_id]) == NULL) | 69 | if (sat_id > 1 || (sat = sats[sat_id]) == NULL) |
82 | return NULL; | 70 | return NULL; |
83 | 71 | ||
84 | err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8); | 72 | err = i2c_smbus_write_word_data(sat->i2c, 8, id << 8); |
85 | if (err) { | 73 | if (err) { |
86 | printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); | 74 | printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); |
87 | return NULL; | 75 | return NULL; |
88 | } | 76 | } |
89 | 77 | ||
90 | err = i2c_smbus_read_word_data(&sat->i2c, 9); | 78 | err = i2c_smbus_read_word_data(sat->i2c, 9); |
91 | if (err < 0) { | 79 | if (err < 0) { |
92 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); | 80 | printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); |
93 | return NULL; | 81 | return NULL; |
@@ -105,7 +93,7 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | |||
105 | return NULL; | 93 | return NULL; |
106 | 94 | ||
107 | for (i = 0; i < len; i += 4) { | 95 | for (i = 0; i < len; i += 4) { |
108 | err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data); | 96 | err = i2c_smbus_read_i2c_block_data(sat->i2c, 0xa, 4, data); |
109 | if (err < 0) { | 97 | if (err < 0) { |
110 | printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", | 98 | printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", |
111 | err); | 99 | err); |
@@ -138,7 +126,7 @@ static int wf_sat_read_cache(struct wf_sat *sat) | |||
138 | { | 126 | { |
139 | int err; | 127 | int err; |
140 | 128 | ||
141 | err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache); | 129 | err = i2c_smbus_read_i2c_block_data(sat->i2c, 0x3f, 16, sat->cache); |
142 | if (err < 0) | 130 | if (err < 0) |
143 | return err; | 131 | return err; |
144 | sat->last_read = jiffies; | 132 | sat->last_read = jiffies; |
@@ -161,7 +149,7 @@ static int wf_sat_get(struct wf_sensor *sr, s32 *value) | |||
161 | int i, err; | 149 | int i, err; |
162 | s32 val; | 150 | s32 val; |
163 | 151 | ||
164 | if (sat->i2c.adapter == NULL) | 152 | if (sat->i2c == NULL) |
165 | return -ENODEV; | 153 | return -ENODEV; |
166 | 154 | ||
167 | mutex_lock(&sat->mutex); | 155 | mutex_lock(&sat->mutex); |
@@ -193,10 +181,6 @@ static void wf_sat_release(struct wf_sensor *sr) | |||
193 | struct wf_sat *sat = sens->sat; | 181 | struct wf_sat *sat = sens->sat; |
194 | 182 | ||
195 | if (atomic_dec_and_test(&sat->refcnt)) { | 183 | if (atomic_dec_and_test(&sat->refcnt)) { |
196 | if (sat->i2c.adapter) { | ||
197 | i2c_detach_client(&sat->i2c); | ||
198 | sat->i2c.adapter = NULL; | ||
199 | } | ||
200 | if (sat->nr >= 0) | 184 | if (sat->nr >= 0) |
201 | sats[sat->nr] = NULL; | 185 | sats[sat->nr] = NULL; |
202 | kfree(sat); | 186 | kfree(sat); |
@@ -212,38 +196,58 @@ static struct wf_sensor_ops wf_sat_ops = { | |||
212 | 196 | ||
213 | static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) | 197 | static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) |
214 | { | 198 | { |
199 | struct i2c_board_info info; | ||
200 | struct i2c_client *client; | ||
201 | const u32 *reg; | ||
202 | u8 addr; | ||
203 | |||
204 | reg = of_get_property(dev, "reg", NULL); | ||
205 | if (reg == NULL) | ||
206 | return; | ||
207 | addr = *reg; | ||
208 | DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); | ||
209 | |||
210 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
211 | info.addr = (addr >> 1) & 0x7f; | ||
212 | info.platform_data = dev; | ||
213 | strlcpy(info.type, "wf_sat", I2C_NAME_SIZE); | ||
214 | |||
215 | client = i2c_new_device(adapter, &info); | ||
216 | if (client == NULL) { | ||
217 | printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Let i2c-core delete that device on driver removal. | ||
223 | * This is safe because i2c-core holds the core_lock mutex for us. | ||
224 | */ | ||
225 | list_add_tail(&client->detected, &client->driver->clients); | ||
226 | } | ||
227 | |||
228 | static int wf_sat_probe(struct i2c_client *client, | ||
229 | const struct i2c_device_id *id) | ||
230 | { | ||
231 | struct device_node *dev = client->dev.platform_data; | ||
215 | struct wf_sat *sat; | 232 | struct wf_sat *sat; |
216 | struct wf_sat_sensor *sens; | 233 | struct wf_sat_sensor *sens; |
217 | const u32 *reg; | 234 | const u32 *reg; |
218 | const char *loc, *type; | 235 | const char *loc, *type; |
219 | u8 addr, chip, core; | 236 | u8 chip, core; |
220 | struct device_node *child; | 237 | struct device_node *child; |
221 | int shift, cpu, index; | 238 | int shift, cpu, index; |
222 | char *name; | 239 | char *name; |
223 | int vsens[2], isens[2]; | 240 | int vsens[2], isens[2]; |
224 | 241 | ||
225 | reg = of_get_property(dev, "reg", NULL); | ||
226 | if (reg == NULL) | ||
227 | return; | ||
228 | addr = *reg; | ||
229 | DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); | ||
230 | |||
231 | sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); | 242 | sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); |
232 | if (sat == NULL) | 243 | if (sat == NULL) |
233 | return; | 244 | return -ENOMEM; |
234 | sat->nr = -1; | 245 | sat->nr = -1; |
235 | sat->node = of_node_get(dev); | 246 | sat->node = of_node_get(dev); |
236 | atomic_set(&sat->refcnt, 0); | 247 | atomic_set(&sat->refcnt, 0); |
237 | mutex_init(&sat->mutex); | 248 | mutex_init(&sat->mutex); |
238 | sat->i2c.addr = (addr >> 1) & 0x7f; | 249 | sat->i2c = client; |
239 | sat->i2c.adapter = adapter; | 250 | i2c_set_clientdata(client, sat); |
240 | sat->i2c.driver = &wf_sat_driver; | ||
241 | strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1); | ||
242 | |||
243 | if (i2c_attach_client(&sat->i2c)) { | ||
244 | printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); | ||
245 | goto fail; | ||
246 | } | ||
247 | 251 | ||
248 | vsens[0] = vsens[1] = -1; | 252 | vsens[0] = vsens[1] = -1; |
249 | isens[0] = isens[1] = -1; | 253 | isens[0] = isens[1] = -1; |
@@ -344,10 +348,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) | |||
344 | if (sat->nr >= 0) | 348 | if (sat->nr >= 0) |
345 | sats[sat->nr] = sat; | 349 | sats[sat->nr] = sat; |
346 | 350 | ||
347 | return; | 351 | return 0; |
348 | |||
349 | fail: | ||
350 | kfree(sat); | ||
351 | } | 352 | } |
352 | 353 | ||
353 | static int wf_sat_attach(struct i2c_adapter *adapter) | 354 | static int wf_sat_attach(struct i2c_adapter *adapter) |
@@ -366,16 +367,32 @@ static int wf_sat_attach(struct i2c_adapter *adapter) | |||
366 | return 0; | 367 | return 0; |
367 | } | 368 | } |
368 | 369 | ||
369 | static int wf_sat_detach(struct i2c_client *client) | 370 | static int wf_sat_remove(struct i2c_client *client) |
370 | { | 371 | { |
371 | struct wf_sat *sat = i2c_to_sat(client); | 372 | struct wf_sat *sat = i2c_get_clientdata(client); |
372 | 373 | ||
373 | /* XXX TODO */ | 374 | /* XXX TODO */ |
374 | 375 | ||
375 | sat->i2c.adapter = NULL; | 376 | sat->i2c = NULL; |
377 | i2c_set_clientdata(client, NULL); | ||
376 | return 0; | 378 | return 0; |
377 | } | 379 | } |
378 | 380 | ||
381 | static const struct i2c_device_id wf_sat_id[] = { | ||
382 | { "wf_sat", 0 }, | ||
383 | { } | ||
384 | }; | ||
385 | |||
386 | static struct i2c_driver wf_sat_driver = { | ||
387 | .driver = { | ||
388 | .name = "wf_smu_sat", | ||
389 | }, | ||
390 | .attach_adapter = wf_sat_attach, | ||
391 | .probe = wf_sat_probe, | ||
392 | .remove = wf_sat_remove, | ||
393 | .id_table = wf_sat_id, | ||
394 | }; | ||
395 | |||
379 | static int __init sat_sensors_init(void) | 396 | static int __init sat_sensors_init(void) |
380 | { | 397 | { |
381 | return i2c_add_driver(&wf_sat_driver); | 398 | return i2c_add_driver(&wf_sat_driver); |