 5fcabe628b
			
		
	
	
		5fcabe628b
		
	
	
	
	
		
			
			Now that all of the Property arrays are counted, we can remove the terminator object from each array. Update the assertions in device_class_set_props to match. With struct Property being 88 bytes, this was a rather large form of terminator. Saves 30k from qemu-system-aarch64. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Tested-by: Lei Yang <leiyang@redhat.com> Link: https://lore.kernel.org/r/20241218134251.4724-21-richard.henderson@linaro.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
		
			
				
	
	
		
			253 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * QEMU model of the Xilinx XRAM Controller.
 | |
|  *
 | |
|  * Copyright (c) 2021 Xilinx Inc.
 | |
|  * SPDX-License-Identifier: GPL-2.0-or-later
 | |
|  * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "qemu/units.h"
 | |
| #include "qapi/error.h"
 | |
| #include "migration/vmstate.h"
 | |
| #include "hw/sysbus.h"
 | |
| #include "hw/register.h"
 | |
| #include "hw/qdev-properties.h"
 | |
| #include "hw/irq.h"
 | |
| #include "hw/misc/xlnx-versal-xramc.h"
 | |
| 
 | |
| #ifndef XLNX_XRAM_CTRL_ERR_DEBUG
 | |
| #define XLNX_XRAM_CTRL_ERR_DEBUG 0
 | |
| #endif
 | |
| 
 | |
| static void xram_update_irq(XlnxXramCtrl *s)
 | |
| {
 | |
|     bool pending = s->regs[R_XRAM_ISR] & ~s->regs[R_XRAM_IMR];
 | |
|     qemu_set_irq(s->irq, pending);
 | |
| }
 | |
| 
 | |
| static void xram_isr_postw(RegisterInfo *reg, uint64_t val64)
 | |
| {
 | |
|     XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
 | |
|     xram_update_irq(s);
 | |
| }
 | |
| 
 | |
| static uint64_t xram_ien_prew(RegisterInfo *reg, uint64_t val64)
 | |
