Skip to content

Commit

Permalink
aspeed/i2c: Check SRAM enablement on AST2500
Browse files Browse the repository at this point in the history
The SRAM must be enabled before using the Buffer Pool mode or the DMA
mode. This is not required on other SoCs.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Tested-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20191119141211.25716-3-clg@kaod.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
legoater authored and pm215 committed Dec 16, 2019
1 parent 6054fc7 commit aab90b1
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
37 changes: 37 additions & 0 deletions hw/i2c/aspeed_i2c.c
Expand Up @@ -31,6 +31,8 @@
#define I2C_CTRL_STATUS 0x00 /* Device Interrupt Status */
#define I2C_CTRL_ASSIGN 0x08 /* Device Interrupt Target
Assignment */
#define I2C_CTRL_GLOBAL 0x0C /* Global Control Register */
#define I2C_CTRL_SRAM_EN BIT(0)

/* I2C Device (Bus) Register */

Expand Down Expand Up @@ -271,6 +273,29 @@ static uint8_t aspeed_i2c_get_addr(AspeedI2CBus *bus)
}
}

static bool aspeed_i2c_check_sram(AspeedI2CBus *bus)
{
AspeedI2CState *s = bus->controller;
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s);

if (!aic->check_sram) {
return true;
}

/*
* AST2500: SRAM must be enabled before using the Buffer Pool or
* DMA mode.
*/
if (!(s->ctrl_global & I2C_CTRL_SRAM_EN) &&
(bus->cmd & (I2CD_RX_DMA_ENABLE | I2CD_TX_DMA_ENABLE |
I2CD_RX_BUFF_ENABLE | I2CD_TX_BUFF_ENABLE))) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: SRAM is not enabled\n", __func__);
return false;
}

return true;
}

/*
* The state machine needs some refinement. It is only used to track
* invalid STOP commands for the moment.
Expand All @@ -282,6 +307,10 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
bus->cmd &= ~0xFFFF;
bus->cmd |= value & 0xFFFF;

if (!aspeed_i2c_check_sram(bus)) {
return;
}

if (bus->cmd & I2CD_M_START_CMD) {
uint8_t state = aspeed_i2c_get_state(bus) & I2CD_MACTIVE ?
I2CD_MSTARTR : I2CD_MSTART;
Expand Down Expand Up @@ -436,6 +465,8 @@ static uint64_t aspeed_i2c_ctrl_read(void *opaque, hwaddr offset,
switch (offset) {
case I2C_CTRL_STATUS:
return s->intr_status;
case I2C_CTRL_GLOBAL:
return s->ctrl_global;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
Expand All @@ -448,7 +479,12 @@ static uint64_t aspeed_i2c_ctrl_read(void *opaque, hwaddr offset,
static void aspeed_i2c_ctrl_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
AspeedI2CState *s = opaque;

switch (offset) {
case I2C_CTRL_GLOBAL:
s->ctrl_global = value;
break;
case I2C_CTRL_STATUS:
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
Expand Down Expand Up @@ -684,6 +720,7 @@ static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)
aic->pool_size = 0x100;
aic->pool_base = 0x200;
aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base;
aic->check_sram = true;
}

static const TypeInfo aspeed_2500_i2c_info = {
Expand Down
3 changes: 3 additions & 0 deletions include/hw/i2c/aspeed_i2c.h
Expand Up @@ -61,6 +61,7 @@ typedef struct AspeedI2CState {
qemu_irq irq;

uint32_t intr_status;
uint32_t ctrl_global;
MemoryRegion pool_iomem;
uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];

Expand All @@ -83,6 +84,8 @@ typedef struct AspeedI2CClass {
uint64_t pool_size;
hwaddr pool_base;
uint8_t *(*bus_pool_base)(AspeedI2CBus *);
bool check_sram;

} AspeedI2CClass;

I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr);
Expand Down

0 comments on commit aab90b1

Please sign in to comment.