aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/sl811_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/sl811_cs.c')
-rw-r--r--drivers/usb/host/sl811_cs.c119
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);
67static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; 67static const char driver_name[DEV_NAME_LEN] = "sl811_cs";
68 68
69typedef struct local_info_t { 69typedef 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
74static void sl811_cs_release(dev_link_t * link); 74static 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
141static void sl811_cs_detach(struct pcmcia_device *p_dev) 141static 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
155static void sl811_cs_release(dev_link_t * link) 151static 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
172static void sl811_cs_config(dev_link_t *link) 159static 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
262next_entry: 244next_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) {
298cs_failed: 276cs_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
306static 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
317static 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
328static int sl811_cs_attach(struct pcmcia_device *p_dev) 285static 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
358static struct pcmcia_device_id sl811_ids[] = { 307static 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/*====================================================================*/