From 93198b6cad8af03996373584284a1673ad6000cb Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 13 Nov 2018 18:31:27 -0600 Subject: i2c: Split smbus into parts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit smbus.c and smbus.h had device side code, master side code, and smbus.h has some smbus_eeprom.c definitions. Split them into separate files. Signed-off-by: Corey Minyard Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé --- include/hw/i2c/pm_smbus.h | 2 + include/hw/i2c/smbus.h | 101 ------------------------------------------ include/hw/i2c/smbus_eeprom.h | 35 +++++++++++++++ include/hw/i2c/smbus_master.h | 55 +++++++++++++++++++++++ include/hw/i2c/smbus_slave.h | 69 +++++++++++++++++++++++++++++ 5 files changed, 161 insertions(+), 101 deletions(-) delete mode 100644 include/hw/i2c/smbus.h create mode 100644 include/hw/i2c/smbus_eeprom.h create mode 100644 include/hw/i2c/smbus_master.h create mode 100644 include/hw/i2c/smbus_slave.h (limited to 'include') diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h index 060d3c6ac0..6dd5b7040b 100644 --- a/include/hw/i2c/pm_smbus.h +++ b/include/hw/i2c/pm_smbus.h @@ -1,6 +1,8 @@ #ifndef PM_SMBUS_H #define PM_SMBUS_H +#include "hw/i2c/smbus_master.h" + #define PM_SMBUS_MAX_MSG_SIZE 32 typedef struct PMSMBus { diff --git a/include/hw/i2c/smbus.h b/include/hw/i2c/smbus.h deleted file mode 100644 index 89dfea1a08..0000000000 --- a/include/hw/i2c/smbus.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef QEMU_SMBUS_H -#define QEMU_SMBUS_H - -/* - * QEMU SMBus API - * - * Copyright (c) 2007 Arastra, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "hw/i2c/i2c.h" - -#define TYPE_SMBUS_DEVICE "smbus-device" -#define SMBUS_DEVICE(obj) \ - OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE) -#define SMBUS_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE) -#define SMBUS_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE) - -typedef struct SMBusDevice SMBusDevice; - -typedef struct SMBusDeviceClass -{ - I2CSlaveClass parent_class; - void (*quick_cmd)(SMBusDevice *dev, uint8_t read); - void (*send_byte)(SMBusDevice *dev, uint8_t val); - uint8_t (*receive_byte)(SMBusDevice *dev); - /* We can't distinguish between a word write and a block write with - length 1, so pass the whole data block including the length byte - (if present). The device is responsible figuring out what type of - command this is. */ - void (*write_data)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len); - /* Likewise we can't distinguish between different reads, or even know - the length of the read until the read is complete, so read data a - byte at a time. The device is responsible for adding the length - byte on block reads. */ - uint8_t (*read_data)(SMBusDevice *dev, uint8_t cmd, int n); -} SMBusDeviceClass; - -struct SMBusDevice { - /* The SMBus protocol is implemented on top of I2C. */ - I2CSlave i2c; - - /* Remaining fields for internal use only. */ - int mode; - int data_len; - uint8_t data_buf[34]; /* command + len + 32 bytes of data. */ - uint8_t command; -}; - -/* Master device commands. */ -int smbus_quick_command(I2CBus *bus, uint8_t addr, int read); -int smbus_receive_byte(I2CBus *bus, uint8_t addr); -int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data); -int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command); -int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data); -int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command); -int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data); - -/* - * Do a block transfer from an I2C device. If recv_len is set, then the - * first received byte is a length field and is used to know how much data - * to receive. Otherwise receive "len" bytes. If send_cmd is set, send - * the command byte first before receiving the data. - */ -int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, - int len, bool recv_len, bool send_cmd); - -/* - * Do a block transfer to an I2C device. If send_len is set, send the - * "len" value before the data. - */ -int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, - int len, bool send_len); - -void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf); -void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, - const uint8_t *eeprom_spd, int size); - -enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 }; -uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size, Error **errp); - -#endif diff --git a/include/hw/i2c/smbus_eeprom.h b/include/hw/i2c/smbus_eeprom.h new file mode 100644 index 0000000000..0f96836bab --- /dev/null +++ b/include/hw/i2c/smbus_eeprom.h @@ -0,0 +1,35 @@ +/* + * QEMU SMBus EEPROM API + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_SMBUS_EEPROM_H +#define HW_SMBUS_EEPROM_H + +#include "hw/i2c/i2c.h" + +void smbus_eeprom_init_one(I2CBus *bus, uint8_t address, uint8_t *eeprom_buf); +void smbus_eeprom_init(I2CBus *bus, int nb_eeprom, + const uint8_t *eeprom_spd, int size); + +enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 }; +uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size, Error **errp); + +#endif diff --git a/include/hw/i2c/smbus_master.h b/include/hw/i2c/smbus_master.h new file mode 100644 index 0000000000..bb13bc423c --- /dev/null +++ b/include/hw/i2c/smbus_master.h @@ -0,0 +1,55 @@ +/* + * QEMU SMBus host (master) API + * + * Copyright (c) 2007 Arastra, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_SMBUS_MASTER_H +#define HW_SMBUS_MASTER_H + +#include "hw/i2c/i2c.h" + +/* Master device commands. */ +int smbus_quick_command(I2CBus *bus, uint8_t addr, int read); +int smbus_receive_byte(I2CBus *bus, uint8_t addr); +int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data); +int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command); +int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data); +int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command); +int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data); + +/* + * Do a block transfer from an I2C device. If recv_len is set, then the + * first received byte is a length field and is used to know how much data + * to receive. Otherwise receive "len" bytes. If send_cmd is set, send + * the command byte first before receiving the data. + */ +int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, + int len, bool recv_len, bool send_cmd); + +/* + * Do a block transfer to an I2C device. If send_len is set, send the + * "len" value before the data. + */ +int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data, + int len, bool send_len); + +#endif diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h new file mode 100644 index 0000000000..46b8948f0f --- /dev/null +++ b/include/hw/i2c/smbus_slave.h @@ -0,0 +1,69 @@ +/* + * QEMU SMBus device (slave) API + * + * Copyright (c) 2007 Arastra, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_SMBUS_SLAVE_H +#define HW_SMBUS_SLAVE_H + +#include "hw/i2c/i2c.h" + +#define TYPE_SMBUS_DEVICE "smbus-device" +#define SMBUS_DEVICE(obj) \ + OBJECT_CHECK(SMBusDevice, (obj), TYPE_SMBUS_DEVICE) +#define SMBUS_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(SMBusDeviceClass, (klass), TYPE_SMBUS_DEVICE) +#define SMBUS_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SMBusDeviceClass, (obj), TYPE_SMBUS_DEVICE) + +typedef struct SMBusDevice SMBusDevice; + +typedef struct SMBusDeviceClass +{ + I2CSlaveClass parent_class; + void (*quick_cmd)(SMBusDevice *dev, uint8_t read); + void (*send_byte)(SMBusDevice *dev, uint8_t val); + uint8_t (*receive_byte)(SMBusDevice *dev); + /* We can't distinguish between a word write and a block write with + length 1, so pass the whole data block including the length byte + (if present). The device is responsible figuring out what type of + command this is. */ + void (*write_data)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len); + /* Likewise we can't distinguish between different reads, or even know + the length of the read until the read is complete, so read data a + byte at a time. The device is responsible for adding the length + byte on block reads. */ + uint8_t (*read_data)(SMBusDevice *dev, uint8_t cmd, int n); +} SMBusDeviceClass; + +struct SMBusDevice { + /* The SMBus protocol is implemented on top of I2C. */ + I2CSlave i2c; + + /* Remaining fields for internal use only. */ + int mode; + int data_len; + uint8_t data_buf[34]; /* command + len + 32 bytes of data. */ + uint8_t command; +}; + +#endif -- cgit v1.2.3 From 2ac4c5f4d2415116d3f417a32311d437791dcfce Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 14 Nov 2018 11:50:50 -0600 Subject: i2c: have I2C receive operation return uint8_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is never supposed to fail and cannot return an error, so just have it return the proper type. Have it return 0xff on nothing available, since that's what would happen on a real bus. Signed-off-by: Corey Minyard Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé --- include/hw/i2c/i2c.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h index cf4c45a98f..8e236f7bb4 100644 --- a/include/hw/i2c/i2c.h +++ b/include/hw/i2c/i2c.h @@ -33,10 +33,9 @@ typedef struct I2CSlaveClass { /* * Slave to master. This cannot fail, the device should always - * return something here. Negative values probably result in 0xff - * and a possible log from the driver, and shouldn't be used. + * return something here. */ - int (*recv)(I2CSlave *s); + uint8_t (*recv)(I2CSlave *s); /* * Notify the slave of a bus state change. For start event, @@ -78,7 +77,7 @@ void i2c_end_transfer(I2CBus *bus); void i2c_nack(I2CBus *bus); int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send); int i2c_send(I2CBus *bus, uint8_t data); -int i2c_recv(I2CBus *bus); +uint8_t i2c_recv(I2CBus *bus); DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr); -- cgit v1.2.3 From 905cec6d11088e585fcedb3fd606510959ee50ff Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 30 Nov 2018 13:20:12 -0600 Subject: i2c:smbus: Correct the working of quick commands The logic of handling quick SMBus commands was wrong. If you get a finish event with no data, that's a quick command. Document the quick command while we are at it. Signed-off-by: Corey Minyard --- include/hw/i2c/smbus_slave.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h index 46b8948f0f..5ef1c72ad0 100644 --- a/include/hw/i2c/smbus_slave.h +++ b/include/hw/i2c/smbus_slave.h @@ -40,6 +40,11 @@ typedef struct SMBusDevice SMBusDevice; typedef struct SMBusDeviceClass { I2CSlaveClass parent_class; + + /* + * An operation with no data, special in SMBus. + * This may be NULL, quick commands are ignore in that case. + */ void (*quick_cmd)(SMBusDevice *dev, uint8_t read); void (*send_byte)(SMBusDevice *dev, uint8_t val); uint8_t (*receive_byte)(SMBusDevice *dev); -- cgit v1.2.3 From 9cf27d74a829f651c0da5d80c014a6cef9d4cbd8 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 30 Nov 2018 13:38:21 -0600 Subject: i2c:smbus: Simplify write operation There were two different write functions and the SMBus code kept track of the command. Keeping track of the command wasn't useful, in fact it wasn't quite correct for the eeprom_smbus code. And there is no need for two write functions. Just have one write function and the first byte in the buffer is the command. Signed-off-by: Corey Minyard --- include/hw/i2c/smbus_slave.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h index 5ef1c72ad0..fa92201ec6 100644 --- a/include/hw/i2c/smbus_slave.h +++ b/include/hw/i2c/smbus_slave.h @@ -46,18 +46,24 @@ typedef struct SMBusDeviceClass * This may be NULL, quick commands are ignore in that case. */ void (*quick_cmd)(SMBusDevice *dev, uint8_t read); - void (*send_byte)(SMBusDevice *dev, uint8_t val); + uint8_t (*receive_byte)(SMBusDevice *dev); - /* We can't distinguish between a word write and a block write with - length 1, so pass the whole data block including the length byte - (if present). The device is responsible figuring out what type of - command this is. */ - void (*write_data)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len); + + /* + * We can't distinguish between a word write and a block write with + * length 1, so pass the whole data block including the length byte + * (if present). The device is responsible figuring out what type of + * command this is. + * This may be NULL if no data is written to the device. Writes + * will be ignore in that case. + */ + int (*write_data)(SMBusDevice *dev, uint8_t *buf, uint8_t len); + /* Likewise we can't distinguish between different reads, or even know the length of the read until the read is complete, so read data a byte at a time. The device is responsible for adding the length byte on block reads. */ - uint8_t (*read_data)(SMBusDevice *dev, uint8_t cmd, int n); + uint8_t (*read_data)(SMBusDevice *dev, int n); } SMBusDeviceClass; struct SMBusDevice { @@ -68,7 +74,6 @@ struct SMBusDevice { int mode; int data_len; uint8_t data_buf[34]; /* command + len + 32 bytes of data. */ - uint8_t command; }; #endif -- cgit v1.2.3 From 031ac49886684ae6d6b88f37779cad2ffd1e4d9b Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 30 Nov 2018 13:49:31 -0600 Subject: i2c:smbus: Simplify read handling There were two different read functions, and with the removal of the command passed in there is no functional difference. So remove one of them. With that you don't need one of the states, so that can be removed, too. Signed-off-by: Corey Minyard --- include/hw/i2c/smbus_slave.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h index fa92201ec6..79050fb92d 100644 --- a/include/hw/i2c/smbus_slave.h +++ b/include/hw/i2c/smbus_slave.h @@ -47,8 +47,6 @@ typedef struct SMBusDeviceClass */ void (*quick_cmd)(SMBusDevice *dev, uint8_t read); - uint8_t (*receive_byte)(SMBusDevice *dev); - /* * We can't distinguish between a word write and a block write with * length 1, so pass the whole data block including the length byte @@ -59,11 +57,16 @@ typedef struct SMBusDeviceClass */ int (*write_data)(SMBusDevice *dev, uint8_t *buf, uint8_t len); - /* Likewise we can't distinguish between different reads, or even know - the length of the read until the read is complete, so read data a - byte at a time. The device is responsible for adding the length - byte on block reads. */ - uint8_t (*read_data)(SMBusDevice *dev, int n); + /* + * Likewise we can't distinguish between different reads, or even know + * the length of the read until the read is complete, so read data a + * byte at a time. The device is responsible for adding the length + * byte on block reads. This call cannot fail, it should return + * something, preferably 0xff if nothing is available. + * This may be NULL if no data is read from the device. Reads will + * return 0xff in that case. + */ + uint8_t (*receive_byte)(SMBusDevice *dev); } SMBusDeviceClass; struct SMBusDevice { -- cgit v1.2.3 From 7fccf2a06890e3bc3b30e29827ad3fb93fe88fea Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 14 Nov 2018 14:41:01 -0600 Subject: boards.h: Ignore migration for SMBus devices on older machines Migration capability is being added for pm_smbus and SMBus devices. This change will allow backwards compatibility to be kept when migrating back to an old qemu version. Add a bool to the machine class tho keep smbus migration from happening. Future changes will use this. Signed-off-by: Corey Minyard Cc: Eduardo Habkost Cc: Marcel Apfelbaum Reviewed-by: Dr. David Alan Gilbert --- include/hw/boards.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/hw/boards.h b/include/hw/boards.h index 05f9f45c3d..21212f0859 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -206,6 +206,7 @@ struct MachineClass { void (*numa_auto_assign_ram)(MachineClass *mc, NodeInfo *nodes, int nb_nodes, ram_addr_t size); bool ignore_boot_device_suffixes; + bool smbus_no_migration_support; HotplugHandler *(*get_hotplug_handler)(MachineState *machine, DeviceState *dev); -- cgit v1.2.3 From 52cc6a492b6c6e668f99e13d3cfad5caf7fbfd1c Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 14 Nov 2018 14:41:01 -0600 Subject: i2c:pm_smbus: Fix pm_smbus handling of I2C block read The I2C block read function of pm_smbus was completely broken. It required doing some direct I2C handling because it didn't have a defined size, the OS code just reads bytes until it marks the transaction finished. This also required adjusting how the AMIBIOS workaround code worked, the I2C block mode was setting STS_HOST_BUSY during a transaction, so that bit could no longer be used to inform the host status read code to start the transaction. Create a explicit bool for that operation. Also, don't read the next byte from the device in byte-by-byte mode unless the OS is actually clearing the byte done bit. Just assuming that's what the OS is doing is a bad idea. Signed-off-by: Corey Minyard --- include/hw/i2c/pm_smbus.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h index 6dd5b7040b..7bcca97672 100644 --- a/include/hw/i2c/pm_smbus.h +++ b/include/hw/i2c/pm_smbus.h @@ -33,6 +33,12 @@ typedef struct PMSMBus { /* Set on block transfers after the last byte has been read, so the INTR bit can be set at the right time. */ bool op_done; + + /* Set during an I2C block read, so we know how to handle data. */ + bool in_i2c_block_read; + + /* Used to work around a bug in AMIBIOS, see smb_transaction_start() */ + bool start_transaction_on_status_read; } PMSMBus; void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk); -- cgit v1.2.3 From 8e995f34031d66666b45b779458cb370e86cfe2d Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 26 Nov 2018 12:54:45 -0600 Subject: migration: Add a VMSTATE_BOOL_TEST() macro This will be needed by coming I2C changes. Signed-off-by: Corey Minyard Reviewed-by: Dr. David Alan Gilbert --- include/migration/vmstate.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 067b126cf1..a668ec75b8 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -851,6 +851,9 @@ extern const VMStateInfo vmstate_info_qtailq; #define VMSTATE_INT32_POSITIVE_LE(_f, _s) \ VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t) +#define VMSTATE_BOOL_TEST(_f, _s, _t) \ + VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_bool, bool) + #define VMSTATE_INT8_TEST(_f, _s, _t) \ VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_int8, int8_t) -- cgit v1.2.3 From 4ab2f2a8aabfea95cc53c64e13b3f67960b27fdf Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Thu, 22 Dec 2016 12:28:23 -0600 Subject: i2c:pm_smbus: Fix state transfer Transfer the state information for the SMBus registers and internal data so it will work on a VM transfer. Signed-off-by: Corey Minyard Cc: Michael S. Tsirkin Cc: Paolo Bonzini Cc: Dr. David Alan Gilbert Reviewed-by: Dr. David Alan Gilbert --- include/hw/i2c/pm_smbus.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/hw/i2c/pm_smbus.h b/include/hw/i2c/pm_smbus.h index 7bcca97672..fb55c44444 100644 --- a/include/hw/i2c/pm_smbus.h +++ b/include/hw/i2c/pm_smbus.h @@ -43,4 +43,13 @@ typedef struct PMSMBus { void pm_smbus_init(DeviceState *parent, PMSMBus *smb, bool force_aux_blk); +/* + * For backwards compatibility on migration, older versions don't have + * working migration for pm_smbus, this lets us ignore the migrations + * for older machine versions. + */ +bool pm_smbus_vmstate_needed(void); + +extern const VMStateDescription pmsmb_vmstate; + #endif /* PM_SMBUS_H */ -- cgit v1.2.3 From 547db24a17c22c47f762aae3a0a6f518f574e7f2 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Thu, 7 Dec 2017 09:34:59 -0600 Subject: i2c:smbus_slave: Add an SMBus vmstate structure There is no vmstate handling for SMBus, so no device sitting on SMBus can have a state transfer that works reliably. So add it. Signed-off-by: Corey Minyard Cc: Paolo Bonzini Cc: Michael S. Tsirkin Cc: Dr. David Alan Gilbert Reviewed-by: Dr. David Alan Gilbert --- include/hw/i2c/smbus_slave.h | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/hw/i2c/smbus_slave.h b/include/hw/i2c/smbus_slave.h index 79050fb92d..ebe068304e 100644 --- a/include/hw/i2c/smbus_slave.h +++ b/include/hw/i2c/smbus_slave.h @@ -69,14 +69,32 @@ typedef struct SMBusDeviceClass uint8_t (*receive_byte)(SMBusDevice *dev); } SMBusDeviceClass; +#define SMBUS_DATA_MAX_LEN 34 /* command + len + 32 bytes of data. */ + struct SMBusDevice { /* The SMBus protocol is implemented on top of I2C. */ I2CSlave i2c; /* Remaining fields for internal use only. */ - int mode; - int data_len; - uint8_t data_buf[34]; /* command + len + 32 bytes of data. */ + int32_t mode; + int32_t data_len; + uint8_t data_buf[SMBUS_DATA_MAX_LEN]; }; +extern const VMStateDescription vmstate_smbus_device; + +#define VMSTATE_SMBUS_DEVICE(_field, _state) { \ + .name = (stringify(_field)), \ + .size = sizeof(SMBusDevice), \ + .vmsd = &vmstate_smbus_device, \ + .flags = VMS_STRUCT, \ + .offset = vmstate_offset_value(_state, _field, SMBusDevice), \ +} + +/* + * Users should call this in their .needed functions to know if the + * SMBus slave data needs to be transferred. + */ +bool smbus_vmstate_needed(SMBusDevice *dev); + #endif -- cgit v1.2.3