diff mbox series

[v2,11/12] hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj

Message ID 20200611223016.259837-12-hskinnemoen@google.com (mailing list archive)
State New, archived
Headers show
Series Add Nuvoton NPCM730/NPCM750 SoCs and two BMC machines | expand

Commit Message

Havard Skinnemoen June 11, 2020, 10:30 p.m. UTC
This allows these NPCM7xx-based boards to boot from a flash image, e.g.
one built with OpenBMC. For example like this:

IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc
qemu-system-arm -machine quanta-gsj -nographic \
	-bios ~/qemu/bootrom/npcm7xx_bootrom.bin \
	-drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on

Change-Id: I158a4d9952c0e90f2b1b7280443a7305b6ae57cf
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
---
 hw/arm/npcm7xx_boards.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

Comments

Havard Skinnemoen June 13, 2020, 12:19 a.m. UTC | #1
On Thu, Jun 11, 2020 at 3:30 PM Havard Skinnemoen <hskinnemoen@google.com>
wrote:

> @@ -57,18 +72,30 @@ static NPCM7xxState *npcm7xx_create_soc(MachineState
> *machine)
>  static void npcm750_evb_init(MachineState *machine)
>  {
>      NPCM7xxState *soc;
> +    DriveInfo *dinfo;
>
>      soc = npcm7xx_create_soc(machine);
>
> +    dinfo = drive_get(IF_MTD, 0, 0);
> +    if (dinfo) {
> +        npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", dinfo);
>

Btw, this does not actually work. I initially tested it with the same flash
chip as gsj, which seems to work, but after switching to the Winbond model
(as per the npcm750 evb schematics) it looks like it reads incorrect data
in DIO mode.

While trying to figure out what's going wrong, I stumbled across this patch:

https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg01586.html

which I don't understand. It looks like the winbond model wants one dummy
cycle after the address, since dummy cycles are modeled as byte transfers.
This doesn't seem to match the data sheet, which specifies 4 dummy cycles
in DIO mode (which is actually a special command byte transferred across
two data lines).

If the "continuous read mode command" is actually modeled as a single byte,
then it makes sense because that works out to 4 dummy cycles in DIO mode.
However, I don't understand how the flash controller model is supposed to
detect this situation, and I don't see any flash controller models that
support sending anything but dummy _bits_ between the address and data
phases.

Could you please clarify how this is supposed to work? Are there any
existing machines that use a w25 chip in DIO mode?

Havard
Cédric Le Goater June 17, 2020, 4:42 p.m. UTC | #2
On 6/12/20 12:30 AM, Havard Skinnemoen wrote:
> This allows these NPCM7xx-based boards to boot from a flash image, e.g.
> one built with OpenBMC. For example like this:
> 
> IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc

could you put the image on some site when ready ? 

> qemu-system-arm -machine quanta-gsj -nographic \
> 	-bios ~/qemu/bootrom/npcm7xx_bootrom.bin \
> 	-drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on
> 
> Change-Id: I158a4d9952c0e90f2b1b7280443a7305b6ae57cf
> Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
> Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>

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

> ---
>  hw/arm/npcm7xx_boards.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
> index 86e18af2d7..1ec772fa59 100644
> --- a/hw/arm/npcm7xx_boards.c
> +++ b/hw/arm/npcm7xx_boards.c
> @@ -18,6 +18,7 @@
>  #include "hw/arm/boot.h"
>  #include "hw/arm/npcm7xx.h"
>  #include "hw/core/cpu.h"
> +#include "hw/qdev-properties.h"
>  #include "qapi/error.h"
>  #include "qemu/units.h"
>  
> @@ -40,6 +41,20 @@ static void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
>      arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
>  }
>  
> +static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
> +                                  const char *flash_type, DriveInfo *dinfo) {
> +    DeviceState *flash;
> +    qemu_irq flash_cs;
> +
> +    flash = ssi_create_slave_no_init(fiu->spi, flash_type);
> +    qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo),
> +                        &error_abort);
> +    qdev_init_nofail(flash);
> +
> +    flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
> +    sysbus_connect_irq(SYS_BUS_DEVICE(fiu), cs_no, flash_cs);
> +}
> +
>  static NPCM7xxState *npcm7xx_create_soc(MachineState *machine)
>  {
>      NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
> @@ -57,18 +72,30 @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine)
>  static void npcm750_evb_init(MachineState *machine)
>  {
>      NPCM7xxState *soc;
> +    DriveInfo *dinfo;
>  
>      soc = npcm7xx_create_soc(machine);
>  
> +    dinfo = drive_get(IF_MTD, 0, 0);
> +    if (dinfo) {
> +        npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", dinfo);
> +    }
> +
>      npcm7xx_load_kernel(machine, soc);
>  }
>  
>  static void quanta_gsj_init(MachineState *machine)
>  {
>      NPCM7xxState *soc;
> +    DriveInfo *dinfo;
>  
>      soc = npcm7xx_create_soc(machine);
>  
> +    dinfo = drive_get(IF_MTD, 0, 0);
> +    if (dinfo) {
> +        npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e", dinfo);
> +    }
> +
>      npcm7xx_load_kernel(machine, soc);
>  }
>  
>
Joel Stanley June 18, 2020, 1:35 a.m. UTC | #3
On Wed, 17 Jun 2020 at 16:42, Cédric Le Goater <clg@kaod.org> wrote:
>
> On 6/12/20 12:30 AM, Havard Skinnemoen wrote:
> > This allows these NPCM7xx-based boards to boot from a flash image, e.g.
> > one built with OpenBMC. For example like this:
> >
> > IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc
>
> could you put the image on some site when ready ?

