From 9d6e27160ddcd316d5b5fc9a2caf74d340e2ba93 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 19 Nov 2008 17:11:11 +0000 Subject: glamo-resume-meddling.patch Big chunk of trying to own Glamo resume and not really succeeding Signed-off-by: Andy Green --- drivers/mfd/glamo/glamo-core.c | 169 ++++++++++++++++++----------------------- drivers/mfd/glamo/glamo-core.h | 2 +- drivers/mfd/glamo/glamo-fb.c | 77 ++++++++++++++++++- 3 files changed, 152 insertions(+), 96 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c index 1d7d235f0da..2ddc0357588 100644 --- a/drivers/mfd/glamo/glamo-core.c +++ b/drivers/mfd/glamo/glamo-core.c @@ -393,6 +393,7 @@ static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc) int __glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine) { + printk(KERN_ERR" __glamo_engine_enable %d\n", engine); switch (engine) { case GLAMO_ENGINE_LCD: __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD, @@ -411,14 +412,19 @@ int __glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine) 0xffff); break; case GLAMO_ENGINE_MMC: + /* enable access to MMC unit */ + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), + GLAMO_HOSTBUS2_MMIO_EN_MMC, + GLAMO_HOSTBUS2_MMIO_EN_MMC); __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MMC, GLAMO_CLOCK_MMC_EN_M9CLK | GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK | GLAMO_CLOCK_MMC_DG_TCLK, 0xffff); - __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), - GLAMO_HOSTBUS2_MMIO_EN_MMC, - GLAMO_HOSTBUS2_MMIO_EN_MMC); + /* enable the TCLK divider clk input */ + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1, + GLAMO_CLOCK_GEN51_EN_DIV_TCLK, + GLAMO_CLOCK_GEN51_EN_DIV_TCLK); break; case GLAMO_ENGINE_2D: __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D, @@ -463,6 +469,7 @@ EXPORT_SYMBOL_GPL(glamo_engine_enable); int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine) { + printk(KERN_ERR" __glamo_engine_disable %d\n", engine); switch (engine) { case GLAMO_ENGINE_LCD: /* remove pixel clock to LCM */ @@ -479,25 +486,22 @@ int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine) 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); +// __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, + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MMC, GLAMO_CLOCK_MMC_EN_M9CLK | GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK | - GLAMO_CLOCK_MMC_DG_TCLK); + GLAMO_CLOCK_MMC_DG_TCLK, 0); /* 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); -*/ + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1, + GLAMO_CLOCK_GEN51_EN_DIV_TCLK, 0); + /* kill access to MMC unit */ +// __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2), +// GLAMO_HOSTBUS2_MMIO_EN_MMC, 0); break; default: break; @@ -589,15 +593,8 @@ void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine) spin_lock(&glamo->lock); __reg_set_bit(glamo, rst->reg, rst->val); - spin_unlock(&glamo->lock); - - msleep(1); - - spin_lock(&glamo->lock); __reg_clear_bit(glamo, rst->reg, rst->val); spin_unlock(&glamo->lock); - - msleep(1); } EXPORT_SYMBOL_GPL(glamo_engine_reset); @@ -816,71 +813,75 @@ 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); + /* +Power management +static const REG_VALUE_MASK_TYPE reg_powerOn[] = +{ + { REG_GEN_DFT6, REG_BIT_ALL, REG_DATA(1u << 0) }, + { REG_GEN_PLL3, 0u, REG_DATA(1u << 13) }, + { REG_GEN_MEM_CLK, REG_BIT_ALL, REG_BIT_EN_MOCACLK }, + { REG_MEM_DRAM2, 0u, REG_BIT_EN_DEEP_POWER_DOWN }, + { REG_MEM_DRAM1, 0u, REG_BIT_SELF_REFRESH } +}; + +static const REG_VALUE_MASK_TYPE reg_powerStandby[] = +{ + { REG_MEM_DRAM1, REG_BIT_ALL, REG_BIT_SELF_REFRESH }, + { REG_GEN_MEM_CLK, 0u, REG_BIT_EN_MOCACLK }, + { REG_GEN_PLL3, REG_BIT_ALL, REG_DATA(1u << 13) }, + { REG_GEN_DFT5, REG_BIT_ALL, REG_DATA(1u << 0) } +}; + +static const REG_VALUE_MASK_TYPE reg_powerSuspend[] = +{ + { REG_MEM_DRAM2, REG_BIT_ALL, REG_BIT_EN_DEEP_POWER_DOWN }, + { REG_GEN_MEM_CLK, 0u, REG_BIT_EN_MOCACLK }, + { REG_GEN_PLL3, REG_BIT_ALL, REG_DATA(1u << 13) }, + { REG_GEN_DFT5, REG_BIT_ALL, REG_DATA(1u << 0) } +}; +*/ + switch (new_state) { case GLAMO_POWER_ON: + /* power up PLL1 and PLL2 */ - __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN6, 0x0001, 0xffff); - __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 0x2000, 0x0000); + __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN6, 1, 1); + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 1 << 13, 0); /* spin until PLL1 and PLL2 lock */ while ((__reg_read(glamo, GLAMO_REG_PLL_GEN5) & 3) != 3) ; - /* allow to use the PLLS */ - __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x400, 0); - - /* - * we can go back to using fast PLL as host bus clock source - */ - __reg_write(glamo, 0x200, 0x0e03); - + /* re-enable clocks to memory */ + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY, + GLAMO_CLOCK_MEM_EN_MOCACLK, GLAMO_CLOCK_MEM_EN_MOCACLK); /* 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_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2, + GLAMO_MEM_DRAM2_DEEP_PWRDOWN, 0); + /* clear selfrefresh */ - __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); + __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM1, 1 << 12, 0); /* 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); + + /* allow interrupts */ + __reg_write(glamo, GLAMO_REG_IRQ_ENABLE, 0x1ff); + break; case GLAMO_POWER_SUSPEND: - /* we like to use fast PLL as host bus clock now normally. - * but since we close down the PLLs, this is not going to fly - * during suspend - resume - */ - __reg_write(glamo, 0x200, 0x0e00); - /* disallow PLLS (use CLKI) */ - __reg_set_bit_mask(glamo, GLAMO_REG_DFT_GEN5, 0x400, 0x400); + /* nuke interrupts */ + __reg_write(glamo, GLAMO_REG_IRQ_ENABLE, 0x200); /* stash a copy of which engines were running */ glamo->engine_enabled_bitfield_suspend = @@ -890,37 +891,16 @@ static void glamo_power(struct glamo_core *glamo, 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); + __reg_set_bit_mask(glamo, GLAMO_REG_MEM_DRAM2, + GLAMO_MEM_DRAM2_DEEP_PWRDOWN, GLAMO_MEM_DRAM2_DEEP_PWRDOWN); + /* disable clocks to memory */ + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MEMORY, + GLAMO_CLOCK_MEM_EN_MOCACLK, 0); + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 1 << 13, 1 << 13); + __reg_write(glamo, GLAMO_REG_DFT_GEN5, 0x0001); - /* 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); break; } @@ -1313,15 +1293,16 @@ static int glamo_remove(struct platform_device *pdev) static int glamo_suspend(struct platform_device *pdev, pm_message_t state) { + glamo_handle->suspending = 1; glamo_power(glamo_handle, GLAMO_POWER_SUSPEND); - glamo_handle->is_suspended = 1; - activate_all_resume_dependencies(&glamo_handle->resume_dependency); + return 0; } static int glamo_resume(struct platform_device *pdev) { glamo_power(glamo_handle, GLAMO_POWER_ON); + glamo_handle->suspending = 0; return 0; } diff --git a/drivers/mfd/glamo/glamo-core.h b/drivers/mfd/glamo/glamo-core.h index 58aa72ec6bc..c7b76f83b27 100644 --- a/drivers/mfd/glamo/glamo-core.h +++ b/drivers/mfd/glamo/glamo-core.h @@ -31,7 +31,7 @@ struct glamo_core { struct resume_dependency resume_dependency; u32 engine_enabled_bitfield; u32 engine_enabled_bitfield_suspend; - int is_suspended; + int suspending; }; struct glamo_script { diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c index b886c4e693b..26a6d29ddba 100644 --- a/drivers/mfd/glamo/glamo-fb.c +++ b/drivers/mfd/glamo/glamo-fb.c @@ -125,6 +125,12 @@ static int glamofb_run_script(struct glamofb_handle *glamo, { int i; + if (glamo->mach_info->glamo->suspending) { + dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_run_script while " + "suspended\n"); + return -EBUSY; + } + for (i = 0; i < len; i++) { struct glamo_script *line = &script[i]; @@ -144,6 +150,12 @@ static int glamofb_check_var(struct fb_var_screeninfo *var, { struct glamofb_handle *glamo = info->par; + if (glamo->mach_info->glamo->suspending) { + dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_check_var while " + "suspended\n"); + return -EBUSY; + } + if (var->yres > glamo->mach_info->yres.max) var->yres = glamo->mach_info->yres.max; else if (var->yres < glamo->mach_info->yres.min) @@ -240,6 +252,12 @@ static void __rotate_lcd(struct glamofb_handle *glamo, __u32 rotation) { int glamo_rot; + if (glamo->mach_info->glamo->suspending) { + dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING rotate_lcd while " + "suspended\n"); + return; + } + switch (rotation) { case FB_ROTATE_UR: glamo_rot = GLAMO_LCD_ROT_MODE_0; @@ -305,6 +323,12 @@ static void glamofb_update_lcd_controller(struct glamofb_handle *glamo, if (!glamo || !var) return; + if (glamo->mach_info->glamo->suspending) { + dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_update_lcd_controller while " + "suspended\n"); + return; + } + printk(KERN_ERR"glamofb_update_lcd_controller spin_lock_irqsave\n"); spin_lock_irqsave(&glamo->lock_cmd, flags); @@ -405,6 +429,12 @@ static int glamofb_set_par(struct fb_info *info) struct glamofb_handle *glamo = info->par; struct fb_var_screeninfo *var = &info->var; + if (glamo->mach_info->glamo->suspending) { + dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_set_par while " + "suspended\n"); + return -EBUSY; + } + switch (var->bits_per_pixel) { case 16: info->fix.visual = FB_VISUAL_TRUECOLOR; @@ -469,6 +499,12 @@ static int glamofb_setcolreg(unsigned regno, struct glamofb_handle *glamo = info->par; unsigned int val; + if (glamo->mach_info->glamo->suspending) { + dev_err(&glamo->mach_info->glamo->pdev->dev, "IGNORING glamofb_set_par while " + "suspended\n"); + return -EBUSY; + } + switch (glamo->fb->fix.visual) { case FB_VISUAL_TRUECOLOR: case FB_VISUAL_DIRECTCOLOR: @@ -631,6 +667,12 @@ int glamofb_cmd_mode(struct glamofb_handle *gfb, int on) { int timeout = 2000000; + if (gfb->mach_info->glamo->suspending) { + dev_err(&gfb->mach_info->glamo->pdev->dev, "IGNORING glamofb_cmd_mode while " + "suspended\n"); + return -EBUSY; + } + dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on); if (on) { dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ", @@ -688,6 +730,12 @@ int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val) { int timeout = 200000; + if (gfb->mach_info->glamo->suspending) { + dev_err(&gfb->mach_info->glamo->pdev->dev, "IGNORING glamofb_cmd_write while " + "suspended\n"); + return -EBUSY; + } + dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", __FUNCTION__); while ((!glamofb_cmdq_empty(gfb)) && (timeout--)) yield(); @@ -799,7 +847,7 @@ static int __init glamofb_probe(struct platform_device *pdev) } glamofb->cursor_addr = fbinfo->screen_base + 0xf0000; - platform_set_drvdata(pdev, fbinfo); + platform_set_drvdata(pdev, glamofb); glamofb->mach_info = pdev->dev.platform_data; @@ -891,9 +939,36 @@ static int glamofb_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM + +static int glamofb_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct glamofb_handle *gfb = platform_get_drvdata(pdev); + + if (state.event & PM_EVENT_SLEEP) + fb_set_suspend(gfb->fb, 1); + + return 0; +} + +static int glamofb_resume(struct platform_device *pdev) +{ + struct glamofb_handle *gfb = platform_get_drvdata(pdev); + + fb_set_suspend(gfb->fb, 0); + + return 0; +} +#else +#define glamo_suspend NULL +#define glamo_resume NULL +#endif + static struct platform_driver glamofb_driver = { .probe = glamofb_probe, .remove = glamofb_remove, + .suspend = glamofb_suspend, + .resume = glamofb_resume, .driver = { .name = "glamo-fb", .owner = THIS_MODULE, -- cgit v1.2.3