On 22 December 2011 18:20, Mark Langsdorf <mark.langsd...@calxeda.com> wrote: > From: Rob Herring <rob.herr...@calxeda.com> > > This is just a dummy device for ARM L2 cache controllers, based on the > pl310. The cache type parameter can be defined by a property value > and has a meaningful default. > > Signed-off-by: Rob Herring <rob.herr...@calxeda.com> > Signed-off-by: Mark Langsdorf <mark.langsd...@calxeda.com>
scripts/checkpatch.pl complains about a couple of overlong lines; please fix. > --- > Changes from v1 > Corrected formatting > Clarified the copyrights > Clarified GPL revision > Clarified model version > Removed hw_error() calls > Added a reset function > Restructed everything as switch/case statements > Added a type cache property > > Makefile.target | 1 + > hw/arm_l2x0.c | 173 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 174 insertions(+), 0 deletions(-) > create mode 100644 hw/arm_l2x0.c > > diff --git a/Makefile.target b/Makefile.target > index 3261383..db5e44c 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -336,6 +336,7 @@ obj-arm-y = integratorcp.o versatilepb.o arm_pic.o > arm_timer.o > obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o > pl190.o > obj-arm-y += versatile_pci.o > obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o > +obj-arm-y += arm_l2x0.o > obj-arm-y += arm_mptimer.o > obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o > obj-arm-y += pl061.o > diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c > new file mode 100644 > index 0000000..84f6c5a > --- /dev/null > +++ b/hw/arm_l2x0.c > @@ -0,0 +1,173 @@ > +/* > + * ARM dummy L210, L220, PL310 cache controller. > + * > + * Copyright (c) 2010-2012 Calxeda > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms and conditions of the GNU General Public License, > + * version 2, as published by the Free Software Foundation. "Or any later version". We're trying to avoid new v2-only code, please. > + * > + * This program is distributed in the hope it will be useful, but WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for > + * more details. > + * > + * You should have received a copy of the GNU General Public License along > with > + * this program. If not, see <http://www.gnu.org/licenses/>. > + * > + */ > + > +#include "sysbus.h" > + > +/* L2C-310 r3p1 */ > +#define CACHE_ID 0x410000c6 Why not r3p2 ? > +#define DEFAULT_CACHE_TYPE 0x19080800 > + > +typedef struct l2x0_state { > + SysBusDevice busdev; > + MemoryRegion iomem; > + uint32_t cache_type; > + uint32_t ctrl; > + uint32_t aux_ctrl; > + uint32_t data_ctrl; > + uint32_t tag_ctrl; > + uint32_t filter_start; > + uint32_t filter_end; > +} l2x0_state; > + > +static const VMStateDescription vmstate_l2x0 = { > + .name = "l2x0", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_UINT32(ctrl, l2x0_state), > + VMSTATE_UINT32(aux_ctrl, l2x0_state), > + VMSTATE_UINT32(data_ctrl, l2x0_state), > + VMSTATE_UINT32(tag_ctrl, l2x0_state), > + VMSTATE_UINT32(filter_start, l2x0_state), > + VMSTATE_UINT32(filter_end, l2x0_state), > + VMSTATE_END_OF_LIST() > + } > +}; > + > + > +static uint64_t l2x0_priv_read(void *opaque, target_phys_addr_t offset, > unsigned size) > +{ > + l2x0_state *s = (l2x0_state *)opaque; > + offset &= 0xfff; > + if (offset >= 0x730 && offset < 0x800) { > + return 0; /* cache ops complete */ > + } > + switch (offset) { > + case 0: > + return CACHE_ID; > + case 0x4: > + return s->cache_type; > + case 0x100: > + return s->ctrl; > + case 0x104: > + return s->aux_ctrl; > + case 0x108: > + return s->tag_ctrl; > + case 0x10C: > + return s->data_ctrl; > + case 0xC00: > + return s->filter_start; > + case 0xC04: > + return s->filter_end; > + case 0xF40: > + return 0; > + case 0xF60: > + return 0; > + case 0xF80: > + return 0; > + default: > + fprintf(stderr, "l2x0_priv_read: Bad offset %x\n", (int)offset); > + break; > + } > + return 0; > +} > + > +static void l2x0_priv_write(void *opaque, target_phys_addr_t offset, > uint64_t value, unsigned size) > +{ > + l2x0_state *s = (l2x0_state *)opaque; > + offset &= 0xfff; > + if (offset >= 0x730 && offset < 0x800) { > + /* ignore */ > + return; > + } > + switch (offset) { > + case 0x100: > + s->ctrl = value & 1; > + break; > + case 0x104: > + s->aux_ctrl = value; > + break; > + case 0x108: > + s->tag_ctrl = value; > + break; > + case 0x10C: > + s->data_ctrl = value; > + break; > + case 0xC00: > + s->filter_start = value; > + break; > + case 0xC04: > + s->filter_end = value; > + break; > + case 0xF40: > + return; > + case 0xF60: > + return; > + case 0xF80: > + return; > + default: > + fprintf(stderr, "l2x0_priv_write: Bad offset %x\n", (int)offset); > + break; > + } > +} > + > +static int l2x0_priv_reset(SysBusDevice *dev) > +{ > + l2x0_state *s = FROM_SYSBUS(l2x0_state, dev); > + > + s->aux_ctrl = 0x00020000; TRM says the aux ctrl reset value is 0x02020000. This should be a qdev reset function for the device (registered via .qdev.reset in the SysBusDeviceInfo). You'll need to reset the other registers too. > + return 0; > +} > + > +static const MemoryRegionOps l2x0_mem_ops = { > + .read = l2x0_priv_read, > + .write = l2x0_priv_write, > + .endianness = DEVICE_NATIVE_ENDIAN, > + }; > + > +static int l2x0_priv_init(SysBusDevice *dev) > +{ > + l2x0_state *s = FROM_SYSBUS(l2x0_state, dev); > + > + l2x0_priv_reset(dev); If you make this a qdev reset function you don't need to explicitly call it from your init function. > + > + memory_region_init_io(&s->iomem, &l2x0_mem_ops, s, "l2x0_cc", 0x1000); > + sysbus_init_mmio(dev, &s->iomem); > + return 0; > +} > + > +static SysBusDeviceInfo l2x0_info = { > + .init = l2x0_priv_init, > + .qdev.name = "l2x0", > + .qdev.size = sizeof(l2x0_state), > + .qdev.vmsd = &vmstate_l2x0, > + .qdev.no_user = 1, > + .qdev.props = (Property[]) { > + DEFINE_PROP_UINT32("type", l2x0_state, cache_type, > DEFAULT_CACHE_TYPE), > + DEFINE_PROP_END_OF_LIST(), > + } > +}; > + > +static void l2x0_register_device(void) > +{ > + sysbus_register_withprop(&l2x0_info); > +} > + > +device_init(l2x0_register_device) > + > -- > 1.7.5.4 > -- PMM