2 * Altera 10M50 Nios2 GHRD
4 * Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
6 * Based on LabX device code
8 * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see
22 * <http://www.gnu.org/licenses/lgpl-2.1.html>
25 #include "qemu/osdep.h"
26 #include "qapi/error.h"
28 #include "hw/sysbus.h"
29 #include "hw/char/serial.h"
30 #include "hw/intc/nios2_vic.h"
31 #include "hw/qdev-properties.h"
32 #include "sysemu/sysemu.h"
33 #include "hw/boards.h"
34 #include "exec/memory.h"
35 #include "exec/address-spaces.h"
36 #include "qemu/config-file.h"
40 struct Nios2MachineState
{
41 MachineState parent_obj
;
43 MemoryRegion phys_tcm
;
44 MemoryRegion phys_tcm_alias
;
45 MemoryRegion phys_ram
;
46 MemoryRegion phys_ram_alias
;
51 #define TYPE_NIOS2_MACHINE MACHINE_TYPE_NAME("10m50-ghrd")
52 OBJECT_DECLARE_TYPE(Nios2MachineState
, MachineClass
, NIOS2_MACHINE
)
54 #define BINARY_DEVICE_TREE_FILE "10m50-devboard.dtb"
56 static void nios2_10m50_ghrd_init(MachineState
*machine
)
58 Nios2MachineState
*nms
= NIOS2_MACHINE(machine
);
61 MemoryRegion
*address_space_mem
= get_system_memory();
62 ram_addr_t tcm_base
= 0x0;
63 ram_addr_t tcm_size
= 0x1000; /* 1 kiB, but QEMU limit is 4 kiB */
64 ram_addr_t ram_base
= 0x08000000;
65 ram_addr_t ram_size
= 0x08000000;
69 /* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */
70 memory_region_init_ram(&nms
->phys_tcm
, NULL
, "nios2.tcm", tcm_size
,
72 memory_region_init_alias(&nms
->phys_tcm_alias
, NULL
, "nios2.tcm.alias",
73 &nms
->phys_tcm
, 0, tcm_size
);
74 memory_region_add_subregion(address_space_mem
, tcm_base
, &nms
->phys_tcm
);
75 memory_region_add_subregion(address_space_mem
, 0xc0000000 + tcm_base
,
76 &nms
->phys_tcm_alias
);
78 /* Physical DRAM with alias at 0xc0000000 */
79 memory_region_init_ram(&nms
->phys_ram
, NULL
, "nios2.ram", ram_size
,
81 memory_region_init_alias(&nms
->phys_ram_alias
, NULL
, "nios2.ram.alias",
82 &nms
->phys_ram
, 0, ram_size
);
83 memory_region_add_subregion(address_space_mem
, ram_base
, &nms
->phys_ram
);
84 memory_region_add_subregion(address_space_mem
, 0xc0000000 + ram_base
,
85 &nms
->phys_ram_alias
);
87 /* Create CPU. We need to set eic_present between init and realize. */
88 cpu
= NIOS2_CPU(object_new(TYPE_NIOS2_CPU
));
90 /* Enable the External Interrupt Controller within the CPU. */
91 cpu
->eic_present
= nms
->vic
;
93 /* Configure new exception vectors. */
94 cpu
->reset_addr
= 0xd4000000;
95 cpu
->exception_addr
= 0xc8000120;
96 cpu
->fast_tlb_miss_addr
= 0xc0000100;
98 qdev_realize_and_unref(DEVICE(cpu
), NULL
, &error_fatal
);
101 DeviceState
*dev
= qdev_new(TYPE_NIOS2_VIC
);
102 MemoryRegion
*dev_mr
;
105 object_property_set_link(OBJECT(dev
), "cpu", OBJECT(cpu
), &error_fatal
);
106 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
108 cpu_irq
= qdev_get_gpio_in_named(DEVICE(cpu
), "EIC", 0);
109 sysbus_connect_irq(SYS_BUS_DEVICE(dev
), 0, cpu_irq
);
110 for (int i
= 0; i
< 32; i
++) {
111 irq
[i
] = qdev_get_gpio_in(dev
, i
);
114 dev_mr
= sysbus_mmio_get_region(SYS_BUS_DEVICE(dev
), 0);
115 memory_region_add_subregion(address_space_mem
, 0x18002000, dev_mr
);
117 for (i
= 0; i
< 32; i
++) {
118 irq
[i
] = qdev_get_gpio_in_named(DEVICE(cpu
), "IRQ", i
);
122 /* Register: Altera 16550 UART */
123 serial_mm_init(address_space_mem
, 0xf8001600, 2, irq
[1], 115200,
124 serial_hd(0), DEVICE_NATIVE_ENDIAN
);
126 /* Register: Timer sys_clk_timer */
127 dev
= qdev_new("ALTR.timer");
128 qdev_prop_set_uint32(dev
, "clock-frequency", 75 * 1000000);
129 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
130 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, 0xf8001440);
131 sysbus_connect_irq(SYS_BUS_DEVICE(dev
), 0, irq
[0]);
133 /* Register: Timer sys_clk_timer_1 */
134 dev
= qdev_new("ALTR.timer");
135 qdev_prop_set_uint32(dev
, "clock-frequency", 75 * 1000000);
136 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
137 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, 0xe0000880);
138 sysbus_connect_irq(SYS_BUS_DEVICE(dev
), 0, irq
[5]);
140 nios2_load_kernel(cpu
, ram_base
, ram_size
, machine
->initrd_filename
,
141 BINARY_DEVICE_TREE_FILE
, NULL
);
144 static bool get_vic(Object
*obj
, Error
**errp
)
146 Nios2MachineState
*nms
= NIOS2_MACHINE(obj
);
150 static void set_vic(Object
*obj
, bool value
, Error
**errp
)
152 Nios2MachineState
*nms
= NIOS2_MACHINE(obj
);
156 static void nios2_10m50_ghrd_class_init(ObjectClass
*oc
, void *data
)
158 MachineClass
*mc
= MACHINE_CLASS(oc
);
160 mc
->desc
= "Altera 10M50 GHRD Nios II design";
161 mc
->init
= nios2_10m50_ghrd_init
;
162 mc
->is_default
= true;
164 object_class_property_add_bool(oc
, "vic", get_vic
, set_vic
);
165 object_class_property_set_description(oc
, "vic",
166 "Set on/off to enable/disable the Vectored Interrupt Controller");
169 static const TypeInfo nios2_10m50_ghrd_type_info
= {
170 .name
= TYPE_NIOS2_MACHINE
,
171 .parent
= TYPE_MACHINE
,
172 .instance_size
= sizeof(Nios2MachineState
),
173 .class_init
= nios2_10m50_ghrd_class_init
,
176 static void nios2_10m50_ghrd_type_init(void)
178 type_register_static(&nios2_10m50_ghrd_type_info
);
180 type_init(nios2_10m50_ghrd_type_init
);