Skip to content

Commit

Permalink
pcmcia: introduce autoconfiguration feature
Browse files Browse the repository at this point in the history
Introduce an autoconfiguration feature to set certain values in
pcmcia_loop_config(), instead of copying the same code over and over
in each PCMCIA driver. At first, introduce the following options:

CONF_AUTO_CHECK_VCC	check or matching Vcc entry
CONF_AUTO_SET_VPP	set Vpp
CONF_AUTO_AUDIO		enable the speaker line

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: alsa-devel@alsa-project.org
CC: linux-serial@vger.kernel.org
CC: Jiri Kosina <jkosina@suse.cz>
CC: linux-scsi@vger.kernel.org
Acked-by: Gustavo F. Padovan <padovan@profusion.mobi> (for drivers/bluetooth)
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 9485ee1 commit 440eed4
Show file tree
Hide file tree
Showing 43 changed files with 120 additions and 329 deletions.
23 changes: 3 additions & 20 deletions drivers/ata/pata_pcmcia.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,34 +169,16 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {

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

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

/* Check for matching Vcc, unless we're desperate */
if (!stk->skip_vcc) {
if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
return -ENODEV;
} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
return -ENODEV;
}
}

if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
pdev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
pdev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;

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;
Expand Down Expand Up @@ -249,6 +231,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
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;

/* See if we have a manufacturer identifier. Use it to set is_kme for
vendor quirks */
Expand All @@ -262,10 +245,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
if (!stk)
goto out1;
stk->is_kme = is_kme;
stk->skip_vcc = io_base = ctl_base = 0;
io_base = ctl_base = 0;

if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
stk->skip_vcc = 1;
pdev->config_flags &= ~CONF_AUTO_CHECK_VCC;
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
goto failed; /* No suitable config found */
}
Expand Down
7 changes: 1 addition & 6 deletions drivers/bluetooth/bt3c_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ static int bt3c_probe(struct pcmcia_device *link)
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_VPP;

return bt3c_config(link);
}
Expand All @@ -676,15 +676,11 @@ static void bt3c_detach(struct pcmcia_device *link)
static int bt3c_check_config(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
unsigned long try = (unsigned long) priv_data;

p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;

if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
p_dev->vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
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;
Expand All @@ -697,7 +693,6 @@ static int bt3c_check_config(struct pcmcia_device *p_dev,
static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
Expand Down
7 changes: 1 addition & 6 deletions drivers/bluetooth/btuart_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ static int btuart_probe(struct pcmcia_device *link)
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_VPP;

return btuart_config(link);
}
Expand All @@ -605,15 +605,11 @@ static void btuart_detach(struct pcmcia_device *link)
static int btuart_check_config(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
int *try = priv_data;

p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;

if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
p_dev->vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
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;
Expand All @@ -626,7 +622,6 @@ static int btuart_check_config(struct pcmcia_device *p_dev,
static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
Expand Down
1 change: 0 additions & 1 deletion drivers/bluetooth/dtl1_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,6 @@ static void dtl1_detach(struct pcmcia_device *link)
static int dtl1_confcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
Expand Down
1 change: 0 additions & 1 deletion drivers/char/pcmcia/cm4000_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1744,7 +1744,6 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
static int cm4000_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
if (!cfg->io.nwin)
Expand Down
1 change: 0 additions & 1 deletion drivers/char/pcmcia/cm4040_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,6 @@ static void cm4040_reader_release(struct pcmcia_device *link)
static int cm4040_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
int rc;
Expand Down
1 change: 0 additions & 1 deletion drivers/char/pcmcia/ipwireless/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ static void signalled_reboot_callback(void *callback_data)
static int ipwireless_probe(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
struct ipw_dev *ipw = priv_data;
Expand Down
1 change: 0 additions & 1 deletion drivers/char/pcmcia/synclink_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
if (!cfg->io.nwin)
Expand Down
23 changes: 3 additions & 20 deletions drivers/ide/ide-cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ static int ide_probe(struct pcmcia_device *link)
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;

return ide_config(link);
} /* ide_attach */
Expand Down Expand Up @@ -195,34 +196,16 @@ static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,

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

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

/* Check for matching Vcc, unless we're desperate */
if (!stk->skip_vcc) {
if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
return -ENODEV;
} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
return -ENODEV;
}
}

if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
pdev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
pdev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;

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;
Expand Down Expand Up @@ -271,10 +254,10 @@ static int ide_config(struct pcmcia_device *link)
if (!stk)
goto err_mem;
stk->is_kme = is_kme;
stk->skip_vcc = io_base = ctl_base = 0;
io_base = ctl_base = 0;

if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
stk->skip_vcc = 1;
link->config_flags &= ~CONF_AUTO_CHECK_VCC;
if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
goto failed; /* No suitable config found */
}
Expand Down
1 change: 0 additions & 1 deletion drivers/isdn/hardware/avm/avm_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ static void avmcs_detach(struct pcmcia_device *link)
static int avmcs_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
if (cf->io.nwin <= 0)
Expand Down
1 change: 0 additions & 1 deletion drivers/isdn/hisax/avma1_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ static void __devexit avma1cs_detach(struct pcmcia_device *link)
static int avma1cs_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
if (cf->io.nwin <= 0)
Expand Down
1 change: 0 additions & 1 deletion drivers/isdn/hisax/elsa_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ static void __devexit elsa_cs_detach(struct pcmcia_device *link)
static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
int j;
Expand Down
25 changes: 3 additions & 22 deletions drivers/isdn/hisax/sedlbauer_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,33 +164,11 @@ static void __devexit sedlbauer_detach(struct pcmcia_device *link)
static int sedlbauer_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;

