2 * linux/arch/unicore32/kernel/puv3-core.c
4 * Code specific to PKUnity SoC and UniCore ISA
6 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
7 * Copyright (C) 2001-2010 Guan Xuetao
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.
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>
20 #include <linux/cnt32_to_63.h>
21 #include <linux/usb/musb.h>
24 #include <mach/hardware.h>
28 * This is the PKUnity sched_clock implementation. This has
29 * a resolution of 271ns, and a maximum value of 32025597s (370 days).
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.
35 * ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
37 unsigned long long sched_clock(void)
39 unsigned long long v
= cnt32_to_63(OST_OSCR
);
41 /* original conservative method, but overflow frequently
42 * v *= NSEC_PER_SEC >> 12;
43 * do_div(v, CLOCK_TICK_RATE >> 12);
45 v
= ((v
& 0x7fffffffffffffffULL
) * 2235) >> 5;
50 static struct resource puv3_usb_resources
[] = {
51 /* order is significant! */
53 .start
= PKUNITY_USB_BASE
,
54 .end
= PKUNITY_USB_BASE
+ 0x3ff,
55 .flags
= IORESOURCE_MEM
,
58 .flags
= IORESOURCE_IRQ
,
61 .flags
= IORESOURCE_IRQ
,
65 static struct musb_hdrc_config puv3_usb_config
[] = {
69 #ifdef CONFIG_USB_INVENTRA_DMA
76 static struct musb_hdrc_platform_data puv3_usb_plat
= {
80 .config
= puv3_usb_config
,
83 static struct resource puv3_mmc_resources
[] = {
85 .start
= PKUNITY_SDC_BASE
,
86 .end
= PKUNITY_SDC_BASE
+ 0xfff,
87 .flags
= IORESOURCE_MEM
,
92 .flags
= IORESOURCE_IRQ
,
96 static struct resource puv3_rtc_resources
[] = {
98 .start
= PKUNITY_RTC_BASE
,
99 .end
= PKUNITY_RTC_BASE
+ 0xff,
100 .flags
= IORESOURCE_MEM
,
103 .start
= IRQ_RTCAlarm
,
105 .flags
= IORESOURCE_IRQ
,
110 .flags
= IORESOURCE_IRQ
114 static struct resource puv3_pwm_resources
[] = {
116 .start
= PKUNITY_OST_BASE
+ 0x80,
117 .end
= PKUNITY_OST_BASE
+ 0xff,
118 .flags
= IORESOURCE_MEM
,
122 static struct resource puv3_uart0_resources
[] = {
124 .start
= PKUNITY_UART0_BASE
,
125 .end
= PKUNITY_UART0_BASE
+ 0xff,
126 .flags
= IORESOURCE_MEM
,
131 .flags
= IORESOURCE_IRQ
135 static struct resource puv3_uart1_resources
[] = {
137 .start
= PKUNITY_UART1_BASE
,
138 .end
= PKUNITY_UART1_BASE
+ 0xff,
139 .flags
= IORESOURCE_MEM
,
144 .flags
= IORESOURCE_IRQ
148 static struct resource puv3_umal_resources
[] = {
150 .start
= PKUNITY_UMAL_BASE
,
151 .end
= PKUNITY_UMAL_BASE
+ 0x1fff,
152 .flags
= IORESOURCE_MEM
,
157 .flags
= IORESOURCE_IRQ
161 #ifdef CONFIG_PUV3_PM
163 #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
164 #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
167 * List of global PXA peripheral registers to preserve.
168 * More ones like CP and general purpose register values are preserved
169 * with the stack pointer in sleep.S.
172 SLEEP_SAVE_PM_PLLDDRCFG
,
177 static void puv3_cpu_pm_save(unsigned long *sleep_save
)
179 /* SAVE(PM_PLLDDRCFG); */
182 static void puv3_cpu_pm_restore(unsigned long *sleep_save
)
184 /* RESTORE(PM_PLLDDRCFG); */
187 static int puv3_cpu_pm_prepare(void)
189 /* set resume return address */
190 PM_DIVCFG
= virt_to_phys(puv3_cpu_resume
);
194 static void puv3_cpu_pm_enter(suspend_state_t state
)
196 /* Clear reset status */
197 RESETC_RSSR
= RESETC_RSSR_HWR
| RESETC_RSSR_WDR
198 | RESETC_RSSR_SMR
| RESETC_RSSR_SWR
;
201 /* case PM_SUSPEND_ON:
205 puv3_cpu_pm_prepare();
206 puv3_cpu_suspend(PM_PMCR_SFB
);
211 static int puv3_cpu_pm_valid(suspend_state_t state
)
213 return state
== PM_SUSPEND_MEM
;
216 static void puv3_cpu_pm_finish(void)
218 /* ensure not to come back here if it wasn't intended */
222 static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss
= {
223 .save_count
= SLEEP_SAVE_COUNT
,
224 .valid
= puv3_cpu_pm_valid
,
225 .save
= puv3_cpu_pm_save
,
226 .restore
= puv3_cpu_pm_restore
,
227 .enter
= puv3_cpu_pm_enter
,
228 .prepare
= puv3_cpu_pm_prepare
,
229 .finish
= puv3_cpu_pm_finish
,
232 static void __init
puv3_init_pm(void)
234 puv3_cpu_pm_fns
= &puv3_cpu_pm_fnss
;
237 static inline void puv3_init_pm(void) {}
240 void puv3_ps2_init(void)
244 bclk32
= clk_get(NULL
, "BUS32_CLK");
245 PS2_CNT
= clk_get_rate(bclk32
) / 200000; /* should > 5us */
248 void __init
puv3_core_init(void)
253 platform_device_register_simple("PKUnity-v3-RTC", -1,
254 puv3_rtc_resources
, ARRAY_SIZE(puv3_rtc_resources
));
255 platform_device_register_simple("PKUnity-v3-UMAL", -1,
256 puv3_umal_resources
, ARRAY_SIZE(puv3_umal_resources
));
257 platform_device_register_simple("PKUnity-v3-MMC", -1,
258 puv3_mmc_resources
, ARRAY_SIZE(puv3_mmc_resources
));
259 platform_device_register_simple("PKUnity-v3-PWM", -1,
260 puv3_pwm_resources
, ARRAY_SIZE(puv3_pwm_resources
));
261 platform_device_register_simple("PKUnity-v3-UART", 0,
262 puv3_uart0_resources
, ARRAY_SIZE(puv3_uart0_resources
));
263 platform_device_register_simple("PKUnity-v3-UART", 1,
264 puv3_uart1_resources
, ARRAY_SIZE(puv3_uart1_resources
));
265 platform_device_register_simple("PKUnity-v3-AC97", -1, NULL
, 0);
266 platform_device_register_resndata(&platform_bus
, "musb_hdrc", -1,
267 puv3_usb_resources
, ARRAY_SIZE(puv3_usb_resources
),
268 &puv3_usb_plat
, sizeof(puv3_usb_plat
));