master
c 118 lines 2.82 KB
Raw
1 /*
2 * ASPEED PWM Controller
3 *
4 * Copyright (C) 2017-2021 IBM Corp.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "qemu/log.h"
11 #include "qemu/error-report.h"
12 #include "hw/misc/aspeed_pwm.h"
13 #include "qapi/error.h"
14 #include "migration/vmstate.h"
15
16 #include "trace.h"
17
18 static uint64_t aspeed_pwm_read(void *opaque, hwaddr addr,
19 unsigned int size)
20 {
21 AspeedPWMState *s = ASPEED_PWM(opaque);
22 uint64_t val = 0;
23
24 addr >>= 2;
25
26 if (addr >= ASPEED_PWM_NR_REGS) {
27 qemu_log_mask(LOG_GUEST_ERROR,
28 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
29 __func__, addr << 2);
30 } else {
31 val = s->regs[addr];
32 }
33
34 trace_aspeed_pwm_read(addr << 2, val);
35
36 return val;
37 }
38
39 static void aspeed_pwm_write(void *opaque, hwaddr addr, uint64_t data,
40 unsigned int size)
41 {
42 AspeedPWMState *s = ASPEED_PWM(opaque);
43
44 trace_aspeed_pwm_write(addr, data);
45
46 addr >>= 2;
47
48 if (addr >= ASPEED_PWM_NR_REGS) {
49 qemu_log_mask(LOG_GUEST_ERROR,
50 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
51 __func__, addr << 2);
52 return;
53 }
54
55 s->regs[addr] = data;
56 }
57
58 static const MemoryRegionOps aspeed_pwm_ops = {
59 .read = aspeed_pwm_read,
60 .write = aspeed_pwm_write,
61 .endianness = DEVICE_LITTLE_ENDIAN,
62 .valid = {
63 .min_access_size = 1,
64 .max_access_size = 4,
65 },
66 };
67
68 static void aspeed_pwm_reset_hold(Object *obj, ResetType type)
69 {
70 AspeedPWMState *s = ASPEED_PWM(obj);
71
72 memset(s->regs, 0, sizeof(s->regs));
73 }
74
75 static void aspeed_pwm_realize(DeviceState *dev, Error **errp)
76 {
77 AspeedPWMState *s = ASPEED_PWM(dev);
78 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
79
80 sysbus_init_irq(sbd, &s->irq);
81
82 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_pwm_ops, s,
83 TYPE_ASPEED_PWM, 0x1000);
84
85 sysbus_init_mmio(sbd, &s->iomem);
86 }
87
88 static const VMStateDescription vmstate_aspeed_pwm = {
89 .name = TYPE_ASPEED_PWM,
90 .version_id = 1,
91 .minimum_version_id = 1,
92 .fields = (VMStateField[]) {
93 VMSTATE_UINT32_ARRAY(regs, AspeedPWMState, ASPEED_PWM_NR_REGS),
94 VMSTATE_END_OF_LIST(),
95 }
96 };
97
98 static void aspeed_pwm_class_init(ObjectClass *klass, const void *data)
99 {
100 DeviceClass *dc = DEVICE_CLASS(klass);
101 ResettableClass *rc = RESETTABLE_CLASS(klass);
102
103 dc->realize = aspeed_pwm_realize;
104 rc->phases.hold = aspeed_pwm_reset_hold;
105 dc->desc = "Aspeed PWM Controller";
106 dc->vmsd = &vmstate_aspeed_pwm;
107 }
108
109 static const TypeInfo aspeed_pwm_types[] = {
110 {
111 .name = TYPE_ASPEED_PWM,
112 .parent = TYPE_SYS_BUS_DEVICE,
113 .instance_size = sizeof(AspeedPWMState),
114 .class_init = aspeed_pwm_class_init,
115 }
116 };
117
118 DEFINE_TYPES(aspeed_pwm_types)