Example #1
0
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;
}
Example #2
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;
}
Example #3
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;
};
Example #4
0
/**
 * 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);
}