diff options
Diffstat (limited to 'arch/arm/mach-omap2/gpmc.c')
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 106 |
1 files changed, 99 insertions, 7 deletions
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 15876828db2..e86f5ca180e 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -24,9 +24,9 @@ #include <linux/module.h> #include <asm/mach-types.h> -#include <mach/gpmc.h> +#include <plat/gpmc.h> -#include <mach/sdrc.h> +#include <plat/sdrc.h> /* GPMC register offsets */ #define GPMC_REVISION 0x00 @@ -62,6 +62,33 @@ #define ENABLE_PREFETCH (0x1 << 7) #define DMA_MPU_MODE 2 +/* Structure to save gpmc cs context */ +struct gpmc_cs_config { + u32 config1; + u32 config2; + u32 config3; + u32 config4; + u32 config5; + u32 config6; + u32 config7; + int is_valid; +}; + +/* + * Structure to save/restore gpmc context + * to support core off on OMAP3 + */ +struct omap3_gpmc_regs { + u32 sysconfig; + u32 irqenable; + u32 timeout_ctrl; + u32 config; + u32 prefetch_config1; + u32 prefetch_config2; + u32 prefetch_control; + struct gpmc_cs_config cs_context[GPMC_CS_NUM]; +}; + static struct resource gpmc_mem_root; static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); @@ -261,7 +288,7 @@ static void gpmc_cs_enable_mem(int cs, u32 base, u32 size) l = (base >> GPMC_CHUNK_SHIFT) & 0x3f; l &= ~(0x0f << 8); l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8; - l |= 1 << 6; /* CSVALID */ + l |= GPMC_CONFIG7_CSVALID; gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); } @@ -270,7 +297,7 @@ static void gpmc_cs_disable_mem(int cs) u32 l; l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); - l &= ~(1 << 6); /* CSVALID */ + l &= ~GPMC_CONFIG7_CSVALID; gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); } @@ -290,7 +317,7 @@ static int gpmc_cs_mem_enabled(int cs) u32 l; l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); - return l & (1 << 6); + return l & GPMC_CONFIG7_CSVALID; } int gpmc_cs_set_reserved(int cs, int reserved) @@ -366,7 +393,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) if (r < 0) goto out; - gpmc_cs_enable_mem(cs, res->start, res->end - res->start + 1); + gpmc_cs_enable_mem(cs, res->start, resource_size(res)); *base = res->start; gpmc_cs_set_reserved(cs, 1); out: @@ -378,7 +405,7 @@ EXPORT_SYMBOL(gpmc_cs_request); void gpmc_cs_free(int cs) { spin_lock(&gpmc_mem_lock); - if (cs >= GPMC_CS_NUM || !gpmc_cs_reserved(cs)) { + if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) { printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); BUG(); spin_unlock(&gpmc_mem_lock); @@ -516,3 +543,68 @@ void __init gpmc_init(void) gpmc_write_reg(GPMC_SYSCONFIG, l); gpmc_mem_init(); } + +#ifdef CONFIG_ARCH_OMAP3 +static struct omap3_gpmc_regs gpmc_context; + +void omap3_gpmc_save_context() +{ + int i; + gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG); + gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE); + gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL); + gpmc_context.config = gpmc_read_reg(GPMC_CONFIG); + gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1); + gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2); + gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL); + for (i = 0; i < GPMC_CS_NUM; i++) { + gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i); + if (gpmc_context.cs_context[i].is_valid) { + gpmc_context.cs_context[i].config1 = + gpmc_cs_read_reg(i, GPMC_CS_CONFIG1); + gpmc_context.cs_context[i].config2 = + gpmc_cs_read_reg(i, GPMC_CS_CONFIG2); + gpmc_context.cs_context[i].config3 = + gpmc_cs_read_reg(i, GPMC_CS_CONFIG3); + gpmc_context.cs_context[i].config4 = + gpmc_cs_read_reg(i, GPMC_CS_CONFIG4); + gpmc_context.cs_context[i].config5 = + gpmc_cs_read_reg(i, GPMC_CS_CONFIG5); + gpmc_context.cs_context[i].config6 = + gpmc_cs_read_reg(i, GPMC_CS_CONFIG6); + gpmc_context.cs_context[i].config7 = + gpmc_cs_read_reg(i, GPMC_CS_CONFIG7); + } + } +} + +void omap3_gpmc_restore_context() +{ + int i; + gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig); + gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable); + gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl); + gpmc_write_reg(GPMC_CONFIG, gpmc_context.config); + gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1); + gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2); + gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control); + for (i = 0; i < GPMC_CS_NUM; i++) { + if (gpmc_context.cs_context[i].is_valid) { + gpmc_cs_write_reg(i, GPMC_CS_CONFIG1, + gpmc_context.cs_context[i].config1); + gpmc_cs_write_reg(i, GPMC_CS_CONFIG2, + gpmc_context.cs_context[i].config2); + gpmc_cs_write_reg(i, GPMC_CS_CONFIG3, + gpmc_context.cs_context[i].config3); + gpmc_cs_write_reg(i, GPMC_CS_CONFIG4, + gpmc_context.cs_context[i].config4); + gpmc_cs_write_reg(i, GPMC_CS_CONFIG5, + gpmc_context.cs_context[i].config5); + gpmc_cs_write_reg(i, GPMC_CS_CONFIG6, + gpmc_context.cs_context[i].config6); + gpmc_cs_write_reg(i, GPMC_CS_CONFIG7, + gpmc_context.cs_context[i].config7); + } + } +} +#endif /* CONFIG_ARCH_OMAP3 */ |