[PATCH] hw/misc: Fix arith overflow in NPCM7XX PWM module

2021-01-25 Thread wuhaotsh--- via
There's a potential arith overflow in npcm7xx_pwm_calculate_duty.
This patch fixes it.

Thanks Peter for finding this out.

Signed-off-by: Hao Wu 
---
 hw/misc/npcm7xx_pwm.c  | 4 ++--
 tests/qtest/npcm7xx_pwm-test.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
index e99e3cc7ef..90b4f630a0 100644
--- a/hw/misc/npcm7xx_pwm.c
+++ b/hw/misc/npcm7xx_pwm.c
@@ -102,9 +102,9 @@ static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
 if (p->cnr == 0) {
 duty = 0;
 } else if (p->cmr >= p->cnr) {
-duty = NPCM7XX_PWM_MAX_DUTY;
+duty = (uint64_t)NPCM7XX_PWM_MAX_DUTY;
 } else {
-duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
+duty = (uint64_t)NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 
1);
 }
 } else {
 duty = 0;
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
index 63557d2c06..f55571b31d 100644
--- a/tests/qtest/npcm7xx_pwm-test.c
+++ b/tests/qtest/npcm7xx_pwm-test.c
@@ -280,7 +280,7 @@ static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t 
cmr, bool inverted)
 } else if (cmr >= cnr) {
 duty = MAX_DUTY;
 } else {
-duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
+duty = (uint64_t)MAX_DUTY * (cmr + 1) / (cnr + 1);
 }
 
 if (inverted) {
-- 
2.30.0.280.ga3ce27912f-goog




[PATCH 2/6] hw/i2c: Implement NPCM7XX SMBus Module Single Mode

2021-01-26 Thread wuhaotsh--- via
This commit implements the single-byte mode of the SMBus.

Each Nuvoton SoC has 16 System Management Bus (SMBus). These buses
compliant with SMBus and I2C protocol.

This patch implements the single-byte mode of the SMBus. In this mode,
the user sends or receives a byte each time. The SMBus device transmits
it to the underlying i2c device and sends an interrupt back to the QEMU
guest.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
---
 docs/system/arm/nuvoton.rst|   2 +-
 hw/arm/npcm7xx.c   |  68 ++-
 hw/i2c/meson.build |   1 +
 hw/i2c/npcm7xx_smbus.c | 766 +
 hw/i2c/trace-events|  11 +
 include/hw/arm/npcm7xx.h   |   2 +
 include/hw/i2c/npcm7xx_smbus.h |  88 
 7 files changed, 921 insertions(+), 17 deletions(-)
 create mode 100644 hw/i2c/npcm7xx_smbus.c
 create mode 100644 include/hw/i2c/npcm7xx_smbus.h

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index a1786342e2..34fc799b2d 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -43,6 +43,7 @@ Supported devices
  * GPIO controller
  * Analog to Digital Converter (ADC)
  * Pulse Width Modulation (PWM)
+ * SMBus controller (SMBF)
 
 Missing devices
 ---
@@ -58,7 +59,6 @@ Missing devices
 
  * Ethernet controllers (GMAC and EMC)
  * USB device (USBD)
- * SMBus controller (SMBF)
  * Peripheral SPI controller (PSPI)
  * SD/MMC host
  * PECI interface
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index d1fe9bd1df..8f596ffd69 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -104,6 +104,22 @@ enum NPCM7xxInterrupt {
 NPCM7XX_OHCI_IRQ= 62,
 NPCM7XX_PWM0_IRQ= 93,   /* PWM module 0 */
 NPCM7XX_PWM1_IRQ,   /* PWM module 1 */
+NPCM7XX_SMBUS0_IRQ  = 64,
+NPCM7XX_SMBUS1_IRQ,
+NPCM7XX_SMBUS2_IRQ,
+NPCM7XX_SMBUS3_IRQ,
+NPCM7XX_SMBUS4_IRQ,
+NPCM7XX_SMBUS5_IRQ,
+NPCM7XX_SMBUS6_IRQ,
+NPCM7XX_SMBUS7_IRQ,
+NPCM7XX_SMBUS8_IRQ,
+NPCM7XX_SMBUS9_IRQ,
+NPCM7XX_SMBUS10_IRQ,
+NPCM7XX_SMBUS11_IRQ,
+NPCM7XX_SMBUS12_IRQ,
+NPCM7XX_SMBUS13_IRQ,
+NPCM7XX_SMBUS14_IRQ,
+NPCM7XX_SMBUS15_IRQ,
 NPCM7XX_GPIO0_IRQ   = 116,
 NPCM7XX_GPIO1_IRQ,
 NPCM7XX_GPIO2_IRQ,
@@ -152,6 +168,26 @@ static const hwaddr npcm7xx_pwm_addr[] = {
 0xf0104000,
 };
 
+/* Direct memory-mapped access to each SMBus Module. */
+static const hwaddr npcm7xx_smbus_addr[] = {
+0xf008,
+0xf0081000,
+0xf0082000,
+0xf0083000,
+0xf0084000,
+0xf0085000,
+0xf0086000,
+0xf0087000,
+0xf0088000,
+0xf0089000,
+0xf008a000,
+0xf008b000,
+0xf008c000,
+0xf008d000,
+0xf008e000,
+0xf008f000,
+};
+
 static const struct {
 hwaddr regs_addr;
 uint32_t unconnected_pins;
@@ -353,6 +389,11 @@ static void npcm7xx_init(Object *obj)
 object_initialize_child(obj, "gpio[*]", &s->gpio[i], 
TYPE_NPCM7XX_GPIO);
 }
 
+for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
+object_initialize_child(obj, "smbus[*]", &s->smbus[i],
+TYPE_NPCM7XX_SMBUS);
+}
+
 object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
 object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
 
@@ -509,6 +550,17 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i));
 }
 
+/* SMBus modules. Cannot fail. */
+QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_smbus_addr) != ARRAY_SIZE(s->smbus));
+for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
+Object *obj = OBJECT(&s->smbus[i]);
+
+sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_smbus_addr[i]);
+sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
+   npcm7xx_irq(s, NPCM7XX_SMBUS0_IRQ + i));
+}
+
 /* USB Host */
 object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
  &error_abort);
