Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
puv3-core.c
Go to the documentation of this file.
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 <[email protected]>
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/amba/bus.h>
17 #include <linux/platform_device.h>
18 #include <linux/io.h>
19 #include <linux/cnt32_to_63.h>
20 #include <linux/usb/musb.h>
21 
22 #include <asm/irq.h>
23 #include <mach/hardware.h>
24 #include <mach/pm.h>
25 
26 /*
27  * This is the PKUnity sched_clock implementation. This has
28  * a resolution of 271ns, and a maximum value of 32025597s (370 days).
29  *
30  * The return value is guaranteed to be monotonic in that range as
31  * long as there is always less than 582 seconds between successive
32  * calls to this function.
33  *
34  * ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
35  */
36 unsigned long long sched_clock(void)
37 {
38  unsigned long long v = cnt32_to_63(readl(OST_OSCR));
39 
40  /* original conservative method, but overflow frequently
41  * v *= NSEC_PER_SEC >> 12;
42  * do_div(v, CLOCK_TICK_RATE >> 12);
43  */
44  v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
45 
46  return v;
47 }
48 
49 static struct resource puv3_usb_resources[] = {
50  /* order is significant! */
51  {
52  .start = io_v2p(PKUNITY_USB_BASE),
53  .end = io_v2p(PKUNITY_USB_BASE) + 0x3ff,
54  .flags = IORESOURCE_MEM,
55  }, {
56  .start = IRQ_USB,
57  .flags = IORESOURCE_IRQ,
58  }, {
59  .start = IRQ_USB,
60  .flags = IORESOURCE_IRQ,
61  },
62 };
63 
64 static struct musb_hdrc_config puv3_usb_config[] = {
65  {
66  .num_eps = 16,
67  .multipoint = 1,
68 #ifdef CONFIG_USB_INVENTRA_DMA
69  .dma = 1,
70  .dma_channels = 8,
71 #endif
72  },
73 };
74 
75 static struct musb_hdrc_platform_data puv3_usb_plat = {
76  .mode = MUSB_HOST,
77  .min_power = 100,
78  .clock = 0,
79  .config = puv3_usb_config,
80 };
81 
82 static struct resource puv3_mmc_resources[] = {
83  [0] = {
84  .start = io_v2p(PKUNITY_SDC_BASE),
85  .end = io_v2p(PKUNITY_SDC_BASE) + 0xfff,
86  .flags = IORESOURCE_MEM,
87  },
88  [1] = {
89  .start = IRQ_SDC,
90  .end = IRQ_SDC,
91  .flags = IORESOURCE_IRQ,
92  },
93 };
94 
95 static struct resource puv3_unigfx_resources[] = {
96  [0] = {
97  .start = io_v2p(PKUNITY_UNIGFX_BASE),
98  .end = io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
99  .flags = IORESOURCE_MEM,
100  },
101 };
102 
103 static struct resource puv3_rtc_resources[] = {
104  [0] = {
105  .start = io_v2p(PKUNITY_RTC_BASE),
106  .end = io_v2p(PKUNITY_RTC_BASE) + 0xff,
107  .flags = IORESOURCE_MEM,
108  },
109  [1] = {
110  .start = IRQ_RTCAlarm,
111  .end = IRQ_RTCAlarm,
112  .flags = IORESOURCE_IRQ,
113  },
114  [2] = {
115  .start = IRQ_RTC,
116  .end = IRQ_RTC,
117  .flags = IORESOURCE_IRQ
118  }
119 };
120 
121 static struct resource puv3_pwm_resources[] = {
122  [0] = {
123  .start = io_v2p(PKUNITY_OST_BASE) + 0x80,
124  .end = io_v2p(PKUNITY_OST_BASE) + 0xff,
125  .flags = IORESOURCE_MEM,
126  },
127 };
128 
129 static struct resource puv3_uart0_resources[] = {
130  [0] = {
131  .start = io_v2p(PKUNITY_UART0_BASE),
132  .end = io_v2p(PKUNITY_UART0_BASE) + 0xff,
133  .flags = IORESOURCE_MEM,
134  },
135  [1] = {
136  .start = IRQ_UART0,
137  .end = IRQ_UART0,
138  .flags = IORESOURCE_IRQ
139  }
140 };
141 
142 static struct resource puv3_uart1_resources[] = {
143  [0] = {
144  .start = io_v2p(PKUNITY_UART1_BASE),
145  .end = io_v2p(PKUNITY_UART1_BASE) + 0xff,
146  .flags = IORESOURCE_MEM,
147  },
148  [1] = {
149  .start = IRQ_UART1,
150  .end = IRQ_UART1,
151  .flags = IORESOURCE_IRQ
152  }
153 };
154 
155 static struct resource puv3_umal_resources[] = {
156  [0] = {
157  .start = io_v2p(PKUNITY_UMAL_BASE),
158  .end = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
159  .flags = IORESOURCE_MEM,
160  },
161  [1] = {
162  .start = IRQ_UMAL,
163  .end = IRQ_UMAL,
164  .flags = IORESOURCE_IRQ
165  }
166 };
167 
168 #ifdef CONFIG_PUV3_PM
169 
170 #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
171 #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
172 
173 /*
174  * List of global PXA peripheral registers to preserve.
175  * More ones like CP and general purpose register values are preserved
176  * with the stack pointer in sleep.S.
177  */
178 enum {
179  SLEEP_SAVE_PM_PLLDDRCFG,
181 };
182 
183 
184 static void puv3_cpu_pm_save(unsigned long *sleep_save)
185 {
186 /* SAVE(PM_PLLDDRCFG); */
187 }
188 
189 static void puv3_cpu_pm_restore(unsigned long *sleep_save)
190 {
191 /* RESTORE(PM_PLLDDRCFG); */
192 }
193 
194 static int puv3_cpu_pm_prepare(void)
195 {
196  /* set resume return address */
198  return 0;
199 }
200 
201 static void puv3_cpu_pm_enter(suspend_state_t state)
202 {
203  /* Clear reset status */
206 
207  switch (state) {
208 /* case PM_SUSPEND_ON:
209  puv3_cpu_idle();
210  break; */
211  case PM_SUSPEND_MEM:
212  puv3_cpu_pm_prepare();
214  break;
215  }
216 }
217 
218 static int puv3_cpu_pm_valid(suspend_state_t state)
219 {
220  return state == PM_SUSPEND_MEM;
221 }
222 
223 static void puv3_cpu_pm_finish(void)
224 {
225  /* ensure not to come back here if it wasn't intended */
226  /* PSPR = 0; */
227 }
228 
229 static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
231  .valid = puv3_cpu_pm_valid,
232  .save = puv3_cpu_pm_save,
233  .restore = puv3_cpu_pm_restore,
234  .enter = puv3_cpu_pm_enter,
235  .prepare = puv3_cpu_pm_prepare,
236  .finish = puv3_cpu_pm_finish,
237 };
238 
239 static void __init puv3_init_pm(void)
240 {
241  puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
242 }
243 #else
244 static inline void puv3_init_pm(void) {}
245 #endif
246 
247 void puv3_ps2_init(void)
248 {
249  struct clk *bclk32;
250 
251  bclk32 = clk_get(NULL, "BUS32_CLK");
252  writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
253 }
254 
256 {
257  puv3_init_pm();
258  puv3_ps2_init();
259 
260  platform_device_register_simple("PKUnity-v3-RTC", -1,
261  puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
262  platform_device_register_simple("PKUnity-v3-UMAL", -1,
263  puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
264  platform_device_register_simple("PKUnity-v3-MMC", -1,
265  puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
266  platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
267  puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
268  platform_device_register_simple("PKUnity-v3-PWM", -1,
269  puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
270  platform_device_register_simple("PKUnity-v3-UART", 0,
271  puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
272  platform_device_register_simple("PKUnity-v3-UART", 1,
273  puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
274  platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
275  platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
276  puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
277  &puv3_usb_plat, sizeof(puv3_usb_plat));
278 }
279