Files
luban-lite-t3e-pro/bsp/artinchip/hal/spienc/hal_spienc.c
刘可亮 803cac77d5 V1.0.6
2024-09-03 11:16:08 +08:00

182 lines
4.2 KiB
C

/*
* Copyright (c) 2023, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Hao Xiong <hao.xiong@artinchip.com>
*/
#include <aic_core.h>
#include <aic_hal.h>
#include <hal_spienc.h>
#define SPIE_REG_CTL 0x00
#define SPIE_REG_ICR 0x04
#define SPIE_REG_ISR 0x08
#define SPIE_REG_KCNT 0x0C
#define SPIE_REG_OCNT 0x10
#define SPIE_REG_ADDR 0x14
#define SPIE_REG_TWEAK 0x18
#define SPIE_REG_CPOS 0x1C
#define SPIE_REG_CLEN 0x20
#define SPIE_START_OFF 0
#define SPIE_SPI_SEL_OFF 12
#define SPIE_START_MSK (0x1 << SPIE_START_OFF)
#define SPIE_SPI_SEL_MSK (0x3 << SPIE_SPI_SEL_OFF)
#define SPIE_INTR_KEY_GEN_MSK (1 << 0)
#define SPIE_INTR_ENC_DEC_FIN_MSK (1 << 1)
#define SPIE_INTR_ALL_EMP_MSK (1 << 2)
#define SPIE_INTR_HALF_EMP_MSK (1 << 3)
#define SPIE_INTR_KEY_UDF_MSK (1 << 4)
#define SPIE_INTR_KEY_OVF_MSK (1 << 5)
#define SPIE_INTR_ALL_MSK (0x3F)
#define SPI_CTLR_0 0
#define SPI_CTLR_1 1
#define SPI_CTLR_SE 5
#define SPI_CTLR_INVAL 0xFF
static int bypass = 0;
static int tweak_sel = AIC_SPIENC_USER_TWEAK;
static int hal_spienc_attach_bus(u8 bus)
{
u32 val;
val = readl(SPI_ENC_BASE + SPIE_REG_CTL);
val &= ~SPIE_SPI_SEL_MSK;
switch (bus) {
#if defined(AIC_SPIENC_QSPI0)
case SPI_CTLR_0:
val |= (1 << SPIE_SPI_SEL_OFF);
writel(val, (SPI_ENC_BASE + SPIE_REG_CTL));
break;
#endif
#if defined(AIC_SPIENC_QSPI1)
case SPI_CTLR_1:
val |= (2 << SPIE_SPI_SEL_OFF);
writel(val, (SPI_ENC_BASE + SPIE_REG_CTL));
break;
#endif
#if defined(AIC_USING_SE_SPI)
case SPI_CTLR_SE:
val |= (1 << SPIE_SPI_SEL_OFF);
writel(val, (SPI_ENC_BASE + SPIE_REG_CTL));
break;
#endif
case SPI_CTLR_INVAL:
val |= (0 << SPIE_SPI_SEL_OFF);
writel(val, (SPI_ENC_BASE + SPIE_REG_CTL));
break;
default:
val |= (0 << SPIE_SPI_SEL_OFF);
writel(val, (SPI_ENC_BASE + SPIE_REG_CTL));
hal_log_warn("SPI controller %d not enable spienc\n", bus);
return -EINVAL;
}
return 0;
}
int hal_spienc_init(void)
{
int ret = 0;
ret = hal_clk_enable(CLK_SPIENC);
if (ret < 0) {
hal_log_err("Failed to enable SID clk.\n");
return -EFAULT;
}
ret = hal_clk_enable_deassertrst(CLK_SPIENC);
if (ret < 0) {
hal_log_err("Failed to reset SID deassert.\n");
return -EFAULT;
}
/* Enable Interrupt */
writel(SPIE_INTR_ALL_MSK, (SPI_ENC_BASE + SPIE_REG_ICR));
return 0;
}
void hal_spienc_set_cfg(u32 spi_bus, u32 addr, u32 cpos, u32 clen)
{
u32 tweak = 0;
if (spi_bus == 0) {
#if defined(AIC_SPIENC_QSPI0)
tweak = AIC_SPIENC_QSPI0_TWEAK;
#endif
} else if (spi_bus == 1) {
#if defined(AIC_SPIENC_QSPI1)
tweak = AIC_SPIENC_QSPI1_TWEAK;
#endif
} else if (spi_bus == 5) {
#if defined(AIC_SPIENC_SE_SPI)
tweak = AIC_SPIENC_SE_SPI_TWEAK;
#endif
} else {
tweak = 0;
hal_log_warn("not define spi %d tweak, default(%d).\n", spi_bus, tweak);
}
if (bypass)
hal_spienc_attach_bus(0xff);
else
hal_spienc_attach_bus(spi_bus);
if (tweak_sel == AIC_SPIENC_HW_TWEAK)
tweak = 0;
writel(addr, (SPI_ENC_BASE + SPIE_REG_ADDR));
writel(cpos, (SPI_ENC_BASE + SPIE_REG_CPOS));
writel(clen, (SPI_ENC_BASE + SPIE_REG_CLEN));
writel(tweak, (SPI_ENC_BASE + SPIE_REG_TWEAK));
}
void hal_spienc_set_bypass(int status)
{
bypass = status;
}
void hal_spienc_select_tweak(int select)
{
tweak_sel = select;
}
void hal_spienc_start(void)
{
u32 val;
writel(SPIE_INTR_ALL_MSK, (SPI_ENC_BASE + SPIE_REG_ISR));
val = readl((SPI_ENC_BASE + SPIE_REG_CTL));
val |= SPIE_START_MSK;
writel(val, (SPI_ENC_BASE + SPIE_REG_CTL));
}
void hal_spienc_stop(void)
{
u32 val;
val = readl((SPI_ENC_BASE + SPIE_REG_CTL));
val &= ~SPIE_START_MSK;
writel(val, (SPI_ENC_BASE + SPIE_REG_CTL));
}
int hal_spienc_check_empty(void)
{
u32 val;
val = readl((SPI_ENC_BASE + SPIE_REG_ISR));
writel(val, (SPI_ENC_BASE + SPIE_REG_ISR));
if (val & SPIE_INTR_ALL_EMP_MSK)
return 1;
return 0;
}