static int sdw_handle_port_interrupt()

in bus.c [1422:1493]


static int sdw_handle_port_interrupt(struct sdw_slave *slave,
				     int port, u8 *slave_status)
{
	u8 clear, impl_int_mask;
	int status, status2, ret, count = 0;
	u32 addr;

	if (port == 0)
		return sdw_handle_dp0_interrupt(slave, slave_status);

	addr = SDW_DPN_INT(port);
	status = sdw_read_no_pm(slave, addr);
	if (status < 0) {
		dev_err(&slave->dev,
			"SDW_DPN_INT read failed:%d\n", status);

		return status;
	}

	do {
		clear = status & ~SDW_DPN_INTERRUPTS;

		if (status & SDW_DPN_INT_TEST_FAIL) {
			dev_err(&slave->dev, "Test fail for port:%d\n", port);
			clear |= SDW_DPN_INT_TEST_FAIL;
		}

		/*
		 * Assumption: PORT_READY interrupt will be received only
		 * for ports implementing CP_SM.
		 */
		if (status & SDW_DPN_INT_PORT_READY) {
			complete(&slave->port_ready[port]);
			clear |= SDW_DPN_INT_PORT_READY;
		}

		impl_int_mask = SDW_DPN_INT_IMPDEF1 |
			SDW_DPN_INT_IMPDEF2 | SDW_DPN_INT_IMPDEF3;

		if (status & impl_int_mask) {
			clear |= impl_int_mask;
			*slave_status = clear;
		}

		/* clear the interrupt but don't touch reserved fields */
		ret = sdw_write_no_pm(slave, addr, clear);
		if (ret < 0) {
			dev_err(&slave->dev,
				"SDW_DPN_INT write failed:%d\n", ret);
			return ret;
		}

		/* Read DPN interrupt again */
		status2 = sdw_read_no_pm(slave, addr);
		if (status2 < 0) {
			dev_err(&slave->dev,
				"SDW_DPN_INT read failed:%d\n", status2);
			return status2;
		}
		/* filter to limit loop to interrupts identified in the first status read */
		status &= status2;

		count++;

		/* we can get alerts while processing so keep retrying */
	} while ((status & SDW_DPN_INTERRUPTS) && (count < SDW_READ_INTR_CLEAR_RETRY));

	if (count == SDW_READ_INTR_CLEAR_RETRY)
		dev_warn(&slave->dev, "Reached MAX_RETRY on port read");

	return ret;
}