Re: [PATCH 2/5] hw/arm: ast2600: Wire up the eMMC controller

2020-01-12 Thread Andrew Jeffery



On Fri, 10 Jan 2020, at 22:26, Cédric Le Goater wrote:
> >> +
> >> +    sysbus_init_child_obj(obj, "emmc", OBJECT(>emmc), sizeof(s->emmc),
> >> +  TYPE_ASPEED_SDHCI);
> >> +
> >> +    object_property_set_int(OBJECT(>emmc), 1, "num-slots", 
> >> _abort);
> >> +
> >> +    sysbus_init_child_obj(obj, "emmc[*]", OBJECT(>emmc.slots[0]),
> > 
> > Single block, so use "emmc" instead.
> 
> Andrew, how should we call the objects in the slots ? "sdhci" ? 

I think that's the right way to go, but maybe we need to rethink the naming at 
the
controller level.

Andrew



Re: [PATCH v3 0/4] Expose GT CNTFRQ as a CPU property to support AST2600

2019-12-17 Thread Andrew Jeffery



On Wed, 18 Dec 2019, at 01:55, Peter Maydell wrote:
> On Fri, 13 Dec 2019 at 05:48, Andrew Jeffery  wrote:
> >
> > Hello,
> >
> > This is a v3 of the belated follow-up from a few of my earlier attempts to 
> > fix
> > up the ARM generic timer for correct behaviour on the ASPEED AST2600 SoC. 
> > The
> > AST2600 clocks the generic timer at the rate of HPLL, which is configured to
> > 1125MHz.  This is significantly quicker than the currently hard-coded 
> > generic
> > timer rate of 62.5MHz and so we see "sticky" behaviour in the guest.
> >
> > v2 can be found here:
> >
> > https://patchwork.ozlabs.org/cover/1203474/
> >
> > Changes since v2:
> >
> > * Address some minor review comments from Philippe and add tags
> >
> > Changes since v1:
> >
> > * Fix a user mode build failure from partial renaming of 
> > gt_cntfrq_period_ns()
> > * Add tags from Cedric and Richard
> >
> > Please review.
> >
> > Andrew
> >
> > Andrew Jeffery (4):
> >   target/arm: Remove redundant scaling of nexttick
> >   target/arm: Abstract the generic timer frequency
> >   target/arm: Prepare generic timer for per-platform CNTFRQ
> >   ast2600: Configure CNTFRQ at 1125MHz
> 
> 
> 
> 
> Applied to target-arm.next, thanks.

Thanks for your feedback throughout.

Andrew



Re: [PATCH v2 0/2] hw/arm: ast2600: Wire up eMMC controller

2019-12-12 Thread Andrew Jeffery



On Fri, 13 Dec 2019, at 18:03, Cédric Le Goater wrote:
> On 13/12/2019 05:28, Andrew Jeffery wrote:
> > Hello,
> > 
> > The AST2600 has an additional SDHCI intended for use as an eMMC boot source.
> > These two patches rework the existing ASPEED SDHCI model to accommodate the
> > single-slot nature of the eMMC controller and wire it into the AST2600 SoC.
> > 
> > v2 contains some minor refactorings in response to issues pointed out by
> > Cedric.
>  
> 
> I think these patches are based on mainline. I fixed them locally on 
> my aspeed 5.0 branch and I plan to send them along with other aspeed 
> changes in the 5.0 timeframe.  

Yeah, they're based on Peter's tree. I'll base future patches on yours.

Andrew



[PATCH v3 4/4] ast2600: Configure CNTFRQ at 1125MHz

2019-12-12 Thread Andrew Jeffery
This matches the configuration set by u-boot on the AST2600.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Richard Henderson 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/arm/aspeed_ast2600.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 931887ac681f..5aecc3b3caec 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -259,6 +259,9 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 object_property_set_int(OBJECT(>cpu[i]), aspeed_calc_affinity(i),
 "mp-affinity", _abort);
 
+object_property_set_int(OBJECT(>cpu[i]), 112500, "cntfrq",
+_abort);
+
 /*
  * TODO: the secondary CPUs are started and a boot helper
  * is needed when using -kernel
-- 
git-series 0.9.1



[PATCH v3 3/4] target/arm: Prepare generic timer for per-platform CNTFRQ

2019-12-12 Thread Andrew Jeffery
The ASPEED AST2600 clocks the generic timer at the rate of HPLL. On
recent firmwares this is at 1125MHz, which is considerably quicker than
the assumed 62.5MHz of the current generic timer implementation. The
delta between the value as read from CNTFRQ and the true rate of the
underlying QEMUTimer leads to sticky behaviour in AST2600 guests.

Add a feature-gated property exposing CNTFRQ for ARM CPUs providing the
generic timer. This allows platforms to configure CNTFRQ (and the
associated QEMUTimer) to the appropriate frequency prior to starting the
guest.

As the platform can now determine the rate of CNTFRQ we're exposed to
limitations of QEMUTimer that didn't previously materialise: In the
course of emulation we need to arbitrarily and accurately convert
between guest ticks and time, but we're constrained by QEMUTimer's use
of an integer scaling factor. The effect is QEMUTimer cannot exactly
capture the period of frequencies that do not cleanly divide
NANOSECONDS_PER_SECOND for scaling ticks to time. As such, provide an
equally inaccurate scaling factor for scaling time to ticks so at least
a self-consistent inverse relationship holds.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Richard Henderson 
---
v3:
* Relocate comment as a consequence of uninlining gt_cntfrq_period_ns() in 2/4.
Philippe - I haven't moved it to the previous patch based on my reasoning on
the list. I'm not sure whether you're satisfied by that, so I haven't added
your Reviewed-by tag.

 target/arm/cpu.c| 61 ++
 target/arm/helper.c |  9 ++-
 2 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index cd0dbe005d9f..7b21eb544eae 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -974,10 +974,12 @@ static void arm_cpu_initfn(Object *obj)
 if (tcg_enabled()) {
 cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
 }
-
-cpu->gt_cntfrq_hz = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
 }
 
+static Property arm_cpu_gt_cntfrq_property =
+DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz,
+   NANOSECONDS_PER_SECOND / GTIMER_SCALE);
+
 static Property arm_cpu_reset_cbar_property =
 DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
 
@@ -1059,6 +1061,24 @@ static void arm_set_init_svtor(Object *obj, Visitor *v, 
const char *name,
 
 unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
 {
+/*
+ * The exact approach to calculating guest ticks is:
+ *
+ * muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), cpu->gt_cntfrq_hz,
+ *  NANOSECONDS_PER_SECOND);
+ *
+ * We don't do that. Rather we intentionally use integer division
+ * truncation below and in the caller for the conversion of host monotonic
+ * time to guest ticks to provide the exact inverse for the semantics of
+ * the QEMUTimer scale factor. QEMUTimer's scale facter is an integer, so
+ * it loses precision when representing frequencies where
+ * `(NANOSECONDS_PER_SECOND % cpu->gt_cntfrq) > 0` holds. Failing to
+ * provide an exact inverse leads to scheduling timers with negative
+ * periods, which in turn leads to sticky behaviour in the guest.
+ *
+ * Finally, CNTFRQ is effectively capped at 1GHz to ensure our scale factor
+ * cannot become zero.
+ */
 return NANOSECONDS_PER_SECOND > cpu->gt_cntfrq_hz ?
   NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
 }
@@ -1180,6 +1200,11 @@ void arm_cpu_post_init(Object *obj)
 
 qdev_property_add_static(DEVICE(obj), _cpu_cfgend_property,
  _abort);
+
+if (arm_feature(>env, ARM_FEATURE_GENERIC_TIMER)) {
+qdev_property_add_static(DEVICE(cpu), _cpu_gt_cntfrq_property,
+ _abort);
+}
 }
 
 static void arm_cpu_finalizefn(Object *obj)
@@ -1259,14 +1284,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
-cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_ptimer_cb, cpu);
-cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_vtimer_cb, cpu);
-cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_htimer_cb, cpu);
-cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_stimer_cb, cpu);
+
+{
+uint64_t scale;
+
+if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
+if (!cpu->gt_cntfrq_hz) {
+error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
+   cpu->gt_cntfrq_hz);
+return;
+}
+scale = gt_cntfrq_period_ns

[PATCH v3 1/4] target/arm: Remove redundant scaling of nexttick

2019-12-12 Thread Andrew Jeffery
The corner-case codepath was adjusting nexttick such that overflow
wouldn't occur when timer_mod() scaled the value back up. Remove a use
of GTIMER_SCALE and avoid unnecessary operations by calling
timer_mod_ns() directly.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Richard Henderson 
Reviewed-by: Cédric Le Goater 
---
 target/arm/helper.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index a089fb5a6909..65c4441a3896 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2446,9 +2446,10 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * timer expires we will reset the timer for any remaining period.
  */
 if (nexttick > INT64_MAX / GTIMER_SCALE) {
-nexttick = INT64_MAX / GTIMER_SCALE;
+timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
+} else {
+timer_mod(cpu->gt_timer[timeridx], nexttick);
 }
-timer_mod(cpu->gt_timer[timeridx], nexttick);
 trace_arm_gt_recalc(timeridx, irqstate, nexttick);
 } else {
 /* Timer disabled: ISTATUS and timer output always clear */
-- 
git-series 0.9.1



[PATCH v3 0/4] Expose GT CNTFRQ as a CPU property to support AST2600

2019-12-12 Thread Andrew Jeffery
Hello,

This is a v3 of the belated follow-up from a few of my earlier attempts to fix
up the ARM generic timer for correct behaviour on the ASPEED AST2600 SoC. The
AST2600 clocks the generic timer at the rate of HPLL, which is configured to
1125MHz.  This is significantly quicker than the currently hard-coded generic
timer rate of 62.5MHz and so we see "sticky" behaviour in the guest.

v2 can be found here:

https://patchwork.ozlabs.org/cover/1203474/

Changes since v2:

* Address some minor review comments from Philippe and add tags

Changes since v1:

* Fix a user mode build failure from partial renaming of gt_cntfrq_period_ns()
* Add tags from Cedric and Richard

Please review.

Andrew

Andrew Jeffery (4):
  target/arm: Remove redundant scaling of nexttick
  target/arm: Abstract the generic timer frequency
  target/arm: Prepare generic timer for per-platform CNTFRQ
  ast2600: Configure CNTFRQ at 1125MHz

 hw/arm/aspeed_ast2600.c |  3 ++-
 target/arm/cpu.c| 65 --
 target/arm/cpu.h|  5 +++-
 target/arm/helper.c | 24 
 4 files changed, 83 insertions(+), 14 deletions(-)

base-commit: 04c9c81b8fa2ee33f59a26265700fae6fc646062
-- 
git-series 0.9.1



[PATCH v3 2/4] target/arm: Abstract the generic timer frequency

2019-12-12 Thread Andrew Jeffery
Prepare for SoCs such as the ASPEED AST2600 whose firmware configures
CNTFRQ to values significantly larger than the static 62.5MHz value
currently derived from GTIMER_SCALE. As the OS potentially derives its
timer periods from the CNTFRQ value the lack of support for running
QEMUTimers at the appropriate rate leads to sticky behaviour in the
guest.

Substitute the GTIMER_SCALE constant with use of a helper to derive the
period from gt_cntfrq_hz stored in struct ARMCPU. Initially set
gt_cntfrq_hz to the frequency associated with GTIMER_SCALE so current
behaviour is maintained.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---

v3:
* Uninline gt_cntfrq_period_ns()
* Rename gt_cntfrq to gt_cntfrq_hz

 target/arm/cpu.c|  8 
 target/arm/cpu.h|  5 +
 target/arm/helper.c | 10 +++---
 3 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 7a4ac9339bf9..cd0dbe005d9f 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -974,6 +974,8 @@ static void arm_cpu_initfn(Object *obj)
 if (tcg_enabled()) {
 cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
 }
+
+cpu->gt_cntfrq_hz = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
 }
 
 static Property arm_cpu_reset_cbar_property =
@@ -1055,6 +1057,12 @@ static void arm_set_init_svtor(Object *obj, Visitor *v, 
const char *name,
 visit_type_uint32(v, name, >init_svtor, errp);
 }
 
+unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
+{
+return NANOSECONDS_PER_SECOND > cpu->gt_cntfrq_hz ?
+  NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
+}
+
 void arm_cpu_post_init(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 83a809d4bac4..ff17ec0df545 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -932,8 +932,13 @@ struct ARMCPU {
  */
 DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
 DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
+
+/* Generic timer counter frequency, in Hz */
+uint64_t gt_cntfrq_hz;
 };
 
+unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
+
 void arm_cpu_post_init(Object *obj);
 
 uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 65c4441a3896..2622a9a8d02f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2409,7 +2409,9 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
 
 static uint64_t gt_get_countervalue(CPUARMState *env)
 {
-return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+ARMCPU *cpu = env_archcpu(env);
+
+return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
 }
 
 static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
@@ -2445,7 +2447,7 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * set the timer for as far in the future as possible. When the
  * timer expires we will reset the timer for any remaining period.
  */
-if (nexttick > INT64_MAX / GTIMER_SCALE) {
+if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {
 timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
 } else {
 timer_mod(cpu->gt_timer[timeridx], nexttick);
@@ -2874,11 +2876,13 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 
 static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
+ARMCPU *cpu = env_archcpu(env);
+
 /* Currently we have no support for QEMUTimer in linux-user so we
  * can't call gt_get_countervalue(env), instead we directly
  * call the lower level functions.
  */
-return cpu_get_clock() / GTIMER_SCALE;
+return cpu_get_clock() / gt_cntfrq_period_ns(cpu);
 }
 
 static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
-- 
git-series 0.9.1



[PATCH v2 0/2] hw/arm: ast2600: Wire up eMMC controller

2019-12-12 Thread Andrew Jeffery
Hello,

The AST2600 has an additional SDHCI intended for use as an eMMC boot source.
These two patches rework the existing ASPEED SDHCI model to accommodate the
single-slot nature of the eMMC controller and wire it into the AST2600 SoC.

v2 contains some minor refactorings in response to issues pointed out by
Cedric.

v1 can be found here:

https://patchwork.ozlabs.org/cover/1206845/

Please review!

Andrew

Andrew Jeffery (2):
  hw/sd: Configure number of slots exposed by the ASPEED SDHCI model
  hw/arm: ast2600: Wire up the eMMC controller

 hw/arm/aspeed.c  | 27 +--
 hw/arm/aspeed_ast2600.c  | 23 +++
 hw/arm/aspeed_soc.c  |  2 ++
 hw/sd/aspeed_sdhci.c | 11 +--
 include/hw/arm/aspeed_soc.h  |  2 ++
 include/hw/sd/aspeed_sdhci.h |  1 +
 6 files changed, 54 insertions(+), 12 deletions(-)

base-commit: 6a4ef4e5d1084ce41fafa7d470a644b0fd3d9317
-- 
git-series 0.9.1



[PATCH v2 2/2] hw/arm: ast2600: Wire up the eMMC controller

2019-12-12 Thread Andrew Jeffery
Initialise another SDHCI model instance for the AST2600's eMMC
controller and use the SDHCI's num_slots value introduced previously to
determine whether we should create an SD card instance for the new slot.

Signed-off-by: Andrew Jeffery 
---

v2:
* Extract instantiation of SD cards to helper function

 hw/arm/aspeed.c | 25 -
 hw/arm/aspeed_ast2600.c | 21 +
 include/hw/arm/aspeed_soc.h |  2 ++
 3 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 862549b1f3a9..87baac0ea46c 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -167,6 +167,18 @@ static void aspeed_board_init_flashes(AspeedSMCState *s, 
const char *flashtype,
 }
 }
 
+static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
+{
+BlockBackend *blk;
+DeviceState *card;
+
+blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
+   TYPE_SD_CARD);
+qdev_prop_set_drive(card, "drive", blk, _fatal);
+object_property_set_bool(OBJECT(card), true, "realized", _fatal);
+}
+
 static void aspeed_board_init(MachineState *machine,
   const AspeedBoardConfig *cfg)
 {
@@ -260,16 +272,11 @@ static void aspeed_board_init(MachineState *machine,
 }
 
 for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
-SDHCIState *sdhci = >soc.sdhci.slots[i];
-DriveInfo *dinfo = drive_get_next(IF_SD);
-BlockBackend *blk;
-DeviceState *card;
+sdhci_attach_drive(>soc.sdhci.slots[i], drive_get_next(IF_SD));
+}
 
-blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
-card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
-   TYPE_SD_CARD);
-qdev_prop_set_drive(card, "drive", blk, _fatal);
-object_property_set_bool(OBJECT(card), true, "realized", _fatal);
+if (bmc->soc.emmc.num_slots) {
+sdhci_attach_drive(>soc.emmc.slots[0], drive_get_next(IF_SD));
 }
 
 arm_load_kernel(ARM_CPU(first_cpu), machine, _board_binfo);
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 931ee5aae183..723c8196c8a5 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -46,6 +46,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
 [ASPEED_ADC]   = 0x1E6E9000,
 [ASPEED_VIDEO] = 0x1E70,
 [ASPEED_SDHCI] = 0x1E74,
+[ASPEED_EMMC]  = 0x1E75,
 [ASPEED_GPIO]  = 0x1E78,
 [ASPEED_GPIO_1_8V] = 0x1E780800,
 [ASPEED_RTC]   = 0x1E781000,
@@ -64,6 +65,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
 
 #define ASPEED_SOC_AST2600_MAX_IRQ 128
 
+/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
 static const int aspeed_soc_ast2600_irqmap[] = {
 [ASPEED_UART1] = 47,
 [ASPEED_UART2] = 48,
@@ -77,6 +79,7 @@ static const int aspeed_soc_ast2600_irqmap[] = {
 [ASPEED_ADC]   = 78,
 [ASPEED_XDMA]  = 6,
 [ASPEED_SDHCI] = 43,
+[ASPEED_EMMC]  = 15,
 [ASPEED_GPIO]  = 40,
 [ASPEED_GPIO_1_8V] = 11,
 [ASPEED_RTC]   = 13,
@@ -215,6 +218,14 @@ static void aspeed_soc_ast2600_init(Object *obj)
 sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(>sdhci.slots[i]),
   sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI);
 }
+
+sysbus_init_child_obj(obj, "emmc", OBJECT(>emmc), sizeof(s->emmc),
+  TYPE_ASPEED_SDHCI);
+
+object_property_set_int(OBJECT(>emmc), 1, "num-slots", _abort);
+
+sysbus_init_child_obj(obj, "emmc[*]", OBJECT(>emmc.slots[0]),
+sizeof(s->emmc.slots[0]), TYPE_SYSBUS_SDHCI);
 }
 
 /*
@@ -487,6 +498,16 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 sc->memmap[ASPEED_SDHCI]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>sdhci), 0,
aspeed_soc_get_irq(s, ASPEED_SDHCI));
+
+/* eMMC */
+object_property_set_bool(OBJECT(>emmc), true, "realized", );
+if (err) {
+error_propagate(errp, err);
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>emmc), 0, sc->memmap[ASPEED_EMMC]);
+sysbus_connect_irq(SYS_BUS_DEVICE(>emmc), 0,
+   aspeed_soc_get_irq(s, ASPEED_EMMC));
 }
 
 static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 495c08be1b84..911443f4c071 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -56,6 +56,7 @@ typedef struct AspeedSoCState {
 AspeedGPIOState gpio;
 AspeedGPIOState gpio_1_8v;
 AspeedSDHCIState sdhci;
+AspeedSDHCISt

[PATCH v2 1/2] hw/sd: Configure number of slots exposed by the ASPEED SDHCI model

2019-12-12 Thread Andrew Jeffery
The AST2600 includes a second cut-down version of the SD/MMC controller
found in the AST2500, named the eMMC controller. It's cut down in the
sense that it only supports one slot rather than two, but it brings the
total number of slots supported by the AST2600 to three.

The existing code assumed that the SD controller always provided two
slots. Rework the SDHCI object to expose the number of slots as a
property to be set by the SoC configuration.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/arm/aspeed.c  |  2 +-
 hw/arm/aspeed_ast2600.c  |  2 ++
 hw/arm/aspeed_soc.c  |  2 ++
 hw/sd/aspeed_sdhci.c | 11 +--
 include/hw/sd/aspeed_sdhci.h |  1 +
 5 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 028191ff36fc..862549b1f3a9 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -259,7 +259,7 @@ static void aspeed_board_init(MachineState *machine,
 cfg->i2c_init(bmc);
 }
 
-for (i = 0; i < ARRAY_SIZE(bmc->soc.sdhci.slots); i++) {
+for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
 SDHCIState *sdhci = >soc.sdhci.slots[i];
 DriveInfo *dinfo = drive_get_next(IF_SD);
 BlockBackend *blk;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 931887ac681f..931ee5aae183 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -208,6 +208,8 @@ static void aspeed_soc_ast2600_init(Object *obj)
 sysbus_init_child_obj(obj, "sdc", OBJECT(>sdhci), sizeof(s->sdhci),
   TYPE_ASPEED_SDHCI);
 
+object_property_set_int(OBJECT(>sdhci), 2, "num-slots", _abort);
+
 /* Init sd card slot class here so that they're under the correct parent */
 for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
 sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(>sdhci.slots[i]),
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index f4fe243458fd..c39a42f914d4 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -215,6 +215,8 @@ static void aspeed_soc_init(Object *obj)
 sysbus_init_child_obj(obj, "sdc", OBJECT(>sdhci), sizeof(s->sdhci),
   TYPE_ASPEED_SDHCI);
 
+object_property_set_int(OBJECT(>sdhci), 2, "num-slots", _abort);
+
 /* Init sd card slot class here so that they're under the correct parent */
 for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
 sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(>sdhci.slots[i]),
diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c
index cff3eb7dd21e..939d1510dedb 100644
--- a/hw/sd/aspeed_sdhci.c
+++ b/hw/sd/aspeed_sdhci.c
@@ -13,6 +13,7 @@
 #include "qapi/error.h"
 #include "hw/irq.h"
 #include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
 
 #define ASPEED_SDHCI_INFO0x00
 #define  ASPEED_SDHCI_INFO_RESET 0x0003
@@ -120,14 +121,14 @@ static void aspeed_sdhci_realize(DeviceState *dev, Error 
**errp)
 
 /* Create input irqs for the slots */
 qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_sdhci_set_irq,
-sdhci, NULL, ASPEED_SDHCI_NUM_SLOTS);
+sdhci, NULL, sdhci->num_slots);
 
 sysbus_init_irq(sbd, >irq);
 memory_region_init_io(>iomem, OBJECT(sdhci), _sdhci_ops,
   sdhci, TYPE_ASPEED_SDHCI, 0x1000);
 sysbus_init_mmio(sbd, >iomem);
 
-for (int i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
+for (int i = 0; i < sdhci->num_slots; ++i) {
 Object *sdhci_slot = OBJECT(>slots[i]);
 SysBusDevice *sbd_slot = SYS_BUS_DEVICE(>slots[i]);
 
@@ -174,6 +175,11 @@ static const VMStateDescription vmstate_aspeed_sdhci = {
 },
 };
 
+static Property aspeed_sdhci_properties[] = {
+DEFINE_PROP_UINT8("num-slots", AspeedSDHCIState, num_slots, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(classp);
@@ -181,6 +187,7 @@ static void aspeed_sdhci_class_init(ObjectClass *classp, 
void *data)
 dc->realize = aspeed_sdhci_realize;
 dc->reset = aspeed_sdhci_reset;
 dc->vmsd = _aspeed_sdhci;
+dc->props = aspeed_sdhci_properties;
 }
 
 static TypeInfo aspeed_sdhci_info = {
diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h
index dfdab4379021..dffbb46946b9 100644
--- a/include/hw/sd/aspeed_sdhci.h
+++ b/include/hw/sd/aspeed_sdhci.h
@@ -24,6 +24,7 @@ typedef struct AspeedSDHCIState {
 SysBusDevice parent;
 
 SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
+uint8_t num_slots;
 
 MemoryRegion iomem;
 qemu_irq irq;
-- 
git-series 0.9.1



Re: [PATCH 0/2] hw/arm: ast2600: Wire up eMMC controller

2019-12-10 Thread Andrew Jeffery



On Tue, 10 Dec 2019, at 19:23, Cédric Le Goater wrote:
> On 10/12/2019 01:52, Andrew Jeffery wrote:
> > Hello,
> > 
> > The AST2600 has an additional SDHCI intended for use as an eMMC boot source.
> 
> Have you also considered booting the QEMU Aspeed AST2600 machine 
> from the eMMC device ?
> 

I hadn't got that far. I was surprised we hadn't yet wired up the eMMC 
controller at
all, so I solved that problem first :)

Andrew



Re: [PATCH 1/2] hw/sd: Configure number of slots exposed by the ASPEED SDHCI model

2019-12-10 Thread Andrew Jeffery



On Tue, 10 Dec 2019, at 19:26, Cédric Le Goater wrote:
> On 10/12/2019 01:52, Andrew Jeffery wrote:
> > The AST2600 includes a second cut-down version of the SD/MMC controller
> > found in the AST2500, named the eMMC controller. It's cut down in the
> > sense that it only supports one slot rather than two, but it brings the
> > total number of slots supported by the AST2600 to three.
> > 
> > The existing code assumed that the SD controller always provided two
> > slots. Rework the SDHCI object to expose the number of slots as a
> > property to be set by the SoC configuration.
> > 
> > Signed-off-by: Andrew Jeffery 
> 
> Reviewed-by: Cédric Le Goater 
> 
> One minor question below.
> 
> 
> > ---
> >  hw/arm/aspeed.c  |  2 +-
> >  hw/arm/aspeed_ast2600.c  |  2 ++
> >  hw/arm/aspeed_soc.c  |  3 +++
> >  hw/sd/aspeed_sdhci.c | 11 +--
> >  include/hw/sd/aspeed_sdhci.h |  1 +
> >  5 files changed, 16 insertions(+), 3 deletions(-)
> > 
> > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> > index 028191ff36fc..862549b1f3a9 100644
> > --- a/hw/arm/aspeed.c
> > +++ b/hw/arm/aspeed.c
> > @@ -259,7 +259,7 @@ static void aspeed_board_init(MachineState *machine,
> >  cfg->i2c_init(bmc);
> >  }
> >  
> > -for (i = 0; i < ARRAY_SIZE(bmc->soc.sdhci.slots); i++) {
> > +for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
> >  SDHCIState *sdhci = >soc.sdhci.slots[i];
> >  DriveInfo *dinfo = drive_get_next(IF_SD);
> >  BlockBackend *blk;
> > diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
> > index 931887ac681f..931ee5aae183 100644
> > --- a/hw/arm/aspeed_ast2600.c
> > +++ b/hw/arm/aspeed_ast2600.c
> > @@ -208,6 +208,8 @@ static void aspeed_soc_ast2600_init(Object *obj)
> >  sysbus_init_child_obj(obj, "sdc", OBJECT(>sdhci), sizeof(s->sdhci),
> >TYPE_ASPEED_SDHCI);
> >  
> > +object_property_set_int(OBJECT(>sdhci), 2, "num-slots", 
> > _abort);
> 
> OK. This defines 2 SDHCI slots for the ast2600 SoC, but
> 
> > +
> >  /* Init sd card slot class here so that they're under the correct 
> > parent */
> >  for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
> >  sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(>sdhci.slots[i]),
> > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > index f4fe243458fd..3498f55603f2 100644
> > --- a/hw/arm/aspeed_soc.c
> > +++ b/hw/arm/aspeed_soc.c
> > @@ -215,6 +215,9 @@ static void aspeed_soc_init(Object *obj)
> >  sysbus_init_child_obj(obj, "sdc", OBJECT(>sdhci), sizeof(s->sdhci),
> >TYPE_ASPEED_SDHCI);
> >  
> > +object_property_set_int(OBJECT(>sdhci), ASPEED_SDHCI_NUM_SLOTS,
> > +"num-slots", _abort);
> 
> 
> why use ASPEED_SDHCI_NUM_SLOTS here ?

No good reason. I'll just switch it to '2' like in the 2600.

Andrew



Re: [PATCH 2/2] hw/arm: ast2600: Wire up the eMMC controller

2019-12-10 Thread Andrew Jeffery



On Tue, 10 Dec 2019, at 23:22, Cédric Le Goater wrote:
> On 10/12/2019 01:52, Andrew Jeffery wrote:
> > Initialise another SDHCI model instance for the AST2600's eMMC
> > controller and use the SDHCI's num_slots value introduced previously to
> > determine whether we should create an SD card instance for the new slot.
> > 
> > Signed-off-by: Andrew Jeffery 
> 
> LGTM. One comment.
> 
> > ---
> >  hw/arm/aspeed.c | 13 +
> >  hw/arm/aspeed_ast2600.c | 21 +
> >  include/hw/arm/aspeed_soc.h |  2 ++
> >  3 files changed, 36 insertions(+)
> > 
> > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> > index 862549b1f3a9..0e08d62e9ff3 100644
> > --- a/hw/arm/aspeed.c
> > +++ b/hw/arm/aspeed.c
> > @@ -272,6 +272,19 @@ static void aspeed_board_init(MachineState *machine,
> >  object_property_set_bool(OBJECT(card), true, "realized", 
> > _fatal);
> >  }
> >  
> > +if (bmc->soc.emmc.num_slots) {
> > +SDHCIState *emmc = >soc.emmc.slots[0];
> > +DriveInfo *dinfo = drive_get_next(IF_SD);
> > +BlockBackend *blk;
> > +DeviceState *card;
> > +
> > +blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
> > +card = qdev_create(qdev_get_child_bus(DEVICE(emmc), "sd-bus"),
> > +   TYPE_SD_CARD);
> > +qdev_prop_set_drive(card, "drive", blk, _fatal);
> > +object_property_set_bool(OBJECT(card), true, "realized", 
> > _fatal);
> > +}
> 
> I think we could use a function for the above ^

Yep, I'll refactor that.

Andrew



[PATCH 2/2] hw/arm: ast2600: Wire up the eMMC controller

2019-12-09 Thread Andrew Jeffery
Initialise another SDHCI model instance for the AST2600's eMMC
controller and use the SDHCI's num_slots value introduced previously to
determine whether we should create an SD card instance for the new slot.

Signed-off-by: Andrew Jeffery 
---
 hw/arm/aspeed.c | 13 +
 hw/arm/aspeed_ast2600.c | 21 +
 include/hw/arm/aspeed_soc.h |  2 ++
 3 files changed, 36 insertions(+)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 862549b1f3a9..0e08d62e9ff3 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -272,6 +272,19 @@ static void aspeed_board_init(MachineState *machine,
 object_property_set_bool(OBJECT(card), true, "realized", _fatal);
 }
 
+if (bmc->soc.emmc.num_slots) {
+SDHCIState *emmc = >soc.emmc.slots[0];
+DriveInfo *dinfo = drive_get_next(IF_SD);
+BlockBackend *blk;
+DeviceState *card;
+
+blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+card = qdev_create(qdev_get_child_bus(DEVICE(emmc), "sd-bus"),
+   TYPE_SD_CARD);
+qdev_prop_set_drive(card, "drive", blk, _fatal);
+object_property_set_bool(OBJECT(card), true, "realized", _fatal);
+}
+
 arm_load_kernel(ARM_CPU(first_cpu), machine, _board_binfo);
 }
 
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 931ee5aae183..723c8196c8a5 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -46,6 +46,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
 [ASPEED_ADC]   = 0x1E6E9000,
 [ASPEED_VIDEO] = 0x1E70,
 [ASPEED_SDHCI] = 0x1E74,
+[ASPEED_EMMC]  = 0x1E75,
 [ASPEED_GPIO]  = 0x1E78,
 [ASPEED_GPIO_1_8V] = 0x1E780800,
 [ASPEED_RTC]   = 0x1E781000,
@@ -64,6 +65,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
 
 #define ASPEED_SOC_AST2600_MAX_IRQ 128
 
+/* Shared Peripheral Interrupt values below are offset by -32 from datasheet */
 static const int aspeed_soc_ast2600_irqmap[] = {
 [ASPEED_UART1] = 47,
 [ASPEED_UART2] = 48,
@@ -77,6 +79,7 @@ static const int aspeed_soc_ast2600_irqmap[] = {
 [ASPEED_ADC]   = 78,
 [ASPEED_XDMA]  = 6,
 [ASPEED_SDHCI] = 43,
+[ASPEED_EMMC]  = 15,
 [ASPEED_GPIO]  = 40,
 [ASPEED_GPIO_1_8V] = 11,
 [ASPEED_RTC]   = 13,
@@ -215,6 +218,14 @@ static void aspeed_soc_ast2600_init(Object *obj)
 sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(>sdhci.slots[i]),
   sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI);
 }
+
+sysbus_init_child_obj(obj, "emmc", OBJECT(>emmc), sizeof(s->emmc),
+  TYPE_ASPEED_SDHCI);
+
+object_property_set_int(OBJECT(>emmc), 1, "num-slots", _abort);
+
+sysbus_init_child_obj(obj, "emmc[*]", OBJECT(>emmc.slots[0]),
+sizeof(s->emmc.slots[0]), TYPE_SYSBUS_SDHCI);
 }
 
 /*
@@ -487,6 +498,16 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 sc->memmap[ASPEED_SDHCI]);
 sysbus_connect_irq(SYS_BUS_DEVICE(>sdhci), 0,
aspeed_soc_get_irq(s, ASPEED_SDHCI));
+
+/* eMMC */
+object_property_set_bool(OBJECT(>emmc), true, "realized", );
+if (err) {
+error_propagate(errp, err);
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>emmc), 0, sc->memmap[ASPEED_EMMC]);
+sysbus_connect_irq(SYS_BUS_DEVICE(>emmc), 0,
+   aspeed_soc_get_irq(s, ASPEED_EMMC));
 }
 
 static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 495c08be1b84..911443f4c071 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -56,6 +56,7 @@ typedef struct AspeedSoCState {
 AspeedGPIOState gpio;
 AspeedGPIOState gpio_1_8v;
 AspeedSDHCIState sdhci;
+AspeedSDHCIState emmc;
 } AspeedSoCState;
 
 #define TYPE_ASPEED_SOC "aspeed-soc"
@@ -125,6 +126,7 @@ enum {
 ASPEED_MII4,
 ASPEED_SDRAM,
 ASPEED_XDMA,
+ASPEED_EMMC,
 };
 
 #endif /* ASPEED_SOC_H */
-- 
git-series 0.9.1



[PATCH 1/2] hw/sd: Configure number of slots exposed by the ASPEED SDHCI model

2019-12-09 Thread Andrew Jeffery
The AST2600 includes a second cut-down version of the SD/MMC controller
found in the AST2500, named the eMMC controller. It's cut down in the
sense that it only supports one slot rather than two, but it brings the
total number of slots supported by the AST2600 to three.

The existing code assumed that the SD controller always provided two
slots. Rework the SDHCI object to expose the number of slots as a
property to be set by the SoC configuration.

Signed-off-by: Andrew Jeffery 
---
 hw/arm/aspeed.c  |  2 +-
 hw/arm/aspeed_ast2600.c  |  2 ++
 hw/arm/aspeed_soc.c  |  3 +++
 hw/sd/aspeed_sdhci.c | 11 +--
 include/hw/sd/aspeed_sdhci.h |  1 +
 5 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 028191ff36fc..862549b1f3a9 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -259,7 +259,7 @@ static void aspeed_board_init(MachineState *machine,
 cfg->i2c_init(bmc);
 }
 
-for (i = 0; i < ARRAY_SIZE(bmc->soc.sdhci.slots); i++) {
+for (i = 0; i < bmc->soc.sdhci.num_slots; i++) {
 SDHCIState *sdhci = >soc.sdhci.slots[i];
 DriveInfo *dinfo = drive_get_next(IF_SD);
 BlockBackend *blk;
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 931887ac681f..931ee5aae183 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -208,6 +208,8 @@ static void aspeed_soc_ast2600_init(Object *obj)
 sysbus_init_child_obj(obj, "sdc", OBJECT(>sdhci), sizeof(s->sdhci),
   TYPE_ASPEED_SDHCI);
 
+object_property_set_int(OBJECT(>sdhci), 2, "num-slots", _abort);
+
 /* Init sd card slot class here so that they're under the correct parent */
 for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
 sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(>sdhci.slots[i]),
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index f4fe243458fd..3498f55603f2 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -215,6 +215,9 @@ static void aspeed_soc_init(Object *obj)
 sysbus_init_child_obj(obj, "sdc", OBJECT(>sdhci), sizeof(s->sdhci),
   TYPE_ASPEED_SDHCI);
 
+object_property_set_int(OBJECT(>sdhci), ASPEED_SDHCI_NUM_SLOTS,
+"num-slots", _abort);
+
 /* Init sd card slot class here so that they're under the correct parent */
 for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
 sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(>sdhci.slots[i]),
diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c
index cff3eb7dd21e..939d1510dedb 100644
--- a/hw/sd/aspeed_sdhci.c
+++ b/hw/sd/aspeed_sdhci.c
@@ -13,6 +13,7 @@
 #include "qapi/error.h"
 #include "hw/irq.h"
 #include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
 
 #define ASPEED_SDHCI_INFO0x00
 #define  ASPEED_SDHCI_INFO_RESET 0x0003
@@ -120,14 +121,14 @@ static void aspeed_sdhci_realize(DeviceState *dev, Error 
**errp)
 
 /* Create input irqs for the slots */
 qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_sdhci_set_irq,
-sdhci, NULL, ASPEED_SDHCI_NUM_SLOTS);
+sdhci, NULL, sdhci->num_slots);
 
 sysbus_init_irq(sbd, >irq);
 memory_region_init_io(>iomem, OBJECT(sdhci), _sdhci_ops,
   sdhci, TYPE_ASPEED_SDHCI, 0x1000);
 sysbus_init_mmio(sbd, >iomem);
 
