diff options
Diffstat (limited to 'drivers/mfd/glamo/glamo-core.c')
-rw-r--r-- | drivers/mfd/glamo/glamo-core.c | 269 |
1 files changed, 130 insertions, 139 deletions
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c index d4b526d41fa..ee339010f07 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,15 +1007,15 @@ static ssize_t regs_read(struct device *dev, struct device_attribute *attr, char * name; }; struct reg_range reg_range[] = { -/* { 0x0000, 0x200, "General" }, - { 0x0200, 0x100, "Host Bus" }, - { 0x0300, 0x100, "Memory" }, - { 0x0400, 0x100, "Sensor" }, + { 0x0000, 0x76, "General" }, +/* { 0x0200, 0x100, "Host Bus" }, +*/ { 0x0300, 0x38, "Memory" }, +/* { 0x0400, 0x100, "Sensor" }, { 0x0500, 0x300, "ISP" }, { 0x0800, 0x400, "JPEG" }, { 0x0c00, 0x500, "MPEG" }, */ - { 0x1100, 0x400, "LCD" }, + { 0x1100, 0x88, "LCD" }, /* { 0x1500, 0x080, "MPU 0" }, { 0x1580, 0x080, "MPU 1" }, @@ -1039,7 +1030,7 @@ 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) |