Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/unicore32/kernel/puv3-core.c
10817 views
1
/*
2
* linux/arch/unicore32/kernel/puv3-core.c
3
*
4
* Code specific to PKUnity SoC and UniCore ISA
5
*
6
* Maintained by GUAN Xue-tao <[email protected]>
7
* Copyright (C) 2001-2010 Guan Xuetao
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
12
*/
13
14
#include <linux/init.h>
15
#include <linux/device.h>
16
#include <linux/sysdev.h>
17
#include <linux/amba/bus.h>
18
#include <linux/platform_device.h>
19
#include <linux/io.h>
20
#include <linux/cnt32_to_63.h>
21
#include <linux/usb/musb.h>
22
23
#include <asm/irq.h>
24
#include <mach/hardware.h>
25
#include <mach/pm.h>
26
27
/*
28
* This is the PKUnity sched_clock implementation. This has
29
* a resolution of 271ns, and a maximum value of 32025597s (370 days).
30
*
31
* The return value is guaranteed to be monotonic in that range as
32
* long as there is always less than 582 seconds between successive
33
* calls to this function.
34
*
35
* ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
36
*/
37
unsigned long long sched_clock(void)
38
{
39
unsigned long long v = cnt32_to_63(readl(OST_OSCR));
40
41
/* original conservative method, but overflow frequently
42
* v *= NSEC_PER_SEC >> 12;
43
* do_div(v, CLOCK_TICK_RATE >> 12);
44
*/
45
v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
46
47
return v;
48
}
49
50
static struct resource puv3_usb_resources[] = {
51
/* order is significant! */
52
{
53
.start = io_v2p(PKUNITY_USB_BASE),
54
.end = io_v2p(PKUNITY_USB_BASE) + 0x3ff,
55
.flags = IORESOURCE_MEM,
56
}, {
57
.start = IRQ_USB,
58
.flags = IORESOURCE_IRQ,
59
}, {
60
.start = IRQ_USB,
61
.flags = IORESOURCE_IRQ,
62
},
63
};
64
65
static struct musb_hdrc_config puv3_usb_config[] = {
66
{
67
.num_eps = 16,
68
.multipoint = 1,
69
#ifdef CONFIG_USB_INVENTRA_DMA
70
.dma = 1,
71
.dma_channels = 8,
72
#endif
73
},
74
};
75
76
static struct musb_hdrc_platform_data puv3_usb_plat = {
77
.mode = MUSB_HOST,
78
.min_power = 100,
79
.clock = 0,
80
.config = puv3_usb_config,
81
};
82
83
static struct resource puv3_mmc_resources[] = {
84
[0] = {
85
.start = io_v2p(PKUNITY_SDC_BASE),
86
.end = io_v2p(PKUNITY_SDC_BASE) + 0xfff,
87
.flags = IORESOURCE_MEM,
88
},
89
[1] = {
90
.start = IRQ_SDC,
91
.end = IRQ_SDC,
92
.flags = IORESOURCE_IRQ,
93
},
94
};
95
96
static struct resource puv3_unigfx_resources[] = {
97
[0] = {
98
.start = io_v2p(PKUNITY_UNIGFX_BASE),
99
.end = io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
100
.flags = IORESOURCE_MEM,
101
},
102
};
103
104
static struct resource puv3_rtc_resources[] = {
105
[0] = {
106
.start = io_v2p(PKUNITY_RTC_BASE),
107
.end = io_v2p(PKUNITY_RTC_BASE) + 0xff,
108
.flags = IORESOURCE_MEM,
109
},
110
[1] = {
111
.start = IRQ_RTCAlarm,
112
.end = IRQ_RTCAlarm,
113
.flags = IORESOURCE_IRQ,
114
},
115
[2] = {
116
.start = IRQ_RTC,
117
.end = IRQ_RTC,
118
.flags = IORESOURCE_IRQ
119
}
120
};
121
122
static struct resource puv3_pwm_resources[] = {
123
[0] = {
124
.start = io_v2p(PKUNITY_OST_BASE) + 0x80,
125
.end = io_v2p(PKUNITY_OST_BASE) + 0xff,
126
.flags = IORESOURCE_MEM,
127
},
128
};
129
130
static struct resource puv3_uart0_resources[] = {
131
[0] = {
132
.start = io_v2p(PKUNITY_UART0_BASE),
133
.end = io_v2p(PKUNITY_UART0_BASE) + 0xff,
134
.flags = IORESOURCE_MEM,
135
},
136
[1] = {
137
.start = IRQ_UART0,
138
.end = IRQ_UART0,
139
.flags = IORESOURCE_IRQ
140
}
141
};
142
143
static struct resource puv3_uart1_resources[] = {
144
[0] = {
145
.start = io_v2p(PKUNITY_UART1_BASE),
146
.end = io_v2p(PKUNITY_UART1_BASE) + 0xff,
147
.flags = IORESOURCE_MEM,
148
},
149
[1] = {
150
.start = IRQ_UART1,
151
.end = IRQ_UART1,
152
.flags = IORESOURCE_IRQ
153
}
154
};
155
156
static struct resource puv3_umal_resources[] = {
157
[0] = {
158
.start = io_v2p(PKUNITY_UMAL_BASE),
159
.end = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
160
.flags = IORESOURCE_MEM,
161
},
162
[1] = {
163
.start = IRQ_UMAL,
164
.end = IRQ_UMAL,
165
.flags = IORESOURCE_IRQ
166
}
167
};
168
169
#ifdef CONFIG_PUV3_PM
170
171
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
172
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
173
174
/*
175
* List of global PXA peripheral registers to preserve.
176
* More ones like CP and general purpose register values are preserved
177
* with the stack pointer in sleep.S.
178
*/
179
enum {
180
SLEEP_SAVE_PM_PLLDDRCFG,
181
SLEEP_SAVE_COUNT
182
};
183
184
185
static void puv3_cpu_pm_save(unsigned long *sleep_save)
186
{
187
/* SAVE(PM_PLLDDRCFG); */
188
}
189
190
static void puv3_cpu_pm_restore(unsigned long *sleep_save)
191
{
192
/* RESTORE(PM_PLLDDRCFG); */
193
}
194
195
static int puv3_cpu_pm_prepare(void)
196
{
197
/* set resume return address */
198
writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
199
return 0;
200
}
201
202
static void puv3_cpu_pm_enter(suspend_state_t state)
203
{
204
/* Clear reset status */
205
writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
206
| RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
207
208
switch (state) {
209
/* case PM_SUSPEND_ON:
210
puv3_cpu_idle();
211
break; */
212
case PM_SUSPEND_MEM:
213
puv3_cpu_pm_prepare();
214
puv3_cpu_suspend(PM_PMCR_SFB);
215
break;
216
}
217
}
218
219
static int puv3_cpu_pm_valid(suspend_state_t state)
220
{
221
return state == PM_SUSPEND_MEM;
222
}
223
224
static void puv3_cpu_pm_finish(void)
225
{
226
/* ensure not to come back here if it wasn't intended */
227
/* PSPR = 0; */
228
}
229
230
static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
231
.save_count = SLEEP_SAVE_COUNT,
232
.valid = puv3_cpu_pm_valid,
233
.save = puv3_cpu_pm_save,
234
.restore = puv3_cpu_pm_restore,
235
.enter = puv3_cpu_pm_enter,
236
.prepare = puv3_cpu_pm_prepare,
237
.finish = puv3_cpu_pm_finish,
238
};
239
240
static void __init puv3_init_pm(void)
241
{
242
puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
243
}
244
#else
245
static inline void puv3_init_pm(void) {}
246
#endif
247
248
void puv3_ps2_init(void)
249
{
250
struct clk *bclk32;
251
252
bclk32 = clk_get(NULL, "BUS32_CLK");
253
writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
254
}
255
256
void __init puv3_core_init(void)
257
{
258
puv3_init_pm();
259
puv3_ps2_init();
260
261
platform_device_register_simple("PKUnity-v3-RTC", -1,
262
puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
263
platform_device_register_simple("PKUnity-v3-UMAL", -1,
264
puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
265
platform_device_register_simple("PKUnity-v3-MMC", -1,
266
puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
267
platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
268
puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
269
platform_device_register_simple("PKUnity-v3-PWM", -1,
270
puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
271
platform_device_register_simple("PKUnity-v3-UART", 0,
272
puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
273
platform_device_register_simple("PKUnity-v3-UART", 1,
274
puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
275
platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
276
platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
277
puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
278
&puv3_usb_plat, sizeof(puv3_usb_plat));
279
}
280
281
282