Introduce a port for T-HEAD CK802. A simple demo for T-HEAD CB2201 is also included.

This commit is contained in:
Yuhui.Zheng 2020-01-10 07:53:14 +00:00
parent d2914041f8
commit 0d95aca202
125 changed files with 23809 additions and 0 deletions

View file

@ -0,0 +1,9 @@
source "../../csi/csi_driver/csky/common/Kconfig"
if CONFIG_PLATFORM_PHOBOS
source "../../csi/csi_driver/csky/phobos/Kconfig"
endif
if CONFIG_PLATFORM_HOBBIT1_2
source "../../csi/csi_driver/csky/hobbit1_2/Kconfig"
endif

View file

@ -0,0 +1 @@
v1.0

View file

@ -0,0 +1,525 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_aes.c
* @brief CSI Source File for aes driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <string.h>
#include "csi_core.h"
#include "drv_aes.h"
#include "ck_aes.h"
#define ERR_AES(errno) (CSI_DRV_ERRNO_AES_BASE | errno)
#define AES_NULL_PARA_CHK(para) \
do { \
if (para == NULL) { \
return ERR_AES(EDRV_PARAMETER); \
} \
} while (0)
static ck_aes_reg_t *aes_reg = NULL;
volatile static uint8_t block_cal_done = 0;
typedef struct {
uint32_t base;
uint32_t irq;
void *iv;
uint8_t *result_out;
uint32_t len;
aes_event_cb_t cb;
aes_mode_e mode;
aes_key_len_bits_e keylen;
aes_endian_mode_e endian;
aes_crypto_mode_e enc;
aes_status_t status;
} ck_aes_priv_t;
extern int32_t target_get_aes_count(void);
extern int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq);
static ck_aes_priv_t aes_handle[CONFIG_AES_NUM];
/* Driver Capabilities */
static const aes_capabilities_t driver_capabilities = {
.ecb_mode = 1, /* ECB mode */
.cbc_mode = 1, /* CBC mode */
.cfb_mode = 0, /* CFB mode */
.ofb_mode = 0, /* OFB mode */
.ctr_mode = 0, /* CTR mode */
.bits_128 = 1, /* 128bits key length mode */
.bits_192 = 1, /* 192bits key lenght mode */
.bits_256 = 1 /* 256bits key length mode */
};
extern int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq);
extern int32_t target_get_aes_count(void);
//
// Functions
//
static inline void aes_set_opcode(aes_crypto_mode_e opcode)
{
aes_reg->ctrl &= ~(3 << AES_OPCODE_OFFSET); //clear bit[7:6]
aes_reg->ctrl |= (opcode << AES_OPCODE_OFFSET); //set opcode
}
static inline void aes_set_endian(aes_endian_mode_e endian)
{
if (endian == AES_ENDIAN_LITTLE) {
aes_reg->ctrl &= ~AES_LITTLE_ENDIAN;
} else {
aes_reg->ctrl |= AES_LITTLE_ENDIAN;
}
}
static inline uint32_t aes_set_keylen(aes_key_len_bits_e keylength)
{
aes_reg->ctrl &= ~(3 << AES_KEY_LEN_OFFSET); //clear bit[5:4]
aes_reg->ctrl |= (keylength << AES_KEY_LEN_OFFSET);// Set key length
return 0;
}
static inline void aes_set_mode(aes_mode_e mode)
{
aes_reg->ctrl &= ~(1 << AES_MODE_OFFSET); //clear bit 3
aes_reg->ctrl |= (mode << AES_MODE_OFFSET); //set mode
}
static inline void aes_enable(void)
{
aes_reg->ctrl |= (1 << AES_WORK_ENABLE_OFFSET);
}
static inline void aes_disable(void)
{
aes_reg->ctrl &= ~(1 << AES_WORK_ENABLE_OFFSET);
}
static inline void aes_enable_interrupt(void)
{
aes_reg->ctrl |= (1 << AES_INT_ENABLE_OFFSET);
}
static inline void aes_disable_interrupt(void)
{
aes_reg->ctrl &= ~(1 << AES_INT_ENABLE_OFFSET);
}
static inline void aes_clear_interrupt(void)
{
aes_reg->state = 0x0;
}
static inline uint32_t aes_get_intstatus(uint32_t AES_IT)
{
return (aes_reg->state & AES_IT) ? 1 : 0;
}
static void aes_set_key(void *context, uint8_t *key, aes_key_len_bits_e keylen, uint32_t enc, uint32_t endian)
{
uint8_t keynum = 0;
if (keylen == AES_KEY_LEN_BITS_128) {
keynum = 4;
} else if (keylen == AES_KEY_LEN_BITS_192) {
keynum = 6;
} else if (keylen == AES_KEY_LEN_BITS_256) {
keynum = 8;
}
uint32_t i;
uint32_t temp = 0;
/* set key according to the endian mode */
if (endian == AES_ENDIAN_LITTLE) {
for (i = 0; i < keynum; i++) {
temp = key[3] << 24 | key[2] << 16 | key[1] << 8 | key[0];
aes_reg->key[keynum - 1 - i] = temp;
key += 4;
}
} else if (endian == AES_ENDIAN_BIG) {
for (i = 0; i < keynum; i++) {
temp = key[3] << 24 | key[2] << 16 | key[1] << 8 | key[0];
aes_reg->key[i] = temp;
key += 4;
}
}
if (enc == AES_CRYPTO_MODE_DECRYPT) {
aes_set_opcode(AES_CRYPTO_KEYEXP); /* if the mode is decrypt before decrypt you have to keyexpand */
aes_enable();
// while(block_cal_done == 0);
// block_cal_done = 0;
while (aes_get_intstatus(AES_IT_KEYINT));
aes_set_opcode(AES_CRYPTO_MODE_DECRYPT);
} else if (enc == AES_CRYPTO_MODE_ENCRYPT) {
aes_set_opcode(AES_CRYPTO_MODE_ENCRYPT);
}
aes_disable();
}
static void aes_set_iv(uint32_t mode, uint32_t endian, uint8_t *iv)
{
uint32_t temp;
uint32_t i;
/* set iv if the mode is CBC */
if (mode == AES_MODE_CBC) {
if (endian == AES_ENDIAN_BIG) {
for (i = 0; i < 4; i++) {
temp = iv[3] << 24 | iv[2] << 16 | iv[1] << 8 | iv[0];
aes_reg->iv[i] = temp;
iv += 4;
}
} else if (endian == AES_ENDIAN_LITTLE) {
for (i = 0; i < 4; i++) {
temp = iv[3] << 24 | iv[2] << 16 | iv[1] << 8 | iv[0];
aes_reg->iv[3 - i] = temp;
iv += 4;
}
}
}
}
static int aes_crypto(void *context, uint8_t *in, uint8_t *out,
uint32_t len, uint8_t *iv, uint32_t mode, uint32_t endian, uint32_t enc)
{
uint32_t temp[4];
aes_set_iv(mode, endian, iv);
uint32_t i = 0;
uint32_t j = 0;
/* set the text before aes calculating */
for (i = 0; i < len; i = i + 16) {
for (j = 0; j < 4; j++) {
temp[j] = in[3] << 24 | in[2] << 16 | in[1] << 8 | in[0];
if (endian == AES_ENDIAN_BIG) {
aes_reg->datain[j] = temp[j];
} else if (endian == AES_ENDIAN_LITTLE) {
aes_reg->datain[3 - j] = temp[j];
}
in += 4;
}
aes_enable();
while(block_cal_done == 0);
block_cal_done = 0;
if (enc == AES_CRYPTO_MODE_ENCRYPT && mode == AES_MODE_CBC) {
aes_set_iv(mode, endian, out);
memcpy(iv, out, 16);
out += 16;
} else if (enc == AES_CRYPTO_MODE_DECRYPT && mode == AES_MODE_CBC) {
aes_set_iv(mode, endian, (uint8_t *)&temp);
memcpy(iv, temp, 16);
}
}
return 0;
}
void ck_aes_irqhandler(int32_t idx)
{
ck_aes_priv_t *aes_priv = &aes_handle[idx];
volatile uint32_t j;
uint32_t tmp = 0;
/* get the result after aes calculating*/
if (aes_priv->result_out != NULL) {
for (j = 0; j < 4; j++) {
if (aes_priv->endian == AES_ENDIAN_BIG) {
tmp = aes_reg->dataout[j];
} else if (aes_priv->endian == AES_ENDIAN_LITTLE) {
tmp = aes_reg->dataout[3 - j];
}
memcpy(aes_priv->result_out, &tmp, 4);
aes_priv->result_out += 4;
aes_priv->len -= 4;
}
}
block_cal_done = 1;
/* disable aes and clear the aes interrupt */
aes_disable();
aes_clear_interrupt();
/* execute the callback function */
if (aes_priv->len == 0) {
if (aes_priv->cb) {
aes_priv->cb(AES_EVENT_CRYPTO_COMPLETE);
}
}
}
/**
\brief get aes instance count.
\return aes handle count
*/
int32_t csi_aes_get_instance_count(void)
{
return target_get_aes_count();
}
/**
\brief Initialize AES Interface. 1. Initializes the resources needed for the AES interface 2.registers event callback function
\param[in] idx must not exceed return value of csi_aes_get_instance_count().
\param[in] cb_event Pointer to \ref aes_event_cb_t
\return return aes handle if success
*/
aes_handle_t csi_aes_initialize(int32_t idx, aes_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_AES_NUM) {
return NULL;
}
uint32_t irq = 0u;
uint32_t base = 0u;
/* obtain the aes information */
int32_t real_idx = target_get_aes(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_aes_priv_t *aes_priv = &aes_handle[idx];
aes_priv->base = base;
aes_priv->irq = irq;
/* initialize the aes context */
aes_reg = (ck_aes_reg_t *)(aes_priv->base);
aes_priv->cb = cb_event;
aes_priv->iv = NULL;
aes_priv->len = 16;
aes_priv->result_out = NULL;
aes_priv->mode = AES_MODE_CBC;
aes_priv->keylen = AES_KEY_LEN_BITS_128;
aes_priv->endian = AES_ENDIAN_LITTLE;
aes_priv->status.busy = 0;
aes_enable_interrupt(); /* enable the aes interrupt */
drv_nvic_enable_irq(aes_priv->irq); /* enable the aes bit in nvic */
return (aes_handle_t)aes_priv;
}
/**
\brief De-initialize AES Interface. stops operation and releases the software resources used by the interface
\param[in] handle aes handle to operate.
\return error code
*/
int32_t csi_aes_uninitialize(aes_handle_t handle)
{
AES_NULL_PARA_CHK(handle);
ck_aes_priv_t *aes_priv = handle;
aes_priv->cb = NULL;
aes_disable_interrupt(); /* disable the aes interrupt */
drv_nvic_disable_irq(aes_priv->irq);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] handle aes handle to operate.
\return \ref aes_capabilities_t
*/
aes_capabilities_t csi_aes_get_capabilities(aes_handle_t handle)
{
return driver_capabilities;
}
/**
\brief config aes mode.
\param[in] handle aes handle to operate.
\param[in] mode \ref aes_mode_e
\param[in] keylen_bits \ref aes_key_len_bits_e
\param[in] endian \ref aes_endian_mode_e
\param[in] arg Pointer to the iv address when mode is cbc_mode
\return error code
*/
int32_t csi_aes_config(aes_handle_t handle, aes_mode_e mode, aes_key_len_bits_e keylen_bits, aes_endian_mode_e endian, uint32_t arg)
{
AES_NULL_PARA_CHK(handle);
ck_aes_priv_t *aes_priv = handle;
aes_reg = (ck_aes_reg_t *)(aes_priv->base);
/* config the aes mode */
switch (mode) {
case AES_MODE_CBC:
aes_priv->iv = (void *)arg;
aes_priv->mode = mode;
aes_set_mode(mode);
break;
case AES_MODE_ECB:
aes_priv->mode = mode;
aes_set_mode(mode);
break;
case AES_MODE_CFB:
case AES_MODE_OFB:
case AES_MODE_CTR:
return ERR_AES(EDRV_UNSUPPORTED);
default:
return ERR_AES(EDRV_PARAMETER);
}
/* config the key length */
switch (keylen_bits) {
case AES_KEY_LEN_BITS_128:
case AES_KEY_LEN_BITS_192:
case AES_KEY_LEN_BITS_256:
aes_priv->keylen = keylen_bits;
aes_set_keylen(keylen_bits);
break;
default:
return ERR_AES(EDRV_PARAMETER);
}
/* config the endian mode */
switch (endian) {
case AES_ENDIAN_LITTLE:
aes_priv->endian = endian;
aes_set_endian(endian);
break;
case AES_ENDIAN_BIG:
aes_priv->endian = endian;
aes_set_endian(endian);
break;
default:
return ERR_AES(EDRV_PARAMETER);
}
return 0;
}
/**
\brief set crypto key.
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] key Pointer to the key buf
\param[in] key_len Pointer to the aes_key_len_bits_e
\param[in] enc \ref aes_crypto_mode_e
\return error code
*/
int32_t csi_aes_set_key(aes_handle_t handle, void *context, void *key, aes_key_len_bits_e key_len, aes_crypto_mode_e enc)
{
AES_NULL_PARA_CHK(handle);
AES_NULL_PARA_CHK(key);
if ((key_len != AES_KEY_LEN_BITS_128 &&
key_len != AES_KEY_LEN_BITS_192 &&
key_len != AES_KEY_LEN_BITS_256) ||
(enc != AES_CRYPTO_MODE_ENCRYPT &&
enc != AES_CRYPTO_MODE_DECRYPT)) {
return ERR_AES(EDRV_PARAMETER);
}
ck_aes_priv_t *aes_priv = handle;
aes_priv->enc = enc;
aes_set_key(context, key, key_len, enc, aes_priv->endian);
return 0;
}
/**
\brief encrypt or decrypt
\param[in] handle aes handle to operate.
\param[in] context aes information context(NULL when hardware implementation)
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data.
\param[in] len the Source data len.
\param[in] padding \ref aes_padding_mode_e.
\return error code
*/
int32_t csi_aes_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, aes_padding_mode_e padding)
{
AES_NULL_PARA_CHK(handle);
AES_NULL_PARA_CHK(in);
AES_NULL_PARA_CHK(out);
AES_NULL_PARA_CHK(len);
ck_aes_priv_t *aes_priv = handle;
aes_priv->status.busy = 1;
uint8_t left_len = len & 0xf;
switch (padding) {
case AES_PADDING_MODE_NO:
if (left_len) {
return ERR_AES(EDRV_PARAMETER);
}
/* crypto in padding no mode */
aes_priv->result_out = out;
aes_priv->len = len;
aes_crypto(context, in, out, len, aes_priv->iv, aes_priv->mode, aes_priv->endian, aes_priv->enc);
break;
case AES_PADDING_MODE_ZERO:
if (left_len == 0) {
return ERR_AES(EDRV_PARAMETER);
}
uint8_t i = 0;
for (i = 0; i < (16 - left_len); i++) {
*((uint8_t *)in + len + i) = 0x0;
}
/* crypto in padding zero mode */
aes_priv->result_out = out;
aes_priv->len = len + 16 -left_len;
aes_crypto(context, in, out, len + 16 - left_len, aes_priv->iv, aes_priv->mode, aes_priv->endian, aes_priv->enc);
break;
case AES_PADDING_MODE_PKCS5:
return ERR_AES(EDRV_UNSUPPORTED);
default:
return ERR_AES(EDRV_PARAMETER);
}
aes_priv->status.busy = 0;
return 0;
}
/**
\brief Get AES status.
\param[in] handle aes handle to operate.
\return AES status \ref aes_status_t
*/
aes_status_t csi_aes_get_status(aes_handle_t handle)
{
ck_aes_priv_t *aes_priv = handle;
return aes_priv->status;
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_aes.h
* @brief header file for aes driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_AES_H_
#define _CK_AES_H_
#include <stdio.h>
#include "drv_aes.h"
#include "soc.h"
#define AES_LITTLE_ENDIAN 0x00000100
#define AES_MAX_KEY_LENGTH 32
#define AES_IT_DATAINT 0x4
#define AES_IT_KEYINT 0x2
#define AES_IT_BUSY 0x1
#define AES_IT_ALL 0x7
#define AES_CRYPTO_KEYEXP 0x2
#define AES_WORK_ENABLE_OFFSET 0
#define AES_INT_ENABLE_OFFSET 2
#define AES_MODE_OFFSET 3
#define AES_KEY_LEN_OFFSET 4
#define AES_OPCODE_OFFSET 6
typedef struct {
__IOM uint32_t datain[4]; /* Offset: 0x000 (R/W) Data input 0~127 */
__IOM uint32_t key[8]; /* Offset: 0x010 (R/W) Key 0~255 */
__IOM uint32_t iv[4]; /* Offset: 0x030 (R/W) Initial Vector: 0~127 */
__IOM uint32_t ctrl; /* Offset: 0x040 (R/W) AES Control Register */
__IOM uint32_t state; /* Offset: 0x044 (R/W) AES State Register */
__IOM uint32_t dataout[4]; /* Offset: 0x048 (R/W) Data Output 0~31 */
} ck_aes_reg_t;
#endif

View file

@ -0,0 +1,52 @@
ifeq ($(CONFIG_SHA), y)
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/common/sha/
ifeq ($(CONFIG_PLATFORM_PHOBOS), y)
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/sha/ck_sha_v2.c
endif
ifeq ($(CONFIG_PLATFORM_HOBBIT3), y)
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/sha/ck_sha_v2.c
endif
ifeq ($(CONFIG_PLATFORM_HOBBIT1_2), y)
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/sha/ck_sha_v1.c
endif
endif
ifeq ($(CONFIG_TRNG), y)
ifeq ($(CONFIG_PLATFORM_HOBBIT3), y)
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/common/trng/
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/trng/osr_trng.c
endif
ifeq ($(CONFIG_PLATFORM_PHOBOS), y)
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/common/trng/
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/trng/ck_trng.c
endif
ifeq ($(CONFIG_PLATFORM_HOBBIT1_2), y)
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/common/trng/
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/trng/ck_trng.c
endif
endif
ifeq ($(CONFIG_AES), y)
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/common/aes/
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/aes/ck_aes.c
endif
ifeq ($(CONFIG_RSA), y)
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/common/rsa/
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/rsa/ck_rsa.c
endif
ifeq ($(CONFIG_USART), y)
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/common/usart/
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/usart/dw_usart.c
endif
ifeq ($(CONFIG_PMU), y)
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/common/pmu/
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/pmu/ck_pmu.c
endif
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/wdt/dw_wdt.c
TEE_SRC += $(CSI_DIR)/csi_driver/csky/common/eflash/ck_eflash.c

View file

@ -0,0 +1,441 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_eflash.c
* @brief CSI Source File for Embedded Flash Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include "csi_core.h"
#include "drv_eflash.h"
#include "ck_eflash.h"
#define ERR_EFLASH(errno) (CSI_DRV_ERRNO_EFLASH_BASE | errno)
#define EFLASH_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_EFLASH(EDRV_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
eflash_info_t eflashinfo;
eflash_event_cb_t cb;
eflash_status_t status;
} ck_eflash_priv_t;
extern int32_t target_get_eflash_count(void);
extern int32_t target_get_eflash(int32_t idx, uint32_t *base, eflash_info_t *info);
static ck_eflash_priv_t eflash_handle[CONFIG_EFLASH_NUM];
/* Driver Capabilities */
static const eflash_capabilities_t driver_capabilities = {
.event_ready = 1, /* event_ready */
.data_width = 2, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
.erase_chip = 0 /* erase_chip */
};
//
// Functions
//
static int32_t eflash_program_word(eflash_handle_t handle, uint32_t dstaddr, uint32_t *srcbuf, uint32_t len)
{
ck_eflash_priv_t *eflash_priv = handle;
uint32_t fbase = eflash_priv->base;
uint32_t i;
for (i = 0; i < len; i++) {
*(volatile uint32_t *)(fbase + 0x04) = dstaddr;
*(volatile uint32_t *)(fbase + 0x1c) = *srcbuf;
*(volatile uint32_t *)(fbase + 0x18) = 1;
srcbuf++;
dstaddr += 4;
}
return (i << 2);
}
#ifdef CONFIG_CHIP_CH2201
static uint32_t context[EFLASH_SECTOR_SIZE >> 2] = {0x0};
static int32_t eflash_verify(eflash_handle_t handle, uint32_t addr, const void *data, uint32_t cnt)
{
uint32_t i;
uint8_t error_flag = 1;
uint8_t *block_addr = (uint8_t *)(addr & ~(EFLASH_SECTOR_SIZE - 1));
uint32_t pre_offset = addr - (uint32_t)block_addr;
uint32_t pre_count = (cnt > (EFLASH_SECTOR_SIZE - pre_offset)) ? (EFLASH_SECTOR_SIZE - pre_offset) : cnt;
uint8_t *p = NULL;
uint8_t *dst = NULL;
p = (uint8_t *)data;
dst = (uint8_t *)addr;
uint32_t len = cnt;
volatile uint8_t verify_count = 100;
while (error_flag) {
for (i = 0; i < pre_count; i++) {
if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
*(volatile uint32_t *) 0x50004000 = 'E'; /* for debug */
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = '\n';
memcpy(context, block_addr, EFLASH_SECTOR_SIZE);
memcpy((uint8_t *)context + pre_offset, p, pre_count);
csi_eflash_erase_sector(handle, (uint32_t)dst);
eflash_program_word(handle, (uint32_t)block_addr, context, EFLASH_SECTOR_SIZE >> 2);
break;
}
}
if (i == pre_count || !(verify_count--)) {
error_flag = 0;
}
}
if (!verify_count) {
return ERR_EFLASH(EDRV_TIMEOUT);
}
verify_count = 100;
error_flag = 1;
p += pre_count;
dst += pre_count;
len -= pre_count;
while (len >= EFLASH_SECTOR_SIZE) {
while (error_flag) {
for (i = 0; i < EFLASH_SECTOR_SIZE; i++) {
if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
*(volatile uint32_t *) 0x50004000 = 'E'; /* for debug */
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = '\n';
memcpy((uint8_t *)context, p, EFLASH_SECTOR_SIZE);
csi_eflash_erase_sector(handle, (uint32_t)dst);
eflash_program_word(handle, (uint32_t)dst, context, EFLASH_SECTOR_SIZE >> 2);
break;
}
}
if (i == EFLASH_SECTOR_SIZE || !(verify_count--)) {
error_flag = 0;
}
}
if (!verify_count) {
return ERR_EFLASH(EDRV_TIMEOUT);
}
verify_count = 100;
error_flag = 1;
dst += EFLASH_SECTOR_SIZE;
p += EFLASH_SECTOR_SIZE;
len -= EFLASH_SECTOR_SIZE;
}
if (len > 0) {
while (error_flag) {
for (i = 0; i < len; i++) {
if (*((uint8_t *)dst + i) != *((uint8_t *)p + i)) {
*(volatile uint32_t *) 0x50004000 = 'E'; /* for debug */
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = 'E';
*(volatile uint32_t *) 0x50004000 = '\n';
memcpy(context, dst, EFLASH_SECTOR_SIZE);
memcpy((uint8_t *)context + i, p + i, len - i);
csi_eflash_erase_sector(handle, (uint32_t)dst);
eflash_program_word(handle, (uint32_t)dst, context, EFLASH_SECTOR_SIZE >> 2);
break;
}
}
if (i == len || !(verify_count--)) {
error_flag = 0;
}
}
if (!verify_count) {
return ERR_EFLASH(EDRV_TIMEOUT);
}
verify_count = 100;
}
return 0;
}
#endif
/**
\brief Initialize EFLASH Interface. 1. Initializes the resources needed for the EFLASH interface 2.registers event callback function
\param[in] idx device id
\param[in] cb_event Pointer to \ref eflash_event_cb_t
\return pointer to eflash handle
*/
eflash_handle_t csi_eflash_initialize(int32_t idx, eflash_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_EFLASH_NUM) {
return NULL;
}
/* obtain the eflash information */
uint32_t base = 0u;
eflash_info_t info;
int32_t real_idx = target_get_eflash(idx, &base, &info);
if (real_idx != idx) {
return NULL;
}
ck_eflash_priv_t *eflash_priv = &eflash_handle[idx];
eflash_priv->base = base;
eflash_priv->eflashinfo.start = info.start;
eflash_priv->eflashinfo.end = info.end;
eflash_priv->eflashinfo.sector_count = info.sector_count;
/* initialize the eflash context */
eflash_priv->cb = cb_event;
eflash_priv->status.busy = 0;
eflash_priv->status.error = 0U;
eflash_priv->eflashinfo.sector_size = EFLASH_SECTOR_SIZE;
eflash_priv->eflashinfo.page_size = EFLASH_PAGE_SIZE;
eflash_priv->eflashinfo.program_unit = EFLASH_PROGRAM_UINT;
eflash_priv->eflashinfo.erased_value = EFLASH_ERASED_VALUE;
return (eflash_handle_t)eflash_priv;
}
/**
\brief De-initialize EFLASH Interface. stops operation and releases the software resources used by the interface
\param[in] handle eflash handle to operate.
\return error code
*/
int32_t csi_eflash_uninitialize(eflash_handle_t handle)
{
EFLASH_NULL_PARAM_CHK(handle);
ck_eflash_priv_t *eflash_priv = handle;
eflash_priv->cb = NULL;
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id
\return \ref eflash_capabilities_t
*/
eflash_capabilities_t csi_eflash_get_capabilities(eflash_handle_t handle)
{
return driver_capabilities;
}
/**
\brief Read data from Flash.
\param[in] handle eflash handle to operate.
\param[in] addr Data address.
\param[out] data Pointer to a buffer storing the data read from Flash.
\param[in] cnt Number of data items to read.
\return number of data items read or error code
*/
int32_t csi_eflash_read(eflash_handle_t handle, uint32_t addr, void *data, uint32_t cnt)
{
EFLASH_NULL_PARAM_CHK(handle);
EFLASH_NULL_PARAM_CHK(data);
EFLASH_NULL_PARAM_CHK(cnt);
volatile uint8_t *src_addr = (uint8_t *)addr;
ck_eflash_priv_t *eflash_priv = handle;
if (eflash_priv->eflashinfo.start > addr || eflash_priv->eflashinfo.end < addr || eflash_priv->eflashinfo.start > (addr + cnt - 1) || eflash_priv->eflashinfo.end < (addr + cnt - 1)) {
return ERR_EFLASH(EDRV_PARAMETER);
}
if (eflash_priv->status.busy) {
return ERR_EFLASH(EDRV_BUSY);
}
eflash_priv->status.error = 0U;
int i;
for (i = 0; i < cnt; i++) {
*((uint8_t *)data + i) = *(src_addr + i);
}
return i;
}
/**
\brief Program data to Flash.
\param[in] handle eflash handle to operate.
\param[in] addr Data address.
\param[in] data Pointer to a buffer containing the data to be programmed to Flash..
\param[in] cnt Number of data items to program.
\return number of data items programmed or error code
*/
int32_t csi_eflash_program(eflash_handle_t handle, uint32_t addr, const void *data, uint32_t cnt)
{
EFLASH_NULL_PARAM_CHK(handle);
EFLASH_NULL_PARAM_CHK(data);
EFLASH_NULL_PARAM_CHK(cnt);
ck_eflash_priv_t *eflash_priv = handle;
if (eflash_priv->eflashinfo.start > addr || eflash_priv->eflashinfo.end < addr || eflash_priv->eflashinfo.start > (addr + cnt - 1) || eflash_priv->eflashinfo.end < (addr + cnt - 1)) {
return ERR_EFLASH(EDRV_PARAMETER);
}
uint32_t cur = 0;
uint32_t pad_buf;
if (addr & 0x3) {
return ERR_EFLASH(EDRV_PARAMETER);
}
if (eflash_priv->status.busy) {
return ERR_EFLASH(EDRV_BUSY);
}
eflash_priv->status.busy = 1U;
eflash_priv->status.error = 0U;
if (((uint32_t)data & 0x3) == 0) {
cur = cnt - (cnt & 0x3);
eflash_program_word(handle, addr, (uint32_t *)data, cur >> 2);
} else {
uint8_t *buffer_b = (uint8_t *)data;
for (; cur < cnt - 3; cur += 4, buffer_b += 4) {
pad_buf = buffer_b[0] | (buffer_b[1] << 8) | (buffer_b[2] << 16) | (buffer_b[3] << 24);
eflash_program_word(handle, addr + cur, &pad_buf, 1);
}
}
if (cur < cnt) {
pad_buf = *((volatile uint32_t *)(addr + cur));
uint8_t *pad = (uint8_t *)&pad_buf;
uint8_t *buff = (uint8_t *)data;
uint8_t i;
for (i = 0; i < (cnt - cur); i++) {
pad[i] = buff[cur + i];
}
eflash_program_word(handle, addr + cur, &pad_buf, 1);
}
eflash_priv->status.busy = 0U;
#ifdef CONFIG_CHIP_CH2201
eflash_verify(handle, addr, data, cnt);
#endif
return cnt;
}
/**
\brief Erase Flash Sector.
\param[in] handle eflash handle to operate.
\param[in] addr Sector address
\return error code
*/
int32_t csi_eflash_erase_sector(eflash_handle_t handle, uint32_t addr)
{
EFLASH_NULL_PARAM_CHK(handle);
ck_eflash_priv_t *eflash_priv = handle;
if (eflash_priv->eflashinfo.start > addr || eflash_priv->eflashinfo.end < addr) {
return ERR_EFLASH(EDRV_PARAMETER);
}
addr = addr & ~(EFLASH_SECTOR_SIZE - 1);
uint32_t fbase = eflash_priv->base;
if (eflash_priv->status.busy) {
return ERR_EFLASH(EDRV_BUSY);
}
eflash_priv->status.busy = 1U;
eflash_priv->status.error = 0U;
*(volatile uint32_t *)(fbase + 0x4) = addr;
*(volatile uint32_t *)(fbase + 0x10) = 0x1;
eflash_priv->status.busy = 0U;
return 0;
}
/**
\brief Erase complete Flash.
\param[in] handle eflash handle to operate.
\return error code
*/
int32_t csi_eflash_erase_chip(eflash_handle_t handle)
{
EFLASH_NULL_PARAM_CHK(handle);
return ERR_EFLASH(EDRV_UNSUPPORTED);
}
/**
\brief Get Flash information.
\param[in] handle eflash handle to operate.
\return Pointer to Flash information \ref eflash_info_t
*/
eflash_info_t *csi_eflash_get_info(eflash_handle_t handle)
{
if (handle == NULL) {
return NULL;
}
ck_eflash_priv_t *eflash_priv = handle;
eflash_info_t *eflash_info = &(eflash_priv->eflashinfo);
return eflash_info;
}
/**
\brief Get EFLASH status.
\param[in] handle eflash handle to operate.
\return EFLASH status \ref eflash_status_t
*/
eflash_status_t csi_eflash_get_status(eflash_handle_t handle)
{
if (handle == NULL) {
eflash_status_t ret;
memset(&ret, 0, sizeof(eflash_status_t));
return ret;
}
ck_eflash_priv_t *eflash_priv = handle;
return eflash_priv->status;
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_eflash.h
* @brief head file for ck eflash
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_EFLASH_H_
#define _CK_EFLASH_H_
#include "drv_eflash.h"
#include "soc.h"
#define EFLASH_SECTOR_SIZE 0x200
#define EFLASH_ERASED_VALUE 0xff
#define EFLASH_PROGRAM_UINT 0x4
#define EFLASH_PAGE_SIZE 0
#endif

View file

@ -0,0 +1,366 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_pmu.c
* @brief CSI Source File for Embedded Flash Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include "drv_pmu.h"
#include "drv_tee.h"
#include "drv_eflash.h"
#include "ck_pmu.h"
#define ERR_PMU(errno) (CSI_DRV_ERRNO_PMU_BASE | errno)
#define PMU_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_PMU(EDRV_PARAMETER); \
} \
} while (0)
typedef struct {
uint8_t idx;
uint32_t base;
uint32_t irq;
pmu_event_cb_t cb;
pmu_action_cb_t callback[32];
} ck_pmu_priv_t;
extern int32_t target_get_pmu(int32_t idx, uint32_t *base, uint32_t *irq);
extern int32_t arch_do_cpu_save(void);
extern int32_t arch_do_cpu_resume(void);
extern int32_t arch_resume_context(void);
static ck_pmu_priv_t pmu_handle[CONFIG_PMU_NUM];
static uint32_t s_callback_count = 0;
#define CONFIG_PMU_REGISTER_NUM_SAVE 19
static uint32_t pmu_regs_saved[CONFIG_PMU_REGISTER_NUM_SAVE];
#define CONFIG_CPU_REGISTER_NUM_SAVE 27
uint32_t arch_cpu_saved[CONFIG_CPU_REGISTER_NUM_SAVE];
/* Driver Capabilities */
#if 0
static const pmu_capabilities_t driver_capabilities = {
.event_ready = 1, /* event_ready */
.data_width = 2, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
.erase_chip = 0 /* erase_chip */
};
#endif
//
// Functions
//
static void do_prepare_sleep_action(int32_t idx)
{
uint8_t i;
volatile ck_pmu_reg_t *pbase = (ck_pmu_reg_t *)pmu_handle[idx].base;
for (i = 0; i < sizeof(pmu_regs_saved)/4; i++) {
pmu_regs_saved[i] = *((volatile uint32_t *)pbase + i);
}
}
static void do_wakeup_sleep_action(int32_t idx)
{
uint8_t i;
volatile ck_pmu_reg_t *pbase = (ck_pmu_reg_t *)pmu_handle[idx].base;
*((volatile uint32_t *)pbase + 5) = pmu_regs_saved[5];
while((*((volatile uint32_t *)pbase + 6) & 0xf) != 0xf);
*((volatile uint32_t *)pbase + 11) = pmu_regs_saved[11];
while((*((volatile uint32_t *)pbase + 6) & 0x1f) != 0x1f);
for (i = 0; i < sizeof(pmu_regs_saved)/4; i++) {
if (i != 5 && i != 11) {
*((volatile uint32_t *)pbase + i) = pmu_regs_saved[i];
}
}
}
static uint8_t s_action[CONFIG_PMU_NUM] = {0x0};
int32_t ck_pmu_power_manager(int32_t idx)
{
if (!(s_action[idx] % 2)) {
do_prepare_sleep_action(idx);
s_action[idx]++;
} else {
do_wakeup_sleep_action(idx);
s_action[idx]--;
}
return 0;
}
int32_t ck_pmu_act_callback(pmu_handle_t handle, pmu_event_e event)
{
ck_pmu_priv_t *pmu_priv = handle;
uint32_t i;
for (i = 0; i < s_callback_count; i++) {
if (pmu_priv->callback[i]) {
pmu_priv->callback[i](event);
}
}
if (i != s_callback_count) {
return -1;
}
return 0;
}
void resume_context_from_stop_mode(void)
{
ck_pmu_priv_t *pmu_priv = &pmu_handle[0];
// ck_pmu_power_manager(PMU_EVENT_SLEEP_DONE);
// ck_pmu_act_callback(pmu_priv, PMU_EVENT_SLEEP_DONE);
*((volatile uint32_t *)0x50006100) |= 0xa0000000;
if (pmu_priv->cb) {
pmu_priv->cb(pmu_priv->idx, PMU_EVENT_SLEEP_DONE, PMU_MODE_STDBY);
}
arch_do_cpu_resume();
}
#define CONFIG_LPM_RESUME_ADDR 0x1003f7f0
void set_resume_func(uint32_t *func)
{
eflash_handle_t eflash = csi_eflash_initialize(0, NULL);
csi_eflash_erase_sector(eflash, CONFIG_LPM_RESUME_ADDR);
csi_eflash_program(eflash, CONFIG_LPM_RESUME_ADDR, &func, 4);
}
typedef enum {
WAIT_MODE = 0,
DOZE_MODE,
STOP_MODE,
STANDBY_MODE,
SLEEP_MODE
} lpm_mode_t;
void soc_sleep(pmu_handle_t handle, lpm_mode_t mode)
{
#ifdef CONFIG_TEE_CA
tee_lpm_mode_e lpm_mode = 0;
if (mode == WAIT_MODE) {
lpm_mode = TEE_LPM_MODE_WAIT;
} else if (mode == DOZE_MODE) {
lpm_mode = TEE_LPM_MODE_DOZE;
} else if (mode == STOP_MODE) {
lpm_mode = TEE_LPM_MODE_STOP;
} else if (mode == STANDBY_MODE) {
lpm_mode = TEE_LPM_MODE_STANDBY;
} else {
lpm_mode = TEE_LPM_MODE_WAIT;
}
csi_tee_enter_lpm(0, 0, lpm_mode);
if (mode == STOP_MODE) {
resume_context_from_stop_mode();
}
#else
ck_pmu_priv_t *pmu_priv = handle;
ck_pmu_reg_t *pmu_reg = (ck_pmu_reg_t *)pmu_priv->base;
if (mode == WAIT_MODE) {
pmu_reg->LPCR |= CONFIG_PMU_ENTER_WAIT_MODE;
__WFI();
} else if (mode == DOZE_MODE) {
pmu_reg->LPCR |= CONFIG_PMU_ENTER_DOZE_MODE;
__DOZE();
} else if (mode == STOP_MODE) {
pmu_reg->LPCR |= CONFIG_PMU_ENTER_STOP_MODE;
__STOP();
} else if (mode == STANDBY_MODE) {
pmu_reg->LPCR |= CONFIG_PMU_ENTER_STANDBY_MODE;
__STOP();
} else {
pmu_reg->LPCR |= CONFIG_PMU_ENTER_WAIT_MODE;
__WFI();
}
#endif
}
/**
\brief Initialize PMU Interface. 1. Initializes the resources needed for the PMU interface 2.registers event callback function
\param[in] idx device id
\param[in] cb_event Pointer to \ref pmu_event_cb_t
\return pointer to pmu handle
*/
pmu_handle_t drv_pmu_initialize(int32_t idx, pmu_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_PMU_NUM) {
return NULL;
}
/* obtain the pmu information */
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t real_idx = target_get_pmu(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_pmu_priv_t *pmu_priv = &pmu_handle[idx];
/* initialize the pmu context */
pmu_priv->idx = idx;
pmu_priv->base = base;
pmu_priv->irq = irq;
pmu_priv->cb = cb_event;
return (pmu_handle_t)pmu_priv;
}
/**
\brief De-initialize PMU Interface. stops operation and releases the software resources used by the interface
\param[in] handle pmu handle to operate.
\return error code
*/
int32_t drv_pmu_uninitialize(pmu_handle_t handle)
{
PMU_NULL_PARAM_CHK(handle);
ck_pmu_priv_t *pmu_priv = handle;
pmu_priv->cb = NULL;
return 0;
}
int32_t drv_pmu_power_control(int32_t idx, csi_power_stat_e state)
{
switch (state) {
case DRV_POWER_LOW:
break;
case DRV_POWER_FULL:
break;
case DRV_POWER_OFF:
ck_pmu_power_manager(idx);
// csi_pmu_register_module(dw_usart_power_manager);
break;
default:
break;
}
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id
\return \ref pmu_capabilities_t
*/
#if 0
pmu_capabilities_t csi_pmu_get_capabilities(int32_t idx)
{
if (idx < 0 || idx >= CONFIG_PMU_NUM) {
pmu_capabilities_t ret;
memset(&ret, 0, sizeof(pmu_capabilities_t));
return ret;
}
return driver_capabilities;
}
#endif
/**
\brief choose the pmu mode to enter
\param[in] handle pmu handle to operate.
\param[in] mode \ref pmu_mode_e
\return error code
*/
int32_t drv_pmu_enter_sleep(pmu_handle_t handle, pmu_mode_e mode)
{
PMU_NULL_PARAM_CHK(handle);
switch (mode) {
case PMU_MODE_RUN:
break;
case PMU_MODE_SLEEP:
soc_sleep(handle, WAIT_MODE);
break;
case PMU_MODE_DORMANT:
// soc_sleep(handle, DOZE_MODE);
if (arch_do_cpu_save() == 0) {
*(volatile unsigned int *)(0xe000e1c0) = 0xffffffff; // reload wakeup_IRQ
*(volatile unsigned int *)(0xe000e280) = 0xffffffff; // clear pend IRQ
soc_sleep(handle, STOP_MODE);
}
break;
case PMU_MODE_STDBY:
*(volatile unsigned int *)(0xe000e1c0) = 0xffffffff; // reload wakeup_IRQ
*(volatile unsigned int *)(0xe000e280) = 0xffffffff; // clear pend IRQ
soc_sleep(handle, STANDBY_MODE);
break;
case PMU_MODE_SHUTDOWN:
*(volatile unsigned int *)(0xe000e1c0) = 0xffffffff; // reload wakeup_IRQ
*(volatile unsigned int *)(0xe000e280) = 0xffffffff; // clear pend IRQ
soc_sleep(handle, STANDBY_MODE);
break;
default:
return ERR_PMU(EDRV_PARAMETER);
}
return 0;
}
/**
\brief register module to action pmu event
\param[in] handle pmu handle to operate.
\param[in] callback Pointer to \ref pmu_action_cb_t
\return error code
*/
int32_t drv_pmu_register_module(pmu_action_cb_t callback)
{
ck_pmu_priv_t *pmu_priv = (ck_pmu_priv_t *)&pmu_handle[0];
if (callback == NULL) {
return ERR_PMU(EDRV_PARAMETER);
}
pmu_priv->callback[s_callback_count] = callback;
s_callback_count++;
return 0;
}
/**
\brief Config the wakeup source.
\param[in] handle pmu handle to operate
\param[in] type \ref pmu_wakeup_type
\param[in] pol \ref pmu_wakeup_pol
\param[in] enable flag control the wakeup source is enable or not
\return error code
*/
int32_t drv_pmu_config_wakeup_source(pmu_handle_t handle, uint32_t irq_num, pmu_wakeup_type_e type, pmu_wakeup_pol_e pol, uint8_t enable)
{
PMU_NULL_PARAM_CHK(handle);
if (enable) {
// csi_vic_enable_irq(irq_num);
// csi_vic_enable_sirq(irq_num);
// csi_vic_set_wakeup_irq(irq_num);
drv_nvic_set_wakeup_irq(irq_num);
} else {
// csi_vic_disable_irq(irq_num);
// csi_vic_disable_sirq(irq_num);
drv_nvic_clear_wakeup_irq(irq_num);
// csi_vic_clear_wakeup_irq(irq_num);
}
return 0;
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_pmu.h
* @brief head file for ck pmu
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_PMU_H_
#define _CK_PMU_H_
#include "drv_pmu.h"
#include "soc.h"
#define CONFIG_PMU_ENTER_WAIT_MODE 0x4
#define CONFIG_PMU_ENTER_DOZE_MODE 0x4
#define CONFIG_PMU_ENTER_STOP_MODE 0xc
#define CONFIG_PMU_ENTER_STANDBY_MODE 0x14
typedef struct {
__IOM uint32_t LPCR; /* Offset: 0x000 (R/W) low power control register */
__IOM uint32_t MCLKSEL; /* Offset: 0x004 (R/W) MCLK select register */
__IOM uint32_t CRCR; /* Offset: 0x008 (R/W) clock ratio control register */
__IOM uint32_t CGCR; /* Offset: 0x00c (R/W) clock gate control register */
__IOM uint32_t CGSR; /* Offset: 0x010 (R/W) clock gate status register */
__IOM uint32_t CLKDSENR; /* Offset: 0x014 (R/W) clock disable register */
__IOM uint32_t CLKSTBR; /* Offset: 0x018 (R/W) clock stable register */
__IOM uint32_t CLKSTBST; /* Offset: 0x01c (R/W) clock stable interrupt statue register */
__IOM uint32_t CLKSTBMK; /* Offset: 0x020 (R/W) clock stable interrupt mask register */
__IOM uint32_t CSSCR; /* Offset: 0x024 (R/W) clock source stable counter register */
__IOM uint32_t DFCC; /* Offset: 0x028 (R/W) dynamic frequence conversion control register */
__IOM uint32_t PCR; /* Offset: 0x02c (R/W) pll control register */
__IOM uint32_t PLTR; /* Offset: 0x030 (R/W) pll lock timer register */
__IOM uint32_t SWHRC; /* Offset: 0x034 (R/W) software HRST control register */
__IOM uint32_t SWHRD; /* Offset: 0x038 (R/W) software HRST duration register */
__IOM uint32_t SWPRC; /* Offset: 0x03c (R/W) software PRST control register */
__IOM uint32_t SWPRD; /* Offset: 0x040 (R/W) software PRST duration register */
__IOM uint32_t SWRE; /* Offset: 0x044 (R/W) software reset enable register */
__IOM uint32_t BOOTSEL; /* Offset: 0x048 (R/W) boot selection register */
__IOM uint32_t SCGCR; /* Offset: 0x04c (R/W) security clock gate control register */
__IOM uint32_t SCGSR; /* Offset: 0x050 (R/W) security clock gate status register */
} ck_pmu_reg_t;
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,91 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_rsa.h
* @brief header file for rsa driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_RSA_H_
#define _CK_RSA_H_
#include <stdio.h>
#include "drv_rsa.h"
#include "soc.h"
#define RSA_KEY_LEN 2048
#define RSA_KEY_BYTE (RSA_KEY_LEN >> 3)
#define RSA_KEY_WORD (RSA_KEY_LEN >> 5)
#define BN_MAX_BITS ((RSA_KEY_LEN << 1) + 32)
#define BN_MAX_BYTES ((BN_MAX_BITS + 7) >> 3)
#define BN_MAX_WORDS ((BN_MAX_BYTES + 3) >> 2)
#define MAX_RSA_LP_CNT 10000
#define GET_KEY_BYTE(k) (k >> 3)
#define GET_KEY_WORD(k) (k >> 5)
#define UINT32_TO_UINT64(data) ((uint64_t)(((uint64_t)(data)) & 0x00000000ffffffffU))
#define UINT64L_TO_UINT32(data) ((uint32_t)(((uint64_t)(data)) & 0x00000000ffffffffU))
#define UINT64H_TO_UINT32(data) ((uint32_t)((((uint64_t)(data)) >> 32) & 0x00000000ffffffffU))
#define PKCS1_PADDING 0x01
#define NO_PADDING 0x02
#define MD5_PADDING 0x00
#define SHA1_PADDING 0x01
#define SHA256_PADDING 0x03
#define MD5_HASH_SZ 16
#define SHA1_HASH_SZ 20
#define SHA256_HASH_SZ 32
#define RAS_CALCULATE_Q 0x6
#define RSA_ENABLE_MODULE 0x3
#define RSA_ENDIAN_MODE 0x8
#define RSA_RESET 0x1
#define RSA_CAL_Q_DONE_OFFSET 0x5
typedef struct bignum {
uint32_t pdata[BN_MAX_WORDS];
uint32_t words;
} bignum_t;
typedef struct {
__IOM uint32_t rsa_mwid; /* Offset: 0x000 (R/W) Width of M register */
__IOM uint32_t rsa_ckid; /* Offset: 0x004 (R/W) Width of D register */
__IOM uint32_t rsa_bwid; /* Offset: 0x008 (R/W) Width of B register */
__IOM uint32_t rsa_ctrl; /* Offset: 0x00c (R/W) RSA control register */
__OM uint32_t rsa_rst; /* Offset: 0x010 (W) RSA reset register */
__IM uint32_t rsa_lp_cnt; /* Offset: 0x014 (R) Loop counter for inquiry register*/
__IM uint32_t rsa_q0; /* Offset: 0x018 (R) High-radix MM algorithm assistant register,part 1*/
__IM uint32_t rsa_q1; /* Offset: 0x01c (R) High-radix MM algorithm assistant register,part 2*/
__IOM uint32_t rsa_isr; /* Offset: 0x020 (W/R) Interrupt raw status register */
__IOM uint32_t rsa_imr; /* Offset: 0x024 (W/R) Interrupt mask register */
__IOM uint32_t rev1[54]; /* Reserve regiser */
__IOM uint32_t rsa_rfm; /* Offset: 0x100 (W/R) Register file for modulus M */
__IOM uint32_t rev2[63]; /* Reserve regiser */
__IOM uint32_t rsa_rfd; /* Offset: 0x200 (W/R) Register file for exponent D */
__IOM uint32_t rev3[63]; /* Reserve regiser */
__IOM uint32_t rsa_rfc; /* Offset: 0x300 (W/R) Register file for hard C */
__IOM uint32_t rev4[63]; /* Reserve regiser */
__IOM uint32_t rsa_rfb; /* Offset: 0x400 (W/R) Register file for data B */
__IOM uint32_t rev5[63]; /* Reserve regiser */
__IM uint32_t rsa_rfr; /* Offset: 0x500 (R) Register file for storing the result */
} ck_rsa_reg_t;
#endif

View file

@ -0,0 +1,20 @@
choice
prompt "select sha type "
help
select sha type
config SHA_CK_V2
bool "csky v2 sha"
help
select the ck sha driver
config SHA_CK_V1
bool "csky v1 sha"
help
select the ck sha driver
config SHA_ZX29
bool "csky zx29 sha"
help
select the zx29 sha driver
endchoice

View file

@ -0,0 +1,559 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_sha.c
* @brief CSI Source File for SHA Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "csi_core.h"
#include "drv_sha.h"
#include "ck_sha_v1.h"
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
#define CONFIG_SHA_SUPPORT_MUL_THREAD 1
#endif
typedef struct {
uint32_t base;
uint32_t irq;
sha_event_cb_t cb;
sha_status_t status;
sha_mode_e mode;
sha_endian_mode_e endian;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t state[16];
uint32_t sha_buffer[32];
uint32_t total;
uint8_t first_cal;
#endif
} ck_sha_priv_t;
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static ck_sha_priv_t sha_handle[CONFIG_SHA_NUM];
#endif
bool finish_flag = 0;
/* Driver Capabilities */
static const sha_capabilities_t driver_capabilities = {
.sha1 = 1, /* sha1 mode */
.sha224 = 1, /* sha224 mode */
.sha256 = 1, /* sha256 mode */
.sha384 = 1, /* sha384 mode */
.sha512 = 1, /* sha512 mode */
.sha512_224 = 1, /* sha512_224 mode */
.sha512_256 = 1, /* sha512_256 mode */
.endianmode = 1, /* endian mode */
.interruptmode = 1 /* interrupt mode */
};
#define ERR_SHA(errno) (CSI_DRV_ERRNO_SHA_BASE | errno)
#define SHA_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_SHA(EDRV_PARAMETER); \
} \
} while (0)
extern int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq);
extern int32_t target_get_sha_count(void);
//
// Functions
//
ck_sha_reg_t *sha_reg = NULL;
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static uint32_t sha_buffer[32];
static uint32_t total[2] = {0x0};
static uint8_t first_cal = 1;
#endif
static uint8_t sha_result[64] = {0x0};
static int32_t sha_set_mode(sha_mode_e mode)
{
sha_reg->SHA_MODE &= ~0x7;
sha_reg->SHA_MODE |= mode;
return 0;
}
static void sha_set_source_message(uint32_t baseaddr)
{
sha_reg->SHA_BASEADDR = baseaddr;
}
static void sha_set_dest_message(uint32_t destaddr)
{
sha_reg->SHA_DESTADDR = destaddr;
}
static void sha_enable_without_count(void)
{
sha_reg->SHA_MODE |= 1<<25;
}
static void sha_disable_without_count(void)
{
sha_reg->SHA_MODE &= ~(1<<25);
}
static void sha_set_message_count(uint32_t count)
{
sha_reg->SHA_COUNTER0 = count;
sha_reg->SHA_COUNTER1 = 0;
}
static int32_t sha_enable_initial(void)
{
sha_reg->SHA_MODE |= 1 << SHA_INIT_OFFSET;
return 0;
}
static int32_t sha_disable_initial(void)
{
sha_reg->SHA_MODE &= ~(1 << SHA_INIT_OFFSET);
return 0;
}
static int32_t sha_enable_calculate(void)
{
sha_reg->SHA_CON |= 1;
return 0;
}
static int32_t sha_message_done(void)
{
while(sha_reg->SHA_CON & 0x1);
return 0;
}
static void sha_new_encode(void)
{
sha_reg->SHA_INTSTATE = 0;
sha_reg->SHA_MODE = 0;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
static int32_t sha_restore_context(sha_handle_t handle, uint32_t *data)
{
uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
uint8_t i;
for (i = 0; i < 16; i++) {
result[i] = data[i];
}
return 0;
}
static int32_t sha_save_context(sha_handle_t handle, uint32_t *data)
{
uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
uint8_t i;
for (i = 0; i < 16; i++) {
data[i] = result[i];
}
return 0;
}
#endif
static inline void sha_reverse_order(uint8_t *pdata, int32_t length)
{
uint8_t input_data[length];
uint8_t result[length];
uint32_t tmp = 0;
int32_t i = 0;
memcpy((void *)input_data, (void *)pdata, length);
for (i = 0; i < length; i++) {
tmp = i >> 2;
tmp = tmp << 3;
result[i] = input_data[tmp + 3 - i];
}
memcpy((void *)pdata, (void *)result, length);
}
/**
\brief get sha handle count.
\return sha handle count
*/
int32_t csi_sha_get_instance_count(void)
{
return target_get_sha_count();
}
/**
\brief Initialize SHA Interface. 1. Initializes the resources needed for the SHA interface 2.registers event callback function
\param[in] idx must not exceed return value of csi_sha_get_instance_count()
\param[in] cb_event Pointer to \ref sha_event_cb_t
\return return sha handle if success
*/
sha_handle_t csi_sha_initialize(sha_handle_t handle, sha_event_cb_t cb_event)
{
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t base = 0u;
uint32_t irq;
/* obtain the sha information */
target_get_sha(0, &base, &irq);
ck_sha_priv_t *sha_priv = handle;
memset(sha_priv->state, 0, sizeof(sha_priv->state));
sha_priv->total = 0;
sha_priv->first_cal = 1;
#else
if (idx < 0 || idx >= CONFIG_SHA_NUM) {
return NULL;
}
uint32_t base = 0u;
uint32_t irq;
/* obtain the sha information */
int32_t real_idx = target_get_sha(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_sha_priv_t *sha_priv = &sha_handle[idx];
#endif
sha_priv->base = base;
sha_priv->irq = irq;
/* initialize the sha context */
sha_priv->cb = cb_event;
sha_priv->status.busy = 0;
return (sha_handle_t)sha_priv;
}
/**
\brief De-initialize SHA Interface. stops operation and releases the software resources used by the interface
\param[in] handle sha handle to operate.
\return error code
*/
int32_t csi_sha_uninitialize(sha_handle_t handle)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_priv->cb = NULL;
return 0;
}
/**
\brief Get driver capabilities.
\param[in] handle sha handle to operate.
\return \ref sha_capabilities_t
*/
sha_capabilities_t csi_sha_get_capabilities(sha_handle_t handle)
{
return driver_capabilities;
}
/**
\brief config sha mode.
\param[in] handle sha handle to operate.
\param[in] mode \ref sha_mode_e
\param[in] endian \ref sha_endian_mode_e
\return error code
*/
int32_t csi_sha_config(sha_handle_t handle, sha_mode_e mode, sha_endian_mode_e endian_mode)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_reg = (ck_sha_reg_t *)(sha_priv->base);
/* config the sha mode */
switch (mode) {
case SHA_MODE_512_256:
case SHA_MODE_512_224:
return ERR_SHA(EDRV_UNSUPPORTED);
case SHA_MODE_1:
case SHA_MODE_224:
case SHA_MODE_256:
case SHA_MODE_384:
case SHA_MODE_512:
sha_priv->mode = mode;
break;
default:
return ERR_SHA(EDRV_PARAMETER);
}
return 0;
}
/**
\brief start the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\return error code
*/
int32_t csi_sha_starts(sha_handle_t handle, void *context)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_priv->status.busy = 1;
sha_new_encode();
sha_set_mode(sha_priv->mode);
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(sha_priv->sha_buffer, 0, sizeof(sha_priv->sha_buffer));
memset(sha_priv->state, 0, sizeof(sha_priv->state));
sha_priv->first_cal = 1;
sha_priv->total = 0;
#endif
return 0;
}
/**
\brief updata the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\param[in] input Pointer to the Source data
\param[in] len the data len
\return error code
*/
int32_t csi_sha_update(sha_handle_t handle, void *context, const void *input, uint32_t len)
{
SHA_NULL_PARAM_CHK(handle);
SHA_NULL_PARAM_CHK(input);
if (len <= 0) {
return ERR_SHA(EDRV_PARAMETER);
}
ck_sha_priv_t *sha_priv = handle;
sha_reg = (ck_sha_reg_t *)(sha_priv->base);
uint8_t total_len_num;
uint32_t block_size;
if (sha_priv->mode < 4) {
block_size = 64;
total_len_num = 2;
} else {
block_size = 128;
total_len_num = 4;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t *sha_buffer = sha_priv->sha_buffer;
uint8_t first_cal = sha_priv->first_cal;
sha_set_mode(sha_priv->mode);
uint32_t left = sha_priv->total & (block_size - 1);
uint32_t fill = block_size - left;
uint32_t total_length = sha_priv->total << 3;
uint32_t index = left >> 2;
if (left & 0x3) {
index++;
}
sha_priv->total += len;
sha_priv->total &= 0xffffffff;
#else
uint32_t left = total[0] & (block_size - 1);
uint32_t fill = block_size - left;
uint32_t total_length = total[0] << 3;
uint32_t index = left >> 2;
if (left & 0x3) {
index++;
}
total[0] += len;
total[0] &= 0xffffffff;
#endif
uint8_t *p = (uint8_t *)input;
/* when the text is not aligned by block and len > fill */
if (left && len >= fill) {
if (finish_flag) {
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(((uint8_t *)sha_buffer + left), 0x0, sizeof(sha_priv->sha_buffer) - left);
#else
memset(((uint8_t *)sha_buffer + left), 0x0, sizeof(sha_buffer) - left);
#endif
sha_buffer[index + total_len_num - 1] = total_length;
sha_disable_without_count();
sha_set_message_count(left << 3);
} else {
memcpy((void *)(((uint8_t *)sha_buffer) + left), p, fill);
p += fill;
sha_enable_without_count();
sha_set_message_count(block_size << 3);
}
sha_set_source_message((uint32_t)sha_buffer);
sha_set_dest_message((uint32_t)sha_result);
if (first_cal == 0) {
sha_enable_initial();
} else {
sha_disable_initial();
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_restore_context(handle, (uint32_t *)sha_priv->state);
#endif
sha_enable_calculate();
sha_message_done();
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_save_context(handle, (uint32_t *)sha_priv->state);
#endif
len -= fill;
left = 0;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_priv->first_cal = 0;
first_cal = 0;
#else
first_cal = 0;
#endif
}
/* calculate the hash by block */
while (len >= block_size) {
if (finish_flag) {
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(sha_buffer, 0, sizeof(sha_priv->sha_buffer));
#else
memset(sha_buffer, 0, sizeof(sha_buffer));
#endif
sha_buffer[total_len_num - 1] = total_length;
sha_set_source_message((uint32_t)sha_buffer);
sha_disable_without_count();
sha_set_message_count(0);
} else {
memcpy(sha_buffer, p, block_size);
sha_set_source_message((uint32_t)sha_buffer);
sha_enable_without_count();
sha_set_message_count(block_size << 3);
p += block_size;
}
sha_set_dest_message((uint32_t)sha_result);
if (first_cal == 0) {
sha_enable_initial();
} else {
sha_disable_initial();
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_restore_context(handle, (uint32_t *)sha_priv->state);
#endif
sha_enable_calculate();
sha_message_done();
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_save_context(handle, (uint32_t *)sha_priv->state);
#endif
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_priv->first_cal = 0;
first_cal = 0;
#else
first_cal = 0;
#endif
len -= block_size;
}
/* when the text is not aligned by block and len < fill */
if (len > 0) {
memcpy((void *)(((uint8_t *)sha_buffer) + left), p, len);
}
sha_priv->status.busy = 0;
return 0;
}
/**
\brief finish the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\param[out] output Pointer to the dest data
\return error code
*/
int32_t csi_sha_finish(sha_handle_t handle, void *context, void *output)
{
SHA_NULL_PARAM_CHK(handle);
SHA_NULL_PARAM_CHK(output);
ck_sha_priv_t *sha_priv = handle;
uint32_t block_size;
if (sha_priv->mode < 4) {
block_size = 64;
} else {
block_size = 128;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t last = sha_priv->total & (block_size - 1);
#else
uint32_t last = total[0] & (block_size - 1);
#endif
uint32_t padn = block_size - last;
finish_flag = 1;
csi_sha_update(handle, NULL, output, padn);
uint8_t result_len = 20;
/* convert the data endian according the sha mode */
if (sha_priv->mode == SHA_MODE_1) {
result_len = 20;
} else if (sha_priv->mode == SHA_MODE_224) {
result_len = 28;
} else if (sha_priv->mode == SHA_MODE_256) {
result_len = 32;
} else if (sha_priv->mode == SHA_MODE_512) {
result_len = 64;
} else if (sha_priv->mode == SHA_MODE_384) {
result_len = 48;
}
sha_reverse_order(sha_result, result_len);
memcpy((uint8_t*)output, sha_result, result_len);
finish_flag = 0;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(sha_priv->sha_buffer, 0, sizeof(sha_priv->sha_buffer));
sha_priv->first_cal = 1;
sha_priv->total = 0;
#else
memset(sha_buffer, 0, sizeof(sha_buffer));
first_cal = 1;
total[0] = 0;
#endif
return 0;
}
/**
\brief Get SHA status.
\param[in] handle sha handle to operate.
\return SHA status \ref sha_status_t
*/
sha_status_t csi_sha_get_status(sha_handle_t handle)
{
ck_sha_priv_t *sha_priv = handle;
return sha_priv->status;
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_sha.h
* @brief header file for sha driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_SHA_H_
#define _CK_SHA_H_
#include <stdio.h>
#include "drv_sha.h"
#include "soc.h"
#define SHA_INIT_OFFSET 3
#define SHA_INT_ENABLE_OFFSET 4
#define SHA_ENDIAN_OFFSET 5
#define SHA_CAL_OFFSET 6
typedef struct {
__IOM uint32_t SHA_CON; /* Offset: 0x000 (R/W) Control register */
__IOM uint32_t SHA_MODE; /* Offset: 0x004 (R/W) Mode register */
__IOM uint32_t SHA_INTSTATE; /* Offset: 0x008 (R/W) Instatus register */
__IOM uint32_t SHA_BASEADDR; /* Offset: 0x00c (R/W) Baseaddr register */
__IOM uint32_t SHA_DESTADDR; /* Offset: 0x010 (R/W) Dest addr register */
__IOM uint32_t SHA_COUNTER0; /* Offset: 0x014 (R/W) count0 register */
__IOM uint32_t SHA_COUNTER1; /* Offset: 0x018 (R/W) count1 register */
__IOM uint32_t SHA_COUNTER2; /* Offset: 0x01c (R/W) count2 register */
__IOM uint32_t SHA_COUNTER3; /* Offset: 0x020 (R/W) count3 register */
__IOM uint32_t SHA_H0L; /* Offset: 0x024 (R/W) H0L register */
__IOM uint32_t SHA_H1L; /* Offset: 0x028 (R/W) H1L register */
__IOM uint32_t SHA_H2L; /* Offset: 0x02c (R/W) H2L register */
__IOM uint32_t SHA_H3L; /* Offset: 0x030 (R/W) H3L register */
__IOM uint32_t SHA_H4L; /* Offset: 0x034 (R/W) H4L register */
__IOM uint32_t SHA_H5L; /* Offset: 0x038 (R/W) H5L register */
__IOM uint32_t SHA_H6L; /* Offset: 0x03c (R/W) H6L register */
__IOM uint32_t SHA_H7L; /* Offset: 0x040 (R/W) H7L register */
__IOM uint32_t SHA_H0H; /* Offset: 0x044 (R/W) H0H register */
__IOM uint32_t SHA_H1H; /* Offset: 0x048 (R/W) H1H register */
__IOM uint32_t SHA_H2H; /* Offset: 0x04c (R/W) H2H register */
__IOM uint32_t SHA_H3H; /* Offset: 0x050 (R/W) H3H register */
__IOM uint32_t SHA_H4H; /* Offset: 0x054 (R/W) H4H register */
__IOM uint32_t SHA_H5H; /* Offset: 0x058 (R/W) H5H register */
__IOM uint32_t SHA_H6H; /* Offset: 0x05c (R/W) H6H register */
__IOM uint32_t SHA_H7H; /* Offset: 0x060 (R/W) H7H register */
} ck_sha_reg_t;
#endif

View file

@ -0,0 +1,700 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_sha.c
* @brief CSI Source File for SHA Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "csi_core.h"
#include "drv_sha.h"
#include "ck_sha_v2.h"
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
#define CONFIG_SHA_SUPPORT_MUL_THREAD 1
#endif
typedef struct {
uint32_t base;
uint32_t irq;
sha_event_cb_t cb;
sha_status_t status;
sha_mode_e mode;
sha_endian_mode_e endian;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint8_t state[64];
uint8_t sha_buffer[128];
uint32_t total;
uint32_t last_left;
#endif
} ck_sha_priv_t;
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static ck_sha_priv_t sha_handle[CONFIG_SHA_NUM];
#endif
static uint32_t g_sha_context[CONFIG_SHA_NUM];
bool finish_flag = 0;
/* Driver Capabilities */
static const sha_capabilities_t driver_capabilities = {
.sha1 = 1, /* sha1 mode */
.sha224 = 1, /* sha224 mode */
.sha256 = 1, /* sha256 mode */
.sha384 = 1, /* sha384 mode */
.sha512 = 1, /* sha512 mode */
.sha512_224 = 1, /* sha512_224 mode */
.sha512_256 = 1, /* sha512_256 mode */
.endianmode = 1, /* endian mode */
.interruptmode = 1 /* interrupt mode */
};
#define ERR_SHA(errno) (CSI_DRV_ERRNO_SHA_BASE | errno)
#define SHA_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_SHA(EDRV_PARAMETER); \
} \
} while (0)
//
// Functions
//
ck_sha_reg_t *sha_reg = NULL;
volatile static uint8_t sha_int_flag = 1;
extern int32_t target_get_sha_count(void);
extern int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq);
static int32_t sha_set_mode(sha_mode_e mode)
{
sha_reg->SHA_CON &= ~0x7;
sha_reg->SHA_CON |= mode;
return 0;
}
#ifndef CONFIG_SHA_BLOCK_MODE
static int32_t sha_enable_interrupt(void)
{
sha_reg->SHA_CON |= 1 << SHA_INT_ENABLE_OFFSET;
return 0;
}
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static int32_t sha_disable_interrupt(void)
{
sha_reg->SHA_CON &= ~(1 << SHA_INT_ENABLE_OFFSET);
return 0;
}
#endif
#endif
static void sha_clear_interrupt(void)
{
sha_reg->SHA_INTSTATE = 0;
}
static int32_t sha_enable_initial(void)
{
sha_reg->SHA_CON |= 1 << SHA_INIT_OFFSET;
return 0;
}
static int32_t sha_enable_calculate(void)
{
sha_reg->SHA_CON |= 1 << SHA_CAL_OFFSET;
return 0;
}
#ifdef CONFIG_SHA_BLOCK_MODE
static int32_t sha_message_done(void)
{
while((sha_reg->SHA_CON & 0x40));
return 0;
}
#endif
static int32_t sha_select_endian_mode(sha_endian_mode_e mode)
{
sha_reg->SHA_CON &= ~(1 << SHA_ENDIAN_OFFSET);
sha_reg->SHA_CON |= mode << SHA_ENDIAN_OFFSET;
return 0;
}
static int32_t sha_input_data(uint32_t *data, uint32_t length)
{
uint8_t i;
uint32_t tmp;
uint32_t *input_data = (uint32_t *) & (sha_reg->SHA_DATA1);
for (i = 0; i < length; i++) {
memcpy(&tmp, (uint8_t *)(data+i), 4);
*(input_data + i) = tmp;
}
return 0;
}
static int32_t sha_get_data(sha_handle_t handle, uint32_t *data)
{
ck_sha_priv_t *sha_priv = handle;
uint8_t len = 0;
uint8_t i;
uint32_t temp;
uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
/* according to different mode to obtain the hash result */
if (sha_priv->mode == SHA_MODE_1 || sha_priv->mode == SHA_MODE_224 || sha_priv->mode == SHA_MODE_256) {
if (sha_priv->mode == SHA_MODE_1) {
len = 5;
} else if (sha_priv->mode == SHA_MODE_224) {
len = 7;
} else if (sha_priv->mode == SHA_MODE_256) {
len = 8;
}
for (i = 0; i < len; i++) {
temp = *(result + i);
memcpy(&data[i], &temp, 4);
}
} else {
if (sha_priv->mode == SHA_MODE_384) {
len = 6;
} else if (sha_priv->mode == SHA_MODE_512) {
len = 8;
}
uint32_t *resulth = (uint32_t *)&sha_reg->SHA_H0H;
for (i = 0; i < len; i++) {
// data[i << 1] = *(resulth + i);
// data[(i << 1) + 1] = *(result + i);
temp = *(resulth + i);
memcpy(&data[i<<1], &temp, 4);
temp = *(result + i);
memcpy(&data[(i<<1)+1], &temp, 4);
}
}
return 0;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
static int32_t sha_set_data(sha_handle_t handle, uint32_t *data)
{
ck_sha_priv_t *sha_priv = handle;
uint8_t len = 0;
uint8_t i;
uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
/* according to different mode to obtain the hash result */
if (sha_priv->mode == SHA_MODE_1 || sha_priv->mode == SHA_MODE_224 || sha_priv->mode == SHA_MODE_256) {
if (sha_priv->mode == SHA_MODE_1) {
len = 5;
} else if (sha_priv->mode == SHA_MODE_224) {
len = 7;
} else if (sha_priv->mode == SHA_MODE_256) {
len = 8;
}
for (i = 0; i < len; i++) {
*(result + i) = data[i];
}
} else {
if (sha_priv->mode == SHA_MODE_384) {
len = 6;
} else if (sha_priv->mode == SHA_MODE_512) {
len = 8;
}
uint32_t *resulth = (uint32_t *)&sha_reg->SHA_H0H;
for (i = 0; i < len; i++) {
*(resulth + i) = data[i << 1];
*(result + i) = data[(i << 1) + 1] ;
}
}
return 0;
}
#endif
static inline void sha_reverse_order(uint8_t *pdata, int32_t length)
{
uint8_t input_data[length];
uint8_t result[length];
uint32_t tmp = 0;
int32_t i = 0;
memcpy((void *)input_data, (void *)pdata, length);
for (i = 0; i < length; i++) {
tmp = i >> 2;
tmp = tmp << 3;
result[i] = input_data[tmp + 3 - i];
}
memcpy((void *)pdata, (void *)result, length);
}
void ck_sha_irqhandler(int32_t idx)
{
sha_int_flag = 0;
sha_clear_interrupt(); //clear sha interrupt
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
ck_sha_priv_t *sha_priv = &sha_handle[idx];
#else
ck_sha_priv_t *sha_priv = (ck_sha_priv_t *)g_sha_context[idx];
#endif
if (finish_flag != 0) {
if (sha_priv->cb != NULL) {
sha_priv->cb(SHA_EVENT_COMPLETE); //execute the callback function
}
}
}
/**
\brief get sha handle count.
\return sha handle count
*/
int32_t csi_sha_get_instance_count(void)
{
return target_get_sha_count();
}
/**
\brief Initialize SHA Interface. 1. Initializes the resources needed for the SHA interface 2.registers event callback function
\param[in] idx must not exceed return value of csi_sha_get_instance_count()
\param[in] cb_event Pointer to \ref sha_event_cb_t
\return return sha handle if success
*/
sha_handle_t csi_sha_initialize(sha_handle_t handle, sha_event_cb_t cb_event)
{
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t base = 0u;
uint32_t irq;
/* obtain the sha information */
target_get_sha(0, &base, &irq);
ck_sha_priv_t *sha_priv = handle;
memset(sha_priv->state, 0, sizeof(sha_priv->state));
sha_priv->last_left = 0;
sha_priv->total = 0;
g_sha_context[0] = (uint32_t)handle;
#else
if (idx < 0 || idx >= CONFIG_SHA_NUM) {
return NULL;
}
uint32_t base = 0u;
uint32_t irq;
/* obtain the sha information */
int32_t real_idx = target_get_sha(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
ck_sha_priv_t *sha_priv = &sha_handle[idx];
#endif
sha_priv->base = base;
sha_priv->irq = irq;
/* initialize the sha context */
sha_priv->cb = cb_event;
sha_priv->status.busy = 0;
#ifndef CONFIG_SHA_BLOCK_MODE
drv_nvic_enable_irq(sha_priv->irq);
#endif
return (sha_handle_t)sha_priv;
}
/**
\brief De-initialize SHA Interface. stops operation and releases the software resources used by the interface
\param[in] handle sha handle to operate.
\return error code
*/
int32_t csi_sha_uninitialize(sha_handle_t handle)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_priv->cb = NULL;
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
#ifndef CONFIG_SHA_BLOCK_MODE
sha_disable_interrupt();
drv_nvic_disable_irq(sha_priv->irq);
#endif
#endif
return 0;
}
/**
\brief Get driver capabilities.
\param[in] handle sha handle to operate.
\return \ref sha_capabilities_t
*/
sha_capabilities_t csi_sha_get_capabilities(sha_handle_t handle)
{
return driver_capabilities;
}
/**
\brief config sha mode.
\param[in] handle sha handle to operate.
\param[in] mode \ref sha_mode_e
\param[in] endian \ref sha_endian_mode_e
\return error code
*/
int32_t csi_sha_config(sha_handle_t handle, sha_mode_e mode, sha_endian_mode_e endian_mode)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_reg = (ck_sha_reg_t *)(sha_priv->base);
/* config the sha mode */
switch (mode) {
case SHA_MODE_512_256:
case SHA_MODE_512_224:
return ERR_SHA(EDRV_UNSUPPORTED);
case SHA_MODE_1:
case SHA_MODE_224:
case SHA_MODE_256:
case SHA_MODE_384:
case SHA_MODE_512:
sha_priv->mode = mode;
break;
default:
return ERR_SHA(EDRV_PARAMETER);
}
sha_set_mode(mode);
/*config the sha endian mode */
if (endian_mode == SHA_ENDIAN_MODE_LITTLE) {
sha_priv->endian = endian_mode;
sha_select_endian_mode(endian_mode);
} else if (endian_mode == SHA_ENDIAN_MODE_BIG) {
sha_priv->endian = endian_mode;
sha_select_endian_mode(endian_mode);
} else {
return ERR_SHA(EDRV_PARAMETER);
}
#ifndef CONFIG_SHA_BLOCK_MODE
sha_enable_interrupt();
#endif
return 0;
}
/**
\brief start the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\return error code
*/
int32_t csi_sha_starts(sha_handle_t handle, void *context)
{
SHA_NULL_PARAM_CHK(handle);
ck_sha_priv_t *sha_priv = handle;
sha_enable_initial();
sha_priv->status.busy = 1;
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_get_data(handle, (uint32_t *)sha_priv->state);
#endif
return 0;
}
/**
\brief updata the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\param[in] input Pointer to the Source data
\param[in] len the data len
\return error code
*/
#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
static uint8_t sha_buffer[128];
static uint32_t total[2] = {0x0};
static uint32_t last_left = 0;
#endif
int32_t csi_sha_update(sha_handle_t handle, void *context, const void *input, uint32_t len)
{
SHA_NULL_PARAM_CHK(handle);
SHA_NULL_PARAM_CHK(input);
if (len <= 0) {
return ERR_SHA(EDRV_PARAMETER);
}
g_sha_context[0] = (uint32_t)handle;
ck_sha_priv_t *sha_priv = handle;
sha_reg = (ck_sha_reg_t *)(sha_priv->base);
uint32_t block_size;
if (sha_priv->mode < 4) {
block_size = 64;
} else {
block_size = 128;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint8_t *sha_buffer = sha_priv->sha_buffer;
uint32_t last_left = sha_priv->last_left;
sha_set_mode(sha_priv->mode);
uint32_t left = sha_priv->total & (block_size - 1);
uint32_t fill = block_size - left;
uint32_t total_length = sha_priv->total << 3;
sha_priv->total += len;
sha_priv->total &= 0xffffffff;
uint32_t word_left = sha_priv->total & 0x3;
#else
uint32_t left = total[0] & (block_size - 1);
uint32_t fill = block_size - left;
uint32_t total_length = total[0] << 3;
total[0] += len;
total[0] &= 0xffffffff;
uint32_t word_left = total[0] & 0x3;
#endif
uint8_t temp_data[4];
uint32_t j;
if (finish_flag) {
/*calculate the final word*/
for (j = 0; j < 4; j++) {
temp_data[j] = (total_length >> (8 * j)) & 0xff;
}
}
uint8_t *p = (uint8_t *)input;
/* when the text is not aligned by block and len > fill */
if (left && len >= fill) {
if (finish_flag) {
if (sha_priv->endian == SHA_ENDIAN_MODE_BIG) {
memset(&sha_buffer[left], 0x0, len);
sha_buffer[left] = 0x80;
for (j=0; j<4; j++) {
sha_buffer[left + len - 4 + j] = temp_data[3 - j];
}
} else {
memset(&sha_buffer[left + 4 - last_left], 0x0, len - 4 + last_left);
sha_buffer[left - last_left + 3 - last_left] = 0x80;
for (j = 1; j < 4 - last_left; j++) {
sha_buffer[left - last_left + 3 - last_left - j] = 0x00;
}
for (j=0; j<4; j++) {
sha_buffer[left + len - 4 + j] = temp_data[j];
}
}
} else {
if (last_left && sha_priv->endian == SHA_ENDIAN_MODE_LITTLE) {
uint32_t i;
for (i = 0; i < 4 - last_left; i++) {
*(sha_buffer + left + 3 - last_left - i) = *((uint8_t *)p + 3 - last_left - i);
}
fill = fill - 4 + last_left;
p = (p + 4 - last_left);
}
else if (last_left) {
memcpy((void *)(sha_buffer + left + 4 - last_left), p, fill);
} else {
memcpy((void *)(sha_buffer + left), p, fill);
}
p += fill;
}
/* set the input data */
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_set_data(handle, (uint32_t *)sha_priv->state);
#endif
sha_input_data((uint32_t *)sha_buffer, block_size >> 2);
sha_enable_calculate();
#ifdef CONFIG_SHA_BLOCK_MODE
sha_message_done();
#else
while (sha_int_flag);
sha_int_flag = 1;
#endif
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_get_data(handle, (uint32_t *)sha_priv->state);
#endif
len -= fill;
left = 0;
} else {
if (finish_flag) {
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
memset(sha_buffer, 0, sizeof(sha_priv->sha_buffer));
#else
memset(sha_buffer, 0, sizeof(sha_buffer));
#endif
if (sha_priv->endian == SHA_ENDIAN_MODE_BIG) {
sha_buffer[0] = 0x80;
for (j = 0; j < 4; j++) {
sha_buffer[block_size - 4 + j] = temp_data[3 - j];
}
} else {
sha_buffer[3 - last_left] = 0x80;
for (j = 0; j < 4; j++) {
sha_buffer[block_size - 4 + j] = temp_data[j];
}
}
}
}
/* calculate the hash by block */
while (len >= block_size) {
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_set_data(handle, (uint32_t *)sha_priv->state);
#endif
if (finish_flag) {
if (fill == block_size) {
sha_input_data((uint32_t *)sha_buffer, block_size >> 2);
} else {
sha_input_data((uint32_t *)&sha_buffer[block_size], block_size >> 2);
}
}
else {
sha_input_data((uint32_t *)p, block_size >> 2);
p += block_size;
}
sha_enable_calculate();
#ifdef CONFIG_SHA_BLOCK_MODE
sha_message_done();
#else
while (sha_int_flag);
sha_int_flag = 1;
#endif
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_get_data(handle, (uint32_t *)sha_priv->state);
#endif
len -= block_size;
}
/* when the text is not aligned by block and len < fill */
if (len > 0) {
if (sha_priv->endian == SHA_ENDIAN_MODE_BIG || word_left == 0) {
memcpy((void *)(sha_buffer + left), p, len);
} else {
memcpy((void *)(sha_buffer + left), p, len + 4 - word_left);
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_priv->last_left = word_left;
#else
last_left = word_left;
#endif
}
}
sha_priv->status.busy = 0;
return 0;
}
/**
\brief finish the engine
\param[in] handle sha handle to operate.
\param[in] context Pointer to the sha context.
\param[out] output Pointer to the dest data
\return error code
*/
//static uint32_t total_length;
int32_t csi_sha_finish(sha_handle_t handle, void *context, void *output)
{
SHA_NULL_PARAM_CHK(handle);
SHA_NULL_PARAM_CHK(output);
ck_sha_priv_t *sha_priv = handle;
uint32_t block_size;
uint8_t message_len;
if (sha_priv->mode < 4) {
block_size = 64;
message_len = 8;
} else {
block_size = 128;
message_len = 16;
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
uint32_t last = sha_priv->total & (block_size - 1);
uint32_t padn = (last < (block_size - message_len)) ? (block_size - last) : (block_size + block_size - last);
#else
uint32_t last = total[0] & (block_size - 1);
uint32_t padn = (last < (block_size - message_len)) ? (block_size - last) : (block_size + block_size - last);
#endif
finish_flag = 1;
csi_sha_update(handle, NULL, output, padn);
/* get the hash result */
sha_get_data(handle, (uint32_t *)output);
uint8_t *p = output;
/* convert the data endian according the sha mode */
if (sha_priv->mode == SHA_MODE_1) {
sha_reverse_order(p, 20);
} else if (sha_priv->mode == SHA_MODE_224) {
sha_reverse_order(p, 28);
} else if (sha_priv->mode == SHA_MODE_256) {
sha_reverse_order(p, 32);
} else if (sha_priv->mode == SHA_MODE_512) {
sha_reverse_order(p, 64);
} else if (sha_priv->mode == SHA_MODE_384) {
sha_reverse_order(p, 48);
}
#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
sha_priv->total = 0;
sha_priv->last_left = 0;
#else
total[0] = 0;
last_left = 0;
#endif
finish_flag = 0;
return 0;
}
/**
\brief Get SHA status.
\param[in] handle sha handle to operate.
\return SHA status \ref sha_status_t
*/
sha_status_t csi_sha_get_status(sha_handle_t handle)
{
ck_sha_priv_t *sha_priv = handle;
return sha_priv->status;
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_sha.h
* @brief header file for sha driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_SHA_H_
#define _CK_SHA_H_
#include <stdio.h>
#include "drv_sha.h"
#include "soc.h"
#define SHA_INIT_OFFSET 3
#define SHA_INT_ENABLE_OFFSET 4
#define SHA_ENDIAN_OFFSET 5
#define SHA_CAL_OFFSET 6
typedef struct {
__IOM uint32_t SHA_CON; /* Offset: 0x000 (R/W) Control register */
__IOM uint32_t SHA_INTSTATE; /* Offset: 0x004 (R/W) Instatus register */
__IOM uint32_t SHA_H0L; /* Offset: 0x008 (R/W) H0L register */
__IOM uint32_t SHA_H1L; /* Offset: 0x00c (R/W) H1L register */
__IOM uint32_t SHA_H2L; /* Offset: 0x010 (R/W) H2L register */
__IOM uint32_t SHA_H3L; /* Offset: 0x014 (R/W) H3L register */
__IOM uint32_t SHA_H4L; /* Offset: 0x018 (R/W) H4L register */
__IOM uint32_t SHA_H5L; /* Offset: 0x01c (R/W) H5L register */
__IOM uint32_t SHA_H6L; /* Offset: 0x020 (R/W) H6L register */
__IOM uint32_t SHA_H7L; /* Offset: 0x024 (R/W) H7L register */
__IOM uint32_t SHA_H0H; /* Offset: 0x028 (R/W) H0H register */
__IOM uint32_t SHA_H1H; /* Offset: 0x02c (R/W) H1H register */
__IOM uint32_t SHA_H2H; /* Offset: 0x030 (R/W) H2H register */
__IOM uint32_t SHA_H3H; /* Offset: 0x034 (R/W) H3H register */
__IOM uint32_t SHA_H4H; /* Offset: 0x038 (R/W) H4H register */
__IOM uint32_t SHA_H5H; /* Offset: 0x03c (R/W) H5H register */
__IOM uint32_t SHA_H6H; /* Offset: 0x040 (R/W) H6H register */
__IOM uint32_t SHA_H7H; /* Offset: 0x044 (R/W) H7H register */
__IOM uint32_t SHA_DATA1; /* Offset: 0x048 (R/W) DATA1 register */
uint32_t REV[15];
__IOM uint32_t SHA_DATA2; /* Offset: 0x088 (R/W) DATA2 register */
} ck_sha_reg_t;
#endif
typedef enum {
SHA_STATUS_START_END = 0, /* the one time count mode */
SHA_STATUS_START = 1, /* the first time of the cal */
SHA_STATUS_CONTINUE = 2, /* the middle stage of the cal */
SHA_STATUS_END = 3 /* the last time of the cal*/
} enum_sha_status;

View file

@ -0,0 +1,20 @@
choice
prompt "select trng type "
help
select trng type
config TRNG_CK
bool "csky trng"
help
select the ck trng driver
config TRNG_ZX29
bool "zx29 trng"
help
select the zx29 trng driver
config TRNG_XX
bool "example trng"
help
this option for test
endchoice

View file

@ -0,0 +1,233 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_trng.c
* @brief CSI Source File for TRNG Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "drv_trng.h"
#include "ck_trng.h"
#define ERR_TRNG(errno) (CSI_DRV_ERRNO_TRNG_BASE | errno)
#define TRNG_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_TRNG(EDRV_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
trng_event_cb_t cb;
trng_status_t status;
} ck_trng_priv_t;
extern int32_t target_get_trng_count(void);
extern int32_t target_get_trng(int32_t idx, uint32_t *base);
static ck_trng_priv_t trng_handle[CONFIG_TRNG_NUM];
/* Driver Capabilities */
static const trng_capabilities_t driver_capabilities = {
.lowper_mode = 1 /* low power mode */
};
extern int32_t target_get_trng(int32_t idx, uint32_t *base);
extern int32_t target_get_trng_count(void);
//
// Functions
//
ck_trng_reg_t *trng_reg = NULL;
static int32_t trng_enable(void)
{
trng_reg->TCR |= TRNG_EN;
return 0;
}
static int32_t trng_get_data(void)
{
int data = trng_reg->TDR;
return data;
}
static int32_t trng_data_is_ready(void)
{
int flag = (trng_reg->TCR & TRNG_DATA_READY);
return flag;
}
/**
\brief get trng handle count.
\return trng handle count
*/
int32_t csi_trng_get_instance_count(void)
{
return target_get_trng_count();
}
/**
\brief Initialize TRNG Interface. 1. Initializes the resources needed for the TRNG interface 2.registers event callback function
\param[in] idx must not exceed return value of csi_trng_get_instance_count()
\param[in] cb_event Pointer to \ref trng_event_cb_t
\return pointer to trng handle
*/
trng_handle_t csi_trng_initialize(int32_t idx, trng_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
return NULL;
}
/* obtain the trng information */
uint32_t base = 0u;
int32_t real_idx = target_get_trng(idx, &base);
if (real_idx != idx) {
return NULL;
}
ck_trng_priv_t *trng_priv = &trng_handle[idx];
trng_priv->base = base;
/* initialize the trng context */
trng_reg = (ck_trng_reg_t *)(trng_priv->base);
trng_priv->cb = cb_event;
trng_priv->status.busy = 0;
trng_priv->status.data_valid = 0;
return (trng_handle_t)trng_priv;
}
/**
\brief De-initialize TRNG Interface. stops operation and releases the software resources used by the interface
\param[in] handle trng handle to operate.
\return error code
*/
int32_t csi_trng_uninitialize(trng_handle_t handle)
{
TRNG_NULL_PARAM_CHK(handle);
ck_trng_priv_t *trng_priv = handle;
trng_priv->cb = NULL;
return 0;
}
/**
\brief Get driver capabilities.
\param[in] trng handle to operate.
\return \ref trng_capabilities_t
*/
trng_capabilities_t csi_trng_get_capabilities(trng_handle_t handle)
{
return driver_capabilities;
}
/**
\brief Get data from the TRNG.
\param[in] handle trng handle to operate.
\param[out] data Pointer to buffer with data get from TRNG
\param[in] num Number of data items to obtain
\return error code
*/
int32_t csi_trng_get_data(trng_handle_t handle, void *data, uint32_t num)
{
TRNG_NULL_PARAM_CHK(handle);
TRNG_NULL_PARAM_CHK(data);
TRNG_NULL_PARAM_CHK(num);
ck_trng_priv_t *trng_priv = handle;
trng_priv->status.busy = 1U;
trng_priv->status.data_valid = 0U;
uint8_t left_len = (uint32_t)data & 0x3;
uint32_t result = 0;
/* if the data addr is not aligned by word */
if (left_len) {
trng_enable();
while (!trng_data_is_ready());
result = trng_get_data();
/* wait the data is ready */
while (trng_data_is_ready());
if (num > (4 - left_len)) {
memcpy(data, &result, 4 - left_len);
} else {
memcpy(data, &result, num);
trng_priv->status.busy = 0U;
trng_priv->status.data_valid = 1U;
if (trng_priv->cb) {
trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
}
return 0;
}
num -= (4 - left_len);
data += (4 - left_len);
}
uint32_t word_len = num >> 2;
left_len = num & 0x3;
/* obtain the data by word */
while (word_len--) {
trng_enable();
while (!trng_data_is_ready());
result = trng_get_data();
while (trng_data_is_ready());
*(uint32_t *)data = result;
data = (void *)((uint32_t)data + 4);
}
/* if the num is not aligned by word */
if (left_len) {
trng_enable();
while (!trng_data_is_ready());
result = trng_get_data();
while (trng_data_is_ready());
memcpy(data, &result, left_len);
}
trng_priv->status.busy = 0U;
trng_priv->status.data_valid = 1U;
if (trng_priv->cb) {
trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
}
return 0;
}
/**
\brief Get TRNG status.
\param[in] handle trng handle to operate.
\return TRNG status \ref trng_status_t
*/
trng_status_t csi_trng_get_status(trng_handle_t handle)
{
ck_trng_priv_t *trng_priv = handle;
return trng_priv->status;
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_trng.h
* @brief header file for trng driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _CK_TRNG_H_
#define _CK_TRNG_H_
#include "drv_trng.h"
#include "soc.h"
/*
* define the bits for TCR
*/
#define TRNG_EN (1UL << 1)
#define TRNG_LOWPER_MODE (1UL << 2)
#define TRNG_DATA_READY 1
typedef struct {
__IOM uint32_t TCR; /* Offset: 0x000 (W/R) TRNG control register */
__IM uint32_t TDR; /* Offset: 0x004 (R) TRNG Data register */
} ck_trng_reg_t;
#endif

View file

@ -0,0 +1,241 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file osr_trng.c
* @brief CSI Source File for TRNG Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "drv_trng.h"
#include "osr_trng.h"
#define ERR_TRNG(errno) (CSI_DRV_ERRNO_TRNG_BASE | errno)
#define TRNG_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_TRNG(EDRV_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
trng_event_cb_t cb;
trng_status_t status;
} osr_trng_priv_t;
extern int32_t target_get_trng(int32_t idx, uint32_t *base, uint32_t *irq);
static osr_trng_priv_t trng_handle[CONFIG_TRNG_NUM];
/* Driver Capabilities */
static const trng_capabilities_t driver_capabilities = {
.lowper_mode = 0 /* low power mode */
};
//
// Functions
//
osr_trng_reg_t *trng_reg = NULL;
static int32_t trng_disable_irq(void)
{
trng_reg->RBG_CR &= ~TRNG_IRQ_BIT;
return 0;
}
static int32_t trng_enable(void)
{
trng_reg->RBG_CR |= TRNG_EN;
return 0;
}
static int32_t trng_get_data(void)
{
int data = trng_reg->RBG_DR;
return data;
}
static int32_t trng_data_is_ready(void)
{
int flag = (trng_reg->RBG_FIFO_SR & TRNG_DATA_READY);
return flag;
}
/**
\brief Initialize TRNG Interface. 1. Initializes the resources needed for the TRNG interface 2.registers event callback function
\param[in] idx device id
\param[in] cb_event Pointer to \ref trng_event_cb_t
\return pointer to trng handle
*/
trng_handle_t csi_trng_initialize(int32_t idx, trng_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
return NULL;
}
/* obtain the trng information */
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t real_idx = target_get_trng(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
osr_trng_priv_t *trng_priv = &trng_handle[idx];
trng_priv->base = base;
trng_priv->irq = irq;
/* initialize the trng context */
trng_reg = (osr_trng_reg_t *)(trng_priv->base);
trng_priv->cb = cb_event;
trng_priv->status.busy = 0;
trng_priv->status.data_valid = 0;
trng_disable_irq();
return (trng_handle_t)trng_priv;
}
/**
\brief De-initialize TRNG Interface. stops operation and releases the software resources used by the interface
\param[in] handle trng handle to operate.
\return error code
*/
int32_t csi_trng_uninitialize(trng_handle_t handle)
{
TRNG_NULL_PARAM_CHK(handle);
osr_trng_priv_t *trng_priv = handle;
trng_priv->cb = NULL;
return 0;
}
/**
\brief Get driver capabilities.
\param[in] idx device id.
\return \ref trng_capabilities_t
*/
//trng_capabilities_t csi_trng_get_capabilities(int32_t idx)
trng_capabilities_t csi_trng_get_capabilities(trng_handle_t handle)
{
/*
if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
trng_capabilities_t ret;
memset(&ret, 0, sizeof(trng_capabilities_t));
return ret;
}*/
return driver_capabilities;
}
/**
\brief Get data from the TRNG.
\param[in] handle trng handle to operate.
\param[out] data Pointer to buffer with data get from TRNG
\param[in] num Number of data items to obtain
\return error code
*/
int32_t csi_trng_get_data(trng_handle_t handle, void *data, uint32_t num)
{
TRNG_NULL_PARAM_CHK(handle);
TRNG_NULL_PARAM_CHK(data);
TRNG_NULL_PARAM_CHK(num);
osr_trng_priv_t *trng_priv = handle;
trng_priv->status.busy = 1U;
trng_priv->status.data_valid = 0U;
uint8_t left_len = (uint32_t)data & 0x3;
uint32_t result = 0;
trng_enable();
/* if the data addr is not aligned by word */
if (left_len) {
while (!trng_data_is_ready());
result = trng_get_data();
if (num > (4 - left_len)) {
memcpy(data, &result, 4 - left_len);
} else {
memcpy(data, &result, num);
trng_priv->status.busy = 0U;
trng_priv->status.data_valid = 1U;
if (trng_priv->cb) {
//trng_priv->cb(0, TRNG_EVENT_DATA_GENERATE_COMPLETE);
trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
}
return 0;
}
num -= (4 - left_len);
data += (4 - left_len);
}
uint32_t word_len = num >> 2;
left_len = num & 0x3;
/* obtain the data by word */
while (word_len--) {
while (!trng_data_is_ready());
result = trng_get_data();
*(uint32_t *)data = result;
data = (void *)((uint32_t)data + 4);
}
/* if the num is not aligned by word */
if (left_len) {
while (!trng_data_is_ready());
result = trng_get_data();
memcpy(data, &result, left_len);
}
trng_priv->status.busy = 0U;
trng_priv->status.data_valid = 1U;
if (trng_priv->cb) {
//trng_priv->cb(0, TRNG_EVENT_DATA_GENERATE_COMPLETE);
trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
}
return 0;
}
/**
\brief Get TRNG status.
\param[in] handle trng handle to operate.
\return TRNG status \ref trng_status_t
*/
trng_status_t csi_trng_get_status(trng_handle_t handle)
{
if (handle == NULL) {
trng_status_t ret;
memset(&ret, 0, sizeof(trng_status_t));
return ret;
}
osr_trng_priv_t *trng_priv = handle;
return trng_priv->status;
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file osr_trng.h
* @brief header file for trng driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _OSR_TRNG_H_
#define _OSR_TRNG_H_
#include "drv_trng.h"
#include "soc.h"
/*
* define the bits for TCR
*/
#define TRNG_EN (1UL << 0)
#define TRNG_DATA_READY (0xff << 16)
#define TRNG_IRQ_BIT (1UL << 24)
typedef struct {
__IOM uint32_t RBG_CR; /* Offset: 0x000 (W/R) RBG control register */
__IOM uint32_t RBG_RTCR; /* Offset: 0x004 (W/R) RBG mode selection register */
__IOM uint32_t RBG_SR; /* Offset: 0x008 (W/R) RBG status register */
__IM uint32_t RBG_DR; /* Offset: 0x00c ( /R) RBG data register */
uint32_t Reserved[4];
__IOM uint32_t RBG_FIFO_CR; /* Offset: 0x020 (W/R) FIFO control register */
__IM uint32_t RBG_FIFO_SR; /* Offset: 0x024 ( /R) FIFO status register */
} osr_trng_reg_t;
#endif

View file

@ -0,0 +1,25 @@
choice
prompt "select usart type "
help
select usart type
config USART_DW
bool "designware usart"
help
select the dw usart driver
config USART_CK
bool "csky usart"
help
select the ck usart driver
config USART_SILAN
bool "silan usart"
help
select the silan usart driver
config USART_ZX29
bool "zx29 usart"
help
select the zx29 usart driver
endchoice

View file

@ -0,0 +1,710 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_usart.c
* @brief CSI Source File for usart Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdbool.h>
#include "csi_core.h"
#include "drv_usart.h"
#include "ck_usart.h"
#include "soc.h"
#define ERR_USART(errno) (CSI_DRV_ERRNO_USART_BASE | errno)
/*
* setting config may be accessed when the USART is not
* busy(USR[0]=0) and the DLAB bit(LCR[7]) is set.
*/
#define WAIT_USART_IDLE(addr)\
do { \
int32_t timecount = 0; \
while ((addr->USR & USR_UART_BUSY) && (timecount < UART_BUSY_TIMEOUT)) {\
timecount++;\
}\
if (timecount >= UART_BUSY_TIMEOUT) {\
return ERR_USART(EDRV_TIMEOUT);\
} \
} while(0)
#define USART_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_USART(EDRV_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
usart_event_cb_t cb_event; ///< Event callback
void *cb_arg;
uint32_t rx_total_num;
uint32_t tx_total_num;
uint8_t *rx_buf;
uint8_t *tx_buf;
volatile uint32_t rx_cnt;
volatile uint32_t tx_cnt;
volatile uint32_t tx_busy;
volatile uint32_t rx_busy;
} dw_usart_priv_t;
extern int32_t target_usart_init(pin_t tx, pin_t rx, uint32_t *base, uint32_t *irq);
static dw_usart_priv_t usart_instance[CONFIG_USART_NUM];
static const usart_capabilities_t usart_capabilities = {
.asynchronous = 1, /* supports USART (Asynchronous) mode */
.synchronous_master = 0, /* supports Synchronous Master mode */
.synchronous_slave = 0, /* supports Synchronous Slave mode */
.single_wire = 0, /* supports USART Single-wire mode */
.event_tx_complete = 1, /* Transmit completed event */
.event_rx_timeout = 0, /* Signal receive character timeout event */
};
/**
\brief set the bautrate of usart.
\param[in] addr usart base to operate.
\param[in] baudrate.
\param[in] apbfreq the frequence of the apb.
\return error code
*/
static int32_t dw_usart_set_baudrate(dw_usart_reg_t *addr, uint32_t baudrate, uint32_t apbfreq)
{
WAIT_USART_IDLE(addr);
/* baudrate=(seriak clock freq)/(16*divisor); algorithm :rounding*/
uint32_t divisor = ((apbfreq * 10) / baudrate) >> 4;
if ((divisor % 10) >= 5) {
divisor = (divisor / 10) + 1;
} else {
divisor = divisor / 10;
}
addr->LCR |= LCR_SET_DLAB;
/* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/
addr->DLL = divisor & 0xff;
addr->DLH = (divisor >> 8) & 0xff;
/*
* The DLAB must be cleared after the baudrate is setted
* to access other registers.
*/
addr->LCR &= (~LCR_SET_DLAB);
return 0;
}
/**
\brief enable or disable parity.
\param[in] addr usart base to operate.
\param[in] parity ODD=8, EVEN=16, or NONE=0.
\return error code
*/
static int32_t dw_usart_set_parity(dw_usart_reg_t *addr, usart_parity_e parity)
{
WAIT_USART_IDLE(addr);
switch (parity) {
case USART_PARITY_NONE:
/*CLear the PEN bit(LCR[3]) to disable parity.*/
addr->LCR &= (~LCR_PARITY_ENABLE);
break;
case USART_PARITY_ODD:
/* Set PEN and clear EPS(LCR[4]) to set the ODD parity. */
addr->LCR |= LCR_PARITY_ENABLE;
addr->LCR &= LCR_PARITY_ODD;
break;
case USART_PARITY_EVEN:
/* Set PEN and EPS(LCR[4]) to set the EVEN parity.*/
addr->LCR |= LCR_PARITY_ENABLE;
addr->LCR |= LCR_PARITY_EVEN;
break;
default:
return ERR_USART(EDRV_USART_PARITY);
}
return 0;
}
/**
\brief set the stop bit.
\param[in] addr usart base to operate.
\param[in] stopbit two possible value: USART_STOP_BITS_1 and USART_STOP_BITS_2.
\return error code
*/
static int32_t dw_usart_set_stopbit(dw_usart_reg_t *addr, usart_stop_bits_e stopbit)
{
WAIT_USART_IDLE(addr);
switch (stopbit) {
case USART_STOP_BITS_1:
/* Clear the STOP bit to set 1 stop bit*/
addr->LCR &= LCR_STOP_BIT1;
break;
case USART_STOP_BITS_2:
/*
* If the STOP bit is set "1",we'd gotten 1.5 stop
* bits when DLS(LCR[1:0]) is zero, else 2 stop bits.
*/
addr->LCR |= LCR_STOP_BIT2;
break;
default:
return ERR_USART(EDRV_USART_STOP_BITS);
}
return 0;
}
/**
\brief the transmit data length,and we have four choices:5, 6, 7, and 8 bits.
\param[in] addr usart base to operate.
\param[in] databits the data length that user decides.
\return error code
*/
static int32_t dw_usart_set_databit(dw_usart_reg_t *addr, usart_data_bits_e databits)
{
WAIT_USART_IDLE(addr);
/* The word size decides by the DLS bits(LCR[1:0]), and the
* corresponding relationship between them is:
* DLS word size
* 00 -- 5 bits
* 01 -- 6 bits
* 10 -- 7 bits
* 11 -- 8 bits
*/
switch (databits) {
case USART_DATA_BITS_5:
addr->LCR &= LCR_WORD_SIZE_5;
break;
case USART_DATA_BITS_6:
addr->LCR &= 0xfd;
addr->LCR |= LCR_WORD_SIZE_6;
break;
case USART_DATA_BITS_7:
addr->LCR &= 0xfe;
addr->LCR |= LCR_WORD_SIZE_7;
break;
case USART_DATA_BITS_8:
addr->LCR |= LCR_WORD_SIZE_8;
break;
default:
return ERR_USART(EDRV_USART_DATA_BITS);
}
return 0;
}
/**
\brief get character in query mode.
\param[in] instance usart instance to operate.
\param[in] the pointer to the recieve charater.
\return error code
*/
int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch)
{
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while (!(addr->LSR & LSR_DATA_READY));
*ch = addr->RBR;
return 0;
}
/**
\brief transmit character in query mode.
\param[in] instance usart instance to operate.
\param[in] ch the input charater
\return error code
*/
int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch)
{
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while ((!(addr->LSR & DW_LSR_TRANS_EMPTY)));
addr->THR = ch;
return 0;
}
/**
\brief interrupt service function for transmitter holding register empty.
\param[in] usart_priv usart private to operate.
*/
static void dw_usart_intr_threshold_empty(dw_usart_priv_t *usart_priv)
{
if (usart_priv->tx_total_num == 0) {
return;
}
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
addr->THR = *((uint8_t *)usart_priv->tx_buf);
usart_priv->tx_cnt++;
usart_priv->tx_buf++;
if (usart_priv->tx_cnt >= usart_priv->tx_total_num) {
addr->IER &= (~IER_THRE_INT_ENABLE);
while ((!(addr->LSR & DW_LSR_TEMT)));
usart_priv->tx_cnt = 0;
usart_priv->tx_busy = 0;
usart_priv->tx_buf = NULL;
usart_priv->tx_total_num = 0;
if (usart_priv->cb_event) {
usart_priv->cb_event(USART_EVENT_SEND_COMPLETE, usart_priv->cb_arg);
}
}
}
/**
\brief interrupt service function for receiver data available.
\param[in] usart_priv usart private to operate.
*/
static void dw_usart_intr_recv_data(dw_usart_priv_t *usart_priv)
{
if (usart_priv->cb_event && (usart_priv->rx_total_num == 0)) {
usart_priv->cb_event(USART_EVENT_RECEIVED, usart_priv->cb_arg);
return;
}
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint8_t data = addr->RBR;
if ((usart_priv->rx_total_num == 0) || (usart_priv->rx_buf == NULL)) {
return;
}
*((uint8_t *)usart_priv->rx_buf) = data;
usart_priv->rx_cnt++;
usart_priv->rx_buf++;
if (usart_priv->rx_cnt >= usart_priv->rx_total_num) {
usart_priv->rx_cnt = 0;
usart_priv->rx_buf = NULL;
usart_priv->rx_busy = 0;
usart_priv->rx_total_num = 0;
if (usart_priv->cb_event) {
usart_priv->cb_event(USART_EVENT_RECEIVE_COMPLETE, usart_priv->cb_arg);
}
}
}
/**
\brief the interrupt service function.
\param[in] index of usart instance.
*/
void dw_usart_irqhandler(int32_t idx)
{
dw_usart_priv_t *usart_priv = &usart_instance[idx];
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint8_t intr_state = addr->IIR & 0xf;
switch (intr_state) {
case DW_IIR_THR_EMPTY: /* interrupt source:transmitter holding register empty */
dw_usart_intr_threshold_empty(usart_priv);
break;
case DW_IIR_RECV_DATA: /* interrupt source:receiver data available or receiver fifo trigger level reached */
dw_usart_intr_recv_data(usart_priv);
break;
default:
break;
}
}
/**
\brief Get driver capabilities.
\param[in] handle usart handle to operate.
\return \ref usart_capabilities_t
*/
usart_capabilities_t csi_usart_get_capabilities(usart_handle_t handle)
{
return usart_capabilities;
}
/**
\brief Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function
\param[in] usart pin of tx
\param[in] usart pin of rx
\param[in] cb_event Pointer to \ref usart_event_cb_t
\return return usart handle if success
*/
usart_handle_t csi_usart_initialize(pin_t tx, pin_t rx, usart_event_cb_t cb_event, void *cb_arg)
{
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t idx = target_usart_init(tx, rx, &base, &irq);
if (idx < 0 || idx >= CONFIG_USART_NUM) {
return NULL;
}
dw_usart_priv_t *usart_priv = &usart_instance[idx];
usart_priv->base = base;
usart_priv->irq = irq;
usart_priv->cb_event = cb_event;
usart_priv->cb_arg = cb_arg;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
/* enable received data available */
addr->IER = IER_RDA_INT_ENABLE;
drv_nvic_enable_irq(usart_priv->irq);
return usart_priv;
}
/**
\brief De-initialize UART Interface. stops operation and releases the software resources used by the interface
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_uninitialize(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
drv_nvic_disable_irq(usart_priv->irq);
usart_priv->cb_event = NULL;
return 0;
}
/**
\brief config usart mode.
\param[in] handle usart handle to operate.
\param[in] sysclk configured system clock.
\param[in] mode \ref usart_mode_e
\param[in] parity \ref usart_parity_e
\param[in] stopbits \ref usart_stop_bits_e
\param[in] bits \ref usart_data_bits_e
\param[in] baud configured baud
\return error code
*/
int32_t csi_usart_config(usart_handle_t handle,
uint32_t sysclk,
uint32_t baud,
usart_mode_e mode,
usart_parity_e parity,
usart_stop_bits_e stopbits,
usart_data_bits_e bits)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
/* control the data_bit of the usart*/
int32_t ret = dw_usart_set_baudrate(addr, baud, sysclk);
if (ret < 0) {
return ret;
}
/* control the parity of the usart*/
ret = dw_usart_set_parity(addr, parity);
if (ret < 0) {
return ret;
}
/* control the stopbit of the usart*/
ret = dw_usart_set_stopbit(addr, stopbits);
if (ret < 0) {
return ret;
}
ret = dw_usart_set_databit(addr, bits);
if (ret < 0) {
return ret;
}
return 0;
}
/**
\brief config usart default tx value. used in syn mode
\param[in] handle usart handle to operate.
\param[in] value default tx value
\return error code
*/
int32_t csi_usart_set_default_tx_value(usart_handle_t handle, uint32_t value)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Start sending data to UART transmitter,(received data is ignored).
The function is non-blocking,UART_EVENT_TRANSFER_COMPLETE is signaled when transfer completes.
csi_usart_get_status can indicates if transmission is still in progress or pending
\param[in] handle usart handle to operate.
\param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
\param[in] num Number of data items to send
\return error code
*/
int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
if (num == 0) {
return ERR_USART(EDRV_PARAMETER);
}
dw_usart_priv_t *usart_priv = handle;
uint8_t *source = NULL;
source = (uint8_t *)data;
usart_priv->tx_buf = (uint8_t *)data;
usart_priv->tx_total_num = num;
usart_priv->tx_cnt = 0;
usart_priv->tx_busy = 1;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
/* enable the interrupt*/
addr->IER |= IER_THRE_INT_ENABLE;
return 0;
}
/**
\brief Abort Send data to UART transmitter
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_send(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
usart_priv->tx_cnt = usart_priv->tx_total_num;
return 0;
}
/**
\brief Start receiving data from UART receiver.transmits the default value as specified by csi_usart_set_default_tx_value
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return error code
*/
int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
uint8_t *dest = NULL;
dw_usart_priv_t *usart_priv = handle;
dest = (uint8_t *)data;
usart_priv->rx_buf = (uint8_t *)data; // Save receive buffer usart
usart_priv->rx_total_num = num; // Save number of data to be received
usart_priv->rx_cnt = 0;
usart_priv->rx_busy = 1;
return 0;
}
/**
\brief query data from UART receiver FIFO.
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return receive fifo data num
*/
int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
int32_t recv_num = 0;
while (addr->LSR & 0x1) {
*((uint8_t *)data++) = addr->RBR;
recv_num++;
if (recv_num >= num) {
break;
}
}
return recv_num;
}
/**
\brief Abort Receive data from UART receiver
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_receive(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
usart_priv->rx_cnt = usart_priv->rx_total_num;
return 0;
}
/**
\brief Start sending/receiving data to/from UART transmitter/receiver.
\param[in] handle usart handle to operate.
\param[in] data_out Pointer to buffer with data to send to USART transmitter
\param[out] data_in Pointer to buffer for data to receive from USART receiver
\param[in] num Number of data items to transfer
\return error code
*/
int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief abort sending/receiving data to/from USART transmitter/receiver.
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_transfer(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Get USART status.
\param[in] handle usart handle to operate.
\return USART status \ref usart_status_t
*/
usart_status_t csi_usart_get_status(usart_handle_t handle)
{
usart_status_t usart_status;
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
uint32_t line_status_reg = addr->LSR;
usart_status.tx_busy = usart_priv->tx_busy;
usart_status.rx_busy = usart_priv->rx_busy;
if (line_status_reg & DW_LSR_BI) {
usart_status.rx_break = 1;
}
if (line_status_reg & DW_LSR_FE) {
usart_status.rx_framing_error = 1;
}
if (line_status_reg & DW_LSR_PE) {
usart_status.rx_parity_error = 1;
}
return usart_status;
}
/**
\brief control the transmit.
\param[in] handle usart handle to operate.
\param[in] 1 - enable the transmitter. 0 - disable the transmitter
\return error code
*/
int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief control the receive.
\param[in] handle usart handle to operate.
\param[in] 1 - enable the receiver. 0 - disable the receiver
\return error code
*/
int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief control the break.
\param[in] handle usart handle to operate.
\param[in] 1- Enable continuous Break transmission,0 - disable continuous Break transmission
\return error code
*/
int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief flush receive/send data.
\param[in] handle usart handle to operate.
\param[in] type \ref usart_flush_type_e.
\return error code
*/
int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
if (type == USART_FLUSH_WRITE) {
while ((!(addr->LSR & DW_LSR_TEMT)));
} else if (type == USART_FLUSH_READ) {
while (addr->LSR & 0x1) {
addr->RBR;
}
} else {
return ERR_USART(EDRV_PARAMETER);
}
return 0;
}