-for (int i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
+for (int i = 0; i < sdhci->num_slots; ++i) {
 Object *sdhci_slot = OBJECT(>slots[i]);
 SysBusDevice *sbd_slot = SYS_BUS_DEVICE(>slots[i]);
 
@@ -174,6 +175,11 @@ static const VMStateDescription vmstate_aspeed_sdhci = {
 },
 };
 
+static Property aspeed_sdhci_properties[] = {
+DEFINE_PROP_UINT8("num-slots", AspeedSDHCIState, num_slots, 0),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(classp);
@@ -181,6 +187,7 @@ static void aspeed_sdhci_class_init(ObjectClass *classp, 
void *data)
 dc->realize = aspeed_sdhci_realize;
 dc->reset = aspeed_sdhci_reset;
 dc->vmsd = _aspeed_sdhci;
+dc->props = aspeed_sdhci_properties;
 }
 
 static TypeInfo aspeed_sdhci_info = {
diff --git a/include/hw/sd/aspeed_sdhci.h b/include/hw/sd/aspeed_sdhci.h
index dfdab4379021..dffbb46946b9 100644
--- a/include/hw/sd/aspeed_sdhci.h
+++ b/include/hw/sd/aspeed_sdhci.h
@@ -24,6 +24,7 @@ typedef struct AspeedSDHCIState {
 SysBusDevice parent;
 
 SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
+uint8_t num_slots;
 
 MemoryRegion iomem;
 qemu_irq irq;
-- 
git-series 0.9.1



[PATCH 0/2] hw/arm: ast2600: Wire up eMMC controller

2019-12-09 Thread Andrew Jeffery
Hello,

The AST2600 has an additional SDHCI intended for use as an eMMC boot source.
These two patches rework the existing ASPEED SDHCI model to accommodate the
single-slot nature of the eMMC controller and wire it into the AST2600 SoC.

Please review!

Andrew

Andrew Jeffery (2):
  hw/sd: Configure number of slots exposed by the ASPEED SDHCI model
  hw/arm: ast2600: Wire up the eMMC controller

 hw/arm/aspeed.c  | 15 ++-
 hw/arm/aspeed_ast2600.c  | 23 +++
 hw/arm/aspeed_soc.c  |  3 +++
 hw/sd/aspeed_sdhci.c | 11 +--
 include/hw/arm/aspeed_soc.h  |  2 ++
 include/hw/sd/aspeed_sdhci.h |  1 +
 6 files changed, 52 insertions(+), 3 deletions(-)

base-commit: 6a4ef4e5d1084ce41fafa7d470a644b0fd3d9317
-- 
git-series 0.9.1



Re: [PATCH v2 2/4] target/arm: Abstract the generic timer frequency

2019-12-04 Thread Andrew Jeffery



On Wed, 4 Dec 2019, at 03:57, Philippe Mathieu-Daudé wrote:
> On 12/3/19 1:48 PM, Andrew Jeffery wrote:
> > On Tue, 3 Dec 2019, at 16:39, Philippe Mathieu-Daudé wrote:
> >> On 12/3/19 5:14 AM, Andrew Jeffery wrote:
> >>> Prepare for SoCs such as the ASPEED AST2600 whose firmware configures
> >>> CNTFRQ to values significantly larger than the static 62.5MHz value
> >>> currently derived from GTIMER_SCALE. As the OS potentially derives its
> >>> timer periods from the CNTFRQ value the lack of support for running
> >>> QEMUTimers at the appropriate rate leads to sticky behaviour in the
> >>> guest.
> >>>
> >>> Substitute the GTIMER_SCALE constant with use of a helper to derive the
> >>> period from gt_cntfrq stored in struct ARMCPU. Initially set gt_cntfrq
> >>> to the frequency associated with GTIMER_SCALE so current behaviour is
> >>> maintained.
> >>>
> >>> Signed-off-by: Andrew Jeffery 
> >>> Reviewed-by: Richard Henderson 
> >>> ---
> >>>target/arm/cpu.c|  2 ++
> >>>target/arm/cpu.h| 10 ++
> >>>target/arm/helper.c | 10 +++---
> >>>3 files changed, 19 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> >>> index 7a4ac9339bf9..5698a74061bb 100644
> >>> --- a/target/arm/cpu.c
> >>> +++ b/target/arm/cpu.c
> >>> @@ -974,6 +974,8 @@ static void arm_cpu_initfn(Object *obj)
> >>>if (tcg_enabled()) {
> >>>cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
> >>>}
> >>> +
> >>> +cpu->gt_cntfrq = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
> >>>}
> >>>
> >>>static Property arm_cpu_reset_cbar_property =
> >>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> >>> index 83a809d4bac4..666c03871fdf 100644
> >>> --- a/target/arm/cpu.h
> >>> +++ b/target/arm/cpu.h
> >>> @@ -932,8 +932,18 @@ struct ARMCPU {
> >>> */
> >>>DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
> >>>DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
> >>> +
> >>> +/* Generic timer counter frequency, in Hz */
> >>> +uint64_t gt_cntfrq;
> >>
> >> You can also explicit the unit by calling it 'gt_cntfrq_hz'.
> > 
> > Fair call, I'll fix that.
> > 
> >>
> >>>};
> >>>
> >>> +static inline unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
> >>> +{
> >>> +/* XXX: Could include qemu/timer.h to get NANOSECONDS_PER_SECOND? */
> >>
> >> Why inline this call? I doubt there is a significant performance gain.
> > 
> > It wasn't so much performance. It started out as a macro for a simple 
> > calculation
> > because I didn't want to duplicate it across a number of places, then I 
> > wanted type
> > safety for the pointer so  I switched the macro in the header to an inline 
> > function. So
> > it is an evolution of the patch rather than something that came from an 
> > explicit goal
> > of e.g. performance.
> 
> OK. Eventually NANOSECONDS_PER_SECOND will move to "qemu/units.h".
> 
> Should the XXX comment stay? I'm not sure, it is confusing.

I'll remove that. 

> 
> Reviewed-by: Philippe Mathieu-Daudé 

Thanks. However, did you still want your comment on 4/4 addressed (move
the comment to this patch)?

Andrew



Re: [PATCH v2 3/4] target/arm: Prepare generic timer for per-platform CNTFRQ

2019-12-03 Thread Andrew Jeffery



On Tue, 3 Dec 2019, at 16:49, Philippe Mathieu-Daudé wrote:
> On 12/3/19 5:14 AM, Andrew Jeffery wrote:
> > The ASPEED AST2600 clocks the generic timer at the rate of HPLL. On
> > recent firmwares this is at 1125MHz, which is considerably quicker than
> > the assumed 62.5MHz of the current generic timer implementation. The
> > delta between the value as read from CNTFRQ and the true rate of the
> > underlying QEMUTimer leads to sticky behaviour in AST2600 guests.
> > 
> > Add a feature-gated property exposing CNTFRQ for ARM CPUs providing the
> > generic timer. This allows platforms to configure CNTFRQ (and the
> > associated QEMUTimer) to the appropriate frequency prior to starting the
> > guest.
> > 
> > As the platform can now determine the rate of CNTFRQ we're exposed to
> > limitations of QEMUTimer that didn't previously materialise: In the
> > course of emulation we need to arbitrarily and accurately convert
> > between guest ticks and time, but we're constrained by QEMUTimer's use
> > of an integer scaling factor. The effect is QEMUTimer cannot exactly
> > capture the period of frequencies that do not cleanly divide
> > NANOSECONDS_PER_SECOND for scaling ticks to time. As such, provide an
> > equally inaccurate scaling factor for scaling time to ticks so at least
> > a self-consistent inverse relationship holds.
> > 
> > Signed-off-by: Andrew Jeffery 
> > Reviewed-by: Richard Henderson 
> > ---
> >   target/arm/cpu.c| 43 +--
> >   target/arm/cpu.h| 18 ++
> >   target/arm/helper.c |  9 -
> >   3 files changed, 59 insertions(+), 11 deletions(-)
> > 
> > diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> > index 5698a74061bb..f186019a77fd 100644
> > --- a/target/arm/cpu.c
> > +++ b/target/arm/cpu.c
> > @@ -974,10 +974,12 @@ static void arm_cpu_initfn(Object *obj)
> >   if (tcg_enabled()) {
> >   cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
> >   }
> > -
> > -cpu->gt_cntfrq = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
> >   }
> >   
> > +static Property arm_cpu_gt_cntfrq_property =
> > +DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq,
> > +   NANOSECONDS_PER_SECOND / GTIMER_SCALE);
> > +
> >   static Property arm_cpu_reset_cbar_property =
> >   DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
> >   
> > @@ -1174,6 +1176,11 @@ void arm_cpu_post_init(Object *obj)
> >   
> >   qdev_property_add_static(DEVICE(obj), _cpu_cfgend_property,
> >_abort);
> > +
> > +if (arm_feature(>env, ARM_FEATURE_GENERIC_TIMER)) {
> > +qdev_property_add_static(DEVICE(cpu), _cpu_gt_cntfrq_property,
> > + _abort);
> > +}
> >   }
> >   
> >   static void arm_cpu_finalizefn(Object *obj)
> > @@ -1253,14 +1260,30 @@ static void arm_cpu_realizefn(DeviceState *dev, 
> > Error **errp)
> >   }
> >   }
> >   
> > -cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, 
> > GTIMER_SCALE,
> > -   arm_gt_ptimer_cb, cpu);
> > -cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, 
> > GTIMER_SCALE,
> > -   arm_gt_vtimer_cb, cpu);
> > -cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
> > -  arm_gt_htimer_cb, cpu);
> > -cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
> > -  arm_gt_stimer_cb, cpu);
> > +
> > +{
> > +uint64_t scale;
> 
> Apparently you have to use this odd indent due to the '#ifndef 
> CONFIG_USER_ONLY'. Well, acceptable.

It's the indent associated with the block scope for the scale variable to limit 
its lifetime
to where I needed it.

> 
> > +
> > +if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
> > +if (!cpu->gt_cntfrq) {
> > +error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
> > +   cpu->gt_cntfrq);
> > +return;
> > +}
> > +scale = gt_cntfrq_period_ns(cpu);
> > +} else {
> > +scale = GTIMER_SCALE;
> > +}
> > +
> > +cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,

Re: [PATCH v2 2/4] target/arm: Abstract the generic timer frequency

2019-12-03 Thread Andrew Jeffery



On Tue, 3 Dec 2019, at 16:39, Philippe Mathieu-Daudé wrote:
> On 12/3/19 5:14 AM, Andrew Jeffery wrote:
> > Prepare for SoCs such as the ASPEED AST2600 whose firmware configures
> > CNTFRQ to values significantly larger than the static 62.5MHz value
> > currently derived from GTIMER_SCALE. As the OS potentially derives its
> > timer periods from the CNTFRQ value the lack of support for running
> > QEMUTimers at the appropriate rate leads to sticky behaviour in the
> > guest.
> > 
> > Substitute the GTIMER_SCALE constant with use of a helper to derive the
> > period from gt_cntfrq stored in struct ARMCPU. Initially set gt_cntfrq
> > to the frequency associated with GTIMER_SCALE so current behaviour is
> > maintained.
> > 
> > Signed-off-by: Andrew Jeffery 
> > Reviewed-by: Richard Henderson 
> > ---
> >   target/arm/cpu.c|  2 ++
> >   target/arm/cpu.h| 10 ++
> >   target/arm/helper.c | 10 +++---
> >   3 files changed, 19 insertions(+), 3 deletions(-)
> > 
> > diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> > index 7a4ac9339bf9..5698a74061bb 100644
> > --- a/target/arm/cpu.c
> > +++ b/target/arm/cpu.c
> > @@ -974,6 +974,8 @@ static void arm_cpu_initfn(Object *obj)
> >   if (tcg_enabled()) {
> >   cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
> >   }
> > +
> > +cpu->gt_cntfrq = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
> >   }
> >   
> >   static Property arm_cpu_reset_cbar_property =
> > diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> > index 83a809d4bac4..666c03871fdf 100644
> > --- a/target/arm/cpu.h
> > +++ b/target/arm/cpu.h
> > @@ -932,8 +932,18 @@ struct ARMCPU {
> >*/
> >   DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
> >   DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
> > +
> > +/* Generic timer counter frequency, in Hz */
> > +uint64_t gt_cntfrq;
> 
> You can also explicit the unit by calling it 'gt_cntfrq_hz'.

Fair call, I'll fix that.

> 
> >   };
> >   
> > +static inline unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
> > +{
> > +/* XXX: Could include qemu/timer.h to get NANOSECONDS_PER_SECOND? */
> 
> Why inline this call? I doubt there is a significant performance gain.

It wasn't so much performance. It started out as a macro for a simple 
calculation
because I didn't want to duplicate it across a number of places, then I wanted 
type
safety for the pointer so  I switched the macro in the header to an inline 
function. So
it is an evolution of the patch rather than something that came from an 
explicit goal
of e.g. performance.

Andrew



[PATCH v2 2/4] target/arm: Abstract the generic timer frequency

2019-12-02 Thread Andrew Jeffery
Prepare for SoCs such as the ASPEED AST2600 whose firmware configures
CNTFRQ to values significantly larger than the static 62.5MHz value
currently derived from GTIMER_SCALE. As the OS potentially derives its
timer periods from the CNTFRQ value the lack of support for running
QEMUTimers at the appropriate rate leads to sticky behaviour in the
guest.

Substitute the GTIMER_SCALE constant with use of a helper to derive the
period from gt_cntfrq stored in struct ARMCPU. Initially set gt_cntfrq
to the frequency associated with GTIMER_SCALE so current behaviour is
maintained.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Richard Henderson 
---
 target/arm/cpu.c|  2 ++
 target/arm/cpu.h| 10 ++
 target/arm/helper.c | 10 +++---
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 7a4ac9339bf9..5698a74061bb 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -974,6 +974,8 @@ static void arm_cpu_initfn(Object *obj)
 if (tcg_enabled()) {
 cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
 }
+
+cpu->gt_cntfrq = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
 }
 
 static Property arm_cpu_reset_cbar_property =
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 83a809d4bac4..666c03871fdf 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -932,8 +932,18 @@ struct ARMCPU {
  */
 DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
 DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
+
+/* Generic timer counter frequency, in Hz */
+uint64_t gt_cntfrq;
 };
 
+static inline unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
+{
+/* XXX: Could include qemu/timer.h to get NANOSECONDS_PER_SECOND? */
+const unsigned int ns_per_s = 1000 * 1000 * 1000;
+return ns_per_s > cpu->gt_cntfrq ? ns_per_s / cpu->gt_cntfrq : 1;
+}
+
 void arm_cpu_post_init(Object *obj);
 
 uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 65c4441a3896..2622a9a8d02f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2409,7 +2409,9 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
 
 static uint64_t gt_get_countervalue(CPUARMState *env)
 {
-return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+ARMCPU *cpu = env_archcpu(env);
+
+return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
 }
 
 static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
@@ -2445,7 +2447,7 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * set the timer for as far in the future as possible. When the
  * timer expires we will reset the timer for any remaining period.
  */
-if (nexttick > INT64_MAX / GTIMER_SCALE) {
+if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {
 timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
 } else {
 timer_mod(cpu->gt_timer[timeridx], nexttick);
@@ -2874,11 +2876,13 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 
 static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
+ARMCPU *cpu = env_archcpu(env);
+
 /* Currently we have no support for QEMUTimer in linux-user so we
  * can't call gt_get_countervalue(env), instead we directly
  * call the lower level functions.
  */
-return cpu_get_clock() / GTIMER_SCALE;
+return cpu_get_clock() / gt_cntfrq_period_ns(cpu);
 }
 
 static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
-- 
2.20.1




[PATCH v2 3/4] target/arm: Prepare generic timer for per-platform CNTFRQ

2019-12-02 Thread Andrew Jeffery
The ASPEED AST2600 clocks the generic timer at the rate of HPLL. On
recent firmwares this is at 1125MHz, which is considerably quicker than
the assumed 62.5MHz of the current generic timer implementation. The
delta between the value as read from CNTFRQ and the true rate of the
underlying QEMUTimer leads to sticky behaviour in AST2600 guests.

Add a feature-gated property exposing CNTFRQ for ARM CPUs providing the
generic timer. This allows platforms to configure CNTFRQ (and the
associated QEMUTimer) to the appropriate frequency prior to starting the
guest.

As the platform can now determine the rate of CNTFRQ we're exposed to
limitations of QEMUTimer that didn't previously materialise: In the
course of emulation we need to arbitrarily and accurately convert
between guest ticks and time, but we're constrained by QEMUTimer's use
of an integer scaling factor. The effect is QEMUTimer cannot exactly
capture the period of frequencies that do not cleanly divide
NANOSECONDS_PER_SECOND for scaling ticks to time. As such, provide an
equally inaccurate scaling factor for scaling time to ticks so at least
a self-consistent inverse relationship holds.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Richard Henderson 
---
 target/arm/cpu.c| 43 +--
 target/arm/cpu.h| 18 ++
 target/arm/helper.c |  9 -
 3 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5698a74061bb..f186019a77fd 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -974,10 +974,12 @@ static void arm_cpu_initfn(Object *obj)
 if (tcg_enabled()) {
 cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
 }
-
-cpu->gt_cntfrq = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
 }
 
+static Property arm_cpu_gt_cntfrq_property =
+DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq,
+   NANOSECONDS_PER_SECOND / GTIMER_SCALE);
+
 static Property arm_cpu_reset_cbar_property =
 DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
 
@@ -1174,6 +1176,11 @@ void arm_cpu_post_init(Object *obj)
 
 qdev_property_add_static(DEVICE(obj), _cpu_cfgend_property,
  _abort);
+
+if (arm_feature(>env, ARM_FEATURE_GENERIC_TIMER)) {
+qdev_property_add_static(DEVICE(cpu), _cpu_gt_cntfrq_property,
+ _abort);
+}
 }
 
 static void arm_cpu_finalizefn(Object *obj)
@@ -1253,14 +1260,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
-cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_ptimer_cb, cpu);
-cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_vtimer_cb, cpu);
-cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_htimer_cb, cpu);
-cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_stimer_cb, cpu);
+
+{
+uint64_t scale;
+
+if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
+if (!cpu->gt_cntfrq) {
+error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
+   cpu->gt_cntfrq);
+return;
+}
+scale = gt_cntfrq_period_ns(cpu);
+} else {
+scale = GTIMER_SCALE;
+}
+
+cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_ptimer_cb, cpu);
+cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_vtimer_cb, cpu);
+cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_htimer_cb, cpu);
+cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_stimer_cb, cpu);
+}
 #endif
 
 cpu_exec_realizefn(cs, _err);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 666c03871fdf..0bcd13dcac81 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -939,6 +939,24 @@ struct ARMCPU {
 
 static inline unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
 {
+/*
+ * The exact approach to calculating guest ticks is:
+ *
+ * muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), cpu->gt_cntfrq,
+ *  NANOSECONDS_PER_SECOND);
+ *
+ * We don't do that. Rather we intentionally use integer division
+ * truncation below and in the caller for the conversion of host monotonic
+ * time to guest ticks to provide the exact inverse for the semantics of
+ * the QEMUTimer scale factor. QEMUT

[PATCH v2 4/4] ast2600: Configure CNTFRQ at 1125MHz

2019-12-02 Thread Andrew Jeffery
This matches the configuration set by u-boot on the AST2600.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Richard Henderson 
Reviewed-by: Cédric Le Goater 
---
 hw/arm/aspeed_ast2600.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 931887ac681f..5aecc3b3caec 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -259,6 +259,9 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 object_property_set_int(OBJECT(>cpu[i]), aspeed_calc_affinity(i),
 "mp-affinity", _abort);
 
+object_property_set_int(OBJECT(>cpu[i]), 112500, "cntfrq",
+_abort);
+
 /*
  * TODO: the secondary CPUs are started and a boot helper
  * is needed when using -kernel
-- 
2.20.1




[PATCH v2 0/4] Expose GT CNTFRQ as a CPU property to support AST2600

2019-12-02 Thread Andrew Jeffery
Hello,

This is a v2 of the belated follow-up from a few of my earlier attempts to fix
up the ARM generic timer for correct behaviour on the ASPEED AST2600 SoC. The
AST2600 clocks the generic timer at the rate of HPLL, which is configured to
1125MHz.  This is significantly quicker than the currently hard-coded generic
timer rate of 62.5MHz and so we see "sticky" behaviour in the guest.

v1 can be found here:

https://patchwork.ozlabs.org/cover/1201887/

Changes since v1:

* Fix a user mode build failure from partial renaming of gt_cntfrq_period_ns()
* Add tags from Cedric and Richard

Please review.

Andrew

Andrew Jeffery (4):
  target/arm: Remove redundant scaling of nexttick
  target/arm: Abstract the generic timer frequency
  target/arm: Prepare generic timer for per-platform CNTFRQ
  ast2600: Configure CNTFRQ at 1125MHz

 hw/arm/aspeed_ast2600.c |  3 +++
 target/arm/cpu.c| 41 +
 target/arm/cpu.h| 28 
 target/arm/helper.c | 24 ++--
 4 files changed, 82 insertions(+), 14 deletions(-)

-- 
2.20.1




[PATCH v2 1/4] target/arm: Remove redundant scaling of nexttick

2019-12-02 Thread Andrew Jeffery
The corner-case codepath was adjusting nexttick such that overflow
wouldn't occur when timer_mod() scaled the value back up. Remove a use
of GTIMER_SCALE and avoid unnecessary operations by calling
timer_mod_ns() directly.

Signed-off-by: Andrew Jeffery 
Reviewed-by: Richard Henderson 
Reviewed-by: Cédric Le Goater 
---
 target/arm/helper.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index a089fb5a6909..65c4441a3896 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2446,9 +2446,10 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * timer expires we will reset the timer for any remaining period.
  */
 if (nexttick > INT64_MAX / GTIMER_SCALE) {
-nexttick = INT64_MAX / GTIMER_SCALE;
+timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
+} else {
+timer_mod(cpu->gt_timer[timeridx], nexttick);
 }
-timer_mod(cpu->gt_timer[timeridx], nexttick);
 trace_arm_gt_recalc(timeridx, irqstate, nexttick);
 } else {
 /* Timer disabled: ISTATUS and timer output always clear */
-- 
2.20.1




Re: [PATCH 2/4] target/arm: Abstract the generic timer frequency

2019-12-02 Thread Andrew Jeffery



On Tue, 3 Dec 2019, at 04:42, Peter Maydell wrote:
> On Thu, 28 Nov 2019 at 05:44, Andrew Jeffery  wrote:
> >
> > Prepare for SoCs such as the ASPEED AST2600 whose firmware configures
> > CNTFRQ to values significantly larger than the static 62.5MHz value
> > currently derived from GTIMER_SCALE. As the OS potentially derives its
> > timer periods from the CNTFRQ value the lack of support for running
> > QEMUTimers at the appropriate rate leads to sticky behaviour in the
> > guest.
> >
> > Substitute the GTIMER_SCALE constant with use of a helper to derive the
> > period from gt_cntfrq stored in struct ARMCPU. Initially set gt_cntfrq
> > to the frequency associated with GTIMER_SCALE so current behaviour is
> > maintained.
> >
> > Signed-off-by: Andrew Jeffery 
> 
> > +static inline unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
> > +{
> > +/* XXX: Could include qemu/timer.h to get NANOSECONDS_PER_SECOND? */
> > +const unsigned int ns_per_s = 1000 * 1000 * 1000;
> > +return ns_per_s > cpu->gt_cntfrq ? ns_per_s / cpu->gt_cntfrq : 1;
> > +}
> 
> This function is named gt_cntfrq_period_ns()...
> 
> >  static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
> >  {
> > +ARMCPU *cpu = env_archcpu(env);
> > +
> >  /* Currently we have no support for QEMUTimer in linux-user so we
> >   * can't call gt_get_countervalue(env), instead we directly
> >   * call the lower level functions.
> >   */
> > -return cpu_get_clock() / GTIMER_SCALE;
> > +return cpu_get_clock() / gt_cntfrq_period(cpu);
> >  }
> 
> ...but here we call gt_cntfrq_period(), which doesn't exist,
> and indeed at least one of the patchew build systems reported
> it as a compile failure.
> 

Ah yep, I failed to test user mode after renaming the function and missed this.

I haven't seen an alert from patchew though, I wonder where that got to?

Andrew



Re: [PATCH 2/4] target/arm: Abstract the generic timer frequency

2019-11-28 Thread Andrew Jeffery



On Thu, 28 Nov 2019, at 19:16, Cédric Le Goater wrote:
> On 28/11/2019 06:45, Andrew Jeffery wrote:
> > Prepare for SoCs such as the ASPEED AST2600 whose firmware configures
> > CNTFRQ to values significantly larger than the static 62.5MHz value
> > currently derived from GTIMER_SCALE. As the OS potentially derives its
> > timer periods from the CNTFRQ value the lack of support for running
> > QEMUTimers at the appropriate rate leads to sticky behaviour in the
> > guest.
> > 
> > Substitute the GTIMER_SCALE constant with use of a helper to derive the
> > period from gt_cntfrq stored in struct ARMCPU. Initially set gt_cntfrq
> > to the frequency associated with GTIMER_SCALE so current behaviour is
> > maintained.
> > 
> > Signed-off-by: Andrew Jeffery 
> > ---
> >  target/arm/cpu.c|  2 ++
> >  target/arm/cpu.h| 10 ++
> >  target/arm/helper.c | 10 +++---
> >  3 files changed, 19 insertions(+), 3 deletions(-)
> > 
> > diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> > index 7a4ac9339bf9..5698a74061bb 100644
> > --- a/target/arm/cpu.c
> > +++ b/target/arm/cpu.c
> > @@ -974,6 +974,8 @@ static void arm_cpu_initfn(Object *obj)
> >  if (tcg_enabled()) {
> >  cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
> >  }
> > +
> > +cpu->gt_cntfrq = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
> >  }
> >  
> >  static Property arm_cpu_reset_cbar_property =
> > diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> > index 83a809d4bac4..666c03871fdf 100644
> > --- a/target/arm/cpu.h
> > +++ b/target/arm/cpu.h
> > @@ -932,8 +932,18 @@ struct ARMCPU {
> >   */
> >  DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
> >  DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
> > +
> > +/* Generic timer counter frequency, in Hz */
> > +uint64_t gt_cntfrq;
> >  };
> >  
> > +static inline unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
> > +{
> > +/* XXX: Could include qemu/timer.h to get NANOSECONDS_PER_SECOND? */
> > +const unsigned int ns_per_s = 1000 * 1000 * 1000;
> > +return ns_per_s > cpu->gt_cntfrq ? ns_per_s / cpu->gt_cntfrq : 1;
> > +}
> 
> Are you inlining this helper for performance reasons ? 

Originally I was going to do it as a macro in order to avoid redundantly 
scattering
the calculation around. My thought was to use a macro as it's a simple 
calculation,
but then figured it was a bit nicer as a function for type safety. I already 
had it as a
macro in the header, so it was the least effort to switch it to a static inline 
and leave
it where it was :) So that's the justification, mostly just evolution of 
thought process.
Performance was also a consideration but I've done no measurements.

Andrew



[PATCH 3/4] target/arm: Prepare generic timer for per-platform CNTFRQ

2019-11-27 Thread Andrew Jeffery
The ASPEED AST2600 clocks the generic timer at the rate of HPLL. On
recent firmwares this is at 1125MHz, which is considerably quicker than
the assumed 62.5MHz of the current generic timer implementation. The
delta between the value as read from CNTFRQ and the true rate of the
underlying QEMUTimer leads to sticky behaviour in AST2600 guests.

Add a feature-gated property exposing CNTFRQ for ARM CPUs providing the
generic timer. This allows platforms to configure CNTFRQ (and the
associated QEMUTimer) to the appropriate frequency prior to starting the
guest.

As the platform can now determine the rate of CNTFRQ we're exposed to
limitations of QEMUTimer that didn't previously materialise: In the
course of emulation we need to arbitrarily and accurately convert
between guest ticks and time, but we're constrained by QEMUTimer's use
of an integer scaling factor. Its effect is QEMUTimer cannot exactly
capture the period of frequencies that do not cleanly divide
NANOSECONDS_PER_SECOND for scaling ticks to time. As such, provide an
equally inaccurate scaling factor for scaling time to ticks so at least
an self-consistent inverse relationship holds.

Signed-off-by: Andrew Jeffery 
---
 target/arm/cpu.c| 43 +--
 target/arm/cpu.h| 18 ++
 target/arm/helper.c |  9 -
 3 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5698a74061bb..f186019a77fd 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -974,10 +974,12 @@ static void arm_cpu_initfn(Object *obj)
 if (tcg_enabled()) {
 cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
 }
-
-cpu->gt_cntfrq = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
 }
 
+static Property arm_cpu_gt_cntfrq_property =
+DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq,
+   NANOSECONDS_PER_SECOND / GTIMER_SCALE);
+
 static Property arm_cpu_reset_cbar_property =
 DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
 
@@ -1174,6 +1176,11 @@ void arm_cpu_post_init(Object *obj)
 
 qdev_property_add_static(DEVICE(obj), _cpu_cfgend_property,
  _abort);
+
+if (arm_feature(>env, ARM_FEATURE_GENERIC_TIMER)) {
+qdev_property_add_static(DEVICE(cpu), _cpu_gt_cntfrq_property,
+ _abort);
+}
 }
 
 static void arm_cpu_finalizefn(Object *obj)
