diff options
Diffstat (limited to 'arch/arm/mach-omap2/gpmc.c')
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 9b4e58ee2ca2..be6a75306f10 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -9,27 +9,23 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | #undef DEBUG | ||
13 | |||
12 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
13 | #include <linux/init.h> | 15 | #include <linux/init.h> |
14 | #include <linux/err.h> | 16 | #include <linux/err.h> |
15 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
16 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
17 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/module.h> | ||
18 | 21 | ||
19 | #include <asm/io.h> | 22 | #include <asm/io.h> |
20 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
21 | #include <mach/gpmc.h> | 24 | #include <mach/gpmc.h> |
22 | 25 | ||
23 | #undef DEBUG | 26 | #include "memory.h" |
24 | |||
25 | #ifdef CONFIG_ARCH_OMAP2420 | ||
26 | #define GPMC_BASE 0x6800a000 | ||
27 | #endif | ||
28 | |||
29 | #ifdef CONFIG_ARCH_OMAP2430 | ||
30 | #define GPMC_BASE 0x6E000000 | ||
31 | #endif | ||
32 | 27 | ||
28 | /* GPMC register offsets */ | ||
33 | #define GPMC_REVISION 0x00 | 29 | #define GPMC_REVISION 0x00 |
34 | #define GPMC_SYSCONFIG 0x10 | 30 | #define GPMC_SYSCONFIG 0x10 |
35 | #define GPMC_SYSSTATUS 0x14 | 31 | #define GPMC_SYSSTATUS 0x14 |
@@ -51,7 +47,6 @@ | |||
51 | #define GPMC_CS0 0x60 | 47 | #define GPMC_CS0 0x60 |
52 | #define GPMC_CS_SIZE 0x30 | 48 | #define GPMC_CS_SIZE 0x30 |
53 | 49 | ||
54 | #define GPMC_CS_NUM 8 | ||
55 | #define GPMC_MEM_START 0x00000000 | 50 | #define GPMC_MEM_START 0x00000000 |
56 | #define GPMC_MEM_END 0x3FFFFFFF | 51 | #define GPMC_MEM_END 0x3FFFFFFF |
57 | #define BOOT_ROM_SPACE 0x100000 /* 1MB */ | 52 | #define BOOT_ROM_SPACE 0x100000 /* 1MB */ |
@@ -64,10 +59,9 @@ static struct resource gpmc_cs_mem[GPMC_CS_NUM]; | |||
64 | static DEFINE_SPINLOCK(gpmc_mem_lock); | 59 | static DEFINE_SPINLOCK(gpmc_mem_lock); |
65 | static unsigned gpmc_cs_map; | 60 | static unsigned gpmc_cs_map; |
66 | 61 | ||
67 | static void __iomem *gpmc_base = IO_ADDRESS(GPMC_BASE); | 62 | static void __iomem *gpmc_base; |
68 | static void __iomem *gpmc_cs_base = IO_ADDRESS(GPMC_BASE) + GPMC_CS0; | ||
69 | 63 | ||
70 | static struct clk *gpmc_fck; | 64 | static struct clk *gpmc_l3_clk; |
71 | 65 | ||
72 | static void gpmc_write_reg(int idx, u32 val) | 66 | static void gpmc_write_reg(int idx, u32 val) |
73 | { | 67 | { |
@@ -83,19 +77,32 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val) | |||
83 | { | 77 | { |
84 | void __iomem *reg_addr; | 78 | void __iomem *reg_addr; |
85 | 79 | ||
86 | reg_addr = gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx; | 80 | reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; |
87 | __raw_writel(val, reg_addr); | 81 | __raw_writel(val, reg_addr); |
88 | } | 82 | } |
89 | 83 | ||
90 | u32 gpmc_cs_read_reg(int cs, int idx) | 84 | u32 gpmc_cs_read_reg(int cs, int idx) |
91 | { | 85 | { |
92 | return __raw_readl(gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx); | 86 | void __iomem *reg_addr; |
87 | |||
88 | reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; | ||
89 | return __raw_readl(reg_addr); | ||
93 | } | 90 | } |
94 | 91 | ||
92 | /* TODO: Add support for gpmc_fck to clock framework and use it */ | ||
95 | unsigned long gpmc_get_fclk_period(void) | 93 | unsigned long gpmc_get_fclk_period(void) |
96 | { | 94 | { |
97 | /* In picoseconds */ | 95 | unsigned long rate = clk_get_rate(gpmc_l3_clk); |
98 | return 1000000000 / ((clk_get_rate(gpmc_fck)) / 1000); | 96 | |
97 | if (rate == 0) { | ||
98 | printk(KERN_WARNING "gpmc_l3_clk not enabled\n"); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | rate /= 1000; | ||
103 | rate = 1000000000 / rate; /* In picoseconds */ | ||
104 | |||
105 | return rate; | ||
99 | } | 106 | } |
100 | 107 | ||
101 | unsigned int gpmc_ns_to_ticks(unsigned int time_ns) | 108 | unsigned int gpmc_ns_to_ticks(unsigned int time_ns) |
@@ -108,6 +115,11 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns) | |||
108 | return (time_ns * 1000 + tick_ps - 1) / tick_ps; | 115 | return (time_ns * 1000 + tick_ps - 1) / tick_ps; |
109 | } | 116 | } |
110 | 117 | ||
118 | unsigned int gpmc_ticks_to_ns(unsigned int ticks) | ||
119 | { | ||
120 | return ticks * gpmc_get_fclk_period() / 1000; | ||
121 | } | ||
122 | |||
111 | unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) | 123 | unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) |
112 | { | 124 | { |
113 | unsigned long ticks = gpmc_ns_to_ticks(time_ns); | 125 | unsigned long ticks = gpmc_ns_to_ticks(time_ns); |
@@ -348,6 +360,7 @@ out: | |||
348 | spin_unlock(&gpmc_mem_lock); | 360 | spin_unlock(&gpmc_mem_lock); |
349 | return r; | 361 | return r; |
350 | } | 362 | } |
363 | EXPORT_SYMBOL(gpmc_cs_request); | ||
351 | 364 | ||
352 | void gpmc_cs_free(int cs) | 365 | void gpmc_cs_free(int cs) |
353 | { | 366 | { |
@@ -363,8 +376,9 @@ void gpmc_cs_free(int cs) | |||
363 | gpmc_cs_set_reserved(cs, 0); | 376 | gpmc_cs_set_reserved(cs, 0); |
364 | spin_unlock(&gpmc_mem_lock); | 377 | spin_unlock(&gpmc_mem_lock); |
365 | } | 378 | } |
379 | EXPORT_SYMBOL(gpmc_cs_free); | ||
366 | 380 | ||
367 | void __init gpmc_mem_init(void) | 381 | static void __init gpmc_mem_init(void) |
368 | { | 382 | { |
369 | int cs; | 383 | int cs; |
370 | unsigned long boot_rom_space = 0; | 384 | unsigned long boot_rom_space = 0; |
@@ -394,12 +408,33 @@ void __init gpmc_mem_init(void) | |||
394 | void __init gpmc_init(void) | 408 | void __init gpmc_init(void) |
395 | { | 409 | { |
396 | u32 l; | 410 | u32 l; |
411 | char *ck; | ||
412 | |||
413 | if (cpu_is_omap24xx()) { | ||
414 | ck = "core_l3_ck"; | ||
415 | if (cpu_is_omap2420()) | ||
416 | l = OMAP2420_GPMC_BASE; | ||
417 | else | ||
418 | l = OMAP34XX_GPMC_BASE; | ||
419 | } else if (cpu_is_omap34xx()) { | ||
420 | ck = "gpmc_fck"; | ||
421 | l = OMAP34XX_GPMC_BASE; | ||
422 | } | ||
397 | 423 | ||
398 | gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */ | 424 | gpmc_l3_clk = clk_get(NULL, ck); |
399 | if (IS_ERR(gpmc_fck)) | 425 | if (IS_ERR(gpmc_l3_clk)) { |
400 | WARN_ON(1); | 426 | printk(KERN_ERR "Could not get GPMC clock %s\n", ck); |
401 | else | 427 | return -ENODEV; |
402 | clk_enable(gpmc_fck); | 428 | } |
429 | |||
430 | gpmc_base = ioremap(l, SZ_4K); | ||
431 | if (!gpmc_base) { | ||
432 | clk_put(gpmc_l3_clk); | ||
433 | printk(KERN_ERR "Could not get GPMC register memory\n"); | ||
434 | return -ENOMEM; | ||
435 | } | ||
436 | |||
437 | BUG_ON(IS_ERR(gpmc_l3_clk)); | ||
403 | 438 | ||
404 | l = gpmc_read_reg(GPMC_REVISION); | 439 | l = gpmc_read_reg(GPMC_REVISION); |
405 | printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); | 440 | printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); |