aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-08-30 02:18:54 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2010-09-15 11:56:32 -0400
commitc494bc6c534c78fac2d308ad38073b9226448b0d (patch)
tree1ce2fc2404cb735aacf53a0256fd7cd51b6aad5b /drivers/serial
parent49553c2ef88749dd502687f4eb9c258bb10a4f44 (diff)
pcmcia serial_cs.c: fix multifunction card handling
We shouldn't overwrite pre-set values, and we should also set the port address to the beginning, and not the end of the 8-port range. CC: linux-serial@vger.kernel.org Reported-by: Komuro <komurojun-mbn@nifty.com> Hardware-supplied-by: Jochen Frieling <j.frieling@pengutronix.de> Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/serial_cs.c62
1 files changed, 36 insertions, 26 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 141c69554bd4..7d475b2a79e8 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -335,8 +335,6 @@ static int serial_probe(struct pcmcia_device *link)
335 info->p_dev = link; 335 info->p_dev = link;
336 link->priv = info; 336 link->priv = info;
337 337
338 link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
339 link->resource[0]->end = 8;
340 link->conf.Attributes = CONF_ENABLE_IRQ; 338 link->conf.Attributes = CONF_ENABLE_IRQ;
341 if (do_sound) { 339 if (do_sound) {
342 link->conf.Attributes |= CONF_ENABLE_SPKR; 340 link->conf.Attributes |= CONF_ENABLE_SPKR;
@@ -411,6 +409,27 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
411 409
412/*====================================================================*/ 410/*====================================================================*/
413 411
412static int pfc_config(struct pcmcia_device *p_dev)
413{
414 unsigned int port = 0;
415 struct serial_info *info = p_dev->priv;
416
417 if ((p_dev->resource[1]->end != 0) &&
418 (resource_size(p_dev->resource[1]) == 8)) {
419 port = p_dev->resource[1]->start;
420 info->slave = 1;
421 } else if ((info->manfid == MANFID_OSITECH) &&
422 (resource_size(p_dev->resource[0]) == 0x40)) {
423 port = p_dev->resource[0]->start + 0x28;
424 info->slave = 1;
425 }
426 if (info->slave)
427 return setup_serial(p_dev, info, port, p_dev->irq);
428
429 dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
430 return -ENODEV;
431}
432
414static int simple_config_check(struct pcmcia_device *p_dev, 433static int simple_config_check(struct pcmcia_device *p_dev,
415 cistpl_cftable_entry_t *cf, 434 cistpl_cftable_entry_t *cf,
416 cistpl_cftable_entry_t *dflt, 435 cistpl_cftable_entry_t *dflt,
@@ -461,23 +480,8 @@ static int simple_config(struct pcmcia_device *link)
461 struct serial_info *info = link->priv; 480 struct serial_info *info = link->priv;
462 int i = -ENODEV, try; 481 int i = -ENODEV, try;
463 482
464 /* If the card is already configured, look up the port and irq */ 483 link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
465 if (link->function_config) { 484 link->resource[0]->end = 8;
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 485
482 /* First pass: look for a config entry that looks normal. 486 /* First pass: look for a config entry that looks normal.
483 * Two tries: without IO aliases, then with aliases */ 487 * Two tries: without IO aliases, then with aliases */
@@ -491,8 +495,7 @@ static int simple_config(struct pcmcia_device *link)
491 if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) 495 if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
492 goto found_port; 496 goto found_port;
493 497
494 printk(KERN_NOTICE 498 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; 499 return -1;
497 500
498found_port: 501found_port:
@@ -558,6 +561,7 @@ static int multi_config(struct pcmcia_device *link)
558 int i, base2 = 0; 561 int i, base2 = 0;
559 562
560 /* First, look for a generic full-sized window */ 563 /* First, look for a generic full-sized window */
564 link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
561 link->resource[0]->end = info->multi * 8; 565 link->resource[0]->end = info->multi * 8;
562 if (pcmcia_loop_config(link, multi_config_check, &base2)) { 566 if (pcmcia_loop_config(link, multi_config_check, &base2)) {
563 /* If that didn't work, look for two windows */ 567 /* If that didn't work, look for two windows */
@@ -565,15 +569,14 @@ static int multi_config(struct pcmcia_device *link)
565 info->multi = 2; 569 info->multi = 2;
566 if (pcmcia_loop_config(link, multi_config_check_notpicky, 570 if (pcmcia_loop_config(link, multi_config_check_notpicky,
567 &base2)) { 571 &base2)) {
568 printk(KERN_NOTICE "serial_cs: no usable port range" 572 dev_warn(&link->dev, "no usable port range "
569 "found, giving up\n"); 573 "found, giving up\n");
570 return -ENODEV; 574 return -ENODEV;
571 } 575 }
572 } 576 }
573 577
574 if (!link->irq) 578 if (!link->irq)
575 dev_warn(&link->dev, 579 dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
576 "serial_cs: no usable IRQ found, continuing...\n");
577 580
578 /* 581 /*
579 * Apply any configuration quirks. 582 * Apply any configuration quirks.
@@ -675,6 +678,7 @@ static int serial_config(struct pcmcia_device * link)
675 multifunction cards that ask for appropriate IO port ranges */ 678 multifunction cards that ask for appropriate IO port ranges */
676 if ((info->multi == 0) && 679 if ((info->multi == 0) &&
677 (link->has_func_id) && 680 (link->has_func_id) &&
681 (link->socket->pcmcia_pfc == 0) &&
678 ((link->func_id == CISTPL_FUNCID_MULTI) || 682 ((link->func_id == CISTPL_FUNCID_MULTI) ||
679 (link->func_id == CISTPL_FUNCID_SERIAL))) 683 (link->func_id == CISTPL_FUNCID_SERIAL)))
680 pcmcia_loop_config(link, serial_check_for_multi, info); 684 pcmcia_loop_config(link, serial_check_for_multi, info);
@@ -685,7 +689,13 @@ static int serial_config(struct pcmcia_device * link)
685 if (info->quirk && info->quirk->multi != -1) 689 if (info->quirk && info->quirk->multi != -1)
686 info->multi = info->quirk->multi; 690 info->multi = info->quirk->multi;
687 691
688 if (info->multi > 1) 692 dev_info(&link->dev,
693 "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
694 link->manf_id, link->card_id,
695 link->socket->pcmcia_pfc, info->multi, info->quirk);
696 if (link->socket->pcmcia_pfc)
697 i = pfc_config(link);
698 else if (info->multi > 1)
689 i = multi_config(link); 699 i = multi_config(link);
690 else 700 else
691 i = simple_config(link); 701 i = simple_config(link);
@@ -704,7 +714,7 @@ static int serial_config(struct pcmcia_device * link)
704 return 0; 714 return 0;
705 715
706failed: 716failed:
707 dev_warn(&link->dev, "serial_cs: failed to initialize\n"); 717 dev_warn(&link->dev, "failed to initialize\n");
708 serial_remove(link); 718 serial_remove(link);
709 return -ENODEV; 719 return -ENODEV;
710} 720}