All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements
@ 2016-11-29 15:43 Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 01/30] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
                   ` (30 more replies)
  0 siblings, 31 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

Here is a collection of fixes and improvements on existing models for
the Aspeed SoCs

 * Block
   - add a 'model' option to -drive for MTD devices  

 * SoC level 
   - an AST2400 A1 SoC for the Palmetto machine
   - a new 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.

 * Watchdog 
   - new model.  
   - not complete but reset under U-Boot and reboot under Linux now
     work    

Thanks,

C.

Cédric Le Goater (29):
  target-arm: Add VBAR support to ARM1176 CPUs
  m25p80: add support for the mx66l1g45g
  aspeed: QOMify the CPU object and attach it to the SoC
  aspeed: remove cannot_destroy_with_object_finalize_yet
  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: set the number of flash modules for the FMC controller
  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: extend 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: add a watchdog controller
  aspeed/scu: add a aspeed_scu_get_clk() helper
  wdt: aspeed: use scu to get clock freq

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

 blockdev.c                       |  12 +
 hw/arm/aspeed.c                  | 113 ++++++-
 hw/arm/aspeed_soc.c              | 109 +++++--
 hw/block/m25p80.c                |   1 +
 hw/misc/aspeed_scu.c             |  16 +-
 hw/misc/aspeed_sdmc.c            |   3 +
 hw/ssi/aspeed_smc.c              | 663 +++++++++++++++++++++++++++++++++------
 hw/watchdog/Makefile.objs        |   1 +
 hw/watchdog/wdt_aspeed.c         | 223 +++++++++++++
 include/hw/arm/aspeed_soc.h      |   6 +-
 include/hw/misc/aspeed_scu.h     |   2 +
 include/hw/ssi/aspeed_smc.h      |   8 +-
 include/hw/watchdog/wdt_aspeed.h |  43 +++
 include/sysemu/blockdev.h        |   1 +
 qemu-options.hx                  |   4 +-
 target-arm/cpu.c                 |   6 +
 target-arm/cpu.h                 |   1 +
 target-arm/helper.c              |  24 +-
 tests/m25p80-test.c              |  86 +++++
 19 files changed, 1197 insertions(+), 125 deletions(-)
 create mode 100644 hw/watchdog/wdt_aspeed.c
 create mode 100644 include/hw/watchdog/wdt_aspeed.h

-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 01/30] target-arm: Add VBAR support to ARM1176 CPUs
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-12-14 15:43   ` Peter Maydell
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 02/30] m25p80: add support for the mx66l1g45g Cédric Le Goater
                   ` (29 subsequent siblings)
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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 can used for ARMv7 and ARM1176 CPUs.

The VBAR feature is always set for ARMv7 because some legacy boards
require it even if this is not architecturally correct. However, to
support arm1176 CPUs without TrustZone, which doesn't exist in real
hardware but which is used in old qemu boards, we need to disable the
feature when 'has_el3' is not set.

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

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 99f0dbebb9f6..1007e504248a 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -685,6 +685,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
          */
         cpu->id_pfr1 &= ~0xf0;
         cpu->id_aa64pfr0 &= ~0xf000;
+
+        /* Also disable VBAR support for boards using a arm1176 CPU
+         * without EL3.
+         */
+        unset_feature(env, ARM_FEATURE_VBAR);
     }
 
     if (!cpu->has_pmu || !kvm_enabled()) {
@@ -911,6 +916,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..ab119e62ab0f 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 */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index b5b65caadf8a..d417c8ba802f 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 },
@@ -1412,6 +1406,16 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
     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
 
 static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4506,6 +4510,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);
@@ -4543,6 +4550,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         };
         define_one_arm_cp_reg(cpu, &clidr);
         define_arm_cp_regs(cpu, v7_cp_reginfo);
+
+        /* Always define VBAR even if it doesn't exist in non-EL3
+         * configs. This is needed by some legacy boards.
+         */
+        define_arm_cp_regs(cpu, vbar_cp_reginfo);
         define_debug_regs(cpu);
     } else {
         define_arm_cp_regs(cpu, not_v7_cp_reginfo);
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 02/30] m25p80: add support for the mx66l1g45g
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 01/30] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 03/30] aspeed: QOMify the CPU object and attach it to the SoC Cédric Le Goater
                   ` (28 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Marcin Krzeminski <marcin.krzeminski@nokia.com>
Reviewed-by: Joel Stanley <joel@jms.id.au>
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) },
 
     /* Micron */
     { INFO("n25q032a11",  0x20bb16,      0,  64 << 10,  64, ER_4K) },
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 03/30] aspeed: QOMify the CPU object and attach it to the SoC
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 01/30] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 02/30] m25p80: add support for the mx66l1g45g Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 04/30] aspeed: remove cannot_destroy_with_object_finalize_yet Cédric Le Goater
                   ` (27 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
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;
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 04/30] aspeed: remove cannot_destroy_with_object_finalize_yet
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (2 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 03/30] aspeed: QOMify the CPU object and attach it to the SoC Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 05/30] aspeed: attach the second SPI controller object to the SoC Cédric Le Goater
                   ` (26 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

With commit ce5b1bbf624b ("exec: move cpu_exec_init() calls to realize
functions"), we can now remove cannot_destroy_with_object_finalize_yet.

Suggested-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/arm/aspeed_soc.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index db145e201451..3a6b91f14b45 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -251,12 +251,6 @@ static void aspeed_soc_class_init(ObjectClass *oc, void *data)
 
     sc->info = (AspeedSoCInfo *) data;
     dc->realize = aspeed_soc_realize;
-
-    /*
-     * Reason: creates an ARM CPU, thus use after free(), see
-     * arm_cpu_class_init()
-     */
-    dc->cannot_destroy_with_object_finalize_yet = true;
 }
 
 static const TypeInfo aspeed_soc_type_info = {
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 05/30] aspeed: attach the second SPI controller object to the SoC
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (3 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 04/30] aspeed: remove cannot_destroy_with_object_finalize_yet Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 06/30] aspeed: extend the board configuration with flash models Cédric Le Goater
                   ` (25 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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 3a6b91f14b45..82e27129a900 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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 06/30] aspeed: extend the board configuration with flash models
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (4 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 05/30] aspeed: attach the second SPI controller object to the SoC Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 07/30] aspeed: add support for the romulus-bmc board Cédric Le Goater
                   ` (24 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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>
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;
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 07/30] aspeed: add support for the romulus-bmc board
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (5 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 06/30] aspeed: extend the board configuration with flash models Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 08/30] aspeed: add a memory region for SRAM Cédric Le Goater
                   ` (23 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
---
 hw/arm/aspeed.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 159d562e8912..3509011ae979 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,
 };
 
+/* Palmetto hardware value: 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))
 
+/* AST2500 evb hardware value: 0xF100C2E6 */
 #define AST2500_EVB_HW_STRAP1 ((                                        \
         AST2500_HW_STRAP1_DEFAULTS |                                    \
         SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
@@ -66,6 +69,16 @@ enum {
         SCU_HW_STRAP_MAC0_RGMII) &                                      \
         ~SCU_HW_STRAP_2ND_BOOT_WDT)
 
+/* Romulus hardware value: 0xF10AD206 */
+#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_MODE(SCU_HW_STRAP_SPI_MASTER))
+
 static const AspeedBoardConfig aspeed_boards[] = {
     [PALMETTO_BMC] = {
         .soc_name  = "ast2400-a0",
@@ -79,6 +92,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 +219,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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 08/30] aspeed: add a memory region for SRAM
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (6 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 07/30] aspeed: add support for the romulus-bmc board Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 09/30] aspeed: add the definitions for the AST2400 A1 SoC Cédric Le Goater
                   ` (22 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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>
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 82e27129a900..233a6b9bf59f 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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 09/30] aspeed: add the definitions for the AST2400 A1 SoC
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (7 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 08/30] aspeed: add a memory region for SRAM Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 10/30] aspeed: change SoC revision of the palmetto-bmc machine Cédric Le Goater
                   ` (21 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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>
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 233a6b9bf59f..d111d2e1feca 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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 10/30] aspeed: change SoC revision of the palmetto-bmc machine
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (8 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 09/30] aspeed: add the definitions for the AST2400 A1 SoC Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 11/30] aspeed/scu: fix SCU region size Cédric Le Goater
                   ` (20 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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>
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 3509011ae979..bc70b387890c 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -81,7 +81,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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 11/30] aspeed/scu: fix SCU region size
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (9 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 10/30] aspeed: change SoC revision of the palmetto-bmc machine Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 12/30] aspeed/smc: improve segment register support Cédric Le Goater
                   ` (19 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Andrew Jeffery <andrew@aj.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
 
 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
      [SYS_RST_CTRL]    = 0xFFCFFEDCU,
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 12/30] aspeed/smc: improve segment register support
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (10 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 11/30] aspeed/scu: fix SCU region size Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 13/30] aspeed/smc: set the number of flash modules for the FMC controller Cédric Le Goater
                   ` (18 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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(-)

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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 13/30] aspeed/smc: set the number of flash modules for the FMC controller
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (11 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 12/30] aspeed/smc: improve segment register support Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 14/30] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
                   ` (17 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

Add a new configuration field at the board level and propagate the
value using the "num-cs" property of the FMC controller model.

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

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index bc70b387890c..40c13838fb2d 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -36,6 +36,7 @@ typedef struct AspeedBoardConfig {
     uint32_t hw_strap1;
     const char *fmc_model;
     const char *spi_model;
+    uint32_t num_cs;
 } AspeedBoardConfig;
 
 enum {
@@ -85,18 +86,21 @@ static const AspeedBoardConfig aspeed_boards[] = {
         .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
         .fmc_model = "n25q256a",
         .spi_model = "mx25l25635e",
+        .num_cs    = 1,
     },
     [AST2500_EVB]  = {
         .soc_name  = "ast2500-a1",
         .hw_strap1 = AST2500_EVB_HW_STRAP1,
         .fmc_model = "n25q256a",
         .spi_model = "mx25l25635e",
+        .num_cs    = 1,
     },
     [ROMULUS_BMC]  = {
         .soc_name  = "ast2500-a1",
         .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
         .fmc_model = "n25q256a",
         .spi_model = "mx66l1g45g",
+        .num_cs    = 2,
     },
 };
 
@@ -143,6 +147,8 @@ static void aspeed_board_init(MachineState *machine,
                            &error_abort);
     object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
                             &error_abort);
+    object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
+                            &error_abort);
     object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
                              &error_abort);
 
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index d111d2e1feca..b3e7f07b615d 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -153,6 +153,8 @@ static void aspeed_soc_init(Object *obj)
     object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
     object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
     qdev_set_parent_bus(DEVICE(&s->fmc), sysbus_get_default());
+    object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
+                              &error_abort);
 
     for (i = 0; i < sc->info->spis_num; i++) {
         object_initialize(&s->spi[i], sizeof(s->spi[i]),
@@ -250,10 +252,8 @@ 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));
 
-    /* FMC */
-    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
-    object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
-    error_propagate(&err, local_err);
+    /* FMC, The number of CS is set at the board level */
+    object_property_set_bool(OBJECT(&s->fmc), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
         return;
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 14/30] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (12 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 13/30] aspeed/smc: set the number of flash modules for the FMC controller Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-12-14 17:09   ` Peter Maydell
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 15/30] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper Cédric Le Goater
                   ` (16 subsequent siblings)
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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: Joel Stanley <joel@jms.id.au>
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
---
 hw/ssi/aspeed_smc.c         | 36 ++++++++++++++++++++++++------------
 include/hw/ssi/aspeed_smc.h |  2 +-
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 78f5aed53247..66622f198a2f 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 AspeedSMCFlash *fl)
+{
+    return aspeed_smc_flash_mode(fl) == CTRL_USERMODE;
 }
 
-static inline bool aspeed_smc_is_usermode(const AspeedSMCState *s, int cs)
+static inline bool aspeed_smc_is_ce_stop_active(const AspeedSMCFlash *fl)
 {
-    return aspeed_smc_flash_mode(s, cs) == CTRL_USERMODE;
+    AspeedSMCState *s = fl->controller;
+
+    return s->regs[s->r_ctrl0 + fl->id] & CTRL_CE_STOP_ACTIVE;
 }
 
-static inline bool aspeed_smc_is_writable(const AspeedSMCState *s, int cs)
+static inline bool aspeed_smc_is_writable(const AspeedSMCFlash *fl)
 {
-    return s->regs[s->r_conf] & (1 << (s->conf_enable_w0 + cs));
+    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,9 +408,10 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
     },
 };
 
-static bool aspeed_smc_is_ce_stop_active(const AspeedSMCState *s, int cs)
+static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
 {
-    return s->regs[s->r_ctrl0 + cs] & CTRL_CE_STOP_ACTIVE;
+    AspeedSMCState *s = fl->controller;
+    qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
 }
 
 static void aspeed_smc_update_cs(const AspeedSMCState *s)
@@ -407,7 +419,7 @@ 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));
+        aspeed_smc_flash_update_cs(&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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 15/30] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (13 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 14/30] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 16/30] aspeed/smc: autostrap CE0/1 configuration Cédric Le Goater
                   ` (15 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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>
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
 hw/ssi/aspeed_smc.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 66622f198a2f..1c6c5089f265 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -414,15 +414,6 @@ static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
     qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
 }
 