View file

@ -0,0 +1,89 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file dw_usart.h
* @brief header file for usart driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __CK_USART_H
#define __CK_USART_H
#include <stdio.h>
#include "errno.h"
#include "soc.h"
#define BAUDRATE_DEFAULT 19200
#define UART_BUSY_TIMEOUT 1000000
#define UART_RECEIVE_TIMEOUT 1000
#define UART_TRANSMIT_TIMEOUT 1000
#define UART_MAX_FIFO 0x10
/* UART register bit definitions */
#define USR_UART_BUSY 0x01
#define USR_UART_TFE 0x04
#define USR_UART_RFNE 0x08
#define LSR_DATA_READY 0x01
#define LSR_THR_EMPTY 0x20
#define IER_RDA_INT_ENABLE 0x01
#define IER_THRE_INT_ENABLE 0x02
#define IIR_NO_ISQ_PEND 0x01
#define LCR_SET_DLAB 0x80 /* enable r/w DLR to set the baud rate */
#define LCR_PARITY_ENABLE 0x08 /* parity enabled */
#define LCR_PARITY_EVEN 0x10 /* Even parity enabled */
#define LCR_PARITY_ODD 0xef /* Odd parity enabled */
#define LCR_WORD_SIZE_5 0xfc /* the data length is 5 bits */
#define LCR_WORD_SIZE_6 0x01 /* the data length is 6 bits */
#define LCR_WORD_SIZE_7 0x02 /* the data length is 7 bits */
#define LCR_WORD_SIZE_8 0x03 /* the data length is 8 bits */
#define LCR_STOP_BIT1 0xfb /* 1 stop bit */
#define LCR_STOP_BIT2 0x04 /* 1.5 stop bit */
#define DW_LSR_PFE 0x80
#define DW_LSR_TEMT 0x40
#define DW_LSR_THRE 0x40
#define DW_LSR_BI 0x10
#define DW_LSR_FE 0x08
#define DW_LSR_PE 0x04
#define DW_LSR_OE 0x02
#define DW_LSR_DR 0x01
#define DW_LSR_TRANS_EMPTY 0x20
#define DW_IIR_THR_EMPTY 0x02 /* threshold empty */
#define DW_IIR_RECV_DATA 0x04 /* received data available */
typedef struct {
union {
__IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */
__OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */
__IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */
};
union {
__IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */
__IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */
};
__IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */
__IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */
uint32_t RESERVED0;
__IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */
__IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */
uint32_t RESERVED1[24];
__IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */
} dw_usart_reg_t;
#endif /* __CK_USART_H */

