linux/arch/arm/mach-at91/pm.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-at91/pm.c
   3 * AT91 Power Management
   4 *
   5 * Copyright (C) 2005 David Brownell
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 */
  12
  13#include <linux/suspend.h>
  14#include <linux/sched.h>
  15#include <linux/proc_fs.h>
  16#include <linux/interrupt.h>
  17#include <linux/sysfs.h>
  18#include <linux/module.h>
  19#include <linux/platform_device.h>
  20#include <linux/io.h>
  21
  22#include <asm/irq.h>
  23#include <asm/atomic.h>
  24#include <asm/mach/time.h>
  25#include <asm/mach/irq.h>
  26
  27#include <mach/at91_pmc.h>
  28#include <mach/gpio.h>
  29#include <mach/cpu.h>
  30
  31#include "generic.h"
  32
  33#ifdef CONFIG_ARCH_AT91RM9200
  34#include <mach/at91rm9200_mc.h>
  35
  36/*
  37 * The AT91RM9200 goes into self-refresh mode with this command, and will
  38 * terminate self-refresh automatically on the next SDRAM access.
  39 */
  40#define sdram_selfrefresh_enable()      at91_sys_write(AT91_SDRAMC_SRR, 1)
  41#define sdram_selfrefresh_disable()     do {} while (0)
  42
  43#elif defined(CONFIG_ARCH_AT91CAP9)
  44#include <mach/at91cap9_ddrsdr.h>
  45
  46static u32 saved_lpr;
  47
  48static inline void sdram_selfrefresh_enable(void)
  49{
  50        u32 lpr;
  51
  52        saved_lpr = at91_sys_read(AT91_DDRSDRC_LPR);
  53
  54        lpr = saved_lpr & ~AT91_DDRSDRC_LPCB;
  55        at91_sys_write(AT91_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
  56}
  57
  58#define sdram_selfrefresh_disable()     at91_sys_write(AT91_DDRSDRC_LPR, saved_lpr)
  59
  60#else
  61#include <mach/at91sam9_sdramc.h>
  62
  63#ifdef CONFIG_ARCH_AT91SAM9263
  64/*
  65 * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
  66 * handle those cases both here and in the Suspend-To-RAM support.
  67 */
  68#define AT91_SDRAMC     AT91_SDRAMC0
  69#warning Assuming EB1 SDRAM controller is *NOT* used
  70#endif
  71
  72static u32 saved_lpr;
  73
  74static inline void sdram_selfrefresh_enable(void)
  75{
  76        u32 lpr;
  77
  78        saved_lpr = at91_sys_read(AT91_SDRAMC_LPR);
  79
  80        lpr = saved_lpr & ~AT91_SDRAMC_LPCB;
  81        at91_sys_write(AT91_SDRAMC_LPR, lpr | AT91_SDRAMC_LPCB_SELF_REFRESH);
  82}
  83
  84#define sdram_selfrefresh_disable()     at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
  85
  86#endif
  87
  88
  89/*
  90 * Show the reason for the previous system reset.
  91 */
  92#if defined(AT91_SHDWC)
  93
  94#include <mach/at91_rstc.h>
  95#include <mach/at91_shdwc.h>
  96
  97static void __init show_reset_status(void)
  98{
  99        static char reset[] __initdata = "reset";
 100
 101        static char general[] __initdata = "general";
 102        static char wakeup[] __initdata = "wakeup";
 103        static char watchdog[] __initdata = "watchdog";
 104        static char software[] __initdata = "software";
 105        static char user[] __initdata = "user";
 106        static char unknown[] __initdata = "unknown";
 107
 108        static char signal[] __initdata = "signal";
 109        static char rtc[] __initdata = "rtc";
 110        static char rtt[] __initdata = "rtt";
 111        static char restore[] __initdata = "power-restored";
 112
 113        char *reason, *r2 = reset;
 114        u32 reset_type, wake_type;
 115
 116        reset_type = at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
 117        wake_type = at91_sys_read(AT91_SHDW_SR);
 118
 119        switch (reset_type) {
 120        case AT91_RSTC_RSTTYP_GENERAL:
 121                reason = general;
 122                break;
 123        case AT91_RSTC_RSTTYP_WAKEUP:
 124                /* board-specific code enabled the wakeup sources */
 125                reason = wakeup;
 126
 127                /* "wakeup signal" */
 128                if (wake_type & AT91_SHDW_WAKEUP0)
 129                        r2 = signal;
 130                else {
 131                        r2 = reason;
 132                        if (wake_type & AT91_SHDW_RTTWK)        /* rtt wakeup */
 133                                reason = rtt;
 134                        else if (wake_type & AT91_SHDW_RTCWK)   /* rtc wakeup */
 135                                reason = rtc;
 136                        else if (wake_type == 0)        /* power-restored wakeup */
 137                                reason = restore;
 138                        else                            /* unknown wakeup */
 139                                reason = unknown;
 140                }
 141                break;
 142        case AT91_RSTC_RSTTYP_WATCHDOG:
 143                reason = watchdog;
 144                break;
 145        case AT91_RSTC_RSTTYP_SOFTWARE:
 146                reason = software;
 147                break;
 148        case AT91_RSTC_RSTTYP_USER:
 149                reason = user;
 150                break;
 151        default:
 152                reason = unknown;
 153                break;
 154        }
 155        pr_info("AT91: Starting after %s %s\n", reason, r2);
 156}
 157#else
 158static void __init show_reset_status(void) {}
 159#endif
 160
 161
 162static int at91_pm_valid_state(suspend_state_t state)
 163{
 164        switch (state) {
 165                case PM_SUSPEND_ON:
 166                case PM_SUSPEND_STANDBY:
 167                case PM_SUSPEND_MEM:
 168                        return 1;
 169
 170                default:
 171                        return 0;
 172        }
 173}
 174
 175
 176static suspend_state_t target_state;
 177
 178/*
 179 * Called after processes are frozen, but before we shutdown devices.
 180 */
 181static int at91_pm_begin(suspend_state_t state)
 182{
 183        target_state = state;
 184        return 0;
 185}
 186
 187/*
 188 * Verify that all the clocks are correct before entering
 189 * slow-clock mode.
 190 */
 191static int at91_pm_verify_clocks(void)
 192{
 193        unsigned long scsr;
 194        int i;
 195
 196        scsr = at91_sys_read(AT91_PMC_SCSR);
 197
 198        /* USB must not be using PLLB */
 199        if (cpu_is_at91rm9200()) {
 200                if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) {
 201                        pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
 202                        return 0;
 203                }
 204        } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
 205                if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) {
 206                        pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
 207                        return 0;
 208                }
 209        } else if (cpu_is_at91cap9()) {
 210                if ((scsr & AT91CAP9_PMC_UHP) != 0) {
 211                        pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
 212                        return 0;
 213                }
 214        }
 215
 216#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
 217        /* PCK0..PCK3 must be disabled, or configured to use clk32k */
 218        for (i = 0; i < 4; i++) {
 219                u32 css;
 220
 221                if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
 222                        continue;
 223
 224                css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
 225                if (css != AT91_PMC_CSS_SLOW) {
 226                        pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
 227                        return 0;
 228                }
 229        }
 230#endif
 231
 232        return 1;
 233}
 234
 235/*
 236 * Call this from platform driver suspend() to see how deeply to suspend.
 237 * For example, some controllers (like OHCI) need one of the PLL clocks
 238 * in order to act as a wakeup source, and those are not available when
 239 * going into slow clock mode.
 240 *
 241 * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
 242 * the very same problem (but not using at91 main_clk), and it'd be better
 243 * to add one generic API rather than lots of platform-specific ones.
 244 */
 245int at91_suspend_entering_slow_clock(void)
 246{
 247        return (target_state == PM_SUSPEND_MEM);
 248}
 249EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 250
 251
 252static void (*slow_clock)(void);
 253
 254#ifdef CONFIG_AT91_SLOW_CLOCK
 255extern void at91_slow_clock(void);
 256extern u32 at91_slow_clock_sz;
 257#endif
 258
 259
 260static int at91_pm_enter(suspend_state_t state)
 261{
 262        at91_gpio_suspend();
 263        at91_irq_suspend();
 264
 265        pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
 266                        /* remember all the always-wake irqs */
 267                        (at91_sys_read(AT91_PMC_PCSR)
 268                                        | (1 << AT91_ID_FIQ)
 269                                        | (1 << AT91_ID_SYS)
 270                                        | (at91_extern_irq))
 271                                & at91_sys_read(AT91_AIC_IMR),
 272                        state);
 273
 274        switch (state) {
 275                /*
 276                 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
 277                 * drivers must suspend more deeply:  only the master clock
 278                 * controller may be using the main oscillator.
 279                 */
 280                case PM_SUSPEND_MEM:
 281                        /*
 282                         * Ensure that clocks are in a valid state.
 283                         */
 284                        if (!at91_pm_verify_clocks())
 285                                goto error;
 286
 287                        /*
 288                         * Enter slow clock mode by switching over to clk32k and
 289                         * turning off the main oscillator; reverse on wakeup.
 290                         */
 291                        if (slow_clock) {
 292#ifdef CONFIG_AT91_SLOW_CLOCK
 293                                /* copy slow_clock handler to SRAM, and call it */
 294                                memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz);
 295#endif
 296                                slow_clock();
 297                                break;
 298                        } else {
 299                                pr_info("AT91: PM - no slow clock mode enabled ...\n");
 300                                /* FALLTHROUGH leaving master clock alone */
 301                        }
 302
 303                /*
 304                 * STANDBY mode has *all* drivers suspended; ignores irqs not
 305                 * marked as 'wakeup' event sources; and reduces DRAM power.
 306                 * But otherwise it's identical to PM_SUSPEND_ON:  cpu idle, and
 307                 * nothing fancy done with main or cpu clocks.
 308                 */
 309                case PM_SUSPEND_STANDBY:
 310                        /*
 311                         * NOTE: the Wait-for-Interrupt instruction needs to be
 312                         * in icache so no SDRAM accesses are needed until the
 313                         * wakeup IRQ occurs and self-refresh is terminated.
 314                         */
 315                        asm("b 1f; .align 5; 1:");
 316                        asm("mcr p15, 0, r0, c7, c10, 4");      /* drain write buffer */
 317                        sdram_selfrefresh_enable();
 318                        asm("mcr p15, 0, r0, c7, c0, 4");       /* wait for interrupt */
 319                        sdram_selfrefresh_disable();
 320                        break;
 321
 322                case PM_SUSPEND_ON:
 323                        asm("mcr p15, 0, r0, c7, c0, 4");       /* wait for interrupt */
 324                        break;
 325
 326                default:
 327                        pr_debug("AT91: PM - bogus suspend state %d\n", state);
 328                        goto error;
 329        }
 330
 331        pr_debug("AT91: PM - wakeup %08x\n",
 332                        at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
 333
 334error:
 335        target_state = PM_SUSPEND_ON;
 336        at91_irq_resume();
 337        at91_gpio_resume();
 338        return 0;
 339}
 340
 341/*
 342 * Called right prior to thawing processes.
 343 */
 344static void at91_pm_end(void)
 345{
 346        target_state = PM_SUSPEND_ON;
 347}
 348
 349
 350static struct platform_suspend_ops at91_pm_ops ={
 351        .valid  = at91_pm_valid_state,
 352        .begin  = at91_pm_begin,
 353        .enter  = at91_pm_enter,
 354        .end    = at91_pm_end,
 355};
 356
 357static int __init at91_pm_init(void)
 358{
 359#ifdef CONFIG_AT91_SLOW_CLOCK
 360        slow_clock = (void *) (AT91_IO_VIRT_BASE - at91_slow_clock_sz);
 361#endif
 362
 363        pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
 364
 365#ifdef CONFIG_ARCH_AT91RM9200
 366        /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
 367        at91_sys_write(AT91_SDRAMC_LPR, 0);
 368#endif
 369
 370        suspend_set_ops(&at91_pm_ops);
 371
 372        show_reset_status();
 373        return 0;
 374}
 375arch_initcall(at91_pm_init);
 376
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.