From 791cb95f23045f2d69364786edf61d289889199d Mon Sep 17 00:00:00 2001 From: Klaus Jensen Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: hw/i2c: only schedule pending master when bus is idle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is not given that the current master will release the bus after a transfer ends. Only schedule a pending master if the bus is idle. Fixes: 37fa5ca42623 ("hw/i2c: support multiple masters") Signed-off-by: Klaus Jensen Acked-by: Corey Minyard Message-Id: <20221116084312.35808-2-its@irrelevant.dk> Signed-off-by: Cédric Le Goater --- hw/i2c/aspeed_i2c.c | 2 ++ hw/i2c/core.c | 37 ++++++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 15 deletions(-) (limited to 'hw') diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index c166fd2..1f071a3 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -550,6 +550,8 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value) } SHARED_ARRAY_FIELD_DP32(bus->regs, reg_cmd, M_STOP_CMD, 0); aspeed_i2c_set_state(bus, I2CD_IDLE); + + i2c_schedule_pending_master(bus->bus); } if (aspeed_i2c_bus_pkt_mode_en(bus)) { diff --git a/hw/i2c/core.c b/hw/i2c/core.c index d4ba814..bed594f 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -185,22 +185,39 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, bool is_recv) void i2c_bus_master(I2CBus *bus, QEMUBH *bh) { - if (i2c_bus_busy(bus)) { - I2CPendingMaster *node = g_new(struct I2CPendingMaster, 1); - node->bh = bh; + I2CPendingMaster *node = g_new(struct I2CPendingMaster, 1); + node->bh = bh; + + QSIMPLEQ_INSERT_TAIL(&bus->pending_masters, node, entry); +} + +void i2c_schedule_pending_master(I2CBus *bus) +{ + I2CPendingMaster *node; - QSIMPLEQ_INSERT_TAIL(&bus->pending_masters, node, entry); + if (i2c_bus_busy(bus)) { + /* someone is already controlling the bus; wait for it to release it */ + return; + } + if (QSIMPLEQ_EMPTY(&bus->pending_masters)) { return; } - bus->bh = bh; + node = QSIMPLEQ_FIRST(&bus->pending_masters); + bus->bh = node->bh; + + QSIMPLEQ_REMOVE_HEAD(&bus->pending_masters, entry); + g_free(node); + qemu_bh_schedule(bus->bh); } void i2c_bus_release(I2CBus *bus) { bus->bh = NULL; + + i2c_schedule_pending_master(bus); } int i2c_start_recv(I2CBus *bus, uint8_t address) @@ -234,16 +251,6 @@ void i2c_end_transfer(I2CBus *bus) g_free(node); } bus->broadcast = false; - - if (!QSIMPLEQ_EMPTY(&bus->pending_masters)) { - I2CPendingMaster *node = QSIMPLEQ_FIRST(&bus->pending_masters); - bus->bh = node->bh; - - QSIMPLEQ_REMOVE_HEAD(&bus->pending_masters, entry); - g_free(node); - - qemu_bh_schedule(bus->bh); - } } int i2c_send(I2CBus *bus, uint8_t data) -- cgit v1.1 From b14037f37f913a21eddadb1e4b53a2f7adf720ad Mon Sep 17 00:00:00 2001 From: Klaus Jensen Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: hw/misc: add a toy i2c echo device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an example I2C device to demonstrate how a slave may master the bus and send data asynchronously to another slave. The device will echo whatever it is sent to the device identified by the first byte received. Signed-off-by: Klaus Jensen [ clg: integrated fixes : https://lore.kernel.org/qemu-devel/Y3yMKAhOkYGtnkOp@cormorant.local/ ] Message-Id: <20220601210831.67259-7-its@irrelevant.dk> Signed-off-by: Cédric Le Goater --- hw/misc/i2c-echo.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 2 + 2 files changed, 158 insertions(+) create mode 100644 hw/misc/i2c-echo.c (limited to 'hw') diff --git a/hw/misc/i2c-echo.c b/hw/misc/i2c-echo.c new file mode 100644 index 0000000..5705ab5 --- /dev/null +++ b/hw/misc/i2c-echo.c @@ -0,0 +1,156 @@ +#include "qemu/osdep.h" +#include "qemu/timer.h" +#include "qemu/main-loop.h" +#include "block/aio.h" +#include "hw/i2c/i2c.h" + +#define TYPE_I2C_ECHO "i2c-echo" +OBJECT_DECLARE_SIMPLE_TYPE(I2CEchoState, I2C_ECHO) + +enum i2c_echo_state { + I2C_ECHO_STATE_IDLE, + I2C_ECHO_STATE_START_SEND, + I2C_ECHO_STATE_ACK, +}; + +typedef struct I2CEchoState { + I2CSlave parent_obj; + + I2CBus *bus; + + enum i2c_echo_state state; + QEMUBH *bh; + + unsigned int pos; + uint8_t data[3]; +} I2CEchoState; + +static void i2c_echo_bh(void *opaque) +{ + I2CEchoState *state = opaque; + + switch (state->state) { + case I2C_ECHO_STATE_IDLE: + return; + + case I2C_ECHO_STATE_START_SEND: + if (i2c_start_send_async(state->bus, state->data[0])) { + goto release_bus; + } + + state->pos++; + state->state = I2C_ECHO_STATE_ACK; + return; + + case I2C_ECHO_STATE_ACK: + if (state->pos > 2) { + break; + } + + if (i2c_send_async(state->bus, state->data[state->pos++])) { + break; + } + + return; + } + + + i2c_end_transfer(state->bus); +release_bus: + i2c_bus_release(state->bus); + + state->state = I2C_ECHO_STATE_IDLE; +} + +static int i2c_echo_event(I2CSlave *s, enum i2c_event event) +{ + I2CEchoState *state = I2C_ECHO(s); + + switch (event) { + case I2C_START_RECV: + state->pos = 0; + + break; + + case I2C_START_SEND: + state->pos = 0; + + break; + + case I2C_FINISH: + state->pos = 0; + state->state = I2C_ECHO_STATE_START_SEND; + i2c_bus_master(state->bus, state->bh); + + break; + + case I2C_NACK: + break; + + default: + return -1; + } + + return 0; +} + +static uint8_t i2c_echo_recv(I2CSlave *s) +{ + I2CEchoState *state = I2C_ECHO(s); + + if (state->pos > 2) { + return 0xff; + } + + return state->data[state->pos++]; +} + +static int i2c_echo_send(I2CSlave *s, uint8_t data) +{ + I2CEchoState *state = I2C_ECHO(s); + + if (state->pos > 2) { + return -1; + } + + state->data[state->pos++] = data; + + return 0; +} + +static void i2c_echo_realize(DeviceState *dev, Error **errp) +{ + I2CEchoState *state = I2C_ECHO(dev); + BusState *bus = qdev_get_parent_bus(dev); + + state->bus = I2C_BUS(bus); + state->bh = qemu_bh_new(i2c_echo_bh, state); + + return; +} + +static void i2c_echo_class_init(ObjectClass *oc, void *data) +{ + I2CSlaveClass *sc = I2C_SLAVE_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = i2c_echo_realize; + + sc->event = i2c_echo_event; + sc->recv = i2c_echo_recv; + sc->send = i2c_echo_send; +} + +static const TypeInfo i2c_echo = { + .name = TYPE_I2C_ECHO, + .parent = TYPE_I2C_SLAVE, + .instance_size = sizeof(I2CEchoState), + .class_init = i2c_echo_class_init, +}; + +static void register_types(void) +{ + type_register_static(&i2c_echo); +} + +type_init(register_types); diff --git a/hw/misc/meson.build b/hw/misc/meson.build index fe869b9..a40245a 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -128,6 +128,8 @@ softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c')) softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_ahb_apb_pnp.c')) +softmmu_ss.add(when: 'CONFIG_I2C', if_true: files('i2c-echo.c')) + specific_ss.add(when: 'CONFIG_AVR_POWER', if_true: files('avr_power.c')) specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: files('mac_via.c')) -- cgit v1.1 From 34f73a81e6cb84b2f7fca740887d59504173d2a0 Mon Sep 17 00:00:00 2001 From: Karthikeyan Pasupathi Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: hw/arm/aspeed: Adding new machine Yosemitev2 in QEMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch support Yosemitev2 in QEMU environment. and introduced EEPROM BMC FRU data support "add fbyv2_bmc_fruid data" along with the machine support. Signed-off-by: Karthikeyan Pasupathi Reviewed-by: Cédric Le Goater [ clg: - commit log topic update - Documentation update ] Message-Id: <20230216133326.216017-1-pkarthikeyan1509@gmail.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 31 +++++++++++++++++++++++++++++++ hw/arm/aspeed_eeprom.c | 23 +++++++++++++++++++++++ hw/arm/aspeed_eeprom.h | 3 +++ 3 files changed, 57 insertions(+) (limited to 'hw') diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 27dda58..3f992fe 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -521,6 +521,15 @@ static void ast2600_evb_i2c_init(AspeedMachineState *bmc) TYPE_TMP105, 0x4d); } +static void yosemitev2_bmc_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + + at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 4), 0x51, 128 * KiB); + at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 8), 0x51, 128 * KiB, + yosemitev2_bmc_fruid, yosemitev2_bmc_fruid_len); +} + static void romulus_bmc_i2c_init(AspeedMachineState *bmc) { AspeedSoCState *soc = &bmc->soc; @@ -1174,6 +1183,24 @@ static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data) aspeed_soc_num_cpus(amc->soc_name); }; +static void aspeed_machine_yosemitev2_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Facebook YosemiteV2 BMC (ARM1176)"; + amc->soc_name = "ast2500-a1"; + amc->hw_strap1 = AST2500_EVB_HW_STRAP1; + amc->hw_strap2 = 0; + amc->fmc_model = "n25q256a"; + amc->spi_model = "mx25l25635e"; + amc->num_cs = 2; + amc->i2c_init = yosemitev2_bmc_i2c_init; + mc->default_ram_size = 512 * MiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); +}; + static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1563,6 +1590,10 @@ static const TypeInfo aspeed_machine_types[] = { .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_ast2600_evb_class_init, }, { + .name = MACHINE_TYPE_NAME("yosemitev2-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_yosemitev2_class_init, + }, { .name = MACHINE_TYPE_NAME("tacoma-bmc"), .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_tacoma_class_init, diff --git a/hw/arm/aspeed_eeprom.c b/hw/arm/aspeed_eeprom.c index 04463ac..7006794 100644 --- a/hw/arm/aspeed_eeprom.c +++ b/hw/arm/aspeed_eeprom.c @@ -77,6 +77,29 @@ const uint8_t fby35_bmc_fruid[] = { 0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45, }; +/* Yosemite V2 BMC FRU */ +const uint8_t yosemitev2_bmc_fruid[] = { + 0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x00, 0x36, + 0xe6, 0xd0, 0xc6, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, 0x42, 0x4d, + 0x43, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x4d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0xcd, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xce, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc3, 0x31, 0x2e, + 0x30, 0xc9, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc1, 0x39, 0x01, 0x0c, 0x00, 0xc6, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, 0x59, 0x6f, 0x73, 0x65, 0x6d, + 0x69, 0x74, 0x65, 0x20, 0x56, 0x32, 0x2e, 0x30, 0x20, 0x45, 0x56, 0x54, + 0x32, 0xce, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0xc4, 0x45, 0x56, 0x54, 0x32, 0xcd, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc7, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc3, 0x31, 0x2e, 0x30, 0xc9, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc8, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45, +}; + const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid); const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid); const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid); + +const size_t yosemitev2_bmc_fruid_len = sizeof(yosemitev2_bmc_fruid); diff --git a/hw/arm/aspeed_eeprom.h b/hw/arm/aspeed_eeprom.h index a0f848f..edf18e9 100644 --- a/hw/arm/aspeed_eeprom.h +++ b/hw/arm/aspeed_eeprom.h @@ -16,4 +16,7 @@ extern const size_t fby35_nic_fruid_len; extern const size_t fby35_bb_fruid_len; extern const size_t fby35_bmc_fruid_len; +extern const uint8_t yosemitev2_bmc_fruid[]; +extern const size_t yosemitev2_bmc_fruid_len; + #endif -- cgit v1.1 From 6c323aba4096a26a4d7561bb7abfba95a769fd0a Mon Sep 17 00:00:00 2001 From: Karthikeyan Pasupathi Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: hw/arm/aspeed: Adding new machine Tiogapass in QEMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch support Tiogapass in QEMU environment. and introduced EEPROM BMC FRU data support "add tiogapass_bmc_fruid data" along with the machine support. Signed-off-by: Karthikeyan Pasupathi Reviewed-by: Cédric Le Goater [ clg: - commit log topic update - checkpatch issues - Documentation update ] Message-Id: <20230216184342.253868-1-pkarthikeyan1509@gmail.com> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 32 ++++++++++++++++++++++++++++++++ hw/arm/aspeed_eeprom.c | 22 ++++++++++++++++++++++ hw/arm/aspeed_eeprom.h | 3 +++ 3 files changed, 57 insertions(+) (limited to 'hw') diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 3f992fe..6bafeb8 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -539,6 +539,15 @@ static void romulus_bmc_i2c_init(AspeedMachineState *bmc) i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32); } +static void tiogapass_bmc_i2c_init(AspeedMachineState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + + at24c_eeprom_init(aspeed_i2c_get_bus(&soc->i2c, 4), 0x54, 128 * KiB); + at24c_eeprom_init_rom(aspeed_i2c_get_bus(&soc->i2c, 6), 0x54, 128 * KiB, + tiogapass_bmc_fruid, tiogapass_bmc_fruid_len); +} + static void create_pca9552(AspeedSoCState *soc, int bus_id, int addr) { i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, bus_id), @@ -1218,6 +1227,25 @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data) aspeed_soc_num_cpus(amc->soc_name); }; +static void aspeed_machine_tiogapass_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc); + + mc->desc = "Facebook Tiogapass BMC (ARM1176)"; + amc->soc_name = "ast2500-a1"; + amc->hw_strap1 = AST2500_EVB_HW_STRAP1; + amc->hw_strap2 = 0; + amc->fmc_model = "n25q256a"; + amc->spi_model = "mx25l25635e"; + amc->num_cs = 2; + amc->i2c_init = tiogapass_bmc_i2c_init; + mc->default_ram_size = 1 * GiB; + mc->default_cpus = mc->min_cpus = mc->max_cpus = + aspeed_soc_num_cpus(amc->soc_name); + aspeed_soc_num_cpus(amc->soc_name); +}; + static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1598,6 +1626,10 @@ static const TypeInfo aspeed_machine_types[] = { .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_tacoma_class_init, }, { + .name = MACHINE_TYPE_NAME("tiogapass-bmc"), + .parent = TYPE_ASPEED_MACHINE, + .class_init = aspeed_machine_tiogapass_class_init, + }, { .name = MACHINE_TYPE_NAME("g220a-bmc"), .parent = TYPE_ASPEED_MACHINE, .class_init = aspeed_machine_g220a_class_init, diff --git a/hw/arm/aspeed_eeprom.c b/hw/arm/aspeed_eeprom.c index 7006794..2fb2d5d 100644 --- a/hw/arm/aspeed_eeprom.c +++ b/hw/arm/aspeed_eeprom.c @@ -6,6 +6,27 @@ #include "aspeed_eeprom.h" +/* Tiogapass BMC FRU */ +const uint8_t tiogapass_bmc_fruid[] = { + 0x01, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0xf1, 0x01, 0x0c, 0x00, 0x36, + 0xe6, 0xd0, 0xc6, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, 0x42, 0x4d, + 0x43, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x4d, 0x6f, + 0x64, 0x75, 0x6c, 0x65, 0xcd, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xce, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc3, 0x31, 0x2e, + 0x30, 0xc9, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc1, 0x39, 0x01, 0x0c, 0x00, 0xc6, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xd2, 0x54, 0x69, 0x6f, 0x67, 0x61, + 0x20, 0x50, 0x61, 0x73, 0x73, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, + 0x32, 0xce, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0xc4, 0x58, 0x58, 0x58, 0x32, 0xcd, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc7, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc3, 0x31, 0x2e, 0x30, 0xc9, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xc8, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45, +}; + const uint8_t fby35_nic_fruid[] = { 0x01, 0x00, 0x00, 0x01, 0x0f, 0x20, 0x00, 0xcf, 0x01, 0x0e, 0x19, 0xd7, 0x5e, 0xcf, 0xc8, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xdd, @@ -98,6 +119,7 @@ const uint8_t yosemitev2_bmc_fruid[] = { 0x6e, 0x66, 0x69, 0x67, 0x20, 0x41, 0xc1, 0x45, }; +const size_t tiogapass_bmc_fruid_len = sizeof(tiogapass_bmc_fruid); const size_t fby35_nic_fruid_len = sizeof(fby35_nic_fruid); const size_t fby35_bb_fruid_len = sizeof(fby35_bb_fruid); const size_t fby35_bmc_fruid_len = sizeof(fby35_bmc_fruid); diff --git a/hw/arm/aspeed_eeprom.h b/hw/arm/aspeed_eeprom.h index edf18e9..86db6f0 100644 --- a/hw/arm/aspeed_eeprom.h +++ b/hw/arm/aspeed_eeprom.h @@ -9,6 +9,9 @@ #include "qemu/osdep.h" +extern const uint8_t tiogapass_bmc_fruid[]; +extern const size_t tiogapass_bmc_fruid_len; + extern const uint8_t fby35_nic_fruid[]; extern const uint8_t fby35_bb_fruid[]; extern const uint8_t fby35_bmc_fruid[]; -- cgit v1.1 From 1e001a5a712a41d9acc1bd6cdef0eaf8270c9555 Mon Sep 17 00:00:00 2001 From: Sittisak Sinprem Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: hw/at24c : modify at24c to support 1 byte address mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sittisak Sinprem Reviewed-by: Peter Delevoryas [ clg: checkpatch issues ] Message-Id: <167660539263.10409.9736070122710923479-1@git.sr.ht> Signed-off-by: Cédric Le Goater --- hw/nvram/eeprom_at24c.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c index 3328c32..613c492 100644 --- a/hw/nvram/eeprom_at24c.c +++ b/hw/nvram/eeprom_at24c.c @@ -41,6 +41,13 @@ struct EEPROMState { uint16_t cur; /* total size in bytes */ uint32_t rsize; + /* + * address byte number + * for 24c01, 24c02 size <= 256 byte, use only 1 byte + * otherwise size > 256, use 2 byte + */ + uint8_t asize; + bool writable; /* cells changed since last START? */ bool changed; @@ -91,7 +98,11 @@ uint8_t at24c_eeprom_recv(I2CSlave *s) EEPROMState *ee = AT24C_EE(s); uint8_t ret; - if (ee->haveaddr == 1) { + /* + * If got the byte address but not completely with address size + * will return the invalid value + */ + if (ee->haveaddr > 0 && ee->haveaddr < ee->asize) { return 0xff; } @@ -108,11 +119,11 @@ int at24c_eeprom_send(I2CSlave *s, uint8_t data) { EEPROMState *ee = AT24C_EE(s); - if (ee->haveaddr < 2) { + if (ee->haveaddr < ee->asize) { ee->cur <<= 8; ee->cur |= data; ee->haveaddr++; - if (ee->haveaddr == 2) { + if (ee->haveaddr == ee->asize) { ee->cur %= ee->rsize; DPRINTK("Set pointer %04x\n", ee->cur); } @@ -199,6 +210,18 @@ static void at24c_eeprom_realize(DeviceState *dev, Error **errp) } DPRINTK("Reset read backing file\n"); } + + /* + * If address size didn't define with property set + * value is 0 as default, setting it by Rom size detecting. + */ + if (ee->asize == 0) { + if (ee->rsize <= 256) { + ee->asize = 1; + } else { + ee->asize = 2; + } + } } static @@ -213,6 +236,7 @@ void at24c_eeprom_reset(DeviceState *state) static Property at24c_eeprom_props[] = { DEFINE_PROP_UINT32("rom-size", EEPROMState, rsize, 0), + DEFINE_PROP_UINT8("address-size", EEPROMState, asize, 0), DEFINE_PROP_BOOL("writable", EEPROMState, writable, true), DEFINE_PROP_DRIVE("drive", EEPROMState, blk), DEFINE_PROP_END_OF_LIST() -- cgit v1.1 From ef0eb67ec96e03e6016c1e72b208f5fcbb455724 Mon Sep 17 00:00:00 2001 From: Sittisak Sinprem Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: aspeed/fuji : correct the eeprom size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Device 24C64 the size is 64 kilobits = 8kilobyte Device 24C02 the size is 2 kilobits = 256byte Signed-off-by: Sittisak Sinprem Reviewed-by: Peter Delevoryas [ clg: checkpatch issues ] Message-Id: <167660539263.10409.9736070122710923479-2@git.sr.ht> Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'hw') diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 6bafeb8..cb59a37 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -858,42 +858,46 @@ static void fuji_bmc_i2c_init(AspeedMachineState *bmc) i2c_slave_create_simple(i2c[17], TYPE_LM75, 0x4c); i2c_slave_create_simple(i2c[17], TYPE_LM75, 0x4d); - at24c_eeprom_init(i2c[19], 0x52, 64 * KiB); - at24c_eeprom_init(i2c[20], 0x50, 2 * KiB); - at24c_eeprom_init(i2c[22], 0x52, 2 * KiB); + /* + * EEPROM 24c64 size is 64Kbits or 8 Kbytes + * 24c02 size is 2Kbits or 256 bytes + */ + at24c_eeprom_init(i2c[19], 0x52, 8 * KiB); + at24c_eeprom_init(i2c[20], 0x50, 256); + at24c_eeprom_init(i2c[22], 0x52, 256); i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x48); i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x49); i2c_slave_create_simple(i2c[3], TYPE_LM75, 0x4a); i2c_slave_create_simple(i2c[3], TYPE_TMP422, 0x4c); - at24c_eeprom_init(i2c[8], 0x51, 64 * KiB); + at24c_eeprom_init(i2c[8], 0x51, 8 * KiB); i2c_slave_create_simple(i2c[8], TYPE_LM75, 0x4a); i2c_slave_create_simple(i2c[50], TYPE_LM75, 0x4c); - at24c_eeprom_init(i2c[50], 0x52, 64 * KiB); + at24c_eeprom_init(i2c[50], 0x52, 8 * KiB); i2c_slave_create_simple(i2c[51], TYPE_TMP75, 0x48); i2c_slave_create_simple(i2c[52], TYPE_TMP75, 0x49); i2c_slave_create_simple(i2c[59], TYPE_TMP75, 0x48); i2c_slave_create_simple(i2c[60], TYPE_TMP75, 0x49); - at24c_eeprom_init(i2c[65], 0x53, 64 * KiB); + at24c_eeprom_init(i2c[65], 0x53, 8 * KiB); i2c_slave_create_simple(i2c[66], TYPE_TMP75, 0x49); i2c_slave_create_simple(i2c[66], TYPE_TMP75, 0x48); - at24c_eeprom_init(i2c[68], 0x52, 64 * KiB); - at24c_eeprom_init(i2c[69], 0x52, 64 * KiB); - at24c_eeprom_init(i2c[70], 0x52, 64 * KiB); - at24c_eeprom_init(i2c[71], 0x52, 64 * KiB); + at24c_eeprom_init(i2c[68], 0x52, 8 * KiB); + at24c_eeprom_init(i2c[69], 0x52, 8 * KiB); + at24c_eeprom_init(i2c[70], 0x52, 8 * KiB); + at24c_eeprom_init(i2c[71], 0x52, 8 * KiB); - at24c_eeprom_init(i2c[73], 0x53, 64 * KiB); + at24c_eeprom_init(i2c[73], 0x53, 8 * KiB); i2c_slave_create_simple(i2c[74], TYPE_TMP75, 0x49); i2c_slave_create_simple(i2c[74], TYPE_TMP75, 0x48); - at24c_eeprom_init(i2c[76], 0x52, 64 * KiB); - at24c_eeprom_init(i2c[77], 0x52, 64 * KiB); - at24c_eeprom_init(i2c[78], 0x52, 64 * KiB); - at24c_eeprom_init(i2c[79], 0x52, 64 * KiB); - at24c_eeprom_init(i2c[28], 0x50, 2 * KiB); + at24c_eeprom_init(i2c[76], 0x52, 8 * KiB); + at24c_eeprom_init(i2c[77], 0x52, 8 * KiB); + at24c_eeprom_init(i2c[78], 0x52, 8 * KiB); + at24c_eeprom_init(i2c[79], 0x52, 8 * KiB); + at24c_eeprom_init(i2c[28], 0x50, 256); for (int i = 0; i < 8; i++) { at24c_eeprom_init(i2c[81 + i * 8], 0x56, 64 * KiB); -- cgit v1.1 From 5aa281d757960ea79190bcfb25294e2499de165e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: aspeed: Introduce a spi_boot region under the SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default boot address of the Aspeed SoCs is 0x0. For this reason, the FMC flash device contents are remapped by HW on the first 256MB of the address space. In QEMU, this is currently done in the machine init with the setup of a region alias. Move this code to the SoC and introduce an extra container to prepare ground for the boot ROM region which will overlap the FMC flash remapping. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 13 +------------ hw/arm/aspeed_ast2600.c | 13 +++++++++++++ hw/arm/aspeed_soc.c | 14 ++++++++++++++ hw/arm/fby35.c | 8 +------- 4 files changed, 29 insertions(+), 19 deletions(-) (limited to 'hw') diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index cb59a37..4a2814b 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -388,18 +388,7 @@ static void aspeed_machine_init(MachineState *machine) MemoryRegion *boot_rom = g_new(MemoryRegion, 1); uint64_t size = memory_region_size(&fl->mmio); - /* - * create a ROM region using the default mapping window size of - * the flash module. The window size is 64MB for the AST2400 - * SoC and 128MB for the AST2500 SoC, which is twice as big as - * needed by the flash modules of the Aspeed machines. - */ - if (ASPEED_MACHINE(machine)->mmio_exec) { - memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom", - &fl->mmio, 0, size); - memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR, - boot_rom); - } else { + if (!ASPEED_MACHINE(machine)->mmio_exec) { memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", size, &error_abort); memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR, diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index bb2769d..1bf1246 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -21,6 +21,7 @@ #define ASPEED_SOC_DPMCU_SIZE 0x00040000 static const hwaddr aspeed_soc_ast2600_memmap[] = { + [ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, [ASPEED_DEV_SRAM] = 0x10000000, [ASPEED_DEV_DPMCU] = 0x18000000, /* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */ @@ -282,6 +283,12 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) qemu_irq irq; g_autofree char *sram_name = NULL; + /* Default boot region (SPI memory or ROMs) */ + memory_region_init(&s->spi_boot_container, OBJECT(s), + "aspeed.spi_boot_container", 0x10000000); + memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SPI_BOOT], + &s->spi_boot_container); + /* IO space */ aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io", sc->memmap[ASPEED_DEV_IOMEM], @@ -431,6 +438,12 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0, aspeed_soc_get_irq(s, ASPEED_DEV_FMC)); + /* Set up an alias on the FMC CE0 region (boot default) */ + MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio; + memory_region_init_alias(&s->spi_boot, OBJECT(s), "aspeed.spi_boot", + fmc0_mmio, 0, memory_region_size(fmc0_mmio)); + memory_region_add_subregion(&s->spi_boot_container, 0x0, &s->spi_boot); + /* SPI */ for (i = 0; i < sc->spis_num; i++) { object_property_set_link(OBJECT(&s->spi[i]), "dram", diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index e884d6b..bf22258 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -25,6 +25,7 @@ #define ASPEED_SOC_IOMEM_SIZE 0x00200000 static const hwaddr aspeed_soc_ast2400_memmap[] = { + [ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, [ASPEED_DEV_IOMEM] = 0x1E600000, [ASPEED_DEV_FMC] = 0x1E620000, [ASPEED_DEV_SPI1] = 0x1E630000, @@ -59,6 +60,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = { }; static const hwaddr aspeed_soc_ast2500_memmap[] = { + [ASPEED_DEV_SPI_BOOT] = ASPEED_SOC_SPI_BOOT_ADDR, [ASPEED_DEV_IOMEM] = 0x1E600000, [ASPEED_DEV_FMC] = 0x1E620000, [ASPEED_DEV_SPI1] = 0x1E630000, @@ -245,6 +247,12 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) Error *err = NULL; g_autofree char *sram_name = NULL; + /* Default boot region (SPI memory or ROMs) */ + memory_region_init(&s->spi_boot_container, OBJECT(s), + "aspeed.spi_boot_container", 0x10000000); + memory_region_add_subregion(s->memory, sc->memmap[ASPEED_DEV_SPI_BOOT], + &s->spi_boot_container); + /* IO space */ aspeed_mmio_map_unimplemented(s, SYS_BUS_DEVICE(&s->iomem), "aspeed.io", sc->memmap[ASPEED_DEV_IOMEM], @@ -354,6 +362,12 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0, aspeed_soc_get_irq(s, ASPEED_DEV_FMC)); + /* Set up an alias on the FMC CE0 region (boot default) */ + MemoryRegion *fmc0_mmio = &s->fmc.flashes[0].mmio; + memory_region_init_alias(&s->spi_boot, OBJECT(s), "aspeed.spi_boot", + fmc0_mmio, 0, memory_region_size(fmc0_mmio)); + memory_region_add_subregion(&s->spi_boot_container, 0x0, &s->spi_boot); + /* SPI */ for (i = 0; i < sc->spis_num; i++) { if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) { diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c index 90c04bb..f4600c2 100644 --- a/hw/arm/fby35.c +++ b/hw/arm/fby35.c @@ -100,13 +100,7 @@ static void fby35_bmc_init(Fby35State *s) MemoryRegion *boot_rom = g_new(MemoryRegion, 1); uint64_t size = memory_region_size(&fl->mmio); - if (s->mmio_exec) { - memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom", - &fl->mmio, 0, size); - memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR, - boot_rom); - } else { - + if (!s->mmio_exec) { memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", size, &error_abort); memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR, -- cgit v1.1 From 8b744a6a473015a24d528f480b99faf95da50775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: aspeed: Add a boot_rom overlap region in the SoC spi_boot container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid the SPI transactions fetching instructions from the FMC CE0 flash device and speed up boot, a ROM can be created if a drive is available. Reverse the logic to allow a machine to boot without a drive, using a block device instead : -blockdev node-name=fmc0,driver=file,filename=/path/to/flash.img \ -device mx66u51235f,bus=ssi.0,drive=fmc0 Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'hw') diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 4a2814b..e261738 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -241,12 +241,9 @@ static void aspeed_reset_secondary(ARMCPU *cpu, cpu_set_pc(cs, info->smp_loader_start); } -#define FIRMWARE_ADDR 0x0 - -static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size, +static void write_boot_rom(BlockBackend *blk, hwaddr addr, size_t rom_size, Error **errp) { - BlockBackend *blk = blk_by_legacy_dinfo(dinfo); g_autofree void *storage = NULL; int64_t size; @@ -272,6 +269,22 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size, rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr); } +/* + * Create a ROM and copy the flash contents at the expected address + * (0x0). Boots faster than execute-in-place. + */ +static void aspeed_install_boot_rom(AspeedSoCState *soc, BlockBackend *blk, + uint64_t rom_size) +{ + MemoryRegion *boot_rom = g_new(MemoryRegion, 1); + + memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", rom_size, + &error_abort); + memory_region_add_subregion_overlap(&soc->spi_boot_container, 0, + boot_rom, 1); + write_boot_rom(blk, ASPEED_SOC_SPI_BOOT_ADDR, rom_size, &error_abort); +} + void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, unsigned int count, int unit0) { @@ -332,7 +345,6 @@ static void aspeed_machine_init(MachineState *machine) AspeedMachineState *bmc = ASPEED_MACHINE(machine); AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine); AspeedSoCClass *sc; - DriveInfo *drive0 = drive_get(IF_MTD, 0, 0); int i; NICInfo *nd = &nd_table[0]; @@ -382,21 +394,6 @@ static void aspeed_machine_init(MachineState *machine) bmc->spi_model ? bmc->spi_model : amc->spi_model, 1, amc->num_cs); - /* Install first FMC flash content as a boot rom. */ - if (drive0) { - AspeedSMCFlash *fl = &bmc->soc.fmc.flashes[0]; - MemoryRegion *boot_rom = g_new(MemoryRegion, 1); - uint64_t size = memory_region_size(&fl->mmio); - - if (!ASPEED_MACHINE(machine)->mmio_exec) { - memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom", - size, &error_abort); - memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR, - boot_rom); - write_boot_rom(drive0, FIRMWARE_ADDR, size, &error_abort); - } - } - if (machine->kernel_filename && sc->num_cpus > 1) { /* With no u-boot we must set up a boot stub for the secondary CPU */ MemoryRegion *smpboot = g_new(MemoryRegion, 1); @@ -427,6 +424,16 @@ static void aspeed_machine_init(MachineState *machine) drive_get(IF_SD, 0, bmc->soc.sdhci.num_slots)); } + if (!bmc->mmio_exec) { + DriveInfo *mtd0 = drive_get(IF_MTD, 0, 0); + + if (mtd0) { + uint64_t rom_size = memory_region_size(&bmc->soc.spi_boot); + aspeed_install_boot_rom(&bmc->soc, blk_by_legacy_dinfo(mtd0), + rom_size); + } + } + arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo); } -- cgit v1.1 From b22a2d409b1acfdf0d63d1bb3595194ceb3d94da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Thu, 2 Mar 2023 13:57:50 +0100 Subject: aspeed/smc: Replace SysBus IRQs with GPIO lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's cleaner and removes the curious '+ 1' required to skip the DMA IRQ line of the controller. Signed-off-by: Cédric Le Goater Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Cédric Le Goater --- hw/arm/aspeed.c | 2 +- hw/ssi/aspeed_smc.c | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index e261738..86601cb 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -306,7 +306,7 @@ void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, qdev_realize_and_unref(dev, BUS(s->spi), &error_fatal); cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0); - sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line); + qdev_connect_gpio_out_named(DEVICE(s), "cs", i, cs_line); } } diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index 22df4be..7281169 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -1134,10 +1134,7 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp) /* Setup cs_lines for peripherals */ s->cs_lines = g_new0(qemu_irq, asc->cs_num_max); - - for (i = 0; i < asc->cs_num_max; ++i) { - sysbus_init_irq(sbd, &s->cs_lines[i]); - } + qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", asc->cs_num_max); /* The memory region for the controller registers */ memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s, -- cgit v1.1