-static void aspeed_smc_update_cs(const AspeedSMCState *s)
-{
-    int i;
-
-    for (i = 0; i < s->num_cs; ++i) {
-        aspeed_smc_flash_update_cs(&s->flashes[i]);
-    }
-}
-
 static void aspeed_smc_reset(DeviceState *d)
 {
     AspeedSMCState *s = ASPEED_SMC(d);
@@ -436,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 */
@@ -443,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)
@@ -494,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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 16/30] aspeed/smc: autostrap CE0/1 configuration
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (14 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 15/30] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
                   ` (14 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

HW autodetects the type and the 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>
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)
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (15 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 16/30] aspeed/smc: autostrap CE0/1 configuration Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-12-04 16:31   ` mar.krzeminski
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 18/30] aspeed/smc: extend tests for " Cédric Le Goater
                   ` (13 subsequent siblings)
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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));
     }
 }
 
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 18/30] aspeed/smc: extend tests for Command mode
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (16 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 19/30] aspeed/smc: unfold the AspeedSMCController array Cédric Le Goater
                   ` (12 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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.

So add a couple of tests doing direct reads and writes on the AHB bus.

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();
 
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 19/30] aspeed/smc: unfold the AspeedSMCController array
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (17 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 18/30] aspeed/smc: extend tests for " Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 20/30] aspeed/smc: add a 'sdram_base' property Cédric Le Goater
                   ` (11 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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: Joel Stanley <joel@jms.id.au>
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 {
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 20/30] aspeed/smc: add a 'sdram_base' property
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (18 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 19/30] aspeed/smc: unfold the AspeedSMCController array Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 21/30] aspeed/smc: add support for DMAs Cédric Le Goater
                   ` (10 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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>
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
---
 hw/arm/aspeed_soc.c         | 5 ++++-
 hw/ssi/aspeed_smc.c         | 1 +
 include/hw/ssi/aspeed_smc.h | 3 +++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index b3e7f07b615d..4fb777e6df6e 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -253,7 +253,10 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
                        qdev_get_gpio_in(DEVICE(&s->vic), 12));
 
     /* FMC, The number of CS is set at the board level */
-    object_property_set_bool(OBJECT(&s->fmc), true, "realized", &err);
+    object_property_set_int(OBJECT(&s->fmc), sc->info->sdram_base, "sdram-base",
+                            &err);
+    object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
+    error_propagate(&err, local_err);
     if (err) {
         error_propagate(errp, err);
         return;
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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 21/30] aspeed/smc: add support for DMAs
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (19 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 20/30] aspeed/smc: add a 'sdram_base' property Cédric Le Goater
@ 2016-11-29 15:43 ` Cédric Le Goater
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 22/30] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
                   ` (9 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:43 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 22/30] aspeed/smc: handle dummy bytes when doing fast reads
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (20 preceding siblings ...)
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 21/30] aspeed/smc: add support for DMAs Cédric Le Goater
@ 2016-11-29 15:44 ` Cédric Le Goater
  2016-12-04 16:46   ` mar.krzeminski
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 23/30] aspeed/smc: adjust the size of the register region Cédric Le Goater
                   ` (8 subsequent siblings)
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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         | 58 ++++++++++++++++++++++++++++++++++++++-------
 include/hw/ssi/aspeed_smc.h |  1 +
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 9596ea94a3bc..733fd8b09c06 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 /* 2 bits [7: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,50 @@ 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];
+    uint32_t dummy_high = (r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1;
+    uint32_t dummy_low = (r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3;
+
+    return ((dummy_high << 2) | dummy_low) * 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 +628,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 +670,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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 23/30] aspeed/smc: adjust the size of the register region
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (21 preceding siblings ...)
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 22/30] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
@ 2016-11-29 15:44 ` Cédric Le Goater
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
                   ` (7 subsequent siblings)
  30 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

The SPI controller of the AST2400 SoC 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         | 25 ++++++++++---------------
 include/hw/ssi/aspeed_smc.h |  1 +
 2 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 733fd8b09c06..2d1e604ca3e7 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -135,6 +135,9 @@
 #define R_SPI_MISC_CTRL   (0x10 / 4)
 #define R_SPI_TIMINGS     (0x14 / 4)
 
+#define ASPEED_SMC_R_SPI_MAX (0x20 / 4)
+#define ASPEED_SMC_R_SMC_MAX (0x20 / 4)
+
 #define ASPEED_SOC_SMC_FLASH_BASE   0x10000000
 #define ASPEED_SOC_FMC_FLASH_BASE   0x20000000
 #define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
@@ -209,6 +212,7 @@ static const AspeedSMCController controllers[] = {
         .flash_window_base = ASPEED_SOC_SMC_FLASH_BASE,
         .flash_window_size = 0x6000000,
         .has_dma           = false,
+        .nregs             = ASPEED_SMC_R_SMC_MAX,
     }, {
         .name              = "aspeed.smc.fmc",
         .r_conf            = R_CONF,
@@ -221,6 +225,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 +238,7 @@ static const AspeedSMCController controllers[] = {
         .flash_window_base = ASPEED_SOC_SPI_FLASH_BASE,
         .flash_window_size = 0x10000000,
         .has_dma           = false,
+        .nregs             = ASPEED_SMC_R_SPI_MAX,
     }, {
         .name              = "aspeed.smc.ast2500-fmc",
         .r_conf            = R_CONF,
@@ -245,6 +251,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 +264,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 +277,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,
     },
 };
 
@@ -713,13 +722,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 ||
@@ -943,13 +945,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) {
@@ -1031,7 +1026,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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (22 preceding siblings ...)
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 23/30] aspeed/smc: adjust the size of the register region Cédric Le Goater
@ 2016-11-29 15:44 ` Cédric Le Goater
  2016-12-04 17:00   ` mar.krzeminski
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices Cédric Le Goater
                   ` (6 subsequent siblings)
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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>
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 40c13838fb2d..a92c2f1c362b 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 */
@@ -104,6 +106,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)
 {
@@ -135,6 +159,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);
@@ -168,6 +193,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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (23 preceding siblings ...)
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
@ 2016-11-29 15:44 ` Cédric Le Goater
  2016-11-29 16:06   ` Cédric Le Goater
  2016-11-29 17:30   ` Cédric Le Goater
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 26/30] aspeed/smc: use flash model option Cédric Le Goater
                   ` (5 subsequent siblings)
  30 siblings, 2 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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>
Reviewed-by: Joel Stanley <joel@jms.id.au>
---
 blockdev.c                | 12 ++++++++++++
 include/sysemu/blockdev.h |  1 +
 qemu-options.hx           |  4 +++-
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/blockdev.c b/blockdev.c
index 245e1e1d177a..bcc99365b86c 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;
@@ -1076,6 +1081,12 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
     }
 
+    model = qemu_opt_get(legacy_opts, "model");
+    if (model && type != IF_MTD) {
+        error_report("model is not supported by this bus type");
+        goto fail;
+    }
+
     /* Actual block device init: Functionality shared with blockdev-add */
     blk = blockdev_init(filename, bs_opts, &local_err);
     bs_opts = NULL;
@@ -1102,6 +1113,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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 26/30] aspeed/smc: use flash model option
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (24 preceding siblings ...)
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices Cédric Le Goater
@ 2016-11-29 15:44 ` Cédric Le Goater
  2016-11-30 16:26   ` Cédric Le Goater
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 27/30] wdt: Add Aspeed watchdog device model Cédric Le Goater
                   ` (4 subsequent siblings)
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

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(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index a92c2f1c362b..f4232ce42cd0 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -138,6 +138,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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 27/30] wdt: Add Aspeed watchdog device model
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (25 preceding siblings ...)
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 26/30] aspeed/smc: use flash model option Cédric Le Goater
@ 2016-11-29 15:44 ` Cédric Le Goater
  2017-01-16 17:14   ` Cédric Le Goater
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 28/30] aspeed: add a watchdog controller Cédric Le Goater
                   ` (3 subsequent siblings)
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Joel Stanley, Cédric Le Goater

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

The Aspeed SoC includes a set of watchdog timers using 32-bit
decrement counters, which can be based either on the APB clock or
a 1 MHz clock.

The watchdog timer is designed to prevent system deadlock and, in
general, it should be restarted before timeout. When a timeout occurs,
different types of signals can be generated, ARM reset, SOC reset,
System reset, CPU Interrupt, external signal or boot from alternate
block. The current model only performs the system reset function as
this is used by U-Boot and Linux.

Signed-off-by: Joel Stanley <joel@jms.id.au>
[clg: - fixed compile breakage
      - fixed io region size
      - added watchdog_perform_action() on timer expiry
      - wrote a commit log ]
Signed-off-by: Cédric Le Goater <clg@kaod.org>
[andrew: - fixed scaling of the reload value ]
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
---
 hw/watchdog/Makefile.objs        |   1 +
 hw/watchdog/wdt_aspeed.c         | 212 +++++++++++++++++++++++++++++++++++++++
 include/hw/watchdog/wdt_aspeed.h |  41 ++++++++
 3 files changed, 254 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..cdba3983b7af
--- /dev/null
+++ b/hw/watchdog/wdt_aspeed.c
@@ -0,0 +1,212 @@
+/*
+ * 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      0x20
+
+#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;
+    }
+
+}
+
+#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:
+        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) {
+            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) + 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) + reload);
+        } 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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 28/30] aspeed: add a watchdog controller
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (26 preceding siblings ...)
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 27/30] wdt: Add Aspeed watchdog device model Cédric Le Goater
@ 2016-11-29 15:44 ` Cédric Le Goater
  2016-11-30  2:01   ` Andrew Jeffery
  2016-11-29 16:07 ` [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper Cédric Le Goater
                   ` (2 subsequent siblings)
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 15:44 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

This enables reboot of a guest from U-Boot and Linux.

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(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 4fb777e6df6e..6df76382f007 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 };
@@ -170,6 +171,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 void aspeed_soc_realize(DeviceState *dev, Error **errp)
@@ -289,6 +294,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] 64+ messages in thread

* Re: [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices Cédric Le Goater
@ 2016-11-29 16:06   ` Cédric Le Goater
  2016-11-29 17:30   ` Cédric Le Goater
  1 sibling, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 16:06 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Kevin Wolf, Qemu-block

On 11/29/2016 04:44 PM, Cédric Le Goater wrote:
> This could be used to define the flash model to use on some boards
> definitions.

As this patch was part of a larger set, I did not send the whole 
set to qemu-block@ list. Could you please take a look at the proposal ? 

Thanks,

C.


> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
>  blockdev.c                | 12 ++++++++++++
>  include/sysemu/blockdev.h |  1 +
>  qemu-options.hx           |  4 +++-
>  3 files changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/blockdev.c b/blockdev.c
> index 245e1e1d177a..bcc99365b86c 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;
> @@ -1076,6 +1081,12 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>          qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
>      }
>  
> +    model = qemu_opt_get(legacy_opts, "model");
> +    if (model && type != IF_MTD) {
> +        error_report("model is not supported by this bus type");
> +        goto fail;
> +    }
> +
>      /* Actual block device init: Functionality shared with blockdev-add */
>      blk = blockdev_init(filename, bs_opts, &local_err);
>      bs_opts = NULL;
> @@ -1102,6 +1113,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}
> 

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

