All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card
@ 2022-12-18 21:19 Strahinja Jankovic
  2022-12-18 21:19 ` [PATCH v2 1/7] hw/misc: Allwinner-A10 Clock Controller Module Emulation Strahinja Jankovic
                   ` (7 more replies)
  0 siblings, 8 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

This patch series adds missing Allwinner A10 modules needed for
successful SPL boot:
- Clock controller module
- DRAM controller
- I2C0 controller (added also for Allwinner H3 since it is the same)
- AXP-209 connected to I2C0 bus

It also updates Allwinner A10 emulation so SPL is copied from attached
SD card if `-kernel` parameter is not passed when starting QEMU
(approach adapted from Allwinner H3 implementation).

Boot from SD card has been tested with Cubieboard Armbian SD card image and custom
Yocto image built for Cubieboard.
Example usage for Armbian image:
qemu-system-arm -M cubieboard -nographic -sd ~/Armbian_22.11.0-trunk_Cubieboard_kinetic_edge_6.0.7.img

v2 from v1:
* replaced DB_PRINTF with tracing functions
* removed .init function in AXP209 since .reset covers functionality
* moved defines to allwinner_i2c.c from header file
* updated docs with information about TWI
* minor code style fixes

Strahinja Jankovic (7):
  hw/misc: Allwinner-A10 Clock Controller Module Emulation
  hw/misc: Allwinner A10 DRAM Controller Emulation
  hw/i2c: Allwinner TWI/I2C Emulation
  hw/misc: Allwinner AXP-209 Emulation
  hw/arm: Add AXP-209 to Cubieboard
  hw/arm: Allwinner A10 enable SPL load from MMC
  docs/system/arm: Update Allwinner with TWI (I2C)

 docs/system/arm/cubieboard.rst        |   1 +
 docs/system/arm/orangepi.rst          |   1 +
 hw/arm/Kconfig                        |   5 +
 hw/arm/allwinner-a10.c                |  40 +++
 hw/arm/allwinner-h3.c                 |  11 +-
 hw/arm/cubieboard.c                   |  11 +
 hw/i2c/Kconfig                        |   4 +
 hw/i2c/allwinner-i2c.c                | 459 ++++++++++++++++++++++++++
 hw/i2c/meson.build                    |   1 +
 hw/i2c/trace-events                   |   5 +
 hw/misc/Kconfig                       |  10 +
 hw/misc/allwinner-a10-ccm.c           | 224 +++++++++++++
 hw/misc/allwinner-a10-dramc.c         | 179 ++++++++++
 hw/misc/allwinner-axp-209.c           | 238 +++++++++++++
 hw/misc/meson.build                   |   3 +
 hw/misc/trace-events                  |   5 +
 include/hw/arm/allwinner-a10.h        |  27 ++
 include/hw/arm/allwinner-h3.h         |   3 +
 include/hw/i2c/allwinner-i2c.h        |  55 +++
 include/hw/misc/allwinner-a10-ccm.h   |  67 ++++
 include/hw/misc/allwinner-a10-dramc.h |  68 ++++
 21 files changed, 1416 insertions(+), 1 deletion(-)
 create mode 100644 hw/i2c/allwinner-i2c.c
 create mode 100644 hw/misc/allwinner-a10-ccm.c
 create mode 100644 hw/misc/allwinner-a10-dramc.c
 create mode 100644 hw/misc/allwinner-axp-209.c
 create mode 100644 include/hw/i2c/allwinner-i2c.h
 create mode 100644 include/hw/misc/allwinner-a10-ccm.h
 create mode 100644 include/hw/misc/allwinner-a10-dramc.h

-- 
2.30.2



^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v2 1/7] hw/misc: Allwinner-A10 Clock Controller Module Emulation
  2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
@ 2022-12-18 21:19 ` Strahinja Jankovic
  2022-12-18 21:19 ` [PATCH v2 2/7] hw/misc: Allwinner A10 DRAM Controller Emulation Strahinja Jankovic
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

During SPL boot several Clock Controller Module (CCM) registers are
read, most important are PLL and Tuning, as well as divisor registers.

This patch adds these registers and initializes reset values from user's
guide.

Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>

Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
---
 hw/arm/Kconfig                      |   1 +
 hw/arm/allwinner-a10.c              |   7 +
 hw/misc/Kconfig                     |   3 +
 hw/misc/allwinner-a10-ccm.c         | 224 ++++++++++++++++++++++++++++
 hw/misc/meson.build                 |   1 +
 include/hw/arm/allwinner-a10.h      |   2 +
 include/hw/misc/allwinner-a10-ccm.h |  67 +++++++++
 7 files changed, 305 insertions(+)
 create mode 100644 hw/misc/allwinner-a10-ccm.c
 create mode 100644 include/hw/misc/allwinner-a10-ccm.h

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 17fcde8e1c..14f52b41af 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -319,6 +319,7 @@ config ALLWINNER_A10
     select AHCI
     select ALLWINNER_A10_PIT
     select ALLWINNER_A10_PIC
+    select ALLWINNER_A10_CCM
     select ALLWINNER_EMAC
     select SERIAL
     select UNIMP
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index 79082289ea..86baeeeca2 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -26,6 +26,7 @@
 #include "hw/usb/hcd-ohci.h"
 
 #define AW_A10_MMC0_BASE        0x01c0f000
+#define AW_A10_CCM_BASE         0x01c20000
 #define AW_A10_PIC_REG_BASE     0x01c20400
 #define AW_A10_PIT_REG_BASE     0x01c20c00
 #define AW_A10_UART0_REG_BASE   0x01c28000
@@ -46,6 +47,8 @@ static void aw_a10_init(Object *obj)
 
     object_initialize_child(obj, "timer", &s->timer, TYPE_AW_A10_PIT);
 
+    object_initialize_child(obj, "ccm", &s->ccm, TYPE_AW_A10_CCM);
+
     object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
 
     object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
@@ -103,6 +106,10 @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion(get_system_memory(), 0x00000000, &s->sram_a);
     create_unimplemented_device("a10-sram-ctrl", 0x01c00000, 4 * KiB);
 
+    /* Clock Control Module */
+    sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, AW_A10_CCM_BASE);
+
     /* FIXME use qdev NIC properties instead of nd_table[] */
     if (nd_table[0].used) {
         qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index cbabe9f78c..ed07bf4133 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -174,4 +174,7 @@ config VIRT_CTRL
 config LASI
     bool
 
+config ALLWINNER_A10_CCM
+    bool
+
 source macio/Kconfig
diff --git a/hw/misc/allwinner-a10-ccm.c b/hw/misc/allwinner-a10-ccm.c
new file mode 100644
index 0000000000..68146ee340
--- /dev/null
+++ b/hw/misc/allwinner-a10-ccm.c
@@ -0,0 +1,224 @@
+/*
+ * Allwinner A10 Clock Control Module emulation
+ *
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ *  This file is derived from Allwinner H3 CCU,
+ *  by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 "qemu/osdep.h"
+#include "qemu/units.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/misc/allwinner-a10-ccm.h"
+
+/* CCM register offsets */
+enum {
+    REG_PLL1_CFG             = 0x0000, /* PLL1 Control */
+    REG_PLL1_TUN             = 0x0004, /* PLL1 Tuning */
+    REG_PLL2_CFG             = 0x0008, /* PLL2 Control */
+    REG_PLL2_TUN             = 0x000C, /* PLL2 Tuning */
+    REG_PLL3_CFG             = 0x0010, /* PLL3 Control */
+    REG_PLL4_CFG             = 0x0018, /* PLL4 Control */
+    REG_PLL5_CFG             = 0x0020, /* PLL5 Control */
+    REG_PLL5_TUN             = 0x0024, /* PLL5 Tuning */
+    REG_PLL6_CFG             = 0x0028, /* PLL6 Control */
+    REG_PLL6_TUN             = 0x002C, /* PLL6 Tuning */
+    REG_PLL7_CFG             = 0x0030, /* PLL7 Control */
+    REG_PLL1_TUN2            = 0x0038, /* PLL1 Tuning2 */
+    REG_PLL5_TUN2            = 0x003C, /* PLL5 Tuning2 */
+    REG_PLL8_CFG             = 0x0040, /* PLL8 Control */
+    REG_OSC24M_CFG           = 0x0050, /* OSC24M Control */
+    REG_CPU_AHB_APB0_CFG     = 0x0054, /* CPU, AHB and APB0 Divide Ratio */
+};
+
+#define REG_INDEX(offset)    (offset / sizeof(uint32_t))
+
+/* CCM register reset values */
+enum {
+    REG_PLL1_CFG_RST         = 0x21005000,
+    REG_PLL1_TUN_RST         = 0x0A101000,
+    REG_PLL2_CFG_RST         = 0x08100010,
+    REG_PLL2_TUN_RST         = 0x00000000,
+    REG_PLL3_CFG_RST         = 0x0010D063,
+    REG_PLL4_CFG_RST         = 0x21009911,
+    REG_PLL5_CFG_RST         = 0x11049280,
+    REG_PLL5_TUN_RST         = 0x14888000,
+    REG_PLL6_CFG_RST         = 0x21009911,
+    REG_PLL6_TUN_RST         = 0x00000000,
+    REG_PLL7_CFG_RST         = 0x0010D063,
+    REG_PLL1_TUN2_RST        = 0x00000000,
+    REG_PLL5_TUN2_RST        = 0x00000000,
+    REG_PLL8_CFG_RST         = 0x21009911,
+    REG_OSC24M_CFG_RST       = 0x00138013,
+    REG_CPU_AHB_APB0_CFG_RST = 0x00010010,
+};
+
+static uint64_t allwinner_a10_ccm_read(void *opaque, hwaddr offset,
+                                       unsigned size)
+{
+    const AwA10ClockCtlState *s = AW_A10_CCM(opaque);
+    const uint32_t idx = REG_INDEX(offset);
+
+    switch (offset) {
+    case REG_PLL1_CFG:
+    case REG_PLL1_TUN:
+    case REG_PLL2_CFG:
+    case REG_PLL2_TUN:
+    case REG_PLL3_CFG:
+    case REG_PLL4_CFG:
+    case REG_PLL5_CFG:
+    case REG_PLL5_TUN:
+    case REG_PLL6_CFG:
+    case REG_PLL6_TUN:
+    case REG_PLL7_CFG:
+    case REG_PLL1_TUN2:
+    case REG_PLL5_TUN2:
+    case REG_PLL8_CFG:
+    case REG_OSC24M_CFG:
+    case REG_CPU_AHB_APB0_CFG:
+        break;
+    case 0x158 ... AW_A10_CCM_IOSIZE:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
+                      __func__, (uint32_t)offset);
+        return 0;
+    default:
+        qemu_log_mask(LOG_UNIMP, "%s: unimplemented read offset 0x%04x\n",
+                      __func__, (uint32_t)offset);
+        return 0;
+    }
+
+    return s->regs[idx];
+}
+
+static void allwinner_a10_ccm_write(void *opaque, hwaddr offset,
+                                   uint64_t val, unsigned size)
+{
+    AwA10ClockCtlState *s = AW_A10_CCM(opaque);
+    const uint32_t idx = REG_INDEX(offset);
+
+    switch (offset) {
+    case REG_PLL1_CFG:
+    case REG_PLL1_TUN:
+    case REG_PLL2_CFG:
+    case REG_PLL2_TUN:
+    case REG_PLL3_CFG:
+    case REG_PLL4_CFG:
+    case REG_PLL5_CFG:
+    case REG_PLL5_TUN:
+    case REG_PLL6_CFG:
+    case REG_PLL6_TUN:
+    case REG_PLL7_CFG:
+    case REG_PLL1_TUN2:
+    case REG_PLL5_TUN2:
+    case REG_PLL8_CFG:
+    case REG_OSC24M_CFG:
+    case REG_CPU_AHB_APB0_CFG:
+        break;
+    case 0x158 ... AW_A10_CCM_IOSIZE:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
+                      __func__, (uint32_t)offset);
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
+                      __func__, (uint32_t)offset);
+        break;
+    }
+
+    s->regs[idx] = (uint32_t) val;
+}
+
+static const MemoryRegionOps allwinner_a10_ccm_ops = {
+    .read = allwinner_a10_ccm_read,
+    .write = allwinner_a10_ccm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl.min_access_size = 4,
+};
+
+static void allwinner_a10_ccm_reset_enter(Object *obj, ResetType type)
+{
+    AwA10ClockCtlState *s = AW_A10_CCM(obj);
+
+    /* Set default values for registers */
+    s->regs[REG_INDEX(REG_PLL1_CFG)] = REG_PLL1_CFG_RST;
+    s->regs[REG_INDEX(REG_PLL1_TUN)] = REG_PLL1_TUN_RST;
+    s->regs[REG_INDEX(REG_PLL2_CFG)] = REG_PLL2_CFG_RST;
+    s->regs[REG_INDEX(REG_PLL2_TUN)] = REG_PLL2_TUN_RST;
+    s->regs[REG_INDEX(REG_PLL3_CFG)] = REG_PLL3_CFG_RST;
+    s->regs[REG_INDEX(REG_PLL4_CFG)] = REG_PLL4_CFG_RST;
+    s->regs[REG_INDEX(REG_PLL5_CFG)] = REG_PLL5_CFG_RST;
+    s->regs[REG_INDEX(REG_PLL5_TUN)] = REG_PLL5_TUN_RST;
+    s->regs[REG_INDEX(REG_PLL6_CFG)] = REG_PLL6_CFG_RST;
+    s->regs[REG_INDEX(REG_PLL6_TUN)] = REG_PLL6_TUN_RST;
+    s->regs[REG_INDEX(REG_PLL7_CFG)] = REG_PLL7_CFG_RST;
+    s->regs[REG_INDEX(REG_PLL1_TUN2)] = REG_PLL1_TUN2_RST;
+    s->regs[REG_INDEX(REG_PLL5_TUN2)] = REG_PLL5_TUN2_RST;
+    s->regs[REG_INDEX(REG_PLL8_CFG)] = REG_PLL8_CFG_RST;
+    s->regs[REG_INDEX(REG_OSC24M_CFG)] = REG_OSC24M_CFG_RST;
+    s->regs[REG_INDEX(REG_CPU_AHB_APB0_CFG)] = REG_CPU_AHB_APB0_CFG_RST;
+}
+
+static void allwinner_a10_ccm_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    AwA10ClockCtlState *s = AW_A10_CCM(obj);
+
+    /* Memory mapping */
+    memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_a10_ccm_ops, s,
+                          TYPE_AW_A10_CCM, AW_A10_CCM_IOSIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static const VMStateDescription allwinner_a10_ccm_vmstate = {
+    .name = "allwinner-a10-ccm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, AwA10ClockCtlState, AW_A10_CCM_REGS_NUM),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void allwinner_a10_ccm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.enter = allwinner_a10_ccm_reset_enter;
+    dc->vmsd = &allwinner_a10_ccm_vmstate;
+}
+
+static const TypeInfo allwinner_a10_ccm_info = {
+    .name          = TYPE_AW_A10_CCM,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_init = allwinner_a10_ccm_init,
+    .instance_size = sizeof(AwA10ClockCtlState),
+    .class_init    = allwinner_a10_ccm_class_init,
+};
+
+static void allwinner_a10_ccm_register(void)
+{
+    type_register_static(&allwinner_a10_ccm_info);
+}
+
+type_init(allwinner_a10_ccm_register)
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index ed0598dc9e..c828dbeb26 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -38,6 +38,7 @@ subdir('macio')
 
 softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
 
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
 specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
index a76dc7b84d..45d0fc2f7e 100644
--- a/include/hw/arm/allwinner-a10.h
+++ b/include/hw/arm/allwinner-a10.h
@@ -12,6 +12,7 @@
 #include "hw/usb/hcd-ohci.h"
 #include "hw/usb/hcd-ehci.h"
 #include "hw/rtc/allwinner-rtc.h"
+#include "hw/misc/allwinner-a10-ccm.h"
 
 #include "target/arm/cpu.h"
 #include "qom/object.h"