View file

@ -0,0 +1,761 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file dw_usart.c
* @brief CSI Source File for usart Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdbool.h>
#include "csi_core.h"
#include "drv_usart.h"
#include "dw_usart.h"
#include "soc.h"
#define ERR_USART(errno) (CSI_DRV_ERRNO_USART_BASE | errno)
/*
* setting config may be accessed when the USART is not
* busy(USR[0]=0) and the DLAB bit(LCR[7]) is set.
*/
#define WAIT_USART_IDLE(addr)\
do { \
int32_t timecount = 0; \
while ((addr->USR & USR_UART_BUSY) && (timecount < UART_BUSY_TIMEOUT)) {\
timecount++;\
}\
if (timecount >= UART_BUSY_TIMEOUT) {\
return ERR_USART(EDRV_TIMEOUT);\
} \
} while(0)
#define USART_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_USART(EDRV_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
} dw_usart_priv_t;
extern int32_t target_usart_init(pin_t tx, pin_t rx, uint32_t *base, uint32_t *irq);
extern int32_t target_usart_flowctrl_init(pin_t tx_flow, pin_t rx_flow, uint32_t flag);
static dw_usart_priv_t usart_instance[CONFIG_USART_NUM];
static const usart_capabilities_t usart_capabilities = {
.asynchronous = 0, /* supports USART (Asynchronous) mode */
.synchronous_master = 0, /* supports Synchronous Master mode */
.synchronous_slave = 0, /* supports Synchronous Slave mode */
.single_wire = 0, /* supports USART Single-wire mode */
.event_tx_complete = 0, /* Transmit completed event */
.event_rx_timeout = 0, /* Signal receive character timeout event */
};
/**
\brief set the baut drate of usart.
\param[in] addr usart base to operate.
\param[in] baudrate baud rate
\param[in] apbfreq the frequency of the apb.
\return error code
*/
int32_t csi_usart_config_baudrate(usart_handle_t handle, uint32_t baudrate, uint32_t apbfreq)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
#ifdef CONFIG_CHIP_HOBBIT1_2
uint8_t data[16];
csi_usart_receive_query(handle, data, 16);
#endif
WAIT_USART_IDLE(addr);
/* baudrate=(seriak clock freq)/(16*divisor); algorithm :rounding*/
uint32_t divisor = ((apbfreq * 10) / baudrate) >> 4;
if ((divisor % 10) >= 5) {
divisor = (divisor / 10) + 1;
} else {
divisor = divisor / 10;
}
addr->LCR |= LCR_SET_DLAB;
/* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/
addr->DLL = divisor & 0xff;
addr->DLH = (divisor >> 8) & 0xff;
/*
* The DLAB must be cleared after the baudrate is setted
* to access other registers.
*/
addr->LCR &= (~LCR_SET_DLAB);
return 0;
}
/**
\brief config usart mode.
\param[in] handle usart handle to operate.
\param[in] mode \ref usart_mode_e
\return error code
*/
int32_t csi_usart_config_mode(usart_handle_t handle, usart_mode_e mode)
{
if (mode == USART_MODE_ASYNCHRONOUS) {
return 0;
}
return ERR_USART(EDRV_USART_MODE);
}
/**
\brief config usart parity.
\param[in] handle usart handle to operate.
\param[in] parity \ref usart_parity_e
\return error code
*/
int32_t csi_usart_config_parity(usart_handle_t handle, usart_parity_e parity)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
WAIT_USART_IDLE(addr);
switch (parity) {
case USART_PARITY_NONE:
/*CLear the PEN bit(LCR[3]) to disable parity.*/
addr->LCR &= (~LCR_PARITY_ENABLE);
break;
case USART_PARITY_ODD:
/* Set PEN and clear EPS(LCR[4]) to set the ODD parity. */
addr->LCR |= LCR_PARITY_ENABLE;
addr->LCR &= LCR_PARITY_ODD;
break;
case USART_PARITY_EVEN:
/* Set PEN and EPS(LCR[4]) to set the EVEN parity.*/
addr->LCR |= LCR_PARITY_ENABLE;
addr->LCR |= LCR_PARITY_EVEN;
break;
default:
return ERR_USART(EDRV_USART_PARITY);
}
return 0;
}
/**
\brief config usart stop bit number.
\param[in] handle usart handle to operate.
\param[in] stopbits \ref usart_stop_bits_e
\return error code
*/
int32_t dw_usart_config_stopbits(usart_handle_t handle, usart_stop_bits_e stopbit)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
WAIT_USART_IDLE(addr);
switch (stopbit) {
case USART_STOP_BITS_1:
/* Clear the STOP bit to set 1 stop bit*/
addr->LCR &= LCR_STOP_BIT1;
break;
case USART_STOP_BITS_2:
/*
* If the STOP bit is set "1",we'd gotten 1.5 stop
* bits when DLS(LCR[1:0]) is zero, else 2 stop bits.
*/
addr->LCR |= LCR_STOP_BIT2;
break;
default:
return ERR_USART(EDRV_USART_STOP_BITS);
}
return 0;
}
/**
\brief config usart data length.
\param[in] handle usart handle to operate.
\param[in] databits \ref usart_data_bits_e
\return error code
*/
int32_t csi_usart_config_databits(usart_handle_t handle, usart_data_bits_e databits)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
#ifdef CONFIG_CHIP_HOBBIT1_2
uint8_t data[16];
csi_usart_receive_query(handle, data, 16);
#endif
WAIT_USART_IDLE(addr);
/* The word size decides by the DLS bits(LCR[1:0]), and the
* corresponding relationship between them is:
* DLS word size
* 00 -- 5 bits
* 01 -- 6 bits
* 10 -- 7 bits
* 11 -- 8 bits
*/
switch (databits) {
case USART_DATA_BITS_5:
addr->LCR &= LCR_WORD_SIZE_5;
break;
case USART_DATA_BITS_6:
addr->LCR &= 0xfd;
addr->LCR |= LCR_WORD_SIZE_6;
break;
case USART_DATA_BITS_7:
addr->LCR &= 0xfe;
addr->LCR |= LCR_WORD_SIZE_7;
break;
case USART_DATA_BITS_8:
addr->LCR |= LCR_WORD_SIZE_8;
break;
default:
return ERR_USART(EDRV_USART_DATA_BITS);
}
return 0;
}
/**
\brief get character in query mode.
\param[in] handle usart handle to operate.
\param[in] the pointer to the received character if return 0.
\return error code
*/
int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch)
{
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while (!(addr->LSR & LSR_DATA_READY));
*ch = addr->RBR;
return 0;
}
/**
\brief transmit character in query mode.
\param[in] handle usart handle to operate.
\param[in] ch the input character
\return error code
*/
int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch)
{
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
while ((!(addr->LSR & DW_LSR_TRANS_EMPTY)));
addr->THR = ch;
return 0;
}
/**
\brief the interrupt service function.
\param[in] index of usart instance.
*/
void dw_usart_irqhandler(int32_t idx)
{
(void)idx;
}
/**
\brief Get driver capabilities.
\param[in] handle usart handle to operate.
\return \ref usart_capabilities_t
*/
usart_capabilities_t csi_usart_get_capabilities(usart_handle_t handle)
{
return usart_capabilities;
}
/**
\brief Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function
\param[in] usart pin of tx
\param[in] usart pin of rx
\param[in] cb_event Pointer to \ref usart_event_cb_t
\return return usart handle if success
*/
usart_handle_t csi_usart_initialize(pin_t tx, pin_t rx, usart_event_cb_t cb_event, void *cb_arg)
{
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t idx = target_usart_init(tx, rx, &base, &irq);
if (idx < 0 || idx >= CONFIG_USART_NUM) {
return NULL;
}
dw_usart_priv_t *usart_priv = &usart_instance[idx];
usart_priv->base = base;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
/* FIFO enable */
addr->FCR = DW_FCR_FIFOE | DW_FCR_RT_FIFO_HALF;
return usart_priv;
}
/**
\brief De-initialize UART Interface. stops operation and releases the software resources used by the interface
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_uninitialize(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief config usart mode.
\param[in] handle usart handle to operate.
\param[in] sysclk configured system clock.
\param[in] baud baud rate
\param[in] mode \ref usart_mode_e
\param[in] parity \ref usart_parity_e
\param[in] stopbits \ref usart_stop_bits_e
\param[in] bits \ref usart_data_bits_e
\return error code
*/
int32_t csi_usart_config(usart_handle_t handle,
uint32_t sysclk,
uint32_t baud,
usart_mode_e mode,
usart_parity_e parity,
usart_stop_bits_e stopbits,
usart_data_bits_e bits)
{
int32_t ret;
/* control the data_bit of the usart*/
ret = csi_usart_config_baudrate(handle, baud, sysclk);
if (ret < 0) {
return ret;
}
/* control mode of the usart*/
ret = csi_usart_config_mode(handle, mode);
if (ret < 0) {
return ret;
}
/* control the parity of the usart*/
ret = csi_usart_config_parity(handle, parity);
if (ret < 0) {
return ret;
}
/* control the stopbit of the usart*/
ret = dw_usart_config_stopbits(handle, stopbits);
if (ret < 0) {
return ret;
}
ret = csi_usart_config_databits(handle, bits);
if (ret < 0) {
return ret;
}
return 0;
}
/**
\brief config usart default tx value. used in syn mode
\param[in] handle usart handle to operate.
\param[in] value default tx value
\return error code
*/
int32_t csi_usart_set_default_tx_value(usart_handle_t handle, uint32_t value)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Start sending data to UART transmitter,(received data is ignored).
The function is non-blocking,UART_EVENT_TRANSFER_COMPLETE is signaled when transfer completes.
csi_usart_get_status can indicates if transmission is still in progress or pending
\param[in] handle usart handle to operate.
\param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
\param[in] num Number of data items to send
\return error code
*/
int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
USART_NULL_PARAM_CHK(data);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Abort Send data to UART transmitter
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_send(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Start receiving data from UART receiver.transmits the default value as specified by csi_usart_set_default_tx_value
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return error code
*/
int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief query data from UART receiver FIFO.
\param[in] handle usart handle to operate.
\param[out] data Pointer to buffer for data to receive from UART receiver
\param[in] num Number of data items to receive
\return receive fifo data num
*/
int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Abort Receive data from UART receiver
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_receive(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Start sending/receiving data to/from UART transmitter/receiver.
\param[in] handle usart handle to operate.
\param[in] data_out Pointer to buffer with data to send to USART transmitter
\param[out] data_in Pointer to buffer for data to receive from USART receiver
\param[in] num Number of data items to transfer
\return error code
*/
int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief abort sending/receiving data to/from USART transmitter/receiver.
\param[in] handle usart handle to operate.
\return error code
*/
int32_t csi_usart_abort_transfer(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Get USART status.
\param[in] handle usart handle to operate.
\return USART status \ref usart_status_t
*/
usart_status_t csi_usart_get_status(usart_handle_t handle)
{
usart_status_t status = {0};
return status;
}
/**
\brief control the transmit.
\param[in] handle usart handle to operate.
\param[in] 1 - enable the transmitter. 0 - disable the transmitter
\return error code
*/
int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief control the receive.
\param[in] handle usart handle to operate.
\param[in] 1 - enable the receiver. 0 - disable the receiver
\return error code
*/
int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return 0;
}
/**
\brief control the break.
\param[in] handle usart handle to operate.
\param[in] 1- Enable continuous Break transmission,0 - disable continuous Break transmission
\return error code
*/
int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable)
{
USART_NULL_PARAM_CHK(handle);
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief flush receive/send data.
\param[in] handle usart handle to operate.
\param[in] type \ref usart_flush_type_e.
\return error code
*/
int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
if (type == USART_FLUSH_WRITE) {
addr->FCR |= DW_FCR_XFIFOR;
while (addr->FCR & DW_FCR_XFIFOR);
} else if (type == USART_FLUSH_READ) {
addr->FCR |= DW_FCR_RFIFOR;
while (addr->FCR & DW_FCR_RFIFOR);
} else {
return ERR_USART(EDRV_PARAMETER);
}
return 0;
}
/**
\brief control interrupt on/off.
\param[in] handle usart handle to operate.
\param[in] type \ref usart_intr_type_e.
\param[in] flag 0-OFF, 1-ON.
\return error code
*/
int32_t csi_usart_interrupt_on_off(usart_handle_t handle, usart_intr_type_e type, int flag)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Get usart send data count.
\param[in] handle usart handle to operate.
\return number of data bytes transferred
*/
uint32_t csi_usart_get_tx_count(usart_handle_t handle)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief Get usart receive data count.
\param[in] handle usart handle to operate.
\return number of data bytes transferred
*/
uint32_t csi_usart_get_rx_count(usart_handle_t handle)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief control usart power.
\param[in] handle usart handle to operate.
\param[in] state power state.\ref csi_power_stat_e.
\return error code
*/
int32_t csi_usart_power_control(usart_handle_t handle, csi_power_stat_e state)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief config usart flow control type.
\param[in] handle usart handle to operate.
\param[in] flowctrl_type flow control type.\ref usart_flowctrl_type_e.
\param[in] tx_flow The TX flow pin name
\param[in] rx_flow The RX flow pin name
\return error code
*/
int32_t csi_usart_config_flowctrl(usart_handle_t handle,
usart_flowctrl_type_e flowctrl_type,
pin_t tx_flow, pin_t rx_flow)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
int32_t ret;
switch (flowctrl_type) {
case USART_FLOWCTRL_CTS:
return ERR_USART(EDRV_UNSUPPORTED);
case USART_FLOWCTRL_RTS:
return ERR_USART(EDRV_UNSUPPORTED);
case USART_FLOWCTRL_CTS_RTS:
ret = target_usart_flowctrl_init(tx_flow, rx_flow, 1);
if (ret < 0) {
return ERR_USART(EDRV_PARAMETER);
}
WAIT_USART_IDLE(addr);
addr->MCR |= DW_MCR_AFCE | DW_MCR_RTS;
break;
case USART_FLOWCTRL_NONE:
ret = target_usart_flowctrl_init(tx_flow, rx_flow, 0);
if (ret < 0) {
return ERR_USART(EDRV_PARAMETER);
}
WAIT_USART_IDLE(addr);
addr->MCR = 0;
break;
default:
return ERR_USART(EDRV_UNSUPPORTED);
}
return 0;
}
/**
\brief usart modem control.
\param[in] handle usart handle to operate.
\param[in] modem_ctrl modem control action.\ref usart_modem_ctrl_e.
\return error code
*/
int32_t csi_usart_modem_ctrl(usart_handle_t handle, usart_modem_ctrl_e modem_ctrl)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief get usart modem status.
\param[in] handle usart handle to operate.
\param[in] modem_ctrl modem control action.\ref usart_modem_ctrl_e.
\return modem status.\ref usart_modem_stat_t.
*/
usart_modem_stat_t csi_usart_get_modem_stat(usart_handle_t handle)
{
usart_modem_stat_t modem_stat = {0};
return modem_stat;
}
/**
\brief config usart clock Polarity and Phase.
\param[in] handle usart handle to operate.
\param[in] cpol Clock Polarity.\ref usart_cpol_e.
\param[in] cpha Clock Phase.\ref usart_cpha_e.
\return error code
*/
int32_t csi_usart_config_clock(usart_handle_t handle, usart_cpol_e cpol, usart_cpha_e cpha)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief config usart guard time.
\param[in] handle usart handle to operate.
\param[in] num_of_bits guard time in number of bit periods.
\return error code
*/
int32_t csi_usart_config_guard_time(usart_handle_t handle, uint32_t num_of_bits)
{
return ERR_USART(EDRV_UNSUPPORTED);
}
/**
\brief check if usart is readable(data received).
\param[in] handle usart handle to operate.
\return 1 - a character can be read, 0 if nothing to read ,negative for error code
*/
int32_t csi_usart_readable(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
if (addr->LSR & LSR_DATA_READY) {
return 1;
} else {
return 0;
}
}
/**
\brief check if usart is writable(free for data sending).
\param[in] handle usart handle to operate.
\return 1 - a character can be written, 0 - cannot be written ,negative for error code
*/
int32_t csi_usart_writable(usart_handle_t handle)
{
USART_NULL_PARAM_CHK(handle);
dw_usart_priv_t *usart_priv = handle;
dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base);
if (addr->LSR & DW_LSR_TRANS_EMPTY) {
return 1;
} else {
return 0;
}
}

