[PATCH 7/8] hw/arm: Set drive property for at24c eeprom
This patch allows the user to attach an external drive as a property for an onboard at24c eeprom device. It uses an unit number to distinguish different devices. Signed-off-by: Hao Wu --- hw/arm/npcm7xx_boards.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index b083b0c572..b8337871ba 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -141,11 +141,16 @@ static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, uint32_t num) } static void at24c_eeprom_init(I2CBus *i2c_bus, int bus, uint8_t addr, - uint32_t rsize) + uint32_t rsize, int unit) { I2CSlave *i2c_dev = i2c_slave_new("at24c-eeprom", addr); DeviceState *dev = DEVICE(i2c_dev); +DriveInfo *dinfo; +dinfo = drive_get(IF_OTHER, bus, unit); +if (dinfo) { +qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo)); +} qdev_prop_set_uint32(dev, "rom-size", rsize); i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort); } @@ -252,8 +257,8 @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc) 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(npcm7xx_i2c_get_bus(soc, 9), 9, 0x55, 8192); -at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 10), 10, 0x55, 8192); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 9), 9, 0x55, 8192, 0); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 10), 10, 0x55, 8192, 1); /* * i2c-11: @@ -360,7 +365,7 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77); /* mbfru */ -at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 4), 4, 0x50, 8192); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 4), 4, 0x50, 8192, 0); i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); @@ -372,7 +377,7 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x49); /* bmcfru */ -at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 14), 14, 0x55, 8192); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 14), 14, 0x55, 8192, 1); /* TODO: Add remaining i2c devices. */ } -- 2.37.0.170.g444d1eabd0-goog
[PATCH 6/8] hw/arm: npcm8xx_boards: EEPROMs can take bus as parameter
We allow at24c_eeprom_init to take a I2CBus* as parameter. This allows us to attach an EEPROM device behind an I2C mux which is not possible with the old method. Signed-off-by: Hao Wu --- hw/arm/npcm7xx_boards.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 6bc6f5d2fe..b083b0c572 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -140,10 +140,9 @@ 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, +static void at24c_eeprom_init(I2CBus *i2c_bus, 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); @@ -253,8 +252,8 @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc) 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); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 9), 9, 0x55, 8192); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 10), 10, 0x55, 8192); /* * i2c-11: @@ -360,7 +359,8 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77); -at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ +/* mbfru */ +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 4), 4, 0x50, 8192); i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); @@ -371,7 +371,8 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 4), "tmp105", 0x48); i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x49); -at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ +/* bmcfru */ +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 14), 14, 0x55, 8192); /* TODO: Add remaining i2c devices. */ } -- 2.37.0.170.g444d1eabd0-goog
[PATCH 1/8] hw/i2c: Clear ACK bit in NPCM7xx SMBus module
The ACK bit in NPCM7XX SMBus module should be cleared each time it sends out a NACK signal. This patch fixes the bug that it fails to do so. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell --- hw/i2c/npcm7xx_smbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index e7e0ba66fe..f18e311556 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -270,7 +270,7 @@ static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s) if (s->st & NPCM7XX_SMBCTL1_ACK) { trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); i2c_nack(s->bus); -s->st &= NPCM7XX_SMBCTL1_ACK; +s->st &= ~NPCM7XX_SMBCTL1_ACK; } trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda); npcm7xx_smbus_update_irq(s); -- 2.37.0.170.g444d1eabd0-goog
[PATCH 4/8] hw/adc: Make adci[*] R/W in NPCM7XX ADC
Our sensor test requires both reading and writing from a sensor's QOM property. So we need to make the input of ADC module R/W instead of write only for that to work. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 47fb9e5f74..bc6f3f55e6 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -242,7 +242,7 @@ static void npcm7xx_adc_init(Object *obj) for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) { object_property_add_uint32_ptr(obj, "adci[*]", -&s->adci[i], OBJ_PROP_FLAG_WRITE); +&s->adci[i], OBJ_PROP_FLAG_READWRITE); } object_property_add_uint32_ptr(obj, "vref", &s->vref, OBJ_PROP_FLAG_WRITE); -- 2.37.0.170.g444d1eabd0-goog
[PATCH 0/8] Misc NPCM7XX patches
[NOTE: I'm reviving a bunch of patches that was in the process of upstreaming a while ago but paused.] This patch set contains a few bug fixes and I2C devices for some NPCM7XX boards. Patch 1~2 fix a problem that causes the SMBus module to behave incorrectly when it's in FIFO mode and trying to receive more than 16 bytes at a time. Patch 3 fixes a error in a register for ADC module. Patch 4 makes the ADC input to be R/W instead of write only. It allows a test system to read these via QMP and has no negative effect. Patch 5 adds a new blockdev IF type IF_OTHER. Patch 6 allows at24c_eeprom_init to take a bus as parameter so it can be used by more use cases (e.g. behind an I2C mux.) Patch 7 allows at24c_eeprom_init to take a drive as property, similar to sdhci_attach_device(). Patch 8 uses the function defined in patch 5 to add the EEPROM and other I2C devices for Quanta GBS board. -- Changes since v4: 1. Add comments to patch 5. 2. Split patch 6 into 2 patches according to the feedback. Each patch does it own task. -- Changes since v3: 1. Add a new blockdev IF type IF_OTHER. 2. Use IF_OTHER instead of IF_NONE. -- Changes since v2: 1. Dropped patch 7. 2. Drop an extra variable in patch 5. -- Changes since v1: 1. Rewrote patch 5 to implement the function in NPCM7xx board file instead of the EEPROM device file. 2. Slightly modify patch 6 to adapt to the changes and QEMU comment style. 3. Squash patch 7 into patch 5 to make it compile. 4. Add a new patch 7. Hao Wu (7): hw/i2c: Clear ACK bit in NPCM7xx SMBus module hw/i2c: Read FIFO during RXF_CTL change in NPCM7XX SMBus hw/adc: Fix CONV bit in NPCM7XX ADC CON register hw/adc: Make adci[*] R/W in NPCM7XX ADC blockdev: Add a new IF type IF_OTHER hw/arm: npcm8xx_boards: EEPROMs can take bus as parameter hw/arm: Set drive property for at24c eeprom Patrick Venture (1): hw/arm: quanta-gbs-bmc add i2c devices blockdev.c | 4 +- hw/adc/npcm7xx_adc.c | 4 +- hw/arm/npcm7xx_boards.c| 102 - hw/i2c/npcm7xx_smbus.c | 8 +-- include/sysemu/blockdev.h | 1 + tests/qtest/npcm7xx_adc-test.c | 2 +- 6 files changed, 73 insertions(+), 48 deletions(-) -- 2.37.0.170.g444d1eabd0-goog
[PATCH 2/8] hw/i2c: Read FIFO during RXF_CTL change in NPCM7XX SMBus
Originally we read in from SMBus when RXF_STS is cleared. However, the driver clears RXF_STS before setting RXF_CTL, causing the SM bus module to read incorrect amount of bytes in FIFO mode when the number of bytes read changed. This patch fixes this issue. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Acked-by: Corey Minyard --- hw/i2c/npcm7xx_smbus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index f18e311556..1435daea94 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -637,9 +637,6 @@ static void npcm7xx_smbus_write_rxf_sts(NPCM7xxSMBusState *s, uint8_t value) { if (value & NPCM7XX_SMBRXF_STS_RX_THST) { s->rxf_sts &= ~NPCM7XX_SMBRXF_STS_RX_THST; -if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { -npcm7xx_smbus_recv_fifo(s); -} } } @@ -651,6 +648,9 @@ static void npcm7xx_smbus_write_rxf_ctl(NPCM7xxSMBusState *s, uint8_t value) new_ctl = KEEP_OLD_BIT(s->rxf_ctl, new_ctl, NPCM7XX_SMBRXF_CTL_LAST); } s->rxf_ctl = new_ctl; +if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { +npcm7xx_smbus_recv_fifo(s); +} } static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size) -- 2.37.0.170.g444d1eabd0-goog
[PATCH 5/8] blockdev: Add a new IF type IF_OTHER
This type is used to represent block devs that are not suitable to be represented by other existing types. A sample use is to represent an at24c eeprom device defined in hw/nvram/eeprom_at24c.c. The block device can be used to contain the content of the said eeprom device. Signed-off-by: Hao Wu --- blockdev.c| 4 +++- include/sysemu/blockdev.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index 9230888e34..befd69ac5f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -82,6 +82,7 @@ static const char *const if_name[IF_COUNT] = { [IF_MTD] = "mtd", [IF_SD] = "sd", [IF_VIRTIO] = "virtio", +[IF_OTHER] = "other", [IF_XEN] = "xen", }; @@ -726,7 +727,8 @@ QemuOptsList qemu_legacy_drive_opts = { },{ .name = "if", .type = QEMU_OPT_STRING, -.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", +.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio," +" other)", },{ .name = "file", .type = QEMU_OPT_STRING, diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 3211b16513..d9dd5af291 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -21,6 +21,7 @@ typedef enum { */ IF_NONE = 0, IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, +IF_OTHER, IF_COUNT } BlockInterfaceType; -- 2.37.0.170.g444d1eabd0-goog
[PATCH 3/8] hw/adc: Fix CONV bit in NPCM7XX ADC CON register
The correct bit for the CONV bit in NPCM7XX ADC is bit 13. This patch fixes that in the module, and also lower the IRQ when the guest is done handling an interrupt event from the ADC module. Signed-off-by: Hao Wu Reviewed-by: Patrick Venture Reviewed-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- tests/qtest/npcm7xx_adc-test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 0f0a9f63e2..47fb9e5f74 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -36,7 +36,7 @@ REG32(NPCM7XX_ADC_DATA, 0x4) #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_CONVBIT(13) #define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8) #define NPCM7XX_ADC_MAX_RESULT 1023 diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c index 3fa6d9ece0..8048044d28 100644 --- a/tests/qtest/npcm7xx_adc-test.c +++ b/tests/qtest/npcm7xx_adc-test.c @@ -50,7 +50,7 @@ #define CON_INT BIT(18) #define CON_EN BIT(17) #define CON_RST BIT(16) -#define CON_CONVBIT(14) +#define CON_CONVBIT(13) #define CON_DIV(rv) extract32(rv, 1, 8) #define FST_RDSTBIT(1) -- 2.37.0.170.g444d1eabd0-goog
[PATCH 8/8] hw/arm: quanta-gbs-bmc add i2c devices
From: Patrick Venture Adds supported i2c devices to the quanta-gbc-bmc board. Signed-off-by: Patrick Venture Reviewed-by: Hao Wu --- hw/arm/npcm7xx_boards.c | 82 - 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index b8337871ba..4bae5589f0 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -290,10 +290,12 @@ static void quanta_gsj_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc) static void quanta_gbs_i2c_init(NPCM7xxState *soc) { +I2CSlave *i2c_mux; + +/* i2c-0: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 0), TYPE_PCA9546, 0x71); + /* - * i2c-0: - * pca9546@71 - * * i2c-1: * pca9535@24 * pca9535@20 @@ -302,46 +304,60 @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) * pca9535@23 * pca9535@25 * pca9535@26 - * - * i2c-2: - * sbtsi@4c - * - * i2c-5: - * atmel,24c64@50 mb_fru - * pca9546@71 - * - channel 0: max31725@54 - * - channel 1: max31725@55 - * - channel 2: max31725@5d - * atmel,24c64@51 fan_fru - * - channel 3: atmel,24c64@52 hsbp_fru - * + */ + +/* i2c-2: sbtsi@4c */ + +/* i2c-5: */ +/* mb_fru */ +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 5), 5, 0x50, 8192, 0); +i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 5), + TYPE_PCA9546, 0x71); +/* max31725 is tmp105 compatible. */ +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 0), "tmp105", 0x54); +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1), "tmp105", 0x55); +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 2), "tmp105", 0x5d); +/* fan_fru */ +at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 2), 5, 0x51, 8192, 1); +/* hsbp_fru */ +at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 3), 5, 0x52, 8192, 2); + +/* * i2c-6: * pca9545@73 * * i2c-7: * pca9545@72 - * - * i2c-8: - * adi,adm1272@10 - * - * i2c-9: - * pca9546@71 - * - channel 0: isil,isl68137@60 - * - channel 1: isil,isl68137@61 - * - channel 2: isil,isl68137@63 - * - channel 3: isil,isl68137@45 - * + */ + +/* i2c-8: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 8), "adm1272", 0x10); + +/* i2c-9: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 9), TYPE_PCA9546, 0x71); +/* + * - channel 0: isil,isl68137@60 + * - channel 1: isil,isl68137@61 + * - channel 2: isil,isl68137@63 + * - channel 3: isil,isl68137@45 + */ + +/* * i2c-10: * pca9545@71 * * i2c-11: * pca9545@76 - * - * i2c-12: - * maxim,max34451@4e - * isil,isl68137@5d - * isil,isl68137@5e - * + */ + +/* i2c-12: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 12), "max34451", 0x4e); +/* + * isil,isl68137@5d + * isil,isl68137@5e + */ + +/* * i2c-14: * pca9545@70 */ -- 2.37.0.170.g444d1eabd0-goog
[PATCH 0/8] Misc NPCM7XX patches
[NOTE: I'm reviving a bunch of patches that was in the process of upstreaming a while ago but paused.] This patch set contains a few bug fixes and I2C devices for some NPCM7XX boards. Patch 1~2 fix a problem that causes the SMBus module to behave incorrectly when it's in FIFO mode and trying to receive more than 16 bytes at a time. Patch 3 fixes a error in a register for ADC module. Patch 4 makes the ADC input to be R/W instead of write only. It allows a test system to read these via QMP and has no negative effect. Patch 5 adds a new blockdev IF type IF_OTHER. Patch 6 allows at24c_eeprom_init to take a bus as parameter so it can be used by more use cases (e.g. behind an I2C mux.) Patch 7 allows at24c_eeprom_init to take a drive as property, similar to sdhci_attach_device(). Patch 8 uses the function defined in patch 5 to add the EEPROM and other I2C devices for Quanta GBS board. -- Changes since v4: 1. Add comments to patch 5. 2. Split patch 6 into 2 patches according to the feedback. Each patch does it own task. -- Changes since v3: 1. Add a new blockdev IF type IF_OTHER. 2. Use IF_OTHER instead of IF_NONE. -- Changes since v2: 1. Dropped patch 7. 2. Drop an extra variable in patch 5. -- Changes since v1: 1. Rewrote patch 5 to implement the function in NPCM7xx board file instead of the EEPROM device file. 2. Slightly modify patch 6 to adapt to the changes and QEMU comment style. 3. Squash patch 7 into patch 5 to make it compile. 4. Add a new patch 7. Hao Wu (7): hw/i2c: Clear ACK bit in NPCM7xx SMBus module hw/i2c: Read FIFO during RXF_CTL change in NPCM7XX SMBus hw/adc: Fix CONV bit in NPCM7XX ADC CON register hw/adc: Make adci[*] R/W in NPCM7XX ADC blockdev: Add a new IF type IF_OTHER hw/arm: npcm8xx_boards: EEPROMs can take bus as parameter hw/arm: Set drive property for at24c eeprom Patrick Venture (1): hw/arm: quanta-gbs-bmc add i2c devices blockdev.c | 4 +- hw/adc/npcm7xx_adc.c | 4 +- hw/arm/npcm7xx_boards.c| 102 - hw/i2c/npcm7xx_smbus.c | 8 +-- include/sysemu/blockdev.h | 1 + tests/qtest/npcm7xx_adc-test.c | 2 +- 6 files changed, 73 insertions(+), 48 deletions(-) -- 2.37.0.170.g444d1eabd0-goog
[PATCH 3/8] hw/adc: Fix CONV bit in NPCM7XX ADC CON register
The correct bit for the CONV bit in NPCM7XX ADC is bit 13. This patch fixes that in the module, and also lower the IRQ when the guest is done handling an interrupt event from the ADC module. Signed-off-by: Hao Wu Reviewed-by: Patrick Venture Reviewed-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- tests/qtest/npcm7xx_adc-test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 0f0a9f63e2..47fb9e5f74 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -36,7 +36,7 @@ REG32(NPCM7XX_ADC_DATA, 0x4) #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_CONVBIT(13) #define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8) #define NPCM7XX_ADC_MAX_RESULT 1023 diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c index 3fa6d9ece0..8048044d28 100644 --- a/tests/qtest/npcm7xx_adc-test.c +++ b/tests/qtest/npcm7xx_adc-test.c @@ -50,7 +50,7 @@ #define CON_INT BIT(18) #define CON_EN BIT(17) #define CON_RST BIT(16) -#define CON_CONVBIT(14) +#define CON_CONVBIT(13) #define CON_DIV(rv) extract32(rv, 1, 8) #define FST_RDSTBIT(1) -- 2.37.0.170.g444d1eabd0-goog
[PATCH 4/8] hw/adc: Make adci[*] R/W in NPCM7XX ADC
Our sensor test requires both reading and writing from a sensor's QOM property. So we need to make the input of ADC module R/W instead of write only for that to work. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 47fb9e5f74..bc6f3f55e6 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -242,7 +242,7 @@ static void npcm7xx_adc_init(Object *obj) for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) { object_property_add_uint32_ptr(obj, "adci[*]", -&s->adci[i], OBJ_PROP_FLAG_WRITE); +&s->adci[i], OBJ_PROP_FLAG_READWRITE); } object_property_add_uint32_ptr(obj, "vref", &s->vref, OBJ_PROP_FLAG_WRITE); -- 2.37.0.170.g444d1eabd0-goog
[PATCH 1/8] hw/i2c: Clear ACK bit in NPCM7xx SMBus module
The ACK bit in NPCM7XX SMBus module should be cleared each time it sends out a NACK signal. This patch fixes the bug that it fails to do so. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell --- hw/i2c/npcm7xx_smbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index e7e0ba66fe..f18e311556 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -270,7 +270,7 @@ static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s) if (s->st & NPCM7XX_SMBCTL1_ACK) { trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); i2c_nack(s->bus); -s->st &= NPCM7XX_SMBCTL1_ACK; +s->st &= ~NPCM7XX_SMBCTL1_ACK; } trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda); npcm7xx_smbus_update_irq(s); -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 0/8] Misc NPCM7XX patches
[NOTE: I'm reviving a bunch of patches that was in the process of upstreaming a while ago but paused.] This patch set contains a few bug fixes and I2C devices for some NPCM7XX boards. Patch 1~2 fix a problem that causes the SMBus module to behave incorrectly when it's in FIFO mode and trying to receive more than 16 bytes at a time. Patch 3 fixes a error in a register for ADC module. Patch 4 makes the ADC input to be R/W instead of write only. It allows a test system to read these via QMP and has no negative effect. Patch 5 adds a new blockdev IF type IF_OTHER. Patch 6 allows at24c_eeprom_init to take a bus as parameter so it can be used by more use cases (e.g. behind an I2C mux.) Patch 7 allows at24c_eeprom_init to take a drive as property, similar to sdhci_attach_device(). Patch 8 uses the function defined in patch 5 to add the EEPROM and other I2C devices for Quanta GBS board. -- Changes since v4: 1. Add comments to patch 5. 2. Split patch 6 into 2 patches according to the feedback. Each patch does it own task. -- Changes since v3: 1. Add a new blockdev IF type IF_OTHER. 2. Use IF_OTHER instead of IF_NONE. -- Changes since v2: 1. Dropped patch 7. 2. Drop an extra variable in patch 5. -- Changes since v1: 1. Rewrote patch 5 to implement the function in NPCM7xx board file instead of the EEPROM device file. 2. Slightly modify patch 6 to adapt to the changes and QEMU comment style. 3. Squash patch 7 into patch 5 to make it compile. 4. Add a new patch 7. Hao Wu (7): hw/i2c: Clear ACK bit in NPCM7xx SMBus module hw/i2c: Read FIFO during RXF_CTL change in NPCM7XX SMBus hw/adc: Fix CONV bit in NPCM7XX ADC CON register hw/adc: Make adci[*] R/W in NPCM7XX ADC blockdev: Add a new IF type IF_OTHER hw/arm: npcm8xx_boards: EEPROMs can take bus as parameter hw/arm: Set drive property for at24c eeprom Patrick Venture (1): hw/arm: quanta-gbs-bmc add i2c devices blockdev.c | 4 +- hw/adc/npcm7xx_adc.c | 4 +- hw/arm/npcm7xx_boards.c| 102 - hw/i2c/npcm7xx_smbus.c | 8 +-- include/sysemu/blockdev.h | 1 + tests/qtest/npcm7xx_adc-test.c | 2 +- 6 files changed, 73 insertions(+), 48 deletions(-) -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 1/8] hw/i2c: Clear ACK bit in NPCM7xx SMBus module
The ACK bit in NPCM7XX SMBus module should be cleared each time it sends out a NACK signal. This patch fixes the bug that it fails to do so. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell --- hw/i2c/npcm7xx_smbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index e7e0ba66fe..f18e311556 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -270,7 +270,7 @@ static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s) if (s->st & NPCM7XX_SMBCTL1_ACK) { trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); i2c_nack(s->bus); -s->st &= NPCM7XX_SMBCTL1_ACK; +s->st &= ~NPCM7XX_SMBCTL1_ACK; } trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda); npcm7xx_smbus_update_irq(s); -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 2/8] hw/i2c: Read FIFO during RXF_CTL change in NPCM7XX SMBus
Originally we read in from SMBus when RXF_STS is cleared. However, the driver clears RXF_STS before setting RXF_CTL, causing the SM bus module to read incorrect amount of bytes in FIFO mode when the number of bytes read changed. This patch fixes this issue. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Acked-by: Corey Minyard --- hw/i2c/npcm7xx_smbus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index f18e311556..1435daea94 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -637,9 +637,6 @@ static void npcm7xx_smbus_write_rxf_sts(NPCM7xxSMBusState *s, uint8_t value) { if (value & NPCM7XX_SMBRXF_STS_RX_THST) { s->rxf_sts &= ~NPCM7XX_SMBRXF_STS_RX_THST; -if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { -npcm7xx_smbus_recv_fifo(s); -} } } @@ -651,6 +648,9 @@ static void npcm7xx_smbus_write_rxf_ctl(NPCM7xxSMBusState *s, uint8_t value) new_ctl = KEEP_OLD_BIT(s->rxf_ctl, new_ctl, NPCM7XX_SMBRXF_CTL_LAST); } s->rxf_ctl = new_ctl; +if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { +npcm7xx_smbus_recv_fifo(s); +} } static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size) -- 2.37.0.170.g444d1eabd0-goog
[PATCH 2/8] hw/i2c: Read FIFO during RXF_CTL change in NPCM7XX SMBus
Originally we read in from SMBus when RXF_STS is cleared. However, the driver clears RXF_STS before setting RXF_CTL, causing the SM bus module to read incorrect amount of bytes in FIFO mode when the number of bytes read changed. This patch fixes this issue. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Acked-by: Corey Minyard --- hw/i2c/npcm7xx_smbus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index f18e311556..1435daea94 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -637,9 +637,6 @@ static void npcm7xx_smbus_write_rxf_sts(NPCM7xxSMBusState *s, uint8_t value) { if (value & NPCM7XX_SMBRXF_STS_RX_THST) { s->rxf_sts &= ~NPCM7XX_SMBRXF_STS_RX_THST; -if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { -npcm7xx_smbus_recv_fifo(s); -} } } @@ -651,6 +648,9 @@ static void npcm7xx_smbus_write_rxf_ctl(NPCM7xxSMBusState *s, uint8_t value) new_ctl = KEEP_OLD_BIT(s->rxf_ctl, new_ctl, NPCM7XX_SMBRXF_CTL_LAST); } s->rxf_ctl = new_ctl; +if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { +npcm7xx_smbus_recv_fifo(s); +} } static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size) -- 2.37.0.170.g444d1eabd0-goog
[PATCH 5/8] blockdev: Add a new IF type IF_OTHER
This type is used to represent block devs that are not suitable to be represented by other existing types. A sample use is to represent an at24c eeprom device defined in hw/nvram/eeprom_at24c.c. The block device can be used to contain the content of the said eeprom device. Signed-off-by: Hao Wu --- blockdev.c| 4 +++- include/sysemu/blockdev.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index 9230888e34..befd69ac5f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -82,6 +82,7 @@ static const char *const if_name[IF_COUNT] = { [IF_MTD] = "mtd", [IF_SD] = "sd", [IF_VIRTIO] = "virtio", +[IF_OTHER] = "other", [IF_XEN] = "xen", }; @@ -726,7 +727,8 @@ QemuOptsList qemu_legacy_drive_opts = { },{ .name = "if", .type = QEMU_OPT_STRING, -.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", +.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio," +" other)", },{ .name = "file", .type = QEMU_OPT_STRING, diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 3211b16513..d9dd5af291 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -21,6 +21,7 @@ typedef enum { */ IF_NONE = 0, IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, +IF_OTHER, IF_COUNT } BlockInterfaceType; -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 5/8] blockdev: Add a new IF type IF_OTHER
This type is used to represent block devs that are not suitable to be represented by other existing types. A sample use is to represent an at24c eeprom device defined in hw/nvram/eeprom_at24c.c. The block device can be used to contain the content of the said eeprom device. Signed-off-by: Hao Wu --- blockdev.c| 4 +++- include/sysemu/blockdev.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index 9230888e34..befd69ac5f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -82,6 +82,7 @@ static const char *const if_name[IF_COUNT] = { [IF_MTD] = "mtd", [IF_SD] = "sd", [IF_VIRTIO] = "virtio", +[IF_OTHER] = "other", [IF_XEN] = "xen", }; @@ -726,7 +727,8 @@ QemuOptsList qemu_legacy_drive_opts = { },{ .name = "if", .type = QEMU_OPT_STRING, -.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", +.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio," +" other)", },{ .name = "file", .type = QEMU_OPT_STRING, diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 3211b16513..d9dd5af291 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -21,6 +21,7 @@ typedef enum { */ IF_NONE = 0, IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, +IF_OTHER, IF_COUNT } BlockInterfaceType; -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 7/8] hw/arm: Set drive property for at24c eeprom
This patch allows the user to attach an external drive as a property for an onboard at24c eeprom device. It uses an unit number to distinguish different devices. Signed-off-by: Hao Wu --- hw/arm/npcm7xx_boards.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index b083b0c572..b8337871ba 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -141,11 +141,16 @@ static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, uint32_t num) } static void at24c_eeprom_init(I2CBus *i2c_bus, int bus, uint8_t addr, - uint32_t rsize) + uint32_t rsize, int unit) { I2CSlave *i2c_dev = i2c_slave_new("at24c-eeprom", addr); DeviceState *dev = DEVICE(i2c_dev); +DriveInfo *dinfo; +dinfo = drive_get(IF_OTHER, bus, unit); +if (dinfo) { +qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo)); +} qdev_prop_set_uint32(dev, "rom-size", rsize); i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort); } @@ -252,8 +257,8 @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc) 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(npcm7xx_i2c_get_bus(soc, 9), 9, 0x55, 8192); -at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 10), 10, 0x55, 8192); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 9), 9, 0x55, 8192, 0); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 10), 10, 0x55, 8192, 1); /* * i2c-11: @@ -360,7 +365,7 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77); /* mbfru */ -at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 4), 4, 0x50, 8192); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 4), 4, 0x50, 8192, 0); i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); @@ -372,7 +377,7 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x49); /* bmcfru */ -at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 14), 14, 0x55, 8192); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 14), 14, 0x55, 8192, 1); /* TODO: Add remaining i2c devices. */ } -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 4/8] hw/adc: Make adci[*] R/W in NPCM7XX ADC
Our sensor test requires both reading and writing from a sensor's QOM property. So we need to make the input of ADC module R/W instead of write only for that to work. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 47fb9e5f74..bc6f3f55e6 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -242,7 +242,7 @@ static void npcm7xx_adc_init(Object *obj) for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) { object_property_add_uint32_ptr(obj, "adci[*]", -&s->adci[i], OBJ_PROP_FLAG_WRITE); +&s->adci[i], OBJ_PROP_FLAG_READWRITE); } object_property_add_uint32_ptr(obj, "vref", &s->vref, OBJ_PROP_FLAG_WRITE); -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 3/8] hw/adc: Fix CONV bit in NPCM7XX ADC CON register
The correct bit for the CONV bit in NPCM7XX ADC is bit 13. This patch fixes that in the module, and also lower the IRQ when the guest is done handling an interrupt event from the ADC module. Signed-off-by: Hao Wu Reviewed-by: Patrick Venture Reviewed-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- tests/qtest/npcm7xx_adc-test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 0f0a9f63e2..47fb9e5f74 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -36,7 +36,7 @@ REG32(NPCM7XX_ADC_DATA, 0x4) #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_CONVBIT(13) #define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8) #define NPCM7XX_ADC_MAX_RESULT 1023 diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c index 3fa6d9ece0..8048044d28 100644 --- a/tests/qtest/npcm7xx_adc-test.c +++ b/tests/qtest/npcm7xx_adc-test.c @@ -50,7 +50,7 @@ #define CON_INT BIT(18) #define CON_EN BIT(17) #define CON_RST BIT(16) -#define CON_CONVBIT(14) +#define CON_CONVBIT(13) #define CON_DIV(rv) extract32(rv, 1, 8) #define FST_RDSTBIT(1) -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 6/8] hw/arm: npcm8xx_boards: EEPROMs can take bus as parameter
We allow at24c_eeprom_init to take a I2CBus* as parameter. This allows us to attach an EEPROM device behind an I2C mux which is not possible with the old method. Signed-off-by: Hao Wu --- hw/arm/npcm7xx_boards.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 6bc6f5d2fe..b083b0c572 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -140,10 +140,9 @@ 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, +static void at24c_eeprom_init(I2CBus *i2c_bus, 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); @@ -253,8 +252,8 @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc) 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); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 9), 9, 0x55, 8192); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 10), 10, 0x55, 8192); /* * i2c-11: @@ -360,7 +359,8 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77); -at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ +/* mbfru */ +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 4), 4, 0x50, 8192); i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); @@ -371,7 +371,8 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 4), "tmp105", 0x48); i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x49); -at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ +/* bmcfru */ +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 14), 14, 0x55, 8192); /* TODO: Add remaining i2c devices. */ } -- 2.37.0.170.g444d1eabd0-goog
[PATCH v5 8/8] hw/arm: quanta-gbs-bmc add i2c devices
From: Patrick Venture Adds supported i2c devices to the quanta-gbc-bmc board. Signed-off-by: Patrick Venture Reviewed-by: Hao Wu --- hw/arm/npcm7xx_boards.c | 82 - 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index b8337871ba..4bae5589f0 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -290,10 +290,12 @@ static void quanta_gsj_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc) static void quanta_gbs_i2c_init(NPCM7xxState *soc) { +I2CSlave *i2c_mux; + +/* i2c-0: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 0), TYPE_PCA9546, 0x71); + /* - * i2c-0: - * pca9546@71 - * * i2c-1: * pca9535@24 * pca9535@20 @@ -302,46 +304,60 @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) * pca9535@23 * pca9535@25 * pca9535@26 - * - * i2c-2: - * sbtsi@4c - * - * i2c-5: - * atmel,24c64@50 mb_fru - * pca9546@71 - * - channel 0: max31725@54 - * - channel 1: max31725@55 - * - channel 2: max31725@5d - * atmel,24c64@51 fan_fru - * - channel 3: atmel,24c64@52 hsbp_fru - * + */ + +/* i2c-2: sbtsi@4c */ + +/* i2c-5: */ +/* mb_fru */ +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 5), 5, 0x50, 8192, 0); +i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 5), + TYPE_PCA9546, 0x71); +/* max31725 is tmp105 compatible. */ +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 0), "tmp105", 0x54); +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1), "tmp105", 0x55); +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 2), "tmp105", 0x5d); +/* fan_fru */ +at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 2), 5, 0x51, 8192, 1); +/* hsbp_fru */ +at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 3), 5, 0x52, 8192, 2); + +/* * i2c-6: * pca9545@73 * * i2c-7: * pca9545@72 - * - * i2c-8: - * adi,adm1272@10 - * - * i2c-9: - * pca9546@71 - * - channel 0: isil,isl68137@60 - * - channel 1: isil,isl68137@61 - * - channel 2: isil,isl68137@63 - * - channel 3: isil,isl68137@45 - * + */ + +/* i2c-8: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 8), "adm1272", 0x10); + +/* i2c-9: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 9), TYPE_PCA9546, 0x71); +/* + * - channel 0: isil,isl68137@60 + * - channel 1: isil,isl68137@61 + * - channel 2: isil,isl68137@63 + * - channel 3: isil,isl68137@45 + */ + +/* * i2c-10: * pca9545@71 * * i2c-11: * pca9545@76 - * - * i2c-12: - * maxim,max34451@4e - * isil,isl68137@5d - * isil,isl68137@5e - * + */ + +/* i2c-12: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 12), "max34451", 0x4e); +/* + * isil,isl68137@5d + * isil,isl68137@5e + */ + +/* * i2c-14: * pca9545@70 */ -- 2.37.0.170.g444d1eabd0-goog
[PATCH v3 0/5] hw/arm: Add MMC device for NPCM7XX boards
This patch set implements the Nuvoton MMC device for NPCM7XX boards. The MMC device is compatible with the SDHCI interface in QEMU. It allows the user to attach an SD card image to it. Changes since v2: 1. Fix an error use of strcmp in qtest. Changes since v1: 1. Rearrange the "add SDHCI commands" to just before when it's actually used. 2. Add standrad SDHCI MMIO as subregion, similar to cadence_sdhci. e. Add a vmstate for NPCM7XX SDHCI. 4. Address various minor fixes suggested by Peter Maydell. Shengtan Mao (5): hw/sd: add nuvoton MMC hw/arm: Add Nuvoton SD module to board hw/arm: Attach MMC to quanta-gbs-bmc tests/qtest/libqos: add SDHCI commands tests/qtest: add qtests for npcm7xx sdhci hw/arm/npcm7xx.c | 12 +- hw/arm/npcm7xx_boards.c | 20 +++ hw/sd/meson.build| 1 + hw/sd/npcm7xx_sdhci.c| 182 +++ include/hw/arm/npcm7xx.h | 2 + include/hw/sd/npcm7xx_sdhci.h| 65 ++ tests/qtest/libqos/meson.build | 1 + tests/qtest/libqos/sdhci-cmd.c | 116 + tests/qtest/libqos/sdhci-cmd.h | 70 +++ tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 209 +++ 11 files changed, 678 insertions(+), 1 deletion(-) create mode 100644 hw/sd/npcm7xx_sdhci.c create mode 100644 include/hw/sd/npcm7xx_sdhci.h create mode 100644 tests/qtest/libqos/sdhci-cmd.c create mode 100644 tests/qtest/libqos/sdhci-cmd.h create mode 100644 tests/qtest/npcm7xx_sdhci-test.c -- 2.33.1.1089.g2158813163f-goog
[PATCH v3 1/5] hw/sd: add nuvoton MMC
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- hw/sd/meson.build | 1 + hw/sd/npcm7xx_sdhci.c | 182 ++ include/hw/sd/npcm7xx_sdhci.h | 65 3 files changed, 248 insertions(+) create mode 100644 hw/sd/npcm7xx_sdhci.c create mode 100644 include/hw/sd/npcm7xx_sdhci.h diff --git a/hw/sd/meson.build b/hw/sd/meson.build index f1ce357a3b..807ca07b7c 100644 --- a/hw/sd/meson.build +++ b/hw/sd/meson.build @@ -9,4 +9,5 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_mmci.c')) softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c')) softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c')) softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c')) +softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c')) softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c')) diff --git a/hw/sd/npcm7xx_sdhci.c b/hw/sd/npcm7xx_sdhci.c new file mode 100644 index 00..ef503365df --- /dev/null +++ b/hw/sd/npcm7xx_sdhci.c @@ -0,0 +1,182 @@ +/* + * NPCM7xx SD-3.0 / eMMC-4.51 Host Controller + * + * Copyright (c) 2021 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/sd/npcm7xx_sdhci.h" +#include "migration/vmstate.h" +#include "sdhci-internal.h" +#include "qemu/log.h" + +static uint64_t npcm7xx_sdhci_read(void *opaque, hwaddr addr, unsigned int size) +{ +NPCM7xxSDHCIState *s = opaque; +uint64_t val = 0; + +switch (addr) { +case NPCM7XX_PRSTVALS_0: +case NPCM7XX_PRSTVALS_1: +case NPCM7XX_PRSTVALS_2: +case NPCM7XX_PRSTVALS_3: +case NPCM7XX_PRSTVALS_4: +case NPCM7XX_PRSTVALS_5: +val = s->regs.prstvals[(addr - NPCM7XX_PRSTVALS_0) / 2]; +break; +case NPCM7XX_BOOTTOCTRL: +val = s->regs.boottoctrl; +break; +default: +qemu_log_mask(LOG_GUEST_ERROR, "SDHCI read of nonexistent reg: 0x%02" + HWADDR_PRIx, addr); +break; +} + +return val; +} + +static void npcm7xx_sdhci_write(void *opaque, hwaddr addr, uint64_t val, +unsigned int size) +{ +NPCM7xxSDHCIState *s = opaque; + +switch (addr) { +case NPCM7XX_BOOTTOCTRL: +s->regs.boottoctrl = val; +break; +default: +qemu_log_mask(LOG_GUEST_ERROR, "SDHCI write of nonexistent reg: 0x%02" + HWADDR_PRIx, addr); +break; +} +} + +static bool npcm7xx_sdhci_check_mem_op(void *opaque, hwaddr addr, + unsigned size, bool is_write, + MemTxAttrs attrs) +{ +switch (addr) { +case NPCM7XX_PRSTVALS_0: +case NPCM7XX_PRSTVALS_1: +case NPCM7XX_PRSTVALS_2: +case NPCM7XX_PRSTVALS_3: +case NPCM7XX_PRSTVALS_4: +case NPCM7XX_PRSTVALS_5: +/* RO Word */ +return !is_write && size == 2; +case NPCM7XX_BOOTTOCTRL: +/* R/W Dword */ +return size == 4; +default: +return false; +} +} + +static const MemoryRegionOps npcm7xx_sdhci_ops = { +.read = npcm7xx_sdhci_read, +.write = npcm7xx_sdhci_write, +.endianness = DEVICE_NATIVE_ENDIAN, +.valid = { +.min_access_size = 1, +.max_access_size = 4, +.unaligned = false, +.accepts = npcm7xx_sdhci_check_mem_op, +}, +}; + +static void npcm7xx_sdhci_realize(DeviceState *dev, Error **errp) +{ +NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(dev); +SysBusDevice *sbd = SYS_BUS_DEVICE(dev); +SysBusDevice *sbd_sdhci = SYS_BUS_DEVICE(&s->sdhci); + +memory_region_init(&s->container, OBJECT(s), + "npcm7xx.sdhci-container", 0x1000); +sysbus_init_mmio(sbd, &s->container); + +memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_sdhci_ops, s, + TYPE_NPCM7XX_SDHCI, NPCM7XX_SDHCI_REGSIZE); +memory_region_add_subregion_overlap(&s->container, NPCM7XX_PRSTVALS, +&s->iomem, 1); + +s
[PATCH v3 3/5] hw/arm: Attach MMC to quanta-gbs-bmc
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- hw/arm/npcm7xx_boards.c | 20 1 file changed, 20 insertions(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index a656169f61..dec7d16ae5 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -27,6 +27,9 @@ #include "qemu-common.h" #include "qemu/datadir.h" #include "qemu/units.h" +#include "sysemu/blockdev.h" +#include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" #define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7 #define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff @@ -81,6 +84,22 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram) &error_abort); } +static void sdhci_attach_drive(SDHCIState *sdhci) +{ +DriveInfo *di = drive_get_next(IF_SD); +BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; + +BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus"); +if (bus == NULL) { +error_report("No SD bus found in SOC object"); +exit(1); +} + +DeviceState *carddev = qdev_new(TYPE_SD_CARD); +qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); +qdev_realize_and_unref(carddev, bus, &error_fatal); +} + static NPCM7xxState *npcm7xx_create_soc(MachineState *machine, uint32_t hw_straps) { @@ -355,6 +374,7 @@ static void quanta_gbs_init(MachineState *machine) drive_get(IF_MTD, 0, 0)); quanta_gbs_i2c_init(soc); +sdhci_attach_drive(&soc->mmc.sdhci); npcm7xx_load_kernel(machine, soc); } -- 2.33.1.1089.g2158813163f-goog
[PATCH v3 2/5] hw/arm: Add Nuvoton SD module to board
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- hw/arm/npcm7xx.c | 12 +++- include/hw/arm/npcm7xx.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index 2ab0080e0b..878c2208e0 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -63,6 +63,8 @@ #define NPCM7XX_ROM_BA (0x) #define NPCM7XX_ROM_SZ (64 * KiB) +/* SDHCI Modules */ +#define NPCM7XX_MMC_BA (0xf0842000) /* Clock configuration values to be fixed up when bypassing bootloader */ @@ -83,6 +85,7 @@ enum NPCM7xxInterrupt { NPCM7XX_UART3_IRQ, NPCM7XX_EMC1RX_IRQ = 15, NPCM7XX_EMC1TX_IRQ, +NPCM7XX_MMC_IRQ = 26, NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */ NPCM7XX_TIMER1_IRQ, NPCM7XX_TIMER2_IRQ, @@ -443,6 +446,8 @@ static void npcm7xx_init(Object *obj) for (i = 0; i < ARRAY_SIZE(s->emc); i++) { object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC); } + +object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI); } static void npcm7xx_realize(DeviceState *dev, Error **errp) @@ -707,6 +712,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) &error_abort); memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom); +/* SDHCI */ +sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort); +sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM7XX_MMC_BA); +sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0, +npcm7xx_irq(s, NPCM7XX_MMC_IRQ)); + create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB); create_unimplemented_device("npcm7xx.vdmx", 0xe080, 4 * KiB); create_unimplemented_device("npcm7xx.pcierc", 0xe100, 64 * KiB); @@ -736,7 +747,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB); create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB); create_unimplemented_device("npcm7xx.sd", 0xf084, 8 * KiB); -create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB); create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB); create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB); create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB); diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h index 61ecc57ab9..ce593235d9 100644 --- a/include/hw/arm/npcm7xx.h +++ b/include/hw/arm/npcm7xx.h @@ -35,6 +35,7 @@ #include "hw/usb/hcd-ehci.h" #include "hw/usb/hcd-ohci.h" #include "target/arm/cpu.h" +#include "hw/sd/npcm7xx_sdhci.h" #define NPCM7XX_MAX_NUM_CPUS(2) @@ -103,6 +104,7 @@ typedef struct NPCM7xxState { OHCISysBusState ohci; NPCM7xxFIUState fiu[2]; NPCM7xxEMCState emc[2]; +NPCM7xxSDHCIState mmc; } NPCM7xxState; #define TYPE_NPCM7XX"npcm7xx" -- 2.33.1.1089.g2158813163f-goog
[PATCH v3 4/5] tests/qtest/libqos: add SDHCI commands
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- tests/qtest/libqos/meson.build | 1 + tests/qtest/libqos/sdhci-cmd.c | 116 + tests/qtest/libqos/sdhci-cmd.h | 70 3 files changed, 187 insertions(+) create mode 100644 tests/qtest/libqos/sdhci-cmd.c create mode 100644 tests/qtest/libqos/sdhci-cmd.h diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build index 1f5c8f1053..4af1f04787 100644 --- a/tests/qtest/libqos/meson.build +++ b/tests/qtest/libqos/meson.build @@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c', 'fw_cfg.c', 'malloc.c', 'libqos.c', +'sdhci-cmd.c', # spapr 'malloc-spapr.c', diff --git a/tests/qtest/libqos/sdhci-cmd.c b/tests/qtest/libqos/sdhci-cmd.c new file mode 100644 index 00..2d9e518341 --- /dev/null +++ b/tests/qtest/libqos/sdhci-cmd.c @@ -0,0 +1,116 @@ +/* + * MMC Host Controller Commands + * + * Copyright (c) 2021 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 "sdhci-cmd.h" +#include "libqtest.h" + +static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count) +{ +uint32_t mask = 0xff; +size_t index = 0; +uint32_t msg_frag; +int size; +while (index < count) { +size = count - index; +if (size > 4) { +size = 4; +} +msg_frag = qtest_readl(qts, reg); +while (size > 0) { +msg[index] = msg_frag & mask; +if (msg[index++] == 0) { +return index; +} +msg_frag >>= 8; +--size; +} +} +return index; +} + +static void write_fifo(QTestState *qts, uint64_t reg, const char *msg, + size_t count) +{ +size_t index = 0; +uint32_t msg_frag; +int size; +int frag_i; +while (index < count) { +size = count - index; +if (size > 4) { +size = 4; +} +msg_frag = 0; +frag_i = 0; +while (frag_i < size) { +msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8); +++frag_i; +} +qtest_writel(qts, reg, msg_frag); +} +} + +static void fill_block(QTestState *qts, uint64_t reg, int count) +{ +while (--count >= 0) { +qtest_writel(qts, reg, 0); +} +} + +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize, +uint16_t blkcnt, uint32_t argument, uint16_t trnmod, +uint16_t cmdreg) +{ +qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize); +qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt); +qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument); +qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod); +qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg); +} + +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg, + size_t count) +{ +sdhci_cmd_regs(qts, base_addr, count, 1, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN, + SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); + +/* read sd fifo_buffer */ +ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count); + +sdhci_cmd_regs(qts, base_addr, 0, 0, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN, + SDHC_STOP_TRANSMISSION); + +return bytes_read; +} + +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg, + size_t count, size_t blksize) +{ +sdhci_cmd_regs(qts, base_addr, blksize, 1, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN, + SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); + +/* write to sd fifo_buffer */ +write_fifo(qts, base_addr + SDHC_BDATA, msg, count); +fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4); + +sdhci_cmd_regs(qts, base_addr, 0, 0, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN, + SDHC_STOP_TRANSMISSION); +} diff --git a/tests/qtest/libqos/sdhci-cmd.h b/tests/qtest/libqos/sdhci-cmd.h new file mode 1006
[PATCH v3 5/5] tests/qtest: add qtests for npcm7xx sdhci
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 209 +++ 2 files changed, 210 insertions(+) create mode 100644 tests/qtest/npcm7xx_sdhci-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index c9d8458062..84fa391229 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -157,6 +157,7 @@ qtests_npcm7xx = \ 'npcm7xx_gpio-test', 'npcm7xx_pwm-test', 'npcm7xx_rng-test', + 'npcm7xx_sdhci-test', 'npcm7xx_smbus-test', 'npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test'] + \ diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c new file mode 100644 index 00..9724c221d1 --- /dev/null +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -0,0 +1,209 @@ +/* + * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller + * + * Copyright (c) 2021 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/sd/npcm7xx_sdhci.h" + +#include "libqos/libqtest.h" +#include "libqtest-single.h" +#include "libqos/sdhci-cmd.h" + +#define NPCM7XX_MMC_BA 0xF0842000 +#define NPCM7XX_BLK_SIZE 512 +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) + +static char *sd_path; + +static QTestState *setup_sd_card(void) +{ +QTestState *qts = qtest_initf( +"-machine quanta-gbs-bmc " +"-device sd-card,drive=drive0 " +"-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off", +sd_path); + +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_SWRST, SDHC_RESET_ALL); +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_CLKCON, + SDHC_CLOCK_SDCLK_EN | SDHC_CLOCK_INT_STABLE | + SDHC_CLOCK_INT_EN); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_APP_CMD); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4120, 0, (41 << 8)); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_ALL_SEND_CID); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4567, 0, + SDHC_SELECT_DESELECT_CARD); + +return qts; +} + +static void write_sdread(QTestState *qts, const char *msg) +{ +size_t len = strlen(msg); +char *rmsg = g_malloc(len); + +/* write message to sd */ +int fd = open(sd_path, O_WRONLY); +int ret; + +g_assert(fd > 0); +ret = write(fd, msg, len); +g_assert(ret == len); +ret = close(fd); +g_assert(ret == 0); + +/* read message using sdhci */ +ret = sdhci_read_cmd(qts, NPCM7XX_MMC_BA, rmsg, len); +g_assert(ret == len); +g_assert(!memcmp(rmsg, msg, len)); + +free(rmsg); +} + +/* Check MMC can read values from sd */ +static void test_read_sd(void) +{ +QTestState *qts = setup_sd_card(); + +write_sdread(qts, "hello world"); +write_sdread(qts, "goodbye"); + +qtest_quit(qts); +} + +static void sdwrite_read(QTestState *qts, const char *msg) +{ +size_t len = strlen(msg); +char *rmsg = g_malloc(len); + +/* write message using sdhci */ +sdhci_write_cmd(qts, NPCM7XX_MMC_BA, msg, len, NPCM7XX_BLK_SIZE); + +/* read message from sd */ +int fd = open(sd_path, O_RDONLY); +int ret; + +g_assert(fd > 0); +ret = read(fd, rmsg, len); +g_assert(ret == len); +ret = close(fd); +g_assert(ret == 0); + +g_assert(!memcmp(rmsg, msg, len)); + +free(rmsg); +} + +/* Check MMC can write values to sd */ +static void test_write_sd(void) +{ +QTestState *qts = setup_sd_card(); + +sdwrite_read(qts, "hello world"); +sdwrite_read(qts, "goodbye"); + +qtest_quit(qts); +} + +/* Check SDHCI has correct default values. */ +static void test_reset(void) +{ +QTestState *qts = qtest_init("-machine quanta-gbs-bmc"); + +uint64_t addr = NPCM7XX_MMC_BA; +uint64_t end_addr = addr + 0x100; +uint16_t prstvals_resets[] = {NPCM7XX_PRSTVALS_0_RESET, + NPCM7XX_PRSTVALS_1_RESET, + 0, + NPCM7XX_PRSTVALS_3_RESET, + 0, +
[PATCH v4 1/7] hw/i2c: Clear ACK bit in NPCM7xx SMBus module
The ACK bit in NPCM7XX SMBus module should be cleared each time it sends out a NACK signal. This patch fixes the bug that it fails to do so. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell --- hw/i2c/npcm7xx_smbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index e7e0ba66fe..f18e311556 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -270,7 +270,7 @@ static void npcm7xx_smbus_recv_byte(NPCM7xxSMBusState *s) if (s->st & NPCM7XX_SMBCTL1_ACK) { trace_npcm7xx_smbus_nack(DEVICE(s)->canonical_path); i2c_nack(s->bus); -s->st &= NPCM7XX_SMBCTL1_ACK; +s->st &= ~NPCM7XX_SMBCTL1_ACK; } trace_npcm7xx_smbus_recv_byte((DEVICE(s)->canonical_path), s->sda); npcm7xx_smbus_update_irq(s); -- 2.33.1.1089.g2158813163f-goog
[PATCH v4 0/7] Misc NPCM7XX patches
This patch set contains a few bug fixes and I2C devices for some NPCM7XX boards. Patch 1~2 fix a problem that causes the SMBus module to behave incorrectly when it's in FIFO mode and trying to receive more than 16 bytes at a time. Patch 3 fixes a error in a register for ADC module. Patch 4 makes the ADC input to be R/W instead of write only. It allows a test system to read these via QMP and has no negative effect. Patch 5 adds a new blockdev IF type IF_OTHER. Patch 6 modifies at24c_eeprom_init in NPCM7xx boards so that it can fit more use cases. Patch 7 uses the function defined in patch 5 to add the EEPROM and other I2C devices for Quanta GBS board. -- Changes since v3: 1. Add a new blockdev IF type IF_OTHER. 2. Use IF_OTHER instead of IF_NONE. -- Changes since v2: 1. Dropped patch 7. 2. Drop an extra variable in patch 5. -- Changes since v1: 1. Rewrote patch 5 to implement the function in NPCM7xx board file instead of the EEPROM device file. 2. Slightly modify patch 6 to adapt to the changes and QEMU comment style. 3. Squash patch 7 into patch 5 to make it compile. 4. Add a new patch 7. Hao Wu (6): hw/i2c: Clear ACK bit in NPCM7xx SMBus module hw/i2c: Read FIFO during RXF_CTL change in NPCM7XX SMBus hw/adc: Fix CONV bit in NPCM7XX ADC CON register hw/adc: Make adci[*] R/W in NPCM7XX ADC blockdev: Add a new IF type IF_OTHER hw/nvram: Update at24c EEPROM init function in NPCM7xx boards Patrick Venture (1): hw/arm: quanta-gbs-bmc add i2c devices blockdev.c | 3 +- hw/adc/npcm7xx_adc.c | 4 +- hw/arm/npcm7xx_boards.c| 96 -- hw/i2c/npcm7xx_smbus.c | 8 +-- include/sysemu/blockdev.h | 1 + meson | 2 +- tests/qtest/npcm7xx_adc-test.c | 2 +- 7 files changed, 69 insertions(+), 47 deletions(-) -- 2.33.1.1089.g2158813163f-goog
[PATCH v4 2/7] hw/i2c: Read FIFO during RXF_CTL change in NPCM7XX SMBus
Originally we read in from SMBus when RXF_STS is cleared. However, the driver clears RXF_STS before setting RXF_CTL, causing the SM bus module to read incorrect amount of bytes in FIFO mode when the number of bytes read changed. This patch fixes this issue. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Acked-by: Corey Minyard --- hw/i2c/npcm7xx_smbus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c index f18e311556..1435daea94 100644 --- a/hw/i2c/npcm7xx_smbus.c +++ b/hw/i2c/npcm7xx_smbus.c @@ -637,9 +637,6 @@ static void npcm7xx_smbus_write_rxf_sts(NPCM7xxSMBusState *s, uint8_t value) { if (value & NPCM7XX_SMBRXF_STS_RX_THST) { s->rxf_sts &= ~NPCM7XX_SMBRXF_STS_RX_THST; -if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { -npcm7xx_smbus_recv_fifo(s); -} } } @@ -651,6 +648,9 @@ static void npcm7xx_smbus_write_rxf_ctl(NPCM7xxSMBusState *s, uint8_t value) new_ctl = KEEP_OLD_BIT(s->rxf_ctl, new_ctl, NPCM7XX_SMBRXF_CTL_LAST); } s->rxf_ctl = new_ctl; +if (s->status == NPCM7XX_SMBUS_STATUS_RECEIVING) { +npcm7xx_smbus_recv_fifo(s); +} } static uint64_t npcm7xx_smbus_read(void *opaque, hwaddr offset, unsigned size) -- 2.33.1.1089.g2158813163f-goog
[PATCH v4 6/7] hw/nvram: Update at24c EEPROM init function in NPCM7xx boards
We made 3 changes to the at24c_eeprom_init function in npcm7xx_boards.c: 1. We allow the function to take a I2CBus* as parameter. This allows us to attach an EEPROM device behind an I2C mux which is not possible with the old method. 2. We make at24c EEPROMs are backed by drives so that we can specify the content of the EEPROMs. 3. Instead of using i2c address as unit number, This patch assigns unique unit numbers for each eeproms in each board. This avoids conflict in providing multiple eeprom contents with the same address. In the old method if we specify two drives with the same unit number, the following error will occur: `Device with id 'none85' exists`. Signed-off-by: Hao Wu --- hw/arm/npcm7xx_boards.c | 14 +- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index dec7d16ae5..9121e081fa 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -126,13 +126,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) +static void at24c_eeprom_init(I2CBus *i2c_bus, int bus, uint8_t addr, + uint32_t rsize, int unit_number) { -I2CBus *i2c_bus = npcm7xx_i2c_get_bus(soc, bus); I2CSlave *i2c_dev = i2c_slave_new("at24c-eeprom", addr); DeviceState *dev = DEVICE(i2c_dev); +DriveInfo *dinfo; +dinfo = drive_get(IF_OTHER, bus, unit_number); +if (dinfo) { +qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo)); +} qdev_prop_set_uint32(dev, "rom-size", rsize); i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort); } @@ -239,8 +243,8 @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc) 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); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 9), 9, 0x55, 8192, 0); +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 10), 10, 0x55, 8192, 1); /* * i2c-11: -- 2.33.1.1089.g2158813163f-goog
[PATCH v4 3/7] hw/adc: Fix CONV bit in NPCM7XX ADC CON register
The correct bit for the CONV bit in NPCM7XX ADC is bit 13. This patch fixes that in the module, and also lower the IRQ when the guest is done handling an interrupt event from the ADC module. Signed-off-by: Hao Wu Reviewed-by: Patrick Venture Reviewed-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- tests/qtest/npcm7xx_adc-test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 0f0a9f63e2..47fb9e5f74 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -36,7 +36,7 @@ REG32(NPCM7XX_ADC_DATA, 0x4) #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_CONVBIT(13) #define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8) #define NPCM7XX_ADC_MAX_RESULT 1023 diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c index 5ce8ce13b3..aaf127dd42 100644 --- a/tests/qtest/npcm7xx_adc-test.c +++ b/tests/qtest/npcm7xx_adc-test.c @@ -50,7 +50,7 @@ #define CON_INT BIT(18) #define CON_EN BIT(17) #define CON_RST BIT(16) -#define CON_CONVBIT(14) +#define CON_CONVBIT(13) #define CON_DIV(rv) extract32(rv, 1, 8) #define FST_RDSTBIT(1) -- 2.33.1.1089.g2158813163f-goog
[PATCH v4 7/7] hw/arm: quanta-gbs-bmc add i2c devices
From: Patrick Venture Adds supported i2c devices to the quanta-gbc-bmc board. Signed-off-by: Patrick Venture Reviewed-by: Hao Wu --- hw/arm/npcm7xx_boards.c | 82 - 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 9121e081fa..7fb1b3dbc2 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -276,10 +276,12 @@ static void quanta_gsj_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc) static void quanta_gbs_i2c_init(NPCM7xxState *soc) { +I2CSlave *i2c_mux; + +/* i2c-0: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 0), TYPE_PCA9546, 0x71); + /* - * i2c-0: - * pca9546@71 - * * i2c-1: * pca9535@24 * pca9535@20 @@ -288,46 +290,60 @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) * pca9535@23 * pca9535@25 * pca9535@26 - * - * i2c-2: - * sbtsi@4c - * - * i2c-5: - * atmel,24c64@50 mb_fru - * pca9546@71 - * - channel 0: max31725@54 - * - channel 1: max31725@55 - * - channel 2: max31725@5d - * atmel,24c64@51 fan_fru - * - channel 3: atmel,24c64@52 hsbp_fru - * + */ + +/* i2c-2: sbtsi@4c */ + +/* i2c-5: */ +/* mb_fru */ +at24c_eeprom_init(npcm7xx_i2c_get_bus(soc, 5), 5, 0x50, 8192, 0); +i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 5), + TYPE_PCA9546, 0x71); +/* max31725 is tmp105 compatible. */ +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 0), "tmp105", 0x54); +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1), "tmp105", 0x55); +i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 2), "tmp105", 0x5d); +/* fan_fru */ +at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 2), 5, 0x51, 8192, 1); +/* hsbp_fru */ +at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 3), 5, 0x52, 8192, 2); + +/* * i2c-6: * pca9545@73 * * i2c-7: * pca9545@72 - * - * i2c-8: - * adi,adm1272@10 - * - * i2c-9: - * pca9546@71 - * - channel 0: isil,isl68137@60 - * - channel 1: isil,isl68137@61 - * - channel 2: isil,isl68137@63 - * - channel 3: isil,isl68137@45 - * + */ + +/* i2c-8: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 8), "adm1272", 0x10); + +/* i2c-9: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 9), TYPE_PCA9546, 0x71); +/* + * - channel 0: isil,isl68137@60 + * - channel 1: isil,isl68137@61 + * - channel 2: isil,isl68137@63 + * - channel 3: isil,isl68137@45 + */ + +/* * i2c-10: * pca9545@71 * * i2c-11: * pca9545@76 - * - * i2c-12: - * maxim,max34451@4e - * isil,isl68137@5d - * isil,isl68137@5e - * + */ + +/* i2c-12: */ +i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 12), "max34451", 0x4e); +/* + * isil,isl68137@5d + * isil,isl68137@5e + */ + +/* * i2c-14: * pca9545@70 */ -- 2.33.1.1089.g2158813163f-goog
[PATCH v4 5/7] blockdev: Add a new IF type IF_OTHER
This type is used to represent block devs that are not suitable to be represented by other existing types. Signed-of-by: Hao Wu --- blockdev.c| 3 ++- include/sysemu/blockdev.h | 1 + meson | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/blockdev.c b/blockdev.c index b35072644e..c26cbcc422 100644 --- a/blockdev.c +++ b/blockdev.c @@ -80,6 +80,7 @@ static const char *const if_name[IF_COUNT] = { [IF_MTD] = "mtd", [IF_SD] = "sd", [IF_VIRTIO] = "virtio", +[IF_OTHER] = "other", [IF_XEN] = "xen", }; @@ -739,7 +740,7 @@ QemuOptsList qemu_legacy_drive_opts = { },{ .name = "if", .type = QEMU_OPT_STRING, -.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", +.help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio, other)", },{ .name = "file", .type = QEMU_OPT_STRING, diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 32c2d6023c..bce6aab573 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -24,6 +24,7 @@ typedef enum { */ IF_NONE = 0, IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, +IF_OTHER, IF_COUNT } BlockInterfaceType; diff --git a/meson b/meson index b25d94e7c7..776acd2a80 16 --- a/meson +++ b/meson @@ -1 +1 @@ -Subproject commit b25d94e7c77fda05a7fdfe8afe562cf9760d69da +Subproject commit 776acd2a805c9b42b4f0375150977df42130317f -- 2.33.1.1089.g2158813163f-goog
[PATCH v4 4/7] hw/adc: Make adci[*] R/W in NPCM7XX ADC
Our sensor test requires both reading and writing from a sensor's QOM property. So we need to make the input of ADC module R/W instead of write only for that to work. Signed-off-by: Hao Wu Reviewed-by: Titus Rwantare Reviewed-by: Peter Maydell --- hw/adc/npcm7xx_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c index 47fb9e5f74..bc6f3f55e6 100644 --- a/hw/adc/npcm7xx_adc.c +++ b/hw/adc/npcm7xx_adc.c @@ -242,7 +242,7 @@ static void npcm7xx_adc_init(Object *obj) for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) { object_property_add_uint32_ptr(obj, "adci[*]", -&s->adci[i], OBJ_PROP_FLAG_WRITE); +&s->adci[i], OBJ_PROP_FLAG_READWRITE); } object_property_add_uint32_ptr(obj, "vref", &s->vref, OBJ_PROP_FLAG_WRITE); -- 2.33.1.1089.g2158813163f-goog
Re: [PATCH v2 03/13] hw/arm/npcm7xx_boards: Replace drive_get_next() by drive_get()
Yes, there's SD and MMC buses. It looks like the current code only supports mmc ("soc->mmc.sdhci") but not the sd ("soc->sd.sdhci"). It's probably good to make the bus number a parameter as well and use them to distinguish. We might need a separate patch to do that. On Wed, Nov 17, 2021 at 8:54 AM Havard Skinnemoen wrote: > On Wed, Nov 17, 2021 at 8:34 AM Markus Armbruster > wrote: > > > > drive_get_next() is basically a bad idea. It returns the "next" block > > backend of a certain interface type. "Next" means bus=0,unit=N, where > > subsequent calls count N up from zero, per interface type. > > > > This lets you define unit numbers implicitly by execution order. If the > > order changes, or new calls appear "in the middle", unit numbers change. > > ABI break. Hard to spot in review. > > > > Machine "quanta-gbs-bmc" connects just one backend with > > drive_get_next(), but with a helper function. Change it to use > > drive_get() directly. This makes the unit numbers explicit in the > > code. > > > > Cc: Havard Skinnemoen > > Cc: Tyrone Ting > > Cc: Peter Maydell > > Cc: qemu-...@nongnu.org > > Signed-off-by: Markus Armbruster > > --- > > hw/arm/npcm7xx_boards.c | 6 +++--- > > 1 file changed, 3 insertions(+), 3 deletions(-) > > > > diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c > > index dec7d16ae5..d8a49e4e85 100644 > > --- a/hw/arm/npcm7xx_boards.c > > +++ b/hw/arm/npcm7xx_boards.c > > @@ -84,9 +84,9 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, > MemoryRegion *dram) > > &error_abort); > > } > > > > -static void sdhci_attach_drive(SDHCIState *sdhci) > > +static void sdhci_attach_drive(SDHCIState *sdhci, int unit) > > { > > -DriveInfo *di = drive_get_next(IF_SD); > > +DriveInfo *di = drive_get(IF_SD, 0, unit); > > +Hao Wu IIRC the chip has separate SD and eMMC buses. Would it make > sense to take the bus number as a parameter as well? Is bus 0 the > right one to use in this case? > > The existing code always uses bus 0, so this is an improvement either way. > > Reviewed-by: Havard Skinnemoen > > > BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; > > > > BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus"); > > @@ -374,7 +374,7 @@ static void quanta_gbs_init(MachineState *machine) > >drive_get(IF_MTD, 0, 0)); > > > > quanta_gbs_i2c_init(soc); > > -sdhci_attach_drive(&soc->mmc.sdhci); > > +sdhci_attach_drive(&soc->mmc.sdhci, 0); > > npcm7xx_load_kernel(machine, soc); > > } > > > > -- > > 2.31.1 > > >
[PATCH v4] tests/qtest: add qtests for npcm7xx sdhci
From: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Signed-off-by: Shengtan Mao Signed-off-by: Patrick Venture Signed-off-by: Hao Wu --- v4: * use strncmp to compare fixed length strings v3: * fixup compilation from missing macro value v2: * update copyright year * check result of open * use g_free instead of free * move declarations to the top * use g_file_open_tmp --- tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 215 +++ 2 files changed, 216 insertions(+) create mode 100644 tests/qtest/npcm7xx_sdhci-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 842b1df420..2b566999cd 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -189,6 +189,7 @@ qtests_npcm7xx = \ 'npcm7xx_gpio-test', 'npcm7xx_pwm-test', 'npcm7xx_rng-test', + 'npcm7xx_sdhci-test', 'npcm7xx_smbus-test', 'npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test'] + \ diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c new file mode 100644 index 00..7de28f900b --- /dev/null +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -0,0 +1,215 @@ +/* + * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller + * + * Copyright (c) 2022 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/sd/npcm7xx_sdhci.h" + +#include "libqos/libqtest.h" +#include "libqtest-single.h" +#include "libqos/sdhci-cmd.h" + +#define NPCM7XX_REG_SIZE 0x100 +#define NPCM7XX_MMC_BA 0xF0842000 +#define NPCM7XX_BLK_SIZE 512 --- tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 215 +++ 2 files changed, 216 insertions(+) create mode 100644 tests/qtest/npcm7xx_sdhci-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index f33d84d19b..721eafad12 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -190,6 +190,7 @@ qtests_npcm7xx = \ 'npcm7xx_gpio-test', 'npcm7xx_pwm-test', 'npcm7xx_rng-test', + 'npcm7xx_sdhci-test', 'npcm7xx_smbus-test', 'npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test'] + \ diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c new file mode 100644 index 00..fbb4e2f2e1 --- /dev/null +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -0,0 +1,215 @@ +/* + * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller + * + * Copyright (c) 2022 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/sd/npcm7xx_sdhci.h" + +#include "libqos/libqtest.h" +#include "libqtest-single.h" +#include "libqos/sdhci-cmd.h" + +#define NPCM7XX_REG_SIZE 0x100 +#define NPCM7XX_MMC_BA 0xF0842000 +#define NPCM7XX_BLK_SIZE 512 +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) + +char *sd_path; + +static QTestState *setup_sd_card(void) +{ +QTestState *qts = qtest_initf( +"-machine kudo-bmc " +"-device sd-card,drive=drive0 " +"-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off", +sd_path); + +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_SWRST, SDHC_RESET_ALL); +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_CLKCON, + SDHC_CLOCK_SDCLK_EN | SDHC_CLOCK_INT_STABLE | + SDHC_CLOCK_INT_EN); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_APP_CMD); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4120, 0, (41 << 8)); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_ALL_SEND_CID); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4567, 0, + SDHC_SELECT_DESELECT_CARD); + +return qts; +} + +static void write_s
Re: [PATCH v4] tests/qtest: add qtests for npcm7xx sdhci
I have sent an updated version that uses memcmp() On Fri, Feb 25, 2022 at 3:44 AM Peter Maydell wrote: > On Thu, 24 Feb 2022 at 19:03, Hao Wu wrote: > > > > From: Shengtan Mao > > > > Reviewed-by: Hao Wu > > Reviewed-by: Chris Rauer > > Signed-off-by: Shengtan Mao > > Signed-off-by: Patrick Venture > > Signed-off-by: Hao Wu > > --- > > v4: > > * use strncmp to compare fixed length strings > > v3: > > * fixup compilation from missing macro value > > v2: > > * update copyright year > > * check result of open > > * use g_free instead of free > > * move declarations to the top > > * use g_file_open_tmp > > --- > > > +static void write_sdread(QTestState *qts, const char *msg) > > +{ > > +int fd, ret; > > +size_t len = strlen(msg); > > +char *rmsg = g_malloc(len); > > + > > +/* write message to sd */ > > +fd = open(sd_path, O_WRONLY); > > +g_assert(fd >= 0); > > +ret = write(fd, msg, len); > > +close(fd); > > +g_assert(ret == len); > > + > > +/* read message using sdhci */ > > +ret = sdhci_read_cmd(qts, NPCM7XX_MMC_BA, rmsg, len); > > +g_assert(ret == len); > > +g_assert(!strncmp(rmsg, msg, len)); > > We always know we want to compare exactly 'len' bytes here, and we know > the buffers in each case are at least that large. The right function > for that is memcmp(), I think. > > thanks > -- PMM >
[PATCH v5] tests/qtest: add qtests for npcm7xx sdhci
From: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Signed-off-by: Shengtan Mao Signed-off-by: Patrick Venture --- v5 * use memcmp to compare whether strings are expected v4 * use strncmp instead of strcmp v3: * fixup compilation from missing macro value v2: * update copyright year * check result of open * use g_free instead of free * move declarations to the top * use g_file_open_tmp --- tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 215 +++ 2 files changed, 216 insertions(+) create mode 100644 tests/qtest/npcm7xx_sdhci-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index f33d84d19b..721eafad12 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -190,6 +190,7 @@ qtests_npcm7xx = \ 'npcm7xx_gpio-test', 'npcm7xx_pwm-test', 'npcm7xx_rng-test', + 'npcm7xx_sdhci-test', 'npcm7xx_smbus-test', 'npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test'] + \ diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c new file mode 100644 index 00..c1f496fb29 --- /dev/null +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -0,0 +1,215 @@ +/* + * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller + * + * Copyright (c) 2022 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/sd/npcm7xx_sdhci.h" + +#include "libqos/libqtest.h" +#include "libqtest-single.h" +#include "libqos/sdhci-cmd.h" + +#define NPCM7XX_REG_SIZE 0x100 +#define NPCM7XX_MMC_BA 0xF0842000 +#define NPCM7XX_BLK_SIZE 512 +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) + +char *sd_path; + +static QTestState *setup_sd_card(void) +{ +QTestState *qts = qtest_initf( +"-machine kudo-bmc " +"-device sd-card,drive=drive0 " +"-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off", +sd_path); + +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_SWRST, SDHC_RESET_ALL); +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_CLKCON, + SDHC_CLOCK_SDCLK_EN | SDHC_CLOCK_INT_STABLE | + SDHC_CLOCK_INT_EN); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_APP_CMD); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4120, 0, (41 << 8)); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_ALL_SEND_CID); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4567, 0, + SDHC_SELECT_DESELECT_CARD); + +return qts; +} + +static void write_sdread(QTestState *qts, const char *msg) +{ +int fd, ret; +size_t len = strlen(msg); +char *rmsg = g_malloc(len); + +/* write message to sd */ +fd = open(sd_path, O_WRONLY); +g_assert(fd >= 0); +ret = write(fd, msg, len); +close(fd); +g_assert(ret == len); + +/* read message using sdhci */ +ret = sdhci_read_cmd(qts, NPCM7XX_MMC_BA, rmsg, len); +g_assert(ret == len); +g_assert(!memcmp(rmsg, msg, len)); + +g_free(rmsg); +} + +/* Check MMC can read values from sd */ +static void test_read_sd(void) +{ +QTestState *qts = setup_sd_card(); + +write_sdread(qts, "hello world"); +write_sdread(qts, "goodbye"); + +qtest_quit(qts); +} + +static void sdwrite_read(QTestState *qts, const char *msg) +{ +int fd, ret; +size_t len = strlen(msg); +char *rmsg = g_malloc(len); + +/* write message using sdhci */ +sdhci_write_cmd(qts, NPCM7XX_MMC_BA, msg, len, NPCM7XX_BLK_SIZE); + +/* read message from sd */ +fd = open(sd_path, O_RDONLY); +g_assert(fd >= 0); +ret = read(fd, rmsg, len); +close(fd); +g_assert(ret == len); + +g_assert(!memcmp(rmsg, msg, len)); + +g_free(rmsg); +} + +/* Check MMC can write values to sd */ +static void test_write_sd(void) +{ +QTestState *qts = setup_sd_card(); + +sdwrite_read(qts, "hello world"); +sdwrite_read(qts, "goodbye"); + +qtest_quit(qts); +} + +/* Check SDHCI has correct default values. */ +static void test_reset(void) +{ +QTestState *qts = qtest_init("-machine kudo-bmc"); +uint64_t addr = NPCM7XX_MMC_BA; +uint64_t end_addr = addr + NPCM7XX_REG_SIZE; +uint16_t prstvals_resets[] = {NPCM
[PATCH 0/4] hw/arm: Add MMC device for NPCM7XX boards
This patch set implements the Nuvoton MMC device for NPCM7XX boards. The MMC device is compatible with the SDHCI interface in QEMU. It allows the user to attach an SD card image to it. Shengtan Mao (4): tests/qtest/libqos: add SDHCI commands hw/sd: add nuvoton MMC hw/arm: Attach MMC to quanta-gbs-bmc tests/qtest: add qtests for npcm7xx sdhci hw/arm/npcm7xx.c | 12 +- hw/arm/npcm7xx_boards.c | 21 hw/sd/meson.build| 1 + hw/sd/npcm7xx_sdhci.c| 131 include/hw/arm/npcm7xx.h | 2 + include/hw/sd/npcm7xx_sdhci.h| 65 ++ tests/qtest/libqos/meson.build | 1 + tests/qtest/libqos/sdhci-cmd.c | 116 ++ tests/qtest/libqos/sdhci-cmd.h | 70 +++ tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 201 +++ 11 files changed, 620 insertions(+), 1 deletion(-) create mode 100644 hw/sd/npcm7xx_sdhci.c create mode 100644 include/hw/sd/npcm7xx_sdhci.h create mode 100644 tests/qtest/libqos/sdhci-cmd.c create mode 100644 tests/qtest/libqos/sdhci-cmd.h create mode 100644 tests/qtest/npcm7xx_sdhci-test.c -- 2.33.0.153.gba50c8fa24-goog
[PATCH 1/4] tests/qtest/libqos: add SDHCI commands
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting --- tests/qtest/libqos/meson.build | 1 + tests/qtest/libqos/sdhci-cmd.c | 116 + tests/qtest/libqos/sdhci-cmd.h | 70 3 files changed, 187 insertions(+) create mode 100644 tests/qtest/libqos/sdhci-cmd.c create mode 100644 tests/qtest/libqos/sdhci-cmd.h diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build index 1f5c8f1053..4af1f04787 100644 --- a/tests/qtest/libqos/meson.build +++ b/tests/qtest/libqos/meson.build @@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c', 'fw_cfg.c', 'malloc.c', 'libqos.c', +'sdhci-cmd.c', # spapr 'malloc-spapr.c', diff --git a/tests/qtest/libqos/sdhci-cmd.c b/tests/qtest/libqos/sdhci-cmd.c new file mode 100644 index 00..2d9e518341 --- /dev/null +++ b/tests/qtest/libqos/sdhci-cmd.c @@ -0,0 +1,116 @@ +/* + * MMC Host Controller Commands + * + * Copyright (c) 2021 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 "sdhci-cmd.h" +#include "libqtest.h" + +static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count) +{ +uint32_t mask = 0xff; +size_t index = 0; +uint32_t msg_frag; +int size; +while (index < count) { +size = count - index; +if (size > 4) { +size = 4; +} +msg_frag = qtest_readl(qts, reg); +while (size > 0) { +msg[index] = msg_frag & mask; +if (msg[index++] == 0) { +return index; +} +msg_frag >>= 8; +--size; +} +} +return index; +} + +static void write_fifo(QTestState *qts, uint64_t reg, const char *msg, + size_t count) +{ +size_t index = 0; +uint32_t msg_frag; +int size; +int frag_i; +while (index < count) { +size = count - index; +if (size > 4) { +size = 4; +} +msg_frag = 0; +frag_i = 0; +while (frag_i < size) { +msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8); +++frag_i; +} +qtest_writel(qts, reg, msg_frag); +} +} + +static void fill_block(QTestState *qts, uint64_t reg, int count) +{ +while (--count >= 0) { +qtest_writel(qts, reg, 0); +} +} + +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize, +uint16_t blkcnt, uint32_t argument, uint16_t trnmod, +uint16_t cmdreg) +{ +qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize); +qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt); +qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument); +qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod); +qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg); +} + +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg, + size_t count) +{ +sdhci_cmd_regs(qts, base_addr, count, 1, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN, + SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); + +/* read sd fifo_buffer */ +ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count); + +sdhci_cmd_regs(qts, base_addr, 0, 0, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN, + SDHC_STOP_TRANSMISSION); + +return bytes_read; +} + +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg, + size_t count, size_t blksize) +{ +sdhci_cmd_regs(qts, base_addr, blksize, 1, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN, + SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); + +/* write to sd fifo_buffer */ +write_fifo(qts, base_addr + SDHC_BDATA, msg, count); +fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4); + +sdhci_cmd_regs(qts, base_addr, 0, 0, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN, + SDHC_STOP_TRANSMISSION); +} diff --git a/tests/qtest/libqos/sdhci-cmd.h b/tests/qtest/libqos/sdhci-cmd.h new file mode 100644 index 00..64763c5a2a --- /dev/null +
[PATCH 3/4] hw/arm: Attach MMC to quanta-gbs-bmc
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Tyrone Ting --- hw/arm/npcm7xx_boards.c | 21 + 1 file changed, 21 insertions(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index e5a3243995..7205483280 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -27,6 +27,10 @@ #include "qemu-common.h" #include "qemu/datadir.h" #include "qemu/units.h" +#include "sysemu/blockdev.h" +#include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" + #define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7 #define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff @@ -80,6 +84,22 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram) &error_abort); } +static void sdhci_attach_drive(SDHCIState *sdhci) +{ +DriveInfo *di = drive_get_next(IF_SD); +BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; + +BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus"); +if (bus == NULL) { +error_report("No SD bus found in SOC object"); +exit(1); +} + +DeviceState *carddev = qdev_new(TYPE_SD_CARD); +qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); +qdev_realize_and_unref(carddev, bus, &error_fatal); +} + static NPCM7xxState *npcm7xx_create_soc(MachineState *machine, uint32_t hw_straps) { @@ -354,6 +374,7 @@ static void quanta_gbs_init(MachineState *machine) drive_get(IF_MTD, 0, 0)); quanta_gbs_i2c_init(soc); +sdhci_attach_drive(&soc->mmc.sdhci); npcm7xx_load_kernel(machine, soc); } -- 2.33.0.153.gba50c8fa24-goog
[PATCH 2/4] hw/sd: add nuvoton MMC
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting --- hw/arm/npcm7xx.c | 12 +++- hw/sd/meson.build | 1 + hw/sd/npcm7xx_sdhci.c | 131 ++ include/hw/arm/npcm7xx.h | 2 + include/hw/sd/npcm7xx_sdhci.h | 65 + 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 hw/sd/npcm7xx_sdhci.c create mode 100644 include/hw/sd/npcm7xx_sdhci.h diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index 2ab0080e0b..878c2208e0 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -63,6 +63,8 @@ #define NPCM7XX_ROM_BA (0x) #define NPCM7XX_ROM_SZ (64 * KiB) +/* SDHCI Modules */ +#define NPCM7XX_MMC_BA (0xf0842000) /* Clock configuration values to be fixed up when bypassing bootloader */ @@ -83,6 +85,7 @@ enum NPCM7xxInterrupt { NPCM7XX_UART3_IRQ, NPCM7XX_EMC1RX_IRQ = 15, NPCM7XX_EMC1TX_IRQ, +NPCM7XX_MMC_IRQ = 26, NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */ NPCM7XX_TIMER1_IRQ, NPCM7XX_TIMER2_IRQ, @@ -443,6 +446,8 @@ static void npcm7xx_init(Object *obj) for (i = 0; i < ARRAY_SIZE(s->emc); i++) { object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC); } + +object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI); } static void npcm7xx_realize(DeviceState *dev, Error **errp) @@ -707,6 +712,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) &error_abort); memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom); +/* SDHCI */ +sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort); +sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM7XX_MMC_BA); +sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0, +npcm7xx_irq(s, NPCM7XX_MMC_IRQ)); + create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB); create_unimplemented_device("npcm7xx.vdmx", 0xe080, 4 * KiB); create_unimplemented_device("npcm7xx.pcierc", 0xe100, 64 * KiB); @@ -736,7 +747,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB); create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB); create_unimplemented_device("npcm7xx.sd", 0xf084, 8 * KiB); -create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB); create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB); create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB); create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB); diff --git a/hw/sd/meson.build b/hw/sd/meson.build index f1ce357a3b..807ca07b7c 100644 --- a/hw/sd/meson.build +++ b/hw/sd/meson.build @@ -9,4 +9,5 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_mmci.c')) softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c')) softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c')) softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c')) +softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c')) softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c')) diff --git a/hw/sd/npcm7xx_sdhci.c b/hw/sd/npcm7xx_sdhci.c new file mode 100644 index 00..85cccdc485 --- /dev/null +++ b/hw/sd/npcm7xx_sdhci.c @@ -0,0 +1,131 @@ +/* + * NPCM7xx SD-3.0 / eMMC-4.51 Host Controller + * + * Copyright (c) 2021 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/sd/npcm7xx_sdhci.h" +#include "sdhci-internal.h" + +static uint64_t npcm7xx_sdhci_read(void *opaque, hwaddr addr, unsigned int size) +{ +NPCM7xxSDHCIState *s = opaque; +uint64_t val = 0; + +switch (addr) { +case NPCM7XX_PRSTVALS_0: +case NPCM7XX_PRSTVALS_1: +case NPCM7XX_PRSTVALS_2: +case NPCM7XX_PRSTVALS_3: +case NPCM7XX_PRSTVALS_4: +case
[PATCH 4/4] tests/qtest: add qtests for npcm7xx sdhci
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting --- tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 201 +++ 2 files changed, 202 insertions(+) create mode 100644 tests/qtest/npcm7xx_sdhci-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 757bb8499a..ef9c904779 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -157,6 +157,7 @@ qtests_npcm7xx = \ 'npcm7xx_gpio-test', 'npcm7xx_pwm-test', 'npcm7xx_rng-test', + 'npcm7xx_sdhci-test', 'npcm7xx_smbus-test', 'npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test'] + \ diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c new file mode 100644 index 00..5c4e78fda4 --- /dev/null +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -0,0 +1,201 @@ +/* + * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller + * + * Copyright (c) 2021 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/sd/npcm7xx_sdhci.h" + +#include "libqos/libqtest.h" +#include "libqtest-single.h" +#include "libqos/sdhci-cmd.h" + +#define NPCM7XX_MMC_BA 0xF0842000 +#define NPCM7XX_BLK_SIZE 512 +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) + +char *sd_path; + +static QTestState *setup_sd_card(void) +{ +QTestState *qts = qtest_initf( +"-machine quanta-gbs-bmc " +"-device sd-card,drive=drive0 " +"-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off", +sd_path); + +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_SWRST, SDHC_RESET_ALL); +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_CLKCON, + SDHC_CLOCK_SDCLK_EN | SDHC_CLOCK_INT_STABLE | + SDHC_CLOCK_INT_EN); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_APP_CMD); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4120, 0, (41 << 8)); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_ALL_SEND_CID); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4567, 0, + SDHC_SELECT_DESELECT_CARD); + +return qts; +} + +static void write_sdread(QTestState *qts, const char *msg) +{ +size_t len = strlen(msg); +char *rmsg = g_malloc(len); + +/* write message to sd */ +int fd = open(sd_path, O_WRONLY); +int ret = write(fd, msg, len); +close(fd); +g_assert(ret == len); + +/* read message using sdhci */ +ret = sdhci_read_cmd(qts, NPCM7XX_MMC_BA, rmsg, len); +g_assert(ret == len); +g_assert(!strcmp(rmsg, msg)); + +free(rmsg); +} + +/* Check MMC can read values from sd */ +static void test_read_sd(void) +{ +QTestState *qts = setup_sd_card(); + +write_sdread(qts, "hello world"); +write_sdread(qts, "goodbye"); + +qtest_quit(qts); +} + +static void sdwrite_read(QTestState *qts, const char *msg) +{ +size_t len = strlen(msg); +char *rmsg = g_malloc(len); + +/* write message using sdhci */ +sdhci_write_cmd(qts, NPCM7XX_MMC_BA, msg, len, NPCM7XX_BLK_SIZE); + +/* read message from sd */ +int fd = open(sd_path, O_RDONLY); +int ret = read(fd, rmsg, len); +close(fd); +g_assert(ret == len); + +g_assert(!strcmp(rmsg, msg)); + +free(rmsg); +} + +/* Check MMC can write values to sd */ +static void test_write_sd(void) +{ +QTestState *qts = setup_sd_card(); + +sdwrite_read(qts, "hello world"); +sdwrite_read(qts, "goodbye"); + +qtest_quit(qts); +} + +/* Check SDHCI has correct default values. */ +static void test_reset(void) +{ +QTestState *qts = qtest_init("-machine quanta-gbs-bmc"); + +uint64_t addr = NPCM7XX_MMC_BA; +uint64_t end_addr = addr + NPCM7XX_REG_SIZE; +uint16_t prstvals_resets[] = {NPCM7XX_PRSTVALS_0_RESET, + NPCM7XX_PRSTVALS_1_RESET, + 0, + NPCM7XX_PRSTVALS_3_RESET, + 0, + 0}; +int i; +uint32_t mask; +while (addr < end_addr) { +switch (addr - NPCM7XX_MMC_BA) { +case SDHC_PRNSTS: +/* ignores bits 20 to 24:
[PATCH v2 0/5] hw/arm: Add MMC device for NPCM7XX boards
This patch set implements the Nuvoton MMC device for NPCM7XX boards. The MMC device is compatible with the SDHCI interface in QEMU. It allows the user to attach an SD card image to it. Changes since v1: 1. Rearrange the "add SDHCI commands" to just before when it's actually used. 2. Add standrad SDHCI MMIO as subregion, similar to cadence_sdhci. e. Add a vmstate for NPCM7XX SDHCI. 4. Address various minor fixes suggested by Peter Maydell. Shengtan Mao (5): hw/sd: add nuvoton MMC hw/arm: Add Nuvoton SD module to board hw/arm: Attach MMC to quanta-gbs-bmc tests/qtest/libqos: add SDHCI commands tests/qtest: add qtests for npcm7xx sdhci hw/arm/npcm7xx.c | 12 +- hw/arm/npcm7xx_boards.c | 20 +++ hw/sd/meson.build| 1 + hw/sd/npcm7xx_sdhci.c| 182 +++ include/hw/arm/npcm7xx.h | 2 + include/hw/sd/npcm7xx_sdhci.h| 65 ++ tests/qtest/libqos/meson.build | 1 + tests/qtest/libqos/sdhci-cmd.c | 116 + tests/qtest/libqos/sdhci-cmd.h | 70 +++ tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 209 +++ 11 files changed, 678 insertions(+), 1 deletion(-) create mode 100644 hw/sd/npcm7xx_sdhci.c create mode 100644 include/hw/sd/npcm7xx_sdhci.h create mode 100644 tests/qtest/libqos/sdhci-cmd.c create mode 100644 tests/qtest/libqos/sdhci-cmd.h create mode 100644 tests/qtest/npcm7xx_sdhci-test.c -- 2.33.0.882.g93a45727a2-goog
[PATCH v2 1/5] hw/sd: add nuvoton MMC
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu --- hw/sd/meson.build | 1 + hw/sd/npcm7xx_sdhci.c | 182 ++ include/hw/sd/npcm7xx_sdhci.h | 65 3 files changed, 248 insertions(+) create mode 100644 hw/sd/npcm7xx_sdhci.c create mode 100644 include/hw/sd/npcm7xx_sdhci.h diff --git a/hw/sd/meson.build b/hw/sd/meson.build index f1ce357a3b..807ca07b7c 100644 --- a/hw/sd/meson.build +++ b/hw/sd/meson.build @@ -9,4 +9,5 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_mmci.c')) softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c')) softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c')) softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c')) +softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c')) softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c')) diff --git a/hw/sd/npcm7xx_sdhci.c b/hw/sd/npcm7xx_sdhci.c new file mode 100644 index 00..1148afe060 --- /dev/null +++ b/hw/sd/npcm7xx_sdhci.c @@ -0,0 +1,182 @@ +/* + * NPCM7xx SD-3.0 / eMMC-4.51 Host Controller + * + * Copyright (c) 2021 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/sd/npcm7xx_sdhci.h" +#include "migration/vmstate.h" +#include "sdhci-internal.h" +#include "qemu/log.h" + +static uint64_t npcm7xx_sdhci_read(void *opaque, hwaddr addr, unsigned int size) +{ +NPCM7xxSDHCIState *s = opaque; +uint64_t val = 0; + +switch (addr) { +case NPCM7XX_PRSTVALS_0: +case NPCM7XX_PRSTVALS_1: +case NPCM7XX_PRSTVALS_2: +case NPCM7XX_PRSTVALS_3: +case NPCM7XX_PRSTVALS_4: +case NPCM7XX_PRSTVALS_5: +val = s->regs.prstvals[(addr - NPCM7XX_PRSTVALS_0) / 2]; +break; +case NPCM7XX_BOOTTOCTRL: +val = s->regs.boottoctrl; +break; +default: +qemu_log_mask(LOG_GUEST_ERROR, "SDHCI read of nonexist reg: 0x%02" + HWADDR_PRIx, addr); +break; +} + +return val; +} + +static void npcm7xx_sdhci_write(void *opaque, hwaddr addr, uint64_t val, +unsigned int size) +{ +NPCM7xxSDHCIState *s = opaque; + +switch (addr) { +case NPCM7XX_BOOTTOCTRL: +s->regs.boottoctrl = val; +break; +default: +qemu_log_mask(LOG_GUEST_ERROR, "SDHCI write of nonexist reg: 0x%02" + HWADDR_PRIx, addr); +break; +} +} + +static bool npcm7xx_sdhci_check_mem_op(void *opaque, hwaddr addr, + unsigned size, bool is_write, + MemTxAttrs attrs) +{ +switch (addr) { +case NPCM7XX_PRSTVALS_0: +case NPCM7XX_PRSTVALS_1: +case NPCM7XX_PRSTVALS_2: +case NPCM7XX_PRSTVALS_3: +case NPCM7XX_PRSTVALS_4: +case NPCM7XX_PRSTVALS_5: +/* RO Word */ +return !is_write && size == 2; +case NPCM7XX_BOOTTOCTRL: +/* R/W Dword */ +return size == 4; +default: +return false; +} +} + +static const MemoryRegionOps npcm7xx_sdhci_ops = { +.read = npcm7xx_sdhci_read, +.write = npcm7xx_sdhci_write, +.endianness = DEVICE_NATIVE_ENDIAN, +.valid = { +.min_access_size = 1, +.max_access_size = 4, +.unaligned = false, +.accepts = npcm7xx_sdhci_check_mem_op, +}, +}; + +static void npcm7xx_sdhci_realize(DeviceState *dev, Error **errp) +{ +NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(dev); +SysBusDevice *sbd = SYS_BUS_DEVICE(dev); +SysBusDevice *sbd_sdhci = SYS_BUS_DEVICE(&s->sdhci); + +memory_region_init(&s->container, OBJECT(s), + "npcm7xx.sdhci-container", 0x1000); +sysbus_init_mmio(sbd, &s->container); + +memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_sdhci_ops, s, + TYPE_NPCM7XX_SDHCI, NPCM7XX_SDHCI_REGSIZE); +memory_region_add_subregion_overlap(&s->container, NPCM7XX_PRSTVALS, +&s->iomem, 1); + +sysbus_realize(sbd_sdhci, errp); +memory_regi
[PATCH v2 2/5] hw/arm: Add Nuvoton SD module to board
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu --- hw/arm/npcm7xx.c | 12 +++- include/hw/arm/npcm7xx.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index 2ab0080e0b..878c2208e0 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -63,6 +63,8 @@ #define NPCM7XX_ROM_BA (0x) #define NPCM7XX_ROM_SZ (64 * KiB) +/* SDHCI Modules */ +#define NPCM7XX_MMC_BA (0xf0842000) /* Clock configuration values to be fixed up when bypassing bootloader */ @@ -83,6 +85,7 @@ enum NPCM7xxInterrupt { NPCM7XX_UART3_IRQ, NPCM7XX_EMC1RX_IRQ = 15, NPCM7XX_EMC1TX_IRQ, +NPCM7XX_MMC_IRQ = 26, NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */ NPCM7XX_TIMER1_IRQ, NPCM7XX_TIMER2_IRQ, @@ -443,6 +446,8 @@ static void npcm7xx_init(Object *obj) for (i = 0; i < ARRAY_SIZE(s->emc); i++) { object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC); } + +object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI); } static void npcm7xx_realize(DeviceState *dev, Error **errp) @@ -707,6 +712,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) &error_abort); memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom); +/* SDHCI */ +sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort); +sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM7XX_MMC_BA); +sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0, +npcm7xx_irq(s, NPCM7XX_MMC_IRQ)); + create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB); create_unimplemented_device("npcm7xx.vdmx", 0xe080, 4 * KiB); create_unimplemented_device("npcm7xx.pcierc", 0xe100, 64 * KiB); @@ -736,7 +747,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB); create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB); create_unimplemented_device("npcm7xx.sd", 0xf084, 8 * KiB); -create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB); create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB); create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB); create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB); diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h index 61ecc57ab9..ce593235d9 100644 --- a/include/hw/arm/npcm7xx.h +++ b/include/hw/arm/npcm7xx.h @@ -35,6 +35,7 @@ #include "hw/usb/hcd-ehci.h" #include "hw/usb/hcd-ohci.h" #include "target/arm/cpu.h" +#include "hw/sd/npcm7xx_sdhci.h" #define NPCM7XX_MAX_NUM_CPUS(2) @@ -103,6 +104,7 @@ typedef struct NPCM7xxState { OHCISysBusState ohci; NPCM7xxFIUState fiu[2]; NPCM7xxEMCState emc[2]; +NPCM7xxSDHCIState mmc; } NPCM7xxState; #define TYPE_NPCM7XX"npcm7xx" -- 2.33.0.882.g93a45727a2-goog
[PATCH v2 4/5] tests/qtest/libqos: add SDHCI commands
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu --- tests/qtest/libqos/meson.build | 1 + tests/qtest/libqos/sdhci-cmd.c | 116 + tests/qtest/libqos/sdhci-cmd.h | 70 3 files changed, 187 insertions(+) create mode 100644 tests/qtest/libqos/sdhci-cmd.c create mode 100644 tests/qtest/libqos/sdhci-cmd.h diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build index 1f5c8f1053..4af1f04787 100644 --- a/tests/qtest/libqos/meson.build +++ b/tests/qtest/libqos/meson.build @@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c', 'fw_cfg.c', 'malloc.c', 'libqos.c', +'sdhci-cmd.c', # spapr 'malloc-spapr.c', diff --git a/tests/qtest/libqos/sdhci-cmd.c b/tests/qtest/libqos/sdhci-cmd.c new file mode 100644 index 00..2d9e518341 --- /dev/null +++ b/tests/qtest/libqos/sdhci-cmd.c @@ -0,0 +1,116 @@ +/* + * MMC Host Controller Commands + * + * Copyright (c) 2021 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 "sdhci-cmd.h" +#include "libqtest.h" + +static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count) +{ +uint32_t mask = 0xff; +size_t index = 0; +uint32_t msg_frag; +int size; +while (index < count) { +size = count - index; +if (size > 4) { +size = 4; +} +msg_frag = qtest_readl(qts, reg); +while (size > 0) { +msg[index] = msg_frag & mask; +if (msg[index++] == 0) { +return index; +} +msg_frag >>= 8; +--size; +} +} +return index; +} + +static void write_fifo(QTestState *qts, uint64_t reg, const char *msg, + size_t count) +{ +size_t index = 0; +uint32_t msg_frag; +int size; +int frag_i; +while (index < count) { +size = count - index; +if (size > 4) { +size = 4; +} +msg_frag = 0; +frag_i = 0; +while (frag_i < size) { +msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8); +++frag_i; +} +qtest_writel(qts, reg, msg_frag); +} +} + +static void fill_block(QTestState *qts, uint64_t reg, int count) +{ +while (--count >= 0) { +qtest_writel(qts, reg, 0); +} +} + +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize, +uint16_t blkcnt, uint32_t argument, uint16_t trnmod, +uint16_t cmdreg) +{ +qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize); +qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt); +qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument); +qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod); +qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg); +} + +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg, + size_t count) +{ +sdhci_cmd_regs(qts, base_addr, count, 1, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN, + SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); + +/* read sd fifo_buffer */ +ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count); + +sdhci_cmd_regs(qts, base_addr, 0, 0, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN, + SDHC_STOP_TRANSMISSION); + +return bytes_read; +} + +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg, + size_t count, size_t blksize) +{ +sdhci_cmd_regs(qts, base_addr, blksize, 1, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN, + SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); + +/* write to sd fifo_buffer */ +write_fifo(qts, base_addr + SDHC_BDATA, msg, count); +fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4); + +sdhci_cmd_regs(qts, base_addr, 0, 0, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN, + SDHC_STOP_TRANSMISSION); +} diff --git a/tests/qtest/libqos/sdhci-cmd.h b/tests/qtest/libqos/sdhci-cmd.h new file mode 100644 index 00..64763c
[PATCH v2 3/5] hw/arm: Attach MMC to quanta-gbs-bmc
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu Reviewed-by: Peter Maydell --- hw/arm/npcm7xx_boards.c | 20 1 file changed, 20 insertions(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index a656169f61..dec7d16ae5 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -27,6 +27,9 @@ #include "qemu-common.h" #include "qemu/datadir.h" #include "qemu/units.h" +#include "sysemu/blockdev.h" +#include "sysemu/sysemu.h" +#include "sysemu/block-backend.h" #define NPCM750_EVB_POWER_ON_STRAPS 0x1ff7 #define QUANTA_GSJ_POWER_ON_STRAPS 0x1fff @@ -81,6 +84,22 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram) &error_abort); } +static void sdhci_attach_drive(SDHCIState *sdhci) +{ +DriveInfo *di = drive_get_next(IF_SD); +BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; + +BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus"); +if (bus == NULL) { +error_report("No SD bus found in SOC object"); +exit(1); +} + +DeviceState *carddev = qdev_new(TYPE_SD_CARD); +qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal); +qdev_realize_and_unref(carddev, bus, &error_fatal); +} + static NPCM7xxState *npcm7xx_create_soc(MachineState *machine, uint32_t hw_straps) { @@ -355,6 +374,7 @@ static void quanta_gbs_init(MachineState *machine) drive_get(IF_MTD, 0, 0)); quanta_gbs_i2c_init(soc); +sdhci_attach_drive(&soc->mmc.sdhci); npcm7xx_load_kernel(machine, soc); } -- 2.33.0.882.g93a45727a2-goog
[PATCH v2 5/5] tests/qtest: add qtests for npcm7xx sdhci
From: Shengtan Mao Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Reviewed-by: Tyrone Ting Signed-off-by: Hao Wu --- tests/qtest/meson.build | 1 + tests/qtest/npcm7xx_sdhci-test.c | 209 +++ 2 files changed, 210 insertions(+) create mode 100644 tests/qtest/npcm7xx_sdhci-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 19444d4752..989da9ceb4 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -157,6 +157,7 @@ qtests_npcm7xx = \ 'npcm7xx_gpio-test', 'npcm7xx_pwm-test', 'npcm7xx_rng-test', + 'npcm7xx_sdhci-test', 'npcm7xx_smbus-test', 'npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test'] + \ diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c new file mode 100644 index 00..a6732f657d --- /dev/null +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -0,0 +1,209 @@ +/* + * QTests for NPCM7xx SD-3.0 / MMC-4.51 Host Controller + * + * Copyright (c) 2021 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/sd/npcm7xx_sdhci.h" + +#include "libqos/libqtest.h" +#include "libqtest-single.h" +#include "libqos/sdhci-cmd.h" + +#define NPCM7XX_MMC_BA 0xF0842000 +#define NPCM7XX_BLK_SIZE 512 +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) + +static char *sd_path; + +static QTestState *setup_sd_card(void) +{ +QTestState *qts = qtest_initf( +"-machine quanta-gbs-bmc " +"-device sd-card,drive=drive0 " +"-drive id=drive0,if=none,file=%s,format=raw,auto-read-only=off", +sd_path); + +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_SWRST, SDHC_RESET_ALL); +qtest_writew(qts, NPCM7XX_MMC_BA + SDHC_CLKCON, + SDHC_CLOCK_SDCLK_EN | SDHC_CLOCK_INT_STABLE | + SDHC_CLOCK_INT_EN); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_APP_CMD); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4120, 0, (41 << 8)); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_ALL_SEND_CID); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0, 0, SDHC_SEND_RELATIVE_ADDR); +sdhci_cmd_regs(qts, NPCM7XX_MMC_BA, 0, 0, 0x4567, 0, + SDHC_SELECT_DESELECT_CARD); + +return qts; +} + +static void write_sdread(QTestState *qts, const char *msg) +{ +size_t len = strlen(msg); +char *rmsg = g_malloc(len); + +/* write message to sd */ +int fd = open(sd_path, O_WRONLY); +int ret; + +g_assert(fd > 0); +ret = write(fd, msg, len); +g_assert(ret == len); +ret = close(fd); +g_assert(ret == 0); + +/* read message using sdhci */ +ret = sdhci_read_cmd(qts, NPCM7XX_MMC_BA, rmsg, len); +g_assert(ret == len); +g_assert(!strcmp(rmsg, msg)); + +free(rmsg); +} + +/* Check MMC can read values from sd */ +static void test_read_sd(void) +{ +QTestState *qts = setup_sd_card(); + +write_sdread(qts, "hello world"); +write_sdread(qts, "goodbye"); + +qtest_quit(qts); +} + +static void sdwrite_read(QTestState *qts, const char *msg) +{ +size_t len = strlen(msg); +char *rmsg = g_malloc(len); + +/* write message using sdhci */ +sdhci_write_cmd(qts, NPCM7XX_MMC_BA, msg, len, NPCM7XX_BLK_SIZE); + +/* read message from sd */ +int fd = open(sd_path, O_RDONLY); +int ret; + +g_assert(fd > 0); +ret = read(fd, rmsg, len); +g_assert(ret == len); +ret = close(fd); +g_assert(ret == 0); + +g_assert(!strcmp(rmsg, msg)); + +free(rmsg); +} + +/* Check MMC can write values to sd */ +static void test_write_sd(void) +{ +QTestState *qts = setup_sd_card(); + +sdwrite_read(qts, "hello world"); +sdwrite_read(qts, "goodbye"); + +qtest_quit(qts); +} + +/* Check SDHCI has correct default values. */ +static void test_reset(void) +{ +QTestState *qts = qtest_init("-machine quanta-gbs-bmc"); + +uint64_t addr = NPCM7XX_MMC_BA; +uint64_t end_addr = addr + 0x100; +uint16_t prstvals_resets[] = {NPCM7XX_PRSTVALS_0_RESET, + NPCM7XX_PRSTVALS_1_RESET, + 0, + NPCM7XX_PRSTVALS_3_RESET, + 0, + 0}; +int i; +
[PATCH] tests/qtest: Reduce npcm7xx_sdhci test image size
Creating 1GB image for a simple qtest is unnecessary and could lead to failures. We reduce the image size to 1MB to reduce the test overhead. Signed-off-by: Hao Wu --- tests/qtest/npcm7xx_sdhci-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/npcm7xx_sdhci-test.c b/tests/qtest/npcm7xx_sdhci-test.c index aa35a77e8d..5d68540e52 100644 --- a/tests/qtest/npcm7xx_sdhci-test.c +++ b/tests/qtest/npcm7xx_sdhci-test.c @@ -24,7 +24,7 @@ #define NPCM7XX_REG_SIZE 0x100 #define NPCM7XX_MMC_BA 0xF0842000 #define NPCM7XX_BLK_SIZE 512 -#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30) +#define NPCM7XX_TEST_IMAGE_SIZE (1 << 20) char *sd_path; -- 2.36.1.476.g0c4daa206d-goog