diff options
Diffstat (limited to 'drivers/serial/serial_cs.c')
-rw-r--r-- | drivers/serial/serial_cs.c | 116 |
1 files changed, 62 insertions, 54 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index ab17c08ddc03..7d475b2a79e8 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -45,7 +45,6 @@ #include <asm/io.h> #include <asm/system.h> -#include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/ciscode.h> @@ -115,16 +114,14 @@ static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_ static int quirk_post_ibm(struct pcmcia_device *link) { - conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; + u8 val; int ret; - ret = pcmcia_access_configuration_register(link, ®); + ret = pcmcia_read_config_byte(link, 0x800, &val); if (ret) goto failed; - reg.Action = CS_WRITE; - reg.Value = reg.Value | 1; - ret = pcmcia_access_configuration_register(link, ®); + ret = pcmcia_write_config_byte(link, 0x800, val | 1); if (ret) goto failed; return 0; @@ -338,8 +335,6 @@ static int serial_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; link->conf.Attributes = CONF_ENABLE_IRQ; if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; @@ -414,6 +409,27 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, /*====================================================================*/ +static int pfc_config(struct pcmcia_device *p_dev) +{ + unsigned int port = 0; + struct serial_info *info = p_dev->priv; + + if ((p_dev->resource[1]->end != 0) && + (resource_size(p_dev->resource[1]) == 8)) { + port = p_dev->resource[1]->start; + info->slave = 1; + } else if ((info->manfid == MANFID_OSITECH) && + (resource_size(p_dev->resource[0]) == 0x40)) { + port = p_dev->resource[0]->start + 0x28; + info->slave = 1; + } + if (info->slave) + return setup_serial(p_dev, info, port, p_dev->irq); + + dev_warn(&p_dev->dev, "no usable port range found, giving up\n"); + return -ENODEV; +} + static int simple_config_check(struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cf, cistpl_cftable_entry_t *dflt, @@ -427,12 +443,13 @@ static int simple_config_check(struct pcmcia_device *p_dev, p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + p_dev->io_lines = ((*try & 0x1) == 0) ? + 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)]) && (cf->io.win[0].base != 0)) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ? - 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = cf->io.win[0].base; + if (!pcmcia_request_io(p_dev)) return 0; } return -EINVAL; @@ -449,9 +466,9 @@ static int simple_config_check_notpicky(struct pcmcia_device *p_dev, if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { for (j = 0; j < 5; j++) { - p_dev->io.BasePort1 = base[j]; - p_dev->io.IOAddrLines = base[j] ? 16 : 3; - if (!pcmcia_request_io(p_dev, &p_dev->io)) + p_dev->resource[0]->start = base[j]; + p_dev->io_lines = base[j] ? 16 : 3; + if (!pcmcia_request_io(p_dev)) return 0; } } @@ -463,23 +480,8 @@ static int simple_config(struct pcmcia_device *link) struct serial_info *info = link->priv; int i = -ENODEV, try; - /* If the card is already configured, look up the port and irq */ - if (link->function_config) { - unsigned int port = 0; - if ((link->io.BasePort2 != 0) && - (link->io.NumPorts2 == 8)) { - port = link->io.BasePort2; - info->slave = 1; - } else if ((info->manfid == MANFID_OSITECH) && - (link->io.NumPorts1 == 0x40)) { - port = link->io.BasePort1 + 0x28; - info->slave = 1; - } - if (info->slave) { - return setup_serial(link, info, port, - link->irq); - } - } + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 8; /* First pass: look for a config entry that looks normal. * Two tries: without IO aliases, then with aliases */ @@ -493,8 +495,7 @@ static int simple_config(struct pcmcia_device *link) if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) goto found_port; - printk(KERN_NOTICE - "serial_cs: no usable port range found, giving up\n"); + dev_warn(&link->dev, "no usable port range found, giving up\n"); return -1; found_port: @@ -510,7 +511,7 @@ found_port: i = pcmcia_request_configuration(link, &link->conf); if (i != 0) return -1; - return setup_serial(link, info, link->io.BasePort1, link->irq); + return setup_serial(link, info, link->resource[0]->start, link->irq); } static int multi_config_check(struct pcmcia_device *p_dev, @@ -524,10 +525,10 @@ static int multi_config_check(struct pcmcia_device *p_dev, /* The quad port cards have bad CIS's, so just look for a window larger than 8 ports and assume it will be right */ if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) { - *base2 = p_dev->io.BasePort1 + 8; + p_dev->resource[0]->start = cf->io.win[0].base; + p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; + if (!pcmcia_request_io(p_dev)) { + *base2 = p_dev->resource[0]->start + 8; return 0; } } @@ -543,11 +544,11 @@ static int multi_config_check_notpicky(struct pcmcia_device *p_dev, int *base2 = priv_data; if (cf->io.nwin == 2) { - p_dev->io.BasePort1 = cf->io.win[0].base; - p_dev->io.BasePort2 = cf->io.win[1].base; - p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - if (!pcmcia_request_io(p_dev, &p_dev->io)) { - *base2 = p_dev->io.BasePort2; + p_dev->resource[0]->start = cf->io.win[0].base; + p_dev->resource[1]->start = cf->io.win[1].base; + p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK; + if (!pcmcia_request_io(p_dev)) { + *base2 = p_dev->resource[1]->start; return 0; } } @@ -560,22 +561,22 @@ static int multi_config(struct pcmcia_device *link) int i, base2 = 0; /* First, look for a generic full-sized window */ - link->io.NumPorts1 = info->multi * 8; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = info->multi * 8; if (pcmcia_loop_config(link, multi_config_check, &base2)) { /* If that didn't work, look for two windows */ - link->io.NumPorts1 = link->io.NumPorts2 = 8; + link->resource[0]->end = link->resource[1]->end = 8; info->multi = 2; if (pcmcia_loop_config(link, multi_config_check_notpicky, &base2)) { - printk(KERN_NOTICE "serial_cs: no usable port range" + dev_warn(&link->dev, "no usable port range " "found, giving up\n"); return -ENODEV; } } if (!link->irq) - dev_warn(&link->dev, - "serial_cs: no usable IRQ found, continuing...\n"); + dev_warn(&link->dev, "no usable IRQ found, continuing...\n"); /* * Apply any configuration quirks. @@ -599,9 +600,9 @@ static int multi_config(struct pcmcia_device *link) link->conf.ConfigIndex == 3) { err = setup_serial(link, info, base2, link->irq); - base2 = link->io.BasePort1; + base2 = link->resource[0]->start;; } else { - err = setup_serial(link, info, link->io.BasePort1, + err = setup_serial(link, info, link->resource[0]->start, link->irq); } info->c950ctrl = base2; @@ -616,7 +617,7 @@ static int multi_config(struct pcmcia_device *link) return 0; } - setup_serial(link, info, link->io.BasePort1, link->irq); + setup_serial(link, info, link->resource[0]->start, link->irq); for (i = 0; i < info->multi - 1; i++) setup_serial(link, info, base2 + (8 * i), link->irq); @@ -677,6 +678,7 @@ static int serial_config(struct pcmcia_device * link) multifunction cards that ask for appropriate IO port ranges */ if ((info->multi == 0) && (link->has_func_id) && + (link->socket->pcmcia_pfc == 0) && ((link->func_id == CISTPL_FUNCID_MULTI) || (link->func_id == CISTPL_FUNCID_SERIAL))) pcmcia_loop_config(link, serial_check_for_multi, info); @@ -687,7 +689,13 @@ static int serial_config(struct pcmcia_device * link) if (info->quirk && info->quirk->multi != -1) info->multi = info->quirk->multi; - if (info->multi > 1) + dev_info(&link->dev, + "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n", + link->manf_id, link->card_id, + link->socket->pcmcia_pfc, info->multi, info->quirk); + if (link->socket->pcmcia_pfc) + i = pfc_config(link); + else if (info->multi > 1) i = multi_config(link); else i = simple_config(link); @@ -706,7 +714,7 @@ static int serial_config(struct pcmcia_device * link) return 0; failed: - dev_warn(&link->dev, "serial_cs: failed to initialize\n"); + dev_warn(&link->dev, "failed to initialize\n"); serial_remove(link); return -ENODEV; } |