in hisi-spmi-controller.c [187:261]
static int spmi_write_cmd(struct spmi_controller *ctrl,
u8 opc, u8 slave_id, u16 slave_addr, const u8 *__buf, size_t bc)
{
struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev);
u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel;
const u8 *buf = __buf;
unsigned long flags;
u32 cmd, data;
int rc;
u8 op_code, i;
if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
dev_err(&ctrl->dev,
"spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
return -EINVAL;
}
switch (opc) {
case SPMI_CMD_WRITE:
op_code = SPMI_CMD_REG_WRITE;
break;
case SPMI_CMD_EXT_WRITE:
op_code = SPMI_CMD_EXT_REG_WRITE;
break;
case SPMI_CMD_EXT_WRITEL:
op_code = SPMI_CMD_EXT_REG_WRITE_L;
break;
default:
dev_err(&ctrl->dev, "invalid write cmd 0x%x\n", opc);
return -EINVAL;
}
cmd = SPMI_APB_SPMI_CMD_EN |
(op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |
((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |
((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) |
((slave_addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET);
/* Write data to FIFOs */
spin_lock_irqsave(&spmi_controller->lock, flags);
for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) {
data = 0;
if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) {
memcpy(&data, buf, sizeof(data));
buf += sizeof(data);
} else {
memcpy(&data, buf, bc % SPMI_PER_DATAREG_BYTE);
buf += (bc % SPMI_PER_DATAREG_BYTE);
}
writel((u32 __force)cpu_to_be32(data),
spmi_controller->base + chnl_ofst +
SPMI_APB_SPMI_WDATA0_BASE_ADDR +
SPMI_PER_DATAREG_BYTE * i);
}
/* Start the transaction */
writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR);
rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller,
spmi_controller->base, slave_id,
slave_addr);
spin_unlock_irqrestore(&spmi_controller->lock, flags);
if (rc)
dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n",
opc, slave_id, slave_addr, bc);
else
dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, wrote value: %*ph\n",
__func__, slave_id, slave_addr, (int)bc, __buf);
return rc;
}