Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm/mach-pxa/pxa25x.c
29269 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* linux/arch/arm/mach-pxa/pxa25x.c
4
*
5
* Author: Nicolas Pitre
6
* Created: Jun 15, 2001
7
* Copyright: MontaVista Software Inc.
8
*
9
* Code specific to PXA21x/25x/26x variants.
10
*
11
* Since this file should be linked before any other machine specific file,
12
* the __initcall() here will be executed first. This serves as default
13
* initialization stuff for PXA machines which can be overridden later if
14
* need be.
15
*/
16
#include <linux/dmaengine.h>
17
#include <linux/dma/pxa-dma.h>
18
#include <linux/gpio.h>
19
#include <linux/gpio-pxa.h>
20
#include <linux/module.h>
21
#include <linux/kernel.h>
22
#include <linux/init.h>
23
#include <linux/platform_device.h>
24
#include <linux/suspend.h>
25
#include <linux/syscore_ops.h>
26
#include <linux/irq.h>
27
#include <linux/irqchip.h>
28
#include <linux/platform_data/mmp_dma.h>
29
#include <linux/soc/pxa/cpu.h>
30
#include <linux/soc/pxa/smemc.h>
31
32
#include <asm/mach/map.h>
33
#include <asm/suspend.h>
34
#include "irqs.h"
35
#include "pxa25x.h"
36
#include "reset.h"
37
#include "pm.h"
38
#include "addr-map.h"
39
#include "smemc.h"
40
41
#include "generic.h"
42
#include "devices.h"
43
44
/*
45
* Various clock factors driven by the CCCR register.
46
*/
47
48
#ifdef CONFIG_PM
49
50
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
51
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
52
53
/*
54
* List of global PXA peripheral registers to preserve.
55
* More ones like CP and general purpose register values are preserved
56
* with the stack pointer in sleep.S.
57
*/
58
enum {
59
SLEEP_SAVE_PSTR,
60
SLEEP_SAVE_COUNT
61
};
62
63
64
static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
65
{
66
SAVE(PSTR);
67
}
68
69
static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
70
{
71
RESTORE(PSTR);
72
}
73
74
static void pxa25x_cpu_pm_enter(suspend_state_t state)
75
{
76
/* Clear reset status */
77
RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
78
79
switch (state) {
80
case PM_SUSPEND_MEM:
81
cpu_suspend(PWRMODE_SLEEP, pxa25x_finish_suspend);
82
break;
83
}
84
}
85
86
static int pxa25x_cpu_pm_prepare(void)
87
{
88
/* set resume return address */
89
PSPR = __pa_symbol(cpu_resume);
90
return 0;
91
}
92
93
static void pxa25x_cpu_pm_finish(void)
94
{
95
/* ensure not to come back here if it wasn't intended */
96
PSPR = 0;
97
}
98
99
static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = {
100
.save_count = SLEEP_SAVE_COUNT,
101
.valid = suspend_valid_only_mem,
102
.save = pxa25x_cpu_pm_save,
103
.restore = pxa25x_cpu_pm_restore,
104
.enter = pxa25x_cpu_pm_enter,
105
.prepare = pxa25x_cpu_pm_prepare,
106
.finish = pxa25x_cpu_pm_finish,
107
};
108
109
static void __init pxa25x_init_pm(void)
110
{
111
pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns;
112
}
113
#else
114
static inline void pxa25x_init_pm(void) {}
115
#endif
116
117
/* PXA25x: supports wakeup from GPIO0..GPIO15 and RTC alarm
118
*/
119
120
static int pxa25x_set_wake(struct irq_data *d, unsigned int on)
121
{
122
int gpio = pxa_irq_to_gpio(d->irq);
123
uint32_t mask = 0;
124
125
if (gpio >= 0 && gpio < 85)
126
return gpio_set_wake(gpio, on);
127
128
if (d->irq == IRQ_RTCAlrm) {
129
mask = PWER_RTC;
130
goto set_pwer;
131
}
132
133
return -EINVAL;
134
135
set_pwer:
136
if (on)
137
PWER |= mask;
138
else
139
PWER &=~mask;
140
141
return 0;
142
}
143
144
void __init pxa25x_init_irq(void)
145
{
146
pxa_init_irq(32, pxa25x_set_wake);
147
set_handle_irq(pxa25x_handle_irq);
148
}
149
150
static int __init __init
151
pxa25x_dt_init_irq(struct device_node *node, struct device_node *parent)
152
{
153
pxa_dt_irq_init(pxa25x_set_wake);
154
set_handle_irq(icip_handle_irq);
155
156
return 0;
157
}
158
IRQCHIP_DECLARE(pxa25x_intc, "marvell,pxa-intc", pxa25x_dt_init_irq);
159
160
static struct map_desc pxa25x_io_desc[] __initdata = {
161
{ /* Mem Ctl */
162
.virtual = (unsigned long)SMEMC_VIRT,
163
.pfn = __phys_to_pfn(PXA2XX_SMEMC_BASE),
164
.length = SMEMC_SIZE,
165
.type = MT_DEVICE
166
}, { /* UNCACHED_PHYS_0 */
167
.virtual = UNCACHED_PHYS_0,
168
.pfn = __phys_to_pfn(0x00000000),
169
.length = UNCACHED_PHYS_0_SIZE,
170
.type = MT_DEVICE
171
},
172
};
173
174
void __init pxa25x_map_io(void)
175
{
176
pxa_map_io();
177
iotable_init(ARRAY_AND_SIZE(pxa25x_io_desc));
178
pxa25x_get_clk_frequency_khz(1);
179
}
180
181
static struct platform_device *pxa25x_devices[] __initdata = {
182
&pxa25x_device_gpio,
183
&pxa25x_device_udc,
184
&pxa_device_pmu,
185
&pxa_device_i2s,
186
&sa1100_device_rtc,
187
&pxa25x_device_ssp,
188
&pxa25x_device_nssp,
189
&pxa25x_device_assp,
190
&pxa25x_device_pwm0,
191
&pxa25x_device_pwm1,
192
&pxa_device_asoc_platform,
193
};
194
195
static const struct dma_slave_map pxa25x_slave_map[] = {
196
/* PXA25x, PXA27x and PXA3xx common entries */
197
{ "pxa2xx-ac97", "pcm_pcm_mic_mono", PDMA_FILTER_PARAM(LOWEST, 8) },
198
{ "pxa2xx-ac97", "pcm_pcm_aux_mono_in", PDMA_FILTER_PARAM(LOWEST, 9) },
199
{ "pxa2xx-ac97", "pcm_pcm_aux_mono_out",
200
PDMA_FILTER_PARAM(LOWEST, 10) },
201
{ "pxa2xx-ac97", "pcm_pcm_stereo_in", PDMA_FILTER_PARAM(LOWEST, 11) },
202
{ "pxa2xx-ac97", "pcm_pcm_stereo_out", PDMA_FILTER_PARAM(LOWEST, 12) },
203
{ "pxa-ssp-dai.1", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
204
{ "pxa-ssp-dai.1", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
205
{ "pxa-ssp-dai.2", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
206
{ "pxa-ssp-dai.2", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
207
{ "pxa2xx-ir", "rx", PDMA_FILTER_PARAM(LOWEST, 17) },
208
{ "pxa2xx-ir", "tx", PDMA_FILTER_PARAM(LOWEST, 18) },
209
{ "pxa2xx-mci.0", "rx", PDMA_FILTER_PARAM(LOWEST, 21) },
210
{ "pxa2xx-mci.0", "tx", PDMA_FILTER_PARAM(LOWEST, 22) },
211
212
/* PXA25x specific map */
213
{ "pxa25x-ssp.0", "rx", PDMA_FILTER_PARAM(LOWEST, 13) },
214
{ "pxa25x-ssp.0", "tx", PDMA_FILTER_PARAM(LOWEST, 14) },
215
{ "pxa25x-nssp.1", "rx", PDMA_FILTER_PARAM(LOWEST, 15) },
216
{ "pxa25x-nssp.1", "tx", PDMA_FILTER_PARAM(LOWEST, 16) },
217
{ "pxa25x-nssp.2", "rx", PDMA_FILTER_PARAM(LOWEST, 23) },
218
{ "pxa25x-nssp.2", "tx", PDMA_FILTER_PARAM(LOWEST, 24) },
219
};
220
221
static struct mmp_dma_platdata pxa25x_dma_pdata = {
222
.dma_channels = 16,
223
.nb_requestors = 40,
224
.slave_map = pxa25x_slave_map,
225
.slave_map_cnt = ARRAY_SIZE(pxa25x_slave_map),
226
};
227
228
static int __init pxa25x_init(void)
229
{
230
int ret = 0;
231
232
if (cpu_is_pxa25x()) {
233
234
pxa_register_wdt(RCSR);
235
236
pxa25x_init_pm();
237
238
register_syscore_ops(&pxa_irq_syscore_ops);
239
register_syscore_ops(&pxa2xx_mfp_syscore_ops);
240
241
if (!of_have_populated_dt()) {
242
software_node_register(&pxa2xx_gpiochip_node);
243
pxa2xx_set_dmac_info(&pxa25x_dma_pdata);
244
ret = platform_add_devices(pxa25x_devices,
245
ARRAY_SIZE(pxa25x_devices));
246
}
247
}
248
249
return ret;
250
}
251
252
postcore_initcall(pxa25x_init);
253
254