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 <mach/pxa25x.h> 34 #include <mach/reset.h> 35 #include <mach/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 */ 56 enum { 57 SLEEP_SAVE_PSTR, 58 SLEEP_SAVE_COUNT 59 }; 60 61 62 static void pxa25x_cpu_pm_save(unsigned long *sleep_save) 63 { 64 SAVE(PSTR); 65 } 66 67 static void pxa25x_cpu_pm_restore(unsigned long *sleep_save) 68 { 69 RESTORE(PSTR); 70 } 71 72 static 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 84 static int pxa25x_cpu_pm_prepare(void) 85 { 86 /* set resume return address */ 87 PSPR = virt_to_phys(cpu_resume); 88 return 0; 89 } 90 91 static void pxa25x_cpu_pm_finish(void) 92 { 93 /* ensure not to come back here if it wasn't intended */ 94 PSPR = 0; 95 } 96 97 static 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 107 static void __init pxa25x_init_pm(void) 108 { 109 pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns; 110 } 111 #else 112 static inline void pxa25x_init_pm(void) {} 113 #endif 114 115 /* PXA25x: supports wakeup from GPIO0..GPIO15 and RTC alarm 116 */ 117 118 static 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 133 set_pwer: 134 if (on) 135 PWER |= mask; 136 else 137 PWER &=~mask; 138 139 return 0; 140 } 141 142 void __init pxa25x_init_irq(void) 143 { 144 pxa_init_irq(32, pxa25x_set_wake); 145 } 146 147 #ifdef CONFIG_CPU_PXA26x 148 void __init pxa26x_init_irq(void) 149 { 150 pxa_init_irq(32, pxa25x_set_wake); 151 } 152 #endif 153 154 static 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 168 void __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 175 static 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 180 static 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 193 static 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); 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 220 postcore_initcall(pxa25x_init); 221