imx6_ccm.c 22 KB

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