@@ -1253,14 +1260,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
-cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_ptimer_cb, cpu);
-cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_vtimer_cb, cpu);
-cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_htimer_cb, cpu);
-cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_stimer_cb, cpu);
+
+{
+uint64_t scale;
+
+if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
+if (!cpu->gt_cntfrq) {
+error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
+   cpu->gt_cntfrq);
+return;
+}
+scale = gt_cntfrq_period_ns(cpu);
+} else {
+scale = GTIMER_SCALE;
+}
+
+cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_ptimer_cb, cpu);
+cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_vtimer_cb, cpu);
+cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_htimer_cb, cpu);
+cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_stimer_cb, cpu);
+}
 #endif
 
 cpu_exec_realizefn(cs, _err);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 666c03871fdf..0bcd13dcac81 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -939,6 +939,24 @@ struct ARMCPU {
 
 static inline unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
 {
+/*
+ * The exact approach to calculating guest ticks is:
+ *
+ * muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), cpu->gt_cntfrq,
+ *  NANOSECONDS_PER_SECOND);
+ *
+ * We don't do that. Rather we intentionally use integer division
+ * truncation below and in the caller for the conversion of host monotonic
+ * time to guest ticks to provide the exact inverse for the semantics of
+ * the QEMUTimer scale factor. QEMUTimer's scale facte

[PATCH 0/4] Expose GT CNTFRQ as a CPU property to support AST2600

2019-11-27 Thread Andrew Jeffery
Hello,

This is a belated follow-up from a few of my earlier attempts to fix up the
ARM generic timer for correct behaviour on the ASPEED AST2600 SoC. The AST2600
clocks the generic timer at the rate of HPLL, which is configured to 1125MHz.
This is significantly quicker than the currently hard-coded generic timer rate
of 62.5MHz and so we see "sticky" behaviour in the guest.

Please review.

Andrew

Andrew Jeffery (4):
  target/arm: Remove redundant scaling of nexttick
  target/arm: Abstract the generic timer frequency
  target/arm: Prepare generic timer for per-platform CNTFRQ
  ast2600: Configure CNTFRQ at 1125MHz

 hw/arm/aspeed_ast2600.c |  3 +++
 target/arm/cpu.c| 41 +
 target/arm/cpu.h| 28 
 target/arm/helper.c | 24 ++--
 4 files changed, 82 insertions(+), 14 deletions(-)

-- 
2.20.1




[PATCH 2/4] target/arm: Abstract the generic timer frequency

2019-11-27 Thread Andrew Jeffery
Prepare for SoCs such as the ASPEED AST2600 whose firmware configures
CNTFRQ to values significantly larger than the static 62.5MHz value
currently derived from GTIMER_SCALE. As the OS potentially derives its
timer periods from the CNTFRQ value the lack of support for running
QEMUTimers at the appropriate rate leads to sticky behaviour in the
guest.

Substitute the GTIMER_SCALE constant with use of a helper to derive the
period from gt_cntfrq stored in struct ARMCPU. Initially set gt_cntfrq
to the frequency associated with GTIMER_SCALE so current behaviour is
maintained.

Signed-off-by: Andrew Jeffery 
---
 target/arm/cpu.c|  2 ++
 target/arm/cpu.h| 10 ++
 target/arm/helper.c | 10 +++---
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 7a4ac9339bf9..5698a74061bb 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -974,6 +974,8 @@ static void arm_cpu_initfn(Object *obj)
 if (tcg_enabled()) {
 cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
 }
+
+cpu->gt_cntfrq = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
 }
 
 static Property arm_cpu_reset_cbar_property =
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 83a809d4bac4..666c03871fdf 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -932,8 +932,18 @@ struct ARMCPU {
  */
 DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
 DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
+
+/* Generic timer counter frequency, in Hz */
+uint64_t gt_cntfrq;
 };
 
+static inline unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
+{
+/* XXX: Could include qemu/timer.h to get NANOSECONDS_PER_SECOND? */
+const unsigned int ns_per_s = 1000 * 1000 * 1000;
+return ns_per_s > cpu->gt_cntfrq ? ns_per_s / cpu->gt_cntfrq : 1;
+}
+
 void arm_cpu_post_init(Object *obj);
 
 uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 65c4441a3896..1cc0551081a0 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2409,7 +2409,9 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
 
 static uint64_t gt_get_countervalue(CPUARMState *env)
 {
-return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+ARMCPU *cpu = env_archcpu(env);
+
+return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
 }
 
 static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
@@ -2445,7 +2447,7 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * set the timer for as far in the future as possible. When the
  * timer expires we will reset the timer for any remaining period.
  */
-if (nexttick > INT64_MAX / GTIMER_SCALE) {
+if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {
 timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
 } else {
 timer_mod(cpu->gt_timer[timeridx], nexttick);
@@ -2874,11 +2876,13 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 
 static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
 {
+ARMCPU *cpu = env_archcpu(env);
+
 /* Currently we have no support for QEMUTimer in linux-user so we
  * can't call gt_get_countervalue(env), instead we directly
  * call the lower level functions.
  */
-return cpu_get_clock() / GTIMER_SCALE;
+return cpu_get_clock() / gt_cntfrq_period(cpu);
 }
 
 static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
-- 
2.20.1




[PATCH 4/4] ast2600: Configure CNTFRQ at 1125MHz

2019-11-27 Thread Andrew Jeffery
This matches the configuration set by u-boot on the AST2600.

Signed-off-by: Andrew Jeffery 
---
 hw/arm/aspeed_ast2600.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 931887ac681f..5aecc3b3caec 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -259,6 +259,9 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, 
Error **errp)
 object_property_set_int(OBJECT(>cpu[i]), aspeed_calc_affinity(i),
 "mp-affinity", _abort);
 
+object_property_set_int(OBJECT(>cpu[i]), 112500, "cntfrq",
+_abort);
+
 /*
  * TODO: the secondary CPUs are started and a boot helper
  * is needed when using -kernel
-- 
2.20.1




[PATCH 1/4] target/arm: Remove redundant scaling of nexttick

2019-11-27 Thread Andrew Jeffery
The corner-case codepath was adjusting nexttick such that overflow
wouldn't occur when timer_mod() scaled the value back up. Remove a use
of GTIMER_SCALE and avoid unnecessary operations by calling
timer_mod_ns() directly.

Signed-off-by: Andrew Jeffery 
---
 target/arm/helper.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index a089fb5a6909..65c4441a3896 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2446,9 +2446,10 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * timer expires we will reset the timer for any remaining period.
  */
 if (nexttick > INT64_MAX / GTIMER_SCALE) {
-nexttick = INT64_MAX / GTIMER_SCALE;
+timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
+} else {
+timer_mod(cpu->gt_timer[timeridx], nexttick);
 }
-timer_mod(cpu->gt_timer[timeridx], nexttick);
 trace_arm_gt_recalc(timeridx, irqstate, nexttick);
 } else {
 /* Timer disabled: ISTATUS and timer output always clear */
-- 
2.20.1




Re: [Qemu-devel] [PATCH v5] target-arm: Make the counter tick relative to cntfrq

2019-09-20 Thread Andrew Jeffery



On Wed, 18 Sep 2019, at 04:55, Richard Henderson wrote:
> On 9/17/19 12:14 PM, Peter Maydell wrote:
> >> +static Property arm_cpu_gt_cntfrq_property =
> >> +DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq,
> >> +   (1000 * 1000 * 1000) / GTIMER_SCALE);
> > I think it would be helpful to have a comment saynig what units
> > this property is in.
> > 
> 
> Should this be NANOSECONDS_PER_SECOND?
> It's certainly a suspicious use of 1e9 otherwise.

You're right that it should be NANOSECONDS_PER_SECOND but
this was just code motion of the definition of the reset value for
CNTFRQ_EL0 in target/arm/helper.c.

Andrew



Re: [PATCH v5] target-arm: Make the counter tick relative to cntfrq

2019-09-20 Thread Andrew Jeffery



On Wed, 18 Sep 2019, at 01:44, Peter Maydell wrote:
> On Thu, 12 Sep 2019 at 07:56, Andrew Jeffery  wrote:
> > diff --git a/target/arm/helper.c b/target/arm/helper.c
> > index 507026c9154b..09975704d47f 100644
> > --- a/target/arm/helper.c
> > +++ b/target/arm/helper.c
> > @@ -2409,7 +2409,21 @@ static CPAccessResult gt_stimer_access(CPUARMState 
> > *env,
> >
> >  static uint64_t gt_get_countervalue(CPUARMState *env)
> >  {
> > -return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
> > +uint64_t effective;
> > +
> > +/*
> > + * Deal with quantized clock scaling by calculating the effective 
> > frequency
> > + * in terms of the timer scale.
> > + */
> > +if (env->cp15.c14_cntfrq <= NANOSECONDS_PER_SECOND) {
> > +uint32_t scale = NANOSECONDS_PER_SECOND / env->cp15.c14_cntfrq;
> > +effective = NANOSECONDS_PER_SECOND / scale;
> > +} else {
> > +effective = NANOSECONDS_PER_SECOND;
> > +}
> 
> What is this doing, and why didn't we need to do it before?

I'll fix all of your other comments, but I think this question in particular is 
best
answered by turning the patch into a short series. It's a bit of a complex 
story.
I'll try to split what's going on into smaller steps so what I've done above is
better documented. The short story is there's asymmetry between converting
time to ticks and ticks to time that leads us to schedule timers in the past for
most CNTFRQ values if we don't do something like the above.

Andrew



Re: [PATCH 03/21] hw: aspeed_scu: Add AST2600 support

2019-09-19 Thread Andrew Jeffery



On Thu, 19 Sep 2019, at 15:19, Cédric Le Goater wrote:
> From: Joel Stanley 
> 
> The SCU controller on the AST2600 SoC has extra registers. Increase
> the number of regs of the model and introduce a new field in the class
> to customize the MemoryRegion operations depending on the SoC model.
> 
> Signed-off-by: Joel Stanley 
> [clg: - improved commit log
>   - changed vmstate version
>   - reworked model integration into new objet class ]
> Signed-off-by: Cédric Le Goater 
> ---
>  include/hw/misc/aspeed_scu.h |   7 +-
>  hw/misc/aspeed_scu.c | 190 +--
>  2 files changed, 189 insertions(+), 8 deletions(-)

...

> +static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, 
> uint64_t data,
> + unsigned size)
> +{
> +AspeedSCUState *s = ASPEED_SCU(opaque);
> +int reg = TO_REG(offset);
> +
> +if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "%s: Out-of-bounds write at offset 0x%" 
> HWADDR_PRIx "\n",
> +  __func__, offset);
> +return;
> +}
> +
> +if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", 
> __func__);
> +}
> +
> +trace_aspeed_scu_write(offset, size, data);
> +
> +switch (reg) {
> +case AST2600_PROT_KEY:
> +s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
> +return;
> +case AST2600_HW_STRAP1:
> +case AST2600_HW_STRAP2:
> +if (s->regs[reg + 2]) {
> +return;
> +}
> +/* fall through */
> +case AST2600_SYS_RST_CTRL:
> +case AST2600_SYS_RST_CTRL2:
> +/* W1S (Write 1 to set) registers */
> +s->regs[reg] |= data;
> +return;
> +case AST2600_SYS_RST_CTRL_CLR:
> +case AST2600_SYS_RST_CTRL2_CLR:
> +case AST2600_HW_STRAP1_CLR:
> +case AST2600_HW_STRAP2_CLR:
> +/* W1C (Write 1 to clear) registers */
> +s->regs[reg] &= ~data;

This clear should respect the protection register for each strap case.

Andrew



Re: [Qemu-devel] [PATCH 00/21] aspeed: Add support for the AST2600 SoC

2019-09-19 Thread Andrew Jeffery



On Fri, 20 Sep 2019, at 06:26, no-re...@patchew.org wrote:
> Patchew URL: https://patchew.org/QEMU/20190919055002.6729-1-...@kaod.org/
> 
> 
> 
> Hi,
> 
> This series failed the docker-quick@centos7 build test. Please find the 
> testing commands and
> their output below. If you have Docker installed, you can probably 
> reproduce it
> locally.
> 
> === TEST SCRIPT BEGIN ===
> #!/bin/bash
> make docker-image-centos7 V=1 NETWORK=1
> time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
> === TEST SCRIPT END ===
> 
> libudev   no
> default devices   yes
> 
> warning: Python 2 support is deprecated
> warning: Python 3 will be required for building future versions of QEMU
> cross containers  no
> 
> NOTE: guest cross-compilers enabled: cc
> ---
> Property '.cntfrq' not found

Ah, we should drop the patch introducing the CNTFRQ configuration for the 2600
as well given the patch adding support to configure it isn't part of the series.

Andrew



[Qemu-devel] [PATCH v5] target-arm: Make the counter tick relative to cntfrq

2019-09-12 Thread Andrew Jeffery
Allow machines to configure CNTFRQ via a property if the ARM core
supports the generic timer. This is necessary on e.g. the ASPEED AST2600
SoC where the generic timer clock is run at 800MHz or above. The default
value for CNTFRQ remains at 62.50MHz (based on GTIMER_SCALE).

CNTFRQ is a read-as-written co-processor register; the property sets the
register's initial value which is used during realize() to configure the
QEMUTimers that back the generic timers. Beyond that the firmware can to
do whatever it sees fit with the CNTFRQ register though changes to the
value will not be reflected in the timers' rate.

I've tested this using an out-of-tree AST2600 SoC model (Cortex-A7) with
the SDK u-boot that sets CNTFRQ as appropriate, and by starting/running
machines with assorted ARM CPUs (palmetto-bmc with the ARM926EJ-S,
romulus-bmc with the ARM1176 and raspi2 with the Cortex-A53).

Signed-off-by: Andrew Jeffery 
---
v5: Remove unrelated submodule updates that snuck into v4

v4: https://patchwork.ozlabs.org/patch/1161340/
Fix configuration for cores without a generic timer

v3: https://patchwork.ozlabs.org/patch/1160634/
Peter - I think this addresses most of your feedback. I still reach into
the QEMUTimer to fetch out scale when adjusting the nexttick
calculation, but we no longer need to update the scale member and force
a recalculation of the period.

v2: https://patchwork.ozlabs.org/patch/1144389/
Signed-off-by: Andrew Jeffery 
---
 target/arm/cpu.c| 43 +++
 target/arm/cpu.h|  3 +++
 target/arm/helper.c | 30 ++
 3 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 2399c144718d..8b63a27761bb 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -40,6 +40,8 @@
 #include "disas/capstone.h"
 #include "fpu/softfloat.h"
 
+#include 
+
 static void arm_cpu_set_pc(CPUState *cs, vaddr value)
 {
 ARMCPU *cpu = ARM_CPU(cs);
@@ -976,6 +978,10 @@ static void arm_cpu_initfn(Object *obj)
 }
 }
 
+static Property arm_cpu_gt_cntfrq_property =
+DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq,
+   (1000 * 1000 * 1000) / GTIMER_SCALE);
+
 static Property arm_cpu_reset_cbar_property =
 DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
 
@@ -1172,6 +1178,11 @@ void arm_cpu_post_init(Object *obj)
 
 qdev_property_add_static(DEVICE(obj), _cpu_cfgend_property,
  _abort);
+
+if (arm_feature(>env, ARM_FEATURE_GENERIC_TIMER)) {
+qdev_property_add_static(DEVICE(cpu), _cpu_gt_cntfrq_property,
+ _abort);
+}
 }
 
 static void arm_cpu_finalizefn(Object *obj)
@@ -1238,14 +1249,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
-cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_ptimer_cb, cpu);
-cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_vtimer_cb, cpu);
-cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_htimer_cb, cpu);
-cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_stimer_cb, cpu);
+
+{
+uint64_t scale;
+
+if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
+if (!cpu->gt_cntfrq) {
+error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
+   cpu->gt_cntfrq);
+return;
+}
+scale = MAX(1, NANOSECONDS_PER_SECOND / cpu->gt_cntfrq);
+} else {
+scale = GTIMER_SCALE;
+}
+
+cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_ptimer_cb, cpu);
+cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_vtimer_cb, cpu);
+cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_htimer_cb, cpu);
+cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_stimer_cb, cpu);
+}
 #endif
 
 cpu_exec_realizefn(cs, _err);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 297ad5e47ad8..8bd576f834ba 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -915,6 +915,9 @@ struct ARMCPU {
 
 /* Used to set the maximum vector length the cpu will support.  */
 uint32_t sve_max_vq;
+
+/* Used to configure the generic timer input clock */
+uint64_t gt_cntfrq;
 };
 
 void arm_cpu_post_init(Object *obj);
diff --git 

Re: [Qemu-devel] [PATCH v4] target-arm: Make the counter tick relative to cntfrq

2019-09-12 Thread Andrew Jeffery



On Thu, 12 Sep 2019, at 15:52, Cédric Le Goater wrote:
> On 12/09/2019 05:25, Andrew Jeffery wrote:
> > Allow machines to configure CNTFRQ via a property if the ARM core
> > supports the generic timer. This is necessary on e.g. the ASPEED AST2600
> > SoC where the generic timer clock is run at 800MHz or above. The default
> > value for CNTFRQ remains at 62.50MHz (based on GTIMER_SCALE).
> > 
> > CNTFRQ is a read-as-written co-processor register; the property sets the
> > register's initial value which is used during realize() to configure the
> > QEMUTimers that back the generic timers. Beyond that the firmware can to
> > do whatever it sees fit with the CNTFRQ register though changes to the
> > value will not be reflected in the timers' rate.
> > 
> > I've tested this using an out-of-tree AST2600 SoC model (Cortex-A7) with
> > the SDK u-boot that sets CNTFRQ as appropriate, and by starting/running
> > machines with assorted ARM CPUs (palmetto-bmc with the ARM926EJ-S,
> > romulus-bmc with the ARM1176 and raspi2 with the Cortex-A53).
> > 
> > Signed-off-by: Andrew Jeffery 
> > ---
> > v4: Fix configuration for cores without a generic timer
> > 
> > v3: https://patchwork.ozlabs.org/patch/1160634/
> > Peter - I think this addresses most of your feedback. I still reach into
> > the QEMUTimer to fetch out scale when adjusting the nexttick
> > calculation, but we no longer need to update the scale member and force
> > a recalculation of the period.
> > 
> > v2: https://patchwork.ozlabs.org/patch/1144389/
> > ---
> >  roms/SLOF   |  2 +-
> >  roms/skiboot|  2 +-
> >  target/arm/cpu.c| 43 +++
> >  target/arm/cpu.h|  3 +++
> >  target/arm/helper.c | 30 ++
> >  5 files changed, 66 insertions(+), 14 deletions(-)
> > 
> > diff --git a/roms/SLOF b/roms/SLOF
> > index 7bfe584e3219..ea221600a116 16
> > --- a/roms/SLOF
> > +++ b/roms/SLOF
> > @@ -1 +1 @@
> > -Subproject commit 7bfe584e321946771692711ff83ad2b5850daca7
> > +Subproject commit ea221600a116883137ef90b2b7ab7d2472bc4f10
> > diff --git a/roms/skiboot b/roms/skiboot
> > index 261ca8e779e5..3a6fdede6ce1 16
> > --- a/roms/skiboot
> > +++ b/roms/skiboot
> > @@ -1 +1 @@
> > -Subproject commit 261ca8e779e5138869a45f174caa49be6a274501
> > +Subproject commit 3a6fdede6ce117facec0108afe716cf5d0472c3f
> 
> 
> The changes above seem not related.

How did they get in there? :eyeroll:

Thanks. v5 I guess.

Andrew



[Qemu-devel] [PATCH v4] target-arm: Make the counter tick relative to cntfrq

2019-09-11 Thread Andrew Jeffery
Allow machines to configure CNTFRQ via a property if the ARM core
supports the generic timer. This is necessary on e.g. the ASPEED AST2600
SoC where the generic timer clock is run at 800MHz or above. The default
value for CNTFRQ remains at 62.50MHz (based on GTIMER_SCALE).

CNTFRQ is a read-as-written co-processor register; the property sets the
register's initial value which is used during realize() to configure the
QEMUTimers that back the generic timers. Beyond that the firmware can to
do whatever it sees fit with the CNTFRQ register though changes to the
value will not be reflected in the timers' rate.

I've tested this using an out-of-tree AST2600 SoC model (Cortex-A7) with
the SDK u-boot that sets CNTFRQ as appropriate, and by starting/running
machines with assorted ARM CPUs (palmetto-bmc with the ARM926EJ-S,
romulus-bmc with the ARM1176 and raspi2 with the Cortex-A53).

Signed-off-by: Andrew Jeffery 
---
v4: Fix configuration for cores without a generic timer

v3: https://patchwork.ozlabs.org/patch/1160634/
Peter - I think this addresses most of your feedback. I still reach into
the QEMUTimer to fetch out scale when adjusting the nexttick
calculation, but we no longer need to update the scale member and force
a recalculation of the period.

v2: https://patchwork.ozlabs.org/patch/1144389/
---
 roms/SLOF   |  2 +-
 roms/skiboot|  2 +-
 target/arm/cpu.c| 43 +++
 target/arm/cpu.h|  3 +++
 target/arm/helper.c | 30 ++
 5 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/roms/SLOF b/roms/SLOF
index 7bfe584e3219..ea221600a116 16
--- a/roms/SLOF
+++ b/roms/SLOF
@@ -1 +1 @@
-Subproject commit 7bfe584e321946771692711ff83ad2b5850daca7
+Subproject commit ea221600a116883137ef90b2b7ab7d2472bc4f10
diff --git a/roms/skiboot b/roms/skiboot
index 261ca8e779e5..3a6fdede6ce1 16
--- a/roms/skiboot
+++ b/roms/skiboot
@@ -1 +1 @@
-Subproject commit 261ca8e779e5138869a45f174caa49be6a274501
+Subproject commit 3a6fdede6ce117facec0108afe716cf5d0472c3f
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 2399c144718d..8b63a27761bb 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -40,6 +40,8 @@
 #include "disas/capstone.h"
 #include "fpu/softfloat.h"
 
+#include 
+
 static void arm_cpu_set_pc(CPUState *cs, vaddr value)
 {
 ARMCPU *cpu = ARM_CPU(cs);
@@ -976,6 +978,10 @@ static void arm_cpu_initfn(Object *obj)
 }
 }
 
+static Property arm_cpu_gt_cntfrq_property =
+DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq,
+   (1000 * 1000 * 1000) / GTIMER_SCALE);
+
 static Property arm_cpu_reset_cbar_property =
 DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
 
@@ -1172,6 +1178,11 @@ void arm_cpu_post_init(Object *obj)
 
 qdev_property_add_static(DEVICE(obj), _cpu_cfgend_property,
  _abort);
+
+if (arm_feature(>env, ARM_FEATURE_GENERIC_TIMER)) {
+qdev_property_add_static(DEVICE(cpu), _cpu_gt_cntfrq_property,
+ _abort);
+}
 }
 
 static void arm_cpu_finalizefn(Object *obj)
@@ -1238,14 +1249,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
-cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_ptimer_cb, cpu);
-cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_vtimer_cb, cpu);
-cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_htimer_cb, cpu);
-cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_stimer_cb, cpu);
+
+{
+uint64_t scale;
+
+if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
+if (!cpu->gt_cntfrq) {
+error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
+   cpu->gt_cntfrq);
+return;
+}
+scale = MAX(1, NANOSECONDS_PER_SECOND / cpu->gt_cntfrq);
+} else {
+scale = GTIMER_SCALE;
+}
+
+cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_ptimer_cb, cpu);
+cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_vtimer_cb, cpu);
+cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_htimer_cb, cpu);
+cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_stimer_cb, cpu);
+}
 #endif
 
 cpu_exec_realizefn(cs,

Re: [Qemu-devel] [PATCH v3] target-arm: Make the counter tick relative to cntfrq

2019-09-11 Thread Andrew Jeffery



On Wed, 11 Sep 2019, at 15:40, no-re...@patchew.org wrote:
> Patchew URL: https://patchew.org/QEMU/20190911034302.29108-1-and...@aj.id.au/
> 
> 
> 
> Hi,
> 
> This series failed the docker-quick@centos7 build test. Please find the 
> testing commands and
> their output below. If you have Docker installed, you can probably 
> reproduce it
> locally.

Disregard v3, I got distracted by some updates to the way ASPEED's u-boot 
configures
CNTFRQ and didn't test some relevant cases.

Sorry for the noise.

Andrew



[Qemu-devel] [PATCH v3] target-arm: Make the counter tick relative to cntfrq

2019-09-10 Thread Andrew Jeffery
Allow machines to configure CNTFRQ via a property if the ARM core
supports the generic timer. This is necessary on e.g. the ASPEED AST2600
SoC where the generic timer clock is run at 800MHz or above.

CNTFRQ is a read-as-written co-processor register; the property sets the
register's initial value which is used during realize() to configure the
QEMUTimers that back the generic timers. Beyond that the firmware can to
do whatever it sees fit with the CNTFRQ register though changes to the
value will not be reflected in the timers' rate.

Signed-off-by: Andrew Jeffery 
---
Peter - I think this addresses most of your feedback. I still reach into
the QEMUTimer to fetch out scale when adjusting the nexttick
calculation, but we no longer need to update the scale member and force
a recalculation of the period.
---
 target/arm/cpu.c| 36 
 target/arm/helper.c | 20 +---
 2 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 2399c144718d..7ac422729608 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -40,6 +40,8 @@
 #include "disas/capstone.h"
 #include "fpu/softfloat.h"
 
+#include 
+
 static void arm_cpu_set_pc(CPUState *cs, vaddr value)
 {
 ARMCPU *cpu = ARM_CPU(cs);
@@ -976,6 +978,10 @@ static void arm_cpu_initfn(Object *obj)
 }
 }
 
+static Property arm_cpu_cp_cntfrq_property =
+DEFINE_PROP_UINT64("cntfrq", ARMCPU, env.cp15.c14_cntfrq,
+   (1000 * 1000 * 1000) / GTIMER_SCALE);
+
 static Property arm_cpu_reset_cbar_property =
 DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
 
@@ -1172,6 +1178,11 @@ void arm_cpu_post_init(Object *obj)
 
 qdev_property_add_static(DEVICE(obj), _cpu_cfgend_property,
  _abort);
+
+if (arm_feature(>env, ARM_FEATURE_GENERIC_TIMER)) {
+qdev_property_add_static(DEVICE(cpu), _cpu_cp_cntfrq_property,
+ _abort);
+}
 }
 
 static void arm_cpu_finalizefn(Object *obj)
@@ -1238,14 +1249,23 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
-cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_ptimer_cb, cpu);
-cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-   arm_gt_vtimer_cb, cpu);
-cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_htimer_cb, cpu);
-cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
-  arm_gt_stimer_cb, cpu);
+if (!env->cp15.c14_cntfrq) {
+error_setg(errp, "Invalid CNTFRQ: %"PRIx64"Hz", env->cp15.c14_cntfrq);
+return;
+}
+
+{
+uint64_t scale = MAX(1, NANOSECONDS_PER_SECOND / env->cp15.c14_cntfrq);
+
+cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_ptimer_cb, cpu);
+cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+   arm_gt_vtimer_cb, cpu);
+cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_htimer_cb, cpu);
+cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
+  arm_gt_stimer_cb, cpu);
+}
 #endif
 
 cpu_exec_realizefn(cs, _err);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 507026c9154b..8783f92c718c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2409,7 +2409,21 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
 
 static uint64_t gt_get_countervalue(CPUARMState *env)
 {
-return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+uint64_t effective;
+
+/*
+ * Deal with quantized clock scaling by calculating the effective frequency
+ * in terms of the timer scale.
+ */
+if (env->cp15.c14_cntfrq <= NANOSECONDS_PER_SECOND) {
+uint32_t scale = NANOSECONDS_PER_SECOND / env->cp15.c14_cntfrq;
+effective = NANOSECONDS_PER_SECOND / scale;
+} else {
+effective = NANOSECONDS_PER_SECOND;
+}
+
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), effective,
+NANOSECONDS_PER_SECOND);
 }
 
 static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
@@ -2445,8 +2459,8 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * set the timer for as far in the future as possible. When the
  * timer expires we will reset the timer for any remaining period.
  */
