static int das08_pcmcia_config_loop(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; /* Do we need to allocate an interrupt? */ p_dev->conf.Attributes |= 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)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(io->flags); p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; p_dev->resource[0]->start = io->win[0].base; p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { p_dev->resource[1]->flags = p_dev->resource[0]->flags; p_dev->resource[1]->start = io->win[1].base; p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ return pcmcia_request_io(p_dev); } return 0; }
/*====================================================================== sedlbauer_config() is scheduled to run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the device available to the system. ======================================================================*/ 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->conf.Attributes |= CONF_ENABLE_SPKR; p_dev->conf.Status = CCSR_AUDIO_ENA; } /* 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->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; p_dev->conf.Attributes |= 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)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; p_dev->resource[0]->start = io->win[0].base; p_dev->resource[0]->end = io->win[0].len; 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) { p_dev->resource[1]->flags = p_dev->resource[0]->flags; p_dev->resource[1]->start = io->win[1].base; p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ p_dev->io_lines = 3; if (pcmcia_request_io(p_dev) != 0) return -ENODEV; } return 0; }
static int spectrum_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) goto next_entry; /* 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) { DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", __func__, vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); if (!ignore_cis_vcc) goto next_entry; } } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", __func__, vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); if (!ignore_cis_vcc) goto next_entry; } } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; /* Do we need to allocate an interrupt? */ p_dev->conf.Attributes |= 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)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(io->flags); p_dev->resource[0]->start = io->win[0].base; p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { p_dev->resource[1]->flags = p_dev->resource[0]->flags; p_dev->resource[1]->start = io->win[1].base; p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ if (pcmcia_request_io(p_dev) != 0) goto next_entry; } return 0; next_entry: pcmcia_disable_device(p_dev); return -ENODEV; };
/** * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config() * * pcmcia_do_loop_config() is the internal callback for the call from * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred * by a struct pcmcia_cfg_mem. */ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) { struct pcmcia_cfg_mem *cfg_mem = priv; struct pcmcia_device *p_dev = cfg_mem->p_dev; cistpl_cftable_entry_t *cfg = &parse->cftable_entry; cistpl_cftable_entry_t *dflt = &cfg_mem->dflt; unsigned int flags = p_dev->config_flags; unsigned int vcc = p_dev->socket->socket.Vcc; dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n", cfg->index, flags); /* default values */ cfg_mem->p_dev->config_index = cfg->index; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) cfg_mem->dflt = *cfg; /* check for matching Vcc? */ if (flags & CONF_AUTO_CHECK_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; } } /* set Vpp? */ if (flags & CONF_AUTO_SET_VPP) { 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; } /* enable audio? */ if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO)) p_dev->config_flags |= CONF_ENABLE_SPKR; /* 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); }