| {
 | |
|     XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
 | |
|     uint32_t val = val64;
 | |
| 
 | |
|     s->regs[R_XRAM_IMR] &= ~val;
 | |
|     xram_update_irq(s);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static uint64_t xram_ids_prew(RegisterInfo *reg, uint64_t val64)
 | |
| {
 | |
|     XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
 | |
|     uint32_t val = val64;
 | |
| 
 | |
|     s->regs[R_XRAM_IMR] |= val;
 | |
|     xram_update_irq(s);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static const RegisterAccessInfo xram_ctrl_regs_info[] = {
 | |
|     {   .name = "XRAM_ERR_CTRL",  .addr = A_XRAM_ERR_CTRL,
 | |
|         .reset = 0xf,
 | |
|         .rsvd = 0xfffffff0,
 | |
|     },{ .name = "XRAM_ISR",  .addr = A_XRAM_ISR,
 | |
|         .rsvd = 0xfffff800,
 | |
|         .w1c = 0x7ff,
 | |
|         .post_write = xram_isr_postw,
 | |
|     },{ .name = "XRAM_IMR",  .addr = A_XRAM_IMR,
 | |
|         .reset = 0x7ff,
 | |
|         .rsvd = 0xfffff800,
 | |
|         .ro = 0x7ff,
 | |
|     },{ .name = "XRAM_IEN",  .addr = A_XRAM_IEN,
 | |
|         .rsvd = 0xfffff800,
 | |
|         .pre_write = xram_ien_prew,
 | |
|     },{ .name = "XRAM_IDS",  .addr = A_XRAM_IDS,
 | |
|         .rsvd = 0xfffff800,
 | |
|         .pre_write = xram_ids_prew,
 | |
|     },{ .name = "XRAM_ECC_CNTL",  .addr = A_XRAM_ECC_CNTL,
 | |
|         .rsvd = 0xfffffff8,
 | |
|     },{ .name = "XRAM_CLR_EXE",  .addr = A_XRAM_CLR_EXE,
 | |
|         .rsvd = 0xffffff00,
 | |
|     },{ .name = "XRAM_CE_FFA",  .addr = A_XRAM_CE_FFA,
 | |
|         .rsvd = 0xfff00000,
 | |
|         .ro = 0xfffff,
 | |
|     },{ .name = "XRAM_CE_FFD0",  .addr = A_XRAM_CE_FFD0,
 | |
|         .ro = 0xffffffff,
 | |
|     },{ .name = "XRAM_CE_FFD1",  .addr = A_XRAM_CE_FFD1,
 | |
|         .ro = 0xffffffff,
 | |
|     },{ .name = "XRAM_CE_FFD2",  .addr = A_XRAM_CE_FFD2,
 | |
|         .ro = 0xffffffff,
 | |
|     },{ .name = "XRAM_CE_FFD3",  .addr = A_XRAM_CE_FFD3,
 | |
|         .ro = 0xffffffff,
 | |
|     },{ .name = "XRAM_CE_FFE",  .addr = A_XRAM_CE_FFE,
 | |
|         .rsvd = 0xffff0000,
 | |
|         .ro = 0xffff,
 | |
|     },{ .name = "XRAM_UE_FFA",  .addr = A_XRAM_UE_FFA,
 | |
|         .rsvd = 0xfff00000,
 | |
|         .ro = 0xfffff,
 | |
|     },{ .name = "XRAM_UE_FFD0",  .addr = A_XRAM_UE_FFD0,
 | |
|         .ro = 0xffffffff,
 | |
|     },{ .name = "XRAM_UE_FFD1",  .addr = A_XRAM_UE_FFD1,
 | |
|         .ro = 0xffffffff,
 | |
|     },{ .name = "XRAM_UE_FFD2",  .addr = A_XRAM_UE_FFD2,
 | |
|         .ro = 0xffffffff,
 | |
|     },{ .name = "XRAM_UE_FFD3",  .addr = A_XRAM_UE_FFD3,
 | |
|         .ro = 0xffffffff,
 | |
|     },{ .name = "XRAM_UE_FFE",  .addr = A_XRAM_UE_FFE,
 | |
|         .rsvd = 0xffff0000,
 | |
|         .ro = 0xffff,
 | |
|     },{ .name = "XRAM_FI_D0",  .addr = A_XRAM_FI_D0,
 | |
|     },{ .name = "XRAM_FI_D1",  .addr = A_XRAM_FI_D1,
 | |
|     },{ .name = "XRAM_FI_D2",  .addr = A_XRAM_FI_D2,
 | |
|     },{ .name = "XRAM_FI_D3",  .addr = A_XRAM_FI_D3,
 | |
|     },{ .name = "XRAM_FI_SY",  .addr = A_XRAM_FI_SY,
 | |
|         .rsvd = 0xffff0000,
 | |
|     },{ .name = "XRAM_RMW_UE_FFA",  .addr = A_XRAM_RMW_UE_FFA,
 | |
|         .rsvd = 0xfff00000,
 | |
|         .ro = 0xfffff,
 | |
|     },{ .name = "XRAM_FI_CNTR",  .addr = A_XRAM_FI_CNTR,
 | |
|         .rsvd = 0xff000000,
 | |
|     },{ .name = "XRAM_IMP",  .addr = A_XRAM_IMP,
 | |
|         .reset = 0x4,
 | |
|         .rsvd = 0xfffffff0,
 | |
|         .ro = 0xf,
 | |
|     },{ .name = "XRAM_PRDY_DBG",  .addr = A_XRAM_PRDY_DBG,
 | |
|         .reset = 0xffff,
 | |
|         .rsvd = 0xffff0000,
 | |
|         .ro = 0xffff,
 | |
|     },{ .name = "XRAM_SAFETY_CHK",  .addr = A_XRAM_SAFETY_CHK,
 | |
|     }
 | |
| };
 | |
| 
 | |
| static void xram_ctrl_reset_enter(Object *obj, ResetType type)
 | |
| {
 | |
|     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
 | |
|     unsigned int i;
 | |
| 
 | |
|     for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 | |
|         register_reset(&s->regs_info[i]);
 | |
|     }
 | |
| 
 | |
|     ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
 | |
| }
 | |
| 
 | |
| static void xram_ctrl_reset_hold(Object *obj, ResetType type)
 | |
| {
 | |
|     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
 | |
| 
 | |
|     xram_update_irq(s);
 | |
| }
 | |
| 
 | |
| static const MemoryRegionOps xram_ctrl_ops = {
 | |
|     .read = register_read_memory,
 | |
|     .write = register_write_memory,
 | |
|     .endianness = DEVICE_LITTLE_ENDIAN,
 | |
|     .valid = {
 | |
|         .min_access_size = 4,
 | |
|         .max_access_size = 4,
 | |
|     },
 | |
| };
 | |
| 
 | |
| static void xram_ctrl_realize(DeviceState *dev, Error **errp)
 | |
| {
 | |
|     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 | |
|     XlnxXramCtrl *s = XLNX_XRAM_CTRL(dev);
 | |
| 
 | |
|     switch (s->cfg.size) {
 | |
|     case 64 * KiB:
 | |
|         s->cfg.encoded_size = 0;
 | |
|         break;
 | |
|     case 128 * KiB:
 | |
|         s->cfg.encoded_size = 1;
 | |
|         break;
 | |
|     case 256 * KiB:
 | |
|         s->cfg.encoded_size = 2;
 | |
|         break;
 | |
|     case 512 * KiB:
 | |
|         s->cfg.encoded_size = 3;
 | |
|         break;
 | |
|     case 1 * MiB:
 | |
|         s->cfg.encoded_size = 4;
 | |
|         break;
 | |
|     default:
 | |
|         error_setg(errp, "Unsupported XRAM size %" PRId64, s->cfg.size);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     memory_region_init_ram(&s->ram, OBJECT(s),
 | |
|                            object_get_canonical_path_component(OBJECT(s)),
 | |
|                            s->cfg.size, &error_fatal);
 | |
|     sysbus_init_mmio(sbd, &s->ram);
 | |
| }
 | |
| 
 | |
| static void xram_ctrl_init(Object *obj)
 | |
| {
 | |
|     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
 | |
|     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 | |
| 
 | |
|     s->reg_array =
 | |
|         register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
 | |
|                               ARRAY_SIZE(xram_ctrl_regs_info),
 | |
|                               s->regs_info, s->regs,
 | |
|                               &xram_ctrl_ops,
 | |
|                               XLNX_XRAM_CTRL_ERR_DEBUG,
 | |
|                               XRAM_CTRL_R_MAX * 4);
 | |
|     sysbus_init_mmio(sbd, &s->reg_array->mem);
 | |
|     sysbus_init_irq(sbd, &s->irq);
 | |
| }
 | |
| 
 | |
| static void xram_ctrl_finalize(Object *obj)
 | |
| {
 | |
|     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
 | |
|     register_finalize_block(s->reg_array);
 | |
| }
 | |
| 
 | |
| static const VMStateDescription vmstate_xram_ctrl = {
 | |
|     .name = TYPE_XLNX_XRAM_CTRL,
 | |
|     .version_id = 1,
 | |
|     .minimum_version_id = 1,
 | |
|     .fields = (const VMStateField[]) {
 | |
|         VMSTATE_UINT32_ARRAY(regs, XlnxXramCtrl, XRAM_CTRL_R_MAX),
 | |
|         VMSTATE_END_OF_LIST(),
 | |
|     }
 | |
| };
 | |
| 
 | |
| static const Property xram_ctrl_properties[] = {
 | |
|     DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB),
 | |
| };
 | |