* [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (27 preceding siblings ...)
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 28/30] aspeed: add a watchdog controller Cédric Le Goater
@ 2016-11-29 16:07 ` Cédric Le Goater
  2016-11-29 16:07   ` [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq Cédric Le Goater
  2016-11-29 19:16   ` [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper Cédric Le Goater
  2016-11-29 17:26 ` Cédric Le Goater
  2016-12-14 17:12 ` [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Peter Maydell
  30 siblings, 2 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 16:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

The clock frequency is defined in the HW STRAP1 register of the SCU
device.

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

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 95022d3607ad..351b8f79aca0 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/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
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq
  2016-11-29 16:07 ` [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper Cédric Le Goater
@ 2016-11-29 16:07   ` Cédric Le Goater
  2016-11-29 19:17     ` Cédric Le Goater
  2016-11-29 19:16   ` [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper Cédric Le Goater
  1 sibling, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 16:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

Add a link to the object model and a helper routine to retrieve the
value instead of using a constant value.

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/watchdog/wdt_aspeed.c         | 19 +++++++++++++++----
 include/hw/watchdog/wdt_aspeed.h |  2 ++
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 6df76382f007..712ae9d6c54d 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -175,6 +175,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 void aspeed_soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index cdba3983b7af..01266fb1b76b 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      0x20
 
@@ -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/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] 64+ messages in thread

* [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (28 preceding siblings ...)
  2016-11-29 16:07 ` [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper Cédric Le Goater
@ 2016-11-29 17:26 ` Cédric Le Goater
  2016-11-29 17:26   ` [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq Cédric Le Goater
  2016-12-14 17:12 ` [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Peter Maydell
  30 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 17:26 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

The clock frequency is defined in the HW STRAP1 register of the SCU
device.

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

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 95022d3607ad..351b8f79aca0 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/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
-- 
2.7.4

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

* [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq
  2016-11-29 17:26 ` Cédric Le Goater
@ 2016-11-29 17:26   ` Cédric Le Goater
  0 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 17:26 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Cédric Le Goater

Add a link to the object model and a helper routine to retrieve the
value instead of using a constant value.

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/watchdog/wdt_aspeed.c         | 19 +++++++++++++++----
 include/hw/watchdog/wdt_aspeed.h |  2 ++
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 6df76382f007..712ae9d6c54d 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -175,6 +175,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 void aspeed_soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index cdba3983b7af..01266fb1b76b 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      0x20
 
@@ -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/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] 64+ messages in thread

* Re: [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices Cédric Le Goater
  2016-11-29 16:06   ` Cédric Le Goater
@ 2016-11-29 17:30   ` Cédric Le Goater
  2016-11-29 18:08     ` Kevin Wolf
  1 sibling, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 17:30 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Kevin Wolf, Qemu-block

On 11/29/2016 04:44 PM, Cédric Le Goater wrote:
> This could be used to define the flash model to use on some boards
> definitions.

As this patch was part of a larger set, I did not send the whole 
set to qemu-block@ list. Could you please take a look at the proposal ? 

Thanks,

C.


> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
>  blockdev.c                | 12 ++++++++++++
>  include/sysemu/blockdev.h |  1 +
>  qemu-options.hx           |  4 +++-
>  3 files changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/blockdev.c b/blockdev.c
> index 245e1e1d177a..bcc99365b86c 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;
> @@ -1076,6 +1081,12 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>          qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
>      }
>  
> +    model = qemu_opt_get(legacy_opts, "model");
> +    if (model && type != IF_MTD) {
> +        error_report("model is not supported by this bus type");
> +        goto fail;
> +    }
> +
>      /* Actual block device init: Functionality shared with blockdev-add */
>      blk = blockdev_init(filename, bs_opts, &local_err);
>      bs_opts = NULL;
> @@ -1102,6 +1113,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}
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices
  2016-11-29 17:30   ` Cédric Le Goater
@ 2016-11-29 18:08     ` Kevin Wolf
  2016-11-30 15:09       ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: Kevin Wolf @ 2016-11-29 18:08 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: Peter Maydell, qemu-devel, qemu-arm, Andrew Jeffery,
	Marcin Krzeminski, Peter Crosthwaite, Qemu-block, armbru

Am 29.11.2016 um 18:30 hat Cédric Le Goater geschrieben:
> On 11/29/2016 04:44 PM, Cédric Le Goater wrote:
> > This could be used to define the flash model to use on some boards
> > definitions.
> 
> As this patch was part of a larger set, I did not send the whole 
> set to qemu-block@ list. Could you please take a look at the proposal ? 

This is a device level option rather than a block backend one. We messed
up -drive in its early days by including some device options, but we
don't generally want to add to this.

The correct way would be to add a qdev property for this and specify it
with -device or -global.

Kevin

> > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > Reviewed-by: Joel Stanley <joel@jms.id.au>
> > ---
> >  blockdev.c                | 12 ++++++++++++
> >  include/sysemu/blockdev.h |  1 +
> >  qemu-options.hx           |  4 +++-
> >  3 files changed, 16 insertions(+), 1 deletion(-)
> > 
> > diff --git a/blockdev.c b/blockdev.c
> > index 245e1e1d177a..bcc99365b86c 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;
> > @@ -1076,6 +1081,12 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
> >          qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
> >      }
> >  
> > +    model = qemu_opt_get(legacy_opts, "model");
> > +    if (model && type != IF_MTD) {
> > +        error_report("model is not supported by this bus type");
> > +        goto fail;
> > +    }
> > +
> >      /* Actual block device init: Functionality shared with blockdev-add */
> >      blk = blockdev_init(filename, bs_opts, &local_err);
> >      bs_opts = NULL;
> > @@ -1102,6 +1113,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}
> > 
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper
  2016-11-29 16:07 ` [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper Cédric Le Goater
  2016-11-29 16:07   ` [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq Cédric Le Goater
@ 2016-11-29 19:16   ` Cédric Le Goater
  1 sibling, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 19:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite

This is a duplicate resend. Our SMTP server had an issue and 
the message finaly went through ...

On 11/29/2016 05:07 PM, Cédric Le Goater wrote:
> The clock frequency is defined in the HW STRAP1 register of the SCU
> device.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
>  hw/misc/aspeed_scu.c         | 12 ++++++++++++
>  include/hw/misc/aspeed_scu.h |  1 +
>  2 files changed, 13 insertions(+)
> 
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index 95022d3607ad..351b8f79aca0 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/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
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq
  2016-11-29 16:07   ` [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq Cédric Le Goater
@ 2016-11-29 19:17     ` Cédric Le Goater
  0 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-29 19:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite

This is a duplicate also.

Sorry for the noise.

C. 

11/29/2016 05:07 PM, Cédric Le Goater wrote:
> Add a link to the object model and a helper routine to retrieve the
> value instead of using a constant value.
> 
> 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/watchdog/wdt_aspeed.c         | 19 +++++++++++++++----
>  include/hw/watchdog/wdt_aspeed.h |  2 ++
>  3 files changed, 19 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 6df76382f007..712ae9d6c54d 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -175,6 +175,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 void aspeed_soc_realize(DeviceState *dev, Error **errp)
> diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> index cdba3983b7af..01266fb1b76b 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      0x20
>  
> @@ -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/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 */
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 28/30] aspeed: add a watchdog controller
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 28/30] aspeed: add a watchdog controller Cédric Le Goater
@ 2016-11-30  2:01   ` Andrew Jeffery
  0 siblings, 0 replies; 64+ messages in thread
From: Andrew Jeffery @ 2016-11-30  2:01 UTC (permalink / raw)
  To: Cédric Le Goater, Peter Maydell
  Cc: qemu-devel, qemu-arm, Marcin Krzeminski, Peter Crosthwaite

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

On Tue, 2016-11-29 at 16:44 +0100, Cédric Le Goater wrote:
> This enables reboot of a guest from U-Boot and Linux.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Reviewed-by: Joel Stanley <joel@jms.id.au>

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 4fb777e6df6e..6df76382f007 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 };
> @@ -170,6 +171,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 void aspeed_soc_realize(DeviceState *dev, Error **errp)
> @@ -289,6 +294,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] 64+ messages in thread

* Re: [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices
  2016-11-29 18:08     ` Kevin Wolf
@ 2016-11-30 15:09       ` Cédric Le Goater
  2016-11-30 15:55         ` Kevin Wolf
  0 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-30 15:09 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: Peter Maydell, qemu-devel, qemu-arm, Andrew Jeffery,
	Marcin Krzeminski, Peter Crosthwaite, Qemu-block, armbru

On 11/29/2016 07:08 PM, Kevin Wolf wrote:
> Am 29.11.2016 um 18:30 hat Cédric Le Goater geschrieben:
>> On 11/29/2016 04:44 PM, Cédric Le Goater wrote:
>>> This could be used to define the flash model to use on some boards
>>> definitions.
>>
>> As this patch was part of a larger set, I did not send the whole 
>> set to qemu-block@ list. Could you please take a look at the proposal ? 
> 
> This is a device level option rather than a block backend one. We messed
> up -drive in its early days by including some device options, but we
> don't generally want to add to this.
> 
> The correct way would be to add a qdev property for this and specify it
> with -device or -global.

OK. I see. I should use something like this on the command line :

	-drive file=flash-romulus-test,format=raw,if=mtd,id=bmc \
	-device mx25l25635e,drive=bmc \
	-drive file=flash-romulus-test2,format=raw,if=mtd,id=bmc2 \
	-device mx25l25635e,drive=bmc2 \
	-drive file=romulus.pnor,format=raw,if=mtd,id=pnor \
	-device mx66l1g45g,drive=pnor 

and retrieve the attached m25p80 device from the drive with the 
routine blk_get_attached_dev(). That is changing a bit the way
the platform is initialized but it is cleaner as no default 
devices are automatically added.

Thanks,

C. 

> Kevin
> 
>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>> Reviewed-by: Joel Stanley <joel@jms.id.au>
>>> ---
>>>  blockdev.c                | 12 ++++++++++++
>>>  include/sysemu/blockdev.h |  1 +
>>>  qemu-options.hx           |  4 +++-
>>>  3 files changed, 16 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/blockdev.c b/blockdev.c
>>> index 245e1e1d177a..bcc99365b86c 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;
>>> @@ -1076,6 +1081,12 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>>>          qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
>>>      }
>>>  
>>> +    model = qemu_opt_get(legacy_opts, "model");
>>> +    if (model && type != IF_MTD) {
>>> +        error_report("model is not supported by this bus type");
>>> +        goto fail;
>>> +    }
>>> +
>>>      /* Actual block device init: Functionality shared with blockdev-add */
>>>      blk = blockdev_init(filename, bs_opts, &local_err);
>>>      bs_opts = NULL;
>>> @@ -1102,6 +1113,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}
>>>
>>

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

* Re: [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices
  2016-11-30 15:09       ` Cédric Le Goater
@ 2016-11-30 15:55         ` Kevin Wolf
  0 siblings, 0 replies; 64+ messages in thread
From: Kevin Wolf @ 2016-11-30 15:55 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: Peter Maydell, qemu-devel, qemu-arm, Andrew Jeffery,
	Marcin Krzeminski, Peter Crosthwaite, Qemu-block, armbru

Am 30.11.2016 um 16:09 hat Cédric Le Goater geschrieben:
> On 11/29/2016 07:08 PM, Kevin Wolf wrote:
> > Am 29.11.2016 um 18:30 hat Cédric Le Goater geschrieben:
> >> On 11/29/2016 04:44 PM, Cédric Le Goater wrote:
> >>> This could be used to define the flash model to use on some boards
> >>> definitions.
> >>
> >> As this patch was part of a larger set, I did not send the whole 
> >> set to qemu-block@ list. Could you please take a look at the proposal ? 
> > 
> > This is a device level option rather than a block backend one. We messed
> > up -drive in its early days by including some device options, but we
> > don't generally want to add to this.
> > 
> > The correct way would be to add a qdev property for this and specify it
> > with -device or -global.
> 
> OK. I see. I should use something like this on the command line :
> 
> 	-drive file=flash-romulus-test,format=raw,if=mtd,id=bmc \
> 	-device mx25l25635e,drive=bmc \
> 	-drive file=flash-romulus-test2,format=raw,if=mtd,id=bmc2 \
> 	-device mx25l25635e,drive=bmc2 \
> 	-drive file=romulus.pnor,format=raw,if=mtd,id=pnor \
> 	-device mx66l1g45g,drive=pnor 

I think you mean if=none instead of if=mtd everywhere, now that you're
using an explicit -device.

> and retrieve the attached m25p80 device from the drive with the 
> routine blk_get_attached_dev(). That is changing a bit the way
> the platform is initialized but it is cleaner as no default 
> devices are automatically added.

Right. For compatibility (and convenience) you can and probably should
still support if=mtd to create the device automatically, but then the
user just gets the defaults for the options that -drive doesn't allow to
specify.

Kevin

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

* Re: [Qemu-devel] [PATCH for-2.9 26/30] aspeed/smc: use flash model option
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 26/30] aspeed/smc: use flash model option Cédric Le Goater
@ 2016-11-30 16:26   ` Cédric Le Goater
  0 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-11-30 16:26 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite

On 11/29/2016 04:44 PM, Cédric Le Goater wrote:
> so that we can change the flash model from the command line.

After kevin input on this topic, we should drop patch 25 and 26.

Thanks,

C. 

> 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(+)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index a92c2f1c362b..f4232ce42cd0 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -138,6 +138,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
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
@ 2016-12-04 16:31   ` mar.krzeminski
  2016-12-05 14:07     ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: mar.krzeminski @ 2016-12-04 16:31 UTC (permalink / raw)
  To: Cédric Le Goater, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm

Hi Cedric,

Since there is no public datasheet user guide for SMC I would ask some 
question
regarding HW itself because I got impression that you are implementing 
in this
model a part functionality that is done by Bootrom.

W dniu 29.11.2016 o 16:43, Cédric Le Goater pisze:
> 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 */
Are you sure that the controller is aware af all above commands 
(especially WD/WE and RDS)?
> +
> +/* Used for Macronix and Winbond flashes. */
> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
> +
Same as above but I think 4byte address mode bit changes onlu nymber of 
bytes
that is sent after instruction.
>   /*
>    * 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) {
cmd == 0 => NOP command for some flash (eg. mx66l1g45g).
> +        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 ? */
I am not aware of any flash that needs that, this command should be send 
only once.
I also think that HW does not send this command (see above comment).
> +    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:
CTRL_FREADMODE should not sent dummy bytes?

Thanks,
Marcin
> +        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));
>       }
>   }
>   

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

* Re: [Qemu-devel] [PATCH for-2.9 22/30] aspeed/smc: handle dummy bytes when doing fast reads
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 22/30] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
@ 2016-12-04 16:46   ` mar.krzeminski
  2016-12-05 14:14     ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: mar.krzeminski @ 2016-12-04 16:46 UTC (permalink / raw)
  To: Cédric Le Goater, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm



W dniu 29.11.2016 o 16:44, Cédric Le Goater pisze:
> 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         | 58 ++++++++++++++++++++++++++++++++++++++-------
>   include/hw/ssi/aspeed_smc.h |  1 +
>   2 files changed, 51 insertions(+), 8 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 9596ea94a3bc..733fd8b09c06 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 /* 2 bits [7: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,50 @@ 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];
> +    uint32_t dummy_high = (r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1;
> +    uint32_t dummy_low = (r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3;
> +
> +    return ((dummy_high << 2) | dummy_low) * 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);
> +        }
> +    }
Generally this is wrong, controller should be not aware of any command 
in user mode.
Currently you are forced to do this by m25p80c dummy cycles implementation.
I had no time to improve this since it need to update in Xilinx models, 
but maybe it is good place to talk about the solution.
I was thinking to add to ssi function transferN, and use it in flash models.
Firs introduce new state for dummy cycles in m25p80 and then:
a) in case caller use ssi_transfer(transfer8 in flsh models) dummy count 
will be incremented by 8.
This should solve the problem when flash is connected to controller that 
is not aware about dummy cycles,
like this mode or clear SPI controller.
b) when caller use ssi_trasferN length (in bits) will be the number of 
dummy cycles.

What is your opinion?
> +    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 +628,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 +670,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;

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

* Re: [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
@ 2016-12-04 17:00   ` mar.krzeminski
  2016-12-05  9:36     ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: mar.krzeminski @ 2016-12-04 17:00 UTC (permalink / raw)
  To: Cédric Le Goater, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm

Hi Cedric,

it looks like good idea for now to handle boot from flash.
As I understand you are trying to omit bootrom code in Qemu model?
This could lead you to some hacks in device models (eg SMC).

W dniu 29.11.2016 o 16:44, Cédric Le Goater pisze:
> 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>
> 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 40c13838fb2d..a92c2f1c362b 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 */
> @@ -104,6 +106,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);
> +    }
I was not able to attach smaller file as m25p80 storage.
> +
> +    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)
>   {
> @@ -135,6 +159,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);
> @@ -168,6 +193,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);
Is it possible that fl->size will be bigger than segment size?
I think max_size here should be segment size in smc.