View file

@ -0,0 +1,116 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file dw_usart.h
* @brief header file for usart driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __DW_USART_H
#define __DW_USART_H
#include <stdio.h>
#include "errno.h"
#include "soc.h"
#define BAUDRATE_DEFAULT 19200
#define UART_BUSY_TIMEOUT 1000000
#define UART_RECEIVE_TIMEOUT 1000
#define UART_TRANSMIT_TIMEOUT 1000
#define UART_MAX_FIFO 0x10
/* UART register bit definitions */
#define USR_UART_BUSY 0x01
#define USR_UART_TFE 0x04
#define USR_UART_RFNE 0x08
#define LSR_DATA_READY 0x01
#define LSR_THR_EMPTY 0x20
#define IER_RDA_INT_ENABLE 0x01
#define IER_THRE_INT_ENABLE 0x02
#define IIR_NO_ISQ_PEND 0x01
#define IIR_RECV_LINE_ENABLE 0x04
#define LCR_SET_DLAB 0x80 /* enable r/w DLR to set the baud rate */
#define LCR_PARITY_ENABLE 0x08 /* parity enabled */
#define LCR_PARITY_EVEN 0x10 /* Even parity enabled */
#define LCR_PARITY_ODD 0xef /* Odd parity enabled */
#define LCR_WORD_SIZE_5 0xfc /* the data length is 5 bits */
#define LCR_WORD_SIZE_6 0x01 /* the data length is 6 bits */
#define LCR_WORD_SIZE_7 0x02 /* the data length is 7 bits */
#define LCR_WORD_SIZE_8 0x03 /* the data length is 8 bits */
#define LCR_STOP_BIT1 0xfb /* 1 stop bit */
#define LCR_STOP_BIT2 0x04 /* 1.5 stop bit */
#define DW_LSR_PFE 0x80
#define DW_LSR_TEMT 0x40
#define DW_LSR_THRE 0x40
#define DW_LSR_BI 0x10
#define DW_LSR_FE 0x08
#define DW_LSR_PE 0x04
#define DW_LSR_OE 0x02
#define DW_LSR_DR 0x01
#define DW_LSR_TRANS_EMPTY 0x20
#define DW_FCR_FIFOE 0x01
#define DW_FCR_RFIFOR 0x02
#define DW_FCR_XFIFOR 0x04
#define DW_FCR_RT_FIFO_SINGLE 0x0 << 6 /* rcvr trigger 1 character in the FIFO */
#define DW_FCR_RT_FIFO_QUARTER 0x1 << 6 /* rcvr trigger FIFO 1/4 full */
#define DW_FCR_RT_FIFO_HALF 0x2 << 6 /* rcvr trigger FIFO 1/2 full */
#define DW_FCR_RT_FIFO_LESSTWO 0x3 << 6 /* rcvr trigger FIFO 2 less than full */
#define DW_FCR_TET_FIFO_EMPTY 0x0 << 4 /* tx empty trigger FIFO empty */
#define DW_FCR_TET_FIFO_TWO 0x1 << 4 /* tx empty trigger 2 characters in the FIFO */
#define DW_FCR_TET_FIFO_QUARTER 0x2 << 4 /* tx empty trigger FIFO 1/4 full */
#define DW_FCR_TET_FIFO_HALF 0x3 << 4 /* tx empty trigger FIFO 1/2 full*/
#define DW_IIR_THR_EMPTY 0x02 /* threshold empty */
#define DW_IIR_RECV_DATA 0x04 /* received data available */
#define DW_IIR_RECV_LINE 0x06 /* receiver line status */
#define DW_IIR_CHAR_TIMEOUT 0x0c /* character timeout */
#define DW_MCR_AFCE 0x20 /* Auto Flow Control Enable */
#define DW_MCR_RTS 0x02
typedef struct {
union {
__IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */
__OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */
__IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */
};
union {
__IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */
__IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */
};
union {
__IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */
__OM uint32_t FCR; /* Offset: 0x008 ( /W) FIFO control register */
};
__IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */
__IOM uint32_t MCR; /* Offset: 0x010 (R/W) Modem control register */
__IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */
__IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */
uint32_t RESERVED1[21];
__IOM uint32_t FAR; /* Offset: 0x070 (R/W) FIFO accesss register */
__IM uint32_t TFR; /* Offset: 0x074 (R/ ) transmit FIFO read */
__OM uint32_t RFW; /* Offset: 0x078 ( /W) receive FIFO write */
__IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */
__IM uint32_t TFL; /* Offset: 0x080 (R/ ) transmit FIFO level */
__IM uint32_t RFL; /* Offset: 0x084 (R/ ) receive FIFO level */
} dw_usart_reg_t;
#endif /* __DW_USART_H */

View file

@ -0,0 +1,11 @@
choice
prompt "select wdt type "
help
select wdt type
config WDT_DW
bool "designware wdt"
help
select the dw wdt driver
endchoice

View file

