aux_create_slave() calls qdev_init_nofail() which in turn "realizes" the corresponding object. This is unlike qdev_create(), and it is wrong because qdev_init_nofail() must not be called from an instance_init function. Move qdev_init_nofail() and the subsequent aux_map_slave into the caller's realize function. There are two more bugs that needs to be fixed here, too, where the objects are created but not added as children. Therefore when you call object_unparent on them, nothing happens. In particular dpcd and edid give you an infinite loop in bus_unparent, because device_unparent is not called and does not remove them from the list of devices on the bus. Reported-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Thomas Huth <thuth@redhat.com> Message-id: 1531745974-17187-17-git-send-email-thuth@redhat.com [thuth: Added Paolo's fixup for the dpcd and edid unparenting] Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
141 lines
3.4 KiB
C
141 lines
3.4 KiB
C
/*
|
|
* auxbus.h
|
|
*
|
|
* Copyright (C)2014 : GreenSocs Ltd
|
|
* http://www.greensocs.com/ , email: info@greensocs.com
|
|
*
|
|
* Developed by :
|
|
* Frederic Konrad <fred.konrad@greensocs.com>
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#ifndef HW_MISC_AUXBUS_H
|
|
#define HW_MISC_AUXBUS_H
|
|
|
|
#include "hw/qdev.h"
|
|
|
|
typedef struct AUXBus AUXBus;
|
|
typedef struct AUXSlave AUXSlave;
|
|
typedef enum AUXCommand AUXCommand;
|
|
typedef enum AUXReply AUXReply;
|
|
typedef struct AUXTOI2CState AUXTOI2CState;
|
|
|
|
enum AUXCommand {
|
|
WRITE_I2C = 0,
|
|
READ_I2C = 1,
|
|
WRITE_I2C_STATUS = 2,
|
|
WRITE_I2C_MOT = 4,
|
|
READ_I2C_MOT = 5,
|
|
WRITE_AUX = 8,
|
|
READ_AUX = 9
|
|
};
|
|
|
|
enum AUXReply {
|
|
AUX_I2C_ACK = 0,
|
|
AUX_NACK = 1,
|
|
AUX_DEFER = 2,
|
|
AUX_I2C_NACK = 4,
|
|
AUX_I2C_DEFER = 8
|
|
};
|
|
|
|
#define TYPE_AUX_BUS "aux-bus"
|
|
#define AUX_BUS(obj) OBJECT_CHECK(AUXBus, (obj), TYPE_AUX_BUS)
|
|
|
|
struct AUXBus {
|
|
/* < private > */
|
|
BusState qbus;
|
|
|
|
/* < public > */
|
|
AUXSlave *current_dev;
|
|
AUXSlave *dev;
|
|
uint32_t last_i2c_address;
|
|
AUXCommand last_transaction;
|
|
|
|
AUXTOI2CState *bridge;
|
|
|
|
MemoryRegion *aux_io;
|
|
AddressSpace aux_addr_space;
|
|
};
|
|
|
|
#define TYPE_AUX_SLAVE "aux-slave"
|
|
#define AUX_SLAVE(obj) \
|
|
OBJECT_CHECK(AUXSlave, (obj), TYPE_AUX_SLAVE)
|
|
|
|
struct AUXSlave {
|
|
/* < private > */
|
|
DeviceState parent_obj;
|
|
|
|
/* < public > */
|
|
MemoryRegion *mmio;
|
|
};
|
|
|
|
/**
|
|
* aux_init_bus: Initialize an AUX bus.
|
|
*
|
|
* Returns the new AUX bus created.
|
|
*
|
|
* @parent The device where this bus is located.
|
|
* @name The name of the bus.
|
|
*/
|
|
AUXBus *aux_init_bus(DeviceState *parent, const char *name);
|
|
|
|
/*
|
|
* aux_request: Make a request on the bus.
|
|
*
|
|
* Returns the reply of the request.
|
|
*
|
|
* @bus Ths bus where the request happen.
|
|
* @cmd The command requested.
|
|
* @address The 20bits address of the slave.
|
|
* @len The length of the read or write.
|
|
* @data The data array which will be filled or read during transfer.
|
|
*/
|
|
AUXReply aux_request(AUXBus *bus, AUXCommand cmd, uint32_t address,
|
|
uint8_t len, uint8_t *data);
|
|
|
|
/*
|
|
* aux_get_i2c_bus: Get the i2c bus for I2C over AUX command.
|
|
*
|
|
* Returns the i2c bus associated to this AUX bus.
|
|
*
|
|
* @bus The AUX bus.
|
|
*/
|
|
I2CBus *aux_get_i2c_bus(AUXBus *bus);
|
|
|
|
/*
|
|
* aux_init_mmio: Init an mmio for an AUX slave.
|
|
*
|
|
* @aux_slave The AUX slave.
|
|
* @mmio The mmio to be registered.
|
|
*/
|
|
void aux_init_mmio(AUXSlave *aux_slave, MemoryRegion *mmio);
|
|
|
|
/* aux_create_slave: Create a new device on an AUX bus
|
|
*
|
|
* @bus The AUX bus for the new device.
|
|
* @name The type of the device to be created.
|
|
*/
|
|
DeviceState *aux_create_slave(AUXBus *bus, const char *name);
|
|
|
|
/* aux_map_slave: Map the mmio for an AUX slave on the bus.
|
|
*
|
|
* @dev The AUX slave.
|
|
* @addr The address for the slave's mmio.
|
|
*/
|
|
void aux_map_slave(AUXSlave *dev, hwaddr addr);
|
|
|
|
#endif /* HW_MISC_AUXBUS_H */
|