2
0

imx6_ccm.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /*
  2. * IMX6 Clock Control Module
  3. *
  4. * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  7. * See the COPYING file in the top-level directory.
  8. *
  9. * To get the timer frequencies right, we need to emulate at least part of
  10. * the CCM.
  11. */
  12. #include "qemu/osdep.h"
  13. #include "hw/misc/imx6_ccm.h"
  14. #include "migration/vmstate.h"
  15. #include "qemu/log.h"
  16. #include "qemu/module.h"
  17. #ifndef DEBUG_IMX6_CCM
  18. #define DEBUG_IMX6_CCM 0
  19. #endif
  20. #define DPRINTF(fmt, args...) \
  21. do { \
  22. if (DEBUG_IMX6_CCM) { \
  23. fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX6_CCM, \
  24. __func__, ##args); \
  25. } \
  26. } while (0)
  27. static const char *imx6_ccm_reg_name(uint32_t reg)
  28. {
  29. static char unknown[20];
  30. switch (reg) {
  31. case CCM_CCR:
  32. return "CCR";
  33. case CCM_CCDR:
  34. return "CCDR";
  35. case CCM_CSR:
  36. return "CSR";
  37. case CCM_CCSR:
  38. return "CCSR";
  39. case CCM_CACRR:
  40. return "CACRR";
  41. case CCM_CBCDR:
  42. return "CBCDR";
  43. case CCM_CBCMR:
  44. return "CBCMR";
  45. case CCM_CSCMR1:
  46. return "CSCMR1";
  47. case CCM_CSCMR2:
  48. return "CSCMR2";
  49. case CCM_CSCDR1:
  50. return "CSCDR1";
  51. case CCM_CS1CDR:
  52. return "CS1CDR";
  53. case CCM_CS2CDR:
  54. return "CS2CDR";
  55. case CCM_CDCDR:
  56. return "CDCDR";
  57. case CCM_CHSCCDR:
  58. return "CHSCCDR";
  59. case CCM_CSCDR2:
  60. return "CSCDR2";
  61. case CCM_CSCDR3:
  62. return "CSCDR3";
  63. case CCM_CDHIPR:
  64. return "CDHIPR";
  65. case CCM_CTOR:
  66. return "CTOR";
  67. case CCM_CLPCR:
  68. return "CLPCR";
  69. case CCM_CISR:
  70. return "CISR";
  71. case CCM_CIMR:
  72. return "CIMR";
  73. case CCM_CCOSR:
  74. return "CCOSR";
  75. case CCM_CGPR:
  76. return "CGPR";
  77. case CCM_CCGR0:
  78. return "CCGR0";
  79. case CCM_CCGR1:
  80. return "CCGR1";
  81. case CCM_CCGR2:
  82. return "CCGR2";
  83. case CCM_CCGR3:
  84. return "CCGR3";
  85. case CCM_CCGR4:
  86. return "CCGR4";
  87. case CCM_CCGR5:
  88. return "CCGR5";
  89. case CCM_CCGR6:
  90. return "CCGR6";
  91. case CCM_CMEOR:
  92. return "CMEOR";
  93. default:
  94. sprintf(unknown, "%u ?", reg);
  95. return unknown;
  96. }
  97. }
  98. static const char *imx6_analog_reg_name(uint32_t reg)
  99. {
  100. static char unknown[20];
  101. switch (reg) {
  102. case CCM_ANALOG_PLL_ARM:
  103. return "PLL_ARM";
  104. case CCM_ANALOG_PLL_ARM_SET:
  105. return "PLL_ARM_SET";
  106. case CCM_ANALOG_PLL_ARM_CLR:
  107. return "PLL_ARM_CLR";
  108. case CCM_ANALOG_PLL_ARM_TOG:
  109. return "PLL_ARM_TOG";
  110. case CCM_ANALOG_PLL_USB1:
  111. return "PLL_USB1";
  112. case CCM_ANALOG_PLL_USB1_SET:
  113. return "PLL_USB1_SET";
  114. case CCM_ANALOG_PLL_USB1_CLR:
  115. return "PLL_USB1_CLR";
  116. case CCM_ANALOG_PLL_USB1_TOG:
  117. return "PLL_USB1_TOG";
  118. case CCM_ANALOG_PLL_USB2:
  119. return "PLL_USB2";
  120. case CCM_ANALOG_PLL_USB2_SET:
  121. return "PLL_USB2_SET";
  122. case CCM_ANALOG_PLL_USB2_CLR:
  123. return "PLL_USB2_CLR";
  124. case CCM_ANALOG_PLL_USB2_TOG:
  125. return "PLL_USB2_TOG";
  126. case CCM_ANALOG_PLL_SYS:
  127. return "PLL_SYS";
  128. case CCM_ANALOG_PLL_SYS_SET:
  129. return "PLL_SYS_SET";
  130. case CCM_ANALOG_PLL_SYS_CLR:
  131. return "PLL_SYS_CLR";
  132. case CCM_ANALOG_PLL_SYS_TOG:
  133. return "PLL_SYS_TOG";
  134. case CCM_ANALOG_PLL_SYS_SS:
  135. return "PLL_SYS_SS";
  136. case CCM_ANALOG_PLL_SYS_NUM:
  137. return "PLL_SYS_NUM";
  138. case CCM_ANALOG_PLL_SYS_DENOM:
  139. return "PLL_SYS_DENOM";
  140. case CCM_ANALOG_PLL_AUDIO:
  141. return "PLL_AUDIO";
  142. case CCM_ANALOG_PLL_AUDIO_SET:
  143. return "PLL_AUDIO_SET";
  144. case CCM_ANALOG_PLL_AUDIO_CLR:
  145. return "PLL_AUDIO_CLR";
  146. case CCM_ANALOG_PLL_AUDIO_TOG:
  147. return "PLL_AUDIO_TOG";
  148. case CCM_ANALOG_PLL_AUDIO_NUM:
  149. return "PLL_AUDIO_NUM";
  150. case CCM_ANALOG_PLL_AUDIO_DENOM:
  151. return "PLL_AUDIO_DENOM";
  152. case CCM_ANALOG_PLL_VIDEO:
  153. return "PLL_VIDEO";
  154. case CCM_ANALOG_PLL_VIDEO_SET:
  155. return "PLL_VIDEO_SET";
  156. case CCM_ANALOG_PLL_VIDEO_CLR:
  157. return "PLL_VIDEO_CLR";
  158. case CCM_ANALOG_PLL_VIDEO_TOG:
  159. return "PLL_VIDEO_TOG";
  160. case CCM_ANALOG_PLL_VIDEO_NUM:
  161. return "PLL_VIDEO_NUM";
  162. case CCM_ANALOG_PLL_VIDEO_DENOM:
  163. return "PLL_VIDEO_DENOM";
  164. case CCM_ANALOG_PLL_MLB:
  165. return "PLL_MLB";
  166. case CCM_ANALOG_PLL_MLB_SET:
  167. return "PLL_MLB_SET";
  168. case CCM_ANALOG_PLL_MLB_CLR:
  169. return "PLL_MLB_CLR";
  170. case CCM_ANALOG_PLL_MLB_TOG:
  171. return "PLL_MLB_TOG";
  172. case CCM_ANALOG_PLL_ENET:
  173. return "PLL_ENET";
  174. case CCM_ANALOG_PLL_ENET_SET:
  175. return "PLL_ENET_SET";
  176. case CCM_ANALOG_PLL_ENET_CLR:
  177. return "PLL_ENET_CLR";
  178. case CCM_ANALOG_PLL_ENET_TOG:
  179. return "PLL_ENET_TOG";
  180. case CCM_ANALOG_PFD_480:
  181. return "PFD_480";
  182. case CCM_ANALOG_PFD_480_SET:
  183. return "PFD_480_SET";
  184. case CCM_ANALOG_PFD_480_CLR:
  185. return "PFD_480_CLR";
  186. case CCM_ANALOG_PFD_480_TOG:
  187. return "PFD_480_TOG";
  188. case CCM_ANALOG_PFD_528:
  189. return "PFD_528";
  190. case CCM_ANALOG_PFD_528_SET:
  191. return "PFD_528_SET";
  192. case CCM_ANALOG_PFD_528_CLR:
  193. return "PFD_528_CLR";
  194. case CCM_ANALOG_PFD_528_TOG:
  195. return "PFD_528_TOG";
  196. case CCM_ANALOG_MISC0:
  197. return "MISC0";
  198. case CCM_ANALOG_MISC0_SET:
  199. return "MISC0_SET";
  200. case CCM_ANALOG_MISC0_CLR:
  201. return "MISC0_CLR";
  202. case CCM_ANALOG_MISC0_TOG:
  203. return "MISC0_TOG";
  204. case CCM_ANALOG_MISC2:
  205. return "MISC2";
  206. case CCM_ANALOG_MISC2_SET:
  207. return "MISC2_SET";
  208. case CCM_ANALOG_MISC2_CLR:
  209. return "MISC2_CLR";
  210. case CCM_ANALOG_MISC2_TOG:
  211. return "MISC2_TOG";
  212. case PMU_REG_1P1:
  213. return "PMU_REG_1P1";
  214. case PMU_REG_3P0:
  215. return "PMU_REG_3P0";
  216. case PMU_REG_2P5:
  217. return "PMU_REG_2P5";
  218. case PMU_REG_CORE:
  219. return "PMU_REG_CORE";
  220. case PMU_MISC1:
  221. return "PMU_MISC1";
  222. case PMU_MISC1_SET:
  223. return "PMU_MISC1_SET";
  224. case PMU_MISC1_CLR:
  225. return "PMU_MISC1_CLR";
  226. case PMU_MISC1_TOG:
  227. return "PMU_MISC1_TOG";
  228. case USB_ANALOG_DIGPROG:
  229. return "USB_ANALOG_DIGPROG";
  230. default:
  231. sprintf(unknown, "%u ?", reg);
  232. return unknown;
  233. }
  234. }
  235. #define CKIH_FREQ 24000000 /* 24MHz crystal input */
  236. static const VMStateDescription vmstate_imx6_ccm = {
  237. .name = TYPE_IMX6_CCM,
  238. .version_id = 1,
  239. .minimum_version_id = 1,
  240. .fields = (VMStateField[]) {
  241. VMSTATE_UINT32_ARRAY(ccm, IMX6CCMState, CCM_MAX),
  242. VMSTATE_UINT32_ARRAY(analog, IMX6CCMState, CCM_ANALOG_MAX),
  243. VMSTATE_END_OF_LIST()
  244. },
  245. };
  246. static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
  247. {
  248. uint64_t freq = 24000000;
  249. if (EXTRACT(dev->analog[CCM_ANALOG_PLL_SYS], DIV_SELECT)) {
  250. freq *= 22;
  251. } else {
  252. freq *= 20;
  253. }
  254. DPRINTF("freq = %u\n", (uint32_t)freq);
  255. return freq;
  256. }
  257. static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
  258. {
  259. uint64_t freq = 0;
  260. freq = imx6_analog_get_pll2_clk(dev) * 18
  261. / EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
  262. DPRINTF("freq = %u\n", (uint32_t)freq);
  263. return freq;
  264. }
  265. static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
  266. {
  267. uint64_t freq = 0;
  268. freq = imx6_analog_get_pll2_clk(dev) * 18
  269. / EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
  270. DPRINTF("freq = %u\n", (uint32_t)freq);
  271. return freq;
  272. }
  273. static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
  274. {
  275. uint64_t freq = 0;
  276. switch (EXTRACT(dev->ccm[CCM_CBCMR], PRE_PERIPH_CLK_SEL)) {
  277. case 0:
  278. freq = imx6_analog_get_pll2_clk(dev);
  279. break;
  280. case 1:
  281. freq = imx6_analog_get_pll2_pfd2_clk(dev);
  282. break;
  283. case 2:
  284. freq = imx6_analog_get_pll2_pfd0_clk(dev);
  285. break;
  286. case 3:
  287. freq = imx6_analog_get_pll2_pfd2_clk(dev) / 2;
  288. break;
  289. default:
  290. /* We should never get there */
  291. g_assert_not_reached();
  292. break;
  293. }
  294. DPRINTF("freq = %u\n", (uint32_t)freq);
  295. return freq;
  296. }
  297. static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev)
  298. {
  299. uint64_t freq = 0;
  300. freq = imx6_analog_get_periph_clk(dev)
  301. / (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF));
  302. DPRINTF("freq = %u\n", (uint32_t)freq);
  303. return freq;
  304. }
  305. static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev)
  306. {
  307. uint64_t freq = 0;
  308. freq = imx6_ccm_get_ahb_clk(dev)
  309. / (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));
  310. DPRINTF("freq = %u\n", (uint32_t)freq);
  311. return freq;
  312. }
  313. static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
  314. {
  315. uint64_t freq = 0;
  316. freq = imx6_ccm_get_ipg_clk(dev)
  317. / (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF));
  318. DPRINTF("freq = %u\n", (uint32_t)freq);
  319. return freq;
  320. }
  321. static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
  322. {
  323. uint32_t freq = 0;
  324. IMX6CCMState *s = IMX6_CCM(dev);
  325. switch (clock) {
  326. case CLK_NONE:
  327. break;
  328. case CLK_IPG:
  329. freq = imx6_ccm_get_ipg_clk(s);
  330. break;
  331. case CLK_IPG_HIGH:
  332. freq = imx6_ccm_get_per_clk(s);
  333. break;
  334. case CLK_32k:
  335. freq = CKIL_FREQ;
  336. break;
  337. case CLK_HIGH:
  338. freq = 24000000;
  339. break;
  340. case CLK_HIGH_DIV:
  341. freq = 24000000 / 8;
  342. break;
  343. default:
  344. qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
  345. TYPE_IMX6_CCM, __func__, clock);
  346. break;
  347. }
  348. DPRINTF("Clock = %d) = %u\n", clock, freq);
  349. return freq;
  350. }
  351. static void imx6_ccm_reset(DeviceState *dev)
  352. {
  353. IMX6CCMState *s = IMX6_CCM(dev);
  354. DPRINTF("\n");
  355. s->ccm[CCM_CCR] = 0x040116FF;
  356. s->ccm[CCM_CCDR] = 0x00000000;
  357. s->ccm[CCM_CSR] = 0x00000010;
  358. s->ccm[CCM_CCSR] = 0x00000100;
  359. s->ccm[CCM_CACRR] = 0x00000000;
  360. s->ccm[CCM_CBCDR] = 0x00018D40;
  361. s->ccm[CCM_CBCMR] = 0x00022324;
  362. s->ccm[CCM_CSCMR1] = 0x00F00000;
  363. s->ccm[CCM_CSCMR2] = 0x02B92F06;
  364. s->ccm[CCM_CSCDR1] = 0x00490B00;
  365. s->ccm[CCM_CS1CDR] = 0x0EC102C1;
  366. s->ccm[CCM_CS2CDR] = 0x000736C1;
  367. s->ccm[CCM_CDCDR] = 0x33F71F92;
  368. s->ccm[CCM_CHSCCDR] = 0x0002A150;
  369. s->ccm[CCM_CSCDR2] = 0x0002A150;
  370. s->ccm[CCM_CSCDR3] = 0x00014841;
  371. s->ccm[CCM_CDHIPR] = 0x00000000;
  372. s->ccm[CCM_CTOR] = 0x00000000;
  373. s->ccm[CCM_CLPCR] = 0x00000079;
  374. s->ccm[CCM_CISR] = 0x00000000;
  375. s->ccm[CCM_CIMR] = 0xFFFFFFFF;
  376. s->ccm[CCM_CCOSR] = 0x000A0001;
  377. s->ccm[CCM_CGPR] = 0x0000FE62;
  378. s->ccm[CCM_CCGR0] = 0xFFFFFFFF;
  379. s->ccm[CCM_CCGR1] = 0xFFFFFFFF;
  380. s->ccm[CCM_CCGR2] = 0xFC3FFFFF;
  381. s->ccm[CCM_CCGR3] = 0xFFFFFFFF;
  382. s->ccm[CCM_CCGR4] = 0xFFFFFFFF;
  383. s->ccm[CCM_CCGR5] = 0xFFFFFFFF;
  384. s->ccm[CCM_CCGR6] = 0xFFFFFFFF;
  385. s->ccm[CCM_CMEOR] = 0xFFFFFFFF;
  386. s->analog[CCM_ANALOG_PLL_ARM] = 0x00013042;
  387. s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000;
  388. s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000;
  389. s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001;
  390. s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000;
  391. s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000;
  392. s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012;
  393. s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006;
  394. s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100;
  395. s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C;
  396. s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C;
  397. s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100;
  398. s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447;
  399. s->analog[CCM_ANALOG_PLL_MLB] = 0x00010000;
  400. s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001;
  401. s->analog[CCM_ANALOG_PFD_480] = 0x1311100C;
  402. s->analog[CCM_ANALOG_PFD_528] = 0x1018101B;
  403. s->analog[PMU_REG_1P1] = 0x00001073;
  404. s->analog[PMU_REG_3P0] = 0x00000F74;
  405. s->analog[PMU_REG_2P5] = 0x00005071;
  406. s->analog[PMU_REG_CORE] = 0x00402010;
  407. s->analog[PMU_MISC0] = 0x04000080;
  408. s->analog[PMU_MISC1] = 0x00000000;
  409. s->analog[PMU_MISC2] = 0x00272727;
  410. s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x00000004;
  411. s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000;
  412. s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000;
  413. s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000;
  414. s->analog[USB_ANALOG_USB1_MISC] = 0x00000002;
  415. s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x00000004;
  416. s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000;
  417. s->analog[USB_ANALOG_USB2_MISC] = 0x00000002;
  418. s->analog[USB_ANALOG_DIGPROG] = 0x00630000;
  419. /* all PLLs need to be locked */
  420. s->analog[CCM_ANALOG_PLL_ARM] |= CCM_ANALOG_PLL_LOCK;
  421. s->analog[CCM_ANALOG_PLL_USB1] |= CCM_ANALOG_PLL_LOCK;
  422. s->analog[CCM_ANALOG_PLL_USB2] |= CCM_ANALOG_PLL_LOCK;
  423. s->analog[CCM_ANALOG_PLL_SYS] |= CCM_ANALOG_PLL_LOCK;
  424. s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
  425. s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
  426. s->analog[CCM_ANALOG_PLL_MLB] |= CCM_ANALOG_PLL_LOCK;
  427. s->analog[CCM_ANALOG_PLL_ENET] |= CCM_ANALOG_PLL_LOCK;
  428. }
  429. static uint64_t imx6_ccm_read(void *opaque, hwaddr offset, unsigned size)
  430. {
  431. uint32_t value = 0;
  432. uint32_t index = offset >> 2;
  433. IMX6CCMState *s = (IMX6CCMState *)opaque;
  434. value = s->ccm[index];
  435. DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_ccm_reg_name(index), value);
  436. return (uint64_t)value;
  437. }
  438. static void imx6_ccm_write(void *opaque, hwaddr offset, uint64_t value,
  439. unsigned size)
  440. {
  441. uint32_t index = offset >> 2;
  442. IMX6CCMState *s = (IMX6CCMState *)opaque;
  443. DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_ccm_reg_name(index),
  444. (uint32_t)value);
  445. /*
  446. * We will do a better implementation later. In particular some bits
  447. * cannot be written to.
  448. */
  449. s->ccm[index] = (uint32_t)value;
  450. }
  451. static uint64_t imx6_analog_read(void *opaque, hwaddr offset, unsigned size)
  452. {
  453. uint32_t value;
  454. uint32_t index = offset >> 2;
  455. IMX6CCMState *s = (IMX6CCMState *)opaque;
  456. switch (index) {
  457. case CCM_ANALOG_PLL_ARM_SET:
  458. case CCM_ANALOG_PLL_USB1_SET:
  459. case CCM_ANALOG_PLL_USB2_SET:
  460. case CCM_ANALOG_PLL_SYS_SET:
  461. case CCM_ANALOG_PLL_AUDIO_SET:
  462. case CCM_ANALOG_PLL_VIDEO_SET:
  463. case CCM_ANALOG_PLL_MLB_SET:
  464. case CCM_ANALOG_PLL_ENET_SET:
  465. case CCM_ANALOG_PFD_480_SET:
  466. case CCM_ANALOG_PFD_528_SET:
  467. case CCM_ANALOG_MISC0_SET:
  468. case PMU_MISC1_SET:
  469. case CCM_ANALOG_MISC2_SET:
  470. case USB_ANALOG_USB1_VBUS_DETECT_SET:
  471. case USB_ANALOG_USB1_CHRG_DETECT_SET:
  472. case USB_ANALOG_USB1_MISC_SET:
  473. case USB_ANALOG_USB2_VBUS_DETECT_SET:
  474. case USB_ANALOG_USB2_CHRG_DETECT_SET:
  475. case USB_ANALOG_USB2_MISC_SET:
  476. /*
  477. * All REG_NAME_SET register access are in fact targeting the
  478. * the REG_NAME register.
  479. */
  480. value = s->analog[index - 1];
  481. break;
  482. case CCM_ANALOG_PLL_ARM_CLR:
  483. case CCM_ANALOG_PLL_USB1_CLR:
  484. case CCM_ANALOG_PLL_USB2_CLR:
  485. case CCM_ANALOG_PLL_SYS_CLR:
  486. case CCM_ANALOG_PLL_AUDIO_CLR:
  487. case CCM_ANALOG_PLL_VIDEO_CLR:
  488. case CCM_ANALOG_PLL_MLB_CLR:
  489. case CCM_ANALOG_PLL_ENET_CLR:
  490. case CCM_ANALOG_PFD_480_CLR:
  491. case CCM_ANALOG_PFD_528_CLR:
  492. case CCM_ANALOG_MISC0_CLR:
  493. case PMU_MISC1_CLR:
  494. case CCM_ANALOG_MISC2_CLR:
  495. case USB_ANALOG_USB1_VBUS_DETECT_CLR:
  496. case USB_ANALOG_USB1_CHRG_DETECT_CLR:
  497. case USB_ANALOG_USB1_MISC_CLR:
  498. case USB_ANALOG_USB2_VBUS_DETECT_CLR:
  499. case USB_ANALOG_USB2_CHRG_DETECT_CLR:
  500. case USB_ANALOG_USB2_MISC_CLR:
  501. /*
  502. * All REG_NAME_CLR register access are in fact targeting the
  503. * the REG_NAME register.
  504. */
  505. value = s->analog[index - 2];
  506. break;
  507. case CCM_ANALOG_PLL_ARM_TOG:
  508. case CCM_ANALOG_PLL_USB1_TOG:
  509. case CCM_ANALOG_PLL_USB2_TOG:
  510. case CCM_ANALOG_PLL_SYS_TOG:
  511. case CCM_ANALOG_PLL_AUDIO_TOG:
  512. case CCM_ANALOG_PLL_VIDEO_TOG:
  513. case CCM_ANALOG_PLL_MLB_TOG:
  514. case CCM_ANALOG_PLL_ENET_TOG:
  515. case CCM_ANALOG_PFD_480_TOG:
  516. case CCM_ANALOG_PFD_528_TOG:
  517. case CCM_ANALOG_MISC0_TOG:
  518. case PMU_MISC1_TOG:
  519. case CCM_ANALOG_MISC2_TOG:
  520. case USB_ANALOG_USB1_VBUS_DETECT_TOG:
  521. case USB_ANALOG_USB1_CHRG_DETECT_TOG:
  522. case USB_ANALOG_USB1_MISC_TOG:
  523. case USB_ANALOG_USB2_VBUS_DETECT_TOG:
  524. case USB_ANALOG_USB2_CHRG_DETECT_TOG:
  525. case USB_ANALOG_USB2_MISC_TOG:
  526. /*
  527. * All REG_NAME_TOG register access are in fact targeting the
  528. * the REG_NAME register.
  529. */
  530. value = s->analog[index - 3];
  531. break;
  532. default:
  533. value = s->analog[index];
  534. break;
  535. }
  536. DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_analog_reg_name(index), value);
  537. return (uint64_t)value;
  538. }
  539. static void imx6_analog_write(void *opaque, hwaddr offset, uint64_t value,
  540. unsigned size)
  541. {
  542. uint32_t index = offset >> 2;
  543. IMX6CCMState *s = (IMX6CCMState *)opaque;
  544. DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_analog_reg_name(index),
  545. (uint32_t)value);
  546. switch (index) {
  547. case CCM_ANALOG_PLL_ARM_SET:
  548. case CCM_ANALOG_PLL_USB1_SET:
  549. case CCM_ANALOG_PLL_USB2_SET:
  550. case CCM_ANALOG_PLL_SYS_SET:
  551. case CCM_ANALOG_PLL_AUDIO_SET:
  552. case CCM_ANALOG_PLL_VIDEO_SET:
  553. case CCM_ANALOG_PLL_MLB_SET:
  554. case CCM_ANALOG_PLL_ENET_SET:
  555. case CCM_ANALOG_PFD_480_SET:
  556. case CCM_ANALOG_PFD_528_SET:
  557. case CCM_ANALOG_MISC0_SET:
  558. case PMU_MISC1_SET:
  559. case CCM_ANALOG_MISC2_SET:
  560. case USB_ANALOG_USB1_VBUS_DETECT_SET:
  561. case USB_ANALOG_USB1_CHRG_DETECT_SET:
  562. case USB_ANALOG_USB1_MISC_SET:
  563. case USB_ANALOG_USB2_VBUS_DETECT_SET:
  564. case USB_ANALOG_USB2_CHRG_DETECT_SET:
  565. case USB_ANALOG_USB2_MISC_SET:
  566. /*
  567. * All REG_NAME_SET register access are in fact targeting the
  568. * the REG_NAME register. So we change the value of the
  569. * REG_NAME register, setting bits passed in the value.
  570. */
  571. s->analog[index - 1] |= value;
  572. break;
  573. case CCM_ANALOG_PLL_ARM_CLR:
  574. case CCM_ANALOG_PLL_USB1_CLR:
  575. case CCM_ANALOG_PLL_USB2_CLR:
  576. case CCM_ANALOG_PLL_SYS_CLR:
  577. case CCM_ANALOG_PLL_AUDIO_CLR:
  578. case CCM_ANALOG_PLL_VIDEO_CLR:
  579. case CCM_ANALOG_PLL_MLB_CLR:
  580. case CCM_ANALOG_PLL_ENET_CLR:
  581. case CCM_ANALOG_PFD_480_CLR:
  582. case CCM_ANALOG_PFD_528_CLR:
  583. case CCM_ANALOG_MISC0_CLR:
  584. case PMU_MISC1_CLR:
  585. case CCM_ANALOG_MISC2_CLR:
  586. case USB_ANALOG_USB1_VBUS_DETECT_CLR:
  587. case USB_ANALOG_USB1_CHRG_DETECT_CLR:
  588. case USB_ANALOG_USB1_MISC_CLR:
  589. case USB_ANALOG_USB2_VBUS_DETECT_CLR:
  590. case USB_ANALOG_USB2_CHRG_DETECT_CLR:
  591. case USB_ANALOG_USB2_MISC_CLR:
  592. /*
  593. * All REG_NAME_CLR register access are in fact targeting the
  594. * the REG_NAME register. So we change the value of the
  595. * REG_NAME register, unsetting bits passed in the value.
  596. */
  597. s->analog[index - 2] &= ~value;
  598. break;
  599. case CCM_ANALOG_PLL_ARM_TOG:
  600. case CCM_ANALOG_PLL_USB1_TOG:
  601. case CCM_ANALOG_PLL_USB2_TOG:
  602. case CCM_ANALOG_PLL_SYS_TOG:
  603. case CCM_ANALOG_PLL_AUDIO_TOG:
  604. case CCM_ANALOG_PLL_VIDEO_TOG:
  605. case CCM_ANALOG_PLL_MLB_TOG:
  606. case CCM_ANALOG_PLL_ENET_TOG:
  607. case CCM_ANALOG_PFD_480_TOG:
  608. case CCM_ANALOG_PFD_528_TOG:
  609. case CCM_ANALOG_MISC0_TOG:
  610. case PMU_MISC1_TOG:
  611. case CCM_ANALOG_MISC2_TOG:
  612. case USB_ANALOG_USB1_VBUS_DETECT_TOG:
  613. case USB_ANALOG_USB1_CHRG_DETECT_TOG:
  614. case USB_ANALOG_USB1_MISC_TOG:
  615. case USB_ANALOG_USB2_VBUS_DETECT_TOG:
  616. case USB_ANALOG_USB2_CHRG_DETECT_TOG:
  617. case USB_ANALOG_USB2_MISC_TOG:
  618. /*
  619. * All REG_NAME_TOG register access are in fact targeting the
  620. * the REG_NAME register. So we change the value of the
  621. * REG_NAME register, toggling bits passed in the value.
  622. */
  623. s->analog[index - 3] ^= value;
  624. break;
  625. default:
  626. /*
  627. * We will do a better implementation later. In particular some bits
  628. * cannot be written to.
  629. */
  630. s->analog[index] = value;
  631. break;
  632. }
  633. }
  634. static const struct MemoryRegionOps imx6_ccm_ops = {
  635. .read = imx6_ccm_read,
  636. .write = imx6_ccm_write,
  637. .endianness = DEVICE_NATIVE_ENDIAN,
  638. .valid = {
  639. /*
  640. * Our device would not work correctly if the guest was doing
  641. * unaligned access. This might not be a limitation on the real
  642. * device but in practice there is no reason for a guest to access
  643. * this device unaligned.
  644. */
  645. .min_access_size = 4,
  646. .max_access_size = 4,
  647. .unaligned = false,
  648. },
  649. };
  650. static const struct MemoryRegionOps imx6_analog_ops = {
  651. .read = imx6_analog_read,
  652. .write = imx6_analog_write,
  653. .endianness = DEVICE_NATIVE_ENDIAN,
  654. .valid = {
  655. /*
  656. * Our device would not work correctly if the guest was doing
  657. * unaligned access. This might not be a limitation on the real
  658. * device but in practice there is no reason for a guest to access
  659. * this device unaligned.
  660. */
  661. .min_access_size = 4,
  662. .max_access_size = 4,
  663. .unaligned = false,
  664. },
  665. };
  666. static void imx6_ccm_init(Object *obj)
  667. {
  668. DeviceState *dev = DEVICE(obj);
  669. SysBusDevice *sd = SYS_BUS_DEVICE(obj);
  670. IMX6CCMState *s = IMX6_CCM(obj);
  671. /* initialize a container for the all memory range */
  672. memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6_CCM, 0x5000);
  673. /* We initialize an IO memory region for the CCM part */
  674. memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6_ccm_ops, s,
  675. TYPE_IMX6_CCM ".ccm", CCM_MAX * sizeof(uint32_t));
  676. /* Add the CCM as a subregion at offset 0 */
  677. memory_region_add_subregion(&s->container, 0, &s->ioccm);
  678. /* We initialize an IO memory region for the ANALOG part */
  679. memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6_analog_ops, s,
  680. TYPE_IMX6_CCM ".analog",
  681. CCM_ANALOG_MAX * sizeof(uint32_t));
  682. /* Add the ANALOG as a subregion at offset 0x4000 */
  683. memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog);
  684. sysbus_init_mmio(sd, &s->container);
  685. }
  686. static void imx6_ccm_class_init(ObjectClass *klass, void *data)
  687. {
  688. DeviceClass *dc = DEVICE_CLASS(klass);
  689. IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
  690. dc->reset = imx6_ccm_reset;
  691. dc->vmsd = &vmstate_imx6_ccm;
  692. dc->desc = "i.MX6 Clock Control Module";
  693. ccm->get_clock_frequency = imx6_ccm_get_clock_frequency;
  694. }
  695. static const TypeInfo imx6_ccm_info = {
  696. .name = TYPE_IMX6_CCM,
  697. .parent = TYPE_IMX_CCM,
  698. .instance_size = sizeof(IMX6CCMState),
  699. .instance_init = imx6_ccm_init,
  700. .class_init = imx6_ccm_class_init,
  701. };
  702. static void imx6_ccm_register_types(void)
  703. {
  704. type_register_static(&imx6_ccm_info);
  705. }
  706. type_init(imx6_ccm_register_types)