diff options
Diffstat (limited to 'arch/arm/mach-omap2/gpmc.c')
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 90 |
1 files changed, 64 insertions, 26 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index f51d69bc457..763bdbeaf68 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -9,27 +9,23 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#undef DEBUG + #include <linux/kernel.h> #include <linux/init.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/ioport.h> #include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/module.h> -#include <asm/io.h> #include <asm/mach-types.h> #include <mach/gpmc.h> -#undef DEBUG - -#ifdef CONFIG_ARCH_OMAP2420 -#define GPMC_BASE 0x6800a000 -#endif - -#ifdef CONFIG_ARCH_OMAP2430 -#define GPMC_BASE 0x6E000000 -#endif +#include <mach/sdrc.h> +/* GPMC register offsets */ #define GPMC_REVISION 0x00 #define GPMC_SYSCONFIG 0x10 #define GPMC_SYSSTATUS 0x14 @@ -51,7 +47,6 @@ #define GPMC_CS0 0x60 #define GPMC_CS_SIZE 0x30 -#define GPMC_CS_NUM 8 #define GPMC_MEM_START 0x00000000 #define GPMC_MEM_END 0x3FFFFFFF #define BOOT_ROM_SPACE 0x100000 /* 1MB */ @@ -64,12 +59,9 @@ static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); static unsigned gpmc_cs_map; -static void __iomem *gpmc_base = - (void __iomem *) IO_ADDRESS(GPMC_BASE); -static void __iomem *gpmc_cs_base = - (void __iomem *) IO_ADDRESS(GPMC_BASE) + GPMC_CS0; +static void __iomem *gpmc_base; -static struct clk *gpmc_fck; +static struct clk *gpmc_l3_clk; static void gpmc_write_reg(int idx, u32 val) { @@ -85,19 +77,32 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val) { void __iomem *reg_addr; - reg_addr = gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx; + reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; __raw_writel(val, reg_addr); } u32 gpmc_cs_read_reg(int cs, int idx) { - return __raw_readl(gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx); + void __iomem *reg_addr; + + reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; + return __raw_readl(reg_addr); } +/* TODO: Add support for gpmc_fck to clock framework and use it */ unsigned long gpmc_get_fclk_period(void) { - /* In picoseconds */ - return 1000000000 / ((clk_get_rate(gpmc_fck)) / 1000); + unsigned long rate = clk_get_rate(gpmc_l3_clk); + + if (rate == 0) { + printk(KERN_WARNING "gpmc_l3_clk not enabled\n"); + return 0; + } + + rate /= 1000; + rate = 1000000000 / rate; /* In picoseconds */ + + return rate; } unsigned int gpmc_ns_to_ticks(unsigned int time_ns) @@ -110,6 +115,11 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns) return (time_ns * 1000 + tick_ps - 1) / tick_ps; } +unsigned int gpmc_ticks_to_ns(unsigned int ticks) +{ + return ticks * gpmc_get_fclk_period() / 1000; +} + unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) { unsigned long ticks = gpmc_ns_to_ticks(time_ns); @@ -210,6 +220,11 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + if (cpu_is_omap34xx()) { + GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); + GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access); + } + /* caller is expected to have initialized CONFIG1 to cover * at least sync vs async */ @@ -350,6 +365,7 @@ out: spin_unlock(&gpmc_mem_lock); return r; } +EXPORT_SYMBOL(gpmc_cs_request); void gpmc_cs_free(int cs) { @@ -365,8 +381,9 @@ void gpmc_cs_free(int cs) gpmc_cs_set_reserved(cs, 0); spin_unlock(&gpmc_mem_lock); } +EXPORT_SYMBOL(gpmc_cs_free); -void __init gpmc_mem_init(void) +static void __init gpmc_mem_init(void) { int cs; unsigned long boot_rom_space = 0; @@ -396,12 +413,33 @@ void __init gpmc_mem_init(void) void __init gpmc_init(void) { u32 l; + char *ck; + + if (cpu_is_omap24xx()) { + ck = "core_l3_ck"; + if (cpu_is_omap2420()) + l = OMAP2420_GPMC_BASE; + else + l = OMAP34XX_GPMC_BASE; + } else if (cpu_is_omap34xx()) { + ck = "gpmc_fck"; + l = OMAP34XX_GPMC_BASE; + } - gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */ - if (IS_ERR(gpmc_fck)) - WARN_ON(1); - else - clk_enable(gpmc_fck); + gpmc_l3_clk = clk_get(NULL, ck); + if (IS_ERR(gpmc_l3_clk)) { + printk(KERN_ERR "Could not get GPMC clock %s\n", ck); + return -ENODEV; + } + + gpmc_base = ioremap(l, SZ_4K); + if (!gpmc_base) { + clk_put(gpmc_l3_clk); + printk(KERN_ERR "Could not get GPMC register memory\n"); + return -ENOMEM; + } + + BUG_ON(IS_ERR(gpmc_l3_clk)); l = gpmc_read_reg(GPMC_REVISION); printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); |