diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 7 | ||||
-rw-r--r-- | drivers/serial/amba-pl010.c | 9 | ||||
-rw-r--r-- | drivers/serial/ioc3_serial.c | 5 | ||||
-rw-r--r-- | drivers/serial/mfd.c | 18 | ||||
-rw-r--r-- | drivers/serial/mpc52xx_uart.c | 1 | ||||
-rw-r--r-- | drivers/serial/mrst_max3110.c | 1 | ||||
-rw-r--r-- | drivers/serial/samsung.c | 2 | ||||
-rw-r--r-- | drivers/serial/serial_cs.c | 261 |
8 files changed, 134 insertions, 170 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 12900f7083b0..3198c5335f0b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -458,6 +458,7 @@ config SERIAL_SAMSUNG_UARTS | |||
458 | int | 458 | int |
459 | depends on ARM && PLAT_SAMSUNG | 459 | depends on ARM && PLAT_SAMSUNG |
460 | default 2 if ARCH_S3C2400 | 460 | default 2 if ARCH_S3C2400 |
461 | default 6 if ARCH_S5P6450 | ||
461 | default 4 if SERIAL_SAMSUNG_UARTS_4 | 462 | default 4 if SERIAL_SAMSUNG_UARTS_4 |
462 | default 3 | 463 | default 3 |
463 | help | 464 | help |
@@ -526,12 +527,12 @@ config SERIAL_S3C24A0 | |||
526 | Serial port support for the Samsung S3C24A0 SoC | 527 | Serial port support for the Samsung S3C24A0 SoC |
527 | 528 | ||
528 | config SERIAL_S3C6400 | 529 | config SERIAL_S3C6400 |
529 | tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support" | 530 | tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support" |
530 | depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100) | 531 | depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100) |
531 | select SERIAL_SAMSUNG_UARTS_4 | 532 | select SERIAL_SAMSUNG_UARTS_4 |
532 | default y | 533 | default y |
533 | help | 534 | help |
534 | Serial port support for the Samsung S3C6400, S3C6410, S5P6440 | 535 | Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450 |
535 | and S5PC100 SoCs | 536 | and S5PC100 SoCs |
536 | 537 | ||
537 | config SERIAL_S5PV210 | 538 | config SERIAL_S5PV210 |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 50441ffe8e38..2904aa044126 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -472,14 +472,9 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, | |||
472 | spin_unlock_irqrestore(&uap->port.lock, flags); | 472 | spin_unlock_irqrestore(&uap->port.lock, flags); |
473 | } | 473 | } |
474 | 474 | ||
475 | static void pl010_set_ldisc(struct uart_port *port) | 475 | static void pl010_set_ldisc(struct uart_port *port, int new) |
476 | { | 476 | { |
477 | int line = port->line; | 477 | if (new == N_PPS) { |
478 | |||
479 | if (line >= port->state->port.tty->driver->num) | ||
480 | return; | ||
481 | |||
482 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | ||
483 | port->flags |= UPF_HARDPPS_CD; | 478 | port->flags |= UPF_HARDPPS_CD; |
484 | pl010_enable_ms(port); | 479 | pl010_enable_ms(port); |
485 | } else | 480 | } else |
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 93de907b1208..ee43efc7bdcc 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c | |||
@@ -2017,6 +2017,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) | |||
2017 | struct ioc3_port *port; | 2017 | struct ioc3_port *port; |
2018 | struct ioc3_port *ports[PORTS_PER_CARD]; | 2018 | struct ioc3_port *ports[PORTS_PER_CARD]; |
2019 | int phys_port; | 2019 | int phys_port; |
2020 | int cnt; | ||
2020 | 2021 | ||
2021 | DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd)); | 2022 | DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd)); |
2022 | 2023 | ||
@@ -2044,6 +2045,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) | |||
2044 | if (!port) { | 2045 | if (!port) { |
2045 | printk(KERN_WARNING | 2046 | printk(KERN_WARNING |
2046 | "IOC3 serial memory not available for port\n"); | 2047 | "IOC3 serial memory not available for port\n"); |
2048 | ret = -ENOMEM; | ||
2047 | goto out4; | 2049 | goto out4; |
2048 | } | 2050 | } |
2049 | spin_lock_init(&port->ip_lock); | 2051 | spin_lock_init(&port->ip_lock); |
@@ -2146,6 +2148,9 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) | |||
2146 | 2148 | ||
2147 | /* error exits that give back resources */ | 2149 | /* error exits that give back resources */ |
2148 | out4: | 2150 | out4: |
2151 | for (cnt = 0; cnt < phys_port; cnt++) | ||
2152 | kfree(ports[cnt]); | ||
2153 | |||
2149 | kfree(card_ptr); | 2154 | kfree(card_ptr); |
2150 | return ret; | 2155 | return ret; |
2151 | } | 2156 | } |
diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c index bc9af503907f..5dff45c76d32 100644 --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/sysrq.h> | 29 | #include <linux/sysrq.h> |
30 | #include <linux/slab.h> | ||
30 | #include <linux/serial_reg.h> | 31 | #include <linux/serial_reg.h> |
31 | #include <linux/circ_buf.h> | 32 | #include <linux/circ_buf.h> |
32 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
@@ -1423,7 +1424,6 @@ static void hsu_global_init(void) | |||
1423 | } | 1424 | } |
1424 | 1425 | ||
1425 | phsu = hsu; | 1426 | phsu = hsu; |
1426 | |||
1427 | hsu_debugfs_init(hsu); | 1427 | hsu_debugfs_init(hsu); |
1428 | return; | 1428 | return; |
1429 | 1429 | ||
@@ -1435,18 +1435,20 @@ err_free_region: | |||
1435 | 1435 | ||
1436 | static void serial_hsu_remove(struct pci_dev *pdev) | 1436 | static void serial_hsu_remove(struct pci_dev *pdev) |
1437 | { | 1437 | { |
1438 | struct hsu_port *hsu; | 1438 | void *priv = pci_get_drvdata(pdev); |
1439 | int i; | 1439 | struct uart_hsu_port *up; |
1440 | 1440 | ||
1441 | hsu = pci_get_drvdata(pdev); | 1441 | if (!priv) |
1442 | if (!hsu) | ||
1443 | return; | 1442 | return; |
1444 | 1443 | ||
1445 | for (i = 0; i < 3; i++) | 1444 | /* For port 0/1/2, priv is the address of uart_hsu_port */ |
1446 | uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port); | 1445 | if (pdev->device != 0x081E) { |
1446 | up = priv; | ||
1447 | uart_remove_one_port(&serial_hsu_reg, &up->port); | ||
1448 | } | ||
1447 | 1449 | ||
1448 | pci_set_drvdata(pdev, NULL); | 1450 | pci_set_drvdata(pdev, NULL); |
1449 | free_irq(hsu->irq, hsu); | 1451 | free_irq(pdev->irq, priv); |
1450 | pci_disable_device(pdev); | 1452 | pci_disable_device(pdev); |
1451 | } | 1453 | } |
1452 | 1454 | ||
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 8dedb266f143..c4399e23565a 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -500,6 +500,7 @@ static int __init mpc512x_psc_fifoc_init(void) | |||
500 | psc_fifoc = of_iomap(np, 0); | 500 | psc_fifoc = of_iomap(np, 0); |
501 | if (!psc_fifoc) { | 501 | if (!psc_fifoc) { |
502 | pr_err("%s: Can't map FIFOC\n", __func__); | 502 | pr_err("%s: Can't map FIFOC\n", __func__); |
503 | of_node_put(np); | ||
503 | return -ENODEV; | 504 | return -ENODEV; |
504 | } | 505 | } |
505 | 506 | ||
diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c index f6ad1ecbff79..51c15f58e01e 100644 --- a/drivers/serial/mrst_max3110.c +++ b/drivers/serial/mrst_max3110.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
32 | #include <linux/irq.h> | ||
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | #include <linux/console.h> | 34 | #include <linux/console.h> |
34 | #include <linux/sysrq.h> | 35 | #include <linux/sysrq.h> |
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index b1156ba8ad14..7ac2bf5167cd 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c | |||
@@ -1101,7 +1101,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, | |||
1101 | dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); | 1101 | dbg("resource %p (%lx..%lx)\n", res, res->start, res->end); |
1102 | 1102 | ||
1103 | port->mapbase = res->start; | 1103 | port->mapbase = res->start; |
1104 | port->membase = S3C_VA_UART + res->start - (S3C_PA_UART & 0xfff00000); | 1104 | port->membase = S3C_VA_UART + (res->start & 0xfffff); |
1105 | ret = platform_get_irq(platdev, 0); | 1105 | ret = platform_get_irq(platdev, 0); |
1106 | if (ret < 0) | 1106 | if (ret < 0) |
1107 | port->irq = 0; | 1107 | port->irq = 0; |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 141c69554bd4..93760b2ea172 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <asm/io.h> | 45 | #include <asm/io.h> |
46 | #include <asm/system.h> | 46 | #include <asm/system.h> |
47 | 47 | ||
48 | #include <pcmcia/cs.h> | ||
49 | #include <pcmcia/cistpl.h> | 48 | #include <pcmcia/cistpl.h> |
50 | #include <pcmcia/ciscode.h> | 49 | #include <pcmcia/ciscode.h> |
51 | #include <pcmcia/ds.h> | 50 | #include <pcmcia/ds.h> |
@@ -183,10 +182,8 @@ static void quirk_config_socket(struct pcmcia_device *link) | |||
183 | { | 182 | { |
184 | struct serial_info *info = link->priv; | 183 | struct serial_info *info = link->priv; |
185 | 184 | ||
186 | if (info->multi) { | 185 | if (info->multi) |
187 | link->conf.Present |= PRESENT_EXT_STATUS; | 186 | link->config_flags |= CONF_ENABLE_ESR; |
188 | link->conf.ExtStatus = ESR_REQ_ATTN_ENA; | ||
189 | } | ||
190 | } | 187 | } |
191 | 188 | ||
192 | static const struct serial_quirk quirks[] = { | 189 | static const struct serial_quirk quirks[] = { |
@@ -265,13 +262,6 @@ static const struct serial_quirk quirks[] = { | |||
265 | static int serial_config(struct pcmcia_device * link); | 262 | static int serial_config(struct pcmcia_device * link); |
266 | 263 | ||
267 | 264 | ||
268 | /*====================================================================== | ||
269 | |||
270 | After a card is removed, serial_remove() will unregister | ||
271 | the serial device(s), and release the PCMCIA configuration. | ||
272 | |||
273 | ======================================================================*/ | ||
274 | |||
275 | static void serial_remove(struct pcmcia_device *link) | 265 | static void serial_remove(struct pcmcia_device *link) |
276 | { | 266 | { |
277 | struct serial_info *info = link->priv; | 267 | struct serial_info *info = link->priv; |
@@ -314,14 +304,6 @@ static int serial_resume(struct pcmcia_device *link) | |||
314 | return 0; | 304 | return 0; |
315 | } | 305 | } |
316 | 306 | ||
317 | /*====================================================================== | ||
318 | |||
319 | serial_attach() creates an "instance" of the driver, allocating | ||
320 | local data structures for one device. The device is registered | ||
321 | with Card Services. | ||
322 | |||
323 | ======================================================================*/ | ||
324 | |||
325 | static int serial_probe(struct pcmcia_device *link) | 307 | static int serial_probe(struct pcmcia_device *link) |
326 | { | 308 | { |
327 | struct serial_info *info; | 309 | struct serial_info *info; |
@@ -335,27 +317,13 @@ static int serial_probe(struct pcmcia_device *link) | |||
335 | info->p_dev = link; | 317 | info->p_dev = link; |
336 | link->priv = info; | 318 | link->priv = info; |
337 | 319 | ||
338 | link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; | 320 | link->config_flags |= CONF_ENABLE_IRQ; |
339 | link->resource[0]->end = 8; | 321 | if (do_sound) |
340 | link->conf.Attributes = CONF_ENABLE_IRQ; | 322 | link->config_flags |= CONF_ENABLE_SPKR; |
341 | if (do_sound) { | ||
342 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
343 | link->conf.Status = CCSR_AUDIO_ENA; | ||
344 | } | ||
345 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
346 | 323 | ||
347 | return serial_config(link); | 324 | return serial_config(link); |
348 | } | 325 | } |
349 | 326 | ||
350 | /*====================================================================== | ||
351 | |||
352 | This deletes a driver "instance". The device is de-registered | ||
353 | with Card Services. If it has been released, all local data | ||
354 | structures are freed. Otherwise, the structures will be freed | ||
355 | when the device is released. | ||
356 | |||
357 | ======================================================================*/ | ||
358 | |||
359 | static void serial_detach(struct pcmcia_device *link) | 327 | static void serial_detach(struct pcmcia_device *link) |
360 | { | 328 | { |
361 | struct serial_info *info = link->priv; | 329 | struct serial_info *info = link->priv; |
@@ -363,11 +331,6 @@ static void serial_detach(struct pcmcia_device *link) | |||
363 | dev_dbg(&link->dev, "serial_detach\n"); | 331 | dev_dbg(&link->dev, "serial_detach\n"); |
364 | 332 | ||
365 | /* | 333 | /* |
366 | * Ensure any outstanding scheduled tasks are completed. | ||
367 | */ | ||
368 | flush_scheduled_work(); | ||
369 | |||
370 | /* | ||
371 | * Ensure that the ports have been released. | 334 | * Ensure that the ports have been released. |
372 | */ | 335 | */ |
373 | serial_remove(link); | 336 | serial_remove(link); |
@@ -411,47 +374,66 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, | |||
411 | 374 | ||
412 | /*====================================================================*/ | 375 | /*====================================================================*/ |
413 | 376 | ||
414 | static int simple_config_check(struct pcmcia_device *p_dev, | 377 | static int pfc_config(struct pcmcia_device *p_dev) |
415 | cistpl_cftable_entry_t *cf, | 378 | { |
416 | cistpl_cftable_entry_t *dflt, | 379 | unsigned int port = 0; |
417 | unsigned int vcc, | 380 | struct serial_info *info = p_dev->priv; |
418 | void *priv_data) | 381 | |
382 | if ((p_dev->resource[1]->end != 0) && | ||
383 | (resource_size(p_dev->resource[1]) == 8)) { | ||
384 | port = p_dev->resource[1]->start; | ||
385 | info->slave = 1; | ||
386 | } else if ((info->manfid == MANFID_OSITECH) && | ||
387 | (resource_size(p_dev->resource[0]) == 0x40)) { | ||
388 | port = p_dev->resource[0]->start + 0x28; | ||
389 | info->slave = 1; | ||
390 | } | ||
391 | if (info->slave) | ||
392 | return setup_serial(p_dev, info, port, p_dev->irq); | ||
393 | |||
394 | dev_warn(&p_dev->dev, "no usable port range found, giving up\n"); | ||
395 | return -ENODEV; | ||
396 | } | ||
397 | |||
398 | static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data) | ||
419 | { | 399 | { |
420 | static const int size_table[2] = { 8, 16 }; | 400 | static const int size_table[2] = { 8, 16 }; |
421 | int *try = priv_data; | 401 | int *try = priv_data; |
422 | 402 | ||
423 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 403 | if (p_dev->resource[0]->start == 0) |
424 | p_dev->conf.Vpp = | 404 | return -ENODEV; |
425 | cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
426 | 405 | ||
427 | p_dev->io_lines = ((*try & 0x1) == 0) ? | 406 | if ((*try & 0x1) == 0) |
428 | 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | 407 | p_dev->io_lines = 16; |
429 | 408 | ||
430 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)]) | 409 | if (p_dev->resource[0]->end != size_table[(*try >> 1)]) |
431 | && (cf->io.win[0].base != 0)) { | 410 | return -ENODEV; |
432 | p_dev->resource[0]->start = cf->io.win[0].base; | 411 | |
433 | if (!pcmcia_request_io(p_dev)) | 412 | p_dev->resource[0]->end = 8; |
434 | return 0; | 413 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
435 | } | 414 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
436 | return -EINVAL; | 415 | |
416 | return pcmcia_request_io(p_dev); | ||
437 | } | 417 | } |
438 | 418 | ||
439 | static int simple_config_check_notpicky(struct pcmcia_device *p_dev, | 419 | static int simple_config_check_notpicky(struct pcmcia_device *p_dev, |
440 | cistpl_cftable_entry_t *cf, | ||
441 | cistpl_cftable_entry_t *dflt, | ||
442 | unsigned int vcc, | ||
443 | void *priv_data) | 420 | void *priv_data) |
444 | { | 421 | { |
445 | static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | 422 | static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; |
446 | int j; | 423 | int j; |
447 | 424 | ||
448 | if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | 425 | if (p_dev->io_lines > 3) |
449 | for (j = 0; j < 5; j++) { | 426 | return -ENODEV; |
450 | p_dev->resource[0]->start = base[j]; | 427 | |
451 | p_dev->io_lines = base[j] ? 16 : 3; | 428 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
452 | if (!pcmcia_request_io(p_dev)) | 429 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
453 | return 0; | 430 | p_dev->resource[0]->end = 8; |
454 | } | 431 | |
432 | for (j = 0; j < 5; j++) { | ||
433 | p_dev->resource[0]->start = base[j]; | ||
434 | p_dev->io_lines = base[j] ? 16 : 3; | ||
435 | if (!pcmcia_request_io(p_dev)) | ||
436 | return 0; | ||
455 | } | 437 | } |
456 | return -ENODEV; | 438 | return -ENODEV; |
457 | } | 439 | } |
@@ -461,26 +443,9 @@ static int simple_config(struct pcmcia_device *link) | |||
461 | struct serial_info *info = link->priv; | 443 | struct serial_info *info = link->priv; |
462 | int i = -ENODEV, try; | 444 | int i = -ENODEV, try; |
463 | 445 | ||
464 | /* If the card is already configured, look up the port and irq */ | ||
465 | if (link->function_config) { | ||
466 | unsigned int port = 0; | ||
467 | if ((link->resource[1]->end != 0) && | ||
468 | (resource_size(link->resource[1]) == 8)) { | ||
469 | port = link->resource[1]->end; | ||
470 | info->slave = 1; | ||
471 | } else if ((info->manfid == MANFID_OSITECH) && | ||
472 | (resource_size(link->resource[0]) == 0x40)) { | ||
473 | port = link->resource[0]->start + 0x28; | ||
474 | info->slave = 1; | ||
475 | } | ||
476 | if (info->slave) { | ||
477 | return setup_serial(link, info, port, | ||
478 | link->irq); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | /* First pass: look for a config entry that looks normal. | 446 | /* First pass: look for a config entry that looks normal. |
483 | * Two tries: without IO aliases, then with aliases */ | 447 | * Two tries: without IO aliases, then with aliases */ |
448 | link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO; | ||
484 | for (try = 0; try < 4; try++) | 449 | for (try = 0; try < 4; try++) |
485 | if (!pcmcia_loop_config(link, simple_config_check, &try)) | 450 | if (!pcmcia_loop_config(link, simple_config_check, &try)) |
486 | goto found_port; | 451 | goto found_port; |
@@ -491,13 +456,12 @@ static int simple_config(struct pcmcia_device *link) | |||
491 | if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) | 456 | if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) |
492 | goto found_port; | 457 | goto found_port; |
493 | 458 | ||
494 | printk(KERN_NOTICE | 459 | dev_warn(&link->dev, "no usable port range found, giving up\n"); |
495 | "serial_cs: no usable port range found, giving up\n"); | ||
496 | return -1; | 460 | return -1; |
497 | 461 | ||
498 | found_port: | 462 | found_port: |
499 | if (info->multi && (info->manfid == MANFID_3COM)) | 463 | if (info->multi && (info->manfid == MANFID_3COM)) |
500 | link->conf.ConfigIndex &= ~(0x08); | 464 | link->config_index &= ~(0x08); |
501 | 465 | ||
502 | /* | 466 | /* |
503 | * Apply any configuration quirks. | 467 | * Apply any configuration quirks. |
@@ -505,51 +469,50 @@ found_port: | |||
505 | if (info->quirk && info->quirk->config) | 469 | if (info->quirk && info->quirk->config) |
506 | info->quirk->config(link); | 470 | info->quirk->config(link); |
507 | 471 | ||
508 | i = pcmcia_request_configuration(link, &link->conf); | 472 | i = pcmcia_enable_device(link); |
509 | if (i != 0) | 473 | if (i != 0) |
510 | return -1; | 474 | return -1; |
511 | return setup_serial(link, info, link->resource[0]->start, link->irq); | 475 | return setup_serial(link, info, link->resource[0]->start, link->irq); |
512 | } | 476 | } |
513 | 477 | ||
514 | static int multi_config_check(struct pcmcia_device *p_dev, | 478 | static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data) |
515 | cistpl_cftable_entry_t *cf, | ||
516 | cistpl_cftable_entry_t *dflt, | ||
517 | unsigned int vcc, | ||
518 | void *priv_data) | ||
519 | { | 479 | { |
520 | int *base2 = priv_data; | 480 | int *multi = priv_data; |
481 | |||
482 | if (p_dev->resource[1]->end) | ||
483 | return -EINVAL; | ||
521 | 484 | ||
522 | /* The quad port cards have bad CIS's, so just look for a | 485 | /* The quad port cards have bad CIS's, so just look for a |
523 | window larger than 8 ports and assume it will be right */ | 486 | window larger than 8 ports and assume it will be right */ |
524 | if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { | 487 | if (p_dev->resource[0]->end <= 8) |
525 | p_dev->resource[0]->start = cf->io.win[0].base; | 488 | return -EINVAL; |
526 | p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; | 489 | |
527 | if (!pcmcia_request_io(p_dev)) { | 490 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
528 | *base2 = p_dev->resource[0]->start + 8; | 491 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
529 | return 0; | 492 | p_dev->resource[0]->end = *multi * 8; |
530 | } | 493 | |
531 | } | 494 | if (pcmcia_request_io(p_dev)) |
532 | return -ENODEV; | 495 | return -ENODEV; |
496 | return 0; | ||
533 | } | 497 | } |
534 | 498 | ||
535 | static int multi_config_check_notpicky(struct pcmcia_device *p_dev, | 499 | static int multi_config_check_notpicky(struct pcmcia_device *p_dev, |
536 | cistpl_cftable_entry_t *cf, | ||
537 | cistpl_cftable_entry_t *dflt, | ||
538 | unsigned int vcc, | ||
539 | void *priv_data) | 500 | void *priv_data) |
540 | { | 501 | { |
541 | int *base2 = priv_data; | 502 | int *base2 = priv_data; |
542 | 503 | ||
543 | if (cf->io.nwin == 2) { | 504 | if (!p_dev->resource[0]->end || !p_dev->resource[1]->end) |
544 | p_dev->resource[0]->start = cf->io.win[0].base; | 505 | return -ENODEV; |
545 | p_dev->resource[1]->start = cf->io.win[1].base; | 506 | |
546 | p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; | 507 | p_dev->resource[0]->end = p_dev->resource[1]->end = 8; |
547 | if (!pcmcia_request_io(p_dev)) { | 508 | p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; |
548 | *base2 = p_dev->resource[1]->start; | 509 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; |
549 | return 0; | 510 | |
550 | } | 511 | if (pcmcia_request_io(p_dev)) |
551 | } | 512 | return -ENODEV; |
552 | return -ENODEV; | 513 | |
514 | *base2 = p_dev->resource[0]->start + 8; | ||
515 | return 0; | ||
553 | } | 516 | } |
554 | 517 | ||
555 | static int multi_config(struct pcmcia_device *link) | 518 | static int multi_config(struct pcmcia_device *link) |
@@ -557,23 +520,23 @@ static int multi_config(struct pcmcia_device *link) | |||
557 | struct serial_info *info = link->priv; | 520 | struct serial_info *info = link->priv; |
558 | int i, base2 = 0; | 521 | int i, base2 = 0; |
559 | 522 | ||
523 | link->config_flags |= CONF_AUTO_SET_IO; | ||
560 | /* First, look for a generic full-sized window */ | 524 | /* First, look for a generic full-sized window */ |
561 | link->resource[0]->end = info->multi * 8; | 525 | if (!pcmcia_loop_config(link, multi_config_check, &info->multi)) |
562 | if (pcmcia_loop_config(link, multi_config_check, &base2)) { | 526 | base2 = link->resource[0]->start + 8; |
527 | else { | ||
563 | /* If that didn't work, look for two windows */ | 528 | /* If that didn't work, look for two windows */ |
564 | link->resource[0]->end = link->resource[1]->end = 8; | ||
565 | info->multi = 2; | 529 | info->multi = 2; |
566 | if (pcmcia_loop_config(link, multi_config_check_notpicky, | 530 | if (pcmcia_loop_config(link, multi_config_check_notpicky, |
567 | &base2)) { | 531 | &base2)) { |
568 | printk(KERN_NOTICE "serial_cs: no usable port range" | 532 | dev_warn(&link->dev, "no usable port range " |
569 | "found, giving up\n"); | 533 | "found, giving up\n"); |
570 | return -ENODEV; | 534 | return -ENODEV; |
571 | } | 535 | } |
572 | } | 536 | } |
573 | 537 | ||
574 | if (!link->irq) | 538 | if (!link->irq) |
575 | dev_warn(&link->dev, | 539 | dev_warn(&link->dev, "no usable IRQ found, continuing...\n"); |
576 | "serial_cs: no usable IRQ found, continuing...\n"); | ||
577 | 540 | ||
578 | /* | 541 | /* |
579 | * Apply any configuration quirks. | 542 | * Apply any configuration quirks. |
@@ -581,7 +544,7 @@ static int multi_config(struct pcmcia_device *link) | |||
581 | if (info->quirk && info->quirk->config) | 544 | if (info->quirk && info->quirk->config) |
582 | info->quirk->config(link); | 545 | info->quirk->config(link); |
583 | 546 | ||
584 | i = pcmcia_request_configuration(link, &link->conf); | 547 | i = pcmcia_enable_device(link); |
585 | if (i != 0) | 548 | if (i != 0) |
586 | return -ENODEV; | 549 | return -ENODEV; |
587 | 550 | ||
@@ -593,11 +556,11 @@ static int multi_config(struct pcmcia_device *link) | |||
593 | info->prodid == PRODID_POSSIO_GCC)) { | 556 | info->prodid == PRODID_POSSIO_GCC)) { |
594 | int err; | 557 | int err; |
595 | 558 | ||
596 | if (link->conf.ConfigIndex == 1 || | 559 | if (link->config_index == 1 || |
597 | link->conf.ConfigIndex == 3) { | 560 | link->config_index == 3) { |
598 | err = setup_serial(link, info, base2, | 561 | err = setup_serial(link, info, base2, |
599 | link->irq); | 562 | link->irq); |
600 | base2 = link->resource[0]->start;; | 563 | base2 = link->resource[0]->start; |
601 | } else { | 564 | } else { |
602 | err = setup_serial(link, info, link->resource[0]->start, | 565 | err = setup_serial(link, info, link->resource[0]->start, |
603 | link->irq); | 566 | link->irq); |
@@ -621,33 +584,24 @@ static int multi_config(struct pcmcia_device *link) | |||
621 | return 0; | 584 | return 0; |
622 | } | 585 | } |
623 | 586 | ||
624 | static int serial_check_for_multi(struct pcmcia_device *p_dev, | 587 | static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data) |
625 | cistpl_cftable_entry_t *cf, | ||
626 | cistpl_cftable_entry_t *dflt, | ||
627 | unsigned int vcc, | ||
628 | void *priv_data) | ||
629 | { | 588 | { |
630 | struct serial_info *info = p_dev->priv; | 589 | struct serial_info *info = p_dev->priv; |
631 | 590 | ||
632 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | 591 | if (!p_dev->resource[0]->end) |
633 | info->multi = cf->io.win[0].len >> 3; | 592 | return -EINVAL; |
593 | |||
594 | if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0)) | ||
595 | info->multi = p_dev->resource[0]->end >> 3; | ||
634 | 596 | ||
635 | if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && | 597 | if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8) |
636 | (cf->io.win[1].len == 8)) | 598 | && (p_dev->resource[1]->end == 8)) |
637 | info->multi = 2; | 599 | info->multi = 2; |
638 | 600 | ||
639 | return 0; /* break */ | 601 | return 0; /* break */ |
640 | } | 602 | } |
641 | 603 | ||
642 | 604 | ||
643 | /*====================================================================== | ||
644 | |||
645 | serial_config() is scheduled to run after a CARD_INSERTION event | ||
646 | is received, to configure the PCMCIA socket, and to make the | ||
647 | serial device available to the system. | ||
648 | |||
649 | ======================================================================*/ | ||
650 | |||
651 | static int serial_config(struct pcmcia_device * link) | 605 | static int serial_config(struct pcmcia_device * link) |
652 | { | 606 | { |
653 | struct serial_info *info = link->priv; | 607 | struct serial_info *info = link->priv; |
@@ -675,6 +629,7 @@ static int serial_config(struct pcmcia_device * link) | |||
675 | multifunction cards that ask for appropriate IO port ranges */ | 629 | multifunction cards that ask for appropriate IO port ranges */ |
676 | if ((info->multi == 0) && | 630 | if ((info->multi == 0) && |
677 | (link->has_func_id) && | 631 | (link->has_func_id) && |
632 | (link->socket->pcmcia_pfc == 0) && | ||
678 | ((link->func_id == CISTPL_FUNCID_MULTI) || | 633 | ((link->func_id == CISTPL_FUNCID_MULTI) || |
679 | (link->func_id == CISTPL_FUNCID_SERIAL))) | 634 | (link->func_id == CISTPL_FUNCID_SERIAL))) |
680 | pcmcia_loop_config(link, serial_check_for_multi, info); | 635 | pcmcia_loop_config(link, serial_check_for_multi, info); |
@@ -685,7 +640,13 @@ static int serial_config(struct pcmcia_device * link) | |||
685 | if (info->quirk && info->quirk->multi != -1) | 640 | if (info->quirk && info->quirk->multi != -1) |
686 | info->multi = info->quirk->multi; | 641 | info->multi = info->quirk->multi; |
687 | 642 | ||
688 | if (info->multi > 1) | 643 | dev_info(&link->dev, |
644 | "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n", | ||
645 | link->manf_id, link->card_id, | ||
646 | link->socket->pcmcia_pfc, info->multi, info->quirk); | ||
647 | if (link->socket->pcmcia_pfc) | ||
648 | i = pfc_config(link); | ||
649 | else if (info->multi > 1) | ||
689 | i = multi_config(link); | 650 | i = multi_config(link); |
690 | else | 651 | else |
691 | i = simple_config(link); | 652 | i = simple_config(link); |
@@ -704,7 +665,7 @@ static int serial_config(struct pcmcia_device * link) | |||
704 | return 0; | 665 | return 0; |
705 | 666 | ||
706 | failed: | 667 | failed: |
707 | dev_warn(&link->dev, "serial_cs: failed to initialize\n"); | 668 | dev_warn(&link->dev, "failed to initialize\n"); |
708 | serial_remove(link); | 669 | serial_remove(link); |
709 | return -ENODEV; | 670 | return -ENODEV; |
710 | } | 671 | } |
@@ -884,9 +845,7 @@ MODULE_FIRMWARE("cis/RS-COM-2P.cis"); | |||
884 | 845 | ||
885 | static struct pcmcia_driver serial_cs_driver = { | 846 | static struct pcmcia_driver serial_cs_driver = { |
886 | .owner = THIS_MODULE, | 847 | .owner = THIS_MODULE, |
887 | .drv = { | 848 | .name = "serial_cs", |
888 | .name = "serial_cs", | ||
889 | }, | ||
890 | .probe = serial_probe, | 849 | .probe = serial_probe, |
891 | .remove = serial_detach, | 850 | .remove = serial_detach, |
892 | .id_table = serial_ids, | 851 | .id_table = serial_ids, |