@@ -576,22 +628,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 create_unimplemented_device("npcm7xx.pcierc",   0xe100,  64 * KiB);
 create_unimplemented_device("npcm7xx.kcs",  0xf0007000,   4 * KiB);
 create_unimplemented_device("npcm7xx.gfxi", 0xf000e000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[0]", 0xf008,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[6]",

[PATCH 0/6] hw/i2c: Add NPCM7XX SMBus Device

2021-01-26 Thread wuhaotsh--- via
This patch set implements the System manager bus (SMBus) module in NPCM7XX
SoC. Basically, it emulates the data transactions of the module, not the
SDA/SCL levels. We have also added a QTest which contains read and write
operations for both single-byte and FIFO mode, and added basic I2C device
trees for npcm750-evb and quanta-gsj boards.

We also cleaned up the unimplemented GPIO devices in npcm7xx.c since they
are already implemented.

Hao Wu (6):
  hw/arm: Remove GPIO from unimplemented NPCM7XX
  hw/i2c: Implement NPCM7XX SMBus Module Single Mode
  hw/arm: Add I2C device tree for NPCM750 eval board
  hw/arm: Add I2C device tree for Quanta GSJ
  hw/i2c: Add a QTest for NPCM7XX SMBus Device
  hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode

 docs/system/arm/nuvoton.rst  |2 +-
 hw/arm/npcm7xx.c |   76 ++-
 hw/arm/npcm7xx_boards.c  |   32 +
 hw/i2c/meson.build   |1 +
 hw/i2c/npcm7xx_smbus.c   | 1071 ++
 hw/i2c/trace-events  |   12 +
 include/hw/arm/npcm7xx.h |2 +
 include/hw/i2c/npcm7xx_smbus.h   |  113 
 tests/qtest/meson.build  |1 +
 tests/qtest/npcm7xx_smbus-test.c |  495 ++
 10 files changed, 1780 insertions(+), 25 deletions(-)
 create mode 100644 hw/i2c/npcm7xx_smbus.c
 create mode 100644 include/hw/i2c/npcm7xx_smbus.h
 create mode 100644 tests/qtest/npcm7xx_smbus-test.c

-- 
2.30.0.365.g02bc693789-goog




[PATCH 3/6] hw/arm: Add I2C device tree for NPCM750 eval board

2021-01-26 Thread wuhaotsh--- via
Add an I2C device tree for NPCM750 evaluation board.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
---
 hw/arm/npcm7xx_boards.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 3fdd5cab01..2d82f48848 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -98,6 +98,20 @@ static NPCM7xxState *npcm7xx_create_soc(MachineState 
*machine,
 return NPCM7XX(obj);
 }
 
+static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, uint32_t num)
+{
+g_assert(num < ARRAY_SIZE(soc->smbus));
+return I2C_BUS(qdev_get_child_bus(DEVICE(&soc->smbus[num]), "i2c-bus"));
+}
+
+static void npcm750_evb_i2c_init(NPCM7xxState *soc)
+{
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 0), "tmp105", 0x48);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x48);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x48);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
+}
+
 static void npcm750_evb_init(MachineState *machine)
 {
 NPCM7xxState *soc;
@@ -108,6 +122,7 @@ static void npcm750_evb_init(MachineState *machine)
 
 npcm7xx_load_bootrom(machine, soc);
 npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
+npcm750_evb_i2c_init(soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.30.0.365.g02bc693789-goog




[PATCH 6/6] hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode

2021-01-26 Thread wuhaotsh--- via
This patch implements the FIFO mode of the SMBus module. In FIFO, the
user transmits or receives at most 16 bytes at a time. The FIFO mode
allows the module to transmit large amount of data faster than single
byte mode.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
---
 hw/i2c/npcm7xx_smbus.c   | 331 +--
 hw/i2c/trace-events  |   1 +
 include/hw/i2c/npcm7xx_smbus.h   |  25 +++
 tests/qtest/npcm7xx_smbus-test.c | 149 +-
 4 files changed, 490 insertions(+), 16 deletions(-)

diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
index e8a8fdbaff..19a9cdb179 100644
--- a/hw/i2c/npcm7xx_smbus.c
+++ b/hw/i2c/npcm7xx_smbus.c
@@ -27,7 +27,7 @@
 #include "trace.h"
 
 #define NPCM7XX_SMBUS_VERSION 1
-#define NPCM7XX_SMBUS_FIFO_EN 0
+#define NPCM7XX_SMBUS_FIFO_EN 1
 
 enum NPCM7xxSMBusCommonRegister {
 NPCM7XX_SMB_SDA = 0x0,
@@ -132,10 +132,41 @@ enum NPCM7xxSMBusBank1Register {
 #define NPCM7XX_ADDR_EN BIT(7)
 #define NPCM7XX_ADDR_A(rv)  extract8((rv), 0, 6)
 
+/* FIFO Mode Register Fields */
+/* FIF_CTL fields */
+#define NPCM7XX_SMBFIF_CTL_FIFO_EN  BIT(4)
+#define NPCM7XX_SMBFIF_CTL_FAIR_RDY_IE  BIT(2)
+#define NPCM7XX_SMBFIF_CTL_FAIR_RDY BIT(1)
+#define NPCM7XX_SMBFIF_CTL_FAIR_BUSYBIT(0)
+/* FIF_CTS fields */
+#define NPCM7XX_SMBFIF_CTS_STR  BIT(7)
+#define NPCM7XX_SMBFIF_CTS_CLR_FIFO BIT(6)
+#define NPCM7XX_SMBFIF_CTS_RFTE_IE  BIT(3)
+#define NPCM7XX_SMBFIF_CTS_RXF_TXE  BIT(1)
+/* TXF_CTL fields */
+#define NPCM7XX_SMBTXF_CTL_THR_TXIE BIT(6)
+#define NPCM7XX_SMBTXF_CTL_TX_THR(rv)   extract8((rv), 0, 5)
+/* T_OUT fields */
+#define NPCM7XX_SMBT_OUT_ST BIT(7)
+#define NPCM7XX_SMBT_OUT_IE BIT(6)
+#define NPCM7XX_SMBT_OUT_CLKDIV(rv) extract8((rv), 0, 6)
+/* TXF_STS fields */
+#define NPCM7XX_SMBTXF_STS_TX_THST  BIT(6)
+#define NPCM7XX_SMBTXF_STS_TX_BYTES(rv) extract8((rv), 0, 5)
+/* RXF_STS fields */
+#define NPCM7XX_SMBRXF_STS_RX_THST  BIT(6)
+#define NPCM7XX_SMBRXF_STS_RX_BYTES(rv) extract8((rv), 0, 5)
+/* RXF_CTL fields */
+#define NPCM7XX_SMBRXF_CTL_THR_RXIE BIT(6)
+#define NPCM7XX_SMBRXF_CTL_LAST BIT(5)
+#define NPCM7XX_SMBRXF_CTL_RX_THR(rv)   extract8((rv), 0, 5)
+
 #define KEEP_OLD_BIT(o, n, b)   (((n) & (~(b))) | ((o) & (b)))
 #define WRITE_ONE_CLEAR(o, n, b)((n) & (b) ? (o) & (~(b)) : (o))
 
 #define NPCM7XX_SMBUS_ENABLED(s)((s)->ctl2 & NPCM7XX_SMBCTL2_ENABLE)
+#define NPCM7XX_SMBUS_FIFO_ENABLED(s) (NPCM7XX_SMBUS_FIFO_EN && \
+(s)->fif_ctl & NPCM7XX_SMBFIF_CTL_FIFO_EN)
 
 /* Reset values */
 #define NPCM7XX_SMB_ST_INIT_VAL 0x00
@@ -150,6 +181,14 @@ enum NPCM7xxSMBusBank1Register {
 #define NPCM7XX_SMB_ADDR_INIT_VAL   0x00
 #define NPCM7XX_SMB_SCLLT_INIT_VAL  0x00
 #define NPCM7XX_SMB_SCLHT_INIT_VAL  0x00
+#define NPCM7XX_SMB_FIF_CTL_INIT_VAL 0x00
+#define NPCM7XX_SMB_FIF_CTS_INIT_VAL 0x00
+#define NPCM7XX_SMB_FAIR_PER_INIT_VAL 0x00
+#define NPCM7XX_SMB_TXF_CTL_INIT_VAL 0x00
+#define NPCM7XX_SMB_T_OUT_INIT_VAL 0x3f
+#define NPCM7XX_SMB_TXF_STS_INIT_VAL 0x00
+#define NPCM7XX_SMB_RXF_STS_INIT_VAL 0x00
+#define NPCM7XX_SMB_RXF_CTL_INIT_VAL 0x01
 
 static uint8_t npcm7xx_smbus_get_version(void)
 {
@@ -169,7 +208,13 @@ static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState *s)
(s->ctl1 & NPCM7XX_SMBCTL1_STASTRE &&
 s->st & NPCM7XX_SMBST_SDAST) ||
(s->ctl1 & NPCM7XX_SMBCTL1_EOBINTE &&
-s->cst3 & NPCM7XX_SMBCST3_EO_BUSY));
+s->cst3 & NPCM7XX_SMBCST3_EO_BUSY) ||
+   (s->rxf_ctl & NPCM7XX_SMBRXF_CTL_THR_RXIE &&
+s->rxf_sts & NPCM7XX_SMBRXF_STS_RX_THST) ||
+   (s->txf_ctl & NPCM7XX_SMBTXF_CTL_THR_TXIE &&
+s->txf_sts & NPCM7XX_SMBTXF_STS_TX_THST) ||
+   (s->fif_cts & NPCM7XX_SMBFIF_CTS_RFTE_IE &&
+s->fif_cts & NPCM7XX_SMBFIF_CTS_RXF_TXE));
 
 if (level) {
 s->cst2 |= NPCM7XX_SMBCST2_INTSTS;
@@ -187,6 +232,13 @@ static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s)
 s->status = NPCM7XX_SMBUS_STATUS_NEGACK;
 }
 
