/* 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; }
/* 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; }
/* 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; }
/* 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); }
/* 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; }