Exemplo n.º 1
0
/* Enable/disable device */
static int r592_enable_device(struct r592_device *dev, bool enable)
{
	dbg("%sabling the device", enable ? "en" : "dis");

	if (enable) {

		/* Power up the card */
		r592_write_reg(dev, R592_POWER, R592_POWER_0 | R592_POWER_1);

		/* Perform a reset */
		r592_set_reg_mask(dev, R592_IO, R592_IO_RESET);

		msleep(100);
	} else
		/* Power down the card */
		r592_write_reg(dev, R592_POWER, 0);

	return 0;
}
Exemplo n.º 2
0
/* Interrupt handler */
static irqreturn_t r592_irq(int irq, void *data)
{
    struct r592_device *dev = (struct r592_device *)data;
    irqreturn_t ret = IRQ_NONE;
    u32 reg;
    u16 irq_enable, irq_status;
    unsigned long flags;
    int error;

    spin_lock_irqsave(&dev->irq_lock, flags);

    reg = r592_read_reg(dev, R592_REG_MSC);
    irq_enable = reg >> 16;
    irq_status = reg & 0xFFFF;

    /* Ack the interrupts */
    reg &= ~irq_status;
    r592_write_reg(dev, R592_REG_MSC, reg);

    /* Get the IRQ status minus bits that aren't enabled */
    irq_status &= (irq_enable);

    /* Due to limitation of memstick core, we don't look at bits that
    	indicate that card was removed/inserted and/or present */
    if (irq_status & (R592_REG_MSC_IRQ_INSERT | R592_REG_MSC_IRQ_REMOVE)) {

        bool card_was_added = irq_status & R592_REG_MSC_IRQ_INSERT;
        ret = IRQ_HANDLED;

        message("IRQ: card %s", card_was_added ? "added" : "removed");

        mod_timer(&dev->detect_timer,
                  jiffies + msecs_to_jiffies(card_was_added ? 500 : 50));
    }

    if (irq_status &
            (R592_REG_MSC_FIFO_DMA_DONE | R592_REG_MSC_FIFO_DMA_ERR)) {
        ret = IRQ_HANDLED;

        if (irq_status & R592_REG_MSC_FIFO_DMA_ERR) {
            message("IRQ: DMA error");
            error = -EIO;
        } else {
            dbg_verbose("IRQ: dma done");
            error = 0;
        }

        r592_stop_dma(dev, error);
        complete(&dev->dma_done);
    }

    spin_unlock_irqrestore(&dev->irq_lock, flags);
    return ret;
}
Exemplo n.º 3
0
/* Cleanups DMA related settings */
static void r592_stop_dma(struct r592_device *dev, int error)
{
    r592_clear_reg_mask(dev, R592_FIFO_DMA_SETTINGS,
                        R592_FIFO_DMA_SETTINGS_EN);

    /* This is only a precation */
    r592_write_reg(dev, R592_FIFO_DMA,
                   dev->dummy_dma_page_physical_address);

    r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_EN_MASK);
    r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_ACK_MASK);
    dev->dma_error = error;
}
Exemplo n.º 4
0
/* eg, if card is detected, arm it to detect removal, and vice versa */
static void r592_update_card_detect(struct r592_device *dev)
{
    u32 reg = r592_read_reg(dev, R592_REG_MSC);
    bool card_detected = reg & R592_REG_MSC_PRSNT;

    dbg("update card detect. card state: %s", card_detected ?
        "present" : "absent");

    reg &= ~((R592_REG_MSC_IRQ_REMOVE | R592_REG_MSC_IRQ_INSERT) << 16);

    if (card_detected)
        reg |= (R592_REG_MSC_IRQ_REMOVE << 16);
    else
        reg |= (R592_REG_MSC_IRQ_INSERT << 16);

    r592_write_reg(dev, R592_REG_MSC, reg);
}
Exemplo n.º 5
0
/* Executes one TPC (data is read/written from small or large fifo) */
static void r592_execute_tpc(struct r592_device *dev)
{
    bool is_write;
    int len, error;
    u32 status, reg;

    if (!dev->req) {
        message("BUG: tpc execution without request!");
        return;
    }

    is_write = dev->req->tpc >= MS_TPC_SET_RW_REG_ADRS;
    len = dev->req->long_data ?
          dev->req->sg.length : dev->req->data_len;

    /* Ensure that FIFO can hold the input data */
    if (len > R592_LFIFO_SIZE) {
        message("IO: hardware doesn't support TPCs longer that 512");
        error = -ENOSYS;
        goto out;
    }

    if (!(r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_PRSNT)) {
        dbg("IO: refusing to send TPC because card is absent");
        error = -ENODEV;
        goto out;
    }

    dbg("IO: executing %s LEN=%d",
        memstick_debug_get_tpc_name(dev->req->tpc), len);

    /* Set IO direction */
    if (is_write)
        r592_set_reg_mask(dev, R592_IO, R592_IO_DIRECTION);
    else
        r592_clear_reg_mask(dev, R592_IO, R592_IO_DIRECTION);


    error = r592_test_fifo_empty(dev);
    if (error)
        goto out;

    /* Transfer write data */
    if (is_write) {
        error = r592_transfer_fifo_dma(dev);
        if (error == -EINVAL)
            error = r592_transfer_fifo_pio(dev);
    }

    if (error)
        goto out;

    /* Trigger the TPC */
    reg = (len << R592_TPC_EXEC_LEN_SHIFT) |
          (dev->req->tpc << R592_TPC_EXEC_TPC_SHIFT) |
          R592_TPC_EXEC_BIG_FIFO;

    r592_write_reg(dev, R592_TPC_EXEC, reg);

    /* Wait for TPC completion */
    status = R592_STATUS_RDY;
    if (dev->req->need_card_int)
        status |= R592_STATUS_CED;

    error = r592_wait_status(dev, status, status);
    if (error) {
        message("card didn't respond");
        goto out;
    }

    /* Test IO errors */
    error = r592_test_io_error(dev);
    if (error) {
        dbg("IO error");
        goto out;
    }

    /* Read data from FIFO */
    if (!is_write) {
        error = r592_transfer_fifo_dma(dev);
        if (error == -EINVAL)
            error = r592_transfer_fifo_pio(dev);
    }

    /* read INT reg. This can be shortened with shifts, but that way
    	its more readable */
    if (dev->parallel_mode && dev->req->need_card_int) {

        dev->req->int_reg = 0;
        status = r592_read_reg(dev, R592_STATUS);

        if (status & R592_STATUS_P_CMDNACK)
            dev->req->int_reg |= MEMSTICK_INT_CMDNAK;
        if (status & R592_STATUS_P_BREQ)
            dev->req->int_reg |= MEMSTICK_INT_BREQ;
        if (status & R592_STATUS_P_INTERR)
            dev->req->int_reg |= MEMSTICK_INT_ERR;
        if (status & R592_STATUS_P_CED)
            dev->req->int_reg |= MEMSTICK_INT_CED;
    }

    if (error)
        dbg("FIFO read error");
out:
    dev->req->error = error;
    r592_clear_reg_mask(dev, R592_REG_MSC, R592_REG_MSC_LED);
    return;
}