Thanks,
Marcin
> +    }
> +
>       aspeed_board_binfo.kernel_filename = machine->kernel_filename;
>       aspeed_board_binfo.initrd_filename = machine->initrd_filename;
>       aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;

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

* Re: [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM
  2016-12-04 17:00   ` mar.krzeminski
@ 2016-12-05  9:36     ` Cédric Le Goater
  2016-12-05  9:57       ` Marcin Krzemiński
  0 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-12-05  9:36 UTC (permalink / raw)
  To: mar.krzeminski, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm

Hello Marcin,

On 12/04/2016 06:00 PM, mar.krzeminski wrote:
> Hi Cedric,
> 
> it looks like good idea for now to handle boot from flash.
> As I understand you are trying to omit bootrom code in Qemu model?

I suppose you mean handling a romd memory region under the m25p80 
object ? 

> This could lead you to some hacks in device models (eg SMC).

I haven't had to, yet. 
 
> W dniu 29.11.2016 o 16:44, Cédric Le Goater pisze:
>> 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>
>> 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 40c13838fb2d..a92c2f1c362b 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 */
>> @@ -104,6 +106,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);
>> +    }
> I was not able to attach smaller file as m25p80 storage.

yes that's most probably because m25p80_realize() does : 

       if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
            error_setg(errp, "failed to read the initial flash content");
            return;
        }

my bad. May be, we could relax a bit the test and allow smaller block 
backends ? 


>> +
>> +    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)
>>  {
>> @@ -135,6 +159,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);
>> @@ -168,6 +193,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);
>
> Is it possible that fl->size will be bigger than segment size?
>
> I think max_size here should be segment size in smc.

I am not sure what you mean by "segment" ? 

fl->size holds the default mapping window size on the AHB bus of the 
flash chip CS0. The size can be changed by the guest using the segment 
address registers but for CS0 this should be "autoconfigured" by HW.

Here, we are just using the default from the specs but we could go a 
little further in the model and setup the mapping window size of CS0 
using the block backend size, and set up the segment registers accordingly.
There are some checks to be done. It might be a little complex.

Thanks,

C. 


> Thanks,
> Marcin
>> +    }
>> +
>>      aspeed_board_binfo.kernel_filename = machine->kernel_filename;
>>      aspeed_board_binfo.initrd_filename = machine->initrd_filename;
>>      aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM
  2016-12-05  9:36     ` Cédric Le Goater
@ 2016-12-05  9:57       ` Marcin Krzemiński
  2016-12-05 14:53         ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: Marcin Krzemiński @ 2016-12-05  9:57 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: Peter Maydell, Peter Crosthwaite, Andrew Jeffery,
	Marcin Krzeminski, qemu-devel@nongnu.org Developers, qemu-arm

2016-12-05 10:36 GMT+01:00 Cédric Le Goater <clg@kaod.org>:

> Hello Marcin,
>
> On 12/04/2016 06:00 PM, mar.krzeminski wrote:
> > Hi Cedric,
> >
> > it looks like good idea for now to handle boot from flash.
> > As I understand you are trying to omit bootrom code in Qemu model?
>
> I suppose you mean handling a romd memory region under the m25p80
> object ?
>
It could be that I mess up everything because my understanding how the real
HW
work and boot is wrong. Please correct my assumptions:
1. You are setting boot source to spi-nor (jumper, resistor whatever)
2. There is a small bootrom in SoC (not u-boot) that set eg. reset vector,
configure SMC
and start execude code from flash.
3. Memory mapped flash content is at address 0x1c000000.


>
> > This could lead you to some hacks in device models (eg SMC).
>
> I haven't had to, yet.
>
> > W dniu 29.11.2016 o 16:44, Cédric Le Goater pisze:
> >> 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>
> >> 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 40c13838fb2d..a92c2f1c362b 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 */
> >> @@ -104,6 +106,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);
> >> +    }
> > I was not able to attach smaller file as m25p80 storage.
>
> yes that's most probably because m25p80_realize() does :
>
>        if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
>             error_setg(errp, "failed to read the initial flash content");
>             return;
>         }
>
> my bad. May be, we could relax a bit the test and allow smaller block
> backends ?
>

I think not, if you have fs on flash (eg. UBI) and smaller image fs will
not mount,
or in worse case you can issue writes outside the file.

>
>
> >> +
> >> +    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)
> >>  {
> >> @@ -135,6 +159,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);
> >> @@ -168,6 +193,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);
> >
> > Is it possible that fl->size will be bigger than segment size?
> >
> > I think max_size here should be segment size in smc.
>
> I am not sure what you mean by "segment" ?
>
> fl->size holds the default mapping window size on the AHB bus of the
> flash chip CS0. The size can be changed by the guest using the segment
> address registers but for CS0 this should be "autoconfigured" by HW.
>

This is exactly what i meant, I was thinking that fl->size is the size of
the whole flash,
not the size of memory mapped part.

>
> Here, we are just using the default from the specs but we could go a
> little further in the model and setup the mapping window size of CS0
> using the block backend size, and set up the segment registers accordingly.
> There are some checks to be done. It might be a little complex.
>

I do not think there is a reason for doing that yet :)

Thanks,
Marcin

>
> Thanks,
>
> C.
>
>
> > Thanks,
> > Marcin
> >> +    }
> >> +
> >>      aspeed_board_binfo.kernel_filename = machine->kernel_filename;
> >>      aspeed_board_binfo.initrd_filename = machine->initrd_filename;
> >>      aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
> >
>
>

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

* Re: [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2016-12-04 16:31   ` mar.krzeminski
@ 2016-12-05 14:07     ` Cédric Le Goater
  2016-12-05 15:33       ` mar.krzeminski
  0 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-12-05 14:07 UTC (permalink / raw)
  To: mar.krzeminski, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm

On 12/04/2016 05:31 PM, mar.krzeminski wrote:
> Hi Cedric,
> 
> Since there is no public datasheet user guide for SMC I would ask some question
> regarding HW itself because I got impression that you are implementing in this
> model a part functionality that is done by Bootrom.
> 
> W dniu 29.11.2016 o 16:43, Cédric Le Goater pisze:
>> 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 */
> Are you sure that the controller is aware af all above commands (especially WD/WE and RDS)?

HW is aware of SPI_OP_READ which is the default command for the 
"normal" read mode. For other modes, fast and write, the command 
op is configured in the CEx Control Register. 

These ops are used in the model :

 * SPI_OP_READ_FAST, for dummies
 * SPI_OP_EN4B, might be useless if we expect software to send
   this command before using this mode.
 * SPI_OP_WREN, same comment.

The rest I should remove as it is unused.

>> +
>> +/* Used for Macronix and Winbond flashes. */
>> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
>> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
>> +
> Same as above but I think 4byte address mode bit changes onlu nymber of bytes
> that is sent after instruction.
>
>>  /*
>>   * 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) {
> cmd == 0 => NOP command for some flash (eg. mx66l1g45g).

So I should use another default value, OxFF ? 

>> +        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 ? */
> I am not aware of any flash that needs that, this  command should be send only once.

yes. That is what I think also.  

it also means that a preliminary 4BYTE command should be 
sent before using that mode. 

> I also think that HW does not send this command (see above comment).
>
>> +    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:
> CTRL_FREADMODE should not sent dummy bytes?

yes it should. this is in a following patch.

Thanks,

C. 

> 
> Thanks,
> Marcin
>> +        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));
>>      }
>>  }
>>  
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 22/30] aspeed/smc: handle dummy bytes when doing fast reads
  2016-12-04 16:46   ` mar.krzeminski
@ 2016-12-05 14:14     ` Cédric Le Goater
  2016-12-05 15:12       ` mar.krzeminski
  0 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-12-05 14:14 UTC (permalink / raw)
  To: mar.krzeminski, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm

On 12/04/2016 05:46 PM, mar.krzeminski wrote:
> 
> 
> W dniu 29.11.2016 o 16:44, Cédric Le Goater pisze:
>> 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         | 58 ++++++++++++++++++++++++++++++++++++++-------
>>  include/hw/ssi/aspeed_smc.h |  1 +
>>  2 files changed, 51 insertions(+), 8 deletions(-)
>>
>> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
>> index 9596ea94a3bc..733fd8b09c06 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 /* 2 bits [7: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,50 @@ 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];
>> +    uint32_t dummy_high = (r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1;
>> +    uint32_t dummy_low = (r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3;
>> +
>> +    return ((dummy_high << 2) | dummy_low) * 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);
>> +        }
>> +    }
> Generally this is wrong, controller should be not aware of any command in user mode.
> Currently you are forced to do this by m25p80c dummy cycles implementation.
> I had no time to improve this since it need to update in Xilinx models, but maybe it is good place to talk about the solution.
> I was thinking to add to ssi function transferN, and use it in flash models.
> Firs introduce new state for dummy cycles in m25p80 and then:

This new state would depend on the command op ? fastread would put
the object in a dummy_cycle state ? 

> a) in case caller use ssi_transfer(transfer8 in flsh models) dummy count will be incremented by 8.
> This should solve the problem when flash is connected to controller that is not aware about dummy cycles,
> like this mode or clear SPI controller.
> b) when caller use ssi_trasferN length (in bits) will be the number of dummy cycles.
> 
> What is your opinion?

when you have some time, please send a quick rfc patch for the API :) 
so that I can experiment on the aspeed controller.

Thanks,

C. 

>> +    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 +628,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 +670,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;
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM
  2016-12-05  9:57       ` Marcin Krzemiński
@ 2016-12-05 14:53         ` Cédric Le Goater
  2016-12-05 15:09           ` mar.krzeminski
  0 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2016-12-05 14:53 UTC (permalink / raw)
  To: Marcin Krzemiński
  Cc: Peter Maydell, Peter Crosthwaite, Andrew Jeffery,
	Marcin Krzeminski, qemu-devel@nongnu.org Developers, qemu-arm

On 12/05/2016 10:57 AM, Marcin Krzemiński wrote:
> 
> 2016-12-05 10:36 GMT+01:00 Cédric Le Goater <clg@kaod.org <mailto:clg@kaod.org>>:
> 
>     Hello Marcin,
> 
>     On 12/04/2016 06:00 PM, mar.krzeminski wrote:
>     > Hi Cedric,
>     >
>     > it looks like good idea for now to handle boot from flash.
>     > As I understand you are trying to omit bootrom code in Qemu model?
> 
>     I suppose you mean handling a romd memory region under the m25p80
>     object ?
> 
> It could be that I mess up everything because my understanding how the real HW
> work and boot is wrong. Please correct my assumptions:
> 1. You are setting boot source to spi-nor (jumper, resistor whatever)
> 2. There is a small bootrom in SoC (not u-boot) that set eg. reset vector, configure SMC
> and start execude code from flash.
> 3. Memory mapped flash content is at address 0x1c000000.

No. The memory flash content CS0 is mapped at 0x0 and starts 
with U-Boot directly, there is no preliminary loader.

U-Boot is not merged in mainline yet. We are "slowly" building a
tree for upstream : 
 
	https://github.com/openbmc/u-boot/
	https://github.com/legoater/u-boot/


>     > This could lead you to some hacks in device models (eg SMC).
> 
>     I haven't had to, yet.
> 
>     > W dniu 29.11.2016 o 16:44, Cédric Le Goater pisze:
>     >> 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 <mailto:clg@kaod.org>>
>     >> Reviewed-by: Joel Stanley <joel@jms.id.au <mailto:joel@jms.id.au>>
>     >> Reviewed-by: Andrew Jeffery <andrew@aj.id.au <mailto: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 40c13838fb2d..a92c2f1c362b 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 */
>     >> @@ -104,6 +106,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);
>     >> +    }
>     > I was not able to attach smaller file as m25p80 storage.
> 
>     yes that's most probably because m25p80_realize() does :
> 
>            if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
>                 error_setg(errp, "failed to read the initial flash content");
>                 return;
>             }
> 
>     my bad. May be, we could relax a bit the test and allow smaller block
>     backends ?
> 
>  
> I think not, if you have fs on flash (eg. UBI) and smaller image fs will not mount,
> or in worse case you can issue writes outside the file. 
> 
> 
> 
>     >> +
>     >> +    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)
>     >>  {
>     >> @@ -135,6 +159,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);
>     >> @@ -168,6 +193,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);
>     >
>     > Is it possible that fl->size will be bigger than segment size?
>     >
>     > I think max_size here should be segment size in smc.
> 
>     I am not sure what you mean by "segment" ?
> 
>     fl->size holds the default mapping window size on the AHB bus of the
>     flash chip CS0. The size can be changed by the guest using the segment
>     address registers but for CS0 this should be "autoconfigured" by HW.
> 
> 
> This is exactly what i meant, I was thinking that fl->size is the size of the whole flash,
> not the size of memory mapped part.
> 
> 
>     Here, we are just using the default from the specs but we could go a
>     little further in the model and setup the mapping window size of CS0
>     using the block backend size, and set up the segment registers accordingly.
>     There are some checks to be done. It might be a little complex.
> 
> 
> I do not think there is a reason for doing that yet :)

ok. I need to think about the API between the different objects, SCU and SMC,
to configure the hw strapping.

Thanks,

C. 

