in cadence_master.c [780:858]
static int cdns_update_slave_status(struct sdw_cdns *cdns,
u64 slave_intstat)
{
enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
bool is_slave = false;
u32 mask;
int i, set_status;
memset(status, 0, sizeof(status));
for (i = 0; i <= SDW_MAX_DEVICES; i++) {
mask = (slave_intstat >> (i * CDNS_MCP_SLAVE_STATUS_NUM)) &
CDNS_MCP_SLAVE_STATUS_BITS;
if (!mask)
continue;
is_slave = true;
set_status = 0;
if (mask & CDNS_MCP_SLAVE_INTSTAT_RESERVED) {
status[i] = SDW_SLAVE_RESERVED;
set_status++;
}
if (mask & CDNS_MCP_SLAVE_INTSTAT_ATTACHED) {
status[i] = SDW_SLAVE_ATTACHED;
set_status++;
}
if (mask & CDNS_MCP_SLAVE_INTSTAT_ALERT) {
status[i] = SDW_SLAVE_ALERT;
set_status++;
}
if (mask & CDNS_MCP_SLAVE_INTSTAT_NPRESENT) {
status[i] = SDW_SLAVE_UNATTACHED;
set_status++;
}
/* first check if Slave reported multiple status */
if (set_status > 1) {
u32 val;
dev_warn_ratelimited(cdns->dev,
"Slave %d reported multiple Status: %d\n",
i, mask);
/* check latest status extracted from PING commands */
val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);
val >>= (i * 2);
switch (val & 0x3) {
case 0:
status[i] = SDW_SLAVE_UNATTACHED;
break;
case 1:
status[i] = SDW_SLAVE_ATTACHED;
break;
case 2:
status[i] = SDW_SLAVE_ALERT;
break;
case 3:
default:
status[i] = SDW_SLAVE_RESERVED;
break;
}
dev_warn_ratelimited(cdns->dev,
"Slave %d status updated to %d\n",
i, status[i]);
}
}
if (is_slave)
return sdw_handle_slave_status(&cdns->bus, status);
return 0;
}