+static void npcm7xx_smbus_clear_buffer(NPCM7xxSMBusState *s)
+{
+s->fif_cts &= ~NPCM7XX_SMBFIF_CTS_RXF_TXE;
+s->txf_sts = 0;
+s->rxf_sts = 0;
+}
+
 static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value)
 {
 int rv = i2c_send(s->bus, value);
@@ -195,6 +247,15 @@ static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, 
uint8_t value)
 npcm7xx_smbus_nack(s);
 } else {
 s->st |= NPCM7XX_SMBST_SDAST;
+if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
+s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE;
+if (NPCM7XX_SMBTXF_STS_TX_BYTES(s->txf_sts) ==
+NPCM7XX_SMBTXF_CTL_TX_THR(s->txf_ctl)) {
+

[PATCH 5/6] hw/i2c: Add a QTest for NPCM7XX SMBus Device

2021-01-26 Thread wuhaotsh--- via
This patch adds a QTest for NPCM7XX SMBus's single byte mode. It sends a
byte to a device in the evaluation board, and verify the retrieved value
is equivalent to the sent value.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
---
 tests/qtest/meson.build  |   1 +
 tests/qtest/npcm7xx_smbus-test.c | 352 +++
 2 files changed, 353 insertions(+)
 create mode 100644 tests/qtest/npcm7xx_smbus-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 16d04625b8..aa62d59817 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -138,6 +138,7 @@ qtests_npcm7xx = \
'npcm7xx_gpio-test',
'npcm7xx_pwm-test',
'npcm7xx_rng-test',
+   'npcm7xx_smbus-test',
'npcm7xx_timer-test',
'npcm7xx_watchdog_timer-test']
 qtests_arm = \
diff --git a/tests/qtest/npcm7xx_smbus-test.c b/tests/qtest/npcm7xx_smbus-test.c
new file mode 100644
index 00..4594b107df
--- /dev/null
+++ b/tests/qtest/npcm7xx_smbus-test.c
@@ -0,0 +1,352 @@
+/*
+ * QTests for Nuvoton NPCM7xx SMBus Modules.
+ *
+ * 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/bitops.h"
+#include "libqos/i2c.h"
+#include "libqos/libqtest.h"
+#include "hw/misc/tmp105_regs.h"
+
+#define NR_SMBUS_DEVICES16
+#define SMBUS_ADDR(x)   (0xf008 + 0x1000 * (x))
+#define SMBUS_IRQ(x)(64 + (x))
+
+#define EVB_DEVICE_ADDR 0x48
+#define INVALID_DEVICE_ADDR 0x01
+
+const int evb_bus_list[] = {0, 1, 2, 6};
+
+/* Offsets */
+enum CommonRegister {
+OFFSET_SDA = 0x0,
+OFFSET_ST  = 0x2,
+OFFSET_CST = 0x4,
+OFFSET_CTL1= 0x6,
+OFFSET_ADDR1   = 0x8,
+OFFSET_CTL2= 0xa,
+OFFSET_ADDR2   = 0xc,
+OFFSET_CTL3= 0xe,
+OFFSET_CST2= 0x18,
+OFFSET_CST3= 0x19,
+};
+
+enum NPCM7xxSMBusBank0Register {
+OFFSET_ADDR3   = 0x10,
+OFFSET_ADDR7   = 0x11,
+OFFSET_ADDR4   = 0x12,
+OFFSET_ADDR8   = 0x13,
+OFFSET_ADDR5   = 0x14,
+OFFSET_ADDR9   = 0x15,
+OFFSET_ADDR6   = 0x16,
+OFFSET_ADDR10  = 0x17,
+OFFSET_CTL4= 0x1a,
+OFFSET_CTL5= 0x1b,
+OFFSET_SCLLT   = 0x1c,
+OFFSET_FIF_CTL = 0x1d,
+OFFSET_SCLHT   = 0x1e,
+};
+
+enum NPCM7xxSMBusBank1Register {
+OFFSET_FIF_CTS  = 0x10,
+OFFSET_FAIR_PER = 0x11,
+OFFSET_TXF_CTL  = 0x12,
+OFFSET_T_OUT= 0x14,
+OFFSET_TXF_STS  = 0x1a,
+OFFSET_RXF_STS  = 0x1c,
+OFFSET_RXF_CTL  = 0x1e,
+};
+
+/* ST fields */
+#define ST_STP  BIT(7)
+#define ST_SDASTBIT(6)
+#define ST_BER  BIT(5)
+#define ST_NEGACK   BIT(4)
+#define ST_STASTR   BIT(3)
+#define ST_NMATCH   BIT(2)
+#define ST_MODE BIT(1)
+#define ST_XMIT BIT(0)
+
+/* CST fields */
+#define CST_ARPMATCHBIT(7)
+#define CST_MATCHAF BIT(6)
+#define CST_TGSCL   BIT(5)
+#define CST_TSDABIT(4)
+#define CST_GCMATCH BIT(3)
+#define CST_MATCH   BIT(2)
+#define CST_BB  BIT(1)
+#define CST_BUSYBIT(0)
+
+/* CST2 fields */
+#define CST2_INSTTS BIT(7)
+#define CST2_MATCH7FBIT(6)
+#define CST2_MATCH6FBIT(5)
+#define CST2_MATCH5FBIT(4)
+#define CST2_MATCH4FBIT(3)
+#define CST2_MATCH3FBIT(2)
+#define CST2_MATCH2FBIT(1)
+#define CST2_MATCH1FBIT(0)
+
+/* CST3 fields */
+#define CST3_EO_BUSYBIT(7)
+#define CST3_MATCH10F   BIT(2)
+#define CST3_MATCH9FBIT(1)
+#define CST3_MATCH8FBIT(0)
+
+/* CTL1 fields */
+#define CTL1_STASTREBIT(7)
+#define CTL1_NMINTE BIT(6)
+#define CTL1_GCMEN  BIT(5)
+#define CTL1_ACKBIT(4)
+#define CTL1_EOBINTEBIT(3)
+#define CTL1_INTEN  BIT(2)
+#define CTL1_STOP   BIT(1)
+#define CTL1_START  BIT(0)
+
+/* CTL2 fields */
+#define CTL2_SCLFRQ(rv) extract8((rv), 1, 6)
+#define CTL2_ENABLE BIT(0)
+
+/* CTL3 fields */
+#define CTL3_SCL_LVLBIT(7)
+#define CTL3_SDA_LVLBIT(6)
+#define CTL3_BNK_SELBIT(5)
+#define CTL3_400K_MODE  BIT(4)
+#define CTL3_IDL_START  BIT(3)
+#define CTL3_ARPMEN BIT(2)
+#define CTL3_SCLFRQ(rv) extract8((rv), 0, 2)
+
+/* ADDR fields */
+#define ADDR_EN BIT(7)
+#define ADDR_A(rv)  extract8((rv), 0, 6)
+
+
+static void check_running(QTestState *qts, uint64_t base_addr)
+{
+g_assert_true(qtest_readb(qts, base_

[PATCH 1/6] hw/arm: Remove GPIO from unimplemented NPCM7XX

2021-01-26 Thread wuhaotsh--- via
NPCM7XX GPIO devices have been implemented in hw/gpio/npcm7xx-gpio.c. So
we removed them from the unimplemented devices list.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu
---
 hw/arm/npcm7xx.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 72040d4079..d1fe9bd1df 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -576,14 +576,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 create_unimplemented_device("npcm7xx.pcierc",   0xe100,  64 * KiB);
 create_unimplemented_device("npcm7xx.kcs",  0xf0007000,   4 * KiB);
 create_unimplemented_device("npcm7xx.gfxi", 0xf000e000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[0]",  0xf001,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[1]",  0xf0011000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[2]",  0xf0012000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[3]",  0xf0013000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[4]",  0xf0014000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[5]",  0xf0015000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[6]",  0xf0016000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[7]",  0xf0017000,   4 * KiB);
 create_unimplemented_device("npcm7xx.smbus[0]", 0xf008,   4 * KiB);
 create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000,   4 * KiB);
 create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000,   4 * KiB);
-- 
2.30.0.365.g02bc693789-goog




[PATCH 4/6] hw/arm: Add I2C device tree for Quanta GSJ

2021-01-26 Thread wuhaotsh--- via
Add an I2C device tree for Quanta GSJ. We only included devices with
existing QEMU implementation, including AT24 EEPROM and temperature
sensors.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
---
 hw/arm/npcm7xx_boards.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 2d82f48848..1418629e06 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -19,6 +19,7 @@
 #include "exec/address-spaces.h"
 #include "hw/arm/npcm7xx.h"
 #include "hw/core/cpu.h"
+#include "hw/i2c/smbus_eeprom.h"
 #include "hw/loader.h"
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
@@ -112,6 +113,21 @@ static void npcm750_evb_i2c_init(NPCM7xxState *soc)
 i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
 }
 
+static void quanta_gsj_i2c_init(NPCM7xxState *soc)
+{
+uint8_t *eeprom_buf0 = g_malloc0(32 * 1024);
+uint8_t *eeprom_buf1 = g_malloc0(32 * 1024);
+
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x48);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x48);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 3), "tmp105", 0x48);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), "tmp105", 0x48);
+smbus_eeprom_init_one(npcm7xx_i2c_get_bus(soc, 9), 0x55, eeprom_buf0);
+smbus_eeprom_init_one(npcm7xx_i2c_get_bus(soc, 10), 0x55, eeprom_buf1);
+
+/* TODO: Add addtional i2c devices. */
+}
+
 static void npcm750_evb_init(MachineState *machine)
 {
 NPCM7xxState *soc;
@@ -137,6 +153,7 @@ static void quanta_gsj_init(MachineState *machine)
 npcm7xx_load_bootrom(machine, soc);
 npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
   drive_get(IF_MTD, 0, 0));
