imx25_ccm.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * IMX25 Clock Control Module
  3. *
  4. * Copyright (C) 2012 NICTA
  5. * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
  6. *
  7. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  8. * See the COPYING file in the top-level directory.
  9. *
  10. * To get the timer frequencies right, we need to emulate at least part of
  11. * the CCM.
  12. */
  13. #include "qemu/osdep.h"
  14. #include "hw/misc/imx25_ccm.h"
  15. #include "migration/vmstate.h"
  16. #include "qemu/log.h"
  17. #include "qemu/module.h"
  18. #ifndef DEBUG_IMX25_CCM
  19. #define DEBUG_IMX25_CCM 0
  20. #endif
  21. #define DPRINTF(fmt, args...) \
  22. do { \
  23. if (DEBUG_IMX25_CCM) { \
  24. fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX25_CCM, \
  25. __func__, ##args); \
  26. } \
  27. } while (0)
  28. static const char *imx25_ccm_reg_name(uint32_t reg)
  29. {
  30. static char unknown[20];
  31. switch (reg) {
  32. case IMX25_CCM_MPCTL_REG:
  33. return "mpctl";
  34. case IMX25_CCM_UPCTL_REG:
  35. return "upctl";
  36. case IMX25_CCM_CCTL_REG:
  37. return "cctl";
  38. case IMX25_CCM_CGCR0_REG:
  39. return "cgcr0";
  40. case IMX25_CCM_CGCR1_REG:
  41. return "cgcr1";
  42. case IMX25_CCM_CGCR2_REG:
  43. return "cgcr2";
  44. case IMX25_CCM_PCDR0_REG:
  45. return "pcdr0";
  46. case IMX25_CCM_PCDR1_REG:
  47. return "pcdr1";
  48. case IMX25_CCM_PCDR2_REG:
  49. return "pcdr2";
  50. case IMX25_CCM_PCDR3_REG:
  51. return "pcdr3";
  52. case IMX25_CCM_RCSR_REG:
  53. return "rcsr";
  54. case IMX25_CCM_CRDR_REG:
  55. return "crdr";
  56. case IMX25_CCM_DCVR0_REG:
  57. return "dcvr0";
  58. case IMX25_CCM_DCVR1_REG:
  59. return "dcvr1";
  60. case IMX25_CCM_DCVR2_REG:
  61. return "dcvr2";
  62. case IMX25_CCM_DCVR3_REG:
  63. return "dcvr3";
  64. case IMX25_CCM_LTR0_REG:
  65. return "ltr0";
  66. case IMX25_CCM_LTR1_REG:
  67. return "ltr1";
  68. case IMX25_CCM_LTR2_REG:
  69. return "ltr2";
  70. case IMX25_CCM_LTR3_REG:
  71. return "ltr3";
  72. case IMX25_CCM_LTBR0_REG:
  73. return "ltbr0";
  74. case IMX25_CCM_LTBR1_REG:
  75. return "ltbr1";
  76. case IMX25_CCM_PMCR0_REG:
  77. return "pmcr0";
  78. case IMX25_CCM_PMCR1_REG:
  79. return "pmcr1";
  80. case IMX25_CCM_PMCR2_REG:
  81. return "pmcr2";
  82. case IMX25_CCM_MCR_REG:
  83. return "mcr";
  84. case IMX25_CCM_LPIMR0_REG:
  85. return "lpimr0";
  86. case IMX25_CCM_LPIMR1_REG:
  87. return "lpimr1";
  88. default:
  89. sprintf(unknown, "[%u ?]", reg);
  90. return unknown;
  91. }
  92. }
  93. #define CKIH_FREQ 24000000 /* 24MHz crystal input */
  94. static const VMStateDescription vmstate_imx25_ccm = {
  95. .name = TYPE_IMX25_CCM,
  96. .version_id = 1,
  97. .minimum_version_id = 1,
  98. .fields = (VMStateField[]) {
  99. VMSTATE_UINT32_ARRAY(reg, IMX25CCMState, IMX25_CCM_MAX_REG),
  100. VMSTATE_END_OF_LIST()
  101. },
  102. };
  103. static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
  104. {
  105. uint32_t freq;
  106. IMX25CCMState *s = IMX25_CCM(dev);
  107. if (EXTRACT(s->reg[IMX25_CCM_CCTL_REG], MPLL_BYPASS)) {
  108. freq = CKIH_FREQ;
  109. } else {
  110. freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
  111. }
  112. DPRINTF("freq = %u\n", freq);
  113. return freq;
  114. }
  115. static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
  116. {
  117. uint32_t freq;
  118. IMX25CCMState *s = IMX25_CCM(dev);
  119. freq = imx25_ccm_get_mpll_clk(dev);
  120. if (EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_SRC)) {
  121. freq = (freq * 3 / 4);
  122. }
  123. freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
  124. DPRINTF("freq = %u\n", freq);
  125. return freq;
  126. }
  127. static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
  128. {
  129. uint32_t freq;
  130. IMX25CCMState *s = IMX25_CCM(dev);
  131. freq = imx25_ccm_get_mcu_clk(dev)
  132. / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
  133. DPRINTF("freq = %u\n", freq);
  134. return freq;
  135. }
  136. static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
  137. {
  138. uint32_t freq;
  139. freq = imx25_ccm_get_ahb_clk(dev) / 2;
  140. DPRINTF("freq = %u\n", freq);
  141. return freq;
  142. }
  143. static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
  144. {
  145. uint32_t freq = 0;
  146. DPRINTF("Clock = %d)\n", clock);
  147. switch (clock) {
  148. case CLK_NONE:
  149. break;
  150. case CLK_IPG:
  151. case CLK_IPG_HIGH:
  152. freq = imx25_ccm_get_ipg_clk(dev);
  153. break;
  154. case CLK_32k:
  155. freq = CKIL_FREQ;
  156. break;
  157. default:
  158. qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
  159. TYPE_IMX25_CCM, __func__, clock);
  160. break;
  161. }
  162. DPRINTF("Clock = %d) = %u\n", clock, freq);
  163. return freq;
  164. }
  165. static void imx25_ccm_reset(DeviceState *dev)
  166. {
  167. IMX25CCMState *s = IMX25_CCM(dev);
  168. DPRINTF("\n");
  169. memset(s->reg, 0, IMX25_CCM_MAX_REG * sizeof(uint32_t));
  170. s->reg[IMX25_CCM_MPCTL_REG] = 0x800b2c01;
  171. s->reg[IMX25_CCM_UPCTL_REG] = 0x84042800;
  172. /*
  173. * The value below gives:
  174. * CPU = 133 MHz, AHB = 66,5 MHz, IPG = 33 MHz.
  175. */
  176. s->reg[IMX25_CCM_CCTL_REG] = 0xd0030000;
  177. s->reg[IMX25_CCM_CGCR0_REG] = 0x028A0100;
  178. s->reg[IMX25_CCM_CGCR1_REG] = 0x04008100;
  179. s->reg[IMX25_CCM_CGCR2_REG] = 0x00000438;
  180. s->reg[IMX25_CCM_PCDR0_REG] = 0x01010101;
  181. s->reg[IMX25_CCM_PCDR1_REG] = 0x01010101;
  182. s->reg[IMX25_CCM_PCDR2_REG] = 0x01010101;
  183. s->reg[IMX25_CCM_PCDR3_REG] = 0x01010101;
  184. s->reg[IMX25_CCM_PMCR0_REG] = 0x00A00000;
  185. s->reg[IMX25_CCM_PMCR1_REG] = 0x0000A030;
  186. s->reg[IMX25_CCM_PMCR2_REG] = 0x0000A030;
  187. s->reg[IMX25_CCM_MCR_REG] = 0x43000000;
  188. /*
  189. * default boot will change the reset values to allow:
  190. * CPU = 399 MHz, AHB = 133 MHz, IPG = 66,5 MHz.
  191. * For some reason, this doesn't work. With the value below, linux
  192. * detects a 88 MHz IPG CLK instead of 66,5 MHz.
  193. s->reg[IMX25_CCM_CCTL_REG] = 0x20032000;
  194. */
  195. }
  196. static uint64_t imx25_ccm_read(void *opaque, hwaddr offset, unsigned size)
  197. {
  198. uint32_t value = 0;
  199. IMX25CCMState *s = (IMX25CCMState *)opaque;
  200. if (offset < 0x70) {
  201. value = s->reg[offset >> 2];
  202. } else {
  203. qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
  204. HWADDR_PRIx "\n", TYPE_IMX25_CCM, __func__, offset);
  205. }
  206. DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx25_ccm_reg_name(offset >> 2),
  207. value);
  208. return value;
  209. }
  210. static void imx25_ccm_write(void *opaque, hwaddr offset, uint64_t value,
  211. unsigned size)
  212. {
  213. IMX25CCMState *s = (IMX25CCMState *)opaque;
  214. DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx25_ccm_reg_name(offset >> 2),
  215. (uint32_t)value);
  216. if (offset < 0x70) {
  217. /*
  218. * We will do a better implementation later. In particular some bits
  219. * cannot be written to.
  220. */
  221. s->reg[offset >> 2] = value;
  222. } else {
  223. qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
  224. HWADDR_PRIx "\n", TYPE_IMX25_CCM, __func__, offset);
  225. }
  226. }
  227. static const struct MemoryRegionOps imx25_ccm_ops = {
  228. .read = imx25_ccm_read,
  229. .write = imx25_ccm_write,
  230. .endianness = DEVICE_NATIVE_ENDIAN,
  231. .valid = {
  232. /*
  233. * Our device would not work correctly if the guest was doing
  234. * unaligned access. This might not be a limitation on the real
  235. * device but in practice there is no reason for a guest to access
  236. * this device unaligned.
  237. */
  238. .min_access_size = 4,
  239. .max_access_size = 4,
  240. .unaligned = false,
  241. },
  242. };
  243. static void imx25_ccm_init(Object *obj)
  244. {
  245. DeviceState *dev = DEVICE(obj);
  246. SysBusDevice *sd = SYS_BUS_DEVICE(obj);
  247. IMX25CCMState *s = IMX25_CCM(obj);
  248. memory_region_init_io(&s->iomem, OBJECT(dev), &imx25_ccm_ops, s,
  249. TYPE_IMX25_CCM, 0x1000);
  250. sysbus_init_mmio(sd, &s->iomem);
  251. }
  252. static void imx25_ccm_class_init(ObjectClass *klass, void *data)
  253. {
  254. DeviceClass *dc = DEVICE_CLASS(klass);
  255. IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
  256. dc->reset = imx25_ccm_reset;
  257. dc->vmsd = &vmstate_imx25_ccm;
  258. dc->desc = "i.MX25 Clock Control Module";
  259. ccm->get_clock_frequency = imx25_ccm_get_clock_frequency;
  260. }
  261. static const TypeInfo imx25_ccm_info = {
  262. .name = TYPE_IMX25_CCM,
  263. .parent = TYPE_IMX_CCM,
  264. .instance_size = sizeof(IMX25CCMState),
  265. .instance_init = imx25_ccm_init,
  266. .class_init = imx25_ccm_class_init,
  267. };
  268. static void imx25_ccm_register_types(void)
  269. {
  270. type_register_static(&imx25_ccm_info);
  271. }
  272. type_init(imx25_ccm_register_types)