xref: /openbmc/qemu/hw/misc/imx31_ccm.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
1cb54d868SJean-Christophe Dubois /*
2cb54d868SJean-Christophe Dubois  * IMX31 Clock Control Module
3cb54d868SJean-Christophe Dubois  *
4cb54d868SJean-Christophe Dubois  * Copyright (C) 2012 NICTA
5cb54d868SJean-Christophe Dubois  * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
6cb54d868SJean-Christophe Dubois  *
7cb54d868SJean-Christophe Dubois  * This work is licensed under the terms of the GNU GPL, version 2 or later.
8cb54d868SJean-Christophe Dubois  * See the COPYING file in the top-level directory.
9cb54d868SJean-Christophe Dubois  *
10cb54d868SJean-Christophe Dubois  * To get the timer frequencies right, we need to emulate at least part of
11cb54d868SJean-Christophe Dubois  * the i.MX31 CCM.
12cb54d868SJean-Christophe Dubois  */
13cb54d868SJean-Christophe Dubois 
148ef94f0bSPeter Maydell #include "qemu/osdep.h"
15cb54d868SJean-Christophe Dubois #include "hw/misc/imx31_ccm.h"
16d6454270SMarkus Armbruster #include "migration/vmstate.h"
1703dd024fSPaolo Bonzini #include "qemu/log.h"
180b8fa32fSMarkus Armbruster #include "qemu/module.h"
19cb54d868SJean-Christophe Dubois 
20cb54d868SJean-Christophe Dubois #define CKIH_FREQ 26000000 /* 26MHz crystal input */
21cb54d868SJean-Christophe Dubois 
22cb54d868SJean-Christophe Dubois #ifndef DEBUG_IMX31_CCM
23cb54d868SJean-Christophe Dubois #define DEBUG_IMX31_CCM 0
24cb54d868SJean-Christophe Dubois #endif
25cb54d868SJean-Christophe Dubois 
26cb54d868SJean-Christophe Dubois #define DPRINTF(fmt, args...) \
27cb54d868SJean-Christophe Dubois     do { \
28cb54d868SJean-Christophe Dubois         if (DEBUG_IMX31_CCM) { \
29cb54d868SJean-Christophe Dubois             fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX31_CCM, \
30cb54d868SJean-Christophe Dubois                                              __func__, ##args); \
31cb54d868SJean-Christophe Dubois         } \
32cb54d868SJean-Christophe Dubois     } while (0)
33cb54d868SJean-Christophe Dubois 
imx31_ccm_reg_name(uint32_t reg)34d675765aSPeter Maydell static const char *imx31_ccm_reg_name(uint32_t reg)
35cb54d868SJean-Christophe Dubois {
36fea01f96SJean-Christophe DUBOIS     static char unknown[20];
37fea01f96SJean-Christophe DUBOIS 
38cb54d868SJean-Christophe Dubois     switch (reg) {
39fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_CCMR_REG:
40cb54d868SJean-Christophe Dubois         return "CCMR";
41fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_PDR0_REG:
42cb54d868SJean-Christophe Dubois         return "PDR0";
43fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_PDR1_REG:
44cb54d868SJean-Christophe Dubois         return "PDR1";
45fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_RCSR_REG:
46cb54d868SJean-Christophe Dubois         return "RCSR";
47fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_MPCTL_REG:
48cb54d868SJean-Christophe Dubois         return "MPCTL";
49fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_UPCTL_REG:
50cb54d868SJean-Christophe Dubois         return "UPCTL";
51fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_SPCTL_REG:
52cb54d868SJean-Christophe Dubois         return "SPCTL";
53fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_COSR_REG:
54cb54d868SJean-Christophe Dubois         return "COSR";
55fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_CGR0_REG:
56cb54d868SJean-Christophe Dubois         return "CGR0";
57fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_CGR1_REG:
58cb54d868SJean-Christophe Dubois         return "CGR1";
59fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_CGR2_REG:
60cb54d868SJean-Christophe Dubois         return "CGR2";
61fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_WIMR_REG:
62cb54d868SJean-Christophe Dubois         return "WIMR";
63fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_LDC_REG:
64cb54d868SJean-Christophe Dubois         return "LDC";
65fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_DCVR0_REG:
66cb54d868SJean-Christophe Dubois         return "DCVR0";
67fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_DCVR1_REG:
68cb54d868SJean-Christophe Dubois         return "DCVR1";
69fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_DCVR2_REG:
70cb54d868SJean-Christophe Dubois         return "DCVR2";
71fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_DCVR3_REG:
72cb54d868SJean-Christophe Dubois         return "DCVR3";
73fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_LTR0_REG:
74cb54d868SJean-Christophe Dubois         return "LTR0";
75fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_LTR1_REG:
76cb54d868SJean-Christophe Dubois         return "LTR1";
77fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_LTR2_REG:
78cb54d868SJean-Christophe Dubois         return "LTR2";
79fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_LTR3_REG:
80cb54d868SJean-Christophe Dubois         return "LTR3";
81fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_LTBR0_REG:
82cb54d868SJean-Christophe Dubois         return "LTBR0";
83fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_LTBR1_REG:
84cb54d868SJean-Christophe Dubois         return "LTBR1";
85fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_PMCR0_REG:
86cb54d868SJean-Christophe Dubois         return "PMCR0";
87fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_PMCR1_REG:
88cb54d868SJean-Christophe Dubois         return "PMCR1";
89fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_PDR2_REG:
90cb54d868SJean-Christophe Dubois         return "PDR2";
91cb54d868SJean-Christophe Dubois     default:
92ca4af17cSPhilippe Mathieu-Daudé         snprintf(unknown, sizeof(unknown), "[%u ?]", reg);
93fea01f96SJean-Christophe DUBOIS         return unknown;
94cb54d868SJean-Christophe Dubois     }
95cb54d868SJean-Christophe Dubois }
96cb54d868SJean-Christophe Dubois 
97cb54d868SJean-Christophe Dubois static const VMStateDescription vmstate_imx31_ccm = {
98cb54d868SJean-Christophe Dubois     .name = TYPE_IMX31_CCM,
99fea01f96SJean-Christophe DUBOIS     .version_id = 2,
100fea01f96SJean-Christophe DUBOIS     .minimum_version_id = 2,
101e4ea952fSRichard Henderson     .fields = (const VMStateField[]) {
102fea01f96SJean-Christophe DUBOIS         VMSTATE_UINT32_ARRAY(reg, IMX31CCMState, IMX31_CCM_MAX_REG),
103cb54d868SJean-Christophe Dubois         VMSTATE_END_OF_LIST()
104cb54d868SJean-Christophe Dubois     },
105cb54d868SJean-Christophe Dubois };
106cb54d868SJean-Christophe Dubois 
imx31_ccm_get_pll_ref_clk(IMXCCMState * dev)107cb54d868SJean-Christophe Dubois static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
108cb54d868SJean-Christophe Dubois {
109cb54d868SJean-Christophe Dubois     uint32_t freq = 0;
110cb54d868SJean-Christophe Dubois     IMX31CCMState *s = IMX31_CCM(dev);
111cb54d868SJean-Christophe Dubois 
112fea01f96SJean-Christophe DUBOIS     if ((s->reg[IMX31_CCM_CCMR_REG] & CCMR_PRCS) == 2) {
113fea01f96SJean-Christophe DUBOIS         if (s->reg[IMX31_CCM_CCMR_REG] & CCMR_FPME) {
114cb54d868SJean-Christophe Dubois             freq = CKIL_FREQ;
115fea01f96SJean-Christophe DUBOIS             if (s->reg[IMX31_CCM_CCMR_REG] & CCMR_FPMF) {
116cb54d868SJean-Christophe Dubois                 freq *= 1024;
117cb54d868SJean-Christophe Dubois             }
118cb54d868SJean-Christophe Dubois         }
119cb54d868SJean-Christophe Dubois     } else {
120cb54d868SJean-Christophe Dubois         freq = CKIH_FREQ;
121cb54d868SJean-Christophe Dubois     }
122cb54d868SJean-Christophe Dubois 
123a88ae037SAlex Chen     DPRINTF("freq = %u\n", freq);
124cb54d868SJean-Christophe Dubois 
125cb54d868SJean-Christophe Dubois     return freq;
126cb54d868SJean-Christophe Dubois }
127cb54d868SJean-Christophe Dubois 
imx31_ccm_get_mpll_clk(IMXCCMState * dev)128cb54d868SJean-Christophe Dubois static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
129cb54d868SJean-Christophe Dubois {
130cb54d868SJean-Christophe Dubois     uint32_t freq;
131cb54d868SJean-Christophe Dubois     IMX31CCMState *s = IMX31_CCM(dev);
132cb54d868SJean-Christophe Dubois 
133fea01f96SJean-Christophe DUBOIS     freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
134fea01f96SJean-Christophe DUBOIS                             imx31_ccm_get_pll_ref_clk(dev));
135cb54d868SJean-Christophe Dubois 
136a88ae037SAlex Chen     DPRINTF("freq = %u\n", freq);
137cb54d868SJean-Christophe Dubois 
138cb54d868SJean-Christophe Dubois     return freq;
139cb54d868SJean-Christophe Dubois }
140cb54d868SJean-Christophe Dubois 
imx31_ccm_get_mcu_main_clk(IMXCCMState * dev)141cb54d868SJean-Christophe Dubois static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
142cb54d868SJean-Christophe Dubois {
143cb54d868SJean-Christophe Dubois     uint32_t freq;
144cb54d868SJean-Christophe Dubois     IMX31CCMState *s = IMX31_CCM(dev);
145cb54d868SJean-Christophe Dubois 
146fea01f96SJean-Christophe DUBOIS     if ((s->reg[IMX31_CCM_CCMR_REG] & CCMR_MDS) ||
147fea01f96SJean-Christophe DUBOIS         !(s->reg[IMX31_CCM_CCMR_REG] & CCMR_MPE)) {
148cb54d868SJean-Christophe Dubois         freq = imx31_ccm_get_pll_ref_clk(dev);
149cb54d868SJean-Christophe Dubois     } else {
150cb54d868SJean-Christophe Dubois         freq = imx31_ccm_get_mpll_clk(dev);
151cb54d868SJean-Christophe Dubois     }
152cb54d868SJean-Christophe Dubois 
153a88ae037SAlex Chen     DPRINTF("freq = %u\n", freq);
154cb54d868SJean-Christophe Dubois 
155cb54d868SJean-Christophe Dubois     return freq;
156cb54d868SJean-Christophe Dubois }
157cb54d868SJean-Christophe Dubois 
imx31_ccm_get_hclk_clk(IMXCCMState * dev)158cb54d868SJean-Christophe Dubois static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
159cb54d868SJean-Christophe Dubois {
160cb54d868SJean-Christophe Dubois     uint32_t freq;
161cb54d868SJean-Christophe Dubois     IMX31CCMState *s = IMX31_CCM(dev);
162cb54d868SJean-Christophe Dubois 
163fea01f96SJean-Christophe DUBOIS     freq = imx31_ccm_get_mcu_main_clk(dev)
164fea01f96SJean-Christophe DUBOIS            / (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
165cb54d868SJean-Christophe Dubois 
166a88ae037SAlex Chen     DPRINTF("freq = %u\n", freq);
167cb54d868SJean-Christophe Dubois 
168cb54d868SJean-Christophe Dubois     return freq;
169cb54d868SJean-Christophe Dubois }
170cb54d868SJean-Christophe Dubois 
imx31_ccm_get_ipg_clk(IMXCCMState * dev)171cb54d868SJean-Christophe Dubois static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
172cb54d868SJean-Christophe Dubois {
173cb54d868SJean-Christophe Dubois     uint32_t freq;
174cb54d868SJean-Christophe Dubois     IMX31CCMState *s = IMX31_CCM(dev);
175cb54d868SJean-Christophe Dubois 
176fea01f96SJean-Christophe DUBOIS     freq = imx31_ccm_get_hclk_clk(dev)
177fea01f96SJean-Christophe DUBOIS            / (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
178cb54d868SJean-Christophe Dubois 
179a88ae037SAlex Chen     DPRINTF("freq = %u\n", freq);
180cb54d868SJean-Christophe Dubois 
181cb54d868SJean-Christophe Dubois     return freq;
182cb54d868SJean-Christophe Dubois }
183cb54d868SJean-Christophe Dubois 
imx31_ccm_get_clock_frequency(IMXCCMState * dev,IMXClk clock)184cb54d868SJean-Christophe Dubois static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
185cb54d868SJean-Christophe Dubois {
186cb54d868SJean-Christophe Dubois     uint32_t freq = 0;
187cb54d868SJean-Christophe Dubois 
188cb54d868SJean-Christophe Dubois     switch (clock) {
189c91a5883SJean-Christophe Dubois     case CLK_NONE:
190cb54d868SJean-Christophe Dubois         break;
191cb54d868SJean-Christophe Dubois     case CLK_IPG:
192d552f675SJean-Christophe Dubois     case CLK_IPG_HIGH:
193cb54d868SJean-Christophe Dubois         freq = imx31_ccm_get_ipg_clk(dev);
194cb54d868SJean-Christophe Dubois         break;
195cb54d868SJean-Christophe Dubois     case CLK_32k:
196cb54d868SJean-Christophe Dubois         freq = CKIL_FREQ;
197cb54d868SJean-Christophe Dubois         break;
198cb54d868SJean-Christophe Dubois     default:
199cb54d868SJean-Christophe Dubois         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
200cb54d868SJean-Christophe Dubois                       TYPE_IMX31_CCM, __func__, clock);
201cb54d868SJean-Christophe Dubois         break;
202cb54d868SJean-Christophe Dubois     }
203cb54d868SJean-Christophe Dubois 
204a88ae037SAlex Chen     DPRINTF("Clock = %d) = %u\n", clock, freq);
205cb54d868SJean-Christophe Dubois 
206cb54d868SJean-Christophe Dubois     return freq;
207cb54d868SJean-Christophe Dubois }
208cb54d868SJean-Christophe Dubois 
imx31_ccm_reset(DeviceState * dev)209cb54d868SJean-Christophe Dubois static void imx31_ccm_reset(DeviceState *dev)
210cb54d868SJean-Christophe Dubois {
211cb54d868SJean-Christophe Dubois     IMX31CCMState *s = IMX31_CCM(dev);
212cb54d868SJean-Christophe Dubois 
213cb54d868SJean-Christophe Dubois     DPRINTF("()\n");
214cb54d868SJean-Christophe Dubois 
215fea01f96SJean-Christophe DUBOIS     memset(s->reg, 0, sizeof(uint32_t) * IMX31_CCM_MAX_REG);
216fea01f96SJean-Christophe DUBOIS 
217fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_CCMR_REG]   = 0x074b0b7d;
218fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_PDR0_REG]   = 0xff870b48;
219fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_PDR1_REG]   = 0x49fcfe7f;
220fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_RCSR_REG]   = 0x007f0000;
221fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_MPCTL_REG]  = 0x04001800;
222fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_UPCTL_REG]  = 0x04051c03;
223fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_SPCTL_REG]  = 0x04043001;
224fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_COSR_REG]   = 0x00000280;
225fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_CGR0_REG]   = 0xffffffff;
226fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_CGR1_REG]   = 0xffffffff;
227fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_CGR2_REG]   = 0xffffffff;
228fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_WIMR_REG]   = 0xffffffff;
229fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_LTR1_REG]   = 0x00004040;
230fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_PMCR0_REG]  = 0x80209828;
231fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_PMCR1_REG]  = 0x00aa0000;
232fea01f96SJean-Christophe DUBOIS     s->reg[IMX31_CCM_PDR2_REG]   = 0x00000285;
233cb54d868SJean-Christophe Dubois }
234cb54d868SJean-Christophe Dubois 
imx31_ccm_read(void * opaque,hwaddr offset,unsigned size)235cb54d868SJean-Christophe Dubois static uint64_t imx31_ccm_read(void *opaque, hwaddr offset, unsigned size)
236cb54d868SJean-Christophe Dubois {
2373a87d009SPeter Maydell     uint32_t value = 0;
238cb54d868SJean-Christophe Dubois     IMX31CCMState *s = (IMX31CCMState *)opaque;
239cb54d868SJean-Christophe Dubois 
240fea01f96SJean-Christophe DUBOIS     if ((offset >> 2) < IMX31_CCM_MAX_REG) {
241fea01f96SJean-Christophe DUBOIS         value = s->reg[offset >> 2];
242fea01f96SJean-Christophe DUBOIS     } else {
243cb54d868SJean-Christophe Dubois         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
244cb54d868SJean-Christophe Dubois                       HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset);
245cb54d868SJean-Christophe Dubois     }
246cb54d868SJean-Christophe Dubois 
247cb54d868SJean-Christophe Dubois     DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2),
248cb54d868SJean-Christophe Dubois             value);
249cb54d868SJean-Christophe Dubois 
250cb54d868SJean-Christophe Dubois     return (uint64_t)value;
251cb54d868SJean-Christophe Dubois }
252cb54d868SJean-Christophe Dubois 
imx31_ccm_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)253cb54d868SJean-Christophe Dubois static void imx31_ccm_write(void *opaque, hwaddr offset, uint64_t value,
254cb54d868SJean-Christophe Dubois                             unsigned size)
255cb54d868SJean-Christophe Dubois {
256cb54d868SJean-Christophe Dubois     IMX31CCMState *s = (IMX31CCMState *)opaque;
257cb54d868SJean-Christophe Dubois 
258cb54d868SJean-Christophe Dubois     DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2),
259cb54d868SJean-Christophe Dubois             (uint32_t)value);
260cb54d868SJean-Christophe Dubois 
261cb54d868SJean-Christophe Dubois     switch (offset >> 2) {
262fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_CCMR_REG:
263fea01f96SJean-Christophe DUBOIS         s->reg[IMX31_CCM_CCMR_REG] = CCMR_FPMF | (value & 0x3b6fdfff);
264cb54d868SJean-Christophe Dubois         break;
265fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_PDR0_REG:
266fea01f96SJean-Christophe DUBOIS         s->reg[IMX31_CCM_PDR0_REG] = value & 0xff9f3fff;
267cb54d868SJean-Christophe Dubois         break;
268fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_PDR1_REG:
269fea01f96SJean-Christophe DUBOIS         s->reg[IMX31_CCM_PDR1_REG] = value;
270cb54d868SJean-Christophe Dubois         break;
271fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_MPCTL_REG:
272fea01f96SJean-Christophe DUBOIS         s->reg[IMX31_CCM_MPCTL_REG] = value & 0xbfff3fff;
273cb54d868SJean-Christophe Dubois         break;
274fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_SPCTL_REG:
275fea01f96SJean-Christophe DUBOIS         s->reg[IMX31_CCM_SPCTL_REG] = value & 0xbfff3fff;
276cb54d868SJean-Christophe Dubois         break;
277fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_CGR0_REG:
278fea01f96SJean-Christophe DUBOIS         s->reg[IMX31_CCM_CGR0_REG] = value;
279cb54d868SJean-Christophe Dubois         break;
280fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_CGR1_REG:
281fea01f96SJean-Christophe DUBOIS         s->reg[IMX31_CCM_CGR1_REG] = value;
282cb54d868SJean-Christophe Dubois         break;
283fea01f96SJean-Christophe DUBOIS     case IMX31_CCM_CGR2_REG:
284fea01f96SJean-Christophe DUBOIS         s->reg[IMX31_CCM_CGR2_REG] = value;
285cb54d868SJean-Christophe Dubois         break;
286cb54d868SJean-Christophe Dubois     default:
287cb54d868SJean-Christophe Dubois         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
288cb54d868SJean-Christophe Dubois                       HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset);
289cb54d868SJean-Christophe Dubois         break;
290cb54d868SJean-Christophe Dubois     }
291cb54d868SJean-Christophe Dubois }
292cb54d868SJean-Christophe Dubois 
293cb54d868SJean-Christophe Dubois static const struct MemoryRegionOps imx31_ccm_ops = {
294cb54d868SJean-Christophe Dubois     .read = imx31_ccm_read,
295cb54d868SJean-Christophe Dubois     .write = imx31_ccm_write,
296cb54d868SJean-Christophe Dubois     .endianness = DEVICE_NATIVE_ENDIAN,
297cb54d868SJean-Christophe Dubois     .valid = {
298cb54d868SJean-Christophe Dubois         /*
299cb54d868SJean-Christophe Dubois          * Our device would not work correctly if the guest was doing
300cb54d868SJean-Christophe Dubois          * unaligned access. This might not be a limitation on the real
301cb54d868SJean-Christophe Dubois          * device but in practice there is no reason for a guest to access
302cb54d868SJean-Christophe Dubois          * this device unaligned.
303cb54d868SJean-Christophe Dubois          */
304cb54d868SJean-Christophe Dubois         .min_access_size = 4,
305cb54d868SJean-Christophe Dubois         .max_access_size = 4,
306cb54d868SJean-Christophe Dubois         .unaligned = false,
307cb54d868SJean-Christophe Dubois     },
308cb54d868SJean-Christophe Dubois 
309cb54d868SJean-Christophe Dubois };
310cb54d868SJean-Christophe Dubois 
imx31_ccm_init(Object * obj)311cb54d868SJean-Christophe Dubois static void imx31_ccm_init(Object *obj)
312cb54d868SJean-Christophe Dubois {
313cb54d868SJean-Christophe Dubois     DeviceState *dev = DEVICE(obj);
314cb54d868SJean-Christophe Dubois     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
315cb54d868SJean-Christophe Dubois     IMX31CCMState *s = IMX31_CCM(obj);
316cb54d868SJean-Christophe Dubois 
317cb54d868SJean-Christophe Dubois     memory_region_init_io(&s->iomem, OBJECT(dev), &imx31_ccm_ops, s,
318cb54d868SJean-Christophe Dubois                           TYPE_IMX31_CCM, 0x1000);
319cb54d868SJean-Christophe Dubois     sysbus_init_mmio(sd, &s->iomem);
320cb54d868SJean-Christophe Dubois }
321cb54d868SJean-Christophe Dubois 
imx31_ccm_class_init(ObjectClass * klass,void * data)322cb54d868SJean-Christophe Dubois static void imx31_ccm_class_init(ObjectClass *klass, void *data)
323cb54d868SJean-Christophe Dubois {
324cb54d868SJean-Christophe Dubois     DeviceClass *dc  = DEVICE_CLASS(klass);
325cb54d868SJean-Christophe Dubois     IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
326cb54d868SJean-Christophe Dubois 
327*e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, imx31_ccm_reset);
328cb54d868SJean-Christophe Dubois     dc->vmsd  = &vmstate_imx31_ccm;
329cb54d868SJean-Christophe Dubois     dc->desc  = "i.MX31 Clock Control Module";
330cb54d868SJean-Christophe Dubois 
331cb54d868SJean-Christophe Dubois     ccm->get_clock_frequency = imx31_ccm_get_clock_frequency;
332cb54d868SJean-Christophe Dubois }
333cb54d868SJean-Christophe Dubois 
334cb54d868SJean-Christophe Dubois static const TypeInfo imx31_ccm_info = {
335cb54d868SJean-Christophe Dubois     .name          = TYPE_IMX31_CCM,
336cb54d868SJean-Christophe Dubois     .parent        = TYPE_IMX_CCM,
337cb54d868SJean-Christophe Dubois     .instance_size = sizeof(IMX31CCMState),
338cb54d868SJean-Christophe Dubois     .instance_init = imx31_ccm_init,
339cb54d868SJean-Christophe Dubois     .class_init    = imx31_ccm_class_init,
340cb54d868SJean-Christophe Dubois };
341cb54d868SJean-Christophe Dubois 
imx31_ccm_register_types(void)342cb54d868SJean-Christophe Dubois static void imx31_ccm_register_types(void)
343cb54d868SJean-Christophe Dubois {
344cb54d868SJean-Christophe Dubois     type_register_static(&imx31_ccm_info);
345cb54d868SJean-Christophe Dubois }
346cb54d868SJean-Christophe Dubois 
347cb54d868SJean-Christophe Dubois type_init(imx31_ccm_register_types)
348