Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources

This commit is contained in:
2026-07-06 11:30:13 +08:00
commit e76462eeb7
3451 changed files with 1415300 additions and 0 deletions

1818
sdk/driver/adc/hgadc_v1.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
#ifndef _HGADC_V1_HW_H
#define _HGADC_V1_HW_H
#ifdef __cplusplus
extern "C" {
#endif
#define LL_ADKEY_SOTF_KICK(hw) (hw->ADC_CON_KICK |= BIT(0))
#define LL_ADKEY_GET_IRQ_EN_SAMPLE_DONE(hw) (hw->ADKEY_CON & BIT(20))
#define LL_ADKEY_GET_DONE_PENDING(hw) (hw->ADKEY_STA & BIT(0))
#define LL_ADKEY_CLEAR_DONE_PENDING(hw) (hw->ADKEY_STA = BIT(0))
#define LL_ADKEY_GET_DATA(hw) (hw->ADKEY_DATA & 0xFFF)
/** @brief ADC register structure
* @{
*/
struct hgadc_v1_hw {
__IO uint32 ADC_ANA_CTRL0;
__IO uint32 ADC_ANA_CTRL1;
__IO uint32 ADC_CON_EN;
__IO uint32 ADC_CON_FUN;
__IO uint32 ADC_CON_SMP;
__IO uint32 ADC_CON_SEL0;
__IO uint32 ADC_CON_SEL1;
__IO uint32 ADC_CON_KICK;
__IO uint32 ADC_CON_CMP;
__IO uint32 ADC_CON_STA;
__IO uint32 ADC_DMA_STADR;
__IO uint32 ADC_DMA_CNT;
__IO uint32 ADC_CON_EXTEND0;
__IO uint32 ADC_CON_EXTEND1;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGADC_V0_HW_H */

404
sdk/driver/crc/hg_crc.c Normal file
View File

@@ -0,0 +1,404 @@
/**
* @file hg_crc.c
* @author LeonLeeV
* @brief
* @version
* TXW80X; TXW81X; TXW82X
* @date 2023-08-02
*
* @copyright Copyright (c) 2023
*
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "devid.h"
#include "osal/string.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/irq.h"
#include "dev/crc/hg_crc.h"
#include "hg_crc_hw.h"
struct hgcrc_config {
uint32 poly;
uint32 poly_bits;
uint32 init_val;
uint32 xor_out;
char ref_in;
char ref_out;
};
static const struct hgcrc_config tcpip_chksum = {
.init_val = 0x0,
.xor_out = 0x0,
.poly = 0x0,
.poly_bits = 0,
.ref_in = 1,
.ref_out = 1,
};
static const struct hgcrc_config crc5_usb = {
.init_val = 0x1f,
.xor_out = 0x1f,
.poly = 0x14,
.poly_bits = 5,
.ref_in = 1,
.ref_out = 1,
};
static const struct hgcrc_config crc7_mmc = {
.init_val = 0x0,
.xor_out = 0x0,
.poly = 0x48,
.poly_bits = 7,
.ref_in = 0,
.ref_out = 0,
};
static const struct hgcrc_config crc8_maxim = {
.init_val = 0x0,
.xor_out = 0x0,
.poly = 0x8C,
.poly_bits = 8,
.ref_in = 1,
.ref_out = 1,
};
static const struct hgcrc_config crc8 = {
.init_val = 0x0,
.xor_out = 0x0,
.poly = 0xE0,
.poly_bits = 8,
.ref_in = 0,
.ref_out = 0,
};
static const struct hgcrc_config crc16 = {
.init_val = 0x0,
.xor_out = 0x0,
.poly = 0xA001,
.poly_bits = 16,
.ref_in = 1,
.ref_out = 1,
};
static const struct hgcrc_config crc16_ccitt = {
.init_val = 0x0,
.xor_out = 0x0,
.poly = 0x8408,
.poly_bits = 16,
.ref_in = 1,
.ref_out = 1,
};
static const struct hgcrc_config crc16_modbus = {
.init_val = 0xFFFF,
.xor_out = 0x0,
.poly = 0xA001,
.poly_bits = 16,
.ref_in = 1,
.ref_out = 1,
};
static const struct hgcrc_config crc32_winrar = {
.init_val = 0xFFFFFFFF,
.xor_out = 0xFFFFFFFF,
.poly = 0xEDB88320,
.poly_bits = 32,
.ref_in = 1,
.ref_out = 1,
};
static const struct hgcrc_config *hgcrc_cfg[CRC_TYPE_MAX] = {
[CRC_TYPE_TCPIP_CHKSUM] = &tcpip_chksum,
[CRC_TYPE_CRC5_USB] = &crc5_usb,
[CRC_TYPE_CRC7_MMC] = &crc7_mmc,
[CRC_TYPE_CRC8_MAXIM] = &crc8_maxim,
[CRC_TYPE_CRC8] = &crc8,
[CRC_TYPE_CRC16] = &crc16,
[CRC_TYPE_CRC16_CCITT] = &crc16_ccitt,
[CRC_TYPE_CRC16_MODBUS] = &crc16_modbus,
[CRC_TYPE_CRC32_WINRAR] = &crc32_winrar,
};
static void hg_crc_irq_handler(void *data)
{
struct hg_crc *crc = (struct hg_crc *)data;
struct hg_crc_hw *hw = (struct hg_crc_hw *)crc->hw;
hw->CRC_KST = LL_CRC_KST_DMA_PENDING_CLR;
os_sema_up(&crc->done);
}
/**
* CRC len 512KB for TXW81x/TXW82X» 64KB for TXW80x
*/
static int32 hg_crc_calc_continue(struct crc_dev *crc, struct crc_dev_req *req, uint32 *crc_value)
{
int32 tmo = 2000;
int32 ret = 0;
struct hg_crc *dev = (struct hg_crc *)crc;
struct hg_crc_hw *hw = (struct hg_crc_hw *)dev->hw;
hw->CRC_INIT = hw->CRC_OUT ^ hw->CRC_INV;
/* kick */
#if defined(TXW80X)
hw->DMA_ADDR = (uint32)req->data & 0x00FFFFFF;
#else
hw->DMA_ADDR = (uint32)req->data;
#endif
hw->DMA_LEN = req->len;
ret = os_sema_down(&dev->done, tmo);
*crc_value = hw->CRC_OUT;
return ret > 0 ? RET_OK : RET_ERR;
}
int32 hg_crc5_usb_calc_nonos(struct crc_dev *crc, struct crc_dev_req *req, uint32 *crc_value, uint32 flags)
{
uint32 cfg_reg;
struct hg_crc *dev = (struct hg_crc *)crc;
struct hg_crc_hw *hw = (struct hg_crc_hw *)dev->hw;
hw->CRC_CFG &= ~ LL_CRC_CFG_INT_EN;
cfg_reg = LL_CRC_CFG_POLY_BITS(5) | LL_CRC_CFG_DMAWAIT_CLOCK(5);
cfg_reg |= LL_CRC_CFG_BIT_ORDER_RIGHT;
/* config */
hw->CRC_INIT = 0x1f;
hw->CRC_INV = 0x1f;
hw->CRC_POLY = 0x14;
hw->CRC_CFG = cfg_reg;
/* kick */
#if defined(TXW80X)
hw->DMA_ADDR = (uint32)req->data & 0x00FFFFFF;
#else
hw->DMA_ADDR = (uint32)req->data;
#endif
hw->DMA_LEN = req->len;
while(!(hw->CRC_STA & LL_CRC_STA_DMA_PENDING));
hw->CRC_KST = LL_CRC_KST_DMA_PENDING_CLR;
*crc_value = hw->CRC_OUT;
hw->CRC_CFG |= LL_CRC_CFG_INT_EN;
return 0;
}
int32 hg_crc8_calc_nonos(struct crc_dev *crc, struct crc_dev_req *req, uint32 *crc_value, uint32 flags)
{
uint32 cfg_reg;
struct hg_crc *dev = (struct hg_crc *)crc;
struct hg_crc_hw *hw = (struct hg_crc_hw *)dev->hw;
hw->CRC_CFG &= ~ LL_CRC_CFG_INT_EN;
cfg_reg = LL_CRC_CFG_POLY_BITS(8) | LL_CRC_CFG_DMAWAIT_CLOCK(5);
cfg_reg |= LL_CRC_CFG_BIT_ORDER_LEFT;
/* config */
hw->CRC_INIT = 0x0;
hw->CRC_INV = 0x0;
hw->CRC_POLY = 0xE0;
hw->CRC_CFG = cfg_reg;
/* kick */
#if defined(TXW80X)
hw->DMA_ADDR = (uint32)req->data & 0x00FFFFFF;
#else
hw->DMA_ADDR = (uint32)req->data;
#endif
hw->DMA_LEN = req->len;
while(!(hw->CRC_STA & LL_CRC_STA_DMA_PENDING));
hw->CRC_KST = LL_CRC_KST_DMA_PENDING_CLR;
*crc_value = hw->CRC_OUT;
hw->CRC_CFG |= LL_CRC_CFG_INT_EN;
return 0;
}
/**
* CRC len 512KB for TXW81x/TXW82X£» 64KB for TXW80x
*/
static int32 hg_crc_calc(struct crc_dev *crc, struct crc_dev_req *req, uint32 *crc_value, uint32 flags)
{
int32 ret = 0;
uint32 cfg_reg = 0;
struct hg_crc *dev = (struct hg_crc *)crc;
struct hg_crc_hw *hw = (struct hg_crc_hw *)dev->hw;
const struct hgcrc_config *p_cfg;
if (req == NULL || req->data == NULL || req->len == 0 || req->type >= CRC_TYPE_MAX) {
os_printf(KERN_ERR"%s ARG err\r\n", __FUNCTION__);
return -EINVAL;
}
if ((CRC_TYPE_TCPIP_CHKSUM == req->type) && (req->len < 4)) {
os_printf(KERN_ERR"%s not support\r\n", __FUNCTION__);
return -ENOTSUP;
}
if ((dev->flags & BIT(HGCRC_FLAGS_SUSPEND))) {
os_printf(KERN_ERR"%s at suspend\r\n", __FUNCTION__);
return -ENOTSUP;
}
p_cfg = hgcrc_cfg[req->type];
if (p_cfg == NULL) {
os_printf(KERN_ERR"%s not support\r\n", __FUNCTION__);
return -ENOTSUP;
}
os_mutex_lock(&dev->lock, osWaitForever);
os_sema_eat(&dev->done);
sysctrl_crc_reset();
if (0 == p_cfg->poly_bits) {
cfg_reg = LL_CRC_CFG_INT_EN | LL_CRC_CFG_TCP_MODE_EN | LL_CRC_CFG_DMAWAIT_CLOCK(5);
} else {
cfg_reg = LL_CRC_CFG_INT_EN | LL_CRC_CFG_POLY_BITS(p_cfg->poly_bits) | LL_CRC_CFG_DMAWAIT_CLOCK(5);
if (p_cfg->ref_in) {
cfg_reg |= LL_CRC_CFG_BIT_ORDER_RIGHT;
} else {
cfg_reg |= LL_CRC_CFG_BIT_ORDER_LEFT;
}
}
/* config */
hw->CRC_INV = p_cfg->xor_out;
hw->CRC_INIT = p_cfg->init_val;
if (flags & CRC_DEV_FLAGS_CONTINUE_CALC) {
hw->CRC_INIT = p_cfg->xor_out ^ req->crc_last;
}
hw->CRC_POLY = p_cfg->poly;
hw->CRC_CFG = cfg_reg;
/* kick */
#ifdef PSRAM_HEAP
if (req->flag) {
;
} else if (CRC_TYPE_TCPIP_CHKSUM == req->type) {
sys_dcache_clean_range_unaligned((uint32_t *)req->data, req->len);
} else {
sys_dcache_clean_range((uint32_t *)req->data, req->len);
}
#endif
#if defined(TXW80X)
hw->DMA_ADDR = (uint32)req->data & 0x00FFFFFF;
#else
hw->DMA_ADDR = (uint32)req->data;
#endif
hw->DMA_LEN = req->len;
ret = os_sema_down(&dev->done, 2000);
if (!ret) {
os_printf(KERN_ERR"%s timeout\r\n", __FUNCTION__);
}
*crc_value = hw->CRC_OUT;
os_mutex_unlock(&dev->lock);
return ret > 0 ? RET_OK : RET_ERR;
}
void hg_crc_test_printf(struct crc_dev *crc)
{
uint8_t src[64];
for (int i = 0;i<64;i++)
src[i] = 99+i;
struct crc_dev_req req = {
.type = CRC_TYPE_CRC32_WINRAR,
.data = src,
.len = 64,
};
uint32 crc_val = 0;
hg_crc_calc(crc, &req, &crc_val, 0);
_os_printf("crc r: 0x%08x\r\n", crc_val);
if (crc_val != 0x81efdc25) {
_os_printf("crc lp err\r\n");
}
}
#ifdef CONFIG_SLEEP
//#define HGCRC_SLEEP_TEST(dev) hg_crc_test_printf(dev)
#define HGCRC_SLEEP_TEST(dev)
int32 hg_crc_suspend(struct dev_obj *dev)
{
int32 ret = 0;
struct hg_crc *crc = (struct hg_crc *)dev;
struct hg_crc_hw *hw = (struct hg_crc_hw *)crc->hw;
if ((crc->flags & BIT(HGCRC_FLAGS_SUSPEND))) {
return RET_OK;
}
HGCRC_SLEEP_TEST(dev);
ret = os_mutex_lock(&crc->lock, osWaitForever);
if (ret < 0) {
return ret;
}
irq_disable(crc->irq_num);
crc->flags |= BIT(HGCRC_FLAGS_SUSPEND);
/* register backup ?*/
sysctrl_crc_clk_close();
return RET_OK;
}
int32 hg_crc_resume(struct dev_obj *dev)
{
int32 ret = 0;
struct hg_crc *crc = (struct hg_crc *)dev;
struct hg_crc_hw *hw = (struct hg_crc_hw *)crc->hw;
if ((crc->flags & BIT(HGCRC_FLAGS_SUSPEND))) {
ret = os_mutex_unlock(&crc->lock);
if (ret < 0) {
return ret;
}
sysctrl_crc_clk_open();
sysctrl_crc_reset();
/* register recovery ?*/
crc->flags &= ~ BIT(HGCRC_FLAGS_SUSPEND);
irq_enable(crc->irq_num);
HGCRC_SLEEP_TEST(dev);
}
return RET_OK;
}
#endif
static const struct crc_hal_ops crc_ops = {
.calc = hg_crc_calc,
#ifdef CONFIG_SLEEP
.ops.suspend = hg_crc_suspend,
.ops.resume = hg_crc_resume,
#endif
};
__init int32 hg_crc_attach(uint32 dev_id, struct hg_crc *crc)
{
struct hg_crc_hw *hw = (struct hg_crc_hw *)crc->hw;
crc->dev.dev.ops = (const struct devobj_ops *)&crc_ops;
crc->flags = 0;
os_mutex_init(&crc->lock);
os_sema_init(&crc->done, 0);
sysctrl_crc_clk_open();
sysctrl_crc_reset();
request_irq(crc->irq_num, hg_crc_irq_handler, crc);
hw->CRC_CFG |= LL_CRC_CFG_INT_EN;
irq_enable(crc->irq_num);
dev_register(dev_id, (struct dev_obj *)crc);
return RET_OK;
}

View File

@@ -0,0 +1,75 @@
#ifndef _HG_CRC_HW_H_
#define _HG_CRC_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
enum hg_crc_flags {
HGCRC_FLAGS_SUSPEND = BIT(0),
HGCRC_FLAGS_HOLD = BIT(1),
};
/***** CRC_CFG Register *****/
/*! CRC interrupt enable
*/
#define LL_CRC_CFG_INT_EN (1UL << 0)
/*! CRC shift bit direction
*/
#define LL_CRC_CFG_BIT_ORDER_LEFT (1UL << 1)
#define LL_CRC_CFG_BIT_ORDER_RIGHT (0UL << 1)
/*! CRC POLY width: 5/7/8/16/32
*/
#define LL_CRC_CFG_POLY_BITS(n) (((n)&0x3F) << 8)
/*! CRC DMA data wait clock every time
*/
#define LL_CRC_CFG_DMAWAIT_CLOCK(n) (((n)&0x7) << 16)
/*! CRC TCP mode enable
*/
#define LL_CRC_CFG_TCP_MODE_EN (1UL << 24)
/***** CRC_KST Register *****/
/*! CRC pending clear
*/
#define LL_CRC_KST_DMA_PENDING_CLR (1UL << 0)
/***** CRC_STA Register *****/
/*! CRC pending
*/
#define LL_CRC_STA_DMA_PENDING (1UL << 0)
/***** CRC_INIT Register *****/
/***** CRC_INV Register *****/
/***** CRC_POLY Register *****/
/***** CRC_DMA_ADDR Register *****/
/***** CRC_DMA_LEN Register *****/
/***** CRC_CRC_OUT Register *****/
/**
* @brief CRC
*/
struct hg_crc_hw {
__IO uint32 CRC_CFG; // 0x0c
__IO uint32 CRC_INIT; // 0x04
__IO uint32 CRC_INV; // 0x08
__IO uint32 CRC_POLY; // 0x0c
__IO uint32 CRC_KST; // 0x10
__IO uint32 CRC_STA; // 0x14
uint32 RESERVED0;
__IO uint32 DMA_ADDR; // 0x1c
__IO uint32 DMA_LEN; // 0x20
__IO uint32 CRC_OUT; // 0x24
} ;
#ifdef __cplusplus
}
#endif
#endif /* _HG_CRC_H_ */

216
sdk/driver/dma/dw_dmac.c Normal file
View File

@@ -0,0 +1,216 @@
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "string.h"
#include "osal/irq.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "hal/dma.h"
#include "dev/dma/dw_dmac.h"
#include "osal/string.h"
static void dw_dmac_irq_handler(void *data)
{
uint32 ch;
struct hgdma_dw *dma = (struct hgdma_dw *)data;
for(ch=0; ch<DW_DMAC_MAX_DMAC_CHN; ch++) {
if((dma->hw->MaskTfrL & BIT(ch)) && (dma->hw->RawTfrL & BIT(ch))) {
dma->hw->ClearTfrL = BIT(ch);
dma->state[ch] |= DW_DMAC_XFER_DONE(ch);
if(dma->irq_hdl[ch]) {
dma->irq_hdl[ch]((void *)dma, ch, DMA_IRQ_TYPE_DONE, dma->irq_data[ch]);
}
}
if((dma->hw->MaskErrL & BIT(ch)) && (dma->hw->RawErrL & BIT(ch))) {
dma->hw->ClearErrL = BIT(ch);
dma->state[ch] |= DW_DMAC_XFER_ERR(ch);
if(dma->irq_hdl[ch]) {
dma->irq_hdl[ch]((void *)dma, ch, DMA_IRQ_TYPE_ERROR, dma->irq_data[ch]);
}
}
}
}
static int32 dw_dmac_xfer(struct dma_device *dma, struct dma_xfer_data *data)
{
uint32 ch;
uint32 flags;
uint32 src_id = data->src_id;
uint32 dest_id = data->dst_id;
uint32 direct = data->dir;
uint8 src_dir = (data->src_addr_mode == DMA_XFER_MODE_RECYCLE) ? DW_DMAC_ADDR_NO_CHANGE : DW_DMAC_ADDR_INC;
uint8 dst_dir = (data->dst_addr_mode == DMA_XFER_MODE_RECYCLE) ? DW_DMAC_ADDR_NO_CHANGE : DW_DMAC_ADDR_INC;
struct hgdma_dw *dev = (struct hgdma_dw *)dma;
struct hgdma_dw_hw *hw = (struct hgdma_dw_hw *)dev->hw;
if(!dev->opened) {
return RET_ERR;
}
/* get free channel */
flags = disable_irq();
for(ch=0; ch<DW_DMAC_MAX_DMAC_CHN; ch++) {
if(!(dev->chn_used_flag & BIT(ch))) {
dev->chn_used_flag |= BIT(ch);
break;
}
}
enable_irq(flags);
if(ch >= DW_DMAC_MAX_DMAC_CHN)
return -EBUSY;
ASSERT(data->element_per_width < DMA_SLAVE_BUSWIDTH_8_BYTES);
if(data->element_per_width >= DMA_SLAVE_BUSWIDTH_8_BYTES) {
return RET_ERR;
}
hw->CH[ch].SARH = 0x0000;
hw->CH[ch].DARH = 0x0000;
hw->CH[ch].SARL = data->src;
hw->CH[ch].DARL = data->dest;
switch(direct) {
case DMA_XFER_DIR_M2M:
hw->CH[ch].CTLL = DW_DMAC_CTLL_SMS(1) | DW_DMAC_CTLL_DMS(1) |
DW_DMAC_CTLL_FC(DW_DMAC_FC_D_M2M) |
DW_DMAC_CTLL_SRC_DIR(src_dir) |
DW_DMAC_CTLL_DST_DIR(dst_dir);
/* Configure dma req channel */
hw->CH[ch].CFGH = DW_DMAC_CFGH_DST_PER(0) |
DW_DMAC_CFGH_SRC_PER(0) |
DW_DMAC_CFGH_PROTCTL(1);
break;
case DMA_XFER_DIR_D2M:
hw->CH[ch].CTLL = DW_DMAC_CTLL_SMS(0) | DW_DMAC_CTLL_DMS(1) |
DW_DMAC_CTLL_FC(DW_DMAC_FC_D_P2M) |
DW_DMAC_CTLL_SRC_DIR(src_dir) |
DW_DMAC_CTLL_DST_DIR(dst_dir);
/* Configure dma req channel */
hw->CH[ch].CFGH = DW_DMAC_CFGH_DST_PER(0) |
DW_DMAC_CFGH_SRC_PER(src_id) |
DW_DMAC_CFGH_PROTCTL(1);
break;
case DMA_XFER_DIR_M2D:
hw->CH[ch].CTLL = DW_DMAC_CTLL_SMS(1) | DW_DMAC_CTLL_DMS(0) |
DW_DMAC_CTLL_FC(DW_DMAC_FC_D_M2P) |
DW_DMAC_CTLL_SRC_DIR(src_dir) |
DW_DMAC_CTLL_DST_DIR(dst_dir);
/* Configure dma req channel */
hw->CH[ch].CFGH = DW_DMAC_CFGH_DST_PER(dest_id) |
DW_DMAC_CFGH_SRC_PER(0) |
DW_DMAC_CFGH_PROTCTL(1);
break;
case DMA_XFER_DIR_D2D:
hw->CH[ch].CTLL = DW_DMAC_CTLL_SMS(0) | DW_DMAC_CTLL_DMS(0) |
DW_DMAC_CTLL_FC(DW_DMAC_FC_D_P2P) |
DW_DMAC_CTLL_SRC_DIR(src_dir) |
DW_DMAC_CTLL_DST_DIR(dst_dir);
/* Configure dma req channel */
hw->CH[ch].CFGH = DW_DMAC_CFGH_DST_PER(dest_id) |
DW_DMAC_CFGH_SRC_PER(src_id) |
DW_DMAC_CFGH_PROTCTL(1);
break;
default:
dev->chn_used_flag &= ~ BIT(ch);
return RET_ERR;
}
/* Configure block size */
hw->CH[ch].CTLH = data->element_num;
hw->CH[ch].CTLL |= DW_DMAC_CTLL_INT_EN |
DW_DMAC_CTLL_SRC_MSIZE(DW_DMAC_MSIZE_1) |
DW_DMAC_CTLL_DST_MSIZE(DW_DMAC_MSIZE_1) |
DW_DMAC_CTLL_SRC_WIDTH(data->element_per_width) |
DW_DMAC_CTLL_DST_WIDTH(data->element_per_width);
/* AMBA burst length no limited. */
hw->CH[ch].CFGL = DW_DMAC_CFGL_MAX_BURST(0);
dev->state[ch] = 0x0000;
dev->irq_hdl[ch] = data->irq_hdl;
dev->irq_data[ch] = data->irq_data;
//start xfer
hw->ChEnRegL = DW_DMAC_WRITE_EN(ch);
return ch;
}
static int32 dw_dmac_get_status(struct dma_device *dma, uint32 chn)
{
struct hgdma_dw *dev = (struct hgdma_dw *)dma;
if(!dev->opened) {
return RET_ERR;
}
if(dev->state[chn] & DW_DMAC_XFER_ERR(chn)) {
return DMA_ERROR;
} else if(dev->state[chn] & DW_DMAC_XFER_DONE(chn)) {
return DMA_SUCCESS;
} else {
return DMA_IN_PROGRESS;
}
}
static int32 dw_dmac_stop(struct dma_device *dma, uint32 chn)
{
uint32 flags;
struct hgdma_dw *dev = (struct hgdma_dw *)dma;
struct hgdma_dw_hw *p_dmac = (struct hgdma_dw_hw *)dev->hw;
flags = disable_irq();
if(dev->chn_used_flag & BIT(chn)) {
p_dmac->ChEnRegL = DW_DMAC_WRITE_DIS(chn);
dev->chn_used_flag &= ~ BIT(chn);
}
enable_irq(flags);
return RET_OK;
}
static const struct dma_hal_ops dw_ops = {
.xfer = dw_dmac_xfer,
.get_status = dw_dmac_get_status,
.stop = dw_dmac_stop,
};
__init int32 dw_dmac_attach(uint32 dev_id, struct hgdma_dw *dmac)
{
uint32 ch;
dmac->opened = 1;
dmac->dev.dev.ops = (const struct devobj_ops *)&dw_ops;
for(ch=0; ch<DW_DMAC_MAX_DMAC_CHN; ch++) {
dmac->irq_hdl[ch] = NULL;
dmac->irq_data[ch] = 0;
dmac->state[ch] = 0;
}
dmac->hw->ChEnRegL = 0xFF00;
dmac->hw->DmaCfgRegL = 0x0000;
/* reset dmac */
dmac->hw->ClearBlockL = DW_DMAC_MAX_DMAC_CHN_MASK;
dmac->hw->ClearDstTranL = DW_DMAC_MAX_DMAC_CHN_MASK;
dmac->hw->ClearErrL = DW_DMAC_MAX_DMAC_CHN_MASK;
dmac->hw->ClearSrcTranL = DW_DMAC_MAX_DMAC_CHN_MASK;
dmac->hw->ClearTfrL = DW_DMAC_MAX_DMAC_CHN_MASK;
/* disable mask */
dmac->hw->MaskErrL = 0xFFFF;
dmac->hw->MaskTfrL = 0xFFFF;
dmac->hw->MaskBlockL = 0xFF00;
dmac->hw->MaskDstTranL = 0xFF00;
dmac->hw->MaskSrcTranL = 0xFF00;
/* enable DMAC */
dmac->hw->DmaCfgRegL = DW_DMAC_CFG_DMA_EN;
irq_enable(dmac->irq_num);
request_irq(dmac->irq_num, dw_dmac_irq_handler, dmac);
dev_register(dev_id, (struct dev_obj *)dmac);
return RET_OK;
}

434
sdk/driver/dma/hg_m2m_dma.c Normal file
View File

@@ -0,0 +1,434 @@
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "osal/irq.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/string.h"
#include "hal/dma.h"
#include "dev/dma/hg_m2m_dma.h"
#include "osal/sleep.h"
#define DMA_LEN_THRESHOLD (2048)
uint32_t in_disable_irq(void);
static void hg_m2m0_dma_irq_handler(void *data)
{
struct mem_dma_dev *dma = (struct mem_dma_dev *)data;
struct mem_dma_hw *hw = (struct mem_dma_hw *)dma->hw;
hw->dma_ch[0].DMA_SAIE = 1;
os_sema_up(&dma->done[0]);
}
static void hg_m2m1_dma_irq_handler(void *data)
{
struct mem_dma_dev *dma = (struct mem_dma_dev *)data;
struct mem_dma_hw *hw = (struct mem_dma_hw *)dma->hw;
hw->dma_ch[1].DMA_SAIE = 1;
os_sema_up(&dma->done[1]);
}
#ifdef TXW82X
static void hg_m2m2_dma_irq_handler(void *data)
{
struct mem_dma_dev *dma = (struct mem_dma_dev *)data;
struct mem_dma_hw *hw = (struct mem_dma_hw *)dma->hw;
hw->dma_ch[2].DMA_SAIE = 1;
os_sema_up(&dma->done[2]);
}
#endif
static inline int32 hg_m2m_dma_get_free_ch(struct mem_dma_dev *dev, uint8 ch_fix)
{
int32 ch = (ch_fix >= HG_M2M_DMA_NUM) ? (HG_M2M_DMA_NUM-1) : ch_fix;
uint32 flags = disable_irq();
for (; ch>=0; ) {
if (!(dev->busy_flag & BIT(ch))){
dev->busy_flag |= BIT(ch);
break;
}
if (ch_fix < HG_M2M_DMA_NUM) {
ch = -1;
break;
} else {
ch--;
}
}
enable_irq(flags);
return ch;
}
static inline void hg_m2m_dma_free_ch(struct mem_dma_dev *dev, int32 ch)
{
uint32 flags = disable_irq();
dev->busy_flag &= ~ BIT(ch);
enable_irq(flags);
}
#define is_memset_same_val(n) ((((n) >> 0) & 0xff) == (((n) >> 8) & 0xff))
static void hg_soft_memset(uint32 *dest, uint32 val, uint32 size)
{
uint32 i = 0;
uint8 head_size = (uint32)dest % 4;
uint8 tail_size = ((uint32)dest+size) % 4;
uint32 c_size = ALIGN(size, 4) + ALIGN(head_size, 4);
uint32 *p_dst = (uint32 *)((uint32)dest - head_size);
uint8 *p_dst_bt = (uint8 *)dest;
if (is_memset_same_val(val))
{
os_memset((void*)dest, (val & 0xff), size);
} else {
for (; i < c_size>>2; i++)
*p_dst++ = val;
for (i = head_size; i < (head_size << 1); i++)
*p_dst_bt++ = val>>((i % 4)<<3);
p_dst_bt = (uint8 *)((uint32)dest + size - tail_size);
for (i = tail_size; i < (tail_size << 1); i++)
*p_dst_bt++ = val>>((i % 4)<<3);
}
}
const uint8 dma_element_size[4] = {1,2,4,8};
static int32 hg_m2m_dma_xfer(struct dma_device *dma, struct dma_xfer_data *data)
{
int32 ch = -1;
uint32 val = (data->src_addr_mode == DMA_XFER_MODE_RECYCLE) ? (*((uint32 *)data->src)) : (0);
uint32 count = data->element_num * dma_element_size[data->element_per_width];
static uint8 ch0_lock = 0;
uint32 retry;
uint32 addr_offset = 0;
uint32 dma_cnt = 0;
int32 ret = 0;
struct mem_dma_dev *dev = (struct mem_dma_dev *)dma;
struct mem_dma_hw *hw = (struct mem_dma_hw *)dev->hw;
retry = (__in_interrupt() || in_disable_irq()) ? 1 : (count >> (8+(2*dev->dma1_status)));
if (!retry) retry = 1;
if (data->element_per_width >= DMA_SLAVE_BUSWIDTH_UNDEFINED) {
return -EBUSY;
}
/* get free channel */
for ( ; (!dev->suspend) && (retry--); ) {
if (data->dir != DMA_XFER_DIR_M2M) {
uint32 flags = disable_irq();
ch = hg_m2m_dma_get_free_ch(dev, 0);
if (0 == ch)
ch0_lock = 1;
enable_irq(flags);
} else {
ch = hg_m2m_dma_get_free_ch(dev, ch0_lock ? (HG_M2M_DMA_NUM - 1) : HG_M2M_DMA_NUM);
}
if (ch >= 0) {
break;
}
}
if (ch < 0) {
if (data->src_addr_mode == DMA_XFER_MODE_RECYCLE) {
hg_soft_memset((void*)data->dest, val, count);
} else if(data->src_addr_mode == DMA_XFER_MODE_INCREASE){
os_memcpy((void*)data->dest, (void*)data->src, count);
}
return ch;
}
#ifdef TXW81X
uint32 dst_addr = data->dest>>24;
if (dst_addr == 0x38 || dst_addr == 0x08) {
while(ll_sysctrl_dma2ahb_is_busy((ch) ? (DMA2AHB_BURST_CH_M2M1_WR) : (DMA2AHB_BURST_CH_M2M0_WR)));
}
#endif
//sysctrl_m2m_dma_reset();
#if defined(TXW81X)
hw->dma_ch[ch].DMA_CON &= HG_M2M_DMA_CON_ENDIAN_RES;
hw->dma_ch[ch].DMA_ISIZE = 0;
#elif defined(TXW82X)
hw->dma_ch[ch].DMA_CON = 0x00;
hw->dma_ch[ch].DMA_CON |= HG_M2M_DMA_CON_ENDIAN_SET(data->endian);
#else
hw->dma_ch[ch].DMA_CON = 0x00;
#endif
hw->dma_ch[ch].DMA_DATA = val;
while(count)
{
hw->dma_ch[ch].DMA_TADR = (uint32)data->dest + addr_offset;
hw->dma_ch[ch].DMA_SADR = (uint32)data->src + addr_offset;
dma_cnt = (count > (HG_M2M_DMA_MAX_LEN)) ? (HG_M2M_DMA_MAX_LEN) : (count);
if ((!__in_interrupt()) && (!in_disable_irq()) && (dma_cnt > DMA_LEN_THRESHOLD)) {
hw->dma_ch[ch].DMA_SAIE = 0x10001;
os_sema_eat(&dev->done[ch]);
} else {
hw->dma_ch[ch].DMA_SAIE = 1;
}
hw->dma_ch[ch].DMA_DLEN = dma_cnt - 1;
count -= dma_cnt;
addr_offset += dma_cnt;
if (data->src_addr_mode == DMA_XFER_MODE_RECYCLE) {
hw->dma_ch[ch].DMA_CON |= (HG_M2M_DMA_CON_MEMSET | HG_M2M_DMA_CON_DTE);
} else if(data->src_addr_mode == DMA_XFER_MODE_INCREASE){
hw->dma_ch[ch].DMA_CON |= (HG_M2M_DMA_CON_MEMCPY | HG_M2M_DMA_CON_DTE);
}
if (hw->dma_ch[ch].DMA_SAIE & 0x10000) {
ret = os_sema_down(&dev->done[ch], 50);
if (!ret) {
os_printf(KERN_ERR"hw_dma err: {%08x <--- %08x} len=%d\r\n", hw->dma_ch[ch].DMA_TADR, hw->dma_ch[ch].DMA_SADR, dma_cnt);
}
} else {
while (hw->dma_ch[ch].DMA_CON & HG_M2M_DMA_CON_DTE) {
}
}
}
hw->dma_ch[ch].DMA_CON = 0x00;
hg_m2m_dma_free_ch(dev, ch);
if(ch && dev->dma1_mutex && !dev->dma1_status)
{
dev->dma1_status = true;
hg_m2m_dma_get_free_ch(dev, ch);
}
return ch;
}
static int32 hg_m2m_dma_only_hw_xfer(struct dma_device *dma, struct dma_xfer_data *data)
{
int32 ch = -1;
uint32 val = (data->src_addr_mode == DMA_XFER_MODE_RECYCLE) ? (*((uint32 *)data->src)) : (0);
uint32 count = data->element_num * dma_element_size[data->element_per_width];
static uint8 ch0_lock = 0;
uint32 retry;
uint32 addr_offset = 0;
uint32 dma_cnt = 0;
int32 ret = 0;
struct mem_dma_dev *dev = (struct mem_dma_dev *)dma;
struct mem_dma_hw *hw = (struct mem_dma_hw *)dev->hw;
retry = (__in_interrupt() || in_disable_irq()) ? 1 : (count >> (8+(2*dev->dma1_status)));
if (!retry) retry = 1;
if (data->element_per_width >= DMA_SLAVE_BUSWIDTH_UNDEFINED) {
return -EBUSY;
}
/* get free channel */
for ( ; (!dev->suspend) && (retry); ) {
if (data->dir != DMA_XFER_DIR_M2M) {
uint32 flags = disable_irq();
ch = hg_m2m_dma_get_free_ch(dev, 0);
if (0 == ch)
ch0_lock = 1;
enable_irq(flags);
} else {
ch = hg_m2m_dma_get_free_ch(dev, ch0_lock ? (HG_M2M_DMA_NUM - 1) : HG_M2M_DMA_NUM);
}
if (ch >= 0) {
break;
}
os_sleep_ms(1);
}
#ifdef TXW81X
uint32 dst_addr = data->dest>>24;
if (dst_addr == 0x38 || dst_addr == 0x08) {
while(ll_sysctrl_dma2ahb_is_busy((ch) ? (DMA2AHB_BURST_CH_M2M1_WR) : (DMA2AHB_BURST_CH_M2M0_WR)));
}
#endif
//sysctrl_m2m_dma_reset();
#if defined(TXW81X)
hw->dma_ch[ch].DMA_CON &= HG_M2M_DMA_CON_ENDIAN_RES;
hw->dma_ch[ch].DMA_ISIZE = 0;
#elif defined(TXW82X)
hw->dma_ch[ch].DMA_CON = 0x00;
hw->dma_ch[ch].DMA_CON |= HG_M2M_DMA_CON_ENDIAN_SET(data->endian);
#else
hw->dma_ch[ch].DMA_CON = 0x00;
#endif
hw->dma_ch[ch].DMA_DATA = val;
while(count)
{
hw->dma_ch[ch].DMA_TADR = (uint32)data->dest + addr_offset;
hw->dma_ch[ch].DMA_SADR = (uint32)data->src + addr_offset;
dma_cnt = (count > (HG_M2M_DMA_MAX_LEN)) ? (HG_M2M_DMA_MAX_LEN) : (count);
if ((!__in_interrupt()) && (!in_disable_irq()) && (dma_cnt > DMA_LEN_THRESHOLD)) {
hw->dma_ch[ch].DMA_SAIE = 0x10001;
os_sema_eat(&dev->done[ch]);
} else {
hw->dma_ch[ch].DMA_SAIE = 1;
}
hw->dma_ch[ch].DMA_DLEN = dma_cnt - 1;
count -= dma_cnt;
addr_offset += dma_cnt;
if (data->src_addr_mode == DMA_XFER_MODE_RECYCLE) {
hw->dma_ch[ch].DMA_CON |= (HG_M2M_DMA_CON_MEMSET | HG_M2M_DMA_CON_DTE);
} else if(data->src_addr_mode == DMA_XFER_MODE_INCREASE){
hw->dma_ch[ch].DMA_CON |= (HG_M2M_DMA_CON_MEMCPY | HG_M2M_DMA_CON_DTE);
}
if (hw->dma_ch[ch].DMA_SAIE & 0x10000) {
ret = os_sema_down(&dev->done[ch], 50);
if (!ret) {
os_printf(KERN_ERR"hw_dma err: {%08x <--- %08x} len=%d\r\n", hw->dma_ch[ch].DMA_TADR, hw->dma_ch[ch].DMA_SADR, dma_cnt);
}
} else {
while (hw->dma_ch[ch].DMA_CON & HG_M2M_DMA_CON_DTE) {
}
}
}
hw->dma_ch[ch].DMA_CON = 0x00;
hg_m2m_dma_free_ch(dev, ch);
if(ch && dev->dma1_mutex && !dev->dma1_status)
{
dev->dma1_status = true;
hg_m2m_dma_get_free_ch(dev, ch);
}
return ch;
}
static int32 hg_m2m_dma_get_status(struct dma_device *dma, uint32 chn)
{
struct mem_dma_dev *dev = (struct mem_dma_dev *)dma;
struct mem_dma_hw *hw = (struct mem_dma_hw *)dev->hw;
if (hw->dma_ch[chn].DMA_CON & HG_M2M_DMA_CON_DTE) {
return DMA_IN_PROGRESS;
} else {
return DMA_SUCCESS;
}
}
static int32 hg_m2m_dma_ioctl(struct dma_device *dma, uint32 cmd, int32 param1, int32 param2)
{
int32 ret_val = RET_OK;
switch (cmd)
{
#if (defined(TX81X) || defined(TXW82X))
case DMA_IOCTL_CMD_ENDIAN:{
struct mem_dma_dev *dev = (struct mem_dma_dev *)dma;
struct mem_dma_hw *hw = (struct mem_dma_hw *)dev->hw;
for (int i = 0; i < HG_M2M_DMA_NUM; i++)
hw->dma_ch[i].DMA_CON = ((hw->dma_ch[i].DMA_CON & (~HG_M2M_DMA_CON_ENDIAN_RES)) | HG_M2M_DMA_CON_ENDIAN_SET(param1));
break;
}
case DMA_IOCTL_CMD_CHECK_DMA1_STATUS:{
struct mem_dma_dev *dev = (struct mem_dma_dev *)dma;
ret_val = dev->dma1_status;
break;
}
case DMA_IOCTL_CMD_DMA1_LOCK:{
struct mem_dma_dev *dev = (struct mem_dma_dev *)dma;
int32 ch = hg_m2m_dma_get_free_ch(dev, 1);
if(ch)
{
dev->dma1_status = true;
}else{
hg_m2m_dma_free_ch(dev, ch);
dev->dma1_status = false;
}
dev->dma1_mutex = true;
break;
};
case DMA_IOCTL_CMD_DMA1_UNLOCK:{
struct mem_dma_dev *dev = (struct mem_dma_dev *)dma;
hg_m2m_dma_free_ch(dev, 1);
dev->dma1_mutex = false;
dev->dma1_status = false;
break;
};
#endif
default:
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
#ifdef CONFIG_SLEEP
int32 hg_m2m_dma_suspend(struct dev_obj *dev)
{
struct mem_dma_dev *dma = (struct mem_dma_dev *)dev;
if (dma->suspend) {
return -ENOTSUP;
}
/* force all dma busy */
dma->suspend = 1;
for (int i = 0; i < HG_M2M_DMA_NUM; i++)
while (0 != hg_m2m_dma_get_free_ch(dma, i)) { os_sleep_ms(1); }
return RET_OK;
}
int32 hg_m2m_dma_resume(struct dev_obj *dev)
{
struct mem_dma_dev *dma = (struct mem_dma_dev *)dev;
if (!dma->suspend) {
return -ENOTSUP;
}
hg_m2m_dma_free_ch(dma, 0);
hg_m2m_dma_free_ch(dma, 1);
irq_enable(dma->irq_num);
irq_enable(dma->irq_num+1);
dma->suspend = 0;
return RET_OK;
}
#endif
static const struct dma_hal_ops m2m_ops = {
.xfer = hg_m2m_dma_xfer,
.only_hw_xfer = hg_m2m_dma_only_hw_xfer,
.get_status = hg_m2m_dma_get_status,
.ioctl = hg_m2m_dma_ioctl,
#ifdef CONFIG_SLEEP
.ops.suspend = hg_m2m_dma_suspend,
.ops.resume = hg_m2m_dma_resume,
#endif
};
__init int32 hg_m2m_dma_dev_attach(uint32 dev_id, struct mem_dma_dev *p_dma)
{
#ifdef TXW82X
void *irq_handler[] = {hg_m2m0_dma_irq_handler, hg_m2m1_dma_irq_handler, hg_m2m2_dma_irq_handler};
#else
void *irq_handler[] = {hg_m2m0_dma_irq_handler, hg_m2m1_dma_irq_handler};
#endif
p_dma->dev.dev.ops = (const struct devobj_ops *)&m2m_ops;
p_dma->busy_flag = 0;
p_dma->suspend = 0;
for (uint8 i = 0; i < HG_M2M_DMA_NUM; i++)
{
os_sema_init(&p_dma->done[i], 0);
p_dma->hw->dma_ch[i].DMA_CON = 0x00;
p_dma->hw->dma_ch[i].DMA_SAIE = HG_M2M_DMA_SAIE_TCP_PENDING;
irq_enable(p_dma->irq_num[i]);
request_irq(p_dma->irq_num[i], irq_handler[i], p_dma);
}
dev_register(dev_id, (struct dev_obj *)p_dma);
return RET_OK;
}

1402
sdk/driver/gpio/hggpio_v4.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
#ifndef _HGGPIO_V4_HW_H_
#define _HGGPIO_V4_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Switches for uncommon functions */
#define HGGPIO_V4_DIR_ATOMIC_EN (1)
#define HGGPIO_V4_DRIVER_STRENGTH_EN (1)
#define HGGPIO_V4_DEBUNCE_EN (1)
#define HGGPIO_V4_TOGGLE_EN (1)
#define HGGPIO_V4_SET_ATOMIC_EN (1)
#define HGGPIO_V4_ANALOG_EN (1)
#define HGGPIO_V4_LOCK_EN (0)
#define HGGPIO_V4_INPUT_LAG_EN (0)
#define HGGPIO_V4_ADC_ANALOG_INPUT_EN (0)
#define HGGPIO_V4_TK_ANALOG_INPUT_EN (0)
/**
* @breif huge-ic gpio register definition
*/
struct hggpio_v4_hw {
__IO uint32_t MODE;
__IO uint32_t OTYPE;
__IO uint32_t OSPEEDL;
__IO uint32_t OSPEEDH;
__IO uint32_t PUPL;
__IO uint32_t PUPH;
__IO uint32_t PUDL;
__IO uint32_t PUDH;
__IO uint32_t IDAT;
__IO uint32_t ODAT;
__IO uint32_t BSR;
__IO uint32_t RES0;
__IO uint32_t AFRL;
__IO uint32_t AFRH;
__IO uint32_t TGL;
__IO uint32_t IMK;
__IO uint32_t HY;
__IO uint32_t RES2;
__IO uint32_t RES3;
__IO uint32_t DEBEN;
__IO uint32_t AIOEN;
__IO uint32_t PND;
__IO uint32_t PNDCLR;
__IO uint32_t TRG0;
__IO uint32_t RES4;
__IO uint32_t RES5;
__IO uint32_t RES6;
__IO uint32_t RES7;
__IO uint32_t IEEN;
__IO uint32_t IOFUNCOUTCON0;
__IO uint32_t IOFUNCOUTCON1;
__IO uint32_t IOFUNCOUTCON2;
__IO uint32_t IOFUNCOUTCON3;
} ;
#ifdef __cplusplus
}
#endif
#endif /* _HGGPIO_V4_HW_H_ */

1101
sdk/driver/i2c/hgi2c_v1.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,306 @@
#ifndef _HGI2C_V1_HW_H
#define _HGI2C_V1_HW_H
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup IIC MODULE REGISTER
* @{
*/
/***** CON0(for IIC) Register *****/
#define LL_IIC_CON0_SBC_IE(n) (((n)&0x01) << 30)
#define LL_IIC_CON0_SBC_EN(n) (((n)&0x01) << 29)
#define LL_IIC_CON0_ALERT_IE(n) (((n)&0x01) << 28)
#define LL_IIC_CON0_NOSTRETCH_EN(n) (((n)&0x01) << 27)
#define LL_IIC_CON0_SMBDEV_ADR_EN(n) (((n)&0x01) << 26)
#define LL_IIC_CON0_SMBALERT_EN(n) (((n)&0x01) << 25)
#define LL_IIC_CON0_SMBHOST_ADR_EN(n) (((n)&0x01) << 24)
/*! IIC received NACK signal interrupt enable
*/
#define LL_IIC_CON0_STRONG_DRV_EN (1UL << 23)
/*! IIC received NACK signal interrupt enable
*/
#define LL_IIC_CON0_RX_NACK_IE_EN (1UL << 22)
/*! IIC arbitration loss interrupt enable
*/
#define LL_IIC_CON0_AL_IE_EN (1UL << 21)
/*! IIC received STOP signal interrupt enable
*/
#define LL_IIC_CON0_STOP_IE_EN (1UL << 20)
#define LL_IIC_CON0_ADR_MTH_IE(n) (((n)&0x01) << 19)
#define LL_IIC_CON0_I2C_FILTER_MAX(n) (((n)&0x1F) << 14)
#define LL_IIC_CON0_I2C_AL_EN(n) (((n)&0x01) << 13)
/*! IIC slave broadcast interrupt enable
*/
#define LL_IIC_CON0_BROADCAST_IE_EN (1UL << 12)
#define LL_IIC_CON0_ISP_CMD_LEN(n) (((n)&0x0F) << 8)
#define LL_IIC_CON0_ISP_MODE_EN (1UL << 7)
#define LL_IIC_CON0_TIMEOUTB_IE(n) (((n)&0x01) << 3)
#define LL_IIC_CON0_TIMEOUTA_IE(n) (((n)&0x01) << 2)
/*! The IIC responds to the NACK signal after receiving the data
*/
#define LL_IIC_CON0_TX_NACK (1UL << 1)
/*! IIC slave address bit width
*/
#define LL_IIC_CON0_SLAVE_ADR_WIDTH(n) (((n)&0x01) << 0)
/***** CON1(for IIC) Register *****/
#define LL_IIC_CON1_PING_PONG_EN(n) ((n&0x1) << 12)
#define LL_IIC_CON1_CLRBUFCNT_CLRSSP_EN(n) ((n&0x1) << 11)
#define LL_IIC_CON1_RX_TIMEOUT_IE(n) ((n&0x1) << 10)
/*! IIC DMA interrupt enable
*/
#define LL_IIC_CON1_DMA_IE_EN (1UL << 9)
/*! IIC FIFO overflow interrupt enable
*/
#define LL_IIC_CON1_BUF_OV_IE_EN (1UL << 8)
/*! IIC RX FIFO not empty interrupt enable
*/
#define LL_IIC_CON1_RX_BUF_NOT_EMPTY_IE_EN (1UL << 7)
/*! IIC TX FIFO not full interrupt enable
*/
#define LL_IIC_CON1_TX_BUF_NOT_FULL_IE_EN (1UL << 6)
/*! IIC transfers one frame interrupt enable
*/
#define LL_IIC_CON1_SSP_IE_EN (1UL << 5)
/*! IIC DMA enable
*/
#define LL_IIC_CON1_DMA_EN (1UL << 4)
/*! The IIC is set to the TX direction
*/
#define LL_IIC_CON1_TX_EN (1UL << 3)
/*! IIC working mode
*/
#define LL_IIC_CON1_MODE(n) (((n)&0x01) << 2)
/*! IIC module selet
*/
#define LL_IIC_CON1_IIC_SEL (1UL << 1)
/*! SPI/IIC module enable
*/
#define LL_IIC_CON1_SSP_EN (1UL << 0)
/***** SSP CMD DATA(for IIC) Register *****/
/*! IIC master transfers START signal
*/
#define LL_IIC_CMD_DATA_START_BIT_EN (1UL << 8)
/*! IIC master transfers STOP signal
*/
#define LL_IIC_CMD_DATA_STOP_BIT_EN (1UL << 9)
/*! Write data
*/
#define LL_IIC_CMD_DATA_WRITE(n) (((n)&0xFF) << 0)
/*! Read data
*/
#define LL_IIC_CMD_DATA_READ(n) (((n)>>0) & 0xFF)
/***** BAUD(for IIC) Register *****/
#define LL_IIC_TIMECON_PRESC(n) (((n)&0x0F) << 28)
#define LL_IIC_TIMECON_SCLDEL(n) (((n)&0x0F) << 24)
#define LL_IIC_TIMECON_SDADEL(n) (((n)&0x0F) << 20)
#define LL_IIC_TIMECON_SCLH(n) (((n)&0x3FF) << 10)
#define LL_IIC_TIMECON_SCLL(n) (((n)&0x3FF) << 0)
/***** DMA Tx LEN(for IIC) Register *****/
/*! Set DMA Tx length(12bit)
*/
#define LL_IIC_DMA_TX_LEN(n) (n)
/***** DMA Tx CNT(for IIC) Register *****/
/*! The length of the byte of the received data(12bit)
*/
#define LL_IIC_DMA_TX_CNT(n) (n)
/***** DMA Tx STADR(for IIC) Register *****/
/*! DMA Tx start address(13bit)
*/
#define LL_IIC_DMA_TX_STADR(n) (n)
/***** DMA Rx LEN(for IIC) Register *****/
/*! Set DMA Rx length(12bit)
*/
#define LL_IIC_DMA_RX_LEN(n) (n)
/***** DMA Rx CNT(for IIC) Register *****/
/*! The length of the byte of the received data(12bit)
*/
#define LL_IIC_DMA_RX_CNT(n) (n)
/***** DMA Rx STADR(for IIC) Register *****/
/*! DMA Rx start address(13bit)
*/
#define LL_IIC_DMA_RX_STADR(n) (n)
/***** STA1(for IIC) Register *****/
#define LL_IIC_STA1_HSYNC_PEND_CLR_BUF_CNT (1UL << 31)
#define LL_IIC_STA1_HSYNC_PEND (1UL << 21)
#define LL_IIC_STA1_VSYNC_PEND (1UL << 20)
#define LL_IIC_STA1_DMA_PPBUF_SEL (1UL << 19)
#define LL_IIC_STA1_RX_TIMEOUT_PEND (1UL << 18)
#define LL_IIC_STA1_MODF (1UL << 17)
#define LL_IIC_STA1_SLAVE_WRONG_CMD_PENDING (1UL << 16)
#define LL_IIC_STA1_SLAVE_WIREMODE_CFG_PENDING (1UL << 15)
#define LL_IIC_STA1_SLAVE_RDSTATUS_PENDING (1UL << 14)
#define LL_IIC_STA1_SLAVE_RDDATA_PENDING (1UL << 13)
#define LL_IIC_STA1_SLAVE_WRDATA_PENDING (1UL << 12)
#define LL_IIC_STA1_CLEAR_BUF_CNT (1UL << 9)
/*! Get how many bytes of valid data in the FIFO
*/
#define LL_IIC_STA1_BUF_CNT(n) (((n)& 0x07) )
#define LL_IIC_STA1_MASTER_RX_BUSY_PENDING (1UL << 8)
#define LL_IIC_STA1_SLAVE_CS_STATE (1UL << 7)
#define LL_IIC_STA1_SSP_BUSY_PENDING (1UL << 6)
#define LL_IIC_STA1_NSS_POS_PENDING (1UL << 5)
#define LL_IIC_STA1_DMA_PENDING (1UL << 4)
#define LL_IIC_STA1_BUF_OV_PENDING (1UL << 3)
#define LL_IIC_STA1_BUF_EMPTY_PENDING (1UL << 2)
#define LL_IIC_STA1_BUF_FULL_PENDING (1UL << 1)
#define LL_IIC_STA1_DONE_PENDING (1UL << 0)
/***** STA2(for IIC) Register *****/
#define LL_IIC_STA2_STATE(n) ((n&0x07)<<16)
#define LL_IIC_STA2_TIMEOUTB_PEND(n) ((n&0x01)<<13)
#define LL_IIC_STA2_TIMEOUTA_PEND(n) ((n&0x01)<<12)
#define LL_IIC_STA2_SBC_PEND(n) ((n&0x01)<<11)
#define LL_IIC_STA2_ALERT_PEND(n) ((n&0x01)<<10)
#define LL_IIC_STA2_I2C_AL(n) ((n&0x01)<<9)
#define LL_IIC_STA2_RX_NACK(n) ((n&0x01)<<8)
#define LL_IIC_STA2_STOP_PEND(n) ((n&0x01)<<7)
#define LL_IIC_STA2_I2C_BUS_BUSY(n) ((n&0x01)<<6)
#define LL_IIC_STA2_SLV_RW(n) ((n&0x01)<<5)
#define LL_IIC_STA2_ADRMTHCODE(n) ((n&0x07)<<2)
#define LL_IIC_STA2_SLV_ADDRED(n) ((n&0x01)<<1)
#define LL_IIC_STA2_ADR_MTH_PEND(n) ((n&0x01)<<0)
/***** OWNADRCON(for IIC) Register *****/
#define LL_IIC_OWNADRCON_OWN_ADR2_MASK(n) ((n&0x07)<<24)
#define LL_IIC_OWNADRCON_OWN_ADR2(n) ((n&0x7F)<<17)
#define LL_IIC_OWNADRCON_OWN_ADR2_EN(n) ((n&0x01)<<16)
#define LL_IIC_OWNADRCON_OWN_ADR1_S(n) ((n&0x01)<<11)
#define LL_IIC_OWNADRCON_OWN_ADR1_EN(n) ((n&0x01)<<10)
#define LL_IIC_OWNADRCON_OWN_ADR1(n) ((n&0x3FF)<<0)
/***** RBUF(for IIC) Register *****/
#define LL_IIC_RBUF(n) ((n))
/***** TIMEOUTCON(for IIC) Register *****/
#define LL_IIC_TIMEOUTCON_TIMEOUTB_EN(n) ((n&01)<<31)
#define LL_IIC_TIMEOUTCON_TIMEOUTB(n) ((n&0xFFF)<<16)
#define LL_IIC_TIMEOUTCON_TIMEOUTA_EN(n) ((n&01)<<15)
#define LL_IIC_TIMEOUTCON_TIMEOUTA_S(n) ((n&01)<<12)
#define LL_IIC_TIMEOUTCON_TIMEOUTA(n) ((n&0xFFF)<<0)
/***** RX TIMEOUTCON(for IIC) Register *****/
#define LL_IIC_RXTIMEOUTCON_RX_TIMEOUT(n) ((n&0x1ffffff7)<<1)
#define LL_IIC_RXTIMEOUTCON_RX_TIMEOUT_EN(n) ((n&0x1)<<0)
typedef enum {
/*! IIC does not transmit signals other than ACK.
*/
LL_IIC_NONE_FLAG = 0,
/*! IIC sends START signal
*/
LL_IIC_START_FLAG = 1,
/*! IIC sends STOP signal
*/
LL_IIC_STOP_FLAG = 2,
/*! IIC sends NACK signal
*/
LL_IIC_NACK_FLAG = 4,
} TYPE_ENUM_LL_IIC_FLAG;
/**
* @brief IIC
*/
struct hgi2c_v1_hw {
__IO uint32_t CON0;
__IO uint32_t CON1;
__IO uint32_t CMD_DATA;
__IO uint32_t TIMECON;
__IO uint32_t TDMALEN;
__IO uint32_t RDMALEN;
__IO uint32_t TDMACNT;
__IO uint32_t RDMACNT;
__IO uint32_t TSTADR;
__IO uint32_t RSTADR;
__IO uint32_t STA1;
__IO uint32_t STA2;
__IO uint32_t SLAVESTA;
__IO uint32_t OWNADRCON;
__IO uint32_t RBUF;
__IO uint32_t TIMEOUTCON;
__IO uint32_t RXTIMEOUTCON;
__IO uint32_t RSTADR1;
__IO uint32_t VSYNC_TCON;
__IO uint32_t HSYNC_TCON;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGI2C_V1_HW_H */

908
sdk/driver/i2s/hgi2s_v0.c Normal file
View File

@@ -0,0 +1,908 @@
/**
* @file hgi2s_v0.c
* @author bxd
* @brief iis
* @version
* TXW80X; TXW81X
* @date 2023-08-02
*
* @copyright Copyright (c) 2023
*
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "osal/irq.h"
#include "osal/string.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "hal/i2s.h"
#include "dev/i2s/hgi2s_v0.h"
#include "hgi2s_v0_hw.h"
#define __OVER_SAMPPLE_RATE (512)
struct __iis_cfg {
uint32 mclk_div;
uint32 baud_div;
uint32 wscon_div;
};
const struct __iis_cfg iis_cfg_8k[] = {
/*!
* over_sample: 512.000
* sample_rate: 8000.000
* 8 bit
*/
//mclk_rate:4.103MHz, bclk_rate:128.205KHz, sample_rate:8012.821Hz, error_rate:1602.56ppm,mclk = 116, baud = 15, wscon = 7
{
.mclk_div = 116,
.baud_div = 15,
.wscon_div = 7,
},
/*!
* over_sample: 512.000
* sample_rate: 8000.000
* 16 bit
*/
//mclk_rate:4.103MHz, bclk_rate:256.410KHz, sample_rate:8012.821Hz, error_rate:1602.56ppm,mclk = 116, baud = 7, wscon = 15
{
.mclk_div = 116,
.baud_div = 7,
.wscon_div = 15,
},
/*!
* over_sample: 768.000
* sample_rate: 8000.000
* 24 bit
*/
//mclk_rate:6.154MHz, bclk_rate:384.615KHz, sample_rate:8012.821Hz, error_rate:1602.56ppm,mclk = 77, baud = 7, wscon = 23
{
.mclk_div = 77,
.baud_div = 7,
.wscon_div = 23,
}
};
const struct __iis_cfg iis_cfg_16k[] = {
/*!
* over_sample: 256.000
* sample_rate: 16000.000
* 8 bit
*/
//mclk_rate:4.103MHz, bclk_rate:256.410KHz, sample_rate:16025.641Hz, error_rate:1602.56ppm,mclk = 116, baud = 7, wscon = 7
{
.mclk_div = 116,
.baud_div = 7,
.wscon_div = 7,
},
/*!
* over_sample: 256.000
* sample_rate: 16000.000
* 16 bit
*/
//mclk_rate:4.103MHz, bclk_rate:512.821KHz, sample_rate:16025.641Hz, error_rate:1602.56ppm,mclk = 116, baud = 3, wscon = 15
{
.mclk_div = 116,
.baud_div = 3,
.wscon_div = 15,
},
/*!
* over_sample: 384.000
* sample_rate: 16000.000
* 24 bit
*/
//mclk_rate:6.154MHz, bclk_rate:769.231KHz, sample_rate:16025.641Hz, error_rate:1602.56ppm,mclk = 77, baud = 3, wscon = 23
{
.mclk_div = 77,
.baud_div = 3,
.wscon_div = 23,
}
};
const struct __iis_cfg iis_cfg_44_1k[] = {
/*!
* over_sample: 128.000
* sample_rate: 44100.000
* 16 bit
*/
//mclk_rate:5.647MHz, bclk_rate:705.882KHz, sample_rate:44117.647Hz, error_rate:400.16ppm,mclk = 84, baud = 3, wscon = 7
{
.mclk_div = 84,
.baud_div = 3,
.wscon_div = 7,
},
/*!
* over_sample: 128.000
* sample_rate: 44100.000
* 16 bit
*/
//mclk_rate:5.647MHz, bclk_rate:1411.765KHz, sample_rate:44117.647Hz, error_rate:400.16ppm,mclk = 84, baud = 1, wscon = 15
{
.mclk_div = 84,
.baud_div = 1,
.wscon_div = 15,
},
/*!
* over_sample: 128.000
* sample_rate: 44100.000
* 24 bit
*/
//no support
};
const struct __iis_cfg iis_cfg_48k[] = {
/*!
* over_sample: 256.000
* sample_rate: 48000.000
* 8 bit
*/
//mclk_rate:12.308MHz, bclk_rate:769.231KHz, sample_rate:48076.923Hz, error_rate:1602.56ppm,mclk = 38, baud = 7, wscon = 7
{
.mclk_div = 38,
.baud_div = 7,
.wscon_div = 7,
},
/*!
* over_sample: 768.000
* sample_rate: 48000.000
* 16 bit
*/
//mclk_rate:36.923MHz, bclk_rate:1538.462KHz, sample_rate:48076.923Hz, error_rate:1602.56ppm,mclk = 12, baud = 11, wscon = 15
{
.mclk_div = 12,
.baud_div = 11,
.wscon_div = 15,
},
/*!
* over_sample: 768.000
* sample_rate: 48000.000
* 16 bit
*/
//mclk_rate:36.923MHz, bclk_rate:2307.692KHz, sample_rate:48076.923Hz, error_rate:1602.56ppm,mclk = 12, baud = 7, wscon = 23
{
.mclk_div = 12,
.baud_div = 7,
.wscon_div = 23,
}
};
/**********************************************************************************/
/* I2S LOW LAYER FUNCTION */
/**********************************************************************************/
static int32 hgi2s_v0_switch_hal_i2s_mode(enum i2s_mode mode) {
switch (mode) {
case (I2S_MODE_MASTER ):
return 0;
break;
case (I2S_MODE_SLAVE ):
return 1;
break;
default:
return -1;
break;
}
}
static int32 hgi2s_v0_switch_hal_i2s_channel(enum i2s_channel channel) {
switch (channel) {
case (I2S_CHANNEL_MONO ):
return 1;
break;
case (I2S_CHANNEL_STEREO):
return 0;
break;
default:
return -1;
break;
}
}
static int32 hgi2s_v0_switch_hal_i2s_sample_bits(enum i2s_sample_bits bits) {
switch (bits) {
case (I2S_SAMPLE_BITS_8BITS ):
return 8;
break;
case (I2S_SAMPLE_BITS_16BITS):
return 16;
break;
case (I2S_SAMPLE_BITS_24BITS):
return 24;
break;
default:
return -1;
break;
}
}
static int32 hgi2s_v0_switch_hal_i2s_data_fmt(enum i2s_data_fmt data_fmt) {
switch (data_fmt) {
case (I2S_DATA_FMT_I2S):
return 0;
break;
case (I2S_DATA_FMT_LSB):
return 1;
break;
case (I2S_DATA_FMT_MSB):
return 2;
break;
case (I2S_DATA_FMT_PCM):
return 3;
break;
default:
return -1;
break;
}
}
static const struct __iis_cfg* hgi2s_v0_switch_hal_i2s_sample_freq(enum i2s_sample_freq frequency, enum i2s_sample_bits bits)
{
const struct __iis_cfg *p_iis_cfg = NULL;
int8 index = -1;
if (I2S_SAMPLE_BITS_8BITS ==bits) {index=0;}
if (I2S_SAMPLE_BITS_16BITS==bits) {index=1;}
if (I2S_SAMPLE_BITS_24BITS==bits) {index=2;}
switch (frequency) {
case (I2S_SAMPLE_FREQ_8K):
p_iis_cfg = iis_cfg_8k;
break;
case (I2S_SAMPLE_FREQ_16K):
p_iis_cfg = iis_cfg_16k;
break;
case (I2S_SAMPLE_FREQ_44_1K):
p_iis_cfg = iis_cfg_44_1k;
if (I2S_SAMPLE_BITS_24BITS==bits) {
index=-1; p_iis_cfg=NULL;
os_printf("iis info: no support 44.1k, 24bit\r\n");
}
break;
case (I2S_SAMPLE_FREQ_48K ):
p_iis_cfg = iis_cfg_48k;
break;
default:
return NULL;
break;
}
if ((index==-1) || (p_iis_cfg==NULL)) {
return NULL;
} else {
return &p_iis_cfg[index];
}
}
static inline void hgi2s_v0_set_mclk(struct hgi2s_v0_hw *p_i2s, uint32 mclk_div) {
//uint32 mclk_div = 0;
//IIS0
if (IIS0_BASE == (uint32)p_i2s) {
SYSCTRL_REG_OPT(
SYSCTRL->SYS_CON3 = (SYSCTRL->SYS_CON3 & ~(0x01 << 28)) | (0 << 28);
);
#if 0
/* i2s module clk use pll0 & pll1 */
os_printf("iis0 pll clk:%d\r\n", peripheral_clock_get(HG_APB0_PT_IIS0));
os_printf("iis1 pll clk:%d\r\n", peripheral_clock_get(HG_APB0_PT_IIS0));
mclk_div = ((peripheral_clock_get(HG_APB0_PT_IIS0)+((freq*__OVER_SAMPPLE_RATE)/2)) / (freq*__OVER_SAMPPLE_RATE));
#endif
#if 0
/* FPGA: 96MHz */
mclk_div = (96000000 / (freq*256));
#endif
SYSCTRL_REG_OPT(
SYSCTRL->CLK_CON0 = (SYSCTRL->CLK_CON0 & ~(0x7f << 16)) | ((mclk_div) << 16);
);
}
//IIS1
else if(IIS1_BASE == (uint32)p_i2s){
SYSCTRL_REG_OPT(
SYSCTRL->SYS_CON3 = (SYSCTRL->SYS_CON3 & ~(0x01 << 29)) | (0 << 29);
);
#if 0
/* i2s module clk use pll0 & pll1 */
mclk_div = (peripheral_clock_get(HG_APB0_PT_IIS1) / (freq*256));
#endif
#if 0
/* FPGA: 96MHz */
mclk_div = (96000000 / (freq*256));
#endif
SYSCTRL_REG_OPT(
SYSCTRL->CLK_CON0 = (SYSCTRL->CLK_CON0 & ~(0x7f << 23)) | ((mclk_div) << 23);
);
}
}
static inline void hgi2s_v0_enable(struct hgi2s_v0_hw *p_i2s) {
p_i2s->CON |= LL_I2S_CON_ENABLE(1);
}
static inline void hgi2s_v0_disable(struct hgi2s_v0_hw *p_i2s) {
p_i2s->CON &= ~ LL_I2S_CON_ENABLE(1);
}
static inline void hgi2s_v0_set_tx(struct hgi2s_v0_hw *p_i2s) {
p_i2s->CON |= LL_I2S_CON_WORKMODE(1);
}
static inline void hgi2s_v0_set_rx(struct hgi2s_v0_hw *p_i2s) {
p_i2s->CON &= ~ LL_I2S_CON_WORKMODE(1);
}
static int32 hgi2s_v0_set_wsclk_pol(struct hgi2s_v0_hw *p_i2s, uint32 value) {
hgi2s_v0_disable(p_i2s);
if (value) {
p_i2s->CON |= LL_I2S_CON_WSPOL(1);
} else {
p_i2s->CON &= ~ LL_I2S_CON_WSPOL(1);
}
return RET_OK;
}
static int32 hgi2s_v0_set_sample_bits(struct hgi2s_v0_hw *p_i2s, enum i2s_sample_bits bits) {
int32 i2s_sample_bits_to_reg = 0;
i2s_sample_bits_to_reg = hgi2s_v0_switch_hal_i2s_sample_bits(bits);
if ((-1) == i2s_sample_bits_to_reg) {
return RET_ERR;
}
hgi2s_v0_disable(p_i2s);
p_i2s->BIT_SET = i2s_sample_bits_to_reg;
p_i2s->WS_CON = i2s_sample_bits_to_reg;
p_i2s->BAUD = (64 / i2s_sample_bits_to_reg) - 1;
return RET_OK;
}
static int32 hgi2s_v0_set_channel(struct hgi2s_v0_hw *p_i2s, enum i2s_channel channel) {
int32 i2s_channel_to_reg = 0;
i2s_channel_to_reg = hgi2s_v0_switch_hal_i2s_channel(channel);
if ((-1) == i2s_channel_to_reg) {
return RET_ERR;
}
hgi2s_v0_disable(p_i2s);
p_i2s->CON = (p_i2s->CON &~ LL_I2S_CON_MONO(0x3)) | LL_I2S_CON_MONO(i2s_channel_to_reg);
return RET_OK;
}
static int32 hgi2s_v0_set_data_fmt(struct hgi2s_v0_hw *p_i2s, enum i2s_data_fmt data_fmt) {
int32 i2s_data_fmt_to_reg = 0;
i2s_data_fmt_to_reg = hgi2s_v0_switch_hal_i2s_data_fmt(data_fmt);
if ((-1) == i2s_data_fmt_to_reg) {
return RET_ERR;
}
hgi2s_v0_disable(p_i2s);
p_i2s->CON = (p_i2s->CON &~ LL_I2S_CON_FRMT(0x3)) | LL_I2S_CON_FRMT(i2s_data_fmt_to_reg);
return RET_OK;
}
static int32 hgi2s_v0_set_debounce(struct hgi2s_v0_hw *p_i2s, uint32 enable) {
hgi2s_v0_disable(p_i2s);
if (!enable) {
p_i2s->CON |= LL_I2S_CON_BCLKDBSBPS(1) | LL_I2S_CON_RXDBSBPS(1) | LL_I2S_CON_WSCLKDBSBPS(1);
} else {
p_i2s->CON &= ~(LL_I2S_CON_BCLKDBSBPS(1) | LL_I2S_CON_RXDBSBPS(1) | LL_I2S_CON_WSCLKDBSBPS(1));
}
return RET_OK;
}
static int32 hgi2s_v0_set_duplex(struct hgi2s_v0 *dev, uint32 enable) {
if (enable) {
dev->duplex_en = 1;
} else {
dev->duplex_en = 0;
}
return RET_OK;
}
/**********************************************************************************/
/* I2S ATTCH FUNCTION */
/**********************************************************************************/
int32 hgi2s_v0_open(struct i2s_device *i2s, enum i2s_mode mode, enum i2s_sample_freq frequency, enum i2s_sample_bits bits)
{
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
const struct __iis_cfg *p_iis_cfg = NULL;
uint32 i2s_reg_con = 0;
int32 i2s_mode_to_reg = 0;
int32 i2s_channel_to_reg = 0;
int32 i2s_sample_bits_to_reg = 0;
int32 i2s_data_fmt_to_reg = 0;
//int32 i2s_sample_freq_to_reg = 0;
if (dev->opened) {
if (!dev->dsleep) {
return -EBUSY;
}
}
/* hal enum */
i2s_mode_to_reg = hgi2s_v0_switch_hal_i2s_mode(mode );
i2s_channel_to_reg = hgi2s_v0_switch_hal_i2s_channel(I2S_CHANNEL_STEREO);
i2s_data_fmt_to_reg = hgi2s_v0_switch_hal_i2s_data_fmt(I2S_DATA_FMT_I2S );
i2s_sample_bits_to_reg = hgi2s_v0_switch_hal_i2s_sample_bits(bits );
p_iis_cfg = hgi2s_v0_switch_hal_i2s_sample_freq(frequency,bits);
if (((-1) == i2s_mode_to_reg ) || \
((-1) == i2s_channel_to_reg ) || \
((-1) == i2s_data_fmt_to_reg ) || \
((-1) == i2s_sample_bits_to_reg) || \
((NULL) == p_iis_cfg)) {
return -EINVAL;
}
#if 0
/* make sure the sys_clk */
if (0 != ((peripheral_clock_get(HG_APB0_PT_IIS0)*2) % (i2s_sample_freq_to_reg * 256))) {
return RET_ERR;
}
#endif
/* pin config */
if (pin_func(dev->dev.dev.dev_id , 1) != RET_OK) {
return RET_ERR;
}
/*
* open I2S clk
*/
if (IIS0_BASE == (uint32)hw) {
sysctrl_iis0_clk_open();
} else if (IIS1_BASE == (uint32)hw) {
sysctrl_iis1_clk_open();
}
/*
* clear the regs
*/
hw->BAUD = 0;
hw->BIT_SET = 0;
hw->CON = 0;
hw->DMA_LEN = 0;
hw->DMA_STADR = 0;
hw->WS_CON = 0;
hw->STA = 0xFFFF;
/* reg config */
i2s_reg_con = hw->CON;
i2s_reg_con = LL_I2S_CON_MODE(i2s_mode_to_reg ) |
LL_I2S_CON_MONO(i2s_channel_to_reg ) |
LL_I2S_CON_MCLK_OE(1 ) | /* open mclk to io */
LL_I2S_CON_WSPOL(0 ) |
LL_I2S_CON_BCKPOL(0 ) |
LL_I2S_CON_FRMT(i2s_data_fmt_to_reg) ;
if (mode == I2S_MODE_SLAVE) {
i2s_reg_con |= (LL_I2S_CON_BCLKDBSBPS(0) | LL_I2S_CON_RXDBSBPS(0) | LL_I2S_CON_WSCLKDBSBPS(0));
} else {
//close debounce
i2s_reg_con |= (LL_I2S_CON_BCLKDBSBPS(1) | LL_I2S_CON_RXDBSBPS(1) | LL_I2S_CON_WSCLKDBSBPS(1));
}
hw->CON = i2s_reg_con;
hw->WS_CON = p_iis_cfg->wscon_div;
hw->BAUD = p_iis_cfg->baud_div;
hw->BIT_SET = i2s_sample_bits_to_reg - 1;
if (mode == I2S_MODE_SLAVE) {
hgi2s_v0_set_mclk(hw, 5);
} else {
hgi2s_v0_set_mclk(hw, p_iis_cfg->mclk_div);
}
dev->opened = 1;
dev->duplex_en = 0;
dev->dsleep = 0;
return RET_OK;
}
int32 hgi2s_v0_close(struct i2s_device *i2s) {
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
if (!dev->opened) {
return RET_OK;
}
/*
* close IIS clk
*/
if (IIS0_BASE == (uint32)hw) {
sysctrl_iis0_clk_close();
} else if (IIS1_BASE == (uint32)hw) {
sysctrl_iis1_clk_close();
}
irq_disable(dev->irq_num );
pin_func(dev->dev.dev.dev_id, 0);
hgi2s_v0_disable(hw );
dev->opened = 0;
dev->duplex_en = 0;
dev->dsleep = 0;
return RET_OK;
}
int32 hgi2s_v0_write(struct i2s_device *i2s, const void* buf, uint32 len) {
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
uint32 len_to_reg = 0;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
len_to_reg = len;
hw->DMA_STADR = (uint32)buf;
hw->DMA_LEN = len_to_reg;
hgi2s_v0_set_tx(hw);
if (!dev->duplex_en) {
hgi2s_v0_enable(hw);
}
return RET_OK;
}
int32 hgi2s_v0_read(struct i2s_device *i2s, void* buf, uint32 len) {
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
uint32 len_to_reg = 0;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
len_to_reg = len;
hw->DMA_STADR = (uint32)buf;
hw->DMA_LEN = len_to_reg;
hgi2s_v0_set_rx(hw);
if (!dev->duplex_en) {
hgi2s_v0_enable(hw);
}
return RET_OK;
}
int32 hgi2s_v0_ioctl(struct i2s_device *i2s, uint32 cmd, uint32 param) {
int32 ret_val = RET_OK;
struct hgi2s_v0 *dev = (struct hgi2s_v0*)i2s;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
switch(cmd) {
case (I2S_IOCTL_CMD_SET_WSCLK_POL):
ret_val = hgi2s_v0_set_wsclk_pol(hw , param);
break;
case (I2S_IOCTL_CMD_SET_SAMPLE_BITS):
ret_val = hgi2s_v0_set_sample_bits(hw, param);
break;
case (I2S_IOCTL_CMD_SET_CHANNEL):
ret_val = hgi2s_v0_set_channel(hw , param);
break;
case (I2S_IOCTL_CMD_SET_DATA_FMT):
ret_val = hgi2s_v0_set_data_fmt(hw , param);
break;
case (I2S_IOCTL_CMD_SET_DEBOUNCE):
ret_val = hgi2s_v0_set_debounce(hw , param);
break;
case (I2S_IOCTL_CMD_SET_DUPLEX):
ret_val = hgi2s_v0_set_duplex(dev , param);
break;
default:
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
#ifdef CONFIG_SLEEP
static int32 hgi2s_v0_suspend(struct dev_obj *obj)
{
struct hgi2s_v0 *dev = (struct hgi2s_v0*)obj;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_OK;
}
if (0 > os_mutex_lock(&dev->bp_suspend_lock, 10000)) {
return RET_ERR;
}
/*!
* Close the IIS
*/
hw->CON &= ~ BIT(0);
pin_func(dev->dev.dev.dev_id , 0);
/*
* close irq
*/
irq_disable(dev->irq_num);
/*
* clear pending
*/
hw->STA = 0xFFFFFFFF;
os_memset((void *)&dev->bp_regs, 0, sizeof(dev->bp_regs));
/*
* save the reglist
*/
dev->bp_regs.con = hw->CON;
dev->bp_regs.bit_set = hw->BIT_SET;
dev->bp_regs.baud = hw->BAUD;
dev->bp_regs.ws_con = hw->WS_CON;
dev->bp_regs.dma_stadr = hw->DMA_STADR;
dev->bp_regs.dma_len = hw->DMA_LEN;
/*
* save the irq_hdl created by user
*/
dev->bp_irq_hdl = dev->irq_hdl;
dev->bp_irq_data = dev->irq_data;
/*
* close IIS clk
*/
if (IIS0_BASE == (uint32)hw) {
sysctrl_iis0_clk_close();
} else if (IIS1_BASE == (uint32)hw) {
sysctrl_iis1_clk_close();
}
dev->dsleep = 1;
os_mutex_unlock(&dev->bp_suspend_lock);
return RET_OK;
}
static int32 hgi2s_v0_resume(struct dev_obj *obj)
{
struct hgi2s_v0 *dev = (struct hgi2s_v0*)obj;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
if ((!dev->opened) || (!dev->dsleep)) {
return RET_OK;
}
if (0 > os_mutex_lock(&dev->bp_resume_lock, 10000)) {
return RET_ERR;
}
/* pin config */
if (pin_func(dev->dev.dev.dev_id , 1) != RET_OK) {
return RET_ERR;
}
/*
* open I2S clk
*/
if (IIS0_BASE == (uint32)hw) {
sysctrl_iis0_clk_open();
} else if (IIS1_BASE == (uint32)hw) {
sysctrl_iis1_clk_open();
}
/*
* recovery the reglist from sram
*/
hw->BIT_SET = dev->bp_regs.bit_set;
hw->BAUD = dev->bp_regs.baud;
hw->WS_CON = dev->bp_regs.ws_con;
hw->DMA_STADR = dev->bp_regs.dma_stadr;
hw->DMA_LEN = dev->bp_regs.dma_len;
hw->CON = dev->bp_regs.con;
/*
* recovery the irq handle and data
*/
dev->irq_hdl = dev->bp_irq_hdl;
dev->irq_data = dev->bp_irq_data;
os_memset((void *)&dev->bp_regs, 0, sizeof(dev->bp_regs));
/*!
* Open the IIS
*/
hw->CON |= BIT(0);
/*
* open irq
*/
irq_enable(dev->irq_num);
dev->dsleep = 0;
os_mutex_unlock(&dev->bp_resume_lock);
return RET_OK;
}
#endif
/* interrupt handler */
static void hgi2s_v0_irq_handler(void *data) {
struct hgi2s_v0 *dev = (struct hgi2s_v0 *)data;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
if ((hw->CON & LL_I2S_CON_HF_PEND_IE(1)) && (hw->STA & LL_I2S_STA_DMA_HF_PENGING(1))) {
hw->STA = LL_I2S_STA_DMA_HF_PENGING(1);
if (dev->irq_hdl) {
dev->irq_hdl(I2S_IRQ_FLAG_HALF, dev->irq_data);
}
}
if ((hw->CON & LL_I2S_CON_OV_PEND_IE(1)) && (hw->STA & LL_I2S_STA_DMA_OV_PENGING(1))) {
hw->STA = LL_I2S_STA_DMA_OV_PENGING(1);
if (dev->irq_hdl) {
dev->irq_hdl(I2S_IRQ_FLAG_FULL, dev->irq_data);
}
}
}
/* request interrupt */
int32 hgi2s_v0_request_irq(struct i2s_device *i2s, uint32 irq_flag, i2s_irq_hdl irqhdl, uint32 irq_data) {
struct hgi2s_v0 *dev = (struct hgi2s_v0 *)i2s;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
dev->irq_hdl = irqhdl;
dev->irq_data = irq_data;
request_irq(dev->irq_num, hgi2s_v0_irq_handler, dev);
if (irq_flag & I2S_IRQ_FLAG_HALF) {
hw->CON |= LL_I2S_CON_HF_PEND_IE(1);
}
if (irq_flag & I2S_IRQ_FLAG_FULL) {
hw->CON |= LL_I2S_CON_OV_PEND_IE(1);
}
irq_enable(dev->irq_num);
return RET_OK;
}
int32 hgi2s_v0_release_irq(struct i2s_device *i2s, uint32 irq_flag) {
struct hgi2s_v0 *dev = (struct hgi2s_v0 *)i2s;
struct hgi2s_v0_hw *hw = (struct hgi2s_v0_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
if (irq_flag & I2S_IRQ_FLAG_HALF) {
hw->CON &= ~ LL_I2S_CON_HF_PEND_IE(1);
}
if (irq_flag & I2S_IRQ_FLAG_FULL) {
hw->CON &= ~ LL_I2S_CON_OV_PEND_IE(1);
}
return RET_OK;
}
static const struct i2s_hal_ops i2s_v0_ops = {
.open = hgi2s_v0_open,
.close = hgi2s_v0_close,
.write = hgi2s_v0_write,
.read = hgi2s_v0_read,
.request_irq = hgi2s_v0_request_irq,
.release_irq = hgi2s_v0_release_irq,
.ioctl = hgi2s_v0_ioctl,
#ifdef CONFIG_SLEEP
.ops.suspend = hgi2s_v0_suspend,
.ops.resume = hgi2s_v0_resume,
#endif
};
int32 hgi2s_v0_attach(uint32 dev_id, struct hgi2s_v0 *i2s) {
i2s->opened = 0;
i2s->dsleep = 0;
i2s->irq_hdl = NULL;
i2s->irq_data = 0;
i2s->duplex_en = 0;
i2s->dev.dev.ops = (const struct devobj_ops *)&i2s_v0_ops;
#ifdef CONFIG_SLEEP
os_mutex_init(&i2s->bp_suspend_lock);
os_mutex_init(&i2s->bp_resume_lock);
#endif
irq_disable(i2s->irq_num);
dev_register(dev_id, (struct dev_obj *)i2s);
return RET_OK;
}

View File

@@ -0,0 +1,124 @@
#ifndef _HGI2S_V0_HW_H
#define _HGI2S_V0_HW_H
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup IIS MODULE REGISTER
* @{
*/
/***** CON Register *****/
/*! Filter the RX data from IO
*/
#define LL_I2S_CON_RXDBSBPS(n) (((n)&0x01) << 14)
/*! Filter the WSCLK clock from IO
*/
#define LL_I2S_CON_WSCLKDBSBPS(n) (((n)&0x01) << 13)
/*! Filter the BCLK clock from IO
*/
#define LL_I2S_CON_BCLKDBSBPS(n) (((n)&0x01) << 12)
/*! I2S work mode select
*/
#define LL_I2S_CON_MCLK_OE(n) (((n)&0x01) << 11)
/*! I2S channel mode select
*/
#define LL_I2S_CON_OV_PEND_IE(n) (((n)&0x01) << 10)
/*! I2S BCK clock polarity
*/
#define LL_I2S_CON_HF_PEND_IE(n) (((n)&0x01) << 9)
/*! I2S WS clock polarity
*/
#define LL_I2S_CON_WORKMODE(n) (((n)&0x01) << 8)
/*! sign extension function
*/
#define LL_I2S_CON_MONO(n) (((n)&0x03) << 6)
/*! I2S mode select
*/
#define LL_I2S_CON_BCKPOL(n) (((n)&0x01) << 5)
/*! I2S serial data format
*/
#define LL_I2S_CON_WSPOL(n) (((n)&0x01) << 4)
/*! Receive channel select
*/
#define LL_I2S_CON_MODE(n) (((n)&0x01) << 3)
/*! Transmit channel select
*/
#define LL_I2S_CON_FRMT(n) (((n)&0x03) << 1)
/*! I2S enable
*/
#define LL_I2S_CON_ENABLE(n) (((n)&0x01) << 0)
/***** BIT_SET Register *****/
/*! I2S bit set
*/
#define LL_I2S_BIT_SET_IISBIT(n) (((n)&0x1F) << 0)
/***** BUAD Register *****/
/*! I2S baud set
*/
#define LL_I2S_BAUD_SET_BUAD(n) (((n)&0x3F) << 0)
/***** WSCON Register *****/
/*! I2S wscon set
*/
#define LL_I2S_WSCON_SET_WSCON(n) (((n)&0x3F) << 0)
/***** STA Register *****/
/*! I2S DMA data over pending
*/
#define LL_I2S_STA_DMA_OV_PENGING(n) (((n)&0x01) << 5)
/*! I2S DMA data half pending
*/
#define LL_I2S_STA_DMA_HF_PENGING(n) (((n)&0x01) << 4)
/*! I2S transmit done pending
*/
#define LL_I2S_STA_DONE_PENGING(n) (((n)&0x01) << 3)
/*! I2S work state pending
*/
#define LL_I2S_STA_WORK_STATE_PENGING(n) (((n)&0x01) << 2)
/*! I2S fifo write full pending
*/
#define LL_I2S_STA_FIFO_WFULL_PENGING(n) (((n)&0x01) << 1)
/*! I2S fifo read empty pending
*/
#define LL_I2S_STA_FIFO_REMPTY_PENGING(n) (((n)&0x01) << 0)
/***** STADR0 Register *****/
/*! I2S DMA address config
*/
#define LL_I2S_STADR_DMA_ADDR0(n) (((n)&0xFFFFFFFF) << 0)
/***** DMALEN Register *****/
/*! I2S DMA len config
*/
#define LL_I2S_DMALEN_LEN(n) (((n)&0xFFFF) << 0)
/** @brief I2S register structure
* @{
*/
struct hgi2s_v0_hw {
__IO uint32_t CON;
__IO uint32_t BIT_SET;
__IO uint32_t BAUD;
__IO uint32_t WS_CON;
__IO uint32_t STA;
__IO uint32_t DMA_STADR;
__IO uint32_t RESERVE;
__IO uint32_t DMA_LEN;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGI2S_V0_HW_H */

834
sdk/driver/jpeg/hgjpg_v3.c Normal file
View File

@@ -0,0 +1,834 @@
#include "sys_config.h"
#include "tx_platform.h"
#include "list.h"
#include "dev.h"
#include "typesdef.h"
#include "lib/video/dvp/cmos_sensor/csi.h"
#include "dev/csi/hgdvp.h"
#include "devid.h"
#include "osal/irq.h"
#include "osal/string.h"
#include "dev/jpg/hgjpg.h"
#include "lib/video/dvp/jpeg/jpg.h"
#include "hal/jpeg.h"
#include "osal/task.h"
#include "osal/sleep.h"
//调用外部接口
void driver_timer_add(int32_t (*func)(void *arg,uint32_t kick_time), void *arg);
struct hgjpg_hw
{
__IO uint32 CSR0;
__IO uint32 CSR1;
__IO uint32 CSR2;
__IO uint32 CSR3;
__IO uint32 DMA_CON;
__IO uint32 DMA_CON1;
__IO uint32 DMA_STA;
__IO uint32 DMA_TADR0;
__IO uint32 DMA_TADR1;
__IO uint32 DMA_DLEN;
__IO uint32 DMA_DHT_ADR;
__IO uint32 DMA_DADR;
__IO uint32 DMA_DTO;
__IO uint32 DMA_SF_YADR;
__IO uint32 DMA_SF_UADR;
__IO uint32 DMA_SF_VADR;
};
struct hgjpg_table_hw
{
__IO uint32 DQT[32];
};
struct hgjpg_huff_hw
{
__IO uint32_t HUFF[192];
};
struct jpg_device *p_jpg_global[JPG_NUM];
volatile uint8_t jpg_ready[JPG_NUM];
volatile uint8_t jpg_oe_enable[JPG_NUM];
volatile uint8_t jpg_oe_used[JPG_NUM];
volatile uint8_t jpg_oe_ok[JPG_NUM];
extern volatile uint8 isp_ov_err;
jpg_irq_hdl jpgirq_vector_table[JPG_NUM][JPG_IRQ_NUM];
void * jpgirq_dev_table[JPG_NUM][JPG_IRQ_NUM];
void irq_jpg_enable(struct hgjpg_hw *p_jpg,uint8 mode,uint8 irq){
if(mode){
p_jpg->DMA_CON |= BIT(irq+13);
}else{
p_jpg->DMA_CON &= ~BIT(irq+13);
}
}
extern volatile uint8_t vpp_oe;
void JPG_IRQHandler_action(void *p_jpg)
{
uint32 jpgr = 0;
uint32 sta = 0;
uint8_t jpg_err = 0;
uint8 dec_err = 0;
uint32 arg = 0;
uint32 arg2 = 0;
int8_t loop;
struct hgjpg *jpg_hw;// = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw;// = (struct hgjpg_hw *)jpg_hw->hw;
jpgr = *(volatile uint32_t*)0x40005200; //fix jpg reg error bug,imp
uint8_t src_from;
if(p_jpg_global[0]){
jpg_hw = (struct hgjpg*)p_jpg_global[0];
hw = (struct hgjpg_hw *)jpg_hw->hw;
sta = (hw->DMA_STA & ((hw->DMA_CON >> 13) &0x01f));
src_from = (hw->DMA_CON& 0xE0)>>5;
for(loop = JPG_IRQ_NUM-1;loop >= 0;loop--) {
if(sta&BIT(loop)){
if(jpg_hw->opened)
{
if(loop == DONE_IRQ){
//_os_printf("--(%d)",SCHED->BW_STA_CNT);
jpg_hw->addr_count = 0;
arg = hw->DMA_DLEN;
if(jpg_hw->deal_time != ((hw->DMA_STA>>16)&0xff)){
arg2 = 1;
}
jpg_hw->deal_time = 0;
}
else if(loop == JPG_BUF_ERR){
_os_printf(KERN_INFO"hw->DMA_STA0:%x\r\n",hw->DMA_STA);
jpg_hw->addr_count = 0;
arg = hw->DMA_DLEN;
jpg_hw->deal_time = 0;
}else if(loop == JPG_OUTBUF_FULL){
jpg_hw->deal_time++;
}
if(isp_ov_err && (jpg_hw->decode== 0 && (src_from == 0 || src_from == 1 || src_from == 3))){
if(loop == DONE_IRQ){
jpgirq_vector_table[0][JPG_BUF_ERR] (loop,(uint32)jpgirq_dev_table[0][JPG_BUF_ERR],arg,arg2);
jpg_err = 1;
}
}
//如果有错,就不再继续执行其他的中断
if(jpg_err==0 && jpgirq_vector_table[0][loop] != NULL)
jpgirq_vector_table[0][loop] (loop,(uint32)jpgirq_dev_table[0][loop],arg,arg2);
if(loop == JPG_BUF_ERR)
{
jpg_err = 1;
}
}
hw->DMA_STA = BIT(loop);
}
}
}
if(p_jpg_global[1]){
jpg_hw = (struct hgjpg*)p_jpg_global[1];
hw = (struct hgjpg_hw *)jpg_hw->hw;
sta = (hw->DMA_STA & ((hw->DMA_CON >> 13) &0x1f));
src_from = (hw->DMA_CON& 0xE0)>>5;
for(loop = JPG_IRQ_NUM-1;loop >= 0;loop--) {
if(sta&BIT(loop)){
if(jpg_hw->opened || jpg_hw->decode)
{
if(loop == DONE_IRQ){
jpg_hw->addr_count = 0;
arg = hw->DMA_DLEN;
if(jpg_hw->deal_time != ((hw->DMA_STA>>16)&0xff)){
arg2 = 1;
}
jpg_hw->deal_time = 0;
jpg_hw->decode = 0;
}
else if(loop == JPG_BUF_ERR){
_os_printf(KERN_INFO"hw->DMA_STA1:%x\r\n",hw->DMA_STA);
jpg_hw->addr_count = 0;
arg = hw->DMA_DLEN;
jpg_hw->deal_time = 0;
jpg_hw->decode = 0;
if(hw->DMA_STA & BIT(8)){
dec_err = 1;
}
}else if(loop == JPG_OUTBUF_FULL){
jpg_hw->deal_time++;
}
if(isp_ov_err && (jpg_hw->decode== 0 && (src_from == 0 || src_from == 1 || src_from == 3))){
if(loop == DONE_IRQ){
jpgirq_vector_table[1][JPG_BUF_ERR] (loop,(uint32)jpgirq_dev_table[1][JPG_BUF_ERR],arg,arg2);
jpg_err = 1;
}
}
if(jpgirq_vector_table[1][loop] != NULL)
jpgirq_vector_table[1][loop] (loop,(uint32)jpgirq_dev_table[1][loop],arg,arg2);
if(dec_err == 1){
jpg_hw->decode = 0;
hw->DMA_CON |= BIT(12); //复位
__NOP();__NOP();__NOP();
}
}
hw->DMA_STA = BIT(loop);
}
}
}
}
/*
int32 hgjpg_set_len(struct jpg_device *p_jpg,uint32 buflen,uint32 head_reserver){
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
hw->DMA_CON |= ((buflen - head_reserver)<<16);
return 0;
}
*/
void jpg_table_init(struct hgjpg_hw *p_jpg,struct hgjpg_table_hw* p_jpg_dqt,struct hgjpg_huff_hw *p_jpg_huff,uint32 table_index){
uint32 itk = 0;
uint32 *ptable;
ptable = (uint32*)quality_tab[table_index];
for(itk = 0;itk <32;itk++){
p_jpg_dqt->DQT[itk] = ptable[itk];
}
#if 0
uint16 *huftbl;
huftbl = (uint16_t*)htable;
for(itk = 0;itk <384;itk=itk+2){
p_jpg_huff->HUFF[itk/2] = (uint32)huftbl[itk]|(uint32)huftbl[itk+1]<<12;
}
#endif
p_jpg->DMA_DHT_ADR = (uint32)dhtable;
}
static void jpg_huff_init(struct hgjpg* jpg)
{
struct hgjpg_huff_hw *p_jpg_huff = (struct hgjpg_huff_hw *)jpg->huf_hw;
uint32 itk = 0;
uint16 *huftbl;
huftbl = (uint16_t*)htable;
for(itk = 0;itk <384;itk=itk+2)
{
p_jpg_huff->HUFF[itk/2] = (uint32)huftbl[itk]|(uint32)huftbl[itk+1]<<12;
}
}
void jpg_csr_encode_config(struct hgjpg_hw *p_jpg,uint32 image_h,uint32 image_w){
p_jpg->CSR1 = (image_h<<16)|BIT(2)|BIT(8);
if((image_h%16) != 0)
image_h = ((image_h/16)+1)*16;
p_jpg->CSR2 = ((image_h * image_w) /256)-1;
p_jpg->CSR3 = (image_w<<16)|(image_w/16 - 1);
}
int32 hgjpg_open(struct jpg_device *p_jpg){
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
uint8 jpg_chose;
//fix psram read data lock bug
//burst enable 0
//1ms
//burst enable 1
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
//hw->CSR1 = 0;
uint32_t jpgr = *(volatile uint32_t*)0x40005200; //fix jpg reg error bug,imp
(void)jpgr;
}
//SCHED->BW_STA_CYCLE = 60000000;
//SCHED->CTRL_CON |=BIT(1);
//open之前先将pending清除(预防之前pengding有残留)
hw->DMA_STA = hw->DMA_STA;
jpg_hw->decode = 0;
jpg_hw->opened = 1;
jpg_ready[jpg_chose] = 1;
hw->DMA_CON |= BIT(0); //enable jpg
hw->DMA_CON1 |= BIT(5);
//hw->CSR0 = 1;
irq_enable(jpg_hw->irq_num);
return 0;
}
int32_t hgjpg_timer_close(void *arg,uint32_t kick_time)
{
struct hgjpg *jpg_hw = (struct hgjpg*)arg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
int32_t ret = 1;
//代表jpg已经完成
if(!(hw->DMA_STA&(0x7<<25)))
{
ret = 0;
}
//超时也要退出
if(os_jiffies() - kick_time > 1000)
{
ret = 0;
}
//关闭jpg
if(!ret)
{
uint8_t jpg_chose = 0;
uint32_t flag;
flag = disable_irq();
hw->DMA_CON &= ~(7<<5);
hw->DMA_CON |= (SOFT_DATA <<5);
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
}
enable_irq(flag);
flag = disable_irq();
hw->DMA_CON &= ~BIT(0); //disable jpg
hw->DMA_STA = hw->DMA_STA;
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
hw->CSR1 = 0;
uint32_t jpgr = *(volatile uint32_t*)0x40005200; //fix jpg reg error bug,imp
(void)jpgr;
}
jpg_ready[jpg_chose] = 0;
enable_irq(flag);
jpg_hw->opened = 0;
jpg_hw->decode = 0;
jpg_hw->addr_count = 0;
jpg_hw->jpg_run = 0;
}
return ret;
}
int32 hgjpg_close(struct jpg_device *p_jpg){
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
uint8_t jpg_chose = 0;
uint32_t flag;
uint32_t in_disable_irq(void);
if(!(__in_interrupt() || in_disable_irq()))
{
//在线程,jpg的close启动timer去操作
driver_timer_add(hgjpg_timer_close,(void*)jpg_hw);
}
//在中断,则直接去关闭
else
{
hw->DMA_CON &= ~(7<<5);
hw->DMA_CON |= (SOFT_DATA <<5);
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
}
flag = disable_irq();
hw->DMA_CON &= ~BIT(0); //disable jpg
hw->DMA_STA = hw->DMA_STA;
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
//hw->CSR1 = 0;
uint32_t jpgr = *(volatile uint32_t*)0x40005200; //fix jpg reg error bug,imp
(void)jpgr;
}
jpg_ready[jpg_chose] = 0;
enable_irq(flag);
jpg_hw->opened = 0;
jpg_hw->decode = 0;
jpg_hw->addr_count = 0;
jpg_hw->jpg_run = 0;
}
return 0;
}
int32 hgjpg_suspend(struct dev_obj *obj){
struct hgjpg *jpg_hw = (struct hgjpg*)obj;
struct hgjpg_hw *hw;
struct hgjpg_hw *hw_cfg;
jpg_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgjpg_hw));
//memcpy((uint8 *)p_jpg->cfg_backup,(uint8 *)jpg_hw->hw,sizeof(struct hgjpg_hw));
hw_cfg = (struct hgjpg_hw*)jpg_hw->cfg_backup;
hw = (struct hgjpg_hw*)jpg_hw->hw;
hw_cfg->CSR0 = hw->CSR0;
hw_cfg->CSR1 = hw->CSR1;
hw_cfg->CSR2 = hw->CSR2;
hw_cfg->CSR3 = hw->CSR3;
hw_cfg->DMA_CON1= hw->DMA_CON1;
hw_cfg->DMA_STA = hw->DMA_STA;
hw_cfg->DMA_DHT_ADR = hw->DMA_DHT_ADR;
hw_cfg->DMA_DADR= hw->DMA_DADR;
hw_cfg->DMA_DTO = hw->DMA_DTO;
hw_cfg->DMA_SF_YADR = hw->DMA_SF_YADR;
hw_cfg->DMA_SF_UADR = hw->DMA_SF_UADR;
hw_cfg->DMA_SF_VADR = hw->DMA_SF_VADR;
hw_cfg->DMA_TADR0 = hw->DMA_TADR0;
hw_cfg->DMA_TADR1 = hw->DMA_TADR1;
hw_cfg->DMA_DLEN = hw->DMA_DLEN;
hw_cfg->DMA_CON = hw->DMA_CON;
irq_disable(jpg_hw->irq_num);
return 0;
}
int32 hgjpg_resume(struct dev_obj *obj){
uint32 jpgr = 0;
struct hgjpg *jpg_hw = (struct hgjpg*)obj;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
struct hgjpg_hw *hw_cfg;
struct hgjpg_table_hw *thw = (struct hgjpg_table_hw *)jpg_hw->thw;
struct hgjpg_huff_hw *hufhw = (struct hgjpg_huff_hw *)jpg_hw->huf_hw;
//memcpy((uint8 *)jpg_hw->hw,(uint8 *)p_jpg->cfg_backup,sizeof(struct hgjpg_hw));
// SCHED->BW_STA_CYCLE = SYS_CLK;
SYSCTRL->CPU1_CON1 &= ~BIT(17);
// SCHED->CTRL_CON |=BIT(1);
SYSCTRL->SYS_CON8 |= BIT(8); //960M enable
SYSCTRL->SYS_CON14 &= ~(7<<29);
SYSCTRL->SYS_CON14 |= (6<<29); //mjpeg_pll2x_divnp5 div 3
SYSCTRL->SYS_CON14 |= BIT(28); //mjpeg_pll2x_divnp5 en
SYSCTRL->CLK_CON6 &= ~(3<<30);
SYSCTRL->CLK_CON6 |= (1<<30); //select mjpeg_pll2x_divnp5
SYSCTRL->CLK_CON6 &= (~(7<<0)); //mjpeg 1div
SYSCTRL->CPU1_CON0 |= BIT(0);
SYSCTRL->CLK_CON3 |= BIT(14); //mjpg0 clk en
SYSCTRL->CLK_CON4 |= BIT(0); //mjpg1 clk en
SYSCTRL->SYS_CON7 &= ~BIT(10);
SYSCTRL->SYS_CON7 |= BIT(10); //JPG0
SYSCTRL->SYS_CON7 &= ~BIT(20);
SYSCTRL->SYS_CON7 |= BIT(20); //JPG1
jpgr = *(volatile uint32_t*)0x40005200; //fix jpg reg error bug,imp
hw_cfg = (struct hgjpg_hw*)jpg_hw->cfg_backup;
jpg_table_init(hw,thw,hufhw,0x01);
hw->CSR0 = hw_cfg->CSR0;
hw->CSR1 = hw_cfg->CSR1;
hw->CSR2 = hw_cfg->CSR2;
hw->CSR3 = hw_cfg->CSR3;
hw->DMA_CON1= hw_cfg->DMA_CON1;
hw->DMA_STA = hw_cfg->DMA_STA;
hw->DMA_DHT_ADR = hw_cfg->DMA_DHT_ADR;
hw->DMA_DADR= hw_cfg->DMA_DADR;
hw->DMA_DTO = hw_cfg->DMA_DTO;
hw->DMA_SF_YADR = hw_cfg->DMA_SF_YADR;
hw->DMA_SF_UADR = hw_cfg->DMA_SF_UADR;
hw->DMA_SF_VADR = hw_cfg->DMA_SF_VADR;
hw->DMA_TADR0 = hw_cfg->DMA_TADR0;
hw->DMA_TADR1 = hw_cfg->DMA_TADR1;
hw->DMA_DLEN = hw_cfg->DMA_DLEN;
hw->DMA_CON = hw_cfg->DMA_CON;
jpgr = *(volatile uint32_t*)0x40005200;
irq_enable(jpg_hw->irq_num);
os_free(jpg_hw->cfg_backup);
return 0;
}
int32 hgjpg_init(struct jpg_device *p_jpg,uint32 table_index,uint32 qt){
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
struct hgjpg_table_hw *thw = (struct hgjpg_table_hw *)jpg_hw->thw;
struct hgjpg_huff_hw *hufhw = (struct hgjpg_huff_hw *)jpg_hw->huf_hw;
hw->DMA_CON |= BIT(12); //复位
__NOP();__NOP();__NOP();
SYSCTRL->CLK_CON3 |= BIT(14);
SYSCTRL->SYS_CON0 |= BIT(2); //
jpg_table_init(hw,thw,hufhw,table_index);
hw->DMA_CON = (qt<<1);
jpg_hw->addr_count = 0;
return 0;
}
int32 hgjpg_set_addr(struct jpg_device *p_jpg,uint32 param,uint32 buflen){
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
uint8 jpg_chose;
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
}
if(jpg_hw->jpg_run == 0){
//printf("#################hw:%X\n",hw);
//os_printf("jpg_hw->addr_count:%d\n",jpg_hw->addr_count);
//os_printf("jpg_ready[jpg_chose]:%d\t%d\n",jpg_ready[jpg_chose],jpg_chose);
//os_printf("jpg_chose:%d\n",jpg_chose);
jpg_hw->jpg_run = 1;
jpg_hw->set_buf_len = 1;
}
if(jpg_hw->addr_count%2){
hw->DMA_TADR1 = param;
}else{
if(jpg_ready[jpg_chose]){
hw->DMA_TADR0 = param;
//hw->DMA_CON1 &= ~BIT(5);
hw->DMA_CON1 |= BIT(5);
jpg_ready[jpg_chose] = 0;
}else{
hw->DMA_TADR0 = param;
}
}
if(jpg_hw->set_buf_len){
hw->DMA_CON |= ((buflen/4-1)<<20);
jpg_hw->set_buf_len = 0;
}
jpg_hw->addr_count++;
return 0;
}
//decode to scaler
int32 hgjpg_decode(struct jpg_device *p_jpg,uint32 photo,uint32_t len){
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
if(hw->DMA_CON & BIT(0)){
hw->DMA_CON &= ~BIT(0);
}
hw->DMA_CON &= ~(7<<5);
hw->DMA_CON |= BIT(12); //复位
__NOP();__NOP();__NOP();
//hw->DMA_CON &= ~BIT(12);
hw->CSR1 = BIT(3)|BIT(8);
hw->DMA_DADR = photo;
jpg_hw->decode = 1;
if (len % 4) {
len = len + 4;
}
//寄存器检查仅仅支持1M以下
if(len != 0 && len < 0x100000){
hw->DMA_DLEN = len; //需要word对齐
hw->DMA_CON1 |= BIT(1);
}
else
{
hw->DMA_CON1 &= ~BIT(1);
}
hw->DMA_CON &= ~(0xf<<1);
hw->DMA_CON |= BIT(4);
hw->DMA_CON |= BIT(0);
irq_enable(jpg_hw->irq_num);
return 0;
}
int32 hgjpg_ioctl(struct jpg_device *p_jpg,uint32 cmd,uint32 param1,uint32 param2){
int32 ret_val = RET_OK;
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
struct hgjpg_table_hw *thw = (struct hgjpg_table_hw *)jpg_hw->thw;
uint8 jpg_chose;
uint32* dqt;
uint32 itk;
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
}
switch(cmd){
case JPG_IOCTL_CMD_IS_ONLINE:
return jpg_hw->opened;
break;
case JPG_IOCTL_CMD_SET_ADR:
hgjpg_set_addr(p_jpg,param1,param2);
break;
case JPG_IOCTL_CMD_SET_QT:
hw->DMA_CON &= ~(0xf<<1);
hw->DMA_CON |= (param1<<1);
break;
case JPG_IOCTL_CMD_SET_SIZE:
jpg_csr_encode_config(hw,param1,param2);
break;
case JPG_IOCTL_CMD_UPDATE_QT:
dqt = (uint32*)param1;
for(itk = 0;itk <32;itk++){
thw->DQT[itk] = dqt[itk];
}
break;
case JPG_IOCTL_CMD_DECODE_TAG:
if(param1){
hw->DMA_CON |= BIT(8);
}else{
hw->DMA_CON &= ~BIT(8);
}
break;
/*
case JPG_IOCTL_CMD_OPEN_DBG:
if(param1){
hw->DMA_CON |= BIT(10);
}else{
hw->DMA_CON &= ~BIT(10);
}
break;
*/
case JPG_IOCTL_CMD_SOFT_FRAME_START:
hw->DMA_CON |= BIT(10);
break;
case JPG_IOCTL_CMD_SOFT_KICK:
hw->DMA_CON |= BIT(9);
break;
case JPG_IOCTL_CMD_SET_SRC_FROM:
hw->DMA_CON &= ~(7<<5);
hw->DMA_CON |= (param1 <<5);
break;
case JPG_IOCTL_CMD_HW_CHK:
if(param1){
hw->DMA_CON |= BIT(11);
}else{
hw->DMA_CON &= ~BIT(11);
}
break;
case JPG_IOCTL_CMD_IS_IDLE:
if(hw->DMA_STA&(0x7<<25)){
ret_val = 0;
}else{
ret_val = 1;
}
break;
case JPG_IOCTL_CMD_BUFF_INIT:
if(param1 == 1){
hw->DMA_CON1 |= BIT(5);
}else{
hw->DMA_CON1 &= ~BIT(5);
}
break;
case JPG_IOCTL_CMD_VSYNC_DLY:
if(param1 == 1){
hw->DMA_CON1 |= BIT(4);
}else{
hw->DMA_CON1 &= ~BIT(4);
}
break;
case JPG_IOCTL_CMD_SET_SOFT_Y:
hw->DMA_SF_YADR = param1;
break;
case JPG_IOCTL_CMD_SET_SOFT_UV:
hw->DMA_SF_UADR = param1;
hw->DMA_SF_VADR = param2;
break;
case JPG_IOCTL_CMD_TIMEOUT_CNT:
hw->DMA_DTO = param1;
break;
case JPG_IOCTL_CMD_TIMEOUT_EN:
hw->DMA_CON1 |= BIT(3);
break;
case JPG_IOCTL_CMD_DECAUTO_RUN_EN:
hw->DMA_CON1 |= BIT(2);
break;
case JPG_IOCTL_CMD_DEC_LEN_CFG_EN:
//SET this bit ,may set the dlen len reg, otherwise while auto dec until finish or timeout err happen
if(param1){
hw->DMA_CON1 |= BIT(1);
}else{
hw->DMA_CON1 &= ~BIT(1);
}
break;
case JPG_IOCTL_CMD_DEC_FLUSH_EN:
//set this bit,dec while run ,but not set data to memory,just check dec right or false
if(param1){
hw->DMA_CON1 |= BIT(0);
}else{
hw->DMA_CON1 &= ~BIT(0);
}
break;
case JPG_IOCTL_CMD_CODEC_RESET:
hw->DMA_CON |= BIT(12);
break;
case JPG_IOCTL_CMD_SET_DLEN:
hw->DMA_DLEN = param1;
break;
case JPG_IOCTL_CMD_SET_READY:
jpg_ready[jpg_chose] = 1;
break;
case JPG_IOCTL_CMD_SET_OE_SELECT:
if(param1 == 1){
jpg_oe_enable[jpg_chose] = 1;
jpg_oe_used[jpg_chose] = param2;
}else{
jpg_oe_enable[jpg_chose] = 0;
}
break;
case JPG_IOCTL_CMD_SET_OE:
jpg_oe_ok[jpg_chose] = param1;
break;
case JPG_IOCTL_CMD_GET_OE:
if(jpg_oe_enable[jpg_chose] == 1){
if(jpg_oe_ok[jpg_chose] == jpg_oe_used[jpg_chose]){
ret_val = 1;
}else{
ret_val = 0;
}
}else{
ret_val = 1;
}
break;
default:
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
int32 jpgirq_register(struct jpg_device *p_jpg, jpg_irq_hdl isr,uint32 irq_flag, uint32 irq_data)
{
uint8 jpg_chose;
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
uint32 irq_num = 0;
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
}
p_jpg_global[jpg_chose] = p_jpg;
request_irq(MJPEG01_IRQn, JPG_IRQHandler_action, NULL);
if(irq_flag == JPG_IRQ_FLAG_JPG_DONE ){
irq_num = DONE_IRQ;
}else if(irq_flag == JPG_IRQ_FLAG_JPG_BUF_FULL ){
irq_num = JPG_OUTBUF_FULL;
}else if(irq_flag == JPG_IRQ_FLAG_ERROR ){
irq_num = JPG_BUF_ERR;
}else if(irq_flag == JPG_IRQ_FLAG_PIXEL_DONE ){
irq_num = JPG_PIXEL_DONE;
}else if(irq_flag == JPG_IRQ_FLAG_TIME_OUT){
irq_num = JPG_TIME_OUT;
}
irq_jpg_enable(hw, 1, irq_num);
jpgirq_vector_table[jpg_chose][irq_num] = isr;
jpgirq_dev_table[jpg_chose][irq_num] = (void *)irq_data;
hw->DMA_STA |= BIT(irq_num);
return 0;
}
int32 jpgirq_unregister(struct jpg_device *p_jpg,uint32 irq_flag){
uint8 jpg_chose;
struct hgjpg *jpg_hw = (struct hgjpg*)p_jpg;
struct hgjpg_hw *hw = (struct hgjpg_hw *)jpg_hw->hw;
uint32 irq_num = 0;
if(hw == (void *)MJPEG0_BASE){
jpg_chose = 0;
}
if(hw == (void *)MJPEG1_BASE){
jpg_chose = 1;
}
if(irq_flag == JPG_IRQ_FLAG_JPG_DONE ){
irq_num = DONE_IRQ;
}else if(irq_flag == JPG_IRQ_FLAG_JPG_BUF_FULL ){
irq_num = JPG_OUTBUF_FULL;
}else if(irq_flag == JPG_IRQ_FLAG_ERROR ){
irq_num = JPG_BUF_ERR;
}else if(irq_flag == JPG_IRQ_FLAG_PIXEL_DONE ){
irq_num = JPG_PIXEL_DONE;
}else if(irq_flag == JPG_IRQ_FLAG_TIME_OUT){
irq_num = JPG_TIME_OUT;
}
irq_jpg_enable(hw, 0, irq_num);
jpgirq_vector_table[jpg_chose][irq_num] = NULL;
jpgirq_dev_table[jpg_chose][irq_num] = NULL;
hw->DMA_STA |= BIT(irq_num);
return 0;
}
static const struct jpeg_hal_ops jpeg_ops = {
.open = hgjpg_open,
.close = hgjpg_close,
.init = hgjpg_init,
.decode = hgjpg_decode,
.ioctl = hgjpg_ioctl,
.request_irq = jpgirq_register,
.release_irq = jpgirq_unregister,
#ifdef CONFIG_SLEEP
.ops.suspend = hgjpg_suspend,
.ops.resume = hgjpg_resume,
#endif
};
void hgjpg_attach(uint32 dev_id, struct hgjpg *jpg)
{
jpg->dev.dev.ops = (const struct devobj_ops *)&jpeg_ops;
irq_disable(jpg->irq_num);
dev_register(dev_id, (struct dev_obj *)jpg);
jpg_huff_init(jpg);
}

