xref: /openbmc/qemu/hw/i3c/aspeed_i3c.c (revision fd85e880b9f68a307f373751e9d714ea553e8466)
1 /*
2  * ASPEED I3C Controller
3  *
4  * Copyright (C) 2021 ASPEED Technology Inc.
5  * Copyright (C) 2025 Google, LLC.
6  *
7  * This code is licensed under the GPL version 2 or later.  See
8  * the COPYING file in the top-level directory.
9  */
10 
11 #include "qemu/osdep.h"
12 #include "qemu/log.h"
13 #include "qemu/error-report.h"
14 #include "hw/i3c/aspeed_i3c.h"
15 #include "hw/registerfields.h"
16 #include "hw/qdev-properties.h"
17 #include "qapi/error.h"
18 #include "migration/vmstate.h"
19 #include "trace.h"
20 
21 /* I3C Controller Registers */
22 REG32(I3C1_REG0, 0x10)
23 REG32(I3C1_REG1, 0x14)
24     FIELD(I3C1_REG1, I2C_MODE,      0,  1)
25     FIELD(I3C1_REG1, SLV_TEST_MODE, 1,  1)
26     FIELD(I3C1_REG1, ACT_MODE,      2,  2)
27     FIELD(I3C1_REG1, PENDING_INT,   4,  4)
28     FIELD(I3C1_REG1, SA,            8,  7)
29     FIELD(I3C1_REG1, SA_EN,         15, 1)
30     FIELD(I3C1_REG1, INST_ID,       16, 4)
31 REG32(I3C2_REG0, 0x20)
32 REG32(I3C2_REG1, 0x24)
33     FIELD(I3C2_REG1, I2C_MODE,      0,  1)
34     FIELD(I3C2_REG1, SLV_TEST_MODE, 1,  1)
35     FIELD(I3C2_REG1, ACT_MODE,      2,  2)
36     FIELD(I3C2_REG1, PENDING_INT,   4,  4)
37     FIELD(I3C2_REG1, SA,            8,  7)
38     FIELD(I3C2_REG1, SA_EN,         15, 1)
39     FIELD(I3C2_REG1, INST_ID,       16, 4)
40 REG32(I3C3_REG0, 0x30)
41 REG32(I3C3_REG1, 0x34)
42     FIELD(I3C3_REG1, I2C_MODE,      0,  1)
43     FIELD(I3C3_REG1, SLV_TEST_MODE, 1,  1)
44     FIELD(I3C3_REG1, ACT_MODE,      2,  2)
45     FIELD(I3C3_REG1, PENDING_INT,   4,  4)
46     FIELD(I3C3_REG1, SA,            8,  7)
47     FIELD(I3C3_REG1, SA_EN,         15, 1)
48     FIELD(I3C3_REG1, INST_ID,       16, 4)
49 REG32(I3C4_REG0, 0x40)
50 REG32(I3C4_REG1, 0x44)
51     FIELD(I3C4_REG1, I2C_MODE,      0,  1)
52     FIELD(I3C4_REG1, SLV_TEST_MODE, 1,  1)
53     FIELD(I3C4_REG1, ACT_MODE,      2,  2)
54     FIELD(I3C4_REG1, PENDING_INT,   4,  4)
55     FIELD(I3C4_REG1, SA,            8,  7)
56     FIELD(I3C4_REG1, SA_EN,         15, 1)
57     FIELD(I3C4_REG1, INST_ID,       16, 4)
58 REG32(I3C5_REG0, 0x50)
59 REG32(I3C5_REG1, 0x54)
60     FIELD(I3C5_REG1, I2C_MODE,      0,  1)
61     FIELD(I3C5_REG1, SLV_TEST_MODE, 1,  1)
62     FIELD(I3C5_REG1, ACT_MODE,      2,  2)
63     FIELD(I3C5_REG1, PENDING_INT,   4,  4)
64     FIELD(I3C5_REG1, SA,            8,  7)
65     FIELD(I3C5_REG1, SA_EN,         15, 1)
66     FIELD(I3C5_REG1, INST_ID,       16, 4)
67 REG32(I3C6_REG0, 0x60)
68 REG32(I3C6_REG1, 0x64)
69     FIELD(I3C6_REG1, I2C_MODE,      0,  1)
70     FIELD(I3C6_REG1, SLV_TEST_MODE, 1,  1)
71     FIELD(I3C6_REG1, ACT_MODE,      2,  2)
72     FIELD(I3C6_REG1, PENDING_INT,   4,  4)
73     FIELD(I3C6_REG1, SA,            8,  7)
74     FIELD(I3C6_REG1, SA_EN,         15, 1)
75     FIELD(I3C6_REG1, INST_ID,       16, 4)
76 
77 static const uint32_t ast2600_i3c_controller_ro[ASPEED_I3C_NR_REGS] = {
78     [R_I3C1_REG0]                   = 0xfc000000,
79     [R_I3C1_REG1]                   = 0xfff00000,
80     [R_I3C2_REG0]                   = 0xfc000000,
81     [R_I3C2_REG1]                   = 0xfff00000,
82     [R_I3C3_REG0]                   = 0xfc000000,
83     [R_I3C3_REG1]                   = 0xfff00000,
84     [R_I3C4_REG0]                   = 0xfc000000,
85     [R_I3C4_REG1]                   = 0xfff00000,
86     [R_I3C5_REG0]                   = 0xfc000000,
87     [R_I3C5_REG1]                   = 0xfff00000,
88     [R_I3C6_REG0]                   = 0xfc000000,
89     [R_I3C6_REG1]                   = 0xfff00000,
90 };
91 
aspeed_i3c_read(void * opaque,hwaddr addr,unsigned int size)92 static uint64_t aspeed_i3c_read(void *opaque, hwaddr addr, unsigned int size)
93 {
94     AspeedI3CState *s = ASPEED_I3C(opaque);
95     uint64_t val = 0;
96 
97     val = s->regs[addr >> 2];
98 
99     trace_aspeed_i3c_read(addr, val);
100 
101     return val;
102 }
103 
aspeed_i3c_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)104 static void aspeed_i3c_write(void *opaque,
105                              hwaddr addr,
106                              uint64_t data,
107                              unsigned int size)
108 {
109     AspeedI3CState *s = ASPEED_I3C(opaque);
110 
111     trace_aspeed_i3c_write(addr, data);
112 
113     addr >>= 2;
114 
115     data &= ~ast2600_i3c_controller_ro[addr];
116     /* I3C controller register */
117     switch (addr) {
118     case R_I3C1_REG1:
119     case R_I3C2_REG1:
120     case R_I3C3_REG1:
121     case R_I3C4_REG1:
122     case R_I3C5_REG1:
123     case R_I3C6_REG1:
124         if (data & R_I3C1_REG1_I2C_MODE_MASK) {
125             qemu_log_mask(LOG_UNIMP,
126                           "%s: Unsupported I2C mode [0x%08" HWADDR_PRIx
127                           "]=%08" PRIx64 "\n",
128                           __func__, addr << 2, data);
129             break;
130         }
131         if (data & R_I3C1_REG1_SA_EN_MASK) {
132             qemu_log_mask(LOG_UNIMP,
133                           "%s: Unsupported slave mode [%08" HWADDR_PRIx
134                           "]=0x%08" PRIx64 "\n",
135                           __func__, addr << 2, data);
136             break;
137         }
138         s->regs[addr] = data;
139         break;
140     default:
141         s->regs[addr] = data;
142         break;
143     }
144 }
145 
146 static const MemoryRegionOps aspeed_i3c_ops = {
147     .read = aspeed_i3c_read,
148     .write = aspeed_i3c_write,
149     .endianness = DEVICE_LITTLE_ENDIAN,
150     .valid = {
151         .min_access_size = 1,
152         .max_access_size = 4,
153     }
154 };
155 
aspeed_i3c_get_bus(AspeedI3CState * s,uint8_t bus_num)156 I3CBus *aspeed_i3c_get_bus(AspeedI3CState *s, uint8_t bus_num)
157 {
158     if (bus_num < ARRAY_SIZE(s->devices)) {
159         return s->devices[bus_num].bus;
160     }
161     /* Developer error, fail fast. */
162     g_assert_not_reached();
163 }
164 
aspeed_i3c_reset(DeviceState * dev)165 static void aspeed_i3c_reset(DeviceState *dev)
166 {
167     AspeedI3CState *s = ASPEED_I3C(dev);
168     memset(s->regs, 0, sizeof(s->regs));
169 }
170 
aspeed_i3c_instance_init(Object * obj)171 static void aspeed_i3c_instance_init(Object *obj)
172 {
173     AspeedI3CState *s = ASPEED_I3C(obj);
174     int i;
175 
176     for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) {
177         object_initialize_child(obj, "device[*]", &s->devices[i],
178                 TYPE_DW_I3C);
179     }
180 }
181 
aspeed_i3c_realize(DeviceState * dev,Error ** errp)182 static void aspeed_i3c_realize(DeviceState *dev, Error **errp)
183 {
184     int i;
185     AspeedI3CState *s = ASPEED_I3C(dev);
186     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
187 
188     memory_region_init(&s->iomem_container, OBJECT(s),
189             TYPE_ASPEED_I3C ".container", 0x8000);
190 
191     sysbus_init_mmio(sbd, &s->iomem_container);
192 
193     memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i3c_ops, s,
194             TYPE_ASPEED_I3C ".regs", ASPEED_I3C_NR_REGS << 2);
195 
196     memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem);
197 
198     for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) {
199         Object *i3c_dev = OBJECT(&s->devices[i]);
200 
201         if (!object_property_set_uint(i3c_dev, "device-id", i, errp)) {
202             return;
203         }
204 
205         if (!sysbus_realize(SYS_BUS_DEVICE(i3c_dev), errp)) {
206             return;
207         }
208 
209         /*
210          * Register Address of I3CX Device =
211          *     (Base Address of Global Register) + (Offset of I3CX) + Offset
212          * X = 0, 1, 2, 3, 4, 5
213          * Offset of I3C0 = 0x2000
214          * Offset of I3C1 = 0x3000
215          * Offset of I3C2 = 0x4000
216          * Offset of I3C3 = 0x5000
217          * Offset of I3C4 = 0x6000
218          * Offset of I3C5 = 0x7000
219          */
220         memory_region_add_subregion(&s->iomem_container,
221                 0x2000 + i * 0x1000, &s->devices[i].mr);
222     }
223 
224 }
225 
226 static const VMStateDescription vmstate_aspeed_i3c = {
227     .name = TYPE_ASPEED_I3C,
228     .version_id = 1,
229     .minimum_version_id = 1,
230     .fields = (const VMStateField[]) {
231         VMSTATE_UINT32_ARRAY(regs, AspeedI3CState, ASPEED_I3C_NR_REGS),
232         VMSTATE_STRUCT_ARRAY(devices, AspeedI3CState, ASPEED_I3C_NR_DEVICES, 1,
233                              vmstate_dw_i3c, DWI3C),
234         VMSTATE_END_OF_LIST(),
235     }
236 };
237 
aspeed_i3c_class_init(ObjectClass * klass,const void * data)238 static void aspeed_i3c_class_init(ObjectClass *klass, const void *data)
239 {
240     DeviceClass *dc = DEVICE_CLASS(klass);
241 
242     dc->realize = aspeed_i3c_realize;
243     device_class_set_legacy_reset(dc, aspeed_i3c_reset);
244     dc->desc = "Aspeed I3C Controller";
245     dc->vmsd = &vmstate_aspeed_i3c;
246 }
247 
248 static const TypeInfo aspeed_i3c_info = {
249     .name = TYPE_ASPEED_I3C,
250     .parent = TYPE_SYS_BUS_DEVICE,
251     .instance_init = aspeed_i3c_instance_init,
252     .instance_size = sizeof(AspeedI3CState),
253     .class_init = aspeed_i3c_class_init,
254 };
255 
aspeed_i3c_register_types(void)256 static void aspeed_i3c_register_types(void)
257 {
258     type_register_static(&aspeed_i3c_info);
259 }
260 
261 type_init(aspeed_i3c_register_types);
262