All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH qemu 00/38] aspeed: going mainline
@ 2016-11-18 14:21 Cédric Le Goater
  2016-11-18 14:21 ` [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g Cédric Le Goater
                   ` (37 more replies)
  0 siblings, 38 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

Hello,

This is rather large patchset which I intend to send to mainline qemu
in a couple of weeks when time permits. In there, you will find a lot
of littles fixes, some improvements on existing models and a couple of
new models which were never exposed to mainline yet. Feel free to scan
through the patches or just read the summary below and ask questions.

* SoC level 
  - an AST2400 A1 SoC for the Palmetto machine
  - a Romulus machine  
  - a SRAM region (which is used at early boot in U-Boot, serves as a
    stack, and by DRAM calibration)

* SMC (Flash controller) 
  - Command mode support. Flash contents is accessed directly on the
    AHB bus   
  - DMA support
  - dummy bytes
  - auto strapping of configuration for boot flash
  - use CS0 as a boot ROM. Today, qemu can not boot from a MMIO region.
    As this is complex to do (TCG layer modification), we use a ROM
    region in which we copy the flash contents. Hopefully, I got it 
    right this time.

* SDMC (DRAM controller) 
  - support for new registers to fake DRAM calibration (AST2400). This
    is a good start to understand what these 3000 lines of ARM
    assembly do in the lowlevel_init routine of U-Boot. What a mess ...
  
* I2C
  - a couple more devices 
  - the current model does not support the Linux driver sent to
    mailine. This is because the irq status handling is way too
    simplistic, or even broken. Anyone has some spare cycles for it ?
  
* Watchdog 
  - new model.  
  - not complete but reset under U-Boot and reboot under Linux now
    work so I think it is time to send the model upstream.
  - needs an upstream sponsor 
  
* Network 
  - new model of the ftgmac100 device
  - the ring buffer handling is imperfect and it does not support
    U-Boot (a pity) but we need feedback else this is going to bit rot
    for another 6 months
  - NSCI fake backend

For future work, please see the wiki : 

   https://github.com/openbmc/qemu/wiki

Cheers,

C.


Andrew Jeffery (1):
  wdt: aspeed: Fix failed reboot due to timer miscalculation

Cédric Le Goater (36):
  m25p80: add support for the mx66l1g45g
  aspeed: QOMify the CPU object and attach it to the SoC
  aspeed: attach the second SPI controller object to the SoC
  aspeed: extend the board configuration with flash models
  aspeed: add support for the romulus-bmc board
  aspeed: add a memory region for SRAM
  aspeed: add the definitions for the AST2400 A1 SoC
  aspeed: change SoC revision of the palmetto-bmc machine
  aspeed/scu: fix SCU region size
  aspeed/smc: improve segment register support
  aspeed/smc: get the number of flash modules from hw strapping
  aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines
  aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper
  aspeed/smc: autostrap CE0/1 configuration
  aspeed/smc: handle SPI flash Command mode
  aspeed/smc: add tests for Command mode
  aspeed/smc: unfold the AspeedSMCController array
  aspeed/smc: add a 'sdram_base' property
  aspeed/smc: add support for DMAs
  aspeed/smc: handle dummy bytes when doing fast reads
  aspeed/smc: adjust the size of the register region
  aspeed: use first SPI flash as a boot ROM
  block: add a model option for MTD devices
  aspeed/smc: use flash model option
  aspeed/sdmc: rework the locking register of the memory controller
  aspeed/sdmc: fake a few more registers to let DRAM calibration run
  hw/misc: add a TMP42{1,2,3} device model
  aspeed: add a temp sensor device on I2C bus 3
  aspeed: add a rtc device on I2C bus 0
  aspeed: add a watchdog controller
  wdt: aspeed: use scu to get clock freq
  net: add FTGMAC100 support
  net/ftgmac100: add a 'aspeed' property
  ast2400: add a FTGMAC100 nic
  slirp: add a fake NCSI backend
  target-arm: Add VBAR support to ARM1176 CPUs

Joel Stanley (1):
  wdt: Add Aspeed watchdog device model

 blockdev.c                       |  13 +
 default-configs/arm-softmmu.mak  |   2 +
 hw/arm/aspeed.c                  | 108 ++++-
 hw/arm/aspeed_soc.c              | 162 ++++++-
 hw/block/m25p80.c                |   1 +
 hw/misc/Makefile.objs            |   1 +
 hw/misc/aspeed_scu.c             |  18 +-
 hw/misc/aspeed_sdmc.c            | 219 +++++++++-
 hw/misc/tmp421.c                 | 400 +++++++++++++++++
 hw/net/Makefile.objs             |   1 +
 hw/net/ftgmac100.c               | 916 +++++++++++++++++++++++++++++++++++++++
 hw/ssi/aspeed_smc.c              | 660 ++++++++++++++++++++++++----
 hw/watchdog/Makefile.objs        |   1 +
 hw/watchdog/wdt_aspeed.c         | 223 ++++++++++
 include/hw/arm/aspeed_soc.h      |   8 +-
 include/hw/misc/aspeed_scu.h     |   2 +
 include/hw/misc/aspeed_sdmc.h    |   3 +-
 include/hw/net/ftgmac100.h       |  64 +++
 include/hw/ssi/aspeed_smc.h      |   8 +-
 include/hw/watchdog/wdt_aspeed.h |  43 ++
 include/net/eth.h                |   1 +
 include/sysemu/blockdev.h        |   1 +
 qemu-options.hx                  |   4 +-
 slirp/Makefile.objs              |   2 +-
 slirp/ncsi-pkt.h                 | 394 +++++++++++++++++
 slirp/ncsi.c                     |  95 ++++
 slirp/slirp.c                    |   4 +
 slirp/slirp.h                    |   3 +
 target-arm/cpu.c                 |   2 +
 target-arm/cpu.h                 |   1 +
 target-arm/helper.c              |  18 +-
 tests/m25p80-test.c              |  86 ++++
 32 files changed, 3334 insertions(+), 130 deletions(-)
 create mode 100644 hw/misc/tmp421.c
 create mode 100644 hw/net/ftgmac100.c
 create mode 100644 hw/watchdog/wdt_aspeed.c
 create mode 100644 include/hw/net/ftgmac100.h
 create mode 100644 include/hw/watchdog/wdt_aspeed.h
 create mode 100644 slirp/ncsi-pkt.h
 create mode 100644 slirp/ncsi.c

-- 
2.7.4

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

* [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-21 10:31   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC Cédric Le Goater
                   ` (36 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/block/m25p80.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index d29ff4cb4f4b..e3c1166ea6e3 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -203,6 +203,7 @@ static const FlashPartInfo known_devices[] = {
     { INFO("mx25l25655e", 0xc22619,      0,  64 << 10, 512, 0) },
     { INFO("mx66u51235f", 0xc2253a,      0,  64 << 10, 1024, ER_4K | ER_32K) },
     { INFO("mx66u1g45g",  0xc2253b,      0,  64 << 10, 2048, ER_4K | ER_32K) },
+    { INFO("mx66l1g45g",  0xc2201b,      0,  64 << 10, 2048, ER_4K | ER_32K) },
 
     /* Micron */
     { INFO("n25q032a11",  0x20bb16,      0,  64 << 10,  64, ER_4K) },
-- 
2.7.4

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

* [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
  2016-11-18 14:21 ` [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-21 10:59   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 03/38] aspeed: attach the second SPI controller object " Cédric Le Goater
                   ` (35 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c         | 17 ++++++++++++++---
 include/hw/arm/aspeed_soc.h |  2 +-
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index e14f5c217eab..db145e201451 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -87,9 +87,13 @@ static void aspeed_soc_init(Object *obj)
 {
     AspeedSoCState *s = ASPEED_SOC(obj);
     AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
+    char *cpu_typename;
     int i;
 
-    s->cpu = cpu_arm_init(sc->info->cpu_model);
+    cpu_typename = g_strdup_printf("%s-" TYPE_ARM_CPU, sc->info->cpu_model);
+    object_initialize(&s->cpu, sizeof(s->cpu), cpu_typename);
+    object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
+    g_free(cpu_typename);
 
     object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
     object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
@@ -146,6 +150,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion_overlap(get_system_memory(),
                                         ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
 
+    /* CPU */
+    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
     /* VIC */
     object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
     if (err) {
@@ -154,9 +165,9 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
     }
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
-                       qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
+                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
-                       qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
+                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
 
     /* Timer */
     object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 5406b498d7ef..6f1b679c97b1 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -27,7 +27,7 @@ typedef struct AspeedSoCState {
     DeviceState parent;
 
     /*< public >*/
-    ARMCPU *cpu;
+    ARMCPU cpu;
     MemoryRegion iomem;
     AspeedVICState vic;
     AspeedTimerCtrlState timerctrl;
-- 
2.7.4

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

* [PATCH qemu 03/38] aspeed: attach the second SPI controller object to the SoC
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
  2016-11-18 14:21 ` [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g Cédric Le Goater
  2016-11-18 14:21 ` [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21 11:03   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 04/38] aspeed: extend the board configuration with flash models Cédric Le Goater
                   ` (34 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index db145e201451..bbbbfd13862c 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -124,7 +124,7 @@ static void aspeed_soc_init(Object *obj)
     for (i = 0; i < sc->info->spis_num; i++) {
         object_initialize(&s->spi[i], sizeof(s->spi[i]),
                           sc->info->spi_typename[i]);
-        object_property_add_child(obj, "spi", OBJECT(&s->spi[i]), NULL);
+        object_property_add_child(obj, "spi[*]", OBJECT(&s->spi[i]), NULL);
         qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
     }
 
-- 
2.7.4

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

* [PATCH qemu 04/38] aspeed: extend the board configuration with flash models
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (2 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 03/38] aspeed: attach the second SPI controller object " Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-21 11:07   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board Cédric Le Goater
                   ` (33 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

Future machine will use different flash models for the FMC and the SPI
controllers.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index c7206fda6d85..159d562e8912 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -34,6 +34,8 @@ typedef struct AspeedBoardState {
 typedef struct AspeedBoardConfig {
     const char *soc_name;
     uint32_t hw_strap1;
+    const char *fmc_model;
+    const char *spi_model;
 } AspeedBoardConfig;
 
 enum {
@@ -65,8 +67,18 @@ enum {
         ~SCU_HW_STRAP_2ND_BOOT_WDT)
 
 static const AspeedBoardConfig aspeed_boards[] = {
-    [PALMETTO_BMC] = { "ast2400-a0", PALMETTO_BMC_HW_STRAP1 },
-    [AST2500_EVB]  = { "ast2500-a1", AST2500_EVB_HW_STRAP1 },
+    [PALMETTO_BMC] = {
+        .soc_name  = "ast2400-a0",
+        .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
+        .fmc_model = "n25q256a",
+        .spi_model = "mx25l25635e",
+    },
+    [AST2500_EVB]  = {
+        .soc_name  = "ast2500-a1",
+        .hw_strap1 = AST2500_EVB_HW_STRAP1,
+        .fmc_model = "n25q256a",
+        .spi_model = "mx25l25635e",
+    },
 };
 
 static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
@@ -128,8 +140,8 @@ static void aspeed_board_init(MachineState *machine,
     object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
                                    &error_abort);
 
-    aspeed_board_init_flashes(&bmc->soc.fmc, "n25q256a", &error_abort);
-    aspeed_board_init_flashes(&bmc->soc.spi[0], "mx25l25635e", &error_abort);
+    aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
+    aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);
 
     aspeed_board_binfo.kernel_filename = machine->kernel_filename;
     aspeed_board_binfo.initrd_filename = machine->initrd_filename;
-- 
2.7.4

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

* [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (3 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 04/38] aspeed: extend the board configuration with flash models Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-21 12:18   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 06/38] aspeed: add a memory region for SRAM Cédric Le Goater
                   ` (32 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

The Romulus machine is an OpenPOWER system with an AST2500 SoC for
the BMC and a POWER9 chip for the host. It does not make much
difference for qemu a part from the fact that the FMC controller has
two SPI flash module slaves.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 159d562e8912..aea73f79d92c 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -41,8 +41,10 @@ typedef struct AspeedBoardConfig {
 enum {
     PALMETTO_BMC,
     AST2500_EVB,
+    ROMULUS_BMC,
 };
 
+/* 0x120CE416 */
 #define PALMETTO_BMC_HW_STRAP1 (                                        \
         SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) |               \
         SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
@@ -56,6 +58,7 @@ enum {
         SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) |                       \
         SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
 
+/* 0xF100C2E6 */
 #define AST2500_EVB_HW_STRAP1 ((                                        \
         AST2500_HW_STRAP1_DEFAULTS |                                    \
         SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
@@ -66,6 +69,17 @@ enum {
         SCU_HW_STRAP_MAC0_RGMII) &                                      \
         ~SCU_HW_STRAP_2ND_BOOT_WDT)
 
+/* 0xF10AE216 */
+#define ROMULUS_BMC_HW_STRAP1 (                                     \
+        AST2500_HW_STRAP1_DEFAULTS |                                    \
+        SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
+        SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE |                        \
+        SCU_AST2500_HW_STRAP_UART_DEBUG |                               \
+        SCU_AST2500_HW_STRAP_DDR4_ENABLE |                              \
+        SCU_AST2500_HW_STRAP_ACPI_ENABLE |                              \
+        SCU_HW_STRAP_SPI_WIDTH |                                        \
+        SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN))
+
 static const AspeedBoardConfig aspeed_boards[] = {
     [PALMETTO_BMC] = {
         .soc_name  = "ast2400-a0",
@@ -79,6 +93,12 @@ static const AspeedBoardConfig aspeed_boards[] = {
         .fmc_model = "n25q256a",
         .spi_model = "mx25l25635e",
     },
+    [ROMULUS_BMC]  = {
+        .soc_name  = "ast2500-a1",
+        .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
+        .fmc_model = "n25q256a",
+        .spi_model = "mx66l1g45g",
+    },
 };
 
 static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
@@ -200,10 +220,35 @@ static const TypeInfo ast2500_evb_type = {
     .class_init = ast2500_evb_class_init,
 };
 
+static void romulus_bmc_init(MachineState *machine)
+{
+    aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]);
+}
+
+static void romulus_bmc_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "OpenPOWER Romulus BMC (ARM1176)";
+    mc->init = romulus_bmc_init;
+    mc->max_cpus = 1;
+    mc->no_sdcard = 1;
+    mc->no_floppy = 1;
+    mc->no_cdrom = 1;
+    mc->no_parallel = 1;
+}
+
+static const TypeInfo romulus_bmc_type = {
+    .name = MACHINE_TYPE_NAME("romulus-bmc"),
+    .parent = TYPE_MACHINE,
+    .class_init = romulus_bmc_class_init,
+};
+
 static void aspeed_machine_init(void)
 {
     type_register_static(&palmetto_bmc_type);
     type_register_static(&ast2500_evb_type);
+    type_register_static(&romulus_bmc_type);
 }
 
 type_init(aspeed_machine_init)
-- 
2.7.4

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

* [PATCH qemu 06/38] aspeed: add a memory region for SRAM
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (4 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-21 12:21   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 07/38] aspeed: add the definitions for the AST2400 A1 SoC Cédric Le Goater
                   ` (31 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

The size of the SRAM depends on the SoC model, so use a per-soc
definition when creating the region.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c         | 52 +++++++++++++++++++++++++++++++++++++--------
 include/hw/arm/aspeed_soc.h |  2 ++
 2 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index bbbbfd13862c..387b712d8fd5 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -29,6 +29,7 @@
 #define ASPEED_SOC_VIC_BASE         0x1E6C0000
 #define ASPEED_SOC_SDMC_BASE        0x1E6E0000
 #define ASPEED_SOC_SCU_BASE         0x1E6E2000
+#define ASPEED_SOC_SRAM_BASE        0x1E720000
 #define ASPEED_SOC_TIMER_BASE       0x1E782000
 #define ASPEED_SOC_I2C_BASE         0x1E78A000
 
@@ -47,15 +48,37 @@ static const char *aspeed_soc_ast2500_typenames[] = {
     "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
 
 static const AspeedSoCInfo aspeed_socs[] = {
-    { "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE,
-      1, aspeed_soc_ast2400_spi_bases,
-      "aspeed.smc.fmc", aspeed_soc_ast2400_typenames },
-    { "ast2400",    "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE,
-      1, aspeed_soc_ast2400_spi_bases,
-     "aspeed.smc.fmc", aspeed_soc_ast2400_typenames },
-    { "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE,
-      2, aspeed_soc_ast2500_spi_bases,
-      "aspeed.smc.ast2500-fmc", aspeed_soc_ast2500_typenames },
+    {
+        .name         = "ast2400-a0",
+        .cpu_model    = "arm926",
+        .silicon_rev  = AST2400_A0_SILICON_REV,
+        .sdram_base   = AST2400_SDRAM_BASE,
+        .sram_size    = 0x8000,
+        .spis_num     = 1,
+        .spi_bases    = aspeed_soc_ast2400_spi_bases,
+        .fmc_typename = "aspeed.smc.fmc",
+        .spi_typename = aspeed_soc_ast2400_typenames,
+    }, {
+        .name         = "ast2400",
+        .cpu_model    = "arm926",
+        .silicon_rev  = AST2400_A0_SILICON_REV,
+        .sdram_base   = AST2400_SDRAM_BASE,
+        .sram_size    = 0x8000,
+        .spis_num     = 1,
+        .spi_bases    = aspeed_soc_ast2400_spi_bases,
+        .fmc_typename = "aspeed.smc.fmc",
+        .spi_typename = aspeed_soc_ast2400_typenames,
+    }, {
+        .name         = "ast2500-a1",
+        .cpu_model    = "arm1176",
+        .silicon_rev  = AST2500_A1_SILICON_REV,
+        .sdram_base   = AST2500_SDRAM_BASE,
+        .sram_size    = 0x9000,
+        .spis_num     = 2,
+        .spi_bases    = aspeed_soc_ast2500_spi_bases,
+        .fmc_typename = "aspeed.smc.ast2500-fmc",
+        .spi_typename = aspeed_soc_ast2500_typenames,
+    },
 };
 
 /*
@@ -157,6 +180,17 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    /* SRAM */
+    memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
+                           sc->info->sram_size, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    vmstate_register_ram_global(&s->sram);
+    memory_region_add_subregion(get_system_memory(), ASPEED_SOC_SRAM_BASE,
+                                &s->sram);
+
     /* VIC */
     object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
     if (err) {
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 6f1b679c97b1..1ab5deaa0813 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -29,6 +29,7 @@ typedef struct AspeedSoCState {
     /*< public >*/
     ARMCPU cpu;
     MemoryRegion iomem;
+    MemoryRegion sram;
     AspeedVICState vic;
     AspeedTimerCtrlState timerctrl;
     AspeedI2CState i2c;
@@ -46,6 +47,7 @@ typedef struct AspeedSoCInfo {
     const char *cpu_model;
     uint32_t silicon_rev;
     hwaddr sdram_base;
+    uint64_t sram_size;
     int spis_num;
     const hwaddr *spi_bases;
     const char *fmc_typename;
-- 
2.7.4

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

* [PATCH qemu 07/38] aspeed: add the definitions for the AST2400 A1 SoC
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (5 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 06/38] aspeed: add a memory region for SRAM Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-21 12:50   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 08/38] aspeed: change SoC revision of the palmetto-bmc machine Cédric Le Goater
                   ` (30 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

There is not much differences with the A0 revision a part from the DDR
calibration.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c          | 10 ++++++++++
 hw/misc/aspeed_scu.c         |  2 ++
 hw/misc/aspeed_sdmc.c        |  3 +++
 include/hw/misc/aspeed_scu.h |  1 +
 4 files changed, 16 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 387b712d8fd5..503efe0f5f77 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -59,6 +59,16 @@ static const AspeedSoCInfo aspeed_socs[] = {
         .fmc_typename = "aspeed.smc.fmc",
         .spi_typename = aspeed_soc_ast2400_typenames,
     }, {
+        .name         = "ast2400-a1",
+        .cpu_model    = "arm926",
+        .silicon_rev  = AST2400_A1_SILICON_REV,
+        .sdram_base   = AST2400_SDRAM_BASE,
+        .sram_size    = 0x8000,
+        .spis_num     = 1,
+        .spi_bases    = aspeed_soc_ast2400_spi_bases,
+        .fmc_typename = "aspeed.smc.fmc",
+        .spi_typename = aspeed_soc_ast2400_typenames,
+    }, {
         .name         = "ast2400",
         .cpu_model    = "arm926",
         .silicon_rev  = AST2400_A0_SILICON_REV,
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index b1f3e6f6b87a..34e86385d837 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -231,6 +231,7 @@ static void aspeed_scu_reset(DeviceState *dev)
 
     switch (s->silicon_rev) {
     case AST2400_A0_SILICON_REV:
+    case AST2400_A1_SILICON_REV:
         reset = ast2400_a0_resets;
         break;
     case AST2500_A0_SILICON_REV:
@@ -249,6 +250,7 @@ static void aspeed_scu_reset(DeviceState *dev)
 
 static uint32_t aspeed_silicon_revs[] = {
     AST2400_A0_SILICON_REV,
+    AST2400_A1_SILICON_REV,
     AST2500_A0_SILICON_REV,
     AST2500_A1_SILICON_REV,
 };
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 8830dc084c38..5f3ac0b6f608 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -119,6 +119,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
         /* Make sure readonly bits are kept */
         switch (s->silicon_rev) {
         case AST2400_A0_SILICON_REV:
+        case AST2400_A1_SILICON_REV:
             data &= ~ASPEED_SDMC_READONLY_MASK;
             break;
         case AST2500_A0_SILICON_REV:
@@ -193,6 +194,7 @@ static void aspeed_sdmc_reset(DeviceState *dev)
     /* Set ram size bit and defaults values */
     switch (s->silicon_rev) {
     case AST2400_A0_SILICON_REV:
+    case AST2400_A1_SILICON_REV:
         s->regs[R_CONF] |=
             ASPEED_SDMC_VGA_COMPAT |
             ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
@@ -224,6 +226,7 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
 
     switch (s->silicon_rev) {
     case AST2400_A0_SILICON_REV:
+    case AST2400_A1_SILICON_REV:
         s->ram_bits = ast2400_rambits(s);
         break;
     case AST2500_A0_SILICON_REV:
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index 14ffc43de809..bd4ac013f997 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -32,6 +32,7 @@ typedef struct AspeedSCUState {
 } AspeedSCUState;
 
 #define AST2400_A0_SILICON_REV   0x02000303U
+#define AST2400_A1_SILICON_REV   0x02010303U
 #define AST2500_A0_SILICON_REV   0x04000303U
 #define AST2500_A1_SILICON_REV   0x04010303U
 
-- 
2.7.4

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

* [PATCH qemu 08/38] aspeed: change SoC revision of the palmetto-bmc machine
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (6 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 07/38] aspeed: add the definitions for the AST2400 A1 SoC Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-21 13:16   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 09/38] aspeed/scu: fix SCU region size Cédric Le Goater
                   ` (29 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

The palmetto BMC machine uses a AST2400 revision A1 SoC.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index aea73f79d92c..5e35d4562de0 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -82,7 +82,7 @@ enum {
 
 static const AspeedBoardConfig aspeed_boards[] = {
     [PALMETTO_BMC] = {
-        .soc_name  = "ast2400-a0",
+        .soc_name  = "ast2400-a1",
         .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
         .fmc_model = "n25q256a",
         .spi_model = "mx25l25635e",
-- 
2.7.4

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

* [PATCH qemu 09/38] aspeed/scu: fix SCU region size
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (7 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 08/38] aspeed: change SoC revision of the palmetto-bmc machine Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-21 12:54   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 10/38] aspeed/smc: improve segment register support Cédric Le Goater
                   ` (28 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/misc/aspeed_scu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 34e86385d837..95022d3607ad 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -86,7 +86,7 @@
 #define BMC_DEV_ID           TO_REG(0x1A4)
 
 #define PROT_KEY_UNLOCK 0x1688A8A8
-#define SCU_IO_REGION_SIZE 0x20000
+#define SCU_IO_REGION_SIZE 0x1000
 
 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
      [SYS_RST_CTRL]    = 0xFFCFFEDCU,
-- 
2.7.4

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

* [PATCH qemu 10/38] aspeed/smc: improve segment register support
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (8 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 09/38] aspeed/scu: fix SCU region size Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-18 14:21 ` [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping Cédric Le Goater
                   ` (27 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

The HW does not enforce all the rules in the specs and allows a few
"curious" setups like zero size segments and overlaps. So change the
model to be in sync but keep the warnings which are always interesting
for debug.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 6e8403ebc246..78f5aed53247 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -253,7 +253,8 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Tried to change CS0 start address to 0x%"
                       HWADDR_PRIx "\n", s->ctrl->name, seg.addr);
-        return;
+        seg.addr = s->ctrl->flash_window_base;
+        new = aspeed_smc_segment_to_reg(&seg);
     }
 
     /*
@@ -267,8 +268,10 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
         s->ctrl->segments[cs].size) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Tried to change CS%d end address to 0x%"
-                      HWADDR_PRIx "\n", s->ctrl->name, cs, seg.addr);
-        return;
+                      HWADDR_PRIx "\n", s->ctrl->name, cs, seg.addr + seg.size);
+        seg.size = s->ctrl->segments[cs].addr + s->ctrl->segments[cs].size -
+            seg.addr;
+        new = aspeed_smc_segment_to_reg(&seg);
     }
 
     /* Keep the segment in the overall flash window */
@@ -281,16 +284,14 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
     }
 
     /* Check start address vs. alignment */
-    if (seg.addr % seg.size) {
+    if (seg.size && !QEMU_IS_ALIGNED(seg.addr, seg.size)) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: new segment for CS%d is not "
                       "aligned : [ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
                       s->ctrl->name, cs, seg.addr, seg.addr + seg.size);
     }
 
-    /* And segments should not overlap */
-    if (aspeed_smc_flash_overlap(s, &seg, cs)) {
-        return;
-    }
+    /* And segments should not overlap (in the specs) */
+    aspeed_smc_flash_overlap(s, &seg, cs);
 
     /* All should be fine now to move the region */
     memory_region_transaction_begin();
-- 
2.7.4

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

* [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (9 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 10/38] aspeed/smc: improve segment register support Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-21 13:13   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 12/38] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
                   ` (26 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

If the second watchdog is activated, a second flash module is
available. It should be of the same model.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 503efe0f5f77..fcf029f8c1c2 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -170,12 +170,30 @@ static void aspeed_soc_init(Object *obj)
                               "ram-size", &error_abort);
 }
 
+static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
+{
+    Error *err = NULL;
+    uint32_t hw_strap1;
+
+    hw_strap1 = object_property_get_int(OBJECT(&s->scu), "hw-strap1", errp);
+    if (err) {
+        error_propagate(errp, err);
+        return -1;
+    }
+
+    /*
+     * If the second watchdog is activated, then we have two chips.
+     */
+    return hw_strap1 & SCU_HW_STRAP_2ND_BOOT_WDT ? 2 : 1;
+}
+
 static void aspeed_soc_realize(DeviceState *dev, Error **errp)
 {
     int i;
     AspeedSoCState *s = ASPEED_SOC(dev);
     AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
     Error *err = NULL, *local_err = NULL;
+    int fmc_num_cs;
 
     /* IO space */
     memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
@@ -251,7 +269,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
                        qdev_get_gpio_in(DEVICE(&s->vic), 12));
 
     /* FMC */
-    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
+    fmc_num_cs = aspeed_fmc_get_cs(s, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
     object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
     error_propagate(&err, local_err);
     if (err) {
-- 
2.7.4

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

* [PATCH qemu 12/38] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (10 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-21 13:20   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper Cédric Le Goater
                   ` (25 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

Change the routines prototype to use a 'AspeedSMCFlash *' instead of
'AspeedSMCState *'. The result will help in making future changes
clearer.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c         | 37 ++++++++++++++++++++++---------------
 include/hw/ssi/aspeed_smc.h |  2 +-
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 78f5aed53247..91cdc0bf1ac7 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -328,19 +328,30 @@ static const MemoryRegionOps aspeed_smc_flash_default_ops = {
     },
 };
 
-static inline int aspeed_smc_flash_mode(const AspeedSMCState *s, int cs)
+static inline int aspeed_smc_flash_mode(const AspeedSMCFlash *fl)
 {
-    return s->regs[s->r_ctrl0 + cs] & CTRL_CMD_MODE_MASK;
+    AspeedSMCState *s = fl->controller;
+
+    return s->regs[s->r_ctrl0 + fl->id] & CTRL_CMD_MODE_MASK;
 }
 
-static inline bool aspeed_smc_is_usermode(const AspeedSMCState *s, int cs)
+static inline bool aspeed_smc_is_usermode(const AspeedSMCFlash *fl)
 {
-    return aspeed_smc_flash_mode(s, cs) == CTRL_USERMODE;
+    return aspeed_smc_flash_mode(fl) == CTRL_USERMODE;
 }
 
-static inline bool aspeed_smc_is_writable(const AspeedSMCState *s, int cs)
+static inline bool aspeed_smc_is_ce_stop_active(const AspeedSMCFlash *fl)
 {
-    return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + cs));
+    AspeedSMCState *s = fl->controller;
+
+    return s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE;
+}
+
+static inline bool aspeed_smc_is_writable(const AspeedSMCFlash *fl)
+{
+    AspeedSMCState *s = fl->controller;
+
+    return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + fl->id));
 }
 
 static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
@@ -350,7 +361,7 @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
     uint64_t ret = 0;
     int i;
 
-    if (aspeed_smc_is_usermode(s, fl->id)) {
+    if (aspeed_smc_is_usermode(fl)) {
         for (i = 0; i < size; i++) {
             ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
         }
@@ -370,13 +381,13 @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
     const AspeedSMCState *s = fl->controller;
     int i;
 
-    if (!aspeed_smc_is_writable(s, fl->id)) {
+    if (!aspeed_smc_is_writable(fl)) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: flash is not writable at 0x%"
                       HWADDR_PRIx "\n", __func__, addr);
         return;
     }
 
-    if (!aspeed_smc_is_usermode(s, fl->id)) {
+    if (!aspeed_smc_is_usermode(fl)) {
         qemu_log_mask(LOG_UNIMP, "%s: usermode not implemented\n",
                       __func__);
         return;
@@ -397,17 +408,13 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
     },
 };
 
-static bool aspeed_smc_is_ce_stop_active(const AspeedSMCState *s, int cs)
-{
-    return s->regs[s->r_ctrl0 + cs] & CTRL_CE_STOP_ACTIVE;
-}
-
 static void aspeed_smc_update_cs(const AspeedSMCState *s)
 {
     int i;
 
     for (i = 0; i < s->num_cs; ++i) {
-        qemu_set_irq(s->cs_lines[i], aspeed_smc_is_ce_stop_active(s, i));
+        qemu_set_irq(s->cs_lines[i],
+                     aspeed_smc_is_ce_stop_active(&s->flashes[i]));
     }
 }
 
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index bdfbcc0ffa7d..c64954f6103f 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -47,7 +47,7 @@ typedef struct AspeedSMCController {
 } AspeedSMCController;
 
 typedef struct AspeedSMCFlash {
-    const struct AspeedSMCState *controller;
+    struct AspeedSMCState *controller;
 
     uint8_t id;
     uint32_t size;
-- 
2.7.4

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

* [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (11 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 12/38] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-21 13:36   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 14/38] aspeed/smc: autostrap CE0/1 configuration Cédric Le Goater
                   ` (24 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

aspeed_smc_update_cs() was uselessly looping on all CS to update their
status.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 91cdc0bf1ac7..1c6c5089f265 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -408,14 +408,10 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
     },
 };
 
-static void aspeed_smc_update_cs(const AspeedSMCState *s)
+static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
 {
-    int i;
-
-    for (i = 0; i < s->num_cs; ++i) {
-        qemu_set_irq(s->cs_lines[i],
-                     aspeed_smc_is_ce_stop_active(&s->flashes[i]));
-    }
+    AspeedSMCState *s = fl->controller;
+    qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
 }
 
 static void aspeed_smc_reset(DeviceState *d)
@@ -431,6 +427,7 @@ static void aspeed_smc_reset(DeviceState *d)
     /* Unselect all slaves */
     for (i = 0; i < s->num_cs; ++i) {
         s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
+        qemu_set_irq(s->cs_lines[i], true);
     }
 
     /* setup default segment register values for all */
@@ -438,8 +435,6 @@ static void aspeed_smc_reset(DeviceState *d)
         s->regs[R_SEG_ADDR0 + i] =
             aspeed_smc_segment_to_reg(&s->ctrl->segments[i]);
     }
-
-    aspeed_smc_update_cs(s);
 }
 
 static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
@@ -489,8 +484,9 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
         addr == s->r_ce_ctrl) {
         s->regs[addr] = value;
     } else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
+        int cs = addr - s->r_ctrl0;
         s->regs[addr] = value;
-        aspeed_smc_update_cs(s);
+        aspeed_smc_flash_update_cs(&s->flashes[cs]);
     } else if (addr >= R_SEG_ADDR0 &&
                addr < R_SEG_ADDR0 + s->ctrl->max_slaves) {
         int cs = addr - R_SEG_ADDR0;
-- 
2.7.4

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

* [PATCH qemu 14/38] aspeed/smc: autostrap CE0/1 configuration
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (12 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-25  3:07   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 15/38] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
                   ` (23 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

HW autodetect type and size of the first and second flash modules of
the FMC controller.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 1c6c5089f265..72a44150b0a1 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -39,11 +39,14 @@
 #define   CONF_ENABLE_W2       18
 #define   CONF_ENABLE_W1       17
 #define   CONF_ENABLE_W0       16
-#define   CONF_FLASH_TYPE4     9
-#define   CONF_FLASH_TYPE3     7
-#define   CONF_FLASH_TYPE2     5
-#define   CONF_FLASH_TYPE1     3
-#define   CONF_FLASH_TYPE0     1
+#define   CONF_FLASH_TYPE4     8
+#define   CONF_FLASH_TYPE3     6
+#define   CONF_FLASH_TYPE2     4
+#define   CONF_FLASH_TYPE1     2
+#define   CONF_FLASH_TYPE0     0
+#define      CONF_FLASH_TYPE_NOR   0x0
+#define      CONF_FLASH_TYPE_NAND  0x1
+#define      CONF_FLASH_TYPE_SPI   0x2
 
 /* CE Control Register */
 #define R_CE_CTRL            (0x04 / 4)
@@ -435,6 +438,19 @@ static void aspeed_smc_reset(DeviceState *d)
         s->regs[R_SEG_ADDR0 + i] =
             aspeed_smc_segment_to_reg(&s->ctrl->segments[i]);
     }
+
+    /* CE0 and CE1 HW strapping for FMC controllers : SPI flash type
+     * and 4BYTE mode
+     */
+    if (s->ctrl->segments == aspeed_segments_fmc ||
+        s->ctrl->segments == aspeed_segments_ast2500_fmc) {
+        s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0);
+        s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1);
+
+        /* We should be able to detect the flash size in some ways. */
+        s->regs[s->r_ce_ctrl] |= (1 << (CTRL_EXTENDED0));
+        s->regs[s->r_ce_ctrl] |= (1 << (CTRL_EXTENDED1));
+    }
 }
 
 static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
-- 
2.7.4

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

* [PATCH qemu 15/38] aspeed/smc: handle SPI flash Command mode
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (13 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 14/38] aspeed/smc: autostrap CE0/1 configuration Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-25  4:23   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 16/38] aspeed/smc: add tests for " Cédric Le Goater
                   ` (22 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

The Aspeed SMC controllers have a mode (Command mode) in which
accesses to the flash content are no different than doing MMIOs. The
controller generates all the necessary commands to load (or store)
data in memory.

However, accesses are restricted to the segment window assigned the
the flash module by the controller. This window is defined by the
Segment Address Register.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 162 insertions(+), 12 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 72a44150b0a1..eec087199a22 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -69,6 +69,7 @@
 #define R_CTRL0           (0x10 / 4)
 #define   CTRL_CMD_SHIFT           16
 #define   CTRL_CMD_MASK            0xff
+#define   CTRL_AST2400_SPI_4BYTE   (1 << 13)
 #define   CTRL_CE_STOP_ACTIVE      (1 << 2)
 #define   CTRL_CMD_MODE_MASK       0x3
 #define     CTRL_READMODE          0x0
@@ -135,6 +136,16 @@
 #define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
 #define ASPEED_SOC_SPI2_FLASH_BASE  0x38000000
 
+/* Flash opcodes. */
+#define SPI_OP_READ       0x03    /* Read data bytes (low frequency) */
+#define SPI_OP_WRDI       0x04    /* Write disable */
+#define SPI_OP_RDSR       0x05    /* Read status register */
+#define SPI_OP_WREN       0x06    /* Write enable */
+
+/* Used for Macronix and Winbond flashes. */
+#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
+#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
+
 /*
  * Default segments mapping addresses and size for each slave per
  * controller. These can be changed when board is initialized with the
@@ -357,6 +368,98 @@ static inline bool aspeed_smc_is_writable(const AspeedSMCFlash *fl)
     return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + fl->id));
 }
 
+static inline int aspeed_smc_flash_cmd(const AspeedSMCFlash *fl)
+{
+    AspeedSMCState *s = fl->controller;
+    int cmd = (s->regs[s->r_ctrl0 + fl->id] >> CTRL_CMD_SHIFT) & CTRL_CMD_MASK;
+
+    /* This is the default value for read mode. In other modes, the
+     * command should be defined */
+    if (aspeed_smc_flash_mode(fl) == CTRL_READMODE) {
+        cmd = SPI_OP_READ;
+    }
+
+    if (!cmd) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: no command defined for mode %d\n",
+                      __func__, aspeed_smc_flash_mode(fl));
+    }
+
+    return cmd;
+}
+
+static inline int aspeed_smc_flash_is_4byte(const AspeedSMCFlash *fl)
+{
+    AspeedSMCState *s = fl->controller;
+
+    if (s->ctrl->segments == aspeed_segments_spi) {
+        return s->regs[s->r_ctrl0] & CTRL_AST2400_SPI_4BYTE;
+    } else {
+        return s->regs[s->r_ce_ctrl] & (1 << (CTRL_EXTENDED0 + fl->id));
+    }
+}
+
+static void aspeed_smc_flash_select(const AspeedSMCFlash *fl)
+{
+    AspeedSMCState *s = fl->controller;
+
+    s->regs[s->r_ctrl0 + fl->id] &= ~CTRL_CE_STOP_ACTIVE;
+    qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
+}
+
+static void aspeed_smc_flash_unselect(const AspeedSMCFlash *fl)
+{
+    AspeedSMCState *s = fl->controller;
+
+    s->regs[s->r_ctrl0 + fl->id] |= CTRL_CE_STOP_ACTIVE;
+    qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
+}
+
+static uint32_t aspeed_smc_check_segment_addr(AspeedSMCFlash *fl, uint32_t addr)
+{
+    AspeedSMCState *s = fl->controller;
+    AspeedSegments seg;
+
+    aspeed_smc_reg_to_segment(s->regs[R_SEG_ADDR0 + fl->id], &seg);
+    if ((addr & (seg.size - 1)) != addr) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: invalid address 0x%08x for CS%d segment : "
+                      "[ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
+                      s->ctrl->name, addr, fl->id, seg.addr,
+                      seg.addr + seg.size);
+    }
+
+    addr &= seg.size - 1;
+    return addr;
+}
+
+static void aspeed_smc_flash_setup_read(AspeedSMCFlash *fl, uint32_t addr)
+{
+    AspeedSMCState *s = fl->controller;
+    uint8_t cmd = aspeed_smc_flash_cmd(fl);
+
+    /*
+     * To be checked: I am not sure the Aspeed SPI controller needs to
+     * enable writes when running in READ/FREAD command mode
+     */
+
+    /* access can not exceed CS segment */
+    addr = aspeed_smc_check_segment_addr(fl, addr);
+
+    /* TODO: do we have to send 4BYTE each time ? */
+    if (aspeed_smc_flash_is_4byte(fl)) {
+        ssi_transfer(s->spi, SPI_OP_EN4B);
+    }
+
+    ssi_transfer(s->spi, cmd);
+
+    if (aspeed_smc_flash_is_4byte(fl)) {
+        ssi_transfer(s->spi, (addr >> 24) & 0xff);
+    }
+    ssi_transfer(s->spi, (addr >> 16) & 0xff);
+    ssi_transfer(s->spi, (addr >> 8) & 0xff);
+    ssi_transfer(s->spi, (addr & 0xff));
+}
+
 static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
 {
     AspeedSMCFlash *fl = opaque;
@@ -364,19 +467,55 @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
     uint64_t ret = 0;
     int i;
 
-    if (aspeed_smc_is_usermode(fl)) {
+    switch (aspeed_smc_flash_mode(fl)) {
+    case CTRL_USERMODE:
         for (i = 0; i < size; i++) {
             ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
         }
-    } else {
-        qemu_log_mask(LOG_UNIMP, "%s: usermode not implemented\n",
-                      __func__);
-        ret = -1;
+        break;
+    case CTRL_READMODE:
+    case CTRL_FREADMODE:
+        aspeed_smc_flash_select(fl);
+        aspeed_smc_flash_setup_read(fl, addr);
+
+        for (i = 0; i < size; i++) {
+            ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
+        }
+
+        aspeed_smc_flash_unselect(fl);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid flash mode %d\n",
+                      __func__, aspeed_smc_flash_mode(fl));
     }
 
     return ret;
 }
 
+static void aspeed_smc_flash_setup_write(AspeedSMCFlash *fl, uint32_t addr)
+{
+    AspeedSMCState *s = fl->controller;
+    uint8_t cmd = aspeed_smc_flash_cmd(fl);
+
+    /* Flash access can not exceed CS segment */
+    addr = aspeed_smc_check_segment_addr(fl, addr);
+
+    /* TODO: do we have to send 4BYTE each time ? */
+    if (aspeed_smc_flash_is_4byte(fl)) {
+        ssi_transfer(s->spi, SPI_OP_EN4B);
+    }
+
+    ssi_transfer(s->spi, SPI_OP_WREN);
+    ssi_transfer(s->spi, cmd);
+
+    if (aspeed_smc_flash_is_4byte(fl)) {
+        ssi_transfer(s->spi, (addr >> 24) & 0xff);
+    }
+    ssi_transfer(s->spi, (addr >> 16) & 0xff);
+    ssi_transfer(s->spi, (addr >> 8) & 0xff);
+    ssi_transfer(s->spi, (addr & 0xff));
+}
+
 static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
                            unsigned size)
 {
@@ -390,14 +529,25 @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
         return;
     }
 
-    if (!aspeed_smc_is_usermode(fl)) {
-        qemu_log_mask(LOG_UNIMP, "%s: usermode not implemented\n",
-                      __func__);
-        return;
-    }
+    switch (aspeed_smc_flash_mode(fl)) {
+    case CTRL_USERMODE:
+        for (i = 0; i < size; i++) {
+            ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
+        }
+        break;
+    case CTRL_WRITEMODE:
+        aspeed_smc_flash_select(fl);
+        aspeed_smc_flash_setup_write(fl, addr);
+
+        for (i = 0; i < size; i++) {
+            ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
+        }
 
-    for (i = 0; i < size; i++) {
-        ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
+        aspeed_smc_flash_unselect(fl);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid flash mode %d\n",
+                      __func__, aspeed_smc_flash_mode(fl));
     }
 }
 
-- 
2.7.4

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

* [PATCH qemu 16/38] aspeed/smc: add tests for Command mode
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (14 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 15/38] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-25  4:30   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 17/38] aspeed/smc: unfold the AspeedSMCController array Cédric Le Goater
                   ` (21 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

0005 tests add a read_page_mem test

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 tests/m25p80-test.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/tests/m25p80-test.c b/tests/m25p80-test.c
index cb7ec81f1a6d..3d449bd194a9 100644
--- a/tests/m25p80-test.c
+++ b/tests/m25p80-test.c
@@ -36,6 +36,9 @@
 #define   CRTL_EXTENDED0       0  /* 32 bit addressing for SPI */
 #define R_CTRL0             0x10
 #define   CTRL_CE_STOP_ACTIVE  (1 << 2)
+#define   CTRL_READMODE        0x0
+#define   CTRL_FREADMODE       0x1
+#define   CTRL_WRITEMODE       0x2
 #define   CTRL_USERMODE        0x3
 
 #define ASPEED_FMC_BASE    0x1E620000
@@ -76,6 +79,22 @@ static void spi_conf(uint32_t value)
     writel(ASPEED_FMC_BASE + R_CONF, conf);
 }
 
+static void spi_ce_ctrl(uint32_t value)
+{
+    uint32_t conf = readl(ASPEED_FMC_BASE + R_CE_CTRL);
+
+    conf |= value;
+    writel(ASPEED_FMC_BASE + R_CE_CTRL, conf);
+}
+
+static void spi_ctrl_setmode(uint8_t mode, uint8_t cmd)
+{
+    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
+    ctrl &= ~(CTRL_USERMODE | 0xff << 16);
+    ctrl |= mode | (cmd << 16);
+    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
+}
+
 static void spi_ctrl_start_user(void)
 {
     uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
@@ -128,6 +147,18 @@ static void read_page(uint32_t addr, uint32_t *page)
     spi_ctrl_stop_user();
 }
 
+static void read_page_mem(uint32_t addr, uint32_t *page)
+{
+    int i;
+
+    /* move out USER mode to use direct reads from the AHB bus */
+    spi_ctrl_setmode(CTRL_READMODE, READ);
+
+    for (i = 0; i < PAGE_SIZE / 4; i++) {
+        page[i] = make_be32(readl(ASPEED_FLASH_BASE + addr + i * 4));
+    }
+}
+
 static void test_erase_sector(void)
 {
     uint32_t some_page_addr = 0x600 * PAGE_SIZE;
@@ -195,6 +226,7 @@ static void test_write_page(void)
 
     spi_ctrl_start_user();
     writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
+    writeb(ASPEED_FLASH_BASE, WREN);
     writeb(ASPEED_FLASH_BASE, PP);
     writel(ASPEED_FLASH_BASE, make_be32(my_page_addr));
 
@@ -217,6 +249,58 @@ static void test_write_page(void)
     }
 }
 
+static void test_read_page_mem(void)
+{
+    uint32_t my_page_addr = 0x14000 * PAGE_SIZE; /* beyond 16MB */
+    uint32_t some_page_addr = 0x15000 * PAGE_SIZE;
+    uint32_t page[PAGE_SIZE / 4];
+    int i;
+
+    /* Enable 4BYTE mode for flash. This is should be strapped by HW
+     * for CE0 anyhow.
+     */
+    spi_ce_ctrl(1 << CRTL_EXTENDED0);
+
+    /* Check what was written */
+    read_page_mem(my_page_addr, page);
+    for (i = 0; i < PAGE_SIZE / 4; i++) {
+        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
+    }
+
+    /* Check some other page. It should be full of 0xff */
+    read_page_mem(some_page_addr, page);
+    for (i = 0; i < PAGE_SIZE / 4; i++) {
+        g_assert_cmphex(page[i], ==, 0xffffffff);
+    }
+}
+
+static void test_write_page_mem(void)
+{
+    uint32_t my_page_addr = 0x15000 * PAGE_SIZE;
+    uint32_t page[PAGE_SIZE / 4];
+    int i;
+
+    /* Enable 4BYTE mode for flash. This is should be strapped by HW
+     * for CE0 anyhow.
+     */
+    spi_ce_ctrl(1 << CRTL_EXTENDED0);
+
+    /* move out USER mode to use direct writes to the AHB bus */
+    spi_ctrl_setmode(CTRL_WRITEMODE, PP);
+
+    for (i = 0; i < PAGE_SIZE / 4; i++) {
+        writel(ASPEED_FLASH_BASE + my_page_addr + i * 4,
+               make_be32(my_page_addr + i * 4));
+    }
+
+    /* Check what was written */
+    read_page_mem(my_page_addr, page);
+    for (i = 0; i < PAGE_SIZE / 4; i++) {
+        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
+    }
+}
+
+
 static char tmp_path[] = "/tmp/qtest.m25p80.XXXXXX";
 
 int main(int argc, char **argv)
@@ -242,6 +326,8 @@ int main(int argc, char **argv)
     qtest_add_func("/m25p80/erase_sector", test_erase_sector);
     qtest_add_func("/m25p80/erase_all",  test_erase_all);
     qtest_add_func("/m25p80/write_page", test_write_page);
+    qtest_add_func("/m25p80/read_page_mem", test_read_page_mem);
+    qtest_add_func("/m25p80/write_page_mem", test_write_page_mem);
 
     ret = g_test_run();
 
-- 
2.7.4

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

* [PATCH qemu 17/38] aspeed/smc: unfold the AspeedSMCController array
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (15 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 16/38] aspeed/smc: add tests for " Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-25  4:31   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 18/38] aspeed/smc: add a 'sdram_base' property Cédric Le Goater
                   ` (20 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

This is getting difficult to read. Also add a 'has_dma' field for each
controller type.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c         | 91 ++++++++++++++++++++++++++++++++++++---------
 include/hw/ssi/aspeed_smc.h |  1 +
 2 files changed, 74 insertions(+), 18 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index eec087199a22..8e7e3bd9e335 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -184,24 +184,79 @@ static const AspeedSegments aspeed_segments_ast2500_spi2[] = {
 };
 
 static const AspeedSMCController controllers[] = {
-    { "aspeed.smc.smc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
-      CONF_ENABLE_W0, 5, aspeed_segments_legacy,
-      ASPEED_SOC_SMC_FLASH_BASE, 0x6000000 },
-    { "aspeed.smc.fmc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
-      CONF_ENABLE_W0, 5, aspeed_segments_fmc,
-      ASPEED_SOC_FMC_FLASH_BASE, 0x10000000 },
-    { "aspeed.smc.spi", R_SPI_CONF, 0xff, R_SPI_CTRL0, R_SPI_TIMINGS,
-      SPI_CONF_ENABLE_W0, 1, aspeed_segments_spi,
-      ASPEED_SOC_SPI_FLASH_BASE, 0x10000000 },
-    { "aspeed.smc.ast2500-fmc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
-      CONF_ENABLE_W0, 3, aspeed_segments_ast2500_fmc,
-      ASPEED_SOC_FMC_FLASH_BASE, 0x10000000 },
-    { "aspeed.smc.ast2500-spi1", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
-      CONF_ENABLE_W0, 2, aspeed_segments_ast2500_spi1,
-      ASPEED_SOC_SPI_FLASH_BASE, 0x8000000 },
-    { "aspeed.smc.ast2500-spi2", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
-      CONF_ENABLE_W0, 2, aspeed_segments_ast2500_spi2,
-      ASPEED_SOC_SPI2_FLASH_BASE, 0x8000000 },
+    {
+        .name              = "aspeed.smc.smc",
+        .r_conf            = R_CONF,
+        .r_ce_ctrl         = R_CE_CTRL,
+        .r_ctrl0           = R_CTRL0,
+        .r_timings         = R_TIMINGS,
+        .conf_enable_w0    = CONF_ENABLE_W0,
+        .max_slaves        = 5,
+        .segments          = aspeed_segments_legacy,
+        .flash_window_base = ASPEED_SOC_SMC_FLASH_BASE,
+        .flash_window_size = 0x6000000,
+        .has_dma           = false,
+    }, {
+        .name              = "aspeed.smc.fmc",
+        .r_conf            = R_CONF,
+        .r_ce_ctrl         = R_CE_CTRL,
+        .r_ctrl0           = R_CTRL0,
+        .r_timings         = R_TIMINGS,
+        .conf_enable_w0    = CONF_ENABLE_W0,
+        .max_slaves        = 5,
+        .segments          = aspeed_segments_fmc,
+        .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
+        .flash_window_size = 0x10000000,
+        .has_dma           = true,
+    }, {
+        .name              = "aspeed.smc.spi",
+        .r_conf            = R_SPI_CONF,
+        .r_ce_ctrl         = 0xff,
+        .r_ctrl0           = R_SPI_CTRL0,
+        .r_timings         = R_SPI_TIMINGS,
+        .conf_enable_w0    = SPI_CONF_ENABLE_W0,
+        .max_slaves        = 1,
+        .segments          = aspeed_segments_spi,
+        .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
+        .flash_window_size = 0x10000000,
+        .has_dma           = false,
+    }, {
+        .name              = "aspeed.smc.ast2500-fmc",
+        .r_conf            = R_CONF,
+        .r_ce_ctrl         = R_CE_CTRL,
+        .r_ctrl0           = R_CTRL0,
+        .r_timings         = R_TIMINGS,
+        .conf_enable_w0    = CONF_ENABLE_W0,
+        .max_slaves        = 3,
+        .segments          = aspeed_segments_ast2500_fmc,
+        .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
+        .flash_window_size = 0x10000000,
+        .has_dma           = true,
+    }, {
+        .name              = "aspeed.smc.ast2500-spi1",
+        .r_conf            = R_CONF,
+        .r_ce_ctrl         = R_CE_CTRL,
+        .r_ctrl0           = R_CTRL0,
+        .r_timings         = R_TIMINGS,
+        .conf_enable_w0    = CONF_ENABLE_W0,
+        .max_slaves        = 2,
+        .segments          = aspeed_segments_ast2500_spi1,
+        .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
+        .flash_window_size = 0x8000000,
+        .has_dma           = false,
+    }, {
+        .name              = "aspeed.smc.ast2500-spi2",
+        .r_conf            = R_CONF,
+        .r_ce_ctrl         = R_CE_CTRL,
+        .r_ctrl0           = R_CTRL0,
+        .r_timings         = R_TIMINGS,
+        .conf_enable_w0    = CONF_ENABLE_W0,
+        .max_slaves        = 2,
+        .segments          = aspeed_segments_ast2500_spi2,
+        .flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE,
+        .flash_window_size = 0x8000000,
+        .has_dma           = false,
+    },
 };
 
 /*
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index c64954f6103f..39ee601940e8 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -44,6 +44,7 @@ typedef struct AspeedSMCController {
     const AspeedSegments *segments;
     hwaddr flash_window_base;
     uint32_t flash_window_size;
+    bool has_dma;
 } AspeedSMCController;
 
 typedef struct AspeedSMCFlash {
-- 
2.7.4

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

* [PATCH qemu 18/38] aspeed/smc: add a 'sdram_base' property
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (16 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 17/38] aspeed/smc: unfold the AspeedSMCController array Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-25  4:35   ` Andrew Jeffery
  2016-11-18 14:21 ` [PATCH qemu 19/38] aspeed/smc: add support for DMAs Cédric Le Goater
                   ` (19 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

The setting of the DRAM address of the DMA transaction depends on the
DRAM base address of the SoC, so we add a property to give this
information to the model.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c         | 7 +++++++
 hw/ssi/aspeed_smc.c         | 1 +
 include/hw/ssi/aspeed_smc.h | 3 +++
 3 files changed, 11 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index fcf029f8c1c2..24354f700115 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -276,6 +276,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
     }
 
     object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
+    object_property_set_int(OBJECT(&s->fmc), sc->info->sdram_base, "sdram-base",
+                            &local_err);
+    error_propagate(&err, local_err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
     object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
     error_propagate(&err, local_err);
     if (err) {
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 8e7e3bd9e335..24c78aa57537 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -819,6 +819,7 @@ static const VMStateDescription vmstate_aspeed_smc = {
 };
 
 static Property aspeed_smc_properties[] = {
+    DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0),
     DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1),
     DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index 39ee601940e8..88a904849801 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -96,6 +96,9 @@ typedef struct AspeedSMCState {
     uint8_t r_timings;
     uint8_t conf_enable_w0;
 
+    /* for DMA support */
+    uint64_t sdram_base;
+
     AspeedSMCFlash *flashes;
 } AspeedSMCState;
 
-- 
2.7.4

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

* [PATCH qemu 19/38] aspeed/smc: add support for DMAs
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (17 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 18/38] aspeed/smc: add a 'sdram_base' property Cédric Le Goater
@ 2016-11-18 14:21 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-18 14:22 ` [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
                   ` (18 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:21 UTC (permalink / raw)
  To: openbmc

Some of SMC controllers on the Aspeed SoCs support DMA to access the
flash modules. It can operate in a normal mode, to copy to or from the
flash module mapping window, or in a checksum calculation mode, to
evaluate the best clock settings for reads.

When DMA is enabled, a DMA request is built and passed on to a bottom
half to handle the memory transaction. The CPU is notified of the
completion with an IRQ if it was enabled.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 227 insertions(+), 7 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 24c78aa57537..9596ea94a3bc 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -26,8 +26,10 @@
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
+#include "qemu/coroutine.h"
 #include "include/qemu/error-report.h"
 #include "exec/address-spaces.h"
+#include "sysemu/dma.h"
 
 #include "hw/ssi/aspeed_smc.h"
 
@@ -104,10 +106,10 @@
 #define   DMA_CTRL_DELAY_SHIFT  8
 #define   DMA_CTRL_FREQ_MASK    0xf
 #define   DMA_CTRL_FREQ_SHIFT   4
-#define   DMA_CTRL_MODE         (1 << 3)
+#define   DMA_CTRL_CALIB        (1 << 3)
 #define   DMA_CTRL_CKSUM        (1 << 2)
-#define   DMA_CTRL_DIR          (1 << 1)
-#define   DMA_CTRL_EN           (1 << 0)
+#define   DMA_CTRL_WRITE        (1 << 1)
+#define   DMA_CTRL_ENABLE       (1 << 0)
 
 /* DMA Flash Side Address */
 #define R_DMA_FLASH_ADDR  (0x84 / 4)
@@ -136,6 +138,14 @@
 #define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
 #define ASPEED_SOC_SPI2_FLASH_BASE  0x38000000
 
+/*
+ * DMA address and size encoding
+ */
+#define DMA_LENGTH(x)           (((x) & ~0xFE000003))
+#define DMA_DRAM_ADDR(base, x)  (((x) & ~0xE0000003) | base)
+#define DMA_FLASH_ADDR(x)       (((x) & ~0xE0000003) | \
+                                 ASPEED_SOC_FMC_FLASH_BASE)
+
 /* Flash opcodes. */
 #define SPI_OP_READ       0x03    /* Read data bytes (low frequency) */
 #define SPI_OP_WRDI       0x04    /* Write disable */
@@ -629,9 +639,6 @@ static void aspeed_smc_reset(DeviceState *d)
 
     memset(s->regs, 0, sizeof s->regs);
 
-    /* Pretend DMA is done (u-boot initialization) */
-    s->regs[R_INTR_CTRL] = INTR_CTRL_DMA_STATUS;
-
     /* Unselect all slaves */
     for (i = 0; i < s->num_cs; ++i) {
         s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
@@ -675,6 +682,11 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
         addr == s->r_timings ||
         addr == s->r_ce_ctrl ||
         addr == R_INTR_CTRL ||
+        (s->ctrl->has_dma && addr == R_DMA_CTRL) ||
+        (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) ||
+        (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) ||
+        (s->ctrl->has_dma && addr == R_DMA_LEN) ||
+        (s->ctrl->has_dma && addr == R_DMA_CHECKSUM) ||
         (addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) ||
         (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)) {
         return s->regs[addr];
@@ -685,6 +697,202 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
     }
 }
 
+typedef struct AspeedDmaCo {
+    AspeedSMCState *s;
+    int len;
+    uint32_t flash_addr;
+    uint32_t dram_addr;
+    uint32_t checksum;
+    bool direction;
+} AspeedDmaCo;
+
+static void coroutine_fn aspeed_smc_dma_done(AspeedDmaCo *dmaco)
+{
+    AspeedSMCState *s = dmaco->s;
+
+    s->regs[R_INTR_CTRL] |= INTR_CTRL_DMA_STATUS;
+    if (s->regs[R_INTR_CTRL] & INTR_CTRL_DMA_EN) {
+        qemu_irq_raise(s->irq);
+    }
+}
+
+static bool coroutine_fn aspeed_smc_dma_update(AspeedDmaCo *dmaco)
+{
+    AspeedSMCState *s = dmaco->s;
+    bool ret;
+
+    /* add locking on R_DMA_CTRL ? */
+    if (s->regs[R_DMA_CTRL] & DMA_CTRL_ENABLE) {
+        s->regs[R_DMA_FLASH_ADDR] = dmaco->flash_addr;
+        s->regs[R_DMA_DRAM_ADDR] = dmaco->dram_addr;
+        s->regs[R_DMA_LEN] = dmaco->len - 4;
+        s->regs[R_DMA_CHECKSUM] = dmaco->checksum;
+        ret = true;
+    } else {
+        ret = false;
+    }
+
+    return ret;
+}
+
+/*
+ * Accumulate the result of the reads in a register. It will be used
+ * later to do timing calibration.
+ */
+static void coroutine_fn aspeed_smc_dma_checksum(void* opaque)
+{
+    AspeedDmaCo *dmaco = opaque;
+    uint32_t data;
+
+    while (dmaco->len) {
+        /* check for disablement and update register values */
+        if (!aspeed_smc_dma_update(dmaco)) {
+            goto out;
+        }
+
+        cpu_physical_memory_read(dmaco->flash_addr, &data, 4);
+        dmaco->checksum += data;
+        dmaco->flash_addr += 4;
+        dmaco->len -= 4;
+    }
+
+    aspeed_smc_dma_done(dmaco);
+out:
+    g_free(dmaco);
+}
+
+static void coroutine_fn aspeed_smc_dma_rw(void* opaque)
+{
+    AspeedDmaCo *dmaco = opaque;
+    uint32_t data;
+
+    while (dmaco->len) {
+        /* check for disablement and update register values */
+        if (!aspeed_smc_dma_update(dmaco)) {
+            goto out;
+        }
+
+        if (dmaco->direction) {
+            dma_memory_read(&address_space_memory, dmaco->dram_addr, &data, 4);
+            cpu_physical_memory_write(dmaco->flash_addr, &data, 4);
+        } else {
+            cpu_physical_memory_read(dmaco->flash_addr, &data, 4);
+            dma_memory_write(&address_space_memory, dmaco->dram_addr,
+                             &data, 4);
+        }
+
+        dmaco->flash_addr += 4;
+        dmaco->dram_addr += 4;
+        dmaco->len -= 4;
+    }
+
+    aspeed_smc_dma_done(dmaco);
+out:
+    g_free(dmaco);
+}
+
+
+static void aspeed_smc_dma_stop(AspeedSMCState *s)
+{
+    /*
+     * When the DMA is disabled, INTR_CTRL_DMA_STATUS=0 means the
+     * engine is idle
+     */
+    s->regs[R_INTR_CTRL] &= ~INTR_CTRL_DMA_STATUS;
+    s->regs[R_DMA_CHECKSUM] = 0x0;
+    s->regs[R_DMA_FLASH_ADDR] = 0;
+    s->regs[R_DMA_DRAM_ADDR] = 0;
+    s->regs[R_DMA_LEN] = 0;
+
+    /*
+     * Lower DMA irq even in any case. The IRQ control register could
+     * have been cleared before disabling the DMA.
+     */
+    qemu_irq_lower(s->irq);
+}
+
+typedef struct AspeedDmaRequest {
+    Coroutine *co;
+    QEMUBH *bh;
+} AspeedDmaRequest;
+
+static void aspeed_smc_dma_run(void *opaque)
+{
+    AspeedDmaRequest *dmareq = opaque;
+
+    qemu_coroutine_enter(dmareq->co);
+    qemu_bh_delete(dmareq->bh);
+    g_free(dmareq);
+}
+
+static void aspeed_smc_dma_schedule(Coroutine *co)
+{
+    AspeedDmaRequest *dmareq;
+
+    dmareq = g_new0(AspeedDmaRequest, 1);
+
+    dmareq->co = co;
+    dmareq->bh = qemu_bh_new(aspeed_smc_dma_run, dmareq);
+    qemu_bh_schedule(dmareq->bh);
+}
+
+static void aspeed_smc_dma_start(void *opaque)
+{
+    AspeedSMCState *s = opaque;
+    AspeedDmaCo *dmaco;
+    Coroutine *co;
+
+    /* freed in the coroutine */
+    dmaco = g_new0(AspeedDmaCo, 1);
+
+    /* A DMA transaction has a minimum of 4 bytes */
+    dmaco->len        = s->regs[R_DMA_LEN] + 4;
+    dmaco->flash_addr = s->regs[R_DMA_FLASH_ADDR];
+    dmaco->dram_addr  = s->regs[R_DMA_DRAM_ADDR];
+    dmaco->direction  = (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE);
+    dmaco->s          = s;
+
+    if (s->regs[R_DMA_CTRL] & DMA_CTRL_CKSUM) {
+        co = qemu_coroutine_create(aspeed_smc_dma_checksum, dmaco);
+    } else {
+        co = qemu_coroutine_create(aspeed_smc_dma_rw, dmaco);
+    }
+
+    aspeed_smc_dma_schedule(co);
+}
+
+/*
+ * This is to run one DMA at a time. When INTR_CTRL_DMA_STATUS becomes
+ * 1, the DMA has completed and a new DMA can start even if the result
+ * of the previous was not collected.
+ */
+static bool aspeed_smc_dma_in_progress(AspeedSMCState *s)
+{
+    bool ret = (s->regs[R_DMA_CTRL] & DMA_CTRL_ENABLE) &&
+        !(s->regs[R_INTR_CTRL] & INTR_CTRL_DMA_STATUS);
+    return ret;
+}
+
+static void aspeed_smc_dma_ctrl(AspeedSMCState *s, uint64_t dma_ctrl)
+{
+    if (dma_ctrl & DMA_CTRL_ENABLE) {
+        /* add locking on R_DMA_CTRL ? */
+        if (aspeed_smc_dma_in_progress(s)) {
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA in progress\n",
+                          __func__);
+            return;
+        }
+
+        s->regs[R_DMA_CTRL] = dma_ctrl;
+
+        aspeed_smc_dma_start(s);
+    } else {
+        s->regs[R_DMA_CTRL] = dma_ctrl;
+
+        aspeed_smc_dma_stop(s);
+    }
+}
+
 static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
                              unsigned int size)
 {
@@ -715,6 +923,16 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
         if (value != s->regs[R_SEG_ADDR0 + cs]) {
             aspeed_smc_flash_set_segment(s, cs, value);
         }
+    } else if (addr == R_INTR_CTRL) {
+        s->regs[addr] = value;
+    } else if (s->ctrl->has_dma && addr == R_DMA_CTRL) {
+        aspeed_smc_dma_ctrl(s, value);
+    } else if (s->ctrl->has_dma && addr == R_DMA_DRAM_ADDR) {
+        s->regs[addr] = DMA_DRAM_ADDR(s->sdram_base, value);
+    } else if (s->ctrl->has_dma && addr == R_DMA_FLASH_ADDR) {
+        s->regs[addr] = DMA_FLASH_ADDR(value);
+    } else if (s->ctrl->has_dma && addr == R_DMA_LEN) {
+        s->regs[addr] = DMA_LENGTH(value);
     } else {
         qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
                       __func__, addr);
@@ -747,6 +965,9 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
     s->r_timings = s->ctrl->r_timings;
     s->conf_enable_w0 = s->ctrl->conf_enable_w0;
 
+    /* DMA irq */
+    sysbus_init_irq(sbd, &s->irq);
+
     /* Enforce some real HW limits */
     if (s->num_cs > s->ctrl->max_slaves) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: num_cs cannot exceed: %d\n",
@@ -757,7 +978,6 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
     s->spi = ssi_create_bus(dev, "spi");
 
     /* Setup cs_lines for slaves */
-    sysbus_init_irq(sbd, &s->irq);
     s->cs_lines = g_new0(qemu_irq, s->num_cs);
     ssi_auto_connect_slaves(dev, s->cs_lines, s->spi);
 
-- 
2.7.4

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

* [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (18 preceding siblings ...)
  2016-11-18 14:21 ` [PATCH qemu 19/38] aspeed/smc: add support for DMAs Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-28  1:35   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region Cédric Le Goater
                   ` (17 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

When doing fast read, a certain amount of dummy bytes should be sent
before the read. This number is configurable in the controler CE0
Control Register and needs to be modeled using fake transfers the
flash module.

When the controller is configured for Command mode, the SPI command
used to do the read is stored in the CE0 control register but, in User
mode, we need to snoop into the flow of bytes to catch the command. It
should be the first byte after CS select.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c         | 57 ++++++++++++++++++++++++++++++++++++++-------
 include/hw/ssi/aspeed_smc.h |  1 +
 2 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 9596ea94a3bc..c0ae07ef8c96 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -71,7 +71,9 @@
 #define R_CTRL0           (0x10 / 4)
 #define   CTRL_CMD_SHIFT           16
 #define   CTRL_CMD_MASK            0xff
+#define   CTRL_DUMMY_HIGH_SHIFT    14
 #define   CTRL_AST2400_SPI_4BYTE   (1 << 13)
+#define   CTRL_DUMMY_LOW_SHIFT     6
 #define   CTRL_CE_STOP_ACTIVE      (1 << 2)
 #define   CTRL_CMD_MODE_MASK       0x3
 #define     CTRL_READMODE          0x0
@@ -151,6 +153,7 @@
 #define SPI_OP_WRDI       0x04    /* Write disable */
 #define SPI_OP_RDSR       0x05    /* Read status register */
 #define SPI_OP_WREN       0x06    /* Write enable */
+#define SPI_OP_READ_FAST  0x0b    /* Read data bytes (high frequency) */
 
 /* Used for Macronix and Winbond flashes. */
 #define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
@@ -510,6 +513,12 @@ static void aspeed_smc_flash_setup_read(AspeedSMCFlash *fl, uint32_t addr)
     /* access can not exceed CS segment */
     addr = aspeed_smc_check_segment_addr(fl, addr);
 
+    /*
+     * Remember command as we might need to send dummy bytes before
+     * reading data
+     */
+    fl->cmd = cmd;
+
     /* TODO: do we have to send 4BYTE each time ? */
     if (aspeed_smc_flash_is_4byte(fl)) {
         ssi_transfer(s->spi, SPI_OP_EN4B);
@@ -525,27 +534,49 @@ static void aspeed_smc_flash_setup_read(AspeedSMCFlash *fl, uint32_t addr)
     ssi_transfer(s->spi, (addr & 0xff));
 }
 
+static int aspeed_smc_flash_dummies(const AspeedSMCFlash *fl)
+{
+    AspeedSMCState *s = fl->controller;
+    uint32_t r_ctrl0 = s->regs[s->r_ctrl0 + fl->id];
+
+    return ((((r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1) << 2) |
+            ((r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3)) * 8;
+}
+
+static uint64_t aspeed_smc_flash_do_read(AspeedSMCFlash *fl, unsigned size)
+{
+    AspeedSMCState *s = fl->controller;
+    uint64_t ret = 0;
+    int i;
+
+    if (fl->cmd == SPI_OP_READ_FAST) {
+        for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
+            ssi_transfer(s->spi, 0x0);
+        }
+    }
+    fl->cmd = 0;
+
+    for (i = 0; i < size; i++) {
+        ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
+    }
+    return ret;
+}
+
 static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
 {
     AspeedSMCFlash *fl = opaque;
-    const AspeedSMCState *s = fl->controller;
     uint64_t ret = 0;
-    int i;
 
     switch (aspeed_smc_flash_mode(fl)) {
     case CTRL_USERMODE:
-        for (i = 0; i < size; i++) {
-            ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
-        }
+        ret = aspeed_smc_flash_do_read(fl, size);
         break;
     case CTRL_READMODE:
     case CTRL_FREADMODE:
         aspeed_smc_flash_select(fl);
         aspeed_smc_flash_setup_read(fl, addr);
 
-        for (i = 0; i < size; i++) {
-            ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
-        }
+        ret = aspeed_smc_flash_do_read(fl, size);
 
         aspeed_smc_flash_unselect(fl);
         break;
@@ -596,6 +627,15 @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
 
     switch (aspeed_smc_flash_mode(fl)) {
     case CTRL_USERMODE:
+        /*
+         * First write after chip select is the chip command. Remember
+         * it as we might need to send dummy bytes before reading
+         * data. It will be reseted when the chip is unselected.
+         */
+        if (!fl->cmd) {
+            fl->cmd = data & 0xff;
+        }
+
         for (i = 0; i < size; i++) {
             ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
         }
@@ -629,6 +669,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
 static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
 {
     AspeedSMCState *s = fl->controller;
+    fl->cmd = 0;
     qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
 }
 
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index 88a904849801..3ae0a369073d 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -52,6 +52,7 @@ typedef struct AspeedSMCFlash {
 
     uint8_t id;
     uint32_t size;
+    uint8_t cmd;
 
     MemoryRegion mmio;
     DeviceState *flash;
-- 
2.7.4

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

* [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (19 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-28  1:44   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 22/38] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
                   ` (16 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

The SPI controller of the AST2400 SoC does not support DMAs and
segment registers, hence it has less registers. So we can adjust the
size of the memory region holding the registers depending on the
controller type. We can also remove the guest_error logging which is
useless as the range of the region is strict enough.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c         | 23 ++++++++---------------
 include/hw/ssi/aspeed_smc.h |  1 +
 2 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index c0ae07ef8c96..7d7800d96271 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -135,6 +135,8 @@
 #define R_SPI_MISC_CTRL   (0x10 / 4)
 #define R_SPI_TIMINGS     (0x14 / 4)
 
+#define R_SPI_MAX         (0x20 / 4)
+
 #define ASPEED_SOC_SMC_FLASH_BASE   0x10000000
 #define ASPEED_SOC_FMC_FLASH_BASE   0x20000000
 #define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
@@ -221,6 +223,7 @@ static const AspeedSMCController controllers[] = {
         .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
         .flash_window_size = 0x10000000,
         .has_dma           = true,
+        .nregs             = ASPEED_SMC_R_MAX,
     }, {
         .name              = "aspeed.smc.spi",
         .r_conf            = R_SPI_CONF,
@@ -233,6 +236,7 @@ static const AspeedSMCController controllers[] = {
         .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
         .flash_window_size = 0x10000000,
         .has_dma           = false,
+        .nregs             = R_SPI_MAX,
     }, {
         .name              = "aspeed.smc.ast2500-fmc",
         .r_conf            = R_CONF,
@@ -245,6 +249,7 @@ static const AspeedSMCController controllers[] = {
         .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
         .flash_window_size = 0x10000000,
         .has_dma           = true,
+        .nregs             = ASPEED_SMC_R_MAX,
     }, {
         .name              = "aspeed.smc.ast2500-spi1",
         .r_conf            = R_CONF,
@@ -257,6 +262,7 @@ static const AspeedSMCController controllers[] = {
         .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
         .flash_window_size = 0x8000000,
         .has_dma           = false,
+        .nregs             = ASPEED_SMC_R_MAX,
     }, {
         .name              = "aspeed.smc.ast2500-spi2",
         .r_conf            = R_CONF,
@@ -269,6 +275,7 @@ static const AspeedSMCController controllers[] = {
         .flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE,
         .flash_window_size = 0x8000000,
         .has_dma           = false,
+        .nregs             = ASPEED_SMC_R_MAX,
     },
 };
 
@@ -712,13 +719,6 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
 
     addr >>= 2;
 
-    if (addr >= ARRAY_SIZE(s->regs)) {
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "%s: Out-of-bounds read at 0x%" HWADDR_PRIx "\n",
-                      __func__, addr);
-        return 0;
-    }
-
     if (addr == s->r_conf ||
         addr == s->r_timings ||
         addr == s->r_ce_ctrl ||
@@ -942,13 +942,6 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
 
     addr >>= 2;
 
-    if (addr >= ARRAY_SIZE(s->regs)) {
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "%s: Out-of-bounds write at 0x%" HWADDR_PRIx "\n",
-                      __func__, addr);
-        return;
-    }
-
     if (addr == s->r_conf ||
         addr == s->r_timings ||
         addr == s->r_ce_ctrl) {
@@ -1030,7 +1023,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
 
     /* The memory region for the controller registers */
     memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
-                          s->ctrl->name, ASPEED_SMC_R_MAX * 4);
+                          s->ctrl->name, s->ctrl->nregs * 4);
     sysbus_init_mmio(sbd, &s->mmio);
 
     /*
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
index 3ae0a369073d..91bad82e9c65 100644
--- a/include/hw/ssi/aspeed_smc.h
+++ b/include/hw/ssi/aspeed_smc.h
@@ -45,6 +45,7 @@ typedef struct AspeedSMCController {
     hwaddr flash_window_base;
     uint32_t flash_window_size;
     bool has_dma;
+    uint32_t nregs;
 } AspeedSMCController;
 
 typedef struct AspeedSMCFlash {
-- 
2.7.4

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

* [PATCH qemu 22/38] aspeed: use first SPI flash as a boot ROM
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (20 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-28  1:47   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 23/38] block: add a model option for MTD devices Cédric Le Goater
                   ` (15 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

Fill a ROM region with the flash content to support U-Boot. This is a
little hacky but until we can boot from a MMIO region, it seems
difficult to do anything else.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 5e35d4562de0..3e1781f30f55 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -20,6 +20,8 @@
 #include "qemu/log.h"
 #include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
+#include "hw/loader.h"
+#include "qemu/error-report.h"
 
 static struct arm_boot_info aspeed_board_binfo = {
     .board_id = -1, /* device-tree-only board */
@@ -101,6 +103,28 @@ static const AspeedBoardConfig aspeed_boards[] = {
     },
 };
 
+#define FIRMWARE_ADDR 0x0
+
+static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
+                           Error **errp)
+{
+    BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
+    uint8_t *storage;
+
+    if (rom_size > blk_getlength(blk)) {
+        rom_size = blk_getlength(blk);
+    }
+
+    storage = g_new0(uint8_t, rom_size);
+    if (blk_pread(blk, 0, storage, rom_size) < 0) {
+        error_setg(errp, "failed to read the initial flash content");
+        return;
+    }
+
+    rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
+    g_free(storage);
+}
+
 static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
                                       Error **errp)
 {
@@ -132,6 +156,7 @@ static void aspeed_board_init(MachineState *machine,
 {
     AspeedBoardState *bmc;
     AspeedSoCClass *sc;
+    DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
 
     bmc = g_new0(AspeedBoardState, 1);
     object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
@@ -163,6 +188,22 @@ static void aspeed_board_init(MachineState *machine,
     aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
     aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);
 
+    /* Install first FMC flash content as a boot rom. */
+    if (drive0) {
+        AspeedSMCFlash *fl = &bmc->soc.fmc.flashes[0];
+        MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+
+        /*
+         * create a ROM region using the default mapping window size of
+         * the flash module.
+         */
+        memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
+                               fl->size, &error_abort);
+        memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
+                                    boot_rom);
+        write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
+    }
+
     aspeed_board_binfo.kernel_filename = machine->kernel_filename;
     aspeed_board_binfo.initrd_filename = machine->initrd_filename;
     aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
-- 
2.7.4

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

* [PATCH qemu 23/38] block: add a model option for MTD devices
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (21 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 22/38] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:27   ` Joel Stanley
  2016-11-18 14:22 ` [PATCH qemu 24/38] aspeed/smc: use flash model option Cédric Le Goater
                   ` (14 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

This could be used to define the flash model to use on some boards
definitions.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 blockdev.c                | 13 +++++++++++++
 include/sysemu/blockdev.h |  1 +
 qemu-options.hx           |  4 +++-
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/blockdev.c b/blockdev.c
index 245e1e1d177a..fcea923edf02 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -742,6 +742,10 @@ QemuOptsList qemu_legacy_drive_opts = {
             .type = QEMU_OPT_STRING,
             .help = "pci address (virtio only)",
         },{
+            .name = "model",
+            .type = QEMU_OPT_STRING,
+            .help = "flash model (mtd only)",
+        },{
             .name = "serial",
             .type = QEMU_OPT_STRING,
             .help = "disk serial number",
@@ -790,6 +794,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     bool read_only = false;
     bool copy_on_read;
     const char *serial;
+    const char *model;
     const char *filename;
     Error *local_err = NULL;
     int i;
@@ -1030,6 +1035,13 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         g_free(new_id);
     }
 
+   /* Add virtio block device */
+    model = qemu_opt_get(legacy_opts, "model");
+    if (model && type != IF_MTD) {
+        error_report("model is not supported by this bus type");
+        goto fail;
+    }
+
     /* Add virtio block device */
     devaddr = qemu_opt_get(legacy_opts, "addr");
     if (devaddr && type != IF_VIRTIO) {
@@ -1102,6 +1114,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     dinfo->unit = unit_id;
     dinfo->devaddr = devaddr;
     dinfo->serial = g_strdup(serial);
+    dinfo->model = g_strdup(model);
 
     blk_set_legacy_dinfo(blk, dinfo);
 
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 16432f350805..10c66e5e86a4 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -39,6 +39,7 @@ struct DriveInfo {
     int cyls, heads, secs, trans;
     QemuOpts *opts;
     char *serial;
+    char *model;
     QTAILQ_ENTRY(DriveInfo) next;
 };
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 4a5b29f349f7..16add85bd0f5 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -517,7 +517,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive,
     "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
     "       [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
     "       [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
-    "       [,serial=s][,addr=A][,rerror=ignore|stop|report]\n"
+    "       [,serial=s][,model=m][,addr=A][,rerror=ignore|stop|report]\n"
     "       [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
     "       [,readonly=on|off][,copy-on-read=on|off]\n"
     "       [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n"
@@ -570,6 +570,8 @@ the format.  Can be used to specify format=raw to avoid interpreting
 an untrusted format header.
 @item serial=@var{serial}
 This option specifies the serial number to assign to the device.
+@item model=@var{model}
+This option specifies the model to use to create a flash device (if=mtd only).
 @item addr=@var{addr}
 Specify the controller's PCI address (if=virtio only).
 @item werror=@var{action},rerror=@var{action}
-- 
2.7.4

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

* [PATCH qemu 24/38] aspeed/smc: use flash model option
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (22 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 23/38] block: add a model option for MTD devices Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-18 14:22 ` [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller Cédric Le Goater
                   ` (13 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

so that we can change the flash model from the command line.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 3e1781f30f55..0108512b070d 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -135,6 +135,8 @@ static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
         DriveInfo *dinfo = drive_get_next(IF_MTD);
         qemu_irq cs_line;
 
+        flashtype = dinfo && dinfo->model ? dinfo->model : flashtype;
+
         /*
          * FIXME: check that we are not using a flash module exceeding
          * the controller segment size
-- 
2.7.4

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

* [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (23 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 24/38] aspeed/smc: use flash model option Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-28  1:55   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run Cédric Le Goater
                   ` (12 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

The lock register is unlocked with a write of a special value and
locked with a write of any other value. When unlocked, reads return
one and when locked a zero.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/misc/aspeed_sdmc.c         | 28 +++++++++++++++++++---------
 include/hw/misc/aspeed_sdmc.h |  1 +
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 5f3ac0b6f608..867caa2d64dc 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -83,17 +83,22 @@
 static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
 {
     AspeedSDMCState *s = ASPEED_SDMC(opaque);
+    uint64_t val = 0;
 
     addr >>= 2;
 
-    if (addr >= ARRAY_SIZE(s->regs)) {
+    switch (addr) {
+    case R_PROT:
+        val = s->unlocked;
+        break;
+    default:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
                       __func__, addr);
-        return 0;
+        break;
     }
 
-    return s->regs[addr];
+    return val;
 }
 
 static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
@@ -103,19 +108,18 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
 
     addr >>= 2;
 
-    if (addr >= ARRAY_SIZE(s->regs)) {
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
-                      __func__, addr);
+    if (addr == R_PROT) {
+        s->unlocked = (data == PROT_KEY_UNLOCK);
         return;
     }
 
-    if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) {
+    if (!s->unlocked) { /* TODO protect : MCR04 ∼ MCR7C */
         qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
         return;
     }
 
-    if (addr == R_CONF) {
+    switch (addr) {
+    case R_CONF:
         /* Make sure readonly bits are kept */
         switch (s->silicon_rev) {
         case AST2400_A0_SILICON_REV:
@@ -128,6 +132,12 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
         default:
             g_assert_not_reached();
         }
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
+                      __func__, addr << 2);
+        return;
     }
 
     s->regs[addr] = data;
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index 551c8afdf4be..a4415d9efc2f 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -28,6 +28,7 @@ typedef struct AspeedSDMCState {
     uint32_t ram_bits;
     uint64_t ram_size;
 
+    bool unlocked;
 } AspeedSDMCState;
 
 #endif /* ASPEED_SDMC_H */
-- 
2.7.4

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

* [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (24 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
  2016-11-28  2:02   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 27/38] hw/misc: add a TMP42{1,2,3} device model Cédric Le Goater
                   ` (11 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

It helps in understanding the DRAM calibration sequence which is all
written in assembly, and may be rewritten in C one day.

This provides support only for the AST2400 SoC (DDR3). AST2500 still
uses the SOC_SCRATCH1 to pretend DRAM was already initialized.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/misc/aspeed_scu.c          |   2 +-
 hw/misc/aspeed_sdmc.c         | 188 ++++++++++++++++++++++++++++++++++++++++++
 include/hw/misc/aspeed_sdmc.h |   2 +-
 3 files changed, 190 insertions(+), 2 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 95022d3607ad..b5efba9121b2 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -100,7 +100,7 @@ static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
      [PCI_CTRL2]       = 0x20001A03U,
      [PCI_CTRL3]       = 0x04000030U,
      [SYS_RST_STATUS]  = 0x00000001U,
-     [SOC_SCRATCH1]    = 0x000000C0U, /* SoC completed DRAM init */
+     [SOC_SCRATCH1]    = 0x00000000U,
      [MISC_CTRL2]      = 0x00000023U,
      [RNG_CTRL]        = 0x0000000EU,
      [PINMUX_CTRL2]    = 0x0000F000U,
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 867caa2d64dc..c71d18953c1c 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -80,6 +80,114 @@
      ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT |            \
      ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
 
+/* MCR08: Graphics Memory Protection Register */
+#define R_GRAPHIC_MEM_PROT              (0x8 / 4)
+
+/* MCR0C: Refresh Timing Register */
+#define R_REFRESH_TIMING                (0x0C / 4)
+
+/* MCR10: AC Timing Register #1 */
+#define R_AC_TIMING1                    (0x10 / 4)
+
+/* MCR14: AC Timing Register #2 */
+#define R_AC_TIMING2                    (0x14 / 4)
+
+/* MCR18: CK/DQS Delay Control Register */
+#define R_CQDQS_DELAY_CTRL              (0x18 / 4)
+
+/* MCR1C: MCLK to MCLK2X Calibration(CBR) Status Register */
+#define R_MCLK_CALIB_STATUS             (0x1C / 4)
+#define   MCLK2X_PHASE                      (0x96 << 16)
+
+/* MCR20: DQS Input Phase Calibration Control and Status */
+#define R_DQS_INPUT_CALIB_STATUS        (0x20 / 4)
+
+/* MCR24: ????  */
+#define R_MCR24                         (0x24 / 4)
+
+/* MCR28: Mode Setting Control Register */
+#define R_MODE_SETTING_CTRL             (0x28 / 4)
+
+/* MCR2C: MRS/EMRS2 Mode Setting Register */
+#define R_MRS_MODE_SETTING_CTRL         (0x2C / 4)
+
+/* MCR30: EMRS/EMRS3 Mode Setting Register */
+#define R_EMRS_MODE_SETTING_CTRL        (0x30 / 4)
+
+/* MCR34: Power Control Register */
+#define R_POWER_CTRL                    (0x34 / 4)
+
+/* MCR38: Page Miss Latency Mask Register */
+#define R_PAGE_MISS_MASK                (0x38 / 4)
+
+/* MCR40: Maximum Grant Length Register #1 */
+#define R_MAX_GRANT_LEN1                (0x40 / 4)
+
+/* MCR44: Maximum Grant Length Register #2 */
+#define R_MAX_GRANT_LEN2                (0x44 / 4)
+
+/* MCR48: Maximum Grant Length Register #3 */
+#define R_MAX_GRANT_LEN3                (0x48 / 4)
+
+/* MCR4C: Maximum Grant Length Register #4 */
+#define R_MAX_GRANT_LEN4                (0x4C / 4)
+
+/* MCR50: Interrupt Control/Status Register */
+#define R_IRQ_STATUS_CTRL               (0x50 / 4)
+
+/* MCR54: ECC Protection Address Range Register */
+#define R_ECC_PROTECT                   (0x54 / 4)
+
+/* MCR58: ????  */
+#define R_MCR58                         (0x58 / 4)
+
+/* MCR60: IO Buffer Mode Register */
+#define R_IO_BUFFER_MODE                (0x60 / 4)
+
+/* MCR64: DLL Control Register #1 */
+#define R_DLL_CTRL                      (0x64 / 4)
+
+/* MCR68: DLL Control Register #2 */
+#define R_DLL_CTRL2                     (0x68 / 4)
+
+/* MCR6C: DDR IO Impedance Calibration Control */
+#define R_DDR_IO_IMPEDANCE_CTRL         (0x6C / 4)
+
+/* MCR70: ECC Testing Control/Status Register */
+#define R_ECC_STATUS_CTRL               (0x70 / 4)
+#define   ECC_TEST_FINISH                  (1 << 12)
+
+/* MCR74: Testing Start Address and Length Register */
+#define R_START_ADDR_LEN                (0x74 / 4)
+
+/* MCR78: Testing Fail DQ Bit Register */
+#define R_FAIL_DQ                       (0x78 / 4)
+
+/* MCR7C: Test Initial Value Register */
+#define R_TEST_INIT_VALUE               (0x7C / 4)
+
+/* MCR80: DQ Input Delay Calibration Control #1 */
+#define R_DQ_DELAY_CALIB_CTRL1          (0x80 / 4)
+#define   DQ_DELAY_CALIB_COUNT_DONE        (1 << 31)
+
+/* MCR84: DQ Input Delay Calibration Control #2 */
+#define R_DQ_DELAY_CALIB_CTRL2          (0x84 / 4)
+
+/* MCR88: DQ Input Delay Calibration Control #3 */
+#define R_DQ_DELAY_CALIB_CTRL3          (0x88 / 4)
+
+/* MCR8C: CK Duty Counter Value */
+#define R_CK_DUTY_VALUE                 (0x8C / 4)
+
+/* MCR100: AST2000 Backward Compatible SCU Password */
+#define R_COMPAT_SCU_PASSWORD           (0x100 / 4)
+
+/* MCR120: AST2000 Backward Compatible SCU MPLL Parameter */
+#define R_COMPAT_SCU_MPLL               (0x120 / 4)
+
+/* MCR170: AST2000 Backward Compatible SCU Hardware Strapping Value */
+#define R_COMPAT_SCU_HW_STRAPPING       (0x170 / 4)
+
 static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
 {
     AspeedSDMCState *s = ASPEED_SDMC(opaque);
@@ -91,6 +199,48 @@ static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
     case R_PROT:
         val = s->unlocked;
         break;
+    case R_CONF:
+    case R_GRAPHIC_MEM_PROT:
+    case R_REFRESH_TIMING:
+    case R_AC_TIMING1:
+    case R_AC_TIMING2:
+    case R_CQDQS_DELAY_CTRL:
+    case R_MCLK_CALIB_STATUS:
+    case R_DQS_INPUT_CALIB_STATUS:
+    case R_MCR24:
+    case R_MODE_SETTING_CTRL:
+    case R_MRS_MODE_SETTING_CTRL:
+    case R_EMRS_MODE_SETTING_CTRL:
+    case R_POWER_CTRL:
+    case R_PAGE_MISS_MASK:
+    case R_MAX_GRANT_LEN1:
+    case R_MAX_GRANT_LEN2:
+    case R_MAX_GRANT_LEN3:
+    case R_MAX_GRANT_LEN4:
+    case R_IRQ_STATUS_CTRL:
+    case R_ECC_PROTECT:
+    case R_MCR58:
+    case R_IO_BUFFER_MODE:
+    case R_DLL_CTRL:
+    case R_DLL_CTRL2:
+    case R_DDR_IO_IMPEDANCE_CTRL:
+    case R_START_ADDR_LEN:
+    case R_FAIL_DQ:
+    case R_TEST_INIT_VALUE:
+    case R_DQ_DELAY_CALIB_CTRL2:
+    case R_DQ_DELAY_CALIB_CTRL3:
+    case R_CK_DUTY_VALUE:
+    case R_COMPAT_SCU_PASSWORD:
+    case R_COMPAT_SCU_MPLL:
+    case R_COMPAT_SCU_HW_STRAPPING:
+        val = s->regs[addr];
+        break;
+    case R_DQ_DELAY_CALIB_CTRL1:
+        val = s->regs[addr] | DQ_DELAY_CALIB_COUNT_DONE;
+        break;
+    case R_ECC_STATUS_CTRL:
+        val = s->regs[addr] | ECC_TEST_FINISH;
+        break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
@@ -133,6 +283,42 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
             g_assert_not_reached();
         }
         break;
+    case R_GRAPHIC_MEM_PROT:
+    case R_REFRESH_TIMING:
+    case R_AC_TIMING1:
+    case R_AC_TIMING2:
+    case R_CQDQS_DELAY_CTRL:
+    case R_MCLK_CALIB_STATUS:
+    case R_DQS_INPUT_CALIB_STATUS:
+    case R_MCR24:
+    case R_MODE_SETTING_CTRL:
+    case R_MRS_MODE_SETTING_CTRL:
+    case R_EMRS_MODE_SETTING_CTRL:
+    case R_POWER_CTRL:
+    case R_PAGE_MISS_MASK:
+    case R_MAX_GRANT_LEN1:
+    case R_MAX_GRANT_LEN2:
+    case R_MAX_GRANT_LEN3:
+    case R_MAX_GRANT_LEN4:
+    case R_IRQ_STATUS_CTRL:
+    case R_ECC_PROTECT:
+    case R_MCR58:
+    case R_IO_BUFFER_MODE:
+    case R_DLL_CTRL:
+    case R_DLL_CTRL2:
+    case R_DDR_IO_IMPEDANCE_CTRL:
+    case R_ECC_STATUS_CTRL:
+    case R_START_ADDR_LEN:
+    case R_FAIL_DQ:
+    case R_TEST_INIT_VALUE:
+    case R_DQ_DELAY_CALIB_CTRL1:
+    case R_DQ_DELAY_CALIB_CTRL2:
+    case R_DQ_DELAY_CALIB_CTRL3:
+    case R_CK_DUTY_VALUE:
+    case R_COMPAT_SCU_PASSWORD:
+    case R_COMPAT_SCU_MPLL:
+    case R_COMPAT_SCU_HW_STRAPPING:
+        break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
@@ -221,6 +407,8 @@ static void aspeed_sdmc_reset(DeviceState *dev)
     default:
         g_assert_not_reached();
     }
+
+    s->regs[R_MCLK_CALIB_STATUS] = MCLK2X_PHASE;
 }
 
 static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index a4415d9efc2f..e073a6c9419a 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -14,7 +14,7 @@
 #define TYPE_ASPEED_SDMC "aspeed.sdmc"
 #define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
 
-#define ASPEED_SDMC_NR_REGS (0x8 >> 2)
+#define ASPEED_SDMC_NR_REGS (0x174 >> 2)
 
 typedef struct AspeedSDMCState {
     /*< private >*/
-- 
2.7.4

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

* [PATCH qemu 27/38] hw/misc: add a TMP42{1,2,3} device model
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (25 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-18 14:22 ` [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3 Cédric Le Goater
                   ` (10 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

Largely inspired by the TMP105 temperature sensor, here is a model for
the TMP42{1,2,3} temperature sensors.

Specs can be found here :

	http://www.ti.com/lit/gpn/tmp421

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 default-configs/arm-softmmu.mak |   1 +
 hw/misc/Makefile.objs           |   1 +
 hw/misc/tmp421.c                | 400 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 402 insertions(+)
 create mode 100644 hw/misc/tmp421.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 6de3e16a3e11..e3ac9e0ec104 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -14,6 +14,7 @@ CONFIG_TWL92230=y
 CONFIG_TSC2005=y
 CONFIG_LM832X=y
 CONFIG_TMP105=y
+CONFIG_TMP421=y
 CONFIG_STELLARIS=y
 CONFIG_STELLARIS_INPUT=y
 CONFIG_STELLARIS_ENET=y
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 1a89615a6270..69610caa325d 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -1,6 +1,7 @@
 common-obj-$(CONFIG_APPLESMC) += applesmc.o
 common-obj-$(CONFIG_MAX111X) += max111x.o
 common-obj-$(CONFIG_TMP105) += tmp105.o
+common-obj-$(CONFIG_TMP421) += tmp421.o
 common-obj-$(CONFIG_ISA_DEBUG) += debugexit.o
 common-obj-$(CONFIG_SGA) += sga.o
 common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
diff --git a/hw/misc/tmp421.c b/hw/misc/tmp421.c
new file mode 100644
index 000000000000..0e310e0639e1
--- /dev/null
+++ b/hw/misc/tmp421.c
@@ -0,0 +1,400 @@
+/*
+ * Texas Instruments TMP421 temperature sensor.
+ *
+ * Copyright (c) 2016 IBM Corporation.
+ *
+ * Largely inspired by :
+ *
+ * Texas Instruments TMP105 temperature sensor.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * 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 or
+ * (at your option) version 3 of the License.
+ *
+ * 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 "hw/hw.h"
+#include "hw/i2c/i2c.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+
+/* Manufacturer / Device ID's */
+#define TMP421_MANUFACTURER_ID          0x55
+#define TMP421_DEVICE_ID                0x21
+#define TMP422_DEVICE_ID                0x22
+#define TMP423_DEVICE_ID                0x23
+
+typedef struct DeviceInfo {
+    int model;
+    const char *name;
+} DeviceInfo;
+
+static const DeviceInfo devices[] = {
+    { TMP421_DEVICE_ID, "tmp421" },
+    { TMP422_DEVICE_ID, "tmp422" },
+    { TMP423_DEVICE_ID, "tmp423" },
+};
+
+typedef struct TMP421State {
+    /*< private >*/
+    I2CSlave i2c;
+    /*< public >*/
+
+    int16_t temperature[4];
+
+    uint8_t status;
+    uint8_t config[2];
+    uint8_t rate;
+
+    uint8_t len;
+    uint8_t buf[2];
+    uint8_t pointer;
+
+} TMP421State;
+
+typedef struct TMP421Class {
+    I2CSlaveClass parent_class;
+    DeviceInfo *dev;
+} TMP421Class;
+
+#define TYPE_TMP421 "tmp421-generic"
+#define TMP421(obj) OBJECT_CHECK(TMP421State, (obj), TYPE_TMP421)
+
+#define TMP421_CLASS(klass) \
+     OBJECT_CLASS_CHECK(TMP421Class, (klass), TYPE_TMP421)
+#define TMP421_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(TMP421Class, (obj), TYPE_TMP421)
+
+/* the TMP421 registers */
+#define TMP421_STATUS_REG               0x08
+#define    TMP421_STATUS_BUSY             (1 << 7)
+#define TMP421_CONFIG_REG_1             0x09
+#define    TMP421_CONFIG_RANGE            (1 << 2)
+#define    TMP421_CONFIG_SHUTDOWN         (1 << 6)
+#define TMP421_CONFIG_REG_2             0x0A
+#define    TMP421_CONFIG_RC               (1 << 2)
+#define    TMP421_CONFIG_LEN              (1 << 3)
+#define    TMP421_CONFIG_REN              (1 << 4)
+#define    TMP421_CONFIG_REN2             (1 << 5)
+#define    TMP421_CONFIG_REN3             (1 << 6)
+
+#define TMP421_CONVERSION_RATE_REG      0x0B
+#define TMP421_ONE_SHOT                 0x0F
+
+#define TMP421_RESET                    0xFC
+#define TMP421_MANUFACTURER_ID_REG      0xFE
+#define TMP421_DEVICE_ID_REG            0xFF
+
+#define TMP421_TEMP_MSB0                0x00
+#define TMP421_TEMP_MSB1                0x01
+#define TMP421_TEMP_MSB2                0x02
+#define TMP421_TEMP_MSB3                0x03
+#define TMP421_TEMP_LSB0                0x10
+#define TMP421_TEMP_LSB1                0x11
+#define TMP421_TEMP_LSB2                0x12
+#define TMP421_TEMP_LSB3                0x13
+
+static const int32_t mins[2] = { -40000, -55000 };
+static const int32_t maxs[2] = { 127000, 150000 };
+
+static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name,
+                                   void *opaque, Error **errp)
+{
+    TMP421State *s = TMP421(obj);
+    bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE);
+    int offset = ext_range * 64 * 256;
+    int64_t value;
+    int tempid;
+
+    if (sscanf(name, "temperature%d", &tempid) != 1) {
+        error_setg(errp, "error reading %s: %m", name);
+        return;
+    }
+
+    if (tempid >= 4 || tempid < 0) {
+        error_setg(errp, "error reading %s", name);
+        return;
+    }
+
+    value = ((s->temperature[tempid] - offset) * 1000 + 128) / 256;
+
+    visit_type_int(v, name, &value, errp);
+}
+
+/* Units are 0.001 centigrades relative to 0 C.  s->temperature is 8.8
+ * fixed point, so units are 1/256 centigrades.  A simple ratio will do.
+ */
+static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name,
+                                   void *opaque, Error **errp)
+{
+    TMP421State *s = TMP421(obj);
+    Error *local_err = NULL;
+    int64_t temp;
+    bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE);
+    int offset = ext_range * 64 * 256;
+    int tempid;
+
+    visit_type_int(v, name, &temp, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (temp >= maxs[ext_range] || temp < mins[ext_range]) {
+        error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range",
+                   temp / 1000, temp % 1000);
+        return;
+    }
+
+    if (sscanf(name, "temperature%d", &tempid) != 1) {
+        error_setg(errp, "error reading %s: %m", name);
+        return;
+    }
+
+    if (tempid >= 4 || tempid < 0) {
+        error_setg(errp, "error reading %s", name);
+        return;
+    }
+
+    s->temperature[tempid] = (int16_t) ((temp * 256 - 128) / 1000) + offset;
+}
+
+static void tmp421_read(TMP421State *s)
+{
+    TMP421Class *sc = TMP421_GET_CLASS(s);
+
+    s->len = 0;
+
+    switch (s->pointer) {
+    case TMP421_MANUFACTURER_ID_REG:
+        s->buf[s->len++] = TMP421_MANUFACTURER_ID;
+        break;
+    case TMP421_DEVICE_ID_REG:
+        s->buf[s->len++] = sc->dev->model;
+        break;
+    case TMP421_CONFIG_REG_1:
+        s->buf[s->len++] = s->config[0];
+        break;
+    case TMP421_CONFIG_REG_2:
+        s->buf[s->len++] = s->config[1];
+        break;
+    case TMP421_CONVERSION_RATE_REG:
+        s->buf[s->len++] = s->rate;
+        break;
+    case TMP421_STATUS_REG:
+        s->buf[s->len++] = s->status;
+        break;
+
+        /* FIXME: check for channel enablement in config registers */
+    case TMP421_TEMP_MSB0:
+        s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 8);
+        s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0;
+        break;
+    case TMP421_TEMP_MSB1:
+        s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 8);
+        s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0;
+        break;
+    case TMP421_TEMP_MSB2:
+        s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 8);
+        s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0;
+        break;
+    case TMP421_TEMP_MSB3:
+        s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 8);
+        s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0;
+        break;
+    case TMP421_TEMP_LSB0:
+        s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0;
+        break;
+    case TMP421_TEMP_LSB1:
+        s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0;
+        break;
+    case TMP421_TEMP_LSB2:
+        s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0;
+        break;
+    case TMP421_TEMP_LSB3:
+        s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0;
+        break;
+    }
+}
+
+static void tmp421_reset(I2CSlave *i2c);
+
+static void tmp421_write(TMP421State *s)
+{
+    switch (s->pointer) {
+    case TMP421_CONVERSION_RATE_REG:
+        s->rate = s->buf[0];
+        break;
+    case TMP421_CONFIG_REG_1:
+        s->config[0] = s->buf[0];
+        break;
+    case TMP421_CONFIG_REG_2:
+        s->config[1] = s->buf[0];
+        break;
+    case TMP421_RESET:
+        tmp421_reset(I2C_SLAVE(s));
+        break;
+    }
+}
+
+static int tmp421_rx(I2CSlave *i2c)
+{
+    TMP421State *s = TMP421(i2c);
+
+    if (s->len < 2) {
+        return s->buf[s->len++];
+    } else {
+        return 0xff;
+    }
+}
+
+static int tmp421_tx(I2CSlave *i2c, uint8_t data)
+{
+    TMP421State *s = TMP421(i2c);
+
+    if (s->len == 0) {
+        /* first byte is the register pointer for a read or write
+         * operation */
+        s->pointer = data;
+        s->len++;
+    } else if (s->len == 1) {
+        /* second byte is the data to write. The device only supports
+         * one byte writes */
+        s->buf[0] = data;
+        tmp421_write(s);
+    }
+
+    return 0;
+}
+
+static void tmp421_event(I2CSlave *i2c, enum i2c_event event)
+{
+    TMP421State *s = TMP421(i2c);
+
+    if (event == I2C_START_RECV) {
+        tmp421_read(s);
+    }
+
+    s->len = 0;
+}
+
+static const VMStateDescription vmstate_tmp421 = {
+    .name = "TMP421",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(len, TMP421State),
+        VMSTATE_UINT8_ARRAY(buf, TMP421State, 2),
+        VMSTATE_UINT8(pointer, TMP421State),
+        VMSTATE_UINT8_ARRAY(config, TMP421State, 2),
+        VMSTATE_UINT8(status, TMP421State),
+        VMSTATE_UINT8(rate, TMP421State),
+        VMSTATE_INT16_ARRAY(temperature, TMP421State, 4),
+        VMSTATE_I2C_SLAVE(i2c, TMP421State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void tmp421_reset(I2CSlave *i2c)
+{
+    TMP421State *s = TMP421(i2c);
+    TMP421Class *sc = TMP421_GET_CLASS(s);
+
+    memset(s->temperature, 0, sizeof(s->temperature));
+    s->pointer = 0;
+
+    s->config[0] = 0; /* TMP421_CONFIG_RANGE */
+
+     /* resistance correction and channel enablement */
+    switch (sc->dev->model) {
+    case TMP421_DEVICE_ID:
+        s->config[1] = 0x1c;
+        break;
+    case TMP422_DEVICE_ID:
+        s->config[1] = 0x3c;
+        break;
+    case TMP423_DEVICE_ID:
+        s->config[1] = 0x7c;
+        break;
+    }
+
+    s->rate = 0x7;       /* 8Hz */
+    s->status = 0;
+}
+
+static int tmp421_init(I2CSlave *i2c)
+{
+    TMP421State *s = TMP421(i2c);
+
+    tmp421_reset(&s->i2c);
+
+    return 0;
+}
+
+static void tmp421_initfn(Object *obj)
+{
+    object_property_add(obj, "temperature0", "int",
+                        tmp421_get_temperature,
+                        tmp421_set_temperature, NULL, NULL, NULL);
+    object_property_add(obj, "temperature1", "int",
+                        tmp421_get_temperature,
+                        tmp421_set_temperature, NULL, NULL, NULL);
+    object_property_add(obj, "temperature2", "int",
+                        tmp421_get_temperature,
+                        tmp421_set_temperature, NULL, NULL, NULL);
+    object_property_add(obj, "temperature3", "int",
+                        tmp421_get_temperature,
+                        tmp421_set_temperature, NULL, NULL, NULL);
+}
+
+static void tmp421_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+    TMP421Class *sc = TMP421_CLASS(klass);
+
+    k->init = tmp421_init;
+    k->event = tmp421_event;
+    k->recv = tmp421_rx;
+    k->send = tmp421_tx;
+    dc->vmsd = &vmstate_tmp421;
+    sc->dev = (DeviceInfo *) data;
+}
+
+static const TypeInfo tmp421_info = {
+    .name          = TYPE_TMP421,
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(TMP421State),
+    .instance_init = tmp421_initfn,
+    .class_init    = tmp421_class_init,
+};
+
+static void tmp421_register_types(void)
+{
+    int i;
+
+    type_register_static(&tmp421_info);
+    for (i = 0; i < ARRAY_SIZE(devices); ++i) {
+        TypeInfo ti = {
+            .name       = devices[i].name,
+            .parent     = TYPE_TMP421,
+            .class_init = tmp421_class_init,
+            .class_data = (void *) &devices[i],
+        };
+        type_register(&ti);
+    }
+}
+
+type_init(tmp421_register_types)
-- 
2.7.4

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

* [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (26 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 27/38] hw/misc: add a TMP42{1,2,3} device model Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-22 16:57   ` Cédric Le Goater
  2016-11-18 14:22 ` [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0 Cédric Le Goater
                   ` (9 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

Temperatures can be changed from the monitor with :

	(qemu) qom-set /machine/unattached/device[2] temperature0 12000

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 24354f700115..2aa15d90cc31 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -268,6 +268,14 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
                        qdev_get_gpio_in(DEVICE(&s->vic), 12));
 
+    /* add a TMP423 temperature sensor */
+    dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&s->i2c), 2),
+                           "tmp423", 0x4c);
+    object_property_set_int(OBJECT(dev), 31000, "temperature0", &err);
+    object_property_set_int(OBJECT(dev), 28000, "temperature1", &err);
+    object_property_set_int(OBJECT(dev), 20000, "temperature2", &err);
+    object_property_set_int(OBJECT(dev), 110000, "temperature3", &err);
+
     /* FMC */
     fmc_num_cs = aspeed_fmc_get_cs(s, &err);
     if (err) {
-- 
2.7.4

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

* [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (27 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3 Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:27   ` Joel Stanley
                     ` (2 more replies)
  2016-11-18 14:22 ` [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model Cédric Le Goater
                   ` (8 subsequent siblings)
  37 siblings, 3 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

The palmetto platform has a ds3231 RTC device but not qemu. Let's use
a ds1338 instead which provides enough basic RTC features. Only alarms
will be missing

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 2aa15d90cc31..d2bc0ba2070d 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -276,6 +276,10 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
     object_property_set_int(OBJECT(dev), 20000, "temperature2", &err);
     object_property_set_int(OBJECT(dev), 110000, "temperature3", &err);
 
+    /* The palmetto platform expects a ds3231 RTC but a ds1338 is
+     * enough to provide basic RTC features. Alarms will be missing */
+    i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&s->i2c), 0), "ds1338", 0x68);
+
     /* FMC */
     fmc_num_cs = aspeed_fmc_get_cs(s, &err);
     if (err) {
-- 
2.7.4

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

* [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (28 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0 Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21 13:03   ` Cédric Le Goater
  2016-11-18 14:22 ` [PATCH qemu 31/38] aspeed: add a watchdog controller Cédric Le Goater
                   ` (7 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

From: Joel Stanley <joel@jms.id.au>

Signed-off-by: Joel Stanley <joel@jms.id.au>
[clg: fixed compile breakage
      fixed io region size
      added  watchdog_perform_action() on timer expiry ]
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/watchdog/Makefile.objs        |   1 +
 hw/watchdog/wdt_aspeed.c         | 194 +++++++++++++++++++++++++++++++++++++++
 include/hw/watchdog/wdt_aspeed.h |  41 +++++++++
 3 files changed, 236 insertions(+)
 create mode 100644 hw/watchdog/wdt_aspeed.c
 create mode 100644 include/hw/watchdog/wdt_aspeed.h

diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
index 72e3ffd93c59..9589bed63a3d 100644
--- a/hw/watchdog/Makefile.objs
+++ b/hw/watchdog/Makefile.objs
@@ -2,3 +2,4 @@ common-obj-y += watchdog.o
 common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
 common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
 common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
+common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
new file mode 100644
index 000000000000..29d9d7f91463
--- /dev/null
+++ b/hw/watchdog/wdt_aspeed.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2016 IBM Corporation
+ *
+ * This code is licensed under the GPL version 2 or later.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "sysemu/watchdog.h"
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "hw/watchdog/wdt_aspeed.h"
+
+#define WDT_IO_REGION_SIZE      0x1000
+
+#define WDT_STATUS              0x00
+#define WDT_RELOAD_VALUE        0x04
+#define WDT_RESTART             0x08
+#define WDT_CTRL                0x0C
+#define WDT_TIMEOUT_STATUS      0x10
+#define WDT_TIMEOUT_CLEAR       0x14
+#define WDT_RESET_WDITH         0x18
+
+#define WDT_RESTART_MAGIC       0x4755
+
+static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
+{
+    AspeedWDTState *s = ASPEED_WDT(opaque);
+
+    switch (offset) {
+    case WDT_STATUS:
+        return s->reg_status;
+    case WDT_RELOAD_VALUE:
+        return s->reg_reload_value;
+    case WDT_RESTART:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: read from write-only reg at offset 0x%"
+                      HWADDR_PRIx "\n", __func__, offset);
+        return 0;
+    case WDT_CTRL:
+        return s->reg_ctrl;
+    case WDT_TIMEOUT_STATUS:
+    case WDT_TIMEOUT_CLEAR:
+    case WDT_RESET_WDITH:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: uninmplemented read at offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+        return 0;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+        return 0;
+    }
+
+}
+
+static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
+                             unsigned size)
+{
+    AspeedWDTState *s = ASPEED_WDT(opaque);
+    bool en = data & BIT(0);
+
+    switch (offset) {
+    case WDT_STATUS:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: write to read-only reg at offset 0x%"
+                      HWADDR_PRIx "\n", __func__, offset);
+        break;
+    case WDT_RELOAD_VALUE:
+        s->reg_reload_value = data;
+        break;
+    case WDT_RESTART:
+        if ((data & 0xFFFF) == 0x4755) {
+            s->reg_status = s->reg_reload_value;
+
+            if (s->enabled) {
+                timer_mod(s->timer,
+                          qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+                          s->reg_reload_value * NANOSECONDS_PER_SECOND);
+            }
+        }
+        break;
+    case WDT_CTRL:
+        if (en && !s->enabled) {
+            s->enabled = true;
+            timer_mod(s->timer,
+                      qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+                      s->reg_reload_value * NANOSECONDS_PER_SECOND);
+        } else if (!en && s->enabled) {
+            s->enabled = false;
+            timer_del(s->timer);
+        }
+        break;
+    case WDT_TIMEOUT_STATUS:
+    case WDT_TIMEOUT_CLEAR:
+    case WDT_RESET_WDITH:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: uninmplemented write at offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
+                      __func__, offset);
+    }
+    return;
+}
+
+static WatchdogTimerModel model = {
+    .wdt_name = TYPE_ASPEED_WDT,
+    .wdt_description = "aspeed watchdog device",
+};
+
+static const VMStateDescription vmstate_aspeed_wdt = {
+    .name = "vmstate_aspeed_wdt",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_TIMER_PTR(timer, AspeedWDTState),
+        VMSTATE_BOOL(enabled, AspeedWDTState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const MemoryRegionOps aspeed_wdt_ops = {
+    .read = aspeed_wdt_read,
+    .write = aspeed_wdt_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .valid.unaligned = false,
+};
+
+static void aspeed_wdt_reset(DeviceState *dev)
+{
+    AspeedWDTState *s = ASPEED_WDT(dev);
+
+    s->reg_status = 0x3EF1480;
+    s->reg_reload_value = 0x03EF1480;
+    s->reg_restart = 0;
+    s->reg_ctrl = 0;
+
+    s->enabled = false;
+    timer_del(s->timer);
+}
+
+static void aspeed_wdt_timer_expired(void *dev)
+{
+    AspeedWDTState *s = ASPEED_WDT(dev);
+
+    qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
+    watchdog_perform_action();
+    timer_del(s->timer);
+}
+
+static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    AspeedWDTState *s = ASPEED_WDT(dev);
+
+    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired,
+                            dev);
+
+    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_wdt_ops, s,
+                          TYPE_ASPEED_WDT, WDT_IO_REGION_SIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = aspeed_wdt_realize;
+    dc->reset = aspeed_wdt_reset;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    dc->vmsd = &vmstate_aspeed_wdt;
+}
+
+static const TypeInfo aspeed_wdt_info = {
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .name  = TYPE_ASPEED_WDT,
+    .instance_size  = sizeof(AspeedWDTState),
+    .class_init = aspeed_wdt_class_init,
+};
+
+static void wdt_aspeed_register_types(void)
+{
+    watchdog_add_model(&model);
+    type_register_static(&aspeed_wdt_info);
+}
+
+type_init(wdt_aspeed_register_types)
diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
new file mode 100644
index 000000000000..dbf45ae968db
--- /dev/null
+++ b/include/hw/watchdog/wdt_aspeed.h
@@ -0,0 +1,41 @@
+/*
+ * ASPEED Watchdog Controller
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+#ifndef ASPEED_WDT_H
+#define ASPEED_WDT_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ASPEED_WDT "aspeed.wdt"
+#define ASPEED_WDT(obj) \
+    OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT)
+#define ASPEED_WDT_CLASS(klass) \
+    OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT)
+#define ASPEED_WDT_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT)
+
+#define WDT_ASPEED_INIT      0
+#define WDT_ASPEED_CHANGE    1
+#define WDT_ASPEED_CANCEL    2
+
+typedef struct AspeedWDTState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    QEMUTimer *timer;
+    bool enabled;
+
+    /*< public >*/
+    MemoryRegion iomem;
+
+    uint32_t reg_status;
+    uint32_t reg_reload_value;
+    uint32_t reg_restart;
+    uint32_t reg_ctrl;
+} AspeedWDTState;
+
+#endif  /* ASPEED_WDT_H */
-- 
2.7.4

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

* [PATCH qemu 31/38] aspeed: add a watchdog controller
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (29 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:27   ` Joel Stanley
  2016-11-28  2:12   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 32/38] wdt: aspeed: Fix failed reboot due to timer miscalculation Cédric Le Goater
                   ` (6 subsequent siblings)
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c         | 13 +++++++++++++
 include/hw/arm/aspeed_soc.h |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index d2bc0ba2070d..2926ed2dd46d 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -31,6 +31,7 @@
 #define ASPEED_SOC_SCU_BASE         0x1E6E2000
 #define ASPEED_SOC_SRAM_BASE        0x1E720000
 #define ASPEED_SOC_TIMER_BASE       0x1E782000
+#define ASPEED_SOC_WDT_BASE         0x1E785000
 #define ASPEED_SOC_I2C_BASE         0x1E78A000
 
 static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
@@ -168,6 +169,10 @@ static void aspeed_soc_init(Object *obj)
                          sc->info->silicon_rev);
     object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
                               "ram-size", &error_abort);
+
+    object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ASPEED_WDT);
+    object_property_add_child(obj, "wdt", OBJECT(&s->wdt), NULL);
+    qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
 }
 
 static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
@@ -329,6 +334,14 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
         return;
     }
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE);
+
+    /* Watch dog */
+    object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, ASPEED_SOC_WDT_BASE);
 }
 
 static void aspeed_soc_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 1ab5deaa0813..dbec0c159885 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -19,6 +19,7 @@
 #include "hw/timer/aspeed_timer.h"
 #include "hw/i2c/aspeed_i2c.h"
 #include "hw/ssi/aspeed_smc.h"
+#include "hw/watchdog/wdt_aspeed.h"
 
 #define ASPEED_SPIS_NUM  2
 
@@ -37,6 +38,7 @@ typedef struct AspeedSoCState {
     AspeedSMCState fmc;
     AspeedSMCState spi[ASPEED_SPIS_NUM];
     AspeedSDMCState sdmc;
+    AspeedWDTState wdt;
 } AspeedSoCState;
 
 #define TYPE_ASPEED_SOC "aspeed-soc"
-- 
2.7.4

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

* [PATCH qemu 32/38] wdt: aspeed: Fix failed reboot due to timer miscalculation
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (30 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 31/38] aspeed: add a watchdog controller Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-18 14:22 ` [PATCH qemu 33/38] wdt: aspeed: use scu to get clock freq Cédric Le Goater
                   ` (5 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

From: Andrew Jeffery <andrew@aj.id.au>

The implementation was incorrectly scaling the reload value by
nanoseconds per second. In reality the span represented by the reload
value is determined by the selected clock, either APB or 1MHz.

Test the selected clock and apply the appropriate scaling, then
convert to nanoseconds for the timer infrastructure. Note that the APB
rate is hard-coded and reflects the value used by the timer
controller, and isn't necessarily an accurate representation of the
clock configuration programmed in the SCU.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/watchdog/wdt_aspeed.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index 29d9d7f91463..860d4b73e2b6 100644
--- a/hw/watchdog/wdt_aspeed.c
+++ b/hw/watchdog/wdt_aspeed.c
@@ -56,11 +56,14 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
 
 }
 
+#define PCLK_HZ 24000000
+
 static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
                              unsigned size)
 {
     AspeedWDTState *s = ASPEED_WDT(opaque);
     bool en = data & BIT(0);
+    bool pclk = !(data & BIT(4));
 
     switch (offset) {
     case WDT_STATUS:
@@ -73,21 +76,36 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
         break;
     case WDT_RESTART:
         if ((data & 0xFFFF) == 0x4755) {
+            uint32_t reload;
+
             s->reg_status = s->reg_reload_value;
 
+            if (pclk) {
+                reload = muldiv64(s->reg_reload_value, NANOSECONDS_PER_SECOND,
+                                  PCLK_HZ) ;
+            } else {
+                reload = s->reg_reload_value * 1000;
+            }
+
             if (s->enabled) {
                 timer_mod(s->timer,
-                          qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
-                          s->reg_reload_value * NANOSECONDS_PER_SECOND);
+                          qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + reload);
             }
         }
         break;
     case WDT_CTRL:
         if (en && !s->enabled) {
+            uint32_t reload;
+
+            if (pclk) {
+                reload = muldiv64(s->reg_reload_value, NANOSECONDS_PER_SECOND,
+                                  PCLK_HZ);
+            } else {
+                reload = s->reg_reload_value * 1000;
+            }
+
             s->enabled = true;
-            timer_mod(s->timer,
-                      qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
-                      s->reg_reload_value * NANOSECONDS_PER_SECOND);
+            timer_mod(s->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + reload);
         } else if (!en && s->enabled) {
             s->enabled = false;
             timer_del(s->timer);
-- 
2.7.4

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

* [PATCH qemu 33/38] wdt: aspeed: use scu to get clock freq
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (31 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 32/38] wdt: aspeed: Fix failed reboot due to timer miscalculation Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:27   ` Joel Stanley
  2016-11-18 14:22 ` [PATCH qemu 34/38] net: add FTGMAC100 support Cédric Le Goater
                   ` (4 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c              |  2 ++
 hw/misc/aspeed_scu.c             | 12 ++++++++++++
 hw/watchdog/wdt_aspeed.c         | 19 +++++++++++++++----
 include/hw/misc/aspeed_scu.h     |  1 +
 include/hw/watchdog/wdt_aspeed.h |  2 ++
 5 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 2926ed2dd46d..06c1f03555b1 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -173,6 +173,8 @@ static void aspeed_soc_init(Object *obj)
     object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ASPEED_WDT);
     object_property_add_child(obj, "wdt", OBJECT(&s->wdt), NULL);
     qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
+    object_property_add_const_link(OBJECT(&s->wdt), "scu", OBJECT(&s->scu),
+                                   NULL);
 }
 
 static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index b5efba9121b2..3f577ca12771 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -268,6 +268,18 @@ bool is_supported_silicon_rev(uint32_t silicon_rev)
     return false;
 }
 
+#define ASPEED_PLL_25MHZ    25000000
+#define ASPEED_PLL_24MHZ    24000000
+#define ASPEED_PLL_12MHZ    12000000
+
+uint32_t aspeed_scu_get_clk(AspeedSCUState *scu)
+{
+    if (scu->hw_strap1 & AST2400_CLK_25M_IN)
+        return ASPEED_PLL_25MHZ;
+    else
+        return ASPEED_PLL_24MHZ;
+}
+
 static void aspeed_scu_realize(DeviceState *dev, Error **errp)
 {
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index 860d4b73e2b6..276783de90ad 100644
--- a/hw/watchdog/wdt_aspeed.c
+++ b/hw/watchdog/wdt_aspeed.c
@@ -7,10 +7,12 @@
 
 #include "qemu/osdep.h"
 #include "qemu/log.h"
+#include "qapi/error.h"
 #include "sysemu/watchdog.h"
 #include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "hw/watchdog/wdt_aspeed.h"
+#include "hw/misc/aspeed_scu.h"
 
 #define WDT_IO_REGION_SIZE      0x1000
 
@@ -56,8 +58,6 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
 
 }
 
-#define PCLK_HZ 24000000
-
 static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
                              unsigned size)
 {
@@ -82,7 +82,7 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
 
             if (pclk) {
                 reload = muldiv64(s->reg_reload_value, NANOSECONDS_PER_SECOND,
-                                  PCLK_HZ) ;
+                                  s->pclk_freq);
             } else {
                 reload = s->reg_reload_value * 1000;
             }
@@ -99,7 +99,7 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
 
             if (pclk) {
                 reload = muldiv64(s->reg_reload_value, NANOSECONDS_PER_SECOND,
-                                  PCLK_HZ);
+                                  s->pclk_freq);
             } else {
                 reload = s->reg_reload_value * 1000;
             }
@@ -177,10 +177,21 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
 {
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     AspeedWDTState *s = ASPEED_WDT(dev);
+    Object *obj;
+    Error *err = NULL;
 
     s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired,
                             dev);
 
+    obj = object_property_get_link(OBJECT(dev), "scu", &err);
+    if (!obj) {
+        error_setg(errp, "%s: required link 'scu' not found: %s",
+                   __func__, error_get_pretty(err));
+        return;
+    }
+
+    s->pclk_freq = aspeed_scu_get_clk(ASPEED_SCU(obj));
+
     memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_wdt_ops, s,
                           TYPE_ASPEED_WDT, WDT_IO_REGION_SIZE);
     sysbus_init_mmio(sbd, &s->iomem);
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index bd4ac013f997..067f9f01819d 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -37,6 +37,7 @@ typedef struct AspeedSCUState {
 #define AST2500_A1_SILICON_REV   0x04010303U
 
 extern bool is_supported_silicon_rev(uint32_t silicon_rev);
+extern uint32_t aspeed_scu_get_clk(AspeedSCUState *scu);
 
 /*
  * Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions
diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
index dbf45ae968db..0483335ecee5 100644
--- a/include/hw/watchdog/wdt_aspeed.h
+++ b/include/hw/watchdog/wdt_aspeed.h
@@ -36,6 +36,8 @@ typedef struct AspeedWDTState {
     uint32_t reg_reload_value;
     uint32_t reg_restart;
     uint32_t reg_ctrl;
+
+    uint32_t pclk_freq;
 } AspeedWDTState;
 
 #endif  /* ASPEED_WDT_H */
-- 
2.7.4

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

* [PATCH qemu 34/38] net: add FTGMAC100 support
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (32 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 33/38] wdt: aspeed: use scu to get clock freq Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-28  2:13   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 35/38] net/ftgmac100: add a 'aspeed' property Cédric Le Goater
                   ` (3 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

The FTGMAC100 device is configured and controlled via a set of
registers available on AHB bus. Packets are transmitted and received
using DMA ring buffers.

The model is for the moment complete enough to satisfy U-Boot and the
Linux kernel but there are areas that need some more attention :

 - PHY support, this is a copy paste from the Coldfire model
 - Automatic receive/transmit polling, no timers are used to poll the
   ring buffers descriptors. We just expect the qemu nic backend to
   push packets when they arrive.
 - CRC

And some are still on the TODO list (not used today in the drivers) :

 - Ethernet Address Filtering
 - Multicast
 - High priority queues
 - VLAN
 - NCSI, may be we could add n/w filters
 - etc.

The code is based on the Coldfire Fast Ethernet Controller emulation.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 default-configs/arm-softmmu.mak |   1 +
 hw/net/Makefile.objs            |   1 +
 hw/net/ftgmac100.c              | 900 ++++++++++++++++++++++++++++++++++++++++
 include/hw/net/ftgmac100.h      |  62 +++
 4 files changed, 964 insertions(+)
 create mode 100644 hw/net/ftgmac100.c
 create mode 100644 include/hw/net/ftgmac100.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index e3ac9e0ec104..81def25bfd54 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -29,6 +29,7 @@ CONFIG_LAN9118=y
 CONFIG_SMC91C111=y
 CONFIG_ALLWINNER_EMAC=y
 CONFIG_IMX_FEC=y
+CONFIG_FTGMAC100=y
 CONFIG_DS1338=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
index 610ed3e7ae64..7ca51d85a672 100644
--- a/hw/net/Makefile.objs
+++ b/hw/net/Makefile.objs
@@ -26,6 +26,7 @@ common-obj-$(CONFIG_IMX_FEC) += imx_fec.o
 common-obj-$(CONFIG_CADENCE) += cadence_gem.o
 common-obj-$(CONFIG_STELLARIS_ENET) += stellaris_enet.o
 common-obj-$(CONFIG_LANCE) += lance.o
+common-obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 
 obj-$(CONFIG_ETRAXFS) += etraxfs_eth.o
 obj-$(CONFIG_COLDFIRE) += mcf_fec.o
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
new file mode 100644
index 000000000000..22573ff956fd
--- /dev/null
+++ b/hw/net/ftgmac100.c
@@ -0,0 +1,900 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * Based on Coldfire Fast Ethernet Controller emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ *  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 "hw/net/ftgmac100.h"
+#include "sysemu/dma.h"
+#include "qemu/log.h"
+
+/* For crc32 */
+#include <zlib.h>
+
+#ifdef FTGMAC100_DEBUG
+#define DEBUG(fmt, ...) do {         \
+        fprintf(stderr,  "%s: " fmt, __func__, ## __VA_ARGS__);  \
+    } while (0);
+#else
+    #define DEBUG(...) do {} while (0)
+#endif
+
+#ifdef FTGMAC100_PHY_DEBUG
+#define PHY_DEBUG(fmt, ...) do {         \
+        fprintf(stderr,  "%s: " fmt, __func__, ## __VA_ARGS__);  \
+    } while (0);
+#else
+    #define PHY_DEBUG(...) do {} while (0)
+#endif
+
+/*
+ * IFTGMAC100 registers
+ */
+#define FTGMAC100_ISR             0x00
+#define FTGMAC100_IER             0x04
+#define FTGMAC100_MAC_MADR        0x08
+#define FTGMAC100_MAC_LADR        0x0c
+
+#define FTGMAC100_NPTXPD          0x18
+#define FTGMAC100_RXPD            0x1C
+#define FTGMAC100_NPTXR_BADR      0x20
+#define FTGMAC100_RXR_BADR        0x24
+#define FTGMAC100_APTC            0x34
+#define FTGMAC100_RBSR            0x4c
+
+#define FTGMAC100_MACCR           0x50
+#define FTGMAC100_PHYCR           0x60
+#define FTGMAC100_PHYDATA         0x64
+
+/*
+ * Interrupt status register & interrupt enable register
+ */
+#define FTGMAC100_INT_RPKT_BUF    (1 << 0)
+#define FTGMAC100_INT_RPKT_FIFO   (1 << 1)
+#define FTGMAC100_INT_NO_RXBUF    (1 << 2)
+#define FTGMAC100_INT_RPKT_LOST   (1 << 3)
+#define FTGMAC100_INT_XPKT_ETH    (1 << 4)
+#define FTGMAC100_INT_XPKT_FIFO   (1 << 5)
+#define FTGMAC100_INT_NO_NPTXBUF  (1 << 6)
+#define FTGMAC100_INT_XPKT_LOST   (1 << 7)
+#define FTGMAC100_INT_AHB_ERR     (1 << 8)
+#define FTGMAC100_INT_PHYSTS_CHG  (1 << 9)
+#define FTGMAC100_INT_NO_HPTXBUF  (1 << 10)
+
+/*
+ * Automatic polling timer control register
+ */
+#define FTGMAC100_APTC_RXPOLL_CNT(x)        ((x) & 0xf)
+#define FTGMAC100_APTC_RXPOLL_TIME_SEL      (1 << 4)
+#define FTGMAC100_APTC_TXPOLL_CNT(x)        (((x) >> 8) & 0xf)
+#define FTGMAC100_APTC_TXPOLL_TIME_SEL      (1 << 12)
+
+/*
+ * PHY control register
+ */
+#define FTGMAC100_PHYCR_MIIRD               (1 << 26)
+#define FTGMAC100_PHYCR_MIIWR               (1 << 27)
+
+/*
+ * PHY data register
+ */
+#define FTGMAC100_PHYDATA_MIIWDATA(x)       ((x) & 0xffff)
+#define FTGMAC100_PHYDATA_MIIRDATA(phydata) (((phydata) >> 16) & 0xffff)
+
+
+/*
+ * MAC control register
+ */
+#define FTGMAC100_MACCR_TXDMA_EN         (1 << 0)
+#define FTGMAC100_MACCR_RXDMA_EN         (1 << 1)
+#define FTGMAC100_MACCR_TXMAC_EN         (1 << 2)
+#define FTGMAC100_MACCR_RXMAC_EN         (1 << 3)
+#define FTGMAC100_MACCR_RM_VLAN          (1 << 4)
+#define FTGMAC100_MACCR_HPTXR_EN         (1 << 5)
+#define FTGMAC100_MACCR_LOOP_EN          (1 << 6)
+#define FTGMAC100_MACCR_ENRX_IN_HALFTX   (1 << 7)
+#define FTGMAC100_MACCR_FULLDUP          (1 << 8)
+#define FTGMAC100_MACCR_GIGA_MODE        (1 << 9)
+#define FTGMAC100_MACCR_CRC_APD          (1 << 10)
+#define FTGMAC100_MACCR_RX_RUNT          (1 << 12)
+#define FTGMAC100_MACCR_JUMBO_LF         (1 << 13)
+#define FTGMAC100_MACCR_RX_ALL           (1 << 14)
+#define FTGMAC100_MACCR_HT_MULTI_EN      (1 << 15)
+#define FTGMAC100_MACCR_RX_MULTIPKT      (1 << 16)
+#define FTGMAC100_MACCR_RX_BROADPKT      (1 << 17)
+#define FTGMAC100_MACCR_DISCARD_CRCERR   (1 << 18)
+#define FTGMAC100_MACCR_FAST_MODE        (1 << 19)
+#define FTGMAC100_MACCR_SW_RST           (1 << 31)
+
+/*
+ * Transmit descriptor, aligned to 16 bytes
+ */
+struct ftgmac100_txdes {
+        unsigned int        txdes0;
+        unsigned int        txdes1;
+        unsigned int        txdes2;      /* not used by HW */
+        unsigned int        txdes3;      /* TXBUF_BADR */
+} __attribute__ ((aligned(16)));
+
+#define FTGMAC100_TXDES0_TXBUF_SIZE(x)   ((x) & 0x3fff)
+#define FTGMAC100_TXDES0_EDOTR           (1 << 15)
+#define FTGMAC100_TXDES0_CRC_ERR         (1 << 19)
+#define FTGMAC100_TXDES0_LTS             (1 << 28)
+#define FTGMAC100_TXDES0_FTS             (1 << 29)
+#define FTGMAC100_TXDES0_TXDMA_OWN       (1 << 31)
+
+#define FTGMAC100_TXDES1_VLANTAG_CI(x)   ((x) & 0xffff)
+#define FTGMAC100_TXDES1_INS_VLANTAG     (1 << 16)
+#define FTGMAC100_TXDES1_TCP_CHKSUM      (1 << 17)
+#define FTGMAC100_TXDES1_UDP_CHKSUM      (1 << 18)
+#define FTGMAC100_TXDES1_IP_CHKSUM       (1 << 19)
+#define FTGMAC100_TXDES1_LLC             (1 << 22)
+#define FTGMAC100_TXDES1_TX2FIC          (1 << 30)
+#define FTGMAC100_TXDES1_TXIC            (1 << 31)
+
+/*
+ * Receive descriptor, aligned to 16 bytes
+ */
+struct ftgmac100_rxdes {
+        unsigned int        rxdes0;
+        unsigned int        rxdes1;
+        unsigned int        rxdes2;      /* not used by HW */
+        unsigned int        rxdes3;      /* RXBUF_BADR */
+} __attribute__ ((aligned(16)));
+
+#define FTGMAC100_RXDES0_VDBC            0x3fff
+#define FTGMAC100_RXDES0_EDORR           (1 << 15)
+#define FTGMAC100_RXDES0_MULTICAST       (1 << 16)
+#define FTGMAC100_RXDES0_BROADCAST       (1 << 17)
+#define FTGMAC100_RXDES0_RX_ERR          (1 << 18)
+#define FTGMAC100_RXDES0_CRC_ERR         (1 << 19)
+#define FTGMAC100_RXDES0_FTL             (1 << 20)
+#define FTGMAC100_RXDES0_RUNT            (1 << 21)
+#define FTGMAC100_RXDES0_RX_ODD_NB       (1 << 22)
+#define FTGMAC100_RXDES0_FIFO_FULL       (1 << 23)
+#define FTGMAC100_RXDES0_PAUSE_OPCODE    (1 << 24)
+#define FTGMAC100_RXDES0_PAUSE_FRAME     (1 << 25)
+#define FTGMAC100_RXDES0_LRS             (1 << 28)
+#define FTGMAC100_RXDES0_FRS             (1 << 29)
+#define FTGMAC100_RXDES0_RXPKT_RDY       (1 << 31)
+
+#define FTGMAC100_RXDES1_VLANTAG_CI      0xffff
+#define FTGMAC100_RXDES1_PROT_MASK       (0x3 << 20)
+#define FTGMAC100_RXDES1_PROT_NONIP      (0x0 << 20)
+#define FTGMAC100_RXDES1_PROT_IP         (0x1 << 20)
+#define FTGMAC100_RXDES1_PROT_TCPIP      (0x2 << 20)
+#define FTGMAC100_RXDES1_PROT_UDPIP      (0x3 << 20)
+#define FTGMAC100_RXDES1_LLC             (1 << 22)
+#define FTGMAC100_RXDES1_DF              (1 << 23)
+#define FTGMAC100_RXDES1_VLANTAG_AVAIL   (1 << 24)
+#define FTGMAC100_RXDES1_TCP_CHKSUM_ERR  (1 << 25)
+#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR  (1 << 26)
+#define FTGMAC100_RXDES1_IP_CHKSUM_ERR   (1 << 27)
+
+/*
+ * PHY values (to be defined elsewhere ...)
+ */
+#define PHY_INT_ENERGYON            (1 << 7)
+#define PHY_INT_AUTONEG_COMPLETE    (1 << 6)
+#define PHY_INT_FAULT               (1 << 5)
+#define PHY_INT_DOWN                (1 << 4)
+#define PHY_INT_AUTONEG_LP          (1 << 3)
+#define PHY_INT_PARFAULT            (1 << 2)
+#define PHY_INT_AUTONEG_PAGE        (1 << 1)
+
+/* Common Buffer Descriptor  */
+typedef struct {
+    uint32_t        des0;
+    uint32_t        des1;
+    uint32_t        des2;        /* not used by HW */
+    uint32_t        des3;        /* TXBUF_BADR */
+} Ftgmac100Desc  __attribute__ ((aligned(16)));
+
+/* max frame size is :
+ *
+ *   9216 for Jumbo frames (+ 4 for VLAN)
+ *   1518 for other frames (+ 4 for VLAN)
+ */
+#define FTGMAC100_MAX_FRAME_SIZE(s)                             \
+    ((s->maccr & FTGMAC100_MACCR_JUMBO_LF ? 9216 : 1518) + 4)
+
+static void ftgmac100_update_irq(Ftgmac100State *s);
+
+/*
+ * The MII phy could raise a GPIO to the processor which in turn
+ * could be handled as an interrpt by the OS.
+ * For now we don't handle any GPIO/interrupt line, so the OS will
+ * have to poll for the PHY status.
+ */
+static void phy_update_irq(Ftgmac100State *s)
+{
+    ftgmac100_update_irq(s);
+}
+
+static void phy_update_link(Ftgmac100State *s)
+{
+    /* Autonegotiation status mirrors link status.  */
+    if (qemu_get_queue(s->nic)->link_down) {
+        PHY_DEBUG("link is down\n");
+        s->phy_status &= ~0x0024;
+        s->phy_int |= PHY_INT_DOWN;
+    } else {
+        PHY_DEBUG("link is up\n");
+        s->phy_status |= 0x0024;
+        s->phy_int |= PHY_INT_ENERGYON;
+        s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
+    }
+    phy_update_irq(s);
+}
+
+static void ftgmac100_set_link(NetClientState *nc)
+{
+    phy_update_link(FTGMAC100(qemu_get_nic_opaque(nc)));
+}
+
+static void phy_reset(Ftgmac100State *s)
+{
+    s->phy_status = 0x7809;
+    s->phy_control = 0x3000;
+    s->phy_advertise = 0x01e1;
+    s->phy_int_mask = 0;
+    s->phy_int = 0;
+    phy_update_link(s);
+}
+
+static uint32_t do_phy_read(Ftgmac100State *s, int reg)
+{
+    uint32_t val;
+
+    if (reg > 31) {
+        /* we only advertise one phy */
+        return 0;
+    }
+
+    switch (reg) {
+    case 0:     /* Basic Control */
+        val = s->phy_control;
+        break;
+    case 1:     /* Basic Status */
+        val = s->phy_status;
+        break;
+    case 2:     /* ID1 */
+        val = 0x0007;
+        break;
+    case 3:     /* ID2 */
+        val = 0xc0d1;
+        break;
+    case 4:     /* Auto-neg advertisement */
+        val = s->phy_advertise;
+        break;
+    case 5:     /* Auto-neg Link Partner Ability */
+        val = 0x0f71;
+        break;
+    case 6:     /* Auto-neg Expansion */
+        val = 1;
+        break;
+        val = 0x0800;
+        break;
+    case 29:    /* Interrupt source.  */
+        val = s->phy_int;
+        s->phy_int = 0;
+        phy_update_irq(s);
+        break;
+    case 30:    /* Interrupt mask */
+        val = s->phy_int_mask;
+        break;
+    case 0x0a: /* 1000BASE-T status  */
+    case 17:
+    case 18:
+    case 27:
+    case 31:
+        qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
+                      __func__, reg);
+        val = 0;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
+                      __func__, reg);
+        val = 0;
+        break;
+    }
+
+    PHY_DEBUG("PHY read 0x%04x @%d\n", val, reg);
+    return val;
+}
+
+static void do_phy_write(Ftgmac100State *s, int reg, uint32_t val)
+{
+    PHY_DEBUG("PHY: write 0x%04x @%d\n", val, reg);
+
+    if (reg > 31) {
+        /* we only advertise one phy */
+        return;
+    }
+
+    switch (reg) {
+    case 0:     /* Basic Control */
+        if (val & 0x8000) {
+            phy_reset(s);
+        } else {
+            s->phy_control = val & 0x7980;
+            /* Complete autonegotiation immediately.  */
+            if (val & 0x1000) {
+                s->phy_status |= 0x0020;
+            }
+        }
+        break;
+    case 4:     /* Auto-neg advertisement */
+        s->phy_advertise = (val & 0x2d7f) | 0x80;
+        break;
+    case 30:    /* Interrupt mask */
+        s->phy_int_mask = val & 0xff;
+        phy_update_irq(s);
+        break;
+    case 17:
+    case 18:
+    case 27:
+    case 31:
+        qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
+                      __func__, reg);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
+                      __func__, reg);
+        break;
+    }
+}
+
+static void ftgmac100_read_bd(Ftgmac100Desc *bd, dma_addr_t addr)
+{
+    dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
+    bd->des0 = le32_to_cpu(bd->des0);
+    bd->des1 = le32_to_cpu(bd->des1);
+    bd->des2 = le32_to_cpu(bd->des2);
+    bd->des3 = le32_to_cpu(bd->des3);
+}
+
+static void ftgmac100_write_bd(Ftgmac100Desc *bd, dma_addr_t addr)
+{
+    Ftgmac100Desc lebd;
+    lebd.des0 = cpu_to_le32(bd->des0);
+    lebd.des1 = cpu_to_le32(bd->des1);
+    lebd.des2 = cpu_to_le32(bd->des2);
+    lebd.des3 = cpu_to_le32(bd->des3);
+    dma_memory_write(&address_space_memory, addr, &lebd, sizeof(lebd));
+}
+
+static void ftgmac100_update_irq(Ftgmac100State *s)
+{
+    uint32_t active;
+    uint32_t changed;
+
+    active = s->isr & s->ier;
+    changed = active ^ s->irq_state;
+    if (changed) {
+        qemu_set_irq(s->irq, active);
+    }
+    s->irq_state = active;
+}
+
+/* Locate a possible first descriptor to transmit. When Linux resets
+ * the device, the indexes of ring buffers are cleared but the dma
+ * buffers are not, so we need to find a starting point.
+ */
+static uint32_t ftgmac100_find_txdes(Ftgmac100State *s, uint32_t addr)
+{
+    Ftgmac100Desc bd;
+
+    while (1) {
+        ftgmac100_read_bd(&bd, addr);
+        if (bd.des0 & (FTGMAC100_TXDES0_FTS | FTGMAC100_TXDES0_EDOTR)) {
+            break;
+        }
+        addr += sizeof(Ftgmac100Desc);
+    }
+    return addr;
+}
+
+static void ftgmac100_do_tx(Ftgmac100State *s)
+{
+    int frame_size = 0;
+    uint8_t frame[FTGMAC100_MAX_FRAME_SIZE(s)];
+    uint8_t *ptr = frame;
+    uint32_t addr;
+
+    addr = ftgmac100_find_txdes(s, s->tx_descriptor);
+
+    while (1) {
+        Ftgmac100Desc bd;
+        int len;
+
+        ftgmac100_read_bd(&bd, addr);
+        if ((bd.des0 & FTGMAC100_TXDES0_TXDMA_OWN) == 0) {
+            /* Run out of descriptors to transmit.  */
+            s->isr |= FTGMAC100_INT_NO_NPTXBUF;
+            break;
+        }
+        len = bd.des0 & 0x3FFF;
+        if (frame_size + len > FTGMAC100_MAX_FRAME_SIZE(s)) {
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n",
+                          __func__, len);
+            len = FTGMAC100_MAX_FRAME_SIZE(s) - frame_size;
+        }
+        dma_memory_read(&address_space_memory, bd.des3, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.des0 & FTGMAC100_TXDES0_LTS) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(qemu_get_queue(s->nic), frame, len);
+            ptr = frame;
+            frame_size = 0;
+            if (bd.des1 & FTGMAC100_TXDES1_TXIC) {
+                s->isr |= FTGMAC100_INT_XPKT_ETH;
+            }
+        }
+
+        if (bd.des1 & FTGMAC100_TXDES1_TX2FIC) {
+            s->isr |= FTGMAC100_INT_XPKT_FIFO;
+        }
+        bd.des0 &= ~FTGMAC100_TXDES0_TXDMA_OWN;
+
+        /* Write back the modified descriptor.  */
+        ftgmac100_write_bd(&bd, addr);
+        /* Advance to the next descriptor.  */
+        if (bd.des0 & FTGMAC100_TXDES0_EDOTR) {
+            addr = s->tx_ring;
+        } else {
+            addr += sizeof(Ftgmac100Desc);
+        }
+    }
+
+    s->tx_descriptor = addr;
+
+    ftgmac100_update_irq(s);
+}
+
+static void ftgmac100_enable_rx(Ftgmac100State *s)
+{
+    Ftgmac100Desc bd;
+    uint32_t full;
+
+    /* Find an empty descriptor to use */
+    while (1) {
+        ftgmac100_read_bd(&bd, s->rx_descriptor);
+        full = (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY);
+        if (!full || bd.des0 & FTGMAC100_TXDES0_EDOTR) {
+            break;
+        }
+        s->rx_descriptor += sizeof(Ftgmac100Desc);
+    }
+
+    if (full) {
+        DEBUG("RX buffer full\n");
+    }
+
+    s->rx_enabled = (full == 0);
+    if (s->rx_enabled) {
+        qemu_flush_queued_packets(qemu_get_queue(s->nic));
+    }
+}
+
+/*
+ * This is purely informative. The HW can poll the RW (and RX) ring
+ * buffers for available descriptors but we don't need to trigger a
+ * timer for that in qemu.
+ */
+static uint32_t ftgmac100_rxpoll(Ftgmac100State *s)
+{
+    /* Polling times :
+     *
+     * Speed      TIME_SEL=0    TIME_SEL=1
+     *
+     *    10         51.2 ms      819.2 ms
+     *   100         5.12 ms      81.92 ms
+     *  1000        1.024 ms     16.384 ms
+     */
+    static const int div[] = { 20, 200, 1000 };
+
+    uint32_t cnt = 1024 * FTGMAC100_APTC_RXPOLL_CNT(s->aptcr);
+    uint32_t speed = (s->maccr & FTGMAC100_MACCR_FAST_MODE) ? 1 : 0;
+    uint32_t period;
+
+    if (s->aptcr & FTGMAC100_APTC_RXPOLL_TIME_SEL) {
+        cnt <<= 4;
+    }
+
+    if (s->maccr & FTGMAC100_MACCR_GIGA_MODE) {
+        speed = 2;
+    }
+
+    period = cnt / div[speed];
+
+    DEBUG("polling in %d ms\n", period);
+    return period;
+}
+
+static void ftgmac100_reset(DeviceState *d)
+{
+    Ftgmac100State *s = FTGMAC100(d);
+
+    /* Reset the FTGMAC100 */
+    s->isr = 0;
+    s->ier = 0;
+    s->rx_enabled = 0;
+    s->maccr = 0;
+    s->rx_ring = 0;
+    s->rx_descriptor = 0;
+    s->rbsr = 0x640; /* HW default according to u-boot driver */
+    s->tx_ring = 0;
+    s->tx_descriptor = 0;
+    s->phycr = 0;
+    s->phydata = 0;
+    s->aptcr = 0;
+
+    /* We also reset the PHY */
+    phy_reset(s);
+}
+
+static uint64_t ftgmac100_read(void *opaque, hwaddr addr, unsigned size)
+{
+    Ftgmac100State *s = FTGMAC100(opaque);
+
+    DEBUG("reading from @ 0x%" HWADDR_PRIx "\n", addr);
+
+    switch (addr & 0xff) {
+    case FTGMAC100_ISR:
+        return s->isr;
+    case FTGMAC100_IER:
+        return s->ier;
+    case FTGMAC100_MAC_MADR:
+        return (s->conf.macaddr.a[0] << 8)  | s->conf.macaddr.a[1];
+    case FTGMAC100_MAC_LADR:
+        return (s->conf.macaddr.a[2] << 24) | (s->conf.macaddr.a[3] << 16) |
+               (s->conf.macaddr.a[4] << 8)  |  s->conf.macaddr.a[5];
+    case FTGMAC100_MACCR:
+        return s->maccr;
+    case FTGMAC100_PHYCR:
+        return s->phycr;
+    case FTGMAC100_PHYDATA:
+        return s->phydata;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_FTGMAC100, __func__, addr);
+        return 0;
+    }
+}
+
+static void ftgmac100_write(void *opaque, hwaddr addr,
+                          uint64_t value, unsigned size)
+{
+    Ftgmac100State *s = FTGMAC100(opaque);
+
+    DEBUG("writing 0x%08x @ 0x%" HWADDR_PRIx "\n", (int)value, addr);
+
+    switch (addr & 0xff) {
+    case FTGMAC100_ISR: /* Interrupt status */
+        s->isr &= ~value;
+        break;
+    case FTGMAC100_IER:  /* Interrupt control */
+        s->ier = value;
+        break;
+    case FTGMAC100_MAC_MADR: /* MAC */
+        s->conf.macaddr.a[0] = value >> 8;
+        s->conf.macaddr.a[1] = value;
+        break;
+    case FTGMAC100_MAC_LADR:
+        s->conf.macaddr.a[2] = value >> 24;
+        s->conf.macaddr.a[3] = value >> 16;
+        s->conf.macaddr.a[4] = value >> 8;
+        s->conf.macaddr.a[5] = value;
+        break;
+
+    case FTGMAC100_RXR_BADR:  /* Ring buffer address */
+        s->rx_ring = value;
+        s->rx_descriptor = s->rx_ring;
+        break;
+
+    case FTGMAC100_RBSR: /* DMA buffer size */
+        s->rbsr = value;
+        break;
+
+    case FTGMAC100_NPTXR_BADR:  /* Transmit buffer address */
+        s->tx_ring = value;
+        s->tx_descriptor = s->tx_ring;
+        break;
+
+    case FTGMAC100_NPTXPD: /* Trigger transmit */
+        if (s->maccr & FTGMAC100_MACCR_TXDMA_EN) {
+            ftgmac100_do_tx(s);
+        }
+        break;
+
+    case FTGMAC100_RXPD: /* Receive Poll Demand Register */
+        if ((s->maccr & FTGMAC100_MACCR_RXDMA_EN) && !s->rx_enabled) {
+            /*
+             * TODO: This is required for u-boot but clearly, this is
+             * broken.
+             */
+            ftgmac100_enable_rx(s);
+        }
+        break;
+
+    case FTGMAC100_APTC: /* Automatic polling */
+        s->aptcr = value;
+
+        if (FTGMAC100_APTC_RXPOLL_CNT(s->aptcr)) {
+            ftgmac100_rxpoll(s);
+        }
+
+        if (FTGMAC100_APTC_TXPOLL_CNT(s->aptcr)) {
+            qemu_log_mask(LOG_UNIMP, "%s: no transmit polling\n", __func__);
+        }
+        break;
+
+    case FTGMAC100_MACCR: /* MAC Device control */
+        s->maccr = value;
+        if (value & FTGMAC100_MACCR_SW_RST) {
+            ftgmac100_reset(DEVICE(s));
+        }
+
+        if ((s->maccr & FTGMAC100_MACCR_RXDMA_EN) && !s->rx_enabled) {
+            ftgmac100_enable_rx(s);
+        }
+
+        if ((s->maccr & FTGMAC100_MACCR_RXDMA_EN) == 0) {
+            s->rx_enabled = 0;
+        }
+        break;
+
+    case FTGMAC100_PHYCR:  /* PHY Device control */
+        s->phycr = value;
+        if (value & FTGMAC100_PHYCR_MIIWR) {
+            do_phy_write(s, extract32(value, 21, 5), s->phydata & 0xffff);
+            s->phycr &= ~FTGMAC100_PHYCR_MIIWR;
+       } else {
+            s->phydata = do_phy_read(s, extract32(value, 21, 5)) << 16;
+            s->phycr &= ~FTGMAC100_PHYCR_MIIRD;
+       }
+        break;
+    case FTGMAC100_PHYDATA:
+        s->phydata = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
+                      HWADDR_PRIx "\n", TYPE_FTGMAC100, __func__, addr);
+        break;
+    }
+
+    ftgmac100_update_irq(s);
+}
+
+static bool packet_is_broadcast(const uint8_t *buf)
+{
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    return memcmp(buf, sa_bcast, 6) == 0;
+}
+
+static int ftgmac100_can_receive(NetClientState *nc)
+{
+    Ftgmac100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
+
+    return s->rx_enabled;
+}
+
+static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
+                               size_t len)
+{
+    Ftgmac100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
+    Ftgmac100Desc bd;
+    uint32_t flags = 0;
+    uint32_t addr;
+    uint32_t crc;
+    uint32_t buf_addr;
+    uint8_t *crc_ptr;
+    unsigned int buf_len;
+    size_t size = len;
+    uint32_t first = FTGMAC100_RXDES0_FRS;
+
+    DEBUG("len %d\n", (int)size);
+
+    if (!s->rx_enabled) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__);
+        return 0;
+    }
+
+    /* FIXME: Pad short packets.  */
+
+    /* 4 bytes for the CRC.  */
+    size += 4;
+    crc = cpu_to_be32(crc32(~0, buf, size));
+    crc_ptr = (uint8_t *) &crc;
+
+    /* Huge frames are truncted.  */
+    if (size > FTGMAC100_MAX_FRAME_SIZE(s)) {
+        size = FTGMAC100_MAX_FRAME_SIZE(s);
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %zd bytes\n",
+                      __func__, size);
+        flags |= FTGMAC100_RXDES0_FTL | FTGMAC100_RXDES0_RX_ERR;
+    }
+
+    if (packet_is_broadcast(buf)) {
+        flags |= FTGMAC100_RXDES0_BROADCAST;
+    }
+
+    addr = s->rx_descriptor;
+    while (size > 0) {
+        ftgmac100_read_bd(&bd, addr);
+        if (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY) {
+            /* No descriptors available.  Bail out.  */
+            /*
+             * FIXME: This is wrong. We should probably either
+             * save the remainder for when more RX buffers are
+             * available, or flag an error.
+             */
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: Lost end of frame\n",
+                          __func__);
+            s->isr |= FTGMAC100_INT_NO_RXBUF;
+            break;
+        }
+        buf_len = (size <= s->rbsr) ? size : s->rbsr;
+        bd.des0 |= buf_len & 0x3fff;
+        size -= buf_len;
+
+        /* The last 4 bytes are the CRC.  */
+        if (size < 4) {
+            buf_len += size - 4;
+        }
+        buf_addr = bd.des3;
+        dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
+        buf += buf_len;
+        if (size < 4) {
+            dma_memory_write(&address_space_memory, buf_addr + buf_len,
+                             crc_ptr, 4 - size);
+            crc_ptr += 4 - size;
+        }
+
+        bd.des0 |= first | FTGMAC100_RXDES0_RXPKT_RDY;
+        first = 0;
+        if (size == 0) {
+            /* Last buffer in frame.  */
+            bd.des0 |= flags | FTGMAC100_RXDES0_LRS;
+            DEBUG("rx frame flags %04x\n", bd.des0);
+            s->isr |= FTGMAC100_INT_RPKT_BUF;
+        } else {
+            s->isr |= FTGMAC100_INT_RPKT_FIFO;
+        }
+        ftgmac100_write_bd(&bd, addr);
+        if (bd.des0 & FTGMAC100_RXDES0_EDORR) {
+            addr = s->rx_ring;
+        } else {
+            addr += sizeof(Ftgmac100Desc);
+        }
+    }
+    s->rx_descriptor = addr;
+
+    ftgmac100_enable_rx(s);
+    ftgmac100_update_irq(s);
+    return len;
+}
+
+static const MemoryRegionOps ftgmac100_ops = {
+    .read = ftgmac100_read,
+    .write = ftgmac100_write,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void ftgmac100_cleanup(NetClientState *nc)
+{
+    Ftgmac100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
+
+    s->nic = NULL;
+}
+
+static NetClientInfo net_ftgmac100_info = {
+    .type = NET_CLIENT_DRIVER_NIC,
+    .size = sizeof(NICState),
+    .can_receive = ftgmac100_can_receive,
+    .receive = ftgmac100_receive,
+    .cleanup = ftgmac100_cleanup,
+    .link_status_changed = ftgmac100_set_link,
+};
+
+static void ftgmac100_realize(DeviceState *dev, Error **errp)
+{
+    Ftgmac100State *s = FTGMAC100(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    memory_region_init_io(&s->iomem, OBJECT(dev), &ftgmac100_ops, s,
+                          TYPE_FTGMAC100, 0x2000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+    s->conf.peers.ncs[0] = nd_table[0].netdev;
+
+    s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf,
+                          object_get_typename(OBJECT(dev)), DEVICE(dev)->id,
+                          s);
+    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+}
+
+static const VMStateDescription vmstate_ftgmac100 = {
+    .name = TYPE_FTGMAC100,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(irq_state, Ftgmac100State),
+        VMSTATE_UINT32(isr, Ftgmac100State),
+        VMSTATE_UINT32(ier, Ftgmac100State),
+        VMSTATE_UINT32(rx_enabled, Ftgmac100State),
+        VMSTATE_UINT32(rx_ring, Ftgmac100State),
+        VMSTATE_UINT32(rbsr, Ftgmac100State),
+        VMSTATE_UINT32(tx_ring, Ftgmac100State),
+        VMSTATE_UINT32(rx_descriptor, Ftgmac100State),
+        VMSTATE_UINT32(tx_descriptor, Ftgmac100State),
+        VMSTATE_UINT32(maccr, Ftgmac100State),
+        VMSTATE_UINT32(phycr, Ftgmac100State),
+        VMSTATE_UINT32(phydata, Ftgmac100State),
+        VMSTATE_UINT32(aptcr, Ftgmac100State),
+
+        VMSTATE_UINT32(phy_status, Ftgmac100State),
+        VMSTATE_UINT32(phy_control, Ftgmac100State),
+        VMSTATE_UINT32(phy_advertise, Ftgmac100State),
+        VMSTATE_UINT32(phy_int, Ftgmac100State),
+        VMSTATE_UINT32(phy_int_mask, Ftgmac100State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property ftgmac100_properties[] = {
+    DEFINE_NIC_PROPERTIES(Ftgmac100State, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ftgmac100_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_ftgmac100;
+    dc->reset = ftgmac100_reset;
+    dc->props = ftgmac100_properties;
+    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
+    dc->realize = ftgmac100_realize;
+    dc->desc = "Faraday FTGMAC100 Gigabit Ethernet emulation";
+}
+
+static const TypeInfo ftgmac100_info = {
+    .name = TYPE_FTGMAC100,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(Ftgmac100State),
+    .class_init = ftgmac100_class_init,
+};
+
+static void ftgmac100_register_types(void)
+{
+    type_register_static(&ftgmac100_info);
+}
+
+type_init(ftgmac100_register_types)
diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h
new file mode 100644
index 000000000000..cc5cb4207a5c
--- /dev/null
+++ b/include/hw/net/ftgmac100.h
@@ -0,0 +1,62 @@
+/*
+ * Faraday FTGMAC100 Gigabit Ethernet
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * 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 FTGMAC100_H
+#define FTGMAC100_H
+
+#define TYPE_FTGMAC100 "ftgmac100"
+#define FTGMAC100(obj) OBJECT_CHECK(Ftgmac100State, (obj), TYPE_FTGMAC100)
+
+#include "hw/sysbus.h"
+#include "net/net.h"
+
+typedef struct Ftgmac100State {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    NICState *nic;
+    NICConf conf;
+    qemu_irq irq;
+    MemoryRegion iomem;
+
+    uint32_t irq_state;
+    uint32_t isr;
+    uint32_t ier;
+    uint32_t rx_enabled;
+    uint32_t rx_ring;
+    uint32_t rbsr;
+    uint32_t rx_descriptor;
+    uint32_t tx_ring;
+    uint32_t tx_descriptor;
+    uint32_t maccr;
+    uint32_t phycr;
+    uint32_t phydata;
+    uint32_t aptcr;
+
+    uint32_t phy_status;
+    uint32_t phy_control;
+    uint32_t phy_advertise;
+    uint32_t phy_int;
+    uint32_t phy_int_mask;
+
+} Ftgmac100State;
+
+#endif
-- 
2.7.4

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

* [PATCH qemu 35/38] net/ftgmac100: add a 'aspeed' property
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (33 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 34/38] net: add FTGMAC100 support Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-28  2:22   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 36/38] ast2400: add a FTGMAC100 nic Cédric Le Goater
                   ` (2 subsequent siblings)
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

Aspeed SOCs have different definitions for the end of ring bits. Add a
property to specify which set of bits should be used by the nic device
model.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/net/ftgmac100.c         | 24 ++++++++++++++++++++----
 include/hw/net/ftgmac100.h |  2 ++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
index 22573ff956fd..0a8ab6b9e4d8 100644
--- a/hw/net/ftgmac100.c
+++ b/hw/net/ftgmac100.c
@@ -136,9 +136,11 @@ struct ftgmac100_txdes {
 
 #define FTGMAC100_TXDES0_TXBUF_SIZE(x)   ((x) & 0x3fff)
 #define FTGMAC100_TXDES0_EDOTR           (1 << 15)
+
 #define FTGMAC100_TXDES0_CRC_ERR         (1 << 19)
 #define FTGMAC100_TXDES0_LTS             (1 << 28)
 #define FTGMAC100_TXDES0_FTS             (1 << 29)
+#define FTGMAC100_TXDES0_EDOTR_ASPEED    (1 << 30)
 #define FTGMAC100_TXDES0_TXDMA_OWN       (1 << 31)
 
 #define FTGMAC100_TXDES1_VLANTAG_CI(x)   ((x) & 0xffff)
@@ -174,6 +176,7 @@ struct ftgmac100_rxdes {
 #define FTGMAC100_RXDES0_PAUSE_FRAME     (1 << 25)
 #define FTGMAC100_RXDES0_LRS             (1 << 28)
 #define FTGMAC100_RXDES0_FRS             (1 << 29)
+#define FTGMAC100_RXDES0_EDORR_ASPEED    (1 << 30)
 #define FTGMAC100_RXDES0_RXPKT_RDY       (1 << 31)
 
 #define FTGMAC100_RXDES1_VLANTAG_CI      0xffff
@@ -208,6 +211,18 @@ typedef struct {
     uint32_t        des3;        /* TXBUF_BADR */
 } Ftgmac100Desc  __attribute__ ((aligned(16)));
 
+static inline uint32_t ftgmac100_rxdes0_edorr(Ftgmac100State *s)
+{
+    return s->aspeed ?
+        FTGMAC100_RXDES0_EDORR_ASPEED : FTGMAC100_RXDES0_EDORR;
+}
+
+static inline uint32_t ftgmac100_txdes0_edotr(Ftgmac100State *s)
+{
+    return s->aspeed ?
+        FTGMAC100_TXDES0_EDOTR_ASPEED : FTGMAC100_TXDES0_EDOTR;
+}
+
 /* max frame size is :
  *
  *   9216 for Jumbo frames (+ 4 for VLAN)
@@ -405,7 +420,7 @@ static uint32_t ftgmac100_find_txdes(Ftgmac100State *s, uint32_t addr)
 
     while (1) {
         ftgmac100_read_bd(&bd, addr);
-        if (bd.des0 & (FTGMAC100_TXDES0_FTS | FTGMAC100_TXDES0_EDOTR)) {
+        if (bd.des0 & (FTGMAC100_TXDES0_FTS | ftgmac100_txdes0_edotr(s))) {
             break;
         }
         addr += sizeof(Ftgmac100Desc);
@@ -459,7 +474,7 @@ static void ftgmac100_do_tx(Ftgmac100State *s)
         /* Write back the modified descriptor.  */
         ftgmac100_write_bd(&bd, addr);
         /* Advance to the next descriptor.  */
-        if (bd.des0 & FTGMAC100_TXDES0_EDOTR) {
+        if (bd.des0 & ftgmac100_txdes0_edotr(s)) {
             addr = s->tx_ring;
         } else {
             addr += sizeof(Ftgmac100Desc);
@@ -480,7 +495,7 @@ static void ftgmac100_enable_rx(Ftgmac100State *s)
     while (1) {
         ftgmac100_read_bd(&bd, s->rx_descriptor);
         full = (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY);
-        if (!full || bd.des0 & FTGMAC100_TXDES0_EDOTR) {
+        if (!full || bd.des0 & ftgmac100_txdes0_edotr(s)) {
             break;
         }
         s->rx_descriptor += sizeof(Ftgmac100Desc);
@@ -784,7 +799,7 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
             s->isr |= FTGMAC100_INT_RPKT_FIFO;
         }
         ftgmac100_write_bd(&bd, addr);
-        if (bd.des0 & FTGMAC100_RXDES0_EDORR) {
+        if (bd.des0 & ftgmac100_rxdes0_edorr(s)) {
             addr = s->rx_ring;
         } else {
             addr += sizeof(Ftgmac100Desc);
@@ -869,6 +884,7 @@ static const VMStateDescription vmstate_ftgmac100 = {
 };
 
 static Property ftgmac100_properties[] = {
+    DEFINE_PROP_BOOL("aspeed", Ftgmac100State, aspeed, false),
     DEFINE_NIC_PROPERTIES(Ftgmac100State, conf),
     DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h
index cc5cb4207a5c..ee8975000260 100644
--- a/include/hw/net/ftgmac100.h
+++ b/include/hw/net/ftgmac100.h
@@ -57,6 +57,8 @@ typedef struct Ftgmac100State {
     uint32_t phy_int;
     uint32_t phy_int_mask;
 
+    bool aspeed;
+
 } Ftgmac100State;
 
 #endif
-- 
2.7.4

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

* [PATCH qemu 36/38] ast2400: add a FTGMAC100 nic
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (34 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 35/38] net/ftgmac100: add a 'aspeed' property Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-28  2:25   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 37/38] slirp: add a fake NCSI backend Cédric Le Goater
  2016-11-18 14:22 ` [PATCH qemu 38/38] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

Only the first nic, but the second shouldn't be too complex to add if
needed.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c         | 21 +++++++++++++++++++++
 include/hw/arm/aspeed_soc.h |  2 ++
 2 files changed, 23 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 06c1f03555b1..f3c41509a4ea 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -19,6 +19,7 @@
 #include "hw/char/serial.h"
 #include "qemu/log.h"
 #include "hw/i2c/aspeed_i2c.h"
+#include "net/net.h"
 
 #define ASPEED_SOC_UART_5_BASE      0x00184000
 #define ASPEED_SOC_IOMEM_SIZE       0x00200000
@@ -33,6 +34,8 @@
 #define ASPEED_SOC_TIMER_BASE       0x1E782000
 #define ASPEED_SOC_WDT_BASE         0x1E785000
 #define ASPEED_SOC_I2C_BASE         0x1E78A000
+#define ASPEED_SOC_ETH1_BASE        0x1E660000
+#define ASPEED_SOC_ETH2_BASE        0x1E680000
 
 static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
 static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
@@ -175,6 +178,10 @@ static void aspeed_soc_init(Object *obj)
     qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
     object_property_add_const_link(OBJECT(&s->wdt), "scu", OBJECT(&s->scu),
                                    NULL);
+
+    object_initialize(&s->ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100);
+    object_property_add_child(obj, "ftgmac100", OBJECT(&s->ftgmac100), NULL);
+    qdev_set_parent_bus(DEVICE(&s->ftgmac100), sysbus_get_default());
 }
 
 static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
@@ -344,6 +351,20 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
         return;
     }
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, ASPEED_SOC_WDT_BASE);
+
+    /* Net */
+    qdev_set_nic_properties(DEVICE(&s->ftgmac100), &nd_table[0]);
+    object_property_set_bool(OBJECT(&s->ftgmac100), true, "aspeed", &err);
+    object_property_set_bool(OBJECT(&s->ftgmac100), true, "realized",
+                             &local_err);
+    error_propagate(&err, local_err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ftgmac100), 0, ASPEED_SOC_ETH1_BASE);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100), 0,
+                       qdev_get_gpio_in(DEVICE(&s->vic), 2));
 }
 
 static void aspeed_soc_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index dbec0c159885..1fd0dc690be1 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -20,6 +20,7 @@
 #include "hw/i2c/aspeed_i2c.h"
 #include "hw/ssi/aspeed_smc.h"
 #include "hw/watchdog/wdt_aspeed.h"
+#include "hw/net/ftgmac100.h"
 
 #define ASPEED_SPIS_NUM  2
 
@@ -39,6 +40,7 @@ typedef struct AspeedSoCState {
     AspeedSMCState spi[ASPEED_SPIS_NUM];
     AspeedSDMCState sdmc;
     AspeedWDTState wdt;
+    Ftgmac100State ftgmac100;
 } AspeedSoCState;
 
 #define TYPE_ASPEED_SOC "aspeed-soc"
-- 
2.7.4

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

* [PATCH qemu 37/38] slirp: add a fake NCSI backend
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (35 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 36/38] ast2400: add a FTGMAC100 nic Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
  2016-11-28  2:26   ` Andrew Jeffery
  2016-11-18 14:22 ` [PATCH qemu 38/38] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
  37 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

This only reverses the NCSI packets to make the Linux driver happy.

The NCSI header file <ncsi-pkt.h> comes from Linux.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 include/net/eth.h   |   1 +
 slirp/Makefile.objs |   2 +-
 slirp/ncsi-pkt.h    | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/ncsi.c        |  95 +++++++++++++
 slirp/slirp.c       |   4 +
 slirp/slirp.h       |   3 +
 6 files changed, 498 insertions(+), 1 deletion(-)
 create mode 100644 slirp/ncsi-pkt.h
 create mode 100644 slirp/ncsi.c

diff --git a/include/net/eth.h b/include/net/eth.h
index 2013175857ba..6237004559bc 100644
--- a/include/net/eth.h
+++ b/include/net/eth.h
@@ -209,6 +209,7 @@ struct tcp_hdr {
 #define ETH_P_IPV6                (0x86dd)
 #define ETH_P_VLAN                (0x8100)
 #define ETH_P_DVLAN               (0x88a8)
+#define ETH_P_NCSI                (0x88f8)      /* NCSI protocol             */
 #define ETH_P_UNKNOWN             (0xffff)
 #define VLAN_VID_MASK             0x0fff
 #define IP_HEADER_VERSION_4       (4)
diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
index 1baa1f1c7cfb..28049b03cddc 100644
--- a/slirp/Makefile.objs
+++ b/slirp/Makefile.objs
@@ -2,4 +2,4 @@ common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
                ip_input.o ip_output.o dnssearch.o dhcpv6.o
 common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
 common-obj-y += tcp_subr.o tcp_timer.o udp.o udp6.o bootp.o tftp.o arp_table.o \
-                ndp_table.o
+                ndp_table.o ncsi.o
diff --git a/slirp/ncsi-pkt.h b/slirp/ncsi-pkt.h
new file mode 100644
index 000000000000..20c787103ec2
--- /dev/null
+++ b/slirp/ncsi-pkt.h
@@ -0,0 +1,394 @@
+#ifndef NCSI_PKT_H
+#define NCSI_PKT_H
+
+#define __be32 uint32_t
+#define __be16 uint16_t
+
+struct ncsi_pkt_hdr {
+        unsigned char   mc_id;          /* Management controller ID */
+        unsigned char   revision;       /* NCSI version - 0x01      */
+        unsigned char   reserved;       /* Reserved                 */
+        unsigned char   id;             /* Packet sequence number   */
+        unsigned char   type;           /* Packet type              */
+        unsigned char   channel;        /* Network controller ID    */
+        __be16          length;         /* Payload length           */
+        __be32          reserved1[2];   /* Reserved                 */
+};
+
+struct ncsi_cmd_pkt_hdr {
+        struct ncsi_pkt_hdr     common;         /* Common NCSI packet header */
+};
+
+struct ncsi_rsp_pkt_hdr {
+        struct ncsi_pkt_hdr     common;         /* Common NCSI packet header */
+        __be16                  code;           /* Response code             */
+        __be16                  reason;         /* Response reason           */
+};
+
+struct ncsi_aen_pkt_hdr {
+        struct ncsi_pkt_hdr     common;         /* Common NCSI packet header */
+        unsigned char           reserved2[3];   /* Reserved                  */
+        unsigned char           type;           /* AEN packet type           */
+};
+
+/* NCSI common command and response packets */
+struct ncsi_cmd_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
+        __be32                  checksum;       /* Checksum       */
+        unsigned char           pad[26];
+};
+
+struct ncsi_rsp_pkt {
+        struct ncsi_rsp_pkt_hdr rsp;            /* Response header */
+        __be32                  checksum;       /* Checksum        */
+        unsigned char           pad[22];
+};
+
+/* Select Package */
+struct ncsi_cmd_sp_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
+        unsigned char           reserved[3];    /* Reserved       */
+        unsigned char           hw_arbitration; /* HW arbitration */
+        __be32                  checksum;       /* Checksum       */
+        unsigned char           pad[22];
+};
+
+/* Disable Channel */
+struct ncsi_cmd_dc_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header  */
+        unsigned char           reserved[3];    /* Reserved        */
+        unsigned char           ald;            /* Allow link down */
+        __be32                  checksum;       /* Checksum        */
+        unsigned char           pad[22];
+};
+
+/* Reset Channel */
+struct ncsi_cmd_rc_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
+        __be32                  reserved;       /* Reserved       */
+        __be32                  checksum;       /* Checksum       */
+        unsigned char           pad[22];
+};
+
+/* AEN Enable */
+struct ncsi_cmd_ae_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header   */
+        unsigned char           reserved[3];    /* Reserved         */
+        unsigned char           mc_id;          /* MC ID            */
+        __be32                  mode;           /* AEN working mode */
+        __be32                  checksum;       /* Checksum         */
+        unsigned char           pad[18];
+};
+
+/* Set Link */
+struct ncsi_cmd_sl_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header    */
+        __be32                  mode;           /* Link working mode */
+        __be32                  oem_mode;       /* OEM link mode     */
+        __be32                  checksum;       /* Checksum          */
+        unsigned char           pad[18];
+};
+
+/* Get Link Status */
+struct ncsi_rsp_gls_pkt {
+        struct ncsi_rsp_pkt_hdr rsp;            /* Response header   */
+        __be32                  status;         /* Link status       */
+        __be32                  other;          /* Other indications */
+        __be32                  oem_status;     /* OEM link status   */
+        __be32                  checksum;       /* Checksum          */
+        unsigned char           pad[10];
+};
+
+/* Set VLAN Filter */
+struct ncsi_cmd_svf_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header    */
+        __be16                  reserved;       /* Reserved          */
+        __be16                  vlan;           /* VLAN ID           */
+        __be16                  reserved1;      /* Reserved          */
+        unsigned char           index;          /* VLAN table index  */
+        unsigned char           enable;         /* Enable or disable */
+        __be32                  checksum;       /* Checksum          */
+        unsigned char           pad[14];
+};
+
+/* Enable VLAN */
+struct ncsi_cmd_ev_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header   */
+        unsigned char           reserved[3];    /* Reserved         */
+        unsigned char           mode;           /* VLAN filter mode */
+        __be32                  checksum;       /* Checksum         */
+        unsigned char           pad[22];
+};
+
+/* Set MAC Address */
+struct ncsi_cmd_sma_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header          */
+        unsigned char           mac[6];         /* MAC address             */
+        unsigned char           index;          /* MAC table index         */
+        unsigned char           at_e;           /* Addr type and operation */
+        __be32                  checksum;       /* Checksum                */
+        unsigned char           pad[18];
+};
+
+/* Enable Broadcast Filter */
+struct ncsi_cmd_ebf_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
+        __be32                  mode;           /* Filter mode    */
+        __be32                  checksum;       /* Checksum       */
+        unsigned char           pad[22];
+};
+
+/* Enable Global Multicast Filter */
+struct ncsi_cmd_egmf_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
+        __be32                  mode;           /* Global MC mode */
+        __be32                  checksum;       /* Checksum       */
+        unsigned char           pad[22];
+};
+
+/* Set NCSI Flow Control */
+struct ncsi_cmd_snfc_pkt {
+        struct ncsi_cmd_pkt_hdr cmd;            /* Command header    */
+        unsigned char           reserved[3];    /* Reserved          */
+        unsigned char           mode;           /* Flow control mode */
+        __be32                  checksum;       /* Checksum          */
+        unsigned char           pad[22];
+};
+
+/* Get Version ID */
+struct ncsi_rsp_gvi_pkt {
+        struct ncsi_rsp_pkt_hdr rsp;            /* Response header   */
+        __be32                  ncsi_version;   /* NCSI version      */
+        unsigned char           reserved[3];    /* Reserved          */
+        unsigned char           alpha2;         /* NCSI version      */
+        unsigned char           fw_name[12];    /* f/w name string   */
+        __be32                  fw_version;     /* f/w version       */
+        __be16                  pci_ids[4];     /* PCI IDs           */
+        __be32                  mf_id;          /* Manufacture ID    */
+        __be32                  checksum;
+};
+
+/* Get Capabilities */
+struct ncsi_rsp_gc_pkt {
+        struct ncsi_rsp_pkt_hdr rsp;            /* Response header   */
+        __be32                  cap;            /* Capabilities      */
+        __be32                  bc_cap;         /* Broadcast cap     */
+        __be32                  mc_cap;         /* Multicast cap     */
+        __be32                  buf_cap;        /* Buffering cap     */
+        __be32                  aen_cap;        /* AEN cap           */
+        unsigned char           vlan_cnt;       /* VLAN filter count */
+        unsigned char           mixed_cnt;      /* Mix filter count  */
+        unsigned char           mc_cnt;         /* MC filter count   */
+        unsigned char           uc_cnt;         /* UC filter count   */
+        unsigned char           reserved[2];    /* Reserved          */
+        unsigned char           vlan_mode;      /* VLAN mode         */
+        unsigned char           channel_cnt;    /* Channel count     */
+        __be32                  checksum;       /* Checksum          */
+};
+
+/* Get Parameters */
+struct ncsi_rsp_gp_pkt {
+        struct ncsi_rsp_pkt_hdr rsp;            /* Response header       */
+        unsigned char           mac_cnt;        /* Number of MAC addr    */
+        unsigned char           reserved[2];    /* Reserved              */
+        unsigned char           mac_enable;     /* MAC addr enable flags */
+        unsigned char           vlan_cnt;       /* VLAN tag count        */
+        unsigned char           reserved1;      /* Reserved              */
+        __be16                  vlan_enable;    /* VLAN tag enable flags */
+        __be32                  link_mode;      /* Link setting          */
+        __be32                  bc_mode;        /* BC filter mode        */
+        __be32                  valid_modes;    /* Valid mode parameters */
+        unsigned char           vlan_mode;      /* VLAN mode             */
+        unsigned char           fc_mode;        /* Flow control mode     */
+        unsigned char           reserved2[2];   /* Reserved              */
+        __be32                  aen_mode;       /* AEN mode              */
+        unsigned char           mac[6];         /* Supported MAC addr    */
+        __be16                  vlan;           /* Supported VLAN tags   */
+        __be32                  checksum;       /* Checksum              */
+};
+
+/* Get Controller Packet Statistics */
+struct ncsi_rsp_gcps_pkt {
+        struct ncsi_rsp_pkt_hdr rsp;            /* Response header            */
+        __be32                  cnt_hi;         /* Counter cleared            */
+        __be32                  cnt_lo;         /* Counter cleared            */
+        __be32                  rx_bytes;       /* Rx bytes                   */
+        __be32                  tx_bytes;       /* Tx bytes                   */
+        __be32                  rx_uc_pkts;     /* Rx UC packets              */
+        __be32                  rx_mc_pkts;     /* Rx MC packets              */
+        __be32                  rx_bc_pkts;     /* Rx BC packets              */
+        __be32                  tx_uc_pkts;     /* Tx UC packets              */
+        __be32                  tx_mc_pkts;     /* Tx MC packets              */
+        __be32                  tx_bc_pkts;     /* Tx BC packets              */
+        __be32                  fcs_err;        /* FCS errors                 */
+        __be32                  align_err;      /* Alignment errors           */
+        __be32                  false_carrier;  /* False carrier detection    */
+        __be32                  runt_pkts;      /* Rx runt packets            */
+        __be32                  jabber_pkts;    /* Rx jabber packets          */
+        __be32                  rx_pause_xon;   /* Rx pause XON frames        */
+        __be32                  rx_pause_xoff;  /* Rx XOFF frames             */
+        __be32                  tx_pause_xon;   /* Tx XON frames              */
+        __be32                  tx_pause_xoff;  /* Tx XOFF frames             */
+        __be32                  tx_s_collision; /* Single collision frames    */
+        __be32                  tx_m_collision; /* Multiple collision frames  */
+        __be32                  l_collision;    /* Late collision frames      */
+        __be32                  e_collision;    /* Excessive collision frames */
+        __be32                  rx_ctl_frames;  /* Rx control frames          */
+        __be32                  rx_64_frames;   /* Rx 64-bytes frames         */
+        __be32                  rx_127_frames;  /* Rx 65-127 bytes frames     */
+        __be32                  rx_255_frames;  /* Rx 128-255 bytes frames    */
+        __be32                  rx_511_frames;  /* Rx 256-511 bytes frames    */
+        __be32                  rx_1023_frames; /* Rx 512-1023 bytes frames   */
+        __be32                  rx_1522_frames; /* Rx 1024-1522 bytes frames  */
+        __be32                  rx_9022_frames; /* Rx 1523-9022 bytes frames  */
+        __be32                  tx_64_frames;   /* Tx 64-bytes frames         */
+        __be32                  tx_127_frames;  /* Tx 65-127 bytes frames     */
+        __be32                  tx_255_frames;  /* Tx 128-255 bytes frames    */
+        __be32                  tx_511_frames;  /* Tx 256-511 bytes frames    */
+        __be32                  tx_1023_frames; /* Tx 512-1023 bytes frames   */
+        __be32                  tx_1522_frames; /* Tx 1024-1522 bytes frames  */
+        __be32                  tx_9022_frames; /* Tx 1523-9022 bytes frames  */
+        __be32                  rx_valid_bytes; /* Rx valid bytes             */
+        __be32                  rx_runt_pkts;   /* Rx error runt packets      */
+        __be32                  rx_jabber_pkts; /* Rx error jabber packets    */
+        __be32                  checksum;       /* Checksum                   */
+};
+
+/* Get NCSI Statistics */
+struct ncsi_rsp_gns_pkt {
+        struct ncsi_rsp_pkt_hdr rsp;            /* Response header         */
+        __be32                  rx_cmds;        /* Rx NCSI commands        */
+        __be32                  dropped_cmds;   /* Dropped commands        */
+        __be32                  cmd_type_errs;  /* Command type errors     */
+        __be32                  cmd_csum_errs;  /* Command checksum errors */
+        __be32                  rx_pkts;        /* Rx NCSI packets         */
+        __be32                  tx_pkts;        /* Tx NCSI packets         */
+        __be32                  tx_aen_pkts;    /* Tx AEN packets          */
+        __be32                  checksum;       /* Checksum                */
+};
+
+/* Get NCSI Pass-through Statistics */
+struct ncsi_rsp_gnpts_pkt {
+        struct ncsi_rsp_pkt_hdr rsp;            /* Response header     */
+        __be32                  tx_pkts;        /* Tx packets          */
+        __be32                  tx_dropped;     /* Tx dropped packets  */
+        __be32                  tx_channel_err; /* Tx channel errors   */
+        __be32                  tx_us_err;      /* Tx undersize errors */
+        __be32                  rx_pkts;        /* Rx packets          */
+        __be32                  rx_dropped;     /* Rx dropped packets  */
+        __be32                  rx_channel_err; /* Rx channel errors   */
+        __be32                  rx_us_err;      /* Rx undersize errors */
+        __be32                  rx_os_err;      /* Rx oversize errors  */
+        __be32                  checksum;       /* Checksum            */
+};
+
+/* AEN: Link State Change */
+struct ncsi_aen_lsc_pkt {
+        struct ncsi_aen_pkt_hdr aen;            /* AEN header      */
+        __be32                  status;         /* Link status     */
+        __be32                  oem_status;     /* OEM link status */
+        __be32                  checksum;       /* Checksum        */
+        unsigned char           pad[14];
+};
+
+/* AEN: Configuration Required */
+struct ncsi_aen_cr_pkt {
+        struct ncsi_aen_pkt_hdr aen;            /* AEN header */
+        __be32                  checksum;       /* Checksum   */
+        unsigned char           pad[22];
+};
+
+/* AEN: Host Network Controller Driver Status Change */
+struct ncsi_aen_hncdsc_pkt {
+        struct ncsi_aen_pkt_hdr aen;            /* AEN header */
+        __be32                  status;         /* Status     */
+        __be32                  checksum;       /* Checksum   */
+        unsigned char           pad[18];
+};
+
+/* NCSI packet revision */
+#define NCSI_PKT_REVISION       0x01
+
+/* NCSI packet commands */
+#define NCSI_PKT_CMD_CIS        0x00    /* Clear Initial State              */
+#define NCSI_PKT_CMD_SP         0x01    /* Select Package                   */
+#define NCSI_PKT_CMD_DP         0x02    /* Deselect Package                 */
+#define NCSI_PKT_CMD_EC         0x03    /* Enable Channel                   */
+#define NCSI_PKT_CMD_DC         0x04    /* Disable Channel                  */
+#define NCSI_PKT_CMD_RC         0x05    /* Reset Channel                    */
+#define NCSI_PKT_CMD_ECNT       0x06    /* Enable Channel Network Tx        */
+#define NCSI_PKT_CMD_DCNT       0x07    /* Disable Channel Network Tx       */
+#define NCSI_PKT_CMD_AE         0x08    /* AEN Enable                       */
+#define NCSI_PKT_CMD_SL         0x09    /* Set Link                         */
+#define NCSI_PKT_CMD_GLS        0x0a    /* Get Link                         */
+#define NCSI_PKT_CMD_SVF        0x0b    /* Set VLAN Filter                  */
+#define NCSI_PKT_CMD_EV         0x0c    /* Enable VLAN                      */
+#define NCSI_PKT_CMD_DV         0x0d    /* Disable VLAN                     */
+#define NCSI_PKT_CMD_SMA        0x0e    /* Set MAC address                  */
+#define NCSI_PKT_CMD_EBF        0x10    /* Enable Broadcast Filter          */
+#define NCSI_PKT_CMD_DBF        0x11    /* Disable Broadcast Filter         */
+#define NCSI_PKT_CMD_EGMF       0x12    /* Enable Global Multicast Filter   */
+#define NCSI_PKT_CMD_DGMF       0x13    /* Disable Global Multicast Filter  */
+#define NCSI_PKT_CMD_SNFC       0x14    /* Set NCSI Flow Control            */
+#define NCSI_PKT_CMD_GVI        0x15    /* Get Version ID                   */
+#define NCSI_PKT_CMD_GC         0x16    /* Get Capabilities                 */
+#define NCSI_PKT_CMD_GP         0x17    /* Get Parameters                   */
+#define NCSI_PKT_CMD_GCPS       0x18    /* Get Controller Packet Statistics */
+#define NCSI_PKT_CMD_GNS        0x19    /* Get NCSI Statistics              */
+#define NCSI_PKT_CMD_GNPTS      0x1a    /* Get NCSI Pass-throu Statistics   */
+#define NCSI_PKT_CMD_OEM        0x50    /* OEM                              */
+
+/* NCSI packet responses */
+#define NCSI_PKT_RSP_CIS        (NCSI_PKT_CMD_CIS + 0x80)
+#define NCSI_PKT_RSP_SP         (NCSI_PKT_CMD_SP + 0x80)
+#define NCSI_PKT_RSP_DP         (NCSI_PKT_CMD_DP + 0x80)
+#define NCSI_PKT_RSP_EC         (NCSI_PKT_CMD_EC + 0x80)
+#define NCSI_PKT_RSP_DC         (NCSI_PKT_CMD_DC + 0x80)
+#define NCSI_PKT_RSP_RC         (NCSI_PKT_CMD_RC + 0x80)
+#define NCSI_PKT_RSP_ECNT       (NCSI_PKT_CMD_ECNT + 0x80)
+#define NCSI_PKT_RSP_DCNT       (NCSI_PKT_CMD_DCNT + 0x80)
+#define NCSI_PKT_RSP_AE         (NCSI_PKT_CMD_AE + 0x80)
+#define NCSI_PKT_RSP_SL         (NCSI_PKT_CMD_SL + 0x80)
+#define NCSI_PKT_RSP_GLS        (NCSI_PKT_CMD_GLS + 0x80)
+#define NCSI_PKT_RSP_SVF        (NCSI_PKT_CMD_SVF + 0x80)
+#define NCSI_PKT_RSP_EV         (NCSI_PKT_CMD_EV + 0x80)
+#define NCSI_PKT_RSP_DV         (NCSI_PKT_CMD_DV + 0x80)
+#define NCSI_PKT_RSP_SMA        (NCSI_PKT_CMD_SMA + 0x80)
+#define NCSI_PKT_RSP_EBF        (NCSI_PKT_CMD_EBF + 0x80)
+#define NCSI_PKT_RSP_DBF        (NCSI_PKT_CMD_DBF + 0x80)
+#define NCSI_PKT_RSP_EGMF       (NCSI_PKT_CMD_EGMF + 0x80)
+#define NCSI_PKT_RSP_DGMF       (NCSI_PKT_CMD_DGMF + 0x80)
+#define NCSI_PKT_RSP_SNFC       (NCSI_PKT_CMD_SNFC + 0x80)
+#define NCSI_PKT_RSP_GVI        (NCSI_PKT_CMD_GVI + 0x80)
+#define NCSI_PKT_RSP_GC         (NCSI_PKT_CMD_GC + 0x80)
+#define NCSI_PKT_RSP_GP         (NCSI_PKT_CMD_GP + 0x80)
+#define NCSI_PKT_RSP_GCPS       (NCSI_PKT_CMD_GCPS + 0x80)
+#define NCSI_PKT_RSP_GNS        (NCSI_PKT_CMD_GNS + 0x80)
+#define NCSI_PKT_RSP_GNPTS      (NCSI_PKT_CMD_GNPTS + 0x80)
+#define NCSI_PKT_RSP_OEM        (NCSI_PKT_CMD_OEM + 0x80)
+
+/* NCSI packet type: AEN */
+#define NCSI_PKT_AEN            0xFF    /* AEN Packet               */
+#define NCSI_PKT_AEN_LSC        0x00    /* Link status change       */
+#define NCSI_PKT_AEN_CR         0x01    /* Configuration required   */
+#define NCSI_PKT_AEN_HNCDSC     0x02    /* HNC driver status change */
+
+/* NCSI response code/reason */
+#define NCSI_PKT_RSP_C_COMPLETED        0x0000  /* Command Completed        */
+#define NCSI_PKT_RSP_C_FAILED           0x0001  /* Command Failed           */
+#define NCSI_PKT_RSP_C_UNAVAILABLE      0x0002  /* Command Unavailable      */
+#define NCSI_PKT_RSP_C_UNSUPPORTED      0x0003  /* Command Unsupported      */
+#define NCSI_PKT_RSP_R_NO_ERROR         0x0000  /* No Error                 */
+#define NCSI_PKT_RSP_R_INTERFACE        0x0001  /* Interface not ready      */
+#define NCSI_PKT_RSP_R_PARAM            0x0002  /* Invalid Parameter        */
+#define NCSI_PKT_RSP_R_CHANNEL          0x0003  /* Channel not Ready        */
+#define NCSI_PKT_RSP_R_PACKAGE          0x0004  /* Package not Ready        */
+#define NCSI_PKT_RSP_R_LENGTH           0x0005  /* Invalid payload length   */
+#define NCSI_PKT_RSP_R_UNKNOWN          0x7fff  /* Command type unsupported */
+
+/* NCSI AEN packet type */
+#define NCSI_PKT_AEN_LSC                0x00    /* Link status change        */
+#define NCSI_PKT_AEN_CR                 0x01    /* Configuration required    */
+#define NCSI_PKT_AEN_HNCDSC             0x02    /* Host driver status change */
+
+#endif /* NCSI_PKT_H */
diff --git a/slirp/ncsi.c b/slirp/ncsi.c
new file mode 100644
index 000000000000..8f8f4609eff5
--- /dev/null
+++ b/slirp/ncsi.c
@@ -0,0 +1,95 @@
+/*
+ * NCSI
+ *
+ * Copyright (C) 2016 IBM Corp.
+ *
+ * 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 <slirp.h>
+
+#include "ncsi-pkt.h"
+
+#if defined(_WIN32)
+/* Windows ntohl() returns an u_long value.
+ * Add a type cast to match the format strings. */
+# define ntohl(n) ((uint32_t)ntohl(n))
+#endif
+
+/*
+ * ncsi header + checksum + max payload (NCSI_PKT_CMD_GVI)
+ */
+#define NCSI_LEN (sizeof(struct ncsi_pkt_hdr) + 4 + 36)
+
+void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
+{
+    struct ncsi_pkt_hdr *nh = (struct ncsi_pkt_hdr *)(pkt + ETH_HLEN);
+    uint8_t ncsi_reply[ETH_HLEN + NCSI_LEN];
+    struct ethhdr *reh = (struct ethhdr *)ncsi_reply;
+    struct ncsi_rsp_pkt_hdr *rnh = (struct ncsi_rsp_pkt_hdr *)
+        (ncsi_reply + ETH_HLEN);
+
+    memset(ncsi_reply, 0, sizeof(ncsi_reply));
+
+    memset(reh->h_dest, 0xff, ETH_ALEN);
+    memset(reh->h_source, 0xff, ETH_ALEN);
+    reh->h_proto = htons(ETH_P_NCSI);
+
+    rnh->common.mc_id        = nh->mc_id;
+    rnh->common.revision     = NCSI_PKT_REVISION;
+    rnh->common.reserved     = 0;
+    rnh->common.id           = nh->id;
+    rnh->common.type         = nh->type + 0x80;
+    rnh->common.channel      = nh->channel;
+    rnh->common.length       = htons(4);
+    rnh->common.reserved1[0] = 0;
+    rnh->common.reserved1[1] = 0;
+    rnh->code         = htons(NCSI_PKT_RSP_C_COMPLETED);
+    rnh->reason       = htons(NCSI_PKT_RSP_R_NO_ERROR);
+
+    switch (nh->type) {
+    case NCSI_PKT_CMD_SMA:
+        rnh->common.length = htons(4);
+        break;
+    case NCSI_PKT_CMD_GVI:
+        rnh->common.length = htons(36);
+        break;
+    case NCSI_PKT_CMD_GC: {
+        struct ncsi_rsp_gc_pkt *rsp = (struct ncsi_rsp_gc_pkt *) rnh;
+
+        rnh->common.length = htons(32);
+        rsp->cap = htonl(~0);
+        rsp->bc_cap = htonl(~0);
+        rsp->mc_cap = htonl(~0);
+        rsp->buf_cap = htonl(~0);
+        rsp->aen_cap = htonl(~0);
+        rsp->vlan_mode = 0xff;
+        rsp->uc_cnt = 2;
+        break;
+    }
+
+    case NCSI_PKT_CMD_GLS: {
+        struct ncsi_rsp_gls_pkt *rsp = (struct ncsi_rsp_gls_pkt *) rnh;
+
+        rnh->common.length = htons(16);
+        rsp->status = htonl(0x1);
+        break;
+    }
+    default:
+        break;
+    }
+
+    slirp_output(slirp->opaque, ncsi_reply, sizeof(ncsi_reply));
+}
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 6e2b4e5a9010..c445c474e7e5 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -870,6 +870,10 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
         }
         break;
 
+    case ETH_P_NCSI:
+        ncsi_input(slirp, pkt, pkt_len);
+        break;
+
     default:
         break;
     }
diff --git a/slirp/slirp.h b/slirp/slirp.h
index a1f31391341d..ef75357d4d75 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -292,6 +292,9 @@ int tcp_emu(struct socket *, struct mbuf *);
 int tcp_ctl(struct socket *);
 struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
 
+/* ncsi.c */
+void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
+
 #ifndef _WIN32
 #define min(x,y) ((x) < (y) ? (x) : (y))
 #define max(x,y) ((x) > (y) ? (x) : (y))
-- 
2.7.4

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

* [PATCH qemu 38/38] target-arm: Add VBAR support to ARM1176 CPUs
  2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
                   ` (36 preceding siblings ...)
  2016-11-18 14:22 ` [PATCH qemu 37/38] slirp: add a fake NCSI backend Cédric Le Goater
@ 2016-11-18 14:22 ` Cédric Le Goater
  2016-11-21  7:27   ` Joel Stanley
  37 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-18 14:22 UTC (permalink / raw)
  To: openbmc

ARM1176 CPUs support the Vector Base Address Register but currently,
qemu only supports VBAR on ARMv7 CPUs. Fix this by adding a new
feature ARM_FEATURE_VBAR which is used for ARMv7 and ARM1176 CPUs.

Signed-off-by: Cédric Le Goater <clg@kaod.org>

From Peter Maydell :

    Is it sufficient to set ARM_FEATURE_VBAR in the realizefn
    if FEATURE_V7 or FEATURE_EL3? (watch out that realizefn
    may change the value of the FEATURE_EL3 bit partway down
    so you'd need to do the check there) ?

    We implement VBAR in v7-without-EL3 even though architecturally
    it should only exist in v7-with-EL3 because we have some
    legacy board models which we implement as without-EL3 but
    where the guest (Linux) assumes it's running on a with-EL3
    CPU in NS mode. I'd rather we stick to the architectural
    definition for 1176 if we can rather than expanding the
    "things we do which aren't architectural" set if there's
    no legacy config that requires it. (If it is necessary
    to define it for 1176 always then that's OK, I'd just
    prefer not to unless we know we have to.)

    We should probably also have a brief comment noting that
    we define VBAR always in v7, even though architecturally
    it doesn't exist in non-EL3 configs, for the benefit of
    legacy board models.

    (In v8 VBAR is required whether EL3 is implemented or not.)

    thanks
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 target-arm/cpu.c    |  2 ++
 target-arm/cpu.h    |  1 +
 target-arm/helper.c | 18 ++++++++++++------
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 99f0dbebb9f6..f8566deb0939 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -589,6 +589,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         set_feature(env, ARM_FEATURE_LPAE);
     }
     if (arm_feature(env, ARM_FEATURE_V7)) {
+        set_feature(env, ARM_FEATURE_VBAR);
         set_feature(env, ARM_FEATURE_VAPA);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_MPIDR);
@@ -911,6 +912,7 @@ static void arm1176_initfn(Object *obj)
 
     cpu->dtb_compatible = "arm,arm1176";
     set_feature(&cpu->env, ARM_FEATURE_V6K);
+    set_feature(&cpu->env, ARM_FEATURE_VBAR);
     set_feature(&cpu->env, ARM_FEATURE_VFP);
     set_feature(&cpu->env, ARM_FEATURE_VAPA);
     set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ca5c849ed65e..c6841df8afb9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1125,6 +1125,7 @@ enum arm_features {
     ARM_FEATURE_V8_PMULL, /* implements PMULL part of v8 Crypto Extensions */
     ARM_FEATURE_THUMB_DSP, /* DSP insns supported in the Thumb encodings */
     ARM_FEATURE_PMU, /* has PMU support */
+    ARM_FEATURE_VBAR, /* has cp15 VBAR (ARM1176) */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index b5b65caadf8a..9bfffa4a4b60 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1252,12 +1252,6 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .access = PL1_RW, .accessfn = access_tpm, .type = ARM_CP_ALIAS,
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
       .writefn = pmintenclr_write },
-    { .name = "VBAR", .state = ARM_CP_STATE_BOTH,
-      .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .writefn = vbar_write,
-      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
-                             offsetof(CPUARMState, cp15.vbar_ns) },
-      .resetvalue = 0 },
     { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_RAW },
@@ -1411,6 +1405,15 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
       .resetvalue = 0 },
     REGINFO_SENTINEL
 };
+static const ARMCPRegInfo vbar_cp_reginfo[] = {
+    { .name = "VBAR", .state = ARM_CP_STATE_BOTH,
+      .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .writefn = vbar_write,
+      .bank_fieldoffsets = { offsetof(CPUARMState, cp15.vbar_s),
+                             offsetof(CPUARMState, cp15.vbar_ns) },
+      .resetvalue = 0 },
+    REGINFO_SENTINEL
+};
 
 #ifndef CONFIG_USER_ONLY
 
@@ -4506,6 +4509,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
     if (arm_feature(env, ARM_FEATURE_V6K)) {
         define_arm_cp_regs(cpu, v6k_cp_reginfo);
     }
+    if (arm_feature(env, ARM_FEATURE_VBAR)) {
+        define_arm_cp_regs(cpu, vbar_cp_reginfo);
+    }
     if (arm_feature(env, ARM_FEATURE_V7MP) &&
         !arm_feature(env, ARM_FEATURE_MPU)) {
         define_arm_cp_regs(cpu, v7mp_cp_reginfo);
-- 
2.7.4

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

* Re: [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g
  2016-11-18 14:21 ` [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-21 10:31   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/block/m25p80.c | 1 +
>  1 file changed, 1 insertion(+)

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

* Re: [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC
  2016-11-18 14:21 ` [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-21 10:59   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 17 ++++++++++++++---
>  include/hw/arm/aspeed_soc.h |  2 +-
>  2 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index e14f5c217eab..db145e201451 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -87,9 +87,13 @@ static void aspeed_soc_init(Object *obj)
>  {
>      AspeedSoCState *s = ASPEED_SOC(obj);
>      AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> +    char *cpu_typename;
>      int i;
>
> -    s->cpu = cpu_arm_init(sc->info->cpu_model);
> +    cpu_typename = g_strdup_printf("%s-" TYPE_ARM_CPU, sc->info->cpu_model);
> +    object_initialize(&s->cpu, sizeof(s->cpu), cpu_typename);
> +    object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
> +    g_free(cpu_typename);
>
>      object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
>      object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
> @@ -146,6 +150,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>      memory_region_add_subregion_overlap(get_system_memory(),
>                                          ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
>
> +    /* CPU */
> +    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
>      /* VIC */
>      object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
>      if (err) {
> @@ -154,9 +165,9 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>      }
>      sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
>      sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
> -                       qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
> +                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
>      sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
> -                       qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
> +                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
>
>      /* Timer */
>      object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
> diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> index 5406b498d7ef..6f1b679c97b1 100644
> --- a/include/hw/arm/aspeed_soc.h
> +++ b/include/hw/arm/aspeed_soc.h
> @@ -27,7 +27,7 @@ typedef struct AspeedSoCState {
>      DeviceState parent;
>
>      /*< public >*/
> -    ARMCPU *cpu;
> +    ARMCPU cpu;
>      MemoryRegion iomem;
>      AspeedVICState vic;
>      AspeedTimerCtrlState timerctrl;
> --
> 2.7.4
>
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board
  2016-11-18 14:21 ` [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-21 12:18   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The Romulus machine is an OpenPOWER system with an AST2500 SoC for
> the BMC and a POWER9 chip for the host. It does not make much
> difference for qemu a part from the fact that the FMC controller has
> two SPI flash module slaves.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 45 insertions(+)
>
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 159d562e8912..aea73f79d92c 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -41,8 +41,10 @@ typedef struct AspeedBoardConfig {
>  enum {
>      PALMETTO_BMC,
>      AST2500_EVB,
> +    ROMULUS_BMC,
>  };
>
> +/* 0x120CE416 */

Is this the value of the strap as taken from the hardware? Perhaps add
a comment to say so.

>  #define PALMETTO_BMC_HW_STRAP1 (                                        \
>          SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) |               \
>          SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
> @@ -56,6 +58,7 @@ enum {
>          SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) |                       \
>          SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
>

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

* Re: [PATCH qemu 06/38] aspeed: add a memory region for SRAM
  2016-11-18 14:21 ` [PATCH qemu 06/38] aspeed: add a memory region for SRAM Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-21 12:21   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The size of the SRAM depends on the SoC model, so use a per-soc
> definition when creating the region.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 52 +++++++++++++++++++++++++++++++++++++--------
>  include/hw/arm/aspeed_soc.h |  2 ++
>  2 files changed, 45 insertions(+), 9 deletions(-)

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

* Re: [PATCH qemu 10/38] aspeed/smc: improve segment register support
  2016-11-18 14:21 ` [PATCH qemu 10/38] aspeed/smc: improve segment register support Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  0 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The HW does not enforce all the rules in the specs and allows a few
> "curious" setups like zero size segments and overlaps. So change the
> model to be in sync but keep the warnings which are always interesting
> for debug.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/ssi/aspeed_smc.c | 17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)

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

* Re: [PATCH qemu 12/38] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines
  2016-11-18 14:21 ` [PATCH qemu 12/38] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-21 13:20   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Change the routines prototype to use a 'AspeedSMCFlash *' instead of
> 'AspeedSMCState *'. The result will help in making future changes
> clearer.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Once you've added in the one you put in patch 13:

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/ssi/aspeed_smc.c         | 37 ++++++++++++++++++++++---------------
>  include/hw/ssi/aspeed_smc.h |  2 +-
>  2 files changed, 23 insertions(+), 16 deletions(-)

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

* Re: [PATCH qemu 14/38] aspeed/smc: autostrap CE0/1 configuration
  2016-11-18 14:21 ` [PATCH qemu 14/38] aspeed/smc: autostrap CE0/1 configuration Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-25  3:07   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> HW autodetect type and size of the first and second flash modules of
> the FMC controller.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/ssi/aspeed_smc.c | 26 +++++++++++++++++++++-----
>  1 file changed, 21 insertions(+), 5 deletions(-)

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

* Re: [PATCH qemu 15/38] aspeed/smc: handle SPI flash Command mode
  2016-11-18 14:21 ` [PATCH qemu 15/38] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-25  4:23   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The Aspeed SMC controllers have a mode (Command mode) in which
> accesses to the flash content are no different than doing MMIOs. The
> controller generates all the necessary commands to load (or store)
> data in memory.
>
> However, accesses are restricted to the segment window assigned the
> the flash module by the controller. This window is defined by the
> Segment Address Register.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/ssi/aspeed_smc.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 162 insertions(+), 12 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 72a44150b0a1..eec087199a22 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c

> @@ -357,6 +368,98 @@ static inline bool aspeed_smc_is_writable(const AspeedSMCFlash *fl)
>      return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + fl->id));
>  }
>
> +static inline int aspeed_smc_flash_cmd(const AspeedSMCFlash *fl)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    int cmd = (s->regs[s->r_ctrl0 + fl->id] >> CTRL_CMD_SHIFT) & CTRL_CMD_MASK;

I would expect mask to be 0x00FF0000 and you to mask and then shift.
You appear to have the mask shifted down already, so the code is
correct, but it's unexpected.

> +
> +    /* This is the default value for read mode. In other modes, the
> +     * command should be defined */
> +    if (aspeed_smc_flash_mode(fl) == CTRL_READMODE) {
> +        cmd = SPI_OP_READ;
> +    }

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

* Re: [PATCH qemu 16/38] aspeed/smc: add tests for Command mode
  2016-11-18 14:21 ` [PATCH qemu 16/38] aspeed/smc: add tests for " Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-21 10:32     ` Cédric Le Goater
  2016-11-25  4:30   ` Andrew Jeffery
  1 sibling, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> 0005 tests add a read_page_mem test

This looks like something went wrong

>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  tests/m25p80-test.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 86 insertions(+)
>
> diff --git a/tests/m25p80-test.c b/tests/m25p80-test.c
> index cb7ec81f1a6d..3d449bd194a9 100644
> --- a/tests/m25p80-test.c
> +++ b/tests/m25p80-test.c
> @@ -36,6 +36,9 @@
>  #define   CRTL_EXTENDED0       0  /* 32 bit addressing for SPI */
>  #define R_CTRL0             0x10
>  #define   CTRL_CE_STOP_ACTIVE  (1 << 2)
> +#define   CTRL_READMODE        0x0
> +#define   CTRL_FREADMODE       0x1
> +#define   CTRL_WRITEMODE       0x2
>  #define   CTRL_USERMODE        0x3
>
>  #define ASPEED_FMC_BASE    0x1E620000
> @@ -76,6 +79,22 @@ static void spi_conf(uint32_t value)
>      writel(ASPEED_FMC_BASE + R_CONF, conf);
>  }
>
> +static void spi_ce_ctrl(uint32_t value)
> +{
> +    uint32_t conf = readl(ASPEED_FMC_BASE + R_CE_CTRL);
> +
> +    conf |= value;
> +    writel(ASPEED_FMC_BASE + R_CE_CTRL, conf);
> +}
> +
> +static void spi_ctrl_setmode(uint8_t mode, uint8_t cmd)
> +{
> +    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
> +    ctrl &= ~(CTRL_USERMODE | 0xff << 16);
> +    ctrl |= mode | (cmd << 16);
> +    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
> +}
> +
>  static void spi_ctrl_start_user(void)
>  {
>      uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
> @@ -128,6 +147,18 @@ static void read_page(uint32_t addr, uint32_t *page)
>      spi_ctrl_stop_user();
>  }
>
> +static void read_page_mem(uint32_t addr, uint32_t *page)
> +{
> +    int i;
> +
> +    /* move out USER mode to use direct reads from the AHB bus */
> +    spi_ctrl_setmode(CTRL_READMODE, READ);
> +
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        page[i] = make_be32(readl(ASPEED_FLASH_BASE + addr + i * 4));
> +    }
> +}
> +
>  static void test_erase_sector(void)
>  {
>      uint32_t some_page_addr = 0x600 * PAGE_SIZE;
> @@ -195,6 +226,7 @@ static void test_write_page(void)
>
>      spi_ctrl_start_user();
>      writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
> +    writeb(ASPEED_FLASH_BASE, WREN);
>      writeb(ASPEED_FLASH_BASE, PP);
>      writel(ASPEED_FLASH_BASE, make_be32(my_page_addr));
>
> @@ -217,6 +249,58 @@ static void test_write_page(void)
>      }
>  }
>
> +static void test_read_page_mem(void)
> +{
> +    uint32_t my_page_addr = 0x14000 * PAGE_SIZE; /* beyond 16MB */
> +    uint32_t some_page_addr = 0x15000 * PAGE_SIZE;
> +    uint32_t page[PAGE_SIZE / 4];
> +    int i;
> +
> +    /* Enable 4BYTE mode for flash. This is should be strapped by HW
> +     * for CE0 anyhow.
> +     */
> +    spi_ce_ctrl(1 << CRTL_EXTENDED0);
> +
> +    /* Check what was written */
> +    read_page_mem(my_page_addr, page);
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
> +    }
> +
> +    /* Check some other page. It should be full of 0xff */
> +    read_page_mem(some_page_addr, page);
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        g_assert_cmphex(page[i], ==, 0xffffffff);
> +    }
> +}
> +
> +static void test_write_page_mem(void)
> +{
> +    uint32_t my_page_addr = 0x15000 * PAGE_SIZE;
> +    uint32_t page[PAGE_SIZE / 4];
> +    int i;
> +
> +    /* Enable 4BYTE mode for flash. This is should be strapped by HW
> +     * for CE0 anyhow.
> +     */
> +    spi_ce_ctrl(1 << CRTL_EXTENDED0);
> +
> +    /* move out USER mode to use direct writes to the AHB bus */
> +    spi_ctrl_setmode(CTRL_WRITEMODE, PP);
> +
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        writel(ASPEED_FLASH_BASE + my_page_addr + i * 4,
> +               make_be32(my_page_addr + i * 4));
> +    }
> +
> +    /* Check what was written */
> +    read_page_mem(my_page_addr, page);
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
> +    }
> +}
> +
> +
>  static char tmp_path[] = "/tmp/qtest.m25p80.XXXXXX";
>
>  int main(int argc, char **argv)
> @@ -242,6 +326,8 @@ int main(int argc, char **argv)
>      qtest_add_func("/m25p80/erase_sector", test_erase_sector);
>      qtest_add_func("/m25p80/erase_all",  test_erase_all);
>      qtest_add_func("/m25p80/write_page", test_write_page);
> +    qtest_add_func("/m25p80/read_page_mem", test_read_page_mem);
> +    qtest_add_func("/m25p80/write_page_mem", test_write_page_mem);
>
>      ret = g_test_run();
>
> --
> 2.7.4
>
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH qemu 19/38] aspeed/smc: add support for DMAs
  2016-11-18 14:21 ` [PATCH qemu 19/38] aspeed/smc: add support for DMAs Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-21 11:07     ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Some of SMC controllers on the Aspeed SoCs support DMA to access the
> flash modules. It can operate in a normal mode, to copy to or from the
> flash module mapping window, or in a checksum calculation mode, to
> evaluate the best clock settings for reads.
>
> When DMA is enabled, a DMA request is built and passed on to a bottom
> half to handle the memory transaction. The CPU is notified of the
> completion with an IRQ if it was enabled.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/ssi/aspeed_smc.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 227 insertions(+), 7 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 24c78aa57537..9596ea94a3bc 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c

> @@ -685,6 +697,202 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
>      }
>  }
>
> +typedef struct AspeedDmaCo {
> +    AspeedSMCState *s;
> +    int len;
> +    uint32_t flash_addr;
> +    uint32_t dram_addr;
> +    uint32_t checksum;
> +    bool direction;
> +} AspeedDmaCo;

What does the "Co" part mean?

> +
> +static void coroutine_fn aspeed_smc_dma_done(AspeedDmaCo *dmaco)
> +{
> +    AspeedSMCState *s = dmaco->s;
> +
> +    s->regs[R_INTR_CTRL] |= INTR_CTRL_DMA_STATUS;
> +    if (s->regs[R_INTR_CTRL] & INTR_CTRL_DMA_EN) {
> +        qemu_irq_raise(s->irq);
> +    }
> +}

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

* Re: [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads
  2016-11-18 14:22 ` [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-21 12:50     ` Cédric Le Goater
  2016-11-28  1:35   ` Andrew Jeffery
  1 sibling, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 9596ea94a3bc..c0ae07ef8c96 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c

> @@ -525,27 +534,49 @@ static void aspeed_smc_flash_setup_read(AspeedSMCFlash *fl, uint32_t addr)
>      ssi_transfer(s->spi, (addr & 0xff));
>  }
>
> +static int aspeed_smc_flash_dummies(const AspeedSMCFlash *fl)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    uint32_t r_ctrl0 = s->regs[s->r_ctrl0 + fl->id];
> +
> +    return ((((r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1) << 2) |
> +            ((r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3)) * 8;

This is crazy :)

It might be easier to read if we had a few local variables. Might not
though, so it's up to you.

> +}
> +
> +static uint64_t aspeed_smc_flash_do_read(AspeedSMCFlash *fl, unsigned size)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    uint64_t ret = 0;
> +    int i;
> +
> +    if (fl->cmd == SPI_OP_READ_FAST) {
> +        for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
> +            ssi_transfer(s->spi, 0x0);

Do you need to check the return value here as well, like you do below?

> +        }
> +    }
> +    fl->cmd = 0;
> +
> +    for (i = 0; i < size; i++) {
> +        ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
> +    }
> +    return ret;
> +}

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

* Re: [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region
  2016-11-18 14:22 ` [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-28  1:44   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The SPI controller of the AST2400 SoC does not support DMAs and
> segment registers, hence it has less registers. So we can adjust the
> size of the memory region holding the registers depending on the
> controller type. We can also remove the guest_error logging which is
> useless as the range of the region is strict enough.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/ssi/aspeed_smc.c         | 23 ++++++++---------------
>  include/hw/ssi/aspeed_smc.h |  1 +
>  2 files changed, 9 insertions(+), 15 deletions(-)

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

* Re: [PATCH qemu 22/38] aspeed: use first SPI flash as a boot ROM
  2016-11-18 14:22 ` [PATCH qemu 22/38] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-28  1:47   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Fill a ROM region with the flash content to support U-Boot. This is a
> little hacky but until we can boot from a MMIO region, it seems
> difficult to do anything else.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
>  hw/arm/aspeed.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)

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

* Re: [PATCH qemu 24/38] aspeed/smc: use flash model option
  2016-11-18 14:22 ` [PATCH qemu 24/38] aspeed/smc: use flash model option Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  0 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> so that we can change the flash model from the command line.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed.c | 2 ++
>  1 file changed, 2 insertions(+)

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

* Re: [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller
  2016-11-18 14:22 ` [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-28  1:55   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The lock register is unlocked with a write of a special value and
> locked with a write of any other value. When unlocked, reads return
> one and when locked a zero.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/misc/aspeed_sdmc.c         | 28 +++++++++++++++++++---------
>  include/hw/misc/aspeed_sdmc.h |  1 +
>  2 files changed, 20 insertions(+), 9 deletions(-)

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

* Re: [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run
  2016-11-18 14:22 ` [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run Cédric Le Goater
@ 2016-11-21  7:25   ` Joel Stanley
  2016-11-28  2:02   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:25 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> It helps in understanding the DRAM calibration sequence which is all
> written in assembly, and may be rewritten in C one day.
>
> This provides support only for the AST2400 SoC (DDR3). AST2500 still
> uses the SOC_SCRATCH1 to pretend DRAM was already initialized.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/misc/aspeed_scu.c          |   2 +-
>  hw/misc/aspeed_sdmc.c         | 188 ++++++++++++++++++++++++++++++++++++++++++
>  include/hw/misc/aspeed_sdmc.h |   2 +-
>  3 files changed, 190 insertions(+), 2 deletions(-)

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

* Re: [PATCH qemu 27/38] hw/misc: add a TMP42{1,2,3} device model
  2016-11-18 14:22 ` [PATCH qemu 27/38] hw/misc: add a TMP42{1,2,3} device model Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  0 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Largely inspired by the TMP105 temperature sensor, here is a model for
> the TMP42{1,2,3} temperature sensors.
>
> Specs can be found here :
>
>         http://www.ti.com/lit/gpn/tmp421
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  default-configs/arm-softmmu.mak |   1 +
>  hw/misc/Makefile.objs           |   1 +
>  hw/misc/tmp421.c                | 400 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 402 insertions(+)
>  create mode 100644 hw/misc/tmp421.c

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

* Re: [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3
  2016-11-18 14:22 ` [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3 Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-22 16:57   ` Cédric Le Goater
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Temperatures can be changed from the monitor with :
>
>         (qemu) qom-set /machine/unattached/device[2] temperature0 12000
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c | 8 ++++++++
>  1 file changed, 8 insertions(+)

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

* Re: [PATCH qemu 32/38] wdt: aspeed: Fix failed reboot due to timer miscalculation
  2016-11-18 14:22 ` [PATCH qemu 32/38] wdt: aspeed: Fix failed reboot due to timer miscalculation Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  0 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> From: Andrew Jeffery <andrew@aj.id.au>
>
> The implementation was incorrectly scaling the reload value by
> nanoseconds per second. In reality the span represented by the reload
> value is determined by the selected clock, either APB or 1MHz.
>
> Test the selected clock and apply the appropriate scaling, then
> convert to nanoseconds for the timer infrastructure. Note that the APB
> rate is hard-coded and reflects the value used by the timer
> controller, and isn't necessarily an accurate representation of the
> clock configuration programmed in the SCU.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/watchdog/wdt_aspeed.c | 28 +++++++++++++++++++++++-----
>  1 file changed, 23 insertions(+), 5 deletions(-)

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

* Re: [PATCH qemu 36/38] ast2400: add a FTGMAC100 nic
  2016-11-18 14:22 ` [PATCH qemu 36/38] ast2400: add a FTGMAC100 nic Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-28  2:25   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Only the first nic, but the second shouldn't be too complex to add if
> needed.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 21 +++++++++++++++++++++
>  include/hw/arm/aspeed_soc.h |  2 ++
>  2 files changed, 23 insertions(+)

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

* Re: [PATCH qemu 37/38] slirp: add a fake NCSI backend
  2016-11-18 14:22 ` [PATCH qemu 37/38] slirp: add a fake NCSI backend Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-21 13:04     ` Cédric Le Goater
  2016-11-28  2:26   ` Andrew Jeffery
  1 sibling, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> This only reverses the NCSI packets to make the Linux driver happy.
>
> The NCSI header file <ncsi-pkt.h> comes from Linux.

It's changed a tad, can you please grab the latest version from upstream?

>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  include/net/eth.h   |   1 +
>  slirp/Makefile.objs |   2 +-
>  slirp/ncsi-pkt.h    | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  slirp/ncsi.c        |  95 +++++++++++++
>  slirp/slirp.c       |   4 +
>  slirp/slirp.h       |   3 +
>  6 files changed, 498 insertions(+), 1 deletion(-)
>  create mode 100644 slirp/ncsi-pkt.h
>  create mode 100644 slirp/ncsi.c

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

* Re: [PATCH qemu 07/38] aspeed: add the definitions for the AST2400 A1 SoC
  2016-11-18 14:21 ` [PATCH qemu 07/38] aspeed: add the definitions for the AST2400 A1 SoC Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-21 12:50   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> There is not much differences with the A0 revision a part from the DDR
> calibration.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c          | 10 ++++++++++
>  hw/misc/aspeed_scu.c         |  2 ++
>  hw/misc/aspeed_sdmc.c        |  3 +++
>  include/hw/misc/aspeed_scu.h |  1 +
>  4 files changed, 16 insertions(+)

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-18 14:21 ` [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-21  9:59     ` Cédric Le Goater
  2016-11-21 13:13   ` Andrew Jeffery
  1 sibling, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> If the second watchdog is activated, a second flash module is
> available. It should be of the same model.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Nice. We should enable WDT2 in u-boot and the device tree for ast2500 systems.

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c | 26 +++++++++++++++++++++++++-
>  1 file changed, 25 insertions(+), 1 deletion(-)

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

* Re: [PATCH qemu 08/38] aspeed: change SoC revision of the palmetto-bmc machine
  2016-11-18 14:21 ` [PATCH qemu 08/38] aspeed: change SoC revision of the palmetto-bmc machine Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-21 13:16   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The palmetto BMC machine uses a AST2400 revision A1 SoC.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>

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

* Re: [PATCH qemu 04/38] aspeed: extend the board configuration with flash models
  2016-11-18 14:21 ` [PATCH qemu 04/38] aspeed: extend the board configuration with flash models Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-21 11:07   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Future machine will use different flash models for the FMC and the SPI
> controllers.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed.c | 20 ++++++++++++++++----
>  1 file changed, 16 insertions(+), 4 deletions(-)

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

* Re: [PATCH qemu 17/38] aspeed/smc: unfold the AspeedSMCController array
  2016-11-18 14:21 ` [PATCH qemu 17/38] aspeed/smc: unfold the AspeedSMCController array Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-25  4:31   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> This is getting difficult to read. Also add a 'has_dma' field for each
> controller type.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewd-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/ssi/aspeed_smc.c         | 91 ++++++++++++++++++++++++++++++++++++---------
>  include/hw/ssi/aspeed_smc.h |  1 +
>  2 files changed, 74 insertions(+), 18 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index eec087199a22..8e7e3bd9e335 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -184,24 +184,79 @@ static const AspeedSegments aspeed_segments_ast2500_spi2[] = {
>  };

> +        .name              = "aspeed.smc.spi",
> +        .r_conf            = R_SPI_CONF,
> +        .r_ce_ctrl         = 0xff,

What does 0xff mean in this context? Should we have a #define for this?

> +        .r_ctrl0           = R_SPI_CTRL0,
> +        .r_timings         = R_SPI_TIMINGS,

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

* Re: [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper
  2016-11-18 14:21 ` [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-21 10:02     ` Cédric Le Goater
  2016-11-21 13:36   ` Andrew Jeffery
  1 sibling, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> aspeed_smc_update_cs() was uselessly looping on all CS to update their
> status.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/ssi/aspeed_smc.c | 16 ++++++----------
>  1 file changed, 6 insertions(+), 10 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 91cdc0bf1ac7..1c6c5089f265 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -408,14 +408,10 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
>      },
>  };
>
> -static void aspeed_smc_update_cs(const AspeedSMCState *s)
> +static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)

This hunk should have been in patch 12 I think.

>  {
> -    int i;
> -
> -    for (i = 0; i < s->num_cs; ++i) {
> -        qemu_set_irq(s->cs_lines[i],
> -                     aspeed_smc_is_ce_stop_active(&s->flashes[i]));
> -    }
> +    AspeedSMCState *s = fl->controller;
> +    qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
>  }

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

* Re: [PATCH qemu 18/38] aspeed/smc: add a 'sdram_base' property
  2016-11-18 14:21 ` [PATCH qemu 18/38] aspeed/smc: add a 'sdram_base' property Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-25  4:35   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The setting of the DRAM address of the DMA transaction depends on the
> DRAM base address of the SoC, so we add a property to give this
> information to the model.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 7 +++++++
>  hw/ssi/aspeed_smc.c         | 1 +
>  include/hw/ssi/aspeed_smc.h | 3 +++
>  3 files changed, 11 insertions(+)

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

* Re: [PATCH qemu 09/38] aspeed/scu: fix SCU region size
  2016-11-18 14:21 ` [PATCH qemu 09/38] aspeed/scu: fix SCU region size Cédric Le Goater
@ 2016-11-21  7:26   ` Joel Stanley
  2016-11-21  9:44     ` Cédric Le Goater
  2016-11-21 12:54   ` Andrew Jeffery
  1 sibling, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:26 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/misc/aspeed_scu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index 34e86385d837..95022d3607ad 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -86,7 +86,7 @@
>  #define BMC_DEV_ID           TO_REG(0x1A4)
>
>  #define PROT_KEY_UNLOCK 0x1688A8A8
> -#define SCU_IO_REGION_SIZE 0x20000
> +#define SCU_IO_REGION_SIZE 0x1000
>

The last register is at 0x1A4. Do we want to use that as the size?

>  static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
>       [SYS_RST_CTRL]    = 0xFFCFFEDCU,
> --
> 2.7.4
>
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH qemu 23/38] block: add a model option for MTD devices
  2016-11-18 14:22 ` [PATCH qemu 23/38] block: add a model option for MTD devices Cédric Le Goater
@ 2016-11-21  7:27   ` Joel Stanley
  2016-11-21 10:31     ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:27 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> This could be used to define the flash model to use on some boards
> definitions.

Nice, I like it.

Could we add an option specify the mac/ncsi setup of the system too?
Some hardware will have a NCSI device on one MAC and a PHY on the
other. It would be handy to be able to test those without adding a new
board.

>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  blockdev.c                | 13 +++++++++++++
>  include/sysemu/blockdev.h |  1 +
>  qemu-options.hx           |  4 +++-
>  3 files changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/blockdev.c b/blockdev.c
> index 245e1e1d177a..fcea923edf02 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -742,6 +742,10 @@ QemuOptsList qemu_legacy_drive_opts = {
>              .type = QEMU_OPT_STRING,
>              .help = "pci address (virtio only)",
>          },{
> +            .name = "model",
> +            .type = QEMU_OPT_STRING,
> +            .help = "flash model (mtd only)",
> +        },{
>              .name = "serial",
>              .type = QEMU_OPT_STRING,
>              .help = "disk serial number",
> @@ -790,6 +794,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>      bool read_only = false;
>      bool copy_on_read;
>      const char *serial;
> +    const char *model;
>      const char *filename;
>      Error *local_err = NULL;
>      int i;
> @@ -1030,6 +1035,13 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>          g_free(new_id);
>      }
>
> +   /* Add virtio block device */
> +    model = qemu_opt_get(legacy_opts, "model");
> +    if (model && type != IF_MTD) {
> +        error_report("model is not supported by this bus type");
> +        goto fail;
> +    }
> +
>      /* Add virtio block device */
>      devaddr = qemu_opt_get(legacy_opts, "addr");
>      if (devaddr && type != IF_VIRTIO) {
> @@ -1102,6 +1114,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>      dinfo->unit = unit_id;
>      dinfo->devaddr = devaddr;
>      dinfo->serial = g_strdup(serial);
> +    dinfo->model = g_strdup(model);
>
>      blk_set_legacy_dinfo(blk, dinfo);
>
> diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
> index 16432f350805..10c66e5e86a4 100644
> --- a/include/sysemu/blockdev.h
> +++ b/include/sysemu/blockdev.h
> @@ -39,6 +39,7 @@ struct DriveInfo {
>      int cyls, heads, secs, trans;
>      QemuOpts *opts;
>      char *serial;
> +    char *model;
>      QTAILQ_ENTRY(DriveInfo) next;
>  };
>
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 4a5b29f349f7..16add85bd0f5 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -517,7 +517,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive,
>      "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
>      "       [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
>      "       [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
> -    "       [,serial=s][,addr=A][,rerror=ignore|stop|report]\n"
> +    "       [,serial=s][,model=m][,addr=A][,rerror=ignore|stop|report]\n"
>      "       [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
>      "       [,readonly=on|off][,copy-on-read=on|off]\n"
>      "       [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n"
> @@ -570,6 +570,8 @@ the format.  Can be used to specify format=raw to avoid interpreting
>  an untrusted format header.
>  @item serial=@var{serial}
>  This option specifies the serial number to assign to the device.
> +@item model=@var{model}
> +This option specifies the model to use to create a flash device (if=mtd only).
>  @item addr=@var{addr}
>  Specify the controller's PCI address (if=virtio only).
>  @item werror=@var{action},rerror=@var{action}
> --
> 2.7.4
>
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH qemu 33/38] wdt: aspeed: use scu to get clock freq
  2016-11-18 14:22 ` [PATCH qemu 33/38] wdt: aspeed: use scu to get clock freq Cédric Le Goater
@ 2016-11-21  7:27   ` Joel Stanley
  0 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:27 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c              |  2 ++
>  hw/misc/aspeed_scu.c             | 12 ++++++++++++
>  hw/watchdog/wdt_aspeed.c         | 19 +++++++++++++++----
>  include/hw/misc/aspeed_scu.h     |  1 +
>  include/hw/watchdog/wdt_aspeed.h |  2 ++
>  5 files changed, 32 insertions(+), 4 deletions(-)
>
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 2926ed2dd46d..06c1f03555b1 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -173,6 +173,8 @@ static void aspeed_soc_init(Object *obj)
>      object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ASPEED_WDT);
>      object_property_add_child(obj, "wdt", OBJECT(&s->wdt), NULL);
>      qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
> +    object_property_add_const_link(OBJECT(&s->wdt), "scu", OBJECT(&s->scu),
> +                                   NULL);
>  }
>
>  static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index b5efba9121b2..3f577ca12771 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -268,6 +268,18 @@ bool is_supported_silicon_rev(uint32_t silicon_rev)
>      return false;
>  }
>
> +#define ASPEED_PLL_25MHZ    25000000
> +#define ASPEED_PLL_24MHZ    24000000
> +#define ASPEED_PLL_12MHZ    12000000
> +
> +uint32_t aspeed_scu_get_clk(AspeedSCUState *scu)
> +{
> +    if (scu->hw_strap1 & AST2400_CLK_25M_IN)
> +        return ASPEED_PLL_25MHZ;
> +    else
> +        return ASPEED_PLL_24MHZ;
> +}
> +
>  static void aspeed_scu_realize(DeviceState *dev, Error **errp)
>  {
>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> index 860d4b73e2b6..276783de90ad 100644
> --- a/hw/watchdog/wdt_aspeed.c
> +++ b/hw/watchdog/wdt_aspeed.c
> @@ -7,10 +7,12 @@
>
>  #include "qemu/osdep.h"
>  #include "qemu/log.h"
> +#include "qapi/error.h"
>  #include "sysemu/watchdog.h"
>  #include "hw/sysbus.h"
>  #include "qemu/timer.h"
>  #include "hw/watchdog/wdt_aspeed.h"
> +#include "hw/misc/aspeed_scu.h"
>
>  #define WDT_IO_REGION_SIZE      0x1000
>
> @@ -56,8 +58,6 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
>
>  }
>
> -#define PCLK_HZ 24000000
> -
>  static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
>                               unsigned size)
>  {
> @@ -82,7 +82,7 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
>
>              if (pclk) {
>                  reload = muldiv64(s->reg_reload_value, NANOSECONDS_PER_SECOND,
> -                                  PCLK_HZ) ;
> +                                  s->pclk_freq);
>              } else {
>                  reload = s->reg_reload_value * 1000;
>              }
> @@ -99,7 +99,7 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
>
>              if (pclk) {
>                  reload = muldiv64(s->reg_reload_value, NANOSECONDS_PER_SECOND,
> -                                  PCLK_HZ);
> +                                  s->pclk_freq);
>              } else {
>                  reload = s->reg_reload_value * 1000;
>              }
> @@ -177,10 +177,21 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
>  {
>      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>      AspeedWDTState *s = ASPEED_WDT(dev);
> +    Object *obj;
> +    Error *err = NULL;
>
>      s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired,
>                              dev);
>
> +    obj = object_property_get_link(OBJECT(dev), "scu", &err);
> +    if (!obj) {
> +        error_setg(errp, "%s: required link 'scu' not found: %s",
> +                   __func__, error_get_pretty(err));
> +        return;
> +    }
> +
> +    s->pclk_freq = aspeed_scu_get_clk(ASPEED_SCU(obj));
> +
>      memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_wdt_ops, s,
>                            TYPE_ASPEED_WDT, WDT_IO_REGION_SIZE);
>      sysbus_init_mmio(sbd, &s->iomem);
> diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
> index bd4ac013f997..067f9f01819d 100644
> --- a/include/hw/misc/aspeed_scu.h
> +++ b/include/hw/misc/aspeed_scu.h
> @@ -37,6 +37,7 @@ typedef struct AspeedSCUState {
>  #define AST2500_A1_SILICON_REV   0x04010303U
>
>  extern bool is_supported_silicon_rev(uint32_t silicon_rev);
> +extern uint32_t aspeed_scu_get_clk(AspeedSCUState *scu);
>
>  /*
>   * Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions
> diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
> index dbf45ae968db..0483335ecee5 100644
> --- a/include/hw/watchdog/wdt_aspeed.h
> +++ b/include/hw/watchdog/wdt_aspeed.h
> @@ -36,6 +36,8 @@ typedef struct AspeedWDTState {
>      uint32_t reg_reload_value;
>      uint32_t reg_restart;
>      uint32_t reg_ctrl;
> +
> +    uint32_t pclk_freq;
>  } AspeedWDTState;
>
>  #endif  /* ASPEED_WDT_H */
> --
> 2.7.4
>
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH qemu 38/38] target-arm: Add VBAR support to ARM1176 CPUs
  2016-11-18 14:22 ` [PATCH qemu 38/38] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
@ 2016-11-21  7:27   ` Joel Stanley
  0 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:27 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> ARM1176 CPUs support the Vector Base Address Register but currently,
> qemu only supports VBAR on ARMv7 CPUs. Fix this by adding a new
> feature ARM_FEATURE_VBAR which is used for ARMv7 and ARM1176 CPUs.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>
> From Peter Maydell :
>
>     Is it sufficient to set ARM_FEATURE_VBAR in the realizefn
>     if FEATURE_V7 or FEATURE_EL3? (watch out that realizefn
>     may change the value of the FEATURE_EL3 bit partway down
>     so you'd need to do the check there) ?
>
>     We implement VBAR in v7-without-EL3 even though architecturally
>     it should only exist in v7-with-EL3 because we have some
>     legacy board models which we implement as without-EL3 but
>     where the guest (Linux) assumes it's running on a with-EL3
>     CPU in NS mode. I'd rather we stick to the architectural
>     definition for 1176 if we can rather than expanding the
>     "things we do which aren't architectural" set if there's
>     no legacy config that requires it. (If it is necessary
>     to define it for 1176 always then that's OK, I'd just
>     prefer not to unless we know we have to.)
>
>     We should probably also have a brief comment noting that
>     we define VBAR always in v7, even though architecturally
>     it doesn't exist in non-EL3 configs, for the benefit of
>     legacy board models.
>
>     (In v8 VBAR is required whether EL3 is implemented or not.)
>
>     thanks
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Tested-by: Joel Stanley <joel@jms.id.au>


> ---
>  target-arm/cpu.c    |  2 ++
>  target-arm/cpu.h    |  1 +
>  target-arm/helper.c | 18 ++++++++++++------
>  3 files changed, 15 insertions(+), 6 deletions(-)

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

* Re: [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0
  2016-11-18 14:22 ` [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0 Cédric Le Goater
@ 2016-11-21  7:27   ` Joel Stanley
  2016-11-22 17:00   ` Cédric Le Goater
  2016-11-28  2:05   ` Andrew Jeffery
  2 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:27 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> The palmetto platform has a ds3231 RTC device but not qemu. Let's use
> a ds1338 instead which provides enough basic RTC features. Only alarms
> will be missing
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c | 4 ++++
>  1 file changed, 4 insertions(+)

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

* Re: [PATCH qemu 31/38] aspeed: add a watchdog controller
  2016-11-18 14:22 ` [PATCH qemu 31/38] aspeed: add a watchdog controller Cédric Le Goater
@ 2016-11-21  7:27   ` Joel Stanley
  2016-11-21 12:53     ` Cédric Le Goater
  2016-11-28  2:12   ` Andrew Jeffery
  1 sibling, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21  7:27 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:

I assume with this we can reboot the guest? Might be worth mentioning
in the commit message.

> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Joel Stanley <joel@jms.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 13 +++++++++++++
>  include/hw/arm/aspeed_soc.h |  2 ++
>  2 files changed, 15 insertions(+)

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

* Re: [PATCH qemu 09/38] aspeed/scu: fix SCU region size
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21  9:44     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21  9:44 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:26 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> 
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> 
>> ---
>>  hw/misc/aspeed_scu.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
>> index 34e86385d837..95022d3607ad 100644
>> --- a/hw/misc/aspeed_scu.c
>> +++ b/hw/misc/aspeed_scu.c
>> @@ -86,7 +86,7 @@
>>  #define BMC_DEV_ID           TO_REG(0x1A4)
>>
>>  #define PROT_KEY_UNLOCK 0x1688A8A8
>> -#define SCU_IO_REGION_SIZE 0x20000
>> +#define SCU_IO_REGION_SIZE 0x1000
>>
> 
> The last register is at 0x1A4. Do we want to use that as the size?

That is a good remark. 

The Aspeed specs define address space ranges for each controller
but the full window is not covered by the registers. So when 
you go beyond the last register, the HW loops back on the first 
after while. Holes are filled with 0xffffffff or 0x0. 

I suppose restricting the window to the last register is the 
best option. Event if it is possible, going beyond is a guest 
error anyhow.

Thanks,

C. 

> 
>>  static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
>>       [SYS_RST_CTRL]    = 0xFFCFFEDCU,
>> --
>> 2.7.4
>>
>> _______________________________________________
>> openbmc mailing list
>> openbmc@lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21  9:59     ` Cédric Le Goater
  2016-11-21 10:05       ` Joel Stanley
  0 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21  9:59 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:26 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
>> If the second watchdog is activated, a second flash module is
>> available. It should be of the same model.
>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> 
> Nice. We should enable WDT2 in u-boot and the device tree for ast2500 systems.

Yes. I think we have ~20s to deactivate it before the system is reseted 
to boot on CS1.
 
Thanks,

C.

> Reviewed-by: Joel Stanley <joel@jms.id.au>
> 
>> ---
>>  hw/arm/aspeed_soc.c | 26 +++++++++++++++++++++++++-
>>  1 file changed, 25 insertions(+), 1 deletion(-)

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

* Re: [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21 10:02     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 10:02 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:26 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
>> aspeed_smc_update_cs() was uselessly looping on all CS to update their
>> status.
>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> 
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> 
>> ---
>>  hw/ssi/aspeed_smc.c | 16 ++++++----------
>>  1 file changed, 6 insertions(+), 10 deletions(-)
>>
>> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
>> index 91cdc0bf1ac7..1c6c5089f265 100644
>> --- a/hw/ssi/aspeed_smc.c
>> +++ b/hw/ssi/aspeed_smc.c
>> @@ -408,14 +408,10 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
>>      },
>>  };
>>
>> -static void aspeed_smc_update_cs(const AspeedSMCState *s)
>> +static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
> 
> This hunk should have been in patch 12 I think.

ok. I will add the aspeed_smc_flash_update_cs() in the previous patch
and remove aspeed_smc_update_cs() in this one.

C.


> 
>>  {
>> -    int i;
>> -
>> -    for (i = 0; i < s->num_cs; ++i) {
>> -        qemu_set_irq(s->cs_lines[i],
>> -                     aspeed_smc_is_ce_stop_active(&s->flashes[i]));
>> -    }
>> +    AspeedSMCState *s = fl->controller;
>> +    qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
>>  }

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-21  9:59     ` Cédric Le Goater
@ 2016-11-21 10:05       ` Joel Stanley
  0 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21 10:05 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Mon, Nov 21, 2016 at 8:29 PM, Cédric Le Goater <clg@kaod.org> wrote:
> On 11/21/2016 08:26 AM, Joel Stanley wrote:
>> On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
>>> If the second watchdog is activated, a second flash module is
>>> available. It should be of the same model.
>>>
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>
>> Nice. We should enable WDT2 in u-boot and the device tree for ast2500 systems.
>
> Yes. I think we have ~20s to deactivate it before the system is reseted
> to boot on CS1.

I opened this ticket for us to track the work:

 https://github.com/openbmc/openbmc/issues/822

Cheers,

Joel

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

* Re: [PATCH qemu 23/38] block: add a model option for MTD devices
  2016-11-21  7:27   ` Joel Stanley
@ 2016-11-21 10:31     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 10:31 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:27 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
>> This could be used to define the flash model to use on some boards
>> definitions.
> 
> Nice, I like it.
> 
> Could we add an option specify the mac/ncsi setup of the system too?
> Some hardware will have a NCSI device on one MAC and a PHY on the
> other. It would be handy to be able to test those without adding a new
> board.

we could use a property at the machine level and propagate in the 
sub device models :

	-machine [type=]name[,prop[=value][,...]]

or directly use a property at the network device model.

	-device driver[,prop[=value][,...]]

C. 


>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> 
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> 
>> ---
>>  blockdev.c                | 13 +++++++++++++
>>  include/sysemu/blockdev.h |  1 +
>>  qemu-options.hx           |  4 +++-
>>  3 files changed, 17 insertions(+), 1 deletion(-)
>>
>> diff --git a/blockdev.c b/blockdev.c
>> index 245e1e1d177a..fcea923edf02 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -742,6 +742,10 @@ QemuOptsList qemu_legacy_drive_opts = {
>>              .type = QEMU_OPT_STRING,
>>              .help = "pci address (virtio only)",
>>          },{
>> +            .name = "model",
>> +            .type = QEMU_OPT_STRING,
>> +            .help = "flash model (mtd only)",
>> +        },{
>>              .name = "serial",
>>              .type = QEMU_OPT_STRING,
>>              .help = "disk serial number",
>> @@ -790,6 +794,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>>      bool read_only = false;
>>      bool copy_on_read;
>>      const char *serial;
>> +    const char *model;
>>      const char *filename;
>>      Error *local_err = NULL;
>>      int i;
>> @@ -1030,6 +1035,13 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>>          g_free(new_id);
>>      }
>>
>> +   /* Add virtio block device */
>> +    model = qemu_opt_get(legacy_opts, "model");
>> +    if (model && type != IF_MTD) {
>> +        error_report("model is not supported by this bus type");
>> +        goto fail;
>> +    }
>> +
>>      /* Add virtio block device */
>>      devaddr = qemu_opt_get(legacy_opts, "addr");
>>      if (devaddr && type != IF_VIRTIO) {
>> @@ -1102,6 +1114,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>>      dinfo->unit = unit_id;
>>      dinfo->devaddr = devaddr;
>>      dinfo->serial = g_strdup(serial);
>> +    dinfo->model = g_strdup(model);
>>
>>      blk_set_legacy_dinfo(blk, dinfo);
>>
>> diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
>> index 16432f350805..10c66e5e86a4 100644
>> --- a/include/sysemu/blockdev.h
>> +++ b/include/sysemu/blockdev.h
>> @@ -39,6 +39,7 @@ struct DriveInfo {
>>      int cyls, heads, secs, trans;
>>      QemuOpts *opts;
>>      char *serial;
>> +    char *model;
>>      QTAILQ_ENTRY(DriveInfo) next;
>>  };
>>
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index 4a5b29f349f7..16add85bd0f5 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -517,7 +517,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive,
>>      "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
>>      "       [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
>>      "       [,cache=writethrough|writeback|none|directsync|unsafe][,format=f]\n"
>> -    "       [,serial=s][,addr=A][,rerror=ignore|stop|report]\n"
>> +    "       [,serial=s][,model=m][,addr=A][,rerror=ignore|stop|report]\n"
>>      "       [,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native]\n"
>>      "       [,readonly=on|off][,copy-on-read=on|off]\n"
>>      "       [,discard=ignore|unmap][,detect-zeroes=on|off|unmap]\n"
>> @@ -570,6 +570,8 @@ the format.  Can be used to specify format=raw to avoid interpreting
>>  an untrusted format header.
>>  @item serial=@var{serial}
>>  This option specifies the serial number to assign to the device.
>> +@item model=@var{model}
>> +This option specifies the model to use to create a flash device (if=mtd only).
>>  @item addr=@var{addr}
>>  Specify the controller's PCI address (if=virtio only).
>>  @item werror=@var{action},rerror=@var{action}
>> --
>> 2.7.4
>>
>> _______________________________________________
>> openbmc mailing list
>> openbmc@lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g
  2016-11-18 14:21 ` [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-21 10:31   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 10:31 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 1024 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/block/m25p80.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index d29ff4cb4f4b..e3c1166ea6e3 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -203,6 +203,7 @@ static const FlashPartInfo known_devices[] = {
>      { INFO("mx25l25655e", 0xc22619,      0,  64 << 10, 512, 0) },
>      { INFO("mx66u51235f", 0xc2253a,      0,  64 << 10, 1024, ER_4K | ER_32K) },
>      { INFO("mx66u1g45g",  0xc2253b,      0,  64 << 10, 2048, ER_4K | ER_32K) },
> +    { INFO("mx66l1g45g",  0xc2201b,      0,  64 << 10, 2048, ER_4K | ER_32K) },

Looks like there's no flag bit for 64K erase blocks in qemu?

>  
>      /* Micron */
>      { INFO("n25q032a11",  0x20bb16,      0,  64 << 10,  64, ER_4K) },

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 16/38] aspeed/smc: add tests for Command mode
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-21 10:32     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 10:32 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:25 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
>> 0005 tests add a read_page_mem test
> 
> This looks like something went wrong

Euh, yeah I need to write a commit log for this patch ! 

C. 
>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  tests/m25p80-test.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 86 insertions(+)
>>
>> diff --git a/tests/m25p80-test.c b/tests/m25p80-test.c
>> index cb7ec81f1a6d..3d449bd194a9 100644
>> --- a/tests/m25p80-test.c
>> +++ b/tests/m25p80-test.c
>> @@ -36,6 +36,9 @@
>>  #define   CRTL_EXTENDED0       0  /* 32 bit addressing for SPI */
>>  #define R_CTRL0             0x10
>>  #define   CTRL_CE_STOP_ACTIVE  (1 << 2)
>> +#define   CTRL_READMODE        0x0
>> +#define   CTRL_FREADMODE       0x1
>> +#define   CTRL_WRITEMODE       0x2
>>  #define   CTRL_USERMODE        0x3
>>
>>  #define ASPEED_FMC_BASE    0x1E620000
>> @@ -76,6 +79,22 @@ static void spi_conf(uint32_t value)
>>      writel(ASPEED_FMC_BASE + R_CONF, conf);
>>  }
>>
>> +static void spi_ce_ctrl(uint32_t value)
>> +{
>> +    uint32_t conf = readl(ASPEED_FMC_BASE + R_CE_CTRL);
>> +
>> +    conf |= value;
>> +    writel(ASPEED_FMC_BASE + R_CE_CTRL, conf);
>> +}
>> +
>> +static void spi_ctrl_setmode(uint8_t mode, uint8_t cmd)
>> +{
>> +    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
>> +    ctrl &= ~(CTRL_USERMODE | 0xff << 16);
>> +    ctrl |= mode | (cmd << 16);
>> +    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
>> +}
>> +
>>  static void spi_ctrl_start_user(void)
>>  {
>>      uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
>> @@ -128,6 +147,18 @@ static void read_page(uint32_t addr, uint32_t *page)
>>      spi_ctrl_stop_user();
>>  }
>>
>> +static void read_page_mem(uint32_t addr, uint32_t *page)
>> +{
>> +    int i;
>> +
>> +    /* move out USER mode to use direct reads from the AHB bus */
>> +    spi_ctrl_setmode(CTRL_READMODE, READ);
>> +
>> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
>> +        page[i] = make_be32(readl(ASPEED_FLASH_BASE + addr + i * 4));
>> +    }
>> +}
>> +
>>  static void test_erase_sector(void)
>>  {
>>      uint32_t some_page_addr = 0x600 * PAGE_SIZE;
>> @@ -195,6 +226,7 @@ static void test_write_page(void)
>>
>>      spi_ctrl_start_user();
>>      writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
>> +    writeb(ASPEED_FLASH_BASE, WREN);
>>      writeb(ASPEED_FLASH_BASE, PP);
>>      writel(ASPEED_FLASH_BASE, make_be32(my_page_addr));
>>
>> @@ -217,6 +249,58 @@ static void test_write_page(void)
>>      }
>>  }
>>
>> +static void test_read_page_mem(void)
>> +{
>> +    uint32_t my_page_addr = 0x14000 * PAGE_SIZE; /* beyond 16MB */
>> +    uint32_t some_page_addr = 0x15000 * PAGE_SIZE;
>> +    uint32_t page[PAGE_SIZE / 4];
>> +    int i;
>> +
>> +    /* Enable 4BYTE mode for flash. This is should be strapped by HW
>> +     * for CE0 anyhow.
>> +     */
>> +    spi_ce_ctrl(1 << CRTL_EXTENDED0);
>> +
>> +    /* Check what was written */
>> +    read_page_mem(my_page_addr, page);
>> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
>> +        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
>> +    }
>> +
>> +    /* Check some other page. It should be full of 0xff */
>> +    read_page_mem(some_page_addr, page);
>> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
>> +        g_assert_cmphex(page[i], ==, 0xffffffff);
>> +    }
>> +}
>> +
>> +static void test_write_page_mem(void)
>> +{
>> +    uint32_t my_page_addr = 0x15000 * PAGE_SIZE;
>> +    uint32_t page[PAGE_SIZE / 4];
>> +    int i;
>> +
>> +    /* Enable 4BYTE mode for flash. This is should be strapped by HW
>> +     * for CE0 anyhow.
>> +     */
>> +    spi_ce_ctrl(1 << CRTL_EXTENDED0);
>> +
>> +    /* move out USER mode to use direct writes to the AHB bus */
>> +    spi_ctrl_setmode(CTRL_WRITEMODE, PP);
>> +
>> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
>> +        writel(ASPEED_FLASH_BASE + my_page_addr + i * 4,
>> +               make_be32(my_page_addr + i * 4));
>> +    }
>> +
>> +    /* Check what was written */
>> +    read_page_mem(my_page_addr, page);
>> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
>> +        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
>> +    }
>> +}
>> +
>> +
>>  static char tmp_path[] = "/tmp/qtest.m25p80.XXXXXX";
>>
>>  int main(int argc, char **argv)
>> @@ -242,6 +326,8 @@ int main(int argc, char **argv)
>>      qtest_add_func("/m25p80/erase_sector", test_erase_sector);
>>      qtest_add_func("/m25p80/erase_all",  test_erase_all);
>>      qtest_add_func("/m25p80/write_page", test_write_page);
>> +    qtest_add_func("/m25p80/read_page_mem", test_read_page_mem);
>> +    qtest_add_func("/m25p80/write_page_mem", test_write_page_mem);
>>
>>      ret = g_test_run();
>>
>> --
>> 2.7.4
>>
>> _______________________________________________
>> openbmc mailing list
>> openbmc@lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC
  2016-11-18 14:21 ` [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-21 10:59   ` Andrew Jeffery
  2016-11-21 14:14     ` Cédric Le Goater
  1 sibling, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 10:59 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 3286 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

With this I think we can finally drop

    dc->cannot_destroy_with_object_finalize_yet = true;

from aspeed_soc_class_init() in hw/arm/aspeed_soc.c. See commit

    ce5b1bbf624b exec: move cpu_exec_init() calls to realize functions

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 17 ++++++++++++++---
>  include/hw/arm/aspeed_soc.h |  2 +-
>  2 files changed, 15 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index e14f5c217eab..db145e201451 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -87,9 +87,13 @@ static void aspeed_soc_init(Object *obj)
>  {
>      AspeedSoCState *s = ASPEED_SOC(obj);
>      AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> +    char *cpu_typename;
>      int i;
>  
> -    s->cpu = cpu_arm_init(sc->info->cpu_model);
> +    cpu_typename = g_strdup_printf("%s-" TYPE_ARM_CPU, sc->info->cpu_model);
> +    object_initialize(&s->cpu, sizeof(s->cpu), cpu_typename);
> +    object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
> +    g_free(cpu_typename);
>  
>      object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
>      object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
> @@ -146,6 +150,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>      memory_region_add_subregion_overlap(get_system_memory(),
>                                          ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
>  
> +    /* CPU */
> +    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
>      /* VIC */
>      object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
>      if (err) {
> @@ -154,9 +165,9 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>      }
>      sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
>      sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
> -                       qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
> +                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
>      sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
> -                       qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
> +                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
>  
>      /* Timer */
>      object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
> diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> index 5406b498d7ef..6f1b679c97b1 100644
> --- a/include/hw/arm/aspeed_soc.h
> +++ b/include/hw/arm/aspeed_soc.h
> @@ -27,7 +27,7 @@ typedef struct AspeedSoCState {
>      DeviceState parent;
>  
>      /*< public >*/
> -    ARMCPU *cpu;
> +    ARMCPU cpu;
>      MemoryRegion iomem;
>      AspeedVICState vic;
>      AspeedTimerCtrlState timerctrl;

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 03/38] aspeed: attach the second SPI controller object to the SoC
  2016-11-18 14:21 ` [PATCH qemu 03/38] aspeed: attach the second SPI controller object " Cédric Le Goater
@ 2016-11-21 11:03   ` Andrew Jeffery
  2016-11-21 11:42     ` Joel Stanley
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 11:03 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 1016 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed_soc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index db145e201451..bbbbfd13862c 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -124,7 +124,7 @@ static void aspeed_soc_init(Object *obj)
>      for (i = 0; i < sc->info->spis_num; i++) {
>          object_initialize(&s->spi[i], sizeof(s->spi[i]),
>                            sc->info->spi_typename[i]);
> -        object_property_add_child(obj, "spi", OBJECT(&s->spi[i]), NULL);
> +        object_property_add_child(obj, "spi[*]", OBJECT(&s->spi[i]), NULL);

Such a curious API. I guess it's effective.

>          qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
>      }
>  

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 19/38] aspeed/smc: add support for DMAs
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-21 11:07     ` Cédric Le Goater
  2016-11-21 11:24       ` Joel Stanley
  0 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 11:07 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:25 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
>> Some of SMC controllers on the Aspeed SoCs support DMA to access the
>> flash modules. It can operate in a normal mode, to copy to or from the
>> flash module mapping window, or in a checksum calculation mode, to
>> evaluate the best clock settings for reads.
>>
>> When DMA is enabled, a DMA request is built and passed on to a bottom
>> half to handle the memory transaction. The CPU is notified of the
>> completion with an IRQ if it was enabled.
>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/ssi/aspeed_smc.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 227 insertions(+), 7 deletions(-)
>>
>> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
>> index 24c78aa57537..9596ea94a3bc 100644
>> --- a/hw/ssi/aspeed_smc.c
>> +++ b/hw/ssi/aspeed_smc.c
> 
>> @@ -685,6 +697,202 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
>>      }
>>  }
>>
>> +typedef struct AspeedDmaCo {
>> +    AspeedSMCState *s;
>> +    int len;
>> +    uint32_t flash_addr;
>> +    uint32_t dram_addr;
>> +    uint32_t checksum;
>> +    bool direction;
>> +} AspeedDmaCo;
> 
> What does the "Co" part mean?

For Coroutine. 

We could do without Coroutines but I think it makes the code a little 
cleaner when we spawn the DMAs to do the flash access or the checksum 
calculation.

I will copy a few experts on the topic as I am not one clearly.

Thanks,

C. 

>> +
>> +static void coroutine_fn aspeed_smc_dma_done(AspeedDmaCo *dmaco)
>> +{
>> +    AspeedSMCState *s = dmaco->s;
>> +
>> +    s->regs[R_INTR_CTRL] |= INTR_CTRL_DMA_STATUS;
>> +    if (s->regs[R_INTR_CTRL] & INTR_CTRL_DMA_EN) {
>> +        qemu_irq_raise(s->irq);
>> +    }
>> +}

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

* Re: [PATCH qemu 04/38] aspeed: extend the board configuration with flash models
  2016-11-18 14:21 ` [PATCH qemu 04/38] aspeed: extend the board configuration with flash models Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21 11:07   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 11:07 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 2360 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> Future machine will use different flash models for the FMC and the SPI
> controllers.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed.c | 20 ++++++++++++++++----
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index c7206fda6d85..159d562e8912 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -34,6 +34,8 @@ typedef struct AspeedBoardState {
>  typedef struct AspeedBoardConfig {
>      const char *soc_name;
>      uint32_t hw_strap1;
> +    const char *fmc_model;
> +    const char *spi_model;
>  } AspeedBoardConfig;
>  
>  enum {
> @@ -65,8 +67,18 @@ enum {
>          ~SCU_HW_STRAP_2ND_BOOT_WDT)
>  
>  static const AspeedBoardConfig aspeed_boards[] = {
> -    [PALMETTO_BMC] = { "ast2400-a0", PALMETTO_BMC_HW_STRAP1 },
> -    [AST2500_EVB]  = { "ast2500-a1", AST2500_EVB_HW_STRAP1 },
> +    [PALMETTO_BMC] = {
> +        .soc_name  = "ast2400-a0",
> +        .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
> +        .fmc_model = "n25q256a",
> +        .spi_model = "mx25l25635e",
> +    },
> +    [AST2500_EVB]  = {
> +        .soc_name  = "ast2500-a1",
> +        .hw_strap1 = AST2500_EVB_HW_STRAP1,
> +        .fmc_model = "n25q256a",
> +        .spi_model = "mx25l25635e",
> +    },
>  };
>  
>  static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
> @@ -128,8 +140,8 @@ static void aspeed_board_init(MachineState *machine,
>      object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
>                                     &error_abort);
>  
> -    aspeed_board_init_flashes(&bmc->soc.fmc, "n25q256a", &error_abort);
> -    aspeed_board_init_flashes(&bmc->soc.spi[0], "mx25l25635e", &error_abort);
> +    aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
> +    aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);
>  
>      aspeed_board_binfo.kernel_filename = machine->kernel_filename;
>      aspeed_board_binfo.initrd_filename = machine->initrd_filename;

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 19/38] aspeed/smc: add support for DMAs
  2016-11-21 11:07     ` Cédric Le Goater
@ 2016-11-21 11:24       ` Joel Stanley
  0 siblings, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21 11:24 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist

On Mon, Nov 21, 2016 at 9:37 PM, Cédric Le Goater <clg@kaod.org> wrote:
> On 11/21/2016 08:25 AM, Joel Stanley wrote:
>> On Sat, Nov 19, 2016 at 12:51 AM, Cédric Le Goater <clg@kaod.org> wrote:
>>> Some of SMC controllers on the Aspeed SoCs support DMA to access the
>>> flash modules. It can operate in a normal mode, to copy to or from the
>>> flash module mapping window, or in a checksum calculation mode, to
>>> evaluate the best clock settings for reads.
>>>
>>> When DMA is enabled, a DMA request is built and passed on to a bottom
>>> half to handle the memory transaction. The CPU is notified of the
>>> completion with an IRQ if it was enabled.
>>>
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>> ---
>>>  hw/ssi/aspeed_smc.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++--
>>>  1 file changed, 227 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
>>> index 24c78aa57537..9596ea94a3bc 100644
>>> --- a/hw/ssi/aspeed_smc.c
>>> +++ b/hw/ssi/aspeed_smc.c
>>
>>> @@ -685,6 +697,202 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
>>>      }
>>>  }
>>>
>>> +typedef struct AspeedDmaCo {
>>> +    AspeedSMCState *s;
>>> +    int len;
>>> +    uint32_t flash_addr;
>>> +    uint32_t dram_addr;
>>> +    uint32_t checksum;
>>> +    bool direction;
>>> +} AspeedDmaCo;
>>
>> What does the "Co" part mean?
>
> For Coroutine.
>
> We could do without Coroutines but I think it makes the code a little
> cleaner when we spawn the DMAs to do the flash access or the checksum
> calculation.

Cool, that's what I thought. I agree, sounds like a good idea.

Cheers,

Joel

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

* Re: [PATCH qemu 03/38] aspeed: attach the second SPI controller object to the SoC
  2016-11-21 11:03   ` Andrew Jeffery
@ 2016-11-21 11:42     ` Joel Stanley
  2016-11-21 11:57       ` Andrew Jeffery
  0 siblings, 1 reply; 142+ messages in thread
From: Joel Stanley @ 2016-11-21 11:42 UTC (permalink / raw)
  To: Andrew Jeffery; +Cc: Cédric Le Goater, OpenBMC Maillist

On Mon, Nov 21, 2016 at 9:33 PM, Andrew Jeffery <andrew@aj.id.au> wrote:
> On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>
> Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
>
>> ---
>>  hw/arm/aspeed_soc.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
>> index db145e201451..bbbbfd13862c 100644
>> --- a/hw/arm/aspeed_soc.c
>> +++ b/hw/arm/aspeed_soc.c
>> @@ -124,7 +124,7 @@ static void aspeed_soc_init(Object *obj)
>>      for (i = 0; i < sc->info->spis_num; i++) {
>>          object_initialize(&s->spi[i], sizeof(s->spi[i]),
>>                            sc->info->spi_typename[i]);
>> -        object_property_add_child(obj, "spi", OBJECT(&s->spi[i]), NULL);
>> +        object_property_add_child(obj, "spi[*]", OBJECT(&s->spi[i]), NULL);
>
> Such a curious API. I guess it's effective.

I didn't review this one because wtf is with that *?

Cheers,

Joel

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

* Re: [PATCH qemu 03/38] aspeed: attach the second SPI controller object to the SoC
  2016-11-21 11:42     ` Joel Stanley
@ 2016-11-21 11:57       ` Andrew Jeffery
  2016-11-21 13:14         ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 11:57 UTC (permalink / raw)
  To: Joel Stanley; +Cc: Cédric Le Goater, OpenBMC Maillist

[-- Attachment #1: Type: text/plain, Size: 1448 bytes --]

On Mon, 2016-11-21 at 22:12 +1030, Joel Stanley wrote:
> > On Mon, Nov 21, 2016 at 9:33 PM, Andrew Jeffery <andrew@aj.id.au> wrote:
> > On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> > > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > 
> > > > Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
> > 
> > > ---
> > >  hw/arm/aspeed_soc.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > > index db145e201451..bbbbfd13862c 100644
> > > --- a/hw/arm/aspeed_soc.c
> > > +++ b/hw/arm/aspeed_soc.c
> > > @@ -124,7 +124,7 @@ static void aspeed_soc_init(Object *obj)
> > >      for (i = 0; i < sc->info->spis_num; i++) {
> > >          object_initialize(&s->spi[i], sizeof(s->spi[i]),
> > >                            sc->info->spi_typename[i]);
> > > -        object_property_add_child(obj, "spi", OBJECT(&s->spi[i]), NULL);
> > > +        object_property_add_child(obj, "spi[*]", OBJECT(&s->spi[i]), NULL);
> > 
> > Such a curious API. I guess it's effective.
> 
> I didn't review this one because wtf is with that *?

According the code it means "keep incrementing a counter until you
generate a unique object name and successfully register the object".
AKA the 'i' we already use here, just the API doesn't provide an
argument to pass it.

> 
> Cheers,
> 
> Joel

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board
  2016-11-18 14:21 ` [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-21 12:18   ` Andrew Jeffery
  2016-11-21 14:44     ` Cédric Le Goater
  1 sibling, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 12:18 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 5129 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> The Romulus machine is an OpenPOWER system with an AST2500 SoC for
> the BMC and a POWER9 chip for the host. It does not make much
> difference for qemu a part from the fact that the FMC controller has
> two SPI flash module slaves.
> 
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/arm/aspeed.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 45 insertions(+)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 159d562e8912..aea73f79d92c 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -41,8 +41,10 @@ typedef struct AspeedBoardConfig {
>  enum {
>      PALMETTO_BMC,
>      AST2500_EVB,
> +    ROMULUS_BMC,
>  };
>  
> +/* 0x120CE416 */
>  #define PALMETTO_BMC_HW_STRAP1 (                                        \
>          SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) |               \
>          SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
> @@ -56,6 +58,7 @@ enum {
>          SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) |                       \
>          SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
>  
> +/* 0xF100C2E6 */
>  #define AST2500_EVB_HW_STRAP1 ((                                        \
>          AST2500_HW_STRAP1_DEFAULTS |                                    \
>          SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
> @@ -66,6 +69,17 @@ enum {
>          SCU_HW_STRAP_MAC0_RGMII) &                                      \
>          ~SCU_HW_STRAP_2ND_BOOT_WDT)
>  
> +/* 0xF10AE216 */
> +#define ROMULUS_BMC_HW_STRAP1 (                                     \
> +        AST2500_HW_STRAP1_DEFAULTS |                                    \

In the defaults it says we define 16MB VGA memory, but how do we strap
for that? It doesn't look like you can set bit 2 from the strapping
table, and if we're setting bit 3 as 0 then we're getting either 8 or
32MB of memory. Is there a typo in the datasheet?

> +        SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
> +        SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE |                        \
> +        SCU_AST2500_HW_STRAP_UART_DEBUG |                               \
> +        SCU_AST2500_HW_STRAP_DDR4_ENABLE |                              \
> +        SCU_AST2500_HW_STRAP_ACPI_ENABLE |                              \

Hello? Is that you Jon??

Does anyone know why we're enabling ACPI on Romulus?

> +        SCU_HW_STRAP_SPI_WIDTH |                                        \
> +        SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN))

According to the schematic I have we're setting bit 27 (Fast reset mode
for ARM ICE debugger). But apparently that's not what's been read off
some existing Romulus?

> +
>  static const AspeedBoardConfig aspeed_boards[] = {
>      [PALMETTO_BMC] = {
>          .soc_name  = "ast2400-a0",
> @@ -79,6 +93,12 @@ static const AspeedBoardConfig aspeed_boards[] = {
>          .fmc_model = "n25q256a",
>          .spi_model = "mx25l25635e",
>      },
> +    [ROMULUS_BMC]  = {
> +        .soc_name  = "ast2500-a1",
> +        .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
> +        .fmc_model = "n25q256a",
> +        .spi_model = "mx66l1g45g",
> +    },
>  };
>  
>  static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
> @@ -200,10 +220,35 @@ static const TypeInfo ast2500_evb_type = {
>      .class_init = ast2500_evb_class_init,
>  };
>  
> +static void romulus_bmc_init(MachineState *machine)
> +{
> +    aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]);
> +}
> +
> +static void romulus_bmc_class_init(ObjectClass *oc, void *data)
> +{
> +    MachineClass *mc = MACHINE_CLASS(oc);
> +
> +    mc->desc = "OpenPOWER Romulus BMC (ARM1176)";
> +    mc->init = romulus_bmc_init;
> +    mc->max_cpus = 1;
> +    mc->no_sdcard = 1;
> +    mc->no_floppy = 1;
> +    mc->no_cdrom = 1;
> +    mc->no_parallel = 1;
> +}
> +
> +static const TypeInfo romulus_bmc_type = {
> +    .name = MACHINE_TYPE_NAME("romulus-bmc"),
> +    .parent = TYPE_MACHINE,
> +    .class_init = romulus_bmc_class_init,
> +};
> +
>  static void aspeed_machine_init(void)
>  {
>      type_register_static(&palmetto_bmc_type);
>      type_register_static(&ast2500_evb_type);
> +    type_register_static(&romulus_bmc_type);
>  }
>  
>  type_init(aspeed_machine_init)

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 06/38] aspeed: add a memory region for SRAM
  2016-11-18 14:21 ` [PATCH qemu 06/38] aspeed: add a memory region for SRAM Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-21 12:21   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 12:21 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 4883 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> The size of the SRAM depends on the SoC model, so use a per-soc
> definition when creating the region.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 52 +++++++++++++++++++++++++++++++++++++--------
>  include/hw/arm/aspeed_soc.h |  2 ++
>  2 files changed, 45 insertions(+), 9 deletions(-)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index bbbbfd13862c..387b712d8fd5 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -29,6 +29,7 @@
>  #define ASPEED_SOC_VIC_BASE         0x1E6C0000
>  #define ASPEED_SOC_SDMC_BASE        0x1E6E0000
>  #define ASPEED_SOC_SCU_BASE         0x1E6E2000
> +#define ASPEED_SOC_SRAM_BASE        0x1E720000
>  #define ASPEED_SOC_TIMER_BASE       0x1E782000
>  #define ASPEED_SOC_I2C_BASE         0x1E78A000
>  
> @@ -47,15 +48,37 @@ static const char *aspeed_soc_ast2500_typenames[] = {
>      "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
>  
>  static const AspeedSoCInfo aspeed_socs[] = {
> -    { "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE,
> -      1, aspeed_soc_ast2400_spi_bases,
> -      "aspeed.smc.fmc", aspeed_soc_ast2400_typenames },
> -    { "ast2400",    "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE,
> -      1, aspeed_soc_ast2400_spi_bases,
> -     "aspeed.smc.fmc", aspeed_soc_ast2400_typenames },
> -    { "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE,
> -      2, aspeed_soc_ast2500_spi_bases,
> -      "aspeed.smc.ast2500-fmc", aspeed_soc_ast2500_typenames },
> +    {
> +        .name         = "ast2400-a0",
> +        .cpu_model    = "arm926",
> +        .silicon_rev  = AST2400_A0_SILICON_REV,
> +        .sdram_base   = AST2400_SDRAM_BASE,
> +        .sram_size    = 0x8000,
> +        .spis_num     = 1,
> +        .spi_bases    = aspeed_soc_ast2400_spi_bases,
> +        .fmc_typename = "aspeed.smc.fmc",
> +        .spi_typename = aspeed_soc_ast2400_typenames,
> +    }, {
> +        .name         = "ast2400",
> +        .cpu_model    = "arm926",
> +        .silicon_rev  = AST2400_A0_SILICON_REV,
> +        .sdram_base   = AST2400_SDRAM_BASE,
> +        .sram_size    = 0x8000,
> +        .spis_num     = 1,
> +        .spi_bases    = aspeed_soc_ast2400_spi_bases,
> +        .fmc_typename = "aspeed.smc.fmc",
> +        .spi_typename = aspeed_soc_ast2400_typenames,
> +    }, {
> +        .name         = "ast2500-a1",
> +        .cpu_model    = "arm1176",
> +        .silicon_rev  = AST2500_A1_SILICON_REV,
> +        .sdram_base   = AST2500_SDRAM_BASE,
> +        .sram_size    = 0x9000,
> +        .spis_num     = 2,
> +        .spi_bases    = aspeed_soc_ast2500_spi_bases,
> +        .fmc_typename = "aspeed.smc.ast2500-fmc",
> +        .spi_typename = aspeed_soc_ast2500_typenames,
> +    },
>  };
>  
>  /*
> @@ -157,6 +180,17 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> +    /* SRAM */
> +    memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
> +                           sc->info->sram_size, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    vmstate_register_ram_global(&s->sram);
> +    memory_region_add_subregion(get_system_memory(), ASPEED_SOC_SRAM_BASE,
> +                                &s->sram);
> +
>      /* VIC */
>      object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
>      if (err) {
> diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> index 6f1b679c97b1..1ab5deaa0813 100644
> --- a/include/hw/arm/aspeed_soc.h
> +++ b/include/hw/arm/aspeed_soc.h
> @@ -29,6 +29,7 @@ typedef struct AspeedSoCState {
>      /*< public >*/
>      ARMCPU cpu;
>      MemoryRegion iomem;
> +    MemoryRegion sram;
>      AspeedVICState vic;
>      AspeedTimerCtrlState timerctrl;
>      AspeedI2CState i2c;
> @@ -46,6 +47,7 @@ typedef struct AspeedSoCInfo {
>      const char *cpu_model;
>      uint32_t silicon_rev;
>      hwaddr sdram_base;
> +    uint64_t sram_size;
>      int spis_num;
>      const hwaddr *spi_bases;
>      const char *fmc_typename;

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-21 12:50     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 12:50 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:25 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
>> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
>> index 9596ea94a3bc..c0ae07ef8c96 100644
>> --- a/hw/ssi/aspeed_smc.c
>> +++ b/hw/ssi/aspeed_smc.c
> 
>> @@ -525,27 +534,49 @@ static void aspeed_smc_flash_setup_read(AspeedSMCFlash *fl, uint32_t addr)
>>      ssi_transfer(s->spi, (addr & 0xff));
>>  }
>>
>> +static int aspeed_smc_flash_dummies(const AspeedSMCFlash *fl)
>> +{
>> +    AspeedSMCState *s = fl->controller;
>> +    uint32_t r_ctrl0 = s->regs[s->r_ctrl0 + fl->id];
>> +
>> +    return ((((r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1) << 2) |
>> +            ((r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3)) * 8;
> 
> This is crazy :)

Isn't that lovely :) 

Here's another nice one that we have merged already :

	https://github.com/openbmc/qemu/blob/master/include/hw/misc/aspeed_scu.h#L100

> It might be easier to read if we had a few local variables. Might not
> though, so it's up to you.

yeah. This is not a macro. I can add a dummy_low and a dummy_high to ease
reading.

>> +}
>> +
>> +static uint64_t aspeed_smc_flash_do_read(AspeedSMCFlash *fl, unsigned size)
>> +{
>> +    AspeedSMCState *s = fl->controller;
>> +    uint64_t ret = 0;
>> +    int i;
>> +
>> +    if (fl->cmd == SPI_OP_READ_FAST) {
>> +        for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
>> +            ssi_transfer(s->spi, 0x0);
> 
> Do you need to check the return value here as well, like you do below?

no we don't. the m25p80 model simulates dummy cycles with dummy writes, so
we can discard the return value which is a zero.

C. 

>> +        }
>> +    }
>> +    fl->cmd = 0;
>> +
>> +    for (i = 0; i < size; i++) {
>> +        ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
>> +    }
>> +    return ret;
>> +}

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

* Re: [PATCH qemu 07/38] aspeed: add the definitions for the AST2400 A1 SoC
  2016-11-18 14:21 ` [PATCH qemu 07/38] aspeed: add the definitions for the AST2400 A1 SoC Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21 12:50   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 12:50 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 4103 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> There is not much differences with the A0 revision a part from the DDR
> calibration.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed_soc.c          | 10 ++++++++++
>  hw/misc/aspeed_scu.c         |  2 ++
>  hw/misc/aspeed_sdmc.c        |  3 +++
>  include/hw/misc/aspeed_scu.h |  1 +
>  4 files changed, 16 insertions(+)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 387b712d8fd5..503efe0f5f77 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -59,6 +59,16 @@ static const AspeedSoCInfo aspeed_socs[] = {
>          .fmc_typename = "aspeed.smc.fmc",
>          .spi_typename = aspeed_soc_ast2400_typenames,
>      }, {
> +        .name         = "ast2400-a1",
> +        .cpu_model    = "arm926",
> +        .silicon_rev  = AST2400_A1_SILICON_REV,
> +        .sdram_base   = AST2400_SDRAM_BASE,
> +        .sram_size    = 0x8000,
> +        .spis_num     = 1,
> +        .spi_bases    = aspeed_soc_ast2400_spi_bases,
> +        .fmc_typename = "aspeed.smc.fmc",
> +        .spi_typename = aspeed_soc_ast2400_typenames,
> +    }, {
>          .name         = "ast2400",
>          .cpu_model    = "arm926",
>          .silicon_rev  = AST2400_A0_SILICON_REV,
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index b1f3e6f6b87a..34e86385d837 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -231,6 +231,7 @@ static void aspeed_scu_reset(DeviceState *dev)
>  
>      switch (s->silicon_rev) {
>      case AST2400_A0_SILICON_REV:
> +    case AST2400_A1_SILICON_REV:
>          reset = ast2400_a0_resets;
>          break;
>      case AST2500_A0_SILICON_REV:
> @@ -249,6 +250,7 @@ static void aspeed_scu_reset(DeviceState *dev)
>  
>  static uint32_t aspeed_silicon_revs[] = {
>      AST2400_A0_SILICON_REV,
> +    AST2400_A1_SILICON_REV,
>      AST2500_A0_SILICON_REV,
>      AST2500_A1_SILICON_REV,
>  };
> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
> index 8830dc084c38..5f3ac0b6f608 100644
> --- a/hw/misc/aspeed_sdmc.c
> +++ b/hw/misc/aspeed_sdmc.c
> @@ -119,6 +119,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>          /* Make sure readonly bits are kept */
>          switch (s->silicon_rev) {
>          case AST2400_A0_SILICON_REV:
> +        case AST2400_A1_SILICON_REV:
>              data &= ~ASPEED_SDMC_READONLY_MASK;
>              break;
>          case AST2500_A0_SILICON_REV:
> @@ -193,6 +194,7 @@ static void aspeed_sdmc_reset(DeviceState *dev)
>      /* Set ram size bit and defaults values */
>      switch (s->silicon_rev) {
>      case AST2400_A0_SILICON_REV:
> +    case AST2400_A1_SILICON_REV:
>          s->regs[R_CONF] |=
>              ASPEED_SDMC_VGA_COMPAT |
>              ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
> @@ -224,6 +226,7 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
>  
>      switch (s->silicon_rev) {
>      case AST2400_A0_SILICON_REV:
> +    case AST2400_A1_SILICON_REV:
>          s->ram_bits = ast2400_rambits(s);
>          break;
>      case AST2500_A0_SILICON_REV:
> diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
> index 14ffc43de809..bd4ac013f997 100644
> --- a/include/hw/misc/aspeed_scu.h
> +++ b/include/hw/misc/aspeed_scu.h
> @@ -32,6 +32,7 @@ typedef struct AspeedSCUState {
>  } AspeedSCUState;
>  
>  #define AST2400_A0_SILICON_REV   0x02000303U
> +#define AST2400_A1_SILICON_REV   0x02010303U
>  #define AST2500_A0_SILICON_REV   0x04000303U
>  #define AST2500_A1_SILICON_REV   0x04010303U
>  

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 31/38] aspeed: add a watchdog controller
  2016-11-21  7:27   ` Joel Stanley
@ 2016-11-21 12:53     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 12:53 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:27 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
> 
> I assume with this we can reboot the guest? Might be worth mentioning
> in the commit message.

yes. The commit message is a bit short :) we need to write a minimum 
one.

>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> 
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> 
>> ---
>>  hw/arm/aspeed_soc.c         | 13 +++++++++++++
>>  include/hw/arm/aspeed_soc.h |  2 ++
>>  2 files changed, 15 insertions(+)

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

* Re: [PATCH qemu 09/38] aspeed/scu: fix SCU region size
  2016-11-18 14:21 ` [PATCH qemu 09/38] aspeed/scu: fix SCU region size Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21 12:54   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 12:54 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 256 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/misc/aspeed_scu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model
  2016-11-18 14:22 ` [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model Cédric Le Goater
@ 2016-11-21 13:03   ` Cédric Le Goater
  2016-11-21 13:23     ` Joel Stanley
  2016-11-28  2:11     ` Andrew Jeffery
  0 siblings, 2 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 13:03 UTC (permalink / raw)
  To: openbmc; +Cc: Andrew Jeffery, Joel Stanley

On 11/18/2016 03:22 PM, Cédric Le Goater wrote:
> From: Joel Stanley <joel@jms.id.au>
> 
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> [clg: fixed compile breakage
>       fixed io region size
>       added  watchdog_perform_action() on timer expiry ]
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/watchdog/Makefile.objs        |   1 +
>  hw/watchdog/wdt_aspeed.c         | 194 +++++++++++++++++++++++++++++++++++++++
>  include/hw/watchdog/wdt_aspeed.h |  41 +++++++++
>  3 files changed, 236 insertions(+)
>  create mode 100644 hw/watchdog/wdt_aspeed.c
>  create mode 100644 include/hw/watchdog/wdt_aspeed.h
> 
> diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
> index 72e3ffd93c59..9589bed63a3d 100644
> --- a/hw/watchdog/Makefile.objs
> +++ b/hw/watchdog/Makefile.objs
> @@ -2,3 +2,4 @@ common-obj-y += watchdog.o
>  common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
>  common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
>  common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
> +common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o
> diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> new file mode 100644
> index 000000000000..29d9d7f91463
> --- /dev/null
> +++ b/hw/watchdog/wdt_aspeed.c
> @@ -0,0 +1,194 @@
> +/*
> + * Copyright 2016 IBM Corporation
> + *
> + * This code is licensed under the GPL version 2 or later.  See
> + * the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "sysemu/watchdog.h"
> +#include "hw/sysbus.h"
> +#include "qemu/timer.h"
> +#include "hw/watchdog/wdt_aspeed.h"
> +
> +#define WDT_IO_REGION_SIZE      0x1000
> +
> +#define WDT_STATUS              0x00
> +#define WDT_RELOAD_VALUE        0x04
> +#define WDT_RESTART             0x08
> +#define WDT_CTRL                0x0C
> +#define WDT_TIMEOUT_STATUS      0x10
> +#define WDT_TIMEOUT_CLEAR       0x14
> +#define WDT_RESET_WDITH         0x18


May be we should reduce the size of WDT_IO_REGION_SIZE to 0x20
to instantiate the three watchdog of the Aspeed AST2500 with 
one class ? 

Here is the layout :

WDT00: WDT1 Counter Status Register
WDT04: WDT1 Counter Reload Value Register
WDT08: WDT1 Counter Restart Register
WDT0C: WDT1 Control Register
WDT10: WDT1 Timeout Status Register
WDT14: WDT1 Clear Timeout Status Register
WDT18: WDT1 Reset Width Register
WDT1C: WDT1 Reset Mask Register (AST2500)

WDT20: WDT2 Counter Status Register
WDT24: WDT2 Counter Reload Value Register
WDT28: WDT2 Counter Restart Register
WDT2C: WDT2 Control Register
WDT30: WDT2 Timeout Status Register
WDT34: WDT2 Clear Timeout Status Register
WDT38: WDT2 Reset Width Register
WDT3C: WDT2 Reset Mask Register  (AST2500)

WDT40: WDT3 Counter Status Register  (AST2500)
WDT44: WDT3 Counter Reload Value Register  (AST2500)
WDT48: WDT3 Counter Restart Register  (AST2500)
WDT4C: WDT3 Control Register  (AST2500)
WDT50: WDT3 Timeout Status Register  (AST2500)
WDT54: WDT3 Clear Timeout Status Register  (AST2500)
WDT5C: WDT3 Reset Mask Register  (AST2500)

C.




> +#define WDT_RESTART_MAGIC       0x4755
> +
> +static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
> +{
> +    AspeedWDTState *s = ASPEED_WDT(opaque);
> +
> +    switch (offset) {
> +    case WDT_STATUS:
> +        return s->reg_status;
> +    case WDT_RELOAD_VALUE:
> +        return s->reg_reload_value;
> +    case WDT_RESTART:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: read from write-only reg at offset 0x%"
> +                      HWADDR_PRIx "\n", __func__, offset);
> +        return 0;
> +    case WDT_CTRL:
> +        return s->reg_ctrl;
> +    case WDT_TIMEOUT_STATUS:
> +    case WDT_TIMEOUT_CLEAR:
> +    case WDT_RESET_WDITH:
> +        qemu_log_mask(LOG_UNIMP,
> +                      "%s: uninmplemented read at offset 0x%" HWADDR_PRIx "\n",
> +                      __func__, offset);
> +        return 0;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
> +                      __func__, offset);
> +        return 0;
> +    }
> +
> +}
> +
> +static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
> +                             unsigned size)
> +{
> +    AspeedWDTState *s = ASPEED_WDT(opaque);
> +    bool en = data & BIT(0);
> +
> +    switch (offset) {
> +    case WDT_STATUS:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: write to read-only reg at offset 0x%"
> +                      HWADDR_PRIx "\n", __func__, offset);
> +        break;
> +    case WDT_RELOAD_VALUE:
> +        s->reg_reload_value = data;
> +        break;
> +    case WDT_RESTART:
> +        if ((data & 0xFFFF) == 0x4755) {
> +            s->reg_status = s->reg_reload_value;
> +
> +            if (s->enabled) {
> +                timer_mod(s->timer,
> +                          qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
> +                          s->reg_reload_value * NANOSECONDS_PER_SECOND);
> +            }
> +        }
> +        break;
> +    case WDT_CTRL:
> +        if (en && !s->enabled) {
> +            s->enabled = true;
> +            timer_mod(s->timer,
> +                      qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
> +                      s->reg_reload_value * NANOSECONDS_PER_SECOND);
> +        } else if (!en && s->enabled) {
> +            s->enabled = false;
> +            timer_del(s->timer);
> +        }
> +        break;
> +    case WDT_TIMEOUT_STATUS:
> +    case WDT_TIMEOUT_CLEAR:
> +    case WDT_RESET_WDITH:
> +        qemu_log_mask(LOG_UNIMP,
> +                      "%s: uninmplemented write at offset 0x%" HWADDR_PRIx "\n",
> +                      __func__, offset);
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> +                      __func__, offset);
> +    }
> +    return;
> +}
> +
> +static WatchdogTimerModel model = {
> +    .wdt_name = TYPE_ASPEED_WDT,
> +    .wdt_description = "aspeed watchdog device",
> +};
> +
> +static const VMStateDescription vmstate_aspeed_wdt = {
> +    .name = "vmstate_aspeed_wdt",
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_TIMER_PTR(timer, AspeedWDTState),
> +        VMSTATE_BOOL(enabled, AspeedWDTState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const MemoryRegionOps aspeed_wdt_ops = {
> +    .read = aspeed_wdt_read,
> +    .write = aspeed_wdt_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +    .valid.min_access_size = 4,
> +    .valid.max_access_size = 4,
> +    .valid.unaligned = false,
> +};
> +
> +static void aspeed_wdt_reset(DeviceState *dev)
> +{
> +    AspeedWDTState *s = ASPEED_WDT(dev);
> +
> +    s->reg_status = 0x3EF1480;
> +    s->reg_reload_value = 0x03EF1480;
> +    s->reg_restart = 0;
> +    s->reg_ctrl = 0;
> +
> +    s->enabled = false;
> +    timer_del(s->timer);
> +}
> +
> +static void aspeed_wdt_timer_expired(void *dev)
> +{
> +    AspeedWDTState *s = ASPEED_WDT(dev);
> +
> +    qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
> +    watchdog_perform_action();
> +    timer_del(s->timer);
> +}
> +
> +static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
> +{
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    AspeedWDTState *s = ASPEED_WDT(dev);
> +
> +    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired,
> +                            dev);
> +
> +    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_wdt_ops, s,
> +                          TYPE_ASPEED_WDT, WDT_IO_REGION_SIZE);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +}
> +
> +static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = aspeed_wdt_realize;
> +    dc->reset = aspeed_wdt_reset;
> +    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> +    dc->vmsd = &vmstate_aspeed_wdt;
> +}
> +
> +static const TypeInfo aspeed_wdt_info = {
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .name  = TYPE_ASPEED_WDT,
> +    .instance_size  = sizeof(AspeedWDTState),
> +    .class_init = aspeed_wdt_class_init,
> +};
> +
> +static void wdt_aspeed_register_types(void)
> +{
> +    watchdog_add_model(&model);
> +    type_register_static(&aspeed_wdt_info);
> +}
> +
> +type_init(wdt_aspeed_register_types)
> diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
> new file mode 100644
> index 000000000000..dbf45ae968db
> --- /dev/null
> +++ b/include/hw/watchdog/wdt_aspeed.h
> @@ -0,0 +1,41 @@
> +/*
> + * ASPEED Watchdog Controller
> + *
> + * Copyright (C) 2016 IBM Corp.
> + *
> + * This code is licensed under the GPL version 2 or later. See the
> + * COPYING file in the top-level directory.
> + */
> +#ifndef ASPEED_WDT_H
> +#define ASPEED_WDT_H
> +
> +#include "hw/sysbus.h"
> +
> +#define TYPE_ASPEED_WDT "aspeed.wdt"
> +#define ASPEED_WDT(obj) \
> +    OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT)
> +#define ASPEED_WDT_CLASS(klass) \
> +    OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT)
> +#define ASPEED_WDT_GET_CLASS(obj) \
> +    OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT)
> +
> +#define WDT_ASPEED_INIT      0
> +#define WDT_ASPEED_CHANGE    1
> +#define WDT_ASPEED_CANCEL    2
> +
> +typedef struct AspeedWDTState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    QEMUTimer *timer;
> +    bool enabled;
> +
> +    /*< public >*/
> +    MemoryRegion iomem;
> +
> +    uint32_t reg_status;
> +    uint32_t reg_reload_value;
> +    uint32_t reg_restart;
> +    uint32_t reg_ctrl;
> +} AspeedWDTState;
> +
> +#endif  /* ASPEED_WDT_H */
> 

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

* Re: [PATCH qemu 37/38] slirp: add a fake NCSI backend
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21 13:04     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 13:04 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 08:26 AM, Joel Stanley wrote:
> On Sat, Nov 19, 2016 at 12:52 AM, Cédric Le Goater <clg@kaod.org> wrote:
>> This only reverses the NCSI packets to make the Linux driver happy.
>>
>> The NCSI header file <ncsi-pkt.h> comes from Linux.
> 
> It's changed a tad, can you please grab the latest version from upstream?

sure.

C.

>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  include/net/eth.h   |   1 +
>>  slirp/Makefile.objs |   2 +-
>>  slirp/ncsi-pkt.h    | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  slirp/ncsi.c        |  95 +++++++++++++
>>  slirp/slirp.c       |   4 +
>>  slirp/slirp.h       |   3 +
>>  6 files changed, 498 insertions(+), 1 deletion(-)
>>  create mode 100644 slirp/ncsi-pkt.h
>>  create mode 100644 slirp/ncsi.c

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-18 14:21 ` [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21 13:13   ` Andrew Jeffery
  2016-11-21 13:29     ` Cédric Le Goater
  1 sibling, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 13:13 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 2543 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> If the second watchdog is activated, a second flash module is
> available. It should be of the same model.
> 
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/arm/aspeed_soc.c | 26 +++++++++++++++++++++++++-
>  1 file changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 503efe0f5f77..fcf029f8c1c2 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -170,12 +170,30 @@ static void aspeed_soc_init(Object *obj)
>                                "ram-size", &error_abort);
>  }
>  
> +static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
> +{
> +    Error *err = NULL;
> +    uint32_t hw_strap1;
> +
> +    hw_strap1 = object_property_get_int(OBJECT(&s->scu), "hw-strap1", errp);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return -1;
> +    }
> +
> +    /*
> +     * If the second watchdog is activated, then we have two chips.
> +     */
> +    return hw_strap1 & SCU_HW_STRAP_2ND_BOOT_WDT ? 2 : 1;

Should we instead count the muxed chip selects? We also have FWSPICS2#.
  We would be looking at:

FWSPICS0#: Dedicated pin, no configuration
FWSPICS1#: SCU88[24]=1 & COND2
FWSPICS2#: SCU88[25]=1 & COND2

Where COND2 is: SCU94[1:0] = 0

> +}
> +
>  static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>  {
>      int i;
>      AspeedSoCState *s = ASPEED_SOC(dev);
>      AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
>      Error *err = NULL, *local_err = NULL;
> +    int fmc_num_cs;
>  
>      /* IO space */
>      memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
> @@ -251,7 +269,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>                         qdev_get_gpio_in(DEVICE(&s->vic), 12));
>  
>      /* FMC */
> -    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
> +    fmc_num_cs = aspeed_fmc_get_cs(s, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
>      object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
>      error_propagate(&err, local_err);
>      if (err) {

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 03/38] aspeed: attach the second SPI controller object to the SoC
  2016-11-21 11:57       ` Andrew Jeffery
@ 2016-11-21 13:14         ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 13:14 UTC (permalink / raw)
  To: Andrew Jeffery, Joel Stanley; +Cc: OpenBMC Maillist

On 11/21/2016 12:57 PM, Andrew Jeffery wrote:
> On Mon, 2016-11-21 at 22:12 +1030, Joel Stanley wrote:
>>> On Mon, Nov 21, 2016 at 9:33 PM, Andrew Jeffery <andrew@aj.id.au> wrote:
>>> On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
>>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>>
>>>>> Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
>>>
>>>> ---
>>>>  hw/arm/aspeed_soc.c | 2 +-
>>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
>>>> index db145e201451..bbbbfd13862c 100644
>>>> --- a/hw/arm/aspeed_soc.c
>>>> +++ b/hw/arm/aspeed_soc.c
>>>> @@ -124,7 +124,7 @@ static void aspeed_soc_init(Object *obj)
>>>>      for (i = 0; i < sc->info->spis_num; i++) {
>>>>          object_initialize(&s->spi[i], sizeof(s->spi[i]),
>>>>                            sc->info->spi_typename[i]);
>>>> -        object_property_add_child(obj, "spi", OBJECT(&s->spi[i]), NULL);
>>>> +        object_property_add_child(obj, "spi[*]", OBJECT(&s->spi[i]), NULL);
>>>
>>> Such a curious API. I guess it's effective.
>>
>> I didn't review this one because wtf is with that *?
> 
> According the code it means "keep incrementing a counter until you
> generate a unique object name and successfully register the object".
> AKA the 'i' we already use here, just the API doesn't provide an
> argument to pass it.

yes. see : 

	https://github.com/openbmc/qemu/blob/master/qom/object.c#L910

C.

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

* Re: [PATCH qemu 08/38] aspeed: change SoC revision of the palmetto-bmc machine
  2016-11-18 14:21 ` [PATCH qemu 08/38] aspeed: change SoC revision of the palmetto-bmc machine Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21 13:16   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 13:16 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 927 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> The palmetto BMC machine uses a AST2400 revision A1 SoC.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Verified on palm5 here in Aus. Not sure how I concluded A0 initially,
unless it was a typo.

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index aea73f79d92c..5e35d4562de0 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -82,7 +82,7 @@ enum {
>  
>  static const AspeedBoardConfig aspeed_boards[] = {
>      [PALMETTO_BMC] = {
> -        .soc_name  = "ast2400-a0",
> +        .soc_name  = "ast2400-a1",
>          .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
>          .fmc_model = "n25q256a",
>          .spi_model = "mx25l25635e",

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 12/38] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines
  2016-11-18 14:21 ` [PATCH qemu 12/38] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-21 13:20   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 13:20 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 4453 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> Change the routines prototype to use a 'AspeedSMCFlash *' instead of
> 'AspeedSMCState *'. The result will help in making future changes
> clearer.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/ssi/aspeed_smc.c         | 37 ++++++++++++++++++++++---------------
>  include/hw/ssi/aspeed_smc.h |  2 +-
>  2 files changed, 23 insertions(+), 16 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 78f5aed53247..91cdc0bf1ac7 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -328,19 +328,30 @@ static const MemoryRegionOps aspeed_smc_flash_default_ops = {
>      },
>  };
>  
> -static inline int aspeed_smc_flash_mode(const AspeedSMCState *s, int cs)
> +static inline int aspeed_smc_flash_mode(const AspeedSMCFlash *fl)
>  {
> -    return s->regs[s->r_ctrl0 + cs] & CTRL_CMD_MODE_MASK;
> +    AspeedSMCState *s = fl->controller;
> +
> +    return s->regs[s->r_ctrl0 + fl->id] & CTRL_CMD_MODE_MASK;
>  }
>  
> -static inline bool aspeed_smc_is_usermode(const AspeedSMCState *s, int cs)
> +static inline bool aspeed_smc_is_usermode(const AspeedSMCFlash *fl)
>  {
> -    return aspeed_smc_flash_mode(s, cs) == CTRL_USERMODE;
> +    return aspeed_smc_flash_mode(fl) == CTRL_USERMODE;
>  }
>  
> -static inline bool aspeed_smc_is_writable(const AspeedSMCState *s, int cs)
> +static inline bool aspeed_smc_is_ce_stop_active(const AspeedSMCFlash *fl)
>  {
> -    return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + cs));
> +    AspeedSMCState *s = fl->controller;
> +
> +    return s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE;
> +}
> +
> +static inline bool aspeed_smc_is_writable(const AspeedSMCFlash *fl)
> +{
> +    AspeedSMCState *s = fl->controller;
> +
> +    return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + fl->id));
>  }
>  
>  static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
> @@ -350,7 +361,7 @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
>      uint64_t ret = 0;
>      int i;
>  
> -    if (aspeed_smc_is_usermode(s, fl->id)) {
> +    if (aspeed_smc_is_usermode(fl)) {
>          for (i = 0; i < size; i++) {
>              ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
>          }
> @@ -370,13 +381,13 @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
>      const AspeedSMCState *s = fl->controller;
>      int i;
>  
> -    if (!aspeed_smc_is_writable(s, fl->id)) {
> +    if (!aspeed_smc_is_writable(fl)) {
>          qemu_log_mask(LOG_GUEST_ERROR, "%s: flash is not writable at 0x%"
>                        HWADDR_PRIx "\n", __func__, addr);
>          return;
>      }
>  
> -    if (!aspeed_smc_is_usermode(s, fl->id)) {
> +    if (!aspeed_smc_is_usermode(fl)) {
>          qemu_log_mask(LOG_UNIMP, "%s: usermode not implemented\n",
>                        __func__);
>          return;
> @@ -397,17 +408,13 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
>      },
>  };
>  
> -static bool aspeed_smc_is_ce_stop_active(const AspeedSMCState *s, int cs)
> -{
> -    return s->regs[s->r_ctrl0 + cs] & CTRL_CE_STOP_ACTIVE;
> -}
> -
>  static void aspeed_smc_update_cs(const AspeedSMCState *s)
>  {
>      int i;
>  
>      for (i = 0; i < s->num_cs; ++i) {
> -        qemu_set_irq(s->cs_lines[i], aspeed_smc_is_ce_stop_active(s, i));
> +        qemu_set_irq(s->cs_lines[i],
> +                     aspeed_smc_is_ce_stop_active(&s->flashes[i]));
>      }
>  }
>  
> diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
> index bdfbcc0ffa7d..c64954f6103f 100644
> --- a/include/hw/ssi/aspeed_smc.h
> +++ b/include/hw/ssi/aspeed_smc.h
> @@ -47,7 +47,7 @@ typedef struct AspeedSMCController {
>  } AspeedSMCController;
>  
>  typedef struct AspeedSMCFlash {
> -    const struct AspeedSMCState *controller;
> +    struct AspeedSMCState *controller;
>  
>      uint8_t id;
>      uint32_t size;

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model
  2016-11-21 13:03   ` Cédric Le Goater
@ 2016-11-21 13:23     ` Joel Stanley
  2016-11-28  2:11     ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Joel Stanley @ 2016-11-21 13:23 UTC (permalink / raw)
  To: Cédric Le Goater; +Cc: OpenBMC Maillist, Andrew Jeffery

On Mon, Nov 21, 2016 at 11:33 PM, Cédric Le Goater <clg@kaod.org> wrote:
>> +
>> +#define WDT_IO_REGION_SIZE      0x1000
>> +
>> +#define WDT_STATUS              0x00
>> +#define WDT_RELOAD_VALUE        0x04
>> +#define WDT_RESTART             0x08
>> +#define WDT_CTRL                0x0C
>> +#define WDT_TIMEOUT_STATUS      0x10
>> +#define WDT_TIMEOUT_CLEAR       0x14
>> +#define WDT_RESET_WDITH         0x18
>
>
> May be we should reduce the size of WDT_IO_REGION_SIZE to 0x20
> to instantiate the three watchdog of the Aspeed AST2500 with
> one class ?

Yep I agree. This is how the kernel driver does it too.

Cheers,

Joel

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-21 13:13   ` Andrew Jeffery
@ 2016-11-21 13:29     ` Cédric Le Goater
  2016-11-21 13:35       ` Andrew Jeffery
  0 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 13:29 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/21/2016 02:13 PM, Andrew Jeffery wrote:
> On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
>> If the second watchdog is activated, a second flash module is
>> available. It should be of the same model.
>>
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/arm/aspeed_soc.c | 26 +++++++++++++++++++++++++-
>>  1 file changed, 25 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
>> index 503efe0f5f77..fcf029f8c1c2 100644
>> --- a/hw/arm/aspeed_soc.c
>> +++ b/hw/arm/aspeed_soc.c
>> @@ -170,12 +170,30 @@ static void aspeed_soc_init(Object *obj)
>>                                "ram-size", &error_abort);
>>  }
>>  
>> +static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
>> +{
>> +    Error *err = NULL;
>> +    uint32_t hw_strap1;
>> +
>> +    hw_strap1 = object_property_get_int(OBJECT(&s->scu), "hw-strap1", errp);
>> +    if (err) {
>> +        error_propagate(errp, err);
>> +        return -1;
>> +    }
>> +
>> +    /*
>> +     * If the second watchdog is activated, then we have two chips.
>> +     */
>> +    return hw_strap1 & SCU_HW_STRAP_2ND_BOOT_WDT ? 2 : 1;
> 
> Should we instead count the muxed chip selects? We also have FWSPICS2#.
>   We would be looking at:
> 
> FWSPICS0#: Dedicated pin, no configuration
> FWSPICS1#: SCU88[24]=1 & COND2
> FWSPICS2#: SCU88[25]=1 & COND2
> 
> Where COND2 is: SCU94[1:0] = 0

Yes I agree. that would be much better for the AST2500 but I don't see 
a solution for the AST2400 ? 

C. 

>> +}
>> +
>>  static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>>  {
>>      int i;
>>      AspeedSoCState *s = ASPEED_SOC(dev);
>>      AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
>>      Error *err = NULL, *local_err = NULL;
>> +    int fmc_num_cs;
>>  
>>      /* IO space */
>>      memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
>> @@ -251,7 +269,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>>                         qdev_get_gpio_in(DEVICE(&s->vic), 12));
>>  
>>      /* FMC */
>> -    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
>> +    fmc_num_cs = aspeed_fmc_get_cs(s, &err);
>> +    if (err) {
>> +        error_propagate(errp, err);
>> +        return;
>> +    }
>> +
>> +    object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
>>      object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
>>      error_propagate(&err, local_err);
>>      if (err) {

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-21 13:29     ` Cédric Le Goater
@ 2016-11-21 13:35       ` Andrew Jeffery
  2016-11-21 13:47         ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 13:35 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 3228 bytes --]

On Mon, 2016-11-21 at 14:29 +0100, Cédric Le Goater wrote:
> On 11/21/2016 02:13 PM, Andrew Jeffery wrote:
> > On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> > > If the second watchdog is activated, a second flash module is
> > > available. It should be of the same model.
> > > 
> > > > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > > 
> > > ---
> > >  hw/arm/aspeed_soc.c | 26 +++++++++++++++++++++++++-
> > >  1 file changed, 25 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > > index 503efe0f5f77..fcf029f8c1c2 100644
> > > --- a/hw/arm/aspeed_soc.c
> > > +++ b/hw/arm/aspeed_soc.c
> > > @@ -170,12 +170,30 @@ static void aspeed_soc_init(Object *obj)
> > >                                "ram-size", &error_abort);
> > >  }
> > >  
> > > +static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
> > > +{
> > > +    Error *err = NULL;
> > > +    uint32_t hw_strap1;
> > > +
> > > +    hw_strap1 = object_property_get_int(OBJECT(&s->scu), "hw-strap1", errp);
> > > +    if (err) {
> > > +        error_propagate(errp, err);
> > > +        return -1;
> > > +    }
> > > +
> > > +    /*
> > > +     * If the second watchdog is activated, then we have two chips.
> > > +     */
> > > +    return hw_strap1 & SCU_HW_STRAP_2ND_BOOT_WDT ? 2 : 1;
> > 
> > Should we instead count the muxed chip selects? We also have FWSPICS2#.
> >   We would be looking at:
> > 
> > FWSPICS0#: Dedicated pin, no configuration
> > FWSPICS1#: SCU88[24]=1 & COND2
> > FWSPICS2#: SCU88[25]=1 & COND2
> > 
> > Where COND2 is: SCU94[1:0] = 0
> 
> Yes I agree. that would be much better for the AST2500 but I don't see 
> a solution for the AST2400 ? 
> 

Looks like we count ROMCS[1-4]:

ROMCS1#: SCU88[24]=1
ROMCS2#: SCU88[25]=1
ROMCS3#: SCU88[26]=1
ROMCS4#: SCU88[27]=1

Page 113/114.

Andrew

> 
> C. 
> 
> > > +}
> > > +
> > >  static void aspeed_soc_realize(DeviceState *dev, Error **errp)
> > >  {
> > >      int i;
> > >      AspeedSoCState *s = ASPEED_SOC(dev);
> > >      AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
> > >      Error *err = NULL, *local_err = NULL;
> > > +    int fmc_num_cs;
> > >  
> > >      /* IO space */
> > >      memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
> > > @@ -251,7 +269,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
> > >                         qdev_get_gpio_in(DEVICE(&s->vic), 12));
> > >  
> > >      /* FMC */
> > > -    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
> > > +    fmc_num_cs = aspeed_fmc_get_cs(s, &err);
> > > +    if (err) {
> > > +        error_propagate(errp, err);
> > > +        return;
> > > +    }
> > > +
> > > +    object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
> > >      object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
> > >      error_propagate(&err, local_err);
> > >      if (err) {
> 
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper
  2016-11-18 14:21 ` [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-21 13:36   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-21 13:36 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 2472 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> aspeed_smc_update_cs() was uselessly looping on all CS to update their
> status.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/ssi/aspeed_smc.c | 16 ++++++----------
>  1 file changed, 6 insertions(+), 10 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 91cdc0bf1ac7..1c6c5089f265 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -408,14 +408,10 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
>      },
>  };
>  
> -static void aspeed_smc_update_cs(const AspeedSMCState *s)
> +static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
>  {
> -    int i;
> -
> -    for (i = 0; i < s->num_cs; ++i) {
> -        qemu_set_irq(s->cs_lines[i],
> -                     aspeed_smc_is_ce_stop_active(&s->flashes[i]));
> -    }
> +    AspeedSMCState *s = fl->controller;
> +    qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
>  }
>  
>  static void aspeed_smc_reset(DeviceState *d)
> @@ -431,6 +427,7 @@ static void aspeed_smc_reset(DeviceState *d)
>      /* Unselect all slaves */
>      for (i = 0; i < s->num_cs; ++i) {
>          s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
> +        qemu_set_irq(s->cs_lines[i], true);
>      }
>  
>      /* setup default segment register values for all */
> @@ -438,8 +435,6 @@ static void aspeed_smc_reset(DeviceState *d)
>          s->regs[R_SEG_ADDR0 + i] =
>              aspeed_smc_segment_to_reg(&s->ctrl->segments[i]);
>      }
> -
> -    aspeed_smc_update_cs(s);
>  }
>  
>  static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
> @@ -489,8 +484,9 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
>          addr == s->r_ce_ctrl) {
>          s->regs[addr] = value;
>      } else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
> +        int cs = addr - s->r_ctrl0;
>          s->regs[addr] = value;
> -        aspeed_smc_update_cs(s);
> +        aspeed_smc_flash_update_cs(&s->flashes[cs]);
>      } else if (addr >= R_SEG_ADDR0 &&
>                 addr < R_SEG_ADDR0 + s->ctrl->max_slaves) {
>          int cs = addr - R_SEG_ADDR0;

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-21 13:35       ` Andrew Jeffery
@ 2016-11-21 13:47         ` Cédric Le Goater
  2016-11-22  3:10           ` Andrew Jeffery
  0 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 13:47 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/21/2016 02:35 PM, Andrew Jeffery wrote:
> On Mon, 2016-11-21 at 14:29 +0100, Cédric Le Goater wrote:
>> On 11/21/2016 02:13 PM, Andrew Jeffery wrote:
>>> On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
>>>> If the second watchdog is activated, a second flash module is
>>>> available. It should be of the same model.
>>>>
>>>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>>>
>>>> ---
>>>>  hw/arm/aspeed_soc.c | 26 +++++++++++++++++++++++++-
>>>>  1 file changed, 25 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
>>>> index 503efe0f5f77..fcf029f8c1c2 100644
>>>> --- a/hw/arm/aspeed_soc.c
>>>> +++ b/hw/arm/aspeed_soc.c
>>>> @@ -170,12 +170,30 @@ static void aspeed_soc_init(Object *obj)
>>>>                                "ram-size", &error_abort);
>>>>  }
>>>>  
>>>> +static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
>>>> +{
>>>> +    Error *err = NULL;
>>>> +    uint32_t hw_strap1;
>>>> +
>>>> +    hw_strap1 = object_property_get_int(OBJECT(&s->scu), "hw-strap1", errp);
>>>> +    if (err) {
>>>> +        error_propagate(errp, err);
>>>> +        return -1;
>>>> +    }
>>>> +
>>>> +    /*
>>>> +     * If the second watchdog is activated, then we have two chips.
>>>> +     */
>>>> +    return hw_strap1 & SCU_HW_STRAP_2ND_BOOT_WDT ? 2 : 1;
>>>
>>> Should we instead count the muxed chip selects? We also have FWSPICS2#.
>>>   We would be looking at:
>>>
>>> FWSPICS0#: Dedicated pin, no configuration
>>> FWSPICS1#: SCU88[24]=1 & COND2
>>> FWSPICS2#: SCU88[25]=1 & COND2
>>>
>>> Where COND2 is: SCU94[1:0] = 0
>>
>> Yes I agree. that would be much better for the AST2500 but I don't see 
>> a solution for the AST2400 ? 
>>
> 
> Looks like we count ROMCS[1-4]:
> 
> ROMCS1#: SCU88[24]=1
> ROMCS2#: SCU88[25]=1
> ROMCS3#: SCU88[26]=1
> ROMCS4#: SCU88[27]=1
> 
> Page 113/114.

yes ! 

So we should set or unset these SCU regs when the SoC is created and 
derive the wdt2 enablement from them. I suppose that the helper routine 
to check for the conditions would be under SCU. 

or do we start a simple pinctrl model and slowly add the enablement
of the pins we need ? 

Thanks,

C. 

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

* Re: [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC
  2016-11-21 10:59   ` Andrew Jeffery
@ 2016-11-21 14:14     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 14:14 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/21/2016 11:59 AM, Andrew Jeffery wrote:
> On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
>> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> With this I think we can finally drop
> 
>     dc->cannot_destroy_with_object_finalize_yet = true;
> 
> from aspeed_soc_class_init() in hw/arm/aspeed_soc.c. See commit
> 
>     ce5b1bbf624b exec: move cpu_exec_init() calls to realize functions
> 

Indeed. I just checked and added a patch for it.

Thanks,

C. 

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

* Re: [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board
  2016-11-21 12:18   ` Andrew Jeffery
@ 2016-11-21 14:44     ` Cédric Le Goater
  2016-11-22  3:06       ` Andrew Jeffery
  0 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-21 14:44 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/21/2016 01:18 PM, Andrew Jeffery wrote:
> On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
>> The Romulus machine is an OpenPOWER system with an AST2500 SoC for
>> the BMC and a POWER9 chip for the host. It does not make much
>> difference for qemu a part from the fact that the FMC controller has
>> two SPI flash module slaves.
>>
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/arm/aspeed.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 45 insertions(+)
>>
>> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
>> index 159d562e8912..aea73f79d92c 100644
>> --- a/hw/arm/aspeed.c
>> +++ b/hw/arm/aspeed.c
>> @@ -41,8 +41,10 @@ typedef struct AspeedBoardConfig {
>>  enum {
>>      PALMETTO_BMC,
>>      AST2500_EVB,
>> +    ROMULUS_BMC,
>>  };
>>  
>> +/* 0x120CE416 */
>>  #define PALMETTO_BMC_HW_STRAP1 (                                        \
>>          SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) |               \
>>          SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
>> @@ -56,6 +58,7 @@ enum {
>>          SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) |                       \
>>          SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
>>  
>> +/* 0xF100C2E6 */
>>  #define AST2500_EVB_HW_STRAP1 ((                                        \
>>          AST2500_HW_STRAP1_DEFAULTS |                                    \
>>          SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
>> @@ -66,6 +69,17 @@ enum {
>>          SCU_HW_STRAP_MAC0_RGMII) &                                      \
>>          ~SCU_HW_STRAP_2ND_BOOT_WDT)
>>  
>> +/* 0xF10AE216 */

That is a witherspoon value. I haven't had access to a Romulus yet.

>> +#define ROMULUS_BMC_HW_STRAP1 (                                     \
>> +        AST2500_HW_STRAP1_DEFAULTS |                                    \
> 
> In the defaults it says we define 16MB VGA memory, but how do we strap
> for that? It doesn't look like you can set bit 2 from the strapping
> table, and if we're setting bit 3 as 0 then we're getting either 8 or
> 32MB of memory. Is there a typo in the datasheet?

The VGA memory size selection is SCU70[3:2]. Both are RW. We should be fine.

>> +        SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
>> +        SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE |                        \
>> +        SCU_AST2500_HW_STRAP_UART_DEBUG |                               \
>> +        SCU_AST2500_HW_STRAP_DDR4_ENABLE |                              \
>> +        SCU_AST2500_HW_STRAP_ACPI_ENABLE |                              \
> 
> Hello? Is that you Jon??
> 
> Does anyone know why we're enabling ACPI on Romulus?

indeed. no idea why, and there is no default value for this bit.


>> +        SCU_HW_STRAP_SPI_WIDTH |                                        \
>> +        SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN))
> 
> According to the schematic I have we're setting bit 27 (Fast reset mode
> for ARM ICE debugger). But apparently that's not what's been read off
> some existing Romulus?

again this is a witherspoon value. It might be different on a Romulus.

Thanks,

C.


>> +
>>  static const AspeedBoardConfig aspeed_boards[] = {
>>      [PALMETTO_BMC] = {
>>          .soc_name  = "ast2400-a0",
>> @@ -79,6 +93,12 @@ static const AspeedBoardConfig aspeed_boards[] = {
>>          .fmc_model = "n25q256a",
>>          .spi_model = "mx25l25635e",
>>      },
>> +    [ROMULUS_BMC]  = {
>> +        .soc_name  = "ast2500-a1",
>> +        .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
>> +        .fmc_model = "n25q256a",
>> +        .spi_model = "mx66l1g45g",
>> +    },
>>  };
>>  
>>  static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
>> @@ -200,10 +220,35 @@ static const TypeInfo ast2500_evb_type = {
>>      .class_init = ast2500_evb_class_init,
>>  };
>>  
>> +static void romulus_bmc_init(MachineState *machine)
>> +{
>> +    aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]);
>> +}
>> +
>> +static void romulus_bmc_class_init(ObjectClass *oc, void *data)
>> +{
>> +    MachineClass *mc = MACHINE_CLASS(oc);
>> +
>> +    mc->desc = "OpenPOWER Romulus BMC (ARM1176)";
>> +    mc->init = romulus_bmc_init;
>> +    mc->max_cpus = 1;
>> +    mc->no_sdcard = 1;
>> +    mc->no_floppy = 1;
>> +    mc->no_cdrom = 1;
>> +    mc->no_parallel = 1;
>> +}
>> +
>> +static const TypeInfo romulus_bmc_type = {
>> +    .name = MACHINE_TYPE_NAME("romulus-bmc"),
>> +    .parent = TYPE_MACHINE,
>> +    .class_init = romulus_bmc_class_init,
>> +};
>> +
>>  static void aspeed_machine_init(void)
>>  {
>>      type_register_static(&palmetto_bmc_type);
>>      type_register_static(&ast2500_evb_type);
>> +    type_register_static(&romulus_bmc_type);
>>  }
>>  
>>  type_init(aspeed_machine_init)

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

* Re: [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board
  2016-11-21 14:44     ` Cédric Le Goater
@ 2016-11-22  3:06       ` Andrew Jeffery
  0 siblings, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-22  3:06 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 7173 bytes --]

On Mon, 2016-11-21 at 15:44 +0100, Cédric Le Goater wrote:
> On 11/21/2016 01:18 PM, Andrew Jeffery wrote:
> > On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> > > The Romulus machine is an OpenPOWER system with an AST2500 SoC for
> > > the BMC and a POWER9 chip for the host. It does not make much
> > > difference for qemu a part from the fact that the FMC controller has
> > > two SPI flash module slaves.
> > > 
> > > > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > > 
> > > ---
> > >  hw/arm/aspeed.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 45 insertions(+)
> > > 
> > > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> > > index 159d562e8912..aea73f79d92c 100644
> > > --- a/hw/arm/aspeed.c
> > > +++ b/hw/arm/aspeed.c
> > > @@ -41,8 +41,10 @@ typedef struct AspeedBoardConfig {
> > >  enum {
> > >      PALMETTO_BMC,
> > >      AST2500_EVB,
> > > +    ROMULUS_BMC,
> > >  };
> > >  
> > > +/* 0x120CE416 */
> > >  #define PALMETTO_BMC_HW_STRAP1 (                                        \
> > >          SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) |               \
> > >          SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
> > > @@ -56,6 +58,7 @@ enum {
> > >          SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) |                       \
> > >          SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
> > >  
> > > +/* 0xF100C2E6 */
> > >  #define AST2500_EVB_HW_STRAP1 ((                                        \
> > >          AST2500_HW_STRAP1_DEFAULTS |                                    \
> > >          SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
> > > @@ -66,6 +69,17 @@ enum {
> > >          SCU_HW_STRAP_MAC0_RGMII) &                                      \
> > >          ~SCU_HW_STRAP_2ND_BOOT_WDT)
> > >  
> > > +/* 0xF10AE216 */
> 
> That is a witherspoon value. I haven't had access to a Romulus yet.

Okay. We can derive it from the schematic anyway. I checked the values
you've configured via the macros and it looks like it matches.

> 
> > > +#define ROMULUS_BMC_HW_STRAP1 (                                     \
> > > +        AST2500_HW_STRAP1_DEFAULTS |                                    \
> > 
> > In the defaults it says we define 16MB VGA memory, but how do we strap
> > for that? It doesn't look like you can set bit 2 from the strapping
> > table, and if we're setting bit 3 as 0 then we're getting either 8 or
> > 32MB of memory. Is there a typo in the datasheet?
> 
> The VGA memory size selection is SCU70[3:2]. Both are RW. We should be fine.

Sorry, that lacked a bit of context. I was looking at the datasheet and
the schematic, and couldn't find a way to affect bit 2 in SCU70. In
qemu that doesn't matter so much, we can "do what we want", but it
seemed the hardware was oddly limited unless I've overlooked something.

> 
> > > +        SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
> > > +        SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE |                        \
> > > +        SCU_AST2500_HW_STRAP_UART_DEBUG |                               \
> > > +        SCU_AST2500_HW_STRAP_DDR4_ENABLE |                              \
> > > +        SCU_AST2500_HW_STRAP_ACPI_ENABLE |                              \
> > 
> > Hello? Is that you Jon??
> > 
> > Does anyone know why we're enabling ACPI on Romulus?
> 
> indeed. no idea why, and there is no default value for this bit.

Comparing the AST2400 and AST2500 datasheets it seems Aspeed inverted
the meaning of the bit in the AST2500. Which might mean the strapping
was a hangover from systems with an AST2400.

Joel/Patrick: This strapping conflicts with the following nets:

PM_PCIE_SLOT1_WAKE_L (GPIOY0_SIOS3#)
PM_PCIE_SLOT2_WAKE_L (GPIOY1_SIOS5#)
PM_PCIE_SLOT3_WAKE_L (GPIOY2_SIOPWREQ#)
PM_PCIE_SLOT4_WAKE_L (GPIOY3_SIOONCTRL#)
PM_PCIE_SLOT5_WAKE_L (GPIOZ0_VPOG2_NORA0_SIOPBI#)

It also affects the following not-connected nets:

NC_BMC_GPIOZ1 (GPIOZ1_VPOG3_NORA1_SIOPWRGD)
NC_BMC_GPIOZ2 (GPIOZ2_VPOG4_NORA2_SIOPBO#)
NC_BMC_GPIOZ3 (GPIOZ3_VPOG5_NORA3_SIOSCI#)

> 
> 
> > > +        SCU_HW_STRAP_SPI_WIDTH |                                        \
> > > +        SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN))
> > 
> > According to the schematic I have we're setting bit 27 (Fast reset mode
> > for ARM ICE debugger). But apparently that's not what's been read off
> > some existing Romulus?
> 
> again this is a witherspoon value. It might be different on a Romulus.

According to the schematics I have the bit is set for Romulus.

Andrew

> 
> Thanks,
> 
> C.
> 
> 
> > > +
> > >  static const AspeedBoardConfig aspeed_boards[] = {
> > >      [PALMETTO_BMC] = {
> > >          .soc_name  = "ast2400-a0",
> > > @@ -79,6 +93,12 @@ static const AspeedBoardConfig aspeed_boards[] = {
> > >          .fmc_model = "n25q256a",
> > >          .spi_model = "mx25l25635e",
> > >      },
> > > +    [ROMULUS_BMC]  = {
> > > +        .soc_name  = "ast2500-a1",
> > > +        .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
> > > +        .fmc_model = "n25q256a",
> > > +        .spi_model = "mx66l1g45g",
> > > +    },
> > >  };
> > >  
> > >  static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
> > > @@ -200,10 +220,35 @@ static const TypeInfo ast2500_evb_type = {
> > >      .class_init = ast2500_evb_class_init,
> > >  };
> > >  
> > > +static void romulus_bmc_init(MachineState *machine)
> > > +{
> > > +    aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]);
> > > +}
> > > +
> > > +static void romulus_bmc_class_init(ObjectClass *oc, void *data)
> > > +{
> > > +    MachineClass *mc = MACHINE_CLASS(oc);
> > > +
> > > +    mc->desc = "OpenPOWER Romulus BMC (ARM1176)";
> > > +    mc->init = romulus_bmc_init;
> > > +    mc->max_cpus = 1;
> > > +    mc->no_sdcard = 1;
> > > +    mc->no_floppy = 1;
> > > +    mc->no_cdrom = 1;
> > > +    mc->no_parallel = 1;
> > > +}
> > > +
> > > +static const TypeInfo romulus_bmc_type = {
> > > +    .name = MACHINE_TYPE_NAME("romulus-bmc"),
> > > +    .parent = TYPE_MACHINE,
> > > +    .class_init = romulus_bmc_class_init,
> > > +};
> > > +
> > >  static void aspeed_machine_init(void)
> > >  {
> > >      type_register_static(&palmetto_bmc_type);
> > >      type_register_static(&ast2500_evb_type);
> > > +    type_register_static(&romulus_bmc_type);
> > >  }
> > >  
> > >  type_init(aspeed_machine_init)
> 
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-21 13:47         ` Cédric Le Goater
@ 2016-11-22  3:10           ` Andrew Jeffery
  2016-11-22  7:21             ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-22  3:10 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 2834 bytes --]

On Mon, 2016-11-21 at 14:47 +0100, Cédric Le Goater wrote:
> On 11/21/2016 02:35 PM, Andrew Jeffery wrote:
> > On Mon, 2016-11-21 at 14:29 +0100, Cédric Le Goater wrote:
> > > On 11/21/2016 02:13 PM, Andrew Jeffery wrote:
> > > > On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> > > > > If the second watchdog is activated, a second flash module is
> > > > > available. It should be of the same model.
> > > > > 
> > > > > > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > > > > 
> > > > > ---
> > > > >  hw/arm/aspeed_soc.c | 26 +++++++++++++++++++++++++-
> > > > >  1 file changed, 25 insertions(+), 1 deletion(-)
> > > > > 
> > > > > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > > > > index 503efe0f5f77..fcf029f8c1c2 100644
> > > > > --- a/hw/arm/aspeed_soc.c
> > > > > +++ b/hw/arm/aspeed_soc.c
> > > > > @@ -170,12 +170,30 @@ static void aspeed_soc_init(Object *obj)
> > > > >                                "ram-size", &error_abort);
> > > > >  }
> > > > >  
> > > > > +static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
> > > > > +{
> > > > > +    Error *err = NULL;
> > > > > +    uint32_t hw_strap1;
> > > > > +
> > > > > +    hw_strap1 = object_property_get_int(OBJECT(&s->scu), "hw-strap1", errp);
> > > > > +    if (err) {
> > > > > +        error_propagate(errp, err);
> > > > > +        return -1;
> > > > > +    }
> > > > > +
> > > > > +    /*
> > > > > +     * If the second watchdog is activated, then we have two chips.
> > > > > +     */
> > > > > +    return hw_strap1 & SCU_HW_STRAP_2ND_BOOT_WDT ? 2 : 1;
> > > > 
> > > > Should we instead count the muxed chip selects? We also have FWSPICS2#.
> > > >   We would be looking at:
> > > > 
> > > > FWSPICS0#: Dedicated pin, no configuration
> > > > FWSPICS1#: SCU88[24]=1 & COND2
> > > > FWSPICS2#: SCU88[25]=1 & COND2
> > > > 
> > > > Where COND2 is: SCU94[1:0] = 0
> > > 
> > > Yes I agree. that would be much better for the AST2500 but I don't see 
> > > a solution for the AST2400 ? 
> > > 
> > 
> > Looks like we count ROMCS[1-4]:
> > 
> > ROMCS1#: SCU88[24]=1
> > ROMCS2#: SCU88[25]=1
> > ROMCS3#: SCU88[26]=1
> > ROMCS4#: SCU88[27]=1
> > 
> > Page 113/114.
> 
> yes ! 
> 
> So we should set or unset these SCU regs when the SoC is created and 
> derive the wdt2 enablement from them. I suppose that the helper routine 
> to check for the conditions would be under SCU. 
> 
> or do we start a simple pinctrl model and slowly add the enablement
> of the pins we need ? 
> 

From the discussion on IRC last night between Cédric, Joel and myself
we decided to start on a pinmux backend to help manage these issues.

Andrew

> Thanks,
> 
> C. 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-22  3:10           ` Andrew Jeffery
@ 2016-11-22  7:21             ` Cédric Le Goater
  2016-11-23  1:22               ` Andrew Jeffery
  0 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-22  7:21 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

>> So we should set or unset these SCU regs when the SoC is created and 
>> derive the wdt2 enablement from them. I suppose that the helper routine 
>> to check for the conditions would be under SCU. 
>>
>> or do we start a simple pinctrl model and slowly add the enablement
>> of the pins we need ? 
>>
> 
> From the discussion on IRC last night between Cédric, Joel and myself
> we decided to start on a pinmux backend to help manage these issues.

Do you have a rough idea of an API that the SoC could use ? 

	enum AspeedAST2500Function {
		FWSPICS0,
		FWSPICS1,
		FWSPICS2,
	};

	enum AspeedAST2400Function {
		ROMCS1,
		ROMCS2,
		ROMCS3,
		ROMCS4,
	};

	bool aspeed_pin_is_enabled(AspeedPinmux *p, int func);

Thanks,

C. 

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

* Re: [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3
  2016-11-18 14:22 ` [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3 Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-22 16:57   ` Cédric Le Goater
  2016-11-28  2:04     ` Andrew Jeffery
  1 sibling, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-22 16:57 UTC (permalink / raw)
  To: openbmc; +Cc: Andrew Jeffery

On 11/18/2016 03:22 PM, Cédric Le Goater wrote:
> Temperatures can be changed from the monitor with :
> 
> 	(qemu) qom-set /machine/unattached/device[2] temperature0 12000


These devices should be defined at the machine level, in palmetto_bmc_init(), 
and not at the SoC level. 

C.

> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/arm/aspeed_soc.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 24354f700115..2aa15d90cc31 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -268,6 +268,14 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>      sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
>                         qdev_get_gpio_in(DEVICE(&s->vic), 12));
>  
> +    /* add a TMP423 temperature sensor */
> +    dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&s->i2c), 2),
> +                           "tmp423", 0x4c);
> +    object_property_set_int(OBJECT(dev), 31000, "temperature0", &err);
> +    object_property_set_int(OBJECT(dev), 28000, "temperature1", &err);
> +    object_property_set_int(OBJECT(dev), 20000, "temperature2", &err);
> +    object_property_set_int(OBJECT(dev), 110000, "temperature3", &err);
> +
>      /* FMC */
>      fmc_num_cs = aspeed_fmc_get_cs(s, &err);
>      if (err) {
> 

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

* Re: [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0
  2016-11-18 14:22 ` [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0 Cédric Le Goater
  2016-11-21  7:27   ` Joel Stanley
@ 2016-11-22 17:00   ` Cédric Le Goater
  2016-11-28  2:05   ` Andrew Jeffery
  2 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-22 17:00 UTC (permalink / raw)
  To: openbmc; +Cc: Andrew Jeffery, Alastair D'Silva

On 11/18/2016 03:22 PM, Cédric Le Goater wrote:
> The palmetto platform has a ds3231 RTC device but not qemu. Let's use
> a ds1338 instead which provides enough basic RTC features. Only alarms
> will be missing

This belongs to the machine level also and it is conflicting with 
Alastair's patchset. We will have to synchronize our work.

C.


> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/arm/aspeed_soc.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 2aa15d90cc31..d2bc0ba2070d 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -276,6 +276,10 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>      object_property_set_int(OBJECT(dev), 20000, "temperature2", &err);
>      object_property_set_int(OBJECT(dev), 110000, "temperature3", &err);
>  
> +    /* The palmetto platform expects a ds3231 RTC but a ds1338 is
> +     * enough to provide basic RTC features. Alarms will be missing */
> +    i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&s->i2c), 0), "ds1338", 0x68);
> +
>      /* FMC */
>      fmc_num_cs = aspeed_fmc_get_cs(s, &err);
>      if (err) {
> 

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-22  7:21             ` Cédric Le Goater
@ 2016-11-23  1:22               ` Andrew Jeffery
  2016-11-23  9:33                 ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-23  1:22 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 1927 bytes --]

On Tue, 2016-11-22 at 08:21 +0100, Cédric Le Goater wrote:
> > > So we should set or unset these SCU regs when the SoC is created
> > > and 
> > > derive the wdt2 enablement from them. I suppose that the helper
> > > routine 
> > > to check for the conditions would be under SCU. 
> > > 
> > > or do we start a simple pinctrl model and slowly add the
> > > enablement
> > > of the pins we need ? 
> > > 
> > 
> > From the discussion on IRC last night between Cédric, Joel and
> > myself
> > we decided to start on a pinmux backend to help manage these
> > issues.
> 
> Do you have a rough idea of an API that the SoC could use ? 
> 
> 	enum AspeedAST2500Function {
> 		FWSPICS0,
> 		FWSPICS1,
> 		FWSPICS2,
> 	};
> 
> 	enum AspeedAST2400Function {
> 		ROMCS1,
> 		ROMCS2,
> 		ROMCS3,
> 		ROMCS4,
> 	};
> 
> 	bool aspeed_pin_is_enabled(AspeedPinmux *p, int func);

Largely this looks good.

But bikeshedding a bit, but I think the function name should focus on
functions, not pins. The function maps to some pin in the physical
case, but for qemu's purposes we don't care about that just yet. Even
if we do care in the future we can internally map functions to pins
behind a pinmux abstraction. As such I think we can get away with a
small tweak:

bool aspeed_pinmux_is_enabled(AspeedPinmux *p, int func);

Did you have any thought about how we hoist ourselves from a
AspeedPinmux to say an AspeedAST2500Pinmux with this interface? As it
stands (without specifying parts of AspeedPinmux) we don't have the
context to correctly interpret the func arg. Already with these few
functions we have to test different bits depending on the SoC at hand,
and the 2500 has the extra requirements of talking to the GFX and LPC
controllers in other cases.

I expect having a tag field internal to p is enough. I'll have a think
about it.

Andrew

> 
> Thanks,
> 
> C. 
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-23  1:22               ` Andrew Jeffery
@ 2016-11-23  9:33                 ` Cédric Le Goater
  2016-11-23 19:08                   ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-23  9:33 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/23/2016 02:22 AM, Andrew Jeffery wrote:
> On Tue, 2016-11-22 at 08:21 +0100, Cédric Le Goater wrote:
>>>> So we should set or unset these SCU regs when the SoC is created
>>>> and 
>>>> derive the wdt2 enablement from them. I suppose that the helper
>>>> routine 
>>>> to check for the conditions would be under SCU. 
>>>>
>>>> or do we start a simple pinctrl model and slowly add the
>>>> enablement
>>>> of the pins we need ? 
>>>>
>>>
>>> From the discussion on IRC last night between Cédric, Joel and
>>> myself
>>> we decided to start on a pinmux backend to help manage these
>>> issues.
>>
>> Do you have a rough idea of an API that the SoC could use ? 
>>
>> 	enum AspeedAST2500Function {
>> 		FWSPICS0,
>> 		FWSPICS1,
>> 		FWSPICS2,
>> 	};
>>
>> 	enum AspeedAST2400Function {
>> 		ROMCS1,
>> 		ROMCS2,
>> 		ROMCS3,
>> 		ROMCS4,
>> 	};
>>
>> 	bool aspeed_pin_is_enabled(AspeedPinmux *p, int func);
> 
> Largely this looks good.
> 
> But bikeshedding a bit, but I think the function name should focus on
> functions, not pins. The function maps to some pin in the physical
> case, but for qemu's purposes we don't care about that just yet. Even
> if we do care in the future we can internally map functions to pins
> behind a pinmux abstraction. As such I think we can get away with a
> small tweak:
> 
> bool aspeed_pinmux_is_enabled(AspeedPinmux *p, int func);

ok Looks good to me. I will fake this in the patchset to ease the 
change in the future.

> Did you have any thought about how we hoist ourselves from a
> AspeedPinmux to say an AspeedAST2500Pinmux with this interface? 

There are different solutions. We could introduce a class like

#define TYPE_ASPEED_PINMUX "aspeed-pinmux"
#define ASPEED_PINMUX(obj)
     OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX)
#define ASPEED_PINMUX_CLASS(klass) \
     OBJECT_CLASS_CHECK(AspeedPinmuxClass, (klass), TYPE_ASPEED_PINMUX)
#define ASPEED_PINMUX_GET_CLASS(obj) \
     OBJECT_GET_CLASS(AspeedPinmuxClass, (obj), TYPE_ASPEED_PINMUX)

typedef struct AspeedPinmux {
	...
} AspeedPinmux;

typedef struct AspeedPinmuxClass {
	...
	AspeedPinmuxType pinmux_type;
        ... 

or
	... 
        bool (*is_enabled)(AspeedPinmux *pmux, int func);
	....
} AspeedPinmuxClass;

#define TYPE_ASPEED_PINMUX_POWER8E TYPE_ASPEED_PINMUX "-ast2500"
#define ASPEED_PINMUX_AST2500(obj) \
    OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX_AST2500)

#define TYPE_ASPEED_PINMUX_POWER8E TYPE_ASPEED_PINMUX "-ast2400"
#define ASPEED_PINMUX_AST2400(obj) \
    OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX_AST2400)


and use 'pinmux_type' to dispatch to specific handlers or directly
include the handlers we need under the class. 

If we only have handlers and no state, we could define a Interface
and tie it to the soc object.

typedef struct AspeedPinmuxInterface {
    Object parent;
} AspeedPinmuxInterface;

#define TYPE_ASPEED_PINMUX_INTERFACE "aspeed-pinmux-interface"
#define ASPEED_PINMUX_INTERFACE(obj) \
     OBJECT_CHECK(AspeedPinmuxInterface, (obj), TYPE_ASPEED_PINMUX_INTERFACE)
#define ASPEED_PINMUX_INTERFACE_CLASS(klass)                \
    OBJECT_CLASS_CHECK(AspeedPinmuxInterfaceClass, (klass), \
                       TYPE_ASPEED_PINMUX_INTERFACE)
#define ASPEED_PINMUX_INTERFACE_GET_CLASS(obj) \
     OBJECT_GET_CLASS(AspeedPinmuxInterfaceClass, (obj), TYPE_ASPEED_PINMUX_INTERFACE)

typedef struct AspeedPinmuxInterfaceClass {
    InterfaceClass parent;
    bool (*is_enabled)(AspeedPinmuxInterface *dev, int func);
    ...
} AspeedPinmuxInterfaceClass;


Conceptually, the SoC object would have a set of routines to handle
muxing. that seems ok to me as pinmux is a rather invasive component 
needing access to all controllers to be able to set the functions. 

C.

> As it
> stands (without specifying parts of AspeedPinmux) we don't have the
> context to correctly interpret the func arg. Already with these few
> functions we have to test different bits depending on the SoC at hand,
> and the 2500 has the extra requirements of talking to the GFX and LPC
> controllers in other cases.
> 
> I expect having a tag field internal to p is enough. I'll have a think
> about it.
> 
> Andrew
> 
>>
>> Thanks,
>>
>> C. 

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-23  9:33                 ` Cédric Le Goater
@ 2016-11-23 19:08                   ` Cédric Le Goater
  2016-11-24  1:00                     ` Andrew Jeffery
  0 siblings, 1 reply; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-23 19:08 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/23/2016 10:33 AM, Cédric Le Goater wrote:
> On 11/23/2016 02:22 AM, Andrew Jeffery wrote:
>> On Tue, 2016-11-22 at 08:21 +0100, Cédric Le Goater wrote:
>>>>> So we should set or unset these SCU regs when the SoC is created
>>>>> and 
>>>>> derive the wdt2 enablement from them. I suppose that the helper
>>>>> routine 
>>>>> to check for the conditions would be under SCU. 
>>>>>
>>>>> or do we start a simple pinctrl model and slowly add the
>>>>> enablement
>>>>> of the pins we need ? 
>>>>>
>>>>
>>>> From the discussion on IRC last night between Cédric, Joel and
>>>> myself
>>>> we decided to start on a pinmux backend to help manage these
>>>> issues.
>>>
>>> Do you have a rough idea of an API that the SoC could use ? 
>>>
>>> 	enum AspeedAST2500Function {
>>> 		FWSPICS0,
>>> 		FWSPICS1,
>>> 		FWSPICS2,
>>> 	};
>>>
>>> 	enum AspeedAST2400Function {
>>> 		ROMCS1,
>>> 		ROMCS2,
>>> 		ROMCS3,
>>> 		ROMCS4,
>>> 	};
>>>
>>> 	bool aspeed_pin_is_enabled(AspeedPinmux *p, int func);
>>
>> Largely this looks good.
>>
>> But bikeshedding a bit, but I think the function name should focus on
>> functions, not pins. The function maps to some pin in the physical
>> case, but for qemu's purposes we don't care about that just yet. Even
>> if we do care in the future we can internally map functions to pins
>> behind a pinmux abstraction. As such I think we can get away with a
>> small tweak:
>>
>> bool aspeed_pinmux_is_enabled(AspeedPinmux *p, int func);
> 
> ok Looks good to me. I will fake this in the patchset to ease the 
> change in the future.
> 
>> Did you have any thought about how we hoist ourselves from a
>> AspeedPinmux to say an AspeedAST2500Pinmux with this interface? 
> 
> There are different solutions. We could introduce a class like
> 
> #define TYPE_ASPEED_PINMUX "aspeed-pinmux"
> #define ASPEED_PINMUX(obj)
>      OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX)
> #define ASPEED_PINMUX_CLASS(klass) \
>      OBJECT_CLASS_CHECK(AspeedPinmuxClass, (klass), TYPE_ASPEED_PINMUX)
> #define ASPEED_PINMUX_GET_CLASS(obj) \
>      OBJECT_GET_CLASS(AspeedPinmuxClass, (obj), TYPE_ASPEED_PINMUX)
> 
> typedef struct AspeedPinmux {
> 	...
> } AspeedPinmux;
> 
> typedef struct AspeedPinmuxClass {
> 	...
> 	AspeedPinmuxType pinmux_type;
>         ... 
> 
> or
> 	... 
>         bool (*is_enabled)(AspeedPinmux *pmux, int func);
> 	....
> } AspeedPinmuxClass;
> 
> #define TYPE_ASPEED_PINMUX_POWER8E TYPE_ASPEED_PINMUX "-ast2500"
> #define ASPEED_PINMUX_AST2500(obj) \
>     OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX_AST2500)
> 
> #define TYPE_ASPEED_PINMUX_POWER8E TYPE_ASPEED_PINMUX "-ast2400"
> #define ASPEED_PINMUX_AST2400(obj) \
>     OBJECT_CHECK(AspeedPinmux, (obj), TYPE_ASPEED_PINMUX_AST2400)
> 
> 
> and use 'pinmux_type' to dispatch to specific handlers or directly
> include the handlers we need under the class. 
> 
> If we only have handlers and no state, we could define a Interface
> and tie it to the soc object.
> 
> typedef struct AspeedPinmuxInterface {
>     Object parent;
> } AspeedPinmuxInterface;
> 
> #define TYPE_ASPEED_PINMUX_INTERFACE "aspeed-pinmux-interface"
> #define ASPEED_PINMUX_INTERFACE(obj) \
>      OBJECT_CHECK(AspeedPinmuxInterface, (obj), TYPE_ASPEED_PINMUX_INTERFACE)
> #define ASPEED_PINMUX_INTERFACE_CLASS(klass)                \
>     OBJECT_CLASS_CHECK(AspeedPinmuxInterfaceClass, (klass), \
>                        TYPE_ASPEED_PINMUX_INTERFACE)
> #define ASPEED_PINMUX_INTERFACE_GET_CLASS(obj) \
>      OBJECT_GET_CLASS(AspeedPinmuxInterfaceClass, (obj), TYPE_ASPEED_PINMUX_INTERFACE)
> 
> typedef struct AspeedPinmuxInterfaceClass {
>     InterfaceClass parent;
>     bool (*is_enabled)(AspeedPinmuxInterface *dev, int func);
>     ...
> } AspeedPinmuxInterfaceClass;
> 
> 
> Conceptually, the SoC object would have a set of routines to handle
> muxing. that seems ok to me as pinmux is a rather invasive component 
> needing access to all controllers to be able to set the functions. 

Here is a quick patch for it to get an overall feeling.

C.


Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed.c              |    6 +++
 hw/arm/aspeed_soc.c          |   86 ++++++++++++++++++++++++++++++++++++++++++-
 hw/misc/aspeed_scu.c         |    2 +
 include/hw/arm/aspeed_soc.h  |    2 +
 include/hw/misc/aspeed_scu.h |    1 
 5 files changed, 96 insertions(+), 1 deletion(-)

Index: qemu-aspeed.git/hw/arm/aspeed_soc.c
===================================================================
--- qemu-aspeed.git.orig/hw/arm/aspeed_soc.c
+++ qemu-aspeed.git/hw/arm/aspeed_soc.c
@@ -47,6 +47,9 @@ static const hwaddr aspeed_soc_ast2500_s
 static const char *aspeed_soc_ast2500_typenames[] = {
     "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
 
+static bool aspeed_soc_ast2400_is_enabled(AspeedSoCState *obj, int func);
+static bool aspeed_soc_ast2500_is_enabled(AspeedSoCState *obj, int func);
+
 static const AspeedSoCInfo aspeed_socs[] = {
     {
         .name         = "ast2400-a0",
@@ -58,6 +61,7 @@ static const AspeedSoCInfo aspeed_socs[]
         .spi_bases    = aspeed_soc_ast2400_spi_bases,
         .fmc_typename = "aspeed.smc.fmc",
         .spi_typename = aspeed_soc_ast2400_typenames,
+        .is_enabled   = aspeed_soc_ast2400_is_enabled,
     }, {
         .name         = "ast2400-a1",
         .cpu_model    = "arm926",
@@ -68,6 +72,7 @@ static const AspeedSoCInfo aspeed_socs[]
         .spi_bases    = aspeed_soc_ast2400_spi_bases,
         .fmc_typename = "aspeed.smc.fmc",
         .spi_typename = aspeed_soc_ast2400_typenames,
+        .is_enabled   = aspeed_soc_ast2400_is_enabled,
     }, {
         .name         = "ast2400",
         .cpu_model    = "arm926",
@@ -78,6 +83,7 @@ static const AspeedSoCInfo aspeed_socs[]
         .spi_bases    = aspeed_soc_ast2400_spi_bases,
         .fmc_typename = "aspeed.smc.fmc",
         .spi_typename = aspeed_soc_ast2400_typenames,
+        .is_enabled   = aspeed_soc_ast2500_is_enabled,
     }, {
         .name         = "ast2500-a1",
         .cpu_model    = "arm1176",
@@ -88,6 +94,7 @@ static const AspeedSoCInfo aspeed_socs[]
         .spi_bases    = aspeed_soc_ast2500_spi_bases,
         .fmc_typename = "aspeed.smc.ast2500-fmc",
         .spi_typename = aspeed_soc_ast2500_typenames,
+        .is_enabled   = aspeed_soc_ast2500_is_enabled,
     },
 };
 
@@ -149,6 +156,8 @@ static void aspeed_soc_init(Object *obj)
                               "hw-strap1", &error_abort);
     object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
                               "hw-strap2", &error_abort);
+    object_property_add_alias(obj, "pinmux-ctrl3", OBJECT(&s->scu),
+                              "pinmux-ctrl3", &error_abort);
 
     object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
     object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
@@ -170,12 +179,81 @@ static void aspeed_soc_init(Object *obj)
                               "ram-size", &error_abort);
 }
 
+/* AST2400 */
+enum {
+    ROMCS1,
+    ROMCS2,
+    ROMCS3,
+    ROMCS4,
+};
+
+static bool aspeed_soc_ast2400_is_enabled(AspeedSoCState *soc, int function)
+{
+    switch (function) {
+    case ROMCS1:
+        return soc->scu.pinmux_ctrl3 & (1 << 24);
+    case ROMCS2:
+        return soc->scu.pinmux_ctrl3 & (1 << 25);
+    case ROMCS3:
+        return soc->scu.pinmux_ctrl3 & (1 << 26);
+    case ROMCS4:
+        return soc->scu.pinmux_ctrl3 & (1 << 27);
+    default:
+        return false;
+    }
+}
+
+/* AST2500 */
+enum {
+    FWSPICS1,
+    FWSPICS2,
+};
+
+static bool aspeed_soc_ast2500_is_enabled(AspeedSoCState *soc, int function)
+{
+    bool cond2 = !(soc->scu.regs[0x94 >> 2] & 0x3);
+
+    switch (function) {
+    case FWSPICS1:
+        return (soc->scu.pinmux_ctrl3 & (1 << 24)) && cond2;
+    case FWSPICS2:
+        return (soc->scu.pinmux_ctrl3 & (1 << 25)) && cond2;
+    default:
+        return false;
+    }
+}
+
+static int aspeed_fmc_get_cs(AspeedSoCState *soc, Error **errp)
+{
+    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
+    int cs = 1;
+
+    switch (sc->info->silicon_rev) {
+    case AST2400_A0_SILICON_REV:
+    case AST2400_A1_SILICON_REV:
+        cs += sc->info->is_enabled(soc, ROMCS1);
+        cs += sc->info->is_enabled(soc, ROMCS2);
+        cs += sc->info->is_enabled(soc, ROMCS3);
+        cs += sc->info->is_enabled(soc, ROMCS4);
+        break;
+    case AST2500_A0_SILICON_REV:
+    case AST2500_A1_SILICON_REV:
+        cs += sc->info->is_enabled(soc, FWSPICS1);
+        cs += sc->info->is_enabled(soc, FWSPICS2);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    return cs;
+}
+
 static void aspeed_soc_realize(DeviceState *dev, Error **errp)
 {
     int i;
     AspeedSoCState *s = ASPEED_SOC(dev);
     AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
     Error *err = NULL, *local_err = NULL;
+    int fmc_num_cs;
 
     /* IO space */
     memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
@@ -251,7 +329,13 @@ static void aspeed_soc_realize(DeviceSta
                        qdev_get_gpio_in(DEVICE(&s->vic), 12));
 
     /* FMC */
-    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
+    fmc_num_cs = aspeed_fmc_get_cs(s, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
     object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
     error_propagate(&err, local_err);
     if (err) {
Index: qemu-aspeed.git/include/hw/arm/aspeed_soc.h
===================================================================
--- qemu-aspeed.git.orig/include/hw/arm/aspeed_soc.h
+++ qemu-aspeed.git/include/hw/arm/aspeed_soc.h
@@ -52,6 +52,8 @@ typedef struct AspeedSoCInfo {
     const hwaddr *spi_bases;
     const char *fmc_typename;
     const char **spi_typename;
+
+    bool (*is_enabled)(AspeedSoCState *obj, int function);
 } AspeedSoCInfo;
 
 typedef struct AspeedSoCClass {
Index: qemu-aspeed.git/hw/misc/aspeed_scu.c
===================================================================
--- qemu-aspeed.git.orig/hw/misc/aspeed_scu.c
+++ qemu-aspeed.git/hw/misc/aspeed_scu.c
@@ -246,6 +246,7 @@ static void aspeed_scu_reset(DeviceState
     s->regs[SILICON_REV] = s->silicon_rev;
     s->regs[HW_STRAP1] = s->hw_strap1;
     s->regs[HW_STRAP2] = s->hw_strap2;
+    s->regs[PINMUX_CTRL3] = s->pinmux_ctrl3;
 }
 
 static uint32_t aspeed_silicon_revs[] = {
@@ -299,6 +300,7 @@ static Property aspeed_scu_properties[]
     DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
     DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
     DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
+    DEFINE_PROP_UINT32("pinmux-ctrl3", AspeedSCUState, pinmux_ctrl3, 0),
     DEFINE_PROP_END_OF_LIST(),
 };
 
Index: qemu-aspeed.git/include/hw/misc/aspeed_scu.h
===================================================================
--- qemu-aspeed.git.orig/include/hw/misc/aspeed_scu.h
+++ qemu-aspeed.git/include/hw/misc/aspeed_scu.h
@@ -29,6 +29,7 @@ typedef struct AspeedSCUState {
     uint32_t silicon_rev;
     uint32_t hw_strap1;
     uint32_t hw_strap2;
+    uint32_t pinmux_ctrl3;
 } AspeedSCUState;
 
 #define AST2400_A0_SILICON_REV   0x02000303U
Index: qemu-aspeed.git/hw/arm/aspeed.c
===================================================================
--- qemu-aspeed.git.orig/hw/arm/aspeed.c
+++ qemu-aspeed.git/hw/arm/aspeed.c
@@ -34,6 +34,7 @@ typedef struct AspeedBoardState {
 typedef struct AspeedBoardConfig {
     const char *soc_name;
     uint32_t hw_strap1;
+    uint32_t pinmux_ctrl3;
     const char *fmc_model;
     const char *spi_model;
 } AspeedBoardConfig;
@@ -84,18 +85,21 @@ static const AspeedBoardConfig aspeed_bo
     [PALMETTO_BMC] = {
         .soc_name  = "ast2400-a1",
         .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
+        .pinmux_ctrl3 = 0x00000000U,
         .fmc_model = "n25q256a",
         .spi_model = "mx25l25635e",
     },
     [AST2500_EVB]  = {
         .soc_name  = "ast2500-a1",
         .hw_strap1 = AST2500_EVB_HW_STRAP1,
+        .pinmux_ctrl3 = 0x00000000U,
         .fmc_model = "n25q256a",
         .spi_model = "mx25l25635e",
     },
     [ROMULUS_BMC]  = {
         .soc_name  = "ast2500-a1",
         .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
+        .pinmux_ctrl3 = 0x01000000U,
         .fmc_model = "n25q256a",
         .spi_model = "mx66l1g45g",
     },
@@ -144,6 +148,8 @@ static void aspeed_board_init(MachineSta
                            &error_abort);
     object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
                             &error_abort);
+    object_property_set_int(OBJECT(&bmc->soc), cfg->pinmux_ctrl3,
+                            "pinmux-ctrl3", &error_abort);
     object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
                              &error_abort);
 

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-23 19:08                   ` Cédric Le Goater
@ 2016-11-24  1:00                     ` Andrew Jeffery
  2016-11-24  6:31                       ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-24  1:00 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 14009 bytes --]

On Wed, 2016-11-23 at 20:08 +0100, Cédric Le Goater wrote:
> On 11/23/2016 10:33 AM, Cédric Le Goater wrote:
> > On 11/23/2016 02:22 AM, Andrew Jeffery wrote:
> > > On Tue, 2016-11-22 at 08:21 +0100, Cédric Le Goater wrote:
> > > > > > So we should set or unset these SCU regs when the SoC is created
> > > > > > and 
> > > > > > derive the wdt2 enablement from them. I suppose that the helper
> > > > > > routine 
> > > > > > to check for the conditions would be under SCU. 
> > > > > > 
> > > > > > or do we start a simple pinctrl model and slowly add the
> > > > > > enablement
> > > > > > of the pins we need ? 
> > > > > > 
> > > > > 
> > > > > From the discussion on IRC last night between Cédric, Joel and
> > > > > myself
> > > > > we decided to start on a pinmux backend to help manage these
> > > > > issues.
> > > > 
> > > > Do you have a rough idea of an API that the SoC could use ? 
> > > > 
> > > > 	enum AspeedAST2500Function {
> > > > > > > > 		FWSPICS0,
> > > > > > > > 		FWSPICS1,
> > > > > > > > 		FWSPICS2,
> > > > 	};
> > > > 
> > > > 	enum AspeedAST2400Function {
> > > > > > > > 		ROMCS1,
> > > > > > > > 		ROMCS2,
> > > > > > > > 		ROMCS3,
> > > > > > > > 		ROMCS4,
> > > > 	};
> > > > 
> > > > 	bool aspeed_pin_is_enabled(AspeedPinmux *p, int func);
> > > 
> > > Largely this looks good.
> > > 
> > > But bikeshedding a bit, but I think the function name should focus on
> > > functions, not pins. The function maps to some pin in the physical
> > > case, but for qemu's purposes we don't care about that just yet. Even
> > > if we do care in the future we can internally map functions to pins
> > > behind a pinmux abstraction. As such I think we can get away with a
> > > small tweak:
> > > 
> > > bool aspeed_pinmux_is_enabled(AspeedPinmux *p, int func);
> > 
> > ok Looks good to me. I will fake this in the patchset to ease the 
> > change in the future.
> > 
> > > Did you have any thought about how we hoist ourselves from a
> > > AspeedPinmux to say an AspeedAST2500Pinmux with this interface? 
> > 
> > There are different solutions. We could introduce a class like
> > 

*snip*

> > 
> > 
> > Conceptually, the SoC object would have a set of routines to handle
> > muxing. that seems ok to me as pinmux is a rather invasive component 
> > needing access to all controllers to be able to set the functions. 
> 
> Here is a quick patch for it to get an overall feeling.

Hmm. I don't know how I feel about mixing the pinmux with the SoC code.
 If you've seen the kernel pinmux driver this is going to get large, so
I'd prefer to isolate it a separate file so we can ignore it for the
most part. It's hard to do that if it's in the SoC code.

But!

On the basis of your patch below I'm reconsidering the pinmux idea. The
problem patch 11/38 was solving was knowing how many flash slaves we
have. Previously we thought that was completely described by the second
watchdog bit in the SCU, but now I can't think why we aren't simply
describing this as a property of the board (say in AspeedBoardConfig)
and avoiding pinmux contortions. Is there a problem with that? It is
yet another property to configure, but it's a board level problem at
the end of the day and will be *much* less code.

Thoughts?

Thanks for prototyping the patch.

Andrew

> 
> C.
> 
> 
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/arm/aspeed.c              |    6 +++
>  hw/arm/aspeed_soc.c          |   86 ++++++++++++++++++++++++++++++++++++++++++-
>  hw/misc/aspeed_scu.c         |    2 +
>  include/hw/arm/aspeed_soc.h  |    2 +
>  include/hw/misc/aspeed_scu.h |    1 
>  5 files changed, 96 insertions(+), 1 deletion(-)
> 
> Index: qemu-aspeed.git/hw/arm/aspeed_soc.c
> ===================================================================
> --- qemu-aspeed.git.orig/hw/arm/aspeed_soc.c
> +++ qemu-aspeed.git/hw/arm/aspeed_soc.c
> @@ -47,6 +47,9 @@ static const hwaddr aspeed_soc_ast2500_s
>  static const char *aspeed_soc_ast2500_typenames[] = {
>      "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
>  
> +static bool aspeed_soc_ast2400_is_enabled(AspeedSoCState *obj, int func);
> +static bool aspeed_soc_ast2500_is_enabled(AspeedSoCState *obj, int func);
> +
>  static const AspeedSoCInfo aspeed_socs[] = {
>      {
>          .name         = "ast2400-a0",
> @@ -58,6 +61,7 @@ static const AspeedSoCInfo aspeed_socs[]
>          .spi_bases    = aspeed_soc_ast2400_spi_bases,
>          .fmc_typename = "aspeed.smc.fmc",
>          .spi_typename = aspeed_soc_ast2400_typenames,
> +        .is_enabled   = aspeed_soc_ast2400_is_enabled,
>      }, {
>          .name         = "ast2400-a1",
>          .cpu_model    = "arm926",
> @@ -68,6 +72,7 @@ static const AspeedSoCInfo aspeed_socs[]
>          .spi_bases    = aspeed_soc_ast2400_spi_bases,
>          .fmc_typename = "aspeed.smc.fmc",
>          .spi_typename = aspeed_soc_ast2400_typenames,
> +        .is_enabled   = aspeed_soc_ast2400_is_enabled,
>      }, {
>          .name         = "ast2400",
>          .cpu_model    = "arm926",
> @@ -78,6 +83,7 @@ static const AspeedSoCInfo aspeed_socs[]
>          .spi_bases    = aspeed_soc_ast2400_spi_bases,
>          .fmc_typename = "aspeed.smc.fmc",
>          .spi_typename = aspeed_soc_ast2400_typenames,
> +        .is_enabled   = aspeed_soc_ast2500_is_enabled,
>      }, {
>          .name         = "ast2500-a1",
>          .cpu_model    = "arm1176",
> @@ -88,6 +94,7 @@ static const AspeedSoCInfo aspeed_socs[]
>          .spi_bases    = aspeed_soc_ast2500_spi_bases,
>          .fmc_typename = "aspeed.smc.ast2500-fmc",
>          .spi_typename = aspeed_soc_ast2500_typenames,
> +        .is_enabled   = aspeed_soc_ast2500_is_enabled,
>      },
>  };
>  
> @@ -149,6 +156,8 @@ static void aspeed_soc_init(Object *obj)
>                                "hw-strap1", &error_abort);
>      object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
>                                "hw-strap2", &error_abort);
> +    object_property_add_alias(obj, "pinmux-ctrl3", OBJECT(&s->scu),
> +                              "pinmux-ctrl3", &error_abort);
>  
>      object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
>      object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
> @@ -170,12 +179,81 @@ static void aspeed_soc_init(Object *obj)
>                                "ram-size", &error_abort);
>  }
>  
> +/* AST2400 */
> +enum {
> +    ROMCS1,
> +    ROMCS2,
> +    ROMCS3,
> +    ROMCS4,
> +};
> +
> +static bool aspeed_soc_ast2400_is_enabled(AspeedSoCState *soc, int function)
> +{
> +    switch (function) {
> +    case ROMCS1:
> +        return soc->scu.pinmux_ctrl3 & (1 << 24);
> +    case ROMCS2:
> +        return soc->scu.pinmux_ctrl3 & (1 << 25);
> +    case ROMCS3:
> +        return soc->scu.pinmux_ctrl3 & (1 << 26);
> +    case ROMCS4:
> +        return soc->scu.pinmux_ctrl3 & (1 << 27);
> +    default:
> +        return false;
> +    }
> +}
> +
> +/* AST2500 */
> +enum {
> +    FWSPICS1,
> +    FWSPICS2,
> +};
> +
> +static bool aspeed_soc_ast2500_is_enabled(AspeedSoCState *soc, int function)
> +{
> +    bool cond2 = !(soc->scu.regs[0x94 >> 2] & 0x3);
> +
> +    switch (function) {
> +    case FWSPICS1:
> +        return (soc->scu.pinmux_ctrl3 & (1 << 24)) && cond2;
> +    case FWSPICS2:
> +        return (soc->scu.pinmux_ctrl3 & (1 << 25)) && cond2;
> +    default:
> +        return false;
> +    }
> +}
> +
> +static int aspeed_fmc_get_cs(AspeedSoCState *soc, Error **errp)
> +{
> +    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(soc);
> +    int cs = 1;
> +
> +    switch (sc->info->silicon_rev) {
> +    case AST2400_A0_SILICON_REV:
> +    case AST2400_A1_SILICON_REV:
> +        cs += sc->info->is_enabled(soc, ROMCS1);
> +        cs += sc->info->is_enabled(soc, ROMCS2);
> +        cs += sc->info->is_enabled(soc, ROMCS3);
> +        cs += sc->info->is_enabled(soc, ROMCS4);
> +        break;
> +    case AST2500_A0_SILICON_REV:
> +    case AST2500_A1_SILICON_REV:
> +        cs += sc->info->is_enabled(soc, FWSPICS1);
> +        cs += sc->info->is_enabled(soc, FWSPICS2);
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
> +    return cs;
> +}
> +
>  static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>  {
>      int i;
>      AspeedSoCState *s = ASPEED_SOC(dev);
>      AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
>      Error *err = NULL, *local_err = NULL;
> +    int fmc_num_cs;
>  
>      /* IO space */
>      memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
> @@ -251,7 +329,13 @@ static void aspeed_soc_realize(DeviceSta
>                         qdev_get_gpio_in(DEVICE(&s->vic), 12));
>  
>      /* FMC */
> -    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
> +    fmc_num_cs = aspeed_fmc_get_cs(s, &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
>      object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
>      error_propagate(&err, local_err);
>      if (err) {
> Index: qemu-aspeed.git/include/hw/arm/aspeed_soc.h
> ===================================================================
> --- qemu-aspeed.git.orig/include/hw/arm/aspeed_soc.h
> +++ qemu-aspeed.git/include/hw/arm/aspeed_soc.h
> @@ -52,6 +52,8 @@ typedef struct AspeedSoCInfo {
>      const hwaddr *spi_bases;
>      const char *fmc_typename;
>      const char **spi_typename;
> +
> +    bool (*is_enabled)(AspeedSoCState *obj, int function);
>  } AspeedSoCInfo;
>  
>  typedef struct AspeedSoCClass {
> Index: qemu-aspeed.git/hw/misc/aspeed_scu.c
> ===================================================================
> --- qemu-aspeed.git.orig/hw/misc/aspeed_scu.c
> +++ qemu-aspeed.git/hw/misc/aspeed_scu.c
> @@ -246,6 +246,7 @@ static void aspeed_scu_reset(DeviceState
>      s->regs[SILICON_REV] = s->silicon_rev;
>      s->regs[HW_STRAP1] = s->hw_strap1;
>      s->regs[HW_STRAP2] = s->hw_strap2;
> +    s->regs[PINMUX_CTRL3] = s->pinmux_ctrl3;
>  }
>  
>  static uint32_t aspeed_silicon_revs[] = {
> @@ -299,6 +300,7 @@ static Property aspeed_scu_properties[]
>      DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
>      DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
>      DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
> +    DEFINE_PROP_UINT32("pinmux-ctrl3", AspeedSCUState, pinmux_ctrl3, 0),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> Index: qemu-aspeed.git/include/hw/misc/aspeed_scu.h
> ===================================================================
> --- qemu-aspeed.git.orig/include/hw/misc/aspeed_scu.h
> +++ qemu-aspeed.git/include/hw/misc/aspeed_scu.h
> @@ -29,6 +29,7 @@ typedef struct AspeedSCUState {
>      uint32_t silicon_rev;
>      uint32_t hw_strap1;
>      uint32_t hw_strap2;
> +    uint32_t pinmux_ctrl3;
>  } AspeedSCUState;
>  
>  #define AST2400_A0_SILICON_REV   0x02000303U
> Index: qemu-aspeed.git/hw/arm/aspeed.c
> ===================================================================
> --- qemu-aspeed.git.orig/hw/arm/aspeed.c
> +++ qemu-aspeed.git/hw/arm/aspeed.c
> @@ -34,6 +34,7 @@ typedef struct AspeedBoardState {
>  typedef struct AspeedBoardConfig {
>      const char *soc_name;
>      uint32_t hw_strap1;
> +    uint32_t pinmux_ctrl3;
>      const char *fmc_model;
>      const char *spi_model;
>  } AspeedBoardConfig;
> @@ -84,18 +85,21 @@ static const AspeedBoardConfig aspeed_bo
>      [PALMETTO_BMC] = {
>          .soc_name  = "ast2400-a1",
>          .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
> +        .pinmux_ctrl3 = 0x00000000U,
>          .fmc_model = "n25q256a",
>          .spi_model = "mx25l25635e",
>      },
>      [AST2500_EVB]  = {
>          .soc_name  = "ast2500-a1",
>          .hw_strap1 = AST2500_EVB_HW_STRAP1,
> +        .pinmux_ctrl3 = 0x00000000U,
>          .fmc_model = "n25q256a",
>          .spi_model = "mx25l25635e",
>      },
>      [ROMULUS_BMC]  = {
>          .soc_name  = "ast2500-a1",
>          .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
> +        .pinmux_ctrl3 = 0x01000000U,
>          .fmc_model = "n25q256a",
>          .spi_model = "mx66l1g45g",
>      },
> @@ -144,6 +148,8 @@ static void aspeed_board_init(MachineSta
>                             &error_abort);
>      object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
>                              &error_abort);
> +    object_property_set_int(OBJECT(&bmc->soc), cfg->pinmux_ctrl3,
> +                            "pinmux-ctrl3", &error_abort);
>      object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
>                               &error_abort);
>  
> 
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping
  2016-11-24  1:00                     ` Andrew Jeffery
@ 2016-11-24  6:31                       ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-24  6:31 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc


> Hmm. I don't know how I feel about mixing the pinmux with the SoC code.
>  If you've seen the kernel pinmux driver this is going to get large, so
> I'd prefer to isolate it a separate file so we can ignore it for the
> most part. It's hard to do that if it's in the SoC code.
> 
> But!
> 
> On the basis of your patch below I'm reconsidering the pinmux idea. The
> problem patch 11/38 was solving was knowing how many flash slaves we
> have. Previously we thought that was completely described by the second
> watchdog bit in the SCU, 
>
> but now I can't think why we aren't simply describing this as a property 
> of the board (say in AspeedBoardConfig) and avoiding pinmux contortions. 
> Is there a problem with that? 

No problem at all. It does not kill puppies.

I was trying to find a way to detect the presence of a second flash module
from the HW configuration. It is still currently a mystery to me because
enabling a function does not mean there is something behind the pins.

> It is yet another property to configure, but it's a board level problem 
> at the end of the day and will be *much* less code.
> 
> Thoughts?

Let's go that way. It should be simple as there is already a "num-cs"
property.

Thanks,

C. 

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

* Re: [PATCH qemu 14/38] aspeed/smc: autostrap CE0/1 configuration
  2016-11-18 14:21 ` [PATCH qemu 14/38] aspeed/smc: autostrap CE0/1 configuration Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-25  3:07   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-25  3:07 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 2344 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> HW autodetect type and size of the first and second flash modules of
> the FMC controller.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/ssi/aspeed_smc.c | 26 +++++++++++++++++++++-----
>  1 file changed, 21 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 1c6c5089f265..72a44150b0a1 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -39,11 +39,14 @@
>  #define   CONF_ENABLE_W2       18
>  #define   CONF_ENABLE_W1       17
>  #define   CONF_ENABLE_W0       16
> -#define   CONF_FLASH_TYPE4     9
> -#define   CONF_FLASH_TYPE3     7
> -#define   CONF_FLASH_TYPE2     5
> -#define   CONF_FLASH_TYPE1     3
> -#define   CONF_FLASH_TYPE0     1
> +#define   CONF_FLASH_TYPE4     8
> +#define   CONF_FLASH_TYPE3     6
> +#define   CONF_FLASH_TYPE2     4
> +#define   CONF_FLASH_TYPE1     2
> +#define   CONF_FLASH_TYPE0     0
> +#define      CONF_FLASH_TYPE_NOR   0x0
> +#define      CONF_FLASH_TYPE_NAND  0x1
> +#define      CONF_FLASH_TYPE_SPI   0x2
>  
>  /* CE Control Register */
>  #define R_CE_CTRL            (0x04 / 4)
> @@ -435,6 +438,19 @@ static void aspeed_smc_reset(DeviceState *d)
>          s->regs[R_SEG_ADDR0 + i] =
>              aspeed_smc_segment_to_reg(&s->ctrl->segments[i]);
>      }
> +
> +    /* CE0 and CE1 HW strapping for FMC controllers : SPI flash type
> +     * and 4BYTE mode
> +     */
> +    if (s->ctrl->segments == aspeed_segments_fmc ||
> +        s->ctrl->segments == aspeed_segments_ast2500_fmc) {
> +        s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI <<
> CONF_FLASH_TYPE0);
> +        s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI <<
> CONF_FLASH_TYPE1);
> +
> +        /* We should be able to detect the flash size in some ways.
> */
> +        s->regs[s->r_ce_ctrl] |= (1 << (CTRL_EXTENDED0));
> +        s->regs[s->r_ce_ctrl] |= (1 << (CTRL_EXTENDED1));
> +    }
>  }
>  
>  static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned
> int size)

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 15/38] aspeed/smc: handle SPI flash Command mode
  2016-11-18 14:21 ` [PATCH qemu 15/38] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-25  4:23   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-25  4:23 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 9407 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> The Aspeed SMC controllers have a mode (Command mode) in which
> accesses to the flash content are no different than doing MMIOs. The
> controller generates all the necessary commands to load (or store)
> data in memory.
> 
> However, accesses are restricted to the segment window assigned the
> the flash module by the controller. This window is defined by the
> Segment Address Register.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/ssi/aspeed_smc.c | 174
> ++++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 162 insertions(+), 12 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 72a44150b0a1..eec087199a22 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -69,6 +69,7 @@
>  #define R_CTRL0           (0x10 / 4)
>  #define   CTRL_CMD_SHIFT           16
>  #define   CTRL_CMD_MASK            0xff
> +#define   CTRL_AST2400_SPI_4BYTE   (1 << 13)
>  #define   CTRL_CE_STOP_ACTIVE      (1 << 2)
>  #define   CTRL_CMD_MODE_MASK       0x3
>  #define     CTRL_READMODE          0x0
> @@ -135,6 +136,16 @@
>  #define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
>  #define ASPEED_SOC_SPI2_FLASH_BASE  0x38000000
>  
> +/* Flash opcodes. */
> +#define SPI_OP_READ       0x03    /* Read data bytes (low frequency)
> */
> +#define SPI_OP_WRDI       0x04    /* Write disable */
> +#define SPI_OP_RDSR       0x05    /* Read status register */
> +#define SPI_OP_WREN       0x06    /* Write enable */
> +
> +/* Used for Macronix and Winbond flashes. */
> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
> +
>  /*
>   * Default segments mapping addresses and size for each slave per
>   * controller. These can be changed when board is initialized with
> the
> @@ -357,6 +368,98 @@ static inline bool aspeed_smc_is_writable(const
> AspeedSMCFlash *fl)
>      return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + fl->id));
>  }
>  
> +static inline int aspeed_smc_flash_cmd(const AspeedSMCFlash *fl)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    int cmd = (s->regs[s->r_ctrl0 + fl->id] >> CTRL_CMD_SHIFT) &
> CTRL_CMD_MASK;
> +
> +    /* This is the default value for read mode. In other modes, the
> +     * command should be defined */
> +    if (aspeed_smc_flash_mode(fl) == CTRL_READMODE) {
> +        cmd = SPI_OP_READ;
> +    }
> +
> +    if (!cmd) {
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: no command defined for
> mode %d\n",
> +                      __func__, aspeed_smc_flash_mode(fl));
> +    }
> +
> +    return cmd;
> +}
> +
> +static inline int aspeed_smc_flash_is_4byte(const AspeedSMCFlash
> *fl)
> +{
> +    AspeedSMCState *s = fl->controller;
> +
> +    if (s->ctrl->segments == aspeed_segments_spi) {
> +        return s->regs[s->r_ctrl0] & CTRL_AST2400_SPI_4BYTE;
> +    } else {
> +        return s->regs[s->r_ce_ctrl] & (1 << (CTRL_EXTENDED0 + fl-
> >id));
> +    }
> +}
> +
> +static void aspeed_smc_flash_select(const AspeedSMCFlash *fl)
> +{
> +    AspeedSMCState *s = fl->controller;
> +
> +    s->regs[s->r_ctrl0 + fl->id] &= ~CTRL_CE_STOP_ACTIVE;
> +    qemu_set_irq(s->cs_lines[fl->id],
> aspeed_smc_is_ce_stop_active(fl));
> +}
> +
> +static void aspeed_smc_flash_unselect(const AspeedSMCFlash *fl)
> +{
> +    AspeedSMCState *s = fl->controller;
> +
> +    s->regs[s->r_ctrl0 + fl->id] |= CTRL_CE_STOP_ACTIVE;
> +    qemu_set_irq(s->cs_lines[fl->id],
> aspeed_smc_is_ce_stop_active(fl));
> +}
> +
> +static uint32_t aspeed_smc_check_segment_addr(AspeedSMCFlash *fl,
> uint32_t addr)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    AspeedSegments seg;
> +
> +    aspeed_smc_reg_to_segment(s->regs[R_SEG_ADDR0 + fl->id], &seg);
> +    if ((addr & (seg.size - 1)) != addr) {
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: invalid address 0x%08x for CS%d segment :
> "
> +                      "[ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
> +                      s->ctrl->name, addr, fl->id, seg.addr,
> +                      seg.addr + seg.size);
> +    }
> +
> +    addr &= seg.size - 1;
> +    return addr;
> +}
> +
> +static void aspeed_smc_flash_setup_read(AspeedSMCFlash *fl, uint32_t
> addr)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    uint8_t cmd = aspeed_smc_flash_cmd(fl);
> +
> +    /*
> +     * To be checked: I am not sure the Aspeed SPI controller needs
> to
> +     * enable writes when running in READ/FREAD command mode
> +     */
> +
> +    /* access can not exceed CS segment */
> +    addr = aspeed_smc_check_segment_addr(fl, addr);
> +
> +    /* TODO: do we have to send 4BYTE each time ? */
> +    if (aspeed_smc_flash_is_4byte(fl)) {
> +        ssi_transfer(s->spi, SPI_OP_EN4B);
> +    }
> +
> +    ssi_transfer(s->spi, cmd);
> +
> +    if (aspeed_smc_flash_is_4byte(fl)) {
> +        ssi_transfer(s->spi, (addr >> 24) & 0xff);
> +    }
> +    ssi_transfer(s->spi, (addr >> 16) & 0xff);
> +    ssi_transfer(s->spi, (addr >> 8) & 0xff);
> +    ssi_transfer(s->spi, (addr & 0xff));
> +}
> +
>  static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr,
> unsigned size)
>  {
>      AspeedSMCFlash *fl = opaque;
> @@ -364,19 +467,55 @@ static uint64_t aspeed_smc_flash_read(void
> *opaque, hwaddr addr, unsigned size)
>      uint64_t ret = 0;
>      int i;
>  
> -    if (aspeed_smc_is_usermode(fl)) {
> +    switch (aspeed_smc_flash_mode(fl)) {
> +    case CTRL_USERMODE:
>          for (i = 0; i < size; i++) {
>              ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
>          }
> -    } else {
> -        qemu_log_mask(LOG_UNIMP, "%s: usermode not implemented\n",
> -                      __func__);
> -        ret = -1;
> +        break;
> +    case CTRL_READMODE:
> +    case CTRL_FREADMODE:
> +        aspeed_smc_flash_select(fl);
> +        aspeed_smc_flash_setup_read(fl, addr);
> +
> +        for (i = 0; i < size; i++) {
> +            ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
> +        }
> +
> +        aspeed_smc_flash_unselect(fl);
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid flash mode
> %d\n",
> +                      __func__, aspeed_smc_flash_mode(fl));
>      }
>  
>      return ret;
>  }
>  
> +static void aspeed_smc_flash_setup_write(AspeedSMCFlash *fl,
> uint32_t addr)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    uint8_t cmd = aspeed_smc_flash_cmd(fl);
> +
> +    /* Flash access can not exceed CS segment */
> +    addr = aspeed_smc_check_segment_addr(fl, addr);
> +
> +    /* TODO: do we have to send 4BYTE each time ? */
> +    if (aspeed_smc_flash_is_4byte(fl)) {
> +        ssi_transfer(s->spi, SPI_OP_EN4B);
> +    }
> +
> +    ssi_transfer(s->spi, SPI_OP_WREN);
> +    ssi_transfer(s->spi, cmd);
> +
> +    if (aspeed_smc_flash_is_4byte(fl)) {
> +        ssi_transfer(s->spi, (addr >> 24) & 0xff);
> +    }
> +    ssi_transfer(s->spi, (addr >> 16) & 0xff);
> +    ssi_transfer(s->spi, (addr >> 8) & 0xff);
> +    ssi_transfer(s->spi, (addr & 0xff));
> +}
> +
>  static void aspeed_smc_flash_write(void *opaque, hwaddr addr,
> uint64_t data,
>                             unsigned size)
>  {
> @@ -390,14 +529,25 @@ static void aspeed_smc_flash_write(void
> *opaque, hwaddr addr, uint64_t data,
>          return;
>      }
>  
> -    if (!aspeed_smc_is_usermode(fl)) {
> -        qemu_log_mask(LOG_UNIMP, "%s: usermode not implemented\n",
> -                      __func__);
> -        return;
> -    }
> +    switch (aspeed_smc_flash_mode(fl)) {
> +    case CTRL_USERMODE:
> +        for (i = 0; i < size; i++) {
> +            ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
> +        }
> +        break;
> +    case CTRL_WRITEMODE:
> +        aspeed_smc_flash_select(fl);
> +        aspeed_smc_flash_setup_write(fl, addr);
> +
> +        for (i = 0; i < size; i++) {
> +            ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
> +        }
>  
> -    for (i = 0; i < size; i++) {
> -        ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
> +        aspeed_smc_flash_unselect(fl);
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid flash mode
> %d\n",
> +                      __func__, aspeed_smc_flash_mode(fl));
>      }
>  }
>  

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 16/38] aspeed/smc: add tests for Command mode
  2016-11-18 14:21 ` [PATCH qemu 16/38] aspeed/smc: add tests for " Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-25  4:30   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-25  4:30 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 5081 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> 0005 tests add a read_page_mem test
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  tests/m25p80-test.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 86 insertions(+)
> 
> diff --git a/tests/m25p80-test.c b/tests/m25p80-test.c
> index cb7ec81f1a6d..3d449bd194a9 100644
> --- a/tests/m25p80-test.c
> +++ b/tests/m25p80-test.c
> @@ -36,6 +36,9 @@
>  #define   CRTL_EXTENDED0       0  /* 32 bit addressing for SPI */
>  #define R_CTRL0             0x10
>  #define   CTRL_CE_STOP_ACTIVE  (1 << 2)
> +#define   CTRL_READMODE        0x0
> +#define   CTRL_FREADMODE       0x1
> +#define   CTRL_WRITEMODE       0x2
>  #define   CTRL_USERMODE        0x3
>  
>  #define ASPEED_FMC_BASE    0x1E620000
> @@ -76,6 +79,22 @@ static void spi_conf(uint32_t value)
>      writel(ASPEED_FMC_BASE + R_CONF, conf);
>  }
>  
> +static void spi_ce_ctrl(uint32_t value)
> +{
> +    uint32_t conf = readl(ASPEED_FMC_BASE + R_CE_CTRL);
> +
> +    conf |= value;
> +    writel(ASPEED_FMC_BASE + R_CE_CTRL, conf);
> +}
> +
> +static void spi_ctrl_setmode(uint8_t mode, uint8_t cmd)
> +{
> +    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
> +    ctrl &= ~(CTRL_USERMODE | 0xff << 16);
> +    ctrl |= mode | (cmd << 16);
> +    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
> +}
> +
>  static void spi_ctrl_start_user(void)
>  {
>      uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
> @@ -128,6 +147,18 @@ static void read_page(uint32_t addr, uint32_t *page)
>      spi_ctrl_stop_user();
>  }
>  
> +static void read_page_mem(uint32_t addr, uint32_t *page)
> +{
> +    int i;
> +
> +    /* move out USER mode to use direct reads from the AHB bus */
> +    spi_ctrl_setmode(CTRL_READMODE, READ);
> +
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        page[i] = make_be32(readl(ASPEED_FLASH_BASE + addr + i * 4));
> +    }
> +}
> +
>  static void test_erase_sector(void)
>  {
>      uint32_t some_page_addr = 0x600 * PAGE_SIZE;
> @@ -195,6 +226,7 @@ static void test_write_page(void)
>  
>      spi_ctrl_start_user();
>      writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
> +    writeb(ASPEED_FLASH_BASE, WREN);
>      writeb(ASPEED_FLASH_BASE, PP);
>      writel(ASPEED_FLASH_BASE, make_be32(my_page_addr));
>  
> @@ -217,6 +249,58 @@ static void test_write_page(void)
>      }
>  }
>  
> +static void test_read_page_mem(void)
> +{
> +    uint32_t my_page_addr = 0x14000 * PAGE_SIZE; /* beyond 16MB */
> +    uint32_t some_page_addr = 0x15000 * PAGE_SIZE;
> +    uint32_t page[PAGE_SIZE / 4];
> +    int i;
> +
> +    /* Enable 4BYTE mode for flash. This is should be strapped by HW
> +     * for CE0 anyhow.
> +     */
> +    spi_ce_ctrl(1 << CRTL_EXTENDED0);
> +
> +    /* Check what was written */
> +    read_page_mem(my_page_addr, page);
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
> +    }
> +
> +    /* Check some other page. It should be full of 0xff */
> +    read_page_mem(some_page_addr, page);
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        g_assert_cmphex(page[i], ==, 0xffffffff);
> +    }
> +}
> +
> +static void test_write_page_mem(void)
> +{
> +    uint32_t my_page_addr = 0x15000 * PAGE_SIZE;
> +    uint32_t page[PAGE_SIZE / 4];
> +    int i;
> +
> +    /* Enable 4BYTE mode for flash. This is should be strapped by HW
> +     * for CE0 anyhow.
> +     */
> +    spi_ce_ctrl(1 << CRTL_EXTENDED0);
> +
> +    /* move out USER mode to use direct writes to the AHB bus */
> +    spi_ctrl_setmode(CTRL_WRITEMODE, PP);
> +
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        writel(ASPEED_FLASH_BASE + my_page_addr + i * 4,
> +               make_be32(my_page_addr + i * 4));
> +    }
> +
> +    /* Check what was written */
> +    read_page_mem(my_page_addr, page);
> +    for (i = 0; i < PAGE_SIZE / 4; i++) {
> +        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
> +    }
> +}
> +
> +
>  static char tmp_path[] = "/tmp/qtest.m25p80.XXXXXX";
>  
>  int main(int argc, char **argv)
> @@ -242,6 +326,8 @@ int main(int argc, char **argv)
>      qtest_add_func("/m25p80/erase_sector", test_erase_sector);
>      qtest_add_func("/m25p80/erase_all",  test_erase_all);
>      qtest_add_func("/m25p80/write_page", test_write_page);
> +    qtest_add_func("/m25p80/read_page_mem", test_read_page_mem);
> +    qtest_add_func("/m25p80/write_page_mem", test_write_page_mem);
>  
>      ret = g_test_run();
>  

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 17/38] aspeed/smc: unfold the AspeedSMCController array
  2016-11-18 14:21 ` [PATCH qemu 17/38] aspeed/smc: unfold the AspeedSMCController array Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-25  4:31   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-25  4:31 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 6597 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> This is getting difficult to read. Also add a 'has_dma' field for
> each
> controller type.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/ssi/aspeed_smc.c         | 91
> ++++++++++++++++++++++++++++++++++++---------
>  include/hw/ssi/aspeed_smc.h |  1 +
>  2 files changed, 74 insertions(+), 18 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index eec087199a22..8e7e3bd9e335 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -184,24 +184,79 @@ static const AspeedSegments
> aspeed_segments_ast2500_spi2[] = {
>  };
>  
>  static const AspeedSMCController controllers[] = {
> -    { "aspeed.smc.smc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
> -      CONF_ENABLE_W0, 5, aspeed_segments_legacy,
> -      ASPEED_SOC_SMC_FLASH_BASE, 0x6000000 },
> -    { "aspeed.smc.fmc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
> -      CONF_ENABLE_W0, 5, aspeed_segments_fmc,
> -      ASPEED_SOC_FMC_FLASH_BASE, 0x10000000 },
> -    { "aspeed.smc.spi", R_SPI_CONF, 0xff, R_SPI_CTRL0,
> R_SPI_TIMINGS,
> -      SPI_CONF_ENABLE_W0, 1, aspeed_segments_spi,
> -      ASPEED_SOC_SPI_FLASH_BASE, 0x10000000 },
> -    { "aspeed.smc.ast2500-fmc", R_CONF, R_CE_CTRL, R_CTRL0,
> R_TIMINGS,
> -      CONF_ENABLE_W0, 3, aspeed_segments_ast2500_fmc,
> -      ASPEED_SOC_FMC_FLASH_BASE, 0x10000000 },
> -    { "aspeed.smc.ast2500-spi1", R_CONF, R_CE_CTRL, R_CTRL0,
> R_TIMINGS,
> -      CONF_ENABLE_W0, 2, aspeed_segments_ast2500_spi1,
> -      ASPEED_SOC_SPI_FLASH_BASE, 0x8000000 },
> -    { "aspeed.smc.ast2500-spi2", R_CONF, R_CE_CTRL, R_CTRL0,
> R_TIMINGS,
> -      CONF_ENABLE_W0, 2, aspeed_segments_ast2500_spi2,
> -      ASPEED_SOC_SPI2_FLASH_BASE, 0x8000000 },
> +    {
> +        .name              = "aspeed.smc.smc",
> +        .r_conf            = R_CONF,
> +        .r_ce_ctrl         = R_CE_CTRL,
> +        .r_ctrl0           = R_CTRL0,
> +        .r_timings         = R_TIMINGS,
> +        .conf_enable_w0    = CONF_ENABLE_W0,
> +        .max_slaves        = 5,
> +        .segments          = aspeed_segments_legacy,
> +        .flash_window_base = ASPEED_SOC_SMC_FLASH_BASE,
> +        .flash_window_size = 0x6000000,
> +        .has_dma           = false,
> +    }, {
> +        .name              = "aspeed.smc.fmc",
> +        .r_conf            = R_CONF,
> +        .r_ce_ctrl         = R_CE_CTRL,
> +        .r_ctrl0           = R_CTRL0,
> +        .r_timings         = R_TIMINGS,
> +        .conf_enable_w0    = CONF_ENABLE_W0,
> +        .max_slaves        = 5,
> +        .segments          = aspeed_segments_fmc,
> +        .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
> +        .flash_window_size = 0x10000000,
> +        .has_dma           = true,
> +    }, {
> +        .name              = "aspeed.smc.spi",
> +        .r_conf            = R_SPI_CONF,
> +        .r_ce_ctrl         = 0xff,
> +        .r_ctrl0           = R_SPI_CTRL0,
> +        .r_timings         = R_SPI_TIMINGS,
> +        .conf_enable_w0    = SPI_CONF_ENABLE_W0,
> +        .max_slaves        = 1,
> +        .segments          = aspeed_segments_spi,
> +        .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
> +        .flash_window_size = 0x10000000,
> +        .has_dma           = false,
> +    }, {
> +        .name              = "aspeed.smc.ast2500-fmc",
> +        .r_conf            = R_CONF,
> +        .r_ce_ctrl         = R_CE_CTRL,
> +        .r_ctrl0           = R_CTRL0,
> +        .r_timings         = R_TIMINGS,
> +        .conf_enable_w0    = CONF_ENABLE_W0,
> +        .max_slaves        = 3,
> +        .segments          = aspeed_segments_ast2500_fmc,
> +        .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
> +        .flash_window_size = 0x10000000,
> +        .has_dma           = true,
> +    }, {
> +        .name              = "aspeed.smc.ast2500-spi1",
> +        .r_conf            = R_CONF,
> +        .r_ce_ctrl         = R_CE_CTRL,
> +        .r_ctrl0           = R_CTRL0,
> +        .r_timings         = R_TIMINGS,
> +        .conf_enable_w0    = CONF_ENABLE_W0,
> +        .max_slaves        = 2,
> +        .segments          = aspeed_segments_ast2500_spi1,
> +        .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
> +        .flash_window_size = 0x8000000,
> +        .has_dma           = false,
> +    }, {
> +        .name              = "aspeed.smc.ast2500-spi2",
> +        .r_conf            = R_CONF,
> +        .r_ce_ctrl         = R_CE_CTRL,
> +        .r_ctrl0           = R_CTRL0,
> +        .r_timings         = R_TIMINGS,
> +        .conf_enable_w0    = CONF_ENABLE_W0,
> +        .max_slaves        = 2,
> +        .segments          = aspeed_segments_ast2500_spi2,
> +        .flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE,
> +        .flash_window_size = 0x8000000,
> +        .has_dma           = false,
> +    },
>  };
>  
>  /*
> diff --git a/include/hw/ssi/aspeed_smc.h
> b/include/hw/ssi/aspeed_smc.h
> index c64954f6103f..39ee601940e8 100644
> --- a/include/hw/ssi/aspeed_smc.h
> +++ b/include/hw/ssi/aspeed_smc.h
> @@ -44,6 +44,7 @@ typedef struct AspeedSMCController {
>      const AspeedSegments *segments;
>      hwaddr flash_window_base;
>      uint32_t flash_window_size;
> +    bool has_dma;
>  } AspeedSMCController;
>  
>  typedef struct AspeedSMCFlash {

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 18/38] aspeed/smc: add a 'sdram_base' property
  2016-11-18 14:21 ` [PATCH qemu 18/38] aspeed/smc: add a 'sdram_base' property Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-25  4:35   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-25  4:35 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 2308 bytes --]

On Fri, 2016-11-18 at 15:21 +0100, Cédric Le Goater wrote:
> The setting of the DRAM address of the DMA transaction depends on the
> DRAM base address of the SoC, so we add a property to give this
> information to the model.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 7 +++++++
>  hw/ssi/aspeed_smc.c         | 1 +
>  include/hw/ssi/aspeed_smc.h | 3 +++
>  3 files changed, 11 insertions(+)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index fcf029f8c1c2..24354f700115 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -276,6 +276,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>      }
>  
>      object_property_set_int(OBJECT(&s->fmc), fmc_num_cs, "num-cs", &err);
> +    object_property_set_int(OBJECT(&s->fmc), sc->info->sdram_base, "sdram-base",
> +                            &local_err);
> +    error_propagate(&err, local_err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
>      object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
>      error_propagate(&err, local_err);
>      if (err) {
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 8e7e3bd9e335..24c78aa57537 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -819,6 +819,7 @@ static const VMStateDescription vmstate_aspeed_smc = {
>  };
>  
>  static Property aspeed_smc_properties[] = {
> +    DEFINE_PROP_UINT64("sdram-base", AspeedSMCState, sdram_base, 0),
>      DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1),
>      DEFINE_PROP_END_OF_LIST(),
>  };
> diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
> index 39ee601940e8..88a904849801 100644
> --- a/include/hw/ssi/aspeed_smc.h
> +++ b/include/hw/ssi/aspeed_smc.h
> @@ -96,6 +96,9 @@ typedef struct AspeedSMCState {
>      uint8_t r_timings;
>      uint8_t conf_enable_w0;
>  
> +    /* for DMA support */
> +    uint64_t sdram_base;
> +
>      AspeedSMCFlash *flashes;
>  } AspeedSMCState;
>  

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads
  2016-11-18 14:22 ` [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-28  1:35   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  1:35 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 5983 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> When doing fast read, a certain amount of dummy bytes should be sent
> before the read. This number is configurable in the controler CE0
> Control Register and needs to be modeled using fake transfers the
> flash module.
> 
> When the controller is configured for Command mode, the SPI command
> used to do the read is stored in the CE0 control register but, in User
> mode, we need to snoop into the flow of bytes to catch the command. It
> should be the first byte after CS select.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/ssi/aspeed_smc.c         | 57 ++++++++++++++++++++++++++++++++++++++-------
>  include/hw/ssi/aspeed_smc.h |  1 +
>  2 files changed, 50 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 9596ea94a3bc..c0ae07ef8c96 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -71,7 +71,9 @@
>  #define R_CTRL0           (0x10 / 4)
>  #define   CTRL_CMD_SHIFT           16
>  #define   CTRL_CMD_MASK            0xff
> +#define   CTRL_DUMMY_HIGH_SHIFT    14
>  #define   CTRL_AST2400_SPI_4BYTE   (1 << 13)
> +#define   CTRL_DUMMY_LOW_SHIFT     6
>  #define   CTRL_CE_STOP_ACTIVE      (1 << 2)
>  #define   CTRL_CMD_MODE_MASK       0x3
>  #define     CTRL_READMODE          0x0
> @@ -151,6 +153,7 @@
>  #define SPI_OP_WRDI       0x04    /* Write disable */
>  #define SPI_OP_RDSR       0x05    /* Read status register */
>  #define SPI_OP_WREN       0x06    /* Write enable */
> +#define SPI_OP_READ_FAST  0x0b    /* Read data bytes (high frequency) */
>  
>  /* Used for Macronix and Winbond flashes. */
>  #define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
> @@ -510,6 +513,12 @@ static void aspeed_smc_flash_setup_read(AspeedSMCFlash *fl, uint32_t addr)
>      /* access can not exceed CS segment */
>      addr = aspeed_smc_check_segment_addr(fl, addr);
>  
> +    /*
> +     * Remember command as we might need to send dummy bytes before
> +     * reading data
> +     */
> +    fl->cmd = cmd;
> +
>      /* TODO: do we have to send 4BYTE each time ? */
>      if (aspeed_smc_flash_is_4byte(fl)) {
>          ssi_transfer(s->spi, SPI_OP_EN4B);
> @@ -525,27 +534,49 @@ static void aspeed_smc_flash_setup_read(AspeedSMCFlash *fl, uint32_t addr)
>      ssi_transfer(s->spi, (addr & 0xff));
>  }
>  
> +static int aspeed_smc_flash_dummies(const AspeedSMCFlash *fl)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    uint32_t r_ctrl0 = s->regs[s->r_ctrl0 + fl->id];
> +
> +    return ((((r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1) << 2) |
> +            ((r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3)) * 8;
> +}
> +
> +static uint64_t aspeed_smc_flash_do_read(AspeedSMCFlash *fl, unsigned size)
> +{
> +    AspeedSMCState *s = fl->controller;
> +    uint64_t ret = 0;
> +    int i;
> +
> +    if (fl->cmd == SPI_OP_READ_FAST) {
> +        for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
> +            ssi_transfer(s->spi, 0x0);
> +        }
> +    }
> +    fl->cmd = 0;
> +
> +    for (i = 0; i < size; i++) {
> +        ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
> +    }
> +    return ret;
> +}
> +
>  static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
>  {
>      AspeedSMCFlash *fl = opaque;
> -    const AspeedSMCState *s = fl->controller;
>      uint64_t ret = 0;
> -    int i;
>  
>      switch (aspeed_smc_flash_mode(fl)) {
>      case CTRL_USERMODE:
> -        for (i = 0; i < size; i++) {
> -            ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
> -        }
> +        ret = aspeed_smc_flash_do_read(fl, size);
>          break;
>      case CTRL_READMODE:
>      case CTRL_FREADMODE:
>          aspeed_smc_flash_select(fl);
>          aspeed_smc_flash_setup_read(fl, addr);
>  
> -        for (i = 0; i < size; i++) {
> -            ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
> -        }
> +        ret = aspeed_smc_flash_do_read(fl, size);
>  
>          aspeed_smc_flash_unselect(fl);
>          break;
> @@ -596,6 +627,15 @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
>  
>      switch (aspeed_smc_flash_mode(fl)) {
>      case CTRL_USERMODE:
> +        /*
> +         * First write after chip select is the chip command. Remember
> +         * it as we might need to send dummy bytes before reading
> +         * data. It will be reseted when the chip is unselected.
> +         */
> +        if (!fl->cmd) {
> +            fl->cmd = data & 0xff;
> +        }
> +
>          for (i = 0; i < size; i++) {
>              ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
>          }
> @@ -629,6 +669,7 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
>  static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
>  {
>      AspeedSMCState *s = fl->controller;
> +    fl->cmd = 0;
>      qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
>  }
>  
> diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
> index 88a904849801..3ae0a369073d 100644
> --- a/include/hw/ssi/aspeed_smc.h
> +++ b/include/hw/ssi/aspeed_smc.h
> @@ -52,6 +52,7 @@ typedef struct AspeedSMCFlash {
>  
>      uint8_t id;
>      uint32_t size;
> +    uint8_t cmd;
>  
>      MemoryRegion mmio;
>      DeviceState *flash;

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region
  2016-11-18 14:22 ` [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-28  1:44   ` Andrew Jeffery
  2016-11-28  7:24     ` Cédric Le Goater
  1 sibling, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  1:44 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 5536 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> The SPI controller of the AST2400 SoC does not support DMAs and
> segment registers, hence it has less registers. So we can adjust the
> size of the memory region holding the registers depending on the
> controller type. We can also remove the guest_error logging which is
> useless as the range of the region is strict enough.
> 
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/ssi/aspeed_smc.c         | 23 ++++++++---------------
>  include/hw/ssi/aspeed_smc.h |  1 +
>  2 files changed, 9 insertions(+), 15 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index c0ae07ef8c96..7d7800d96271 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -135,6 +135,8 @@
>  #define R_SPI_MISC_CTRL   (0x10 / 4)
>  #define R_SPI_TIMINGS     (0x14 / 4)
>  
> +#define R_SPI_MAX         (0x20 / 4)
> +
>  #define ASPEED_SOC_SMC_FLASH_BASE   0x10000000
>  #define ASPEED_SOC_FMC_FLASH_BASE   0x20000000
>  #define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
> @@ -221,6 +223,7 @@ static const AspeedSMCController controllers[] = {
>          .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
>          .flash_window_size = 0x10000000,
>          .has_dma           = true,
> +        .nregs             = ASPEED_SMC_R_MAX,
>      }, {
>          .name              = "aspeed.smc.spi",
>          .r_conf            = R_SPI_CONF,
> @@ -233,6 +236,7 @@ static const AspeedSMCController controllers[] = {
>          .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
>          .flash_window_size = 0x10000000,
>          .has_dma           = false,
> +        .nregs             = R_SPI_MAX,
>      }, {
>          .name              = "aspeed.smc.ast2500-fmc",
>          .r_conf            = R_CONF,
> @@ -245,6 +249,7 @@ static const AspeedSMCController controllers[] = {
>          .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
>          .flash_window_size = 0x10000000,
>          .has_dma           = true,
> +        .nregs             = ASPEED_SMC_R_MAX,
>      }, {
>          .name              = "aspeed.smc.ast2500-spi1",
>          .r_conf            = R_CONF,
> @@ -257,6 +262,7 @@ static const AspeedSMCController controllers[] = {
>          .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
>          .flash_window_size = 0x8000000,
>          .has_dma           = false,
> +        .nregs             = ASPEED_SMC_R_MAX,
>      }, {
>          .name              = "aspeed.smc.ast2500-spi2",
>          .r_conf            = R_CONF,
> @@ -269,6 +275,7 @@ static const AspeedSMCController controllers[] = {
>          .flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE,
>          .flash_window_size = 0x8000000,
>          .has_dma           = false,
> +        .nregs             = ASPEED_SMC_R_MAX,
>      },
>  };
>  
> @@ -712,13 +719,6 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
>  
>      addr >>= 2;
>  
> -    if (addr >= ARRAY_SIZE(s->regs)) {
> -        qemu_log_mask(LOG_GUEST_ERROR,
> -                      "%s: Out-of-bounds read at 0x%" HWADDR_PRIx "\n",
> -                      __func__, addr);
> -        return 0;
> -    }
> -
>      if (addr == s->r_conf ||
>          addr == s->r_timings ||
>          addr == s->r_ce_ctrl ||
> @@ -942,13 +942,6 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
>  
>      addr >>= 2;
>  
> -    if (addr >= ARRAY_SIZE(s->regs)) {
> -        qemu_log_mask(LOG_GUEST_ERROR,
> -                      "%s: Out-of-bounds write at 0x%" HWADDR_PRIx "\n",
> -                      __func__, addr);
> -        return;
> -    }
> -
>      if (addr == s->r_conf ||
>          addr == s->r_timings ||
>          addr == s->r_ce_ctrl) {
> @@ -1030,7 +1023,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
>  
>      /* The memory region for the controller registers */
>      memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
> -                          s->ctrl->name, ASPEED_SMC_R_MAX * 4);
> +                          s->ctrl->name, s->ctrl->nregs * 4);

It looks like you missed defining nregs for the "aspeed.smc.smc"
controller. This would suggest we need to.

Andrew

>      sysbus_init_mmio(sbd, &s->mmio);
>  
>      /*
> diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
> index 3ae0a369073d..91bad82e9c65 100644
> --- a/include/hw/ssi/aspeed_smc.h
> +++ b/include/hw/ssi/aspeed_smc.h
> @@ -45,6 +45,7 @@ typedef struct AspeedSMCController {
>      hwaddr flash_window_base;
>      uint32_t flash_window_size;
>      bool has_dma;
> +    uint32_t nregs;
>  } AspeedSMCController;
>  
>  typedef struct AspeedSMCFlash {

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 22/38] aspeed: use first SPI flash as a boot ROM
  2016-11-18 14:22 ` [PATCH qemu 22/38] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-28  1:47   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  1:47 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 3549 bytes --]

aOn Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> Fill a ROM region with the flash content to support U-Boot. This is a
> little hacky but until we can boot from a MMIO region, it seems
> difficult to do anything else.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 5e35d4562de0..3e1781f30f55 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -20,6 +20,8 @@
>  #include "qemu/log.h"
>  #include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
> +#include "hw/loader.h"
> +#include "qemu/error-report.h"
>  
>  static struct arm_boot_info aspeed_board_binfo = {
>      .board_id = -1, /* device-tree-only board */
> @@ -101,6 +103,28 @@ static const AspeedBoardConfig aspeed_boards[] = {
>      },
>  };
>  
> +#define FIRMWARE_ADDR 0x0
> +
> +static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
> +                           Error **errp)
> +{
> +    BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
> +    uint8_t *storage;
> +
> +    if (rom_size > blk_getlength(blk)) {
> +        rom_size = blk_getlength(blk);
> +    }
> +
> +    storage = g_new0(uint8_t, rom_size);
> +    if (blk_pread(blk, 0, storage, rom_size) < 0) {
> +        error_setg(errp, "failed to read the initial flash content");
> +        return;
> +    }
> +
> +    rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
> +    g_free(storage);
> +}
> +
>  static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
>                                        Error **errp)
>  {
> @@ -132,6 +156,7 @@ static void aspeed_board_init(MachineState *machine,
>  {
>      AspeedBoardState *bmc;
>      AspeedSoCClass *sc;
> +    DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
>  
>      bmc = g_new0(AspeedBoardState, 1);
>      object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
> @@ -163,6 +188,22 @@ static void aspeed_board_init(MachineState *machine,
>      aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
>      aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);
>  
> +    /* Install first FMC flash content as a boot rom. */
> +    if (drive0) {
> +        AspeedSMCFlash *fl = &bmc->soc.fmc.flashes[0];
> +        MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
> +
> +        /*
> +         * create a ROM region using the default mapping window size of
> +         * the flash module.
> +         */
> +        memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
> +                               fl->size, &error_abort);
> +        memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
> +                                    boot_rom);
> +        write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
> +    }
> +
>      aspeed_board_binfo.kernel_filename = machine->kernel_filename;
>      aspeed_board_binfo.initrd_filename = machine->initrd_filename;
>      aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller
  2016-11-18 14:22 ` [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-28  1:55   ` Andrew Jeffery
  2016-11-28 12:34     ` Cédric Le Goater
  1 sibling, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  1:55 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 3597 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> The lock register is unlocked with a write of a special value and
> locked with a write of any other value. When unlocked, reads return
> one and when locked a zero.
> 
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/misc/aspeed_sdmc.c         | 28 +++++++++++++++++++---------
>  include/hw/misc/aspeed_sdmc.h |  1 +
>  2 files changed, 20 insertions(+), 9 deletions(-)
> 
> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
> index 5f3ac0b6f608..867caa2d64dc 100644
> --- a/hw/misc/aspeed_sdmc.c
> +++ b/hw/misc/aspeed_sdmc.c
> @@ -83,17 +83,22 @@
>  static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
>  {
>      AspeedSDMCState *s = ASPEED_SDMC(opaque);
> +    uint64_t val = 0;
>  
>      addr >>= 2;
>  
> -    if (addr >= ARRAY_SIZE(s->regs)) {
> +    switch (addr) {
> +    case R_PROT:
> +        val = s->unlocked;
> +        break;
> +    default:
>          qemu_log_mask(LOG_GUEST_ERROR,
>                        "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
>                        __func__, addr);
> -        return 0;
> +        break;
>      }
>  
> -    return s->regs[addr];
> +    return val;

This suggests we only care about R_PROT - the change returns 0 for the
value of other registers. That doesn't seem right.

Andrew

>  }
>  
>  static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
> @@ -103,19 +108,18 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>  
>      addr >>= 2;
>  
> -    if (addr >= ARRAY_SIZE(s->regs)) {
> -        qemu_log_mask(LOG_GUEST_ERROR,
> -                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> -                      __func__, addr);
> +    if (addr == R_PROT) {
> +        s->unlocked = (data == PROT_KEY_UNLOCK);
>          return;
>      }
>  
> -    if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) {
> +    if (!s->unlocked) { /* TODO protect : MCR04 ∼ MCR7C */
>          qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
>          return;
>      }
>  
> -    if (addr == R_CONF) {
> +    switch (addr) {
> +    case R_CONF:
>          /* Make sure readonly bits are kept */
>          switch (s->silicon_rev) {
>          case AST2400_A0_SILICON_REV:
> @@ -128,6 +132,12 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>          default:
>              g_assert_not_reached();
>          }
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> +                      __func__, addr << 2);
> +        return;
>      }
>  
>      s->regs[addr] = data;
> diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
> index 551c8afdf4be..a4415d9efc2f 100644
> --- a/include/hw/misc/aspeed_sdmc.h
> +++ b/include/hw/misc/aspeed_sdmc.h
> @@ -28,6 +28,7 @@ typedef struct AspeedSDMCState {
>      uint32_t ram_bits;
>      uint64_t ram_size;
>  
> +    bool unlocked;
>  } AspeedSDMCState;
>  
>  #endif /* ASPEED_SDMC_H */

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run
  2016-11-18 14:22 ` [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run Cédric Le Goater
  2016-11-21  7:25   ` Joel Stanley
@ 2016-11-28  2:02   ` Andrew Jeffery
  2016-11-28 12:38     ` Cédric Le Goater
  1 sibling, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:02 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 9523 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> It helps in understanding the DRAM calibration sequence which is all
written in assembly, and may be rewritten in C one day.

This provides support only for the AST2400 SoC (DDR3). AST2500 still
uses the SOC_SCRATCH1 to pretend DRAM was already initialized.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/misc/aspeed_scu.c          |   2 +-
 hw/misc/aspeed_sdmc.c         | 188 ++++++++++++++++++++++++++++++++++++++++++
 include/hw/misc/aspeed_sdmc.h |   2 +-
 3 files changed, 190 insertions(+), 2 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 95022d3607ad..b5efba9121b2 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -100,7 +100,7 @@ static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
      [PCI_CTRL2]       = 0x20001A03U,
      [PCI_CTRL3]       = 0x04000030U,
      [SYS_RST_STATUS]  = 0x00000001U,
-     [SOC_SCRATCH1]    = 0x000000C0U, /* SoC completed DRAM init */
+     [SOC_SCRATCH1]    = 0x00000000U,
      [MISC_CTRL2]      = 0x00000023U,
      [RNG_CTRL]        = 0x0000000EU,
      [PINMUX_CTRL2]    = 0x0000F000U,
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 867caa2d64dc..c71d18953c1c 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -80,6 +80,114 @@
      ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT |            \
      ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
 
+/* MCR08: Graphics Memory Protection Register */
+#define R_GRAPHIC_MEM_PROT              (0x8 / 4)
+
+/* MCR0C: Refresh Timing Register */
+#define R_REFRESH_TIMING                (0x0C / 4)
+
+/* MCR10: AC Timing Register #1 */
+#define R_AC_TIMING1                    (0x10 / 4)
+
+/* MCR14: AC Timing Register #2 */
+#define R_AC_TIMING2                    (0x14 / 4)
+
+/* MCR18: CK/DQS Delay Control Register */
+#define R_CQDQS_DELAY_CTRL              (0x18 / 4)
+
+/* MCR1C: MCLK to MCLK2X Calibration(CBR) Status Register */
+#define R_MCLK_CALIB_STATUS             (0x1C / 4)
+#define   MCLK2X_PHASE                      (0x96 << 16)
+
+/* MCR20: DQS Input Phase Calibration Control and Status */
+#define R_DQS_INPUT_CALIB_STATUS        (0x20 / 4)
+
+/* MCR24: ????  */
+#define R_MCR24                         (0x24 / 4)
+
+/* MCR28: Mode Setting Control Register */
+#define R_MODE_SETTING_CTRL             (0x28 / 4)
+
+/* MCR2C: MRS/EMRS2 Mode Setting Register */
+#define R_MRS_MODE_SETTING_CTRL         (0x2C / 4)
+
+/* MCR30: EMRS/EMRS3 Mode Setting Register */
+#define R_EMRS_MODE_SETTING_CTRL        (0x30 / 4)
+
+/* MCR34: Power Control Register */
+#define R_POWER_CTRL                    (0x34 / 4)
+
+/* MCR38: Page Miss Latency Mask Register */
+#define R_PAGE_MISS_MASK                (0x38 / 4)
+
+/* MCR40: Maximum Grant Length Register #1 */
+#define R_MAX_GRANT_LEN1                (0x40 / 4)
+
+/* MCR44: Maximum Grant Length Register #2 */
+#define R_MAX_GRANT_LEN2                (0x44 / 4)
+
+/* MCR48: Maximum Grant Length Register #3 */
+#define R_MAX_GRANT_LEN3                (0x48 / 4)
+
+/* MCR4C: Maximum Grant Length Register #4 */
+#define R_MAX_GRANT_LEN4                (0x4C / 4)
+
+/* MCR50: Interrupt Control/Status Register */
+#define R_IRQ_STATUS_CTRL               (0x50 / 4)
+
+/* MCR54: ECC Protection Address Range Register */
+#define R_ECC_PROTECT                   (0x54 / 4)
+
+/* MCR58: ????  */
+#define R_MCR58                         (0x58 / 4)
+
+/* MCR60: IO Buffer Mode Register */
+#define R_IO_BUFFER_MODE                (0x60 / 4)
+
+/* MCR64: DLL Control Register #1 */
+#define R_DLL_CTRL                      (0x64 / 4)
+
+/* MCR68: DLL Control Register #2 */
+#define R_DLL_CTRL2                     (0x68 / 4)
+
+/* MCR6C: DDR IO Impedance Calibration Control */
+#define R_DDR_IO_IMPEDANCE_CTRL         (0x6C / 4)
+
+/* MCR70: ECC Testing Control/Status Register */
+#define R_ECC_STATUS_CTRL               (0x70 / 4)
+#define   ECC_TEST_FINISH                  (1 << 12)
+
+/* MCR74: Testing Start Address and Length Register */
+#define R_START_ADDR_LEN                (0x74 / 4)
+
+/* MCR78: Testing Fail DQ Bit Register */
+#define R_FAIL_DQ                       (0x78 / 4)
+
+/* MCR7C: Test Initial Value Register */
+#define R_TEST_INIT_VALUE               (0x7C / 4)
+
+/* MCR80: DQ Input Delay Calibration Control #1 */
+#define R_DQ_DELAY_CALIB_CTRL1          (0x80 / 4)
+#define   DQ_DELAY_CALIB_COUNT_DONE        (1 << 31)
+
+/* MCR84: DQ Input Delay Calibration Control #2 */
+#define R_DQ_DELAY_CALIB_CTRL2          (0x84 / 4)
+
+/* MCR88: DQ Input Delay Calibration Control #3 */
+#define R_DQ_DELAY_CALIB_CTRL3          (0x88 / 4)
+
+/* MCR8C: CK Duty Counter Value */
+#define R_CK_DUTY_VALUE                 (0x8C / 4)
+
+/* MCR100: AST2000 Backward Compatible SCU Password */
+#define R_COMPAT_SCU_PASSWORD           (0x100 / 4)
+
+/* MCR120: AST2000 Backward Compatible SCU MPLL Parameter */
+#define R_COMPAT_SCU_MPLL               (0x120 / 4)
+
+/* MCR170: AST2000 Backward Compatible SCU Hardware Strapping Value */
+#define R_COMPAT_SCU_HW_STRAPPING       (0x170 / 4)
+
 static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
 {
     AspeedSDMCState *s = ASPEED_SDMC(opaque);
@@ -91,6 +199,48 @@ static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
     case R_PROT:
         val = s->unlocked;
         break;
+    case R_CONF:
+    case R_GRAPHIC_MEM_PROT:
+    case R_REFRESH_TIMING:
+    case R_AC_TIMING1:
+    case R_AC_TIMING2:
+    case R_CQDQS_DELAY_CTRL:
+    case R_MCLK_CALIB_STATUS:
+    case R_DQS_INPUT_CALIB_STATUS:
+    case R_MCR24:
+    case R_MODE_SETTING_CTRL:
+    case R_MRS_MODE_SETTING_CTRL:
+    case R_EMRS_MODE_SETTING_CTRL:
+    case R_POWER_CTRL:
+    case R_PAGE_MISS_MASK:
+    case R_MAX_GRANT_LEN1:
+    case R_MAX_GRANT_LEN2:
+    case R_MAX_GRANT_LEN3:
+    case R_MAX_GRANT_LEN4:
+    case R_IRQ_STATUS_CTRL:
+    case R_ECC_PROTECT:
+    case R_MCR58:
+    case R_IO_BUFFER_MODE:
+    case R_DLL_CTRL:
+    case R_DLL_CTRL2:
+    case R_DDR_IO_IMPEDANCE_CTRL:
+    case R_START_ADDR_LEN:
+    case R_FAIL_DQ:
+    case R_TEST_INIT_VALUE:
+    case R_DQ_DELAY_CALIB_CTRL2:
+    case R_DQ_DELAY_CALIB_CTRL3:
+    case R_CK_DUTY_VALUE:
+    case R_COMPAT_SCU_PASSWORD:
+    case R_COMPAT_SCU_MPLL:
+    case R_COMPAT_SCU_HW_STRAPPING:

This is a lengthy list of registers. What are your thoughts about using
numeric range values with comments?

 case 0x08 ... 0x38: /* GFX memprotect, refresh timings ... */
 case 0x40 ... 0x58: /* grant length registers, ... */
 ...
  val = s->regs[addr];
  break;

Either way I'm probably not fussed, but I'm interested in your
thoughts.

This addresses my comment on the previous patch, but it would be good
not to break the SDMC commit-to-commit.

Andrew

> +        val = s->regs[addr];
+        break;
+    case R_DQ_DELAY_CALIB_CTRL1:
+        val = s->regs[addr] | DQ_DELAY_CALIB_COUNT_DONE;
+        break;
+    case R_ECC_STATUS_CTRL:
+        val = s->regs[addr] | ECC_TEST_FINISH;
+        break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
@@ -133,6 +283,42 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
             g_assert_not_reached();
         }
         break;
+    case R_GRAPHIC_MEM_PROT:
+    case R_REFRESH_TIMING:
+    case R_AC_TIMING1:
+    case R_AC_TIMING2:
+    case R_CQDQS_DELAY_CTRL:
+    case R_MCLK_CALIB_STATUS:
+    case R_DQS_INPUT_CALIB_STATUS:
+    case R_MCR24:
+    case R_MODE_SETTING_CTRL:
+    case R_MRS_MODE_SETTING_CTRL:
+    case R_EMRS_MODE_SETTING_CTRL:
+    case R_POWER_CTRL:
+    case R_PAGE_MISS_MASK:
+    case R_MAX_GRANT_LEN1:
+    case R_MAX_GRANT_LEN2:
+    case R_MAX_GRANT_LEN3:
+    case R_MAX_GRANT_LEN4:
+    case R_IRQ_STATUS_CTRL:
+    case R_ECC_PROTECT:
+    case R_MCR58:
+    case R_IO_BUFFER_MODE:
+    case R_DLL_CTRL:
+    case R_DLL_CTRL2:
+    case R_DDR_IO_IMPEDANCE_CTRL:
+    case R_ECC_STATUS_CTRL:
+    case R_START_ADDR_LEN:
+    case R_FAIL_DQ:
+    case R_TEST_INIT_VALUE:
+    case R_DQ_DELAY_CALIB_CTRL1:
+    case R_DQ_DELAY_CALIB_CTRL2:
+    case R_DQ_DELAY_CALIB_CTRL3:
+    case R_CK_DUTY_VALUE:
+    case R_COMPAT_SCU_PASSWORD:
+    case R_COMPAT_SCU_MPLL:
+    case R_COMPAT_SCU_HW_STRAPPING:
+        break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
@@ -221,6 +407,8 @@ static void aspeed_sdmc_reset(DeviceState *dev)
     default:
         g_assert_not_reached();
     }
+
+    s->regs[R_MCLK_CALIB_STATUS] = MCLK2X_PHASE;
 }
 
 static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index a4415d9efc2f..e073a6c9419a 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -14,7 +14,7 @@
 #define TYPE_ASPEED_SDMC "aspeed.sdmc"
 #define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
 
-#define ASPEED_SDMC_NR_REGS (0x8 >> 2)
+#define ASPEED_SDMC_NR_REGS (0x174 >> 2)
 
 typedef struct AspeedSDMCState {
     /*< private >*/

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3
  2016-11-22 16:57   ` Cédric Le Goater
@ 2016-11-28  2:04     ` Andrew Jeffery
  2016-11-28  9:51       ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:04 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 1700 bytes --]

On Tue, 2016-11-22 at 17:57 +0100, Cédric Le Goater wrote:
> On 11/18/2016 03:22 PM, Cédric Le Goater wrote:
> > Temperatures can be changed from the monitor with :
> > 
> > 	(qemu) qom-set /machine/unattached/device[2] temperature0 12000
> 
> 
> These devices should be defined at the machine level, in palmetto_bmc_init(), 
> and not at the SoC level. 

Agreed. Did you see my comments on Alistair's RTC patch along these
lines?

Andrew

> 
> C.
> 
> > > > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > ---
> >  hw/arm/aspeed_soc.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > index 24354f700115..2aa15d90cc31 100644
> > --- a/hw/arm/aspeed_soc.c
> > +++ b/hw/arm/aspeed_soc.c
> > @@ -268,6 +268,14 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
> >      sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
> >                         qdev_get_gpio_in(DEVICE(&s->vic), 12));
> >  
> > +    /* add a TMP423 temperature sensor */
> > +    dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&s->i2c), 2),
> > +                           "tmp423", 0x4c);
> > +    object_property_set_int(OBJECT(dev), 31000, "temperature0", &err);
> > +    object_property_set_int(OBJECT(dev), 28000, "temperature1", &err);
> > +    object_property_set_int(OBJECT(dev), 20000, "temperature2", &err);
> > +    object_property_set_int(OBJECT(dev), 110000, "temperature3", &err);
> > +
> >      /* FMC */
> >      fmc_num_cs = aspeed_fmc_get_cs(s, &err);
> >      if (err) {
> > 
> 
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0
  2016-11-18 14:22 ` [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0 Cédric Le Goater
  2016-11-21  7:27   ` Joel Stanley
  2016-11-22 17:00   ` Cédric Le Goater
@ 2016-11-28  2:05   ` Andrew Jeffery
  2016-11-28  2:09     ` Andrew Jeffery
  2 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:05 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 1172 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> The palmetto platform has a ds3231 RTC device but not qemu. Let's use
> a ds1338 instead which provides enough basic RTC features. Only alarms
> will be missing
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed_soc.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 2aa15d90cc31..d2bc0ba2070d 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -276,6 +276,10 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>      object_property_set_int(OBJECT(dev), 20000, "temperature2", &err);
>      object_property_set_int(OBJECT(dev), 110000, "temperature3", &err);
>  
> +    /* The palmetto platform expects a ds3231 RTC but a ds1338 is
> +     * enough to provide basic RTC features. Alarms will be missing */
> +    i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&s->i2c), 0), "ds1338", 0x68);
> +
>      /* FMC */
>      fmc_num_cs = aspeed_fmc_get_cs(s, &err);
>      if (err) {

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0
  2016-11-28  2:05   ` Andrew Jeffery
@ 2016-11-28  2:09     ` Andrew Jeffery
  2016-11-28  9:52       ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:09 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 1422 bytes --]

On Mon, 2016-11-28 at 12:35 +1030, Andrew Jeffery wrote:
> On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> > The palmetto platform has a ds3231 RTC device but not qemu. Let's
> > use
> > a ds1338 instead which provides enough basic RTC features. Only
> > alarms
> > will be missing
> > 
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> 
> Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

With the caveat that we move it to the board file. Evo needs an 'undo
send' option like gmail.

> 
> > ---
> >  hw/arm/aspeed_soc.c | 4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > index 2aa15d90cc31..d2bc0ba2070d 100644
> > --- a/hw/arm/aspeed_soc.c
> > +++ b/hw/arm/aspeed_soc.c
> > @@ -276,6 +276,10 @@ static void aspeed_soc_realize(DeviceState
> > *dev, Error **errp)
> >      object_property_set_int(OBJECT(dev), 20000, "temperature2",
> > &err);
> >      object_property_set_int(OBJECT(dev), 110000, "temperature3",
> > &err);
> >  
> > +    /* The palmetto platform expects a ds3231 RTC but a ds1338 is
> > +     * enough to provide basic RTC features. Alarms will be
> > missing */
> > +    i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&s->i2c), 0),
> > "ds1338", 0x68);
> > +
> >      /* FMC */
> >      fmc_num_cs = aspeed_fmc_get_cs(s, &err);
> >      if (err) {

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model
  2016-11-21 13:03   ` Cédric Le Goater
  2016-11-21 13:23     ` Joel Stanley
@ 2016-11-28  2:11     ` Andrew Jeffery
  2016-11-28  9:58       ` Cédric Le Goater
  1 sibling, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:11 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 11894 bytes --]

On Mon, 2016-11-21 at 14:03 +0100, Cédric Le Goater wrote:
> On 11/18/2016 03:22 PM, Cédric Le Goater wrote:
> > From: Joel Stanley <joel@jms.id.au>
> > 
> > Signed-off-by: Joel Stanley <joel@jms.id.au>
> > [clg: fixed compile breakage
> >       fixed io region size
> >       added  watchdog_perform_action() on timer expiry ]
> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > ---
> >  hw/watchdog/Makefile.objs        |   1 +
> >  hw/watchdog/wdt_aspeed.c         | 194
> > +++++++++++++++++++++++++++++++++++++++
> >  include/hw/watchdog/wdt_aspeed.h |  41 +++++++++
> >  3 files changed, 236 insertions(+)
> >  create mode 100644 hw/watchdog/wdt_aspeed.c
> >  create mode 100644 include/hw/watchdog/wdt_aspeed.h
> > 
> > diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
> > index 72e3ffd93c59..9589bed63a3d 100644
> > --- a/hw/watchdog/Makefile.objs
> > +++ b/hw/watchdog/Makefile.objs
> > @@ -2,3 +2,4 @@ common-obj-y += watchdog.o
> >  common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
> >  common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
> >  common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
> > +common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o
> > diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> > new file mode 100644
> > index 000000000000..29d9d7f91463
> > --- /dev/null
> > +++ b/hw/watchdog/wdt_aspeed.c
> > @@ -0,0 +1,194 @@
> > +/*
> > + * Copyright 2016 IBM Corporation
> > + *
> > + * This code is licensed under the GPL version 2 or later.  See
> > + * the COPYING file in the top-level directory.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qemu/log.h"
> > +#include "sysemu/watchdog.h"
> > +#include "hw/sysbus.h"
> > +#include "qemu/timer.h"
> > +#include "hw/watchdog/wdt_aspeed.h"
> > +
> > +#define WDT_IO_REGION_SIZE      0x1000
> > +
> > +#define WDT_STATUS              0x00
> > +#define WDT_RELOAD_VALUE        0x04
> > +#define WDT_RESTART             0x08
> > +#define WDT_CTRL                0x0C
> > +#define WDT_TIMEOUT_STATUS      0x10
> > +#define WDT_TIMEOUT_CLEAR       0x14
> > +#define WDT_RESET_WDITH         0x18
> 
> 
> May be we should reduce the size of WDT_IO_REGION_SIZE to 0x20
> to instantiate the three watchdog of the Aspeed AST2500 with 
> one class ? 
> 
> Here is the layout :
> 
> WDT00: WDT1 Counter Status Register
> WDT04: WDT1 Counter Reload Value Register
> WDT08: WDT1 Counter Restart Register
> WDT0C: WDT1 Control Register
> WDT10: WDT1 Timeout Status Register
> WDT14: WDT1 Clear Timeout Status Register
> WDT18: WDT1 Reset Width Register
> WDT1C: WDT1 Reset Mask Register (AST2500)
> 
> WDT20: WDT2 Counter Status Register
> WDT24: WDT2 Counter Reload Value Register
> WDT28: WDT2 Counter Restart Register
> WDT2C: WDT2 Control Register
> WDT30: WDT2 Timeout Status Register
> WDT34: WDT2 Clear Timeout Status Register
> WDT38: WDT2 Reset Width Register
> WDT3C: WDT2 Reset Mask Register  (AST2500)
> 
> WDT40: WDT3 Counter Status Register  (AST2500)
> WDT44: WDT3 Counter Reload Value Register  (AST2500)
> WDT48: WDT3 Counter Restart Register  (AST2500)
> WDT4C: WDT3 Control Register  (AST2500)
> WDT50: WDT3 Timeout Status Register  (AST2500)
> WDT54: WDT3 Clear Timeout Status Register  (AST2500)
> WDT5C: WDT3 Reset Mask Register  (AST2500)
> 

If we're hacking it, can we squash the timer fixups and clock rate
derivation into the initial commit? I don't like the idea of sending it
broken.

Andrew

> C.
> 
> 
> 
> 
> > +#define WDT_RESTART_MAGIC       0x4755
> > +
> > +static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset,
> > unsigned size)
> > +{
> > +    AspeedWDTState *s = ASPEED_WDT(opaque);
> > +
> > +    switch (offset) {
> > +    case WDT_STATUS:
> > +        return s->reg_status;
> > +    case WDT_RELOAD_VALUE:
> > +        return s->reg_reload_value;
> > +    case WDT_RESTART:
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: read from write-only reg at offset 0x%"
> > +                      HWADDR_PRIx "\n", __func__, offset);
> > +        return 0;
> > +    case WDT_CTRL:
> > +        return s->reg_ctrl;
> > +    case WDT_TIMEOUT_STATUS:
> > +    case WDT_TIMEOUT_CLEAR:
> > +    case WDT_RESET_WDITH:
> > +        qemu_log_mask(LOG_UNIMP,
> > +                      "%s: uninmplemented read at offset 0x%"
> > HWADDR_PRIx "\n",
> > +                      __func__, offset);
> > +        return 0;
> > +    default:
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: Out-of-bounds read at offset 0x%"
> > HWADDR_PRIx "\n",
> > +                      __func__, offset);
> > +        return 0;
> > +    }
> > +
> > +}
> > +
> > +static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t
> > data,
> > +                             unsigned size)
> > +{
> > +    AspeedWDTState *s = ASPEED_WDT(opaque);
> > +    bool en = data & BIT(0);
> > +
> > +    switch (offset) {
> > +    case WDT_STATUS:
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: write to read-only reg at offset 0x%"
> > +                      HWADDR_PRIx "\n", __func__, offset);
> > +        break;
> > +    case WDT_RELOAD_VALUE:
> > +        s->reg_reload_value = data;
> > +        break;
> > +    case WDT_RESTART:
> > +        if ((data & 0xFFFF) == 0x4755) {
> > +            s->reg_status = s->reg_reload_value;
> > +
> > +            if (s->enabled) {
> > +                timer_mod(s->timer,
> > +                          qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
> > +                          s->reg_reload_value *
> > NANOSECONDS_PER_SECOND);
> > +            }
> > +        }
> > +        break;
> > +    case WDT_CTRL:
> > +        if (en && !s->enabled) {
> > +            s->enabled = true;
> > +            timer_mod(s->timer,
> > +                      qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
> > +                      s->reg_reload_value *
> > NANOSECONDS_PER_SECOND);
> > +        } else if (!en && s->enabled) {
> > +            s->enabled = false;
> > +            timer_del(s->timer);
> > +        }
> > +        break;
> > +    case WDT_TIMEOUT_STATUS:
> > +    case WDT_TIMEOUT_CLEAR:
> > +    case WDT_RESET_WDITH:
> > +        qemu_log_mask(LOG_UNIMP,
> > +                      "%s: uninmplemented write at offset 0x%"
> > HWADDR_PRIx "\n",
> > +                      __func__, offset);
> > +        break;
> > +    default:
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: Out-of-bounds write at offset 0x%"
> > HWADDR_PRIx "\n",
> > +                      __func__, offset);
> > +    }
> > +    return;
> > +}
> > +
> > +static WatchdogTimerModel model = {
> > +    .wdt_name = TYPE_ASPEED_WDT,
> > +    .wdt_description = "aspeed watchdog device",
> > +};
> > +
> > +static const VMStateDescription vmstate_aspeed_wdt = {
> > +    .name = "vmstate_aspeed_wdt",
> > +    .version_id = 0,
> > +    .minimum_version_id = 0,
> > +    .fields = (VMStateField[]) {
> > +        VMSTATE_TIMER_PTR(timer, AspeedWDTState),
> > +        VMSTATE_BOOL(enabled, AspeedWDTState),
> > +        VMSTATE_END_OF_LIST()
> > +    }
> > +};
> > +
> > +static const MemoryRegionOps aspeed_wdt_ops = {
> > +    .read = aspeed_wdt_read,
> > +    .write = aspeed_wdt_write,
> > +    .endianness = DEVICE_LITTLE_ENDIAN,
> > +    .valid.min_access_size = 4,
> > +    .valid.max_access_size = 4,
> > +    .valid.unaligned = false,
> > +};
> > +
> > +static void aspeed_wdt_reset(DeviceState *dev)
> > +{
> > +    AspeedWDTState *s = ASPEED_WDT(dev);
> > +
> > +    s->reg_status = 0x3EF1480;
> > +    s->reg_reload_value = 0x03EF1480;
> > +    s->reg_restart = 0;
> > +    s->reg_ctrl = 0;
> > +
> > +    s->enabled = false;
> > +    timer_del(s->timer);
> > +}
> > +
> > +static void aspeed_wdt_timer_expired(void *dev)
> > +{
> > +    AspeedWDTState *s = ASPEED_WDT(dev);
> > +
> > +    qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
> > +    watchdog_perform_action();
> > +    timer_del(s->timer);
> > +}
> > +
> > +static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
> > +{
> > +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > +    AspeedWDTState *s = ASPEED_WDT(dev);
> > +
> > +    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> > aspeed_wdt_timer_expired,
> > +                            dev);
> > +
> > +    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_wdt_ops,
> > s,
> > +                          TYPE_ASPEED_WDT, WDT_IO_REGION_SIZE);
> > +    sysbus_init_mmio(sbd, &s->iomem);
> > +}
> > +
> > +static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->realize = aspeed_wdt_realize;
> > +    dc->reset = aspeed_wdt_reset;
> > +    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> > +    dc->vmsd = &vmstate_aspeed_wdt;
> > +}
> > +
> > +static const TypeInfo aspeed_wdt_info = {
> > +    .parent = TYPE_SYS_BUS_DEVICE,
> > +    .name  = TYPE_ASPEED_WDT,
> > +    .instance_size  = sizeof(AspeedWDTState),
> > +    .class_init = aspeed_wdt_class_init,
> > +};
> > +
> > +static void wdt_aspeed_register_types(void)
> > +{
> > +    watchdog_add_model(&model);
> > +    type_register_static(&aspeed_wdt_info);
> > +}
> > +
> > +type_init(wdt_aspeed_register_types)
> > diff --git a/include/hw/watchdog/wdt_aspeed.h
> > b/include/hw/watchdog/wdt_aspeed.h
> > new file mode 100644
> > index 000000000000..dbf45ae968db
> > --- /dev/null
> > +++ b/include/hw/watchdog/wdt_aspeed.h
> > @@ -0,0 +1,41 @@
> > +/*
> > + * ASPEED Watchdog Controller
> > + *
> > + * Copyright (C) 2016 IBM Corp.
> > + *
> > + * This code is licensed under the GPL version 2 or later. See the
> > + * COPYING file in the top-level directory.
> > + */
> > +#ifndef ASPEED_WDT_H
> > +#define ASPEED_WDT_H
> > +
> > +#include "hw/sysbus.h"
> > +
> > +#define TYPE_ASPEED_WDT "aspeed.wdt"
> > +#define ASPEED_WDT(obj) \
> > +    OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT)
> > +#define ASPEED_WDT_CLASS(klass) \
> > +    OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT)
> > +#define ASPEED_WDT_GET_CLASS(obj) \
> > +    OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT)
> > +
> > +#define WDT_ASPEED_INIT      0
> > +#define WDT_ASPEED_CHANGE    1
> > +#define WDT_ASPEED_CANCEL    2
> > +
> > +typedef struct AspeedWDTState {
> > +    /*< private >*/
> > +    SysBusDevice parent_obj;
> > +    QEMUTimer *timer;
> > +    bool enabled;
> > +
> > +    /*< public >*/
> > +    MemoryRegion iomem;
> > +
> > +    uint32_t reg_status;
> > +    uint32_t reg_reload_value;
> > +    uint32_t reg_restart;
> > +    uint32_t reg_ctrl;
> > +} AspeedWDTState;
> > +
> > +#endif  /* ASPEED_WDT_H */
> > 
> 
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 31/38] aspeed: add a watchdog controller
  2016-11-18 14:22 ` [PATCH qemu 31/38] aspeed: add a watchdog controller Cédric Le Goater
  2016-11-21  7:27   ` Joel Stanley
@ 2016-11-28  2:12   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:12 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 2688 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 13 +++++++++++++
>  include/hw/arm/aspeed_soc.h |  2 ++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index d2bc0ba2070d..2926ed2dd46d 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -31,6 +31,7 @@
>  #define ASPEED_SOC_SCU_BASE         0x1E6E2000
>  #define ASPEED_SOC_SRAM_BASE        0x1E720000
>  #define ASPEED_SOC_TIMER_BASE       0x1E782000
> +#define ASPEED_SOC_WDT_BASE         0x1E785000
>  #define ASPEED_SOC_I2C_BASE         0x1E78A000
>  
>  static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
> @@ -168,6 +169,10 @@ static void aspeed_soc_init(Object *obj)
>                           sc->info->silicon_rev);
>      object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
>                                "ram-size", &error_abort);
> +
> +    object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ASPEED_WDT);
> +    object_property_add_child(obj, "wdt", OBJECT(&s->wdt), NULL);
> +    qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
>  }
>  
>  static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
> @@ -329,6 +334,14 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>      sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE);
> +
> +    /* Watch dog */
> +    object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, ASPEED_SOC_WDT_BASE);
>  }
>  
>  static void aspeed_soc_class_init(ObjectClass *oc, void *data)
> diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> index 1ab5deaa0813..dbec0c159885 100644
> --- a/include/hw/arm/aspeed_soc.h
> +++ b/include/hw/arm/aspeed_soc.h
> @@ -19,6 +19,7 @@
>  #include "hw/timer/aspeed_timer.h"
>  #include "hw/i2c/aspeed_i2c.h"
>  #include "hw/ssi/aspeed_smc.h"
> +#include "hw/watchdog/wdt_aspeed.h"
>  
>  #define ASPEED_SPIS_NUM  2
>  
> @@ -37,6 +38,7 @@ typedef struct AspeedSoCState {
>      AspeedSMCState fmc;
>      AspeedSMCState spi[ASPEED_SPIS_NUM];
>      AspeedSDMCState sdmc;
> +    AspeedWDTState wdt;
>  } AspeedSoCState;
>  
>  #define TYPE_ASPEED_SOC "aspeed-soc"

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 34/38] net: add FTGMAC100 support
  2016-11-18 14:22 ` [PATCH qemu 34/38] net: add FTGMAC100 support Cédric Le Goater
@ 2016-11-28  2:13   ` Andrew Jeffery
  0 siblings, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:13 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 39029 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> The FTGMAC100 device is configured and controlled via a set of
> registers available on AHB bus. Packets are transmitted and received
> using DMA ring buffers.
> 
> The model is for the moment complete enough to satisfy U-Boot and the
> Linux kernel but there are areas that need some more attention :
> 
>  - PHY support, this is a copy paste from the Coldfire model
>  - Automatic receive/transmit polling, no timers are used to poll the
>    ring buffers descriptors. We just expect the qemu nic backend to
>    push packets when they arrive.
>  - CRC
> 
> And some are still on the TODO list (not used today in the drivers) :
> 
>  - Ethernet Address Filtering
>  - Multicast
>  - High priority queues
>  - VLAN
>  - NCSI, may be we could add n/w filters
>  - etc.
> 
> The code is based on the Coldfire Fast Ethernet Controller emulation.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Tested-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  default-configs/arm-softmmu.mak |   1 +
>  hw/net/Makefile.objs            |   1 +
>  hw/net/ftgmac100.c              | 900 ++++++++++++++++++++++++++++++++++++++++
>  include/hw/net/ftgmac100.h      |  62 +++
>  4 files changed, 964 insertions(+)
>  create mode 100644 hw/net/ftgmac100.c
>  create mode 100644 include/hw/net/ftgmac100.h
> 
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index e3ac9e0ec104..81def25bfd54 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -29,6 +29,7 @@ CONFIG_LAN9118=y
>  CONFIG_SMC91C111=y
>  CONFIG_ALLWINNER_EMAC=y
>  CONFIG_IMX_FEC=y
> +CONFIG_FTGMAC100=y
>  CONFIG_DS1338=y
>  CONFIG_PFLASH_CFI01=y
>  CONFIG_PFLASH_CFI02=y
> diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
> index 610ed3e7ae64..7ca51d85a672 100644
> --- a/hw/net/Makefile.objs
> +++ b/hw/net/Makefile.objs
> @@ -26,6 +26,7 @@ common-obj-$(CONFIG_IMX_FEC) += imx_fec.o
>  common-obj-$(CONFIG_CADENCE) += cadence_gem.o
>  common-obj-$(CONFIG_STELLARIS_ENET) += stellaris_enet.o
>  common-obj-$(CONFIG_LANCE) += lance.o
> +common-obj-$(CONFIG_FTGMAC100) += ftgmac100.o
>  
>  obj-$(CONFIG_ETRAXFS) += etraxfs_eth.o
>  obj-$(CONFIG_COLDFIRE) += mcf_fec.o
> diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
> new file mode 100644
> index 000000000000..22573ff956fd
> --- /dev/null
> +++ b/hw/net/ftgmac100.c
> @@ -0,0 +1,900 @@
> +/*
> + * Faraday FTGMAC100 Gigabit Ethernet
> + *
> + * Copyright (C) 2016 IBM Corp.
> + *
> + * Based on Coldfire Fast Ethernet Controller emulation.
> + *
> + * Copyright (c) 2007 CodeSourcery.
> + *
> + *  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 "hw/net/ftgmac100.h"
> +#include "sysemu/dma.h"
> +#include "qemu/log.h"
> +
> +/* For crc32 */
> +#include <zlib.h>
> +
> +#ifdef FTGMAC100_DEBUG
> +#define DEBUG(fmt, ...) do {         \
> +        fprintf(stderr,  "%s: " fmt, __func__, ## __VA_ARGS__);  \
> +    } while (0);
> +#else
> +    #define DEBUG(...) do {} while (0)
> +#endif
> +
> +#ifdef FTGMAC100_PHY_DEBUG
> +#define PHY_DEBUG(fmt, ...) do {         \
> +        fprintf(stderr,  "%s: " fmt, __func__, ## __VA_ARGS__);  \
> +    } while (0);
> +#else
> +    #define PHY_DEBUG(...) do {} while (0)
> +#endif
> +
> +/*
> + * IFTGMAC100 registers
> + */
> +#define FTGMAC100_ISR             0x00
> +#define FTGMAC100_IER             0x04
> +#define FTGMAC100_MAC_MADR        0x08
> +#define FTGMAC100_MAC_LADR        0x0c
> +
> +#define FTGMAC100_NPTXPD          0x18
> +#define FTGMAC100_RXPD            0x1C
> +#define FTGMAC100_NPTXR_BADR      0x20
> +#define FTGMAC100_RXR_BADR        0x24
> +#define FTGMAC100_APTC            0x34
> +#define FTGMAC100_RBSR            0x4c
> +
> +#define FTGMAC100_MACCR           0x50
> +#define FTGMAC100_PHYCR           0x60
> +#define FTGMAC100_PHYDATA         0x64
> +
> +/*
> + * Interrupt status register & interrupt enable register
> + */
> +#define FTGMAC100_INT_RPKT_BUF    (1 << 0)
> +#define FTGMAC100_INT_RPKT_FIFO   (1 << 1)
> +#define FTGMAC100_INT_NO_RXBUF    (1 << 2)
> +#define FTGMAC100_INT_RPKT_LOST   (1 << 3)
> +#define FTGMAC100_INT_XPKT_ETH    (1 << 4)
> +#define FTGMAC100_INT_XPKT_FIFO   (1 << 5)
> +#define FTGMAC100_INT_NO_NPTXBUF  (1 << 6)
> +#define FTGMAC100_INT_XPKT_LOST   (1 << 7)
> +#define FTGMAC100_INT_AHB_ERR     (1 << 8)
> +#define FTGMAC100_INT_PHYSTS_CHG  (1 << 9)
> +#define FTGMAC100_INT_NO_HPTXBUF  (1 << 10)
> +
> +/*
> + * Automatic polling timer control register
> + */
> +#define FTGMAC100_APTC_RXPOLL_CNT(x)        ((x) & 0xf)
> +#define FTGMAC100_APTC_RXPOLL_TIME_SEL      (1 << 4)
> +#define FTGMAC100_APTC_TXPOLL_CNT(x)        (((x) >> 8) & 0xf)
> +#define FTGMAC100_APTC_TXPOLL_TIME_SEL      (1 << 12)
> +
> +/*
> + * PHY control register
> + */
> +#define FTGMAC100_PHYCR_MIIRD               (1 << 26)
> +#define FTGMAC100_PHYCR_MIIWR               (1 << 27)
> +
> +/*
> + * PHY data register
> + */
> +#define FTGMAC100_PHYDATA_MIIWDATA(x)       ((x) & 0xffff)
> +#define FTGMAC100_PHYDATA_MIIRDATA(phydata) (((phydata) >> 16) & 0xffff)
> +
> +
> +/*
> + * MAC control register
> + */
> +#define FTGMAC100_MACCR_TXDMA_EN         (1 << 0)
> +#define FTGMAC100_MACCR_RXDMA_EN         (1 << 1)
> +#define FTGMAC100_MACCR_TXMAC_EN         (1 << 2)
> +#define FTGMAC100_MACCR_RXMAC_EN         (1 << 3)
> +#define FTGMAC100_MACCR_RM_VLAN          (1 << 4)
> +#define FTGMAC100_MACCR_HPTXR_EN         (1 << 5)
> +#define FTGMAC100_MACCR_LOOP_EN          (1 << 6)
> +#define FTGMAC100_MACCR_ENRX_IN_HALFTX   (1 << 7)
> +#define FTGMAC100_MACCR_FULLDUP          (1 << 8)
> +#define FTGMAC100_MACCR_GIGA_MODE        (1 << 9)
> +#define FTGMAC100_MACCR_CRC_APD          (1 << 10)
> +#define FTGMAC100_MACCR_RX_RUNT          (1 << 12)
> +#define FTGMAC100_MACCR_JUMBO_LF         (1 << 13)
> +#define FTGMAC100_MACCR_RX_ALL           (1 << 14)
> +#define FTGMAC100_MACCR_HT_MULTI_EN      (1 << 15)
> +#define FTGMAC100_MACCR_RX_MULTIPKT      (1 << 16)
> +#define FTGMAC100_MACCR_RX_BROADPKT      (1 << 17)
> +#define FTGMAC100_MACCR_DISCARD_CRCERR   (1 << 18)
> +#define FTGMAC100_MACCR_FAST_MODE        (1 << 19)
> +#define FTGMAC100_MACCR_SW_RST           (1 << 31)
> +
> +/*
> + * Transmit descriptor, aligned to 16 bytes
> + */
> +struct ftgmac100_txdes {
> +        unsigned int        txdes0;
> +        unsigned int        txdes1;
> +        unsigned int        txdes2;      /* not used by HW */
> +        unsigned int        txdes3;      /* TXBUF_BADR */
> +} __attribute__ ((aligned(16)));
> +
> +#define FTGMAC100_TXDES0_TXBUF_SIZE(x)   ((x) & 0x3fff)
> +#define FTGMAC100_TXDES0_EDOTR           (1 << 15)
> +#define FTGMAC100_TXDES0_CRC_ERR         (1 << 19)
> +#define FTGMAC100_TXDES0_LTS             (1 << 28)
> +#define FTGMAC100_TXDES0_FTS             (1 << 29)
> +#define FTGMAC100_TXDES0_TXDMA_OWN       (1 << 31)
> +
> +#define FTGMAC100_TXDES1_VLANTAG_CI(x)   ((x) & 0xffff)
> +#define FTGMAC100_TXDES1_INS_VLANTAG     (1 << 16)
> +#define FTGMAC100_TXDES1_TCP_CHKSUM      (1 << 17)
> +#define FTGMAC100_TXDES1_UDP_CHKSUM      (1 << 18)
> +#define FTGMAC100_TXDES1_IP_CHKSUM       (1 << 19)
> +#define FTGMAC100_TXDES1_LLC             (1 << 22)
> +#define FTGMAC100_TXDES1_TX2FIC          (1 << 30)
> +#define FTGMAC100_TXDES1_TXIC            (1 << 31)
> +
> +/*
> + * Receive descriptor, aligned to 16 bytes
> + */
> +struct ftgmac100_rxdes {
> +        unsigned int        rxdes0;
> +        unsigned int        rxdes1;
> +        unsigned int        rxdes2;      /* not used by HW */
> +        unsigned int        rxdes3;      /* RXBUF_BADR */
> +} __attribute__ ((aligned(16)));
> +
> +#define FTGMAC100_RXDES0_VDBC            0x3fff
> +#define FTGMAC100_RXDES0_EDORR           (1 << 15)
> +#define FTGMAC100_RXDES0_MULTICAST       (1 << 16)
> +#define FTGMAC100_RXDES0_BROADCAST       (1 << 17)
> +#define FTGMAC100_RXDES0_RX_ERR          (1 << 18)
> +#define FTGMAC100_RXDES0_CRC_ERR         (1 << 19)
> +#define FTGMAC100_RXDES0_FTL             (1 << 20)
> +#define FTGMAC100_RXDES0_RUNT            (1 << 21)
> +#define FTGMAC100_RXDES0_RX_ODD_NB       (1 << 22)
> +#define FTGMAC100_RXDES0_FIFO_FULL       (1 << 23)
> +#define FTGMAC100_RXDES0_PAUSE_OPCODE    (1 << 24)
> +#define FTGMAC100_RXDES0_PAUSE_FRAME     (1 << 25)
> +#define FTGMAC100_RXDES0_LRS             (1 << 28)
> +#define FTGMAC100_RXDES0_FRS             (1 << 29)
> +#define FTGMAC100_RXDES0_RXPKT_RDY       (1 << 31)
> +
> +#define FTGMAC100_RXDES1_VLANTAG_CI      0xffff
> +#define FTGMAC100_RXDES1_PROT_MASK       (0x3 << 20)
> +#define FTGMAC100_RXDES1_PROT_NONIP      (0x0 << 20)
> +#define FTGMAC100_RXDES1_PROT_IP         (0x1 << 20)
> +#define FTGMAC100_RXDES1_PROT_TCPIP      (0x2 << 20)
> +#define FTGMAC100_RXDES1_PROT_UDPIP      (0x3 << 20)
> +#define FTGMAC100_RXDES1_LLC             (1 << 22)
> +#define FTGMAC100_RXDES1_DF              (1 << 23)
> +#define FTGMAC100_RXDES1_VLANTAG_AVAIL   (1 << 24)
> +#define FTGMAC100_RXDES1_TCP_CHKSUM_ERR  (1 << 25)
> +#define FTGMAC100_RXDES1_UDP_CHKSUM_ERR  (1 << 26)
> +#define FTGMAC100_RXDES1_IP_CHKSUM_ERR   (1 << 27)
> +
> +/*
> + * PHY values (to be defined elsewhere ...)
> + */
> +#define PHY_INT_ENERGYON            (1 << 7)
> +#define PHY_INT_AUTONEG_COMPLETE    (1 << 6)
> +#define PHY_INT_FAULT               (1 << 5)
> +#define PHY_INT_DOWN                (1 << 4)
> +#define PHY_INT_AUTONEG_LP          (1 << 3)
> +#define PHY_INT_PARFAULT            (1 << 2)
> +#define PHY_INT_AUTONEG_PAGE        (1 << 1)
> +
> +/* Common Buffer Descriptor  */
> +typedef struct {
> +    uint32_t        des0;
> +    uint32_t        des1;
> +    uint32_t        des2;        /* not used by HW */
> +    uint32_t        des3;        /* TXBUF_BADR */
> +} Ftgmac100Desc  __attribute__ ((aligned(16)));
> +
> +/* max frame size is :
> + *
> + *   9216 for Jumbo frames (+ 4 for VLAN)
> + *   1518 for other frames (+ 4 for VLAN)
> + */
> +#define FTGMAC100_MAX_FRAME_SIZE(s)                             \
> +    ((s->maccr & FTGMAC100_MACCR_JUMBO_LF ? 9216 : 1518) + 4)
> +
> +static void ftgmac100_update_irq(Ftgmac100State *s);
> +
> +/*
> + * The MII phy could raise a GPIO to the processor which in turn
> + * could be handled as an interrpt by the OS.
> + * For now we don't handle any GPIO/interrupt line, so the OS will
> + * have to poll for the PHY status.
> + */
> +static void phy_update_irq(Ftgmac100State *s)
> +{
> +    ftgmac100_update_irq(s);
> +}
> +
> +static void phy_update_link(Ftgmac100State *s)
> +{
> +    /* Autonegotiation status mirrors link status.  */
> +    if (qemu_get_queue(s->nic)->link_down) {
> +        PHY_DEBUG("link is down\n");
> +        s->phy_status &= ~0x0024;
> +        s->phy_int |= PHY_INT_DOWN;
> +    } else {
> +        PHY_DEBUG("link is up\n");
> +        s->phy_status |= 0x0024;
> +        s->phy_int |= PHY_INT_ENERGYON;
> +        s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
> +    }
> +    phy_update_irq(s);
> +}
> +
> +static void ftgmac100_set_link(NetClientState *nc)
> +{
> +    phy_update_link(FTGMAC100(qemu_get_nic_opaque(nc)));
> +}
> +
> +static void phy_reset(Ftgmac100State *s)
> +{
> +    s->phy_status = 0x7809;
> +    s->phy_control = 0x3000;
> +    s->phy_advertise = 0x01e1;
> +    s->phy_int_mask = 0;
> +    s->phy_int = 0;
> +    phy_update_link(s);
> +}
> +
> +static uint32_t do_phy_read(Ftgmac100State *s, int reg)
> +{
> +    uint32_t val;
> +
> +    if (reg > 31) {
> +        /* we only advertise one phy */
> +        return 0;
> +    }
> +
> +    switch (reg) {
> +    case 0:     /* Basic Control */
> +        val = s->phy_control;
> +        break;
> +    case 1:     /* Basic Status */
> +        val = s->phy_status;
> +        break;
> +    case 2:     /* ID1 */
> +        val = 0x0007;
> +        break;
> +    case 3:     /* ID2 */
> +        val = 0xc0d1;
> +        break;
> +    case 4:     /* Auto-neg advertisement */
> +        val = s->phy_advertise;
> +        break;
> +    case 5:     /* Auto-neg Link Partner Ability */
> +        val = 0x0f71;
> +        break;
> +    case 6:     /* Auto-neg Expansion */
> +        val = 1;
> +        break;
> +        val = 0x0800;
> +        break;
> +    case 29:    /* Interrupt source.  */
> +        val = s->phy_int;
> +        s->phy_int = 0;
> +        phy_update_irq(s);
> +        break;
> +    case 30:    /* Interrupt mask */
> +        val = s->phy_int_mask;
> +        break;
> +    case 0x0a: /* 1000BASE-T status  */
> +    case 17:
> +    case 18:
> +    case 27:
> +    case 31:
> +        qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
> +                      __func__, reg);
> +        val = 0;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
> +                      __func__, reg);
> +        val = 0;
> +        break;
> +    }
> +
> +    PHY_DEBUG("PHY read 0x%04x @%d\n", val, reg);
> +    return val;
> +}
> +
> +static void do_phy_write(Ftgmac100State *s, int reg, uint32_t val)
> +{
> +    PHY_DEBUG("PHY: write 0x%04x @%d\n", val, reg);
> +
> +    if (reg > 31) {
> +        /* we only advertise one phy */
> +        return;
> +    }
> +
> +    switch (reg) {
> +    case 0:     /* Basic Control */
> +        if (val & 0x8000) {
> +            phy_reset(s);
> +        } else {
> +            s->phy_control = val & 0x7980;
> +            /* Complete autonegotiation immediately.  */
> +            if (val & 0x1000) {
> +                s->phy_status |= 0x0020;
> +            }
> +        }
> +        break;
> +    case 4:     /* Auto-neg advertisement */
> +        s->phy_advertise = (val & 0x2d7f) | 0x80;
> +        break;
> +    case 30:    /* Interrupt mask */
> +        s->phy_int_mask = val & 0xff;
> +        phy_update_irq(s);
> +        break;
> +    case 17:
> +    case 18:
> +    case 27:
> +    case 31:
> +        qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n",
> +                      __func__, reg);
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n",
> +                      __func__, reg);
> +        break;
> +    }
> +}
> +
> +static void ftgmac100_read_bd(Ftgmac100Desc *bd, dma_addr_t addr)
> +{
> +    dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
> +    bd->des0 = le32_to_cpu(bd->des0);
> +    bd->des1 = le32_to_cpu(bd->des1);
> +    bd->des2 = le32_to_cpu(bd->des2);
> +    bd->des3 = le32_to_cpu(bd->des3);
> +}
> +
> +static void ftgmac100_write_bd(Ftgmac100Desc *bd, dma_addr_t addr)
> +{
> +    Ftgmac100Desc lebd;
> +    lebd.des0 = cpu_to_le32(bd->des0);
> +    lebd.des1 = cpu_to_le32(bd->des1);
> +    lebd.des2 = cpu_to_le32(bd->des2);
> +    lebd.des3 = cpu_to_le32(bd->des3);
> +    dma_memory_write(&address_space_memory, addr, &lebd, sizeof(lebd));
> +}
> +
> +static void ftgmac100_update_irq(Ftgmac100State *s)
> +{
> +    uint32_t active;
> +    uint32_t changed;
> +
> +    active = s->isr & s->ier;
> +    changed = active ^ s->irq_state;
> +    if (changed) {
> +        qemu_set_irq(s->irq, active);
> +    }
> +    s->irq_state = active;
> +}
> +
> +/* Locate a possible first descriptor to transmit. When Linux resets
> + * the device, the indexes of ring buffers are cleared but the dma
> + * buffers are not, so we need to find a starting point.
> + */
> +static uint32_t ftgmac100_find_txdes(Ftgmac100State *s, uint32_t addr)
> +{
> +    Ftgmac100Desc bd;
> +
> +    while (1) {
> +        ftgmac100_read_bd(&bd, addr);
> +        if (bd.des0 & (FTGMAC100_TXDES0_FTS | FTGMAC100_TXDES0_EDOTR)) {
> +            break;
> +        }
> +        addr += sizeof(Ftgmac100Desc);
> +    }
> +    return addr;
> +}
> +
> +static void ftgmac100_do_tx(Ftgmac100State *s)
> +{
> +    int frame_size = 0;
> +    uint8_t frame[FTGMAC100_MAX_FRAME_SIZE(s)];
> +    uint8_t *ptr = frame;
> +    uint32_t addr;
> +
> +    addr = ftgmac100_find_txdes(s, s->tx_descriptor);
> +
> +    while (1) {
> +        Ftgmac100Desc bd;
> +        int len;
> +
> +        ftgmac100_read_bd(&bd, addr);
> +        if ((bd.des0 & FTGMAC100_TXDES0_TXDMA_OWN) == 0) {
> +            /* Run out of descriptors to transmit.  */
> +            s->isr |= FTGMAC100_INT_NO_NPTXBUF;
> +            break;
> +        }
> +        len = bd.des0 & 0x3FFF;
> +        if (frame_size + len > FTGMAC100_MAX_FRAME_SIZE(s)) {
> +            qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n",
> +                          __func__, len);
> +            len = FTGMAC100_MAX_FRAME_SIZE(s) - frame_size;
> +        }
> +        dma_memory_read(&address_space_memory, bd.des3, ptr, len);
> +        ptr += len;
> +        frame_size += len;
> +        if (bd.des0 & FTGMAC100_TXDES0_LTS) {
> +            /* Last buffer in frame.  */
> +            qemu_send_packet(qemu_get_queue(s->nic), frame, len);
> +            ptr = frame;
> +            frame_size = 0;
> +            if (bd.des1 & FTGMAC100_TXDES1_TXIC) {
> +                s->isr |= FTGMAC100_INT_XPKT_ETH;
> +            }
> +        }
> +
> +        if (bd.des1 & FTGMAC100_TXDES1_TX2FIC) {
> +            s->isr |= FTGMAC100_INT_XPKT_FIFO;
> +        }
> +        bd.des0 &= ~FTGMAC100_TXDES0_TXDMA_OWN;
> +
> +        /* Write back the modified descriptor.  */
> +        ftgmac100_write_bd(&bd, addr);
> +        /* Advance to the next descriptor.  */
> +        if (bd.des0 & FTGMAC100_TXDES0_EDOTR) {
> +            addr = s->tx_ring;
> +        } else {
> +            addr += sizeof(Ftgmac100Desc);
> +        }
> +    }
> +
> +    s->tx_descriptor = addr;
> +
> +    ftgmac100_update_irq(s);
> +}
> +
> +static void ftgmac100_enable_rx(Ftgmac100State *s)
> +{
> +    Ftgmac100Desc bd;
> +    uint32_t full;
> +
> +    /* Find an empty descriptor to use */
> +    while (1) {
> +        ftgmac100_read_bd(&bd, s->rx_descriptor);
> +        full = (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY);
> +        if (!full || bd.des0 & FTGMAC100_TXDES0_EDOTR) {
> +            break;
> +        }
> +        s->rx_descriptor += sizeof(Ftgmac100Desc);
> +    }
> +
> +    if (full) {
> +        DEBUG("RX buffer full\n");
> +    }
> +
> +    s->rx_enabled = (full == 0);
> +    if (s->rx_enabled) {
> +        qemu_flush_queued_packets(qemu_get_queue(s->nic));
> +    }
> +}
> +
> +/*
> + * This is purely informative. The HW can poll the RW (and RX) ring
> + * buffers for available descriptors but we don't need to trigger a
> + * timer for that in qemu.
> + */
> +static uint32_t ftgmac100_rxpoll(Ftgmac100State *s)
> +{
> +    /* Polling times :
> +     *
> +     * Speed      TIME_SEL=0    TIME_SEL=1
> +     *
> +     *    10         51.2 ms      819.2 ms
> +     *   100         5.12 ms      81.92 ms
> +     *  1000        1.024 ms     16.384 ms
> +     */
> +    static const int div[] = { 20, 200, 1000 };
> +
> +    uint32_t cnt = 1024 * FTGMAC100_APTC_RXPOLL_CNT(s->aptcr);
> +    uint32_t speed = (s->maccr & FTGMAC100_MACCR_FAST_MODE) ? 1 : 0;
> +    uint32_t period;
> +
> +    if (s->aptcr & FTGMAC100_APTC_RXPOLL_TIME_SEL) {
> +        cnt <<= 4;
> +    }
> +
> +    if (s->maccr & FTGMAC100_MACCR_GIGA_MODE) {
> +        speed = 2;
> +    }
> +
> +    period = cnt / div[speed];
> +
> +    DEBUG("polling in %d ms\n", period);
> +    return period;
> +}
> +
> +static void ftgmac100_reset(DeviceState *d)
> +{
> +    Ftgmac100State *s = FTGMAC100(d);
> +
> +    /* Reset the FTGMAC100 */
> +    s->isr = 0;
> +    s->ier = 0;
> +    s->rx_enabled = 0;
> +    s->maccr = 0;
> +    s->rx_ring = 0;
> +    s->rx_descriptor = 0;
> +    s->rbsr = 0x640; /* HW default according to u-boot driver */
> +    s->tx_ring = 0;
> +    s->tx_descriptor = 0;
> +    s->phycr = 0;
> +    s->phydata = 0;
> +    s->aptcr = 0;
> +
> +    /* We also reset the PHY */
> +    phy_reset(s);
> +}
> +
> +static uint64_t ftgmac100_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    Ftgmac100State *s = FTGMAC100(opaque);
> +
> +    DEBUG("reading from @ 0x%" HWADDR_PRIx "\n", addr);
> +
> +    switch (addr & 0xff) {
> +    case FTGMAC100_ISR:
> +        return s->isr;
> +    case FTGMAC100_IER:
> +        return s->ier;
> +    case FTGMAC100_MAC_MADR:
> +        return (s->conf.macaddr.a[0] << 8)  | s->conf.macaddr.a[1];
> +    case FTGMAC100_MAC_LADR:
> +        return (s->conf.macaddr.a[2] << 24) | (s->conf.macaddr.a[3] << 16) |
> +               (s->conf.macaddr.a[4] << 8)  |  s->conf.macaddr.a[5];
> +    case FTGMAC100_MACCR:
> +        return s->maccr;
> +    case FTGMAC100_PHYCR:
> +        return s->phycr;
> +    case FTGMAC100_PHYDATA:
> +        return s->phydata;
> +
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
> +                      HWADDR_PRIx "\n", TYPE_FTGMAC100, __func__, addr);
> +        return 0;
> +    }
> +}
> +
> +static void ftgmac100_write(void *opaque, hwaddr addr,
> +                          uint64_t value, unsigned size)
> +{
> +    Ftgmac100State *s = FTGMAC100(opaque);
> +
> +    DEBUG("writing 0x%08x @ 0x%" HWADDR_PRIx "\n", (int)value, addr);
> +
> +    switch (addr & 0xff) {
> +    case FTGMAC100_ISR: /* Interrupt status */
> +        s->isr &= ~value;
> +        break;
> +    case FTGMAC100_IER:  /* Interrupt control */
> +        s->ier = value;
> +        break;
> +    case FTGMAC100_MAC_MADR: /* MAC */
> +        s->conf.macaddr.a[0] = value >> 8;
> +        s->conf.macaddr.a[1] = value;
> +        break;
> +    case FTGMAC100_MAC_LADR:
> +        s->conf.macaddr.a[2] = value >> 24;
> +        s->conf.macaddr.a[3] = value >> 16;
> +        s->conf.macaddr.a[4] = value >> 8;
> +        s->conf.macaddr.a[5] = value;
> +        break;
> +
> +    case FTGMAC100_RXR_BADR:  /* Ring buffer address */
> +        s->rx_ring = value;
> +        s->rx_descriptor = s->rx_ring;
> +        break;
> +
> +    case FTGMAC100_RBSR: /* DMA buffer size */
> +        s->rbsr = value;
> +        break;
> +
> +    case FTGMAC100_NPTXR_BADR:  /* Transmit buffer address */
> +        s->tx_ring = value;
> +        s->tx_descriptor = s->tx_ring;
> +        break;
> +
> +    case FTGMAC100_NPTXPD: /* Trigger transmit */
> +        if (s->maccr & FTGMAC100_MACCR_TXDMA_EN) {
> +            ftgmac100_do_tx(s);
> +        }
> +        break;
> +
> +    case FTGMAC100_RXPD: /* Receive Poll Demand Register */
> +        if ((s->maccr & FTGMAC100_MACCR_RXDMA_EN) && !s->rx_enabled) {
> +            /*
> +             * TODO: This is required for u-boot but clearly, this is
> +             * broken.
> +             */
> +            ftgmac100_enable_rx(s);
> +        }
> +        break;
> +
> +    case FTGMAC100_APTC: /* Automatic polling */
> +        s->aptcr = value;
> +
> +        if (FTGMAC100_APTC_RXPOLL_CNT(s->aptcr)) {
> +            ftgmac100_rxpoll(s);
> +        }
> +
> +        if (FTGMAC100_APTC_TXPOLL_CNT(s->aptcr)) {
> +            qemu_log_mask(LOG_UNIMP, "%s: no transmit polling\n", __func__);
> +        }
> +        break;
> +
> +    case FTGMAC100_MACCR: /* MAC Device control */
> +        s->maccr = value;
> +        if (value & FTGMAC100_MACCR_SW_RST) {
> +            ftgmac100_reset(DEVICE(s));
> +        }
> +
> +        if ((s->maccr & FTGMAC100_MACCR_RXDMA_EN) && !s->rx_enabled) {
> +            ftgmac100_enable_rx(s);
> +        }
> +
> +        if ((s->maccr & FTGMAC100_MACCR_RXDMA_EN) == 0) {
> +            s->rx_enabled = 0;
> +        }
> +        break;
> +
> +    case FTGMAC100_PHYCR:  /* PHY Device control */
> +        s->phycr = value;
> +        if (value & FTGMAC100_PHYCR_MIIWR) {
> +            do_phy_write(s, extract32(value, 21, 5), s->phydata & 0xffff);
> +            s->phycr &= ~FTGMAC100_PHYCR_MIIWR;
> +       } else {
> +            s->phydata = do_phy_read(s, extract32(value, 21, 5)) << 16;
> +            s->phycr &= ~FTGMAC100_PHYCR_MIIRD;
> +       }
> +        break;
> +    case FTGMAC100_PHYDATA:
> +        s->phydata = value;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
> +                      HWADDR_PRIx "\n", TYPE_FTGMAC100, __func__, addr);
> +        break;
> +    }
> +
> +    ftgmac100_update_irq(s);
> +}
> +
> +static bool packet_is_broadcast(const uint8_t *buf)
> +{
> +    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
> +                                              0xff, 0xff, 0xff};
> +    return memcmp(buf, sa_bcast, 6) == 0;
> +}
> +
> +static int ftgmac100_can_receive(NetClientState *nc)
> +{
> +    Ftgmac100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
> +
> +    return s->rx_enabled;
> +}
> +
> +static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
> +                               size_t len)
> +{
> +    Ftgmac100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
> +    Ftgmac100Desc bd;
> +    uint32_t flags = 0;
> +    uint32_t addr;
> +    uint32_t crc;
> +    uint32_t buf_addr;
> +    uint8_t *crc_ptr;
> +    unsigned int buf_len;
> +    size_t size = len;
> +    uint32_t first = FTGMAC100_RXDES0_FRS;
> +
> +    DEBUG("len %d\n", (int)size);
> +
> +    if (!s->rx_enabled) {
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__);
> +        return 0;
> +    }
> +
> +    /* FIXME: Pad short packets.  */
> +
> +    /* 4 bytes for the CRC.  */
> +    size += 4;
> +    crc = cpu_to_be32(crc32(~0, buf, size));
> +    crc_ptr = (uint8_t *) &crc;
> +
> +    /* Huge frames are truncted.  */
> +    if (size > FTGMAC100_MAX_FRAME_SIZE(s)) {
> +        size = FTGMAC100_MAX_FRAME_SIZE(s);
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %zd bytes\n",
> +                      __func__, size);
> +        flags |= FTGMAC100_RXDES0_FTL | FTGMAC100_RXDES0_RX_ERR;
> +    }
> +
> +    if (packet_is_broadcast(buf)) {
> +        flags |= FTGMAC100_RXDES0_BROADCAST;
> +    }
> +
> +    addr = s->rx_descriptor;
> +    while (size > 0) {
> +        ftgmac100_read_bd(&bd, addr);
> +        if (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY) {
> +            /* No descriptors available.  Bail out.  */
> +            /*
> +             * FIXME: This is wrong. We should probably either
> +             * save the remainder for when more RX buffers are
> +             * available, or flag an error.
> +             */
> +            qemu_log_mask(LOG_GUEST_ERROR, "%s: Lost end of frame\n",
> +                          __func__);
> +            s->isr |= FTGMAC100_INT_NO_RXBUF;
> +            break;
> +        }
> +        buf_len = (size <= s->rbsr) ? size : s->rbsr;
> +        bd.des0 |= buf_len & 0x3fff;
> +        size -= buf_len;
> +
> +        /* The last 4 bytes are the CRC.  */
> +        if (size < 4) {
> +            buf_len += size - 4;
> +        }
> +        buf_addr = bd.des3;
> +        dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
> +        buf += buf_len;
> +        if (size < 4) {
> +            dma_memory_write(&address_space_memory, buf_addr + buf_len,
> +                             crc_ptr, 4 - size);
> +            crc_ptr += 4 - size;
> +        }
> +
> +        bd.des0 |= first | FTGMAC100_RXDES0_RXPKT_RDY;
> +        first = 0;
> +        if (size == 0) {
> +            /* Last buffer in frame.  */
> +            bd.des0 |= flags | FTGMAC100_RXDES0_LRS;
> +            DEBUG("rx frame flags %04x\n", bd.des0);
> +            s->isr |= FTGMAC100_INT_RPKT_BUF;
> +        } else {
> +            s->isr |= FTGMAC100_INT_RPKT_FIFO;
> +        }
> +        ftgmac100_write_bd(&bd, addr);
> +        if (bd.des0 & FTGMAC100_RXDES0_EDORR) {
> +            addr = s->rx_ring;
> +        } else {
> +            addr += sizeof(Ftgmac100Desc);
> +        }
> +    }
> +    s->rx_descriptor = addr;
> +
> +    ftgmac100_enable_rx(s);
> +    ftgmac100_update_irq(s);
> +    return len;
> +}
> +
> +static const MemoryRegionOps ftgmac100_ops = {
> +    .read = ftgmac100_read,
> +    .write = ftgmac100_write,
> +    .valid.min_access_size = 4,
> +    .valid.max_access_size = 4,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static void ftgmac100_cleanup(NetClientState *nc)
> +{
> +    Ftgmac100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
> +
> +    s->nic = NULL;
> +}
> +
> +static NetClientInfo net_ftgmac100_info = {
> +    .type = NET_CLIENT_DRIVER_NIC,
> +    .size = sizeof(NICState),
> +    .can_receive = ftgmac100_can_receive,
> +    .receive = ftgmac100_receive,
> +    .cleanup = ftgmac100_cleanup,
> +    .link_status_changed = ftgmac100_set_link,
> +};
> +
> +static void ftgmac100_realize(DeviceState *dev, Error **errp)
> +{
> +    Ftgmac100State *s = FTGMAC100(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +
> +    memory_region_init_io(&s->iomem, OBJECT(dev), &ftgmac100_ops, s,
> +                          TYPE_FTGMAC100, 0x2000);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +    sysbus_init_irq(sbd, &s->irq);
> +    qemu_macaddr_default_if_unset(&s->conf.macaddr);
> +
> +    s->conf.peers.ncs[0] = nd_table[0].netdev;
> +
> +    s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf,
> +                          object_get_typename(OBJECT(dev)), DEVICE(dev)->id,
> +                          s);
> +    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
> +}
> +
> +static const VMStateDescription vmstate_ftgmac100 = {
> +    .name = TYPE_FTGMAC100,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32(irq_state, Ftgmac100State),
> +        VMSTATE_UINT32(isr, Ftgmac100State),
> +        VMSTATE_UINT32(ier, Ftgmac100State),
> +        VMSTATE_UINT32(rx_enabled, Ftgmac100State),
> +        VMSTATE_UINT32(rx_ring, Ftgmac100State),
> +        VMSTATE_UINT32(rbsr, Ftgmac100State),
> +        VMSTATE_UINT32(tx_ring, Ftgmac100State),
> +        VMSTATE_UINT32(rx_descriptor, Ftgmac100State),
> +        VMSTATE_UINT32(tx_descriptor, Ftgmac100State),
> +        VMSTATE_UINT32(maccr, Ftgmac100State),
> +        VMSTATE_UINT32(phycr, Ftgmac100State),
> +        VMSTATE_UINT32(phydata, Ftgmac100State),
> +        VMSTATE_UINT32(aptcr, Ftgmac100State),
> +
> +        VMSTATE_UINT32(phy_status, Ftgmac100State),
> +        VMSTATE_UINT32(phy_control, Ftgmac100State),
> +        VMSTATE_UINT32(phy_advertise, Ftgmac100State),
> +        VMSTATE_UINT32(phy_int, Ftgmac100State),
> +        VMSTATE_UINT32(phy_int_mask, Ftgmac100State),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static Property ftgmac100_properties[] = {
> +    DEFINE_NIC_PROPERTIES(Ftgmac100State, conf),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void ftgmac100_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->vmsd = &vmstate_ftgmac100;
> +    dc->reset = ftgmac100_reset;
> +    dc->props = ftgmac100_properties;
> +    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
> +    dc->realize = ftgmac100_realize;
> +    dc->desc = "Faraday FTGMAC100 Gigabit Ethernet emulation";
> +}
> +
> +static const TypeInfo ftgmac100_info = {
> +    .name = TYPE_FTGMAC100,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(Ftgmac100State),
> +    .class_init = ftgmac100_class_init,
> +};
> +
> +static void ftgmac100_register_types(void)
> +{
> +    type_register_static(&ftgmac100_info);
> +}
> +
> +type_init(ftgmac100_register_types)
> diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h
> new file mode 100644
> index 000000000000..cc5cb4207a5c
> --- /dev/null
> +++ b/include/hw/net/ftgmac100.h
> @@ -0,0 +1,62 @@
> +/*
> + * Faraday FTGMAC100 Gigabit Ethernet
> + *
> + * Copyright (C) 2016 IBM Corp.
> + *
> + * 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 FTGMAC100_H
> +#define FTGMAC100_H
> +
> +#define TYPE_FTGMAC100 "ftgmac100"
> +#define FTGMAC100(obj) OBJECT_CHECK(Ftgmac100State, (obj), TYPE_FTGMAC100)
> +
> +#include "hw/sysbus.h"
> +#include "net/net.h"
> +
> +typedef struct Ftgmac100State {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +
> +    /*< public >*/
> +    NICState *nic;
> +    NICConf conf;
> +    qemu_irq irq;
> +    MemoryRegion iomem;
> +
> +    uint32_t irq_state;
> +    uint32_t isr;
> +    uint32_t ier;
> +    uint32_t rx_enabled;
> +    uint32_t rx_ring;
> +    uint32_t rbsr;
> +    uint32_t rx_descriptor;
> +    uint32_t tx_ring;
> +    uint32_t tx_descriptor;
> +    uint32_t maccr;
> +    uint32_t phycr;
> +    uint32_t phydata;
> +    uint32_t aptcr;
> +
> +    uint32_t phy_status;
> +    uint32_t phy_control;
> +    uint32_t phy_advertise;
> +    uint32_t phy_int;
> +    uint32_t phy_int_mask;
> +
> +} Ftgmac100State;
> +
> +#endif

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 35/38] net/ftgmac100: add a 'aspeed' property
  2016-11-18 14:22 ` [PATCH qemu 35/38] net/ftgmac100: add a 'aspeed' property Cédric Le Goater
@ 2016-11-28  2:22   ` Andrew Jeffery
  2016-11-28 11:20     ` Cédric Le Goater
  0 siblings, 1 reply; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:22 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 5079 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> Aspeed SOCs have different definitions for the end of ring bits. Add
> a
> property to specify which set of bits should be used by the nic
> device
> model.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  hw/net/ftgmac100.c         | 24 ++++++++++++++++++++----
>  include/hw/net/ftgmac100.h |  2 ++
>  2 files changed, 22 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
> index 22573ff956fd..0a8ab6b9e4d8 100644
> --- a/hw/net/ftgmac100.c
> +++ b/hw/net/ftgmac100.c
> @@ -136,9 +136,11 @@ struct ftgmac100_txdes {
>  
>  #define FTGMAC100_TXDES0_TXBUF_SIZE(x)   ((x) & 0x3fff)
>  #define FTGMAC100_TXDES0_EDOTR           (1 << 15)
> +
>  #define FTGMAC100_TXDES0_CRC_ERR         (1 << 19)
>  #define FTGMAC100_TXDES0_LTS             (1 << 28)
>  #define FTGMAC100_TXDES0_FTS             (1 << 29)
> +#define FTGMAC100_TXDES0_EDOTR_ASPEED    (1 << 30)
>  #define FTGMAC100_TXDES0_TXDMA_OWN       (1 << 31)
>  
>  #define FTGMAC100_TXDES1_VLANTAG_CI(x)   ((x) & 0xffff)
> @@ -174,6 +176,7 @@ struct ftgmac100_rxdes {
>  #define FTGMAC100_RXDES0_PAUSE_FRAME     (1 << 25)
>  #define FTGMAC100_RXDES0_LRS             (1 << 28)
>  #define FTGMAC100_RXDES0_FRS             (1 << 29)
> +#define FTGMAC100_RXDES0_EDORR_ASPEED    (1 << 30)
>  #define FTGMAC100_RXDES0_RXPKT_RDY       (1 << 31)
>  
>  #define FTGMAC100_RXDES1_VLANTAG_CI      0xffff
> @@ -208,6 +211,18 @@ typedef struct {
>      uint32_t        des3;        /* TXBUF_BADR */
>  } Ftgmac100Desc  __attribute__ ((aligned(16)));
>  
> +static inline uint32_t ftgmac100_rxdes0_edorr(Ftgmac100State *s)
> +{
> +    return s->aspeed ?
> +        FTGMAC100_RXDES0_EDORR_ASPEED : FTGMAC100_RXDES0_EDORR;
> +}
> +
> +static inline uint32_t ftgmac100_txdes0_edotr(Ftgmac100State *s)
> +{
> +    return s->aspeed ?
> +        FTGMAC100_TXDES0_EDOTR_ASPEED : FTGMAC100_TXDES0_EDOTR;
> +}
> +
>  /* max frame size is :
>   *
>   *   9216 for Jumbo frames (+ 4 for VLAN)
> @@ -405,7 +420,7 @@ static uint32_t
> ftgmac100_find_txdes(Ftgmac100State *s, uint32_t addr)
>  
>      while (1) {
>          ftgmac100_read_bd(&bd, addr);
> -        if (bd.des0 & (FTGMAC100_TXDES0_FTS |
> FTGMAC100_TXDES0_EDOTR)) {
> +        if (bd.des0 & (FTGMAC100_TXDES0_FTS |
> ftgmac100_txdes0_edotr(s))) {
>              break;
>          }
>          addr += sizeof(Ftgmac100Desc);
> @@ -459,7 +474,7 @@ static void ftgmac100_do_tx(Ftgmac100State *s)
>          /* Write back the modified descriptor.  */
>          ftgmac100_write_bd(&bd, addr);
>          /* Advance to the next descriptor.  */
> -        if (bd.des0 & FTGMAC100_TXDES0_EDOTR) {
> +        if (bd.des0 & ftgmac100_txdes0_edotr(s)) {

Should we just derive the bit and stash it in a state member at realise
time? Would save a branch for every call. Interested in your thoughts,
not necessarily something that must happen.

>              addr = s->tx_ring;
>          } else {
>              addr += sizeof(Ftgmac100Desc);
> @@ -480,7 +495,7 @@ static void ftgmac100_enable_rx(Ftgmac100State
> *s)
>      while (1) {
>          ftgmac100_read_bd(&bd, s->rx_descriptor);
>          full = (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY);
> -        if (!full || bd.des0 & FTGMAC100_TXDES0_EDOTR) {
> +        if (!full || bd.des0 & ftgmac100_txdes0_edotr(s)) {
>              break;
>          }
>          s->rx_descriptor += sizeof(Ftgmac100Desc);
> @@ -784,7 +799,7 @@ static ssize_t ftgmac100_receive(NetClientState
> *nc, const uint8_t *buf,
>              s->isr |= FTGMAC100_INT_RPKT_FIFO;
>          }
>          ftgmac100_write_bd(&bd, addr);
> -        if (bd.des0 & FTGMAC100_RXDES0_EDORR) {
> +        if (bd.des0 & ftgmac100_rxdes0_edorr(s)) {
>              addr = s->rx_ring;
>          } else {
>              addr += sizeof(Ftgmac100Desc);
> @@ -869,6 +884,7 @@ static const VMStateDescription vmstate_ftgmac100
> = {
>  };
>  
>  static Property ftgmac100_properties[] = {
> +    DEFINE_PROP_BOOL("aspeed", Ftgmac100State, aspeed, false),
>      DEFINE_NIC_PROPERTIES(Ftgmac100State, conf),
>      DEFINE_PROP_END_OF_LIST(),
>  };
> diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h
> index cc5cb4207a5c..ee8975000260 100644
> --- a/include/hw/net/ftgmac100.h
> +++ b/include/hw/net/ftgmac100.h
> @@ -57,6 +57,8 @@ typedef struct Ftgmac100State {
>      uint32_t phy_int;
>      uint32_t phy_int_mask;
>  
> +    bool aspeed;
> +
>  } Ftgmac100State;
>  
>  #endif

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 36/38] ast2400: add a FTGMAC100 nic
  2016-11-18 14:22 ` [PATCH qemu 36/38] ast2400: add a FTGMAC100 nic Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-28  2:25   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:25 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 3643 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> Only the first nic, but the second shouldn't be too complex to add if
> needed.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  hw/arm/aspeed_soc.c         | 21 +++++++++++++++++++++
>  include/hw/arm/aspeed_soc.h |  2 ++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 06c1f03555b1..f3c41509a4ea 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -19,6 +19,7 @@
>  #include "hw/char/serial.h"
>  #include "qemu/log.h"
>  #include "hw/i2c/aspeed_i2c.h"
> +#include "net/net.h"
>  
>  #define ASPEED_SOC_UART_5_BASE      0x00184000
>  #define ASPEED_SOC_IOMEM_SIZE       0x00200000
> @@ -33,6 +34,8 @@
>  #define ASPEED_SOC_TIMER_BASE       0x1E782000
>  #define ASPEED_SOC_WDT_BASE         0x1E785000
>  #define ASPEED_SOC_I2C_BASE         0x1E78A000
> +#define ASPEED_SOC_ETH1_BASE        0x1E660000
> +#define ASPEED_SOC_ETH2_BASE        0x1E680000
>  
>  static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
>  static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
> @@ -175,6 +178,10 @@ static void aspeed_soc_init(Object *obj)
>      qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
>      object_property_add_const_link(OBJECT(&s->wdt), "scu", OBJECT(&s->scu),
>                                     NULL);
> +
> +    object_initialize(&s->ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100);
> +    object_property_add_child(obj, "ftgmac100", OBJECT(&s->ftgmac100), NULL);
> +    qdev_set_parent_bus(DEVICE(&s->ftgmac100), sysbus_get_default());
>  }
>  
>  static int aspeed_fmc_get_cs(AspeedSoCState *s, Error **errp)
> @@ -344,6 +351,20 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>      sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, ASPEED_SOC_WDT_BASE);
> +
> +    /* Net */
> +    qdev_set_nic_properties(DEVICE(&s->ftgmac100), &nd_table[0]);
> +    object_property_set_bool(OBJECT(&s->ftgmac100), true, "aspeed", &err);
> +    object_property_set_bool(OBJECT(&s->ftgmac100), true, "realized",
> +                             &local_err);
> +    error_propagate(&err, local_err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ftgmac100), 0, ASPEED_SOC_ETH1_BASE);
> +    sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100), 0,
> +                       qdev_get_gpio_in(DEVICE(&s->vic), 2));
>  }
>  
>  static void aspeed_soc_class_init(ObjectClass *oc, void *data)
> diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> index dbec0c159885..1fd0dc690be1 100644
> --- a/include/hw/arm/aspeed_soc.h
> +++ b/include/hw/arm/aspeed_soc.h
> @@ -20,6 +20,7 @@
>  #include "hw/i2c/aspeed_i2c.h"
>  #include "hw/ssi/aspeed_smc.h"
>  #include "hw/watchdog/wdt_aspeed.h"
> +#include "hw/net/ftgmac100.h"
>  
>  #define ASPEED_SPIS_NUM  2
>  
> @@ -39,6 +40,7 @@ typedef struct AspeedSoCState {
>      AspeedSMCState spi[ASPEED_SPIS_NUM];
>      AspeedSDMCState sdmc;
>      AspeedWDTState wdt;
> +    Ftgmac100State ftgmac100;
>  } AspeedSoCState;
>  
>  #define TYPE_ASPEED_SOC "aspeed-soc"

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 37/38] slirp: add a fake NCSI backend
  2016-11-18 14:22 ` [PATCH qemu 37/38] slirp: add a fake NCSI backend Cédric Le Goater
  2016-11-21  7:26   ` Joel Stanley
@ 2016-11-28  2:26   ` Andrew Jeffery
  1 sibling, 0 replies; 142+ messages in thread
From: Andrew Jeffery @ 2016-11-28  2:26 UTC (permalink / raw)
  To: Cédric Le Goater, openbmc

[-- Attachment #1: Type: text/plain, Size: 37049 bytes --]

On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
> This only reverses the NCSI packets to make the Linux driver happy.
> 
> The NCSI header file <ncsi-pkt.h> comes from Linux.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Tested-by: Andrew Jeffery <andrew@aj.id.au>

> ---
>  include/net/eth.h   |   1 +
>  slirp/Makefile.objs |   2 +-
>  slirp/ncsi-pkt.h    | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  slirp/ncsi.c        |  95 +++++++++++++
>  slirp/slirp.c       |   4 +
>  slirp/slirp.h       |   3 +
>  6 files changed, 498 insertions(+), 1 deletion(-)
>  create mode 100644 slirp/ncsi-pkt.h
>  create mode 100644 slirp/ncsi.c
> 
> diff --git a/include/net/eth.h b/include/net/eth.h
> index 2013175857ba..6237004559bc 100644
> --- a/include/net/eth.h
> +++ b/include/net/eth.h
> @@ -209,6 +209,7 @@ struct tcp_hdr {
>  #define ETH_P_IPV6                (0x86dd)
>  #define ETH_P_VLAN                (0x8100)
>  #define ETH_P_DVLAN               (0x88a8)
> +#define ETH_P_NCSI                (0x88f8)      /* NCSI protocol             */
>  #define ETH_P_UNKNOWN             (0xffff)
>  #define VLAN_VID_MASK             0x0fff
>  #define IP_HEADER_VERSION_4       (4)
> diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
> index 1baa1f1c7cfb..28049b03cddc 100644
> --- a/slirp/Makefile.objs
> +++ b/slirp/Makefile.objs
> @@ -2,4 +2,4 @@ common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
>                 ip_input.o ip_output.o dnssearch.o dhcpv6.o
>  common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
>  common-obj-y += tcp_subr.o tcp_timer.o udp.o udp6.o bootp.o tftp.o arp_table.o \
> -                ndp_table.o
> +                ndp_table.o ncsi.o
> diff --git a/slirp/ncsi-pkt.h b/slirp/ncsi-pkt.h
> new file mode 100644
> index 000000000000..20c787103ec2
> --- /dev/null
> +++ b/slirp/ncsi-pkt.h
> @@ -0,0 +1,394 @@
> +#ifndef NCSI_PKT_H
> +#define NCSI_PKT_H
> +
> +#define __be32 uint32_t
> +#define __be16 uint16_t
> +
> +struct ncsi_pkt_hdr {
> +        unsigned char   mc_id;          /* Management controller ID */
> +        unsigned char   revision;       /* NCSI version - 0x01      */
> +        unsigned char   reserved;       /* Reserved                 */
> +        unsigned char   id;             /* Packet sequence number   */
> +        unsigned char   type;           /* Packet type              */
> +        unsigned char   channel;        /* Network controller ID    */
> +        __be16          length;         /* Payload length           */
> +        __be32          reserved1[2];   /* Reserved                 */
> +};
> +
> +struct ncsi_cmd_pkt_hdr {
> +        struct ncsi_pkt_hdr     common;         /* Common NCSI packet header */
> +};
> +
> +struct ncsi_rsp_pkt_hdr {
> +        struct ncsi_pkt_hdr     common;         /* Common NCSI packet header */
> +        __be16                  code;           /* Response code             */
> +        __be16                  reason;         /* Response reason           */
> +};
> +
> +struct ncsi_aen_pkt_hdr {
> +        struct ncsi_pkt_hdr     common;         /* Common NCSI packet header */
> +        unsigned char           reserved2[3];   /* Reserved                  */
> +        unsigned char           type;           /* AEN packet type           */
> +};
> +
> +/* NCSI common command and response packets */
> +struct ncsi_cmd_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
> +        __be32                  checksum;       /* Checksum       */
> +        unsigned char           pad[26];
> +};
> +
> +struct ncsi_rsp_pkt {
> +        struct ncsi_rsp_pkt_hdr rsp;            /* Response header */
> +        __be32                  checksum;       /* Checksum        */
> +        unsigned char           pad[22];
> +};
> +
> +/* Select Package */
> +struct ncsi_cmd_sp_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
> +        unsigned char           reserved[3];    /* Reserved       */
> +        unsigned char           hw_arbitration; /* HW arbitration */
> +        __be32                  checksum;       /* Checksum       */
> +        unsigned char           pad[22];
> +};
> +
> +/* Disable Channel */
> +struct ncsi_cmd_dc_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header  */
> +        unsigned char           reserved[3];    /* Reserved        */
> +        unsigned char           ald;            /* Allow link down */
> +        __be32                  checksum;       /* Checksum        */
> +        unsigned char           pad[22];
> +};
> +
> +/* Reset Channel */
> +struct ncsi_cmd_rc_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
> +        __be32                  reserved;       /* Reserved       */
> +        __be32                  checksum;       /* Checksum       */
> +        unsigned char           pad[22];
> +};
> +
> +/* AEN Enable */
> +struct ncsi_cmd_ae_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header   */
> +        unsigned char           reserved[3];    /* Reserved         */
> +        unsigned char           mc_id;          /* MC ID            */
> +        __be32                  mode;           /* AEN working mode */
> +        __be32                  checksum;       /* Checksum         */
> +        unsigned char           pad[18];
> +};
> +
> +/* Set Link */
> +struct ncsi_cmd_sl_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header    */
> +        __be32                  mode;           /* Link working mode */
> +        __be32                  oem_mode;       /* OEM link mode     */
> +        __be32                  checksum;       /* Checksum          */
> +        unsigned char           pad[18];
> +};
> +
> +/* Get Link Status */
> +struct ncsi_rsp_gls_pkt {
> +        struct ncsi_rsp_pkt_hdr rsp;            /* Response header   */
> +        __be32                  status;         /* Link status       */
> +        __be32                  other;          /* Other indications */
> +        __be32                  oem_status;     /* OEM link status   */
> +        __be32                  checksum;       /* Checksum          */
> +        unsigned char           pad[10];
> +};
> +
> +/* Set VLAN Filter */
> +struct ncsi_cmd_svf_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header    */
> +        __be16                  reserved;       /* Reserved          */
> +        __be16                  vlan;           /* VLAN ID           */
> +        __be16                  reserved1;      /* Reserved          */
> +        unsigned char           index;          /* VLAN table index  */
> +        unsigned char           enable;         /* Enable or disable */
> +        __be32                  checksum;       /* Checksum          */
> +        unsigned char           pad[14];
> +};
> +
> +/* Enable VLAN */
> +struct ncsi_cmd_ev_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header   */
> +        unsigned char           reserved[3];    /* Reserved         */
> +        unsigned char           mode;           /* VLAN filter mode */
> +        __be32                  checksum;       /* Checksum         */
> +        unsigned char           pad[22];
> +};
> +
> +/* Set MAC Address */
> +struct ncsi_cmd_sma_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header          */
> +        unsigned char           mac[6];         /* MAC address             */
> +        unsigned char           index;          /* MAC table index         */
> +        unsigned char           at_e;           /* Addr type and operation */
> +        __be32                  checksum;       /* Checksum                */
> +        unsigned char           pad[18];
> +};
> +
> +/* Enable Broadcast Filter */
> +struct ncsi_cmd_ebf_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
> +        __be32                  mode;           /* Filter mode    */
> +        __be32                  checksum;       /* Checksum       */
> +        unsigned char           pad[22];
> +};
> +
> +/* Enable Global Multicast Filter */
> +struct ncsi_cmd_egmf_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header */
> +        __be32                  mode;           /* Global MC mode */
> +        __be32                  checksum;       /* Checksum       */
> +        unsigned char           pad[22];
> +};
> +
> +/* Set NCSI Flow Control */
> +struct ncsi_cmd_snfc_pkt {
> +        struct ncsi_cmd_pkt_hdr cmd;            /* Command header    */
> +        unsigned char           reserved[3];    /* Reserved          */
> +        unsigned char           mode;           /* Flow control mode */
> +        __be32                  checksum;       /* Checksum          */
> +        unsigned char           pad[22];
> +};
> +
> +/* Get Version ID */
> +struct ncsi_rsp_gvi_pkt {
> +        struct ncsi_rsp_pkt_hdr rsp;            /* Response header   */
> +        __be32                  ncsi_version;   /* NCSI version      */
> +        unsigned char           reserved[3];    /* Reserved          */
> +        unsigned char           alpha2;         /* NCSI version      */
> +        unsigned char           fw_name[12];    /* f/w name string   */
> +        __be32                  fw_version;     /* f/w version       */
> +        __be16                  pci_ids[4];     /* PCI IDs           */
> +        __be32                  mf_id;          /* Manufacture ID    */
> +        __be32                  checksum;
> +};
> +
> +/* Get Capabilities */
> +struct ncsi_rsp_gc_pkt {
> +        struct ncsi_rsp_pkt_hdr rsp;            /* Response header   */
> +        __be32                  cap;            /* Capabilities      */
> +        __be32                  bc_cap;         /* Broadcast cap     */
> +        __be32                  mc_cap;         /* Multicast cap     */
> +        __be32                  buf_cap;        /* Buffering cap     */
> +        __be32                  aen_cap;        /* AEN cap           */
> +        unsigned char           vlan_cnt;       /* VLAN filter count */
> +        unsigned char           mixed_cnt;      /* Mix filter count  */
> +        unsigned char           mc_cnt;         /* MC filter count   */
> +        unsigned char           uc_cnt;         /* UC filter count   */
> +        unsigned char           reserved[2];    /* Reserved          */
> +        unsigned char           vlan_mode;      /* VLAN mode         */
> +        unsigned char           channel_cnt;    /* Channel count     */
> +        __be32                  checksum;       /* Checksum          */
> +};
> +
> +/* Get Parameters */
> +struct ncsi_rsp_gp_pkt {
> +        struct ncsi_rsp_pkt_hdr rsp;            /* Response header       */
> +        unsigned char           mac_cnt;        /* Number of MAC addr    */
> +        unsigned char           reserved[2];    /* Reserved              */
> +        unsigned char           mac_enable;     /* MAC addr enable flags */
> +        unsigned char           vlan_cnt;       /* VLAN tag count        */
> +        unsigned char           reserved1;      /* Reserved              */
> +        __be16                  vlan_enable;    /* VLAN tag enable flags */
> +        __be32                  link_mode;      /* Link setting          */
> +        __be32                  bc_mode;        /* BC filter mode        */
> +        __be32                  valid_modes;    /* Valid mode parameters */
> +        unsigned char           vlan_mode;      /* VLAN mode             */
> +        unsigned char           fc_mode;        /* Flow control mode     */
> +        unsigned char           reserved2[2];   /* Reserved              */
> +        __be32                  aen_mode;       /* AEN mode              */
> +        unsigned char           mac[6];         /* Supported MAC addr    */
> +        __be16                  vlan;           /* Supported VLAN tags   */
> +        __be32                  checksum;       /* Checksum              */
> +};
> +
> +/* Get Controller Packet Statistics */
> +struct ncsi_rsp_gcps_pkt {
> +        struct ncsi_rsp_pkt_hdr rsp;            /* Response header            */
> +        __be32                  cnt_hi;         /* Counter cleared            */
> +        __be32                  cnt_lo;         /* Counter cleared            */
> +        __be32                  rx_bytes;       /* Rx bytes                   */
> +        __be32                  tx_bytes;       /* Tx bytes                   */
> +        __be32                  rx_uc_pkts;     /* Rx UC packets              */
> +        __be32                  rx_mc_pkts;     /* Rx MC packets              */
> +        __be32                  rx_bc_pkts;     /* Rx BC packets              */
> +        __be32                  tx_uc_pkts;     /* Tx UC packets              */
> +        __be32                  tx_mc_pkts;     /* Tx MC packets              */
> +        __be32                  tx_bc_pkts;     /* Tx BC packets              */
> +        __be32                  fcs_err;        /* FCS errors                 */
> +        __be32                  align_err;      /* Alignment errors           */
> +        __be32                  false_carrier;  /* False carrier detection    */
> +        __be32                  runt_pkts;      /* Rx runt packets            */
> +        __be32                  jabber_pkts;    /* Rx jabber packets          */
> +        __be32                  rx_pause_xon;   /* Rx pause XON frames        */
> +        __be32                  rx_pause_xoff;  /* Rx XOFF frames             */
> +        __be32                  tx_pause_xon;   /* Tx XON frames              */
> +        __be32                  tx_pause_xoff;  /* Tx XOFF frames             */
> +        __be32                  tx_s_collision; /* Single collision frames    */
> +        __be32                  tx_m_collision; /* Multiple collision frames  */
> +        __be32                  l_collision;    /* Late collision frames      */
> +        __be32                  e_collision;    /* Excessive collision frames */
> +        __be32                  rx_ctl_frames;  /* Rx control frames          */
> +        __be32                  rx_64_frames;   /* Rx 64-bytes frames         */
> +        __be32                  rx_127_frames;  /* Rx 65-127 bytes frames     */
> +        __be32                  rx_255_frames;  /* Rx 128-255 bytes frames    */
> +        __be32                  rx_511_frames;  /* Rx 256-511 bytes frames    */
> +        __be32                  rx_1023_frames; /* Rx 512-1023 bytes frames   */
> +        __be32                  rx_1522_frames; /* Rx 1024-1522 bytes frames  */
> +        __be32                  rx_9022_frames; /* Rx 1523-9022 bytes frames  */
> +        __be32                  tx_64_frames;   /* Tx 64-bytes frames         */
> +        __be32                  tx_127_frames;  /* Tx 65-127 bytes frames     */
> +        __be32                  tx_255_frames;  /* Tx 128-255 bytes frames    */
> +        __be32                  tx_511_frames;  /* Tx 256-511 bytes frames    */
> +        __be32                  tx_1023_frames; /* Tx 512-1023 bytes frames   */
> +        __be32                  tx_1522_frames; /* Tx 1024-1522 bytes frames  */
> +        __be32                  tx_9022_frames; /* Tx 1523-9022 bytes frames  */
> +        __be32                  rx_valid_bytes; /* Rx valid bytes             */
> +        __be32                  rx_runt_pkts;   /* Rx error runt packets      */
> +        __be32                  rx_jabber_pkts; /* Rx error jabber packets    */
> +        __be32                  checksum;       /* Checksum                   */
> +};
> +
> +/* Get NCSI Statistics */
> +struct ncsi_rsp_gns_pkt {
> +        struct ncsi_rsp_pkt_hdr rsp;            /* Response header         */
> +        __be32                  rx_cmds;        /* Rx NCSI commands        */
> +        __be32                  dropped_cmds;   /* Dropped commands        */
> +        __be32                  cmd_type_errs;  /* Command type errors     */
> +        __be32                  cmd_csum_errs;  /* Command checksum errors */
> +        __be32                  rx_pkts;        /* Rx NCSI packets         */
> +        __be32                  tx_pkts;        /* Tx NCSI packets         */
> +        __be32                  tx_aen_pkts;    /* Tx AEN packets          */
> +        __be32                  checksum;       /* Checksum                */
> +};
> +
> +/* Get NCSI Pass-through Statistics */
> +struct ncsi_rsp_gnpts_pkt {
> +        struct ncsi_rsp_pkt_hdr rsp;            /* Response header     */
> +        __be32                  tx_pkts;        /* Tx packets          */
> +        __be32                  tx_dropped;     /* Tx dropped packets  */
> +        __be32                  tx_channel_err; /* Tx channel errors   */
> +        __be32                  tx_us_err;      /* Tx undersize errors */
> +        __be32                  rx_pkts;        /* Rx packets          */
> +        __be32                  rx_dropped;     /* Rx dropped packets  */
> +        __be32                  rx_channel_err; /* Rx channel errors   */
> +        __be32                  rx_us_err;      /* Rx undersize errors */
> +        __be32                  rx_os_err;      /* Rx oversize errors  */
> +        __be32                  checksum;       /* Checksum            */
> +};
> +
> +/* AEN: Link State Change */
> +struct ncsi_aen_lsc_pkt {
> +        struct ncsi_aen_pkt_hdr aen;            /* AEN header      */
> +        __be32                  status;         /* Link status     */
> +        __be32                  oem_status;     /* OEM link status */
> +        __be32                  checksum;       /* Checksum        */
> +        unsigned char           pad[14];
> +};
> +
> +/* AEN: Configuration Required */
> +struct ncsi_aen_cr_pkt {
> +        struct ncsi_aen_pkt_hdr aen;            /* AEN header */
> +        __be32                  checksum;       /* Checksum   */
> +        unsigned char           pad[22];
> +};
> +
> +/* AEN: Host Network Controller Driver Status Change */
> +struct ncsi_aen_hncdsc_pkt {
> +        struct ncsi_aen_pkt_hdr aen;            /* AEN header */
> +        __be32                  status;         /* Status     */
> +        __be32                  checksum;       /* Checksum   */
> +        unsigned char           pad[18];
> +};
> +
> +/* NCSI packet revision */
> +#define NCSI_PKT_REVISION       0x01
> +
> +/* NCSI packet commands */
> +#define NCSI_PKT_CMD_CIS        0x00    /* Clear Initial State              */
> +#define NCSI_PKT_CMD_SP         0x01    /* Select Package                   */
> +#define NCSI_PKT_CMD_DP         0x02    /* Deselect Package                 */
> +#define NCSI_PKT_CMD_EC         0x03    /* Enable Channel                   */
> +#define NCSI_PKT_CMD_DC         0x04    /* Disable Channel                  */
> +#define NCSI_PKT_CMD_RC         0x05    /* Reset Channel                    */
> +#define NCSI_PKT_CMD_ECNT       0x06    /* Enable Channel Network Tx        */
> +#define NCSI_PKT_CMD_DCNT       0x07    /* Disable Channel Network Tx       */
> +#define NCSI_PKT_CMD_AE         0x08    /* AEN Enable                       */
> +#define NCSI_PKT_CMD_SL         0x09    /* Set Link                         */
> +#define NCSI_PKT_CMD_GLS        0x0a    /* Get Link                         */
> +#define NCSI_PKT_CMD_SVF        0x0b    /* Set VLAN Filter                  */
> +#define NCSI_PKT_CMD_EV         0x0c    /* Enable VLAN                      */
> +#define NCSI_PKT_CMD_DV         0x0d    /* Disable VLAN                     */
> +#define NCSI_PKT_CMD_SMA        0x0e    /* Set MAC address                  */
> +#define NCSI_PKT_CMD_EBF        0x10    /* Enable Broadcast Filter          */
> +#define NCSI_PKT_CMD_DBF        0x11    /* Disable Broadcast Filter         */
> +#define NCSI_PKT_CMD_EGMF       0x12    /* Enable Global Multicast Filter   */
> +#define NCSI_PKT_CMD_DGMF       0x13    /* Disable Global Multicast Filter  */
> +#define NCSI_PKT_CMD_SNFC       0x14    /* Set NCSI Flow Control            */
> +#define NCSI_PKT_CMD_GVI        0x15    /* Get Version ID                   */
> +#define NCSI_PKT_CMD_GC         0x16    /* Get Capabilities                 */
> +#define NCSI_PKT_CMD_GP         0x17    /* Get Parameters                   */
> +#define NCSI_PKT_CMD_GCPS       0x18    /* Get Controller Packet Statistics */
> +#define NCSI_PKT_CMD_GNS        0x19    /* Get NCSI Statistics              */
> +#define NCSI_PKT_CMD_GNPTS      0x1a    /* Get NCSI Pass-throu Statistics   */
> +#define NCSI_PKT_CMD_OEM        0x50    /* OEM                              */
> +
> +/* NCSI packet responses */
> +#define NCSI_PKT_RSP_CIS        (NCSI_PKT_CMD_CIS + 0x80)
> +#define NCSI_PKT_RSP_SP         (NCSI_PKT_CMD_SP + 0x80)
> +#define NCSI_PKT_RSP_DP         (NCSI_PKT_CMD_DP + 0x80)
> +#define NCSI_PKT_RSP_EC         (NCSI_PKT_CMD_EC + 0x80)
> +#define NCSI_PKT_RSP_DC         (NCSI_PKT_CMD_DC + 0x80)
> +#define NCSI_PKT_RSP_RC         (NCSI_PKT_CMD_RC + 0x80)
> +#define NCSI_PKT_RSP_ECNT       (NCSI_PKT_CMD_ECNT + 0x80)
> +#define NCSI_PKT_RSP_DCNT       (NCSI_PKT_CMD_DCNT + 0x80)
> +#define NCSI_PKT_RSP_AE         (NCSI_PKT_CMD_AE + 0x80)
> +#define NCSI_PKT_RSP_SL         (NCSI_PKT_CMD_SL + 0x80)
> +#define NCSI_PKT_RSP_GLS        (NCSI_PKT_CMD_GLS + 0x80)
> +#define NCSI_PKT_RSP_SVF        (NCSI_PKT_CMD_SVF + 0x80)
> +#define NCSI_PKT_RSP_EV         (NCSI_PKT_CMD_EV + 0x80)
> +#define NCSI_PKT_RSP_DV         (NCSI_PKT_CMD_DV + 0x80)
> +#define NCSI_PKT_RSP_SMA        (NCSI_PKT_CMD_SMA + 0x80)
> +#define NCSI_PKT_RSP_EBF        (NCSI_PKT_CMD_EBF + 0x80)
> +#define NCSI_PKT_RSP_DBF        (NCSI_PKT_CMD_DBF + 0x80)
> +#define NCSI_PKT_RSP_EGMF       (NCSI_PKT_CMD_EGMF + 0x80)
> +#define NCSI_PKT_RSP_DGMF       (NCSI_PKT_CMD_DGMF + 0x80)
> +#define NCSI_PKT_RSP_SNFC       (NCSI_PKT_CMD_SNFC + 0x80)
> +#define NCSI_PKT_RSP_GVI        (NCSI_PKT_CMD_GVI + 0x80)
> +#define NCSI_PKT_RSP_GC         (NCSI_PKT_CMD_GC + 0x80)
> +#define NCSI_PKT_RSP_GP         (NCSI_PKT_CMD_GP + 0x80)
> +#define NCSI_PKT_RSP_GCPS       (NCSI_PKT_CMD_GCPS + 0x80)
> +#define NCSI_PKT_RSP_GNS        (NCSI_PKT_CMD_GNS + 0x80)
> +#define NCSI_PKT_RSP_GNPTS      (NCSI_PKT_CMD_GNPTS + 0x80)
> +#define NCSI_PKT_RSP_OEM        (NCSI_PKT_CMD_OEM + 0x80)
> +
> +/* NCSI packet type: AEN */
> +#define NCSI_PKT_AEN            0xFF    /* AEN Packet               */
> +#define NCSI_PKT_AEN_LSC        0x00    /* Link status change       */
> +#define NCSI_PKT_AEN_CR         0x01    /* Configuration required   */
> +#define NCSI_PKT_AEN_HNCDSC     0x02    /* HNC driver status change */
> +
> +/* NCSI response code/reason */
> +#define NCSI_PKT_RSP_C_COMPLETED        0x0000  /* Command Completed        */
> +#define NCSI_PKT_RSP_C_FAILED           0x0001  /* Command Failed           */
> +#define NCSI_PKT_RSP_C_UNAVAILABLE      0x0002  /* Command Unavailable      */
> +#define NCSI_PKT_RSP_C_UNSUPPORTED      0x0003  /* Command Unsupported      */
> +#define NCSI_PKT_RSP_R_NO_ERROR         0x0000  /* No Error                 */
> +#define NCSI_PKT_RSP_R_INTERFACE        0x0001  /* Interface not ready      */
> +#define NCSI_PKT_RSP_R_PARAM            0x0002  /* Invalid Parameter        */
> +#define NCSI_PKT_RSP_R_CHANNEL          0x0003  /* Channel not Ready        */
> +#define NCSI_PKT_RSP_R_PACKAGE          0x0004  /* Package not Ready        */
> +#define NCSI_PKT_RSP_R_LENGTH           0x0005  /* Invalid payload length   */
> +#define NCSI_PKT_RSP_R_UNKNOWN          0x7fff  /* Command type unsupported */
> +
> +/* NCSI AEN packet type */
> +#define NCSI_PKT_AEN_LSC                0x00    /* Link status change        */
> +#define NCSI_PKT_AEN_CR                 0x01    /* Configuration required    */
> +#define NCSI_PKT_AEN_HNCDSC             0x02    /* Host driver status change */
> +
> +#endif /* NCSI_PKT_H */
> diff --git a/slirp/ncsi.c b/slirp/ncsi.c
> new file mode 100644
> index 000000000000..8f8f4609eff5
> --- /dev/null
> +++ b/slirp/ncsi.c
> @@ -0,0 +1,95 @@
> +/*
> + * NCSI
> + *
> + * Copyright (C) 2016 IBM Corp.
> + *
> + * 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 <slirp.h>
> +
> +#include "ncsi-pkt.h"
> +
> +#if defined(_WIN32)
> +/* Windows ntohl() returns an u_long value.
> + * Add a type cast to match the format strings. */
> +# define ntohl(n) ((uint32_t)ntohl(n))
> +#endif
> +
> +/*
> + * ncsi header + checksum + max payload (NCSI_PKT_CMD_GVI)
> + */
> +#define NCSI_LEN (sizeof(struct ncsi_pkt_hdr) + 4 + 36)
> +
> +void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
> +{
> +    struct ncsi_pkt_hdr *nh = (struct ncsi_pkt_hdr *)(pkt + ETH_HLEN);
> +    uint8_t ncsi_reply[ETH_HLEN + NCSI_LEN];
> +    struct ethhdr *reh = (struct ethhdr *)ncsi_reply;
> +    struct ncsi_rsp_pkt_hdr *rnh = (struct ncsi_rsp_pkt_hdr *)
> +        (ncsi_reply + ETH_HLEN);
> +
> +    memset(ncsi_reply, 0, sizeof(ncsi_reply));
> +
> +    memset(reh->h_dest, 0xff, ETH_ALEN);
> +    memset(reh->h_source, 0xff, ETH_ALEN);
> +    reh->h_proto = htons(ETH_P_NCSI);
> +
> +    rnh->common.mc_id        = nh->mc_id;
> +    rnh->common.revision     = NCSI_PKT_REVISION;
> +    rnh->common.reserved     = 0;
> +    rnh->common.id           = nh->id;
> +    rnh->common.type         = nh->type + 0x80;
> +    rnh->common.channel      = nh->channel;
> +    rnh->common.length       = htons(4);
> +    rnh->common.reserved1[0] = 0;
> +    rnh->common.reserved1[1] = 0;
> +    rnh->code         = htons(NCSI_PKT_RSP_C_COMPLETED);
> +    rnh->reason       = htons(NCSI_PKT_RSP_R_NO_ERROR);
> +
> +    switch (nh->type) {
> +    case NCSI_PKT_CMD_SMA:
> +        rnh->common.length = htons(4);
> +        break;
> +    case NCSI_PKT_CMD_GVI:
> +        rnh->common.length = htons(36);
> +        break;
> +    case NCSI_PKT_CMD_GC: {
> +        struct ncsi_rsp_gc_pkt *rsp = (struct ncsi_rsp_gc_pkt *) rnh;
> +
> +        rnh->common.length = htons(32);
> +        rsp->cap = htonl(~0);
> +        rsp->bc_cap = htonl(~0);
> +        rsp->mc_cap = htonl(~0);
> +        rsp->buf_cap = htonl(~0);
> +        rsp->aen_cap = htonl(~0);
> +        rsp->vlan_mode = 0xff;
> +        rsp->uc_cnt = 2;
> +        break;
> +    }
> +
> +    case NCSI_PKT_CMD_GLS: {
> +        struct ncsi_rsp_gls_pkt *rsp = (struct ncsi_rsp_gls_pkt *) rnh;
> +
> +        rnh->common.length = htons(16);
> +        rsp->status = htonl(0x1);
> +        break;
> +    }
> +    default:
> +        break;
> +    }
> +
> +    slirp_output(slirp->opaque, ncsi_reply, sizeof(ncsi_reply));
> +}
> diff --git a/slirp/slirp.c b/slirp/slirp.c
> index 6e2b4e5a9010..c445c474e7e5 100644
> --- a/slirp/slirp.c
> +++ b/slirp/slirp.c
> @@ -870,6 +870,10 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
>          }
>          break;
>  
> +    case ETH_P_NCSI:
> +        ncsi_input(slirp, pkt, pkt_len);
> +        break;
> +
>      default:
>          break;
>      }
> diff --git a/slirp/slirp.h b/slirp/slirp.h
> index a1f31391341d..ef75357d4d75 100644
> --- a/slirp/slirp.h
> +++ b/slirp/slirp.h
> @@ -292,6 +292,9 @@ int tcp_emu(struct socket *, struct mbuf *);
>  int tcp_ctl(struct socket *);
>  struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
>  
> +/* ncsi.c */
> +void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
> +
>  #ifndef _WIN32
>  #define min(x,y) ((x) < (y) ? (x) : (y))
>  #define max(x,y) ((x) > (y) ? (x) : (y))

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region
  2016-11-28  1:44   ` Andrew Jeffery
@ 2016-11-28  7:24     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-28  7:24 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/28/2016 02:44 AM, Andrew Jeffery wrote:
> On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
>> The SPI controller of the AST2400 SoC does not support DMAs and
>> segment registers, hence it has less registers. So we can adjust the
>> size of the memory region holding the registers depending on the
>> controller type. We can also remove the guest_error logging which is
>> useless as the range of the region is strict enough.
>>
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/ssi/aspeed_smc.c         | 23 ++++++++---------------
>>  include/hw/ssi/aspeed_smc.h |  1 +
>>  2 files changed, 9 insertions(+), 15 deletions(-)
>>
>> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
>> index c0ae07ef8c96..7d7800d96271 100644
>> --- a/hw/ssi/aspeed_smc.c
>> +++ b/hw/ssi/aspeed_smc.c
>> @@ -135,6 +135,8 @@
>>  #define R_SPI_MISC_CTRL   (0x10 / 4)
>>  #define R_SPI_TIMINGS     (0x14 / 4)
>>  
>> +#define R_SPI_MAX         (0x20 / 4)
>> +
>>  #define ASPEED_SOC_SMC_FLASH_BASE   0x10000000
>>  #define ASPEED_SOC_FMC_FLASH_BASE   0x20000000
>>  #define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
>> @@ -221,6 +223,7 @@ static const AspeedSMCController controllers[] = {
>>          .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
>>          .flash_window_size = 0x10000000,
>>          .has_dma           = true,
>> +        .nregs             = ASPEED_SMC_R_MAX,
>>      }, {
>>          .name              = "aspeed.smc.spi",
>>          .r_conf            = R_SPI_CONF,
>> @@ -233,6 +236,7 @@ static const AspeedSMCController controllers[] = {
>>          .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
>>          .flash_window_size = 0x10000000,
>>          .has_dma           = false,
>> +        .nregs             = R_SPI_MAX,
>>      }, {
>>          .name              = "aspeed.smc.ast2500-fmc",
>>          .r_conf            = R_CONF,
>> @@ -245,6 +249,7 @@ static const AspeedSMCController controllers[] = {
>>          .flash_window_base = ASPEED_SOC_FMC_FLASH_BASE,
>>          .flash_window_size = 0x10000000,
>>          .has_dma           = true,
>> +        .nregs             = ASPEED_SMC_R_MAX,
>>      }, {
>>          .name              = "aspeed.smc.ast2500-spi1",
>>          .r_conf            = R_CONF,
>> @@ -257,6 +262,7 @@ static const AspeedSMCController controllers[] = {
>>          .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
>>          .flash_window_size = 0x8000000,
>>          .has_dma           = false,
>> +        .nregs             = ASPEED_SMC_R_MAX,
>>      }, {
>>          .name              = "aspeed.smc.ast2500-spi2",
>>          .r_conf            = R_CONF,
>> @@ -269,6 +275,7 @@ static const AspeedSMCController controllers[] = {
>>          .flash_window_base = ASPEED_SOC_SPI2_FLASH_BASE,
>>          .flash_window_size = 0x8000000,
>>          .has_dma           = false,
>> +        .nregs             = ASPEED_SMC_R_MAX,
>>      },
>>  };
>>  
>> @@ -712,13 +719,6 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
>>  
>>      addr >>= 2;
>>  
>> -    if (addr >= ARRAY_SIZE(s->regs)) {
>> -        qemu_log_mask(LOG_GUEST_ERROR,
>> -                      "%s: Out-of-bounds read at 0x%" HWADDR_PRIx "\n",
>> -                      __func__, addr);
>> -        return 0;
>> -    }
>> -
>>      if (addr == s->r_conf ||
>>          addr == s->r_timings ||
>>          addr == s->r_ce_ctrl ||
>> @@ -942,13 +942,6 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
>>  
>>      addr >>= 2;
>>  
>> -    if (addr >= ARRAY_SIZE(s->regs)) {
>> -        qemu_log_mask(LOG_GUEST_ERROR,
>> -                      "%s: Out-of-bounds write at 0x%" HWADDR_PRIx "\n",
>> -                      __func__, addr);
>> -        return;
>> -    }
>> -
>>      if (addr == s->r_conf ||
>>          addr == s->r_timings ||
>>          addr == s->r_ce_ctrl) {
>> @@ -1030,7 +1023,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
>>  
>>      /* The memory region for the controller registers */
>>      memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
>> -                          s->ctrl->name, ASPEED_SMC_R_MAX * 4);
>> +                          s->ctrl->name, s->ctrl->nregs * 4);
> 
> It looks like you missed defining nregs for the "aspeed.smc.smc"
> controller. This would suggest we need to.

Ah yes. we don't instantiate the legacy controller so I didn't see it.

Thanks,

C. 


> Andrew
> 
>>      sysbus_init_mmio(sbd, &s->mmio);
>>  
>>      /*
>> diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
>> index 3ae0a369073d..91bad82e9c65 100644
>> --- a/include/hw/ssi/aspeed_smc.h
>> +++ b/include/hw/ssi/aspeed_smc.h
>> @@ -45,6 +45,7 @@ typedef struct AspeedSMCController {
>>      hwaddr flash_window_base;
>>      uint32_t flash_window_size;
>>      bool has_dma;
>> +    uint32_t nregs;
>>  } AspeedSMCController;
>>  
>>  typedef struct AspeedSMCFlash {

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

* Re: [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3
  2016-11-28  2:04     ` Andrew Jeffery
@ 2016-11-28  9:51       ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-28  9:51 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc, Alastair D'Silva

On 11/28/2016 03:04 AM, Andrew Jeffery wrote:
> On Tue, 2016-11-22 at 17:57 +0100, Cédric Le Goater wrote:
>> On 11/18/2016 03:22 PM, Cédric Le Goater wrote:
>>> Temperatures can be changed from the monitor with :
>>>
>>> 	(qemu) qom-set /machine/unattached/device[2] temperature0 12000
>>
>>
>> These devices should be defined at the machine level, in palmetto_bmc_init(), 
>> and not at the SoC level. 
> 
> Agreed. Did you see my comments on Alistair's RTC patch along these
> lines?

Regarding aspeed_i2c_bus_init() ? Yes but this patch was sent 
before. 

I was thinking putting these patches on hold and wait for 
Alastair's  proposal to add I2C devices to the board.


C.

> Andrew
> 
>>
>> C.
>>
>>>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>> ---
>>>  hw/arm/aspeed_soc.c | 8 ++++++++
>>>  1 file changed, 8 insertions(+)
>>>
>>> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
>>> index 24354f700115..2aa15d90cc31 100644
>>> --- a/hw/arm/aspeed_soc.c
>>> +++ b/hw/arm/aspeed_soc.c
>>> @@ -268,6 +268,14 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
>>>      sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
>>>                         qdev_get_gpio_in(DEVICE(&s->vic), 12));
>>>  
>>> +    /* add a TMP423 temperature sensor */
>>> +    dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&s->i2c), 2),
>>> +                           "tmp423", 0x4c);
>>> +    object_property_set_int(OBJECT(dev), 31000, "temperature0", &err);
>>> +    object_property_set_int(OBJECT(dev), 28000, "temperature1", &err);
>>> +    object_property_set_int(OBJECT(dev), 20000, "temperature2", &err);
>>> +    object_property_set_int(OBJECT(dev), 110000, "temperature3", &err);
>>> +
>>>      /* FMC */
>>>      fmc_num_cs = aspeed_fmc_get_cs(s, &err);
>>>      if (err) {
>>>
>>

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

* Re: [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0
  2016-11-28  2:09     ` Andrew Jeffery
@ 2016-11-28  9:52       ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-28  9:52 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc, Alastair D'Silva

On 11/28/2016 03:09 AM, Andrew Jeffery wrote:
> On Mon, 2016-11-28 at 12:35 +1030, Andrew Jeffery wrote:
>> On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
>>> The palmetto platform has a ds3231 RTC device but not qemu. Let's
>>> use
>>> a ds1338 instead which provides enough basic RTC features. Only
>>> alarms
>>> will be missing
>>>
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>
>> Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
> 
> With the caveat that we move it to the board file. Evo needs an 'undo
> send' option like gmail.

we could use Alastair's RTC device also which is more complete.

C. 

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

* Re: [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model
  2016-11-28  2:11     ` Andrew Jeffery
@ 2016-11-28  9:58       ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-28  9:58 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/28/2016 03:11 AM, Andrew Jeffery wrote:
> On Mon, 2016-11-21 at 14:03 +0100, Cédric Le Goater wrote:
>> On 11/18/2016 03:22 PM, Cédric Le Goater wrote:
>>> From: Joel Stanley <joel@jms.id.au>
>>>
>>> Signed-off-by: Joel Stanley <joel@jms.id.au>
>>> [clg: fixed compile breakage
>>>       fixed io region size
>>>       added  watchdog_perform_action() on timer expiry ]
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>> ---
>>>  hw/watchdog/Makefile.objs        |   1 +
>>>  hw/watchdog/wdt_aspeed.c         | 194
>>> +++++++++++++++++++++++++++++++++++++++
>>>  include/hw/watchdog/wdt_aspeed.h |  41 +++++++++
>>>  3 files changed, 236 insertions(+)
>>>  create mode 100644 hw/watchdog/wdt_aspeed.c
>>>  create mode 100644 include/hw/watchdog/wdt_aspeed.h
>>>
>>> diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
>>> index 72e3ffd93c59..9589bed63a3d 100644
>>> --- a/hw/watchdog/Makefile.objs
>>> +++ b/hw/watchdog/Makefile.objs
>>> @@ -2,3 +2,4 @@ common-obj-y += watchdog.o
>>>  common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
>>>  common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
>>>  common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
>>> +common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o
>>> diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
>>> new file mode 100644
>>> index 000000000000..29d9d7f91463
>>> --- /dev/null
>>> +++ b/hw/watchdog/wdt_aspeed.c
>>> @@ -0,0 +1,194 @@
>>> +/*
>>> + * Copyright 2016 IBM Corporation
>>> + *
>>> + * This code is licensed under the GPL version 2 or later.  See
>>> + * the COPYING file in the top-level directory.
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "qemu/log.h"
>>> +#include "sysemu/watchdog.h"
>>> +#include "hw/sysbus.h"
>>> +#include "qemu/timer.h"
>>> +#include "hw/watchdog/wdt_aspeed.h"
>>> +
>>> +#define WDT_IO_REGION_SIZE      0x1000
>>> +
>>> +#define WDT_STATUS              0x00
>>> +#define WDT_RELOAD_VALUE        0x04
>>> +#define WDT_RESTART             0x08
>>> +#define WDT_CTRL                0x0C
>>> +#define WDT_TIMEOUT_STATUS      0x10
>>> +#define WDT_TIMEOUT_CLEAR       0x14
>>> +#define WDT_RESET_WDITH         0x18
>>
>>
>> May be we should reduce the size of WDT_IO_REGION_SIZE to 0x20
>> to instantiate the three watchdog of the Aspeed AST2500 with 
>> one class ? 
>>
>> Here is the layout :
>>
>> WDT00: WDT1 Counter Status Register
>> WDT04: WDT1 Counter Reload Value Register
>> WDT08: WDT1 Counter Restart Register
>> WDT0C: WDT1 Control Register
>> WDT10: WDT1 Timeout Status Register
>> WDT14: WDT1 Clear Timeout Status Register
>> WDT18: WDT1 Reset Width Register
>> WDT1C: WDT1 Reset Mask Register (AST2500)
>>
>> WDT20: WDT2 Counter Status Register
>> WDT24: WDT2 Counter Reload Value Register
>> WDT28: WDT2 Counter Restart Register
>> WDT2C: WDT2 Control Register
>> WDT30: WDT2 Timeout Status Register
>> WDT34: WDT2 Clear Timeout Status Register
>> WDT38: WDT2 Reset Width Register
>> WDT3C: WDT2 Reset Mask Register  (AST2500)
>>
>> WDT40: WDT3 Counter Status Register  (AST2500)
>> WDT44: WDT3 Counter Reload Value Register  (AST2500)
>> WDT48: WDT3 Counter Restart Register  (AST2500)
>> WDT4C: WDT3 Control Register  (AST2500)
>> WDT50: WDT3 Timeout Status Register  (AST2500)
>> WDT54: WDT3 Clear Timeout Status Register  (AST2500)
>> WDT5C: WDT3 Reset Mask Register  (AST2500)
>>
> 
> If we're hacking it, can we squash the timer fixups and clock rate
> derivation into the initial commit? I don't like the idea of sending it
> broken.

sure. I will fold your fixes in the initial patch and add your SoB.

C.


> Andrew
> 
>> C.
>>
>>
>>
>>
>>> +#define WDT_RESTART_MAGIC       0x4755
>>> +
>>> +static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset,
>>> unsigned size)
>>> +{
>>> +    AspeedWDTState *s = ASPEED_WDT(opaque);
>>> +
>>> +    switch (offset) {
>>> +    case WDT_STATUS:
>>> +        return s->reg_status;
>>> +    case WDT_RELOAD_VALUE:
>>> +        return s->reg_reload_value;
>>> +    case WDT_RESTART:
>>> +        qemu_log_mask(LOG_GUEST_ERROR,
>>> +                      "%s: read from write-only reg at offset 0x%"
>>> +                      HWADDR_PRIx "\n", __func__, offset);
>>> +        return 0;
>>> +    case WDT_CTRL:
>>> +        return s->reg_ctrl;
>>> +    case WDT_TIMEOUT_STATUS:
>>> +    case WDT_TIMEOUT_CLEAR:
>>> +    case WDT_RESET_WDITH:
>>> +        qemu_log_mask(LOG_UNIMP,
>>> +                      "%s: uninmplemented read at offset 0x%"
>>> HWADDR_PRIx "\n",
>>> +                      __func__, offset);
>>> +        return 0;
>>> +    default:
>>> +        qemu_log_mask(LOG_GUEST_ERROR,
>>> +                      "%s: Out-of-bounds read at offset 0x%"
>>> HWADDR_PRIx "\n",
>>> +                      __func__, offset);
>>> +        return 0;
>>> +    }
>>> +
>>> +}
>>> +
>>> +static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t
>>> data,
>>> +                             unsigned size)
>>> +{
>>> +    AspeedWDTState *s = ASPEED_WDT(opaque);
>>> +    bool en = data & BIT(0);
>>> +
>>> +    switch (offset) {
>>> +    case WDT_STATUS:
>>> +        qemu_log_mask(LOG_GUEST_ERROR,
>>> +                      "%s: write to read-only reg at offset 0x%"
>>> +                      HWADDR_PRIx "\n", __func__, offset);
>>> +        break;
>>> +    case WDT_RELOAD_VALUE:
>>> +        s->reg_reload_value = data;
>>> +        break;
>>> +    case WDT_RESTART:
>>> +        if ((data & 0xFFFF) == 0x4755) {
>>> +            s->reg_status = s->reg_reload_value;
>>> +
>>> +            if (s->enabled) {
>>> +                timer_mod(s->timer,
>>> +                          qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
>>> +                          s->reg_reload_value *
>>> NANOSECONDS_PER_SECOND);
>>> +            }
>>> +        }
>>> +        break;
>>> +    case WDT_CTRL:
>>> +        if (en && !s->enabled) {
>>> +            s->enabled = true;
>>> +            timer_mod(s->timer,
>>> +                      qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
>>> +                      s->reg_reload_value *
>>> NANOSECONDS_PER_SECOND);
>>> +        } else if (!en && s->enabled) {
>>> +            s->enabled = false;
>>> +            timer_del(s->timer);
>>> +        }
>>> +        break;
>>> +    case WDT_TIMEOUT_STATUS:
>>> +    case WDT_TIMEOUT_CLEAR:
>>> +    case WDT_RESET_WDITH:
>>> +        qemu_log_mask(LOG_UNIMP,
>>> +                      "%s: uninmplemented write at offset 0x%"
>>> HWADDR_PRIx "\n",
>>> +                      __func__, offset);
>>> +        break;
>>> +    default:
>>> +        qemu_log_mask(LOG_GUEST_ERROR,
>>> +                      "%s: Out-of-bounds write at offset 0x%"
>>> HWADDR_PRIx "\n",
>>> +                      __func__, offset);
>>> +    }
>>> +    return;
>>> +}
>>> +
>>> +static WatchdogTimerModel model = {
>>> +    .wdt_name = TYPE_ASPEED_WDT,
>>> +    .wdt_description = "aspeed watchdog device",
>>> +};
>>> +
>>> +static const VMStateDescription vmstate_aspeed_wdt = {
>>> +    .name = "vmstate_aspeed_wdt",
>>> +    .version_id = 0,
>>> +    .minimum_version_id = 0,
>>> +    .fields = (VMStateField[]) {
>>> +        VMSTATE_TIMER_PTR(timer, AspeedWDTState),
>>> +        VMSTATE_BOOL(enabled, AspeedWDTState),
>>> +        VMSTATE_END_OF_LIST()
>>> +    }
>>> +};
>>> +
>>> +static const MemoryRegionOps aspeed_wdt_ops = {
>>> +    .read = aspeed_wdt_read,
>>> +    .write = aspeed_wdt_write,
>>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>>> +    .valid.min_access_size = 4,
>>> +    .valid.max_access_size = 4,
>>> +    .valid.unaligned = false,
>>> +};
>>> +
>>> +static void aspeed_wdt_reset(DeviceState *dev)
>>> +{
>>> +    AspeedWDTState *s = ASPEED_WDT(dev);
>>> +
>>> +    s->reg_status = 0x3EF1480;
>>> +    s->reg_reload_value = 0x03EF1480;
>>> +    s->reg_restart = 0;
>>> +    s->reg_ctrl = 0;
>>> +
>>> +    s->enabled = false;
>>> +    timer_del(s->timer);
>>> +}
>>> +
>>> +static void aspeed_wdt_timer_expired(void *dev)
>>> +{
>>> +    AspeedWDTState *s = ASPEED_WDT(dev);
>>> +
>>> +    qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
>>> +    watchdog_perform_action();
>>> +    timer_del(s->timer);
>>> +}
>>> +
>>> +static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
>>> +{
>>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>>> +    AspeedWDTState *s = ASPEED_WDT(dev);
>>> +
>>> +    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
>>> aspeed_wdt_timer_expired,
>>> +                            dev);
>>> +
>>> +    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_wdt_ops,
>>> s,
>>> +                          TYPE_ASPEED_WDT, WDT_IO_REGION_SIZE);
>>> +    sysbus_init_mmio(sbd, &s->iomem);
>>> +}
>>> +
>>> +static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +
>>> +    dc->realize = aspeed_wdt_realize;
>>> +    dc->reset = aspeed_wdt_reset;
>>> +    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>>> +    dc->vmsd = &vmstate_aspeed_wdt;
>>> +}
>>> +
>>> +static const TypeInfo aspeed_wdt_info = {
>>> +    .parent = TYPE_SYS_BUS_DEVICE,
>>> +    .name  = TYPE_ASPEED_WDT,
>>> +    .instance_size  = sizeof(AspeedWDTState),
>>> +    .class_init = aspeed_wdt_class_init,
>>> +};
>>> +
>>> +static void wdt_aspeed_register_types(void)
>>> +{
>>> +    watchdog_add_model(&model);
>>> +    type_register_static(&aspeed_wdt_info);
>>> +}
>>> +
>>> +type_init(wdt_aspeed_register_types)
>>> diff --git a/include/hw/watchdog/wdt_aspeed.h
>>> b/include/hw/watchdog/wdt_aspeed.h
>>> new file mode 100644
>>> index 000000000000..dbf45ae968db
>>> --- /dev/null
>>> +++ b/include/hw/watchdog/wdt_aspeed.h
>>> @@ -0,0 +1,41 @@
>>> +/*
>>> + * ASPEED Watchdog Controller
>>> + *
>>> + * Copyright (C) 2016 IBM Corp.
>>> + *
>>> + * This code is licensed under the GPL version 2 or later. See the
>>> + * COPYING file in the top-level directory.
>>> + */
>>> +#ifndef ASPEED_WDT_H
>>> +#define ASPEED_WDT_H
>>> +
>>> +#include "hw/sysbus.h"
>>> +
>>> +#define TYPE_ASPEED_WDT "aspeed.wdt"
>>> +#define ASPEED_WDT(obj) \
>>> +    OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT)
>>> +#define ASPEED_WDT_CLASS(klass) \
>>> +    OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT)
>>> +#define ASPEED_WDT_GET_CLASS(obj) \
>>> +    OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT)
>>> +
>>> +#define WDT_ASPEED_INIT      0
>>> +#define WDT_ASPEED_CHANGE    1
>>> +#define WDT_ASPEED_CANCEL    2
>>> +
>>> +typedef struct AspeedWDTState {
>>> +    /*< private >*/
>>> +    SysBusDevice parent_obj;
>>> +    QEMUTimer *timer;
>>> +    bool enabled;
>>> +
>>> +    /*< public >*/
>>> +    MemoryRegion iomem;
>>> +
>>> +    uint32_t reg_status;
>>> +    uint32_t reg_reload_value;
>>> +    uint32_t reg_restart;
>>> +    uint32_t reg_ctrl;
>>> +} AspeedWDTState;
>>> +
>>> +#endif  /* ASPEED_WDT_H */
>>>
>>

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

* Re: [PATCH qemu 35/38] net/ftgmac100: add a 'aspeed' property
  2016-11-28  2:22   ` Andrew Jeffery
@ 2016-11-28 11:20     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-28 11:20 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/28/2016 03:22 AM, Andrew Jeffery wrote:
> On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
>> Aspeed SOCs have different definitions for the end of ring bits. Add
>> a
>> property to specify which set of bits should be used by the nic
>> device
>> model.
>>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/net/ftgmac100.c         | 24 ++++++++++++++++++++----
>>  include/hw/net/ftgmac100.h |  2 ++
>>  2 files changed, 22 insertions(+), 4 deletions(-)
>>
>> diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
>> index 22573ff956fd..0a8ab6b9e4d8 100644
>> --- a/hw/net/ftgmac100.c
>> +++ b/hw/net/ftgmac100.c
>> @@ -136,9 +136,11 @@ struct ftgmac100_txdes {
>>  
>>  #define FTGMAC100_TXDES0_TXBUF_SIZE(x)   ((x) & 0x3fff)
>>  #define FTGMAC100_TXDES0_EDOTR           (1 << 15)
>> +
>>  #define FTGMAC100_TXDES0_CRC_ERR         (1 << 19)
>>  #define FTGMAC100_TXDES0_LTS             (1 << 28)
>>  #define FTGMAC100_TXDES0_FTS             (1 << 29)
>> +#define FTGMAC100_TXDES0_EDOTR_ASPEED    (1 << 30)
>>  #define FTGMAC100_TXDES0_TXDMA_OWN       (1 << 31)
>>  
>>  #define FTGMAC100_TXDES1_VLANTAG_CI(x)   ((x) & 0xffff)
>> @@ -174,6 +176,7 @@ struct ftgmac100_rxdes {
>>  #define FTGMAC100_RXDES0_PAUSE_FRAME     (1 << 25)
>>  #define FTGMAC100_RXDES0_LRS             (1 << 28)
>>  #define FTGMAC100_RXDES0_FRS             (1 << 29)
>> +#define FTGMAC100_RXDES0_EDORR_ASPEED    (1 << 30)
>>  #define FTGMAC100_RXDES0_RXPKT_RDY       (1 << 31)
>>  
>>  #define FTGMAC100_RXDES1_VLANTAG_CI      0xffff
>> @@ -208,6 +211,18 @@ typedef struct {
>>      uint32_t        des3;        /* TXBUF_BADR */
>>  } Ftgmac100Desc  __attribute__ ((aligned(16)));
>>  
>> +static inline uint32_t ftgmac100_rxdes0_edorr(Ftgmac100State *s)
>> +{
>> +    return s->aspeed ?
>> +        FTGMAC100_RXDES0_EDORR_ASPEED : FTGMAC100_RXDES0_EDORR;
>> +}
>> +
>> +static inline uint32_t ftgmac100_txdes0_edotr(Ftgmac100State *s)
>> +{
>> +    return s->aspeed ?
>> +        FTGMAC100_TXDES0_EDOTR_ASPEED : FTGMAC100_TXDES0_EDOTR;
>> +}
>> +
>>  /* max frame size is :
>>   *
>>   *   9216 for Jumbo frames (+ 4 for VLAN)
>> @@ -405,7 +420,7 @@ static uint32_t
>> ftgmac100_find_txdes(Ftgmac100State *s, uint32_t addr)
>>  
>>      while (1) {
>>          ftgmac100_read_bd(&bd, addr);
>> -        if (bd.des0 & (FTGMAC100_TXDES0_FTS |
>> FTGMAC100_TXDES0_EDOTR)) {
>> +        if (bd.des0 & (FTGMAC100_TXDES0_FTS |
>> ftgmac100_txdes0_edotr(s))) {
>>              break;
>>          }
>>          addr += sizeof(Ftgmac100Desc);
>> @@ -459,7 +474,7 @@ static void ftgmac100_do_tx(Ftgmac100State *s)
>>          /* Write back the modified descriptor.  */
>>          ftgmac100_write_bd(&bd, addr);
>>          /* Advance to the next descriptor.  */
>> -        if (bd.des0 & FTGMAC100_TXDES0_EDOTR) {
>> +        if (bd.des0 & ftgmac100_txdes0_edotr(s)) {
> 
> Should we just derive the bit and stash it in a state member at realise
> time? Would save a branch for every call. Interested in your thoughts,
> not necessarily something that must happen.

This is a good suggestion and it is a small change in the code.

Thanks,


C.


> 
>>              addr = s->tx_ring;
>>          } else {
>>              addr += sizeof(Ftgmac100Desc);
>> @@ -480,7 +495,7 @@ static void ftgmac100_enable_rx(Ftgmac100State
>> *s)
>>      while (1) {
>>          ftgmac100_read_bd(&bd, s->rx_descriptor);
>>          full = (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY);
>> -        if (!full || bd.des0 & FTGMAC100_TXDES0_EDOTR) {
>> +        if (!full || bd.des0 & ftgmac100_txdes0_edotr(s)) {
>>              break;
>>          }
>>          s->rx_descriptor += sizeof(Ftgmac100Desc);
>> @@ -784,7 +799,7 @@ static ssize_t ftgmac100_receive(NetClientState
>> *nc, const uint8_t *buf,
>>              s->isr |= FTGMAC100_INT_RPKT_FIFO;
>>          }
>>          ftgmac100_write_bd(&bd, addr);
>> -        if (bd.des0 & FTGMAC100_RXDES0_EDORR) {
>> +        if (bd.des0 & ftgmac100_rxdes0_edorr(s)) {
>>              addr = s->rx_ring;
>>          } else {
>>              addr += sizeof(Ftgmac100Desc); 
>> @@ -869,6 +884,7 @@ static const VMStateDescription vmstate_ftgmac100
>> = {
>>  };
>>  
>>  static Property ftgmac100_properties[] = {
>> +    DEFINE_PROP_BOOL("aspeed", Ftgmac100State, aspeed, false),
>>      DEFINE_NIC_PROPERTIES(Ftgmac100State, conf),
>>      DEFINE_PROP_END_OF_LIST(),
>>  };
>> diff --git a/include/hw/net/ftgmac100.h b/include/hw/net/ftgmac100.h
>> index cc5cb4207a5c..ee8975000260 100644
>> --- a/include/hw/net/ftgmac100.h
>> +++ b/include/hw/net/ftgmac100.h
>> @@ -57,6 +57,8 @@ typedef struct Ftgmac100State {
>>      uint32_t phy_int;
>>      uint32_t phy_int_mask;
>>  
>> +    bool aspeed;
>> +
>>  } Ftgmac100State;
>>  
>>  #endif
> 
> Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
> 

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

* Re: [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller
  2016-11-28  1:55   ` Andrew Jeffery
@ 2016-11-28 12:34     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-28 12:34 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

On 11/28/2016 02:55 AM, Andrew Jeffery wrote:
> On Fri, 2016-11-18 at 15:22 +0100, Cédric Le Goater wrote:
>> The lock register is unlocked with a write of a special value and
>> locked with a write of any other value. When unlocked, reads return
>> one and when locked a zero.
>>
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> ---
>>  hw/misc/aspeed_sdmc.c         | 28 +++++++++++++++++++---------
>>  include/hw/misc/aspeed_sdmc.h |  1 +
>>  2 files changed, 20 insertions(+), 9 deletions(-)
>>
>> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
>> index 5f3ac0b6f608..867caa2d64dc 100644
>> --- a/hw/misc/aspeed_sdmc.c
>> +++ b/hw/misc/aspeed_sdmc.c
>> @@ -83,17 +83,22 @@
>>  static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
>>  {
>>      AspeedSDMCState *s = ASPEED_SDMC(opaque);
>> +    uint64_t val = 0;
>>  
>>      addr >>= 2;
>>  
>> -    if (addr >= ARRAY_SIZE(s->regs)) {
>> +    switch (addr) {
>> +    case R_PROT:
>> +        val = s->unlocked;
>> +        break;
>> +    default:
>>          qemu_log_mask(LOG_GUEST_ERROR,
>>                        "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
>>                        __func__, addr);
>> -        return 0;
>> +        break;
>>      }
>>  
>> -    return s->regs[addr];
>> +    return val;
> 
> This suggests we only care about R_PROT - the change returns 0 for the
> value of other registers. That doesn't seem right.

Well, the read already returned 0 and that is what you get most of the 
time on real HW. Some time you get a 0xFFFFFFFF. 

Thanks,

C.


> Andrew
> 
>>  }
>>  
>>  static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>> @@ -103,19 +108,18 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>>  
>>      addr >>= 2;
>>  
>> -    if (addr >= ARRAY_SIZE(s->regs)) {
>> -        qemu_log_mask(LOG_GUEST_ERROR,
>> -                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
>> -                      __func__, addr);
>> +    if (addr == R_PROT) {
>> +        s->unlocked = (data == PROT_KEY_UNLOCK);
>>          return;
>>      }
>>  
>> -    if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) {
>> +    if (!s->unlocked) { /* TODO protect : MCR04 ∼ MCR7C */
>>          qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
>>          return;
>>      }
>>  
>> -    if (addr == R_CONF) {
>> +    switch (addr) {
>> +    case R_CONF:
>>          /* Make sure readonly bits are kept */
>>          switch (s->silicon_rev) {
>>          case AST2400_A0_SILICON_REV:
>> @@ -128,6 +132,12 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>>          default:
>>              g_assert_not_reached();
>>          }
>> +        break;
>> +    default:
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
>> +                      __func__, addr << 2);
>> +        return;
>>      }
>>  
>>      s->regs[addr] = data;
>> diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
>> index 551c8afdf4be..a4415d9efc2f 100644
>> --- a/include/hw/misc/aspeed_sdmc.h
>> +++ b/include/hw/misc/aspeed_sdmc.h
>> @@ -28,6 +28,7 @@ typedef struct AspeedSDMCState {
>>      uint32_t ram_bits;
>>      uint64_t ram_size;
>>  
>> +    bool unlocked;
>>  } AspeedSDMCState;
>>  
>>  #endif /* ASPEED_SDMC_H */

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

* Re: [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run
  2016-11-28  2:02   ` Andrew Jeffery
@ 2016-11-28 12:38     ` Cédric Le Goater
  0 siblings, 0 replies; 142+ messages in thread
From: Cédric Le Goater @ 2016-11-28 12:38 UTC (permalink / raw)
  To: Andrew Jeffery, openbmc

> +    case R_CONF:
> +    case R_GRAPHIC_MEM_PROT:
> +    case R_REFRESH_TIMING:
> +    case R_AC_TIMING1:
> +    case R_AC_TIMING2:
> +    case R_CQDQS_DELAY_CTRL:
> +    case R_MCLK_CALIB_STATUS:
> +    case R_DQS_INPUT_CALIB_STATUS:
> +    case R_MCR24:
> +    case R_MODE_SETTING_CTRL:
> +    case R_MRS_MODE_SETTING_CTRL:
> +    case R_EMRS_MODE_SETTING_CTRL:
> +    case R_POWER_CTRL:
> +    case R_PAGE_MISS_MASK:
> +    case R_MAX_GRANT_LEN1:
> +    case R_MAX_GRANT_LEN2:
> +    case R_MAX_GRANT_LEN3:
> +    case R_MAX_GRANT_LEN4:
> +    case R_IRQ_STATUS_CTRL:
> +    case R_ECC_PROTECT:
> +    case R_MCR58:
> +    case R_IO_BUFFER_MODE:
> +    case R_DLL_CTRL:
> +    case R_DLL_CTRL2:
> +    case R_DDR_IO_IMPEDANCE_CTRL:
> +    case R_START_ADDR_LEN:
> +    case R_FAIL_DQ:
> +    case R_TEST_INIT_VALUE:
> +    case R_DQ_DELAY_CALIB_CTRL2:
> +    case R_DQ_DELAY_CALIB_CTRL3:
> +    case R_CK_DUTY_VALUE:
> +    case R_COMPAT_SCU_PASSWORD:
> +    case R_COMPAT_SCU_MPLL:
> +    case R_COMPAT_SCU_HW_STRAPPING:
> 
> This is a lengthy list of registers. What are your thoughts about using
> numeric range values with comments?
> 
>  case 0x08 ... 0x38: /* GFX memprotect, refresh timings ... */
>  case 0x40 ... 0x58: /* grant length registers, ... */
>  ...
>   val = s->regs[addr];
>   break;

yes. This is better. Adding the full list is not really useful. 
I think we should only be interested in the limited set of 
registers the model fakes. I was thinking also keeping the 
patch for later when we add AST2500 "support".

Thanks,


C.
 
> Either way I'm probably not fussed, but I'm interested in your
> thoughts.
> 
> This addresses my comment on the previous patch, but it would be good
> not to break the SDMC commit-to-commit.


> Andrew
> 
>> +        val = s->regs[addr];
> +        break;
> +    case R_DQ_DELAY_CALIB_CTRL1:
> +        val = s->regs[addr] | DQ_DELAY_CALIB_COUNT_DONE;
> +        break;
> +    case R_ECC_STATUS_CTRL:
> +        val = s->regs[addr] | ECC_TEST_FINISH;
> +        break;
>      default:
>          qemu_log_mask(LOG_GUEST_ERROR,
>                        "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
> @@ -133,6 +283,42 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
>              g_assert_not_reached();
>          }
>          break;
> +    case R_GRAPHIC_MEM_PROT:
> +    case R_REFRESH_TIMING:
> +    case R_AC_TIMING1:
> +    case R_AC_TIMING2:
> +    case R_CQDQS_DELAY_CTRL:
> +    case R_MCLK_CALIB_STATUS:
> +    case R_DQS_INPUT_CALIB_STATUS:
> +    case R_MCR24:
> +    case R_MODE_SETTING_CTRL:
> +    case R_MRS_MODE_SETTING_CTRL:
> +    case R_EMRS_MODE_SETTING_CTRL:
> +    case R_POWER_CTRL:
> +    case R_PAGE_MISS_MASK:
> +    case R_MAX_GRANT_LEN1:
> +    case R_MAX_GRANT_LEN2:
> +    case R_MAX_GRANT_LEN3:
> +    case R_MAX_GRANT_LEN4:
> +    case R_IRQ_STATUS_CTRL:
> +    case R_ECC_PROTECT:
> +    case R_MCR58:
> +    case R_IO_BUFFER_MODE:
> +    case R_DLL_CTRL:
> +    case R_DLL_CTRL2:
> +    case R_DDR_IO_IMPEDANCE_CTRL:
> +    case R_ECC_STATUS_CTRL:
> +    case R_START_ADDR_LEN:
> +    case R_FAIL_DQ:
> +    case R_TEST_INIT_VALUE:
> +    case R_DQ_DELAY_CALIB_CTRL1:
> +    case R_DQ_DELAY_CALIB_CTRL2:
> +    case R_DQ_DELAY_CALIB_CTRL3:
> +    case R_CK_DUTY_VALUE:
> +    case R_COMPAT_SCU_PASSWORD:
> +    case R_COMPAT_SCU_MPLL:
> +    case R_COMPAT_SCU_HW_STRAPPING:
> +        break;
>      default:
>          qemu_log_mask(LOG_GUEST_ERROR,
>                        "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
> @@ -221,6 +407,8 @@ static void aspeed_sdmc_reset(DeviceState *dev)
>      default:
>          g_assert_not_reached();
>      }
> +
> +    s->regs[R_MCLK_CALIB_STATUS] = MCLK2X_PHASE;
>  }
>  
>  static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
> diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
> index a4415d9efc2f..e073a6c9419a 100644
> --- a/include/hw/misc/aspeed_sdmc.h
> +++ b/include/hw/misc/aspeed_sdmc.h
> @@ -14,7 +14,7 @@
>  #define TYPE_ASPEED_SDMC "aspeed.sdmc"
>  #define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
>  
> -#define ASPEED_SDMC_NR_REGS (0x8 >> 2)
> +#define ASPEED_SDMC_NR_REGS (0x174 >> 2)
>  
>  typedef struct AspeedSDMCState {
>      /*< private >*/
> 

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

end of thread, other threads:[~2016-11-28 12:38 UTC | newest]

Thread overview: 142+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-18 14:21 [PATCH qemu 00/38] aspeed: going mainline Cédric Le Goater
2016-11-18 14:21 ` [PATCH qemu 01/38] m25p80: add support for the mx66l1g45g Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-21 10:31   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 02/38] aspeed: QOMify the CPU object and attach it to the SoC Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-21 10:59   ` Andrew Jeffery
2016-11-21 14:14     ` Cédric Le Goater
2016-11-18 14:21 ` [PATCH qemu 03/38] aspeed: attach the second SPI controller object " Cédric Le Goater
2016-11-21 11:03   ` Andrew Jeffery
2016-11-21 11:42     ` Joel Stanley
2016-11-21 11:57       ` Andrew Jeffery
2016-11-21 13:14         ` Cédric Le Goater
2016-11-18 14:21 ` [PATCH qemu 04/38] aspeed: extend the board configuration with flash models Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-21 11:07   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 05/38] aspeed: add support for the romulus-bmc board Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-21 12:18   ` Andrew Jeffery
2016-11-21 14:44     ` Cédric Le Goater
2016-11-22  3:06       ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 06/38] aspeed: add a memory region for SRAM Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-21 12:21   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 07/38] aspeed: add the definitions for the AST2400 A1 SoC Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-21 12:50   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 08/38] aspeed: change SoC revision of the palmetto-bmc machine Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-21 13:16   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 09/38] aspeed/scu: fix SCU region size Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-21  9:44     ` Cédric Le Goater
2016-11-21 12:54   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 10/38] aspeed/smc: improve segment register support Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-18 14:21 ` [PATCH qemu 11/38] aspeed/smc: get the number of flash modules from hw strapping Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-21  9:59     ` Cédric Le Goater
2016-11-21 10:05       ` Joel Stanley
2016-11-21 13:13   ` Andrew Jeffery
2016-11-21 13:29     ` Cédric Le Goater
2016-11-21 13:35       ` Andrew Jeffery
2016-11-21 13:47         ` Cédric Le Goater
2016-11-22  3:10           ` Andrew Jeffery
2016-11-22  7:21             ` Cédric Le Goater
2016-11-23  1:22               ` Andrew Jeffery
2016-11-23  9:33                 ` Cédric Le Goater
2016-11-23 19:08                   ` Cédric Le Goater
2016-11-24  1:00                     ` Andrew Jeffery
2016-11-24  6:31                       ` Cédric Le Goater
2016-11-18 14:21 ` [PATCH qemu 12/38] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-21 13:20   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 13/38] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-21 10:02     ` Cédric Le Goater
2016-11-21 13:36   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 14/38] aspeed/smc: autostrap CE0/1 configuration Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-25  3:07   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 15/38] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-25  4:23   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 16/38] aspeed/smc: add tests for " Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-21 10:32     ` Cédric Le Goater
2016-11-25  4:30   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 17/38] aspeed/smc: unfold the AspeedSMCController array Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-25  4:31   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 18/38] aspeed/smc: add a 'sdram_base' property Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-25  4:35   ` Andrew Jeffery
2016-11-18 14:21 ` [PATCH qemu 19/38] aspeed/smc: add support for DMAs Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-21 11:07     ` Cédric Le Goater
2016-11-21 11:24       ` Joel Stanley
2016-11-18 14:22 ` [PATCH qemu 20/38] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-21 12:50     ` Cédric Le Goater
2016-11-28  1:35   ` Andrew Jeffery
2016-11-18 14:22 ` [PATCH qemu 21/38] aspeed/smc: adjust the size of the register region Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-28  1:44   ` Andrew Jeffery
2016-11-28  7:24     ` Cédric Le Goater
2016-11-18 14:22 ` [PATCH qemu 22/38] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-28  1:47   ` Andrew Jeffery
2016-11-18 14:22 ` [PATCH qemu 23/38] block: add a model option for MTD devices Cédric Le Goater
2016-11-21  7:27   ` Joel Stanley
2016-11-21 10:31     ` Cédric Le Goater
2016-11-18 14:22 ` [PATCH qemu 24/38] aspeed/smc: use flash model option Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-18 14:22 ` [PATCH qemu 25/38] aspeed/sdmc: rework the locking register of the memory controller Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-28  1:55   ` Andrew Jeffery
2016-11-28 12:34     ` Cédric Le Goater
2016-11-18 14:22 ` [PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run Cédric Le Goater
2016-11-21  7:25   ` Joel Stanley
2016-11-28  2:02   ` Andrew Jeffery
2016-11-28 12:38     ` Cédric Le Goater
2016-11-18 14:22 ` [PATCH qemu 27/38] hw/misc: add a TMP42{1,2,3} device model Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-18 14:22 ` [PATCH qemu 28/38] aspeed: add a temp sensor device on I2C bus 3 Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-22 16:57   ` Cédric Le Goater
2016-11-28  2:04     ` Andrew Jeffery
2016-11-28  9:51       ` Cédric Le Goater
2016-11-18 14:22 ` [PATCH qemu 29/38] aspeed: add a rtc device on I2C bus 0 Cédric Le Goater
2016-11-21  7:27   ` Joel Stanley
2016-11-22 17:00   ` Cédric Le Goater
2016-11-28  2:05   ` Andrew Jeffery
2016-11-28  2:09     ` Andrew Jeffery
2016-11-28  9:52       ` Cédric Le Goater
2016-11-18 14:22 ` [PATCH qemu 30/38] wdt: Add Aspeed watchdog device model Cédric Le Goater
2016-11-21 13:03   ` Cédric Le Goater
2016-11-21 13:23     ` Joel Stanley
2016-11-28  2:11     ` Andrew Jeffery
2016-11-28  9:58       ` Cédric Le Goater
2016-11-18 14:22 ` [PATCH qemu 31/38] aspeed: add a watchdog controller Cédric Le Goater
2016-11-21  7:27   ` Joel Stanley
2016-11-21 12:53     ` Cédric Le Goater
2016-11-28  2:12   ` Andrew Jeffery
2016-11-18 14:22 ` [PATCH qemu 32/38] wdt: aspeed: Fix failed reboot due to timer miscalculation Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-18 14:22 ` [PATCH qemu 33/38] wdt: aspeed: use scu to get clock freq Cédric Le Goater
2016-11-21  7:27   ` Joel Stanley
2016-11-18 14:22 ` [PATCH qemu 34/38] net: add FTGMAC100 support Cédric Le Goater
2016-11-28  2:13   ` Andrew Jeffery
2016-11-18 14:22 ` [PATCH qemu 35/38] net/ftgmac100: add a 'aspeed' property Cédric Le Goater
2016-11-28  2:22   ` Andrew Jeffery
2016-11-28 11:20     ` Cédric Le Goater
2016-11-18 14:22 ` [PATCH qemu 36/38] ast2400: add a FTGMAC100 nic Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-28  2:25   ` Andrew Jeffery
2016-11-18 14:22 ` [PATCH qemu 37/38] slirp: add a fake NCSI backend Cédric Le Goater
2016-11-21  7:26   ` Joel Stanley
2016-11-21 13:04     ` Cédric Le Goater
2016-11-28  2:26   ` Andrew Jeffery
2016-11-18 14:22 ` [PATCH qemu 38/38] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
2016-11-21  7:27   ` Joel Stanley

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.