puv3-core.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. };
  93. static struct resource puv3_rtc_resources[] = {
  94. [0] = {
  95. .start = io_v2p(PKUNITY_RTC_BASE),
  96. .end = io_v2p(PKUNITY_RTC_BASE) + 0xff,
  97. .flags = IORESOURCE_MEM,
  98. },
  99. [1] = {
  100. .start = IRQ_RTCAlarm,
  101. .end = IRQ_RTCAlarm,
  102. .flags = IORESOURCE_IRQ,
  103. },
  104. [2] = {
  105. .start = IRQ_RTC,
  106. .end = IRQ_RTC,
  107. .flags = IORESOURCE_IRQ
  108. }
  109. };
  110. static struct resource puv3_pwm_resources[] = {
  111. [0] = {
  112. .start = io_v2p(PKUNITY_OST_BASE) + 0x80,
  113. .end = io_v2p(PKUNITY_OST_BASE) + 0xff,
  114. .flags = IORESOURCE_MEM,
  115. },
  116. };
  117. static struct resource puv3_uart0_resources[] = {
  118. [0] = {
  119. .start = io_v2p(PKUNITY_UART0_BASE),
  120. .end = io_v2p(PKUNITY_UART0_BASE) + 0xff,
  121. .flags = IORESOURCE_MEM,
  122. },
  123. [1] = {
  124. .start = IRQ_UART0,
  125. .end = IRQ_UART0,
  126. .flags = IORESOURCE_IRQ
  127. }
  128. };
  129. static struct resource puv3_uart1_resources[] = {
  130. [0] = {
  131. .start = io_v2p(PKUNITY_UART1_BASE),
  132. .end = io_v2p(PKUNITY_UART1_BASE) + 0xff,
  133. .flags = IORESOURCE_MEM,
  134. },
  135. [1] = {
  136. .start = IRQ_UART1,
  137. .end = IRQ_UART1,
  138. .flags = IORESOURCE_IRQ
  139. }
  140. };
  141. static struct resource puv3_umal_resources[] = {
  142. [0] = {
  143. .start = io_v2p(PKUNITY_UMAL_BASE),
  144. .end = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
  145. .flags = IORESOURCE_MEM,
  146. },
  147. [1] = {
  148. .start = IRQ_UMAL,
  149. .end = IRQ_UMAL,
  150. .flags = IORESOURCE_IRQ
  151. }
  152. };
  153. #ifdef CONFIG_PUV3_PM
  154. #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
  155. #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
  156. /*
  157. * List of global PXA peripheral registers to preserve.
  158. * More ones like CP and general purpose register values are preserved
  159. * with the stack pointer in sleep.S.
  160. */
  161. enum {
  162. SLEEP_SAVE_PM_PLLDDRCFG,
  163. SLEEP_SAVE_COUNT
  164. };
  165. static void puv3_cpu_pm_save(unsigned long *sleep_save)
  166. {
  167. /* SAVE(PM_PLLDDRCFG); */
  168. }
  169. static void puv3_cpu_pm_restore(unsigned long *sleep_save)
  170. {
  171. /* RESTORE(PM_PLLDDRCFG); */
  172. }
  173. static int puv3_cpu_pm_prepare(void)
  174. {
  175. /* set resume return address */
  176. writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
  177. return 0;
  178. }
  179. static void puv3_cpu_pm_enter(suspend_state_t state)
  180. {
  181. /* Clear reset status */
  182. writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
  183. | RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
  184. switch (state) {
  185. /* case PM_SUSPEND_ON:
  186. puv3_cpu_idle();
  187. break; */
  188. case PM_SUSPEND_MEM:
  189. puv3_cpu_pm_prepare();
  190. puv3_cpu_suspend(PM_PMCR_SFB);
  191. break;
  192. }
  193. }
  194. static int puv3_cpu_pm_valid(suspend_state_t state)
  195. {
  196. return state == PM_SUSPEND_MEM;
  197. }
  198. static void puv3_cpu_pm_finish(void)
  199. {
  200. /* ensure not to come back here if it wasn't intended */
  201. /* PSPR = 0; */
  202. }
  203. static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
  204. .save_count = SLEEP_SAVE_COUNT,
  205. .valid = puv3_cpu_pm_valid,
  206. .save = puv3_cpu_pm_save,
  207. .restore = puv3_cpu_pm_restore,
  208. .enter = puv3_cpu_pm_enter,
  209. .prepare = puv3_cpu_pm_prepare,
  210. .finish = puv3_cpu_pm_finish,
  211. };
  212. static void __init puv3_init_pm(void)
  213. {
  214. puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
  215. }
  216. #else
  217. static inline void puv3_init_pm(void) {}
  218. #endif
  219. void puv3_ps2_init(void)
  220. {
  221. struct clk *bclk32;
  222. bclk32 = clk_get(NULL, "BUS32_CLK");
  223. writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
  224. }
  225. void __init puv3_core_init(void)
  226. {
  227. puv3_init_pm();
  228. puv3_ps2_init();
  229. platform_device_register_simple("PKUnity-v3-RTC", -1,
  230. puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
  231. platform_device_register_simple("PKUnity-v3-UMAL", -1,
  232. puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
  233. platform_device_register_simple("PKUnity-v3-MMC", -1,
  234. puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
  235. platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
  236. puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
  237. platform_device_register_simple("PKUnity-v3-PWM", -1,
  238. puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
  239. platform_device_register_simple("PKUnity-v3-UART", 0,
  240. puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
  241. platform_device_register_simple("PKUnity-v3-UART", 1,
  242. puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
  243. platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
  244. platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
  245. puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
  246. &puv3_usb_plat, sizeof(puv3_usb_plat));
  247. }