SAR layout contents are now generated automatically based on SAR ROM contents during boot. u32 offset description ---------- ------------------------- 0 pointer to next entry 1 size of DMA transfer in bytes 2 SAR RAM address for save / restore 3 IO address for save / restore sar_layout_generate() parses this info and stores the resulting data to a list of sar_ram_entry structs, which in turn will be used by sar_save. Signed-off-by: Tero Kristo <t-kristo@xxxxxx> --- arch/arm/mach-omap2/omap-sar.c | 290 +++++++++++++++++++++++++++------------- 1 files changed, 194 insertions(+), 96 deletions(-) diff --git a/arch/arm/mach-omap2/omap-sar.c b/arch/arm/mach-omap2/omap-sar.c index 74e0207..da4696a 100644 --- a/arch/arm/mach-omap2/omap-sar.c +++ b/arch/arm/mach-omap2/omap-sar.c @@ -2,7 +2,8 @@ * OMAP4 Save Restore source file * * Copyright (C) 2010 Texas Instruments, Inc. - * Written by Santosh Shilimkar <santosh.shilimkar@xxxxxx> + * Santosh Shilimkar <santosh.shilimkar@xxxxxx> + * Tero Kristo <t-kristo@xxxxxx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,6 +15,7 @@ #include <linux/io.h> #include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/slab.h> #include "iomap.h" #include "pm.h" @@ -25,35 +27,18 @@ #include "cminst44xx.h" static void __iomem *sar_ram_base; -static void __iomem *omap4_sar_modules[MAX_SAR_MODULES]; static struct powerdomain *l3init_pwrdm; static struct clockdomain *l3init_clkdm; static struct clk *usb_host_ck, *usb_tll_ck; -/* - * SAR_RAM1 register layout consist of EMIF1, EMIF2, CM1, CM2, - * CONTROL_CORE efuse, DMM and USB TLL registers. - * The layout is arranged is a two dimentional array like - * below, - * const u32 sar_ramX_layout[nb_regs_sets][4] = { - * {module_index, reg_offset, size, sar_ram_offset}, - * } - */ -static const u32 omap443x_sar_ram1_layout[][4] = { -}; - -/* - * SAR_RAM2 register layout consist of SYSCTRL_PADCONF_CORE regsiters - */ -static const u32 omap443x_sar_ram2_layout[][4] = { +struct sar_ram_entry { + void __iomem *io_base; + u32 offset; + u32 size; + u32 ram_addr; }; -/* - * SAR_RAM3 and SAR_RAM4 layout is not listed since moslty it's handle by - * secure software. - */ -static const u32 omap443x_sar_ram3_layout[][4] = { -}; +static struct sar_ram_entry *sar_ram_layout[3]; /* * omap_sar_save : @@ -63,25 +48,20 @@ static const u32 omap443x_sar_ram3_layout[][4] = { * @sar_bank_offset - where to backup * @sar_layout - constant table containing the backup info */ -static void sar_save(u32 nb_regs, u32 sar_bank, const u32 sar_layout_table[][4]) +static void sar_save(struct sar_ram_entry *entry) { - u32 reg_val, size, i, j; + u32 reg_val, size, i; void __iomem *reg_read_addr, *sar_wr_addr; - for (i = 0; i < nb_regs; i++) { - if (omap4_sar_modules[(sar_layout_table[i][MODULE_ADDR_IDX])]) { - size = sar_layout_table[i][MODULE_NB_REGS_IDX]; - reg_read_addr = - omap4_sar_modules[sar_layout_table[i] - [MODULE_ADDR_IDX]] - + sar_layout_table[i][MODULE_OFFSET_IDX]; - sar_wr_addr = sar_ram_base + sar_bank + - sar_layout_table[i][SAR_RAM_OFFSET_IDX]; - for (j = 0; j < size; j++) { - reg_val = __raw_readl(reg_read_addr + j * 4); - __raw_writel(reg_val, sar_wr_addr + j * 4); - } + while (entry->size) { + size = entry->size; + reg_read_addr = entry->io_base + entry->offset; + sar_wr_addr = sar_ram_base + entry->ram_addr; + for (i = 0; i < size; i++) { + reg_val = __raw_readl(reg_read_addr + i * 4); + __raw_writel(reg_val, sar_wr_addr + i * 4); } + entry++; } } @@ -100,8 +80,7 @@ static void save_sar_bank3(void) l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm"); clkdm_wakeup(l4_secure_clkdm); - sar_save(ARRAY_SIZE(omap443x_sar_ram3_layout), SAR_BANK3_OFFSET, - omap443x_sar_ram3_layout); + sar_save(sar_ram_layout[2]); clkdm_allow_idle(l4_secure_clkdm); } @@ -116,13 +95,13 @@ static int omap4_sar_not_accessible(void) * registers, otherwise this will trigger an exception. */ usbhost_state = omap4_cminst_read_inst_reg(OMAP4430_CM2_PARTITION, - OMAP4430_CM2_L3INIT_INST, - OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET) + OMAP4430_CM2_L3INIT_INST, + OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET) & (OMAP4430_STBYST_MASK | OMAP4430_IDLEST_MASK); usbtll_state = omap4_cminst_read_inst_reg(OMAP4430_CM2_PARTITION, - OMAP4430_CM2_L3INIT_INST, - OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET) + OMAP4430_CM2_L3INIT_INST, + OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET) & OMAP4430_IDLEST_MASK; if ((usbhost_state == (OMAP4430_STBYST_MASK | OMAP4430_IDLEST_MASK)) && @@ -133,12 +112,12 @@ static int omap4_sar_not_accessible(void) } /* - * omap4_sar_save - + * omap_sar_save - * Save the context to SAR_RAM1 and SAR_RAM2 as per * omap4xxx_sar_ram1_layout and omap4xxx_sar_ram2_layout for the device OFF * mode */ -int omap4_sar_save(void) +int omap_sar_save(void) { /* * Not supported on ES1.0 silicon @@ -163,8 +142,7 @@ int omap4_sar_save(void) clk_enable(usb_tll_ck); /* Save SAR BANK1 */ - sar_save(ARRAY_SIZE(omap443x_sar_ram1_layout), SAR_BANK1_OFFSET, - omap443x_sar_ram1_layout); + sar_save(sar_ram_layout[0]); clk_disable(usb_host_ck); clk_disable(usb_tll_ck); @@ -172,8 +150,7 @@ int omap4_sar_save(void) clkdm_allow_idle(l3init_clkdm); /* Save SAR BANK2 */ - sar_save(ARRAY_SIZE(omap443x_sar_ram2_layout), SAR_BANK2_OFFSET, - omap443x_sar_ram2_layout); + sar_save(sar_ram_layout[1]); return 0; } @@ -194,13 +171,16 @@ int omap4_sar_save(void) * sequencing, the software must overwrite data read from * the following registers implied in phase2a and phase 2b */ -void omap4_sar_overwrite(void) +void omap_sar_overwrite(void) { u32 val = 0; - u32 offset = 0; + u32 usb_offset = 0x2ec; + u32 usb_offset2 = 0x91c; - if (cpu_is_omap446x()) - offset = 0x04; + if (cpu_is_omap446x()) { + usb_offset = 0x2f4; + usb_offset2 = 0x920; + } /* Overwriting Phase1 data to be restored */ /* CM2 MEMIF_CLKTRCTRL = SW_WKUP, before FREQ UPDATE */ @@ -215,7 +195,7 @@ void omap4_sar_overwrite(void) /* CM1 CM_SHADOW_FREQ_CONFIG1, Enable FREQ UPDATE */ val = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1); val |= 1 << OMAP4430_FREQ_UPDATE_SHIFT; - val &= ~OMAP4430_DLL_OVERRIDE_MASK; + val &= ~OMAP4430_DLL_OVERRIDE_2_2_MASK; __raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x104); /* CM2 MEMIF_CLKTRCTRL = HW_AUTO, after FREQ UPDATE */ __raw_writel(0x3, sar_ram_base + SAR_BANK1_OFFSET + 0x124); @@ -223,29 +203,29 @@ void omap4_sar_overwrite(void) /* Overwriting Phase2a data to be restored */ /* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 1, MODULEMODE = 2 */ __raw_writel(0x00000012, - sar_ram_base + SAR_BANK1_OFFSET + 0x2ec + offset); + sar_ram_base + SAR_BANK1_OFFSET + usb_offset); /* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 1, MODULEMODE = 1 */ __raw_writel(0x00000011, - sar_ram_base + SAR_BANK1_OFFSET + 0x2f0 + offset); + sar_ram_base + SAR_BANK1_OFFSET + usb_offset + 4); /* CM2 CM_SDMA_STATICDEP : Enable static depedency for SAR modules */ __raw_writel(0x000090e8, - sar_ram_base + SAR_BANK1_OFFSET + 0x2f4 + offset); + sar_ram_base + SAR_BANK1_OFFSET + usb_offset + 8); /* Overwriting Phase2b data to be restored */ /* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */ val = __raw_readl(OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL); val &= (OMAP4430_CLKSEL_UTMI_P1_MASK | OMAP4430_CLKSEL_UTMI_P2_MASK); - __raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x91c + offset); + __raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + usb_offset2); /* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */ __raw_writel(0x0000000, - sar_ram_base + SAR_BANK1_OFFSET + 0x920 + offset); + sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 4); /* CM2 CM_SDMA_STATICDEP : Clear the static depedency */ __raw_writel(0x00000040, - sar_ram_base + SAR_BANK1_OFFSET + 0x924 + offset); + sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 8); /* readback to ensure data reaches to SAR RAM */ barrier(); - val = __raw_readl(sar_ram_base + SAR_BANK1_OFFSET + 0x924 + offset); + val = __raw_readl(sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 8); } void __iomem *omap4_get_sar_ram_base(void) @@ -253,6 +233,152 @@ void __iomem *omap4_get_sar_ram_base(void) return sar_ram_base; } +static const u32 sar_rom_phases[] = { + 0, 0x30, 0x60 +}; + +struct sar_module { + void __iomem *io_base; + u32 base; + u32 size; + bool invalid; +}; + +static struct sar_module *sar_modules; + +static void sar_ioremap_modules(void) +{ + struct sar_module *mod; + + mod = sar_modules; + + while (mod->base) { + if (!mod->invalid) { + mod->io_base = ioremap(mod->base, mod->size); + if (!mod->io_base) + pr_err("%s: ioremap failed for %08x[%08x]\n", + __func__, mod->base, mod->size); + BUG_ON(!mod->io_base); + } + mod++; + } +} + +static int set_sar_io_addr(struct sar_ram_entry *entry, u32 addr) +{ + struct sar_module *mod; + + mod = sar_modules; + + while (mod->base) { + if (addr >= mod->base && addr <= mod->base + mod->size) { + if (mod->invalid) + break; + entry->io_base = mod->io_base; + entry->offset = addr - mod->base; + return 0; + } + mod++; + } + pr_warn("%s: no matching sar_module for %08x\n", __func__, addr); + return -EINVAL; +} + +static int sar_layout_generate(void) +{ + int phase; + void __iomem *sarrom; + u32 rombase, romend, rambase, ramend; + u32 offset, next; + u16 size; + u32 ram_addr, io_addr; + void *sarram; + struct sar_ram_entry *entry[3]; + int bank; + int ret = 0; + + pr_info("generating sar_ram layout...\n"); + + rombase = OMAP44XX_SAR_ROM_BASE; + romend = rombase + SZ_8K; + rambase = OMAP44XX_SAR_RAM_BASE; + ramend = rambase + SAR_BANK4_OFFSET - 1; + + sarrom = ioremap(rombase, SZ_8K); + + /* Allocate temporary memory for sar ram layout */ + sarram = kmalloc(SAR_BANK4_OFFSET, GFP_KERNEL); + for (bank = 0; bank < 3; bank++) + entry[bank] = sarram + SAR_BANK2_OFFSET * bank; + + for (phase = 0; phase < ARRAY_SIZE(sar_rom_phases); phase++) { + offset = sar_rom_phases[phase]; + + while (1) { + next = __raw_readl(sarrom + offset); + size = __raw_readl(sarrom + offset + 4) & 0xffff; + ram_addr = __raw_readl(sarrom + offset + 8); + io_addr = __raw_readl(sarrom + offset + 12); + + if (ram_addr >= rambase && ram_addr <= ramend) { + /* Valid ram address, add entry */ + ram_addr -= rambase; + bank = ram_addr / SAR_BANK2_OFFSET; + if (!set_sar_io_addr(entry[bank], io_addr)) { + entry[bank]->size = size; + entry[bank]->ram_addr = ram_addr; + entry[bank]++; + } + } + + if (next < rombase || next > romend) + break; + + offset = next - rombase; + } + } + + for (bank = 0; bank < 3; bank++) { + size = (u32)entry[bank] - + (u32)(sarram + SAR_BANK2_OFFSET * bank); + sar_ram_layout[bank] = kmalloc(size + + sizeof(struct sar_ram_entry), GFP_KERNEL); + if (!sar_ram_layout[bank]) { + pr_err("%s: kmalloc failed\n", __func__); + goto cleanup; + } + memcpy(sar_ram_layout[bank], sarram + SAR_BANK2_OFFSET * bank, + size); + memset((void *)sar_ram_layout[bank] + size, 0, + sizeof(struct sar_ram_entry)); + entry[bank] = sar_ram_layout[bank]; + } + +cleanup: + kfree(sarram); + iounmap(sarrom); + pr_info("sar ram layout created\n"); + return ret; +} + +static struct sar_module omap44xx_sar_modules[] = { + { .base = OMAP44XX_EMIF1_BASE, .size = SZ_1M }, + { .base = OMAP44XX_EMIF2_BASE, .size = SZ_1M }, + { .base = OMAP44XX_DMM_BASE, .size = SZ_1M }, + { .base = OMAP4430_CM1_BASE, .size = SZ_8K }, + { .base = OMAP4430_CM2_BASE, .size = SZ_8K }, + { .base = OMAP44XX_C2C_BASE, .size = SZ_1M }, + { .base = OMAP443X_CTRL_BASE, .size = SZ_4K }, + { .base = L3_44XX_BASE_CLK1, .size = SZ_1M }, + { .base = L3_44XX_BASE_CLK2, .size = SZ_1M }, + { .base = L3_44XX_BASE_CLK3, .size = SZ_1M }, + { .base = OMAP44XX_USBTLL_BASE, .size = SZ_1M }, + { .base = OMAP44XX_UHH_CONFIG_BASE, .size = SZ_1M }, + { .base = L4_44XX_PHYS, .size = SZ_4M }, + { .base = L4_PER_44XX_PHYS, .size = SZ_4M }, + { .base = 0 }, +}; + /* * SAR RAM used to save and restore the HW * context in low power modes @@ -273,39 +399,11 @@ static int __init omap4_sar_ram_init(void) sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K); BUG_ON(!sar_ram_base); - /* - * All these are static mappings so ioremap() will - * just return with mapped VA - */ - omap4_sar_modules[EMIF1_INDEX] = ioremap(OMAP44XX_EMIF1_BASE, SZ_1M); - BUG_ON(!omap4_sar_modules[EMIF1_INDEX]); - omap4_sar_modules[EMIF2_INDEX] = ioremap(OMAP44XX_EMIF2_BASE, SZ_1M); - BUG_ON(!omap4_sar_modules[EMIF2_INDEX]); - omap4_sar_modules[DMM_INDEX] = ioremap(OMAP44XX_DMM_BASE, SZ_1M); - BUG_ON(!omap4_sar_modules[DMM_INDEX]); - omap4_sar_modules[CM1_INDEX] = ioremap(OMAP4430_CM1_BASE, SZ_8K); - BUG_ON(!omap4_sar_modules[CM1_INDEX]); - omap4_sar_modules[CM2_INDEX] = ioremap(OMAP4430_CM2_BASE, SZ_8K); - BUG_ON(!omap4_sar_modules[CM2_INDEX]); - omap4_sar_modules[C2C_INDEX] = ioremap(OMAP44XX_C2C_BASE, SZ_1M); - BUG_ON(!omap4_sar_modules[C2C_INDEX]); - omap4_sar_modules[CTRL_MODULE_PAD_CORE_INDEX] = - ioremap(OMAP443X_CTRL_BASE, SZ_4K); - BUG_ON(!omap4_sar_modules[CTRL_MODULE_PAD_CORE_INDEX]); - omap4_sar_modules[L3_CLK1_INDEX] = ioremap(L3_44XX_BASE_CLK1, SZ_1M); - BUG_ON(!omap4_sar_modules[L3_CLK1_INDEX]); - omap4_sar_modules[L3_CLK2_INDEX] = ioremap(L3_44XX_BASE_CLK2, SZ_1M); - BUG_ON(!omap4_sar_modules[L3_CLK2_INDEX]); - omap4_sar_modules[L3_CLK3_INDEX] = ioremap(L3_44XX_BASE_CLK3, SZ_1M); - BUG_ON(!omap4_sar_modules[L3_CLK3_INDEX]); - omap4_sar_modules[USBTLL_INDEX] = ioremap(OMAP44XX_USBTLL_BASE, SZ_1M); - BUG_ON(!omap4_sar_modules[USBTLL_INDEX]); - omap4_sar_modules[UHH_INDEX] = ioremap(OMAP44XX_UHH_CONFIG_BASE, SZ_1M); - BUG_ON(!omap4_sar_modules[UHH_INDEX]); - omap4_sar_modules[L4CORE_INDEX] = ioremap(L4_44XX_PHYS, SZ_4M); - BUG_ON(!omap4_sar_modules[L4CORE_INDEX]); - omap4_sar_modules[L4PER_INDEX] = ioremap(L4_PER_44XX_PHYS, SZ_4M); - BUG_ON(!omap4_sar_modules[L4PER_INDEX]); + sar_modules = omap44xx_sar_modules; + + sar_ioremap_modules(); + + sar_layout_generate(); /* * SAR BANK3 contains all firewall settings and it's saved through -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html