@@ -30,6 +31,7 @@ struct AwA10State {
     /*< public >*/
 
     ARMCPU cpu;
+    AwA10ClockCtlState ccm;
     AwA10PITState timer;
     AwA10PICState intc;
     AwEmacState emac;
diff --git a/include/hw/misc/allwinner-a10-ccm.h b/include/hw/misc/allwinner-a10-ccm.h
new file mode 100644
index 0000000000..7f22532efa
--- /dev/null
+++ b/include/hw/misc/allwinner-a10-ccm.h
@@ -0,0 +1,67 @@
+/*
+ * Allwinner A10 Clock Control Module emulation
+ *
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ *  This file is derived from Allwinner H3 CCU,
+ *  by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/>.
+ */
+
+#ifndef HW_MISC_ALLWINNER_A10_CCM_H
+#define HW_MISC_ALLWINNER_A10_CCM_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+/**
+ * @name Constants
+ * @{
+ */
+
+/** Size of register I/O address space used by CCM device */
+#define AW_A10_CCM_IOSIZE        (0x400)
+
+/** Total number of known registers */
+#define AW_A10_CCM_REGS_NUM      (AW_A10_CCM_IOSIZE / sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * @name Object model
+ * @{
+ */
+
+#define TYPE_AW_A10_CCM    "allwinner-a10-ccm"
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10ClockCtlState, AW_A10_CCM)
+
+/** @} */
+
+/**
+ * Allwinner A10 CCM object instance state.
+ */
+struct AwA10ClockCtlState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    /** Maps I/O registers in physical memory */
+    MemoryRegion iomem;
+
+    /** Array of hardware registers */
+    uint32_t regs[AW_A10_CCM_REGS_NUM];
+};
+
+#endif /* HW_MISC_ALLWINNER_H3_CCU_H */
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 2/7] hw/misc: Allwinner A10 DRAM Controller Emulation
  2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
  2022-12-18 21:19 ` [PATCH v2 1/7] hw/misc: Allwinner-A10 Clock Controller Module Emulation Strahinja Jankovic
@ 2022-12-18 21:19 ` Strahinja Jankovic
  2022-12-18 21:19 ` [PATCH v2 3/7] hw/i2c: Allwinner TWI/I2C Emulation Strahinja Jankovic
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

During SPL boot several DRAM Controller registers are used. Most
important registers are those related to DRAM initialization and
calibration, where SPL initiates process and waits until certain bit is
set/cleared.

This patch adds these registers, initializes reset values from user's
guide and updates state of registers as SPL expects it.

Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>

Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
---
 hw/arm/Kconfig                        |   1 +
 hw/arm/allwinner-a10.c                |   7 +
 hw/misc/Kconfig                       |   3 +
 hw/misc/allwinner-a10-dramc.c         | 179 ++++++++++++++++++++++++++
 hw/misc/meson.build                   |   1 +
 include/hw/arm/allwinner-a10.h        |   2 +
 include/hw/misc/allwinner-a10-dramc.h |  68 ++++++++++
 7 files changed, 261 insertions(+)
 create mode 100644 hw/misc/allwinner-a10-dramc.c
 create mode 100644 include/hw/misc/allwinner-a10-dramc.h

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 14f52b41af..140f142ae5 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -320,6 +320,7 @@ config ALLWINNER_A10
     select ALLWINNER_A10_PIT
     select ALLWINNER_A10_PIC
     select ALLWINNER_A10_CCM
+    select ALLWINNER_A10_DRAMC
     select ALLWINNER_EMAC
     select SERIAL
     select UNIMP
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index 86baeeeca2..a5f7a36ac9 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -25,6 +25,7 @@
 #include "hw/boards.h"
 #include "hw/usb/hcd-ohci.h"
 
+#define AW_A10_DRAMC_BASE       0x01c01000
 #define AW_A10_MMC0_BASE        0x01c0f000
 #define AW_A10_CCM_BASE         0x01c20000
 #define AW_A10_PIC_REG_BASE     0x01c20400
@@ -49,6 +50,8 @@ static void aw_a10_init(Object *obj)
 
     object_initialize_child(obj, "ccm", &s->ccm, TYPE_AW_A10_CCM);
 
+    object_initialize_child(obj, "dramc", &s->dramc, TYPE_AW_A10_DRAMC);
+
     object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
 
     object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
@@ -110,6 +113,10 @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
     sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_fatal);
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, AW_A10_CCM_BASE);
 
+    /* DRAM Control Module */
+    sysbus_realize(SYS_BUS_DEVICE(&s->dramc), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0, AW_A10_DRAMC_BASE);
+
     /* FIXME use qdev NIC properties instead of nd_table[] */
     if (nd_table[0].used) {
         qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index ed07bf4133..052fb54310 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -177,4 +177,7 @@ config LASI
 config ALLWINNER_A10_CCM
     bool
 
+config ALLWINNER_A10_DRAMC
+    bool
+
 source macio/Kconfig
diff --git a/hw/misc/allwinner-a10-dramc.c b/hw/misc/allwinner-a10-dramc.c
new file mode 100644
index 0000000000..e118b0c2fd
--- /dev/null
+++ b/hw/misc/allwinner-a10-dramc.c
@@ -0,0 +1,179 @@
+/*
+ * Allwinner A10 DRAM Controller emulation
+ *
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ *  This file is derived from Allwinner H3 DRAMC,
+ *  by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 "qemu/osdep.h"
+#include "qemu/units.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/misc/allwinner-a10-dramc.h"
+
+/* DRAMC register offsets */
+enum {
+    REG_SDR_CCR = 0x0000,
+    REG_SDR_ZQCR0 = 0x00a8,
+    REG_SDR_ZQSR = 0x00b0
+};
+
+#define REG_INDEX(offset)    (offset / sizeof(uint32_t))
+
+/* DRAMC register flags */
+enum {
+    REG_SDR_CCR_DATA_TRAINING = (1 << 30),
+    REG_SDR_CCR_DRAM_INIT     = (1 << 31),
+};
+enum {
+    REG_SDR_ZQSR_ZCAL         = (1 << 31),
+};
+
+/* DRAMC register reset values */
+enum {
+    REG_SDR_CCR_RESET   = 0x80020000,
+    REG_SDR_ZQCR0_RESET = 0x07b00000,
+    REG_SDR_ZQSR_RESET  = 0x80000000
+};
+
+static uint64_t allwinner_a10_dramc_read(void *opaque, hwaddr offset,
+                                       unsigned size)
+{
+    const AwA10DramControllerState *s = AW_A10_DRAMC(opaque);
+    const uint32_t idx = REG_INDEX(offset);
+
+    switch (offset) {
+    case REG_SDR_CCR:
+    case REG_SDR_ZQCR0:
+    case REG_SDR_ZQSR:
+        break;
+    case 0x2e4 ... AW_A10_DRAMC_IOSIZE:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
+                      __func__, (uint32_t)offset);
+        return 0;
+    default:
+        qemu_log_mask(LOG_UNIMP, "%s: unimplemented read offset 0x%04x\n",
+                      __func__, (uint32_t)offset);
+        return 0;
+    }
+
+    return s->regs[idx];
+}
+
+static void allwinner_a10_dramc_write(void *opaque, hwaddr offset,
+                                   uint64_t val, unsigned size)
+{
+    AwA10DramControllerState *s = AW_A10_DRAMC(opaque);
+    const uint32_t idx = REG_INDEX(offset);
+
+    switch (offset) {
+    case REG_SDR_CCR:
+        if (val & REG_SDR_CCR_DRAM_INIT) {
+            /* Clear DRAM_INIT to indicate process is done. */
+            val &= ~REG_SDR_CCR_DRAM_INIT;
+        }
+        if (val & REG_SDR_CCR_DATA_TRAINING) {
+            /* Clear DATA_TRAINING to indicate process is done. */
+            val &= ~REG_SDR_CCR_DATA_TRAINING;
+        }
+        break;
+    case REG_SDR_ZQCR0:
+        /* Set ZCAL in ZQSR to indicate calibration is done. */
+        s->regs[REG_INDEX(REG_SDR_ZQSR)] |= REG_SDR_ZQSR_ZCAL;
+        break;
+    case 0x2e4 ... AW_A10_DRAMC_IOSIZE:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
+                      __func__, (uint32_t)offset);
+        break;
+    default:
+        qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
+                      __func__, (uint32_t)offset);
+        break;
+    }
+
+    s->regs[idx] = (uint32_t) val;
+}
+
+static const MemoryRegionOps allwinner_a10_dramc_ops = {
+    .read = allwinner_a10_dramc_read,
+    .write = allwinner_a10_dramc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl.min_access_size = 4,
+};
+
+static void allwinner_a10_dramc_reset_enter(Object *obj, ResetType type)
+{
+    AwA10DramControllerState *s = AW_A10_DRAMC(obj);
+
+    /* Set default values for registers */
+    s->regs[REG_INDEX(REG_SDR_CCR)] = REG_SDR_CCR_RESET;
+    s->regs[REG_INDEX(REG_SDR_ZQCR0)] = REG_SDR_ZQCR0_RESET;
+    s->regs[REG_INDEX(REG_SDR_ZQSR)] = REG_SDR_ZQSR_RESET;
+}
+
+static void allwinner_a10_dramc_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    AwA10DramControllerState *s = AW_A10_DRAMC(obj);
+
+    /* Memory mapping */
+    memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_a10_dramc_ops, s,
+                          TYPE_AW_A10_DRAMC, AW_A10_DRAMC_IOSIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static const VMStateDescription allwinner_a10_dramc_vmstate = {
+    .name = "allwinner-a10-dramc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, AwA10DramControllerState,
+                             AW_A10_DRAMC_REGS_NUM),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void allwinner_a10_dramc_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.enter = allwinner_a10_dramc_reset_enter;
+    dc->vmsd = &allwinner_a10_dramc_vmstate;
+}
+
+static const TypeInfo allwinner_a10_dramc_info = {
+    .name          = TYPE_AW_A10_DRAMC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_init = allwinner_a10_dramc_init,
+    .instance_size = sizeof(AwA10DramControllerState),
+    .class_init    = allwinner_a10_dramc_class_init,
+};
+
+static void allwinner_a10_dramc_register(void)
+{
+    type_register_static(&allwinner_a10_dramc_info);
+}
+
+type_init(allwinner_a10_dramc_register)
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index c828dbeb26..9eaa0750b5 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -39,6 +39,7 @@ subdir('macio')
 softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
 
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
 specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
index 45d0fc2f7e..abe4ff7066 100644
--- a/include/hw/arm/allwinner-a10.h
+++ b/include/hw/arm/allwinner-a10.h
@@ -13,6 +13,7 @@
 #include "hw/usb/hcd-ehci.h"
 #include "hw/rtc/allwinner-rtc.h"
 #include "hw/misc/allwinner-a10-ccm.h"
+#include "hw/misc/allwinner-a10-dramc.h"
 
 #include "target/arm/cpu.h"
 #include "qom/object.h"
@@ -32,6 +33,7 @@ struct AwA10State {
 
     ARMCPU cpu;
     AwA10ClockCtlState ccm;
+    AwA10DramControllerState dramc;
     AwA10PITState timer;
     AwA10PICState intc;
     AwEmacState emac;
diff --git a/include/hw/misc/allwinner-a10-dramc.h b/include/hw/misc/allwinner-a10-dramc.h
new file mode 100644
index 0000000000..b61fbecbe7
--- /dev/null
+++ b/include/hw/misc/allwinner-a10-dramc.h
@@ -0,0 +1,68 @@
+/*
+ * Allwinner A10 DRAM Controller emulation
+ *
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ *  This file is derived from Allwinner H3 DRAMC,
+ *  by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/>.
+ */
+
+#ifndef HW_MISC_ALLWINNER_A10_DRAMC_H
+#define HW_MISC_ALLWINNER_A10_DRAMC_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+
+/**
+ * @name Constants
+ * @{
+ */
+
+/** Size of register I/O address space used by DRAMC device */
+#define AW_A10_DRAMC_IOSIZE        (0x1000)
+
+/** Total number of known registers */
+#define AW_A10_DRAMC_REGS_NUM      (AW_A10_DRAMC_IOSIZE / sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * @name Object model
+ * @{
+ */
+
+#define TYPE_AW_A10_DRAMC    "allwinner-a10-dramc"
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10DramControllerState, AW_A10_DRAMC)
+
+/** @} */
+
+/**
+ * Allwinner A10 DRAMC object instance state.
+ */
+struct AwA10DramControllerState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    /** Maps I/O registers in physical memory */
+    MemoryRegion iomem;
+
+    /** Array of hardware registers */
+    uint32_t regs[AW_A10_DRAMC_REGS_NUM];
+};
+
+#endif /* HW_MISC_ALLWINNER_A10_DRAMC_H */
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 3/7] hw/i2c: Allwinner TWI/I2C Emulation
  2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
  2022-12-18 21:19 ` [PATCH v2 1/7] hw/misc: Allwinner-A10 Clock Controller Module Emulation Strahinja Jankovic
  2022-12-18 21:19 ` [PATCH v2 2/7] hw/misc: Allwinner A10 DRAM Controller Emulation Strahinja Jankovic
@ 2022-12-18 21:19 ` Strahinja Jankovic
  2022-12-18 21:19 ` [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation Strahinja Jankovic
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

This patch implements Allwinner TWI/I2C controller emulation. Only
master-mode functionality is implemented.

The SPL boot for Cubieboard expects AXP209 PMIC on TWI0/I2C0 bus, so this is
first part enabling the TWI/I2C bus operation.

Since both Allwinner A10 and H3 use the same module, it is added for
both boards.

Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
---
 hw/arm/Kconfig                 |   2 +
 hw/arm/allwinner-a10.c         |   8 +
 hw/arm/allwinner-h3.c          |  11 +-
 hw/i2c/Kconfig                 |   4 +
 hw/i2c/allwinner-i2c.c         | 459 +++++++++++++++++++++++++++++++++
 hw/i2c/meson.build             |   1 +
 hw/i2c/trace-events            |   5 +
 include/hw/arm/allwinner-a10.h |   2 +
 include/hw/arm/allwinner-h3.h  |   3 +
 include/hw/i2c/allwinner-i2c.h |  55 ++++
 10 files changed, 549 insertions(+), 1 deletion(-)
 create mode 100644 hw/i2c/allwinner-i2c.c
 create mode 100644 include/hw/i2c/allwinner-i2c.h

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 140f142ae5..eefe1fd134 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -322,6 +322,7 @@ config ALLWINNER_A10
     select ALLWINNER_A10_CCM
     select ALLWINNER_A10_DRAMC
     select ALLWINNER_EMAC
+    select ALLWINNER_I2C
     select SERIAL
     select UNIMP
 
@@ -329,6 +330,7 @@ config ALLWINNER_H3
     bool
     select ALLWINNER_A10_PIT
     select ALLWINNER_SUN8I_EMAC
+    select ALLWINNER_I2C
     select SERIAL
     select ARM_TIMER
     select ARM_GIC
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index a5f7a36ac9..17e439777e 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -36,6 +36,7 @@
 #define AW_A10_OHCI_BASE        0x01c14400
 #define AW_A10_SATA_BASE        0x01c18000
 #define AW_A10_RTC_BASE         0x01c20d00
+#define AW_A10_I2C0_BASE        0x01c2ac00
 
 static void aw_a10_init(Object *obj)
 {
@@ -56,6 +57,8 @@ static void aw_a10_init(Object *obj)
 
     object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
 
+    object_initialize_child(obj, "i2c0", &s->i2c0, TYPE_AW_I2C);
+
     if (machine_usb(current_machine)) {
         int i;
 
@@ -176,6 +179,11 @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
     /* RTC */
     sysbus_realize(SYS_BUS_DEVICE(&s->rtc), &error_fatal);
     sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->rtc), 0, AW_A10_RTC_BASE, 10);
+
+    /* I2C */
+    sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, AW_A10_I2C0_BASE);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0, qdev_get_gpio_in(dev, 7));
 }
 
 static void aw_a10_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
index 308ed15552..bfce3c8d92 100644
--- a/hw/arm/allwinner-h3.c
+++ b/hw/arm/allwinner-h3.c
@@ -53,6 +53,7 @@ const hwaddr allwinner_h3_memmap[] = {
     [AW_H3_DEV_UART1]      = 0x01c28400,
     [AW_H3_DEV_UART2]      = 0x01c28800,
     [AW_H3_DEV_UART3]      = 0x01c28c00,
+    [AW_H3_DEV_TWI0]       = 0x01c2ac00,
     [AW_H3_DEV_EMAC]       = 0x01c30000,
     [AW_H3_DEV_DRAMCOM]    = 0x01c62000,
     [AW_H3_DEV_DRAMCTL]    = 0x01c63000,
@@ -106,7 +107,6 @@ struct AwH3Unimplemented {
     { "uart1",     0x01c28400, 1 * KiB },
     { "uart2",     0x01c28800, 1 * KiB },
     { "uart3",     0x01c28c00, 1 * KiB },
-    { "twi0",      0x01c2ac00, 1 * KiB },
     { "twi1",      0x01c2b000, 1 * KiB },
     { "twi2",      0x01c2b400, 1 * KiB },
     { "scr",       0x01c2c400, 1 * KiB },
@@ -150,6 +150,7 @@ enum {
     AW_H3_GIC_SPI_UART1     =  1,
     AW_H3_GIC_SPI_UART2     =  2,
     AW_H3_GIC_SPI_UART3     =  3,
+    AW_H3_GIC_SPI_TWI0      =  6,
     AW_H3_GIC_SPI_TIMER0    = 18,
     AW_H3_GIC_SPI_TIMER1    = 19,
     AW_H3_GIC_SPI_MMC0      = 60,
@@ -225,6 +226,8 @@ static void allwinner_h3_init(Object *obj)
                               "ram-size");
 
     object_initialize_child(obj, "rtc", &s->rtc, TYPE_AW_RTC_SUN6I);
+
+    object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C);
 }
 
 static void allwinner_h3_realize(DeviceState *dev, Error **errp)
@@ -423,6 +426,12 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
     sysbus_realize(SYS_BUS_DEVICE(&s->rtc), &error_fatal);
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, s->memmap[AW_H3_DEV_RTC]);
 
+    /* I2C */
+    sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, s->memmap[AW_H3_DEV_TWI0]);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0,
+                       qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TWI0));
+
     /* Unimplemented devices */
     for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
         create_unimplemented_device(unimplemented[i].device_name,
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
index 9bb8870517..f8ec461be3 100644
--- a/hw/i2c/Kconfig
+++ b/hw/i2c/Kconfig
@@ -34,6 +34,10 @@ config MPC_I2C
     bool
     select I2C
 
+config ALLWINNER_I2C
+    bool
+    select I2C
+
 config PCA954X
     bool
     select I2C
diff --git a/hw/i2c/allwinner-i2c.c b/hw/i2c/allwinner-i2c.c
new file mode 100644
index 0000000000..a435965836
--- /dev/null
+++ b/hw/i2c/allwinner-i2c.c
@@ -0,0 +1,459 @@
+/*
+ *  Allwinner I2C Bus Serial Interface Emulation
+ *
+ *  Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ *  This file is derived from IMX I2C controller,
+ *  by Jean-Christophe DUBOIS .
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that 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/>.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "qemu/osdep.h"
+#include "hw/i2c/allwinner-i2c.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "hw/i2c/i2c.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "qemu/module.h"
+
+/* Allwinner I2C memory map */
+#define TWI_ADDR_REG            0x00  /* slave address register */
+#define TWI_XADDR_REG           0x04  /* extended slave address register */
+#define TWI_DATA_REG            0x08  /* data register */
+#define TWI_CNTR_REG            0x0c  /* control register */
+#define TWI_STAT_REG            0x10  /* status register */
+#define TWI_CCR_REG             0x14  /* clock control register */
+#define TWI_SRST_REG            0x18  /* software reset register */
+#define TWI_EFR_REG             0x1c  /* enhance feature register */
+#define TWI_LCR_REG             0x20  /* line control register */
+
+/* Used only in slave mode, do not set */
+#define TWI_ADDR_RESET          0
+#define TWI_XADDR_RESET         0
+
+/* Data register */
+#define TWI_DATA_MASK           0xFF
+#define TWI_DATA_RESET          0
+
+/* Control register */
+#define TWI_CNTR_INT_EN         (1 << 7)
+#define TWI_CNTR_BUS_EN         (1 << 6)
+#define TWI_CNTR_M_STA          (1 << 5)
+#define TWI_CNTR_M_STP          (1 << 4)
+#define TWI_CNTR_INT_FLAG       (1 << 3)
+#define TWI_CNTR_A_ACK          (1 << 2)
+#define TWI_CNTR_MASK           0xFC
+#define TWI_CNTR_RESET          0
+
+/* Status register */
+#define TWI_STAT_MASK           0xF8
+#define TWI_STAT_RESET          0xF8
+
+/* Clock register */
+#define TWI_CCR_CLK_M_MASK      0x78
+#define TWI_CCR_CLK_N_MASK      0x07
+#define TWI_CCR_MASK            0x7F
+#define TWI_CCR_RESET           0
+
+/* Soft reset */
+#define TWI_SRST_MASK           0x01
+#define TWI_SRST_RESET          0
+
+/* Enhance feature */
+#define TWI_EFR_MASK            0x03
+#define TWI_EFR_RESET           0
+
+/* Line control */
+#define TWI_LCR_SCL_STATE       (1 << 5)
+#define TWI_LCR_SDA_STATE       (1 << 4)
+#define TWI_LCR_SCL_CTL         (1 << 3)
+#define TWI_LCR_SCL_CTL_EN      (1 << 2)
+#define TWI_LCR_SDA_CTL         (1 << 1)
+#define TWI_LCR_SDA_CTL_EN      (1 << 0)
+#define TWI_LCR_MASK            0x3F
+#define TWI_LCR_RESET           0x3A
+
+/* Status value in STAT register is shifted by 3 bits */
+#define TWI_STAT_SHIFT      3
+#define STAT_FROM_STA(x)    ((x) << TWI_STAT_SHIFT)
+#define STAT_TO_STA(x)      ((x) >> TWI_STAT_SHIFT)
+
+enum {
+    STAT_BUS_ERROR = 0,
+    /* Master mode */
+    STAT_M_STA_TX,
+    STAT_M_RSTA_TX,
+    STAT_M_ADDR_WR_ACK,
+    STAT_M_ADDR_WR_NACK,
+    STAT_M_DATA_TX_ACK,
+    STAT_M_DATA_TX_NACK,
+    STAT_M_ARB_LOST,
+    STAT_M_ADDR_RD_ACK,
+    STAT_M_ADDR_RD_NACK,
+    STAT_M_DATA_RX_ACK,
+    STAT_M_DATA_RX_NACK,
+    /* Slave mode */
+    STAT_S_ADDR_WR_ACK,
+    STAT_S_ARB_LOST_AW_ACK,
+    STAT_S_GCA_ACK,
+    STAT_S_ARB_LOST_GCA_ACK,
+    STAT_S_DATA_RX_SA_ACK,
+    STAT_S_DATA_RX_SA_NACK,
+    STAT_S_DATA_RX_GCA_ACK,
+    STAT_S_DATA_RX_GCA_NACK,
+    STAT_S_STP_RSTA,
+    STAT_S_ADDR_RD_ACK,
+    STAT_S_ARB_LOST_AR_ACK,
+    STAT_S_DATA_TX_ACK,
+    STAT_S_DATA_TX_NACK,
+    STAT_S_LB_TX_ACK,
+    /* Master mode, 10-bit */
+    STAT_M_2ND_ADDR_WR_ACK,
+    STAT_M_2ND_ADDR_WR_NACK,
+    /* Idle */
+    STAT_IDLE = 0x1f
+} TWI_STAT_STA;
+
+static const char *allwinner_i2c_get_regname(unsigned offset)
+{
+    switch (offset) {
+    case TWI_ADDR_REG:
+        return "ADDR";
+    case TWI_XADDR_REG:
+        return "XADDR";
+    case TWI_DATA_REG:
+        return "DATA";
+    case TWI_CNTR_REG:
+        return "CNTR";
+    case TWI_STAT_REG:
+        return "STAT";
+    case TWI_CCR_REG:
+        return "CCR";
+    case TWI_SRST_REG:
+        return "SRST";
+    case TWI_EFR_REG:
+        return "EFR";
+    case TWI_LCR_REG:
+        return "LCR";
+    default:
+        return "[?]";
+    }
+}
+
+static inline bool allwinner_i2c_is_reset(AWI2CState *s)
+{
+    return s->srst & TWI_SRST_MASK;
+}
+
+static inline bool allwinner_i2c_bus_is_enabled(AWI2CState *s)
+{
+    return s->cntr & TWI_CNTR_BUS_EN;
+}
+
+static inline bool allwinner_i2c_interrupt_is_enabled(AWI2CState *s)
+{
+    return s->cntr & TWI_CNTR_INT_EN;
+}
+
+static void allwinner_i2c_reset_hold(Object *obj)
+{
+    AWI2CState *s = AW_I2C(obj);
+
+    if (STAT_TO_STA(s->stat) != STAT_IDLE) {
+        i2c_end_transfer(s->bus);
+    }
+
+    s->addr  = TWI_ADDR_RESET;
+    s->xaddr = TWI_XADDR_RESET;
+    s->data  = TWI_DATA_RESET;
+    s->cntr  = TWI_CNTR_RESET;
+    s->stat  = TWI_STAT_RESET;
+    s->ccr   = TWI_CCR_RESET;
+    s->srst  = TWI_SRST_RESET;
+    s->efr   = TWI_EFR_RESET;
+    s->lcr   = TWI_LCR_RESET;
+}
+
+static inline void allwinner_i2c_raise_interrupt(AWI2CState *s)
+{
+    /*
+     * Raise an interrupt if the device is not reset and it is configured
+     * to generate some interrupts.
+     */
+    if (!allwinner_i2c_is_reset(s) && allwinner_i2c_bus_is_enabled(s)) {
+        if (STAT_TO_STA(s->stat) != STAT_IDLE) {
+            s->cntr |= TWI_CNTR_INT_FLAG;
+            if (allwinner_i2c_interrupt_is_enabled(s)) {
+                qemu_irq_raise(s->irq);
+            }
+        }
+    }
+}
+
+static uint64_t allwinner_i2c_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    uint16_t value;
+    AWI2CState *s = AW_I2C(opaque);
+
+    switch (offset) {
+    case TWI_ADDR_REG:
+        value = s->addr;
+        break;
+    case TWI_XADDR_REG:
+        value = s->xaddr;
+        break;
+    case TWI_DATA_REG:
+        if ((STAT_TO_STA(s->stat) == STAT_M_ADDR_RD_ACK) ||
+            (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_ACK) ||
+            (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_NACK)) {
+            /* Get the next byte */
+            s->data = i2c_recv(s->bus);
+
+            if (s->cntr & TWI_CNTR_A_ACK) {
+                s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
+            } else {
+                s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
+            }
+            allwinner_i2c_raise_interrupt(s);
+        }
+        value = s->data;
+        break;
+    case TWI_CNTR_REG:
+        value = s->cntr;
+        break;
+    case TWI_STAT_REG:
+        value = s->stat;
+        /*
+         * If polling when reading then change state to indicate data
+         * is available
+         */
+        if (STAT_TO_STA(s->stat) == STAT_M_ADDR_RD_ACK) {
+            if (s->cntr & TWI_CNTR_A_ACK) {
+                s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
+            } else {
+                s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
+            }
+            allwinner_i2c_raise_interrupt(s);
+        }
+        break;
+    case TWI_CCR_REG:
+        value = s->ccr;
+        break;
+    case TWI_SRST_REG:
+        value = s->srst;
+        break;
+    case TWI_EFR_REG:
+        value = s->efr;
+        break;
+    case TWI_LCR_REG:
+        value = s->lcr;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_AW_I2C, __func__, offset);
+        value = 0;
+        break;
+    }
+
+    trace_allwinner_i2c_read(allwinner_i2c_get_regname(offset), offset, value);
+
+    return (uint64_t)value;
+}
+
+static void allwinner_i2c_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    AWI2CState *s = AW_I2C(opaque);
+
+    value &= 0xff;
+
+    trace_allwinner_i2c_write(allwinner_i2c_get_regname(offset), offset, value);
+
+    switch (offset) {
+    case TWI_ADDR_REG:
+        s->addr = (uint8_t)value;
+        break;
+    case TWI_XADDR_REG:
+        s->xaddr = (uint8_t)value;
+        break;
+    case TWI_DATA_REG:
+        /* If the device is in reset or not enabled, nothing to do */
+        if (allwinner_i2c_is_reset(s) || (!allwinner_i2c_bus_is_enabled(s))) {
+            break;
+        }
+
+        s->data = value & TWI_DATA_MASK;
+
+        switch (STAT_TO_STA(s->stat)) {
+        case STAT_M_STA_TX:
+        case STAT_M_RSTA_TX:
+            /* Send address */
+            if (i2c_start_transfer(s->bus, extract32(s->data, 1, 7),
+                                extract32(s->data, 0, 1))) {
+                /* If non zero is returned, the address is not valid */
+                s->stat = STAT_FROM_STA(STAT_M_ADDR_WR_NACK);
+            } else {
+                /* Determine if read of write */
+                if (extract32(s->data, 0, 1)) {
+                    s->stat = STAT_FROM_STA(STAT_M_ADDR_RD_ACK);
+                } else {
+                    s->stat = STAT_FROM_STA(STAT_M_ADDR_WR_ACK);
+                }
+                allwinner_i2c_raise_interrupt(s);
+            }
+            break;
+        case STAT_M_ADDR_WR_ACK:
+        case STAT_M_DATA_TX_ACK:
+            if (i2c_send(s->bus, s->data)) {
+                /* If the target return non zero then end the transfer */
+                s->stat = STAT_FROM_STA(STAT_M_DATA_TX_NACK);
+                i2c_end_transfer(s->bus);
+            } else {
+                s->stat = STAT_FROM_STA(STAT_M_DATA_TX_ACK);
+                allwinner_i2c_raise_interrupt(s);
+            }
+            break;
+        default:
+            break;
+        }
+        break;
+    case TWI_CNTR_REG:
+        if (!allwinner_i2c_is_reset(s)) {
+            /* Do something only if not in software reset */
+            s->cntr = value & TWI_CNTR_MASK;
+
+            /* Check if start condition should be sent */
+            if (s->cntr & TWI_CNTR_M_STA) {
+                /* Update status */
+                if (STAT_TO_STA(s->stat) == STAT_IDLE) {
+                    /* Send start condition */
+                    s->stat = STAT_FROM_STA(STAT_M_STA_TX);
+                } else {
+                    /* Send repeated start condition */
+                    s->stat = STAT_FROM_STA(STAT_M_RSTA_TX);
+                }
+                /* Clear start condition */
+                s->cntr &= ~TWI_CNTR_M_STA;
+            }
+            if (s->cntr & TWI_CNTR_M_STP) {
+                /* Update status */
+                i2c_end_transfer(s->bus);
+                s->stat = STAT_FROM_STA(STAT_IDLE);
+                s->cntr &= ~TWI_CNTR_M_STP;
+            }
+            if ((s->cntr & TWI_CNTR_INT_FLAG) == 0) {
+                /* Interrupt flag cleared */
+                qemu_irq_lower(s->irq);
+            }
+            if ((s->cntr & TWI_CNTR_A_ACK) == 0) {
+                if (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_ACK) {
+                    s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
+                }
+            } else {
+                if (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_NACK) {
+                    s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
+                }
+            }
+            allwinner_i2c_raise_interrupt(s);
+
+        }
+        break;
+    case TWI_CCR_REG:
+        s->ccr = value & TWI_CCR_MASK;
+        break;
+    case TWI_SRST_REG:
+        if (((value & TWI_SRST_MASK) == 0) && (s->srst & TWI_SRST_MASK)) {
+            /* Perform reset */
+            allwinner_i2c_reset_hold(OBJECT(s));
+        }
+        s->srst = value & TWI_SRST_MASK;
+        break;
+    case TWI_EFR_REG:
+        s->efr = value & TWI_EFR_MASK;
+        break;
+    case TWI_LCR_REG:
+        s->lcr = value & TWI_LCR_MASK;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_AW_I2C, __func__, offset);
+        break;
+    }
+}
+
+static const MemoryRegionOps allwinner_i2c_ops = {
+    .read = allwinner_i2c_read,
+    .write = allwinner_i2c_write,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription allwinner_i2c_vmstate = {
+    .name = TYPE_AW_I2C,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(addr, AWI2CState),
+        VMSTATE_UINT8(xaddr, AWI2CState),
+        VMSTATE_UINT8(data, AWI2CState),
+        VMSTATE_UINT8(cntr, AWI2CState),
+        VMSTATE_UINT8(ccr, AWI2CState),
+        VMSTATE_UINT8(srst, AWI2CState),
+        VMSTATE_UINT8(efr, AWI2CState),
+        VMSTATE_UINT8(lcr, AWI2CState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void allwinner_i2c_realize(DeviceState *dev, Error **errp)
+{
+    AWI2CState *s = AW_I2C(dev);
+
+    memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_i2c_ops, s,
+                          TYPE_AW_I2C, AW_I2C_MEM_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
+    s->bus = i2c_init_bus(dev, "i2c");
+}
+
+static void allwinner_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.hold = allwinner_i2c_reset_hold;
+    dc->vmsd = &allwinner_i2c_vmstate;
+    dc->realize = allwinner_i2c_realize;
+    dc->desc = "Allwinner I2C Controller";
+}
+
+static const TypeInfo allwinner_i2c_type_info = {
+    .name = TYPE_AW_I2C,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AWI2CState),
+    .class_init = allwinner_i2c_class_init,
+};
+
+static void allwinner_i2c_register_types(void)
+{
+    type_register_static(&allwinner_i2c_type_info);
+}
+
+type_init(allwinner_i2c_register_types)
diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build
index d3df273251..7de7f2f540 100644
--- a/hw/i2c/meson.build
+++ b/hw/i2c/meson.build
@@ -8,6 +8,7 @@ i2c_ss.add(when: 'CONFIG_BITBANG_I2C', if_true: files('bitbang_i2c.c'))
 i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_i2c.c'))
 i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c'))
 i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c'))
+i2c_ss.add(when: 'CONFIG_ALLWINNER_I2C', if_true: files('allwinner-i2c.c'))
 i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))
 i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c'))
 i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c'))
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
index af181d43ee..52dbd53a23 100644
--- a/hw/i2c/trace-events
+++ b/hw/i2c/trace-events
@@ -8,6 +8,11 @@ i2c_send_async(uint8_t address, uint8_t data) "send_async(addr:0x%02x) data:0x%0
 i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) data:0x%02x"
 i2c_ack(void) ""
 
+# allwinner_i2c.c
+
+allwinner_i2c_read(const char* reg_name, uint64_t offset, uint64_t value) "read %s [0x%" PRIx64 "]: -> 0x%" PRIx64
+allwinner_i2c_write(const char* reg_name, uint64_t offset, uint64_t value) "write %s [0x%" PRIx64 "]: <- 0x%" PRIx64
+
 # aspeed_i2c.c
 
 aspeed_i2c_bus_cmd(uint32_t cmd, const char *cmd_flags, uint32_t count, uint32_t intr_status) "handling cmd=0x%x %s count=%d intr=0x%x"
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
index abe4ff7066..763935fca9 100644
--- a/include/hw/arm/allwinner-a10.h
+++ b/include/hw/arm/allwinner-a10.h
@@ -14,6 +14,7 @@
 #include "hw/rtc/allwinner-rtc.h"
 #include "hw/misc/allwinner-a10-ccm.h"
 #include "hw/misc/allwinner-a10-dramc.h"
+#include "hw/i2c/allwinner-i2c.h"
 
 #include "target/arm/cpu.h"
 #include "qom/object.h"
@@ -39,6 +40,7 @@ struct AwA10State {
     AwEmacState emac;
     AllwinnerAHCIState sata;
     AwSdHostState mmc0;
+    AWI2CState i2c0;
     AwRtcState rtc;
     MemoryRegion sram_a;
     EHCISysBusState ehci[AW_A10_NUM_USB];
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
index 63025fb27c..1d7ce20589 100644
--- a/include/hw/arm/allwinner-h3.h
+++ b/include/hw/arm/allwinner-h3.h
@@ -47,6 +47,7 @@
 #include "hw/sd/allwinner-sdhost.h"
 #include "hw/net/allwinner-sun8i-emac.h"
 #include "hw/rtc/allwinner-rtc.h"
+#include "hw/i2c/allwinner-i2c.h"
 #include "target/arm/cpu.h"
 #include "sysemu/block-backend.h"
 
@@ -82,6 +83,7 @@ enum {
     AW_H3_DEV_UART2,
     AW_H3_DEV_UART3,
     AW_H3_DEV_EMAC,
+    AW_H3_DEV_TWI0,
     AW_H3_DEV_DRAMCOM,
     AW_H3_DEV_DRAMCTL,
     AW_H3_DEV_DRAMPHY,
@@ -130,6 +132,7 @@ struct AwH3State {
     AwH3SysCtrlState sysctrl;
     AwSidState sid;
     AwSdHostState mmc0;
+    AWI2CState i2c0;
     AwSun8iEmacState emac;
     AwRtcState rtc;
     GICState gic;
diff --git a/include/hw/i2c/allwinner-i2c.h b/include/hw/i2c/allwinner-i2c.h
new file mode 100644
index 0000000000..4f378b86ba
--- /dev/null
+++ b/include/hw/i2c/allwinner-i2c.h
@@ -0,0 +1,55 @@
+/*
+ *  Allwinner I2C Bus Serial Interface registers definition
+ *
+ *  Copyright (C) 2022 Strahinja Jankovic. <strahinja.p.jankovic@gmail.com>
+ *
+ *  This file is derived from IMX I2C controller,
+ *  by Jean-Christophe DUBOIS .
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that 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/>.
+ *
+ */
+
+#ifndef ALLWINNER_I2C_H
+#define ALLWINNER_I2C_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_AW_I2C "allwinner.i2c"
+OBJECT_DECLARE_SIMPLE_TYPE(AWI2CState, AW_I2C)
+
+#define AW_I2C_MEM_SIZE         0x24
+
+struct AWI2CState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    MemoryRegion iomem;
+    I2CBus *bus;
+    qemu_irq irq;
+
+    uint8_t addr;
+    uint8_t xaddr;
+    uint8_t data;
+    uint8_t cntr;
+    uint8_t stat;
+    uint8_t ccr;
+    uint8_t srst;
+    uint8_t efr;
+    uint8_t lcr;
+};
+
+#endif /* ALLWINNER_I2C_H */
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation
  2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
                   ` (2 preceding siblings ...)
  2022-12-18 21:19 ` [PATCH v2 3/7] hw/i2c: Allwinner TWI/I2C Emulation Strahinja Jankovic
@ 2022-12-18 21:19 ` Strahinja Jankovic
  2022-12-18 21:28   ` Strahinja Jankovic
  2022-12-18 22:07   ` Philippe Mathieu-Daudé
  2022-12-18 21:19 ` [PATCH v2 5/7] hw/arm: Add AXP-209 to Cubieboard Strahinja Jankovic
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

This patch adds minimal support for AXP-209 PMU.
Most important is chip ID since U-Boot SPL expects version 0x1. Besides
the chip ID register, reset values for two more registers used by A10
U-Boot SPL are covered.

Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
---
 hw/arm/Kconfig              |   1 +
 hw/misc/Kconfig             |   4 +
 hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
 hw/misc/meson.build         |   1 +
 hw/misc/trace-events        |   5 +
 5 files changed, 249 insertions(+)
 create mode 100644 hw/misc/allwinner-axp-209.c

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index eefe1fd134..67c6e83fe6 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -323,6 +323,7 @@ config ALLWINNER_A10
     select ALLWINNER_A10_DRAMC
     select ALLWINNER_EMAC
     select ALLWINNER_I2C
+    select ALLWINNER_AXP_209
     select SERIAL
     select UNIMP
 
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 052fb54310..3855d937fd 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
 config ALLWINNER_A10_DRAMC
     bool
 
+config ALLWINNER_AXP_209
+    bool
+    depends on I2C
+
 source macio/Kconfig
diff --git a/hw/misc/allwinner-axp-209.c b/hw/misc/allwinner-axp-209.c
new file mode 100644
index 0000000000..cf79175034
--- /dev/null
+++ b/hw/misc/allwinner-axp-209.c
@@ -0,0 +1,238 @@
+/*
+ * AXP-209 Emulation
+ *
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/i2c/i2c.h"
+#include "migration/vmstate.h"
+
+#define TYPE_AXP_209 "allwinner.axp209"
+
+#define AXP_209(obj) \
+    OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP_209)
+
+/* registers */
+enum {
+    REG_POWER_STATUS = 0x0u,
+    REG_OPERATING_MODE,
+    REG_OTG_VBUS_STATUS,
+    REG_CHIP_VERSION,
+    REG_DATA_CACHE_0,
+    REG_DATA_CACHE_1,
+    REG_DATA_CACHE_2,
+    REG_DATA_CACHE_3,
+    REG_DATA_CACHE_4,
+    REG_DATA_CACHE_5,
+    REG_DATA_CACHE_6,
+    REG_DATA_CACHE_7,
+    REG_DATA_CACHE_8,
+    REG_DATA_CACHE_9,
+    REG_DATA_CACHE_A,
+    REG_DATA_CACHE_B,
+    REG_POWER_OUTPUT_CTRL = 0x12u,
+    REG_DC_DC2_OUT_V_CTRL = 0x23u,
+    REG_DC_DC2_DVS_CTRL = 0x25u,
+    REG_DC_DC3_OUT_V_CTRL = 0x27u,
+    REG_LDO2_4_OUT_V_CTRL,
+    REG_LDO3_OUT_V_CTRL,
+    REG_VBUS_CH_MGMT = 0x30u,
+    REG_SHUTDOWN_V_CTRL,
+    REG_SHUTDOWN_CTRL,
+    REG_CHARGE_CTRL_1,
+    REG_CHARGE_CTRL_2,
+    REG_SPARE_CHARGE_CTRL,
+    REG_PEK_KEY_CTRL,
+    REG_DC_DC_FREQ_SET,
+    REG_CHR_TEMP_TH_SET,
+    REG_CHR_HIGH_TEMP_TH_CTRL,
+    REG_IPSOUT_WARN_L1,
+    REG_IPSOUT_WARN_L2,
+    REG_DISCHR_TEMP_TH_SET,
+    REG_DISCHR_HIGH_TEMP_TH_CTRL,
+    REG_IRQ_BANK_1_CTRL = 0x40u,
+    REG_IRQ_BANK_2_CTRL,
+    REG_IRQ_BANK_3_CTRL,
+    REG_IRQ_BANK_4_CTRL,
+    REG_IRQ_BANK_5_CTRL,
+    REG_IRQ_BANK_1_STAT = 0x48u,
+    REG_IRQ_BANK_2_STAT,
+    REG_IRQ_BANK_3_STAT,
+    REG_IRQ_BANK_4_STAT,
+    REG_IRQ_BANK_5_STAT,
+    REG_ADC_ACIN_V_H = 0x56u,
+    REG_ADC_ACIN_V_L,
+    REG_ADC_ACIN_CURR_H,
+    REG_ADC_ACIN_CURR_L,
+    REG_ADC_VBUS_V_H,
+    REG_ADC_VBUS_V_L,
+    REG_ADC_VBUS_CURR_H,
+    REG_ADC_VBUS_CURR_L,
+    REG_ADC_INT_TEMP_H,
+    REG_ADC_INT_TEMP_L,
+    REG_ADC_TEMP_SENS_V_H = 0x62u,
+    REG_ADC_TEMP_SENS_V_L,
+    REG_ADC_BAT_V_H = 0x78u,
+    REG_ADC_BAT_V_L,
+    REG_ADC_BAT_DISCHR_CURR_H,
+    REG_ADC_BAT_DISCHR_CURR_L,
+    REG_ADC_BAT_CHR_CURR_H,
+    REG_ADC_BAT_CHR_CURR_L,
+    REG_ADC_IPSOUT_V_H,
+    REG_ADC_IPSOUT_V_L,
+    REG_DC_DC_MOD_SEL = 0x80u,
+    REG_ADC_EN_1,
+    REG_ADC_EN_2,
+    REG_ADC_SR_CTRL,
+    REG_ADC_IN_RANGE,
+    REG_GPIO1_ADC_IRQ_RISING_TH,
+    REG_GPIO1_ADC_IRQ_FALLING_TH,
+    REG_TIMER_CTRL = 0x8au,
+    REG_VBUS_CTRL_MON_SRP,
+    REG_OVER_TEMP_SHUTDOWN = 0x8fu,
+    REG_GPIO0_FEAT_SET,
+    REG_GPIO_OUT_HIGH_SET,
+    REG_GPIO1_FEAT_SET,
+    REG_GPIO2_FEAT_SET,
+    REG_GPIO_SIG_STATE_SET_MON,
+    REG_GPIO3_SET,
+    REG_COULOMB_CNTR_CTRL = 0xb8u,
+    REG_POWER_MEAS_RES,
+    NR_REGS
+};
+
+#define AXP_209_CHIP_VERSION_ID             (0x01)
+#define AXP_209_DC_DC2_OUT_V_CTRL_RESET     (0x16)
+#define AXP_209_IRQ_BANK_1_CTRL_RESET       (0xd8)
+
+/* A simple I2C slave which returns values of ID or CNT register. */
+typedef struct AXP209I2CState {
+    /*< private >*/
+    I2CSlave i2c;
+    /*< public >*/
+    uint8_t regs[NR_REGS];  /* peripheral registers */
+    uint8_t ptr;            /* current register index */
+    uint8_t count;          /* counter used for tx/rx */
+} AXP209I2CState;
+
+/* Reset all counters and load ID register */
+static void axp_209_reset_enter(Object *obj, ResetType type)
+{
+    AXP209I2CState *s = AXP_209(obj);
+
+    memset(s->regs, 0, NR_REGS);
+    s->ptr = 0;
+    s->count = 0;
+    s->regs[REG_CHIP_VERSION] = AXP_209_CHIP_VERSION_ID;
+    s->regs[REG_DC_DC2_OUT_V_CTRL] = AXP_209_DC_DC2_OUT_V_CTRL_RESET;
+    s->regs[REG_IRQ_BANK_1_CTRL] = AXP_209_IRQ_BANK_1_CTRL_RESET;
+}
+
+/* Handle events from master. */
+static int axp_209_event(I2CSlave *i2c, enum i2c_event event)
+{
+    AXP209I2CState *s = AXP_209(i2c);
+
+    s->count = 0;
+
+    return 0;
+}
+
+/* Called when master requests read */
+static uint8_t axp_209_rx(I2CSlave *i2c)
+{
+    AXP209I2CState *s = AXP_209(i2c);
+    uint8_t ret = 0xff;
+
+    if (s->ptr < NR_REGS) {
+        ret = s->regs[s->ptr++];
+    }
+
+    trace_allwinner_axp_209_rx(s->ptr - 1, ret);
+
+    return ret;
+}
+
+/*
+ * Called when master sends write.
+ * Update ptr with byte 0, then perform write with second byte.
+ */
+static int axp_209_tx(I2CSlave *i2c, uint8_t data)
+{
+    AXP209I2CState *s = AXP_209(i2c);
+
+    if (s->count == 0) {
+        /* Store register address */
+        s->ptr = data;
+        s->count++;
+        trace_allwinner_axp_209_select(data);
+    } else {
+        trace_allwinner_axp_209_tx(s->ptr, data);
+        if (s->ptr == REG_DC_DC2_OUT_V_CTRL) {
+            s->regs[s->ptr++] = data;
+        }
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_axp_209 = {
+    .name = TYPE_AXP_209,
+    .version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8_ARRAY(regs, AXP209I2CState, NR_REGS),
+        VMSTATE_UINT8(count, AXP209I2CState),
+        VMSTATE_UINT8(ptr, AXP209I2CState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void axp_209_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
+    ResettableClass *rc = RESETTABLE_CLASS(oc);
+
+    rc->phases.enter = axp_209_reset_enter;
+    dc->vmsd = &vmstate_axp_209;
+    isc->event = axp_209_event;
+    isc->recv = axp_209_rx;
+    isc->send = axp_209_tx;
+}
+
+static const TypeInfo axp_209_info = {
+    .name = TYPE_AXP_209,
+    .parent = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(AXP209I2CState),
+    .class_init = axp_209_class_init
+};
+
+static void axp_209_register_devices(void)
+{
+    type_register_static(&axp_209_info);
+}
+
+type_init(axp_209_register_devices);
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 9eaa0750b5..7d332851cb 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -40,6 +40,7 @@ softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
 
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_AXP_209', if_true: files('allwinner-axp-209.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
 specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
 softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c18bc0605e..f6a7a6901f 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -1,5 +1,10 @@
 # See docs/devel/tracing.rst for syntax documentation.
 
+# allwinner-axp209.c
+allwinner_axp_209_rx(uint8_t reg, uint8_t data) "Read reg 0x%" PRIx8 " : 0x%" PRIx8
+allwinner_axp_209_select(uint8_t reg) "Accessing reg 0x%" PRIx8
+allwinner_axp_209_tx(uint8_t reg, uint8_t data) "Write reg 0x%" PRIx8 " : 0x%" PRIx8
+
 # allwinner-cpucfg.c
 allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIx32
 allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 5/7] hw/arm: Add AXP-209 to Cubieboard
  2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
                   ` (3 preceding siblings ...)
  2022-12-18 21:19 ` [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation Strahinja Jankovic
@ 2022-12-18 21:19 ` Strahinja Jankovic
  2022-12-18 21:55   ` Philippe Mathieu-Daudé
  2022-12-18 21:19 ` [PATCH v2 6/7] hw/arm: Allwinner A10 enable SPL load from MMC Strahinja Jankovic
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

