Skip to content

Commit 8a88b9f

Browse files
lbmengalistair23
authored andcommitted
hw/riscv: sifive_u: Hook a GPIO controller
SiFive FU540 SoC integrates a GPIO controller with 16 GPIO lines. This hooks the exsiting SiFive GPIO model to the SoC, and adds its device tree data as well. Signed-off-by: Bin Meng <[email protected]> Reviewed-by: Alistair Francis <[email protected]> Message-id: [email protected] Message-Id: <[email protected]> Signed-off-by: Alistair Francis <[email protected]>
1 parent 4bb216f commit 8a88b9f

File tree

2 files changed

+60
-2
lines changed

2 files changed

+60
-2
lines changed

hw/riscv/sifive_u.c

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
* 1) CLINT (Core Level Interruptor)
1212
* 2) PLIC (Platform Level Interrupt Controller)
1313
* 3) PRCI (Power, Reset, Clock, Interrupt)
14-
* 4) OTP (One-Time Programmable) memory with stored serial number
15-
* 5) GEM (Gigabit Ethernet Controller) and management block
14+
* 4) GPIO (General Purpose Input/Output Controller)
15+
* 5) OTP (One-Time Programmable) memory with stored serial number
16+
* 6) GEM (Gigabit Ethernet Controller) and management block
1617
*
1718
* This board currently generates devicetree dynamically that indicates at least
1819
* two harts and up to five harts.
@@ -75,6 +76,7 @@ static const struct MemmapEntry {
7576
[SIFIVE_U_PRCI] = { 0x10000000, 0x1000 },
7677
[SIFIVE_U_UART0] = { 0x10010000, 0x1000 },
7778
[SIFIVE_U_UART1] = { 0x10011000, 0x1000 },
79+
[SIFIVE_U_GPIO] = { 0x10060000, 0x1000 },
7880
[SIFIVE_U_OTP] = { 0x10070000, 0x1000 },
7981
[SIFIVE_U_FLASH0] = { 0x20000000, 0x10000000 },
8082
[SIFIVE_U_DRAM] = { 0x80000000, 0x0 },
@@ -268,6 +270,28 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
268270
g_free(cells);
269271
g_free(nodename);
270272

273+
nodename = g_strdup_printf("/soc/gpio@%lx",
274+
(long)memmap[SIFIVE_U_GPIO].base);
275+
qemu_fdt_add_subnode(fdt, nodename);
276+
qemu_fdt_setprop_cells(fdt, nodename, "clocks",
277+
prci_phandle, PRCI_CLK_TLCLK);
278+
qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 2);
279+
qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
280+
qemu_fdt_setprop_cell(fdt, nodename, "#gpio-cells", 2);
281+
qemu_fdt_setprop(fdt, nodename, "gpio-controller", NULL, 0);
282+
qemu_fdt_setprop_cells(fdt, nodename, "reg",
283+
0x0, memmap[SIFIVE_U_GPIO].base,
284+
0x0, memmap[SIFIVE_U_GPIO].size);
285+
qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_GPIO_IRQ0,
286+
SIFIVE_U_GPIO_IRQ1, SIFIVE_U_GPIO_IRQ2, SIFIVE_U_GPIO_IRQ3,
287+
SIFIVE_U_GPIO_IRQ4, SIFIVE_U_GPIO_IRQ5, SIFIVE_U_GPIO_IRQ6,
288+
SIFIVE_U_GPIO_IRQ7, SIFIVE_U_GPIO_IRQ8, SIFIVE_U_GPIO_IRQ9,
289+
SIFIVE_U_GPIO_IRQ10, SIFIVE_U_GPIO_IRQ11, SIFIVE_U_GPIO_IRQ12,
290+
SIFIVE_U_GPIO_IRQ13, SIFIVE_U_GPIO_IRQ14, SIFIVE_U_GPIO_IRQ15);
291+
qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
292+
qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,gpio0");
293+
g_free(nodename);
294+
271295
phy_phandle = phandle++;
272296
nodename = g_strdup_printf("/soc/ethernet@%lx",
273297
(long)memmap[SIFIVE_U_GEM].base);
@@ -515,6 +539,7 @@ static void sifive_u_soc_instance_init(Object *obj)
515539
object_initialize_child(obj, "prci", &s->prci, TYPE_SIFIVE_U_PRCI);
516540
object_initialize_child(obj, "otp", &s->otp, TYPE_SIFIVE_U_OTP);
517541
object_initialize_child(obj, "gem", &s->gem, TYPE_CADENCE_GEM);
542+
object_initialize_child(obj, "gpio", &s->gpio, TYPE_SIFIVE_GPIO);
518543
}
519544

