@@ -159,8 +159,13 @@ static uint8_t pca954x_read_byte(SMBusDevice *d)
static void pca954x_enter_reset(Object *obj, ResetType type)
{
Pca954xState *s = PCA954X(obj);
+ Pca954xClass *pc = PCA954X_GET_CLASS(obj);
+
/* Reset will disable all channels. */
pca954x_write(s, 0);
+ if (pc->parent.parent_phases.enter) {
+ pc->parent.parent_phases.enter(obj, type);
+ }
}
I2CBus *pca954x_i2c_get_bus(I2CSlave *mux, uint8_t channel)
@@ -212,8 +212,11 @@ static void smbus_device_class_init(ObjectClass *klass, void *data)
{
I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
+ SMBusDeviceClass *sdc = SMBUS_DEVICE_CLASS(klass);
rc->phases.enter = smbus_device_enter_reset;
+ resettable_class_set_parent_phases(rc, smbus_device_enter_reset, NULL, NULL,
+ &sdc->parent_phases);
sc->event = smbus_i2c_event;
sc->recv = smbus_i2c_recv;
sc->send = smbus_i2c_send;
@@ -35,6 +35,7 @@ OBJECT_DECLARE_TYPE(SMBusDevice, SMBusDeviceClass,
struct SMBusDeviceClass {
I2CSlaveClass parent_class;
+ ResettablePhases parent_phases;
/*
* An operation with no data, special in SMBus.
When a reset happens, both the SMBusDevice and PCA954x class do their variable resetting on an enter reset. Because of this, only the PCA954x has its reset called, which can leave the SMBusDevice in a bad state if it was in the middle of a transaction. To fix this we add parent reset functions for the SMBusDevice class, and have the mux class invoke it when it resets. Signed-off-by: Joe Komlodi <komlodi@google.com> --- hw/i2c/i2c_mux_pca954x.c | 5 +++++ hw/i2c/smbus_slave.c | 3 +++ include/hw/i2c/smbus_slave.h | 1 + 3 files changed, 9 insertions(+)