SPL Boot for Cubieboard expects AXP-209 connected to I2C0 bus.

Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
---
 hw/arm/cubieboard.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
index 5e3372a3c7..afc7980414 100644
--- a/hw/arm/cubieboard.c
+++ b/hw/arm/cubieboard.c
@@ -20,6 +20,7 @@
 #include "hw/boards.h"
 #include "hw/qdev-properties.h"
 #include "hw/arm/allwinner-a10.h"
+#include "hw/i2c/i2c.h"
 
 static struct arm_boot_info cubieboard_binfo = {
     .loader_start = AW_A10_SDRAM_BASE,
@@ -34,6 +35,7 @@ static void cubieboard_init(MachineState *machine)
     BlockBackend *blk;
     BusState *bus;
     DeviceState *carddev;
+    I2CBus *i2c;
 
     /* BIOS is not supported by this board */
     if (machine->firmware) {
@@ -80,6 +82,10 @@ static void cubieboard_init(MachineState *machine)
         exit(1);
     }
 
+    /* Connect AXP 209 */
+    i2c = (I2CBus *)qdev_get_child_bus(DEVICE(&a10->i2c0), "i2c");
+    i2c_slave_create_simple(i2c, "allwinner.axp209", 0x34);
+
     /* Retrieve SD bus */
     di = drive_get(IF_SD, 0, 0);
     blk = di ? blk_by_legacy_dinfo(di) : NULL;
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 6/7] hw/arm: Allwinner A10 enable SPL load from MMC
  2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
                   ` (4 preceding siblings ...)
  2022-12-18 21:19 ` [PATCH v2 5/7] hw/arm: Add AXP-209 to Cubieboard Strahinja Jankovic
