[PATCH] hw/misc: Fix arith overflow in NPCM7XX PWM module
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 > >