aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/gpmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/gpmc.c')
-rw-r--r--arch/arm/mach-omap2/gpmc.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index f46933bc9373..130034bf01d5 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -14,6 +14,7 @@
14 */ 14 */
15#undef DEBUG 15#undef DEBUG
16 16
17#include <linux/irq.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/err.h> 20#include <linux/err.h>
@@ -22,6 +23,7 @@
22#include <linux/spinlock.h> 23#include <linux/spinlock.h>
23#include <linux/io.h> 24#include <linux/io.h>
24#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/interrupt.h>
25 27
26#include <asm/mach-types.h> 28#include <asm/mach-types.h>
27#include <plat/gpmc.h> 29#include <plat/gpmc.h>
@@ -58,7 +60,6 @@
58#define GPMC_CHUNK_SHIFT 24 /* 16 MB */ 60#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
59#define GPMC_SECTION_SHIFT 28 /* 128 MB */ 61#define GPMC_SECTION_SHIFT 28 /* 128 MB */
60 62
61#define PREFETCH_FIFOTHRESHOLD (0x40 << 8)
62#define CS_NUM_SHIFT 24 63#define CS_NUM_SHIFT 24
63#define ENABLE_PREFETCH (0x1 << 7) 64#define ENABLE_PREFETCH (0x1 << 7)
64#define DMA_MPU_MODE 2 65#define DMA_MPU_MODE 2
@@ -100,6 +101,8 @@ static void __iomem *gpmc_base;
100 101
101static struct clk *gpmc_l3_clk; 102static struct clk *gpmc_l3_clk;
102 103
104static irqreturn_t gpmc_handle_irq(int irq, void *dev);
105
103static void gpmc_write_reg(int idx, u32 val) 106static void gpmc_write_reg(int idx, u32 val)
104{ 107{
105 __raw_writel(val, gpmc_base + idx); 108 __raw_writel(val, gpmc_base + idx);
@@ -168,6 +171,16 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
168 return (time_ns * 1000 + tick_ps - 1) / tick_ps; 171 return (time_ns * 1000 + tick_ps - 1) / tick_ps;
169} 172}
170 173
174unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
175{
176 unsigned long tick_ps;
177
178 /* Calculate in picosecs to yield more exact results */
179 tick_ps = gpmc_get_fclk_period();
180
181 return (time_ps + tick_ps - 1) / tick_ps;
182}
183
171unsigned int gpmc_ticks_to_ns(unsigned int ticks) 184unsigned int gpmc_ticks_to_ns(unsigned int ticks)
172{ 185{
173 return ticks * gpmc_get_fclk_period() / 1000; 186 return ticks * gpmc_get_fclk_period() / 1000;
@@ -235,7 +248,7 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
235 int div; 248 int div;
236 u32 l; 249 u32 l;
237 250
238 l = sync_clk * 1000 + (gpmc_get_fclk_period() - 1); 251 l = sync_clk + (gpmc_get_fclk_period() - 1);
239 div = l / gpmc_get_fclk_period(); 252 div = l / gpmc_get_fclk_period();
240 if (div > 4) 253 if (div > 4)
241 return -1; 254 return -1;
@@ -487,6 +500,10 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
487 u32 regval = 0; 500 u32 regval = 0;
488 501
489 switch (cmd) { 502 switch (cmd) {
503 case GPMC_ENABLE_IRQ:
504 gpmc_write_reg(GPMC_IRQENABLE, wval);
505 break;
506
490 case GPMC_SET_IRQ_STATUS: 507 case GPMC_SET_IRQ_STATUS:
491 gpmc_write_reg(GPMC_IRQSTATUS, wval); 508 gpmc_write_reg(GPMC_IRQSTATUS, wval);
492 break; 509 break;
@@ -588,15 +605,19 @@ EXPORT_SYMBOL(gpmc_nand_write);
588/** 605/**
589 * gpmc_prefetch_enable - configures and starts prefetch transfer 606 * gpmc_prefetch_enable - configures and starts prefetch transfer
590 * @cs: cs (chip select) number 607 * @cs: cs (chip select) number
608 * @fifo_th: fifo threshold to be used for read/ write
591 * @dma_mode: dma mode enable (1) or disable (0) 609 * @dma_mode: dma mode enable (1) or disable (0)
592 * @u32_count: number of bytes to be transferred 610 * @u32_count: number of bytes to be transferred
593 * @is_write: prefetch read(0) or write post(1) mode 611 * @is_write: prefetch read(0) or write post(1) mode
594 */ 612 */
595int gpmc_prefetch_enable(int cs, int dma_mode, 613int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
596 unsigned int u32_count, int is_write) 614 unsigned int u32_count, int is_write)
597{ 615{
598 616
599 if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { 617 if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
618 pr_err("gpmc: fifo threshold is not supported\n");
619 return -1;
620 } else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
600 /* Set the amount of bytes to be prefetched */ 621 /* Set the amount of bytes to be prefetched */
601 gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count); 622 gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
602 623
@@ -604,7 +625,7 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
604 * enable the engine. Set which cs is has requested for. 625 * enable the engine. Set which cs is has requested for.
605 */ 626 */
606 gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) | 627 gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
607 PREFETCH_FIFOTHRESHOLD | 628 PREFETCH_FIFOTHRESHOLD(fifo_th) |
608 ENABLE_PREFETCH | 629 ENABLE_PREFETCH |
609 (dma_mode << DMA_MPU_MODE) | 630 (dma_mode << DMA_MPU_MODE) |
610 (0x1 & is_write))); 631 (0x1 & is_write)));
@@ -668,9 +689,11 @@ static void __init gpmc_mem_init(void)
668 } 689 }
669} 690}
670 691
671void __init gpmc_init(void) 692static int __init gpmc_init(void)
672{ 693{
673 u32 l; 694 u32 l, irq;
695 int cs, ret = -EINVAL;
696 int gpmc_irq;
674 char *ck = NULL; 697 char *ck = NULL;
675 698
676 if (cpu_is_omap24xx()) { 699 if (cpu_is_omap24xx()) {
@@ -679,16 +702,19 @@ void __init gpmc_init(void)
679 l = OMAP2420_GPMC_BASE; 702 l = OMAP2420_GPMC_BASE;
680 else 703 else
681 l = OMAP34XX_GPMC_BASE; 704 l = OMAP34XX_GPMC_BASE;
705 gpmc_irq = INT_34XX_GPMC_IRQ;
682 } else if (cpu_is_omap34xx()) { 706 } else if (cpu_is_omap34xx()) {
683 ck = "gpmc_fck"; 707 ck = "gpmc_fck";
684 l = OMAP34XX_GPMC_BASE; 708 l = OMAP34XX_GPMC_BASE;
709 gpmc_irq = INT_34XX_GPMC_IRQ;
685 } else if (cpu_is_omap44xx()) { 710 } else if (cpu_is_omap44xx()) {
686 ck = "gpmc_ck"; 711 ck = "gpmc_ck";
687 l = OMAP44XX_GPMC_BASE; 712 l = OMAP44XX_GPMC_BASE;
713 gpmc_irq = OMAP44XX_IRQ_GPMC;
688 } 714 }
689 715
690 if (WARN_ON(!ck)) 716 if (WARN_ON(!ck))
691 return; 717 return ret;
692 718
693 gpmc_l3_clk = clk_get(NULL, ck); 719 gpmc_l3_clk = clk_get(NULL, ck);
694 if (IS_ERR(gpmc_l3_clk)) { 720 if (IS_ERR(gpmc_l3_clk)) {
@@ -713,6 +739,35 @@ void __init gpmc_init(void)
713 l |= (0x02 << 3) | (1 << 0); 739 l |= (0x02 << 3) | (1 << 0);
714 gpmc_write_reg(GPMC_SYSCONFIG, l); 740 gpmc_write_reg(GPMC_SYSCONFIG, l);
715 gpmc_mem_init(); 741 gpmc_mem_init();
742
743 /* initalize the irq_chained */
744 irq = OMAP_GPMC_IRQ_BASE;
745 for (cs = 0; cs < GPMC_CS_NUM; cs++) {
746 irq_set_chip_and_handler(irq, &dummy_irq_chip,
747 handle_simple_irq);
748 set_irq_flags(irq, IRQF_VALID);
749 irq++;
750 }
751
752 ret = request_irq(gpmc_irq,
753 gpmc_handle_irq, IRQF_SHARED, "gpmc", gpmc_base);
754 if (ret)
755 pr_err("gpmc: irq-%d could not claim: err %d\n",
756 gpmc_irq, ret);
757 return ret;
758}
759postcore_initcall(gpmc_init);
760
761static irqreturn_t gpmc_handle_irq(int irq, void *dev)
762{
763 u8 cs;
764
765 /* check cs to invoke the irq */
766 cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
767 if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
768 generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
769
770 return IRQ_HANDLED;
716} 771}
717 772
718#ifdef CONFIG_ARCH_OMAP3 773#ifdef CONFIG_ARCH_OMAP3