From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:39706) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ReFrl-0000AK-Lq for qemu-devel@nongnu.org; Fri, 23 Dec 2011 19:53:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ReFrk-0004QZ-3I for qemu-devel@nongnu.org; Fri, 23 Dec 2011 19:53:37 -0500 Received: from mail-qw0-f52.google.com ([209.85.216.52]:41494) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ReFrk-0004QT-0F for qemu-devel@nongnu.org; Fri, 23 Dec 2011 19:53:36 -0500 Received: by qadc11 with SMTP id c11so6117187qad.4 for ; Fri, 23 Dec 2011 16:53:35 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <1324578014-24746-8-git-send-email-mark.langsdorf@calxeda.com> References: <1324578014-24746-1-git-send-email-mark.langsdorf@calxeda.com> <1324578014-24746-8-git-send-email-mark.langsdorf@calxeda.com> Date: Sat, 24 Dec 2011 00:53:34 +0000 Message-ID: From: Peter Maydell Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v2 7/9] add L2x0/PL310 cache controller device List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Mark Langsdorf Cc: kwolf@redhat.com, qemu-devel@nongnu.org, Rob Herring , paul@codesourcery.com On 22 December 2011 18:20, Mark Langsdorf wrot= e: > From: Rob Herring > > 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 > Signed-off-by: Mark Langsdorf scripts/checkpatch.pl complains about a couple of overlong lines; please fix. > --- > Changes from v1 > =C2=A0 =C2=A0 =C2=A0 =C2=A0Corrected formatting > =C2=A0 =C2=A0 =C2=A0 =C2=A0Clarified the copyrights > =C2=A0 =C2=A0 =C2=A0 =C2=A0Clarified GPL revision > =C2=A0 =C2=A0 =C2=A0 =C2=A0Clarified model version > =C2=A0 =C2=A0 =C2=A0 =C2=A0Removed hw_error() calls > =C2=A0 =C2=A0 =C2=A0 =C2=A0Added a reset function > =C2=A0 =C2=A0 =C2=A0 =C2=A0Restructed everything as switch/case statement= s > =C2=A0 =C2=A0 =C2=A0 =C2=A0Added a type cache property > > =C2=A0Makefile.target | =C2=A0 =C2=A01 + > =C2=A0hw/arm_l2x0.c =C2=A0 | =C2=A0173 ++++++++++++++++++++++++++++++++++= +++++++++++++++++++++ > =C2=A02 files changed, 174 insertions(+), 0 deletions(-) > =C2=A0create 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 =3D integratorcp.o versatilepb.o arm_pic.o = arm_timer.o > =C2=A0obj-arm-y +=3D arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o p= l181.o pl190.o > =C2=A0obj-arm-y +=3D versatile_pci.o > =C2=A0obj-arm-y +=3D realview_gic.o realview.o arm_sysctl.o arm11mpcore.o= a9mpcore.o > +obj-arm-y +=3D arm_l2x0.o > =C2=A0obj-arm-y +=3D arm_mptimer.o > =C2=A0obj-arm-y +=3D armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris= _enet.o > =C2=A0obj-arm-y +=3D 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 WITHOU= T > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. =C2=A0See the GNU General Public Li= cense for > + * more details. > + * > + * You should have received a copy of the GNU General Public License alo= ng with > + * this program. =C2=A0If not, see . > + * > + */ > + > +#include "sysbus.h" > + > +/* L2C-310 r3p1 */ > +#define CACHE_ID 0x410000c6 Why not r3p2 ? > +#define DEFAULT_CACHE_TYPE 0x19080800 > + > +typedef struct l2x0_state { > + =C2=A0 =C2=A0SysBusDevice busdev; > + =C2=A0 =C2=A0MemoryRegion iomem; > + =C2=A0 =C2=A0uint32_t cache_type; > + =C2=A0 =C2=A0uint32_t ctrl; > + =C2=A0 =C2=A0uint32_t aux_ctrl; > + =C2=A0 =C2=A0uint32_t data_ctrl; > + =C2=A0 =C2=A0uint32_t tag_ctrl; > + =C2=A0 =C2=A0uint32_t filter_start; > + =C2=A0 =C2=A0uint32_t filter_end; > +} l2x0_state; > + > +static const VMStateDescription vmstate_l2x0 =3D { > + =C2=A0 =C2=A0.name =3D "l2x0", > + =C2=A0 =C2=A0.version_id =3D 1, > + =C2=A0 =C2=A0.minimum_version_id =3D 1, > + =C2=A0 =C2=A0.fields =3D (VMStateField[]) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0VMSTATE_UINT32(ctrl, l2x0_state), > + =C2=A0 =C2=A0 =C2=A0 =C2=A0VMSTATE_UINT32(aux_ctrl, l2x0_state), > + =C2=A0 =C2=A0 =C2=A0 =C2=A0VMSTATE_UINT32(data_ctrl, l2x0_state), > + =C2=A0 =C2=A0 =C2=A0 =C2=A0VMSTATE_UINT32(tag_ctrl, l2x0_state), > + =C2=A0 =C2=A0 =C2=A0 =C2=A0VMSTATE_UINT32(filter_start, l2x0_state), > + =C2=A0 =C2=A0 =C2=A0 =C2=A0VMSTATE_UINT32(filter_end, l2x0_state), > + =C2=A0 =C2=A0 =C2=A0 =C2=A0VMSTATE_END_OF_LIST() > + =C2=A0 =C2=A0} > +}; > + > + > +static uint64_t l2x0_priv_read(void *opaque, target_phys_addr_t offset, = unsigned size) > +{ > + =C2=A0 =C2=A0l2x0_state *s =3D (l2x0_state *)opaque; > + =C2=A0 =C2=A0offset &=3D 0xfff; > + =C2=A0 =C2=A0if (offset >=3D 0x730 && offset < 0x800) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0; /* cache ops complete */ > + =C2=A0 =C2=A0} > + =C2=A0 =C2=A0switch (offset) { > + =C2=A0 =C2=A0case 0: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return CACHE_ID; > + =C2=A0 =C2=A0case 0x4: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return s->cache_type; > + =C2=A0 =C2=A0case 0x100: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return s->ctrl; > + =C2=A0 =C2=A0case 0x104: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return s->aux_ctrl; > + =C2=A0 =C2=A0case 0x108: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return s->tag_ctrl; > + =C2=A0 =C2=A0case 0x10C: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return s->data_ctrl; > + =C2=A0 =C2=A0case 0xC00: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return s->filter_start; > + =C2=A0 =C2=A0case 0xC04: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return s->filter_end; > + =C2=A0 =C2=A0case 0xF40: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0; > + =C2=A0 =C2=A0case 0xF60: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0; > + =C2=A0 =C2=A0case 0xF80: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0; > + =C2=A0 =C2=A0default: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "l2x0_priv_read: Bad offset = %x\n", (int)offset); > + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; > + =C2=A0 =C2=A0} > + =C2=A0 =C2=A0return 0; > +} > + > +static void l2x0_priv_write(void *opaque, target_phys_addr_t offset, uin= t64_t value, unsigned size) > +{ > + =C2=A0 =C2=A0l2x0_state *s =3D (l2x0_state *)opaque; > + =C2=A0 =C2=A0offset &=3D 0xfff; > + =C2=A0 =C2=A0if (offset >=3D 0x730 && offset < 0x800) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0/* ignore */ > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0} > + =C2=A0 =C2=A0switch (offset) { > + =C2=A0 =C2=A0case 0x100: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0s->ctrl =3D value & 1; > + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; > + =C2=A0 =C2=A0case 0x104: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0s->aux_ctrl =3D value; > + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; > + =C2=A0 =C2=A0case 0x108: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0s->tag_ctrl =3D value; > + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; > + =C2=A0 =C2=A0case 0x10C: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0s->data_ctrl =3D value; > + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; > + =C2=A0 =C2=A0case 0xC00: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0s->filter_start =3D value; > + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; > + =C2=A0 =C2=A0case 0xC04: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0s->filter_end =3D value; > + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; > + =C2=A0 =C2=A0case 0xF40: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0case 0xF60: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0case 0xF80: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0default: > + =C2=A0 =C2=A0 =C2=A0 =C2=A0fprintf(stderr, "l2x0_priv_write: Bad offset= %x\n", (int)offset); > + =C2=A0 =C2=A0 =C2=A0 =C2=A0break; > + =C2=A0 =C2=A0} > +} > + > +static int l2x0_priv_reset(SysBusDevice *dev) > +{ > + =C2=A0 =C2=A0l2x0_state *s =3D FROM_SYSBUS(l2x0_state, dev); > + > + =C2=A0 =C2=A0s->aux_ctrl =3D 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. > + =C2=A0 =C2=A0return 0; > +} > + > +static const MemoryRegionOps l2x0_mem_ops =3D { > + =C2=A0 =C2=A0.read =3D l2x0_priv_read, > + =C2=A0 =C2=A0.write =3D l2x0_priv_write, > + =C2=A0 =C2=A0.endianness =3D DEVICE_NATIVE_ENDIAN, > + }; > + > +static int l2x0_priv_init(SysBusDevice *dev) > +{ > + =C2=A0 =C2=A0l2x0_state *s =3D FROM_SYSBUS(l2x0_state, dev); > + > + =C2=A0 =C2=A0l2x0_priv_reset(dev); If you make this a qdev reset function you don't need to explicitly call it from your init function. > + > + =C2=A0 =C2=A0memory_region_init_io(&s->iomem, &l2x0_mem_ops, s, "l2x0_c= c", 0x1000); > + =C2=A0 =C2=A0sysbus_init_mmio(dev, &s->iomem); > + =C2=A0 =C2=A0return 0; > +} > + > +static SysBusDeviceInfo l2x0_info =3D { > + =C2=A0 =C2=A0.init =3D l2x0_priv_init, > + =C2=A0 =C2=A0.qdev.name =3D "l2x0", > + =C2=A0 =C2=A0.qdev.size =3D sizeof(l2x0_state), > + =C2=A0 =C2=A0.qdev.vmsd =3D &vmstate_l2x0, > + =C2=A0 =C2=A0.qdev.no_user =3D 1, > + =C2=A0 =C2=A0.qdev.props =3D (Property[]) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0DEFINE_PROP_UINT32("type", l2x0_state, cache= _type, DEFAULT_CACHE_TYPE), > + =C2=A0 =C2=A0 =C2=A0 =C2=A0DEFINE_PROP_END_OF_LIST(), > + =C2=A0 =C2=A0} > +}; > + > +static void l2x0_register_device(void) > +{ > + =C2=A0 =C2=A0sysbus_register_withprop(&l2x0_info); > +} > + > +device_init(l2x0_register_device) > + > -- > 1.7.5.4 > -- PMM