/*
 * wait for SPI engine while it is busy
 */
static int pcan_wait_spi_busy(struct pcan_pccard *card)
{
	unsigned long timeout = jiffies +
				msecs_to_jiffies(PCC_SPI_MAX_BUSY_WAIT_MS) + 1;

	/* be sure to read status at least once after sleeping */
	while (pcan_read_reg(card, PCC_CSR) & PCC_CSR_SPI_BUSY) {
		if (time_after(jiffies, timeout))
			return -EBUSY;
		schedule();
	}

	return 0;
}
/*
 * setup PCMCIA socket and probe for PEAK-System PC-CARD
 */
static int __devinit pcan_probe(struct pcmcia_device *pdev)
{
	struct pcan_pccard *card;
	int err;

	pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;

	err = pcmcia_loop_config(pdev, pcan_conf_check, NULL);
	if (err) {
		dev_err(&pdev->dev, "pcmcia_loop_config() error %d\n", err);
		goto probe_err_1;
	}

	if (!pdev->irq) {
		dev_err(&pdev->dev, "no irq assigned\n");
		err = -ENODEV;
		goto probe_err_1;
	}

	err = pcmcia_enable_device(pdev);
	if (err) {
		dev_err(&pdev->dev, "pcmcia_enable_device failed err=%d\n",
			err);
		goto probe_err_1;
	}

	card = kzalloc(sizeof(struct pcan_pccard), GFP_KERNEL);
	if (!card) {
		dev_err(&pdev->dev, "couldn't allocate card memory\n");
		err = -ENOMEM;
		goto probe_err_2;
	}

	card->pdev = pdev;
	pdev->priv = card;

	/* sja1000 api uses iomem */
	card->ioport_addr = ioport_map(pdev->resource[0]->start,
					resource_size(pdev->resource[0]));
	if (!card->ioport_addr) {
		dev_err(&pdev->dev, "couldn't map io port into io memory\n");
		err = -ENOMEM;
		goto probe_err_3;
	}
	card->fw_major = pcan_read_reg(card, PCC_FW_MAJOR);
	card->fw_minor = pcan_read_reg(card, PCC_FW_MINOR);

	/* display board name and firware version */
	dev_info(&pdev->dev, "PEAK-System pcmcia card %s fw %d.%d\n",
		pdev->prod_id[1] ? pdev->prod_id[1] : "PCAN-PC Card",
		card->fw_major, card->fw_minor);

	/* detect available channels */
	pcan_add_channels(card);
	if (!card->chan_count)
		goto probe_err_4;

	/* init the timer which controls the leds */
	init_timer(&card->led_timer);
	card->led_timer.function = pcan_led_timer;
	card->led_timer.data = (unsigned long)card;

	/* request the given irq */
	err = request_irq(pdev->irq, &pcan_isr, IRQF_SHARED, PCC_NAME, card);
	if (err) {
		dev_err(&pdev->dev, "couldn't request irq%d\n", pdev->irq);
		goto probe_err_5;
	}

	/* power on the connectors */
	pcan_set_can_power(card, 1);

	return 0;

probe_err_5:
	/* unregister can devices from network */
	pcan_free_channels(card);

probe_err_4:
	ioport_unmap(card->ioport_addr);

probe_err_3:
	kfree(card);
	pdev->priv = NULL;

probe_err_2:
	pcmcia_disable_device(pdev);

probe_err_1:
	return err;
}
/*
 * write data in device eeprom
 */
