diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/sl811_cs.c | 119 |
1 files changed, 33 insertions, 86 deletions
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 134d2000128a..302aa1ec312f 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c | |||
@@ -67,11 +67,11 @@ module_param(pc_debug, int, 0644); | |||
67 | static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; | 67 | static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; |
68 | 68 | ||
69 | typedef struct local_info_t { | 69 | typedef struct local_info_t { |
70 | dev_link_t link; | 70 | struct pcmcia_device *p_dev; |
71 | dev_node_t node; | 71 | dev_node_t node; |
72 | } local_info_t; | 72 | } local_info_t; |
73 | 73 | ||
74 | static void sl811_cs_release(dev_link_t * link); | 74 | static void sl811_cs_release(struct pcmcia_device * link); |
75 | 75 | ||
76 | /*====================================================================*/ | 76 | /*====================================================================*/ |
77 | 77 | ||
@@ -138,41 +138,27 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) | |||
138 | 138 | ||
139 | /*====================================================================*/ | 139 | /*====================================================================*/ |
140 | 140 | ||
141 | static void sl811_cs_detach(struct pcmcia_device *p_dev) | 141 | static void sl811_cs_detach(struct pcmcia_device *link) |
142 | { | 142 | { |
143 | dev_link_t *link = dev_to_instance(p_dev); | ||
144 | |||
145 | DBG(0, "sl811_cs_detach(0x%p)\n", link); | 143 | DBG(0, "sl811_cs_detach(0x%p)\n", link); |
146 | 144 | ||
147 | link->state &= ~DEV_PRESENT; | 145 | sl811_cs_release(link); |
148 | if (link->state & DEV_CONFIG) | ||
149 | sl811_cs_release(link); | ||
150 | 146 | ||
151 | /* This points to the parent local_info_t struct */ | 147 | /* This points to the parent local_info_t struct */ |
152 | kfree(link->priv); | 148 | kfree(link->priv); |
153 | } | 149 | } |
154 | 150 | ||
155 | static void sl811_cs_release(dev_link_t * link) | 151 | static void sl811_cs_release(struct pcmcia_device * link) |
156 | { | 152 | { |
157 | |||
158 | DBG(0, "sl811_cs_release(0x%p)\n", link); | 153 | DBG(0, "sl811_cs_release(0x%p)\n", link); |
159 | 154 | ||
160 | /* Unlink the device chain */ | 155 | pcmcia_disable_device(link); |
161 | link->dev = NULL; | ||
162 | |||
163 | platform_device_unregister(&platform_dev); | 156 | platform_device_unregister(&platform_dev); |
164 | pcmcia_release_configuration(link->handle); | ||
165 | if (link->io.NumPorts1) | ||
166 | pcmcia_release_io(link->handle, &link->io); | ||
167 | if (link->irq.AssignedIRQ) | ||
168 | pcmcia_release_irq(link->handle, &link->irq); | ||
169 | link->state &= ~DEV_CONFIG; | ||
170 | } | 157 | } |
171 | 158 | ||
172 | static void sl811_cs_config(dev_link_t *link) | 159 | static int sl811_cs_config(struct pcmcia_device *link) |
173 | { | 160 | { |
174 | client_handle_t handle = link->handle; | 161 | struct device *parent = &handle_to_dev(link); |
175 | struct device *parent = &handle_to_dev(handle); | ||
176 | local_info_t *dev = link->priv; | 162 | local_info_t *dev = link->priv; |
177 | tuple_t tuple; | 163 | tuple_t tuple; |
178 | cisparse_t parse; | 164 | cisparse_t parse; |
@@ -188,27 +174,23 @@ static void sl811_cs_config(dev_link_t *link) | |||
188 | tuple.TupleData = buf; | 174 | tuple.TupleData = buf; |
189 | tuple.TupleDataMax = sizeof(buf); | 175 | tuple.TupleDataMax = sizeof(buf); |
190 | tuple.TupleOffset = 0; | 176 | tuple.TupleOffset = 0; |
191 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 177 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
192 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 178 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
193 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 179 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
194 | link->conf.ConfigBase = parse.config.base; | 180 | link->conf.ConfigBase = parse.config.base; |
195 | link->conf.Present = parse.config.rmask[0]; | 181 | link->conf.Present = parse.config.rmask[0]; |
196 | 182 | ||
197 | /* Configure card */ | ||
198 | link->state |= DEV_CONFIG; | ||
199 | |||
200 | /* Look up the current Vcc */ | 183 | /* Look up the current Vcc */ |
201 | CS_CHECK(GetConfigurationInfo, | 184 | CS_CHECK(GetConfigurationInfo, |
202 | pcmcia_get_configuration_info(handle, &conf)); | 185 | pcmcia_get_configuration_info(link, &conf)); |
203 | link->conf.Vcc = conf.Vcc; | ||
204 | 186 | ||
205 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 187 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
206 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 188 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
207 | while (1) { | 189 | while (1) { |
208 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 190 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
209 | 191 | ||
210 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 | 192 | if (pcmcia_get_tuple_data(link, &tuple) != 0 |
211 | || pcmcia_parse_tuple(handle, &tuple, &parse) | 193 | || pcmcia_parse_tuple(link, &tuple, &parse) |
212 | != 0) | 194 | != 0) |
213 | goto next_entry; | 195 | goto next_entry; |
214 | 196 | ||
@@ -234,10 +216,10 @@ static void sl811_cs_config(dev_link_t *link) | |||
234 | } | 216 | } |
235 | 217 | ||
236 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | 218 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) |
237 | link->conf.Vpp1 = link->conf.Vpp2 = | 219 | link->conf.Vpp = |
238 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | 220 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; |
239 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) | 221 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) |
240 | link->conf.Vpp1 = link->conf.Vpp2 = | 222 | link->conf.Vpp = |
241 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; | 223 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; |
242 | 224 | ||
243 | /* we need an interrupt */ | 225 | /* we need an interrupt */ |
@@ -254,15 +236,14 @@ static void sl811_cs_config(dev_link_t *link) | |||
254 | link->io.BasePort1 = io->win[0].base; | 236 | link->io.BasePort1 = io->win[0].base; |
255 | link->io.NumPorts1 = io->win[0].len; | 237 | link->io.NumPorts1 = io->win[0].len; |
256 | 238 | ||
257 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 239 | if (pcmcia_request_io(link, &link->io) != 0) |
258 | goto next_entry; | 240 | goto next_entry; |
259 | } | 241 | } |
260 | break; | 242 | break; |
261 | 243 | ||
262 | next_entry: | 244 | next_entry: |
263 | if (link->io.NumPorts1) | 245 | pcmcia_disable_device(link); |
264 | pcmcia_release_io(link->handle, &link->io); | 246 | last_ret = pcmcia_get_next_tuple(link, &tuple); |
265 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | ||
266 | } | 247 | } |
267 | 248 | ||
268 | /* require an IRQ and two registers */ | 249 | /* require an IRQ and two registers */ |
@@ -270,71 +251,46 @@ next_entry: | |||
270 | goto cs_failed; | 251 | goto cs_failed; |
271 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 252 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
272 | CS_CHECK(RequestIRQ, | 253 | CS_CHECK(RequestIRQ, |
273 | pcmcia_request_irq(link->handle, &link->irq)); | 254 | pcmcia_request_irq(link, &link->irq)); |
274 | else | 255 | else |
275 | goto cs_failed; | 256 | goto cs_failed; |
276 | 257 | ||
277 | CS_CHECK(RequestConfiguration, | 258 | CS_CHECK(RequestConfiguration, |
278 | pcmcia_request_configuration(link->handle, &link->conf)); | 259 | pcmcia_request_configuration(link, &link->conf)); |
279 | 260 | ||
280 | sprintf(dev->node.dev_name, driver_name); | 261 | sprintf(dev->node.dev_name, driver_name); |
281 | dev->node.major = dev->node.minor = 0; | 262 | dev->node.major = dev->node.minor = 0; |
282 | link->dev = &dev->node; | 263 | link->dev_node = &dev->node; |
283 | 264 | ||
284 | printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", | 265 | printk(KERN_INFO "%s: index 0x%02x: ", |
285 | dev->node.dev_name, link->conf.ConfigIndex, | 266 | dev->node.dev_name, link->conf.ConfigIndex); |
286 | link->conf.Vcc/10, link->conf.Vcc%10); | 267 | if (link->conf.Vpp) |
287 | if (link->conf.Vpp1) | 268 | printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); |
288 | printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); | ||
289 | printk(", irq %d", link->irq.AssignedIRQ); | 269 | printk(", irq %d", link->irq.AssignedIRQ); |
290 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | 270 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, |
291 | link->io.BasePort1+link->io.NumPorts1-1); | 271 | link->io.BasePort1+link->io.NumPorts1-1); |
292 | printk("\n"); | 272 | printk("\n"); |
293 | 273 | ||
294 | link->state &= ~DEV_CONFIG_PENDING; | ||
295 | |||
296 | if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) | 274 | if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) |
297 | < 0) { | 275 | < 0) { |
298 | cs_failed: | 276 | cs_failed: |
299 | printk("sl811_cs_config failed\n"); | 277 | printk("sl811_cs_config failed\n"); |
300 | cs_error(link->handle, last_fn, last_ret); | 278 | cs_error(link, last_fn, last_ret); |
301 | sl811_cs_release(link); | 279 | sl811_cs_release(link); |
302 | link->state &= ~DEV_CONFIG_PENDING; | 280 | return -ENODEV; |
303 | } | 281 | } |
304 | } | ||
305 | |||
306 | static int sl811_suspend(struct pcmcia_device *dev) | ||
307 | { | ||
308 | dev_link_t *link = dev_to_instance(dev); | ||
309 | |||
310 | link->state |= DEV_SUSPEND; | ||
311 | if (link->state & DEV_CONFIG) | ||
312 | pcmcia_release_configuration(link->handle); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int sl811_resume(struct pcmcia_device *dev) | ||
318 | { | ||
319 | dev_link_t *link = dev_to_instance(dev); | ||
320 | |||
321 | link->state &= ~DEV_SUSPEND; | ||
322 | if (link->state & DEV_CONFIG) | ||
323 | pcmcia_request_configuration(link->handle, &link->conf); | ||
324 | |||
325 | return 0; | 282 | return 0; |
326 | } | 283 | } |
327 | 284 | ||
328 | static int sl811_cs_attach(struct pcmcia_device *p_dev) | 285 | static int sl811_cs_probe(struct pcmcia_device *link) |
329 | { | 286 | { |
330 | local_info_t *local; | 287 | local_info_t *local; |
331 | dev_link_t *link; | ||
332 | 288 | ||
333 | local = kmalloc(sizeof(local_info_t), GFP_KERNEL); | 289 | local = kmalloc(sizeof(local_info_t), GFP_KERNEL); |
334 | if (!local) | 290 | if (!local) |
335 | return -ENOMEM; | 291 | return -ENOMEM; |
336 | memset(local, 0, sizeof(local_info_t)); | 292 | memset(local, 0, sizeof(local_info_t)); |
337 | link = &local->link; | 293 | local->p_dev = link; |
338 | link->priv = local; | 294 | link->priv = local; |
339 | 295 | ||
340 | /* Initialize */ | 296 | /* Initialize */ |
@@ -343,16 +299,9 @@ static int sl811_cs_attach(struct pcmcia_device *p_dev) | |||
343 | link->irq.Handler = NULL; | 299 | link->irq.Handler = NULL; |
344 | 300 | ||
345 | link->conf.Attributes = 0; | 301 | link->conf.Attributes = 0; |
346 | link->conf.Vcc = 33; | ||
347 | link->conf.IntType = INT_MEMORY_AND_IO; | 302 | link->conf.IntType = INT_MEMORY_AND_IO; |
348 | 303 | ||
349 | link->handle = p_dev; | 304 | return sl811_cs_config(link); |
350 | p_dev->instance = link; | ||
351 | |||
352 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
353 | sl811_cs_config(link); | ||
354 | |||
355 | return 0; | ||
356 | } | 305 | } |
357 | 306 | ||
358 | static struct pcmcia_device_id sl811_ids[] = { | 307 | static struct pcmcia_device_id sl811_ids[] = { |
@@ -366,11 +315,9 @@ static struct pcmcia_driver sl811_cs_driver = { | |||
366 | .drv = { | 315 | .drv = { |
367 | .name = (char *)driver_name, | 316 | .name = (char *)driver_name, |
368 | }, | 317 | }, |
369 | .probe = sl811_cs_attach, | 318 | .probe = sl811_cs_probe, |
370 | .remove = sl811_cs_detach, | 319 | .remove = sl811_cs_detach, |
371 | .id_table = sl811_ids, | 320 | .id_table = sl811_ids, |
372 | .suspend = sl811_suspend, | ||
373 | .resume = sl811_resume, | ||
374 | }; | 321 | }; |
375 | 322 | ||
376 | /*====================================================================*/ | 323 | /*====================================================================*/ |