1#include "qemu/osdep.h"
2#include "hw/fdt_generic_util.h"
3#include "hw/fdt_generic_devices.h"
4#include "qom/object.h"
5#include "sysemu/blockdev.h"
6#include "exec/memory.h"
7#include "exec/address-spaces.h"
8#include "qemu/log.h"
9#include "qapi/error.h"
10#include "sysemu/char.h"
11#include "qemu/coroutine.h"
12#include "qapi-types.h"
13
14#include "hw/char/serial.h"
15#include "hw/block/flash.h"
16#include "hw/qdev-core.h"
17
18#define FLASH_SECTOR_SIZE (64 * 1024)
19
20
21
22
23
24
25
26
27
28
29#ifndef FDT_GENERIC_UTIL_ERR_DEBUG
30#define FDT_GENERIC_UTIL_ERR_DEBUG 0
31#endif
32#define DB_PRINT(lvl, ...) do { \
33 if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
34 qemu_log_mask(lvl, ": %s: ", __func__); \
35 qemu_log_mask(lvl, ## __VA_ARGS__); \
36 } \
37} while (0);
38
39#define DB_PRINT_NP(lvl, ...) do { \
40 if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
41 qemu_log_mask(lvl, "%s", node_path); \
42 DB_PRINT((lvl), ## __VA_ARGS__); \
43 } \
44} while (0);
45
46int fdt_generic_num_cpus;
47
48int pflash_cfi01_fdt_init(char *node_path, FDTMachineInfo *fdti, void *opaque)
49{
50
51 uint32_t flash_base = 0;
52 uint32_t flash_size = 0;
53
54 DriveInfo *dinfo;
55 uint32_t bank_width;
56
57
58 flash_base = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 0,
59 false, &error_abort);
60 flash_size = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 1,
61 false, &error_abort);
62 bank_width = qemu_fdt_getprop_cell(fdti->fdt, node_path, "bank-width",
63 0, false, &error_abort);
64
65 DB_PRINT_NP(0, "FLASH: baseaddr: 0x%x, size: 0x%x\n",
66 flash_base, flash_size);
67
68 dinfo = drive_get_next(IF_PFLASH);
69 pflash_cfi01_register(flash_base, NULL, node_path, flash_size,
70 dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
71 FLASH_SECTOR_SIZE, flash_size/FLASH_SECTOR_SIZE,
72 bank_width, 0x89, 0x18, 0x0000, 0x0, 0);
73 return 0;
74}
75
76static int uart16550_fdt_init(char *node_path, FDTMachineInfo *fdti,
77 void *priv)
78{
79
80 MemoryRegion *address_space_mem = get_system_memory();
81 hwaddr base;
82 uint32_t baudrate;
83 qemu_irq irqline;
84 bool map_mode;
85 char irq_info[1024];
86 Error *err = NULL;
87
88
89 base = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 0,
90 false, &error_abort);
91 base += qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg-offset", 0,
92 false, &error_abort);
93 base &= ~3ULL;
94
95 baudrate = qemu_fdt_getprop_cell(fdti->fdt, node_path, "current-speed",
96 0, false, &err);
97 if (err) {
98 baudrate = 115200;
99 }
100
101 irqline = *fdt_get_irq_info(fdti, node_path, 0, irq_info, &map_mode);
102 assert(!map_mode);
103 DB_PRINT_NP(0, "UART16550a: baseaddr: 0x" TARGET_FMT_plx
104 ", irq: %s, baud %d\n", base, irq_info, baudrate);
105
106
107 serial_mm_init(address_space_mem, base, 2, irqline, baudrate,
108 qemu_char_get_next_serial(), DEVICE_LITTLE_ENDIAN);
109 return 0;
110}
111
112static int i2c_bus_fdt_init(char *node_path, FDTMachineInfo *fdti, void *priv)
113{
114 Object *parent;
115 DeviceState *dev;
116 char parent_node_path[DT_PATH_LENGTH];
117 char *node_name = qemu_devtree_get_node_name(fdti->fdt, node_path);
118
119 DB_PRINT_NP(1, "\n");
120
121 if (qemu_devtree_getparent(fdti->fdt, parent_node_path, node_path)) {
122 abort();
123 }
124 while (!fdt_init_has_opaque(fdti, parent_node_path)) {
125 fdt_init_yield(fdti);
126 }
127 parent = fdt_init_get_opaque(fdti, parent_node_path);
128 dev = (DeviceState *)object_dynamic_cast(parent, TYPE_DEVICE);
129 if (parent && dev) {
130 while (!dev->realized) {
131 fdt_init_yield(fdti);
132 }
133 DB_PRINT_NP(0, "parenting i2c bus to %s bus %s\n", parent_node_path,
134 node_name);
135 fdt_init_set_opaque(fdti, node_path,
136 qdev_get_child_bus(dev, node_name));
137 } else {
138 DB_PRINT_NP(0, "orphaning i2c bus\n");
139 }
140 return 0;
141}
142
143static int sysmem_fdt_init(char *node_path, FDTMachineInfo *fdti,
144 void *priv)
145{
146 fdt_init_set_opaque(fdti, node_path, OBJECT(get_system_memory()));
147 return 0;
148}
149
150static inline void razwi_unimp_rw(void *opaque, hwaddr addr, uint64_t val64,
151 unsigned int size, bool rnw) {
152 char str[1024];
153
154 snprintf(str, sizeof(str), "%s: RAZ/WI device %s: addr: %#llx data: %#llx"
155 " size: %d\n",
156 opaque ? (const char *)opaque : "(none)", rnw ? "read" : "write",
157 (unsigned long long)addr, (unsigned long long)val64, size);
158
159 DB_PRINT(0, "%s", str);
160 qemu_log_mask(LOG_UNIMP, "%s", str);
161}
162
163fdt_register_compatibility(sysmem_fdt_init, "compatible:qemu:system-memory");
164fdt_register_compatibility_n(uart16550_fdt_init, "compatible:ns16550", 0);
165fdt_register_compatibility_n(uart16550_fdt_init, "compatible:ns16550a", 1);
166
167static const void *null;
168
169fdt_register_compatibility_n(null, "compatible:marvell,88e1111", 1);
170fdt_register_compatibility_n(null, "compatible:arm,pl310-cache", 2);
171fdt_register_compatibility_n(null, "compatible:xlnx,ps7-cortexa9-1.00.a", 3);
172fdt_register_compatibility_n(null, "compatible:xlnx,zynq_remoteproc", 4);
173fdt_register_compatibility_n(null, "compatible:xlnx,ps7-smcc-1.00.a", 5);
174fdt_register_compatibility_n(null, "compatible:xlnx,ps7-smc", 6);
175fdt_register_compatibility_n(null, "compatible:xlnx,ps7-nand-1.00.a", 7);
176fdt_register_compatibility_n(null, "compatible:xlnx,ps7-ram-1.00.a", 8);
177fdt_register_compatibility_n(null, "compatible:xlnx,ps7-ocm", 9);
178fdt_register_compatibility_n(null, "compatible:marvell,88e1118r", 10);
179fdt_register_compatibility_n(null, "compatible:xlnx,ps7-clkc", 11);
180fdt_register_compatibility_n(null, "compatible:xlnx,ps7-ddrc", 12);
181fdt_register_compatibility_n(null, "compatible:xlnx,ps7-scuc-1.00.a", 13);
182fdt_register_compatibility_n(null, "compatible:fixed-clock", 14);
183fdt_register_compatibility_n(null, "compatible:xlnx,pinctrl-zynq", 15);
184fdt_register_compatibility_n(null, "compatible:ulpi-phy", 16);
185fdt_register_compatibility_n(null, "compatible:xlnx,zynq-efuse", 17);
186fdt_register_compatibility_n(null, "compatible:qemu:memory-region-spec", 18);
187
188fdt_register_instance_n(i2c_bus_fdt_init, "i2c@0", 0);
189fdt_register_instance_n(i2c_bus_fdt_init, "i2c@1", 1);
190fdt_register_instance_n(i2c_bus_fdt_init, "i2c@2", 2);
191fdt_register_instance_n(i2c_bus_fdt_init, "i2c@3", 3);
192fdt_register_instance_n(i2c_bus_fdt_init, "i2c@4", 4);
193fdt_register_instance_n(i2c_bus_fdt_init, "i2c@5", 5);
194fdt_register_instance_n(i2c_bus_fdt_init, "i2c@6", 6);
195fdt_register_instance_n(i2c_bus_fdt_init, "i2c@7", 7);
196
197static const TypeInfo fdt_qom_aliases [] = {
198 { .name = "xlnx.ps7-ethernet", .parent = "cadence_gem" },
199 { .name = "cdns,gem", .parent = "cadence_gem" },
200 { .name = "cdns,zynq-gem", .parent = "cadence_gem" },
201 { .name = "cdns,zynqmp-gem", .parent = "cadence_gem" },
202 { .name = "xlnx.ps7-ttc", .parent = "cadence_ttc" },
203 { .name = "cdns.ttc", .parent = "cadence_ttc" },
204 { .name = "cdns.uart", .parent = "cadence_uart" },
205 { .name = "xlnx.ps7-uart", .parent = "cadence_uart" },
206 { .name = "silabs,si570", .parent = "si57x" },
207
208
209
210#ifdef CONFIG_USB_EHCI_SYSBUS
211 { .name = "xlnx.ps7-usb", .parent = "xlnx,ps7-usb" },
212 { .name = "xlnx.zynq-usb", .parent = "xlnx,ps7-usb" },
213#endif
214 { .name = "xlnx.zynq-qspi", .parent = "xlnx.ps7-qspi" },
215 { .name = "xlnx.xuartps", .parent = "cadence_uart" },
216 { .name = "simple-bus", .parent = "qemu:memory-region" },
217 { .name = "xlnx,axi-dpdma-1.0", .parent = "xlnx.dpdma" },
218 { .name = "xlnx,xps-gpio-1.00.a", .parent = "xlnx.axi-gpio" },
219 { .name = "arasan,sdhci-8.9a", .parent = "xilinx.zynqmp-sdhci" },
220 { .name = "cdns.spi-r1p6", .parent = "xlnx.ps7-spi" },
221 { .name = "xlnx,eth-dma", .parent = "xlnx.axi-dma" },
222};
223
224static void fdt_generic_register_types(void)
225{
226 int i;
227
228 for (i = 0; i < ARRAY_SIZE(fdt_qom_aliases); ++i) {
229 type_register_static(&fdt_qom_aliases[i]);
230 }
231}
232
233type_init(fdt_generic_register_types)
234