master
c 243 lines 7.92 KB
Raw
1 /*
2 * Axiado SoC AX3000
3 *
4 * Author: Kuan-Jui Chiu <kchiu@axiado.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "qemu/osdep.h"
10 #include "system/address-spaces.h"
11 #include "hw/arm/bsa.h"
12 #include "hw/arm/ax3000-soc.h"
13 #include "hw/misc/unimp.h"
14 #include "system/system.h"
15 #include "qobject/qlist.h"
16 #include "qom/object.h"
17 #include "hw/core/boards.h"
18
19 static void ax3000_init(Object *obj)
20 {
21 Ax3000SoCState *s = AX3000_SOC(obj);
22 Ax3000SoCClass *sc = AX3000_SOC_GET_CLASS(s);
23
24 for (int i = 0; i < sc->num_cpus; i++) {
25 g_autofree char *name = g_strdup_printf("cpu%d", i);
26 object_initialize_child(obj, name, &s->cpu[i],
27 ARM_CPU_TYPE_NAME("cortex-a53"));
28 }
29
30 object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
31
32 for (int i = 0; i < AX3000_NUM_UARTS; i++) {
33 g_autofree char *name = g_strdup_printf("uart%d", i);
34 object_initialize_child(obj, name, &s->uart[i], TYPE_CADENCE_UART);
35 }
36
37 object_initialize_child(obj, "clk", &s->ax3000_clk, TYPE_AX3000_CLK);
38 object_initialize_child(obj, "sdhci0", &s->sdhci0, TYPE_AXIADO_SDHCI);
39
40 for (int i = 0; i < AX3000_NUM_GPIOS; i++) {
41 g_autofree char *name = g_strdup_printf("gpio%d", i);
42 object_initialize_child(obj, name, &s->gpio[i], TYPE_CADENCE_GPIO);
43 }
44 }
45
46 static void ax3000_realize(DeviceState *dev, Error **errp)
47 {
48 Ax3000SoCState *s = AX3000_SOC(dev);
49 Ax3000SoCClass *sc = AX3000_SOC_GET_CLASS(s);
50 SysBusDevice *gic_sbd = SYS_BUS_DEVICE(&s->gic);
51 DeviceState *gic_dev = DEVICE(&s->gic);
52 QList *redist_region_count;
53 SysBusDevice *sdhci0_sbd;
54 DeviceState *card;
55 DriveInfo *dinfo;
56
57 /* CPUs */
58 for (int i = 0; i < sc->num_cpus; i++) {
59 object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
60 &error_abort);
61
62 if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
63 object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
64 false, &error_abort);
65 }
66
67 if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
68 return;
69 }
70 }
71
72 /* GIC */
73 qdev_prop_set_uint32(gic_dev, "num-cpu", sc->num_cpus);
74 qdev_prop_set_uint32(gic_dev, "num-irq",
75 AX3000_NUM_IRQS + GIC_INTERNAL);
76
77 redist_region_count = qlist_new();
78 qlist_append_int(redist_region_count, sc->num_cpus);
79 qdev_prop_set_array(gic_dev, "redist-region-count", redist_region_count);
80
81 if (!sysbus_realize(gic_sbd, errp)) {
82 return;
83 }
84
85 sysbus_mmio_map(gic_sbd, 0, AX3000_GIC_DIST_BASE);
86 sysbus_mmio_map(gic_sbd, 1, AX3000_GIC_REDIST_BASE);
87
88 /*
89 * Mapping from the output timer irq lines from the CPU to the
90 * GIC PPI inputs.
91 */
92 const int timer_irqs[] = {
93 [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
94 [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
95 [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
96 [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ
97 };
98
99 /*
100 * Wire the outputs from each CPU's generic timer and the GICv3
101 * maintenance interrupt signal to the appropriate GIC PPI inputs, and
102 * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
103 */
104 for (int i = 0; i < sc->num_cpus; i++) {
105 DeviceState *cpu_dev = DEVICE(&s->cpu[i]);
106 int intidbase = AX3000_NUM_IRQS + i * GIC_INTERNAL;
107 qemu_irq irq;
108
109 for (int j = 0; j < ARRAY_SIZE(timer_irqs); j++) {
110 irq = qdev_get_gpio_in(gic_dev, intidbase + timer_irqs[j]);
111 qdev_connect_gpio_out(cpu_dev, j, irq);
112 }
113
114 irq = qdev_get_gpio_in(gic_dev, intidbase + ARCH_GIC_MAINT_IRQ);
115 qdev_connect_gpio_out_named(cpu_dev, "gicv3-maintenance-interrupt",
116 0, irq);
117
118 sysbus_connect_irq(gic_sbd, i,
119 qdev_get_gpio_in(cpu_dev, ARM_CPU_IRQ));
120 sysbus_connect_irq(gic_sbd, i + sc->num_cpus,
121 qdev_get_gpio_in(cpu_dev, ARM_CPU_FIQ));
122 sysbus_connect_irq(gic_sbd, i + 2 * sc->num_cpus,
123 qdev_get_gpio_in(cpu_dev, ARM_CPU_VIRQ));
124 sysbus_connect_irq(gic_sbd, i + 3 * sc->num_cpus,
125 qdev_get_gpio_in(cpu_dev, ARM_CPU_VFIQ));
126 }
127
128 /* DRAM */
129 const struct {
130 hwaddr addr;
131 size_t size;
132 const char *name;
133 } dram_table[] = {
134 { AX3000_DRAM0_BASE, AX3000_DRAM0_SIZE, "dram0" },
135 { AX3000_DRAM1_BASE, AX3000_DRAM1_SIZE, "dram1" }
136 };
137
138 for (int i = 0; i < AX3000_NUM_BANKS; i++) {
139 memory_region_init_ram(&s->dram[i], OBJECT(s), dram_table[i].name,
140 dram_table[i].size, &error_fatal);
141 memory_region_add_subregion(get_system_memory(), dram_table[i].addr,
142 &s->dram[i]);
143 }
144
145 /* UARTs */
146 const struct {
147 hwaddr addr;
148 unsigned int irq;
149 } serial_table[] = {
150 { AX3000_UART0_BASE, AX3000_UART0_IRQ },
151 { AX3000_UART1_BASE, AX3000_UART1_IRQ },
152 { AX3000_UART2_BASE, AX3000_UART2_IRQ },
153 { AX3000_UART3_BASE, AX3000_UART3_IRQ }
154 };
155
156 for (int i = 0; i < AX3000_NUM_UARTS; i++) {
157 qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
158 if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
159 return;
160 }
161
162 sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
163 sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
164 qdev_get_gpio_in(gic_dev, serial_table[i].irq));
165 }
166
167 /* Timer control */
168 create_unimplemented_device("ax3000.timerctrl", AX3000_TIMER_CTRL, 32);
169
170 /* Clock control */
171 if (!sysbus_realize(SYS_BUS_DEVICE(&s->ax3000_clk), errp)) {
172 return;
173 }
174 sysbus_mmio_map(SYS_BUS_DEVICE(&s->ax3000_clk), 0, AX3000_PLL_BASE);
175
176 /* SDHCI */
177 sdhci0_sbd = SYS_BUS_DEVICE(&s->sdhci0);
178 if (!sysbus_realize(sdhci0_sbd, errp)) {
179 return;
180 }
181
182 sysbus_mmio_map(sdhci0_sbd, 0, AX3000_SDHCI0_BASE);
183 sysbus_mmio_map(sdhci0_sbd, 1, AX3000_EMMC_PHY_BASE);
184 sysbus_connect_irq(sdhci0_sbd, 0,
185 qdev_get_gpio_in(gic_dev, AX3000_SDHCI0_IRQ));
186
187 dinfo = drive_get(IF_SD, 0, 0);
188 if (dinfo) {
189 card = qdev_new(TYPE_SD_CARD);
190 qdev_prop_set_drive_err(card, "drive",
191 blk_by_legacy_dinfo(dinfo),
192 &error_fatal);
193 qdev_realize_and_unref(card, s->sdhci0.sd_bus, &error_fatal);
194 }
195
196 /* GPIOs */
197 const struct {
198 hwaddr addr;
199 unsigned int irq;
200 } gpio_table[] = {
201 { AX3000_GPIO0_BASE, AX3000_GPIO0_IRQ },
202 { AX3000_GPIO1_BASE, AX3000_GPIO1_IRQ },
203 { AX3000_GPIO2_BASE, AX3000_GPIO2_IRQ },
204 { AX3000_GPIO3_BASE, AX3000_GPIO3_IRQ },
205 { AX3000_GPIO4_BASE, AX3000_GPIO4_IRQ },
206 { AX3000_GPIO5_BASE, AX3000_GPIO5_IRQ },
207 { AX3000_GPIO6_BASE, AX3000_GPIO6_IRQ },
208 { AX3000_GPIO7_BASE, AX3000_GPIO7_IRQ }
209 };
210
211 for (int i = 0; i < AX3000_NUM_GPIOS; i++) {
212 if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
213 return;
214 }
215
216 sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
217 sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
218 qdev_get_gpio_in(gic_dev, gpio_table[i].irq));
219 }
220 }
221
222 static void ax3000_class_init(ObjectClass *oc, const void *data)
223 {
224 DeviceClass *dc = DEVICE_CLASS(oc);
225 Ax3000SoCClass *sc = AX3000_SOC_CLASS(oc);
226
227 dc->desc = "Axiado SoC AX3000";
228 dc->realize = ax3000_realize;
229 sc->num_cpus = AX3000_NUM_CPUS;
230 }
231
232 static const TypeInfo axiado_soc_types[] = {
233 {
234 .name = TYPE_AX3000_SOC,
235 .parent = TYPE_SYS_BUS_DEVICE,
236 .instance_size = sizeof(Ax3000SoCState),
237 .instance_init = ax3000_init,
238 .class_init = ax3000_class_init,
239 .class_size = sizeof(Ax3000SoCClass),
240 }
241 };
242
243 DEFINE_TYPES(axiado_soc_types)