Merge branch 'kvm-updates/2.6.39' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[pandora-kernel.git] / arch / unicore32 / kernel / puv3-core.c
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 <gxt@mprc.pku.edu.cn>
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         [1] = {
103                 .start  = PKUNITY_UNIGFX_MMAP_BASE,
104                 .end    = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE,
105                 .flags  = IORESOURCE_MEM,
106         },
107 };
108
109 static struct resource puv3_rtc_resources[] = {
110         [0] = {
111                 .start = io_v2p(PKUNITY_RTC_BASE),
112                 .end   = io_v2p(PKUNITY_RTC_BASE) + 0xff,
113                 .flags = IORESOURCE_MEM,
114         },
115         [1] = {
116                 .start = IRQ_RTCAlarm,
117                 .end   = IRQ_RTCAlarm,
118                 .flags = IORESOURCE_IRQ,
119         },
120         [2] = {
121                 .start = IRQ_RTC,
122                 .end   = IRQ_RTC,
123                 .flags = IORESOURCE_IRQ
124         }
125 };
126
127 static struct resource puv3_pwm_resources[] = {
128         [0] = {
129                 .start  = io_v2p(PKUNITY_OST_BASE) + 0x80,
130                 .end    = io_v2p(PKUNITY_OST_BASE) + 0xff,
131                 .flags  = IORESOURCE_MEM,
132         },
133 };
134
135 static struct resource puv3_uart0_resources[] = {
136         [0] = {
137                 .start = io_v2p(PKUNITY_UART0_BASE),
138                 .end   = io_v2p(PKUNITY_UART0_BASE) + 0xff,
139                 .flags = IORESOURCE_MEM,
140         },
141         [1] = {
142                 .start = IRQ_UART0,
143                 .end   = IRQ_UART0,
144                 .flags = IORESOURCE_IRQ
145         }
146 };
147
148 static struct resource puv3_uart1_resources[] = {
149         [0] = {
150                 .start = io_v2p(PKUNITY_UART1_BASE),
151                 .end   = io_v2p(PKUNITY_UART1_BASE) + 0xff,
152                 .flags = IORESOURCE_MEM,
153         },
154         [1] = {
155                 .start = IRQ_UART1,
156                 .end   = IRQ_UART1,
157                 .flags = IORESOURCE_IRQ
158         }
159 };
160
161 static struct resource puv3_umal_resources[] = {
162         [0] = {
163                 .start = io_v2p(PKUNITY_UMAL_BASE),
164                 .end   = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
165                 .flags = IORESOURCE_MEM,
166         },
167         [1] = {
168                 .start = IRQ_UMAL,
169                 .end   = IRQ_UMAL,
170                 .flags = IORESOURCE_IRQ
171         }
172 };
173
174 #ifdef CONFIG_PUV3_PM
175
176 #define SAVE(x)         sleep_save[SLEEP_SAVE_##x] = x
177 #define RESTORE(x)      x = sleep_save[SLEEP_SAVE_##x]
178
179 /*
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.
183  */
184 enum {
185         SLEEP_SAVE_PM_PLLDDRCFG,
186         SLEEP_SAVE_COUNT
187 };
188
189
190 static void puv3_cpu_pm_save(unsigned long *sleep_save)
191 {
192 /*      SAVE(PM_PLLDDRCFG); */
193 }
194
195 static void puv3_cpu_pm_restore(unsigned long *sleep_save)
196 {
197 /*      RESTORE(PM_PLLDDRCFG); */
198 }
199
200 static int puv3_cpu_pm_prepare(void)
201 {
202         /* set resume return address */
203         writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
204         return 0;
205 }
206
207 static void puv3_cpu_pm_enter(suspend_state_t state)
208 {
209         /* Clear reset status */
210         writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
211                         | RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
212
213         switch (state) {
214 /*      case PM_SUSPEND_ON:
215                 puv3_cpu_idle();
216                 break; */
217         case PM_SUSPEND_MEM:
218                 puv3_cpu_pm_prepare();
219                 puv3_cpu_suspend(PM_PMCR_SFB);
220                 break;
221         }
222 }
223
224 static int puv3_cpu_pm_valid(suspend_state_t state)
225 {
226         return state == PM_SUSPEND_MEM;
227 }
228
229 static void puv3_cpu_pm_finish(void)
230 {
231         /* ensure not to come back here if it wasn't intended */
232         /* PSPR = 0; */
233 }
234
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,
243 };
244
245 static void __init puv3_init_pm(void)
246 {
247         puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
248 }
249 #else
250 static inline void puv3_init_pm(void) {}
251 #endif
252
253 void puv3_ps2_init(void)
254 {
255         struct clk *bclk32;
256
257         bclk32 = clk_get(NULL, "BUS32_CLK");
258         writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
259 }
260
261 void __init puv3_core_init(void)
262 {
263         puv3_init_pm();
264         puv3_ps2_init();
265
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));
284 }
285