@ 2022-12-18 21:19 ` Strahinja Jankovic
  2022-12-18 21:59   ` Philippe Mathieu-Daudé
  2022-12-18 21:19 ` [PATCH v2 7/7] docs/system/arm: Update Allwinner with TWI (I2C) Strahinja Jankovic
  2022-12-18 22:17 ` [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Philippe Mathieu-Daudé
  7 siblings, 1 reply; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

This patch enables copying of SPL from MMC if `-kernel` parameter is not
passed when starting QEMU. SPL is copied to SRAM_A.

The approach is reused from Allwinner H3 implementation.

Tested with Armbian and custom Yocto image.

Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>

Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
---
 hw/arm/allwinner-a10.c         | 18 ++++++++++++++++++
 hw/arm/cubieboard.c            |  5 +++++
 include/hw/arm/allwinner-a10.h | 21 +++++++++++++++++++++
 3 files changed, 44 insertions(+)

diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index 17e439777e..dc1966ff7a 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -24,7 +24,9 @@
 #include "sysemu/sysemu.h"
 #include "hw/boards.h"
 #include "hw/usb/hcd-ohci.h"
+#include "hw/loader.h"
 
+#define AW_A10_SRAM_A_BASE      0x00000000
 #define AW_A10_DRAMC_BASE       0x01c01000
 #define AW_A10_MMC0_BASE        0x01c0f000
 #define AW_A10_CCM_BASE         0x01c20000
@@ -38,6 +40,22 @@
 #define AW_A10_RTC_BASE         0x01c20d00
 #define AW_A10_I2C0_BASE        0x01c2ac00
 
+void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk)
+{
+    const int64_t rom_size = 32 * KiB;
+    g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
+
+    if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
+        error_setg(&error_fatal, "%s: failed to read BlockBackend data",
+                   __func__);
+        return;
+    }
+
+    rom_add_blob("allwinner-a10.bootrom", buffer, rom_size,
+                  rom_size, AW_A10_SRAM_A_BASE,
+                  NULL, NULL, NULL, NULL, false);
+}
+
 static void aw_a10_init(Object *obj)
 {
     AwA10State *s = AW_A10(obj);
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
index afc7980414..37659c35fd 100644
--- a/hw/arm/cubieboard.c
+++ b/hw/arm/cubieboard.c
@@ -99,6 +99,11 @@ static void cubieboard_init(MachineState *machine)
     memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
                                 machine->ram);
 