-if (nexttick > INT64_MAX / GTIMER_SCALE) {
-   

Re: [Qemu-devel] [PATCH v2] target-arm: Make the counter tick relative to cntfrq

2019-08-28 Thread Andrew Jeffery



On Thu, 29 Aug 2019, at 11:08, Andrew Jeffery wrote:
> 
> 
> On Wed, 28 Aug 2019, at 01:39, Peter Maydell wrote:
> > On Fri, 9 Aug 2019 at 06:43, Andrew Jeffery  wrote:
> > >
> > > The use of GTIMER_SCALE assumes the clock feeding the generic timer is
> > > 62.5MHz for all platforms. This is untrue in general, for example the
> > > ASPEED AST2600 feeds the counter with either an 800 or 1200MHz clock,
> > > and CNTFRQ is configured appropriately by u-boot.
> > >
> > > To cope with these values we need to take care of the quantization
> > > caused by the clock scaling in terms of nanoseconds per clock by
> > > calculating an effective frequency such that NANOSECONDS_PER_SECOND is
> > > an integer multiple of the effective frequency. Failing to account for
> > > the quantisation leads to sticky behaviour in the VM as the guest timer
> > > subsystems account for the difference between delay time and the counter
> > > value.
> > >
> > > Signed-off-by: Andrew Jeffery 
> > > ---
> > > v2:
> > > 1. Removed the user-mode change that broke v1
> > > 2. Rearranged the implementation as a consequence of 1.
> > >
> > >  target/arm/helper.c | 51 ++---
> > >  1 file changed, 48 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/target/arm/helper.c b/target/arm/helper.c
> > > index b74c23a9bc08..166a54daf278 100644
> > > --- a/target/arm/helper.c
> > > +++ b/target/arm/helper.c
> > > @@ -2277,6 +2277,34 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
> > >
> > >  #ifndef CONFIG_USER_ONLY
> > >
> > > +static void gt_recalc_timer(ARMCPU *cpu, int timeridx);
> > > +static void gt_cntfrq_write(CPUARMState *env, const ARMCPRegInfo *ri,
> > > +uint64_t value)
> > > +{
> > > +uint64_t scale;
> > > +ARMCPU *cpu;
> > > +int i;
> > > +
> > > +raw_write(env, ri, value);
> > > +
> > > +/* Fix up the timer scaling */
> > > +cpu = env_archcpu(env);
> > > +scale = MAX(1, NANOSECONDS_PER_SECOND / value);
> > > +for (i = 0; i < NUM_GTIMERS; i++) {
> > > +if (!cpu->gt_timer[i]) {
> > > +continue;
> > > +}
> > > +
> > > +cpu->gt_timer[i]->scale = scale;
> > 
> > Reaching into the internals of a QEMUTimer and changing
> > the 'scale' value seems like a bad idea. If QEMUTimer doesn't
> > have a facility for changing the frequency and we need one
> > then we should add one at that API layer.
> 
> Yeah, fair point. It is an RFC patch

Ugh, I just looked at the subject and realised I hadn't added "RFC".

Too many things going on :/

Andrew



Re: [Qemu-devel] [PATCH v2] target-arm: Make the counter tick relative to cntfrq

2019-08-28 Thread Andrew Jeffery



On Wed, 28 Aug 2019, at 01:39, Peter Maydell wrote:
> On Fri, 9 Aug 2019 at 06:43, Andrew Jeffery  wrote:
> >
> > The use of GTIMER_SCALE assumes the clock feeding the generic timer is
> > 62.5MHz for all platforms. This is untrue in general, for example the
> > ASPEED AST2600 feeds the counter with either an 800 or 1200MHz clock,
> > and CNTFRQ is configured appropriately by u-boot.
> >
> > To cope with these values we need to take care of the quantization
> > caused by the clock scaling in terms of nanoseconds per clock by
> > calculating an effective frequency such that NANOSECONDS_PER_SECOND is
> > an integer multiple of the effective frequency. Failing to account for
> > the quantisation leads to sticky behaviour in the VM as the guest timer
> > subsystems account for the difference between delay time and the counter
> > value.
> >
> > Signed-off-by: Andrew Jeffery 
> > ---
> > v2:
> > 1. Removed the user-mode change that broke v1
> > 2. Rearranged the implementation as a consequence of 1.
> >
> >  target/arm/helper.c | 51 ++---
> >  1 file changed, 48 insertions(+), 3 deletions(-)
> >
> > diff --git a/target/arm/helper.c b/target/arm/helper.c
> > index b74c23a9bc08..166a54daf278 100644
> > --- a/target/arm/helper.c
> > +++ b/target/arm/helper.c
> > @@ -2277,6 +2277,34 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
> >
> >  #ifndef CONFIG_USER_ONLY
> >
> > +static void gt_recalc_timer(ARMCPU *cpu, int timeridx);
> > +static void gt_cntfrq_write(CPUARMState *env, const ARMCPRegInfo *ri,
> > +uint64_t value)
> > +{
> > +uint64_t scale;
> > +ARMCPU *cpu;
> > +int i;
> > +
> > +raw_write(env, ri, value);
> > +
> > +/* Fix up the timer scaling */
> > +cpu = env_archcpu(env);
> > +scale = MAX(1, NANOSECONDS_PER_SECOND / value);
> > +for (i = 0; i < NUM_GTIMERS; i++) {
> > +if (!cpu->gt_timer[i]) {
> > +continue;
> > +}
> > +
> > +cpu->gt_timer[i]->scale = scale;
> 
> Reaching into the internals of a QEMUTimer and changing
> the 'scale' value seems like a bad idea. If QEMUTimer doesn't
> have a facility for changing the frequency and we need one
> then we should add one at that API layer.

Yeah, fair point. It is an RFC patch for these kinds of reasons -
I solved the problem but wasn't at all convinced about the
shape of the solution.

> 
> Also, this isn't how the hardware works, I'm pretty sure.
> In hardware the timers tick at whatever frequency they're
> set up to tick, and CNTFRQ is just a reads-as-written register
> that firmware can fill in with an appropriate value that it's
> determined from somewhere for the benefit of other software.

Yes, I think you're right. Again, as above this got rid of the
problem, but needed some massaging. The write just was a
handy hook point to inject the change of frequency.

> 
> If on ASPEED SoCs the timer frequency is different, then we
> should model that by having CPU properties for timer frequency
> and having the SoC set those properties, I think.

Sounds good, I'll work on that approach.

Thanks for the feedback.

Andrew



Re: [Qemu-devel] [PATCH v9 01/11] hw/arm: simplify arm_load_dtb

2019-08-13 Thread Andrew Jeffery



On Wed, 14 Aug 2019, at 07:30, Alistair Francis wrote:
> On Fri, Aug 9, 2019 at 12:01 AM Tao  wrote:
> >
> > From: Tao Xu 
> >
> > In struct arm_boot_info, kernel_filename, initrd_filename and
> > kernel_cmdline are copied from from MachineState. This patch add
> > MachineState as a parameter into arm_load_dtb() and move the copy chunk
> > of kernel_filename, initrd_filename and kernel_cmdline into
> > arm_load_kernel().
> >
> > Reviewed-by: Igor Mammedov 
> > Reviewed-by: Liu Jingqi 
> > Suggested-by: Igor Mammedov 
> > Signed-off-by: Tao Xu 
> 
> Reviewed-by: Alistair Francis 
> 
> Alistair
> 
> > ---
> >
> > No changes in v9
> > ---
> >  hw/arm/aspeed.c   |  5 +

For the ASPEED machines:

Acked-by: Andrew Jeffery 



[Qemu-devel] [PATCH v2] target-arm: Make the counter tick relative to cntfrq

2019-08-08 Thread Andrew Jeffery
The use of GTIMER_SCALE assumes the clock feeding the generic timer is
62.5MHz for all platforms. This is untrue in general, for example the
ASPEED AST2600 feeds the counter with either an 800 or 1200MHz clock,
and CNTFRQ is configured appropriately by u-boot.

To cope with these values we need to take care of the quantization
caused by the clock scaling in terms of nanoseconds per clock by
calculating an effective frequency such that NANOSECONDS_PER_SECOND is
an integer multiple of the effective frequency. Failing to account for
the quantisation leads to sticky behaviour in the VM as the guest timer
subsystems account for the difference between delay time and the counter
value.

Signed-off-by: Andrew Jeffery 
---
v2:
1. Removed the user-mode change that broke v1
2. Rearranged the implementation as a consequence of 1.

 target/arm/helper.c | 51 ++---
 1 file changed, 48 insertions(+), 3 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index b74c23a9bc08..166a54daf278 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2277,6 +2277,34 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
 
 #ifndef CONFIG_USER_ONLY
 
+static void gt_recalc_timer(ARMCPU *cpu, int timeridx);
+static void gt_cntfrq_write(CPUARMState *env, const ARMCPRegInfo *ri,
+uint64_t value)
+{
+uint64_t scale;
+ARMCPU *cpu;
+int i;
+
+raw_write(env, ri, value);
+
+/* Fix up the timer scaling */
+cpu = env_archcpu(env);
+scale = MAX(1, NANOSECONDS_PER_SECOND / value);
+for (i = 0; i < NUM_GTIMERS; i++) {
+if (!cpu->gt_timer[i]) {
+continue;
+}
+
+cpu->gt_timer[i]->scale = scale;
+gt_recalc_timer(cpu, i);
+}
+}
+
+static void gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
+{
+gt_cntfrq_write(env, opaque, opaque->resetvalue);
+}
+
 static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo 
*ri,
bool isread)
 {
@@ -2407,7 +2435,21 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
 
 static uint64_t gt_get_countervalue(CPUARMState *env)
 {
-return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+uint64_t effective;
+
+/*
+ * Deal with quantized clock scaling by calculating the effective frequency
+ * in terms of the timer scale.
+ */
+if (env->cp15.c14_cntfrq <= NANOSECONDS_PER_SECOND) {
+uint32_t scale = NANOSECONDS_PER_SECOND / env->cp15.c14_cntfrq;
+effective = NANOSECONDS_PER_SECOND / scale;
+} else {
+effective = NANOSECONDS_PER_SECOND;
+}
+
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), effective,
+NANOSECONDS_PER_SECOND);
 }
 
 static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
@@ -2443,8 +2485,8 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * set the timer for as far in the future as possible. When the
  * timer expires we will reset the timer for any remaining period.
  */
-if (nexttick > INT64_MAX / GTIMER_SCALE) {
-nexttick = INT64_MAX / GTIMER_SCALE;
+if (nexttick > INT64_MAX / cpu->gt_timer[timeridx]->scale) {
+nexttick = INT64_MAX / cpu->gt_timer[timeridx]->scale;
 }
 timer_mod(cpu->gt_timer[timeridx], nexttick);
 trace_arm_gt_recalc(timeridx, irqstate, nexttick);
@@ -2686,13 +2728,16 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 { .name = "CNTFRQ", .cp = 15, .crn = 14, .crm = 0, .opc1 = 0, .opc2 = 0,
   .type = ARM_CP_ALIAS,
   .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
+  .writefn = gt_cntfrq_write,
   .fieldoffset = offsetoflow32(CPUARMState, cp15.c14_cntfrq),
 },
 { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
   .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
   .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
+  .writefn = gt_cntfrq_write,
   .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
   .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE,
+  .resetfn = gt_cntfrq_reset,
 },
 /* overall control: mostly access permissions */
 { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH,
-- 
2.20.1




Re: [Qemu-devel] [PATCH] target-arm: Make the counter tick relative to cntfrq

2019-08-08 Thread Andrew Jeffery



On Fri, 9 Aug 2019, at 13:36, no-re...@patchew.org wrote:
> Patchew URL: https://patchew.org/QEMU/20190809031321.14760-1-and...@aj.id.au/
> 
> 
> 
> Hi,
> 
> This series failed build test on s390x host. Please find the details below.
> 
> === TEST SCRIPT BEGIN ===
> #!/bin/bash
> # Testing script will be invoked under the git checkout with
> # HEAD pointing to a commit that has the patches applied on top of "base"
> # branch
> set -e
> 
> echo
> echo "=== ENV ==="
> env
> 
> echo
> echo "=== PACKAGES ==="
> rpm -qa
> 
> echo
> echo "=== UNAME ==="
> uname -a
> 
> CC=$HOME/bin/cc
> INSTALL=$PWD/install
> BUILD=$PWD/build
> mkdir -p $BUILD $INSTALL
> SRC=$PWD
> cd $BUILD
> $SRC/configure --cc=$CC --prefix=$INSTALL
> make -j4
> # XXX: we need reliable clean up
> # make check -j4 V=1
> make install
> === TEST SCRIPT END ===
> 
>   CC  aarch64_be-linux-user/target/arm/arm-semi.o
>   CC  aarch64_be-linux-user/target/arm/helper.o
> /var/tmp/patchew-tester-tmp-hkd7ua1n/src/target/arm/helper.c: In 
> function ‘gt_virt_cnt_read’:
> /var/tmp/patchew-tester-tmp-hkd7ua1n/src/target/arm/helper.c:2921:12: 
> error: implicit declaration of function ‘gt_calc_tick’ 
> [-Werror=implicit-function-declaration]
>  2921 | return gt_calc_tick(env, cpu_get_clock());
>   |^~~~
> /var/tmp/patchew-tester-tmp-hkd7ua1n/src/target/arm/helper.c:2921:12: 
> error: nested extern declaration of ‘gt_calc_tick’ 
> [-Werror=nested-externs]
> cc1: all warnings being treated as errors
> make[1]: *** [/var/tmp/patchew-tester-tmp-hkd7ua1n/src/rules.mak:69: 
> target/arm/helper.o] Error 1
> make: *** [Makefile:472: aarch64_be-linux-user/all] Error 2
> 

Ah, I missed that I put the implementation inside the
#ifndef CONFIG_USER_ONLY` block. Maybe we can just not do the scaling
for userspace anyway?

Andrew



[Qemu-devel] [PATCH] target-arm: Make the counter tick relative to cntfrq

2019-08-08 Thread Andrew Jeffery
The use of GTIMER_SCALE assumes the clock feeding the generic timer is
62.5MHz for all platforms. This is untrue in general, for example the
ASPEED AST2600 feeds the counter with either an 800 or 1200MHz clock,
and CNTFRQ is configured appropriately by u-boot.

To cope with these values we need to take care of the quantization
caused by the clock scaling in terms of nanoseconds per clock by
calculating an effective frequency such that NANOSECONDS_PER_SECOND is
an integer multiple of the effective frequency. Failing to account for
the quantisation leads to sticky behaviour in the VM as the guest timer
subsystems account for the difference between delay time and the counter
value.

Signed-off-by: Andrew Jeffery 
---
The timer rate assumptions seemed unusual, so I'm not sure if this patch is way
off-base or not. However it does make the AST2600 u-boot and kernel behave
correctly.

 target/arm/helper.c | 51 +
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index b74c23a9bc08..35d14c183630 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2277,6 +2277,34 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
 
 #ifndef CONFIG_USER_ONLY
 
+static void gt_recalc_timer(ARMCPU *cpu, int timeridx);
+static void gt_cntfrq_write(CPUARMState *env, const ARMCPRegInfo *ri,
+uint64_t value)
+{
+uint64_t scale;
+ARMCPU *cpu;
+int i;
+
+raw_write(env, ri, value);
+
+/* Fix up the timer scaling */
+cpu = env_archcpu(env);
+scale = MAX(1, NANOSECONDS_PER_SECOND / value);
+for (i = 0; i < NUM_GTIMERS; i++) {
+if (!cpu->gt_timer[i]) {
+continue;
+}
+
+cpu->gt_timer[i]->scale = scale;
+gt_recalc_timer(cpu, i);
+}
+}
+
+static void gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
+{
+gt_cntfrq_write(env, opaque, opaque->resetvalue);
+}
+
 static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo 
*ri,
bool isread)
 {
@@ -2405,9 +2433,21 @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
 }
 }
 
+static uint64_t gt_calc_tick(CPUARMState *env, uint64_t ns)
+{
+/*
+ * Deal with quantized clock scaling by calculating the effective frequency
+ * in terms of the timer scale.
+ */
+uint32_t scale = MAX(1, NANOSECONDS_PER_SECOND / env->cp15.c14_cntfrq);
+uint64_t effective = NANOSECONDS_PER_SECOND / scale;
+
+return muldiv64(ns, effective, NANOSECONDS_PER_SECOND);
+}
+
 static uint64_t gt_get_countervalue(CPUARMState *env)
 {
-return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+return gt_calc_tick(env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 }
 
 static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
@@ -2443,8 +2483,8 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
  * set the timer for as far in the future as possible. When the
  * timer expires we will reset the timer for any remaining period.
  */
-if (nexttick > INT64_MAX / GTIMER_SCALE) {
-nexttick = INT64_MAX / GTIMER_SCALE;
+if (nexttick > INT64_MAX / cpu->gt_timer[timeridx]->scale) {
+nexttick = INT64_MAX / cpu->gt_timer[timeridx]->scale;
 }
 timer_mod(cpu->gt_timer[timeridx], nexttick);
 trace_arm_gt_recalc(timeridx, irqstate, nexttick);
@@ -2686,13 +2726,16 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
 { .name = "CNTFRQ", .cp = 15, .crn = 14, .crm = 0, .opc1 = 0, .opc2 = 0,
   .type = ARM_CP_ALIAS,
   .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
+  .writefn = gt_cntfrq_write,
   .fieldoffset = offsetoflow32(CPUARMState, cp15.c14_cntfrq),
 },
 { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
   .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
   .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
+  .writefn = gt_cntfrq_write,
   .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
   .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE,
+  .resetfn = gt_cntfrq_reset,
 },
 /* overall control: mostly access permissions */
 { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH,
@@ -2875,7 +2918,7 @@ static uint64_t gt_virt_cnt_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
  * can't call gt_get_countervalue(env), instead we directly
  * call the lower level functions.
  */
-return cpu_get_clock() / GTIMER_SCALE;
+return gt_calc_tick(env, cpu_get_clock());
 }
 
 static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
-- 
2.20.1




Re: [Qemu-devel] [PATCH 1/2] hw/gpio: Add basic Aspeed GPIO model

2019-07-14 Thread Andrew Jeffery



On Mon, 15 Jul 2019, at 12:06, Rashmica Gupta wrote:
> Sorry for the late reply! I agree with most of your feedback and will
> send out
> a v2 shortly with those changes. I have a few replies below
> 
> [snip]
> 
> > > +static const struct AspeedGPIO gpios[0x1f0] = {
> > > +/* Set ABCD */
> > > +[GPIO_ABCD_DATA_VALUE] = {0, read_data_value,
> > > _write_data_value},
> > 
> > Maybe there would be less tedium (and risk of minor bugs) here if we
> > add
> > a table for looking up the read/write callbacks from a type, and just
> > stash
> > the type in struct AspeedGPIO (or a pointer to the corresponding type
> > ops),
> > e.g:
> > 
> > enum gpio_property { gpio_direction = 0, gpio_int_enable, ... };
> > 
> > struct aspeed_gpio_reg_ops {
> > int (*read)(...);
> > int (*write)(...);
> > };
> > 
> > struct aspeed_gpio_reg_ops gpio_reg_ops[] = {
> > [gpio_direction]  = { .read = read_direction, .write =
> > write_direction };
> > ...
> > };
> > 
> > Then we have:
> > 
> > static const struct AspeedGPIO gpios[...] = {
> >  [GPIO_ABCD_DIRECTION] = { .set = 0, .type = gpio_direction },
> >  ...
> > };
> > 
> > Not wedded to the idea, just thinking out loud. What do you think?
> > 
> 
> I'm not a huge fan of the extra indirection. It is less error prone but
> is this a place that is likely to be updated regularly?

Right - if you've written correctly already then there's not much benefit.

> 
> 
> > > +[GPIO_ABCD_DIRECTION] = {0, read_direction, _write_direction},
> > > +[GPIO_ABCD_INT_ENABLE] = {0, read_int_enable,
> > > _write_int_enable},
> > > +[GPIO_ABCD_INT_SENS_0] = {0, read_int_sens_0,
> > > _write_int_sens_0},
> > > +[GPIO_ABCD_INT_SENS_1] = {0, read_int_sens_1,
> > > _write_int_sens_1},
> > > +[GPIO_ABCD_INT_SENS_2] = {0, read_int_sens_2,
> > > _write_int_sens_2},
> > > +[GPIO_ABCD_INT_STATUS] = {0, read_int_status,
> > > _write_int_status},
> > > +[GPIO_ABCD_RESET_TOLERANT] = {0, read_reset_tol,
> > > _write_reset_tol},
> > > +[GPIO_ABCD_DEBOUNCE_1] = {0, read_debounce_1,
> > > _write_debounce_1},
> > > +[GPIO_ABCD_DEBOUNCE_2] = {0, read_debounce_2,
> > > _write_debounce_2},
> > > +[GPIO_ABCD_COMMAND_SRC_0] = {0, read_cmd_source_0, 
> > > _write_cmd_source_0},
> > > +[GPIO_ABCD_COMMAND_SRC_1] = {0, read_cmd_source_1, 
> > > _write_cmd_source_1},
> > > +[GPIO_ABCD_DATA_READ] = {0, read_data, NULL},
> > > +[GPIO_ABCD_INPUT_MASK] = {0, read_input_mask,
> > > _write_input_mask},
> > > +/* Set EFGH */
> > > +[GPIO_EFGH_DATA_VALUE] = {1, read_data_value,
> > > _write_data_value},
> > > +[GPIO_EFGH_DIRECTION] = {1, read_direction, _write_direction
> > > },
> > > +[GPIO_EFGH_INT_ENABLE] = {1, read_int_enable,
> > > _write_int_enable},
> > > +[GPIO_EFGH_INT_SENS_0] = {1, read_int_sens_0,
> > > _write_int_sens_0},
> > > +[GPIO_EFGH_INT_SENS_1] = {1, read_int_sens_1,
> > > _write_int_sens_1},
> > > +[GPIO_EFGH_INT_SENS_2] = {1, read_int_sens_2,
> > > _write_int_sens_2},
> > > +[GPIO_EFGH_INT_STATUS] = {1, read_int_status,
> > > _write_int_status},
> > > +[GPIO_EFGH_RESET_TOL] = {1,
> > > read_reset_tol,   _write_reset_tol},
> > > +[GPIO_EFGH_DEBOUNCE_1] = {1,
> > > read_debounce_1,  _write_debounce_1},
> > > +[GPIO_EFGH_DEBOUNCE_2] = {1,
> > > read_debounce_2,  _write_debounce_2},
> > > +[GPIO_EFGH_COMMAND_SRC_0] = {1, read_cmd_source_0,  
> > > _write_cmd_source_0},
> > > +[GPIO_EFGH_COMMAND_SRC_1] = {1, read_cmd_source_1,  
> > > _write_cmd_source_1},
> > > +[GPIO_EFGH_DATA_READ] = {1, read_data, NULL},
> > > +[GPIO_EFGH_INPUT_MASK] = {1,
> > > read_input_mask,  _write_input_mask},
> > > +/* Set IJKL */
> > > +[GPIO_IJKL_DATA_VALUE] = {2, read_data_value,
> > > _write_data_value},
> > > +[GPIO_IJKL_DIRECTION] = {2, read_direction, _write_direction},
> > > +[GPIO_IJKL_INT_ENABLE] = {2, read_int_enable,
> > > _write_int_enable},
> > > +[GPIO_IJKL_INT_SENS_0] = {2, read_int_sens_0,
> > > _write_int_sens_0},
> > > +[GPIO_IJKL_INT_SENS_1] = {2, read_int_sens_1,
> > > _write_int_sens_1},
> > > +[GPIO_IJKL_INT_SENS_2] = {2, read_int_sens_2,
> > > _write_int_sens_2},
> > > +[GPIO_IJKL_INT_STATUS] = {2, read_int_status,
> > > _write_int_status},
> > > +[GPIO_IJKL_RESET_TOLERANT] = {2, read_reset_tol,
> > > _write_reset_tol},
> > > +[GPIO_IJKL_DEBOUNCE_1] = {2, read_debounce_1,
> > > _write_debounce_1},
> > > +[GPIO_IJKL_DEBOUNCE_2] = {2, read_debounce_2,
> > > _write_debounce_2},
> > > +[GPIO_IJKL_COMMAND_SRC_0] = {2, read_cmd_source_0, 
> > > _write_cmd_source_0},
> > > +[GPIO_IJKL_COMMAND_SRC_1] = {2, read_cmd_source_1, 
> > > _write_cmd_source_1},
> > > +[GPIO_IJKL_DATA_READ] = {2, read_data, NULL},
> > > +[GPIO_IJKL_INPUT_MASK] = {2, read_input_mask,
> > > _write_input_mask},
> > > +/* Set MNOP */
> > > +[GPIO_MNOP_DATA_VALUE] = {3, read_data_value,
> > > _write_data_value},
> > > +[GPIO_MNOP_DIRECTION] 

Re: [Qemu-devel] [PATCH 1/2] hw/gpio: Add basic Aspeed GPIO model

2019-07-02 Thread Andrew Jeffery



On Tue, 18 Jun 2019, at 18:52, Rashmica Gupta wrote:
> Add in details for GPIO controller for AST 2400 and 2500
> 
> Signed-off-by: Rashmica Gupta 
> ---
>  hw/gpio/Makefile.objs |   1 +
>  hw/gpio/aspeed_gpio.c | 869 ++
>  include/hw/gpio/aspeed_gpio.h |  76 +++
>  3 files changed, 946 insertions(+)
>  create mode 100644 hw/gpio/aspeed_gpio.c
>  create mode 100644 include/hw/gpio/aspeed_gpio.h
> 
> diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
> index e5da0cb54f..d305b3b24b 100644
> --- a/hw/gpio/Makefile.objs
> +++ b/hw/gpio/Makefile.objs
> @@ -9,3 +9,4 @@ obj-$(CONFIG_OMAP) += omap_gpio.o
>  obj-$(CONFIG_IMX) += imx_gpio.o
>  obj-$(CONFIG_RASPI) += bcm2835_gpio.o
>  obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o
> +obj-$(CONFIG_ASPEED_SOC) += aspeed_gpio.o
> diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
> new file mode 100644
> index 00..d84dd69255
> --- /dev/null
> +++ b/hw/gpio/aspeed_gpio.c
> @@ -0,0 +1,869 @@
> +/*
> + *  ASPEED GPIO Controller
> + *
> + *  Copyright (C) 2017-2019 IBM Corp.
> + *
> + * This code is licensed under the GPL version 2 or later.  See
> + * the COPYING file in the top-level directory.
> + *

I'd use a SPDX license marker here instead.

> + *
> + * This models the ast2400 and ast2500 GPIO controllers.
> + *
> + * GPIO pins are arranged in groups of 8 pins labeled 
> A,B,..,Y,Z,AA,AB,AC.
> + * (Note that the ast2400 controller only goes up to group AB).
> + * A set has four groups (except set AC which only has one) and is
> + * referred to by the groups it is composed of (eg 
> ABCD,EFGH,...,YZAAAB).
> + * Each set is accessed and controlled by a bank of 14 registers.
> + *
> + * These registers operate on a per pin level where each bit in the 
> register
> + * corresponds to a pin, except for the command source registers. The 
> command
> + * source registers operate on a per group level where bits 24, 16, 8 
> and 0
> + * correspond to each group in the set.
> + *
> + *  eg. registers for set ABCD:
> + *  |D7...D0|C7...C0|B7...B0|A7...A0| <- GPIOs
> + *  |31...24|23...16|158|7.0| <- bit position
> + *
> + * Note that there are a couple of groups that only have 4 pins.
> +
> + * There are three ways that this model deviates from the behaviour of 
> the
> + * actual controller:
> + * (1) There are three debounce registers which aren't modeled and so 
> the per
> + * set debounce setting registers don't affect anything.
> + *
> + * (2) The only control source driving the GPIO pins in the model is 
> the ARM
> + * model (as there currently aren't models for the LPC or Coprocessor 
> [TODO]).
> + *
> + * (3) None of the registers in the model are reset tolerant. [TODO]
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "hw/gpio/aspeed_gpio.h"
> +#include "include/hw/misc/aspeed_scu.h"
> +#include "qapi/error.h"
> +#include "qapi/visitor.h"
> +
> +#define ASPEED_GPIOS_PER_REG 32
> +
> +/* GPIO Source Types */
> +#define ASPEED_CMD_SRC_MASK 0x01010101
> +#define ASPEED_SOURCE_ARM   0
> +#define ASPEED_SOURCE_LPC   1
> +#define ASPEED_SOURCE_COPROCESSOR   2
> +#define ASPEED_SOURCE_RESERVED  3
> +
> +/* GPIO Interrupt Triggers */
> +#define ASPEED_FALLING_EDGE 0
> +#define ASPEED_RISING_EDGE  1
> +#define ASPEED_LEVEL_LOW2
> +#define ASPEED_LEVEL_HIGH   3
> +#define ASPEED_DUAL_EDGE4
> +
> +/* GPIO Register Address Offsets */
> +#define GPIO_ABCD_DATA_VALUE 0x000
> +#define GPIO_ABCD_DIRECTION  0x004
> +#define GPIO_ABCD_INT_ENABLE 0x008
> +#define GPIO_ABCD_INT_SENS_0 0x00C
> +#define GPIO_ABCD_INT_SENS_1 0x010
> +#define GPIO_ABCD_INT_SENS_2 0x014
> +#define GPIO_ABCD_INT_STATUS 0x018
> +#define GPIO_ABCD_RESET_TOLERANT 0x01C
> +#define GPIO_EFGH_DATA_VALUE 0x020
> +#define GPIO_EFGH_DIRECTION  0x024
> +#define GPIO_EFGH_INT_ENABLE 0x028
> +#define GPIO_EFGH_INT_SENS_0 0x02C
> +#define GPIO_EFGH_INT_SENS_1 0x030
> +#define GPIO_EFGH_INT_SENS_2 0x034
> +#define GPIO_EFGH_INT_STATUS 0x038
> +#define GPIO_EFGH_RESET_TOL  0x03C
> +#define GPIO_ABCD_DEBOUNCE_1 0x040
> +#define GPIO_ABCD_DEBOUNCE_2 0x044
> +#define GPIO_EFGH_DEBOUNCE_1 0x048
> +#define GPIO_EFGH_DEBOUNCE_2 0x04C
> +#define GPIO_DEBOUNCE_TIME_1 0x050
> +#define GPIO_DEBOUNCE_TIME_2 0x054
> +#define GPIO_DEBOUNCE_TIME_3 0x058
> +#define GPIO_ABCD_COMMAND_SRC_0  0x060
> +#define GPIO_ABCD_COMMAND_SRC_1  0x064
> +#define GPIO_EFGH_COMMAND_SRC_0  0x068
> +#define GPIO_EFGH_COMMAND_SRC_1  0x06C
> +#define GPIO_IJKL_DATA_VALUE 0x070
> +#define GPIO_IJKL_DIRECTION  0x074
> +#define GPIO_MNOP_DATA_VALUE 0x078
> +#define GPIO_MNOP_DIRECTION  0x07C
> +#define GPIO_QRST_DATA_VALUE 0x080
> +#define GPIO_QRST_DIRECTION  0x084
> +#define GPIO_UVWX_DATA_VALUE 0x088
> +#define GPIO_UWVX_DIRECTION  0x08C
> +#define GPIO_IJKL_COMMAND_SRC_0  0x090
> +#define 

Re: [Qemu-devel] [PATCH v2 11/21] aspeed/timer: Ensure positive muldiv delta

2019-06-19 Thread Andrew Jeffery



On Wed, 19 Jun 2019, at 02:24, Cédric Le Goater wrote:
> From: Christian Svensson 
> 
> If the host decrements the counter register that results in a negative
> delta. This is then passed to muldiv64 which only handles unsigned
> numbers resulting in bogus results.
> 
> This fix ensures the delta being operated on is positive.
> 
> Test case: kexec a kernel using aspeed_timer and it will freeze on the
> second bootup when the kernel initializes the timer. With this patch
> that no longer happens and the timer appears to run OK.
> 
> Signed-off-by: Christian Svensson 
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Andrew Jeffery 

> ---
>  hw/timer/aspeed_timer.c | 6 +-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
> index 6501fa0768e7..1f0f1886fb2a 100644
> --- a/hw/timer/aspeed_timer.c
> +++ b/hw/timer/aspeed_timer.c
> @@ -275,7 +275,11 @@ static void 
> aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
>  int64_t delta = (int64_t) value - (int64_t) 
> calculate_ticks(t, now);
>  uint32_t rate = calculate_rate(t);
>  
> -t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
> +if (delta >= 0) {
> +t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
> +} else {
> +t->start -= muldiv64(-delta, NANOSECONDS_PER_SECOND, rate);
> +}
>  aspeed_timer_mod(t);
>  }
>  break;
> -- 
> 2.21.0
> 
>



Re: [Qemu-devel] [PATCH qemu] aspeed: Add support for the swift-bmc board

2019-06-03 Thread Andrew Jeffery



On Tue, 4 Jun 2019, at 09:07, Joel Stanley wrote:
> On Mon, 3 Jun 2019 at 19:11, Adriana Kobylak  wrote:
> >
> > From: Adriana Kobylak 
> >
> > The Swift board is an OpenPOWER system hosting POWER processors.
> > Add support for their BMC including the I2C devices as found on HW.
> >
> > Signed-off-by: Adriana Kobylak 
> > Reviewed-by: Cédric Le Goater 
> > ---
> >  hw/arm/aspeed.c | 42 ++
> >  1 file changed, 42 insertions(+)
> >
> > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> > index 33070a6..cd95b3c 100644
> > --- a/hw/arm/aspeed.c
> > +++ b/hw/arm/aspeed.c
> > @@ -73,6 +73,9 @@ struct AspeedBoardState {
> >  SCU_AST2500_HW_STRAP_ACPI_ENABLE |  \
> >  SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
> >
> > +/* TODO: Swift hardware value: ? (use romulus definition for now) */
> > +#define SWIFT_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
> 
> I got this from hardware: 0xF11AD206

There are two differences from the value noted in the comment below:

1. Bit 4 is clear in your value
2. Bit 20 is set in your value

Bit 4 is reserved, so not sure if we should care about the difference.

Bit 20 is the SuperIO decode disable bit. I don't think we care much
about it at the moment, but we may as we model more of the LPC
interface in the future.

Andrew

> 
> The rest looks okay.
> 
> Reviewed-by: Joel Stanley 
> 
> > +
> >  /* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
> >  #define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
> >
> > @@ -287,6 +290,35 @@ static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
> >  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 11), "ds1338", 
> > 0x32);
> >  }
> >
> > +static void swift_bmc_i2c_init(AspeedBoardState *bmc)
> > +{
> > +AspeedSoCState *soc = >soc;
> > +
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 3), "pca9552", 
> > 0x60);
> > +
> > +/* The swift board expects a TMP275 but a TMP105 is compatible */
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 7), "tmp105", 
> > 0x48);
> > +/* The swift board expects a pca9551 but a pca9552 is compatible */
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 7), "pca9552", 
> > 0x60);
> > +
> > +/* The swift board expects an Epson RX8900 RTC but a ds1338 is 
> > compatible */
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 8), "ds1338", 
> > 0x32);
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 8), "pca9552", 
> > 0x60);
> > +
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 9), "tmp423", 
> > 0x4c);
> > +/* The swift board expects a pca9539 but a pca9552 is compatible */
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 9), "pca9552", 
> > 0x74);
> > +
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 10), "tmp423", 
> > 0x4c);
> > +/* The swift board expects a pca9539 but a pca9552 is compatible */
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 10), "pca9552",
> > + 0x74);
> > +
> > +/* The swift board expects a TMP275 but a TMP105 is compatible */
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 12), "tmp105", 
> > 0x48);
> > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 12), "tmp105", 
> > 0x4a);
> > +}
> > +
> >  static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
> >  {
> >  AspeedSoCState *soc = >soc;
> > @@ -378,6 +410,16 @@ static const AspeedBoardConfig aspeed_boards[] = {
> >  .i2c_init  = romulus_bmc_i2c_init,
> >  .ram   = 512 * MiB,
> >  }, {
> > +.name  = MACHINE_TYPE_NAME("swift-bmc"),
> > +.desc  = "OpenPOWER Swift BMC (ARM1176)",
> > +.soc_name  = "ast2500-a1",
> > +.hw_strap1 = SWIFT_BMC_HW_STRAP1,
> > +.fmc_model = "mx66l1g45g",
> > +.spi_model = "mx66l1g45g",
> > +.num_cs= 2,
> > +.i2c_init  = swift_bmc_i2c_init,
> > +.ram   = 512 * MiB,
> > +}, {
> >  .name  = MACHINE_TYPE_NAME("witherspoon-bmc"),
> >  .desc  = "OpenPOWER Witherspoon BMC (ARM1176)",
> >  .soc_name  = "ast2500-a1",
> > --
> > 1.8.3.1
> >
>



Re: [Qemu-devel] [PATCH] arm: aspeed: Set SDRAM size

2019-05-01 Thread Andrew Jeffery



On Wed, 1 May 2019, at 15:48, Joel Stanley wrote:
> We currently use Qemu's default of 128MB. As we know how much ram each
> machine ships with, make it easier on users by setting a default.
> 
> It can still be overridden with -m on the command line.
> 
> Signed-off-by: Joel Stanley 

Reviewed-by: Andrew Jeffery 

> ---
>  hw/arm/aspeed.c | 6 ++
>  include/hw/arm/aspeed.h | 1 +
>  2 files changed, 7 insertions(+)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 1c23ebd99252..3f3d4162b3c5 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -331,6 +331,8 @@ static void aspeed_machine_class_init(ObjectClass 
> *oc, void *data)
>  mc->no_floppy = 1;
>  mc->no_cdrom = 1;
>  mc->no_parallel = 1;
> +if (board->ram)
> +mc->default_ram_size = board->ram;
>  amc->board = board;
>  }
>  
> @@ -352,6 +354,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
>  .spi_model = "mx25l25635e",
>  .num_cs= 1,
>  .i2c_init  = palmetto_bmc_i2c_init,
> +.ram   = 256 << 20,
>  }, {
>  .name  = MACHINE_TYPE_NAME("ast2500-evb"),
>  .desc  = "Aspeed AST2500 EVB (ARM1176)",
> @@ -361,6 +364,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
>  .spi_model = "mx25l25635e",
>  .num_cs= 1,
>  .i2c_init  = ast2500_evb_i2c_init,
> +.ram   = 512 << 20,
>  }, {
>  .name  = MACHINE_TYPE_NAME("romulus-bmc"),
>  .desc  = "OpenPOWER Romulus BMC (ARM1176)",
> @@ -370,6 +374,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
>  .spi_model = "mx66l1g45g",
>  .num_cs= 2,
>  .i2c_init  = romulus_bmc_i2c_init,
> +.ram   = 512 << 20,
>  }, {
>  .name  = MACHINE_TYPE_NAME("witherspoon-bmc"),
>  .desc  = "OpenPOWER Witherspoon BMC (ARM1176)",
> @@ -379,6 +384,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
>  .spi_model = "mx66l1g45g",
>  .num_cs= 2,
>  .i2c_init  = witherspoon_bmc_i2c_init,
> +.ram   = 512 << 20,
>  },
>  };
>  
> diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
> index 325c091d09e4..02073a6b4d61 100644
> --- a/include/hw/arm/aspeed.h
> +++ b/include/hw/arm/aspeed.h
> @@ -22,6 +22,7 @@ typedef struct AspeedBoardConfig {
>  const char *spi_model;
>  uint32_t num_cs;
>  void (*i2c_init)(AspeedBoardState *bmc);
> +uint32_t ram;
>  } AspeedBoardConfig;
>  
>  #define TYPE_ASPEED_MACHINE   MACHINE_TYPE_NAME("aspeed")
> -- 
> 2.20.1
> 
>



Re: [Qemu-devel] [PATCH 2/3] aspeed: add a per SoC mapping for the memory space

2019-04-11 Thread Andrew Jeffery