520545
static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
@@ -600,6 +625,20 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
600625
sysbus_realize(SYS_BUS_DEVICE(&s->prci), &err);
601626
sysbus_mmio_map(SYS_BUS_DEVICE(&s->prci), 0, memmap[SIFIVE_U_PRCI].base);
602627

628+
qdev_prop_set_uint32(DEVICE(&s->gpio), "ngpio", 16);
629+
sysbus_realize(SYS_BUS_DEVICE(&s->gpio), &err);
630+
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, memmap[SIFIVE_U_GPIO].base);
631+
632+
/* Pass all GPIOs to the SOC layer so they are available to the board */
633+
qdev_pass_gpios(DEVICE(&s->gpio), dev, NULL);
634+
635+
/* Connect GPIO interrupts to the PLIC */
636+
for (i = 0; i < 16; i++) {
637+
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), i,
638+
qdev_get_gpio_in(DEVICE(s->plic),
639+
SIFIVE_U_GPIO_IRQ0 + i));
640+
}
641+
603642
qdev_prop_set_uint32(DEVICE(&s->otp), "serial", s->serial);
604643
sysbus_realize(SYS_BUS_DEVICE(&s->otp), &err);
605644
sysbus_mmio_map(SYS_BUS_DEVICE(&s->otp), 0, memmap[SIFIVE_U_OTP].base);

include/hw/riscv/sifive_u.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "hw/net/cadence_gem.h"
2323
#include "hw/riscv/riscv_hart.h"
2424
#include "hw/riscv/sifive_cpu.h"
25+
#include "hw/riscv/sifive_gpio.h"
2526
#include "hw/riscv/sifive_u_prci.h"
2627
#include "hw/riscv/sifive_u_otp.h"
2728

@@ -40,6 +41,7 @@ typedef struct SiFiveUSoCState {
4041
RISCVHartArrayState u_cpus;
4142
DeviceState *plic;
4243
SiFiveUPRCIState prci;
44+
SIFIVEGPIOState gpio;
4345
SiFiveUOTPState otp;
4446
CadenceGEMState gem;
4547

@@ -73,6 +75,7 @@ enum {
7375
SIFIVE_U_PRCI,
7476
SIFIVE_U_UART0,
7577
SIFIVE_U_UART1,
78+
SIFIVE_U_GPIO,
7679
SIFIVE_U_OTP,
7780
SIFIVE_U_FLASH0,
7881
SIFIVE_U_DRAM,
@@ -83,6 +86,22 @@ enum {
8386
enum {
8487
SIFIVE_U_UART0_IRQ = 4,
8588
SIFIVE_U_UART1_IRQ = 5,
89+
SIFIVE_U_GPIO_IRQ0 = 7,
90+
SIFIVE_U_GPIO_IRQ1 = 8,
91+
SIFIVE_U_GPIO_IRQ2 = 9,
92+
SIFIVE_U_GPIO_IRQ3 = 10,
93+
SIFIVE_U_GPIO_IRQ4 = 11,
94+
SIFIVE_U_GPIO_IRQ5 = 12,
95+
SIFIVE_U_GPIO_IRQ6 = 13,
96+
SIFIVE_U_GPIO_IRQ7 = 14,
97+
SIFIVE_U_GPIO_IRQ8 = 15,
98+
SIFIVE_U_GPIO_IRQ9 = 16,
99+
SIFIVE_U_GPIO_IRQ10 = 17,
100+
SIFIVE_U_GPIO_IRQ11 = 18,
101+
SIFIVE_U_GPIO_IRQ12 = 19,
102+
SIFIVE_U_GPIO_IRQ13 = 20,
103+
SIFIVE_U_GPIO_IRQ14 = 21,
104+
SIFIVE_U_GPIO_IRQ15 = 22,
86105
SIFIVE_U_GEM_IRQ = 0x35
87106
};
88107

0 commit comments

Comments
 (0)