This commit is contained in:
刘可亮
2024-10-30 16:50:31 +08:00
parent 0ef85b55da
commit 661e71562d
458 changed files with 46555 additions and 12133 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2023, ArtInChip Technology Co., Ltd
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -15,6 +15,10 @@
#include <hw_symmetric.h>
#include <hw_bignum.h>
#include <hal_ce.h>
#ifdef AIC_DCE_DRV
#include <hal_dce.h>
#include <hw_crc.h>
#endif
#define AES_BLOCK_SIZE 16
#define AES_MAX_KEY_LEN 32
@@ -649,6 +653,66 @@ static const struct hwcrypto_hash_ops hash_ops = {
.finish = drv_hash_finish,
};
#ifdef AIC_DCE_DRV
#define CRC_32_POLY 0x04C11DB7
rt_err_t drv_crc_init(struct rt_hwcrypto_ctx *ctx)
{
rt_err_t res = RT_EOK;
res = hal_dce_init();
if (res)
res = -RT_ERROR;
return res;
}
static rt_uint32_t drv_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in,
rt_size_t length)
{
rt_uint32_t crc_result = 0, ret;
if (ctx->crc_cfg.poly != CRC_32_POLY) {
pr_err("Artinchip hardware crc only support CRC_32_POLY.\n");
return -RT_ERROR;
}
if (ctx->crc_cfg.xorout)
hal_dce_crc32_xor_val(ctx->crc_cfg.xorout);
if (ctx->crc_cfg.flags)
hal_dce_crc32_cfg((ctx->crc_cfg.flags & CRC_FLAG_REFIN), 0,
(ctx->crc_cfg.flags & CRC_FLAG_REFIN),
(ctx->crc_cfg.flags & CRC_FLAG_REFOUT));
hal_dce_crc32_start(ctx->crc_cfg.last_val, (u8 *)in, length);
ret = hal_dce_crc32_wait();
if (!ret) {
crc_result = hal_dce_crc32_result();
} else {
pr_err("\t%s error: time out\n", __func__);
return -RT_ERROR;
}
ctx->crc_cfg.last_val = crc_result;
return crc_result;
}
void drv_crc_uninit(struct rt_hwcrypto_ctx *ctx)
{
if (!ctx)
return;
if (ctx->contex) {
aicos_free_align(0, ctx->contex);
ctx->contex = NULL;
}
hal_dce_deinit();
}
static const struct hwcrypto_crc_ops crc_ops = {
.update = drv_crc_update,
};
#endif
static rt_err_t aic_hwcrypto_create(struct rt_hwcrypto_ctx *ctx)
{
rt_err_t res = RT_EOK;
@@ -677,6 +741,12 @@ static rt_err_t aic_hwcrypto_create(struct rt_hwcrypto_ctx *ctx)
/* Setup HASH operation */
((struct hwcrypto_hash *)ctx)->ops = &hash_ops;
break;
#ifdef AIC_DCE_DRV
case HWCRYPTO_TYPE_CRC:
drv_crc_init(ctx);
((struct hwcrypto_crc *)ctx)->ops = &crc_ops;
break;
#endif
default:
res = -RT_ERROR;
break;
@@ -703,6 +773,11 @@ static void aic_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx)
case HWCRYPTO_TYPE_SHA2:
drv_sha_uninit(ctx);
break;
#ifdef AIC_DCE_DRV
case HWCRYPTO_TYPE_CRC:
drv_crc_uninit(ctx);
break;
#endif
default:
break;
}
@@ -743,7 +818,6 @@ static void aic_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx)
break;
case HWCRYPTO_TYPE_RC4:
case HWCRYPTO_TYPE_RNG:
case HWCRYPTO_TYPE_CRC:
break;
case HWCRYPTO_TYPE_BIGNUM:
drv_rsa_init(ctx);
@@ -754,6 +828,11 @@ static void aic_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx)
drv_sha_init(ctx);
drv_sha_start(ctx);
break;
#ifdef AIC_DCE_DRV
case HWCRYPTO_TYPE_CRC:
drv_crc_init(ctx);
break;
#endif
default:
break;
}

View File

@@ -3,7 +3,7 @@
#-----------------------------
menu "CIR protocol select"
depends on AIC_USING_CIR
depends on (AIC_USING_CIR || AIC_USING_R_CIR)
config AIC_CIR_NEC
bool "NEC protocol"

View File

@@ -180,6 +180,15 @@ int rt_hw_aic_cir_init(void)
aic_cir_dev.dev.type = RT_Device_Class_Char;
#endif
#ifdef AIC_USING_R_CIR
aic_cir_dev.aic_cir_ctrl.cir_base = R_CIR_BASE;
aic_cir_dev.aic_cir_ctrl.irq_num = R_CIR_IRQn;
#else
aic_cir_dev.aic_cir_ctrl.cir_base = CIR_BASE;
aic_cir_dev.aic_cir_ctrl.irq_num = CIR_IRQn;
#endif
aic_cir_dev.aic_cir_ctrl.clk_idx = CLK_CIR;
rt_mutex_init(&aic_cir_dev.lock, "cir_mutex", RT_IPC_FLAG_PRIO);
rt_device_register(&aic_cir_dev.dev, "cir", 0);
LOG_I("ArtInChip CIR device register success\n");

View File

@@ -0,0 +1,3 @@
#-----------------------------
# devices local parameter
#-----------------------------

View File

@@ -0,0 +1,8 @@
/*
* Copyright (c) 2024, ArtInChip Technology CO.,LTD. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Author: Chen Junlong <junlong.chen@artinchip.com>
*/
/* do nothing, dce drv is implemented in ce drv */

View File

