diff options
Diffstat (limited to 'arch/arm/mach-omap2/gpmc.c')
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 548 |
1 files changed, 396 insertions, 152 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 410e1bac7815..ed946df5ad8a 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/of.h> | 28 | #include <linux/of.h> |
29 | #include <linux/of_address.h> | ||
29 | #include <linux/of_mtd.h> | 30 | #include <linux/of_mtd.h> |
30 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
31 | #include <linux/mtd/nand.h> | 32 | #include <linux/mtd/nand.h> |
@@ -91,9 +92,7 @@ | |||
91 | #define GPMC_CS_SIZE 0x30 | 92 | #define GPMC_CS_SIZE 0x30 |
92 | #define GPMC_BCH_SIZE 0x10 | 93 | #define GPMC_BCH_SIZE 0x10 |
93 | 94 | ||
94 | #define GPMC_MEM_START 0x00000000 | ||
95 | #define GPMC_MEM_END 0x3FFFFFFF | 95 | #define GPMC_MEM_END 0x3FFFFFFF |
96 | #define BOOT_ROM_SPACE 0x100000 /* 1MB */ | ||
97 | 96 | ||
98 | #define GPMC_CHUNK_SHIFT 24 /* 16 MB */ | 97 | #define GPMC_CHUNK_SHIFT 24 /* 16 MB */ |
99 | #define GPMC_SECTION_SHIFT 28 /* 128 MB */ | 98 | #define GPMC_SECTION_SHIFT 28 /* 128 MB */ |
@@ -107,6 +106,9 @@ | |||
107 | 106 | ||
108 | #define GPMC_HAS_WR_ACCESS 0x1 | 107 | #define GPMC_HAS_WR_ACCESS 0x1 |
109 | #define GPMC_HAS_WR_DATA_MUX_BUS 0x2 | 108 | #define GPMC_HAS_WR_DATA_MUX_BUS 0x2 |
109 | #define GPMC_HAS_MUX_AAD 0x4 | ||
110 | |||
111 | #define GPMC_NR_WAITPINS 4 | ||
110 | 112 | ||
111 | /* XXX: Only NAND irq has been considered,currently these are the only ones used | 113 | /* XXX: Only NAND irq has been considered,currently these are the only ones used |
112 | */ | 114 | */ |
@@ -153,6 +155,7 @@ static struct resource gpmc_cs_mem[GPMC_CS_NUM]; | |||
153 | static DEFINE_SPINLOCK(gpmc_mem_lock); | 155 | static DEFINE_SPINLOCK(gpmc_mem_lock); |
154 | /* Define chip-selects as reserved by default until probe completes */ | 156 | /* Define chip-selects as reserved by default until probe completes */ |
155 | static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1); | 157 | static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1); |
158 | static unsigned int gpmc_nr_waitpins; | ||
156 | static struct device *gpmc_dev; | 159 | static struct device *gpmc_dev; |
157 | static int gpmc_irq; | 160 | static int gpmc_irq; |
158 | static resource_size_t phys_base, mem_size; | 161 | static resource_size_t phys_base, mem_size; |
@@ -181,7 +184,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val) | |||
181 | __raw_writel(val, reg_addr); | 184 | __raw_writel(val, reg_addr); |
182 | } | 185 | } |
183 | 186 | ||
184 | u32 gpmc_cs_read_reg(int cs, int idx) | 187 | static u32 gpmc_cs_read_reg(int cs, int idx) |
185 | { | 188 | { |
186 | void __iomem *reg_addr; | 189 | void __iomem *reg_addr; |
187 | 190 | ||
@@ -190,7 +193,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) | |||
190 | } | 193 | } |
191 | 194 | ||
192 | /* TODO: Add support for gpmc_fck to clock framework and use it */ | 195 | /* TODO: Add support for gpmc_fck to clock framework and use it */ |
193 | unsigned long gpmc_get_fclk_period(void) | 196 | static unsigned long gpmc_get_fclk_period(void) |
194 | { | 197 | { |
195 | unsigned long rate = clk_get_rate(gpmc_l3_clk); | 198 | unsigned long rate = clk_get_rate(gpmc_l3_clk); |
196 | 199 | ||
@@ -205,7 +208,7 @@ unsigned long gpmc_get_fclk_period(void) | |||
205 | return rate; | 208 | return rate; |
206 | } | 209 | } |
207 | 210 | ||
208 | unsigned int gpmc_ns_to_ticks(unsigned int time_ns) | 211 | static unsigned int gpmc_ns_to_ticks(unsigned int time_ns) |
209 | { | 212 | { |
210 | unsigned long tick_ps; | 213 | unsigned long tick_ps; |
211 | 214 | ||
@@ -215,7 +218,7 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns) | |||
215 | return (time_ns * 1000 + tick_ps - 1) / tick_ps; | 218 | return (time_ns * 1000 + tick_ps - 1) / tick_ps; |
216 | } | 219 | } |
217 | 220 | ||
218 | unsigned int gpmc_ps_to_ticks(unsigned int time_ps) | 221 | static unsigned int gpmc_ps_to_ticks(unsigned int time_ps) |
219 | { | 222 | { |
220 | unsigned long tick_ps; | 223 | unsigned long tick_ps; |
221 | 224 | ||
@@ -230,13 +233,6 @@ unsigned int gpmc_ticks_to_ns(unsigned int ticks) | |||
230 | return ticks * gpmc_get_fclk_period() / 1000; | 233 | return ticks * gpmc_get_fclk_period() / 1000; |
231 | } | 234 | } |
232 | 235 | ||
233 | unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) | ||
234 | { | ||
235 | unsigned long ticks = gpmc_ns_to_ticks(time_ns); | ||
236 | |||
237 | return ticks * gpmc_get_fclk_period() / 1000; | ||
238 | } | ||
239 | |||
240 | static unsigned int gpmc_ticks_to_ps(unsigned int ticks) | 236 | static unsigned int gpmc_ticks_to_ps(unsigned int ticks) |
241 | { | 237 | { |
242 | return ticks * gpmc_get_fclk_period(); | 238 | return ticks * gpmc_get_fclk_period(); |
@@ -405,11 +401,18 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) | |||
405 | return 0; | 401 | return 0; |
406 | } | 402 | } |
407 | 403 | ||
408 | static void gpmc_cs_enable_mem(int cs, u32 base, u32 size) | 404 | static int gpmc_cs_enable_mem(int cs, u32 base, u32 size) |
409 | { | 405 | { |
410 | u32 l; | 406 | u32 l; |
411 | u32 mask; | 407 | u32 mask; |
412 | 408 | ||
409 | /* | ||
410 | * Ensure that base address is aligned on a | ||
411 | * boundary equal to or greater than size. | ||
412 | */ | ||
413 | if (base & (size - 1)) | ||
414 | return -EINVAL; | ||
415 | |||
413 | mask = (1 << GPMC_SECTION_SHIFT) - size; | 416 | mask = (1 << GPMC_SECTION_SHIFT) - size; |
414 | l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); | 417 | l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); |
415 | l &= ~0x3f; | 418 | l &= ~0x3f; |
@@ -418,6 +421,8 @@ static void gpmc_cs_enable_mem(int cs, u32 base, u32 size) | |||
418 | l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8; | 421 | l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8; |
419 | l |= GPMC_CONFIG7_CSVALID; | 422 | l |= GPMC_CONFIG7_CSVALID; |
420 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); | 423 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); |
424 | |||
425 | return 0; | ||
421 | } | 426 | } |
422 | 427 | ||
423 | static void gpmc_cs_disable_mem(int cs) | 428 | static void gpmc_cs_disable_mem(int cs) |
@@ -448,22 +453,14 @@ static int gpmc_cs_mem_enabled(int cs) | |||
448 | return l & GPMC_CONFIG7_CSVALID; | 453 | return l & GPMC_CONFIG7_CSVALID; |
449 | } | 454 | } |
450 | 455 | ||
451 | int gpmc_cs_set_reserved(int cs, int reserved) | 456 | static void gpmc_cs_set_reserved(int cs, int reserved) |
452 | { | 457 | { |
453 | if (cs > GPMC_CS_NUM) | ||
454 | return -ENODEV; | ||
455 | |||
456 | gpmc_cs_map &= ~(1 << cs); | 458 | gpmc_cs_map &= ~(1 << cs); |
457 | gpmc_cs_map |= (reserved ? 1 : 0) << cs; | 459 | gpmc_cs_map |= (reserved ? 1 : 0) << cs; |
458 | |||
459 | return 0; | ||
460 | } | 460 | } |
461 | 461 | ||
462 | int gpmc_cs_reserved(int cs) | 462 | static bool gpmc_cs_reserved(int cs) |
463 | { | 463 | { |
464 | if (cs > GPMC_CS_NUM) | ||
465 | return -ENODEV; | ||
466 | |||
467 | return gpmc_cs_map & (1 << cs); | 464 | return gpmc_cs_map & (1 << cs); |
468 | } | 465 | } |
469 | 466 | ||
@@ -510,6 +507,39 @@ static int gpmc_cs_delete_mem(int cs) | |||
510 | return r; | 507 | return r; |
511 | } | 508 | } |
512 | 509 | ||
510 | /** | ||
511 | * gpmc_cs_remap - remaps a chip-select physical base address | ||
512 | * @cs: chip-select to remap | ||
513 | * @base: physical base address to re-map chip-select to | ||
514 | * | ||
515 | * Re-maps a chip-select to a new physical base address specified by | ||
516 | * "base". Returns 0 on success and appropriate negative error code | ||
517 | * on failure. | ||
518 | */ | ||
519 | static int gpmc_cs_remap(int cs, u32 base) | ||
520 | { | ||
521 | int ret; | ||
522 | u32 old_base, size; | ||
523 | |||
524 | if (cs > GPMC_CS_NUM) | ||
525 | return -ENODEV; | ||
526 | gpmc_cs_get_memconf(cs, &old_base, &size); | ||
527 | if (base == old_base) | ||
528 | return 0; | ||
529 | gpmc_cs_disable_mem(cs); | ||
530 | ret = gpmc_cs_delete_mem(cs); | ||
531 | if (ret < 0) | ||
532 | return ret; | ||
533 | ret = gpmc_cs_insert_mem(cs, base, size); | ||
534 | if (ret < 0) | ||
535 | return ret; | ||
536 | ret = gpmc_cs_enable_mem(cs, base, size); | ||
537 | if (ret < 0) | ||
538 | return ret; | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
513 | int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) | 543 | int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) |
514 | { | 544 | { |
515 | struct resource *res = &gpmc_cs_mem[cs]; | 545 | struct resource *res = &gpmc_cs_mem[cs]; |
@@ -535,7 +565,12 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) | |||
535 | if (r < 0) | 565 | if (r < 0) |
536 | goto out; | 566 | goto out; |
537 | 567 | ||
538 | gpmc_cs_enable_mem(cs, res->start, resource_size(res)); | 568 | r = gpmc_cs_enable_mem(cs, res->start, resource_size(res)); |
569 | if (r < 0) { | ||
570 | release_resource(res); | ||
571 | goto out; | ||
572 | } | ||
573 | |||
539 | *base = res->start; | 574 | *base = res->start; |
540 | gpmc_cs_set_reserved(cs, 1); | 575 | gpmc_cs_set_reserved(cs, 1); |
541 | out: | 576 | out: |
@@ -561,16 +596,14 @@ void gpmc_cs_free(int cs) | |||
561 | EXPORT_SYMBOL(gpmc_cs_free); | 596 | EXPORT_SYMBOL(gpmc_cs_free); |
562 | 597 | ||
563 | /** | 598 | /** |
564 | * gpmc_cs_configure - write request to configure gpmc | 599 | * gpmc_configure - write request to configure gpmc |
565 | * @cs: chip select number | ||
566 | * @cmd: command type | 600 | * @cmd: command type |
567 | * @wval: value to write | 601 | * @wval: value to write |
568 | * @return status of the operation | 602 | * @return status of the operation |
569 | */ | 603 | */ |
570 | int gpmc_cs_configure(int cs, int cmd, int wval) | 604 | int gpmc_configure(int cmd, int wval) |
571 | { | 605 | { |
572 | int err = 0; | 606 | u32 regval; |
573 | u32 regval = 0; | ||
574 | 607 | ||
575 | switch (cmd) { | 608 | switch (cmd) { |
576 | case GPMC_ENABLE_IRQ: | 609 | case GPMC_ENABLE_IRQ: |
@@ -590,43 +623,14 @@ int gpmc_cs_configure(int cs, int cmd, int wval) | |||
590 | gpmc_write_reg(GPMC_CONFIG, regval); | 623 | gpmc_write_reg(GPMC_CONFIG, regval); |
591 | break; | 624 | break; |
592 | 625 | ||
593 | case GPMC_CONFIG_RDY_BSY: | ||
594 | regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); | ||
595 | if (wval) | ||
596 | regval |= WR_RD_PIN_MONITORING; | ||
597 | else | ||
598 | regval &= ~WR_RD_PIN_MONITORING; | ||
599 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); | ||
600 | break; | ||
601 | |||
602 | case GPMC_CONFIG_DEV_SIZE: | ||
603 | regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); | ||
604 | |||
605 | /* clear 2 target bits */ | ||
606 | regval &= ~GPMC_CONFIG1_DEVICESIZE(3); | ||
607 | |||
608 | /* set the proper value */ | ||
609 | regval |= GPMC_CONFIG1_DEVICESIZE(wval); | ||
610 | |||
611 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); | ||
612 | break; | ||
613 | |||
614 | case GPMC_CONFIG_DEV_TYPE: | ||
615 | regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); | ||
616 | regval |= GPMC_CONFIG1_DEVICETYPE(wval); | ||
617 | if (wval == GPMC_DEVICETYPE_NOR) | ||
618 | regval |= GPMC_CONFIG1_MUXADDDATA; | ||
619 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); | ||
620 | break; | ||
621 | |||
622 | default: | 626 | default: |
623 | printk(KERN_ERR "gpmc_configure_cs: Not supported\n"); | 627 | pr_err("%s: command not supported\n", __func__); |
624 | err = -EINVAL; | 628 | return -EINVAL; |
625 | } | 629 | } |
626 | 630 | ||
627 | return err; | 631 | return 0; |
628 | } | 632 | } |
629 | EXPORT_SYMBOL(gpmc_cs_configure); | 633 | EXPORT_SYMBOL(gpmc_configure); |
630 | 634 | ||
631 | void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) | 635 | void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) |
632 | { | 636 | { |
@@ -716,7 +720,7 @@ static int gpmc_setup_irq(void) | |||
716 | return -EINVAL; | 720 | return -EINVAL; |
717 | 721 | ||
718 | gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0); | 722 | gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0); |
719 | if (IS_ERR_VALUE(gpmc_irq_start)) { | 723 | if (gpmc_irq_start < 0) { |
720 | pr_err("irq_alloc_descs failed\n"); | 724 | pr_err("irq_alloc_descs failed\n"); |
721 | return gpmc_irq_start; | 725 | return gpmc_irq_start; |
722 | } | 726 | } |
@@ -781,16 +785,16 @@ static void gpmc_mem_exit(void) | |||
781 | 785 | ||
782 | } | 786 | } |
783 | 787 | ||
784 | static int gpmc_mem_init(void) | 788 | static void gpmc_mem_init(void) |
785 | { | 789 | { |
786 | int cs, rc; | 790 | int cs; |
787 | unsigned long boot_rom_space = 0; | ||
788 | 791 | ||
789 | /* never allocate the first page, to facilitate bug detection; | 792 | /* |
790 | * even if we didn't boot from ROM. | 793 | * The first 1MB of GPMC address space is typically mapped to |
794 | * the internal ROM. Never allocate the first page, to | ||
795 | * facilitate bug detection; even if we didn't boot from ROM. | ||
791 | */ | 796 | */ |
792 | boot_rom_space = BOOT_ROM_SPACE; | 797 | gpmc_mem_root.start = SZ_1M; |
793 | gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space; | ||
794 | gpmc_mem_root.end = GPMC_MEM_END; | 798 | gpmc_mem_root.end = GPMC_MEM_END; |
795 | 799 | ||
796 | /* Reserve all regions that has been set up by bootloader */ | 800 | /* Reserve all regions that has been set up by bootloader */ |
@@ -800,16 +804,12 @@ static int gpmc_mem_init(void) | |||
800 | if (!gpmc_cs_mem_enabled(cs)) | 804 | if (!gpmc_cs_mem_enabled(cs)) |
801 | continue; | 805 | continue; |
802 | gpmc_cs_get_memconf(cs, &base, &size); | 806 | gpmc_cs_get_memconf(cs, &base, &size); |
803 | rc = gpmc_cs_insert_mem(cs, base, size); | 807 | if (gpmc_cs_insert_mem(cs, base, size)) { |
804 | if (IS_ERR_VALUE(rc)) { | 808 | pr_warn("%s: disabling cs %d mapped at 0x%x-0x%x\n", |
805 | while (--cs >= 0) | 809 | __func__, cs, base, base + size); |
806 | if (gpmc_cs_mem_enabled(cs)) | 810 | gpmc_cs_disable_mem(cs); |
807 | gpmc_cs_delete_mem(cs); | ||
808 | return rc; | ||
809 | } | 811 | } |
810 | } | 812 | } |
811 | |||
812 | return 0; | ||
813 | } | 813 | } |
814 | 814 | ||
815 | static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk) | 815 | static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk) |
@@ -825,9 +825,9 @@ static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk) | |||
825 | 825 | ||
826 | /* XXX: can the cycles be avoided ? */ | 826 | /* XXX: can the cycles be avoided ? */ |
827 | static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t, | 827 | static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t, |
828 | struct gpmc_device_timings *dev_t) | 828 | struct gpmc_device_timings *dev_t, |
829 | bool mux) | ||
829 | { | 830 | { |
830 | bool mux = dev_t->mux; | ||
831 | u32 temp; | 831 | u32 temp; |
832 | 832 | ||
833 | /* adv_rd_off */ | 833 | /* adv_rd_off */ |
@@ -880,9 +880,9 @@ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t, | |||
880 | } | 880 | } |
881 | 881 | ||
882 | static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t, | 882 | static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t, |
883 | struct gpmc_device_timings *dev_t) | 883 | struct gpmc_device_timings *dev_t, |
884 | bool mux) | ||
884 | { | 885 | { |
885 | bool mux = dev_t->mux; | ||
886 | u32 temp; | 886 | u32 temp; |
887 | 887 | ||
888 | /* adv_wr_off */ | 888 | /* adv_wr_off */ |
@@ -942,9 +942,9 @@ static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t, | |||
942 | } | 942 | } |
943 | 943 | ||
944 | static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t, | 944 | static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t, |
945 | struct gpmc_device_timings *dev_t) | 945 | struct gpmc_device_timings *dev_t, |
946 | bool mux) | ||
946 | { | 947 | { |
947 | bool mux = dev_t->mux; | ||
948 | u32 temp; | 948 | u32 temp; |
949 | 949 | ||
950 | /* adv_rd_off */ | 950 | /* adv_rd_off */ |
@@ -982,9 +982,9 @@ static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t, | |||
982 | } | 982 | } |
983 | 983 | ||
984 | static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t, | 984 | static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t, |
985 | struct gpmc_device_timings *dev_t) | 985 | struct gpmc_device_timings *dev_t, |
986 | bool mux) | ||
986 | { | 987 | { |
987 | bool mux = dev_t->mux; | ||
988 | u32 temp; | 988 | u32 temp; |
989 | 989 | ||
990 | /* adv_wr_off */ | 990 | /* adv_wr_off */ |
@@ -1054,7 +1054,8 @@ static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t, | |||
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t, | 1056 | static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t, |
1057 | struct gpmc_device_timings *dev_t) | 1057 | struct gpmc_device_timings *dev_t, |
1058 | bool sync) | ||
1058 | { | 1059 | { |
1059 | u32 temp; | 1060 | u32 temp; |
1060 | 1061 | ||
@@ -1068,7 +1069,7 @@ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t, | |||
1068 | gpmc_t->cs_on + dev_t->t_ce_avd); | 1069 | gpmc_t->cs_on + dev_t->t_ce_avd); |
1069 | gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp); | 1070 | gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp); |
1070 | 1071 | ||
1071 | if (dev_t->sync_write || dev_t->sync_read) | 1072 | if (sync) |
1072 | gpmc_calc_sync_common_timings(gpmc_t, dev_t); | 1073 | gpmc_calc_sync_common_timings(gpmc_t, dev_t); |
1073 | 1074 | ||
1074 | return 0; | 1075 | return 0; |
@@ -1103,21 +1104,29 @@ static void gpmc_convert_ps_to_ns(struct gpmc_timings *t) | |||
1103 | } | 1104 | } |
1104 | 1105 | ||
1105 | int gpmc_calc_timings(struct gpmc_timings *gpmc_t, | 1106 | int gpmc_calc_timings(struct gpmc_timings *gpmc_t, |
1106 | struct gpmc_device_timings *dev_t) | 1107 | struct gpmc_settings *gpmc_s, |
1108 | struct gpmc_device_timings *dev_t) | ||
1107 | { | 1109 | { |
1110 | bool mux = false, sync = false; | ||
1111 | |||
1112 | if (gpmc_s) { | ||
1113 | mux = gpmc_s->mux_add_data ? true : false; | ||
1114 | sync = (gpmc_s->sync_read || gpmc_s->sync_write); | ||
1115 | } | ||
1116 | |||
1108 | memset(gpmc_t, 0, sizeof(*gpmc_t)); | 1117 | memset(gpmc_t, 0, sizeof(*gpmc_t)); |
1109 | 1118 | ||
1110 | gpmc_calc_common_timings(gpmc_t, dev_t); | 1119 | gpmc_calc_common_timings(gpmc_t, dev_t, sync); |
1111 | 1120 | ||
1112 | if (dev_t->sync_read) | 1121 | if (gpmc_s && gpmc_s->sync_read) |
1113 | gpmc_calc_sync_read_timings(gpmc_t, dev_t); | 1122 | gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux); |
1114 | else | 1123 | else |
1115 | gpmc_calc_async_read_timings(gpmc_t, dev_t); | 1124 | gpmc_calc_async_read_timings(gpmc_t, dev_t, mux); |
1116 | 1125 | ||
1117 | if (dev_t->sync_write) | 1126 | if (gpmc_s && gpmc_s->sync_write) |
1118 | gpmc_calc_sync_write_timings(gpmc_t, dev_t); | 1127 | gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux); |
1119 | else | 1128 | else |
1120 | gpmc_calc_async_write_timings(gpmc_t, dev_t); | 1129 | gpmc_calc_async_write_timings(gpmc_t, dev_t, mux); |
1121 | 1130 | ||
1122 | /* TODO: remove, see function definition */ | 1131 | /* TODO: remove, see function definition */ |
1123 | gpmc_convert_ps_to_ns(gpmc_t); | 1132 | gpmc_convert_ps_to_ns(gpmc_t); |
@@ -1125,6 +1134,90 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t, | |||
1125 | return 0; | 1134 | return 0; |
1126 | } | 1135 | } |
1127 | 1136 | ||
1137 | /** | ||
1138 | * gpmc_cs_program_settings - programs non-timing related settings | ||
1139 | * @cs: GPMC chip-select to program | ||
1140 | * @p: pointer to GPMC settings structure | ||
1141 | * | ||
1142 | * Programs non-timing related settings for a GPMC chip-select, such as | ||
1143 | * bus-width, burst configuration, etc. Function should be called once | ||
1144 | * for each chip-select that is being used and must be called before | ||
1145 | * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1 | ||
1146 | * register will be initialised to zero by this function. Returns 0 on | ||
1147 | * success and appropriate negative error code on failure. | ||
1148 | */ | ||
1149 | int gpmc_cs_program_settings(int cs, struct gpmc_settings *p) | ||
1150 | { | ||
1151 | u32 config1; | ||
1152 | |||
1153 | if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) { | ||
1154 | pr_err("%s: invalid width %d!", __func__, p->device_width); | ||
1155 | return -EINVAL; | ||
1156 | } | ||
1157 | |||
1158 | /* Address-data multiplexing not supported for NAND devices */ | ||
1159 | if (p->device_nand && p->mux_add_data) { | ||
1160 | pr_err("%s: invalid configuration!\n", __func__); | ||
1161 | return -EINVAL; | ||
1162 | } | ||
1163 | |||
1164 | if ((p->mux_add_data > GPMC_MUX_AD) || | ||
1165 | ((p->mux_add_data == GPMC_MUX_AAD) && | ||
1166 | !(gpmc_capability & GPMC_HAS_MUX_AAD))) { | ||
1167 | pr_err("%s: invalid multiplex configuration!\n", __func__); | ||
1168 | return -EINVAL; | ||
1169 | } | ||
1170 | |||
1171 | /* Page/burst mode supports lengths of 4, 8 and 16 bytes */ | ||
1172 | if (p->burst_read || p->burst_write) { | ||
1173 | switch (p->burst_len) { | ||
1174 | case GPMC_BURST_4: | ||
1175 | case GPMC_BURST_8: | ||
1176 | case GPMC_BURST_16: | ||
1177 | break; | ||
1178 | default: | ||
1179 | pr_err("%s: invalid page/burst-length (%d)\n", | ||
1180 | __func__, p->burst_len); | ||
1181 | return -EINVAL; | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | if ((p->wait_on_read || p->wait_on_write) && | ||
1186 | (p->wait_pin > gpmc_nr_waitpins)) { | ||
1187 | pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin); | ||
1188 | return -EINVAL; | ||
1189 | } | ||
1190 | |||
1191 | config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1)); | ||
1192 | |||
1193 | if (p->sync_read) | ||
1194 | config1 |= GPMC_CONFIG1_READTYPE_SYNC; | ||
1195 | if (p->sync_write) | ||
1196 | config1 |= GPMC_CONFIG1_WRITETYPE_SYNC; | ||
1197 | if (p->wait_on_read) | ||
1198 | config1 |= GPMC_CONFIG1_WAIT_READ_MON; | ||
1199 | if (p->wait_on_write) | ||
1200 | config1 |= GPMC_CONFIG1_WAIT_WRITE_MON; | ||
1201 | if (p->wait_on_read || p->wait_on_write) | ||
1202 | config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin); | ||
1203 | if (p->device_nand) | ||
1204 | config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND); | ||
1205 | if (p->mux_add_data) | ||
1206 | config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data); | ||
1207 | if (p->burst_read) | ||
1208 | config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP; | ||
1209 | if (p->burst_write) | ||
1210 | config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP; | ||
1211 | if (p->burst_read || p->burst_write) { | ||
1212 | config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3); | ||
1213 | config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0; | ||
1214 | } | ||
1215 | |||
1216 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1); | ||
1217 | |||
1218 | return 0; | ||
1219 | } | ||
1220 | |||
1128 | #ifdef CONFIG_OF | 1221 | #ifdef CONFIG_OF |
1129 | static struct of_device_id gpmc_dt_ids[] = { | 1222 | static struct of_device_id gpmc_dt_ids[] = { |
1130 | { .compatible = "ti,omap2420-gpmc" }, | 1223 | { .compatible = "ti,omap2420-gpmc" }, |
@@ -1136,70 +1229,110 @@ static struct of_device_id gpmc_dt_ids[] = { | |||
1136 | }; | 1229 | }; |
1137 | MODULE_DEVICE_TABLE(of, gpmc_dt_ids); | 1230 | MODULE_DEVICE_TABLE(of, gpmc_dt_ids); |
1138 | 1231 | ||
1232 | /** | ||
1233 | * gpmc_read_settings_dt - read gpmc settings from device-tree | ||
1234 | * @np: pointer to device-tree node for a gpmc child device | ||
1235 | * @p: pointer to gpmc settings structure | ||
1236 | * | ||
1237 | * Reads the GPMC settings for a GPMC child device from device-tree and | ||
1238 | * stores them in the GPMC settings structure passed. The GPMC settings | ||
1239 | * structure is initialised to zero by this function and so any | ||
1240 | * previously stored settings will be cleared. | ||
1241 | */ | ||
1242 | void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p) | ||
1243 | { | ||
1244 | memset(p, 0, sizeof(struct gpmc_settings)); | ||
1245 | |||
1246 | p->sync_read = of_property_read_bool(np, "gpmc,sync-read"); | ||
1247 | p->sync_write = of_property_read_bool(np, "gpmc,sync-write"); | ||
1248 | p->device_nand = of_property_read_bool(np, "gpmc,device-nand"); | ||
1249 | of_property_read_u32(np, "gpmc,device-width", &p->device_width); | ||
1250 | of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data); | ||
1251 | |||
1252 | if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) { | ||
1253 | p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap"); | ||
1254 | p->burst_read = of_property_read_bool(np, "gpmc,burst-read"); | ||
1255 | p->burst_write = of_property_read_bool(np, "gpmc,burst-write"); | ||
1256 | if (!p->burst_read && !p->burst_write) | ||
1257 | pr_warn("%s: page/burst-length set but not used!\n", | ||
1258 | __func__); | ||
1259 | } | ||
1260 | |||
1261 | if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) { | ||
1262 | p->wait_on_read = of_property_read_bool(np, | ||
1263 | "gpmc,wait-on-read"); | ||
1264 | p->wait_on_write = of_property_read_bool(np, | ||
1265 | "gpmc,wait-on-write"); | ||
1266 | if (!p->wait_on_read && !p->wait_on_write) | ||
1267 | pr_warn("%s: read/write wait monitoring not enabled!\n", | ||
1268 | __func__); | ||
1269 | } | ||
1270 | } | ||
1271 | |||
1139 | static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, | 1272 | static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, |
1140 | struct gpmc_timings *gpmc_t) | 1273 | struct gpmc_timings *gpmc_t) |
1141 | { | 1274 | { |
1142 | u32 val; | 1275 | struct gpmc_bool_timings *p; |
1276 | |||
1277 | if (!np || !gpmc_t) | ||
1278 | return; | ||
1143 | 1279 | ||
1144 | memset(gpmc_t, 0, sizeof(*gpmc_t)); | 1280 | memset(gpmc_t, 0, sizeof(*gpmc_t)); |
1145 | 1281 | ||
1146 | /* minimum clock period for syncronous mode */ | 1282 | /* minimum clock period for syncronous mode */ |
1147 | if (!of_property_read_u32(np, "gpmc,sync-clk", &val)) | 1283 | of_property_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk); |
1148 | gpmc_t->sync_clk = val; | ||
1149 | 1284 | ||
1150 | /* chip select timtings */ | 1285 | /* chip select timtings */ |
1151 | if (!of_property_read_u32(np, "gpmc,cs-on", &val)) | 1286 | of_property_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on); |
1152 | gpmc_t->cs_on = val; | 1287 | of_property_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off); |
1153 | 1288 | of_property_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off); | |
1154 | if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val)) | ||
1155 | gpmc_t->cs_rd_off = val; | ||
1156 | |||
1157 | if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val)) | ||
1158 | gpmc_t->cs_wr_off = val; | ||
1159 | 1289 | ||
1160 | /* ADV signal timings */ | 1290 | /* ADV signal timings */ |
1161 | if (!of_property_read_u32(np, "gpmc,adv-on", &val)) | 1291 | of_property_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on); |
1162 | gpmc_t->adv_on = val; | 1292 | of_property_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off); |
1163 | 1293 | of_property_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off); | |
1164 | if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val)) | ||
1165 | gpmc_t->adv_rd_off = val; | ||
1166 | |||
1167 | if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val)) | ||
1168 | gpmc_t->adv_wr_off = val; | ||
1169 | 1294 | ||
1170 | /* WE signal timings */ | 1295 | /* WE signal timings */ |
1171 | if (!of_property_read_u32(np, "gpmc,we-on", &val)) | 1296 | of_property_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on); |
1172 | gpmc_t->we_on = val; | 1297 | of_property_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off); |
1173 | |||
1174 | if (!of_property_read_u32(np, "gpmc,we-off", &val)) | ||
1175 | gpmc_t->we_off = val; | ||
1176 | 1298 | ||
1177 | /* OE signal timings */ | 1299 | /* OE signal timings */ |
1178 | if (!of_property_read_u32(np, "gpmc,oe-on", &val)) | 1300 | of_property_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on); |
1179 | gpmc_t->oe_on = val; | 1301 | of_property_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off); |
1180 | |||
1181 | if (!of_property_read_u32(np, "gpmc,oe-off", &val)) | ||
1182 | gpmc_t->oe_off = val; | ||
1183 | 1302 | ||
1184 | /* access and cycle timings */ | 1303 | /* access and cycle timings */ |
1185 | if (!of_property_read_u32(np, "gpmc,page-burst-access", &val)) | 1304 | of_property_read_u32(np, "gpmc,page-burst-access-ns", |
1186 | gpmc_t->page_burst_access = val; | 1305 | &gpmc_t->page_burst_access); |
1187 | 1306 | of_property_read_u32(np, "gpmc,access-ns", &gpmc_t->access); | |
1188 | if (!of_property_read_u32(np, "gpmc,access", &val)) | 1307 | of_property_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle); |
1189 | gpmc_t->access = val; | 1308 | of_property_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle); |
1190 | 1309 | of_property_read_u32(np, "gpmc,bus-turnaround-ns", | |
1191 | if (!of_property_read_u32(np, "gpmc,rd-cycle", &val)) | 1310 | &gpmc_t->bus_turnaround); |
1192 | gpmc_t->rd_cycle = val; | 1311 | of_property_read_u32(np, "gpmc,cycle2cycle-delay-ns", |
1193 | 1312 | &gpmc_t->cycle2cycle_delay); | |
1194 | if (!of_property_read_u32(np, "gpmc,wr-cycle", &val)) | 1313 | of_property_read_u32(np, "gpmc,wait-monitoring-ns", |
1195 | gpmc_t->wr_cycle = val; | 1314 | &gpmc_t->wait_monitoring); |
1196 | 1315 | of_property_read_u32(np, "gpmc,clk-activation-ns", | |
1197 | /* only for OMAP3430 */ | 1316 | &gpmc_t->clk_activation); |
1198 | if (!of_property_read_u32(np, "gpmc,wr-access", &val)) | 1317 | |
1199 | gpmc_t->wr_access = val; | 1318 | /* only applicable to OMAP3+ */ |
1200 | 1319 | of_property_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access); | |
1201 | if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val)) | 1320 | of_property_read_u32(np, "gpmc,wr-data-mux-bus-ns", |
1202 | gpmc_t->wr_data_mux_bus = val; | 1321 | &gpmc_t->wr_data_mux_bus); |
1322 | |||
1323 | /* bool timing parameters */ | ||
1324 | p = &gpmc_t->bool_timings; | ||
1325 | |||
1326 | p->cycle2cyclediffcsen = | ||
1327 | of_property_read_bool(np, "gpmc,cycle2cycle-diffcsen"); | ||
1328 | p->cycle2cyclesamecsen = | ||
1329 | of_property_read_bool(np, "gpmc,cycle2cycle-samecsen"); | ||
1330 | p->we_extra_delay = of_property_read_bool(np, "gpmc,we-extra-delay"); | ||
1331 | p->oe_extra_delay = of_property_read_bool(np, "gpmc,oe-extra-delay"); | ||
1332 | p->adv_extra_delay = of_property_read_bool(np, "gpmc,adv-extra-delay"); | ||
1333 | p->cs_extra_delay = of_property_read_bool(np, "gpmc,cs-extra-delay"); | ||
1334 | p->time_para_granularity = | ||
1335 | of_property_read_bool(np, "gpmc,time-para-granularity"); | ||
1203 | } | 1336 | } |
1204 | 1337 | ||
1205 | #ifdef CONFIG_MTD_NAND | 1338 | #ifdef CONFIG_MTD_NAND |
@@ -1295,6 +1428,81 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev, | |||
1295 | } | 1428 | } |
1296 | #endif | 1429 | #endif |
1297 | 1430 | ||
1431 | /** | ||
1432 | * gpmc_probe_generic_child - configures the gpmc for a child device | ||
1433 | * @pdev: pointer to gpmc platform device | ||
1434 | * @child: pointer to device-tree node for child device | ||
1435 | * | ||
1436 | * Allocates and configures a GPMC chip-select for a child device. | ||
1437 | * Returns 0 on success and appropriate negative error code on failure. | ||
1438 | */ | ||
1439 | static int gpmc_probe_generic_child(struct platform_device *pdev, | ||
1440 | struct device_node *child) | ||
1441 | { | ||
1442 | struct gpmc_settings gpmc_s; | ||
1443 | struct gpmc_timings gpmc_t; | ||
1444 | struct resource res; | ||
1445 | unsigned long base; | ||
1446 | int ret, cs; | ||
1447 | |||
1448 | if (of_property_read_u32(child, "reg", &cs) < 0) { | ||
1449 | dev_err(&pdev->dev, "%s has no 'reg' property\n", | ||
1450 | child->full_name); | ||
1451 | return -ENODEV; | ||
1452 | } | ||
1453 | |||
1454 | if (of_address_to_resource(child, 0, &res) < 0) { | ||
1455 | dev_err(&pdev->dev, "%s has malformed 'reg' property\n", | ||
1456 | child->full_name); | ||
1457 | return -ENODEV; | ||
1458 | } | ||
1459 | |||
1460 | ret = gpmc_cs_request(cs, resource_size(&res), &base); | ||
1461 | if (ret < 0) { | ||
1462 | dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs); | ||
1463 | return ret; | ||
1464 | } | ||
1465 | |||
1466 | /* | ||
1467 | * FIXME: gpmc_cs_request() will map the CS to an arbitary | ||
1468 | * location in the gpmc address space. When booting with | ||
1469 | * device-tree we want the NOR flash to be mapped to the | ||
1470 | * location specified in the device-tree blob. So remap the | ||
1471 | * CS to this location. Once DT migration is complete should | ||
1472 | * just make gpmc_cs_request() map a specific address. | ||
1473 | */ | ||
1474 | ret = gpmc_cs_remap(cs, res.start); | ||
1475 | if (ret < 0) { | ||
1476 | dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n", | ||
1477 | cs, res.start); | ||
1478 | goto err; | ||
1479 | } | ||
1480 | |||
1481 | gpmc_read_settings_dt(child, &gpmc_s); | ||
1482 | |||
1483 | ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width); | ||
1484 | if (ret < 0) | ||
1485 | goto err; | ||
1486 | |||
1487 | ret = gpmc_cs_program_settings(cs, &gpmc_s); | ||
1488 | if (ret < 0) | ||
1489 | goto err; | ||
1490 | |||
1491 | gpmc_read_timings_dt(child, &gpmc_t); | ||
1492 | gpmc_cs_set_timings(cs, &gpmc_t); | ||
1493 | |||
1494 | if (of_platform_device_create(child, NULL, &pdev->dev)) | ||
1495 | return 0; | ||
1496 | |||
1497 | dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name); | ||
1498 | ret = -ENODEV; | ||
1499 | |||
1500 | err: | ||
1501 | gpmc_cs_free(cs); | ||
1502 | |||
1503 | return ret; | ||
1504 | } | ||
1505 | |||
1298 | static int gpmc_probe_dt(struct platform_device *pdev) | 1506 | static int gpmc_probe_dt(struct platform_device *pdev) |
1299 | { | 1507 | { |
1300 | int ret; | 1508 | int ret; |
@@ -1305,6 +1513,13 @@ static int gpmc_probe_dt(struct platform_device *pdev) | |||
1305 | if (!of_id) | 1513 | if (!of_id) |
1306 | return 0; | 1514 | return 0; |
1307 | 1515 | ||
1516 | ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins", | ||
1517 | &gpmc_nr_waitpins); | ||
1518 | if (ret < 0) { | ||
1519 | pr_err("%s: number of wait pins not found!\n", __func__); | ||
1520 | return ret; | ||
1521 | } | ||
1522 | |||
1308 | for_each_node_by_name(child, "nand") { | 1523 | for_each_node_by_name(child, "nand") { |
1309 | ret = gpmc_probe_nand_child(pdev, child); | 1524 | ret = gpmc_probe_nand_child(pdev, child); |
1310 | if (ret < 0) { | 1525 | if (ret < 0) { |
@@ -1320,6 +1535,23 @@ static int gpmc_probe_dt(struct platform_device *pdev) | |||
1320 | return ret; | 1535 | return ret; |
1321 | } | 1536 | } |
1322 | } | 1537 | } |
1538 | |||
1539 | for_each_node_by_name(child, "nor") { | ||
1540 | ret = gpmc_probe_generic_child(pdev, child); | ||
1541 | if (ret < 0) { | ||
1542 | of_node_put(child); | ||
1543 | return ret; | ||
1544 | } | ||
1545 | } | ||
1546 | |||
1547 | for_each_node_by_name(child, "ethernet") { | ||
1548 | ret = gpmc_probe_generic_child(pdev, child); | ||
1549 | if (ret < 0) { | ||
1550 | of_node_put(child); | ||
1551 | return ret; | ||
1552 | } | ||
1553 | } | ||
1554 | |||
1323 | return 0; | 1555 | return 0; |
1324 | } | 1556 | } |
1325 | #else | 1557 | #else |
@@ -1364,25 +1596,37 @@ static int gpmc_probe(struct platform_device *pdev) | |||
1364 | gpmc_dev = &pdev->dev; | 1596 | gpmc_dev = &pdev->dev; |
1365 | 1597 | ||
1366 | l = gpmc_read_reg(GPMC_REVISION); | 1598 | l = gpmc_read_reg(GPMC_REVISION); |
1599 | |||
1600 | /* | ||
1601 | * FIXME: Once device-tree migration is complete the below flags | ||
1602 | * should be populated based upon the device-tree compatible | ||
1603 | * string. For now just use the IP revision. OMAP3+ devices have | ||
1604 | * the wr_access and wr_data_mux_bus register fields. OMAP4+ | ||
1605 | * devices support the addr-addr-data multiplex protocol. | ||
1606 | * | ||
1607 | * GPMC IP revisions: | ||
1608 | * - OMAP24xx = 2.0 | ||
1609 | * - OMAP3xxx = 5.0 | ||
1610 | * - OMAP44xx/54xx/AM335x = 6.0 | ||
1611 | */ | ||
1367 | if (GPMC_REVISION_MAJOR(l) > 0x4) | 1612 | if (GPMC_REVISION_MAJOR(l) > 0x4) |
1368 | gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; | 1613 | gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; |
1614 | if (GPMC_REVISION_MAJOR(l) > 0x5) | ||
1615 | gpmc_capability |= GPMC_HAS_MUX_AAD; | ||
1369 | dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), | 1616 | dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), |
1370 | GPMC_REVISION_MINOR(l)); | 1617 | GPMC_REVISION_MINOR(l)); |
1371 | 1618 | ||
1372 | rc = gpmc_mem_init(); | 1619 | gpmc_mem_init(); |
1373 | if (IS_ERR_VALUE(rc)) { | ||
1374 | clk_disable_unprepare(gpmc_l3_clk); | ||
1375 | clk_put(gpmc_l3_clk); | ||
1376 | dev_err(gpmc_dev, "failed to reserve memory\n"); | ||
1377 | return rc; | ||
1378 | } | ||
1379 | 1620 | ||
1380 | if (IS_ERR_VALUE(gpmc_setup_irq())) | 1621 | if (gpmc_setup_irq() < 0) |
1381 | dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); | 1622 | dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); |
1382 | 1623 | ||
1383 | /* Now the GPMC is initialised, unreserve the chip-selects */ | 1624 | /* Now the GPMC is initialised, unreserve the chip-selects */ |
1384 | gpmc_cs_map = 0; | 1625 | gpmc_cs_map = 0; |
1385 | 1626 | ||
1627 | if (!pdev->dev.of_node) | ||
1628 | gpmc_nr_waitpins = GPMC_NR_WAITPINS; | ||
1629 | |||
1386 | rc = gpmc_probe_dt(pdev); | 1630 | rc = gpmc_probe_dt(pdev); |
1387 | if (rc < 0) { | 1631 | if (rc < 0) { |
1388 | clk_disable_unprepare(gpmc_l3_clk); | 1632 | clk_disable_unprepare(gpmc_l3_clk); |