Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * BRIEF MODULE DESCRIPTION
0003  *  Au1xx0 Power Management routines.
0004  *
0005  * Copyright 2001, 2008 MontaVista Software Inc.
0006  * Author: MontaVista Software, Inc. <source@mvista.com>
0007  *
0008  *  Some of the routines are right out of init/main.c, whose
0009  *  copyrights apply here.
0010  *
0011  *  This program is free software; you can redistribute  it and/or modify it
0012  *  under  the terms of  the GNU General  Public License as published by the
0013  *  Free Software Foundation;  either version 2 of the  License, or (at your
0014  *  option) any later version.
0015  *
0016  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
0017  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
0018  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
0019  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
0020  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0021  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
0022  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
0023  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
0024  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0025  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026  *
0027  *  You should have received a copy of the  GNU General Public License along
0028  *  with this program; if not, write  to the Free Software Foundation, Inc.,
0029  *  675 Mass Ave, Cambridge, MA 02139, USA.
0030  */
0031 
0032 #include <linux/pm.h>
0033 #include <linux/sysctl.h>
0034 #include <linux/jiffies.h>
0035 
0036 #include <linux/uaccess.h>
0037 #include <asm/mach-au1x00/au1000.h>
0038 
0039 /*
0040  * We need to save/restore a bunch of core registers that are
0041  * either volatile or reset to some state across a processor sleep.
0042  * If reading a register doesn't provide a proper result for a
0043  * later restore, we have to provide a function for loading that
0044  * register and save a copy.
0045  *
0046  * We only have to save/restore registers that aren't otherwise
0047  * done as part of a driver pm_* function.
0048  */
0049 static unsigned int sleep_sys_clocks[5];
0050 static unsigned int sleep_sys_pinfunc;
0051 static unsigned int sleep_static_memctlr[4][3];
0052 
0053 
0054 static void save_core_regs(void)
0055 {
0056     /* Clocks and PLLs. */
0057     sleep_sys_clocks[0] = alchemy_rdsys(AU1000_SYS_FREQCTRL0);
0058     sleep_sys_clocks[1] = alchemy_rdsys(AU1000_SYS_FREQCTRL1);
0059     sleep_sys_clocks[2] = alchemy_rdsys(AU1000_SYS_CLKSRC);
0060     sleep_sys_clocks[3] = alchemy_rdsys(AU1000_SYS_CPUPLL);
0061     sleep_sys_clocks[4] = alchemy_rdsys(AU1000_SYS_AUXPLL);
0062 
0063     /* pin mux config */
0064     sleep_sys_pinfunc = alchemy_rdsys(AU1000_SYS_PINFUNC);
0065 
0066     /* Save the static memory controller configuration. */
0067     sleep_static_memctlr[0][0] = alchemy_rdsmem(AU1000_MEM_STCFG0);
0068     sleep_static_memctlr[0][1] = alchemy_rdsmem(AU1000_MEM_STTIME0);
0069     sleep_static_memctlr[0][2] = alchemy_rdsmem(AU1000_MEM_STADDR0);
0070     sleep_static_memctlr[1][0] = alchemy_rdsmem(AU1000_MEM_STCFG1);
0071     sleep_static_memctlr[1][1] = alchemy_rdsmem(AU1000_MEM_STTIME1);
0072     sleep_static_memctlr[1][2] = alchemy_rdsmem(AU1000_MEM_STADDR1);
0073     sleep_static_memctlr[2][0] = alchemy_rdsmem(AU1000_MEM_STCFG2);
0074     sleep_static_memctlr[2][1] = alchemy_rdsmem(AU1000_MEM_STTIME2);
0075     sleep_static_memctlr[2][2] = alchemy_rdsmem(AU1000_MEM_STADDR2);
0076     sleep_static_memctlr[3][0] = alchemy_rdsmem(AU1000_MEM_STCFG3);
0077     sleep_static_memctlr[3][1] = alchemy_rdsmem(AU1000_MEM_STTIME3);
0078     sleep_static_memctlr[3][2] = alchemy_rdsmem(AU1000_MEM_STADDR3);
0079 }
0080 
0081 static void restore_core_regs(void)
0082 {
0083     /* restore clock configuration.  Writing CPUPLL last will
0084      * stall a bit and stabilize other clocks (unless this is
0085      * one of those Au1000 with a write-only PLL, where we dont
0086      * have a valid value)
0087      */
0088     alchemy_wrsys(sleep_sys_clocks[0], AU1000_SYS_FREQCTRL0);
0089     alchemy_wrsys(sleep_sys_clocks[1], AU1000_SYS_FREQCTRL1);
0090     alchemy_wrsys(sleep_sys_clocks[2], AU1000_SYS_CLKSRC);
0091     alchemy_wrsys(sleep_sys_clocks[4], AU1000_SYS_AUXPLL);
0092     if (!au1xxx_cpu_has_pll_wo())
0093         alchemy_wrsys(sleep_sys_clocks[3], AU1000_SYS_CPUPLL);
0094 
0095     alchemy_wrsys(sleep_sys_pinfunc, AU1000_SYS_PINFUNC);
0096 
0097     /* Restore the static memory controller configuration. */
0098     alchemy_wrsmem(sleep_static_memctlr[0][0], AU1000_MEM_STCFG0);
0099     alchemy_wrsmem(sleep_static_memctlr[0][1], AU1000_MEM_STTIME0);
0100     alchemy_wrsmem(sleep_static_memctlr[0][2], AU1000_MEM_STADDR0);
0101     alchemy_wrsmem(sleep_static_memctlr[1][0], AU1000_MEM_STCFG1);
0102     alchemy_wrsmem(sleep_static_memctlr[1][1], AU1000_MEM_STTIME1);
0103     alchemy_wrsmem(sleep_static_memctlr[1][2], AU1000_MEM_STADDR1);
0104     alchemy_wrsmem(sleep_static_memctlr[2][0], AU1000_MEM_STCFG2);
0105     alchemy_wrsmem(sleep_static_memctlr[2][1], AU1000_MEM_STTIME2);
0106     alchemy_wrsmem(sleep_static_memctlr[2][2], AU1000_MEM_STADDR2);
0107     alchemy_wrsmem(sleep_static_memctlr[3][0], AU1000_MEM_STCFG3);
0108     alchemy_wrsmem(sleep_static_memctlr[3][1], AU1000_MEM_STTIME3);
0109     alchemy_wrsmem(sleep_static_memctlr[3][2], AU1000_MEM_STADDR3);
0110 }
0111 
0112 void au_sleep(void)
0113 {
0114     save_core_regs();
0115 
0116     switch (alchemy_get_cputype()) {
0117     case ALCHEMY_CPU_AU1000:
0118     case ALCHEMY_CPU_AU1500:
0119     case ALCHEMY_CPU_AU1100:
0120         alchemy_sleep_au1000();
0121         break;
0122     case ALCHEMY_CPU_AU1550:
0123     case ALCHEMY_CPU_AU1200:
0124         alchemy_sleep_au1550();
0125         break;
0126     case ALCHEMY_CPU_AU1300:
0127         alchemy_sleep_au1300();
0128         break;
0129     }
0130 
0131     restore_core_regs();
0132 }