@@ -225,3 +225,26 @@ endif
config AIC_PANEL_SPI_EMULATION
bool
default n
config AIC_SCREEN_CROP
bool "Enable screen crop"
default n
help
Some LCD screen need to be cropped, the effective area displayed is less
than the timing signal.
If unsure select "N".
if AIC_SCREEN_CROP
config AIC_SCREEN_CROP_POS_X
int "screen crop x position of pixels"
default 0
config AIC_SCREEN_CROP_POS_Y
int "screen crop y position of pixels"
default 0
config AIC_SCREEN_CROP_WIDTH
int "screen crop width"
default 0
config AIC_SCREEN_CROP_HEIGHT
int "screen crop height"
default 0
endif

View File

@@ -21,17 +21,42 @@
/**
* lvds channel output order
*
* default D3 CK D2 D1 D0
* 4 3 2 1 0
* link 0 default D3 CK D2 D1 D0
* PD26/PD27 PD24/PD25 PD22/PD23 PD20/PD21 PD18/PD19
*
* link 1 default D3 CK D2 D1 D0
* PD16/PD17 PD14/PD15 PD12/PD13 PD10/PD11 PD8/PD9
*
*
* link 0 example:
* D2 CK D3 D1 D0
* PD26/PD27 PD24/PD25 PD22/PD23 PD20/PD21 PD18/PD19
*
* AIC_LVDS_LINK0_LANES LVDS_LANES(LVDS_D2, LVDS_CK, LVDS_D3, LVDS_D1, LVDS_D0)
* link1 example is the same as link0
*/
#define AIC_LVDS_LINK0_LANES LVDS_LANES(LVDS_D3, LVDS_CK, LVDS_D2, LVDS_D1, LVDS_D0)
#define AIC_LVDS_LINK1_LANES LVDS_LANES(LVDS_D3, LVDS_CK, LVDS_D2, LVDS_D1, LVDS_D0)
/**
* lvds channel polarities
*
* link 0 default PD26/PD27 PD24/PD25 PD22/PD23 PD20/PD21 PD18/PD19
* N/P N/P N/P N/P N/P
*
* link 1 default PD16/PD17 PD14/PD15 PD12/PD13 PD10/PD11 PD8/PD9
* N/P N/P N/P N/P N/P
*
*
* link 0 example:
* PD26/PD27 PD24/PD25 PD22/PD23 PD20/PD21 PD18/PD19
* N/P P/N N/P P/N N/P
*
* AIC_LVDS_LINK0_POL 0b01010
* link1 example is the same as link0
*/
#define AIC_LVDS_LINK0_POL 0x0
#define AIC_LVDS_LINK1_POL 0x0
#define AIC_LVDS_LINK0_POL 0b00000
#define AIC_LVDS_LINK1_POL 0b00000
/**
* lvds channel phy config
@@ -43,13 +68,41 @@
* MIPI-DSI options
*/
/* data line assignments */
/**
* data lane assignments
*
* default D3 D2 D1 D0
* PD26/PD27 PD24/PD25 PD22/PD23 PD19/PD20
*
* example D0 D1 D2 D3
* PD26/PD27 PD24/PD25 PD22/PD23 PD19/PD20
*
* LANE_ASSIGNMENTS 0x0123
*/
#define LANE_ASSIGNMENTS 0x3210
/* data line polarities */
/**
* data lane polarities
*
* default PD26/PD27 PD24/PD25 PD22/PD23 PD19/PD20
* N/P N/P N/P N/P
*
* example PD26/PD27 PD24/PD25 PD22/PD23 PD19/PD20
* P/N N/P P/N N/P
*
* LANE_POLARITIES 0b1010
*/
#define LANE_POLARITIES 0b0000
/* data clk inverse */
/**
* data clk inverse
*
* default PD24/PD25
* N/P
*
* CLK_INVERSE 1 PD24/PD25
* P/N
*/
#define CLK_INVERSE 0
/* virtual channel id */

View File

