From: Jiri Gaisler <j...@gaisler.se> AMBA plug&play is used by kernels to probe available devices (Timers, UART, etc...). This is a static declaration of devices implemented in QEMU. In the future, a more advanced version could compute those information directly from the device tree.
Signed-off-by: Fabien Chouteau <chout...@adacore.com> --- V2: - AHB and APB PNP are now grouped in one device - Initialisation moved to .instance_init - Minor fixes hw/sparc/Makefile.objs | 1 + hw/sparc/grlib_ambapnp.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ hw/sparc/leon3.c | 3 + include/hw/sparc/grlib.h | 22 +++++++ 4 files changed, 175 insertions(+) create mode 100644 hw/sparc/grlib_ambapnp.c diff --git a/hw/sparc/Makefile.objs b/hw/sparc/Makefile.objs index c987b5b..e763701 100644 --- a/hw/sparc/Makefile.objs +++ b/hw/sparc/Makefile.objs @@ -1 +1,2 @@ obj-y += sun4m.o leon3.o +obj-$(CONFIG_GRLIB) += grlib_ambapnp.o diff --git a/hw/sparc/grlib_ambapnp.c b/hw/sparc/grlib_ambapnp.c new file mode 100644 index 0000000..dd53004 --- /dev/null +++ b/hw/sparc/grlib_ambapnp.c @@ -0,0 +1,149 @@ +/* + * QEMU GRLIB AMBA Plug&Play Emulator + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/sysbus.h" +#include "hw/sparc/grlib.h" + +/* Size of memory mapped registers */ +#define APBPNP_REG_SIZE (4096 - 8) +#define AHBPNP_REG_SIZE 4096 + +#define GRLIB_AMBA_PNP(obj) \ + OBJECT_CHECK(AMBAPNP, (obj), TYPE_GRLIB_AMBA_PNP) + +typedef struct AMBAPNP { + SysBusDevice parent_obj; + MemoryRegion ahb_iomem; + MemoryRegion apb_iomem; +} AMBAPNP; + +/* APB PNP */ + +static uint64_t grlib_apbpnp_read(void *opaque, hwaddr addr, + unsigned size) +{ + uint64_t read_data; + addr &= 0xfff; + + /* Unit registers */ + switch (addr & 0xffc) { + case 0x00: + read_data = 0x0400f000; /* Memory controller */ + break; + case 0x04: + read_data = 0x0000fff1; + break; + case 0x08: + read_data = 0x0100c023; /* APBUART */ + break; + case 0x0C: + read_data = 0x0010fff1; + break; + case 0x10: + read_data = 0x0100d040; /* IRQMP */ + break; + case 0x14: + read_data = 0x0020fff1; + break; + case 0x18: + read_data = 0x01011006; /* GPTIMER */ + break; + case 0x1C: + read_data = 0x0030fff1; + break; + + default: + read_data = 0; + } + if (size == 1) { + read_data >>= (24 - (addr & 3) * 8); + read_data &= 0x0ff; + } + return read_data; +} + +static const MemoryRegionOps grlib_apbpnp_ops = { + .read = grlib_apbpnp_read, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +/* AHB PNP */ + +static uint64_t grlib_ahbpnp_read(void *opaque, hwaddr addr, + unsigned size) +{ + addr &= 0xffc; + + /* Unit registers */ + switch (addr) { + case 0: + return 0x01003000; /* LEON3 */ + case 0x800: + return 0x0400f000; /* Memory controller */ + case 0x810: + return 0x0003e002; + case 0x814: + return 0x2000e002; + case 0x818: + return 0x4003c002; + case 0x820: + return 0x01006000; /* APB bridge @ 0x80000000 */ + case 0x830: + return 0x8000fff2; + + default: + return 0; + } +} + +static const MemoryRegionOps grlib_ahbpnp_ops = { + .read = grlib_ahbpnp_read, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void grlib_ambapnp_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + AMBAPNP *pnp = GRLIB_AMBA_PNP(obj); + + memory_region_init_io(&pnp->ahb_iomem, OBJECT(pnp), &grlib_ahbpnp_ops, pnp, + "ahbpnp", AHBPNP_REG_SIZE); + sysbus_init_mmio(sbd, &pnp->ahb_iomem); + + memory_region_init_io(&pnp->apb_iomem, OBJECT(pnp), &grlib_apbpnp_ops, pnp, + "apbpnp", APBPNP_REG_SIZE); + sysbus_init_mmio(sbd, &pnp->apb_iomem); +} + +static const TypeInfo grlib_ambapnp_info = { + .name = TYPE_GRLIB_AMBA_PNP, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AMBAPNP), + .instance_init = grlib_ambapnp_init, +}; + +static void grlib_ambapnp_register_types(void) +{ + type_register_static(&grlib_ambapnp_info); +} + +type_init(grlib_ambapnp_register_types) diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 751392e..2962539 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -207,6 +207,9 @@ static void leon3_generic_hw_init(MachineState *machine) } } + /* Allocate AHB/APB PNP */ + grlib_ambapnp_create(0xFFFFF000 /* AHB */, 0x800FF000 /* APB */); + /* Allocate timers */ grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6); diff --git a/include/hw/sparc/grlib.h b/include/hw/sparc/grlib.h index 470ce72..5c098df 100644 --- a/include/hw/sparc/grlib.h +++ b/include/hw/sparc/grlib.h @@ -123,4 +123,26 @@ DeviceState *grlib_apbuart_create(hwaddr base, return dev; } + +/* AMBA PNP */ + +#define TYPE_GRLIB_AMBA_PNP "grlib,ambapnp" + +static inline +DeviceState *grlib_ambapnp_create(hwaddr ahbpnp_base, hwaddr apbpnp_base) +{ + DeviceState *dev; + + dev = qdev_create(NULL, TYPE_GRLIB_AMBA_PNP); + + if (qdev_init(dev)) { + return NULL; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, ahbpnp_base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, apbpnp_base); + + return dev; +} + #endif /* ! _GRLIB_H_ */ -- 1.7.9.5