Merge branches 'acpi-tables', 'acpi-osl', 'acpi-misc' and 'acpi-tools'
[sfrench/cifs-2.6.git] / arch / unicore32 / kernel / puv3-core.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  linux/arch/unicore32/kernel/puv3-core.c
4  *
5  * Code specific to PKUnity SoC and UniCore ISA
6  *
7  *      Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
8  *      Copyright (C) 2001-2010 Guan Xuetao
9  */
10
11 #include <linux/init.h>
12 #include <linux/device.h>
13 #include <linux/amba/bus.h>
14 #include <linux/platform_device.h>
15 #include <linux/io.h>
16 #include <linux/cnt32_to_63.h>
17 #include <linux/usb/musb.h>
18
19 #include <asm/irq.h>
20 #include <mach/hardware.h>
21 #include <mach/pm.h>
22
23 /*
24  * This is the PKUnity sched_clock implementation.  This has
25  * a resolution of 271ns, and a maximum value of 32025597s (370 days).
26  *
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.
30  *
31  *  ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
32  */
33 unsigned long long sched_clock(void)
34 {
35         unsigned long long v = cnt32_to_63(readl(OST_OSCR));
36
37         /* original conservative method, but overflow frequently
38          * v *= NSEC_PER_SEC >> 12;
39          * do_div(v, CLOCK_TICK_RATE >> 12);
40          */
41         v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
42
43         return v;
44 }
45
46 static struct resource puv3_usb_resources[] = {
47         /* order is significant! */
48         {
49                 .start          = io_v2p(PKUNITY_USB_BASE),
50                 .end            = io_v2p(PKUNITY_USB_BASE) + 0x3ff,
51                 .flags          = IORESOURCE_MEM,
52         }, {
53                 .start          = IRQ_USB,
54                 .flags          = IORESOURCE_IRQ,
55         }, {
56                 .start          = IRQ_USB,
57                 .flags          = IORESOURCE_IRQ,
58         },
59 };
60
61 static struct musb_hdrc_config  puv3_usb_config[] = {
62         {
63                 .num_eps = 16,
64                 .multipoint = 1,
65 #ifdef CONFIG_USB_INVENTRA_DMA
66                 .dma = 1,
67                 .dma_channels = 8,
68 #endif
69         },
70 };
71
72 static struct musb_hdrc_platform_data puv3_usb_plat = {
73         .mode           = MUSB_HOST,
74         .min_power      = 100,
75         .clock          = 0,
76         .config         = puv3_usb_config,
77 };
78
79 static struct resource puv3_mmc_resources[] = {
80         [0] = {
81                 .start  = io_v2p(PKUNITY_SDC_BASE),
82                 .end    = io_v2p(PKUNITY_SDC_BASE) + 0xfff,
83                 .flags  = IORESOURCE_MEM,
84         },
85         [1] = {
86                 .start  = IRQ_SDC,
87                 .end    = IRQ_SDC,
88                 .flags  = IORESOURCE_IRQ,
89         },
90 };
91
92 static struct resource puv3_unigfx_resources[] = {
93         [0] = {
94                 .start  = io_v2p(PKUNITY_UNIGFX_BASE),
95                 .end    = io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
96                 .flags  = IORESOURCE_MEM,
97         },
98 };
99
100 static struct resource puv3_rtc_resources[] = {
101         [0] = {
102                 .start = io_v2p(PKUNITY_RTC_BASE),
103                 .end   = io_v2p(PKUNITY_RTC_BASE) + 0xff,
104                 .flags = IORESOURCE_MEM,
105         },
106         [1] = {
107                 .start = IRQ_RTCAlarm,
108                 .end   = IRQ_RTCAlarm,
109                 .flags = IORESOURCE_IRQ,
110         },
111         [2] = {
112                 .start = IRQ_RTC,
113                 .end   = IRQ_RTC,
114                 .flags = IORESOURCE_IRQ
115         }
116 };
117
118 static struct resource puv3_pwm_resources[] = {
119         [0] = {
120                 .start  = io_v2p(PKUNITY_OST_BASE) + 0x80,
121                 .end    = io_v2p(PKUNITY_OST_BASE) + 0xff,
122                 .flags  = IORESOURCE_MEM,
123         },
124 };
125
126 static struct resource puv3_uart0_resources[] = {
127         [0] = {
128                 .start = io_v2p(PKUNITY_UART0_BASE),
129                 .end   = io_v2p(PKUNITY_UART0_BASE) + 0xff,
130                 .flags = IORESOURCE_MEM,
131         },
132         [1] = {
133                 .start = IRQ_UART0,
134                 .end   = IRQ_UART0,
135                 .flags = IORESOURCE_IRQ
136         }
137 };
138
139 static struct resource puv3_uart1_resources[] = {
140         [0] = {
141                 .start = io_v2p(PKUNITY_UART1_BASE),
142                 .end   = io_v2p(PKUNITY_UART1_BASE) + 0xff,
143                 .flags = IORESOURCE_MEM,
144         },
145         [1] = {
146                 .start = IRQ_UART1,
147                 .end   = IRQ_UART1,
148                 .flags = IORESOURCE_IRQ
149         }
150 };
151
152 static struct resource puv3_umal_resources[] = {
153         [0] = {
154                 .start = io_v2p(PKUNITY_UMAL_BASE),
155                 .end   = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
156                 .flags = IORESOURCE_MEM,
157         },
158         [1] = {
159                 .start = IRQ_UMAL,
160                 .end   = IRQ_UMAL,
161                 .flags = IORESOURCE_IRQ
162         }
163 };
164
165 #ifdef CONFIG_PUV3_PM
166
167 #define SAVE(x)         sleep_save[SLEEP_SAVE_##x] = x
168 #define RESTORE(x)      x = sleep_save[SLEEP_SAVE_##x]
169
170 /*
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.
174  */
175 enum {
176         SLEEP_SAVE_PM_PLLDDRCFG,
177         SLEEP_SAVE_COUNT
178 };
179
180
181 static void puv3_cpu_pm_save(unsigned long *sleep_save)
182 {
183 /*      SAVE(PM_PLLDDRCFG); */
184 }
185
186 static void puv3_cpu_pm_restore(unsigned long *sleep_save)
187 {
188 /*      RESTORE(PM_PLLDDRCFG); */
189 }
190
191 static int puv3_cpu_pm_prepare(void)
192 {
193         /* set resume return address */
194         writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
195         return 0;
196 }
197
198 static void puv3_cpu_pm_enter(suspend_state_t state)
199 {
200         /* Clear reset status */
201         writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
202                         | RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
203
204         switch (state) {
205 /*      case PM_SUSPEND_ON:
206                 puv3_cpu_idle();
207                 break; */
208         case PM_SUSPEND_MEM:
209                 puv3_cpu_pm_prepare();
210                 puv3_cpu_suspend(PM_PMCR_SFB);
211                 break;
212         }
213 }
214
215 static int puv3_cpu_pm_valid(suspend_state_t state)
216 {
217         return state == PM_SUSPEND_MEM;
218 }
219
220 static void puv3_cpu_pm_finish(void)
221 {
222         /* ensure not to come back here if it wasn't intended */
223         /* PSPR = 0; */
224 }
225
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,
234 };
235
236 static void __init puv3_init_pm(void)
237 {
238         puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
239 }
240 #else
241 static inline void puv3_init_pm(void) {}
242 #endif
243
244 void puv3_ps2_init(void)
245 {
246         struct clk *bclk32;
247
248         bclk32 = clk_get(NULL, "BUS32_CLK");
249         writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
250 }
251
252 void __init puv3_core_init(void)
253 {
254         puv3_init_pm();
255         puv3_ps2_init();
256
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));
275 }
276