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(readl(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 = io_v2p(PKUNITY_USB_BASE),
54 .end = io_v2p(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 = io_v2p(PKUNITY_SDC_BASE),
86 .end = io_v2p(PKUNITY_SDC_BASE) + 0xfff,
87 .flags = IORESOURCE_MEM,
92 .flags = IORESOURCE_IRQ,
96 static struct resource puv3_unigfx_resources[] = {
98 .start = io_v2p(PKUNITY_UNIGFX_BASE),
99 .end = io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
100 .flags = IORESOURCE_MEM,
103 .start = PKUNITY_UNIGFX_MMAP_BASE,
104 .end = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE,
105 .flags = IORESOURCE_MEM,
109 static struct resource puv3_rtc_resources[] = {
111 .start = io_v2p(PKUNITY_RTC_BASE),
112 .end = io_v2p(PKUNITY_RTC_BASE) + 0xff,
113 .flags = IORESOURCE_MEM,
116 .start = IRQ_RTCAlarm,
118 .flags = IORESOURCE_IRQ,
123 .flags = IORESOURCE_IRQ
127 static struct resource puv3_pwm_resources[] = {
129 .start = io_v2p(PKUNITY_OST_BASE) + 0x80,
130 .end = io_v2p(PKUNITY_OST_BASE) + 0xff,
131 .flags = IORESOURCE_MEM,
135 static struct resource puv3_uart0_resources[] = {
137 .start = io_v2p(PKUNITY_UART0_BASE),
138 .end = io_v2p(PKUNITY_UART0_BASE) + 0xff,
139 .flags = IORESOURCE_MEM,
144 .flags = IORESOURCE_IRQ
148 static struct resource puv3_uart1_resources[] = {
150 .start = io_v2p(PKUNITY_UART1_BASE),
151 .end = io_v2p(PKUNITY_UART1_BASE) + 0xff,
152 .flags = IORESOURCE_MEM,
157 .flags = IORESOURCE_IRQ
161 static struct resource puv3_umal_resources[] = {
163 .start = io_v2p(PKUNITY_UMAL_BASE),
164 .end = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
165 .flags = IORESOURCE_MEM,
170 .flags = IORESOURCE_IRQ
174 #ifdef CONFIG_PUV3_PM
176 #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
177 #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
180 * List of global PXA peripheral registers to preserve.
181 * More ones like CP and general purpose register values are preserved
182 * with the stack pointer in sleep.S.
185 SLEEP_SAVE_PM_PLLDDRCFG,
190 static void puv3_cpu_pm_save(unsigned long *sleep_save)
192 /* SAVE(PM_PLLDDRCFG); */
195 static void puv3_cpu_pm_restore(unsigned long *sleep_save)
197 /* RESTORE(PM_PLLDDRCFG); */
200 static int puv3_cpu_pm_prepare(void)
202 /* set resume return address */
203 writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
207 static void puv3_cpu_pm_enter(suspend_state_t state)
209 /* Clear reset status */
210 writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
211 | RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
214 /* case PM_SUSPEND_ON:
218 puv3_cpu_pm_prepare();
219 puv3_cpu_suspend(PM_PMCR_SFB);
224 static int puv3_cpu_pm_valid(suspend_state_t state)
226 return state == PM_SUSPEND_MEM;
229 static void puv3_cpu_pm_finish(void)
231 /* ensure not to come back here if it wasn't intended */
235 static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
236 .save_count = SLEEP_SAVE_COUNT,
237 .valid = puv3_cpu_pm_valid,
238 .save = puv3_cpu_pm_save,
239 .restore = puv3_cpu_pm_restore,
240 .enter = puv3_cpu_pm_enter,
241 .prepare = puv3_cpu_pm_prepare,
242 .finish = puv3_cpu_pm_finish,
245 static void __init puv3_init_pm(void)
247 puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
250 static inline void puv3_init_pm(void) {}
253 void puv3_ps2_init(void)
257 bclk32 = clk_get(NULL, "BUS32_CLK");
258 writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
261 void __init puv3_core_init(void)
266 platform_device_register_simple("PKUnity-v3-RTC", -1,
267 puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
268 platform_device_register_simple("PKUnity-v3-UMAL", -1,
269 puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
270 platform_device_register_simple("PKUnity-v3-MMC", -1,
271 puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
272 platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
273 puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
274 platform_device_register_simple("PKUnity-v3-PWM", -1,
275 puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
276 platform_device_register_simple("PKUnity-v3-UART", 0,
277 puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
278 platform_device_register_simple("PKUnity-v3-UART", 1,
279 puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
280 platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
281 platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
282 puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
283 &puv3_usb_plat, sizeof(puv3_usb_plat));