On Fri, 12 Apr 2019, at 11:48, Joel Stanley wrote:
> On Thu, 11 Apr 2019 at 16:10, Cédric Le Goater  wrote:
> >
> > This will simplify the definition of new SoCs, like the AST2600 which
> > should use a slightly different address space and have a different set
> > of controllers.
> >
> > Signed-off-by: Cédric Le Goater 
> 
> > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > index 5bbd1fb87d18..9b601709e93c 100644
> > --- a/hw/arm/aspeed_soc.c
> > +++ b/hw/arm/aspeed_soc.c
> 
> > +static const hwaddr aspeed_soc_ast2400_memmap[] = {
> 
> > +static const hwaddr aspeed_soc_ast2500_memmap[] = {
> 
> Most of these arrays is common. And some of it will stay common in the
> 2600. Any ideas how we could avoid duplication?

I dunno, I feel that any attempt to create some "common" layout concept is
more distracting than having soc-specific, complete layouts described.

There's no reason why they're common beyond coincidence (i.e. it's at
ASPEED's whim). I think this is fine.

Reviewed-by: Andrew Jeffery 

> 
> This is fine for now.
> 
> Reviewed-by: Joel Stanley 
>



Re: [Qemu-devel] [PATCH 3/3] aspeed: use sysbus_init_child_obj() to initialize children

2019-04-11 Thread Andrew Jeffery



On Fri, 12 Apr 2019, at 01:40, Cédric Le Goater wrote:
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Andrew Jeffery 

> ---
>  hw/arm/aspeed_soc.c | 50 ++---
>  1 file changed, 20 insertions(+), 30 deletions(-)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 9b601709e93c..110956828c44 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -212,12 +212,11 @@ static void aspeed_soc_init(Object *obj)
>  AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
>  int i;
>  
> -object_initialize(>cpu, sizeof(s->cpu), sc->info->cpu_type);
> -object_property_add_child(obj, "cpu", OBJECT(>cpu), NULL);
> +object_initialize_child(obj, "cpu", OBJECT(>cpu), sizeof(s->cpu),
> +sc->info->cpu_type, _abort, NULL);
>  
> -object_initialize(>scu, sizeof(s->scu), TYPE_ASPEED_SCU);
> -object_property_add_child(obj, "scu", OBJECT(>scu), NULL);
> -qdev_set_parent_bus(DEVICE(>scu), sysbus_get_default());
> +sysbus_init_child_obj(obj, "scu", OBJECT(>scu), sizeof(s->scu),
> +  TYPE_ASPEED_SCU);
>  qdev_prop_set_uint32(DEVICE(>scu), "silicon-rev",
>   sc->info->silicon_rev);
>  object_property_add_alias(obj, "hw-strap1", OBJECT(>scu),
> @@ -227,36 +226,29 @@ static void aspeed_soc_init(Object *obj)
>  object_property_add_alias(obj, "hw-prot-key", OBJECT(>scu),
>"hw-prot-key", _abort);
>  
> -object_initialize(>vic, sizeof(s->vic), TYPE_ASPEED_VIC);
> -object_property_add_child(obj, "vic", OBJECT(>vic), NULL);
> -qdev_set_parent_bus(DEVICE(>vic), sysbus_get_default());
> +sysbus_init_child_obj(obj, "vic", OBJECT(>vic), sizeof(s->vic),
> +  TYPE_ASPEED_VIC);
>  
> -object_initialize(>timerctrl, sizeof(s->timerctrl), 
> TYPE_ASPEED_TIMER);
> -object_property_add_child(obj, "timerctrl", OBJECT(>timerctrl), NULL);
> +sysbus_init_child_obj(obj, "timerctrl", OBJECT(>timerctrl),
> +  sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
>  object_property_add_const_link(OBJECT(>timerctrl), "scu",
> OBJECT(>scu), _abort);
> -qdev_set_parent_bus(DEVICE(>timerctrl), sysbus_get_default());
>  
> -object_initialize(>i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
> -object_property_add_child(obj, "i2c", OBJECT(>i2c), NULL);
> -qdev_set_parent_bus(DEVICE(>i2c), sysbus_get_default());
> +sysbus_init_child_obj(obj, "i2c", OBJECT(>i2c), sizeof(s->i2c),
> +  TYPE_ASPEED_I2C);
>  
> -object_initialize(>fmc, sizeof(s->fmc), sc->info->fmc_typename);
> -object_property_add_child(obj, "fmc", OBJECT(>fmc), NULL);
> -qdev_set_parent_bus(DEVICE(>fmc), sysbus_get_default());
> +sysbus_init_child_obj(obj, "fmc", OBJECT(>fmc), sizeof(s->fmc),
> +  sc->info->fmc_typename);
>  object_property_add_alias(obj, "num-cs", OBJECT(>fmc), "num-cs",
>_abort);
>  
>  for (i = 0; i < sc->info->spis_num; i++) {
> -object_initialize(>spi[i], sizeof(s->spi[i]),
> -  sc->info->spi_typename[i]);
> -object_property_add_child(obj, "spi[*]", OBJECT(>spi[i]), NULL);
> -qdev_set_parent_bus(DEVICE(>spi[i]), sysbus_get_default());
> +sysbus_init_child_obj(obj, "spi[*]", OBJECT(>spi[i]),
> +  sizeof(s->spi[i]), sc->info->spi_typename[i]);
>  }
>  
> -object_initialize(>sdmc, sizeof(s->sdmc), TYPE_ASPEED_SDMC);
> -object_property_add_child(obj, "sdmc", OBJECT(>sdmc), NULL);
> -qdev_set_parent_bus(DEVICE(>sdmc), sysbus_get_default());
> +sysbus_init_child_obj(obj, "sdmc", OBJECT(>sdmc), sizeof(s->sdmc),
> +  TYPE_ASPEED_SDMC);
>  qdev_prop_set_uint32(DEVICE(>sdmc), "silicon-rev",
>   sc->info->silicon_rev);
>  object_property_add_alias(obj, "ram-size", OBJECT(>sdmc),
> @@ -265,16 +257,14 @@ static void aspeed_soc_init(Object *obj)
>"max-ram-size", _abort);
>  
>  for (i = 0; i < sc->info->wdts_num; i++) {
> -object_initialize(&g

Re: [Qemu-devel] [PATCH 1/3] aspeed: add a per SoC mapping for the interrupt space

2019-04-11 Thread Andrew Jeffery



On Fri, 12 Apr 2019, at 02:13, Philippe Mathieu-Daudé wrote:
> Hi Cédric,
> 
> On 4/11/19 6:10 PM, Cédric Le Goater wrote:
> > This will simplify the definition of new SoCs, like the AST2600 which
> > should use a different CPU and a different IRQ number layout.
> > 
> > Signed-off-by: Cédric Le Goater 
> > ---
> >  include/hw/arm/aspeed_soc.h |  1 +
> >  hw/arm/aspeed_soc.c | 93 +
> >  2 files changed, 86 insertions(+), 8 deletions(-)
> > 
> > diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> > index 11ec0179db50..b0d266434288 100644
> > --- a/include/hw/arm/aspeed_soc.h
> > +++ b/include/hw/arm/aspeed_soc.h
> > @@ -57,6 +57,7 @@ typedef struct AspeedSoCInfo {
> >  const char *fmc_typename;
> >  const char **spi_typename;
> >  int wdts_num;
> > +const int *irqmap;
> >  } AspeedSoCInfo;
> >  
> >  typedef struct AspeedSoCClass {
> > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> > index a27233d4876b..5bbd1fb87d18 100644
> > --- a/hw/arm/aspeed_soc.c
> > +++ b/hw/arm/aspeed_soc.c
> > @@ -22,6 +22,42 @@
> >  #include "hw/i2c/aspeed_i2c.h"
> >  #include "net/net.h"
> >  
> > +enum {
> > +ASPEED_IOMEM,
> > +ASPEED_UART1,
> > +ASPEED_UART2,
> > +ASPEED_UART3,
> > +ASPEED_UART4,
> > +ASPEED_UART5,
> > +ASPEED_VUART,
> > +ASPEED_FMC,
> > +ASPEED_SPI1,
> > +ASPEED_SPI2,
> > +ASPEED_VIC,
> > +ASPEED_SDMC,
> > +ASPEED_SCU,
> > +ASPEED_ADC,
> > +ASPEED_SRAM,
> > +ASPEED_GPIO,
> > +ASPEED_RTC,
> > +ASPEED_TIMER1,
> > +ASPEED_TIMER2,
> > +ASPEED_TIMER3,
> > +ASPEED_TIMER4,
> > +ASPEED_TIMER5,
> > +ASPEED_TIMER6,
> > +ASPEED_TIMER7,
> > +ASPEED_TIMER8,
> 
> You use an enum to define const values. It is recommended to also define
> the value, to avoid problems if someone add/remove a value in the list
> (unlikely, but we never know... imagine someone wants to try this SoC
> with 9 timers and add ASPEED_TIMER9) ;)

The enum's not used outside of aspeed_soc.c though, so it should all be
self-consistent? Adding ASPEED_TIMER9 would just adjust the designated
initialiser index values in aspeed_soc_ast2400_irqmap declaration below.
Am I missing something?

Specifying enum values seems tedious in this case.

Andrew

> 
> > +ASPEED_WDT,
> > +ASPEED_PWM,
> > +ASPEED_LPC,
> > +ASPEED_IBT,
> > +ASPEED_I2C,
> > +ASPEED_ETH1,
> > +ASPEED_ETH2,
> > +ASPEED_SDRAM,
> > +};
> > +
> >  #define ASPEED_SOC_UART_5_BASE  0x00184000
> >  #define ASPEED_SOC_IOMEM_SIZE   0x0020
> >  #define ASPEED_SOC_IOMEM_BASE   0x1E60
> > @@ -38,12 +74,42 @@
> >  #define ASPEED_SOC_ETH1_BASE0x1E66
> >  #define ASPEED_SOC_ETH2_BASE0x1E68
> >  
> > -static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
> > -static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
> > +static const int aspeed_soc_ast2400_irqmap[] = {
> > +[ASPEED_UART1]  = 9,
> > +[ASPEED_UART2]  = 32,
> > +[ASPEED_UART3]  = 33,
> > +[ASPEED_UART4]  = 34,
> > +[ASPEED_UART5]  = 10,
> > +[ASPEED_VUART]  = 8,
> > +[ASPEED_FMC]= 19,
> > +[ASPEED_SDMC]   = 0,
> > +[ASPEED_SCU]= 21,
> > +[ASPEED_ADC]= 31,
> > +[ASPEED_GPIO]   = 20,
> > +[ASPEED_RTC]= 22,
> > +[ASPEED_TIMER1] = 16,
> > +[ASPEED_TIMER2] = 17,
> > +[ASPEED_TIMER3] = 18,
> > +[ASPEED_TIMER4] = 35,
> > +[ASPEED_TIMER5] = 36,
> > +[ASPEED_TIMER6] = 37,
> > +[ASPEED_TIMER7] = 38,
> > +[ASPEED_TIMER8] = 39,
> > +[ASPEED_WDT]= 27,
> > +[ASPEED_PWM]= 28,
> > +[ASPEED_LPC]= 8,
> > +[ASPEED_IBT]= 8, /* LPC */
> > +[ASPEED_I2C]= 12,
> > +[ASPEED_ETH1]   = 2,
> > +[ASPEED_ETH2]   = 3,
> > +};
> >  
> >  #define AST2400_SDRAM_BASE   0x4000
> >  #define AST2500_SDRAM_BASE   0x8000
> >  
> > +/* AST2500 uses the same IRQs as the AST2400 */
> > +#define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap
> > +
> >  static const hwaddr aspeed_soc_ast2400_spi_bases[] = { ASPEED_SOC_SPI_BASE 
> > };
> >  static const char *aspeed_soc_ast2400_typenames[] = { "aspeed.smc.spi" };
> >  
> > @@ -64,6 +130,7 @@ static const AspeedSoCInfo aspeed_socs[] = {
> >  .fmc_typename = "aspeed.smc.fmc",
> >  .spi_typename = aspeed_soc_ast2400_typenames,
> >  .wdts_num = 2,
> > +.irqmap   = aspeed_soc_ast2400_irqmap,
> >  }, {
> >  .name = "ast2400-a1",
> >  .cpu_type = ARM_CPU_TYPE_NAME("arm926"),
> > @@ -75,6 +142,7 @@ static const AspeedSoCInfo aspeed_socs[] = {
> >  .fmc_typename = "aspeed.smc.fmc",
> >  .spi_typename = aspeed_soc_ast2400_typenames,
> >  .wdts_num = 2,
> > +.irqmap   = aspeed_soc_ast2400_irqmap,
> >  }, {
> >  .name = "ast2400",
> >  .cpu_type = 

Re: [Qemu-devel] Maintainers, please tell us how to boot your machines!

2019-03-12 Thread Andrew Jeffery



On Wed, 13 Mar 2019, at 07:07, Cédric Le Goater wrote:
> On 3/12/19 6:36 PM, Markus Armbruster wrote:
> > Dear board code maintainers,
> > 
> > This is a (rather late) follow-up to the last QEMU summit.  Minutes[*]:
> > 
> >  * Deprecating unmaintained features (devices, targets, backends) in QEMU
> > 
> >QEMU has a mechanism to deprecate features but there remains a lot of
> >old unmaintained code.  Refactoring is hindered by untested legacy
> >code, so there is a desire to deprecate unmaintained features more
> >often.
> > 
> >[...]
> > 
> >We should require at least a minimal test for each board; if nobody
> >cares enough to come up with one, that board should be deprecated.
> > 
> >[...]
> > 
> >Also see the qemu-devel discussion about deprecating code:
> >https://lists.nongnu.org/archive/html/qemu-devel/2018-10/msg05828.html.
> > 
> > That's a link to "Minutes of KVM Forum BoF on deprecating stuff".
> > Quote:
> > 
> >  * One obvious class of candidates for removal is machines we don't know
> >how to boot, or can't boot, say because we lack required firmware
> >and/or OS.
> > 
> >Of course, "can boot" should be an automated test.  As a first step
> >towards that, we should at least document how to boot each machine.
> >We're going to ask machine maintainers to do that.
> > 
> > Let's get going on this.
> > 
> > I gathered the machine types, mapped them to source files, which I fed
> > to get_maintainer.pl.  Results are appended.  If you're cc'ed,
> > MAINTAINERS fingers you for at least one machine type's source file.
> > Please tell us for all of them how to to a "meaningful" boot test.
> > 
> > For now, what's "meaningful" is entirely up to you.  Booting Linux
> > certainly is.
> > 
> > Make sure to include a complete QEMU command line.  If your QEMU command
> > line requires resources beyond the QEMU source tree and what we build
> > from it, please detail them, and provide download URLs as far as
> > possible.
> > 
> > Goals for this exercise:
> > 
> > * Gather information we need to cover more machines in our automated
> >   testing.
> > 
> >   Related work:
> >   [PATCH v4 00/19] Acceptance Tests: target architecture support
> >   Message-Id: <20190312121150.8638-1-cr...@redhat.com>
> >   https://lists.gnu.org/archive/html/qemu-devel/2019-03/msg03881.html
> > 
> > * Maybe identify a few machines we don't know how to boot anymore.
> > 
> > Thanks in advance for your help!
> > 
> > 
> > 
> > Machines with at least one maintainer:
> > 
> > = hw/alpha/dp264.c =
> > Richard Henderson  (maintainer:Alpha Machines)
> > 
> > = hw/arm/aspeed.c =
> > "Cédric Le Goater"  (maintainer:ASPEED BMCs)
> > Peter Maydell  (maintainer:ASPEED BMCs)
> > Andrew Jeffery  (reviewer:ASPEED BMCs)
> > Joel Stanley  (reviewer:ASPEED BMCs)
> > qemu-...@nongnu.org (open list:ASPEED BMCs)
> 
> I have checked the URLs but they could change in the future :
> 
> * palmetto-bmc
> 
>   
> https://openpower.xyz/job/openbmc-build/lastSuccessfulBuild/distro=ubuntu,label=builder,target=palmetto/artifact/deploy/images/palmetto/flash-palmetto
> 
>   qemu-system-arm -m 512 -M palmetto-bmc -net 
> nic,macaddr=C0:FF:EE:00:00:01,model=ftgmac100 -net 
> user,id=netdev0,hostfwd=::-:22,hostname=ast1 -drive 
> file=flash-palmetto,format=raw,if=mtd -nographic
> 
> * romulus-bmc
> 
>   
> https://openpower.xyz/job/openbmc-build/lastSuccessfulBuild/distro=ubuntu,label=builder,target=romulus/artifact/deploy/images/romulus/flash-romulus
> 
>   qemu-system-arm -m 512 -M romulus-bmc -net 
> nic,macaddr=C0:FF:EE:00:00:01,model=ftgmac100 -net 
> user,id=netdev0,hostfwd=::-:22,hostname=ast1 -drive 
> file=flash-romulus,format=raw,if=mtd -nographic
> 
> * ast2500-evb
> 
>   
> https://openpower.xyz/job/openbmc-build/lastSuccessfulBuild/distro=ubuntu,label=builder,target=evb-ast2500/artifact/deploy/images/evb-ast2500/flash-evb-ast2500
> 
>   qemu-system-arm -m 512 -M ast2500-evb -net 
> nic,macaddr=C0:FF:EE:00:00:01,model=ftgmac100 -net 
> user,id=netdev0,hostfwd=::-:22,hostname=ast1 -drive 
> file=flash-evb-ast2500,format=raw,if=mtd -nographic
> 
> * witherspoon-bmc
> 
>   
> https://openpower.xyz/job/openbmc-build/lastSuccessfulBuild/distro=ubuntu,label=builder,target=witherspoon/artifact/deploy/images/witherspoon/obmc-phosphor-image-witherspoon

Re: [Qemu-devel] [PATCH] ftgmac100: implement the new MDIO interface on Aspeed SoC

2019-01-13 Thread Andrew Jeffery



On Fri, 11 Jan 2019, at 23:27, Cédric Le Goater wrote:
> The PHY behind the MAC of an Aspeed SoC can be controlled using two
> different MDC/MDIO interfaces. The same registers PHYCR (MAC60) and
> PHYDATA (MAC64) are involved but they have a different layout.
> 
> BIT31 of the Feature Register (MAC40) controls which MDC/MDIO
> interface is active.
> 
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Andrew Jeffery 

> ---
>  hw/net/ftgmac100.c | 80 +++---
>  1 file changed, 68 insertions(+), 12 deletions(-)
> 
> diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
> index 909c1182eebe..790430346b51 100644
> --- a/hw/net/ftgmac100.c
> +++ b/hw/net/ftgmac100.c
> @@ -89,6 +89,18 @@
>  #define FTGMAC100_PHYDATA_MIIWDATA(x)   ((x) & 0x)
>  #define FTGMAC100_PHYDATA_MIIRDATA(x)   (((x) >> 16) & 0x)
>  
> +/*
> + * PHY control register - New MDC/MDIO interface
> + */
> +#define FTGMAC100_PHYCR_NEW_DATA(x) (((x) >> 16) & 0x)
> +#define FTGMAC100_PHYCR_NEW_FIRE(1 << 15)
> +#define FTGMAC100_PHYCR_NEW_ST_22   (1 << 12)
> +#define FTGMAC100_PHYCR_NEW_OP(x)   (((x) >> 10) & 3)
> +#define   FTGMAC100_PHYCR_NEW_OP_WRITE0x1
> +#define   FTGMAC100_PHYCR_NEW_OP_READ 0x2
> +#define FTGMAC100_PHYCR_NEW_DEV(x)  (((x) >> 5) & 0x1f)
> +#define FTGMAC100_PHYCR_NEW_REG(x)  ((x) & 0x1f)
> +
>  /*
>   * Feature Register
>   */
> @@ -269,9 +281,9 @@ static void phy_reset(FTGMAC100State *s)
>  s->phy_int = 0;
>  }
>  
> -static uint32_t do_phy_read(FTGMAC100State *s, int reg)
> +static uint16_t do_phy_read(FTGMAC100State *s, uint8_t reg)
>  {
> -uint32_t val;
> +uint16_t val;
>  
>  switch (reg) {
>  case MII_BMCR: /* Basic Control */
> @@ -336,7 +348,7 @@ static uint32_t do_phy_read(FTGMAC100State *s, int reg)
> MII_BMCR_FD | MII_BMCR_CTST)
>  #define MII_ANAR_MASK 0x2d7f
>  
> -static void do_phy_write(FTGMAC100State *s, int reg, uint32_t val)
> +static void do_phy_write(FTGMAC100State *s, uint8_t reg, uint16_t val)
>  {
>  switch (reg) {
>  case MII_BMCR: /* Basic Control */
> @@ -373,6 +385,55 @@ static void do_phy_write(FTGMAC100State *s, int 
> reg, uint32_t val)
>  }
>  }
>  
> +static void do_phy_new_ctl(FTGMAC100State *s)
> +{
> +uint8_t reg;
> +uint16_t data;
> +
> +if (!(s->phycr & FTGMAC100_PHYCR_NEW_ST_22)) {
> +qemu_log_mask(LOG_UNIMP, "%s: unsupported ST code\n", __func__);
> +return;
> +}
> +
> +/* Nothing to do */
> +if (!(s->phycr & FTGMAC100_PHYCR_NEW_FIRE)) {
> +return;
> +}
> +
> +reg = FTGMAC100_PHYCR_NEW_REG(s->phycr);
> +data = FTGMAC100_PHYCR_NEW_DATA(s->phycr);
> +
> +switch (FTGMAC100_PHYCR_NEW_OP(s->phycr)) {
> +case FTGMAC100_PHYCR_NEW_OP_WRITE:
> +do_phy_write(s, reg, data);
> +break;
> +case FTGMAC100_PHYCR_NEW_OP_READ:
> +s->phydata = do_phy_read(s, reg) & 0x;
> +break;
> +default:
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid OP code %08x\n",
> +  __func__, s->phycr);
> +}
> +
> +s->phycr &= ~FTGMAC100_PHYCR_NEW_FIRE;
> +}
> +
> +static void do_phy_ctl(FTGMAC100State *s)
> +{
> +uint8_t reg = FTGMAC100_PHYCR_REG(s->phycr);
> +
> +if (s->phycr & FTGMAC100_PHYCR_MIIWR) {
> +do_phy_write(s, reg, s->phydata & 0x);
> +s->phycr &= ~FTGMAC100_PHYCR_MIIWR;
> +} else if (s->phycr & FTGMAC100_PHYCR_MIIRD) {
> +s->phydata = do_phy_read(s, reg) << 16;
> +s->phycr &= ~FTGMAC100_PHYCR_MIIRD;
> +} else {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: no OP code %08x\n",
> +  __func__, s->phycr);
> +}
> +}
> +
>  static int ftgmac100_read_bd(FTGMAC100Desc *bd, dma_addr_t addr)
>  {
>  if (dma_memory_read(_space_memory, addr, bd, sizeof(*bd))) {
> @@ -628,7 +689,6 @@ static void ftgmac100_write(void *opaque, hwaddr addr,
>uint64_t value, unsigned size)
>  {
>  FTGMAC100State *s = FTGMAC100(opaque);
> -int reg;
>  
>  switch (addr & 0xff) {
>  case FTGMAC100_ISR: /* Interrupt status */
> @@ -711,14 +771,11 @@ static void ftgmac100_write(void *opaque, hwaddr addr,
>  break;
>  
>  case FTGMAC100_PHYCR:  /* PHY Device control */
> -reg = FTGMAC100_PHYCR_REG(value);
>  s->phycr = value;
> -if (valu

Re: [Qemu-devel] [PATCH] gitdm: Add other IBMers

2019-01-02 Thread Andrew Jeffery
On Wed, 2 Jan 2019, at 21:36, Joel Stanley wrote:
> Here are some IBMers who use their personal addresses when submitting
> patches.
> 
> Signed-off-by: Joel Stanley 

For the addition of my address:

Acked-by: Andrew Jeffery 

> ---
>  contrib/gitdm/group-map-ibm | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/contrib/gitdm/group-map-ibm b/contrib/gitdm/group-map-ibm
> index b66db5f4a825..6c0570107d65 100644
> --- a/contrib/gitdm/group-map-ibm
> +++ b/contrib/gitdm/group-map-ibm
> @@ -2,5 +2,10 @@
>  # Some IBM contributors submit via another domain
>  #
>  
> +a...@ozlabs.ru
> +and...@aj.id.au
> +b...@kernel.crashing.org
>  c...@kaod.org
>  gr...@kaod.org
> +j...@jms.id.au
> +sjitindarsi...@gmail.com
> -- 
> 2.19.1
> 



Re: [Qemu-devel] [RFC PATCH 1/1] memory: Support unaligned accesses on aligned-only models

2018-09-20 Thread Andrew Jeffery
On Thu, 20 Sep 2018, at 21:43, Cédric Le Goater wrote:
> Andrew,
> 
> On 07/14/2017 08:20 AM, Andrew Jeffery wrote:
> > Hi Paolo,
> > 
> > Thanks for taking a look!
> > 
> > On Thu, 2017-07-13 at 14:05 +0200, Paolo Bonzini wrote:
> >> On 30/06/2017 05:00, Andrew Jeffery wrote:
> >>> This RFC patch stems from a discussion on a patch for an ADC model[1] 
> >>> where it
> >>> was pointed out that I should be able to use the .impl member of
> >>> MemoryRegionOps to constrain how my read() and write() callbacks where 
> >>> invoked.
> >>>
> >>> I tried Phil's suggested approach and found I got reads of size 4, but 
> >>> with an
> >>> address that was not 4-byte aligned.
> >>>
> >>> Looking at the source for access_with_adjusted_size() lead to the comment
> >>>
> >>>  /* FIXME: support unaligned access? */
> >>>
> >>> which at least suggests that the implementation isn't complete.
> >>>
> >>> So, this patch is a quick and incomplete attempt at resolving the issue 
> >>> to see
> >>> whether I'm on the right track or way off in the weeds.
> >>>
> >>> I've lightly tested it with the ADC model mentioned above, and it appears 
> >>> to do
> >>> the right thing (I changed the values generated by the ADC to distinguish
> >>> between the lower and upper 16 bits).
> >>
> >> I think the idea is okay.
> >>
> >>> +access_addr[0] = align_down(addr, access_size);
> >>> +access_addr[1] = align_up(addr + size, access_size);
> >>> +
> >>> +for (cur = access_addr[0]; cur < access_addr[1]; cur += 
> >>> access_size) {
> >>> +uint64_t mask_bounds[2];
> >>> +mask_bounds[0] = MAX(addr, cur) - cur;
> >>> +mask_bounds[1] =
> >>> +MIN(addr + size, align_up(cur + 1, access_size)) - cur;
> >>> +
> >>> +access_mask = (-1ULL << mask_bounds[0] * 8) &
> >>> +(-1ULL >> (64 - mask_bounds[1] * 8));
> >>
> >> Please use MAKE_64BIT_MASK.
> > 
> > Okay.
> > 
> >>
> >>> +r |= access(mr, cur, _value, access_size,
> >>> +  (MAX(addr, cur) - addr), access_mask, attrs);
> >>> +
> >>> +/* XXX: Can't do this hack for writes */
> >>> +access_value >>= mask_bounds[0] * 8;
> >>> +}
> >>
> >> Can you subtract access_addr[0] from mask_bounds[0] and mask_bounds[1]
> >> (instead of cur) to remove the need for this right shift?
> > 
> > I haven't looked at the patch since I sent it. Given you think the idea
> > of the patch is okay I'll get back to working on it and think about
> > this.
> 
> We have been using successfully this patch for over a year now and it 
> would be nice to get it merged along with the ADC model. Do you have 
> a new version addressing Paolo's remarks ?

Aggh, no :( I've been meaning to get to it, but have been significantly 
distracted
for quite some time now. I'm not sure when I'll be able to look at it. I'm 
happy for
someone else to have a crack at fixing it in the mean time :)

Thanks for the reminder.

Andrew



Re: [Qemu-devel] [PATCH] aspeed: Implement write-1-{set, clear} for AST2500 strapping

2018-07-12 Thread Andrew Jeffery
On Fri, 13 Jul 2018, at 01:28, Peter Maydell wrote:
> On 9 July 2018 at 15:35, Andrew Jeffery  wrote:
> > The AST2500 SoC family changes the runtime behaviour of the hardware
> > strapping register (SCU70) to write-1-set/write-1-clear, with
> > write-1-clear implemented on the "read-only" SoC revision register
> > (SCU7C). For the the AST2400, the hardware strapping is
> > runtime-configured with read-modify-write semantics.
> >
> > Signed-off-by: Andrew Jeffery 
> > ---
> 
> Hi -- is this a bugfix suitable for 3.0, or something you'd
> like to wait until 3.1 ? The commit message sounds like a bugfix...

If we could get it into 3.0 that would be great. I ran into a case where the 
distinction was important so it would be good to have it resolved sooner rather 
than later.

Cheers,

Andrew



[Qemu-devel] [PATCH] aspeed: Implement write-1-{set, clear} for AST2500 strapping

2018-07-09 Thread Andrew Jeffery
The AST2500 SoC family changes the runtime behaviour of the hardware
strapping register (SCU70) to write-1-set/write-1-clear, with
write-1-clear implemented on the "read-only" SoC revision register
(SCU7C). For the the AST2400, the hardware strapping is
runtime-configured with read-modify-write semantics.

Signed-off-by: Andrew Jeffery 
---
 hw/misc/aspeed_scu.c | 19 +--
 include/hw/misc/aspeed_scu.h |  2 ++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 5e6d5744eeca..9051767cbbcd 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -202,11 +202,26 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, 
uint64_t data,
 case PROT_KEY:
 s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
 return;
-
+case HW_STRAP1:
+if (ASPEED_IS_AST2500(s->regs[SILICON_REV])) {
+s->regs[HW_STRAP1] |= data;
+return;
+}
+/* Jump to assignment below */
+break;
+case SILICON_REV:
+if (ASPEED_IS_AST2500(s->regs[SILICON_REV])) {
+s->regs[HW_STRAP1] &= ~data;
+} else {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
+  __func__, offset);
+}
+/* Avoid assignment below, we've handled everything */
+return;
 case FREQ_CNTR_EVAL:
 case VGA_SCRATCH1 ... VGA_SCRATCH8:
 case RNG_DATA:
-case SILICON_REV:
 case FREE_CNTR4:
 case FREE_CNTR4_EXT:
 qemu_log_mask(LOG_GUEST_ERROR,
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index d70cc0aeca61..169611a211bb 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -37,6 +37,8 @@ typedef struct AspeedSCUState {
 #define AST2500_A0_SILICON_REV   0x04000303U
 #define AST2500_A1_SILICON_REV   0x04010303U
 
+#define ASPEED_IS_AST2500(si_rev) si_rev) >> 24) & 0xff) == 0x04)
+
 extern bool is_supported_silicon_rev(uint32_t silicon_rev);
 
 #define ASPEED_SCU_PROT_KEY  0x1688A8A8
-- 
2.17.1




Re: [Qemu-devel] [PATCH] MAINTAINERS: Add ASPEED BMCs

2018-06-25 Thread Andrew Jeffery
On Mon, 25 Jun 2018, at 20:43, Philippe Mathieu-Daudé wrote:
> Hi Joel,
> 
> On 06/25/2018 08:07 AM, Joel Stanley wrote:
> > This adds Cedric as the maintainer, with Andrew and I as reviewers, for
> > the ASPEED boards and the peripherals we use.
> 
> Good idea, this should speed up ASPEED reviews.
> 
> > 
> > Signed-off-by: Joel Stanley 
> > ---
> >  MAINTAINERS | 11 +++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 2874ddce6097..14bcf2ed3e3d 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -644,6 +644,17 @@ M: Subbaraya Sundeep 
> >  S: Maintained
> >  F: hw/arm/msf2-som.c
> >  
> > +ASPEED BMCs
> > +M: Cédric Le Goater 
> > +R: Andrew Jeffery 
> > +R: Joel Stanley 
> > +L: qemu-...@nongnu.org
> > +S: Maintained
> > +F: hw/*/*aspeed*
> > +F: include/*/*aspeed*
> 
> This line does not match, however include/hw/*/*aspeed* does.
> 
> With that fixed:
> Reviewed-by: Philippe Mathieu-Daudé 

Similarly:

Reviewed-by: Andrew Jeffery 

> 
> > +F: hw/net/ftgmac100.c
> > +F: include/hw/net/ftgmac100.h
> > +
> >  CRIS Machines
> >  -
> >  Axis Dev88
> > 



Re: [Qemu-devel] [PATCH 3/3] aspeed/smc: rename aspeed_smc_flash_send_addr() to aspeed_smc_flash_setup()

2018-06-25 Thread Andrew Jeffery
On Tue, 12 Jun 2018, at 16:27, Cédric Le Goater wrote:
> Also handle the fake transfers for dummy bytes in this setup
> routine. It will be useful when we activate MMIO execution.
> 
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Andrew Jeffery 

> ---
>  hw/ssi/aspeed_smc.c | 31 ---
>  1 file changed, 16 insertions(+), 15 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index b15370893583..b29bfd3124a9 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -503,10 +503,11 @@ static int aspeed_smc_flash_dummies(const 
> AspeedSMCFlash *fl)
>  return dummies;
>  }
>  
> -static void aspeed_smc_flash_send_addr(AspeedSMCFlash *fl, uint32_t addr)
> +static void aspeed_smc_flash_setup(AspeedSMCFlash *fl, uint32_t addr)
>  {
>  const AspeedSMCState *s = fl->controller;
>  uint8_t cmd = aspeed_smc_flash_cmd(fl);
> +int i;
>  
>  /* Flash access can not exceed CS segment */
>  addr = aspeed_smc_check_segment_addr(fl, addr);
> @@ -519,6 +520,18 @@ static void 
> aspeed_smc_flash_send_addr(AspeedSMCFlash *fl, uint32_t addr)
>  ssi_transfer(s->spi, (addr >> 16) & 0xff);
>  ssi_transfer(s->spi, (addr >> 8) & 0xff);
>  ssi_transfer(s->spi, (addr & 0xff));
> +
> +/*
> + * Use fake transfers to model dummy bytes. The value should
> + * be configured to some non-zero value in fast read mode and
> + * zero in read mode. But, as the HW allows inconsistent
> + * settings, let's check for fast read mode.
> + */
> +if (aspeed_smc_flash_mode(fl) == CTRL_FREADMODE) {
> +for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
> +ssi_transfer(fl->controller->spi, 0xFF);
> +}
> +}
>  }
>  
>  static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, 
> unsigned size)
> @@ -537,19 +550,7 @@ static uint64_t aspeed_smc_flash_read(void *opaque, 
> hwaddr addr, unsigned size)
>  case CTRL_READMODE:
>  case CTRL_FREADMODE:
>  aspeed_smc_flash_select(fl);
> -aspeed_smc_flash_send_addr(fl, addr);
> -
> -/*
> - * Use fake transfers to model dummy bytes. The value should
> - * be configured to some non-zero value in fast read mode and
> - * zero in read mode. But, as the HW allows inconsistent
> - * settings, let's check for fast read mode.
> - */
> -if (aspeed_smc_flash_mode(fl) == CTRL_FREADMODE) {
> -for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
> -ssi_transfer(fl->controller->spi, 0xFF);
> -}
> -}
> +aspeed_smc_flash_setup(fl, addr);
>  
>  for (i = 0; i < size; i++) {
>  ret |= ssi_transfer(s->spi, 0x0) << (8 * i);
> @@ -586,7 +587,7 @@ static void aspeed_smc_flash_write(void *opaque, 
> hwaddr addr, uint64_t data,
>  break;
>  case CTRL_WRITEMODE:
>  aspeed_smc_flash_select(fl);
> -aspeed_smc_flash_send_addr(fl, addr);
> +aspeed_smc_flash_setup(fl, addr);
>  
>  for (i = 0; i < size; i++) {
>  ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
> -- 
> 2.13.6
> 
> 



Re: [Qemu-devel] [PATCH 2/3] aspeed/smc: fix HW strapping

2018-06-25 Thread Andrew Jeffery
On Tue, 12 Jun 2018, at 16:27, Cédric Le Goater wrote:
> Only the flash type is strapped by HW. The 4BYTE mode is set by
> firmware when the flash device is detected.
> 
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Andrew Jeffery 

> ---
>  hw/ssi/aspeed_smc.c | 8 +---
>  1 file changed, 1 insertion(+), 7 deletions(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index fce126e6ee92..b15370893583 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -639,23 +639,17 @@ static void aspeed_smc_reset(DeviceState *d)
>  aspeed_smc_segment_to_reg(>ctrl->segments[i]);
>  }
>  
> -/* HW strapping for AST2500 FMC controllers  */
> +/* HW strapping flash type for FMC controllers  */
>  if (s->ctrl->segments == aspeed_segments_ast2500_fmc) {
>  /* flash type is fixed to SPI for CE0 and CE1 */
>  s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0);
>  s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1);
> -
> -/* 4BYTE mode is autodetected for CE0. Let's force it to 1 for
> - * now */
> -s->regs[s->r_ce_ctrl] |= (1 << (CTRL_EXTENDED0));
>  }
>  
>  /* HW strapping for AST2400 FMC controllers (SCU70). Let's use the
>   * configuration of the palmetto-bmc machine */
>  if (s->ctrl->segments == aspeed_segments_fmc) {
>  s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0);
> -
> -s->regs[s->r_ce_ctrl] |= (1 << (CTRL_EXTENDED0));
>  }
>  }
>  
> -- 
> 2.13.6
> 
> 



Re: [Qemu-devel] [Qemu-arm] [PATCH 1/3] aspeed/smc: fix dummy cycles count when in dual IO mode

2018-06-25 Thread Andrew Jeffery
On Tue, 12 Jun 2018, at 16:27, Cédric Le Goater wrote:
> When configured in dual I/O mode, address and data are sent in dual
> mode, including the dummy byte cycles in between. Adapt the count to
> the IO setting.
> 
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Andrew Jeffery 

> ---
>  hw/ssi/aspeed_smc.c | 9 -
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 5059396bc623..fce126e6ee92 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -66,6 +66,8 @@
>  
>  /* CEx Control Register */
>  #define R_CTRL0   (0x10 / 4)
> +#define   CTRL_IO_DUAL_DATA(1 << 29)
> +#define   CTRL_IO_DUAL_ADDR_DATA   (1 << 28) /* Includes dummies */
>  #define   CTRL_CMD_SHIFT   16
>  #define   CTRL_CMD_MASK0xff
>  #define   CTRL_DUMMY_HIGH_SHIFT14
> @@ -492,8 +494,13 @@ static int aspeed_smc_flash_dummies(const 
> AspeedSMCFlash *fl)
>  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;
> +uint32_t dummies = ((dummy_high << 2) | dummy_low) * 8;
>  
> -return ((dummy_high << 2) | dummy_low) * 8;
> +if (r_ctrl0 & CTRL_IO_DUAL_ADDR_DATA) {
> +dummies /= 2;
> +}
> +
> +return dummies;
>  }
>  
>  static void aspeed_smc_flash_send_addr(AspeedSMCFlash *fl, uint32_t addr)
> -- 
> 2.13.6
> 
> 



Re: [Qemu-devel] [PATCH v2 3/3] aspeed/timer: use the APB frequency from the SCU

2018-06-24 Thread Andrew Jeffery
On Fri, 22 Jun 2018, at 17:27, Cédric Le Goater wrote:
> The timer controller can be driven by either an external 1MHz clock or
> by the APB clock. Today, the model makes the assumption that the APB
> frequency is always set to 24MHz but this is incorrect.
> 
> The AST2400 SoC on the palmetto machines uses a 48MHz input clock
> source and the APB can be set to 48MHz. The consequence is a general
> system slowdown. The QEMU machines using the AST2500 SoC do not seem
> impacted today because the APB frequency is still set to 24MHz.
> 
> We fix the timer frequency for all SoCs by linking the Timer model to
> the SCU model. The APB frequency driving the timers is now the one
> configured for the SoC.
> 
> Signed-off-by: Cédric Le Goater 
> Reviewed-by: Joel Stanley 

Reviewed-by: Andrew Jeffery 

> ---
>  include/hw/timer/aspeed_timer.h |  4 
>  hw/arm/aspeed_soc.c |  2 ++
>  hw/timer/aspeed_timer.c | 19 +++
>  3 files changed, 21 insertions(+), 4 deletions(-)
> 
> diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h
> index bd6c1a7f9609..040a08873432 100644
> --- a/include/hw/timer/aspeed_timer.h
> +++ b/include/hw/timer/aspeed_timer.h
> @@ -24,6 +24,8 @@
>  
>  #include "qemu/timer.h"
>  
> +typedef struct AspeedSCUState AspeedSCUState;
> +
>  #define ASPEED_TIMER(obj) \
>  OBJECT_CHECK(AspeedTimerCtrlState, (obj), TYPE_ASPEED_TIMER);
>  #define TYPE_ASPEED_TIMER "aspeed.timer"
> @@ -55,6 +57,8 @@ typedef struct AspeedTimerCtrlState {
>  uint32_t ctrl;
>  uint32_t ctrl2;
>  AspeedTimer timers[ASPEED_TIMER_NR_TIMERS];
> +
> +AspeedSCUState *scu;
>  } AspeedTimerCtrlState;
>  
>  #endif /* ASPEED_TIMER_H */
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 7cc05ee27ea4..e68911af0f90 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -127,6 +127,8 @@ static void aspeed_soc_init(Object *obj)
>  
>  object_initialize(>timerctrl, sizeof(s->timerctrl), 
> TYPE_ASPEED_TIMER);
>  object_property_add_child(obj, "timerctrl", OBJECT(>timerctrl), NULL);
> +object_property_add_const_link(OBJECT(>timerctrl), "scu",
> +   OBJECT(>scu), _abort);
>  qdev_set_parent_bus(DEVICE(>timerctrl), sysbus_get_default());
>  
>  object_initialize(>i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
> diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
> index 1e31e22b6f1f..5e3f51b66b43 100644
> --- a/hw/timer/aspeed_timer.c
> +++ b/hw/timer/aspeed_timer.c
> @@ -10,8 +10,10 @@
>   */
>  
>  #include "qemu/osdep.h"
> +#include "qapi/error.h"
>  #include "hw/sysbus.h"
>  #include "hw/timer/aspeed_timer.h"
> +#include "hw/misc/aspeed_scu.h"
>  #include "qemu-common.h"
>  #include "qemu/bitops.h"
>  #include "qemu/timer.h"
> @@ -26,7 +28,6 @@
>  #define TIMER_CLOCK_USE_EXT true
>  #define TIMER_CLOCK_EXT_HZ 100
>  #define TIMER_CLOCK_USE_APB false
> -#define TIMER_CLOCK_APB_HZ 2400
>  
>  #define TIMER_REG_STATUS 0
>  #define TIMER_REG_RELOAD 1
> @@ -80,11 +81,11 @@ static inline bool timer_external_clock(AspeedTimer *t)
>  return timer_ctrl_status(t, op_external_clock);
>  }
>  
> -static uint32_t clock_rates[] = { TIMER_CLOCK_APB_HZ, TIMER_CLOCK_EXT_HZ };
> -
>  static inline uint32_t calculate_rate(struct AspeedTimer *t)
>  {
> -return clock_rates[timer_external_clock(t)];
> +AspeedTimerCtrlState *s = timer_to_ctrl(t);
> +
> +return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ : s->scu->apb_freq;
>  }
>  
>  static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t 
> now_ns)
> @@ -449,6 +450,16 @@ static void aspeed_timer_realize(DeviceState *dev, 
> Error **errp)
>  int i;
>  SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>  AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
> +Object *obj;
> +Error *err = NULL;
> +
> +obj = object_property_get_link(OBJECT(dev), "scu", );
> +if (!obj) {
> +error_propagate(errp, err);
> +error_prepend(errp, "required link 'scu' not found: ");
> +return;
> +}
> +s->scu = ASPEED_SCU(obj);
>  
>  for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
>  aspeed_init_one_timer(s, i);
> -- 
> 2.13.6
> 



Re: [Qemu-devel] [PATCH v2 2/3] aspeed: initialize the SCU controller first

2018-06-24 Thread Andrew Jeffery
On Fri, 22 Jun 2018, at 17:26, Cédric Le Goater wrote:
> The System Control Unit should be initialized first as it drives all
> the configuration of the SoC and other device models.
> 
> Signed-off-by: Cédric Le Goater 
> Reviewed-by: Joel Stanley 

Acked-by: Andrew Jeffery 

> ---
>  hw/arm/aspeed_soc.c | 40 
>  1 file changed, 20 insertions(+), 20 deletions(-)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 1955a892f4a4..7cc05ee27ea4 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -109,18 +109,6 @@ static void aspeed_soc_init(Object *obj)
>  object_initialize(>cpu, sizeof(s->cpu), sc->info->cpu_type);
>  object_property_add_child(obj, "cpu", OBJECT(>cpu), NULL);
>  
> -object_initialize(>vic, sizeof(s->vic), TYPE_ASPEED_VIC);
> -object_property_add_child(obj, "vic", OBJECT(>vic), NULL);
> -qdev_set_parent_bus(DEVICE(>vic), sysbus_get_default());
> -
> -object_initialize(>timerctrl, sizeof(s->timerctrl), 
> TYPE_ASPEED_TIMER);
> -object_property_add_child(obj, "timerctrl", OBJECT(>timerctrl), NULL);
> -qdev_set_parent_bus(DEVICE(>timerctrl), sysbus_get_default());
> -
> -object_initialize(>i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
> -object_property_add_child(obj, "i2c", OBJECT(>i2c), NULL);
> -qdev_set_parent_bus(DEVICE(>i2c), sysbus_get_default());
> -
>  object_initialize(>scu, sizeof(s->scu), TYPE_ASPEED_SCU);
>  object_property_add_child(obj, "scu", OBJECT(>scu), NULL);
>  qdev_set_parent_bus(DEVICE(>scu), sysbus_get_default());
> @@ -133,6 +121,18 @@ static void aspeed_soc_init(Object *obj)
>  object_property_add_alias(obj, "hw-prot-key", OBJECT(>scu),
>"hw-prot-key", _abort);
>  
> +object_initialize(>vic, sizeof(s->vic), TYPE_ASPEED_VIC);
> +object_property_add_child(obj, "vic", OBJECT(>vic), NULL);
> +qdev_set_parent_bus(DEVICE(>vic), sysbus_get_default());
> +
> +object_initialize(>timerctrl, sizeof(s->timerctrl), 
> TYPE_ASPEED_TIMER);
> +object_property_add_child(obj, "timerctrl", OBJECT(>timerctrl), 
> NULL);
> +qdev_set_parent_bus(DEVICE(>timerctrl), sysbus_get_default());
> +
> +object_initialize(>i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
> +object_property_add_child(obj, "i2c", OBJECT(>i2c), NULL);
> +qdev_set_parent_bus(DEVICE(>i2c), sysbus_get_default());
> +
>  object_initialize(>fmc, sizeof(s->fmc), sc->info->fmc_typename);
>  object_property_add_child(obj, "fmc", OBJECT(>fmc), NULL);
>  qdev_set_parent_bus(DEVICE(>fmc), sysbus_get_default());
> @@ -195,6 +195,14 @@ static void aspeed_soc_realize(DeviceState *dev, 
> Error **errp)
>  memory_region_add_subregion(get_system_memory(), 
> ASPEED_SOC_SRAM_BASE,
>  >sram);
>  
> +/* SCU */
> +object_property_set_bool(OBJECT(>scu), true, "realized", );
> +if (err) {
> +error_propagate(errp, err);
> +return;
> +}
> +sysbus_mmio_map(SYS_BUS_DEVICE(>scu), 0, ASPEED_SOC_SCU_BASE);
> +
>  /* VIC */
>  object_property_set_bool(OBJECT(>vic), true, "realized", );
>  if (err) {
> @@ -219,14 +227,6 @@ static void aspeed_soc_realize(DeviceState *dev, 
> Error **errp)
>  sysbus_connect_irq(SYS_BUS_DEVICE(>timerctrl), i, irq);
>  }
>  
> -/* SCU */
> -object_property_set_bool(OBJECT(>scu), true, "realized", );
> -if (err) {
> -error_propagate(errp, err);
> -return;
> -}
> -sysbus_mmio_map(SYS_BUS_DEVICE(>scu), 0, ASPEED_SOC_SCU_BASE);
> -
>  /* UART - attach an 8250 to the IO space as our UART5 */
>  if (serial_hd(0)) {
>  qemu_irq uart5 = qdev_get_gpio_in(DEVICE(>vic), uart_irqs[4]);
> -- 
> 2.13.6
> 



Re: [Qemu-devel] [PATCH v2 1/3] aspeed/scu: introduce clock frequencies

2018-06-24 Thread Andrew Jeffery
On Fri, 22 Jun 2018, at 17:26, Cédric Le Goater wrote:
> All Aspeed SoC clocks are driven by an input source clock which can
> have different frequencies : 24MHz or 25MHz, and also, on the Aspeed
> AST2400 SoC, 48MHz. The H-PLL (CPU) clock is defined from a
> calculation using parameters in the H-PLL Parameter register or from a
> predefined set of frequencies if the setting is strapped by hardware
> (Aspeed AST2400 SoC). The other clocks of the SoC are then defined
> from the H-PLL using dividers.
> 
> We introduce first the APB clock because it should be used to drive
> the Aspeed timer model.
> 
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Andrew Jeffery 

> ---
>  include/hw/misc/aspeed_scu.h |  70 ++--
>  hw/misc/aspeed_scu.c | 106 
> +++
>  2 files changed, 172 insertions(+), 4 deletions(-)
> 
> diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
> index d70cc0aeca61..f662c38188f4 100644
> --- a/include/hw/misc/aspeed_scu.h
> +++ b/include/hw/misc/aspeed_scu.h
> @@ -30,6 +30,10 @@ typedef struct AspeedSCUState {
>  uint32_t hw_strap1;
>  uint32_t hw_strap2;
>  uint32_t hw_prot_key;
> +
> +uint32_t clkin;
> +uint32_t hpll;
> +uint32_t apb_freq;
>  } AspeedSCUState;
>  
>  #define AST2400_A0_SILICON_REV   0x02000303U
> @@ -58,7 +62,64 @@ extern bool is_supported_silicon_rev(uint32_t silicon_rev);
>   *   1. 2012/12/29 Ryan Chen Create
>   */
>  
> -/* Hardware Strapping Register definition (for Aspeed AST2400 SOC)
> +/* SCU08   Clock Selection Register
> + *
> + *  31 Enable Video Engine clock dynamic slow down
> + *  30:28  Video Engine clock slow down setting
> + *  27 2D Engine GCLK clock source selection
> + *  26 2D Engine GCLK clock throttling enable
> + *  25:23  APB PCLK divider selection
> + *  22:20  LPC Host LHCLK divider selection
> + *  19 LPC Host LHCLK clock generation/output enable control
> + *  18:16  MAC AHB bus clock divider selection
> + *  15 SD/SDIO clock running enable
> + *  14:12  SD/SDIO divider selection
> + *  11 Reserved
> + *  10:8   Video port output clock delay control bit
> + *  7  ARM CPU/AHB clock slow down enable
> + *  6:4ARM CPU/AHB clock slow down setting
> + *  3:2ECLK clock source selection
> + *  1  CPU/AHB clock slow down idle timer
> + *  0  CPU/AHB clock dynamic slow down enable (defined in bit[6:4])
> + */
> +#define SCU_CLK_GET_PCLK_DIV(x)(((x) >> 23) & 0x7)
> +
> +/* SCU24   H-PLL Parameter Register (for Aspeed AST2400 SOC)
> + *
> + *  18 H-PLL parameter selection
> + *   0: Select H-PLL by strapping resistors
> + *   1: Select H-PLL by the programmed registers (SCU24[17:0])
> + *  17 Enable H-PLL bypass mode
> + *  16 Turn off H-PLL
> + *  10:5   H-PLL Numerator
> + *  4  H-PLL Output Divider
> + *  3:0H-PLL Denumerator
> + *
> + *  (Output frequency) = 24MHz * (2-OD) * [(Numerator+2) / (Denumerator
> +1)]
> + */
> +
> +#define SCU_AST2400_H_PLL_PROGRAMMED   (0x1 << 18)
> +#define SCU_AST2400_H_PLL_BYPASS_EN(0x1 << 17)
> +#define SCU_AST2400_H_PLL_OFF  (0x1 << 16)
> +
> +/* SCU24   H-PLL Parameter Register (for Aspeed AST2500 SOC)
> + *
> + *  21 Enable H-PLL reset
> + *  20 Enable H-PLL bypass mode
> + *  19 Turn off H-PLL
> + *  18:13  H-PLL Post Divider
> + *  12:5   H-PLL Numerator (M)
> + *  4:0H-PLL Denumerator (N)
> + *
> + *  (Output frequency) = CLKIN(24MHz) * [(M+1) / (N+1)] / (P+1)
> + *
> + * The default frequency is 792Mhz when CLKIN = 24MHz
> + */
> +
> +#define SCU_H_PLL_BYPASS_EN(0x1 << 20)
> +#define SCU_H_PLL_OFF  (0x1 << 19)
> +
> +/* SCU70  Hardware Strapping Register definition (for Aspeed AST2400 
> SOC)
>   *
>   * 31:29  Software defined strapping registers
>   * 28:27  DRAM size setting (for VGA driver use)
> @@ -107,12 +168,13 @@ extern bool is_supported_silicon_rev(uint32_t 
> silicon_rev);
>  #define SCU_AST2400_HW_STRAP_GET_CLK_SOURCE(x) (x) >> 23) & 
> 0x1) << 1) \
>  | (((x) >> 18) & 
> 0x1))
>  #define SCU_AST2400_HW_STRAP_CLK_SOURCE_MASK   ((0x1 << 23) | (0x1 
> << 18))
> -#define AST2400_CLK_25M_IN (0x1 << 23)
> +#define SCU_HW_STRAP_CLK_25M_IN(0x1 << 23)
>  #define AST2400_CLK_24M_IN 0
>  #define AST2400_CLK_48M_IN

Re: [Qemu-devel] [PATCH] Fix ast2500 protection register emulation

2018-02-20 Thread Andrew Jeffery
On Tue, 20 Feb 2018, at 23:56, Hugo Landau wrote:
> Some register blocks of the ast2500 are protected by protection key
> registers which require the right magic value to be written to those
> registers to allow those registers to be mutated.
> 
> Register manuals indicate that writing the correct magic value to these
> registers should cause subsequent reads from those values to return 1,
> and writing any other value should cause subsequent reads to return 0.
> 
> Previously, qemu implemented these registers incorrectly: the registers
> were handled as simple memory, meaning that writing some value x to a
> protection key register would result in subsequent reads from that
> register returning the same value x. The protection was implemented by
> ensuring that the current value of that register equaled the magic
> value.
> 
> This modifies qemu to have the correct behaviour: attempts to write to a
> ast2500 protection register results in a transition to 1 or 0 depending
> on whether the written value is the correct magic. The protection logic
> is updated to ensure that the value of the register is nonzero.
> 
> This bug caused deadlocks with u-boot HEAD: when u-boot is done with a
> protectable register block, it attempts to lock it by writing the
> bitwise inverse of the correct magic value, and then spinning forever
> until the register reads as zero. Since qemu implemented writes to these
> registers as ordinary memory writes, writing the inverse of the magic
> value resulted in subsequent reads returning that value, leading to
> u-boot spinning forever.
> 
> Signed-off-by: Hugo Landau <hlan...@devever.net>

Acked-by: Andrew Jeffery <and...@aj.id.au>

> ---
>  hw/misc/aspeed_scu.c  | 6 +-
>  hw/misc/aspeed_sdmc.c | 8 +++-
>  2 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index 74537ce975..5e6d5744ee 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -191,7 +191,7 @@ static void aspeed_scu_write(void *opaque, hwaddr 
> offset, uint64_t data,
>  }
>  
>  if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
> -s->regs[PROT_KEY] != ASPEED_SCU_PROT_KEY) {
> +!s->regs[PROT_KEY]) {
>  qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", 
> __func__);
>  return;
>  }
> @@ -199,6 +199,10 @@ static void aspeed_scu_write(void *opaque, hwaddr 
> offset, uint64_t data,
>  trace_aspeed_scu_write(offset, size, data);
>  
>  switch (reg) {
> +case PROT_KEY:
> +s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
> +return;
> +
>  case FREQ_CNTR_EVAL:
>  case VGA_SCRATCH1 ... VGA_SCRATCH8:
>  case RNG_DATA:
> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
> index f0b3053fae..265171ee42 100644
> --- a/hw/misc/aspeed_sdmc.c
> +++ b/hw/misc/aspeed_sdmc.c
> @@ -110,7 +110,12 @@ static void aspeed_sdmc_write(void *opaque, hwaddr 
> addr, uint64_t data,
>  return;
>  }
>  
> -if (addr != R_PROT && s->regs[R_PROT] != PROT_KEY_UNLOCK) {
> +if (addr == R_PROT) {
> +  s->regs[addr] = (data == PROT_KEY_UNLOCK) ? 1 : 0;
> +  return;
> +}
> +
> +if (!s->regs[R_PROT]) {
>  qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", 
> __func__);
>  return;
>  }
> @@ -123,6 +128,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr 
> addr, uint64_t data,
>  data &= ~ASPEED_SDMC_READONLY_MASK;
>  break;
>  case AST2500_A0_SILICON_REV:
> +case AST2500_A1_SILICON_REV:
>  data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
>  break;
>  default:
> -- 
> 2.15.0
> 
> 



Re: [Qemu-devel] [PATCH v2 2/2] hw/arm/aspeed: simplify using the 'unimplemented device' for aspeed_soc.io

2018-02-11 Thread Andrew Jeffery
On Fri, 2018-02-09 at 05:57 -0300, Philippe Mathieu-Daudé wrote:
> (qemu) info mtree
>  address-space: cpu-memory-0
>- (prio 0, i/o): system
>  -07ff (prio 0, rom): aspeed.boot_rom
> -1e60-1e7f (prio -1, i/o): aspeed_soc.io
> +1e60-1e7f (prio -1000, i/o): aspeed_soc.io
>  1e62-1e6200ff (prio 0, i/o): aspeed.smc.ast2500-fmc
>  1e63-1e6300ff (prio 0, i/o): aspeed.smc.ast2500-spi1
>  1e631000-1e6310ff (prio 0, i/o): aspeed.smc.ast2500-spi2
> 
> Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org>
> Reviewed-by: Cédric Le Goater <c...@kaod.org>

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

> ---
>  include/hw/arm/aspeed_soc.h |  1 -
>  hw/arm/aspeed_soc.c | 32 +++-
>  2 files changed, 3 insertions(+), 30 deletions(-)
> 
> diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
> index f26914a2b9..11ec0179db 100644
> --- a/include/hw/arm/aspeed_soc.h
> +++ b/include/hw/arm/aspeed_soc.h
> @@ -31,7 +31,6 @@ typedef struct AspeedSoCState {
>  
>  /*< public >*/
>  ARMCPU cpu;
> -MemoryRegion iomem;
>  MemoryRegion sram;
>  AspeedVICState vic;
>  AspeedTimerCtrlState timerctrl;
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 2a5d041b3b..30d25f8b06 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -15,6 +15,7 @@
>  #include "qemu-common.h"
>  #include "cpu.h"
>  #include "exec/address-spaces.h"
> +#include "hw/misc/unimp.h"
>  #include "hw/arm/aspeed_soc.h"
>  #include "hw/char/serial.h"
>  #include "qemu/log.h"
> @@ -99,31 +100,6 @@ static const AspeedSoCInfo aspeed_socs[] = {
>  },
>  };
>  
> -/*
> - * IO handlers: simply catch any reads/writes to IO addresses that aren't
> - * handled by a device mapping.
> - */
> -
> -static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size)
> -{
> -qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
> -  __func__, offset, size);
> -return 0;
> -}
> -
> -static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value,
> -unsigned size)
> -{
> -qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " 
> [%u]\n",
> -  __func__, offset, value, size);
> -}
> -
> -static const MemoryRegionOps aspeed_soc_io_ops = {
> -.read = aspeed_soc_io_read,
> -.write = aspeed_soc_io_write,
> -.endianness = DEVICE_LITTLE_ENDIAN,
> -};
> -
>  static void aspeed_soc_init(Object *obj)
>  {
>  AspeedSoCState *s = ASPEED_SOC(obj);
> @@ -199,10 +175,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error 
> **errp)
>  Error *err = NULL, *local_err = NULL;
>  
>  /* IO space */
> -memory_region_init_io(>iomem, NULL, _soc_io_ops, NULL,
> -"aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE);
> -memory_region_add_subregion_overlap(get_system_memory(),
> -ASPEED_SOC_IOMEM_BASE, >iomem, 
> -1);
> +create_unimplemented_device("aspeed_soc.io",
> +ASPEED_SOC_IOMEM_BASE, 
> ASPEED_SOC_IOMEM_SIZE);
>  
>  /* CPU */
>  object_property_set_bool(OBJECT(>cpu), true, "realized", );

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH v2 1/2] hw/arm/aspeed: directly map the serial device to the system address space

2018-02-11 Thread Andrew Jeffery
On Fri, 2018-02-09 at 05:57 -0300, Philippe Mathieu-Daudé wrote:
> (qemu) info mtree
>  address-space: cpu-memory-0
>- (prio 0, i/o): system
>  -07ff (prio 0, rom): aspeed.boot_rom
>  1e60-1e7f (prio -1, i/o): aspeed_soc.io
> -  1e784000-1e78401f (prio 0, i/o): serial
>  1e62-1e6200ff (prio 0, i/o):
> aspeed.smc.ast2500-fmc
>  1e63-1e6300ff (prio 0, i/o):
> aspeed.smc.ast2500-spi1
>  [...]
>  1e72-1e728fff (prio 0, ram): aspeed.sram
>  1e782000-1e782fff (prio 0, i/o): aspeed.timer
> +1e784000-1e78401f (prio 0, i/o): serial
>  1e785000-1e78501f (prio 0, i/o): aspeed.wdt
>  1e785020-1e78503f (prio 0, i/o): aspeed.wdt
> 
> Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org>

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

> ---
>  hw/arm/aspeed_soc.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index c83b7e207b..2a5d041b3b 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -257,7 +257,8 @@ static void aspeed_soc_realize(DeviceState *dev,
> Error **errp)
>  /* UART - attach an 8250 to the IO space as our UART5 */
>  if (serial_hds[0]) {
>  qemu_irq uart5 = qdev_get_gpio_in(DEVICE(>vic),
> uart_irqs[4]);
> -serial_mm_init(>iomem, ASPEED_SOC_UART_5_BASE, 2,
> +serial_mm_init(get_system_memory(),
> +   ASPEED_SOC_IOMEM_BASE +
> ASPEED_SOC_UART_5_BASE, 2,
> uart5, 38400, serial_hds[0],
> DEVICE_LITTLE_ENDIAN);
>  }
>  

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH 1/2] hw/arm/aspeed: directly map the serial device to the system address space

2018-02-08 Thread Andrew Jeffery
On Thu, 2018-02-08 at 14:40 -0300, Philippe Mathieu-Daudé wrote:
> On 02/08/2018 02:30 PM, Peter Maydell wrote:
> > On 8 February 2018 at 17:22, Philippe Mathieu-Daudé  wrote:
> > > Signed-off-by: Philippe Mathieu-Daudé 
> > > ---
> > >  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 c83b7e207b..a786750e14 100644
> > > --- a/hw/arm/aspeed_soc.c
> > > +++ b/hw/arm/aspeed_soc.c
> > > @@ -257,7 +257,7 @@ static void aspeed_soc_realize(DeviceState *dev, 
> > > Error **errp)
> > >  /* UART - attach an 8250 to the IO space as our UART5 */
> > >  if (serial_hds[0]) {
> > >  qemu_irq uart5 = qdev_get_gpio_in(DEVICE(>vic), uart_irqs[4]);
> > > -serial_mm_init(>iomem, ASPEED_SOC_UART_5_BASE, 2,
> > > +serial_mm_init(get_system_memory(), ASPEED_SOC_UART_5_BASE, 2,
> > > uart5, 38400, serial_hds[0], 
> > > DEVICE_LITTLE_ENDIAN);
> > >  }
> > 
> > Is this a bug fix? It certainly changes behaviour, which
> > suggests that a fuller commit message would be useful.
> 
> This patch is buggy indeed, using system_memory the serial address
> should be ASPEED_SOC_IOMEM_BASE + ASPEED_SOC_UART_5_BASE.
> 

If you'd like to test, you can grab images from here:

https://openpower.xyz/job/openbmc-build/distro=ubuntu,target=romulus/

For example (without the patch):

$ wget 
https://openpower.xyz/job/openbmc-build/1240/distro=ubuntu,target=romulus/artifact/deploy/images/romulus/image-bmc
...
$ qemu-system-arm -M romulus-bmc -m 512 -drive file=image-bmc,if=mtd,format=raw 
-nographic


U-Boot 2016.07 (Jan 25 2018 - 16:31:27 +)   

   Watchdog enabled 
DRAM:  496 MiB  
Flash: 32 MiB   
*** Warning - bad CRC, using default environment

In:serial   
Out:   serial   
Err:   serial   
Net:   aspeednic#0  
Error: aspeednic#0 address not set. 

Hit any key to stop autoboot:  0
## Loading kernel from FIT Image at 2008 ...
...

And yeah, this patch breaks output.

Thanks for the cleanup though.

Andrew

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH v2] hw/arm/aspeed: Unlock SCU when running kernel

2017-11-13 Thread Andrew Jeffery
On Mon, 2017-11-13 at 23:58 +1030, Joel Stanley wrote:
> The ASPEED hardware contains a lock register for the SCU that disables
> any writes to the SCU when it is locked. The machine comes up with the
> lock enabled, but on all known hardware u-boot will unlock it and leave
> it unlocked when loading the kernel.
> 
> This means the kernel expects the SCU to be unlocked. When booting from
> an emulated ROM the normal u-boot unlock path is executed. Things don't
> go well when booting using the -kernel command line, as u-boot does not
> run first.
> 
> Change behaviour so that when a kernel is passed to the machine, set the
> reset value of the SCU to be unlocked.
> 
> Signed-off-by: Joel Stanley 
> ---
> v2:
>  - use the correct value for the key
>  - rename it ASPEED_SCU_PROT_KEY
> ---
>  hw/arm/aspeed.c  | 10 ++
>  hw/arm/aspeed_soc.c  |  2 ++
>  hw/misc/aspeed_scu.c |  5 +++--
>  include/hw/misc/aspeed_scu.h |  3 +++
>  4 files changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index ab895ad490af..754df8403273 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -36,6 +36,7 @@ typedef struct AspeedBoardState {
>  typedef struct AspeedBoardConfig {
>  const char *soc_name;
>  uint32_t hw_strap1;
> +uint32_t hw_prot_key;

It doesn't seem like this member is used?

With respect to the patch as a whole, I was planning to implement a
small kernel driver for the SCU to unlock it on probe but never got
around to it. However, this seems reasonable; I always worked around it
locally in a much more hacky fashion. It would be handy to have an
upstream solution.

Andrew

>  const char *fmc_model;
>  const char *spi_model;
>  uint32_t num_cs;
> @@ -186,6 +187,15 @@ static void aspeed_board_init(MachineState *machine,
>  _abort);
>  object_property_set_int(OBJECT(>soc), cfg->num_cs, "num-cs",
>  _abort);
> +if (machine->kernel_filename) {
> +/*
> + * When booting with a -kernel command line there is no u-boot
> + * that runs to unlock the SCU. In this case set the default to
> + * be unlocked as the kernel expects
> + */
> +object_property_set_int(OBJECT(>soc), ASPEED_SCU_PROT_KEY,
> +"hw-prot-key", _abort);
> +}
>  object_property_set_bool(OBJECT(>soc), true, "realized",
>   _abort);
>  
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 5aa3d2ddd9cd..c83b7e207b86 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -154,6 +154,8 @@ static void aspeed_soc_init(Object *obj)
>"hw-strap1", _abort);
>  object_property_add_alias(obj, "hw-strap2", OBJECT(>scu),
>"hw-strap2", _abort);
> +object_property_add_alias(obj, "hw-prot-key", OBJECT(>scu),
> +  "hw-prot-key", _abort);
>  
>  object_initialize(>fmc, sizeof(s->fmc), sc->info->fmc_typename);
>  object_property_add_child(obj, "fmc", OBJECT(>fmc), NULL);
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index 95022d3607ad..74537ce9755d 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -85,7 +85,6 @@
>  #define BMC_REV  TO_REG(0x19C)
>  #define BMC_DEV_ID   TO_REG(0x1A4)
>  
> -#define PROT_KEY_UNLOCK 0x1688A8A8
>  #define SCU_IO_REGION_SIZE 0x1000
>  
>  static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
> @@ -192,7 +191,7 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, 
> uint64_t data,
>  }
>  
>  if (reg > PROT_KEY && reg < CPU2_BASE_SEG1 &&
> -s->regs[PROT_KEY] != PROT_KEY_UNLOCK) {
> +s->regs[PROT_KEY] != ASPEED_SCU_PROT_KEY) {
>  qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
>  return;
>  }
> @@ -246,6 +245,7 @@ static void aspeed_scu_reset(DeviceState *dev)
>  s->regs[SILICON_REV] = s->silicon_rev;
>  s->regs[HW_STRAP1] = s->hw_strap1;
>  s->regs[HW_STRAP2] = s->hw_strap2;
> +s->regs[PROT_KEY] = s->hw_prot_key;
>  }
>  
>  static uint32_t aspeed_silicon_revs[] = {
> @@ -299,6 +299,7 @@ static Property aspeed_scu_properties[] = {
>  DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
>  DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
>  DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
> +DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState, hw_prot_key, 0),
>  DEFINE_PROP_END_OF_LIST(),
>  };
>  
> diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
> index bd4ac013f997..d70cc0aeca61 100644
> --- a/include/hw/misc/aspeed_scu.h
> +++ b/include/hw/misc/aspeed_scu.h
> @@ -29,6 +29,7 @@ typedef struct AspeedSCUState {
>  uint32_t silicon_rev;
>  uint32_t hw_strap1;
>  uint32_t 

Re: [Qemu-devel] [PATCH v2 1/6] aspeed: add support for the witherspoon-bmc board

2017-10-15 Thread Andrew Jeffery
On Wed, 2017-10-11 at 09:28 +0200, Cédric Le Goater wrote:
> On 10/11/2017 05:49 AM, Andrew Jeffery wrote:
> > On Tue, 2017-10-10 at 15:30 +0200, Cédric Le Goater wrote:
> > > On 10/09/2017 02:04 AM, Andrew Jeffery wrote:
> > > > On Wed, 2017-09-20 at 09:01 +0200, Cédric Le Goater wrote:
> > > > > The Witherspoon boards are OpenPOWER system hosting POWER9 Processors.
> > > > > Let's add support for their BMC including a couple of I2C devices as
> > > > > found on real HW.
> > > > >  
> > > > > > > > Signed-off-by: Cédric Le Goater <c...@kaod.org>
> > > > > 
> > > > > ---
> > > > >  hw/arm/aspeed.c | 49 
> > > > > +
> > > > >  1 file changed, 49 insertions(+)
> > > > >  
> > > > > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> > > > > index ab895ad490af..81f522f711ae 100644
> > > > > --- a/hw/arm/aspeed.c
> > > > > +++ b/hw/arm/aspeed.c
> > > > > @@ -46,6 +46,7 @@ enum {
> > > > >  PALMETTO_BMC,
> > > > >  AST2500_EVB,
> > > > >  ROMULUS_BMC,
> > > > > +WITHERSPOON_BMC,
> > > > >  };
> > > > >  
> > > > >  /* Palmetto hardware value: 0x120CE416 */
> > > > > @@ -83,8 +84,12 @@ enum {
> > > > >  SCU_AST2500_HW_STRAP_ACPI_ENABLE |   
> > > > >    \
> > > > >  SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
> > > > >  
> > > > > +/* Witherspoon hardware value: 0xF10AD216 (but use romulus 
> > > > > definition) */
> > > > > +#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
> > > > > +
> > > > >  static void palmetto_bmc_i2c_init(AspeedBoardState *bmc);
> > > > >  static void ast2500_evb_i2c_init(AspeedBoardState *bmc);
> > > > > +static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc);
> > > > >  
> > > > >  static const AspeedBoardConfig aspeed_boards[] = {
> > > > >  [PALMETTO_BMC] = {
> > > > > @@ -110,6 +115,14 @@ static const AspeedBoardConfig aspeed_boards[] = 
> > > > > {
> > > > >  .spi_model = "mx66l1g45g",
> > > > >  .num_cs= 2,
> > > > >  },
> > > > > +[WITHERSPOON_BMC]  = {
> > > > > +.soc_name  = "ast2500-a1",
> > > > > +.hw_strap1 = WITHERSPOON_BMC_HW_STRAP1,
> > > > > +.fmc_model = "mx25l25635e",
> > > > > +.spi_model = "mx66l1g45g",
> > > > > +.num_cs= 2,
> > > > > +.i2c_init  = witherspoon_bmc_i2c_init,
> > > > > +},
> > > > >  };
> > > > >  
> > > > >  #define FIRMWARE_ADDR 0x0
> > > > > @@ -337,11 +350,47 @@ static const TypeInfo romulus_bmc_type = {
> > > > >  .class_init = romulus_bmc_class_init,
> > > > >  };
> > > > >  
> > > > > +static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
> > > > > +{
> > > > > +AspeedSoCState *soc = >soc;
> > > > > +
> > > > > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 4), 
> > > > > "tmp423", 0x4c);
> > > > > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 5), 
> > > > > "tmp423", 0x4c);
> > > > > +
> > > > > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 9), 
> > > > > "tmp105", 0x4a);
> > > > 
> > > > Looks like I need to track down newer versions of the schematics I have.
> > > 
> > > the device on the board is a tmp275 but the tmp105 model is compatible.
> > 
> > It neither device is listed in the version I have :)
> 
> Here is my source :
> 
>   
> https://github.com/openbmc/linux/blob/dev-4.10/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts#L504
> 

Yeah, I ended up jumping on a machine and verifying the device was on
the bus.

Cheers,

Andrew

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH v2 1/6] aspeed: add support for the witherspoon-bmc board

