From: Ninad Palsule <ninad@linux.ibm.com>
To: "Cédric Le Goater" <clg@kaod.org>,
qemu-devel@nongnu.org, peter.maydell@linaro.org,
andrew@codeconstruct.com.au, joel@jms.id.au, pbonzini@redhat.com,
marcandre.lureau@redhat.com, berrange@redhat.com,
thuth@redhat.com, philmd@linaro.org, lvivier@redhat.com
Cc: qemu-arm@nongnu.org, Andrew Jeffery <andrew@aj.id.au>
Subject: Re: [PATCH v6 06/10] hw/fsi: Aspeed APB2OPB interface
Date: Thu, 26 Oct 2023 10:27:01 -0500 [thread overview]
Message-ID: <8269cf50-05d1-4f57-8fc8-0a074721a0df@linux.ibm.com> (raw)
In-Reply-To: <58deedee-a291-4d73-a3f1-09ea16c953f0@kaod.org>
Hello Cedric,
On 10/24/23 10:21, Cédric Le Goater wrote:
> On 10/24/23 17:00, Ninad Palsule wrote:
>> Hello Cedric,
>>
>> On 10/24/23 02:46, Cédric Le Goater wrote:
>>> On 10/21/23 23:17, Ninad Palsule wrote:
>>>> This is a part of patchset where IBM's Flexible Service Interface is
>>>> introduced.
>>>>
>>>> An APB-to-OPB bridge enabling access to the OPB from the ARM core in
>>>> the AST2600. Hardware limitations prevent the OPB from being directly
>>>> mapped into APB, so all accesses are indirect through the bridge.
>>>>
>>>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>>>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>>>> ---
>>>> v2:
>>>> - Incorporated review comments by Joel
>>>> v3:
>>>> - Incorporated review comments by Thomas Huth
>>>> v4:
>>>> - Compile FSI with ASPEED_SOC only.
>>>> v5:
>>>> - Incorporated review comments by Cedric.
>>>> v6:
>>>> - Incorporated review comments by Cedric.
>>>> ---
>>>> include/hw/fsi/aspeed-apb2opb.h | 33 ++++
>>>> hw/fsi/aspeed-apb2opb.c | 280
>>>> ++++++++++++++++++++++++++++++++
>>>> hw/arm/Kconfig | 1 +
>>>> hw/fsi/Kconfig | 4 +
>>>> hw/fsi/meson.build | 1 +
>>>> hw/fsi/trace-events | 2 +
>>>> 6 files changed, 321 insertions(+)
>>>> create mode 100644 include/hw/fsi/aspeed-apb2opb.h
>>>> create mode 100644 hw/fsi/aspeed-apb2opb.c
>>>>
>>>> diff --git a/include/hw/fsi/aspeed-apb2opb.h
>>>> b/include/hw/fsi/aspeed-apb2opb.h
>>>> new file mode 100644
>>>> index 0000000000..a81ae67023
>>>> --- /dev/null
>>>> +++ b/include/hw/fsi/aspeed-apb2opb.h
>>>> @@ -0,0 +1,33 @@
>>>> +/*
>>>> + * SPDX-License-Identifier: GPL-2.0-or-later
>>>> + * Copyright (C) 2023 IBM Corp.
>>>> + *
>>>> + * ASPEED APB2OPB Bridge
>>>> + */
>>>> +#ifndef FSI_ASPEED_APB2OPB_H
>>>> +#define FSI_ASPEED_APB2OPB_H
>>>> +
>>>> +#include "hw/sysbus.h"
>>>> +#include "hw/fsi/opb.h"
>>>> +
>>>> +#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb"
>>>> +OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB)
>>>> +
>>>> +#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1)
>>>> +
>>>> +#define ASPEED_FSI_NUM 2
>>>> +
>>>> +typedef struct AspeedAPB2OPBState {
>>>> + /*< private >*/
>>>> + SysBusDevice parent_obj;
>>>> +
>>>> + /*< public >*/
>>>> + MemoryRegion iomem;
>>>> +
>>>> + uint32_t regs[ASPEED_APB2OPB_NR_REGS];
>>>> + qemu_irq irq;
>>>> +
>>>> + OPBus opb[ASPEED_FSI_NUM];
>>>> +} AspeedAPB2OPBState;
>>>> +
>>>> +#endif /* FSI_ASPEED_APB2OPB_H */
>>>> diff --git a/hw/fsi/aspeed-apb2opb.c b/hw/fsi/aspeed-apb2opb.c
>>>> new file mode 100644
>>>> index 0000000000..6f97a6bc7d
>>>> --- /dev/null
>>>> +++ b/hw/fsi/aspeed-apb2opb.c
>>>> @@ -0,0 +1,280 @@
>>>> +/*
>>>> + * SPDX-License-Identifier: GPL-2.0-or-later
>>>> + * Copyright (C) 2023 IBM Corp.
>>>> + *
>>>> + * ASPEED APB-OPB FSI interface
>>>> + */
>>>> +
>>>> +#include "qemu/osdep.h"
>>>> +#include "qemu/log.h"
>>>> +#include "qom/object.h"
>>>> +#include "qapi/error.h"
>>>> +#include "trace.h"
>>>> +
>>>> +#include "hw/fsi/aspeed-apb2opb.h"
>>>> +#include "hw/qdev-core.h"
>>>> +
>>>> +#define TO_REG(x) (x >> 2)
>>>> +#define GENMASK(t, b) (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b))
>>>> - 1))
>>>> +
>>>> +#define APB2OPB_VERSION TO_REG(0x00)
>>>> +#define APB2OPB_VERSION_VER GENMASK(7, 0)
>>>> +
>>>> +#define APB2OPB_TRIGGER TO_REG(0x04)
>>>> +#define APB2OPB_TRIGGER_EN BIT(0)
>>>> +
>>>> +#define APB2OPB_CONTROL TO_REG(0x08)
>>>> +#define APB2OPB_CONTROL_OFF GENMASK(31, 13)
>>>> +
>>>> +#define APB2OPB_OPB2FSI TO_REG(0x0c)
>>>> +#define APB2OPB_OPB2FSI_OFF GENMASK(31, 22)
>>>> +
>>>> +#define APB2OPB_OPB0_SEL TO_REG(0x10)
>>>> +#define APB2OPB_OPB1_SEL TO_REG(0x28)
>>>> +#define APB2OPB_OPB_SEL_EN BIT(0)
>>>> +
>>>> +#define APB2OPB_OPB0_MODE TO_REG(0x14)
>>>> +#define APB2OPB_OPB1_MODE TO_REG(0x2c)
>>>> +#define APB2OPB_OPB_MODE_RD BIT(0)
>>>> +
>>>> +#define APB2OPB_OPB0_XFER TO_REG(0x18)
>>>> +#define APB2OPB_OPB1_XFER TO_REG(0x30)
>>>> +#define APB2OPB_OPB_XFER_FULL BIT(1)
>>>> +#define APB2OPB_OPB_XFER_HALF BIT(0)
>>>> +
>>>> +#define APB2OPB_OPB0_ADDR TO_REG(0x1c)
>>>> +#define APB2OPB_OPB0_WRITE_DATA TO_REG(0x20)
>>>> +
>>>> +#define APB2OPB_OPB1_ADDR TO_REG(0x34)
>>>> +#define APB2OPB_OPB1_WRITE_DATA TO_REG(0x38)
>>>> +
>>>> +#define APB2OPB_IRQ_STS TO_REG(0x48)
>>>> +#define APB2OPB_IRQ_STS_OPB1_TX_ACK BIT(17)
>>>> +#define APB2OPB_IRQ_STS_OPB0_TX_ACK BIT(16)
>>>> +
>>>> +#define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c)
>>>> +#define APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE 0x0011101b
>>>> +#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN TO_REG(0x50)
>>>> +#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE 0x0c330f3f
>>>> +#define APB2OPB_OPB1_WRITE_WORD_ENDIAN TO_REG(0x54)
>>>> +#define APB2OPB_OPB1_WRITE_BYTE_ENDIAN TO_REG(0x58)
>>>> +#define APB2OPB_OPB0_READ_BYTE_ENDIAN TO_REG(0x5c)
>>>> +#define APB2OPB_OPB1_READ_BYTE_ENDIAN TO_REG(0x60)
>>>> +#define APB2OPB_OPB0_READ_WORD_ENDIAN_BE 0x00030b1b
>>>> +
>>>> +#define APB2OPB_OPB0_READ_DATA TO_REG(0x84)
>>>> +#define APB2OPB_OPB1_READ_DATA TO_REG(0x90)
>>>> +
>>>> +/*
>>>> + * The following magic values came from AST2600 data sheet
>>>> + * The register values are defined under section "FSI controller"
>>>> + * as initial values.
>>>> + */
>>>> +static const uint32_t aspeed_apb2opb_reset[ASPEED_APB2OPB_NR_REGS]
>>>> = {
>>>> + [APB2OPB_VERSION] = 0x000000a1,
>>>> + [APB2OPB_OPB0_WRITE_WORD_ENDIAN] = 0x0044eee4,
>>>> + [APB2OPB_OPB0_WRITE_BYTE_ENDIAN] = 0x0055aaff,
>>>> + [APB2OPB_OPB1_WRITE_WORD_ENDIAN] = 0x00117717,
>>>> + [APB2OPB_OPB1_WRITE_BYTE_ENDIAN] = 0xffaa5500,
>>>> + [APB2OPB_OPB0_READ_BYTE_ENDIAN] = 0x0044eee4,
>>>> + [APB2OPB_OPB1_READ_BYTE_ENDIAN] = 0x00117717
>>>> +};
>>>> +
>>>> +static uint64_t fsi_aspeed_apb2opb_read(void *opaque, hwaddr addr,
>>>> + unsigned size)
>>>> +{
>>>> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque);
>>>> +
>>>> + trace_fsi_aspeed_apb2opb_read(addr, size);
>>>> +
>>>> + if (addr + size > sizeof(s->regs)) {
>>>
>>>
>>> hmm, the parameter 'size' is a memop transaction size not an address
>>> offset.
>> OK, Changed it to validate the register (index) instead of addr + size.
>>>
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "%s: Out of bounds read: 0x%"HWADDR_PRIx"
>>>> for %u\n",
>>>> + __func__, addr, size);
>>>> + return 0;
>>>> + }
>>>> +
>>>> + return s->regs[TO_REG(addr)];
>>>> +}
>>>> +
>>>> +static void fsi_aspeed_apb2opb_write(void *opaque, hwaddr addr,
>>>> uint64_t data,
>>>> + unsigned size)
>>>> +{
>>>> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque);
>>>> +
>>>> + trace_fsi_aspeed_apb2opb_write(addr, size, data);
>>>> +
>>>> + if (addr + size > sizeof(s->regs)) {
>>>
>>> same comment.
>> Fixed it same as above.
>>>
>>>
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "%s: Out of bounds write: %"HWADDR_PRIx" for
>>>> %u\n",
>>>> + __func__, addr, size);
>>>> + return;
>>>> + }
>>>> +
>>>> + switch (TO_REG(addr)) {
>>>> + case APB2OPB_CONTROL:
>>>> + fsi_opb_fsi_master_address(&s->opb[0], data &
>>>> APB2OPB_CONTROL_OFF);
>>>
>>> fsi_opb_fsi_master_address() should statically defined in this file
>> We have separation of OPB bus implementation and APB2OPB interface.
>> If we move this function here then we will be exposing OPB
>> implementation here.
Defined a static function and removed from opb.c
>>>
>>>> + break;
>>>> + case APB2OPB_OPB2FSI:
>>>> + fsi_opb_opb2fsi_address(&s->opb[0], data &
>>>> APB2OPB_OPB2FSI_OFF);
>>>
>>>
>>> same for fsi_opb_opb2fsi_address()
>> Same as above.
Same as above.
>>>
>>>> + break;
>>>> + case APB2OPB_OPB0_WRITE_WORD_ENDIAN:
>>>> + if (data != APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE) {
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "%s: Bridge needs to be driven as BE
>>>> (0x%x)\n",
>>>> + __func__,
>>>> APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE);
>>>> + }
>>>> + break;
>>>> + case APB2OPB_OPB0_WRITE_BYTE_ENDIAN:
>>>> + if (data != APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE) {
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "%s: Bridge needs to be driven as BE
>>>> (0x%x)\n",
>>>> + __func__,
>>>> APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE);
>>>> + }
>>>> + break;
>>>> + case APB2OPB_OPB0_READ_BYTE_ENDIAN:
>>>> + if (data != APB2OPB_OPB0_READ_WORD_ENDIAN_BE) {
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "%s: Bridge needs to be driven as BE
>>>> (0x%x)\n",
>>>> + __func__,
>>>> APB2OPB_OPB0_READ_WORD_ENDIAN_BE);
>>>> + }
>>>> + break;
>>>> + case APB2OPB_TRIGGER:
>>>> + {
>>>> + uint32_t opb, op_mode, op_size, op_addr, op_data;
>>>> +
>>>> + assert((s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) ^
>>>> + (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN));
>>>> +
>>>> + if (s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) {
>>>> + opb = 0;
>>>> + op_mode = s->regs[APB2OPB_OPB0_MODE];
>>>> + op_size = s->regs[APB2OPB_OPB0_XFER];
>>>> + op_addr = s->regs[APB2OPB_OPB0_ADDR];
>>>> + op_data = s->regs[APB2OPB_OPB0_WRITE_DATA];
>>>> + } else if (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN) {
>>>> + opb = 1;
>>>> + op_mode = s->regs[APB2OPB_OPB1_MODE];
>>>> + op_size = s->regs[APB2OPB_OPB1_XFER];
>>>> + op_addr = s->regs[APB2OPB_OPB1_ADDR];
>>>> + op_data = s->regs[APB2OPB_OPB1_WRITE_DATA];
>>>> + } else {
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "%s: Invalid operation: 0x%"HWADDR_PRIx"
>>>> for %u\n",
>>>> + __func__, addr, size);
>>>> + return;
>>>> + }
>>>> +
>>>> + if (op_size & ~(APB2OPB_OPB_XFER_HALF |
>>>> APB2OPB_OPB_XFER_FULL)) {
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "OPB transaction failed: Unrecognised
>>>> access width: %d\n",
>>>
>>> Unrecognized
>> Fixed
>>>
>>>> + op_size);
>>>> + return;
>>>> + }
>>>> +
>>>> + op_size += 1;
>>>> +
>>>> + if (op_mode & APB2OPB_OPB_MODE_RD) {
>>>> + int index = opb ? APB2OPB_OPB1_READ_DATA
>>>> + : APB2OPB_OPB0_READ_DATA;
>>>> +
>>>> + switch (op_size) {
>>>> + case 1:
>>>> + s->regs[index] = fsi_opb_read8(&s->opb[opb],
>>>> op_addr);
>>>> + break;
>>>> + case 2:
>>>> + s->regs[index] = fsi_opb_read16(&s->opb[opb],
>>>> op_addr);
>>>> + break;
>>>> + case 4:
>>>> + s->regs[index] = fsi_opb_read32(&s->opb[opb],
>>>> op_addr);
>>>> + break;
>>>> + default:
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "%s: Size not supported: %u\n",
>>>> + __func__, size);
>>>
>>> this should use op_size and not size and seems redudant with
>>> the unrecognized test above.
>> true, Keeping it in case bits meaning change in future.
>>>
>>>
>>>> + return;
>>>> + }
>>>> + } else {
>>>> + /* FIXME: Endian swizzling */
>>>> + switch (op_size) {
>>>> + case 1:
>>>> + fsi_opb_write8(&s->opb[opb], op_addr, op_data);
>>>> + break;
>>>> + case 2:
>>>> + fsi_opb_write16(&s->opb[opb], op_addr, op_data);
>>>> + break;
>>>> + case 4:
>>>> + fsi_opb_write32(&s->opb[opb], op_addr, op_data);
>>>> + break;
>>>> + default:
>>>> + qemu_log_mask(LOG_GUEST_ERROR,
>>>> + "%s: Size not supported: %u\n",
>>>> + __func__, op_size);
>>>> + return;
>>>> + }
>>>> + }
>>>
>>>
>>> The above is equivalent to :
>>>
>>> MemTxResult result;
>>> bool is_write = !(op_mode & APB2OPB_OPB_MODE_RD);
>>> int index = opb ? APB2OPB_OPB1_READ_DATA :
>>> APB2OPB_OPB0_READ_DATA;
>>> AddressSpace *as = &s->opb[opb].as;
>>>
>>> result = address_space_rw(as, op_addr, MEMTXATTRS_UNSPECIFIED,
>>> &op_data, op_size, is_write);
>>> if (result != MEMTX_OK) {
>>> qemu_log_mask(LOG_GUEST_ERROR, "%s: OPB %s failed @%08x\n",
>>> __func__, is_write ? "write" : "read",
>>> op_addr);
>>> return;
>>> }
>>>
>>> if (!is_write) {
>>> s->regs[index] = op_data;
>>> }
>>>
>>> and the fsi_opb_* routines are useless to me.
>> We are trying to keep the separation between OPB implementation and
>> interface hence we have all those fsi_opb_*. I feel that we should
>> keep as it is so that future extensions will be easier. Please let me
>> know.
>
> Well, I can't really tell because I don't know enough about FSI :/
>
> The models look fragile and I have spent already a lot of time trying
> to untangle what they are trying to do. Please ask your teammates or
> let's see in the next QEMU cycle.
I have decided to go with the approach you suggested and it looks much
better. Fixed it.
Thanks for the review.
Regards,
Ninad
>
> Thanks,
>
> C.
>
>
next prev parent reply other threads:[~2023-10-26 15:27 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-21 21:17 [PATCH v6 00/10] Introduce model for IBM's FSI Ninad Palsule
2023-10-21 21:17 ` [PATCH v6 01/10] hw/fsi: Introduce IBM's Local bus Ninad Palsule
2023-10-23 14:58 ` Philippe Mathieu-Daudé
2023-10-23 17:10 ` Ninad Palsule
2023-10-21 21:17 ` [PATCH v6 02/10] hw/fsi: Introduce IBM's scratchpad Ninad Palsule
2023-10-23 15:00 ` Philippe Mathieu-Daudé
2023-10-23 17:08 ` Ninad Palsule
2023-10-24 7:08 ` Philippe Mathieu-Daudé
2023-10-26 15:24 ` Ninad Palsule
2023-10-21 21:17 ` [PATCH v6 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave Ninad Palsule
2023-10-21 21:17 ` [PATCH v6 04/10] hw/fsi: Introduce IBM's FSI Ninad Palsule
2023-10-21 21:17 ` [PATCH v6 05/10] hw/fsi: IBM's On-chip Peripheral Bus Ninad Palsule
2023-10-21 21:17 ` [PATCH v6 06/10] hw/fsi: Aspeed APB2OPB interface Ninad Palsule
2023-10-24 7:46 ` Cédric Le Goater
2023-10-24 15:00 ` Ninad Palsule
2023-10-24 15:21 ` Cédric Le Goater
2023-10-24 18:42 ` Ninad Palsule
2023-10-26 15:27 ` Ninad Palsule [this message]
2023-10-27 5:25 ` Andrew Jeffery
2023-10-21 21:17 ` [PATCH v6 07/10] hw/arm: Hook up FSI module in AST2600 Ninad Palsule
2023-10-23 15:03 ` Philippe Mathieu-Daudé
2023-10-21 21:17 ` [PATCH v6 08/10] hw/fsi: Added qtest Ninad Palsule
2023-10-23 6:51 ` Thomas Huth
2023-10-23 15:25 ` Ninad Palsule
2023-10-24 7:34 ` Cédric Le Goater
2023-10-26 15:30 ` Ninad Palsule
2023-10-21 21:17 ` [PATCH v6 09/10] hw/fsi: Added FSI documentation Ninad Palsule
2023-10-24 7:37 ` Cédric Le Goater
2023-10-26 15:32 ` Ninad Palsule
2023-10-21 21:17 ` [PATCH v6 10/10] hw/fsi: Update MAINTAINER list Ninad Palsule
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8269cf50-05d1-4f57-8fc8-0a074721a0df@linux.ibm.com \
--to=ninad@linux.ibm.com \
--cc=andrew@aj.id.au \
--cc=andrew@codeconstruct.com.au \
--cc=berrange@redhat.com \
--cc=clg@kaod.org \
--cc=joel@jms.id.au \
--cc=lvivier@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).