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 <[email protected]>
---
 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 <[email protected]>
+ * Santosh Shilimkar <[email protected]>
+ * Tero Kristo <[email protected]>
  *
  * 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to