+    /* Load target kernel or start using BootROM */
+    if (!machine->kernel_filename && blk && blk_is_available(blk)) {
+        /* Use Boot ROM to copy data from SD card to SRAM */
+        allwinner_a10_bootrom_setup(a10, blk);
+    }
     /* TODO create and connect IDE devices for ide_drive_get() */
 
     cubieboard_binfo.ram_size = machine->ram_size;
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
index 763935fca9..b3c9ed24c7 100644
--- a/include/hw/arm/allwinner-a10.h
+++ b/include/hw/arm/allwinner-a10.h
@@ -15,6 +15,7 @@
 #include "hw/misc/allwinner-a10-ccm.h"
 #include "hw/misc/allwinner-a10-dramc.h"
 #include "hw/i2c/allwinner-i2c.h"
+#include "sysemu/block-backend.h"
 
 #include "target/arm/cpu.h"
 #include "qom/object.h"
@@ -47,4 +48,24 @@ struct AwA10State {
     OHCISysBusState ohci[AW_A10_NUM_USB];
 };
 
+/**
+ * Emulate Boot ROM firmware setup functionality.
+ *
+ * A real Allwinner A10 SoC contains a Boot ROM
+ * which is the first code that runs right after
+ * the SoC is powered on. The Boot ROM is responsible
+ * for loading user code (e.g. a bootloader) from any
+ * of the supported external devices and writing the
+ * downloaded code to internal SRAM. After loading the SoC
+ * begins executing the code written to SRAM.
+ *
+ * This function emulates the Boot ROM by copying 32 KiB
+ * of data from the given block device and writes it to
+ * the start of the first internal SRAM memory.
+ *
+ * @s: Allwinner A10 state object pointer
+ * @blk: Block backend device object pointer
+ */
+void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk);
+
 #endif
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v2 7/7] docs/system/arm: Update Allwinner with TWI (I2C)
  2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
                   ` (5 preceding siblings ...)
  2022-12-18 21:19 ` [PATCH v2 6/7] hw/arm: Allwinner A10 enable SPL load from MMC Strahinja Jankovic