2017-10-10 Thread Andrew Jeffery
On Tue, 2017-10-10 at 15:30 +0200, Cédric Le Goater wrote:
> On 10/09/2017 02:04 AM, Andrew Jeffery wrote:
> > On Wed, 2017-09-20 at 09:01 +0200, Cédric Le Goater wrote:
> > > The Witherspoon boards are OpenPOWER system hosting POWER9 Processors.
> > > Let's add support for their BMC including a couple of I2C devices as
> > > found on real HW.
> > >  
> > > > > > Signed-off-by: Cédric Le Goater <c...@kaod.org>
> > > ---
> > >  hw/arm/aspeed.c | 49 +
> > >  1 file changed, 49 insertions(+)
> > >  
> > > diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> > > index ab895ad490af..81f522f711ae 100644
> > > --- a/hw/arm/aspeed.c
> > > +++ b/hw/arm/aspeed.c
> > > @@ -46,6 +46,7 @@ enum {
> > >  PALMETTO_BMC,
> > >  AST2500_EVB,
> > >  ROMULUS_BMC,
> > > +WITHERSPOON_BMC,
> > >  };
> > >  
> > >  /* Palmetto hardware value: 0x120CE416 */
> > > @@ -83,8 +84,12 @@ enum {
> > >  SCU_AST2500_HW_STRAP_ACPI_ENABLE |  \
> > >  SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
> > >  
> > > +/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
> > > +#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
> > > +
> > >  static void palmetto_bmc_i2c_init(AspeedBoardState *bmc);
> > >  static void ast2500_evb_i2c_init(AspeedBoardState *bmc);
> > > +static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc);
> > >  
> > >  static const AspeedBoardConfig aspeed_boards[] = {
> > >  [PALMETTO_BMC] = {
> > > @@ -110,6 +115,14 @@ static const AspeedBoardConfig aspeed_boards[] = {
> > >  .spi_model = "mx66l1g45g",
> > >  .num_cs= 2,
> > >  },
> > > +[WITHERSPOON_BMC]  = {
> > > +.soc_name  = "ast2500-a1",
> > > +.hw_strap1 = WITHERSPOON_BMC_HW_STRAP1,
> > > +.fmc_model = "mx25l25635e",
> > > +.spi_model = "mx66l1g45g",
> > > +.num_cs= 2,
> > > +.i2c_init  = witherspoon_bmc_i2c_init,
> > > +},
> > >  };
> > >  
> > >  #define FIRMWARE_ADDR 0x0
> > > @@ -337,11 +350,47 @@ static const TypeInfo romulus_bmc_type = {
> > >  .class_init = romulus_bmc_class_init,
> > >  };
> > >  
> > > +static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
> > > +{
> > > +AspeedSoCState *soc = >soc;
> > > +
> > > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 4), "tmp423", 
> > > 0x4c);
> > > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 5), "tmp423", 
> > > 0x4c);
> > > +
> > > +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 9), "tmp105", 
> > > 0x4a);
> > 
> > Looks like I need to track down newer versions of the schematics I have.
> 
> the device on the board is a tmp275 but the tmp105 model is compatible.

It neither device is listed in the version I have :)

Andrew

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH v2 6/6] aspeed: add the pc9552 chips to the witherspoon machine

2017-10-08 Thread Andrew Jeffery
On Wed, 2017-09-20 at 09:01 +0200, Cédric Le Goater wrote:
> The pca9552 LED blinkers on the Witherspoon machine are used for leds
> but also as GPIOs to control fans and GPUs.
> 
> Signed-off-by: Cédric Le Goater <c...@kaod.org>

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

> ---
>  hw/arm/aspeed.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 462f8008cff5..2ae46d71bff7 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -379,6 +379,8 @@ static void witherspoon_bmc_i2c_init(AspeedBoardState 
> *bmc)
>  AspeedSoCState *soc = >soc;
>  uint8_t *eeprom_buf = g_malloc0(8 * 1024);
>  
> +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 3), "pca9552", 
> 0x60);
> +
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 4), "tmp423", 
> 0x4c);
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 5), "tmp423", 
> 0x4c);
>  
> @@ -390,6 +392,8 @@ static void witherspoon_bmc_i2c_init(AspeedBoardState 
> *bmc)
>  
>  smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(>i2c), 11), 0x51,
>    eeprom_buf);
> +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 11), "pca9552",
> + 0x60);
>  }
>  
>  static void witherspoon_bmc_init(MachineState *machine)

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH v2 4/6] aspeed: Add EEPROM I2C devices

2017-10-08 Thread Andrew Jeffery
On Wed, 2017-09-20 at 09:01 +0200, Cédric Le Goater wrote:
> The Aspeed boards have at least one EEPROM to hold the Vital Product
> Data (VPD).
> 
> Signed-off-by: Cédric Le Goater <c...@kaod.org>

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

> ---
> 
> Changes since v1:
> 
>  - fixed palmetto EEPROM size
>  - used smbus_eeprom_init_one()
> 
> hw/arm/aspeed.c | 13 +
>  1 file changed, 13 insertions(+)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 362b683e9021..462f8008cff5 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -17,6 +17,7 @@
>  #include "hw/arm/arm.h"
>  #include "hw/arm/aspeed_soc.h"
>  #include "hw/boards.h"
> +#include "hw/i2c/smbus.h"
>  #include "qemu/log.h"
>  #include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
> @@ -255,11 +256,15 @@ static void palmetto_bmc_i2c_init(AspeedBoardState *bmc)
>  {
>  AspeedSoCState *soc = >soc;
>  DeviceState *dev;
> +uint8_t *eeprom_buf = g_malloc0(32 * 1024);
>  
>  /* The palmetto platform expects a ds3231 RTC but a ds1338 is
>   * enough to provide basic RTC features. Alarms will be missing */
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 0), "ds1338", 
> 0x68);
>  
> +smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(>i2c), 0), 0x50,
> +  eeprom_buf);
> +
>  /* add a TMP423 temperature sensor */
>  dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 2),
> "tmp423", 0x4c);
> @@ -297,6 +302,10 @@ static const TypeInfo palmetto_bmc_type = {
>  static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
>  {
>  AspeedSoCState *soc = >soc;
> +uint8_t *eeprom_buf = g_malloc0(8 * 1024);
> +
> +smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(>i2c), 3), 0x50,
> +  eeprom_buf);
>  
>  /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 7), "tmp105", 
> 0x4d);
> @@ -368,6 +377,7 @@ static const TypeInfo romulus_bmc_type = {
>  static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
>  {
>  AspeedSoCState *soc = >soc;
> +uint8_t *eeprom_buf = g_malloc0(8 * 1024);
>  
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 4), "tmp423", 
> 0x4c);
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 5), "tmp423", 
> 0x4c);
> @@ -377,6 +387,9 @@ static void witherspoon_bmc_i2c_init(AspeedBoardState 
> *bmc)
>  /* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
>   * good enough */
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 11), "ds1338", 
> 0x32);
> +
> +smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(>i2c), 11), 0x51,
> +  eeprom_buf);
>  }
>  
>  static void witherspoon_bmc_init(MachineState *machine)

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH v2 2/6] aspeed: add an I2C RTC device to all machines

2017-10-08 Thread Andrew Jeffery
On Wed, 2017-09-20 at 09:01 +0200, Cédric Le Goater wrote:
> The AST2500 EVB does not have an RTC but we can pretend that one is
> plugged on the I2C bus header.
> 
> The romulus and witherspoon boards expects an Epson RX8900 I2C RTC but
> a ds1338 is good enough for the basic features we need.
> 
> Signed-off-by: Cédric Le Goater <c...@kaod.org>

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

> ---
>  hw/arm/aspeed.c | 19 +++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 81f522f711ae..362b683e9021 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -89,6 +89,7 @@ enum {
>  
>  static void palmetto_bmc_i2c_init(AspeedBoardState *bmc);
>  static void ast2500_evb_i2c_init(AspeedBoardState *bmc);
> +static void romulus_bmc_i2c_init(AspeedBoardState *bmc);
>  static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc);
>  
>  static const AspeedBoardConfig aspeed_boards[] = {
> @@ -114,6 +115,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
>  .fmc_model = "n25q256a",
>  .spi_model = "mx66l1g45g",
>  .num_cs= 2,
> +.i2c_init  = romulus_bmc_i2c_init,
>  },
>  [WITHERSPOON_BMC]  = {
>  .soc_name  = "ast2500-a1",
> @@ -298,6 +300,10 @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
>  
>  /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 7), "tmp105", 
> 0x4d);
> +
> +/* The AST2500 EVB does not have an RTC. Let's pretend that one is
> + * plugged on the I2C bus header */
> +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 11), "ds1338", 
> 0x32);
>  }
>  
>  static void ast2500_evb_init(MachineState *machine)
> @@ -325,6 +331,15 @@ static const TypeInfo ast2500_evb_type = {
>  .class_init = ast2500_evb_class_init,
>  };
>  
> +static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
> +{
> +AspeedSoCState *soc = >soc;
> +
> +/* The romulus board expects Epson RX8900 I2C RTC but a ds1338 is
> + * good enough */
> +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 11), "ds1338", 
> 0x32);
> +}
> +
>  static void romulus_bmc_init(MachineState *machine)
>  {
>  aspeed_board_init(machine, _boards[ROMULUS_BMC]);
> @@ -358,6 +373,10 @@ static void witherspoon_bmc_i2c_init(AspeedBoardState 
> *bmc)
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 5), "tmp423", 
> 0x4c);
>  
>  i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 9), "tmp105", 
> 0x4a);
> +
> +/* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
> + * good enough */
> +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 11), "ds1338", 
> 0x32);
>  }
>  
>  static void witherspoon_bmc_init(MachineState *machine)

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH v2 1/6] aspeed: add support for the witherspoon-bmc board

2017-10-08 Thread Andrew Jeffery
On Wed, 2017-09-20 at 09:01 +0200, Cédric Le Goater wrote:
> The Witherspoon boards are OpenPOWER system hosting POWER9 Processors.
> Let's add support for their BMC including a couple of I2C devices as
> found on real HW.
> 
> Signed-off-by: Cédric Le Goater <c...@kaod.org>
> ---
>  hw/arm/aspeed.c | 49 +
>  1 file changed, 49 insertions(+)
> 
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index ab895ad490af..81f522f711ae 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -46,6 +46,7 @@ enum {
>  PALMETTO_BMC,
>  AST2500_EVB,
>  ROMULUS_BMC,
> +WITHERSPOON_BMC,
>  };
>  
>  /* Palmetto hardware value: 0x120CE416 */
> @@ -83,8 +84,12 @@ enum {
>  SCU_AST2500_HW_STRAP_ACPI_ENABLE |  \
>  SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
>  
> +/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
> +#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
> +
>  static void palmetto_bmc_i2c_init(AspeedBoardState *bmc);
>  static void ast2500_evb_i2c_init(AspeedBoardState *bmc);
> +static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc);
>  
>  static const AspeedBoardConfig aspeed_boards[] = {
>  [PALMETTO_BMC] = {
> @@ -110,6 +115,14 @@ static const AspeedBoardConfig aspeed_boards[] = {
>  .spi_model = "mx66l1g45g",
>  .num_cs= 2,
>  },
> +[WITHERSPOON_BMC]  = {
> +.soc_name  = "ast2500-a1",
> +.hw_strap1 = WITHERSPOON_BMC_HW_STRAP1,
> +.fmc_model = "mx25l25635e",
> +.spi_model = "mx66l1g45g",
> +.num_cs= 2,
> +.i2c_init  = witherspoon_bmc_i2c_init,
> +},
>  };
>  
>  #define FIRMWARE_ADDR 0x0
> @@ -337,11 +350,47 @@ static const TypeInfo romulus_bmc_type = {
>  .class_init = romulus_bmc_class_init,
>  };
>  
> +static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
> +{
> +AspeedSoCState *soc = >soc;
> +
> +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 4), "tmp423", 
> 0x4c);
> +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 5), "tmp423", 
> 0x4c);
> +
> +i2c_create_slave(aspeed_i2c_get_bus(DEVICE(>i2c), 9), "tmp105", 
> 0x4a);

Looks like I need to track down newer versions of the schematics I have.

