pcmcia: use autoconfiguration feature for ioports and iomem

When CONF_AUTO_SET_IO or CONF_AUTO_SET_IOMEM are set, the corresponding
fields in struct pcmcia_device *p_dev->resource[0,1,2] are set
accordinly. Drivers wishing to override certain settings may do so in
the callback function, but they no longer need to parse the CIS entries
stored in cistpl_cftable_entry_t themselves.

CC: netdev@vger.kernel.org
CC: linux-wireless@vger.kernel.org
CC: linux-ide@vger.kernel.org
CC: linux-usb@vger.kernel.org
CC: laforge@gnumonks.org
CC: linux-mtd@lists.infradead.org
CC: linux-bluetooth@vger.kernel.org
CC: alsa-devel@alsa-project.org
CC: linux-serial@vger.kernel.org
CC: Jiri Kosina <jkosina@suse.cz>
CC: linux-scsi@vger.kernel.org
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
Dominik Brodowski
2010-07-30 13:13:46 +02:00
parent 440eed43e2
commit 00990e7ce0
44 changed files with 514 additions and 1024 deletions

View File

@@ -6,7 +6,7 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Copyright (C) 1999 David A. Hinds
* Copyright (C) 2004-2009 Dominik Brodowski
* Copyright (C) 2004-2010 Dominik Brodowski
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -125,13 +125,24 @@ next_entry:
return ret;
}
/**
* pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
*/
static int pcmcia_io_cfg_data_width(unsigned int flags)
{
if (!(flags & CISTPL_IO_8BIT))
return IO_DATA_PATH_WIDTH_16;
if (!(flags & CISTPL_IO_16BIT))
return IO_DATA_PATH_WIDTH_8;
return IO_DATA_PATH_WIDTH_AUTO;
}
struct pcmcia_cfg_mem {
struct pcmcia_device *p_dev;
int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
void *priv_data;
int (*conf_check) (struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data);
cisparse_t parse;
cistpl_cftable_entry_t dflt;
};
@@ -184,16 +195,63 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
p_dev->config_flags |= CONF_ENABLE_SPKR;
return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt,
cfg_mem->priv_data);
/* IO window settings? */
if (flags & CONF_AUTO_SET_IO) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
int i = 0;
p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
if (io->nwin == 0)
return -ENODEV;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
if (io->nwin > 1) {
/* For multifunction cards, by convention, we
* configure the network function with window 0,
* and serial with window 1 */
i = (io->win[1].len > io->win[0].len);
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1-i].base;
p_dev->resource[1]->end = io->win[1-i].len;
}
p_dev->resource[0]->start = io->win[i].base;
p_dev->resource[0]->end = io->win[i].len;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
}
/* MEM window settings? */
if (flags & CONF_AUTO_SET_IOMEM) {
/* so far, we only set one memory window */
cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
if (mem->nwin == 0)
return -ENODEV;
p_dev->resource[2]->start = mem->win[0].host_addr;
p_dev->resource[2]->end = mem->win[0].len;
if (p_dev->resource[2]->end < 0x1000)
p_dev->resource[2]->end = 0x1000;
p_dev->card_addr = mem->win[0].card_addr;
}
dev_dbg(&p_dev->dev,
"checking configuration %x: %pr %pr %pr (%d lines)\n",
p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
p_dev->resource[2], p_dev->io_lines);
return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
}
/**
* pcmcia_loop_config() - loop over configuration options
* @p_dev: the struct pcmcia_device which we need to loop for.
* @conf_check: function to call for each configuration option.
* It gets passed the struct pcmcia_device, the CIS data
* describing the configuration option, and private data
* It gets passed the struct pcmcia_device and private data
* being passed to pcmcia_loop_config()
* @priv_data: private data to be passed to the conf_check function.
*
@@ -203,8 +261,6 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
*/
int pcmcia_loop_config(struct pcmcia_device *p_dev,
int (*conf_check) (struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data),
void *priv_data)
{