Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Asherah Connor
On 21/02/23 01:02:p, Heinrich Schuchardt wrote:
> On 23.02.21 12:43, Asherah Connor wrote:
> For which architectures does the fw_cfg device exist?
> 
> It it is only ARM and X86, than I am missing such a dependency on
> CONFIG_CMD_QFW.

Right now we have:

arch/arm/Kconfig:
...
config ARCH_QEMU
...
imply CMD_QFW

I think we also want this:

arch/x86/cpu/qemu/Kconfig
config QEMU
...
imply CMD_QFW

This is my first time using Kconfig and I'll admit I'm not too certain
where things go.


> If these numbers are constants, why should they be copied to platform
> data? This only increases code size.
> 
> I think there is nothing wrong with using constants here.

Okay, excellent.  I'll fold those into drivers/misc/qfw_pio.c and get
rid of the qfw_pio_plat struct entirely.  


> ARM yield is meant to be used on multi-threaded systems to indicate that
> the thread can be swapped. Why would we need it in U-Boot which is
> single-threaded?
> 
> Can't we simply use
> 
> while (be32_to_cpu(dma.control) & ~FW_CFG_DMA_ERROR);
> 
> with no command in the loop for all architectures?

Good question.  This code originated here, where the original (x86-only)
driver used pause:

https://gitlab.denx.de/u-boot/u-boot/-/commit/f60df20aa966c3de850afafe3cce70a51d0b261c#41c93c056084377352da52f1d88fc49288a4846f_0_59

When porting to Arm I used the equivalent.

While U-Boot is single-threaded, the architecture that executes this
instruction is always QEMU, and -- at a guess -- it might be that
pause/yield here lets QEMU finish its part of the DMA faster.

I've run the QEMU tests on arm(64)/x86(_64) without the yield or pause
and they still pass.  It might be simply unnecessary, so I'll remove for
now in favour of simplicity and less arch-specific code.

Best,