> +}
> +
> +static void witherspoon_bmc_init(MachineState *machine)
> +{
> +aspeed_board_init(machine, _boards[WITHERSPOON_BMC]);
> +}
> +
> +static void witherspoon_bmc_class_init(ObjectClass *oc, void *data)
> +{
> +MachineClass *mc = MACHINE_CLASS(oc);
> +
> +mc->desc = "OpenPOWER Witherspoon BMC (ARM1176)";
> +mc->init = witherspoon_bmc_init;
> +mc->max_cpus = 1;
> +mc->no_sdcard = 1;
> +mc->no_floppy = 1;
> +mc->no_cdrom = 1;
> +mc->no_parallel = 1;
> +mc->ignore_memory_transaction_failures = true;

Aside from the issue with the above as pointed out by Peter,

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

> +}
> +
> +static const TypeInfo witherspoon_bmc_type = {
> +.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
> +.parent = TYPE_MACHINE,
> +.class_init = witherspoon_bmc_class_init,
> +};
> +
>  static void aspeed_machine_init(void)
>  {
>  type_register_static(_bmc_type);
>  type_register_static(_evb_type);
>  type_register_static(_bmc_type);
> +type_register_static(_bmc_type);
>  }
>  
>  type_init(aspeed_machine_init)

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH v2] watchdog/aspeed: fix variable type to store reload value

2017-10-08 Thread Andrew Jeffery
On Wed, 2017-09-20 at 08:49 +0200, Cédric Le Goater wrote:
> Initially from Anton D. Kachalov" <mo...@yandex-team.ru> but the SoB was
> missing.
> 
> Signed-off-by: Cédric Le Goater <c...@kaod.org>
> [clg: change commit log and subject
>   replace UL suffix by ULL ]
> Signed-off-by: Cédric Le Goater <c...@kaod.org>

Acked-by: Andrew Jeffery <and...@aj.id.au>

> ---
>  hw/watchdog/wdt_aspeed.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> index 22bce364d7b5..95f6ad186d72 100644
> --- a/hw/watchdog/wdt_aspeed.c
> +++ b/hw/watchdog/wdt_aspeed.c
> @@ -100,13 +100,13 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr 
> offset, unsigned size)
>  
>  static void aspeed_wdt_reload(AspeedWDTState *s, bool pclk)
>  {
> -uint32_t reload;
> +uint64_t reload;
>  
>  if (pclk) {
>  reload = muldiv64(s->regs[WDT_RELOAD_VALUE], NANOSECONDS_PER_SECOND,
>    s->pclk_freq);
>  } else {
> -reload = s->regs[WDT_RELOAD_VALUE] * 1000;
> +reload = s->regs[WDT_RELOAD_VALUE] * 1000ULL;
>  }
>  
>  if (aspeed_wdt_is_enabled(s)) {

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH for 2.11 v2 1/2] watchdog: wdt_aspeed: Add support for the reset width register

2017-08-09 Thread Andrew Jeffery


On Wed, Aug 9, 2017, at 18:28, Cédric Le Goater wrote:
> On 08/09/2017 08:28 AM, Andrew Jeffery wrote:
> > The reset width register controls how the pulse on the SoC's WDTRST{1,2}
> > pins behaves. A pulse is emitted if the external reset bit is set in
> > WDT_CTRL. On the AST2500 WDT_RESET_WIDTH can consume magic bit patterns
> > to configure push-pull/open-drain and active-high/active-low
> > behaviours and thus needs some special handling in the write path.
> > 
> > As some of the capabilities depend on the SoC version a silicon-rev
> > property is introduced, which is used to guard version-specific
> > behaviour.
> > 
> > Signed-off-by: Andrew Jeffery <and...@aj.id.au>
> 
> One minor comment below. Nevertheless :
> 
> Reviewed-by: Cédric Le Goater <c...@kaod.org>
> 
> > ---
> >  hw/watchdog/wdt_aspeed.c | 93 
> > +++-
> >  include/hw/watchdog/wdt_aspeed.h |  2 +
> >  2 files changed, 84 insertions(+), 11 deletions(-)
> > 
> > diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> > index 8bbe579b6b66..22bce364d7b5 100644
> > --- a/hw/watchdog/wdt_aspeed.c
> > +++ b/hw/watchdog/wdt_aspeed.c
> > @@ -8,16 +8,19 @@
> >   */
> >  
> >  #include "qemu/osdep.h"
> > +
> > +#include "qapi/error.h"
> >  #include "qemu/log.h"
> > +#include "qemu/timer.h"
> >  #include "sysemu/watchdog.h"
> > +#include "hw/misc/aspeed_scu.h"
> >  #include "hw/sysbus.h"
> > -#include "qemu/timer.h"
> >  #include "hw/watchdog/wdt_aspeed.h"
> >  
> > -#define WDT_STATUS  (0x00 / 4)
> > -#define WDT_RELOAD_VALUE(0x04 / 4)
> > -#define WDT_RESTART (0x08 / 4)
> > -#define WDT_CTRL(0x0C / 4)
> > +#define WDT_STATUS  (0x00 / 4)
> > +#define WDT_RELOAD_VALUE(0x04 / 4)
> > +#define WDT_RESTART (0x08 / 4)
> > +#define WDT_CTRL(0x0C / 4)
> >  #define   WDT_CTRL_RESET_MODE_SOC   (0x00 << 5)
> >  #define   WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
> >  #define   WDT_CTRL_1MHZ_CLK BIT(4)
> > @@ -25,18 +28,41 @@
> >  #define   WDT_CTRL_WDT_INTR BIT(2)
> >  #define   WDT_CTRL_RESET_SYSTEM BIT(1)
> >  #define   WDT_CTRL_ENABLE   BIT(0)
> > +#define WDT_RESET_WIDTH (0x18 / 4)
> > +#define   WDT_RESET_WIDTH_ACTIVE_HIGH   BIT(31)
> > +#define WDT_POLARITY_MASK   (0xFF << 24)
> > +#define WDT_ACTIVE_HIGH_MAGIC   (0xA5 << 24)
> > +#define WDT_ACTIVE_LOW_MAGIC(0x5A << 24)
> > +#define   WDT_RESET_WIDTH_PUSH_PULL BIT(30)
> > +#define WDT_DRIVE_TYPE_MASK (0xFF << 24)
> > +#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
> > +#define WDT_OPEN_DRAIN_MAGIC(0x8A << 24)
> >  
> > -#define WDT_TIMEOUT_STATUS  (0x10 / 4)
> > -#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
> > -#define WDT_RESET_WDITH (0x18 / 4)
> > +#define WDT_TIMEOUT_STATUS  (0x10 / 4)
> > +#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
> >  
> > -#define WDT_RESTART_MAGIC   0x4755
> > +#define WDT_RESTART_MAGIC   0x4755
> >  
> >  static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
> >  {
> >  return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE;
> >  }
> >  
> > +static bool is_ast2500(const AspeedWDTState *s)
> 
> I think we could use this routine in other controllers (scu, sdmc). 
> So may be, in a follow-up patch, we could move it in aspeed_scu.h

Right, I figured we would move it when we came to need it elsewhere.

Thanks for the review.

Cheers,

Andrew

> 
> Thanks,
> 
> C. 
>  
> > +{
> > +switch (s->silicon_rev) {
> > +case AST2500_A0_SILICON_REV:
> > +case AST2500_A1_SILICON_REV:
> > +return true;
> > +case AST2400_A0_SILICON_REV:
> > +case AST2400_A1_SILICON_REV:
> > +default:
> > +break;
> > +}
> > +
> > +return false;
> > +}
> > +
> >  static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
> >  {
> >  AspeedWDTState *s = ASPEED_WDT(opaque);
> > @@ -55,9 +81,10 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr 
> > offset, unsigned size)
> >  return 0;
> >  case WDT

Re: [Qemu-devel] [PATCH for 2.11 v2 2/2] ARM: aspeed_soc: Propagate silicon-rev to watchdog

2017-08-09 Thread Andrew Jeffery
Ugh, disregard this one; I changed the subject and reissued `git
format-patch`, which naturally doesn't overwrite any existing patch in
the output directory and so the old one got sent as well.

Andrew

On Wed, 2017-08-09 at 15:58 +0930, Andrew Jeffery wrote:
> This is required to configure differences in behaviour between the
> AST2400 and AST2500 watchdog IPs.
> 
> Signed-off-by: Andrew Jeffery <and...@aj.id.au>
> ---
>  hw/arm/aspeed_soc.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
> index 3034849c80bf..79804e1ee652 100644
> --- a/hw/arm/aspeed_soc.c
> +++ b/hw/arm/aspeed_soc.c
> @@ -183,6 +183,8 @@ static void aspeed_soc_init(Object *obj)
>  object_initialize(>wdt[i], sizeof(s->wdt[i]),
> TYPE_ASPEED_WDT);
>  object_property_add_child(obj, "wdt[*]", OBJECT(>wdt[i]), 
> NULL);
>  qdev_set_parent_bus(DEVICE(>wdt[i]),
> sysbus_get_default());
> +qdev_prop_set_uint32(DEVICE(>wdt[i]), "silicon-rev",
> +sc->info->silicon_rev);
>  }
>  
>  object_initialize(>ftgmac100, sizeof(s->ftgmac100),
> TYPE_FTGMAC100);

signature.asc
Description: This is a digitally signed message part


[Qemu-devel] [PATCH for 2.11 v2 2/2] aspeed_soc: Propagate silicon-rev to watchdog

2017-08-09 Thread Andrew Jeffery
This is required to configure differences in behaviour between the
AST2400 and AST2500 watchdog IPs.

Signed-off-by: Andrew Jeffery <and...@aj.id.au>
---
 hw/arm/aspeed_soc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 3034849c80bf..79804e1ee652 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -183,6 +183,8 @@ static void aspeed_soc_init(Object *obj)
 object_initialize(>wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT);
 object_property_add_child(obj, "wdt[*]", OBJECT(>wdt[i]), NULL);
 qdev_set_parent_bus(DEVICE(>wdt[i]), sysbus_get_default());
+qdev_prop_set_uint32(DEVICE(>wdt[i]), "silicon-rev",
+sc->info->silicon_rev);
 }
 
 object_initialize(>ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100);
-- 
2.11.0




[Qemu-devel] [PATCH for 2.11 v2 1/2] watchdog: wdt_aspeed: Add support for the reset width register

2017-08-09 Thread Andrew Jeffery
The reset width register controls how the pulse on the SoC's WDTRST{1,2}
pins behaves. A pulse is emitted if the external reset bit is set in
WDT_CTRL. On the AST2500 WDT_RESET_WIDTH can consume magic bit patterns
to configure push-pull/open-drain and active-high/active-low
behaviours and thus needs some special handling in the write path.

As some of the capabilities depend on the SoC version a silicon-rev
property is introduced, which is used to guard version-specific
behaviour.

Signed-off-by: Andrew Jeffery <and...@aj.id.au>
---
 hw/watchdog/wdt_aspeed.c | 93 +++-
 include/hw/watchdog/wdt_aspeed.h |  2 +
 2 files changed, 84 insertions(+), 11 deletions(-)

diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index 8bbe579b6b66..22bce364d7b5 100644
--- a/hw/watchdog/wdt_aspeed.c
+++ b/hw/watchdog/wdt_aspeed.c
@@ -8,16 +8,19 @@
  */
 
 #include "qemu/osdep.h"
+
+#include "qapi/error.h"
 #include "qemu/log.h"
+#include "qemu/timer.h"
 #include "sysemu/watchdog.h"
+#include "hw/misc/aspeed_scu.h"
 #include "hw/sysbus.h"
-#include "qemu/timer.h"
 #include "hw/watchdog/wdt_aspeed.h"
 
-#define WDT_STATUS  (0x00 / 4)
-#define WDT_RELOAD_VALUE(0x04 / 4)
-#define WDT_RESTART (0x08 / 4)
-#define WDT_CTRL(0x0C / 4)
+#define WDT_STATUS  (0x00 / 4)
+#define WDT_RELOAD_VALUE(0x04 / 4)
+#define WDT_RESTART (0x08 / 4)
+#define WDT_CTRL(0x0C / 4)
 #define   WDT_CTRL_RESET_MODE_SOC   (0x00 << 5)
 #define   WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
 #define   WDT_CTRL_1MHZ_CLK BIT(4)
@@ -25,18 +28,41 @@
 #define   WDT_CTRL_WDT_INTR BIT(2)
 #define   WDT_CTRL_RESET_SYSTEM BIT(1)
 #define   WDT_CTRL_ENABLE   BIT(0)
+#define WDT_RESET_WIDTH (0x18 / 4)
+#define   WDT_RESET_WIDTH_ACTIVE_HIGH   BIT(31)
+#define WDT_POLARITY_MASK   (0xFF << 24)
+#define WDT_ACTIVE_HIGH_MAGIC   (0xA5 << 24)
+#define WDT_ACTIVE_LOW_MAGIC(0x5A << 24)
+#define   WDT_RESET_WIDTH_PUSH_PULL BIT(30)
+#define WDT_DRIVE_TYPE_MASK (0xFF << 24)
+#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
+#define WDT_OPEN_DRAIN_MAGIC(0x8A << 24)
 
-#define WDT_TIMEOUT_STATUS  (0x10 / 4)
-#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
-#define WDT_RESET_WDITH (0x18 / 4)
+#define WDT_TIMEOUT_STATUS  (0x10 / 4)
+#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
 
-#define WDT_RESTART_MAGIC   0x4755
+#define WDT_RESTART_MAGIC   0x4755
 
 static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
 {
 return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE;
 }
 
+static bool is_ast2500(const AspeedWDTState *s)
+{
+switch (s->silicon_rev) {
+case AST2500_A0_SILICON_REV:
+case AST2500_A1_SILICON_REV:
+return true;
+case AST2400_A0_SILICON_REV:
+case AST2400_A1_SILICON_REV:
+default:
+break;
+}
+
+return false;
+}
+
 static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
 {
 AspeedWDTState *s = ASPEED_WDT(opaque);
@@ -55,9 +81,10 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, 
unsigned size)
 return 0;
 case WDT_CTRL:
 return s->regs[WDT_CTRL];
+case WDT_RESET_WIDTH:
+return s->regs[WDT_RESET_WIDTH];
 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);
@@ -119,9 +146,27 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, 
uint64_t data,
 timer_del(s->timer);
 }
 break;
+case WDT_RESET_WIDTH:
+{
+uint32_t property = data & WDT_POLARITY_MASK;
+
+if (property && is_ast2500(s)) {
+if (property == WDT_ACTIVE_HIGH_MAGIC) {
+s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_ACTIVE_HIGH;
+} else if (property == WDT_ACTIVE_LOW_MAGIC) {
+s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_ACTIVE_HIGH;
+} else if (property == WDT_PUSH_PULL_MAGIC) {
+s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_PUSH_PULL;
+} else if (property == WDT_OPEN_DRAIN_MAGIC) {
+s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_PUSH_PULL;
+}
+}
+s->regs[WDT_RESET_WIDTH] &= ~s->ext_pulse_width_mask;
+s->regs[WDT_RESET_WIDTH] |= data & s->ext_pulse_width_mask;
+break;
+}
 case WDT_TIMEOUT_STATUS:
 case WDT_TIMEOUT_CLEAR:
-case WDT_RE

[Qemu-devel] [PATCH for 2.11 v2 2/2] ARM: aspeed_soc: Propagate silicon-rev to watchdog

2017-08-09 Thread Andrew Jeffery
This is required to configure differences in behaviour between the
AST2400 and AST2500 watchdog IPs.

Signed-off-by: Andrew Jeffery <and...@aj.id.au>
---
 hw/arm/aspeed_soc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 3034849c80bf..79804e1ee652 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -183,6 +183,8 @@ static void aspeed_soc_init(Object *obj)
 object_initialize(>wdt[i], sizeof(s->wdt[i]), TYPE_ASPEED_WDT);
 object_property_add_child(obj, "wdt[*]", OBJECT(>wdt[i]), NULL);
 qdev_set_parent_bus(DEVICE(>wdt[i]), sysbus_get_default());
+qdev_prop_set_uint32(DEVICE(>wdt[i]), "silicon-rev",
+sc->info->silicon_rev);
 }
 
 object_initialize(>ftgmac100, sizeof(s->ftgmac100), TYPE_FTGMAC100);
-- 
2.11.0




[Qemu-devel] [PATCH for 2.11 v2 0/2] wdt_aspeed: Support reset width patterns

2017-08-09 Thread Andrew Jeffery
Hello,

These two patches add support for the reset width configuration register in the
Aspeed watchdog. Initially this was just one patch[1], but I've reworked it as
two to explicitly support the varying capabilities between Aspeed SoC versions.

Andrew

[1] http://patchwork.ozlabs.org/patch/796039/

Andrew Jeffery (2):
  watchdog: wdt_aspeed: Add support for the reset width register
  aspeed_soc: Propagate silicon-rev to watchdog

 hw/arm/aspeed_soc.c  |  2 +
 hw/watchdog/wdt_aspeed.c | 93 +++-
 include/hw/watchdog/wdt_aspeed.h |  2 +
 3 files changed, 86 insertions(+), 11 deletions(-)

-- 
2.11.0




Re: [Qemu-devel] [PATCH] watchdog: wdt_aspeed: Add support for the reset width register

2017-08-02 Thread Andrew Jeffery
On Tue, 2017-08-01 at 09:21 +0200, Cédric Le Goater wrote:
> On 08/01/2017 03:04 AM, Andrew Jeffery wrote:
> > The reset width register controls how the pulse on the SoC's WDTRST{1,2}
> > pins behaves. A pulse is emitted if the external reset bit is set in
> > WDT_CTRL. WDT_RESET_WIDTH requires magic bit patterns to configure both
> > push-pull/open-drain and active-high/active-low behaviours and thus
> > needs some special handling in the write path.
> > 
> > > > Signed-off-by: Andrew Jeffery <and...@aj.id.au>
> > ---
> > I understand that we're in stabilisation mode, but I thought I'd send this 
> > out
> > to provoke any feedback. Happy to resend after the 2.10 release if required.
> > 
> >  hw/watchdog/wdt_aspeed.c | 47 
> > +--
> >  1 file changed, 37 insertions(+), 10 deletions(-)
> > 
> > diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> > index 8bbe579b6b66..4ef1412e99fc 100644
> > --- a/hw/watchdog/wdt_aspeed.c
> > +++ b/hw/watchdog/wdt_aspeed.c
> > @@ -14,10 +14,10 @@
> >  #include "qemu/timer.h"
> >  #include "hw/watchdog/wdt_aspeed.h"
> >  
> > -#define WDT_STATUS  (0x00 / 4)
> > -#define WDT_RELOAD_VALUE(0x04 / 4)
> > -#define WDT_RESTART (0x08 / 4)
> > -#define WDT_CTRL(0x0C / 4)
> > +#define WDT_STATUS  (0x00 / 4)
> > +#define WDT_RELOAD_VALUE(0x04 / 4)
> > +#define WDT_RESTART (0x08 / 4)
> > +#define WDT_CTRL(0x0C / 4)
> >  #define   WDT_CTRL_RESET_MODE_SOC   (0x00 << 5)
> >  #define   WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
> >  #define   WDT_CTRL_1MHZ_CLK BIT(4)
> > @@ -25,12 +25,21 @@
> >  #define   WDT_CTRL_WDT_INTR BIT(2)
> >  #define   WDT_CTRL_RESET_SYSTEM BIT(1)
> >  #define   WDT_CTRL_ENABLE   BIT(0)
> > +#define WDT_RESET_WIDTH (0x18 / 4)
> > +#define   WDT_RESET_WIDTH_ACTIVE_HIGH   BIT(31)
> > +#define WDT_POLARITY_MASK   (0xFF << 24)
> > +#define WDT_ACTIVE_HIGH_MAGIC   (0xA5 << 24)
> > +#define WDT_ACTIVE_LOW_MAGIC(0x5A << 24)
> > +#define   WDT_RESET_WIDTH_PUSH_PULL BIT(30)
> > +#define WDT_DRIVE_TYPE_MASK (0xFF << 24)
> > +#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
> > +#define WDT_OPEN_DRAIN_MAGIC(0x8A << 24)
> > +#define   WDT_RESET_WIDTH_DURATION  0xFFF;
> 
> I would call this define WDT_RESET_WIDTH_DEFAULT (0xFF) and 
> use it also in the aspeed_wdt_reset()

This WDT_RESET_WIDTH_DURATION is intended as a mask. It's probably
poorly named. As I found when replying to Phil, the width actually
varies between the AST2400 and AST2500, and on the AST2500 is actually
20 bits wide, not 12 (and is 8 bits on the AST2400). I'll need to
respin to fix that. On the otherhand, 0xFF is the default value for the
field on both the AST2400 and AST2500.

> 
> I have checked the specs and the bits definitions are correct.
> What else could we model ? Would the pulse be interesting ? 

Hrm, we could. In Witherspoon (and Romulus?) systems the pulse is being
used to drive the FAULT pin on the MAX31785 fan controller. I've got
some very hacky patches lying around adding PMBus support and a basic
MAX31785 model to QEMU - with a bit of extra work we could hook up the
external watchdog signal to the FAULT pin and drive our virtual fans to
100% PWM duty as per the hardware.

It's not high on my todo list though :)

Andrew

> 
> C.
> 
> 
> >  
> > -#define WDT_TIMEOUT_STATUS  (0x10 / 4)
> > -#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
> > -#define WDT_RESET_WDITH (0x18 / 4)
> > +#define WDT_TIMEOUT_STATUS  (0x10 / 4)
> > +#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
> >  
> > -#define WDT_RESTART_MAGIC   0x4755
> > +#define WDT_RESTART_MAGIC   0x4755
> >  
> >  static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
> >  {
> > @@ -55,9 +64,10 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr 
> > offset, unsigned size)
> >  return 0;
> >  case WDT_CTRL:
> >  return s->regs[WDT_CTRL];
> > +case WDT_RESET_WIDTH:
> > +return s->regs[WDT_RESET_WIDTH];
> >  case WDT_TIMEOUT_STATUS:
> >  case WDT_TIMEOUT_CLEAR:
> > -case WDT_RESET_WDITH:
> >  qemu_log_mask(LOG_UNIMP,
> >    "%s: uninmplemented read at offset 0

Re: [Qemu-devel] [Qemu-arm] [PATCH] watchdog: wdt_aspeed: Add support for the reset width register

2017-07-31 Thread Andrew Jeffery
Hi Phil,

On Tue, 2017-08-01 at 00:23 -0300, Philippe Mathieu-Daudé wrote:
> Hi Andrew,
> 
> On 07/31/2017 10:04 PM, Andrew Jeffery wrote:
> > The reset width register controls how the pulse on the SoC's WDTRST{1,2}
> > pins behaves. A pulse is emitted if the external reset bit is set in
> > WDT_CTRL. WDT_RESET_WIDTH requires magic bit patterns to configure both
> > push-pull/open-drain and active-high/active-low behaviours and thus
> > needs some special handling in the write path.
> 
> I wanted to verify the datashit but it seems to unavailable, looking there:
> https://www.verical.com/datasheet/aspeed-technology-inc-interface-misc-ast2050a3-gp-4078885.pdf
> 
> Can you point out which cpu model you are modeling and where to get this 
> watchdog datashit please? You might also add this to the header, for the 
> next one looking at this file :)

The watchdog model is common to at least the Aspeed AST2400- and
AST2500- SoC families, which I have datasheets for. However, they are
not available to the public and therefore (unfortunately) I can't point
you to them. You may be able to access them if you have appropriate
arrangements with Aspeed.

Regarding the features exposed by the patch, configuration of the
electrical properties of the  external reset signal is only provided in
the AST2500's watchdog IP, but the bits used in the reset width
register are marked as reserved on the AST2400. Therefore I thought it
was reasonable not to guard them behind some kind of revision test.

> 
> > 
> > > > Signed-off-by: Andrew Jeffery <and...@aj.id.au>
> > ---
> > I understand that we're in stabilisation mode, but I thought I'd send this 
> > out
> > to provoke any feedback. Happy to resend after the 2.10 release if required.
> 
> you can subject it "PATCH for 2.11" so ppl testing/closing 2.10 can keep 
> focused but still queue your mail for when 2.10 release is out.

Thanks for the tip.

> 
> > 
> >   hw/watchdog/wdt_aspeed.c | 47 
> > +--
> >   1 file changed, 37 insertions(+), 10 deletions(-)
> > 
> > diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> > index 8bbe579b6b66..4ef1412e99fc 100644
> > --- a/hw/watchdog/wdt_aspeed.c
> > +++ b/hw/watchdog/wdt_aspeed.c
> > @@ -14,10 +14,10 @@
> >   #include "qemu/timer.h"
> >   #include "hw/watchdog/wdt_aspeed.h"
> >   
> > -#define WDT_STATUS  (0x00 / 4)
> > -#define WDT_RELOAD_VALUE(0x04 / 4)
> > -#define WDT_RESTART (0x08 / 4)
> > -#define WDT_CTRL(0x0C / 4)
> > +#define WDT_STATUS  (0x00 / 4)
> > +#define WDT_RELOAD_VALUE(0x04 / 4)
> > +#define WDT_RESTART (0x08 / 4)
> > +#define WDT_CTRL(0x0C / 4)
> >   #define   WDT_CTRL_RESET_MODE_SOC   (0x00 << 5)
> >   #define   WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
> >   #define   WDT_CTRL_1MHZ_CLK BIT(4)
> > @@ -25,12 +25,21 @@
> >   #define   WDT_CTRL_WDT_INTR BIT(2)
> >   #define   WDT_CTRL_RESET_SYSTEM BIT(1)
> >   #define   WDT_CTRL_ENABLE   BIT(0)
> > +#define WDT_RESET_WIDTH (0x18 / 4)
> > +#define   WDT_RESET_WIDTH_ACTIVE_HIGH   BIT(31)
> > +#define WDT_POLARITY_MASK   (0xFF << 24)
> > +#define WDT_ACTIVE_HIGH_MAGIC   (0xA5 << 24)
> > +#define WDT_ACTIVE_LOW_MAGIC(0x5A << 24)
> > +#define   WDT_RESET_WIDTH_PUSH_PULL BIT(30)
> > +#define WDT_DRIVE_TYPE_MASK (0xFF << 24)
> > +#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
> > +#define WDT_OPEN_DRAIN_MAGIC(0x8A << 24)
> > +#define   WDT_RESET_WIDTH_DURATION  0xFFF;
> 
> Which model? the AST2050 seems to be 0xff.

Ah, good catch, this is also the case in the AST2400. The AST2500
extends this field. Host code for the AST2400 and AST2050 *shouldn't*
set any greater values; is it worth enforcing?

> 
> >   
> > -#define WDT_TIMEOUT_STATUS  (0x10 / 4)
> > -#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
> > -#define WDT_RESET_WDITH (0x18 / 4)
> > +#define WDT_TIMEOUT_STATUS  (0x10 / 4)
> > +#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
> >   
> > -#define WDT_RESTART_MAGIC   0x4755
> > +#define WDT_RESTART_MAGIC   0x4755
> >   
> >   static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
> >   {
> > @@ -55,9 +64,10 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr 
> > offset, unsigned s

[Qemu-devel] [PATCH] watchdog: wdt_aspeed: Add support for the reset width register

2017-07-31 Thread Andrew Jeffery
The reset width register controls how the pulse on the SoC's WDTRST{1,2}
pins behaves. A pulse is emitted if the external reset bit is set in
WDT_CTRL. WDT_RESET_WIDTH requires magic bit patterns to configure both
push-pull/open-drain and active-high/active-low behaviours and thus
needs some special handling in the write path.

Signed-off-by: Andrew Jeffery <and...@aj.id.au>
---
I understand that we're in stabilisation mode, but I thought I'd send this out
to provoke any feedback. Happy to resend after the 2.10 release if required.

 hw/watchdog/wdt_aspeed.c | 47 +--
 1 file changed, 37 insertions(+), 10 deletions(-)

diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index 8bbe579b6b66..4ef1412e99fc 100644
--- a/hw/watchdog/wdt_aspeed.c
+++ b/hw/watchdog/wdt_aspeed.c
@@ -14,10 +14,10 @@
 #include "qemu/timer.h"
 #include "hw/watchdog/wdt_aspeed.h"
 
-#define WDT_STATUS  (0x00 / 4)
-#define WDT_RELOAD_VALUE(0x04 / 4)
-#define WDT_RESTART (0x08 / 4)
-#define WDT_CTRL(0x0C / 4)
+#define WDT_STATUS  (0x00 / 4)
+#define WDT_RELOAD_VALUE(0x04 / 4)
+#define WDT_RESTART (0x08 / 4)
+#define WDT_CTRL(0x0C / 4)
 #define   WDT_CTRL_RESET_MODE_SOC   (0x00 << 5)
 #define   WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
 #define   WDT_CTRL_1MHZ_CLK BIT(4)
@@ -25,12 +25,21 @@
 #define   WDT_CTRL_WDT_INTR BIT(2)
 #define   WDT_CTRL_RESET_SYSTEM BIT(1)
 #define   WDT_CTRL_ENABLE   BIT(0)
+#define WDT_RESET_WIDTH (0x18 / 4)
+#define   WDT_RESET_WIDTH_ACTIVE_HIGH   BIT(31)
+#define WDT_POLARITY_MASK   (0xFF << 24)
+#define WDT_ACTIVE_HIGH_MAGIC   (0xA5 << 24)
+#define WDT_ACTIVE_LOW_MAGIC(0x5A << 24)
+#define   WDT_RESET_WIDTH_PUSH_PULL BIT(30)
+#define WDT_DRIVE_TYPE_MASK (0xFF << 24)
+#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
+#define WDT_OPEN_DRAIN_MAGIC(0x8A << 24)
+#define   WDT_RESET_WIDTH_DURATION  0xFFF;
 
-#define WDT_TIMEOUT_STATUS  (0x10 / 4)
-#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
-#define WDT_RESET_WDITH (0x18 / 4)
+#define WDT_TIMEOUT_STATUS  (0x10 / 4)
+#define WDT_TIMEOUT_CLEAR   (0x14 / 4)
 
-#define WDT_RESTART_MAGIC   0x4755
+#define WDT_RESTART_MAGIC   0x4755
 
 static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
 {
@@ -55,9 +64,10 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, 
unsigned size)
 return 0;
 case WDT_CTRL:
 return s->regs[WDT_CTRL];
+case WDT_RESET_WIDTH:
+return s->regs[WDT_RESET_WIDTH];
 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);
@@ -119,9 +129,25 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, 
uint64_t data,
 timer_del(s->timer);
 }
 break;
+case WDT_RESET_WIDTH:
+{
+uint32_t property = data & WDT_POLARITY_MASK;
+
+if (property == WDT_ACTIVE_HIGH_MAGIC) {
+s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_ACTIVE_HIGH;
+} else if (property == WDT_ACTIVE_LOW_MAGIC) {
+s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_ACTIVE_HIGH;
+} else if (property == WDT_PUSH_PULL_MAGIC) {
+s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_PUSH_PULL;
+} else if (property == WDT_OPEN_DRAIN_MAGIC) {
+s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_PUSH_PULL;
+}
+s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_DURATION;
+s->regs[WDT_RESET_WIDTH] |= data & WDT_RESET_WIDTH_DURATION;
+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);
@@ -167,6 +193,7 @@ static void aspeed_wdt_reset(DeviceState *dev)
 s->regs[WDT_RELOAD_VALUE] = 0x03EF1480;
 s->regs[WDT_RESTART] = 0;
 s->regs[WDT_CTRL] = 0;
+s->regs[WDT_RESET_WIDTH] = 0XFF;
 
 timer_del(s->timer);
 }
-- 
2.11.0




Re: [Qemu-devel] [RFC PATCH 1/1] memory: Support unaligned accesses on aligned-only models

2017-07-14 Thread Andrew Jeffery
Hi Paolo,

Thanks for taking a look!

On Thu, 2017-07-13 at 14:05 +0200, Paolo Bonzini wrote:
> On 30/06/2017 05:00, Andrew Jeffery wrote:
> > This RFC patch stems from a discussion on a patch for an ADC model[1] where 
> > it
> > was pointed out that I should be able to use the .impl member of
> > MemoryRegionOps to constrain how my read() and write() callbacks where 
> > invoked.
> > 
> > I tried Phil's suggested approach and found I got reads of size 4, but with 
> > an
> > address that was not 4-byte aligned.
> > 
> > Looking at the source for access_with_adjusted_size() lead to the comment
> > 
> >  /* FIXME: support unaligned access? */
> > 
> > which at least suggests that the implementation isn't complete.
> > 
> > So, this patch is a quick and incomplete attempt at resolving the issue to 
> > see
> > whether I'm on the right track or way off in the weeds.
> > 
> > I've lightly tested it with the ADC model mentioned above, and it appears 
> > to do
> > the right thing (I changed the values generated by the ADC to distinguish
> > between the lower and upper 16 bits).
> 
> I think the idea is okay.
> 
> > +access_addr[0] = align_down(addr, access_size);
> > +access_addr[1] = align_up(addr + size, access_size);
> > +
> > +for (cur = access_addr[0]; cur < access_addr[1]; cur += 
> > access_size) {
> > +uint64_t mask_bounds[2];
> > +mask_bounds[0] = MAX(addr, cur) - cur;
> > +mask_bounds[1] =
> > +MIN(addr + size, align_up(cur + 1, access_size)) - cur;
> > +
> > +access_mask = (-1ULL << mask_bounds[0] * 8) &
> > +(-1ULL >> (64 - mask_bounds[1] * 8));
> 
> Please use MAKE_64BIT_MASK.

Okay.

> 
> > +r |= access(mr, cur, _value, access_size,
> > +  (MAX(addr, cur) - addr), access_mask, attrs);
> > +
> > +/* XXX: Can't do this hack for writes */
> > +access_value >>= mask_bounds[0] * 8;
> > +}
> 
> Can you subtract access_addr[0] from mask_bounds[0] and mask_bounds[1]
> (instead of cur) to remove the need for this right shift?

I haven't looked at the patch since I sent it. Given you think the idea
 of the patch is okay I'll get back to working on it and think about
this.

Cheers,

Andrew

> 
> Thanks,
> 
> Paolo

signature.asc
Description: This is a digitally signed message part


[Qemu-devel] [RFC PATCH 1/1] memory: Support unaligned accesses on aligned-only models

2017-06-29 Thread Andrew Jeffery
Signed-off-by: Andrew Jeffery <and...@aj.id.au>
---
Hello,

This RFC patch stems from a discussion on a patch for an ADC model[1] where it
was pointed out that I should be able to use the .impl member of
MemoryRegionOps to constrain how my read() and write() callbacks where invoked.

I tried Phil's suggested approach and found I got reads of size 4, but with an
address that was not 4-byte aligned.

Looking at the source for access_with_adjusted_size() lead to the comment

 /* FIXME: support unaligned access? */

which at least suggests that the implementation isn't complete.

So, this patch is a quick and incomplete attempt at resolving the issue to see
whether I'm on the right track or way off in the weeds.

I've lightly tested it with the ADC model mentioned above, and it appears to do
the right thing (I changed the values generated by the ADC to distinguish
between the lower and upper 16 bits).

Things the patch is not:

1. Capable of handling unaligned writes
2. Tested on big-endian models

If the general idea of the patch is reasonable I'll look to resolve the above
to points.

Cheers,

Andrew

[1] http://lists.nongnu.org/archive/html/qemu-arm/2017-05/msg00400.html
 memory.c | 144 +++
 1 file changed, 137 insertions(+), 7 deletions(-)