View File

@@ -0,0 +1,227 @@
#include "typesdef.h"
#include "errno.h"
#include "osal/irq.h"
#include "devid.h"
#include "dev/osd_enc/hgosd_enc.h"
#include "osal/string.h"
struct hgosdenc_hw
{
__IO uint32 OSD_ENC_CON;
__IO uint32 OSD_ENC_STA;
__IO uint32 OSD_ENC_SADR;
__IO uint32 OSD_ENC_TADR;
__IO uint32 OSD_ENC_RLEN;
__IO uint32 OSD_ENC_DLEN;
__IO uint32 OSD_ENC_IDENT0;
__IO uint32 OSD_ENC_IDENT1;
__IO uint32 OSD_ENC_TRANS0;
__IO uint32 OSD_ENC_TRANS1;
};
static int32 hgosd_ioctl(struct osdenc_device *p_osd, enum osdenc_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2)
{
int32 ret_val = RET_OK;
struct hgosd *osd_hw = (struct hgosd*)p_osd;
struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw;
uint32_t *p32;
switch(ioctl_cmd){
case OSD_IOCTL_TRAN_IDENT_TRANS:
p32 = (uint32_t *)param1;
hw->OSD_ENC_IDENT0 = p32[0];
hw->OSD_ENC_IDENT1 = p32[1];
hw->OSD_ENC_TRANS0 = p32[2];
hw->OSD_ENC_TRANS1 = p32[3];
break;
case OSD_IOCTL_ENC_ADR:
hw->OSD_ENC_SADR = param1;
hw->OSD_ENC_TADR = param2;
break;
case OSD_IOCTL_SET_ENC_RLEN:
hw->OSD_ENC_RLEN = ((param1/4 + 1)/2)*2 - 1; //word 偶对齐 -1
break;
case OSD_IOCTL_SET_ENC_FORMAT:
if(param1 == 1){
hw->OSD_ENC_CON &= ~BIT(1); //565
}else{
hw->OSD_ENC_CON |= BIT(1); //888
}
break;
case OSD_IOCTL_GET_ENC_DLEN:
return hw->OSD_ENC_DLEN*4;
break;
case OSD_IOCTL_SET_ENC_RUN:
hw->OSD_ENC_CON |= BIT(0);
break;
default:
os_printf("NO OSD IOCTL:%d\r\n",ioctl_cmd);
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
osdenc_irq_hdl encirq_vector_table[ENC_IRQ_NUM];
void * encirq_dev_table[ENC_IRQ_NUM];
void irq_osdenc_enable(struct osdenc_device *p_osd,uint8 mode,uint8 irq){
struct hgosd *osd_hw = (struct hgosd*)p_osd;
struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw;
if(mode){
hw->OSD_ENC_CON |= BIT(irq+2);
}else{
hw->OSD_ENC_CON &= ~BIT(irq+2);
}
}
void OSD_ENC_IRQHandler_action(void *p_osd){
uint32 sta = 0;
uint8 loop;
struct hgosd *osd_hw = (struct hgosd*)p_osd;
struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw;
sta = hw->OSD_ENC_STA;
for(loop = 0;loop < ENC_IRQ_NUM;loop++){
if(sta&BIT(loop)){
hw->OSD_ENC_STA = BIT(loop);
if(encirq_vector_table[loop] != NULL)
encirq_vector_table[loop] (loop,(uint32)encirq_dev_table[loop],0);
}
}
}
int32 osd_enc_irq_register(struct osdenc_device *p_osd,uint32 irq, osdenc_irq_hdl isr, uint32 dev_id){
struct hgosd *osd_hw = (struct hgosd*)p_osd;
struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw;
request_irq(osd_hw->irq_num, OSD_ENC_IRQHandler_action, p_osd);
irq_osdenc_enable(p_osd, 1, irq);
encirq_vector_table[irq] = isr;
encirq_dev_table[irq] = (void*)dev_id;
hw->OSD_ENC_STA |= BIT(irq);
os_printf("osdencirq_register:%d %x %x\r\n",irq,(uint32)encirq_vector_table[irq],(uint32)isr);
return 0;
}
int32 osd_enc_irq_unregister(struct osdenc_device *p_osd,uint32 irq){
struct hgosd *osd_hw = (struct hgosd*)p_osd;
struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw;
irq_osdenc_enable(p_osd, 0, irq);
encirq_vector_table[irq] = NULL;
encirq_dev_table[irq] = 0;
hw->OSD_ENC_STA |= BIT(irq);
return 0;
}
static int32 hgosdenc_open(struct osdenc_device *p_osd){
struct hgosd *osd_hw = (struct hgosd*)p_osd;
//struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw;
#ifdef FPGA_SUPPORT
SYSCTRL->SYS_CON0 |= BIT(12);
#else
sysctrl_osd_enc_clk_open();
SYSCTRL->SYS_CON7 |= BIT(15);
#endif
irq_enable(osd_hw->irq_num);
return 0;
}
static int32 hgosdenc_close(struct osdenc_device *p_osd){
struct hgosd *osd_hw = (struct hgosd*)p_osd;
//struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw;
sysctrl_osd_enc_clk_close();
irq_disable(osd_hw->irq_num);
return 0;
}
int32 hgosdenc_suspend(struct dev_obj *obj){
struct hgosd *osd_hw = (struct hgosd*)obj;
struct hgosdenc_hw *hw;
struct hgosdenc_hw *hw_cfg;
//确保已经被打开并且休眠过,直接返回
if(!osd_hw->opened || osd_hw->dsleep)
{
return RET_OK;
}
osd_hw->dsleep = 1;
osd_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgosdenc_hw));
hw_cfg = (struct hgosdenc_hw*)osd_hw->cfg_backup;
hw = (struct hgosdenc_hw*)osd_hw->hw;
hw_cfg->OSD_ENC_CON=hw->OSD_ENC_CON;
hw_cfg->OSD_ENC_STA=hw->OSD_ENC_STA;
hw_cfg->OSD_ENC_SADR=hw->OSD_ENC_SADR;
hw_cfg->OSD_ENC_TADR=hw->OSD_ENC_TADR;
hw_cfg->OSD_ENC_RLEN=hw->OSD_ENC_RLEN;
hw_cfg->OSD_ENC_DLEN=hw->OSD_ENC_DLEN;
hw_cfg->OSD_ENC_IDENT0=hw->OSD_ENC_IDENT0;
hw_cfg->OSD_ENC_IDENT1=hw->OSD_ENC_IDENT1;
hw_cfg->OSD_ENC_TRANS0=hw->OSD_ENC_TRANS0;
hw_cfg->OSD_ENC_TRANS1=hw->OSD_ENC_TRANS1;
irq_disable(osd_hw->irq_num);
return 0;
}
int32 hgosdenc_resume(struct dev_obj *obj){
struct hgosd *osd_hw = (struct hgosd*)obj;
struct hgosdenc_hw *hw;
struct hgosdenc_hw *hw_cfg;
//如果已经被打开并且没有休眠过,直接返回
if(!osd_hw->opened || !osd_hw->dsleep)
{
return RET_OK;
}
osd_hw->dsleep = 0;
hw_cfg = (struct hgosdenc_hw*)osd_hw->cfg_backup;
hw = (struct hgosdenc_hw*)osd_hw->hw;
hw->OSD_ENC_CON=hw_cfg->OSD_ENC_CON;
hw->OSD_ENC_STA=hw_cfg->OSD_ENC_STA;
hw->OSD_ENC_SADR=hw_cfg->OSD_ENC_SADR;
hw->OSD_ENC_TADR=hw_cfg->OSD_ENC_TADR;
hw->OSD_ENC_RLEN=hw_cfg->OSD_ENC_RLEN;
hw->OSD_ENC_DLEN=hw_cfg->OSD_ENC_DLEN;
hw->OSD_ENC_IDENT0=hw_cfg->OSD_ENC_IDENT0;
hw->OSD_ENC_IDENT1=hw_cfg->OSD_ENC_IDENT1;
hw->OSD_ENC_TRANS0=hw_cfg->OSD_ENC_TRANS0;
hw->OSD_ENC_TRANS1=hw_cfg->OSD_ENC_TRANS1;
irq_enable(osd_hw->irq_num);
os_free(osd_hw->cfg_backup);
return 0;
}
static const struct osdenc_hal_ops dev_ops = {
.open = hgosdenc_open,
.close = hgosdenc_close,
.ioctl = hgosd_ioctl,
.request_irq = osd_enc_irq_register,
.release_irq = osd_enc_irq_unregister,
#ifdef CONFIG_SLEEP
.ops.suspend = hgosdenc_suspend,
.ops.resume = hgosdenc_resume,
#endif
};
int32 hgosdenc_attach(uint32 dev_id, struct hgosd *hgosd){
hgosd->opened = 0;
hgosd->use_dma = 0;
hgosd->irq_hdl = NULL;
hgosd->irq_data = 0;
hgosd->dev.dev.ops = (const struct devobj_ops *)&dev_ops;
irq_disable(hgosd->irq_num);
dev_register(dev_id, (struct dev_obj *)hgosd);
return 0;
}