@ 2022-12-18 21:19 ` Strahinja Jankovic
  2022-12-18 22:02   ` Philippe Mathieu-Daudé
  2022-12-18 22:17 ` [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Philippe Mathieu-Daudé
  7 siblings, 1 reply; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:19 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

TWI (I2C) is supported so docs are updated for Cubieboard and
Orangepi-PC board.

Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
---
 docs/system/arm/cubieboard.rst | 1 +
 docs/system/arm/orangepi.rst   | 1 +
 2 files changed, 2 insertions(+)

diff --git a/docs/system/arm/cubieboard.rst b/docs/system/arm/cubieboard.rst
index 344ff8cef9..8d485f5435 100644
--- a/docs/system/arm/cubieboard.rst
+++ b/docs/system/arm/cubieboard.rst
@@ -14,3 +14,4 @@ Emulated devices:
 - SDHCI
 - USB controller
 - SATA controller
+- TWI (I2C) controller
diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
index 83c7445197..e5973600a1 100644
--- a/docs/system/arm/orangepi.rst
+++ b/docs/system/arm/orangepi.rst
@@ -25,6 +25,7 @@ The Orange Pi PC machine supports the following devices:
  * Clock Control Unit
  * System Control module
  * Security Identifier device
+ * TWI (I2C)
 
 Limitations
 """""""""""
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation
  2022-12-18 21:19 ` [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation Strahinja Jankovic
@ 2022-12-18 21:28   ` Strahinja Jankovic
  2022-12-18 22:07   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 21:28 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Philippe Mathieu-Daudé

I forgot to add Philippe Mathieu-Daudé in CC for this patch, so I'm
fixing it now.

Best regards,
Strahinja Jankovic

On Sun, Dec 18, 2022 at 10:19 PM Strahinja Jankovic
<strahinjapjankovic@gmail.com> wrote:
>
> This patch adds minimal support for AXP-209 PMU.
> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> the chip ID register, reset values for two more registers used by A10
> U-Boot SPL are covered.
>
> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> ---
>  hw/arm/Kconfig              |   1 +
>  hw/misc/Kconfig             |   4 +
>  hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
>  hw/misc/meson.build         |   1 +
>  hw/misc/trace-events        |   5 +
>  5 files changed, 249 insertions(+)
>  create mode 100644 hw/misc/allwinner-axp-209.c
>
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index eefe1fd134..67c6e83fe6 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -323,6 +323,7 @@ config ALLWINNER_A10
>      select ALLWINNER_A10_DRAMC
>      select ALLWINNER_EMAC
>      select ALLWINNER_I2C
> +    select ALLWINNER_AXP_209
>      select SERIAL
>      select UNIMP
>
> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> index 052fb54310..3855d937fd 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
>  config ALLWINNER_A10_DRAMC
>      bool
>
> +config ALLWINNER_AXP_209
> +    bool
> +    depends on I2C
> +
>  source macio/Kconfig
> diff --git a/hw/misc/allwinner-axp-209.c b/hw/misc/allwinner-axp-209.c
> new file mode 100644
> index 0000000000..cf79175034
> --- /dev/null
> +++ b/hw/misc/allwinner-axp-209.c
> @@ -0,0 +1,238 @@
> +/*
> + * AXP-209 Emulation
> + *
> + * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * SPDX-License-Identifier: MIT
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +#include "hw/i2c/i2c.h"
> +#include "migration/vmstate.h"
> +
> +#define TYPE_AXP_209 "allwinner.axp209"
> +
> +#define AXP_209(obj) \
> +    OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP_209)
> +
> +/* registers */
> +enum {
> +    REG_POWER_STATUS = 0x0u,
> +    REG_OPERATING_MODE,
> +    REG_OTG_VBUS_STATUS,
> +    REG_CHIP_VERSION,
> +    REG_DATA_CACHE_0,
> +    REG_DATA_CACHE_1,
> +    REG_DATA_CACHE_2,
> +    REG_DATA_CACHE_3,
> +    REG_DATA_CACHE_4,
> +    REG_DATA_CACHE_5,
> +    REG_DATA_CACHE_6,
> +    REG_DATA_CACHE_7,
> +    REG_DATA_CACHE_8,
> +    REG_DATA_CACHE_9,
> +    REG_DATA_CACHE_A,
> +    REG_DATA_CACHE_B,
> +    REG_POWER_OUTPUT_CTRL = 0x12u,
> +    REG_DC_DC2_OUT_V_CTRL = 0x23u,
> +    REG_DC_DC2_DVS_CTRL = 0x25u,
> +    REG_DC_DC3_OUT_V_CTRL = 0x27u,
> +    REG_LDO2_4_OUT_V_CTRL,
> +    REG_LDO3_OUT_V_CTRL,
> +    REG_VBUS_CH_MGMT = 0x30u,
> +    REG_SHUTDOWN_V_CTRL,
> +    REG_SHUTDOWN_CTRL,
> +    REG_CHARGE_CTRL_1,
> +    REG_CHARGE_CTRL_2,
> +    REG_SPARE_CHARGE_CTRL,
> +    REG_PEK_KEY_CTRL,
> +    REG_DC_DC_FREQ_SET,
> +    REG_CHR_TEMP_TH_SET,
> +    REG_CHR_HIGH_TEMP_TH_CTRL,
> +    REG_IPSOUT_WARN_L1,
> +    REG_IPSOUT_WARN_L2,
> +    REG_DISCHR_TEMP_TH_SET,
> +    REG_DISCHR_HIGH_TEMP_TH_CTRL,
> +    REG_IRQ_BANK_1_CTRL = 0x40u,
> +    REG_IRQ_BANK_2_CTRL,
> +    REG_IRQ_BANK_3_CTRL,
> +    REG_IRQ_BANK_4_CTRL,
> +    REG_IRQ_BANK_5_CTRL,
> +    REG_IRQ_BANK_1_STAT = 0x48u,
> +    REG_IRQ_BANK_2_STAT,
> +    REG_IRQ_BANK_3_STAT,
> +    REG_IRQ_BANK_4_STAT,
> +    REG_IRQ_BANK_5_STAT,
> +    REG_ADC_ACIN_V_H = 0x56u,
> +    REG_ADC_ACIN_V_L,
> +    REG_ADC_ACIN_CURR_H,
> +    REG_ADC_ACIN_CURR_L,
> +    REG_ADC_VBUS_V_H,
> +    REG_ADC_VBUS_V_L,
> +    REG_ADC_VBUS_CURR_H,
> +    REG_ADC_VBUS_CURR_L,
> +    REG_ADC_INT_TEMP_H,
> +    REG_ADC_INT_TEMP_L,
> +    REG_ADC_TEMP_SENS_V_H = 0x62u,
> +    REG_ADC_TEMP_SENS_V_L,
> +    REG_ADC_BAT_V_H = 0x78u,
> +    REG_ADC_BAT_V_L,
> +    REG_ADC_BAT_DISCHR_CURR_H,
> +    REG_ADC_BAT_DISCHR_CURR_L,
> +    REG_ADC_BAT_CHR_CURR_H,
> +    REG_ADC_BAT_CHR_CURR_L,
> +    REG_ADC_IPSOUT_V_H,
> +    REG_ADC_IPSOUT_V_L,
> +    REG_DC_DC_MOD_SEL = 0x80u,
> +    REG_ADC_EN_1,
> +    REG_ADC_EN_2,
> +    REG_ADC_SR_CTRL,
> +    REG_ADC_IN_RANGE,
> +    REG_GPIO1_ADC_IRQ_RISING_TH,
> +    REG_GPIO1_ADC_IRQ_FALLING_TH,
> +    REG_TIMER_CTRL = 0x8au,
> +    REG_VBUS_CTRL_MON_SRP,
> +    REG_OVER_TEMP_SHUTDOWN = 0x8fu,
> +    REG_GPIO0_FEAT_SET,
> +    REG_GPIO_OUT_HIGH_SET,
> +    REG_GPIO1_FEAT_SET,
> +    REG_GPIO2_FEAT_SET,
> +    REG_GPIO_SIG_STATE_SET_MON,
> +    REG_GPIO3_SET,
> +    REG_COULOMB_CNTR_CTRL = 0xb8u,
> +    REG_POWER_MEAS_RES,
> +    NR_REGS
> +};
> +
> +#define AXP_209_CHIP_VERSION_ID             (0x01)
> +#define AXP_209_DC_DC2_OUT_V_CTRL_RESET     (0x16)
> +#define AXP_209_IRQ_BANK_1_CTRL_RESET       (0xd8)
> +
> +/* A simple I2C slave which returns values of ID or CNT register. */
> +typedef struct AXP209I2CState {
> +    /*< private >*/
> +    I2CSlave i2c;
> +    /*< public >*/
> +    uint8_t regs[NR_REGS];  /* peripheral registers */
> +    uint8_t ptr;            /* current register index */
> +    uint8_t count;          /* counter used for tx/rx */
> +} AXP209I2CState;
> +
> +/* Reset all counters and load ID register */
> +static void axp_209_reset_enter(Object *obj, ResetType type)
> +{
> +    AXP209I2CState *s = AXP_209(obj);
> +
> +    memset(s->regs, 0, NR_REGS);
> +    s->ptr = 0;
> +    s->count = 0;
> +    s->regs[REG_CHIP_VERSION] = AXP_209_CHIP_VERSION_ID;
> +    s->regs[REG_DC_DC2_OUT_V_CTRL] = AXP_209_DC_DC2_OUT_V_CTRL_RESET;
> +    s->regs[REG_IRQ_BANK_1_CTRL] = AXP_209_IRQ_BANK_1_CTRL_RESET;
> +}
> +
> +/* Handle events from master. */
> +static int axp_209_event(I2CSlave *i2c, enum i2c_event event)
> +{
> +    AXP209I2CState *s = AXP_209(i2c);
> +
> +    s->count = 0;
> +
> +    return 0;
> +}
> +
> +/* Called when master requests read */
> +static uint8_t axp_209_rx(I2CSlave *i2c)
> +{
> +    AXP209I2CState *s = AXP_209(i2c);
> +    uint8_t ret = 0xff;
> +
> +    if (s->ptr < NR_REGS) {
> +        ret = s->regs[s->ptr++];
> +    }
> +
> +    trace_allwinner_axp_209_rx(s->ptr - 1, ret);
> +
> +    return ret;
> +}
> +
> +/*
> + * Called when master sends write.
> + * Update ptr with byte 0, then perform write with second byte.
> + */
> +static int axp_209_tx(I2CSlave *i2c, uint8_t data)
> +{
> +    AXP209I2CState *s = AXP_209(i2c);
> +
> +    if (s->count == 0) {
> +        /* Store register address */
> +        s->ptr = data;
> +        s->count++;
> +        trace_allwinner_axp_209_select(data);
> +    } else {
> +        trace_allwinner_axp_209_tx(s->ptr, data);
> +        if (s->ptr == REG_DC_DC2_OUT_V_CTRL) {
> +            s->regs[s->ptr++] = data;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_axp_209 = {
> +    .name = TYPE_AXP_209,
> +    .version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8_ARRAY(regs, AXP209I2CState, NR_REGS),
> +        VMSTATE_UINT8(count, AXP209I2CState),
> +        VMSTATE_UINT8(ptr, AXP209I2CState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void axp_209_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
> +    ResettableClass *rc = RESETTABLE_CLASS(oc);
> +
> +    rc->phases.enter = axp_209_reset_enter;
> +    dc->vmsd = &vmstate_axp_209;
> +    isc->event = axp_209_event;
> +    isc->recv = axp_209_rx;
> +    isc->send = axp_209_tx;
> +}
> +
> +static const TypeInfo axp_209_info = {
> +    .name = TYPE_AXP_209,
> +    .parent = TYPE_I2C_SLAVE,
> +    .instance_size = sizeof(AXP209I2CState),
> +    .class_init = axp_209_class_init
> +};
> +
> +static void axp_209_register_devices(void)
> +{
> +    type_register_static(&axp_209_info);
> +}
> +
> +type_init(axp_209_register_devices);
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> index 9eaa0750b5..7d332851cb 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -40,6 +40,7 @@ softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
>
>  softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
>  softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
> +softmmu_ss.add(when: 'CONFIG_ALLWINNER_AXP_209', if_true: files('allwinner-axp-209.c'))
>  softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
>  specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
>  softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
> diff --git a/hw/misc/trace-events b/hw/misc/trace-events
> index c18bc0605e..f6a7a6901f 100644
> --- a/hw/misc/trace-events
> +++ b/hw/misc/trace-events
> @@ -1,5 +1,10 @@
>  # See docs/devel/tracing.rst for syntax documentation.
>
> +# allwinner-axp209.c
> +allwinner_axp_209_rx(uint8_t reg, uint8_t data) "Read reg 0x%" PRIx8 " : 0x%" PRIx8
> +allwinner_axp_209_select(uint8_t reg) "Accessing reg 0x%" PRIx8
> +allwinner_axp_209_tx(uint8_t reg, uint8_t data) "Write reg 0x%" PRIx8 " : 0x%" PRIx8
> +
>  # allwinner-cpucfg.c
>  allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIx32
>  allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
> --
> 2.30.2
>


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 5/7] hw/arm: Add AXP-209 to Cubieboard
  2022-12-18 21:19 ` [PATCH v2 5/7] hw/arm: Add AXP-209 to Cubieboard Strahinja Jankovic
@ 2022-12-18 21:55   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-12-18 21:55 UTC (permalink / raw)
  To: Strahinja Jankovic, Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

On 18/12/22 22:19, Strahinja Jankovic wrote:
> SPL Boot for Cubieboard expects AXP-209 connected to I2C0 bus.
> 
> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> ---
>   hw/arm/cubieboard.c | 6 ++++++
>   1 file changed, 6 insertions(+)
> 
> diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
> index 5e3372a3c7..afc7980414 100644
> --- a/hw/arm/cubieboard.c
> +++ b/hw/arm/cubieboard.c
> @@ -20,6 +20,7 @@
>   #include "hw/boards.h"
>   #include "hw/qdev-properties.h"
>   #include "hw/arm/allwinner-a10.h"
> +#include "hw/i2c/i2c.h"
>   
>   static struct arm_boot_info cubieboard_binfo = {
>       .loader_start = AW_A10_SDRAM_BASE,
> @@ -34,6 +35,7 @@ static void cubieboard_init(MachineState *machine)
>       BlockBackend *blk;
>       BusState *bus;
>       DeviceState *carddev;
> +    I2CBus *i2c;
>   
>       /* BIOS is not supported by this board */
>       if (machine->firmware) {
> @@ -80,6 +82,10 @@ static void cubieboard_init(MachineState *machine)
>           exit(1);
>       }
>   
> +    /* Connect AXP 209 */
> +    i2c = (I2CBus *)qdev_get_child_bus(DEVICE(&a10->i2c0), "i2c");

Preferably using I2C_BUS() instead of the cast:

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> +    i2c_slave_create_simple(i2c, "allwinner.axp209", 0x34);
> +
>       /* Retrieve SD bus */
>       di = drive_get(IF_SD, 0, 0);
>       blk = di ? blk_by_legacy_dinfo(di) : NULL;



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 6/7] hw/arm: Allwinner A10 enable SPL load from MMC
  2022-12-18 21:19 ` [PATCH v2 6/7] hw/arm: Allwinner A10 enable SPL load from MMC Strahinja Jankovic
@ 2022-12-18 21:59   ` Philippe Mathieu-Daudé
  2022-12-18 22:16     ` Strahinja Jankovic
  0 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-12-18 21:59 UTC (permalink / raw)
  To: Strahinja Jankovic, Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

On 18/12/22 22:19, Strahinja Jankovic wrote:
> This patch enables copying of SPL from MMC if `-kernel` parameter is not
> passed when starting QEMU. SPL is copied to SRAM_A.
> 
> The approach is reused from Allwinner H3 implementation.
> 
> Tested with Armbian and custom Yocto image.
> 
> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> 
> Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
> ---
>   hw/arm/allwinner-a10.c         | 18 ++++++++++++++++++
>   hw/arm/cubieboard.c            |  5 +++++
>   include/hw/arm/allwinner-a10.h | 21 +++++++++++++++++++++
>   3 files changed, 44 insertions(+)
> 
> diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
> index 17e439777e..dc1966ff7a 100644
> --- a/hw/arm/allwinner-a10.c
> +++ b/hw/arm/allwinner-a10.c
> @@ -24,7 +24,9 @@
>   #include "sysemu/sysemu.h"
>   #include "hw/boards.h"
>   #include "hw/usb/hcd-ohci.h"
> +#include "hw/loader.h"
>   
> +#define AW_A10_SRAM_A_BASE      0x00000000
>   #define AW_A10_DRAMC_BASE       0x01c01000
>   #define AW_A10_MMC0_BASE        0x01c0f000
>   #define AW_A10_CCM_BASE         0x01c20000
> @@ -38,6 +40,22 @@
>   #define AW_A10_RTC_BASE         0x01c20d00
>   #define AW_A10_I2C0_BASE        0x01c2ac00
>   
> +void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk)
> +{
> +    const int64_t rom_size = 32 * KiB;
> +    g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
> +
> +    if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
> +        error_setg(&error_fatal, "%s: failed to read BlockBackend data",
> +                   __func__);
> +        return;
> +    }
> +
> +    rom_add_blob("allwinner-a10.bootrom", buffer, rom_size,
> +                  rom_size, AW_A10_SRAM_A_BASE,
> +                  NULL, NULL, NULL, NULL, false);
> +}
> +
>   static void aw_a10_init(Object *obj)
>   {
>       AwA10State *s = AW_A10(obj);
> diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
> index afc7980414..37659c35fd 100644
> --- a/hw/arm/cubieboard.c
> +++ b/hw/arm/cubieboard.c
> @@ -99,6 +99,11 @@ static void cubieboard_init(MachineState *machine)
>       memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
>                                   machine->ram);
>   
> +    /* Load target kernel or start using BootROM */
> +    if (!machine->kernel_filename && blk && blk_is_available(blk)) {
> +        /* Use Boot ROM to copy data from SD card to SRAM */
> +        allwinner_a10_bootrom_setup(a10, blk);
> +    }
>       /* TODO create and connect IDE devices for ide_drive_get() */
>   
>       cubieboard_binfo.ram_size = machine->ram_size;
> diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
> index 763935fca9..b3c9ed24c7 100644
> --- a/include/hw/arm/allwinner-a10.h
> +++ b/include/hw/arm/allwinner-a10.h
> @@ -15,6 +15,7 @@
>   #include "hw/misc/allwinner-a10-ccm.h"
>   #include "hw/misc/allwinner-a10-dramc.h"
>   #include "hw/i2c/allwinner-i2c.h"
> +#include "sysemu/block-backend.h"
>   
>   #include "target/arm/cpu.h"
>   #include "qom/object.h"
> @@ -47,4 +48,24 @@ struct AwA10State {
>       OHCISysBusState ohci[AW_A10_NUM_USB];
>   };
>   
> +/**
> + * Emulate Boot ROM firmware setup functionality.
> + *
> + * A real Allwinner A10 SoC contains a Boot ROM
> + * which is the first code that runs right after
> + * the SoC is powered on. The Boot ROM is responsible
> + * for loading user code (e.g. a bootloader) from any
> + * of the supported external devices and writing the
> + * downloaded code to internal SRAM. After loading the SoC
> + * begins executing the code written to SRAM.
> + *
> + * This function emulates the Boot ROM by copying 32 KiB
> + * of data

"at offset 8 KiB" ?

> from the given block device and writes it to
> + * the start of the first internal SRAM memory.
> + *
> + * @s: Allwinner A10 state object pointer
> + * @blk: Block backend device object pointer
> + */
> +void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk);
> +
>   #endif



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 7/7] docs/system/arm: Update Allwinner with TWI (I2C)
  2022-12-18 21:19 ` [PATCH v2 7/7] docs/system/arm: Update Allwinner with TWI (I2C) Strahinja Jankovic
@ 2022-12-18 22:02   ` Philippe Mathieu-Daudé
  2022-12-18 22:08     ` Strahinja Jankovic
  0 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-12-18 22:02 UTC (permalink / raw)
  To: Strahinja Jankovic, Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

On 18/12/22 22:19, Strahinja Jankovic wrote:
> TWI (I2C) is supported so docs are updated for Cubieboard and
> Orangepi-PC board.
> 
> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> ---
>   docs/system/arm/cubieboard.rst | 1 +
>   docs/system/arm/orangepi.rst   | 1 +
>   2 files changed, 2 insertions(+)
> 
> diff --git a/docs/system/arm/cubieboard.rst b/docs/system/arm/cubieboard.rst
> index 344ff8cef9..8d485f5435 100644
> --- a/docs/system/arm/cubieboard.rst
> +++ b/docs/system/arm/cubieboard.rst
> @@ -14,3 +14,4 @@ Emulated devices:
>   - SDHCI
>   - USB controller
>   - SATA controller
> +- TWI (I2C) controller
> diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
> index 83c7445197..e5973600a1 100644
> --- a/docs/system/arm/orangepi.rst
> +++ b/docs/system/arm/orangepi.rst
> @@ -25,6 +25,7 @@ The Orange Pi PC machine supports the following devices:
>    * Clock Control Unit
>    * System Control module
>    * Security Identifier device
> + * TWI (I2C)
>   
>   Limitations
>   """""""""""

Squash to patch #3 "hw/i2c: Allwinner TWI/I2C Emulation"?


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation
  2022-12-18 21:19 ` [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation Strahinja Jankovic
  2022-12-18 21:28   ` Strahinja Jankovic
@ 2022-12-18 22:07   ` Philippe Mathieu-Daudé
  2022-12-18 22:12     ` Strahinja Jankovic
  1 sibling, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-12-18 22:07 UTC (permalink / raw)
  To: Strahinja Jankovic, Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

On 18/12/22 22:19, Strahinja Jankovic wrote:
> This patch adds minimal support for AXP-209 PMU.
> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> the chip ID register, reset values for two more registers used by A10
> U-Boot SPL are covered.
> 
> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> ---
>   hw/arm/Kconfig              |   1 +
>   hw/misc/Kconfig             |   4 +
>   hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
>   hw/misc/meson.build         |   1 +
>   hw/misc/trace-events        |   5 +
>   5 files changed, 249 insertions(+)
>   create mode 100644 hw/misc/allwinner-axp-209.c


> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> index 052fb54310..3855d937fd 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
>   config ALLWINNER_A10_DRAMC
>       bool
>   
> +config ALLWINNER_AXP_209

This controller is not specific to AllWinner. It can be plugged on any
i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!

> +    bool
> +    depends on I2C
> +
>   source macio/Kconfig
> diff --git a/hw/misc/allwinner-axp-209.c b/hw/misc/allwinner-axp-209.c
> new file mode 100644
> index 0000000000..cf79175034
> --- /dev/null
> +++ b/hw/misc/allwinner-axp-209.c
> @@ -0,0 +1,238 @@
> +/*
> + * AXP-209 Emulation
> + *
> + * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 7/7] docs/system/arm: Update Allwinner with TWI (I2C)
  2022-12-18 22:02   ` Philippe Mathieu-Daudé
@ 2022-12-18 22:08     ` Strahinja Jankovic
  0 siblings, 0 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 22:08 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

Hi,

On Sun, Dec 18, 2022 at 11:02 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 22:19, Strahinja Jankovic wrote:
> > TWI (I2C) is supported so docs are updated for Cubieboard and
> > Orangepi-PC board.
> >
> > Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> > ---
> >   docs/system/arm/cubieboard.rst | 1 +
> >   docs/system/arm/orangepi.rst   | 1 +
> >   2 files changed, 2 insertions(+)
> >
> > diff --git a/docs/system/arm/cubieboard.rst b/docs/system/arm/cubieboard.rst
> > index 344ff8cef9..8d485f5435 100644
> > --- a/docs/system/arm/cubieboard.rst
> > +++ b/docs/system/arm/cubieboard.rst
> > @@ -14,3 +14,4 @@ Emulated devices:
> >   - SDHCI
> >   - USB controller
> >   - SATA controller
> > +- TWI (I2C) controller
> > diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
> > index 83c7445197..e5973600a1 100644
> > --- a/docs/system/arm/orangepi.rst
> > +++ b/docs/system/arm/orangepi.rst
> > @@ -25,6 +25,7 @@ The Orange Pi PC machine supports the following devices:
> >    * Clock Control Unit
> >    * System Control module
> >    * Security Identifier device
> > + * TWI (I2C)
> >
> >   Limitations
> >   """""""""""
>
> Squash to patch #3 "hw/i2c: Allwinner TWI/I2C Emulation"?

Yes, that makes sense, I will do it. Thanks.

Best regards,
Strahinja


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation
  2022-12-18 22:07   ` Philippe Mathieu-Daudé
@ 2022-12-18 22:12     ` Strahinja Jankovic
  2022-12-18 22:23       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 22:12 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

Hi,

On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 22:19, Strahinja Jankovic wrote:
> > This patch adds minimal support for AXP-209 PMU.
> > Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> > the chip ID register, reset values for two more registers used by A10
> > U-Boot SPL are covered.
> >
> > Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> > ---
> >   hw/arm/Kconfig              |   1 +
> >   hw/misc/Kconfig             |   4 +
> >   hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
> >   hw/misc/meson.build         |   1 +
> >   hw/misc/trace-events        |   5 +
> >   5 files changed, 249 insertions(+)
> >   create mode 100644 hw/misc/allwinner-axp-209.c
>
>
> > diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> > index 052fb54310..3855d937fd 100644
> > --- a/hw/misc/Kconfig
> > +++ b/hw/misc/Kconfig
> > @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
> >   config ALLWINNER_A10_DRAMC
> >       bool
> >
> > +config ALLWINNER_AXP_209
>
> This controller is not specific to AllWinner. It can be plugged on any
> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!

Do you mean only in Kconfig, or everywhere (file name, function names,
etc.)? Thanks.

Best regards,
Strahinja


>
> > +    bool
> > +    depends on I2C
> > +
> >   source macio/Kconfig
> > diff --git a/hw/misc/allwinner-axp-209.c b/hw/misc/allwinner-axp-209.c
> > new file mode 100644
> > index 0000000000..cf79175034
> > --- /dev/null
> > +++ b/hw/misc/allwinner-axp-209.c
> > @@ -0,0 +1,238 @@
> > +/*
> > + * AXP-209 Emulation
> > + *
> > + * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 6/7] hw/arm: Allwinner A10 enable SPL load from MMC
  2022-12-18 21:59   ` Philippe Mathieu-Daudé
@ 2022-12-18 22:16     ` Strahinja Jankovic
  0 siblings, 0 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 22:16 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

Hi,

On Sun, Dec 18, 2022 at 10:59 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 22:19, Strahinja Jankovic wrote:
> > This patch enables copying of SPL from MMC if `-kernel` parameter is not
> > passed when starting QEMU. SPL is copied to SRAM_A.
> >
> > The approach is reused from Allwinner H3 implementation.
> >
> > Tested with Armbian and custom Yocto image.
> >
> > Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> >
> > Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
> > ---
> >   hw/arm/allwinner-a10.c         | 18 ++++++++++++++++++
> >   hw/arm/cubieboard.c            |  5 +++++
> >   include/hw/arm/allwinner-a10.h | 21 +++++++++++++++++++++
> >   3 files changed, 44 insertions(+)
> >
> > diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
> > index 17e439777e..dc1966ff7a 100644
> > --- a/hw/arm/allwinner-a10.c
> > +++ b/hw/arm/allwinner-a10.c
> > @@ -24,7 +24,9 @@
> >   #include "sysemu/sysemu.h"
> >   #include "hw/boards.h"
> >   #include "hw/usb/hcd-ohci.h"
> > +#include "hw/loader.h"
> >
> > +#define AW_A10_SRAM_A_BASE      0x00000000
> >   #define AW_A10_DRAMC_BASE       0x01c01000
> >   #define AW_A10_MMC0_BASE        0x01c0f000
> >   #define AW_A10_CCM_BASE         0x01c20000
> > @@ -38,6 +40,22 @@
> >   #define AW_A10_RTC_BASE         0x01c20d00
> >   #define AW_A10_I2C0_BASE        0x01c2ac00
> >
> > +void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk)
> > +{
> > +    const int64_t rom_size = 32 * KiB;
> > +    g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
> > +
> > +    if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
> > +        error_setg(&error_fatal, "%s: failed to read BlockBackend data",
> > +                   __func__);
> > +        return;
> > +    }
> > +
> > +    rom_add_blob("allwinner-a10.bootrom", buffer, rom_size,
> > +                  rom_size, AW_A10_SRAM_A_BASE,
> > +                  NULL, NULL, NULL, NULL, false);
> > +}
> > +
> >   static void aw_a10_init(Object *obj)
> >   {
> >       AwA10State *s = AW_A10(obj);
> > diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
> > index afc7980414..37659c35fd 100644
> > --- a/hw/arm/cubieboard.c
> > +++ b/hw/arm/cubieboard.c
> > @@ -99,6 +99,11 @@ static void cubieboard_init(MachineState *machine)
> >       memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
> >                                   machine->ram);
> >
> > +    /* Load target kernel or start using BootROM */
> > +    if (!machine->kernel_filename && blk && blk_is_available(blk)) {
> > +        /* Use Boot ROM to copy data from SD card to SRAM */
> > +        allwinner_a10_bootrom_setup(a10, blk);
> > +    }
> >       /* TODO create and connect IDE devices for ide_drive_get() */
> >
> >       cubieboard_binfo.ram_size = machine->ram_size;
> > diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
> > index 763935fca9..b3c9ed24c7 100644
> > --- a/include/hw/arm/allwinner-a10.h
> > +++ b/include/hw/arm/allwinner-a10.h
> > @@ -15,6 +15,7 @@
> >   #include "hw/misc/allwinner-a10-ccm.h"
> >   #include "hw/misc/allwinner-a10-dramc.h"
> >   #include "hw/i2c/allwinner-i2c.h"
> > +#include "sysemu/block-backend.h"
> >
> >   #include "target/arm/cpu.h"
> >   #include "qom/object.h"
> > @@ -47,4 +48,24 @@ struct AwA10State {
> >       OHCISysBusState ohci[AW_A10_NUM_USB];
> >   };
> >
> > +/**
> > + * Emulate Boot ROM firmware setup functionality.
> > + *
> > + * A real Allwinner A10 SoC contains a Boot ROM
> > + * which is the first code that runs right after
> > + * the SoC is powered on. The Boot ROM is responsible
> > + * for loading user code (e.g. a bootloader) from any
> > + * of the supported external devices and writing the
> > + * downloaded code to internal SRAM. After loading the SoC
> > + * begins executing the code written to SRAM.
> > + *
> > + * This function emulates the Boot ROM by copying 32 KiB
> > + * of data
>
> "at offset 8 KiB" ?

Yes, that is correct. I will update the function description.

Best regards,
Strahinja

>
> > from the given block device and writes it to
> > + * the start of the first internal SRAM memory.
> > + *
> > + * @s: Allwinner A10 state object pointer
> > + * @blk: Block backend device object pointer
> > + */
> > +void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk);
> > +
> >   #endif
>


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card
  2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
                   ` (6 preceding siblings ...)
  2022-12-18 21:19 ` [PATCH v2 7/7] docs/system/arm: Update Allwinner with TWI (I2C) Strahinja Jankovic