+quanta_gsj_i2c_init(soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.30.0.365.g02bc693789-goog




[PATCH v2] hw/misc: Fix arith overflow in NPCM7XX PWM module

2021-01-26 Thread wuhaotsh--- via
Fix potential overflow problem when calculating pwm_duty.
1. Ensure p->cmr and p->cnr to be from [0,65535], according to the
   hardware specification.
2. Changed duty to uint32_t. However, since MAX_DUTY * (p->cmr+1)
   can excceed UINT32_MAX, we convert them to uint64_t in computation
   and converted them back to uint32_t.
   (duty is guaranteed to be <= MAX_DUTY so it won't overflow.)

Fixes: CID 1442342
Suggested-by: Peter Maydell 
Reviewed-by: Doug Evans 
Signed-off-by: Hao Wu 
---
 hw/misc/npcm7xx_pwm.c  | 23 +++
 tests/qtest/npcm7xx_pwm-test.c |  4 ++--
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
index e99e3cc7ef..dabcb6c0f9 100644
--- a/hw/misc/npcm7xx_pwm.c
+++ b/hw/misc/npcm7xx_pwm.c
@@ -58,6 +58,9 @@ REG32(NPCM7XX_PWM_PWDR3, 0x50);
 #define NPCM7XX_CH_INV  BIT(2)
 #define NPCM7XX_CH_MOD  BIT(3)
 
+#define NPCM7XX_MAX_CMR 65535
+#define NPCM7XX_MAX_CNR 65535
+
 /* Offset of each PWM channel's prescaler in the PPR register. */
 static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
 /* Offset of each PWM channel's clock selector in the CSR register. */
@@ -96,7 +99,7 @@ static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
 
 static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
 {
-uint64_t duty;
+uint32_t duty;
 
 if (p->running) {
 if (p->cnr == 0) {
@@ -104,7 +107,7 @@ static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
 } else if (p->cmr >= p->cnr) {
 duty = NPCM7XX_PWM_MAX_DUTY;
 } else {
-duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
+duty = (uint64_t)NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 
1);
 }
 } else {
 duty = 0;
@@ -357,7 +360,13 @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
 case A_NPCM7XX_PWM_CNR2:
 case A_NPCM7XX_PWM_CNR3:
 p = &s->pwm[npcm7xx_cnr_index(offset)];
-p->cnr = value;
+if (value > NPCM7XX_MAX_CNR) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: invalid cnr value: %u", __func__, value);
+p->cnr = NPCM7XX_MAX_CNR;
+} else {
+p->cnr = value;
+}
 npcm7xx_pwm_update_output(p);
 break;
 
@@ -366,7 +375,13 @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
 case A_NPCM7XX_PWM_CMR2:
 case A_NPCM7XX_PWM_CMR3:
 p = &s->pwm[npcm7xx_cmr_index(offset)];
-p->cmr = value;
+if (value > NPCM7XX_MAX_CMR) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: invalid cmr value: %u", __func__, value);
+p->cmr = NPCM7XX_MAX_CMR;
+} else {
+p->cmr = value;
+}
 npcm7xx_pwm_update_output(p);
 break;
 
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
index 63557d2c06..3d82654b81 100644
--- a/tests/qtest/npcm7xx_pwm-test.c
+++ b/tests/qtest/npcm7xx_pwm-test.c
@@ -272,7 +272,7 @@ static uint64_t pwm_compute_freq(QTestState *qts, uint32_t 
ppr, uint32_t csr,
 
 static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
 {
-uint64_t duty;
+uint32_t duty;
 
 if (cnr == 0) {
 /* PWM is stopped. */
@@ -280,7 +280,7 @@ static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t 
cmr, bool inverted)
 } else if (cmr >= cnr) {
 duty = MAX_DUTY;
 } else {
-duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
+duty = (uint64_t)MAX_DUTY * (cmr + 1) / (cnr + 1);
 }
 
 if (inverted) {
-- 
2.30.0.365.g02bc693789-goog




Re: [PATCH 6/6] hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode

2021-01-27 Thread wuhaotsh--- via
On Tue, Jan 26, 2021 at 3:47 PM Corey Minyard  wrote:

> On Tue, Jan 26, 2021 at 11:32:37AM -0800, wuhaotsh--- via wrote:
> > +
> > +static void npcm7xx_smbus_read_byte_fifo(NPCM7xxSMBusState *s)
> > +{
> > +uint8_t received_bytes = NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts);
> > +
> > +if (received_bytes == 0) {
> > +npcm7xx_smbus_recv_fifo(s);
> > +return;
> > +}
> > +
> > +s->sda = s->rx_fifo[s->rx_cur];
> > +s->rx_cur = (s->rx_cur + 1u) % NPCM7XX_SMBUS_FIFO_SIZE;
> > +--s->rxf_sts;
>
> This open-coded decrement seems a little risky.  Are you sure in every
> case that s->rxf_sts > 0?  There's no way what's running in the VM can
> game this and cause a buffer overrun?  One caller to this function seems
> to protect against this, and another does not.
>
s->rxf_sts is uint8_t so it's guaranteed to be >=0.
In the case s->rxf_sts == 0,  NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts) is
also 0, so it'll take the if-branch and return without running --s->rxf_sts.
I'll probably add "g_assert(s->rxf_sts > 0)" to clarify.

>
> Other than this, I didn't see any issues with this patch.
>
> -corey
>


Re: [PATCH 6/6] hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode

2021-01-27 Thread wuhaotsh--- via
On Wed, Jan 27, 2021 at 1:42 PM Corey Minyard  wrote:

> On Wed, Jan 27, 2021 at 12:37:46PM -0800, wuhaotsh--- via wrote:
> > On Tue, Jan 26, 2021 at 3:47 PM Corey Minyard  wrote:
> >
> > > On Tue, Jan 26, 2021 at 11:32:37AM -0800, wuhaotsh--- via wrote:
> > > > +
> > > > +static void npcm7xx_smbus_read_byte_fifo(NPCM7xxSMBusState *s)
> > > > +{
> > > > +uint8_t received_bytes =
> NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts);
> > > > +
> > > > +if (received_bytes == 0) {
> > > > +npcm7xx_smbus_recv_fifo(s);
> > > > +return;
> > > > +}
> > > > +
> > > > +s->sda = s->rx_fifo[s->rx_cur];
> > > > +s->rx_cur = (s->rx_cur + 1u) % NPCM7XX_SMBUS_FIFO_SIZE;
> > > > +--s->rxf_sts;
> > >
> > > This open-coded decrement seems a little risky.  Are you sure in every
> > > case that s->rxf_sts > 0?  There's no way what's running in the VM can
> > > game this and cause a buffer overrun?  One caller to this function
> seems
> > > to protect against this, and another does not.
> > >
> > s->rxf_sts is uint8_t so it's guaranteed to be >=0.
> > In the case s->rxf_sts == 0,  NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts) is
> > also 0, so it'll take the if-branch and return without running
> --s->rxf_sts.
>
> That is true if called from the
> NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE case.  There is no such check
> in the NPCM7XX_SMBUS_STATUS_RECEIVING case.
>
I don't understand the reasoning here. The caller doesn't matter.
Previous code has:
 #define NPCM7XX_SMBRXF_STS_RX_BYTES(rv) extract8((rv), 0, 5)
So
 uint8_t received_bytes = NPCM7XX_SMBRXF_STS_RX_BYTES(s->rxf_sts);
is guaranteed to be 0 if s->rxf_sts == 0.
As a result the code will take the following branch and returns:
 if (received_bytes == 0) {
npcm7xx_smbus_recv_fifo(s);
return;
 }
And will not execute the --s->rxf_sts sentence.
Please let me know if I missed anything here.

>
> > I'll probably add "g_assert(s->rxf_sts > 0)" to clarify.
>
> You never want to do an assert if the hosted system can do something to
> cause it.  If you add the check to the NPCM7XX_SMBUS_STATUS_RECEIVING
> case, it would be ok, but really unnecessary.
>
> If it's fine if s->rxf_sts wraps to 0xff, then this all doesn't matter,
> but you want to add a comment to that effect if so.  These sorts of
> things look dangerous.
>
> There is also the question about who takes these patches in.  I'm the
> I2C maintainer, but there's other code in this series.  Once everything
> is ready, I can ack them if we take it through the ARM tree.  Or I can
> take it through my tree with the proper acks.
>
I think either  way is fine. Previous NPCM7XX patch series were taken in
the ARM tree. But as i2c code taking into your tree is also fine.

>
> -corey
>
> >
> > >
> > > Other than this, I didn't see any issues with this patch.
> > >
> > > -corey
> > >
>


[PATCH v2 0/6] hw/i2c: Add NPCM7XX SMBus Device

2021-01-28 Thread wuhaotsh--- via
This patch set implements the System manager bus (SMBus) module in NPCM7XX
SoC. Basically, it emulates the data transactions of the module, not the
SDA/SCL levels. We have also added a QTest which contains read and write
operations for both single-byte and FIFO mode, and added basic I2C devices
for npcm750-evb and quanta-gsj boards.

We also cleaned up the unimplemented GPIO devices in npcm7xx.c since they
are already implemented.

Changes since v1:
- Fix errors for i2c device addresses for temperature sensors in GSJ machine
- Use at24c device to emulate GSJ EEPROM. It supports more than 256 bytes.
- Fill in VMState in npcm7xx_smbus.c
- Change commit message in patch 3 and 4
- Fix order in npcm7xx.c IRQ list
- Add a few extra comments to make things clearer

Hao Wu (6):
  hw/arm: Remove GPIO from unimplemented NPCM7XX
  hw/i2c: Implement NPCM7XX SMBus Module Single Mode
  hw/arm: Add I2C sensors for NPCM750 eval board
  hw/arm: Add I2C sensors and EEPROM for GSJ machine
  hw/i2c: Add a QTest for NPCM7XX SMBus Device
  hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode

 default-configs/devices/arm-softmmu.mak |1 +
 docs/system/arm/nuvoton.rst |2 +-
 hw/arm/npcm7xx.c|   76 +-
 hw/arm/npcm7xx_boards.c |   46 +
 hw/i2c/meson.build  |1 +
 hw/i2c/npcm7xx_smbus.c  | 1097 +++
 hw/i2c/trace-events |   12 +
 include/hw/arm/npcm7xx.h|2 +
 include/hw/i2c/npcm7xx_smbus.h  |  113 +++
 tests/qtest/meson.build |1 +
 tests/qtest/npcm7xx_smbus-test.c|  495 ++
 11 files changed, 1821 insertions(+), 25 deletions(-)
 create mode 100644 hw/i2c/npcm7xx_smbus.c
 create mode 100644 include/hw/i2c/npcm7xx_smbus.h
 create mode 100644 tests/qtest/npcm7xx_smbus-test.c

-- 
2.30.0.365.g02bc693789-goog




[PATCH v2 3/6] hw/arm: Add I2C sensors for NPCM750 eval board

2021-01-28 Thread wuhaotsh--- via
Add I2C temperature sensors for NPCM750 eval board.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
---
 hw/arm/npcm7xx_boards.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 3fdd5cab01..47a215bd01 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -98,6 +98,24 @@ static NPCM7xxState *npcm7xx_create_soc(MachineState 
*machine,
 return NPCM7XX(obj);
 }
 
+static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, uint32_t num)
+{
+g_assert(num < ARRAY_SIZE(soc->smbus));
+return I2C_BUS(qdev_get_child_bus(DEVICE(&soc->smbus[num]), "i2c-bus"));
+}
+
+static void npcm750_evb_i2c_init(NPCM7xxState *soc)
+{
+/* lm75 temperature sensor on SVB, tmp105 is compatible */
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 0), "tmp105", 0x48);
+/* lm75 temperature sensor on EB, tmp105 is compatible */
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x48);
+/* tmp100 temperature sensor on EB, tmp105 is compatible */
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x48);
+/* tmp100 temperature sensor on SVB, tmp105 is compatible */
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
+}
+
 static void npcm750_evb_init(MachineState *machine)
 {
 NPCM7xxState *soc;
@@ -108,6 +126,7 @@ static void npcm750_evb_init(MachineState *machine)
 
 npcm7xx_load_bootrom(machine, soc);
 npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
+npcm750_evb_i2c_init(soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.30.0.365.g02bc693789-goog




[PATCH v2 2/6] hw/i2c: Implement NPCM7XX SMBus Module Single Mode

2021-01-28 Thread wuhaotsh--- via
This commit implements the single-byte mode of the SMBus.

Each Nuvoton SoC has 16 System Management Bus (SMBus). These buses
compliant with SMBus and I2C protocol.

This patch implements the single-byte mode of the SMBus. In this mode,
the user sends or receives a byte each time. The SMBus device transmits
it to the underlying i2c device and sends an interrupt back to the QEMU
guest.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
Reviewed-by: Corey Minyard 
Ack-by: Corey Minyard 
---
 docs/system/arm/nuvoton.rst|   2 +-
 hw/arm/npcm7xx.c   |  68 ++-
 hw/i2c/meson.build |   1 +
 hw/i2c/npcm7xx_smbus.c | 781 +
 hw/i2c/trace-events|  11 +
 include/hw/arm/npcm7xx.h   |   2 +
 include/hw/i2c/npcm7xx_smbus.h |  88 
 7 files changed, 936 insertions(+), 17 deletions(-)
 create mode 100644 hw/i2c/npcm7xx_smbus.c
 create mode 100644 include/hw/i2c/npcm7xx_smbus.h

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index a1786342e2..34fc799b2d 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -43,6 +43,7 @@ Supported devices
  * GPIO controller
  * Analog to Digital Converter (ADC)
  * Pulse Width Modulation (PWM)
+ * SMBus controller (SMBF)
 
 Missing devices
 ---
@@ -58,7 +59,6 @@ Missing devices
 
  * Ethernet controllers (GMAC and EMC)
  * USB device (USBD)
- * SMBus controller (SMBF)
  * Peripheral SPI controller (PSPI)
  * SD/MMC host
  * PECI interface
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index d1fe9bd1df..f8950f9470 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -102,6 +102,22 @@ enum NPCM7xxInterrupt {
 NPCM7XX_WDG2_IRQ,   /* Timer Module 2 Watchdog */
 NPCM7XX_EHCI_IRQ= 61,
 NPCM7XX_OHCI_IRQ= 62,
+NPCM7XX_SMBUS0_IRQ  = 64,
+NPCM7XX_SMBUS1_IRQ,
+NPCM7XX_SMBUS2_IRQ,
+NPCM7XX_SMBUS3_IRQ,
+NPCM7XX_SMBUS4_IRQ,
+NPCM7XX_SMBUS5_IRQ,
+NPCM7XX_SMBUS6_IRQ,
+NPCM7XX_SMBUS7_IRQ,
+NPCM7XX_SMBUS8_IRQ,
+NPCM7XX_SMBUS9_IRQ,
+NPCM7XX_SMBUS10_IRQ,
+NPCM7XX_SMBUS11_IRQ,
+NPCM7XX_SMBUS12_IRQ,
+NPCM7XX_SMBUS13_IRQ,
+NPCM7XX_SMBUS14_IRQ,
+NPCM7XX_SMBUS15_IRQ,
 NPCM7XX_PWM0_IRQ= 93,   /* PWM module 0 */
 NPCM7XX_PWM1_IRQ,   /* PWM module 1 */
 NPCM7XX_GPIO0_IRQ   = 116,
@@ -152,6 +168,26 @@ static const hwaddr npcm7xx_pwm_addr[] = {
 0xf0104000,
 };
 
+/* Direct memory-mapped access to each SMBus Module. */
+static const hwaddr npcm7xx_smbus_addr[] = {
+0xf008,
+0xf0081000,
+0xf0082000,
+0xf0083000,
+0xf0084000,
+0xf0085000,
+0xf0086000,
+0xf0087000,
+0xf0088000,
+0xf0089000,
+0xf008a000,
+0xf008b000,
+0xf008c000,
+0xf008d000,
+0xf008e000,
+0xf008f000,
+};
+
 static const struct {
 hwaddr regs_addr;
 uint32_t unconnected_pins;
@@ -353,6 +389,11 @@ static void npcm7xx_init(Object *obj)
 object_initialize_child(obj, "gpio[*]", &s->gpio[i], 
TYPE_NPCM7XX_GPIO);
 }
 
+for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
+object_initialize_child(obj, "smbus[*]", &s->smbus[i],
+TYPE_NPCM7XX_SMBUS);
+}
+
 object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
 object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
 
@@ -509,6 +550,17 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i));
 }
 