373
sdk/driver/pwm/hgpwm_v0.c Normal file
View File

@@ -0,0 +1,373 @@
/**
* @file hgpwm_v0.c
* @author bxd
* @brief pwm
* @version
* TXW80X; TXW81X
* @date 2023-08-02
*
* @copyright Copyright (c) 2023
*
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "osal/irq.h"
#include "osal/string.h"
#include "hal/timer_device.h"
#include "hal/pwm.h"
#include "dev/pwm/hgpwm_v0.h"
/**********************************************************************************/
/* LOW LAYER FUNCTION */
/**********************************************************************************/
static int32 hgpwm_v0_switch_hal_pwm_channel(enum pwm_channel param) {
switch (param) {
case (PWM_CHANNEL_0):
return 0;
break;
case (PWM_CHANNEL_1):
return 1;
break;
case (PWM_CHANNEL_2):
return 2;
break;
case (PWM_CHANNEL_3):
return 3;
break;
case (PWM_CHANNEL_4):
return 4;
break;
case (PWM_CHANNEL_5):
return 5;
break;
// case (PWM_CHANNEL_6):
// return 6;
// break;
// case (PWM_CHANNEL_7):
// return 7;
// break;
// case (PWM_CHANNEL_8):
// return 8;
// break;
// case (PWM_CHANNEL_9):
// return 9;
// break;
// case (PWM_CHANNEL_10):
// return 10;
// break;
default:
return -1;
break;
}
}
static int32 hgpwm_v0_config(struct hgpwm_v0 *dev, enum pwm_channel channel, struct hgpwm_v0_config *config) {
struct hgpwm_v0_config *p_config = config;
uint32 channel_to_reg = 0;
int32 ret_val = RET_OK;
/* Make sure the config struct pointer */
if (!p_config) {
return -EINVAL;
}
/* Make sure the channel */
channel_to_reg = hgpwm_v0_switch_hal_pwm_channel(channel);
if ((-1) == channel_to_reg) {
return -EINVAL;
}
/* Make sure the timer is attached */
if ((dev->channel[channel_to_reg])) {
ret_val = timer_device_ioctl((struct timer_device *)dev->channel[channel_to_reg], HGPWM_V0_FUNC_CMD_MASK, (uint32)p_config, 0);
} else {
ret_val = RET_ERR;
}
return ret_val;
}
/**********************************************************************************/
/* ATTCH FUNCTION */
/**********************************************************************************/
static int32 hgpwm_v0_init(struct pwm_device *pwm, enum pwm_channel channel, uint32 period_sysclkpd_cnt, uint32 h_duty_sysclkpd_cnt) {
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
int32 channel_num = 0;
int32 ret_val = RET_OK;
/* Make sure the channel */
channel_num = hgpwm_v0_switch_hal_pwm_channel(channel);
if ((-1) == channel_num) {
return -EINVAL;
}
/* Make busy status */
if (dev->opened[channel_num]) {
return -EBUSY;
}
/* config pwm */
config.period = period_sysclkpd_cnt;
config.duty = h_duty_sysclkpd_cnt;
config.func_cmd = HGPWM_V0_FUNC_CMD_INIT;
ret_val = hgpwm_v0_config(dev, channel, &config);
dev->opened[channel_num] = 1;
return ret_val;
}
static int32 hgpwm_v0_deinit(struct pwm_device *pwm, enum pwm_channel channel) {
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
int32 channel_num = 0;
int32 ret_val = RET_OK;
/* Make sure the channel */
channel_num = hgpwm_v0_switch_hal_pwm_channel(channel);
if ((-1) == channel_num) {
return -EINVAL;
}
/* Make busy status */
if (!(dev->opened[channel_num])) {
return RET_OK;
}
config.func_cmd = HGPWM_V0_FUNC_CMD_DEINIT;
ret_val = hgpwm_v0_config(dev, channel, &config);
dev->opened[channel_num] = 0;
return ret_val;
}
static int32 hgpwm_v0_start(struct pwm_device *pwm, enum pwm_channel channel) {
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
int32 channel_num = 0;
int32 ret_val = RET_OK;
/* Make sure the channel */
channel_num = hgpwm_v0_switch_hal_pwm_channel(channel);
if ((-1) == channel_num) {
return -EINVAL;
}
/* Make busy status */
if (!(dev->opened[channel_num])) {
return RET_ERR;
}
config.func_cmd = HGPWM_V0_FUNC_CMD_START;
ret_val = hgpwm_v0_config(dev, channel, &config);
return ret_val;
}
static int32 hgpwm_v0_stop(struct pwm_device *pwm, enum pwm_channel channel) {
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
int32 channel_num = 0;
int32 ret_val = RET_OK;
/* Make sure the channel */
channel_num = hgpwm_v0_switch_hal_pwm_channel(channel);
if ((-1) == channel_num) {
return -EINVAL;
}
/* Make busy status */
if (!(dev->opened[channel_num])) {
return RET_OK;
}
config.func_cmd = HGPWM_V0_FUNC_CMD_STOP;
ret_val = hgpwm_v0_config(dev, channel, &config);
return ret_val;
}
#ifdef CONFIG_SLEEP
static int32 hgpwm_v0_suspend(struct pwm_device *pwm, enum pwm_channel channel)
{
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
int32 channel_num = 0;
int32 ret_val = RET_OK;
/* Make sure the channel */
channel_num = hgpwm_v0_switch_hal_pwm_channel(channel);
if ((-1) == channel_num) {
return -EINVAL;
}
/* Make busy status */
if (!(dev->opened[channel_num])) {
return RET_OK;
}
config.func_cmd = HGPWM_V0_FUNC_CMD_SUSPEND;
ret_val = hgpwm_v0_config(dev, channel, &config);
return ret_val;
}
static int32 hgpwm_v0_resume(struct pwm_device *pwm, enum pwm_channel channel)
{
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
int32 channel_num = 0;
int32 ret_val = RET_OK;
/* Make sure the channel */
channel_num = hgpwm_v0_switch_hal_pwm_channel(channel);
if ((-1) == channel_num) {
return -EINVAL;
}
/* Make busy status */
if (!(dev->opened[channel_num])) {
return RET_OK;
}
config.func_cmd = HGPWM_V0_FUNC_CMD_RESUME;
ret_val = hgpwm_v0_config(dev, channel, &config);
return ret_val;
}
#endif
static int32 hgpwm_v0_ioctl(struct pwm_device *pwm, enum pwm_channel channel, enum pwm_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2) {
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
int32 ret_val = RET_OK;
switch (ioctl_cmd) {
case (PWM_IOCTL_CMD_SET_PERIOD_DUTY):
config.func_cmd = HGPWM_V0_FUNC_CMD_IOCTL_SET_PERIOD_DUTY;
config.period = param1;
config.duty = param2;
ret_val = hgpwm_v0_config(dev, channel, &config);
break;
case (PWM_IOCTL_CMD_SET_SINGLE_INCREAM):
config.func_cmd = HGPWM_V0_FUNC_CMD_IOCTL_SET_SINGLE_INCREAM;
config.period = param1;
config.duty = param2;
ret_val = hgpwm_v0_config(dev, channel, &config);
break;
case (PWM_IOCTL_CMD_SET_INCREAM_DECREASE):
config.func_cmd = HGPWM_V0_FUNC_CMD_IOCTL_SET_INCREAM_DECREASE;
config.period = param1;
config.duty = param2;
ret_val = hgpwm_v0_config(dev, channel, &config);
break;
case (PWM_IOCTL_CMD_SET_PRESCALER):
/*!
* @brief: set prescaler
* @param1: prescaler
* @param2: NULL
*/
config.func_cmd = HGPWM_V0_FUNC_CMD_IOCTL_SET_PRESCALER;
config.param1 = param1;
ret_val = hgpwm_v0_config(dev, channel, &config);
break;
case (PWM_IOCTL_CMD_SET_PERIOD_DUTY_IMMEDIATELY):
/*!
* @brief: set period and duty immediately
* @param1: period
* @param2: duty
*/
config.func_cmd = HGPWM_V0_FUNC_CMD_IOCTL_SET_PERIOD_DUTY_IMMEDIATELY;
config.period = param1;
config.duty = param2;
ret_val = hgpwm_v0_config(dev, channel, &config);
break;
default:
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
static int32 hgpwm_v0_request_irq(struct pwm_device *pwm, enum pwm_channel channel, enum pwm_irq_flag irq_flag, pwm_irq_hdl irq_hdl, uint32 data) {
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
switch (irq_flag) {
case (PWM_IRQ_FLAG_COMPARE):
config.func_cmd = HGPWM_V0_FUNC_CMD_REQUEST_IRQ_COMPARE;
config.irq_hdl = irq_hdl;
config.irq_data = data;
hgpwm_v0_config(dev, channel, &config);
break;
case (PWM_IRQ_FLAG_PERIOD):
config.func_cmd = HGPWM_V0_FUNC_CMD_REQUEST_IRQ_PERIOD;
config.irq_hdl = irq_hdl;
config.irq_data = data;
hgpwm_v0_config(dev, channel, &config);
break;
}
return RET_OK;
}
static int32 hgpwm_v0_release_irq(struct pwm_device *pwm, enum pwm_channel channel) {
struct hgpwm_v0 *dev = (struct hgpwm_v0 *)pwm;
struct hgpwm_v0_config config = {0};
config.func_cmd = HGPWM_V0_FUNC_CMD_RELEASE_IRQ;
config.irq_data = 0;
config.irq_hdl = NULL;
hgpwm_v0_config(dev, channel, &config);
return RET_OK;
}
static const struct pwm_hal_ops pwm_v0_ops = {
.init = hgpwm_v0_init,
.deinit = hgpwm_v0_deinit,
.start = hgpwm_v0_start,
.stop = hgpwm_v0_stop,
.ioctl = hgpwm_v0_ioctl,
.request_irq = hgpwm_v0_request_irq,
.release_irq = hgpwm_v0_release_irq,
#ifdef CONFIG_SLEEP
.ops.suspend = NULL,//hgpwm_v0_suspend,
.ops.resume = NULL,//hgpwm_v0_resume,
#endif
};
int32 hgpwm_v0_attach(uint32 dev_id, struct hgpwm_v0 *pwm) {
uint32 i = 0;
for (i=0; i<HGPWM_MAX_PWM_CHANNEL; i++) {
pwm->opened[i] = 0;
}
pwm->dev.dev.ops = (const struct devobj_ops *)&pwm_v0_ops;
dev_register(dev_id, (struct dev_obj *)pwm);
return RET_OK;
}

File diff suppressed because it is too large Load Diff

449
sdk/driver/sha/hgsha_v1.c Normal file
View File

@@ -0,0 +1,449 @@
/**
******************************************************************************
* @file hgsha.c
* @author HUGE-IC Application Team
* @version V1.0.0
* @date
* @brief sha256
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2019 HUGE-IC</center></h2>
*
*
*
******************************************************************************
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "devid.h"
#include "osal/string.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/irq.h"
#include "osal/string.h"
#include "osal/sleep.h"
#include "dev/sha/hgsha_v1.h"
#include "hgsha_v1_hw.h"
#include "hal/sha.h"
#if 1
#define SHA_PRINTF(fmt, arg...) printf(fmt, ##arg)
#else
#define SHA_PRINTF(fmt, arg...)
#endif
typedef enum {
SHA1_INIT = BIT(3) | BIT(1),
SHA1_UPDATE = BIT(3),
SHA1_FINISH = BIT(3) | BIT(2),
SHA2_INIT = BIT(1),
SHA2_UPDATE = 0,
SHA2_FINISH = BIT(2),
SHA_INTR_EN = BIT(0),
} SHA_HWMODE;
#define SHA_NONBLOCK (0x1000)
/********************************
*
* LOW LAYER FUNCTION AREA
*
* *****************************/
static inline void ll_sha_get_result_big_endian(struct hgsha_v1_hw *hw, uint8 *buf)
{
volatile uint32_t *tmp = (uint32_t *) & (hw->SHA_RESULT0);
uint32_t tmp_dat = 0;
for (uint32_t i = 0; i < 8; i++, tmp++) {
tmp_dat = *tmp;
*buf++ = (tmp_dat ) & 0xFF;
*buf++ = (tmp_dat >> 8) & 0xFF;
*buf++ = (tmp_dat >> 16) & 0xFF;
*buf++ = (tmp_dat >> 24) & 0xFF;
}
}
static inline void ll_sha_get_result_little_endian(struct hgsha_v1_hw *hw, uint8 *buf)
{
volatile uint32_t *tmp = (uint32_t *) & (hw->SHA_RESULT0);
uint32_t tmp_dat = 0;
for (uint32_t i = 0; i < 8; i++, tmp++) {
tmp_dat = *tmp;
*buf++ = (tmp_dat >> 24) & 0xFF;
*buf++ = (tmp_dat >> 16) & 0xFF;
*buf++ = (tmp_dat >> 8) & 0xFF;
*buf++ = (tmp_dat ) & 0xFF;
}
}
static void ll_sha_calc(struct hgsha_v1_hw *sha, uint8_t *buf, uint16_t len, SHA_HWMODE mode)
{
sha->SHA_STADDR = (uint32)buf;
sha->SHA_BYTELEN = len;
sha->SHA_PENDING = 1;
sha->SHA_CONFIG = mode;
sha->SHA_START = 1;
// while(!sha->SHA_PENDING);
}
/********************************
*
* DRIVE LAYER FUNCTION AREA
*
* *****************************/
static void hgsha_irq_handle(void *args)
{
struct hgsha_v1 *sha = (struct hgsha_v1 *)args;
struct hgsha_v1_hw *sha_reg = (struct hgsha_v1_hw *)sha->hw;
sha_reg->SHA_PENDING = 1;
os_sema_up(&sha->done);
if (sha->irq_func) {
sha->irq_func(sha->irq_data);
}
}
static int32_t hgsha_v1_request_irq(struct sha_dev *dev, void * irq_handle, void *args)
{
struct hgsha_v1 *sha = (struct hgsha_v1 *)dev;
sha->irq_func = args;
sha->irq_data = irq_handle;
return RET_OK;
}
static int hgsha_v1_release_irq(struct sha_dev *dev)
{
struct hgsha_v1 *sha = (struct hgsha_v1 *)dev;
sha->irq_func = NULL;
return RET_OK;
}
static int hgsha_v1_transform(struct sha_dev *dev, struct sha_req *req)
{
struct hgsha_v1 *sha = (struct hgsha_v1 *)dev;
struct hgsha_v1_hw *hw = (struct hgsha_v1_hw *)sha->hw;
int ret = 0;
uint8_t *buf = req->input;
uint32_t blocks = req->len / 64;
uint32_t stas = 0;
SHA_HWMODE mode = 0;
if (os_mutex_lock(&sha->lock, 4000)) {
printf("sha get mutex failure\r\n");
return RET_ERR;
}
switch (req->type) {
case T_SHA1:
stas = 5 * 4;
mode = SHA1_UPDATE;
break;
case T_SHA256:
stas = 8 * 4;
mode = SHA2_UPDATE;
break;
default:
return -1;
}
mode |= SHA_INTR_EN;
memcpy((void*)&hw->SHA_RESULT0, req->state, stas);
sys_dcache_clean_range_unaligned((void*)req->input, req->len);
os_sema_eat(&sha->done);
for (int bs = 512;bs>8;bs/=2) {
for (;blocks>=bs;) {
ll_sha_calc(hw, buf, bs * 64, mode);
buf += bs * 64;
blocks -= bs;
ret |= !os_sema_down(&sha->done, 8000);
}
}
if (blocks) {
uint64_t tick = os_jiffies();
mode &= ~SHA_INTR_EN;
ll_sha_calc(hw, buf, blocks * 64, mode);
while(!hw->SHA_PENDING)
{
if (os_jiffies()-tick >= 8000) {
ret = 1;
break;
}
}
}
memcpy(req->state, (void*)&hw->SHA_RESULT0, stas);
os_mutex_unlock(&sha->lock);
return ret;
}
int __sha_init(struct sha_dev *dev, struct sha_ctx * ctx)
{
if (ctx->type == T_SHA1) {
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
} else {
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
ctx->dlen = 0;
ctx->bit_len = 0;
return 0;
}
int __sha_update(struct sha_dev *sha, struct sha_ctx *ctx, uint8_t *buf, uint32_t len)
{
struct sha_req req = {
.state = ctx->state,
.type = ctx->type,
};
if (ctx->dlen) {
if (ctx->dlen + len >= 64) {
memcpy(&ctx->buf[ctx->dlen], buf, 64 - ctx->dlen);
buf += 64 - ctx->dlen;
len -= 64 - ctx->dlen;
req.input = ctx->buf;
req.len = 64;
hgsha_v1_transform(sha, &req);
ctx->bit_len += req.len * 8;
ctx->dlen = 0;
} else {
memcpy(&ctx->buf[ctx->dlen], buf, len);
ctx->dlen += len;
len = 0;
}
}
for (int i = 512; i != 0; i /= 2) {
while (len / 64 >= i) {
req.input = buf;
req.len = i * 64;
hgsha_v1_transform(sha, &req);
ctx->bit_len += req.len * 8;
buf += i * 64;
len -= i * 64;
}
}
if (len) {
memcpy(ctx->buf, buf, len);
ctx->dlen = len;
}
return 0;
}
int __sha_final(struct sha_dev *sha, struct sha_ctx *ctx, uint8_t *hash)
{
struct sha_req req = {
.state = ctx->state,
.type = ctx->type,
.input = ctx->buf,
.len = 64,
};
// Pad whatever data is left in the buffer.
int i = ctx->dlen;
if (ctx->dlen < 56) {
ctx->buf[i++] = 0x80;
while (i < 56)
ctx->buf[i++] = 0x00;
} else {
ctx->buf[i++] = 0x80;
while (i < 64)
ctx->buf[i++] = 0x00;
hgsha_v1_transform(sha, &req);
memset(ctx->buf, 0, 56);
}
// Append to the padding the total message's length in bits and transform.
ctx->bit_len += ctx->dlen * 8;
ctx->buf[63] = ctx->bit_len;
ctx->buf[62] = ctx->bit_len >> 8;
ctx->buf[61] = ctx->bit_len >> 16;
ctx->buf[60] = ctx->bit_len >> 24;
ctx->buf[59] = ctx->bit_len >> 32;
ctx->buf[58] = ctx->bit_len >> 40;
ctx->buf[57] = ctx->bit_len >> 48;
ctx->buf[56] = ctx->bit_len >> 56;
hgsha_v1_transform(sha, &req);
// Since this implementation uses little endian uint8_t ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash.
for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
if (ctx->type == T_SHA256) {
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}
return 0;
}
static int hgsha_v1_init(struct sha_dev *dev, SHA_TYPE type)
{
struct hgsha_v1 *sha = (struct hgsha_v1 *)dev;
sha->ctx.type = type;
sha->ctx.bit_len = 0;
sha->ctx.dlen = 0;
__sha_init(dev, sha->pctx);
return 0;
}
static int32 hgsha_v1_update(struct sha_dev *dev, uint8 *input, uint32 len)
{
struct hgsha_v1 *sha = (struct hgsha_v1 *)dev;
return __sha_update(dev, sha->pctx, input, len);
}
static int32 hgsha_v1_final(struct sha_dev *dev, uint8 *output)
{
struct hgsha_v1 *sha = (struct hgsha_v1 *)dev;
return __sha_final(dev, sha->pctx, output);
}
static int32 hgsha_v1_ioctl(struct sha_dev *dev, uint32 cmd, uint32 param1, uint32 param2)
{
struct hgsha_v1 *sha = (struct hgsha_v1 *)dev;
switch (cmd) {
case SHA_IOCTL_CMD_START:
os_mutex_lock(&sha->lock, osWaitForever);
break;
case SHA_IOCTL_CMD_END:
os_mutex_unlock(&sha->lock);
break;
case SHA_IOCTL_CMD_RESET:
break;
case SHA_IOCTL_GET_CTX:
*((struct sha_ctx*)param1) = sha->ctx;
break;
case SHA_IOCTL_PUT_CTX:
sha->ctx = *((struct sha_ctx*)param1);
break;
case SHA_IOCTL_RELOAD_CTX:
sha->pctx = (struct sha_ctx*)param1;
break;
default:
return RET_ERR;
}
return RET_OK;
}
void hg_sha_test_printf(struct sha_dev *dev)
{
uint8_t src[64];
uint32_t rsum = 0;
uint32_t state[8] = {
0x12345678, 0x66225544, 0x11447788, 0x22441597,
0x22441597, 0x11447788, 0x66225544, 0x12345678
};
for (int i = 0;i<64;i++)
src[i] = i;
struct sha_req req = {
.type = T_SHA256,
.input = src,
.state = state,
.len = 64,
};
hgsha_v1_transform(dev, &req);
for (int i = 0;i<8;i++)
rsum += state[i];
_os_printf("sha test: %x\r\n", rsum);
if (rsum != 0x4a635c1c) {
_os_printf("sha lp err\r\n");
}
}
#ifdef CONFIG_SLEEP
// #define HGSHA_SLEEP_TEST(dev) hg_sha_test_printf(dev)
#define HGSHA_SLEEP_TEST(dev)
static int32 hgsha_v1_suspend(struct sha_dev *dev)
{
struct hgsha_v1 *sha =(struct hgsha_v1 *)dev;
struct hgsha_v1_hw *sha_reg = sha->hw;
HGSHA_SLEEP_TEST(dev);
if(os_mutex_lock(&sha->lock, 80000)) {
return RET_ERR;
}
irq_disable(sha->irq_num);
sysctrl_sha_clk_close();
return 0;
}
static int32 hgsha_v1_resume(struct sha_dev *dev)
{
struct hgsha_v1 *sha =(struct hgsha_v1 *)dev;
struct hgsha_v1_hw *hw = (struct hgsha_v1_hw *)sha->hw;
os_mutex_unlock(&sha->lock);
sysctrl_sha_clk_open();
sysctrl_sha_reset();
hw->SHA_PENDING |= 1;
irq_enable(sha->irq_num);
HGSHA_SLEEP_TEST(dev);
return 0;
}
#endif
static const struct sha_hal_ops sha_v1_ops = {
.init = hgsha_v1_init,
.update = hgsha_v1_update,
.final = hgsha_v1_final,
.xform = hgsha_v1_transform,
.ioctl = hgsha_v1_ioctl,
.requset_irq = hgsha_v1_request_irq,
.release_irq = hgsha_v1_release_irq,
#ifdef CONFIG_SLEEP
.ops.suspend = (int32 (*)(struct dev_obj *obj))hgsha_v1_suspend,
.ops.resume = (int32 (*)(struct dev_obj *obj))hgsha_v1_resume,
#endif
};
__init int32_t hgsha_v1_attach(uint32_t dev_id, struct hgsha_v1 *sha)
{
sha->dev.dev.ops = (const struct devobj_ops *)&sha_v1_ops;
struct hgsha_v1_hw *hw = (struct hgsha_v1_hw *)sha->hw;
//clear pending
hw->SHA_PENDING |= 1;
sha->irq_func = NULL;
sha->flags = 0;
sha->pctx = &sha->ctx;
os_mutex_init(&sha->lock);
os_sema_init(&sha->done, 0);
request_irq(sha->irq_num, hgsha_irq_handle, sha);
irq_enable(sha->irq_num);
dev_register(dev_id, (struct dev_obj *)sha);
return RET_OK;
}

View File

@@ -0,0 +1,23 @@
#ifndef _HGSHA_V0_HW_H_
#define _HGSHA_V0_HW_H_
#include "typesdef.h"
struct hgsha_v1_hw {
__IO uint32 SHA_START;
__IO uint32 SHA_BYTELEN;
__IO uint32 SHA_CONFIG;
__IO uint32 SHA_PENDING;
__IO uint32 SHA_STADDR;
uint32 reserved[3];
__IO uint32 SHA_RESULT0;
__IO uint32 SHA_RESULT1;
__IO uint32 SHA_RESULT2;
__IO uint32 SHA_RESULT3;
__IO uint32 SHA_RESULT4;
__IO uint32 SHA_RESULT5;
__IO uint32 SHA_RESULT6;
__IO uint32 SHA_RESULT7;
};
#endif

711
sdk/driver/spi/hgcqspi_hw.h Normal file
View File

@@ -0,0 +1,711 @@
#ifndef _HGCQSPI_HW_H_
#define _HGCQSPI_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @brief SPI register structure
* @{
*/
struct hgcqspi_hw {
__IO uint32 CONFIG; //0x00
__IO uint32 DEV_RDINSTR_CONFIG; //0x04
__IO uint32 DEV_WRINSTR_CONFIG; //0x08
__IO uint32 DEV_DELAY; //0x0c
__IO uint32 READ_DATA_CAPTURE; //0x10
__IO uint32 DEV_SIZE_CONFIG; //0x14
__IO uint32 SRAM_PARTITION; //0x18
__IO uint32 IND_AHB_TRIGGER; //0x1c
__IO uint32 PERIPH_CFG; //0x20
__IO uint32 REMAP_ADD; //0x24
__IO uint32 MODE_BIT; //0x28
__IO uint32 SRAM_FILL_LEVEL; //0x2c
__IO uint32 TX_THRESH; //0x30
__IO uint32 RX_THRESH; //0x34
__IO uint32 WRITE_COMP_CTRL; //0x38
__IO uint32 MAX_NO_OF_POLLS; //0x3c
__IO uint32 INT_STATUS; //0x40
__IO uint32 INT_MASK; //0x44
uint32 RESERVED0[2];
__IO uint32 WRITE_PROT_L; //0x50
__IO uint32 WRITE_PROT_U; //0x54
__IO uint32 WRITE_PROT_CTRL; //0x58
uint32 RESERVED1[1];
__IO uint32 IND_RD_XFER_CTRL; //0x60
__IO uint32 IND_RD_XFER_WMARK; //0x64
__IO uint32 IND_RD_XFER_START_ADD; //0x68
__IO uint32 IND_RD_XFER_NUM_BYTES; //0x6c
__IO uint32 IND_WR_XFER_CTRL; //0x70
__IO uint32 IND_WR_XFER_WMARK; //0x74
__IO uint32 IND_WR_XFER_START_ADD; //0x78
__IO uint32 IND_WR_XFER_NUM_BYTES; //0x7c
__IO uint32 IND_AHB_TRIGGER_RANGE; //0x80
uint32 RESERVED2[2];
__IO uint32 FLASH_CMD_CTRL_MEM; //0x8C
__IO uint32 FLASH_CMD_CTRL; //0x90
__IO uint32 FLASH_CMD_ADD; //0x94
uint32 RESERVED3[2];
__IO uint32 FLASH_CMD_RDATA_L; //0xa0
__IO uint32 FLASH_CMD_RDATA_U; //0xa4
__IO uint32 FLASH_CMD_WDATA_L; //0xa8
__IO uint32 FLASH_CMD_WDATA_U; //0xac
__IO uint32 FLASH_STATUS; //0xb0
__IO uint32 PHY_CONFIG; //0xb4
__IO uint32 PHY_DLL_MASTER_CONFIG; //0xb8
__IO uint32 DLL_OBSERVABLE_L; //0xbc
__IO uint32 DLL_OBSERVABLE_U; //0xc0
uint32 RESERVED4[5];
__IO uint32 NEW_ADD_CONFIG0; //d8
__IO uint32 NEW_ADD_CONFIG1; //dc
__IO uint32 OPCODE_EXT_L; //E0
__IO uint32 OPCODE_EXT_U; //E4
__IO uint32 READ_DATA_CAPTURE_EXT; //0xE8
__IO uint32 WRITE_PROT_CTRL_EXT; //0xEC
__IO uint32 DEV_RDINSTR_CONFIG_CS1; //0xF0
__IO uint32 DEV_WRINSTR_CONFIG_CS1; //0xF4
__IO uint32 MONITOR; //0xF8, for OSPI
__IO uint32 MODULE_ID; //0xfc
};
/** @addtogroup SPI MODULE REGISTER
* @{
*/
#define CQSPI_NAME "cadence-qspi"
#define CQSPI_MAX_CHIPSELECT 1//16
#define CQSPI_AHB_TRIG_ADDR (0x18000000)
/* Operation timeout value */
#define CQSPI_TIMEOUT_MS 500
#define CQSPI_READ_TIMEOUT_MS 10
/* Instruction type */
#define CQSPI_INST_TYPE_SINGLE 0
#define CQSPI_INST_TYPE_DUAL 1
#define CQSPI_INST_TYPE_QUAD 2
#define CQSPI_DUMMY_CLKS_PER_BYTE 8
#define CQSPI_DUMMY_BYTES_MAX 4
#define CQSPI_DUMMY_CLKS_MAX 31
#define CQSPI_STIG_DATA_LEN_MAX 8
/* Register map */
#define CQSPI_REG_CONFIG 0x00
#define CQSPI_REG_CONFIG_ENABLE_MASK BIT(0)
#define CQSPI_REG_CONFIG_DECODE_MASK BIT(9)
#define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10
#define CQSPI_REG_CONFIG_DMA_MASK BIT(15)
#define CQSPI_REG_CONFIG_BAUD_LSB 19
#define CQSPI_REG_CONFIG_IDLE_LSB 31
#define CQSPI_REG_CONFIG_CHIPSELECT_MASK 0xF
#define CQSPI_REG_CONFIG_BAUD_MASK 0xF
#define CQSPI_REG_RD_INSTR 0x04
#define CQSPI_REG_RD_INSTR_OPCODE_LSB 0
#define CQSPI_REG_RD_INSTR_TYPE_INSTR_LSB 8
#define CQSPI_REG_RD_INSTR_TYPE_ADDR_LSB 12
#define CQSPI_REG_RD_INSTR_TYPE_DATA_LSB 16
#define CQSPI_REG_RD_INSTR_MODE_EN_LSB 20
#define CQSPI_REG_RD_INSTR_DUMMY_LSB 24
#define CQSPI_REG_RD_INSTR_TYPE_INSTR_MASK 0x3
#define CQSPI_REG_RD_INSTR_TYPE_ADDR_MASK 0x3
#define CQSPI_REG_RD_INSTR_TYPE_DATA_MASK 0x3
#define CQSPI_REG_RD_INSTR_DUMMY_MASK 0x1F
#define CQSPI_REG_WR_INSTR 0x08
#define CQSPI_REG_WR_INSTR_OPCODE_LSB 0
#define CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB 12
#define CQSPI_REG_WR_INSTR_TYPE_DATA_LSB 16
#define CQSPI_REG_DELAY 0x0C
#define CQSPI_REG_DELAY_TSLCH_LSB 0
#define CQSPI_REG_DELAY_TCHSH_LSB 8
#define CQSPI_REG_DELAY_TSD2D_LSB 16
#define CQSPI_REG_DELAY_TSHSL_LSB 24
#define CQSPI_REG_DELAY_TSLCH_MASK 0xFF
#define CQSPI_REG_DELAY_TCHSH_MASK 0xFF
#define CQSPI_REG_DELAY_TSD2D_MASK 0xFF
#define CQSPI_REG_DELAY_TSHSL_MASK 0xFF
#define CQSPI_REG_READCAPTURE 0x10
#define CQSPI_REG_READCAPTURE_BYPASS_LSB 0
#define CQSPI_REG_READCAPTURE_DELAY_LSB 1
#define CQSPI_REG_READCAPTURE_DELAY_MASK 0xF
#define CQSPI_REG_SIZE 0x14
#define CQSPI_REG_SIZE_ADDRESS_LSB 0
#define CQSPI_REG_SIZE_PAGE_LSB 4
#define CQSPI_REG_SIZE_BLOCK_LSB 16
#define CQSPI_REG_SIZE_ADDRESS_MASK 0xF
#define CQSPI_REG_SIZE_PAGE_MASK 0xFFF
#define CQSPI_REG_SIZE_BLOCK_MASK 0x3F
#define CQSPI_REG_SRAMPARTITION 0x18
#define CQSPI_REG_INDIRECTTRIGGER 0x1C
#define CQSPI_REG_DMA 0x20
#define CQSPI_REG_DMA_SINGLE_LSB 0
#define CQSPI_REG_DMA_BURST_LSB 8
#define CQSPI_REG_DMA_SINGLE_MASK 0xFF
#define CQSPI_REG_DMA_BURST_MASK 0xFF
#define CQSPI_REG_REMAP 0x24
#define CQSPI_REG_MODE_BIT 0x28
#define CQSPI_REG_SDRAMLEVEL 0x2C
#define CQSPI_REG_SDRAMLEVEL_RD_LSB 0
#define CQSPI_REG_SDRAMLEVEL_WR_LSB 16
#define CQSPI_REG_SDRAMLEVEL_RD_MASK 0xFFFF
#define CQSPI_REG_SDRAMLEVEL_WR_MASK 0xFFFF
#define CQSPI_REG_IRQSTATUS 0x40
#define CQSPI_REG_IRQMASK 0x44
#define CQSPI_REG_INDIRECTRD 0x60
#define CQSPI_REG_INDIRECTRD_START_MASK BIT(0)
#define CQSPI_REG_INDIRECTRD_CANCEL_MASK BIT(1)
#define CQSPI_REG_INDIRECTRD_DONE_MASK BIT(5)
#define CQSPI_REG_INDIRECTRDWATERMARK 0x64
#define CQSPI_REG_INDIRECTRDSTARTADDR 0x68
#define CQSPI_REG_INDIRECTRDBYTES 0x6C
#define CQSPI_REG_CMDCTRL 0x90
#define CQSPI_REG_CMDCTRL_EXECUTE_MASK BIT(0)
#define CQSPI_REG_CMDCTRL_INPROGRESS_MASK BIT(1)
#define CQSPI_REG_CMDCTRL_WR_BYTES_LSB 12
#define CQSPI_REG_CMDCTRL_WR_EN_LSB 15
#define CQSPI_REG_CMDCTRL_ADD_BYTES_LSB 16
#define CQSPI_REG_CMDCTRL_ADDR_EN_LSB 19
#define CQSPI_REG_CMDCTRL_RD_BYTES_LSB 20
#define CQSPI_REG_CMDCTRL_RD_EN_LSB 23
#define CQSPI_REG_CMDCTRL_OPCODE_LSB 24
#define CQSPI_REG_CMDCTRL_WR_BYTES_MASK 0x7
#define CQSPI_REG_CMDCTRL_ADD_BYTES_MASK 0x3
#define CQSPI_REG_CMDCTRL_RD_BYTES_MASK 0x7
#define CQSPI_REG_INDIRECTWR 0x70
#define CQSPI_REG_INDIRECTWR_START_MASK BIT(0)
#define CQSPI_REG_INDIRECTWR_CANCEL_MASK BIT(1)
#define CQSPI_REG_INDIRECTWR_DONE_MASK BIT(5)
#define CQSPI_REG_INDIRECTWRWATERMARK 0x74
#define CQSPI_REG_INDIRECTWRSTARTADDR 0x78
#define CQSPI_REG_INDIRECTWRBYTES 0x7C
#define CQSPI_REG_CMDADDRESS 0x94
#define CQSPI_REG_CMDREADDATALOWER 0xA0
#define CQSPI_REG_CMDREADDATAUPPER 0xA4
#define CQSPI_REG_CMDWRITEDATALOWER 0xA8
#define CQSPI_REG_CMDWRITEDATAUPPER 0xAC
/* Interrupt status bits */
#define CQSPI_REG_IRQ_MODE_ERR BIT(0)
#define CQSPI_REG_IRQ_UNDERFLOW BIT(1)
#define CQSPI_REG_IRQ_IND_COMP BIT(2)
#define CQSPI_REG_IRQ_IND_RD_REJECT BIT(3)
#define CQSPI_REG_IRQ_WR_PROTECTED_ERR BIT(4)
#define CQSPI_REG_IRQ_ILLEGAL_AHB_ERR BIT(5)
#define CQSPI_REG_IRQ_WATERMARK BIT(6)
#define CQSPI_REG_IRQ_IND_SRAM_FULL BIT(12)
#define CQSPI_IRQ_MASK_RD (CQSPI_REG_IRQ_WATERMARK | \
CQSPI_REG_IRQ_IND_SRAM_FULL | \
CQSPI_REG_IRQ_IND_COMP)
#define CQSPI_IRQ_MASK_WR (CQSPI_REG_IRQ_IND_COMP | \
CQSPI_REG_IRQ_WATERMARK | \
CQSPI_REG_IRQ_UNDERFLOW)
#define CQSPI_IRQ_STATUS_MASK 0x1FFFF
/*
* Note on opcode nomenclature: some opcodes have a format like
* SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
* of I/O lines used for the opcode, address, and data (respectively). The
* FUNCTION has an optional suffix of '4', to represent an opcode which
* requires a 4-byte (32-bit) address.
*/
/* Flash opcodes. */
#define SPINOR_OP_WREN 0x06 /* Write enable */
#define SPINOR_OP_RDSR 0x05 /* Read status register */
#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
#define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */
#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */
#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */
#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */
#define SPINOR_OP_RDCR 0x35 /* Read configuration register */
#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
/* Used for SST flashes only. */
#define SPINOR_OP_BP 0x02 /* Byte program */
#define SPINOR_OP_WRDI 0x04 /* Write disable */
#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
/* Used for Macronix and Winbond flashes. */
#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
/* Used for Spansion flashes only. */
#define SPINOR_OP_BRWR 0x17 /* Bank register write */
/* Used for Micron flashes only. */
#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */
#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */
/* Status Register bits. */
#define SR_WIP BIT(0) /* Write in progress */
#define SR_WEL BIT(1) /* Write enable latch */
/* meaning of other SR_* bits may differ between vendors */
#define SR_BP0 BIT(2) /* Block protect 0 */
#define SR_BP1 BIT(3) /* Block protect 1 */
#define SR_BP2 BIT(4) /* Block protect 2 */
#define SR_TB BIT(5) /* Top/Bottom protect */
#define SR_SRWD BIT(7) /* SR write protect */
#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */
/* Enhanced Volatile Configuration Register bits */
#define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */
/* Flag Status Register bits */
#define FSR_READY BIT(7)
/* Configuration Register bits. */
#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */
enum qspi_dev_size {
QSPI_DEV_SIZE_8MB,
QSPI_DEV_SIZE_16MB,
QSPI_DEV_SIZE_32MB,
QSPI_DEV_SIZE_4MB,
};
/**
* @brief ll_qspi_enable
* @param p_qspi :QSPI register structure pointer
* @retval none
*/
__STATIC_INLINE void ll_qspi_enable(struct hgcqspi_hw *p_qspi)
{
p_qspi->CONFIG |= CQSPI_REG_CONFIG_ENABLE_MASK;
}
/**
* @brief ll_qspi_disable
* @param p_qspi :QSPI register structure pointer
* @retval none
*/
__STATIC_INLINE void ll_qspi_disable(struct hgcqspi_hw *p_qspi)
{
p_qspi->CONFIG &= ~CQSPI_REG_CONFIG_ENABLE_MASK;
}
/**
* @brief ll_qspi_cs_sel
* @param p_qspi :QSPI register structure pointer
* @param cs :cs select [0:3]
* @retval none
*/
__STATIC_INLINE void ll_qspi_cs_sel(struct hgcqspi_hw *p_qspi, uint8 cs)
{
p_qspi->CONFIG = (p_qspi->CONFIG & ~(CQSPI_REG_CONFIG_CHIPSELECT_MASK << CQSPI_REG_CONFIG_CHIPSELECT_LSB)) |
((~(BIT(cs)) & CQSPI_REG_CONFIG_CHIPSELECT_MASK) << CQSPI_REG_CONFIG_CHIPSELECT_LSB);
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param
* @retval none
*/
__STATIC_INLINE void ll_qspi_ahb_decoder_enable(struct hgcqspi_hw *p_qspi)
{
p_qspi->CONFIG |= BIT(23);
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param
* @retval none
*/
__STATIC_INLINE void ll_qspi_set_device_size(struct hgcqspi_hw *p_qspi, uint8 dev_index, enum qspi_dev_size dev_size)
{
uint32 dev_size_reg = p_qspi->DEV_SIZE_CONFIG;
dev_size_reg &= ~((BIT(22)|BIT(21)) << (dev_index*2));
dev_size_reg |= (dev_size << (21 + dev_index*2));
p_qspi->DEV_SIZE_CONFIG = dev_size_reg;
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param
* @retval none
*/
__STATIC_INLINE void ll_qspi_set_page_size(struct hgcqspi_hw *p_qspi, uint32 page_size)
{
uint32 dev_size_reg = p_qspi->DEV_SIZE_CONFIG;
dev_size_reg &= 0xFFFF000F;
dev_size_reg |= (page_size & 0x0FFF) << 4;
p_qspi->DEV_SIZE_CONFIG = dev_size_reg;
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param size : blocksiez = power(2, size)
* @retval none
*/
__STATIC_INLINE void ll_qspi_set_block_size(struct hgcqspi_hw *p_qspi, uint32 size)
{
uint32 dev_size_reg = p_qspi->DEV_SIZE_CONFIG;
dev_size_reg &= 0xFFE0FFFF;
dev_size_reg |= (size & 0x01F) << 16;
p_qspi->DEV_SIZE_CONFIG = dev_size_reg;
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param
* @retval none
*/
__STATIC_INLINE void ll_qspi_ahb_decoder_disable(struct hgcqspi_hw *p_qspi)
{
p_qspi->CONFIG &= ~(BIT(23));
}
/**
* @brief ll_qspi_set_clk
* @param p_qspi :QSPI register structure pointer
* @param clk_hz :
* @retval none
*/
__STATIC_INLINE void ll_qspi_set_clk(struct hgcqspi_hw *p_qspi, uint32 clk_hz)
{
uint32 div;
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
/* Recalculate the baudrate divisor based on QSPI specification. */
#if 1//FPGA
div = DIV_ROUND_UP(96000000, 2 * clk_hz) - 1;
#else
/* fill this : sys_clock_cfg.syspll_clk */
div = DIV_ROUND_UP(384000000, 2 * clk_hz) - 1;
#endif
/* avoid qspi div2 bug */
if (0 == div) div = 1;
p_qspi->CONFIG = (p_qspi->CONFIG & ~(CQSPI_REG_CONFIG_BAUD_MASK << CQSPI_REG_CONFIG_BAUD_LSB)) |
((div & CQSPI_REG_CONFIG_BAUD_MASK) << CQSPI_REG_CONFIG_BAUD_LSB);
}
/**
* @brief ll_qspi_is_idle
* @param p_qspi :QSPI register structure pointer
* @param :
* @retval none
*/
__STATIC_INLINE bool ll_qspi_is_idle(struct hgcqspi_hw *p_qspi)
{
return (p_qspi->CONFIG & BIT(31)) ? TRUE : FALSE;
}
/**
* @brief ll_qspi_is_cmd_done
* @param p_qspi :QSPI register structure pointer
* @param :
* @retval none
*/
__STATIC_INLINE bool ll_qspi_is_cmd_done(struct hgcqspi_hw *p_qspi)
{
return (p_qspi->FLASH_CMD_CTRL & BIT(1)) ? FALSE : TRUE;
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param :
* @retval none
*/
__STATIC_INLINE void ll_qspi_wel_enable(struct hgcqspi_hw *p_qspi)
{
p_qspi->DEV_WRINSTR_CONFIG &= ~(BIT(8));
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param :
* @retval none
*/
__STATIC_INLINE void ll_qspi_wel_disable(struct hgcqspi_hw *p_qspi)
{
p_qspi->DEV_WRINSTR_CONFIG |= BIT(8);
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param :
* @retval none
*/
__STATIC_INLINE bool ll_qspi_is_wel_enable(struct hgcqspi_hw *p_qspi)
{
return (p_qspi->DEV_WRINSTR_CONFIG & BIT(8)) ? FALSE : TRUE;
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param :
* @retval none
*/
__STATIC_INLINE void ll_qspi_poll_enable(struct hgcqspi_hw *p_qspi)
{
p_qspi->WRITE_COMP_CTRL &= ~(BIT(14));
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param :
* @retval none
*/
__STATIC_INLINE void ll_qspi_poll_disable(struct hgcqspi_hw *p_qspi)
{
p_qspi->WRITE_COMP_CTRL |= BIT(14);
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param :
* @retval none
*/
__STATIC_INLINE bool ll_qspi_is_poll_enable(struct hgcqspi_hw *p_qspi)
{
return (p_qspi->WRITE_COMP_CTRL & BIT(14)) ? FALSE : TRUE;
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param width : 0/1/2 for data width 1/2/4
* @retval none
*/
__STATIC_INLINE void ll_qspi_set_rd_attr(struct hgcqspi_hw *p_qspi,
uint8 cmd,
uint8 cmd_width,
uint8 addr_width,
uint8 dat_width,
uint8 dummys,
uint8 ddr_en)
{
p_qspi->DEV_RDINSTR_CONFIG = ((dummys & 0x1F) << 24) |
((dat_width & 0x3) << 16) |
((addr_width & 0x3) << 12) |
((ddr_en & 0x1) << 10) |
((cmd_width & 0x3) << 8) |
cmd;
}
/**
* @brief
* @param p_qspi :QSPI register structure pointer
* @param width : 0/1/2 for data width 1/2/4
* @retval none
*/
__STATIC_INLINE void ll_qspi_set_wr_attr(struct hgcqspi_hw *p_qspi,
uint8 cmd,
uint8 cmd_width,
uint8 addr_width,
uint8 dat_width,
uint8 dummys,
uint8 wel_disable)
{
p_qspi->DEV_WRINSTR_CONFIG = ((dummys & 0x1F) << 24) |
((dat_width & 0x3) << 16) |
((addr_width & 0x3) << 12) |
((wel_disable & 0x1) << 8) |
cmd;
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param width :
* @retval none
*/
__STATIC_INLINE void ll_qspi_set_clk_mode(struct hgcqspi_hw *p_qspi, uint8 clock_mode)
{
p_qspi->CONFIG = (p_qspi->CONFIG & ~(BIT(1)|BIT(2))) | ((clock_mode & 0x3) << 1);
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param delay_ref_clk : the delay_ref_clk less than divor is better
* @retval none
*/
__STATIC_INLINE void ll_qspi_set_sample_dalay(struct hgcqspi_hw *p_qspi, uint8 delay_ref_clk)
{
delay_ref_clk &= 0xF;
p_qspi->DEV_DELAY = (p_qspi->DEV_DELAY & ~(0xFUL<<1)) | ((delay_ref_clk) << 1);
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param delay_ref_clk : the delay_ref_clk less than divor is better
* @retval none
*/
__STATIC_INLINE void ll_qspi_remap_enable(struct hgcqspi_hw *p_qspi, uint32 offset)
{
while(!ll_qspi_is_idle(p_qspi));
p_qspi->REMAP_ADD = offset;
p_qspi->CONFIG |= (BIT(16));
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
while(!ll_qspi_is_idle(p_qspi));
//csi_dcache_invalid();
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param delay_ref_clk : the delay_ref_clk less than divor is better
* @retval none
*/
__STATIC_INLINE void ll_qspi_remap_disable(struct hgcqspi_hw *p_qspi)
{
while(!ll_qspi_is_idle(p_qspi));
p_qspi->CONFIG &= ~(BIT(16));
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
while(!ll_qspi_is_idle(p_qspi));
//csi_dcache_invalid();
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param delay_ref_clk : the delay_ref_clk less than divor is better
* @retval none
*/
__STATIC_INLINE void ll_qspi_dac_enable(struct hgcqspi_hw *p_qspi)
{
p_qspi->CONFIG |= (BIT(7));
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param delay_ref_clk : the delay_ref_clk less than divor is better
* @retval none
*/
__STATIC_INLINE void ll_qspi_dac_disable(struct hgcqspi_hw *p_qspi)
{
p_qspi->CONFIG &= ~(BIT(7));
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param delay_ref_clk : the delay_ref_clk less than divor is better
* @retval none
*/
__STATIC_INLINE void ll_qspi_cs_fix_enable(struct hgcqspi_hw *p_qspi)
{
p_qspi->WRITE_PROT_CTRL |= (BIT(3));
}
/**
* @brief
* @param p_qspi : QSPI register structure pointer
* @param delay_ref_clk : the delay_ref_clk less than divor is better
* @retval none
*/
__STATIC_INLINE void ll_qspi_cs_fix_disable(struct hgcqspi_hw *p_qspi)
{
p_qspi->WRITE_PROT_CTRL &= ~(BIT(3));
}
__STATIC_INLINE uint32 ll_qspi_is_xip_mode(struct hgcqspi_hw *p_qspi)
{
return (p_qspi->CONFIG & (BIT(17)|BIT(18))) ? 1:0;
}
__STATIC_INLINE uint32 ll_qspi_is_dtr_mode(struct hgcqspi_hw *p_qspi)
{
return (p_qspi->DEV_RDINSTR_CONFIG & BIT(10)) ? 1:0;
}
/**
* @brief hg_qspi_set_encrypt_disable_range
* @param p_qspi : QSPI register structure pointer
* @param index : rang 0/1
* @param st_addr_1k :
* @param end_addr_1k :
* @retval none
*/
__STATIC_INLINE void hg_qspi_set_encrypt_disable_range(struct hgcqspi_hw *p_qspi, uint8 index, uint32 st_addr_1k, uint32 end_addr_1k)
{
uint32 reg = (st_addr_1k & 0x7FFF) | ((end_addr_1k & 0x7FFF) << 16);
SYSCTRL_REG_OPT(
if (index) {
SYSCTRL->QSPI_ENCDEC_CON1 = reg;
} else {
SYSCTRL->QSPI_ENCDEC_CON0 = (SYSCTRL->QSPI_ENCDEC_CON0 & BIT(31)) | reg;
}
);
}
enum hgcqspi_flags {
hgcqspi_flags_suspend,
};
#ifdef __cplusplus
}
#endif
#endif /* _HGCQSPI_H_ */

View File

@@ -0,0 +1,259 @@
#ifndef _HGSPI_V1_HW_H_
#define _HGSPI_V1_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup SPI MODULE REGISTER
* @{
*/
/***** CON0(for SPI) Register *****/
/*! SPI slave read status done interrupt enable
*/
#define LL_SPI_CON0_SLAVE_WRONGCMD_IE_EN (1UL << 25)
/*! SPI slave read status done interrupt enable
*/
#define LL_SPI_CON0_SLAVE_WIREMODE_IE_EN (1UL << 24)
/*! SPI slave read status done interrupt enable
*/
#define LL_SPI_CON0_SLAVE_RDSTATUS_IE_EN (1UL << 23)
/*! SPI slave read data done interrupt enable
*/
#define LL_SPI_CON0_SLAVE_RDDATA_IE_EN (1UL << 22)
/*! SPI slave write data done interrupt enable
*/
#define LL_SPI_CON0_SLAVE_WRDATA_IE_EN (1UL << 21)
/*! SPI slave state enable
*/
#define LL_SPI_CON0_SLAVE_STATE_EN (1UL << 20)
/*! SPI frame size
*/
#define LL_SPI_CON0_FRAME_SIZE(n) (((n)&0x3F) << 14)
/*! Get SPI frame size
*/
#define LL_SPI_CON0_GET_FRAME_SIZE(n) (((n)>>14) & 0x3F)
/*! SPI slave CS(NSS) rising edge interrupt enable
*/
#define LL_SPI_CON0_NSS_POS_IE_EN (1UL << 13)
/*! SPI CS(NSS) pin enable
*/
#define LL_SPI_CON0_NSS_PIN_EN (1UL << 12)
/*! SPI CS(NSS) output high
* @note Only valid in SPI master mode
*/
#define LL_SPI_CON0_NSS_HIGH (1UL << 11)
/*! Input data synchronization enable in SPI slave mode
*/
#define LL_SPI_CON0_SLAVE_SYNC_EN (1UL << 7)
/*! Input data synchronization enable in SPI master mode
*/
#define LL_SPI_CON0_MASTER_SYNC_EN (1UL << 6)
/*! The SPI transfers data from the low bit
*/
#define LL_SPI_CON0_LSB_FIRST (1UL << 4)
/*! SPI wire mode
*/
#define LL_SPI_CON0_WIRE_MODE(n) (((n)&0x03) << 2)
/*! Get SPI wire mode
*/
#define LL_SPI_CON0_WIRE_MODE_GET(n) (((n)>>2) & 0x03)
/*! SPI mode
*/
#define LL_SPI_CON0_SPI_MODE(n) (((n)&0x03) << 0)
/***** CON1(for SPI) Register *****/
/*! SPI DMA done interrupt enable
*/
#define LL_SPI_CON1_DMA_IE_EN (1UL << 9)
/*! SPI FIFO overflow interrupt enable
*/
#define LL_SPI_CON1_BUF_OV_IE_EN (1UL << 8)
/*! SPI RX FIFO not empty interrupt enable
*/
#define LL_SPI_CON1_RX_BUF_NOT_EMPTY_IE_EN (1UL << 7)
/*! SPI TX FIFO not full interrupt enable
*/
#define LL_SPI_CON1_TX_BUF_NOT_FULL_IE_EN (1UL << 6)
/*! SPI transfers one frame interrupt enable
*/
#define LL_SPI_CON1_SSP_IE_EN (1UL << 5)
/*! SPI DMA enable
*/
#define LL_SPI_CON1_DMA_EN (1UL << 4)
/*! The SPI is set to the TX direction
*/
#define LL_SPI_CON1_TX_EN (1UL << 3)
/*! SPI working mode
*/
#define LL_SPI_CON1_MODE(n) (((n)&0x01) << 2)
/*! Get SPI working mode
*/
#define LL_SPI_CON1_GET_MODE(n) (((n)>>2) & 0x01)
/*! SPI/IIC selection
*/
#define LL_SPI_CON1_SPI_I2C_SEL(n) (((n)&0x01) << 1)
/*! SPI/IIC module enable
*/
#define LL_SPI_CON1_SSP_EN (1UL << 0)
/***** SSP CMD DATA(for SPI) Register *****/
/*! Write data(32bit)
*/
#define LL_SPI_SSP_CMD_DATA_WRITE(n) (n)
/*! Read data(32bit)
*/
#define LL_SPI_SSP_CMD_DATA_READ(n) (n)
/***** BAUD(for SPI) Register *****/
/*! Set baud rate(16bit)
*/
#define LL_SPI_BAUD(n) (n)
/***** DMA Tx LEN(for SPI) Register *****/
/*! Set DMA Tx length(12bit)
*/
#define LL_SPI_DMA_TX_LEN(n) (n)
/***** DMA Tx CNT(for SPI) Register *****/
/*! The length of the byte of the transmitted data(12bit)
*/
#define LL_SPI_DMA_TX_CNT(n) (n)
/***** DMA Tx STADR(for SPI) Register *****/
/*! DMA Tx start address(13bit)
*/
#define LL_SPI_DMA_TX_STADR(n) (n)
/***** DMA Rx LEN(for SPI) Register *****/
/*! Set DMA Rx length(12bit)
*/
#define LL_SPI_DMA_RX_LEN(n) (n)
/***** DMA Rx CNT(for SPI) Register *****/
/*! The length of the byte of the received data(12bit)
*/
#define LL_SPI_DMA_RX_CNT(n) (n)
/***** DMA Rx STADR(for SPI) Register *****/
/*! DMA Rx start address(13bit)
*/
#define LL_SPI_DMA_RX_STADR(n) (n)
/***** STA(for SPI) Register *****/
/*! SPI Slave wrong cmd pending
*/
#define LL_SPI_STA_SLAVE_WRONG_CMD_PENDING (1UL << 28)
/*! SPI Slave wiremode change pending
*/
#define LL_SPI_STA_SLAVE_WIREMODE_CFG_PENDING (1UL << 23)
/*! SPI Slave read status pending
*/
#define LL_SPI_STA_SLAVE_RDSTATUS_PENDING (1UL << 22)
/*! SPI Slave read data pending
*/
#define LL_SPI_STA_SLAVE_RDDATA_PENDING (1UL << 21)
/*! SPI Slave write data pending
*/
#define LL_SPI_STA_SLAVE_WRDATA_PENDING (1UL << 20)
/*! Clear fifo
*/
#define LL_SPI_STA_CLEAR_BUF_CNT (1UL << 19)
/*! Get how many bytes of valid data in the FIFO
*/
#define LL_SPI_STA_BUF_CNT(n) (((n)>>16) & 0x07)
/*! SPI master receive data busy pending
*/
#define LL_SPI_STA_MASTER_RX_BUSY_PENDING (1UL << 15)
/*! The SPI slave gets the CS pin state
*/
#define LL_SPI_STA_SLAVE_CS_STATE (1UL << 11)
/*! SPI module busy pending
*/
#define LL_SPI_STA_SSP_BUSY_PENDING (1UL << 10)
/*! SPI slave CS(NSS) rising edge detected pending
*/
#define LL_SPI_STA_NSS_POS_PENDING (1UL << 5)
/*! SPI DMA done pending
*/
#define LL_SPI_STA_DMA_PENDING (1UL << 4)
/*! SPI FIFO overflow pending
*/
#define LL_SPI_STA_BUF_OV_PENDING (1UL << 3)
/*! SPI FIFO empty pending
*/
#define LL_SPI_STA_BUF_EMPTY_PENDING (1UL << 2)
/*! SPI FIFO full pending
*/
#define LL_SPI_STA_BUF_FULL_PENDING (1UL << 1)
/*! SPI transfers one frame done pending
*/
#define LL_SPI_STA_DONE_PENDING (1UL << 0)
/***** SLAVESTA(for SPI) Register *****/
#define LL_SPI_SLAVE_STA_TX_LEN(n) (((n)&0xFF) << 16)
#define LL_SPI_SLAVE_STA_RX_LEN(n) (((n)&0xFF) << 8)
#define LL_SPI_SLAVE_STA_RX_READY_EN (1UL << 7)
#define LL_SPI_SLAVE_STA_TX_READY_EN (1UL << 6)
#define LL_SPI_SLAVE_STA_SW_RESERVED (1UL << 5)
#define LL_SPI_SLAVE_STA_WRONG_COMMAND (1UL << 4)
#define LL_SPI_SLAVE_STA_DATA_TOGGLE (1UL << 3)
#define LL_SPI_SLAVE_STA_TX_OVERFLOW (1UL << 2)
#define LL_SPI_SLAVE_STA_RX_READY_FLG (1UL << 1)
#define LL_SPI_SLAVE_STA_TX_READY_FLG (1UL << 0)
/***** SSP_DLY Register *****/
/*! Transfer delay time config
@Note: t = APB_CLK * (n)
*/
#define LL_SPI_AND_IIC_SSP_DLY(n) ((n & 0xFF) << 0)
/** @brief SPI register structure
* @{
*/
struct hgspi_v1_hw {
__IO uint32_t CON0;
__IO uint32_t CON1;
__IO uint32_t CMD_DATA;
__IO uint32_t BAUD;
__IO uint32_t TDMALEN;
__IO uint32_t RDMALEN;
__IO uint32_t TDMACNT;
__IO uint32_t RDMACNT;
__IO uint32_t TSTADR;
__IO uint32_t RSTADR;
__IO uint32_t STA;
__IO uint32_t SLAVESTA;
__IO uint32_t SSP_DLY;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGSPI_V1_HW_H_ */

View File

@@ -0,0 +1,68 @@
#ifndef _HGGPIO_V4_HW_H_
#define _HGGPIO_V4_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
/***** SPICON *****/
/*! Interrupt flag clear, write 1 to clear, write 0 to have no effect
*/
#define LL_SIMPLE_SPI_CON_SPIINTCLR(n) (((n)&0x01) << 10)
/*! SPI interrupt flag
*/
#define LL_SIMPLE_SPI_CON_SPIINT(n) (((n)&0x01) << 9)
/*! SPI status flag
*/
#define LL_SIMPLE_SPI_CON_SPIDONE(n) (((n)&0x01) << 8)
/*! DMA enable flag
*/
#define LL_SIMPLE_SPI_CON_SPIDISYNCEN(n) (((n)&0x01) << 7)
/*! Master or slave control bits
*/
#define LL_SIMPLE_SPI_CON_SPISM(n) (((n)&0x01) << 6)
/*! Send or receive control bits
*/
#define LL_SIMPLE_SPI_CON_SPIRXTX(n) (((n)&0x01) << 5)
/*! 2-wire or 3-wire mode selection
*/
#define LL_SIMPLE_SPI_CON_SPI2W3W(n) (((n)&0x01) << 4)
/*! SPI interrupt enable bit
*/
#define LL_SIMPLE_SPI_CON_SPIINTEN(n) (((n)&0x01) << 3)
/*! Sampling mode selection bit
*/
#define LL_SIMPLE_SPI_CON_SPISMPSEL(n) (((n)&0x01) << 2)
/*! Clock line idle state selection bit
*/
#define LL_SIMPLE_SPI_CON_SPIIDST(n) (((n)&0x01) << 1)
/*! SPI enable bit
*/
#define LL_SIMPLE_SPI_CON_SPIEN(n) (((n)&0x01) << 0)
/*****SPIBAUD *****/
/*! Baud rate setting
*/
#define LL_SIMPLE_SPI_SPIBAUD(n) (((n)&0x0000FFFF) << 0)
/***** SPIDATA *****/
/*! Data register
*/
#define LL_SIMPLE_SPI_SPIDATA(n) (((n)&0x000000FF) << 0)
struct hgspi_v2_hw {
__IO uint32_t CON;
__IO uint32_t BAUD;
__IO uint32_t DATA;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGGPIO_V4_HW_H_ */

1558
sdk/driver/spi/hgspi_v3.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,305 @@
#ifndef _HGSPI_V3_HW_H_
#define _HGSPI_V3_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup SPI MODULE REGISTER
* @{
*/
/***** CON0(for SPI) Register *****/
#define LL_SPI_CON0_DUMMY_CNT(n) ((n&0x0F) << 26)
#define LL_SPI_CON0_SLAVE_WRONG_CMD_IE (1UL << 25)
#define LL_SPI_CON0_SLAVE_WIREMODE_CFG_IE (1UL << 24)
/*! SPI slave read status done interrupt enable
*/
#define LL_SPI_CON0_SLAVE_RDSTATUS_IE_EN (1UL << 23)
/*! SPI slave read data done interrupt enable
*/
#define LL_SPI_CON0_SLAVE_RDDATA_IE_EN (1UL << 22)
/*! SPI slave write data done interrupt enable
*/
#define LL_SPI_CON0_SLAVE_WRDATA_IE_EN (1UL << 21)
/*! SPI slave state enable
*/
#define LL_SPI_CON0_SLAVE_STATE_EN (1UL << 20)
/*! SPI frame size
*/
#define LL_SPI_CON0_FRAME_SIZE(n) (((n)&0x3F) << 14)
/*! Get SPI frame size
*/
#define LL_SPI_CON0_GET_FRAME_SIZE(n) (((n)>>14) & 0x3F)
/*! SPI slave CS(NSS) rising edge interrupt enable
*/
#define LL_SPI_CON0_NSS_POS_IE_EN (1UL << 13)
#define LL_SPI_CON0_SSOE(n) ((n&0x01) << 12)
/*! SPI CS(NSS) output high
* @note Only valid in SPI master mode
*/
#define LL_SPI_CON0_NSS_HIGH (1UL << 11)
/*! SPI CS(NSS) pin enable
*/
#define LL_SPI_CON0_NSS_PIN_EN (1UL << 10)
#define LL_SPI_CON0_SPI_HIGH_SPEED(n) ((n&0x3) << 8)
#define LL_SPI_CON0_SLAVE_DATAIN_SEL(n) ((n&0x3) << 6)
/*! The SPI transfers data from the low bit
*/
#define LL_SPI_CON0_LSB_FIRST (1UL << 5)
/*! SPI wire mode
*/
#define LL_SPI_CON0_WIRE_MODE(n) (((n)&0x07) << 2)
/*! Get SPI wire mode
*/
#define LL_SPI_CON0_WIRE_MODE_GET(n) (((n)>>2) & 0x03)
/*! SPI mode
*/
#define LL_SPI_CON0_SPI_MODE(n) (((n)&0x03) << 0)
/***** CON1(for SPI) Register *****/
#define LL_SPI_CON1_PING_PONG_EN(n) ((n&0x1) << 12)
#define LL_SPI_CON1_CLRBUFCNT_CLRSSP_EN(n) ((n&0x1) << 11)
#define LL_SPI_CON1_RX_TIMEOUT_IE(n) ((n&0x1) << 10)
/*! SPI DMA done interrupt enable
*/
#define LL_SPI_CON1_DMA_IE_EN (1UL << 9)
/*! SPI FIFO overflow interrupt enable
*/
#define LL_SPI_CON1_BUF_OV_IE_EN (1UL << 8)
/*! SPI RX FIFO not empty interrupt enable
*/
#define LL_SPI_CON1_RX_BUF_NOT_EMPTY_IE_EN (1UL << 7)
/*! SPI TX FIFO not full interrupt enable
*/
#define LL_SPI_CON1_TX_BUF_NOT_FULL_IE_EN (1UL << 6)
/*! SPI transfers one frame interrupt enable
*/
#define LL_SPI_CON1_SSP_IE_EN (1UL << 5)
/*! SPI DMA enable
*/
#define LL_SPI_CON1_DMA_EN (1UL << 4)
/*! The SPI is set to the TX direction
*/
#define LL_SPI_CON1_TX_EN (1UL << 3)
/*! SPI working mode
*/
#define LL_SPI_CON1_MODE(n) (((n)&0x01) << 2)
/*! Get SPI working mode
*/
#define LL_SPI_CON1_GET_MODE(n) (((n)>>2) & 0x01)
/*! SPI/IIC selection
*/
#define LL_SPI_CON1_SPI_I2C_SEL(n) (((n)&0x01) << 1)
/*! SPI/IIC module enable
*/
#define LL_SPI_CON1_SSP_EN (1UL << 0)
/***** SSP CMD DATA(for SPI) Register *****/
/*! Write data(32bit)
*/
#define LL_SPI_SSP_CMD_DATA_WRITE(n) (n)
/*! Read data(32bit)
*/
#define LL_SPI_SSP_CMD_DATA_READ(n) (n)
/***** TIMECON(for SPI) Register *****/
/*! Set baud rate(16bit)
*/
#define LL_SPI_TIMECON_SPI_RX_DLY(n) ((n&0xFFFF)<<16)
#define LL_SPI_TIMECON_BAUD(n) ((n&0xFFFF)<<0)
/***** DMA Tx LEN(for SPI) Register *****/
/*! Set DMA Tx length(12bit)
*/
#define LL_SPI_DMA_TX_LEN(n) (n)
/***** DMA Tx CNT(for SPI) Register *****/
/*! The length of the byte of the transmitted data(12bit)
*/
#define LL_SPI_DMA_TX_CNT(n) (n)
/***** DMA Tx STADR(for SPI) Register *****/
/*! DMA Tx start address(13bit)
*/
#define LL_SPI_DMA_TX_STADR(n) (n)
/***** DMA Rx LEN(for SPI) Register *****/
/*! Set DMA Rx length(12bit)
*/
#define LL_SPI_DMA_RX_LEN(n) (n)
/***** DMA Rx CNT(for SPI) Register *****/
/*! The length of the byte of the received data(12bit)
*/
#define LL_SPI_DMA_RX_CNT(n) (n)
/***** DMA Rx STADR(for SPI) Register *****/
/*! DMA Rx start address(13bit)
*/
#define LL_SPI_DMA_RX_STADR(n) (n)
/***** STA(for SPI) Register *****/
#define LL_SPI_STA_CLR_BUF_CNT (1UL << 31)
#define LL_SPI_STA_HSYNC_PEND (1UL << 21)
#define LL_SPI_STA_VSYNC_PEND (1UL << 20)
#define LL_SPI_STA_DMA_PPBUF_SEL (1UL << 19)
#define LL_SPI_STA_RX_TIMEOUT_PEND (1UL << 18)
#define LL_SPI_STA_MODF (1UL << 17)
/*! SPI Slave wrong cmd pending
*/
#define LL_SPI_STA_SLAVE_WRONG_CMD_PENDING (1UL << 16)
/*! SPI Slave wiremode change pending
*/
#define LL_SPI_STA_SLAVE_WIREMODE_CFG_PENDING (1UL << 15)
/*! SPI Slave read status pending
*/
#define LL_SPI_STA_SLAVE_RDSTATUS_PENDING (1UL << 14)
/*! SPI Slave read data pending
*/
#define LL_SPI_STA_SLAVE_RDDATA_PENDING (1UL << 13)
/*! SPI Slave write data pending
*/
#define LL_SPI_STA_SLAVE_WRDATA_PENDING (1UL << 12)
/*! Clear fifo
*/
#define LL_SPI_STA_CLEAR_BUF_CNT (1UL << 9)
/*! Get how many bytes of valid data in the FIFO
*/
#define LL_SPI_STA_BUF_CNT(n) (((n)>>9) & 0x07)
/*! SPI master receive data busy pending
*/
#define LL_SPI_STA_MASTER_RX_BUSY_PENDING (1UL << 8)
/*! The SPI slave gets the CS pin state
*/
#define LL_SPI_STA_SLAVE_CS_STATE (1UL << 7)
/*! SPI module busy pending
*/
#define LL_SPI_STA_SSP_BUSY_PENDING (1UL << 6)
/*! SPI slave CS(NSS) rising edge detected pending
*/
#define LL_SPI_STA_NSS_POS_PENDING (1UL << 5)
/*! SPI DMA done pending
*/
#define LL_SPI_STA_DMA_PENDING (1UL << 4)
/*! SPI FIFO overflow pending
*/
#define LL_SPI_STA_BUF_OV_PENDING (1UL << 3)
/*! SPI FIFO empty pending
*/
#define LL_SPI_STA_BUF_EMPTY_PENDING (1UL << 2)
/*! SPI FIFO full pending
*/
#define LL_SPI_STA_BUF_FULL_PENDING (1UL << 1)
/*! SPI transfers one frame done pending
*/
#define LL_SPI_STA_DONE_PENDING (1UL << 0)
/***** RBUF(for SPI) Register *****/
#define LL_SPI_RBUF(n) ((n) & 0xFF)
/***** RX_TIMEOUTCON(for SPI) Register *****/
#define LL_SPI_RX_TIMEOUTCON(n) ((n&0x1FFFFFFF)<<1)
#define LL_SPI_RX_TIMEOUT_EN(n) ((n&0x1)<<0)
/***** RSTADR1(for SPI) Register *****/
#define LL_SPI_RSTADR1(n) (n)
/***** VSYNV_TCON(for SPI) Register *****/
#define LL_SPI_VSYNV_TCON_VSYNC_TIME(n) ((n&0x1FFFFF)<<8)
#define LL_SPI_VSYNV_TCON_VSYNC_MASK_CNT(n) ((n&0x3F)<<1)
#define LL_SPI_VSYNV_TCON_VHSYNC_DETEN(n) ((n&0x01)<<0)
/***** HSYNV_TCON(for SPI) Register *****/
#define LL_SPI_HSYNV_TCON_HSYNC_TIME(n) ((n&0xFFFF)<<8)
#define LL_SPI_HSYNV_TCON_HSYNC_MASK_CNT(n) ((n&0x3F)<<0)
/***** SLAVESTA(for SPI) Register *****/
#define LL_SPI_SLAVE_STA_TX_LEN(n) (((n)&0xFF) << 16)
#define LL_SPI_SLAVE_STA_RX_LEN(n) (((n)&0xFF) << 8)
#define LL_SPI_SLAVE_STA_RX_READY_EN (1UL << 7)
#define LL_SPI_SLAVE_STA_TX_READY_EN (1UL << 6)
#define LL_SPI_SLAVE_STA_SW_RESERVED (1UL << 5)
#define LL_SPI_SLAVE_STA_WRONG_COMMAND (1UL << 4)
#define LL_SPI_SLAVE_STA_DATA_TOGGLE (1UL << 3)
#define LL_SPI_SLAVE_STA_TX_OVERFLOW (1UL << 2)
#define LL_SPI_SLAVE_STA_RX_READY_FLG (1UL << 1)
#define LL_SPI_SLAVE_STA_TX_READY_FLG (1UL << 0)
/** @brief SPI register structure
* @{
*/
struct hgspi_v3_hw {
__IO uint32_t CON0;
__IO uint32_t CON1;
__IO uint32_t CMD_DATA;
__IO uint32_t TIMECON;
__IO uint32_t TDMALEN;
__IO uint32_t RDMALEN;
__IO uint32_t TDMACNT;
__IO uint32_t RDMACNT;
__IO uint32_t TSTADR;
__IO uint32_t RSTADR;
__IO uint32_t STA1;
__IO uint32_t STA2;
__IO uint32_t SLAVESTA;
__IO uint32_t OWNADRCON;
__IO uint32_t RBUF;
__IO uint32_t TIMEOUTCON;
__IO uint32_t RXTIMEOUTCON;
__IO uint32_t RSTADR1;
__IO uint32_t VSYNC_TCON;
__IO uint32_t HSYNC_TCON;
__IO uint32_t LINE_LEN;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGSPI_V3_HW_H_ */

View File

@@ -0,0 +1,288 @@
/**
******************************************************************************
* @file hg_sysaes_v3.c
* @author HUGE-IC Application Team
* @version TXW81X
* @date
* @brief standard aes support aes 128/192/256
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2019 HUGE-IC</center></h2>
*
*
*
******************************************************************************
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "devid.h"
#include "osal/string.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/irq.h"
#include "dev/sysaes/hg_sysaes_v3.h"
#include "hg_sysaes_v3_hw.h"
#include "hal/sysaes.h"
#define SYS_AES_DEBUG_ERR_ENABLE 1
#if SYS_AES_DEBUG_ERR_ENABLE
#define SYS_AES_ERR_PRINTF(fmt, args...) os_printf(fmt, ##args)
#else
#define SYS_AES_ERR_PRINTF(fmt, args...)
#endif
static void hg_sysaes_v3_irq_handler(void *data)
{
struct hg_sysaes_v3 *sysaes = (struct hg_sysaes_v3 *)data;
struct hg_sysaes_v3_hw *hw = (struct hg_sysaes_v3_hw *)sysaes->hw;
hw->AES_STAT = AES_STAT_COMP_PD_MSK;
os_sema_up(&sysaes->done);
}
static void hg_sysaes_v3_fill_key(struct sysaes_dev *dev, struct sysaes_para *para)
{
struct hg_sysaes_v3 *sysaes = (struct hg_sysaes_v3 *)dev;
struct hg_sysaes_v3_hw *hw = (struct hg_sysaes_v3_hw *)sysaes->hw;
for (uint8 i = 0; i < 8; ++i) {
hw->KEY[i] = get_unaligned_le32((const void*)&para->key[i*4]);
}
}
static int32 hg_sysaes_v3_hdl(struct sysaes_dev *dev, struct sysaes_para *para, uint32 flags)
{
int32 ret;
uint32 aes_key_len = 0;
uint32 aes_mode = 0;
struct hg_sysaes_v3 *sysaes = (struct hg_sysaes_v3 *)dev;
struct hg_sysaes_v3_hw *hw = (struct hg_sysaes_v3_hw *)sysaes->hw;
if ((para->key_len > AES_KEY_LEN_BIT_256)) {
return RET_ERR;
}
ret = os_mutex_lock(&sysaes->lock, osWaitForever);
if (ret) {
if (flags == ENCRYPT) {
SYS_AES_ERR_PRINTF("sysaes encrypt lock timeout!\r\n");
} else {
SYS_AES_ERR_PRINTF("sysaes decrypt lock timeout!\r\n");
}
os_mutex_unlock(&sysaes->lock);
return RET_ERR;
}
os_sema_eat(&sysaes->done);
if (flags == ENCRYPT) {
hw->AES_CTRL &= ~AES_CTRL_EOD_MSK;
} else {
hw->AES_CTRL |= AES_CTRL_EOD_MSK;
}
switch (para->mode) {
case AES_MODE_ECB:
aes_mode = AES_CTRL_AES_ECB;
break;
case AES_MODE_CBC:
aes_mode = AES_CTRL_AES_CBC;
break;
case AES_MODE_CTR:
aes_mode = AES_CTRL_AES_CTR;
break;
default:
break;
}
hw->AES_CTRL = (hw->AES_CTRL & ~ AES_CTRL_AES_MODE_MSK) | (aes_mode & AES_CTRL_AES_MODE_MSK);
switch (para->key_len) {
case AES_KEY_LEN_BIT_128:
aes_key_len = AES_CTRL_AES_128;
break;
case AES_KEY_LEN_BIT_192:
aes_key_len = AES_CTRL_AES_192;
break;
case AES_KEY_LEN_BIT_256:
aes_key_len = AES_CTRL_AES_256;
break;
default:
break;
}
hw->AES_CTRL = (hw->AES_CTRL & ~ AES_CTRL_AES_KEYLEN_MSK) |
(aes_key_len & AES_CTRL_AES_KEYLEN_MSK) |
AES_CTRL_IRQ_EN_MSK;
// READ_ADDR
sys_dcache_clean_range_unaligned((uint32 *)para->src, para->aes_len);
// WRITE_ADDR
sys_dcache_invalid_range_unaligned((uint32 *)para->dest, para->aes_len);
hw->SADDR = (uint32)para->src;
hw->DADDR = (uint32)para->dest;
hw->BLOCK_NUM = para->aes_len;
hw->AES_CTRL &= ~AES_CTRL_MOD_MSK;
for (uint8 i = 0; i < 8; ++i) {
hw->KEY[i] = get_unaligned_le32((const void*)&para->key[i*4]);
}
for (uint8 i = 0; i < 4; ++i) {
hw->IV[i] = get_unaligned_le32((const void*)&para->iv[i*4]);
}
if(para->mode == AES_MODE_CTR) {
hw->IV[3] = (para->iv[12]) | (para->iv[13] << 8) | (para->iv[15] << 16) | (para->iv[14] << 24);
}
hw->AES_STAT = AES_STAT_COMP_PD_MSK;
while(ll_sysctrl_dma2ahb_is_busy(DMA2AHB_BURST_CH_SYSAES_WR));
hw->AES_CTRL |= AES_CTRL_START_MSK;
ret = os_sema_down(&sysaes->done, 2000);
if (!ret) {
sysctrl_sysaes_reset();
if (flags == ENCRYPT) {
SYS_AES_ERR_PRINTF("sysaes encrypt wait irq timeout!\r\n");
} else {
SYS_AES_ERR_PRINTF("sysaes decrypt wait irq timeout!\r\n");
}
os_mutex_unlock(&sysaes->lock);
return RET_ERR;
}
os_mutex_unlock(&sysaes->lock);
return RET_OK;
}
static int32 hg_sysaes_v3_encrypt(struct sysaes_dev *dev, struct sysaes_para *para)
{
if (para->mode > AES_MODE_CTR) {
return RET_ERR;
}
//hg_sysaes_v3_fill_key(dev, para);
return hg_sysaes_v3_hdl(dev, para, ENCRYPT);
}
static int32 hg_sysaes_v3_decrypt(struct sysaes_dev *dev, struct sysaes_para *para)
{
if (para->mode > AES_MODE_CTR) {
return RET_ERR;
}
//hg_sysaes_v3_fill_key(dev, para);
if (para->mode == AES_MODE_CTR) {
return hg_sysaes_v3_hdl(dev, para, ENCRYPT);
} else {
return hg_sysaes_v3_hdl(dev, para, DECRYPT);
}
}
#ifdef CONFIG_SLEEP
// #define HGAES_SLEEP_TEST(PARA) hg_sysaes_test_printf(PARA)
#define HGAES_SLEEP_TEST(PARA)
void hg_sysaes_test_printf(struct sysaes_dev *dev)
{
uint32_t iv[4] = {0};
volatile uint32_t pt[8];
volatile uint32_t ct[8];
uint32_t ptsum = 0;
uint32_t ctsum = 0;
uint32_t decsum = 0;
for (int i = 0;i<8;i++)
{
pt[i] = 0x12345678+i;
ptsum += pt[i];
}
struct sysaes_para para = {
.mode = AES_MODE_ECB,
.key_len = AES_KEY_LEN_BIT_256,
.dest = (void*)ct,
.src = (void*)pt,
.iv = (void*)iv,
.aes_len = 32,
};
memset(para.key, 0, 32);
hg_sysaes_v3_encrypt(dev, &para);
for (int i = 0;i<8;i++)
{
ctsum += ct[i];
}
_os_printf("ptsum: %x\r\n", ptsum);
_os_printf("ctsum: %x\r\n", ctsum);
para.dest = (void*)pt;
para.src = (void*)ct;
hg_sysaes_v3_decrypt(dev, &para);
for (int i = 0;i<8;i++)
{
decsum += pt[i];
}
_os_printf("decsum: %x\r\n", decsum);
if ((ptsum != decsum) || (ptsum != 0x91a2b3dc) || (ctsum != 0x2e3c234f)) {
_os_printf("sysaes lp err\r\n");
}
}
int32 hg_sysaes_v3_suspend(struct dev_obj *dev)
{
int32 ret = 0;
struct hg_sysaes_v3 *sysaes = (struct hg_sysaes_v3 *)dev;
struct hg_sysaes_v3_hw *hw = (struct hg_sysaes_v3_hw *)sysaes->hw;
(void)hw;
if (sysaes->flags & BIT(HG_SYSAES_FLAGS_SUSPEND)) {
return RET_OK;
}
HGAES_SLEEP_TEST(dev);
ret = os_mutex_lock(&sysaes->lock, osWaitForever);
if (ret < 0)
return ret;
irq_disable(sysaes->irq_num);
sysctrl_sysaes_clk_close();
sysaes->flags |= BIT(HG_SYSAES_FLAGS_SUSPEND);
return RET_OK;
}
int32 hg_sysaes_v3_resume(struct dev_obj *dev)
{
int32 ret = 0;
struct hg_sysaes_v3 *sysaes = (struct hg_sysaes_v3 *)dev;
struct hg_sysaes_v3_hw *hw = (struct hg_sysaes_v3_hw *)sysaes->hw;
(void)hw;
if (sysaes->flags & BIT(HG_SYSAES_FLAGS_SUSPEND)) {
ret = os_mutex_unlock(&sysaes->lock);
if (ret < 0)
return ret;
sysctrl_sysaes_clk_open();
sysctrl_sysaes_reset();
sysaes->flags &= ~ BIT(HG_SYSAES_FLAGS_SUSPEND);
irq_enable(sysaes->irq_num);
HGAES_SLEEP_TEST(dev);
}
return RET_OK;
}
#endif
static const struct aes_hal_ops aes_v3_ops = {
.encrypt = hg_sysaes_v3_encrypt,
.decrypt = hg_sysaes_v3_decrypt,
#ifdef CONFIG_SLEEP
.ops.suspend = hg_sysaes_v3_suspend,
.ops.resume = hg_sysaes_v3_resume,
#endif
};
__init int32 hg_sysaes_v3_attach(uint32 dev_id, struct hg_sysaes_v3 *sysaes)
{
sysaes->dev.dev.ops = (const struct devobj_ops *)&aes_v3_ops;
os_mutex_init(&sysaes->lock);
os_sema_init(&sysaes->done, 0);
sysctrl_sysaes_clk_open();
sysctrl_sysaes_reset();
request_irq(sysaes->irq_num, hg_sysaes_v3_irq_handler, sysaes);
irq_enable(sysaes->irq_num);
dev_register(dev_id, (struct dev_obj *)sysaes);
return RET_OK;
}

View File

@@ -0,0 +1,54 @@
#ifndef _HG_SYSAES_V3_HW_H_
#define _HG_SYSAES_V3_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
#define BLOCK_NUM_NUM_MSK 0x000fffff
#define BLOCK_NUM_NUM_SHIFT 0
#define AES_CTRL_START_MSK 0x00000001
#define AES_CTRL_START_SHIFT 0
#define AES_CTRL_EOD_MSK 0x00000002
#define AES_CTRL_EOD_SHIFT 1
#define AES_CTRL_MOD_MSK 0x00000004
#define AES_CTRL_MOD_SHIFT 2
#define AES_CTRL_IRQ_EN_MSK 0x00000008
#define AES_CTRL_IRQ_EN_SHIFT 3
#define AES_CTRL_AES_128 0
#define AES_CTRL_AES_192 BIT(4)
#define AES_CTRL_AES_256 BIT(5)
#define AES_CTRL_AES_KEYLEN_MSK (BIT(4)|BIT(5))
#define AES_CTRL_AES_ECB 0
#define AES_CTRL_AES_CBC BIT(6)
#define AES_CTRL_AES_CTR BIT(7)
#define AES_CTRL_AES_MODE_MSK (BIT(6)|BIT(7))
#define AES_STAT_COMP_PD_MSK 0x00000001
#define AES_STAT_COMP_PD_SHIFT 0
enum hg_sysaes_v3_mode {
ENCRYPT,
DECRYPT,
};
enum hg_sysaes_v3_flags {
HG_SYSAES_FLAGS_SUSPEND,
};
struct hg_sysaes_v3_hw {
__IO uint32 KEY[8];
__IO uint32 SADDR;
__IO uint32 DADDR;
__IO uint32 BLOCK_NUM;
uint32 RESERVED0[1];
__IO uint32 IV[4];
__IO uint32 AES_CTRL;
__IO uint32 AES_STAT;
};
#endif /* _HG_SYSAES_V3_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,311 @@
#ifndef _HGTIMER_V4_HW_H
#define _HGTIMER_V4_HW_H
#ifdef __cplusplus
extern "C" {
#endif
/***** TIMERx CON Register *****/
/*! Timer IR selection whether lsb first send (for TIMER1/2 only)
*/
#define LL_TIMER_CON_IR_TMR_FST_LSB_SEL (1UL << 29)
/*! Timer IR function logic 0 PWM polarity selection (for TIMER1/2 only)
*/
#define LL_TIMER_CON_IR_ZERO_PWMPOL (1UL << 28)
/*! Timer IR function logic 1 PWM polarity selection (for TIMER1/2 only)
*/
#define LL_TIMER_CON_IR_ONE_PWMPOL (1UL << 27)
/*! Timer IR function enable (for TIMER1/2 only)
*/
#define LL_TIMER_CON_IR_EN (1UL << 26)
/*! PWM polarity selection in TIMER module
*/
#define LL_TIMER_CON_PWMPOL (1UL << 25)
/*! The polarity of capture event 1 is selected: 0 = rising edge, 1 = falling edge.
*/
#define LL_TIMER_CON_CAP1POL(n) ((n & 0x1) << 21)
/*! When the capture event 1 occurs, the value of the CNT is automatically cleared.
*/
#define LL_TIMER_CON_CTRRST1 (1UL << 17)
/*! The number of the Capture register:
* 00 : Capture data store in CAP1
* 01 : Capture data store in CAP1 CAP2
* 10 : Capture data store in CAP1 CAP2 CAP3
* 11 : Capture data store in CAP1 CAP2 CAP3 CAP4
*/
#define LL_TIMER_CON_CAP_CNT(n) (((n)&0x3) << 15)
/*! Capture selection:
* 00 : GPIO
* 01 : GPIO OR
* 10 : compare0 output
* 11 : compare1 output
*/
#define LL_TIMER_CON_CAP_SEL(n) (((n)&0x3) << 13)
/*! Output sync signal selection:
* 00 : CNT value = PRD value
* 01 : CNT value = CMP value
* 10 : Output SYNCI value to SYNCO
* 11 : PWM output is assigned to SYNCO
*/
#define LL_TIMER_CON_SYNCO_SEL(n) (((n)&0x3) << 11)
/*! Synci polarity inversion:
* 1 : Invert
* 0 : not reversed
*/
#define LL_TIMER_CON_SYNCI_POL (1UL << 10)
/*! Synci function selection
* 00 : disable
* 01 : kick start
* 10 : reset
* 11 : gating
*/
#define LL_TIMER_CON_SLAVE_MODE(n) (((n)&0x3) << 8)
/*! Timer prescaler settings:
* 000 : 0 frequency division
* 001 : 2 frequency division
* 010 : 4 frequency division
* 011 : 8 frequency division
* 100 : 16 frequency division
* 101 : 32 frequency division
* 110 : 64 frequency division
* 111 : 128 frequency division
*/
#define LL_TIMER_CON_PSC(n) (((n)&0x7) << 5)
/*! Timer counter source select bits:
* 001 : Internal high speed RC
* 010 : Internal low speed RC
* 011 : External crystal oscillator divided by 2 clocks
* 100 : timer inc pin rising
* 101 : timer inc pin falling
* 110 : timer inc pin rising and falling
* Others : system clock
*/
#define LL_TIMER_CON_INC_SRC_SEL(n) (((n)&0x7) << 2)
/*! Timer mode select bits:
* 00 : timer counter mode
* 01 : timer pwm mode
* 10 : timer capture mode
* Others : reservation
*/
#define LL_TIMER_CON_MODE_SEL(n) (((n)&0x3) << 0)
/***** TIMERx EN Register *****/
/*! TMR enable signal, active high.
*/
#define LL_TIMER_EN_TMREN (1UL << 0)
/***** TIMERx IE Register *****/
/*! Timer IR TX word done interrupt enable (for TIMER1/2 only)
*/
#define LL_TIMER_IE_IR_TX_WORD_DONE_IE (1UL << 11)
/*! Timer IR TX done interrupt enable (for TIMER1/2 only)
*/
#define LL_TIMER_IE_IR_TX_DONE_IE (1UL << 10)
/*! Dma buffer full interrupt enable.
*/
#define LL_TIMER_IE_DMA_FL_IE (1UL << 9)
/*! Dma buffer half full interrupt enable.
*/
#define LL_TIMER_IE_DMA_HF_IE (1UL << 8)
/*! The slave mode trigger mode or reset mode interrupt enable.
*/
#define LL_TIMER_IE_SLAVE_IE (1UL << 7)
/*! When the CNT value is equal to the CMP value, the interrupt is enabled and is valid only in pwm mode.
*/
#define LL_TIMER_IE_CMP_IE (1UL << 6)
/*! When the CNT value is equal to the PRD value, the interrupt is enabled and is valid only in the counter mode/PWM mode.
*/
#define LL_TIMER_IE_PRD_IE (1UL << 5)
/*! When the CNT value overflows (16'hffff), the interrupt is enabled.
*/
#define LL_TIMER_IE_OVF_IE (1UL << 4)
/*! When the capture event 1 occurs, the interrupt is enabled.
@note: none this capture event interrupt
*/
#define LL_TIMER_IE_CAP1_IE (1UL << 0)
/***** TIMERx CNT Register *****/
/*! Count register.
*/
#define LL_TIMER_CNT(n) (((n)&0xFFFFFFFF) << 0)
/***** TIMERx FLG Register *****/
/*! Timer IR TX word done interrupt flag (for TIMER1/2 only)
*/
#define LL_TIMER_IE_IR_TX_WORD_DONE_FLG (1UL << 11)
/*! Timer IR TX done interrupt flag (for TIMER1/2 only)
*/
#define LL_TIMER_IE_IR_TX_DONE_FLG (1UL << 10)
/*! Dma buffer full sign.
*/
#define LL_TIMER_IE_DMA_FL_FLG (1UL << 9)
/*! Dma buffer half full sign.
*/
#define LL_TIMER_IE_DMA_HF_FLG (1UL << 8)
/*! The slave mode flag (reset or trigger only).
*/
#define LL_TIMER_IE_SLAVE_FLG (1UL << 7)
/*! The CNT value is equal to the CMP value flag and is valid only in pwm mode.
*/
#define LL_TIMER_IE_CMP_FLG (1UL << 6)
/*! The CNT value is equal to the PRD value flag and is valid only in counter mode/PWM mode.
*/
#define LL_TIMER_IE_PRD_FLG (1UL << 5)
/*! CNT value overflow (16'hffff) flag.
*/
#define LL_TIMER_IE_OVF_FLG (1UL << 4)
/*! Capture event 1 occurs.
*/
#define LL_TIMER_IE_CAP1_FLG (1UL << 0)
/***** TIMERx CLR Register *****/
/*! Timer IR TX word done interrupt clear (for TIMER1/2 only)
*/
#define LL_TIMER_IE_IR_TX_WORD_DONE_CLR (1UL << 11)
/*! Timer IR TX done interrupt clear (for TIMER1/2 only)
*/
#define LL_TIMER_IE_IR_TX_DONE_CLR (1UL << 10)
/*! Dma buffer full sign clear.
*/
#define LL_TIMER_IE_DMA_FL_CLR (1UL << 9)
/*! Dma buffer half full sign clear.
*/
#define LL_TIMER_IE_DMA_HF_CLR (1UL << 8)
/*! The slave mode flag (reset or trigger only) clear.
*/
#define LL_TIMER_IE_SLAVE_CLR (1UL << 7)
/*! The CNT value is equal to the CMP value flag clear.
*/
#define LL_TIMER_IE_CMP_CLR (1UL << 6)
/*! The CNT value is equal to the PRD value flag clear.
*/
#define LL_TIMER_IE_PRD_CLR (1UL << 5)
/*! The CNT value overflow (16'hffff) flag is cleared.
*/
#define LL_TIMER_IE_OVF_CLR (1UL << 4)
/*! Capture event 1 occurs flag clear.
*/
#define LL_TIMER_IE_CAP1_CLR (1UL << 0)
/***** TIMERx CAP1/PR Register *****/
/*! Capture mode : capture register 1
* Timing mode/PWM mode: Count period register
*/
#define LL_TIMER_CMP1_PR(n) (((n)&0xFFFFFFFF) << 0)
/***** TIMERx CAP2/CMP Register *****/
/*! Capture mode : capture register 2
* Timing mode/PWM mode: compare register
*/
#define LL_TIMER_CMP2_CMP(n) (((n)&0xFFFFFFFF) << 0)
/***** TIMERx CAP3/PR_SD Register *****/
/*! Capture mode : capture register 3
* Timing mode/PWM mode: counting period shadow register
*/
#define LL_TIMER_CMP3_PR_SD(n) (((n)&0xFFFFFFFF) << 0)
/***** TIMERx CAP4/CMP_SD Register *****/
/*! Capture mode : capture register 4
* Timing mode/PWM mode: Compare shadow registers
*/
#define LL_TIMER_CMP4_CMP_SD(n) (((n)&0xFFFFFFFF) << 0)
/***** TIMERx DCCTL Register *****/
/*! Dma mode selection
* 0 : Single mode, after the specified dma length is completed, disable TMR.
* 1 : Loop mode, after the dma length is specified, restart from the start address.
*/
#define LL_TIMER_DMA_LPBK (1UL << 1)
/*! Dma enabled.
*/
#define LL_TIMER_DMA_EN (1UL << 0)
/***** TIMERx DADR Register *****/
/*! Dma starting address.
*/
#define LL_TIMER_DADR_STADR(n) (((n)&0xFFFF) << 0)
/***** TIMERx DLEN Register *****/
/*! Dma buffer length (32bit), if the buffer is n, the configuration is n-1;
*/
#define LL_TIMER_DLEN_LEN(n) (((n)&0xFFFF) << 0)
/***** TIMERx DCNT Register *****/
/*! The number of dma data is valid.
*/
#define LL_TIMER_DCNT_CNT(n) (((n)&0xFFFF) << 0)
/***** TIMER ALLCON Register *****/
/*! The timer3 sync count value is cleared.
*/
#define LL_TIMER_ALLCON_TMR3_SYNC (1UL << 11)
/*! The timer2 sync count value is cleared.
*/
#define LL_TIMER_ALLCON_TMR2_SYNC (1UL << 10)
/*! The timer1 sync count value is cleared.
*/
#define LL_TIMER_ALLCON_TMR1_SYNC (1UL << 9)
/*! The timer0 sync count value is cleared.
*/
#define LL_TIMER_ALLCON_TMR0_SYNC (1UL << 8)
/*! Timer3 starts counting.
*/
#define LL_TIMER_ALLCON_TMR3_KICK (1UL << 3)
/*! Timer2 starts counting.
*/
#define LL_TIMER_ALLCON_TMR2_KICK (1UL << 2)
/*! Timer1 starts counting.
*/
#define LL_TIMER_ALLCON_TMR1_KICK (1UL << 1)
/*! Timer0 starts counting.
*/
#define LL_TIMER_ALLCON_TMR0_KICK (1UL << 0)
/*! Configure the trigger path for the sync count of TIMER.
*/
#define LL_TIMER_ALLCON_SYNC_COUNT_ALL(n) (((n)&0x3F) << 8)
/*! Configure the synchronous trigger path of TIMER.
*/
#define LL_TIMER_ALLCON_KICK_ALL(n) (((n)&0x3F) << 0)
struct hgtimer_v4_hw {
__IO uint32_t TMR_CON;
__IO uint32_t TMR_EN;
__IO uint32_t TMR_IE;
__IO uint32_t TMR_CNT;
__IO uint32_t TMR_FLG;
__IO uint32_t TMR_CLR;
__IO uint32_t TMR_CAP1;
__IO uint32_t TMR_CAP2;
__IO uint32_t TMR_CAP3;
__IO uint32_t TMR_CAP4;
/* The following registers only for timer1 & timer2 */
__IO uint32_t TMR_DCTL;
__IO uint32_t TMR_DADR;
__IO uint32_t TMR_DLEN;
__IO uint32_t TMR_DCNT;
__IO uint32_t TMR_IR_BCNT;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGTIMER_V4_HW_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,96 @@
#ifndef _HGTIMER_V7_HW_H
#define _HGTIMER_V7_HW_H
#ifdef __cplusplus
extern "C" {
#endif
/***** SINPLE TIMERx CTL Register *****/
/*! Capture selection:
* 00 : GPIO
* 01 : GPIO OR
* 10 : compare0 output
* 11 : compare1 output
*/
#define LL_SIMPLE_TIMER_CAP_SEL(n) (((n)&0x3) << 16)
/*!Period break flag
*/
#define LL_SIMPLE_TIMER_PERIOD_ING (1UL << 15)
/*!Mark of capture
*/
#define LL_SIMPLE_TIMER_CAP_ING (1UL << 14)
/*!Periodic interrupt was enabled
*/
#define LL_SIMPLE_TIMER_PERIOD_IE (1UL << 13)
/*!Capture interrupt enable
*/
#define LL_SIMPLE_TIMER_CAP_IE (1UL << 12)
/*! Timer prescaler settings:
* 000 : 0 frequency division
* 001 : 2 frequency division
* 010 : 4 frequency division
* 011 : 8 frequency division
* 100 : 16 frequency division
* 101 : 32 frequency division
* 110 : 64 frequency division
* 111 : 128 frequency division
*/
#define LL_SIMPLE_TIMER_PSC(n) (((n)&0x7) << 8)
/*! Capture source edge selection
* 0x0: Capture occurs during rising edge
* 0x1: Capture occurs at falling edge
* 0x2: Capture occurs along both the rising and falling edges
* 0x3: Capture occurs along both the rising and falling edges
*/
#define LL_SIMPLE_TIMER_EDG_SCL(n) (((n)&0x3) << 6)
/*! simple timer mode select bits:
* 01 : timer counter mode
* 10 : timer pwm mode
* 11 : timer capture mode
* This bit of non-zero time counting is enabled
*/
#define LL_SIMPLE_TIMER_MODE_SEL(n) (((n)&0x3) << 4)
/*! Timer counter source select bits:
8 000 : Select GPIO (CAP PIN) as the clock source Select the rising edge as the count source;
* 001 : Select the GPIO (CAP PIN) as the clock source and the falling edge as the count source
* 010 : Select EXT_CLK_SRC1 as the clock source and the rising and falling edges as the count sources
* 011 : Select EXT_CLK_SRC0 as the clock source and the rising and falling edges as the count sources
* 100 : Select EXT_CLK_SRC2 as the clock source and the rising and falling edges as the count sources
* 111 : Select the overflow of the previous timer is selected as the count source. (withString multiple timers into one 64bit counter
* Others : system clock
*/
#define LL_SIMPLE_TIMER_INC_SRC_SEL(n) (((n)&0x7) << 0)
/***** SINPLE TIMERx CNT Register *****/
/*!Counter register
*/
#define LL_SIMPLE_TIMER_CNT(n) (((n)&0xFFFFFFFF) << 0)
/***** SINPLE TIMERx PERIOD Register *****/
/*!Period register
*/
#define LL_SIMPLE_TIMER_PERIOD(n) (((n)&0xFFFFFFFF) << 0)
/***** SINPLE TIMERx PERIOD Register *****/
/*!Comparison value register
*/
#define LL_SIMPLE_TIMER_PWM(n) (((n)&0xFFFFFFFF) << 0)
struct hgtimer_v7_hw {
__IO uint32_t TMR_CTL;
__IO uint32_t TMR_CNT;
__IO uint32_t TMR_PR;
__IO uint32_t TMR_PWM;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGTIMER_V7_HW_H */

1066
sdk/driver/uart/hguart_v2.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,250 @@
#ifndef _HGUART_V2_HW_H_
#define _HGUART_V2_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
/***** UARTCON *****/
/*! RX buffer trigger threshold
*/
#define LL_UART_CON_RBUF_TRIG(n) (((n)&0x03) << 18)
/*! Singal RTS_N enable
*/
#define LL_UART_CON_RTS_EN (1UL << 17)
/*! Singal CTS_N enable
*/
#define LL_UART_CON_CTS_EN (1UL << 16)
/*! Transmission complete interrupt enable
*/
#define LL_UART_CON_TCIE_EN (1UL << 15)
/*! UART with carrier output enable.
* @note UART0 outputs pwm of TIMER0, and UART1 outputs pwm of TIMER1.
*/
#define LL_UART_CON_TMR_PWM_EN (1UL << 14)
/*! Frame error interrupt enable
* @note A frame error refers to a low-level signal received by rx during
* the stop bit.
*/
#define LL_UART_CON_FERR_IE_EN (1UL << 11)
/*! TX buffer empty interrupt enable
*/
#define LL_UART_CON_TXBUF_EMPTY_IE_EN (1UL << 10)
/*! RX buffer not empty interrupt enable
*/
#define LL_UART_CON_RXBUF_NEMPTY_IE_EN (1UL << 9)
/*! Inverted TX signal
*/
#define LL_UART_CON_TX_INV_EN (1UL << 8)
/*! Inverted RX signal
*/
#define LL_UART_CON_RX_INV_EN (1UL << 7)
/*! Odd parity
* @note Parity and 9bit data transfer cannot be used at the same time.
*/
#define LL_UART_CON_ODD_EN (1UL << 6)
/*! parity enable
* @note Parity and 9bit data transfer cannot be used at the same time.
*/
#define LL_UART_CON_PARITY_EN (1UL << 5)
/*! 9bit data transfer enable
* @note Parity and 9bit data transfer cannot be used at the same time.
*/
#define LL_UART_CON_BIT9_EN (1UL << 4)
/*! Stop bit selection
*/
#define LL_UART_CON_STOP_BIT(n) (((n)&0x01) << 3)
/*! Work mode selection
*/
#define LL_UART_CON_WORK_MODE(n) (((n)&0x03) << 1)
/*! UART module enable
*/
#define LL_UART_CON_UART_EN (1UL << 0)
/***** UARTSTA *****/
/*! Transmission complete pending
*/
#define LL_UART_STA_TC_PENDING (1UL << 12)
/*! RX timeout detection pending
* @note Only UART0 has this feature.
*/
#define LL_UART_STA_TO_PEND (1UL << 11)
/*! RX parity error pending
* @note 4 bits corrspond to 4 frame data in rx buffer.
*/
#define LL_UART_STA_PERR_PEND(n) (((n)>>7) & 0x0F)
/*! The amount of data in the rx fifo
*/
#define LL_UART_STA_RX_CNT(n) (((n)>>4) & 0x07)
/*! Frame error pending
*/
#define LL_UART_STA_FERR_PENDING (1UL << 3)
/*! RX FIFO overflow pending
*/
#define LL_UART_STA_RX_BUF_OV (1UL << 2)
/*! RX FIFO not empty pending
*/
#define LL_UART_STA_RX_BUF_NOT_EMPTY (1UL << 1)
/*! TX FIFO empty pending
*/
#define LL_UART_STA_TX_BUF_EMPTY (1UL << 0)
/***** DMACON *****/
/*! RX DMA parity error interrupt enable
* @note Only UART1 has this feature
*/
#define LL_UART_DMACON_RX_DMA_PERR_IE_EN (1UL << 4)
/*! RX DMA interrupt enable
* @note Only UART1 has this feature
*/
#define LL_UART_DMACON_RX_DMA_IE_EN (1UL << 3)
/*! TX DMA interrupt enable
* @note Only UART1 has this feature
*/
#define LL_UART_DMACON_TX_DMA_IE_EN (1UL << 2)
/*! RX DMA enable
* @note Only UART1 has this feature
*/
#define LL_UART_DMACON_RX_DMA_EN (0x0101UL << 1)
/*! TX DMA enable
* @note Only UART1 has this feature
*/
#define LL_UART_DMACON_TX_DMA_EN (0x0101UL << 0)
/***** DMASTA *****/
/*! RX DMA parity error pending
* @note Only UART1 has this feature
*/
#define LL_UART_DMASTA_RX_DMA_PERR (1UL << 2)
/*! RX DMA pending
* @note Only UART1 has this feature
*/
#define LL_UART_DMASTA_RX_DMA_PEND (1UL << 1)
/*! TX DMA pending
* @note Only UART1 has this feature
*/
#define LL_UART_DMASTA_TX_DMA_PEND (1UL << 0)
/***** UART_RS485_CON *****/
/*! RS485 RE enable
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_CON_RE_EN (1UL << 9)
/*! RS485 DE enable
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_CON_DE_EN (1UL << 8)
/*! RS485 work mode
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_CON_RS485_MODE(n) (((n)&0x01) << 3)
/*! RS485 RE polarity
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_CON_RE_POL(n) (((n)&0x01) << 2)
/*! RS485 DE polarity
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_CON_DE_POL(n) (((n)&0x01) << 1)
/*! RS485 enable
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_CON_RS485_EN (1UL << 0)
/***** UART_RS485_DET *****/
/*! The time interval between the end of STOP BIT and DE invalid. The unit
* is the uart module clock.
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_DET_DE_DAT(n) (((n)&0x01FF) << 16)
/*! The time interval between the time DE is valid and the START BIT is sent.
* The unit is the uart module clock.
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_DET_DE_AT(n) (((n)&0x01FF) << 0)
/***** UART_RS485_TAT *****/
/*! The time interval between the valid of RE and DE valid, the unit is the
* uart module clock.
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_TAT_RE2DE_T(n) (((n)&0xFFFF) << 16)
/*! The time interval between DE valid and RE valid, the unit is the uart
* module clock.
* @note Only UART1 has this feature
*/
#define LL_UART_RS485_TAT_DE2RE_T(n) (((n)&0xFFFF) << 0)
/***** UART_TOCON *****/
/*! Timeout time configure
*/
#define LL_UART_TOCON_TO_BIT_LEN(n) (((n)&0xFFFF) << 16)
/*! Timeout interrupt enable
*/
#define LL_UART_TOCON_TO_IE_EN (1UL << 1)
/*! Timeout enable
*/
#define LL_UART_TOCON_TO_EN (1UL << 0)
typedef struct hguart_v2_hw {
__IO uint32_t CON;
__IO uint32_t BAUD;
__IO uint32_t DATA;
__IO uint32_t STA;
__IO uint32_t TSTADR;
__IO uint32_t RSTADR;
__IO uint32_t TDMALEN;
__IO uint32_t RDMALEN;
__IO uint32_t TDMACNT;
__IO uint32_t RDMACNT;
__IO uint32_t DMACON;
__IO uint32_t DMASTA;
__IO uint32_t RS485_CON;
__IO uint32_t RS485_DET;
__IO uint32_t RS485_TAT;
__IO uint32_t TOCON;
}UART_TypeDef;
/**
* @brief enable RS485 RE pin
* @param p_uart : The structure pointer of the UART
* @retval None
*/
__STATIC_INLINE void ll_uart485_re_enable(UART_TypeDef *p_uart) {
p_uart->RS485_CON |= LL_UART_RS485_CON_RE_EN;
}
/**
* @brief disable RS485 RE pin
* @param p_uart : The structure pointer of the UART
* @retval None
*/
__STATIC_INLINE void ll_uart485_re_disable(UART_TypeDef *p_uart) {
p_uart->RS485_CON &= (~LL_UART_RS485_CON_RE_EN);
}
/**
* @brief enable RS485 DE pin
* @param p_uart : The structure pointer of the UART
* @retval None
*/
__STATIC_INLINE void ll_uart485_de_enable(UART_TypeDef *p_uart) {
p_uart->RS485_CON |= LL_UART_RS485_CON_DE_EN;
}
/**
* @brief disable RS485 DE pin
* @param p_uart : The structure pointer of the UART
* @retval None
*/
__STATIC_INLINE void ll_uart485_de_disable(UART_TypeDef *p_uart) {
p_uart->RS485_CON &= (~LL_UART_RS485_CON_DE_EN);
}
#ifdef __cplusplus
}
#endif
#endif /* _HGUART_V2_HW_H_ */

726
sdk/driver/uart/hguart_v4.c Normal file
View File

@@ -0,0 +1,726 @@
/**
* @file hguart_v4.c
* @author bxd
* @brief simple uart
* @version
* TXW81X
* @date 2023-08-02
*
* @copyright Copyright (c) 2023
*
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "osal/irq.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/string.h"
#include "hal/uart.h"
#include "hal/gpio.h"
#include "dev/uart/hguart_v4.h"
#include "hguart_v4_hw.h"
#define SIMPLE_UART_LOCK(mutex, flag)\
do{\
if(flag){\
os_mutex_lock(mutex, osWaitForever);\
}\
}while(0);
#define SIMPLE_UART_UNLOCK(mutex, flag)\
do{\
if(flag){\
os_mutex_unlock(mutex);\
}\
}while(0);
/**********************************************************************************/
/* UART LOW LAYER FUNCTION */
/**********************************************************************************/
static int32 hguart_v4_set_dma(struct hguart_v4 *dev, uint32 enable)
{
if (enable) {
dev->use_dma = 1;
} else {
dev->use_dma = 0;
}
return RET_OK;
}
static int32 hguart_v4_dma_rx_config(struct hguart_v4_hw *p_uart, uint8 status)
{
uint32 _dmacon = p_uart->DMACON;
uint32 flag = 0;
if (status) {
_dmacon = 0x5;
} else {
_dmacon = 0;
}
/*!
* fix: kick 2 times to counteract an unnecessary rx dma done
*/
if (p_uart->CON & LL_SIMPLE_UART_CON_DMA_IE) {
p_uart->CON &=~ LL_SIMPLE_UART_CON_DMA_IE;
flag = 1;
//printf("<%x>", *(uint32 *)(0x40004b70));
}
p_uart->DMACON = _dmacon;
__NOP();__NOP();__NOP();__NOP();
//printf("<%x>", *(uint32 *)(0x40004b70));
//clear rx done pending
p_uart->CON |= LL_SIMPLE_UART_CON_CLRDMAPEND;
//kick again
p_uart->DMACON = _dmacon;
__NOP();__NOP();__NOP();__NOP();
//printf("<%x>", *(uint32 *)(0x40004b70));
//clear rx done pending
p_uart->CON |= LL_SIMPLE_UART_CON_CLRDMAPEND;
//printf("<%x>", *(uint32 *)(0x40004b70));
if (flag) {
flag = 0;
p_uart->CON |= LL_SIMPLE_UART_CON_DMA_IE;
}
return 0;
}
static int32 hguart_v4_dma_tx_config(struct hguart_v4_hw *p_uart, uint8 status)
{
uint32 _dmacon = p_uart->DMACON;
if (status) {
_dmacon = 0xA;
} else {
_dmacon = 0;
}
p_uart->DMACON = _dmacon;
return 0;
}
static int32 hguart_v4_set_time_out(struct hguart_v4_hw *p_uart, uint32 time_bit, uint32 enable)
{
if (enable) {
p_uart->CON |= LL_SIMPLE_UART_CON_TO_EN;
p_uart->TOCON = LL_SIMPLE_UART_TOCON(time_bit);
} else {
p_uart->CON &=~ LL_SIMPLE_UART_CON_TO_EN;
p_uart->TOCON = 0;
}
return RET_OK;
}
/**********************************************************************************/
/* UART ATTCH FUNCTION */
/**********************************************************************************/
static int32 hguart_v4_open(struct uart_device *uart, uint32 baudrate) {
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if (dev->opened) {
if (!dev->dsleep) {
return -EBUSY;
}
}
/* pin config */
if (pin_func(dev->dev.dev.dev_id , 1) != RET_OK) {
return RET_ERR;
}
/* reg config */
hw->BAUD = (peripheral_clock_get(HG_APB0_PT_UART4) / baudrate) - 1;
hw->CON = LL_SIMPLE_UART_CON_UARTEN;
dev->opened = 1;
dev->irq_dma_rx = 0;
dev->irq_dma_tx = 0;
dev->use_dma = 0;
dev->dsleep = 0;
return RET_OK;
}
static int32 hguart_v4_close(struct uart_device *uart) {
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if (!dev->opened) {
return RET_OK;
}
irq_disable(dev->irq_num );
pin_func(dev->dev.dev.dev_id, 0);
hw->CON &= ~ LL_SIMPLE_UART_CON_UARTEN;
dev->opened = 0;
dev->irq_dma_rx = 0;
dev->irq_dma_tx = 0;
dev->use_dma = 0;
dev->dsleep = 0;
return RET_OK;
}
static int32 hguart_v4_putc(struct uart_device *uart, int8 value) {
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
SIMPLE_UART_LOCK(&dev->mutex_tx, dev->debug_uart);
if (dev->opened && (hw->CON & LL_SIMPLE_UART_CON_UARTEN)) {
while(!(hw->CON & LL_SIMPLE_UART_CON_TXBUFEMPTY));
hw->DATA = value;
SIMPLE_UART_UNLOCK(&dev->mutex_tx, dev->debug_uart);
return RET_OK;
} else {
SIMPLE_UART_UNLOCK(&dev->mutex_tx, dev->debug_uart);
return -EIO;
}
}
static uint8 hguart_v4_getc(struct uart_device *uart) {
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
SIMPLE_UART_LOCK(&dev->mutex_rx, dev->debug_uart);
while(!(hw->CON & LL_SIMPLE_UART_CON_RXBUFNOTEMPTY));
hw->CON |= LL_SIMPLE_UART_CON_CLRRXDONE;
SIMPLE_UART_UNLOCK(&dev->mutex_rx, dev->debug_uart);
return hw->DATA;
}
static int32 hguart_v4_rs485_de_set(void)
{
if(PIN_UART4_DE != 255) {
gpio_set_val(PIN_UART4_DE, 1);
return RET_OK;
}
if(PIN_UART5_DE != 255) {
gpio_set_val(PIN_UART5_DE, 1);
return RET_OK;
}
return RET_ERR;
}
static int32 hguart_v4_rs485_de_reset(void)
{
if(PIN_UART4_DE != 255) {
gpio_set_val(PIN_UART4_DE, 0);
return RET_OK;
}
if(PIN_UART5_DE != 255) {
gpio_set_val(PIN_UART5_DE, 0);
return RET_OK;
}
return RET_ERR;
}
static int32 hguart_v4_rs485_re_set(void)
{
if(PIN_UART4_RE != 255) {
gpio_set_val(PIN_UART4_RE, 1);
return RET_OK;
}
if(PIN_UART5_RE != 255) {
gpio_set_val(PIN_UART5_RE, 1);
return RET_OK;
}
return RET_ERR;
}
static int32 hguart_v4_rs485_re_reset(void)
{
if(PIN_UART4_RE != 255) {
gpio_set_val(PIN_UART4_RE, 0);
return RET_OK;
}
if(PIN_UART5_RE != 255) {
gpio_set_val(PIN_UART5_RE, 0);
return RET_OK;
}
return RET_ERR;
}
static int32 hguart_v4_puts(struct uart_device *uart, uint8 *buf, uint32 size) {
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
uint32 i = 0;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
SIMPLE_UART_LOCK(&dev->mutex_tx, dev->debug_uart);
if (dev->use_dma) {
if (dev->debug_uart) {
//enable uart 1Byte tx done irq
hw->CON |= LL_SIMPLE_UART_CON_UARTTXIE;
dev->p_tx_buf = (uint8 *)buf;
dev->tx_total_byte = size;
dev->tx_cur_byte = 0;
//send 1Byte to trigger 1Byte tx done irq
hw->DATA = buf[0];
os_sema_down(&dev->sema_tx, osWaitForever);
//disable uart 1Byte tx done irq
hw->CON &=~ LL_SIMPLE_UART_CON_UARTTXIE;
} else if (dev->rs485_set) {
hguart_v4_dma_tx_config(hw, 0);
hw->CON |= LL_SIMPLE_UART_CON_CLRDMAPEND;
hguart_v4_rs485_de_set();
hguart_v4_rs485_re_set();
hw->DMAADR = (uint32)buf;
hw->DMALEN = size;
hguart_v4_dma_tx_config(hw, 1);
/* waiting for tx done */
while (!(hw->CON & LL_SIMPLE_UART_CON_DMAPEND));
hguart_v4_rs485_re_reset();
hguart_v4_rs485_de_reset();
} else {
for (i = 0; i < size; i++) {
hguart_v4_putc(uart, buf[i]);
}
}
} else {
for (i = 0; i < size; i++) {
hguart_v4_putc(uart, buf[i]);
}
}
SIMPLE_UART_UNLOCK(&dev->mutex_tx, dev->debug_uart);
return RET_OK;
}
static int32 hguart_v4_gets(struct uart_device *uart, uint8 *buf, uint32 size) {
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
uint32 i = 0;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
SIMPLE_UART_LOCK(&dev->mutex_rx, dev->debug_uart);
if (dev->use_dma) {
hw->DMAADR = (uint32)buf;
hw->DMALEN = size;
hguart_v4_dma_rx_config(hw, 1);
} else {
for (i = 0; i < size; i++) {
hguart_v4_getc(uart);
}
}
SIMPLE_UART_UNLOCK(&dev->mutex_rx, dev->debug_uart);
return i;
}
static int32 hguart_v4_ioctl(struct uart_device *uart, enum uart_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2) {
int32 ret_val = RET_OK;
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
switch (ioctl_cmd) {
case (UART_IOCTL_CMD_USE_DMA):
ret_val = hguart_v4_set_dma(dev, param1);
break;
case (UART_IOCTL_CMD_SET_TIME_OUT):
ret_val = hguart_v4_set_time_out((struct hguart_v4_hw *)dev->hw, param1, param2);
break;
case (UART_IOCTL_CMD_DISABLE_DEBUG_SELECTION):
dev->debug_uart = (param1) ? (1) : (0);
ret_val = RET_OK;
break;
case (UART_IOCTL_CMD_SET_RS485_EN):
dev->rs485_set = (param1) ? (1) : (0);
ret_val = RET_OK;
break;
default:
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
/* interrupt handler */
static void hguart_v4_irq_handler(void *data) {
struct hguart_v4 *dev = (struct hguart_v4 *)data;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if ((hw->CON & LL_SIMPLE_UART_CON_UARTTXIE) && (hw->CON & LL_SIMPLE_UART_CON_TXDONE)) {
hw->CON |= LL_SIMPLE_UART_CON_CLRTXDONE;
dev->tx_cur_byte++;
//printf("cur len:%d\r\n", dev->tx_cur_byte);
if (dev->tx_cur_byte == dev->tx_total_byte) {
//printf("up\r\n");
os_sema_up(&dev->sema_tx);
//diable uart tx 1byte done irq
hw->CON &=~ LL_SIMPLE_UART_CON_UARTTXIE;
} else {
hw->DATA = dev->p_tx_buf[dev->tx_cur_byte];
}
}
if ((hw->CON & LL_SIMPLE_UART_CON_UARTRXIE) && (hw->CON & LL_SIMPLE_UART_CON_RXBUFNOTEMPTY)) {
hw->CON |= LL_SIMPLE_UART_CON_CLRRXDONE;
if (dev->irq_hdl) {
dev->irq_hdl(UART_IRQ_FLAG_RX_BYTE, dev->irq_data, hw->DATA, 0);
}
}
if ((hw->CON & LL_SIMPLE_UART_CON_FERRIE) && (hw->CON & LL_SIMPLE_UART_CON_FERR)) {
hw->CON |= LL_SIMPLE_UART_CON_CLRFERR;
if (dev->irq_hdl) {
dev->irq_hdl(UART_IRQ_FLAG_FRAME_ERR, dev->irq_data, 0, 0);
}
}
//UART4/5 TIMEOUT来了之后DMA DONE也会起来故DMA DONE中断之前要判断是否TIMEOUT
if (!(hw->CON & LL_SIMPLE_UART_CON_TO_PENDING)) {
if ((hw->CON & LL_SIMPLE_UART_CON_DMA_IE) && (hw->CON & LL_SIMPLE_UART_CON_DMAPEND)) {
hw->CON |= LL_SIMPLE_UART_CON_CLRDMAPEND;
if (dev->irq_hdl) {
if (dev->irq_dma_rx) {
dev->irq_hdl(UART_IRQ_FLAG_DMA_RX_DONE, dev->irq_data, hw->DMACNT, 0);
} else {
dev->irq_hdl(UART_IRQ_FLAG_DMA_TX_DONE, dev->irq_data, hw->DMACNT, 0);
}
}
}
} else {
if ((hw->CON & LL_SIMPLE_UART_CON_TO_IE) && (hw->CON & LL_SIMPLE_UART_CON_TO_PENDING)) {
hw->CON |= (LL_SIMPLE_UART_CON_CLRTOPEND | LL_SIMPLE_UART_CON_CLRDMAPEND);
if (dev->irq_hdl) {
dev->irq_hdl(UART_IRQ_FLAG_TIME_OUT, dev->irq_data, hw->DMACNT, 0);
}
}
}
}
/* request interrupt */
static int32 hguart_v4_request_irq(struct uart_device *uart, uart_irq_hdl irqhdl, uint32 irq_flag, uint32 data) {
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
dev->irq_hdl = irqhdl;
dev->irq_data = data ;
if (irq_flag & UART_IRQ_FLAG_RX_BYTE) {
hw->CON |= LL_SIMPLE_UART_CON_UARTRXIE;
}
if (irq_flag & UART_IRQ_FLAG_FRAME_ERR) {
hw->CON |= LL_SIMPLE_UART_CON_FERRIE;
}
if (irq_flag & UART_IRQ_FLAG_DMA_RX_DONE) {
hw->CON |= LL_SIMPLE_UART_CON_DMA_IE;
dev->irq_dma_tx = 0;
dev->irq_dma_rx = 1;
}
if (irq_flag & UART_IRQ_FLAG_DMA_TX_DONE) {
hw->CON |= LL_SIMPLE_UART_CON_DMA_IE;
dev->irq_dma_tx = 1;
dev->irq_dma_rx = 0;
}
if (irq_flag & UART_IRQ_FLAG_TIME_OUT) {
hw->CON |= LL_SIMPLE_UART_CON_TO_IE;
}
#if defined(TXW81X)
irq_enable(dev->comm_irq_num);
#elif defined(TXW82X)
irq_enable(dev->irq_num);
#endif
return RET_OK;
}
static int32 hguart_v4_release_irq(struct uart_device *uart, uint32 irq_flag) {
struct hguart_v4 *dev = (struct hguart_v4 *)uart;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if ((!dev->opened) || (dev->dsleep)) {
return RET_ERR;
}
if (irq_flag & UART_IRQ_FLAG_RX_BYTE) {
hw->CON &= ~ LL_SIMPLE_UART_CON_UARTRXIE;
}
if (irq_flag & UART_IRQ_FLAG_FRAME_ERR) {
hw->CON &= ~ LL_SIMPLE_UART_CON_FERRIE;
}
if (irq_flag & UART_IRQ_FLAG_DMA_RX_DONE) {
hw->CON &=~ LL_SIMPLE_UART_CON_DMA_IE;
}
if (irq_flag & UART_IRQ_FLAG_TIME_OUT) {
hw->CON &=~ LL_SIMPLE_UART_CON_TO_IE;
}
#if defined(TXW81X)
irq_disable(dev->comm_irq_num);
#elif defined(TXW82X)
irq_disable(dev->irq_num);
#endif
return RET_OK;
}
#ifdef CONFIG_SLEEP
int32 hguart_v4_suspend(struct dev_obj *obj)
{
struct hguart_v4 *dev = (struct hguart_v4 *)obj;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if (!dev->opened) {
return RET_OK;
}
if (0 > os_mutex_lock(&dev->bp_suspend_lock, 10000)) {
return RET_ERR;
}
/*!
* Close the UART
*/
hw->CON &= ~ BIT(4);
// pin_func(dev->dev.dev.dev_id, 0);
#if defined(TXW81X)
irq_disable(dev->comm_irq_num);
#elif defined(TXW82X)
irq_disable(dev->irq_num);
#endif
/*
* clear pending
*/
hw->CON |= 0x3f000000;
os_memset((void *)&dev->bp_regs, 0, sizeof(dev->bp_regs));
/*
* save the reglist
*/
dev->bp_regs.con = hw->CON;
dev->bp_regs.baud = hw->BAUD;
dev->bp_regs.tocon = hw->TOCON;
dev->bp_regs.dmaadr = hw->DMAADR;
dev->bp_regs.dmalen = hw->DMALEN;
dev->bp_regs.dmacon = hw->DMACON;
/*
* save the irq_hdl created by user
*/
dev->bp_irq_hdl = dev->irq_hdl;
dev->bp_irq_data = dev->irq_data;
//venus v2uart4&5 clk and uart0 clk are share the same source
if (UART4_BASE == (uint32)hw) {
// sysctrl_uart4_clk_close();
} else if (UART5_BASE == (uint32)hw) {
// sysctrl_uart5_clk_close();
}
dev->dsleep = 1;
os_mutex_unlock(&dev->bp_suspend_lock);
return RET_OK;
}
int32 hguart_v4_resume(struct dev_obj *obj)
{
struct hguart_v4 *dev = (struct hguart_v4 *)obj;
struct hguart_v4_hw *hw = (struct hguart_v4_hw *)dev->hw;
if (!dev->opened) {
return RET_OK;
}
if (0 > os_mutex_lock(&dev->bp_resume_lock, 10000)) {
return RET_ERR;
}
/* pin config */
// if (pin_func(dev->dev.dev.dev_id, 1) != RET_OK) {
// return RET_ERR;
// }
/*
* recovery the UART clk
*/
if (UART4_BASE == (uint32)hw) {
// sysctrl_uart4_clk_open();
} else if (UART5_BASE == (uint32)hw) {
// sysctrl_uart5_clk_open();
}
/*
* recovery the reglist from sram
*/
hw->CON = dev->bp_regs.con;
hw->BAUD = dev->bp_regs.baud;
hw->TOCON = dev->bp_regs.tocon;
hw->DMAADR = dev->bp_regs.dmaadr;
hw->DMALEN = dev->bp_regs.dmalen;
hw->DMACON = dev->bp_regs.dmacon;
/*
* recovery the irq handle and data
*/
dev->irq_hdl = dev->bp_irq_hdl;
dev->irq_data = dev->bp_irq_data;
os_memset((void *)&dev->bp_regs, 0, sizeof(dev->bp_regs));
/*!
* Open the UART
*/
hw->CON |= BIT(4);
if (hw->DMACON & 1) {
hguart_v4_dma_rx_config(hw, 1);
}
#if defined(TXW81X)
irq_enable(dev->comm_irq_num);
#elif defined(TXW82X)
irq_enable(dev->irq_num);
#endif
dev->dsleep = 0;
os_mutex_unlock(&dev->bp_resume_lock);
return RET_OK;
}
#endif
static const struct uart_hal_ops uart_v4_ops = {
.open = hguart_v4_open,
.close = hguart_v4_close,
.getc = hguart_v4_getc,
.putc = hguart_v4_putc,
.gets = hguart_v4_gets,
.puts = hguart_v4_puts,
.ioctl = hguart_v4_ioctl,
.request_irq = hguart_v4_request_irq,
.release_irq = hguart_v4_release_irq,
#ifdef CONFIG_SLEEP
.ops.suspend = hguart_v4_suspend,
.ops.resume = hguart_v4_resume,
#endif
};
int32 hguart_v4_attach(uint32 dev_id, struct hguart_v4 *uart) {
uart->irq_data = 0;
uart->irq_hdl = NULL;
uart->opened = 0;
uart->irq_dma_rx = 0;
uart->irq_dma_tx = 0;
uart->use_dma = 0;
uart->debug_uart = 0;
uart->rs485_set = 0;
uart->dsleep = 0;
uart->p_tx_buf = NULL;
uart->tx_cur_byte = 0;
uart->tx_total_byte = 0;
uart->dev.dev.ops = (const struct devobj_ops *)&uart_v4_ops;
os_sema_init(&uart->sema_tx, 0);
os_mutex_init(&uart->mutex_rx);
os_mutex_init(&uart->mutex_tx);
#ifdef CONFIG_SLEEP
os_mutex_init(&uart->bp_suspend_lock);
os_mutex_init(&uart->bp_resume_lock);
#endif
request_irq(uart->irq_num, hguart_v4_irq_handler, uart);
dev_register(dev_id, (struct dev_obj *)uart);
return RET_OK;
}

View File

@@ -0,0 +1,164 @@
#ifndef _HGUART_V4_HW_H_
#define _HGUART_V4_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
/***** UARTCON *****/
/*! Timeout interrupt en
*/
#define LL_SIMPLE_UART_CON_TO_IE (1UL << 31)
/*! Timeout function en
*/
#define LL_SIMPLE_UART_CON_TO_EN (1UL << 30)
/*! Timeout pending
*/
#define LL_SIMPLE_UART_CON_CLRTOPEND (1UL << 29)
/*! Transmission completed The 1byte flag was cleared to zero
*/
#define LL_SIMPLE_UART_CON_CLRTXDONE (1UL << 28)
/*! The frame receiving error detection flag is cleared to zero
*/
#define LL_SIMPLE_UART_CON_CLRFERR (1UL << 27)
/*! The receive cache register is not null flag cleared
*/
#define LL_SIMPLE_UART_CON_CLRRXDONE (1UL << 26)
/*! DMA interrupt flag cleared to zero
*/
#define LL_SIMPLE_UART_CON_CLRDMAPEND (1UL << 25)
/*! Receive address interrupt flag cleared to zero
*/
#define LL_SIMPLE_UART_CON_CLRRXADDRPEND (1UL << 24)
/*! Transmission completed 1byte flag. This bit is 0 when the module is disabled
*/
#define LL_SIMPLE_UART_CON_TXDONE (1UL << 21)
/*! Frame receiving error detection flag
*/
#define LL_SIMPLE_UART_CON_FERR (1UL << 20)
/*! Receive cache register is not empty flag, this bit is 0 when the module is not enabled
*/
#define LL_SIMPLE_UART_CON_RXBUFNOTEMPTY (1UL << 19)
/*! The send cache register is an empty flag. This bit is 0 when the module is disabled
*/
#define LL_SIMPLE_UART_CON_TXBUFEMPTY (1UL << 18)
/*! The DMA completion flag bit, which is set to 1 when a send or receive is complete using DMA
*/
#define LL_SIMPLE_UART_CON_DMAPEND (1UL << 17)
/*! Receive address interrupt flag RXADDRPEND
*/
#define LL_SIMPLE_UART_CON_RXADDRPEND (1UL << 16)
/*! RX_TIMEOUT PENDING
*/
#define LL_SIMPLE_UART_CON_TO_PENDING (1UL << 15)
/*! Select UART output with which PWM carrier:
*/
#define LL_SIMPLE_UART_CON_CARRIER_SEL(n) (((n)&0x09) << 11)
/*! Set the CARRIER_SEL bit to the PWM carrier mode enable bit. Specify the carrier_sel bit for the specific PWM carrier of the TIMER
*/
#define LL_SIMPLE_UART_CON_PWM_CARRIER_EN (1UL << 10)
/*! The receiving address was interrupted. Procedure
*/
#define LL_SIMPLE_UART_CON_RXADDRIE (1UL << 9)
/*! Error detection interrupt enabled
*/
#define LL_SIMPLE_UART_CON_FERRIE (1UL << 8)
/*! DMA interrupt enabled
*/
#define LL_SIMPLE_UART_CON_DMA_IE (1UL << 7)
/*! Stop bit setting
*/
#define LL_SIMPLE_UART_CON_STOPBIT (1UL << 6)
/*! The 9bit function was enabled
*/
#define LL_SIMPLE_UART_CON_BIT9EN (1UL << 5)
/*! The Uart function was enabled
*/
#define LL_SIMPLE_UART_CON_UARTEN (1UL << 4)
/*! Send data inversely
*/
#define LL_SIMPLE_UART_CON_TXINV (1UL << 3)
/*! The received data is reversed
*/
#define LL_SIMPLE_UART_CON_RXINV (1UL << 2)
/*! Send 1byte to enable the interrupt
*/
#define LL_SIMPLE_UART_CON_UARTTXIE (1UL << 1)
/*! The receiving interrupt function was enabled
*/
#define LL_SIMPLE_UART_CON_UARTRXIE (1UL << 0)
/***** UARTBAUD *****/
/*! Baud rate setting
*/
#define LL_SIMPLE_UART_UARTBAUD(n) (((n)&0x0003FFFF) << 0)
/***** UARTDATA *****/
/*! Data register
*/
#define LL_SIMPLE_UART_UARTDATA(n) (((n)&0x000000FF) << 0)
/***** UARTTOCON *****/
/*! TOCON register
*/
#define LL_SIMPLE_UART_TOCON(n) (((n)&0x0000FFFF) << 0)
/***** UARTDMAADR *****/
/*! DMAADR register
*/
#define LL_SIMPLE_UART_UARTDMAADR(n) (((n)&0xFFFFFFFF) << 0)
/***** UARTDMALEN *****/
/*! DMALEN register
*/
#define LL_SIMPLE_UART_UARTDMALEN(n) (((n)&0x000007FF) << 0)
/***** UARTDMACON *****/
/*!DMACON register
*/
#define LL_SIMPLE_UART_UART_TX_USEDMA_KEY (1UL << 3)
#define LL_SIMPLE_UART_UART_RX_USEDMA_KEY (1UL << 2)
#define LL_SIMPLE_UART_UART_TX_USEDMA (1UL << 1)
#define LL_SIMPLE_UART_UART_RX_USEDMA (1UL << 0)
/**
* @brief Simple Universal Synchronous Asynchronous Receiver Transmitter
*/
struct hguart_v4_hw{
__IO uint32_t CON;
__IO uint32_t BAUD;
__IO uint32_t DATA;
__IO uint32_t TOCON;
__IO uint32_t DMAADR;
__IO uint32_t DMALEN;
__IO uint32_t DMACON;
__IO uint32_t DMACNT;
};
#ifdef __cplusplus
}
#endif
#endif /* _HGUART_V4_HW_H_ */

838
sdk/driver/vpp/hgvpp_v3.c Normal file
View File

@@ -0,0 +1,838 @@
#include "typesdef.h"
#include "errno.h"
#include "osal/irq.h"
#include "devid.h"
#include "dev/vpp/hgvpp.h"
#include "osal/string.h"
struct hgvpp_hw
{
__IO uint32_t CON;
__IO uint32_t CON1;
__IO uint32_t SIZE;
__IO uint32_t DLT;
__IO uint32_t DHT;
__IO uint32_t STA;
__IO uint32_t DMA_YADR;
__IO uint32_t DMA_UADR;
__IO uint32_t DMA_VADR;
__IO uint32_t DMA_YADR1;
__IO uint32_t DMA_UADR1;
__IO uint32_t DMA_VADR1;
__IO uint32_t IWM0_CON;
__IO uint32_t IWM0_CON1;
__IO uint32_t IWM0_SIZE;
__IO uint32_t IWM0_YUV;
__IO uint32_t IWM0_YUV1;
__IO uint32_t IWM0_LADR;
__IO uint32_t IWM0_HADR;
__IO uint32_t IWM0_IDX0;
__IO uint32_t IWM0_IDX1;
__IO uint32_t IWM0_IDX2;
__IO uint32_t IWM1_CON;
__IO uint32_t IWM1_SIZE;
__IO uint32_t IWM1_YUV;
__IO uint32_t IWM1_LADR;
__IO uint32_t IPF_SADR;
__IO uint32_t MD_CON;
__IO uint32_t MD_WIN_CON0;
__IO uint32_t MD_WIN_CON1;
__IO uint32_t MD_BASE_ADDR;
__IO uint32_t ITP_PSRAM_YADR;
__IO uint32_t ITP_PSRAM_UADR;
__IO uint32_t ITP_PSRAM_VADR;
__IO uint32_t FRM_PSRAM_YCNT;
__IO uint32_t FRM_PSRAM_UVCNT;
__IO uint32_t FRM1_PSRAM_YCNT;
__IO uint32_t FRM1_PSRAM_UVCNT;
};
vpp_irq_hdl vppirq_vector_table[VPP_IRQ_NUM];
volatile uint32 vppirq_dev_table[VPP_IRQ_NUM];
extern volatile uint8 isp_ov_err;
static int32 hgvpp_ioctl(struct vpp_device *p_vpp, enum vpp_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2)
{
int32 ret_val = RET_OK;
uint32 w,h,num;
uint32 x_s,y_s,x_e,y_e;
//uint32 *size_array;
struct hgvpp *vpp_hw = (struct hgvpp*)p_vpp;
struct hgvpp_hw *hw = (struct hgvpp_hw *)vpp_hw->hw;
switch(ioctl_cmd){
case VPP_IOCTL_CMD_ITP_AUTO_CLOSE:
if(param1)
hw->CON &= ~BIT(30);
else
hw->CON |= BIT(30);
break;
case VPP_IOCTL_CMD_ITP_Y_ADDR:
hw->ITP_PSRAM_YADR = param1;
break;
case VPP_IOCTL_CMD_ITP_U_ADDR:
hw->ITP_PSRAM_UADR = param1;
break;
case VPP_IOCTL_CMD_ITP_V_ADDR:
hw->ITP_PSRAM_VADR = param1;
break;
case VPP_IOCTL_CMD_ITP_EN:
if(param1)
hw->CON |= BIT(29);
else
hw->CON &= ~BIT(29);
break;
case VPP_IOCTL_CMD_SET_TAKE_PHOTO_LINEBUF:
if(param1 < 8){
hw->CON1 &= ~(0x7<<10);
hw->CON1 |= (param1<<10);
}
break;
case VPP_IOCTL_CMD_DIS_UV_MODE:
if(param1)
hw->CON |= BIT(4);
else
hw->CON &= ~BIT(4);
if(param2){
hw->CON1 |= BIT(5);
}else{
hw->CON1 &= ~BIT(5);
}
break;
case VPP_IOCTL_CMD_SET_THRESHOLD:
hw->DLT = param1;
hw->DHT = param2;
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_RC:
if(param1)
hw->IWM0_CON |= BIT(5);
else
hw->IWM0_CON &= ~BIT(5);
break;
case VPP_IOCTL_CMD_SET_WATERMARK1_RC:
if(param1)
hw->IWM1_CON |= BIT(5);
else
hw->IWM1_CON &= ~BIT(5);
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_COLOR:
hw->IWM0_YUV = param1;
break;
case VPP_IOCTL_CMD_SET_WATERMARK1_COLOR:
hw->IWM1_YUV = param1;
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_BMPADR:
hw->IWM0_LADR = param1;
break;
case VPP_IOCTL_CMD_SET_WATERMARK1_BMPADR:
hw->IWM1_LADR = param1;
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_LOCATED:
hw->IWM0_CON &= ~(0x1ff<<15);
hw->IWM0_CON &= ~(0xff<<24);
hw->IWM0_CON |= (((param1&0Xff00)>>8)<<24);
hw->IWM0_CON |= ((param1&0Xff)<<15);
break;
case VPP_IOCTL_CMD_SET_WATERMARK1_LOCATED:
hw->IWM1_CON &= ~(0xff<<16);
hw->IWM1_CON &= ~(0xff<<24);
hw->IWM1_CON |= (((param1&0Xff00)>>8)<<24);
hw->IWM1_CON |= ((param1&0Xff)<<16);
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_CONTRAST:
hw->IWM0_CON &= ~(0x7<<2);
hw->IWM0_CON |= (param1<<2);
break;
case VPP_IOCTL_CMD_SET_WATERMARK1_CONTRAST:
hw->IWM1_CON &= ~(0x7<<2);
hw->IWM1_CON |= (param1<<2);
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_CHAR_SIZE_AND_NUM:
w = param1&0xff;
h = ((param1&0xff00)>>8)&0xff;
num = param2&0xff;
hw->IWM0_SIZE &= ~(0x1f<<0);
hw->IWM0_SIZE |= (num<<0);
hw->IWM0_SIZE &= ~(0x3f<<5);
hw->IWM0_SIZE |= (w<<5);
hw->IWM0_SIZE &= ~(0x3ff<<12);
hw->IWM0_SIZE |= ((w*num)<<12);
hw->IWM0_SIZE &= ~(0xff<<23);
hw->IWM0_SIZE |= (h<<23);
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_CHAR_IDX:
if(param2 > 23)
return ret_val;
if(param2 < 8){
hw->IWM0_IDX0 &= ~(0xf<<(param2*4));
hw->IWM0_IDX0 |= (param1<<(param2*4));
}
else if(param2 < 16){
hw->IWM0_IDX1 &= ~(0xf<<((param2-8)*4));
hw->IWM0_IDX1 |= (param1<<((param2-8)*4));
}else{
hw->IWM0_IDX2 &= ~(0xf<<((param2-16)*4));
hw->IWM0_IDX2 |= (param1<<((param2-16)*4));
}
break;
case VPP_IOCTL_CMD_SET_WATERMARK1_PHOTO_SIZE:
w = param1&0xff;
h = ((param1&0xff00)>>8)&0xff;
hw->IWM1_SIZE &= ~(0xff<<12);
hw->IWM1_SIZE |= (w<<12);
hw->IWM1_SIZE &= ~(0xff<<23);
hw->IWM1_SIZE |= (h<<23);
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_MODE:
if(param1)
hw->IWM0_CON |= BIT(1);
else
hw->IWM0_CON &= ~BIT(1);
break;
case VPP_IOCTL_CMD_SET_WATERMARK1_MODE:
if(param1)
hw->IWM1_CON |= BIT(1);
else
hw->IWM1_CON &= ~BIT(1);
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_EN:
if(param1)
hw->IWM0_CON |= BIT(0);
else
hw->IWM0_CON &= ~BIT(0);
break;
case VPP_IOCTL_CMD_SET_WATERMARK1_EN:
if(param1)
hw->IWM1_CON |= BIT(0);
else
hw->IWM1_CON &= ~BIT(0);
break;
case VPP_IOCTL_CMD_SET_MOTION_DET_EN:
if(param1){
//hw->MD_CON &= ~(0x1f<<18);
//hw->MD_CON |= (BIT(23));
hw->MD_CON |= BIT(0);
}
else{
hw->MD_CON &= ~BIT(0);
}
break;
case VPP_IOCTL_CMD_SET_MOTION_ALL_FRAME_OR_WINDOW:
if(param1 == 0){
hw->MD_CON |= (BIT(26));
}
else{
hw->MD_CON &= ~BIT(26);
}
break;
case VPP_IOCTL_CMD_SET_MOTION_CALBUF:
hw->MD_BASE_ADDR = param1;
break;
case VPP_IOCTL_CMD_SET_MOTION_RANGE:
x_s = param1&0xfff;
y_s = ((param1&0xfff0000)>>16)&0xfff;
x_e = param2&0xfff;
y_e = ((param2&0xfff0000)>>16)&0xfff;
//hw->MD_WIN_CON0 = param1;
//hw->MD_WIN_CON1 = param1;
hw->MD_WIN_CON0 = (x_s | (y_s<<16));
hw->MD_WIN_CON1 = ((x_e-1) | ((y_e-1)<<16));
break;
case VPP_IOCTL_CMD_SET_MOTION_BLK_THRESHOLD:
param1 = param1&0xff;
hw->MD_CON &= ~(0xff<<1);
hw->MD_CON |= (param1<<1);
break;
case VPP_IOCTL_CMD_SET_MOTION_FRAME_THRESHOLD:
param1 = param1&0xfff;
hw->MD_CON &= ~(0xfff<<9);
hw->MD_CON |= (param1<<9);
break;
case VPP_IOCTL_CMD_SET_MOTION_FRAME_INTERVAL:
param1 = param1&0x1f;
hw->MD_CON &= ~(0x1f<<21);
hw->MD_CON |= (param1<<21);
break;
case VPP_IOCTL_CMD_SET_IFP_ADDR:
hw->IPF_SADR = param1;
break;
case VPP_IOCTL_CMD_SET_IFP_EN:
if(param1){
hw->CON |= BIT(28);
}
else{
hw->CON &= ~BIT(28);
}
break;
case VPP_IOCTL_CMD_SET_MODE:
if(param1){
hw->CON |= BIT(1);
//os_printf("vpp input raw or rgb888\r\n");
}
else{
hw->CON &= ~BIT(1);
//os_printf("vpp input YUV422\r\n");
}
break;
case VPP_IOCTL_CMD_SET_SIZE:
w = param1;
h = param2;
if(w%16 != 0){
os_printf("###############################warning image_w no align 16 Byte##################################################\r\n");
}
if(h%8 != 0){
os_printf("###############################warning image_h no align 8 Byte##################################################\r\n");
}
hw->SIZE = (h<<12) | (w<<0);
break;
case VPP_IOCTL_CMD_SET_YCBCR:
if(param1 > 3){
os_printf("set ycbcr error:%d\r\n",param1);
}
hw->CON &= ~(BIT(2)|BIT(3));
hw->CON |= param1<<2;
break;
case VPP_IOCTL_CMD_BUF0_CNT:
if(param1 > 16){
os_printf("set buf0 error:%d\r\n",param1);
}
hw->CON &= ~(0x0f<<9);
hw->CON |= (param1<<9);
break;
case VPP_IOCTL_CMD_BUF1_CNT:
if(param1 > 16){
os_printf("set buf1 error:%d\r\n",param1);
}
hw->CON1 &= ~(0x0f<<6);
hw->CON1 |= (param1<<6);
break;
case VPP_IOCTL_CMD_BUF0_EN:
if(param1)
hw->CON |= BIT(8);
else
hw->CON &= ~BIT(8);
break;
case VPP_IOCTL_CMD_BUF1_EN:
if(param1)
hw->CON1 |= BIT(1);
else
hw->CON1 &= ~BIT(1);
break;
case VPP_IOCTL_CMD_FTUSB3_EN:
if(param1)
hw->CON1 |= BIT(0);
else
hw->CON1 &= ~BIT(0);
break;
case VPP_IOCTL_CMD_BUF1_SHRINK:
hw->CON1 &= ~(0x07<<2);
hw->CON1 |= (param1<<2); //0: 1/2
//1: 1/3
//2: 1/4
//3: 1/6
//4: 2/3
//5: 1/1
break;
case VPP_IOCTL_CMD_INPUT_INTERFACE:
hw->CON &= ~(0x07<<5);
hw->CON |= (param1<<5);
break;
case VPP_IOCTL_CMD_BUF0_Y_ADDR:
hw->DMA_YADR = param1;
break;
case VPP_IOCTL_CMD_BUF0_U_ADDR:
hw->DMA_UADR = param1;
break;
case VPP_IOCTL_CMD_BUF0_V_ADDR:
hw->DMA_VADR = param1;
break;
case VPP_IOCTL_CMD_BUF1_Y_ADDR:
hw->DMA_YADR1 = param1;
break;
case VPP_IOCTL_CMD_BUF1_U_ADDR:
hw->DMA_UADR1 = param1;
break;
case VPP_IOCTL_CMD_BUF1_V_ADDR:
hw->DMA_VADR1 = param1;
break;
// case VPP_IOCTL_CMD_ISP_CONFIG:
// hw->CON = 0;
// hw->CON |= 0x3 << 20;
// hw->CON |= 0x3 << 5;
// hw->CON |= 0x1 << 1;
// hw->CON1 |= 0x1 << 0;
// hw->CON |= BIT(0);
// break;
case VPP_IOCTL_CMD_GET_STA:
ret_val = hw->STA;
break;
case VPP_IOCTL_CMD_PSRAM_YCNT:
w = param1;
h = param2;
hw->FRM_PSRAM_YCNT = (w*h)/4 -1;
break;
case VPP_IOCTL_CMD_PSRAM_UVCNT:
w = param1;
h = param2;
hw->FRM_PSRAM_UVCNT = (w*h)/16 -1;
break;
case VPP_IOCTL_CMD_PSRAM1_YCNT:
w = param1;
h = param2;
hw->FRM1_PSRAM_YCNT = (w*h)/4 -1;
break;
case VPP_IOCTL_CMD_PSRAM1_UVCNT:
w = param1;
h = param2;
hw->FRM1_PSRAM_UVCNT = (w*h)/16 -1;
break;
case VPP_IOCTL_CMD_FRAME_SAVE_NO_SRAM:
hw->CON1 &= ~(3<<13);
if(param1 == 1){
hw->CON1 |= (1<<13);
}else if(param1 == 2){
hw->CON1 |= (2<<13);
}
break;
case VPP_IOCTL_CMD_F1_SAVE_NO_SRAM:
if(param1 == 1){ //frame1 save
hw->CON1 |= BIT(15); //enable
}else{
hw->CON1 &= ~BIT(15); //disable
}
break;
case VPP_IOCTL_CMD_GET_F0_IS_PSRAM:
if((hw->CON1 & (3<<13)) == (1<<13)){
ret_val = 1;
}else{
ret_val = 0;
}
break;
case VPP_IOCTL_CMD_GET_F1_IS_PSRAM:
if((hw->CON1 & (3<<13)) == (2<<13)){
ret_val = 1;
}else if((hw->CON1 & BIT(15)) == BIT(15)){
ret_val = 1;
}else{
ret_val = 0;
}
break;
case VPP_IOCTL_CMD_GET_F0_IS_ENABLE:
if(hw->CON&BIT(8)){
ret_val = 1;
}else{
ret_val = 0;
}
break;
case VPP_IOCTL_CMD_GET_F1_IS_ENABLE:
if(hw->CON1&BIT(1)){
ret_val = 1;
}else{
ret_val = 0;
}
break;
case VPP_IOCTL_CMD_GET_F1_MODE:
if(hw->CON1&BIT(17)){
ret_val = 1; //2N mode
}else{
ret_val = 0; //16+2n mode
}
break;
case VPP_IOCTL_CMD_GET_F1_SHRINK:
ret_val = (hw->CON1&0x07)>>2;
break;
case VPP_IOCTL_CMD_SRAMBUFF_CNT_MODE:
if(param1 == 1){ //VPP BUF0
hw->CON1 |= BIT(16); //2N
}else{
hw->CON1 &= ~BIT(16); //16+2N
}
if(param2 == 1){ //VPP BUF1
hw->CON1 |= BIT(17); //2N
}else{
hw->CON1 &= ~BIT(17); //16+2N
}
break;
case VPP_IOCTL_CMD_SCALEBUF_SELECT:
if(param1 == 1){ //SCALE1
hw->CON1 |= BIT(18); //BUF 1
}else{
hw->CON1 &= ~BIT(18); //BUF 0
}
if(param2 == 1){ //SCALE3
hw->CON1 |= BIT(19); //BUF 1
}else{
hw->CON1 &= ~BIT(19); //BUF 0
}
break;
case VPP_IOCTL_CMD_GET_SCALE1BUF_SELECT:
if(hw->CON1&BIT(18)){
ret_val = 1; //<2F>õ<EFBFBD><C3B5><EFBFBD>buf1
}else{
ret_val = 0; //<2F>õ<EFBFBD><C3B5><EFBFBD>buf0
}
break;
case VPP_IOCTL_CMD_GET_SCALE3BUF_SELECT:
if(hw->CON1&BIT(19)){
ret_val = 1; //<2F>õ<EFBFBD><C3B5><EFBFBD>buf1
}else{
ret_val = 0; //<2F>õ<EFBFBD><C3B5><EFBFBD>buf0
}
break;
case VPP_IOCTL_CMD_GEN420_BUF_SEL:
if(param1 == 0){
hw->CON1 &= ~BIT(20); //BUF 0
}else{
hw->CON1 |= BIT(20); //BUF 1
}
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_AUTO_RC_THRESHOLD:
hw->IWM0_CON1 = 0;
hw->IWM0_CON1 = param1/8;
hw->IWM0_CON1 |= (param2/8)<<18;
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_AUTO_RC_COLOR:
if(param1)
hw->IWM0_CON |= BIT(6);
else
hw->IWM0_CON &= ~BIT(6);
hw->IWM0_YUV1 = param2;
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_AUTO_RC_HADR:
hw->IWM0_HADR = param1; //sram for moudle cal threshold
break;
case VPP_IOCTL_CMD_SET_WATERMARK0_AUTO_RC_MODE:
if(param1)
hw->IWM0_CON |= BIT(7);
else
hw->IWM0_CON &= ~BIT(7);
break;
case VPP_IOCTL_CMD_IS_CLOSED:
ret_val = vpp_hw->opened?0:1;
break;
default:
os_printf("NO VPP IOCTL:%d\r\n",ioctl_cmd);
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
void VPP_IRQHandler_action(void *p_vpp)
{
uint32 jpgr = 0;
uint32 sta = 0;
uint8 loop;
struct hgvpp *vpp_hw = (struct hgvpp*)p_vpp;
struct hgvpp_hw *hw = (struct hgvpp_hw *)vpp_hw->hw;
jpgr = *(volatile uint32_t*)0x40005200; //fix jpg reg error bug,imp
sta = hw->STA;
for(loop = 0;loop < VPP_IRQ_NUM;loop++){
if(sta&BIT(loop)){
hw->STA = BIT(loop);
if(loop == IPF_OV_ISR){
isp_ov_err = 1;
}
if(isp_ov_err){
if(loop == FRAME_DONE_ISR){
os_printf("isp ov,vpp drop\r\n");
isp_ov_err = 0;
}
}else{
if(loop == FRAME_DONE_ISR){
isp_ov_err = 0;
}
if(vppirq_vector_table[loop] != NULL)
vppirq_vector_table[loop] (loop,vppirq_dev_table[loop],0);
}
}
}
}
void irq_vpp_enable(struct vpp_device *p_vpp,uint8 mode,uint8 irq){
struct hgvpp *vpp_hw = (struct hgvpp*)p_vpp;
struct hgvpp_hw *hw = (struct hgvpp_hw *)vpp_hw->hw;
if(mode){
hw->CON |= BIT(irq+19);
}else{
hw->CON &= ~BIT(irq+19);
}
}
int32 vppirq_register(struct vpp_device *p_vpp,uint32 irq, vpp_irq_hdl isr, uint32 dev_id){
struct hgvpp *vpp_hw = (struct hgvpp*)p_vpp;
struct hgvpp_hw *hw = (struct hgvpp_hw *)vpp_hw->hw;
request_irq(vpp_hw->irq_num, VPP_IRQHandler_action, p_vpp);
irq_vpp_enable(p_vpp, 1, irq);
vppirq_vector_table[irq] = isr;
vppirq_dev_table[irq] = dev_id;
hw->STA |= BIT(irq);
os_printf("vppirq_register:%d %x %x\r\n",irq,(uint32)vppirq_vector_table[irq],(uint32)isr);
return 0;
}
int32 vppirq_unregister(struct vpp_device *p_vpp,uint32 irq){
struct hgvpp *vpp_hw = (struct hgvpp*)p_vpp;
struct hgvpp_hw *hw = (struct hgvpp_hw *)vpp_hw->hw;
irq_vpp_enable(p_vpp, 0, irq);
vppirq_vector_table[irq] = NULL;
vppirq_dev_table[irq] = 0;
hw->STA |= BIT(irq);
return 0;
}
static int32 hgvpp_open(struct vpp_device *p_vpp){
struct hgvpp *vpp_hw = (struct hgvpp*)p_vpp;
struct hgvpp_hw *hw = (struct hgvpp_hw *)vpp_hw->hw;
vpp_hw->opened = 1;
hw->CON |= BIT(0);
irq_enable(vpp_hw->irq_num);
return 0;
}
static int32 hgvpp_close(struct vpp_device *p_vpp){
struct hgvpp *vpp_hw = (struct hgvpp*)p_vpp;
struct hgvpp_hw *hw = (struct hgvpp_hw *)vpp_hw->hw;
vpp_hw->opened = 0;
hw->CON &= ~BIT(0);
irq_disable(vpp_hw->irq_num);
return 0;
}
int32 hgvpp_suspend(struct dev_obj *obj){
struct hgvpp *vpp_hw = (struct hgvpp*)obj;
struct hgvpp_hw *hw;
struct hgvpp_hw *hw_cfg;
//确保已经被打开并且休眠过,直接返回
if(!vpp_hw->opened || vpp_hw->dsleep)
{
return RET_OK;
}
vpp_hw->dsleep = 1;
vpp_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgvpp_hw));
hw_cfg = (struct hgvpp_hw*)vpp_hw->cfg_backup;
hw = (struct hgvpp_hw*)vpp_hw->hw;
hw_cfg->CON = hw->CON;
hw_cfg->CON1 = hw->CON1;
hw_cfg->SIZE = hw->SIZE;
hw_cfg->DLT = hw->DLT;
hw_cfg->DHT = hw->DHT;
hw_cfg->STA = hw->STA;
hw_cfg->DMA_YADR = hw->DMA_YADR;
hw_cfg->DMA_UADR = hw->DMA_UADR;
hw_cfg->DMA_VADR = hw->DMA_VADR;
hw_cfg->DMA_YADR1 = hw->DMA_YADR1;
hw_cfg->DMA_UADR1 = hw->DMA_UADR1;
hw_cfg->DMA_VADR1 = hw->DMA_VADR1;
hw_cfg->IWM0_CON = hw->IWM0_CON;
hw_cfg->IWM0_CON1 = hw->IWM0_CON1;
hw_cfg->IWM0_SIZE = hw->IWM0_SIZE;
hw_cfg->IWM0_YUV = hw->IWM0_YUV;
hw_cfg->IWM0_YUV1 = hw->IWM0_YUV1;
hw_cfg->IWM0_LADR = hw->IWM0_LADR;
hw_cfg->IWM0_HADR = hw->IWM0_HADR;
hw_cfg->IWM0_IDX0 = hw->IWM0_IDX0;
hw_cfg->IWM0_IDX1 = hw->IWM0_IDX1;
hw_cfg->IWM0_IDX2 = hw->IWM0_IDX2;
hw_cfg->IWM1_CON = hw->IWM1_CON;
hw_cfg->IWM1_SIZE = hw->IWM1_SIZE;
hw_cfg->IWM1_YUV = hw->IWM1_YUV;
hw_cfg->IWM1_LADR = hw->IWM1_LADR;
hw_cfg->IPF_SADR = hw->IPF_SADR;
hw_cfg->MD_CON = hw->MD_CON;
hw_cfg->MD_WIN_CON0 = hw->MD_WIN_CON0;
hw_cfg->MD_WIN_CON1 = hw->MD_WIN_CON1;
hw_cfg->MD_BASE_ADDR = hw->MD_BASE_ADDR;
hw_cfg->ITP_PSRAM_YADR = hw->ITP_PSRAM_YADR;
hw_cfg->ITP_PSRAM_UADR = hw->ITP_PSRAM_UADR;
hw_cfg->ITP_PSRAM_VADR = hw->ITP_PSRAM_VADR;
hw_cfg->FRM_PSRAM_YCNT = hw->FRM_PSRAM_YCNT;
hw_cfg->FRM_PSRAM_UVCNT = hw->FRM_PSRAM_UVCNT;
hw_cfg->FRM1_PSRAM_YCNT = hw->FRM1_PSRAM_YCNT;
hw_cfg->FRM1_PSRAM_UVCNT = hw->FRM1_PSRAM_UVCNT;
irq_disable(vpp_hw->irq_num);
return 0;
}
int32 hgvpp_resume(struct dev_obj *obj){
struct hgvpp *vpp_hw = (struct hgvpp*)obj;
struct hgvpp_hw *hw;
struct hgvpp_hw *hw_cfg;
//如果已经被打开并且没有休眠过,直接返回
if(!vpp_hw->opened || !vpp_hw->dsleep)
{
return RET_OK;
}
vpp_hw->dsleep = 0;
hw_cfg = (struct hgvpp_hw*)vpp_hw->cfg_backup;
hw = (struct hgvpp_hw*)vpp_hw->hw;
hw->CON = hw_cfg->CON;
hw->CON1 = hw_cfg->CON1;
hw->SIZE = hw_cfg->SIZE;
hw->DLT = hw_cfg->DLT;
hw->DHT = hw_cfg->DHT;
hw->STA = hw_cfg->STA;
hw->DMA_YADR = hw_cfg->DMA_YADR;
hw->DMA_UADR = hw_cfg->DMA_UADR;
hw->DMA_VADR = hw_cfg->DMA_VADR;
hw->DMA_YADR1 = hw_cfg->DMA_YADR1;
hw->DMA_UADR1 = hw_cfg->DMA_UADR1;
hw->DMA_VADR1 = hw_cfg->DMA_VADR1;
hw->IWM0_CON = hw_cfg->IWM0_CON;
hw->IWM0_CON1 = hw_cfg->IWM0_CON1;
hw->IWM0_SIZE = hw_cfg->IWM0_SIZE;
hw->IWM0_YUV = hw_cfg->IWM0_YUV;
hw->IWM0_YUV1 = hw_cfg->IWM0_YUV1;
hw->IWM0_LADR = hw_cfg->IWM0_LADR;
hw->IWM0_HADR = hw_cfg->IWM0_HADR;
hw->IWM0_IDX0 = hw_cfg->IWM0_IDX0;
hw->IWM0_IDX1 = hw_cfg->IWM0_IDX1;
hw->IWM0_IDX2 = hw_cfg->IWM0_IDX2;
hw->IWM1_CON = hw_cfg->IWM1_CON;
hw->IWM1_SIZE = hw_cfg->IWM1_SIZE;
hw->IWM1_YUV = hw_cfg->IWM1_YUV;
hw->IWM1_LADR = hw_cfg->IWM1_LADR;
hw->IPF_SADR = hw_cfg->IPF_SADR;
hw->MD_CON = hw_cfg->MD_CON;
hw->MD_WIN_CON0 = hw_cfg->MD_WIN_CON0;
hw->MD_WIN_CON1 = hw_cfg->MD_WIN_CON1;
hw->MD_BASE_ADDR = hw_cfg->MD_BASE_ADDR;
hw->ITP_PSRAM_YADR = hw_cfg->ITP_PSRAM_YADR;
hw->ITP_PSRAM_UADR = hw_cfg->ITP_PSRAM_UADR;
hw->ITP_PSRAM_VADR = hw_cfg->ITP_PSRAM_VADR;
hw->FRM_PSRAM_YCNT = hw_cfg->FRM_PSRAM_YCNT;
hw->FRM_PSRAM_UVCNT = hw_cfg->FRM_PSRAM_UVCNT;
hw->FRM1_PSRAM_YCNT = hw_cfg->FRM1_PSRAM_YCNT;
hw->FRM1_PSRAM_UVCNT = hw_cfg->FRM1_PSRAM_UVCNT;
irq_enable(vpp_hw->irq_num);
os_free(vpp_hw->cfg_backup);
return 0;
}
static const struct vpp_hal_ops dev_ops = {
.open = hgvpp_open,
.close = hgvpp_close,
.ioctl = hgvpp_ioctl,
.request_irq = vppirq_register,
.release_irq = vppirq_unregister,
#ifdef CONFIG_SLEEP
.ops.suspend = hgvpp_suspend,
.ops.resume = hgvpp_resume,
#endif
};
int32 hgvpp_attach(uint32 dev_id, struct hgvpp *vpp){
vpp->opened = 0;
vpp->use_dma = 0;
vpp->irq_hdl = NULL;
//memset(dvp->irq_hdl,0,sizeof(dvp->irq_hdl));
vpp->irq_data = 0;
//memset(dvp->irq_data,0,sizeof(dvp->irq_data));
vpp->dev.dev.ops = (const struct devobj_ops *)&dev_ops;
irq_disable(vpp->irq_num);
dev_register(dev_id, (struct dev_obj *)vpp);
return 0;
}