@ 2022-12-18 22:17 ` Philippe Mathieu-Daudé
  2022-12-18 22:34   ` Strahinja Jankovic
  7 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-12-18 22:17 UTC (permalink / raw)
  To: Strahinja Jankovic, Peter Maydell
  Cc: Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel,
	Strahinja Jankovic

On 18/12/22 22:19, Strahinja Jankovic wrote:
> This patch series adds missing Allwinner A10 modules needed for
> successful SPL boot:
> - Clock controller module
> - DRAM controller
> - I2C0 controller (added also for Allwinner H3 since it is the same)
> - AXP-209 connected to I2C0 bus
> 
> It also updates Allwinner A10 emulation so SPL is copied from attached
> SD card if `-kernel` parameter is not passed when starting QEMU
> (approach adapted from Allwinner H3 implementation).
> 
> Boot from SD card has been tested with Cubieboard Armbian SD card image and custom
> Yocto image built for Cubieboard.
> Example usage for Armbian image:
> qemu-system-arm -M cubieboard -nographic -sd ~/Armbian_22.11.0-trunk_Cubieboard_kinetic_edge_6.0.7.img

As a follow-up, could you add a test similar to
test_arm_orangepi_bionic_20_08() in tests/avocado/boot_linux_console.py?

This test could be refactored as do_test_arm_allwinner_armbian(), called
for orangepi and cubieboard with the corresponding url / hash.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation
  2022-12-18 22:12     ` Strahinja Jankovic
@ 2022-12-18 22:23       ` Philippe Mathieu-Daudé
  2022-12-18 22:39         ` Strahinja Jankovic
  0 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-12-18 22:23 UTC (permalink / raw)
  To: Strahinja Jankovic
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

On 18/12/22 23:12, Strahinja Jankovic wrote:
> Hi,
> 
> On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
> <philmd@linaro.org> wrote:
>>
>> On 18/12/22 22:19, Strahinja Jankovic wrote:
>>> This patch adds minimal support for AXP-209 PMU.
>>> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
>>> the chip ID register, reset values for two more registers used by A10
>>> U-Boot SPL are covered.
>>>
>>> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
>>> ---
>>>    hw/arm/Kconfig              |   1 +
>>>    hw/misc/Kconfig             |   4 +
>>>    hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
>>>    hw/misc/meson.build         |   1 +
>>>    hw/misc/trace-events        |   5 +
>>>    5 files changed, 249 insertions(+)
>>>    create mode 100644 hw/misc/allwinner-axp-209.c
>>
>>
>>> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
>>> index 052fb54310..3855d937fd 100644
>>> --- a/hw/misc/Kconfig
>>> +++ b/hw/misc/Kconfig
>>> @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
>>>    config ALLWINNER_A10_DRAMC
>>>        bool
>>>
>>> +config ALLWINNER_AXP_209
>>
>> This controller is not specific to AllWinner. It can be plugged on any
>> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!
> 
> Do you mean only in Kconfig, or everywhere (file name, function names,
> etc.)? Thanks.

Keeping the file / functions names with 'allwinner' would give the false
idea this is AllWinner specific; rather confusing isn't it? Besides it
is not part of the SoC, this is an external component sitting on the
bus. So "everywhere".

Also, the "select ALLWINNER_AXP_209/AXP209_PMU" line in hw/arm/Kconfig
belongs to the next patch "hw/arm: Add AXP-209 to Cubieboard".

Regards,

Phil.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card
  2022-12-18 22:17 ` [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Philippe Mathieu-Daudé
@ 2022-12-18 22:34   ` Strahinja Jankovic
  2022-12-18 22:57     ` Strahinja Jankovic
  0 siblings, 1 reply; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 22:34 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

Hi,


On Sun, Dec 18, 2022 at 11:17 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 22:19, Strahinja Jankovic wrote:
> > This patch series adds missing Allwinner A10 modules needed for
> > successful SPL boot:
> > - Clock controller module
> > - DRAM controller
> > - I2C0 controller (added also for Allwinner H3 since it is the same)
> > - AXP-209 connected to I2C0 bus
> >
> > It also updates Allwinner A10 emulation so SPL is copied from attached
> > SD card if `-kernel` parameter is not passed when starting QEMU
> > (approach adapted from Allwinner H3 implementation).
> >
> > Boot from SD card has been tested with Cubieboard Armbian SD card image and custom
> > Yocto image built for Cubieboard.
> > Example usage for Armbian image:
> > qemu-system-arm -M cubieboard -nographic -sd ~/Armbian_22.11.0-trunk_Cubieboard_kinetic_edge_6.0.7.img
>
> As a follow-up, could you add a test similar to
> test_arm_orangepi_bionic_20_08() in tests/avocado/boot_linux_console.py?
>
> This test could be refactored as do_test_arm_allwinner_armbian(), called
> for orangepi and cubieboard with the corresponding url / hash.

I was planning to do it (I already have a patch for cubieboard), but
there is a problem with finding a stable-enough image for cubieboard
for automated testing.
Unfortunately, Cubieboard does not have supported Armbian images as
OrangePi-PC has (it only has weekly builds). From the images that can
be found on archive.armbian.com, there is only one bionic image
(21.02) and it won't boot because it hangs due to the musb issue (I
tried both with my patches and without, by extracting
kernel/dtb/initrd). Other images are focal, but for some reason, in
those images it is impossible to interrupt U-Boot (tested with 21.08),
so I could not append to bootcmd to make boot process more verbose and
easier to monitor for automated testing.

That is why, for now, I would suggest not updating the SPL/SD boot
test for Cubieboard.

Best regards,
Strahinja


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation
  2022-12-18 22:23       ` Philippe Mathieu-Daudé
@ 2022-12-18 22:39         ` Strahinja Jankovic
  2022-12-19  7:15           ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 22:39 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

Hi,

On Sun, Dec 18, 2022 at 11:23 PM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 23:12, Strahinja Jankovic wrote:
> > Hi,
> >
> > On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
> > <philmd@linaro.org> wrote:
> >>
> >> On 18/12/22 22:19, Strahinja Jankovic wrote:
> >>> This patch adds minimal support for AXP-209 PMU.
> >>> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> >>> the chip ID register, reset values for two more registers used by A10
> >>> U-Boot SPL are covered.
> >>>
> >>> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> >>> ---
> >>>    hw/arm/Kconfig              |   1 +
> >>>    hw/misc/Kconfig             |   4 +
> >>>    hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
> >>>    hw/misc/meson.build         |   1 +
> >>>    hw/misc/trace-events        |   5 +
> >>>    5 files changed, 249 insertions(+)
> >>>    create mode 100644 hw/misc/allwinner-axp-209.c
> >>
> >>
> >>> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> >>> index 052fb54310..3855d937fd 100644
> >>> --- a/hw/misc/Kconfig
> >>> +++ b/hw/misc/Kconfig
> >>> @@ -180,4 +180,8 @@ config ALLWINNER_A10_CCM
> >>>    config ALLWINNER_A10_DRAMC
> >>>        bool
> >>>
> >>> +config ALLWINNER_AXP_209
> >>
> >> This controller is not specific to AllWinner. It can be plugged on any
> >> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!
> >
> > Do you mean only in Kconfig, or everywhere (file name, function names,
> > etc.)? Thanks.
>
> Keeping the file / functions names with 'allwinner' would give the false
> idea this is AllWinner specific; rather confusing isn't it? Besides it
> is not part of the SoC, this is an external component sitting on the
> bus. So "everywhere".

I was expecting that answer, but I wanted to check :)
When I started writing code for AXP209 it was indeed without allwinner
prefix, but then checkpatch.pl complained about missing lines in
MAINTAINERS. At that time it was easier to add the prefix (and get a
match in MAINTAINERS) than to investigate if I should update the
MAINTAINERS file or ignore the checkpatch.pl complaint.

I will update everything related to AXP209 so it does not have the
Allwinner prefix.

>
> Also, the "select ALLWINNER_AXP_209/AXP209_PMU" line in hw/arm/Kconfig
> belongs to the next patch "hw/arm: Add AXP-209 to Cubieboard".

I agree, will fix it.

Best regards,
Strahinja

>
> Regards,
>
> Phil.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card
  2022-12-18 22:34   ` Strahinja Jankovic
@ 2022-12-18 22:57     ` Strahinja Jankovic
  2022-12-19  7:11       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-18 22:57 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

Hi,

I just looked around a bit more. Would OpenWrt image be acceptable?
It looks like there are releases for cubieboard that are kept for a
longer time, and I just checked that they work properly, so I could
add them to the acceptance test.

Best regards,
Strahinja