diff --git a/memory.c b/memory.c
index 0ddc4cc28deb..b9fae8d382bc 100644
--- a/memory.c
+++ b/memory.c
@@ -432,6 +432,7 @@ static MemTxResult  
memory_region_read_accessor(MemoryRegion *mr,
 {
 uint64_t tmp;
 
+
 tmp = mr->ops->read(mr->opaque, addr, size);
 if (mr->subpage) {
 trace_memory_region_subpage_read(get_cpu_index(), mr, addr, tmp, size);
@@ -552,7 +553,7 @@ static MemTxResult 
memory_region_write_with_attrs_accessor(MemoryRegion *mr,
 return mr->ops->write_with_attrs(mr->opaque, addr, tmp, size, attrs);
 }
 
-static MemTxResult access_with_adjusted_size(hwaddr addr,
+static MemTxResult access_with_adjusted_size_aligned(hwaddr addr,
   uint64_t *value,
   unsigned size,
   unsigned access_size_min,
@@ -567,10 +568,11 @@ static MemTxResult access_with_adjusted_size(hwaddr addr,
   MemoryRegion *mr,
   MemTxAttrs attrs)
 {
+
+MemTxResult r = MEMTX_OK;
 uint64_t access_mask;
 unsigned access_size;
 unsigned i;
-MemTxResult r = MEMTX_OK;
 
 if (!access_size_min) {
 access_size_min = 1;
@@ -579,7 +581,6 @@ static MemTxResult access_with_adjusted_size(hwaddr addr,
 access_size_max = 4;
 }
 
-/* FIXME: support unaligned access? */
 access_size = MAX(MIN(size, access_size_max), access_size_min);
 access_mask = -1ULL >> (64 - access_size * 8);
 if (memory_region_big_endian(mr)) {
@@ -596,6 +597,133 @@ static MemTxResult access_with_adjusted_size(hwaddr addr,
 return r;
 }
 
+/* Assume power-of-two size */
+#define align_down(addr, size) ((addr) & ~((size) - 1))
+#define align_up(addr, size) \
+({ typeof(size) __size = size; align_down((addr) + (__size) - 1, 
(__size)); })
+
+static MemTxResult access_with_adjusted_size_unaligned(hwaddr addr,
+  uint64_t *value,
+  unsigned size,
+  unsigned access_size_min,
+  unsigned access_size_max,
+  bool unaligned,
+  MemTxResult (*access)(MemoryRegion *mr,
+hwaddr addr,
+uint64_t *value,
+unsigned size,
+unsigned shift,
+uint64_t mask,
+MemTxAttrs attrs),
+  MemoryRegion *mr,
+  MemTxAttrs attrs)
+{
+uint64_t access_value = 0;
+MemTxResult r = MEMTX_OK;
+hwaddr access_addr[2];
+uint64_t access_mask;
+unsigned access_size;
+
+if (unlikely(!access_size_min)) {
+access_size_min = 1;
+}
+if (unlikely(!access_size_max)) {
+access_size_max = 4;
+}
+
+access_size = MAX(MIN(size, access_size_max), access_size_min);
+access_addr[0] = align_down(addr, access_size);
+access_addr[1] = align_up(addr + size, access_size);
+
+if (memory_region_big_endian(mr)) {
+hwaddr cur;
+
+/* XXX: Big-endian path is untested...  */
+
+for (cur = access_addr[0]; cur < access_addr[1]; cur += access_size) {
+uint64_t mask_bounds[2];
+
+ 

Re: [Qemu-devel] [PATCH] timer/aspeed: fix timer enablement when a reload is not set

2017-06-12 Thread Andrew Jeffery
On Fri, 2017-06-09 at 07:40 +0200, Cédric Le Goater wrote:
> On 06/09/2017 04:26 AM, Andrew Jeffery wrote:
> > On Tue, 2017-06-06 at 10:55 +0200, Cédric Le Goater wrote:
> > > When a timer is enabled before a reload value is set, the controller
> > > waits for a reload value to be set before starting decrementing. This
> > > fix tries to cover that case by changing the timer expiry only when
> > > a reload value is valid.
> > > 
> > > > Signed-off-by: Cédric Le Goater <c...@kaod.org>
> > > 
> > > ---
> > >  hw/timer/aspeed_timer.c | 37 +
> > >  1 file changed, 29 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
> > > index 9b70ee09b07f..50acbf530a3a 100644
> > > --- a/hw/timer/aspeed_timer.c
> > > +++ b/hw/timer/aspeed_timer.c
> > > @@ -130,15 +130,26 @@ static uint64_t calculate_next(struct AspeedTimer 
> > > *t)
> > >  next = seq[1];
> > >  } else if (now < seq[2]) {
> > >  next = seq[2];
> > > -} else {
> > > +} else if (t->reload) {
> > >  reload_ns = muldiv64(t->reload, NANOSECONDS_PER_SECOND, 
> > > rate);
> > >  t->start = now - ((now - t->start) % reload_ns);
> > > +} else {
> > > +/* no reload value, return 0 */
> > > +break;
> > >  }
> > >  }
> > >  
> > >  return next;
> > >  }
> > >  
> > > +static void aspeed_timer_mod(AspeedTimer *t)
> > > +{
> > > +uint64_t next = calculate_next(t);
> > > +if (next) {
> > > +timer_mod(>timer, next);
> > > +}
> > > +}
> > > +
> > >  static void aspeed_timer_expire(void *opaque)
> > >  {
> > >  AspeedTimer *t = opaque;
> > > @@ -164,7 +175,7 @@ static void aspeed_timer_expire(void *opaque)
> > >  qemu_set_irq(t->irq, t->level);
> > >  }
> > >  
> > > -timer_mod(>timer, calculate_next(t));
> > > +aspeed_timer_mod(t);
> > >  }
> > >  
> > >  static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
> > > @@ -227,10 +238,23 @@ static void 
> > > aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
> > > uint32_t value)
> > >  {
> > >  AspeedTimer *t;
> > > +uint32_t old_reload;
> > >  
> > >  trace_aspeed_timer_set_value(timer, reg, value);
> > >  t = >timers[timer];
> > >  switch (reg) {
> > > +case TIMER_REG_RELOAD:
> > > +old_reload = t->reload;
> > > +t->reload = value;
> > > +
> > > +/* If the reload value was not previously set, or zero, and
> > > + * the current value is valid, try to start the timer if it is
> > > + * enabled.
> > > + */
> > > +if (old_reload || !t->reload) {
> > > +break;
> > > +}
> > 
> > Maybe I need more caffeine, but I initially struggled to reconcile the
> > condition with the comment, as the condition checks the inverse in
> > order to break while the comment discusses the non-breaking case. 
> 
> I agree. The reload "value" is used in a hidden way to the activate the 
> timer.
> 
> > However, after trying for several minutes, I'm not sure there's an easy
> > way to improve it.
> 
> I tried a few things. May be, we could move the following code in 
> its own routine and call it twice ? 

I don't think it's necessary. The comment serves as enough warning - it
should at least make people think before modifying the code.

Cheers,

Andrew

>  
> > > +
> > >  case TIMER_REG_STATUS:
> > >  if (timer_enabled(t)) {
> > >  uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> > > @@ -238,17 +262,14 @@ static void 
> > > aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
> > >  uint32_t rate = calculate_rate(t);
> > >  
> > >  t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
> > > -timer_mod(>timer, calculate_next(t));
> > > +        aspeed_timer_mod(t);
> > >  }
> > >  break;
> > > -case TIMER_REG_RELOAD:
> > > -t->reload = value;
> > > -break;
> > >  case TIMER_REG_MATCH_FIRST:
> > >  case TIMER_REG_MATCH_SECOND:
> > >  t->match[reg - 2] = value;
> > >  if (timer_enabled(t)) {
> > > -timer_mod(>timer, calculate_next(t));
> > > +aspeed_timer_mod(t);
> > >  }
> > >  break;
> > >  default:
> > > @@ -268,7 +289,7 @@ static void aspeed_timer_ctrl_enable(AspeedTimer *t, 
> > > bool enable)
> > >  trace_aspeed_timer_ctrl_enable(t->id, enable);
> > >  if (enable) {
> > >  t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> > > -timer_mod(>timer, calculate_next(t));
> > > +aspeed_timer_mod(t);
> > >  } else {
> > >  timer_del(>timer);
> > >  }
> > 
> > Reviewed-by: Andrew Jeffery <and...@aj.id.au>
> 
> Thanks,
> 
> C.

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [PATCH] timer/aspeed: fix timer enablement when a reload is not set

2017-06-08 Thread Andrew Jeffery
On Tue, 2017-06-06 at 10:55 +0200, Cédric Le Goater wrote:
> When a timer is enabled before a reload value is set, the controller
> waits for a reload value to be set before starting decrementing. This
> fix tries to cover that case by changing the timer expiry only when
> a reload value is valid.
> 
> > Signed-off-by: Cédric Le Goater <c...@kaod.org>
> ---
>  hw/timer/aspeed_timer.c | 37 +
>  1 file changed, 29 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
> index 9b70ee09b07f..50acbf530a3a 100644
> --- a/hw/timer/aspeed_timer.c
> +++ b/hw/timer/aspeed_timer.c
> @@ -130,15 +130,26 @@ static uint64_t calculate_next(struct AspeedTimer *t)
>  next = seq[1];
>  } else if (now < seq[2]) {
>  next = seq[2];
> -} else {
> +} else if (t->reload) {
>  reload_ns = muldiv64(t->reload, NANOSECONDS_PER_SECOND, rate);
>  t->start = now - ((now - t->start) % reload_ns);
> +} else {
> +/* no reload value, return 0 */
> +break;
>  }
>  }
>  
>  return next;
>  }
>  
> +static void aspeed_timer_mod(AspeedTimer *t)
> +{
> +uint64_t next = calculate_next(t);
> +if (next) {
> +timer_mod(>timer, next);
> +}
> +}
> +
>  static void aspeed_timer_expire(void *opaque)
>  {
>  AspeedTimer *t = opaque;
> @@ -164,7 +175,7 @@ static void aspeed_timer_expire(void *opaque)
>  qemu_set_irq(t->irq, t->level);
>  }
>  
> -timer_mod(>timer, calculate_next(t));
> +aspeed_timer_mod(t);
>  }
>  
>  static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
> @@ -227,10 +238,23 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState 
> *s, int timer, int reg,
> uint32_t value)
>  {
>  AspeedTimer *t;
> +uint32_t old_reload;
>  
>  trace_aspeed_timer_set_value(timer, reg, value);
>  t = >timers[timer];
>  switch (reg) {
> +case TIMER_REG_RELOAD:
> +old_reload = t->reload;
> +t->reload = value;
> +
> +/* If the reload value was not previously set, or zero, and
> + * the current value is valid, try to start the timer if it is
> + * enabled.
> + */
> +if (old_reload || !t->reload) {
> +break;
> +}

Maybe I need more caffeine, but I initially struggled to reconcile the
condition with the comment, as the condition checks the inverse in
order to break while the comment discusses the non-breaking case. 

However, after trying for several minutes, I'm not sure there's an easy
way to improve it.

> +
>  case TIMER_REG_STATUS:
>  if (timer_enabled(t)) {
>  uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> @@ -238,17 +262,14 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState 
> *s, int timer, int reg,
>  uint32_t rate = calculate_rate(t);
>  
>  t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
> -timer_mod(>timer, calculate_next(t));
> +aspeed_timer_mod(t);
>  }
>  break;
> -case TIMER_REG_RELOAD:
> -t->reload = value;
> -break;
>  case TIMER_REG_MATCH_FIRST:
>  case TIMER_REG_MATCH_SECOND:
>  t->match[reg - 2] = value;
>  if (timer_enabled(t)) {
> -timer_mod(>timer, calculate_next(t));
> +aspeed_timer_mod(t);
>  }
>  break;
>  default:
> @@ -268,7 +289,7 @@ static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool 
> enable)
>  trace_aspeed_timer_ctrl_enable(t->id, enable);
>  if (enable) {
>  t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> -timer_mod(>timer, calculate_next(t));
> +aspeed_timer_mod(t);
>  } else {
>  timer_del(>timer);
>  }

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

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [Qemu-arm] [PATCH 1/2] hw/adc: Add basic Aspeed ADC model

2017-05-23 Thread Andrew Jeffery
On Wed, 2017-05-24 at 02:15 -0300, Philippe Mathieu-Daudé wrote:
> Hi Andrew,
> 
> On 05/22/2017 02:14 AM, Andrew Jeffery wrote:
> > On Mon, 2017-05-22 at 03:15 +, Ryan Chen wrote:
> > > In ASPEED SoC chip, all register access have following rule.
> > > Most of controller write access is only support 32bit access.
> > > Read is support 8bits/16bits/32bits.
> 
> This makes sens thinking about how a DMA controller can take advantage 
> of the ADC.
> 
> > 
> > Thanks for clearing that up Ryan.
> > 
> > Phil: I'll rework the model so the reads are 16-bits.
> 
> This shouldn't be necessary, QEMU is supposed to supports different 
> access size for different implemented size, so you can declare your 
> implementation as 32-bit and valid accesses from 8 to 32:
> 
>   static const MemoryRegionOps aspeed_adc_ops = {
>   .read = aspeed_adc_read,
>   .write = aspeed_adc_write,
>   .endianness = DEVICE_LITTLE_ENDIAN,
>   .valid.min_access_size = 1,
>   .valid.max_access_size = 4,
>   .valid.unaligned = false,
> +.impl.min_access_size = 4,
> +.impl.max_access_size = 4,
>   };
> 
> This way an I/O access from the CPU or a DMA could use 8/16-bit while 
> you keep a 32-bit implementation. The adjustment is done by 
> access_with_adjusted_size() from memory.c.
> 
> Afaik there is, however, no distinction between read/write different 
> access size in current QEMU MemoryRegionOps model.

Yep, I realised all of the above when I went to implement it. Thanks
for pointing it out though!

Andrew

signature.asc
Description: This is a digitally signed message part


Re: [Qemu-devel] [Qemu-arm] [PATCH 1/2] hw/adc: Add basic Aspeed ADC model

2017-05-21 Thread Andrew Jeffery
On Mon, 2017-05-22 at 03:15 +, Ryan Chen wrote:
> In ASPEED SoC chip, all register access have following rule. 
> Most of controller write access is only support 32bit access. 
> Read is support 8bits/16bits/32bits. 

Thanks for clearing that up Ryan.

Phil: I'll rework the model so the reads are 16-bits.

Thanks,

Andrew

> 
> 
> 
> Best Regards,
> Ryan
> 
> 信驊科技股份有限公司
> ASPEED Technology Inc.
> 2F,No.15,Industry East Road 4.,Hsinchu Science Park, Hsinchu City 30077, 
> Taiwan
> Tel: 886-3-578-9568  #857
> Fax: 886-3-578-9586
> * Email Confidentiality Notice 
> DISCLAIMER:
> This message (and any attachments) may contain legally privileged and/or 
> other confidential information. If you have received it in error, please 
> notify the sender by reply e-mail and immediately delete the e-mail and any 
> attachments without copying or disclosing the contents. Thank you.
> 
> -Original Message-
> > From: Andrew Jeffery [mailto:and...@aj.id.au] 
> Sent: Monday, May 22, 2017 8:24 AM
> > To: Philippe Mathieu-Daudé <f4...@amsat.org>; qemu-...@nongnu.org
> > > > Cc: Peter Maydell <peter.mayd...@linaro.org>; Ryan Chen 
> > > > <ryan_c...@aspeedtech.com>; Alistair Francis <alist...@alistair23.me>; 
> > > > qemu-devel@nongnu.org; Cédric Le Goater <c...@kaod.org>; Joel Stanley 
> > > > <j...@jms.id.au>
> Subject: Re: [Qemu-arm] [PATCH 1/2] hw/adc: Add basic Aspeed ADC model
> 
> Hi Phil,
> 
> On Sat, 2017-05-20 at 00:21 -0300, Philippe Mathieu-Daudé wrote:
> > Hi Andrew,
> > 
> > On 05/19/2017 09:26 PM, Andrew Jeffery wrote:
> > > This model implements enough behaviour to do basic functionality 
> > > tests such as device initialisation and read out of dummy sample 
> > > values. The sample value generation strategy is similar to the STM 
> > > ADC already in the tree.
> > > 
> > > > > Signed-off-by: Andrew Jeffery <and...@aj.id.au>
> > > 
> > > ---
> > >  hw/adc/Makefile.objs|   1 +
> > >  hw/adc/aspeed_adc.c | 246 
> > > 
> > >  include/hw/adc/aspeed_adc.h |  33 ++
> > >  3 files changed, 280 insertions(+)
> > >  create mode 100644 hw/adc/aspeed_adc.c
> > >  create mode 100644 include/hw/adc/aspeed_adc.h
> > > 
> > > diff --git a/hw/adc/Makefile.objs b/hw/adc/Makefile.objs index 
> > > 3f6dfdedaec7..2bf9362ba3c4 100644
> > > --- a/hw/adc/Makefile.objs
> > > +++ b/hw/adc/Makefile.objs
> > > @@ -1 +1,2 @@
> > >  obj-$(CONFIG_STM32F2XX_ADC) += stm32f2xx_adc.o
> > > +obj-$(CONFIG_ASPEED_SOC) += aspeed_adc.o
> > > diff --git a/hw/adc/aspeed_adc.c b/hw/adc/aspeed_adc.c new file mode 
> > > 100644 index ..d08f1684f7bc
> > > --- /dev/null
> > > +++ b/hw/adc/aspeed_adc.c
> > > @@ -0,0 +1,246 @@
> > > +/*
> > > + * Aspeed ADC
> > > + *
> > > > > + * Andrew Jeffery <and...@aj.id.au>
> > > 
> > > + *
> > > + * Copyright 2017 IBM Corp.
> > > + *
> > > + * This code is licensed under the GPL version 2 or later.  See
> > > + * the COPYING file in the top-level directory.
> > > + */
> > > +
> > > +#include "qemu/osdep.h"
> > > +#include "hw/adc/aspeed_adc.h"
> > > +#include "qapi/error.h"
> > > +#include "qemu/log.h"
> > > +
> > > +#define ASPEED_ADC_ENGINE_CTRL  0x00 #define  
> > > +ASPEED_ADC_ENGINE_CH_EN_MASK   0x #define   
> > > +ASPEED_ADC_ENGINE_CH_EN(x)((BIT(x)) << 16) #define  
> > > +ASPEED_ADC_ENGINE_INIT BIT(8) #define  
> > > +ASPEED_ADC_ENGINE_AUTO_COMPBIT(5) #define  
> > > +ASPEED_ADC_ENGINE_COMP BIT(4) #define  
> > > +ASPEED_ADC_ENGINE_MODE_MASK0x000e #define   
> > > +ASPEED_ADC_ENGINE_MODE_OFF(0b000 << 1) #define   
> > > +ASPEED_ADC_ENGINE_MODE_STANDBY(0b001 << 1) #define   
> > > +ASPEED_ADC_ENGINE_MODE_NORMAL (0b111 << 1) #define  
> > > +ASPEED_ADC_ENGINE_EN   BIT(0)
> > > +
> > > +#define ASPEED_ADC_L_MASK   ((1 << 10) - 1) #define 
> > > +ASPEED_ADC_L(x) ((x) & ASPEED_ADC_L_MASK) #define 
> > > +ASPEED_ADC_H(x) (((x) >> 16) & ASPEED_ADC_L_MASK) #define 
> > > +ASPEED_ADC_LH_MASK  

Re: [Qemu-devel] [Qemu-arm] [PATCH 1/2] hw/adc: Add basic Aspeed ADC model

2017-05-21 Thread Andrew Jeffery
Hi Phil,

On Sat, 2017-05-20 at 00:21 -0300, Philippe Mathieu-Daudé wrote:
> Hi Andrew,
> 
> On 05/19/2017 09:26 PM, Andrew Jeffery wrote:
> > This model implements enough behaviour to do basic functionality tests
> > such as device initialisation and read out of dummy sample values. The
> > sample value generation strategy is similar to the STM ADC already in
> > the tree.
> > 
> > > > Signed-off-by: Andrew Jeffery <and...@aj.id.au>
> > ---
> >  hw/adc/Makefile.objs|   1 +
> >  hw/adc/aspeed_adc.c | 246 
> > 
> >  include/hw/adc/aspeed_adc.h |  33 ++
> >  3 files changed, 280 insertions(+)
> >  create mode 100644 hw/adc/aspeed_adc.c
> >  create mode 100644 include/hw/adc/aspeed_adc.h
> > 
> > diff --git a/hw/adc/Makefile.objs b/hw/adc/Makefile.objs
> > index 3f6dfdedaec7..2bf9362ba3c4 100644
> > --- a/hw/adc/Makefile.objs
> > +++ b/hw/adc/Makefile.objs
> > @@ -1 +1,2 @@
> >  obj-$(CONFIG_STM32F2XX_ADC) += stm32f2xx_adc.o
> > +obj-$(CONFIG_ASPEED_SOC) += aspeed_adc.o
> > diff --git a/hw/adc/aspeed_adc.c b/hw/adc/aspeed_adc.c
> > new file mode 100644
> > index ..d08f1684f7bc
> > --- /dev/null
> > +++ b/hw/adc/aspeed_adc.c
> > @@ -0,0 +1,246 @@
> > +/*
> > + * Aspeed ADC
> > + *
> > > > + * Andrew Jeffery <and...@aj.id.au>
> > + *
> > + * Copyright 2017 IBM Corp.
> > + *
> > + * This code is licensed under the GPL version 2 or later.  See
> > + * the COPYING file in the top-level directory.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "hw/adc/aspeed_adc.h"
> > +#include "qapi/error.h"
> > +#include "qemu/log.h"
> > +
> > +#define ASPEED_ADC_ENGINE_CTRL  0x00
> > +#define  ASPEED_ADC_ENGINE_CH_EN_MASK   0x
> > +#define   ASPEED_ADC_ENGINE_CH_EN(x)((BIT(x)) << 16)
> > +#define  ASPEED_ADC_ENGINE_INIT BIT(8)
> > +#define  ASPEED_ADC_ENGINE_AUTO_COMPBIT(5)
> > +#define  ASPEED_ADC_ENGINE_COMP BIT(4)
> > +#define  ASPEED_ADC_ENGINE_MODE_MASK0x000e
> > +#define   ASPEED_ADC_ENGINE_MODE_OFF(0b000 << 1)
> > +#define   ASPEED_ADC_ENGINE_MODE_STANDBY(0b001 << 1)
> > +#define   ASPEED_ADC_ENGINE_MODE_NORMAL (0b111 << 1)
> > +#define  ASPEED_ADC_ENGINE_EN   BIT(0)
> > +
> > +#define ASPEED_ADC_L_MASK   ((1 << 10) - 1)
> > +#define ASPEED_ADC_L(x) ((x) & ASPEED_ADC_L_MASK)
> > +#define ASPEED_ADC_H(x) (((x) >> 16) & ASPEED_ADC_L_MASK)
> > +#define ASPEED_ADC_LH_MASK  (ASPEED_ADC_L_MASK << 16 | 
> > ASPEED_ADC_L_MASK)
> > +
> > +static inline uint32_t update_channels(uint32_t current)
> > +{
> > +const uint32_t next = (current + 7) & 0x3ff;
> > +
> > +return (next << 16) | next;
> > +}
> > +
> > +static bool breaks_threshold(AspeedADCState *s, int ch_off)
> > +{
> > +const uint32_t a = ASPEED_ADC_L(s->channels[ch_off]);
> > +const uint32_t a_lower = ASPEED_ADC_L(s->bounds[2 * ch_off]);
> > +const uint32_t a_upper = ASPEED_ADC_H(s->bounds[2 * ch_off]);
> > +const uint32_t b = ASPEED_ADC_H(s->channels[ch_off]);
> > +const uint32_t b_lower = ASPEED_ADC_L(s->bounds[2 * ch_off + 1]);
> > +const uint32_t b_upper = ASPEED_ADC_H(s->bounds[2 * ch_off + 1]);
> > +
> > +return ((a < a_lower || a > a_upper)) ||
> > +   ((b < b_lower || b > b_upper));
> > +}
> > +
> > +static uint32_t read_channel_sample(AspeedADCState *s, int ch_off)
> > +{
> > +uint32_t ret;
> > +
> > +/* Poor man's sampling */
> > +ret = s->channels[ch_off];
> > +s->channels[ch_off] = update_channels(s->channels[ch_off]);
> > +
> > +if (breaks_threshold(s, ch_off)) {
> > +qemu_irq_raise(s->irq);
> > +}
> > +
> > +return ret;
> > +}
> > +
> > +#define TO_INDEX(addr, base) (((addr) - (base)) >> 2)
> > +
> > +static uint64_t aspeed_adc_read(void *opaque, hwaddr addr,
> > + unsigned int size)
> > +{
> > +AspeedADCState *s = ASPEED_ADC(opaque);
> > +uint64_t ret;
> > +
> > +switch (addr) {
> > +case 0x00:
> > +ret = s->engine_ctrl;
> > + 

Re: [Qemu-devel] [PATCH 0/2] hw/adc: Implement a basic Aspeed ADC model

2017-05-19 Thread Andrew Jeffery
On Fri, 2017-05-19 at 17:51 -0700, no-re...@patchew.org wrote:
> In file included from /tmp/qemu-test/src/hw/adc/aspeed_adc.c:15:0:
> /tmp/qemu-test/src/hw/adc/aspeed_adc.c: In function 'aspeed_adc_read':
> /tmp/qemu-test/src/hw/adc/aspeed_adc.c:106:34: error: format '%lx' expects 
> argument of type 'long unsigned int', but argument 3 has type 'hwaddr {aka 
> long long unsigned int}' [-Werror=format=]
>  qemu_log_mask(LOG_UNIMP, "%s: addr: 0x%lx, size: %u\n", __func__, 
> addr,
>   ^
> /tmp/qemu-test/src/include/qemu/log.h:94:22: note: in definition of macro 
> 'qemu_log_mask'
>  qemu_log(FMT, ## __VA_ARGS__);  \
>   ^~~
> /tmp/qemu-test/src/hw/adc/aspeed_adc.c: In function 'aspeed_adc_write':
> /tmp/qemu-test/src/hw/adc/aspeed_adc.c:162:34: error: format '%lu' expects 
> argument of type 'long unsigned int', but argument 3 has type 'hwaddr {aka 
> long long unsigned int}' [-Werror=format=]
>  qemu_log_mask(LOG_UNIMP, "%s: %lu\n", __func__, addr);
>   ^
> /tmp/qemu-test/src/include/qemu/log.h:94:22: note: in definition of macro 
> 'qemu_log_mask'
>  qemu_log(FMT, ## __VA_ARGS__);  \
>   ^~~
> cc1: all warnings being treated as errors
> /tmp/qemu-test/src/rules.mak:69: recipe for target 'hw/adc/aspeed_adc.o' 
> failed
> make[1]: *** [hw/adc/aspeed_adc.o] Error 1
> make[1]: *** Waiting for unfinished jobs
>   CC  aarch64-softmmu/hw/scsi/virtio-scsi-dataplane.o
> Makefile:327: recipe for target 'subdir-aarch64-softmmu' failed
> make: *** [subdir-aarch64-softmmu] Error 2
> make: *** Waiting for unfinished jobs
>   GEN x86_64-softmmu/qemu-system-x86_64.exe
> tests/docker/Makefile.include:118: recipe for target 'docker-run' failed
> make[1]: *** [docker-run] Error 2
> make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-i73ef6w0/src'
> tests/docker/Makefile.include:149: recipe for target 
> 'docker-run-test-mingw@fedora' failed
> > make: *** [docker-run-test-mingw@fedora] Error 2
> === OUTPUT END ===
> 
> Test command exited with code: 2

I'll fix the format string issues in v2 along with any other issues
identified in review.

Separately, is it necessary for the bot to send the entirety of the
build output? Can we make it a bit smarter to send just the error with
some small amount of context? Maybe send the full log as an attachment?
Or host it and link to it from the email? It's a bit tedious having to
scroll through all that output to find the error at the bottom.

Cheers,

Andrew

signature.asc
Description: This is a digitally signed message part


[Qemu-devel] [PATCH 1/2] hw/adc: Add basic Aspeed ADC model

2017-05-19 Thread Andrew Jeffery
This model implements enough behaviour to do basic functionality tests
such as device initialisation and read out of dummy sample values. The
sample value generation strategy is similar to the STM ADC already in
the tree.

Signed-off-by: Andrew Jeffery <and...@aj.id.au>
---
 hw/adc/Makefile.objs|   1 +
 hw/adc/aspeed_adc.c | 246 
 include/hw/adc/aspeed_adc.h |  33 ++
 3 files changed, 280 insertions(+)
 create mode 100644 hw/adc/aspeed_adc.c
 create mode 100644 include/hw/adc/aspeed_adc.h

diff --git a/hw/adc/Makefile.objs b/hw/adc/Makefile.objs
index 3f6dfdedaec7..2bf9362ba3c4 100644
--- a/hw/adc/Makefile.objs
+++ b/hw/adc/Makefile.objs
@@ -1 +1,2 @@
 obj-$(CONFIG_STM32F2XX_ADC) += stm32f2xx_adc.o
+obj-$(CONFIG_ASPEED_SOC) += aspeed_adc.o
diff --git a/hw/adc/aspeed_adc.c b/hw/adc/aspeed_adc.c
new file mode 100644
index ..d08f1684f7bc
--- /dev/null
+++ b/hw/adc/aspeed_adc.c
@@ -0,0 +1,246 @@
+/*
+ * Aspeed ADC
+ *
+ * Andrew Jeffery <and...@aj.id.au>
+ *
+ * Copyright 2017 IBM Corp.
+ *
+ * This code is licensed under the GPL version 2 or later.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/adc/aspeed_adc.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+
+#define ASPEED_ADC_ENGINE_CTRL  0x00
+#define  ASPEED_ADC_ENGINE_CH_EN_MASK   0x
+#define   ASPEED_ADC_ENGINE_CH_EN(x)((BIT(x)) << 16)
+#define  ASPEED_ADC_ENGINE_INIT BIT(8)
+#define  ASPEED_ADC_ENGINE_AUTO_COMPBIT(5)
+#define  ASPEED_ADC_ENGINE_COMP BIT(4)
+#define  ASPEED_ADC_ENGINE_MODE_MASK0x000e
+#define   ASPEED_ADC_ENGINE_MODE_OFF(0b000 << 1)
+#define   ASPEED_ADC_ENGINE_MODE_STANDBY(0b001 << 1)
+#define   ASPEED_ADC_ENGINE_MODE_NORMAL (0b111 << 1)
+#define  ASPEED_ADC_ENGINE_EN   BIT(0)
+
+#define ASPEED_ADC_L_MASK   ((1 << 10) - 1)
+#define ASPEED_ADC_L(x) ((x) & ASPEED_ADC_L_MASK)
+#define ASPEED_ADC_H(x) (((x) >> 16) & ASPEED_ADC_L_MASK)
+#define ASPEED_ADC_LH_MASK  (ASPEED_ADC_L_MASK << 16 | ASPEED_ADC_L_MASK)
+
+static inline uint32_t update_channels(uint32_t current)
+{
+const uint32_t next = (current + 7) & 0x3ff;
+
+return (next << 16) | next;
+}
+
+static bool breaks_threshold(AspeedADCState *s, int ch_off)
+{
+const uint32_t a = ASPEED_ADC_L(s->channels[ch_off]);
+const uint32_t a_lower = ASPEED_ADC_L(s->bounds[2 * ch_off]);
+const uint32_t a_upper = ASPEED_ADC_H(s->bounds[2 * ch_off]);
+const uint32_t b = ASPEED_ADC_H(s->channels[ch_off]);
+const uint32_t b_lower = ASPEED_ADC_L(s->bounds[2 * ch_off + 1]);
+const uint32_t b_upper = ASPEED_ADC_H(s->bounds[2 * ch_off + 1]);
+
+return ((a < a_lower || a > a_upper)) ||
+   ((b < b_lower || b > b_upper));
+}
+
+static uint32_t read_channel_sample(AspeedADCState *s, int ch_off)
+{
+uint32_t ret;
+
+/* Poor man's sampling */
+ret = s->channels[ch_off];
+s->channels[ch_off] = update_channels(s->channels[ch_off]);
+
+if (breaks_threshold(s, ch_off)) {
+qemu_irq_raise(s->irq);
+}
+
+return ret;
+}
+
+#define TO_INDEX(addr, base) (((addr) - (base)) >> 2)
+
+static uint64_t aspeed_adc_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+AspeedADCState *s = ASPEED_ADC(opaque);
+uint64_t ret;
+
+switch (addr) {
+case 0x00:
+ret = s->engine_ctrl;
+break;
+case 0x04:
+ret = s->irq_ctrl;
+break;
+case 0x08:
+ret = s->vga_detect_ctrl;
+break;
+case 0x0c:
+ret = s->adc_clk_ctrl;
+break;
+case 0x10 ... 0x2e:
+ret = read_channel_sample(s, TO_INDEX(addr, 0x10));
+break;
+case 0x30 ... 0x6e:
+ret = s->bounds[TO_INDEX(addr, 0x30)];
+break;
+case 0x70 ... 0xae:
+ret = s->hysteresis[TO_INDEX(addr, 0x70)];
+break;
+case 0xc0:
+ret = s->irq_src;
+break;
+case 0xc4:
+ret = s->comp_trim;
+break;
+default:
+qemu_log_mask(LOG_UNIMP, "%s: addr: 0x%lx, size: %u\n", __func__, addr,
+size);
+ret = 0;
+break;
+}
+
+return ret;
+}
+
+static void aspeed_adc_write(void *opaque, hwaddr addr,
+   uint64_t val, unsigned int size)
+{
+AspeedADCState *s = ASPEED_ADC(opaque);
+
+switch (addr) {
+case 0x00:
+{
+uint32_t init;
+
+init = !!(val & ASPEED_ADC_ENGINE_EN);
+init *= ASPEED_ADC_ENGINE_INIT;
+
+val &= ~ASPEED_ADC_ENGINE_INIT;
+val |= init;
+}
+
+val &

[Qemu-devel] [PATCH 2/2] hw/arm: Integrate ADC model into Aspeed SoC

2017-05-19 Thread Andrew Jeffery
Signed-off-by: Andrew Jeffery <and...@aj.id.au>
---
 hw/arm/aspeed_soc.c | 15 +++
 include/hw/arm/aspeed_soc.h |  2 ++
 2 files changed, 17 insertions(+)

diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 5c667d2c35b6..11f9588720d2 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -31,6 +31,7 @@
 #define ASPEED_SOC_VIC_BASE 0x1E6C
 #define ASPEED_SOC_SDMC_BASE0x1E6E
 #define ASPEED_SOC_SCU_BASE 0x1E6E2000
+#define ASPEED_SOC_ADC_BASE 0x1E6E9000
 #define ASPEED_SOC_SRAM_BASE0x1E72
 #define ASPEED_SOC_TIMER_BASE   0x1E782000
 #define ASPEED_SOC_WDT_BASE 0x1E785000
@@ -157,6 +158,10 @@ static void aspeed_soc_init(Object *obj)
 object_property_add_alias(obj, "hw-strap2", OBJECT(>scu),
   "hw-strap2", _abort);
 
+object_initialize(>adc, sizeof(s->adc), TYPE_ASPEED_ADC);
+object_property_add_child(obj, "adc", OBJECT(>adc), NULL);
+qdev_set_parent_bus(DEVICE(>adc), sysbus_get_default());
+
 object_initialize(>fmc, sizeof(s->fmc), sc->info->fmc_typename);
 object_property_add_child(obj, "fmc", OBJECT(>fmc), NULL);
 qdev_set_parent_bus(DEVICE(>fmc), sysbus_get_default());
@@ -256,6 +261,16 @@ static void aspeed_soc_realize(DeviceState *dev, Error 
**errp)
 }
 sysbus_mmio_map(SYS_BUS_DEVICE(>scu), 0, ASPEED_SOC_SCU_BASE);
 
+/* ADC */
+object_property_set_bool(OBJECT(>adc), true, "realized", );
+if (err) {
+error_propagate(errp, err);
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>adc), 0, ASPEED_SOC_ADC_BASE);
+sysbus_connect_irq(SYS_BUS_DEVICE(>adc), 0,
+qdev_get_gpio_in(DEVICE(>vic), 31));
+
 /* UART - attach an 8250 to the IO space as our UART5 */
 if (serial_hds[0]) {
 qemu_irq uart5 = qdev_get_gpio_in(DEVICE(>vic), uart_irqs[4]);
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index d16205c66b5f..3b4d66d30f08 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -15,6 +15,7 @@
 #include "hw/arm/arm.h"
 #include "hw/intc/aspeed_vic.h"
 #include "hw/misc/aspeed_scu.h"
+#include "hw/adc/aspeed_adc.h"
 #include "hw/misc/aspeed_sdmc.h"
 #include "hw/timer/aspeed_timer.h"
 #include "hw/i2c/aspeed_i2c.h"
@@ -37,6 +38,7 @@ typedef struct AspeedSoCState {
 AspeedTimerCtrlState timerctrl;
 AspeedI2CState i2c;
 AspeedSCUState scu;
+AspeedADCState adc;
 AspeedSMCState fmc;
 AspeedSMCState spi[ASPEED_SPIS_NUM];
 AspeedSDMCState sdmc;
-- 
2.9.3




[Qemu-devel] [PATCH 0/2] hw/adc: Implement a basic Aspeed ADC model

2017-05-19 Thread Andrew Jeffery
Hello,

This short series introduces a basic model for the Aspeed ADC and glues it into
the generic Aspeed SoC definition. The register interface is enhanced slightly
from the AST2400 to the AST2500, but in a backwards-compatible way by making
use of reserved bits. As such I haven't made any effort to differentiate the
two.

The addition of a basic ADC model allows the Aspeed SDK kernel to boot under
QEMU's ast2500-evb machine. The upstream kernel driver doesn't test the
initialisation bit before completing its probe(), and thus doesn't get stuck if
the bit is not set. This is in contrast to the SDK kernel which spins on the
initialisation bit, never making forward progress in the absence of the ADC
model.

Tested with both Aspeed's SDK kernel and upstream Linux.

Cheers,

Andrew

Andrew Jeffery (2):
  hw/adc: Add basic Aspeed ADC model
  hw/arm: Integrate ADC model into Aspeed SoC

 hw/adc/Makefile.objs|   1 +
 hw/adc/aspeed_adc.c | 246 
 hw/arm/aspeed_soc.c |  15 +++
 include/hw/adc/aspeed_adc.h |  33 ++
 include/hw/arm/aspeed_soc.h |   2 +
 5 files changed, 297 insertions(+)
 create mode 100644 hw/adc/aspeed_adc.c
 create mode 100644 include/hw/adc/aspeed_adc.h

-- 
2.9.3




<    1   2   3   >