Skip to content

Commit

Permalink
pcmcia: use autoconfiguration feature for ioports and iomem
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dominik Brodowski committed Sep 29, 2010
1 parent 440eed4 commit 00990e7
Show file tree
Hide file tree
Showing 44 changed files with 515 additions and 1,025 deletions.
12 changes: 12 additions & 0 deletions Documentation/pcmcia/driver-changes.txt
@@ -1,4 +1,16 @@
This file details changes in 2.6 which affect PCMCIA card driver authors:
* pcmcia_loop_config() and autoconfiguration (as of 2.6.36)
If struct pcmcia_device *p_dev->config_flags is set accordingly,
pcmcia_loop_config() now sets up certain configuration values
automatically, though the driver may still override the settings
in the callback function. The following autoconfiguration options
are provided at the moment:
CONF_AUTO_CHECK_VCC : check for matching Vcc
CONF_AUTO_SET_VPP : set Vpp
CONF_AUTO_AUDIO : auto-enable audio line, if required
CONF_AUTO_SET_IO : set ioport resources (->resource[0,1])
CONF_AUTO_SET_IOMEM : set first iomem resource (->resource[2])

* pcmcia_request_configuration -> pcmcia_enable_device (as of 2.6.36)
pcmcia_request_configuration() got renamed to pcmcia_enable_device(),
as it mirrors pcmcia_disable_device(). Configuration settings are now
Expand Down
81 changes: 26 additions & 55 deletions drivers/ata/pata_pcmcia.c
Expand Up @@ -167,45 +167,26 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
};


struct pcmcia_config_check {
unsigned long ctl_base;
int is_kme;
};

static int pcmcia_check_one_config(struct pcmcia_device *pdev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
{
struct pcmcia_config_check *stk = priv_data;

if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
pdev->resource[0]->start = io->win[0].base;
if (!(io->flags & CISTPL_IO_16BIT)) {
pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
}
if (io->nwin == 2) {
pdev->resource[0]->end = 8;
pdev->resource[1]->start = io->win[1].base;
pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
if (pcmcia_request_io(pdev) != 0)
return -ENODEV;
stk->ctl_base = pdev->resource[1]->start;
} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
pdev->resource[0]->end = io->win[0].len;
pdev->resource[1]->end = 0;
if (pcmcia_request_io(pdev) != 0)
return -ENODEV;
stk->ctl_base = pdev->resource[0]->start + 0x0e;
} else
int *is_kme = priv_data;

if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
}
pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;

if (pdev->resource[1]->end) {
pdev->resource[0]->end = 8;
pdev->resource[1]->end = (*is_kme) ? 2 : 1;
} else {
if (pdev->resource[0]->end < 16)
return -ENODEV;
/* If we've got this far, we're done */
return 0;
}
return -ENODEV;

return pcmcia_request_io(pdev);
}

/**
Expand All @@ -220,40 +201,33 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
{
struct ata_host *host;
struct ata_port *ap;
struct pcmcia_config_check *stk = NULL;
int is_kme = 0, ret = -ENOMEM, p;
unsigned long io_base, ctl_base;
void __iomem *io_addr, *ctl_addr;
int n_ports = 1;
struct ata_port_operations *ops = &pcmcia_port_ops;

/* Set up attributes in order to probe card and get resources */
pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
pdev->config_flags |= CONF_ENABLE_IRQ;
pdev->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;

/* See if we have a manufacturer identifier. Use it to set is_kme for
vendor quirks */
is_kme = ((pdev->manf_id == MANFID_KME) &&
((pdev->card_id == PRODID_KME_KXLC005_A) ||
(pdev->card_id == PRODID_KME_KXLC005_B)));

/* Allocate resoure probing structures */

stk = kzalloc(sizeof(*stk), GFP_KERNEL);
if (!stk)
goto out1;
stk->is_kme = is_kme;
io_base = ctl_base = 0;

if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) {
pdev->config_flags &= ~CONF_AUTO_CHECK_VCC;
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme))
goto failed; /* No suitable config found */
}
io_base = pdev->resource[0]->start;
ctl_base = stk->ctl_base;
if (pdev->resource[1]->end)
ctl_base = pdev->resource[1]->start;
else
ctl_base = pdev->resource[0]->start + 0x0e;

if (!pdev->irq)
goto failed;

