diff options
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1231-fix-glamo-suspend-resume-dram-and-engines.patch.patch')
-rw-r--r-- | target/linux/s3c24xx/patches-2.6.24/1231-fix-glamo-suspend-resume-dram-and-engines.patch.patch | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1231-fix-glamo-suspend-resume-dram-and-engines.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1231-fix-glamo-suspend-resume-dram-and-engines.patch.patch new file mode 100644 index 0000000..58070a6 --- /dev/null +++ b/target/linux/s3c24xx/patches-2.6.24/1231-fix-glamo-suspend-resume-dram-and-engines.patch.patch @@ -0,0 +1,428 @@ +From e1673170182af199be7c6a2a346d8bad7e4dc532 Mon Sep 17 00:00:00 2001 +From: Andy Green <andy@openmoko.com> +Date: Tue, 15 Jul 2008 09:04:00 +0100 +Subject: [PATCH] fix-glamo-suspend-resume-dram-and-engines.patch + +Two issues... we never took care to take down engines in suspend +and bring them back in resume. This was part of the display +corruption that could be seen briefly on resume. The other issue +that made the "noise" corruption was bad ordering of resume steps. + +This patch simplifies (removing needless re-init) resume actions +and makes explicit the suspend and resume steps. It also adds +code to track which engines are up and push them down in suspend +and bring them back in resume. + +The result is no more corruption of display buffer in suspend, it +comes back completely clean. + +Signed-off-by: Andy Green <andy@openmoko.com> +--- + drivers/mfd/glamo/glamo-core.c | 266 +++++++++++++++++++--------------------- + drivers/mfd/glamo/glamo-core.h | 2 + + drivers/mfd/glamo/glamo-regs.h | 6 +- + 3 files changed, 135 insertions(+), 139 deletions(-) + +diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c +index 2412b7d..bea0387 100644 +--- a/drivers/mfd/glamo/glamo-core.c ++++ b/drivers/mfd/glamo/glamo-core.c +@@ -54,6 +54,8 @@ + + #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1) + ++#define GLAMO_MEM_REFRESH_COUNT 0x100 ++ + static struct glamo_core *glamo_handle; + + static inline void __reg_write(struct glamo_core *glamo, +@@ -381,9 +383,8 @@ out_unlock: + * 'engine' support + ***********************************************************************/ + +-int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine) ++int __glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine) + { +- spin_lock(&glamo->lock); + switch (engine) { + case GLAMO_ENGINE_LCD: + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD, +@@ -432,27 +433,59 @@ int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine) + default: + break; + } +- spin_unlock(&glamo->lock); ++ ++ glamo->engine_enabled_bitfield |= 1 << engine; + + return 0; + } +-EXPORT_SYMBOL_GPL(glamo_engine_enable); + +-int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine) ++int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine) + { ++ int ret; ++ + spin_lock(&glamo->lock); ++ ++ ret = __glamo_engine_enable(glamo, engine); ++ ++ spin_unlock(&glamo->lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(glamo_engine_enable); ++ ++int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine) ++{ + switch (engine) { ++ case GLAMO_ENGINE_LCD: ++ /* remove pixel clock to LCM */ ++ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD, ++ GLAMO_CLOCK_LCD_EN_DCLK, 0); ++ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD, ++ GLAMO_CLOCK_LCD_EN_DHCLK | ++ GLAMO_CLOCK_LCD_EN_DMCLK, 0); ++ /* kill memory clock */ ++ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD, ++ GLAMO_CLOCK_LCD_EN_M5CLK, 0); ++ /* stop dividing the clocks */ ++ __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1, ++ GLAMO_CLOCK_GEN51_EN_DIV_DHCLK | ++ GLAMO_CLOCK_GEN51_EN_DIV_DMCLK | ++ GLAMO_CLOCK_GEN51_EN_DIV_DCLK, 0); ++ __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), ++ GLAMO_HOSTBUS2_MMIO_EN_LCD, 0); ++ break; ++ + case GLAMO_ENGINE_MMC: + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MMC, 0, + GLAMO_CLOCK_MMC_EN_M9CLK | + GLAMO_CLOCK_MMC_EN_TCLK | + GLAMO_CLOCK_MMC_DG_M9CLK | + GLAMO_CLOCK_MMC_DG_TCLK); +- __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), 0, +- GLAMO_HOSTBUS2_MMIO_EN_MMC); + /* disable the TCLK divider clk input */ + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1, 0, + GLAMO_CLOCK_GEN51_EN_DIV_TCLK); ++ __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), 0, ++ GLAMO_HOSTBUS2_MMIO_EN_MMC); + /* good idea to hold the thing in reset when we power it off? */ + /* writew(readw(glamo->base + GLAMO_REG_CLOCK_MMC) | + GLAMO_CLOCK_MMC_RESET, glamo->base + GLAMO_REG_CLOCK_MMC); +@@ -461,10 +494,23 @@ int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine) + default: + break; + } +- spin_unlock(&glamo->lock); ++ ++ glamo->engine_enabled_bitfield &= ~(1 << engine); + + return 0; + } ++int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine) ++{ ++ int ret; ++ ++ spin_lock(&glamo->lock); ++ ++ ret = __glamo_engine_disable(glamo, engine); ++ ++ spin_unlock(&glamo->lock); ++ ++ return ret; ++} + EXPORT_SYMBOL_GPL(glamo_engine_disable); + + struct glamo_script reset_regs[] = { +@@ -618,7 +664,7 @@ int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script, + if (may_sleep) + msleep(line->val); + else +- mdelay(line->val); ++ mdelay(line->val * 4); + break; + case 0xfffd: + /* spin until PLLs lock */ +@@ -717,111 +763,17 @@ static struct glamo_script glamo_init_script[] = { + { GLAMO_REG_CLOCK_MEMORY, 0x000b }, + }; + +-static struct glamo_script glamo_resume_script[] = { +- { GLAMO_REG_IRQ_ENABLE, 0x01ff }, +- { GLAMO_REG_CLOCK_GEN6, 0x2000 }, +- { GLAMO_REG_CLOCK_GEN7, 0x0001 }, /* 0101 */ +- { GLAMO_REG_CLOCK_GEN8, 0x0100 }, +- { GLAMO_REG_CLOCK_HOST, 0x000d }, +- { 0x200, 0x0ef0 }, +- { 0x202, 0x07ff }, +- { 0x212, 0x0000 }, +- { 0x214, 0x4000 }, +- { 0x216, 0xf00e }, +- { GLAMO_REG_MEM_TYPE, 0x0874 }, /* 8MB, 16 word pg wr+rd */ +- { GLAMO_REG_MEM_GEN, 0xafaf }, /* 63 grants min + max */ +- +- { GLAMO_REG_MEM_TIMING1, 0x0108 }, +- { GLAMO_REG_MEM_TIMING2, 0x0010 }, /* Taa = 3 MCLK */ +- { GLAMO_REG_MEM_TIMING3, 0x0000 }, +- { GLAMO_REG_MEM_TIMING4, 0x0000 }, /* CE1# delay fall/rise */ +- { GLAMO_REG_MEM_TIMING5, 0x0000 }, /* UB# LB# */ +- { GLAMO_REG_MEM_TIMING6, 0x0000 }, /* OE# */ +- { GLAMO_REG_MEM_TIMING7, 0x0000 }, /* WE# */ +- { GLAMO_REG_MEM_TIMING8, 0x1002 }, /* MCLK delay, was 0x1000 */ +- { GLAMO_REG_MEM_TIMING9, 0x6006 }, +- { GLAMO_REG_MEM_TIMING10, 0x00ff }, +- { GLAMO_REG_MEM_TIMING11, 0x0001 }, +- { GLAMO_REG_MEM_POWER1, 0x0020 }, +- { GLAMO_REG_MEM_POWER2, 0x0000 }, +- { GLAMO_REG_MEM_DRAM1, 0x0000 }, +- { 0xfffe, 1 }, +- { GLAMO_REG_MEM_DRAM1, 0xc100 }, +- { 0xfffe, 1 }, +- { GLAMO_REG_MEM_DRAM1, 0xe100 }, +- { GLAMO_REG_MEM_DRAM2, 0x01d6 }, +- { GLAMO_REG_CLOCK_MEMORY, 0x000b }, +-}; +- +-#if 0 /* MM370 */ +-static const struct glamo_script regs_vram_2mb = { +- { GLAMO_REG_CLOCK_MEMORY, 0x3aaa }, +- { 0xfffe, 50 }, +- { GLAMO_REG_CLOCK_MEMORY, 0x0aaa }, +- { 0xfffe, 3 }, +- { GLAMO_REG_MEM_POWER1, 0x0020 }, +- { 0x033a, 0x0000 }, +- { 0x033c, 0x0000 }, +- { 0x033e, 0x0000 }, +- { 0x0340, 0x0000 }, +- { 0x0342, 0x0000 }, +- { 0x0344, 0x0000 }, +- { 0x0346, 0x0240 }, +- { GLAMO_REG_MEM_TIMING8, 0x1016 }, +- { GLAMO_REG_MEM_TIMING9, 0x6067 }, +- { GLAMO_REG_MEM_TIMING10, 0x00ff }, +- { GLAMO_REG_MEM_TIMING11, 0x0030 }, +- { GLAMO_REG_MEM_GEN, 0x3fff }, +- { GLAMO_REG_MEM_GEN, 0xafaf }, +- { GLAMO_REG_MEM_TIMING1, 0x0108 }, +- { GLAMO_REG_MEM_TIMING2, 0x0010 }, +- { GLAMO_REG_MEM_DRAM1, 0x0a00 }, +- { 0xfffe, 3 }, +- { GLAMO_REG_MEM_DRAM1, 0xe200 }, +- { 0xfffe, 1 }, +-}; +- +-static const struct glamo_script regs_vram_8mb = { +- { GLAMO_REG_CLOCK_MEMORY, 0x3aaa }, +- { 0xfffe, 50 }, +- { GLAMO_REG_CLOCK_MEMORY, 0x0aaa }, +- { 0xfffe, 3 }, +- { GLAMO_REG_MEM_POWER1, 0x0020 }, +- { 0x033a, 0x45cf }, +- { 0x033c, 0x4240 }, +- { 0x033e, 0x53e0 }, +- { 0x0340, 0x1401 }, +- { 0x0342, 0x0c44 }, +- { 0x0344, 0x1d0b }, +- { 0x0346, 0x25ac }, +- { 0x0348, 0x1953 }, +- { 0xfffe, 1 }, +- { GLAMO_REG_MEM_TYPE, 0x087a }, +- { GLAMO_REG_MEM_DRAM2, 0x01d6 }, +- { GLAMO_REG_MEM_TIMING8, 0x1060 }, +- { GLAMO_REG_MEM_TIMING9, 0x6067 }, +- { GLAMO_REG_MEM_TIMING10, 0x00ff }, +- { GLAMO_REG_MEM_TIMING11, 0x0030 }, +- { GLAMO_REG_MEM_GEN, 0x3fff }, +- { GLAMO_REG_MEM_GEN, 0xafaf }, +- { GLAMO_REG_MEM_TIMING1, 0x3108 }, +- { GLAMO_REG_MEM_TIMING2, 0x0010 }, +- { GLAMO_REG_MEM_DRAM1, 0x0a00 }, +- { 0xfffe, 3 }, +- { GLAMO_REG_MEM_DRAM1, 0xe200 }, +- { 0xfffe, 1 }, +-}; +-#endif + + enum glamo_power { + GLAMO_POWER_ON, +- GLAMO_POWER_STANDBY, + GLAMO_POWER_SUSPEND, + }; + + static void glamo_power(struct glamo_core *glamo, + enum glamo_power new_state) + { ++ int n; ++ + spin_lock(&glamo->lock); + + dev_dbg(&glamo->pdev->dev, "***** glamo_power -> %d\n", new_state); +@@ -836,37 +788,76 @@ static void glamo_power(struct glamo_core *glamo, + while ((__reg_read(glamo, GLAMO_REG_PLL_GEN5) & 3) != 3) + ; + +- /* enable memory clock and get it out of deep pwrdown */ +- __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY, +- GLAMO_CLOCK_MEM_EN_MOCACLK, 0xffff); +- __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2, +- GLAMO_MEM_DRAM2_DEEP_PWRDOWN, 0x0000); +- __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM1, +- GLAMO_MEM_DRAM1_SELF_REFRESH, 0x0000); +- +- glamo_run_script(glamo, glamo_resume_script, +- ARRAY_SIZE(glamo_resume_script), 0); +- +- break; +- +- case GLAMO_POWER_STANDBY: +- /* enable memory self-refresh */ +- __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM1, +- GLAMO_MEM_DRAM1_SELF_REFRESH, 0xffff); +- /* stop memory clock */ +- __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY, +- GLAMO_CLOCK_MEM_EN_MOCACLK, 0x0000); +- /* power down PLL2 and then PLL1 */ +- __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0xffff); +- __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x0001, 0xffff); ++ /* Get memory out of deep powerdown */ ++ ++ __reg_write(glamo, GLAMO_REG_MEM_DRAM2, ++ (7 << 6) | /* tRC */ ++ (1 << 4) | /* tRP */ ++ (1 << 2) | /* tRCD */ ++ 2); /* CAS latency */ ++ ++ /* Stop self-refresh */ ++ ++ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, ++ GLAMO_MEM_DRAM1_EN_DRAM_REFRESH | ++ GLAMO_MEM_DRAM1_EN_GATE_CKE | ++ GLAMO_MEM_REFRESH_COUNT); ++ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, ++ GLAMO_MEM_DRAM1_EN_MODEREG_SET | ++ GLAMO_MEM_DRAM1_EN_DRAM_REFRESH | ++ GLAMO_MEM_DRAM1_EN_GATE_CKE | ++ GLAMO_MEM_REFRESH_COUNT); ++ ++ /* re-enable clocks to memory */ ++ ++ __reg_write(glamo, GLAMO_REG_CLOCK_MEMORY, ++ GLAMO_CLOCK_MEM_EN_MOCACLK | ++ GLAMO_CLOCK_MEM_EN_M1CLK | ++ GLAMO_CLOCK_MEM_DG_M1CLK); ++ ++ /* restore each engine that was up before suspend */ ++ for (n = 0; n < __NUM_GLAMO_ENGINES; n++) ++ if (glamo->engine_enabled_bitfield_suspend & (1 << n)) ++ __glamo_engine_enable(glamo, n); + break; + + case GLAMO_POWER_SUSPEND: +- __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2, +- GLAMO_MEM_DRAM2_DEEP_PWRDOWN, 0xffff); +- /* stop memory clock */ +- __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY, +- GLAMO_CLOCK_MEM_EN_MOCACLK, 0x0000); ++ /* stash a copy of which engines were running */ ++ glamo->engine_enabled_bitfield_suspend = ++ glamo->engine_enabled_bitfield; ++ ++ /* take down each engine before we kill mem and pll */ ++ for (n = 0; n < __NUM_GLAMO_ENGINES; n++) ++ if (glamo->engine_enabled_bitfield & (1 << n)) ++ __glamo_engine_disable(glamo, n); ++ ++ /* enable self-refresh */ ++ ++ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, ++ GLAMO_MEM_DRAM1_EN_DRAM_REFRESH | ++ GLAMO_MEM_DRAM1_EN_GATE_CKE | ++ GLAMO_MEM_DRAM1_SELF_REFRESH | ++ GLAMO_MEM_REFRESH_COUNT); ++ __reg_write(glamo, GLAMO_REG_MEM_DRAM1, ++ GLAMO_MEM_DRAM1_EN_MODEREG_SET | ++ GLAMO_MEM_DRAM1_EN_DRAM_REFRESH | ++ GLAMO_MEM_DRAM1_EN_GATE_CKE | ++ GLAMO_MEM_DRAM1_SELF_REFRESH | ++ GLAMO_MEM_REFRESH_COUNT); ++ ++ /* force RAM into deep powerdown */ ++ ++ __reg_write(glamo, GLAMO_REG_MEM_DRAM2, ++ GLAMO_MEM_DRAM2_DEEP_PWRDOWN | ++ (7 << 6) | /* tRC */ ++ (1 << 4) | /* tRP */ ++ (1 << 2) | /* tRCD */ ++ 2); /* CAS latency */ ++ ++ /* kill clocks to memory */ ++ ++ __reg_write(glamo, GLAMO_REG_CLOCK_MEMORY, 0); ++ + /* power down PLL2 and then PLL1 */ + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0xffff); + __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x0001, 0xffff); +@@ -1016,9 +1007,9 @@ static ssize_t regs_read(struct device *dev, struct device_attribute *attr, + char * name; + }; + struct reg_range reg_range[] = { +- { 0x0000, 0x200, "General" }, ++ { 0x0000, 0x76, "General" }, + { 0x0200, 0x100, "Host Bus" }, +- { 0x0300, 0x100, "Memory" }, ++ { 0x0300, 0x38, "Memory" }, + /* { 0x0400, 0x100, "Sensor" }, + { 0x0500, 0x300, "ISP" }, + { 0x0800, 0x400, "JPEG" }, +@@ -1037,12 +1028,11 @@ static ssize_t regs_read(struct device *dev, struct device_attribute *attr, + + for (r = 0; r < ARRAY_SIZE(reg_range); r++) { + n1 = 0; +- end += sprintf(end, "\n%s\n\n", reg_range[r].name); ++ end += sprintf(end, "\n%s\n", reg_range[r].name); + for (n = reg_range[r].start; + n < reg_range[r].start + reg_range[r].count; n += 2) { + if (((n1++) & 7) == 0) +- end += sprintf(end, "\n%04X: ", +- n + reg_range[r].start); ++ end += sprintf(end, "\n%04X: ", n); + end += sprintf(end, "%04x ", __reg_read(glamo, n)); + } + end += sprintf(end, "\n"); +diff --git a/drivers/mfd/glamo/glamo-core.h b/drivers/mfd/glamo/glamo-core.h +index 82b95f5..8d647ec 100644 +--- a/drivers/mfd/glamo/glamo-core.h ++++ b/drivers/mfd/glamo/glamo-core.h +@@ -30,6 +30,8 @@ struct glamo_core { + u_int16_t revision; + spinlock_t lock; + struct resume_dependency resume_dependency; ++ u32 engine_enabled_bitfield; ++ u32 engine_enabled_bitfield_suspend; + }; + + struct glamo_script { +diff --git a/drivers/mfd/glamo/glamo-regs.h b/drivers/mfd/glamo/glamo-regs.h +index 32411e3..2328b8a 100644 +--- a/drivers/mfd/glamo/glamo-regs.h ++++ b/drivers/mfd/glamo/glamo-regs.h +@@ -142,8 +142,12 @@ enum glamo_register_mem { + #define GLAMO_MEM_TYPE_MASK 0x03 + + enum glamo_reg_mem_dram1 { +- GLAMO_MEM_DRAM1_EN_SDRAM_CLK = (1 << 11), ++ /* b0 - b10 == refresh period, 1 -> 2048 clocks */ ++ GLAMO_MEM_DRAM1_EN_GATE_CLK = (1 << 11), + GLAMO_MEM_DRAM1_SELF_REFRESH = (1 << 12), ++ GLAMO_MEM_DRAM1_EN_GATE_CKE = (1 << 13), ++ GLAMO_MEM_DRAM1_EN_DRAM_REFRESH = (1 << 14), ++ GLAMO_MEM_DRAM1_EN_MODEREG_SET = (1 << 15), + }; + + enum glamo_reg_mem_dram2 { +-- +1.5.6.5 + |