| 
 | |
| static void xram_ctrl_class_init(ObjectClass *klass, void *data)
 | |
| {
 | |
|     ResettableClass *rc = RESETTABLE_CLASS(klass);
 | |
|     DeviceClass *dc = DEVICE_CLASS(klass);
 | |
| 
 | |
|     dc->realize = xram_ctrl_realize;
 | |
|     dc->vmsd = &vmstate_xram_ctrl;
 | |
|     device_class_set_props(dc, xram_ctrl_properties);
 | |
| 
 | |
|     rc->phases.enter = xram_ctrl_reset_enter;
 | |
|     rc->phases.hold = xram_ctrl_reset_hold;
 | |
| }
 | |
| 
 | |
| static const TypeInfo xram_ctrl_info = {
 | |
|     .name              = TYPE_XLNX_XRAM_CTRL,
 | |
|     .parent            = TYPE_SYS_BUS_DEVICE,
 | |
|     .instance_size     = sizeof(XlnxXramCtrl),
 | |
|     .class_init        = xram_ctrl_class_init,
 | |
|     .instance_init     = xram_ctrl_init,
 | |
|     .instance_finalize = xram_ctrl_finalize,
 | |
| };
 | |
| 
 | |
| static void xram_ctrl_register_types(void)
 | |
| {
 | |
|     type_register_static(&xram_ctrl_info);
 | |
| }
 | |
| 
 | |
| type_init(xram_ctrl_register_types)
 |