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.c81
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];
64static DEFINE_SPINLOCK(gpmc_mem_lock); 59static DEFINE_SPINLOCK(gpmc_mem_lock);
65static unsigned gpmc_cs_map; 60static unsigned gpmc_cs_map;
66 61
67static void __iomem *gpmc_base = IO_ADDRESS(GPMC_BASE); 62static void __iomem *gpmc_base;
68static void __iomem *gpmc_cs_base = IO_ADDRESS(GPMC_BASE) + GPMC_CS0;
69 63
70static struct clk *gpmc_fck; 64static struct clk *gpmc_l3_clk;
71 65
72static void gpmc_write_reg(int idx, u32 val) 66static 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
90u32 gpmc_cs_read_reg(int cs, int idx) 84u32 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 */
95unsigned long gpmc_get_fclk_period(void) 93unsigned 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
101unsigned int gpmc_ns_to_ticks(unsigned int time_ns) 108unsigned 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
118unsigned int gpmc_ticks_to_ns(unsigned int ticks)
119{
120 return ticks * gpmc_get_fclk_period() / 1000;
121}
122
111unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) 123unsigned 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}
363EXPORT_SYMBOL(gpmc_cs_request);
351 364
352void gpmc_cs_free(int cs) 365void 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}
379EXPORT_SYMBOL(gpmc_cs_free);
366 380
367void __init gpmc_mem_init(void) 381static 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)
394void __init gpmc_init(void) 408void __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);