+/* SMBus modules. Cannot fail. */
+QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_smbus_addr) != ARRAY_SIZE(s->smbus));
+for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
+Object *obj = OBJECT(&s->smbus[i]);
+
+sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_smbus_addr[i]);
+sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
+   npcm7xx_irq(s, NPCM7XX_SMBUS0_IRQ + i));
+}
+
 /* USB Host */
 object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
  &error_abort);
@@ -576,22 +628,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 create_unimplemented_device("npcm7xx.pcierc",   0xe100,  64 * KiB);
 create_unimplemented_device("npcm7xx.kcs",  0xf0007000,   4 * KiB);
 create_unimplemented_device("npcm7xx.gfxi", 0xf000e000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[0]", 0xf008,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000,   4 * KiB);
-create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000,   4 * KiB);
-create_unimplemente

[PATCH v2 1/6] hw/arm: Remove GPIO from unimplemented NPCM7XX

2021-01-28 Thread wuhaotsh--- via
NPCM7XX GPIO devices have been implemented in hw/gpio/npcm7xx-gpio.c. So
we removed them from the unimplemented devices list.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu
---
 hw/arm/npcm7xx.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 72040d4079..d1fe9bd1df 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -576,14 +576,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 create_unimplemented_device("npcm7xx.pcierc",   0xe100,  64 * KiB);
 create_unimplemented_device("npcm7xx.kcs",  0xf0007000,   4 * KiB);
 create_unimplemented_device("npcm7xx.gfxi", 0xf000e000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[0]",  0xf001,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[1]",  0xf0011000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[2]",  0xf0012000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[3]",  0xf0013000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[4]",  0xf0014000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[5]",  0xf0015000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[6]",  0xf0016000,   4 * KiB);
-create_unimplemented_device("npcm7xx.gpio[7]",  0xf0017000,   4 * KiB);
 create_unimplemented_device("npcm7xx.smbus[0]", 0xf008,   4 * KiB);
 create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000,   4 * KiB);
 create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000,   4 * KiB);
