From 185b919e5feec94641cdf7f4c9ca9fecfa9eb59a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 5 Mar 2010 02:56:25 +0000 Subject: [PATCH] jz4740 pm: Fix gpio suspend/resume. Turn pll off while in suspend and gate clocks off which arn't handeld by their subsystems yet. SVN-Revision: 19984 --- .../arch/mips/jz4740/board-n526.c | 2 +- .../arch/mips/jz4740/board-qi_lb60.c | 2 +- .../files-2.6.32/arch/mips/jz4740/clock.c | 23 ++++++++++--- .../files-2.6.32/arch/mips/jz4740/clock.h | 4 ++- .../files-2.6.32/arch/mips/jz4740/gpio.c | 33 +++++++++++-------- .../xburst/files-2.6.32/arch/mips/jz4740/pm.c | 8 +++++ 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-n526.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-n526.c index 6e65417eb9..e3e671011e 100644 --- a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-n526.c +++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-n526.c @@ -321,7 +321,7 @@ static int __init n526_board_setup(void) if (jz_gpiolib_init()) panic("Failed to initalize jz gpio\n"); - jz4740_init_clocks(); + jz4740_clock_init(); board_gpio_setup(); if (n526_init_platform_devices()) diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c index 3866b8d717..8004417160 100644 --- a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c +++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/board-qi_lb60.c @@ -412,7 +412,7 @@ static int __init qi_lb60_board_setup(void) if (jz_gpiolib_init()) panic("Failed to initalize jz gpio\n"); - jz_init_clocks(); + jz4740_clock_init(); board_gpio_setup(); if (qi_lb60_init_platform_devices()) diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.c index 26ae08d7c1..12a54ed9f6 100644 --- a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.c +++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.c @@ -158,7 +158,7 @@ static int jz_clk_enable_gating(struct clk *clk) { if (clk->gate_bit == JZ4740_CLK_NOT_GATED) return -EINVAL; - + jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit); return 0; } @@ -873,7 +873,24 @@ void jz4740_clock_udc_enable_auto_suspend(void) } EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend); -int jz_init_clocks(void) +void jz4740_clock_suspend(void) +{ + jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, + JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); + + jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); +} + +void jz4740_clock_resume(void) +{ + jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED); + while ((jz_clk_reg_read(JZ_REG_CLOCK_PLL) & JZ_CLOCK_PLL_STABLE) == 0); + + jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, + JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0); +} + +int jz4740_clock_init(void) { uint32_t val; @@ -905,5 +922,3 @@ int jz_init_clocks(void) return 0; } -EXPORT_SYMBOL_GPL(jz_init_clocks); - diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.h b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.h index e0fd9ece5d..9c91f0d94b 100644 --- a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.h +++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/clock.h @@ -23,7 +23,9 @@ struct jz4740_clock_board_data { extern struct jz4740_clock_board_data jz4740_clock_bdata; -int jz_init_clocks(void); +int jz4740_clock_init(void); +void jz4740_clock_suspend(void); +void jz4740_clock_resume(void); struct clk; diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/gpio.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/gpio.c index 30f83fa09f..60d6053840 100644 --- a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/gpio.c +++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/gpio.c @@ -106,6 +106,7 @@ int jz_gpio_set_function(int gpio, enum jz_gpio_function function) jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR); } else { jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_SET); + jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR); switch (function) { case JZ_GPIO_FUNC1: jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR); @@ -164,7 +165,8 @@ void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num for (i = 0; i < num; ++i, ++request) { jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); - jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_DIRECTION_SET); + jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_DIRECTION_CLEAR); + jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_PULL_SET); } } EXPORT_SYMBOL_GPL(jz_gpio_bulk_suspend); @@ -431,20 +433,35 @@ static struct jz_gpio_chip jz_gpio_chips[] = { JZ_GPIO_CHIP(D), }; -static int jz_gpio_suspend(struct sys_device *dev, pm_message_t state) +int jz_gpio_suspend(void) { struct jz_gpio_chip *chip = jz_gpio_chips; int i, gpio; + for (i = 0; i < ARRAY_SIZE(jz_gpio_chips); ++i, ++chip) { gpio = chip->gpio_chip.base; chip->suspend_mask = readl(GPIO_TO_REG(gpio, JZ_REG_GPIO_MASK)); writel(~(chip->wakeup), GPIO_TO_REG(gpio, JZ_REG_GPIO_MASK_SET)); } + chip = jz_gpio_chips; +#if 0 + for (i = 0; i < ARRAY_SIZE(jz_gpio_chips); ++i, ++chip) { + printk("GPIO %d: \n", i); + printk("\tPin: %.8x\n", readl(CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_PIN))); + printk("\tData: %.8x\n", readl(CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_DATA))); + printk("\tPull: %.8x\n", readl(CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_PULL))); + printk("\tFunc: %.8x\n", readl(CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_FUNC))); + printk("\tSelect: %.8x\n", readl(CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_SELECT))); + printk("\tDirection: %.8x\n", readl(CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_DIRECTION))); + printk("\tTrigger: %.8x\n", readl(CHIP_TO_REG(&chip->gpio_chip, JZ_REG_GPIO_TRIGGER))); + } +#endif + return 0; } -static int jz_gpio_resume(struct sys_device *dev) +int jz_gpio_resume(void) { struct jz_gpio_chip *chip = jz_gpio_chips; int i; @@ -455,12 +472,6 @@ static int jz_gpio_resume(struct sys_device *dev) return 0; } -static struct sysdev_class jz_gpio_sysdev = { - .name = "JZ4740 GPIO", - .suspend = jz_gpio_suspend, - .resume = jz_gpio_resume, -}; - int __init jz_gpiolib_init(void) { struct jz_gpio_chip *chip = jz_gpio_chips; @@ -480,11 +491,7 @@ int __init jz_gpiolib_init(void) } } - sysdev_class_register(&jz_gpio_sysdev); - printk("JZ GPIO initalized\n"); return 0; } - - diff --git a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/pm.c b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/pm.c index 9fb0cebaba..e7e463ef3d 100644 --- a/target/linux/xburst/files-2.6.32/arch/mips/jz4740/pm.c +++ b/target/linux/xburst/files-2.6.32/arch/mips/jz4740/pm.c @@ -20,12 +20,18 @@ #include #include +#include "clock.h" + extern void jz4740_intc_suspend(void); extern void jz4740_intc_resume(void); +extern void jz_gpio_suspend(void); +extern void jz_gpio_resume(void); static int jz_pm_enter(suspend_state_t state) { + jz_gpio_suspend(); jz4740_intc_suspend(); + jz4740_clock_suspend(); jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_SLEEP); @@ -35,7 +41,9 @@ static int jz_pm_enter(suspend_state_t state) jz4740_clock_set_wait_mode(JZ4740_WAIT_MODE_IDLE); + jz4740_clock_resume(); jz4740_intc_resume(); + jz_gpio_resume(); return 0; } -- 2.25.1