aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/gpmc-nand.c28
-rw-r--r--arch/arm/mach-omap2/gpmc-onenand.c23
-rw-r--r--arch/arm/mach-omap2/gpmc.c156
3 files changed, 184 insertions, 23 deletions
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 386dec8d2351..045596a3e899 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -21,15 +21,23 @@
21#include <plat/board.h> 21#include <plat/board.h>
22#include <plat/gpmc.h> 22#include <plat/gpmc.h>
23 23
24static struct resource gpmc_nand_resource = { 24static struct resource gpmc_nand_resource[] = {
25 .flags = IORESOURCE_MEM, 25 {
26 .flags = IORESOURCE_MEM,
27 },
28 {
29 .flags = IORESOURCE_IRQ,
30 },
31 {
32 .flags = IORESOURCE_IRQ,
33 },
26}; 34};
27 35
28static struct platform_device gpmc_nand_device = { 36static struct platform_device gpmc_nand_device = {
29 .name = "omap2-nand", 37 .name = "omap2-nand",
30 .id = 0, 38 .id = 0,
31 .num_resources = 1, 39 .num_resources = ARRAY_SIZE(gpmc_nand_resource),
32 .resource = &gpmc_nand_resource, 40 .resource = gpmc_nand_resource,
33}; 41};
34 42
35static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) 43static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
@@ -75,6 +83,7 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
75 gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0); 83 gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
76 gpmc_cs_configure(gpmc_nand_data->cs, 84 gpmc_cs_configure(gpmc_nand_data->cs,
77 GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); 85 GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
86 gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
78 err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t); 87 err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
79 if (err) 88 if (err)
80 return err; 89 return err;
@@ -90,12 +99,19 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
90 gpmc_nand_device.dev.platform_data = gpmc_nand_data; 99 gpmc_nand_device.dev.platform_data = gpmc_nand_data;
91 100
92 err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE, 101 err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
93 &gpmc_nand_data->phys_base); 102 (unsigned long *)&gpmc_nand_resource[0].start);
94 if (err < 0) { 103 if (err < 0) {
95 dev_err(dev, "Cannot request GPMC CS\n"); 104 dev_err(dev, "Cannot request GPMC CS\n");
96 return err; 105 return err;
97 } 106 }
98 107
108 gpmc_nand_resource[0].end = gpmc_nand_resource[0].start +
109 NAND_IO_SIZE - 1;
110
111 gpmc_nand_resource[1].start =
112 gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
113 gpmc_nand_resource[2].start =
114 gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
99 /* Set timings in GPMC */ 115 /* Set timings in GPMC */
100 err = omap2_nand_gpmc_retime(gpmc_nand_data); 116 err = omap2_nand_gpmc_retime(gpmc_nand_data);
101 if (err < 0) { 117 if (err < 0) {
@@ -108,6 +124,8 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
108 gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1); 124 gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
109 } 125 }
110 126
127 gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
128
111 err = platform_device_register(&gpmc_nand_device); 129 err = platform_device_register(&gpmc_nand_device);
112 if (err < 0) { 130 if (err < 0) {
113 dev_err(dev, "Unable to register NAND device\n"); 131 dev_err(dev, "Unable to register NAND device\n");
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index a0fa9bb2bda5..71d7c07dd350 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -23,11 +23,19 @@
23#include <plat/board.h> 23#include <plat/board.h>
24#include <plat/gpmc.h> 24#include <plat/gpmc.h>
25 25
26#define ONENAND_IO_SIZE SZ_128K
27
26static struct omap_onenand_platform_data *gpmc_onenand_data; 28static struct omap_onenand_platform_data *gpmc_onenand_data;
27 29
30static struct resource gpmc_onenand_resource = {
31 .flags = IORESOURCE_MEM,
32};
33
28static struct platform_device gpmc_onenand_device = { 34static struct platform_device gpmc_onenand_device = {
29 .name = "omap2-onenand", 35 .name = "omap2-onenand",
30 .id = -1, 36 .id = -1,
37 .num_resources = 1,
38 .resource = &gpmc_onenand_resource,
31}; 39};
32 40
33static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) 41static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
@@ -390,6 +398,8 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
390 398
391void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) 399void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
392{ 400{
401 int err;
402
393 gpmc_onenand_data = _onenand_data; 403 gpmc_onenand_data = _onenand_data;
394 gpmc_onenand_data->onenand_setup = gpmc_onenand_setup; 404 gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
395 gpmc_onenand_device.dev.platform_data = gpmc_onenand_data; 405 gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
@@ -401,8 +411,19 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
401 gpmc_onenand_data->flags |= ONENAND_SYNC_READ; 411 gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
402 } 412 }
403 413
414 err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
415 (unsigned long *)&gpmc_onenand_resource.start);
416 if (err < 0) {
417 pr_err("%s: Cannot request GPMC CS\n", __func__);
418 return;
419 }
420
421 gpmc_onenand_resource.end = gpmc_onenand_resource.start +
422 ONENAND_IO_SIZE - 1;
423
404 if (platform_device_register(&gpmc_onenand_device) < 0) { 424 if (platform_device_register(&gpmc_onenand_device) < 0) {
405 printk(KERN_ERR "Unable to register OneNAND device\n"); 425 pr_err("%s: Unable to register OneNAND device\n", __func__);
426 gpmc_cs_free(gpmc_onenand_data->cs);
406 return; 427 return;
407 } 428 }
408} 429}
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index b2b5759ab0fe..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);
@@ -682,6 +695,117 @@ int gpmc_prefetch_reset(int cs)
682} 695}
683EXPORT_SYMBOL(gpmc_prefetch_reset); 696EXPORT_SYMBOL(gpmc_prefetch_reset);
684 697
698void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
699{
700 reg->gpmc_status = gpmc_base + GPMC_STATUS;
701 reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET +
702 GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
703 reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET +
704 GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
705 reg->gpmc_nand_data = gpmc_base + GPMC_CS0_OFFSET +
706 GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
707 reg->gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1;
708 reg->gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2;
709 reg->gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL;
710 reg->gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS;
711 reg->gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG;
712 reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL;
713 reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG;
714 reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT;
715 reg->gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0;
716}
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
685static void __init gpmc_mem_init(void) 809static void __init gpmc_mem_init(void)
686{ 810{
687 int cs; 811 int cs;
@@ -711,8 +835,8 @@ static void __init gpmc_mem_init(void)
711 835
712static int __init gpmc_init(void) 836static int __init gpmc_init(void)
713{ 837{
714 u32 l, irq; 838 u32 l;
715 int cs, ret = -EINVAL; 839 int ret = -EINVAL;
716 int gpmc_irq; 840 int gpmc_irq;
717 char *ck = NULL; 841 char *ck = NULL;
718 842
@@ -761,16 +885,7 @@ static int __init gpmc_init(void)
761 gpmc_write_reg(GPMC_SYSCONFIG, l); 885 gpmc_write_reg(GPMC_SYSCONFIG, l);
762 gpmc_mem_init(); 886 gpmc_mem_init();
763 887
764 /* initalize the irq_chained */ 888 ret = gpmc_setup_irq(gpmc_irq);
765 irq = OMAP_GPMC_IRQ_BASE;
766 for (cs = 0; cs < GPMC_CS_NUM; cs++) {
767 irq_set_chip_and_handler(irq, &dummy_irq_chip,
768 handle_simple_irq);
769 set_irq_flags(irq, IRQF_VALID);
770 irq++;
771 }
772
773 ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
774 if (ret) 889 if (ret)
775 pr_err("gpmc: irq-%d could not claim: err %d\n", 890 pr_err("gpmc: irq-%d could not claim: err %d\n",
776 gpmc_irq, ret); 891 gpmc_irq, ret);
@@ -780,12 +895,19 @@ postcore_initcall(gpmc_init);
780 895
781static irqreturn_t gpmc_handle_irq(int irq, void *dev) 896static irqreturn_t gpmc_handle_irq(int irq, void *dev)
782{ 897{
783 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);
784 909
785 /* check cs to invoke the irq */ 910 gpmc_write_reg(GPMC_IRQSTATUS, regval);
786 cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
787 if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
788 generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
789 911
790 return IRQ_HANDLED; 912 return IRQ_HANDLED;
791} 913}