MTD: OneNAND: S5PC110: Implement DMA interrupt method
PATCH 1/1 MTD: OneNAND: S5PC110: Implement DMA interrupt method
From: Kyungmin Park <[email protected]>
Implement DMA interrupt method. previous time it polls the DMA status. It can reduce the CPU power but decrease the performance a little.
--- drivers/mtd/onenand/samsung.c | 85 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 84 insertions(+), 1 deletions(-)
drivers/mtd/onenand/samsung.c +84 -1
@@ -22,6 +22,7 @@#include <linux/mtd/onenand.h> #include <linux/mtd/partitions.h> #include <linux/dma-mapping.h> +#include <linux/interrupt.h> #include <asm/mach/flash.h> #include <plat/regs-onenand.h>
@@ -81,6 +82,17 @@ enum soc_type {#define S5PC110_DMA_TRANS_CMD 0x418#define S5PC110_DMA_TRANS_STATUS 0x41C#define S5PC110_DMA_TRANS_DIR 0x420 +#define S5PC110_INTC_DMA_CLR 0x1004 +#define S5PC110_INTC_ONENAND_CLR 0x1008 +#define S5PC110_INTC_DMA_MASK 0x1024 +#define S5PC110_INTC_ONENAND_MASK 0x1028 +#define S5PC110_INTC_DMA_PEND 0x1044 +#define S5PC110_INTC_ONENAND_PEND 0x1048 +#define S5PC110_INTC_DMA_STATUS 0x1064 +#define S5PC110_INTC_ONENAND_STATUS 0x1068 + +#define S5PC110_INTC_DMA_TD (1 << 24) +#define S5PC110_INTC_DMA_TE (1 << 16)#define S5PC110_DMA_CFG_SINGLE (0x0 << 16)#define S5PC110_DMA_CFG_4BURST (0x2 << 16)
@@ -134,6 +146,7 @@ struct s3c_onenand {void __iomem *dma_addr;struct resource *dma_res;unsigned long phys_base; +struct completion complete;#ifdef CONFIG_MTD_PARTITIONS struct mtd_partition *parts;#endif
@@ -531,7 +544,9 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area,return 0 ; } -static int s5pc110_dma_ops (void *dst,void *src,size_t count,int direction) +static int (*s5pc110_dma_ops)(void *dst,void *src,size_t count,int direction); + +static int s5pc110_dma_poll (void *dst,void *src,size_t count,int direction) {void __iomem *base = onenand->dma_addr;int status;
@@ -575,6 +590,60 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction)return 0 ; } +static irqreturn_t s5pc110_onenand_irq (int irq,void *data) +{ +void __iomem *base = onenand->dma_addr; +int status, cmd =0 ; + + status =readl (base +S5PC110_INTC_DMA_STATUS ); + +if (likely (status &S5PC110_INTC_DMA_TD )) + cmd =S5PC110_DMA_TRANS_CMD_TDC ; + +if (unlikely (status &S5PC110_INTC_DMA_TE )) + cmd =S5PC110_DMA_TRANS_CMD_TEC ; + +writel (cmd, base +S5PC110_DMA_TRANS_CMD ); +writel (status, base +S5PC110_INTC_DMA_CLR ); + +if (!onenand->complete.done) +complete (&onenand->complete); + +return IRQ_HANDLED ; +} + +static int s5pc110_dma_irq (void *dst,void *src,size_t count,int direction) +{ +void __iomem *base = onenand->dma_addr; +int status; + + status =readl (base +S5PC110_INTC_DMA_MASK ); +if (status) { + status &= ~(S5PC110_INTC_DMA_TD |S5PC110_INTC_DMA_TE ); +writel (status, base +S5PC110_INTC_DMA_MASK ); + } + +writel (src, base +S5PC110_DMA_SRC_ADDR ); +writel (dst, base +S5PC110_DMA_DST_ADDR ); + +if (direction ==S5PC110_DMA_DIR_READ ) { +writel (S5PC110_DMA_SRC_CFG_READ , base +S5PC110_DMA_SRC_CFG ); +writel (S5PC110_DMA_DST_CFG_READ , base +S5PC110_DMA_DST_CFG ); + }else { +writel (S5PC110_DMA_SRC_CFG_WRITE , base +S5PC110_DMA_SRC_CFG ); +writel (S5PC110_DMA_DST_CFG_WRITE , base +S5PC110_DMA_DST_CFG ); + } + +writel (count, base +S5PC110_DMA_TRANS_SIZE ); +writel (direction, base +S5PC110_DMA_TRANS_DIR ); + +writel (S5PC110_DMA_TRANS_CMD_TR , base +S5PC110_DMA_TRANS_CMD ); + +wait_for_completion_timeout (&onenand->complete,msecs_to_jiffies (20 )); + +return 0 ; +} +static int s5pc110_read_bufferram (struct mtd_info *mtd,int area,unsigned char *buffer,int offset,size_t count) {
@@ -919,6 +988,20 @@ static int s3c_onenand_probe(struct platform_device *pdev) } onenand->phys_base = onenand->base_res->start; + + s5pc110_dma_ops = s5pc110_dma_poll; +/* Interrupt support */ + r =platform_get_resource (pdev,IORESOURCE_IRQ ,0 ); +if (r) { +init_completion (&onenand->complete); + s5pc110_dma_ops = s5pc110_dma_irq; + err =request_irq (r->start, s5pc110_onenand_irq, +IRQF_SHARED ,"onenand" , &onenand); +if (err) { +dev_err (&pdev->dev,"failed to get irq\n" ); + goto scan_failed; + } + } }if (onenand_scan (mtd,1 )) {
Signature · 1 line
1.5.3.3
Quoted 6 lines · Kyungmin Park
From: Kyungmin Park <[email protected]>
Implement DMA interrupt method. previous time it polls the DMA status. It can reduce the CPU power but decrease the performance a little.
Signed-off-by Kyungmin Park <[email protected]>
Does not apply to the l2 tree. Also it is not clear at all whether it depends on the previous series or it is completely independent. Please, re-send with the other patches which I did not take yet.
Signature · 2 lines
Best Regards, Artem Bityutskiy (Артём Битюцкий)
Quoted 11 lines · Artem Bityutskiy
Quoted 6 lines · Kyungmin Park
From: Kyungmin Park <[email protected]>
Implement DMA interrupt method. previous time it polls the DMA status. It can reduce the CPU power but decrease the performance a little.
Signed-off-by Kyungmin Park <[email protected]>Does not apply to the l2 tree. Also it is not clear at all whether it depends on the previous series or it is completely independent. Please, re-send with the other patches which I did not take yet.
It's dependent on previous patches, I think these patches including previous are for 2.6.37.
Okay I'll re-send based on l2 tree.
Thank you,
Kyungmin Park
Quoted 6 lines
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)