@@ -17,9 +17,11 @@
#define DE_TIMEOUT_MS 100
static unsigned int vsync_flag = 0;
static struct aic_de_comp *g_aic_de_comp;
static int aic_de_set_gamma_config(struct aicfb_gamma_config *gamma);
static int aic_de_set_ccm_config(struct aicfb_ccm_config *ccm);
static struct aic_de_comp *aic_de_request_drvdata(void)
{
return g_aic_de_comp;
@@ -38,10 +40,8 @@ static irqreturn_t aic_de_handler(int irq, void *ctx)
status = de_timing_interrupt_status(comp->regs);
de_timing_interrupt_clean_status(comp->regs, status);
if ((status & TIMING_INIT_V_BLANK_FLAG) && vsync_flag) {
vsync_flag = 0;
if (status & TIMING_INIT_V_BLANK_FLAG)
aicos_wqueue_wakeup(comp->vsync_queue);
}
if (comp->scaler_active & SCALER0_CTRL_ACTIVE) {
comp->scaler_active = comp->scaler_active & 0xF;
@@ -237,6 +237,9 @@ static int aic_de_timing_enable(void)
de_timing_enable_interrupt(comp->regs, true, TIMING_INIT_UNDERFLOW_FLAG);
#endif
aic_de_set_gamma_config(&comp->gamma);
aic_de_set_ccm_config(&comp->ccm);
de_timing_enable(comp->regs, 1);
aic_de_release_drvdata();
@@ -257,7 +260,6 @@ static int aic_de_wait_for_vsync(void)
struct aic_de_comp *comp = aic_de_request_drvdata();
int ret = 0;
vsync_flag = 1;
ret = aicos_wqueue_wait(comp->vsync_queue, DE_TIMEOUT_MS);
if (ret < 0) {
hal_log_err("DE wait vsync irq failed, ret: %d\n", ret);

View File

@@ -208,6 +208,11 @@ int config_ui_layer_rect(struct aic_de_comp *comp,
de_ui_layer_enable(comp->regs, 1);
}
#ifdef AIC_SCREEN_CROP
x_offset += AIC_SCREEN_CROP_POS_X;
y_offset += AIC_SCREEN_CROP_POS_Y;
#endif
de_ui_layer_set_rect(comp->regs, in_w, in_h, x_offset, y_offset,
stride0, addr0, layer_data->rect_id);
de_ui_layer_rect_enable(comp->regs, layer_data->rect_id, 1);

View File

@@ -746,6 +746,18 @@ static int de_vi_layer_config_format(struct aic_de_comp *comp,
return -EINVAL;
}
static void de_vi_layer_config_crop_pos(struct aic_de_comp *comp,
struct aicfb_layer_data *layer_data)
{
#ifdef AIC_SCREEN_CROP
u32 x_offset = layer_data->pos.x + AIC_SCREEN_CROP_POS_X;
u32 y_offset = layer_data->pos.y + AIC_SCREEN_CROP_POS_Y;
reg_write(comp->regs + VIDEO_LAYER_OFFSET,
VIDEO_LAYER_OFFSET_SET(x_offset, y_offset));
#endif
}
int config_video_layer(struct aic_de_comp *comp,
struct aicfb_layer_data *layer_data)
{
@@ -766,6 +778,7 @@ int config_video_layer(struct aic_de_comp *comp,
}
de_vi_layer_config_format(comp, format_info, layer_data);
de_vi_layer_config_crop_pos(comp, layer_data);
return 0;
}

View File

@@ -688,15 +688,20 @@ static void aicfb_fb_info_setup(struct aicfb_info *fbi)
fbi->fb_rotate = 0;
#endif
#ifdef AIC_SCREEN_CROP
active_w = AIC_SCREEN_CROP_WIDTH;
active_h = AIC_SCREEN_CROP_HEIGHT;
#else
active_w = fbi->panel->timings->hactive;
active_h = fbi->panel->timings->vactive;
#endif
if (fbi->fb_rotate == 90 || fbi->fb_rotate == 270)
{
active_w = fbi->panel->timings->vactive;
active_h = fbi->panel->timings->hactive;
}
else
{
active_w = fbi->panel->timings->hactive;
active_h = fbi->panel->timings->vactive;
u32 tmp = active_w;
active_w = active_h;
active_h = tmp;
}
stride = ALIGN_8B(active_w * bpp / 8);
@@ -724,8 +729,8 @@ static void fb_color_block(struct aicfb_info *fbi)
};
unsigned char *pos = (unsigned char *)fbi->fb_start;
width = fbi->panel->timings->hactive;
height = fbi->panel->timings->vactive;
width = fbi->width;
height = fbi->height;
switch (fbi->bits_per_pixel) {
#if defined(AICFB_ARGB8888) || defined(AICFB_ABGR8888) || defined(AICFB_XRGB8888)
@@ -818,7 +823,6 @@ static void aicfb_update_alpha(struct aicfb_info *fbi)
static void aicfb_update_layer(struct aicfb_info *fbi)
{
struct platform_driver *de = fbi->de;
struct aic_panel *panel = fbi->panel;
struct aicfb_layer_data layer = {0};
layer.layer_id = AICFB_LAYER_TYPE_UI;
@@ -830,11 +834,10 @@ static void aicfb_update_layer(struct aicfb_info *fbi)
switch (fbi->fb_rotate)
{
case 0:
layer.buf.size.width = panel->timings->hactive;
layer.buf.size.height = panel->timings->vactive;
layer.buf.size.width = fbi->width;
layer.buf.size.height = fbi->height;
layer.buf.stride[0] = fbi->stride;
layer.buf.phy_addr[0] = (uintptr_t)fbi->fb_start;
layer.buf.format = AICFB_FORMAT;
break;
#ifdef AIC_FB_ROTATE_EN
case 90:
@@ -843,16 +846,15 @@ static void aicfb_update_layer(struct aicfb_info *fbi)
unsigned int stride = ALIGN_8B(fbi->height * fbi->bits_per_pixel / 8);
layer.buf.phy_addr[0] = (uintptr_t)fbi->fb_start + fbi->fb_size * AIC_FB_DRAW_BUF_NUM;
layer.buf.size.width = panel->timings->hactive;
layer.buf.size.height = panel->timings->vactive;
layer.buf.size.width = fbi->height;
layer.buf.size.height = fbi->width;
layer.buf.stride[0] = stride;
break;
}
case 180:
pr_info("rotate 180\n");
layer.buf.phy_addr[0] = (uintptr_t)fbi->fb_start + fbi->fb_size * AIC_FB_DRAW_BUF_NUM;
layer.buf.size.width = panel->timings->hactive;
layer.buf.size.height = panel->timings->vactive;
layer.buf.size.width = fbi->width;
layer.buf.size.height = fbi->height;
layer.buf.stride[0] = fbi->stride;
break;
#endif

View File

@@ -2,6 +2,25 @@
# i2c devices local parameter
#-----------------------------
# soft_i2c parameter
menu "SOFT_I2C Parameter"
depends on AIC_USING_SOFT_I2C
config AIC_SOFT_I2C_SCL_PIN
string "SOFT_I2C SCL PIN"
default "PD.6"
config AIC_SOFT_I2C_SDA_PIN
string "SOFT_I2C SDA PIN"
default "PD.7"
config AIC_DEV_SOFT_I2C_DELAY_TIME
int "Setting SOFT_I2C GPIO Level Change Delay Time(us)"
default 5
endmenu
# i2c0 parameter
menu "I2C0 Parameter"

View File

@@ -117,17 +117,24 @@ struct aic_i2c_bus {
struct rt_completion cmd_complete;
};
static struct aic_i2c_bus g_aic_i2c_dev[AIC_I2C_CH_NUM];
static struct aic_i2c_bus g_aic_i2c_dev[I2C_MAX_CHAN];
irqreturn_t aic_i2c_slave_irqhandler(int irq, void * data)
{
int index = irq - I2C0_IRQn;
int i, index = 0;
uint32_t intr_stat;
uint8_t val;
uint8_t fifo_num;
struct slave_param parm;
aic_i2c_ctrl *i2c_dev;
for (i = 0; i < I2C_MAX_CHAN; i++) {
if (irq == g_aic_i2c_dev[i].aic_bus.irq_index) {
index = i;
break;
}
}
i2c_dev = &g_aic_i2c_dev[index].aic_bus;
intr_stat = hal_i2c_get_raw_interrupt_state(i2c_dev);
fifo_num = hal_i2c_get_receive_fifo_num(i2c_dev);
@@ -280,10 +287,17 @@ static void aic_i2c_handle_write(struct aic_i2c_ctrl *i2c_dev)
irqreturn_t aic_i2c_irqhandler(int irq, void * data)
{
int index = irq - I2C0_IRQn;
int i, index = 0;
uint32_t status = 0;
aic_i2c_ctrl *i2c_dev;
for (i = 0; i < I2C_MAX_CHAN; i++) {
if (irq == g_aic_i2c_dev[i].aic_bus.irq_index) {
index = i;
break;
}
}
i2c_dev = &g_aic_i2c_dev[index].aic_bus;
status = hal_i2c_get_raw_interrupt_state(i2c_dev);
/* clear all interrupt flags */
@@ -386,7 +400,7 @@ static rt_size_t aic_i2c_master_xfer(struct rt_i2c_bus_device *bus,
}
hal_i2c_module_disable(i2c_dev);
return (ret < 0) ? ret : num;
return (ret < 0) ? 0 : num;
}
#else
static rt_size_t aic_i2c_master_xfer(struct rt_i2c_bus_device *bus,

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: hjh <jiehua.huang@artinchip.com>
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <aic_core.h>
#include <stdint.h>
#include <stdbool.h>
#include <drivers/i2c-bit-ops.h>
#include "aic_hal_clk.h"
#include "aic_common.h"
#include "aic_log.h"
#define AIC_SOFT_I2C_TIMEOUT 1000
struct aic_soft_i2c_pin {
u32 sda_pin;
u32 scl_pin;
};
struct aic_soft_i2c_bus {
struct rt_i2c_bus_device bus;
struct aic_soft_i2c_pin aic_i2c_pin;
};
static struct aic_soft_i2c_bus g_aic_soft_i2c;
static void aic_soft_i2c_set_sda(void *data, rt_int32_t state)
{
rt_pin_mode(g_aic_soft_i2c.aic_i2c_pin.sda_pin, PIN_MODE_OUTPUT);
rt_pin_write(g_aic_soft_i2c.aic_i2c_pin.sda_pin, state);
}
static void aic_soft_i2c_set_scl(void *data, rt_int32_t state)
{
rt_pin_mode(g_aic_soft_i2c.aic_i2c_pin.scl_pin, PIN_MODE_OUTPUT);
rt_pin_write(g_aic_soft_i2c.aic_i2c_pin.scl_pin, state);
}
static rt_int32_t aic_soft_i2c_get_sda(void *data)
{
rt_int32_t ret;
rt_pin_mode(g_aic_soft_i2c.aic_i2c_pin.sda_pin, PIN_MODE_INPUT_PULLUP);
ret = rt_pin_read(g_aic_soft_i2c.aic_i2c_pin.sda_pin);
return ret;
}
static rt_int32_t aic_soft_i2c_get_scl(void *data)
{
rt_int32_t ret;
rt_pin_mode(g_aic_soft_i2c.aic_i2c_pin.scl_pin, PIN_MODE_INPUT_PULLUP);
ret = rt_pin_read(g_aic_soft_i2c.aic_i2c_pin.scl_pin);
return ret;
}
static void aic_soft_i2c_udelay(rt_uint32_t us)
{
aic_udelay(us);
}
struct rt_i2c_bit_ops aic_soft_i2c_ops = {
.data = NULL,
.set_sda = aic_soft_i2c_set_sda,
.set_scl = aic_soft_i2c_set_scl,
.get_sda = aic_soft_i2c_get_sda,
.get_scl = aic_soft_i2c_get_scl,
.udelay = aic_soft_i2c_udelay,
#ifdef AIC_USING_SOFT_I2C
.delay_us = AIC_DEV_SOFT_I2C_DELAY_TIME,
#endif
.timeout = AIC_SOFT_I2C_TIMEOUT,
};
static int aic_soft_i2c_register()
{
int ret = RT_EOK;
#ifdef AIC_USING_SOFT_I2C
g_aic_soft_i2c.aic_i2c_pin.sda_pin = rt_pin_get(AIC_SOFT_I2C_SDA_PIN);
g_aic_soft_i2c.aic_i2c_pin.scl_pin = rt_pin_get(AIC_SOFT_I2C_SCL_PIN);
g_aic_soft_i2c.bus.priv = &aic_soft_i2c_ops;
ret = rt_i2c_bit_add_bus(&g_aic_soft_i2c.bus, "soft_i2c");
if (ret) {
hal_log_err("register soft i2c fail\r\n");
return ret;
}
#endif
return ret;
}
INIT_DEVICE_EXPORT(aic_soft_i2c_register);

View File

@@ -1,9 +1,9 @@
/*
* Copyright (c) 2022-2023, ArtInChip Technology Co., Ltd
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Li Siyao <siyao.li@artinchip.com>
* Authors: Siyao Li <siyao.li@artinchip.com>
*/
#include <stdbool.h>
@@ -229,9 +229,16 @@ static rt_uint8_t drv_psadc_resolution(struct rt_adc_device *dev)
return 12;
}
static rt_err_t drv_psadc_convert(struct rt_adc_device *dev, rt_uint32_t ch,
rt_uint32_t *value)
{
return RT_EOK;
}
static const struct rt_adc_ops aic_adc_ops =
{
.enabled = drv_psadc_enabled,
.convert = drv_psadc_convert,
.get_resolution = drv_psadc_resolution,
.get_adc_values_poll = drv_psadc_get_adc_values_poll,
.get_adc_values = drv_psadc_get_adc_values,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Artinchip Technology Co., Ltd
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -57,7 +57,7 @@ static struct aic_qspi qspi_controller[] = {
#endif
},
#endif
#if defined(AIC_USING_QSPI1)
#if defined(AIC_USING_QSPI1) && !defined(AIC_QSPI1_BUS_SPI)
{
.name = "qspi1",
.idx = 1,
@@ -75,7 +75,7 @@ static struct aic_qspi qspi_controller[] = {
#endif
},
#endif
#if defined(AIC_USING_QSPI2)
#if defined(AIC_USING_QSPI2) && !defined(AIC_QSPI2_BUS_SPI)
{
.name = "qspi2",
.idx = 2,
@@ -93,7 +93,7 @@ static struct aic_qspi qspi_controller[] = {
#endif
},
#endif
#if defined(AIC_USING_QSPI3)
#if defined(AIC_USING_QSPI3) && !defined(AIC_QSPI3_BUS_SPI)
{
.name = "qspi3",
.idx = 3,
@@ -111,7 +111,7 @@ static struct aic_qspi qspi_controller[] = {
#endif
},
#endif
#if defined(AIC_USING_QSPI4)
#if defined(AIC_USING_QSPI4) && !defined(AIC_QSPI4_BUS_SPI)
{
.name = "qspi4",
.idx = 4,

View File

@@ -0,0 +1,455 @@
/*
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Jiji Chen <jiji.chen@artinchip.com>
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#include <aic_core.h>
#include <aic_drv.h>
#include <aic_hal.h>
#include <hal_qspi.h>
#include <hal_dma.h>
#include <aic_dma_id.h>
#include <aic_clk_id.h>
#define ASYNC_DATA_SIZE 64
struct aic_qspi {
struct rt_spi_bus dev;
char *name;
uint32_t idx;
uint32_t clk_id;
uint32_t clk_in_hz;
uint32_t dma_port_id;
uint32_t irq_num;
#if defined(AIC_QSPI_MULTIPLE_CS_NUM)
uint32_t cs_num;
#endif
qspi_master_handle handle;
struct rt_qspi_configuration configuration;
rt_sem_t xfer_sem;
bool inited;
uint32_t rxd_dlymode;
uint32_t txd_dlymode;
uint32_t txc_dlymode;
bool nonblock;
};
static struct aic_qspi spi_controller[] = {
#if defined(AIC_USING_QSPI1) && defined(AIC_QSPI1_BUS_SPI)
{
.name = "spi1",
.idx = 1,
.clk_id = CLK_QSPI1,
.clk_in_hz = AIC_DEV_QSPI1_MAX_SRC_FREQ_HZ,
.dma_port_id = DMA_ID_SPI1,
.irq_num = QSPI1_IRQn,
#if defined(AIC_QSPI_MULTIPLE_CS_NUM)
.cs_num = AIC_QSPI1_CS_NUM,
#endif
.rxd_dlymode = AIC_DEV_QSPI1_DELAY_MODE,
#if defined(AIC_QSPI_DRV_V20)
.txd_dlymode = AIC_DEV_QSPI1_TXD_DELAY_MODE,
.txc_dlymode = AIC_DEV_QSPI1_TX_CLK_DELAY_MODE,
#endif
},
#endif
#if defined(AIC_USING_QSPI2) && defined(AIC_QSPI2_BUS_SPI)
{
.name = "spi2",
.idx = 2,
.clk_id = CLK_QSPI2,
.clk_in_hz = AIC_DEV_QSPI2_MAX_SRC_FREQ_HZ,
.dma_port_id = DMA_ID_SPI2,
.irq_num = QSPI2_IRQn,
#if defined(AIC_QSPI_MULTIPLE_CS_NUM)
.cs_num = AIC_QSPI2_CS_NUM,
#endif
.rxd_dlymode = AIC_DEV_QSPI2_DELAY_MODE,
#if defined(AIC_QSPI_DRV_V20)
.txd_dlymode = AIC_DEV_QSPI2_TXD_DELAY_MODE,
.txc_dlymode = AIC_DEV_QSPI2_TX_CLK_DELAY_MODE,
#endif
},
#endif
#if defined(AIC_USING_QSPI3) && defined(AIC_QSPI3_BUS_SPI)
{
.name = "spi3",
.idx = 3,
.clk_id = CLK_QSPI3,
.clk_in_hz = AIC_DEV_QSPI3_MAX_SRC_FREQ_HZ,
.dma_port_id = DMA_ID_SPI3,
.irq_num = QSPI3_IRQn,
#if defined(AIC_QSPI_MULTIPLE_CS_NUM)
.cs_num = AIC_QSPI3_CS_NUM,
#endif
.rxd_dlymode = AIC_DEV_QSPI3_DELAY_MODE,
#if defined(AIC_QSPI_DRV_V20)
.txd_dlymode = AIC_DEV_QSPI3_TXD_DELAY_MODE,
.txc_dlymode = AIC_DEV_QSPI3_TX_CLK_DELAY_MODE,
#endif
},
#endif
#if defined(AIC_USING_QSPI4) && defined(AIC_QSPI4_BUS_SPI)
{
.name = "spi4",
.idx = 4,
.clk_id = CLK_QSPI4,
.clk_in_hz = AIC_DEV_QSPI4_MAX_SRC_FREQ_HZ,
.dma_port_id = DMA_ID_SPI4,
.irq_num = QSPI4_IRQn,
#if defined(AIC_QSPI_MULTIPLE_CS_NUM)
.cs_num = AIC_QSPI4_CS_NUM,
#endif
.rxd_dlymode = AIC_DEV_QSPI4_DELAY_MODE,
#if defined(AIC_QSPI_DRV_V20)
.txd_dlymode = AIC_DEV_QSPI4_TXD_DELAY_MODE,
.txc_dlymode = AIC_DEV_QSPI4_TX_CLK_DELAY_MODE,
#endif
},
#endif
};
static const u32 bit_mode_table[] = {
#ifdef AIC_QSPI1_BIT_MODE
1,
#endif
#ifdef AIC_QSPI2_BIT_MODE
2,
#endif
#ifdef AIC_QSPI3_BIT_MODE
3,
#endif
};
static bool spi_support_bit_mode(struct aic_qspi *qspi)
{
u32 i;
for (i = 0; i < ARRAY_SIZE(bit_mode_table); i++) {
if (bit_mode_table[i] == qspi->idx)
return true;
}
return false;
}
#ifdef AIC_QSPI_DRV_DEBUG
void dump_cmd(uint8_t *data, uint32_t len)
{
uint32_t i;
printf("CMD: (%lu) ", (unsigned long)len);
for (i = 0; i < len; i++)
printf("%02X ", data[i]);
printf("\n");
}
#endif
static rt_uint32_t drv_spi_send(struct aic_qspi *qspi,
struct rt_spi_message *message,
const uint8_t *tx, uint32_t size)
{
struct qspi_transfer t;
u32 ret = 0;
t.rx_data = NULL;
t.tx_data = (uint8_t *)tx;
t.data_len = size;
ret = hal_qspi_master_transfer_sync(&qspi->handle, &t);
return ret;
}
static rt_uint32_t drv_spi_receive(struct aic_qspi *qspi,
struct rt_spi_message *message,
const uint8_t *tx, uint32_t size)
{
struct qspi_transfer t;
u32 ret = 0;
t.tx_data = NULL;
t.rx_data = (uint8_t *)tx;
t.data_len = size;
ret = hal_qspi_master_transfer_sync(&qspi->handle, &t);
return ret;
}
static rt_uint32_t drv_spi_transfer(struct aic_qspi *qspi,
struct rt_spi_message *message)
{
u32 ret = 0;
struct qspi_transfer t;
t.tx_data = (u8 *)message->send_buf;
t.rx_data = message->recv_buf;
t.data_len = message->length;
ret = hal_qspi_master_transfer_sync(&qspi->handle, &t);
return ret;
}
static void spi_set_cs_before(struct rt_spi_device *device,
struct rt_spi_message *message)
{
struct rt_qspi_configuration *cfg;
struct aic_qspi *qspi;
u32 cs_num = 0;
qspi = (struct aic_qspi *)device->bus;
cfg = &qspi->configuration;
if (message->cs_take && !(cfg->parent.mode & RT_SPI_NO_CS)) {
#if defined(AIC_QSPI_MULTIPLE_CS_NUM)
cs_num = qspi->cs_num;
#endif
hal_qspi_master_set_cs(&qspi->handle, cs_num, true);
}
}
static void spi_set_cs_after(struct rt_spi_device *device,
struct rt_spi_message *message)
{
struct rt_qspi_configuration *cfg;
struct aic_qspi *qspi;
u32 cs_num = 0;
qspi = (struct aic_qspi *)device->bus;
cfg = &qspi->configuration;
if (message->cs_release && !(cfg->parent.mode & RT_SPI_NO_CS)) {
#if defined(AIC_QSPI_MULTIPLE_CS_NUM)
cs_num = qspi->cs_num;
#endif
if (!qspi->nonblock)
hal_qspi_master_set_cs(&qspi->handle, cs_num, false);
}
}
static rt_uint32_t spi_xfer(struct rt_spi_device *device,
struct rt_spi_message *message)
{
struct aic_qspi *qspi;
rt_uint32_t ret = 0;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->bus != RT_NULL);
qspi = (struct aic_qspi *)device->bus;
spi_set_cs_before(device, message);
if (message->recv_buf && message->send_buf)
ret = drv_spi_transfer(qspi, message);
else if (message->recv_buf)
ret = drv_spi_receive(qspi, message, message->recv_buf, message->length);
else if (message->send_buf)
ret = drv_spi_send(qspi, message, message->send_buf, message->length);
spi_set_cs_after(device, message);
if (ret)
return ret;
return message->length;
}
static void qspi_master_async_callback(qspi_master_handle *h, void *priv)
{
struct aic_qspi *qspi = priv;
u32 cs_num = 0;
#if defined(AIC_QSPI_MULTIPLE_CS_NUM)
cs_num = qspi->cs_num;
#endif
rt_sem_release(qspi->xfer_sem);
hal_qspi_master_set_cs(&qspi->handle, cs_num, false);
}
static irqreturn_t qspi_irq_handler(int irq_num, void *arg)
{
qspi_master_handle *h = arg;
rt_interrupt_enter();
hal_qspi_master_irq_handler(h);
rt_interrupt_leave();
return IRQ_HANDLED;
}
static rt_err_t spi_configure(struct rt_spi_device *device,
struct rt_spi_configuration *configuration)
{
struct qspi_master_config cfg;
struct aic_qspi *qspi;
rt_uint32_t bus_hz;
rt_err_t ret = RT_EOK;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(configuration != RT_NULL);
qspi = (struct aic_qspi *)device->bus;
if (spi_support_bit_mode(qspi))
qspi->handle.bit_mode = true;
else
qspi->handle.bit_mode = false;
if ((rt_memcmp(&qspi->configuration, configuration,
sizeof(struct rt_spi_configuration)) != 0) ||
(qspi->handle.bit_mode == true)) {
rt_memcpy(&qspi->configuration, configuration,
sizeof(struct rt_spi_configuration));
rt_memset(&cfg, 0, sizeof(cfg));
cfg.idx = qspi->idx;
cfg.clk_id = qspi->clk_id;
bus_hz = configuration->max_hz;
if (bus_hz < HAL_QSPI_MIN_FREQ_HZ)
bus_hz = HAL_QSPI_MIN_FREQ_HZ;
if (bus_hz > HAL_QSPI_MAX_FREQ_HZ)
bus_hz = HAL_QSPI_MAX_FREQ_HZ;
cfg.clk_in_hz = qspi->clk_in_hz;
if (cfg.clk_in_hz > HAL_QSPI_MAX_FREQ_HZ)
cfg.clk_in_hz = HAL_QSPI_MAX_FREQ_HZ;
if (qspi->clk_in_hz % bus_hz)
cfg.clk_in_hz = bus_hz;
if (cfg.clk_in_hz < HAL_QSPI_INPUT_MIN_FREQ_HZ)
cfg.clk_in_hz = HAL_QSPI_INPUT_MIN_FREQ_HZ;
if (configuration->mode & RT_SPI_MSB)
cfg.lsb_en = false;
else
cfg.lsb_en = true;
if (configuration->mode & RT_SPI_CPHA)
cfg.cpha = HAL_QSPI_CPHA_SECOND_EDGE;
else
cfg.cpha = HAL_QSPI_CPHA_FIRST_EDGE;
if (configuration->mode & RT_SPI_CPOL)
cfg.cpol = HAL_QSPI_CPOL_ACTIVE_LOW;
else
cfg.cpol = HAL_QSPI_CPOL_ACTIVE_HIGH;
if (configuration->mode & RT_SPI_CS_HIGH)
cfg.cs_polarity = HAL_QSPI_CS_POL_VALID_HIGH;
else
cfg.cs_polarity = HAL_QSPI_CS_POL_VALID_LOW;
cfg.rx_dlymode = qspi->rxd_dlymode;
cfg.tx_dlymode = aic_convert_tx_dlymode(qspi->txc_dlymode, qspi->txd_dlymode);
ret = hal_qspi_master_init(&qspi->handle, &cfg);
if (ret) {
pr_err("spi init failed.\n");
return ret;
}
if (!qspi->inited) {
#ifdef AIC_DMA_DRV
struct qspi_master_dma_config dmacfg;
rt_memset(&dmacfg, 0, sizeof(dmacfg));
dmacfg.port_id = qspi->dma_port_id;
ret = hal_qspi_master_dma_config(&qspi->handle, &dmacfg);
if (ret) {
pr_err("qspi dma config failed.\n");
return ret;
}
#endif
ret = hal_qspi_master_register_cb(&qspi->handle,
qspi_master_async_callback, qspi);
if (ret) {
pr_err("qspi register async callback failed.\n");
return ret;
}
aicos_request_irq(qspi->irq_num, qspi_irq_handler, 0, NULL,
(void *)&qspi->handle);
aicos_irq_enable(qspi->irq_num);
}
bus_hz = configuration->max_hz;
if (bus_hz > HAL_QSPI_MAX_FREQ_HZ)
bus_hz = HAL_QSPI_MAX_FREQ_HZ;
hal_qspi_master_set_bus_freq(&qspi->handle, bus_hz);
if (ret) {
pr_err("qspi set bus frequency failed.\n");
return ret;
}
}
qspi->inited = true;
return ret;
}
static rt_err_t spi_nonblock_set(struct rt_spi_device *device,
rt_uint32_t nonblock)
{
struct aic_qspi *qspi;
qspi = (struct aic_qspi *)device->bus;
if (nonblock == 1)
qspi->nonblock = true;
else
qspi->nonblock = false;
return RT_EOK;
}
static rt_uint32_t spi_get_transfer_status(struct rt_spi_device *device)
{
struct aic_qspi *qspi;
qspi = (struct aic_qspi *)device->bus;
return hal_qspi_master_get_status(&qspi->handle);
}
rt_err_t aic_spi_bus_attach_device(const char *bus_name,
const char *device_name)
{
struct rt_spi_device *spi_device = RT_NULL;
rt_err_t result = RT_EOK;
RT_ASSERT(bus_name != RT_NULL);
RT_ASSERT(device_name != RT_NULL);
spi_device =
(struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
result = rt_spi_bus_attach_device(spi_device, device_name,
bus_name, RT_NULL);
if (result != RT_EOK && spi_device != NULL)
rt_free(spi_device);
return result;
}
static const struct rt_spi_ops aic_spi_ops = {
.configure = spi_configure,
.xfer = spi_xfer,
.nonblock = spi_nonblock_set,
.gstatus = spi_get_transfer_status,
};
static int rt_hw_spi_bus_init(void)
{
char sem_name[RT_NAME_MAX];
rt_err_t ret = RT_EOK;
int i;
for (i = 0; i < ARRAY_SIZE(spi_controller); i++) {
ret = rt_spi_bus_register(&spi_controller[i].dev,
spi_controller[i].name, &aic_spi_ops);
if (ret != RT_EOK)
break;
rt_sprintf(sem_name, "%s_s", spi_controller[i].name);
spi_controller[i].xfer_sem =
rt_sem_create(sem_name, 0, RT_IPC_FLAG_PRIO);
if (!spi_controller[i].xfer_sem) {
ret = RT_ENOMEM;
break;
}
}
return ret;
}
INIT_BOARD_EXPORT(rt_hw_spi_bus_init);

View File

@@ -94,6 +94,10 @@ menu "UART0 Parameter"
default 6 if AIC_DEV_UART0_MODE_RS232_SW_HW_FLOW_CTRL
default 7 if AIC_DEV_UART0_MODE_RS485_SIMULATION
config AIC_SERIAL_USING_FLOWCTRL
bool
default y if AIC_DEV_UART0_MODE_RS232_UNAUTO_FLOW_CTRL || AIC_DEV_UART0_MODE_RS232_SW_FLOW_CTRL || AIC_DEV_UART0_MODE_RS232_SW_HW_FLOW_CTRL
menuconfig AIC_UART0_RTS_ENABLE
bool
prompt "Enable RTS"
@@ -258,6 +262,10 @@ menu "UART1 Parameter"
default 6 if AIC_DEV_UART1_MODE_RS232_SW_HW_FLOW_CTRL
default 7 if AIC_DEV_UART1_MODE_RS485_SIMULATION
config AIC_SERIAL_USING_FLOWCTRL
bool
default y if AIC_DEV_UART1_MODE_RS232_UNAUTO_FLOW_CTRL || AIC_DEV_UART1_MODE_RS232_SW_FLOW_CTRL || AIC_DEV_UART1_MODE_RS232_SW_HW_FLOW_CTRL
menuconfig AIC_UART1_RTS_ENABLE
bool
prompt "Enable RTS"
@@ -422,6 +430,9 @@ menu "UART2 Parameter"
default 6 if AIC_DEV_UART2_MODE_RS232_SW_HW_FLOW_CTRL
default 7 if AIC_DEV_UART2_MODE_RS485_SIMULATION
config AIC_SERIAL_USING_FLOWCTRL
bool
default y if AIC_DEV_UART2_MODE_RS232_UNAUTO_FLOW_CTRL || AIC_DEV_UART2_MODE_RS232_SW_FLOW_CTRL || AIC_DEV_UART2_MODE_RS232_SW_HW_FLOW_CTRL
menuconfig AIC_UART2_RTS_ENABLE
bool
@@ -588,6 +599,10 @@ menu "UART3 Parameter"
default 6 if AIC_DEV_UART3_MODE_RS232_SW_HW_FLOW_CTRL
default 7 if AIC_DEV_UART3_MODE_RS485_SIMULATION
config AIC_SERIAL_USING_FLOWCTRL
bool
default y if AIC_DEV_UART3_MODE_RS232_UNAUTO_FLOW_CTRL || AIC_DEV_UART3_MODE_RS232_SW_FLOW_CTRL || AIC_DEV_UART3_MODE_RS232_SW_HW_FLOW_CTRL
menuconfig AIC_UART3_RTS_ENABLE
bool
prompt "Enable RTS"
@@ -752,6 +767,10 @@ menu "UART4 Parameter"
default 6 if AIC_DEV_UART4_MODE_RS232_SW_HW_FLOW_CTRL
default 7 if AIC_DEV_UART4_MODE_RS485_SIMULATION
config AIC_SERIAL_USING_FLOWCTRL
bool
default y if AIC_DEV_UART4_MODE_RS232_UNAUTO_FLOW_CTRL || AIC_DEV_UART4_MODE_RS232_SW_FLOW_CTRL || AIC_DEV_UART4_MODE_RS232_SW_HW_FLOW_CTRL
menuconfig AIC_UART4_RTS_ENABLE
bool
prompt "Enable RTS"
@@ -917,6 +936,10 @@ menu "UART5 Parameter"
default 6 if AIC_DEV_UART5_MODE_RS232_SW_HW_FLOW_CTRL
default 7 if AIC_DEV_UART5_MODE_RS485_SIMULATION
config AIC_SERIAL_USING_FLOWCTRL
bool
default y if AIC_DEV_UART5_MODE_RS232_UNAUTO_FLOW_CTRL || AIC_DEV_UART5_MODE_RS232_SW_FLOW_CTRL || AIC_DEV_UART5_MODE_RS232_SW_HW_FLOW_CTRL
menuconfig AIC_UART5_RTS_ENABLE
bool
prompt "Enable RTS"
@@ -1081,6 +1104,10 @@ menu "UART6 Parameter"
default 6 if AIC_DEV_UART6_MODE_RS232_SW_HW_FLOW_CTRL
default 7 if AIC_DEV_UART6_MODE_RS485_SIMULATION
config AIC_SERIAL_USING_FLOWCTRL
bool
default y if AIC_DEV_UART6_MODE_RS232_UNAUTO_FLOW_CTRL || AIC_DEV_UART6_MODE_RS232_SW_FLOW_CTRL || AIC_DEV_UART6_MODE_RS232_SW_HW_FLOW_CTRL
menuconfig AIC_UART6_RTS_ENABLE
bool
prompt "Enable RTS"
@@ -1245,6 +1272,10 @@ menu "UART7 Parameter"
default 6 if AIC_DEV_UART7_MODE_RS232_SW_HW_FLOW_CTRL
default 7 if AIC_DEV_UART7_MODE_RS485_SIMULATION
config AIC_SERIAL_USING_FLOWCTRL
bool
default y if AIC_DEV_UART7_MODE_RS232_UNAUTO_FLOW_CTRL || AIC_DEV_UART7_MODE_RS232_SW_FLOW_CTRL || AIC_DEV_UART7_MODE_RS232_SW_HW_FLOW_CTRL
menuconfig AIC_UART7_RTS_ENABLE
bool
prompt "Enable RTS"