blob: 6007f7b00d73bbaf0c955bad12a3c96277e3ce91 [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright 2018-2019 NXP
*
* Brief CAAM Job Rings Hardware Abstration Layer.
* Implementation of primitives to access HW
*/
#include <caam_common.h>
#include <caam_hal_jr.h>
#include <caam_io.h>
#include <caam_pwr.h>
#include <caam_utils_delay.h>
#include <registers/ctrl_regs.h>
#include <registers/jr_regs.h>
/*
* List of common JR registers to save/restore
*/
static const struct reglist jr_backup[] = {
BACKUP_REG(JRX_IRBAR, 2, 0, 0),
BACKUP_REG(JRX_IRSR, 1, 0, 0),
BACKUP_REG(JRX_ORBAR, 2, 0, 0),
BACKUP_REG(JRX_ORSR, 1, 0, 0),
BACKUP_REG(JRX_JRCFGR_LS, 1, 0, 0),
};
enum caam_status caam_hal_jr_reset(vaddr_t baseaddr)
{
uint16_t timeout = 10000;
uint32_t reg_val = 0;
/*
* Reset is done in 2 steps:
* - Flush all pending jobs (Set RESET bit)
* - Reset the Job Ring (Set RESET bit second time)
*/
/* Mask interrupts to poll for reset completion status */
io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK);
/* Initiate flush (required prior to reset) */
io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET);
do {
caam_udelay(100);
reg_val = io_caam_read32(baseaddr + JRX_JRINTR);
reg_val &= BM_JRX_JRINTR_HALT;
} while ((reg_val == JRINTR_HALT_ONGOING) && --timeout);
if (!timeout || reg_val != JRINTR_HALT_DONE) {
EMSG("Failed to flush job ring\n");
return CAAM_FAILURE;
}
/* Initiate reset */
timeout = 100;
io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET);
do {
caam_udelay(100);
reg_val = io_caam_read32(baseaddr + JRX_JRCR);
} while ((reg_val & JRX_JRCR_RESET) && --timeout);
if (!timeout) {
EMSG("Failed to reset job ring\n");
return CAAM_FAILURE;
}
return CAAM_NO_ERROR;
}
void caam_hal_jr_config(vaddr_t baseaddr, uint8_t nbjobs, uint64_t inrings,
uint64_t outrings)
{
uint32_t value = 0;
/* Setup the JR input queue */
io_caam_write32(baseaddr + JRX_IRBAR, inrings >> 32);
io_caam_write32(baseaddr + JRX_IRBAR + 4, inrings);
io_caam_write32(baseaddr + JRX_IRSR, nbjobs);
/* Setup the JR output queue */
io_caam_write32(baseaddr + JRX_ORBAR, outrings >> 32);
io_caam_write32(baseaddr + JRX_ORBAR + 4, outrings);
io_caam_write32(baseaddr + JRX_ORSR, nbjobs);
/* Disable the JR interrupt */
caam_hal_jr_disable_itr(baseaddr);
/*
* Configure interrupt and disable it:
* Optimization to generate an interrupt either when there are
* half of the job done
* or when there is a job done and 10 clock cycles elapsed without
* new job completion
*/
value = JRX_JRCFGR_LS_ICTT(10);
value |= JRX_JRCFGR_LS_ICDCT(nbjobs / 2);
value |= JRX_JRCFGR_LS_ICEN;
value |= JRX_JRCFGR_LS_IMSK;
io_caam_write32(baseaddr + JRX_JRCFGR_LS, value);
#ifdef CFG_NXP_CAAM_RUNTIME_JR
caam_pwr_add_backup(baseaddr, jr_backup, ARRAY_SIZE(jr_backup));
#endif
}
uint32_t caam_hal_jr_read_nbslot_available(vaddr_t baseaddr)
{
return io_caam_read32(baseaddr + JRX_IRSAR);
}
void caam_hal_jr_add_newjob(vaddr_t baseaddr)
{
io_caam_write32(baseaddr + JRX_IRJAR, 1);
}
uint32_t caam_hal_jr_get_nbjob_done(vaddr_t baseaddr)
{
return io_caam_read32(baseaddr + JRX_ORSFR);
}
void caam_hal_jr_del_job(vaddr_t baseaddr)
{
io_caam_write32(baseaddr + JRX_ORJRR, 1);
}
void caam_hal_jr_disable_itr(vaddr_t baseaddr)
{
io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK);
io_setbits32(baseaddr + JRX_JRINTR, JRX_JRINTR_JRI);
}
void caam_hal_jr_enable_itr(vaddr_t baseaddr)
{
io_mask32(baseaddr + JRX_JRCFGR_LS, ~JRX_JRCFGR_LS_IMSK,
JRX_JRCFGR_LS_IMSK);
}
bool caam_hal_jr_check_ack_itr(vaddr_t baseaddr)
{
uint32_t val = 0;
val = io_caam_read32(baseaddr + JRX_JRINTR);
if ((val & JRX_JRINTR_JRI) == JRX_JRINTR_JRI) {
/* Acknowledge interrupt */
io_setbits32(baseaddr + JRX_JRINTR, JRX_JRINTR_JRI);
return true;
}
return false;
}
enum caam_status caam_hal_jr_halt(vaddr_t baseaddr)
{
uint16_t timeout = 10000;
uint32_t val = 0;
/* Mask interrupts to poll for completion status */
io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK);
/* Request Job ring halt */
io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_PARK);
/* Check if there is a job running */
val = io_caam_read32(baseaddr + JRX_IRSR);
if ((caam_hal_jr_read_nbslot_available(baseaddr) == val) &&
(io_caam_read32(baseaddr + JRX_CSTA) != JRX_CSTA_BSY))
return CAAM_NO_ERROR;
/* Wait until all jobs complete */
do {
caam_udelay(10);
val = io_caam_read32(baseaddr + JRX_JRINTR);
val &= BM_JRX_JRINTR_HALT;
} while ((val != JRINTR_HALT_DONE) && --timeout);
if (!timeout)
return CAAM_BUSY;
return CAAM_NO_ERROR;
}
enum caam_status caam_hal_jr_flush(vaddr_t baseaddr)
{
uint16_t timeout = 10000;
uint32_t val = 0;
/* Mask interrupts to poll for completion status */
io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK);
/* Request Job ring to flush input queue */
io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET);
/* Check if there is a job running */
val = io_caam_read32(baseaddr + JRX_IRSR);
if ((caam_hal_jr_read_nbslot_available(baseaddr) == val) &&
(io_caam_read32(baseaddr + JRX_CSTA) != JRX_CSTA_BSY))
return CAAM_NO_ERROR;
/* Wait until all jobs complete */
do {
caam_udelay(10);
val = io_caam_read32(baseaddr + JRX_JRINTR);
val &= BM_JRX_JRINTR_HALT;
} while ((val == JRINTR_HALT_DONE) && --timeout);
if (!timeout)
return CAAM_BUSY;
return CAAM_NO_ERROR;
}
void caam_hal_jr_resume(vaddr_t baseaddr)
{
io_caam_write32(baseaddr + JRX_JRINTR, JRINTR_HALT_RESUME);
caam_hal_jr_enable_itr(baseaddr);
}
uint8_t caam_hal_jr_input_index(vaddr_t baseaddr)
{
return io_caam_read32(baseaddr + JRX_IRRIR) >> 2;
}
uint8_t caam_hal_jr_output_index(vaddr_t baseaddr)
{
return io_caam_read32(baseaddr + JRX_ORWIR) >> 3;
}