@ -0,0 +1,259 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file dw_wdt.c
* @brief CSI Source File for WDT Driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdio.h>
#include "drv_wdt.h"
#include "dw_wdt.h"
#include "soc.h"
#include "csi_core.h"
#define ERR_WDT(errno) (CSI_DRV_ERRNO_WDT_BASE | errno)
static uint32_t timeout_ms[16] = {4, 7, 13, 26, 52, 105, 210, 419, 839, 1678, 3355, 6711,
13422, 26844, 53687, 107374
};
#define WDT_NULL_PARAM_CHK(para) \
do { \
if (para == NULL) { \
return ERR_WDT(EDRV_PARAMETER); \
} \
} while (0)
typedef struct {
uint32_t base;
uint32_t irq;
wdt_event_cb_t cb_event;
} dw_wdt_priv_t;
extern int32_t target_get_wdt_count(void);
extern int32_t target_get_wdt(int32_t idx, uint32_t *base, uint32_t *irq);
static dw_wdt_priv_t wdt_instance[CONFIG_WDT_NUM];
/* Driver Capabilities */
static const wdt_capabilities_t wdt_capabilities = {
.interrupt = 1, ///< supports interrupt
};
static inline void dw_wdt_enable(dw_wdt_reg_t *addr)
{
uint32_t value = addr->WDT_CR;
value |= 1 << 0;
addr->WDT_CR = value;
}
static inline void dw_wdt_disable(dw_wdt_reg_t *addr)
{
uint32_t value = addr->WDT_CR;
value &= ~(1 << 0);
addr->WDT_CR = value;
}
void dw_wdt_irqhandler(int32_t idx)
{
dw_wdt_priv_t *wdt_priv = &wdt_instance[idx];
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
addr->WDT_EOI;
if (wdt_priv->cb_event) {
wdt_priv->cb_event(WDT_EVENT_TIMEOUT);
}
}
/**
\brief get wdt instance count.
\return wdt instance count
*/
int32_t csi_wdt_get_instance_count(void)
{
return target_get_wdt_count();
}
/**
\brief Initialize WDT Interface. 1. Initializes the resources needed for the WDT interface 2.registers event callback function
\param[in] idx must not exceed return value of csi_wdt_get_instance_count()
\param[in] cb_event Pointer to \ref wdt_event_cb_t
\return pointer to wdt instance
*/
wdt_handle_t csi_wdt_initialize(int32_t idx, wdt_event_cb_t cb_event)
{
if (idx < 0 || idx >= CONFIG_WDT_NUM) {
return NULL;
}
uint32_t base = 0u;
uint32_t irq = 0u;
int32_t real_idx = target_get_wdt(idx, &base, &irq);
if (real_idx != idx) {
return NULL;
}
dw_wdt_priv_t *wdt_priv = &wdt_instance[idx];
wdt_priv->base = base;
wdt_priv->irq = irq;
wdt_priv->cb_event = cb_event;
drv_nvic_enable_irq(wdt_priv->irq);
return (wdt_handle_t)wdt_priv;
}
/**
\brief De-initialize WDT Interface. stops operation and releases the software resources used by the interface
\param[in] instance wdt instance to operate.
\return \ref execution_status
*/
int32_t csi_wdt_uninitialize(wdt_handle_t handle)
{
WDT_NULL_PARAM_CHK(handle);
dw_wdt_priv_t *wdt_priv = handle;
wdt_priv->cb_event = NULL;
drv_nvic_disable_irq(wdt_priv->irq);
return 0;
}
/**
\brief Get driver capabilities.
\param[in] wdt instance to operate.
\return \ref wdt_capabilities_t
*/
wdt_capabilities_t csi_wdt_get_capabilities(wdt_handle_t handle)
{
return wdt_capabilities;
}
/**
\brief Set the WDT value. value = (2^t*0xffff * 10^6 /freq)/10^3(t: 0 ~ 15).
\param[in] handle wdt handle to operate.
\param[in] value the timeout value(ms) \ref:timeout_ms[]
\return \ref execution_status
*/
int32_t csi_wdt_set_timeout(wdt_handle_t handle, uint32_t value)
{
WDT_NULL_PARAM_CHK(handle);
uint32_t i = 0u;
for (i = 0; i <= 15 ; i++) {
if (timeout_ms[i] == value) {
break;
}
if (i == 15) {
return ERR_WDT(EDRV_PARAMETER);
}
}
dw_wdt_priv_t *wdt_priv = handle;
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
uint32_t config = addr->WDT_CR;
uint32_t en_stat = 0; /*origin wdt enable status*/
if ((config & 0x1) != 0) {
en_stat = 1;
}
config = 0;
addr->WDT_CR = config;
/*before configuration, must disable wdt first*/
dw_wdt_disable(addr);
i += i << 4;
addr->WDT_TORR = i;
if (en_stat == 1) {
dw_wdt_enable(addr);
csi_wdt_restart(handle);
}
return 0;
}
/**
\brief Start the WDT.
\param[in] handle wdt handle to operate.
\return \ref execution_status
*/
int32_t csi_wdt_start(wdt_handle_t handle)
{
WDT_NULL_PARAM_CHK(handle);
dw_wdt_priv_t *wdt_priv = handle;
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
dw_wdt_enable(addr);
csi_wdt_restart(handle);
return 0;
}
/**
\brief Stop the WDT.
\param[in] handle wdt handle to operate.
\return \ref execution_status
*/
int32_t csi_wdt_stop(wdt_handle_t handle)
{
WDT_NULL_PARAM_CHK(handle);
return ERR_WDT(EDRV_UNSUPPORTED);
}
/**
\brief Restart the WDT.
\param[in] handle wdt handle to operate.
\return \ref execution_status
*/
int32_t csi_wdt_restart(wdt_handle_t handle)
{
WDT_NULL_PARAM_CHK(handle);
dw_wdt_priv_t *wdt_priv = handle;
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
addr->WDT_CRR = DW_WDT_CRR_RESET;
return 0;
}
/**
\brief Read the WDT Current value.
\param[in] handle wdt handle to operate.
\param[in] value Pointer to the Value.
\return \ref execution_status
*/
int32_t csi_wdt_read_current_value(wdt_handle_t handle, uint32_t *value)
{
WDT_NULL_PARAM_CHK(handle);
dw_wdt_priv_t *wdt_priv = handle;
dw_wdt_reg_t *addr = (dw_wdt_reg_t *)(wdt_priv->base);
*value = addr->WDT_CCVR;
return 0;
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file dw_wdt.h
* @brief header file for wdt driver
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef __DW_WDT_H
#define __DW_WDT_H
#include <stdio.h>
#include "soc.h"
#define DW_WDT_CRR_RESET 0x76
typedef struct {
__IOM uint8_t WDT_CR:5; /* Offset: 0x000 (R/W) WDT control register */
uint8_t RESERVED0[3];
__IOM uint8_t WDT_TORR; /* Offset: 0x004 (R/W) WDT timeout range register */
uint8_t RESERVED1[3];
__IM uint32_t WDT_CCVR; /* Offset: 0x008 (R/ ) WDT current counter value register */
__OM uint8_t WDT_CRR:8; /* Offset: 0x00C ( /W) WDT count restart register */
uint8_t RESERVED2[3];
__IM uint8_t WDT_STAT:1; /* Offset: 0x010 (R/ ) WDT interrupt status register */
uint8_t RESERVED3[3];
__IM uint8_t WDT_EOI:1; /* Offset: 0x014 (R/ ) WDT interrupt clear register */
uint8_t RESERVED4[3];
} dw_wdt_reg_t;
#endif /* __DW_WDT_H */

View file

@ -0,0 +1,14 @@
ifeq ($(CONFIG_PLATFORM_PHOBOS), y)
include $(CSI_DIR)/csi_driver/csky/phobos/csi.mk
endif
ifeq ($(CONFIG_PLATFORM_HOBBIT1_2), y)
include $(CSI_DIR)/csi_driver/csky/hobbit1_2/csi.mk
endif
ifeq ($(CONFIG_PLATFORM_HOBBIT3), y)
include $(CSI_DIR)/csi_driver/csky/hobbit3/csi.mk
endif
include $(CSI_DIR)/csi_driver/csky/common/csi.mk

View file

@ -0,0 +1,5 @@
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/hobbit1_2/include
TEE_SRC += \
$(CSI_DIR)/csi_driver/csky/hobbit1_2/devices.c \
$(CSI_DIR)/csi_driver/csky/hobbit1_2/isr.c \
$(CSI_DIR)/csi_driver/csky/hobbit1_2/pinmux.c

View file

@ -0,0 +1,829 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file devices.c
* @brief source file for the devices
* @version V1.0
* @date 24. August 2017
******************************************************************************/
#include "soc.h"
#include "config.h"
#include <drv_usart.h>
#include <drv_timer.h>
#include <drv_rtc.h>
#include <drv_trng.h>
#include <drv_crc.h>
#include <drv_aes.h>
#include <drv_rsa.h>
#include <drv_eflash.h>
#include <drv_spi.h>
#include <drv_gpio.h>
#include <stdio.h>
#include "pin_name.h"
#include "pinmux.h"
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
#if CONFIG_GPIO
struct {
uint32_t base;
uint32_t irq;
uint32_t pin_num;
port_name_t port;
}
const sg_gpio_config[CONFIG_GPIO_NUM] = {
{CSKY_GPIO0_BASE, GPIOA_IRQn, 28, PORTA},
{CSKY_GPIO1_BASE, GPIOB_IRQn, 4, PORTB},
};
typedef struct {
pin_t gpio_pin;
uint32_t cfg_idx; //idx of sg_gpio_config[]
} gpio_pin_map_t;
const static gpio_pin_map_t s_gpio_pin_map[] = {
{PA0_TRIG0_ACMP1P_TCK, 0},
{PA1_TRIG1_ACMP1N_TMS, 0},
{PA2_TXD0_SPI0MISO, 0},
{PA3_RXD0_SPI0MOSI, 0},
{PA4_CTS0_PWM0_SPI0SCK_TRIG0, 0},
{PA5_RTS0_PWM1_SPI0SSN_TRIG1, 0},
{PB0_SCL0_PWM2_I2SMCLK, 1},
{PB1_SDA0_PWM3_I2SSCK, 1},
{PB2_SPI0SCK_PWM4_I2SWS, 1},
{PB3_SPI0MISO_PWM5_I2SSD, 1},
{PA6_SPI0MOSI_PWM6_SCL0, 0},
{PA7_SPI0SSN_PWM7_SDA0, 0},
{PA8_WKUP_ADC0_ACMP0P, 0},
{PA9_BOOT_ADC1_PWMFAULT, 0},
{PA10_ADC2_TXD0, 0},
{PA11_ACMP0N_ADC3_RXD0, 0},
{PA12_PWM8_TCK_ADC4, 0},
{PA13_PWM9_TMS_ADC5, 0},
{PA14_PWM10_ADC6, 0},
{PA15_PWM11_ADC7, 0},
{PA16_RXD1_ADC8, 0},
{PA17_TXD1_ADC9, 0},
{PA18_SPI1SSN0_ACMP0O, 0},
{PA19_SPI1SSN1_ACMP1O, 0},
{PA20_SPI1SSN2_TRIG0_RXD1, 0},
{PA21_SPI1SCK_TRIG1_TXD1, 0},
{PA22_SPI1MISO_PWM0_ADC10, 0},
{PA23_SPI1MOSI_PWM1_ADC11, 0},
{PA24_TXD2_I2SMCLK_SPI1SSN0, 0},
{PA25_RXD2_I2SSCK_SPI1SSN1, 0},
{PA26_CTS2_I2SWS_ADC12, 0},
{PA27_RTS2_I2SSD_ADC13, 0}
};
int32_t target_gpio_port_init(port_name_t port, uint32_t *base, uint32_t *irq, uint32_t *pin_num)
{
int i;
for (i = 0; i < CONFIG_GPIO_NUM; i++) {
if (sg_gpio_config[i].port == port) {
*base = sg_gpio_config[i].base;
*irq = sg_gpio_config[i].irq;
*pin_num = sg_gpio_config[i].pin_num;
return i;
}
}
return -1;
}
/**
\param[in] instance idx, must not exceed return value of target_get_gpio_count()
\brief get gpio instance.
\return pointer to gpio instance
*/
int32_t target_gpio_pin_init(pin_t gpio_pin, uint32_t *port_idx)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_gpio_pin_map) / sizeof(gpio_pin_map_t); idx++) {
if (s_gpio_pin_map[idx].gpio_pin == gpio_pin) {
*port_idx = s_gpio_pin_map[idx].cfg_idx;
/*pinmux*/
pin_mux(s_gpio_pin_map[idx].gpio_pin, 0xff);
if (idx >= 10) {
return idx - 4;
} else if (idx >= 6) {
return idx - 6;
} else {
return idx;
}
}
}
return -1;
}
#endif
#if CONFIG_TIMER
struct {
uint32_t base;
uint32_t irq;
}
const sg_timer_config[CONFIG_TIMER_NUM] = {
{CSKY_TIM0_BASE, TIMA0_IRQn},
{CSKY_TIM0_BASE + 0x14, TIMA1_IRQn},
{CSKY_TIM1_BASE, TIMB0_IRQn},
{CSKY_TIM1_BASE + 0x14, TIMB1_IRQn}
};
int32_t target_get_timer_count(void)
{
return CONFIG_TIMER_NUM;
}
int32_t target_get_timer(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_timer_count()) {
return NULL;
}
*base = sg_timer_config[idx].base;
*irq = sg_timer_config[idx].irq;
return idx;
}
#endif
#if CONFIG_PMU
struct {
uint32_t base;
uint32_t irq;
}
const sg_pmu_config[CONFIG_PMU_NUM] = {
{CSKY_CLKGEN_BASE, POWM_IRQn}
};
int32_t target_get_pmu(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx > CONFIG_PMU_NUM) {
return -1;
}
*base = sg_pmu_config[idx].base;
*irq = sg_pmu_config[idx].irq;
return idx;
}
#endif
#if CONFIG_RTC
#undef CSKY_PMU_BASE
#define CSKY_PMU_BASE 0x40002000
#define BIT1 (0x1)
struct {
uint32_t base;
uint32_t irq;
}
const sg_rtc_config[CONFIG_RTC_NUM] = {
{CSKY_RTC0_BASE, RTC_IRQn},
{CSKY_RTC1_BASE, RTC1_IRQn}
};
int32_t target_get_rtc_count(void)
{
return CONFIG_RTC_NUM;
}
int32_t target_get_rtc(int32_t idx, uint32_t *base, uint32_t *irq)
{
unsigned int value;
if (idx >= target_get_rtc_count()) {
return NULL;
}
value = readl(CSKY_PMU_BASE);
value &= ~BIT1;
writel(value, CSKY_PMU_BASE);
*base = sg_rtc_config[idx].base;
*irq = sg_rtc_config[idx].irq;
return idx;
}
#endif
#if CONFIG_TRNG
struct {
uint32_t base;
}
const sg_trng_config[CONFIG_TRNG_NUM] = {
{CSKY_TRNG_BASE}
};
/**
\brief get trng instance count.
\return trng instance count
*/
int32_t target_get_trng_count(void)
{
return CONFIG_TRNG_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_trng_count()
\brief get trng instance.
\return pointer to trng instance
*/
int32_t target_get_trng(int32_t idx, uint32_t *base)
{
if (idx >= target_get_trng_count()) {
return NULL;
}
*base = sg_trng_config[idx].base;
return idx;
}
#endif
#if CONFIG_CRC
struct {
uint32_t base;
}
const sg_crc_config[CONFIG_CRC_NUM] = {
{CSKY_CRC_BASE}
};
/**
\brief get crc instance count.
\return crc instance count
*/
int32_t target_get_crc_count(void)
{
return CONFIG_CRC_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_crc_count()
\brief get crc instance.
\return pointer to crc instance
*/
int32_t target_get_crc(int32_t idx, uint32_t *base)
{
if (idx >= target_get_crc_count()) {
return NULL;
}
*base = sg_crc_config[idx].base;
return idx;
}
#endif
#if CONFIG_USART
struct {
uint32_t base;
uint32_t irq;
}
const sg_usart_config[CONFIG_USART_NUM] = {
{CSKY_UART0_BASE, UART0_IRQn},
{CSKY_UART1_BASE, UART1_IRQn},
{CSKY_UART2_BASE, UART2_IRQn},
};
typedef struct {
pin_t tx;
pin_t rx;
pin_t cts;
pin_t rts;
uint16_t cfg_idx; //idx of sg_usart_config[]
uint16_t function;
} usart_pin_map_t;
const static usart_pin_map_t s_usart_pin_map[] = {
{
PA2_TXD0_SPI0MISO,
PA3_RXD0_SPI0MOSI,
-1,
-1,
0,
0
},
{
PA10_ADC2_TXD0,
PA11_ACMP0N_ADC3_RXD0,
-1,
-1,
0,
2
},
{
PA17_TXD1_ADC9,
PA16_RXD1_ADC8,
-1,
-1,
1,
0
},
{
PA21_SPI1SCK_TRIG1_TXD1,
PA20_SPI1SSN2_TRIG0_RXD1,
-1,
-1,
1,
2,
},
{
PA24_TXD2_I2SMCLK_SPI1SSN0,
PA25_RXD2_I2SSCK_SPI1SSN1,
PA26_CTS2_I2SWS_ADC12,
PA27_RTS2_I2SSD_ADC13,
2,
0
},
};
/**
\param[in] instance idx, must not exceed return value of target_get_usart_count()
\brief get usart instance.
\return pointer to usart instance
*/
int32_t target_usart_init(pin_t tx, pin_t rx, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t); idx++) {
if (s_usart_pin_map[idx].tx == tx && s_usart_pin_map[idx].rx == rx) {
*base = sg_usart_config[s_usart_pin_map[idx].cfg_idx].base;
*irq = sg_usart_config[s_usart_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_usart_pin_map[idx].tx, s_usart_pin_map[idx].function);
pin_mux(s_usart_pin_map[idx].rx, s_usart_pin_map[idx].function);
return s_usart_pin_map[idx].cfg_idx;
}
}
return -1;
}
/**
\brief control usart flow.
\param[in] tx_flow The TX flow pin name
\param[in] rx_flow The RX flow pin name
\param[in] flag 0-disable, 1-enable.
\return 0 if setting ready ,negative for error code
*/
int32_t target_usart_flowctrl_init(pin_t tx_flow, pin_t rx_flow, uint32_t flag)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t); idx++) {
if ((s_usart_pin_map[idx].cts == tx_flow) &&(s_usart_pin_map[idx].rts == rx_flow))
break;
}
if (idx >= sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t)) {
return -1;
}
if ((s_usart_pin_map[idx].cts == tx_flow) && flag) {
pin_mux(s_usart_pin_map[idx].cts, s_usart_pin_map[idx].function);
} else if ((s_usart_pin_map[idx].cts == tx_flow) && (flag == 0)) {
pin_mux(s_usart_pin_map[idx].cts, 0xff);
} else {
return -1;
}
if ((s_usart_pin_map[idx].rts == rx_flow) && flag) {
pin_mux(s_usart_pin_map[idx].rts, s_usart_pin_map[idx].function);
} else if ((s_usart_pin_map[idx].rts == rx_flow) && (flag == 0)) {
pin_mux(s_usart_pin_map[idx].rts, 0xff);
} else {
return -1;
}
return 0;
}
#endif
#if CONFIG_SPI
struct {
uint32_t base;
uint32_t irq;
}
const sg_spi_config[CONFIG_SPI_NUM] = {
{CSKY_SPI0_BASE, SPI0_IRQn},
{CSKY_SPI1_BASE, SPI1_IRQn}
};
typedef struct {
pin_t mosi;
pin_t miso;
pin_t sclk;
pin_t ssel;
uint32_t cfg_idx; //idx of sg_iic_config[]
uint16_t function;
} spi_pin_map_t;
const static spi_pin_map_t s_spi_pin_map[] = {
{
PA2_TXD0_SPI0MISO,
PA3_RXD0_SPI0MOSI,
PA4_CTS0_PWM0_SPI0SCK_TRIG0,
PA5_RTS0_PWM1_SPI0SSN_TRIG1,
0,
2
},
{
PB3_SPI0MISO_PWM5_I2SSD,
PA6_SPI0MOSI_PWM6_SCL0,
PB2_SPI0SCK_PWM4_I2SWS,
PA7_SPI0SSN_PWM7_SDA0,
0,
0
},
{
PA22_SPI1MISO_PWM0_ADC10,
PA23_SPI1MOSI_PWM1_ADC11,
PA21_SPI1SCK_TRIG1_TXD1,
PA18_SPI1SSN0_ACMP0O,
1,
0
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_spi_count()
\brief get spi instance.
\return pointer to spi instance
*/
int32_t target_spi_init(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_spi_pin_map) / sizeof(spi_pin_map_t); idx++) {
if (s_spi_pin_map[idx].mosi == mosi && s_spi_pin_map[idx].miso == miso
&& s_spi_pin_map[idx].sclk == sclk && s_spi_pin_map[idx].ssel == ssel) {
*base = sg_spi_config[s_spi_pin_map[idx].cfg_idx].base;
*irq = sg_spi_config[s_spi_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_spi_pin_map[idx].mosi, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].miso, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].sclk, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].ssel, s_spi_pin_map[idx].function);
return s_spi_pin_map[idx].cfg_idx;
}
}
return -1;
}
#endif
#if CONFIG_AES
struct {
uint32_t base;
uint32_t irq;
}
const sg_aes_config[CONFIG_AES_NUM] = {
{CSKY_AES_BASE, AES_IRQn}
};
/**
\brief get aes instance count.
\return aes instance count
*/
int32_t target_get_aes_count(void)
{
return CONFIG_AES_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_aes_count()
\brief get aes instance.
\return pointer to aes instance
*/
int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_aes_count()) {
return NULL;
}
*base = sg_aes_config[idx].base;
*irq = sg_aes_config[idx].irq;
return idx;
}
#endif
#if CONFIG_RSA
struct {
uint32_t base;
uint32_t irq;
}
const sg_rsa_config[CONFIG_RSA_NUM] = {
{CSKY_RSA_BASE, RSA_IRQn}
};
/**
\brief get rsa instance count.
\return rsa instance count
*/
int32_t target_get_rsa_count(void)
{
return CONFIG_RSA_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_rsa_count()
\brief get rsa instance.
\return pointer to rsa instance
*/
int32_t target_get_rsa(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_rsa_count()) {
return NULL;
}
*base = sg_rsa_config[idx].base;
*irq = sg_rsa_config[idx].irq;
return idx;
}
#endif
#if CONFIG_EFLASH
struct {
uint32_t base;
eflash_info_t info;
}
const sg_eflash_config[CONFIG_EFLASH_NUM] = {
{CSKY_EFLASH_CONTROL_BASE, {0x10000000, 0x1003f800, 0x1fc}}
};
/**
\brief get eflash instance count.
\return eflash instance count
*/
int32_t target_get_eflash_count(void)
{
return CONFIG_EFLASH_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_eflash_count()
\brief get eflash instance.
\return pointer to eflash instance
*/
int32_t target_get_eflash(int32_t idx, uint32_t *base, eflash_info_t *info)
{
if (idx >= target_get_eflash_count()) {
return NULL;
}
*base = sg_eflash_config[idx].base;
info->start = sg_eflash_config[idx].info.start;
info->end = sg_eflash_config[idx].info.end;
info->sector_count = sg_eflash_config[idx].info.sector_count;
return idx;
}
#endif
#if CONFIG_WDT
struct {
uint32_t base;
uint32_t irq;
}
const sg_wdt_config[CONFIG_WDT_NUM] = {
{CSKY_WDT_BASE, WDT_IRQn}
};
int32_t target_get_wdt_count(void)
{
return CONFIG_WDT_NUM;
}
int32_t target_get_wdt(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_wdt_count()) {
return NULL;
}
*base = sg_wdt_config[idx].base;
*irq = sg_wdt_config[idx].irq;
return idx;
}
#endif
#if CONFIG_DMAC
struct {
uint32_t base;
uint32_t irq;
}
const sg_dmac_config[CONFIG_DMAC_NUM] = {
{CSKY_DMAC0_BASE, SEU_DMAC_IRQn},
{CSKY_DMAC1_BASE, NONSEU_DMAC_IRQn}
};
int32_t target_get_dmac_count(void)
{
return CONFIG_DMAC_NUM;
}
int32_t target_get_dmac(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_dmac_count()) {
return NULL;
}
*base = sg_dmac_config[idx].base;
*irq = sg_dmac_config[idx].irq;
return idx;
}
#endif
#if CONFIG_IIC
struct {
uint32_t base;
uint32_t irq;
}
const sg_iic_config[CONFIG_IIC_NUM] = {
{CSKY_I2C0_BASE, I2C0_IRQn},
{CSKY_I2C1_BASE, I2C1_IRQn}
};
typedef struct {
pin_t scl;
pin_t sda;
uint16_t cfg_idx; //idx of sg_iic_config[]
uint16_t function;
} iic_pin_map_t;
const static iic_pin_map_t s_iic_pin_map[] = {
{
PB0_SCL0_PWM2_I2SMCLK,
PB1_SDA0_PWM3_I2SSCK,
0,
0
},
{
PA6_SPI0MOSI_PWM6_SCL0,
PA7_SPI0SSN_PWM7_SDA0,
0,
2
},
{
PC0_SCL1_CTS1_PWM10_ADC14,
PC1_SDA1_RTS1_PWM11_ADC15,
1,
0
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_iic_count()
\brief get iic instance.
\return pointer to iic instance
*/
int32_t target_iic_init(pin_t scl, pin_t sda, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_iic_pin_map) / sizeof(iic_pin_map_t); idx++) {
if (s_iic_pin_map[idx].scl == scl && s_iic_pin_map[idx].sda == sda) {
*base = sg_iic_config[s_iic_pin_map[idx].cfg_idx].base;
*irq = sg_iic_config[s_iic_pin_map[idx].cfg_idx].irq;
/*pinmux*/
if (s_iic_pin_map[idx].cfg_idx == 0) {
pin_mux(s_iic_pin_map[idx].scl, s_iic_pin_map[idx].function);
pin_mux(s_iic_pin_map[idx].sda, s_iic_pin_map[idx].function);
}
return s_iic_pin_map[idx].cfg_idx;
}
}
return -1;
}
#endif
#if CONFIG_PWM
struct {
uint32_t base;
uint32_t irq;
}
const sg_pwm_config[CONFIG_PWM_NUM] = {
{CSKY_PWM_BASE, PWM_IRQn},
};
typedef struct {
pin_t pwm_pin;
uint32_t cfg_idx; //idx of sg_pwm_config[]
uint32_t ch_num;
uint16_t function;
} pwm_pin_map_t;
const static pwm_pin_map_t s_pwm_pin_map[] = {
{PA4_CTS0_PWM0_SPI0SCK_TRIG0, 0, 0, 1},
{PA5_RTS0_PWM1_SPI0SSN_TRIG1, 0, 0, 1},
{PB0_SCL0_PWM2_I2SMCLK, 0, 1, 1},
{PB1_SDA0_PWM3_I2SSCK, 0, 1, 1},
{PB2_SPI0SCK_PWM4_I2SWS, 0, 2, 1},
{PB3_SPI0MISO_PWM5_I2SSD, 0, 2, 1},
{PA6_SPI0MOSI_PWM6_SCL0, 0, 3, 1},
{PA7_SPI0SSN_PWM7_SDA0, 0, 3, 1},
{PA12_PWM8_TCK_ADC4, 0, 4, 0},
{PA13_PWM9_TMS_ADC5, 0, 4, 0},
{PA14_PWM10_ADC6, 0, 5, 0},
{PA15_PWM11_ADC7, 0, 5, 0},
{PA22_SPI1MISO_PWM0_ADC10, 0, 0, 1},
{PA23_SPI1MOSI_PWM1_ADC11, 0, 0, 1},
{PC0_SCL1_CTS1_PWM10_ADC14, 0, 5, 2},
{PC1_SDA1_RTS1_PWM11_ADC15, 0, 5, 2}
};
/**
\param[in] instance idx, must not exceed return value of target_get_pwm_count()
\brief get pwm instance.
\return pointer to pwm instance
*/
int32_t target_pwm_init(pin_t pwm_pin, uint32_t *ch_num, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_pwm_pin_map) / sizeof(pwm_pin_map_t); idx++) {
if (s_pwm_pin_map[idx].pwm_pin == pwm_pin) {
*base = sg_pwm_config[s_pwm_pin_map[idx].cfg_idx].base;
*irq = sg_pwm_config[s_pwm_pin_map[idx].cfg_idx].irq;
*ch_num = s_pwm_pin_map[idx].ch_num;
/*pinmux*/
pin_mux(s_pwm_pin_map[idx].pwm_pin, s_pwm_pin_map[idx].function);
return s_pwm_pin_map[idx].cfg_idx;
}
}
return -1;
}
#endif
#if CONFIG_SHA
struct {
uint32_t base;
uint32_t irq;
}
const sg_sha_config[CONFIG_SHA_NUM] = {
{CSKY_SHA_BASE, SHA_IRQn}
};
/**
\brief get sha instance count.
\return sha instance count
*/
int32_t target_get_sha_count(void)
{
return CONFIG_SHA_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_sha_count()
\brief get sha instance.
\return pointer to sha instance
*/
int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_sha_count()) {
return NULL;
}
*base = sg_sha_config[idx].base;
*irq = sg_sha_config[idx].irq;
return idx;
}
#endif

View file

@ -0,0 +1,68 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file ck_sys_freq.h
* @brief header file for setting system frequency.
* @version V1.0
* @date 18. July 2017
******************************************************************************/
#ifndef _CK_SYS_FREQ_H_
#define _CK_SYS_FREQ_H_
#include <stdint.h>
#include "soc.h"
#define PMU_MCLK_SEL (CSKY_CLKGEN_BASE + 0x4)
#define MCLK_REG_VAL 0x8UL
#define PMU_CLK_STABLE (CSKY_CLKGEN_BASE + 0x18)
#define PMU_PLL_CTRL (CSKY_CLKGEN_BASE + 0x2c)
#define TRC_ADDR (CSKY_OTP_BASE + 0x20)
#define TRC_REG_VAL 0x1UL
#define EXTERNAL_CLK_SOURCE 0x8UL
#define EXTERNAL_CLK_16M (EXTERNAL_CLK_SOURCE * 2)
#define EXTERNAL_CLK_24M (EXTERNAL_CLK_SOURCE * 3)
#define EXTERNAL_CLK_32M (EXTERNAL_CLK_SOURCE * 4)
#define EXTERNAL_CLK_40M (EXTERNAL_CLK_SOURCE * 5)
#define EXTERNAL_CLK_48M (EXTERNAL_CLK_SOURCE * 6)
#define CLK_8M_REG_VAL 0xc0202UL
#define CLK_16M_REG_VAL 0xc0204UL
#define CLK_24M_REG_VAL 0xc0206UL
#define CLK_32M_REG_VAL 0xc0208UL
#define CLK_40M_REG_VAL 0xc020aUL
#define CLK_48M_REG_VAL 0xc020cUL
typedef enum {
IHS_CLK = 0, //internal high speed clock
EHS_CLK = 1 //external high speed clock
} clk_gen_t;
typedef enum {
CLK_8M = 0,
CLK_16M = 1,
CLK_24M = 2,
CLK_32M = 3,
CLK_40M = 4,
CLK_48M = 5
} clk_val_t;
void ck_set_sys_freq (clk_gen_t source, clk_val_t val);
#endif /* _CK_SYS_FREQ_H_ */

View file

@ -0,0 +1,83 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pin_name.h
* @brief header file for the pin_name
* @version V1.0
* @date 23. August 2017
******************************************************************************/
#ifndef _PINNAMES_H
#define _PINNAMES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PA0_TRIG0_ACMP1P_TCK = 0,
PA1_TRIG1_ACMP1N_TMS,
PA2_TXD0_SPI0MISO,
PA3_RXD0_SPI0MOSI,
PA4_CTS0_PWM0_SPI0SCK_TRIG0,
PA5_RTS0_PWM1_SPI0SSN_TRIG1,
PB0_SCL0_PWM2_I2SMCLK,
PB1_SDA0_PWM3_I2SSCK,
PB2_SPI0SCK_PWM4_I2SWS,
PB3_SPI0MISO_PWM5_I2SSD,
PA6_SPI0MOSI_PWM6_SCL0,
PA7_SPI0SSN_PWM7_SDA0,
PA8_WKUP_ADC0_ACMP0P,
PA9_BOOT_ADC1_PWMFAULT,
PA10_ADC2_TXD0,
PA11_ACMP0N_ADC3_RXD0,
PA12_PWM8_TCK_ADC4,
PA13_PWM9_TMS_ADC5,
PA14_PWM10_ADC6,
PA15_PWM11_ADC7,
PA16_RXD1_ADC8,
PA17_TXD1_ADC9,
PA18_SPI1SSN0_ACMP0O,
PA19_SPI1SSN1_ACMP1O,
PA20_SPI1SSN2_TRIG0_RXD1,
PA21_SPI1SCK_TRIG1_TXD1,
PA22_SPI1MISO_PWM0_ADC10,
PA23_SPI1MOSI_PWM1_ADC11,
PA24_TXD2_I2SMCLK_SPI1SSN0,
PA25_RXD2_I2SSCK_SPI1SSN1,
PA26_CTS2_I2SWS_ADC12,
PA27_RTS2_I2SSD_ADC13,
PC0_SCL1_CTS1_PWM10_ADC14,
PC1_SDA1_RTS1_PWM11_ADC15,
}
pin_name_t;
typedef enum {
PORTA = 0,
PORTB = 1,
} port_name_t;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,122 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pinmux.h
* @brief Header file for the pinmux
* @version V1.0
* @date 23. August 2017
******************************************************************************/
#ifndef HOBBIT1_2_PINMUX_H
#define HOBBIT1_2_PINMUX_H
#include <stdint.h>
#include "pin_name.h"
void hobbit_ioreuse_initial(void);
int32_t pin_mux(pin_name_t pin, uint16_t function);
/*IOMUX0L function definition */
/* IOMUX0H function definition */
#define PA16_UART1_RX 0x00010000
#define PA17_UART1_TX 0x00020000
#define PA20_UART1_RX 0x00020000
#define PA21_UART1_TX 0x00080000
//use for spi eth
#define PA3_SPI0MOSI 0x00000080
#define PA2_SPI0MISO 0x00000020
#define PA4_SPI0SCK 0x00000200
#define PA5_SPI0SSN 0x00000800
#define PA23_SPI1MOSI 0x00800000
#define PA22_SPI1MISO 0x00400000
#define PA21_SPI1SCK 0x00200000
#define PA18_SPI1SSN0 0x00040000
/* IOMUX1L function definition */
/* flag as identification */
#define GPIO_SET_BIT0 0x00000001
#define GPIO_SET_BIT1 0x00000002
#define GPIO_SET_BIT2 0x00000004
#define GPIO_SET_BIT3 0x00000008
#define GPIO_SET_BIT4 0x00000010
#define GPIO_SET_BIT5 0x00000020
#define GPIO_SET_BIT6 0x00000040
#define GPIO_SET_BIT7 0x00000080
#define GPIO_SET_BIT8 0x00000100
#define GPIO_SET_BIT9 0x00000200
#define GPIO_SET_BIT10 0x00000400
#define GPIO_SET_BIT11 0x00000800
#define GPIO_SET_BIT12 0x00001000
#define GPIO_SET_BIT13 0x00002000
#define GPIO_SET_BIT14 0x00004000
#define GPIO_SET_BIT15 0x00008000
#define GPIO_SET_BIT16 0x00010000
#define GPIO_SET_BIT17 0x00020000
#define GPIO_SET_BIT18 0x00040000
#define GPIO_SET_BIT19 0x00080000
#define GPIO_SET_BIT20 0x00100000
#define GPIO_SET_BIT21 0x00200000
#define GPIO_SET_BIT22 0x00400000
#define GPIO_SET_BIT23 0x00800000
#define GPIO_SET_BIT24 0x01000000
#define GPIO_SET_BIT25 0x02000000
#define GPIO_SET_BIT26 0x04000000
#define GPIO_SET_BIT27 0x08000000
#define GPIO_SET_BIT28 0x10000000
#define GPIO_SET_BIT29 0x20000000
#define GPIO_SET_BIT30 0x40000000
#define GPIO_SET_BIT31 0x80000000
/******************************************************************************
* hobbit1_2 gpio control and gpio reuse function
* selecting regester adddress
******************************************************************************/
#define HOBBIT1_2_GIPO0_PORTCTL_REG 0x50006008
#define HOBBIT1_2_GIPO1_PORTCTL_REG 0x50009008
#define HOBBIT1_2_IOMUX0L_REG 0x50006100
#define HOBBIT1_2_IOMUX0H_REG 0x50006104
#define HOBBIT1_2_IOMUX1L_REG 0x50006108
/*************basic gpio reuse v1.0********************************************
* UART1(PA16,PA17) for bootrom
* UART1(PA20,PA21) for console
******************************************************************************/
#define GPIO0_REUSE_EN (0x00000000)
#define GPIO0_REUSE_DIS (GPIO_SET_BIT16 | GPIO_SET_BIT17)
#define GPIO1_REUSE_EN (0x00000000)
#define IOMUX0L_FUNCTION_SEL (0x00000000)
#define IOMUX0H_FUNCTION_SEL (0x00000000)
#define IOMUX1L_FUNCTION_SEL (0x00000000)
#endif /* HOBBIT_PINMUX_H */

View file

@ -0,0 +1,333 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**************************************************************************//**
* @file soc.h
* @brief CSI Core Peripheral Access Layer Header File for
* CSKYSOC Device Series
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef SOC_H
#define SOC_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SYSTEM_CLOCK
#define SYSTEM_CLOCK (24000000)
#endif
#ifndef IHS_VALUE
#define IHS_VALUE (8000000)
#endif
#ifndef EHS_VALUE
#define EHS_VALUE (8000000)
#endif
/* ------------------------- Interrupt Number Definition ------------------------ */
typedef enum IRQn
{
/* ---------------------- CSKYCK801 Specific Interrupt Numbers --------------------- */
GPIOA_IRQn = 0, /* gpio Interrupt */
CORET_IRQn = 1, /* core Timer Interrupt */
TIMA0_IRQn = 2, /* timerA0 Interrupt */
TIMA1_IRQn = 3, /* timerA1 Interrupt */
I2S_IRQn = 4, /* i2s Interrupt */
WDT_IRQn = 5, /* wdt Interrupt */
UART0_IRQn = 6, /* uart0 Interrupt */
UART1_IRQn = 7, /* uart1 Interrupt */
UART2_IRQn = 8, /* uart2 Interrupt */
I2C0_IRQn = 9, /* i2c0 Interrupt */
I2C1_IRQn = 10, /* i2c1 Interrupt */
SPI1_IRQn = 11, /* spi0 Interrupt */
SPI0_IRQn = 12, /* spi1 Interrupt */
RTC_IRQn = 13, /* rtc Interrupt */
EXTWAK_IRQn = 14, /* extwakeup Interrupt */
ADC_IRQn = 15, /* adc interrupt */
CMP_IRQn = 16, /* cmp interrupt */
SEU_DMAC_IRQn = 17, /* seu dmac Interrupt */
POWM_IRQn = 18, /* powm Interrupt */
PWM_IRQn = 19, /* pwm Interrupt */
SYS_RESET_IRQn = 20, /* system reset Interrupt */
REV_IRQn = 21, /* rev Interrupt */
NONSEU_DMAC_IRQn = 22, /* nonuseu dmac Interrupt */
TIMB0_IRQn = 23, /* timerB0 Interrupt */
TIMB1_IRQn = 24, /* timerB1 Interrupt */
RTC1_IRQn = 25, /* rtc1 Interrupt */
AES_IRQn = 26, /* aes Interrupt */
GPIOB_IRQn = 27, /* trng Interrupt */
RSA_IRQn = 28, /* rsa Interrupt */
SHA_IRQn = 29, /* sha Interrupt */
}
IRQn_Type;
/* ================================================================================ */
/* ================ Processor and Core Peripheral Section ================ */
/* ================================================================================ */
/* -------- Configuration of the CK801 Processor and Core Peripherals ------- */
#define __CK802_REV 0x0000U /* Core revision r0p0 */
#define __MGU_PRESENT 0 /* MGU present or not */
#define __NVIC_PRIO_BITS 2 /* Number of Bits used for Priority Levels */
#define __Vendor_SysTickConfig 0 /* Set to 1 if different SysTick Config is used */
#include "core_ck802.h" /* Processor and core peripherals */
#include "stdint.h"
typedef enum {
CKENUM_DMA_UART0_RX,
CKENUM_DMA_UART0_TX,
CKENUM_DMA_UART1_RX,
CKENUM_DMA_UART1_TX,
CKENUM_DMA_ADC_RX,
CKENUM_DMA_ADC_TX,
CKENUM_DMA_SPI1_RX,
CKENUM_DMA_SPI1_TX,
CKENUM_DMA_SPI0_RX,
CKENUM_DMA_SPI0_TX,
CKENUM_DMA_IIC_RX,
CKENUM_DMA_IIC_TX,
CKENUM_DMA_IIC1_RX,
CKENUM_DMA_IIC1_TX,
CKENUM_DMA_IIS_RX,
CKENUM_DMA_IIS_TX,
CKENUM_DMA_MEMORY
} ckenum_dma_device_e;
/* ================================================================================ */
/* ================ Device Specific Peripheral Section ================ */
/* ================================================================================ */
#if 0
/* ================================================================================ */
/* ============== Universal Asyncronous Receiver / Transmitter (UART) ============= */
/* ================================================================================ */
typedef struct {
union {
__IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */
__OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */
__IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */
};
union {
__IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */
__IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */
};
__IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */
__IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */
__IOM uint32_t MCR; /* Offset: 0x010 (R/W) Modem control register */
__IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */
__IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */
uint32_t RESERVED1[24];
__IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */
} CSKY_UART_TypeDef;
/* ================================================================================ */
/* ============== Inter-Integrated Circuit (IIC) ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t IC_CON; /* Offset: 0x000 (R/W) Receive buffer register */
__IOM uint32_t IC_TAR; /* Offset: 0x004 (R/W) Transmission hold register */
__IOM uint32_t IC_SAR; /* Offset: 0x008 (R/W) Clock frequency division low section register */
__IOM uint32_t IC_HS_MADDR; /* Offset: 0x00c (R/W) Clock frequency division high section register */
__IOM uint32_t IC_DATA_CMD; /* Offset: 0x010 (R/W) Interrupt enable register */
__IOM uint32_t IC_SS_SCL_HCNT; /* Offset: 0x014 (R/W) Interrupt indicia register */
__IOM uint32_t IC_SS_SCL_LCNT; /* Offset: 0x018 (R/W) Transmission control register */
__IOM uint32_t IC_FS_SCL_HCNT; /* Offset: 0x01c (R/W) Modem control register */
__IOM uint32_t IC_FS_SCL_LCNT; /* Offset: 0x020 (R/W) Transmission state register */
__IOM uint32_t IC_HS_SCL_HCNT; /* Offset: 0x024 (R/W) Transmission state register */
__IOM uint32_t IC_HS_SCL_LCNT; /* Offset: 0x028 (R/W) Transmission state register */
__IOM uint32_t IC_INTR_STAT; /* Offset: 0x02c (R) Transmission state register */
__IOM uint32_t IC_INTR_MASK; /* Offset: 0x030 (R/W) Transmission state register */
__IOM uint32_t IC_RAW_INTR_STAT; /* Offset: 0x034 (R) Transmission state register */
__IOM uint32_t IC_RX_TL; /* Offset: 0x038 (R/W) Transmission state register */
__IOM uint32_t IC_TX_TL; /* Offset: 0x03c (R/W) Transmission state register */
__IOM uint32_t IC_CLR_INTR; /* Offset: 0x040 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_UNDER; /* Offset: 0x044 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_OVER; /* Offset: 0x048 (R) Transmission state register */
__IOM uint32_t IC_CLR_TX_OVER; /* Offset: 0x04c (R) Transmission state register */
__IOM uint32_t IC_CLR_RD_REQ; /* Offset: 0x050 (R) Transmission state register */
__IOM uint32_t IC_CLR_TX_ABRT; /* Offset: 0x054 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_DONE; /* Offset: 0x058 (R) Transmission state register */
__IOM uint32_t IC_CLR_ACTIVITY; /* Offset: 0x05c (R) Transmission state register */
__IOM uint32_t IC_CLR_STOP_DET; /* Offset: 0x060 (R) Transmission state register */
__IOM uint32_t IC_CLR_START_DET; /* Offset: 0x064 (R) Transmission state register */
__IOM uint32_t IC_CLR_GEN_CALL; /* Offset: 0x068 (R) Transmission state register */
__IOM uint32_t IC_ENABLE; /* Offset: 0x06c (R/W) Transmission state register */
__IOM uint32_t IC_STATUS; /* Offset: 0x070 (R) Transmission state register */
__IOM uint32_t IC_TXFLR; /* Offset: 0x074 (R) Transmission state register */
__IOM uint32_t IC_RXFLR; /* Offset: 0x078 (R) Transmission state register */
uint32_t RESERVED; /* Offset: 0x014 (R/ ) Transmission state register */
__IOM uint32_t IC_TX_ABRT_SOURCE; /* Offset: 0x080 (R/W) Transmission state register */
__IOM uint32_t IC_SAR1; /* Offset: 0x084 (R/W) Transmission state register */
__IOM uint32_t IC_DMA_CR; /* Offset: 0x088 (R/W) Transmission state register */
__IOM uint32_t IC_DMA_TDLR; /* Offset: 0x08c (R/W) Transmission state register */
__IOM uint32_t IC_DMA_RDLR; /* Offset: 0x090 (R/W) Transmission state register */
__IOM uint32_t IC_SAR2; /* Offset: 0x094 (R/W) Transmission state register */
__IOM uint32_t IC_SAR3; /* Offset: 0x098 (R/W) Transmission state register */
__IOM uint32_t IC_MULTI_SLAVE; /* Offset: 0x09c (R/W) Transmission state register */
__IOM uint32_t IC_GEN_CALL_EN; /* Offset: 0x0a0 (R/W) Transmission state register */
} CSKY_IIC_TypeDef;
/* ================================================================================ */
/* ============== TIMER ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t TxLoadCount; /* Offset: 0x000 (R/W) Receive buffer register */
__IOM uint32_t TxCurrentValue; /* Offset: 0x004 (R) Transmission hold register */
__IOM uint32_t TxControl; /* Offset: 0x008 (R/W) Clock frequency division low section register */
__IOM uint32_t TxEOI; /* Offset: 0x00c (R) Clock frequency division high section register */
__IOM uint32_t TxIntStatus; /* Offset: 0x010 (R) Interrupt enable register */
} CSKY_TIMER_TypeDef;
/* ================================================================================ */
/* ============== TIMER Control ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t TimersIntStatus; /* Offset: 0x000 (R) Interrupt indicia register */
__IOM uint32_t TimerEOI; /* Offset: 0x004 (R) Transmission control register */
__IOM uint32_t TimerRawIntStatus; /* Offset: 0x008 (R) Modem control register */
} CSKY_TIMER_Control_TypeDef;
/* ================================================================================ */
/* ============== GPIO ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t SWPORT_DR; /* Offset: 0x000 (R/W) Interrupt indicia register */
__IOM uint32_t SWPORT_DDR; /* Offset: 0x004 (R/W) Interrupt indicia register */
__IOM uint32_t PORT_CTL; /* Offset: 0x008 (R/W) Interrupt indicia register */
} CKStruct_GPIO, *PCKStruct_GPIO;
typedef struct {
__IOM uint32_t SHA_CON; /* Offset: 0x000 (R/W) Control register */
__IOM uint32_t SHA_INTSTATE; /* Offset: 0x004 (R/W) Instatus register */
__IOM uint32_t SHA_H0L; /* Offset: 0x008 (R/W) H0L register */
__IOM uint32_t SHA_H1L; /* Offset: 0x00c (R/W) H1L register */
__IOM uint32_t SHA_H2L; /* Offset: 0x010 (R/W) H2L register */
__IOM uint32_t SHA_H3L; /* Offset: 0x014 (R/W) H3L register */
__IOM uint32_t SHA_H4L; /* Offset: 0x018 (R/W) H4L register */
__IOM uint32_t SHA_H5L; /* Offset: 0x01c (R/W) H5L register */
__IOM uint32_t SHA_H6L; /* Offset: 0x020 (R/W) H6L register */
__IOM uint32_t SHA_H7L; /* Offset: 0x024 (R/W) H7L register */
__IOM uint32_t SHA_H0H; /* Offset: 0x028 (R/W) H0H register */
__IOM uint32_t SHA_H1H; /* Offset: 0x02c (R/W) H1H register */
__IOM uint32_t SHA_H2H; /* Offset: 0x030 (R/W) H2H register */
__IOM uint32_t SHA_H3H; /* Offset: 0x034 (R/W) H3H register */
__IOM uint32_t SHA_H4H; /* Offset: 0x038 (R/W) H4H register */
__IOM uint32_t SHA_H5H; /* Offset: 0x03c (R/W) H5H register */
__IOM uint32_t SHA_H6H; /* Offset: 0x040 (R/W) H6H register */
__IOM uint32_t SHA_H7H; /* Offset: 0x044 (R/W) H7H register */
__IOM uint32_t SHA_DATA1; /* Offset: 0x048 (R/W) DATA1 register */
uint32_t REV[15];
__IOM uint32_t SHA_DATA2; /* Offset: 0x088 (R/W) DATA2 register */
} CSKY_SHA_TypeDef;
#endif
#define CONFIG_PMU_NUM 1
#define CONFIG_CRC_NUM 1
#define CONFIG_EFLASH_NUM 1
#define CONFIG_IIC_NUM 2
#define CONFIG_TRNG_NUM 1
#define CONFIG_AES_NUM 1
#define CONFIG_RSA_NUM 1
#define CONFIG_SHA_NUM 1
#define CONFIG_SPI_NUM 2
#define CONFIG_PWM_NUM 6
#define CONFIG_TIMER_NUM 4
#define CONFIG_RTC_NUM 2
#define CONFIG_WDT_NUM 1
#define CONFIG_DMAC_NUM 2
#define CONFIG_GPIO_NUM 2
#define CONFIG_GPIO_PIN_NUM 32
#define CONFIG_USART_NUM 3
#define CONFIG_ETH_NUM 2
/* ================================================================================ */
/* ================ Peripheral memory map ================ */
/* ================================================================================ */
/* -------------------------- CHIP memory map ------------------------------- */
#define CSKY_EFLASH_BASE (0x10000000UL)
#define CSKY_SRAM_BASE (0x60000000UL)
/* AHB */
#define CSKY_AHB_ARB_BASE (0x40000000UL)
#define CSKY_DMAC0_BASE (0x40001000UL)
#define CSKY_CLKGEN_BASE (0x40002000UL)
#define CSKY_CRC_BASE (0x40003000UL)
#define CSKY_DMAC1_BASE (0x40004000UL)
#define CSKY_OTP_BASE (0x4003F000UL)
#define CSKY_AES_BASE (0x40006000UL)
#define CSKY_SRAM_SASC_BASE (0x40007000UL)
#define CSKY_SHA_BASE (0x40008000UL)
#define CSKY_TRNG_BASE (0x40009000UL)
#define CSKY_RSA_BASE (0x4000a000UL)
#define CSKY_EFLASH_CONTROL_BASE (0x4003f000UL)
#define CSKY_APB0_BRIDGE_BASE (0x50000000UL)
#define CSKY_APB1_BRIDGE_BASE (0x50010000UL)
/* APB0 */
#define CSKY_WDT_BASE (0x50001000UL)
#define CSKY_SPI0_BASE (0x50002000UL)
#define CSKY_RTC0_BASE (0x50003000UL)
#define CSKY_UART0_BASE (0x50004000UL)
#define CSKY_UART1_BASE (0x50005000UL)
#define CSKY_GPIO0_BASE (0x50006000UL)
#define CSKY_I2C0_BASE (0x50007000UL)
#define CSKY_I2S_BASE (0x50008000UL)
#define CSKY_GPIO1_BASE (0x50009000UL)
#define CSKY_SIPC_BASE (0x5000a000UL)
/* APB1 */
#define CSKY_TIM0_BASE (0x50011000UL)
#define CSKY_SPI1_BASE (0x50012000UL)
#define CSKY_I2C1_BASE (0x50013000UL)
#define CSKY_PWM_BASE (0x50014000UL)
#define CSKY_UART2_BASE (0x50015000UL)
#define CSKY_ADC_CTL_BASE (0x50016000UL)
#define CSKY_CMP_CTL_BASE (0x50017000UL)
#define CSKY_ETB_BASE (0x50018000UL)
#define CSKY_TIM1_BASE (0x50019000UL)
#define CSKY_RTC1_BASE (0x5001a000UL)
#define SHA_CONTEXT_SIZE 224
/* ================================================================================ */
/* ================ Peripheral declaration ================ */
/* ================================================================================ */
#define CSKY_UART1 (( CSKY_UART_TypeDef *) CSKY_UART1_BASE)
#define CSKY_SHA (( CSKY_SHA_TypeDef *) CSKY_SHA_BASE)
#include <config.h>
#ifdef __cplusplus
}
#endif
#endif /* SOC_H */

