puv3-core.c 6.5 KB

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