xref: /qemu/hw/misc/imx6ul_ccm.c (revision d6454270575da1f16a8923c7cb240e46ef243f72)
1781182e1SJean-Christophe Dubois /*
2781182e1SJean-Christophe Dubois  * IMX6UL Clock Control Module
3781182e1SJean-Christophe Dubois  *
4781182e1SJean-Christophe Dubois  * Copyright (c) 2018 Jean-Christophe Dubois <jcd@tribudubois.net>
5781182e1SJean-Christophe Dubois  *
6781182e1SJean-Christophe Dubois  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7781182e1SJean-Christophe Dubois  * See the COPYING file in the top-level directory.
8781182e1SJean-Christophe Dubois  *
9781182e1SJean-Christophe Dubois  * To get the timer frequencies right, we need to emulate at least part of
10781182e1SJean-Christophe Dubois  * the CCM.
11781182e1SJean-Christophe Dubois  */
12781182e1SJean-Christophe Dubois 
13781182e1SJean-Christophe Dubois #include "qemu/osdep.h"
14781182e1SJean-Christophe Dubois #include "hw/registerfields.h"
15*d6454270SMarkus Armbruster #include "migration/vmstate.h"
16781182e1SJean-Christophe Dubois #include "hw/misc/imx6ul_ccm.h"
17781182e1SJean-Christophe Dubois #include "qemu/log.h"
180b8fa32fSMarkus Armbruster #include "qemu/module.h"
19781182e1SJean-Christophe Dubois 
20781182e1SJean-Christophe Dubois #include "trace.h"
21781182e1SJean-Christophe Dubois 
22781182e1SJean-Christophe Dubois static const char *imx6ul_ccm_reg_name(uint32_t reg)
23781182e1SJean-Christophe Dubois {
24781182e1SJean-Christophe Dubois     static char unknown[20];
25781182e1SJean-Christophe Dubois 
26781182e1SJean-Christophe Dubois     switch (reg) {
27781182e1SJean-Christophe Dubois     case CCM_CCR:
28781182e1SJean-Christophe Dubois         return "CCR";
29781182e1SJean-Christophe Dubois     case CCM_CCDR:
30781182e1SJean-Christophe Dubois         return "CCDR";
31781182e1SJean-Christophe Dubois     case CCM_CSR:
32781182e1SJean-Christophe Dubois         return "CSR";
33781182e1SJean-Christophe Dubois     case CCM_CCSR:
34781182e1SJean-Christophe Dubois         return "CCSR";
35781182e1SJean-Christophe Dubois     case CCM_CACRR:
36781182e1SJean-Christophe Dubois         return "CACRR";
37781182e1SJean-Christophe Dubois     case CCM_CBCDR:
38781182e1SJean-Christophe Dubois         return "CBCDR";
39781182e1SJean-Christophe Dubois     case CCM_CBCMR:
40781182e1SJean-Christophe Dubois         return "CBCMR";
41781182e1SJean-Christophe Dubois     case CCM_CSCMR1:
42781182e1SJean-Christophe Dubois         return "CSCMR1";
43781182e1SJean-Christophe Dubois     case CCM_CSCMR2:
44781182e1SJean-Christophe Dubois         return "CSCMR2";
45781182e1SJean-Christophe Dubois     case CCM_CSCDR1:
46781182e1SJean-Christophe Dubois         return "CSCDR1";
47781182e1SJean-Christophe Dubois     case CCM_CS1CDR:
48781182e1SJean-Christophe Dubois         return "CS1CDR";
49781182e1SJean-Christophe Dubois     case CCM_CS2CDR:
50781182e1SJean-Christophe Dubois         return "CS2CDR";
51781182e1SJean-Christophe Dubois     case CCM_CDCDR:
52781182e1SJean-Christophe Dubois         return "CDCDR";
53781182e1SJean-Christophe Dubois     case CCM_CHSCCDR:
54781182e1SJean-Christophe Dubois         return "CHSCCDR";
55781182e1SJean-Christophe Dubois     case CCM_CSCDR2:
56781182e1SJean-Christophe Dubois         return "CSCDR2";
57781182e1SJean-Christophe Dubois     case CCM_CSCDR3:
58781182e1SJean-Christophe Dubois         return "CSCDR3";
59781182e1SJean-Christophe Dubois     case CCM_CDHIPR:
60781182e1SJean-Christophe Dubois         return "CDHIPR";
61781182e1SJean-Christophe Dubois     case CCM_CTOR:
62781182e1SJean-Christophe Dubois         return "CTOR";
63781182e1SJean-Christophe Dubois     case CCM_CLPCR:
64781182e1SJean-Christophe Dubois         return "CLPCR";
65781182e1SJean-Christophe Dubois     case CCM_CISR:
66781182e1SJean-Christophe Dubois         return "CISR";
67781182e1SJean-Christophe Dubois     case CCM_CIMR:
68781182e1SJean-Christophe Dubois         return "CIMR";
69781182e1SJean-Christophe Dubois     case CCM_CCOSR:
70781182e1SJean-Christophe Dubois         return "CCOSR";
71781182e1SJean-Christophe Dubois     case CCM_CGPR:
72781182e1SJean-Christophe Dubois         return "CGPR";
73781182e1SJean-Christophe Dubois     case CCM_CCGR0:
74781182e1SJean-Christophe Dubois         return "CCGR0";
75781182e1SJean-Christophe Dubois     case CCM_CCGR1:
76781182e1SJean-Christophe Dubois         return "CCGR1";
77781182e1SJean-Christophe Dubois     case CCM_CCGR2:
78781182e1SJean-Christophe Dubois         return "CCGR2";
79781182e1SJean-Christophe Dubois     case CCM_CCGR3:
80781182e1SJean-Christophe Dubois         return "CCGR3";
81781182e1SJean-Christophe Dubois     case CCM_CCGR4:
82781182e1SJean-Christophe Dubois         return "CCGR4";
83781182e1SJean-Christophe Dubois     case CCM_CCGR5:
84781182e1SJean-Christophe Dubois         return "CCGR5";
85781182e1SJean-Christophe Dubois     case CCM_CCGR6:
86781182e1SJean-Christophe Dubois         return "CCGR6";
87781182e1SJean-Christophe Dubois     case CCM_CMEOR:
88781182e1SJean-Christophe Dubois         return "CMEOR";
89781182e1SJean-Christophe Dubois     default:
90781182e1SJean-Christophe Dubois         sprintf(unknown, "%d ?", reg);
91781182e1SJean-Christophe Dubois         return unknown;
92781182e1SJean-Christophe Dubois     }
93781182e1SJean-Christophe Dubois }
94781182e1SJean-Christophe Dubois 
95781182e1SJean-Christophe Dubois static const char *imx6ul_analog_reg_name(uint32_t reg)
96781182e1SJean-Christophe Dubois {
97781182e1SJean-Christophe Dubois     static char unknown[20];
98781182e1SJean-Christophe Dubois 
99781182e1SJean-Christophe Dubois     switch (reg) {
100781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM:
101781182e1SJean-Christophe Dubois         return "PLL_ARM";
102781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_SET:
103781182e1SJean-Christophe Dubois         return "PLL_ARM_SET";
104781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_CLR:
105781182e1SJean-Christophe Dubois         return "PLL_ARM_CLR";
106781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_TOG:
107781182e1SJean-Christophe Dubois         return "PLL_ARM_TOG";
108781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1:
109781182e1SJean-Christophe Dubois         return "PLL_USB1";
110781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_SET:
111781182e1SJean-Christophe Dubois         return "PLL_USB1_SET";
112781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_CLR:
113781182e1SJean-Christophe Dubois         return "PLL_USB1_CLR";
114781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_TOG:
115781182e1SJean-Christophe Dubois         return "PLL_USB1_TOG";
116781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2:
117781182e1SJean-Christophe Dubois         return "PLL_USB2";
118781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_SET:
119781182e1SJean-Christophe Dubois         return "PLL_USB2_SET";
120781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_CLR:
121781182e1SJean-Christophe Dubois         return "PLL_USB2_CLR";
122781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_TOG:
123781182e1SJean-Christophe Dubois         return "PLL_USB2_TOG";
124781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS:
125781182e1SJean-Christophe Dubois         return "PLL_SYS";
126781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_SET:
127781182e1SJean-Christophe Dubois         return "PLL_SYS_SET";
128781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_CLR:
129781182e1SJean-Christophe Dubois         return "PLL_SYS_CLR";
130781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_TOG:
131781182e1SJean-Christophe Dubois         return "PLL_SYS_TOG";
132781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_SS:
133781182e1SJean-Christophe Dubois         return "PLL_SYS_SS";
134781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_NUM:
135781182e1SJean-Christophe Dubois         return "PLL_SYS_NUM";
136781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_DENOM:
137781182e1SJean-Christophe Dubois         return "PLL_SYS_DENOM";
138781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO:
139781182e1SJean-Christophe Dubois         return "PLL_AUDIO";
140781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_SET:
141781182e1SJean-Christophe Dubois         return "PLL_AUDIO_SET";
142781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_CLR:
143781182e1SJean-Christophe Dubois         return "PLL_AUDIO_CLR";
144781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_TOG:
145781182e1SJean-Christophe Dubois         return "PLL_AUDIO_TOG";
146781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_NUM:
147781182e1SJean-Christophe Dubois         return "PLL_AUDIO_NUM";
148781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_DENOM:
149781182e1SJean-Christophe Dubois         return "PLL_AUDIO_DENOM";
150781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO:
151781182e1SJean-Christophe Dubois         return "PLL_VIDEO";
152781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_SET:
153781182e1SJean-Christophe Dubois         return "PLL_VIDEO_SET";
154781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_CLR:
155781182e1SJean-Christophe Dubois         return "PLL_VIDEO_CLR";
156781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_TOG:
157781182e1SJean-Christophe Dubois         return "PLL_VIDEO_TOG";
158781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_NUM:
159781182e1SJean-Christophe Dubois         return "PLL_VIDEO_NUM";
160781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_DENOM:
161781182e1SJean-Christophe Dubois         return "PLL_VIDEO_DENOM";
162781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET:
163781182e1SJean-Christophe Dubois         return "PLL_ENET";
164781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_SET:
165781182e1SJean-Christophe Dubois         return "PLL_ENET_SET";
166781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_CLR:
167781182e1SJean-Christophe Dubois         return "PLL_ENET_CLR";
168781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_TOG:
169781182e1SJean-Christophe Dubois         return "PLL_ENET_TOG";
170781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480:
171781182e1SJean-Christophe Dubois         return "PFD_480";
172781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_SET:
173781182e1SJean-Christophe Dubois         return "PFD_480_SET";
174781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_CLR:
175781182e1SJean-Christophe Dubois         return "PFD_480_CLR";
176781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_TOG:
177781182e1SJean-Christophe Dubois         return "PFD_480_TOG";
178781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528:
179781182e1SJean-Christophe Dubois         return "PFD_528";
180781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_SET:
181781182e1SJean-Christophe Dubois         return "PFD_528_SET";
182781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_CLR:
183781182e1SJean-Christophe Dubois         return "PFD_528_CLR";
184781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_TOG:
185781182e1SJean-Christophe Dubois         return "PFD_528_TOG";
186781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0:
187781182e1SJean-Christophe Dubois         return "MISC0";
188781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_SET:
189781182e1SJean-Christophe Dubois         return "MISC0_SET";
190781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_CLR:
191781182e1SJean-Christophe Dubois         return "MISC0_CLR";
192781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_TOG:
193781182e1SJean-Christophe Dubois         return "MISC0_TOG";
194781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2:
195781182e1SJean-Christophe Dubois         return "MISC2";
196781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_SET:
197781182e1SJean-Christophe Dubois         return "MISC2_SET";
198781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_CLR:
199781182e1SJean-Christophe Dubois         return "MISC2_CLR";
200781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_TOG:
201781182e1SJean-Christophe Dubois         return "MISC2_TOG";
202781182e1SJean-Christophe Dubois     case PMU_REG_1P1:
203781182e1SJean-Christophe Dubois         return "PMU_REG_1P1";
204781182e1SJean-Christophe Dubois     case PMU_REG_3P0:
205781182e1SJean-Christophe Dubois         return "PMU_REG_3P0";
206781182e1SJean-Christophe Dubois     case PMU_REG_2P5:
207781182e1SJean-Christophe Dubois         return "PMU_REG_2P5";
208781182e1SJean-Christophe Dubois     case PMU_REG_CORE:
209781182e1SJean-Christophe Dubois         return "PMU_REG_CORE";
210781182e1SJean-Christophe Dubois     case PMU_MISC1:
211781182e1SJean-Christophe Dubois         return "PMU_MISC1";
212781182e1SJean-Christophe Dubois     case PMU_MISC1_SET:
213781182e1SJean-Christophe Dubois         return "PMU_MISC1_SET";
214781182e1SJean-Christophe Dubois     case PMU_MISC1_CLR:
215781182e1SJean-Christophe Dubois         return "PMU_MISC1_CLR";
216781182e1SJean-Christophe Dubois     case PMU_MISC1_TOG:
217781182e1SJean-Christophe Dubois         return "PMU_MISC1_TOG";
218781182e1SJean-Christophe Dubois     case USB_ANALOG_DIGPROG:
219781182e1SJean-Christophe Dubois         return "USB_ANALOG_DIGPROG";
220781182e1SJean-Christophe Dubois     default:
221781182e1SJean-Christophe Dubois         sprintf(unknown, "%d ?", reg);
222781182e1SJean-Christophe Dubois         return unknown;
223781182e1SJean-Christophe Dubois     }
224781182e1SJean-Christophe Dubois }
225781182e1SJean-Christophe Dubois 
226781182e1SJean-Christophe Dubois #define CKIH_FREQ 24000000 /* 24MHz crystal input */
227781182e1SJean-Christophe Dubois 
228781182e1SJean-Christophe Dubois static const VMStateDescription vmstate_imx6ul_ccm = {
229781182e1SJean-Christophe Dubois     .name = TYPE_IMX6UL_CCM,
230781182e1SJean-Christophe Dubois     .version_id = 1,
231781182e1SJean-Christophe Dubois     .minimum_version_id = 1,
232781182e1SJean-Christophe Dubois     .fields = (VMStateField[]) {
233781182e1SJean-Christophe Dubois         VMSTATE_UINT32_ARRAY(ccm, IMX6ULCCMState, CCM_MAX),
234781182e1SJean-Christophe Dubois         VMSTATE_UINT32_ARRAY(analog, IMX6ULCCMState, CCM_ANALOG_MAX),
235781182e1SJean-Christophe Dubois         VMSTATE_END_OF_LIST()
236781182e1SJean-Christophe Dubois     },
237781182e1SJean-Christophe Dubois };
238781182e1SJean-Christophe Dubois 
239781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_osc_clk(IMX6ULCCMState *dev)
240781182e1SJean-Christophe Dubois {
241781182e1SJean-Christophe Dubois     uint64_t freq = CKIH_FREQ;
242781182e1SJean-Christophe Dubois 
243781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
244781182e1SJean-Christophe Dubois 
245781182e1SJean-Christophe Dubois     return freq;
246781182e1SJean-Christophe Dubois }
247781182e1SJean-Christophe Dubois 
248781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_clk(IMX6ULCCMState *dev)
249781182e1SJean-Christophe Dubois {
250781182e1SJean-Christophe Dubois     uint64_t freq = imx6ul_analog_get_osc_clk(dev);
251781182e1SJean-Christophe Dubois 
252781182e1SJean-Christophe Dubois     if (FIELD_EX32(dev->analog[CCM_ANALOG_PLL_SYS],
253781182e1SJean-Christophe Dubois                    ANALOG_PLL_SYS, DIV_SELECT)) {
254781182e1SJean-Christophe Dubois         freq *= 22;
255781182e1SJean-Christophe Dubois     } else {
256781182e1SJean-Christophe Dubois         freq *= 20;
257781182e1SJean-Christophe Dubois     }
258781182e1SJean-Christophe Dubois 
259781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
260781182e1SJean-Christophe Dubois 
261781182e1SJean-Christophe Dubois     return freq;
262781182e1SJean-Christophe Dubois }
263781182e1SJean-Christophe Dubois 
264781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll3_clk(IMX6ULCCMState *dev)
265781182e1SJean-Christophe Dubois {
266781182e1SJean-Christophe Dubois     uint64_t freq = imx6ul_analog_get_osc_clk(dev) * 20;
267781182e1SJean-Christophe Dubois 
268781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
269781182e1SJean-Christophe Dubois 
270781182e1SJean-Christophe Dubois     return freq;
271781182e1SJean-Christophe Dubois }
272781182e1SJean-Christophe Dubois 
273781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_pfd0_clk(IMX6ULCCMState *dev)
274781182e1SJean-Christophe Dubois {
275781182e1SJean-Christophe Dubois     uint64_t freq = 0;
276781182e1SJean-Christophe Dubois 
277781182e1SJean-Christophe Dubois     freq = imx6ul_analog_get_pll2_clk(dev) * 18
278781182e1SJean-Christophe Dubois            / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
279781182e1SJean-Christophe Dubois                         ANALOG_PFD_528, PFD0_FRAC);
280781182e1SJean-Christophe Dubois 
281781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
282781182e1SJean-Christophe Dubois 
283781182e1SJean-Christophe Dubois     return freq;
284781182e1SJean-Christophe Dubois }
285781182e1SJean-Christophe Dubois 
286781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_get_pll2_pfd2_clk(IMX6ULCCMState *dev)
287781182e1SJean-Christophe Dubois {
288781182e1SJean-Christophe Dubois     uint64_t freq = 0;
289781182e1SJean-Christophe Dubois 
290781182e1SJean-Christophe Dubois     freq = imx6ul_analog_get_pll2_clk(dev) * 18
291781182e1SJean-Christophe Dubois            / FIELD_EX32(dev->analog[CCM_ANALOG_PFD_528],
292781182e1SJean-Christophe Dubois                         ANALOG_PFD_528, PFD2_FRAC);
293781182e1SJean-Christophe Dubois 
294781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
295781182e1SJean-Christophe Dubois 
296781182e1SJean-Christophe Dubois     return freq;
297781182e1SJean-Christophe Dubois }
298781182e1SJean-Christophe Dubois 
299781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_pll2_bypass_clk(IMX6ULCCMState *dev)
300781182e1SJean-Christophe Dubois {
301781182e1SJean-Christophe Dubois     uint64_t freq = 0;
302781182e1SJean-Christophe Dubois 
303781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
304781182e1SJean-Christophe Dubois 
305781182e1SJean-Christophe Dubois     return freq;
306781182e1SJean-Christophe Dubois }
307781182e1SJean-Christophe Dubois 
308781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk2_sel_clk(IMX6ULCCMState *dev)
309781182e1SJean-Christophe Dubois {
310781182e1SJean-Christophe Dubois     uint64_t freq = 0;
311781182e1SJean-Christophe Dubois 
312781182e1SJean-Christophe Dubois     switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PERIPH_CLK2_SEL)) {
313781182e1SJean-Christophe Dubois     case 0:
314781182e1SJean-Christophe Dubois         freq = imx6ul_analog_get_pll3_clk(dev);
315781182e1SJean-Christophe Dubois         break;
316781182e1SJean-Christophe Dubois     case 1:
317781182e1SJean-Christophe Dubois         freq = imx6ul_analog_get_osc_clk(dev);
318781182e1SJean-Christophe Dubois         break;
319781182e1SJean-Christophe Dubois     case 2:
320781182e1SJean-Christophe Dubois         freq = imx6ul_analog_pll2_bypass_clk(dev);
321781182e1SJean-Christophe Dubois         break;
322781182e1SJean-Christophe Dubois     case 3:
323781182e1SJean-Christophe Dubois         /* We should never get there as 3 is a reserved value */
324781182e1SJean-Christophe Dubois         qemu_log_mask(LOG_GUEST_ERROR,
325781182e1SJean-Christophe Dubois                       "[%s]%s: unsupported PERIPH_CLK2_SEL value 3\n",
326781182e1SJean-Christophe Dubois                       TYPE_IMX6UL_CCM, __func__);
327781182e1SJean-Christophe Dubois         /* freq is set to 0 as we don't know what it should be */
328781182e1SJean-Christophe Dubois         break;
329781182e1SJean-Christophe Dubois     default:
330781182e1SJean-Christophe Dubois         g_assert_not_reached();
331781182e1SJean-Christophe Dubois     }
332781182e1SJean-Christophe Dubois 
333781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
334781182e1SJean-Christophe Dubois 
335781182e1SJean-Christophe Dubois     return freq;
336781182e1SJean-Christophe Dubois }
337781182e1SJean-Christophe Dubois 
338781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk_sel_clk(IMX6ULCCMState *dev)
339781182e1SJean-Christophe Dubois {
340781182e1SJean-Christophe Dubois     uint64_t freq = 0;
341781182e1SJean-Christophe Dubois 
342781182e1SJean-Christophe Dubois     switch (FIELD_EX32(dev->ccm[CCM_CBCMR], CBCMR, PRE_PERIPH_CLK_SEL)) {
343781182e1SJean-Christophe Dubois     case 0:
344781182e1SJean-Christophe Dubois         freq = imx6ul_analog_get_pll2_clk(dev);
345781182e1SJean-Christophe Dubois         break;
346781182e1SJean-Christophe Dubois     case 1:
347781182e1SJean-Christophe Dubois         freq = imx6ul_analog_get_pll2_pfd2_clk(dev);
348781182e1SJean-Christophe Dubois         break;
349781182e1SJean-Christophe Dubois     case 2:
350781182e1SJean-Christophe Dubois         freq = imx6ul_analog_get_pll2_pfd0_clk(dev);
351781182e1SJean-Christophe Dubois         break;
352781182e1SJean-Christophe Dubois     case 3:
353781182e1SJean-Christophe Dubois         freq = imx6ul_analog_get_pll2_pfd2_clk(dev) / 2;
354781182e1SJean-Christophe Dubois         break;
355781182e1SJean-Christophe Dubois     default:
356781182e1SJean-Christophe Dubois         g_assert_not_reached();
357781182e1SJean-Christophe Dubois     }
358781182e1SJean-Christophe Dubois 
359781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
360781182e1SJean-Christophe Dubois 
361781182e1SJean-Christophe Dubois     return freq;
362781182e1SJean-Christophe Dubois }
363781182e1SJean-Christophe Dubois 
364781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_clk2_clk(IMX6ULCCMState *dev)
365781182e1SJean-Christophe Dubois {
366781182e1SJean-Christophe Dubois     uint64_t freq = 0;
367781182e1SJean-Christophe Dubois 
368781182e1SJean-Christophe Dubois     freq = imx6ul_ccm_get_periph_clk2_sel_clk(dev)
369781182e1SJean-Christophe Dubois            / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK2_PODF));
370781182e1SJean-Christophe Dubois 
371781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
372781182e1SJean-Christophe Dubois 
373781182e1SJean-Christophe Dubois     return freq;
374781182e1SJean-Christophe Dubois }
375781182e1SJean-Christophe Dubois 
376781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_periph_sel_clk(IMX6ULCCMState *dev)
377781182e1SJean-Christophe Dubois {
378781182e1SJean-Christophe Dubois     uint64_t freq = 0;
379781182e1SJean-Christophe Dubois 
380781182e1SJean-Christophe Dubois     switch (FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, PERIPH_CLK_SEL)) {
381781182e1SJean-Christophe Dubois     case 0:
382781182e1SJean-Christophe Dubois         freq = imx6ul_ccm_get_periph_clk_sel_clk(dev);
383781182e1SJean-Christophe Dubois         break;
384781182e1SJean-Christophe Dubois     case 1:
385781182e1SJean-Christophe Dubois         freq = imx6ul_ccm_get_periph_clk2_clk(dev);
386781182e1SJean-Christophe Dubois         break;
387781182e1SJean-Christophe Dubois     default:
388781182e1SJean-Christophe Dubois         g_assert_not_reached();
389781182e1SJean-Christophe Dubois     }
390781182e1SJean-Christophe Dubois 
391781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
392781182e1SJean-Christophe Dubois 
393781182e1SJean-Christophe Dubois     return freq;
394781182e1SJean-Christophe Dubois }
395781182e1SJean-Christophe Dubois 
396781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_ahb_clk(IMX6ULCCMState *dev)
397781182e1SJean-Christophe Dubois {
398781182e1SJean-Christophe Dubois     uint64_t freq = 0;
399781182e1SJean-Christophe Dubois 
400781182e1SJean-Christophe Dubois     freq = imx6ul_ccm_get_periph_sel_clk(dev)
401781182e1SJean-Christophe Dubois            / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, AHB_PODF));
402781182e1SJean-Christophe Dubois 
403781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
404781182e1SJean-Christophe Dubois 
405781182e1SJean-Christophe Dubois     return freq;
406781182e1SJean-Christophe Dubois }
407781182e1SJean-Christophe Dubois 
408781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_ipg_clk(IMX6ULCCMState *dev)
409781182e1SJean-Christophe Dubois {
410781182e1SJean-Christophe Dubois     uint64_t freq = 0;
411781182e1SJean-Christophe Dubois 
412781182e1SJean-Christophe Dubois     freq = imx6ul_ccm_get_ahb_clk(dev)
413781182e1SJean-Christophe Dubois            / (1 + FIELD_EX32(dev->ccm[CCM_CBCDR], CBCDR, IPG_PODF));
414781182e1SJean-Christophe Dubois 
415781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
416781182e1SJean-Christophe Dubois 
417781182e1SJean-Christophe Dubois     return freq;
418781182e1SJean-Christophe Dubois }
419781182e1SJean-Christophe Dubois 
420781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_per_sel_clk(IMX6ULCCMState *dev)
421781182e1SJean-Christophe Dubois {
422781182e1SJean-Christophe Dubois     uint64_t freq = 0;
423781182e1SJean-Christophe Dubois 
424781182e1SJean-Christophe Dubois     switch (FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_CLK_SEL)) {
425781182e1SJean-Christophe Dubois     case 0:
426781182e1SJean-Christophe Dubois         freq = imx6ul_ccm_get_ipg_clk(dev);
427781182e1SJean-Christophe Dubois         break;
428781182e1SJean-Christophe Dubois     case 1:
429781182e1SJean-Christophe Dubois         freq = imx6ul_analog_get_osc_clk(dev);
430781182e1SJean-Christophe Dubois         break;
431781182e1SJean-Christophe Dubois     default:
432781182e1SJean-Christophe Dubois         g_assert_not_reached();
433781182e1SJean-Christophe Dubois     }
434781182e1SJean-Christophe Dubois 
435781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
436781182e1SJean-Christophe Dubois 
437781182e1SJean-Christophe Dubois     return freq;
438781182e1SJean-Christophe Dubois }
439781182e1SJean-Christophe Dubois 
440781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_get_per_clk(IMX6ULCCMState *dev)
441781182e1SJean-Christophe Dubois {
442781182e1SJean-Christophe Dubois     uint64_t freq = 0;
443781182e1SJean-Christophe Dubois 
444781182e1SJean-Christophe Dubois     freq = imx6ul_ccm_get_per_sel_clk(dev)
445781182e1SJean-Christophe Dubois            / (1 + FIELD_EX32(dev->ccm[CCM_CSCMR1], CSCMR1, PERCLK_PODF));
446781182e1SJean-Christophe Dubois 
447781182e1SJean-Christophe Dubois     trace_ccm_freq((uint32_t)freq);
448781182e1SJean-Christophe Dubois 
449781182e1SJean-Christophe Dubois     return freq;
450781182e1SJean-Christophe Dubois }
451781182e1SJean-Christophe Dubois 
452781182e1SJean-Christophe Dubois static uint32_t imx6ul_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
453781182e1SJean-Christophe Dubois {
454781182e1SJean-Christophe Dubois     uint32_t freq = 0;
455781182e1SJean-Christophe Dubois     IMX6ULCCMState *s = IMX6UL_CCM(dev);
456781182e1SJean-Christophe Dubois 
457781182e1SJean-Christophe Dubois     switch (clock) {
458781182e1SJean-Christophe Dubois     case CLK_NONE:
459781182e1SJean-Christophe Dubois         break;
460781182e1SJean-Christophe Dubois     case CLK_IPG:
461781182e1SJean-Christophe Dubois         freq = imx6ul_ccm_get_ipg_clk(s);
462781182e1SJean-Christophe Dubois         break;
463781182e1SJean-Christophe Dubois     case CLK_IPG_HIGH:
464781182e1SJean-Christophe Dubois         freq = imx6ul_ccm_get_per_clk(s);
465781182e1SJean-Christophe Dubois         break;
466781182e1SJean-Christophe Dubois     case CLK_32k:
467781182e1SJean-Christophe Dubois         freq = CKIL_FREQ;
468781182e1SJean-Christophe Dubois         break;
469781182e1SJean-Christophe Dubois     case CLK_HIGH:
470781182e1SJean-Christophe Dubois         freq = CKIH_FREQ;
471781182e1SJean-Christophe Dubois         break;
472781182e1SJean-Christophe Dubois     case CLK_HIGH_DIV:
473781182e1SJean-Christophe Dubois         freq = CKIH_FREQ / 8;
474781182e1SJean-Christophe Dubois         break;
475781182e1SJean-Christophe Dubois     default:
476781182e1SJean-Christophe Dubois         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
477781182e1SJean-Christophe Dubois                       TYPE_IMX6UL_CCM, __func__, clock);
478781182e1SJean-Christophe Dubois         break;
479781182e1SJean-Christophe Dubois     }
480781182e1SJean-Christophe Dubois 
481781182e1SJean-Christophe Dubois     trace_ccm_clock_freq(clock, freq);
482781182e1SJean-Christophe Dubois 
483781182e1SJean-Christophe Dubois     return freq;
484781182e1SJean-Christophe Dubois }
485781182e1SJean-Christophe Dubois 
486781182e1SJean-Christophe Dubois static void imx6ul_ccm_reset(DeviceState *dev)
487781182e1SJean-Christophe Dubois {
488781182e1SJean-Christophe Dubois     IMX6ULCCMState *s = IMX6UL_CCM(dev);
489781182e1SJean-Christophe Dubois 
490781182e1SJean-Christophe Dubois     trace_ccm_entry();
491781182e1SJean-Christophe Dubois 
492781182e1SJean-Christophe Dubois     s->ccm[CCM_CCR] = 0x0401167F;
493781182e1SJean-Christophe Dubois     s->ccm[CCM_CCDR] = 0x00000000;
494781182e1SJean-Christophe Dubois     s->ccm[CCM_CSR] = 0x00000010;
495781182e1SJean-Christophe Dubois     s->ccm[CCM_CCSR] = 0x00000100;
496781182e1SJean-Christophe Dubois     s->ccm[CCM_CACRR] = 0x00000000;
497781182e1SJean-Christophe Dubois     s->ccm[CCM_CBCDR] = 0x00018D00;
498781182e1SJean-Christophe Dubois     s->ccm[CCM_CBCMR] = 0x24860324;
499781182e1SJean-Christophe Dubois     s->ccm[CCM_CSCMR1] = 0x04900080;
500781182e1SJean-Christophe Dubois     s->ccm[CCM_CSCMR2] = 0x03192F06;
501781182e1SJean-Christophe Dubois     s->ccm[CCM_CSCDR1] = 0x00490B00;
502781182e1SJean-Christophe Dubois     s->ccm[CCM_CS1CDR] = 0x0EC102C1;
503781182e1SJean-Christophe Dubois     s->ccm[CCM_CS2CDR] = 0x000336C1;
504781182e1SJean-Christophe Dubois     s->ccm[CCM_CDCDR] = 0x33F71F92;
505781182e1SJean-Christophe Dubois     s->ccm[CCM_CHSCCDR] = 0x000248A4;
506781182e1SJean-Christophe Dubois     s->ccm[CCM_CSCDR2] = 0x00029B48;
507781182e1SJean-Christophe Dubois     s->ccm[CCM_CSCDR3] = 0x00014841;
508781182e1SJean-Christophe Dubois     s->ccm[CCM_CDHIPR] = 0x00000000;
509781182e1SJean-Christophe Dubois     s->ccm[CCM_CTOR] = 0x00000000;
510781182e1SJean-Christophe Dubois     s->ccm[CCM_CLPCR] = 0x00000079;
511781182e1SJean-Christophe Dubois     s->ccm[CCM_CISR] = 0x00000000;
512781182e1SJean-Christophe Dubois     s->ccm[CCM_CIMR] = 0xFFFFFFFF;
513781182e1SJean-Christophe Dubois     s->ccm[CCM_CCOSR] = 0x000A0001;
514781182e1SJean-Christophe Dubois     s->ccm[CCM_CGPR] = 0x0000FE62;
515781182e1SJean-Christophe Dubois     s->ccm[CCM_CCGR0] = 0xFFFFFFFF;
516781182e1SJean-Christophe Dubois     s->ccm[CCM_CCGR1] = 0xFFFFFFFF;
517781182e1SJean-Christophe Dubois     s->ccm[CCM_CCGR2] = 0xFC3FFFFF;
518781182e1SJean-Christophe Dubois     s->ccm[CCM_CCGR3] = 0xFFFFFFFF;
519781182e1SJean-Christophe Dubois     s->ccm[CCM_CCGR4] = 0xFFFFFFFF;
520781182e1SJean-Christophe Dubois     s->ccm[CCM_CCGR5] = 0xFFFFFFFF;
521781182e1SJean-Christophe Dubois     s->ccm[CCM_CCGR6] = 0xFFFFFFFF;
522781182e1SJean-Christophe Dubois     s->ccm[CCM_CMEOR] = 0xFFFFFFFF;
523781182e1SJean-Christophe Dubois 
524781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_ARM] = 0x00013063;
525781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_USB1] = 0x00012000;
526781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_USB2] = 0x00012000;
527781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_SYS] = 0x00013001;
528781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_SYS_SS] = 0x00000000;
529781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_SYS_NUM] = 0x00000000;
530781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_SYS_DENOM] = 0x00000012;
531781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_AUDIO] = 0x00011006;
532781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_AUDIO_NUM] = 0x05F5E100;
533781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619C;
534781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_VIDEO] = 0x0001100C;
535781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_VIDEO_NUM] = 0x05F5E100;
536781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x10A24447;
537781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_ENET] = 0x00011001;
538781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PFD_480] = 0x1311100C;
539781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PFD_528] = 0x1018101B;
540781182e1SJean-Christophe Dubois 
541781182e1SJean-Christophe Dubois     s->analog[PMU_REG_1P1] = 0x00001073;
542781182e1SJean-Christophe Dubois     s->analog[PMU_REG_3P0] = 0x00000F74;
543781182e1SJean-Christophe Dubois     s->analog[PMU_REG_2P5] = 0x00001073;
544781182e1SJean-Christophe Dubois     s->analog[PMU_REG_CORE] = 0x00482012;
545781182e1SJean-Christophe Dubois     s->analog[PMU_MISC0] = 0x04000000;
546781182e1SJean-Christophe Dubois     s->analog[PMU_MISC1] = 0x00000000;
547781182e1SJean-Christophe Dubois     s->analog[PMU_MISC2] = 0x00272727;
548781182e1SJean-Christophe Dubois     s->analog[PMU_LOWPWR_CTRL] = 0x00004009;
549781182e1SJean-Christophe Dubois 
550781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_USB1_VBUS_DETECT] = 0x01000004;
551781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_USB1_CHRG_DETECT] = 0x00000000;
552781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_USB1_VBUS_DETECT_STAT] = 0x00000000;
553781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_USB1_CHRG_DETECT_STAT] = 0x00000000;
554781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_USB1_MISC] = 0x00000002;
555781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_USB2_VBUS_DETECT] = 0x01000004;
556781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_USB2_CHRG_DETECT] = 0x00000000;
557781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_USB2_MISC] = 0x00000002;
558781182e1SJean-Christophe Dubois     s->analog[USB_ANALOG_DIGPROG] = 0x00640000;
559781182e1SJean-Christophe Dubois 
560781182e1SJean-Christophe Dubois     /* all PLLs need to be locked */
561781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_ARM]   |= CCM_ANALOG_PLL_LOCK;
562781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_USB1]  |= CCM_ANALOG_PLL_LOCK;
563781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_USB2]  |= CCM_ANALOG_PLL_LOCK;
564781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_SYS]   |= CCM_ANALOG_PLL_LOCK;
565781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
566781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
567781182e1SJean-Christophe Dubois     s->analog[CCM_ANALOG_PLL_ENET]  |= CCM_ANALOG_PLL_LOCK;
568781182e1SJean-Christophe Dubois 
569781182e1SJean-Christophe Dubois     s->analog[TEMPMON_TEMPSENSE0] = 0x00000001;
570781182e1SJean-Christophe Dubois     s->analog[TEMPMON_TEMPSENSE1] = 0x00000001;
571781182e1SJean-Christophe Dubois     s->analog[TEMPMON_TEMPSENSE2] = 0x00000000;
572781182e1SJean-Christophe Dubois }
573781182e1SJean-Christophe Dubois 
574781182e1SJean-Christophe Dubois static uint64_t imx6ul_ccm_read(void *opaque, hwaddr offset, unsigned size)
575781182e1SJean-Christophe Dubois {
576781182e1SJean-Christophe Dubois     uint32_t value = 0;
577781182e1SJean-Christophe Dubois     uint32_t index = offset >> 2;
578781182e1SJean-Christophe Dubois     IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
579781182e1SJean-Christophe Dubois 
580781182e1SJean-Christophe Dubois     assert(index < CCM_MAX);
581781182e1SJean-Christophe Dubois 
582781182e1SJean-Christophe Dubois     value = s->ccm[index];
583781182e1SJean-Christophe Dubois 
584781182e1SJean-Christophe Dubois     trace_ccm_read_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
585781182e1SJean-Christophe Dubois 
586781182e1SJean-Christophe Dubois     return (uint64_t)value;
587781182e1SJean-Christophe Dubois }
588781182e1SJean-Christophe Dubois 
589781182e1SJean-Christophe Dubois static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value,
590781182e1SJean-Christophe Dubois                            unsigned size)
591781182e1SJean-Christophe Dubois {
592781182e1SJean-Christophe Dubois     uint32_t index = offset >> 2;
593781182e1SJean-Christophe Dubois     IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
594781182e1SJean-Christophe Dubois 
595781182e1SJean-Christophe Dubois     assert(index < CCM_MAX);
596781182e1SJean-Christophe Dubois 
597781182e1SJean-Christophe Dubois     trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
598781182e1SJean-Christophe Dubois 
599781182e1SJean-Christophe Dubois     /*
600781182e1SJean-Christophe Dubois      * We will do a better implementation later. In particular some bits
601781182e1SJean-Christophe Dubois      * cannot be written to.
602781182e1SJean-Christophe Dubois      */
603781182e1SJean-Christophe Dubois     s->ccm[index] = (uint32_t)value;
604781182e1SJean-Christophe Dubois }
605781182e1SJean-Christophe Dubois 
606781182e1SJean-Christophe Dubois static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size)
607781182e1SJean-Christophe Dubois {
608781182e1SJean-Christophe Dubois     uint32_t value;
609781182e1SJean-Christophe Dubois     uint32_t index = offset >> 2;
610781182e1SJean-Christophe Dubois     IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
611781182e1SJean-Christophe Dubois 
612781182e1SJean-Christophe Dubois     assert(index < CCM_ANALOG_MAX);
613781182e1SJean-Christophe Dubois 
614781182e1SJean-Christophe Dubois     switch (index) {
615781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_SET:
616781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_SET:
617781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_SET:
618781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_SET:
619781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_SET:
620781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_SET:
621781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_SET:
622781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_SET:
623781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_SET:
624781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_SET:
625781182e1SJean-Christophe Dubois     case PMU_MISC1_SET:
626781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_SET:
627781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_VBUS_DETECT_SET:
628781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_CHRG_DETECT_SET:
629781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_MISC_SET:
630781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_VBUS_DETECT_SET:
631781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_CHRG_DETECT_SET:
632781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_MISC_SET:
633781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE0_SET:
634781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE1_SET:
635781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE2_SET:
636781182e1SJean-Christophe Dubois         /*
637781182e1SJean-Christophe Dubois          * All REG_NAME_SET register access are in fact targeting
638781182e1SJean-Christophe Dubois          * the REG_NAME register.
639781182e1SJean-Christophe Dubois          */
640781182e1SJean-Christophe Dubois         value = s->analog[index - 1];
641781182e1SJean-Christophe Dubois         break;
642781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_CLR:
643781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_CLR:
644781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_CLR:
645781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_CLR:
646781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_CLR:
647781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_CLR:
648781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_CLR:
649781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_CLR:
650781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_CLR:
651781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_CLR:
652781182e1SJean-Christophe Dubois     case PMU_MISC1_CLR:
653781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_CLR:
654781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_VBUS_DETECT_CLR:
655781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_CHRG_DETECT_CLR:
656781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_MISC_CLR:
657781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_VBUS_DETECT_CLR:
658781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_CHRG_DETECT_CLR:
659781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_MISC_CLR:
660781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE0_CLR:
661781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE1_CLR:
662781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE2_CLR:
663781182e1SJean-Christophe Dubois         /*
664781182e1SJean-Christophe Dubois          * All REG_NAME_CLR register access are in fact targeting
665781182e1SJean-Christophe Dubois          * the REG_NAME register.
666781182e1SJean-Christophe Dubois          */
667781182e1SJean-Christophe Dubois         value = s->analog[index - 2];
668781182e1SJean-Christophe Dubois         break;
669781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_TOG:
670781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_TOG:
671781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_TOG:
672781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_TOG:
673781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_TOG:
674781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_TOG:
675781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_TOG:
676781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_TOG:
677781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_TOG:
678781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_TOG:
679781182e1SJean-Christophe Dubois     case PMU_MISC1_TOG:
680781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_TOG:
681781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_VBUS_DETECT_TOG:
682781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_CHRG_DETECT_TOG:
683781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_MISC_TOG:
684781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_VBUS_DETECT_TOG:
685781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_CHRG_DETECT_TOG:
686781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_MISC_TOG:
687781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE0_TOG:
688781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE1_TOG:
689781182e1SJean-Christophe Dubois     case TEMPMON_TEMPSENSE2_TOG:
690781182e1SJean-Christophe Dubois         /*
691781182e1SJean-Christophe Dubois          * All REG_NAME_TOG register access are in fact targeting
692781182e1SJean-Christophe Dubois          * the REG_NAME register.
693781182e1SJean-Christophe Dubois          */
694781182e1SJean-Christophe Dubois         value = s->analog[index - 3];
695781182e1SJean-Christophe Dubois         break;
696781182e1SJean-Christophe Dubois     default:
697781182e1SJean-Christophe Dubois         value = s->analog[index];
698781182e1SJean-Christophe Dubois         break;
699781182e1SJean-Christophe Dubois     }
700781182e1SJean-Christophe Dubois 
701781182e1SJean-Christophe Dubois     trace_ccm_read_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
702781182e1SJean-Christophe Dubois 
703781182e1SJean-Christophe Dubois     return (uint64_t)value;
704781182e1SJean-Christophe Dubois }
705781182e1SJean-Christophe Dubois 
706781182e1SJean-Christophe Dubois static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
707781182e1SJean-Christophe Dubois                               unsigned size)
708781182e1SJean-Christophe Dubois {
709781182e1SJean-Christophe Dubois     uint32_t index = offset >> 2;
710781182e1SJean-Christophe Dubois     IMX6ULCCMState *s = (IMX6ULCCMState *)opaque;
711781182e1SJean-Christophe Dubois 
712781182e1SJean-Christophe Dubois     assert(index < CCM_ANALOG_MAX);
713781182e1SJean-Christophe Dubois 
714781182e1SJean-Christophe Dubois     trace_ccm_write_reg(imx6ul_analog_reg_name(index), (uint32_t)value);
715781182e1SJean-Christophe Dubois 
716781182e1SJean-Christophe Dubois     switch (index) {
717781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_SET:
718781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_SET:
719781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_SET:
720781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_SET:
721781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_SET:
722781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_SET:
723781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_SET:
724781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_SET:
725781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_SET:
726781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_SET:
727781182e1SJean-Christophe Dubois     case PMU_MISC1_SET:
728781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_SET:
729781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_VBUS_DETECT_SET:
730781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_CHRG_DETECT_SET:
731781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_MISC_SET:
732781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_VBUS_DETECT_SET:
733781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_CHRG_DETECT_SET:
734781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_MISC_SET:
735781182e1SJean-Christophe Dubois         /*
736781182e1SJean-Christophe Dubois          * All REG_NAME_SET register access are in fact targeting
737781182e1SJean-Christophe Dubois          * the REG_NAME register. So we change the value of the
738781182e1SJean-Christophe Dubois          * REG_NAME register, setting bits passed in the value.
739781182e1SJean-Christophe Dubois          */
740781182e1SJean-Christophe Dubois         s->analog[index - 1] |= value;
741781182e1SJean-Christophe Dubois         break;
742781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_CLR:
743781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_CLR:
744781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_CLR:
745781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_CLR:
746781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_CLR:
747781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_CLR:
748781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_CLR:
749781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_CLR:
750781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_CLR:
751781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_CLR:
752781182e1SJean-Christophe Dubois     case PMU_MISC1_CLR:
753781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_CLR:
754781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_VBUS_DETECT_CLR:
755781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_CHRG_DETECT_CLR:
756781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_MISC_CLR:
757781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_VBUS_DETECT_CLR:
758781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_CHRG_DETECT_CLR:
759781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_MISC_CLR:
760781182e1SJean-Christophe Dubois         /*
761781182e1SJean-Christophe Dubois          * All REG_NAME_CLR register access are in fact targeting
762781182e1SJean-Christophe Dubois          * the REG_NAME register. So we change the value of the
763781182e1SJean-Christophe Dubois          * REG_NAME register, unsetting bits passed in the value.
764781182e1SJean-Christophe Dubois          */
765781182e1SJean-Christophe Dubois         s->analog[index - 2] &= ~value;
766781182e1SJean-Christophe Dubois         break;
767781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ARM_TOG:
768781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB1_TOG:
769781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_USB2_TOG:
770781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_SYS_TOG:
771781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_AUDIO_TOG:
772781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_VIDEO_TOG:
773781182e1SJean-Christophe Dubois     case CCM_ANALOG_PLL_ENET_TOG:
774781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_480_TOG:
775781182e1SJean-Christophe Dubois     case CCM_ANALOG_PFD_528_TOG:
776781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC0_TOG:
777781182e1SJean-Christophe Dubois     case PMU_MISC1_TOG:
778781182e1SJean-Christophe Dubois     case CCM_ANALOG_MISC2_TOG:
779781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_VBUS_DETECT_TOG:
780781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_CHRG_DETECT_TOG:
781781182e1SJean-Christophe Dubois     case USB_ANALOG_USB1_MISC_TOG:
782781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_VBUS_DETECT_TOG:
783781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_CHRG_DETECT_TOG:
784781182e1SJean-Christophe Dubois     case USB_ANALOG_USB2_MISC_TOG:
785781182e1SJean-Christophe Dubois         /*
786781182e1SJean-Christophe Dubois          * All REG_NAME_TOG register access are in fact targeting
787781182e1SJean-Christophe Dubois          * the REG_NAME register. So we change the value of the
788781182e1SJean-Christophe Dubois          * REG_NAME register, toggling bits passed in the value.
789781182e1SJean-Christophe Dubois          */
790781182e1SJean-Christophe Dubois         s->analog[index - 3] ^= value;
791781182e1SJean-Christophe Dubois         break;
792781182e1SJean-Christophe Dubois     default:
793781182e1SJean-Christophe Dubois         /*
794781182e1SJean-Christophe Dubois          * We will do a better implementation later. In particular some bits
795781182e1SJean-Christophe Dubois          * cannot be written to.
796781182e1SJean-Christophe Dubois          */
797781182e1SJean-Christophe Dubois         s->analog[index] = value;
798781182e1SJean-Christophe Dubois         break;
799781182e1SJean-Christophe Dubois     }
800781182e1SJean-Christophe Dubois }
801781182e1SJean-Christophe Dubois 
802781182e1SJean-Christophe Dubois static const struct MemoryRegionOps imx6ul_ccm_ops = {
803781182e1SJean-Christophe Dubois     .read = imx6ul_ccm_read,
804781182e1SJean-Christophe Dubois     .write = imx6ul_ccm_write,
805781182e1SJean-Christophe Dubois     .endianness = DEVICE_NATIVE_ENDIAN,
806781182e1SJean-Christophe Dubois     .valid = {
807781182e1SJean-Christophe Dubois         /*
808781182e1SJean-Christophe Dubois          * Our device would not work correctly if the guest was doing
809781182e1SJean-Christophe Dubois          * unaligned access. This might not be a limitation on the real
810781182e1SJean-Christophe Dubois          * device but in practice there is no reason for a guest to access
811781182e1SJean-Christophe Dubois          * this device unaligned.
812781182e1SJean-Christophe Dubois          */
813781182e1SJean-Christophe Dubois         .min_access_size = 4,
814781182e1SJean-Christophe Dubois         .max_access_size = 4,
815781182e1SJean-Christophe Dubois         .unaligned = false,
816781182e1SJean-Christophe Dubois     },
817781182e1SJean-Christophe Dubois };
818781182e1SJean-Christophe Dubois 
819781182e1SJean-Christophe Dubois static const struct MemoryRegionOps imx6ul_analog_ops = {
820781182e1SJean-Christophe Dubois     .read = imx6ul_analog_read,
821781182e1SJean-Christophe Dubois     .write = imx6ul_analog_write,
822781182e1SJean-Christophe Dubois     .endianness = DEVICE_NATIVE_ENDIAN,
823781182e1SJean-Christophe Dubois     .valid = {
824781182e1SJean-Christophe Dubois         /*
825781182e1SJean-Christophe Dubois          * Our device would not work correctly if the guest was doing
826781182e1SJean-Christophe Dubois          * unaligned access. This might not be a limitation on the real
827781182e1SJean-Christophe Dubois          * device but in practice there is no reason for a guest to access
828781182e1SJean-Christophe Dubois          * this device unaligned.
829781182e1SJean-Christophe Dubois          */
830781182e1SJean-Christophe Dubois         .min_access_size = 4,
831781182e1SJean-Christophe Dubois         .max_access_size = 4,
832781182e1SJean-Christophe Dubois         .unaligned = false,
833781182e1SJean-Christophe Dubois     },
834781182e1SJean-Christophe Dubois };
835781182e1SJean-Christophe Dubois 
836781182e1SJean-Christophe Dubois static void imx6ul_ccm_init(Object *obj)
837781182e1SJean-Christophe Dubois {
838781182e1SJean-Christophe Dubois     DeviceState *dev = DEVICE(obj);
839781182e1SJean-Christophe Dubois     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
840781182e1SJean-Christophe Dubois     IMX6ULCCMState *s = IMX6UL_CCM(obj);
841781182e1SJean-Christophe Dubois 
842781182e1SJean-Christophe Dubois     /* initialize a container for the all memory range */
843781182e1SJean-Christophe Dubois     memory_region_init(&s->container, OBJECT(dev), TYPE_IMX6UL_CCM, 0x8000);
844781182e1SJean-Christophe Dubois 
845781182e1SJean-Christophe Dubois     /* We initialize an IO memory region for the CCM part */
846781182e1SJean-Christophe Dubois     memory_region_init_io(&s->ioccm, OBJECT(dev), &imx6ul_ccm_ops, s,
847781182e1SJean-Christophe Dubois                           TYPE_IMX6UL_CCM ".ccm", CCM_MAX * sizeof(uint32_t));
848781182e1SJean-Christophe Dubois 
849781182e1SJean-Christophe Dubois     /* Add the CCM as a subregion at offset 0 */
850781182e1SJean-Christophe Dubois     memory_region_add_subregion(&s->container, 0, &s->ioccm);
851781182e1SJean-Christophe Dubois 
852781182e1SJean-Christophe Dubois     /* We initialize an IO memory region for the ANALOG part */
853781182e1SJean-Christophe Dubois     memory_region_init_io(&s->ioanalog, OBJECT(dev), &imx6ul_analog_ops, s,
854781182e1SJean-Christophe Dubois                           TYPE_IMX6UL_CCM ".analog",
855781182e1SJean-Christophe Dubois                           CCM_ANALOG_MAX * sizeof(uint32_t));
856781182e1SJean-Christophe Dubois 
857781182e1SJean-Christophe Dubois     /* Add the ANALOG as a subregion at offset 0x4000 */
858781182e1SJean-Christophe Dubois     memory_region_add_subregion(&s->container, 0x4000, &s->ioanalog);
859781182e1SJean-Christophe Dubois 
860781182e1SJean-Christophe Dubois     sysbus_init_mmio(sd, &s->container);
861781182e1SJean-Christophe Dubois }
862781182e1SJean-Christophe Dubois 
863781182e1SJean-Christophe Dubois static void imx6ul_ccm_class_init(ObjectClass *klass, void *data)
864781182e1SJean-Christophe Dubois {
865781182e1SJean-Christophe Dubois     DeviceClass *dc = DEVICE_CLASS(klass);
866781182e1SJean-Christophe Dubois     IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
867781182e1SJean-Christophe Dubois 
868781182e1SJean-Christophe Dubois     dc->reset = imx6ul_ccm_reset;
869781182e1SJean-Christophe Dubois     dc->vmsd = &vmstate_imx6ul_ccm;
870781182e1SJean-Christophe Dubois     dc->desc = "i.MX6UL Clock Control Module";
871781182e1SJean-Christophe Dubois 
872781182e1SJean-Christophe Dubois     ccm->get_clock_frequency = imx6ul_ccm_get_clock_frequency;
873781182e1SJean-Christophe Dubois }
874781182e1SJean-Christophe Dubois 
875781182e1SJean-Christophe Dubois static const TypeInfo imx6ul_ccm_info = {
876781182e1SJean-Christophe Dubois     .name          = TYPE_IMX6UL_CCM,
877781182e1SJean-Christophe Dubois     .parent        = TYPE_IMX_CCM,
878781182e1SJean-Christophe Dubois     .instance_size = sizeof(IMX6ULCCMState),
879781182e1SJean-Christophe Dubois     .instance_init = imx6ul_ccm_init,
880781182e1SJean-Christophe Dubois     .class_init    = imx6ul_ccm_class_init,
881781182e1SJean-Christophe Dubois };
882781182e1SJean-Christophe Dubois 
883781182e1SJean-Christophe Dubois static void imx6ul_ccm_register_types(void)
884781182e1SJean-Christophe Dubois {
885781182e1SJean-Christophe Dubois     type_register_static(&imx6ul_ccm_info);
886781182e1SJean-Christophe Dubois }
887781182e1SJean-Christophe Dubois 
888781182e1SJean-Christophe Dubois type_init(imx6ul_ccm_register_types)
889