/* Does this card need audio output? */
if (cfg->flags & CISTPL_CFTABLE_AUDIO)
p_dev->config_flags |= CONF_ENABLE_SPKR;

/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
return -ENODEV;
} else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
return -ENODEV;
}

if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;

p_dev->config_flags |= CONF_ENABLE_IRQ;

/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
Expand Down Expand Up @@ -223,6 +201,9 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)

dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);

link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO;

/*
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
Expand Down
1 change: 0 additions & 1 deletion drivers/isdn/hisax/teles_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ static void __devexit teles_detach(struct pcmcia_device *link)
static int teles_cs_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
int j;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/pcmcia/axnet_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ static int try_io_port(struct pcmcia_device *link)
static int axnet_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
int i;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/pcmcia/fmvj18x_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,6 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
static int fmvj18x_ioprobe(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
return 0; /* strange, but that's what the code did already before... */
Expand Down
1 change: 0 additions & 1 deletion drivers/net/pcmcia/pcnet_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,6 @@ static int try_io_port(struct pcmcia_device *link)
static int pcnet_confcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
int *priv = priv_data;
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/pcmcia/smc91c92_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,6 @@ static int mhz_3288_power(struct pcmcia_device *link)
static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
int k;
Expand Down Expand Up @@ -590,7 +589,6 @@ static int mot_setup(struct pcmcia_device *link)
static int smc_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
p_dev->resource[0]->start = cf->io.win[0].base;
Expand Down
5 changes: 2 additions & 3 deletions drivers/net/pcmcia/xirc2ps_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,6 @@ static int
xirc2ps_config_modem(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
unsigned int ioaddr;
Expand All @@ -688,7 +687,6 @@ static int
xirc2ps_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
int *pass = priv_data;
Expand Down Expand Up @@ -826,7 +824,8 @@ xirc2ps_config(struct pcmcia_device * link)
* the Mako if (on the first pass) the COR bit 5 is set.
*/
for (pass=0; pass < 2; pass++)
if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
if (!pcmcia_loop_config(link, xirc2ps_config_check,
&pass))
goto port_found;
/* if special option:
* try to configure as Ethernet only.
Expand Down
17 changes: 3 additions & 14 deletions drivers/net/wireless/airo_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,25 +140,11 @@ static void airo_detach(struct pcmcia_device *link)
static int airo_cs_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
unsigned int vcc,
void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;

/* Does this card need audio output? */
if (cfg->flags & CISTPL_CFTABLE_AUDIO)
p_dev->config_flags |= CONF_ENABLE_SPKR;

/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;

p_dev->config_flags |= CONF_ENABLE_IRQ;

/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
Expand Down Expand Up @@ -193,6 +179,9 @@ static int airo_config(struct pcmcia_device *link)

dev_dbg(&link->dev, "airo_config\n");

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

/*
* In this loop, we scan the CIS for configuration table
* entries, each of which describes a valid card
Expand Down
Loading

0 comments on commit 440eed4

Please sign in to comment.