They are built as part of OpenBMC CI:

https://openpower.xyz/job/openbmc-build/distro=ubuntu,label=builder,target=gsj/lastSuccessfulBuild/artifact/deploy/images/gsj/

Cheers,

Joel

>
> > qemu-system-arm -machine quanta-gsj -nographic \
> >       -bios ~/qemu/bootrom/npcm7xx_bootrom.bin \
> >       -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on
> >
> > Change-Id: I158a4d9952c0e90f2b1b7280443a7305b6ae57cf
> > Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
> > Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
>
> Reviewed-by: Cédric Le Goater <clg@kaod.org>
Havard Skinnemoen June 18, 2020, 2:40 a.m. UTC | #4
On Wed, Jun 17, 2020 at 6:35 PM Joel Stanley <joel@jms.id.au> wrote:

> On Wed, 17 Jun 2020 at 16:42, Cédric Le Goater <clg@kaod.org> wrote:
> >
> > On 6/12/20 12:30 AM, Havard Skinnemoen wrote:
> > > This allows these NPCM7xx-based boards to boot from a flash image, e.g.
> > > one built with OpenBMC. For example like this:
> > >
> > > IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc
> >
> > could you put the image on some site when ready ?
>
> They are built as part of OpenBMC CI:
>
>
> https://openpower.xyz/job/openbmc-build/distro=ubuntu,label=builder,target=gsj/lastSuccessfulBuild/artifact/deploy/images/gsj/


Cool, I didn't know that!

Trying to boot that image reminds me of a couple of issues I ran into.

1. This error:

spi_master spi0: /ahb/fiu@fb000000/spi-nor@0 has no valid
'spi-max-frequency' property (-22)

should be fixed by
https://github.com/Nuvoton-Israel/linux/commit/c9185ea65bec8ba7b617080c6278eb3e36db4eb4
but it looks like it hasn't propagated into the openbmc repo yet.

2. npcm7xx_ether_probe crashes the kernel, presumably because there's no
emac model in qemu yet. I worked around it by disabling that driver, but it
shouldn't be necessary once the emac model is done.

3. IIRC, after getting past (1) and (2), it turned out the MTD partition
layout didn't match the device tree, so I had to adjust some offsets in the
openbmc build. I was planning to post that to the openbmc list after making
sure I'm cleared to contribute.

Havard
diff mbox series

Patch

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 86e18af2d7..1ec772fa59 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -18,6 +18,7 @@ 
 #include "hw/arm/boot.h"
 #include "hw/arm/npcm7xx.h"
 #include "hw/core/cpu.h"
+#include "hw/qdev-properties.h"
 #include "qapi/error.h"
 #include "qemu/units.h"
 
@@ -40,6 +41,20 @@  static void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
     arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
 }
 
+static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
+                                  const char *flash_type, DriveInfo *dinfo) {
+    DeviceState *flash;
+    qemu_irq flash_cs;
+
+    flash = ssi_create_slave_no_init(fiu->spi, flash_type);
+    qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo),
+                        &error_abort);
+    qdev_init_nofail(flash);
+
+    flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
+    sysbus_connect_irq(SYS_BUS_DEVICE(fiu), cs_no, flash_cs);
+}
+
 static NPCM7xxState *npcm7xx_create_soc(MachineState *machine)
 {
     NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
@@ -57,18 +72,30 @@  static NPCM7xxState *npcm7xx_create_soc(MachineState *machine)
 static void npcm750_evb_init(MachineState *machine)
 {
     NPCM7xxState *soc;
+    DriveInfo *dinfo;
 
     soc = npcm7xx_create_soc(machine);
 
+    dinfo = drive_get(IF_MTD, 0, 0);
+    if (dinfo) {
+        npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", dinfo);
+    }
+
     npcm7xx_load_kernel(machine, soc);
 }
 
 static void quanta_gsj_init(MachineState *machine)
 {
     NPCM7xxState *soc;
+    DriveInfo *dinfo;
 
     soc = npcm7xx_create_soc(machine);
 
+    dinfo = drive_get(IF_MTD, 0, 0);
+    if (dinfo) {
+        npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e", dinfo);
+    }
+
     npcm7xx_load_kernel(machine, soc);
 }