if (!dev->dma_usable)
message("Non dma capable device detected, dma disabled");
if (!r852_enable_dma) {
message("disabling dma on user request");
dev->dma_usable = 0;
}
}
/* * Enable dma. Enables ether first or second stage of the DMA, * Expects dev->dma_dir and dev->dma_state be set
*/ staticvoid r852_dma_enable(struct r852_device *dev)
{
uint8_t dma_reg, dma_irq_reg;
/* Set up dma settings */
dma_reg = r852_read_reg_dword(dev, R852_DMA_SETTINGS);
dma_reg &= ~(R852_DMA_READ | R852_DMA_INTERNAL | R852_DMA_MEMORY);
if (dev->dma_dir)
dma_reg |= R852_DMA_READ;
if (dev->dma_state == DMA_INTERNAL) {
dma_reg |= R852_DMA_INTERNAL; /* Precaution to make sure HW doesn't write */ /* to random kernel memory */
r852_write_reg_dword(dev, R852_DMA_ADDR,
cpu_to_le32(dev->phys_bounce_buffer));
} else {
dma_reg |= R852_DMA_MEMORY;
r852_write_reg_dword(dev, R852_DMA_ADDR,
cpu_to_le32(dev->phys_dma_addr));
}
/* Precaution: make sure write reached the device */
r852_read_reg_dword(dev, R852_DMA_ADDR);
/* * Disable dma, called from the interrupt handler, which specifies * success of the operation via 'error' argument
*/ staticvoid r852_dma_done(struct r852_device *dev, int error)
{
WARN_ON(dev->dma_stage == 0);
/* Precaution to make sure HW doesn't write to random kernel memory */
r852_write_reg_dword(dev, R852_DMA_ADDR,
cpu_to_le32(dev->phys_bounce_buffer));
r852_read_reg_dword(dev, R852_DMA_ADDR);
/* * Wait, till dma is done, which includes both phases of it
*/ staticint r852_dma_wait(struct r852_device *dev)
{ long timeout = wait_for_completion_timeout(&dev->dma_done,
msecs_to_jiffies(1000)); if (!timeout) {
dbg("timeout waiting for DMA interrupt"); return -ETIMEDOUT;
}
return 0;
}
/* * Read/Write one page using dma. Only pages can be read (512 bytes)
*/ staticvoid r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read)
{ int bounce = 0; unsignedlong flags; int error;
dev->dma_error = 0;
/* Set dma direction */
dev->dma_dir = do_read;
dev->dma_stage = 1;
reinit_completion(&dev->dma_done);
/* Set initial dma state: for reading first fill on board buffer,
from device, for writes first fill the buffer from memory*/
dev->dma_state = do_read ? DMA_INTERNAL : DMA_MEMORY;
/* if incoming buffer is not page aligned, we should do bounce */ if ((unsignedlong)buf & (R852_DMA_LEN-1))
bounce = 1;
if (!bounce) {
dev->phys_dma_addr = dma_map_single(&dev->pci_dev->dev, buf,
R852_DMA_LEN,
do_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE); if (dma_mapping_error(&dev->pci_dev->dev, dev->phys_dma_addr))
bounce = 1;
}
if (bounce) {
dbg_verbose("dma: using bounce buffer");
dev->phys_dma_addr = dev->phys_bounce_buffer; if (!do_read)
memcpy(dev->bounce_buffer, buf, R852_DMA_LEN);
}
/* Wait till complete */
error = r852_dma_wait(dev);
if (error) {
r852_dma_done(dev, error); return;
}
if (do_read && bounce)
memcpy((void *)buf, dev->bounce_buffer, R852_DMA_LEN);
}
/* * Program data lines of the nand chip to send data to it
*/ staticvoid r852_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
{ struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
uint32_t reg;
/* Don't allow any access to hardware if we suspect card removal */ if (dev->card_unstable) return;
/* Special case for whole sector read */ if (len == R852_DMA_LEN && dev->dma_usable) {
r852_do_dma(dev, (uint8_t *)buf, 0); return;
}
/* * Read data lines of the nand chip to retrieve data
*/ staticvoid r852_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
{ struct r852_device *dev = r852_get_dev(nand_to_mtd(chip));
uint32_t reg;
if (dev->card_unstable) { /* since we can't signal error here, at least, return
predictable buffer */
memset(buf, 0, len); return;
}
/* special case for whole sector read */ if (len == R852_DMA_LEN && dev->dma_usable) {
r852_do_dma(dev, buf, 1); return;
}
/* read in dword sized chunks */ while (len >= 4) {
/* when write is started, enable write access */ if (dat == NAND_CMD_ERASE1)
dev->ctlreg |= R852_CTL_WRITE;
r852_write_reg(dev, R852_CTL, dev->ctlreg);
}
/* HACK: NAND_CMD_SEQIN is called without NAND_CTRL_CHANGE, but we need
to set write mode */ if (dat == NAND_CMD_SEQIN && (dev->ctlreg & R852_CTL_COMMAND)) {
dev->ctlreg |= R852_CTL_WRITE;
r852_write_reg(dev, R852_CTL, dev->ctlreg);
}
if (dat != NAND_CMD_NONE)
r852_write_reg(dev, R852_DATALINE, dat);
}
/* * Wait till card is ready. * based on nand_wait, but returns errors on DMA error
*/ staticint r852_wait(struct nand_chip *chip)
{ struct r852_device *dev = nand_get_controller_data(chip);
unsignedlong timeout;
u8 status;
timeout = jiffies + msecs_to_jiffies(400);
while (time_before(jiffies, timeout)) if (chip->legacy.dev_ready(chip)) break;
nand_status_op(chip, &status);
/* Unfortunately, no way to send detailed error status... */ if (dev->dma_error) {
status |= NAND_STATUS_FAIL;
dev->dma_error = 0;
} return status;
}
/* * This is copy of nand_read_oob_std * nand_read_oob_syndrome assumes we can send column address - we can't
*/ staticint r852_read_oob(struct nand_chip *chip, int page)
{ struct mtd_info *mtd = nand_to_mtd(chip);
/* * Update card detection IRQ state according to current card state * which is read in r852_card_update_present
*/ staticvoid r852_update_card_detect(struct r852_device *dev)
{ int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE);
dev->card_unstable = 0;
/* * Register the nand device * Called when the card is detected
*/ staticint r852_register_nand_device(struct r852_device *dev)
{ struct mtd_info *mtd = nand_to_mtd(dev->chip);
WARN_ON(dev->card_registered);
mtd->dev.parent = &dev->pci_dev->dev;
if (dev->readonly)
dev->chip->options |= NAND_ROM;
r852_engine_enable(dev);
if (sm_register_device(mtd, dev->sm)) goto error1;
if (device_create_file(&mtd->dev, &dev_attr_media_type)) {
message("can't create media type sysfs attribute"); goto error3;
}
if (card_status & (R852_CARD_IRQ_INSERT|R852_CARD_IRQ_REMOVE)) {
ret = IRQ_HANDLED;
dev->card_detected = !!(card_status & R852_CARD_IRQ_INSERT);
/* we shouldn't receive any interrupts if we wait for card
to settle */
WARN_ON(dev->card_unstable);
/* disable irqs while card is unstable */ /* this will timeout DMA if active, but better that garbage */
r852_disable_irqs(dev);
if (dev->card_unstable) goto out;
/* let, card state to settle a bit, and then do the work */
dev->card_unstable = 1;
queue_delayed_work(dev->card_workqueue,
&dev->card_detect_work, msecs_to_jiffies(100)); goto out;
}
/* Stop detect workqueue -
we are going to unregister the device anyway*/
cancel_delayed_work_sync(&dev->card_detect_work);
destroy_workqueue(dev->card_workqueue);
/* Unregister the device, this might make more IO */
r852_unregister_nand_device(dev);
if (dev->ctlreg & R852_CTL_CARDENABLE) return -EBUSY;
/* First make sure the detect work is gone */
cancel_delayed_work_sync(&dev->card_detect_work);
/* Turn off the interrupts and stop the device */
r852_disable_irqs(dev);
r852_engine_disable(dev);
/* If card was pulled off just during the suspend, which is very unlikely, we will remove it on resume, it too late now
anyway... */
dev->card_unstable = 0; return 0;
}
/* If card status changed, just do the work */ if (dev->card_detected != dev->card_registered) {
dbg("card was %s during low power state",
dev->card_detected ? "added" : "removed");
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.35Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.