1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "qemu/osdep.h"
27#include "hw/sysbus.h"
28#include "qemu/log.h"
29
30#include "qemu/bitops.h"
31#include "qapi/qmp/qerror.h"
32#include "hw/register-dep.h"
33#include "hw/fdt_generic_util.h"
34
35#ifndef ZYNQMP_IOU_SLCR_ERR_DEBUG
36#define ZYNQMP_IOU_SLCR_ERR_DEBUG 0
37#endif
38
39#define TYPE_ZYNQMP_IOU_SLCR "xilinx.zynqmp-iou-slcr"
40
41#define ZYNQMP_IOU_SLCR(obj) \
42 OBJECT_CHECK(ZynqMPIOUSLCR, (obj), TYPE_ZYNQMP_IOU_SLCR)
43
44DEP_REG32(MIO, 0x0)
45 #define R_MIO_RSVD 0xffffff01
46DEP_REG32(BANK0_CTRL0, 0x138)
47 DEP_FIELD(BANK0_CTRL0, DRIVE0, 26, 0)
48DEP_REG32(BANK0_CTRL1, 0x13c)
49 DEP_FIELD(BANK0_CTRL1, DRIVE1, 26, 0)
50DEP_REG32(BANK0_CTRL3, 0x140)
51 DEP_FIELD(BANK0_CTRL3, SCHMITT_CMOS_N, 26, 0)
52DEP_REG32(BANK0_CTRL4, 0x144)
53 DEP_FIELD(BANK0_CTRL4, PULL_HIGH_LOW_N, 26, 0)
54DEP_REG32(BANK0_CTRL5, 0x148)
55 DEP_FIELD(BANK0_CTRL5, PULL_ENABLE, 26, 0)
56DEP_REG32(BANK0_CTRL6, 0x14c)
57 DEP_FIELD(BANK0_CTRL6, SLOW_FAST_SLEW_N, 26, 0)
58DEP_REG32(BANK0_STATUS, 0x150)
59 DEP_FIELD(BANK0_STATUS, VOLTAGE_MODE, 1, 0)
60DEP_REG32(BANK1_CTRL0, 0x154)
61 DEP_FIELD(BANK1_CTRL0, DRIVE0, 26, 0)
62DEP_REG32(BANK1_CTRL1, 0x158)
63 DEP_FIELD(BANK1_CTRL1, DRIVE1, 26, 0)
64DEP_REG32(BANK1_CTRL3, 0x15c)
65 DEP_FIELD(BANK1_CTRL3, SCHMITT_CMOS_N, 26, 0)
66DEP_REG32(BANK1_CTRL4, 0x160)
67 DEP_FIELD(BANK1_CTRL4, PULL_HIGH_LOW_N, 26, 0)
68DEP_REG32(BANK1_CTRL5, 0x164)
69 DEP_FIELD(BANK1_CTRL5, PULL_ENABLE_13_TO_0, 14, 12)
70 DEP_FIELD(BANK1_CTRL5, PULL_ENABLE_25_TO_14, 12, 0)
71DEP_REG32(BANK1_CTRL6, 0x168)
72 DEP_FIELD(BANK1_CTRL6, SLOW_FAST_SLEW_N, 26, 0)
73DEP_REG32(BANK1_STATUS, 0x16c)
74 DEP_FIELD(BANK1_STATUS, VOLTAGE_MODE, 1, 0)
75DEP_REG32(BANK2_CTRL0, 0x170)
76 DEP_FIELD(BANK2_CTRL0, DRIVE0, 26, 0)
77DEP_REG32(BANK2_CTRL1, 0x174)
78 DEP_FIELD(BANK2_CTRL1, DRIVE1, 26, 0)
79DEP_REG32(BANK2_CTRL3, 0x178)
80 DEP_FIELD(BANK2_CTRL3, SCHMITT_CMOS_N, 26, 0)
81DEP_REG32(BANK2_CTRL4, 0x17c)
82 DEP_FIELD(BANK2_CTRL4, PULL_HIGH_LOW_N, 26, 0)
83DEP_REG32(BANK2_CTRL5, 0x180)
84 DEP_FIELD(BANK2_CTRL5, PULL_ENABLE, 26, 0)
85DEP_REG32(BANK2_CTRL6, 0x184)
86 DEP_FIELD(BANK2_CTRL6, SLOW_FAST_SLEW_N, 26, 0)
87DEP_REG32(BANK2_STATUS, 0x188)
88 DEP_FIELD(BANK2_STATUS, VOLTAGE_MODE, 1, 0)
89DEP_REG32(SD_SLOTTYPE, 0x310)
90 #define R_SD_SLOTTYPE_RSVD 0xffffff9c
91
92#define R_MAX ((R_SD_SLOTTYPE) + 1)
93
94typedef struct ZynqMPIOUSLCR ZynqMPIOUSLCR;
95
96struct ZynqMPIOUSLCR {
97 SysBusDevice busdev;
98 MemoryRegion iomem;
99
100 bool mio_bank0v;
101 bool mio_bank1v;
102 bool mio_bank2v;
103 uint32_t regs[R_MAX];
104 DepRegisterInfo regs_info[R_MAX];
105};
106
107static const DepRegisterAccessInfo zynqmp_iou_slcr_regs_info[] = {
108#define M(x) \
109 { .name = "MIO" #x, .decode.addr = A_MIO + 4 * x, \
110 .rsvd = R_MIO_RSVD, \
111 },
112 M( 0) M( 1) M( 2) M( 3) M( 4) M( 5) M( 6) M( 7) M( 8) M( 9)
113 M(10) M(11) M(12) M(13) M(14) M(15) M(16) M(17) M(18) M(19)
114 M(20) M(21) M(22) M(23) M(24) M(25) M(26) M(27) M(28) M(29)
115 M(30) M(31) M(32) M(33) M(34) M(35) M(36) M(37) M(38) M(39)
116 M(40) M(41) M(42) M(43) M(44) M(45) M(46) M(47) M(48) M(49)
117 M(50) M(51) M(52) M(53) M(54) M(55) M(56) M(57) M(58) M(59)
118 M(60) M(61) M(62) M(63) M(64) M(65) M(66) M(67) M(78) M(69)
119 M(70) M(71) M(72) M(73) M(74) M(75) M(76) M(77)
120#undef M
121 { .name = "BANK0_CTRL0", .decode.addr = A_BANK0_CTRL0,
122 .reset = 0x3ffffff,
123 },{ .name = "BANK0_CTRL1", .decode.addr = A_BANK0_CTRL1,
124 },{ .name = "BANK0_CTRL3", .decode.addr = A_BANK0_CTRL3,
125 },{ .name = "BANK0_CTRL4", .decode.addr = A_BANK0_CTRL4,
126 .reset = 0x3ffffff,
127 },{ .name = "BANK0_CTRL5", .decode.addr = A_BANK0_CTRL5,
128 .reset = 0x3ffffff,
129 },{ .name = "BANK0_CTRL6", .decode.addr = A_BANK0_CTRL6,
130 },{ .name = "BANK0_STATUS", .decode.addr = A_BANK0_STATUS,
131 .ro = 0x1,
132 },{ .name = "BANK1_CTRL0", .decode.addr = A_BANK1_CTRL0,
133 .reset = 0x3ffffff,
134 },{ .name = "BANK1_CTRL1", .decode.addr = A_BANK1_CTRL1,
135 },{ .name = "BANK1_CTRL3", .decode.addr = A_BANK1_CTRL3,
136 },{ .name = "BANK1_CTRL4", .decode.addr = A_BANK1_CTRL4,
137 .reset = 0x3ffffff,
138 },{ .name = "BANK1_CTRL5", .decode.addr = A_BANK1_CTRL5,
139 .reset = 0x3ffffff,
140 },{ .name = "BANK1_CTRL6", .decode.addr = A_BANK1_CTRL6,
141 },{ .name = "BANK1_STATUS", .decode.addr = A_BANK1_STATUS,
142 .ro = 0x1,
143 },{ .name = "BANK2_CTRL0", .decode.addr = A_BANK2_CTRL0,
144 .reset = 0x3ffffff,
145 },{ .name = "BANK2_CTRL1", .decode.addr = A_BANK2_CTRL1,
146 },{ .name = "BANK2_CTRL3", .decode.addr = A_BANK2_CTRL3,
147 },{ .name = "BANK2_CTRL4", .decode.addr = A_BANK2_CTRL4,
148 .reset = 0x3ffffff,
149 },{ .name = "BANK2_CTRL5", .decode.addr = A_BANK2_CTRL5,
150 .reset = 0x3ffffff,
151 },{ .name = "BANK2_CTRL6", .decode.addr = A_BANK2_CTRL6,
152 },{ .name = "BANK2_STATUS", .decode.addr = A_BANK2_STATUS,
153 .ro = 0x1,
154 },
155 { .name = "SD Slot TYPE", .decode.addr = A_SD_SLOTTYPE,
156 .rsvd = R_SD_SLOTTYPE_RSVD,
157 .gpios = (DepRegisterGPIOMapping []) {
158 { .name = "SD0_SLOTTYPE", .bit_pos = 0, .width = 2 },
159 { .name = "SD1_SLOTTYPE", .bit_pos = 15, .width = 2 },
160 {},
161 }
162 }
163};
164
165static void zynqmp_iou_slcr_reset(DeviceState *dev)
166{
167 ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(dev);
168 int i;
169
170 for (i = 0; i < R_MAX; ++i) {
171 dep_register_reset(&s->regs_info[i]);
172 }
173 DEP_AF_DP32(s->regs, BANK0_STATUS, VOLTAGE_MODE, s->mio_bank0v);
174 DEP_AF_DP32(s->regs, BANK1_STATUS, VOLTAGE_MODE, s->mio_bank1v);
175 DEP_AF_DP32(s->regs, BANK2_STATUS, VOLTAGE_MODE, s->mio_bank2v);
176}
177
178static const MemoryRegionOps zynqmp_iou_slcr_ops = {
179 .read = dep_register_read_memory_le,
180 .write = dep_register_write_memory_le,
181 .endianness = DEVICE_LITTLE_ENDIAN,
182 .valid = {
183 .min_access_size = 4,
184 .max_access_size = 4,
185 }
186};
187
188static void zynqmp_iou_slcr_realize(DeviceState *dev, Error **errp)
189{
190 ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(dev);
191 const char *prefix = object_get_canonical_path(OBJECT(dev));
192 int i;
193
194 for (i = 0; i < ARRAY_SIZE(zynqmp_iou_slcr_regs_info); ++i) {
195 DepRegisterInfo *r = &s->regs_info[i];
196
197 *r = (DepRegisterInfo) {
198 .data = (uint8_t *)&s->regs[
199 zynqmp_iou_slcr_regs_info[i].decode.addr/4],
200 .data_size = sizeof(uint32_t),
201 .access = &zynqmp_iou_slcr_regs_info[i],
202 .debug = ZYNQMP_IOU_SLCR_ERR_DEBUG,
203 .prefix = prefix,
204 .opaque = s,
205 };
206 dep_register_init(r);
207 qdev_pass_all_gpios(DEVICE(r), dev);
208
209 memory_region_init_io(&r->mem, OBJECT(dev), &zynqmp_iou_slcr_ops, r,
210 r->access->name, 4);
211 memory_region_add_subregion(&s->iomem, r->access->decode.addr, &r->mem);
212 }
213 return;
214}
215
216static void zynqmp_iou_slcr_init(Object *obj)
217{
218 ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(obj);
219
220 memory_region_init(&s->iomem, obj, "MMIO", R_MAX * 4);
221 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
222}
223
224static const VMStateDescription vmstate_zynqmp_iou_slcr = {
225 .name = "zynqmp_iou_slcr",
226 .version_id = 1,
227 .minimum_version_id = 1,
228 .minimum_version_id_old = 1,
229 .fields = (VMStateField[]) {
230 VMSTATE_UINT32_ARRAY(regs, ZynqMPIOUSLCR, R_MAX),
231 VMSTATE_END_OF_LIST(),
232 }
233};
234
235static const FDTGenericGPIOSet zynqmp_iou_slcr_controller_gpios [] = {
236 {
237
238 .names = &fdt_generic_gpio_name_set_gpio,
239 .gpios = (FDTGenericGPIOConnection []) {
240 { .name = "SD0_SLOTTYPE", .fdt_index = 0 },
241 { .name = "SD1_SLOTTYPE", .fdt_index = 1 },
242 { },
243 },
244 },
245 { },
246};
247
248static Property zynqmp_iou_slcr_props[] = {
249 DEFINE_PROP_BOOL("mio-bank0-1.8v", ZynqMPIOUSLCR, mio_bank0v, false),
250 DEFINE_PROP_BOOL("mio-bank1-1.8v", ZynqMPIOUSLCR, mio_bank1v, false),
251 DEFINE_PROP_BOOL("mio-bank2-1.8v", ZynqMPIOUSLCR, mio_bank2v, false),
252 DEFINE_PROP_END_OF_LIST(),
253};
254
255static void zynqmp_iou_slcr_class_init(ObjectClass *klass, void *data)
256{
257 DeviceClass *dc = DEVICE_CLASS(klass);
258 FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
259
260 dc->reset = zynqmp_iou_slcr_reset;
261 dc->realize = zynqmp_iou_slcr_realize;
262 dc->vmsd = &vmstate_zynqmp_iou_slcr;
263 dc->props = zynqmp_iou_slcr_props;
264
265 fggc->controller_gpios = zynqmp_iou_slcr_controller_gpios;
266}
267
268static const TypeInfo zynqmp_iou_slcr_info = {
269 .name = TYPE_ZYNQMP_IOU_SLCR,
270 .parent = TYPE_SYS_BUS_DEVICE,
271 .instance_size = sizeof(ZynqMPIOUSLCR),
272 .class_init = zynqmp_iou_slcr_class_init,
273 .instance_init = zynqmp_iou_slcr_init,
274 .interfaces = (InterfaceInfo[]) {
275 { TYPE_FDT_GENERIC_GPIO },
276 { },
277 }
278};
279
280static void zynqmp_iou_slcr_register_types(void)
281{
282 type_register_static(&zynqmp_iou_slcr_info);
283}
284
285type_init(zynqmp_iou_slcr_register_types)
286