[PATCH qemu 10/12] ast2400: add a BT device
Andrew Jeffery
andrew at aj.id.au
Tue Jun 7 17:15:35 AEST 2016
On Sun, 2016-05-29 at 23:20 +0200, Cédric Le Goater wrote:
> This is an dummy empty shell for the moment. The plan would be to plug
> this device in the IPMI framework already available in qemu and work
> on a backend to connect it to an external host (a powernv guest) or a
> ipmi-host simulator.
>
> Signed-off-by: Cédric Le Goater <clg at kaod.org>
> ---
> hw/arm/ast2400.c | 17 +++++
> hw/misc/Makefile.objs | 2 +-
> hw/misc/aspeed_bt.c | 175 ++++++++++++++++++++++++++++++++++++++++++++
> include/hw/arm/ast2400.h | 2 +
> include/hw/misc/aspeed_bt.h | 31 ++++++++
> 5 files changed, 226 insertions(+), 1 deletion(-)
> create mode 100644 hw/misc/aspeed_bt.c
> create mode 100644 include/hw/misc/aspeed_bt.h
>
> diff --git a/hw/arm/ast2400.c b/hw/arm/ast2400.c
> index 8f678983cee5..a4a7c10e4361 100644
> --- a/hw/arm/ast2400.c
> +++ b/hw/arm/ast2400.c
> @@ -29,6 +29,8 @@
> #define AST2400_VIC_BASE 0x1E6C0000
> #define AST2400_SCU_BASE 0x1E6E2000
> #define AST2400_TIMER_BASE 0x1E782000
> +#define AST2400_LPC_BASE 0x1E789000
> +#define AST2400_IBT_BASE (AST2400_LPC_BASE + 0x140)
> #define AST2400_I2C_BASE 0x1E78A000
>
> static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
> @@ -88,6 +90,11 @@ static void ast2400_init(Object *obj)
> object_initialize(&s->spi, sizeof(s->spi), TYPE_ASPEED_SMC);
> object_property_add_child(obj, "spi", OBJECT(&s->spi), NULL);
> qdev_set_parent_bus(DEVICE(&s->spi), sysbus_get_default());
> + qdev_set_parent_bus(DEVICE(&s->i2c), sysbus_get_default());
> +
> + object_initialize(&s->bt, sizeof(s->bt), TYPE_ASPEED_BT);
> + object_property_add_child(obj, "bt", OBJECT(&s->bt), NULL);
> + qdev_set_parent_bus(DEVICE(&s->bt), sysbus_get_default());
> }
>
> static void ast2400_realize(DeviceState *dev, Error **errp)
> @@ -204,6 +211,16 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
> return;
> }
> sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, AST2400_SPI_BASE);
> +
> + /* iBT */
> + object_property_set_bool(OBJECT(&s->bt), true, "realized", &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->bt), 0, AST2400_IBT_BASE);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->bt), 0,
> + qdev_get_gpio_in(DEVICE(&s->vic), 10));
> }
>
> static void ast2400_class_init(ObjectClass *oc, void *data)
> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
> index e50596965b03..b2931f85f097 100644
> --- a/hw/misc/Makefile.objs
> +++ b/hw/misc/Makefile.objs
> @@ -51,4 +51,4 @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
> obj-$(CONFIG_PVPANIC) += pvpanic.o
> obj-$(CONFIG_EDU) += edu.o
> obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
> -obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o
> +obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_bt.o
> diff --git a/hw/misc/aspeed_bt.c b/hw/misc/aspeed_bt.c
> new file mode 100644
> index 000000000000..496c9aa0be4a
> --- /dev/null
> +++ b/hw/misc/aspeed_bt.c
> @@ -0,0 +1,175 @@
> +/*
> + * ASPEED iBT Device
> + *
> + * Copyright 2016 IBM Corp.
> + *
> + * This code is licensed under the GPL version 2 or later. See
> + * the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include
> +#include "hw/misc/aspeed_bt.h"
> +#include "hw/qdev-properties.h"
> +#include "qemu/bitops.h"
> +#include "trace.h"
> +
> +#ifdef ASPEED_BT_DEBUG
> +#define DB_PRINT(fmt, ...) do { \
> + fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \
> + } while (0);
> +#else
> + #define DB_PRINT(...) do {} while (0)
> +#endif
If they're worth keeping should we switch to trace events?
> +
> +#define BT_IO_REGION_SIZE 0x1C
> +
> +#define TO_REG(o) (o >> 2)
> +
> +#define BT_CR0 0x0
> +#define BT_CR0_IO_BASE 16
> +#define BT_CR0_IRQ 12
How were you planning to use BT_CR0_IO_BASE and BT_CR0_IRQ? They don't
seem to correspond to obvious fields in CR0. They don't appear to be
used by the code though.
> +#define BT_CR0_EN_CLR_SLV_RDP 0x8
> +#define BT_CR0_EN_CLR_SLV_WRP 0x4
> +#define BT_CR0_ENABLE_IBT 0x1
> +#define BT_CR1 0x4
> +#define BT_CR1_IRQ_H2B 0x01
> +#define BT_CR1_IRQ_HBUSY 0x40
> +#define BT_CR2 0x8
> +#define BT_CR2_IRQ_H2B 0x01
> +#define BT_CR2_IRQ_HBUSY 0x40
> +#define BT_CR3 0xc
> +#define BT_CTRL 0x10
The alignment of the value is a bit misleading - indented too far?
> +#define BT_CTRL_B_BUSY 0x80
> +#define BT_CTRL_H_BUSY 0x40
> +#define BT_CTRL_OEM0 0x20
> +#define BT_CTRL_SMS_ATN 0x10
> +#define BT_CTRL_B2H_ATN 0x08
> +#define BT_CTRL_H2B_ATN 0x04
> +#define BT_CTRL_CLR_RD_PTR 0x02
> +#define BT_CTRL_CLR_WR_PTR 0x01
> +#define BT_BMC2HOST 0x14
> +#define BT_INTMASK 0x18
> +#define BT_INTMASK_B2H_IRQEN 0x01
> +#define BT_INTMASK_B2H_IRQ 0x02
> +#define BT_INTMASK_BMC_HWRST 0x80
> +
> +static uint64_t aspeed_bt_read(void *opaque, hwaddr offset, unsigned size)
> +{
> + AspeedBTState *s = ASPEED_BT(opaque);
> +
> + DB_PRINT("To 0x%" HWADDR_PRIx " of size %u\n", offset, size);
> +
> + if (TO_REG(offset) >= ARRAY_SIZE(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + return 0;
> + }
> +
> + switch (offset) {
> + case 0x00 ... 0x18:
> + break;
> + default:
> + qemu_log_mask(LOG_UNIMP,
> + "%s: Read from uninitialised register 0x%"
> + HWADDR_PRIx "\n", __func__, offset);
> + break;
> + }
> +
> + return s->regs[TO_REG(offset)];
> +}
> +
> +static void aspeed_bt_write(void *opaque, hwaddr offset, uint64_t data,
> + unsigned size)
> +{
> + AspeedBTState *s = ASPEED_BT(opaque);
> +
> + DB_PRINT("To 0x%" HWADDR_PRIx " of size %u: 0x%" PRIx64"\n",
> + offset, size, data);
> +
> + if (TO_REG(offset) >= ARRAY_SIZE(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> + __func__, offset);
> + return;
> + }
> +
> + switch (offset) {
> + case 0x00 ... 0x18:
> + break;
> + default:
> + qemu_log_mask(LOG_UNIMP,
> + "%s: Write to uninitialised register 0x%"
> + HWADDR_PRIx "\n", __func__, offset);
> + break;
> + }
> +
> + s->regs[TO_REG(offset)] = (uint32_t) data;
> +}
> +
> +static const MemoryRegionOps aspeed_bt_ops = {
> + .read = aspeed_bt_read,
> + .write = aspeed_bt_write,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> + .valid.min_access_size = 4,
> + .valid.max_access_size = 4,
> + .valid.unaligned = false,
> +};
> +
> +static void aspeed_bt_reset(DeviceState *dev)
> +{
> + AspeedBTState *s = ASPEED_BT(dev);
> +
> + memset(s->regs, 0, sizeof(s->regs));
> +}
> +
> +static void aspeed_bt_realize(DeviceState *dev, Error **errp)
> +{
> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> + AspeedBTState *s = ASPEED_BT(dev);
> +
> + sysbus_init_irq(sbd, &s->irq);
> + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_bt_ops, s,
> + TYPE_ASPEED_BT, BT_IO_REGION_SIZE);
> +
> + sysbus_init_mmio(sbd, &s->iomem);
> +}
> +
> +static Property aspeed_bt_props[] = {
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static const VMStateDescription vmstate_aspeed_bt = {
> + .name = "aspeed.bt",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT32_ARRAY(regs, AspeedBTState, ASPEED_BT_NR_REGS),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> +static void aspeed_bt_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + dc->realize = aspeed_bt_realize;
> + dc->reset = aspeed_bt_reset;
> + dc->desc = "ASPEED iBT Device";
> + dc->vmsd = &vmstate_aspeed_bt;
> + dc->props = aspeed_bt_props;
> +}
> +
> +static const TypeInfo aspeed_bt_info = {
> + .name = TYPE_ASPEED_BT,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(AspeedBTState),
> + .class_init = aspeed_bt_class_init,
> +};
> +
> +static void aspeed_bt_register_types(void)
> +{
> + type_register_static(&aspeed_bt_info);
> +}
> +
> +type_init(aspeed_bt_register_types);
> diff --git a/include/hw/arm/ast2400.h b/include/hw/arm/ast2400.h
> index 9ba4245619c1..2b517e89eeea 100644
> --- a/include/hw/arm/ast2400.h
> +++ b/include/hw/arm/ast2400.h
> @@ -18,6 +18,7 @@
> #include "hw/timer/aspeed_timer.h"
> #include "hw/i2c/aspeed_i2c.h"
> #include "hw/ssi/aspeed_smc.h"
> +#include "hw/misc/aspeed_bt.h"
>
> typedef struct AST2400State {
> /*< private >*/
> @@ -33,6 +34,7 @@ typedef struct AST2400State {
> AspeedI2CState i2c;
> AspeedSMCState smc;
> AspeedSMCState spi;
> + AspeedBTState bt;
> } AST2400State;
>
> #define TYPE_AST2400 "ast2400"
> diff --git a/include/hw/misc/aspeed_bt.h b/include/hw/misc/aspeed_bt.h
> new file mode 100644
> index 000000000000..1e9aa9510959
> --- /dev/null
> +++ b/include/hw/misc/aspeed_bt.h
> @@ -0,0 +1,31 @@
> +/*
> + * ASPEED iBT Device
> + *
> + * Copyright 2016 IBM Corp.
> + *
> + * This code is licensed under the GPL version 2 or later. See
> + * the COPYING file in the top-level directory.
> + */
> +#ifndef ASPEED_BT_H
> +#define ASPEED_BT_H
> +
> +#include "hw/sysbus.h"
> +
> +#define TYPE_ASPEED_BT "aspeed.bt"
> +#define ASPEED_BT(obj) OBJECT_CHECK(AspeedBTState, (obj), TYPE_ASPEED_BT)
> +
> +#define ASPEED_BT_NR_REGS (0x1C >> 2)
> +
> +typedef struct AspeedBTState {
> + /*< private >*/
> + SysBusDevice parent_obj;
> +
> + /*< public >*/
> + MemoryRegion iomem;
> + qemu_irq irq;
> +
> + uint32_t regs[ASPEED_BT_NR_REGS];
> +
> +} AspeedBTState;
> +
> +#endif /* ASPEED_BT_H */
Cheers,
Andrew
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.ozlabs.org/pipermail/openbmc/attachments/20160607/7e700673/attachment.sig>
More information about the openbmc
mailing list