static int pcan_write_eeprom(struct pcan_pccard *card, u16 addr, u8 v)
{
	u8 status;
	int err, i;

	/* write instruction enabling write */
	pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_WREN);
	err = pcan_wait_spi_busy(card);
	if (err)
		goto we_spi_err;

	/* wait until write enabled */
	for (i = 0; i < PCC_WRITE_MAX_LOOP; i++) {
		/* write instruction reading the status register */
		pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_RDSR);
		err = pcan_wait_spi_busy(card);
		if (err)
			goto we_spi_err;

		/* get status register value and check write enable bit */
		status = pcan_read_reg(card, PCC_SPI_DIR);
		if (status & PCC_EEP_SR_WEN)
			break;
	}

	if (i >= PCC_WRITE_MAX_LOOP) {
		dev_err(&card->pdev->dev,
			"stop waiting to be allowed to write in eeprom\n");
		return -EIO;
	}

	/* set address and data */
	pcan_write_reg(card, PCC_SPI_ADR, addr & 0xff);
	pcan_write_reg(card, PCC_SPI_DOR, v);

	/*
	 * write instruction with bit[3] set according to address value:
	 * if addr refers to upper half of the memory array: bit[3] = 1
	 */
	pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_WRITE(addr));
	err = pcan_wait_spi_busy(card);
	if (err)
		goto we_spi_err;

	/* wait while write in progress */
	for (i = 0; i < PCC_WRITE_MAX_LOOP; i++) {
		/* write instruction reading the status register */
		pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_RDSR);
		err = pcan_wait_spi_busy(card);
		if (err)
			goto we_spi_err;

		/* get status register value and check write in progress bit */
		status = pcan_read_reg(card, PCC_SPI_DIR);
		if (!(status & PCC_EEP_SR_WIP))
			break;
	}

	if (i >= PCC_WRITE_MAX_LOOP) {
		dev_err(&card->pdev->dev,
			"stop waiting for write in eeprom to complete\n");
		return -EIO;
	}

	/* write instruction disabling write */
	pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_WRDI);
	err = pcan_wait_spi_busy(card);
	if (err)
		goto we_spi_err;

	return 0;

we_spi_err:
	dev_err(&card->pdev->dev,
		"stop waiting (spi engine always busy) err %d\n", err);

	return err;
}
/*
 * check whether the card is present by checking its fw version numbers
 * against values read at probing time.
 */
static inline int pcan_pccard_present(struct pcan_pccard *card)
{
	return ((pcan_read_reg(card, PCC_FW_MAJOR) == card->fw_major) &&
		(pcan_read_reg(card, PCC_FW_MINOR) == card->fw_minor));
}
static int pcan_write_eeprom(struct pcan_pccard *card, u16 addr, u8 v)
{
	u8 status;
	int err, i;

	
	pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_WREN);
	err = pcan_wait_spi_busy(card);
	if (err)
		goto we_spi_err;

	
	for (i = 0; i < PCC_WRITE_MAX_LOOP; i++) {
		
		pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_RDSR);
		err = pcan_wait_spi_busy(card);
		if (err)
			goto we_spi_err;

		
		status = pcan_read_reg(card, PCC_SPI_DIR);
		if (status & PCC_EEP_SR_WEN)
			break;
	}

	if (i >= PCC_WRITE_MAX_LOOP) {
		dev_err(&card->pdev->dev,
			"stop waiting to be allowed to write in eeprom\n");
		return -EIO;
	}

	
	pcan_write_reg(card, PCC_SPI_ADR, addr & 0xff);
	pcan_write_reg(card, PCC_SPI_DOR, v);

	pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_WRITE(addr));
	err = pcan_wait_spi_busy(card);
	if (err)
		goto we_spi_err;

	
	for (i = 0; i < PCC_WRITE_MAX_LOOP; i++) {
		
		pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_RDSR);
		err = pcan_wait_spi_busy(card);
		if (err)
			goto we_spi_err;

		
		status = pcan_read_reg(card, PCC_SPI_DIR);
		if (!(status & PCC_EEP_SR_WIP))
			break;
	}

	if (i >= PCC_WRITE_MAX_LOOP) {
		dev_err(&card->pdev->dev,
			"stop waiting for write in eeprom to complete\n");
		return -EIO;
	}

	
	pcan_write_reg(card, PCC_SPI_IR, PCC_EEP_WRDI);
	err = pcan_wait_spi_busy(card);
	if (err)
		goto we_spi_err;

	return 0;

we_spi_err:
	dev_err(&card->pdev->dev,
		"stop waiting (spi engine always busy) err %d\n", err);

	return err;
}