in fsi-master-aspeed.c [149:204]
static int __opb_read(struct fsi_master_aspeed *aspeed, uint32_t addr,
u32 transfer_size, void *out)
{
void __iomem *base = aspeed->base;
u32 result, reg;
int status, ret;
/*
* The ordering of these writes up until the trigger
* write does not matter, so use writel_relaxed.
*/
writel_relaxed(CMD_READ, base + OPB0_RW);
writel_relaxed(transfer_size, base + OPB0_XFER_SIZE);
writel_relaxed(addr, base + OPB0_FSI_ADDR);
writel_relaxed(0x1, base + OPB_IRQ_CLEAR);
writel(0x1, base + OPB_TRIGGER);
ret = readl_poll_timeout(base + OPB_IRQ_STATUS, reg,
(reg & OPB0_XFER_ACK_EN) != 0,
0, OPB_POLL_TIMEOUT);
status = readl(base + OPB0_STATUS);
result = readl(base + OPB0_FSI_DATA_R);
trace_fsi_master_aspeed_opb_read(addr, transfer_size, result,
readl(base + OPB0_STATUS),
reg);
/* Return error when poll timed out */
if (ret)
return ret;
/* Command failed, master will reset */
if (status & STATUS_ERR_ACK)
return -EIO;
if (out) {
switch (transfer_size) {
case XFER_BYTE:
*(u8 *)out = result;
break;
case XFER_HALFWORD:
*(u16 *)out = result;
break;
case XFER_FULLWORD:
*(u32 *)out = result;
break;
default:
return -EINVAL;
}
}
return 0;
}