View file

@ -0,0 +1,229 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file isr.c
* @brief source file for the interrupt server route
* @version V1.0
* @date 25. August 2017
******************************************************************************/
#include <drv_common.h>
#include "config.h"
#include "soc.h"
#ifndef CONFIG_KERNEL_NONE
#include <csi_kernel.h>
#endif
extern void dw_usart_irqhandler(int32_t idx);
extern void dw_timer_irqhandler(int32_t idx);
extern void dw_gpio_irqhandler(int32_t idx);
extern void dw_iic_irqhandler(int32_t idx);
extern void ck_rtc_irqhandler(int32_t idx);
extern void dw_spi_irqhandler(int32_t idx);
extern void dw_wdt_irqhandler(int32_t idx);
extern void ck_dma_irqhandler(int32_t idx);
extern void ck_aes_irqhandler(int32_t idx);
extern void ck_sha_irqhandler(int32_t idx);
extern void xPortSysTickHandler( void );
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#define ATTRIBUTE_ISR
#ifndef CONFIG_KERNEL_NONE
#define CSI_INTRPT_ENTER() csi_kernel_intrpt_enter()
#define CSI_INTRPT_EXIT() csi_kernel_intrpt_exit()
#else
#define CSI_INTRPT_ENTER()
#define CSI_INTRPT_EXIT()
#endif
ATTRIBUTE_ISR void CORET_IRQHandler(void)
{
readl(0xE000E010);
xPortSysTickHandler();
}
#if defined(CONFIG_USART)
ATTRIBUTE_ISR void USART0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART2_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(2);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART3_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(3);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_TIMER)
ATTRIBUTE_ISR void TIMA0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMA1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMB0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(2);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMB1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(3);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_GPIO)
ATTRIBUTE_ISR void GPIO0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_gpio_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void GPIO1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_gpio_irqhandler(1);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_IIC)
ATTRIBUTE_ISR void I2C0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_iic_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void I2C1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_iic_irqhandler(1);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_RTC)
ATTRIBUTE_ISR void RTC_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_rtc_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void RTC1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_rtc_irqhandler(1);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_AES)
ATTRIBUTE_ISR void AES_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_aes_irqhandler(0);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_TRNG)
ATTRIBUTE_ISR void TRNG_IRQHandler(void)
{
CSI_INTRPT_ENTER();
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_RSA)
ATTRIBUTE_ISR void RSA_IRQHandler(void)
{
CSI_INTRPT_ENTER();
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_SPI) && defined(CONFIG_GPIO)
ATTRIBUTE_ISR void SPI0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_spi_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void SPI1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_spi_irqhandler(1);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_WDT)
ATTRIBUTE_ISR void WDT_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_wdt_irqhandler(0);
CSI_INTRPT_EXIT();
}
#endif

View file

@ -0,0 +1,157 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pinmux.c
* @brief source file for the pinmux
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdint.h>
#include "pinmux.h"
#include "pin_name.h"
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
/*******************************************************************************
* function: hobbit_ioreuse_inital
*
* description:
* initial hobbit_pinmux
*******************************************************************************/
void hobbit_ioreuse_initial(void)
{
unsigned int value;
value = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
value &= ~(GPIO0_REUSE_DIS);
writel(value, HOBBIT1_2_GIPO0_PORTCTL_REG);
}
int32_t pin_mux(pin_name_t pin, uint16_t function)
{
unsigned int val = 0;
unsigned int reg_val = 0;
uint8_t offset;
if (function > 3) {
if (pin <= PB3_SPI0MISO_PWM5_I2SSD) {
if (pin <= PA5_RTS0_PWM1_SPI0SSN_TRIG1) {
offset = pin;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, HOBBIT1_2_GIPO0_PORTCTL_REG);
return 0;
} else if (pin >= PB0_SCL0_PWM2_I2SMCLK) {
offset = pin - 6;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO1_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, HOBBIT1_2_GIPO1_PORTCTL_REG);
return 0;
}
}
if ((pin >= PA6_SPI0MOSI_PWM6_SCL0) && (pin <= PA27_RTS2_I2SSD_ADC13)) {
offset = pin - 4;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, HOBBIT1_2_GIPO0_PORTCTL_REG);
return 0;
}
return -1;
}
if ((pin >= PA6_SPI0MOSI_PWM6_SCL0) && (pin <= PA27_RTS2_I2SSD_ADC13)) {
offset = pin - 4;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
val |= (1 << offset);
writel(val, HOBBIT1_2_GIPO0_PORTCTL_REG);
if (pin <= PA11_ACMP0N_ADC3_RXD0) {
offset = pin;
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT1_2_IOMUX0L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX0L_REG);
return 0;
} else {
offset = pin - 16;
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT1_2_IOMUX0H_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX0H_REG);
return 0;
}
}
if ((pin >= PA0_TRIG0_ACMP1P_TCK) && (pin <= PB3_SPI0MISO_PWM5_I2SSD)) {
if (pin >= PB0_SCL0_PWM2_I2SMCLK) {
offset = pin - 6;
val = readl(HOBBIT1_2_GIPO1_PORTCTL_REG);
val |= (1 << offset);
writel(val, HOBBIT1_2_GIPO1_PORTCTL_REG);
offset = pin;
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT1_2_IOMUX0L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX0L_REG);
return 0;
}
if (pin <= PA5_RTS0_PWM1_SPI0SSN_TRIG1) {
offset = pin;
/* gpio data source select */
val = readl(HOBBIT1_2_GIPO0_PORTCTL_REG);
val |= (1 << offset);
writel(val, HOBBIT1_2_GIPO0_PORTCTL_REG);
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT1_2_IOMUX0L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX0L_REG);
return 0;
}
}
if (pin > PA27_RTS2_I2SSD_ADC13) {
offset = pin - PC0_SCL1_CTS1_PWM10_ADC14;
reg_val = (0x3 << (offset *2));
val = readl(HOBBIT1_2_IOMUX1L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT1_2_IOMUX1L_REG);
}
return -1;
}

View file

@ -0,0 +1,5 @@
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/hobbit3/include
TEE_SRC += \
$(CSI_DIR)/csi_driver/csky/hobbit3/devices.c \
$(CSI_DIR)/csi_driver/csky/hobbit3/isr.c \
$(CSI_DIR)/csi_driver/csky/hobbit3/pinmux.c

View file

@ -0,0 +1,804 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file devices.c
* @brief source file for the devices
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <soc.h>
#include <config.h>
#include <drv_usart.h>
#include <stdio.h>
#include <drv_timer.h>
#include <drv_rtc.h>
#include <drv_trng.h>
#include <drv_crc.h>
#include <drv_aes.h>
#include <drv_rsa.h>
#include <drv_eflash.h>
#include <drv_spi.h>
#include <drv_gpio.h>
#include "pin_name.h"
#include "pinmux.h"
//typedef int32_t int32_t;
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
#if 0
struct {
uint32_t base;
uint32_t irq;
}
const sg_usi_config[CONFIG_USI_NUM] = {
{CSKY_USI0_BASE, USI0_IRQn},
{CSKY_USI1_BASE, USI1_IRQn},
};
typedef struct {
int32_t sclk;
int32_t sd0;
int32_t sd1;
int32_t nss;
uint16_t cfg_idx; //idx of sg_usi_config[]
uint16_t function;
} usi_pin_map_t;
const static usi_pin_map_t s_usi_pin_map[] = {
{
PA10_UART0CTS_USI0SCLK_SPU4_I2C0SCL,
PA11_UART0RTS_USI0SD0_SPU5_I2C0SDA,
PA12_XX_USI0SD1_XX_UART2RX,
PA13_XX_USI0NSS_XX_UART2TX,
0,
1
},
{
PA16_SPI0CS0_PWMTRIG0_XX_USI1SCLK,
PA17_SPI0MOSI_PWMTRIG1_XX_USI1SD0,
PA18_SPI0MISO_XX_SPU6_USI1SD1,
PA19_SPI0SCK_FAULT_SPU7_USI1NSS,
1,
3
},
};
#endif
struct {
uint32_t base;
uint32_t irq;
}
const static sg_usart_config[CONFIG_USART_NUM] = {
{CSKY_UART0_BASE, UART0_IRQn},
{CSKY_UART1_BASE, UART1_IRQn},
{CSKY_UART2_BASE, UART2_IRQn},
{CSKY_UART3_BASE, UART3_IRQn}
};
typedef struct {
int32_t tx;
int32_t rx;
#if 0
int32_t cts;
int32_t rts;
#endif
uint16_t cfg_idx; //idx of sg_usart_config[]
uint16_t function;
} usart_pin_map_t;
const static usart_pin_map_t s_usart_pin_map[] = {
{
PA8_UART0TX_XX_SPU2_SIROUT0,
PA9_UART0RX_XX_SPU3_SIRIN0,
0,
0
},
{
PA21_UART1TX_PWM1_SPU9_SIROUT1,
PA20_UART1RX_PWM0_SPU8_SIRIN1,
1,
0
},
{
PA0_I2C0SCL_SPI1CS1_SPU0_UART1TX,
PA1_I2C0SDA_SPI1CS2_SPU1_UART1RX,
1,
4,
},
{
PB0_UART2TX_XX_XX_SIROUT2,
PB1_UART2RX_XX_XX_SIRIN2,
2,
0
},
{
PB13_UART3TX_SPI1MISO_SPU29_SIROUT3,
PB12_UART3RX_SPI1CS0_SPU28_SIRIN3,
3,
0
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_usart_count()
\brief get usart instance.
\return pointer to usart instance
*/
int32_t target_usart_init(pin_t tx, pin_t rx, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t); idx++) {
if (s_usart_pin_map[idx].tx == tx && s_usart_pin_map[idx].rx == rx) {
*base = sg_usart_config[s_usart_pin_map[idx].cfg_idx].base;
*irq = sg_usart_config[s_usart_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_usart_pin_map[idx].tx, s_usart_pin_map[idx].function);
pin_mux(s_usart_pin_map[idx].rx, s_usart_pin_map[idx].function);
return s_usart_pin_map[idx].cfg_idx;
}
}
return -1;
}
/**
\brief control usart flow.
\param[in] tx_flow The TX flow pin name
\param[in] rx_flow The RX flow pin name
\param[in] flag 0-disable, 1-enable.
\return 0 if setting ready ,negative for error code
*/
int32_t target_usart_flowctrl_init(int32_t tx_flow, int32_t rx_flow, uint32_t flag)
{
#if 0
uint32_t idx;
for (idx = 0; idx < sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t); idx++) {
if ((s_usart_pin_map[idx].cts == tx_flow) &&(s_usart_pin_map[idx].rts == rx_flow))
break;
}
if (idx >= sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t)) {
return -1;
}
if ((s_usart_pin_map[idx].cts == tx_flow) && flag) {
pin_mux(s_usart_pin_map[idx].cts, s_usart_pin_map[idx].function);
} else if ((s_usart_pin_map[idx].cts == tx_flow) && (flag == 0)) {
pin_mux(s_usart_pin_map[idx].cts, 0xff);
} else {
return -1;
}
if ((s_usart_pin_map[idx].rts == rx_flow) && flag) {
pin_mux(s_usart_pin_map[idx].rts, s_usart_pin_map[idx].function);
} else if ((s_usart_pin_map[idx].rts == rx_flow) && (flag == 0)) {
pin_mux(s_usart_pin_map[idx].rts, 0xff);
} else {
return -1;
}
return 0;
#endif
return 0;
}
struct {
uint32_t base;
uint32_t irq;
uint32_t pin_num;
port_name_t port;
}
const sg_gpio_config[CONFIG_GPIO_NUM] = {
{CSKY_GPIO0_BASE, GPIOA_IRQn, 32, PORTA},
{CSKY_GPIO1_BASE, GPIOB_IRQn, 16, PORTB}
};
typedef struct {
int32_t gpio_pin;
uint32_t cfg_idx; //idx of sg_gpio_config[]
} gpio_pin_map_t;
const static gpio_pin_map_t s_gpio_pin_map[] = {
{PA0_I2C0SCL_SPI1CS1_SPU0_UART1TX ,0},
{PA1_I2C0SDA_SPI1CS2_SPU1_UART1RX,0},
{PA2_QSPI0CLK_XX_XX_XX,0},
{PA3_QSPI0MISO_XX_XX_XX,0},
{PA4_QSPI0MOSI_XX_XX_XX,0},
{PA5_QSPI0HOLD_XX_XX_XX,0},
{PA6_QSPI0WP_XX_XX_XX,0},
{PA7_QSPI0CS0_XX_XX_XX,0},
{PA8_UART0TX_XX_SPU2_SIROUT0,0},
{PA9_UART0RX_XX_SPU3_SIRIN0,0},
{PA10_UART0CTS_USI0SCLK_SPU4_I2C0SCL,0},
{PA11_UART0RTS_USI0SD0_SPU5_I2C0SDA,0},
{PA12_XX_USI0SD1_XX_UART2RX,0},
{PA13_XX_USI0NSS_XX_UART2TX,0},
{PA14_SPI0CS2_FAULT_I2C1SDA_XX,0},
{PA15_SPI0CS1_XX_I2C1SCL_XX,0},
{PA16_SPI0CS0_PWMTRIG0_XX_USI1SCLK,0},
{PA17_SPI0MOSI_PWMTRIG1_XX_USI1SD0,0},
{PA18_SPI0MISO_XX_SPU6_USI1SD1,0},
{PA19_SPI0SCK_FAULT_SPU7_USI1NSS,0},
{PA20_UART1RX_PWM0_SPU8_SIRIN1,0},
{PA21_UART1TX_PWM1_SPU9_SIROUT1,0},
{PA22_UART1CTS_PWM2_SPU10_XX,0},
{PA23_UART1RTS_PWM3_SPU11_XX,0},
{PA24_USI1NSS_PWM4_SPU12_XX,0},
{PA25_USI1SD1_PWM5_SPU13_XX,0},
{PA26_USI1SD0_PWM6_SPU14_XX,0},
{PA27_USI1SCLK_PWM7_SPU15_XX,0},
{PA28_I2C1SCL_PWM8_SPU16_XX,0},
{PA29_I2C1SDA_PWM9_SPU17_XX,0},
{PA30_I2C0SDA_PWM10_SPU18_XX,0},
{PA31_I2C0SCL_PWM11_SPU19_XX,0},
{PB0_UART2TX_XX_XX_SIROUT2,1},
{PB1_UART2RX_XX_XX_SIRIN2,1},
{PB2_UART2RTS_XX_XX_XX,1},
{PB3_UART2CTS_XX_XX_XX,1},
{PB4_XX_XX_SPU20_UART3TX,1},
{PB5_QSPI1CS1_XX_SPU21_UART3RX,1},
{PB6_QSPI1WP_XX_SPU22_XX,1},
{PB7_QSPI1HOLD_XX_SPU23_XX,1},
{PB8_QSPI1CS0_PWMTRIG0_SPU24_XX,1},
{PB9_QSPI1MOSI_PWMTRIG1_SPU25_XX,1},
{PB10_QSPI1MISO_XX_SPU26_I2C1SDA,1},
{PB11_QSPI1CLK_XX_SPU27_I2C1SCL,1},
{PB12_UART3RX_SPI1CS0_SPU28_SIRIN3,1},
{PB13_UART3TX_SPI1MISO_SPU29_SIROUT3,1},
{PB14_UART3RTS_SPI1MOSI_SPU30_XX,1},
{PB15_UART3CTS_SPI1SCK_SPU31_XX,1}
};
int32_t target_gpio_port_init(port_name_t port, uint32_t *base, uint32_t *irq, uint32_t *pin_num)
{
int i;
for (i = 0; i < CONFIG_GPIO_NUM; i++) {
if (sg_gpio_config[i].port == port) {
*base = sg_gpio_config[i].base;
*irq = sg_gpio_config[i].irq;
*pin_num = sg_gpio_config[i].pin_num;
return i;
}
}
return -1;
}
/**
\param[in] instance idx, must not exceed return value of target_get_gpio_count()
\brief get gpio instance.
\return pointer to gpio instance
*/
int32_t target_gpio_pin_init(int32_t gpio_pin, uint32_t *port_idx)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_gpio_pin_map) / sizeof(gpio_pin_map_t); idx++) {
if (s_gpio_pin_map[idx].gpio_pin == gpio_pin) {
*port_idx = s_gpio_pin_map[idx].cfg_idx;
/*pinmux*/
pin_mux(s_gpio_pin_map[idx].gpio_pin, 0xff);
return idx;
}
}
return -1;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_timer_config[CONFIG_TIMER_NUM] = {
{CSKY_TIM0_BASE, TIMA0_IRQn},
{CSKY_TIM0_BASE + 0x14, TIMA1_IRQn},
{CSKY_TIM1_BASE, TIMB0_IRQn},
{CSKY_TIM1_BASE + 0x14, TIMB1_IRQn},
{CSKY_TIM2_BASE, TIM34567_IRQn},
{CSKY_TIM2_BASE + 0x14, TIM34567_IRQn},
{CSKY_TIM3_BASE, TIM34567_IRQn},
{CSKY_TIM3_BASE + 0x14, TIM34567_IRQn},
{CSKY_TIM4_BASE, TIM34567_IRQn},
{CSKY_TIM4_BASE + 0x14, TIM34567_IRQn},
{CSKY_TIM5_BASE, TIM34567_IRQn},
{CSKY_TIM5_BASE + 0x14, TIM34567_IRQn},
{CSKY_TIM6_BASE, TIM34567_IRQn},
{CSKY_TIM6_BASE + 0x14, TIM34567_IRQn},
};
int32_t target_get_timer_count(void)
{
return CONFIG_TIMER_NUM;
}
int32_t target_get_timer(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_timer_count()) {
return NULL;
}
*base = sg_timer_config[idx].base;
*irq = sg_timer_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_sha_config[CONFIG_SHA_NUM] = {
{CSKY_SHA_BASE, SHA_IRQn}
};
/**
\brief get sha instance count.
\return sha instance count
*/
int32_t target_get_sha_count(void)
{
return CONFIG_SHA_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_sha_count()
\brief get sha instance.
\return pointer to sha instance
*/
int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_sha_count()) {
return NULL;
}
*base = sg_sha_config[idx].base;
*irq = sg_sha_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_rsa_config[CONFIG_RSA_NUM] = {
{CSKY_RSA_BASE, RSA_IRQn}
};
/**
\brief get rsa instance count.
\return rsa instance count
*/
int32_t target_get_rsa_count(void)
{
return CONFIG_RSA_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_rsa_count()
\brief get rsa instance.
\return pointer to rsa instance
*/
int32_t target_get_rsa(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_rsa_count()) {
return NULL;
}
*base = sg_rsa_config[idx].base;
*irq = sg_rsa_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_aes_config[CONFIG_AES_NUM] = {
{CSKY_AES_BASE, AES_IRQn}
};
/**
\brief get aes instance count.
\return aes instance count
*/
int32_t target_get_aes_count(void)
{
return CONFIG_AES_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_aes_count()
\brief get aes instance.
\return pointer to aes instance
*/
int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_aes_count()) {
return NULL;
}
*base = sg_aes_config[idx].base;
*irq = sg_aes_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_trng_config[CONFIG_TRNG_NUM] = {
{CSKY_TRNG_BASE, TRNG_IRQn}
};
/**
\param[in] instance idx
\brief get trng instance.
\return pointer to trng instance
*/
int32_t target_get_trng(int32_t idx, uint32_t *base)
{
*base = sg_trng_config[idx].base;
return idx;
}
struct {
uint32_t base;
}
const sg_crc_config[CONFIG_CRC_NUM] = {
{CSKY_CRC_BASE}
};
/**
\param[in] instance idx
\brief get crc instance.
\return pointer to crc instance
*/
int32_t target_get_crc(int32_t idx, uint32_t *base)
{
*base = sg_crc_config[idx].base;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_iic_config[CONFIG_IIC_NUM] = {
{CSKY_I2C0_BASE, I2C0_IRQn},
{CSKY_I2C1_BASE, I2C1_IRQn}
};
typedef struct {
int32_t scl;
int32_t sda;
uint16_t cfg_idx; //idx of sg_iic_config[]
uint16_t function;
} iic_pin_map_t;
const static iic_pin_map_t s_iic_pin_map[] = {
{
PA31_I2C0SCL_PWM11_SPU19_XX,
PA30_I2C0SDA_PWM10_SPU18_XX,
0,
0
},
{
PA28_I2C1SCL_PWM8_SPU16_XX,
PA29_I2C1SDA_PWM9_SPU17_XX,
1,
0
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_iic_count()
\brief get iic instance.
\return pointer to iic instance
*/
int32_t target_iic_init(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= sizeof(s_iic_pin_map) / sizeof(iic_pin_map_t)) {
return -1;
}
*base = sg_iic_config[s_iic_pin_map[idx].cfg_idx].base;
*irq = sg_iic_config[s_iic_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_iic_pin_map[idx].scl, s_iic_pin_map[idx].function);
pin_mux(s_iic_pin_map[idx].sda, s_iic_pin_map[idx].function);
return s_iic_pin_map[idx].cfg_idx;
}
#define BIT1 (0x1)
struct {
uint32_t base;
uint32_t irq;
}
const sg_rtc_config[CONFIG_RTC_NUM] = {
{CSKY_RTC0_BASE, RTC_IRQn},
};
int32_t target_get_rtc_count(void)
{
return CONFIG_RTC_NUM;
}
int32_t target_get_rtc(int32_t idx, uint32_t *base, uint32_t *irq)
{
unsigned int value;
if (idx >= target_get_rtc_count()) {
return NULL;
}
value = readl(CSKY_PMU_BASE);
value &= ~BIT1;
writel(value, CSKY_PMU_BASE);
*base = sg_rtc_config[idx].base;
*irq = sg_rtc_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_spi_config[CONFIG_SPI_NUM] = {
{CSKY_SPI0_BASE, SPI0_IRQn},
{CSKY_SPI1_BASE, SPI1_IRQn}
};
typedef struct {
int32_t mosi;
int32_t miso;
int32_t sclk;
int32_t ssel;
uint32_t cfg_idx; //idx of sg_iic_config[]
uint16_t function;
} spi_pin_map_t;
const static spi_pin_map_t s_spi_pin_map[] = {
{
PA18_SPI0MISO_XX_SPU6_USI1SD1,
PA17_SPI0MOSI_PWMTRIG1_XX_USI1SD0,
PA19_SPI0SCK_FAULT_SPU7_USI1NSS,
PA16_SPI0CS0_PWMTRIG0_XX_USI1SCLK,
0,
0
},
{
PB13_UART3TX_SPI1MISO_SPU29_SIROUT3,
PB14_UART3RTS_SPI1MOSI_SPU30_XX,
PB15_UART3CTS_SPI1SCK_SPU31_XX,
PB12_UART3RX_SPI1CS0_SPU28_SIRIN3,
1,
1
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_spi_count()
\brief get spi instance.
\return pointer to spi instance
*/
int32_t target_spi_init(int32_t idx, uint32_t *base, uint32_t *irq, uint32_t *ssel)
{
if (idx >= sizeof(s_spi_pin_map) / sizeof(spi_pin_map_t)) {
return -1;
}
*base = sg_spi_config[s_spi_pin_map[idx].cfg_idx].base;
*irq = sg_spi_config[s_spi_pin_map[idx].cfg_idx].irq;
*ssel = s_spi_pin_map[idx].ssel;
/*pinmux*/
pin_mux(s_spi_pin_map[idx].mosi, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].miso, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].sclk, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].ssel, s_spi_pin_map[idx].function);
return s_spi_pin_map[idx].cfg_idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_dmac_config[CONFIG_DMAC_NUM] = {
{CSKY_DMAC0_BASE, DMAC_IRQn},
};
int32_t target_get_dmac_count(void)
{
return CONFIG_DMAC_NUM;
}
int32_t target_get_dmac(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_dmac_count()) {
return NULL;
}
*base = sg_dmac_config[idx].base;
*irq = sg_dmac_config[idx].irq;
return idx;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_pwm_config[CONFIG_PWM_NUM] = {
{CSKY_PWM_BASE, PWM_IRQn},
};
typedef struct {
int32_t pwm_pin;
uint32_t cfg_idx; //idx of sg_pwm_config[]
uint32_t ch_num;
uint16_t function;
} pwm_pin_map_t;
const static pwm_pin_map_t s_pwm_pin_map[] = {
{PA20_UART1RX_PWM0_SPU8_SIRIN1, 0, 0, 1},
{PA21_UART1TX_PWM1_SPU9_SIROUT1, 0, 1, 1},
{PA22_UART1CTS_PWM2_SPU10_XX, 0, 2, 1},
{PA23_UART1RTS_PWM3_SPU11_XX, 0, 3, 1},
{PA24_USI1NSS_PWM4_SPU12_XX, 0, 4, 1},
{PA25_USI1SD1_PWM5_SPU13_XX, 0, 5, 1},
{PA26_USI1SD0_PWM6_SPU14_XX, 0, 6, 1},
{PA27_USI1SCLK_PWM7_SPU15_XX, 0, 7, 1},
{PA28_I2C1SCL_PWM8_SPU16_XX, 0, 8, 1},
{PA29_I2C1SDA_PWM9_SPU17_XX, 0, 9, 1},
{PA30_I2C0SDA_PWM10_SPU18_XX, 0, 10, 1},
{PA31_I2C0SCL_PWM11_SPU19_XX, 0, 11, 1}
};
/**
\param[in] instance idx, must not exceed return value of target_get_pwm_count()
\brief get pwm instance.
\return pointer to pwm instance
*/
int32_t target_pwm_init(int32_t pwm_pin, uint32_t *ch_num, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_pwm_pin_map) / sizeof(pwm_pin_map_t); idx++) {
if (s_pwm_pin_map[idx].pwm_pin == pwm_pin) {
*base = sg_pwm_config[s_pwm_pin_map[idx].cfg_idx].base;
*irq = sg_pwm_config[s_pwm_pin_map[idx].cfg_idx].irq;
*ch_num = s_pwm_pin_map[idx].ch_num;
/*pinmux*/
pin_mux(s_pwm_pin_map[idx].pwm_pin, s_pwm_pin_map[idx].function);
return s_pwm_pin_map[idx].cfg_idx;
}
}
return -1;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_wdt_config[CONFIG_WDT_NUM] = {
{CSKY_WDT_BASE, WDT_IRQn}
};
int32_t target_get_wdt_count(void)
{
return CONFIG_WDT_NUM;
}
int32_t target_get_wdt(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_wdt_count()) {
return NULL;
}
*base = sg_wdt_config[idx].base;
*irq = sg_wdt_config[idx].irq;
return idx;
}
int32_t target_get_etb_count(void)
{
return CONFIG_ETB_NUM;
}
int32_t target_get_etb(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_etb_count()) {
return NULL;
}
// *base = sg_etb_config[idx].base;
// *irq = sg_etb_config[idx].irq;
return 0;
}
struct {
uint32_t base;
uint32_t irq;
}
const sg_qspi_config[CONFIG_QSPI_NUM] = {
{CSKY_QSPIC0_BASE, QSPIC1_IRQn},
{CSKY_QSPIC1_BASE, QSPIC1_IRQn}
};
typedef struct {
pin_name_t sclk;
pin_name_t miso;
pin_name_t mosi;
pin_name_t hold;
pin_name_t wp;
pin_name_t ssel;
uint32_t cfg_idx;
uint16_t function;
} qspi_pin_map_t;
const static qspi_pin_map_t s_qspi_pin_map[] = {
{
PA2_QSPI0CLK_XX_XX_XX,
PA3_QSPI0MISO_XX_XX_XX,
PA4_QSPI0MOSI_XX_XX_XX,
PA5_QSPI0HOLD_XX_XX_XX,
PA6_QSPI0WP_XX_XX_XX,
PA7_QSPI0CS0_XX_XX_XX,
0,
0
},
{
PB11_QSPI1CLK_XX_SPU27_I2C1SCL,
PB10_QSPI1MISO_XX_SPU26_I2C1SDA,
PB9_QSPI1MOSI_PWMTRIG1_SPU25_XX,
PB7_QSPI1HOLD_XX_SPU23_XX,
PB6_QSPI1WP_XX_SPU22_XX,
PB8_QSPI1CS0_PWMTRIG0_SPU24_XX,
1,
0
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_qspi_count()
\brief get qspi instance.
\return pointer to qspi instance
*/
int32_t target_qspi_init(pin_name_t mosi, pin_name_t miso, pin_name_t sclk, pin_name_t ssel, pin_name_t wp, pin_name_t hold, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_qspi_pin_map) / sizeof(qspi_pin_map_t); idx++) {
if (s_qspi_pin_map[idx].mosi == mosi && s_qspi_pin_map[idx].miso == miso
&& s_qspi_pin_map[idx].sclk == sclk && s_qspi_pin_map[idx].ssel == ssel
&& s_qspi_pin_map[idx].hold == hold && s_qspi_pin_map[idx].wp == wp) {
pin_mux(s_qspi_pin_map[idx].mosi, s_qspi_pin_map[idx].function);
pin_mux(s_qspi_pin_map[idx].miso, s_qspi_pin_map[idx].function);
pin_mux(s_qspi_pin_map[idx].sclk, s_qspi_pin_map[idx].function);
pin_mux(s_qspi_pin_map[idx].hold, s_qspi_pin_map[idx].function);
pin_mux(s_qspi_pin_map[idx].wp, s_qspi_pin_map[idx].function);
pin_mux(s_qspi_pin_map[idx].ssel, s_qspi_pin_map[idx].function);
return s_qspi_pin_map[idx].cfg_idx;
}
}
return -1;
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pin_name.h
* @brief header file for the pin_name
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _PINNAMES_H
#define _PINNAMES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PA0_I2C0SCL_SPI1CS1_SPU0_UART1TX = 0,
PA1_I2C0SDA_SPI1CS2_SPU1_UART1RX,
PA2_QSPI0CLK_XX_XX_XX,
PA3_QSPI0MISO_XX_XX_XX,
PA4_QSPI0MOSI_XX_XX_XX,
PA5_QSPI0HOLD_XX_XX_XX,
PA6_QSPI0WP_XX_XX_XX,
PA7_QSPI0CS0_XX_XX_XX,
PA8_UART0TX_XX_SPU2_SIROUT0,
PA9_UART0RX_XX_SPU3_SIRIN0,
PA10_UART0CTS_USI0SCLK_SPU4_I2C0SCL,
PA11_UART0RTS_USI0SD0_SPU5_I2C0SDA,
PA12_XX_USI0SD1_XX_UART2RX,
PA13_XX_USI0NSS_XX_UART2TX,
PA14_SPI0CS2_FAULT_I2C1SDA_XX,
PA15_SPI0CS1_XX_I2C1SCL_XX,
PA16_SPI0CS0_PWMTRIG0_XX_USI1SCLK,
PA17_SPI0MOSI_PWMTRIG1_XX_USI1SD0,
PA18_SPI0MISO_XX_SPU6_USI1SD1,
PA19_SPI0SCK_FAULT_SPU7_USI1NSS,
PA20_UART1RX_PWM0_SPU8_SIRIN1,
PA21_UART1TX_PWM1_SPU9_SIROUT1,
PA22_UART1CTS_PWM2_SPU10_XX,
PA23_UART1RTS_PWM3_SPU11_XX,
PA24_USI1NSS_PWM4_SPU12_XX,
PA25_USI1SD1_PWM5_SPU13_XX,
PA26_USI1SD0_PWM6_SPU14_XX,
PA27_USI1SCLK_PWM7_SPU15_XX,
PA28_I2C1SCL_PWM8_SPU16_XX,
PA29_I2C1SDA_PWM9_SPU17_XX,
PA30_I2C0SDA_PWM10_SPU18_XX,
PA31_I2C0SCL_PWM11_SPU19_XX,
PB0_UART2TX_XX_XX_SIROUT2,
PB1_UART2RX_XX_XX_SIRIN2,
PB2_UART2RTS_XX_XX_XX,
PB3_UART2CTS_XX_XX_XX,
PB4_XX_XX_SPU20_UART3TX,
PB5_QSPI1CS1_XX_SPU21_UART3RX,
PB6_QSPI1WP_XX_SPU22_XX,
PB7_QSPI1HOLD_XX_SPU23_XX,
PB8_QSPI1CS0_PWMTRIG0_SPU24_XX,
PB9_QSPI1MOSI_PWMTRIG1_SPU25_XX,
PB10_QSPI1MISO_XX_SPU26_I2C1SDA,
PB11_QSPI1CLK_XX_SPU27_I2C1SCL,
PB12_UART3RX_SPI1CS0_SPU28_SIRIN3,
PB13_UART3TX_SPI1MISO_SPU29_SIROUT3,
PB14_UART3RTS_SPI1MOSI_SPU30_XX,
PB15_UART3CTS_SPI1SCK_SPU31_XX,
}
pin_name_t;
typedef enum {
PORTA = 0,
PORTB = 1
} port_name_t;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,99 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pinmux.h
* @brief Header file for the pinmux
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef HOBBIT_PINMUX_H
#define HOBBIT_PINMUX_H
#include <stdint.h>
#include "pin_name.h"
void hobbit_ioreuse_initial(void);
int32_t pin_mux(pin_name_t pin, uint16_t function);
/*IOMUX0L function definition */
/* IOMUX0H function definition */
#define PA20_UART1_RX 0x00000000
#define PA21_UART1_TX 0x00000000
/* IOMUX1L function definition */
/* flag as identification */
#define GPIO_SET_BIT0 0x00000001
#define GPIO_SET_BIT1 0x00000002
#define GPIO_SET_BIT2 0x00000004
#define GPIO_SET_BIT3 0x00000008
#define GPIO_SET_BIT4 0x00000010
#define GPIO_SET_BIT5 0x00000020
#define GPIO_SET_BIT6 0x00000040
#define GPIO_SET_BIT7 0x00000080
#define GPIO_SET_BIT8 0x00000100
#define GPIO_SET_BIT9 0x00000200
#define GPIO_SET_BIT10 0x00000400
#define GPIO_SET_BIT11 0x00000800
#define GPIO_SET_BIT12 0x00001000
#define GPIO_SET_BIT13 0x00002000
#define GPIO_SET_BIT14 0x00004000
#define GPIO_SET_BIT15 0x00008000
#define GPIO_SET_BIT16 0x00010000
#define GPIO_SET_BIT17 0x00020000
#define GPIO_SET_BIT18 0x00040000
#define GPIO_SET_BIT19 0x00080000
#define GPIO_SET_BIT20 0x00100000
#define GPIO_SET_BIT21 0x00200000
#define GPIO_SET_BIT22 0x00400000
#define GPIO_SET_BIT23 0x00800000
#define GPIO_SET_BIT24 0x01000000
#define GPIO_SET_BIT25 0x02000000
#define GPIO_SET_BIT26 0x04000000
#define GPIO_SET_BIT27 0x08000000
#define GPIO_SET_BIT28 0x10000000
#define GPIO_SET_BIT29 0x20000000
#define GPIO_SET_BIT30 0x40000000
#define GPIO_SET_BIT31 0x80000000
/******************************************************************************
* hobbit gpio control and gpio reuse function
* selecting regester adddress
******************************************************************************/
#define HOBBIT_GIPO0_PORTCTL_REG 0x60030000
#define HOBBIT_GIPO1_PORTCTL_REG 0x60030004
#define HOBBIT_IOMUX0L_REG 0x60030008
#define HOBBIT_IOMUX0H_REG 0x6003000C
#define HOBBIT_IOMUX1L_REG 0x60030010
/*************basic gpio reuse v1.0********************************************
* UART1(PA20,PA21)
******************************************************************************/
#define GPIO0_REUSE_EN (GPIO_SET_BIT20|GPIO_SET_BIT21)
#define GPIO1_REUSE_EN (0x00000000)
#define IOMUX0L_FUNCTION_SEL (0x00000000)
#define IOMUX0H_FUNCTION_SEL (PA20_UART1_RX|PA21_UART1_TX)
#define IOMUX1L_FUNCTION_SEL (0x00000000)
#endif /* HOBBIT_PINMUX_H */

View file

@ -0,0 +1,206 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**************************************************************************//**
* @file soc.h
* @brief CSI Core Peripheral Access Layer Header File for
* CSKYSOC Device Series
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef SOC_H
#define SOC_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SYSTEM_CLOCK
#define SYSTEM_CLOCK (20000000)
#endif
#ifndef LSP_DEFAULT_FREQ
#define LSP_DEFAULT_FREQ (20000000)
#endif
/* ------------------------- Interrupt Number Definition ------------------------ */
typedef enum IRQn
{
/* ---------------------- CSKYCK801 Specific Interrupt Numbers --------------------- */
GPIOA_IRQn = 0,
CORET_IRQn = 1, /* core Timer Interrupt */
TIMA0_IRQn = 2, /* timerA0 Interrupt */
TIMA1_IRQn = 3, /* timerA1 Interrupt */
TIM34567_IRQn = 4, /* timerC ~ timerH Interrupt */
WDT_IRQn = 5, /* wdt Interrupt */
UART0_IRQn = 6, /* uart0 Interrupt */
UART1_IRQn = 7, /* uart1 Interrupt */
UART2_IRQn = 8, /* uart2 Interrupt */
I2C0_IRQn = 9, /* i2c0 Interrupt */
I2C1_IRQn = 10, /* i2c1 Interrupt */
SPI1_IRQn = 11, /* spi1 Interrupt */
SPI0_IRQn = 12, /* spi0 Interrupt */
RTC_IRQn = 13, /* rtc Interrupt */
UART3_IRQn = 14, /* uart3 Interrupt */
ADC_IRQn = 15, /* adc Interrupt */
QSPIC1_IRQn = 16, /* qspic1 interrupt */
DMAC_IRQn = 17, /* dmac Interrupt */
PMU_IRQn = 18, /* pmu Interrupt */
PWM_IRQn = 19, /* pwm Interrupt */
USI0_IRQn = 20, /* usi0 Interrupt */
USI1_IRQn = 21, /* usi1 Interrupt */
SPU_IRQn = 22, /* spu Interrupt */
TIMB0_IRQn = 23, /* timerB0 Interrupt */
TIMB1_IRQn = 24, /* timerB1 Interrupt */
GPIOB_IRQn = 27, /* GPIOB Interrupt */
AES_IRQn = 26, /* aes Interrupt */
RSA_IRQn = 28, /* rsa Interrupt */
SHA_IRQn = 29, /* sha Interrupt */
TRNG_IRQn = 30, /* trng Interrupt */
} IRQn_Type;
/* ================================================================================ */
/* ================ Processor and Core Peripheral Section ================ */
/* ================================================================================ */
/* -------- Configuration of the CK801 Processor and Core Peripherals ------- */
#define __CK803_REV 0x0000U /* Core revision r0p0 */
#define __MPU_PRESENT 0 /* MGU present or not */
#define __VIC_PRIO_BITS 2 /* Number of Bits used for Priority Levels */
#define __Vendor_SysTickConfig 0 /* Set to 1 if different SysTick Config is used */
#include "core_ck802.h" /* Processor and core peripherals */
#include "stdint.h"
typedef enum {
CKENUM_DMA_UART0_RX,
CKENUM_DMA_UART0_TX,
CKENUM_DMA_UART1_RX,
CKENUM_DMA_UART1_TX,
CKENUM_DMA_ADC_RX,
CKENUM_DMA_ADC_TX,
CKENUM_DMA_SPI1_RX,
CKENUM_DMA_SPI1_TX,
CKENUM_DMA_SPI0_RX,
CKENUM_DMA_SPI0_TX,
CKENUM_DMA_IIC_RX,
CKENUM_DMA_IIC_TX,
CKENUM_DMA_IIC1_RX,
CKENUM_DMA_IIC1_TX,
CKENUM_DMA_IIS_RX,
CKENUM_DMA_IIS_TX,
CKENUM_DMA_MEMORY
} ckenum_dma_device_e;
#define CONFIG_CRC_NUM 1
#define CONFIG_IIC_NUM 2
#define CONFIG_TRNG_NUM 1
#define CONFIG_AES_NUM 1
#define CONFIG_RSA_NUM 1
#define CONFIG_SHA_NUM 1
#define CONFIG_SPI_NUM 2
#define CONFIG_QSPI_NUM 2
#define CONFIG_PWM_NUM 1
#define CONFIG_TIMER_NUM 14
#define CONFIG_RTC_NUM 1
#define CONFIG_WDT_NUM 1
#define CONFIG_DMAC_NUM 1
#define CONFIG_GPIO_NUM 2
#define CONFIG_GPIO_PIN_NUM 43
#define CONFIG_USART_NUM 4
#define CONFIG_SPU_NUM 1
#define CONFIG_EFLASH_NUM 1
#define CONFIG_ETB_NUM 1
#define CONFIG_USI_NUM 2
/* ================================================================================ */
/* ================ Peripheral memory map ================ */
/* ================================================================================ */
/* -------------------------- CPU FPGA memory map ------------------------------- */
#define CSKY_EFLASH_BASE (0x10000000UL)
#define CSKY_QSPIMEM_BASE (0x18000000UL)
#define CSKY_SRAM_BASE (0x20000000UL)
#define CSKY_PMU_BASE (0x40000000UL)
#define CSKY_DMAC0_BASE (0x40001000UL)
#define CSKY_OTP_BASE (0x40006000UL)
#define CSKY_SASC_BASE (0x40009000UL)
#define CSKY_SPU_BASE (0x40020000UL)
#define CSKY_QSPIC1_BASE (0x40030000UL)
#define CSKY_EFLASH_CONTROL_BASE (0x40005000UL)
#define CSKY_SASC_BASE (0x40009000UL)
/* SUB0*/
#define CSKY_AES_BASE (0x4000D000UL)
#define CSKY_SHA_BASE (0x4000E000UL)
#define CSKY_RSA_BASE (0x4000F000UL)
#define CSKY_CRC_BASE (0x40010000UL)
#define CSKY_TRNG_BASE (0x40011000UL)
/* APB0 */
#define CSKY_TIM0_BASE (0x50000000UL)
#define CSKY_TIM1_BASE (0x50000400UL)
#define CSKY_TIM2_BASE (0x50000800UL)
#define CSKY_TIM3_BASE (0x50000C00UL)
#define CSKY_RTC0_BASE (0x50004000UL)
#define CSKY_WDT_BASE (0x50008000UL)
#define CSKY_SPI0_BASE (0x5000C000UL)
#define CSKY_UART0_BASE (0x50010000UL)
#define CSKY_UART1_BASE (0x50010400UL)
#define CSKY_I2C0_BASE (0x50014000UL)
#define CSKY_GPIO0_BASE (0x50018000UL)
#define CSKY_PWM_BASE (0x5001C000UL)
#define CSKY_ADC_BASE (0x50020000UL)
#define CSKY_USI0_BASE (0x50028000UL)
#define CSKY_QSPIC0_BASE (0x5002C000UL)
/* APB1*/
#define CSKY_TIM4_BASE (0x60000000UL)
#define CSKY_TIM5_BASE (0x60000400UL)
#define CSKY_TIM6_BASE (0x60000800UL)
#define CSKY_TIM7_BASE (0x60000C00UL)
#define CSKY_LPWDT_BASE (0x60008000UL)
#define CSKY_SPI1_BASE (0x6000C000UL)
#define CSKY_UART2_BASE (0x60010000UL)
#define CSKY_UART3_BASE (0x60010400UL)
#define CSKY_I2C1_BASE (0x60014000UL)
#define CSKY_GPIO1_BASE (0x60018000UL)
#define CSKY_TIPC_BASE (0x6001c000UL)
#define CSKY_ETB_BASE (0x60024000UL)
#define CSKY_USI1_BASE (0x60028000UL)
#define CSKY_DAC_BASE (0x6002C000UL)
#define CSKY_IOC_BASE (0x60030000UL)
#define SHA_CONTEXT_SIZE 224
/* ================================================================================ */
/* ================ Peripheral declaration ================ */
/* ================================================================================ */
#define CSKY_UART1 (( CSKY_UART_TypeDef *) CSKY_UART1_BASE)
#define CSKY_SHA (( CSKY_SHA_TypeDef *) CSKY_SHA_BASE)
#ifdef CONFIG_HAVE_VIC
#define ATTRIBUTE_ISR __attribute__((isr))
#else
#define ATTRIBUTE_ISR
#endif
#ifdef __cplusplus
}
#endif
#endif /* SOC_H */