> Thanks,
> Marcin
> 
> 
>     Thanks,
> 
>     C.
> 
> 
>     > Thanks,
>     > Marcin
>     >> +    }
>     >> +
>     >>      aspeed_board_binfo.kernel_filename = machine->kernel_filename;
>     >>      aspeed_board_binfo.initrd_filename = machine->initrd_filename;
>     >>      aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
>     >
> 
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM
  2016-12-05 14:53         ` Cédric Le Goater
@ 2016-12-05 15:09           ` mar.krzeminski
  0 siblings, 0 replies; 64+ messages in thread
From: mar.krzeminski @ 2016-12-05 15:09 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: Peter Maydell, Peter Crosthwaite, Andrew Jeffery,
	Marcin Krzeminski, qemu-devel@nongnu.org Developers, qemu-arm



W dniu 05.12.2016 o 15:53, Cédric Le Goater pisze:
> On 12/05/2016 10:57 AM, Marcin Krzemiński wrote:
>> 2016-12-05 10:36 GMT+01:00 Cédric Le Goater <clg@kaod.org <mailto:clg@kaod.org>>:
>>
>>      Hello Marcin,
>>
>>      On 12/04/2016 06:00 PM, mar.krzeminski wrote:
>>      > Hi Cedric,
>>      >
>>      > it looks like good idea for now to handle boot from flash.
>>      > As I understand you are trying to omit bootrom code in Qemu model?
>>
>>      I suppose you mean handling a romd memory region under the m25p80
>>      object ?
>>
>> It could be that I mess up everything because my understanding how the real HW
>> work and boot is wrong. Please correct my assumptions:
>> 1. You are setting boot source to spi-nor (jumper, resistor whatever)
>> 2. There is a small bootrom in SoC (not u-boot) that set eg. reset vector, configure SMC
>> and start execude code from flash.
>> 3. Memory mapped flash content is at address 0x1c000000.
> No. The memory flash content CS0 is mapped at 0x0 and starts
> with U-Boot directly, there is no preliminary loader.
>
> U-Boot is not merged in mainline yet. We are "slowly" building a
> tree for upstream :
>   
> 	https://github.com/openbmc/u-boot/
> 	https://github.com/legoater/u-boot/
Thanks, I will look at those source in that case and the get back.

Thanks,
Marcin
>
>
>>      > This could lead you to some hacks in device models (eg SMC).
>>
>>      I haven't had to, yet.
>>
>>      > W dniu 29.11.2016 o 16:44, Cédric Le Goater pisze:
>>      >> 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 <mailto:clg@kaod.org>>
>>      >> Reviewed-by: Joel Stanley <joel@jms.id.au <mailto:joel@jms.id.au>>
>>      >> Reviewed-by: Andrew Jeffery <andrew@aj.id.au <mailto: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 40c13838fb2d..a92c2f1c362b 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 */
>>      >> @@ -104,6 +106,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);
>>      >> +    }
>>      > I was not able to attach smaller file as m25p80 storage.
>>
>>      yes that's most probably because m25p80_realize() does :
>>
>>             if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
>>                  error_setg(errp, "failed to read the initial flash content");
>>                  return;
>>              }
>>
>>      my bad. May be, we could relax a bit the test and allow smaller block
>>      backends ?
>>
>>   
>> I think not, if you have fs on flash (eg. UBI) and smaller image fs will not mount,
>> or in worse case you can issue writes outside the file.
>>
>>
>>
>>      >> +
>>      >> +    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)
>>      >>  {
>>      >> @@ -135,6 +159,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);
>>      >> @@ -168,6 +193,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);
>>      >
>>      > Is it possible that fl->size will be bigger than segment size?
>>      >
>>      > I think max_size here should be segment size in smc.
>>
>>      I am not sure what you mean by "segment" ?
>>
>>      fl->size holds the default mapping window size on the AHB bus of the
>>      flash chip CS0. The size can be changed by the guest using the segment
>>      address registers but for CS0 this should be "autoconfigured" by HW.
>>
>>
>> This is exactly what i meant, I was thinking that fl->size is the size of the whole flash,
>> not the size of memory mapped part.
>>
>>
>>      Here, we are just using the default from the specs but we could go a
>>      little further in the model and setup the mapping window size of CS0
>>      using the block backend size, and set up the segment registers accordingly.
>>      There are some checks to be done. It might be a little complex.
>>
>>
>> I do not think there is a reason for doing that yet :)
> ok. I need to think about the API between the different objects, SCU and SMC,
> to configure the hw strapping.
>
> Thanks,
>
> C.
>
>> Thanks,
>> Marcin
>>
>>
>>      Thanks,
>>
>>      C.
>>
>>
>>      > Thanks,
>>      > Marcin
>>      >> +    }
>>      >> +
>>      >>      aspeed_board_binfo.kernel_filename = machine->kernel_filename;
>>      >>      aspeed_board_binfo.initrd_filename = machine->initrd_filename;
>>      >>      aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
>>      >
>>
>>
>

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

* Re: [Qemu-devel] [PATCH for-2.9 22/30] aspeed/smc: handle dummy bytes when doing fast reads
  2016-12-05 14:14     ` Cédric Le Goater
@ 2016-12-05 15:12       ` mar.krzeminski
  0 siblings, 0 replies; 64+ messages in thread
From: mar.krzeminski @ 2016-12-05 15:12 UTC (permalink / raw)
  To: Cédric Le Goater, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm



W dniu 05.12.2016 o 15:14, Cédric Le Goater pisze:
> On 12/04/2016 05:46 PM, mar.krzeminski wrote:
>>
>> W dniu 29.11.2016 o 16:44, Cédric Le Goater pisze:
>>> 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         | 58 ++++++++++++++++++++++++++++++++++++++-------
>>>   include/hw/ssi/aspeed_smc.h |  1 +
>>>   2 files changed, 51 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
>>> index 9596ea94a3bc..733fd8b09c06 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 /* 2 bits [7: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,50 @@ 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];
>>> +    uint32_t dummy_high = (r_ctrl0 >> CTRL_DUMMY_HIGH_SHIFT) & 0x1;
>>> +    uint32_t dummy_low = (r_ctrl0 >> CTRL_DUMMY_LOW_SHIFT) & 0x3;
>>> +
>>> +    return ((dummy_high << 2) | dummy_low) * 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);
>>> +        }
>>> +    }
>> Generally this is wrong, controller should be not aware of any command in user mode.
>> Currently you are forced to do this by m25p80c dummy cycles implementation.
>> I had no time to improve this since it need to update in Xilinx models, but maybe it is good place to talk about the solution.
>> I was thinking to add to ssi function transferN, and use it in flash models.
>> Firs introduce new state for dummy cycles in m25p80 and then:
> This new state would depend on the command op ? fastread would put
> the object in a dummy_cycle state ?
Yes, only when needed (so it will be all fast reads in single/dual/quad 
modes).
>
>> a) in case caller use ssi_transfer(transfer8 in flsh models) dummy count will be incremented by 8.
>> This should solve the problem when flash is connected to controller that is not aware about dummy cycles,
>> like this mode or clear SPI controller.
>> b) when caller use ssi_trasferN length (in bits) will be the number of dummy cycles.
>>
>> What is your opinion?
> when you have some time, please send a quick rfc patch for the API :)
> so that I can experiment on the aspeed controller.
Will do, can not promise when, but target is 2.9 :)

Thanks,
Marcin
>
> Thanks,
>
> C.
>
>>> +    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 +628,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 +670,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;
>

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

* Re: [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2016-12-05 14:07     ` Cédric Le Goater
@ 2016-12-05 15:33       ` mar.krzeminski
  2017-01-02 15:56         ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: mar.krzeminski @ 2016-12-05 15:33 UTC (permalink / raw)
  To: Cédric Le Goater, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm



W dniu 05.12.2016 o 15:07, Cédric Le Goater pisze:
> On 12/04/2016 05:31 PM, mar.krzeminski wrote:
>> Hi Cedric,
>>
>> Since there is no public datasheet user guide for SMC I would ask some question
>> regarding HW itself because I got impression that you are implementing in this
>> model a part functionality that is done by Bootrom.
>>
>> W dniu 29.11.2016 o 16:43, Cédric Le Goater pisze:
>>> 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 */
>> Are you sure that the controller is aware af all above commands (especially WD/WE and RDS)?
> HW is aware of SPI_OP_READ which is the default command for the
> "normal" read mode. For other modes, fast and write, the command
> op is configured in the CEx Control Register.
>
> These ops are used in the model :
>
>   * SPI_OP_READ_FAST, for dummies
>   * SPI_OP_EN4B, might be useless if we expect software to send
>     this command before using this mode.
>   * SPI_OP_WREN, same comment.
>
> The rest I should remove as it is unused.
I think only SPI_OP_READ should stay in the model, rest goes to guest.
>
>>> +
>>> +/* Used for Macronix and Winbond flashes. */
>>> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
>>> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
>>> +
>> Same as above but I think 4byte address mode bit changes onlu nymber of bytes
>> that is sent after instruction.
>>
>>>   /*
>>>    * 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) {
>> cmd == 0 => NOP command for some flash (eg. mx66l1g45g).
> So I should use another default value, OxFF ?
I believe this check is not needed at all because m25p80c will tell if 
it has
unsupported instruction and HW should accept all register values, isn't it?
>
>>> +        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 ? */
>> I am not aware of any flash that needs that, this  command should be send only once.
> yes. That is what I think also.
>
> it also means that a preliminary 4BYTE command should be
> sent before using that mode.
Generally there are two ways to access more than 16MiB in flash:
- 4byte address mode: all commands change to accept 4byte address, not 
supported by all flash devices.
- 4byte opcodes: different opcode is used to signal 4-byte long address 
(eg. 0x3 three bytes, 0x13 four).
Also not all flash support that. If the HW does not use any of those, 
ones should be removed from this model.

>
>> I also think that HW does not send this command (see above comment).
>>
>>> +    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:
>> CTRL_FREADMODE should not sent dummy bytes?
> yes it should. this is in a following patch.
Yes, I noticed that after sending this email :)

Thanks,
Marcin
>
> Thanks,
>
> C.
>
>> Thanks,
>> Marcin
>>> +        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));
>>>       }
>>>   }
>>>   
>

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

* Re: [Qemu-devel] [PATCH for-2.9 01/30] target-arm: Add VBAR support to ARM1176 CPUs
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 01/30] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
@ 2016-12-14 15:43   ` Peter Maydell
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Maydell @ 2016-12-14 15:43 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: QEMU Developers, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite

On 29 November 2016 at 15:43, 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 can used for ARMv7 and ARM1176 CPUs.
>
> The VBAR feature is always set for ARMv7 because some legacy boards
> require it even if this is not architecturally correct. However, to
> support arm1176 CPUs without TrustZone, which doesn't exist in real
> hardware but which is used in old qemu boards, we need to disable the
> feature when 'has_el3' is not set.
>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  target-arm/cpu.c    |  6 ++++++
>  target-arm/cpu.h    |  1 +
>  target-arm/helper.c | 24 ++++++++++++++++++------
>  3 files changed, 25 insertions(+), 6 deletions(-)
>
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index 99f0dbebb9f6..1007e504248a 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -685,6 +685,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
>           */
>          cpu->id_pfr1 &= ~0xf0;
>          cpu->id_aa64pfr0 &= ~0xf000;
> +
> +        /* Also disable VBAR support for boards using a arm1176 CPU
> +         * without EL3.
> +         */
> +        unset_feature(env, ARM_FEATURE_VBAR);
>      }
>
>      if (!cpu->has_pmu || !kvm_enabled()) {
> @@ -911,6 +916,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..ab119e62ab0f 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 */
>  };
>
>  static inline int arm_feature(CPUARMState *env, int feature)
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index b5b65caadf8a..d417c8ba802f 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 },
> @@ -1412,6 +1406,16 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
>      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
>
>  static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -4506,6 +4510,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);
> @@ -4543,6 +4550,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
>          };
>          define_one_arm_cp_reg(cpu, &clidr);
>          define_arm_cp_regs(cpu, v7_cp_reginfo);
> +
> +        /* Always define VBAR even if it doesn't exist in non-EL3
> +         * configs. This is needed by some legacy boards.
> +         */
> +        define_arm_cp_regs(cpu, vbar_cp_reginfo);
>          define_debug_regs(cpu);
>      } else {
>          define_arm_cp_regs(cpu, not_v7_cp_reginfo);
> --
> 2.7.4

This all seems overcomplicated to me. The aim is to define VBAR for:
 * CPUs with TrustZone/EL3
 * ARMv7 CPUs (even if no EL3, for legacy reasons)
right?

We do that by changing arm_cpu_realizefn():
 * add set_feature(arm, ARM_FEATURE_VBAR) to the things we enable
   when the ARM_FEATURE_V7 bit is set (with a comment about why)
 * add
    if (arm_feature(env, ARM_FEATURE_EL3)) {
       set_feature(env, ARM_FEATURE_VBAR));
    }
   in the appropriate place
and then register_cp_regs_for_features() just does
   if (arm_feature(env, ARM_FEATURE_VBAR)) {
       define_arm_cp_regs(cpu, vbar_cp_reginfo);
   }

You don't need to explicitly set the VBAR feature in the 1176
initfn, or unset set feature bits, or register vbar_cp_reginfo
in two separate places.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH for-2.9 14/30] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines
  2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 14/30] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
@ 2016-12-14 17:09   ` Peter Maydell
  2016-12-15 13:38     ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: Peter Maydell @ 2016-12-14 17:09 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: QEMU Developers, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite

On 29 November 2016 at 15:43, 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>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> Reviewed-by: Andrew Jeffery <andrew@aj.id.au>

This patch breaks 'make check' because the palmetto-bmc
model now segfaults on startup:

