2
0

imx6ul_ccm.c 25 KB

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