1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/arch/unicore32/kernel/puv3-core.c
5 * Code specific to PKUnity SoC and UniCore ISA
7 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
8 * Copyright (C) 2001-2010 Guan Xuetao
11 #include <linux/init.h>
12 #include <linux/device.h>
13 #include <linux/amba/bus.h>
14 #include <linux/platform_device.h>
16 #include <linux/cnt32_to_63.h>
17 #include <linux/usb/musb.h>
20 #include <mach/hardware.h>
24 * This is the PKUnity sched_clock implementation. This has
25 * a resolution of 271ns, and a maximum value of 32025597s (370 days).
27 * The return value is guaranteed to be monotonic in that range as
28 * long as there is always less than 582 seconds between successive
29 * calls to this function.
31 * ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
33 unsigned long long sched_clock(void)
35 unsigned long long v
= cnt32_to_63(readl(OST_OSCR
));
37 /* original conservative method, but overflow frequently
38 * v *= NSEC_PER_SEC >> 12;
39 * do_div(v, CLOCK_TICK_RATE >> 12);
41 v
= ((v
& 0x7fffffffffffffffULL
) * 2235) >> 5;
46 static struct resource puv3_usb_resources
[] = {
47 /* order is significant! */
49 .start
= io_v2p(PKUNITY_USB_BASE
),
50 .end
= io_v2p(PKUNITY_USB_BASE
) + 0x3ff,
51 .flags
= IORESOURCE_MEM
,
54 .flags
= IORESOURCE_IRQ
,
57 .flags
= IORESOURCE_IRQ
,
61 static struct musb_hdrc_config puv3_usb_config
[] = {
65 #ifdef CONFIG_USB_INVENTRA_DMA
72 static struct musb_hdrc_platform_data puv3_usb_plat
= {
76 .config
= puv3_usb_config
,
79 static struct resource puv3_mmc_resources
[] = {
81 .start
= io_v2p(PKUNITY_SDC_BASE
),
82 .end
= io_v2p(PKUNITY_SDC_BASE
) + 0xfff,
83 .flags
= IORESOURCE_MEM
,
88 .flags
= IORESOURCE_IRQ
,
92 static struct resource puv3_unigfx_resources
[] = {
94 .start
= io_v2p(PKUNITY_UNIGFX_BASE
),
95 .end
= io_v2p(PKUNITY_UNIGFX_BASE
) + 0xfff,
96 .flags
= IORESOURCE_MEM
,
100 static struct resource puv3_rtc_resources
[] = {
102 .start
= io_v2p(PKUNITY_RTC_BASE
),
103 .end
= io_v2p(PKUNITY_RTC_BASE
) + 0xff,
104 .flags
= IORESOURCE_MEM
,
107 .start
= IRQ_RTCAlarm
,
109 .flags
= IORESOURCE_IRQ
,
114 .flags
= IORESOURCE_IRQ
118 static struct resource puv3_pwm_resources
[] = {
120 .start
= io_v2p(PKUNITY_OST_BASE
) + 0x80,
121 .end
= io_v2p(PKUNITY_OST_BASE
) + 0xff,
122 .flags
= IORESOURCE_MEM
,
126 static struct resource puv3_uart0_resources
[] = {
128 .start
= io_v2p(PKUNITY_UART0_BASE
),
129 .end
= io_v2p(PKUNITY_UART0_BASE
) + 0xff,
130 .flags
= IORESOURCE_MEM
,
135 .flags
= IORESOURCE_IRQ
139 static struct resource puv3_uart1_resources
[] = {
141 .start
= io_v2p(PKUNITY_UART1_BASE
),
142 .end
= io_v2p(PKUNITY_UART1_BASE
) + 0xff,
143 .flags
= IORESOURCE_MEM
,
148 .flags
= IORESOURCE_IRQ
152 static struct resource puv3_umal_resources
[] = {
154 .start
= io_v2p(PKUNITY_UMAL_BASE
),
155 .end
= io_v2p(PKUNITY_UMAL_BASE
) + 0x1fff,
156 .flags
= IORESOURCE_MEM
,
161 .flags
= IORESOURCE_IRQ
165 #ifdef CONFIG_PUV3_PM
167 #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
168 #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
171 * List of global PXA peripheral registers to preserve.
172 * More ones like CP and general purpose register values are preserved
173 * with the stack pointer in sleep.S.
176 SLEEP_SAVE_PM_PLLDDRCFG
,
181 static void puv3_cpu_pm_save(unsigned long *sleep_save
)
183 /* SAVE(PM_PLLDDRCFG); */
186 static void puv3_cpu_pm_restore(unsigned long *sleep_save
)
188 /* RESTORE(PM_PLLDDRCFG); */
191 static int puv3_cpu_pm_prepare(void)
193 /* set resume return address */
194 writel(virt_to_phys(puv3_cpu_resume
), PM_DIVCFG
);
198 static void puv3_cpu_pm_enter(suspend_state_t state
)
200 /* Clear reset status */
201 writel(RESETC_RSSR_HWR
| RESETC_RSSR_WDR
202 | RESETC_RSSR_SMR
| RESETC_RSSR_SWR
, RESETC_RSSR
);
205 /* case PM_SUSPEND_ON:
209 puv3_cpu_pm_prepare();
210 puv3_cpu_suspend(PM_PMCR_SFB
);
215 static int puv3_cpu_pm_valid(suspend_state_t state
)
217 return state
== PM_SUSPEND_MEM
;
220 static void puv3_cpu_pm_finish(void)
222 /* ensure not to come back here if it wasn't intended */
226 static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss
= {
227 .save_count
= SLEEP_SAVE_COUNT
,
228 .valid
= puv3_cpu_pm_valid
,
229 .save
= puv3_cpu_pm_save
,
230 .restore
= puv3_cpu_pm_restore
,
231 .enter
= puv3_cpu_pm_enter
,
232 .prepare
= puv3_cpu_pm_prepare
,
233 .finish
= puv3_cpu_pm_finish
,
236 static void __init
puv3_init_pm(void)
238 puv3_cpu_pm_fns
= &puv3_cpu_pm_fnss
;
241 static inline void puv3_init_pm(void) {}
244 void puv3_ps2_init(void)
248 bclk32
= clk_get(NULL
, "BUS32_CLK");
249 writel(clk_get_rate(bclk32
) / 200000, PS2_CNT
); /* should > 5us */
252 void __init
puv3_core_init(void)
257 platform_device_register_simple("PKUnity-v3-RTC", -1,
258 puv3_rtc_resources
, ARRAY_SIZE(puv3_rtc_resources
));
259 platform_device_register_simple("PKUnity-v3-UMAL", -1,
260 puv3_umal_resources
, ARRAY_SIZE(puv3_umal_resources
));
261 platform_device_register_simple("PKUnity-v3-MMC", -1,
262 puv3_mmc_resources
, ARRAY_SIZE(puv3_mmc_resources
));
263 platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
264 puv3_unigfx_resources
, ARRAY_SIZE(puv3_unigfx_resources
));
265 platform_device_register_simple("PKUnity-v3-PWM", -1,
266 puv3_pwm_resources
, ARRAY_SIZE(puv3_pwm_resources
));
267 platform_device_register_simple("PKUnity-v3-UART", 0,
268 puv3_uart0_resources
, ARRAY_SIZE(puv3_uart0_resources
));
269 platform_device_register_simple("PKUnity-v3-UART", 1,
270 puv3_uart1_resources
, ARRAY_SIZE(puv3_uart1_resources
));
271 platform_device_register_simple("PKUnity-v3-AC97", -1, NULL
, 0);
272 platform_device_register_resndata(NULL
, "musb_hdrc", -1,
273 puv3_usb_resources
, ARRAY_SIZE(puv3_usb_resources
),
274 &puv3_usb_plat
, sizeof(puv3_usb_plat
));