aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2010-02-26 19:04:02 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-03-08 21:31:18 -0500
commitfb45d3232c641bfee5000c8a81e2005903734702 (patch)
tree726df94625464228e8aad7ad208552f6aa2f7672 /drivers
parentd4080cb32ee3d2ed18aa69ffde6010524bd686cd (diff)
mtd: r852: Few fixes for problems that occur when card is rapidly inserted/removed.
First don't enable card detection logic to early. Second be very careful with DMA engine, to be sure it doesn't write to kernel memory driver doesn't own. Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/nand/r852.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 218a42dadff1..cb271167b4a5 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -96,14 +96,21 @@ static void r852_dma_enable(struct r852_device *dev)
96 if (dev->dma_dir) 96 if (dev->dma_dir)
97 dma_reg |= R852_DMA_READ; 97 dma_reg |= R852_DMA_READ;
98 98
99 if (dev->dma_state == DMA_INTERNAL) 99 if (dev->dma_state == DMA_INTERNAL) {
100 dma_reg |= R852_DMA_INTERNAL; 100 dma_reg |= R852_DMA_INTERNAL;
101 else { 101 /* Precaution to make sure HW doesn't write */
102 /* to random kernel memory */
103 r852_write_reg_dword(dev, R852_DMA_ADDR,
104 cpu_to_le32(dev->phys_bounce_buffer));
105 } else {
102 dma_reg |= R852_DMA_MEMORY; 106 dma_reg |= R852_DMA_MEMORY;
103 r852_write_reg_dword(dev, R852_DMA_ADDR, 107 r852_write_reg_dword(dev, R852_DMA_ADDR,
104 cpu_to_le32(dev->phys_dma_addr)); 108 cpu_to_le32(dev->phys_dma_addr));
105 } 109 }
106 110
111 /* Precaution: make sure write reached the device */
112 r852_read_reg_dword(dev, R852_DMA_ADDR);
113
107 r852_write_reg_dword(dev, R852_DMA_SETTINGS, dma_reg); 114 r852_write_reg_dword(dev, R852_DMA_SETTINGS, dma_reg);
108 115
109 /* Set dma irq */ 116 /* Set dma irq */
@@ -129,6 +136,11 @@ static void r852_dma_done(struct r852_device *dev, int error)
129 r852_write_reg_dword(dev, R852_DMA_SETTINGS, 0); 136 r852_write_reg_dword(dev, R852_DMA_SETTINGS, 0);
130 r852_write_reg_dword(dev, R852_DMA_IRQ_ENABLE, 0); 137 r852_write_reg_dword(dev, R852_DMA_IRQ_ENABLE, 0);
131 138
139 /* Precaution to make sure HW doesn't write to random kernel memory */
140 r852_write_reg_dword(dev, R852_DMA_ADDR,
141 cpu_to_le32(dev->phys_bounce_buffer));
142 r852_read_reg_dword(dev, R852_DMA_ADDR);
143
132 dev->dma_error = error; 144 dev->dma_error = error;
133 dev->dma_stage = 0; 145 dev->dma_stage = 0;
134 146
@@ -579,6 +591,7 @@ void r852_card_update_present(struct r852_device *dev)
579void r852_update_card_detect(struct r852_device *dev) 591void r852_update_card_detect(struct r852_device *dev)
580{ 592{
581 int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE); 593 int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE);
594 dev->card_unstable = 0;
582 595
583 card_detect_reg &= ~(R852_CARD_IRQ_REMOVE | R852_CARD_IRQ_INSERT); 596 card_detect_reg &= ~(R852_CARD_IRQ_REMOVE | R852_CARD_IRQ_INSERT);
584 card_detect_reg |= R852_CARD_IRQ_GENABLE; 597 card_detect_reg |= R852_CARD_IRQ_GENABLE;
@@ -690,10 +703,10 @@ void r852_card_detect_work(struct work_struct *work)
690 struct r852_device *dev = 703 struct r852_device *dev =
691 container_of(work, struct r852_device, card_detect_work.work); 704 container_of(work, struct r852_device, card_detect_work.work);
692 705
693 r852_update_card_detect(dev); 706 r852_card_update_present(dev);
694 dev->card_unstable = 0; 707 dev->card_unstable = 0;
695 708
696 /* false alarm */ 709 /* False alarm */
697 if (dev->card_detected == dev->card_registred) 710 if (dev->card_detected == dev->card_registred)
698 goto exit; 711 goto exit;
699 712