gdb --args ./build/x86/arm-softmmu/qemu-system-arm -M palmetto-bmc
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
[...]
(gdb) r
Starting program:
/home/petmay01/linaro/qemu-from-laptop/qemu/build/x86/arm-softmmu/qemu-system-arm
-M palmetto-bmc
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fffd1270700 (LWP 30296)]
[New Thread 0x7fffcfb97700 (LWP 30297)]
[New Thread 0x7fffcf396700 (LWP 30298)]
[New Thread 0x7fffceb95700 (LWP 30299)]
[New Thread 0x7fffbf709700 (LWP 30300)]

Thread 1 "qemu-system-arm" received signal SIGSEGV, Segmentation fault.
0x0000555555b2fce8 in aspeed_smc_flash_update_cs (fl=0x0)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:413
413         AspeedSMCState *s = fl->controller;
(gdb) bt
#0  0x0000555555b2fce8 in aspeed_smc_flash_update_cs (fl=0x0)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:413
#1  0x0000555555b2fd6a in aspeed_smc_update_cs (s=0x7fffcc3924c0)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:422
#2  0x0000555555b2febc in aspeed_smc_reset (d=0x7fffcc3924c0)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:447
#3  0x0000555555b304a6 in aspeed_smc_realize (dev=0x7fffcc3924c0,
errp=0x7fffffffdcf0) at
/home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:556
#4  0x0000555555a19329 in device_set_realized (obj=0x7fffcc3924c0,
value=true, errp=0x7fffffffde98) at
/home/petmay01/linaro/qemu-from-laptop/qemu/hw/core/qdev.c:918
#5  0x0000555555c17e50 in property_set_bool (obj=0x7fffcc3924c0, v=
    0x555556ea9d90, name=0x555555d639e7 "realized",
opaque=0x5555569cafb0, errp=0x7fffffffde98) at
/home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1854
#6  0x0000555555c1635b in object_property_set (obj=0x7fffcc3924c0, v=
    0x555556ea9d90, name=0x555555d639e7 "realized", errp=0x7fffffffde98)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1088
#7  0x0000555555c19183 in object_property_set_qobject
(obj=0x7fffcc3924c0, value=0x555556ea9c80, name=0x555555d639e7
"realized", errp=0x7fffffffde98)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/qom-qobject.c:27
#8  0x0000555555c165fe in object_property_set_bool
(obj=0x7fffcc3924c0, value=true, name=0x555555d639e7 "realized",
errp=0x7fffffffde98)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1157
#9  0x00005555558da673 in aspeed_soc_realize (dev=0x7fffcc371010,
errp=0x7fffffffdf20) at
/home/petmay01/linaro/qemu-from-laptop/qemu/hw/arm/aspeed_soc.c:256
#10 0x0000555555a19329 in device_set_realized (obj=0x7fffcc371010,
value=true, errp=0x555556849518 <error_abort>)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/core/qdev.c:918
#11 0x0000555555c17e50 in property_set_bool (obj=0x7fffcc371010, v=
    0x5555569cc5b0, name=0x555555d63b5c "realized",
opaque=0x5555569be320, errp=0x555556849518 <error_abort>)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1854
#12 0x0000555555c1635b in object_property_set (obj=0x7fffcc371010, v=
    0x5555569cc5b0, name=0x555555d63b5c "realized",
errp=0x555556849518 <error_abort>) at
/home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1088
#13 0x0000555555c19183 in object_property_set_qobject
(obj=0x7fffcc371010, value=0x5555569cc3a0, name=0x555555d63b5c
"realized", errp=0x555556849518 <error_abort>)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/qom-qobject.c:27
#14 0x0000555555c165fe in object_property_set_bool
(obj=0x7fffcc371010, value=true, name=0x555555d63b5c "realized",
errp=0x555556849518 <error_abort>)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1157
#15 0x00005555558dadfe in aspeed_board_init (machine=0x55555693d8a0,
cfg=0x555556184fe0 <aspeed_boards>)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/arm/aspeed.c:152
#16 0x00005555558daf9c in palmetto_bmc_init (machine=0x55555693d8a0)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/arm/aspeed.c:182
#17 0x000055555596af75 in main (argc=3, argv=0x7fffffffe4c8,
envp=0x7fffffffe4e8)
    at /home/petmay01/linaro/qemu-from-laptop/qemu/vl.c:4548

Calling reset from realize is probably a bad idea (reset gets
called later anyway), and calling qemu_set_irq() from reset
isn't recommended either. These may or may not be the cause
of the crash though.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements
  2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
                   ` (29 preceding siblings ...)
  2016-11-29 17:26 ` Cédric Le Goater
@ 2016-12-14 17:12 ` Peter Maydell
  2016-12-14 17:51   ` Cédric Le Goater
  30 siblings, 1 reply; 64+ messages in thread
From: Peter Maydell @ 2016-12-14 17:12 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: QEMU Developers, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite

On 29 November 2016 at 15:43, Cédric Le Goater <clg@kaod.org> wrote:
> Here is a collection of fixes and improvements on existing models for
> the Aspeed SoCs

I have taken into target-arm.next for 2.9 patches 2-13:

>   m25p80: add support for the mx66l1g45g
>   aspeed: QOMify the CPU object and attach it to the SoC
>   aspeed: remove cannot_destroy_with_object_finalize_yet
>   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: set the number of flash modules for the FMC controller

which should at least reduce the size of this patchset for the
next round.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements
  2016-12-14 17:12 ` [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Peter Maydell
@ 2016-12-14 17:51   ` Cédric Le Goater
  0 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-12-14 17:51 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite

On 12/14/2016 06:12 PM, Peter Maydell wrote:
> On 29 November 2016 at 15:43, Cédric Le Goater <clg@kaod.org> wrote:
>> Here is a collection of fixes and improvements on existing models for
>> the Aspeed SoCs
> 
> I have taken into target-arm.next for 2.9 patches 2-13:
> 
>>   m25p80: add support for the mx66l1g45g
>>   aspeed: QOMify the CPU object and attach it to the SoC
>>   aspeed: remove cannot_destroy_with_object_finalize_yet
>>   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: set the number of flash modules for the FMC controller
> 
> which should at least reduce the size of this patchset for the
> next round.

Thanks a lot, I was going to ask you that :) 

I think I can simplify easily the vbar patch with the input
you just gave. I lost my way with the EL3 I guess.

The model option to the drive should be just dropped. However, 
using -drive / -device to define the flash modules on the command 
line introduces more changes as we need to take them into 
account at reset time and not at init time anymore. I need to
think about it.

Marcin had some concerns on the way the patchset handles the 
command mode modeling of the SMC controller. It can be improved 
surely but I won't do that right now. So that's a couple of 
patches for later.

I will take a look at the crash you spotted. Funny that I did
not see that.

The watchdog needs some review. It is nice to have as it gives
Linux reboot.

Alastair has an interesting RTC device we could plug on the 
palmetto machine. I have a little TMP421 device on the waiting
stack after.

Thanks,


C.

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

* Re: [Qemu-devel] [PATCH for-2.9 14/30] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines
  2016-12-14 17:09   ` Peter Maydell
@ 2016-12-15 13:38     ` Cédric Le Goater
  0 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2016-12-15 13:38 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite

On 12/14/2016 06:09 PM, Peter Maydell wrote:
> On 29 November 2016 at 15:43, 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>
>> Reviewed-by: Joel Stanley <joel@jms.id.au>
>> Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
> 
> This patch breaks 'make check' because the palmetto-bmc
> model now segfaults on startup:
> 
> gdb --args ./build/x86/arm-softmmu/qemu-system-arm -M palmetto-bmc
> GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
> [...]
> (gdb) r
> Starting program:
> /home/petmay01/linaro/qemu-from-laptop/qemu/build/x86/arm-softmmu/qemu-system-arm
> -M palmetto-bmc
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
> [New Thread 0x7fffd1270700 (LWP 30296)]
> [New Thread 0x7fffcfb97700 (LWP 30297)]
> [New Thread 0x7fffcf396700 (LWP 30298)]
> [New Thread 0x7fffceb95700 (LWP 30299)]
> [New Thread 0x7fffbf709700 (LWP 30300)]
> 
> Thread 1 "qemu-system-arm" received signal SIGSEGV, Segmentation fault.
> 0x0000555555b2fce8 in aspeed_smc_flash_update_cs (fl=0x0)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:413
> 413         AspeedSMCState *s = fl->controller;
> (gdb) bt
> #0  0x0000555555b2fce8 in aspeed_smc_flash_update_cs (fl=0x0)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:413
> #1  0x0000555555b2fd6a in aspeed_smc_update_cs (s=0x7fffcc3924c0)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:422
> #2  0x0000555555b2febc in aspeed_smc_reset (d=0x7fffcc3924c0)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:447
> #3  0x0000555555b304a6 in aspeed_smc_realize (dev=0x7fffcc3924c0,
> errp=0x7fffffffdcf0) at
> /home/petmay01/linaro/qemu-from-laptop/qemu/hw/ssi/aspeed_smc.c:556
> #4  0x0000555555a19329 in device_set_realized (obj=0x7fffcc3924c0,
> value=true, errp=0x7fffffffde98) at
> /home/petmay01/linaro/qemu-from-laptop/qemu/hw/core/qdev.c:918
> #5  0x0000555555c17e50 in property_set_bool (obj=0x7fffcc3924c0, v=
>     0x555556ea9d90, name=0x555555d639e7 "realized",
> opaque=0x5555569cafb0, errp=0x7fffffffde98) at
> /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1854
> #6  0x0000555555c1635b in object_property_set (obj=0x7fffcc3924c0, v=
>     0x555556ea9d90, name=0x555555d639e7 "realized", errp=0x7fffffffde98)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1088
> #7  0x0000555555c19183 in object_property_set_qobject
> (obj=0x7fffcc3924c0, value=0x555556ea9c80, name=0x555555d639e7
> "realized", errp=0x7fffffffde98)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/qom-qobject.c:27
> #8  0x0000555555c165fe in object_property_set_bool
> (obj=0x7fffcc3924c0, value=true, name=0x555555d639e7 "realized",
> errp=0x7fffffffde98)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1157
> #9  0x00005555558da673 in aspeed_soc_realize (dev=0x7fffcc371010,
> errp=0x7fffffffdf20) at
> /home/petmay01/linaro/qemu-from-laptop/qemu/hw/arm/aspeed_soc.c:256
> #10 0x0000555555a19329 in device_set_realized (obj=0x7fffcc371010,
> value=true, errp=0x555556849518 <error_abort>)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/core/qdev.c:918
> #11 0x0000555555c17e50 in property_set_bool (obj=0x7fffcc371010, v=
>     0x5555569cc5b0, name=0x555555d63b5c "realized",
> opaque=0x5555569be320, errp=0x555556849518 <error_abort>)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1854
> #12 0x0000555555c1635b in object_property_set (obj=0x7fffcc371010, v=
>     0x5555569cc5b0, name=0x555555d63b5c "realized",
> errp=0x555556849518 <error_abort>) at
> /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1088
> #13 0x0000555555c19183 in object_property_set_qobject
> (obj=0x7fffcc371010, value=0x5555569cc3a0, name=0x555555d63b5c
> "realized", errp=0x555556849518 <error_abort>)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/qom-qobject.c:27
> #14 0x0000555555c165fe in object_property_set_bool
> (obj=0x7fffcc371010, value=true, name=0x555555d63b5c "realized",
> errp=0x555556849518 <error_abort>)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/qom/object.c:1157
> #15 0x00005555558dadfe in aspeed_board_init (machine=0x55555693d8a0,
> cfg=0x555556184fe0 <aspeed_boards>)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/arm/aspeed.c:152
> #16 0x00005555558daf9c in palmetto_bmc_init (machine=0x55555693d8a0)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/hw/arm/aspeed.c:182
> #17 0x000055555596af75 in main (argc=3, argv=0x7fffffffe4c8,
> envp=0x7fffffffe4e8)
>     at /home/petmay01/linaro/qemu-from-laptop/qemu/vl.c:4548
> 
> Calling reset from realize is probably a bad idea (reset gets
> called later anyway), and calling qemu_set_irq() from reset
> isn't recommended either. These may or may not be the cause
> of the crash though.

It it a bad split with the following patch so I will merge them in 
the next version and try to cleanup up the qemu_set_irq().

Thanks,

C.

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

