コード例 #1
0
ファイル: hw-txe.c プロジェクト: forgivemyheart/linux
/**
 * mei_txe_check_and_ack_intrs - translate multi BAR interrupt into
 *  single bit mask and acknowledge the interrupts
 *
 * @dev: the device structure
 * @do_ack: acknowledge interrupts
 *
 * Return: true if found interrupts to process.
 */
static bool mei_txe_check_and_ack_intrs(struct mei_device *dev, bool do_ack)
{
	struct mei_txe_hw *hw = to_txe_hw(dev);
	u32 hisr;
	u32 hhisr;
	u32 ipc_isr;
	u32 aliveness;
	bool generated;

	/* read interrupt registers */
	hhisr = mei_txe_br_reg_read(hw, HHISR_REG);
	generated = (hhisr & IPC_HHIER_MSK);
	if (!generated)
		goto out;

	hisr = mei_txe_br_reg_read(hw, HISR_REG);

	aliveness = mei_txe_aliveness_get(dev);
	if (hhisr & IPC_HHIER_SEC && aliveness) {
		ipc_isr = mei_txe_sec_reg_read_silent(hw,
				SEC_IPC_HOST_INT_STATUS_REG);
	} else {
		ipc_isr = 0;
		hhisr &= ~IPC_HHIER_SEC;
	}

	generated = generated ||
		(hisr & HISR_INT_STS_MSK) ||
		(ipc_isr & SEC_IPC_HOST_INT_STATUS_PENDING);

	if (generated && do_ack) {
		/* Save the interrupt causes */
		hw->intr_cause |= hisr & HISR_INT_STS_MSK;
		if (ipc_isr & SEC_IPC_HOST_INT_STATUS_IN_RDY)
			hw->intr_cause |= TXE_INTR_IN_READY;


		mei_txe_intr_disable(dev);
		/* Clear the interrupts in hierarchy:
		 * IPC and Bridge, than the High Level */
		mei_txe_sec_reg_write_silent(hw,
			SEC_IPC_HOST_INT_STATUS_REG, ipc_isr);
		mei_txe_br_reg_write(hw, HISR_REG, hisr);
		mei_txe_br_reg_write(hw, HHISR_REG, hhisr);
	}

out:
	return generated;
}
コード例 #2
0
ファイル: hw-txe.c プロジェクト: AkyZero/wrapfs-latest
/**
 * mei_txe_out_data_read - read dword from the device buffer
 *	at offset idx
 *
 * @dev: the device structure
 * @idx: index in the device buffer
 *
 * returns register value at index
 */
static u32 mei_txe_out_data_read(const struct mei_device *dev,
					unsigned long idx)
{
	struct mei_txe_hw *hw = to_txe_hw(dev);
	return mei_txe_br_reg_read(hw,
		BRIDGE_IPC_OUTPUT_PAYLOAD_REG + (idx * sizeof(u32)));
}
コード例 #3
0
ファイル: hw-txe.c プロジェクト: AkyZero/wrapfs-latest
/**
 * mei_txe_aliveness_get - get aliveness response register value
 * @dev: the device structure
 *
 * Extract HICR_HOST_ALIVENESS_RESP_ACK bit
 * from HICR_HOST_ALIVENESS_RESP register value
 */
static u32 mei_txe_aliveness_get(struct mei_device *dev)
{
	struct mei_txe_hw *hw = to_txe_hw(dev);
	u32 reg;
	reg = mei_txe_br_reg_read(hw, HICR_HOST_ALIVENESS_RESP_REG);
	return reg & HICR_HOST_ALIVENESS_RESP_ACK;
}
コード例 #4
0
ファイル: hw-txe.c プロジェクト: AkyZero/wrapfs-latest
/**
 * mei_txe_aliveness_req_get - get aliveness requested register value
 *
 * @dev: the device structure
 *
 * Extract HICR_HOST_ALIVENESS_RESP_ACK bit from
 * from HICR_HOST_ALIVENESS_REQ register value
 */
static u32 mei_txe_aliveness_req_get(struct mei_device *dev)
{
	struct mei_txe_hw *hw = to_txe_hw(dev);
	u32 reg;
	reg = mei_txe_br_reg_read(hw, SICR_HOST_ALIVENESS_REQ_REG);
	return reg & SICR_HOST_ALIVENESS_REQ_REQUESTED;
}
コード例 #5
0
ファイル: hw-txe.c プロジェクト: acton393/linux
/**
 * mei_txe_host_is_ready - check if the host is ready
 *
 * @dev: the device structure
 *
 * Return: true if host is ready
 */
static inline bool mei_txe_host_is_ready(struct mei_device *dev)
{
	struct mei_txe_hw *hw = to_txe_hw(dev);
	u32 reg = mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG);

	return !!(reg & HICR_SEC_IPC_READINESS_HOST_RDY);
}
コード例 #6
0
ファイル: hw-txe.c プロジェクト: acton393/linux
/**
 * mei_txe_hw_start - start the hardware after reset
 *
 * @dev: the device structure
 *
 * Return: 0 on success an error code otherwise
 */