View file

@ -0,0 +1,244 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file isr.c
* @brief source file for the interrupt server route
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <drv_common.h>
#include <config.h>
#include "soc.h"
#ifndef CONFIG_KERNEL_NONE
#include <csi_kernel.h>
#endif
#ifndef CONFIG_USI
extern void dw_spi_irqhandler(int32_t idx);
extern void dw_usart_irqhandler(int32_t idx);
extern void dw_iic_irqhandler(int32_t idx);
#else
extern void ck_usi_irqhandler(int idx);
#endif
extern void ck_spu_irqhandler(int32_t idx);
extern void dw_timer_irqhandler(int32_t idx);
extern void dw_gpio_irqhandler(int32_t idx);
extern void ck_rtc_irqhandler(int32_t idx);
extern void dw_wdt_irqhandler(int32_t idx);
extern void ck_dma_irqhandler(int32_t idx);
extern void ck_aes_irqhandler(int32_t idx);
extern void ck_sha_irqhandler(int32_t idx);
#ifdef CONFIG_KERNEL_FREERTOS
extern void CoretimeIsr(void);
extern void CKPendSVIsr(void);
#endif
extern void systick_handler(void);
extern void xPortSysTickHandler(void);
extern void OSTimeTick(void);
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#ifndef CONFIG_KERNEL_NONE
#define CSI_INTRPT_ENTER() csi_kernel_intrpt_enter()
#define CSI_INTRPT_EXIT() csi_kernel_intrpt_exit()
#else
#define CSI_INTRPT_ENTER()
#define CSI_INTRPT_EXIT()
#endif
ATTRIBUTE_ISR void CORET_IRQHandler(void)
{
#ifndef CONFIG_KERNEL_FREERTOS
CSI_INTRPT_ENTER();
#endif
readl(0xE000E010);
#if defined(CONFIG_KERNEL_RHINO)
systick_handler();
#elif defined(CONFIG_KERNEL_FREERTOS)
xPortSysTickHandler();
#elif defined(CONFIG_KERNEL_UCOS)
OSTimeTick();
#endif
#ifndef CONFIG_KERNEL_FREERTOS
CSI_INTRPT_EXIT();
#endif
}
#ifdef CONFIG_SPU
ATTRIBUTE_ISR void SPU_IRQHandler(void)
{
ck_spu_irqhandler(0);
}
#endif
#ifndef CONFIG_USI
ATTRIBUTE_ISR void SPI0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_spi_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void SPI1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_spi_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void I2C0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_iic_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void I2C1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_iic_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART2_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(2);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART3_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(3);
CSI_INTRPT_EXIT();
}
#else
ATTRIBUTE_ISR void USI0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_usi_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USI1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_usi_irqhandler(1);
CSI_INTRPT_EXIT();
}
#endif
ATTRIBUTE_ISR void TIMA0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMA1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMB0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(2);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMB1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(3);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIM34567_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(4);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void GPIOA_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_gpio_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void GPIOB_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_gpio_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void RTC_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_rtc_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void AES_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_aes_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void SHA_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_sha_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void WDT_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_wdt_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void DMAC_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_dma_irqhandler(0);
CSI_INTRPT_EXIT();
}

View file

@ -0,0 +1,138 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pinmux.c
* @brief source file for the pinmux
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdint.h>
#include "pinmux.h"
#include "pin_name.h"
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
/*******************************************************************************
* function: hobbit_ioreuse_inital
*
* description:
* initial hobbit_pinmux
*******************************************************************************/
extern int32_t target_qspi_init(pin_name_t mosi, pin_name_t miso, pin_name_t sclk, pin_name_t ssel, pin_name_t wp, pin_name_t hold, uint32_t *base, uint32_t *irq);
void hobbit_ioreuse_initial(void)
{
unsigned int value;
/* gpio data source select */
value = readl(HOBBIT_GIPO0_PORTCTL_REG);
value |= GPIO0_REUSE_EN;
writel(value, HOBBIT_GIPO0_PORTCTL_REG);
value = readl(HOBBIT_GIPO1_PORTCTL_REG);
value |= GPIO1_REUSE_EN;
writel(value, HOBBIT_GIPO1_PORTCTL_REG);
/* reuse function select */
value = readl(HOBBIT_IOMUX0L_REG);
value |= IOMUX0L_FUNCTION_SEL;
writel(value, HOBBIT_IOMUX0H_REG);
value = readl(HOBBIT_IOMUX0H_REG);
value |= IOMUX1L_FUNCTION_SEL;
writel(value, HOBBIT_IOMUX0H_REG);
value = readl(HOBBIT_IOMUX1L_REG);
value |= IOMUX1L_FUNCTION_SEL;
writel(value, HOBBIT_IOMUX1L_REG);
target_qspi_init(PA4_QSPI0MOSI_XX_XX_XX, PA3_QSPI0MISO_XX_XX_XX, PA2_QSPI0CLK_XX_XX_XX, PA7_QSPI0CS0_XX_XX_XX, PA6_QSPI0WP_XX_XX_XX, PA5_QSPI0HOLD_XX_XX_XX, 0, 0);
}
int32_t pin_mux(pin_name_t pin, uint16_t function)
{
unsigned int val = 0;
unsigned int reg_val = 0;
uint8_t offset;
if (function > 3) {
if (pin < PB0_UART2TX_XX_XX_SIROUT2) {
offset = pin;
/* gpio data source select */
val = readl(HOBBIT_GIPO0_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, HOBBIT_GIPO0_PORTCTL_REG);
return 0;
} else if (pin >= PB0_UART2TX_XX_XX_SIROUT2) {
offset = pin - 32;
/* gpio data source select */
val = readl(HOBBIT_GIPO1_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, HOBBIT_GIPO1_PORTCTL_REG);
return 0;
} else {
return -1;
}
}
if (pin >= PB0_UART2TX_XX_XX_SIROUT2) {
offset = pin - 32;
/* gpio data source select */
val = readl(HOBBIT_GIPO1_PORTCTL_REG);
val |= (1 << offset);
writel(val, HOBBIT_GIPO1_PORTCTL_REG);
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT_IOMUX1L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT_IOMUX1L_REG);
return 0;
}
offset = pin;
/* gpio data source select */
val = readl(HOBBIT_GIPO0_PORTCTL_REG);
val |= (1 << offset);
writel(val, HOBBIT_GIPO0_PORTCTL_REG);
if (pin >= PA16_SPI0CS0_PWMTRIG0_XX_USI1SCLK) {
offset = pin - 16;
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT_IOMUX0H_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT_IOMUX0H_REG);
return 0;
}
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(HOBBIT_IOMUX0L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, HOBBIT_IOMUX0L_REG);
return 0;
}

View file

@ -0,0 +1,5 @@
TEE_INC += -I$(CSI_DIR)/csi_driver/csky/phobos/include
TEE_SRC += \
$(CSI_DIR)/csi_driver/csky/phobos/devices.c \
$(CSI_DIR)/csi_driver/csky/phobos/isr.c \
$(CSI_DIR)/csi_driver/csky/phobos/pinmux.c

View file

@ -0,0 +1,843 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file devices.c
* @brief source file for the devices
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include "soc.h"
#include "config.h"
#include <drv_usart.h>
#include <drv_trng.h>
#include <drv_crc.h>
#include <drv_aes.h>
#include <drv_rsa.h>
#include <drv_eflash.h>
#include <drv_timer.h>
#include <drv_gpio.h>
#include <drv_iic.h>
#include <drv_rtc.h>
#include <drv_spi.h>
#include <drv_wdt.h>
#include <drv_sha.h>
#include <drv_pwm.h>
#include <drv_dmac.h>
#include <stdio.h>
#include "pin_name.h"
#include "pinmux.h"
//typedef int32_t pin_t;
#if CONFIG_IIC
struct {
uint32_t base;
uint32_t irq;
}
const sg_iic_config[CONFIG_IIC_NUM] = {
{CSKY_I2C0_BASE, I2C0_IRQn},
{CSKY_I2C1_BASE, I2C1_IRQn}
};
typedef struct {
pin_t scl;
pin_t sda;
uint16_t cfg_idx; //idx of sg_iic_config[]
uint16_t function;
//uint32_t scl_reg;
//uint32_t scl_cfg;
//uint32_t sda_reg;
//uint32_t sda_cfg;
} iic_pin_map_t;
const static iic_pin_map_t s_iic_pin_map[] = {
{
PA4_SCL0_PWM4_SPI0RX_XX,
PA5_SDA0_PWM5_SPI0CS_XX,
0,
0
},
{
PA6_SPI0CLK_PWMTRIG0_SCL0_XX,
PA7_SPI0TX_PWMTRIG1_SDA0_XX,
0,
2
},
{
PA31_I2SSDA__SCL0_PWM4_XX,
PB0_ADC0_SDA0_PWM5_XX,
0,
1
},
{
PA8_SPI0RX_TRIGFAULT_SCL1_XX,
PA9_SPI0CS_PWM0_SDA1_XX,
1,
2
},
{
PA14_SCL1_PWM5_SPI1RX_XX,
PA15_SDA1_PWMTRIG0_SPI1CS0_XX,
1,
0
},
{
PB1_ADC1_SCL1_USISCLK_XX,
PB2_ADC2_SDA1_USISD0_XX,
1,
1
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_iic_count()
\brief get iic instance.
\return pointer to iic instance
*/
int32_t target_iic_init(pin_t scl, pin_t sda, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_iic_pin_map) / sizeof(iic_pin_map_t); idx++) {
if (s_iic_pin_map[idx].scl == scl && s_iic_pin_map[idx].sda == sda) {
*base = sg_iic_config[s_iic_pin_map[idx].cfg_idx].base;
*irq = sg_iic_config[s_iic_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_iic_pin_map[idx].scl, s_iic_pin_map[idx].function);
pin_mux(s_iic_pin_map[idx].sda, s_iic_pin_map[idx].function);
return s_iic_pin_map[idx].cfg_idx;
}
}
return -1;
}
#endif
#if CONFIG_USART
struct {
uint32_t base;
uint32_t irq;
}
const sg_usart_config[CONFIG_USART_NUM] = {
{CSKY_UART0_BASE, UART0_IRQn},
{CSKY_UART1_BASE, UART1_IRQn},
{CSKY_UART2_BASE, UART2_IRQn},
{CSKY_UART3_BASE, UART3_IRQn}
};
typedef struct {
pin_t tx;
pin_t rx;
pin_t cts;
pin_t rts;
uint16_t cfg_idx; //idx of sg_usart_config[]
uint16_t function;
} usart_pin_map_t;
const static usart_pin_map_t s_usart_pin_map[] = {
{
PA0_TXD0_PWM0_XX_SIROUT0,
PA1_RXD0_PWM1_XX_SIRIN0,
-1,
-1,
0,
0
},
{
PA10_TXD1_PWM1_XX_SIROUT1,
PA11_RXD1_PWM2_XX_SIRIN1,
-1,
-1,
1,
0
},
{
PA23_TXD2_PWM5_XX_SIROUT2,
PA22_RXD2_PWM4_XX_SIRIN2,
PA24_CTS2_PWMTRIG0_SPI1CS1_XX,
PA25_XX_PWMTRIG1_SPI1CS2_XX,
2,
0
},
{
PA26_TXD3_PWMFAULT_XX_SIROUT3,
PA27_RXD3_PWM0_XX_SIRIN3,
-1,
-1,
3,
0
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_usart_count()
\brief get usart instance.
\return pointer to usart instance
*/
int32_t target_usart_init(pin_t tx, pin_t rx, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t); idx++) {
if (s_usart_pin_map[idx].tx == tx && s_usart_pin_map[idx].rx == rx) {
*base = sg_usart_config[s_usart_pin_map[idx].cfg_idx].base;
*irq = sg_usart_config[s_usart_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_usart_pin_map[idx].tx, s_usart_pin_map[idx].function);
pin_mux(s_usart_pin_map[idx].rx, s_usart_pin_map[idx].function);
return s_usart_pin_map[idx].cfg_idx;
}
}
return -1;
}
/**
\brief control usart flow.
\param[in] tx_flow The TX flow pin name
\param[in] rx_flow The RX flow pin name
\param[in] flag 0-disable, 1-enable.
\return 0 if setting ready ,negative for error code
*/
int32_t target_usart_flowctrl_init(pin_t tx_flow, pin_t rx_flow, uint32_t flag)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t); idx++) {
if ((s_usart_pin_map[idx].cts == tx_flow) &&(s_usart_pin_map[idx].rts == rx_flow))
break;
}
if (idx >= sizeof(s_usart_pin_map) / sizeof(usart_pin_map_t)) {
return -1;
}
if ((s_usart_pin_map[idx].cts == tx_flow) && flag) {
pin_mux(s_usart_pin_map[idx].cts, s_usart_pin_map[idx].function);
} else if ((s_usart_pin_map[idx].cts == tx_flow) && (flag == 0)) {
pin_mux(s_usart_pin_map[idx].cts, 0xff);
} else {
return -1;
}
if ((s_usart_pin_map[idx].rts == rx_flow) && flag) {
pin_mux(s_usart_pin_map[idx].rts, s_usart_pin_map[idx].function);
} else if ((s_usart_pin_map[idx].rts == rx_flow) && (flag == 0)) {
pin_mux(s_usart_pin_map[idx].rts, 0xff);
} else {
return -1;
}
return 0;
}
#endif
#if CONFIG_TRNG
struct {
uint32_t base;
}
const sg_trng_config[CONFIG_TRNG_NUM] = {
{CSKY_TRNG_BASE}
};
/**
\brief get trng instance count.
\return trng instance count
*/
int32_t target_get_trng_count(void)
{
return CONFIG_TRNG_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_trng_count()
\brief get trng instance.
\return pointer to trng instance
*/
int32_t target_get_trng(int32_t idx, uint32_t *base)
{
if (idx >= target_get_trng_count()) {
return NULL;
}
*base = sg_trng_config[idx].base;
return idx;
}
#endif
#if CONFIG_CRC
struct {
uint32_t base;
}
const sg_crc_config[CONFIG_CRC_NUM] = {
{CSKY_CRC_BASE}
};
/**
\brief get crc instance count.
\return crc instance count
*/
int32_t target_get_crc_count(void)
{
return CONFIG_CRC_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_crc_count()
\brief get crc instance.
\return pointer to crc instance
*/
int32_t target_get_crc(int32_t idx, uint32_t *base)
{
if (idx >= target_get_crc_count()) {
return NULL;
}
*base = sg_crc_config[idx].base;
return idx;
}
#endif
#if CONFIG_EFLASH
struct {
uint32_t base;
eflash_info info;
}
const sg_eflash_config[CONFIG_EFLASH_NUM] = {
{CSKY_EFLASH_CONTROL_BASE, {0x10000000, 0x1003f800, 0x1fc}}
};
/**
\brief get eflash instance count.
\return eflash instance count
*/
int32_t target_get_eflash_count(void)
{
return CONFIG_EFLASH_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_eflash_count()
\brief get eflash instance.
\return pointer to eflash instance
*/
int32_t target_get_eflash(int32_t idx, uint32_t *base, eflash_info *info)
{
if (idx >= target_get_eflash_count()) {
return NULL;
}
*base = sg_eflash_config[idx].base;
info->start = sg_eflash_config[idx].info.start;
info->end = sg_eflash_config[idx].info.end;
info->sector_count = sg_eflash_config[idx].info.sector_count;
return idx;
}
#endif
#if CONFIG_TIMER
struct {
uint32_t base;
uint32_t irq;
}
const sg_timer_config[CONFIG_TIMER_NUM] = {
{CSKY_TIMERA0_BASE, TIMA0_IRQn},
{CSKY_TIMERA1_BASE, TIMA1_IRQn},
{CSKY_TIMERB0_BASE, TIMB0_IRQn},
{CSKY_TIMERB1_BASE, TIMB1_IRQn}
};
int32_t target_get_timer_count(void)
{
return CONFIG_TIMER_NUM;
}
int32_t target_get_timer(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_timer_count()) {
return NULL;
}
*base = sg_timer_config[idx].base;
*irq = sg_timer_config[idx].irq;
return idx;
}
#endif
#if CONFIG_GPIO
struct {
uint32_t base;
uint32_t irq;
uint32_t pin_num;
port_name_t port;
}
const sg_gpio_config[CONFIG_GPIO_NUM] = {
{CSKY_GPIOA_BASE, GPIOA_IRQn, 32, PORTA},
{CSKY_GPIOB_BASE, GPIOB_IRQn, 11, PORTB}
};
typedef struct {
pin_t gpio_pin;
uint32_t cfg_idx; //idx of sg_gpio_config[]
} gpio_pin_map_t;
const static gpio_pin_map_t s_gpio_pin_map[] = {
{PA0_TXD0_PWM0_XX_SIROUT0, 0},
{PA1_RXD0_PWM1_XX_SIRIN0, 0},
{PA2_CTS0_PWM2_SPI0CLK_XX, 0},
{PA3_RTS0_PWM3_SPI0TX_XX, 0},
{PA4_SCL0_PWM4_SPI0RX_XX, 0},
{PA5_SDA0_PWM5_SPI0CS_XX, 0},
{PA6_SPI0CLK_PWMTRIG0_SCL0_XX, 0},
{PA7_SPI0TX_PWMTRIG1_SDA0_XX, 0},
{PA8_SPI0RX_TRIGFAULT_SCL1_XX, 0},
{PA9_SPI0CS_PWM0_SDA1_XX, 0},
{PA10_TXD1_PWM1_XX_SIROUT1, 0},
{PA11_RXD1_PWM2_XX_SIRIN1, 0},
{PA12_CTS1_PWM3_SPI1CLK_XX, 0},
{PA13_RTS1_PWM4_SPI1TX_XX, 0},
{PA14_SCL1_PWM5_SPI1RX_XX, 0},
{PA15_SDA1_PWMTRIG0_SPI1CS0_XX, 0},
{PA16_SPI1CLK_PWMTRIG1_XX_XX, 0},
{PA17_SPI1TX_PWMFAULT_XX_XX, 0},
{PA18_SPI1RX_PWM0_XX_XX, 0},
{PA19_SPI1CS0_PWM1_XX_XX, 0},
{PA20_SPI1CS1_PWM2_XX_XX, 0},
{PA21_SPI1CS2_PWM3_XX_XX, 0},
{PA22_RXD2_PWM4_XX_SIRIN2, 0},
{PA23_TXD2_PWM5_XX_SIROUT2, 0},
{PA24_CTS2_PWMTRIG0_SPI1CS1_XX, 0},
{PA25_XX_PWMTRIG1_SPI1CS2_XX, 0},
{PA26_TXD3_PWMFAULT_XX_SIROUT3, 0},
{PA27_RXD3_PWM0_XX_SIRIN3, 0},
{PA28_I2SMCLK_PWM1_XX_XX, 0},
{PA29_I2SSCLK_PWM2_XX_XX, 0},
{PA30_I2SWSCLK_PWM3_XX_XX, 0},
{PA31_I2SSDA__SCL0_PWM4_XX, 0},
{PB0_ADC0_SDA0_PWM5_XX, 1},
{PB1_ADC1_SCL1_USISCLK_XX, 1},
{PB2_ADC2_SDA1_USISD0_XX, 1},
{PB3_ADC3_SPI1CLK_USISD1_XX, 1},
{PB4_ADC4_SPI1TX_USINSS_XX, 1},
{PB5_ADC5_SPI1RX_USISCLK_XX, 1},
{PB6_ADC6_SPI1CS0_USISD0_XX, 1},
{PB7_ADC7_SPI1CS1_USISD1_XX, 1},
{PB8_PWMTRIG0_SPI1CS2_USINSS_XX, 1},
{PB9_PWMTRIG1_CTS3_XX_XX, 1},
{PB10_PWMFAULT_RTS3_XX_XX, 1}
};
int32_t target_gpio_port_init(port_name_t port, uint32_t *base, uint32_t *irq, uint32_t *pin_num)
{
int i;
for (i = 0; i < CONFIG_GPIO_NUM; i++) {
if (sg_gpio_config[i].port == port) {
*base = sg_gpio_config[i].base;
*irq = sg_gpio_config[i].irq;
*pin_num = sg_gpio_config[i].pin_num;
return i;
}
}
return -1;
}
/**
\param[in] instance idx, must not exceed return value of target_get_gpio_count()
\brief get gpio instance.
\return pointer to gpio instance
*/
int32_t target_gpio_pin_init(pin_t gpio_pin, uint32_t *port_idx)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_gpio_pin_map) / sizeof(gpio_pin_map_t); idx++) {
if (s_gpio_pin_map[idx].gpio_pin == gpio_pin) {
*port_idx = s_gpio_pin_map[idx].cfg_idx;
/*pinmux*/
pin_mux(s_gpio_pin_map[idx].gpio_pin, 0xff);
if (idx >= 32) {
return idx-32;
}
return idx;
}
}
return -1;
}
#endif
#if CONFIG_AES
struct {
uint32_t base;
uint32_t irq;
}
const sg_aes_config[CONFIG_AES_NUM] = {
{CSKY_AES_BASE, AES_IRQn}
};
/**
\brief get aes instance count.
\return aes instance count
*/
int32_t target_get_aes_count(void)
{
return CONFIG_AES_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_aes_count()
\brief get aes instance.
\return pointer to aes instance
*/
int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_aes_count()) {
return NULL;
}
*base = sg_aes_config[idx].base;
*irq = sg_aes_config[idx].irq;
return idx;
}
#endif
#if CONFIG_RSA
struct {
uint32_t base;
uint32_t irq;
}
const sg_rsa_config[CONFIG_RSA_NUM] = {
{CSKY_RSA_BASE, RSA_IRQn}
};
/**
\brief get rsa instance count.
\return rsa instance count
*/
int32_t target_get_rsa_count(void)
{
return CONFIG_RSA_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_rsa_count()
\brief get rsa instance.
\return pointer to rsa instance
*/
int32_t target_get_rsa(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_rsa_count()) {
return NULL;
}
*base = sg_rsa_config[idx].base;
*irq = sg_rsa_config[idx].irq;
return idx;
}
#endif
#if CONFIG_RTC
struct {
uint32_t base;
uint32_t irq;
}
const sg_rtc_config[CONFIG_RTC_NUM] = {
{CSKY_RTC_BASE, RTC_IRQn}
};
int32_t target_get_rtc_count(void)
{
return CONFIG_RTC_NUM;
}
int32_t target_get_rtc(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_rtc_count()) {
return NULL;
}
*base = sg_rtc_config[idx].base;
*irq = sg_rtc_config[idx].irq;
return idx;
}
#endif
#if CONFIG_SPI
struct {
uint32_t base;
uint32_t irq;
}
const sg_spi_config[CONFIG_SPI_NUM] = {
{CSKY_SPI0_BASE, SPI0_IRQn},
{CSKY_SPI1_BASE, SPI1_IRQn}
};
typedef struct {
pin_t mosi;
pin_t miso;
pin_t sclk;
pin_t ssel;
uint32_t cfg_idx; //idx of sg_iic_config[]
uint16_t function;
} spi_pin_map_t;
const static spi_pin_map_t s_spi_pin_map[] = {
{
PA7_SPI0TX_PWMTRIG1_SDA0_XX,
PA8_SPI0RX_TRIGFAULT_SCL1_XX,
PA6_SPI0CLK_PWMTRIG0_SCL0_XX,
PA9_SPI0CS_PWM0_SDA1_XX,
0,
0
},
{
PA17_SPI1TX_PWMFAULT_XX_XX,
PA18_SPI1RX_PWM0_XX_XX,
PA16_SPI1CLK_PWMTRIG1_XX_XX,
PA19_SPI1CS0_PWM1_XX_XX,
1,
0
},
{
PA13_RTS1_PWM4_SPI1TX_XX,
PA14_SCL1_PWM5_SPI1RX_XX,
PA12_CTS1_PWM3_SPI1CLK_XX,
PA15_SDA1_PWMTRIG0_SPI1CS0_XX,
1,
2
},
{
PB4_ADC4_SPI1TX_USINSS_XX,
PB5_ADC5_SPI1RX_USISCLK_XX,
PB3_ADC3_SPI1CLK_USISD1_XX,
PB6_ADC6_SPI1CS0_USISD0_XX,
1,
1
}
};
/**
\param[in] instance idx, must not exceed return value of target_get_spi_count()
\brief get spi instance.
\return pointer to spi instance
*/
int32_t target_spi_init(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_spi_pin_map) / sizeof(spi_pin_map_t); idx++) {
if (s_spi_pin_map[idx].mosi == mosi && s_spi_pin_map[idx].miso == miso
&& s_spi_pin_map[idx].sclk == sclk && s_spi_pin_map[idx].ssel == ssel) {
*base = sg_spi_config[s_spi_pin_map[idx].cfg_idx].base;
*irq = sg_spi_config[s_spi_pin_map[idx].cfg_idx].irq;
/*pinmux*/
pin_mux(s_spi_pin_map[idx].mosi, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].miso, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].sclk, s_spi_pin_map[idx].function);
pin_mux(s_spi_pin_map[idx].ssel, s_spi_pin_map[idx].function);
return s_spi_pin_map[idx].cfg_idx;
}
}
return -1;
}
#endif
#if CONFIG_WDT
struct {
uint32_t base;
uint32_t irq;
}
const sg_wdt_config[CONFIG_WDT_NUM] = {
{CSKY_WDT_BASE, WDT_IRQn}
};
int32_t target_get_wdt_count(void)
{
return CONFIG_WDT_NUM;
}
int32_t target_get_wdt(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_wdt_count()) {
return NULL;
}
*base = sg_wdt_config[idx].base;
*irq = sg_wdt_config[idx].irq;
return idx;
}
#endif
#if CONFIG_SHA
struct {
uint32_t base;
uint32_t irq;
}
const sg_sha_config[CONFIG_SHA_NUM] = {
{CSKY_SHA_BASE, SHA_IRQn}
};
/**
\brief get sha instance count.
\return sha instance count
*/
int32_t target_get_sha_count(void)
{
return CONFIG_SHA_NUM;
}
/**
\param[in] instance idx, must not exceed return value of target_get_sha_count()
\brief get sha instance.
\return pointer to sha instance
*/
int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_sha_count()) {
return NULL;
}
*base = sg_sha_config[idx].base;
*irq = sg_sha_config[idx].irq;
return idx;
}
#endif
#if CONFIG_PWM
struct {
uint32_t base;
uint32_t irq;
}
const sg_pwm_config[CONFIG_PWM_NUM] = {
{CSKY_PWM_BASE, PWM_IRQn},
};
typedef struct {
pin_t pwm_pin;
uint32_t cfg_idx; //idx of sg_pwm_config[]
uint32_t ch_num;
uint16_t function;
} pwm_pin_map_t;
const static pwm_pin_map_t s_pwm_pin_map[] = {
{PA0_TXD0_PWM0_XX_SIROUT0, 0, 0, 1},
{PA9_SPI0CS_PWM0_SDA1_XX, 0, 0, 1},
{PA18_SPI1RX_PWM0_XX_XX, 0, 0, 1},
{PA27_RXD3_PWM0_XX_SIRIN3, 0, 0, 1},
{PA1_RXD0_PWM1_XX_SIRIN0, 0, 1, 1},
{PA10_TXD1_PWM1_XX_SIROUT1, 0, 1, 1},
{PA19_SPI1CS0_PWM1_XX_XX, 0, 1, 1},
{PA28_I2SMCLK_PWM1_XX_XX, 0, 1, 1},
{PA2_CTS0_PWM2_SPI0CLK_XX, 0, 2, 1},
{PA11_RXD1_PWM2_XX_SIRIN1, 0, 2, 1},
{PA20_SPI1CS1_PWM2_XX_XX, 0, 2, 1},
{PA29_I2SSCLK_PWM2_XX_XX, 0, 2, 1},
{PA3_RTS0_PWM3_SPI0TX_XX, 0, 3, 1},
{PA12_CTS1_PWM3_SPI1CLK_XX, 0, 3, 1},
{PA21_SPI1CS2_PWM3_XX_XX, 0, 3, 1},
{PA30_I2SWSCLK_PWM3_XX_XX, 0, 3, 1},
{PA4_SCL0_PWM4_SPI0RX_XX, 0, 4, 1},
{PA13_RTS1_PWM4_SPI1TX_XX, 0, 4, 1},
{PA22_RXD2_PWM4_XX_SIRIN2, 0, 4, 1},
{PA31_I2SSDA__SCL0_PWM4_XX, 0, 4, 1},
{PA5_SDA0_PWM5_SPI0CS_XX, 0, 5, 1},
{PA14_SCL1_PWM5_SPI1RX_XX, 0, 5, 1},
{PA23_TXD2_PWM5_XX_SIROUT2, 0, 5, 1},
{PB0_ADC0_SDA0_PWM5_XX, 0, 5, 1},
};
/**
\param[in] instance idx, must not exceed return value of target_get_pwm_count()
\brief get pwm instance.
\return pointer to pwm instance
*/
int32_t target_pwm_init(pin_t pwm_pin, uint32_t *ch_num, uint32_t *base, uint32_t *irq)
{
uint32_t idx;
for (idx = 0; idx < sizeof(s_pwm_pin_map) / sizeof(pwm_pin_map_t); idx++) {
if (s_pwm_pin_map[idx].pwm_pin == pwm_pin) {
*base = sg_pwm_config[s_pwm_pin_map[idx].cfg_idx].base;
*irq = sg_pwm_config[s_pwm_pin_map[idx].cfg_idx].irq;
*ch_num = s_pwm_pin_map[idx].ch_num;
/*pinmux*/
pin_mux(s_pwm_pin_map[idx].pwm_pin, s_pwm_pin_map[idx].function);
return s_pwm_pin_map[idx].cfg_idx;
}
}
return -1;
}
#endif
#if CONFIG_DMAC
struct {
uint32_t base;
uint32_t irq;
}
const sg_dmac_config[CONFIG_DMAC_NUM] = {
{CSKY_DMA_BASE, DMAC_IRQn},
};
int32_t target_get_dmac_count(void)
{
return CONFIG_DMAC_NUM;
}
int32_t target_get_dmac(int32_t idx, uint32_t *base, uint32_t *irq)
{
if (idx >= target_get_dmac_count()) {
return NULL;
}
*base = sg_dmac_config[idx].base;
*irq = sg_dmac_config[idx].irq;
return idx;
}
#endif

