linux/arch/arm/mach-pxa/pxa25x.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-pxa/pxa25x.c
   3 *
   4 *  Author:     Nicolas Pitre
   5 *  Created:    Jun 15, 2001
   6 *  Copyright:  MontaVista Software Inc.
   7 *
   8 * Code specific to PXA21x/25x/26x variants.
   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 * Since this file should be linked before any other machine specific file,
  15 * the __initcall() here will be executed first.  This serves as default
  16 * initialization stuff for PXA machines which can be overridden later if
  17 * need be.
  18 */
  19#include <linux/gpio.h>
  20#include <linux/gpio-pxa.h>
  21#include <linux/module.h>
  22#include <linux/kernel.h>
  23#include <linux/init.h>
  24#include <linux/platform_device.h>
  25#include <linux/suspend.h>
  26#include <linux/syscore_ops.h>
  27#include <linux/irq.h>
  28
  29#include <asm/mach/map.h>
  30#include <asm/suspend.h>
  31#include <mach/hardware.h>
  32#include <mach/irqs.h>
  33#include "pxa25x.h"
  34#include <mach/reset.h>
  35#include "pm.h"
  36#include <mach/dma.h>
  37#include <mach/smemc.h>
  38
  39#include "generic.h"
  40#include "devices.h"
  41
  42/*
  43 * Various clock factors driven by the CCCR register.
  44 */
  45
  46#ifdef CONFIG_PM
  47
  48#define SAVE(x)         sleep_save[SLEEP_SAVE_##x] = x
  49#define RESTORE(x)      x = sleep_save[SLEEP_SAVE_##x]
  50
  51/*
  52 * List of global PXA peripheral registers to preserve.
  53 * More ones like CP and general purpose register values are preserved
  54 * with the stack pointer in sleep.S.
  55 */
  56enum {
  57        SLEEP_SAVE_PSTR,
  58        SLEEP_SAVE_COUNT
  59};
  60
  61
  62static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
  63{
  64        SAVE(PSTR);
  65}
  66
  67static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
  68{
  69        RESTORE(PSTR);
  70}
  71
  72static void pxa25x_cpu_pm_enter(suspend_state_t state)
  73{
  74        /* Clear reset status */
  75        RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
  76
  77        switch (state) {
  78        case PM_SUSPEND_MEM:
  79                cpu_suspend(PWRMODE_SLEEP, pxa25x_finish_suspend);
  80                break;
  81        }
  82}
  83
  84static int pxa25x_cpu_pm_prepare(void)
  85{
  86        /* set resume return address */
  87        PSPR = virt_to_phys(cpu_resume);
  88        return 0;
  89}
  90
  91static void pxa25x_cpu_pm_finish(void)
  92{
  93        /* ensure not to come back here if it wasn't intended */
  94        PSPR = 0;
  95}
  96
  97static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = {
  98        .save_count     = SLEEP_SAVE_COUNT,
  99        .valid          = suspend_valid_only_mem,
 100        .save           = pxa25x_cpu_pm_save,
 101        .restore        = pxa25x_cpu_pm_restore,
 102        .enter          = pxa25x_cpu_pm_enter,
 103        .prepare        = pxa25x_cpu_pm_prepare,
 104        .finish         = pxa25x_cpu_pm_finish,
 105};
 106
 107static void __init pxa25x_init_pm(void)
 108{
 109        pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns;
 110}
 111#else
 112static inline void pxa25x_init_pm(void) {}
 113#endif
 114
 115/* PXA25x: supports wakeup from GPIO0..GPIO15 and RTC alarm
 116 */
 117
 118static int pxa25x_set_wake(struct irq_data *d, unsigned int on)
 119{
 120        int gpio = pxa_irq_to_gpio(d->irq);
 121        uint32_t mask = 0;
 122
 123        if (gpio >= 0 && gpio < 85)
 124                return gpio_set_wake(gpio, on);
 125
 126        if (d->irq == IRQ_RTCAlrm) {
 127                mask = PWER_RTC;
 128                goto set_pwer;
 129        }
 130
 131        return -EINVAL;
 132
 133set_pwer:
 134        if (on)
 135                PWER |= mask;
 136        else
 137                PWER &=~mask;
 138
 139        return 0;
 140}
 141
 142void __init pxa25x_init_irq(void)
 143{
 144        pxa_init_irq(32, pxa25x_set_wake);
 145}
 146
 147#ifdef CONFIG_CPU_PXA26x
 148void __init pxa26x_init_irq(void)
 149{
 150        pxa_init_irq(32, pxa25x_set_wake);
 151}
 152#endif
 153
 154static struct map_desc pxa25x_io_desc[] __initdata = {
 155        {       /* Mem Ctl */
 156                .virtual        = (unsigned long)SMEMC_VIRT,
 157                .pfn            = __phys_to_pfn(PXA2XX_SMEMC_BASE),
 158                .length         = SMEMC_SIZE,
 159                .type           = MT_DEVICE
 160        }, {    /* UNCACHED_PHYS_0 */
 161                .virtual        = UNCACHED_PHYS_0,
 162                .pfn            = __phys_to_pfn(0x00000000),
 163                .length         = UNCACHED_PHYS_0_SIZE,
 164                .type           = MT_DEVICE
 165        },
 166};
 167
 168void __init pxa25x_map_io(void)
 169{
 170        pxa_map_io();
 171        iotable_init(ARRAY_AND_SIZE(pxa25x_io_desc));
 172        pxa25x_get_clk_frequency_khz(1);
 173}
 174
 175static struct pxa_gpio_platform_data pxa25x_gpio_info __initdata = {
 176        .irq_base       = PXA_GPIO_TO_IRQ(0),
 177        .gpio_set_wake  = gpio_set_wake,
 178};
 179
 180static struct platform_device *pxa25x_devices[] __initdata = {
 181        &pxa25x_device_udc,
 182        &pxa_device_pmu,
 183        &pxa_device_i2s,
 184        &sa1100_device_rtc,
 185        &pxa25x_device_ssp,
 186        &pxa25x_device_nssp,
 187        &pxa25x_device_assp,
 188        &pxa25x_device_pwm0,
 189        &pxa25x_device_pwm1,
 190        &pxa_device_asoc_platform,
 191};
 192
 193static int __init pxa25x_init(void)
 194{
 195        int ret = 0;
 196
 197        if (cpu_is_pxa25x()) {
 198
 199                reset_status = RCSR;
 200
 201                if ((ret = pxa_init_dma(IRQ_DMA, 16)))
 202                        return ret;
 203
 204                pxa25x_init_pm();
 205
 206                register_syscore_ops(&pxa_irq_syscore_ops);
 207                register_syscore_ops(&pxa2xx_mfp_syscore_ops);
 208
 209                pxa2xx_set_dmac_info(16, 40);
 210                pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info);
 211                ret = platform_add_devices(pxa25x_devices,
 212                                           ARRAY_SIZE(pxa25x_devices));
 213                if (ret)
 214                        return ret;
 215        }
 216
 217        return ret;
 218}
 219
 220postcore_initcall(pxa25x_init);
 221