Asherah


Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Asherah Connor
On 21/02/23 06:02:p, Tom Rini wrote:
> Ah well, so my experiment would likely have not worked back then anyhow
> (but I don't recall seeing an error at the time).  Anyhow, for now in
> U-Boot as there's not a generic QEMU symbol, this side of things should
> depend on ARM||X86 for now and let future enhancements add it elsewhere.
> Thanks!

I think this is a fine way to do it.  If users come forward wanting to
use it on other archs we can rethink it, but as long as there are only
two it seems not yet worth making fully generic.

Best,

Asherah



Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Tom Rini
On Tue, Feb 23, 2021 at 11:54:01PM +, Asherah Connor wrote:
> On 21/02/23 11:02:p, Tom Rini wrote:
> > On Tue, Feb 23, 2021 at 05:15:49PM +0100, Heinrich Schuchardt wrote:
> > > On 2/23/21 5:03 PM, Tom Rini wrote:
> > > > On Tue, Feb 23, 2021 at 04:54:45PM +0100, Heinrich Schuchardt wrote:
> > > > > qemu-system-riscv64 does not allow me to specify a file for the qfw 
> > > > > interface.
> > > > 
> > > > Really?  It's listed under the help (taken from out docker images):
> > > > $ /opt/qemu/bin/qemu-system-riscv64 --help
> > > > ...
> > > > Debug/Expert options:
> > > > -fw_cfg [name=],file=
> > > >  add named fw_cfg entry with contents from file
> > > > -fw_cfg [name=],string=
> > > >  add named fw_cfg entry with contents from string
> > > > 
> > > 
> > > The man-page is shared by all qemu-system-*. It is not architecture
> > > specific. That is why it shows items like: "PS/2 mouse and keyboard".
> > > 
> > > qemu-system-riscv64 (v5.0.0) has no fw_cfg device:
> > > 
> > > $ qemu-system-riscv64 -machine virt -m 1G -nographic -bios u-boot
> > > -fw_cfg opt/foo,file=foo
> > > qemu-system-riscv64: -fw_cfg opt/foo,file=foo: fw_cfg device not available
> > > 
> > > qemu-system-aarch64 does not complain:
> > > 
> > > $ qemu-system-aarch64 -machine virt -m 1G -nographic -bios u-boot
> > > -fw_cfg opt/foo,file=foo
> > 
> > So all that's missing is someone hooking that up inside qemu itself.
> > I'm pretty sure it works on PowerPC, from when I was trying to figure
> > out how to pass something in to qemu-ppce500 a while ago.
> > qemu-system-mips/sh4 don't complain.
> 
> A review of the various FW_CFG_ Kconfig options in QEMU itself suggests
> there is support on at least i386, arm, ppc, and mips (their arch
> terms).  Looking further, it appears sparc(64) and hppa (HP PA-RISC) are
> also supported in the source base.
> 
> But actually trying it, it looks like a freshly built QEMU 5.2.0 does
> not support qfw on ppce500:
> 
> $ qemu-system-ppc -M ppce500 -nographic -bios \
>   build-qemu-ppce500/u-boot -fw_cfg xyz,string=hello
> qemu-system-ppc: -fw_cfg xyz,string=hello: fw_cfg device not available
> 
> Same for mips(64)(el).  Maybe I missed a configuration option somewhere.
> The sparc systems work fine.

Ah well, so my experiment would likely have not worked back then anyhow
(but I don't recall seeing an error at the time).  Anyhow, for now in
U-Boot as there's not a generic QEMU symbol, this side of things should
depend on ARM||X86 for now and let future enhancements add it elsewhere.
Thanks!

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Asherah Connor
On 21/02/23 11:02:p, Tom Rini wrote:
> On Tue, Feb 23, 2021 at 05:15:49PM +0100, Heinrich Schuchardt wrote:
> > On 2/23/21 5:03 PM, Tom Rini wrote:
> > > On Tue, Feb 23, 2021 at 04:54:45PM +0100, Heinrich Schuchardt wrote:
> > > > qemu-system-riscv64 does not allow me to specify a file for the qfw 
> > > > interface.
> > > 
> > > Really?  It's listed under the help (taken from out docker images):
> > > $ /opt/qemu/bin/qemu-system-riscv64 --help
> > > ...
> > > Debug/Expert options:
> > > -fw_cfg [name=],file=
> > >  add named fw_cfg entry with contents from file
> > > -fw_cfg [name=],string=
> > >  add named fw_cfg entry with contents from string
> > > 
> > 
> > The man-page is shared by all qemu-system-*. It is not architecture
> > specific. That is why it shows items like: "PS/2 mouse and keyboard".
> > 
> > qemu-system-riscv64 (v5.0.0) has no fw_cfg device:
> > 
> > $ qemu-system-riscv64 -machine virt -m 1G -nographic -bios u-boot
> > -fw_cfg opt/foo,file=foo
> > qemu-system-riscv64: -fw_cfg opt/foo,file=foo: fw_cfg device not available
> > 
> > qemu-system-aarch64 does not complain:
> > 
> > $ qemu-system-aarch64 -machine virt -m 1G -nographic -bios u-boot
> > -fw_cfg opt/foo,file=foo
> 
> So all that's missing is someone hooking that up inside qemu itself.
> I'm pretty sure it works on PowerPC, from when I was trying to figure
> out how to pass something in to qemu-ppce500 a while ago.
> qemu-system-mips/sh4 don't complain.

A review of the various FW_CFG_ Kconfig options in QEMU itself suggests
there is support on at least i386, arm, ppc, and mips (their arch
terms).  Looking further, it appears sparc(64) and hppa (HP PA-RISC) are
also supported in the source base.

But actually trying it, it looks like a freshly built QEMU 5.2.0 does
not support qfw on ppce500:

$ qemu-system-ppc -M ppce500 -nographic -bios \
  build-qemu-ppce500/u-boot -fw_cfg xyz,string=hello
qemu-system-ppc: -fw_cfg xyz,string=hello: fw_cfg device not available

Same for mips(64)(el).  Maybe I missed a configuration option somewhere.
The sparc systems work fine.

Best,

Asherah


Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Tom Rini
On Tue, Feb 23, 2021 at 05:15:49PM +0100, Heinrich Schuchardt wrote:
> On 2/23/21 5:03 PM, Tom Rini wrote:
> > On Tue, Feb 23, 2021 at 04:54:45PM +0100, Heinrich Schuchardt wrote:
> > > Am 23. Februar 2021 15:53:38 MEZ schrieb Tom Rini :
> > > > On Tue, Feb 23, 2021 at 01:59:52PM +0100, Heinrich Schuchardt wrote:
> > > > > On 23.02.21 12:43, Asherah Connor wrote:
> > > > > > Updates the QFW driver to use the driver model, and adds support
> > > > for QFW
> > > > > > on Arm platforms by configuring from the device tree and using MMIO
> > > > > > accordingly.  A sandbox driver for QFW is also included, and a
> > > > simple DM
> > > > > > unit test for it.
> > > > > 
> > > > > For which architectures does the fw_cfg device exist?
> > > > > 
> > > > > It it is only ARM and X86, than I am missing such a dependency on
> > > > > CONFIG_CMD_QFW.
> > > > 
> > > > The qemu 'qfw' interface is I believe a generic QEMU thing and a
> > > > generic
> > > > U-Boot cleanup would be to have a common QEMU symbol for everyone to
> > > > select.
> > > 
> > > qemu-system-riscv64 does not allow me to specify a file for the qfw 
> > > interface.
> > 
> > Really?  It's listed under the help (taken from out docker images):
> > $ /opt/qemu/bin/qemu-system-riscv64 --help
> > ...
> > Debug/Expert options:
> > -fw_cfg [name=],file=
> >  add named fw_cfg entry with contents from file
> > -fw_cfg [name=],string=
> >  add named fw_cfg entry with contents from string
> > 
> 
> The man-page is shared by all qemu-system-*. It is not architecture
> specific. That is why it shows items like: "PS/2 mouse and keyboard".
> 
> qemu-system-riscv64 (v5.0.0) has no fw_cfg device:
> 
> $ qemu-system-riscv64 -machine virt -m 1G -nographic -bios u-boot
> -fw_cfg opt/foo,file=foo
> qemu-system-riscv64: -fw_cfg opt/foo,file=foo: fw_cfg device not available
> 
> qemu-system-aarch64 does not complain:
> 
> $ qemu-system-aarch64 -machine virt -m 1G -nographic -bios u-boot
> -fw_cfg opt/foo,file=foo

So all that's missing is someone hooking that up inside qemu itself.
I'm pretty sure it works on PowerPC, from when I was trying to figure
out how to pass something in to qemu-ppce500 a while ago.
qemu-system-mips/sh4 don't complain.

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Heinrich Schuchardt

On 2/23/21 5:03 PM, Tom Rini wrote:

On Tue, Feb 23, 2021 at 04:54:45PM +0100, Heinrich Schuchardt wrote:

Am 23. Februar 2021 15:53:38 MEZ schrieb Tom Rini :

On Tue, Feb 23, 2021 at 01:59:52PM +0100, Heinrich Schuchardt wrote:

On 23.02.21 12:43, Asherah Connor wrote:

Updates the QFW driver to use the driver model, and adds support

for QFW

on Arm platforms by configuring from the device tree and using MMIO
accordingly.  A sandbox driver for QFW is also included, and a

simple DM

unit test for it.


For which architectures does the fw_cfg device exist?

It it is only ARM and X86, than I am missing such a dependency on
CONFIG_CMD_QFW.


The qemu 'qfw' interface is I believe a generic QEMU thing and a
generic
U-Boot cleanup would be to have a common QEMU symbol for everyone to
select.


qemu-system-riscv64 does not allow me to specify a file for the qfw interface.


Really?  It's listed under the help (taken from out docker images):
$ /opt/qemu/bin/qemu-system-riscv64 --help
...
Debug/Expert options:
-fw_cfg [name=],file=
 add named fw_cfg entry with contents from file
-fw_cfg [name=],string=
 add named fw_cfg entry with contents from string



The man-page is shared by all qemu-system-*. It is not architecture
specific. That is why it shows items like: "PS/2 mouse and keyboard".

qemu-system-riscv64 (v5.0.0) has no fw_cfg device:

$ qemu-system-riscv64 -machine virt -m 1G -nographic -bios u-boot
-fw_cfg opt/foo,file=foo
qemu-system-riscv64: -fw_cfg opt/foo,file=foo: fw_cfg device not available

qemu-system-aarch64 does not complain:

$ qemu-system-aarch64 -machine virt -m 1G -nographic -bios u-boot
-fw_cfg opt/foo,file=foo

Best regards

Heinrich


Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Tom Rini
On Tue, Feb 23, 2021 at 04:54:45PM +0100, Heinrich Schuchardt wrote:
> Am 23. Februar 2021 15:53:38 MEZ schrieb Tom Rini :
> >On Tue, Feb 23, 2021 at 01:59:52PM +0100, Heinrich Schuchardt wrote:
> >> On 23.02.21 12:43, Asherah Connor wrote:
> >> > Updates the QFW driver to use the driver model, and adds support
> >for QFW
> >> > on Arm platforms by configuring from the device tree and using MMIO
> >> > accordingly.  A sandbox driver for QFW is also included, and a
> >simple DM
> >> > unit test for it.
> >> 
> >> For which architectures does the fw_cfg device exist?
> >> 
> >> It it is only ARM and X86, than I am missing such a dependency on
> >> CONFIG_CMD_QFW.
> >
> >The qemu 'qfw' interface is I believe a generic QEMU thing and a
> >generic
> >U-Boot cleanup would be to have a common QEMU symbol for everyone to
> >select.
> 
> qemu-system-riscv64 does not allow me to specify a file for the qfw interface.

Really?  It's listed under the help (taken from out docker images):
$ /opt/qemu/bin/qemu-system-riscv64 --help
...
Debug/Expert options:
-fw_cfg [name=],file=
add named fw_cfg entry with contents from file
-fw_cfg [name=],string=
add named fw_cfg entry with contents from string

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Heinrich Schuchardt
Am 23. Februar 2021 15:53:38 MEZ schrieb Tom Rini :
>On Tue, Feb 23, 2021 at 01:59:52PM +0100, Heinrich Schuchardt wrote:
>> On 23.02.21 12:43, Asherah Connor wrote:
>> > Updates the QFW driver to use the driver model, and adds support
>for QFW
>> > on Arm platforms by configuring from the device tree and using MMIO
>> > accordingly.  A sandbox driver for QFW is also included, and a
>simple DM
>> > unit test for it.
>> 
>> For which architectures does the fw_cfg device exist?
>> 
>> It it is only ARM and X86, than I am missing such a dependency on
>> CONFIG_CMD_QFW.
>
>The qemu 'qfw' interface is I believe a generic QEMU thing and a
>generic
>U-Boot cleanup would be to have a common QEMU symbol for everyone to
>select.


qemu-system-riscv64 does not allow me to specify a file for the qfw interface.

Best regards

Heinrich



Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Tom Rini
On Tue, Feb 23, 2021 at 01:59:52PM +0100, Heinrich Schuchardt wrote:
> On 23.02.21 12:43, Asherah Connor wrote:
> > Updates the QFW driver to use the driver model, and adds support for QFW
> > on Arm platforms by configuring from the device tree and using MMIO
> > accordingly.  A sandbox driver for QFW is also included, and a simple DM
> > unit test for it.
> 
> For which architectures does the fw_cfg device exist?
> 
> It it is only ARM and X86, than I am missing such a dependency on
> CONFIG_CMD_QFW.

The qemu 'qfw' interface is I believe a generic QEMU thing and a generic
U-Boot cleanup would be to have a common QEMU symbol for everyone to
select.

-- 
Tom


signature.asc
Description: PGP signature


Re: [PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Heinrich Schuchardt
On 23.02.21 12:43, Asherah Connor wrote:
> Updates the QFW driver to use the driver model, and adds support for QFW
> on Arm platforms by configuring from the device tree and using MMIO
> accordingly.  A sandbox driver for QFW is also included, and a simple DM
> unit test for it.

For which architectures does the fw_cfg device exist?

It it is only ARM and X86, than I am missing such a dependency on
CONFIG_CMD_QFW.

>
> Signed-off-by: Asherah Connor 
> ---
>
> Changes in v3:
> - ARCH_QEMU now implies CMD_QFW, not QFW
> - rename qemu_fwcfg_read_entry_pio to ..._io
>
>  arch/arm/Kconfig |   1 +
>  arch/x86/cpu/qemu/cpu.c  |   7 +-
>  arch/x86/cpu/qemu/qemu.c |  54 ++--
>  arch/x86/cpu/qfw_cpu.c   |  11 +-
>  cmd/qfw.c|  44 +++---
>  drivers/misc/Kconfig |   1 +
>  drivers/misc/qfw.c   | 289 +++
>  include/qfw.h|  63 +
>  8 files changed, 292 insertions(+), 178 deletions(-)
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index d51abbeaf0..cd01dc458a 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -937,6 +937,7 @@ config ARCH_QEMU
>   imply DM_RNG
>   imply DM_RTC
>   imply RTC_PL031
> + imply CMD_QFW
>
>  config ARCH_RMOBILE
>   bool "Renesas ARM SoCs"
> diff --git a/arch/x86/cpu/qemu/cpu.c b/arch/x86/cpu/qemu/cpu.c
> index 9ce86b379c..ab1b797f9a 100644
> --- a/arch/x86/cpu/qemu/cpu.c
> +++ b/arch/x86/cpu/qemu/cpu.c
> @@ -22,7 +22,12 @@ int cpu_qemu_get_desc(const struct udevice *dev, char 
> *buf, int size)
>
>  static int cpu_qemu_get_count(const struct udevice *dev)
>  {
> - return qemu_fwcfg_online_cpus();
> + struct udevice *qfw_dev = qemu_fwcfg_dev();
> +
> + if (!qfw_dev)
> + return -ENODEV;
> +
> + return qemu_fwcfg_online_cpus(qfw_dev);
>  }
>
>  static const struct cpu_ops cpu_qemu_ops = {
> diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c
> index 044a429c13..e255af9a4a 100644
> --- a/arch/x86/cpu/qemu/qemu.c
> +++ b/arch/x86/cpu/qemu/qemu.c
> @@ -8,6 +8,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -19,45 +20,20 @@ static bool i440fx;
>  #ifdef CONFIG_QFW
>
>  /* on x86, the qfw registers are all IO ports */
> -#define FW_CONTROL_PORT  0x510
> -#define FW_DATA_PORT 0x511
> -#define FW_DMA_PORT_LOW  0x514
> -#define FW_DMA_PORT_HIGH 0x518
> -
> -static void qemu_x86_fwcfg_read_entry_pio(uint16_t entry,
> - uint32_t size, void *address)
> -{
> - uint32_t i = 0;
> - uint8_t *data = address;
> -
> - /*
> -  * writting FW_CFG_INVALID will cause read operation to resume at
> -  * last offset, otherwise read will start at offset 0
> -  *
> -  * Note: on platform where the control register is IO port, the
> -  * endianness is little endian.
> -  */
> - if (entry != FW_CFG_INVALID)
> - outw(cpu_to_le16(entry), FW_CONTROL_PORT);
> -
> - /* the endianness of data register is string-preserving */
> - while (size--)
> - data[i++] = inb(FW_DATA_PORT);
> -}
> -
> -static void qemu_x86_fwcfg_read_entry_dma(struct fw_cfg_dma_access *dma)
> -{
> - /* the DMA address register is big endian */
> - outl(cpu_to_be32((uintptr_t)dma), FW_DMA_PORT_HIGH);
> -
> - while (be32_to_cpu(dma->control) & ~FW_CFG_DMA_ERROR)
> - __asm__ __volatile__ ("pause");
> -}
> +static const struct qfw_plat x86_qfw_plat = {
> + .io = {
> + .control_port   = 0x510,
> + .data_port  = 0x511,
> + .dma_port_low   = 0x514,
> + .dma_port_high  = 0x518,
> + },
> +};

If these numbers are constants, why should they be copied to platform
data? This only increases code size.

I think there is nothing wrong with using constants here.


>
> -static struct fw_cfg_arch_ops fwcfg_x86_ops = {
> - .arch_read_pio = qemu_x86_fwcfg_read_entry_pio,
> - .arch_read_dma = qemu_x86_fwcfg_read_entry_dma
> +U_BOOT_DRVINFO(x86_qfw) = {
> + .name = "qfw",
> + .plat = _qfw_plat,
>  };
> +
>  #endif
>
>  static void enable_pm_piix(void)
> @@ -132,10 +108,6 @@ static void qemu_chipset_init(void)
>
>   enable_pm_ich9();
>   }
> -
> -#ifdef CONFIG_QFW
> - qemu_fwcfg_init(_x86_ops);
> -#endif
>  }
>
>  #if !CONFIG_IS_ENABLED(SPL_X86_32BIT_INIT)
> diff --git a/arch/x86/cpu/qfw_cpu.c b/arch/x86/cpu/qfw_cpu.c
> index b959eaddde..c8fb918494 100644
> --- a/arch/x86/cpu/qfw_cpu.c
> +++ b/arch/x86/cpu/qfw_cpu.c
> @@ -18,7 +18,7 @@ int qemu_cpu_fixup(void)
>   int cpu_num;
>   int cpu_online;
>   struct uclass *uc;
> - struct udevice *dev, *pdev;
> + struct udevice *dev, *pdev, *qfwdev;
>   struct cpu_plat *plat;
>   char *cpu;
>
> @@ -39,6 +39,13 @@ int qemu_cpu_fixup(void)
>   return -ENODEV;
>   }
>
> + /* get qfw dev */
> + qfwdev = qemu_fwcfg_dev();
> + if (!qfwdev) {
> +

[PATCH v3 1/4] arm: x86: qemu: move qfw to DM, include Arm support

2021-02-23 Thread Asherah Connor
Updates the QFW driver to use the driver model, and adds support for QFW
on Arm platforms by configuring from the device tree and using MMIO
accordingly.  A sandbox driver for QFW is also included, and a simple DM
unit test for it.

Signed-off-by: Asherah Connor 
---

Changes in v3:
- ARCH_QEMU now implies CMD_QFW, not QFW
- rename qemu_fwcfg_read_entry_pio to ..._io

 arch/arm/Kconfig |   1 +
 arch/x86/cpu/qemu/cpu.c  |   7 +-
 arch/x86/cpu/qemu/qemu.c |  54 ++--
 arch/x86/cpu/qfw_cpu.c   |  11 +-
 cmd/qfw.c|  44 +++---
 drivers/misc/Kconfig |   1 +
 drivers/misc/qfw.c   | 289 +++
 include/qfw.h|  63 +
 8 files changed, 292 insertions(+), 178 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d51abbeaf0..cd01dc458a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -937,6 +937,7 @@ config ARCH_QEMU
imply DM_RNG
imply DM_RTC
imply RTC_PL031
+   imply CMD_QFW
 
 config ARCH_RMOBILE
bool "Renesas ARM SoCs"
diff --git a/arch/x86/cpu/qemu/cpu.c b/arch/x86/cpu/qemu/cpu.c
index 9ce86b379c..ab1b797f9a 100644
--- a/arch/x86/cpu/qemu/cpu.c
+++ b/arch/x86/cpu/qemu/cpu.c
@@ -22,7 +22,12 @@ int cpu_qemu_get_desc(const struct udevice *dev, char *buf, 
int size)
 
 static int cpu_qemu_get_count(const struct udevice *dev)
 {
-   return qemu_fwcfg_online_cpus();
+   struct udevice *qfw_dev = qemu_fwcfg_dev();
+
+   if (!qfw_dev)
+   return -ENODEV;
+
+   return qemu_fwcfg_online_cpus(qfw_dev);
 }
 
 static const struct cpu_ops cpu_qemu_ops = {
diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c
index 044a429c13..e255af9a4a 100644
--- a/arch/x86/cpu/qemu/qemu.c
+++ b/arch/x86/cpu/qemu/qemu.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -19,45 +20,20 @@ static bool i440fx;
 #ifdef CONFIG_QFW
 
 /* on x86, the qfw registers are all IO ports */
-#define FW_CONTROL_PORT0x510
-#define FW_DATA_PORT   0x511
-#define FW_DMA_PORT_LOW0x514
-#define FW_DMA_PORT_HIGH   0x518
-
-static void qemu_x86_fwcfg_read_entry_pio(uint16_t entry,
-   uint32_t size, void *address)
-{
-   uint32_t i = 0;
-   uint8_t *data = address;
-
-   /*
-* writting FW_CFG_INVALID will cause read operation to resume at
-* last offset, otherwise read will start at offset 0
-*
-* Note: on platform where the control register is IO port, the
-* endianness is little endian.
-*/
-   if (entry != FW_CFG_INVALID)
-   outw(cpu_to_le16(entry), FW_CONTROL_PORT);
-
-   /* the endianness of data register is string-preserving */
-   while (size--)
-   data[i++] = inb(FW_DATA_PORT);
-}
-
-static void qemu_x86_fwcfg_read_entry_dma(struct fw_cfg_dma_access *dma)
-{
-   /* the DMA address register is big endian */
-   outl(cpu_to_be32((uintptr_t)dma), FW_DMA_PORT_HIGH);
-
-   while (be32_to_cpu(dma->control) & ~FW_CFG_DMA_ERROR)
-   __asm__ __volatile__ ("pause");
-}
+static const struct qfw_plat x86_qfw_plat = {
+   .io = {
+   .control_port   = 0x510,
+   .data_port  = 0x511,
+   .dma_port_low   = 0x514,
+   .dma_port_high  = 0x518,
+   },
+};
 
-static struct fw_cfg_arch_ops fwcfg_x86_ops = {
-   .arch_read_pio = qemu_x86_fwcfg_read_entry_pio,
-   .arch_read_dma = qemu_x86_fwcfg_read_entry_dma
+U_BOOT_DRVINFO(x86_qfw) = {
+   .name = "qfw",
+   .plat = _qfw_plat,
 };
+
 #endif
 
 static void enable_pm_piix(void)
@@ -132,10 +108,6 @@ static void qemu_chipset_init(void)
 
enable_pm_ich9();
}
-
-#ifdef CONFIG_QFW
-   qemu_fwcfg_init(_x86_ops);
-#endif
 }
 
 #if !CONFIG_IS_ENABLED(SPL_X86_32BIT_INIT)
diff --git a/arch/x86/cpu/qfw_cpu.c b/arch/x86/cpu/qfw_cpu.c
index b959eaddde..c8fb918494 100644
--- a/arch/x86/cpu/qfw_cpu.c
+++ b/arch/x86/cpu/qfw_cpu.c
@@ -18,7 +18,7 @@ int qemu_cpu_fixup(void)
int cpu_num;
int cpu_online;
struct uclass *uc;
-   struct udevice *dev, *pdev;
+   struct udevice *dev, *pdev, *qfwdev;
struct cpu_plat *plat;
char *cpu;
 
@@ -39,6 +39,13 @@ int qemu_cpu_fixup(void)
return -ENODEV;
}
 
+   /* get qfw dev */
+   qfwdev = qemu_fwcfg_dev();
+   if (!qfwdev) {
+   printf("unable to find qfw device\n");
+   return -ENODEV;
+   }
+
/* calculate cpus that are already bound */
cpu_num = 0;
for (uclass_find_first_device(UCLASS_CPU, );
@@ -48,7 +55,7 @@ int qemu_cpu_fixup(void)
}
 
/* get actual cpu number */
-   cpu_online = qemu_fwcfg_online_cpus();
+   cpu_online = qemu_fwcfg_online_cpus(qfwdev);
if (cpu_online < 0) {
printf("unable to get online cpu number: %d\n", cpu_online);