puv3-core.c 6.4 KB

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