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