On Sun, Dec 18, 2022 at 11:34 PM Strahinja Jankovic
<strahinjapjankovic@gmail.com> wrote:
>
> Hi,
>
>
> On Sun, Dec 18, 2022 at 11:17 PM Philippe Mathieu-Daudé
> <philmd@linaro.org> wrote:
> >
> > On 18/12/22 22:19, Strahinja Jankovic wrote:
> > > This patch series adds missing Allwinner A10 modules needed for
> > > successful SPL boot:
> > > - Clock controller module
> > > - DRAM controller
> > > - I2C0 controller (added also for Allwinner H3 since it is the same)
> > > - AXP-209 connected to I2C0 bus
> > >
> > > It also updates Allwinner A10 emulation so SPL is copied from attached
> > > SD card if `-kernel` parameter is not passed when starting QEMU
> > > (approach adapted from Allwinner H3 implementation).
> > >
> > > Boot from SD card has been tested with Cubieboard Armbian SD card image and custom
> > > Yocto image built for Cubieboard.
> > > Example usage for Armbian image:
> > > qemu-system-arm -M cubieboard -nographic -sd ~/Armbian_22.11.0-trunk_Cubieboard_kinetic_edge_6.0.7.img
> >
> > As a follow-up, could you add a test similar to
> > test_arm_orangepi_bionic_20_08() in tests/avocado/boot_linux_console.py?
> >
> > This test could be refactored as do_test_arm_allwinner_armbian(), called
> > for orangepi and cubieboard with the corresponding url / hash.
>
> I was planning to do it (I already have a patch for cubieboard), but
> there is a problem with finding a stable-enough image for cubieboard
> for automated testing.
> Unfortunately, Cubieboard does not have supported Armbian images as
> OrangePi-PC has (it only has weekly builds). From the images that can
> be found on archive.armbian.com, there is only one bionic image
> (21.02) and it won't boot because it hangs due to the musb issue (I
> tried both with my patches and without, by extracting
> kernel/dtb/initrd). Other images are focal, but for some reason, in
> those images it is impossible to interrupt U-Boot (tested with 21.08),
> so I could not append to bootcmd to make boot process more verbose and
> easier to monitor for automated testing.
>
> That is why, for now, I would suggest not updating the SPL/SD boot
> test for Cubieboard.
>
> Best regards,
> Strahinja


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card
  2022-12-18 22:57     ` Strahinja Jankovic
@ 2022-12-19  7:11       ` Philippe Mathieu-Daudé
  2022-12-19 22:03         ` Strahinja Jankovic
  0 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-12-19  7:11 UTC (permalink / raw)
  To: Strahinja Jankovic
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

On 18/12/22 23:57, Strahinja Jankovic wrote:
> Hi,
> 
> I just looked around a bit more. Would OpenWrt image be acceptable?

Sure.

> It looks like there are releases for cubieboard that are kept for a
> longer time, and I just checked that they work properly, so I could
> add them to the acceptance test.
> 
> Best regards,
> Strahinja
> 
> On Sun, Dec 18, 2022 at 11:34 PM Strahinja Jankovic
> <strahinjapjankovic@gmail.com> wrote:
>>
>> Hi,
>>
>>
>> On Sun, Dec 18, 2022 at 11:17 PM Philippe Mathieu-Daudé
>> <philmd@linaro.org> wrote:
>>>
>>> On 18/12/22 22:19, Strahinja Jankovic wrote:
>>>> This patch series adds missing Allwinner A10 modules needed for
>>>> successful SPL boot:
>>>> - Clock controller module
>>>> - DRAM controller
>>>> - I2C0 controller (added also for Allwinner H3 since it is the same)
>>>> - AXP-209 connected to I2C0 bus
>>>>
>>>> It also updates Allwinner A10 emulation so SPL is copied from attached
>>>> SD card if `-kernel` parameter is not passed when starting QEMU
>>>> (approach adapted from Allwinner H3 implementation).
>>>>
>>>> Boot from SD card has been tested with Cubieboard Armbian SD card image and custom
>>>> Yocto image built for Cubieboard.
>>>> Example usage for Armbian image:
>>>> qemu-system-arm -M cubieboard -nographic -sd ~/Armbian_22.11.0-trunk_Cubieboard_kinetic_edge_6.0.7.img
>>>
>>> As a follow-up, could you add a test similar to
>>> test_arm_orangepi_bionic_20_08() in tests/avocado/boot_linux_console.py?
>>>
>>> This test could be refactored as do_test_arm_allwinner_armbian(), called
>>> for orangepi and cubieboard with the corresponding url / hash.
>>
>> I was planning to do it (I already have a patch for cubieboard), but
>> there is a problem with finding a stable-enough image for cubieboard
>> for automated testing.
>> Unfortunately, Cubieboard does not have supported Armbian images as
>> OrangePi-PC has (it only has weekly builds).

Developers shouldn't worry about that but focus on the testing. The
QEMU project doesn't have dedicated sysadmin / storage, but if it had
it should be their problem, not yours. Meanwhile such a test is still
useful. Artifacts come with their hash, so can be uploaded elsewhere
later.

>> From the images that can
>> be found on archive.armbian.com, there is only one bionic image
>> (21.02) and it won't boot because it hangs due to the musb issue (I
>> tried both with my patches and without, by extracting
>> kernel/dtb/initrd).

Similar approach:
https://lore.kernel.org/qemu-devel/20201018205551.1537927-4-f4bug@amsat.org/

>> Other images are focal, but for some reason, in
>> those images it is impossible to interrupt U-Boot (tested with 21.08),
>> so I could not append to bootcmd to make boot process more verbose and
>> easier to monitor for automated testing.
>>
>> That is why, for now, I would suggest not updating the SPL/SD boot
>> test for Cubieboard.

Niek can tell how many times his tests catched regressions for his
OrangePi machine; I remember at least 3 occasions :)

Regards,

Phil.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation
  2022-12-18 22:39         ` Strahinja Jankovic
@ 2022-12-19  7:15           ` Philippe Mathieu-Daudé
  2022-12-19 22:05             ` Strahinja Jankovic
  0 siblings, 1 reply; 25+ messages in thread
From: Philippe Mathieu-Daudé @ 2022-12-19  7:15 UTC (permalink / raw)
  To: Strahinja Jankovic
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

On 18/12/22 23:39, Strahinja Jankovic wrote:
> Hi,
> 
> On Sun, Dec 18, 2022 at 11:23 PM Philippe Mathieu-Daudé
> <philmd@linaro.org> wrote:
>>
>> On 18/12/22 23:12, Strahinja Jankovic wrote:
>>> Hi,
>>>
>>> On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
>>> <philmd@linaro.org> wrote:
>>>>
>>>> On 18/12/22 22:19, Strahinja Jankovic wrote:
>>>>> This patch adds minimal support for AXP-209 PMU.
>>>>> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
>>>>> the chip ID register, reset values for two more registers used by A10
>>>>> U-Boot SPL are covered.
>>>>>
>>>>> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
>>>>> ---
>>>>>     hw/arm/Kconfig              |   1 +
>>>>>     hw/misc/Kconfig             |   4 +
>>>>>     hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
>>>>>     hw/misc/meson.build         |   1 +
>>>>>     hw/misc/trace-events        |   5 +
>>>>>     5 files changed, 249 insertions(+)
>>>>>     create mode 100644 hw/misc/allwinner-axp-209.c


>>>>> +config ALLWINNER_AXP_209
>>>>
>>>> This controller is not specific to AllWinner. It can be plugged on any
>>>> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!
>>>
>>> Do you mean only in Kconfig, or everywhere (file name, function names,
>>> etc.)? Thanks.
>>
>> Keeping the file / functions names with 'allwinner' would give the false
>> idea this is AllWinner specific; rather confusing isn't it? Besides it
>> is not part of the SoC, this is an external component sitting on the
>> bus. So "everywhere".
> 
> I was expecting that answer, but I wanted to check :)
> When I started writing code for AXP209 it was indeed without allwinner
> prefix, but then checkpatch.pl complained about missing lines in
> MAINTAINERS. At that time it was easier to add the prefix (and get a
> match in MAINTAINERS) than to investigate if I should update the
> MAINTAINERS file or ignore the checkpatch.pl complaint.
> 
> I will update everything related to AXP209 so it does not have the
> Allwinner prefix.

Add a new AXP209 MAINTAINERS's section with your name :) Or add the new
file to the Allwinner-a10 section and add your name as designated
reviewer or co-maintainer :)


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card
  2022-12-19  7:11       ` Philippe Mathieu-Daudé
@ 2022-12-19 22:03         ` Strahinja Jankovic
  0 siblings, 0 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-19 22:03 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

Hi,

On Mon, Dec 19, 2022 at 8:11 AM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 23:57, Strahinja Jankovic wrote:
> > Hi,
> >
> > I just looked around a bit more. Would OpenWrt image be acceptable?
>
> Sure.
>
> > It looks like there are releases for cubieboard that are kept for a
> > longer time, and I just checked that they work properly, so I could
> > add them to the acceptance test.
> >
> > Best regards,
> > Strahinja
> >
> > On Sun, Dec 18, 2022 at 11:34 PM Strahinja Jankovic
> > <strahinjapjankovic@gmail.com> wrote:
> >>
> >> Hi,
> >>
> >>
> >> On Sun, Dec 18, 2022 at 11:17 PM Philippe Mathieu-Daudé
> >> <philmd@linaro.org> wrote:
> >>>
> >>> On 18/12/22 22:19, Strahinja Jankovic wrote:
> >>>> This patch series adds missing Allwinner A10 modules needed for
> >>>> successful SPL boot:
> >>>> - Clock controller module
> >>>> - DRAM controller
> >>>> - I2C0 controller (added also for Allwinner H3 since it is the same)
> >>>> - AXP-209 connected to I2C0 bus
> >>>>
> >>>> It also updates Allwinner A10 emulation so SPL is copied from attached
> >>>> SD card if `-kernel` parameter is not passed when starting QEMU
> >>>> (approach adapted from Allwinner H3 implementation).
> >>>>
> >>>> Boot from SD card has been tested with Cubieboard Armbian SD card image and custom
> >>>> Yocto image built for Cubieboard.
> >>>> Example usage for Armbian image:
> >>>> qemu-system-arm -M cubieboard -nographic -sd ~/Armbian_22.11.0-trunk_Cubieboard_kinetic_edge_6.0.7.img
> >>>
> >>> As a follow-up, could you add a test similar to
> >>> test_arm_orangepi_bionic_20_08() in tests/avocado/boot_linux_console.py?
> >>>
> >>> This test could be refactored as do_test_arm_allwinner_armbian(), called
> >>> for orangepi and cubieboard with the corresponding url / hash.
> >>
> >> I was planning to do it (I already have a patch for cubieboard), but
> >> there is a problem with finding a stable-enough image for cubieboard
> >> for automated testing.
> >> Unfortunately, Cubieboard does not have supported Armbian images as
> >> OrangePi-PC has (it only has weekly builds).
>
> Developers shouldn't worry about that but focus on the testing. The
> QEMU project doesn't have dedicated sysadmin / storage, but if it had
> it should be their problem, not yours. Meanwhile such a test is still
> useful. Artifacts come with their hash, so can be uploaded elsewhere
> later.
>
> >> From the images that can
> >> be found on archive.armbian.com, there is only one bionic image
> >> (21.02) and it won't boot because it hangs due to the musb issue (I
> >> tried both with my patches and without, by extracting
> >> kernel/dtb/initrd).
>
> Similar approach:
> https://lore.kernel.org/qemu-devel/20201018205551.1537927-4-f4bug@amsat.org/
>
> >> Other images are focal, but for some reason, in
> >> those images it is impossible to interrupt U-Boot (tested with 21.08),
> >> so I could not append to bootcmd to make boot process more verbose and
> >> easier to monitor for automated testing.
> >>
> >> That is why, for now, I would suggest not updating the SPL/SD boot
> >> test for Cubieboard.
>
> Niek can tell how many times his tests catched regressions for his
> OrangePi machine; I remember at least 3 occasions :)

Thanks for the suggestions, I will add the SPL boot test and use
OpenWrt image for it.

Best regards,
Strahinja

>
> Regards,
>
> Phil.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation
  2022-12-19  7:15           ` Philippe Mathieu-Daudé
@ 2022-12-19 22:05             ` Strahinja Jankovic
  0 siblings, 0 replies; 25+ messages in thread
From: Strahinja Jankovic @ 2022-12-19 22:05 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Beniamino Galvani, Niek Linnenbank, qemu-arm, qemu-devel

On Mon, Dec 19, 2022 at 8:15 AM Philippe Mathieu-Daudé
<philmd@linaro.org> wrote:
>
> On 18/12/22 23:39, Strahinja Jankovic wrote:
> > Hi,
> >
> > On Sun, Dec 18, 2022 at 11:23 PM Philippe Mathieu-Daudé
> > <philmd@linaro.org> wrote:
> >>
> >> On 18/12/22 23:12, Strahinja Jankovic wrote:
> >>> Hi,
> >>>
> >>> On Sun, Dec 18, 2022 at 11:07 PM Philippe Mathieu-Daudé
> >>> <philmd@linaro.org> wrote:
> >>>>
> >>>> On 18/12/22 22:19, Strahinja Jankovic wrote:
> >>>>> This patch adds minimal support for AXP-209 PMU.
> >>>>> Most important is chip ID since U-Boot SPL expects version 0x1. Besides
> >>>>> the chip ID register, reset values for two more registers used by A10
> >>>>> U-Boot SPL are covered.
> >>>>>
> >>>>> Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
> >>>>> ---
> >>>>>     hw/arm/Kconfig              |   1 +
> >>>>>     hw/misc/Kconfig             |   4 +
> >>>>>     hw/misc/allwinner-axp-209.c | 238 ++++++++++++++++++++++++++++++++++++
> >>>>>     hw/misc/meson.build         |   1 +
> >>>>>     hw/misc/trace-events        |   5 +
> >>>>>     5 files changed, 249 insertions(+)
> >>>>>     create mode 100644 hw/misc/allwinner-axp-209.c
>
>
> >>>>> +config ALLWINNER_AXP_209
> >>>>
> >>>> This controller is not specific to AllWinner. It can be plugged on any
> >>>> i2c bus. Please rename it AXP209_PMU. Otherwise LGTM!
> >>>
> >>> Do you mean only in Kconfig, or everywhere (file name, function names,
> >>> etc.)? Thanks.
> >>
> >> Keeping the file / functions names with 'allwinner' would give the false
> >> idea this is AllWinner specific; rather confusing isn't it? Besides it
> >> is not part of the SoC, this is an external component sitting on the
> >> bus. So "everywhere".
> >
> > I was expecting that answer, but I wanted to check :)
> > When I started writing code for AXP209 it was indeed without allwinner
> > prefix, but then checkpatch.pl complained about missing lines in
> > MAINTAINERS. At that time it was easier to add the prefix (and get a
> > match in MAINTAINERS) than to investigate if I should update the
> > MAINTAINERS file or ignore the checkpatch.pl complaint.
> >
> > I will update everything related to AXP209 so it does not have the
> > Allwinner prefix.
>
> Add a new AXP209 MAINTAINERS's section with your name :) Or add the new
> file to the Allwinner-a10 section and add your name as designated
> reviewer or co-maintainer :)

Thanks, I will take one of these suggested approaches.

Best regards,
Strahinja


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2022-12-19 22:06 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-18 21:19 [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Strahinja Jankovic
2022-12-18 21:19 ` [PATCH v2 1/7] hw/misc: Allwinner-A10 Clock Controller Module Emulation Strahinja Jankovic
2022-12-18 21:19 ` [PATCH v2 2/7] hw/misc: Allwinner A10 DRAM Controller Emulation Strahinja Jankovic
2022-12-18 21:19 ` [PATCH v2 3/7] hw/i2c: Allwinner TWI/I2C Emulation Strahinja Jankovic
2022-12-18 21:19 ` [PATCH v2 4/7] hw/misc: Allwinner AXP-209 Emulation Strahinja Jankovic
2022-12-18 21:28   ` Strahinja Jankovic
2022-12-18 22:07   ` Philippe Mathieu-Daudé
2022-12-18 22:12     ` Strahinja Jankovic
2022-12-18 22:23       ` Philippe Mathieu-Daudé
2022-12-18 22:39         ` Strahinja Jankovic
2022-12-19  7:15           ` Philippe Mathieu-Daudé
2022-12-19 22:05             ` Strahinja Jankovic
2022-12-18 21:19 ` [PATCH v2 5/7] hw/arm: Add AXP-209 to Cubieboard Strahinja Jankovic
2022-12-18 21:55   ` Philippe Mathieu-Daudé
2022-12-18 21:19 ` [PATCH v2 6/7] hw/arm: Allwinner A10 enable SPL load from MMC Strahinja Jankovic
2022-12-18 21:59   ` Philippe Mathieu-Daudé
2022-12-18 22:16     ` Strahinja Jankovic
2022-12-18 21:19 ` [PATCH v2 7/7] docs/system/arm: Update Allwinner with TWI (I2C) Strahinja Jankovic
2022-12-18 22:02   ` Philippe Mathieu-Daudé
2022-12-18 22:08     ` Strahinja Jankovic
2022-12-18 22:17 ` [PATCH v2 0/7] Enable Cubieboard A10 boot SPL from SD card Philippe Mathieu-Daudé
2022-12-18 22:34   ` Strahinja Jankovic
2022-12-18 22:57     ` Strahinja Jankovic
2022-12-19  7:11       ` Philippe Mathieu-Daudé
2022-12-19 22:03         ` Strahinja Jankovic

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.