View file

@ -0,0 +1,88 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pn_name.h
* @brief header file for the pin_name
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef _PINNAMES_H
#define _PINNAMES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PA0_TXD0_PWM0_XX_SIROUT0 = 0,
PA1_RXD0_PWM1_XX_SIRIN0,
PA2_CTS0_PWM2_SPI0CLK_XX,
PA3_RTS0_PWM3_SPI0TX_XX,
PA4_SCL0_PWM4_SPI0RX_XX,
PA5_SDA0_PWM5_SPI0CS_XX,
PA6_SPI0CLK_PWMTRIG0_SCL0_XX,
PA7_SPI0TX_PWMTRIG1_SDA0_XX,
PA8_SPI0RX_TRIGFAULT_SCL1_XX,
PA9_SPI0CS_PWM0_SDA1_XX,
PA10_TXD1_PWM1_XX_SIROUT1,
PA11_RXD1_PWM2_XX_SIRIN1,
PA12_CTS1_PWM3_SPI1CLK_XX,
PA13_RTS1_PWM4_SPI1TX_XX,
PA14_SCL1_PWM5_SPI1RX_XX,
PA15_SDA1_PWMTRIG0_SPI1CS0_XX,
PA16_SPI1CLK_PWMTRIG1_XX_XX,
PA17_SPI1TX_PWMFAULT_XX_XX,
PA18_SPI1RX_PWM0_XX_XX,
PA19_SPI1CS0_PWM1_XX_XX,
PA20_SPI1CS1_PWM2_XX_XX,
PA21_SPI1CS2_PWM3_XX_XX,
PA22_RXD2_PWM4_XX_SIRIN2,
PA23_TXD2_PWM5_XX_SIROUT2,
PA24_CTS2_PWMTRIG0_SPI1CS1_XX,
PA25_XX_PWMTRIG1_SPI1CS2_XX,
PA26_TXD3_PWMFAULT_XX_SIROUT3,
PA27_RXD3_PWM0_XX_SIRIN3,
PA28_I2SMCLK_PWM1_XX_XX,
PA29_I2SSCLK_PWM2_XX_XX,
PA30_I2SWSCLK_PWM3_XX_XX,
PA31_I2SSDA__SCL0_PWM4_XX,
PB0_ADC0_SDA0_PWM5_XX,
PB1_ADC1_SCL1_USISCLK_XX,
PB2_ADC2_SDA1_USISD0_XX,
PB3_ADC3_SPI1CLK_USISD1_XX,
PB4_ADC4_SPI1TX_USINSS_XX,
PB5_ADC5_SPI1RX_USISCLK_XX,
PB6_ADC6_SPI1CS0_USISD0_XX,
PB7_ADC7_SPI1CS1_USISD1_XX,
PB8_PWMTRIG0_SPI1CS2_USINSS_XX,
PB9_PWMTRIG1_CTS3_XX_XX,
PB10_PWMFAULT_RTS3_XX_XX
}
pin_name_t;
typedef enum {
PORTA = 0,
PORTB = 1
} port_name_t;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,221 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pinmux.h
* @brief Header file for the pinmux
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef PHOBOS_PINMUX_H
#define PHOBOS_PINMUX_H
#include <stdint.h>
#include "pin_name.h"
void phobos_ioreuse_initial(void);
int32_t pin_mux(pin_name_t pin, uint16_t function);
/* IOMUX0L function definition */
#define PA0_UART0_TX 0x00000000
#define PA0_PWM_CH0 0x00000001
#define PA0_UART0_SIROUT 0x00000003
#define PA1_UART0_RX 0x00000000
#define PA1_PWM_CH1 0x00000004
#define PA1_UART0_SIRIN 0x0000000C
#define PA2_UART0_CTS 0x00000000
#define PA2_PWM_CH2 0x00000010
#define PA2_SPI0_CLK 0x00000020
#define PA3_UART0_TRS 0x00000000
#define PA3_PWM_CH3 0x00000040
#define PA3_SPI0_TX 0x00000080
#define PA4_I2C0_SCL 0x00000000
#define PA4_PWM_CH4 0x00000100
#define PA4_SPI0_RX 0x00000200
#define PA5_I2C0_SDA 0x00000000
#define PA5_PWM_CH5 0x00000400
#define PA5_SPI0_CS 0x00000800
#define PA6_SPI0_CLK 0x00000000
#define PA6_ETB_TRIG0 0x00001000
#define PA6_I2C0_SCL 0x00002000
#define PA7_SPI_TX 0x00000000
#define PA7_ETB_TRIG1 0x00004000
#define PA7_I2C0_SDA 0x00008000
#define PA8_SPI0_TX 0x00000000
#define PA8_PWM_FAULT 0x00010000
#define PA8_I2C1_SCL 0x00020000
#define PA9_SPI0_CS 0x00000000
#define PA9_PWM_CH0 0x00040000
#define PA9_I2C1_SDA 0x00080000
#define PA10_UART1_TX 0x00000000
#define PA10_PWM_CH1 0x00100000
#define PA10_UART1_SIROUT 0x00300000
#define PA11_UART1_RX 0x00000000
#define PA11_PWM_CH2 0x00400000
#define PA11_UART1_SIRIN 0x00C00000
#define PA12_UART1_CTS 0x00000000
#define PA12_PWM_CH3 0x01000000
#define PA12_SPI1_CLK 0x02000000
#define PA13_UART1_RTS 0x00000000
#define PA13_PWM_CH4 0x04000000
#define PA13_SPI1_TX 0x08000000
#define PA14_I2C1_SCL 0x00000000
#define PA14_PWM_CH5 0x10000000
#define PA14_SPI1_RX 0x20000000
#define PA15_I2C1_SDA 0x00000000
#define PA15_ETB_TRIG0 0x40000000
#define PA15_SPI1_CS0 0x80000000
/* IOMUX0H function definition */
#define PA16_SPI1_CLK 0x00000000
#define PA16_ETB_TRIG1 0x00000001
#define PA17_SPI1_TX 0x00000000
#define PA17_PWM_FAULT 0x00000004
#define PA18_SPI1_RX 0x00000000
#define PA18_PWM_CH0 0x00000010
#define PA19_SPI1_CS0 0x00000000
#define PA19_PWM_CH1 0x00000040
#define PA20_UART2_RX 0x00000000
#define PA20_PWM_CH2 0x00000100
#define PA21_SPI1_CS2 0x00000000
#define PA21_PWM_CH3 0x00000400
#define PA22_UART2_RX 0x00000000
#define PA22_PWM_CH4 0x00001000
#define PA22_UART2_SIRI 0x00003000
#define PA23_UART2_TX 0x00000000
#define PA23_PWM_CH5 0x00004000
#define PA23_UART2_SIROUT 0x0000C000
#define PA24_UART2_CTS 0x00000000
#define PA24_ETB_TRIG0 0x00010000
#define PA24_SPI1_CS1 0x00020000
#define PA25_UART2_RTS 0x00000000
#define PA25_ETB_TRIG1 0x00040000
#define PA25_SPI1_CS2 0x00080000
#define PA26_UART3_TX 0x00000000
#define PA26_PWM_FAULT 0x00100000
#define PA26_UART3_SIROUT 0x00300000
#define PA27_UART3_RX 0x00000000
#define PA27_PWM_CH0 0x00400000
#define PA27_UART3_SIRIN 0x00C00000
#define PA28_I2S_MCLK 0x00000000
#define PA28_PWM_CH1 0x01000000
#define PA29_I2S_SCLK 0x00000000
#define PA29_PWM_CH2 0x04000000
#define PA30_I2S_WSCLK 0x00000000
#define PA30_PWM_CH3 0x10000000
#define PA31_I2S_SDA 0x00000000
#define PA31_I2C0_SCL 0x40000000
#define PA31_PWM_CH4 0x80000000
/* IOMUX1L function definition */
#define PB0_ADC0 0x00000000
#define PB0_I2C0_SDA 0x00000001
#define PB0_PWM_CH5 0x00000002
#define PB1_ADC1 0x00000000
#define PB1_I2C1_SCL 0x00000004
#define PB1_USI_SCLK 0x00000008
#define PB2_ADC2 0x00000000
#define PB2_I2C1_SDA 0x00000010
#define PB2_USI_SD0 0x00000020
#define PB3_ADC3 0x00000000
#define PB3_SPI1_CLK 0x00000040
#define PB3_USI_SD1 0x00000080
#define PB4_ADC4 0x00000000
#define PB4_SPI1_TX 0x00000100
#define PB4_USI_NSS 0x00000200
#define PB5_ADC5 0x00000000
#define PB5_SPI1_RX 0x00000400
#define PB5_USI_SCLK 0x00000800
#define PB6_ADC6 0x00000000
#define PB6_SPI1_CS0 0x00001000
#define PB6_USI_SD0 0x00002000
#define PB7_ADC7 0x00000000
#define PB7_SPI1_CS1 0x00004000
#define PB7_USI_SD1 0x00008000
#define PB8_ETB_TRIG0 0x00000000
#define PB8_SPI1_CS2 0x00010000
#define PB8_USI_NSS 0x00020000
#define PB9_ETB_TRIG1 0x00000000
#define PB9_UART3_CTS 0x00040000
#define PB10_PWM_FAULT 0x00000000
#define PB10_UART3_RTS 0x00100000
/* flag as identification */
#define GPIO_SET_BIT0 0x00000001
#define GPIO_SET_BIT1 0x00000002
#define GPIO_SET_BIT2 0x00000004
#define GPIO_SET_BIT3 0x00000008
#define GPIO_SET_BIT4 0x00000010
#define GPIO_SET_BIT5 0x00000020
#define GPIO_SET_BIT6 0x00000040
#define GPIO_SET_BIT7 0x00000080
#define GPIO_SET_BIT8 0x00000100
#define GPIO_SET_BIT9 0x00000200
#define GPIO_SET_BIT10 0x00000400
#define GPIO_SET_BIT11 0x00000800
#define GPIO_SET_BIT12 0x00001000
#define GPIO_SET_BIT13 0x00002000
#define GPIO_SET_BIT14 0x00004000
#define GPIO_SET_BIT15 0x00008000
#define GPIO_SET_BIT16 0x00010000
#define GPIO_SET_BIT17 0x00020000
#define GPIO_SET_BIT18 0x00040000
#define GPIO_SET_BIT19 0x00080000
#define GPIO_SET_BIT20 0x00100000
#define GPIO_SET_BIT21 0x00200000
#define GPIO_SET_BIT22 0x00400000
#define GPIO_SET_BIT23 0x00800000
#define GPIO_SET_BIT24 0x01000000
#define GPIO_SET_BIT25 0x02000000
#define GPIO_SET_BIT26 0x04000000
#define GPIO_SET_BIT27 0x08000000
#define GPIO_SET_BIT28 0x10000000
#define GPIO_SET_BIT29 0x20000000
#define GPIO_SET_BIT30 0x40000000
#define GPIO_SET_BIT31 0x80000000
/******************************************************************************
* phobos gpio control and gpio reuse function
* selecting regester adddress
******************************************************************************/
#define PHOBOS_GIPO0_PORTCTL_REG 0x50018008
#define PHOBOS_GIPO1_PORTCTL_REG 0x60018008
#define PHOBOS_IOMUX0L_REG 0x50018100
#define PHOBOS_IOMUX0H_REG 0x50018104
#define PHOBOS_IOMUX1L_REG 0x50018108
/*************basic gpio reuse v1.0********************************************
* UART0(PA0,PA1)
* UART1(PA10,PA11)
* UART2(PA22,PA23)
* UART3(PA26,PA27)
* IIS(PA24,PA25,PA26,PA27)
* SPI1(PA16,PA17,PA18)
* IIC0(PA4,PA5)
******************************************************************************/
#define GPIO0_REUSE_EN (GPIO_SET_BIT0|GPIO_SET_BIT1|GPIO_SET_BIT4|GPIO_SET_BIT5|GPIO_SET_BIT6|GPIO_SET_BIT9|GPIO_SET_BIT10|GPIO_SET_BIT11|GPIO_SET_BIT16|GPIO_SET_BIT17|GPIO_SET_BIT18|GPIO_SET_BIT22|GPIO_SET_BIT23|GPIO_SET_BIT26|GPIO_SET_BIT27)
#define GPIO1_REUSE_EN (GPIO_SET_BIT0)
#define IOMUX0L_FUNCTION_SEL (PA0_UART0_TX|PA1_UART0_RX|PA4_I2C0_SCL|PA5_I2C0_SDA|PA6_ETB_TRIG0|PA9_PWM_CH0|PA10_UART1_TX|PA11_UART1_RX)
#define IOMUX0H_FUNCTION_SEL (PA16_SPI1_CLK|PA17_SPI1_TX|PA18_SPI1_RX|PA22_UART2_RX|PA23_UART2_TX|PA26_UART3_TX|PA27_UART3_RX)
#define IOMUX1L_FUNCTION_SEL (PB0_ADC0)
#define PWM_GPIO0_REUSE_EN (GPIO0_REUSE_EN|GPIO_SET_BIT0|GPIO_SET_BIT1|GPIO_SET_BIT2|GPIO_SET_BIT12|GPIO_SET_BIT13|GPIO_SET_BIT14)
#define PWM_IOMUX0L_FUNCTION_SEL (IOMUX0L_FUNCTION_SEL|PA0_PWM_CH0|PA1_PWM_CH1|PA2_PWM_CH2|PA12_PWM_CH3|PA13_PWM_CH4|PA14_PWM_CH5)
#endif /* PHOBOS_PINMUX_H */

View file

@ -0,0 +1,327 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**************************************************************************//**
* @file soc.h
* @brief CSI Core Peripheral Access Layer Header File for
* CSKYSOC Device Series
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#ifndef SOC_H
#define SOC_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef SYSTEM_CLOCK
#define SYSTEM_CLOCK (20000000)
#endif
/* ------------------------- Interrupt Number Definition ------------------------ */
typedef enum IRQn
{
/* ---------------------- CSKYCK801 Specific Interrupt Numbers --------------------- */
GPIOA_IRQn = 0,
CORET_IRQn = 1, /* core Timer Interrupt */
TIMA0_IRQn = 2, /* timerA0 Interrupt */
TIMA1_IRQn = 3, /* timerA1 Interrupt */
WDT_IRQn = 5, /* wdt Interrupt */
UART0_IRQn = 6, /* uart0 Interrupt */
UART1_IRQn = 7, /* uart1 Interrupt */
UART2_IRQn = 8, /* uart2 Interrupt */
I2C0_IRQn = 9, /* i2c0 Interrupt */
I2C1_IRQn = 10, /* i2c1 Interrupt */
SPI1_IRQn = 11, /* spi0 Interrupt */
SPI0_IRQn = 12, /* spi1 Interrupt */
RTC_IRQn = 13, /* rtc Interrupt */
EXTWAK_IRQn = 14, /* extwakeup Interrupt */
DMAC_IRQn = 17, /* dmac Interrupt */
PMU_IRQn = 18, /* pmu Interrupt */
PWM_IRQn = 19, /* pwm Interrupt */
UART3_IRQn = 21, /* uart3 Interrupt */
TIMB0_IRQn = 23, /* timerB0 Interrupt */
TIMB1_IRQn = 24, /* timerB1 Interrupt */
GPIOB_IRQn = 27, /* GPIOB Interrupt */
AES_IRQn = 26, /* aes Interrupt */
RSA_IRQn = 28, /* rsa Interrupt */
SHA_IRQn = 29, /* sha Interrupt */
}
IRQn_Type;
/* ================================================================================ */
/* ================ Processor and Core Peripheral Section ================ */
/* ================================================================================ */
/* -------- Configuration of the CK801 Processor and Core Peripherals ------- */
#define __CK802_REV 0x0000U /* Core revision r0p0 */
#define __MGU_PRESENT 0 /* MGU present or not */
#define __NVIC_PRIO_BITS 2 /* Number of Bits used for Priority Levels */
#define __Vendor_SysTickConfig 0 /* Set to 1 if different SysTick Config is used */
#include "core_ck802.h" /* Processor and core peripherals */
#include "stdint.h"
typedef enum {
CKENUM_DMA_UART0_RX,
CKENUM_DMA_UART0_TX,
CKENUM_DMA_UART1_RX,
CKENUM_DMA_UART1_TX,
CKENUM_DMA_ADC_RX,
CKENUM_DMA_ADC_TX,
CKENUM_DMA_SPI1_RX,
CKENUM_DMA_SPI1_TX,
CKENUM_DMA_SPI0_RX,
CKENUM_DMA_SPI0_TX,
CKENUM_DMA_IIC_RX,
CKENUM_DMA_IIC_TX,
CKENUM_DMA_IIC1_RX,
CKENUM_DMA_IIC1_TX,
CKENUM_DMA_IIS_RX,
CKENUM_DMA_IIS_TX,
CKENUM_DMA_MEMORY
} ckenum_dma_device_e;
/* ================================================================================ */
/* ================ Device Specific Peripheral Section ================ */
/* ================================================================================ */
#if 0
/* ================================================================================ */
/* ============== Universal Asyncronous Receiver / Transmitter (UART) ============= */
/* ================================================================================ */
typedef struct {
union {
__IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */
__OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */
__IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */
};
union {
__IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */
__IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */
};
__IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */
__IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */
__IOM uint32_t MCR; /* Offset: 0x010 (R/W) Modem control register */
__IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */
__IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */
uint32_t RESERVED1[24];
__IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */
} CSKY_UART_TypeDef;
/* ================================================================================ */
/* ============== Inter-Integrated Circuit (IIC) ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t IC_CON; /* Offset: 0x000 (R/W) Receive buffer register */
__IOM uint32_t IC_TAR; /* Offset: 0x004 (R/W) Transmission hold register */
__IOM uint32_t IC_SAR; /* Offset: 0x008 (R/W) Clock frequency division low section register */
__IOM uint32_t IC_HS_MADDR; /* Offset: 0x00c (R/W) Clock frequency division high section register */
__IOM uint32_t IC_DATA_CMD; /* Offset: 0x010 (R/W) Interrupt enable register */
__IOM uint32_t IC_SS_SCL_HCNT; /* Offset: 0x014 (R/W) Interrupt indicia register */
__IOM uint32_t IC_SS_SCL_LCNT; /* Offset: 0x018 (R/W) Transmission control register */
__IOM uint32_t IC_FS_SCL_HCNT; /* Offset: 0x01c (R/W) Modem control register */
__IOM uint32_t IC_FS_SCL_LCNT; /* Offset: 0x020 (R/W) Transmission state register */
__IOM uint32_t IC_HS_SCL_HCNT; /* Offset: 0x024 (R/W) Transmission state register */
__IOM uint32_t IC_HS_SCL_LCNT; /* Offset: 0x028 (R/W) Transmission state register */
__IOM uint32_t IC_INTR_STAT; /* Offset: 0x02c (R) Transmission state register */
__IOM uint32_t IC_INTR_MASK; /* Offset: 0x030 (R/W) Transmission state register */
__IOM uint32_t IC_RAW_INTR_STAT; /* Offset: 0x034 (R) Transmission state register */
__IOM uint32_t IC_RX_TL; /* Offset: 0x038 (R/W) Transmission state register */
__IOM uint32_t IC_TX_TL; /* Offset: 0x03c (R/W) Transmission state register */
__IOM uint32_t IC_CLR_INTR; /* Offset: 0x040 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_UNDER; /* Offset: 0x044 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_OVER; /* Offset: 0x048 (R) Transmission state register */
__IOM uint32_t IC_CLR_TX_OVER; /* Offset: 0x04c (R) Transmission state register */
__IOM uint32_t IC_CLR_RD_REQ; /* Offset: 0x050 (R) Transmission state register */
__IOM uint32_t IC_CLR_TX_ABRT; /* Offset: 0x054 (R) Transmission state register */
__IOM uint32_t IC_CLR_RX_DONE; /* Offset: 0x058 (R) Transmission state register */
__IOM uint32_t IC_CLR_ACTIVITY; /* Offset: 0x05c (R) Transmission state register */
__IOM uint32_t IC_CLR_STOP_DET; /* Offset: 0x060 (R) Transmission state register */
__IOM uint32_t IC_CLR_START_DET; /* Offset: 0x064 (R) Transmission state register */
__IOM uint32_t IC_CLR_GEN_CALL; /* Offset: 0x068 (R) Transmission state register */
__IOM uint32_t IC_ENABLE; /* Offset: 0x06c (R/W) Transmission state register */
__IOM uint32_t IC_STATUS; /* Offset: 0x070 (R) Transmission state register */
__IOM uint32_t IC_TXFLR; /* Offset: 0x074 (R) Transmission state register */
__IOM uint32_t IC_RXFLR; /* Offset: 0x078 (R) Transmission state register */
uint32_t RESERVED; /* Offset: 0x014 (R/ ) Transmission state register */
__IOM uint32_t IC_TX_ABRT_SOURCE; /* Offset: 0x080 (R/W) Transmission state register */
__IOM uint32_t IC_SAR1; /* Offset: 0x084 (R/W) Transmission state register */
__IOM uint32_t IC_DMA_CR; /* Offset: 0x088 (R/W) Transmission state register */
__IOM uint32_t IC_DMA_TDLR; /* Offset: 0x08c (R/W) Transmission state register */
__IOM uint32_t IC_DMA_RDLR; /* Offset: 0x090 (R/W) Transmission state register */
__IOM uint32_t IC_SAR2; /* Offset: 0x094 (R/W) Transmission state register */
__IOM uint32_t IC_SAR3; /* Offset: 0x098 (R/W) Transmission state register */
__IOM uint32_t IC_MULTI_SLAVE; /* Offset: 0x09c (R/W) Transmission state register */
__IOM uint32_t IC_GEN_CALL_EN; /* Offset: 0x0a0 (R/W) Transmission state register */
} CSKY_IIC_TypeDef;
/* ================================================================================ */
/* ============== TIMER ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t TxLoadCount; /* Offset: 0x000 (R/W) Receive buffer register */
__IOM uint32_t TxCurrentValue; /* Offset: 0x004 (R) Transmission hold register */
__IOM uint32_t TxControl; /* Offset: 0x008 (R/W) Clock frequency division low section register */
__IOM uint32_t TxEOI; /* Offset: 0x00c (R) Clock frequency division high section register */
__IOM uint32_t TxIntStatus; /* Offset: 0x010 (R) Interrupt enable register */
} CSKY_TIMER_TypeDef;
/* ================================================================================ */
/* ============== TIMER Control ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t TimersIntStatus; /* Offset: 0x000 (R) Interrupt indicia register */
__IOM uint32_t TimerEOI; /* Offset: 0x004 (R) Transmission control register */
__IOM uint32_t TimerRawIntStatus; /* Offset: 0x008 (R) Modem control register */
} CSKY_TIMER_Control_TypeDef;
/* ================================================================================ */
/* ============== GPIO ============= */
/* ================================================================================ */
typedef struct {
__IOM uint32_t SWPORT_DR; /* Offset: 0x000 (R/W) Interrupt indicia register */
__IOM uint32_t SWPORT_DDR; /* Offset: 0x004 (R/W) Interrupt indicia register */
__IOM uint32_t PORT_CTL; /* Offset: 0x008 (R/W) Interrupt indicia register */
} CKStruct_GPIO, *PCKStruct_GPIO;
typedef struct {
__IOM uint32_t SHA_CON; /* Offset: 0x000 (R/W) Control register */
__IOM uint32_t SHA_INTSTATE; /* Offset: 0x004 (R/W) Instatus register */
__IOM uint32_t SHA_H0L; /* Offset: 0x008 (R/W) H0L register */
__IOM uint32_t SHA_H1L; /* Offset: 0x00c (R/W) H1L register */
__IOM uint32_t SHA_H2L; /* Offset: 0x010 (R/W) H2L register */
__IOM uint32_t SHA_H3L; /* Offset: 0x014 (R/W) H3L register */
__IOM uint32_t SHA_H4L; /* Offset: 0x018 (R/W) H4L register */
__IOM uint32_t SHA_H5L; /* Offset: 0x01c (R/W) H5L register */
__IOM uint32_t SHA_H6L; /* Offset: 0x020 (R/W) H6L register */
__IOM uint32_t SHA_H7L; /* Offset: 0x024 (R/W) H7L register */
__IOM uint32_t SHA_H0H; /* Offset: 0x028 (R/W) H0H register */
__IOM uint32_t SHA_H1H; /* Offset: 0x02c (R/W) H1H register */
__IOM uint32_t SHA_H2H; /* Offset: 0x030 (R/W) H2H register */
__IOM uint32_t SHA_H3H; /* Offset: 0x034 (R/W) H3H register */
__IOM uint32_t SHA_H4H; /* Offset: 0x038 (R/W) H4H register */
__IOM uint32_t SHA_H5H; /* Offset: 0x03c (R/W) H5H register */
__IOM uint32_t SHA_H6H; /* Offset: 0x040 (R/W) H6H register */
__IOM uint32_t SHA_H7H; /* Offset: 0x044 (R/W) H7H register */
__IOM uint32_t SHA_DATA1; /* Offset: 0x048 (R/W) DATA1 register */
uint32_t REV[15];
__IOM uint32_t SHA_DATA2; /* Offset: 0x088 (R/W) DATA2 register */
} CSKY_SHA_TypeDef;
#endif
#define CONFIG_CRC_NUM 1
#define CONFIG_IIC_NUM 2
#define CONFIG_TRNG_NUM 1
#define CONFIG_EFLASH_NUM 1
#define CONFIG_AES_NUM 1
#define CONFIG_RSA_NUM 1
#define CONFIG_SHA_NUM 1
#define CONFIG_SPI_NUM 2
#define CONFIG_PWM_NUM 1
#define CONFIG_TIMER_NUM 4
#define CONFIG_RTC_NUM 1
#define CONFIG_WDT_NUM 1
#define CONFIG_DMAC_NUM 1
#define CONFIG_ETH_NUM 2
#define CSKY_I2C0_BASE (0x50014000UL)
#define CSKY_I2C1_BASE (0x60014000UL)
#define CONFIG_USART_NUM 4
#define CSKY_UART0_BASE (0x50010000UL)
#define CSKY_UART1_BASE (0x50010400UL)
#define CSKY_UART2_BASE (0x60010000UL)
#define CSKY_UART3_BASE (0x60010400UL)
/* ================================================================================ */
/* ================ Peripheral memory map ================ */
/* ================================================================================ */
/* -------------------------- CPU FPGA memory map ------------------------------- */
#define CSKY_EFLASH_BASE (0x10000000UL)
#define CSKY_SRAM_BASE (0x20000000UL)
#define CSKY_PMU_BASE (0x40000000UL)
#define CSKY_DMA_BASE (0x40001000UL)
#define CSKY_EFLASH_CONTROL_BASE (0x40005000UL)
#define CSKY_OTP_BASE (0x40006000UL)
#define CSKY_SRAM_CONTROL_BASE (0x40009000UL)
#define CSKY_AES_BASE (0x4000d000UL)
#define CSKY_SHA_BASE (0x4000e000UL)
#define CSKY_RSA_BASE (0x4000f000UL)
#define CSKY_CRC_BASE (0x40010000UL)
#define CSKY_TRNG_BASE (0x40015000UL)
#define CSKY_TIMERA0_BASE (0x50000000UL)
#define CSKY_TIMERA1_BASE (0x50000014UL)
#define CSKY_TIMERA_CONTROL_BASE (0x500000a0UL)
#define CSKY_RTC_BASE (0x50004000UL)
#define CSKY_WDT_BASE (0x50008000UL)
#define CSKY_SPI0_BASE (0x5000c000UL)
#define SHA_CONTEXT_SIZE 224
#define CONFIG_GPIO_NUM 2
#define CONFIG_GPIO_PIN_NUM 43
#define CSKY_GPIOA_BASE (0x50018000UL)
#define CSKY_GPIOA_CONTROL_BASE (0x50018030UL)
#define CSKY_PWM_BASE (0x5001c000UL)
#define CSKY_ADC_BASE (0x50020000UL)
#define CSKY_I2S0_BASE (0x50030000UL)
#define CSKY_TIMERB0_BASE (0x60000000UL)
#define CSKY_TIMERB1_BASE (0x60000014UL)
#define CSKY_SPI1_BASE (0x6000c000UL)
#define CSKY_GPIOB_BASE (0x60018000UL)
#define CSKY_GPIOB_CONTROL_BASE (0x60018030UL)
#define CSKY_TIMERB_CONTROL_BASE (0x600000a0UL)
#define CSKY_SIPC_BASE (0x6001c000UL)
#define CSKY_I2S1_BASE (0x60020000UL)
#define CSKY_ETB_BASE (0x60024000UL)
#define CSKY_USI_BASE (0x60028000UL)
/* ================================================================================ */
/* ================ Peripheral declaration ================ */
/* ================================================================================ */
#define CSKY_UART1 (( CSKY_UART_TypeDef *) CSKY_UART1_BASE)
#define CSKY_SHA (( CSKY_SHA_TypeDef *) CSKY_SHA_BASE)
#include <config.h>
#ifdef CONFIG_HAVE_VIC
#define ATTRIBUTE_ISR __attribute__((isr))
#else
#define ATTRIBUTE_ISR
#endif
#ifdef __cplusplus
}
#endif
#endif /* SOC_H */

View file

@ -0,0 +1,216 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file isr.c
* @brief source file for the interrupt server route
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <drv_common.h>
#include "config.h"
#include "soc.h"
#ifndef CONFIG_KERNEL_NONE
#include <csi_kernel.h>
#endif
extern void dw_usart_irqhandler(int32_t idx);
extern void dw_timer_irqhandler(int32_t idx);
extern void dw_gpio_irqhandler(int32_t idx);
extern void dw_iic_irqhandler(int32_t idx);
extern void ck_rtc_irqhandler(int32_t idx);
extern void dw_spi_irqhandler(int32_t idx);
extern void dw_wdt_irqhandler(int32_t idx);
extern void ck_dma_irqhandler(int32_t idx);
extern void ck_aes_irqhandler(int32_t idx);
extern void ck_sha_irqhandler(int32_t idx);
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#ifndef CONFIG_KERNEL_NONE
#define CSI_INTRPT_ENTER() csi_kernel_intrpt_enter()
#define CSI_INTRPT_EXIT() csi_kernel_intrpt_exit()
#else
#define CSI_INTRPT_ENTER()
#define CSI_INTRPT_EXIT()
#endif
ATTRIBUTE_ISR void CORET_IRQHandler(void)
{
readl(0xE000E010);
}
#if defined(CONFIG_USART)
ATTRIBUTE_ISR void USART0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART2_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(2);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void USART3_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_usart_irqhandler(3);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_TIMER)
ATTRIBUTE_ISR void TIMA0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMA1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(1);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMB0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(2);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void TIMB1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_timer_irqhandler(3);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_GPIO)
ATTRIBUTE_ISR void GPIOA_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_gpio_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void GPIOB_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_gpio_irqhandler(1);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_IIC)
ATTRIBUTE_ISR void I2C0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_iic_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void I2C1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_iic_irqhandler(1);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_RTC)
ATTRIBUTE_ISR void RTC_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_rtc_irqhandler(0);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_AES)
ATTRIBUTE_ISR void AES_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_aes_irqhandler(0);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_SHA)
ATTRIBUTE_ISR void SHA_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_sha_irqhandler(0);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_SPI) && defined(CONFIG_GPIO)
ATTRIBUTE_ISR void SPI0_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_spi_irqhandler(0);
CSI_INTRPT_EXIT();
}
ATTRIBUTE_ISR void SPI1_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_spi_irqhandler(1);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_WDT)
ATTRIBUTE_ISR void WDT_IRQHandler(void)
{
CSI_INTRPT_ENTER();
dw_wdt_irqhandler(0);
CSI_INTRPT_EXIT();
}
#endif
#if defined(CONFIG_DMAC)
ATTRIBUTE_ISR void DMAC_IRQHandler(void)
{
CSI_INTRPT_ENTER();
ck_dma_irqhandler(0);
CSI_INTRPT_EXIT();
}
#endif

View file

@ -0,0 +1,150 @@
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* @file pinmux.c
* @brief source file for the pinmux
* @version V1.0
* @date 02. June 2017
******************************************************************************/
#include <stdint.h>
#include "pinmux.h"
#include "pin_name.h"
#define readl(addr) \
({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
/*******************************************************************************
* function: phobos_ioreuse_inital
*
* description:
* initial phobos_pinmux
*******************************************************************************/
void phobos_ioreuse_initial(void)
{
unsigned int value;
/* gpio data source select */
value = readl(PHOBOS_GIPO0_PORTCTL_REG);
value |= GPIO0_REUSE_EN;
writel(value, PHOBOS_GIPO0_PORTCTL_REG);
value = readl(PHOBOS_GIPO1_PORTCTL_REG);
value |= GPIO1_REUSE_EN;
writel(value, PHOBOS_GIPO1_PORTCTL_REG);
/* reuse function select */
value = readl(PHOBOS_IOMUX0L_REG);
value |= IOMUX0L_FUNCTION_SEL;
writel(value, PHOBOS_IOMUX0L_REG);
value = readl(PHOBOS_IOMUX0H_REG);
value |= IOMUX1L_FUNCTION_SEL;
writel(value, PHOBOS_IOMUX0H_REG);
value = readl(PHOBOS_IOMUX1L_REG);
value |= IOMUX1L_FUNCTION_SEL;
writel(value, PHOBOS_IOMUX1L_REG);
}
void phobos_pwm_ioreuse(void)
{
unsigned int value;
/* gpio data source select */
value = readl(PHOBOS_GIPO0_PORTCTL_REG);
value |= PWM_GPIO0_REUSE_EN;
writel(value, PHOBOS_GIPO0_PORTCTL_REG);
/* reuse function select */
value = readl(PHOBOS_IOMUX0L_REG);
value |= PWM_IOMUX0L_FUNCTION_SEL;
writel(value, PHOBOS_IOMUX0L_REG);
}
int32_t pin_mux(pin_name_t pin, uint16_t function)
{
unsigned int val = 0;
unsigned int reg_val = 0;
uint8_t offset;
if (function > 3) {
if (pin < PB0_ADC0_SDA0_PWM5_XX) {
offset = pin;
/* gpio data source select */
val = readl(PHOBOS_GIPO0_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, PHOBOS_GIPO0_PORTCTL_REG);
return 0;
} else if (pin >= PB0_ADC0_SDA0_PWM5_XX) {
offset = pin - 32;
/* gpio data source select */
val = readl(PHOBOS_GIPO1_PORTCTL_REG);
val &= ~(1 << offset);
writel(val, PHOBOS_GIPO1_PORTCTL_REG);
return 0;
} else {
return -1;
}
}
if (pin >= PB0_ADC0_SDA0_PWM5_XX) {
offset = pin - 32;
/* gpio data source select */
val = readl(PHOBOS_GIPO1_PORTCTL_REG);
val |= (1 << offset);
writel(val, PHOBOS_GIPO1_PORTCTL_REG);
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(PHOBOS_IOMUX1L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, PHOBOS_IOMUX1L_REG);
return 0;
}
offset = pin;
/* gpio data source select */
val = readl(PHOBOS_GIPO0_PORTCTL_REG);
val |= (1 << offset);
writel(val, PHOBOS_GIPO0_PORTCTL_REG);
if (pin >= PA16_SPI1CLK_PWMTRIG1_XX_XX) {
offset = pin - 16;
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(PHOBOS_IOMUX0H_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, PHOBOS_IOMUX0H_REG);
return 0;
}
reg_val = (0x3 << (offset * 2));
/* reuse function select */
val = readl(PHOBOS_IOMUX0L_REG);
val &= ~(reg_val);
val |= (function << (2 * offset));
writel(val, PHOBOS_IOMUX0L_REG);
return 0;
}