Re: [PATCH 1/3] MAINTAINERS: Add myself to maintainers and remove Havard

2023-02-06 Thread Havard Skinnemoen
On Mon, Feb 6, 2023 at 3:34 PM Hao Wu  wrote:
>
> Havard is no longer working on the Nuvoton systems for a while
> and won't be able to do any work on it in the future. So I'll
> take over maintaining the Nuvoton system from him.
>
> Signed-off-by: Hao Wu 

Acked-by: Havard Skinnemoen 

Just to confirm that I'm no longer on the team that does all the
exciting qemu work, but I love to see all the great work that the team
is doing.

Havard

> ---
>  MAINTAINERS | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index fa10ecaeb9..347936e41c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -799,8 +799,8 @@ F: include/hw/net/mv88w8618_eth.h
>  F: docs/system/arm/musicpal.rst
>
>  Nuvoton NPCM7xx
> -M: Havard Skinnemoen 
>  M: Tyrone Ting 
> +M: Hao Wu 
>  L: qemu-...@nongnu.org
>  S: Supported
>  F: hw/*/npcm7xx*
> --
> 2.39.1.519.gcb327c4b5f-goog
>



Re: [PATCH v2 03/13] hw/arm/npcm7xx_boards: Replace drive_get_next() by drive_get()

2021-11-17 Thread Havard Skinnemoen
On Wed, Nov 17, 2021 at 8:34 AM Markus Armbruster  wrote:
>
> drive_get_next() is basically a bad idea.  It returns the "next" block
> backend of a certain interface type.  "Next" means bus=0,unit=N, where
> subsequent calls count N up from zero, per interface type.
>
> This lets you define unit numbers implicitly by execution order.  If the
> order changes, or new calls appear "in the middle", unit numbers change.
> ABI break.  Hard to spot in review.
>
> Machine "quanta-gbs-bmc" connects just one backend with
> drive_get_next(), but with a helper function.  Change it to use
> drive_get() directly.  This makes the unit numbers explicit in the
> code.
>
> Cc: Havard Skinnemoen 
> Cc: Tyrone Ting 
> Cc: Peter Maydell 
> Cc: qemu-...@nongnu.org
> Signed-off-by: Markus Armbruster 
> ---
>  hw/arm/npcm7xx_boards.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
> index dec7d16ae5..d8a49e4e85 100644
> --- a/hw/arm/npcm7xx_boards.c
> +++ b/hw/arm/npcm7xx_boards.c
> @@ -84,9 +84,9 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, 
> MemoryRegion *dram)
>   _abort);
>  }
>
> -static void sdhci_attach_drive(SDHCIState *sdhci)
> +static void sdhci_attach_drive(SDHCIState *sdhci, int unit)
>  {
> -DriveInfo *di = drive_get_next(IF_SD);
> +DriveInfo *di = drive_get(IF_SD, 0, unit);

+Hao Wu IIRC the chip has separate SD and eMMC buses. Would it make
sense to take the bus number as a parameter as well? Is bus 0 the
right one to use in this case?

The existing code always uses bus 0, so this is an improvement either way.

Reviewed-by: Havard Skinnemoen 

>  BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
>
>  BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus");
> @@ -374,7 +374,7 @@ static void quanta_gbs_init(MachineState *machine)
>drive_get(IF_MTD, 0, 0));
>
>  quanta_gbs_i2c_init(soc);
> -sdhci_attach_drive(>mmc.sdhci);
> +sdhci_attach_drive(>mmc.sdhci, 0);
>  npcm7xx_load_kernel(machine, soc);
>  }
>
> --
> 2.31.1
>



Re: [PULL 16/21] hw/timer: Refactor NPCM7XX Timer to use CLK clock

2021-07-27 Thread Havard Skinnemoen
On Tue, Jul 27, 2021 at 7:19 AM Peter Maydell  wrote:
>
> On Thu, 4 Feb 2021 at 22:38, Hao Wu  wrote:
> >
> > I don't see this error. It could be some error in the clock that the timer 
> > module does not get a correct clock input.
> > How do you reproduce this?
> >
> > On Thu, Feb 4, 2021 at 1:39 AM Philippe Mathieu-Daudé  
> > wrote:
> >>
> >> Hi,
> >>
> >> On Tue, Jan 12, 2021 at 6:20 PM Peter Maydell 
> >> wrote:
> >> >
> >> > From: Hao Wu 
> >> >
> >> > This patch makes NPCM7XX Timer to use a the timer clock generated by the
> >> > CLK module instead of the magic number TIMER_REF_HZ.
> >> >
> >> > Reviewed-by: Havard Skinnemoen 
> >> > Reviewed-by: Tyrone Ting 
> >> > Signed-off-by: Hao Wu 
> >> > Message-id: 20210108190945.949196-3-wuhao...@google.com
> >> > Reviewed-by: Peter Maydell 
> >> > Signed-off-by: Peter Maydell 
> >> > ---
> >> >  include/hw/misc/npcm7xx_clk.h|  6 -
> >> >  include/hw/timer/npcm7xx_timer.h |  1 +
> >> >  hw/arm/npcm7xx.c |  5 
> >> >  hw/timer/npcm7xx_timer.c | 39 +++-
> >> >  4 files changed, 24 insertions(+), 27 deletions(-)
> >>
> >> Is that a spurious error (building with Clang)?
> >>
> >> Running test qtest-arm/npcm7xx_timer-test
> >> ERROR:../tests/qtest/npcm7xx_timer-test.c:475:test_periodic_interrupt:
> >> assertion failed (tim_read(td, TISR) == tim_timer_bit(td)): (0x
> >> == 0x0004)
> >> ERROR:../tests/qtest/npcm7xx_timer-test.c:476:test_periodic_interrupt:
> >> 'qtest_get_irq(global_qtest, tim_timer_irq(td))' should be TRUE
> >> FAIL 155 qtest-arm/npcm7xx_timer-test
> >> /arm/npcm7xx_timer/tim[2]/timer[2]/periodic_interrupt
> >> make: *** [Makefile.mtest:1033: run-test-127] Error 1
>
> This intermittent is still with us:
>
> /arm/npcm7xx_timer/tim[2]/timer[0]/periodic_interrupt: **
> ERROR:../../tests/qtest/npcm7xx_timer-test.c:475:test_periodic_interrupt:
> assertion failed (tim_read(td, TISR) == tim_timer_bit(td)):
> (0x == 0x0001)
> **
> ERROR:../../tests/qtest/npcm7xx_timer-test.c:476:test_periodic_interrupt:
> 'qtest_get_irq(global_qtest, tim_timer_irq(td))' should be TRUE
> FAIL

It looks like the interrupt fires consistently with the status bit. It
also only happens once during that loop of four timer periods (the
test calls g_test_set_nonfatal_assertions() so we would have seen more
failures reported if this wasn't the case).

I'm wondering if the clock_step_next() call is occasionally hitting a
different timer, causing it to return before it has advanced to the
next period of the timer module? If so, it might help to use
clock_step(tim_calculate_step(...)) like some of the other tests do.
This would also verify that the timer is actually firing at the right
interval.

Havard



Re: [PATCH] tests/qtest/npcm7xx_pwm-test.c: Avoid g_assert_true() for non-test assertions

2021-05-05 Thread Havard Skinnemoen
On Wed, May 5, 2021 at 6:55 AM Peter Maydell  wrote:
>
> In the glib API, the distinction between g_assert() and
> g_assert_true() is that the former is for "bug, terminate the
> application" and the latter is for "test check, on failure either
> terminate or just mark the testcase as failed".  For QEMU, g_assert()
> is always fatal, so code can assume that if the assertion fails
> execution does not proceed, but this is not true of g_assert_true().
>
> In npcm7xx_pwm-test, the pwm_index() and pwm_module_index() functions
> include some assertions that are just guarding against possible bugs
> in the test code that might lead us to out-of-bounds array accesses.
> These should use g_assert() because they aren't part of what the test
> is testing and the code does not correctly handle the case where the
> condition was false.
>
> This fixes some Coverity issues where Coverity knows that
> g_assert_true() can continue when the condition is false and
> complains about the possible array overrun at various callsites.
>
> Fixes: Coverity CID 1442340, 1442341, 1442343, 1442344, 1442345, 1442346
> Signed-off-by: Peter Maydell 

Reviewed-by: Havard Skinnemoen 



Re: [PATCH] qtest/npcm7xx_pwm-test: Fix memleak in pwm_qom_get

2021-01-15 Thread Havard Skinnemoen via
+Hao Wu

On Fri, Jan 15, 2021 at 1:15 AM Philippe Mathieu-Daudé  wrote:
>
> On 1/15/21 8:56 AM, Gan Qixin wrote:
> > The pwm_qom_get function didn't free "response", which caused an indirect
> > memory leak. So use qobject_unref() to fix it.
> >
> > ASAN shows memory leak stack:
> >
> > Indirect leak of 7416 byte(s) in 18000 object(s) allocated from:
> > #0 0x7f96e2f79d4e in __interceptor_calloc (/lib64/libasan.so.5+0x112d4e)
> > #1 0x7f96e2d98a50 in g_malloc0 (/lib64/libglib-2.0.so.0+0x55a50)
> > #2 0x556313112180 in qdict_new ../qobject/qdict.c:30
> > #3 0x556313115bca in parse_object ../qobject/json-parser.c:318
> > #4 0x556313117810 in parse_value ../qobject/json-parser.c:546
> > #5 0x556313117bda in json_parser_parse ../qobject/json-parser.c:580
> > #6 0x55631310fe67 in json_message_process_token 
> > ../qobject/json-streamer.c:92
> > #7 0x5563131210b7 in json_lexer_feed_char ../qobject/json-lexer.c:313
> > #8 0x556313121662 in json_lexer_feed ../qobject/json-lexer.c:350
> > #9 0x5563131101e9 in json_message_parser_feed 
> > ../qobject/json-streamer.c:121
> > #10 0x5563130cb81e in qmp_fd_receive ../tests/qtest/libqtest.c:614
> > #11 0x5563130cba2b in qtest_qmp_receive_dict 
> > ../tests/qtest/libqtest.c:636
> > #12 0x5563130cb939 in qtest_qmp_receive ../tests/qtest/libqtest.c:624
> > #13 0x5563130cbe0d in qtest_vqmp ../tests/qtest/libqtest.c:715
> > #14 0x5563130cc40f in qtest_qmp ../tests/qtest/libqtest.c:756
> > #15 0x5563130c5623 in pwm_qom_get ../tests/qtest/npcm7xx_pwm-test.c:180
> > #16 0x5563130c595e in pwm_get_duty ../tests/qtest/npcm7xx_pwm-test.c:210
> > #17 0x5563130c7529 in test_toggle ../tests/qtest/npcm7xx_pwm-test.c:447
> >
> > Reported-by: Euler Robot 
> > Signed-off-by: Gan Qixin 
> > ---
> > Cc: Havard Skinnemoen 
> > Cc: Tyrone Ting 
> > Cc: Thomas Huth 
> > Cc: Laurent Vivier 
> > ---
> >  tests/qtest/npcm7xx_pwm-test.c | 5 -
> >  1 file changed, 4 insertions(+), 1 deletion(-)
>
> Reviewed-by: Philippe Mathieu-Daudé 

Reviewed-by: Havard Skinnemoen 

Thanks!



Re: [PATCH 0/9] hw/block: m25p80: Fix the mess of dummy bytes needed for fast read commands

2021-01-14 Thread Havard Skinnemoen via
Hi Bin,

On Thu, Jan 14, 2021 at 6:08 PM Bin Meng  wrote:
>
> Hi Francisco,
>
> On Fri, Jan 15, 2021 at 2:13 AM Francisco Iglesias
>  wrote:
> >
> > Hi Bin,
> >
> > On [2021 Jan 14] Thu 23:08:53, Bin Meng wrote:
> > > From: Bin Meng 
> > >
> > > The m25p80 model uses s->needed_bytes to indicate how many follow-up
> > > bytes are expected to be received after it receives a command. For
> > > example, depending on the address mode, either 3-byte address or
> > > 4-byte address is needed.
> > >
> > > For fast read family commands, some dummy cycles are required after
> > > sending the address bytes, and the dummy cycles need to be counted
> > > in s->needed_bytes. This is where the mess began.
> > >
> > > As the variable name (needed_bytes) indicates, the unit is in byte.
> > > It is not in bit, or cycle. However for some reason the model has
> > > been using the number of dummy cycles for s->needed_bytes. The right
> > > approach is to convert the number of dummy cycles to bytes based on
> > > the SPI protocol, for example, 6 dummy cycles for the Fast Read Quad
> > > I/O (EBh) should be converted to 3 bytes per the formula (6 * 4 / 8).
> >
> > While not being the original implementor I must assume that above solution 
> > was
> > considered but not chosen by the developers due to it is inaccuracy (it
> > wouldn't be possible to model exacly 6 dummy cycles, only a multiple of 8,
> > meaning that if the controller is wrongly programmed to generate 7 the error
> > wouldn't be caught and the controller will still be considered "correct"). 
> > Now
> > that we have this detail in the implementation I'm in favor of keeping it, 
> > this
> > also because the detail is already in use for catching exactly above error.
> >
>
> I found no clue from the commit message that my proposed solution here
> was ever considered, otherwise all SPI controller models supporting
> software generation should have been found out seriously broken long
> time ago!
>
> The issue you pointed out that we require the total number of dummy
> bits should be multiple of 8 is true, that's why I added the
> unimplemented log message in this series (patch 2/3/4) to warn users
> if this expectation is not met. However this will not cause any issue
> when running U-Boot or Linux, because both spi-nor drivers expect the
> same assumption as we do here.
>
> See U-Boot spi_nor_read_data() and Linux spi_nor_spimem_read_data(),
> there is a logic to calculate the dummy bytes needed for fast read
> command:
>
> /* convert the dummy cycles to the number of bytes */
> op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
>
> Note the default dummy cycles configuration for all flashes I have
> looked into as of today, meets the multiple of 8 assumption. On some
> flashes the dummy cycle number is configurable, and if it's been
> configured to be an odd value, it would not work on U-Boot/Linux in
> the first place.
>
> > >
> > > Things get complicated when interacting with different SPI or QSPI
> > > flash controllers. There are major two cases:
> > >
> > > - Dummy bytes prepared by drivers, and wrote to the controller fifo.
> > >   For such case, driver will calculate the correct number of dummy
> > >   bytes and write them into the tx fifo. Fixing the m25p80 model will
> > >   fix flashes working with such controllers.
> >
> > Above can be fixed while still keeping the detailed dummy cycle 
> > implementation
> > inside m25p80. Perhaps one of the following could be looked into: 
> > configurating
> > the amount, letting the spi ctrl fetch the amount from m25p80 or by 
> > inheriting
> > some functionality handling this in the SPI controller. Or a mixture of 
> > above.
>
> Please send patches to explain this in detail how this is going to
> work. I am open to all possible solutions.
>
> >
> > > - Dummy bytes not prepared by drivers. Drivers just tell the hardware
> > >   the dummy cycle configuration via some registers, and hardware will
> > >   automatically generate dummy cycles for us. Fixing the m25p80 model
> > >   is not enough, and we will need to fix the SPI/QSPI models for such
> > >   controllers.
> > >
> > > This series fixes the mess in the m25p80 from the flash side first,
> >
> > Considering the problems solved by the solution in tree I find m25p80 pretty
> > clean, at least I don't see any clearly better way for accurately modeling 
> > the
> > dummy clock cycles. Counting bits instead of bytes would for example still
> > force the controllers to mark which bits to count (when transmitting one 
> > dummy
> > byte from a txfifo on four lines (Quad command) it generates 2 dummy clock
> > cycles since it takes two cycles to transfer 8 bits).
> >
>
> SPI is a bit based protocol, not bytes. If you insist on bit modeling
> with the dummy cycles then you should also suggest we change all
> cycles (including command/addr/dummy/data phases) to be modeled with
> bits. That way we can accurately emulate everything, for example one
> 

Re: [PATCH 9/9] hw/ssi: npcm7xx_fiu: Correct the dummy cycle emulation logic

2021-01-14 Thread Havard Skinnemoen via
On Thu, Jan 14, 2021 at 7:10 AM Bin Meng  wrote:
>
> From: Bin Meng 
>
> I believe send_dummy_bits() should also be fixed, but I really don't
> know how based on my pure read/guess of the codes since there is no
> public datasheet available for this NPCM7xx SoC.
>
> Signed-off-by: Bin Meng 

Just a quick comment before I look at the rest of the patch series:
The emulated dummy bits behavior has a lot more to do with what the
m25p80 emulator seemed to expect than the actual NPCM7xx behavior. If
the m25p behavior now interprets the dummy cycles the same way as the
rest of the cycles, this change seems correct, but you're right that
send_dummy_bits probably needs some attention as well.

I _think_ it's just a matter of turning this:

for (j = 0; j < 8; j += bits_per_clock) {
ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock));
}

into this:

ssi_transfer(spi, extract32(uma_cmd, field, BITS_PER_BYTE));

which might have the very nice side effect of speeding up SPI flash
access quite a bit.

Thanks a lot for looking into this.

>
> ---
>
>  hw/ssi/npcm7xx_fiu.c | 8 +++-
>  1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
> index 5040132b07..e76fb5ad9f 100644
> --- a/hw/ssi/npcm7xx_fiu.c
> +++ b/hw/ssi/npcm7xx_fiu.c
> @@ -150,7 +150,7 @@ static uint64_t npcm7xx_fiu_flash_read(void *opaque, 
> hwaddr addr,
>  NPCM7xxFIUState *fiu = f->fiu;
>  uint64_t value = 0;
>  uint32_t drd_cfg;
> -int dummy_cycles;
> +int dummy_bytes;
>  int i;
>
>  if (fiu->active_cs != -1) {
> @@ -180,10 +180,8 @@ static uint64_t npcm7xx_fiu_flash_read(void *opaque, 
> hwaddr addr,
>  break;
>  }
>
> -/* Flash chip model expects one transfer per dummy bit, not byte */
> -dummy_cycles =
> -(FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg);
> -for (i = 0; i < dummy_cycles; i++) {
> +dummy_bytes = FIU_DRD_CFG_DBW(drd_cfg) >> FIU_DRD_CFG_ACCTYPE(drd_cfg);
> +for (i = 0; i < dummy_bytes; i++) {
>  ssi_transfer(fiu->spi, 0);
>  }
>
> --
> 2.25.1
>



Re: [PATCH 0/7] Additional NPCM7xx devices and IPMI BMC emulation support

2020-12-11 Thread Havard Skinnemoen via
On Fri, Dec 11, 2020 at 4:16 PM Corey Minyard  wrote:

> On Fri, Dec 11, 2020 at 12:56:07PM -0800, Hao Wu wrote:
> > Tl,dr: We'll remove the IPMI changes from the current patch set and
> > refactor
> >   them in a separate patch set.
> >
> > Thank you for your review! On high level, we are trying to emulate the
> BMC
> > side of the IPMI protocol. So we cannot directly use the existing IPMI
> code.
> > However, they do have a lot in duplication as you pointed out. So we'll
> > refactor
> > the existing IPMI code and update in a way that we only add the required
> > functionality.
>
> Ah, I didn't figure that out from what you posted.  So the idea is you
> can create the BMC side of the system in one qemu session with your
> changes and then you connect it to a host system running qemu with the
> host side of the interface.
>
> The wire protocol is basically symmetric, but the command handling will
> need to be separate.  So you probably want to split out the base
> protocol from ipmi_bmc_extern into its own file and use that from your
> own file, to avoid the duplication.
>
> You need to do proper ATTN handling on the BMC side.  And you will also
> need ties into GPIOs and whatnot for doing the reset, NMI, etc.
>
> "ipmi_host" is probably not the best name.  At least to me that implied
> the host side of the interface.  I'm not coming up with something I
> really like, though.  Maybe "bmc_host"?  That's more descriptive, though
> I'm sure a better name exists.  Then you could have "bmc_host_extern"
> for the protocol.  If you come up with a better naming scheme, the
> existing files can be renamed, too.
>

The naming is my fault.

My thinking was that ipmi-host-extern is to the BMC what ipmi-bmc-extern is
to the host. That is, the former represents the host as seen by the BMC,
and the latter represents the BMC as seen by the host.

I sent some docs to the list earlier this year, but sadly, I never got
around to follow up. You can see the generated docs here:

https://hskinnemoen.github.io/qemu/specs/ipmi.html

Hao, perhaps you should include my documentation patches in your next IPMI
series? If we come up with a better naming scheme for both sides, I can
update the docs accordingly.

Havard


> Thanks,
>
> -corey
>
> >
> > As for the KCS module, the BMC side of the protocol is the opposite
> > direction
> > of the existing ipmi_kcs.c code which is on the host/CPU side. For
> example,
> > in READ_STATE the CPU would read data while the BMC would write data.
> > So we can't directly use the same implementation. (They're different
> files
> > in
> > Linux either.) However, we can refactor it to re-use some of the common
> > definitions.
> >
> > We would like to remove the IPMI and KCS stuff from the current patch
> set.
> > We'll send the refactored code in a separate patch set after addressing
> > your concerns.
> >
> > Thanks again for the review!
> >
> > On Thu, Dec 10, 2020 at 7:04 PM Corey Minyard  wrote:
> >
> > > On Thu, Dec 10, 2020 at 05:51:49PM -0800, Hao Wu wrote:
> > > > This patch series include a few more NPCM7XX devices including
> > > >
> > > > - Analog Digital Converter (ADC)
> > > > - Pulse Width Modulation (PWM)
> > > > - Keyboard Style Controller (KSC)
> > > >
> > > > To utilize these modules we also add two extra functionalities:
> > > >
> > > > 1. We modified the CLK module to generate clock values using
> qdev_clock.
> > > >These clocks are used to determine various clocks in NPCM7XX
> devices.
> > > > 2. We added support for emulating IPMI responder devices in BMC
> machines,
> > > >similar to the existing IPMI device support for CPU emulation.
> This
> > > allows
> > > >a qemu instance running BMC firmware to serve as an external BMC
> for
> > > a qemu
> > > >instance running server software. It utilizes the KCS module we
> > > implemented.
> > >
> > > Looking at the IPMI changes, why didn't you just re-use the existing
> > > IPMI infrastructure?  ipmi_host.[ch] is basically a subset of
> ipmi.[ch],
> > > and the ipmi_host_extern looks like a copy of of ipmi_bmc_extern with
> > > some names changed.  That kind of code duplication is not acceptable.
> > > Plus you copied my code and removed my copyrights, which is really
> > > not acceptable and illegal.
> > >
> > > I'm not exactly sure why you needed you own KCS interface, either.  It
> > > looks like the interface is somewhat different in some ways, but
> > > integrating it into the current KCS code is probably a better choice if
> > > that can be done.
> > >
> > > -corey
> > >
> > > >
> > > > Hao Wu (7):
> > > >   hw/misc: Add clock converter in NPCM7XX CLK module
> > > >   hw/timer: Refactor NPCM7XX Timer to use CLK clock
> > > >   hw/adc: Add an ADC module for NPCM7XX
> > > >   hw/misc: Add a PWM module for NPCM7XX
> > > >   hw/ipmi: Add an IPMI host interface
> > > >   hw/ipmi: Add a KCS Module for NPCM7XX
> > > >   hw/ipmi: Add an IPMI external host device
> > > >
> > > >  

Re: [PATCH-for-5.2? 1/2] tests/qtest: variable defined by g_autofree need to be initialized

2020-11-18 Thread Havard Skinnemoen
On Wed, Nov 18, 2020 at 3:57 AM Chen Qun  wrote:
>
> According to the glib function requirements, we need initialise
>  the variable. Otherwise there will be compilation warnings:
>
> glib-autocleanups.h:28:3: warning: ‘full_name’ may be
> used uninitialized in this function [-Wmaybe-uninitialized]
>28 |   g_free (*pp);
>   |   ^~~~
>
> Reported-by: Euler Robot 
> Signed-off-by: Chen Qun 

Reviewed-by: Havard Skinnemoen 

I'd be totally fine with Philippe's suggestion too.

Thanks!

> ---
>  tests/qtest/npcm7xx_timer-test.c | 8 +++-
>  1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/tests/qtest/npcm7xx_timer-test.c 
> b/tests/qtest/npcm7xx_timer-test.c
> index f08b0cd62a..83774a5b90 100644
> --- a/tests/qtest/npcm7xx_timer-test.c
> +++ b/tests/qtest/npcm7xx_timer-test.c
> @@ -512,11 +512,9 @@ static void test_disable_on_expiration(gconstpointer 
> test_data)
>   */
>  static void tim_add_test(const char *name, const TestData *td, GTestDataFunc 
> fn)
>  {
> -g_autofree char *full_name;
> -
> -full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
> -tim_index(td->tim), timer_index(td->timer),
> -name);
> +g_autofree char *full_name = g_strdup_printf(
> +"npcm7xx_timer/tim[%d]/timer[%d]/%s", tim_index(td->tim),
> +timer_index(td->timer), name);
>  qtest_add_data_func(full_name, td, fn);
>  }
>
> --
> 2.23.0
>



Re: [PATCH-for-5.2? 2/2] tests/qtest: fix memleak in npcm7xx_watchdog_timer-test

2020-11-18 Thread Havard Skinnemoen
On Wed, Nov 18, 2020 at 3:57 AM Chen Qun  wrote:
>
> Properly free resp for get_watchdog_action() to avoid memory leak.
> ASAN shows memory leak stack:
>
> Indirect leak of 12360 byte(s) in 3 object(s) allocated from:
> #0 0x7f41ab6cbd4e in __interceptor_calloc (/lib64/libasan.so.5+0x112d4e)
> #1 0x7f41ab4eaa50 in g_malloc0 (/lib64/libglib-2.0.so.0+0x55a50)
> #2 0x556487d5374b in qdict_new ../qobject/qdict.c:29
> #3 0x556487d65e1a in parse_object ../qobject/json-parser.c:318
> #4 0x556487d65cb6 in parse_pair ../qobject/json-parser.c:287
> #5 0x556487d65ebd in parse_object ../qobject/json-parser.c:343
> #6 0x556487d661d5 in json_parser_parse ../qobject/json-parser.c:580
> #7 0x556487d513df in json_message_process_token 
> ../qobject/json-streamer.c:92
> #8 0x556487d63919 in json_lexer_feed_char ../qobject/json-lexer.c:313
> #9 0x556487d63d75 in json_lexer_feed ../qobject/json-lexer.c:350
> #10 0x556487d28b2a in qmp_fd_receive ../tests/qtest/libqtest.c:613
> #11 0x556487d2a16f in qtest_qmp_eventwait_ref 
> ../tests/qtest/libqtest.c:827
> #12 0x556487d248e2 in get_watchdog_action 
> ../tests/qtest/npcm7xx_watchdog_timer-test.c:94
> #13 0x556487d25765 in test_enabling_flags 
> ../tests/qtest/npcm7xx_watchdog_timer-test.c:243
>
> Reported-by: Euler Robot 
> Signed-off-by: Chen Qun 

Reviewed-by: Havard Skinnemoen 

> ---
>  tests/qtest/npcm7xx_watchdog_timer-test.c | 6 --
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/tests/qtest/npcm7xx_watchdog_timer-test.c 
> b/tests/qtest/npcm7xx_watchdog_timer-test.c
> index 54d5d6d8f2..3aae5a0438 100644
> --- a/tests/qtest/npcm7xx_watchdog_timer-test.c
> +++ b/tests/qtest/npcm7xx_watchdog_timer-test.c
> @@ -204,6 +204,7 @@ static void test_enabling_flags(gconstpointer watchdog)
>  {
>  const Watchdog *wd = watchdog;
>  QTestState *qts;
> +QDict *rsp;
>
>  /* Neither WTIE or WTRE is set, no interrupt or reset should happen */
>  qts = qtest_init("-machine quanta-gsj");
> @@ -240,8 +241,9 @@ static void test_enabling_flags(gconstpointer watchdog)
>  g_assert_false(qtest_get_irq(qts, wd->irq));
>  qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
>  watchdog_prescaler(qts, wd)));
> -g_assert_false(strcmp(qdict_get_str(get_watchdog_action(qts), "action"),
> -"reset"));
> +rsp = get_watchdog_action(qts);
> +g_assert_false(strcmp(qdict_get_str(rsp, "action"), "reset"));
> +qobject_unref(rsp);
>  qtest_qmp_eventwait(qts, "RESET");
>  qtest_quit(qts);
>
> --
> 2.23.0
>



[PATCH 3/3] tests/qtest/npcm7xx_rng-test: dump random data on failure

2020-11-02 Thread Havard Skinnemoen via
Dump the collected random data after a randomness test failure.

Note that you won't actually see this unless you add
g_test_set_nonfatal_assertions() back in.

Signed-off-by: Havard Skinnemoen 
---
 tests/qtest/npcm7xx_rng-test.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
index d7e42cf062..09111d640c 100644
--- a/tests/qtest/npcm7xx_rng-test.c
+++ b/tests/qtest/npcm7xx_rng-test.c
@@ -20,6 +20,7 @@
 
 #include "libqtest-single.h"
 #include "qemu/bitops.h"
+#include "qemu-common.h"
 
 #define RNG_BASE_ADDR   0xf000b000
 
@@ -36,6 +37,13 @@
 /* Number of bits to collect for randomness tests. */
 #define TEST_INPUT_BITS  (128)
 
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
+{
+if (g_test_failed()) {
+qemu_hexdump(stderr, "", buf, size);
+}
+}
+
 static void rng_writeb(unsigned int offset, uint8_t value)
 {
 writeb(RNG_BASE_ADDR + offset, value);
@@ -188,6 +196,7 @@ static void test_continuous_monobit(void)
 }
 
 g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
+dump_buf_if_failed(buf, sizeof(buf));
 }
 
 /*
@@ -209,6 +218,7 @@ static void test_continuous_runs(void)
 }
 
 g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 
0.01);
+dump_buf_if_failed(buf.c, sizeof(buf));
 }
 
 /*
@@ -230,6 +240,7 @@ static void test_first_byte_monobit(void)
 }
 
 g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
+dump_buf_if_failed(buf, sizeof(buf));
 }
 
 /*
@@ -254,6 +265,7 @@ static void test_first_byte_runs(void)
 }
 
 g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 
0.01);
+dump_buf_if_failed(buf.c, sizeof(buf));
 }
 
 int main(int argc, char **argv)
-- 
2.29.1.341.ge80a0c044ae-goog




[PATCH 2/3] tests/qtest/npcm7xx: Don't call g_test_set_nonfatal_assertions

2020-11-02 Thread Havard Skinnemoen via
Even though g_test_set_nonfatal_assertions() makes test failure
reporting a lot better, no other tests currently do this so we'll turn
it off as well.

Signed-off-by: Havard Skinnemoen 
---
 tests/qtest/npcm7xx_gpio-test.c   | 1 -
 tests/qtest/npcm7xx_rng-test.c| 1 -
 tests/qtest/npcm7xx_timer-test.c  | 1 -
 tests/qtest/npcm7xx_watchdog_timer-test.c | 1 -
 4 files changed, 4 deletions(-)

diff --git a/tests/qtest/npcm7xx_gpio-test.c b/tests/qtest/npcm7xx_gpio-test.c
index 1004cef812..3af49173a7 100644
--- a/tests/qtest/npcm7xx_gpio-test.c
+++ b/tests/qtest/npcm7xx_gpio-test.c
@@ -357,7 +357,6 @@ int main(int argc, char **argv)
 int i;
 
 g_test_init(, , NULL);
-g_test_set_nonfatal_assertions();
 
 qtest_add_func("/npcm7xx_gpio/dout_to_din", test_dout_to_din);
 qtest_add_func("/npcm7xx_gpio/pullup_pulldown", test_pullup_pulldown);
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
index 57787c5ffc..d7e42cf062 100644
--- a/tests/qtest/npcm7xx_rng-test.c
+++ b/tests/qtest/npcm7xx_rng-test.c
@@ -261,7 +261,6 @@ int main(int argc, char **argv)
 int ret;
 
 g_test_init(, , NULL);
-g_test_set_nonfatal_assertions();
 
 qtest_add_func("npcm7xx_rng/enable_disable", test_enable_disable);
 qtest_add_func("npcm7xx_rng/rosel", test_rosel);
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
index f08b0cd62a..77e6e0d472 100644
--- a/tests/qtest/npcm7xx_timer-test.c
+++ b/tests/qtest/npcm7xx_timer-test.c
@@ -530,7 +530,6 @@ int main(int argc, char **argv)
 int i, j;
 
 g_test_init(, , NULL);
-g_test_set_nonfatal_assertions();
 
 for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
 for (j = 0; j < ARRAY_SIZE(timer); j++) {
diff --git a/tests/qtest/npcm7xx_watchdog_timer-test.c 
b/tests/qtest/npcm7xx_watchdog_timer-test.c
index 54d5d6d8f2..426303ecfa 100644
--- a/tests/qtest/npcm7xx_watchdog_timer-test.c
+++ b/tests/qtest/npcm7xx_watchdog_timer-test.c
@@ -303,7 +303,6 @@ static void watchdog_add_test(const char *name, const 
Watchdog* wd,
 int main(int argc, char **argv)
 {
 g_test_init(, , NULL);
-g_test_set_nonfatal_assertions();
 
 for (int i = 0; i < ARRAY_SIZE(watchdog_list); ++i) {
 const Watchdog *wd = _list[i];
-- 
2.29.1.341.ge80a0c044ae-goog




[PATCH 0/3] tests/qtest: npcm7xx test fixes

2020-11-02 Thread Havard Skinnemoen via
This series contains a fix for the randomness calculation in npcm7xx_rng-test.
It also makes test failures fatal. The last patch would have dumped the random
data to stderr if the randomness test fails, except now that failures are
fatal, it never actually gets a chance to do that.

It may not make sense to apply all three, but I'd definitely take (1), and I'll
leave it up to you whether to apply (2), (3) or both.

Havard Skinnemoen (3):
  tests/qtest/npcm7xx_rng-test: count runs properly
  tests/qtest/npcm7xx: Don't call g_test_set_nonfatal_assertions
  tests/qtest/npcm7xx_rng-test: dump random data on failure

 tests/qtest/npcm7xx_gpio-test.c   |  1 -
 tests/qtest/npcm7xx_rng-test.c| 15 +--
 tests/qtest/npcm7xx_timer-test.c  |  1 -
 tests/qtest/npcm7xx_watchdog_timer-test.c |  1 -
 4 files changed, 13 insertions(+), 5 deletions(-)

-- 
2.29.1.341.ge80a0c044ae-goog




[PATCH 1/3] tests/qtest/npcm7xx_rng-test: count runs properly

2020-11-02 Thread Havard Skinnemoen via
The number of runs is equal to the number of 0-1 and 1-0 transitions,
plus one. Currently, it's counting the number of times these transitions
do _not_ happen, plus one.

Source:
https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-22r1a.pdf
section 2.3.4 point (3).

Signed-off-by: Havard Skinnemoen 
---
 tests/qtest/npcm7xx_rng-test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
index da6e639bf6..57787c5ffc 100644
--- a/tests/qtest/npcm7xx_rng-test.c
+++ b/tests/qtest/npcm7xx_rng-test.c
@@ -126,7 +126,7 @@ static double calc_runs_p(const unsigned long *buf, 
unsigned int nr_bits)
 pi = (double)nr_ones / nr_bits;
 
 for (k = 0; k < nr_bits - 1; k++) {
-vn_obs += !(test_bit(k, buf) ^ test_bit(k + 1, buf));
+vn_obs += (test_bit(k, buf) ^ test_bit(k + 1, buf));
 }
 vn_obs += 1;
 
-- 
2.29.1.341.ge80a0c044ae-goog




Re: [PATCH v3 4/6] hw/misc: Add npcm7xx random number generator

2020-11-02 Thread Havard Skinnemoen
On Mon, Nov 2, 2020 at 9:14 AM Peter Maydell  wrote:
>
> On Mon, 2 Nov 2020 at 16:50, Havard Skinnemoen  wrote:
> > But none of this is really specific to the RNG test, so I can remove
> > it if you prefer for consistency.
>
> I would prefer us to be consistent. If you want to propose
> don't-stop-on-asserts then we should set that consistently
> at some higher level of the test suite, not in every
> individual test.

OK, I will remove g_test_set_nonfatal_assertions from all the tests
I've submitted.

As for the randomness failures, I did find a bug in the runs test, but
fixing it doesn't make much of an impact on the flakiness.

I've seen failures from both monobit and runs, both first_bit and
continuous. So it doesn't look like there's a systemic problem
anywhere.

I dumped the random data on failure and put it through the
https://github.com/Honno/coinflip/ implementation of monobit and runs,
and after fixing the runs bug, they consistently produce the same P
value. Here's one example that failed the qtest with P=0.000180106965:

$ ./randomness_test.py e1 ec cc 55  29 5d c9 ac  85 45 ed 4b  b6 96 56 ab
Monobit test:
normalised diff  0.53
p-value  0.596
┌───┬───┐
│ value │ count │
├───┼───┤
│ 1 │67 │
│ 0 │61 │
└───┴───┘

Runs test:
no. of runs  85
p-value   0.0

You can find the script at
https://gist.github.com/hskinnemoen/41f7513ca228c2bac959c3b14e87025f

Apparently, successive bits are toggling too often, producing too many
runs of 1s or 0s. This will of course happen from time to time since
the input is random. And the monobit test will fail if there are too
many or too few 1s compared to zeroes, which is also something that
can't really be prevented.

While we can always tune this to happen less often, e.g. by dropping
the P-value threshold or running the tests multiple times, we can
never guarantee that a randomness test won't fail. So I suspect we
should keep these tests disabled by default, but keep them available
so that we can easily do a randomness test if there's any suspicion
that the emulated RNG device produces bad data. Does that make sense?

Havard



Re: [PATCH v3 4/6] hw/misc: Add npcm7xx random number generator

2020-11-02 Thread Havard Skinnemoen
On Mon, Nov 2, 2020 at 3:36 AM Peter Maydell  wrote:
>
> On Fri, 23 Oct 2020 at 22:06, Havard Skinnemoen  
> wrote:
> >
> > The RNG module returns a byte of randomness when the Data Valid bit is
> > set.
> >
> > This implementation ignores the prescaler setting, and loads a new value
> > into RNGD every time RNGCS is read while the RNG is enabled and random
> > data is available.
> >
> > A qtest featuring some simple randomness tests is included.
>
> > +int main(int argc, char **argv)
> > +{
> > +int ret;
> > +
> > +g_test_init(, , NULL);
> > +g_test_set_nonfatal_assertions();
>
> While I was looking at this test case I noticed that it
> calls g_test_set_nonfatal_assertions(). Why does it do that?
> In our entire set of tests, only the npcm7xx test cases call
> that function, and they don't explain why they're a special
> case that needs to do so.

It's often useful to see more than the first failure when debugging
tests. Using the randomness flakiness as an example, it's very useful
to know if more than just one of the randomness tests fail. If I
remove g_test_set_nonfatal_assertions, I get:

**
ERROR:../../../tests/qtest/npcm7xx_rng-test.c:256:test_first_byte_runs:
assertion failed (calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE) >
0.01): (0.00204666737 > 0.01)
Bail out! 
ERROR:../../../tests/qtest/npcm7xx_rng-test.c:256:test_first_byte_runs:
assertion failed (calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE) >
0.01): (0.00204666737 > 0.01)
Aborted

which doesn't even tell me the name of the test that failed, let alone
anything about whether any subsequent tests passed.

Also note that it doesn't provide a clear "not ok" signal, which makes
life difficult for any downstream processing of the TAP output. It
looks like the test unexpectedly crashed.

Compare this to the output with g_test_set_nonfatal_assertions:

**
ERROR:../../../tests/qtest/npcm7xx_rng-test.c:232:test_first_byte_monobit:
assertion failed (calc_monobit_p(buf, sizeof(buf)) > 0.01):
(4.78548397e-05 > 0.01)
# ERROR:../../../tests/qtest/npcm7xx_rng-test.c:232:test_first_byte_monobit:
assertion failed (calc_monobit_p(buf, sizeof(buf)) > 0.01):
(4.78548397e-05 > 0.01)
not ok 5 /arm/npcm7xx_rng/first_byte/monobit
ok 6 /arm/npcm7xx_rng/first_byte/runs

which clearly shows that the "first_byte/monobit" test failed, and the
subsequent "first_byte/runs" test passed.

But none of this is really specific to the RNG test, so I can remove
it if you prefer for consistency.

Havard



Re: [PATCH] tests/qtest/npcm7xx_rng-test: Disable randomness tests

2020-11-02 Thread Havard Skinnemoen
On Mon, Nov 2, 2020 at 7:24 AM Peter Maydell  wrote:
>
> The randomness tests in the NPCM7xx RNG test fail intermittently
> but fairly frequently. On my machine running the test in a loop:
>  while QTEST_QEMU_BINARY=./qemu-system-aarch64 
> ./tests/qtest/npcm7xx_rng-test; do true; done
>
> will fail in less than a minute with an error like:
> ERROR:../../tests/qtest/npcm7xx_rng-test.c:256:test_first_byte_runs:
> assertion failed (calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE) > 0.01): 
> (0.00286205989 > 0.01)
>
> (Failures have been observed on all 4 of the randomness tests,
> not just first_byte_runs.)
>
> It's not clear why these tests are failing like this, but intermittent
> failures make CI and merge testing awkward, so disable running them
> unless a developer specifically sets QEMU_TEST_FLAKY_RNG_TESTS when
> running the test suite, until we work out the cause.
>
> Signed-off-by: Peter Maydell 
> ---
>  tests/qtest/npcm7xx_rng-test.c | 14 ++
>  1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
> index da6e639bf6f..e7cde85fbbc 100644
> --- a/tests/qtest/npcm7xx_rng-test.c
> +++ b/tests/qtest/npcm7xx_rng-test.c
> @@ -265,10 +265,16 @@ int main(int argc, char **argv)
>
>  qtest_add_func("npcm7xx_rng/enable_disable", test_enable_disable);
>  qtest_add_func("npcm7xx_rng/rosel", test_rosel);
> -qtest_add_func("npcm7xx_rng/continuous/monobit", 
> test_continuous_monobit);
> -qtest_add_func("npcm7xx_rng/continuous/runs", test_continuous_runs);
> -qtest_add_func("npcm7xx_rng/first_byte/monobit", 
> test_first_byte_monobit);
> -qtest_add_func("npcm7xx_rng/first_byte/runs", test_first_byte_runs);
> +/*
> + * These tests fail intermittently; only run them on explicit
> + * request until we figure out why.
> + */
> +if (getenv("QEMU_TEST_FLAKY_RNG_TESTS")) {
> +qtest_add_func("npcm7xx_rng/continuous/monobit", 
> test_continuous_monobit);
> +qtest_add_func("npcm7xx_rng/continuous/runs", test_continuous_runs);
> +qtest_add_func("npcm7xx_rng/first_byte/monobit", 
> test_first_byte_monobit);
> +qtest_add_func("npcm7xx_rng/first_byte/runs", test_first_byte_runs);
> +}

Reviewed-by: Havard Skinnemoen 

Thanks!

>  qtest_start("-machine npcm750-evb");
>  ret = g_test_run();
> --
> 2.20.1
>



Re: [PATCH v3 4/6] hw/misc: Add npcm7xx random number generator

2020-10-30 Thread Havard Skinnemoen
On Fri, Oct 30, 2020 at 6:34 AM Peter Maydell  wrote:
>
> On Fri, 23 Oct 2020 at 22:06, Havard Skinnemoen  
> wrote:
> >
> > The RNG module returns a byte of randomness when the Data Valid bit is
> > set.
> >
> > This implementation ignores the prescaler setting, and loads a new value
> > into RNGD every time RNGCS is read while the RNG is enabled and random
> > data is available.
> >
> > A qtest featuring some simple randomness tests is included.
> >
> > Reviewed-by: Tyrone Ting 
> > Reviewed-by: Peter Maydell 
> > Signed-off-by: Havard Skinnemoen 
>
> I've just seen some intermittent failures on the rng tests
> in this patch:
>
> PASS 1 qtest-arm/npcm7xx_rng-test /arm/npcm7xx_rng/enable_disable
> PASS 2 qtest-arm/npcm7xx_rng-test /arm/npcm7xx_rng/rosel
> **
> ERROR:../../tests/qtest/npcm7xx_rng-test.c:190:test_continuous_monobit:
> assertion failed (calc_monobit_p(buf, sizeof(buf)) > 0.01):
> (0.00800994233 > 0.01)
>
> (on OSX)
>
> and (on x86-64 Linux):
>
> MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}
> QTEST_QEMU_IMG=./qemu-img G_TEST_DBUS_DAEMON=/home/petmay01/li
> naro/qemu-for-merges/tests/dbus-vmstate-daemon.sh
> QTEST_QEMU_BINARY=./qemu-system-arm tests/qtest/npcm7xx_rng-test --tap
> -k
> PASS 1 qtest-arm/npcm7xx_rng-test /arm/npcm7xx_rng/enable_disable
> PASS 2 qtest-arm/npcm7xx_rng-test /arm/npcm7xx_rng/rosel
> PASS 3 qtest-arm/npcm7xx_rng-test /arm/npcm7xx_rng/continuous/monobit
> **
> ERROR:../../tests/qtest/npcm7xx_rng-test.c:211:test_continuous_runs:
> assertion failed (calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE) >
> 0.01): (0.00198053202 > 0.01)
>
>
> Are these just "we got a bit unlucky in the values we got from
> the RNG" ?

Yes, it looks like the randomness is a little low.

> If so, we probably need to disable these tests from the set
> that we run in "make check" -- we can't really have "there's
> a non-zero chance that the test fails" tests in our CI loop...

Agree. Is there a way to disable the test by default, or should I send
a patch to remove it?

Havard



[PATCH v3 6/6] hw/gpio: Add GPIO model for Nuvoton NPCM7xx

2020-10-23 Thread Havard Skinnemoen via
The NPCM7xx chips have multiple GPIO controllers that are mostly
identical except for some minor differences like the reset values of
some registers. Each controller controls up to 32 pins.

Each individual pin is modeled as a pair of unnamed GPIOs -- one for
emitting the actual pin state, and one for driving the pin externally.
Like the nRF51 GPIO controller, a gpio level may be negative, which
means the pin is not driven, or floating.

Reviewed-by: Tyrone Ting 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst |   2 +-
 include/hw/arm/npcm7xx.h|   2 +
 include/hw/gpio/npcm7xx_gpio.h  |  55 +
 hw/arm/npcm7xx.c|  80 ++
 hw/gpio/npcm7xx_gpio.c  | 424 
 tests/qtest/npcm7xx_gpio-test.c | 385 +
 hw/gpio/meson.build |   1 +
 hw/gpio/trace-events|   7 +
 tests/qtest/meson.build |   3 +-
 9 files changed, 957 insertions(+), 2 deletions(-)
 create mode 100644 include/hw/gpio/npcm7xx_gpio.h
 create mode 100644 hw/gpio/npcm7xx_gpio.c
 create mode 100644 tests/qtest/npcm7xx_gpio-test.c

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index 99fc61c740..b00d405d52 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -40,11 +40,11 @@ Supported devices
  * Flash Interface Unit (FIU; no protection features)
  * Random Number Generator (RNG)
  * USB host (USBH)
+ * GPIO controller
 
 Missing devices
 ---
 
- * GPIO controller
  * LPC/eSPI host-to-BMC interface, including
 
* Keyboard and mouse controller interface (KBCI)
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index aeee1beaaa..5469247e38 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -18,6 +18,7 @@
 
 #include "hw/boards.h"
 #include "hw/cpu/a9mpcore.h"
+#include "hw/gpio/npcm7xx_gpio.h"
 #include "hw/mem/npcm7xx_mc.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
@@ -79,6 +80,7 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
 NPCM7xxRNGState rng;
+NPCM7xxGPIOStategpio[8];
 EHCISysBusState ehci;
 OHCISysBusState ohci;
 NPCM7xxFIUState fiu[2];
diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h
new file mode 100644
index 00..b1d771bd77
--- /dev/null
+++ b/include/hw/gpio/npcm7xx_gpio.h
@@ -0,0 +1,55 @@
+/*
+ * Nuvoton NPCM7xx General Purpose Input / Output (GPIO)
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef NPCM7XX_GPIO_H
+#define NPCM7XX_GPIO_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/* Number of pins managed by each controller. */
+#define NPCM7XX_GPIO_NR_PINS (32)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_GPIO_NR_REGS (0x80 / sizeof(uint32_t))
+
+typedef struct NPCM7xxGPIOState {
+SysBusDevice parent;
+
+/* Properties to be defined by the SoC */
+uint32_t reset_pu;
+uint32_t reset_pd;
+uint32_t reset_osrc;
+uint32_t reset_odsc;
+
+MemoryRegion mmio;
+
+qemu_irq irq;
+qemu_irq output[NPCM7XX_GPIO_NR_PINS];
+
+uint32_t pin_level;
+uint32_t ext_level;
+uint32_t ext_driven;
+
+uint32_t regs[NPCM7XX_GPIO_NR_REGS];
+} NPCM7xxGPIOState;
+
+#define TYPE_NPCM7XX_GPIO "npcm7xx-gpio"
+#define NPCM7XX_GPIO(obj) \
+OBJECT_CHECK(NPCM7xxGPIOState, (obj), TYPE_NPCM7XX_GPIO)
+
+#endif /* NPCM7XX_GPIO_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index c1d122576b..47e2b6fc40 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -96,6 +96,14 @@ enum NPCM7xxInterrupt {
 NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
 NPCM7XX_EHCI_IRQ= 61,
 NPCM7XX_OHCI_IRQ= 62,
+NPCM7XX_GPIO0_IRQ   = 116,
+NPCM7XX_GPIO1_IRQ,
+NPCM7XX_GPIO2_IRQ,
+NPCM7XX_GPIO3_IRQ,
+NPCM7XX_GPIO4_IRQ,
+NPCM7XX_GPIO5_IRQ,
+NPCM7XX_GPIO6_IRQ,
+NPCM7XX_GPIO7_IRQ,
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -130,6 +138,55 @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
 0xb800, /* CS3 */
 };
 
+static const struct {
+hwaddr regs_addr;
+uint32_t unconnected_pins;
+uint32_t reset_pu;
+uint32_t reset_pd;
+uint32_t reset_osr

[PATCH v3 3/6] hw/timer: Adding watchdog for NPCM7XX Timer.

2020-10-23 Thread Havard Skinnemoen via
From: Hao Wu 

The watchdog is part of NPCM7XX's timer module. Its behavior is
controlled by the WTCR register in the timer.

When enabled, the watchdog issues an interrupt signal after a pre-set
amount of cycles, and issues a reset signal shortly after that.

Reviewed-by: Tyrone Ting 
Signed-off-by: Hao Wu 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/misc/npcm7xx_clk.h |   2 +
 include/hw/timer/npcm7xx_timer.h  |  48 +++-
 hw/arm/npcm7xx.c  |  12 +
 hw/misc/npcm7xx_clk.c |  28 ++
 hw/timer/npcm7xx_timer.c  | 266 ++
 tests/qtest/npcm7xx_watchdog_timer-test.c | 320 ++
 MAINTAINERS   |   1 +
 tests/qtest/meson.build   |   2 +-
 8 files changed, 625 insertions(+), 54 deletions(-)
 create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c

diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
index cdcc9e8534..2338fbbdb5 100644
--- a/include/hw/misc/npcm7xx_clk.h
+++ b/include/hw/misc/npcm7xx_clk.h
@@ -31,6 +31,8 @@
  */
 #define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
 
+#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
+
 typedef struct NPCM7xxCLKState {
 SysBusDevice parent;
 
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
index 878a365a79..6993fd723a 100644
--- a/include/hw/timer/npcm7xx_timer.h
+++ b/include/hw/timer/npcm7xx_timer.h
@@ -29,14 +29,31 @@
  */
 #define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
 
+/* The basic watchdog timer period is 2^14 clock cycles. */
+#define NPCM7XX_WATCHDOG_BASETIME_SHIFT 14
+
+#define NPCM7XX_WATCHDOG_RESET_GPIO_OUT "npcm7xx-clk-watchdog-reset-gpio-out"
+
 typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
 
 /**
- * struct NPCM7xxTimer - Individual timer state.
- * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * struct NPCM7xxBaseTimer - Basic functionality that both regular timer and
+ * watchdog timer use.
  * @qtimer: QEMU timer that notifies us on expiration.
  * @expires_ns: Absolute virtual expiration time.
  * @remaining_ns: Remaining time until expiration if timer is paused.
+ */
+typedef struct NPCM7xxBaseTimer {
+QEMUTimer   qtimer;
+int64_t expires_ns;
+int64_t remaining_ns;
+} NPCM7xxBaseTimer;
+
+/**
+ * struct NPCM7xxTimer - Individual timer state.
+ * @ctrl: The timer module that owns this timer.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @base_timer: The basic timer functionality for this timer.
  * @tcsr: The Timer Control and Status Register.
  * @ticr: The Timer Initial Count Register.
  */
@@ -44,21 +61,38 @@ typedef struct NPCM7xxTimer {
 NPCM7xxTimerCtrlState *ctrl;
 
 qemu_irqirq;
-QEMUTimer   qtimer;
-int64_t expires_ns;
-int64_t remaining_ns;
+NPCM7xxBaseTimer base_timer;
 
 uint32_ttcsr;
 uint32_tticr;
 } NPCM7xxTimer;
 
+/**
+ * struct NPCM7xxWatchdogTimer - The watchdog timer state.
+ * @ctrl: The timer module that owns this timer.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @reset_signal: The GPIO used to send a reset signal.
+ * @base_timer: The basic timer functionality for this timer.
+ * @wtcr: The Watchdog Timer Control Register.
+ */
+typedef struct NPCM7xxWatchdogTimer {
+NPCM7xxTimerCtrlState *ctrl;
+
+qemu_irqirq;
+qemu_irqreset_signal;
+NPCM7xxBaseTimer base_timer;
+
+uint32_twtcr;
+} NPCM7xxWatchdogTimer;
+
 /**
  * struct NPCM7xxTimerCtrlState - Timer Module device state.
  * @parent: System bus device.
  * @iomem: Memory region through which registers are accessed.
+ * @index: The index of this timer module.
  * @tisr: The Timer Interrupt Status Register.
- * @wtcr: The Watchdog Timer Control Register.
  * @timer: The five individual timers managed by this module.
+ * @watchdog_timer: The watchdog timer managed by this module.
  */
 struct NPCM7xxTimerCtrlState {
 SysBusDevice parent;
@@ -66,9 +100,9 @@ struct NPCM7xxTimerCtrlState {
 MemoryRegion iomem;
 
 uint32_ttisr;
-uint32_twtcr;
 
 NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
+NPCM7xxWatchdogTimer watchdog_timer;
 };
 
 #define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 037f3a26f2..c341dcab8b 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -86,6 +86,9 @@ enum NPCM7xxInterrupt {
 NPCM7XX_TIMER12_IRQ,
 NPCM7XX_TIMER13_IRQ,
 NPCM7XX_TIMER14_IRQ,
+NPCM7XX_WDG0_IRQ= 47,   /* Timer Module 0 Watchdog */
+NPCM7XX_WDG1_IRQ,   /* Timer Module 1 Watchdog */
+NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -353,6 +356,15 @@ static vo

[PATCH v3 5/6] hw/arm/npcm7xx: Add EHCI and OHCI controllers

2020-10-23 Thread Havard Skinnemoen via
The NPCM730 and NPCM750 chips have a single USB host port shared between
a USB 2.0 EHCI host controller and a USB 1.1 OHCI host controller. This
adds support for both of them.

Testing notes:
  * With -device usb-kbd, qemu will automatically insert a full-speed
hub, and the keyboard becomes controlled by the OHCI controller.
  * With -device usb-kbd,bus=usb-bus.0,port=1, the keyboard is directly
attached to the port without any hubs, and the device becomes
controlled by the EHCI controller since it's high speed capable.
  * With -device usb-kbd,bus=usb-bus.0,port=1,usb_version=1, the
keyboard is directly attached to the port, but it only advertises
itself as full-speed capable, so it becomes controlled by the OHCI
controller.

In all cases, the keyboard device enumerates correctly.

Reviewed-by: Tyrone Ting 
Reviewed-by: Gerd Hoffmann 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst |  2 +-
 hw/usb/hcd-ehci.h   |  1 +
 include/hw/arm/npcm7xx.h|  4 
 hw/arm/npcm7xx.c| 27 +--
 hw/usb/hcd-ehci-sysbus.c| 19 +++
 5 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index 4342434df4..99fc61c740 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -39,6 +39,7 @@ Supported devices
  * OTP controllers (no protection features)
  * Flash Interface Unit (FIU; no protection features)
  * Random Number Generator (RNG)
+ * USB host (USBH)
 
 Missing devices
 ---
@@ -54,7 +55,6 @@ Missing devices
* eSPI slave interface
 
  * Ethernet controllers (GMAC and EMC)
- * USB host (USBH)
  * USB device (USBD)
  * SMBus controller (SMBF)
  * Peripheral SPI controller (PSPI)
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index fd122dd4cd..a173707d9b 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -344,6 +344,7 @@ struct EHCIPCIState {
 #define TYPE_PLATFORM_EHCI "platform-ehci-usb"
 #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
 #define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
+#define TYPE_NPCM7XX_EHCI "npcm7xx-ehci-usb"
 #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
 #define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
 #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 761f9b987e..aeee1beaaa 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -25,6 +25,8 @@
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "hw/ssi/npcm7xx_fiu.h"
+#include "hw/usb/hcd-ehci.h"
+#include "hw/usb/hcd-ohci.h"
 #include "target/arm/cpu.h"
 
 #define NPCM7XX_MAX_NUM_CPUS(2)
@@ -77,6 +79,8 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
 NPCM7xxRNGState rng;
+EHCISysBusState ehci;
+OHCISysBusState ohci;
 NPCM7xxFIUState fiu[2];
 } NPCM7xxState;
 
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index cb4db41c54..c1d122576b 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -46,6 +46,10 @@
 #define NPCM7XX_MC_BA   (0xf0824000)
 #define NPCM7XX_RNG_BA  (0xf000b000)
 
+/* USB Host modules */
+#define NPCM7XX_EHCI_BA (0xf0806000)
+#define NPCM7XX_OHCI_BA (0xf0807000)
+
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
 #define NPCM7XX_RAM3_SZ (4 * KiB)
@@ -90,6 +94,8 @@ enum NPCM7xxInterrupt {
 NPCM7XX_WDG0_IRQ= 47,   /* Timer Module 0 Watchdog */
 NPCM7XX_WDG1_IRQ,   /* Timer Module 1 Watchdog */
 NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
+NPCM7XX_EHCI_IRQ= 61,
+NPCM7XX_OHCI_IRQ= 62,
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -263,6 +269,9 @@ static void npcm7xx_init(Object *obj)
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
 }
 
+object_initialize_child(obj, "ehci", >ehci, TYPE_NPCM7XX_EHCI);
+object_initialize_child(obj, "ohci", >ohci, TYPE_SYSBUS_OHCI);
+
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
 for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
 object_initialize_child(obj, npcm7xx_fiu[i].name, >fiu[i],
@@ -380,6 +389,22 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 sysbus_realize(SYS_BUS_DEVICE(>rng), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>rng), 0, NPCM7XX_RNG_BA);
 
+/* USB Host */
+object_property_set_bool(OBJECT(>ehci), "companion-enable", true,
+ _abort);
+sysbus_realize(SYS_BUS_DEVICE(>ehci), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>

[PATCH v3 0/6] Additional NPCM7xx features, devices and tests

2020-10-23 Thread Havard Skinnemoen via
This is an update to the initial NPCM7xx patch series adding

  - Watchdog timer support. This makes the reboot command work.
  - Random Number Generator device.
  - USB Host Controllers.
  - GPIO Controllers.

The watchdog was implemented by my new teammate Hao Wu. Expect to see more
patches from him in the near future.

This series has also been pushed to the npcm7xx-5.2-update branch of my github
repository at

  https://github.com/hskinnemoen/qemu

Changes since v2:

  - Watchdog timer test now uses libqos/libqtest.h API consistently instead of
a mix of that and libqtest-single.h.
  - Made all npcm7xx-related tests conditional on CONFIG_NPCM7XX. An extra
patch was added for the previously submitted timer test.

Changes since v1:

  - Dropped the timer test since it's already applied (thanks Peter).
  - Watchdog reset signaling is now using GPIOs instead of a custom API
(thanks Peter for suggesting, and Hao for implementing it).
  - Various comment updates for the timer.
  - VMState added to GPIO device.
  - Missing VMstate terminator added to RNG device.
  - Include order in RNG test fixed.

Again, thanks a lot for reviewing!

Havard

Hao Wu (1):
  hw/timer: Adding watchdog for NPCM7XX Timer.

Havard Skinnemoen (5):
  tests/qtest: Make npcm7xx_timer-test conditional on CONFIG_NPCM7XX
  Move npcm7xx_timer_reached_zero call out of npcm7xx_timer_pause
  hw/misc: Add npcm7xx random number generator
  hw/arm/npcm7xx: Add EHCI and OHCI controllers
  hw/gpio: Add GPIO model for Nuvoton NPCM7xx

 docs/system/arm/nuvoton.rst   |   6 +-
 hw/usb/hcd-ehci.h |   1 +
 include/hw/arm/npcm7xx.h  |   8 +
 include/hw/gpio/npcm7xx_gpio.h|  55 +++
 include/hw/misc/npcm7xx_clk.h |   2 +
 include/hw/misc/npcm7xx_rng.h |  34 ++
 include/hw/timer/npcm7xx_timer.h  |  48 ++-
 hw/arm/npcm7xx.c  | 126 ++-
 hw/gpio/npcm7xx_gpio.c| 424 ++
 hw/misc/npcm7xx_clk.c |  28 ++
 hw/misc/npcm7xx_rng.c | 180 +
 hw/timer/npcm7xx_timer.c  | 270 +++---
 hw/usb/hcd-ehci-sysbus.c  |  19 +
 tests/qtest/npcm7xx_gpio-test.c   | 385 
 tests/qtest/npcm7xx_rng-test.c| 278 ++
 tests/qtest/npcm7xx_watchdog_timer-test.c | 320 
 MAINTAINERS   |   1 +
 hw/gpio/meson.build   |   1 +
 hw/gpio/trace-events  |   7 +
 hw/misc/meson.build   |   1 +
 hw/misc/trace-events  |   4 +
 tests/qtest/meson.build   |   7 +-
 22 files changed, 2143 insertions(+), 62 deletions(-)
 create mode 100644 include/hw/gpio/npcm7xx_gpio.h
 create mode 100644 include/hw/misc/npcm7xx_rng.h
 create mode 100644 hw/gpio/npcm7xx_gpio.c
 create mode 100644 hw/misc/npcm7xx_rng.c
 create mode 100644 tests/qtest/npcm7xx_gpio-test.c
 create mode 100644 tests/qtest/npcm7xx_rng-test.c
 create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c

-- 
2.29.0.rc1.297.gfa9743e501-goog




[PATCH v3 4/6] hw/misc: Add npcm7xx random number generator

2020-10-23 Thread Havard Skinnemoen via
The RNG module returns a byte of randomness when the Data Valid bit is
set.

This implementation ignores the prescaler setting, and loads a new value
into RNGD every time RNGCS is read while the RNG is enabled and random
data is available.

A qtest featuring some simple randomness tests is included.

Reviewed-by: Tyrone Ting 
Reviewed-by: Peter Maydell 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst|   2 +-
 include/hw/arm/npcm7xx.h   |   2 +
 include/hw/misc/npcm7xx_rng.h  |  34 
 hw/arm/npcm7xx.c   |   7 +-
 hw/misc/npcm7xx_rng.c  | 180 +
 tests/qtest/npcm7xx_rng-test.c | 278 +
 hw/misc/meson.build|   1 +
 hw/misc/trace-events   |   4 +
 tests/qtest/meson.build|   5 +-
 9 files changed, 510 insertions(+), 3 deletions(-)
 create mode 100644 include/hw/misc/npcm7xx_rng.h
 create mode 100644 hw/misc/npcm7xx_rng.c
 create mode 100644 tests/qtest/npcm7xx_rng-test.c

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index e3e1a3a3a7..4342434df4 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -38,6 +38,7 @@ Supported devices
  * DDR4 memory controller (dummy interface indicating memory training is done)
  * OTP controllers (no protection features)
  * Flash Interface Unit (FIU; no protection features)
+ * Random Number Generator (RNG)
 
 Missing devices
 ---
@@ -59,7 +60,6 @@ Missing devices
  * Peripheral SPI controller (PSPI)
  * Analog to Digital Converter (ADC)
  * SD/MMC host
- * Random Number Generator (RNG)
  * PECI interface
  * Pulse Width Modulation (PWM)
  * Tachometer
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 13106af215..761f9b987e 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -21,6 +21,7 @@
 #include "hw/mem/npcm7xx_mc.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
+#include "hw/misc/npcm7xx_rng.h"
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "hw/ssi/npcm7xx_fiu.h"
@@ -75,6 +76,7 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState key_storage;
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
+NPCM7xxRNGState rng;
 NPCM7xxFIUState fiu[2];
 } NPCM7xxState;
 
diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h
new file mode 100644
index 00..5e85fd439d
--- /dev/null
+++ b/include/hw/misc/npcm7xx_rng.h
@@ -0,0 +1,34 @@
+/*
+ * Nuvoton NPCM7xx Random Number Generator.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_RNG_H
+#define NPCM7XX_RNG_H
+
+#include "hw/sysbus.h"
+
+typedef struct NPCM7xxRNGState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint8_t rngcs;
+uint8_t rngd;
+uint8_t rngmode;
+} NPCM7xxRNGState;
+
+#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
+#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG)
+
+#endif /* NPCM7XX_RNG_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index c341dcab8b..cb4db41c54 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -44,6 +44,7 @@
 #define NPCM7XX_GCR_BA  (0xf080)
 #define NPCM7XX_CLK_BA  (0xf0801000)
 #define NPCM7XX_MC_BA   (0xf0824000)
+#define NPCM7XX_RNG_BA  (0xf000b000)
 
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
@@ -256,6 +257,7 @@ static void npcm7xx_init(Object *obj)
 object_initialize_child(obj, "otp2", >fuse_array,
 TYPE_NPCM7XX_FUSE_ARRAY);
 object_initialize_child(obj, "mc", >mc, TYPE_NPCM7XX_MC);
+object_initialize_child(obj, "rng", >rng, TYPE_NPCM7XX_RNG);
 
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
@@ -374,6 +376,10 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
serial_hd(i), DEVICE_LITTLE_ENDIAN);
 }
 
+/* Random Number Generator. Cannot fail. */
+sysbus_realize(SYS_BUS_DEVICE(>rng), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>rng), 0, NPCM7XX_RNG_BA);
+
 /*
  * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
  * specified, but this is a programming error.
@@ -

[PATCH v3 1/6] tests/qtest: Make npcm7xx_timer-test conditional on CONFIG_NPCM7XX

2020-10-23 Thread Havard Skinnemoen via
This test won't work if qemu was compiled without CONFIG_NPCM7XX, as
pointed out by Thomas Huth on a different patch.

Signed-off-by: Havard Skinnemoen 
---
 tests/qtest/meson.build | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 28d4068718..7e0ecaa2c5 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -133,12 +133,13 @@ qtests_sparc64 = \
   (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : 
[]) +\
   ['prom-env-test', 'boot-serial-test']
 
+qtests_npcm7xx = ['npcm7xx_timer-test']
 qtests_arm = \
   (config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : 
[]) + \
+  (config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
   ['arm-cpu-features',
'microbit-test',
'm25p80-test',
-   'npcm7xx_timer-test',
'test-arm-mptimer',
'boot-serial-test',
'hexloader-test']
-- 
2.29.0.rc1.297.gfa9743e501-goog




[PATCH v3 2/6] Move npcm7xx_timer_reached_zero call out of npcm7xx_timer_pause

2020-10-23 Thread Havard Skinnemoen via
This allows us to reuse npcm7xx_timer_pause for the watchdog timer.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 hw/timer/npcm7xx_timer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
index 5703e43d40..2df9e3e496 100644
--- a/hw/timer/npcm7xx_timer.c
+++ b/hw/timer/npcm7xx_timer.c
@@ -157,9 +157,6 @@ static void npcm7xx_timer_pause(NPCM7xxTimer *t)
 timer_del(>qtimer);
 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 t->remaining_ns = t->expires_ns - now;
-if (t->remaining_ns <= 0) {
-npcm7xx_timer_reached_zero(t);
-}
 }
 
 /*
@@ -239,6 +236,9 @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, 
uint32_t new_tcsr)
 } else {
 t->tcsr &= ~NPCM7XX_TCSR_CACT;
 npcm7xx_timer_pause(t);
+if (t->remaining_ns <= 0) {
+npcm7xx_timer_reached_zero(t);
+}
 }
 }
 }
-- 
2.29.0.rc1.297.gfa9743e501-goog




[Bug 1901068] [NEW] Deleted tests are still run if they exist in the build tree

2020-10-22 Thread Havard Skinnemoen
Public bug reported:

Steps to reproduce:
1. Add a new device along with a qtest to exercise it.
2. Run make check-qtest. It passes.
3. Revert the commit that added the device and qtest.
4. Run make check-qtest again. It now fails because the device no longer 
exists, but the test is somehow still there even though the source files are 
gone and it's not mentioned in tests/qtest/meson.build.

After running make clean, make check-qtest passes again.

$ git describe
v5.1.0-2465-g4c5b97bfd0

** Affects: qemu
 Importance: Undecided
 Status: New

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1901068

Title:
  Deleted tests are still run if they exist in the build tree

Status in QEMU:
  New

Bug description:
  Steps to reproduce:
  1. Add a new device along with a qtest to exercise it.
  2. Run make check-qtest. It passes.
  3. Revert the commit that added the device and qtest.
  4. Run make check-qtest again. It now fails because the device no longer 
exists, but the test is somehow still there even though the source files are 
gone and it's not mentioned in tests/qtest/meson.build.

  After running make clean, make check-qtest passes again.

  $ git describe
  v5.1.0-2465-g4c5b97bfd0

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1901068/+subscriptions



[PATCH v2 4/5] hw/arm/npcm7xx: Add EHCI and OHCI controllers

2020-10-21 Thread Havard Skinnemoen via
The NPCM730 and NPCM750 chips have a single USB host port shared between
a USB 2.0 EHCI host controller and a USB 1.1 OHCI host controller. This
adds support for both of them.

Testing notes:
  * With -device usb-kbd, qemu will automatically insert a full-speed
hub, and the keyboard becomes controlled by the OHCI controller.
  * With -device usb-kbd,bus=usb-bus.0,port=1, the keyboard is directly
attached to the port without any hubs, and the device becomes
controlled by the EHCI controller since it's high speed capable.
  * With -device usb-kbd,bus=usb-bus.0,port=1,usb_version=1, the
keyboard is directly attached to the port, but it only advertises
itself as full-speed capable, so it becomes controlled by the OHCI
controller.

In all cases, the keyboard device enumerates correctly.

Reviewed-by: Tyrone Ting 
Reviewed-by: Gerd Hoffmann 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst |  2 +-
 hw/usb/hcd-ehci.h   |  1 +
 include/hw/arm/npcm7xx.h|  4 
 hw/arm/npcm7xx.c| 27 +--
 hw/usb/hcd-ehci-sysbus.c| 19 +++
 5 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index 4342434df4..99fc61c740 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -39,6 +39,7 @@ Supported devices
  * OTP controllers (no protection features)
  * Flash Interface Unit (FIU; no protection features)
  * Random Number Generator (RNG)
+ * USB host (USBH)
 
 Missing devices
 ---
@@ -54,7 +55,6 @@ Missing devices
* eSPI slave interface
 
  * Ethernet controllers (GMAC and EMC)
- * USB host (USBH)
  * USB device (USBD)
  * SMBus controller (SMBF)
  * Peripheral SPI controller (PSPI)
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index fd122dd4cd..a173707d9b 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -344,6 +344,7 @@ struct EHCIPCIState {
 #define TYPE_PLATFORM_EHCI "platform-ehci-usb"
 #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
 #define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
+#define TYPE_NPCM7XX_EHCI "npcm7xx-ehci-usb"
 #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
 #define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
 #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 761f9b987e..aeee1beaaa 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -25,6 +25,8 @@
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "hw/ssi/npcm7xx_fiu.h"
+#include "hw/usb/hcd-ehci.h"
+#include "hw/usb/hcd-ohci.h"
 #include "target/arm/cpu.h"
 
 #define NPCM7XX_MAX_NUM_CPUS(2)
@@ -77,6 +79,8 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
 NPCM7xxRNGState rng;
+EHCISysBusState ehci;
+OHCISysBusState ohci;
 NPCM7xxFIUState fiu[2];
 } NPCM7xxState;
 
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index cb4db41c54..c1d122576b 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -46,6 +46,10 @@
 #define NPCM7XX_MC_BA   (0xf0824000)
 #define NPCM7XX_RNG_BA  (0xf000b000)
 
+/* USB Host modules */
+#define NPCM7XX_EHCI_BA (0xf0806000)
+#define NPCM7XX_OHCI_BA (0xf0807000)
+
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
 #define NPCM7XX_RAM3_SZ (4 * KiB)
@@ -90,6 +94,8 @@ enum NPCM7xxInterrupt {
 NPCM7XX_WDG0_IRQ= 47,   /* Timer Module 0 Watchdog */
 NPCM7XX_WDG1_IRQ,   /* Timer Module 1 Watchdog */
 NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
+NPCM7XX_EHCI_IRQ= 61,
+NPCM7XX_OHCI_IRQ= 62,
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -263,6 +269,9 @@ static void npcm7xx_init(Object *obj)
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
 }
 
+object_initialize_child(obj, "ehci", >ehci, TYPE_NPCM7XX_EHCI);
+object_initialize_child(obj, "ohci", >ohci, TYPE_SYSBUS_OHCI);
+
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
 for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
 object_initialize_child(obj, npcm7xx_fiu[i].name, >fiu[i],
@@ -380,6 +389,22 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 sysbus_realize(SYS_BUS_DEVICE(>rng), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>rng), 0, NPCM7XX_RNG_BA);
 
+/* USB Host */
+object_property_set_bool(OBJECT(>ehci), "companion-enable", true,
+ _abort);
+sysbus_realize(SYS_BUS_DEVICE(>ehci), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>

[PATCH v2 5/5] hw/gpio: Add GPIO model for Nuvoton NPCM7xx

2020-10-21 Thread Havard Skinnemoen via
The NPCM7xx chips have multiple GPIO controllers that are mostly
identical except for some minor differences like the reset values of
some registers. Each controller controls up to 32 pins.

Each individual pin is modeled as a pair of unnamed GPIOs -- one for
emitting the actual pin state, and one for driving the pin externally.
Like the nRF51 GPIO controller, a gpio level may be negative, which
means the pin is not driven, or floating.

Reviewed-by: Tyrone Ting 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst |   2 +-
 include/hw/arm/npcm7xx.h|   2 +
 include/hw/gpio/npcm7xx_gpio.h  |  55 +
 hw/arm/npcm7xx.c|  80 ++
 hw/gpio/npcm7xx_gpio.c  | 424 
 tests/qtest/npcm7xx_gpio-test.c | 385 +
 hw/gpio/meson.build |   1 +
 hw/gpio/trace-events|   7 +
 tests/qtest/meson.build |   1 +
 9 files changed, 956 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/gpio/npcm7xx_gpio.h
 create mode 100644 hw/gpio/npcm7xx_gpio.c
 create mode 100644 tests/qtest/npcm7xx_gpio-test.c

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index 99fc61c740..b00d405d52 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -40,11 +40,11 @@ Supported devices
  * Flash Interface Unit (FIU; no protection features)
  * Random Number Generator (RNG)
  * USB host (USBH)
+ * GPIO controller
 
 Missing devices
 ---
 
- * GPIO controller
  * LPC/eSPI host-to-BMC interface, including
 
* Keyboard and mouse controller interface (KBCI)
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index aeee1beaaa..5469247e38 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -18,6 +18,7 @@
 
 #include "hw/boards.h"
 #include "hw/cpu/a9mpcore.h"
+#include "hw/gpio/npcm7xx_gpio.h"
 #include "hw/mem/npcm7xx_mc.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
@@ -79,6 +80,7 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
 NPCM7xxRNGState rng;
+NPCM7xxGPIOStategpio[8];
 EHCISysBusState ehci;
 OHCISysBusState ohci;
 NPCM7xxFIUState fiu[2];
diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h
new file mode 100644
index 00..b1d771bd77
--- /dev/null
+++ b/include/hw/gpio/npcm7xx_gpio.h
@@ -0,0 +1,55 @@
+/*
+ * Nuvoton NPCM7xx General Purpose Input / Output (GPIO)
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef NPCM7XX_GPIO_H
+#define NPCM7XX_GPIO_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/* Number of pins managed by each controller. */
+#define NPCM7XX_GPIO_NR_PINS (32)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_GPIO_NR_REGS (0x80 / sizeof(uint32_t))
+
+typedef struct NPCM7xxGPIOState {
+SysBusDevice parent;
+
+/* Properties to be defined by the SoC */
+uint32_t reset_pu;
+uint32_t reset_pd;
+uint32_t reset_osrc;
+uint32_t reset_odsc;
+
+MemoryRegion mmio;
+
+qemu_irq irq;
+qemu_irq output[NPCM7XX_GPIO_NR_PINS];
+
+uint32_t pin_level;
+uint32_t ext_level;
+uint32_t ext_driven;
+
+uint32_t regs[NPCM7XX_GPIO_NR_REGS];
+} NPCM7xxGPIOState;
+
+#define TYPE_NPCM7XX_GPIO "npcm7xx-gpio"
+#define NPCM7XX_GPIO(obj) \
+OBJECT_CHECK(NPCM7xxGPIOState, (obj), TYPE_NPCM7XX_GPIO)
+
+#endif /* NPCM7XX_GPIO_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index c1d122576b..47e2b6fc40 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -96,6 +96,14 @@ enum NPCM7xxInterrupt {
 NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
 NPCM7XX_EHCI_IRQ= 61,
 NPCM7XX_OHCI_IRQ= 62,
+NPCM7XX_GPIO0_IRQ   = 116,
+NPCM7XX_GPIO1_IRQ,
+NPCM7XX_GPIO2_IRQ,
+NPCM7XX_GPIO3_IRQ,
+NPCM7XX_GPIO4_IRQ,
+NPCM7XX_GPIO5_IRQ,
+NPCM7XX_GPIO6_IRQ,
+NPCM7XX_GPIO7_IRQ,
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -130,6 +138,55 @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
 0xb800, /* CS3 */
 };
 
+static const struct {
+hwaddr regs_addr;
+uint32_t unconnected_pins;
+uint32_t reset_pu;
+uint32_t reset_pd;
+uint32_t reset_osr

[PATCH v2 3/5] hw/misc: Add npcm7xx random number generator

2020-10-21 Thread Havard Skinnemoen via
The RNG module returns a byte of randomness when the Data Valid bit is
set.

This implementation ignores the prescaler setting, and loads a new value
into RNGD every time RNGCS is read while the RNG is enabled and random
data is available.

A qtest featuring some simple randomness tests is included.

Reviewed-by: Tyrone Ting 
Reviewed-by: Peter Maydell 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst|   2 +-
 include/hw/arm/npcm7xx.h   |   2 +
 include/hw/misc/npcm7xx_rng.h  |  34 
 hw/arm/npcm7xx.c   |   7 +-
 hw/misc/npcm7xx_rng.c  | 180 +
 tests/qtest/npcm7xx_rng-test.c | 278 +
 hw/misc/meson.build|   1 +
 hw/misc/trace-events   |   4 +
 tests/qtest/meson.build|   1 +
 9 files changed, 507 insertions(+), 2 deletions(-)
 create mode 100644 include/hw/misc/npcm7xx_rng.h
 create mode 100644 hw/misc/npcm7xx_rng.c
 create mode 100644 tests/qtest/npcm7xx_rng-test.c

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index e3e1a3a3a7..4342434df4 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -38,6 +38,7 @@ Supported devices
  * DDR4 memory controller (dummy interface indicating memory training is done)
  * OTP controllers (no protection features)
  * Flash Interface Unit (FIU; no protection features)
+ * Random Number Generator (RNG)
 
 Missing devices
 ---
@@ -59,7 +60,6 @@ Missing devices
  * Peripheral SPI controller (PSPI)
  * Analog to Digital Converter (ADC)
  * SD/MMC host
- * Random Number Generator (RNG)
  * PECI interface
  * Pulse Width Modulation (PWM)
  * Tachometer
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 13106af215..761f9b987e 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -21,6 +21,7 @@
 #include "hw/mem/npcm7xx_mc.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
+#include "hw/misc/npcm7xx_rng.h"
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "hw/ssi/npcm7xx_fiu.h"
@@ -75,6 +76,7 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState key_storage;
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
+NPCM7xxRNGState rng;
 NPCM7xxFIUState fiu[2];
 } NPCM7xxState;
 
diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h
new file mode 100644
index 00..5e85fd439d
--- /dev/null
+++ b/include/hw/misc/npcm7xx_rng.h
@@ -0,0 +1,34 @@
+/*
+ * Nuvoton NPCM7xx Random Number Generator.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_RNG_H
+#define NPCM7XX_RNG_H
+
+#include "hw/sysbus.h"
+
+typedef struct NPCM7xxRNGState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint8_t rngcs;
+uint8_t rngd;
+uint8_t rngmode;
+} NPCM7xxRNGState;
+
+#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
+#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG)
+
+#endif /* NPCM7XX_RNG_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index c341dcab8b..cb4db41c54 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -44,6 +44,7 @@
 #define NPCM7XX_GCR_BA  (0xf080)
 #define NPCM7XX_CLK_BA  (0xf0801000)
 #define NPCM7XX_MC_BA   (0xf0824000)
+#define NPCM7XX_RNG_BA  (0xf000b000)
 
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
@@ -256,6 +257,7 @@ static void npcm7xx_init(Object *obj)
 object_initialize_child(obj, "otp2", >fuse_array,
 TYPE_NPCM7XX_FUSE_ARRAY);
 object_initialize_child(obj, "mc", >mc, TYPE_NPCM7XX_MC);
+object_initialize_child(obj, "rng", >rng, TYPE_NPCM7XX_RNG);
 
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
@@ -374,6 +376,10 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
serial_hd(i), DEVICE_LITTLE_ENDIAN);
 }
 
+/* Random Number Generator. Cannot fail. */
+sysbus_realize(SYS_BUS_DEVICE(>rng), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>rng), 0, NPCM7XX_RNG_BA);
+
 /*
  * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
  * specified, but this is a programming error.
@@ -

[PATCH v2 1/5] Move npcm7xx_timer_reached_zero call out of npcm7xx_timer_pause

2020-10-21 Thread Havard Skinnemoen via
This allows us to reuse npcm7xx_timer_pause for the watchdog timer.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 hw/timer/npcm7xx_timer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
index 5703e43d40..2df9e3e496 100644
--- a/hw/timer/npcm7xx_timer.c
+++ b/hw/timer/npcm7xx_timer.c
@@ -157,9 +157,6 @@ static void npcm7xx_timer_pause(NPCM7xxTimer *t)
 timer_del(>qtimer);
 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 t->remaining_ns = t->expires_ns - now;
-if (t->remaining_ns <= 0) {
-npcm7xx_timer_reached_zero(t);
-}
 }
 
 /*
@@ -239,6 +236,9 @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, 
uint32_t new_tcsr)
 } else {
 t->tcsr &= ~NPCM7XX_TCSR_CACT;
 npcm7xx_timer_pause(t);
+if (t->remaining_ns <= 0) {
+npcm7xx_timer_reached_zero(t);
+}
 }
 }
 }
-- 
2.29.0.rc1.297.gfa9743e501-goog




[PATCH v2 2/5] hw/timer: Adding watchdog for NPCM7XX Timer.

2020-10-21 Thread Havard Skinnemoen via
From: Hao Wu 

The watchdog is part of NPCM7XX's timer module. Its behavior is
controlled by the WTCR register in the timer.

When enabled, the watchdog issues an interrupt signal after a pre-set
amount of cycles, and issues a reset signal shortly after that.

Reviewed-by: Tyrone Ting 
Signed-off-by: Hao Wu 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/misc/npcm7xx_clk.h |   2 +
 include/hw/timer/npcm7xx_timer.h  |  48 +++-
 hw/arm/npcm7xx.c  |  12 +
 hw/misc/npcm7xx_clk.c |  28 ++
 hw/timer/npcm7xx_timer.c  | 266 ++
 tests/qtest/npcm7xx_watchdog_timer-test.c | 313 ++
 MAINTAINERS   |   1 +
 tests/qtest/meson.build   |   1 +
 8 files changed, 618 insertions(+), 53 deletions(-)
 create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c

diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
index cdcc9e8534..2338fbbdb5 100644
--- a/include/hw/misc/npcm7xx_clk.h
+++ b/include/hw/misc/npcm7xx_clk.h
@@ -31,6 +31,8 @@
  */
 #define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
 
+#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
+
 typedef struct NPCM7xxCLKState {
 SysBusDevice parent;
 
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
index 878a365a79..6993fd723a 100644
--- a/include/hw/timer/npcm7xx_timer.h
+++ b/include/hw/timer/npcm7xx_timer.h
@@ -29,14 +29,31 @@
  */
 #define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
 
+/* The basic watchdog timer period is 2^14 clock cycles. */
+#define NPCM7XX_WATCHDOG_BASETIME_SHIFT 14
+
+#define NPCM7XX_WATCHDOG_RESET_GPIO_OUT "npcm7xx-clk-watchdog-reset-gpio-out"
+
 typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
 
 /**
- * struct NPCM7xxTimer - Individual timer state.
- * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * struct NPCM7xxBaseTimer - Basic functionality that both regular timer and
+ * watchdog timer use.
  * @qtimer: QEMU timer that notifies us on expiration.
  * @expires_ns: Absolute virtual expiration time.
  * @remaining_ns: Remaining time until expiration if timer is paused.
+ */
+typedef struct NPCM7xxBaseTimer {
+QEMUTimer   qtimer;
+int64_t expires_ns;
+int64_t remaining_ns;
+} NPCM7xxBaseTimer;
+
+/**
+ * struct NPCM7xxTimer - Individual timer state.
+ * @ctrl: The timer module that owns this timer.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @base_timer: The basic timer functionality for this timer.
  * @tcsr: The Timer Control and Status Register.
  * @ticr: The Timer Initial Count Register.
  */
@@ -44,21 +61,38 @@ typedef struct NPCM7xxTimer {
 NPCM7xxTimerCtrlState *ctrl;
 
 qemu_irqirq;
-QEMUTimer   qtimer;
-int64_t expires_ns;
-int64_t remaining_ns;
+NPCM7xxBaseTimer base_timer;
 
 uint32_ttcsr;
 uint32_tticr;
 } NPCM7xxTimer;
 
+/**
+ * struct NPCM7xxWatchdogTimer - The watchdog timer state.
+ * @ctrl: The timer module that owns this timer.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @reset_signal: The GPIO used to send a reset signal.
+ * @base_timer: The basic timer functionality for this timer.
+ * @wtcr: The Watchdog Timer Control Register.
+ */
+typedef struct NPCM7xxWatchdogTimer {
+NPCM7xxTimerCtrlState *ctrl;
+
+qemu_irqirq;
+qemu_irqreset_signal;
+NPCM7xxBaseTimer base_timer;
+
+uint32_twtcr;
+} NPCM7xxWatchdogTimer;
+
 /**
  * struct NPCM7xxTimerCtrlState - Timer Module device state.
  * @parent: System bus device.
  * @iomem: Memory region through which registers are accessed.
+ * @index: The index of this timer module.
  * @tisr: The Timer Interrupt Status Register.
- * @wtcr: The Watchdog Timer Control Register.
  * @timer: The five individual timers managed by this module.
+ * @watchdog_timer: The watchdog timer managed by this module.
  */
 struct NPCM7xxTimerCtrlState {
 SysBusDevice parent;
@@ -66,9 +100,9 @@ struct NPCM7xxTimerCtrlState {
 MemoryRegion iomem;
 
 uint32_ttisr;
-uint32_twtcr;
 
 NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
+NPCM7xxWatchdogTimer watchdog_timer;
 };
 
 #define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 037f3a26f2..c341dcab8b 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -86,6 +86,9 @@ enum NPCM7xxInterrupt {
 NPCM7XX_TIMER12_IRQ,
 NPCM7XX_TIMER13_IRQ,
 NPCM7XX_TIMER14_IRQ,
+NPCM7XX_WDG0_IRQ= 47,   /* Timer Module 0 Watchdog */
+NPCM7XX_WDG1_IRQ,   /* Timer Module 1 Watchdog */
+NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -353,6 +356,15 @@ static vo

[PATCH v2 0/5] Additional NPCM7xx features, devices and tests

2020-10-21 Thread Havard Skinnemoen via
This is an update to the initial NPCM7xx patch series adding

  - Watchdog timer support. This makes the reboot command work.
  - Random Number Generator device.
  - USB Host Controllers.
  - GPIO Controllers.

The watchdog was implemented by my new teammate Hao Wu. Expect to see more
patches from him in the near future.

This series has also been pushed to the npcm7xx-5.2-update branch of my github
repository at

  https://github.com/hskinnemoen/qemu

Changes since v1:

  - Dropped the timer test since it's already applied (thanks Peter).
  - Watchdog reset signaling is now using GPIOs instead of a custom API
(thanks Peter for suggesting, and Hao for implementing it).
  - A few comment updates for the watchdog timer.
  - VMState added to GPIO device.
  - Missing VMstate terminator added to RNG device.
  - Include order in RNG test fixed.

Again, thanks a lot for reviewing!

Havard

Hao Wu (1):
  hw/timer: Adding watchdog for NPCM7XX Timer.

Havard Skinnemoen (4):
  Move npcm7xx_timer_reached_zero call out of npcm7xx_timer_pause
  hw/misc: Add npcm7xx random number generator
  hw/arm/npcm7xx: Add EHCI and OHCI controllers
  hw/gpio: Add GPIO model for Nuvoton NPCM7xx

 docs/system/arm/nuvoton.rst   |   6 +-
 hw/usb/hcd-ehci.h |   1 +
 include/hw/arm/npcm7xx.h  |   8 +
 include/hw/gpio/npcm7xx_gpio.h|  55 +++
 include/hw/misc/npcm7xx_clk.h |   2 +
 include/hw/misc/npcm7xx_rng.h |  34 ++
 include/hw/timer/npcm7xx_timer.h  |  48 ++-
 hw/arm/npcm7xx.c  | 126 ++-
 hw/gpio/npcm7xx_gpio.c| 424 ++
 hw/misc/npcm7xx_clk.c |  28 ++
 hw/misc/npcm7xx_rng.c | 180 +
 hw/timer/npcm7xx_timer.c  | 270 +++---
 hw/usb/hcd-ehci-sysbus.c  |  19 +
 tests/qtest/npcm7xx_gpio-test.c   | 385 
 tests/qtest/npcm7xx_rng-test.c| 278 ++
 tests/qtest/npcm7xx_watchdog_timer-test.c | 313 
 MAINTAINERS   |   1 +
 hw/gpio/meson.build   |   1 +
 hw/gpio/trace-events  |   7 +
 hw/misc/meson.build   |   1 +
 hw/misc/trace-events  |   4 +
 tests/qtest/meson.build   |   3 +
 22 files changed, 2133 insertions(+), 61 deletions(-)
 create mode 100644 include/hw/gpio/npcm7xx_gpio.h
 create mode 100644 include/hw/misc/npcm7xx_rng.h
 create mode 100644 hw/gpio/npcm7xx_gpio.c
 create mode 100644 hw/misc/npcm7xx_rng.c
 create mode 100644 tests/qtest/npcm7xx_gpio-test.c
 create mode 100644 tests/qtest/npcm7xx_rng-test.c
 create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c

-- 
2.29.0.rc1.297.gfa9743e501-goog




Re: [PATCH 4/6] hw/misc: Add npcm7xx random number generator

2020-10-20 Thread Havard Skinnemoen
On Tue, Oct 20, 2020 at 6:02 AM Peter Maydell  wrote:
>
> On Fri, 9 Oct 2020 at 00:22, Havard Skinnemoen  wrote:
> >
> > The RNG module returns a byte of randomness when the Data Valid bit is
> > set.
> >
> > This implementation ignores the prescaler setting, and loads a new value
> > into RNGD every time RNGCS is read while the RNG is enabled and random
> > data is available.
> >
> > A qtest featuring some simple randomness tests is included.
> >
> > Reviewed-by: Tyrone Ting 
> > Signed-off-by: Havard Skinnemoen 
>
>
> > +static const VMStateDescription vmstate_npcm7xx_rng = {
> > +.name = "npcm7xx-rng",
> > +.version_id = 0,
> > +.minimum_version_id = 0,
> > +.fields = (VMStateField[]) {
> > +VMSTATE_UINT8(rngcs, NPCM7xxRNGState),
> > +VMSTATE_UINT8(rngd, NPCM7xxRNGState),
> > +VMSTATE_UINT8(rngmode, NPCM7xxRNGState),
> > +},
>
> This is missing the VMSTATE_END_OF_LIST() terminator.
>
> > +};
> > +
>
> > --- /dev/null
> > +++ b/tests/qtest/npcm7xx_rng-test.c
> > @@ -0,0 +1,278 @@
> > +/*
> > + * QTest testcase for the Nuvoton NPCM7xx Random Number Generator
> > + *
> > + * Copyright 2020 Google LLC
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License as published by the
> > + * Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful, but 
> > WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> > + * for more details.
> > + */
> > +
> > +#include 
> > +
> > +#include "qemu/osdep.h"
>
> osdep.h must always be the first #include line, before anything
> else, including system includes.
>
> > + * Verifies that the first data byte collected after enabling the RNG 
> > satisfies
> > + * a monobit test.
>
> Some of this "is this really a random number" testing seems a bit
> overkill given that the RNG device is just plumbing through the
> qemu_guest_getrandom() result, but since you've written the code
> we may as well keep it :-)

You may be right, though there were a couple of reasons why I added it.

One is that rngd was complaining about /dev/hwrng failing randomness
tests, so I wanted to make sure my device wasn't doing anything to
ruin the randomness. In the end, it turned out to be a kernel bug:
https://lkml.org/lkml/2020/9/23/1021

Another reason is that the value from qemu_guest_getrandom() isn't
consumed directly when reading the data register; it's latched when
reading the status register and returned on the next read from the
data register. So it's possible to imagine a bug causing the same
value to be returned over and over, which should cause the randomness
test to fail.

> If you fix the #include order and the missing terminator then

Will do, thanks!

> Reviewed-by: Peter Maydell 
>
> thanks
> -- PMM



[PATCH 6/6] hw/gpio: Add GPIO model for Nuvoton NPCM7xx

2020-10-08 Thread Havard Skinnemoen via
The NPCM7xx chips have multiple GPIO controllers that are mostly
identical except for some minor differences like the reset values of
some registers. Each controller controls up to 32 pins.

Each individual pin is modeled as a pair of unnamed GPIOs -- one for
emitting the actual pin state, and one for driving the pin externally.
Like the nRF51 GPIO controller, a gpio level may be negative, which
means the pin is not driven, or floating.

Reviewed-by: Tyrone Ting 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst |   2 +-
 include/hw/arm/npcm7xx.h|   2 +
 include/hw/gpio/npcm7xx_gpio.h  |  55 +
 hw/arm/npcm7xx.c|  80 +++
 hw/gpio/npcm7xx_gpio.c  | 409 
 tests/qtest/npcm7xx_gpio-test.c | 385 ++
 hw/gpio/meson.build |   1 +
 hw/gpio/trace-events|   7 +
 tests/qtest/meson.build |   1 +
 9 files changed, 941 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/gpio/npcm7xx_gpio.h
 create mode 100644 hw/gpio/npcm7xx_gpio.c
 create mode 100644 tests/qtest/npcm7xx_gpio-test.c

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index 99fc61c740..b00d405d52 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -40,11 +40,11 @@ Supported devices
  * Flash Interface Unit (FIU; no protection features)
  * Random Number Generator (RNG)
  * USB host (USBH)
+ * GPIO controller
 
 Missing devices
 ---
 
- * GPIO controller
  * LPC/eSPI host-to-BMC interface, including
 
* Keyboard and mouse controller interface (KBCI)
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index aeee1beaaa..5469247e38 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -18,6 +18,7 @@
 
 #include "hw/boards.h"
 #include "hw/cpu/a9mpcore.h"
+#include "hw/gpio/npcm7xx_gpio.h"
 #include "hw/mem/npcm7xx_mc.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
@@ -79,6 +80,7 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
 NPCM7xxRNGState rng;
+NPCM7xxGPIOStategpio[8];
 EHCISysBusState ehci;
 OHCISysBusState ohci;
 NPCM7xxFIUState fiu[2];
diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h
new file mode 100644
index 00..b1d771bd77
--- /dev/null
+++ b/include/hw/gpio/npcm7xx_gpio.h
@@ -0,0 +1,55 @@
+/*
+ * Nuvoton NPCM7xx General Purpose Input / Output (GPIO)
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef NPCM7XX_GPIO_H
+#define NPCM7XX_GPIO_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/* Number of pins managed by each controller. */
+#define NPCM7XX_GPIO_NR_PINS (32)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_GPIO_NR_REGS (0x80 / sizeof(uint32_t))
+
+typedef struct NPCM7xxGPIOState {
+SysBusDevice parent;
+
+/* Properties to be defined by the SoC */
+uint32_t reset_pu;
+uint32_t reset_pd;
+uint32_t reset_osrc;
+uint32_t reset_odsc;
+
+MemoryRegion mmio;
+
+qemu_irq irq;
+qemu_irq output[NPCM7XX_GPIO_NR_PINS];
+
+uint32_t pin_level;
+uint32_t ext_level;
+uint32_t ext_driven;
+
+uint32_t regs[NPCM7XX_GPIO_NR_REGS];
+} NPCM7xxGPIOState;
+
+#define TYPE_NPCM7XX_GPIO "npcm7xx-gpio"
+#define NPCM7XX_GPIO(obj) \
+OBJECT_CHECK(NPCM7xxGPIOState, (obj), TYPE_NPCM7XX_GPIO)
+
+#endif /* NPCM7XX_GPIO_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index ab37442d9c..67a552c279 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -96,6 +96,14 @@ enum NPCM7xxInterrupt {
 NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
 NPCM7XX_EHCI_IRQ= 61,
 NPCM7XX_OHCI_IRQ= 62,
+NPCM7XX_GPIO0_IRQ   = 116,
+NPCM7XX_GPIO1_IRQ,
+NPCM7XX_GPIO2_IRQ,
+NPCM7XX_GPIO3_IRQ,
+NPCM7XX_GPIO4_IRQ,
+NPCM7XX_GPIO5_IRQ,
+NPCM7XX_GPIO6_IRQ,
+NPCM7XX_GPIO7_IRQ,
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -130,6 +138,55 @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
 0xb800, /* CS3 */
 };
 
+static const struct {
+hwaddr regs_addr;
+uint32_t unconnected_pins;
+uint32_t reset_pu;
+uint32_t reset_pd;
+uint32_t reset_osr

[PATCH 5/6] hw/arm/npcm7xx: Add EHCI and OHCI controllers

2020-10-08 Thread Havard Skinnemoen via
The NPCM730 and NPCM750 chips have a single USB host port shared between
a USB 2.0 EHCI host controller and a USB 1.1 OHCI host controller. This
adds support for both of them.

Testing notes:
  * With -device usb-kbd, qemu will automatically insert a full-speed
hub, and the keyboard becomes controlled by the OHCI controller.
  * With -device usb-kbd,bus=usb-bus.0,port=1, the keyboard is directly
attached to the port without any hubs, and the device becomes
controlled by the EHCI controller since it's high speed capable.
  * With -device usb-kbd,bus=usb-bus.0,port=1,usb_version=1, the
keyboard is directly attached to the port, but it only advertises
itself as full-speed capable, so it becomes controlled by the OHCI
controller.

In all cases, the keyboard device enumerates correctly.

Cc: Gerd Hoffmann 
Reviewed-by: Tyrone Ting 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst |  2 +-
 hw/usb/hcd-ehci.h   |  1 +
 include/hw/arm/npcm7xx.h|  4 
 hw/arm/npcm7xx.c| 27 +--
 hw/usb/hcd-ehci-sysbus.c| 19 +++
 5 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index 4342434df4..99fc61c740 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -39,6 +39,7 @@ Supported devices
  * OTP controllers (no protection features)
  * Flash Interface Unit (FIU; no protection features)
  * Random Number Generator (RNG)
+ * USB host (USBH)
 
 Missing devices
 ---
@@ -54,7 +55,6 @@ Missing devices
* eSPI slave interface
 
  * Ethernet controllers (GMAC and EMC)
- * USB host (USBH)
  * USB device (USBD)
  * SMBus controller (SMBF)
  * Peripheral SPI controller (PSPI)
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index fd122dd4cd..a173707d9b 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -344,6 +344,7 @@ struct EHCIPCIState {
 #define TYPE_PLATFORM_EHCI "platform-ehci-usb"
 #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
 #define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
+#define TYPE_NPCM7XX_EHCI "npcm7xx-ehci-usb"
 #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
 #define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
 #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 761f9b987e..aeee1beaaa 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -25,6 +25,8 @@
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "hw/ssi/npcm7xx_fiu.h"
+#include "hw/usb/hcd-ehci.h"
+#include "hw/usb/hcd-ohci.h"
 #include "target/arm/cpu.h"
 
 #define NPCM7XX_MAX_NUM_CPUS(2)
@@ -77,6 +79,8 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
 NPCM7xxRNGState rng;
+EHCISysBusState ehci;
+OHCISysBusState ohci;
 NPCM7xxFIUState fiu[2];
 } NPCM7xxState;
 
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index c4bbf3c7d5..ab37442d9c 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -46,6 +46,10 @@
 #define NPCM7XX_MC_BA   (0xf0824000)
 #define NPCM7XX_RNG_BA  (0xf000b000)
 
+/* USB Host modules */
+#define NPCM7XX_EHCI_BA (0xf0806000)
+#define NPCM7XX_OHCI_BA (0xf0807000)
+
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
 #define NPCM7XX_RAM3_SZ (4 * KiB)
@@ -90,6 +94,8 @@ enum NPCM7xxInterrupt {
 NPCM7XX_WDG0_IRQ= 47,   /* Timer Module 0 Watchdog */
 NPCM7XX_WDG1_IRQ,   /* Timer Module 1 Watchdog */
 NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
+NPCM7XX_EHCI_IRQ= 61,
+NPCM7XX_OHCI_IRQ= 62,
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -263,6 +269,9 @@ static void npcm7xx_init(Object *obj)
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
 }
 
+object_initialize_child(obj, "ehci", >ehci, TYPE_NPCM7XX_EHCI);
+object_initialize_child(obj, "ohci", >ohci, TYPE_SYSBUS_OHCI);
+
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
 for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
 object_initialize_child(obj, npcm7xx_fiu[i].name, >fiu[i],
@@ -379,6 +388,22 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 sysbus_realize(SYS_BUS_DEVICE(>rng), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>rng), 0, NPCM7XX_RNG_BA);
 
+/* USB Host */
+object_property_set_bool(OBJECT(>ehci), "companion-enable", true,
+ _abort);
+sysbus_realize(SYS_BUS_DEVICE(>ehci), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>ehci), 0, NPCM7XX_EHCI_BA);
+sysbu

[PATCH 2/6] Move npcm7xx_timer_reached_zero call out of npcm7xx_timer_pause

2020-10-08 Thread Havard Skinnemoen via
This allows us to reuse npcm7xx_timer_pause for the watchdog timer.

Signed-off-by: Havard Skinnemoen 
---
 hw/timer/npcm7xx_timer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
index 5703e43d40..2df9e3e496 100644
--- a/hw/timer/npcm7xx_timer.c
+++ b/hw/timer/npcm7xx_timer.c
@@ -157,9 +157,6 @@ static void npcm7xx_timer_pause(NPCM7xxTimer *t)
 timer_del(>qtimer);
 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 t->remaining_ns = t->expires_ns - now;
-if (t->remaining_ns <= 0) {
-npcm7xx_timer_reached_zero(t);
-}
 }
 
 /*
@@ -239,6 +236,9 @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, 
uint32_t new_tcsr)
 } else {
 t->tcsr &= ~NPCM7XX_TCSR_CACT;
 npcm7xx_timer_pause(t);
+if (t->remaining_ns <= 0) {
+npcm7xx_timer_reached_zero(t);
+}
 }
 }
 }
-- 
2.28.0.1011.ga647a8990f-goog




[PATCH 4/6] hw/misc: Add npcm7xx random number generator

2020-10-08 Thread Havard Skinnemoen via
The RNG module returns a byte of randomness when the Data Valid bit is
set.

This implementation ignores the prescaler setting, and loads a new value
into RNGD every time RNGCS is read while the RNG is enabled and random
data is available.

A qtest featuring some simple randomness tests is included.

Reviewed-by: Tyrone Ting 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst|   2 +-
 include/hw/arm/npcm7xx.h   |   2 +
 include/hw/misc/npcm7xx_rng.h  |  34 
 hw/arm/npcm7xx.c   |   7 +-
 hw/misc/npcm7xx_rng.c  | 179 +
 tests/qtest/npcm7xx_rng-test.c | 278 +
 hw/misc/meson.build|   1 +
 hw/misc/trace-events   |   4 +
 tests/qtest/meson.build|   1 +
 9 files changed, 506 insertions(+), 2 deletions(-)
 create mode 100644 include/hw/misc/npcm7xx_rng.h
 create mode 100644 hw/misc/npcm7xx_rng.c
 create mode 100644 tests/qtest/npcm7xx_rng-test.c

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index e3e1a3a3a7..4342434df4 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -38,6 +38,7 @@ Supported devices
  * DDR4 memory controller (dummy interface indicating memory training is done)
  * OTP controllers (no protection features)
  * Flash Interface Unit (FIU; no protection features)
+ * Random Number Generator (RNG)
 
 Missing devices
 ---
@@ -59,7 +60,6 @@ Missing devices
  * Peripheral SPI controller (PSPI)
  * Analog to Digital Converter (ADC)
  * SD/MMC host
- * Random Number Generator (RNG)
  * PECI interface
  * Pulse Width Modulation (PWM)
  * Tachometer
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 13106af215..761f9b987e 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -21,6 +21,7 @@
 #include "hw/mem/npcm7xx_mc.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
+#include "hw/misc/npcm7xx_rng.h"
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "hw/ssi/npcm7xx_fiu.h"
@@ -75,6 +76,7 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState key_storage;
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
+NPCM7xxRNGState rng;
 NPCM7xxFIUState fiu[2];
 } NPCM7xxState;
 
diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h
new file mode 100644
index 00..5e85fd439d
--- /dev/null
+++ b/include/hw/misc/npcm7xx_rng.h
@@ -0,0 +1,34 @@
+/*
+ * Nuvoton NPCM7xx Random Number Generator.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_RNG_H
+#define NPCM7XX_RNG_H
+
+#include "hw/sysbus.h"
+
+typedef struct NPCM7xxRNGState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint8_t rngcs;
+uint8_t rngd;
+uint8_t rngmode;
+} NPCM7xxRNGState;
+
+#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
+#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG)
+
+#endif /* NPCM7XX_RNG_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 472efeaf3d..c4bbf3c7d5 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -44,6 +44,7 @@
 #define NPCM7XX_GCR_BA  (0xf080)
 #define NPCM7XX_CLK_BA  (0xf0801000)
 #define NPCM7XX_MC_BA   (0xf0824000)
+#define NPCM7XX_RNG_BA  (0xf000b000)
 
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
@@ -256,6 +257,7 @@ static void npcm7xx_init(Object *obj)
 object_initialize_child(obj, "otp2", >fuse_array,
 TYPE_NPCM7XX_FUSE_ARRAY);
 object_initialize_child(obj, "mc", >mc, TYPE_NPCM7XX_MC);
+object_initialize_child(obj, "rng", >rng, TYPE_NPCM7XX_RNG);
 
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
@@ -373,6 +375,10 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
serial_hd(i), DEVICE_LITTLE_ENDIAN);
 }
 
+/* Random Number Generator. Cannot fail. */
+sysbus_realize(SYS_BUS_DEVICE(>rng), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>rng), 0, NPCM7XX_RNG_BA);
+
 /*
  * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
  * specified, but this is a programming error.
@@ -411,7 +417,6 @@ static void npcm7xx

[PATCH 1/6] tests/qtest: Add npcm7xx timer test

2020-10-08 Thread Havard Skinnemoen via
This test exercises the various modes of the npcm7xx timer. In
particular, it triggers the bug found by the fuzzer, as reported here:

https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html

It also found several other bugs, especially related to interrupt
handling.

The test exercises all the timers in all the timer modules, which
expands to 180 test cases in total.

Reviewed-by: Tyrone Ting 
Signed-off-by: Havard Skinnemoen 
---
 tests/qtest/npcm7xx_timer-test.c | 562 +++
 tests/qtest/meson.build  |   1 +
 2 files changed, 563 insertions(+)
 create mode 100644 tests/qtest/npcm7xx_timer-test.c

diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
new file mode 100644
index 00..f08b0cd62a
--- /dev/null
+++ b/tests/qtest/npcm7xx_timer-test.c
@@ -0,0 +1,562 @@
+/*
+ * QTest testcase for the Nuvoton NPCM7xx Timer
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/timer.h"
+#include "libqtest-single.h"
+
+#define TIM_REF_HZ  (2500)
+
+/* Bits in TCSRx */
+#define CEN BIT(30)
+#define IE  BIT(29)
+#define MODE_ONESHOT(0 << 27)
+#define MODE_PERIODIC   (1 << 27)
+#define CRSTBIT(26)
+#define CACTBIT(25)
+#define PRESCALE(x) (x)
+
+/* Registers shared between all timers in a module. */
+#define TISR0x18
+#define WTCR0x1c
+# define WTCLK(x)   ((x) << 10)
+
+/* Power-on default; used to re-initialize timers before each test. */
+#define TCSR_DEFAULTPRESCALE(5)
+
+/* Register offsets for a timer within a timer block. */
+typedef struct Timer {
+unsigned int tcsr_offset;
+unsigned int ticr_offset;
+unsigned int tdr_offset;
+} Timer;
+
+/* A timer block containing 5 timers. */
+typedef struct TimerBlock {
+int irq_base;
+uint64_t base_addr;
+} TimerBlock;
+
+/* Testdata for testing a particular timer within a timer block. */
+typedef struct TestData {
+const TimerBlock *tim;
+const Timer *timer;
+} TestData;
+
+const TimerBlock timer_block[] = {
+{
+.irq_base   = 32,
+.base_addr  = 0xf0008000,
+},
+{
+.irq_base   = 37,
+.base_addr  = 0xf0009000,
+},
+{
+.irq_base   = 42,
+.base_addr  = 0xf000a000,
+},
+};
+
+const Timer timer[] = {
+{
+.tcsr_offset= 0x00,
+.ticr_offset= 0x08,
+.tdr_offset = 0x10,
+}, {
+.tcsr_offset= 0x04,
+.ticr_offset= 0x0c,
+.tdr_offset = 0x14,
+}, {
+.tcsr_offset= 0x20,
+.ticr_offset= 0x28,
+.tdr_offset = 0x30,
+}, {
+.tcsr_offset= 0x24,
+.ticr_offset= 0x2c,
+.tdr_offset = 0x34,
+}, {
+.tcsr_offset= 0x40,
+.ticr_offset= 0x48,
+.tdr_offset = 0x50,
+},
+};
+
+/* Returns the index of the timer block. */
+static int tim_index(const TimerBlock *tim)
+{
+ptrdiff_t diff = tim - timer_block;
+
+g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
+
+return diff;
+}
+
+/* Returns the index of a timer within a timer block. */
+static int timer_index(const Timer *t)
+{
+ptrdiff_t diff = t - timer;
+
+g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
+
+return diff;
+}
+
+/* Returns the irq line for a given timer. */
+static int tim_timer_irq(const TestData *td)
+{
+return td->tim->irq_base + timer_index(td->timer);
+}
+
+/* Register read/write accessors. */
+
+static void tim_write(const TestData *td,
+  unsigned int offset, uint32_t value)
+{
+writel(td->tim->base_addr + offset, value);
+}
+
+static uint32_t tim_read(const TestData *td, unsigned int offset)
+{
+return readl(td->tim->base_addr + offset);
+}
+
+static void tim_write_tcsr(const TestData *td, uint32_t value)
+{
+tim_write(td, td->timer->tcsr_offset, value);
+}
+
+static uint32_t tim_read_tcsr(const TestData *td)
+{
+return tim_read(td, td->timer->tcsr_offset);
+}
+
+static void tim_write_ticr(const TestData *td, uint32_t value)
+{
+tim_write(td, td->timer->ticr_offset, value);
+}
+
+static uint32_t tim_read_ticr(const TestData *td)
+{
+return tim_read(td, td->timer->ticr_offset);
+}
+
+static uint32_t tim_read_tdr(const TestData *td)
+{
+return tim_re

[PATCH 3/6] hw/timer: Adding watchdog for NPCM7XX Timer.

2020-10-08 Thread Havard Skinnemoen via
From: Hao Wu 

The watchdog is part of NPCM7XX's timer module. Its behavior is
controlled by the WTCR register in the timer.

When enabled, the watchdog issues an interrupt signal after a pre-set
amount of cycles, and issues a reset signal shortly after that.

Reviewed-by: Tyrone Ting 
Signed-off-by: Hao Wu 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/misc/npcm7xx_clk.h |   9 +
 include/hw/timer/npcm7xx_timer.h  |  43 ++-
 hw/arm/npcm7xx.c  |  11 +
 hw/misc/npcm7xx_clk.c |  20 ++
 hw/timer/npcm7xx_timer.c  | 275 +++
 tests/qtest/npcm7xx_watchdog_timer-test.c | 313 ++
 MAINTAINERS   |   1 +
 tests/qtest/meson.build   |   1 +
 8 files changed, 620 insertions(+), 53 deletions(-)
 create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c

diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
index cdcc9e8534..483028cf63 100644
--- a/include/hw/misc/npcm7xx_clk.h
+++ b/include/hw/misc/npcm7xx_clk.h
@@ -42,6 +42,15 @@ typedef struct NPCM7xxCLKState {
 int64_t ref_ns;
 } NPCM7xxCLKState;
 
+/**
+ * npcm7xx_clk_perform_watchdog_reset - Perform watchdog reset action generated
+ * by a watchdog event.
+ * @clk: The clock module that connects to the watchdog.
+ * @watchdog_index: The index of the watchdog that triggered the reset action.
+ */
+void npcm7xx_clk_perform_watchdog_reset(NPCM7xxCLKState *clk,
+int watchdog_index);
+
 #define TYPE_NPCM7XX_CLK "npcm7xx-clk"
 #define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
 
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
index 878a365a79..3adeb56f3b 100644
--- a/include/hw/timer/npcm7xx_timer.h
+++ b/include/hw/timer/npcm7xx_timer.h
@@ -29,14 +29,27 @@
  */
 #define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
 
+/* The basic watchdog timer period is 2^14 clock cycles. */
+#define NPCM7XX_WATCHDOG_BASETIME_SHIFT 14
+
 typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
 
 /**
- * struct NPCM7xxTimer - Individual timer state.
- * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * struct NPCM7xxBaseTimer - Basic functionality that both regular timer and
+ * watchdog timer use.
  * @qtimer: QEMU timer that notifies us on expiration.
  * @expires_ns: Absolute virtual expiration time.
  * @remaining_ns: Remaining time until expiration if timer is paused.
+ */
+typedef struct NPCM7xxBaseTimer {
+QEMUTimer   qtimer;
+int64_t expires_ns;
+int64_t remaining_ns;
+} NPCM7xxBaseTimer;
+
+/**
+ * struct NPCM7xxTimer - Individual timer state.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
  * @tcsr: The Timer Control and Status Register.
  * @ticr: The Timer Initial Count Register.
  */
@@ -44,20 +57,34 @@ typedef struct NPCM7xxTimer {
 NPCM7xxTimerCtrlState *ctrl;
 
 qemu_irqirq;
-QEMUTimer   qtimer;
-int64_t expires_ns;
-int64_t remaining_ns;
+NPCM7xxBaseTimer base_timer;
 
 uint32_ttcsr;
 uint32_tticr;
 } NPCM7xxTimer;
 
+/**
+ * struct NPCM7xxWatchdogTimer - The watchdog timer state.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @qtimer: QEMU timer that notifies us on expiration.
+ * @expires_ns: Absolute virtual expiration time.
+ * @remaining_ns: Remaining time until expiration if timer is paused.
+ * @wtcr: The Watchdog Timer Control Register.
+ */
+typedef struct NPCM7xxWatchdogTimer {
+NPCM7xxTimerCtrlState *ctrl;
+
+qemu_irqirq;
+NPCM7xxBaseTimer base_timer;
+
+uint32_twtcr;
+} NPCM7xxWatchdogTimer;
+
 /**
  * struct NPCM7xxTimerCtrlState - Timer Module device state.
  * @parent: System bus device.
  * @iomem: Memory region through which registers are accessed.
  * @tisr: The Timer Interrupt Status Register.
- * @wtcr: The Watchdog Timer Control Register.
  * @timer: The five individual timers managed by this module.
  */
 struct NPCM7xxTimerCtrlState {
@@ -65,10 +92,12 @@ struct NPCM7xxTimerCtrlState {
 
 MemoryRegion iomem;
 
+uint8_t index;
+NPCM7xxCLKState *clk;
 uint32_ttisr;
-uint32_twtcr;
 
 NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
+NPCM7xxWatchdogTimer watchdog_timer;
 };
 
 #define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 037f3a26f2..472efeaf3d 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -86,6 +86,9 @@ enum NPCM7xxInterrupt {
 NPCM7XX_TIMER12_IRQ,
 NPCM7XX_TIMER13_IRQ,
 NPCM7XX_TIMER14_IRQ,
+NPCM7XX_WDG0_IRQ= 47,   /* Timer Module 0 Watchdog */
+NPCM7XX_WDG1_IRQ,   /* Timer Module 1 Watchdog */
+NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
 };
 
 /* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
@@ -345,6 +3

[PATCH 0/6] Additional NPCM7xx features, devices and tests

2020-10-08 Thread Havard Skinnemoen via
This is an update to the initial NPCM7xx patch series adding

  - A timer test that found several issues that were fixed in the final version
of the series (see
https://www.mail-archive.com/qemu-devel@nongnu.org/msg739516.html).
  - Watchdog timer support. This makes the reboot command work.
  - Random Number Generator device.
  - USB Host Controllers.
  - GPIO Controllers.

The watchdog was implemented by my new teammate Hao Wu. Expect to see more
patches from him in the near future.

This series has also been pushed to the npcm7xx-5.2-update branch of my github
repository at

  https://github.com/hskinnemoen/qemu

Again, thanks a lot for reviewing!

Havard

Hao Wu (1):
  hw/timer: Adding watchdog for NPCM7XX Timer.

Havard Skinnemoen (5):
  tests/qtest: Add npcm7xx timer test
  Move npcm7xx_timer_reached_zero call out of npcm7xx_timer_pause
  hw/misc: Add npcm7xx random number generator
  hw/arm/npcm7xx: Add EHCI and OHCI controllers
  hw/gpio: Add GPIO model for Nuvoton NPCM7xx

 docs/system/arm/nuvoton.rst   |   6 +-
 hw/usb/hcd-ehci.h |   1 +
 include/hw/arm/npcm7xx.h  |   8 +
 include/hw/gpio/npcm7xx_gpio.h|  55 +++
 include/hw/misc/npcm7xx_clk.h |   9 +
 include/hw/misc/npcm7xx_rng.h |  34 ++
 include/hw/timer/npcm7xx_timer.h  |  43 +-
 hw/arm/npcm7xx.c  | 125 -
 hw/gpio/npcm7xx_gpio.c| 409 
 hw/misc/npcm7xx_clk.c |  20 +
 hw/misc/npcm7xx_rng.c | 179 +++
 hw/timer/npcm7xx_timer.c  | 279 +--
 hw/usb/hcd-ehci-sysbus.c  |  19 +
 tests/qtest/npcm7xx_gpio-test.c   | 385 +++
 tests/qtest/npcm7xx_rng-test.c| 278 +++
 tests/qtest/npcm7xx_timer-test.c  | 562 ++
 tests/qtest/npcm7xx_watchdog_timer-test.c | 313 
 MAINTAINERS   |   1 +
 hw/gpio/meson.build   |   1 +
 hw/gpio/trace-events  |   7 +
 hw/misc/meson.build   |   1 +
 hw/misc/trace-events  |   4 +
 tests/qtest/meson.build   |   4 +
 23 files changed, 2682 insertions(+), 61 deletions(-)
 create mode 100644 include/hw/gpio/npcm7xx_gpio.h
 create mode 100644 include/hw/misc/npcm7xx_rng.h
 create mode 100644 hw/gpio/npcm7xx_gpio.c
 create mode 100644 hw/misc/npcm7xx_rng.c
 create mode 100644 tests/qtest/npcm7xx_gpio-test.c
 create mode 100644 tests/qtest/npcm7xx_rng-test.c
 create mode 100644 tests/qtest/npcm7xx_timer-test.c
 create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c

-- 
2.28.0.1011.ga647a8990f-goog




Re: [RFC 0/3] QEMU as IPMI BMC emulator

2020-09-29 Thread Havard Skinnemoen
On Tue, Sep 29, 2020 at 10:46 AM Corey Minyard  wrote:
>
> On Mon, Sep 28, 2020 at 05:39:13PM -0700, Havard Skinnemoen via wrote:
> > This series briefly documents the existing IPMI device support for main
> > processor emulation, and goes on to propose a similar device structure to
> > emulate IPMI responder devices in BMC machines. This would allow a qemu
> > instance running BMC firmware to serve as an external BMC for a qemu 
> > instance
> > running server software.
> >
> > RFC only at this point because the series does not include actual code to
> > implement this. I'd appreciate some initial feedback on
> >
> > 1. Whether anyone else is interested in something like this.
>
> Though I've had this idea once or twice, I'm not working on real BMCs,
> so I didn't really pursue anything.  It's a good idea, I think, for the
> BMC developers, and possibly for system developers trying to do
> integration testing between BMCs and system software.
>
> You will need to tie in to more emulation than just the BMC side of the
> system interface registers.  You will also need to tie into GPIOs or
> whatnot for things like host reset.

That is true. The OpenIPMI protocol seems to handle at least some of
that, so it should be just a matter of adding a few GPIO inputs
(power, reset, ATTN, ...) to the ipmi-host-extern device.

I should add some more details about this to the doc.

> Power handling is going to be a bit weird.  The OpenIPMI emulator
> starts/stops qemu based upon power control.  It might be possible to do
> the same thing in this sort of emulator.

Hmm, yeah, I guess we can't kill/restart qemu from within qemu itself.
But perhaps stopping all CPUs and doing a full system reset might be a
good enough approximation for power-off?

> You may need extensions to the protocol, and that's fine.  I can't think
> of any at the moment, but you never know.

True.

> > 2. Completeness (i.e. anything that could be explained in more detail in the
> >docs).
>
> It's certainly a good start.  The second patch would be useful right
> now.  There are more details, of course, but I think that's covered in
> the man page under the various devices.

Thanks, I might send the second patch separately in the next round.

Havard

> Thanks,
>
> -corey
>
> > 3. Naming, and whether 'specs' is the right place to put this.
> > 4. Whether it's OK to enable the blockdiag sphinx extension (if not, I'll 
> > just
> >toss the block diagrams and turn the docs into walls of text).
> >
> > If this seems reasonable, I'll start working with one of my team mates on
> > implementing the common part, as well as the Nuvoton-specific responder 
> > device.
> > Possibly also an Aspeed device.
> >
> > Havard Skinnemoen (3):
> >   docs: enable sphinx blockdiag extension
> >   docs/specs: IPMI device emulation: main processor
> >   docs/specs: IPMI device emulation: BMC
> >
> >  docs/conf.py |   5 +-
> >  docs/specs/index.rst |   1 +
> >  docs/specs/ipmi.rst  | 183 +++
> >  3 files changed, 188 insertions(+), 1 deletion(-)
> >  create mode 100644 docs/specs/ipmi.rst
> >
> > --
> > 2.28.0.709.gb0816b6eb0-goog
> >
> >



Re: [RFC 0/3] QEMU as IPMI BMC emulator

2020-09-29 Thread Havard Skinnemoen
On Mon, Sep 28, 2020 at 10:27 PM Cédric Le Goater  wrote:
>
> On 9/29/20 2:39 AM, Havard Skinnemoen wrote:
> > This series briefly documents the existing IPMI device support for main
> > processor emulation, and goes on to propose a similar device structure to
> > emulate IPMI responder devices in BMC machines. This would allow a qemu
> > instance running BMC firmware to serve as an external BMC for a qemu 
> > instance
> > running server software.
>
> Great idea !
>
> I started working on this topic some years ago with the QEMU PowerNV machine
> and the Aspeed machine. They can communicate over network with this iBT device
> patch :
>
>   
> https://github.com/legoater/qemu/commit/3677ee52f75065b0f65f36382a62f080ac74d683

Oh, cool, if we split that into an Aspeed part and a VM protocol part,
it's basically what I had in mind. Are you planning to submit that, or
would it be OK if we base our work on it?

> This is good enough for the IPMI needs of OpenPOWER systems but the overall
> system lacks a few bus. An important one being the LPC bus which we use for
> PNOR mappings.

Right. Perhaps the next step should be an out-of-process flash protocol?

> So, we added a little PNOR device in the QEMU PowerNV machine and mapped
> its contents in the FW address space of the LPC bus. With the internal IPMI
> BMC simulator, it mimics well enough an OpenPOWER system from the host
> perspective.

Cool.

> All this to say, that if the goal is full system emulation, we should may
> be take another approach and work on the QEMU internals to run multiple
> architectures in the same QEMU binary.

Interesting. Will it be too slow to run the server and BMC in separate
processes?

We might actually be more interested in going the other way and move
more things out of process, as we start to tackle larger, more complex
systems.

> According to Peter, this is mostly a configure/build issue and cleanups
> are needed to remove the assumptions that were done with single arch
> binaries. A big task but not necessarily difficult. I will help for
> ARM and PPC !

It sounds great to have the option to simulate multiple architectures
in the same process, and getting rid of single-arch assumptions seems
like a nice cleanup. However, I'm hoping we'll still support
multi-process system emulation (and the MultiProcessQEMU work seems to
be moving in that direction as well).

> Anyhow, the IPMI documentation you provided is good to have.

If you like, I can split off patch 1-2 (or just 2) and post them
separately while we work on the BMC-side device emulation. If we
decide to keep patch 1 and the block diagrams, we probably need to do
something better for the font path.

Thanks,

Havard



[RFC 3/3] docs/specs: IPMI device emulation: BMC

2020-09-28 Thread Havard Skinnemoen via
The IPMI document is expanded with a proposal to emulate BMC-side IPMI
devices. This allows a QEMU instance running server software to interact
with a different QEMU instance running BMC firmware, which should
closely model how a real server system works.

The document as rendered by "make sphinxdocs" can be seen here:

https://hskinnemoen.github.io/qemu/specs/ipmi.html

Signed-off-by: Havard Skinnemoen 
---
 docs/specs/ipmi.rst | 83 +
 1 file changed, 83 insertions(+)

diff --git a/docs/specs/ipmi.rst b/docs/specs/ipmi.rst
index e0f9ab20ba..f45a452ef9 100644
--- a/docs/specs/ipmi.rst
+++ b/docs/specs/ipmi.rst
@@ -91,6 +91,89 @@ further delegated to an external emulator, or a real BMC. The
 ``ipmi-bmc-extern`` device has a required ``chardev`` property which specifies
 the communications channel to the external BMC.
 
+Baseband Management Controller (BMC) emulation
+==
+
+.. note:: This section is just a proposal. QEMU does not yet support BMC-side
+   IPMI emulation.
+
+This section is about emulation of IPMI-related devices in a System-on-Chip
+(SoC) used as a Baseband Management Controller. This is not to be confused with
+emulating the BMC device as seen by the main processor.
+
+SoCs that are designed to be used as a BMC often have dedicated hardware that
+allows them to be connected to one or more of the IPMI System Interfaces. The
+BMC-side hardware interface is not standardized, so each type of SoC may need
+its own device implementation in QEMU, for example:
+
+* ``aspeed-ipmi-ibt`` for emulating the Aspeed iBT peripheral.
+* ``npcm7xx-ipmi-kcs`` for emulating the Nuvoton NPCM7xx Host-to-BMC Keyboard
+  Controller Style (KCS) channels.
+
+.. blockdiag::
+
+blockdiag bmc_ipmi {
+orientation = portrait
+default_group_color = "none";
+class responder [color = lightblue];
+class host [color = salmon];
+
+host [color="aquamarine", label="External Host"]
+
+group {
+orientation = portrait
+
+group {
+orientation = portrait
+
+ipmi-responder [class = "responder"]
+npcm7xx-ipmi-kcs [class = "responder", stacked]
+
+ipmi-responder <- npcm7xx-ipmi-kcs [hstyle = generalization];
+}
+
+group {
+orientation = portrait
+
+ipmi-host [class = "host"];
+ipmi-host-sim [class = "host"];
+ipmi-host-extern [class = "host"];
+
+ipmi-host <- ipmi-host-sim [hstyle = generalization];
+ipmi-host <- ipmi-host-extern [hstyle = generalization];
+}
+
+ipmi-responder <-> ipmi-host
+}
+
+ipmi-host-extern <-> host [label="chardev"];
+}
+
+IPMI Responder
+--
+
+The software running on the BMC needs to intercept reads and writes to the
+system interface registers on the main processor. This requires special
+hardware that needs to be emulated by QEMU. We'll call these device *IPMI
+responders*.
+
+All *IPMI responder* devices should implement the ``ipmi-responder`` interface
+to allow an IPMI Host implementation to interact with them in a standard way.
+
+IPMI Host
+-
+
+Mirroring the main processor emulation, the responder devices delegate
+emulation of host behavior to a Host device that is a subclass of
+``ipmi-host``. This type of device is called a Host because that's what it
+looks like to the BMC guest software.
+
+The host behavior may be further delegated to an external emulator (e.g.
+another QEMU VM) through the ``ipmi-host-extern`` host implementation. This
+device has a required ``chardev`` property which specifies the communications
+channel to the external host. The wire format is the same as for
+``ipmi-bmc-extern``.
+
 Wire protocol
 =
 
-- 
2.28.0.709.gb0816b6eb0-goog




[RFC 2/3] docs/specs: IPMI device emulation: main processor

2020-09-28 Thread Havard Skinnemoen via
This document is an attempt to briefly document the existing IPMI
emulation support on the main processor. It provides the necessary
background for the BMC-side IPMI emulation proposed by the next patch.

Signed-off-by: Havard Skinnemoen 
---
 docs/specs/index.rst |   1 +
 docs/specs/ipmi.rst  | 100 +++
 2 files changed, 101 insertions(+)
 create mode 100644 docs/specs/ipmi.rst

diff --git a/docs/specs/index.rst b/docs/specs/index.rst
index 1b0eb979d5..9fdb94a578 100644
--- a/docs/specs/index.rst
+++ b/docs/specs/index.rst
@@ -14,5 +14,6 @@ Contents:
ppc-spapr-xive
ppc-spapr-numa
acpi_hw_reduced_hotplug
+   ipmi
tpm
acpi_hest_ghes
diff --git a/docs/specs/ipmi.rst b/docs/specs/ipmi.rst
new file mode 100644
index 00..e0f9ab20ba
--- /dev/null
+++ b/docs/specs/ipmi.rst
@@ -0,0 +1,100 @@
+=
+IPMI device emulation
+=
+
+QEMU supports emulating many types of machines. This includes machines that may
+serve as the main processor in an IPMI system, e.g. x86 or POWER server
+processors, as well as machines emulating ARM-based Baseband Management
+Controllers (BMCs), e.g. AST2xxx or NPCM7xxx systems-on-chip.
+
+Main processor emulation
+
+
+A server platform may include one of the following system interfaces for
+communicating with a BMC:
+
+* A Keyboard Controller Style (KCS) Interface, accessible via ISA
+  (``isa-ipmi-kcs``) or PCI (``pci-ipmi-kcs``).
+* A Block Transfer (BT) Interface, accessible via ISA (``isa-ipmi-bt``) or PCI
+  (``pci-ipmi-bt``).
+* An SMBus System Interface (SSIF; ``smbus-ipmi``).
+  
+These interfaces can all be emulated by QEMU. To emulate the behavior of the
+BMC, the messaging interface emulators use one of the following backends:
+
+* A BMC simulator running within the QEMU process (``ipmi-bmc-sim``).
+* An external BMC simulator or emulator, connected over a chardev
+  (``ipmi-bmc-extern``). `ipmi_sim
+  <https://github.com/wrouesnel/openipmi/blob/master/lanserv/README.ipmi_sim>`_
+  from OpenIPMI is an example external BMC emulator.
+
+The following diagram shows how these entities relate to each other.
+
+.. blockdiag::
+
+blockdiag main_processor_ipmi {
+orientation = portrait
+default_group_color = "none";
+class msgif [color = lightblue];
+class bmc [color = salmon];
+
+ipmi_sim [color="aquamarine", label="External BMC"]
+ipmi-bmc-extern <-> ipmi_sim [label="chardev"];
+
+group {
+orientation = portrait
+
+ipmi-interface <-> ipmi-bmc;
+
+group {
+orientation = portrait
+
+ipmi-interface [class = "msgif"];
+isa-ipmi-kcs [class="msgif", stacked];
+
+ipmi-interface <- isa-ipmi-kcs [hstyle = generalization];
+}
+
+
+group {
+orientation = portrait
+
+ipmi-bmc [class = "bmc"];
+ipmi-bmc-sim [class="bmc"];
+ipmi-bmc-extern [class="bmc"];
+
+ipmi-bmc <- ipmi-bmc-sim [hstyle = generalization];
+ipmi-bmc <- ipmi-bmc-extern [hstyle = generalization];
+}
+
+}
+}
+
+IPMI System Interfaces
+--
+
+The system software running on the main processor may use a *system interface*
+to communicate with the BMC. These are hardware devices attached to an ISA, PCI
+or i2c bus, and in QEMU, they all need to implement ``ipmi-interface``.
+This allows a BMC implementation to interact with the system interface in a
+standard way.
+
+IPMI BMC
+
+
+The system interface devices delegate emulation of BMC behavior to a BMC
+device, that is a subclass of ``ipmi-bmc``. This type of device is called
+a BMC because that's what it looks like to the main processor guest software.
+
+The BMC behavior may be simulated within the qemu process (``ipmi-bmc-sim``) or
+further delegated to an external emulator, or a real BMC. The
+``ipmi-bmc-extern`` device has a required ``chardev`` property which specifies
+the communications channel to the external BMC.
+
+Wire protocol
+=
+
+The wire protocol used between ``ipmi-bmc-extern`` and the external BMC
+emulator is defined by `README.vm
+<https://github.com/wrouesnel/openipmi/blob/master/lanserv/README.vm>`_ from
+the OpenIPMI project.
-- 
2.28.0.709.gb0816b6eb0-goog




[RFC 1/3] docs: enable sphinx blockdiag extension

2020-09-28 Thread Havard Skinnemoen via
Signed-off-by: Havard Skinnemoen 
---
 docs/conf.py | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/docs/conf.py b/docs/conf.py
index 0dbd90dc11..7c72f1a074 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -67,7 +67,10 @@ needs_sphinx = '1.6'
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
-extensions = ['kerneldoc', 'qmp_lexer', 'hxtool', 'depfile']
+extensions = ['kerneldoc', 'qmp_lexer', 'hxtool', 'depfile', 
'sphinxcontrib.blockdiag']
+
+# Fontpath for blockdiag (truetype font)
+blockdiag_fontpath = 
'/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf'
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
-- 
2.28.0.709.gb0816b6eb0-goog




[RFC 0/3] QEMU as IPMI BMC emulator

2020-09-28 Thread Havard Skinnemoen via
This series briefly documents the existing IPMI device support for main
processor emulation, and goes on to propose a similar device structure to
emulate IPMI responder devices in BMC machines. This would allow a qemu
instance running BMC firmware to serve as an external BMC for a qemu instance
running server software.

RFC only at this point because the series does not include actual code to
implement this. I'd appreciate some initial feedback on

1. Whether anyone else is interested in something like this.
2. Completeness (i.e. anything that could be explained in more detail in the
   docs).
3. Naming, and whether 'specs' is the right place to put this.
4. Whether it's OK to enable the blockdiag sphinx extension (if not, I'll just
   toss the block diagrams and turn the docs into walls of text).

If this seems reasonable, I'll start working with one of my team mates on
implementing the common part, as well as the Nuvoton-specific responder device.
Possibly also an Aspeed device.

Havard Skinnemoen (3):
  docs: enable sphinx blockdiag extension
  docs/specs: IPMI device emulation: main processor
  docs/specs: IPMI device emulation: BMC

 docs/conf.py |   5 +-
 docs/specs/index.rst |   1 +
 docs/specs/ipmi.rst  | 183 +++
 3 files changed, 188 insertions(+), 1 deletion(-)
 create mode 100644 docs/specs/ipmi.rst

-- 
2.28.0.709.gb0816b6eb0-goog




Re: [PATCH] hw/ssi/npcm7xx_fiu: Fix handling of unsigned integer

2020-09-19 Thread Havard Skinnemoen
On Sat, Sep 19, 2020 at 6:24 AM Philippe Mathieu-Daudé  wrote:
>
> Fix integer handling issues handling issue reported by Coverity:
>
>   hw/ssi/npcm7xx_fiu.c: 162 in npcm7xx_fiu_flash_read()
>   >>> CID 1432730:  Integer handling issues  (NEGATIVE_RETURNS)
>   >>> "npcm7xx_fiu_cs_index(fiu, f)" is passed to a parameter that cannot 
> be negative.
>   162 npcm7xx_fiu_select(fiu, npcm7xx_fiu_cs_index(fiu, f));
>
>   hw/ssi/npcm7xx_fiu.c: 221 in npcm7xx_fiu_flash_write()
>   218 cs_id = npcm7xx_fiu_cs_index(fiu, f);
>   219 trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, 
> cs_id, addr,
>   220   size, v);
>   >>> CID 1432729:  Integer handling issues  (NEGATIVE_RETURNS)
>   >>> "cs_id" is passed to a parameter that cannot be negative.
>   221 npcm7xx_fiu_select(fiu, cs_id);
>
> Since the index of the flash can not be negative, return an
> unsigned type.
>
> Reported-by: Coverity (CID 1432729 & 1432730: NEGATIVE_RETURNS)
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Havard Skinnemoen 

Thanks!

> ---
>  hw/ssi/npcm7xx_fiu.c | 12 ++--
>  hw/ssi/trace-events  |  2 +-
>  2 files changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
> index 104e8f2b963..5040132b074 100644
> --- a/hw/ssi/npcm7xx_fiu.c
> +++ b/hw/ssi/npcm7xx_fiu.c
> @@ -103,7 +103,8 @@ enum NPCM7xxFIURegister {
>   * Returns the index of flash in the fiu->flash array. This corresponds to 
> the
>   * chip select ID of the flash.
>   */
> -static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, NPCM7xxFIUFlash *flash)
> +static unsigned npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu,
> + NPCM7xxFIUFlash *flash)
>  {
>  int index = flash - fiu->flash;
>
> @@ -113,20 +114,19 @@ static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, 
> NPCM7xxFIUFlash *flash)
>  }
>
>  /* Assert the chip select specified in the UMA Control/Status Register. */
> -static void npcm7xx_fiu_select(NPCM7xxFIUState *s, int cs_id)
> +static void npcm7xx_fiu_select(NPCM7xxFIUState *s, unsigned cs_id)
>  {
>  trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id);
>
>  if (cs_id < s->cs_count) {
>  qemu_irq_lower(s->cs_lines[cs_id]);
> +s->active_cs = cs_id;
>  } else {
>  qemu_log_mask(LOG_GUEST_ERROR,
>"%s: UMA to CS%d; this module has only %d chip 
> selects",
>DEVICE(s)->canonical_path, cs_id, s->cs_count);
> -cs_id = -1;
> +s->active_cs = -1;
>  }
> -
> -s->active_cs = cs_id;
>  }
>
>  /* Deassert the currently active chip select. */
> @@ -206,7 +206,7 @@ static void npcm7xx_fiu_flash_write(void *opaque, hwaddr 
> addr, uint64_t v,
>  NPCM7xxFIUFlash *f = opaque;
>  NPCM7xxFIUState *fiu = f->fiu;
>  uint32_t dwr_cfg;
> -int cs_id;
> +unsigned cs_id;
>  int i;
>
>  if (fiu->active_cs != -1) {
> diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
> index 2f83ef833fb..612d3d6087a 100644
> --- a/hw/ssi/trace-events
> +++ b/hw/ssi/trace-events
> @@ -19,4 +19,4 @@ npcm7xx_fiu_deselect(const char *id, int cs) "%s deselect 
> CS%d"
>  npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s 
> offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
>  npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s 
> offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
>  npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int 
> size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" 
> PRIx64
> -npcm7xx_fiu_flash_write(const char *id, int cs, uint64_t addr, unsigned int 
> size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" 
> PRIx64
> +npcm7xx_fiu_flash_write(const char *id, unsigned cs, uint64_t addr, unsigned 
> int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 
> 0x%" PRIx64
> --
> 2.26.2
>



Re: [PULL 32/36] tests/acceptance: console boot tests for quanta-gsj

2020-09-18 Thread Havard Skinnemoen
On Fri, Sep 18, 2020 at 6:57 AM Philippe Mathieu-Daudé
 wrote:
>
> On Fri, Sep 18, 2020 at 3:52 PM Philippe Mathieu-Daudé
>  wrote:
> >
> > Hi Havard,
> >
> > On Mon, Sep 14, 2020 at 5:47 PM Peter Maydell  
> > wrote:
> > >
> > > From: Havard Skinnemoen 
> > >
> > > This adds two acceptance tests for the quanta-gsj machine.
> > >
> > > One test downloads a lightly patched openbmc flash image from github and
> > > verifies that it boots all the way to the login prompt.
> > >
> > > The other test downloads a kernel, initrd and dtb built from the same
> > > openbmc source and verifies that the kernel detects all CPUs and boots
> > > to the point where it can't find the root filesystem (because we have no
> > > flash image in this case).
> > >
> > > Reviewed-by: Philippe Mathieu-Daudé 
> > > Tested-by: Philippe Mathieu-Daudé 
> > > Signed-off-by: Havard Skinnemoen 
> > > Message-id: 20200911052101.2602693-15-hskinnem...@google.com
> > > Signed-off-by: Peter Maydell 
> > > ---
> > [...]
> > > +def test_arm_quanta_gsj_initrd(self):
> > > +"""
> > > +:avocado: tags=arch:arm
> > > +:avocado: tags=machine:quanta-gsj
> > > +"""
> > > +initrd_url = (
> > > +
> > > 'https://github.com/hskinnemoen/openbmc/releases/download/'
> > > +
> > > '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
> > > +initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
> > > +initrd_path = self.fetch_asset(initrd_url, 
> > > asset_hash=initrd_hash)
> > > +kernel_url = (
> > > +
> > > 'https://github.com/hskinnemoen/openbmc/releases/download/'
> > > +'20200711-gsj-qemu-0/uImage-gsj.bin')
> > > +kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
> > > +kernel_path = self.fetch_asset(kernel_url, 
> > > asset_hash=kernel_hash)
> > > +dtb_url = (
> > > +
> > > 'https://github.com/hskinnemoen/openbmc/releases/download/'
> > > +'20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
> > > +dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
> > > +dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
> > > +
> > > +self.vm.set_console()
> > > +kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
> > > +   'console=ttyS0,115200n8 '
> > > +   'earlycon=uart8250,mmio32,0xf0001000')
> > > +self.vm.add_args('-kernel', kernel_path,
> > > + '-initrd', initrd_path,
> > > + '-dtb', dtb_path,
> > > + '-append', kernel_command_line)
> > > +self.vm.launch()
> > > +
> > > +self.wait_for_console_pattern('Booting Linux on physical CPU 
> > > 0x0')
> > > +self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
> > > +self.wait_for_console_pattern(
> > > +'Give root password for system maintenance')
> >
> > This test is failing (timeout) on our CI:
>
> Oops I meant to keep the other one: test_arm_quanta_gsj
> (not test_arm_quanta_gsj_initrd).
>
> > https://gitlab.com/philmd/qemu/-/jobs/745483978#L857

Sorry about that. It only takes 60-ish seconds on my (admittedly beefy) machine.

Havard



Re: [PATCH v2] tests/acceptance: Skip slow quanta-gsj U-boot+Linux test

2020-09-18 Thread Havard Skinnemoen
On Fri, Sep 18, 2020 at 7:33 AM Philippe Mathieu-Daudé  wrote:
>
> The 'arm_quanta_gsj_initrd' test is timeouting on GitLab CI:
> https://gitlab.com/philmd/qemu/-/jobs/745483978#L846
> and also sometimes on my workstation, so proceed as with
> the other slow tests: do not run it by default.
> The test can still be run setting the AVOCADO_TIMEOUT_EXPECTED
> environment variable.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Havard Skinnemoen 
Tested-by: Havard Skinnemoen 

Thanks!

> ---
> Supersedes: <20200918142344.150749-1-f4...@amsat.org>
> ---
>  tests/acceptance/boot_linux_console.py | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/tests/acceptance/boot_linux_console.py 
> b/tests/acceptance/boot_linux_console.py
> index 4a366ce93e4..9b58f6f9003 100644
> --- a/tests/acceptance/boot_linux_console.py
> +++ b/tests/acceptance/boot_linux_console.py
> @@ -568,6 +568,7 @@ def test_arm_cubieboard_sata(self):
>  'sda')
>  # cubieboard's reboot is not functioning; omit reboot test.
>
> +@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
>  def test_arm_quanta_gsj(self):
>  """
>  :avocado: tags=arch:arm
> --
> 2.26.2
>



Re: [PATCH] tests/acceptance: Reduce quanta-gsj U-boot+Linux test time

2020-09-18 Thread Havard Skinnemoen
On Fri, Sep 18, 2020 at 7:27 AM Philippe Mathieu-Daudé  wrote:
>
> On 9/18/20 4:23 PM, Philippe Mathieu-Daudé wrote:
> > The 'arm_quanta_gsj_initrd' test is timeouting on GitLab CI:
> > https://gitlab.com/philmd/qemu/-/jobs/745483978#L846
> >
> > Use the same trick from the 'arm_quanta_gsj' test to reduce the
> > systemd services started and get quicker to the shell prompt.
> >
> > Signed-off-by: Philippe Mathieu-Daudé 
> > ---
> >  tests/acceptance/boot_linux_console.py | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/tests/acceptance/boot_linux_console.py 
> > b/tests/acceptance/boot_linux_console.py
> > index 4a366ce93e4..7748febbf54 100644
> > --- a/tests/acceptance/boot_linux_console.py
> > +++ b/tests/acceptance/boot_linux_console.py
> > @@ -638,6 +638,9 @@ def test_arm_quanta_gsj_initrd(self):
> >
> >  self.vm.set_console()
> >  kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
> > +   
> > 'initcall_blacklist=npcm_i2c_bus_driver_init '
> > +   'systemd.mask=systemd-random-seed.service '
> > +   'systemd.mask=dropbearkey.service '
> > 'console=ttyS0,115200n8 '
> > 'earlycon=uart8250,mmio32,0xf0001000')
> >  self.vm.add_args('-kernel', kernel_path,
> >
>
> Bah unfortunately this is still not enough :(

Right, this patch modifies the initrd test, but that's not the one
that timed out.

(10/40) 
tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_quanta_gsj:
 INTERRUPTED: Test interrupted by SIGTERM\nRunner error occurred:
Timeout reached\nOriginal status: ERROR\n{'name':
'10-tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_quanta_gsj',
'logdir': '/builds/philmd/qemu/build/tests/results/job-2020-09-18T13.41-b9...
(90.81 s)
 (11/40) 
tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_quanta_gsj_initrd:
 PASS (27.00 s)

Havard



Re: [PATCH v9 11/14] hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj

2020-09-12 Thread Havard Skinnemoen
On Fri, Sep 11, 2020 at 5:46 AM Philippe Mathieu-Daudé 
wrote:

>
>
> On 9/11/20 7:20 AM, Havard Skinnemoen via 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
> > qemu-system-arm -machine quanta-gsj -nographic \
> >   -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on
> >
> > Reviewed-by: Tyrone Ting 
> > Reviewed-by: Cédric Le Goater 
> > Tested-by: Cédric Le Goater 
> > Tested-by: Philippe Mathieu-Daudé 
> > Signed-off-by: Havard Skinnemoen 
> > ---
> >  hw/arm/npcm7xx_boards.c | 20 
> >  1 file changed, 20 insertions(+)
> >
> > diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
> > index b4c772d6b5..79e2e2744c 100644
> > --- a/hw/arm/npcm7xx_boards.c
> > +++ b/hw/arm/npcm7xx_boards.c
> > @@ -20,6 +20,7 @@
> >  #include "hw/arm/npcm7xx.h"
> >  #include "hw/core/cpu.h"
> >  #include "hw/loader.h"
> > +#include "hw/qdev-properties.h"
> >  #include "qapi/error.h"
> >  #include "qemu-common.h"
> >  #include "qemu/units.h"
> > @@ -55,6 +56,22 @@ static void npcm7xx_load_bootrom(MachineState
> *machine, NPCM7xxState *soc)
> >  }
> >  }
> >
> > +static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
> > +  const char *flash_type, DriveInfo
> *dinfo)
> > +{
> > +DeviceState *flash;
> > +qemu_irq flash_cs;
> > +
> > +flash = qdev_new(flash_type);
> > +if (dinfo) {
> > +qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
> > +}
> > +qdev_realize_and_unref(flash, BUS(fiu->spi), _fatal);
> > +
> > +flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
> > +qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
> > +}
> > +
> >  static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
> >  {
> >  memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA,
> dram);
> > @@ -92,6 +109,7 @@ static void npcm750_evb_init(MachineState *machine)
> >  qdev_realize(DEVICE(soc), NULL, _fatal);
> >
> >  npcm7xx_load_bootrom(machine, soc);
> > +npcm7xx_connect_flash(>fiu[0], 0, "w25q256", drive_get(IF_MTD,
> 0, 0));
>
> Nitpicking: add definition for '0' magic number
> (consider as future cleanup).
>

Thanks. I've made the change, but won't send it out until this series is
merged, or I'll fold it in if I need to do another iteration for other
reasons.

>  npcm7xx_load_kernel(machine, soc);
> >  }
> >
> > @@ -104,6 +122,8 @@ static void quanta_gsj_init(MachineState *machine)
> >  qdev_realize(DEVICE(soc), NULL, _fatal);
> >
> >  npcm7xx_load_bootrom(machine, soc);
> > +npcm7xx_connect_flash(>fiu[0], 0, "mx25l25635e",
> > +  drive_get(IF_MTD, 0, 0));
>
> Reviewed-by: Philippe Mathieu-Daudé 
>
> >  npcm7xx_load_kernel(machine, soc);
> >  }
> >
> >
>


[PATCH v9 14/14] tests/acceptance: console boot tests for quanta-gsj

2020-09-10 Thread Havard Skinnemoen via
This adds two acceptance tests for the quanta-gsj machine.

One test downloads a lightly patched openbmc flash image from github and
verifies that it boots all the way to the login prompt.

The other test downloads a kernel, initrd and dtb built from the same
openbmc source and verifies that the kernel detects all CPUs and boots
to the point where it can't find the root filesystem (because we have no
flash image in this case).

Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 tests/acceptance/boot_linux_console.py | 83 ++
 1 file changed, 83 insertions(+)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index aaa781a581..4a366ce93e 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -568,6 +568,89 @@ class BootLinuxConsole(LinuxKernelTest):
 'sda')
 # cubieboard's reboot is not functioning; omit reboot test.
 
+def test_arm_quanta_gsj(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:quanta-gsj
+"""
+# 25 MiB compressed, 32 MiB uncompressed.
+image_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
+image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
+image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
+image_name = 'obmc.mtd'
+image_path = os.path.join(self.workdir, image_name)
+archive.gzip_uncompress(image_path_gz, image_path)
+
+self.vm.set_console()
+drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
+self.vm.add_args('-drive', drive_args)
+self.vm.launch()
+
+# Disable drivers and services that stall for a long time during boot,
+# to avoid running past the 90-second timeout. These may be removed
+# as the corresponding device support is added.
+kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
+'console=${console} '
+'mem=${mem} '
+'initcall_blacklist=npcm_i2c_bus_driver_init '
+'systemd.mask=systemd-random-seed.service '
+'systemd.mask=dropbearkey.service '
+)
+
+self.wait_for_console_pattern('> BootBlock by Nuvoton')
+self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
+self.wait_for_console_pattern('>Skip DDR init.')
+self.wait_for_console_pattern('U-Boot ')
+interrupt_interactive_console_until_pattern(
+self, 'Hit any key to stop autoboot:', 'U-Boot>')
+exec_command_and_wait_for_pattern(
+self, "setenv bootargs ${bootargs} " + kernel_command_line,
+'U-Boot>')
+exec_command_and_wait_for_pattern(
+self, 'run romboot', 'Booting Kernel from flash')
+self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
+self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
+self.wait_for_console_pattern('OpenBMC Project Reference Distro')
+self.wait_for_console_pattern('gsj login:')
+
+def test_arm_quanta_gsj_initrd(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:quanta-gsj
+"""
+initrd_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
+initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
+initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+kernel_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/uImage-gsj.bin')
+kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
+kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+dtb_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
+dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
+dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'console=ttyS0,115200n8 '
+   'earlycon=uart8250,mmio32,0xf0001000')
+self.vm.add_args('-kernel', kernel_path,
+ '-initrd', initrd_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line)
+self.vm.launch()
+
+self.wait_for_console_pattern('Booting Linux

[PATCH v9 11/14] hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj

2020-09-10 Thread Havard Skinnemoen via
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 \
-drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Tested-by: Cédric Le Goater 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/npcm7xx_boards.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index b4c772d6b5..79e2e2744c 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -20,6 +20,7 @@
 #include "hw/arm/npcm7xx.h"
 #include "hw/core/cpu.h"
 #include "hw/loader.h"
+#include "hw/qdev-properties.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
 #include "qemu/units.h"
@@ -55,6 +56,22 @@ static void npcm7xx_load_bootrom(MachineState *machine, 
NPCM7xxState *soc)
 }
 }
 
+static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
+  const char *flash_type, DriveInfo *dinfo)
+{
+DeviceState *flash;
+qemu_irq flash_cs;
+
+flash = qdev_new(flash_type);
+if (dinfo) {
+qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
+}
+qdev_realize_and_unref(flash, BUS(fiu->spi), _fatal);
+
+flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
+qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
+}
+
 static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
 {
 memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
@@ -92,6 +109,7 @@ static void npcm750_evb_init(MachineState *machine)
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
 npcm7xx_load_bootrom(machine, soc);
+npcm7xx_connect_flash(>fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
 npcm7xx_load_kernel(machine, soc);
 }
 
@@ -104,6 +122,8 @@ static void quanta_gsj_init(MachineState *machine)
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
 npcm7xx_load_bootrom(machine, soc);
+npcm7xx_connect_flash(>fiu[0], 0, "mx25l25635e",
+  drive_get(IF_MTD, 0, 0));
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.28.0.526.ge36021eeef-goog




[PATCH v9 10/14] hw/ssi: NPCM7xx Flash Interface Unit device model

2020-09-10 Thread Havard Skinnemoen via
This implements a device model for the NPCM7xx SPI flash controller.

Direct reads and writes, and user-mode transactions have been tested in
various modes. Protection features are not implemented yet.

All the FIU instances are available in the SoC's address space,
regardless of whether or not they're connected to actual flash chips.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Tested-by: Alexander Bulekov 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h |   2 +
 include/hw/ssi/npcm7xx_fiu.h |  73 +
 hw/arm/npcm7xx.c |  58 
 hw/ssi/npcm7xx_fiu.c | 572 +++
 hw/arm/Kconfig   |   1 +
 hw/ssi/meson.build   |   1 +
 hw/ssi/trace-events  |  11 +
 7 files changed, 718 insertions(+)
 create mode 100644 include/hw/ssi/npcm7xx_fiu.h
 create mode 100644 hw/ssi/npcm7xx_fiu.c

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 9fa84a0702..78d0d78c52 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -23,6 +23,7 @@
 #include "hw/misc/npcm7xx_gcr.h"
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
+#include "hw/ssi/npcm7xx_fiu.h"
 #include "target/arm/cpu.h"
 
 #define NPCM7XX_MAX_NUM_CPUS(2)
@@ -73,6 +74,7 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState key_storage;
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
+NPCM7xxFIUState fiu[2];
 } NPCM7xxState;
 
 #define TYPE_NPCM7XX"npcm7xx"
diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h
new file mode 100644
index 00..a3a1704289
--- /dev/null
+++ b/include/hw/ssi/npcm7xx_fiu.h
@@ -0,0 +1,73 @@
+/*
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_FIU_H
+#define NPCM7XX_FIU_H
+
+#include "hw/ssi/ssi.h"
+#include "hw/sysbus.h"
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t))
+
+typedef struct NPCM7xxFIUState NPCM7xxFIUState;
+
+/**
+ * struct NPCM7xxFIUFlash - Per-chipselect flash controller state.
+ * @direct_access: Memory region for direct flash access.
+ * @fiu: Pointer to flash controller shared state.
+ */
+typedef struct NPCM7xxFIUFlash {
+MemoryRegion direct_access;
+NPCM7xxFIUState *fiu;
+} NPCM7xxFIUFlash;
+
+/**
+ * NPCM7xxFIUState - Device state for one Flash Interface Unit.
+ * @parent: System bus device.
+ * @mmio: Memory region for register access.
+ * @cs_count: Number of flash chips that may be connected to this module.
+ * @active_cs: Currently active chip select, or -1 if no chip is selected.
+ * @cs_lines: GPIO lines that may be wired to flash chips.
+ * @flash: Array of @cs_count per-flash-chip state objects.
+ * @spi: The SPI bus mastered by this controller.
+ * @regs: Register contents.
+ *
+ * Each FIU has a shared bank of registers, and controls up to four chip
+ * selects. Each chip select has a dedicated memory region which may be used to
+ * read and write the flash connected to that chip select as if it were memory.
+ */
+struct NPCM7xxFIUState {
+SysBusDevice parent;
+
+MemoryRegion mmio;
+
+int32_t cs_count;
+int32_t active_cs;
+qemu_irq *cs_lines;
+NPCM7xxFIUFlash *flash;
+
+SSIBus *spi;
+
+uint32_t regs[NPCM7XX_FIU_NR_REGS];
+};
+
+#define TYPE_NPCM7XX_FIU "npcm7xx-fiu"
+#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU)
+
+#endif /* NPCM7XX_FIU_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 6bb1693833..7884b2b03d 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -99,6 +99,39 @@ static const hwaddr npcm7xx_uart_addr[] = {
 0xf0004000,
 };
 
+/* Direct memory-mapped access to SPI0 CS0-1. */
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
+0x8000, /* CS0 */
+0x8800, /* CS1 */
+};
+
+/* Direct memory-mapped access to SPI3 CS0-3. */
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
+0xa000, /* CS0 */
+0xa800, /* CS1 */
+0xb000, /* CS2 */
+0xb800, /* CS3 */
+};
+
+static const struct {
+const char *name;
+hwaddr regs_addr;
+int cs_count;
+const hwaddr *flash_a

[PATCH v9 08/14] hw/nvram: NPCM7xx OTP device model

2020-09-10 Thread Havard Skinnemoen via
This supports reading and writing OTP fuses and keys. Only fuse reading
has been tested. Protection is not implemented.

Reviewed-by: Avi Fishman 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Tested-by: Alexander Bulekov 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h   |   3 +
 include/hw/nvram/npcm7xx_otp.h |  79 ++
 hw/arm/npcm7xx.c   |  29 +++
 hw/nvram/npcm7xx_otp.c | 440 +
 hw/nvram/meson.build   |   1 +
 5 files changed, 552 insertions(+)
 create mode 100644 include/hw/nvram/npcm7xx_otp.h
 create mode 100644 hw/nvram/npcm7xx_otp.c

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index ba7495869d..5816a07a72 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -20,6 +20,7 @@
 #include "hw/cpu/a9mpcore.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
+#include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "target/arm/cpu.h"
 
@@ -68,6 +69,8 @@ typedef struct NPCM7xxState {
 NPCM7xxGCRState gcr;
 NPCM7xxCLKState clk;
 NPCM7xxTimerCtrlState tim[3];
+NPCM7xxOTPState key_storage;
+NPCM7xxOTPState fuse_array;
 } NPCM7xxState;
 
 #define TYPE_NPCM7XX"npcm7xx"
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
new file mode 100644
index 00..156bbd151a
--- /dev/null
+++ b/include/hw/nvram/npcm7xx_otp.h
@@ -0,0 +1,79 @@
+/*
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_OTP_H
+#define NPCM7XX_OTP_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/* Each OTP module holds 8192 bits of one-time programmable storage */
+#define NPCM7XX_OTP_ARRAY_BITS (8192)
+#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
+
+/* Fuse array offsets */
+#define NPCM7XX_FUSE_FUSTRAP (0)
+#define NPCM7XX_FUSE_CP_FUSTRAP (12)
+#define NPCM7XX_FUSE_DAC_CALIB (16)
+#define NPCM7XX_FUSE_ADC_CALIB (24)
+#define NPCM7XX_FUSE_DERIVATIVE (64)
+#define NPCM7XX_FUSE_TEST_SIG (72)
+#define NPCM7XX_FUSE_DIE_LOCATION (74)
+#define NPCM7XX_FUSE_GP1 (80)
+#define NPCM7XX_FUSE_GP2 (128)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
+
+/**
+ * struct NPCM7xxOTPState - Device state for one OTP module.
+ * @parent: System bus device.
+ * @mmio: Memory region through which registers are accessed.
+ * @regs: Register contents.
+ * @array: OTP storage array.
+ */
+typedef struct NPCM7xxOTPState {
+SysBusDevice parent;
+
+MemoryRegion mmio;
+uint32_t regs[NPCM7XX_OTP_NR_REGS];
+uint8_t array[NPCM7XX_OTP_ARRAY_BYTES];
+} NPCM7xxOTPState;
+
+#define TYPE_NPCM7XX_OTP "npcm7xx-otp"
+#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP)
+
+#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage"
+#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array"
+
+typedef struct NPCM7xxOTPClass NPCM7xxOTPClass;
+
+/**
+ * npcm7xx_otp_array_write - ECC encode and write data to OTP array.
+ * @s: OTP module.
+ * @data: Data to be encoded and written.
+ * @offset: Offset of first byte to be written in the OTP array.
+ * @len: Number of bytes before ECC encoding.
+ *
+ * Each nibble of data is encoded into a byte, so the number of bytes written
+ * to the array will be @len * 2.
+ */
+extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
+unsigned int offset, unsigned int len);
+
+#endif /* NPCM7XX_OTP_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 9669ac5fa0..9166002598 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -34,6 +34,10 @@
 #define NPCM7XX_MMIO_BA (0x8000)
 #define NPCM7XX_MMIO_SZ (0x7ffd)
 
+/* OTP key storage and fuse strap array */
+#define NPCM7XX_OTP1_BA (0xf0189000)
+#define NPCM7XX_OTP2_BA (0xf018a000)
+
 /* Core system modules. */
 #define NPCM7XX_L2C_BA  (0xf03fc000)
 #define NPCM7XX_CPUP_BA (0xf03fe000)
@@ -144,6 +148,20 @@ void npcm7xx_load_kernel(MachineState *machine, 
NPCM7xxState *soc)
 arm_load_kernel(>cpu[0], machine, _binfo);
 }
 
+static void npcm7xx_init

[PATCH v9 05/14] hw/arm: Add two NPCM7xx-based machines

2020-09-10 Thread Havard Skinnemoen via
This adds two new machines, both supported by OpenBMC:

  - npcm750-evb: Nuvoton NPCM750 Evaluation Board.
  - quanta-gsj: A board with a NPCM730 chip.

They rely on the NPCM7xx SoC device to do the heavy lifting. They are
almost completely identical at the moment, apart from the SoC type,
which currently only changes the reset contents of one register
(GCR.MDLR), but they might grow apart a bit more as more functionality
is added.

Both machines can boot the Linux kernel into /bin/sh.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Tested-by: Alexander Bulekov 
Signed-off-by: Havard Skinnemoen 
---
 default-configs/arm-softmmu.mak |   1 +
 include/hw/arm/npcm7xx.h|  19 +
 hw/arm/npcm7xx_boards.c | 145 
 hw/arm/meson.build  |   2 +-
 4 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/npcm7xx_boards.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 8fc09a4a51..9a94ebd0be 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -27,6 +27,7 @@ CONFIG_GUMSTIX=y
 CONFIG_SPITZ=y
 CONFIG_TOSA=y
 CONFIG_Z2=y
+CONFIG_NPCM7XX=y
 CONFIG_COLLIE=y
 CONFIG_ASPEED_SOC=y
 CONFIG_NETDUINO2=y
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index e68d9c79e6..ba7495869d 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -35,6 +35,25 @@
 #define NPCM7XX_SMP_BOOTREG_ADDR(0xf080013c)  /* GCR.SCRPAD */
 #define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100)  /* GIC within A9 */
 
+typedef struct NPCM7xxMachine {
+MachineStateparent;
+} NPCM7xxMachine;
+
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
+#define NPCM7XX_MACHINE(obj)\
+OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
+
+typedef struct NPCM7xxMachineClass {
+MachineClassparent;
+
+const char  *soc_type;
+} NPCM7xxMachineClass;
+
+#define NPCM7XX_MACHINE_CLASS(klass)\
+OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE)
+#define NPCM7XX_MACHINE_GET_CLASS(obj)  \
+OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
+
 typedef struct NPCM7xxState {
 DeviceState parent;
 
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
new file mode 100644
index 00..939391c3a3
--- /dev/null
+++ b/hw/arm/npcm7xx_boards.c
@@ -0,0 +1,145 @@
+/*
+ * Machine definitions for boards featuring an NPCM7xx SoC.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "exec/address-spaces.h"
+#include "hw/arm/npcm7xx.h"
+#include "hw/core/cpu.h"
+#include "qapi/error.h"
+#include "qemu/units.h"
+
+#define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7
+#define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff
+
+static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
+{
+memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
+
+object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram),
+ _abort);
+}
+
+static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
+uint32_t hw_straps)
+{
+NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
+MachineClass *mc = >parent;
+Object *obj;
+
+if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
+error_report("This board can only be used with %s",
+ mc->default_cpu_type);
+exit(1);
+}
+
+obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc",
+_abort, NULL);
+object_property_set_uint(obj, "power-on-straps", hw_straps, _abort);
+
+return NPCM7XX(obj);
+}
+
+static void npcm750_evb_init(MachineState *machine)
+{
+NPCM7xxState *soc;
+
+soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS);
+npcm7xx_connect_dram(soc, machine->ram);
+qdev_realize(DEVICE(soc), NULL, _fatal);
+
+npcm7xx_load_kernel(machine, soc);
+}
+
+static void quanta_gsj_init(MachineState *machine)
+{
+NPCM7xxState *soc;
+
+soc = npcm7xx_cr

[PATCH v9 07/14] hw/arm: Load -bios image as a boot ROM for npcm7xx

2020-09-10 Thread Havard Skinnemoen via
If a -bios option is specified on the command line, load the image into
the internal ROM memory region, which contains the first instructions
run by the CPU after reset.

If -bios is not specified, the vbootrom included with qemu is loaded by
default.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/npcm7xx_boards.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 939391c3a3..b4c772d6b5 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -19,12 +19,42 @@
 #include "exec/address-spaces.h"
 #include "hw/arm/npcm7xx.h"
 #include "hw/core/cpu.h"
+#include "hw/loader.h"
 #include "qapi/error.h"
+#include "qemu-common.h"
 #include "qemu/units.h"
+#include "sysemu/sysemu.h"
 
 #define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7
 #define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff
 
+static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
+
+static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
+{
+g_autofree char *filename = NULL;
+int ret;
+
+if (!bios_name) {
+bios_name = npcm7xx_default_bootrom;
+}
+
+filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+if (!filename) {
+error_report("Could not find ROM image '%s'", bios_name);
+if (!machine->kernel_filename) {
+/* We can't boot without a bootrom or a kernel image. */
+exit(1);
+}
+return;
+}
+ret = load_image_mr(filename, >irom);
+if (ret < 0) {
+error_report("Failed to load ROM image '%s'", filename);
+exit(1);
+}
+}
+
 static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
 {
 memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
@@ -61,6 +91,7 @@ static void npcm750_evb_init(MachineState *machine)
 npcm7xx_connect_dram(soc, machine->ram);
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
+npcm7xx_load_bootrom(machine, soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
@@ -72,6 +103,7 @@ static void quanta_gsj_init(MachineState *machine)
 npcm7xx_connect_dram(soc, machine->ram);
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
+npcm7xx_load_bootrom(machine, soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.28.0.526.ge36021eeef-goog




[PATCH v9 12/14] hw/arm/npcm7xx: add board setup stub for CPU and UART clocks

2020-09-10 Thread Havard Skinnemoen via
When booting directly into a kernel, bypassing the boot loader, the CPU and
UART clocks are not set up correctly. This makes the system appear very
slow, and causes the initrd boot test to fail when optimization is off.

The UART clock must run at 24 MHz. The default 25 MHz reference clock
cannot achieve this, so switch to PLL2/2 @ 480 MHz, which works
perfectly with the default /20 divider.

The CPU clock should run at 800 MHz, so switch it to PLL1/2. PLL1 runs
at 800 MHz by default, so we need to double the feedback divider as well
to make it run at 1600 MHz (so PLL1/2 runs at 800 MHz).

We don't bother checking for PLL lock because we know our emulated PLLs
lock instantly.

Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h |  1 +
 hw/arm/npcm7xx.c | 32 
 2 files changed, 33 insertions(+)

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 78d0d78c52..13106af215 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -37,6 +37,7 @@
 #define NPCM7XX_SMP_LOADER_START(0x)  /* Boot ROM */
 #define NPCM7XX_SMP_BOOTREG_ADDR(0xf080013c)  /* GCR.SCRPAD */
 #define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100)  /* GIC within A9 */
+#define NPCM7XX_BOARD_SETUP_ADDR(0x1000)  /* Boot ROM */
 
 typedef struct NPCM7xxMachine {
 MachineStateparent;
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 7884b2b03d..037f3a26f2 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -55,6 +55,13 @@
 #define NPCM7XX_ROM_BA  (0x)
 #define NPCM7XX_ROM_SZ  (64 * KiB)
 
+/* Clock configuration values to be fixed up when bypassing bootloader */
+
+/* Run PLL1 at 1600 MHz */
+#define NPCM7XX_PLLCON1_FIXUP_VAL   (0x00402101)
+/* Run the CPU from PLL1 and UART from PLL2 */
+#define NPCM7XX_CLKSEL_FIXUP_VAL(0x004aaba9)
+
 /*
  * Interrupt lines going into the GIC. This does not include internal Cortex-A9
  * interrupts.
@@ -132,6 +139,29 @@ static const struct {
 },
 };
 
+static void npcm7xx_write_board_setup(ARMCPU *cpu,
+  const struct arm_boot_info *info)
+{
+uint32_t board_setup[] = {
+0xe59f0010, /* ldr r0, clk_base_addr */
+0xe59f1010, /* ldr r1, pllcon1_value */
+0xe5801010, /* str r1, [r0, #16] */
+0xe59f100c, /* ldr r1, clksel_value */
+0xe5801004, /* str r1, [r0, #4] */
+0xe12fff1e, /* bx lr */
+NPCM7XX_CLK_BA,
+NPCM7XX_PLLCON1_FIXUP_VAL,
+NPCM7XX_CLKSEL_FIXUP_VAL,
+};
+int i;
+
+for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
+board_setup[i] = tswap32(board_setup[i]);
+}
+rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
+   info->board_setup_addr);
+}
+
 static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
  const struct arm_boot_info *info)
 {
@@ -170,6 +200,8 @@ static struct arm_boot_info npcm7xx_binfo = {
 .gic_cpu_if_addr= NPCM7XX_GIC_CPU_IF_ADDR,
 .write_secondary_boot   = npcm7xx_write_secondary_boot,
 .board_id   = -1,
+.board_setup_addr   = NPCM7XX_BOARD_SETUP_ADDR,
+.write_board_setup  = npcm7xx_write_board_setup,
 };
 
 void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
-- 
2.28.0.526.ge36021eeef-goog




[PATCH v9 13/14] docs/system: Add Nuvoton machine documentation

2020-09-10 Thread Havard Skinnemoen via
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst | 92 +
 docs/system/target-arm.rst  |  1 +
 2 files changed, 93 insertions(+)
 create mode 100644 docs/system/arm/nuvoton.rst

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
new file mode 100644
index 00..e3e1a3a3a7
--- /dev/null
+++ b/docs/system/arm/nuvoton.rst
@@ -0,0 +1,92 @@
+Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``)
+=
+
+The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are
+designed to be used as Baseboard Management Controllers (BMCs) in various
+servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an
+assortment of peripherals targeted for either Enterprise or Data Center /
+Hyperscale applications. The former is a superset of the latter, so NPCM750 has
+all the peripherals of NPCM730 and more.
+
+.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/
+
+The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise
+segment. The following machines are based on this chip :
+
+- ``npcm750-evb``   Nuvoton NPCM750 Evaluation board
+
+The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and
+Hyperscale applications. The following machines are based on this chip :
+
+- ``quanta-gsj``Quanta GSJ server BMC
+
+There are also two more SoCs, NPCM710 and NPCM705, which are single-core
+variants of NPCM750 and NPCM730, respectively. These are currently not
+supported by QEMU.
+
+Supported devices
+-
+
+ * SMP (Dual Core Cortex-A9)
+ * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer
+   and Watchdog.
+ * SRAM, ROM and DRAM mappings
+ * System Global Control Registers (GCR)
+ * Clock and reset controller (CLK)
+ * Timer controller (TIM)
+ * Serial ports (16550-based)
+ * DDR4 memory controller (dummy interface indicating memory training is done)
+ * OTP controllers (no protection features)
+ * Flash Interface Unit (FIU; no protection features)
+
+Missing devices
+---
+
+ * GPIO controller
+ * LPC/eSPI host-to-BMC interface, including
+
+   * Keyboard and mouse controller interface (KBCI)
+   * Keyboard Controller Style (KCS) channels
+   * BIOS POST code FIFO
+   * System Wake-up Control (SWC)
+   * Shared memory (SHM)
+   * eSPI slave interface
+
+ * Ethernet controllers (GMAC and EMC)
+ * USB host (USBH)
+ * USB device (USBD)
+ * SMBus controller (SMBF)
+ * Peripheral SPI controller (PSPI)
+ * Analog to Digital Converter (ADC)
+ * SD/MMC host
+ * Random Number Generator (RNG)
+ * PECI interface
+ * Pulse Width Modulation (PWM)
+ * Tachometer
+ * PCI and PCIe root complex and bridges
+ * VDM and MCTP support
+ * Serial I/O expansion
+ * LPC/eSPI host
+ * Coprocessor
+ * Graphics
+ * Video capture
+ * Encoding compression engine
+ * Security features
+
+Boot options
+
+
+The Nuvoton machines can boot from an OpenBMC firmware image, or directly into
+a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and
+possibly others can be downloaded from the OpenPOWER jenkins :
+
+   https://openpower.xyz/
+
+The firmware image should be attached as an MTD drive. Example :
+
+.. code-block:: bash
+
+  $ qemu-system-arm -machine quanta-gsj -nographic \
+  -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw
+
+The default root password for test images is usually ``0penBmc``.
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index afdb37e738..fdcf25c237 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -86,6 +86,7 @@ undocumented; you can get a complete list by running
arm/musicpal
arm/gumstix
arm/nseries
+   arm/nuvoton
arm/orangepi
arm/palm
arm/xscale
-- 
2.28.0.526.ge36021eeef-goog




[PATCH v9 09/14] hw/mem: Stubbed out NPCM7xx Memory Controller model

2020-09-10 Thread Havard Skinnemoen via
This just implements the bare minimum to cause the boot block to skip
memory initialization.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Tested-by: Alexander Bulekov 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h|  2 +
 include/hw/mem/npcm7xx_mc.h | 36 
 hw/arm/npcm7xx.c|  6 +++
 hw/mem/npcm7xx_mc.c | 84 +
 hw/mem/meson.build  |  1 +
 5 files changed, 129 insertions(+)
 create mode 100644 include/hw/mem/npcm7xx_mc.h
 create mode 100644 hw/mem/npcm7xx_mc.c

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 5816a07a72..9fa84a0702 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -18,6 +18,7 @@
 
 #include "hw/boards.h"
 #include "hw/cpu/a9mpcore.h"
+#include "hw/mem/npcm7xx_mc.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
 #include "hw/nvram/npcm7xx_otp.h"
@@ -71,6 +72,7 @@ typedef struct NPCM7xxState {
 NPCM7xxTimerCtrlState tim[3];
 NPCM7xxOTPState key_storage;
 NPCM7xxOTPState fuse_array;
+NPCM7xxMCState  mc;
 } NPCM7xxState;
 
 #define TYPE_NPCM7XX"npcm7xx"
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
new file mode 100644
index 00..7ed38be243
--- /dev/null
+++ b/include/hw/mem/npcm7xx_mc.h
@@ -0,0 +1,36 @@
+/*
+ * Nuvoton NPCM7xx Memory Controller stub
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_MC_H
+#define NPCM7XX_MC_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/**
+ * struct NPCM7xxMCState - Device state for the memory controller.
+ * @parent: System bus device.
+ * @mmio: Memory region through which registers are accessed.
+ */
+typedef struct NPCM7xxMCState {
+SysBusDevice parent;
+
+MemoryRegion mmio;
+} NPCM7xxMCState;
+
+#define TYPE_NPCM7XX_MC "npcm7xx-mc"
+#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC)
+
+#endif /* NPCM7XX_MC_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 9166002598..6bb1693833 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -43,6 +43,7 @@
 #define NPCM7XX_CPUP_BA (0xf03fe000)
 #define NPCM7XX_GCR_BA  (0xf080)
 #define NPCM7XX_CLK_BA  (0xf0801000)
+#define NPCM7XX_MC_BA   (0xf0824000)
 
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
@@ -186,6 +187,7 @@ static void npcm7xx_init(Object *obj)
 TYPE_NPCM7XX_KEY_STORAGE);
 object_initialize_child(obj, "otp2", >fuse_array,
 TYPE_NPCM7XX_FUSE_ARRAY);
+object_initialize_child(obj, "mc", >mc, TYPE_NPCM7XX_MC);
 
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
@@ -261,6 +263,10 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>fuse_array), 0, NPCM7XX_OTP2_BA);
 npcm7xx_init_fuses(s);
 
+/* Fake Memory Controller (MC). Cannot fail. */
+sysbus_realize(SYS_BUS_DEVICE(>mc), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>mc), 0, NPCM7XX_MC_BA);
+
 /* Timer Modules (TIM). Cannot fail. */
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
new file mode 100644
index 00..0435d06ab4
--- /dev/null
+++ b/hw/mem/npcm7xx_mc.c
@@ -0,0 +1,84 @@
+/*
+ * Nuvoton NPCM7xx Memory Controller stub
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/mem/npcm7xx_mc.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include &quo

[PATCH v9 04/14] hw/arm: Add NPCM730 and NPCM750 SoC models

2020-09-10 Thread Havard Skinnemoen via
The Nuvoton NPCM7xx SoC family are used to implement Baseboard
Management Controllers in servers. While the family includes four SoCs,
this patch implements limited support for two of them: NPCM730 (targeted
for Data Center applications) and NPCM750 (targeted for Enterprise
applications).

This patch includes little more than the bare minimum needed to boot a
Linux kernel built with NPCM7xx support in direct-kernel mode:

  - Two Cortex-A9 CPU cores with built-in periperhals.
  - Global Configuration Registers.
  - Clock Management.
  - 3 Timer Modules with 5 timers each.
  - 4 serial ports.

The chips themselves have a lot more features, some of which will be
added to the model at a later stage.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Tested-by: Alexander Bulekov 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h |  85 
 hw/arm/npcm7xx.c | 407 +++
 hw/arm/Kconfig   |   5 +
 hw/arm/meson.build   |   1 +
 4 files changed, 498 insertions(+)
 create mode 100644 include/hw/arm/npcm7xx.h
 create mode 100644 hw/arm/npcm7xx.c

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
new file mode 100644
index 00..e68d9c79e6
--- /dev/null
+++ b/include/hw/arm/npcm7xx.h
@@ -0,0 +1,85 @@
+/*
+ * Nuvoton NPCM7xx SoC family.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_H
+#define NPCM7XX_H
+
+#include "hw/boards.h"
+#include "hw/cpu/a9mpcore.h"
+#include "hw/misc/npcm7xx_clk.h"
+#include "hw/misc/npcm7xx_gcr.h"
+#include "hw/timer/npcm7xx_timer.h"
+#include "target/arm/cpu.h"
+
+#define NPCM7XX_MAX_NUM_CPUS(2)
+
+/* The first half of the address space is reserved for DDR4 DRAM. */
+#define NPCM7XX_DRAM_BA (0x)
+#define NPCM7XX_DRAM_SZ (2 * GiB)
+
+/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */
+#define NPCM7XX_LOADER_START(0x)  /* Start of SDRAM */
+#define NPCM7XX_SMP_LOADER_START(0x)  /* Boot ROM */
+#define NPCM7XX_SMP_BOOTREG_ADDR(0xf080013c)  /* GCR.SCRPAD */
+#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100)  /* GIC within A9 */
+
+typedef struct NPCM7xxState {
+DeviceState parent;
+
+ARMCPU  cpu[NPCM7XX_MAX_NUM_CPUS];
+A9MPPrivState   a9mpcore;
+
+MemoryRegionsram;
+MemoryRegionirom;
+MemoryRegionram3;
+MemoryRegion*dram;
+
+NPCM7xxGCRState gcr;
+NPCM7xxCLKState clk;
+NPCM7xxTimerCtrlState tim[3];
+} NPCM7xxState;
+
+#define TYPE_NPCM7XX"npcm7xx"
+#define NPCM7XX(obj)OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
+
+#define TYPE_NPCM730"npcm730"
+#define TYPE_NPCM750"npcm750"
+
+typedef struct NPCM7xxClass {
+DeviceClass parent;
+
+/* Bitmask of modules that are permanently disabled on this chip. */
+uint32_tdisabled_modules;
+/* Number of CPU cores enabled in this SoC class (may be 1 or 2). */
+uint32_tnum_cpus;
+} NPCM7xxClass;
+
+#define NPCM7XX_CLASS(klass)\
+OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
+#define NPCM7XX_GET_CLASS(obj)  \
+OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
+
+/**
+ * npcm7xx_load_kernel - Loads memory with everything needed to boot
+ * @machine - The machine containing the SoC to be booted.
+ * @soc - The SoC containing the CPU to be booted.
+ *
+ * This will set up the ARM boot info structure for the specific NPCM7xx
+ * derivative and call arm_load_kernel() to set up loading of the kernel, etc.
+ * into memory, if requested by the user.
+ */
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc);
+
+#endif /* NPCM7XX_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
new file mode 100644
index 00..9669ac5fa0
--- /dev/null
+++ b/hw/arm/npcm7xx.c
@@ -0,0 +1,407 @@
+/*
+ * Nuvoton NPCM7xx SoC family.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+

[PATCH v9 03/14] hw/timer: Add NPCM7xx Timer device model

2020-09-10 Thread Havard Skinnemoen via
The NPCM730 and NPCM750 SoCs have three timer modules each holding five
timers and some shared registers (e.g. interrupt status).

Each timer runs at 25 MHz divided by a prescaler, and counts down from a
configurable initial value to zero. When zero is reached, the interrupt
flag for the timer is set, and the timer is disabled (one-shot mode) or
reloaded from its initial value (periodic mode).

This implementation is sufficient to boot a Linux kernel configured for
NPCM750. Note that the kernel does not seem to actually turn on the
interrupts.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Alexander Bulekov 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/timer/npcm7xx_timer.h |  78 +
 hw/timer/npcm7xx_timer.c | 543 +++
 hw/timer/meson.build |   1 +
 hw/timer/trace-events|   5 +
 4 files changed, 627 insertions(+)
 create mode 100644 include/hw/timer/npcm7xx_timer.h
 create mode 100644 hw/timer/npcm7xx_timer.c

diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
new file mode 100644
index 00..878a365a79
--- /dev/null
+++ b/include/hw/timer/npcm7xx_timer.h
@@ -0,0 +1,78 @@
+/*
+ * Nuvoton NPCM7xx Timer Controller
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_TIMER_H
+#define NPCM7XX_TIMER_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+
+/* Each Timer Module (TIM) instance holds five 25 MHz timers. */
+#define NPCM7XX_TIMERS_PER_CTRL (5)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
+
+typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
+
+/**
+ * struct NPCM7xxTimer - Individual timer state.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @qtimer: QEMU timer that notifies us on expiration.
+ * @expires_ns: Absolute virtual expiration time.
+ * @remaining_ns: Remaining time until expiration if timer is paused.
+ * @tcsr: The Timer Control and Status Register.
+ * @ticr: The Timer Initial Count Register.
+ */
+typedef struct NPCM7xxTimer {
+NPCM7xxTimerCtrlState *ctrl;
+
+qemu_irqirq;
+QEMUTimer   qtimer;
+int64_t expires_ns;
+int64_t remaining_ns;
+
+uint32_ttcsr;
+uint32_tticr;
+} NPCM7xxTimer;
+
+/**
+ * struct NPCM7xxTimerCtrlState - Timer Module device state.
+ * @parent: System bus device.
+ * @iomem: Memory region through which registers are accessed.
+ * @tisr: The Timer Interrupt Status Register.
+ * @wtcr: The Watchdog Timer Control Register.
+ * @timer: The five individual timers managed by this module.
+ */
+struct NPCM7xxTimerCtrlState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint32_ttisr;
+uint32_twtcr;
+
+NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
+};
+
+#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
+#define NPCM7XX_TIMER(obj)  \
+OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER)
+
+#endif /* NPCM7XX_TIMER_H */
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
new file mode 100644
index 00..5703e43d40
--- /dev/null
+++ b/hw/timer/npcm7xx_timer.c
@@ -0,0 +1,543 @@
+/*
+ * Nuvoton NPCM7xx Timer Controller
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/irq.h"
+#include "hw/misc/npcm7xx_clk.h"
+#include "hw/timer/npcm7xx_timer.h"
+#include "migration/vmstate.h"
+#include "qemu/bitops.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qemu/units.h"
+#include 

[PATCH v9 06/14] roms: Add virtual Boot ROM for NPCM7xx SoCs

2020-09-10 Thread Havard Skinnemoen via
This is a minimalistic boot ROM written specifically for use with QEMU.
It supports loading the second-stage loader from SPI flash into RAM, SMP
boot, and not much else.

Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 .gitmodules |   3 +++
 MAINTAINERS |   2 ++
 pc-bios/README  |   6 ++
 pc-bios/meson.build |   1 +
 pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
 roms/Makefile   |   7 +++
 roms/vbootrom   |   1 +
 7 files changed, 20 insertions(+)
 create mode 100644 pc-bios/npcm7xx_bootrom.bin
 create mode 16 roms/vbootrom

diff --git a/.gitmodules b/.gitmodules
index ce979398a8..9ffb9f3f4f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -61,3 +61,6 @@
 [submodule "meson"]
path = meson
url = https://github.com/mesonbuild/meson/
+[submodule "roms/vbootrom"]
+   path = roms/vbootrom
+   url = https://github.com/google/vbootrom.git
diff --git a/MAINTAINERS b/MAINTAINERS
index ec03d213ad..094e0a31d3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -757,6 +757,8 @@ L: qemu-...@nongnu.org
 S: Supported
 F: hw/*/npcm7xx*
 F: include/hw/*/npcm7xx*
+F: pc-bios/npcm7xx_bootrom.bin
+F: roms/vbootrom
 
 nSeries
 M: Andrzej Zaborowski 
diff --git a/pc-bios/README b/pc-bios/README
index fa8b58b797..4d6297fca7 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -71,3 +71,9 @@
   ("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI
   source code also contains code reused from other projects desribed here:
   https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md.
+
+- npcm7xx_bootrom.bin is a simplified, free (Apache 2.0) boot ROM for Nuvoton
+  NPCM7xx BMC devices. It currently implements the bare minimum to load, parse,
+  initialize and run boot images stored in SPI flash, but may grow more
+  features over time as needed. The source code is available at:
+  https://github.com/google/vbootrom
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index 8087e5c0a7..182d5ebb35 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -81,6 +81,7 @@ blobs = files(
   'opensbi-riscv64-generic-fw_dynamic.bin',
   'opensbi-riscv32-generic-fw_dynamic.elf',
   'opensbi-riscv64-generic-fw_dynamic.elf',
+  'npcm7xx_bootrom.bin',
 )
 
 if install_blobs
diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin
new file mode 100644
index 
..38f89d1b97b0c2e133af2a9fbed0521be132065b
GIT binary patch
literal 768
zcmd5)JxClu6n-9S05p1#kf90Sj5Z(jG8}+)IZIp~iXK=T&)dL`%d-q*8aR#mq{7
z9`=6;Dr(H0ACe72R5x?!)^86Qj-X%{+!K9iZNA@*wkBAV(l^I9?!Gz=S2I_*1d
zr+tTQDHjvyzKnw(hu00yX`u!FvC;DilBe_YlkeSUVHA-crNk+k
jtiF_MudA

[PATCH v9 00/14] Add Nuvoton NPCM730/NPCM750 SoCs and two BMC machines

2020-09-10 Thread Havard Skinnemoen via
 qdev_init_gpio_out_named instead of sysbus_init_irq for chip
selects.
  - Incorporate review feedback into the TIMER module:
  - Assert that we never pause a timer that has already expired, instead of
trying to handle it. This should be safe since QEMU_CLOCK_VIRTUAL is
stopped while this code is running.
  - Simplify the switch blocks in the read and write handlers.

I made a change to error out if a flash drive was not specified, but reverted
it because it caused make check to fail (qom-test). When specifying a NULL
block device, the m25p flash device initializes its in-memory storage with 0xff
and doesn't attempt to write anything back. This seems correct to me.

Changes since v4:

  - OTP cleanups suggested by Philippe Mathieu-Daudé.
  - Added fuse array definitions based on public Nuvoton bootblock code.
  - Moved class structure to .c file since it's only used internally.
  - Readability improvements.
  - Split the first patch and folded parts of it into three other patches so
that CONFIG_NPCM7XX is only enabled after the initial NPCM7xx machine
support is added.
  - DRAM init moved to machine init code.
  - Consistently use lower-case hex literals.
  - Switched to fine-grained unimplemented devices, based on public bootblock
source code. Added a tiny SRAM that got left out previously.
  - Simplified error handling in npcm7xx_realize() since the board code will
abort anyway, and SoCs are not hot-pluggable.

Changes since v3:

  - License headers are now GPL v2-or-later throughout.
  - Added vmstate throughout (except the memory controller, which doesn't
really have any state worth saving). Successfully booted a gsj image
with two stop/savevm/quit/loadvm cycles along the way.
  - JFFS2 really doesn't like it if I let qemu keep running after savevm,
and then jump back in time with loadvm. I assume this is expected.
  - Fixed an error API violation in npcm7xx_realize, removed pointless error
check after object_property_set_link().
  - Switched the OTP device to use an embedded array instead of a g_malloc0'd
one because I couldn't figure out how to set up vmstate for the latter.

Changes since v2:

  - Simplified the MAINTAINERS entry.
  - Added link to OpenPOWER jenkins for gsj BMC images.
  - Reverted the smpboot change, back to byte swapping.
  - Adapted to upstream API changes:
  - sysbus_init_child_obj -> object_initialize_child
  - object_property_set_bool -> qdev_realize / sysbus_realize
  - ssi_create_slave_no_init -> qdev_new
  - qdev_init_nofail -> qdev_realize_and_unref
  - ssi_auto_connect_slaves removed
  - Moved Boot ROM loading from soc to machine init.
  - Plumbed power-on-straps property from GCR to the machine init code so it
can be properly initialized. Turns out npcm750 memory init doesn't work
without this. npcm730 is fine either way, though I'm not sure why.
  - Reworked the flash init code so it looks more like aspeed (i.e. the flash
device gets added even if there's no drive).

Changes since v1 (requested by reviewers):

  - Clarify the source of CLK reset values.
  - Made smpboot a constant byte array, eliinated byte swapping.
  - NPCM7xxState now stores an array of ARMCPUs, not pointers to ARMCPUs.
  - Clarify why EL3 is disabled.
  - Introduce NPCM7XX_NUM_IRQ constant.
  - Set the number of CPUs according to SoC variant, and disallow command line
overrides (i.e. you can no longer override the number of CPUs with the -smp
parameter). This is trying to follow the spirit of
https://patchwork.kernel.org/patch/11595407/.
  - Switch register operations to DEVICE_LITTLE_ENDIAN throughout.
  - Machine documentation added (new patch).

Changes since v1 to support flash booting:

  - GCR reset value changes to get past memory initialization when booting
from flash (patches 2 and 5):
  - INTCR2 now indicates that the DDR controller is initialized.
  - INTCR3 is initialized according to DDR memory size. A realize()
method was implemented to achieve this.
  - Refactor the machine initialization a bit to make it easier to drop in
machine-specific flash initialization (patch 6).
  - Extend the series with additional patches to enable booting from flash:
  - Boot ROM (through the -bios option).
  - OTP (fuse) controller.
  - Memory Controller stub (just enough to skip memory training).
  - Flash controller.
  - Board-specific flash initialization.

Thanks for reviewing,

Havard

Havard Skinnemoen (14):
  hw/misc: Add NPCM7xx System Global Control Registers device model
  hw/misc: Add NPCM7xx Clock Controller device model
  hw/timer: Add NPCM7xx Timer device model
  hw/arm: Add NPCM730 and NPCM750 SoC models
  hw/arm: Add two NPCM7xx-based machines
  roms: Add virtual Boot ROM for NPCM7xx SoCs
  hw/arm: Load -bios image as a boot ROM for npcm7xx
  hw/nvram: NPCM7xx OTP device model
  hw/mem: Stubbed out NPCM7xx Memory Cont

[PATCH v9 02/14] hw/misc: Add NPCM7xx Clock Controller device model

2020-09-10 Thread Havard Skinnemoen via
Enough functionality to boot the Linux kernel has been implemented. This
includes:

  - Correct power-on reset values so the various clock rates can be
accurately calculated.
  - Clock enables stick around when written.

In addition, a best effort attempt to implement SECCNT and CNTR25M was
made even though I don't think the kernel needs them.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Tested-by: Alexander Bulekov 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/misc/npcm7xx_clk.h |  48 ++
 hw/misc/npcm7xx_clk.c | 266 ++
 hw/misc/meson.build   |   1 +
 hw/misc/trace-events  |   4 +
 4 files changed, 319 insertions(+)
 create mode 100644 include/hw/misc/npcm7xx_clk.h
 create mode 100644 hw/misc/npcm7xx_clk.c

diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
new file mode 100644
index 00..cdcc9e8534
--- /dev/null
+++ b/include/hw/misc/npcm7xx_clk.h
@@ -0,0 +1,48 @@
+/*
+ * Nuvoton NPCM7xx Clock Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_CLK_H
+#define NPCM7XX_CLK_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/*
+ * The reference clock frequency for the timer modules, and the SECCNT and
+ * CNTR25M registers in this module, is always 25 MHz.
+ */
+#define NPCM7XX_TIMER_REF_HZ(2500)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
+
+typedef struct NPCM7xxCLKState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint32_t regs[NPCM7XX_CLK_NR_REGS];
+
+/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
+int64_t ref_ns;
+} NPCM7xxCLKState;
+
+#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
+#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
+
+#endif /* NPCM7XX_CLK_H */
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
new file mode 100644
index 00..21ab4200d1
--- /dev/null
+++ b/hw/misc/npcm7xx_clk.c
@@ -0,0 +1,266 @@
+/*
+ * Nuvoton NPCM7xx Clock Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/misc/npcm7xx_clk.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qemu/units.h"
+#include "trace.h"
+
+#define PLLCON_LOKI BIT(31)
+#define PLLCON_LOKS BIT(30)
+#define PLLCON_PWDENBIT(12)
+
+enum NPCM7xxCLKRegisters {
+NPCM7XX_CLK_CLKEN1,
+NPCM7XX_CLK_CLKSEL,
+NPCM7XX_CLK_CLKDIV1,
+NPCM7XX_CLK_PLLCON0,
+NPCM7XX_CLK_PLLCON1,
+NPCM7XX_CLK_SWRSTR,
+NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t),
+NPCM7XX_CLK_IPSRST2,
+NPCM7XX_CLK_CLKEN2,
+NPCM7XX_CLK_CLKDIV2,
+NPCM7XX_CLK_CLKEN3,
+NPCM7XX_CLK_IPSRST3,
+NPCM7XX_CLK_WD0RCR,
+NPCM7XX_CLK_WD1RCR,
+NPCM7XX_CLK_WD2RCR,
+NPCM7XX_CLK_SWRSTC1,
+NPCM7XX_CLK_SWRSTC2,
+NPCM7XX_CLK_SWRSTC3,
+NPCM7XX_CLK_SWRSTC4,
+NPCM7XX_CLK_PLLCON2,
+NPCM7XX_CLK_CLKDIV3,
+NPCM7XX_CLK_CORSTC,
+NPCM7XX_CLK_PLLCONG,
+NPCM7XX_CLK_AHBCKFI,
+NPCM7XX_CLK_SECCNT,
+NPCM7XX_CLK_CNTR25M,
+NPCM7XX_CLK_REGS_END,
+};
+
+/*
+ * These reset values were taken from version 0.91 of the NPCM750R data sheet.
+ *
+ * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on
+ * core domain reset, but this reset type is not yet supported by QEMU.
+ */
+static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
+[NPCM7XX_CLK_CLKEN1]= 0x,
+[NPCM7XX_CLK_CLKSEL]

[PATCH v9 01/14] hw/misc: Add NPCM7xx System Global Control Registers device model

2020-09-10 Thread Havard Skinnemoen via
Implement a device model for the System Global Control Registers in the
NPCM730 and NPCM750 BMC SoCs.

This is primarily used to enable SMP boot (the boot ROM spins reading
the SCRPAD register) and DDR memory initialization; other registers are
best effort for now.

The reset values of the MDLR and PWRON registers are determined by the
SoC variant (730 vs 750) and board straps respectively.

Reviewed-by: Joel Stanley 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
Tested-by: Alexander Bulekov 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/misc/npcm7xx_gcr.h |  43 ++
 hw/misc/npcm7xx_gcr.c | 269 ++
 MAINTAINERS   |   8 +
 hw/arm/Kconfig|   3 +
 hw/misc/meson.build   |   3 +
 hw/misc/trace-events  |   4 +
 6 files changed, 330 insertions(+)
 create mode 100644 include/hw/misc/npcm7xx_gcr.h
 create mode 100644 hw/misc/npcm7xx_gcr.c

diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
new file mode 100644
index 00..13109d9d32
--- /dev/null
+++ b/include/hw/misc/npcm7xx_gcr.h
@@ -0,0 +1,43 @@
+/*
+ * Nuvoton NPCM7xx System Global Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_GCR_H
+#define NPCM7XX_GCR_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
+
+typedef struct NPCM7xxGCRState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint32_t regs[NPCM7XX_GCR_NR_REGS];
+
+uint32_t reset_pwron;
+uint32_t reset_mdlr;
+uint32_t reset_intcr3;
+} NPCM7xxGCRState;
+
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
+#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
+
+#endif /* NPCM7XX_GCR_H */
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
new file mode 100644
index 00..745f690809
--- /dev/null
+++ b/hw/misc/npcm7xx_gcr.c
@@ -0,0 +1,269 @@
+/*
+ * Nuvoton NPCM7xx System Global Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/misc/npcm7xx_gcr.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+
+#include "trace.h"
+
+#define NPCM7XX_GCR_MIN_DRAM_SIZE   (128 * MiB)
+#define NPCM7XX_GCR_MAX_DRAM_SIZE   (2 * GiB)
+
+enum NPCM7xxGCRRegisters {
+NPCM7XX_GCR_PDID,
+NPCM7XX_GCR_PWRON,
+NPCM7XX_GCR_MFSEL1  = 0x0c / sizeof(uint32_t),
+NPCM7XX_GCR_MFSEL2,
+NPCM7XX_GCR_MISCPE,
+NPCM7XX_GCR_SPSWC   = 0x038 / sizeof(uint32_t),
+NPCM7XX_GCR_INTCR,
+NPCM7XX_GCR_INTSR,
+NPCM7XX_GCR_HIFCR   = 0x050 / sizeof(uint32_t),
+NPCM7XX_GCR_INTCR2  = 0x060 / sizeof(uint32_t),
+NPCM7XX_GCR_MFSEL3,
+NPCM7XX_GCR_SRCNT,
+NPCM7XX_GCR_RESSR,
+NPCM7XX_GCR_RLOCKR1,
+NPCM7XX_GCR_FLOCKR1,
+NPCM7XX_GCR_DSCNT,
+NPCM7XX_GCR_MDLR,
+NPCM7XX_GCR_SCRPAD3,
+NPCM7XX_GCR_SCRPAD2,
+NPCM7XX_GCR_DAVCLVLR= 0x098 / sizeof(uint32_t),
+NPCM7XX_GCR_INTCR3,
+NPCM7XX_GCR_VSINTR  = 0x0ac / sizeof(uint32_t),
+NPCM7XX_GCR_MFSEL4,
+NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t),
+NPCM7XX_GCR_CPCTL   = 0x0d0 / sizeof(uint32_t),
+NPCM7XX_GCR_CP2BST,
+NPCM7XX_GCR_B2CPNT,
+NPCM7XX_GCR_CPPCTL,
+NPCM7XX_GCR_I2CSEGSEL,
+NPCM7XX_GCR_I2CSEGCTL,
+NPCM7XX_GCR_VSRCR,
+NPCM7XX_GCR_MLOCKR,
+NPCM7XX_GCR_SCRPAD  = 0x013c / sizeof(uint32_t),
+NPCM7XX_GCR_USB1PHYCTL,
+NPCM7XX_GCR_USB

Re: [PATCH v8 00/14] Add Nuvoton NPCM730/NPCM750 SoCs and two BMC machines

2020-09-10 Thread Havard Skinnemoen
On Tue, Sep 8, 2020 at 6:32 PM Havard Skinnemoen 
wrote:

> On Tue, Sep 8, 2020 at 12:52 PM Havard Skinnemoen
>  wrote:
> >
> > On Tue, Sep 8, 2020 at 9:58 AM Philippe Mathieu-Daudé 
> wrote:
> > >
> > > On 9/8/20 5:52 PM, Philippe Mathieu-Daudé wrote:
> > > > On 9/8/20 5:02 PM, Alexander Bulekov wrote:
> > > >> Hi Havard,
> > > >> I fuzzed the npcm750-evb machine until I hit over 85% coverage over
> all
> > > >> the new npcm.*\.c files. The only thing I found specific to the new
> > > >> code, so far:
> > > >>
> > > >> cat << EOF | ./qemu-system-arm -machine npcm750-evb -m 128M -qtest
> stdio
> > > >> write 0xf0009040 0x4 0xc4c4c4c4
> > > >> write 0xf0009040 0x4 0x4
> > > >> EOF
> > > >
> > > > This is an odd test because with -qtest the timer is not running,
> > > > so this can not really happen on real hw.
> > > >
> > > > The fix is:
> > > >
> > > > -g_assert(t->remaining_ns > 0);
> > > > +g_assert(qtest_enabled() || t->remaining_ns > 0);
> > >
> > > Alex corrected me on IRC, qtest is irrelevant here.
> > > The problem is he disables the timer twice.
> > >
> > > So maybe something like:
> > >
> > >  static void npcm7xx_timer_pause(NPCM7xxTimer *t)
> > >  {
> > >  int64_t now;
> > >
> > > +if (!timer_pending(>qtimer)) {
> > > +return;
> > > +}
> > >  timer_del(>qtimer);
> > >  now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> > >  t->remaining_ns = t->expires_ns - now;
> > >  g_assert(t->remaining_ns > 0);
> > >  }
> >
> > Thanks, that makes sense. I was worried that making the assert
> > conditional on qtest_enabled() might hide real issues.
>
> Hmm, that didn't help, though it might make sense to keep it there anyway.
>
> What the test case does is:
>
>   1. Enable the timer (with zero expiration time) and reset it at the same
> time.
>   2. Disable the timer zero cycles after it was enabled.
>
> It also touches a bunch of other bits (including reserved bits), but
> they should be irrelevant.
>
> I think there are two issues here.
>
> When the Reset bit is set, the Enable bit should be forced to zero.
> This is easy to fix.
>
> If the timer is enabled with zero expiration time, and immediately
> disabled without advancing the virtual time, npcm7xx_timer_pause() is
> called while the timer is active, but t->expires_ns ==
> qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL). So t->remaining_ns becomes zero
> and triggers the assertion.
>
> If I revert a change that Philippe asked me to do earlier:
>
> timer_del(>qtimer);
>  now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>  t->remaining_ns = t->expires_ns - now;
> -g_assert(t->remaining_ns > 0);
> +if (t->remaining_ns <= 0) {
> +npcm7xx_timer_reached_zero(t);
> +}
>  }
>
> it doesn't crash:
>
> $ cat << EOF | ./qemu-system-arm -machine npcm750-evb -m 128M -qtest
> stdio --trace npcm7xx_timer*
> write 0xf0009040 0x4 0xc4c4c4c4
> write 0xf0009040 0x4 0x4
> EOF
> [I 1599613445.620379] OPENED
> [R +0.180771] write 0xf0009040 0x4 0xc4c4c4c4
> 1361079@1599613445.801182:npcm7xx_timer_write /machine/soc/tim[1]
> offset: 0x0040 value 0xc4c4c4c4
> OK
> [S +0.180816] OK
> [R +0.180833] write 0xf0009040 0x4 0x4
> 1361079@1599613445.801220:npcm7xx_timer_write /machine/soc/tim[1]
> offset: 0x0040 value 0x
> 1361079@1599613445.801295:npcm7xx_timer_irq /machine/soc/tim[1] timer 4
> state 0
> OK
> [S +0.180927] OK
> [I +0.181319] CLOSED
> [I +4.003267] CLOSED
>
> Note that the npcm7xx_timer_irq trace event is a sign of the first
> bug, but fixing that might mask the second bug. If we write the same
> pattern, only without the Reset bit, this would be the correct
> behavior (and it still causes the v8 code to crash).
>
> I think this device deserves a qtest. I wonder if we'd trigger the
> assertion if we set a nonzero expiration time, but happen to clear the
> Enable bit on the exact cycle it's supposed to expire. That would be a
> more realistic scenario, as it wouldn't require multiple register
> writes in the same virtual clock cycle.
>

I wrote some qtests, and found several more bugs, but I wasn't able to
trigger this particular failure mode. I was able to reproduce both of the
bugs found by the fuzzer though.

I'll refresh the patch series tonight or tomorrow, and 

Re: [PATCH v8 07/14] hw/arm: Load -bios image as a boot ROM for npcm7xx

2020-09-10 Thread Havard Skinnemoen
On Thu, Sep 3, 2020 at 11:59 AM Philippe Mathieu-Daudé 
wrote:

> On 8/25/20 2:17 AM, Havard Skinnemoen via wrote:
> > If a -bios option is specified on the command line, load the image into
> > the internal ROM memory region, which contains the first instructions
> > run by the CPU after reset.
> >
> > If -bios is not specified, the vbootrom included with qemu is loaded by
> > default.
> >
> > Reviewed-by: Tyrone Ting 
> > Reviewed-by: Cédric Le Goater 
> > Signed-off-by: Havard Skinnemoen 
> > ---
> >  hw/arm/npcm7xx_boards.c | 33 +
> >  1 file changed, 33 insertions(+)
> >
> > diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
> > index 0b9dce2b35..b67e45e913 100644
> > --- a/hw/arm/npcm7xx_boards.c
> > +++ b/hw/arm/npcm7xx_boards.c
> > @@ -18,12 +18,43 @@
> >
> >  #include "hw/arm/npcm7xx.h"
> >  #include "hw/core/cpu.h"
> > +#include "hw/loader.h"
> >  #include "qapi/error.h"
> > +#include "qemu-common.h"
> >  #include "qemu/units.h"
> > +#include "sysemu/sysemu.h"
> >
> >  #define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7
> >  #define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff
> >
> > +static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
> > +
> > +static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState
> *soc)
> > +{
> > +g_autofree char *filename = NULL;
> > +int ret;
> > +
> > +if (machine->kernel_filename) {
> > +/* Don't load the bootrom if user requested direct kernel boot.
> */
> > +return;
>
> Wondering why not load it always if available, and what would
> happen if booting from a kernel (without bootrom) and running
> "reboot" (via SysRq) in the guest I got:
>
> # echo b > /proc/sysrq-trigger
> sysrq: Resetting
> CPU0: stopping
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.32-7dc9442-dirty-8978043 #1
> Hardware name: NPCM7XX Chip family
> Backtrace:
> [] (dump_backtrace) from [] (show_stack+0x20/0x24)
>  r7: r6:600f0193 r5: r4:b0b5b1b8
> [] (show_stack) from [] (dump_stack+0x94/0xa8)
> [] (dump_stack) from [] (handle_IPI+0x1f0/0x38c)
>  r7: r6:0004 r5:b0b5eb64 r4:b0b729e0
> [] (handle_IPI) from [] (gic_handle_irq+0x9c/0xa0)
>  r10:10c5387d r9:b0b01ef8 r8:d0803100 r7:d0802100 r6:d080210c r5:b0b37db4
>  r4:b0b04504
> [] (gic_handle_irq) from [] (__irq_svc+0x6c/0x90)
> Exception stack(0xb0b01ef8 to 0xb0b01f40)
> 1ee0:   
> 00012f74
> 1f00: cfbc1774 b01112e0 b0b0  b0b03e28 b0b03e6c b0b5e72c
> b08e5ea8
> 1f20: 10c5387d b0b01f54 b0b01f58 b0b01f48 b0104114 b0104118 600f0013
> 
>  r9:b0b0 r8:b0b5e72c r7:b0b01f2c r6: r5:600f0013 r4:b0104118
> [] (arch_cpu_idle) from [] (do_idle+0xec/0x140)
> [] (do_idle) from [] (cpu_startup_entry+0x28/0x2c)
>  r9:410fc090 r8:0810c000 r7: r6:b0a53a40 r5:0001 r4:00ce
> [] (cpu_startup_entry) from [] (rest_init+0xb4/0xbc)
> [] (rest_init) from [] (arch_call_rest_init+0x18/0x1c)
>  r5:0001 r4:b0b72754
> [] (arch_call_rest_init) from []
> (start_kernel+0x428/0x458)
> [] (start_kernel) from [<>] (0x0)
> Reboot failed -- System halted
>
> So not a problem so far...
> Reviewed-by: Philippe Mathieu-Daudé 
>
> But still I'd keep loading the bootrom regardless -kernel.
>

So you mean something like this?

@@ -35,11 +35,6 @@ static void npcm7xx_load_bootrom(MachineState *machine,
NPCM7xxState *soc)
 g_autofree char *filename = NULL;
 int ret;

-if (machine->kernel_filename) {
-/* Don't load the bootrom if user requested direct kernel boot. */
-return;
-}
-
 if (!bios_name) {
 bios_name = npcm7xx_default_bootrom;
 }
@@ -47,7 +42,11 @@ static void npcm7xx_load_bootrom(MachineState *machine,
NPCM7xxState *soc)
 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 if (!filename) {
 error_report("Could not find ROM image '%s'", bios_name);
-exit(1);
+if (!machine->kernel_filename) {
+/* We can't boot without a bootrom or a kernel image. */
+exit(1);
+}
+return;
 }
 ret = load_image_mr(filename, >irom);
 if (ret < 0) {

I'm not sure if it will make much of a difference, as (IIUC)
arm_load_kernel installs a reset hook to jump directly into the kernel,
bypassing the bootrom entirely. I'm assuming a watchdog or SW reset would
trigger the same reset hook and jump right back into the kernel, though I
could be wrong.

Anyway, I can make the above change in any case.

Havard


Re: [PATCH v8 00/14] Add Nuvoton NPCM730/NPCM750 SoCs and two BMC machines

2020-09-08 Thread Havard Skinnemoen
On Tue, Sep 8, 2020 at 12:52 PM Havard Skinnemoen
 wrote:
>
> On Tue, Sep 8, 2020 at 9:58 AM Philippe Mathieu-Daudé  wrote:
> >
> > On 9/8/20 5:52 PM, Philippe Mathieu-Daudé wrote:
> > > On 9/8/20 5:02 PM, Alexander Bulekov wrote:
> > >> Hi Havard,
> > >> I fuzzed the npcm750-evb machine until I hit over 85% coverage over all
> > >> the new npcm.*\.c files. The only thing I found specific to the new
> > >> code, so far:
> > >>
> > >> cat << EOF | ./qemu-system-arm -machine npcm750-evb -m 128M -qtest stdio
> > >> write 0xf0009040 0x4 0xc4c4c4c4
> > >> write 0xf0009040 0x4 0x4
> > >> EOF
> > >
> > > This is an odd test because with -qtest the timer is not running,
> > > so this can not really happen on real hw.
> > >
> > > The fix is:
> > >
> > > -g_assert(t->remaining_ns > 0);
> > > +g_assert(qtest_enabled() || t->remaining_ns > 0);
> >
> > Alex corrected me on IRC, qtest is irrelevant here.
> > The problem is he disables the timer twice.
> >
> > So maybe something like:
> >
> >  static void npcm7xx_timer_pause(NPCM7xxTimer *t)
> >  {
> >  int64_t now;
> >
> > +if (!timer_pending(>qtimer)) {
> > +return;
> > +}
> >  timer_del(>qtimer);
> >  now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> >  t->remaining_ns = t->expires_ns - now;
> >  g_assert(t->remaining_ns > 0);
> >  }
>
> Thanks, that makes sense. I was worried that making the assert
> conditional on qtest_enabled() might hide real issues.

Hmm, that didn't help, though it might make sense to keep it there anyway.

What the test case does is:

  1. Enable the timer (with zero expiration time) and reset it at the same time.
  2. Disable the timer zero cycles after it was enabled.

It also touches a bunch of other bits (including reserved bits), but
they should be irrelevant.

I think there are two issues here.

When the Reset bit is set, the Enable bit should be forced to zero.
This is easy to fix.

If the timer is enabled with zero expiration time, and immediately
disabled without advancing the virtual time, npcm7xx_timer_pause() is
called while the timer is active, but t->expires_ns ==
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL). So t->remaining_ns becomes zero
and triggers the assertion.

If I revert a change that Philippe asked me to do earlier:

timer_del(>qtimer);
 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 t->remaining_ns = t->expires_ns - now;
-g_assert(t->remaining_ns > 0);
+if (t->remaining_ns <= 0) {
+npcm7xx_timer_reached_zero(t);
+}
 }

it doesn't crash:

$ cat << EOF | ./qemu-system-arm -machine npcm750-evb -m 128M -qtest
stdio --trace npcm7xx_timer*
write 0xf0009040 0x4 0xc4c4c4c4
write 0xf0009040 0x4 0x4
EOF
[I 1599613445.620379] OPENED
[R +0.180771] write 0xf0009040 0x4 0xc4c4c4c4
1361079@1599613445.801182:npcm7xx_timer_write /machine/soc/tim[1]
offset: 0x0040 value 0xc4c4c4c4
OK
[S +0.180816] OK
[R +0.180833] write 0xf0009040 0x4 0x4
1361079@1599613445.801220:npcm7xx_timer_write /machine/soc/tim[1]
offset: 0x0040 value 0x
1361079@1599613445.801295:npcm7xx_timer_irq /machine/soc/tim[1] timer 4 state 0
OK
[S +0.180927] OK
[I +0.181319] CLOSED
[I +4.003267] CLOSED

Note that the npcm7xx_timer_irq trace event is a sign of the first
bug, but fixing that might mask the second bug. If we write the same
pattern, only without the Reset bit, this would be the correct
behavior (and it still causes the v8 code to crash).

I think this device deserves a qtest. I wonder if we'd trigger the
assertion if we set a nonzero expiration time, but happen to clear the
Enable bit on the exact cycle it's supposed to expire. That would be a
more realistic scenario, as it wouldn't require multiple register
writes in the same virtual clock cycle.

I probably won't add the qtest to the same series, as I'd like someone
from Nuvoton to get a chance to review it first.

Havard

>
> This fuzz testing is great, it would have been hard to find this bug
> without it. Thanks a lot Alex for running it.
>
> Havard
>
> > >
> > >>
> > >> ERROR:../hw/timer/npcm7xx_timer.c:160:npcm7xx_timer_pause: assertion 
> > >> failed: (t->remaining_ns > 0)
> > >> Bail out! ERROR:../hw/timer/npcm7xx_timer.c:160:npcm7xx_timer_pause: 
> > >> assertion failed: (t->remaining_ns > 0)
> > >> Aborted
> > >>
> > >> I'm doing the same for the quanta-gsj machine, but I'm not sure whether
> > >> it will cover more code, so I'm happy to leave a:
> > >>
> > >>

Re: [PATCH v8 00/14] Add Nuvoton NPCM730/NPCM750 SoCs and two BMC machines

2020-09-08 Thread Havard Skinnemoen
On Tue, Sep 8, 2020 at 9:58 AM Philippe Mathieu-Daudé  wrote:
>
> On 9/8/20 5:52 PM, Philippe Mathieu-Daudé wrote:
> > On 9/8/20 5:02 PM, Alexander Bulekov wrote:
> >> Hi Havard,
> >> I fuzzed the npcm750-evb machine until I hit over 85% coverage over all
> >> the new npcm.*\.c files. The only thing I found specific to the new
> >> code, so far:
> >>
> >> cat << EOF | ./qemu-system-arm -machine npcm750-evb -m 128M -qtest stdio
> >> write 0xf0009040 0x4 0xc4c4c4c4
> >> write 0xf0009040 0x4 0x4
> >> EOF
> >
> > This is an odd test because with -qtest the timer is not running,
> > so this can not really happen on real hw.
> >
> > The fix is:
> >
> > -g_assert(t->remaining_ns > 0);
> > +g_assert(qtest_enabled() || t->remaining_ns > 0);
>
> Alex corrected me on IRC, qtest is irrelevant here.
> The problem is he disables the timer twice.
>
> So maybe something like:
>
>  static void npcm7xx_timer_pause(NPCM7xxTimer *t)
>  {
>  int64_t now;
>
> +if (!timer_pending(>qtimer)) {
> +return;
> +}
>  timer_del(>qtimer);
>  now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>  t->remaining_ns = t->expires_ns - now;
>  g_assert(t->remaining_ns > 0);
>  }

Thanks, that makes sense. I was worried that making the assert
conditional on qtest_enabled() might hide real issues.

This fuzz testing is great, it would have been hard to find this bug
without it. Thanks a lot Alex for running it.

Havard

> >
> >>
> >> ERROR:../hw/timer/npcm7xx_timer.c:160:npcm7xx_timer_pause: assertion 
> >> failed: (t->remaining_ns > 0)
> >> Bail out! ERROR:../hw/timer/npcm7xx_timer.c:160:npcm7xx_timer_pause: 
> >> assertion failed: (t->remaining_ns > 0)
> >> Aborted
> >>
> >> I'm doing the same for the quanta-gsj machine, but I'm not sure whether
> >> it will cover more code, so I'm happy to leave a:
> >>
> >> Tested-by: Alexander Bulekov 
> >>
> >> for the patches that add new virtual-device code (1-5, 7-12 ?)
> >> -Alex
> >
> > Very nice from you for testing running the fuzzer!
> >
> > Regards,
> >
> > Phil.
> >
> >>
> >>
> >> On 200824 1716, Havard Skinnemoen via wrote:
> >>> I also pushed this and the previous patchsets to my qemu fork on github.
> >>> The branches are named npcm7xx-v[1-8].
> >>>
> >>>   https://github.com/hskinnemoen/qemu
> >>>
> >>> This patch series models enough of the Nuvoton NPCM730 and NPCM750 SoCs 
> >>> to boot
> >>> an OpenBMC image built for quanta-gsj. This includes device models for:
> >>>
> >>>   - Global Configuration Registers
> >>>   - Clock Control
> >>>   - Timers
> >>>   - Fuses
> >>>   - Memory Controller
> >>>   - Flash Controller
> >>>
> >>> These modules, along with the existing Cortex A9 CPU cores and built-in
> >>> peripherals, are integrated into a NPCM730 or NPCM750 SoC, which in turn 
> >>> form
> >>> the foundation for the quanta-gsj and npcm750-evb machines, respectively. 
> >>> The
> >>> two SoCs are very similar; the only difference is that NPCM730 is missing 
> >>> some
> >>> peripherals that NPCM750 has, and which are not considered essential for
> >>> datacenter use (e.g. graphics controllers). For more information, see
> >>>
> >>> https://www.nuvoton.com/products/cloud-computing/ibmc/
> >>>
> >>> Both quanta-gsj and npcm750-evb correspond to real boards supported by 
> >>> OpenBMC.
> >>> At the end of the series, qemu can boot an OpenBMC image built for one of 
> >>> these
> >>> boards with some minor modifications.
> >>>
> >>> The patches in this series were developed by Google and reviewed by 
> >>> Nuvoton. We
> >>> will be maintaining the machine and peripheral support together.
> >>>
> >>> The data sheet for these SoCs is not generally available. Please let me 
> >>> know if
> >>> more comments are needed to understand the device behavior.
> >>>
> >>> Changes since v7:
> >>>
> >>>   - Move register enums to .c files throughout, leaving a single
> >>> NPCM7XX_FOO_NR_REGS definition behind in the .h file. A 
> >>> QEMU_BUILD_BUG_ON
> >>> sh

Re: [PATCH v8 08/14] hw/nvram: NPCM7xx OTP device model

2020-09-07 Thread Havard Skinnemoen
On Mon, Sep 7, 2020 at 12:58 PM Alexander Bulekov  wrote:
>
> On 200907 1547, Alexander Bulekov wrote:
> > On 200824 1717, Havard Skinnemoen via wrote:
> > > This supports reading and writing OTP fuses and keys. Only fuse reading
> > > has been tested. Protection is not implemented.
> > >
> > > Reviewed-by: Avi Fishman 
> > > Reviewed-by: Philippe Mathieu-Daudé 
> > > Signed-off-by: Havard Skinnemoen 
> > > ---
> > >  include/hw/arm/npcm7xx.h   |   3 +
> > >  include/hw/nvram/npcm7xx_otp.h |  79 ++
> > >  hw/arm/npcm7xx.c   |  29 +++
> > >  hw/nvram/npcm7xx_otp.c | 439 +
> > >  hw/nvram/meson.build   |   1 +
> > >  5 files changed, 551 insertions(+)
> > >  create mode 100644 include/hw/nvram/npcm7xx_otp.h
> > >  create mode 100644 hw/nvram/npcm7xx_otp.c
> > >
> > > diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
> > > index ba7495869d..5816a07a72 100644
> > > --- a/include/hw/arm/npcm7xx.h
> > > +++ b/include/hw/arm/npcm7xx.h
> > > @@ -20,6 +20,7 @@
> > >  #include "hw/cpu/a9mpcore.h"
> > >  #include "hw/misc/npcm7xx_clk.h"
> > >  #include "hw/misc/npcm7xx_gcr.h"
> > > +#include "hw/nvram/npcm7xx_otp.h"
> > >  #include "hw/timer/npcm7xx_timer.h"
> > >  #include "target/arm/cpu.h"
> > >
> > > @@ -68,6 +69,8 @@ typedef struct NPCM7xxState {
> > >  NPCM7xxGCRState gcr;
> > >  NPCM7xxCLKState clk;
> > >  NPCM7xxTimerCtrlState tim[3];
> > > +NPCM7xxOTPState key_storage;
> > > +NPCM7xxOTPState fuse_array;
> > >  } NPCM7xxState;
> > >
> > >  #define TYPE_NPCM7XX"npcm7xx"
> > > diff --git a/include/hw/nvram/npcm7xx_otp.h 
> > > b/include/hw/nvram/npcm7xx_otp.h
> > > new file mode 100644
> > > index 00..156bbd151a
> > > --- /dev/null
> > > +++ b/include/hw/nvram/npcm7xx_otp.h
> > > @@ -0,0 +1,79 @@
> > > +/*
> > > + * Nuvoton NPCM7xx OTP (Fuse Array) Interface
> > > + *
> > > + * Copyright 2020 Google LLC
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify 
> > > it
> > > + * under the terms of the GNU General Public License as published by the
> > > + * Free Software Foundation; either version 2 of the License, or
> > > + * (at your option) any later version.
> > > + *
> > > + * This program is distributed in the hope that it will be useful, but 
> > > WITHOUT
> > > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> > > + * for more details.
> > > + */
> > > +#ifndef NPCM7XX_OTP_H
> > > +#define NPCM7XX_OTP_H
> > > +
> > > +#include "exec/memory.h"
> > > +#include "hw/sysbus.h"
> > > +
> > > +/* Each OTP module holds 8192 bits of one-time programmable storage */
> > > +#define NPCM7XX_OTP_ARRAY_BITS (8192)
> > > +#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
> > > +
> > > +/* Fuse array offsets */
> > > +#define NPCM7XX_FUSE_FUSTRAP (0)
> > > +#define NPCM7XX_FUSE_CP_FUSTRAP (12)
> > > +#define NPCM7XX_FUSE_DAC_CALIB (16)
> > > +#define NPCM7XX_FUSE_ADC_CALIB (24)
> > > +#define NPCM7XX_FUSE_DERIVATIVE (64)
> > > +#define NPCM7XX_FUSE_TEST_SIG (72)
> > > +#define NPCM7XX_FUSE_DIE_LOCATION (74)
> > > +#define NPCM7XX_FUSE_GP1 (80)
> > > +#define NPCM7XX_FUSE_GP2 (128)
> > > +
> > > +/*
> > > + * Number of registers in our device state structure. Don't change this 
> > > without
> > > + * incrementing the version_id in the vmstate.
> > > + */
> > > +#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
> > > +
> > > +/**
> > > + * struct NPCM7xxOTPState - Device state for one OTP module.
> > > + * @parent: System bus device.
> > > + * @mmio: Memory region through which registers are accessed.
> > > + * @regs: Register contents.
> > > + * @array: OTP storage array.
> > > + */
> > > +typedef struct NPCM7xxOTPState {
> > > +SysBusDevice parent;
> > > +
> > > +MemoryRegion mmio;
> > > +uint32_t regs[NPCM7XX_OTP_NR_REGS];

Re: [PATCH v8 02/14] hw/misc: Add NPCM7xx Clock Controller device model

2020-09-07 Thread Havard Skinnemoen
On Mon, Sep 7, 2020 at 6:40 AM Philippe Mathieu-Daudé  wrote:
>
> On 9/5/20 12:38 AM, Havard Skinnemoen wrote:
> > On Fri, Sep 4, 2020 at 3:02 PM Havard Skinnemoen  
> > wrote:
> >>
> >> On Fri, Sep 4, 2020 at 2:32 AM Philippe Mathieu-Daudé  
> >> wrote:
> >>>
> >>> On 8/25/20 2:16 AM, Havard Skinnemoen via wrote:
> >>>> Enough functionality to boot the Linux kernel has been implemented. This
> >>>> includes:
> >>>>
> >>>>   - Correct power-on reset values so the various clock rates can be
> >>>> accurately calculated.
> >>>>   - Clock enables stick around when written.
> >>>>
> >>>> In addition, a best effort attempt to implement SECCNT and CNTR25M was
> >>>> made even though I don't think the kernel needs them.
> >>>>
> >>>> Reviewed-by: Tyrone Ting 
> >>>> Reviewed-by: Joel Stanley 
> >>>> Reviewed-by: Cédric Le Goater 
> >>>> Signed-off-by: Havard Skinnemoen 
> >>>> ---
> [...]
> >>>> +static void npcm7xx_clk_write(void *opaque, hwaddr offset,
> >>>> +  uint64_t v, unsigned size)
> >>>> +{
> >>>> +uint32_t reg = offset / sizeof(uint32_t);
> >>>> +NPCM7xxCLKState *s = opaque;
> >>>> +uint32_t value = v;
> >>>> +
> >>>> +trace_npcm7xx_clk_write(offset, value);
> >>>> +
> >>>> +if (reg >= NPCM7XX_CLK_NR_REGS) {
> >>>> +qemu_log_mask(LOG_GUEST_ERROR,
> >>>> +  "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
> >>>> +  __func__, offset);
> >>>> +return;
> >>>> +}
> >>>> +
> >>>> +switch (reg) {
> >>>> +case NPCM7XX_CLK_SWRSTR:
> >>>> +qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 
> >>>> 0x%02x\n",
> >>>> +  __func__, value);
> >>>
> >>> Isn't this sufficient?
> >>>
> >>>qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> >>
> >> It's not quite that easy; this register holds 4 bits, each of which
> >> maps to a separate register which defines the modules to reset. It's
> >> not that hard, but a little more than I'd like to add to the series at
> >> this point. I'll send a followup patch once the initial series is in.
> >
> > Actually, I'm not sure if this would have any effect on being able to
> > reboot. Running with -d unimp shows:
> >
> > reboot: Restarting system
> > npcm7xx_timer_write: WTCR write not implemented: 0x0083
> > Reboot failed -- System halted
> >
> > So we need to implement watchdog support, which is something we were
> > planning to do fairly soon.
>
> Well this seems a guest implementation decision to prefer
> wait the watchdog to kick (hard reset?) rather than doing
> a soft reset.
>
> Two different issues IMO. Anyway this is certainly not
> blocking your series to get merged.

I agree, we need to implement both. I just wanted to note that
implementing SWRST alone may not be enough to make reboots work with
the current image. The SW reset registers are actually very similar to
the WD reset registers, so implementing WD reset should make it almost
trivial to add SW reset as well.

It looks like the kernel has a driver that can use SW reset to reboot,
but the DT is missing a property needed to set up the restart handler.

https://elixir.bootlin.com/linux/v5.8.7/source/drivers/reset/reset-npcm.c#L269

Havard



Re: [PATCH v8 02/14] hw/misc: Add NPCM7xx Clock Controller device model

2020-09-04 Thread Havard Skinnemoen
On Fri, Sep 4, 2020 at 3:02 PM Havard Skinnemoen  wrote:
>
> On Fri, Sep 4, 2020 at 2:32 AM Philippe Mathieu-Daudé  wrote:
> >
> > On 8/25/20 2:16 AM, Havard Skinnemoen via wrote:
> > > Enough functionality to boot the Linux kernel has been implemented. This
> > > includes:
> > >
> > >   - Correct power-on reset values so the various clock rates can be
> > > accurately calculated.
> > >   - Clock enables stick around when written.
> > >
> > > In addition, a best effort attempt to implement SECCNT and CNTR25M was
> > > made even though I don't think the kernel needs them.
> > >
> > > Reviewed-by: Tyrone Ting 
> > > Reviewed-by: Joel Stanley 
> > > Reviewed-by: Cédric Le Goater 
> > > Signed-off-by: Havard Skinnemoen 
> > > ---
> > >  include/hw/misc/npcm7xx_clk.h |  48 ++
> > >  hw/misc/npcm7xx_clk.c | 266 ++
> > >  hw/misc/meson.build   |   1 +
> > >  hw/misc/trace-events  |   4 +
> > >  4 files changed, 319 insertions(+)
> > >  create mode 100644 include/hw/misc/npcm7xx_clk.h
> > >  create mode 100644 hw/misc/npcm7xx_clk.c
> > >
> > > diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
> > > new file mode 100644
> > > index 00..cdcc9e8534
> > > --- /dev/null
> > > +++ b/include/hw/misc/npcm7xx_clk.h
> > > @@ -0,0 +1,48 @@
> > > +/*
> > > + * Nuvoton NPCM7xx Clock Control Registers.
> > > + *
> > > + * Copyright 2020 Google LLC
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify 
> > > it
> > > + * under the terms of the GNU General Public License as published by the
> > > + * Free Software Foundation; either version 2 of the License, or
> > > + * (at your option) any later version.
> > > + *
> > > + * This program is distributed in the hope that it will be useful, but 
> > > WITHOUT
> > > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> > > + * for more details.
> > > + */
> > > +#ifndef NPCM7XX_CLK_H
> > > +#define NPCM7XX_CLK_H
> > > +
> > > +#include "exec/memory.h"
> > > +#include "hw/sysbus.h"
> > > +
> > > +/*
> > > + * The reference clock frequency for the timer modules, and the SECCNT 
> > > and
> > > + * CNTR25M registers in this module, is always 25 MHz.
> > > + */
> > > +#define NPCM7XX_TIMER_REF_HZ(2500)
> > > +
> > > +/*
> > > + * Number of registers in our device state structure. Don't change this 
> > > without
> > > + * incrementing the version_id in the vmstate.
> > > + */
> > > +#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
> > > +
> > > +typedef struct NPCM7xxCLKState {
> > > +SysBusDevice parent;
> > > +
> > > +MemoryRegion iomem;
> > > +
> > > +uint32_t regs[NPCM7XX_CLK_NR_REGS];
> > > +
> > > +/* Time reference for SECCNT and CNTR25M, initialized by power on 
> > > reset */
> > > +int64_t ref_ns;
> > > +} NPCM7xxCLKState;
> > > +
> > > +#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
> > > +#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), 
> > > TYPE_NPCM7XX_CLK)
> > > +
> > > +#endif /* NPCM7XX_CLK_H */
> > > diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
> > > new file mode 100644
> > > index 00..21ab4200d1
> > > --- /dev/null
> > > +++ b/hw/misc/npcm7xx_clk.c
> > > @@ -0,0 +1,266 @@
> > > +/*
> > > + * Nuvoton NPCM7xx Clock Control Registers.
> > > + *
> > > + * Copyright 2020 Google LLC
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify 
> > > it
> > > + * under the terms of the GNU General Public License as published by the
> > > + * Free Software Foundation; either version 2 of the License, or
> > > + * (at your option) any later version.
> > > + *
> > > + * This program is distributed in the hope that it will be useful, but 
> > > WITHOUT
> > > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > > + * FITNESS FOR A 

Re: [PATCH v8 02/14] hw/misc: Add NPCM7xx Clock Controller device model

2020-09-04 Thread Havard Skinnemoen
On Fri, Sep 4, 2020 at 2:32 AM Philippe Mathieu-Daudé  wrote:
>
> On 8/25/20 2:16 AM, Havard Skinnemoen via wrote:
> > Enough functionality to boot the Linux kernel has been implemented. This
> > includes:
> >
> >   - Correct power-on reset values so the various clock rates can be
> > accurately calculated.
> >   - Clock enables stick around when written.
> >
> > In addition, a best effort attempt to implement SECCNT and CNTR25M was
> > made even though I don't think the kernel needs them.
> >
> > Reviewed-by: Tyrone Ting 
> > Reviewed-by: Joel Stanley 
> > Reviewed-by: Cédric Le Goater 
> > Signed-off-by: Havard Skinnemoen 
> > ---
> >  include/hw/misc/npcm7xx_clk.h |  48 ++
> >  hw/misc/npcm7xx_clk.c | 266 ++
> >  hw/misc/meson.build   |   1 +
> >  hw/misc/trace-events  |   4 +
> >  4 files changed, 319 insertions(+)
> >  create mode 100644 include/hw/misc/npcm7xx_clk.h
> >  create mode 100644 hw/misc/npcm7xx_clk.c
> >
> > diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
> > new file mode 100644
> > index 00..cdcc9e8534
> > --- /dev/null
> > +++ b/include/hw/misc/npcm7xx_clk.h
> > @@ -0,0 +1,48 @@
> > +/*
> > + * Nuvoton NPCM7xx Clock Control Registers.
> > + *
> > + * Copyright 2020 Google LLC
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License as published by the
> > + * Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful, but 
> > WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> > + * for more details.
> > + */
> > +#ifndef NPCM7XX_CLK_H
> > +#define NPCM7XX_CLK_H
> > +
> > +#include "exec/memory.h"
> > +#include "hw/sysbus.h"
> > +
> > +/*
> > + * The reference clock frequency for the timer modules, and the SECCNT and
> > + * CNTR25M registers in this module, is always 25 MHz.
> > + */
> > +#define NPCM7XX_TIMER_REF_HZ(2500)
> > +
> > +/*
> > + * Number of registers in our device state structure. Don't change this 
> > without
> > + * incrementing the version_id in the vmstate.
> > + */
> > +#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
> > +
> > +typedef struct NPCM7xxCLKState {
> > +SysBusDevice parent;
> > +
> > +MemoryRegion iomem;
> > +
> > +uint32_t regs[NPCM7XX_CLK_NR_REGS];
> > +
> > +/* Time reference for SECCNT and CNTR25M, initialized by power on 
> > reset */
> > +int64_t ref_ns;
> > +} NPCM7xxCLKState;
> > +
> > +#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
> > +#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), 
> > TYPE_NPCM7XX_CLK)
> > +
> > +#endif /* NPCM7XX_CLK_H */
> > diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
> > new file mode 100644
> > index 00..21ab4200d1
> > --- /dev/null
> > +++ b/hw/misc/npcm7xx_clk.c
> > @@ -0,0 +1,266 @@
> > +/*
> > + * Nuvoton NPCM7xx Clock Control Registers.
> > + *
> > + * Copyright 2020 Google LLC
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License as published by the
> > + * Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful, but 
> > WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> > + * for more details.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +
> > +#include "hw/misc/npcm7xx_clk.h"
> > +#include "migration/vmstate.h"
> > +#include "qemu/error-report.h"
> > +#include "qemu/log.h"
> > +#include "qemu/module.h"
> > +#include "qemu/timer.h"
> > +#include "qemu/units.h"
> > +#include "trace.h"
> > +
> > +#define PLLCON_LOKI BIT(31)
> > +#define PLLCON_LOKS   

[PATCH v8 11/14] hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj

2020-08-24 Thread Havard Skinnemoen via
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 \
-drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Tested-by: Cédric Le Goater 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/npcm7xx_boards.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index b67e45e913..70e5c34216 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -19,6 +19,7 @@
 #include "hw/arm/npcm7xx.h"
 #include "hw/core/cpu.h"
 #include "hw/loader.h"
+#include "hw/qdev-properties.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
 #include "qemu/units.h"
@@ -55,6 +56,22 @@ static void npcm7xx_load_bootrom(MachineState *machine, 
NPCM7xxState *soc)
 }
 }
 
+static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
+  const char *flash_type, DriveInfo *dinfo)
+{
+DeviceState *flash;
+qemu_irq flash_cs;
+
+flash = qdev_new(flash_type);
+if (dinfo) {
+qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
+}
+qdev_realize_and_unref(flash, BUS(fiu->spi), _fatal);
+
+flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
+qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
+}
+
 static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
 {
 memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
@@ -92,6 +109,7 @@ static void npcm750_evb_init(MachineState *machine)
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
 npcm7xx_load_bootrom(machine, soc);
+npcm7xx_connect_flash(>fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
 npcm7xx_load_kernel(machine, soc);
 }
 
@@ -104,6 +122,8 @@ static void quanta_gsj_init(MachineState *machine)
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
 npcm7xx_load_bootrom(machine, soc);
+npcm7xx_connect_flash(>fiu[0], 0, "mx25l25635e",
+  drive_get(IF_MTD, 0, 0));
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.28.0.297.g1956fa8f8d-goog




[PATCH v8 08/14] hw/nvram: NPCM7xx OTP device model

2020-08-24 Thread Havard Skinnemoen via
This supports reading and writing OTP fuses and keys. Only fuse reading
has been tested. Protection is not implemented.

Reviewed-by: Avi Fishman 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h   |   3 +
 include/hw/nvram/npcm7xx_otp.h |  79 ++
 hw/arm/npcm7xx.c   |  29 +++
 hw/nvram/npcm7xx_otp.c | 439 +
 hw/nvram/meson.build   |   1 +
 5 files changed, 551 insertions(+)
 create mode 100644 include/hw/nvram/npcm7xx_otp.h
 create mode 100644 hw/nvram/npcm7xx_otp.c

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index ba7495869d..5816a07a72 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -20,6 +20,7 @@
 #include "hw/cpu/a9mpcore.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
+#include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "target/arm/cpu.h"
 
@@ -68,6 +69,8 @@ typedef struct NPCM7xxState {
 NPCM7xxGCRState gcr;
 NPCM7xxCLKState clk;
 NPCM7xxTimerCtrlState tim[3];
+NPCM7xxOTPState key_storage;
+NPCM7xxOTPState fuse_array;
 } NPCM7xxState;
 
 #define TYPE_NPCM7XX"npcm7xx"
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
new file mode 100644
index 00..156bbd151a
--- /dev/null
+++ b/include/hw/nvram/npcm7xx_otp.h
@@ -0,0 +1,79 @@
+/*
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_OTP_H
+#define NPCM7XX_OTP_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/* Each OTP module holds 8192 bits of one-time programmable storage */
+#define NPCM7XX_OTP_ARRAY_BITS (8192)
+#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
+
+/* Fuse array offsets */
+#define NPCM7XX_FUSE_FUSTRAP (0)
+#define NPCM7XX_FUSE_CP_FUSTRAP (12)
+#define NPCM7XX_FUSE_DAC_CALIB (16)
+#define NPCM7XX_FUSE_ADC_CALIB (24)
+#define NPCM7XX_FUSE_DERIVATIVE (64)
+#define NPCM7XX_FUSE_TEST_SIG (72)
+#define NPCM7XX_FUSE_DIE_LOCATION (74)
+#define NPCM7XX_FUSE_GP1 (80)
+#define NPCM7XX_FUSE_GP2 (128)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
+
+/**
+ * struct NPCM7xxOTPState - Device state for one OTP module.
+ * @parent: System bus device.
+ * @mmio: Memory region through which registers are accessed.
+ * @regs: Register contents.
+ * @array: OTP storage array.
+ */
+typedef struct NPCM7xxOTPState {
+SysBusDevice parent;
+
+MemoryRegion mmio;
+uint32_t regs[NPCM7XX_OTP_NR_REGS];
+uint8_t array[NPCM7XX_OTP_ARRAY_BYTES];
+} NPCM7xxOTPState;
+
+#define TYPE_NPCM7XX_OTP "npcm7xx-otp"
+#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP)
+
+#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage"
+#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array"
+
+typedef struct NPCM7xxOTPClass NPCM7xxOTPClass;
+
+/**
+ * npcm7xx_otp_array_write - ECC encode and write data to OTP array.
+ * @s: OTP module.
+ * @data: Data to be encoded and written.
+ * @offset: Offset of first byte to be written in the OTP array.
+ * @len: Number of bytes before ECC encoding.
+ *
+ * Each nibble of data is encoded into a byte, so the number of bytes written
+ * to the array will be @len * 2.
+ */
+extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
+unsigned int offset, unsigned int len);
+
+#endif /* NPCM7XX_OTP_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 9669ac5fa0..9166002598 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -34,6 +34,10 @@
 #define NPCM7XX_MMIO_BA (0x8000)
 #define NPCM7XX_MMIO_SZ (0x7ffd)
 
+/* OTP key storage and fuse strap array */
+#define NPCM7XX_OTP1_BA (0xf0189000)
+#define NPCM7XX_OTP2_BA (0xf018a000)
+
 /* Core system modules. */
 #define NPCM7XX_L2C_BA  (0xf03fc000)
 #define NPCM7XX_CPUP_BA (0xf03fe000)
@@ -144,6 +148,20 @@ void npcm7xx_load_kernel(MachineState *machine, 
NPCM7xxState *soc)
 arm_load_kernel(>cpu[0], machine, _binfo);
 }
 
+static void npcm7xx_init_fuses(NPCM7xxState *s)
+{
+NPCM7xxClass *nc = NPCM7XX_G

[PATCH v8 14/14] tests/acceptance: console boot tests for quanta-gsj

2020-08-24 Thread Havard Skinnemoen via
This adds two acceptance tests for the quanta-gsj machine.

One test downloads a lightly patched openbmc flash image from github and
verifies that it boots all the way to the login prompt.

The other test downloads a kernel, initrd and dtb built from the same
openbmc source and verifies that the kernel detects all CPUs and boots
to the point where it can't find the root filesystem (because we have no
flash image in this case).

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 tests/acceptance/boot_linux_console.py | 83 ++
 1 file changed, 83 insertions(+)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index aaa781a581..4a366ce93e 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -568,6 +568,89 @@ class BootLinuxConsole(LinuxKernelTest):
 'sda')
 # cubieboard's reboot is not functioning; omit reboot test.
 
+def test_arm_quanta_gsj(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:quanta-gsj
+"""
+# 25 MiB compressed, 32 MiB uncompressed.
+image_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
+image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
+image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
+image_name = 'obmc.mtd'
+image_path = os.path.join(self.workdir, image_name)
+archive.gzip_uncompress(image_path_gz, image_path)
+
+self.vm.set_console()
+drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
+self.vm.add_args('-drive', drive_args)
+self.vm.launch()
+
+# Disable drivers and services that stall for a long time during boot,
+# to avoid running past the 90-second timeout. These may be removed
+# as the corresponding device support is added.
+kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
+'console=${console} '
+'mem=${mem} '
+'initcall_blacklist=npcm_i2c_bus_driver_init '
+'systemd.mask=systemd-random-seed.service '
+'systemd.mask=dropbearkey.service '
+)
+
+self.wait_for_console_pattern('> BootBlock by Nuvoton')
+self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
+self.wait_for_console_pattern('>Skip DDR init.')
+self.wait_for_console_pattern('U-Boot ')
+interrupt_interactive_console_until_pattern(
+self, 'Hit any key to stop autoboot:', 'U-Boot>')
+exec_command_and_wait_for_pattern(
+self, "setenv bootargs ${bootargs} " + kernel_command_line,
+'U-Boot>')
+exec_command_and_wait_for_pattern(
+self, 'run romboot', 'Booting Kernel from flash')
+self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
+self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
+self.wait_for_console_pattern('OpenBMC Project Reference Distro')
+self.wait_for_console_pattern('gsj login:')
+
+def test_arm_quanta_gsj_initrd(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:quanta-gsj
+"""
+initrd_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
+initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
+initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+kernel_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/uImage-gsj.bin')
+kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
+kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+dtb_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
+dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
+dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'console=ttyS0,115200n8 '
+   'earlycon=uart8250,mmio32,0xf0001000')
+self.vm.add_args('-kernel', kernel_path,
+ '-initrd', initrd_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line)
+self.vm.launch()
+
+self.wait_for_console_pattern('Booting Linux on physic

[PATCH v8 12/14] hw/arm/npcm7xx: add board setup stub for CPU and UART clocks

2020-08-24 Thread Havard Skinnemoen via
When booting directly into a kernel, bypassing the boot loader, the CPU and
UART clocks are not set up correctly. This makes the system appear very
slow, and causes the initrd boot test to fail when optimization is off.

The UART clock must run at 24 MHz. The default 25 MHz reference clock
cannot achieve this, so switch to PLL2/2 @ 480 MHz, which works
perfectly with the default /20 divider.

The CPU clock should run at 800 MHz, so switch it to PLL1/2. PLL1 runs
at 800 MHz by default, so we need to double the feedback divider as well
to make it run at 1600 MHz (so PLL1/2 runs at 800 MHz).

We don't bother checking for PLL lock because we know our emulated PLLs
lock instantly.

Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h |  1 +
 hw/arm/npcm7xx.c | 32 
 2 files changed, 33 insertions(+)

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 78d0d78c52..13106af215 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -37,6 +37,7 @@
 #define NPCM7XX_SMP_LOADER_START(0x)  /* Boot ROM */
 #define NPCM7XX_SMP_BOOTREG_ADDR(0xf080013c)  /* GCR.SCRPAD */
 #define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100)  /* GIC within A9 */
+#define NPCM7XX_BOARD_SETUP_ADDR(0x1000)  /* Boot ROM */
 
 typedef struct NPCM7xxMachine {
 MachineStateparent;
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 7884b2b03d..037f3a26f2 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -55,6 +55,13 @@
 #define NPCM7XX_ROM_BA  (0x)
 #define NPCM7XX_ROM_SZ  (64 * KiB)
 
+/* Clock configuration values to be fixed up when bypassing bootloader */
+
+/* Run PLL1 at 1600 MHz */
+#define NPCM7XX_PLLCON1_FIXUP_VAL   (0x00402101)
+/* Run the CPU from PLL1 and UART from PLL2 */
+#define NPCM7XX_CLKSEL_FIXUP_VAL(0x004aaba9)
+
 /*
  * Interrupt lines going into the GIC. This does not include internal Cortex-A9
  * interrupts.
@@ -132,6 +139,29 @@ static const struct {
 },
 };
 
+static void npcm7xx_write_board_setup(ARMCPU *cpu,
+  const struct arm_boot_info *info)
+{
+uint32_t board_setup[] = {
+0xe59f0010, /* ldr r0, clk_base_addr */
+0xe59f1010, /* ldr r1, pllcon1_value */
+0xe5801010, /* str r1, [r0, #16] */
+0xe59f100c, /* ldr r1, clksel_value */
+0xe5801004, /* str r1, [r0, #4] */
+0xe12fff1e, /* bx lr */
+NPCM7XX_CLK_BA,
+NPCM7XX_PLLCON1_FIXUP_VAL,
+NPCM7XX_CLKSEL_FIXUP_VAL,
+};
+int i;
+
+for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
+board_setup[i] = tswap32(board_setup[i]);
+}
+rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
+   info->board_setup_addr);
+}
+
 static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
  const struct arm_boot_info *info)
 {
@@ -170,6 +200,8 @@ static struct arm_boot_info npcm7xx_binfo = {
 .gic_cpu_if_addr= NPCM7XX_GIC_CPU_IF_ADDR,
 .write_secondary_boot   = npcm7xx_write_secondary_boot,
 .board_id   = -1,
+.board_setup_addr   = NPCM7XX_BOARD_SETUP_ADDR,
+.write_board_setup  = npcm7xx_write_board_setup,
 };
 
 void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
-- 
2.28.0.297.g1956fa8f8d-goog




[PATCH v8 06/14] roms: Add virtual Boot ROM for NPCM7xx SoCs

2020-08-24 Thread Havard Skinnemoen via
This is a minimalistic boot ROM written specifically for use with QEMU.
It supports loading the second-stage loader from SPI flash into RAM, SMP
boot, and not much else.

Signed-off-by: Havard Skinnemoen 
---
 Makefile|   1 +
 .gitmodules |   3 +++
 MAINTAINERS |   2 ++
 pc-bios/README  |   6 ++
 pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
 roms/Makefile   |   7 +++
 roms/vbootrom   |   1 +
 7 files changed, 20 insertions(+)
 create mode 100644 pc-bios/npcm7xx_bootrom.bin
 create mode 16 roms/vbootrom

diff --git a/Makefile b/Makefile
index 81794d5c34..08e9af3793 100644
--- a/Makefile
+++ b/Makefile
@@ -246,6 +246,7 @@ s390-ccw.img s390-netboot.img \
 slof.bin skiboot.lid \
 palcode-clipper \
 u-boot.e500 u-boot-sam460-20100605.bin \
+npcm7xx_bootrom.bin \
 qemu_vga.ndrv \
 edk2-licenses.txt \
 hppa-firmware.img \
diff --git a/.gitmodules b/.gitmodules
index ce979398a8..9ffb9f3f4f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -61,3 +61,6 @@
 [submodule "meson"]
path = meson
url = https://github.com/mesonbuild/meson/
+[submodule "roms/vbootrom"]
+   path = roms/vbootrom
+   url = https://github.com/google/vbootrom.git
diff --git a/MAINTAINERS b/MAINTAINERS
index 3f72250630..d71afedc20 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -756,6 +756,8 @@ L: qemu-...@nongnu.org
 S: Supported
 F: hw/*/npcm7xx*
 F: include/hw/*/npcm7xx*
+F: pc-bios/npcm7xx_bootrom.bin
+F: roms/vbootrom
 
 nSeries
 M: Andrzej Zaborowski 
diff --git a/pc-bios/README b/pc-bios/README
index fa8b58b797..4d6297fca7 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -71,3 +71,9 @@
   ("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI
   source code also contains code reused from other projects desribed here:
   https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md.
+
+- npcm7xx_bootrom.bin is a simplified, free (Apache 2.0) boot ROM for Nuvoton
+  NPCM7xx BMC devices. It currently implements the bare minimum to load, parse,
+  initialize and run boot images stored in SPI flash, but may grow more
+  features over time as needed. The source code is available at:
+  https://github.com/google/vbootrom
diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin
new file mode 100644
index 
..38f89d1b97b0c2e133af2a9fbed0521be132065b
GIT binary patch
literal 768
zcmd5)JxClu6n-9S05p1#kf90Sj5Z(jG8}+)IZIp~iXK=T&)dL`%d-q*8aR#mq{7
z9`=6;Dr(H0ACe72R5x?!)^86Qj-X%{+!K9iZNA@*wkBAV(l^I9?!Gz=S2I_*1d
zr+tTQDHjvyzKnw(hu00yX`u!FvC;DilBe_YlkeSUVHA-crNk+k
jtiF_MudA

[PATCH v8 07/14] hw/arm: Load -bios image as a boot ROM for npcm7xx

2020-08-24 Thread Havard Skinnemoen via
If a -bios option is specified on the command line, load the image into
the internal ROM memory region, which contains the first instructions
run by the CPU after reset.

If -bios is not specified, the vbootrom included with qemu is loaded by
default.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/npcm7xx_boards.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 0b9dce2b35..b67e45e913 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -18,12 +18,43 @@
 
 #include "hw/arm/npcm7xx.h"
 #include "hw/core/cpu.h"
+#include "hw/loader.h"
 #include "qapi/error.h"
+#include "qemu-common.h"
 #include "qemu/units.h"
+#include "sysemu/sysemu.h"
 
 #define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7
 #define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff
 
+static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
+
+static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
+{
+g_autofree char *filename = NULL;
+int ret;
+
+if (machine->kernel_filename) {
+/* Don't load the bootrom if user requested direct kernel boot. */
+return;
+}
+
+if (!bios_name) {
+bios_name = npcm7xx_default_bootrom;
+}
+
+filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+if (!filename) {
+error_report("Could not find ROM image '%s'", bios_name);
+exit(1);
+}
+ret = load_image_mr(filename, >irom);
+if (ret < 0) {
+error_report("Failed to load ROM image '%s'", filename);
+exit(1);
+}
+}
+
 static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
 {
 memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
@@ -60,6 +91,7 @@ static void npcm750_evb_init(MachineState *machine)
 npcm7xx_connect_dram(soc, machine->ram);
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
+npcm7xx_load_bootrom(machine, soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
@@ -71,6 +103,7 @@ static void quanta_gsj_init(MachineState *machine)
 npcm7xx_connect_dram(soc, machine->ram);
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
+npcm7xx_load_bootrom(machine, soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.28.0.297.g1956fa8f8d-goog




[PATCH v8 04/14] hw/arm: Add NPCM730 and NPCM750 SoC models

2020-08-24 Thread Havard Skinnemoen via
The Nuvoton NPCM7xx SoC family are used to implement Baseboard
Management Controllers in servers. While the family includes four SoCs,
this patch implements limited support for two of them: NPCM730 (targeted
for Data Center applications) and NPCM750 (targeted for Enterprise
applications).

This patch includes little more than the bare minimum needed to boot a
Linux kernel built with NPCM7xx support in direct-kernel mode:

  - Two Cortex-A9 CPU cores with built-in periperhals.
  - Global Configuration Registers.
  - Clock Management.
  - 3 Timer Modules with 5 timers each.
  - 4 serial ports.

The chips themselves have a lot more features, some of which will be
added to the model at a later stage.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h |  85 
 hw/arm/npcm7xx.c | 407 +++
 hw/arm/Kconfig   |   5 +
 hw/arm/meson.build   |   1 +
 4 files changed, 498 insertions(+)
 create mode 100644 include/hw/arm/npcm7xx.h
 create mode 100644 hw/arm/npcm7xx.c

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
new file mode 100644
index 00..e68d9c79e6
--- /dev/null
+++ b/include/hw/arm/npcm7xx.h
@@ -0,0 +1,85 @@
+/*
+ * Nuvoton NPCM7xx SoC family.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_H
+#define NPCM7XX_H
+
+#include "hw/boards.h"
+#include "hw/cpu/a9mpcore.h"
+#include "hw/misc/npcm7xx_clk.h"
+#include "hw/misc/npcm7xx_gcr.h"
+#include "hw/timer/npcm7xx_timer.h"
+#include "target/arm/cpu.h"
+
+#define NPCM7XX_MAX_NUM_CPUS(2)
+
+/* The first half of the address space is reserved for DDR4 DRAM. */
+#define NPCM7XX_DRAM_BA (0x)
+#define NPCM7XX_DRAM_SZ (2 * GiB)
+
+/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */
+#define NPCM7XX_LOADER_START(0x)  /* Start of SDRAM */
+#define NPCM7XX_SMP_LOADER_START(0x)  /* Boot ROM */
+#define NPCM7XX_SMP_BOOTREG_ADDR(0xf080013c)  /* GCR.SCRPAD */
+#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100)  /* GIC within A9 */
+
+typedef struct NPCM7xxState {
+DeviceState parent;
+
+ARMCPU  cpu[NPCM7XX_MAX_NUM_CPUS];
+A9MPPrivState   a9mpcore;
+
+MemoryRegionsram;
+MemoryRegionirom;
+MemoryRegionram3;
+MemoryRegion*dram;
+
+NPCM7xxGCRState gcr;
+NPCM7xxCLKState clk;
+NPCM7xxTimerCtrlState tim[3];
+} NPCM7xxState;
+
+#define TYPE_NPCM7XX"npcm7xx"
+#define NPCM7XX(obj)OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
+
+#define TYPE_NPCM730"npcm730"
+#define TYPE_NPCM750"npcm750"
+
+typedef struct NPCM7xxClass {
+DeviceClass parent;
+
+/* Bitmask of modules that are permanently disabled on this chip. */
+uint32_tdisabled_modules;
+/* Number of CPU cores enabled in this SoC class (may be 1 or 2). */
+uint32_tnum_cpus;
+} NPCM7xxClass;
+
+#define NPCM7XX_CLASS(klass)\
+OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
+#define NPCM7XX_GET_CLASS(obj)  \
+OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
+
+/**
+ * npcm7xx_load_kernel - Loads memory with everything needed to boot
+ * @machine - The machine containing the SoC to be booted.
+ * @soc - The SoC containing the CPU to be booted.
+ *
+ * This will set up the ARM boot info structure for the specific NPCM7xx
+ * derivative and call arm_load_kernel() to set up loading of the kernel, etc.
+ * into memory, if requested by the user.
+ */
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc);
+
+#endif /* NPCM7XX_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
new file mode 100644
index 00..9669ac5fa0
--- /dev/null
+++ b/hw/arm/npcm7xx.c
@@ -0,0 +1,407 @@
+/*
+ * Nuvoton NPCM7xx SoC family.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be 

[PATCH v8 13/14] docs/system: Add Nuvoton machine documentation

2020-08-24 Thread Havard Skinnemoen via
Reviewed-by: Cédric Le Goater 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst | 90 +
 docs/system/target-arm.rst  |  1 +
 2 files changed, 91 insertions(+)
 create mode 100644 docs/system/arm/nuvoton.rst

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
new file mode 100644
index 00..36bf901122
--- /dev/null
+++ b/docs/system/arm/nuvoton.rst
@@ -0,0 +1,90 @@
+Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``)
+=
+
+The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are
+designed to be used as Baseboard Management Controllers (BMCs) in various
+servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an
+assortment of peripherals targeted for either Enterprise or Data Center /
+Hyperscale applications. The former is a superset of the latter, so NPCM750 has
+all the peripherals of NPCM730 and more.
+
+.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/
+
+The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise
+segment. The following machines are based on this chip :
+
+- ``npcm750-evb``   Nuvoton NPCM750 Evaluation board
+
+The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and
+Hyperscale applications. The following machines are based on this chip :
+
+- ``quanta-gsj``Quanta GSJ server BMC
+
+There are also two more SoCs, NPCM710 and NPCM705, which are single-core
+variants of NPCM750 and NPCM730, respectively. These are currently not
+supported by QEMU.
+
+Supported devices
+-
+
+ * SMP (Dual Core Cortex-A9)
+ * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer
+   and Watchdog.
+ * SRAM, ROM and DRAM mappings
+ * System Global Control Registers (GCR)
+ * Clock and reset controller (CLK)
+ * Timer controller (TIM)
+ * Serial ports (16550-based)
+ * DDR4 memory controller (dummy interface indicating memory training is done)
+ * OTP controllers (no protection features)
+ * Flash Interface Unit (FIU; no protection features)
+
+Missing devices
+---
+
+ * GPIO controller
+ * LPC/eSPI host-to-BMC interface, including
+
+   * Keyboard and mouse controller interface (KBCI)
+   * Keyboard Controller Style (KCS) channels
+   * BIOS POST code FIFO
+   * System Wake-up Control (SWC)
+   * Shared memory (SHM)
+   * eSPI slave interface
+
+ * Ethernet controllers (GMAC and EMC)
+ * USB host (USBH)
+ * USB device (USBD)
+ * SMBus controller (SMBF)
+ * Peripheral SPI controller (PSPI)
+ * Analog to Digital Converter (ADC)
+ * SD/MMC host
+ * Random Number Generator (RNG)
+ * PECI interface
+ * Pulse Width Modulation (PWM)
+ * Tachometer
+ * PCI and PCIe root complex and bridges
+ * VDM and MCTP support
+ * Serial I/O expansion
+ * LPC/eSPI host
+ * Coprocessor
+ * Graphics
+ * Video capture
+ * Encoding compression engine
+ * Security features
+
+Boot options
+
+
+The Nuvoton machines can boot from an OpenBMC firmware image, or directly into
+a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and
+possibly others can be downloaded from the OpenPOWER jenkins :
+
+   https://openpower.xyz/
+
+The firmware image should be attached as an MTD drive. Example :
+
+.. code-block:: bash
+
+  $ qemu-system-arm -machine quanta-gsj -nographic \
+  -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index afdb37e738..fdcf25c237 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -86,6 +86,7 @@ undocumented; you can get a complete list by running
arm/musicpal
arm/gumstix
arm/nseries
+   arm/nuvoton
arm/orangepi
arm/palm
arm/xscale
-- 
2.28.0.297.g1956fa8f8d-goog




[PATCH v8 05/14] hw/arm: Add two NPCM7xx-based machines

2020-08-24 Thread Havard Skinnemoen via
This adds two new machines, both supported by OpenBMC:

  - npcm750-evb: Nuvoton NPCM750 Evaluation Board.
  - quanta-gsj: A board with a NPCM730 chip.

They rely on the NPCM7xx SoC device to do the heavy lifting. They are
almost completely identical at the moment, apart from the SoC type,
which currently only changes the reset contents of one register
(GCR.MDLR), but they might grow apart a bit more as more functionality
is added.

Both machines can boot the Linux kernel into /bin/sh.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 default-configs/arm-softmmu.mak |   1 +
 include/hw/arm/npcm7xx.h|  19 +
 hw/arm/npcm7xx_boards.c | 144 
 hw/arm/meson.build  |   2 +-
 4 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/npcm7xx_boards.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 8fc09a4a51..9a94ebd0be 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -27,6 +27,7 @@ CONFIG_GUMSTIX=y
 CONFIG_SPITZ=y
 CONFIG_TOSA=y
 CONFIG_Z2=y
+CONFIG_NPCM7XX=y
 CONFIG_COLLIE=y
 CONFIG_ASPEED_SOC=y
 CONFIG_NETDUINO2=y
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index e68d9c79e6..ba7495869d 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -35,6 +35,25 @@
 #define NPCM7XX_SMP_BOOTREG_ADDR(0xf080013c)  /* GCR.SCRPAD */
 #define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100)  /* GIC within A9 */
 
+typedef struct NPCM7xxMachine {
+MachineStateparent;
+} NPCM7xxMachine;
+
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
+#define NPCM7XX_MACHINE(obj)\
+OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
+
+typedef struct NPCM7xxMachineClass {
+MachineClassparent;
+
+const char  *soc_type;
+} NPCM7xxMachineClass;
+
+#define NPCM7XX_MACHINE_CLASS(klass)\
+OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE)
+#define NPCM7XX_MACHINE_GET_CLASS(obj)  \
+OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
+
 typedef struct NPCM7xxState {
 DeviceState parent;
 
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
new file mode 100644
index 00..0b9dce2b35
--- /dev/null
+++ b/hw/arm/npcm7xx_boards.c
@@ -0,0 +1,144 @@
+/*
+ * Machine definitions for boards featuring an NPCM7xx SoC.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/arm/npcm7xx.h"
+#include "hw/core/cpu.h"
+#include "qapi/error.h"
+#include "qemu/units.h"
+
+#define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7
+#define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff
+
+static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
+{
+memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
+
+object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram),
+ _abort);
+}
+
+static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
+uint32_t hw_straps)
+{
+NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
+MachineClass *mc = >parent;
+Object *obj;
+
+if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
+error_report("This board can only be used with %s",
+ mc->default_cpu_type);
+exit(1);
+}
+
+obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc",
+_abort, NULL);
+object_property_set_uint(obj, "power-on-straps", hw_straps, _abort);
+
+return NPCM7XX(obj);
+}
+
+static void npcm750_evb_init(MachineState *machine)
+{
+NPCM7xxState *soc;
+
+soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS);
+npcm7xx_connect_dram(soc, machine->ram);
+qdev_realize(DEVICE(soc), NULL, _fatal);
+
+npcm7xx_load_kernel(machine, soc);
+}
+
+static void quanta_gsj_init(MachineState *machine)
+{
+NPCM7xxState *soc;
+
+soc = npcm7xx_create_soc(machine, QUANTA_GSJ_POWER_ON_STRAPS);
+npcm7xx_connect_dram(soc, machine->ram);
+

[PATCH v8 09/14] hw/mem: Stubbed out NPCM7xx Memory Controller model

2020-08-24 Thread Havard Skinnemoen via
This just implements the bare minimum to cause the boot block to skip
memory initialization.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h|  2 +
 include/hw/mem/npcm7xx_mc.h | 36 
 hw/arm/npcm7xx.c|  6 +++
 hw/mem/npcm7xx_mc.c | 84 +
 hw/mem/meson.build  |  1 +
 5 files changed, 129 insertions(+)
 create mode 100644 include/hw/mem/npcm7xx_mc.h
 create mode 100644 hw/mem/npcm7xx_mc.c

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 5816a07a72..9fa84a0702 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -18,6 +18,7 @@
 
 #include "hw/boards.h"
 #include "hw/cpu/a9mpcore.h"
+#include "hw/mem/npcm7xx_mc.h"
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
 #include "hw/nvram/npcm7xx_otp.h"
@@ -71,6 +72,7 @@ typedef struct NPCM7xxState {
 NPCM7xxTimerCtrlState tim[3];
 NPCM7xxOTPState key_storage;
 NPCM7xxOTPState fuse_array;
+NPCM7xxMCState  mc;
 } NPCM7xxState;
 
 #define TYPE_NPCM7XX"npcm7xx"
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
new file mode 100644
index 00..7ed38be243
--- /dev/null
+++ b/include/hw/mem/npcm7xx_mc.h
@@ -0,0 +1,36 @@
+/*
+ * Nuvoton NPCM7xx Memory Controller stub
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_MC_H
+#define NPCM7XX_MC_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/**
+ * struct NPCM7xxMCState - Device state for the memory controller.
+ * @parent: System bus device.
+ * @mmio: Memory region through which registers are accessed.
+ */
+typedef struct NPCM7xxMCState {
+SysBusDevice parent;
+
+MemoryRegion mmio;
+} NPCM7xxMCState;
+
+#define TYPE_NPCM7XX_MC "npcm7xx-mc"
+#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC)
+
+#endif /* NPCM7XX_MC_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 9166002598..6bb1693833 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -43,6 +43,7 @@
 #define NPCM7XX_CPUP_BA (0xf03fe000)
 #define NPCM7XX_GCR_BA  (0xf080)
 #define NPCM7XX_CLK_BA  (0xf0801000)
+#define NPCM7XX_MC_BA   (0xf0824000)
 
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
@@ -186,6 +187,7 @@ static void npcm7xx_init(Object *obj)
 TYPE_NPCM7XX_KEY_STORAGE);
 object_initialize_child(obj, "otp2", >fuse_array,
 TYPE_NPCM7XX_FUSE_ARRAY);
+object_initialize_child(obj, "mc", >mc, TYPE_NPCM7XX_MC);
 
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
@@ -261,6 +263,10 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>fuse_array), 0, NPCM7XX_OTP2_BA);
 npcm7xx_init_fuses(s);
 
+/* Fake Memory Controller (MC). Cannot fail. */
+sysbus_realize(SYS_BUS_DEVICE(>mc), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>mc), 0, NPCM7XX_MC_BA);
+
 /* Timer Modules (TIM). Cannot fail. */
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
new file mode 100644
index 00..0435d06ab4
--- /dev/null
+++ b/hw/mem/npcm7xx_mc.c
@@ -0,0 +1,84 @@
+/*
+ * Nuvoton NPCM7xx Memory Controller stub
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/mem/npcm7xx_mc.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+
+#defin

[PATCH v8 02/14] hw/misc: Add NPCM7xx Clock Controller device model

2020-08-24 Thread Havard Skinnemoen via
Enough functionality to boot the Linux kernel has been implemented. This
includes:

  - Correct power-on reset values so the various clock rates can be
accurately calculated.
  - Clock enables stick around when written.

In addition, a best effort attempt to implement SECCNT and CNTR25M was
made even though I don't think the kernel needs them.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/misc/npcm7xx_clk.h |  48 ++
 hw/misc/npcm7xx_clk.c | 266 ++
 hw/misc/meson.build   |   1 +
 hw/misc/trace-events  |   4 +
 4 files changed, 319 insertions(+)
 create mode 100644 include/hw/misc/npcm7xx_clk.h
 create mode 100644 hw/misc/npcm7xx_clk.c

diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
new file mode 100644
index 00..cdcc9e8534
--- /dev/null
+++ b/include/hw/misc/npcm7xx_clk.h
@@ -0,0 +1,48 @@
+/*
+ * Nuvoton NPCM7xx Clock Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_CLK_H
+#define NPCM7XX_CLK_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/*
+ * The reference clock frequency for the timer modules, and the SECCNT and
+ * CNTR25M registers in this module, is always 25 MHz.
+ */
+#define NPCM7XX_TIMER_REF_HZ(2500)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
+
+typedef struct NPCM7xxCLKState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint32_t regs[NPCM7XX_CLK_NR_REGS];
+
+/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
+int64_t ref_ns;
+} NPCM7xxCLKState;
+
+#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
+#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
+
+#endif /* NPCM7XX_CLK_H */
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
new file mode 100644
index 00..21ab4200d1
--- /dev/null
+++ b/hw/misc/npcm7xx_clk.c
@@ -0,0 +1,266 @@
+/*
+ * Nuvoton NPCM7xx Clock Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/misc/npcm7xx_clk.h"
+#include "migration/vmstate.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qemu/units.h"
+#include "trace.h"
+
+#define PLLCON_LOKI BIT(31)
+#define PLLCON_LOKS BIT(30)
+#define PLLCON_PWDENBIT(12)
+
+enum NPCM7xxCLKRegisters {
+NPCM7XX_CLK_CLKEN1,
+NPCM7XX_CLK_CLKSEL,
+NPCM7XX_CLK_CLKDIV1,
+NPCM7XX_CLK_PLLCON0,
+NPCM7XX_CLK_PLLCON1,
+NPCM7XX_CLK_SWRSTR,
+NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t),
+NPCM7XX_CLK_IPSRST2,
+NPCM7XX_CLK_CLKEN2,
+NPCM7XX_CLK_CLKDIV2,
+NPCM7XX_CLK_CLKEN3,
+NPCM7XX_CLK_IPSRST3,
+NPCM7XX_CLK_WD0RCR,
+NPCM7XX_CLK_WD1RCR,
+NPCM7XX_CLK_WD2RCR,
+NPCM7XX_CLK_SWRSTC1,
+NPCM7XX_CLK_SWRSTC2,
+NPCM7XX_CLK_SWRSTC3,
+NPCM7XX_CLK_SWRSTC4,
+NPCM7XX_CLK_PLLCON2,
+NPCM7XX_CLK_CLKDIV3,
+NPCM7XX_CLK_CORSTC,
+NPCM7XX_CLK_PLLCONG,
+NPCM7XX_CLK_AHBCKFI,
+NPCM7XX_CLK_SECCNT,
+NPCM7XX_CLK_CNTR25M,
+NPCM7XX_CLK_REGS_END,
+};
+
+/*
+ * These reset values were taken from version 0.91 of the NPCM750R data sheet.
+ *
+ * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on
+ * core domain reset, but this reset type is not yet supported by QEMU.
+ */
+static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
+[NPCM7XX_CLK_CLKEN1]= 0x,
+[NPCM7XX_CLK_CLKSEL]= 0x004a,
+[NPCM7XX_CLK_CLKDIV1]   = 0x5413f855,
+[NPCM7XX_CLK_PLLCON0]   = 0x00222101 |

[PATCH v8 10/14] hw/ssi: NPCM7xx Flash Interface Unit device model

2020-08-24 Thread Havard Skinnemoen via
This implements a device model for the NPCM7xx SPI flash controller.

Direct reads and writes, and user-mode transactions have been tested in
various modes. Protection features are not implemented yet.

All the FIU instances are available in the SoC's address space,
regardless of whether or not they're connected to actual flash chips.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/arm/npcm7xx.h |   2 +
 include/hw/ssi/npcm7xx_fiu.h |  73 +
 hw/arm/npcm7xx.c |  58 
 hw/ssi/npcm7xx_fiu.c | 572 +++
 hw/arm/Kconfig   |   1 +
 hw/ssi/meson.build   |   1 +
 hw/ssi/trace-events  |  11 +
 7 files changed, 718 insertions(+)
 create mode 100644 include/hw/ssi/npcm7xx_fiu.h
 create mode 100644 hw/ssi/npcm7xx_fiu.c

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 9fa84a0702..78d0d78c52 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -23,6 +23,7 @@
 #include "hw/misc/npcm7xx_gcr.h"
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
+#include "hw/ssi/npcm7xx_fiu.h"
 #include "target/arm/cpu.h"
 
 #define NPCM7XX_MAX_NUM_CPUS(2)
@@ -73,6 +74,7 @@ typedef struct NPCM7xxState {
 NPCM7xxOTPState key_storage;
 NPCM7xxOTPState fuse_array;
 NPCM7xxMCState  mc;
+NPCM7xxFIUState fiu[2];
 } NPCM7xxState;
 
 #define TYPE_NPCM7XX"npcm7xx"
diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h
new file mode 100644
index 00..a3a1704289
--- /dev/null
+++ b/include/hw/ssi/npcm7xx_fiu.h
@@ -0,0 +1,73 @@
+/*
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_FIU_H
+#define NPCM7XX_FIU_H
+
+#include "hw/ssi/ssi.h"
+#include "hw/sysbus.h"
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t))
+
+typedef struct NPCM7xxFIUState NPCM7xxFIUState;
+
+/**
+ * struct NPCM7xxFIUFlash - Per-chipselect flash controller state.
+ * @direct_access: Memory region for direct flash access.
+ * @fiu: Pointer to flash controller shared state.
+ */
+typedef struct NPCM7xxFIUFlash {
+MemoryRegion direct_access;
+NPCM7xxFIUState *fiu;
+} NPCM7xxFIUFlash;
+
+/**
+ * NPCM7xxFIUState - Device state for one Flash Interface Unit.
+ * @parent: System bus device.
+ * @mmio: Memory region for register access.
+ * @cs_count: Number of flash chips that may be connected to this module.
+ * @active_cs: Currently active chip select, or -1 if no chip is selected.
+ * @cs_lines: GPIO lines that may be wired to flash chips.
+ * @flash: Array of @cs_count per-flash-chip state objects.
+ * @spi: The SPI bus mastered by this controller.
+ * @regs: Register contents.
+ *
+ * Each FIU has a shared bank of registers, and controls up to four chip
+ * selects. Each chip select has a dedicated memory region which may be used to
+ * read and write the flash connected to that chip select as if it were memory.
+ */
+struct NPCM7xxFIUState {
+SysBusDevice parent;
+
+MemoryRegion mmio;
+
+int32_t cs_count;
+int32_t active_cs;
+qemu_irq *cs_lines;
+NPCM7xxFIUFlash *flash;
+
+SSIBus *spi;
+
+uint32_t regs[NPCM7XX_FIU_NR_REGS];
+};
+
+#define TYPE_NPCM7XX_FIU "npcm7xx-fiu"
+#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU)
+
+#endif /* NPCM7XX_FIU_H */
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 6bb1693833..7884b2b03d 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -99,6 +99,39 @@ static const hwaddr npcm7xx_uart_addr[] = {
 0xf0004000,
 };
 
+/* Direct memory-mapped access to SPI0 CS0-1. */
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
+0x8000, /* CS0 */
+0x8800, /* CS1 */
+};
+
+/* Direct memory-mapped access to SPI3 CS0-3. */
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
+0xa000, /* CS0 */
+0xa800, /* CS1 */
+0xb000, /* CS2 */
+0xb800, /* CS3 */
+};
+
+static const struct {
+const char *name;
+hwaddr regs_addr;
+int cs_count;
+const hwaddr *flash_addr;
+} npcm7xx_fiu[] = {
+{
+.name = "fiu0",
+.re

[PATCH v8 01/14] hw/misc: Add NPCM7xx System Global Control Registers device model

2020-08-24 Thread Havard Skinnemoen via
Implement a device model for the System Global Control Registers in the
NPCM730 and NPCM750 BMC SoCs.

This is primarily used to enable SMP boot (the boot ROM spins reading
the SCRPAD register) and DDR memory initialization; other registers are
best effort for now.

The reset values of the MDLR and PWRON registers are determined by the
SoC variant (730 vs 750) and board straps respectively.

Reviewed-by: Joel Stanley 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/misc/npcm7xx_gcr.h |  43 ++
 hw/misc/npcm7xx_gcr.c | 269 ++
 MAINTAINERS   |   8 +
 hw/arm/Kconfig|   3 +
 hw/misc/meson.build   |   3 +
 hw/misc/trace-events  |   4 +
 6 files changed, 330 insertions(+)
 create mode 100644 include/hw/misc/npcm7xx_gcr.h
 create mode 100644 hw/misc/npcm7xx_gcr.c

diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
new file mode 100644
index 00..13109d9d32
--- /dev/null
+++ b/include/hw/misc/npcm7xx_gcr.h
@@ -0,0 +1,43 @@
+/*
+ * Nuvoton NPCM7xx System Global Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_GCR_H
+#define NPCM7XX_GCR_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
+
+typedef struct NPCM7xxGCRState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint32_t regs[NPCM7XX_GCR_NR_REGS];
+
+uint32_t reset_pwron;
+uint32_t reset_mdlr;
+uint32_t reset_intcr3;
+} NPCM7xxGCRState;
+
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
+#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
+
+#endif /* NPCM7XX_GCR_H */
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
new file mode 100644
index 00..745f690809
--- /dev/null
+++ b/hw/misc/npcm7xx_gcr.c
@@ -0,0 +1,269 @@
+/*
+ * Nuvoton NPCM7xx System Global Control Registers.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/misc/npcm7xx_gcr.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+
+#include "trace.h"
+
+#define NPCM7XX_GCR_MIN_DRAM_SIZE   (128 * MiB)
+#define NPCM7XX_GCR_MAX_DRAM_SIZE   (2 * GiB)
+
+enum NPCM7xxGCRRegisters {
+NPCM7XX_GCR_PDID,
+NPCM7XX_GCR_PWRON,
+NPCM7XX_GCR_MFSEL1  = 0x0c / sizeof(uint32_t),
+NPCM7XX_GCR_MFSEL2,
+NPCM7XX_GCR_MISCPE,
+NPCM7XX_GCR_SPSWC   = 0x038 / sizeof(uint32_t),
+NPCM7XX_GCR_INTCR,
+NPCM7XX_GCR_INTSR,
+NPCM7XX_GCR_HIFCR   = 0x050 / sizeof(uint32_t),
+NPCM7XX_GCR_INTCR2  = 0x060 / sizeof(uint32_t),
+NPCM7XX_GCR_MFSEL3,
+NPCM7XX_GCR_SRCNT,
+NPCM7XX_GCR_RESSR,
+NPCM7XX_GCR_RLOCKR1,
+NPCM7XX_GCR_FLOCKR1,
+NPCM7XX_GCR_DSCNT,
+NPCM7XX_GCR_MDLR,
+NPCM7XX_GCR_SCRPAD3,
+NPCM7XX_GCR_SCRPAD2,
+NPCM7XX_GCR_DAVCLVLR= 0x098 / sizeof(uint32_t),
+NPCM7XX_GCR_INTCR3,
+NPCM7XX_GCR_VSINTR  = 0x0ac / sizeof(uint32_t),
+NPCM7XX_GCR_MFSEL4,
+NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t),
+NPCM7XX_GCR_CPCTL   = 0x0d0 / sizeof(uint32_t),
+NPCM7XX_GCR_CP2BST,
+NPCM7XX_GCR_B2CPNT,
+NPCM7XX_GCR_CPPCTL,
+NPCM7XX_GCR_I2CSEGSEL,
+NPCM7XX_GCR_I2CSEGCTL,
+NPCM7XX_GCR_VSRCR,
+NPCM7XX_GCR_MLOCKR,
+NPCM7XX_GCR_SCRPAD  = 0x013c / sizeof(uint32_t),
+NPCM7XX_GCR_USB1PHYCTL,
+NPCM7XX_GCR_USB2PHYCTL,
+NPCM7XX_GCR_REGS_END,
+};
+
+static const uint32_t c

[PATCH v8 03/14] hw/timer: Add NPCM7xx Timer device model

2020-08-24 Thread Havard Skinnemoen via
The NPCM730 and NPCM750 SoCs have three timer modules each holding five
timers and some shared registers (e.g. interrupt status).

Each timer runs at 25 MHz divided by a prescaler, and counts down from a
configurable initial value to zero. When zero is reached, the interrupt
flag for the timer is set, and the timer is disabled (one-shot mode) or
reloaded from its initial value (periodic mode).

This implementation is sufficient to boot a Linux kernel configured for
NPCM750. Note that the kernel does not seem to actually turn on the
interrupts.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 include/hw/timer/npcm7xx_timer.h |  78 +
 hw/timer/npcm7xx_timer.c | 509 +++
 hw/timer/meson.build |   1 +
 hw/timer/trace-events|   5 +
 4 files changed, 593 insertions(+)
 create mode 100644 include/hw/timer/npcm7xx_timer.h
 create mode 100644 hw/timer/npcm7xx_timer.c

diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
new file mode 100644
index 00..878a365a79
--- /dev/null
+++ b/include/hw/timer/npcm7xx_timer.h
@@ -0,0 +1,78 @@
+/*
+ * Nuvoton NPCM7xx Timer Controller
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_TIMER_H
+#define NPCM7XX_TIMER_H
+
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+
+/* Each Timer Module (TIM) instance holds five 25 MHz timers. */
+#define NPCM7XX_TIMERS_PER_CTRL (5)
+
+/*
+ * Number of registers in our device state structure. Don't change this without
+ * incrementing the version_id in the vmstate.
+ */
+#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
+
+typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
+
+/**
+ * struct NPCM7xxTimer - Individual timer state.
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
+ * @qtimer: QEMU timer that notifies us on expiration.
+ * @expires_ns: Absolute virtual expiration time.
+ * @remaining_ns: Remaining time until expiration if timer is paused.
+ * @tcsr: The Timer Control and Status Register.
+ * @ticr: The Timer Initial Count Register.
+ */
+typedef struct NPCM7xxTimer {
+NPCM7xxTimerCtrlState *ctrl;
+
+qemu_irqirq;
+QEMUTimer   qtimer;
+int64_t expires_ns;
+int64_t remaining_ns;
+
+uint32_ttcsr;
+uint32_tticr;
+} NPCM7xxTimer;
+
+/**
+ * struct NPCM7xxTimerCtrlState - Timer Module device state.
+ * @parent: System bus device.
+ * @iomem: Memory region through which registers are accessed.
+ * @tisr: The Timer Interrupt Status Register.
+ * @wtcr: The Watchdog Timer Control Register.
+ * @timer: The five individual timers managed by this module.
+ */
+struct NPCM7xxTimerCtrlState {
+SysBusDevice parent;
+
+MemoryRegion iomem;
+
+uint32_ttisr;
+uint32_twtcr;
+
+NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
+};
+
+#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
+#define NPCM7XX_TIMER(obj)  \
+OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER)
+
+#endif /* NPCM7XX_TIMER_H */
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
new file mode 100644
index 00..ad5ebd9878
--- /dev/null
+++ b/hw/timer/npcm7xx_timer.c
@@ -0,0 +1,509 @@
+/*
+ * Nuvoton NPCM7xx Timer Controller
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/irq.h"
+#include "hw/misc/npcm7xx_clk.h"
+#include "hw/timer/npcm7xx_timer.h"
+#include "migration/vmstate.h"
+#include "qemu/bitops.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qemu/units.h"
+#include "trace.h"
+
+/* 32-bit register indices. */
+enum NPCM7xxTimerRegi

[PATCH v8 00/14] Add Nuvoton NPCM730/NPCM750 SoCs and two BMC machines

2020-08-24 Thread Havard Skinnemoen via
 improvements.
  - Split the first patch and folded parts of it into three other patches so
that CONFIG_NPCM7XX is only enabled after the initial NPCM7xx machine
support is added.
  - DRAM init moved to machine init code.
  - Consistently use lower-case hex literals.
  - Switched to fine-grained unimplemented devices, based on public bootblock
source code. Added a tiny SRAM that got left out previously.
  - Simplified error handling in npcm7xx_realize() since the board code will
abort anyway, and SoCs are not hot-pluggable.

Changes since v3:

  - License headers are now GPL v2-or-later throughout.
  - Added vmstate throughout (except the memory controller, which doesn't
really have any state worth saving). Successfully booted a gsj image
with two stop/savevm/quit/loadvm cycles along the way.
  - JFFS2 really doesn't like it if I let qemu keep running after savevm,
and then jump back in time with loadvm. I assume this is expected.
  - Fixed an error API violation in npcm7xx_realize, removed pointless error
check after object_property_set_link().
  - Switched the OTP device to use an embedded array instead of a g_malloc0'd
one because I couldn't figure out how to set up vmstate for the latter.

Changes since v2:

  - Simplified the MAINTAINERS entry.
  - Added link to OpenPOWER jenkins for gsj BMC images.
  - Reverted the smpboot change, back to byte swapping.
  - Adapted to upstream API changes:
  - sysbus_init_child_obj -> object_initialize_child
  - object_property_set_bool -> qdev_realize / sysbus_realize
  - ssi_create_slave_no_init -> qdev_new
  - qdev_init_nofail -> qdev_realize_and_unref
  - ssi_auto_connect_slaves removed
  - Moved Boot ROM loading from soc to machine init.
  - Plumbed power-on-straps property from GCR to the machine init code so it
can be properly initialized. Turns out npcm750 memory init doesn't work
without this. npcm730 is fine either way, though I'm not sure why.
  - Reworked the flash init code so it looks more like aspeed (i.e. the flash
device gets added even if there's no drive).

Changes since v1 (requested by reviewers):

  - Clarify the source of CLK reset values.
  - Made smpboot a constant byte array, eliinated byte swapping.
  - NPCM7xxState now stores an array of ARMCPUs, not pointers to ARMCPUs.
  - Clarify why EL3 is disabled.
  - Introduce NPCM7XX_NUM_IRQ constant.
  - Set the number of CPUs according to SoC variant, and disallow command line
overrides (i.e. you can no longer override the number of CPUs with the -smp
parameter). This is trying to follow the spirit of
https://patchwork.kernel.org/patch/11595407/.
  - Switch register operations to DEVICE_LITTLE_ENDIAN throughout.
  - Machine documentation added (new patch).

Changes since v1 to support flash booting:

  - GCR reset value changes to get past memory initialization when booting
from flash (patches 2 and 5):
  - INTCR2 now indicates that the DDR controller is initialized.
  - INTCR3 is initialized according to DDR memory size. A realize()
method was implemented to achieve this.
  - Refactor the machine initialization a bit to make it easier to drop in
machine-specific flash initialization (patch 6).
  - Extend the series with additional patches to enable booting from flash:
  - Boot ROM (through the -bios option).
  - OTP (fuse) controller.
  - Memory Controller stub (just enough to skip memory training).
  - Flash controller.
  - Board-specific flash initialization.

Thanks for reviewing,

Havard

Havard Skinnemoen (14):
  hw/misc: Add NPCM7xx System Global Control Registers device model
  hw/misc: Add NPCM7xx Clock Controller device model
  hw/timer: Add NPCM7xx Timer device model
  hw/arm: Add NPCM730 and NPCM750 SoC models
  hw/arm: Add two NPCM7xx-based machines
  roms: Add virtual Boot ROM for NPCM7xx SoCs
  hw/arm: Load -bios image as a boot ROM for npcm7xx
  hw/nvram: NPCM7xx OTP device model
  hw/mem: Stubbed out NPCM7xx Memory Controller model
  hw/ssi: NPCM7xx Flash Interface Unit device model
  hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj
  hw/arm/npcm7xx: add board setup stub for CPU and UART clocks
  docs/system: Add Nuvoton machine documentation
  tests/acceptance: console boot tests for quanta-gsj

 docs/system/arm/nuvoton.rst|  90 
 docs/system/target-arm.rst |   1 +
 Makefile   |   1 +
 default-configs/arm-softmmu.mak|   1 +
 include/hw/arm/npcm7xx.h   | 112 +
 include/hw/mem/npcm7xx_mc.h|  36 ++
 include/hw/misc/npcm7xx_clk.h  |  48 +++
 include/hw/misc/npcm7xx_gcr.h  |  43 ++
 include/hw/nvram/npcm7xx_otp.h |  79 
 include/hw/ssi/npcm7xx_fiu.h   |  73 
 include/hw/timer/npcm7xx_timer.h   |  78 
 hw/arm/npcm7xx.c   | 532 +++
 hw/arm/npcm

Re: [PATCH v7 13/13] tests/acceptance: console boot tests for quanta-gsj

2020-08-20 Thread Havard Skinnemoen
On Thu, Aug 20, 2020 at 10:46 AM Philippe Mathieu-Daudé  wrote:
>
> On 8/20/20 6:24 PM, Havard Skinnemoen wrote:
> > On Wed, Aug 19, 2020 at 10:29 PM Philippe Mathieu-Daudé  
> > wrote:
> >>
> >> +Eric / Richard for compiler optimizations.
> >>
> >> On 8/20/20 3:53 AM, Havard Skinnemoen wrote:
> >>> On Tue, Aug 11, 2020 at 8:26 PM Havard Skinnemoen
> >>>  wrote:
> >>>>
> >>>> On Tue, Aug 11, 2020 at 1:48 AM Philippe Mathieu-Daudé  
> >>>> wrote:
> >>>>> INTERRUPTED: Test interrupted by SIGTERM
> >>>>> Runner error occurred: Timeout reached
> >>>>> (240.45 s)
> >>>>>
> >>>>> Is that expected?
> >>>>
> >>>> I'm not sure why it only happens when running direct kernel boot with
> >>>> unoptimized qemu, but it seems a little happier if I enable a few more
> >>>> peripherals that I have queued up (sd, ehci, ohci and rng), though not
> >>>> enough.
> >>>>
> >>>> It still stalls for an awfully long time on "console: Run /init as
> >>>> init process" though. I'm not sure what it's doing there. With -O2 it
> >>>> only takes a couple of seconds to move on.
> >>>
> >>> So it turns out that the kernel gets _really_ sluggish when skipping
> >>> the clock initialization normally done by the boot loader.
> >>>
> >>> I changed the reset value of CLKSEL like this:
> >>>
> >>> diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
> >>> index 21ab4200d1..5e9849410f 100644
> >>> --- a/hw/misc/npcm7xx_clk.c
> >>> +++ b/hw/misc/npcm7xx_clk.c
> >>> @@ -67,7 +67,7 @@ enum NPCM7xxCLKRegisters {
> >>>   */
> >>>  static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
> >>>  [NPCM7XX_CLK_CLKEN1]= 0x,
> >>> -[NPCM7XX_CLK_CLKSEL]= 0x004a,
> >>> +[NPCM7XX_CLK_CLKSEL]= 0x004aaba9,
> >>>  [NPCM7XX_CLK_CLKDIV1]   = 0x5413f855,
> >>>  [NPCM7XX_CLK_PLLCON0]   = 0x00222101 | PLLCON_LOKI,
> >>>  [NPCM7XX_CLK_PLLCON1]   = 0x00202101 | PLLCON_LOKI,
> >>>
> >>> which switches the CPU core and UART to run from PLL2 instead of
> >>> CLKREF (25 MHz).
> >>>
> >>> With this change, the test passes without optimization:
> >>>
> >>>  (02/19) 
> >>> tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_quanta_gsj_initrd:
> >>> PASS (39.62 s)
> >>>
> >>> It doesn't look like this change hurts booting from the bootrom (IIUC
> >>> the nuvoton bootblock overwrites CLKSEL anyway), but it's not super
> >>> clean.
> >>>
> >>> Perhaps I should make it conditional on kernel_filename being set? Or
> >>> would it be better to provide a write_board_setup hook for this?
> >>
> >> QEMU prefers to avoid ifdef'ry at all cost. However I find this
> >> approach acceptable (anyway up to the maintainer):
> >>
> >> +static void npcm7xx_clk_cold_reset_fixup(NPCM7xxCLKState *s)
> >> +{
> >> +#ifndef __OPTIMIZE__
> >> +/*
> >> + * When built without optimization, ...
> >> + * so run CPU core and UART from PLL2 instead of CLKREF.
> >> + */
> >> +s->regs[NPCM7XX_CLK_CLKSEL] |= 0x103,
> >> +#endif
> >> +}
> >
> > I think this is actually a problem regardless of optimization level.
> > Turning optimization off amplifies the problem, but the problem is
> > still there with optimization on.
>
> OK, this reminds me few more details about the problem I had with the
> raspi3 when adding the ClockPowerResetManager block.
> Found the branch. A bit bitter/sad it was more than 1 year ago.
>
> So if ARM_FEATURE_GENERIC_TIMER is available, Linux polls the CNTFRQ_EL0
> register. At that time this register were using a fixed frequency:
>
> #define ARM_CPU_FREQ 10 /* FIXME: 1 GHz, should be configurable */
>
> Xilinx' fork does it this way:
> https://github.com/Xilinx/qemu/commit/9e939b54e2d
>
> Now I see Andrew Jeffery fixed that in 96eec6b2b38
> ("target/arm: Prepare generic timer for per-platform CNTFRQ")
> adding a 'cntfrq' property, which he then sets in the Aspeed
> machine in commit 058d095532d ("ast2600: Configure CNTFRQ at 1125MHz").
>
> Maybe your SoC is simply missing th

Re: [PATCH v7 13/13] tests/acceptance: console boot tests for quanta-gsj

2020-08-20 Thread Havard Skinnemoen
On Wed, Aug 19, 2020 at 10:29 PM Philippe Mathieu-Daudé  wrote:
>
> +Eric / Richard for compiler optimizations.
>
> On 8/20/20 3:53 AM, Havard Skinnemoen wrote:
> > On Tue, Aug 11, 2020 at 8:26 PM Havard Skinnemoen
> >  wrote:
> >>
> >> On Tue, Aug 11, 2020 at 1:48 AM Philippe Mathieu-Daudé  
> >> wrote:
> >>> INTERRUPTED: Test interrupted by SIGTERM
> >>> Runner error occurred: Timeout reached
> >>> (240.45 s)
> >>>
> >>> Is that expected?
> >>
> >> I'm not sure why it only happens when running direct kernel boot with
> >> unoptimized qemu, but it seems a little happier if I enable a few more
> >> peripherals that I have queued up (sd, ehci, ohci and rng), though not
> >> enough.
> >>
> >> It still stalls for an awfully long time on "console: Run /init as
> >> init process" though. I'm not sure what it's doing there. With -O2 it
> >> only takes a couple of seconds to move on.
> >
> > So it turns out that the kernel gets _really_ sluggish when skipping
> > the clock initialization normally done by the boot loader.
> >
> > I changed the reset value of CLKSEL like this:
> >
> > diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
> > index 21ab4200d1..5e9849410f 100644
> > --- a/hw/misc/npcm7xx_clk.c
> > +++ b/hw/misc/npcm7xx_clk.c
> > @@ -67,7 +67,7 @@ enum NPCM7xxCLKRegisters {
> >   */
> >  static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
> >  [NPCM7XX_CLK_CLKEN1]= 0x,
> > -[NPCM7XX_CLK_CLKSEL]= 0x004a,
> > +[NPCM7XX_CLK_CLKSEL]= 0x004aaba9,
> >  [NPCM7XX_CLK_CLKDIV1]   = 0x5413f855,
> >  [NPCM7XX_CLK_PLLCON0]   = 0x00222101 | PLLCON_LOKI,
> >  [NPCM7XX_CLK_PLLCON1]   = 0x00202101 | PLLCON_LOKI,
> >
> > which switches the CPU core and UART to run from PLL2 instead of
> > CLKREF (25 MHz).
> >
> > With this change, the test passes without optimization:
> >
> >  (02/19) 
> > tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_quanta_gsj_initrd:
> > PASS (39.62 s)
> >
> > It doesn't look like this change hurts booting from the bootrom (IIUC
> > the nuvoton bootblock overwrites CLKSEL anyway), but it's not super
> > clean.
> >
> > Perhaps I should make it conditional on kernel_filename being set? Or
> > would it be better to provide a write_board_setup hook for this?
>
> QEMU prefers to avoid ifdef'ry at all cost. However I find this
> approach acceptable (anyway up to the maintainer):
>
> +static void npcm7xx_clk_cold_reset_fixup(NPCM7xxCLKState *s)
> +{
> +#ifndef __OPTIMIZE__
> +/*
> + * When built without optimization, ...
> + * so run CPU core and UART from PLL2 instead of CLKREF.
> + */
> +s->regs[NPCM7XX_CLK_CLKSEL] |= 0x103,
> +#endif
> +}

I think this is actually a problem regardless of optimization level.
Turning optimization off amplifies the problem, but the problem is
still there with optimization on.

This does not affect booting a full flash image, as these fixups (and
more) are done by the boot loader in that case.

Havard



Re: [PATCH v7 13/13] tests/acceptance: console boot tests for quanta-gsj

2020-08-19 Thread Havard Skinnemoen
On Tue, Aug 11, 2020 at 8:26 PM Havard Skinnemoen
 wrote:
>
> On Tue, Aug 11, 2020 at 1:48 AM Philippe Mathieu-Daudé  
> wrote:
> > INTERRUPTED: Test interrupted by SIGTERM
> > Runner error occurred: Timeout reached
> > (240.45 s)
> >
> > Is that expected?
>
> I'm not sure why it only happens when running direct kernel boot with
> unoptimized qemu, but it seems a little happier if I enable a few more
> peripherals that I have queued up (sd, ehci, ohci and rng), though not
> enough.
>
> It still stalls for an awfully long time on "console: Run /init as
> init process" though. I'm not sure what it's doing there. With -O2 it
> only takes a couple of seconds to move on.

So it turns out that the kernel gets _really_ sluggish when skipping
the clock initialization normally done by the boot loader.

I changed the reset value of CLKSEL like this:

diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
index 21ab4200d1..5e9849410f 100644
--- a/hw/misc/npcm7xx_clk.c
+++ b/hw/misc/npcm7xx_clk.c
@@ -67,7 +67,7 @@ enum NPCM7xxCLKRegisters {
  */
 static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
 [NPCM7XX_CLK_CLKEN1]= 0x,
-[NPCM7XX_CLK_CLKSEL]= 0x004a,
+[NPCM7XX_CLK_CLKSEL]= 0x004aaba9,
 [NPCM7XX_CLK_CLKDIV1]   = 0x5413f855,
 [NPCM7XX_CLK_PLLCON0]   = 0x00222101 | PLLCON_LOKI,
 [NPCM7XX_CLK_PLLCON1]   = 0x00202101 | PLLCON_LOKI,

which switches the CPU core and UART to run from PLL2 instead of
CLKREF (25 MHz).

With this change, the test passes without optimization:

 (02/19) 
tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_quanta_gsj_initrd:
PASS (39.62 s)

It doesn't look like this change hurts booting from the bootrom (IIUC
the nuvoton bootblock overwrites CLKSEL anyway), but it's not super
clean.

Perhaps I should make it conditional on kernel_filename being set? Or
would it be better to provide a write_board_setup hook for this?



Re: [PATCH v7 13/13] tests/acceptance: console boot tests for quanta-gsj

2020-08-11 Thread Havard Skinnemoen
On Tue, Aug 11, 2020 at 1:48 AM Philippe Mathieu-Daudé  wrote:
>
> Hi Havard,
>
> On 8/11/20 2:46 AM, Havard Skinnemoen wrote:
> > This adds two acceptance tests for the quanta-gsj machine.
> >
> > One test downloads a lightly patched openbmc flash image from github and
> > verifies that it boots all the way to the login prompt.
> >
> > The other test downloads a kernel, initrd and dtb built from the same
> > openbmc source and verifies that the kernel detects all CPUs and boots
> > to the point where it can't find the root filesystem (because we have no
> > flash image in this case).
> >
> > Reviewed-by: Philippe Mathieu-Daudé 
> > Signed-off-by: Havard Skinnemoen 
> > ---
> >  tests/acceptance/boot_linux_console.py | 65 ++
> >  1 file changed, 65 insertions(+)
> >
> > diff --git a/tests/acceptance/boot_linux_console.py 
> > b/tests/acceptance/boot_linux_console.py
> > index 73cc69c499..8592f33a41 100644
> > --- a/tests/acceptance/boot_linux_console.py
> > +++ b/tests/acceptance/boot_linux_console.py
> > @@ -569,6 +569,71 @@ class BootLinuxConsole(LinuxKernelTest):
> >  'sda')
> >  # cubieboard's reboot is not functioning; omit reboot test.
> >
> > +def test_arm_quanta_gsj(self):
> > +"""
> > +:avocado: tags=arch:arm
> > +:avocado: tags=machine:quanta-gsj
> > +"""
> > +# 25 MiB compressed, 32 MiB uncompressed.
> > +image_url = (
> > +'https://github.com/hskinnemoen/openbmc/releases/download/'
> > +
> > '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
> > +image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
> > +image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
> > +image_name = 'obmc.mtd'
> > +image_path = os.path.join(self.workdir, image_name)
> > +archive.gzip_uncompress(image_path_gz, image_path)
> > +
> > +self.vm.set_console()
> > +drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
> > +self.vm.add_args('-drive', drive_args)
> > +self.vm.launch()
> > +
> > +self.wait_for_console_pattern('> BootBlock by Nuvoton')
> > +self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
> > +self.wait_for_console_pattern('>Skip DDR init.')
> > +self.wait_for_console_pattern('U-Boot ')
> > +self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
>
> Tests timeout using QEMU configured with '--enable-debug
> --extra-cflags=-ggdb':
>
> console: Booting Linux on physical CPU 0x0
> console: CPU1: thread -1, cpu 1, socket 0, mpidr 8001
>
> console: stmmaceth f0802000.eth: DMA HW capability register supported
> console: stmmaceth f0802000.eth: Normal descriptors
> console: stmmaceth f0802000.eth: Ring mode enabled
> console: stmmaceth f0802000.eth: device MAC address 92:f6:8f:80:9f:bb
> INTERRUPTED: Test interrupted by SIGTERM
> Runner error occurred: Timeout reached
> (91.05 s)
>
> My guess is unoptimized build makes guest hashing checks over
> the bitbanged SPI flash emulation takes too long.

Right, flash access is super slow when optimization is turned off.

> Trying with timeout=240s:
>
> console: [* ] (1 of 2) A start job is running for…dplug all Devices
> (44s / no limit)
> console: [**] (2 of 2) A start job is running for…Save Random Seed
> (44s / 10min 13s)
> console: [***   ] (2 of 2) A start job is running for…Save Random Seed
> (45s / 10min 13s)
> console: [ ***  ] (2 of 2) A start job is running for…Save Random Seed
> (45s / 10min 13s)
> console: [  *** ] (1 of 2) A start job is running for…dplug all Devices
> (46s / no limit)
> console: [   ***] (1 of 2) A start job is running for…dplug all Devices
> (46s / no limit)
> console: [**] (1 of 2) A start job is running for…dplug all Devices
> (47s / no limit)
> console: [ *] (2 of 2) A start job is running for…Save Random Seed
> (47s / 10min 13s)
> console: [**] (2 of 2) A start job is running for…Save Random Seed
> (48s / 10min 13s)
> console: [   ***] (2 of 2) A start job is running for…Save Random Seed
> (48s / 10min 13s)
> console: [  *** ] (1 of 2) A start job is running for…dplug all Devices
> (49s / no limit)
> console: [ ***  ] (1 of 2) A start job is running for…dplug all Devices
> (51s / no limit)
> console: [***   ] (1 of 2) A start job is running for…dplug all Devices
> (53s / no limit)
> console: [**] (

[PATCH v7 13/13] tests/acceptance: console boot tests for quanta-gsj

2020-08-10 Thread Havard Skinnemoen
This adds two acceptance tests for the quanta-gsj machine.

One test downloads a lightly patched openbmc flash image from github and
verifies that it boots all the way to the login prompt.

The other test downloads a kernel, initrd and dtb built from the same
openbmc source and verifies that the kernel detects all CPUs and boots
to the point where it can't find the root filesystem (because we have no
flash image in this case).

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 tests/acceptance/boot_linux_console.py | 65 ++
 1 file changed, 65 insertions(+)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 73cc69c499..8592f33a41 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -569,6 +569,71 @@ class BootLinuxConsole(LinuxKernelTest):
 'sda')
 # cubieboard's reboot is not functioning; omit reboot test.
 
+def test_arm_quanta_gsj(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:quanta-gsj
+"""
+# 25 MiB compressed, 32 MiB uncompressed.
+image_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
+image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
+image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
+image_name = 'obmc.mtd'
+image_path = os.path.join(self.workdir, image_name)
+archive.gzip_uncompress(image_path_gz, image_path)
+
+self.vm.set_console()
+drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
+self.vm.add_args('-drive', drive_args)
+self.vm.launch()
+
+self.wait_for_console_pattern('> BootBlock by Nuvoton')
+self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
+self.wait_for_console_pattern('>Skip DDR init.')
+self.wait_for_console_pattern('U-Boot ')
+self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
+self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
+self.wait_for_console_pattern('OpenBMC Project Reference Distro')
+self.wait_for_console_pattern('gsj login:')
+
+def test_arm_quanta_gsj_initrd(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:quanta-gsj
+"""
+initrd_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
+initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
+initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+kernel_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/uImage-gsj.bin')
+kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
+kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+dtb_url = (
+'https://github.com/hskinnemoen/openbmc/releases/download/'
+'20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
+dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
+dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'console=ttyS0,115200n8 '
+   'earlycon=uart8250,mmio32,0xf0001000')
+self.vm.add_args('-kernel', kernel_path,
+ '-initrd', initrd_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line)
+self.vm.launch()
+
+self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
+self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
+self.wait_for_console_pattern(
+'Give root password for system maintenance')
+
 def test_arm_orangepi(self):
 """
 :avocado: tags=arch:arm
-- 
2.28.0.236.gb10cc79966-goog




[PATCH v7 12/13] docs/system: Add Nuvoton machine documentation

2020-08-10 Thread Havard Skinnemoen
Reviewed-by: Cédric Le Goater 
Signed-off-by: Havard Skinnemoen 
---
 docs/system/arm/nuvoton.rst | 90 +
 docs/system/target-arm.rst  |  1 +
 2 files changed, 91 insertions(+)
 create mode 100644 docs/system/arm/nuvoton.rst

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
new file mode 100644
index 00..36bf901122
--- /dev/null
+++ b/docs/system/arm/nuvoton.rst
@@ -0,0 +1,90 @@
+Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``)
+=
+
+The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are
+designed to be used as Baseboard Management Controllers (BMCs) in various
+servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an
+assortment of peripherals targeted for either Enterprise or Data Center /
+Hyperscale applications. The former is a superset of the latter, so NPCM750 has
+all the peripherals of NPCM730 and more.
+
+.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/
+
+The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise
+segment. The following machines are based on this chip :
+
+- ``npcm750-evb``   Nuvoton NPCM750 Evaluation board
+
+The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and
+Hyperscale applications. The following machines are based on this chip :
+
+- ``quanta-gsj``Quanta GSJ server BMC
+
+There are also two more SoCs, NPCM710 and NPCM705, which are single-core
+variants of NPCM750 and NPCM730, respectively. These are currently not
+supported by QEMU.
+
+Supported devices
+-
+
+ * SMP (Dual Core Cortex-A9)
+ * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer
+   and Watchdog.
+ * SRAM, ROM and DRAM mappings
+ * System Global Control Registers (GCR)
+ * Clock and reset controller (CLK)
+ * Timer controller (TIM)
+ * Serial ports (16550-based)
+ * DDR4 memory controller (dummy interface indicating memory training is done)
+ * OTP controllers (no protection features)
+ * Flash Interface Unit (FIU; no protection features)
+
+Missing devices
+---
+
+ * GPIO controller
+ * LPC/eSPI host-to-BMC interface, including
+
+   * Keyboard and mouse controller interface (KBCI)
+   * Keyboard Controller Style (KCS) channels
+   * BIOS POST code FIFO
+   * System Wake-up Control (SWC)
+   * Shared memory (SHM)
+   * eSPI slave interface
+
+ * Ethernet controllers (GMAC and EMC)
+ * USB host (USBH)
+ * USB device (USBD)
+ * SMBus controller (SMBF)
+ * Peripheral SPI controller (PSPI)
+ * Analog to Digital Converter (ADC)
+ * SD/MMC host
+ * Random Number Generator (RNG)
+ * PECI interface
+ * Pulse Width Modulation (PWM)
+ * Tachometer
+ * PCI and PCIe root complex and bridges
+ * VDM and MCTP support
+ * Serial I/O expansion
+ * LPC/eSPI host
+ * Coprocessor
+ * Graphics
+ * Video capture
+ * Encoding compression engine
+ * Security features
+
+Boot options
+
+
+The Nuvoton machines can boot from an OpenBMC firmware image, or directly into
+a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and
+possibly others can be downloaded from the OpenPOWER jenkins :
+
+   https://openpower.xyz/
+
+The firmware image should be attached as an MTD drive. Example :
+
+.. code-block:: bash
+
+  $ qemu-system-arm -machine quanta-gsj -nographic \
+  -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index 4c5b0e4aab..4c0da725ee 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -86,6 +86,7 @@ undocumented; you can get a complete list by running
arm/musicpal
arm/gumstix
arm/nseries
+   arm/nuvoton
arm/orangepi
arm/palm
arm/xscale
-- 
2.28.0.236.gb10cc79966-goog




[PATCH v7 10/13] hw/ssi: NPCM7xx Flash Interface Unit device model

2020-08-10 Thread Havard Skinnemoen
This implements a device model for the NPCM7xx SPI flash controller.

Direct reads and writes, and user-mode transactions have been tested in
various modes. Protection features are not implemented yet.

All the FIU instances are available in the SoC's address space,
regardless of whether or not they're connected to actual flash chips.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/Kconfig   |   1 +
 hw/arm/npcm7xx.c |  58 
 hw/ssi/Makefile.objs |   1 +
 hw/ssi/npcm7xx_fiu.c | 539 +++
 hw/ssi/trace-events  |  11 +
 include/hw/arm/npcm7xx.h |   2 +
 include/hw/ssi/npcm7xx_fiu.h | 100 +++
 7 files changed, 712 insertions(+)
 create mode 100644 hw/ssi/npcm7xx_fiu.c
 create mode 100644 include/hw/ssi/npcm7xx_fiu.h

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index cd74642034..f303c6bead 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -361,6 +361,7 @@ config NPCM7XX
 select ARM_GIC
 select PL310  # cache controller
 select SERIAL
+select SSI
 select UNIMP
 
 config FSL_IMX25
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 6bb1693833..7884b2b03d 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -99,6 +99,39 @@ static const hwaddr npcm7xx_uart_addr[] = {
 0xf0004000,
 };
 
+/* Direct memory-mapped access to SPI0 CS0-1. */
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
+0x8000, /* CS0 */
+0x8800, /* CS1 */
+};
+
+/* Direct memory-mapped access to SPI3 CS0-3. */
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
+0xa000, /* CS0 */
+0xa800, /* CS1 */
+0xb000, /* CS2 */
+0xb800, /* CS3 */
+};
+
+static const struct {
+const char *name;
+hwaddr regs_addr;
+int cs_count;
+const hwaddr *flash_addr;
+} npcm7xx_fiu[] = {
+{
+.name = "fiu0",
+.regs_addr = 0xfb00,
+.cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
+.flash_addr = npcm7xx_fiu0_flash_addr,
+}, {
+.name = "fiu3",
+.regs_addr = 0xc000,
+.cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
+.flash_addr = npcm7xx_fiu3_flash_addr,
+},
+};
+
 static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
  const struct arm_boot_info *info)
 {
@@ -192,6 +225,12 @@ static void npcm7xx_init(Object *obj)
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
 }
+
+QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
+for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
+object_initialize_child(obj, npcm7xx_fiu[i].name, >fiu[i],
+TYPE_NPCM7XX_FIU);
+}
 }
 
 static void npcm7xx_realize(DeviceState *dev, Error **errp)
@@ -291,6 +330,25 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
serial_hd(i), DEVICE_LITTLE_ENDIAN);
 }
 
+/*
+ * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
+ * specified, but this is a programming error.
+ */
+QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
+for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
+SysBusDevice *sbd = SYS_BUS_DEVICE(>fiu[i]);
+int j;
+
+object_property_set_int(OBJECT(sbd), "cs-count",
+npcm7xx_fiu[i].cs_count, _abort);
+sysbus_realize(sbd, _abort);
+
+sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
+for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
+sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
+}
+}
+
 /* RAM2 (SRAM) */
 memory_region_init_ram(>sram, OBJECT(dev), "ram2",
NPCM7XX_RAM2_SZ, _abort);
diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
index 07a85f1967..cab48e72c9 100644
--- a/hw/ssi/Makefile.objs
+++ b/hw/ssi/Makefile.objs
@@ -5,6 +5,7 @@ common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_smc.o
 common-obj-$(CONFIG_STM32F2XX_SPI) += stm32f2xx_spi.o
 common-obj-$(CONFIG_MSF2) += mss-spi.o
+common-obj-$(CONFIG_NPCM7XX) += npcm7xx_fiu.o
 
 common-obj-$(CONFIG_OMAP) += omap_spi.o
 common-obj-$(CONFIG_IMX) += imx_spi.o
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
new file mode 100644
index 00..f1677da160
--- /dev/null
+++ b/hw/ssi/npcm7xx_fiu.c
@@ -0,0 +1,539 @@
+/*
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) 

[PATCH v7 08/13] hw/nvram: NPCM7xx OTP device model

2020-08-10 Thread Havard Skinnemoen
This supports reading and writing OTP fuses and keys. Only fuse reading
has been tested. Protection is not implemented.

Reviewed-by: Avi Fishman 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/npcm7xx.c   |  29 +++
 hw/nvram/Makefile.objs |   1 +
 hw/nvram/npcm7xx_otp.c | 424 +
 include/hw/arm/npcm7xx.h   |   3 +
 include/hw/nvram/npcm7xx_otp.h |  88 +++
 5 files changed, 545 insertions(+)
 create mode 100644 hw/nvram/npcm7xx_otp.c
 create mode 100644 include/hw/nvram/npcm7xx_otp.h

diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 9669ac5fa0..9166002598 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -34,6 +34,10 @@
 #define NPCM7XX_MMIO_BA (0x8000)
 #define NPCM7XX_MMIO_SZ (0x7ffd)
 
+/* OTP key storage and fuse strap array */
+#define NPCM7XX_OTP1_BA (0xf0189000)
+#define NPCM7XX_OTP2_BA (0xf018a000)
+
 /* Core system modules. */
 #define NPCM7XX_L2C_BA  (0xf03fc000)
 #define NPCM7XX_CPUP_BA (0xf03fe000)
@@ -144,6 +148,20 @@ void npcm7xx_load_kernel(MachineState *machine, 
NPCM7xxState *soc)
 arm_load_kernel(>cpu[0], machine, _binfo);
 }
 
+static void npcm7xx_init_fuses(NPCM7xxState *s)
+{
+NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
+uint32_t value;
+
+/*
+ * The initial mask of disabled modules indicates the chip derivative (e.g.
+ * NPCM750 or NPCM730).
+ */
+value = tswap32(nc->disabled_modules);
+npcm7xx_otp_array_write(>fuse_array, , NPCM7XX_FUSE_DERIVATIVE,
+sizeof(value));
+}
+
 static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
 {
 return qdev_get_gpio_in(DEVICE(>a9mpcore), n);
@@ -164,6 +182,10 @@ static void npcm7xx_init(Object *obj)
 object_property_add_alias(obj, "power-on-straps", OBJECT(>gcr),
   "power-on-straps");
 object_initialize_child(obj, "clk", >clk, TYPE_NPCM7XX_CLK);
+object_initialize_child(obj, "otp1", >key_storage,
+TYPE_NPCM7XX_KEY_STORAGE);
+object_initialize_child(obj, "otp2", >fuse_array,
+TYPE_NPCM7XX_FUSE_ARRAY);
 
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
@@ -232,6 +254,13 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 sysbus_realize(SYS_BUS_DEVICE(>clk), _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>clk), 0, NPCM7XX_CLK_BA);
 
+/* OTP key storage and fuse strap array. Cannot fail. */
+sysbus_realize(SYS_BUS_DEVICE(>key_storage), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>key_storage), 0, NPCM7XX_OTP1_BA);
+sysbus_realize(SYS_BUS_DEVICE(>fuse_array), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>fuse_array), 0, NPCM7XX_OTP2_BA);
+npcm7xx_init_fuses(s);
+
 /* Timer Modules (TIM). Cannot fail. */
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs
index f3ad921382..0270f0bbf7 100644
--- a/hw/nvram/Makefile.objs
+++ b/hw/nvram/Makefile.objs
@@ -4,5 +4,6 @@ common-obj-$(CONFIG_AT24C) += eeprom_at24c.o
 common-obj-y += fw_cfg.o
 common-obj-$(CONFIG_CHRP_NVRAM) += chrp_nvram.o
 common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
+common-obj-$(CONFIG_NPCM7XX) += npcm7xx_otp.o
 common-obj-$(CONFIG_NRF51_SOC) += nrf51_nvm.o
 obj-$(CONFIG_PSERIES) += spapr_nvram.o
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
new file mode 100644
index 00..b67d69fdf9
--- /dev/null
+++ b/hw/nvram/npcm7xx_otp.c
@@ -0,0 +1,424 @@
+/*
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/nvram/npcm7xx_otp.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
+#define NPCM7XX_OTP_REGS_SIZE (4 * KiB)
+
+/* Register field definitions. */
+#define FST_RIEN BIT(2)
+#define FST_RDST BIT(1)
+#define FST_RDY BIT(0)
+#define FST_RO

[PATCH v7 09/13] hw/mem: Stubbed out NPCM7xx Memory Controller model

2020-08-10 Thread Havard Skinnemoen
This just implements the bare minimum to cause the boot block to skip
memory initialization.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/npcm7xx.c|  6 +++
 hw/mem/Makefile.objs|  1 +
 hw/mem/npcm7xx_mc.c | 84 +
 include/hw/arm/npcm7xx.h|  2 +
 include/hw/mem/npcm7xx_mc.h | 36 
 5 files changed, 129 insertions(+)
 create mode 100644 hw/mem/npcm7xx_mc.c
 create mode 100644 include/hw/mem/npcm7xx_mc.h

diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 9166002598..6bb1693833 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -43,6 +43,7 @@
 #define NPCM7XX_CPUP_BA (0xf03fe000)
 #define NPCM7XX_GCR_BA  (0xf080)
 #define NPCM7XX_CLK_BA  (0xf0801000)
+#define NPCM7XX_MC_BA   (0xf0824000)
 
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA (0xc0008000)
@@ -186,6 +187,7 @@ static void npcm7xx_init(Object *obj)
 TYPE_NPCM7XX_KEY_STORAGE);
 object_initialize_child(obj, "otp2", >fuse_array,
 TYPE_NPCM7XX_FUSE_ARRAY);
+object_initialize_child(obj, "mc", >mc, TYPE_NPCM7XX_MC);
 
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
 object_initialize_child(obj, "tim[*]", >tim[i], TYPE_NPCM7XX_TIMER);
@@ -261,6 +263,10 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(>fuse_array), 0, NPCM7XX_OTP2_BA);
 npcm7xx_init_fuses(s);
 
+/* Fake Memory Controller (MC). Cannot fail. */
+sysbus_realize(SYS_BUS_DEVICE(>mc), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>mc), 0, NPCM7XX_MC_BA);
+
 /* Timer Modules (TIM). Cannot fail. */
 QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
 for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs
index 56345befd0..9a33ef7b35 100644
--- a/hw/mem/Makefile.objs
+++ b/hw/mem/Makefile.objs
@@ -1,3 +1,4 @@
 common-obj-$(CONFIG_DIMM) += pc-dimm.o
 common-obj-y += memory-device.o
+common-obj-$(CONFIG_NPCM7XX) += npcm7xx_mc.o
 common-obj-$(CONFIG_NVDIMM) += nvdimm.o
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
new file mode 100644
index 00..0435d06ab4
--- /dev/null
+++ b/hw/mem/npcm7xx_mc.c
@@ -0,0 +1,84 @@
+/*
+ * Nuvoton NPCM7xx Memory Controller stub
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/mem/npcm7xx_mc.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+
+#define NPCM7XX_MC_REGS_SIZE (4 * KiB)
+
+static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size)
+{
+/*
+ * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory
+ * controller has already been initialized and will skip DDR training.
+ */
+if (addr == 0) {
+return 0x100;
+}
+
+qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
+
+return 0;
+}
+
+static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v,
+ unsigned int size)
+{
+qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
+}
+
+static const MemoryRegionOps npcm7xx_mc_ops = {
+.read = npcm7xx_mc_read,
+.write = npcm7xx_mc_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
+{
+NPCM7xxMCState *s = NPCM7XX_MC(dev);
+
+memory_region_init_io(>mmio, OBJECT(s), _mc_ops, s, "regs",
+  NPCM7XX_MC_REGS_SIZE);
+sysbus_init_mmio(>parent, >mmio);
+}
+
+static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->desc = "NPCM7xx Memory Controller stub";
+dc->realize = npcm7xx_mc_realize;
+}
+
+static const TypeInfo npcm7xx_mc_types[] = {
+{
+.name = TYPE_NPCM7XX_MC,
+.parent = TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(NPCM7xxMCState),
+.class_init = npcm7xx_mc_class_init,
+},
+};
+DEFINE_TYPES(npc

[PATCH v7 07/13] hw/arm: Load -bios image as a boot ROM for npcm7xx

2020-08-10 Thread Havard Skinnemoen
If a -bios option is specified on the command line, load the image into
the internal ROM memory region, which contains the first instructions
run by the CPU after reset.

If -bios is not specified, the vbootrom included with qemu is loaded by
default.

Reviewed-by: Tyrone Ting 
Reviewed-by: Cédric Le Goater 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/npcm7xx_boards.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 0b9dce2b35..26ea97072b 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -18,12 +18,38 @@
 
 #include "hw/arm/npcm7xx.h"
 #include "hw/core/cpu.h"
+#include "hw/loader.h"
 #include "qapi/error.h"
+#include "qemu-common.h"
 #include "qemu/units.h"
+#include "sysemu/sysemu.h"
 
 #define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7
 #define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff
 
+static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
+
+static void npcm7xx_load_bootrom(NPCM7xxState *soc)
+{
+g_autofree char *filename = NULL;
+int ret;
+
+if (!bios_name) {
+bios_name = npcm7xx_default_bootrom;
+}
+
+filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+if (!filename) {
+error_report("Could not find ROM image '%s'", bios_name);
+exit(1);
+}
+ret = load_image_mr(filename, >irom);
+if (ret < 0) {
+error_report("Failed to load ROM image '%s'", filename);
+exit(1);
+}
+}
+
 static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
 {
 memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
@@ -60,6 +86,7 @@ static void npcm750_evb_init(MachineState *machine)
 npcm7xx_connect_dram(soc, machine->ram);
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
+npcm7xx_load_bootrom(soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
@@ -71,6 +98,7 @@ static void quanta_gsj_init(MachineState *machine)
 npcm7xx_connect_dram(soc, machine->ram);
 qdev_realize(DEVICE(soc), NULL, _fatal);
 
+npcm7xx_load_bootrom(soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.28.0.236.gb10cc79966-goog




[PATCH v7 04/13] hw/arm: Add NPCM730 and NPCM750 SoC models

2020-08-10 Thread Havard Skinnemoen
The Nuvoton NPCM7xx SoC family are used to implement Baseboard
Management Controllers in servers. While the family includes four SoCs,
this patch implements limited support for two of them: NPCM730 (targeted
for Data Center applications) and NPCM750 (targeted for Enterprise
applications).

This patch includes little more than the bare minimum needed to boot a
Linux kernel built with NPCM7xx support in direct-kernel mode:

  - Two Cortex-A9 CPU cores with built-in periperhals.
  - Global Configuration Registers.
  - Clock Management.
  - 3 Timer Modules with 5 timers each.
  - 4 serial ports.

The chips themselves have a lot more features, some of which will be
added to the model at a later stage.

Reviewed-by: Tyrone Ting 
Reviewed-by: Joel Stanley 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Havard Skinnemoen 
---
 hw/arm/Kconfig   |   5 +
 hw/arm/Makefile.objs |   1 +
 hw/arm/npcm7xx.c | 407 +++
 include/hw/arm/npcm7xx.h |  85 
 4 files changed, 498 insertions(+)
 create mode 100644 hw/arm/npcm7xx.c
 create mode 100644 include/hw/arm/npcm7xx.h

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 4aec9c63f8..cd74642034 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -357,6 +357,11 @@ config XLNX_VERSAL
 
 config NPCM7XX
 bool
+select A9MPCORE
+select ARM_GIC
+select PL310  # cache controller
+select SERIAL
+select UNIMP
 
 config FSL_IMX25
 bool
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 534a6a119e..13d163a599 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -41,6 +41,7 @@ obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
 obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
 obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
 obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
+obj-$(CONFIG_NPCM7XX) += npcm7xx.o
 obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
 obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
 obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
new file mode 100644
index 00..9669ac5fa0
--- /dev/null
+++ b/hw/arm/npcm7xx.c
@@ -0,0 +1,407 @@
+/*
+ * Nuvoton NPCM7xx SoC family.
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "exec/address-spaces.h"
+#include "hw/arm/boot.h"
+#include "hw/arm/npcm7xx.h"
+#include "hw/char/serial.h"
+#include "hw/loader.h"
+#include "hw/misc/unimp.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "qemu/units.h"
+#include "sysemu/sysemu.h"
+
+/*
+ * This covers the whole MMIO space. We'll use this to catch any MMIO accesses
+ * that aren't handled by any device.
+ */
+#define NPCM7XX_MMIO_BA (0x8000)
+#define NPCM7XX_MMIO_SZ (0x7ffd)
+
+/* Core system modules. */
+#define NPCM7XX_L2C_BA  (0xf03fc000)
+#define NPCM7XX_CPUP_BA (0xf03fe000)
+#define NPCM7XX_GCR_BA  (0xf080)
+#define NPCM7XX_CLK_BA  (0xf0801000)
+
+/* Internal AHB SRAM */
+#define NPCM7XX_RAM3_BA (0xc0008000)
+#define NPCM7XX_RAM3_SZ (4 * KiB)
+
+/* Memory blocks at the end of the address space */
+#define NPCM7XX_RAM2_BA (0xfffd)
+#define NPCM7XX_RAM2_SZ (128 * KiB)
+#define NPCM7XX_ROM_BA  (0x)
+#define NPCM7XX_ROM_SZ  (64 * KiB)
+
+/*
+ * Interrupt lines going into the GIC. This does not include internal Cortex-A9
+ * interrupts.
+ */
+enum NPCM7xxInterrupt {
+NPCM7XX_UART0_IRQ   = 2,
+NPCM7XX_UART1_IRQ,
+NPCM7XX_UART2_IRQ,
+NPCM7XX_UART3_IRQ,
+NPCM7XX_TIMER0_IRQ  = 32,   /* Timer Module 0 */
+NPCM7XX_TIMER1_IRQ,
+NPCM7XX_TIMER2_IRQ,
+NPCM7XX_TIMER3_IRQ,
+NPCM7XX_TIMER4_IRQ,
+NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */
+NPCM7XX_TIMER6_IRQ,
+NPCM7XX_TIMER7_IRQ,
+NPCM7XX_TIMER8_IRQ,
+NPCM7XX_TIMER9_IRQ,
+NPCM7XX_TIMER10_IRQ,/* Timer Module 2 */
+NPCM7XX_TIMER11_IRQ,
+NPCM7XX_TIMER12_IRQ,
+NPCM7XX_TIMER13_IRQ,
+NPCM7XX_TIMER14_IRQ,
+};
+
+/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
+#define NPCM7XX_NUM_IRQ (160)
+
+/* Register base address for each Timer Module */
+static const hwaddr npcm7xx_tim_addr[] = {
+0xf0008000,
+0xf0009000,
+0xf000a000,
+};
+

  1   2   3   >