aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAfzal Mohammed <afzal@ti.com>2012-08-30 15:53:23 -0400
committerTony Lindgren <tony@atomide.com>2012-08-30 15:53:23 -0400
commit6b6c32fc96d5a0ef1e8c5d9f1b24c3a07b878f6d (patch)
treeea85bc0836bccadbeb144aa648df6658be589cc6
parentd65ccb6da60ac8f38ef6eb10ac53d94f28e0f3b1 (diff)
ARM: OMAP2+: gpmc: Modify interrupt handling
Modify interrupt handling such that interrupts can be handled by GPMC client drivers using standard interrupt APIs rather than requiring the drivers to have knowledge about GPMC interrupt handling. Currently only NAND related interrupts has been considered (which is the case even without this change) as the only user of GPMC interrupt is NAND. Signed-off-by: Afzal Mohammed <afzal@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
-rw-r--r--arch/arm/mach-omap2/gpmc.c136
-rw-r--r--arch/arm/plat-omap/include/plat/gpmc.h1
2 files changed, 120 insertions, 17 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5cce9b00c13e..39c30d9bafd9 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -78,6 +78,15 @@
78#define ENABLE_PREFETCH (0x1 << 7) 78#define ENABLE_PREFETCH (0x1 << 7)
79#define DMA_MPU_MODE 2 79#define DMA_MPU_MODE 2
80 80
81/* XXX: Only NAND irq has been considered,currently these are the only ones used
82 */
83#define GPMC_NR_IRQ 2
84
85struct gpmc_client_irq {
86 unsigned irq;
87 u32 bitmask;
88};
89
81/* Structure to save gpmc cs context */ 90/* Structure to save gpmc cs context */
82struct gpmc_cs_config { 91struct gpmc_cs_config {
83 u32 config1; 92 u32 config1;
@@ -105,6 +114,10 @@ struct omap3_gpmc_regs {
105 struct gpmc_cs_config cs_context[GPMC_CS_NUM]; 114 struct gpmc_cs_config cs_context[GPMC_CS_NUM];
106}; 115};
107 116
117static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ];
118static struct irq_chip gpmc_irq_chip;
119static unsigned gpmc_irq_start;
120
108static struct resource gpmc_mem_root; 121static struct resource gpmc_mem_root;
109static struct resource gpmc_cs_mem[GPMC_CS_NUM]; 122static struct resource gpmc_cs_mem[GPMC_CS_NUM];
110static DEFINE_SPINLOCK(gpmc_mem_lock); 123static DEFINE_SPINLOCK(gpmc_mem_lock);
@@ -702,6 +715,97 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
702 reg->gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0; 715 reg->gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0;
703} 716}
704 717
718int gpmc_get_client_irq(unsigned irq_config)
719{
720 int i;
721
722 if (hweight32(irq_config) > 1)
723 return 0;
724
725 for (i = 0; i < GPMC_NR_IRQ; i++)
726 if (gpmc_client_irq[i].bitmask & irq_config)
727 return gpmc_client_irq[i].irq;
728
729 return 0;
730}
731
732static int gpmc_irq_endis(unsigned irq, bool endis)
733{
734 int i;
735 u32 regval;
736
737 for (i = 0; i < GPMC_NR_IRQ; i++)
738 if (irq == gpmc_client_irq[i].irq) {
739 regval = gpmc_read_reg(GPMC_IRQENABLE);
740 if (endis)
741 regval |= gpmc_client_irq[i].bitmask;
742 else
743 regval &= ~gpmc_client_irq[i].bitmask;
744 gpmc_write_reg(GPMC_IRQENABLE, regval);
745 break;
746 }
747
748 return 0;
749}
750
751static void gpmc_irq_disable(struct irq_data *p)
752{
753 gpmc_irq_endis(p->irq, false);
754}
755
756static void gpmc_irq_enable(struct irq_data *p)
757{
758 gpmc_irq_endis(p->irq, true);
759}
760
761static void gpmc_irq_noop(struct irq_data *data) { }
762
763static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
764
765static int gpmc_setup_irq(int gpmc_irq)
766{
767 int i;
768 u32 regval;
769
770 if (!gpmc_irq)
771 return -EINVAL;
772
773 gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
774 if (IS_ERR_VALUE(gpmc_irq_start)) {
775 pr_err("irq_alloc_descs failed\n");
776 return gpmc_irq_start;
777 }
778
779 gpmc_irq_chip.name = "gpmc";
780 gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret;
781 gpmc_irq_chip.irq_enable = gpmc_irq_enable;
782 gpmc_irq_chip.irq_disable = gpmc_irq_disable;
783 gpmc_irq_chip.irq_shutdown = gpmc_irq_noop;
784 gpmc_irq_chip.irq_ack = gpmc_irq_noop;
785 gpmc_irq_chip.irq_mask = gpmc_irq_noop;
786 gpmc_irq_chip.irq_unmask = gpmc_irq_noop;
787
788 gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE;
789 gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT;
790
791 for (i = 0; i < GPMC_NR_IRQ; i++) {
792 gpmc_client_irq[i].irq = gpmc_irq_start + i;
793 irq_set_chip_and_handler(gpmc_client_irq[i].irq,
794 &gpmc_irq_chip, handle_simple_irq);
795 set_irq_flags(gpmc_client_irq[i].irq,
796 IRQF_VALID | IRQF_NOAUTOEN);
797 }
798
799 /* Disable interrupts */
800 gpmc_write_reg(GPMC_IRQENABLE, 0);
801
802 /* clear interrupts */
803 regval = gpmc_read_reg(GPMC_IRQSTATUS);
804 gpmc_write_reg(GPMC_IRQSTATUS, regval);
805
806 return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL);
807}
808
705static void __init gpmc_mem_init(void) 809static void __init gpmc_mem_init(void)
706{ 810{
707 int cs; 811 int cs;
@@ -731,8 +835,8 @@ static void __init gpmc_mem_init(void)
731 835
732static int __init gpmc_init(void) 836static int __init gpmc_init(void)
733{ 837{
734 u32 l, irq; 838 u32 l;
735 int cs, ret = -EINVAL; 839 int ret = -EINVAL;
736 int gpmc_irq; 840 int gpmc_irq;
737 char *ck = NULL; 841 char *ck = NULL;
738 842
@@ -781,16 +885,7 @@ static int __init gpmc_init(void)
781 gpmc_write_reg(GPMC_SYSCONFIG, l); 885 gpmc_write_reg(GPMC_SYSCONFIG, l);
782 gpmc_mem_init(); 886 gpmc_mem_init();
783 887
784 /* initalize the irq_chained */ 888 ret = gpmc_setup_irq(gpmc_irq);
785 irq = OMAP_GPMC_IRQ_BASE;
786 for (cs = 0; cs < GPMC_CS_NUM; cs++) {
787 irq_set_chip_and_handler(irq, &dummy_irq_chip,
788 handle_simple_irq);
789 set_irq_flags(irq, IRQF_VALID);
790 irq++;
791 }
792
793 ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
794 if (ret) 889 if (ret)
795 pr_err("gpmc: irq-%d could not claim: err %d\n", 890 pr_err("gpmc: irq-%d could not claim: err %d\n",
796 gpmc_irq, ret); 891 gpmc_irq, ret);
@@ -800,12 +895,19 @@ postcore_initcall(gpmc_init);
800 895
801static irqreturn_t gpmc_handle_irq(int irq, void *dev) 896static irqreturn_t gpmc_handle_irq(int irq, void *dev)
802{ 897{
803 u8 cs; 898 int i;
899 u32 regval;
900
901 regval = gpmc_read_reg(GPMC_IRQSTATUS);
902
903 if (!regval)
904 return IRQ_NONE;
905
906 for (i = 0; i < GPMC_NR_IRQ; i++)
907 if (regval & gpmc_client_irq[i].bitmask)
908 generic_handle_irq(gpmc_client_irq[i].irq);
804 909
805 /* check cs to invoke the irq */ 910 gpmc_write_reg(GPMC_IRQSTATUS, regval);
806 cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
807 if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
808 generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
809 911
810 return IRQ_HANDLED; 912 return IRQ_HANDLED;
811} 913}
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 06198a51c4f0..2e6e2597178c 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -150,6 +150,7 @@ struct gpmc_nand_regs {
150}; 150};
151 151
152extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); 152extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
153extern int gpmc_get_client_irq(unsigned irq_config);
153 154
154extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); 155extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
155extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps); 156extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);