1/* linux/arch/arm/mach-s3c64xx/include/mach/pm-core.h 2 * 3 * Copyright 2008 Openmoko, Inc. 4 * Copyright 2008 Simtec Electronics 5 * Ben Dooks <ben@simtec.co.uk> 6 * http://armlinux.simtec.co.uk/ 7 * 8 * S3C64XX - PM core support for arch/arm/plat-s3c/pm.c 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#ifndef __MACH_S3C64XX_PM_CORE_H 16#define __MACH_S3C64XX_PM_CORE_H __FILE__ 17 18#include <linux/serial_s3c.h> 19 20#include <mach/regs-gpio.h> 21 22static inline void s3c_pm_debug_init_uart(void) 23{ 24 u32 tmp = __raw_readl(S3C_PCLK_GATE); 25 26 /* As a note, since the S3C64XX UARTs generally have multiple 27 * clock sources, we simply enable PCLK at the moment and hope 28 * that the resume settings for the UART are suitable for the 29 * use with PCLK. 30 */ 31 32 tmp |= S3C_CLKCON_PCLK_UART0; 33 tmp |= S3C_CLKCON_PCLK_UART1; 34 tmp |= S3C_CLKCON_PCLK_UART2; 35 tmp |= S3C_CLKCON_PCLK_UART3; 36 37 __raw_writel(tmp, S3C_PCLK_GATE); 38 udelay(10); 39} 40 41static inline void s3c_pm_arch_prepare_irqs(void) 42{ 43 /* VIC should have already been taken care of */ 44 45 /* clear any pending EINT0 interrupts */ 46 __raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND); 47} 48 49static inline void s3c_pm_arch_stop_clocks(void) 50{ 51} 52 53static inline void s3c_pm_arch_show_resume_irqs(void) 54{ 55} 56 57/* make these defines, we currently do not have any need to change 58 * the IRQ wake controls depending on the CPU we are running on */ 59 60#define s3c_irqwake_eintallow ((1 << 28) - 1) 61#define s3c_irqwake_intallow (~0) 62 63static inline void s3c_pm_arch_update_uart(void __iomem *regs, 64 struct pm_uart_save *save) 65{ 66 u32 ucon = __raw_readl(regs + S3C2410_UCON); 67 u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK; 68 u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK; 69 u32 new_ucon; 70 u32 delta; 71 72 /* S3C64XX UART blocks only support level interrupts, so ensure that 73 * when we restore unused UART blocks we force the level interrupt 74 * settigs. */ 75 save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL; 76 77 /* We have a constraint on changing the clock type of the UART 78 * between UCLKx and PCLK, so ensure that when we restore UCON 79 * that the CLK field is correctly modified if the bootloader 80 * has changed anything. 81 */ 82 if (ucon_clk != save_clk) { 83 new_ucon = save->ucon; 84 delta = ucon_clk ^ save_clk; 85 86 /* change from UCLKx => wrong PCLK, 87 * either UCLK can be tested for by a bit-test 88 * with UCLK0 */ 89 if (ucon_clk & S3C6400_UCON_UCLK0 && 90 !(save_clk & S3C6400_UCON_UCLK0) && 91 delta & S3C6400_UCON_PCLK2) { 92 new_ucon &= ~S3C6400_UCON_UCLK0; 93 } else if (delta == S3C6400_UCON_PCLK2) { 94 /* as an precaution, don't change from 95 * PCLK2 => PCLK or vice-versa */ 96 new_ucon ^= S3C6400_UCON_PCLK2; 97 } 98 99 S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n", 100 ucon, new_ucon, save->ucon); 101 save->ucon = new_ucon; 102 } 103} 104 105static inline void s3c_pm_restored_gpios(void) 106{ 107 /* ensure sleep mode has been cleared from the system */ 108 109 __raw_writel(0, S3C64XX_SLPEN); 110} 111 112static inline void samsung_pm_saved_gpios(void) 113{ 114 /* turn on the sleep mode and keep it there, as it seems that during 115 * suspend the xCON registers get re-set and thus you can end up with 116 * problems between going to sleep and resuming. 117 */ 118 119 __raw_writel(S3C64XX_SLPEN_USE_xSLP, S3C64XX_SLPEN); 120} 121#endif /* __MACH_S3C64XX_PM_CORE_H */ 122