static int sbefifo_cleanup_hw()

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);
}