/** * mei_txe_read - reads a message from the txe device. * * @dev: the device structure * @buf: message buffer will be written * @len: message size will be read * * returns -EINVAL on error wrong argument and 0 on success */ static int mei_txe_read(struct mei_device *dev, unsigned char *buf, unsigned long len) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 i; u32 *reg_buf = (u32 *)buf; u32 rem = len & 0x3; if (WARN_ON(!buf || !len)) return -EINVAL; dev_dbg(&dev->pdev->dev, "buffer-length = %lu buf[0]0x%08X\n", len, mei_txe_out_data_read(dev, 0)); for (i = 0; i < len / 4; i++) { /* skip header: index starts from 1 */ u32 reg = mei_txe_out_data_read(dev, i + 1); dev_dbg(&dev->pdev->dev, "buf[%d] = 0x%08X\n", i, reg); *reg_buf++ = reg; } if (rem) { u32 reg = mei_txe_out_data_read(dev, i + 1); memcpy(reg_buf, ®, rem); } mei_txe_output_ready_set(hw); return 0; }
/** * 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; }