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