static int mei_txe_hw_start(struct mei_device *dev)
{
	struct mei_txe_hw *hw = to_txe_hw(dev);
	int ret;

	u32 hisr;

	/* bring back interrupts */
	mei_txe_intr_enable(dev);

	ret = mei_txe_readiness_wait(dev);
	if (ret < 0) {
		dev_err(dev->dev, "waiting for readiness failed\n");
		return ret;
	}

	/*
	 * If HISR.INT2_STS interrupt status bit is set then clear it.
	 */
	hisr = mei_txe_br_reg_read(hw, HISR_REG);
	if (hisr & HISR_INT_2_STS)
		mei_txe_br_reg_write(hw, HISR_REG, HISR_INT_2_STS);

	/* Clear the interrupt cause of OutputDoorbell */
	clear_bit(TXE_INTR_OUT_DB_BIT, &hw->intr_cause);

	ret = mei_txe_aliveness_set_sync(dev, 1);
	if (ret < 0) {
		dev_err(dev->dev, "wait for aliveness failed ... bailing out\n");
		return ret;
	}

	pm_runtime_set_active(dev->dev);

	/* enable input ready interrupts:
	 * SEC_IPC_HOST_INT_MASK.IPC_INPUT_READY_INT_MASK
	 */
	mei_txe_input_ready_interrupt_enable(dev);


	/*  Set the SICR_SEC_IPC_OUTPUT_STATUS.IPC_OUTPUT_READY bit */
	mei_txe_output_ready_set(hw);

	/* Set bit SICR_HOST_IPC_READINESS.HOST_RDY
	 */
	mei_txe_readiness_set_host_rdy(dev);

	return 0;
}
コード例 #7
0
ファイル: hw-txe.c プロジェクト: AkyZero/wrapfs-latest
/**
 * mei_txe_irq_thread_handler - txe interrupt thread
 *
 * @irq: The irq number
 * @dev_id: pointer to the device structure
 *
 * returns irqreturn_t
 *
 */
irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
{
	struct mei_device *dev = (struct mei_device *) dev_id;
	struct mei_txe_hw *hw = to_txe_hw(dev);
	struct mei_cl_cb complete_list;
	s32 slots;
	int rets = 0;

	dev_dbg(&dev->pdev->dev, "irq thread: Interrupt Registers HHISR|HISR|SEC=%02X|%04X|%02X\n",
		mei_txe_br_reg_read(hw, HHISR_REG),
		mei_txe_br_reg_read(hw, HISR_REG),
		mei_txe_sec_reg_read_silent(hw, SEC_IPC_HOST_INT_STATUS_REG));


	/* initialize our complete list */
	mutex_lock(&dev->device_lock);
	mei_io_list_init(&complete_list);

	if (pci_dev_msi_enabled(dev->pdev))
		mei_txe_check_and_ack_intrs(dev, true);

	/* show irq events */
	mei_txe_pending_interrupts(dev);

	hw->aliveness = mei_txe_aliveness_get(dev);
	hw->readiness = mei_txe_readiness_get(dev);

	/* Readiness:
	 * Detection of TXE driver going through reset
	 * or TXE driver resetting the HECI interface.
	 */
	if (test_and_clear_bit(TXE_INTR_READINESS_BIT, &hw->intr_cause)) {
		dev_dbg(&dev->pdev->dev, "Readiness Interrupt was received...\n");

		/* Check if SeC is going through reset */
		if (mei_txe_readiness_is_sec_rdy(hw->readiness)) {
			dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
			dev->recvd_hw_ready = true;
		} else {
			dev->recvd_hw_ready = false;
			if (dev->dev_state != MEI_DEV_RESETTING) {

				dev_warn(&dev->pdev->dev, "FW not ready: resetting.\n");
				schedule_work(&dev->reset_work);
				goto end;

			}
		}
		wake_up(&dev->wait_hw_ready);
	}

	/************************************************************/
	/* Check interrupt cause:
	 * Aliveness: Detection of SeC acknowledge of host request that
	 * it remain alive or host cancellation of that request.
	 */

	if (test_and_clear_bit(TXE_INTR_ALIVENESS_BIT, &hw->intr_cause)) {
		/* Clear the interrupt cause */
		dev_dbg(&dev->pdev->dev,
			"Aliveness Interrupt: Status: %d\n", hw->aliveness);
		dev->pg_event = MEI_PG_EVENT_RECEIVED;
		if (waitqueue_active(&hw->wait_aliveness_resp))
			wake_up(&hw->wait_aliveness_resp);
	}


	/* Output Doorbell:
	 * Detection of SeC having sent output to host
	 */
	slots = mei_count_full_read_slots(dev);
	if (test_and_clear_bit(TXE_INTR_OUT_DB_BIT, &hw->intr_cause)) {
		/* Read from TXE */
		rets = mei_irq_read_handler(dev, &complete_list, &slots);
		if (rets && dev->dev_state != MEI_DEV_RESETTING) {
			dev_err(&dev->pdev->dev,
				"mei_irq_read_handler ret = %d.\n", rets);

			schedule_work(&dev->reset_work);
			goto end;
		}
	}
	/* Input Ready: Detection if host can write to SeC */
	if (test_and_clear_bit(TXE_INTR_IN_READY_BIT, &hw->intr_cause)) {
		dev->hbuf_is_ready = true;
		hw->slots = dev->hbuf_depth;
	}

	if (hw->aliveness && dev->hbuf_is_ready) {
		/* get the real register value */
		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
		rets = mei_irq_write_handler(dev, &complete_list);
		if (rets && rets != -EMSGSIZE)
			dev_err(&dev->pdev->dev, "mei_irq_write_handler ret = %d.\n",
				rets);
		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
	}

	mei_irq_compl_handler(dev, &complete_list);

end:
	dev_dbg(&dev->pdev->dev, "interrupt thread end ret = %d\n", rets);

	mutex_unlock(&dev->device_lock);

	mei_enable_interrupts(dev);
	return IRQ_HANDLED;
}
コード例 #8
0
ファイル: hw-txe.c プロジェクト: AkyZero/wrapfs-latest
/**
 * mei_txe_readiness_get - Reads and returns
 *	the HICR_SEC_IPC_READINESS register value
 *
 * @dev: the device structure
 */
static u32 mei_txe_readiness_get(struct mei_device *dev)
{
	struct mei_txe_hw *hw = to_txe_hw(dev);
	return mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG);
}