Expand Down Expand Up @@ -310,13 +284,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
goto failed;

pdev->priv = host;
kfree(stk);
return 0;

failed:
kfree(stk);
pcmcia_disable_device(pdev);
out1:
return ret;
}

Expand Down
53 changes: 27 additions & 26 deletions drivers/bluetooth/bt3c_cs.c
Expand Up @@ -656,10 +656,8 @@ static int bt3c_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;

link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 8;

link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
CONF_AUTO_SET_IO;

return bt3c_config(link);
}
Expand All @@ -673,38 +671,41 @@ static void bt3c_detach(struct pcmcia_device *link)
kfree(info);
}

static int bt3c_check_config(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
unsigned long try = (unsigned long) priv_data;
p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
int *try = priv_data;

if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
(cf->io.win[0].base != 0)) {
p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
if (try == 0)
p_dev->io_lines = 16;

if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
return -EINVAL;

p_dev->resource[0]->end = 8;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;

return pcmcia_request_io(p_dev);
}

static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
int j;

if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
if (p_dev->io_lines > 3)
return -ENODEV;

p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = 8;

for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
}
Expand Down
51 changes: 26 additions & 25 deletions drivers/bluetooth/btuart_cs.c
Expand Up @@ -585,10 +585,8 @@ static int btuart_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;

link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 8;

link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
CONF_AUTO_SET_IO;

return btuart_config(link);
}
Expand All @@ -602,38 +600,41 @@ static void btuart_detach(struct pcmcia_device *link)
kfree(info);
}

static int btuart_check_config(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
int *try = priv_data;
p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;

if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
(cf->io.win[0].base != 0)) {
p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
if (try == 0)
p_dev->io_lines = 16;

if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
return -EINVAL;

p_dev->resource[0]->end = 8;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;

return pcmcia_request_io(p_dev);
}

static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
int j;

if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
if (p_dev->io_lines > 3)
return -ENODEV;

p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = 8;

for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
}
Expand Down
18 changes: 6 additions & 12 deletions drivers/bluetooth/dtl1_cs.c
Expand Up @@ -571,10 +571,7 @@ static int dtl1_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;

link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 8;

link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;

return dtl1_config(link);
}
Expand All @@ -589,17 +586,14 @@ static void dtl1_detach(struct pcmcia_device *link)
kfree(info);
}

static int dtl1_confcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
{
if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
if ((p_dev->resource[1]->end) || (p_dev->resource[1]->end < 8))
return -ENODEV;

p_dev->resource[0]->start = cf->io.win[0].base;
p_dev->resource[0]->end = cf->io.win[0].len; /*yo */
p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;

return pcmcia_request_io(p_dev);
}

Expand Down
15 changes: 3 additions & 12 deletions drivers/char/pcmcia/cm4000_cs.c
Expand Up @@ -1741,26 +1741,17 @@ static void cmm_cm4000_release(struct pcmcia_device * link)

/*==== Interface to PCMCIA Layer =======================================*/

static int cm4000_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if (!cfg->io.nwin)
return -ENODEV;

p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;

return pcmcia_request_io(p_dev);
}

static int cm4000_config(struct pcmcia_device * link, int devno)
{
struct cm4000_dev *dev;

link->config_flags |= CONF_AUTO_SET_IO;

/* read the config-tuples */
if (pcmcia_loop_config(link, cm4000_config_check, NULL))
goto cs_release;
Expand Down
22 changes: 4 additions & 18 deletions drivers/char/pcmcia/cm4040_cs.c
Expand Up @@ -515,25 +515,9 @@ static void cm4040_reader_release(struct pcmcia_device *link)
return;
}

static int cm4040_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
int rc;
if (!cfg->io.nwin)
return -ENODEV;

/* Get the IOaddr */
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
rc = pcmcia_request_io(p_dev);

dev_printk(KERN_INFO, &p_dev->dev,
"pcmcia_request_io returned 0x%x\n", rc);
return rc;
return pcmcia_request_io(p_dev);
}


Expand All @@ -542,6 +526,8 @@ static int reader_config(struct pcmcia_device *link, int devno)
struct reader_dev *dev;
int fail_rc;

link->config_flags |= CONF_AUTO_SET_IO;

if (pcmcia_loop_config(link, cm4040_config_check, NULL))
goto cs_release;

Expand Down

0 comments on commit 00990e7

Please sign in to comment.