* Re: [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2016-12-05 15:33       ` mar.krzeminski
@ 2017-01-02 15:56         ` Cédric Le Goater
  2017-01-02 17:33           ` mar.krzeminski
  0 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2017-01-02 15:56 UTC (permalink / raw)
  To: mar.krzeminski, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, Marcin Krzeminski, qemu-devel,
	qemu-arm

Hello Marcin,

On 12/05/2016 04:33 PM, mar.krzeminski wrote:
> 
> 
> W dniu 05.12.2016 o 15:07, Cédric Le Goater pisze:
>> On 12/04/2016 05:31 PM, mar.krzeminski wrote:
>>> Hi Cedric,
>>>
>>> Since there is no public datasheet user guide for SMC I would ask some question
>>> regarding HW itself because I got impression that you are implementing in this
>>> model a part functionality that is done by Bootrom.
>>>
>>> W dniu 29.11.2016 o 16:43, Cédric Le Goater pisze:
>>>> 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 */
>>> Are you sure that the controller is aware af all above commands (especially WD/WE and RDS)?
>> HW is aware of SPI_OP_READ which is the default command for the 
>> "normal" read mode. For other modes, fast and write, the command 
>> op is configured in the CEx Control Register. 
>>
>> These ops are used in the model :
>>
>>  * SPI_OP_READ_FAST, for dummies
>>  * SPI_OP_EN4B, might be useless if we expect software to send
>>    this command before using this mode.
>>  * SPI_OP_WREN, same comment.
>>
>> The rest I should remove as it is unused.
> I think only SPI_OP_READ should stay in the model, rest goes to guest.

Well, we will need at least one 'EN4B' command to be sent for the qemu 
flash model to work. If the underlying m25p80 object does not know 
about the address width, the expected number of bytes will be wrong and
the result bogus. 

Same remark for the WREN, if the m25p80 object is not write enabled, 
modifying the flash content won't work.

Thanks,

C. 

>>
>>>> +
>>>> +/* Used for Macronix and Winbond flashes. */
>>>> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
>>>> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
>>>> +
>>> Same as above but I think 4byte address mode bit changes onlu nymber of bytes
>>> that is sent after instruction.
>>>
>>>>  /*
>>>>   * 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) {
>>> cmd == 0 => NOP command for some flash (eg. mx66l1g45g).
>> So I should use another default value, OxFF ? 
> I believe this check is not needed at all because m25p80c will tell if it has
> unsupported instruction and HW should accept all register values, isn't it?
>>
>>>> +        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 ? */
>>> I am not aware of any flash that needs that, this  command should be send only once.
>> yes. That is what I think also.  
>>
>> it also means that a preliminary 4BYTE command should be 
>> sent before using that mode.
> Generally there are two ways to access more than 16MiB in flash:
> - 4byte address mode: all commands change to accept 4byte address, not supported by all flash devices.
> - 4byte opcodes: different opcode is used to signal 4-byte long address (eg. 0x3 three bytes, 0x13 four).
> Also not all flash support that. If the HW does not use any of those, ones should be removed from this model.
> 
>>
>>> I also think that HW does not send this command (see above comment).
>>>
>>>> +    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:
>>> CTRL_FREADMODE should not sent dummy bytes?
>> yes it should. this is in a following patch.
> Yes, I noticed that after sending this email :)
> 
> Thanks,
> Marcin
>>
>> Thanks,
>>
>> C. 
>>
>>> Thanks,
>>> Marcin
>>>> +        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));
>>>>      }
>>>>  }
>>>>  
>>
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2017-01-02 15:56         ` Cédric Le Goater
@ 2017-01-02 17:33           ` mar.krzeminski
  2017-01-02 18:02             ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: mar.krzeminski @ 2017-01-02 17:33 UTC (permalink / raw)
  To: Cédric Le Goater, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, mar.krzeminski, qemu-devel, qemu-arm

Hello Cedric,

W dniu 02.01.2017 o 16:56, Cédric Le Goater pisze:
> Hello Marcin,
>
> On 12/05/2016 04:33 PM, mar.krzeminski wrote:
>>
>> W dniu 05.12.2016 o 15:07, Cédric Le Goater pisze:
>>> On 12/04/2016 05:31 PM, mar.krzeminski wrote:
>>>> Hi Cedric,
>>>>
>>>> Since there is no public datasheet user guide for SMC I would ask some question
>>>> regarding HW itself because I got impression that you are implementing in this
>>>> model a part functionality that is done by Bootrom.
>>>>
>>>> W dniu 29.11.2016 o 16:43, Cédric Le Goater pisze:
>>>>> 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 */
>>>> Are you sure that the controller is aware af all above commands (especially WD/WE and RDS)?
>>> HW is aware of SPI_OP_READ which is the default command for the
>>> "normal" read mode. For other modes, fast and write, the command
>>> op is configured in the CEx Control Register.
>>>
>>> These ops are used in the model :
>>>
>>>   * SPI_OP_READ_FAST, for dummies
>>>   * SPI_OP_EN4B, might be useless if we expect software to send
>>>     this command before using this mode.
>>>   * SPI_OP_WREN, same comment.
>>>
>>> The rest I should remove as it is unused.
>> I think only SPI_OP_READ should stay in the model, rest goes to guest.
> Well, we will need at least one 'EN4B' command to be sent for the qemu
> flash model to work. If the underlying m25p80 object does not know
> about the address width, the expected number of bytes will be wrong and
> the result bogus.
Hmm, most of the flash I know by default use 3byte address mode.
What flash are you connecting to model. Do you have same on HW?
>
> Same remark for the WREN, if the m25p80 object is not write enabled,
> modifying the flash content won't work.
Same as above.

Thanks,
Marcin
>
> Thanks,
>
> C.
>
>>>>> +
>>>>> +/* Used for Macronix and Winbond flashes. */
>>>>> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
>>>>> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
>>>>> +
>>>> Same as above but I think 4byte address mode bit changes onlu nymber of bytes
>>>> that is sent after instruction.
>>>>
>>>>>   /*
>>>>>    * 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) {
>>>> cmd == 0 => NOP command for some flash (eg. mx66l1g45g).
>>> So I should use another default value, OxFF ?
>> I believe this check is not needed at all because m25p80c will tell if it has
>> unsupported instruction and HW should accept all register values, isn't it?
>>>>> +        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 ? */
>>>> I am not aware of any flash that needs that, this  command should be send only once.
>>> yes. That is what I think also.
>>>
>>> it also means that a preliminary 4BYTE command should be
>>> sent before using that mode.
>> Generally there are two ways to access more than 16MiB in flash:
>> - 4byte address mode: all commands change to accept 4byte address, not supported by all flash devices.
>> - 4byte opcodes: different opcode is used to signal 4-byte long address (eg. 0x3 three bytes, 0x13 four).
>> Also not all flash support that. If the HW does not use any of those, ones should be removed from this model.
>>
>>>> I also think that HW does not send this command (see above comment).
>>>>
>>>>> +    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:
>>>> CTRL_FREADMODE should not sent dummy bytes?
>>> yes it should. this is in a following patch.
>> Yes, I noticed that after sending this email :)
>>
>> Thanks,
>> Marcin
>>> Thanks,
>>>
>>> C.
>>>
>>>> Thanks,
>>>> Marcin
>>>>> +        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));
>>>>>       }
>>>>>   }
>>>>>   
>

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

* Re: [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2017-01-02 17:33           ` mar.krzeminski
@ 2017-01-02 18:02             ` Cédric Le Goater
  2017-01-02 18:21               ` mar.krzeminski
  0 siblings, 1 reply; 64+ messages in thread
From: Cédric Le Goater @ 2017-01-02 18:02 UTC (permalink / raw)
  To: mar.krzeminski, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, qemu-devel, qemu-arm

On 01/02/2017 06:33 PM, mar.krzeminski wrote:
> Hello Cedric,
> 
> W dniu 02.01.2017 o 16:56, Cédric Le Goater pisze:
>> Hello Marcin,
>>
>> On 12/05/2016 04:33 PM, mar.krzeminski wrote:
>>>
>>> W dniu 05.12.2016 o 15:07, Cédric Le Goater pisze:
>>>> On 12/04/2016 05:31 PM, mar.krzeminski wrote:
>>>>> Hi Cedric,
>>>>>
>>>>> Since there is no public datasheet user guide for SMC I would ask some question
>>>>> regarding HW itself because I got impression that you are implementing in this
>>>>> model a part functionality that is done by Bootrom.
>>>>>
>>>>> W dniu 29.11.2016 o 16:43, Cédric Le Goater pisze:
>>>>>> 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 */
>>>>> Are you sure that the controller is aware af all above commands (especially WD/WE and RDS)?
>>>> HW is aware of SPI_OP_READ which is the default command for the
>>>> "normal" read mode. For other modes, fast and write, the command
>>>> op is configured in the CEx Control Register.
>>>>
>>>> These ops are used in the model :
>>>>
>>>>   * SPI_OP_READ_FAST, for dummies
>>>>   * SPI_OP_EN4B, might be useless if we expect software to send
>>>>     this command before using this mode.
>>>>   * SPI_OP_WREN, same comment.
>>>>
>>>> The rest I should remove as it is unused.
>>> I think only SPI_OP_READ should stay in the model, rest goes to guest.
>> Well, we will need at least one 'EN4B' command to be sent for the qemu
>> flash model to work. If the underlying m25p80 object does not know
>> about the address width, the expected number of bytes will be wrong and
>> the result bogus.
> Hmm, most of the flash I know by default use 3byte address mode.
> What flash are you connecting to model.

chips like n25q256a, mx25l25635e, w25q256. all are > 32MB.

> Do you have same on HW?

No but it is difficult to know what the controller is doing 
in that mode without spying on the bus. 

Anyhow, after some experiments, I think you are right and 
I should  get rid of these command OP in the next version. 

What about the dummy cycles ? the linux driver now has 
support for it and it would be nice to get some support
in qemu also.

Thanks,

C.  

>>
>> Same remark for the WREN, if the m25p80 object is not write enabled,
>> modifying the flash content won't work.
> Same as above.
> 
> Thanks,
> Marcin
>>
>> Thanks,
>>
>> C.
>>
>>>>>> +
>>>>>> +/* Used for Macronix and Winbond flashes. */
>>>>>> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
>>>>>> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
>>>>>> +
>>>>> Same as above but I think 4byte address mode bit changes onlu nymber of bytes
>>>>> that is sent after instruction.
>>>>>
>>>>>>   /*
>>>>>>    * 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) {
>>>>> cmd == 0 => NOP command for some flash (eg. mx66l1g45g).
>>>> So I should use another default value, OxFF ?
>>> I believe this check is not needed at all because m25p80c will tell if it has
>>> unsupported instruction and HW should accept all register values, isn't it?
>>>>>> +        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 ? */
>>>>> I am not aware of any flash that needs that, this  command should be send only once.
>>>> yes. That is what I think also.
>>>>
>>>> it also means that a preliminary 4BYTE command should be
>>>> sent before using that mode.
>>> Generally there are two ways to access more than 16MiB in flash:
>>> - 4byte address mode: all commands change to accept 4byte address, not supported by all flash devices.
>>> - 4byte opcodes: different opcode is used to signal 4-byte long address (eg. 0x3 three bytes, 0x13 four).
>>> Also not all flash support that. If the HW does not use any of those, ones should be removed from this model.
>>>
>>>>> I also think that HW does not send this command (see above comment).
>>>>>
>>>>>> +    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:
>>>>> CTRL_FREADMODE should not sent dummy bytes?
>>>> yes it should. this is in a following patch.
>>> Yes, I noticed that after sending this email :)
>>>
>>> Thanks,
>>> Marcin
>>>> Thanks,
>>>>
>>>> C.
>>>>
>>>>> Thanks,
>>>>> Marcin
>>>>>> +        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));
>>>>>>       }
>>>>>>   }
>>>>>>   
>>
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2017-01-02 18:02             ` Cédric Le Goater
@ 2017-01-02 18:21               ` mar.krzeminski
  2017-01-03 10:50                 ` Cédric Le Goater
  0 siblings, 1 reply; 64+ messages in thread
From: mar.krzeminski @ 2017-01-02 18:21 UTC (permalink / raw)
  To: Cédric Le Goater, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, qemu-devel, qemu-arm



W dniu 02.01.2017 o 19:02, Cédric Le Goater pisze:
> On 01/02/2017 06:33 PM, mar.krzeminski wrote:
>> Hello Cedric,
>>
>> W dniu 02.01.2017 o 16:56, Cédric Le Goater pisze:
>>> Hello Marcin,
>>>
>>> On 12/05/2016 04:33 PM, mar.krzeminski wrote:
>>>> W dniu 05.12.2016 o 15:07, Cédric Le Goater pisze:
>>>>> On 12/04/2016 05:31 PM, mar.krzeminski wrote:
>>>>>> Hi Cedric,
>>>>>>
>>>>>> Since there is no public datasheet user guide for SMC I would ask some question
>>>>>> regarding HW itself because I got impression that you are implementing in this
>>>>>> model a part functionality that is done by Bootrom.
>>>>>>
>>>>>> W dniu 29.11.2016 o 16:43, Cédric Le Goater pisze:
>>>>>>> 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 */
>>>>>> Are you sure that the controller is aware af all above commands (especially WD/WE and RDS)?
>>>>> HW is aware of SPI_OP_READ which is the default command for the
>>>>> "normal" read mode. For other modes, fast and write, the command
>>>>> op is configured in the CEx Control Register.
>>>>>
>>>>> These ops are used in the model :
>>>>>
>>>>>    * SPI_OP_READ_FAST, for dummies
>>>>>    * SPI_OP_EN4B, might be useless if we expect software to send
>>>>>      this command before using this mode.
>>>>>    * SPI_OP_WREN, same comment.
>>>>>
>>>>> The rest I should remove as it is unused.
>>>> I think only SPI_OP_READ should stay in the model, rest goes to guest.
>>> Well, we will need at least one 'EN4B' command to be sent for the qemu
>>> flash model to work. If the underlying m25p80 object does not know
>>> about the address width, the expected number of bytes will be wrong and
>>> the result bogus.
>> Hmm, most of the flash I know by default use 3byte address mode.
>> What flash are you connecting to model.
> chips like n25q256a, mx25l25635e, w25q256. all are > 32MB.
>
>> Do you have same on HW?
> No but it is difficult to know what the controller is doing
> in that mode without spying on the bus.

Maybe aspeed support can help?
Or some clue in the doc.
More generally have you tested this feature in real HW?
> Anyhow, after some experiments, I think you are right and
> I should  get rid of these command OP in the next version.
MHO it is possible that controller send WREN command,
but I would be really surprised if it send EN4B.
>
> What about the dummy cycles ? the linux driver now has
> support for it and it would be nice to get some support
> in qemu also.
Target is still 2.9, but I am quite loaded now. From the other hand,
in current Qemu you can have it working with easy update in the
feature. Just send byte every dummy clock.

Thanks,
Marcin
>
> Thanks,
>
> C.
>
>>> Same remark for the WREN, if the m25p80 object is not write enabled,
>>> modifying the flash content won't work.
>> Same as above.
>>
>> Thanks,
>> Marcin
>>> Thanks,
>>>
>>> C.
>>>
>>>>>>> +
>>>>>>> +/* Used for Macronix and Winbond flashes. */
>>>>>>> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
>>>>>>> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
>>>>>>> +
>>>>>> Same as above but I think 4byte address mode bit changes onlu nymber of bytes
>>>>>> that is sent after instruction.
>>>>>>
>>>>>>>    /*
>>>>>>>     * 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) {
>>>>>> cmd == 0 => NOP command for some flash (eg. mx66l1g45g).
>>>>> So I should use another default value, OxFF ?
>>>> I believe this check is not needed at all because m25p80c will tell if it has
>>>> unsupported instruction and HW should accept all register values, isn't it?
>>>>>>> +        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 ? */
>>>>>> I am not aware of any flash that needs that, this  command should be send only once.
>>>>> yes. That is what I think also.
>>>>>
>>>>> it also means that a preliminary 4BYTE command should be
>>>>> sent before using that mode.
>>>> Generally there are two ways to access more than 16MiB in flash:
>>>> - 4byte address mode: all commands change to accept 4byte address, not supported by all flash devices.
>>>> - 4byte opcodes: different opcode is used to signal 4-byte long address (eg. 0x3 three bytes, 0x13 four).
>>>> Also not all flash support that. If the HW does not use any of those, ones should be removed from this model.
>>>>
>>>>>> I also think that HW does not send this command (see above comment).
>>>>>>
>>>>>>> +    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:
>>>>>> CTRL_FREADMODE should not sent dummy bytes?
>>>>> yes it should. this is in a following patch.
>>>> Yes, I noticed that after sending this email :)
>>>>
>>>> Thanks,
>>>> Marcin
>>>>> Thanks,
>>>>>
>>>>> C.
>>>>>
>>>>>> Thanks,
>>>>>> Marcin
>>>>>>> +        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));
>>>>>>>        }
>>>>>>>    }
>>>>>>>    
>

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

* Re: [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode
  2017-01-02 18:21               ` mar.krzeminski
