• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisión41ef8d44465c3a953d8580f5895c2e1ba6bf2d08 (tree)
Tiempo2021-05-27 14:10:38
AutorYoshinori Sato <ysato@user...>
CommiterYoshinori Sato

Log Message

hw/rx: Add RX62N Clock generator

This module generated core and peripheral clock.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

Cambiar Resumen

Diferencia incremental

--- a/hw/rx/meson.build
+++ b/hw/rx/meson.build
@@ -1,5 +1,5 @@
11 rx_ss = ss.source_set()
22 rx_ss.add(when: 'CONFIG_RX_GDBSIM', if_true: files('rx-gdbsim.c'))
3-rx_ss.add(when: 'CONFIG_RX62N_MCU', if_true: files('rx62n.c'))
3+rx_ss.add(when: 'CONFIG_RX62N_MCU', if_true: files('rx62n.c', 'rx62n-cpg.c'))
44
55 hw_arch += {'rx': rx_ss}
--- /dev/null
+++ b/hw/rx/rx62n-cpg.c
@@ -0,0 +1,344 @@
1+/*
2+ * RX62N Clock Generation Circuit
3+ *
4+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
5+ * (Rev.1.40 R01UH0033EJ0140)
6+ *
7+ * Copyright (c) 2020 Yoshinori Sato
8+ *
9+ * This program is free software; you can redistribute it and/or modify it
10+ * under the terms and conditions of the GNU General Public License,
11+ * version 2 or later, as published by the Free Software Foundation.
12+ *
13+ * This program is distributed in the hope it will be useful, but WITHOUT
14+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16+ * more details.
17+ *
18+ * You should have received a copy of the GNU General Public License along with
19+ * this program. If not, see <http://www.gnu.org/licenses/>.
20+ */
21+
22+#include "qemu/osdep.h"
23+#include "qapi/error.h"
24+#include "qemu/log.h"
25+#include "hw/hw.h"
26+#include "hw/rx/rx62n-cpg.h"
27+#include "hw/sysbus.h"
28+#include "hw/qdev-properties.h"
29+#include "hw/registerfields.h"
30+#include "hw/qdev-properties.h"
31+#include "hw/clock.h"
32+#include "migration/vmstate.h"
33+
34+#define RX62N_XTAL_MIN_HZ (8 * 1000 * 1000)
35+#define RX62N_XTAL_MAX_HZ (14 * 1000 * 1000)
36+
37+REG32(MSTPCRA, 0)
38+REG32(MSTPCRB, 4)
39+REG32(MSTPCRC, 8)
40+REG32(SCKCR, 16)
41+ FIELD(SCKCR, PCK, 8, 3)
42+ FIELD(SCKCR, BCK, 16, 3)
43+ FIELD(SCKCR, PSTOP, 22, 2)
44+ FIELD(SCKCR, ICK, 24, 3)
45+REG8(BCKCR, 32)
46+ FIELD(BCKCR, BCLKDIV, 0, 1)
47+REG16(OSTDCR, 48)
48+ FIELD(OSTDCR, OSTDF, 6, 1)
49+ FIELD(OSTDCR, OSTDE, 7, 1)
50+
51+static const int access_size[] = {4, 4, 1, 2};
52+
53+typedef struct {
54+ const char *name;
55+ int devnum;
56+ int reg;
57+ int offset;
58+ int parentck;
59+} dev_clock_t;
60+
61+enum {
62+ parent_ick, parent_bck, parent_pck,
63+};
64+
65+static const dev_clock_t dev_clock_list[] = {
66+ { .name = "pck_tmr8-1",
67+ .devnum = CK_TMR8_1, .reg = 0, .offset = 4, .parentck = parent_pck, },
68+ { .name = "pck_tmr8-0",
69+ .devnum = CK_TMR8_0, .reg = 0, .offset = 5, .parentck = parent_pck, },
70+ { .name = "pck_mtu-1",
71+ .devnum = CK_MTU_1, .reg = 0, .offset = 8, .parentck = parent_pck, },
72+ { .name = "pck_mtu-0",
73+ .devnum = CK_MTU_0, .reg = 0, .offset = 9, .parentck = parent_pck, },
74+ { .name = "pck_cmt-1",
75+ .devnum = CK_CMT_1, .reg = 0, .offset = 14, .parentck = parent_pck, },
76+ { .name = "pck_cmt-0",
77+ .devnum = CK_CMT_0, .reg = 0, .offset = 15, .parentck = parent_pck, },
78+ { .name = "ick_edmac",
79+ .devnum = CK_EDMAC, .reg = 1, .offset = 15, .parentck = parent_ick, },
80+ { .name = "pck_sci-6",
81+ .devnum = CK_SCI6, .reg = 1, .offset = 25, .parentck = parent_pck, },
82+ { .name = "pck_sci-5",
83+ .devnum = CK_SCI5, .reg = 1, .offset = 26, .parentck = parent_pck, },
84+ { .name = "pck_sci-3",
85+ .devnum = CK_SCI3, .reg = 1, .offset = 28, .parentck = parent_pck, },
86+ { .name = "pck_sci-2",
87+ .devnum = CK_SCI2, .reg = 1, .offset = 29, .parentck = parent_pck, },
88+ { .name = "pck_sci-1",
89+ .devnum = CK_SCI1, .reg = 1, .offset = 30, .parentck = parent_pck, },
90+ { .name = "pck_sci-0",
91+ .devnum = CK_SCI0, .reg = 1, .offset = 31, .parentck = parent_pck, },
92+ { },
93+};
94+
95+static void set_clock_in(RX62NCPGState *cpg, const dev_clock_t *ck)
96+{
97+ Clock *out;
98+ uint64_t period;
99+
100+ out = qdev_get_clock_out(DEVICE(cpg), ck->name);
101+ g_assert(out);
102+ period = 0;
103+ if (extract32(cpg->mstpcr[ck->reg], ck->offset, 1) == 0) {
104+ switch (ck->parentck) {
105+ case parent_ick:
106+ period = clock_get(cpg->clk_ick);
107+ break;
108+ case parent_pck:
109+ period = clock_get(cpg->clk_pck);
110+ break;
111+ }
112+ }
113+ if (clock_get(out) != period) {
114+ clock_update(out, period);
115+ }
116+}
117+
118+#define update_ck(ckname) \
119+ if (cpg->ckname != ckname) { \
120+ cpg->ckname = ckname; \
121+ ckname = 8 / (1 << ckname); \
122+ clock_update_hz(cpg->clk_ ## ckname, \
123+ cpg->xtal_freq_hz * ckname); \
124+ }
125+
126+#define validate_setting(ckname) \
127+ if (ick > ckname) { \
128+ qemu_log_mask(LOG_GUEST_ERROR, \
129+ "rx62n-cpg: Invalid " #ckname " setting." \
130+ " (ick=%d " #ckname "=%d)\n", ick, ckname); \
131+ cpg->ckname = ckname = ick; \
132+ }
133+
134+static void update_divrate(RX62NCPGState *cpg)
135+{
136+ int ick = FIELD_EX32(cpg->sckcr, SCKCR, ICK);
137+ int bck = FIELD_EX32(cpg->sckcr, SCKCR, BCK);
138+ int pck = FIELD_EX32(cpg->sckcr, SCKCR, PCK);
139+ const dev_clock_t *p = dev_clock_list;
140+ validate_setting(pck);
141+ validate_setting(bck);
142+ update_ck(ick);
143+ update_ck(bck);
144+ update_ck(pck);
145+ while (p->name) {
146+ set_clock_in(cpg, p);
147+ p++;
148+ }
149+}
150+
151+static const dev_clock_t *find_clock_list(int crno, int bit)
152+{
153+ const dev_clock_t *ret = dev_clock_list;
154+ while (ret->name) {
155+ if (ret->reg == crno && ret->offset == bit) {
156+ return ret;
157+ }
158+ ret++;
159+ }
160+ return NULL;
161+}
162+
163+static void update_mstpcr(RX62NCPGState *cpg, int crno, uint32_t diff)
164+{
165+ int bit = 0;
166+ const dev_clock_t *p;
167+
168+ while (diff) {
169+ if (diff & 1) {
170+ p = find_clock_list(crno, bit);
171+ if (p) {
172+ set_clock_in(cpg, p);
173+ } else {
174+ qemu_log_mask(LOG_UNIMP, "rx62n-cpg: MSTPCR%c "
175+ " bit %d is not implement.\n", 'A' + crno, bit);
176+ }
177+ }
178+ bit++;
179+ diff >>= 1;
180+ }
181+}
182+
183+static uint64_t cpg_read(void *opaque, hwaddr addr, unsigned size)
184+{
185+ RX62NCPGState *cpg = RX62NCPG(opaque);
186+
187+ if (access_size[addr >> 4] != size) {
188+ qemu_log_mask(LOG_GUEST_ERROR, "rx62n-cpg: Register 0x%"
189+ HWADDR_PRIX " Invalid access size.\n", addr);
190+ return UINT64_MAX;
191+ }
192+ switch (addr) {
193+ case A_MSTPCRA:
194+ return cpg->mstpcr[0] | 0x473530cf;
195+ case A_MSTPCRB:
196+ return cpg->mstpcr[1] | 0x09407ffe;
197+ case A_MSTPCRC:
198+ return (cpg->mstpcr[2] | 0xffff0000) & 0xffff0003;
199+ case A_SCKCR:
200+ return cpg->sckcr & 0x0fcf0f00;
201+ case A_BCKCR:
202+ return cpg->bckcr & 0x01;
203+ case A_OSTDCR:
204+ /* Main OSC always good */
205+ return cpg->ostdcr & 0x0080;
206+ default:
207+ qemu_log_mask(LOG_GUEST_ERROR, "rx62n-cpg: Register 0x%"
208+ HWADDR_PRIX " Invalid address.\n", addr);
209+ return UINT64_MAX;
210+ }
211+}
212+
213+static void cpg_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
214+{
215+ RX62NCPGState *cpg = RX62NCPG(opaque);
216+ uint32_t old_mstpcr;
217+ int cr_no;
218+ if (access_size[addr >> 4] != size) {
219+ qemu_log_mask(LOG_GUEST_ERROR, "rx62n-cpg: Register 0x%"
220+ HWADDR_PRIX " Invalid access size.\n", addr);
221+ return;
222+ }
223+ switch (addr) {
224+ case A_MSTPCRA:
225+ case A_MSTPCRB:
226+ case A_MSTPCRC:
227+ cr_no = (addr & 0x0f) >> 2;
228+ old_mstpcr = cpg->mstpcr[cr_no];
229+ old_mstpcr ^= val;
230+ cpg->mstpcr[cr_no] = val;
231+ update_mstpcr(cpg, cr_no, old_mstpcr);
232+ break;
233+ case A_SCKCR:
234+ cpg->sckcr = val;
235+ update_divrate(cpg);
236+ break;
237+ case A_BCKCR:
238+ cpg->bckcr = val;
239+ break;
240+ case A_OSTDCR:
241+ if (extract16(val, 8, 8) == OSTDCR_KEY) {
242+ cpg->ostdcr = val;
243+ } else {
244+ qemu_log_mask(LOG_GUEST_ERROR, "rx62n-cpg: Register 0x%"
245+ HWADDR_PRIX " Invalid key value.\n", addr);
246+ }
247+ break;
248+ default:
249+ qemu_log_mask(LOG_GUEST_ERROR, "rx62n-cpg: Register 0x%"
250+ HWADDR_PRIX " Invalid address.\n", addr);
251+ }
252+}
253+
254+static const MemoryRegionOps cpg_ops = {
255+ .write = cpg_write,
256+ .read = cpg_read,
257+ .endianness = DEVICE_NATIVE_ENDIAN,
258+ .impl = {
259+ .min_access_size = 1,
260+ .max_access_size = 4,
261+ },
262+};
263+
264+static const ClockPortInitArray rx62n_cpg_clocks = {
265+ QDEV_CLOCK_OUT(RX62NCPGState, clk_ick),
266+ QDEV_CLOCK_OUT(RX62NCPGState, clk_bck),
267+ QDEV_CLOCK_OUT(RX62NCPGState, clk_pck),
268+ QDEV_CLOCK_END
269+};
270+
271+static void cpg_realize(DeviceState *dev, Error **errp)
272+{
273+ RX62NCPGState *cpg = RX62NCPG(dev);
274+ const dev_clock_t *p = dev_clock_list;
275+
276+ if (cpg->xtal_freq_hz == 0) {
277+ error_setg(errp, "\"xtal-frequency-hz\" property must be provided.");
278+ return;
279+ }
280+ /* XTAL range: 8-14 MHz */
281+ if (cpg->xtal_freq_hz < RX62N_XTAL_MIN_HZ ||
282+ cpg->xtal_freq_hz > RX62N_XTAL_MAX_HZ) {
283+ error_setg(errp, "\"xtal-frequency-hz\" property in incorrect range.");
284+ return;
285+ }
286+
287+ cpg->sckcr = FIELD_DP32(cpg->sckcr, SCKCR, ICK, 2);
288+ cpg->sckcr = FIELD_DP32(cpg->sckcr, SCKCR, BCK, 2);
289+ cpg->sckcr = FIELD_DP32(cpg->sckcr, SCKCR, PCK, 2);
290+ cpg->ostdcr = FIELD_DP8(cpg->ostdcr, OSTDCR, OSTDE, 1);
291+ cpg->mstpcr[0] = 0x47ffffff;
292+ cpg->mstpcr[1] = 0xffffffff;
293+ cpg->mstpcr[2] = 0xffff0000;
294+
295+ /* set initial state */
296+ while (p->name) {
297+ set_clock_in(cpg, p);
298+ p++;
299+ }
300+ update_divrate(cpg);
301+}
302+
303+static void rx62n_cpg_init(Object *obj)
304+{
305+ RX62NCPGState *cpg = RX62NCPG(obj);
306+ const dev_clock_t *p = dev_clock_list;
307+ qdev_init_clocks(DEVICE(obj), rx62n_cpg_clocks);
308+ /* connect parent clock */
309+ while (p->name) {
310+ cpg->dev_clocks[p->devnum] = qdev_init_clock_out(DEVICE(obj),
311+ p->name);
312+ p++;
313+ }
314+
315+ memory_region_init_io(&cpg->memory, OBJECT(cpg), &cpg_ops,
316+ cpg, "rx62n-cpg", 0x40);
317+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &cpg->memory);
318+}
319+
320+static Property rx62n_cpg_properties[] = {
321+ DEFINE_PROP_UINT32("xtal-frequency-hz", RX62NCPGState, xtal_freq_hz, 0),
322+ DEFINE_PROP_END_OF_LIST(),
323+};
324+
325+static void rx62n_cpg_class_init(ObjectClass *klass, void *data)
326+{
327+ DeviceClass *dc = DEVICE_CLASS(klass);
328+
329+ dc->realize = cpg_realize;
330+ device_class_set_props(dc, rx62n_cpg_properties);
331+}
332+
333+static const TypeInfo rx62n_cpg_info[] = {
334+ {
335+ .name = TYPE_RX62N_CPG,
336+ .parent = TYPE_SYS_BUS_DEVICE,
337+ .instance_size = sizeof(RX62NCPGState),
338+ .instance_init = rx62n_cpg_init,
339+ .class_init = rx62n_cpg_class_init,
340+ .class_size = sizeof(RX62NCPGClass),
341+ },
342+};
343+
344+DEFINE_TYPES(rx62n_cpg_info)
--- a/hw/rx/rx62n.c
+++ b/hw/rx/rx62n.c
@@ -45,6 +45,7 @@
4545 #define RX62N_TMR_BASE 0x00088200
4646 #define RX62N_CMT_BASE 0x00088000
4747 #define RX62N_SCI_BASE 0x00088240
48+#define RX62N_CPG_BASE 0x00080010
4849
4950 /*
5051 * RX62N Peripheral IRQ
@@ -56,7 +57,6 @@
5657
5758 #define RX62N_XTAL_MIN_HZ (8 * 1000 * 1000)
5859 #define RX62N_XTAL_MAX_HZ (14 * 1000 * 1000)
59-#define RX62N_PCLK_MAX_HZ (50 * 1000 * 1000)
6060
6161 struct RX62NClass {
6262 /*< private >*/
@@ -161,36 +161,45 @@ static void register_tmr(RX62NState *s, int unit)
161161 {
162162 SysBusDevice *tmr;
163163 int i, irqbase;
164+ char ckname[16];
164165
165166 object_initialize_child(OBJECT(s), "tmr[*]",
166167 &s->tmr[unit], TYPE_RENESAS_TMR);
167168 tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
168- qdev_prop_set_uint64(DEVICE(tmr), "input-freq", s->pclk_freq_hz);
169- sysbus_realize(tmr, &error_abort);
170169
171170 irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit;
172171 for (i = 0; i < TMR_NR_IRQ; i++) {
173172 sysbus_connect_irq(tmr, i, s->irq[irqbase + i]);
174173 }
175174 sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10);
175+
176+ qdev_prop_set_uint32(DEVICE(tmr), "unit", unit);
177+ sysbus_realize(tmr, &error_abort);
178+ snprintf(ckname, sizeof(ckname), "pck_tmr8-%d", unit);
179+ qdev_connect_clock_in(DEVICE(tmr), "pck",
180+ qdev_get_clock_out(DEVICE(&s->cpg), ckname));
176181 }
177182
178183 static void register_cmt(RX62NState *s, int unit)
179184 {
180185 SysBusDevice *cmt;
181186 int i, irqbase;
187+ char ckname[16];
182188
183189 object_initialize_child(OBJECT(s), "cmt[*]",
184190 &s->cmt[unit], TYPE_RENESAS_CMT);
185191 cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
186- qdev_prop_set_uint64(DEVICE(cmt), "input-freq", s->pclk_freq_hz);
187- sysbus_realize(cmt, &error_abort);
192+ qdev_prop_set_uint32(DEVICE(cmt), "unit", unit);
188193
189194 irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit;
190195 for (i = 0; i < CMT_NR_IRQ; i++) {
191196 sysbus_connect_irq(cmt, i, s->irq[irqbase + i]);
192197 }
193198 sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10);
199+ sysbus_realize(cmt, &error_abort);
200+ snprintf(ckname, sizeof(ckname), "pck_cmt-%d", unit);
201+ qdev_connect_clock_in(DEVICE(cmt), "pck",
202+ qdev_get_clock_out(DEVICE(&s->cpg), ckname));
194203 }
195204
196205 static void register_sci(RX62NState *s, int unit)
@@ -202,7 +211,6 @@ static void register_sci(RX62NState *s, int unit)
202211 &s->sci[unit], TYPE_RENESAS_SCI);
203212 sci = SYS_BUS_DEVICE(&s->sci[unit]);
204213 qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
205- qdev_prop_set_uint64(DEVICE(sci), "input-freq", s->pclk_freq_hz);
206214 sysbus_realize(sci, &error_abort);
207215
208216 irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit;
@@ -212,6 +220,18 @@ static void register_sci(RX62NState *s, int unit)
212220 sysbus_mmio_map(sci, 0, RX62N_SCI_BASE + unit * 0x08);
213221 }
214222
223+static void register_cpg(RX62NState *s)
224+{
225+ SysBusDevice *cpg;
226+
227+ object_initialize_child(OBJECT(s), "rx62n-cpg", &s->cpg,
228+ TYPE_RX62N_CPG);
229+ cpg = SYS_BUS_DEVICE(&s->cpg);
230+ qdev_prop_set_uint64(DEVICE(cpg), "xtal-frequency-hz", s->xtal_freq_hz);
231+
232+ sysbus_mmio_map(cpg, 0, RX62N_CPG_BASE);
233+}
234+
215235 static void rx62n_realize(DeviceState *dev, Error **errp)
216236 {
217237 RX62NState *s = RX62N_MCU(dev);
@@ -227,11 +247,6 @@ static void rx62n_realize(DeviceState *dev, Error **errp)
227247 error_setg(errp, "\"xtal-frequency-hz\" property in incorrect range.");
228248 return;
229249 }
230- /* Use a 4x fixed multiplier */
231- s->pclk_freq_hz = 4 * s->xtal_freq_hz;
232- /* PCLK range: 8-50 MHz */
233- assert(s->pclk_freq_hz <= RX62N_PCLK_MAX_HZ);
234-
235250 memory_region_init_ram(&s->iram, OBJECT(dev), "iram",
236251 rxc->ram_size, &error_abort);
237252 memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram);
@@ -248,11 +263,13 @@ static void rx62n_realize(DeviceState *dev, Error **errp)
248263
249264 register_icu(s);
250265 s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0);
266+ register_cpg(s);
251267 register_tmr(s, 0);
252268 register_tmr(s, 1);
253269 register_cmt(s, 0);
254270 register_cmt(s, 1);
255271 register_sci(s, 0);
272+ sysbus_realize(SYS_BUS_DEVICE(&s->cpg), &error_abort);
256273 }
257274
258275 static Property rx62n_properties[] = {
--- /dev/null
+++ b/include/hw/rx/rx62n-cpg.h
@@ -0,0 +1,72 @@
1+/*
2+ * RX62N Clock generator circuit
3+ *
4+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
5+ * (Rev.1.40 R01UH0033EJ0140)
6+ *
7+ * Copyright (c) 2020 Yoshinori Sato
8+ *
9+ * This program is free software; you can redistribute it and/or modify it
10+ * under the terms and conditions of the GNU General Public License,
11+ * version 2 or later, as published by the Free Software Foundation.
12+ *
13+ * This program is distributed in the hope it will be useful, but WITHOUT
14+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16+ * more details.
17+ *
18+ * You should have received a copy of the GNU General Public License along with
19+ * this program. If not, see <http://www.gnu.org/licenses/>.
20+ */
21+
22+#ifndef HW_RX_RX62N_CPG_H
23+#define HW_RX_RX62N_CPG_H
24+
25+#include "hw/sysbus.h"
26+#include "hw/qdev-clock.h"
27+
28+#define TYPE_RX62N_CPG "rx62n-cpg"
29+#define RX62NCPG(obj) OBJECT_CHECK(RX62NCPGState, (obj), TYPE_RX62N_CPG)
30+
31+enum {
32+ CK_TMR8_1,
33+ CK_TMR8_0,
34+ CK_MTU_1,
35+ CK_MTU_0,
36+ CK_CMT_1,
37+ CK_CMT_0,
38+ CK_EDMAC,
39+ CK_SCI6,
40+ CK_SCI5,
41+ CK_SCI3,
42+ CK_SCI2,
43+ CK_SCI1,
44+ CK_SCI0,
45+ NUM_SUBCLOCK,
46+};
47+
48+typedef struct RX62NCPGState {
49+ SysBusDevice parent_obj;
50+ uint32_t mstpcr[3];
51+ uint32_t sckcr;
52+ uint8_t bckcr;
53+ uint8_t ostdcr;
54+
55+ int ick;
56+ Clock *clk_ick;
57+ int bck;
58+ Clock *clk_bck;
59+ int pck;
60+ Clock *clk_pck;
61+ Clock *dev_clocks[NUM_SUBCLOCK];
62+ uint32_t xtal_freq_hz;
63+ MemoryRegion memory;
64+} RX62NCPGState;
65+
66+typedef struct RX62NCPGClass {
67+ SysBusDeviceClass parent;
68+} RX62NCPGClass;
69+
70+#define OSTDCR_KEY 0xac
71+
72+#endif
--- a/include/hw/rx/rx62n.h
+++ b/include/hw/rx/rx62n.h
@@ -29,6 +29,7 @@
2929 #include "hw/timer/renesas_tmr.h"
3030 #include "hw/timer/renesas_cmt.h"
3131 #include "hw/char/renesas_sci.h"
32+#include "hw/rx/rx62n-cpg.h"
3233 #include "qemu/units.h"
3334 #include "qom/object.h"
3435
@@ -58,9 +59,9 @@ struct RX62NState {
5859 RTMRState tmr[RX62N_NR_TMR];
5960 RCMTState cmt[RX62N_NR_CMT];
6061 RSCIState sci[RX62N_NR_SCI];
62+ RX62NCPGState cpg;
6163
6264 MemoryRegion *sysmem;
63- bool kernel;
6465
6566 MemoryRegion iram;
6667 MemoryRegion iomem1;
@@ -72,8 +73,7 @@ struct RX62NState {
7273
7374 /* Input Clock (XTAL) frequency */
7475 uint32_t xtal_freq_hz;
75- /* Peripheral Module Clock frequency */
76- uint32_t pclk_freq_hz;
77-};
76+} RX62NState;
77+
7878
7979 #endif