CPG required new hw modules.
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
include/hw/sh4/sh7751-cpg.h | 94 ++++++++
hw/sh4/sh7750.c | 25 ++
hw/sh4/sh7751-cpg.c | 457 ++++++++++++++++++++++++++++++++++++
hw/sh4/meson.build | 1 +
4 files changed, 577 insertions(+)
create mode 100644 include/hw/sh4/sh7751-cpg.h
create mode 100644 hw/sh4/sh7751-cpg.c
diff --git a/include/hw/sh4/sh7751-cpg.h b/include/hw/sh4/sh7751-cpg.h
new file mode 100644
index 0000000000..79f9abe210
--- /dev/null
+++ b/include/hw/sh4/sh7751-cpg.h
@@ -0,0 +1,94 @@
+/*
+ * SH7751(R) Clock generator circuit
+ *
+ * Datasheet: SH7751 Group, SH7751R Group User's Manual: Hardware
+ * (Rev.4.01 R01UH0457EJ0401)
+ *
+ * Copyright (c) 2020 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_SH4_SH7751_CPG_H
+#define HW_SH4_SH7751_CPG_H
+
+#include "hw/sysbus.h"
+#include "hw/qdev-clock.h"
+
+#define TYPE_SH7751_CPG_BASE "sh7751-cpg-base"
+#define SH7751CPGBase(obj) \
+ OBJECT_CHECK(SH7751CPGBaseState, (obj), TYPE_SH7751_CPG_BASE)
+#define TYPE_SH7751_CPG "sh7751-cpg"
+#define SH7751CPG(obj) OBJECT_CHECK(SH7751CPGState, (obj), TYPE_SH7751_CPG)
+#define TYPE_SH7751R_CPG "sh7751r-cpg"
+#define SH7751RCPG(obj) OBJECT_CHECK(SH7751RCPGState, (obj), TYPE_SH7751R_CPG)
+#define SH7751CPG_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SH7751CPGBaseClass, obj, TYPE_SH7751_CPG_BASE)
+#define SH7751CPGBaseClass(klass) \
+ OBJECT_CLASS_CHECK(SH7751CPGBaseClass, klass, TYPE_SH7751_CPG_BASE)
+
+enum {
+ CK_DMAC,
+ CK_SCIF,
+ CK_TMU_0,
+ CK_RTC,
+ CK_SCI,
+ CK_SQ,
+ CK_UBC,
+ CK_PCIC,
+ CK_TMU_1,
+ CK_INTC,
+ NUM_SUBCLOCK,
+};
+
+typedef struct SH7751CPGBaseState {
+ SysBusDevice parent_obj;
+ uint8_t stbcr[2];
+ uint32_t clkstp00;
+ uint16_t freqcr;
+
+ uint32_t clock_mode;
+ int ick;
+ Clock *clk_ick;
+ int bck;
+ Clock *clk_bck;
+ int pck;
+ Clock *clk_pck;
+ Clock *dev_clocks[NUM_SUBCLOCK];
+ uint32_t xtal_freq_hz;
+ MemoryRegion memory[3 * 2];
+} SH7751CPGBaseState;
+
+typedef struct {
+ SH7751CPGBaseState parent_obj;
+} SH7751CPGState;
+
+typedef struct {
+ SH7751CPGBaseState parent_obj;
+} SH7751RCPGState;
+
+typedef struct {
+ SysBusDeviceClass parent;
+ int (*pll1mul)(int mode, uint16_t freqcr);
+ uint16_t *initfreqcr;
+} SH7751CPGBaseClass;
+
+typedef struct {
+ SH7751CPGBaseClass parent;
+} SH7751CPGClass;
+
+typedef struct {
+ SH7751CPGBaseClass parent;
+} SH7751RCPGClass;
+
+#endif
diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
index d53a436d8c..2f6c382aa6 100644
--- a/hw/sh4/sh7750.c
+++ b/hw/sh4/sh7750.c
@@ -24,6 +24,7 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/irq.h"
#include "hw/sh4/sh.h"
#include "sysemu/sysemu.h"
@@ -32,6 +33,8 @@
#include "hw/sh4/sh_intc.h"
#include "hw/timer/tmu012.h"
#include "exec/exec-all.h"
+#include "hw/sh4/sh7751-cpg.h"
+#include "hw/qdev-properties.h"
#define NB_DEVICES 4
@@ -752,9 +755,29 @@ static const MemoryRegionOps sh7750_mmct_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
+static SH7751CPGBaseState *sh_cpg_init(MemoryRegion *sysmem,
+ int cputype)
+{
+ const char *cpgtype;
+ SH7751CPGBaseState *cpg;
+ if (cputype & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
+ cpgtype = TYPE_SH7751R_CPG;
+ } else {
+ cpgtype = TYPE_SH7751_CPG;
+ }
+ cpg = SH7751CPGBase(qdev_new(cpgtype));
+ qdev_prop_set_uint32(DEVICE(cpg), "xtal-frequency-hz", 20 * 1000 * 1000);
+ qdev_prop_set_uint32(DEVICE(cpg), "clock-mode", 5);
+ sysbus_mmio_map(SYS_BUS_DEVICE(cpg), 0, 0x1fc00000);
+ sysbus_mmio_map(SYS_BUS_DEVICE(cpg), 1, P4ADDR(0x1fc00000));
+ sysbus_mmio_map(SYS_BUS_DEVICE(cpg), 2, A7ADDR(0x1fc00000));
+ return cpg;
+}
+
SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
{
SH7750State *s;
+ SH7751CPGBaseState *cpg;
s = g_malloc0(sizeof(SH7750State));
s->cpu = cpu;
@@ -800,6 +823,7 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
cpu->env.intc_handle = &s->intc;
+ cpg = sh_cpg_init(sysmem, cpu->env.id);
sh_serial_init(sysmem, 0x1fe00000,
0, s->periph_freq, serial_hd(0),
s->intc.irqs[SCI1_ERI],
@@ -824,6 +848,7 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
s->intc.irqs[TMU2_TUNI],
s->intc.irqs[TMU2_TICPI]);
+ sysbus_realize(SYS_BUS_DEVICE(cpg), &error_abort);
if (cpu->env.id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
sh_intc_register_sources(&s->intc,
_INTC_ARRAY(vectors_dma4),
diff --git a/hw/sh4/sh7751-cpg.c b/hw/sh4/sh7751-cpg.c
new file mode 100644
index 0000000000..4e057908ff
--- /dev/null
+++ b/hw/sh4/sh7751-cpg.c
@@ -0,0 +1,457 @@
+/*
+ * SH7750 / SH7751 Clock Generation Circuit
+ *
+ * Datasheet: SH7751 Group, SH7751R Group User's Manual: Hardware
+ * (Rev.4.01 R01UH0457EJ0401)
+ *
+ * Copyright (c) 2020 Yoshinori Sato
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "hw/hw.h"
+#include "hw/sh4/sh7751-cpg.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-properties.h"
+#include "hw/registerfields.h"
+#include "hw/qdev-properties.h"
+#include "hw/clock.h"
+#include "migration/vmstate.h"
+
+#define SH7751_XTAL_MIN_HZ (1 * 1000 * 1000)
+#define SH7751_XTAL_MAX_HZ (34 * 1000 * 1000)
+
+REG16(FREQCR, 0)
+ FIELD(FREQCR, PFC, 0, 3)
+ FIELD(FREQCR, BFC, 3, 3)
+ FIELD(FREQCR, IFC, 6, 3)
+ FIELD(FREQCR, PLL2EN, 9, 1)
+ FIELD(FREQCR, PLL1EN, 10, 1)
+ FIELD(FREQCR, CKOEN, 11, 1)
+REG8(STBCR, 4)
+REG8(STBCR2, 16)
+
+REG32(CLKSTP00, 0)
+REG32(CLKSTPCLR00, 8)
+
+typedef struct {
+ const char *name;
+ int devnum;
+ int reg;
+ int offset;
+} dev_clock_t;
+
+static const dev_clock_t dev_clock_list[] = {
+ { .name = "pck_sci", .devnum = CK_SCI, .reg = 0, .offset = 0},
+ { .name = "pck_rtc", .devnum = CK_RTC, .reg = 0, .offset = 1},
+ { .name = "pck_tmu-0", .devnum = CK_TMU_0, .reg = 0, .offset = 2},
+ { .name = "pck_scif", .devnum = CK_SCIF, .reg = 0, .offset = 3},
+ { .name = "pck_dmac", .devnum = CK_DMAC, .reg = 0, .offset = 4},
+ { .name = "pck_ubc", .devnum = CK_UBC, .reg = 1, .offset = 0},
+ { .name = "pck_sq", .devnum = CK_SQ, .reg = 1, .offset = 1},
+ { .name = "pck_intc", .devnum = CK_INTC, .reg = 2, .offset = 0},
+ { .name = "pck_tmu-1", .devnum = CK_TMU_1, .reg = 2, .offset = 1},
+ { .name = "pck_pcic", .devnum = CK_PCIC, .reg = 2, .offset = 2},
+ { },
+};
+
+static void set_clock_in(SH7751CPGBaseState *cpg, const dev_clock_t *ck)
+{
+ Clock *out;
+ uint64_t period;
+
+ out = qdev_get_clock_out(DEVICE(cpg), ck->name);
+ g_assert(out);
+ period = 0;
+ switch (ck->reg) {
+ case 0:
+ case 1:
+ if (extract8(cpg->stbcr[ck->reg], ck->offset, 1) == 0) {
+ period = clock_get(cpg->clk_ick);
+ }
+ break;
+ case 2:
+ if (extract32(cpg->clkstp00, ck->offset, 1) == 0) {
+ period = clock_get(cpg->clk_ick);
+ }
+ break;
+ }
+ if (clock_get(out) != period) {
+ clock_update(out, period);
+ }
+}
+
+static void update_divrate(SH7751CPGBaseState *cpg)
+{
+ SH7751CPGBaseClass *k = SH7751CPG_GET_CLASS(cpg);
+ int ick = FIELD_EX32(cpg->freqcr, FREQCR, IFC);
+ int bck = FIELD_EX32(cpg->freqcr, FREQCR, BFC);
+ int pck = FIELD_EX32(cpg->freqcr, FREQCR, PFC);
+ const dev_clock_t *p = dev_clock_list;
+ uint32_t divinput;
+
+ divinput = cpg->xtal_freq_hz * k->pll1mul(cpg->clock_mode, cpg->freqcr);
+
+ ick = ick < 4 ? ick + 1 : (ick - 1) * 2;
+ clock_update_hz(cpg->clk_ick, divinput / ick);
+ bck = bck < 4 ? bck + 1 : (bck - 1) * 2;
+ clock_update_hz(cpg->clk_bck, divinput / bck);
+ pck = pck < 3 ? pck + 2 : pck * 2;
+ clock_update_hz(cpg->clk_pck, divinput / pck);
+
+ while (p->name) {
+ set_clock_in(cpg, p);
+ p++;
+ }
+}
+
+static const dev_clock_t *find_clock_list(int crno, int bit)
+{
+ const dev_clock_t *ret = dev_clock_list;
+ while (ret->name) {
+ if (ret->reg == crno && ret->offset == bit) {
+ return ret;
+ }
+ ret++;
+ }
+ return NULL;
+}
+
+static void update_stbcr(SH7751CPGBaseState *cpg, int no, uint32_t diff)
+{
+ int bit = 0;
+ const dev_clock_t *p;
+ static const char *reg[] = {"STBCR", "STBCR2", "CLKSTP00"};
+
+ while (diff) {
+ if (diff & 1) {
+ p = find_clock_list(no, bit);
+ if (p) {
+ set_clock_in(cpg, p);
+ } else {
+ qemu_log_mask(LOG_UNIMP, "sh7751-cpg: %s "
+ " bit %d is not implement.\n", reg[no], bit);
+ }
+ }
+ bit++;
+ diff >>= 1;
+ }
+}
+
+static uint64_t cpg_read(void *opaque, hwaddr addr, unsigned size)
+{
+ SH7751CPGBaseState *cpg = SH7751CPGBase(opaque);
+ int reg;
+
+ switch (addr) {
+ case A_FREQCR:
+ if (size != 2) {
+ qemu_log_mask(LOG_GUEST_ERROR, "sh7751-cpg: Register 0x%"
+ HWADDR_PRIX " Invalid access size.\n", addr);
+ return UINT64_MAX;
+ }
+ return cpg->freqcr;
+ case A_STBCR:
+ case A_STBCR2:
+ if (size != 1) {
+ qemu_log_mask(LOG_GUEST_ERROR, "sh7751-cpg: Register 0x%"
+ HWADDR_PRIX " Invalid access size.\n", addr);
+ return UINT64_MAX;
+ }
+ reg = extract32(addr, 4, 1); /* STBCR -> 0x04 / STBCR2 -> 0x10 */
+ return cpg->stbcr[reg];
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "sh7751-cpg: Register 0x%"
+ HWADDR_PRIX " Invalid address.\n", addr);
+ return UINT64_MAX;
+ }
+
+}
+
+static void cpg_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+ SH7751CPGBaseState *cpg = SH7751CPGBase(opaque);
+ uint32_t old_stbcr;
+ int reg;
+
+ switch (addr) {
+ case A_FREQCR:
+ if (size != 2) {
+ qemu_log_mask(LOG_GUEST_ERROR, "sh7751-cpg: Register 0x%"
+ HWADDR_PRIX " Invalid access size.\n", addr);
+ return;
+ }
+ if ((cpg->freqcr ^ val) & 0x0600) {
+ qemu_log_mask(LOG_UNIMP,
+ "sh7751-cpg: PLL operation not supported.\n");
+ }
+ cpg->freqcr = val;
+ update_divrate(cpg);
+ break;
+ case A_STBCR:
+ case A_STBCR2:
+ if (size != 1) {
+ qemu_log_mask(LOG_GUEST_ERROR, "sh7751-cpg: Register 0x%"
+ HWADDR_PRIX " Invalid access size.\n", addr);
+ return;
+ }
+ reg = extract32(addr, 4, 1); /* STBCR -> 0x04 / STBCR2 -> 0x10 */
+ old_stbcr = cpg->stbcr[reg];
+ old_stbcr ^= val;
+ cpg->stbcr[reg] = val;
+ update_stbcr(cpg, reg, old_stbcr);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "sh7751-cpg: Register 0x%"
+ HWADDR_PRIX " Invalid address.\n", addr);
+ }
+}
+
+static uint64_t stp_read(void *opaque, hwaddr addr, unsigned size)
+{
+ SH7751CPGBaseState *cpg = SH7751CPGBase(opaque);
+
+ switch (addr) {
+ case A_CLKSTP00:
+ return cpg->clkstp00;
+ case A_CLKSTPCLR00:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "sh7751-cpg: CLKSTPCLR00 is write only.\n");
+ return UINT64_MAX;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "sh7751-cpg: Register 0x%"
+ HWADDR_PRIX " Invalid address.\n", addr);
+ return UINT64_MAX;
+ }
+}
+
+static void stp_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+ SH7751CPGBaseState *cpg = SH7751CPGBase(opaque);
+
+ val &= 0x7;
+ switch (addr) {
+ case A_CLKSTP00:
+ cpg->clkstp00 |= val;
+ update_stbcr(cpg, 2, val);
+ break;
+ case A_CLKSTPCLR00:
+ cpg->clkstp00 &= ~val;
+ update_stbcr(cpg, 2, val);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "sh7751-cpg: Register 0x%"
+ HWADDR_PRIX " Invalid address.\n", addr);
+ }
+}
+
+static int sh7751_pll1mul(int mode, uint16_t freqcr)
+{
+ int div1;
+ int pll1;
+ switch (mode) {
+ case 3:
+ case 5:
+ case 6:
+ div1 = 2;
+ break;
+ default:
+ div1 = 1;
+ }
+ if (FIELD_EX16(freqcr, FREQCR, PLL1EN)) {
+ pll1 = 6;
+ } else {
+ pll1 = 1;
+ }
+ return pll1 / div1;
+}
+
+static int sh7751r_pll1mul(int mode, uint16_t freqcr)
+{
+ int pll1;
+ switch (mode) {
+ case 0:
+ case 1:
+ case 3:
+ case 5:
+ pll1 = 12;
+ break;
+ case 2:
+ case 4:
+ case 6:
+ pll1 = 6;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ if (!FIELD_EX16(freqcr, FREQCR, PLL1EN)) {
+ pll1 = 1;
+ }
+ return pll1;
+}
+
+static const MemoryRegionOps cpg_ops = {
+ .write = cpg_write,
+ .read = cpg_read,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ },
+};
+
+static const MemoryRegionOps stp_ops = {
+ .write = stp_write,
+ .read = stp_read,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static const ClockPortInitArray sh7751_cpg_clocks = {
+ QDEV_CLOCK_OUT(SH7751CPGBaseState, clk_ick),
+ QDEV_CLOCK_OUT(SH7751CPGBaseState, clk_bck),
+ QDEV_CLOCK_OUT(SH7751CPGBaseState, clk_pck),
+ QDEV_CLOCK_END
+};
+
+static void sh7751cpg_realize(DeviceState *dev, Error **errp)
+{
+ SH7751CPGBaseState *cpg = SH7751CPGBase(dev);
+ SH7751CPGBaseClass *k = SH7751CPG_GET_CLASS(cpg);
+
+ if (cpg->xtal_freq_hz == 0) {
+ error_setg(errp, "\"xtal-frequency-hz\" property must be provided.");
+ return;
+ }
+ /* XTAL range: 1-34 MHz */
+ if (cpg->xtal_freq_hz < SH7751_XTAL_MIN_HZ ||
+ cpg->xtal_freq_hz > SH7751_XTAL_MAX_HZ) {
+ error_setg(errp, "\"xtal-frequency-hz\" property in incorrect range.");
+ return;
+ }
+ /* Clock mode: 0 - 6 */
+ if (cpg->clock_mode > 6) {
+ error_setg(errp, "\"clock-mode\" property in incorrect range.");
+ return;
+ }
+
+ cpg->freqcr = k->initfreqcr[cpg->clock_mode];
+ update_divrate(cpg);
+}
+
+static void sh7751_cpg_init(Object *obj)
+{
+ SH7751CPGBaseState *cpg = SH7751CPGBase(obj);
+ const dev_clock_t *p = dev_clock_list;
+ qdev_init_clocks(DEVICE(obj), sh7751_cpg_clocks);
+ /* connect parent clock */
+ while (p->name) {
+ cpg->dev_clocks[p->devnum] = qdev_init_clock_out(DEVICE(obj),
+ p->name);
+ p++;
+ }
+
+ memory_region_init_io(&cpg->memory[0], OBJECT(cpg), &cpg_ops,
+ cpg, "sh7751-cpg", 0x14);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &cpg->memory[0]);
+ memory_region_init_alias(&cpg->memory[1], NULL,
+ "sh7751-cpg-a4", &cpg->memory[0], 0, 0x14);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &cpg->memory[1]);
+ memory_region_init_alias(&cpg->memory[2], NULL,
+ "sh7751-cpg-p7", &cpg->memory[0], 0, 0x14);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &cpg->memory[2]);
+ memory_region_init_io(&cpg->memory[3], OBJECT(cpg), &stp_ops,
+ cpg, "sh7751-stp", 0x10);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &cpg->memory[3]);
+ memory_region_init_alias(&cpg->memory[4], NULL,
+ "sh7751-stp-a4", &cpg->memory[3], 0, 0x10);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &cpg->memory[4]);
+ memory_region_init_alias(&cpg->memory[5], NULL,
+ "sh7751-stp-p7", &cpg->memory[3], 0, 0x10u);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &cpg->memory[5]);
+}
+
+static Property sh7751_cpg_properties[] = {
+ DEFINE_PROP_UINT32("xtal-frequency-hz",
+ SH7751CPGBaseState, xtal_freq_hz, 0),
+ DEFINE_PROP_UINT32("clock-mode",
+ SH7751CPGBaseState, clock_mode, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sh7751cpg_base_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ device_class_set_props(dc, sh7751_cpg_properties);
+}
+
+static void sh7751cpg_class_init(ObjectClass *klass, void *data)
+{
+ SH7751CPGBaseClass *base = SH7751CPGBaseClass(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ static uint16_t initfreqcr[] = {0x0e1a, 0x0e23, 0x0e13, 0x0e13,
+ 0x0e0a, 0x0e0a, 0x0808};
+
+ base->pll1mul = sh7751_pll1mul;
+ base->initfreqcr = initfreqcr;
+ dc->realize = sh7751cpg_realize;
+}
+
+static void sh7751rcpg_class_init(ObjectClass *klass, void *data)
+{
+ SH7751CPGBaseClass *base = SH7751CPGBaseClass(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ static uint16_t initfreqcr[] = {0x0e1a, 0x0e2c, 0x0e13, 0x0e13,
+ 0x0e0a, 0x0e0a, 0x0808};
+
+ base->pll1mul = sh7751r_pll1mul;
+ base->initfreqcr = initfreqcr;
+ dc->realize = sh7751cpg_realize;
+}
+
+static const TypeInfo sh7751cpg_info[] = {
+ {
+ .name = TYPE_SH7751_CPG_BASE,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SH7751CPGBaseState),
+ .class_init = sh7751cpg_base_class_init,
+ .class_size = sizeof(SH7751CPGBaseClass),
+ .abstract = true,
+ },
+ {
+ .name = TYPE_SH7751_CPG,
+ .parent = TYPE_SH7751_CPG_BASE,
+ .instance_size = sizeof(SH7751CPGState),
+ .instance_init = sh7751_cpg_init,
+ .class_init = sh7751cpg_class_init,
+ .class_size = sizeof(SH7751CPGClass),
+ },
+ {
+ .name = TYPE_SH7751R_CPG,
+ .parent = TYPE_SH7751_CPG_BASE,
+ .instance_size = sizeof(SH7751RCPGState),
+ .instance_init = sh7751_cpg_init,
+ .class_init = sh7751rcpg_class_init,
+ .class_size = sizeof(SH7751RCPGClass),
+ },
+};
+
+DEFINE_TYPES(sh7751cpg_info)
diff --git a/hw/sh4/meson.build b/hw/sh4/meson.build
index 424d5674de..7ed8246152 100644
--- a/hw/sh4/meson.build
+++ b/hw/sh4/meson.build
@@ -2,6 +2,7 @@ sh4_ss = ss.source_set()
sh4_ss.add(files(
'sh7750.c',
'sh7750_regnames.c',
+ 'sh7751-cpg.c',
))
sh4_ss.add(when: 'CONFIG_R2D', if_true: files('r2d.c'))
sh4_ss.add(when: 'CONFIG_SHIX', if_true: files('shix.c'))
--
2.20.1
© 2016 - 2024 Red Hat, Inc.