2 * ASPEED I3C Controller
4 * Copyright (C) 2021 ASPEED Technology Inc.
6 * This code is licensed under the GPL version 2 or later. See
7 * the COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
12 #include "qemu/error-report.h"
13 #include "hw/misc/aspeed_i3c.h"
14 #include "hw/registerfields.h"
15 #include "hw/qdev-properties.h"
16 #include "qapi/error.h"
17 #include "migration/vmstate.h"
20 /* I3C Controller Registers */
21 REG32(I3C1_REG0
, 0x10)
22 REG32(I3C1_REG1
, 0x14)
23 FIELD(I3C1_REG1
, I2C_MODE
, 0, 1)
24 FIELD(I3C1_REG1
, SA_EN
, 15, 1)
25 REG32(I3C2_REG0
, 0x20)
26 REG32(I3C2_REG1
, 0x24)
27 FIELD(I3C2_REG1
, I2C_MODE
, 0, 1)
28 FIELD(I3C2_REG1
, SA_EN
, 15, 1)
29 REG32(I3C3_REG0
, 0x30)
30 REG32(I3C3_REG1
, 0x34)
31 FIELD(I3C3_REG1
, I2C_MODE
, 0, 1)
32 FIELD(I3C3_REG1
, SA_EN
, 15, 1)
33 REG32(I3C4_REG0
, 0x40)
34 REG32(I3C4_REG1
, 0x44)
35 FIELD(I3C4_REG1
, I2C_MODE
, 0, 1)
36 FIELD(I3C4_REG1
, SA_EN
, 15, 1)
37 REG32(I3C5_REG0
, 0x50)
38 REG32(I3C5_REG1
, 0x54)
39 FIELD(I3C5_REG1
, I2C_MODE
, 0, 1)
40 FIELD(I3C5_REG1
, SA_EN
, 15, 1)
41 REG32(I3C6_REG0
, 0x60)
42 REG32(I3C6_REG1
, 0x64)
43 FIELD(I3C6_REG1
, I2C_MODE
, 0, 1)
44 FIELD(I3C6_REG1
, SA_EN
, 15, 1)
46 /* I3C Device Registers */
47 REG32(DEVICE_CTRL
, 0x00)
48 REG32(DEVICE_ADDR
, 0x04)
49 REG32(HW_CAPABILITY
, 0x08)
50 REG32(COMMAND_QUEUE_PORT
, 0x0c)
51 REG32(RESPONSE_QUEUE_PORT
, 0x10)
52 REG32(RX_TX_DATA_PORT
, 0x14)
53 REG32(IBI_QUEUE_STATUS
, 0x18)
54 REG32(IBI_QUEUE_DATA
, 0x18)
55 REG32(QUEUE_THLD_CTRL
, 0x1c)
56 REG32(DATA_BUFFER_THLD_CTRL
, 0x20)
57 REG32(IBI_QUEUE_CTRL
, 0x24)
58 REG32(IBI_MR_REQ_REJECT
, 0x2c)
59 REG32(IBI_SIR_REQ_REJECT
, 0x30)
60 REG32(RESET_CTRL
, 0x34)
61 REG32(SLV_EVENT_CTRL
, 0x38)
62 REG32(INTR_STATUS
, 0x3c)
63 REG32(INTR_STATUS_EN
, 0x40)
64 REG32(INTR_SIGNAL_EN
, 0x44)
65 REG32(INTR_FORCE
, 0x48)
66 REG32(QUEUE_STATUS_LEVEL
, 0x4c)
67 REG32(DATA_BUFFER_STATUS_LEVEL
, 0x50)
68 REG32(PRESENT_STATE
, 0x54)
69 REG32(CCC_DEVICE_STATUS
, 0x58)
70 REG32(DEVICE_ADDR_TABLE_POINTER
, 0x5c)
71 FIELD(DEVICE_ADDR_TABLE_POINTER
, DEPTH
, 16, 16)
72 FIELD(DEVICE_ADDR_TABLE_POINTER
, ADDR
, 0, 16)
73 REG32(DEV_CHAR_TABLE_POINTER
, 0x60)
74 REG32(VENDOR_SPECIFIC_REG_POINTER
, 0x6c)
75 REG32(SLV_MIPI_PID_VALUE
, 0x70)
76 REG32(SLV_PID_VALUE
, 0x74)
77 REG32(SLV_CHAR_CTRL
, 0x78)
78 REG32(SLV_MAX_LEN
, 0x7c)
79 REG32(MAX_READ_TURNAROUND
, 0x80)
80 REG32(MAX_DATA_SPEED
, 0x84)
81 REG32(SLV_DEBUG_STATUS
, 0x88)
82 REG32(SLV_INTR_REQ
, 0x8c)
83 REG32(DEVICE_CTRL_EXTENDED
, 0xb0)
84 REG32(SCL_I3C_OD_TIMING
, 0xb4)
85 REG32(SCL_I3C_PP_TIMING
, 0xb8)
86 REG32(SCL_I2C_FM_TIMING
, 0xbc)
87 REG32(SCL_I2C_FMP_TIMING
, 0xc0)
88 REG32(SCL_EXT_LCNT_TIMING
, 0xc8)
89 REG32(SCL_EXT_TERMN_LCNT_TIMING
, 0xcc)
90 REG32(BUS_FREE_TIMING
, 0xd4)
91 REG32(BUS_IDLE_TIMING
, 0xd8)
92 REG32(I3C_VER_ID
, 0xe0)
93 REG32(I3C_VER_TYPE
, 0xe4)
94 REG32(EXTENDED_CAPABILITY
, 0xe8)
95 REG32(SLAVE_CONFIG
, 0xec)
97 static const uint32_t ast2600_i3c_device_resets
[ASPEED_I3C_DEVICE_NR_REGS
] = {
98 [R_HW_CAPABILITY
] = 0x000e00bf,
99 [R_QUEUE_THLD_CTRL
] = 0x01000101,
100 [R_I3C_VER_ID
] = 0x3130302a,
101 [R_I3C_VER_TYPE
] = 0x6c633033,
102 [R_DEVICE_ADDR_TABLE_POINTER
] = 0x00080280,
103 [R_DEV_CHAR_TABLE_POINTER
] = 0x00020200,
104 [A_VENDOR_SPECIFIC_REG_POINTER
] = 0x000000b0,
105 [R_SLV_MAX_LEN
] = 0x00ff00ff,
108 static uint64_t aspeed_i3c_device_read(void *opaque
, hwaddr offset
,
111 AspeedI3CDevice
*s
= ASPEED_I3C_DEVICE(opaque
);
112 uint32_t addr
= offset
>> 2;
116 case R_COMMAND_QUEUE_PORT
:
120 value
= s
->regs
[addr
];
124 trace_aspeed_i3c_device_read(s
->id
, offset
, value
);
129 static void aspeed_i3c_device_write(void *opaque
, hwaddr offset
,
130 uint64_t value
, unsigned size
)
132 AspeedI3CDevice
*s
= ASPEED_I3C_DEVICE(opaque
);
133 uint32_t addr
= offset
>> 2;
135 trace_aspeed_i3c_device_write(s
->id
, offset
, value
);
138 case R_HW_CAPABILITY
:
139 case R_RESPONSE_QUEUE_PORT
:
140 case R_IBI_QUEUE_DATA
:
141 case R_QUEUE_STATUS_LEVEL
:
142 case R_PRESENT_STATE
:
143 case R_CCC_DEVICE_STATUS
:
144 case R_DEVICE_ADDR_TABLE_POINTER
:
145 case R_VENDOR_SPECIFIC_REG_POINTER
:
146 case R_SLV_CHAR_CTRL
:
148 case R_MAX_READ_TURNAROUND
:
151 case R_EXTENDED_CAPABILITY
:
152 qemu_log_mask(LOG_GUEST_ERROR
,
153 "%s: write to readonly register[0x%02" HWADDR_PRIx
154 "] = 0x%08" PRIx64
"\n",
155 __func__
, offset
, value
);
157 case R_RX_TX_DATA_PORT
:
162 s
->regs
[addr
] = value
;
167 static const VMStateDescription aspeed_i3c_device_vmstate
= {
168 .name
= TYPE_ASPEED_I3C
,
170 .minimum_version_id
= 1,
171 .fields
= (VMStateField
[]){
172 VMSTATE_UINT32_ARRAY(regs
, AspeedI3CDevice
, ASPEED_I3C_DEVICE_NR_REGS
),
173 VMSTATE_END_OF_LIST(),
177 static const MemoryRegionOps aspeed_i3c_device_ops
= {
178 .read
= aspeed_i3c_device_read
,
179 .write
= aspeed_i3c_device_write
,
180 .endianness
= DEVICE_LITTLE_ENDIAN
,
183 static void aspeed_i3c_device_reset(DeviceState
*dev
)
185 AspeedI3CDevice
*s
= ASPEED_I3C_DEVICE(dev
);
187 memcpy(s
->regs
, ast2600_i3c_device_resets
, sizeof(s
->regs
));
190 static void aspeed_i3c_device_realize(DeviceState
*dev
, Error
**errp
)
192 AspeedI3CDevice
*s
= ASPEED_I3C_DEVICE(dev
);
193 g_autofree
char *name
= g_strdup_printf(TYPE_ASPEED_I3C_DEVICE
".%d",
196 sysbus_init_irq(SYS_BUS_DEVICE(dev
), &s
->irq
);
198 memory_region_init_io(&s
->mr
, OBJECT(s
), &aspeed_i3c_device_ops
,
199 s
, name
, ASPEED_I3C_DEVICE_NR_REGS
<< 2);
202 static uint64_t aspeed_i3c_read(void *opaque
, hwaddr addr
, unsigned int size
)
204 AspeedI3CState
*s
= ASPEED_I3C(opaque
);
207 val
= s
->regs
[addr
>> 2];
209 trace_aspeed_i3c_read(addr
, val
);
214 static void aspeed_i3c_write(void *opaque
,
219 AspeedI3CState
*s
= ASPEED_I3C(opaque
);
221 trace_aspeed_i3c_write(addr
, data
);
225 /* I3C controller register */
233 if (data
& R_I3C1_REG1_I2C_MODE_MASK
) {
234 qemu_log_mask(LOG_UNIMP
,
235 "%s: Unsupported I2C mode [0x%08" HWADDR_PRIx
237 __func__
, addr
<< 2, data
);
240 if (data
& R_I3C1_REG1_SA_EN_MASK
) {
241 qemu_log_mask(LOG_UNIMP
,
242 "%s: Unsupported slave mode [%08" HWADDR_PRIx
243 "]=0x%08" PRIx64
"\n",
244 __func__
, addr
<< 2, data
);
247 s
->regs
[addr
] = data
;
250 s
->regs
[addr
] = data
;
255 static const MemoryRegionOps aspeed_i3c_ops
= {
256 .read
= aspeed_i3c_read
,
257 .write
= aspeed_i3c_write
,
258 .endianness
= DEVICE_LITTLE_ENDIAN
,
260 .min_access_size
= 1,
261 .max_access_size
= 4,
265 static void aspeed_i3c_reset(DeviceState
*dev
)
267 AspeedI3CState
*s
= ASPEED_I3C(dev
);
268 memset(s
->regs
, 0, sizeof(s
->regs
));
271 static void aspeed_i3c_instance_init(Object
*obj
)
273 AspeedI3CState
*s
= ASPEED_I3C(obj
);
276 for (i
= 0; i
< ASPEED_I3C_NR_DEVICES
; ++i
) {
277 object_initialize_child(obj
, "device[*]", &s
->devices
[i
],
278 TYPE_ASPEED_I3C_DEVICE
);
282 static void aspeed_i3c_realize(DeviceState
*dev
, Error
**errp
)
285 AspeedI3CState
*s
= ASPEED_I3C(dev
);
286 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
288 memory_region_init(&s
->iomem_container
, OBJECT(s
),
289 TYPE_ASPEED_I3C
".container", 0x8000);
291 sysbus_init_mmio(sbd
, &s
->iomem_container
);
293 memory_region_init_io(&s
->iomem
, OBJECT(s
), &aspeed_i3c_ops
, s
,
294 TYPE_ASPEED_I3C
".regs", ASPEED_I3C_NR_REGS
<< 2);
296 memory_region_add_subregion(&s
->iomem_container
, 0x0, &s
->iomem
);
298 for (i
= 0; i
< ASPEED_I3C_NR_DEVICES
; ++i
) {
299 Object
*dev
= OBJECT(&s
->devices
[i
]);
301 if (!object_property_set_uint(dev
, "device-id", i
, errp
)) {
305 if (!sysbus_realize(SYS_BUS_DEVICE(dev
), errp
)) {
310 * Register Address of I3CX Device =
311 * (Base Address of Global Register) + (Offset of I3CX) + Offset
312 * X = 0, 1, 2, 3, 4, 5
313 * Offset of I3C0 = 0x2000
314 * Offset of I3C1 = 0x3000
315 * Offset of I3C2 = 0x4000
316 * Offset of I3C3 = 0x5000
317 * Offset of I3C4 = 0x6000
318 * Offset of I3C5 = 0x7000
320 memory_region_add_subregion(&s
->iomem_container
,
321 0x2000 + i
* 0x1000, &s
->devices
[i
].mr
);
326 static Property aspeed_i3c_device_properties
[] = {
327 DEFINE_PROP_UINT8("device-id", AspeedI3CDevice
, id
, 0),
328 DEFINE_PROP_END_OF_LIST(),
331 static void aspeed_i3c_device_class_init(ObjectClass
*klass
, void *data
)
333 DeviceClass
*dc
= DEVICE_CLASS(klass
);
335 dc
->desc
= "Aspeed I3C Device";
336 dc
->realize
= aspeed_i3c_device_realize
;
337 dc
->reset
= aspeed_i3c_device_reset
;
338 device_class_set_props(dc
, aspeed_i3c_device_properties
);
341 static const TypeInfo aspeed_i3c_device_info
= {
342 .name
= TYPE_ASPEED_I3C_DEVICE
,
343 .parent
= TYPE_SYS_BUS_DEVICE
,
344 .instance_size
= sizeof(AspeedI3CDevice
),
345 .class_init
= aspeed_i3c_device_class_init
,
348 static const VMStateDescription vmstate_aspeed_i3c
= {
349 .name
= TYPE_ASPEED_I3C
,
351 .minimum_version_id
= 1,
352 .fields
= (VMStateField
[]) {
353 VMSTATE_UINT32_ARRAY(regs
, AspeedI3CState
, ASPEED_I3C_NR_REGS
),
354 VMSTATE_STRUCT_ARRAY(devices
, AspeedI3CState
, ASPEED_I3C_NR_DEVICES
, 1,
355 aspeed_i3c_device_vmstate
, AspeedI3CDevice
),
356 VMSTATE_END_OF_LIST(),
360 static void aspeed_i3c_class_init(ObjectClass
*klass
, void *data
)
362 DeviceClass
*dc
= DEVICE_CLASS(klass
);
364 dc
->realize
= aspeed_i3c_realize
;
365 dc
->reset
= aspeed_i3c_reset
;
366 dc
->desc
= "Aspeed I3C Controller";
367 dc
->vmsd
= &vmstate_aspeed_i3c
;
370 static const TypeInfo aspeed_i3c_info
= {
371 .name
= TYPE_ASPEED_I3C
,
372 .parent
= TYPE_SYS_BUS_DEVICE
,
373 .instance_init
= aspeed_i3c_instance_init
,
374 .instance_size
= sizeof(AspeedI3CState
),
375 .class_init
= aspeed_i3c_class_init
,
378 static void aspeed_i3c_register_types(void)
380 type_register_static(&aspeed_i3c_device_info
);
381 type_register_static(&aspeed_i3c_info
);
384 type_init(aspeed_i3c_register_types
);