-- 
2.30.0.365.g02bc693789-goog




[PATCH v2 4/6] hw/arm: Add I2C sensors and EEPROM for GSJ machine

2021-01-28 Thread wuhaotsh--- via
Add AT24 EEPROM and temperature sensors for GSJ machine.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
---
 default-configs/devices/arm-softmmu.mak |  1 +
 hw/arm/npcm7xx_boards.c | 27 +
 2 files changed, 28 insertions(+)

diff --git a/default-configs/devices/arm-softmmu.mak 
b/default-configs/devices/arm-softmmu.mak
index 0500156a0c..d9805dd539 100644
--- a/default-configs/devices/arm-softmmu.mak
+++ b/default-configs/devices/arm-softmmu.mak
@@ -7,6 +7,7 @@ CONFIG_ARM_V7M=y
 # CONFIG_TEST_DEVICES=n
 
 CONFIG_ARM_VIRT=y
+CONFIG_AT24C=y
 CONFIG_CUBIEBOARD=y
 CONFIG_EXYNOS4=y
 CONFIG_HIGHBANK=y
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 47a215bd01..2d757b4013 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -19,6 +19,7 @@
 #include "exec/address-spaces.h"
 #include "hw/arm/npcm7xx.h"
 #include "hw/core/cpu.h"
+#include "hw/i2c/smbus_eeprom.h"
 #include "hw/loader.h"
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
@@ -104,6 +105,17 @@ static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, 
uint32_t num)
 return I2C_BUS(qdev_get_child_bus(DEVICE(&soc->smbus[num]), "i2c-bus"));
 }
 
+static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr,
+  uint32_t rsize)
+{
+I2CBus *i2c_bus = npcm7xx_i2c_get_bus(soc, bus);
+I2CSlave *i2c_dev = i2c_slave_new("at24c-eeprom", addr);
+DeviceState *dev = DEVICE(i2c_dev);
+
+qdev_prop_set_uint32(dev, "rom-size", rsize);
+i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort);
+}
+
 static void npcm750_evb_i2c_init(NPCM7xxState *soc)
 {
 /* lm75 temperature sensor on SVB, tmp105 is compatible */
@@ -116,6 +128,20 @@ static void npcm750_evb_i2c_init(NPCM7xxState *soc)
 i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
 }
 
+static void quanta_gsj_i2c_init(NPCM7xxState *soc)
+{
+/* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatible. 
*/
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x5c);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x5c);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 3), "tmp105", 0x5c);
+i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), "tmp105", 0x5c);
+
+at24c_eeprom_init(soc, 9, 0x55, 8192);
+at24c_eeprom_init(soc, 10, 0x55, 8192);
+
+/* TODO: Add addtional i2c devices. */
+}
+
 static void npcm750_evb_init(MachineState *machine)
 {
 NPCM7xxState *soc;
@@ -141,6 +167,7 @@ static void quanta_gsj_init(MachineState *machine)
 npcm7xx_load_bootrom(machine, soc);
 npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
   drive_get(IF_MTD, 0, 0));
+quanta_gsj_i2c_init(soc);
 npcm7xx_load_kernel(machine, soc);
 }
 
-- 
2.30.0.365.g02bc693789-goog




[PATCH v2 6/6] hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode

2021-01-28 Thread wuhaotsh--- via
This patch implements the FIFO mode of the SMBus module. In FIFO, the
user transmits or receives at most 16 bytes at a time. The FIFO mode
allows the module to transmit large amount of data faster than single
byte mode.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
Reviewed-by: Corey Minyard 
Ack-by: Corey Minyard 
---
 hw/i2c/npcm7xx_smbus.c   | 342 +--
 hw/i2c/trace-events  |   1 +
 include/hw/i2c/npcm7xx_smbus.h   |  25 +++
 tests/qtest/npcm7xx_smbus-test.c | 149 +-
 4 files changed, 501 insertions(+), 16 deletions(-)

diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
index c72b6e446f..be3253d251 100644
--- a/hw/i2c/npcm7xx_smbus.c
+++ b/hw/i2c/npcm7xx_smbus.c
@@ -27,7 +27,7 @@
 #include "trace.h"
 
 #define NPCM7XX_SMBUS_VERSION 1
-#define NPCM7XX_SMBUS_FIFO_EN 0
+#define NPCM7XX_SMBUS_FIFO_EN 1
 
 enum NPCM7xxSMBusCommonRegister {
 NPCM7XX_SMB_SDA = 0x0,
@@ -132,10 +132,41 @@ enum NPCM7xxSMBusBank1Register {
 #define NPCM7XX_ADDR_EN BIT(7)
 #define NPCM7XX_ADDR_A(rv)  extract8((rv), 0, 6)
 
+/* FIFO Mode Register Fields */
+/* FIF_CTL fields */
+#define NPCM7XX_SMBFIF_CTL_FIFO_EN  BIT(4)
+#define NPCM7XX_SMBFIF_CTL_FAIR_RDY_IE  BIT(2)
+#define NPCM7XX_SMBFIF_CTL_FAIR_RDY BIT(1)
+#define NPCM7XX_SMBFIF_CTL_FAIR_BUSYBIT(0)
+/* FIF_CTS fields */
+#define NPCM7XX_SMBFIF_CTS_STR  BIT(7)
+#define NPCM7XX_SMBFIF_CTS_CLR_FIFO BIT(6)
+#define NPCM7XX_SMBFIF_CTS_RFTE_IE  BIT(3)
+#define NPCM7XX_SMBFIF_CTS_RXF_TXE  BIT(1)
+/* TXF_CTL fields */
+#define NPCM7XX_SMBTXF_CTL_THR_TXIE BIT(6)
+#define NPCM7XX_SMBTXF_CTL_TX_THR(rv)   extract8((rv), 0, 5)
+/* T_OUT fields */
+#define NPCM7XX_SMBT_OUT_ST BIT(7)
+#define NPCM7XX_SMBT_OUT_IE BIT(6)
+#define NPCM7XX_SMBT_OUT_CLKDIV(rv) extract8((rv), 0, 6)
+/* TXF_STS fields */
+#define NPCM7XX_SMBTXF_STS_TX_THST  BIT(6)
+#define NPCM7XX_SMBTXF_STS_TX_BYTES(rv) extract8((rv), 0, 5)
+/* RXF_STS fields */
+#define NPCM7XX_SMBRXF_STS_RX_THST  BIT(6)
+#define NPCM7XX_SMBRXF_STS_RX_BYTES(rv) extract8((rv), 0, 5)
+/* RXF_CTL fields */
+#define NPCM7XX_SMBRXF_CTL_THR_RXIE BIT(6)
+#define NPCM7XX_SMBRXF_CTL_LAST BIT(5)
+#define NPCM7XX_SMBRXF_CTL_RX_THR(rv)   extract8((rv), 0, 5)
+
 #define KEEP_OLD_BIT(o, n, b)   (((n) & (~(b))) | ((o) & (b)))
 #define WRITE_ONE_CLEAR(o, n, b)((n) & (b) ? (o) & (~(b)) : (o))
 
 #define NPCM7XX_SMBUS_ENABLED(s)((s)->ctl2 & NPCM7XX_SMBCTL2_ENABLE)
+#define NPCM7XX_SMBUS_FIFO_ENABLED(s) (NPCM7XX_SMBUS_FIFO_EN && \
+(s)->fif_ctl & NPCM7XX_SMBFIF_CTL_FIFO_EN)
 
 /* Reset values */
 #define NPCM7XX_SMB_ST_INIT_VAL 0x00
@@ -150,6 +181,14 @@ enum NPCM7xxSMBusBank1Register {
 #define NPCM7XX_SMB_ADDR_INIT_VAL   0x00
 #define NPCM7XX_SMB_SCLLT_INIT_VAL  0x00
 #define NPCM7XX_SMB_SCLHT_INIT_VAL  0x00
+#define NPCM7XX_SMB_FIF_CTL_INIT_VAL 0x00
+#define NPCM7XX_SMB_FIF_CTS_INIT_VAL 0x00
+#define NPCM7XX_SMB_FAIR_PER_INIT_VAL 0x00
+#define NPCM7XX_SMB_TXF_CTL_INIT_VAL 0x00
+#define NPCM7XX_SMB_T_OUT_INIT_VAL 0x3f
+#define NPCM7XX_SMB_TXF_STS_INIT_VAL 0x00
+#define NPCM7XX_SMB_RXF_STS_INIT_VAL 0x00
+#define NPCM7XX_SMB_RXF_CTL_INIT_VAL 0x01
 
 static uint8_t npcm7xx_smbus_get_version(void)
 {
@@ -169,7 +208,13 @@ static void npcm7xx_smbus_update_irq(NPCM7xxSMBusState *s)
(s->ctl1 & NPCM7XX_SMBCTL1_STASTRE &&
 s->st & NPCM7XX_SMBST_SDAST) ||
(s->ctl1 & NPCM7XX_SMBCTL1_EOBINTE &&
-s->cst3 & NPCM7XX_SMBCST3_EO_BUSY));
+s->cst3 & NPCM7XX_SMBCST3_EO_BUSY) ||
+   (s->rxf_ctl & NPCM7XX_SMBRXF_CTL_THR_RXIE &&
+s->rxf_sts & NPCM7XX_SMBRXF_STS_RX_THST) ||
+   (s->txf_ctl & NPCM7XX_SMBTXF_CTL_THR_TXIE &&
+s->txf_sts & NPCM7XX_SMBTXF_STS_TX_THST) ||
+   (s->fif_cts & NPCM7XX_SMBFIF_CTS_RFTE_IE &&
+s->fif_cts & NPCM7XX_SMBFIF_CTS_RXF_TXE));
 
 if (level) {
 s->cst2 |= NPCM7XX_SMBCST2_INTSTS;
@@ -187,6 +232,13 @@ static void npcm7xx_smbus_nack(NPCM7xxSMBusState *s)
 s->status = NPCM7XX_SMBUS_STATUS_NEGACK;
 }
 
