in fsi-sbefifo.c [376:442]
static int sbefifo_cleanup_hw(struct sbefifo *sbefifo)
{
struct device *dev = &sbefifo->fsi_dev->dev;
u32 up_status, down_status;
bool need_reset = false;
int rc;
rc = sbefifo_check_sbe_state(sbefifo);
if (rc) {
dev_dbg(dev, "SBE state=%d\n", rc);
return rc;
}
/* If broken, we don't need to look at status, go straight to reset */
if (sbefifo->broken)
goto do_reset;
rc = sbefifo_regr(sbefifo, SBEFIFO_UP | SBEFIFO_STS, &up_status);
if (rc) {
dev_err(dev, "Cleanup: Reading UP status failed, rc=%d\n", rc);
/* Will try reset again on next attempt at using it */
sbefifo->broken = true;
return rc;
}
rc = sbefifo_regr(sbefifo, SBEFIFO_DOWN | SBEFIFO_STS, &down_status);
if (rc) {
dev_err(dev, "Cleanup: Reading DOWN status failed, rc=%d\n", rc);
/* Will try reset again on next attempt at using it */
sbefifo->broken = true;
return rc;
}
/* The FIFO already contains a reset request from the SBE ? */
if (down_status & SBEFIFO_STS_RESET_REQ) {
dev_info(dev, "Cleanup: FIFO reset request set, resetting\n");
rc = sbefifo_regw(sbefifo, SBEFIFO_DOWN, SBEFIFO_PERFORM_RESET);
if (rc) {
sbefifo->broken = true;
dev_err(dev, "Cleanup: Reset reg write failed, rc=%d\n", rc);
return rc;
}
sbefifo->broken = false;
return 0;
}
/* Parity error on either FIFO ? */
if ((up_status | down_status) & SBEFIFO_STS_PARITY_ERR)
need_reset = true;
/* Either FIFO not empty ? */
if (!((up_status & down_status) & SBEFIFO_STS_EMPTY))
need_reset = true;
if (!need_reset)
return 0;
dev_info(dev, "Cleanup: FIFO not clean (up=0x%08x down=0x%08x)\n",
up_status, down_status);
do_reset:
/* Mark broken, will be cleared if/when reset succeeds */
return sbefifo_request_reset(sbefifo);
}