@ 2017-01-03 10:50                 ` Cédric Le Goater
  0 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2017-01-03 10:50 UTC (permalink / raw)
  To: mar.krzeminski, Peter Maydell
  Cc: Peter Crosthwaite, Andrew Jeffery, qemu-devel, qemu-arm

On 01/02/2017 07:21 PM, mar.krzeminski wrote:
> 
> 
> W dniu 02.01.2017 o 19:02, Cédric Le Goater pisze:
>> On 01/02/2017 06:33 PM, mar.krzeminski wrote:
>>> Hello Cedric,
>>>
>>> W dniu 02.01.2017 o 16:56, Cédric Le Goater pisze:
>>>> Hello Marcin,
>>>>
>>>> On 12/05/2016 04:33 PM, mar.krzeminski wrote:
>>>>> W dniu 05.12.2016 o 15:07, Cédric Le Goater pisze:
>>>>>> On 12/04/2016 05:31 PM, mar.krzeminski wrote:
>>>>>>> Hi Cedric,
>>>>>>>
>>>>>>> Since there is no public datasheet user guide for SMC I would ask some question
>>>>>>> regarding HW itself because I got impression that you are implementing in this
>>>>>>> model a part functionality that is done by Bootrom.
>>>>>>>
>>>>>>> W dniu 29.11.2016 o 16:43, Cédric Le Goater pisze:
>>>>>>>> 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 */
>>>>>>> Are you sure that the controller is aware af all above commands (especially WD/WE and RDS)?
>>>>>> HW is aware of SPI_OP_READ which is the default command for the
>>>>>> "normal" read mode. For other modes, fast and write, the command
>>>>>> op is configured in the CEx Control Register.
>>>>>>
>>>>>> These ops are used in the model :
>>>>>>
>>>>>>    * SPI_OP_READ_FAST, for dummies
>>>>>>    * SPI_OP_EN4B, might be useless if we expect software to send
>>>>>>      this command before using this mode.
>>>>>>    * SPI_OP_WREN, same comment.
>>>>>>
>>>>>> The rest I should remove as it is unused.
>>>>> I think only SPI_OP_READ should stay in the model, rest goes to guest.
>>>> Well, we will need at least one 'EN4B' command to be sent for the qemu
>>>> flash model to work. If the underlying m25p80 object does not know
>>>> about the address width, the expected number of bytes will be wrong and
>>>> the result bogus.
>>> Hmm, most of the flash I know by default use 3byte address mode.
>>> What flash are you connecting to model.
>> chips like n25q256a, mx25l25635e, w25q256. all are > 32MB.
>>
>>> Do you have same on HW?
>> No but it is difficult to know what the controller is doing
>> in that mode without spying on the bus.
> 
> Maybe aspeed support can help?
> Or some clue in the doc.

I will try to ping the aspeed engineers to have some hints on how 
this is implemented.

> More generally have you tested this feature in real HW?

yes. we use it to read the flash contents. This is the pflash tool
in the open-power firmware. It is under github.

>> Anyhow, after some experiments, I think you are right and
>> I should  get rid of these command OP in the next version.
> MHO it is possible that controller send WREN command,
> but I would be really surprised if it send EN4B.

yes. we should be fine.

>>
>> What about the dummy cycles ? the linux driver now has
>> support for it and it would be nice to get some support
>> in qemu also.
> Target is still 2.9, but I am quite loaded now. From the other hand,
> in current Qemu you can have it working with easy update in the
> feature. Just send byte every dummy clock.

yes. I was just asking. No hurries on our side.

Thanks,

C. 


> Thanks,
> Marcin
>>
>> Thanks,
>>
>> C.
>>
>>>> Same remark for the WREN, if the m25p80 object is not write enabled,
>>>> modifying the flash content won't work.
>>> Same as above.
>>>
>>> Thanks,
>>> Marcin
>>>> Thanks,
>>>>
>>>> C.
>>>>
>>>>>>>> +
>>>>>>>> +/* Used for Macronix and Winbond flashes. */
>>>>>>>> +#define SPI_OP_EN4B       0xb7    /* Enter 4-byte mode */
>>>>>>>> +#define SPI_OP_EX4B       0xe9    /* Exit 4-byte mode */
>>>>>>>> +
>>>>>>> Same as above but I think 4byte address mode bit changes onlu nymber of bytes
>>>>>>> that is sent after instruction.
>>>>>>>
>>>>>>>>    /*
>>>>>>>>     * 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) {
>>>>>>> cmd == 0 => NOP command for some flash (eg. mx66l1g45g).
>>>>>> So I should use another default value, OxFF ?
>>>>> I believe this check is not needed at all because m25p80c will tell if it has
>>>>> unsupported instruction and HW should accept all register values, isn't it?
>>>>>>>> +        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 ? */
>>>>>>> I am not aware of any flash that needs that, this  command should be send only once.
>>>>>> yes. That is what I think also.
>>>>>>
>>>>>> it also means that a preliminary 4BYTE command should be
>>>>>> sent before using that mode.
>>>>> Generally there are two ways to access more than 16MiB in flash:
>>>>> - 4byte address mode: all commands change to accept 4byte address, not supported by all flash devices.
>>>>> - 4byte opcodes: different opcode is used to signal 4-byte long address (eg. 0x3 three bytes, 0x13 four).
>>>>> Also not all flash support that. If the HW does not use any of those, ones should be removed from this model.
>>>>>
>>>>>>> I also think that HW does not send this command (see above comment).
>>>>>>>
>>>>>>>> +    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:
>>>>>>> CTRL_FREADMODE should not sent dummy bytes?
>>>>>> yes it should. this is in a following patch.
>>>>> Yes, I noticed that after sending this email :)
>>>>>
>>>>> Thanks,
>>>>> Marcin
>>>>>> Thanks,
>>>>>>
>>>>>> C.
>>>>>>
>>>>>>> Thanks,
>>>>>>> Marcin
>>>>>>>> +        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));
>>>>>>>>        }
>>>>>>>>    }
>>>>>>>>    
>>
> 

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

* Re: [Qemu-devel] [PATCH for-2.9 27/30] wdt: Add Aspeed watchdog device model
  2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 27/30] wdt: Add Aspeed watchdog device model Cédric Le Goater
@ 2017-01-16 17:14   ` Cédric Le Goater
  0 siblings, 0 replies; 64+ messages in thread
From: Cédric Le Goater @ 2017-01-16 17:14 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, qemu-arm, Andrew Jeffery, Marcin Krzeminski,
	Peter Crosthwaite, Joel Stanley

On 11/29/2016 04:44 PM, Cédric Le Goater wrote:
> From: Joel Stanley <joel@jms.id.au>
> 
> The Aspeed SoC includes a set of watchdog timers using 32-bit
> decrement counters, which can be based either on the APB clock or
> a 1 MHz clock.
> 
> The watchdog timer is designed to prevent system deadlock and, in
> general, it should be restarted before timeout. When a timeout occurs,
> different types of signals can be generated, ARM reset, SOC reset,
> System reset, CPU Interrupt, external signal or boot from alternate
> block. The current model only performs the system reset function as
> this is used by U-Boot and Linux.
> 

Shall I resend the 3/4 patches related to the watchdog in a separate
patchset ? 

Thanks,

C. 

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

end of thread, other threads:[~2017-01-16 17:14 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-29 15:43 [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 01/30] target-arm: Add VBAR support to ARM1176 CPUs Cédric Le Goater
2016-12-14 15:43   ` Peter Maydell
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 02/30] m25p80: add support for the mx66l1g45g Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 03/30] aspeed: QOMify the CPU object and attach it to the SoC Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 04/30] aspeed: remove cannot_destroy_with_object_finalize_yet Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 05/30] aspeed: attach the second SPI controller object to the SoC Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 06/30] aspeed: extend the board configuration with flash models Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 07/30] aspeed: add support for the romulus-bmc board Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 08/30] aspeed: add a memory region for SRAM Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 09/30] aspeed: add the definitions for the AST2400 A1 SoC Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 10/30] aspeed: change SoC revision of the palmetto-bmc machine Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 11/30] aspeed/scu: fix SCU region size Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 12/30] aspeed/smc: improve segment register support Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 13/30] aspeed/smc: set the number of flash modules for the FMC controller Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 14/30] aspeed/smc: rework the prototype of the AspeedSMCFlash helper routines Cédric Le Goater
2016-12-14 17:09   ` Peter Maydell
2016-12-15 13:38     ` Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 15/30] aspeed/smc: introduce a aspeed_smc_flash_update_cs() helper Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 16/30] aspeed/smc: autostrap CE0/1 configuration Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 17/30] aspeed/smc: handle SPI flash Command mode Cédric Le Goater
2016-12-04 16:31   ` mar.krzeminski
2016-12-05 14:07     ` Cédric Le Goater
2016-12-05 15:33       ` mar.krzeminski
2017-01-02 15:56         ` Cédric Le Goater
2017-01-02 17:33           ` mar.krzeminski
2017-01-02 18:02             ` Cédric Le Goater
2017-01-02 18:21               ` mar.krzeminski
2017-01-03 10:50                 ` Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 18/30] aspeed/smc: extend tests for " Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 19/30] aspeed/smc: unfold the AspeedSMCController array Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 20/30] aspeed/smc: add a 'sdram_base' property Cédric Le Goater
2016-11-29 15:43 ` [Qemu-devel] [PATCH for-2.9 21/30] aspeed/smc: add support for DMAs Cédric Le Goater
2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 22/30] aspeed/smc: handle dummy bytes when doing fast reads Cédric Le Goater
2016-12-04 16:46   ` mar.krzeminski
2016-12-05 14:14     ` Cédric Le Goater
2016-12-05 15:12       ` mar.krzeminski
2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 23/30] aspeed/smc: adjust the size of the register region Cédric Le Goater
2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 24/30] aspeed: use first SPI flash as a boot ROM Cédric Le Goater
2016-12-04 17:00   ` mar.krzeminski
2016-12-05  9:36     ` Cédric Le Goater
2016-12-05  9:57       ` Marcin Krzemiński
2016-12-05 14:53         ` Cédric Le Goater
2016-12-05 15:09           ` mar.krzeminski
2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 25/30] block: add a model option for MTD devices Cédric Le Goater
2016-11-29 16:06   ` Cédric Le Goater
2016-11-29 17:30   ` Cédric Le Goater
2016-11-29 18:08     ` Kevin Wolf
2016-11-30 15:09       ` Cédric Le Goater
2016-11-30 15:55         ` Kevin Wolf
2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 26/30] aspeed/smc: use flash model option Cédric Le Goater
2016-11-30 16:26   ` Cédric Le Goater
2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 27/30] wdt: Add Aspeed watchdog device model Cédric Le Goater
2017-01-16 17:14   ` Cédric Le Goater
2016-11-29 15:44 ` [Qemu-devel] [PATCH for-2.9 28/30] aspeed: add a watchdog controller Cédric Le Goater
2016-11-30  2:01   ` Andrew Jeffery
2016-11-29 16:07 ` [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper Cédric Le Goater
2016-11-29 16:07   ` [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq Cédric Le Goater
2016-11-29 19:17     ` Cédric Le Goater
2016-11-29 19:16   ` [Qemu-devel] [PATCH for-2.9 29/30] aspeed/scu: add a aspeed_scu_get_clk() helper Cédric Le Goater
2016-11-29 17:26 ` Cédric Le Goater
2016-11-29 17:26   ` [Qemu-devel] [PATCH for-2.9 30/30] wdt: aspeed: use scu to get clock freq Cédric Le Goater
2016-12-14 17:12 ` [Qemu-devel] [PATCH for-2.9 00/30] Aspeed SoC fixes and model improvements Peter Maydell
2016-12-14 17:51   ` Cédric Le Goater

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.