+static void npcm7xx_smbus_clear_buffer(NPCM7xxSMBusState *s)
+{
+s->fif_cts &= ~NPCM7XX_SMBFIF_CTS_RXF_TXE;
+s->txf_sts = 0;
+s->rxf_sts = 0;
+}
+
 static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, uint8_t value)
 {
 int rv = i2c_send(s->bus, value);
@@ -195,6 +247,15 @@ static void npcm7xx_smbus_send_byte(NPCM7xxSMBusState *s, 
uint8_t value)
 npcm7xx_smbus_nack(s);
 } else {
 s->st |= NPCM7XX_SMBST_SDAST;
+if (NPCM7XX_SMBUS_FIFO_ENABLED(s)) {
+s->fif_cts |= NPCM7XX_SMBFIF_CTS_RXF_TXE;
+if (NPCM7XX_SMBTXF_STS_TX_BYTES(s->txf_sts) ==
+NPCM7XX

[PATCH v2 5/6] hw/i2c: Add a QTest for NPCM7XX SMBus Device

2021-01-28 Thread wuhaotsh--- via
This patch adds a QTest for NPCM7XX SMBus's single byte mode. It sends a
byte to a device in the evaluation board, and verify the retrieved value
is equivalent to the sent value.

Reviewed-by: Doug Evans
Reviewed-by: Tyrong Ting
Signed-off-by: Hao Wu 
---
 tests/qtest/meson.build  |   1 +
 tests/qtest/npcm7xx_smbus-test.c | 352 +++
 2 files changed, 353 insertions(+)
 create mode 100644 tests/qtest/npcm7xx_smbus-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 16d04625b8..aa62d59817 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -138,6 +138,7 @@ qtests_npcm7xx = \
'npcm7xx_gpio-test',
'npcm7xx_pwm-test',
'npcm7xx_rng-test',
+   'npcm7xx_smbus-test',
'npcm7xx_timer-test',
'npcm7xx_watchdog_timer-test']
 qtests_arm = \
diff --git a/tests/qtest/npcm7xx_smbus-test.c b/tests/qtest/npcm7xx_smbus-test.c
new file mode 100644
index 00..4594b107df
--- /dev/null
+++ b/tests/qtest/npcm7xx_smbus-test.c
@@ -0,0 +1,352 @@
+/*
+ * QTests for Nuvoton NPCM7xx SMBus Modules.
+ *
+ * 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/bitops.h"
+#include "libqos/i2c.h"
+#include "libqos/libqtest.h"
+#include "hw/misc/tmp105_regs.h"
+
+#define NR_SMBUS_DEVICES16
+#define SMBUS_ADDR(x)   (0xf008 + 0x1000 * (x))
+#define SMBUS_IRQ(x)(64 + (x))
+
+#define EVB_DEVICE_ADDR 0x48
+#define INVALID_DEVICE_ADDR 0x01
+
+const int evb_bus_list[] = {0, 1, 2, 6};
+
+/* Offsets */
+enum CommonRegister {
+OFFSET_SDA = 0x0,
+OFFSET_ST  = 0x2,
+OFFSET_CST = 0x4,
+OFFSET_CTL1= 0x6,
+OFFSET_ADDR1   = 0x8,
+OFFSET_CTL2= 0xa,
+OFFSET_ADDR2   = 0xc,
+OFFSET_CTL3= 0xe,
+OFFSET_CST2= 0x18,
+OFFSET_CST3= 0x19,
+};
+
+enum NPCM7xxSMBusBank0Register {
+OFFSET_ADDR3   = 0x10,
+OFFSET_ADDR7   = 0x11,
+OFFSET_ADDR4   = 0x12,
+OFFSET_ADDR8   = 0x13,
+OFFSET_ADDR5   = 0x14,
+OFFSET_ADDR9   = 0x15,
+OFFSET_ADDR6   = 0x16,
+OFFSET_ADDR10  = 0x17,
+OFFSET_CTL4= 0x1a,
+OFFSET_CTL5= 0x1b,
+OFFSET_SCLLT   = 0x1c,
+OFFSET_FIF_CTL = 0x1d,
+OFFSET_SCLHT   = 0x1e,
+};
+
+enum NPCM7xxSMBusBank1Register {
+OFFSET_FIF_CTS  = 0x10,
+OFFSET_FAIR_PER = 0x11,
+OFFSET_TXF_CTL  = 0x12,
+OFFSET_T_OUT= 0x14,
+OFFSET_TXF_STS  = 0x1a,
+OFFSET_RXF_STS  = 0x1c,
+OFFSET_RXF_CTL  = 0x1e,
+};
+
+/* ST fields */
+#define ST_STP  BIT(7)
+#define ST_SDASTBIT(6)
+#define ST_BER  BIT(5)
+#define ST_NEGACK   BIT(4)
+#define ST_STASTR   BIT(3)
+#define ST_NMATCH   BIT(2)
+#define ST_MODE BIT(1)
+#define ST_XMIT BIT(0)
+
+/* CST fields */
+#define CST_ARPMATCHBIT(7)
+#define CST_MATCHAF BIT(6)
+#define CST_TGSCL   BIT(5)
+#define CST_TSDABIT(4)
+#define CST_GCMATCH BIT(3)
+#define CST_MATCH   BIT(2)
+#define CST_BB  BIT(1)
+#define CST_BUSYBIT(0)
+
+/* CST2 fields */
+#define CST2_INSTTS BIT(7)
+#define CST2_MATCH7FBIT(6)
+#define CST2_MATCH6FBIT(5)
+#define CST2_MATCH5FBIT(4)
+#define CST2_MATCH4FBIT(3)
+#define CST2_MATCH3FBIT(2)
+#define CST2_MATCH2FBIT(1)
+#define CST2_MATCH1FBIT(0)
+
+/* CST3 fields */
+#define CST3_EO_BUSYBIT(7)
+#define CST3_MATCH10F   BIT(2)
+#define CST3_MATCH9FBIT(1)
+#define CST3_MATCH8FBIT(0)
+
+/* CTL1 fields */
+#define CTL1_STASTREBIT(7)
+#define CTL1_NMINTE BIT(6)
+#define CTL1_GCMEN  BIT(5)
+#define CTL1_ACKBIT(4)
+#define CTL1_EOBINTEBIT(3)
+#define CTL1_INTEN  BIT(2)
+#define CTL1_STOP   BIT(1)
+#define CTL1_START  BIT(0)
+
+/* CTL2 fields */
+#define CTL2_SCLFRQ(rv) extract8((rv), 1, 6)
+#define CTL2_ENABLE BIT(0)
+
+/* CTL3 fields */
+#define CTL3_SCL_LVLBIT(7)
+#define CTL3_SDA_LVLBIT(6)
+#define CTL3_BNK_SELBIT(5)
+#define CTL3_400K_MODE  BIT(4)
+#define CTL3_IDL_START  BIT(3)
+#define CTL3_ARPMEN BIT(2)
+#define CTL3_SCLFRQ(rv) extract8((rv), 0, 2)
+
+/* ADDR fields */
+#define ADDR_EN BIT(7)
+#define ADDR_A(rv)  extract8((rv), 0, 6)
+
+
+static void check_running(QTestState *qts, uint64_t base_addr)
+{
+g_assert_true(qtest_readb(qts, base_

Re: [PULL 17/21] hw/adc: Add an ADC module for NPCM7XX

2021-01-29 Thread wuhaotsh--- via
On Fri, Jan 29, 2021 at 6:41 AM Philippe Mathieu-Daudé 
wrote:

> Hi Hao Wu,
>
> On 1/12/21 5:57 PM, Peter Maydell wrote:
> > From: Hao Wu 
> >
> > The ADC is part of NPCM7XX Module. Its behavior is controled by the
> > ADC_CON register. It converts one of the eight analog inputs into a
> > digital input and stores it in the ADC_DATA register when enabled.
> >
> > Users can alter input value by using qom-set QMP command.
> >
> > Reviewed-by: Havard Skinnemoen 
> > Reviewed-by: Tyrone Ting 
> > Signed-off-by: Hao Wu 
> > Message-id: 20210108190945.949196-4-wuhao...@google.com
> > [PMM: Added missing hw/adc/trace.h file]
> > Reviewed-by: Peter Maydell 
> > Signed-off-by: Peter Maydell 
> > ---
> >  docs/system/arm/nuvoton.rst|   2 +-
> >  meson.build|   1 +
> >  hw/adc/trace.h |   1 +
> >  include/hw/adc/npcm7xx_adc.h   |  69 ++
> >  include/hw/arm/npcm7xx.h   |   2 +
> >  hw/adc/npcm7xx_adc.c   | 301 ++
> >  hw/arm/npcm7xx.c   |  24 ++-
> >  tests/qtest/npcm7xx_adc-test.c | 377 +
> >  hw/adc/meson.build |   1 +
> >  hw/adc/trace-events|   5 +
> >  tests/qtest/meson.build|   3 +-
> >  11 files changed, 783 insertions(+), 3 deletions(-)
> >  create mode 100644 hw/adc/trace.h
> >  create mode 100644 include/hw/adc/npcm7xx_adc.h
> >  create mode 100644 hw/adc/npcm7xx_adc.c
> >  create mode 100644 tests/qtest/npcm7xx_adc-test.c
> >  create mode 100644 hw/adc/trace-events
> ...
>
> > diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
> > new file mode 100644
> > index 000..870a6d50c27
> > --- /dev/null
> > +++ b/hw/adc/npcm7xx_adc.c
> > @@ -0,0 +1,301 @@
> > +/*
> > + * Nuvoton NPCM7xx ADC Module
> > + *
> > + * 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/adc/npcm7xx_adc.h"
> > +#include "hw/qdev-clock.h"
> > +#include "hw/qdev-properties.h"
> > +#include "hw/registerfields.h"
> > +#include "migration/vmstate.h"
> > +#include "qemu/log.h"
> > +#include "qemu/module.h"
> > +#include "qemu/timer.h"
> > +#include "qemu/units.h"
> > +#include "trace.h"
> > +
> > +REG32(NPCM7XX_ADC_CON, 0x0)
> > +REG32(NPCM7XX_ADC_DATA, 0x4)
> > +
> > +/* Register field definitions. */
> > +#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
> > +#define NPCM7XX_ADC_CON_INT_EN  BIT(21)
> > +#define NPCM7XX_ADC_CON_REFSEL  BIT(19)
> > +#define NPCM7XX_ADC_CON_INT BIT(18)
> > +#define NPCM7XX_ADC_CON_EN  BIT(17)
> > +#define NPCM7XX_ADC_CON_RST BIT(16)
> > +#define NPCM7XX_ADC_CON_CONVBIT(14)
> > +#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
> > +
> > +#define NPCM7XX_ADC_MAX_RESULT  1023
> > +#define NPCM7XX_ADC_DEFAULT_IREF200
> > +#define NPCM7XX_ADC_CONV_CYCLES 20
> > +#define NPCM7XX_ADC_RESET_CYCLES10
> > +#define NPCM7XX_ADC_R0_INPUT50
> > +#define NPCM7XX_ADC_R1_INPUT150
> > +
> > +static void npcm7xx_adc_reset(NPCM7xxADCState *s)
> > +{
> > +timer_del(&s->conv_timer);
> > +s->con = 0x000c0001;
>
> This initialize CON to:
>
> NPCM7XX_ADC_CON_REFSEL | NPCM7XX_ADC_CON_INT | BIT(0)
>
> What is bit 0?
>
This reset value is from h/w spec. The bit is reserved and not used
currently.

>
> > +s->data = 0x;
> > +}
>


Re: [PATCH] npcm7xx_adc-test: Fix memleak in adc_qom_set

2021-01-18 Thread wuhaotsh--- via
On Sun, Jan 17, 2021 at 10:59 PM Gan Qixin  wrote:

> The adc_qom_set 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 593280 byte(s) in 144 object(s) allocated from:
> #0 0x7f9a5e7e8d4e in __interceptor_calloc
> (/lib64/libasan.so.5+0x112d4e)
> #1 0x7f9a5e607a50 in g_malloc0 (/lib64/libglib-2.0.so.0+0x55a50)
> #2 0x55b1bebf636b in qdict_new ../qobject/qdict.c:30
> #3 0x55b1bec09699 in parse_object ../qobject/json-parser.c:318
> #4 0x55b1bec0b2df in parse_value ../qobject/json-parser.c:546
> #5 0x55b1bec0b6a9 in json_parser_parse ../qobject/json-parser.c:580
> #6 0x55b1bec060d1 in json_message_process_token
> ../qobject/json-streamer.c:92
> #7 0x55b1bec16a12 in json_lexer_feed_char ../qobject/json-lexer.c:313
> #8 0x55b1bec16fbd in json_lexer_feed ../qobject/json-lexer.c:350
> #9 0x55b1bec06453 in json_message_parser_feed
> ../qobject/json-streamer.c:121
> #10 0x55b1bebc2d51 in qmp_fd_receive ../tests/qtest/libqtest.c:614
> #11 0x55b1bebc2f5e in qtest_qmp_receive_dict
> ../tests/qtest/libqtest.c:636
> #12 0x55b1bebc2e6c in qtest_qmp_receive ../tests/qtest/libqtest.c:624
> #13 0x55b1bebc3340 in qtest_vqmp ../tests/qtest/libqtest.c:715
> #14 0x55b1bebc3942 in qtest_qmp ../tests/qtest/libqtest.c:756
> #15 0x55b1bebbd64a in adc_qom_set ../tests/qtest/npcm7xx_adc-test.c:127
> #16 0x55b1bebbd793 in adc_write_input
> ../tests/qtest/npcm7xx_adc-test.c:140
> #17 0x55b1bebbdf92 in test_convert_external
> ../tests/qtest/npcm7xx_adc-test.c:246
>
> Reported-by: Euler Robot 
> Signed-off-by: Gan Qixin 
>
Reviewed-by: Hao Wu 

Thanks!

> ---
> Cc: Hao Wu 
> Cc: Havard Skinnemoen 
> Cc: Tyrone Ting 
> Cc: Thomas Huth 
> Cc: Laurent Vivier 
> ---
>  tests/qtest/npcm7xx_adc-test.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/tests/qtest/npcm7xx_adc-test.c
> b/tests/qtest/npcm7xx_adc-test.c
> index f029706945..5ce8ce13b3 100644
> --- a/tests/qtest/npcm7xx_adc-test.c
> +++ b/tests/qtest/npcm7xx_adc-test.c
> @@ -129,6 +129,7 @@ static void adc_qom_set(QTestState *qts, const ADC
> *adc,
>  path, name, value);
>  /* The qom set message returns successfully. */
>  g_assert_true(qdict_haskey(response, "return"));
> +qobject_unref(response);
>  }
>
>  static void adc_write_input(QTestState *qts, const ADC *adc,
> --
> 2.27.0
>
>