master
c 191 lines 5.14 KB
Raw
1 /*
2 * ASPEED LTPI Controller
3 *
4 * Copyright (C) 2025 ASPEED Technology Inc.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "qemu/log.h"
11 #include "migration/vmstate.h"
12 #include "hw/misc/aspeed_ltpi.h"
13
14 #define ASPEED_LTPI_CTRL_BASE 0x000
15 #define ASPEED_LTPI_PHY_BASE 0x200
16 #define ASPEED_LTPI_TOP_BASE 0x800
17
18 #define LTPI_CTRL_LINK_MNG 0x42
19 #define LTPI_PHY_MODE 0x0
20
21 static uint64_t aspeed_ltpi_top_read(void *opaque, hwaddr offset, unsigned size)
22 {
23 AspeedLTPIState *s = opaque;
24 uint32_t idx = offset >> 2;
25
26 return s->top_regs[idx];
27 }
28
29 static void aspeed_ltpi_top_write(void *opaque, hwaddr offset,
30 uint64_t val, unsigned size)
31 {
32 AspeedLTPIState *s = opaque;
33 uint32_t idx = offset >> 2;
34
35 switch (offset) {
36 default:
37 s->top_regs[idx] = (uint32_t)val;
38 break;
39 }
40 }
41
42 static const MemoryRegionOps aspeed_ltpi_top_ops = {
43 .read = aspeed_ltpi_top_read,
44 .write = aspeed_ltpi_top_write,
45 .endianness = DEVICE_LITTLE_ENDIAN,
46 .valid = {
47 .min_access_size = 1,
48 .max_access_size = 4,
49 },
50 };
51
52 static uint64_t aspeed_ltpi_phy_read(void *opaque, hwaddr offset, unsigned size)
53 {
54 AspeedLTPIState *s = opaque;
55 uint32_t idx = offset >> 2;
56
57 return s->phy_regs[idx];
58 }
59
60 static void aspeed_ltpi_phy_write(void *opaque, hwaddr offset,
61 uint64_t val, unsigned size)
62 {
63 AspeedLTPIState *s = opaque;
64 uint32_t idx = offset >> 2;
65
66 switch (offset) {
67 default:
68 s->phy_regs[idx] = (uint32_t)val;
69 break;
70 }
71 }
72
73 static const MemoryRegionOps aspeed_ltpi_phy_ops = {
74 .read = aspeed_ltpi_phy_read,
75 .write = aspeed_ltpi_phy_write,
76 .endianness = DEVICE_LITTLE_ENDIAN,
77 .valid = {
78 .min_access_size = 1,
79 .max_access_size = 4,
80 },
81 };
82
83 static uint64_t aspeed_ltpi_ctrl_read(void *opaque,
84 hwaddr offset, unsigned size)
85 {
86 AspeedLTPIState *s = opaque;
87 uint32_t idx = offset >> 2;
88
89 return s->ctrl_regs[idx];
90 }
91
92 static void aspeed_ltpi_ctrl_write(void *opaque, hwaddr offset,
93 uint64_t val, unsigned size)
94 {
95 AspeedLTPIState *s = opaque;
96 uint32_t idx = offset >> 2;
97
98 switch (offset) {
99 default:
100 s->ctrl_regs[idx] = (uint32_t)val;
101 break;
102 }
103 }
104
105 static const MemoryRegionOps aspeed_ltpi_ctrl_ops = {
106 .read = aspeed_ltpi_ctrl_read,
107 .write = aspeed_ltpi_ctrl_write,
108 .endianness = DEVICE_LITTLE_ENDIAN,
109 .valid = {
110 .min_access_size = 1,
111 .max_access_size = 4,
112 },
113 };
114
115 static void aspeed_ltpi_reset_hold(Object *obj, ResetType type)
116 {
117 AspeedLTPIState *s = ASPEED_LTPI(obj);
118
119 memset(s->ctrl_regs, 0, sizeof(s->ctrl_regs));
120 memset(s->phy_regs, 0, sizeof(s->phy_regs));
121 memset(s->top_regs, 0, sizeof(s->top_regs));
122 /* set default values */
123 s->ctrl_regs[LTPI_CTRL_LINK_MNG] = 0x11900007;
124 s->phy_regs[LTPI_PHY_MODE] = 0x2;
125 }
126
127
128 static const VMStateDescription vmstate_aspeed_ltpi = {
129 .name = TYPE_ASPEED_LTPI,
130 .version_id = 1,
131 .minimum_version_id = 1,
132 .fields = (VMStateField[]) {
133 VMSTATE_UINT32_ARRAY(ctrl_regs, AspeedLTPIState,
134 ASPEED_LTPI_CTRL_SIZE >> 2),
135 VMSTATE_UINT32_ARRAY(phy_regs, AspeedLTPIState,
136 ASPEED_LTPI_PHY_SIZE >> 2),
137 VMSTATE_UINT32_ARRAY(top_regs, AspeedLTPIState,
138 ASPEED_LTPI_TOP_SIZE >> 2),
139
140 VMSTATE_END_OF_LIST()
141 }
142 };
143
144 static void aspeed_ltpi_realize(DeviceState *dev, Error **errp)
145 {
146 AspeedLTPIState *s = ASPEED_LTPI(dev);
147
148 memory_region_init(&s->mmio, OBJECT(s), TYPE_ASPEED_LTPI,
149 ASPEED_LTPI_TOTAL_SIZE);
150
151 memory_region_init_io(&s->mmio_ctrl, OBJECT(s),
152 &aspeed_ltpi_ctrl_ops, s,
153 "aspeed-ltpi-ctrl", ASPEED_LTPI_CTRL_SIZE);
154
155 memory_region_init_io(&s->mmio_phy, OBJECT(s),
156 &aspeed_ltpi_phy_ops, s,
157 "aspeed-ltpi-phy", ASPEED_LTPI_PHY_SIZE);
158
159 memory_region_init_io(&s->mmio_top, OBJECT(s),
160 &aspeed_ltpi_top_ops, s,
161 "aspeed-ltpi-top", ASPEED_LTPI_TOP_SIZE);
162
163 memory_region_add_subregion(&s->mmio,
164 ASPEED_LTPI_CTRL_BASE, &s->mmio_ctrl);
165 memory_region_add_subregion(&s->mmio,
166 ASPEED_LTPI_PHY_BASE, &s->mmio_phy);
167 memory_region_add_subregion(&s->mmio,
168 ASPEED_LTPI_TOP_BASE, &s->mmio_top);
169
170 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
171 }
172
173 static void aspeed_ltpi_class_init(ObjectClass *klass, const void *data)
174 {
175 DeviceClass *dc = DEVICE_CLASS(klass);
176 ResettableClass *rc = RESETTABLE_CLASS(klass);
177 dc->realize = aspeed_ltpi_realize;
178 dc->vmsd = &vmstate_aspeed_ltpi;
179 rc->phases.hold = aspeed_ltpi_reset_hold;
180 }
181
182 static const TypeInfo aspeed_ltpi_types[] = {
183 {
184 .name = TYPE_ASPEED_LTPI,
185 .parent = TYPE_SYS_BUS_DEVICE,
186 .instance_size = sizeof(AspeedLTPIState),
187 .class_init = aspeed_ltpi_class_init,
188 }
189 };
190
191 DEFINE_TYPES(aspeed_ltpi_types)